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