MythTV  master
nettree.cpp
Go to the documentation of this file.
1 // qt
2 #include <QString>
3 #include <QFileInfo>
4 #include <QtAlgorithms>
5 
6 // myth
7 #include <mythdb.h>
8 #include <mythcontext.h>
9 #include <mythdirs.h>
10 #include <mythsystemlegacy.h>
11 #include <mythprogressdialog.h>
12 #include <rssparse.h>
13 #include <netutils.h>
14 #include <mythrssmanager.h>
15 #include <netgrabbermanager.h>
16 #include <mythcoreutil.h>
17 #include <metadata/videoutils.h>
18 #include <mythuiimage.h>
19 #include <mythuitext.h>
20 #include <mythscreenstack.h>
21 #include <mythmainwindow.h>
22 #include <mythsorthelper.h>
23 
24 // mythnetvision
25 #include "treeeditor.h"
26 #include "nettree.h"
27 #include "rsseditor.h"
28 #include "netcommon.h"
29 
30 class GrabberScript;
31 
32 const QString NetTree::RSSNode = tr("RSS Feeds");
33 const QString NetTree::SearchNode = tr("Searches");
34 const QString NetTree::DownloadNode = tr("Downloaded Files");
35 
36 namespace
37 {
38  MythGenericTree *GetNodePtrFromButton(MythUIButtonListItem *item)
39  {
40  if (item)
41  return item->GetData().value<MythGenericTree *>();
42 
43  return nullptr;
44  }
45 }
46 
47 NetTree::NetTree(DialogType type, MythScreenStack *parent, const char *name)
48  : NetBase(parent, name),
49  m_gdt(new GrabberDownloadThread(this)), m_type(type)
50 {
51  connect(m_gdt, SIGNAL(finished()), SLOT(DoTreeRefresh()));
53  "mythNetTree.updateFreq", 6);
55  "mythnetvision.rssBackgroundFetch", false);
57  "mythnetvision.backgroundFetch", false);
58 }
59 
61 {
62  QString windowName = "gallery";
63 
64  switch (m_type)
65  {
66  case DLG_GALLERY:
67  windowName = "gallery";
68  break;
69  case DLG_BROWSER:
70  windowName = "browser";
71  break;
72  case DLG_TREE:
73  windowName = "tree";
74  break;
75  case DLG_DEFAULT:
76  default:
77  break;
78  }
79 
80  if (!LoadWindowFromXML("netvision-ui.xml", windowName, this))
81  return false;
82 
83  bool err = false;
84  if (m_type == DLG_TREE)
85  UIUtilE::Assign(this, m_siteMap, "videos", &err);
86  else
87  UIUtilE::Assign(this, m_siteButtonList, "videos", &err);
88 
89  UIUtilW::Assign(this, m_noSites, "nosites");
90 
91  UIUtilW::Assign(this, m_thumbImage, "preview");
92 
93  UIUtilW::Assign(this, m_downloadable, "downloadable");
94 
95  m_siteGeneric = new MythGenericTree("site root", 0, false);
97 
98  if (err)
99  {
100  LOG(VB_GENERAL, LOG_ERR, "Cannot load screen '" + windowName + "'");
101  return false;
102  }
103 
104  BuildFocusList();
105 
107 
108  if (m_type == DLG_TREE)
109  {
111 
112  connect(m_siteMap, SIGNAL(itemClicked(MythUIButtonListItem *)),
113  SLOT(StreamWebVideo(void)));
114  connect(m_siteMap, SIGNAL(itemSelected(MythUIButtonListItem *)),
115  SLOT(SlotItemChanged(void)));
116  connect(m_siteMap, SIGNAL(nodeChanged(MythGenericTree *)),
117  SLOT(SlotItemChanged(void)));
118  }
119  else
120  {
122 
123  connect(m_siteButtonList, SIGNAL(itemClicked(MythUIButtonListItem *)),
125  connect(m_siteButtonList, SIGNAL(itemSelected(MythUIButtonListItem *)),
126  SLOT(SlotItemChanged(void)));
127  }
128 
129  return true;
130 }
131 
133 {
136 
137  FillTree();
138 }
139 
141 {
142  if (!node)
143  return;
144 
145  m_currentNode = node;
146 }
147 
149 {
150  delete m_siteGeneric;
151  m_siteGeneric = nullptr;
152 
153  delete m_gdt;
154  m_gdt = nullptr;
155 
156  m_rssList.clear();
157 
158  qDeleteAll(m_videos);
159  m_videos.clear();
160 }
161 
163 {
164  if (m_type == DLG_TREE)
166  else
167  {
169 
170  if (!m_currentNode)
172 
173  if (!m_currentNode)
174  return;
175 
177 
178  using MGTreeChildList = QList<MythGenericTree *>;
179  MGTreeChildList *lchildren = m_currentNode->getAllChildren();
180 
181  for (MGTreeChildList::const_iterator p = lchildren->begin();
182  p != lchildren->end(); ++p)
183  {
184  if (*p != nullptr)
185  {
186  auto *item =
187  new MythUIButtonListItem(m_siteButtonList, QString(), nullptr,
189 
190  item->SetData(qVariantFromValue(*p));
191 
192  UpdateItem(item);
193 
194  if (*p == selectedNode)
196  }
197  }
198 
199  SlotItemChanged();
200  }
201 
202  if (m_siteGeneric->childCount() == 0 && m_noSites)
203  m_noSites->SetVisible(true);
204  else if (m_noSites)
205  m_noSites->SetVisible(false);
206 
207  if (m_siteGeneric->childCount() == 0)
208  RunTreeEditor();
209 }
210 
212 {
213  if (!item)
214  return;
215 
216  MythGenericTree *node = GetNodePtrFromButton(item);
217 
218  if (!node)
219  return;
220 
221  auto *site = node->GetData().value<RSSSite *>();
222  auto *video = node->GetData().value<ResultItem *>();
223 
224  int nodeInt = node->getInt();
225 
226  if (nodeInt == kSubFolder)
227  {
228  item->SetText(QString("%1").arg(node->visibleChildCount()),
229  "childcount");
230  item->DisplayState("subfolder", "nodetype");
231  item->SetText(node->GetText(), "title");
232  item->SetText(node->GetText());
233  item->SetImage(node->GetData().toString());
234  }
235  else if (nodeInt == kUpFolder)
236  {
237  item->DisplayState("upfolder", "nodetype");
238  item->SetText(node->GetText(), "title");
239  item->SetText(node->GetText());
240  }
241 
242  if (site)
243  {
244  item->SetText(site->GetTitle());
245  item->SetText(site->GetDescription(), "description");
246  item->SetText(site->GetURL(), "url");
247  item->SetImage(site->GetImage());
248  }
249  else if (video)
250  {
251  item->SetText(video->GetTitle());
252 
253  InfoMap metadataMap;
254  video->toMap(metadataMap);
255  item->SetTextFromMap(metadataMap);
256 
257  int pos = 0;
258  if (m_type != DLG_TREE)
259  pos = m_siteButtonList->GetItemPos(item);
260 
261  QString dlfile = video->GetThumbnail();
262  if (dlfile.contains("%SHAREDIR%"))
263  dlfile.replace("%SHAREDIR%", GetShareDir());
264  else
265  dlfile = getDownloadFilename(video->GetTitle(),
266  video->GetThumbnail());
267 
268  if (QFile::exists(dlfile))
269  item->SetImage(dlfile);
270  else if (video->GetThumbnail().startsWith("http"))
271  m_imageDownload->addThumb(video->GetTitle(), video->GetThumbnail(),
272  qVariantFromValue<uint>(pos));
273  }
274  else
275  {
276  item->SetText(node->GetText());
277  if (!node->GetData().toString().isEmpty())
278  {
279  QString tpath = node->GetData().toString();
280  if (tpath.startsWith("http://"))
281  {
282  uint pos = 0;
283  if (m_type != DLG_TREE)
284  pos = m_siteButtonList->GetItemPos(item);
285 
286  QString dlfile = GetThumbnailFilename(tpath,
287  node->GetText());
288  if (QFile::exists(dlfile))
289  item->SetImage(dlfile);
290  else
291  m_imageDownload->addThumb(node->GetText(), tpath,
292  qVariantFromValue<uint>(pos));
293  }
294  else if (tpath != "0")
295  {
296  QString filename = node->GetData().toString();
297  if (filename.contains("%SHAREDIR%"))
298  filename.replace("%SHAREDIR%", GetShareDir());
299  item->SetImage(filename);
300  }
301  }
302  }
303 }
304 
306 {
307  MythGenericTree *node = GetNodePtrFromButton(item);
308  if (!node)
309  return;
310 
311  int nodeInt = node->getInt();
312 
313  switch (nodeInt)
314  {
315  case kSubFolder:
316  HandleDirSelect(node);
317  break;
318  case kUpFolder:
319  GoBack();
320  break;
321  default:
322  {
323  StreamWebVideo();
324  }
325  }
326  SlotItemChanged();
327 }
328 
330 {
333 
334  SetCurrentNode(node);
335  LoadData();
336 }
337 
339 {
340  bool handled = false;
341 
344 
346  {
348  if (lparent)
349  {
350  SetCurrentNode(lparent);
351  handled = true;
352  }
353  }
354 
355  LoadData();
356 
357  return handled;
358 }
359 
360 bool NetTree::keyPressEvent(QKeyEvent *event)
361 {
362  if (GetFocusWidget()->keyPressEvent(event))
363  return true;
364 
365  QStringList actions;
366  bool handled = GetMythMainWindow()->TranslateKeyPress("Internet Video",
367  event, actions);
368 
369  for (int i = 0; i < actions.size() && !handled; i++)
370  {
371  QString action = actions[i];
372  handled = true;
373 
374  if (action == "MENU")
375  {
376  ShowMenu();
377  }
378  else if (action == "ESCAPE")
379  {
380  if (m_type != DLG_TREE
381  && !GetMythMainWindow()->IsExitingToMain()
383  handled = GoBack();
384  else
385  handled = false;
386  }
387  else
388  handled = false;
389  }
390 
391  if (!handled && MythScreenType::keyPressEvent(event))
392  handled = true;
393 
394  return handled;
395 }
396 
398 {
399  QString label = tr("Playback/Download Options");
400 
401  auto *menu = new MythMenu(label, this, "options");
402 
403  ResultItem *item = nullptr;
404  if (m_type == DLG_TREE)
405  {
407 
408  if (node)
409  item = node->GetData().value<ResultItem *>();
410  }
411  else
412  {
413  MythGenericTree *node =
414  GetNodePtrFromButton(m_siteButtonList->GetItemCurrent());
415 
416  if (node)
417  item = node->GetData().value<ResultItem *>();
418  }
419 
420  if (item)
421  {
422  if (item->GetDownloadable())
423  menu->AddItem(tr("Stream Video"), SLOT(StreamWebVideo()));
424  menu->AddItem(tr("Open Web Link"), SLOT(ShowWebVideo()));
425 
426  if (item->GetDownloadable())
427  menu->AddItem(tr("Save This Video"), SLOT(DoDownloadAndPlay()));
428  }
429 
430  menu->AddItem(tr("Scan/Manage Subscriptions"), nullptr, CreateShowManageMenu());
431  menu->AddItem(tr("Change View"), nullptr, CreateShowViewMenu());
432 
433  auto *menuPopup =
434  new MythDialogBox(menu, m_popupStack, "mythnettreemenupopup");
435 
436  if (menuPopup->Create())
437  m_popupStack->AddScreen(menuPopup);
438  else
439  delete menuPopup;
440 }
441 
443 {
444  QString label = tr("View Options");
445 
446  auto *menu = new MythMenu(label, this, "options");
447 
448  if (m_type != DLG_TREE)
449  menu->AddItem(tr("Switch to List View"), SLOT(SwitchTreeView()));
450  if (m_type != DLG_GALLERY)
451  menu->AddItem(tr("Switch to Gallery View"), SLOT(SwitchGalleryView()));
452  if (m_type != DLG_BROWSER)
453  menu->AddItem(tr("Switch to Browse View"), SLOT(SwitchBrowseView()));
454 
455  return menu;
456 }
457 
459 {
460  QString label = tr("Subscription Management");
461 
462  auto *menu = new MythMenu(label, this, "options");
463 
464  menu->AddItem(tr("Update Site Maps"), SLOT(UpdateTrees()));
465  menu->AddItem(tr("Update RSS"), SLOT(UpdateRSS()));
466  menu->AddItem(tr("Manage Site Subscriptions"), SLOT(RunTreeEditor()));
467  menu->AddItem(tr("Manage RSS Subscriptions"), SLOT(RunRSSEditor()));
468  if (!m_treeAutoUpdate)
469  menu->AddItem(tr("Enable Automatic Site Updates"),
470  SLOT(ToggleTreeUpdates()));
471  else
472  menu->AddItem(tr("Disable Automatic Site Updates"),
473  SLOT(ToggleTreeUpdates()));
474 // if (!m_rssAutoUpdate)
475 // menu->AddItem(tr("Enable Automatic RSS Updates"), SLOT(ToggleRSSUpdates()));
476 // else
477 // menu->AddItem(tr("Disable Automatic RSS Updates"), SLOT(ToggleRSSUpdates()));
478 
479  return menu;
480 }
481 
483 {
484  m_type = DLG_TREE;
485  SwitchView();
486 }
487 
489 {
491  SwitchView();
492 }
493 
495 {
497  SwitchView();
498 }
499 
501 {
502  auto *nettree =
503  new NetTree(m_type, GetMythMainWindow()->GetMainStack(), "nettree");
504 
505  if (nettree->Create())
506  {
507  gCoreContext->SaveSetting("mythnetvision.ViewMode", m_type);
508  MythScreenStack *screenStack = GetScreenStack();
509  screenStack->AddScreen(nettree);
510  screenStack->PopScreen(this, false, false);
511  deleteLater();
512  }
513  else
514  delete nettree;
515 }
516 
518 {
519  // First let's add all the RSS
520  if (!m_rssList.isEmpty())
521  {
522  auto *rssGeneric = new MythGenericTree(RSSNode, kSubFolder, false);
523 
524  // Add an upfolder
525  if (m_type != DLG_TREE)
526  rssGeneric->addNode(tr("Back"), kUpFolder, true, false);
527 
528  rssGeneric->SetData(QString("%1/mythnetvision/icons/rss.png")
529  .arg(GetShareDir()));
530 
531  RSSSite::rssList::iterator i = m_rssList.begin();
532  for (; i != m_rssList.end(); ++i)
533  {
534  ResultItem::resultList items = getRSSArticles((*i)->GetTitle(),
535  VIDEO_PODCAST);
536  auto *ret =
537  new MythGenericTree((*i)->GetTitle(), kSubFolder, false);
538  ret->SetData(qVariantFromValue(*i));
539  rssGeneric->addNode(ret);
540 
541  // Add an upfolder
542  if (m_type != DLG_TREE)
543  ret->addNode(tr("Back"), kUpFolder, true, false);
544 
545  ResultItem::resultList::iterator it = items.begin();
546  for (; it != items.end(); ++it)
547  AddFileNode(ret, *it);
548  SetSubfolderData(ret);
549  }
550 
551  m_siteGeneric->addNode(rssGeneric);
552  SetSubfolderData(rssGeneric);
553  }
554 
555  // Now let's add all the grabber trees
556  for (GrabberScript::scriptList::iterator g = m_grabberList.begin();
557  g != m_grabberList.end(); ++g)
558  {
559 
560  QMultiMap<QPair<QString,QString>, ResultItem*> treePathsNodes =
561  getTreeArticles((*g)->GetTitle(), VIDEO_FILE);
562 
563  QList< QPair<QString,QString> > paths = treePathsNodes.uniqueKeys();
564 
565  auto *ret = new MythGenericTree((*g)->GetTitle(), kSubFolder, false);
566  QString thumb = QString("%1mythnetvision/icons/%2").arg(GetShareDir())
567  .arg((*g)->GetImage());
568  ret->SetData(qVariantFromValue(thumb));
569 
570  // Add an upfolder
571  if (m_type != DLG_TREE)
572  ret->addNode(tr("Back"), kUpFolder, true, false);
573 
574  for (auto it2 = paths.begin(); it2 != paths.end(); ++it2)
575  {
576  QStringList curPaths = (*it2).first.split("/");
577  QString dirthumb = (*it2).second;
578  QList<ResultItem*> videos = treePathsNodes.values(*it2);
579  BuildGenericTree(ret, curPaths, dirthumb, videos);
580  }
581  m_siteGeneric->addNode(ret);
582  SetSubfolderData(ret);
583  }
585 }
586 
588  const QString& dirthumb, QList<ResultItem*> videos)
589 {
590  MythGenericTree *folder = nullptr;
591 
592  // A little loop to determine what path of the provided path might
593  // already exist in the tree.
594 
595  while (folder == nullptr && !paths.empty())
596  {
597  QString curPath = paths.takeFirst();
598  curPath.replace("|", "/");
599  MythGenericTree *tmp = dst->getChildByName(curPath);
600  if (tmp)
601  dst = tmp;
602  else
603  folder = new MythGenericTree(curPath, kSubFolder, false);
604  }
605 
606  if (!folder)
607  return;
608 
609  folder->SetData(dirthumb);
610  dst->addNode(folder);
611 
612  // Add an upfolder
613  if (m_type != DLG_TREE)
614  folder->addNode(tr("Back"), kUpFolder, true, false);
615 
616  if (!paths.empty())
617  BuildGenericTree(folder, paths, dirthumb, videos);
618  else
619  {
620  // File Handling
621  for (QList<ResultItem*>::iterator it = videos.begin();
622  it != videos.end(); ++it)
623  AddFileNode(folder, *it);
624  }
625  SetSubfolderData(folder);
626 }
627 
629 {
630  QString title = video->GetTitle();
631  title.replace("&amp;", "&");
632  MythGenericTree *sub_node = where_to_add->addNode(title, 0, true);
633  sub_node->SetData(qVariantFromValue(video));
634 
635  InfoMap textMap;
636  video->toMap(textMap);
637  sub_node->SetTextFromMap(textMap);
638 
639  m_videos.append(video);
640 }
641 
643 {
644  ResultItem *item = nullptr;
645 
646  if (m_type == DLG_TREE)
647  item = m_siteMap->GetCurrentNode()->GetData().value<ResultItem *>();
648  else
649  {
650  MythGenericTree *node =
651  GetNodePtrFromButton(m_siteButtonList->GetItemCurrent());
652 
653  if (node)
654  item = node->GetData().value<ResultItem *>();
655  }
656  return item;
657 }
658 
660 {
661  InfoMap metadataMap;
662  item->toMap(metadataMap);
663  SetTextFromMap(metadataMap);
664 
665  if (!item->GetThumbnail().isEmpty() && m_thumbImage)
666  {
667  m_thumbImage->Reset();
668  QString dlfile = item->GetThumbnail();
669  if (dlfile.contains("%SHAREDIR%"))
670  {
671  dlfile.replace("%SHAREDIR%", GetShareDir());
672  m_thumbImage->SetFilename(dlfile);
673  m_thumbImage->Load();
674  }
675  else
676  {
677  QString sFilename = getDownloadFilename(item->GetTitle(),
678  item->GetThumbnail());
679 
680  bool exists = QFile::exists(sFilename);
681  if (exists)
682  {
683  m_thumbImage->SetFilename(sFilename);
684  m_thumbImage->Load();
685  }
686  else if (item->GetThumbnail().startsWith("http"))
687  {
689  item->GetThumbnail(),
690  qVariantFromValue<uint>(0));
691  }
692  }
693  }
694  else if (m_thumbImage)
695  m_thumbImage->Reset();
696 
697  if (m_downloadable)
698  {
699  if (item->GetDownloadable())
701  else
703  }
704 }
705 
707 {
708  ResultItem res =
709  ResultItem(site->GetTitle(), site->GetSortTitle(),
710  QString(), QString(), // no subtitle information
711  site->GetDescription(),
712  site->GetURL(), site->GetImage(), QString(),
713  site->GetAuthor(), QDateTime(), nullptr, nullptr, -1, QString(),
714  QStringList(), QString(), QStringList(), 0, 0, QString(),
715  false, QStringList(), 0, 0, false);
716 
717  InfoMap metadataMap;
718  res.toMap(metadataMap);
719  SetTextFromMap(metadataMap);
720 
721  if (!site->GetImage().isEmpty() && m_thumbImage)
722  {
724  m_thumbImage->Load();
725  }
726  else if (m_thumbImage)
727  m_thumbImage->Reset();
728 
729  if (m_downloadable)
731 }
732 
734 {
735  QString title;
736 
737  if (m_type == DLG_TREE)
738  title = m_siteMap->GetItemCurrent()->GetText();
739  else
741 
742  QString thumb;
743  if (m_type == DLG_TREE)
744  thumb = m_siteMap->GetCurrentNode()->GetData().toString();
745  else
746  {
747  MythGenericTree *node =
748  GetNodePtrFromButton(m_siteButtonList->GetItemCurrent());
749 
750  if (node)
751  thumb = node->GetData().toString();
752  }
753 
754  std::shared_ptr<MythSortHelper>sh = getMythSortHelper();
755  ResultItem res =
756  ResultItem(title, sh->doTitle(title), // title, sortTitle
757  QString(), QString(), // no subtitle information
758  QString(), // description
759  QString(), thumb, QString(),
760  QString(), QDateTime(), nullptr, nullptr, -1, QString(),
761  QStringList(), QString(), QStringList(), 0, 0, QString(),
762  false, QStringList(), 0, 0, false);
763 
764  InfoMap metadataMap;
765  res.toMap(metadataMap);
766  SetTextFromMap(metadataMap);
767 
768  if (m_thumbImage)
769  {
770  if (!thumb.startsWith("http://"))
771  {
772  if (thumb.contains("%SHAREDIR%"))
773  thumb.replace("%SHAREDIR%", GetShareDir());
774 
775  bool exists = QFile::exists(thumb);
776 
777  if (exists)
778  {
779  m_thumbImage->SetFilename(thumb);
780  m_thumbImage->Load();
781  }
782  else
783  m_thumbImage->Reset();
784  }
785  else
786  {
787  const QString& url = thumb;
788  QString title2;
789  if (m_type == DLG_TREE)
790  title2 = m_siteMap->GetItemCurrent()->GetText();
791  else
792  title2 = m_siteButtonList->GetItemCurrent()->GetText();
793 
794  QString sFilename = GetDownloadFilename(title2, url);
795 
796  bool exists = QFile::exists(sFilename);
797  if (exists && !url.isEmpty())
798  {
799  m_thumbImage->SetFilename(sFilename);
800  m_thumbImage->Load();
801  }
802  else
803  m_thumbImage->Reset();
804  }
805  }
806 
807  if (m_downloadable)
809 }
810 
812 {
813  ResultItem *item = nullptr;
814  RSSSite *site = nullptr;
815 
816  if (m_type == DLG_TREE)
817  {
818  item = m_siteMap->GetCurrentNode()->GetData().value<ResultItem *>();
819  site = m_siteMap->GetCurrentNode()->GetData().value<RSSSite *>();
820  }
821  else
822  {
823  MythGenericTree *node =
824  GetNodePtrFromButton(m_siteButtonList->GetItemCurrent());
825 
826  if (!node)
827  return;
828 
829  item = node->GetData().value<ResultItem *>();
830  site = node->GetData().value<RSSSite *>();
831  }
832 
833  if (item)
834  UpdateResultItem(item);
835  else if (site)
836  UpdateSiteItem(site);
837  else
839 }
840 
842 {
844 
845  auto *treeedit = new TreeEditor(mainStack, "mythnettreeedit");
846 
847  if (treeedit->Create())
848  {
849  connect(treeedit, SIGNAL(ItemsChanged()), this, SLOT(DoTreeRefresh()));
850 
851  mainStack->AddScreen(treeedit);
852  }
853  else
854  delete treeedit;
855 }
856 
858 {
860 
861  auto *rssedit = new RSSEditor(mainStack, "mythnetrssedit");
862 
863  if (rssedit->Create())
864  {
865  connect(rssedit, SIGNAL(ItemsChanged()), this, SLOT(UpdateRSS()));
866 
867  mainStack->AddScreen(rssedit);
868  }
869  else
870  delete rssedit;
871 }
872 
874 {
875  CloseBusyPopup();
876 
877  TreeRefresh();
878 }
879 
881 {
882  delete m_siteGeneric;
883  m_siteGeneric = new MythGenericTree("site root", 0, false);
885 
888 
889  FillTree();
890  LoadData();
891  SwitchView();
892 }
893 
895 {
896  if (findAllDBRSS().isEmpty())
897  return;
898 
899  QString title(tr("Updating RSS. This could take a while..."));
900  OpenBusyPopup(title);
901 
902  auto *rssMan = new RSSManager();
903  connect(rssMan, SIGNAL(finished()), this, SLOT(DoTreeRefresh()));
904  rssMan->startTimer();
905  rssMan->doUpdate();
906 }
907 
909 {
910  if (m_grabberList.count() == 0)
911  return;
912 
913  QString title(tr("Updating Site Maps. This could take a while..."));
914  OpenBusyPopup(title);
915  m_gdt->refreshAll();
916 }
917 
919 {
921  gCoreContext->SaveBoolSetting("mythnetvision.rssBackgroundFetch",
923 }
924 
926 {
928  gCoreContext->SaveBoolSetting("mythnetvision.backgroundFetch",
930 }
931 
932 void NetTree::customEvent(QEvent *event)
933 {
934  if (event->type() == ThumbnailDLEvent::kEventType)
935  {
936  auto *tde = dynamic_cast<ThumbnailDLEvent *>(event);
937  if (!tde)
938  return;
939 
940  ThumbnailData *data = tde->m_thumb;
941  if (!data)
942  return;
943 
944  QString title = data->title;
945  QString file = data->url;
946  uint pos = data->data.value<uint>();
947 
948  if (file.isEmpty())
949  return;
950 
951  if (m_type == DLG_TREE)
952  {
953  if (title == m_siteMap->GetCurrentNode()->GetText() &&
954  m_thumbImage)
955  {
957  m_thumbImage->Load();
958  m_thumbImage->Show();
959  }
960  }
961  else
962  {
963  if (!((uint)m_siteButtonList->GetCount() >= pos))
964  return;
965 
967 
968  if (item && item->GetText() == title)
969  item->SetImage(file);
970  }
971  }
972  else
973  NetBase::customEvent(event);
974 }
975 
977 {
978  folder->SetText(QString("%1").arg(folder->visibleChildCount()),
979  "childcount");
980  folder->DisplayState("subfolder", "nodetype");
981 }
void TreeRefresh()
Definition: nettree.cpp:880
void RunTreeEditor(void)
Definition: nettree.cpp:841
bool m_treeAutoUpdate
Definition: nettree.h:98
MythGenericTree * GetCurrentNode(void) const
static const QString RSSNode
Definition: nettree.h:126
MythScreenStack * GetScreenStack() const
void StreamWebVideo(void)
Definition: netbase.cpp:87
MythGenericTree * getSelectedChild(bool onlyVisible=false) const
void Show(void)
void DoDownloadAndPlay(void)
Definition: netbase.cpp:280
static const QString SearchNode
Definition: nettree.h:127
MythGenericTree * addNode(const QString &a_string, int an_int=0, bool selectable_flag=false, bool visible=true)
uint visibleChildCount() const
RSSSite::rssList findAllDBRSS()
Definition: netutils.cpp:607
bool TranslateKeyPress(const QString &context, QKeyEvent *e, QStringList &actions, bool allowJumps=true)
Get a list of actions for a keypress in the given context.
uint m_updateFreq
Definition: nettree.h:96
QList< MythGenericTree * > * getAllChildren() const
MythUIText * m_noSites
Definition: nettree.h:89
GrabberDownloadThread * m_gdt
Definition: nettree.h:91
void SetText(const QString &text, const QString &name="", const QString &state="")
void SwitchBrowseView(void)
Definition: nettree.cpp:494
void SetData(QVariant data)
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
void HandleDirSelect(MythGenericTree *node)
Definition: nettree.cpp:329
void UpdateItem(MythUIButtonListItem *item)
Definition: nettree.cpp:211
void SaveSetting(const QString &key, int newValue)
void ShowMenu(void) override
Definition: nettree.cpp:397
void RunRSSEditor(void)
Definition: nettree.cpp:857
void UpdateTrees()
Definition: nettree.cpp:908
void finished(void)
void UpdateResultItem(ResultItem *item)
Definition: nettree.cpp:659
Basic menu dialog, message and a list of options.
int childCount(void) const
const QVariant GetData(void) const
int GetItemPos(MythUIButtonListItem *item) const
void UpdateRSS()
Definition: nettree.cpp:894
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
GrabberScript::scriptList findAllDBTreeGrabbers()
Definition: netutils.cpp:115
MythScreenStack * GetMainStack()
MythUIButtonListItem * GetItemAt(int pos) const
void customEvent(QEvent *levent) override
Definition: nettree.cpp:932
void DisplayState(const QString &state, const QString &name="")
void ShowWebVideo(void)
Definition: netbase.cpp:106
static MythThemedMenu * menu
static guint32 * tmp
Definition: goom_core.c:35
bool Load(bool allowLoadInBackground=true, bool forceStat=false)
Load the image(s), wraps ImageLoader::LoadImage()
void BuildFocusList(void)
void SetImage(MythImage *image, const QString &name="")
Sets an image directly, should only be used in special circumstances since it bypasses the cache.
MythMenu * CreateShowManageMenu(void)
Definition: nettree.cpp:458
MythUIButtonList * m_siteButtonList
Definition: nettree.h:85
GrabberScript::scriptList m_grabberList
Definition: netbase.h:52
QList< ResultItem * > resultList
Definition: rssparse.h:114
QString GetText(const QString &name="") const
void SlotItemChanged()
Definition: nettree.cpp:811
void SetTextFromMap(const InfoMap &infoMap, const QString &state="")
QMultiMap< QPair< QString, QString >, ResultItem * > getTreeArticles(const QString &feedtitle, ArticleType type)
Definition: netutils.cpp:460
virtual void SetVisible(bool visible)
void LoadInBackground(const QString &message="")
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
void SwitchView(void)
Definition: nettree.cpp:500
const QString & GetSortTitle() const
NetTree(DialogType type, MythScreenStack *parent, const char *name=nullptr)
Definition: nettree.cpp:47
QString GetDownloadFilename(const QString &title, const QString &url)
Definition: netutils.cpp:851
void SwitchTreeView(void)
Definition: nettree.cpp:482
DialogType
Definition: nettree.h:20
MythScreenStack * m_popupStack
Definition: netbase.h:47
ResultItem * GetStreamItem() override
Definition: nettree.cpp:642
const bool & GetDownloadable() const
Definition: rssparse.h:154
QString GetShareDir(void)
Definition: mythdirs.cpp:222
bool isRunning(void) const
Definition: mthread.cpp:274
void OpenBusyPopup(const QString &message="")
void Reset(void) override
Reset the image back to the default defined in the theme.
void BuildGenericTree(MythGenericTree *dst, QDomElement &domElem)
virtual void SetTextFromMap(const InfoMap &infoMap)
void FillTree(void)
Definition: nettree.cpp:517
GrabberScript::scriptList findAllDBTreeGrabbersByHost(ArticleType type)
Definition: netutils.cpp:149
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
const QString & GetImage() const
void DoTreeRefresh()
Definition: nettree.cpp:873
void SetText(const QString &text, const QString &name="", const QString &state="")
unsigned int uint
Definition: compat.h:140
MythUIImage * m_thumbImage
Definition: netbase.h:45
MythMenu * CreateShowViewMenu(void)
Definition: nettree.cpp:442
void SwitchGalleryView(void)
Definition: nettree.cpp:488
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
void UpdateSiteItem(RSSSite *site)
Definition: nettree.cpp:706
MythUIType * GetFocusWidget(void) const
const QString & GetURL() const
void Reset() override
Reset the widget to it's original state, should not reset changes made by the theme.
MythMainWindow * GetMythMainWindow(void)
DialogType m_type
Definition: nettree.h:94
QString GetText(const QString &name="") const
RSSSite::rssList m_rssList
Definition: nettree.h:92
MythUIButtonTree * m_siteMap
Definition: nettree.h:84
int getInt() const
int GetNumSetting(const QString &key, int defaultval=0)
bool keyPressEvent(QKeyEvent *) override
Key event handler.
Definition: nettree.cpp:360
bool keyPressEvent(QKeyEvent *) override
Key event handler.
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
void LoadData(void) override
Definition: nettree.cpp:162
void CloseBusyPopup(void)
const QString & GetTitle() const
bool GetBoolSetting(const QString &key, bool defaultval=false)
virtual void PopScreen(MythScreenType *screen=nullptr, bool allowFade=true, bool deleteScreen=true)
void customEvent(QEvent *event) override
Definition: netbase.cpp:221
void ToggleRSSUpdates()
Definition: nettree.cpp:918
const QString & GetAuthor() const
MythGenericTree * getChildByName(const QString &a_name) const
void UpdateCurrentItem(void)
Definition: nettree.cpp:733
const QString & GetDescription() const
void SetCurrentNode(MythGenericTree *node)
Definition: nettree.cpp:140
MythUIButtonListItem * GetItemCurrent(void) const
Return the currently selected list item.
void SetFilename(const QString &filename)
Must be followed by a call to Load() to load the image.
const QString & GetTitle() const
Definition: rssparse.h:134
void addThumb(QString title, QString url, QVariant data)
bool AssignTree(MythGenericTree *tree)
Assign the root node of the tree to be displayed.
MetadataImageDownload * m_imageDownload
Definition: netbase.h:49
void Load() override
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
Definition: nettree.cpp:132
static void SetSubfolderData(MythGenericTree *folder)
Definition: nettree.cpp:976
QList< ResultItem * > m_videos
Definition: nettree.h:82
MythUIStateType * m_downloadable
Definition: netbase.h:46
void SetData(QVariant data)
bool m_rssAutoUpdate
Definition: nettree.h:97
QString GetThumbnailFilename(const QString &url, const QString &title)
Definition: netcommon.cpp:9
bool DisplayState(const QString &name)
void startTimer()
~NetTree()
Definition: nettree.cpp:148
MythGenericTree * getParent(void) const
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
static const QString DownloadNode
Definition: nettree.h:128
void SetItemCurrent(MythUIButtonListItem *item)
bool GoBack()
Definition: nettree.cpp:338
bool SetFocusWidget(MythUIType *widget=nullptr)
void HandleSelect(MythUIButtonListItem *item)
Definition: nettree.cpp:305
MythGenericTree * m_siteGeneric
Definition: nettree.h:86
ResultItem::resultList getRSSArticles(const QString &feedtitle, ArticleType type)
Definition: netutils.cpp:794
void SaveBoolSetting(const QString &key, bool newValue)
void ToggleTreeUpdates()
Definition: nettree.cpp:925
void AddFileNode(MythGenericTree *where_to_add, ResultItem *video)
Definition: nettree.cpp:628
void DisplayState(const QString &state, const QString &name)
void SetTextFromMap(const InfoMap &infoMap, const QString &state="")
QString getDownloadFilename(const QString &title, const QString &url)
const QString & GetThumbnail() const
Definition: rssparse.h:140
bool Create(void) override
Definition: nettree.cpp:60
MythGenericTree * m_currentNode
Definition: nettree.h:87
MythUIButtonListItem * GetItemCurrent() const
std::shared_ptr< MythSortHelper > getMythSortHelper(void)
Get a pointer to the MythSortHelper singleton.
void toMap(InfoMap &metadataMap)
Definition: rssparse.cpp:76
ArticleType m_type