TTKMusicPlayer  4.1.3.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
musiclocalmanagerwidget.cpp
Go to the documentation of this file.
3 #include "musicitemsearchedit.h"
4 #include "musicgiflabelwidget.h"
5 #include "musicsongmeta.h"
6 #include "musicfileutils.h"
7 #include "musicformats.h"
8 #include "ttktabbutton.h"
9 
10 #include <QTimer>
11 #include <QButtonGroup>
12 #if TTK_QT_VERSION_CHECK(5,0,0)
13 # include <QStandardPaths>
14 #else
15 # include <QDesktopServices>
16 #endif
17 
18 namespace TTK
19 {
23  inline static QString generateArtist(const QString &v)
24  {
25  return v.isEmpty() ? QObject::tr("Various Artist") : v;
26  }
30  inline static QString generateAlbum(const QString &v)
31  {
32  return v.isEmpty() ? QObject::tr("Various Album") : v;
33  }
37  inline static QString generateYear(const QString &v)
38  {
39  return v.isEmpty() ? QObject::tr("Various Year") : v;
40  }
44  inline static QString generateGenre(const QString &v)
45  {
46  return v.isEmpty() ? QObject::tr("Various Genre") : v;
47  }
48 }
49 
50 
52  : MusicAbstractTableWidget(parent)
53 {
54  setColumnCount(2);
55 
56  QHeaderView *headerView = horizontalHeader();
57  headerView->setVisible(true);
58  headerView->resizeSection(0, 100);
59  headerView->resizeSection(1, 55);
60 
61  setAlternatingRowColors(true);
62  setFrameShape(QFrame::Box);
63  setTextElideMode(Qt::ElideRight);
64  setWordWrap(false);
65  hide();
66 
67  setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
68  horizontalScrollBar()->setStyleSheet(TTK::UI::ScrollBarStyle04);
69 }
70 
72 {
73  removeItems();
74 }
75 
77 {
78  setRowCount(song.count());
79 
80  int index = 0;
81  for(auto it = song.constBegin(); it != song.constEnd(); ++it, ++index)
82  {
83  QTableWidgetItem *item = new QTableWidgetItem;
84  item->setToolTip(it.key());
85  item->setText(item->toolTip());
86  QtItemSetTextAlignment(item, Qt::AlignLeft | Qt::AlignVCenter);
87  setItem(index, 0, item);
88 
89  item = new QTableWidgetItem;
90  item->setToolTip(QString::number(it.value()));
91  item->setText(item->toolTip());
92  QtItemSetTextAlignment(item, Qt::AlignLeft | Qt::AlignVCenter);
93  setItem(index, 1, item);
94  }
95 }
96 
98 {
99  const int width = G_SETTING_PTR->value(MusicSettingManager::WidgetSize).toSize().width();
100  QHeaderView *headerView = horizontalHeader();
101  headerView->resizeSection(0, 100 + (width - WINDOW_WIDTH_MIN) / 2.0 / 3.0);
102  headerView->resizeSection(1, 55 + (width - WINDOW_WIDTH_MIN) / 2.0 / 3.0);
103 }
104 
105 
106 
109 {
110  setSelectionMode(QAbstractItemView::ExtendedSelection);
111  setColumnCount(7);
112 
113  QHeaderView *headerView = horizontalHeader();
114  headerView->setVisible(true);
115  headerView->resizeSection(0, 200);
116  headerView->resizeSection(1, 100);
117  headerView->resizeSection(2, 100);
118  headerView->resizeSection(3, 40);
119  headerView->resizeSection(4, 100);
120  headerView->resizeSection(5, 100);
121  headerView->resizeSection(6, 200);
122 
123  setAlternatingRowColors(true);
124  setFrameShape(QFrame::Box);
125  setTextElideMode(Qt::ElideRight);
126  setWordWrap(false);
127 
128  setHorizontalHeaderLabels({tr("Title"), tr("Artist"), tr("Album"), tr("Track"), tr("Year"), tr("Genre"), tr("Path")});
129  setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
130  horizontalScrollBar()->setStyleSheet(TTK::UI::ScrollBarStyle04);
131 
132  m_songs = new MusicSongList;
133 }
134 
136 {
137  removeItems();
138  delete m_songs;
139 }
140 
141 void MusicLocalManagerSongsTableWidget::addCellItems(const MusicSongInfoItemList &songs)
142 {
143  setRowCount(songs.count());
144 
145  for(int i = 0; i < songs.count(); ++i)
146  {
147  const MusicSongInfoItem &v = songs[i];
148 
149  QTableWidgetItem *item = new QTableWidgetItem;
150  item->setToolTip(v.m_title);
151  item->setText(item->toolTip());
152  QtItemSetTextAlignment(item, Qt::AlignLeft | Qt::AlignVCenter);
153  setItem(i, 0, item);
154 
155  item = new QTableWidgetItem;
156  item->setToolTip(v.m_artist);
157  item->setText(item->toolTip());
158  QtItemSetTextAlignment(item, Qt::AlignLeft | Qt::AlignVCenter);
159  setItem(i, 1, item);
160 
161  item = new QTableWidgetItem;
162  item->setToolTip(v.m_album);
163  item->setText(item->toolTip());
164  QtItemSetTextAlignment(item, Qt::AlignLeft | Qt::AlignVCenter);
165  setItem(i, 2, item);
166 
167  item = new QTableWidgetItem;
168  item->setToolTip(v.m_track);
169  item->setText(item->toolTip());
170  QtItemSetTextAlignment(item, Qt::AlignLeft | Qt::AlignVCenter);
171  setItem(i, 3, item);
172 
173  item = new QTableWidgetItem;
174  item->setToolTip(v.m_year);
175  item->setText(item->toolTip());
176  QtItemSetTextAlignment(item, Qt::AlignLeft | Qt::AlignVCenter);
177  setItem(i, 4, item);
178 
179  item = new QTableWidgetItem;
180  item->setToolTip(v.m_genre);
181  item->setText(item->toolTip());
182  QtItemSetTextAlignment(item, Qt::AlignLeft | Qt::AlignVCenter);
183  setItem(i, 5, item);
184 
185  item = new QTableWidgetItem;
186  item->setToolTip(v.m_path);
187  item->setText(item->toolTip());
188  QtItemSetTextAlignment(item, Qt::AlignLeft | Qt::AlignVCenter);
189  setItem(i, 6, item);
190 
191  m_songs->append(MusicSong(v.m_path));
192  }
193 }
194 
196 {
197  const int width = G_SETTING_PTR->value(MusicSettingManager::WidgetSize).toSize().width();
198  QHeaderView *headerView = horizontalHeader();
199  headerView->resizeSection(0, 200 + (width - WINDOW_WIDTH_MIN) / 4.0);
200  headerView->resizeSection(1, 100 + (width - WINDOW_WIDTH_MIN) / 4.0);
201  headerView->resizeSection(2, 100 + (width - WINDOW_WIDTH_MIN) / 4.0);
202  headerView->resizeSection(6, 200 + (width - WINDOW_WIDTH_MIN) / 4.0);
203 }
204 
206 {
208  m_songs->clear();
209 }
210 
212 {
213  MusicAbstractSongsListTableWidget::contextMenuEvent(event);
214 
215  QMenu menu(this);
216  menu.setStyleSheet(TTK::UI::MenuStyle02);
217  menu.addAction(QIcon(":/contextMenu/btn_play"), tr("Play"), this, SLOT(playClicked()));
218  menu.addSeparator();
219 
220  createMoreMenu(&menu);
221 
222  const bool status = !(m_songs->isEmpty() || TTK::String::isNetworkUrl(currentSongPath()));
223  menu.addAction(tr("Song Info..."), this, SLOT(showFileInformation()))->setEnabled(status);
224  menu.addAction(QIcon(":/contextMenu/btn_local_file"), tr("Open File Dir"), this, SLOT(openFileDir()))->setEnabled(status);
225  menu.addAction(QIcon(":/contextMenu/btn_ablum"), tr("Ablum"), this, SLOT(showAlbumQueryWidget()));
226  menu.addSeparator();
227 
228  menu.exec(QCursor::pos());
229 }
230 
231 
233  : QWidget(parent),
235 {
237 
238  QVBoxLayout *layout = new QVBoxLayout(this);
239  layout->setSpacing(0);
240  layout->setContentsMargins(0, 0, 0, 0);
241  setLayout(layout);
242 
243  QWidget *mainWidget = new QWidget(this);
244  QVBoxLayout *mainLayout = new QVBoxLayout(mainWidget);
245  mainLayout->setSpacing(0);
246  mainLayout->setContentsMargins(20, 10, 20, 10);
247  mainWidget->setLayout(mainLayout);
248  layout->addWidget(mainWidget);
249 
250  QWidget *topWidget = new QWidget(mainWidget);
251  mainLayout->addWidget(topWidget);
252 
253  QVBoxLayout *topLayout = new QVBoxLayout(topWidget);
254  topLayout->setSpacing(0);
255  topLayout->setContentsMargins(0, 0, 0, 10);
256  topWidget->setLayout(topLayout);
257 
258  QWidget *functionWidget = new QWidget(topWidget);
259  QHBoxLayout *functionWidgetLayout = new QHBoxLayout(functionWidget);
260  functionWidgetLayout->setContentsMargins(0, 0, 0, 10);
261  functionWidget->setLayout(functionWidgetLayout);
262 
263  QLabel *pLabel = new QLabel(tr("Media Library"), functionWidget);
264  QFont pLabelFont = pLabel->font();
265  pLabelFont.setPixelSize(33);
266  pLabel->setFont(pLabelFont);
267  pLabel->setStyleSheet(TTK::UI::ColorStyle01);
268  functionWidgetLayout->addWidget(pLabel);
269 
270  m_sizeLabel = new QLabel(functionWidget);
271  m_sizeLabel->setStyleSheet(TTK::UI::ColorStyle01);
272  functionWidgetLayout->addWidget(m_sizeLabel);
273  functionWidgetLayout->addStretch(1);
274 
275  QPushButton *refresh = new QPushButton(tr("Refresh"), functionWidget);
276  refresh->setIcon(QIcon(":/functions/btn_similar_hover"));
277  refresh->setFixedSize(90, 30);
278  refresh->setStyleSheet(TTK::UI::PushButtonStyle03);
279  refresh->setCursor(QCursor(Qt::PointingHandCursor));
280  functionWidgetLayout->addWidget(refresh);
281 
282  QPushButton *button = new QPushButton(tr("Settings"), functionWidget);
283  button->setIcon(QIcon(":/functions/btn_setting_hover"));
284  button->setFixedSize(90, 30);
285  button->setStyleSheet(TTK::UI::PushButtonStyle03);
286  button->setCursor(QCursor(Qt::PointingHandCursor));
287  functionWidgetLayout->addWidget(button);
288 
289  m_searchEdit = new MusicItemQueryEdit(topWidget);
290  m_searchEdit->setFixedHeight(33);
291  topLayout->addWidget(functionWidget);
292  topLayout->addWidget(m_searchEdit);
293 
294  QWidget *tabWidget = new QWidget(mainWidget);
295  QHBoxLayout *tabWidgetLayout = new QHBoxLayout(tabWidget);
296  tabWidgetLayout->setSpacing(0);
297  tabWidgetLayout->setContentsMargins(0, 0, 0, 0);
298  tabWidget->setLayout(tabWidgetLayout);
299  mainLayout->addWidget(tabWidget);
300 
301  m_tabButton = new TTKTabButton(tabWidget);
302  m_tabButton->addButtons({tr("Song"), tr("Artist"), tr("Album"), tr("Year"), tr("Genre")});
303  tabWidgetLayout->addWidget(m_tabButton);
304  connect(m_tabButton, SIGNAL(clicked(int)), SLOT(typeIndexChanged(int)));
305 
306 #ifdef Q_OS_UNIX
307  refresh->setFocusPolicy(Qt::NoFocus);
308  button->setFocusPolicy(Qt::NoFocus);
309 #endif
310 
311  QWidget *centerWidget = new QWidget(mainWidget);
312  QHBoxLayout *centerWidgetLayout = new QHBoxLayout(centerWidget);
313  centerWidgetLayout->setSpacing(2);
314  centerWidgetLayout->setContentsMargins(0, 5, 0, 0);
315  centerWidget->setLayout(centerWidgetLayout);
316  mainLayout->addWidget(centerWidget);
317 
319  centerWidgetLayout->addWidget(m_statisticTableWidget, 1);
320 
322  centerWidgetLayout->addWidget(m_songTableWidget, 3);
323 
326  m_searchEdit->editor()->setPlaceholderText(tr("Please input search song words"));
327 
329  connect(refresh, SIGNAL(clicked()), SLOT(refreshItems()));
330  connect(button, SIGNAL(clicked()), SLOT(updateMediaLibraryPath()));
331  connect(m_songTableWidget, SIGNAL(cellDoubleClicked(int,int)), SLOT(itemDoubleClicked(int,int)));
332  connect(m_searchEdit->editor(), SIGNAL(cursorPositionChanged(int,int)), SLOT(searchResultChanged(int,int)));
333 }
334 
336 {
337  delete m_sizeLabel;
338  delete m_searchEdit;
339  delete m_loadingLabel;
340  delete m_songTableWidget;
341  delete m_statisticTableWidget;
342 }
343 
345 {
348  m_loadingLabel->move((width() - m_loadingLabel->width()) / 2, (height() + 120 - m_loadingLabel->height()) / 2);
349 }
350 
352 {
353  switch(index)
354  {
355  case 0: m_searchEdit->editor()->setPlaceholderText(tr("Please input search song words")); break;
356  case 1: m_searchEdit->editor()->setPlaceholderText(tr("Please input search artist words")); break;
357  case 2: m_searchEdit->editor()->setPlaceholderText(tr("Please input search album words")); break;
358  case 3: m_searchEdit->editor()->setPlaceholderText(tr("Please input search year words")); break;
359  case 4: m_searchEdit->editor()->setPlaceholderText(tr("Please input search genre words")); break;
360  default: break;
361  }
362 
364  m_searchEdit->editor()->clear();
365  m_statisticTableWidget->setVisible(index != 0);
367 }
368 
370 {
372  {
375  return;
376  }
377 
378  m_containerItems.clear();
379  m_sizeLabel->clear();
381  m_searchEdit->editor()->clear();
383 
384  QString path = G_SETTING_PTR->value(MusicSettingManager::MediaLibraryPath).toString();
385  if(path.isEmpty())
386  {
387 #if TTK_QT_VERSION_CHECK(5,0,0)
388  path = QStandardPaths::writableLocation(QStandardPaths::MusicLocation) + TTK_SEPARATOR;
389 #else
390  path = QDesktopServices::storageLocation(QDesktopServices::MusicLocation) + TTK_SEPARATOR;
391 #endif
393  }
394 
395  m_loadingLabel->run(true);
397  m_sizeLabel->setText(tr(" (Songs Totol: %1)").arg(files.size()));
398 
399  int count = 0;
400  MusicSongMeta meta;
401  for(const QString &path : qAsConst(files))
402  {
404  {
405  break;
406  }
407 
408  if(!meta.read(path))
409  {
410  continue;
411  }
412 
413  MusicSongInfoItem info;
414  info.m_title = TTK::generateSongName(meta.title(), meta.artist());
415  info.m_artist = TTK::generateArtist(meta.artist());
416  info.m_album = TTK::generateAlbum(meta.album());
417  info.m_track = meta.trackNum();
418  info.m_year = TTK::generateYear(meta.year());
419  info.m_genre = TTK::generateGenre(meta.genre());
420  info.m_path = path;
421  m_containerItems << info;
422 
423  qApp->processEvents();
424  m_loadingLabel->setValue(++count * 100.0f / files.size());
425  }
426 
429  m_loadingLabel->run(false);
430 }
431 
433 {
434  const QString &path = TTK::File::getExistingDirectory(this);
435  if(!path.isEmpty())
436  {
438  refreshItems();
439  }
440 }
441 
443 {
444  TTKIntList result;
445  for(int i = 0; i < m_containerItems.count(); ++i)
446  {
447  QString v;
448  switch(m_tabButton->currentIndex())
449  {
450  case 0: v = m_containerItems[i].m_title; break;
451  case 1: v = m_containerItems[i].m_artist; break;
452  case 2: v = m_containerItems[i].m_album; break;
453  case 3: v = m_containerItems[i].m_year; break;
454  case 4: v = m_containerItems[i].m_genre; break;
455  default: break;
456  }
457 
458  if(v.contains(m_searchEdit->editor()->text(), Qt::CaseInsensitive))
459  {
460  result << i;
461  }
462  }
463 
464  MusicSongInfoItemList data;
465  for(const int index : qAsConst(result))
466  {
467  data.append(m_containerItems[index]);
468  }
469 
470  m_searchResultLevel = column;
471  m_searchResultItems.insert(column, result);
472 
476 }
477 
479 {
480  Q_UNUSED(column);
481  mappedSearchRow(m_searchEdit->editor()->text().length(), row);
483 }
484 
485 void MusicLocalManagerWidget::resizeEvent(QResizeEvent *event)
486 {
487  QWidget::resizeEvent(event);
488  resizeWidget();
489 }
490 
491 void MusicLocalManagerWidget::updateStatisticWidget(int index, const MusicSongInfoItemList &items)
492 {
493  if(index == 0)
494  {
495  return;
496  }
497 
498  QString label;
499  MusicSongStatisticItem statistic;
500  for(const MusicSongInfoItem &item : qAsConst(items))
501  {
502  QString data;
503  switch(index)
504  {
505  case 0: break;
506  case 1:
507  {
508  data = item.m_artist;
509  label = tr("Artist");
510  break;
511  }
512  case 2:
513  {
514  data = item.m_album;
515  label = tr("Album");
516  break;
517  }
518  case 3:
519  {
520  data = item.m_year;
521  label = tr("Year");
522  break;
523  }
524  case 4:
525  {
526  data = item.m_genre;
527  label = tr("Genre");
528  break;
529  }
530  default: break;
531  }
532 
533  if(!statistic.contains(data))
534  {
535  statistic.insert(data, 1);
536  }
537  else
538  {
539  statistic.insert(data, statistic[data] + 1);
540  }
541  }
542 
544  m_statisticTableWidget->setHorizontalHeaderLabels({label, tr("Count")});
545 }
MusicLocalManagerSongsTableWidget * m_songTableWidget
TTK_MODULE_EXPORT QString getExistingDirectory(QWidget *parent)
TTK_MODULE_EXPORT QString generateSongName(const QString &title, const QString &artist)
Definition: musicsong.cpp:105
bool read(const QString &url)
QString genre() noexcept
The class of the local manager songs table widget.
QString title() noexcept
void itemDoubleClicked(int row, int column)
MusicGifLabelValueWidget * m_loadingLabel
virtual void contextMenuEvent(QContextMenuEvent *event) overridefinal
QString artist() noexcept
MusicLocalManagerSongsTableWidget(QWidget *parent=nullptr)
static QString generateYear(const QString &v)
void updateStatisticWidget(int index, const MusicSongInfoItemList &items)
static QStringList supportMusicInputFilterFormats()
The class of the table widget base.
TTK_MODULE_EXPORT void enableBreakPoint(bool enable)
void searchResultChanged(int row, int column)
static const QString ScrollBarStyle04
#define QtItemSetTextAlignment(p, a)
Item text alignment.
Definition: ttkqtcompat.h:45
void addButtons(const QStringList &titles)
void addCellItem(const MusicSongStatisticItem &song)
static QString generateAlbum(const QString &v)
virtual void resizeWidget() overridefinal
MusicSearchEdit * editor() const
static const QString ColorStyle01
Color.
Definition: musicuiobject.h:37
void addSongToPlaylist(const QStringList &items)
QList< int > TTKIntList
Definition: ttkqtglobal.h:204
The class of the local song item information.
#define qAsConst
Definition: ttkqtglobal.h:51
static const QString ColorStyle02
Definition: musicuiobject.h:40
MusicLocalManagerStatisticTableWidget * m_statisticTableWidget
QString album() noexcept
MusicLocalManagerWidget(QWidget *parent=nullptr)
static const QString PushButtonStyle03
The namespace of the process utils.
Definition: ttkcompat.h:24
#define TTK_SIGNLE_SHOT(...)
Definition: ttkqtglobal.h:193
static QString generateArtist(const QString &v)
TTK_MODULE_EXPORT bool isBreakPointEnabled()
static const QString BackgroundStyle01
Background.
Definition: musicuiobject.h:77
#define TTK_SEPARATOR
Definition: ttkglobal.h:196
static MusicSongsContainerWidget * instance()
QMap< QString, int > MusicSongStatisticItem
MusicItemQueryEdit * m_searchEdit
#define TTK_SLOT
Definition: ttkqtglobal.h:181
void addCellItems(const MusicSongInfoItemList &songs)
The class of the local manager statistic table widget.
static QString generateGenre(const QString &v)
static const QString BackgroundStyle10
static const QString MenuStyle02
virtual void resizeEvent(QResizeEvent *event) overridefinal
int currentIndex() const
Definition: ttktabbutton.h:55
MusicLocalManagerStatisticTableWidget(QWidget *parent=nullptr)
#define WINDOW_WIDTH_MIN
Definition: musicobject.h:155
The class of the tab button module.
Definition: ttktabbutton.h:29
QString trackNum() noexcept
TTK_MODULE_EXPORT QStringList fileListByPath(const QString &dpath, const QStringList &filter={}, bool recursively=true)
The class of the music song meta.
Definition: musicsongmeta.h:30
The class of the music song info.
Definition: musicsong.h:28
The class of the query line edit widget.
QString year() noexcept
The class of the songs list abstract table widget.
virtual void removeItems() overridefinal
TTK_MODULE_EXPORT bool isNetworkUrl(const QString &path)
#define G_SETTING_PTR
The class of the float gif label value widget.