MythTV  master
playlisteditorview.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include <cstdlib>
3 
4 // qt
5 #include <QKeyEvent>
6 
7 // myth
8 #include <mythcontext.h>
9 #include <mythdbcon.h>
10 #include <mythmainwindow.h>
11 #include <mythuibuttontree.h>
12 #include <mythuitext.h>
13 #include <mythuiutils.h>
14 #include <mythdialogbox.h>
15 #include <mythdirs.h>
16 #include <musicutils.h>
17 
18 // mythmusic
19 #include "musicdata.h"
20 #include "playlistcontainer.h"
21 #include "musiccommon.h"
22 #include "playlisteditorview.h"
23 #include "smartplaylist.h"
24 #include "mainvisual.h"
25 
27  const QString &name, const QString &action,
29  bool showArrow)
30  : MythGenericTree(name)
31 {
32  m_check = check;
33  m_action = action;
34  m_showArrow = showArrow;
35 
36  if (!action.isEmpty() && !action.isNull())
37  setSelectable(true);
38 
39  if (parent)
40  {
41  parent->addNode(this);
42  parent->setDrawArrow(true);
43  }
44 }
45 
47 {
48  m_showArrow = flag;
49  if (m_buttonItem)
50  m_buttonItem->setDrawArrow(true);
51 }
52 
54 {
55  m_check = state;
56  if (m_buttonItem)
57  {
59  m_buttonItem->setChecked(m_check);
60  }
61 }
62 
64 {
65  auto *item = new MusicButtonItem(list, GetText());
66  item->SetData(QVariant::fromValue((MythGenericTree*) this));
67 
68  if (visibleChildCount() > 0)
69  item->setDrawArrow(true);
70 
71  if (m_showArrow)
72  item->setDrawArrow(true);
73 
74  item->setCheckable(m_check != MythUIButtonListItem::CantCheck);
75  item->setChecked(m_check);
76 
77  m_buttonItem = item;
78 
79  return item;
80 }
81 
83 
84 #define LOC QString("PlaylistEditorView: ")
85 #define LOC_WARN QString("PlaylistEditorView, Warning: ")
86 #define LOC_ERR QString("PlaylistEditorView, Error: ")
87 
89  const QString &layout, bool restorePosition)
90  :MusicCommon(parent, parentScreen, "playlisteditorview"),
91  m_layout(layout), m_restorePosition(restorePosition)
92 {
94  gCoreContext->SaveSetting("MusicPlaylistEditorView", layout);
95 }
96 
98 {
100 
102 
103  for (int x = 0; x < m_deleteList.count(); x++)
104  delete m_deleteList.at(x);
105  m_deleteList.clear();
106 
107  delete m_rootNode;
108 }
109 
111 {
112  bool err = false;
113 
114  QString windowName;
115 
116  if (m_layout == "gallery")
117  {
118  windowName = "playlisteditorview_gallery";
120  }
121  else
122  {
123  windowName = "playlisteditorview_tree";
125  }
126 
127  // Load the theme for this screen
128  err = LoadWindowFromXML("music-ui.xml", windowName, this);
129 
130  if (!err)
131  {
132  gPlayer->removeListener(this);
133  return false;
134  }
135 
136  // find common widgets available on any view
137  err = CreateCommon();
138 
139  // find widgets specific to this view
140  UIUtilE::Assign(this, m_playlistTree , "playlist_tree", &err);
141  UIUtilW::Assign(this, m_breadcrumbsText, "breadcrumbs", &err);
142  UIUtilW::Assign(this, m_positionText, "position", &err);
143 
144  if (err)
145  {
146  LOG(VB_GENERAL, LOG_ERR, QString("Cannot load screen '%1'").arg(windowName));
147  gPlayer->removeListener(this);
148  return false;
149  }
150 
151  createRootNode();
152 
154 
156 
157  if (m_restorePosition)
158  {
159  QStringList route = gCoreContext->GetSetting("MusicTreeLastActive", "").split("\n");
160  restoreTreePosition(route);
161  }
162 
163  connect(m_playlistTree, SIGNAL(itemClicked(MythUIButtonListItem*)),
164  this, SLOT(treeItemClicked(MythUIButtonListItem*)));
165  connect(m_playlistTree, SIGNAL(nodeChanged(MythGenericTree*)),
166  this, SLOT(treeNodeChanged(MythGenericTree*)));
167 
169  connect(m_playlistTree, SIGNAL(itemVisible(MythUIButtonListItem*)),
170  this, SLOT(treeItemVisible(MythUIButtonListItem*)));
171 
172  BuildFocusList();
173 
174  return true;
175 }
176 
178 {
179  if ((event->type() == MusicPlayerEvent::MetadataChangedEvent) ||
180  (event->type() == MusicPlayerEvent::AlbumArtChangedEvent))
181  { // NOLINT(bugprone-branch-clone)
182  // TODO: this could be more efficient
183  reloadTree();
184  }
185  else if ((event->type() == MusicPlayerEvent::TrackRemovedEvent) ||
186  (event->type() == MusicPlayerEvent::TrackAddedEvent) ||
187  (event->type() == MusicPlayerEvent::AllTracksRemovedEvent))
188  {
190  }
191  else if (event->type() == MusicPlayerEvent::PlaylistChangedEvent)
192  {
193  //TODO should just update the relevent playlist here
194  reloadTree();
195  }
196  else if (event->type() == MusicPlayerEvent::CDChangedEvent)
197  {
198  //TODO should just update the cd node
199  reloadTree();
200  }
201  else if (event->type() == MythEvent::MythEventMessage)
202  {
203  auto *me = dynamic_cast<MythEvent*>(event);
204  if (!me)
205  return;
206 
207  if (me->Message().startsWith("MUSIC_RESYNC_FINISHED"))
208  {
209  QStringList list = me->Message().simplified().split(' ');
210  if (list.size() == 4)
211  {
212  int added = list[1].toInt();
213  int removed = list[2].toInt();
214  int changed = list[3].toInt();
215 
216  // if something changed reload the tree
217  if (added || removed || changed)
218  reloadTree();
219  }
220  }
221  }
222  else if (event->type() == DialogCompletionEvent::kEventType)
223  {
224  auto *dce = dynamic_cast<DialogCompletionEvent*>(event);
225 
226  // make sure the user didn't ESCAPE out of the menu
227  if ((dce == nullptr) || (dce->GetResult() < 0))
228  return;
229 
230  QString resultid = dce->GetId();
231  QString resulttext = dce->GetResultText();
232 
233  if (resultid == "smartplaylistmenu")
234  {
236  return;
237 
239  if (!node)
240  return;
241 
242  auto *mnode = dynamic_cast<MusicGenericTree*>(node);
243  if (!mnode)
244  return;
245 
246  if (resulttext == tr("New Smart Playlist"))
247  {
248  QString category;
249  if (mnode->getAction() == "smartplaylistcategory")
250  category = mnode->GetText();
251 
253  auto* editor = new SmartPlaylistEditor(mainStack);
254 
255  if (!editor->Create())
256  {
257  delete editor;
258  return;
259  }
260 
261  editor->newSmartPlaylist(category);
262 
263  connect(editor, SIGNAL(smartPLChanged(const QString&, const QString&)),
264  this, SLOT(smartPLChanged(QString, QString)));
265 
266  mainStack->AddScreen(editor);
267  }
268  else if (resulttext == tr("Remove Smart Playlist"))
269  {
270  QString category = mnode->getParent()->GetText();
271  QString name = mnode->GetText();
272 
273  ShowOkPopup(tr("Are you sure you want to delete this Smart Playlist?\n"
274  "Category: %1 - Name: %2").arg(category).arg(name),
275  this, SLOT(deleteSmartPlaylist(bool)), true);
276  }
277  else if (resulttext == tr("Edit Smart Playlist"))
278  {
279  QString category = mnode->getParent()->GetText();
280  QString name = mnode->GetText();
281 
283  auto* editor = new SmartPlaylistEditor(mainStack);
284 
285  if (!editor->Create())
286  {
287  delete editor;
288  return;
289  }
290 
291  editor->editSmartPlaylist(category, name);
292 
293  connect(editor, SIGNAL(smartPLChanged(const QString&, const QString&)),
294  this, SLOT(smartPLChanged(QString, QString)));
295 
296  mainStack->AddScreen(editor);
297  }
298  else if (resulttext == tr("Replace Tracks"))
299  {
303  }
304  else if (resulttext == tr("Add Tracks"))
305  {
309  }
310  }
311  else if (resultid == "treeplaylistmenu")
312  {
314  return;
315 
317  if (!node)
318  return;
319 
320  auto *mnode = dynamic_cast<MusicGenericTree*>(node);
321  if (!mnode)
322  return;
323 
324  if (resulttext == tr("Remove Playlist"))
325  {
326  QString name = mnode->GetText();
327 
328  ShowOkPopup(tr("Are you sure you want to delete this Playlist?\n"
329  "Name: %1").arg(name),
330  this, SLOT(deletePlaylist(bool)), true);
331  }
332  else if (resulttext == tr("Replace Tracks"))
333  {
337  }
338  else if (resulttext == tr("Add Tracks"))
339  {
342  }
343  }
344  }
345 
347 }
348 
349 bool PlaylistEditorView::keyPressEvent(QKeyEvent *event)
350 {
351  // if there is a pending jump point pass the key press to the default handler
352  if (GetMythMainWindow()->IsExitingToMain())
353  {
354  // Just call the parent handler. It will properly clean up.
355  return MusicCommon::keyPressEvent(event);
356  }
357 
359  return true;
360 
361  QStringList actions;
362  bool handled = GetMythMainWindow()->TranslateKeyPress("Music", event, actions);
363 
364  for (int i = 0; i < actions.size() && !handled; i++)
365  {
366  QString action = actions[i];
367  handled = true;
368 
369  if ((action == "EDIT" || action == "INFO") && GetFocusWidget() == m_playlistTree)
370  {
371  handled = false;
372 
374  if (node)
375  {
376  auto *mnode = dynamic_cast<MusicGenericTree*>(node);
377  if (mnode)
378  {
379  if (mnode->getAction() == "smartplaylist" && action == "EDIT")
380  {
381  QString category = mnode->getParent()->GetText();
382  QString name = mnode->GetText();
383 
385  auto* editor = new SmartPlaylistEditor(mainStack);
386 
387  if (!editor->Create())
388  {
389  delete editor;
390  return true;
391  }
392 
393  editor->editSmartPlaylist(category, name);
394  connect(editor, SIGNAL(smartPLChanged(const QString&, const QString&)),
395  this, SLOT(smartPLChanged(QString, QString)));
396 
397  mainStack->AddScreen(editor);
398 
399  handled = true;
400  }
401  else if (mnode->getAction() == "smartplaylistcategory" && action == "EDIT")
402  {
403  QString category = mnode->GetText();
404 
406  auto* editor = new SmartPlaylistEditor(mainStack);
407 
408  if (!editor->Create())
409  {
410  delete editor;
411  return true;
412  }
413 
414  editor->newSmartPlaylist(category);
415 
416  connect(editor, SIGNAL(smartPLChanged(const QString&, const QString&)),
417  this, SLOT(smartPLChanged(QString, QString)));
418 
419  mainStack->AddScreen(editor);
420 
421  handled = true;
422  }
423  else if (mnode->getAction() == "trackid")
424  {
425  MusicMetadata *mdata = gMusicData->m_all_music->getMetadata(mnode->getInt());
426  if (mdata)
427  {
428  if (action == "INFO")
429  showTrackInfo(mdata);
430  else
431  editTrackInfo(mdata);
432  }
433 
434  handled = true;
435  }
436  }
437  }
438  }
439  else if (action == "DELETE" && GetFocusWidget() == m_playlistTree)
440  {
441  handled = false;
442 
444  if (node)
445  {
446  auto *mnode = dynamic_cast<MusicGenericTree*>(node);
447  if (mnode)
448  {
449  if (mnode->getAction() == "smartplaylist")
450  {
451  QString category = mnode->getParent()->GetText();
452  QString name = mnode->GetText();
453 
454  ShowOkPopup(tr("Are you sure you want to delete this Smart Playlist?\n"
455  "Category: %1 - Name: %2").arg(category).arg(name),
456  this, SLOT(deleteSmartPlaylist(bool)), true);
457  handled = true;
458  }
459  else if (mnode->getAction() == "playlist")
460  {
461  QString name = mnode->GetText();
462 
463  ShowOkPopup(tr("Are you sure you want to delete this Playlist?\n"
464  "Name: %1").arg(name),
465  this, SLOT(deletePlaylist(bool)), true);
466  handled = true;
467  }
468  }
469  }
470  }
471  else if (action == "MARK")
472  {
474  if (item)
475  treeItemClicked(item);
476  }
477  else if ((action == "PLAY") && (GetFocusWidget() == m_playlistTree))
478  {
480  if (item)
481  {
482  auto *node = item->GetData().value<MythGenericTree*>();
483  auto *mnode = dynamic_cast<MusicGenericTree*>(node);
484 
485  if (mnode)
486  {
487  updateSonglist(mnode);
488 
489  if (m_songList.count() > 0)
490  {
493 
494  stopVisualizer();
495 
497 
498  if (m_mainvisual)
499  {
500  m_mainvisual->mutex()->lock();
502  m_mainvisual->mutex()->unlock();
503  }
504  }
505  else
506  {
507  handled = false;
508  }
509  }
510  }
511  }
512  else
513  handled = false;
514  }
515 
516  if (!handled && MusicCommon::keyPressEvent(event))
517  handled = true;
518 
519  return handled;
520 }
521 
523 {
524  m_songList.clear();
525 
526  if (node->getAction() == "playlists" ||
527  node->getAction() == "smartplaylists" ||
528  node->getAction() == "smartplaylistcategory")
529  { // NOLINT(bugprone-branch-clone)
530  }
531  else if (node->getAction() == "trackid" || node->getAction() == "cdtrack")
532  {
533  m_songList.append(node->getInt());
534  }
535  else if (node->getAction() == "all tracks" ||
536  node->getAction() == "albums" ||
537  node->getAction() == "compartists" ||
538  node->getAction() == "artists" ||
539  node->getAction() == "genres" ||
540  node->getAction() == "ratings" ||
541  node->getAction() == "years")
542  {
543  // get the list of tracks from the previous 'All Tracks' node
544  auto *allTracksNode = dynamic_cast<MusicGenericTree*>(node->getParent()->getChildAt(0));
545  if (allTracksNode)
546  {
547  for (int x = 0; x < allTracksNode->childCount(); x++)
548  {
549  MythGenericTree *trackNode = allTracksNode->getChildAt(x);
550  if (trackNode)
551  m_songList.append(trackNode->getInt());
552  }
553  }
554  }
555  else if (node->getAction() == "album" ||
556  node->getAction() == "artist" ||
557  node->getAction() == "genre" ||
558  node->getAction() == "rating" ||
559  node->getAction() == "year" ||
560  node->getAction() == "compilations" ||
561  node->getAction() == "compartist")
562  {
563  // get the list of tracks from the 'All Tracks' node
564  auto *allTracksNode = dynamic_cast<MusicGenericTree*>(node->getChildAt(0));
565  if (allTracksNode)
566  {
567  if (allTracksNode->childCount() == 0)
568  filterTracks(allTracksNode);
569 
570  for (int x = 0; x < allTracksNode->childCount(); x++)
571  {
572  MythGenericTree *trackNode = allTracksNode->getChildAt(x);
573  if (trackNode)
574  m_songList.append(trackNode->getInt());
575  }
576  }
577  }
578  else if (node->getAction() == "smartplaylist")
579  {
580  // add the selected smart playlist's tracks to the song list
581  QList<MythGenericTree*> *children = node->getAllChildren();
582  for (int x = 0; x < children->count(); x++)
583  {
584  MythGenericTree *childnode = children->at(x);
585  m_songList.append(childnode->getInt());
586  }
587  }
588  else if (node->getAction() == "playlist")
589  {
590  // get list of tracks to add from the playlist
591  int playlistID = node->getInt();
592  Playlist *playlist = gMusicData->m_all_playlists->getPlaylist(playlistID);
593 
594  if (playlist)
595  {
596  for (int x = 0; x < playlist->getTrackCount(); x++)
597  {
598  MusicMetadata *mdata = playlist->getSongAt(x);
599  if (mdata)
600  m_songList.append((int) mdata->ID());
601  }
602  }
603  }
604  else if (node->getAction() == "error")
605  {
606  // a smart playlist has returned no tracks etc.
607  }
608  else
609  {
610  // fall back to getting the tracks from the MetadataPtrList
611  auto *tracks = node->GetData().value<MetadataPtrList*>();
612  for (int x = 0; x < tracks->count(); x++)
613  {
614  MusicMetadata *mdata = tracks->at(x);
615  if (mdata)
616  m_songList.append((int)mdata->ID());
617  }
618  }
619 }
620 
622 {
624  {
627 
628  MythMenu *menu = nullptr;
629  auto *mnode = dynamic_cast<MusicGenericTree*>(m_playlistTree->GetCurrentNode());
630 
631  if (mnode)
632  {
633  if (mnode->getAction() == "smartplaylists" ||
634  mnode->getAction() == "smartplaylistcategory" ||
635  mnode->getAction() == "smartplaylist")
636  {
638  }
639  else if (mnode->getAction() == "playlists" ||
640  mnode->getAction() == "playlist")
641  {
643  }
644  else if ((mnode->getAction() == "trackid") ||
645  (mnode->getAction() == "error"))
646  {
647  }
648  else
649  {
651  }
652 
653  updateSonglist(mnode);
654  }
655 
656  if (menu)
657  {
658  menu->AddItem(tr("More Options"), nullptr, createMainMenu());
659 
660  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
661 
662  auto *menuPopup = new MythDialogBox(menu, popupStack, "actionmenu");
663 
664  if (menuPopup->Create())
665  popupStack->AddScreen(menuPopup);
666  else
667  delete menu;
668 
669  return;
670  }
671  }
672 
674 }
675 
677 {
678  MythMenu *menu = nullptr;
679 
681  {
682  auto *mnode = dynamic_cast<MusicGenericTree*>(m_playlistTree->GetCurrentNode());
683 
684  if (!mnode)
685  return nullptr;
686 
687  if (mnode->getAction() == "playlist")
688  {
689  menu = new MythMenu(tr("Playlist Actions"), this, "treeplaylistmenu");
690  menu->AddItem(tr("Replace Tracks"));
691  menu->AddItem(tr("Add Tracks"));
692  menu->AddItem(tr("Remove Playlist"));
693  }
694  }
695 
696  return menu;
697 }
698 
700 {
701  MythMenu *menu = nullptr;
702 
704  {
705  auto *mnode = dynamic_cast<MusicGenericTree*>(m_playlistTree->GetCurrentNode());
706 
707  if (!mnode)
708  return nullptr;
709 
710  if (mnode->getAction() == "smartplaylists" || mnode->getAction() == "smartplaylistcategory")
711  {
712  QString label = tr("Smart Playlist Actions");
713 
714  menu = new MythMenu(label, this, "smartplaylistmenu");
715 
716  menu->AddItem(tr("New Smart Playlist"));
717  }
718  else if (mnode->getAction() == "smartplaylist")
719  {
720  menu = new MythMenu(tr("Smart Playlist Actions"), this, "smartplaylistmenu");
721 
722  menu->AddItem(tr("Replace Tracks"));
723  menu->AddItem(tr("Add Tracks"));
724 
725  menu->AddItem(tr("Edit Smart Playlist"));
726  menu->AddItem(tr("New Smart Playlist"));
727  menu->AddItem(tr("Remove Smart Playlist"));
728  }
729  }
730 
731  return menu;
732 }
733 
735 {
736  if (!m_rootNode)
737  m_rootNode = new MusicGenericTree(nullptr, "Root Music Node");
738 
739  auto *node = new MusicGenericTree(m_rootNode, tr("All Tracks"), "all tracks");
740  node->setDrawArrow(true);
741  node->SetData(QVariant::fromValue(gMusicData->m_all_music->getAllMetadata()));
742 
743  node = new MusicGenericTree(m_rootNode, tr("Albums"), "albums");
744  node->setDrawArrow(true);
745  node->SetData(QVariant::fromValue(gMusicData->m_all_music->getAllMetadata()));
746 
747  node = new MusicGenericTree(m_rootNode, tr("Artists"), "artists");
748  node->setDrawArrow(true);
749  node->SetData(QVariant::fromValue(gMusicData->m_all_music->getAllMetadata()));
750 
751  node = new MusicGenericTree(m_rootNode, tr("Genres"), "genres");
752  node->setDrawArrow(true);
753  node->SetData(QVariant::fromValue(gMusicData->m_all_music->getAllMetadata()));
754 #if 0
755  node = new MusicGenericTree(m_rootNode, tr("Tags"), "tags");
756  node->setDrawArrow(true);
757  node->SetData(QVariant::fromValue(gMusicData->all_music->getAllMetadata()));
758 #endif
759  node = new MusicGenericTree(m_rootNode, tr("Ratings"), "ratings");
760  node->setDrawArrow(true);
761  node->SetData(QVariant::fromValue(gMusicData->m_all_music->getAllMetadata()));
762 
763  node = new MusicGenericTree(m_rootNode, tr("Years"), "years");
764  node->setDrawArrow(true);
765  node->SetData(QVariant::fromValue(gMusicData->m_all_music->getAllMetadata()));
766 
767  node = new MusicGenericTree(m_rootNode, tr("Compilations"), "compilations");
768  node->setDrawArrow(true);
769 
771  auto *compTracks = new MetadataPtrList;
772  m_deleteList.append(compTracks);
773 
774  for (int x = 0; x < alltracks->count(); x++)
775  {
776  MusicMetadata *mdata = alltracks->at(x);
777  if (mdata)
778  {
779  if (mdata->Compilation())
780  compTracks->append(mdata);
781  }
782  }
783  node->SetData(QVariant::fromValue(compTracks));
784 
786  {
787  node = new MusicGenericTree(m_rootNode, tr("CD - %1").arg(gMusicData->m_all_music->getCDTitle()), "cd");
788  node->setDrawArrow(true);
789  node->SetData(QVariant::fromValue(gMusicData->m_all_music->getAllCDMetadata()));
790  }
791 
792  node = new MusicGenericTree(m_rootNode, tr("Directory"), "directory");
793  node->setDrawArrow(true);
794  node->SetData(QVariant::fromValue(gMusicData->m_all_music->getAllMetadata()));
795 
796  node = new MusicGenericTree(m_rootNode, tr("Playlists"), "playlists");
797  node->setDrawArrow(true);
798 
799  node = new MusicGenericTree(m_rootNode, tr("Smart Playlists"), "smartplaylists");
800  node->setDrawArrow(true);
801 }
802 
804 {
805  auto *node = item->GetData().value<MythGenericTree*>();
806  auto *mnode = dynamic_cast<MusicGenericTree*>(node);
807 
808  if (!mnode || !gPlayer->getCurrentPlaylist() || mnode->getAction() == "error")
809  return;
810 
811  if (mnode->getAction() == "trackid")
812  {
813  if (gPlayer->getCurrentPlaylist()->checkTrack(mnode->getInt()))
814  {
815  // remove track from the current playlist
816  gPlayer->removeTrack(mnode->getInt());
817  mnode->setCheck(MythUIButtonListItem::NotChecked);
818  }
819  else
820  {
821  // add track to the current playlist
822  gPlayer->addTrack(mnode->getInt(), true);
823  mnode->setCheck(MythUIButtonListItem::FullChecked);
824  }
825  }
826  else
827  ShowMenu();
828 }
829 
830 
832 {
833  auto *node = item->GetData().value<MythGenericTree*>();;
834  auto *mnode = dynamic_cast<MusicGenericTree*>(node);
835 
836  if (!mnode)
837  return;
838 
839  if (item->GetText("*").isEmpty())
840  {
841  item->SetText(" ", "*");
842 
843  QString artFile;
844 
845  if (mnode->getAction() == "trackid")
846  {
847  MusicMetadata *mdata = gMusicData->m_all_music->getMetadata(mnode->getInt());
848  if (mdata)
849  artFile = mdata->getAlbumArtFile();
850  }
851  else if (mnode->getAction() == "album")
852  {
853  // hunt for a coverart image for the album
854  auto *tracks = node->GetData().value<MetadataPtrList*>();
855  for (int x = 0; x < tracks->count(); x++)
856  {
857  MusicMetadata *mdata = tracks->at(x);
858  if (mdata)
859  {
860  artFile = mdata->getAlbumArtFile();
861  if (!artFile.isEmpty())
862  break;
863  }
864  }
865  }
866  else if (mnode->getAction() == "compartist")
867  {
868  artFile = findIcon("artist", mnode->GetText().toLower());
869  }
870  else if (mnode->getAction() == "all tracks" || mnode->getAction() == "genres" ||
871  mnode->getAction() == "albums" || mnode->getAction() == "artists" ||
872  mnode->getAction() == "compartists"|| mnode->getAction() == "ratings" ||
873  mnode->getAction() == "years" || mnode->getAction() == "compilations" ||
874  mnode->getAction() == "cd" || mnode->getAction() == "directory" ||
875  mnode->getAction() == "playlists" || mnode->getAction() == "smartplaylists")
876  {
877  artFile = "blank.png";
878  }
879  else
880  {
881  artFile = findIcon(mnode->getAction(), mnode->GetText().toLower());
882  }
883 
884  QString state = "default";
885 
886  if (mnode->getAction() == "all tracks")
887  state = "alltracks";
888  else if (mnode->getAction() == "genres")
889  state = "genres";
890  else if (mnode->getAction() == "albums")
891  state = "albums";
892  else if (mnode->getAction() == "artists")
893  state = "artists";
894  else if (mnode->getAction() == "compartists")
895  state = "compartists";
896  else if (mnode->getAction() == "ratings")
897  state = "ratings";
898  else if (mnode->getAction() == "years")
899  state = "years";
900  else if (mnode->getAction() == "compilations")
901  state = "compilations";
902  else if (mnode->getAction() == "cd")
903  state = "cd";
904  else if (mnode->getAction() == "directory")
905  state = "directory";
906  else if (mnode->getAction() == "playlists")
907  state = "playlists";
908  else if (mnode->getAction() == "smartplaylists")
909  state = "smartplaylists";
910 
911  item->DisplayState(state, "nodetype");
912 
913  if (artFile.isEmpty())
914  item->SetImage("");
915  else
916  item->SetImage(artFile);
917  }
918 }
919 
921 {
922  auto *mnode = dynamic_cast<MusicGenericTree*>(node);
923  if (!mnode)
924  return;
925 
926  if (m_breadcrumbsText)
927  {
928  QString route = node->getRouteByString().join(" -> ");
929  route = route.remove("Root Music Node -> ");
930  m_breadcrumbsText->SetText(route);
931  }
932 
933  if (m_positionText)
934  {
935  m_positionText->SetText(tr("%1 of %2").arg(node->getPosition() + 1)
936  .arg(node->siblingCount()));
937  }
938 
939  if (mnode->childCount() > 0 || mnode->getAction() == "trackid")
940  return;
941 
942  if (mnode->getAction() == "smartplaylists")
943  {
945  }
946  else if (mnode->getAction() == "smartplaylistcategory")
947  {
948  getSmartPlaylists(mnode);
949  }
950  else if (mnode->getAction() == "smartplaylist")
951  {
952  getSmartPlaylistTracks(mnode, mnode->getInt());
953  }
954  else if (mnode->getAction() == "playlists")
955  {
956  getPlaylists(mnode);
957  }
958  else if (mnode->getAction() == "playlist")
959  {
960  getPlaylistTracks(mnode, mnode->getInt());
961  }
962  else if (mnode->getAction() == "cd")
963  {
964  getCDTracks(mnode);
965  }
966  else
967  filterTracks(mnode);
968 }
969 
971 {
972  auto *tracks = node->GetData().value<MetadataPtrList*>();
973 
974  if (!tracks)
975  return;
976 
977  if (node->getAction() == "all tracks")
978  {
979  QMap<QString, int> map;
980  QStringList list;
981  bool isAlbum = false;
982  auto *parentNode = dynamic_cast<MusicGenericTree*>(node->getParent());
983 
984  if (parentNode)
985  isAlbum = parentNode->getAction() == "album";
986 
987  for (int x = 0; x < tracks->count(); x++)
988  {
989  MusicMetadata *mdata = tracks->at(x);
990  if (mdata)
991  {
992  QString key = mdata->Title();
993 
994  // Add the track number if an album is selected
995  if (isAlbum && mdata->Track() > 0)
996  {
997  key.prepend(QString::number(mdata->Track()) + " - ");
998  if (mdata->Track() < 10)
999  key.prepend("0");
1000 
1001  // Add the disc number if this is a multi-disc album
1002  if (mdata->DiscNumber() > 0)
1003  {
1004  key.prepend(QString::number(mdata->DiscNumber()) + "/");
1005  if (mdata->DiscNumber() < 10)
1006  key.prepend("0");
1007  }
1008  }
1009  map.insertMulti(key, mdata->ID());
1010  }
1011  }
1012 
1013  QMap<QString, int>::const_iterator i = map.constBegin();
1014  while (i != map.constEnd())
1015  {
1016  auto *newnode = new MusicGenericTree(node, i.key(), "trackid");
1017  newnode->setInt(i.value());
1018  newnode->setDrawArrow(false);
1019  bool hasTrack = gPlayer->getCurrentPlaylist() ? gPlayer->getCurrentPlaylist()->checkTrack(newnode->getInt()) : false;
1021  ++i;
1022  }
1023 
1024  node->sortByString(); // Case-insensitive sort
1025  }
1026  else if (node->getAction() == "artists")
1027  {
1028  QMap<QString, MetadataPtrList*> map;
1029 
1030  for (int x = 0; x < tracks->count(); x++)
1031  {
1032  MusicMetadata *mdata = tracks->at(x);
1033  if (mdata)
1034  {
1035  if (map.contains(mdata->Artist()))
1036  {
1037  MetadataPtrList *filteredTracks = map.value(mdata->Artist());
1038  filteredTracks->append(mdata);
1039  }
1040  else
1041  {
1042  auto *filteredTracks = new MetadataPtrList;
1043  m_deleteList.append(filteredTracks);
1044  filteredTracks->append(mdata);
1045  map.insert(mdata->Artist(), filteredTracks);
1046  }
1047  }
1048  }
1049 
1050  QMap<QString, MetadataPtrList*>::const_iterator i = map.constBegin();
1051  while (i != map.constEnd())
1052  {
1053  auto *newnode = new MusicGenericTree(node, i.key(), "artist");
1054  newnode->SetData(QVariant::fromValue(i.value()));
1055  ++i;
1056  }
1057 
1058  node->sortByString(); // Case-insensitive sort
1059  }
1060  else if (node->getAction() == "compartists")
1061  {
1062  QMap<QString, MetadataPtrList*> map;
1063 
1064  for (int x = 0; x < tracks->count(); x++)
1065  {
1066  MusicMetadata *mdata = tracks->at(x);
1067  if (mdata)
1068  {
1069  if (mdata->CompilationArtist() != mdata->Artist())
1070  {
1071  if (map.contains(mdata->CompilationArtist()))
1072  {
1073  MetadataPtrList *filteredTracks = map.value(mdata->CompilationArtist());
1074  filteredTracks->append(mdata);
1075  }
1076  else
1077  {
1078  auto *filteredTracks = new MetadataPtrList;
1079  m_deleteList.append(filteredTracks);
1080  filteredTracks->append(mdata);
1081  map.insert(mdata->CompilationArtist(), filteredTracks);
1082  }
1083  }
1084  }
1085  }
1086 
1087  QMap<QString, MetadataPtrList*>::const_iterator i = map.constBegin();
1088  while (i != map.constEnd())
1089  {
1090  auto *newnode = new MusicGenericTree(node, i.key(), "compartist");
1091  newnode->SetData(QVariant::fromValue(i.value()));
1092  ++i;
1093  }
1094 
1095  node->sortByString(); // Case-insensitive sort
1096  }
1097  else if (node->getAction() == "albums")
1098  {
1099  QMap<QString, MetadataPtrList*> map;
1100 
1101  for (int x = 0; x < tracks->count(); x++)
1102  {
1103  MusicMetadata *mdata = tracks->at(x);
1104  if (mdata)
1105  {
1106  if (map.contains(mdata->Album()))
1107  {
1108  MetadataPtrList *filteredTracks = map.value(mdata->Album());
1109  filteredTracks->append(mdata);
1110  }
1111  else
1112  {
1113  auto *filteredTracks = new MetadataPtrList;
1114  m_deleteList.append(filteredTracks);
1115  filteredTracks->append(mdata);
1116  map.insert(mdata->Album(), filteredTracks);
1117  }
1118  }
1119  }
1120 
1121  QMap<QString, MetadataPtrList*>::const_iterator i = map.constBegin();
1122  while (i != map.constEnd())
1123  {
1124  auto *newnode = new MusicGenericTree(node, i.key(), "album");
1125  newnode->SetData(QVariant::fromValue(i.value()));
1126  ++i;
1127  }
1128 
1129  node->sortByString(); // Case-insensitive sort
1130  }
1131  else if (node->getAction() == "genres")
1132  {
1133  QMap<QString, MetadataPtrList*> map;
1134 
1135  for (int x = 0; x < tracks->count(); x++)
1136  {
1137  MusicMetadata *mdata = tracks->at(x);
1138  if (mdata)
1139  {
1140  if (map.contains(mdata->Genre()))
1141  {
1142  MetadataPtrList *filteredTracks = map.value(mdata->Genre());
1143  filteredTracks->append(mdata);
1144  }
1145  else
1146  {
1147  auto *filteredTracks = new MetadataPtrList;
1148  m_deleteList.append(filteredTracks);
1149  filteredTracks->append(mdata);
1150  map.insert(mdata->Genre(), filteredTracks);
1151  }
1152  }
1153  }
1154 
1155  QMap<QString, MetadataPtrList*>::const_iterator i = map.constBegin();
1156  while (i != map.constEnd())
1157  {
1158  auto *newnode = new MusicGenericTree(node, i.key(), "genre");
1159  newnode->SetSortText(i.key()); // No manipulation of prefixes on genres
1160  newnode->SetData(QVariant::fromValue(i.value()));
1161  ++i;
1162  }
1163 
1164  node->sortByString(); // Case-insensitive sort
1165  }
1166  else if (node->getAction() == "ratings")
1167  {
1168  QMap<QString, MetadataPtrList*> map;
1169 
1170  for (int x = 0; x < tracks->count(); x++)
1171  {
1172  MusicMetadata *mdata = tracks->at(x);
1173  if (mdata)
1174  {
1175  QString ratingStr = tr("%n Star(s)", "", mdata->Rating());
1176  if (map.contains(ratingStr))
1177  {
1178  MetadataPtrList *filteredTracks = map.value(ratingStr);
1179  filteredTracks->append(mdata);
1180  }
1181  else
1182  {
1183  auto *filteredTracks = new MetadataPtrList;
1184  m_deleteList.append(filteredTracks);
1185  filteredTracks->append(mdata);
1186  map.insert(ratingStr, filteredTracks);
1187  }
1188  }
1189  }
1190 
1191  QMap<QString, MetadataPtrList*>::const_iterator i = map.constBegin();
1192  while (i != map.constEnd())
1193  {
1194  auto *newnode = new MusicGenericTree(node, i.key(), "rating");
1195  newnode->SetData(QVariant::fromValue(i.value()));
1196  ++i;
1197  }
1198  }
1199  else if (node->getAction() == "years")
1200  {
1201  QMap<QString, MetadataPtrList*> map;
1202 
1203  for (int x = 0; x < tracks->count(); x++)
1204  {
1205  MusicMetadata *mdata = tracks->at(x);
1206  if (mdata)
1207  {
1208  QString yearStr = QString("%1").arg(mdata->Year());
1209  if (map.contains(yearStr))
1210  {
1211  MetadataPtrList *filteredTracks = map.value(yearStr);
1212  filteredTracks->append(mdata);
1213  }
1214  else
1215  {
1216  auto *filteredTracks = new MetadataPtrList;
1217  m_deleteList.append(filteredTracks);
1218  filteredTracks->append(mdata);
1219  map.insert(yearStr, filteredTracks);
1220  }
1221  }
1222  }
1223 
1224  QMap<QString, MetadataPtrList*>::const_iterator i = map.constBegin();
1225  while (i != map.constEnd())
1226  {
1227  auto *newnode = new MusicGenericTree(node, i.key(), "year");
1228  newnode->SetData(QVariant::fromValue(i.value()));
1229  ++i;
1230  }
1231  }
1232  else if (node->getAction() == "directory")
1233  {
1234  QMap<QString, MetadataPtrList*> map;
1235 
1236  // which directories have we already filtered by
1237  QString dir;
1238  MusicGenericTree *climber = node;
1239  while (climber)
1240  {
1241  dir = climber->GetText() + '/' + dir;
1242  climber = dynamic_cast<MusicGenericTree *>(climber->getParent());
1243  }
1244 
1245  // remove the top two nodes
1246  QString top2 = "Root Music Node/" + tr("Directory") + '/';
1247  if (dir.startsWith(top2))
1248  dir = dir.mid(top2.length());
1249 
1250  for (int x = 0; x < tracks->count(); x++)
1251  {
1252  MusicMetadata *mdata = tracks->at(x);
1253  if (mdata)
1254  {
1255  QString filename = mdata->Filename(false);
1256 
1257  if (filename.startsWith(dir))
1258  filename = filename.mid(dir.length());
1259 
1260  QStringList dirs = filename.split("/");
1261 
1262  QString key = dirs.count() > 1 ? dirs[0] : "[TRACK]" + dirs[0];
1263  if (map.contains(key))
1264  {
1265  MetadataPtrList *filteredTracks = map.value(key);
1266  filteredTracks->append(mdata);
1267  }
1268  else
1269  {
1270  auto *filteredTracks = new MetadataPtrList;
1271  m_deleteList.append(filteredTracks);
1272  filteredTracks->append(mdata);
1273  map.insert(key, filteredTracks);
1274  }
1275  }
1276  }
1277 
1278  // add directories first
1279  QMap<QString, MetadataPtrList*>::const_iterator i = map.constBegin();
1280  while (i != map.constEnd())
1281  {
1282  if (!i.key().startsWith("[TRACK]"))
1283  {
1284  auto *newnode = new MusicGenericTree(node, i.key(), "directory");
1285  newnode->SetData(QVariant::fromValue(i.value()));
1286  }
1287  ++i;
1288  }
1289 
1290  // now add tracks
1291  i = map.constBegin();
1292  while (i != map.constEnd())
1293  {
1294  if (i.key().startsWith("[TRACK]"))
1295  {
1296  auto *newnode = new MusicGenericTree(node, i.key().mid(7), "trackid");
1297  newnode->setInt(i.value()->at(0)->ID());
1298  newnode->setDrawArrow(false);
1299  bool hasTrack = gPlayer->getCurrentPlaylist() ? gPlayer->getCurrentPlaylist()->checkTrack(newnode->getInt()) : false;
1301  }
1302  ++i;
1303  }
1304  }
1305  else if (node->getAction() == "artist" || node->getAction() == "compartist" ||
1306  node->getAction() == "album" || node->getAction() == "genre" ||
1307  node->getAction() == "rating" || node->getAction() == "year" ||
1308  node->getAction() == "compilations")
1309  {
1310  // which fields have we already filtered by
1311  QStringList fields;
1312  MusicGenericTree *climber = node;
1313  while (climber)
1314  {
1315  fields.append(climber->getAction());
1316  climber = dynamic_cast<MusicGenericTree *>(climber->getParent());
1317  }
1318 
1319  auto *newnode = new MusicGenericTree(node, tr("All Tracks"), "all tracks");
1320  newnode->setDrawArrow(true);
1321  newnode->SetData(node->GetData());
1322 
1323  if (!fields.contains("albums"))
1324  {
1325  newnode = new MusicGenericTree(node, tr("Albums"), "albums");
1326  newnode->setDrawArrow(true);
1327  newnode->SetData(node->GetData());
1328  }
1329 
1330  if (!fields.contains("artists"))
1331  {
1332  newnode = new MusicGenericTree(node, tr("Artists"), "artists");
1333  newnode->setDrawArrow(true);
1334  newnode->SetData(node->GetData());
1335  }
1336 
1337  if (!fields.contains("compartists"))
1338  {
1339  // only show the Compilation Artists node if we are one the Compilations branch
1340  bool showCompArtists = false;
1341  MusicGenericTree *mnode = node;
1342  do
1343  {
1344  if (mnode->getAction() == "compilations")
1345  {
1346  showCompArtists = true;
1347  break;
1348  }
1349 
1350  mnode = dynamic_cast<MusicGenericTree *>(mnode->getParent());
1351 
1352  } while (mnode);
1353 
1354  // only show the Comp. Artist if it differs from the Artist
1355  bool found = false;
1356  auto *tracks2 = node->GetData().value<MetadataPtrList*>();
1357  for (int x = 0; x < tracks2->count(); x++)
1358  {
1359  MusicMetadata *mdata = tracks2->at(x);
1360  if (mdata)
1361  {
1362  if (mdata->Artist() != mdata->CompilationArtist())
1363  {
1364  found = true;
1365  break;
1366  }
1367  }
1368  }
1369 
1370  if (showCompArtists && found)
1371  {
1372  newnode = new MusicGenericTree(node, tr("Compilation Artists"), "compartists");
1373  newnode->setDrawArrow(true);
1374  newnode->SetData(node->GetData());
1375  }
1376  }
1377 
1378  if (!fields.contains("genres"))
1379  {
1380  newnode = new MusicGenericTree(node, tr("Genres"), "genres");
1381  newnode->setDrawArrow(true);
1382  newnode->SetData(node->GetData());
1383  }
1384 #if 0
1385  if (!fields.contains("tags"))
1386  {
1387  newnode = new MusicGenericTree(node, tr("Tags"), "tags");
1388  newnode->setDrawArrow(true);
1389  newnode->SetData(node->GetData());
1390  }
1391 #endif
1392  if (!fields.contains("ratings"))
1393  {
1394  newnode = new MusicGenericTree(node, tr("Ratings"), "ratings");
1395  newnode->setDrawArrow(true);
1396  newnode->SetData(node->GetData());
1397  }
1398 
1399  if (!fields.contains("years"))
1400  {
1401  newnode = new MusicGenericTree(node, tr("Years"), "years");
1402  newnode->setDrawArrow(true);
1403  newnode->SetData(node->GetData());
1404  }
1405  }
1406 }
1407 
1409 {
1411 
1412  if (query.exec("SELECT categoryid, name FROM music_smartplaylist_categories ORDER BY name;"))
1413  {
1414  if (query.isActive() && query.size() > 0)
1415  {
1416  // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
1417  while (query.next())
1418  {
1419  // No memory leak. MusicGenericTree adds the new node
1420  // into a list of nodes maintained by its parent.
1421  auto *newnode =
1422  new MusicGenericTree(node, query.value(1).toString(), "smartplaylistcategory");
1423  newnode->setInt(query.value(0).toInt());
1424  }
1425  }
1426  }
1427  else
1428  {
1429  MythDB::DBError("Load smartplaylist categories", query);
1430  }
1431 }
1432 
1434 {
1435  int categoryid = node->getInt();
1436 
1438  query.prepare("SELECT smartplaylistid, name FROM music_smartplaylists WHERE categoryid = :CATEGORYID "
1439  "ORDER BY name;");
1440  query.bindValue(":CATEGORYID", categoryid);
1441  if (query.exec())
1442  {
1443  if (query.isActive() && query.size() > 0)
1444  {
1445  // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
1446  while (query.next())
1447  {
1448  // No memory leak. MusicGenericTree adds the new node
1449  // into a list of nodes maintained by its parent.
1450  auto *newnode =
1451  new MusicGenericTree(node, query.value(1).toString(), "smartplaylist");
1452  newnode->setInt(query.value(0).toInt());
1453  }
1454  }
1455  }
1456  else
1457  MythDB::DBError("Load smartplaylist names", query);
1458 }
1459 
1461 {
1463 
1464  // find smartplaylist
1465  QString matchType;
1466  QString orderBy;
1467  int limitTo = 0;
1468 
1469  query.prepare("SELECT smartplaylistid, matchtype, orderby, limitto "
1470  "FROM music_smartplaylists "
1471  "WHERE smartplaylistid = :SMARTPLAYLISTID;");
1472  query.bindValue(":SMARTPLAYLISTID", playlistID);
1473 
1474  if (query.exec())
1475  {
1476  if (query.isActive() && query.size() > 0)
1477  {
1478  query.first();
1479  matchType = (query.value(1).toString() == "All") ? " AND " : " OR ";
1480  orderBy = query.value(2).toString();
1481  limitTo = query.value(3).toInt();
1482  }
1483  else
1484  {
1485  LOG(VB_GENERAL, LOG_WARNING,
1486  LOC + QString("Cannot find smartplaylist: %1").arg(playlistID));
1487  return;
1488  }
1489  }
1490  else
1491  {
1492  MythDB::DBError("Find SmartPlaylist", query);
1493  return;
1494  }
1495 
1496  // get smartplaylist items
1497  QString whereClause = "WHERE ";
1498 
1499  query.prepare("SELECT field, operator, value1, value2 "
1500  "FROM music_smartplaylist_items "
1501  "WHERE smartplaylistid = :ID;");
1502  query.bindValue(":ID", playlistID);
1503  if (query.exec())
1504  {
1505  bool bFirst = true;
1506  while (query.next())
1507  {
1508  QString fieldName = query.value(0).toString();
1509  QString operatorName = query.value(1).toString();
1510  QString value1 = query.value(2).toString();
1511  QString value2 = query.value(3).toString();
1512  if (!bFirst)
1513  {
1514  whereClause += matchType + getCriteriaSQL(fieldName,
1515  operatorName, value1, value2);
1516  }
1517  else
1518  {
1519  bFirst = false;
1520  whereClause += " " + getCriteriaSQL(fieldName, operatorName,
1521  value1, value2);
1522  }
1523  }
1524  }
1525 
1526  // add order by clause
1527  whereClause += getOrderBySQL(orderBy);
1528 
1529  // add limit
1530  if (limitTo > 0)
1531  whereClause += " LIMIT " + QString::number(limitTo);
1532 
1533 
1534  // find the tracks for this smartplaylist
1535  QString theQuery;
1536 
1537  theQuery = "SELECT song_id, name FROM music_songs "
1538  "LEFT JOIN music_directories ON"
1539  " music_songs.directory_id=music_directories.directory_id "
1540  "LEFT JOIN music_artists ON"
1541  " music_songs.artist_id=music_artists.artist_id "
1542  "LEFT JOIN music_albums ON"
1543  " music_songs.album_id=music_albums.album_id "
1544  "LEFT JOIN music_genres ON"
1545  " music_songs.genre_id=music_genres.genre_id "
1546  "LEFT JOIN music_artists AS music_comp_artists ON "
1547  "music_albums.artist_id=music_comp_artists.artist_id ";
1548  if (whereClause.length() > 0)
1549  theQuery += whereClause;
1550 
1551  if (!query.exec(theQuery))
1552  {
1553  MythDB::DBError("Load songlist from query", query);
1554  return;
1555  }
1556 
1557  while (query.next())
1558  {
1559  auto *newnode =
1560  new MusicGenericTree(node, query.value(1).toString(), "trackid");
1561  newnode->setInt(query.value(0).toInt());
1562  newnode->setDrawArrow(false);
1563  bool hasTrack = gPlayer->getCurrentPlaylist() ? gPlayer->getCurrentPlaylist()->checkTrack(newnode->getInt()) : false;
1565  }
1566 
1567  // check we found some tracks if not add something to let the user know
1568  if (node->childCount() == 0)
1569  {
1570  auto *newnode =
1571  new MusicGenericTree(node, tr("** No matching tracks **"), "error");
1572  newnode->setDrawArrow(false);
1573  }
1574 }
1575 
1577 {
1578  QList<Playlist*> *playlists = gMusicData->m_all_playlists->getPlaylists();
1579 
1580  // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
1581  for (int x =0; x < playlists->count(); x++)
1582  {
1583  Playlist *playlist = playlists->at(x);
1584  // No memory leak. MusicGenericTree adds the new node
1585  // into a list of nodes maintained by its parent.
1586  auto *newnode =
1587  new MusicGenericTree(node, playlist->getName(), "playlist");
1588  newnode->setInt(playlist->getID());
1589  }
1590 }
1591 
1593 {
1595 
1596  for (int x = 0; x < tracks->count(); x++)
1597  {
1598  MusicMetadata *mdata = tracks->at(x);
1599  QString title = QString("%1 - %2").arg(mdata->Track()).arg(mdata->FormatTitle());
1600  auto *newnode = new MusicGenericTree(node, title, "trackid");
1601  newnode->setInt(mdata->ID());
1602  newnode->setDrawArrow(false);
1603  bool hasTrack = gPlayer->getCurrentPlaylist() ? gPlayer->getCurrentPlaylist()->checkTrack(mdata->ID()) : false;
1605  }
1606 }
1607 
1609 {
1610  Playlist *playlist = gMusicData->m_all_playlists->getPlaylist(playlistID);
1611 
1612  if (playlist)
1613  {
1614  for (int x = 0; x < playlist->getTrackCount(); x++)
1615  {
1616  MusicMetadata *mdata = playlist->getSongAt(x);
1617  if (mdata)
1618  {
1619  auto *newnode = new MusicGenericTree(node, mdata->Title(), "trackid");
1620  newnode->setInt(mdata->ID());
1621  newnode->setDrawArrow(false);
1622  bool hasTrack = gPlayer->getCurrentPlaylist() ? gPlayer->getCurrentPlaylist()->checkTrack(mdata->ID()) : false;
1624  }
1625  }
1626  }
1627 
1628  // check we found some tracks if not add something to let the user know
1629  if (node->childCount() == 0)
1630  {
1631  auto *newnode =
1632  new MusicGenericTree(node, tr("** Empty Playlist!! **"), "error");
1633  newnode->setDrawArrow(false);
1634  }
1635 }
1636 
1638 {
1640 }
1641 
1643 {
1644  for (int x = 0; x < node->childCount(); x++)
1645  {
1646  auto *mnode = dynamic_cast<MusicGenericTree*>(node->getChildAt(x));
1647  if (mnode)
1648  {
1649  if (mnode->getAction() == "trackid")
1650  {
1651  bool hasTrack = gPlayer->getCurrentPlaylist() ? gPlayer->getCurrentPlaylist()->checkTrack(mnode->getInt()) : false;
1653  }
1654  else
1655  {
1656  if (mnode->childCount())
1657  updateSelectedTracks(mnode);
1658  }
1659  }
1660  }
1661 }
1662 
1664 {
1665  QStringList route = m_playlistTree->GetCurrentNode()->getRouteByString();
1666 
1667  m_playlistTree->Reset();
1668 
1669  for (int x = 0; x < m_deleteList.count(); x++)
1670  delete m_deleteList.at(x);
1671  m_deleteList.clear();
1672 
1674  createRootNode();
1676 
1677  restoreTreePosition(route);
1678 }
1679 
1680 void PlaylistEditorView::restoreTreePosition(const QStringList &route)
1681 {
1682  if (route.count() < 2)
1683  return;
1684 
1685  // traverse up the tree creating each nodes children as we go
1686  MythGenericTree *node = m_rootNode;
1687  for (int x = 1 ; x < route.count(); x++)
1688  {
1689  node = node->getChildByName(route.at(x));
1690 
1691  if (node)
1692  treeNodeChanged(node);
1693  else
1694  break;
1695  }
1696 
1698 }
1699 
1701 {
1702  if (m_playlistTree)
1703  {
1704  QString route = m_playlistTree->GetCurrentNode()->getRouteByString().join("\n");
1705  gCoreContext->SaveSetting("MusicTreeLastActive", route);
1706  }
1707 }
1708 
1709 void PlaylistEditorView::smartPLChanged(const QString &category, const QString &name)
1710 {
1711  reloadTree();
1712 
1713  // move to the smart playlist in tree
1714  QStringList route;
1715  route << "Root Music Node" << tr("Smart Playlists") << category << name;
1716  restoreTreePosition(route);
1717 }
1718 
1720 {
1721  if (!ok)
1722  return;
1723 
1725  if (node)
1726  {
1727  auto *mnode = dynamic_cast<MusicGenericTree*>(node);
1728  if (mnode)
1729  {
1730  if (mnode->getAction() == "smartplaylist")
1731  {
1732  QString category = mnode->getParent()->GetText();
1733  QString name = mnode->GetText();
1734 
1736  reloadTree();
1737  }
1738  }
1739  }
1740 }
1741 
1743 {
1744  if (!ok)
1745  return;
1746 
1748  if (node)
1749  {
1750  auto *mnode = dynamic_cast<MusicGenericTree*>(node);
1751  if (mnode)
1752  {
1753  if (mnode->getAction() == "playlist")
1754  {
1755  int id = mnode->getInt();
1756 
1759  }
1760  }
1761  }
1762 }
MusicCommon::m_currentView
MusicView m_currentView
Definition: musiccommon.h:139
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:204
MusicGenericTree::setDrawArrow
void setDrawArrow(bool flag)
Definition: playlisteditorview.cpp:46
MusicGenericTree::setCheck
void setCheck(MythUIButtonListItem::CheckState state)
Definition: playlisteditorview.cpp:53
mythuibuttontree.h
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:783
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
MythMainWindow::GetMainStack
MythScreenStack * GetMainStack()
Definition: mythmainwindow.cpp:304
MusicCommon::editTrackInfo
static void editTrackInfo(MusicMetadata *mdata)
Definition: musiccommon.cpp:1868
playlistcontainer.h
PlaylistEditorView::updateSonglist
void updateSonglist(MusicGenericTree *node)
Definition: playlisteditorview.cpp:522
PL_REPLACE
@ PL_REPLACE
Definition: playlist.h:24
MusicGenericTree::MusicGenericTree
MusicGenericTree(MusicGenericTree *parent, const QString &name, const QString &action="", MythUIButtonListItem::CheckState check=MythUIButtonListItem::CantCheck, bool showArrow=true)
Definition: playlisteditorview.cpp:26
MusicMetadata::Title
QString Title() const
Definition: musicmetadata.h:162
gPlayer
MusicPlayer * gPlayer
Definition: musicplayer.cpp:35
PlaylistEditorView::getSmartPlaylistCategories
static void getSmartPlaylistCategories(MusicGenericTree *node)
Definition: playlisteditorview.cpp:1408
MSqlQuery::size
int size(void) const
Definition: mythdbcon.h:203
Playlist::getSongAt
MusicMetadata * getSongAt(int pos) const
Definition: playlist.cpp:1090
MusicMetadata::Filename
QString Filename(bool find=true)
Definition: musicmetadata.cpp:973
MythEvent::MythEventMessage
static Type MythEventMessage
Definition: mythevent.h:73
mythuitext.h
SmartPlaylistEditor::deleteSmartPlaylist
static bool deleteSmartPlaylist(const QString &category, const QString &name)
Definition: smartplaylist.cpp:1084
DialogCompletionEvent::GetId
QString GetId()
Definition: mythdialogbox.h:52
MusicMetadata::Genre
QString Genre() const
Definition: musicmetadata.h:175
MythGenericTree::GetText
QString GetText(const QString &name="") const
Definition: mythgenerictree.cpp:548
ShowOkPopup
MythConfirmationDialog * ShowOkPopup(const QString &message, QObject *parent, const char *slot, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
Definition: mythdialogbox.cpp:550
LOC
#define LOC
Definition: playlisteditorview.cpp:84
getOrderBySQL
QString getOrderBySQL(const QString &orderByFields)
Definition: smartplaylist.cpp:240
MythUIButtonListItem::DisplayState
void DisplayState(const QString &state, const QString &name)
Definition: mythuibuttonlist.cpp:3507
PlaylistEditorView::treeItemClicked
void treeItemClicked(MythUIButtonListItem *item)
Definition: playlisteditorview.cpp:803
MusicCommon::CreateCommon
bool CreateCommon(void)
Definition: musiccommon.cpp:81
AllMusic::getAllCDMetadata
MetadataPtrList * getAllCDMetadata(void)
Definition: musicmetadata.h:447
MusicCommon::createPlaylistOptionsMenu
MythMenu * createPlaylistOptionsMenu(void)
Definition: musiccommon.cpp:2388
MusicMetadata::CompilationArtist
QString CompilationArtist() const
Definition: musicmetadata.h:138
title
QString title
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:633
MusicCommon::keyPressEvent
bool keyPressEvent(QKeyEvent *e) override
Key event handler.
Definition: musiccommon.cpp:581
MusicGenericTree::m_buttonItem
QPointer< MusicButtonItem > m_buttonItem
Definition: playlisteditorview.h:57
PlaylistEditorView::PlaylistEditorView
PlaylistEditorView(MythScreenStack *parent, MythScreenType *parentScreen, const QString &layout, bool restorePosition=false)
Definition: playlisteditorview.cpp:88
MV_PLAYLISTEDITORTREE
@ MV_PLAYLISTEDITORTREE
Definition: musiccommon.h:34
MythMainWindow::TranslateKeyPress
bool TranslateKeyPress(const QString &context, QKeyEvent *e, QStringList &actions, bool allowJumps=true)
Get a list of actions for a keypress in the given context.
Definition: mythmainwindow.cpp:1106
MusicCommon::m_songList
QList< int > m_songList
Definition: musiccommon.h:168
MythGenericTree::visibleChildCount
uint visibleChildCount() const
Definition: mythgenerictree.h:91
MythGenericTree::getInt
int getInt() const
Definition: mythgenerictree.h:66
DialogCompletionEvent::kEventType
static Type kEventType
Definition: mythdialogbox.h:57
PlaylistOptions::insertPLOption
InsertPLOption insertPLOption
Definition: playlist.h:39
Playlist
Definition: playlist.h:45
Playlist::getName
QString getName(void)
Definition: playlist.h:106
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:16
mythdialogbox.h
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:198
MythScreenStack
Definition: mythscreenstack.h:15
arg
arg(title).arg(filename).arg(doDelete))
mythdbcon.h
MythGenericTree::GetData
QVariant GetData(void) const
Definition: mythgenerictree.h:88
MythUIButtonTree::GetItemCurrent
MythUIButtonListItem * GetItemCurrent(void) const
Return the currently selected list item.
Definition: mythuibuttontree.cpp:554
MythUIButtonListItem::FullChecked
@ FullChecked
Definition: mythuibuttonlist.h:34
MusicMetadata::ID
IdType ID() const
Definition: musicmetadata.h:217
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
MusicCommon::doUpdatePlaylist
void doUpdatePlaylist(void)
Definition: musiccommon.cpp:2519
MusicPlayerEvent::TrackAddedEvent
static Type TrackAddedEvent
Definition: musicplayer.h:42
PlaylistEditorView::Create
bool Create(void) override
Definition: playlisteditorview.cpp:110
MusicMetadata::Track
int Track() const
Definition: musicmetadata.h:199
MythGenericTree::getChildByName
MythGenericTree * getChildByName(const QString &a_name) const
Definition: mythgenerictree.cpp:379
category
QString category
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:1419
PlaylistEditorView::getSmartPlaylistTracks
static void getSmartPlaylistTracks(MusicGenericTree *node, int playlistID)
Definition: playlisteditorview.cpp:1460
PlaylistContainer::deletePlaylist
void deletePlaylist(int kill_me)
Definition: playlistcontainer.cpp:229
MusicCommon::showTrackInfo
static void showTrackInfo(MusicMetadata *mdata)
Definition: musiccommon.cpp:1948
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythScreenType
Screen in which all other widgets are contained and rendered.
Definition: mythscreentype.h:44
playlisteditorview.h
MusicMetadata
Definition: musicmetadata.h:80
MusicPlayerEvent::MetadataChangedEvent
static Type MetadataChangedEvent
Definition: musicplayer.h:46
MusicPlayer::getCurrentPlaylist
Playlist * getCurrentPlaylist(void)
Definition: musicplayer.cpp:1595
PlaylistEditorView::getPlaylists
static void getPlaylists(MusicGenericTree *node)
Definition: playlisteditorview.cpp:1576
mythdirs.h
MythUIButtonTree::AssignTree
bool AssignTree(MythGenericTree *tree)
Assign the root node of the tree to be displayed.
Definition: mythuibuttontree.cpp:211
MusicPlayer::removeListener
void removeListener(QObject *listener)
Definition: musicplayer.cpp:159
MusicMetadata::Artist
QString Artist() const
Definition: musicmetadata.h:126
MainVisual::prepare
void prepare(void) override
Definition: mainvisual.cpp:139
menu
static MythThemedMenu * menu
Definition: mythtv/programs/mythtv-setup/main.cpp:55
MythMainWindow::GetStack
MythScreenStack * GetStack(const QString &stackname)
Definition: mythmainwindow.cpp:309
musicutils.h
MythEvent::Message
const QString & Message() const
Definition: mythevent.h:65
MythUIButtonListItem::CheckState
CheckState
Definition: mythuibuttonlist.h:30
PlaylistEditorView::updateSelectedTracks
void updateSelectedTracks(void)
Definition: playlisteditorview.cpp:1637
MythScreenType::GetFocusWidget
MythUIType * GetFocusWidget(void) const
Definition: mythscreentype.cpp:112
AllMusic::getAllMetadata
MetadataPtrList * getAllMetadata(void)
Definition: musicmetadata.h:446
PlaylistEditorView::smartPLChanged
void smartPLChanged(const QString &category, const QString &name)
Definition: playlisteditorview.cpp:1709
getCriteriaSQL
QString getCriteriaSQL(const QString &fieldName, const QString &operatorName, QString value1, QString value2)
Definition: smartplaylist.cpp:149
MusicCommon::m_playlistOptions
PlaylistOptions m_playlistOptions
Definition: musiccommon.h:164
PlaylistEditorView::m_deleteList
QList< MetadataPtrList * > m_deleteList
Definition: playlisteditorview.h:117
PlaylistEditorView::ShowMenu
void ShowMenu(void) override
Definition: playlisteditorview.cpp:621
MythUIButtonListItem::SetText
void SetText(const QString &text, const QString &name="", const QString &state="")
Definition: mythuibuttonlist.cpp:3272
MythGenericTree::getChildAt
MythGenericTree * getChildAt(uint reference) const
Definition: mythgenerictree.cpp:283
MythGenericTree::addNode
MythGenericTree * addNode(const QString &a_string, int an_int=0, bool selectable_flag=false, bool visible=true)
Definition: mythgenerictree.cpp:87
MythObservable::addListener
void addListener(QObject *listener)
Add a listener to the observable.
Definition: mythobservable.cpp:38
mythuiutils.h
MythUIButtonListItem
Definition: mythuibuttonlist.h:27
MusicButtonItem
Definition: playlisteditorview.h:24
MusicCommon::m_moveTrackMode
bool m_moveTrackMode
Definition: musiccommon.h:150
MythUIButtonListItem::CantCheck
@ CantCheck
Definition: mythuibuttonlist.h:31
PlaylistEditorView::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: playlisteditorview.cpp:349
MusicGenericTree::CreateListButton
MythUIButtonListItem * CreateListButton(MythUIButtonList *list) override
Definition: playlisteditorview.cpp:63
PlaylistEditorView::deletePlaylist
void deletePlaylist(bool ok)
Definition: playlisteditorview.cpp:1742
MythGenericTree::sortByString
void sortByString()
Definition: mythgenerictree.cpp:421
MSqlQuery::first
bool first(void)
Wrap QSqlQuery::first() so we can display the query results.
Definition: mythdbcon.cpp:793
MythGenericTree::getRouteByString
QStringList getRouteByString(void)
Definition: mythgenerictree.cpp:228
MythDialogBox
Basic menu dialog, message and a list of options.
Definition: mythdialogbox.h:137
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
MusicGenericTree::getAction
QString getAction(void) const
Definition: playlisteditorview.h:46
MusicMetadata::getAlbumArtFile
QString getAlbumArtFile(void)
Definition: musicmetadata.cpp:1270
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
MythTV::Visual::mutex
QMutex * mutex()
Definition: visual.h:25
MythScreenType::BuildFocusList
void BuildFocusList(void)
Definition: mythscreentype.cpp:222
Playlist::getTrackCount
int getTrackCount(void)
Definition: playlist.h:82
AllMusic::getCDTitle
QString getCDTitle(void) const
Definition: musicmetadata.h:439
MythGenericTree::childCount
int childCount(void) const
Definition: mythgenerictree.cpp:256
PlaylistContainer::getPlaylist
Playlist * getPlaylist(int id)
Definition: playlistcontainer.cpp:134
MV_PLAYLISTEDITORGALLERY
@ MV_PLAYLISTEDITORGALLERY
Definition: musiccommon.h:35
filename
QString filename
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:634
MusicCommon::stopVisualizer
void stopVisualizer(void)
Definition: musiccommon.cpp:1029
AllMusic::getCDTrackCount
int getCDTrackCount(void) const
Definition: musicmetadata.h:441
MusicCommon::m_mainvisual
MainVisual * m_mainvisual
Definition: musiccommon.h:142
SmartPlaylistEditor
Definition: smartplaylist.h:72
MythGenericTree::deleteAllChildren
void deleteAllChildren()
Definition: mythgenerictree.cpp:455
MythGenericTree::setSelectable
void setSelectable(bool flag)
Definition: mythgenerictree.h:96
PlaylistEditorView::deleteSmartPlaylist
void deleteSmartPlaylist(bool ok)
Definition: playlisteditorview.cpp:1719
MythUIButtonTree::GetCurrentNode
MythGenericTree * GetCurrentNode(void) const
Definition: mythuibuttontree.h:32
Playlist::checkTrack
bool checkTrack(MusicMetadata::IdType trackID) const
Definition: playlist.cpp:38
MythUIButtonListItem::GetData
QVariant GetData()
Definition: mythuibuttonlist.cpp:3588
AllMusic::getMetadata
MusicMetadata * getMetadata(int an_id)
Definition: musicmetadata.cpp:1647
MusicPlayer::removeTrack
void removeTrack(int trackID)
Definition: musicplayer.cpp:1577
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
MusicData::m_all_playlists
PlaylistContainer * m_all_playlists
Definition: musicdata.h:54
smartplaylist.h
PlaylistEditorView::~PlaylistEditorView
~PlaylistEditorView(void) override
Definition: playlisteditorview.cpp:97
MusicPlayerEvent::AllTracksRemovedEvent
static Type AllTracksRemovedEvent
Definition: musicplayer.h:45
PlaylistEditorView::reloadTree
void reloadTree(void)
Definition: playlisteditorview.cpp:1663
MythUIButtonTree::SetNodeByString
bool SetNodeByString(QStringList route)
Using a path based on the node string, set the currently selected node.
Definition: mythuibuttontree.cpp:279
MythGenericTree::getAllChildren
QList< MythGenericTree * > * getAllChildren() const
Definition: mythgenerictree.cpp:278
musicdata.h
UIUtilDisp::Assign
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
MythGenericTree::siblingCount
int siblingCount(void) const
Definition: mythgenerictree.cpp:261
PlaylistEditorView::treeItemVisible
static void treeItemVisible(MythUIButtonListItem *item)
Definition: playlisteditorview.cpp:831
musiccommon.h
MusicMetadata::Album
QString Album() const
Definition: musicmetadata.h:150
gMusicData
MusicData * gMusicData
Definition: musicdata.cpp:20
MusicGenericTree
Definition: playlisteditorview.h:37
MythUIButtonListItem::GetText
QString GetText(const QString &name="") const
Definition: mythuibuttonlist.cpp:3313
MythGenericTree::getPosition
int getPosition(void)
Definition: mythgenerictree.cpp:207
PL_INSERTATEND
@ PL_INSERTATEND
Definition: playlist.h:26
MusicCommon::createMainMenu
MythMenu * createMainMenu(void)
Definition: musiccommon.cpp:2178
PlaylistEditorView::getCDTracks
static void getCDTracks(MusicGenericTree *node)
Definition: playlisteditorview.cpp:1592
MythMenu
Definition: mythdialogbox.h:92
MythUIButtonTree::Reset
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuibuttontree.cpp:234
PlaylistEditorView::restoreTreePosition
void restoreTreePosition(const QStringList &route)
Definition: playlisteditorview.cpp:1680
MythUIButtonTree::RemoveCurrentItem
void RemoveCurrentItem(bool deleteNode=false)
Remove the currently selected item from the tree.
Definition: mythuibuttontree.cpp:426
PlaylistEditorView::customEvent
void customEvent(QEvent *event) override
Definition: playlisteditorview.cpp:177
XMLParseBase::LoadWindowFromXML
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
Definition: xmlparsebase.cpp:692
MythUIButtonListItem::SetImage
void SetImage(MythImage *image, const QString &name="")
Sets an image directly, should only be used in special circumstances since it bypasses the cache.
Definition: mythuibuttonlist.cpp:3406
dir
QDir dir
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:1171
MythGenericTree::getParent
MythGenericTree * getParent(void) const
Definition: mythgenerictree.cpp:372
MusicPlayer::addTrack
void addTrack(int trackID, bool updateUI)
Definition: musicplayer.cpp:1590
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:864
MusicPlayerEvent::PlaylistChangedEvent
static Type PlaylistChangedEvent
Definition: musicplayer.h:50
DialogCompletionEvent
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:41
MythGenericTree
Definition: mythgenerictree.h:20
PlaylistEditorView::m_restorePosition
bool m_restorePosition
Definition: playlisteditorview.h:115
MusicMetadata::Compilation
bool Compilation() const
Definition: musicmetadata.h:251
MusicPlayerEvent::TrackRemovedEvent
static Type TrackRemovedEvent
Definition: musicplayer.h:43
MythUIText::SetText
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:135
mythcontext.h
MusicMetadata::FormatTitle
QString FormatTitle()
Definition: musicmetadata.cpp:959
PlaylistEditorView::createPlaylistMenu
MythMenu * createPlaylistMenu(void)
Definition: playlisteditorview.cpp:676
mainvisual.h
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:107
PlaylistEditorView::m_positionText
MythUIText * m_positionText
Definition: playlisteditorview.h:121
build_compdb.action
action
Definition: build_compdb.py:9
PlaylistEditorView::createRootNode
void createRootNode(void)
Definition: playlisteditorview.cpp:734
MusicPlayerEvent::CDChangedEvent
static Type CDChangedEvent
Definition: musicplayer.h:49
PlaylistEditorView::saveTreePosition
void saveTreePosition(void)
Definition: playlisteditorview.cpp:1700
PlaylistOptions::playPLOption
PlayPLOption playPLOption
Definition: playlist.h:40
MetadataPtrList
QList< MusicMetadata * > MetadataPtrList
Definition: musicmetadata.h:395
MusicData::m_all_music
AllMusic * m_all_music
Definition: musicdata.h:55
PlaylistEditorView::getPlaylistTracks
static void getPlaylistTracks(MusicGenericTree *node, int playlistID)
Definition: playlisteditorview.cpp:1608
MusicMetadata::Rating
int Rating() const
Definition: musicmetadata.h:238
PlaylistEditorView::getSmartPlaylists
static void getSmartPlaylists(MusicGenericTree *node)
Definition: playlisteditorview.cpp:1433
MusicGenericTree::m_showArrow
bool m_showArrow
Definition: playlisteditorview.h:59
PlaylistEditorView::createSmartPlaylistMenu
MythMenu * createSmartPlaylistMenu(void)
Definition: playlisteditorview.cpp:699
PL_FIRST
@ PL_FIRST
Definition: playlist.h:32
Playlist::getID
int getID(void) const
Definition: playlist.h:111
MusicGenericTree::m_action
QString m_action
Definition: playlisteditorview.h:56
PlaylistEditorView::treeNodeChanged
void treeNodeChanged(MythGenericTree *node)
Definition: playlisteditorview.cpp:920
MythCoreContext::SaveSetting
void SaveSetting(const QString &key, int newValue)
Definition: mythcorecontext.cpp:884
PL_CURRENT
@ PL_CURRENT
Definition: playlist.h:34
PlaylistContainer::getPlaylists
QList< Playlist * > * getPlaylists(void)
Definition: playlistcontainer.h:71
PlaylistEditorView::m_playlistTree
MythUIButtonTree * m_playlistTree
Definition: playlisteditorview.h:119
MythUIButtonList
List widget, displays list items in a variety of themeable arrangements and can trigger signals when ...
Definition: mythuibuttonlist.h:143
MusicPlayerEvent::AlbumArtChangedEvent
static Type AlbumArtChangedEvent
Definition: musicplayer.h:48
PlaylistEditorView::m_layout
QString m_layout
Definition: playlisteditorview.h:114
mythmainwindow.h
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:49
query
MSqlQuery query(MSqlQuery::InitCon())
PlaylistEditorView::m_rootNode
MusicGenericTree * m_rootNode
Definition: playlisteditorview.h:116
findIcon
META_PUBLIC QString findIcon(const QString &type, const QString &name, bool ignoreCache=false)
find an image for a artist or genre
MusicGenericTree::m_check
MythUIButtonListItem::CheckState m_check
Definition: playlisteditorview.h:58
MusicCommon::customEvent
void customEvent(QEvent *event) override
Definition: musiccommon.cpp:1186
MythObservable::removeListener
void removeListener(QObject *listener)
Remove a listener to the observable.
Definition: mythobservable.cpp:55
MusicMetadata::Year
int Year() const
Definition: musicmetadata.h:196
PlaylistEditorView::filterTracks
void filterTracks(MusicGenericTree *node)
Definition: playlisteditorview.cpp:970
MusicCommon
Definition: musiccommon.h:47
MusicCommon::ShowMenu
void ShowMenu(void) override
Definition: musiccommon.cpp:2164
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:901
MythUIButtonListItem::NotChecked
@ NotChecked
Definition: mythuibuttonlist.h:32
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:808
MusicMetadata::DiscNumber
int DiscNumber() const
Definition: musicmetadata.h:208
PlaylistEditorView::m_breadcrumbsText
MythUIText * m_breadcrumbsText
Definition: playlisteditorview.h:120