TTKMusicPlayer  4.2.0.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
musicapplication.cpp
Go to the documentation of this file.
1 #include "musicapplication.h"
2 #include "ui_musicapplication.h"
5 #include "musicconfigmanager.h"
6 #include "musicplayer.h"
7 #include "musicformats.h"
8 #include "musicplaylist.h"
10 #include "musicbottomareawidget.h"
11 #include "musictopareawidget.h"
12 #include "musicrightareawidget.h"
13 #include "musicleftareawidget.h"
14 #include "musicapplicationmodule.h"
15 #include "musichotkeymanager.h"
16 #include "musicfunctionuiobject.h"
17 #include "musictoastlabel.h"
18 #include "musicfileutils.h"
19 #include "musicplaylistmanager.h"
20 #include "musictinyuiobject.h"
21 #include "musicdispatchmanager.h"
22 #include "musictkplconfigmanager.h"
23 #include "musicinputdialog.h"
24 #include "ttkversion.h"
25 #include "qalgorithm/aeswrapper.h"
26 
28 
30  : TTKAbstractMoveResizeWidget(false, parent),
31  m_ui(new Ui::MusicApplication),
32  m_quitWindowMode(false),
33  m_currentPlaylistRow(TTK_NORMAL_LEVEL)
34 {
35  m_instance = this;
36 
42 
43  m_ui->setupUi(this);
44  const QSize &size = G_SETTING_PTR->value(MusicSettingManager::ScreenSize).toSize();
45  setMinimumSize(WINDOW_WIDTH_MIN, WINDOW_HEIGHT_MIN);
46  setMaximumSize(size.width(), size.height());
47 
48  m_player = new MusicPlayer(this);
49  m_playlist = new MusicPlaylist(this);
51  m_ui->songsContainer->addWidget(m_songTreeWidget);
52 
58 
59  connect(m_rightAreaWidget, SIGNAL(updateBackgroundTheme()), m_topAreaWidget, SLOT(backgroundTransparentChanged()));
60  connect(m_rightAreaWidget, SIGNAL(updateBackgroundThemeDownload()), m_topAreaWidget, SLOT(backgroundThemeDownloadFinished()));
61 
62  m_playlist->setPlaybackMode(TTK::PlayMode::Order); //The default is the order of play
63  m_ui->musicPlayedList->setPlaylist(m_playlist);
64  m_player->setPlaylist(m_playlist);
65  m_player->setVolume(100); //The default Volume is 100
66 
67  connect(m_player, SIGNAL(positionChanged(qint64)), SLOT(positionChanged(qint64)));
68  connect(m_player, SIGNAL(durationChanged(qint64)), SLOT(durationChanged(qint64)));
69  connect(m_player, SIGNAL(stateChanged(TTK::PlayState)), SLOT(playerStateChanged(TTK::PlayState)));
70  connect(m_playlist, SIGNAL(currentIndexChanged(int)), SLOT(showCurrentSong()));
71  connect(m_ui->musicDesktopLrc, SIGNAL(clicked(bool)), m_rightAreaWidget, SLOT(setDestopLrcVisible(bool)));
72 
73  m_ui->musicKey->setFocus();
74  m_ui->lrcDisplayAllButton->hide();
75  m_ui->functionsContainer->setCurrentIndex(MUSIC_SEARCH_PAGE);
76 
77  m_ui->musicTimeWidget->setInputModule(this);
78 
79  G_HOTKEY_PTR->addHotKey(this, SLOT(switchToPlayState()));
80  G_HOTKEY_PTR->addHotKey(this, SLOT(showSettingWidget()));
81  G_HOTKEY_PTR->addHotKey(this, SLOT(playPrevious()));
82  G_HOTKEY_PTR->addHotKey(this, SLOT(playNext()));
83  G_HOTKEY_PTR->addHotKey(this, SLOT(volumeUp()));
84  G_HOTKEY_PTR->addHotKey(this, SLOT(volumeDown()));
85  G_HOTKEY_PTR->addHotKey(this, SLOT(volumeMute()));
86  G_HOTKEY_PTR->addHotKey(this, SLOT(importSongsPopup()));
87  G_HOTKEY_PTR->addHotKey(this, SLOT(addSongToLovestList()));
88  G_HOTKEY_PTR->addHotKey(this, SLOT(currentPlayLocation()));
89  G_HOTKEY_PTR->addHotKey(this, SLOT(importSongsItemList()));
90  G_HOTKEY_PTR->addHotKey(this, SLOT(exportSongsItemList()));
91  G_HOTKEY_PTR->addHotKey(m_applicationModule, SLOT(showSpectrumWidget()));
92  G_HOTKEY_PTR->addHotKey(this, SLOT(windowConciseChanged()));
93  G_HOTKEY_PTR->addHotKey(m_applicationModule, SLOT(showAboutWidget()));
94  G_HOTKEY_PTR->addHotKey(this, SLOT(quitWindow()));
95 
96  // Objects Mouse tracking
97  setObjectsTracking({m_ui->background, m_ui->songsContainer});
98 
100  TTK_SIGNLE_SHOT(m_rightAreaWidget, showSongMainWidget, TTK_SLOT);
101 }
102 
104 {
105  delete m_player;
106  delete m_playlist;
107  delete m_songTreeWidget;
108  delete m_bottomAreaWidget;
109  delete m_topAreaWidget;
110  delete m_rightAreaWidget;
111  delete m_leftAreaWidget;
112  delete m_applicationModule;
113  delete m_ui;
114 }
115 
117 {
118  return m_instance;
119 }
120 
122 {
124  {
125  return {};
126  }
127 
128  const MusicPlayItem &item = m_playlist->currentItem();
129  const MusicSongItemList &items = m_songTreeWidget->items();
130 
131  if(0 <= m_currentPlaylistRow && m_currentPlaylistRow < items.count())
132  {
133  const MusicSongList &songs = items[m_currentPlaylistRow].m_songs;
135  return (index != -1) ? songs[index].name() : QString();
136  }
137  return {};
138 }
139 
141 {
143  {
144  return {};
145  }
146 
147  const MusicPlayItem &item = m_playlist->currentItem();
148  const MusicSongItemList &items = m_songTreeWidget->items();
149 
150  if(0 <= m_currentPlaylistRow && m_currentPlaylistRow < items.count())
151  {
152  const MusicSongList &songs = items[m_currentPlaylistRow].m_songs;
154  return (index != -1) ? songs[index].path() : QString();
155  }
156  return {};
157 }
158 
160 {
162 }
163 
165 {
166  //Loading the current song lrc
168  {
169  return;
170  }
171 
172  const QString &name = currentFileName();
173  const QString &prefixPath = TTK::String::lrcDirPrefix() + name;
174  const QString &nativePath = QFileInfo(currentFilePath()).absolutePath() + TTK_SEPARATOR + name;
175  const QStringList &formats = {LRC_FILE, KRC_FILE, QRC_FILE, TRC_FILE, YRC_FILE};
176 
177  QString path;
178  for(const QString &format : formats)
179  {
180  path = prefixPath + format;
181  if(QFile::exists(path))
182  {
183  break;
184  }
185 
186  // try to load same dir file
187  path = nativePath + format;
188  if(QFile::exists(path))
189  {
190  break;
191  }
192 
193  path.clear();
194  }
195 
197  //reset current song lrc index.
199 }
200 
201 void MusicApplication::importSongsByOutside(const QString &path, bool play)
202 {
203  if(path.isEmpty())
204  {
205  return;
206  }
207 
209 
210  if(play)
211  {
213  }
214 }
215 
216 QString MusicApplication::containsDownloadItem(bool &contains) const
217 {
218  contains = false;
219  QString path;
221  {
222  const MusicPlayItem &item = m_playlist->currentItem();
223  if(item.isValid())
224  {
226  {
227  path = item.m_path;
228  }
229  else
230  {
231  const MusicSong currentSong(item.m_path);
232  path = QString("%1%2.%3").arg(G_SETTING_PTR->value(MusicSettingManager::DownloadMusicDirPath).toString(), currentFileName(), currentSong.format());
233  }
234 
235  contains = QFile::exists(path);
236  }
237  }
238  return path;
239 }
240 
242 {
244  {
245  const MusicPlayItem &item = m_playlist->currentItem();
246  const MusicSongItemList &items = m_songTreeWidget->items();
247  if(item.isValid() && item.m_playlistRow < items.count())
248  {
249  const MusicSongList &currentSongs = items[item.m_playlistRow].m_songs;
250  const int index = m_songTreeWidget->mapSongIndexByFilePath(item.m_playlistRow, item.m_path);
251  const MusicSongList &loveSongs = items[MUSIC_LOVEST_LIST].m_songs;
252  return index != -1 ? loveSongs.contains(currentSongs[index]) : false;
253  }
254  }
255  return false;
256 }
257 
259 {
261  {
262  const MusicSongItemList &items = m_songTreeWidget->items();
263  if(m_songTreeWidget->currentIndex() < items.count())
264  {
265  const MusicSongList &currentSongs = items[m_songTreeWidget->currentIndex()].m_songs;
266  const MusicSongList &loveSongs = items[MUSIC_LOVEST_LIST].m_songs;
267  return loveSongs.contains(currentSongs[index]);
268  }
269  }
270  return false;
271 }
272 
274 {
276 }
277 
279 {
280  return m_player->isPlaying();
281 }
282 
284 {
285  return m_player->duration();
286 }
287 
289 {
290  return m_playlist->playbackMode();
291 }
292 
294 {
296  //
297  m_quitWindowMode = true;
300  //Write configuration files
302 }
303 
305 {
307  m_ui->musicTimeWidget->setValue(position);
308 
309  if(m_playlist->isEmpty())
310  {
311  m_ui->playCurrentTime->setText(TTK_TIME_INIT);
312  }
313  else
314  {
315  m_ui->playCurrentTime->setText(TTKTime::formatDuration(position));
316  }
317  //Show the current play time
318  m_songTreeWidget->updateDurationLabel(m_ui->playCurrentTime->text(), m_ui->playTotalTime->text());
319 }
320 
322 {
323  //Show the current play total time
324  m_ui->musicTimeWidget->setRange(0, duration);
325  m_ui->playTotalTime->setText(TTK_SEPARATOR + TTKTime::formatDuration(duration));
326  //Loading the current song lrc
328  //Update song quality label
329  m_ui->musicQualityLabel->updateQuality();
330 }
331 
333 {
334  if(state == TTK::PlayState::Stopped)
335  {
336  const bool concise = G_SETTING_PTR->value(MusicSettingManager::WindowConciseMode).toBool();
337  m_ui->musicKey->setStyleSheet(concise ? TTK::UI::TinyBtnPlay : TTK::UI::BtnPlay);
338  }
339 }
340 
342 {
343  QString name;
344  const MusicPlayItem &item = m_playlist->currentItem();
345  const int index = m_songTreeWidget->mapSongIndexByFilePath(item.m_playlistRow, item.m_path);
348 
349  if(index > TTK_NORMAL_LEVEL) //The list to end
350  {
351  name = currentFileName();
353  bool exist = false;
354  containsDownloadItem(exist);
355  m_ui->musicDownload->setStyleSheet(exist ? TTK::UI::BtnDownload : TTK::UI::BtnUnDownload);
356  //
357  exist = containsLovestItem();
358  m_ui->musicBestLove->setStyleSheet(exist ? TTK::UI::BtnLove : TTK::UI::BtnUnLove);
359  //
360  m_songTreeWidget->selectRow(index);
361  }
362  else
363  {
364  const bool concise = G_SETTING_PTR->value(MusicSettingManager::WindowConciseMode).toBool();
365  m_ui->musicBestLove->setStyleSheet(TTK::UI::BtnUnLove);
366  m_ui->musicDownload->setStyleSheet(TTK::UI::BtnUnDownload);
367  m_ui->musicKey->setStyleSheet(concise ? TTK::UI::TinyBtnPlay : TTK::UI::BtnPlay);
368  m_player->stop();
370 
374  m_ui->musicTimeWidget->setCurrentPlayState(isPlaying());
375 
376  durationChanged(0);
377  positionChanged(0);
379  }
380 
381  m_ui->musicPlayedList->selectCurrentIndex();
384  m_ui->musicSongTitle->setText(name);
385  m_ui->musicMoreFunction->setCurrentSongName(name);
386  //Show the current play song information
389  //display current ArtTheme pic
391  G_BACKGROUND_PTR->setArtistName(currentFileName());
393 }
394 
396 {
397  if(m_playlist->isEmpty())
398  {
399  return; //The playlist is not performing space-time
400  }
401 
402  const bool concise = G_SETTING_PTR->value(MusicSettingManager::WindowConciseMode).toBool();
403  if(isPlaying())
404  {
405  m_ui->musicKey->setStyleSheet(concise ? TTK::UI::TinyBtnPlay : TTK::UI::BtnPlay);
406  m_player->pause();
409  }
410  else
411  {
412  m_ui->musicKey->setStyleSheet(concise ? TTK::UI::TinyBtnPause : TTK::UI::BtnPause);
413  m_player->play();
416  }
417 
421  m_ui->musicTimeWidget->setCurrentPlayState(isPlaying());
422 }
423 
425 {
426  if(!isPlaying())
427  {
428  return;
429  }
430 
432 }
433 
435 {
436  if(m_playlist->isEmpty())
437  {
438  return; //The playlist is not performing space-time
439  }
440 
441  m_ui->musicPlayedList->clearQueueState();
443 
444  m_player->stop();
446 }
447 
449 {
450  if(m_playlist->isEmpty())
451  {
452  return; //The playlist is not performing space-time
453  }
454 
456 
457  m_player->stop();
459 }
460 
462 {
464  m_ui->musicPlayMode->setPlaybackMode(TTK::PlayMode::Order);
465 }
466 
468 {
470  m_ui->musicPlayMode->setPlaybackMode(TTK::PlayMode::Random);
471 }
472 
474 {
476  m_ui->musicPlayMode->setPlaybackMode(TTK::PlayMode::ListLoop);
477 }
478 
480 {
482  m_ui->musicPlayMode->setPlaybackMode(TTK::PlayMode::OneLoop);
483 }
484 
486 {
488  m_ui->musicPlayMode->setPlaybackMode(TTK::PlayMode::Once);
489 }
490 
492 {
493  int currentVol = m_player->volume();
494  currentVol -= 15;
495  if(currentVol < 0)
496  {
497  currentVol = 0; //reset music volume
498  }
499  volumeChanged(currentVol);
500 }
501 
503 {
504  int currentVol = m_player->volume();
505  currentVol += 15;
506  if(currentVol > 100)
507  {
508  currentVol = 100; //reset music volume
509  }
510  volumeChanged(currentVol);
511 }
512 
514 {
516  const int volume = m_player->volume();
517 
520  m_ui->musicSound->setValue(volume);
521  G_SETTING_PTR->setValue(MusicSettingManager::Volume, volume);
522 }
523 
525 {
528  m_ui->musicSound->setValue(volume);
529  m_player->setVolume(volume);
530  G_SETTING_PTR->setValue(MusicSettingManager::Volume, volume);
531 }
532 
534 {
535  QMenu menu;
536  menu.setStyleSheet(TTK::UI::MenuStyle02);
537  menu.addAction(tr("Open Files"), this, SLOT(importSongsByFiles()));
538  menu.addAction(tr("Open Dir"), this, SLOT(importSongsByDir()));
539  menu.addAction(tr("Open Url"), this, SLOT(importSongsByUrl()));
540  menu.addSeparator();
541  menu.addAction(tr("Files Drag Drop"))->setEnabled(false);
542 
544  menu.exec(QCursor::pos());
545 }
546 
548 {
549  const QStringList &files = TTK::File::getOpenFileNames(this, MusicFormats::supportMusicInputFormats());
550  m_songTreeWidget->importSongsByPath(files, index);
551 }
552 
554 {
555  const QString &path = TTK::File::getExistingDirectory(this);
556  if(path.isEmpty())
557  {
558  return;
559  }
560 
561  m_songTreeWidget->importSongsByUrl(path, index);
562 }
563 
565 {
566  MusicInputDialog dialog;
567  dialog.setPlaceholderText(tr("Please enter the local or network playback address"));
568  if(!dialog.exec())
569  {
570  return;
571  }
572 
573  const QString &path = dialog.text();
574  if(path.isEmpty())
575  {
576  return;
577  }
578 
580 }
581 
583 {
585  if(files.isEmpty())
586  {
587  return;
588  }
589 
590  MusicPlaylistManager manager;
591  MusicSongItemList items;
592  manager.readSongItems(files, items);
594 }
595 
597 {
599  if(path.isEmpty())
600  {
601  return;
602  }
603 
604  const MusicSongItemList &items = m_songTreeWidget->items();
605  if(index < 0 || index >= items.count())
606  {
607  return;
608  }
609 
610  MusicPlaylistManager manager;
611  manager.writeSongItem(path, {items[index]});
612 
613  MusicToastLabel::popup(tr("Export current file success"));
614 }
615 
617 {
619  if(path.isEmpty())
620  {
621  return;
622  }
623 
624  MusicPlaylistManager manager;
625  manager.writeSongItem(path, m_songTreeWidget->items());
626 
627  MusicToastLabel::popup(tr("Export current file success"));
628 }
629 
631 {
632  const QString &path = m_songTreeWidget->mapFilePathBySongIndex(m_currentPlaylistRow, row);
634 }
635 
637 {
639  m_player->stop();
641 }
642 
644 {
645  m_player->stop();
646 
647  if(row != -1)
648  {
649  setPlayIndex();
650  m_currentPlaylistRow = row;
652  }
653  else
654  {
655  m_playlist->clear();
656  m_currentPlaylistRow = row;
658  }
659 }
660 
662 {
663  m_player->stop();
664 
666  {
667  setPlayIndex();
668  const MusicSongItemList &items = m_songTreeWidget->items();
669  const int index = m_songTreeWidget->currentIndex();
670  if(0 <= index && index < items.count())
671  {
672  m_ui->musicPlayedList->append(items[index].m_songs);
673  }
674  }
675 
679 }
680 
681 void MusicApplication::playIndexClicked(int row, int column)
682 {
684  {
685  setPlayIndex();
686  const MusicSongItemList &items = m_songTreeWidget->items();
687  const int index = m_songTreeWidget->currentIndex();
688  if(0 <= index && index < items.count())
689  {
690  m_ui->musicPlayedList->append(items[index].m_songs);
691  }
692  }
693 
694  playIndexBy(row, column);
695 }
696 
698 {
699  //Drag the progress indicator to rewind or fast-forward through the current song
700  m_player->setPosition(time);
701  //Set lrc corrent to show
703 }
704 
706 {
708 }
709 
711 {
712  if(m_playlist->isEmpty())
713  {
714  return;
715  }
716 
717  const MusicPlayItem &item = m_playlist->currentItem();
718  const int index = m_songTreeWidget->mapSongIndexByFilePath(item.m_playlistRow, item.m_path);
720 }
721 
723 {
724  const MusicPlayItem &item = m_playlist->currentItem();
725  const int index = m_songTreeWidget->mapSongIndexByFilePath(item.m_playlistRow, item.m_path);
726  if(m_playlist->isEmpty() || index < 0)
727  {
728  return;
729  }
730 
731  bool contains = true;
732  if(state)
733  {
734  contains = containsLovestItem();
735  if(contains)
736  {
737  m_songTreeWidget->songToLovestListAt(false, index);
739  }
740  else
741  {
742  m_songTreeWidget->songToLovestListAt(true, index);
744  }
745  }
746  else
747  {
748  m_songTreeWidget->songToLovestListAt(false, index);
750  }
751 
752  MusicToastLabel::popup(!contains ? tr("Add music to lovest list done") : tr("Remove music to lovest list done"));
753 }
754 
756 {
759 }
760 
762 {
764 }
765 
767 {
768  QMenu menu(this);
769  menu.setStyleSheet(TTK::UI::MenuStyle02);
770 
771  QMenu *addNewFilesMenu = menu.addMenu(tr("Add New Files"));
772  addNewFilesMenu->addAction(tr("Open Files"), this, SLOT(importSongsByFiles()));
773  addNewFilesMenu->addAction(tr("Open Dir"), this, SLOT(importSongsByDir()));
774  addNewFilesMenu->addAction(tr("Open Url"), this, SLOT(importSongsByUrl()));
775  TTK::Widget::adjustMenuPosition(addNewFilesMenu);
776 
777  QMenu *playbackModeMenu = menu.addMenu(tr("Playback Mode"));
778 
779  QList<QAction*> actions;
780  actions << playbackModeMenu->addAction(tr("Play Once"), this, SLOT(playOnce()));
781  actions << playbackModeMenu->addAction(tr("Single Cycle"), this, SLOT(playOneLoop()));
782  actions << playbackModeMenu->addAction(tr("Order Play"), this, SLOT(playOrder()));
783  actions << playbackModeMenu->addAction(tr("List Cycle"), this, SLOT(playlistLoop()));
784  actions << playbackModeMenu->addAction(tr("Random Play"), this, SLOT(playRandom()));
785 
786  int index = TTK_NORMAL_LEVEL;
787  switch(playMode())
788  {
789  case TTK::PlayMode::Once: index = 0; break;
790  case TTK::PlayMode::OneLoop: index = 1; break;
791  case TTK::PlayMode::Order: index = 2; break;
792  case TTK::PlayMode::ListLoop: index = 3; break;
793  case TTK::PlayMode::Random: index = 4; break;
794  default: break;
795  }
796 
797  if(index > TTK_NORMAL_LEVEL && index < actions.count())
798  {
799  actions[index]->setIcon(QIcon(":/contextMenu/btn_selected"));
800  }
801 
802  menu.addSeparator();
803 
804  QMenu *remoteControlMenu = menu.addMenu(tr("Remote Control"));
805  remoteControlMenu->addAction(tr("Square Remote"), m_topAreaWidget, SLOT(showSquareRemote()));
806  remoteControlMenu->addAction(tr("Rectangle Remote"), m_topAreaWidget, SLOT(showRectangleRemote()));
807  remoteControlMenu->addAction(tr("Simple Style Remote"), m_topAreaWidget, SLOT(showSimpleStyleRemote()));
808  remoteControlMenu->addAction(tr("Complex Style Remote"), m_topAreaWidget, SLOT(showComplexStyleRemote()));
809  remoteControlMenu->addAction(tr("Ripple Remote"), m_topAreaWidget, SLOT(showRippleRemote()));
810  remoteControlMenu->addAction(tr("Delete Remote"), m_topAreaWidget, SLOT(deleteCurrentRemote()));
811  TTK::Widget::adjustMenuPosition(remoteControlMenu);
812 
813  menu.addAction(QIcon(":/contextMenu/btn_equalizer"), tr("Equalizer"), m_applicationModule, SLOT(showEqualizerWidget()));
814  menu.addAction(tr("Sound Effect"), m_applicationModule, SLOT(showSoundEffectWidget()));
815  menu.addAction(tr("Timing Settings"), m_applicationModule, SLOT(showTimerWidget()));
816  menu.addAction(tr("Music Spectrum"), m_applicationModule, SLOT(showSpectrumWidget()));
817  menu.addSeparator();
818 
819  QAction *window = menu.addAction(tr("Window Top"), m_applicationModule, SLOT(setWindowToTop()));
820  window->setIcon(QIcon(m_applicationModule->windowToTop() ? ":/contextMenu/btn_selected" : QString()));
821  menu.addAction(tr("Reset Window"), m_applicationModule, SLOT(resetWindowGeometry()));
822 
823  QMenu *downloadMenu = menu.addMenu(tr("Download"));
825  actions.clear();
826  actions << downloadMenu->addAction(tr("Full Download"), MusicRightAreaWidget::instance(), SLOT(changeDownloadFulllyWidget()));
827  actions << downloadMenu->addAction(tr("Custom"), MusicRightAreaWidget::instance(), SLOT(changeDownloadCustumWidget()));
828 
829  if(index > TTK_NORMAL_LEVEL && index < actions.count())
830  {
831  actions[index]->setIcon(QIcon(":/contextMenu/btn_selected"));
832  }
833 
835  {
836  menu.addAction(QIcon(":/contextMenu/btn_update"), tr("New Version"), m_applicationModule, SLOT(showVersionWidget()));
837  }
838  menu.addAction(QIcon(":/contextMenu/btn_setting"), tr("Settings"), this, SLOT(showSettingWidget()));
839 
840  QMenu *informationMenu = menu.addMenu(QIcon(":/contextMenu/btn_about"), tr("About"));
841  informationMenu->addAction(QIcon(":/contextMenu/btn_bug_reoprt"), tr("Bug Report"), m_applicationModule, SLOT(showBugReportView()));
842  informationMenu->addAction(QIcon(":/contextMenu/btn_about"), tr("Version") + TTK_STR_CAT(TTK_VERSION_STR, TTK_VERSION_TIME_STR), m_applicationModule, SLOT(showAboutWidget()));
843  menu.addSeparator();
844 
845  menu.addAction(QIcon(":/contextMenu/btn_quit"), tr("Quit"), this, SLOT(quitWindow()));
846  menu.exec(QCursor::pos());
847 }
848 
850 {
851  //This attribute is effective immediately.
853  //
857 }
858 
859 void MusicApplication::removeLoveItemAt(const QString &path, bool current)
860 {
861  removeItemAt({path}, false, current, MUSIC_LOVEST_LIST);
862 }
863 
864 void MusicApplication::removeItemAt(const QStringList &path, bool remove, bool current, int playlistRow)
865 {
866  if(path.isEmpty())
867  {
868  return;
869  }
870 
871  if(current)
872  {
873  const MusicPlayItem &item = m_playlist->currentItem();
874  TTKIntList index;
875  for(const QString &p : qAsConst(path))
876  {
877  int idx = -1;
878  do
879  {
880  idx = m_playlist->find(item.m_playlistRow, p, idx + 1);
881  if(idx != -1)
882  {
883  index << idx;
884  }
885  } while(idx != -1);
886  }
887 
888  if(index.isEmpty())
889  {
890  return;
891  }
892  std::sort(index.begin(), index.end());
893 
894  bool contains = false;
895  int oldIndex = m_playlist->currentIndex();
897  if(index.count() == 1 && index.front() == oldIndex)
898  {
899  contains = true;
900  }
902  for(int i = index.count() - 1; i >= 0; --i)
903  {
904  m_ui->musicPlayedList->remove(index[i]);
905  if(i != 0 && !contains && oldIndex <= index[i] && oldIndex >= index[i - 1])
906  {
907  oldIndex -= i;
908  contains = true;
909  }
910  }
911 
912  if(!contains && m_playlist->currentIndex() > index[0])
913  {
914  oldIndex -= index.count();
915  }
916 
917  if(oldIndex == m_playlist->count())
918  {
919  --oldIndex;
920  }
921  m_playlist->setCurrentIndex(oldIndex);
922 
923  if(contains)
924  {
925  //The corresponding item is deleted from the Playlist
926  m_player->stop();
928 
929  const QString &removeParh = playlistRow == MUSIC_NETWORK_LIST ? TTK::generateNetworkSongPath(item.m_path) : item.m_path;
930  if(remove && !QFile::remove(removeParh))
931  {
933  }
934  }
935  }
936  else
937  {
938  for(const QString &p : qAsConst(path))
939  {
940  m_ui->musicPlayedList->remove(playlistRow, p);
941  }
942  }
943 }
944 
946 {
947  const QString &fileName = currentFileName();
948  QFile::remove(TTK::String::lrcDirPrefix() + fileName + LRC_FILE);
950 }
951 
953 {
954  const int pos = m_player->position();
955  if(pos != -1)
956  {
957  //Set lrc corrent to show
959  }
960 }
961 
963 {
964  if(isPlaying())
965  {
966  m_player->setPosition(pos);
967  }
968 }
969 
971 {
972  if(m_playlist->isEmpty() || index < 0 || index >= m_playlist->count())
973  {
974  return;
975  }
976 
978 }
979 
980 void MusicApplication::currentPlaylist(QStringList &list)
981 {
983 }
984 
985 void MusicApplication::resizeEvent(QResizeEvent *event)
986 {
987  if(m_ui->background->isRunning())
988  {
989  event->ignore();
990  return;
991  }
992 
993  if(!m_quitWindowMode)
994  {
999  TTKAbstractMoveResizeWidget::resizeEvent(event);
1000  }
1001  else
1002  {
1003  setMinimumSize(0, 0);
1004  m_ui->background->stop();
1005  event->ignore();
1006  }
1007 }
1008 
1009 void MusicApplication::closeEvent(QCloseEvent *event)
1010 {
1011  TTKAbstractMoveResizeWidget::closeEvent(event);
1012  event->ignore();
1013 
1015  {
1016  hide();
1017  m_bottomAreaWidget->showMessage(tr("Prompt"), tr("TTKMusicPlayer will run in the background"));
1018  }
1019  else
1020  {
1021  quitWindow();
1022  }
1023 }
1024 
1025 void MusicApplication::contextMenuEvent(QContextMenuEvent *event)
1026 {
1027  const int h = event->pos().y();
1028  if(h < m_ui->topWidget->height() || h > height() - m_ui->bottomWidget->height())
1029  {
1030  TTKAbstractMoveResizeWidget::contextMenuEvent(event);
1031  createRightMenu();
1032  }
1033  else
1034  {
1035  event->accept();
1036  }
1037 }
1038 
1040 {
1041  TTKAbstractMoveResizeWidget::enterEvent(event);
1043 }
1044 
1045 void MusicApplication::leaveEvent(QEvent *event)
1046 {
1047  TTKAbstractMoveResizeWidget::leaveEvent(event);
1049 }
1050 
1051 void MusicApplication::mouseMoveEvent(QMouseEvent *event)
1052 {
1054 
1055  if(m_ui->background->isRunning())
1056  {
1057  setFixedSize(G_SETTING_PTR->value(MusicSettingManager::WidgetSize).toSize());
1058  }
1059  else
1060  {
1061  const QSize &size = G_SETTING_PTR->value(MusicSettingManager::ScreenSize).toSize();
1062  setMinimumSize(WINDOW_WIDTH_MIN, WINDOW_HEIGHT_MIN);
1063  setMaximumSize(size.width(), size.height());
1064  }
1065 }
1066 
1067 void MusicApplication::mouseReleaseEvent(QMouseEvent *event)
1068 {
1071 }
1072 
1074 {
1075  if(!m_ui->background->isRunning() && event->pos().y() <= m_ui->topWidget->height() && !G_SETTING_PTR->value(MusicSettingManager::WindowConciseMode).toBool())
1076  {
1077  TTKAbstractMoveResizeWidget::mouseDoubleClickEvent(event);
1078  if(event->buttons() == Qt::LeftButton)
1079  {
1080  isMaximized() ? showNormal() : showMaximized();
1081  }
1082  }
1083  else
1084  {
1085  event->ignore();
1086  }
1087 }
1088 
1089 bool MusicApplication::eventFilter(QObject *object, QEvent *event)
1090 {
1091  if(object == m_ui->centerWidget && (QEvent::ContextMenu == event->type() || QEvent::MouseButtonPress == event->type()))
1092  {
1093  return true;
1094  }
1095  return TTKAbstractMoveResizeWidget::eventFilter(object, event);
1096 }
1097 
1099 {
1103 }
1104 
1106 {
1107  int value = TTK_NORMAL_LEVEL;
1108  //Path configuration song
1109  MusicSongItemList items;
1110  {
1111  MusicTKPLConfigManager manager;
1112  if(manager.fromFile(PLAYLIST_PATH_FULL))
1113  {
1114  manager.readBuffer(items);
1115  }
1116  }
1117 
1118  MusicConfigManager manager;
1119  if(!manager.fromFile(COFIG_PATH_FULL))
1120  {
1121  TTK_ERROR_STREAM("Load config file error:" << COFIG_PATH_FULL);
1122  return;
1123  }
1124 
1125  manager.readBuffer();
1127  const bool success = m_songTreeWidget->addSongItemList(items);
1128 
1130  {
1131  case TTK::PlayMode::Order: playOrder();break;
1132  case TTK::PlayMode::Random: playRandom();break;
1133  case TTK::PlayMode::ListLoop: playlistLoop();break;
1134  case TTK::PlayMode::OneLoop: playOneLoop();break;
1135  case TTK::PlayMode::Once: playOnce();break;
1136  default:break;
1137  }
1138 
1139  value = G_SETTING_PTR->value(MusicSettingManager::RemoteWidgetMode).toInt();
1140  if(value != 0)
1141  {
1143  }
1144 
1145  //The size of the volume of the allocation of songs
1147 
1148  //Configure playback mode
1149  m_ui->musicEnhancedButton->setEnhancedSongConfig(G_SETTING_PTR->value(MusicSettingManager::EnhancedMusicIndex).toInt());
1151  if(G_SETTING_PTR->value(MusicSettingManager::EqualizerEnable).toInt() == 1)
1152  {
1154  }
1155 
1156  //music hotkey
1158  {
1159  QStringList hotkeys = G_SETTING_PTR->value(MusicSettingManager::HotkeyValue).toString().split(TTK_SPLITER);
1160  if(hotkeys.count() != G_HOTKEY_PTR->count())
1161  {
1162  hotkeys = G_HOTKEY_PTR->defaultKeys();
1163  }
1164 
1165  for(int i = 0; i < hotkeys.count(); ++i)
1166  {
1167  G_HOTKEY_PTR->setHotKey(i, hotkeys[i]);
1168  }
1169  //
1170  G_HOTKEY_PTR->setEnabled(true);
1171  }
1172 
1173  //musicSetting
1175  //Just always set fade false, because it is not finished yet.
1177 #ifdef Q_OS_UNIX
1178  //Disable window quit mode on unix
1180 #endif
1181  //Set interior lrc mode always on
1183 
1184  //Set the desktop lrc should be shown
1187 
1188  //Set the current background color and alpha value
1190 
1191  //Configuration from next time also stopped at the last record.
1192  const QStringList &lastPlayIndex = G_SETTING_PTR->value(MusicSettingManager::LastPlayIndex).toStringList();
1193  //add new music file to playlist
1194  value = lastPlayIndex[1].toInt();
1195  m_playlist->add(value, m_songTreeWidget->songsFilePath(value));
1196  if(TTK_NORMAL_LEVEL < value && value < items.count())
1197  {
1198  m_ui->musicPlayedList->append(items[value].m_songs);
1199  }
1200 
1201  applyParameter();
1202 
1203  if(success && lastPlayIndex[0] == "1")
1204  {
1205  TTK_SIGNLE_SHOT(m_songTreeWidget, updateCurrentIndex, TTK_SLOT);
1206  const int index = lastPlayIndex[2].toInt();
1208  m_playlist->blockSignals(true);
1210  m_playlist->blockSignals(false);
1211  m_ui->musicPlayedList->selectCurrentIndex();
1212  }
1213 
1214  //Configure automatic playback
1215  if(G_SETTING_PTR->value(MusicSettingManager::StartUpPlayMode).toInt() == 1)
1216  {
1218  }
1219 
1223 
1224  //Set the lrc color the user set
1226 
1227  //init or reset the window
1228  value = G_SETTING_PTR->value(MusicSettingManager::ShowDesktopLrc).toInt();
1231 
1232  //Reset geometry
1233  setGeometry(manager.readWindowGeometry());
1234 
1235  //Reset window concise
1237  {
1239  }
1240 
1241  //Update check on
1243  {
1245  }
1246 }
1247 
1249 {
1250  MusicConfigManager manager;
1251  if(!manager.load(COFIG_PATH_FULL))
1252  {
1253  TTK_ERROR_STREAM("Load config file error:" << COFIG_PATH_FULL);
1254  return;
1255  }
1256 
1260  G_SETTING_PTR->setValue(MusicSettingManager::Volume, m_ui->musicSound->value());
1261 
1262  QStringList lastPlayIndex = G_SETTING_PTR->value(MusicSettingManager::LastPlayIndex).toStringList();
1263  if(lastPlayIndex.isEmpty())
1264  {
1265  lastPlayIndex << "1" << "-1" << "-1";
1266  }
1267  else
1268  {
1269  const MusicPlayItem &item = m_playlist->currentItem();
1270  lastPlayIndex[1] = QString::number(item.m_playlistRow);
1271  lastPlayIndex[2] = QString::number(m_songTreeWidget->mapSongIndexByFilePath(item.m_playlistRow, item.m_path));
1272  }
1273 
1274  G_SETTING_PTR->setValue(MusicSettingManager::LastPlayIndex, lastPlayIndex);
1280  manager.writeBuffer();
1281 
1282  {
1283  MusicTKPLConfigManager manager;
1284  if(!manager.load(PLAYLIST_PATH_FULL))
1285  {
1286  return;
1287  }
1288 
1289  manager.writeBuffer(m_songTreeWidget->items());
1290  }
1291 }
bool containsLovestItem() const
static MusicRightAreaWidget * instance()
void setupUi(Ui::MusicApplication *ui)
MusicBottomAreaWidget * m_bottomAreaWidget
#define QtEnterEvent
Event enter.
Definition: ttkqtcompat.h:160
int backgroundTransparent() const noexcept
TTK_MODULE_EXPORT QString getExistingDirectory(QWidget *parent)
#define TTKStaticCast(x, y)
Definition: ttkglobal.h:231
The class of the music play item.
Definition: musicplaylist.h:27
The class of the songs container widget.
bool systemTrayIsVisible() noexcept
The class of the app top area widget.
The class of the app object module.
void setEqualizerConfig()
void updateDurationLabel(const QString &current, const QString &total) const
#define G_DISPATCH_PTR
static MusicApplication * instance()
PlayState
Definition: musicobject.h:178
void setShuffleMode(bool shuffle) noexcept
QRect readWindowGeometry() const
#define MUSIC_SEARCH_PAGE
#define PLAYLIST_PATH_FULL
Definition: musicobject.h:148
#define TTK_LOW_LEVEL
Definition: ttkglobal.h:332
void addSongToLovestList(bool state=true)
static QString supportPlaylistInputFormats() noexcept
MusicApplication(QWidget *parent=nullptr)
#define G_BACKGROUND_PTR
#define G_HOTKEY_PTR
void setPlaySongChanged(int index)
MusicPlayItem currentItem() const noexcept
void songToLovestListAt(bool state, int row)
bool fromFile(const QString &name)
virtual void leaveEvent(QEvent *event) overridefinal
QString m_path
Definition: musicplaylist.h:30
virtual void mouseMoveEvent(QMouseEvent *event) overridefinal
void positionChanged(qint64 position)
bool isEmpty() const noexcept
TTK::PlayMode playbackMode() const noexcept
void setObjectsTracking(const QWidgetList &objects)
The class of the ttk moving resize widget base.
QStringList songsFilePath(int index) const
#define TTK_SPLITER
Definition: ttkglobal.h:275
voidpf void uLong size
Definition: ioapi.h:136
void playIndexBy(int row)
static constexpr const char * BtnUnDownload
The class of the app main widget.
void setEnhanced(Enhance type)
Definition: musicplayer.cpp:87
void setCurrentPlayState(bool state) const
void playSortBy(int row)
virtual void mouseReleaseEvent(QMouseEvent *event) overridefinal
QStringList songsFileName(int index) const
MusicPlayer * m_player
void setLabelText(const QString &name) const
bool addSongItemList(const MusicSongItemList &items)
void setPosition(qint64 position)
Definition: musicplayer.cpp:60
virtual void mouseMoveEvent(QMouseEvent *event) override
The class of the playlist manager.
The class of the xml config manager.
void volumeChanged(int volume)
int find(const MusicPlayItem &item) const
static constexpr const char * BtnPlay
The class of the music player.
Definition: musicplayer.h:31
void removeItemAt(const QStringList &path, bool remove, bool current, int playlistRow)
void importSongsByDir(int index=TTK_LOW_LEVEL)
virtual bool eventFilter(QObject *object, QEvent *event) override
Ui::MusicApplication * m_ui
void setInteriorLrcVisible(bool status) const
void playAnyTimeAt(int time)
int mapSongIndexByFilePath(int playlistRow, const QString &path) const
qint64 duration() const
Definition: musicplayer.cpp:50
void add(int playlistRow, const QString &content)
virtual void mouseDoubleClickEvent(QMouseEvent *event) overridefinal
virtual bool eventFilter(QObject *object, QEvent *event) overridefinal
TTK::PlayMode playMode() const noexcept
qint64 position() const
Definition: musicplayer.cpp:55
MusicTopAreaWidget * m_topAreaWidget
void setVolume(int volume)
Definition: musicplayer.cpp:70
static void popup(const QString &text)
TTK_MODULE_EXPORT void enableBreakPoint(bool enable) noexcept
virtual bool readBuffer(MusicSongItemList &items) overridefinal
void playedIndexBy(int row)
#define TTK_TIME_INIT
Definition: ttkglobal.h:299
bool isMuted() const noexcept
Definition: musicplayer.cpp:76
TTK_MODULE_EXPORT QString getSaveFileName(QWidget *parent, const QString &filter="Image Files (*.png *.bmp *.jpg)")
static constexpr int PLAY_PREVIOUS_LEVEL
Definition: musicplaylist.h:58
static constexpr const char * TinyBtnPause
MusicRightAreaWidget * m_rightAreaWidget
void loadCurrentSongLrc(const QString &name, const QString &path) const
void writeSongItem(const QString &path, const MusicSongItemList &item)
TTK_MODULE_EXPORT QString generateNetworkSongPath(const QString &path)
Definition: musicsong.cpp:175
const MusicSongItemList & items() const noexcept
QList< int > TTKIntList
Definition: ttkqtglobal.h:200
#define qAsConst
Definition: ttkqtglobal.h:57
const char * name
Definition: http_parser.c:458
virtual void enterEvent(QtEnterEvent *event) overridefinal
MusicSongsContainerWidget * m_songTreeWidget
void setLabelText(const QString &name) const
void setDestopLrcVisible(bool status) const
static constexpr const char * BtnDownload
void setPlaceholderText(const QString &text)
#define TTK_SIGNLE_SHOT(...)
Definition: ttkqtglobal.h:189
PlayMode
Definition: musicobject.h:185
#define TRC_FILE
Definition: musicobject.h:79
static QString supportMusicInputFormats() noexcept
void importSongsByFiles(int index=TTK_LOW_LEVEL)
void setupUi(Ui::MusicApplication *ui)
MusicPlaylist * m_playlist
void durationChanged(qint64 duration)
void setVolumeValue(int value) const
#define TTK_NORMAL_LEVEL
Definition: ttkglobal.h:333
void currentPlaylist(QStringList &list)
void importSongsByPath(const QStringList &files, int playlistRow)
#define TTK_SEPARATOR
Definition: ttkglobal.h:269
TTK_MODULE_EXPORT QString lrcDirPrefix()
void playIndexClicked(int row, int column)
void updateCurrentTime(qint64 pos)
virtual void mouseReleaseEvent(QMouseEvent *event) override
#define KRC_FILE
Definition: musicobject.h:77
static QString supportPlaylistOutputFormats() noexcept
QString currentFilePath() const
#define TTK_VERSION_TIME_STR
Definition: ttkversion.h:176
#define YRC_FILE
Definition: musicobject.h:80
MusicLeftAreaWidget * m_leftAreaWidget
bool isPlaying() const noexcept
Definition: musicplayer.cpp:35
#define TTK_SLOT
Definition: ttkqtglobal.h:177
void importSongsByUrl(const QString &path, int playlistRow)
static constexpr int PLAY_NEXT_LEVEL
Definition: musicplaylist.h:57
#define TTK_VERSION_STR
Definition: ttkversion.h:175
void setDestopLrcVisible(bool visible) const
void setPlaybackMode(TTK::PlayMode mode) noexcept
void importSongsByOutside(const QString &path, bool play)
void setCurrentIndex(int index)
The class of the app left area widget.
QString format() const noexcept
Definition: musicsong.h:98
int count() const noexcept
The class of the app bottom area widget.
#define QRC_FILE
Definition: musicobject.h:78
static const QString MenuStyle02
void setCurrentPlayState(bool state) const
void setCurrentPlayState(bool state) const
static constexpr const char * TinyBtnPlay
#define COFIG_PATH_FULL
Definition: musicobject.h:147
bool backgroundTransparentEnabled() const
bool windowToTop() const noexcept
bool checkMusicListCurrentIndex() const
void setVolumeValue(int value) const
Enhance enhanced() const noexcept
The class of the tkpl config manager.
void exportSongsItem(int index)
#define MUSIC_NETWORK_LIST
bool load(const QString &name)
#define MUSIC_LOVEST_LIST
virtual void contextMenuEvent(QContextMenuEvent *event) overridefinal
int currentIndex() const noexcept
bool isPlaying() const
virtual void closeEvent(QCloseEvent *event) overridefinal
#define WINDOW_WIDTH_MIN
Definition: musicobject.h:167
static constexpr const char * BtnLove
void readSongItems(const QStringList &paths, MusicSongItemList &items)
#define TTK_STR_CAT(...)
Definition: ttkglobal.h:240
static MusicApplication * m_instance
void setupUi(Ui::MusicApplication *ui)
void enhancedSongChanged(int type)
void checkMetaDataValid(bool mode) const
QString containsDownloadItem(bool &contains) const
TTK_MODULE_EXPORT QStringList getOpenFileNames(QWidget *parent, const QString &filter="Image Files (*.png *.bmp *.jpg)")
static constexpr const char * BtnPause
int volume() const
Definition: musicplayer.cpp:65
The class of the music song info.
Definition: musicsong.h:28
bool isValid() const noexcept
Definition: musicplaylist.h:45
void removeLoveItemAt(const QString &path, bool current)
virtual void resizeEvent(QResizeEvent *event) overridefinal
void appendSongItemList(const MusicSongItemList &items)
void setBackgroundAnimation(bool state)
#define const
Definition: zconf.h:233
void playerStateChanged(TTK::PlayState state)
bool systemCloseConfig() noexcept
void showMessage(const QString &title, const QString &text)
The class of the music play list.
Definition: musicplaylist.h:63
QString backgroundPath() const noexcept
The class of the input widget.
#define MUSIC_NORMAL_LIST
#define LRC_FILE
Definition: musicobject.h:76
void setSongTimeSpeed(qint64 time) const
void setupUi(Ui::MusicApplication *ui)
TTK_MODULE_EXPORT void adjustMenuPosition(QMenu *menu)
void setSongLoveState(bool state)
#define TTK_ERROR_STREAM(msg)
Definition: ttklogger.h:76
qint64 duration() const
The class of the app right area widget.
QString mapFilePathBySongIndex(int playlistRow, int index) const
void remoteTypeChanged(QAction *type)
void setMuted(bool muted)
Definition: musicplayer.cpp:81
void backgroundAnimationChanged(bool state)
void updateCurrentLrc(qint64 current, qint64 total, bool playState) const
QPoint readShowDesktopLrcGeometry() const
state
Definition: http_parser.c:279
#define WINDOW_HEIGHT_MIN
Definition: musicobject.h:168
QString text() const
virtual bool writeBuffer(const MusicSongItemList &items) overridefinal
static constexpr const char * BtnUnLove
#define G_SETTING_PTR
static qint64 formatDuration(const QString &time) noexcept
Definition: ttktime.cpp:123
MusicApplicationModule * m_applicationModule
QString currentFileName() const