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