MythTV  master
editvideometadata.cpp
Go to the documentation of this file.
1 #include <algorithm>
2 
3 #include <QImageReader>
4 #include <QUrl>
5 
6 #include <mythcontext.h>
7 #include <mythdirs.h>
8 
9 #include "mythmainwindow.h"
10 #include "mythdialogbox.h"
11 #include "mythuibuttonlist.h"
12 #include "mythuitext.h"
13 #include "mythuitextedit.h"
14 #include "mythuibutton.h"
15 #include "mythuicheckbox.h"
16 #include "mythuispinbox.h"
17 #include "mythuiimage.h"
18 #include "mythuifilebrowser.h"
19 #include "mythuiimageresults.h"
20 #include "mythuihelper.h"
21 #include "mythprogressdialog.h"
22 #include "mythmiscutil.h"
23 #include "remoteutil.h"
24 #include "globals.h"
25 #include "dbaccess.h"
27 #include "videoutils.h"
28 
29 #include "editvideometadata.h"
30 #include "metadatafactory.h"
31 
32 //static const QString _Location = QObject::tr("Metadata Editor");
33 
35  const QString& lname, VideoMetadata *source_metadata,
36  const VideoMetadataListManager &cache) : MythScreenType(lparent, lname),
37  m_origMetadata(source_metadata),
38  m_metaCache(cache)
39 {
40  m_query = new MetadataDownload(this);
43 
44  m_popupStack = GetMythMainWindow()->GetStack("popup stack");
45 }
46 
48 {
49  delete m_workingMetadata;
50 }
51 
53 {
54  if (!LoadWindowFromXML("video-ui.xml", "edit_metadata", this))
55  return false;
56 
57  bool err = false;
58  UIUtilE::Assign(this, m_titleEdit, "title_edit", &err);
59  UIUtilE::Assign(this, m_subtitleEdit, "subtitle_edit", &err);
60  UIUtilE::Assign(this, m_playerEdit, "player_edit", &err);
61 
62  UIUtilE::Assign(this, m_seasonSpin, "season", &err);
63  UIUtilE::Assign(this, m_episodeSpin, "episode", &err);
64 
65 
66  UIUtilE::Assign(this, m_categoryList, "category_select", &err);
67  UIUtilE::Assign(this, m_levelList, "level_select", &err);
68  UIUtilE::Assign(this, m_childList, "child_select", &err);
69 
70  UIUtilE::Assign(this, m_browseCheck, "browse_check", &err);
71  UIUtilE::Assign(this, m_watchedCheck, "watched_check", &err);
72 
73  UIUtilE::Assign(this, m_doneButton, "done_button", &err);
74 
75  if (err)
76  {
77  LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'edit_metadata'");
78  return false;
79  }
80 
81  UIUtilW::Assign(this, m_coverartText, "coverart_text");
82  UIUtilW::Assign(this, m_screenshotText, "screenshot_text");
83  UIUtilW::Assign(this, m_bannerText, "banner_text");
84  UIUtilW::Assign(this, m_fanartText, "fanart_text");
85  UIUtilW::Assign(this, m_trailerText, "trailer_text");
86 
87  UIUtilW::Assign(this, m_coverartButton, "coverart_button");
88  UIUtilW::Assign(this, m_bannerButton, "banner_button");
89  UIUtilW::Assign(this, m_fanartButton, "fanart_button");
90  UIUtilW::Assign(this, m_screenshotButton, "screenshot_button");
91  UIUtilW::Assign(this, m_trailerButton, "trailer_button");
92 
93  UIUtilW::Assign(this, m_netBannerButton, "net_banner_button");
94  UIUtilW::Assign(this, m_netFanartButton, "net_fanart_button");
95  UIUtilW::Assign(this, m_netScreenshotButton, "net_screenshot_button");
96  UIUtilW::Assign(this, m_netCoverartButton, "net_coverart_button");
97 
98  UIUtilW::Assign(this, m_taglineEdit, "tagline_edit");
99  UIUtilW::Assign(this, m_ratingEdit, "rating_edit");
100  UIUtilW::Assign(this, m_directorEdit, "director_edit");
101  UIUtilW::Assign(this, m_inetrefEdit, "inetref_edit");
102  UIUtilW::Assign(this, m_homepageEdit, "homepage_edit");
103  UIUtilW::Assign(this, m_plotEdit, "description_edit");
104  UIUtilW::Assign(this, m_yearSpin, "year_spin");
105  UIUtilW::Assign(this, m_userRatingSpin, "userrating_spin");
106  UIUtilW::Assign(this, m_lengthSpin, "length_spin");
107 
108  UIUtilW::Assign(this, m_coverart, "coverart");
109  UIUtilW::Assign(this, m_screenshot, "screenshot");
110  UIUtilW::Assign(this, m_banner, "banner");
111  UIUtilW::Assign(this, m_fanart, "fanart");
112 
113  fillWidgets();
114 
115  BuildFocusList();
116 
117  connect(m_titleEdit, SIGNAL(valueChanged()), SLOT(SetTitle()));
119  connect(m_subtitleEdit, SIGNAL(valueChanged()), SLOT(SetSubtitle()));
121  connect(m_playerEdit, SIGNAL(valueChanged()), SLOT(SetPlayer()));
122  if (m_taglineEdit)
123  {
124  connect(m_taglineEdit, SIGNAL(valueChanged()), SLOT(SetTagline()));
126  }
127  if (m_ratingEdit)
128  {
129  connect(m_ratingEdit, SIGNAL(valueChanged()), SLOT(SetRating()));
131  }
132  if (m_directorEdit)
133  {
134  connect(m_directorEdit, SIGNAL(valueChanged()), SLOT(SetDirector()));
136  }
137  if (m_inetrefEdit)
138  connect(m_inetrefEdit, SIGNAL(valueChanged()), SLOT(SetInetRef()));
139  if (m_homepageEdit)
140  {
141  connect(m_homepageEdit, SIGNAL(valueChanged()), SLOT(SetHomepage()));
143  }
144  if (m_plotEdit)
145  {
146  connect(m_plotEdit, SIGNAL(valueChanged()), SLOT(SetPlot()));
148  }
149 
150  connect(m_seasonSpin, SIGNAL(LosingFocus()), SLOT(SetSeason()));
151  connect(m_episodeSpin, SIGNAL(LosingFocus()), SLOT(SetEpisode()));
152  if (m_yearSpin)
153  connect(m_yearSpin, SIGNAL(LosingFocus()), SLOT(SetYear()));
154  if (m_userRatingSpin)
155  connect(m_userRatingSpin, SIGNAL(LosingFocus()), SLOT(SetUserRating()));
156  if (m_lengthSpin)
157  connect(m_lengthSpin, SIGNAL(LosingFocus()), SLOT(SetLength()));
158 
159  connect(m_doneButton, SIGNAL(Clicked()), SLOT(SaveAndExit()));
160 
161  // Find Artwork locally
162  if (m_coverartButton)
163  connect(m_coverartButton, SIGNAL(Clicked()), SLOT(FindCoverArt()));
164  if (m_bannerButton)
165  connect(m_bannerButton, SIGNAL(Clicked()), SLOT(FindBanner()));
166  if (m_fanartButton)
167  connect(m_fanartButton, SIGNAL(Clicked()), SLOT(FindFanart()));
168  if (m_screenshotButton)
169  connect(m_screenshotButton, SIGNAL(Clicked()), SLOT(FindScreenshot()));
170 
171  // Find Artwork on the Internet
173  connect(m_netCoverartButton, SIGNAL(Clicked()), SLOT(FindNetCoverArt()));
174  if (m_netBannerButton)
175  connect(m_netBannerButton, SIGNAL(Clicked()), SLOT(FindNetBanner()));
176  if (m_netFanartButton)
177  connect(m_netFanartButton, SIGNAL(Clicked()), SLOT(FindNetFanart()));
179  connect(m_netScreenshotButton, SIGNAL(Clicked()), SLOT(FindNetScreenshot()));
180 
181  if (m_trailerButton)
182  connect(m_trailerButton, SIGNAL(Clicked()), SLOT(FindTrailer()));
183 
184  connect(m_browseCheck, SIGNAL(valueChanged()), SLOT(ToggleBrowse()));
185  connect(m_watchedCheck, SIGNAL(valueChanged()), SLOT(ToggleWatched()));
186 
187  connect(m_childList, SIGNAL(itemSelected(MythUIButtonListItem*)),
189  connect(m_levelList, SIGNAL(itemSelected(MythUIButtonListItem*)),
191  connect(m_categoryList, SIGNAL(itemSelected(MythUIButtonListItem*)),
193  connect(m_categoryList, SIGNAL(itemClicked(MythUIButtonListItem*)),
194  SLOT(NewCategoryPopup()));
195 
196  return true;
197 }
198 
199 namespace
200 {
201  template <typename T>
202  struct title_sort
203  {
204  bool operator()(const T &lhs, const T &rhs)
205  {
206  return naturalCompare(lhs.second, rhs.second) < 0;
207  }
208  };
209 
210  QStringList GetSupportedImageExtensionFilter()
211  {
212  QStringList ret;
213 
214  QList<QByteArray> exts = QImageReader::supportedImageFormats();
215  for (QList<QByteArray>::iterator p = exts.begin(); p != exts.end(); ++p)
216  {
217  ret.append(QString("*.").append(*p));
218  }
219 
220  return ret;
221  }
222 
223  void FindImagePopup(const QString &prefix, const QString &prefixAlt,
224  QObject &inst, const QString &returnEvent)
225  {
226  QString fp;
227 
228  if (prefix.startsWith("myth://"))
229  fp = prefix;
230  else
231  fp = prefix.isEmpty() ? prefixAlt : prefix;
232 
233  MythScreenStack *popupStack =
234  GetMythMainWindow()->GetStack("popup stack");
235 
236  MythUIFileBrowser *fb = new MythUIFileBrowser(popupStack, fp);
237  fb->SetNameFilter(GetSupportedImageExtensionFilter());
238  if (fb->Create())
239  {
240  fb->SetReturnEvent(&inst, returnEvent);
241  popupStack->AddScreen(fb);
242  }
243  else
244  delete fb;
245  }
246 
247  void FindVideoFilePopup(const QString &prefix, const QString &prefixAlt,
248  QObject &inst, const QString &returnEvent)
249  {
250  QString fp;
251 
252  if (prefix.startsWith("myth://"))
253  fp = prefix;
254  else
255  fp = prefix.isEmpty() ? prefixAlt : prefix;
256 
257  MythScreenStack *popupStack =
258  GetMythMainWindow()->GetStack("popup stack");
259  QStringList exts;
260 
261  const FileAssociations::association_list fa_list =
263  for (FileAssociations::association_list::const_iterator p =
264  fa_list.begin(); p != fa_list.end(); ++p)
265  {
266  exts << QString("*.%1").arg(p->extension.toUpper());
267  }
268 
269  MythUIFileBrowser *fb = new MythUIFileBrowser(popupStack, fp);
270  fb->SetNameFilter(exts);
271  if (fb->Create())
272  {
273  fb->SetReturnEvent(&inst, returnEvent);
274  popupStack->AddScreen(fb);
275  }
276  else
277  delete fb;
278  }
279 
280  const QString CEID_COVERARTFILE = "coverartfile";
281  const QString CEID_BANNERFILE = "bannerfile";
282  const QString CEID_FANARTFILE = "fanartfile";
283  const QString CEID_SCREENSHOTFILE = "screenshotfile";
284  const QString CEID_TRAILERFILE = "trailerfile";
285  const QString CEID_NEWCATEGORY = "newcategory";
286 }
287 
288 void EditMetadataDialog::createBusyDialog(const QString& title)
289 {
290  if (m_busyPopup)
291  return;
292 
293  const QString& message = title;
294 
296  "mythvideobusydialog");
297 
298  if (m_busyPopup->Create())
300 }
301 
303 {
306 
307  m_seasonSpin->SetRange(0,9999,1,5);
309  m_episodeSpin->SetRange(0,999,1,10);
311  if (m_yearSpin)
312  {
313  m_yearSpin->SetRange(0,9999,1,100);
315  }
316  if (m_userRatingSpin)
317  {
318  m_userRatingSpin->SetRange(0,10,1,2);
320  }
321  if (m_lengthSpin)
322  {
323  m_lengthSpin->SetRange(0,999,1,15);
325  }
326 
327  // No memory leak. MythUIButtonListItem adds the new item into
328  // m_categoryList.
329  MythUIButtonListItem *button =
331  const VideoCategory::entry_list &vcl =
333  for (VideoCategory::entry_list::const_iterator p = vcl.begin();
334  p != vcl.end(); ++p)
335  {
336  // No memory leak. MythUIButtonListItem adds the new item into
337  // m_categoryList.
338  button = new MythUIButtonListItem(m_categoryList, p->second);
339  button->SetData(p->first);
340  }
342 
344  i <= ParentalLevel::plHigh && i.good(); ++i)
345  {
346  // No memory leak. MythUIButtonListItem adds the new item into
347  // m_levelList.
348  button = new MythUIButtonListItem(m_levelList,
349  tr("Level %1").arg(i.GetLevel()));
350  button->SetData(i.GetLevel());
351  }
353 
354  //
355  // Fill the "always play this video next" option
356  // with all available videos.
357  //
358 
359  // No memory leak. MythUIButtonListItem adds the new item into
360  // m_childList.
361  // cppcheck-suppress unreadVariable
362  button = new MythUIButtonListItem(m_childList,tr("None"));
363 
364  // TODO: maybe make the title list have the same sort order
365  // as elsewhere.
366  typedef std::vector<std::pair<unsigned int, QString> > title_list;
368  title_list tc;
369  tc.reserve(mdl.size());
370  for (VideoMetadataListManager::metadata_list::const_iterator p = mdl.begin();
371  p != mdl.end(); ++p)
372  {
373  QString title;
374  if ((*p)->GetSeason() > 0 || (*p)->GetEpisode() > 0)
375  title = QString("%1 %2x%3").arg((*p)->GetTitle())
376  .arg(QString::number((*p)->GetSeason()))
377  .arg(QString::number((*p)->GetEpisode()));
378  else
379  title = (*p)->GetTitle();
380  tc.push_back(std::make_pair((*p)->GetID(), title));
381  }
382  std::sort(tc.begin(), tc.end(), title_sort<title_list::value_type>());
383 
384  for (title_list::const_iterator p = tc.begin(); p != tc.end(); ++p)
385  {
386  if (p->first != m_workingMetadata->GetID())
387  {
388  button = new MythUIButtonListItem(m_childList,p->second);
389  button->SetData(p->first);
390  }
391  }
392 
393  if (m_workingMetadata->GetChildID() > 0)
394  {
397  }
398 
403  if (m_coverartText)
405  if (m_screenshotText)
407  if (m_bannerText)
409  if (m_fanartText)
411  if (m_trailerText)
413 
415  if (m_taglineEdit)
417  if (m_ratingEdit)
419  if (m_directorEdit)
421  if (m_inetrefEdit)
423  if (m_homepageEdit)
425  if (m_plotEdit)
427 
428  if (m_coverart)
429  {
430  if (!m_workingMetadata->GetHost().isEmpty() &&
431  !m_workingMetadata->GetCoverFile().isEmpty() &&
432  !m_workingMetadata->GetCoverFile().startsWith("/"))
433  {
437  }
438  else
440 
441  if (!m_workingMetadata->GetCoverFile().isEmpty())
442  m_coverart->Load();
443  }
444  if (m_screenshot)
445  {
446  if (!m_workingMetadata->GetHost().isEmpty() &&
447  !m_workingMetadata->GetScreenshot().isEmpty() &&
448  !m_workingMetadata->GetScreenshot().startsWith("/"))
449  {
453  }
454  else
456 
457  if (!m_workingMetadata->GetScreenshot().isEmpty())
458  m_screenshot->Load();
459  }
460  if (m_banner)
461  {
462  if (!m_workingMetadata->GetHost().isEmpty() &&
463  !m_workingMetadata->GetBanner().isEmpty() &&
464  !m_workingMetadata->GetBanner().startsWith("/"))
465  {
469  }
470  else
472 
473  if (!m_workingMetadata->GetBanner().isEmpty())
474  m_banner->Load();
475  }
476  if (m_fanart)
477  {
478  if (!m_workingMetadata->GetHost().isEmpty() &&
479  !m_workingMetadata->GetFanart().isEmpty() &&
480  !m_workingMetadata->GetFanart().startsWith("/"))
481  {
485  }
486  else
488 
489  if (!m_workingMetadata->GetFanart().isEmpty())
490  m_fanart->Load();
491  }
492 }
493 
495 {
496  QString message = tr("Enter new category");
497 
498  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
499 
500  MythTextInputDialog *categorydialog =
501  new MythTextInputDialog(popupStack,message);
502 
503  if (categorydialog->Create())
504  {
505  categorydialog->SetReturnEvent(this, CEID_NEWCATEGORY);
506  popupStack->AddScreen(categorydialog);
507  }
508 
509 }
510 
511 void EditMetadataDialog::AddCategory(const QString& category)
512 {
513  int id = VideoCategory::GetCategory().add(category);
515  new MythUIButtonListItem(m_categoryList, category, id);
517 }
518 
520 {
523 
524  emit Finished();
525  Close();
526 }
527 
529 {
531 }
532 
534 {
536 }
537 
539 {
540  m_workingMetadata->SetCategoryID(item->GetData().toInt());
541 }
542 
544 {
546 }
547 
549 {
551 }
552 
554 {
556 }
557 
559 {
561 }
562 
564 {
566 }
567 
569 {
571 }
572 
574 {
576 }
577 
579 {
581 }
582 
584 {
586 }
587 
589 {
591 }
592 
594 {
596 }
597 
599 {
601 }
602 
604 {
606  SetShowLevel(ParentalLevel(item->GetData().toInt()).GetLevel());
607 }
608 
610 {
611  cachedChildSelection = item->GetData().toInt();
613 }
614 
616 {
618  SetBrowse(m_browseCheck->GetBooleanCheckState());
619 }
620 
622 {
624  SetWatched(m_watchedCheck->GetBooleanCheckState());
625 }
626 
628 {
629  if (!m_workingMetadata->GetHost().isEmpty())
630  {
631  QString url = generate_file_url("Coverart",
633  "");
634  FindImagePopup(url,"",
635  *this, CEID_COVERARTFILE);
636  }
637  else
638  FindImagePopup(gCoreContext->GetSetting("VideoArtworkDir"),
639  GetConfDir() + "/MythVideo",
640  *this, CEID_COVERARTFILE);
641 }
642 
644 {
645  if (!lookup)
646  return;
647 
648  if (m_busyPopup)
649  {
650  m_busyPopup->Close();
651  m_busyPopup = nullptr;
652  }
653 
654  VideoArtworkType type = lookup->GetData().value<VideoArtworkType>();
655  ArtworkList list = lookup->GetArtwork(type);
656 
657  if (list.isEmpty())
658  {
659  MythWarningNotification n(tr("No image found"), tr("Metadata Editor"));
661  return;
662  }
663  ImageSearchResultsDialog *resultsdialog =
665 
666  connect(resultsdialog, SIGNAL(haveResult(ArtworkInfo, VideoArtworkType)),
668 
669  if (resultsdialog->Create())
670  m_popupStack->AddScreen(resultsdialog);
671 }
672 
674 {
675  QString msg = tr("Downloading selected artwork...");
676  createBusyDialog(msg);
677 
678  MetadataLookup *lookup = new MetadataLookup();
679  lookup->SetType(kMetadataVideo);
680 
682  lookup->SetHost(m_workingMetadata->GetHost());
683  lookup->SetAutomatic(true);
684  lookup->SetData(qVariantFromValue<VideoArtworkType>(type));
685 
686  ArtworkMap downloads;
687  downloads.insert(type, info);
688  lookup->SetDownloads(downloads);
689  lookup->SetAllowOverwrites(true);
690  lookup->SetTitle(m_workingMetadata->GetTitle());
695 
696  m_imageDownload->addDownloads(lookup);
697 }
698 
700 {
701  if (!lookup)
702  return;
703 
704  if (m_busyPopup)
705  {
706  m_busyPopup->Close();
707  m_busyPopup = nullptr;
708  }
709 
710  VideoArtworkType type = lookup->GetData().value<VideoArtworkType>();
711  ArtworkMap map = lookup->GetDownloads();
712 
713  if (map.count() >= 1)
714  {
715  ArtworkInfo info = map.value(type);
716  QString filename = info.url;
717 
718  if (type == kArtworkCoverart)
719  SetCoverArt(filename);
720  else if (type == kArtworkFanart)
721  SetFanart(filename);
722  else if (type == kArtworkBanner)
723  SetBanner(filename);
724  else if (type == kArtworkScreenshot)
725  SetScreenshot(filename);
726  }
727 }
728 
730 {
731  QString msg = tr("Searching for available artwork...");
732  createBusyDialog(msg);
733 
734  MetadataLookup *lookup = new MetadataLookup();
735  lookup->SetStep(kLookupSearch);
736  lookup->SetType(kMetadataVideo);
737  lookup->SetAutomatic(true);
738  if (m_workingMetadata->GetSeason() > 0 ||
741  else if (m_workingMetadata->GetSubtitle().isEmpty())
742  lookup->SetSubtype(kProbableMovie);
743  else
744  lookup->SetSubtype(kUnknownVideo);
745  lookup->SetData(qVariantFromValue<VideoArtworkType>(type));
746 
747  lookup->SetTitle(m_workingMetadata->GetTitle());
752 
753  m_query->addLookup(lookup);
754 }
755 
757 {
759 }
760 
762 {
764 }
765 
767 {
769 }
770 
772 {
774 }
775 
777 {
778  if (file.isEmpty())
779  return;
780 
781  QString origfile = file;
782 
783  if (file.startsWith("myth://"))
784  {
785  QUrl url(file);
786  file = url.path();
787  file = file.right(file.length() - 1);
788  if (!file.endsWith("/"))
790  else
791  m_workingMetadata->SetCoverFile(QString());
792  }
793  else
795 
796  CheckedSet(m_coverartText, file);
797 
798  if (m_coverart)
799  {
800  m_coverart->SetFilename(origfile);
801  m_coverart->Load();
802  }
803 }
804 
806 {
807  if (!m_workingMetadata->GetHost().isEmpty())
808  {
809  QString url = generate_file_url("Banners",
811  "");
812  FindImagePopup(url,"",
813  *this, CEID_BANNERFILE);
814  }
815  else
816  FindImagePopup(gCoreContext->GetSetting("mythvideo.bannerDir"),
817  GetConfDir() + "/MythVideo/Banners",
818  *this, CEID_BANNERFILE);
819 }
820 
822 {
823  if (file.isEmpty())
824  return;
825 
826  QString origfile = file;
827 
828  if (file.startsWith("myth://"))
829  {
830  QUrl url(file);
831  file = url.path();
832  file = file.right(file.length() - 1);
833  if (!file.endsWith("/"))
835  else
836  m_workingMetadata->SetBanner(QString());
837  }
838  else
840 
841  CheckedSet(m_bannerText, file);
842 
843  if (m_banner)
844  {
845  m_banner->SetFilename(origfile);
846  m_banner->Load();
847  }
848 }
849 
851 {
852  if (!m_workingMetadata->GetHost().isEmpty())
853  {
854  QString url = generate_file_url("Fanart",
856  "");
857  FindImagePopup(url,"",
858  *this, CEID_FANARTFILE);
859  }
860  else
861  FindImagePopup(gCoreContext->GetSetting("mythvideo.fanartDir"),
862  GetConfDir() + "/MythVideo/Fanart",
863  *this, CEID_FANARTFILE);
864 }
865 
867 {
868  if (file.isEmpty())
869  return;
870 
871  QString origfile = file;
872 
873  if (file.startsWith("myth://"))
874  {
875  QUrl url(file);
876  file = url.path();
877  file = file.right(file.length() - 1);
878  if (!file.endsWith("/"))
880  else
881  m_workingMetadata->SetFanart(QString());
882  }
883  else
885 
886  CheckedSet(m_fanartText, file);
887 
888  if (m_fanart)
889  {
890  m_fanart->SetFilename(origfile);
891  m_fanart->Load();
892  }
893 }
894 
896 {
897  if (!m_workingMetadata->GetHost().isEmpty())
898  {
899  QString url = generate_file_url("Screenshots",
901  "");
902  FindImagePopup(url,"",
903  *this, CEID_SCREENSHOTFILE);
904  }
905  else
906  FindImagePopup(gCoreContext->GetSetting("mythvideo.screenshotDir"),
907  GetConfDir() + "/MythVideo/Screenshots",
908  *this, CEID_SCREENSHOTFILE);
909 }
910 
912 {
913  if (file.isEmpty())
914  return;
915 
916  QString origfile = file;
917 
918  if (file.startsWith("myth://"))
919  {
920  QUrl url(file);
921  file = url.path();
922  file = file.right(file.length() - 1);
923  if (!file.endsWith("/"))
925  else
926  m_workingMetadata->SetScreenshot(QString());
927  }
928  else
930 
932 
933  if (m_screenshot)
934  {
935  m_screenshot->SetFilename(origfile);
936  m_screenshot->Load();
937  }
938 }
939 
941 {
942  if (!m_workingMetadata->GetHost().isEmpty())
943  {
944  QString url = generate_file_url("Trailers",
946  "");
947  FindVideoFilePopup(url,"",
948  *this, CEID_TRAILERFILE);
949  }
950  else
951  FindVideoFilePopup(gCoreContext->GetSetting("mythvideo.TrailersDir"),
952  GetConfDir() + "/MythVideo/Trailers",
953  *this, CEID_TRAILERFILE);
954 }
955 
957 {
958  if (file.isEmpty())
959  return;
960 
961  if (file.startsWith("myth://"))
962  {
963  QUrl url(file);
964  file = url.path();
965  file = file.right(file.length() - 1);
966  if (!file.endsWith("/"))
968  else
969  m_workingMetadata->SetTrailer(QString());
970  }
971  else
973  CheckedSet(m_trailerText, file);
974 }
975 
977 {
978  if (levent->type() == DialogCompletionEvent::kEventType)
979  {
981 
982  const QString resultid = dce->GetId();
983 
984  if (resultid == CEID_COVERARTFILE)
985  SetCoverArt(dce->GetResultText());
986  else if (resultid == CEID_BANNERFILE)
987  SetBanner(dce->GetResultText());
988  else if (resultid == CEID_FANARTFILE)
989  SetFanart(dce->GetResultText());
990  else if (resultid == CEID_SCREENSHOTFILE)
992  else if (resultid == CEID_TRAILERFILE)
993  SetTrailer(dce->GetResultText());
994  else if (resultid == CEID_NEWCATEGORY)
995  AddCategory(dce->GetResultText());
996  }
997  else if (levent->type() == MetadataLookupEvent::kEventType)
998  {
999  MetadataLookupEvent *lue = (MetadataLookupEvent *)levent;
1000 
1001  MetadataLookupList lul = lue->m_lookupList;
1002 
1003  if (lul.isEmpty())
1004  return;
1005 
1006  // There should really only be one result here.
1007  // If not, USER ERROR!
1008  if (lul.count() == 1)
1009  {
1010  OnArtworkSearchDone(lul[0]);
1011  }
1012  else
1013  {
1014  if (m_busyPopup)
1015  {
1016  m_busyPopup->Close();
1017  m_busyPopup = nullptr;
1018  }
1019  }
1020  }
1021  else if (levent->type() == MetadataLookupFailure::kEventType)
1022  {
1024 
1025  MetadataLookupList lul = luf->m_lookupList;
1026 
1027  if (m_busyPopup)
1028  {
1029  m_busyPopup->Close();
1030  m_busyPopup = nullptr;
1031  }
1032 
1033  if (!lul.empty())
1034  {
1035  MetadataLookup *lookup = lul[0];
1036  LOG(VB_GENERAL, LOG_INFO,
1037  QString("No results found for %1 %2 %3").arg(lookup->GetTitle())
1038  .arg(lookup->GetSeason()).arg(lookup->GetEpisode()));
1039  }
1040  }
1041  else if (levent->type() == ImageDLEvent::kEventType)
1042  {
1043  ImageDLEvent *ide = (ImageDLEvent *)levent;
1044 
1045  MetadataLookup *lookup = ide->m_item;
1046 
1047  if (!lookup)
1048  return;
1049 
1050  handleDownloadedImages(lookup);
1051  }
1052  else if (levent->type() == ImageDLFailureEvent::kEventType)
1053  {
1054  MythErrorNotification n(tr("Failed to retrieve image"),
1055  tr("Metadata Editor"),
1056  tr("Check logs"));
1058  }
1059 }
MythUIImage * m_screenshot
void SetHomepage(const QString &homepage)
void FindNetArt(VideoArtworkType type)
MythUIButton * m_screenshotButton
void SetTitle(const QString &title)
MythUICheckBox * m_watchedCheck
void SetTrailer(QString file)
void SetSubtitle(const QString &subtitle, const QString &sortSubtitle="")
int GetLength() const
ArtworkList GetArtwork(VideoArtworkType type) const
MythUIText * m_fanartText
bool GetWatched() const
void SetSubtitle(const QString &subtitle)
void SetAutomatic(bool autom)
void SetFanart(QString file)
void SetUserRating(float userRating)
MythUITextEdit * m_homepageEdit
const metadata_list & getList() const
MythUITextEdit * m_ratingEdit
const QString & GetPlayCommand() const
void SetTrailer(const QString &trailer)
void LosingFocus()
int GetSeason() const
const QString & GetFanart() const
EditMetadataDialog(MythScreenStack *lparent, const QString &lname, VideoMetadata *source_metadata, const VideoMetadataListManager &cache)
void SetBanner(QString file)
MythUIText * m_screenshotText
void SetData(QVariant data)
MythScreenStack * m_popupStack
MythUISpinBox * m_seasonSpin
void SetFanart(const QString &fanart)
std::vector< file_association > association_list
Definition: dbaccess.h:153
void SetRating(const QString &rating)
void SetInetref(const QString &inetref)
const association_list & getList() const
Definition: dbaccess.cpp:811
void SetData(QVariant data)
void SetAllowOverwrites(bool allow)
LookupType GuessLookupType(ProgramInfo *pginfo)
void SetReturnEvent(QObject *retobject, const QString &resultid)
VideoArtworkType
MythUICheckBox * m_browseCheck
MythUIButton * m_netBannerButton
MythUITextEdit * m_taglineEdit
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:136
bool Create(void) override
void customEvent(QEvent *levent) override
const QString & GetDirector() const
int add(const QString &name)
Definition: dbaccess.cpp:217
const QString & GetBanner() const
MythUIText * m_bannerText
const QString VIDEO_CATEGORY_UNKNOWN
Definition: globals.cpp:7
MythScreenStack * GetStack(const QString &stackname)
void SetDirector(const QString &director)
MetadataImageDownload * m_imageDownload
MythUIButton * m_netFanartButton
MythUIImage * m_banner
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
void SetValue(int val) override
Definition: mythuispinbox.h:26
static VideoCategory & GetCategory()
Definition: dbaccess.cpp:492
MythUIButton * m_trailerButton
void AddCategory(const QString &category)
void handleDownloadedImages(MetadataLookup *lookup)
MythUIButton * m_netScreenshotButton
MythUIButton * m_coverartButton
void SetPlayCommand(const QString &playCommand)
bool Load(bool allowLoadInBackground=true, bool forceStat=false)
Load the image(s), wraps ImageLoader::LoadImage()
void BuildFocusList(void)
unsigned int GetID() const
void SetYear(int year)
static Type kEventType
Definition: mythdialogbox.h:50
void SetTagline(const QString &tagline)
const QString & GetTrailer() const
int GetIntValue(void) const override
Definition: mythuispinbox.h:33
MythUISpinBox * m_yearSpin
void CheckedSet(MythUIStateType *uiItem, const QString &state)
Definition: videoutils.cpp:44
std::vector< entry > entry_list
Definition: dbaccess.h:15
MythUITextEdit * m_titleEdit
uint GetSeason() const
QString GetTitle() const
const QString & GetHomepage() const
void SetStep(LookupStep step)
QString GetConfDir(void)
Definition: mythdirs.cpp:224
void SetNameFilter(QStringList filter)
virtual void Close()
ParentalLevel::Level GetShowLevel() const
int GetYear() const
uint GetEpisode() const
VideoMetadata * m_workingMetadata
MetadataDownload * m_query
void SetRange(int low, int high, int step, uint pageMultiple=5)
Set the lower and upper bounds of the spinbox, the interval and page amount.
void SetLevel(MythUIButtonListItem *)
bool Create(void) override
void SetCoverFile(const QString &coverFile)
bool GetBooleanCheckState(void) const
MythUITextEdit * m_plotEdit
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
const QString & GetTagline() const
void SetMaxLength(const int length)
void SetChildID(int childID)
float GetUserRating() const
void OnArtworkSearchDone(MetadataLookup *lookup)
MythUIButton * m_bannerButton
bool Create(void) override
const QString & GetPlot() const
void SetScreenshot(QString file)
int GetEpisode() const
MetadataLookupList m_lookupList
int GetChildID() const
QString GetSetting(const QString &key, const QString &defaultval="")
void SetEpisode(int episode)
void SetReturnEvent(QObject *retobject, const QString &resultid)
void addDownloads(MetadataLookup *lookup)
addLookup: Add lookup to bottom of the queue MetadataDownload::m_downloadList takes ownership of the ...
MythUIButtonList * m_levelList
MythUIBusyDialog * m_busyPopup
MythUIButton * m_fanartButton
MythUIButton * m_netCoverartButton
MythUIButtonList * m_categoryList
bool Queue(const MythNotification &notification)
Queue a notification Queue() is thread-safe and can be called from anywhere.
const QString & GetRating() const
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
void SetChild(MythUIButtonListItem *)
void SetDownloads(ArtworkMap map)
void SetInetRef(const QString &inetRef)
MetadataLookup * m_item
void OnSearchListSelection(const ArtworkInfo &info, VideoArtworkType type)
int GetCategoryID() const
void SetSeason(uint season)
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
const QString & GetHost() const
MythUIButtonList * m_childList
void SetCoverArt(QString file)
void SetText(const QString &text, bool moveCursor=true)
QVariant GetData() const
static FileAssociations & getFileAssociation()
Definition: dbaccess.cpp:836
MythUISpinBox * m_episodeSpin
void createBusyDialog(const QString &title)
MythMainWindow * GetMythMainWindow(void)
void SetTitle(const QString &title, const QString &sortTitle="")
QList< ArtworkInfo > ArtworkList
std::list< VideoMetadataPtr > metadata_list
bool Create() override
Dialog prompting the user to enter a text string.
MythUISpinBox * m_lengthSpin
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
void SetScreenshot(const QString &screenshot)
static Type kEventType
MythUITextEdit * m_directorEdit
void SetHost(const QString &host)
MythUITextEdit * m_playerEdit
const entry_list & getList()
Definition: dbaccess.cpp:242
void SetFilename(const QString &filename)
Must be followed by a call to Load() to load the image.
void haveResult(bool ok, ArchiveItem *item)
void SetSubtype(LookupType subtype)
VideoMetadata * m_origMetadata
MythUITextEdit * m_subtitleEdit
bool GetBrowse() const
void SetLength(int length)
void SetCheckState(MythUIStateType::StateType state)
void SetType(MetadataType type)
void SetSeason(int season)
QString generate_file_url(const QString &storage_group, const QString &host, const QString &path)
Definition: videoutils.h:65
const QString & GetScreenshot() const
DownloadMap GetDownloads() const
const QString & GetSubtitle() const
const VideoMetadataListManager & m_metaCache
const QString & GetCoverFile() const
MetadataLookupList m_lookupList
void SetEpisode(uint episode)
MythUIText * m_coverartText
Screen in which all other widgets are contained and rendered.
const QString & GetInetRef() const
MythUIImage * m_coverart
const QString & GetTitle() const
void addLookup(MetadataLookup *lookup)
addLookup: Add lookup to bottom of the queue MetadataDownload::m_lookupList takes ownership of the gi...
void SetBanner(const QString &banner)
MythUIButton * m_doneButton
QMultiMap< VideoArtworkType, ArtworkInfo > ArtworkMap
int naturalCompare(const QString &_a, const QString &_b, Qt::CaseSensitivity caseSensitivity)
void SetPlot(const QString &plot)
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:37
MythUIText * m_trailerText
void SetCategoryID(int id)
void SetCategory(MythUIButtonListItem *)
QString GetText(void) const
MythUIImage * m_fanart
MythNotificationCenter * GetNotificationCenter(void)
void SetValueByData(const QVariant &data)
MythUITextEdit * m_inetrefEdit
MythUISpinBox * m_userRatingSpin