TTKMusicPlayer  3.7.0.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
musicsongscontainerwidget.cpp
Go to the documentation of this file.
5 #include "musicmessagebox.h"
6 #include "musicconnectionpool.h"
7 #include "musicprogresswidget.h"
11 #include "musicapplication.h"
12 #include "musictoastlabel.h"
13 #include "musicfileutils.h"
14 #include "musicformats.h"
15 
16 #include <QMimeData>
17 
18 static constexpr int ITEM_MIN_COUNT = MIN_ITEM_COUNT;
19 static constexpr int ITEM_MAX_COUNT = 10;
20 static constexpr int RECENT_ITEM_MAX_COUNT = 50;
21 
23  : MusicSongsToolBoxWidget(parent),
25  m_playRowIndex(MUSIC_NORMAL_LIST),
26  m_lastSearchIndex(MUSIC_NORMAL_LIST),
27  m_selectDeleteIndex(MUSIC_NONE_LIST),
28  m_listFunctionWidget(nullptr),
29  m_songSearchWidget(nullptr)
30 {
31  setAcceptDrops(true);
32 
35 
36  connect(m_listMaskWidget, SIGNAL(itemIndexChanged(int)), SLOT(itemIndexChanged(int)));
37  connect(m_scrollArea->verticalScrollBar(), SIGNAL(valueChanged(int)), SLOT(sliderValueChanaged(int)));
38 
39  G_CONNECTION_PTR->setValue(className(), this);
40  G_CONNECTION_PTR->connect(MusicQueryTableWidget::className(), className());
41 }
42 
44 {
45  G_CONNECTION_PTR->removeValue(this);
46  delete m_listMaskWidget;
47  delete m_listFunctionWidget;
48  delete m_songSearchWidget;
49 
50  while(!m_containerItems.isEmpty())
51  {
52  delete m_containerItems.takeLast().m_itemWidget;
53  }
54 }
55 
56 bool MusicSongsContainerWidget::addMusicItemList(const MusicSongItemList &items)
57 {
58  TTKIntSet inDeed;
60  for(const MusicSongItem &item : qAsConst(items))
61  {
62  inDeed.remove(item.m_itemIndex);
63  }
64  //
65  if(!inDeed.isEmpty())
66  {
67  //if less than four count(0, 1, 2, 3), find and add default items
69  for(const int item : qAsConst(inDeed))
70  {
71  MusicSongItem songItem;
72  switch(item)
73  {
74  case MUSIC_NORMAL_LIST:
75  {
76  songItem.m_itemIndex = item;
77  songItem.m_itemName = tr("Default Item");
78  break;
79  }
80  case MUSIC_LOVEST_LIST:
81  {
82  songItem.m_itemIndex = item;
83  songItem.m_itemName = tr("Lovest Item");
84  break;
85  }
86  case MUSIC_NETWORK_LIST:
87  {
88  songItem.m_itemIndex = item;
89  songItem.m_itemName = tr("Net Item");
90  break;
91  }
92  case MUSIC_RECENT_LIST:
93  {
94  songItem.m_itemIndex = item;
95  songItem.m_itemName = tr("Recent Item");
96  break;
97  }
98  default: break;
99  }
100  m_containerItems << songItem;
101  }
102  std::sort(m_containerItems.begin(), m_containerItems.end());
103  }
104  else
105  {
107  }
108 
109  for(int i = 0; i < m_containerItems.count(); ++i)
110  {
112  }
113 
114  return inDeed.isEmpty();
115 }
116 
117 void MusicSongsContainerWidget::appendMusicItemList(const MusicSongItemList &items)
118 {
119  for(int i = 0; i < items.count(); ++i)
120  {
121  m_containerItems << items[i];
122  MusicSongItem *item = &m_containerItems.back();
123  item->m_itemIndex = ++m_itemIndexRaise;
125  createWidgetItem(item);
126  }
127 }
128 
129 void MusicSongsContainerWidget::importMusicSongsByUrl(const QString &path, int playlistRow)
130 {
131  if(path.isEmpty())
132  {
133  return;
134  }
135 
136  if(playlistRow < 0)
137  {
138  playlistRow = makeValidIndex();
139  }
140 
141  const QFileInfo fin(path);
142  if(fin.isDir())
143  {
144  QStringList files;
145  for(const QFileInfo &fin : TTK::File::fileInfoListByPath(path))
146  {
148  {
149  files << fin.absoluteFilePath();
150  }
151  }
152 
153  importMusicSongsByPath(files, playlistRow);
154  }
155  else if(TTK::String::isNetworkUrl(path))
156  {
158 
160  const QString &prefix = TTK::String::splitToken(path, TTK_SEPARATOR, "?");
161  const QByteArray &md5 = TTK::Algorithm::md5(path.toUtf8());
162  const MusicSong song(path + "#" + md5 + "." + TTK::String::splitToken(path), TTK_DEFAULT_STR, TTK::String::pefix(prefix));
163 
164  if(item->m_songs.contains(song))
165  {
166  return;
167  }
168 
169  item->m_songs << song;
170  item->m_itemWidget->updateSongsList(item->m_songs);
171  setItemTitle(item);
172  }
173  else
174  {
175  QStringList files;
177  {
178  files << fin.absoluteFilePath();
179  }
180 
181  importMusicSongsByPath(files, playlistRow);
182  }
183 }
184 
185 void MusicSongsContainerWidget::importMusicSongsByPath(const QStringList &files, int playlistRow)
186 {
187  if(files.isEmpty())
188  {
189  return;
190  }
191 
192  if(playlistRow < 0)
193  {
194  playlistRow = makeValidIndex();
195  }
196 
198 
199  MusicProgressWidget progress;
200  progress.setTitle(tr("Import file mode"));
201  progress.setRange(0, files.count());
202  progress.show();
203 
204  MusicSongItem *item = &m_containerItems[playlistRow];
205 
206  int i = 0;
207  for(const QString &path : qAsConst(files))
208  {
209  if(item->m_songs.contains(MusicSong(path)))
210  {
211  continue;
212  }
213 
214  progress.setValue(++i);
215  item->m_songs << TTK::generateSongList(path);
216  }
217 
218  if(i != 0)
219  {
220  item->m_itemWidget->updateSongsList(item->m_songs);
221  setItemTitle(item);
222  setCurrentIndex(playlistRow);
223 
224  MusicToastLabel::popup(tr("Import music songs done"));
225  }
226 }
227 
229 {
230  QStringList list;
231 
232  if(index < 0 || index >= m_containerItems.count())
233  {
234  return list;
235  }
236 
237  for(const MusicSong &song : qAsConst(m_containerItems[index].m_songs))
238  {
239  list << song.name();
240  }
241  return list;
242 }
243 
245 {
246  QStringList list;
247  if(index < 0 || index >= m_containerItems.count())
248  {
249  return list;
250  }
251 
252  for(const MusicSong &song : qAsConst(m_containerItems[index].m_songs))
253  {
254  list << song.path();
255  }
256  return list;
257 }
258 
259 int MusicSongsContainerWidget::mapSongIndexByFilePath(int playlistRow, const QString &path) const
260 {
261  if(playlistRow < 0 || playlistRow >= m_containerItems.count() || path.isEmpty())
262  {
263  return -1;
264  }
265 
266  const MusicSongList *songs = &m_containerItems[playlistRow].m_songs;
267  for(int i = 0; i < songs->count(); ++i)
268  {
269  if(MusicSong(path) == songs->at(i))
270  {
271  return i;
272  }
273  }
274  return -1;
275 }
276 
277 QString MusicSongsContainerWidget::mapFilePathBySongIndex(int playlistRow, int index) const
278 {
279  if(playlistRow < 0 || playlistRow >= m_containerItems.count())
280  {
281  return {};
282  }
283 
284  const MusicSongList *songs = &m_containerItems[playlistRow].m_songs;
285  if(index < 0 || index >= songs->count())
286  {
287  return {};
288  }
289 
290  return songs->at(index).path();
291 }
292 
294 {
296  {
297  return;
298  }
299 
300  const TTKIntList &result = m_searchResultItems.value(m_searchResultLevel);
301  if(row >= result.count() || row < 0)
302  {
303  row = -1;
304  return;
305  }
306 
307  row = result[row];
308 
311 }
312 
314 {
315  const int before = m_playRowIndex;
316  m_playRowIndex = index;
317 
318  if(before >= 0)
319  {
321  if(widget && !m_containerItems[before].m_songs.isEmpty())
322  {
323  widget->adjustPlayWidgetRow();
324  }
325  }
326 }
327 
329 {
330  if(!hasSearchResult())
331  {
332  selectRow(index);
333  resizeScrollIndex(index * 30);
334  }
335 }
336 
338 {
340  if(m_playRowIndex < 0)
341  {
342  return;
343  }
344 
346  m_containerItems[m_playRowIndex].m_itemWidget->selectRow(index);
347 }
348 
349 void MusicSongsContainerWidget::updateDurationLabel(const QString &current, const QString &total) const
350 {
351  if(m_playRowIndex < 0)
352  {
353  return;
354  }
355  TTKObjectCast(MusicSongsListPlayTableWidget*, m_containerItems[m_playRowIndex].m_itemWidget)->updateDurationLabel(current, total);
356 }
357 
359 {
360  if(m_containerItems.count() <= ITEM_MAX_COUNT)
361  {
362  QString name = tr("Default Item");
363  checkCurrentNameExist(name);
364  addNewRowItem(name);
365  }
366 }
367 
369 {
370  const int id = foundMappedIndex(index);
371  if(id == -1)
372  {
373  return;
374  }
375 
376  MusicMessageBox message;
377  message.setText(tr("Are you sure to delete?"));
378  if(!message.exec())
379  {
380  return;
381  }
382 
383  const MusicSongItem *item = &m_containerItems[id];
385 
386  if(m_playRowIndex == id)
387  {
389  m_itemList.front().m_widgetItem->setExpand(false);
391  }
392  else if(m_playRowIndex > id)
393  {
395  }
396 
397  m_containerItems.takeAt(id);
398  removeItem(item->m_itemWidget);
399  delete item->m_itemWidget;
400 
401  updatePlayedList(id, -1);
402 }
403 
405 {
406  MusicMessageBox message;
407  message.setText(tr("Are you sure to delete?"));
408  if(!message.exec())
409  {
410  return;
411  }
412 
414  {
416  m_itemList.front().m_widgetItem->setExpand(false);
418  }
419 
420  for(int i = m_containerItems.count() - 1; i > 3; --i)
421  {
422  MusicSongItem item = m_containerItems.takeLast();
423  removeItem(item.m_itemWidget);
424  delete item.m_itemWidget;
425  }
426 }
427 
429 {
430  const int id = foundMappedIndex(index);
431  if(id == -1)
432  {
433  return;
434  }
435 
437 
438  m_selectDeleteIndex = id;
439  //
441  if(widget->rowCount() > 0)
442  {
443  widget->setCurrentCell(0, 1);
444  widget->clearItems();
445  }
446  //
448 
449  if(m_containerItems[id].m_songs.isEmpty() && m_playRowIndex == id)
450  {
452  }
453 }
454 
455 void MusicSongsContainerWidget::changRowItemName(int index, const QString &name)
456 {
457  const int id = foundMappedIndex(index);
458  if(id == -1)
459  {
460  return;
461  }
462 
463  MusicSongItem *item = &m_containerItems[id];
464  item->m_itemName = name;
465  setItemTitle(item);
466 }
467 
469 {
470  start = foundMappedIndex(start);
471  end = foundMappedIndex(end);
472  if(start == end)
473  {
474  return;
475  }
476 
477  //adjust the m_playRowIndex while the item has dragged and dropped
478  if(start < end)
479  {
480  if((start < m_playRowIndex && m_playRowIndex < end) || m_playRowIndex == end)
481  {
483  }
484  else if(m_playRowIndex == start)
485  {
487  }
488  }
489  else
490  {
491  if((end < m_playRowIndex && m_playRowIndex < start) || m_playRowIndex == end)
492  {
494  }
495  else if(m_playRowIndex == start)
496  {
498  }
499  }
500 
501  swapItem(start, end);
502  const MusicSongItem &item = m_containerItems.takeAt(start);
503  m_containerItems.insert(end, item);
504 
505  updatePlayedList(start, end);
506 }
507 
509 {
510  const int id = foundMappedIndex(index);
511  if(id == -1)
512  {
513  return;
514  }
515 
516  const MusicSongItem *item = &m_containerItems[id];
518 }
519 
521 {
522  const int id = foundMappedIndex(index);
523  if(id == -1)
524  {
525  return;
526  }
527 
528  const MusicSongItem *item = &m_containerItems[id];
530 }
531 
533 {
534  if(index == TTK_LOW_LEVEL)
535  {
536  index = m_currentIndex;
537  }
538  else
539  {
540  const int id = foundMappedIndex(index);
541  if(id == -1)
542  {
543  return;
544  }
545 
546  index = id;
547  }
548 
550 }
551 
553 {
554  if(index == TTK_LOW_LEVEL)
555  {
556  index = m_currentIndex;
557  }
558  else
559  {
560  const int id = foundMappedIndex(index);
561  if(id == -1)
562  {
563  return;
564  }
565 
566  index = id;
567  }
568 
570 }
571 
573 {
575 }
576 
578 {
580 }
581 
583 {
584  if(m_currentIndex == -1)
585  {
586  return;
587  }
588 
589  if(!isSearchPlayIndex())
590  {
591  const QStringList searchedSongs(musicSongsFileName(m_lastSearchIndex));
592  TTKIntList result;
593  for(int i = 0; i < searchedSongs.count(); ++i)
594  {
595  result << i;
596  }
597 
599  TTKObjectCast(MusicSongsListPlayTableWidget*, item->m_itemWidget)->updateSearchFileName(&item->m_songs, result);
600 
601  if(item->m_songs.isEmpty())
602  {
603  item->m_itemWidget->updateSongsList(item->m_songs);
604  }
605 
608  }
609 
610  const QString &text = m_songSearchWidget->text();
611  const QStringList searchedSongs(musicSongsFileName(m_currentIndex));
612 
613  TTKIntList result;
614  for(int i = 0; i < searchedSongs.count(); ++i)
615  {
616  if(searchedSongs[i].contains(text, Qt::CaseInsensitive))
617  {
618  result << i;
619  }
620  }
621 
622  m_searchResultLevel = column;
623  m_searchResultItems.insert(column, result);
624 
626  TTKObjectCast(MusicSongsListPlayTableWidget*, item->m_itemWidget)->updateSearchFileName(&item->m_songs, result);
627 
628  if(column == 0)
629  {
630  if(item->m_songs.isEmpty())
631  {
632  item->m_itemWidget->updateSongsList(item->m_songs);
633  }
634 
636  }
637 }
638 
640 {
641  const QStringList &lastPlayIndex = G_SETTING_PTR->value(MusicSettingManager::LastPlayIndex).toStringList();
642  if(lastPlayIndex.count() != 3)
643  {
644  return;
645  }
646 
647  m_playRowIndex = lastPlayIndex[1].toInt();
648  const int index = lastPlayIndex[2].toInt();
649  setCurrentIndex(index);
650  setMusicPlayCount(index);
651 
653 }
654 
656 {
657  if(m_playRowIndex < 0 || m_playRowIndex >= m_containerItems.count())
658  {
659  return;
660  }
661 
662  const MusicSong &song = m_containerItems[m_playRowIndex].m_songs[row];
664 
666  if(state)
667  {
668  item->m_songs << song;
669  widget->updateSongsList(item->m_songs);
670  setItemTitle(item);
671  }
672  else
673  {
674  if(item->m_songs.removeOne(song))
675  {
676  widget->removeItems();
677  widget->updateSongsList(item->m_songs);
678  setItemTitle(item);
680  }
681  }
682 }
683 
685 {
686  if(m_currentIndex < 0 || m_currentIndex >= m_containerItems.count() || hasSearchResult())
687  {
688  return;
689  }
690 
691  const MusicSong &song = m_containerItems[m_currentIndex].m_songs[row];
693 
695  if(MusicSong(MusicApplication::instance()->currentFilePath()) == song)
696  {
698  return;
699  }
700 
702  if(state)
703  {
704  item->m_songs << song;
705  widget->updateSongsList(item->m_songs);
706  setItemTitle(item);
707  }
708  else
709  {
710  if(item->m_songs.removeOne(song))
711  {
712  widget->removeItems();
713  widget->updateSongsList(item->m_songs);
714  setItemTitle(item);
716  }
717  }
718 }
719 
721 {
723  const QByteArray &md5 = TTK::Algorithm::md5(item.m_id.toUtf8());
724  MusicSong song(item.m_nickName + "#" + md5 + "." + item.m_description, item.m_updateTime, item.m_name);
725  song.setFormat(item.m_description);
726  song.setSizeStr(item.m_count);
727 
728  int index = songItem->m_songs.indexOf(song);
729  if(index == -1)
730  {
731  songItem->m_songs << song;
732  songItem->m_itemWidget->updateSongsList(songItem->m_songs);
733  setItemTitle(songItem);
734  index = songItem->m_songs.count() - 1;
735  }
736 
737  if(item.m_category == MUSIC_PLAY_NOW)
738  {
742  }
743 }
744 
745 void MusicSongsContainerWidget::addSongToPlaylist(const QStringList &items)
746 {
747  if(items.isEmpty())
748  {
749  MusicToastLabel::popup(tr("Import music songs is empty"));
750  return;
751  }
752 
753  QStringList files(items);
754  const int row = makeValidIndex();
755  importMusicSongsByPath(files, row);
756 
757  const MusicSongItem *item = &m_containerItems[row];
758  const MusicSongList *musicSongs = &item->m_songs;
759  const MusicSong &song = MusicSong(items.back());
760 
761  int index = musicSongs->count() - 1;
762  if(musicSongs->contains(song))
763  {
764  index = musicSongs->indexOf(song);
765  }
766 
768  setCurrentIndex(row);
770 }
771 
772 void MusicSongsContainerWidget::removeItemAt(const TTKIntList &index, bool fileRemove)
773 {
774  if(index.isEmpty() || hasSearchResult())
775  {
776  return;
777  }
778 
781  QStringList deleteFiles;
782  for(int i = index.count() - 1; i >= 0; --i)
783  {
784  const MusicSong &song = item->m_songs.takeAt(index[i]);
785  deleteFiles << song.path();
786  if(currentIndex != m_playRowIndex && currentIndex == MUSIC_LOVEST_LIST)
787  {
788  const int playIndex = m_containerItems[m_playRowIndex].m_itemWidget->playRowIndex();
789  const MusicSongList &songs = m_containerItems[m_playRowIndex].m_songs;
790  if(playIndex > -1 && playIndex < songs.count())
791  {
792  if(songs[playIndex] == song)
793  {
795  }
796  }
797  }
798 
799  if(fileRemove)
800  {
801  QFile::remove(currentIndex == MUSIC_NETWORK_LIST ? TTK::generateNetworkSongPath(song.path()) : song.path());
802  }
803  }
804 
805  MusicApplication::instance()->removeItemAt(deleteFiles, fileRemove, currentIndex == m_playRowIndex, currentIndex);
806 
807  setItemTitle(item);
808  //create upload file widget if current items is all been deleted
809  TTKObjectCast(MusicSongsListPlayTableWidget*, item->m_itemWidget)->createUploadFileModule();
810 }
811 
812 void MusicSongsContainerWidget::itemIndexSwaped(int start, int end, int play, MusicSongList &songs)
813 {
814  MusicSongList *names = &m_containerItems[m_currentIndex].m_songs;
815  if(start > end)
816  {
817  for(int i = start; i > end; --i)
818  {
819  QtContainerSwap(names, i, i - 1);
820  }
821  }
822  else
823  {
824  for(int i = start; i < end; ++i)
825  {
826  QtContainerSwap(names, i, i + 1);
827  }
828  }
829 
830  songs = *names;
831 
833  {
835  }
836 }
837 
839 {
841  state = (currentIndex == m_playRowIndex);
842 }
843 
845 {
846  empty = !hasSearchResult();
847 }
848 
850 {
851  if(index < 0 || m_playRowIndex < 0)
852  {
853  return;
854  }
855 
856  MusicSongList &songs = m_containerItems[m_playRowIndex].m_songs;
857  if(!songs.isEmpty() && index < songs.count())
858  {
859  MusicSong &song = songs[index];
860  song.setPlayCount(song.playCount() + 1);
861  }
862 }
863 
865 {
867  {
868  return;
869  }
870 
871  MusicSongList *songs = &m_containerItems[m_playRowIndex].m_songs;
872  if(songs->isEmpty() || index >= songs->count())
873  {
874  return;
875  }
876 
878  MusicSong recentSong(songs->at(index));
879  MusicSongList *recentSongs = &item->m_songs;
881  if(!recentSongs->contains(recentSong))
882  {
883  if(recentSongs->count() >= RECENT_ITEM_MAX_COUNT)
884  {
885  recentSongs->takeFirst();
886  widget->removeItems();
887  }
888 
889  recentSong.setPlayCount(recentSong.playCount() + 1);
890  recentSongs->append(recentSong);
891  widget->updateSongsList(*recentSongs);
892 
893  const QString title(QString("%1[%2]").arg(item->m_itemName).arg(recentSongs->count()));
894  setTitle(widget, title);
895  }
896  else
897  {
898  for(MusicSong &song : *recentSongs)
899  {
900  if(recentSong == song)
901  {
902  song.setPlayCount(song.playCount() + 1);
903  break;
904  }
905  }
906  }
907 }
908 
909 void MusicSongsContainerWidget::queryMusicItemList(MusicSongItemList &songs)
910 {
911  songs = m_containerItems;
912 }
913 
915 {
916  if(m_playRowIndex < 0)
917  {
918  return;
919  }
920 
921  TTKObjectCast(MusicSongsListPlayTableWidget*, m_containerItems[m_playRowIndex].m_itemWidget)->updateCurrentArtist();
922 }
923 
925 {
926  if(m_listFunctionWidget == nullptr)
927  {
929  connect(m_listFunctionWidget, SIGNAL(deleteObject()), SLOT(deleteFloatWidget()));
930  resizeWindow();
931  m_listFunctionWidget->show();
932  }
933  else
934  {
935  resizeWindow();
937  }
938 }
939 
941 {
942  const int id = foundMappedIndex(index);
943  if(id == -1)
944  {
945  return;
946  }
947 
949 
952  index = m_containerItems[id].m_sort.m_type;
953  if(index != -1)
954  {
955  sort = TTKStaticCast(MusicSong::Sort, index);
956  }
957 
958  MusicSongList *songs = &m_containerItems[id].m_songs;
959  const MusicSong song(MusicApplication::instance()->currentFilePath());
960 
961  for(int i = 0; i < songs->count(); ++i)
962  {
963  (*songs)[i].setSort(sort);
964  }
965 
966  if(m_containerItems[id].m_sort.m_order == Qt::DescendingOrder)
967  {
968  std::sort(songs->begin(), songs->end());
969  }
970  else
971  {
972  std::sort(songs->begin(), songs->end(), std::greater<MusicSong>());
973  }
974 
975  widget->removeItems();
976  widget->setSongsList(songs);
977 
978  index = songs->indexOf(song);
980  {
982  }
983 }
984 
986 {
987  if(m_songSearchWidget == nullptr)
988  {
990  resizeWindow();
991  }
992 
994 }
995 
997 {
998  if(value >= 40 * (m_currentIndex + 1) && m_currentIndex > -1 && m_currentIndex < m_containerItems.count())
999  {
1003  m_listMaskWidget->setTitle(QString("%1[%2]").arg(item->m_itemName).arg(item->m_songs.count()));
1004  m_listMaskWidget->setExpand(true);
1005  m_listMaskWidget->raise();
1006  m_listMaskWidget->show();
1007  }
1008  else
1009  {
1010  m_listMaskWidget->hide();
1011  }
1012 }
1013 
1015 {
1016  delete m_listFunctionWidget;
1017  m_listFunctionWidget = nullptr;
1018 }
1019 
1021 {
1022  MusicSongsToolBoxWidget::resizeEvent(event);
1023  resizeWindow();
1024 }
1025 
1026 void MusicSongsContainerWidget::dragEnterEvent(QDragEnterEvent *event)
1027 {
1028  MusicSongsToolBoxWidget::dragEnterEvent(event);
1029  event->setDropAction(Qt::IgnoreAction);
1030  event->accept();
1031 }
1032 
1033 void MusicSongsContainerWidget::dragMoveEvent(QDragMoveEvent *event)
1034 {
1035  MusicSongsToolBoxWidget::dragMoveEvent(event);
1036 
1037  bool contains = false;
1038  for(const MusicToolBoxWidgetItem &item : qAsConst(m_itemList))
1039  {
1040  if(!TTK::playlistRowValid(item.m_itemIndex))
1041  {
1042  continue;
1043  }
1044 
1045  QWidget *container = item.m_widgetItem->item();
1046  if(item.m_widgetItem->isActive() || (container && container->isVisible()))
1047  {
1048  contains = true;
1049  }
1050  }
1051 
1052  event->setDropAction(contains ? Qt::CopyAction : Qt::IgnoreAction);
1053  event->accept();
1054 }
1055 
1057 {
1058  MusicSongsToolBoxWidget::dropEvent(event);
1059 
1060  for(const MusicToolBoxWidgetItem &item : qAsConst(m_itemList))
1061  {
1062  if(!TTK::playlistRowValid(item.m_itemIndex))
1063  {
1064  continue;
1065  }
1066 
1067  QWidget *container = item.m_widgetItem->item();
1068  if(item.m_widgetItem->isActive() || (container && container->isVisible()))
1069  {
1070  QStringList files;
1071  const QMimeData *data = event->mimeData();
1072 
1073  for(const QUrl &url : data->urls())
1074  {
1075  files << url.toLocalFile();
1076  }
1077 
1078  importMusicSongsByPath(files, foundMappedIndex(item.m_itemIndex));
1079  break;
1080  }
1081  }
1082 }
1083 
1084 void MusicSongsContainerWidget::contextMenuEvent(QContextMenuEvent *event)
1085 {
1086  MusicSongsToolBoxWidget::contextMenuEvent(event);
1087 
1088  QMenu menu(this);
1089  menu.setStyleSheet(TTK::UI::MenuStyle02);
1090  menu.addAction(tr("Create Item"), this, SLOT(addNewRowItem()));
1091  menu.addAction(tr("Import Item"), MusicApplication::instance(), SLOT(importSongsItemList()));
1092  menu.addAction(tr("Music Test Tools"), this, SLOT(showSongCheckToolsWidget()));
1093  menu.addAction(tr("Lrc Batch Download"), this, SLOT(showLrcDownloadBatchWidget()));
1094  menu.addAction(tr("Delete All"), this, SLOT(deleteRowItems()))->setEnabled(m_containerItems.count() > ITEM_MIN_COUNT);
1095 
1097  menu.exec(QCursor::pos());
1098 }
1099 
1101 {
1102  if(m_songSearchWidget)
1103  {
1105  }
1106 }
1107 
1109 {
1110  if(hasSearchResult())
1111  {
1113  }
1114 }
1115 
1117 {
1118  QString check = name;
1119  for(int i = 1; i <= ITEM_MAX_COUNT; ++i)
1120  {
1121  bool hasName = false;
1122  for(const MusicSongItem &songItem : qAsConst(m_containerItems))
1123  {
1124  if(check == songItem.m_itemName)
1125  {
1126  hasName = true;
1127  check = name + QString::number(i);
1128  break;
1129  }
1130  }
1131 
1132  if(!hasName)
1133  {
1134  name = check;
1135  break;
1136  }
1137  }
1138 }
1139 
1141 {
1142  MusicSongItem item;
1143  item.m_itemName = name;
1144  m_containerItems << item;
1146 }
1147 
1149 {
1151  widget->setMovedScrollBar(m_scrollArea->verticalScrollBar());
1152  widget->setSongSort(&item->m_sort);
1153 
1154  item->m_itemWidget = widget;
1155  item->m_itemIndex = m_itemIndexRaise;
1156 
1157  addCellItem(widget, item->m_itemName);
1158  setSongSort(widget, &item->m_sort);
1160 
1161  connect(widget, SIGNAL(isCurrentPlaylistRow(bool&)), SLOT(isCurrentPlaylistRow(bool&)));
1162  connect(widget, SIGNAL(isSearchedResultEmpty(bool&)), SLOT(isSearchedResultEmpty(bool&)));
1163  connect(widget, SIGNAL(deleteItemAt(TTKIntList,bool)), SLOT(removeItemAt(TTKIntList,bool)));
1164  connect(widget, SIGNAL(itemIndexSwaped(int,int,int,MusicSongList&)), SLOT(itemIndexSwaped(int,int,int,MusicSongList&)));
1165  connect(widget, SIGNAL(addSongToLovestList(bool,int)), SLOT(addSongToLovestList(bool,int)));
1166  connect(widget, SIGNAL(showFloatWidget()), SLOT(showFloatWidget()));
1167  connect(widget, SIGNAL(songListSortBy(int)), SLOT(songListSortBy(int)));
1168 
1170  setInputModule(m_itemList.back().m_widgetItem);
1171 
1172  widget->setSongsList(&item->m_songs);
1173  setTitle(widget, QString("%1[%2]").arg(item->m_itemName).arg(item->m_songs.count()));
1174 }
1175 
1177 {
1178  const QString title(QString("%1[%2]").arg(item->m_itemName).arg(item->m_songs.count()));
1179  setTitle(item->m_itemWidget, title);
1180 
1181  if(m_listMaskWidget->isVisible() && m_listMaskWidget->index() == item->m_itemIndex)
1182  {
1183  m_listMaskWidget->setTitle(title);
1184  }
1185 }
1186 
1188 {
1189  connect(object, SIGNAL(addNewRowItem()), SLOT(addNewRowItem()));
1190  connect(object, SIGNAL(deleteRowItemAll(int)), SLOT(deleteRowItemAll(int)));
1191  connect(object, SIGNAL(deleteRowItem(int)), SLOT(deleteRowItem(int)));
1192  connect(object, SIGNAL(changRowItemName(int,QString)), SLOT(changRowItemName(int,QString)));
1193  connect(object, SIGNAL(addNewFiles(int)), SLOT(importSongsByFiles(int)));
1194  connect(object, SIGNAL(addNewDir(int)), SLOT(importSongsByDir(int)));
1195  connect(object, SIGNAL(songListSortBy(int)), SLOT(songListSortBy(int)));
1196  connect(object, SIGNAL(swapDragItemIndex(int,int)), SLOT(swapDragItemIndex(int,int)));
1197  connect(object, SIGNAL(addToPlayLater(int)), SLOT(addToPlayLater(int)));
1198  connect(object, SIGNAL(addToPlayedList(int)), SLOT(addToPlayedList(int)));
1199 }
1200 
1202 {
1204  {
1205  m_listFunctionWidget->move(width() - m_listFunctionWidget->width() - 15, height() - 40 - m_listFunctionWidget->height());
1206  }
1207 
1208  if(m_songSearchWidget)
1209  {
1210  m_songSearchWidget->move(0, height() - m_songSearchWidget->height());
1211  }
1212 }
1213 
1215 {
1216  for(const MusicSongItem &item : qAsConst(m_containerItems))
1217  {
1218  const int index = foundMappedIndex(item.m_itemIndex);
1219  item.m_itemWidget->setPlaylistRow(index);
1220  }
1221 
1222  TTK::IndexPropertyList items;
1223  if(end == -1)
1224  {
1225  for(int i = begin + 1; i < m_containerItems.count(); ++i)
1226  {
1227  items << TTK::IndexProperty(i + 1, i);
1228  }
1229  }
1230  else
1231  {
1232  items << TTK::IndexProperty(begin, end);
1233 
1234  if(begin > end)
1235  {
1236  for(int i = begin; i < end; ++i)
1237  {
1238  items << TTK::IndexProperty(i + 1, i);
1239  }
1240  }
1241  else
1242  {
1243  for(int i = end; i > begin; --i)
1244  {
1245  items << TTK::IndexProperty(i, i - 1);
1246  }
1247  }
1248  }
1249 
1251 }
1252 
const MusicSongItemList & items() const
void setTitle(QWidget *item, const QString &text)
#define TTKStaticCast(x, y)
Definition: ttkglobal.h:159
void importSongsByDir(int index=TTK_LOW_LEVEL)
TTK_MODULE_EXPORT QByteArray md5(const QByteArray &data)
void queryMusicItemList(MusicSongItemList &songs)
The class of the search result data item.
void updateDurationLabel(const QString &current, const QString &total) const
bool addMusicItemList(const MusicSongItemList &items)
static MusicApplication * instance()
virtual void setVisible(bool visible) overridefinal
virtual void dragEnterEvent(QDragEnterEvent *event) overridefinal
void setText(const QString &text) const
void importMusicSongsByUrl(const QString &path, int playlistRow)
TTK_MODULE_EXPORT bool playlistRowValid(int index)
Definition: musicsong.cpp:95
virtual void contextMenuEvent(QContextMenuEvent *event) overridefinal
#define TTK_DEFAULT_STR
Definition: ttkglobal.h:200
#define QtContainerSwap(p, i, j)
Container swap.
Definition: ttkqtcompat.h:52
#define TTK_LOW_LEVEL
Definition: ttkglobal.h:253
The class of the show progress widget.
void addSongToLovestList(bool state=true)
QString path() const noexcept
Definition: musicsong.h:90
void songToLovestListAt(bool state, int row)
void importSongsByFiles(int index=TTK_LOW_LEVEL)
#define MUSIC_NONE_LIST
void updatePlayedList(const TTK::IndexPropertyList &indexs)
void playIndexBy(int row)
void playSortBy(int row)
QStringList musicSongsFileName(int index) const
static constexpr int RECENT_ITEM_MAX_COUNT
The class of the messagebox widget.
#define MUSIC_RECENT_LIST
void updatePlayedList(int start, int end)
The class of the lrc batch download widget.
MusicSongSearchDialog * m_songSearchWidget
#define TTKGenerateSingleWidget(...)
static MusicPlayedListPopWidget * instance()
#define G_CONNECTION_PTR
QStringList musicSongsFilePath(int index) const
void removeItemAt(const QStringList &path, bool remove, bool current, int playlistRow)
void setSongSort(QWidget *item, MusicSongSort *sort)
void importSongsByDir(int index=TTK_LOW_LEVEL)
The class of the index property.
Definition: musicobject.h:204
void setMovedScrollBar(QScrollBar *bar=nullptr)
int mapSongIndexByFilePath(int playlistRow, const QString &path) const
void swapDragItemIndex(int start, int end)
void setTitle(const QString &name)
The class of the tool box mask widget.
static void popup(const QString &text)
The class of the song check tools widget.
The class of the tool box widget item.
void addSongToPlaylist(const QStringList &items)
TTK_MODULE_EXPORT QString pefix(const QString &name)
void importMusicSongsByPath(const QStringList &files, int playlistRow)
TTK_MODULE_EXPORT QString generateNetworkSongPath(const QString &path)
Definition: musicsong.cpp:182
virtual void updateSongsList(const MusicSongList &songs) overridefinal
#define MUSIC_PLAY_NOW
static constexpr int ITEM_MAX_COUNT
The class of the songs list function widget.
QList< int > TTKIntList
Definition: ttkqtglobal.h:188
#define qAsConst
Definition: ttkqtglobal.h:53
const char * name
Definition: http_parser.c:458
void setInputModule(QObject *object) const
void appendMusicItemList(const MusicSongItemList &items)
void removeItemAt(const TTKIntList &del, bool fileRemove)
virtual void setSongsList(MusicSongList *songs)
void importSongsByFiles(int index=TTK_LOW_LEVEL)
MusicSongsToolBoxMaskWidget * m_listMaskWidget
MusicAbstractSongsListTableWidget * m_itemWidget
Definition: musicsong.h:167
void addSongToLovestList(bool state, int row)
void addCellItem(QWidget *item, const QString &text)
#define TTK_NORMAL_LEVEL
Definition: ttkglobal.h:254
static QStringList supportMusicFormats()
#define TTK_SEPARATOR
Definition: ttkglobal.h:195
void changRowItemName(int index, const QString &name)
QSet< int > TTKIntSet
Definition: ttkqtglobal.h:187
void playIndexClicked(int row, int column)
MusicSongsContainerWidget(QWidget *parent=nullptr)
TTK_MODULE_EXPORT QFileInfoList fileInfoListByPath(const QString &dpath, const QStringList &filter={}, bool recursively=true)
virtual void updateSongsList(const MusicSongList &songs)
MusicToolBoxWidgetItemList m_itemList
void addSongBufferToPlaylist(const MusicResultDataItem &item)
void setItemTitle(MusicSongItem *item)
TTK_MODULE_EXPORT QString splitToken(const QString &name)
virtual void dropEvent(QDropEvent *event) overridefinal
static const QString MenuStyle02
void append(const MusicSongList &songs)
virtual void resizeEvent(QResizeEvent *event) overridefinal
The class of the tool box widget.
The class of the music song item.
Definition: musicsong.h:161
void itemIndexSwaped(int start, int end, int play, MusicSongList &songs)
MusicSongList m_songs
Definition: musicsong.h:166
#define MUSIC_NETWORK_LIST
#define MUSIC_LOVEST_LIST
void setSongSort(MusicSongSort *sort)
void setPlayCount(const int c) noexcept
Definition: musicsong.h:114
#define MIN_ITEM_COUNT
void insert(int playlistRow, const MusicSong &song)
QString m_itemName
Definition: musicsong.h:164
MusicSongsListFunctionWidget * m_listFunctionWidget
#define TTK_FILE_SUFFIX(fin)
Definition: ttkqtglobal.h:173
The class of the music song info.
Definition: musicsong.h:28
The class of the song search widget.
void removeLoveItemAt(const QString &path, bool current)
MusicSongSort m_sort
Definition: musicsong.h:165
#define MUSIC_NORMAL_LIST
int playCount() const noexcept
Definition: musicsong.h:118
TTK_MODULE_EXPORT void adjustMenuPosition(QMenu *menu)
virtual void dragMoveEvent(QDragMoveEvent *event) overridefinal
QString mapFilePathBySongIndex(int playlistRow, int index) const
void searchResultChanged(int row, int column)
static constexpr int ITEM_MIN_COUNT
void createWidgetItem(MusicSongItem *item)
state
Definition: http_parser.c:279
The class of the songs list play table widget.
TTK_MODULE_EXPORT bool isNetworkUrl(const QString &path)
#define G_SETTING_PTR
TTK_MODULE_EXPORT MusicSongList generateSongList(const QString &path)
Definition: musicsong.cpp:139
#define TTKObjectCast(x, y)
Definition: ttkqtglobal.h:60