TTKMusicPlayer  4.1.3.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_currentSongTreeIndex(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(playPrevious()));
81  G_HOTKEY_PTR->addHotKey(this, SLOT(playNext()));
82  G_HOTKEY_PTR->addHotKey(this, SLOT(volumeUp()));
83  G_HOTKEY_PTR->addHotKey(this, SLOT(volumeDown()));
84  G_HOTKEY_PTR->addHotKey(this, SLOT(showSettingWidget()));
85  G_HOTKEY_PTR->addHotKey(this, SLOT(importSongsPopup()));
86  G_HOTKEY_PTR->addHotKey(this, SLOT(volumeMute()));
87 
88  // Objects Mouse tracking
89  setObjectsTracking({m_ui->background, m_ui->songsContainer});
90 
92  TTK_SIGNLE_SHOT(m_rightAreaWidget, showSongMainWidget, TTK_SLOT);
93 }
94 
96 {
97  delete m_player;
98  delete m_playlist;
99  delete m_songTreeWidget;
100  delete m_bottomAreaWidget;
101  delete m_topAreaWidget;
102  delete m_rightAreaWidget;
103  delete m_leftAreaWidget;
104  delete m_applicationModule;
105  delete m_ui;
106 }
107 
109 {
110  return m_instance;
111 }
112 
114 {
116  {
117  return {};
118  }
119 
120  const MusicPlayItem &item = m_playlist->currentItem();
121  const MusicSongItemList &items = m_songTreeWidget->items();
122 
123  if(0 <= m_currentSongTreeIndex && m_currentSongTreeIndex < items.count())
124  {
125  const MusicSongList &songs = items[m_currentSongTreeIndex].m_songs;
127  return (index != -1) ? songs[index].name() : QString();
128  }
129  return {};
130 }
131 
133 {
135  {
136  return {};
137  }
138 
139  const MusicPlayItem &item = m_playlist->currentItem();
140  const MusicSongItemList &items = m_songTreeWidget->items();
141 
142  if(0 <= m_currentSongTreeIndex && m_currentSongTreeIndex < items.count())
143  {
144  const MusicSongList &songs = items[m_currentSongTreeIndex].m_songs;
146  return (index != -1) ? songs[index].path() : QString();
147  }
148  return {};
149 }
150 
152 {
154 }
155 
157 {
158  //Loading the current song lrc
160  {
161  return;
162  }
163 
164  const QString &fileName = currentFileName();
165  const QString &prefixPath = TTK::String::lrcDirPrefix() + fileName;
166  QString path = prefixPath + LRC_FILE;
167 
168  if(!QFile::exists(path))
169  {
170  // try to load krc file
171  path = prefixPath + KRC_FILE;
172 
173  if(!QFile::exists(path))
174  {
175  const QString &nativePath = QFileInfo(currentFilePath()).absoluteDir().absolutePath() + fileName;
176  // try to load same dir lrc file
177  path = nativePath + LRC_FILE;
178 
179  if(!QFile::exists(path))
180  {
181  // try to load same dir krc file
182  path = nativePath + KRC_FILE;
183  }
184  }
185  }
186 
187  m_rightAreaWidget->loadCurrentSongLrc(fileName, path);
188  //reset current song lrc index.
190 }
191 
192 void MusicApplication::importSongsByOutside(const QString &path, bool play)
193 {
194  if(path.isEmpty())
195  {
196  return;
197  }
198 
200  if(play)
201  {
203  }
204 }
205 
206 QString MusicApplication::containsDownloadItem(bool &contains) const
207 {
208  contains = false;
209  QString path;
211  {
212  const MusicPlayItem &item = m_playlist->currentItem();
213  if(item.isValid())
214  {
216  {
217  path = item.m_path;
218  }
219  else
220  {
221  const MusicSong currentSong(item.m_path);
222  path = QString("%1%2.%3").arg(G_SETTING_PTR->value(MusicSettingManager::DownloadMusicDirPath).toString(), currentFileName(), currentSong.format());
223  }
224 
225  contains = QFile::exists(path);
226  }
227  }
228  return path;
229 }
230 
232 {
234  {
235  const MusicPlayItem &item = m_playlist->currentItem();
236  const MusicSongItemList &items = m_songTreeWidget->items();
237  if(item.isValid() && item.m_playlistRow < items.count())
238  {
239  const MusicSongList &currentSongs = items[item.m_playlistRow].m_songs;
240  const int index = m_songTreeWidget->mapSongIndexByFilePath(item.m_playlistRow, item.m_path);
241  const MusicSongList &loveSongs = items[MUSIC_LOVEST_LIST].m_songs;
242  return index != -1 ? loveSongs.contains(currentSongs[index]) : false;
243  }
244  }
245  return false;
246 }
247 
249 {
251  {
252  const MusicSongItemList &items = m_songTreeWidget->items();
253  if(m_songTreeWidget->currentIndex() < items.count())
254  {
255  const MusicSongList &currentSongs = items[m_songTreeWidget->currentIndex()].m_songs;
256  const MusicSongList &loveSongs = items[MUSIC_LOVEST_LIST].m_songs;
257  return loveSongs.contains(currentSongs[index]);
258  }
259  }
260  return false;
261 }
262 
264 {
266 }
267 
269 {
270  return m_player->isPlaying();
271 }
272 
274 {
275  return m_player->duration();
276 }
277 
279 {
280  return m_playlist->playbackMode();
281 }
282 
284 {
286  //
287  m_quitWindowMode = true;
290  //Write configuration files
292 }
293 
295 {
297  m_ui->musicTimeWidget->setValue(position);
298 
299  if(m_playlist->isEmpty())
300  {
301  m_ui->playCurrentTime->setText(TTK_TIME_INIT);
302  }
303  else
304  {
305  m_ui->playCurrentTime->setText(TTKTime::formatDuration(position));
306  }
307  //Show the current play time
308  m_songTreeWidget->updateDurationLabel(m_ui->playCurrentTime->text(), m_ui->playTotalTime->text());
309 }
310 
312 {
313  //Show the current play total time
314  m_ui->musicTimeWidget->setRange(0, duration);
315  m_ui->playTotalTime->setText(TTK_SEPARATOR + TTKTime::formatDuration(duration));
316  //Loading the current song lrc
318  //Update song quality label
319  m_ui->musicQualityLabel->updateQuality();
320 }
321 
323 {
324  if(state == TTK::PlayState::Stopped)
325  {
326  const bool concise = G_SETTING_PTR->value(MusicSettingManager::WindowConciseMode).toBool();
327  m_ui->musicKey->setStyleSheet(concise ? TTK::UI::TinyBtnPlay : TTK::UI::BtnPlay);
328  }
329 }
330 
332 {
333  QString name;
334  const MusicPlayItem &item = m_playlist->currentItem();
335  const int index = m_songTreeWidget->mapSongIndexByFilePath(item.m_playlistRow, item.m_path);
338 
339  if(index > TTK_NORMAL_LEVEL) //The list to end
340  {
341  name = currentFileName();
343  bool exist = false;
344  containsDownloadItem(exist);
345  m_ui->musicDownload->setStyleSheet(exist ? TTK::UI::BtnDownload : TTK::UI::BtnUnDownload);
346  //
347  exist = containsLovestItem();
348  m_ui->musicBestLove->setStyleSheet(exist ? TTK::UI::BtnLove : TTK::UI::BtnUnLove);
349  //
350  m_songTreeWidget->selectRow(index);
351  }
352  else
353  {
354  const bool concise = G_SETTING_PTR->value(MusicSettingManager::WindowConciseMode).toBool();
355  m_ui->musicBestLove->setStyleSheet(TTK::UI::BtnUnLove);
356  m_ui->musicDownload->setStyleSheet(TTK::UI::BtnUnDownload);
357  m_ui->musicKey->setStyleSheet(concise ? TTK::UI::TinyBtnPlay : TTK::UI::BtnPlay);
358  m_player->stop();
360 
364  m_ui->musicTimeWidget->setCurrentPlayState(isPlaying());
365 
366  durationChanged(0);
367  positionChanged(0);
369  }
370 
371  m_ui->musicPlayedList->selectCurrentIndex();
374  m_ui->musicSongTitle->setText(name);
375  m_ui->musicMoreFunction->setCurrentSongName(name);
376  //Show the current play song information
379  //display current ArtTheme pic
381  G_BACKGROUND_PTR->setArtistName(currentFileName());
383 }
384 
386 {
387  if(m_playlist->isEmpty())
388  {
389  return; //The playlist is not performing space-time
390  }
391 
392  const bool concise = G_SETTING_PTR->value(MusicSettingManager::WindowConciseMode).toBool();
393  if(isPlaying())
394  {
395  m_ui->musicKey->setStyleSheet(concise ? TTK::UI::TinyBtnPlay : TTK::UI::BtnPlay);
396  m_player->pause();
399  }
400  else
401  {
402  m_ui->musicKey->setStyleSheet(concise ? TTK::UI::TinyBtnPause : TTK::UI::BtnPause);
403  m_player->play();
406  }
407 
411  m_ui->musicTimeWidget->setCurrentPlayState(isPlaying());
412 }
413 
415 {
416  if(!isPlaying())
417  {
418  return;
419  }
420 
422 }
423 
425 {
426  if(m_playlist->isEmpty())
427  {
428  return; //The playlist is not performing space-time
429  }
430 
431  m_ui->musicPlayedList->clearQueueState();
433 
434  m_player->stop();
436 }
437 
439 {
440  if(m_playlist->isEmpty())
441  {
442  return; //The playlist is not performing space-time
443  }
444 
446 
447  m_player->stop();
449 }
450 
452 {
454  m_ui->musicPlayMode->setPlaybackMode(TTK::PlayMode::Order);
455 }
456 
458 {
460  m_ui->musicPlayMode->setPlaybackMode(TTK::PlayMode::Random);
461 }
462 
464 {
466  m_ui->musicPlayMode->setPlaybackMode(TTK::PlayMode::ListLoop);
467 }
468 
470 {
472  m_ui->musicPlayMode->setPlaybackMode(TTK::PlayMode::OneLoop);
473 }
474 
476 {
478  m_ui->musicPlayMode->setPlaybackMode(TTK::PlayMode::Once);
479 }
480 
482 {
484  const int volume = m_player->volume();
485 
488  m_ui->musicSound->setValue(volume);
489  G_SETTING_PTR->setValue(MusicSettingManager::Volume, volume);
490 }
491 
493 {
496  m_ui->musicSound->setValue(volume);
497  m_player->setVolume(volume);
498  G_SETTING_PTR->setValue(MusicSettingManager::Volume, volume);
499 }
500 
502 {
503  QMenu menu;
504  menu.setStyleSheet(TTK::UI::MenuStyle02);
505  menu.addAction(tr("Open Files"), this, SLOT(importSongsByFiles()));
506  menu.addAction(tr("Open Dir"), this, SLOT(importSongsByDir()));
507  menu.addAction(tr("Open Url"), this, SLOT(importSongsByUrl()));
508  menu.addSeparator();
509  menu.addAction(tr("Files Drag Drop"))->setEnabled(false);
510 
512  menu.exec(QCursor::pos());
513 }
514 
516 {
517  const QStringList &files = TTK::File::getOpenFileNames(this, MusicFormats::supportMusicInputFormats());
518  m_songTreeWidget->importSongsByPath(files, index);
519 }
520 
522 {
523  const QString &path = TTK::File::getExistingDirectory(this);
524  if(path.isEmpty())
525  {
526  return;
527  }
528 
529  m_songTreeWidget->importSongsByUrl(path, index);
530 }
531 
533 {
534  MusicInputDialog dialog;
535  dialog.setPlaceholderText(tr("Please enter the local or network playback address"));
536  if(!dialog.exec())
537  {
538  return;
539  }
540 
541  const QString &path = dialog.text();
542  if(path.isEmpty())
543  {
544  return;
545  }
546 
548 }
549 
551 {
553  if(files.isEmpty())
554  {
555  return;
556  }
557 
558  MusicPlaylistManager manager;
559  MusicSongItemList items;
560  manager.readSongItems(files, items);
562 }
563 
565 {
567  if(path.isEmpty())
568  {
569  return;
570  }
571 
572  const MusicSongItemList &items = m_songTreeWidget->items();
573  if(index < 0 || index >= items.count())
574  {
575  return;
576  }
577 
578  MusicPlaylistManager manager;
579  manager.writeSongItem(path, {items[index]});
580 
581  MusicToastLabel::popup(tr("Export current file success"));
582 }
583 
585 {
587  if(path.isEmpty())
588  {
589  return;
590  }
591 
592  MusicPlaylistManager manager;
593  manager.writeSongItem(path, m_songTreeWidget->items());
594 
595  MusicToastLabel::popup(tr("Export current file success"));
596 }
597 
599 {
602 }
603 
605 {
607  m_player->stop();
609 }
610 
612 {
613  m_player->stop();
614 
615  if(row != -1)
616  {
617  setPlayIndex();
620  }
621  else
622  {
623  m_playlist->clear();
626  }
627 }
628 
630 {
631  m_player->stop();
632 
634  {
635  setPlayIndex();
636  const MusicSongItemList &items = m_songTreeWidget->items();
637  const int index = m_songTreeWidget->currentIndex();
638  if(0 <= index && index < items.count())
639  {
640  m_ui->musicPlayedList->append(items[index].m_songs);
641  }
642  }
643 
647 }
648 
649 void MusicApplication::playIndexClicked(int row, int column)
650 {
652  {
653  setPlayIndex();
654  const MusicSongItemList &items = m_songTreeWidget->items();
655  const int index = m_songTreeWidget->currentIndex();
656  if(0 <= index && index < items.count())
657  {
658  m_ui->musicPlayedList->append(items[index].m_songs);
659  }
660  }
661 
662  playIndexBy(row, column);
663 }
664 
666 {
667  //Drag the progress indicator to rewind or fast-forward through the current song
668  m_player->setPosition(time);
669  //Set lrc corrent to show
671 }
672 
674 {
675  int currentVol = m_player->volume();
676  currentVol -= 15;
677  if(currentVol < 0)
678  {
679  currentVol = 0; //reset music volume
680  }
681  volumeChanged(currentVol);
682 }
683 
685 {
686  int currentVol = m_player->volume();
687  currentVol += 15;
688  if(currentVol > 100)
689  {
690  currentVol = 100; //reset music volume
691  }
692  volumeChanged(currentVol);
693 }
694 
696 {
698 }
699 
701 {
702  if(m_playlist->isEmpty())
703  {
704  return;
705  }
706 
707  const MusicPlayItem &item = m_playlist->currentItem();
708  const int index = m_songTreeWidget->mapSongIndexByFilePath(item.m_playlistRow, item.m_path);
710 }
711 
713 {
714  const MusicPlayItem &item = m_playlist->currentItem();
715  const int index = m_songTreeWidget->mapSongIndexByFilePath(item.m_playlistRow, item.m_path);
716  if(m_playlist->isEmpty() || index < 0)
717  {
718  return;
719  }
720 
721  bool contains = true;
722  if(state)
723  {
724  contains = containsLovestItem();
725  if(contains)
726  {
727  m_songTreeWidget->songToLovestListAt(false, index);
729  }
730  else
731  {
732  m_songTreeWidget->songToLovestListAt(true, index);
734  }
735  }
736  else
737  {
738  m_songTreeWidget->songToLovestListAt(false, index);
740  }
741 
742  MusicToastLabel::popup(!contains ? tr("Add music to lovest list done") : tr("Remove music to lovest list done"));
743 }
744 
746 {
749 }
750 
752 {
754 }
755 
757 {
758  QMenu menu(this);
759  menu.setStyleSheet(TTK::UI::MenuStyle02);
760 
761  QMenu addNewFiles(tr("Add New Files"), &menu);
762  menu.addMenu(&addNewFiles);
763  addNewFiles.addAction(tr("Open Files"), this, SLOT(importSongsByFiles()));
764  addNewFiles.addAction(tr("Open Dir"), this, SLOT(importSongsByDir()));
765  addNewFiles.addAction(tr("Open Url"), this, SLOT(importSongsByUrl()));
766  TTK::Widget::adjustMenuPosition(&addNewFiles);
767 
768  QMenu playbackMode(tr("Playback Mode"), &menu);
769  menu.addMenu(&playbackMode);
770 
771  QList<QAction*> actions;
772  actions << playbackMode.addAction(tr("Play Once"), this, SLOT(playOnce()));
773  actions << playbackMode.addAction(tr("Single Cycle"), this, SLOT(playOneLoop()));
774  actions << playbackMode.addAction(tr("Order Play"), this, SLOT(playOrder()));
775  actions << playbackMode.addAction(tr("List Cycle"), this, SLOT(playlistLoop()));
776  actions << playbackMode.addAction(tr("Random Play"), this, SLOT(playRandom()));
777 
778  int index = TTK_NORMAL_LEVEL;
779  switch(playMode())
780  {
781  case TTK::PlayMode::Once: index = 0; break;
782  case TTK::PlayMode::OneLoop: index = 1; break;
783  case TTK::PlayMode::Order: index = 2; break;
784  case TTK::PlayMode::ListLoop: index = 3; break;
785  case TTK::PlayMode::Random: index = 4; break;
786  default: break;
787  }
788 
789  if(index > TTK_NORMAL_LEVEL && index < actions.count())
790  {
791  actions[index]->setIcon(QIcon(":/contextMenu/btn_selected"));
792  }
793 
794  menu.addSeparator();
795  QMenu remoteControl(tr("Remote Control"), &menu);
796  menu.addMenu(&remoteControl);
797  remoteControl.addAction(tr("Square Remote"), m_topAreaWidget, SLOT(showSquareRemote()));
798  remoteControl.addAction(tr("Rectangle Remote"), m_topAreaWidget, SLOT(showRectangleRemote()));
799  remoteControl.addAction(tr("Simple Style Remote"), m_topAreaWidget, SLOT(showSimpleStyleRemote()));
800  remoteControl.addAction(tr("Complex Style Remote"), m_topAreaWidget, SLOT(showComplexStyleRemote()));
801  remoteControl.addAction(tr("Ripple Remote"), m_topAreaWidget, SLOT(showRippleRemote()));
802  remoteControl.addAction(tr("Delete Remote"), m_topAreaWidget, SLOT(deleteCurrentRemote()));
803  TTK::Widget::adjustMenuPosition(&remoteControl);
804 
805  menu.addAction(QIcon(":/contextMenu/btn_equalizer"), tr("Equalizer"), m_applicationModule, SLOT(showEqualizerWidget()));
806  menu.addAction(tr("Sound Effect"), m_applicationModule, SLOT(showSoundEffectWidget()));
807  menu.addAction(tr("Timing Settings"), m_applicationModule, SLOT(showTimerWidget()));
808  menu.addAction(tr("Music Spectrum"), m_applicationModule, SLOT(showSpectrumWidget()));
809  menu.addSeparator();
810 
811  QAction *window = menu.addAction(tr("Window Top"), m_applicationModule, SLOT(setWindowToTop()));
812  window->setIcon(QIcon(m_applicationModule->windowToTop() ? ":/contextMenu/btn_selected" : QString()));
813  menu.addAction(tr("Reset Window"), m_applicationModule, SLOT(resetWindowGeometry()));
814 
815  QMenu download(tr("Download"), &menu);
816  menu.addMenu(&download);
818  actions.clear();
819  actions << download.addAction(tr("Full Download"), MusicRightAreaWidget::instance(), SLOT(changeDownloadFulllyWidget()));
820  actions << download.addAction(tr("Custom"), MusicRightAreaWidget::instance(), SLOT(changeDownloadCustumWidget()));
821  if(index > TTK_NORMAL_LEVEL && index < actions.count())
822  {
823  actions[index]->setIcon(QIcon(":/contextMenu/btn_selected"));
824  }
825 
827  {
828  menu.addAction(QIcon(":/contextMenu/btn_update"), tr("New Version"), m_applicationModule, SLOT(showVersionWidget()));
829  }
830  menu.addAction(QIcon(":/contextMenu/btn_setting"), tr("Settings"), this, SLOT(showSettingWidget()));
831 
832  QMenu information(tr("About"), &menu);
833  menu.addMenu(&information)->setIcon(QIcon(":/contextMenu/btn_about"));
834  information.addAction(QIcon(":/contextMenu/btn_bug_reoprt"), tr("Bug Report"), m_applicationModule, SLOT(showBugReportView()));
835  information.addAction(QIcon(":/contextMenu/btn_about"), tr("Version") + TTK_STR_CAT(TTK_VERSION_STR, TTK_VERSION_TIME_STR), m_applicationModule, SLOT(showAboutWidget()));
836 
837  menu.addSeparator();
838  menu.addAction(QIcon(":/contextMenu/btn_quit"), tr("Quit"), this, SLOT(quitWindow()));
839  menu.exec(QCursor::pos());
840 }
841 
843 {
844  //This attribute is effective immediately.
846  //
850 }
851 
852 void MusicApplication::removeLoveItemAt(const QString &path, bool current)
853 {
854  removeItemAt({path}, false, current, MUSIC_LOVEST_LIST);
855 }
856 
857 void MusicApplication::removeItemAt(const QStringList &path, bool remove, bool current, int playlistRow)
858 {
859  if(path.isEmpty())
860  {
861  return;
862  }
863 
864  if(current)
865  {
866  const MusicPlayItem &item = m_playlist->currentItem();
867  TTKIntList index;
868  for(const QString &p : qAsConst(path))
869  {
870  int idx = -1;
871  do
872  {
873  idx = m_playlist->find(item.m_playlistRow, p, idx + 1);
874  if(idx != -1)
875  {
876  index << idx;
877  }
878  } while(idx != -1);
879  }
880 
881  if(index.isEmpty())
882  {
883  return;
884  }
885  std::sort(index.begin(), index.end());
886 
887  bool contains = false;
888  int oldIndex = m_playlist->currentIndex();
890  if(index.count() == 1 && index.front() == oldIndex)
891  {
892  contains = true;
893  }
895  for(int i = index.count() - 1; i >= 0; --i)
896  {
897  m_ui->musicPlayedList->remove(index[i]);
898  if(i != 0 && !contains && oldIndex <= index[i] && oldIndex >= index[i - 1])
899  {
900  oldIndex -= i;
901  contains = true;
902  }
903  }
904 
905  if(!contains && m_playlist->currentIndex() > index[0])
906  {
907  oldIndex -= index.count();
908  }
909 
910  if(oldIndex == m_playlist->count())
911  {
912  --oldIndex;
913  }
914  m_playlist->setCurrentIndex(oldIndex);
915 
916  if(contains)
917  {
918  //The corresponding item is deleted from the Playlist
919  m_player->stop();
921 
922  const QString &removeParh = playlistRow == MUSIC_NETWORK_LIST ? TTK::generateNetworkSongPath(item.m_path) : item.m_path;
923  if(remove && !QFile::remove(removeParh))
924  {
926  }
927  }
928  }
929  else
930  {
931  for(const QString &p : qAsConst(path))
932  {
933  m_ui->musicPlayedList->remove(playlistRow, p);
934  }
935  }
936 }
937 
939 {
940  const QString &fileName = currentFileName();
941  QFile::remove(TTK::String::lrcDirPrefix() + fileName + LRC_FILE);
943 }
944 
946 {
947  const int pos = m_player->position();
948  if(pos != -1)
949  {
950  //Set lrc corrent to show
952  }
953 }
954 
956 {
957  if(isPlaying())
958  {
959  m_player->setPosition(pos);
960  }
961 }
962 
964 {
965  if(m_playlist->isEmpty() || index < 0 || index >= m_playlist->count())
966  {
967  return;
968  }
969 
971 }
972 
973 void MusicApplication::currentPlaylist(QStringList &list)
974 {
976 }
977 
978 void MusicApplication::resizeEvent(QResizeEvent *event)
979 {
980  if(m_ui->background->isRunning())
981  {
982  event->ignore();
983  return;
984  }
985 
986  if(!m_quitWindowMode)
987  {
992  TTKAbstractMoveResizeWidget::resizeEvent(event);
993  }
994  else
995  {
996  setMinimumSize(0, 0);
997  m_ui->background->stop();
998  event->ignore();
999  }
1000 }
1001 
1002 void MusicApplication::closeEvent(QCloseEvent *event)
1003 {
1004  TTKAbstractMoveResizeWidget::closeEvent(event);
1005  event->ignore();
1006 
1008  {
1009  hide();
1010  m_bottomAreaWidget->showMessage(tr("Prompt"), tr("TTKMusicPlayer will run in the background"));
1011  }
1012  else
1013  {
1014  quitWindow();
1015  }
1016 }
1017 
1018 void MusicApplication::contextMenuEvent(QContextMenuEvent *event)
1019 {
1020  const int h = event->pos().y();
1021  if(h < m_ui->topWidget->height() || h > height() - m_ui->bottomWidget->height())
1022  {
1023  TTKAbstractMoveResizeWidget::contextMenuEvent(event);
1024  createRightMenu();
1025  }
1026  else
1027  {
1028  event->accept();
1029  }
1030 }
1031 
1033 {
1034  TTKAbstractMoveResizeWidget::enterEvent(event);
1036 }
1037 
1038 void MusicApplication::leaveEvent(QEvent *event)
1039 {
1040  TTKAbstractMoveResizeWidget::leaveEvent(event);
1042 }
1043 
1044 void MusicApplication::mouseMoveEvent(QMouseEvent *event)
1045 {
1047 
1048  if(m_ui->background->isRunning())
1049  {
1050  setFixedSize(G_SETTING_PTR->value(MusicSettingManager::WidgetSize).toSize());
1051  }
1052  else
1053  {
1054  const QSize &size = G_SETTING_PTR->value(MusicSettingManager::ScreenSize).toSize();
1055  setMinimumSize(WINDOW_WIDTH_MIN, WINDOW_HEIGHT_MIN);
1056  setMaximumSize(size.width(), size.height());
1057  }
1058 }
1059 
1060 void MusicApplication::mouseReleaseEvent(QMouseEvent *event)
1061 {
1064 }
1065 
1067 {
1068  if(!m_ui->background->isRunning() && event->pos().y() <= m_ui->topWidget->height() && !G_SETTING_PTR->value(MusicSettingManager::WindowConciseMode).toBool())
1069  {
1070  TTKAbstractMoveResizeWidget::mouseDoubleClickEvent(event);
1071  if(event->buttons() == Qt::LeftButton)
1072  {
1073  isMaximized() ? showNormal() : showMaximized();
1074  }
1075  }
1076  else
1077  {
1078  event->ignore();
1079  }
1080 }
1081 
1082 bool MusicApplication::eventFilter(QObject *object, QEvent *event)
1083 {
1084  if(object == m_ui->centerWidget && (QEvent::ContextMenu == event->type() || QEvent::MouseButtonPress == event->type()))
1085  {
1086  return true;
1087  }
1088  return TTKAbstractMoveResizeWidget::eventFilter(object, event);
1089 }
1090 
1092 {
1096 }
1097 
1099 {
1100  int value = TTK_NORMAL_LEVEL;
1101  //Path configuration song
1102  MusicSongItemList songs;
1103  {
1104  MusicTKPLConfigManager manager;
1105  if(manager.fromFile(PLAYLIST_PATH_FULL))
1106  {
1107  manager.readBuffer(songs);
1108  }
1109  }
1110 
1111  MusicConfigManager manager;
1112  if(!manager.fromFile(COFIG_PATH_FULL))
1113  {
1114  return;
1115  }
1116 
1117  manager.readBuffer();
1119  const bool success = m_songTreeWidget->addSongItemList(songs);
1120 
1122  {
1123  case TTK::PlayMode::Order: playOrder();break;
1124  case TTK::PlayMode::Random: playRandom();break;
1125  case TTK::PlayMode::ListLoop: playlistLoop();break;
1126  case TTK::PlayMode::OneLoop: playOneLoop();break;
1127  case TTK::PlayMode::Once: playOnce();break;
1128  default:break;
1129  }
1130 
1131  value = G_SETTING_PTR->value(MusicSettingManager::RemoteWidgetMode).toInt();
1132  if(value != 0)
1133  {
1135  }
1136 
1137  //The size of the volume of the allocation of songs
1139 
1140  //Configure playback mode
1141  m_ui->musicEnhancedButton->setEnhancedSongConfig(G_SETTING_PTR->value(MusicSettingManager::EnhancedMusicIndex).toInt());
1143  if(G_SETTING_PTR->value(MusicSettingManager::EqualizerEnable).toInt() == 1)
1144  {
1146  }
1147 
1148  //music hotkey
1150  {
1151  QStringList hotkeys = G_SETTING_PTR->value(MusicSettingManager::HotkeyValue).toString().split(TTK_SPLITER);
1152  if(hotkeys.count() != G_HOTKEY_PTR->count())
1153  {
1154  hotkeys = G_HOTKEY_PTR->defaultKeys();
1155  }
1156 
1157  for(int i = 0; i < hotkeys.count(); ++i)
1158  {
1159  G_HOTKEY_PTR->setHotKey(i, hotkeys[i]);
1160  }
1161  //
1162  G_HOTKEY_PTR->setEnabled(true);
1163  }
1164 
1165  //musicSetting
1167  //Just always set fade false, because it is not finished yet.
1169 #ifdef Q_OS_UNIX
1170  //Disable window quit mode on unix
1172 #endif
1173  //Set interior lrc mode always on
1175 
1176  //Set the desktop lrc should be shown
1179 
1180  //Set the current background color and alpha value
1182 
1183  //Configuration from next time also stopped at the last record.
1184  const QStringList &lastPlayIndex = G_SETTING_PTR->value(MusicSettingManager::LastPlayIndex).toStringList();
1185  //add new music file to playlist
1186  value = lastPlayIndex[1].toInt();
1187  m_playlist->add(value, m_songTreeWidget->songsFilePath(value));
1188  if(TTK_NORMAL_LEVEL < value && value < songs.count())
1189  {
1190  m_ui->musicPlayedList->append(songs[value].m_songs);
1191  }
1192 
1193  applyParameter();
1194 
1195  if(success && lastPlayIndex[0] == "1")
1196  {
1197  TTK_SIGNLE_SHOT(m_songTreeWidget, updateCurrentIndex, TTK_SLOT);
1198  const int index = lastPlayIndex[2].toInt();
1200  m_playlist->blockSignals(true);
1202  m_playlist->blockSignals(false);
1203  m_ui->musicPlayedList->selectCurrentIndex();
1204  }
1205 
1206  //Configure automatic playback
1207  if(G_SETTING_PTR->value(MusicSettingManager::StartUpPlayMode).toInt() == 1)
1208  {
1210  }
1211 
1215 
1216  //Set the lrc color the user set
1218 
1219  //init or reset the window
1220  value = G_SETTING_PTR->value(MusicSettingManager::ShowDesktopLrc).toInt();
1223 
1224  //Reset geometry
1225  setGeometry(manager.readWindowGeometry());
1226 
1227  //Reset window concise
1229  {
1231  }
1232 
1233  //Update check on
1235  {
1237  }
1238 }
1239 
1241 {
1242  MusicConfigManager manager;
1243  if(!manager.load(COFIG_PATH_FULL))
1244  {
1245  return;
1246  }
1247 
1251  G_SETTING_PTR->setValue(MusicSettingManager::Volume, m_ui->musicSound->value());
1252 
1253  QStringList lastPlayIndex = G_SETTING_PTR->value(MusicSettingManager::LastPlayIndex).toStringList();
1254  if(lastPlayIndex.isEmpty())
1255  {
1256  lastPlayIndex << "1" << "-1" << "-1";
1257  }
1258  else
1259  {
1260  const MusicPlayItem &item = m_playlist->currentItem();
1261  lastPlayIndex[1] = QString::number(item.m_playlistRow);
1262  lastPlayIndex[2] = QString::number(m_songTreeWidget->mapSongIndexByFilePath(item.m_playlistRow, item.m_path));
1263  }
1264 
1265  G_SETTING_PTR->setValue(MusicSettingManager::LastPlayIndex, lastPlayIndex);
1271  manager.writeBuffer();
1272 
1273  {
1274  MusicTKPLConfigManager manager;
1275  if(!manager.load(PLAYLIST_PATH_FULL))
1276  {
1277  return;
1278  }
1279 
1280  manager.writeBuffer(m_songTreeWidget->items());
1281  }
1282 }
const MusicSongItemList & items() const
bool containsLovestItem() const
static MusicRightAreaWidget * instance()
void setupUi(Ui::MusicApplication *ui)
MusicBottomAreaWidget * m_bottomAreaWidget
#define QtEnterEvent
Event enter.
Definition: ttkqtcompat.h:160
TTK_MODULE_EXPORT QString getExistingDirectory(QWidget *parent)
#define TTKStaticCast(x, y)
Definition: ttkglobal.h:159
The class of the music play item.
Definition: musicplaylist.h:27
The class of the songs container widget.
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:166
QRect readWindowGeometry() const
#define MUSIC_SEARCH_PAGE
#define PLAYLIST_PATH_FULL
Definition: musicobject.h:136
int count() const
#define TTK_LOW_LEVEL
Definition: ttkglobal.h:258
void addSongToLovestList(bool state=true)
MusicApplication(QWidget *parent=nullptr)
#define G_BACKGROUND_PTR
#define G_HOTKEY_PTR
void setPlaySongChanged(int index)
TTK::PlayMode playMode() const
void songToLovestListAt(bool state, int row)
bool fromFile(const QString &name)
TTK_MODULE_EXPORT void enableBreakPoint(bool enable)
static QString supportPlaylistOutputFormats()
virtual void leaveEvent(QEvent *event) overridefinal
QString m_path
Definition: musicplaylist.h:30
virtual void mouseMoveEvent(QMouseEvent *event) overridefinal
void positionChanged(qint64 position)
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:202
static QString supportMusicInputFormats()
voidpf void uLong size
Definition: ioapi.h:136
void playIndexBy(int row)
QString backgroundPath() const
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
TTK::PlayMode playbackMode() const
virtual bool eventFilter(QObject *object, QEvent *event) overridefinal
qint64 position() const
Definition: musicplayer.cpp:55
Enhance enhanced() const
MusicTopAreaWidget * m_topAreaWidget
void setVolume(int volume)
Definition: musicplayer.cpp:70
static void popup(const QString &text)
virtual bool readBuffer(MusicSongItemList &items) overridefinal
void playedIndexBy(int row)
#define TTK_TIME_INIT
Definition: ttkglobal.h:225
TTK_MODULE_EXPORT QString getSaveFileName(QWidget *parent, const QString &filter="Image Files (*.png *.bmp *.jpg)")
MusicPlayItem currentItem() const
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
QList< int > TTKIntList
Definition: ttkqtglobal.h:204
#define qAsConst
Definition: ttkqtglobal.h:51
bool isEmpty() const
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:193
PlayMode
Definition: musicobject.h:173
int currentIndex() const
void importSongsByFiles(int index=TTK_LOW_LEVEL)
bool isMuted() const
Definition: musicplayer.cpp:76
void setupUi(Ui::MusicApplication *ui)
MusicPlaylist * m_playlist
void durationChanged(qint64 duration)
void setVolumeValue(int value) const
#define TTK_NORMAL_LEVEL
Definition: ttkglobal.h:259
void currentPlaylist(QStringList &list)
void importSongsByPath(const QStringList &files, int playlistRow)
void setPlaybackMode(TTK::PlayMode mode)
#define TTK_SEPARATOR
Definition: ttkglobal.h:196
TTK_MODULE_EXPORT QString lrcDirPrefix()
int backgroundTransparent() const
void playIndexClicked(int row, int column)
void updateCurrentTime(qint64 pos)
virtual void mouseReleaseEvent(QMouseEvent *event) override
#define KRC_FILE
Definition: musicobject.h:66
QString currentFilePath() const
#define TTK_VERSION_TIME_STR
Definition: ttkversion.h:176
MusicLeftAreaWidget * m_leftAreaWidget
#define TTK_SLOT
Definition: ttkqtglobal.h:181
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 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
The class of the app bottom area widget.
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:135
bool backgroundTransparentEnabled() const
bool checkMusicListCurrentIndex() const
void setVolumeValue(int value) const
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
bool isPlaying() const
virtual void closeEvent(QCloseEvent *event) overridefinal
#define WINDOW_WIDTH_MIN
Definition: musicobject.h:155
static constexpr const char * BtnLove
void readSongItems(const QStringList &paths, MusicSongItemList &items)
#define TTK_STR_CAT(...)
Definition: ttkglobal.h:167
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
void setShuffleMode(bool shuffle)
The class of the music song info.
Definition: musicsong.h:28
void removeLoveItemAt(const QString &path, bool current)
virtual void resizeEvent(QResizeEvent *event) overridefinal
void appendSongItemList(const MusicSongItemList &items)
bool isValid() const
Definition: musicplaylist.h:45
void setBackgroundAnimation(bool state)
void playerStateChanged(TTK::PlayState state)
void showMessage(const QString &title, const QString &text)
The class of the music play list.
Definition: musicplaylist.h:63
The class of the input widget.
#define MUSIC_NORMAL_LIST
#define LRC_FILE
Definition: musicobject.h:65
static QString supportPlaylistInputFormats()
void setSongTimeSpeed(qint64 time) const
void setupUi(Ui::MusicApplication *ui)
TTK_MODULE_EXPORT void adjustMenuPosition(QMenu *menu)
void setSongLoveState(bool state)
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
bool isPlaying() const
Definition: musicplayer.cpp:35
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:156
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