MythTV  master
gameui.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QMetaType>
3 #include <QStringList>
4 #include <QTimer>
5 
6 // MythTV
7 #include <libmyth/mythcontext.h>
8 #include <libmythbase/mythdirs.h>
14 #include <libmythui/mythuiimage.h>
16 #include <libmythui/mythuitext.h>
17 
18 // MythGame headers
19 #include "gamehandler.h"
20 #include "rominfo.h"
21 #include "gamedetails.h"
22 #include "romedit.h"
23 #include "gamescan.h"
24 #include "gameui.h"
25 
26 static const QString sLocation = "MythGame";
27 
29 {
30  public:
31  GameTreeInfo(const QString& levels, QString filter)
32  : m_levels(levels.split(" "))
33  , m_filter(std::move(filter))
34  {
35  }
36 
37  int getDepth() const { return m_levels.size(); }
38  const QString& getLevel(unsigned i) const { return m_levels[i]; }
39  const QString& getFilter() const { return m_filter; }
40 
41  private:
42  QStringList m_levels;
43  QString m_filter;
44 };
45 
47 
49  : MythScreenType(parent, "GameUI")
50 {
51  m_popupStack = GetMythMainWindow()->GetStack("popup stack");
52 
53  m_query = new MetadataDownload(this);
54  m_imageDownload = new MetadataImageDownload(this);
55 }
56 
58 {
59  if (!LoadWindowFromXML("game-ui.xml", "gameui", this))
60  return false;
61 
62  bool err = false;
63  UIUtilE::Assign(this, m_gameUITree, "gametreelist", &err);
64  UIUtilW::Assign(this, m_gameTitleText, "title");
65  UIUtilW::Assign(this, m_gameSystemText, "system");
66  UIUtilW::Assign(this, m_gameYearText, "year");
67  UIUtilW::Assign(this, m_gameGenreText, "genre");
68  UIUtilW::Assign(this, m_gameFavouriteState, "favorite");
69  UIUtilW::Assign(this, m_gamePlotText, "description");
70  UIUtilW::Assign(this, m_gameImage, "screenshot");
71  UIUtilW::Assign(this, m_fanartImage, "fanart");
72  UIUtilW::Assign(this, m_boxImage, "coverart");
73 
74  if (err)
75  {
76  LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'gameui'");
77  return false;
78  }
79 
81  this, &GameUI::itemClicked);
82 
84  this, &GameUI::nodeChanged);
85 
86  m_gameShowFileName = gCoreContext->GetBoolSetting("GameShowFileNames");
87 
88  BuildTree();
89 
91 
92  return true;
93 }
94 
96 {
97  if (m_gameTree)
98  {
100  delete m_gameTree;
101  m_gameTree = nullptr;
102  }
103 
104  m_gameTree = new MythGenericTree("game root", 0, false);
105 
106  // create system filter to only select games where handlers are present
107  QString systemFilter;
108 
109  // The call to GameHandler::count() fills the handler list for us
110  // to move through.
111  unsigned handlercount = GameHandler::count();
112 
113  for (unsigned i = 0; i < handlercount; ++i)
114  {
115  QString system = GameHandler::getHandler(i)->SystemName();
116  if (i == 0)
117  systemFilter = "`system` in ('" + system + "'";
118  else
119  systemFilter += ",'" + system + "'";
120  }
121  if (systemFilter.isEmpty())
122  {
123  systemFilter = "1=0";
124  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find any game handlers!"));
125  }
126  else
127  systemFilter += ")";
128 
129  m_showHashed = gCoreContext->GetBoolSetting("GameTreeView");
130 
131  // create a few top level nodes - this could be moved to a config based
132  // approach with multiple roots if/when someone has the time to create
133  // the relevant dialog screens
134 
135  QString levels = gCoreContext->GetSetting("GameFavTreeLevels", "gamename");
136 
137  auto *new_node = new MythGenericTree(tr("Favorites"), 1, true);
138  new_node->SetData(QVariant::fromValue(
139  new GameTreeInfo(levels, systemFilter + " and favorite=1")));
140  m_favouriteNode = m_gameTree->addNode(new_node);
141 
142  levels = gCoreContext->GetSetting("GameAllTreeLevels", "system gamename");
143 
144  if (m_showHashed)
145  {
146  int pos = levels.indexOf("gamename");
147  if (pos >= 0)
148  levels.insert(pos, " hash ");
149  }
150 
151  new_node = new MythGenericTree(tr("All Games"), 1, true);
152  new_node->SetData(QVariant::fromValue(
153  new GameTreeInfo(levels, systemFilter)));
154  m_gameTree->addNode(new_node);
155 
156  new_node = new MythGenericTree(tr("- By Genre"), 1, true);
157  new_node->SetData(QVariant::fromValue(
158  new GameTreeInfo("genre gamename", systemFilter)));
159  m_gameTree->addNode(new_node);
160 
161  new_node = new MythGenericTree(tr("- By Year"), 1, true);
162  new_node->SetData(QVariant::fromValue(
163  new GameTreeInfo("year gamename", systemFilter)));
164  m_gameTree->addNode(new_node);
165 
166  new_node = new MythGenericTree(tr("- By Name"), 1, true);
167  new_node->SetData(QVariant::fromValue(
168  new GameTreeInfo("gamename", systemFilter)));
169  m_gameTree->addNode(new_node);
170 
171  new_node = new MythGenericTree(tr("- By Publisher"), 1, true);
172  new_node->SetData(QVariant::fromValue(
173  new GameTreeInfo("publisher gamename", systemFilter)));
174  m_gameTree->addNode(new_node);
175 
178 }
179 
180 bool GameUI::keyPressEvent(QKeyEvent *event)
181 {
182  if (GetFocusWidget()->keyPressEvent(event))
183  return true;
184 
185  QStringList actions;
186  bool handled = GetMythMainWindow()->TranslateKeyPress("Game", event, actions);
187 
188  for (int i = 0; i < actions.size() && !handled; i++)
189  {
190  QString action = actions[i];
191  handled = true;
192 
193  if (action == "MENU")
194  ShowMenu();
195  else if (action == "EDIT")
196  edit();
197  else if (action == "INFO")
198  showInfo();
199  else if (action == "TOGGLEFAV")
200  toggleFavorite();
201  else if ((action == "INCSEARCH") || (action == "INCSEARCHNEXT"))
202  searchStart();
203  else if (action == "DOWNLOADDATA")
204  gameSearch();
205  else
206  handled = false;
207  }
208 
209  if (!handled && MythScreenType::keyPressEvent(event))
210  handled = true;
211 
212  return handled;
213 }
214 
216 {
217  if (!node)
218  return;
219 
220  if (!isLeaf(node))
221  {
222  if (node->childCount() == 0 || node == m_favouriteNode)
223  {
224  node->deleteAllChildren();
225  fillNode(node);
226  }
227  clearRomInfo();
228  }
229  else
230  {
231  auto *romInfo = node->GetData().value<RomInfo *>();
232  if (!romInfo)
233  return;
234  if (romInfo->Romname().isEmpty())
235  romInfo->fillData();
236  updateRomInfo(romInfo);
237  if (!romInfo->Screenshot().isEmpty() || !romInfo->Fanart().isEmpty() ||
238  !romInfo->Boxart().isEmpty())
239  showImages();
240  else
241  {
242  if (m_gameImage)
243  m_gameImage->Reset();
244  if (m_fanartImage)
245  m_fanartImage->Reset();
246  if (m_boxImage)
247  m_boxImage->Reset();
248  }
249  }
250 }
251 
253 {
255  if (isLeaf(node))
256  {
257  auto *romInfo = node->GetData().value<RomInfo *>();
258  if (!romInfo)
259  return;
260  if (romInfo->RomCount() == 1)
261  {
262  GameHandler::Launchgame(romInfo, nullptr);
263  }
264  else
265  {
266  //: %1 is the game name
267  QString msg = tr("Choose System for:\n%1").arg(node->GetText());
268  MythScreenStack *popupStack = GetMythMainWindow()->
269  GetStack("popup stack");
270  auto *chooseSystemPopup = new MythDialogBox(
271  msg, popupStack, "chooseSystemPopup");
272 
273  if (chooseSystemPopup->Create())
274  {
275  chooseSystemPopup->SetReturnEvent(this, "chooseSystemPopup");
276  QString all_systems = romInfo->AllSystems();
277  QStringList players = all_systems.split(',');
278  for (const auto & player : qAsConst(players))
279  chooseSystemPopup->AddButton(player);
280  popupStack->AddScreen(chooseSystemPopup);
281  }
282  else
283  delete chooseSystemPopup;
284  }
285  }
286 }
287 
289 {
290  if (m_gameImage)
291  m_gameImage->Load();
292  if (m_fanartImage)
293  m_fanartImage->Load();
294  if (m_boxImage)
295  m_boxImage->Load();
296 }
297 
298 void GameUI::searchComplete(const QString& string)
299 {
301  return;
302 
304  if (!parent)
305  return;
306 
307  MythGenericTree *new_node = parent->getChildByName(string);
308  if (new_node)
309  m_gameUITree->SetCurrentNode(new_node);
310 }
311 
313 {
314  if (m_gameTitleText)
316  if (m_gameSystemText)
318  if (m_gameYearText)
319  m_gameYearText->SetText(rom->Year());
320  if (m_gameGenreText)
321  m_gameGenreText->SetText(rom->Genre());
322  if (m_gamePlotText)
323  m_gamePlotText->SetText(rom->Plot());
324 
326  {
327  if (rom->Favorite())
329  else
331  }
332 
333  if (m_gameImage)
334  {
335  m_gameImage->Reset();
337  }
338  if (m_fanartImage)
339  {
340  m_fanartImage->Reset();
342  }
343  if (m_boxImage)
344  {
345  m_boxImage->Reset();
346  m_boxImage->SetFilename(rom->Boxart());
347  }
348 }
349 
351 {
352  if (m_gameTitleText)
354  if (m_gameSystemText)
356  if (m_gameYearText)
358  if (m_gameGenreText)
360  if (m_gamePlotText)
364 
365  if (m_gameImage)
366  m_gameImage->Reset();
367 
368  if (m_fanartImage)
369  m_fanartImage->Reset();
370 
371  if (m_boxImage)
372  m_boxImage->Reset();
373 }
374 
375 void GameUI::edit(void)
376 {
378  if (isLeaf(node))
379  {
380  auto *romInfo = node->GetData().value<RomInfo *>();
381 
382  MythScreenStack *screenStack = GetScreenStack();
383 
384  auto *md_editor = new EditRomInfoDialog(screenStack,
385  "mythgameeditmetadata", romInfo);
386 
387  if (md_editor->Create())
388  {
389  screenStack->AddScreen(md_editor);
390  md_editor->SetReturnEvent(this, "editMetadata");
391  }
392  else
393  delete md_editor;
394  }
395 }
396 
398 {
400  if (isLeaf(node))
401  {
402  auto *romInfo = node->GetData().value<RomInfo *>();
403  if (!romInfo)
404  return;
406  auto *details_dialog = new GameDetailsPopup(mainStack, romInfo);
407 
408  if (details_dialog->Create())
409  {
410  mainStack->AddScreen(details_dialog);
411  details_dialog->SetReturnEvent(this, "detailsPopup");
412  }
413  else
414  delete details_dialog;
415  }
416 }
417 
419 {
421 
422  MythScreenStack *popupStack = GetMythMainWindow()->
423  GetStack("popup stack");
424  auto *showMenuPopup =
425  new MythDialogBox(node->GetText(), popupStack, "showMenuPopup");
426 
427  if (showMenuPopup->Create())
428  {
429  showMenuPopup->SetReturnEvent(this, "showMenuPopup");
430 
431  showMenuPopup->AddButton(tr("Scan For Changes"));
432  if (isLeaf(node))
433  {
434  auto *romInfo = node->GetData().value<RomInfo *>();
435  if (romInfo)
436  {
437  showMenuPopup->AddButton(tr("Show Information"));
438  if (romInfo->Favorite())
439  showMenuPopup->AddButton(tr("Remove Favorite"));
440  else
441  showMenuPopup->AddButton(tr("Make Favorite"));
442  showMenuPopup->AddButton(tr("Retrieve Details"));
443  showMenuPopup->AddButton(tr("Edit Details"));
444  }
445  }
446  popupStack->AddScreen(showMenuPopup);
447  }
448  else
449  delete showMenuPopup;
450 }
451 
453 {
455 
456  if (parent != nullptr)
457  {
458  QStringList childList;
459  QList<MythGenericTree*>::iterator it;
460  QList<MythGenericTree*> *children = parent->getAllChildren();
461 
462  for (it = children->begin(); it != children->end(); ++it)
463  {
464  MythGenericTree *child = *it;
465  childList << child->GetText();
466  }
467 
468  MythScreenStack *popupStack =
469  GetMythMainWindow()->GetStack("popup stack");
470  auto *searchDialog = new MythUISearchDialog(popupStack,
471  tr("Game Search"), childList, true, "");
472 
473  if (searchDialog->Create())
474  {
475  connect(searchDialog, &MythUISearchDialog::haveResult,
476  this, &GameUI::searchComplete);
477 
478  popupStack->AddScreen(searchDialog);
479  }
480  else
481  delete searchDialog;
482  }
483 }
484 
486 {
488  if (isLeaf(node))
489  {
490  auto *romInfo = node->GetData().value<RomInfo *>();
491  romInfo->setFavorite(true);
492  updateChangedNode(node, romInfo);
493  }
494 }
495 
496 void GameUI::customEvent(QEvent *event)
497 {
498  if (event->type() == DialogCompletionEvent::kEventType)
499  {
500  auto *dce = dynamic_cast<DialogCompletionEvent*>(event);
501  if (dce == nullptr)
502  return;
503  QString resultid = dce->GetId();
504  QString resulttext = dce->GetResultText();
505 
506  if (resultid == "showMenuPopup")
507  {
508  if (resulttext == tr("Edit Details"))
509  {
510  edit();
511  }
512  if (resulttext == tr("Scan For Changes"))
513  {
514  doScan();
515  }
516  else if (resulttext == tr("Show Information"))
517  {
518  showInfo();
519  }
520  else if (resulttext == tr("Make Favorite") ||
521  resulttext == tr("Remove Favorite"))
522  {
523  toggleFavorite();
524  }
525  else if (resulttext == tr("Retrieve Details"))
526  {
527  gameSearch();
528  }
529  }
530  else if (resultid == "chooseSystemPopup")
531  {
532  if (!resulttext.isEmpty() && resulttext != tr("Cancel"))
533  {
535  auto *romInfo = node->GetData().value<RomInfo *>();
536  GameHandler::Launchgame(romInfo, resulttext);
537  }
538  }
539  else if (resultid == "editMetadata")
540  {
542  auto *oldRomInfo = node->GetData().value<RomInfo *>();
543  delete oldRomInfo;
544 
545  auto *romInfo = dce->GetData().value<RomInfo *>();
546  node->SetData(QVariant::fromValue(romInfo));
547  node->SetText(romInfo->Gamename());
548 
549  romInfo->SaveToDatabase();
550  updateChangedNode(node, romInfo);
551  }
552  else if (resultid == "detailsPopup")
553  {
554  // Play button pushed
555  itemClicked(nullptr);
556  }
557  }
558  if (event->type() == MetadataLookupEvent::kEventType)
559  {
560  auto *lue = dynamic_cast<MetadataLookupEvent *>(event);
561  if (lue == nullptr)
562  return;
563  MetadataLookupList lul = lue->m_lookupList;
564 
565  if (m_busyPopup)
566  {
567  m_busyPopup->Close();
568  m_busyPopup = nullptr;
569  }
570 
571  if (lul.isEmpty())
572  return;
573 
574  if (lul.count() == 1)
575  {
576  OnGameSearchDone(lul[0]);
577  }
578  else
579  {
580  auto *resultsdialog =
582 
583  connect(resultsdialog, &MetadataResultsDialog::haveResult,
585  Qt::QueuedConnection);
586 
587  if (resultsdialog->Create())
588  m_popupStack->AddScreen(resultsdialog);
589  }
590  }
591  else if (event->type() == MetadataLookupFailure::kEventType)
592  {
593  auto *luf = dynamic_cast<MetadataLookupFailure *>(event);
594  if (luf == nullptr)
595  return;
596  MetadataLookupList lul = luf->m_lookupList;
597 
598  if (m_busyPopup)
599  {
600  m_busyPopup->Close();
601  m_busyPopup = nullptr;
602  }
603 
604  if (!lul.empty())
605  {
606  MetadataLookup *lookup = lul[0];
607  auto *node = lookup->GetData().value<MythGenericTree *>();
608  if (node)
609  {
610  auto *metadata = node->GetData().value<RomInfo *>();
611  if (metadata)
612  {
613  }
614  }
615  LOG(VB_GENERAL, LOG_ERR,
616  QString("No results found for %1").arg(lookup->GetTitle()));
617  }
618  }
619  else if (event->type() == ImageDLEvent::kEventType)
620  {
621  auto *ide = dynamic_cast<ImageDLEvent *>(event);
622  if (ide == nullptr)
623  return;
624  MetadataLookup *lookup = ide->m_item;
625 
626  if (!lookup)
627  return;
628 
629  handleDownloadedImages(lookup);
630  }
631  else if (event->type() == ImageDLFailureEvent::kEventType)
632  {
633  MythErrorNotification n(tr("Failed to retrieve image(s)"),
634  sLocation,
635  tr("Check logs"));
637  }
638 }
639 
641 {
642  QString layer = node->GetText();
643  int childDepth = node->getInt() + 1;
644  QString childLevel = getChildLevelString(node);
645  QString filter = getFilter(node);
646  bool childIsLeaf = childDepth == getLevelsOnThisBranch(node) + 1;
647  auto *romInfo = node->GetData().value<RomInfo *>();
648 
649  if (childLevel.isEmpty())
650  childLevel = "gamename";
651 
652  QString columns;
653  QString conj = "where ";
654 
655  if (!filter.isEmpty())
656  {
657  filter = conj + filter;
658  conj = " and ";
659  }
660  if ((childLevel == "gamename") && (m_gameShowFileName))
661  {
662  columns = childIsLeaf
663  ? "romname,`system`,year,genre,gamename"
664  : "romname";
665 
666  if (m_showHashed)
667  filter += " and romname like '" + layer + "%'";
668 
669  }
670  else if ((childLevel == "gamename") && (layer.length() == 1))
671  {
672  columns = childIsLeaf
673  ? childLevel + ",`system`,year,genre,gamename"
674  : childLevel;
675 
676  if (m_showHashed)
677  filter += " and gamename like '" + layer + "%'";
678 
679  }
680  else if (childLevel == "hash")
681  {
682  columns = "left(gamename,1)";
683  }
684  else
685  {
686 
687  columns = childIsLeaf
688  ? childLevel + ",`system`,year,genre,gamename"
689  : childLevel;
690  }
691 
692  // this whole section ought to be in rominfo.cpp really, but I've put it
693  // in here for now to minimise the number of files changed by this mod
694  if (romInfo)
695  {
696  if (!romInfo->System().isEmpty())
697  {
698  filter += conj + "trim(system)=:SYSTEM";
699  conj = " and ";
700  }
701  if (!romInfo->Year().isEmpty())
702  {
703  filter += conj + "year=:YEAR";
704  conj = " and ";
705  }
706  if (!romInfo->Genre().isEmpty())
707  {
708  filter += conj + "trim(genre)=:GENRE";
709  conj = " and ";
710  }
711  if (!romInfo->Plot().isEmpty())
712  {
713  filter += conj + "plot=:PLOT";
714  conj = " and ";
715  }
716  if (!romInfo->Publisher().isEmpty())
717  {
718  filter += conj + "publisher=:PUBLISHER";
719  conj = " and ";
720  }
721  if (!romInfo->Gamename().isEmpty())
722  {
723  filter += conj + "trim(gamename)=:GAMENAME";
724  }
725 
726  }
727 
728  filter += conj + " display = 1 ";
729 
730  QString sql;
731 
732  if ((childLevel == "gamename") && (m_gameShowFileName))
733  {
734  sql = "select distinct "
735  + columns
736  + " from gamemetadata "
737  + filter
738  + " order by romname"
739  + ";";
740  }
741  else if (childLevel == "hash")
742  {
743  sql = "select distinct "
744  + columns
745  + " from gamemetadata "
746  + filter
747  + " order by gamename,romname"
748  + ";";
749  }
750  else
751  {
752  sql = "select distinct "
753  + columns
754  + " from gamemetadata "
755  + filter
756  + " order by "
757  + childLevel
758  + ";";
759  }
760 
761  return sql;
762 }
763 
765 {
766  unsigned this_level = node->getInt();
767  while (node->getInt() != 1)
768  node = node->getParent();
769 
770  auto *gi = node->GetData().value<GameTreeInfo *>();
771  return gi->getLevel(this_level - 1);
772 }
773 
775 {
776  while (node->getInt() != 1)
777  node = node->getParent();
778  auto *gi = node->GetData().value<GameTreeInfo *>();
779  return gi->getFilter();
780 }
781 
783 {
784  while (node->getInt() != 1)
785  node = node->getParent();
786 
787  auto *gi = node->GetData().value<GameTreeInfo *>();
788  return gi->getDepth();
789 }
790 
792 {
793  return (node->getInt() - 1) == getLevelsOnThisBranch(node);
794 }
795 
797 {
798 // QString layername = node->GetText();
799  auto *romInfo = node->GetData().value<RomInfo *>();
800 
801  MSqlQuery query(MSqlQuery::InitCon());
802 
803  query.prepare(getFillSql(node));
804 
805  if (romInfo)
806  {
807  if (!romInfo->System().isEmpty())
808  query.bindValue(":SYSTEM", romInfo->System());
809  if (!romInfo->Year().isEmpty())
810  query.bindValue(":YEAR", romInfo->Year());
811  if (!romInfo->Genre().isEmpty())
812  query.bindValue(":GENRE", romInfo->Genre());
813  if (!romInfo->Plot().isEmpty())
814  query.bindValue(":PLOT", romInfo->Plot());
815  if (!romInfo->Publisher().isEmpty())
816  query.bindValue(":PUBLISHER", romInfo->Publisher());
817  if (!romInfo->Gamename().isEmpty())
818  query.bindValue(":GAMENAME", romInfo->Gamename());
819  }
820 
821  bool IsLeaf = node->getInt() == getLevelsOnThisBranch(node);
822  if (query.exec() && query.size() > 0)
823  {
824  while (query.next())
825  {
826  QString current = query.value(0).toString().trimmed();
827  auto *new_node =
828  new MythGenericTree(current, node->getInt() + 1, false);
829  if (IsLeaf)
830  {
831  auto *temp = new RomInfo();
832  temp->setSystem(query.value(1).toString().trimmed());
833  temp->setYear(query.value(2).toString());
834  temp->setGenre(query.value(3).toString().trimmed());
835  temp->setGamename(query.value(4).toString().trimmed());
836  new_node->SetData(QVariant::fromValue(temp));
837  node->addNode(new_node);
838  }
839  else
840  {
841  RomInfo *newRomInfo = nullptr;
842  if (node->getInt() > 1)
843  {
844  auto *currentRomInfo = node->GetData().value<RomInfo *>();
845  newRomInfo = new RomInfo(*currentRomInfo);
846  }
847  else
848  {
849  newRomInfo = new RomInfo();
850  }
851  new_node->SetData(QVariant::fromValue(newRomInfo));
852  node->addNode(new_node);
853  if (getChildLevelString(node) != "hash")
854  newRomInfo->setField(getChildLevelString(node), current);
855  }
856  }
857  }
858 }
859 
861 {
862  MythGenericTree *top_level = node;
863  while (top_level->getParent() != m_gameTree)
864  {
865  top_level = top_level->getParent();
866  }
867 
868  QList<MythGenericTree*>::iterator it;
869  QList<MythGenericTree*> *children = m_gameTree->getAllChildren();
870 
871  for (it = children->begin(); it != children->end(); ++it)
872  {
873  MythGenericTree *child = *it;
874  if (child != top_level)
875  {
876  child->deleteAllChildren();
877  }
878  }
879 }
880 
882 {
883  resetOtherTrees(node);
884 
885  if (node->getParent() == m_favouriteNode && !romInfo->Favorite())
886  {
887  // node is being removed
889  }
890  else
891  nodeChanged(node);
892 }
893 
895  bool automode)
896 {
897  if (!node)
898  node = m_gameUITree->GetCurrentNode();
899 
900  if (!node)
901  return;
902 
903  auto *metadata = node->GetData().value<RomInfo *>();
904  if (!metadata)
905  return;
906 
907  auto *lookup = new MetadataLookup();
908  lookup->SetStep(kLookupSearch);
909  lookup->SetType(kMetadataGame);
910  lookup->SetData(QVariant::fromValue(node));
911 
912  if (automode)
913  {
914  lookup->SetAutomatic(true);
915  }
916 
917  lookup->SetTitle(metadata->Gamename());
918  lookup->SetInetref(metadata->Inetref());
919  if (m_query->isRunning())
920  m_query->prependLookup(lookup);
921  else
922  m_query->addLookup(lookup);
923 
924  if (!automode)
925  {
926  //: %1 is the game name
927  QString msg = tr("Fetching details for %1")
928  .arg(metadata->Gamename());
929  createBusyDialog(msg);
930  }
931 }
932 
933 void GameUI::createBusyDialog(const QString& title)
934 {
935  if (m_busyPopup)
936  return;
937 
938  const QString& message = title;
939 
941  "mythgamebusydialog");
942 
943  if (m_busyPopup->Create())
945 }
946 
948 {
949  if (!lookup)
950  return;
951 
952  lookup->SetStep(kLookupData);
953  lookup->IncrRef();
954  m_query->prependLookup(lookup);
955 }
956 
958 {
959  if (m_busyPopup)
960  {
961  m_busyPopup->Close();
962  m_busyPopup = nullptr;
963  }
964 
965  if (!lookup)
966  return;
967 
968  auto *node = lookup->GetData().value<MythGenericTree *>();
969  if (!node)
970  return;
971 
972  auto *metadata = node->GetData().value<RomInfo *>();
973  if (!metadata)
974  return;
975 
976  metadata->setGamename(lookup->GetTitle());
977  metadata->setYear(QString::number(lookup->GetYear()));
978  metadata->setPlot(lookup->GetDescription());
979  metadata->setSystem(lookup->GetSystem());
980 
981  QStringList coverart;
982  QStringList fanart;
983  QStringList screenshot;
984 
985  // Imagery
986  ArtworkList coverartlist = lookup->GetArtwork(kArtworkCoverart);
987  for (const auto & art : qAsConst(coverartlist))
988  coverart.prepend(art.url);
989  ArtworkList fanartlist = lookup->GetArtwork(kArtworkFanart);
990  for (const auto & art : qAsConst(fanartlist))
991  fanart.prepend(art.url);
992  ArtworkList screenshotlist = lookup->GetArtwork(kArtworkScreenshot);
993  for (const auto & art : qAsConst(screenshotlist))
994  screenshot.prepend(art.url);
995 
996  StartGameImageSet(node, coverart, fanart, screenshot);
997 
998  metadata->SaveToDatabase();
999  updateChangedNode(node, metadata);
1000 }
1001 
1002 void GameUI::StartGameImageSet(MythGenericTree *node, QStringList coverart,
1003  QStringList fanart, QStringList screenshot)
1004 {
1005  if (!node)
1006  return;
1007 
1008  auto *metadata = node->GetData().value<RomInfo *>();
1009  if (!metadata)
1010  return;
1011 
1012  DownloadMap map;
1013 
1014  if (metadata->Boxart().isEmpty() && !coverart.empty())
1015  {
1016  ArtworkInfo info;
1017  info.url = coverart.takeAt(0).trimmed();
1018  map.insert(kArtworkCoverart, info);
1019  }
1020 
1021  if (metadata->Fanart().isEmpty() && !fanart.empty())
1022  {
1023  ArtworkInfo info;
1024  info.url = fanart.takeAt(0).trimmed();
1025  map.insert(kArtworkFanart, info);
1026  }
1027 
1028  if (metadata->Screenshot().isEmpty() && !screenshot.empty())
1029  {
1030  ArtworkInfo info;
1031  info.url = screenshot.takeAt(0).trimmed();
1032  map.insert(kArtworkScreenshot, info);
1033  }
1034 
1035  auto *lookup = new MetadataLookup();
1036  lookup->SetTitle(metadata->Gamename());
1037  lookup->SetSystem(metadata->System());
1038  lookup->SetInetref(metadata->Inetref());
1039  lookup->SetType(kMetadataGame);
1040  lookup->SetDownloads(map);
1041  lookup->SetData(QVariant::fromValue(node));
1042 
1043  m_imageDownload->addDownloads(lookup);
1044 }
1045 
1047 {
1048  if (!lookup)
1049  return;
1050 
1051  auto *node = lookup->GetData().value<MythGenericTree *>();
1052  if (!node)
1053  return;
1054 
1055  auto *metadata = node->GetData().value<RomInfo *>();
1056  if (!metadata)
1057  return;
1058 
1059  DownloadMap downloads = lookup->GetDownloads();
1060 
1061  if (downloads.isEmpty())
1062  return;
1063 
1064  for (DownloadMap::iterator i = downloads.begin();
1065  i != downloads.end(); ++i)
1066  {
1067  VideoArtworkType type = i.key();
1068  ArtworkInfo info = i.value();
1069  QString filename = info.url;
1070 
1071  if (type == kArtworkCoverart)
1072  metadata->setBoxart(filename);
1073  else if (type == kArtworkFanart)
1074  metadata->setFanart(filename);
1075  else if (type == kArtworkScreenshot)
1076  metadata->setScreenshot(filename);
1077  }
1078 
1079  metadata->SaveToDatabase();
1080  updateChangedNode(node, metadata);
1081 }
1082 
1084 {
1085  if (!m_scanner)
1086  m_scanner = new GameScanner();
1088  m_scanner->doScanAll();
1089 }
1090 
1091 void GameUI::reloadAllData(bool dbChanged)
1092 {
1093  delete m_scanner;
1094  m_scanner = nullptr;
1095 
1096  if (dbChanged)
1097  BuildTree();
1098 }
1099 
GameScanner::doScanAll
void doScanAll(void)
Definition: gamescan.cpp:232
RomInfo::Boxart
QString Boxart() const
Definition: rominfo.h:69
GameUI::getFillSql
QString getFillSql(MythGenericTree *node) const
Definition: gameui.cpp:640
GameUI::m_popupStack
MythScreenStack * m_popupStack
Definition: gameui.h:80
GameUI::isLeaf
static bool isLeaf(MythGenericTree *node)
Definition: gameui.cpp:791
mythuibuttontree.h
mythuimetadataresults.h
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
MythMainWindow::GetMainStack
MythScreenStack * GetMainStack()
Definition: mythmainwindow.cpp:318
GameTreeInfo::m_filter
QString m_filter
Definition: gameui.cpp:43
MythUISearchDialog
Provide a dialog to quickly find an entry in a list.
Definition: mythdialogbox.h:399
VideoArtworkType
VideoArtworkType
Definition: metadataimagehelper.h:10
GameUI::customEvent
void customEvent(QEvent *event) override
Definition: gameui.cpp:496
RefCountHandler
Definition: referencecounterlist.h:17
GameUI::getChildLevelString
static QString getChildLevelString(MythGenericTree *node)
Definition: gameui.cpp:764
mythuitext.h
MythGenericTree::SetData
void SetData(QVariant data)
Definition: mythgenerictree.h:97
GameTreeInfo::GameTreeInfo
GameTreeInfo(const QString &levels, QString filter)
Definition: gameui.cpp:31
DialogCompletionEvent::GetId
QString GetId()
Definition: mythdialogbox.h:52
MythUIText::Reset
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuitext.cpp:82
MetadataImageDownload
Definition: metadataimagedownload.h:87
MythGenericTree::GetText
QString GetText(const QString &name="") const
Definition: mythgenerictree.cpp:556
GameUI::createBusyDialog
void createBusyDialog(const QString &title)
Definition: gameui.cpp:933
RomInfo::Plot
QString Plot() const
Definition: rominfo.h:102
GameUI::ShowMenu
void ShowMenu(void) override
Definition: gameui.cpp:418
GameUI::nodeChanged
void nodeChanged(MythGenericTree *node)
Definition: gameui.cpp:215
MetadataLookup::GetTitle
QString GetTitle() const
Definition: metadatacommon.h:299
MythScreenType::Close
virtual void Close()
Definition: mythscreentype.cpp:386
RomInfo::Gamename
QString Gamename() const
Definition: rominfo.h:78
MetadataResultsDialog
Definition: mythuimetadataresults.h:10
GameUI::m_gameYearText
MythUIText * m_gameYearText
Definition: gameui.h:85
GameUI::edit
void edit(void)
Definition: gameui.cpp:375
GameUI
Definition: gameui.h:25
RomInfo::Favorite
bool Favorite() const
Definition: rominfo.h:117
ArtworkList
QList< ArtworkInfo > ArtworkList
Definition: metadataimagehelper.h:30
EditRomInfoDialog
Definition: romedit.h:9
GameTreeInfo::m_levels
QStringList m_levels
Definition: gameui.cpp:42
GameTreeInfo::getDepth
int getDepth() const
Definition: gameui.cpp:37
GameUI::StartGameImageSet
void StartGameImageSet(MythGenericTree *node, QStringList coverart, QStringList fanart, QStringList screenshot)
Definition: gameui.cpp:1002
GameTreeInfo::getLevel
const QString & getLevel(unsigned i) const
Definition: gameui.cpp:38
MythUIImage::Load
bool Load(bool allowLoadInBackground=true, bool forceStat=false)
Load the image(s), wraps ImageLoader::LoadImage()
Definition: mythuiimage.cpp:966
MetadataDownload::prependLookup
void prependLookup(MetadataLookup *lookup)
prependLookup: Add lookup to top of the queue MetadataDownload::m_lookupList takes ownership of the g...
Definition: metadatadownload.cpp:54
GameUI::m_gameUITree
MythUIButtonTree * m_gameUITree
Definition: gameui.h:82
MythGenericTree::getInt
int getInt() const
Definition: mythgenerictree.h:73
MythUISearchDialog::haveResult
void haveResult(QString)
MythUIBusyDialog::Create
bool Create(void) override
Definition: mythprogressdialog.cpp:32
romedit.h
GameUI::m_scanner
GameScanner * m_scanner
Definition: gameui.h:96
mythdialogbox.h
MythScreenStack
Definition: mythscreenstack.h:16
GameScanner
Definition: gamescan.h:71
MythGenericTree::GetData
QVariant GetData(void) const
Definition: mythgenerictree.h:98
RomInfo::Genre
QString Genre() const
Definition: rominfo.h:81
MythUIButtonTree::SetCurrentNode
bool SetCurrentNode(MythGenericTree *node)
Set the currently selected node.
Definition: mythuibuttontree.cpp:346
MythGenericTree::getChildByName
MythGenericTree * getChildByName(const QString &a_name) const
Definition: mythgenerictree.cpp:378
ImageDLEvent
Definition: metadataimagedownload.h:18
MetadataDownload
Definition: metadatadownload.h:35
MetadataLookup::GetArtwork
ArtworkList GetArtwork(VideoArtworkType type) const
Definition: metadatacommon.cpp:330
GameUI::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: gameui.cpp:180
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythScreenType
Screen in which all other widgets are contained and rendered.
Definition: mythscreentype.h:45
mythuistatetype.h
GameUI::itemClicked
void itemClicked(MythUIButtonListItem *item)
Definition: gameui.cpp:252
MythUIStateType::Reset
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuistatetype.cpp:197
GameUI::doScan
void doScan(void)
Definition: gameui.cpp:1083
mythdirs.h
MythUIImage::Reset
void Reset(void) override
Reset the image back to the default defined in the theme.
Definition: mythuiimage.cpp:643
RomInfo::System
QString System() const
Definition: rominfo.h:75
MythUIButtonTree::AssignTree
bool AssignTree(MythGenericTree *tree)
Assign the root node of the tree to be displayed.
Definition: mythuibuttontree.cpp:213
GameTreeInfo
Definition: gameui.cpp:28
GameUI::searchComplete
void searchComplete(const QString &string)
Definition: gameui.cpp:298
GameUI::m_gameTree
MythGenericTree * m_gameTree
Definition: gameui.h:76
mythuiimage.h
gamescan.h
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:14
kLookupSearch
@ kLookupSearch
Definition: metadatacommon.h:28
sLocation
static const QString sLocation
Definition: gameui.cpp:26
MythScreenType::GetFocusWidget
MythUIType * GetFocusWidget(void) const
Definition: mythscreentype.cpp:113
Q_DECLARE_METATYPE
Q_DECLARE_METATYPE(StandardSetting *)
GameUI::m_gamePlotText
MythUIText * m_gamePlotText
Definition: gameui.h:87
MetadataLookup
Definition: metadatacommon.h:87
MythGenericTree::addNode
MythGenericTree * addNode(const QString &a_string, int an_int=0, bool selectable_flag=false, bool visible=true)
Definition: mythgenerictree.cpp:86
MythUIButtonListItem
Definition: mythuibuttonlist.h:41
MythUIButtonTree::itemClicked
void itemClicked(MythUIButtonListItem *item)
MetadataLookup::GetDownloads
DownloadMap GetDownloads() const
Definition: metadatacommon.h:372
GameUI::updateChangedNode
void updateChangedNode(MythGenericTree *node, RomInfo *romInfo)
Definition: gameui.cpp:881
RomInfo::Screenshot
QString Screenshot() const
Definition: rominfo.h:63
GameUI::m_gameImage
MythUIImage * m_gameImage
Definition: gameui.h:89
RomInfo::fillData
void fillData()
Definition: rominfo.cpp:247
GameUI::gameSearch
void gameSearch(MythGenericTree *node=nullptr, bool automode=false)
Definition: gameui.cpp:894
GameUI::reloadAllData
void reloadAllData(bool dbchanged)
Definition: gameui.cpp:1091
MetadataLookup::GetDescription
QString GetDescription() const
Definition: metadatacommon.h:312
MythMainWindow::TranslateKeyPress
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
Definition: mythmainwindow.cpp:1111
MetadataLookupFailure
Definition: metadatadownload.h:23
ArtworkInfo
Definition: metadataimagehelper.h:21
RomInfo::setGamename
void setGamename(const QString &lgamename)
Definition: rominfo.h:79
RefCountedList< MetadataLookup >
MythDialogBox
Basic menu dialog, message and a list of options.
Definition: mythdialogbox.h:166
MetadataLookup::GetData
QVariant GetData() const
Definition: metadatacommon.h:288
ImageDLFailureEvent::kEventType
static const Type kEventType
Definition: metadataimagedownload.h:67
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:549
kLookupData
@ kLookupData
Definition: metadatacommon.h:29
GameUI::OnGameSearchDone
void OnGameSearchDone(MetadataLookup *lookup)
Definition: gameui.cpp:957
GameHandler::getHandler
static GameHandler * getHandler(uint i)
Definition: gamehandler.cpp:54
MythScreenType::BuildFocusList
void BuildFocusList(void)
Definition: mythscreentype.cpp:206
GameScanner::finished
void finished(bool)
MythGenericTree::childCount
int childCount(void) const
Definition: mythgenerictree.cpp:255
MythErrorNotification
Definition: mythnotification.h:198
kArtworkFanart
@ kArtworkFanart
Definition: metadataimagehelper.h:12
GameUI::m_gameGenreText
MythUIText * m_gameGenreText
Definition: gameui.h:86
GameUI::OnGameSearchListSelection
void OnGameSearchListSelection(RefCountHandler< MetadataLookup > lookup)
Definition: gameui.cpp:947
ImageDLEvent::kEventType
static const Type kEventType
Definition: metadataimagedownload.h:41
RomInfo::setFavorite
void setFavorite(bool updateDatabase=false)
Definition: rominfo.cpp:213
rominfo.h
mythgenerictree.h
MythUIBusyDialog
Definition: mythprogressdialog.h:36
MetadataDownload::addLookup
void addLookup(MetadataLookup *lookup)
addLookup: Add lookup to bottom of the queue MetadataDownload::m_lookupList takes ownership of the gi...
Definition: metadatadownload.cpp:39
MetadataLookup::GetYear
uint GetYear() const
Definition: metadatacommon.h:349
MythGenericTree::deleteAllChildren
void deleteAllChildren()
Definition: mythgenerictree.cpp:454
GameUI::handleDownloadedImages
void handleDownloadedImages(MetadataLookup *lookup)
Definition: gameui.cpp:1046
MythUIButtonTree::GetCurrentNode
MythGenericTree * GetCurrentNode(void) const
Definition: mythuibuttontree.h:32
GameUI::showInfo
void showInfo(void)
Definition: gameui.cpp:397
GameUI::m_busyPopup
MythUIBusyDialog * m_busyPopup
Definition: gameui.h:79
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
MythScreenType::GetScreenStack
MythScreenStack * GetScreenStack() const
Definition: mythscreentype.cpp:217
MythGenericTree::getAllChildren
QList< MythGenericTree * > * getAllChildren() const
Definition: mythgenerictree.cpp:277
UIUtilDisp::Assign
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
MetadataLookupFailure::kEventType
static const Type kEventType
Definition: metadatadownload.h:32
GameDetailsPopup
Definition: gamedetails.h:13
GameUI::m_gameShowFileName
bool m_gameShowFileName
Definition: gameui.h:74
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:905
RomInfo
Definition: rominfo.h:14
MetadataLookup::GetSystem
QString GetSystem() const
Definition: metadatacommon.h:346
MetadataResultsDialog::haveResult
void haveResult(RefCountHandler< MetadataLookup >)
GameUI::m_gameSystemText
MythUIText * m_gameSystemText
Definition: gameui.h:84
GameUI::m_gameTitleText
MythUIText * m_gameTitleText
Definition: gameui.h:83
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:236
MythScreenType::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: mythscreentype.cpp:404
RomInfo::Fanart
QString Fanart() const
Definition: rominfo.h:66
GameHandler::SystemName
QString SystemName() const
Definition: gamehandler.h:105
GameUI::m_fanartImage
MythUIImage * m_fanartImage
Definition: gameui.h:90
XMLParseBase::LoadWindowFromXML
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
Definition: xmlparsebase.cpp:695
MythGenericTree::getParent
MythGenericTree * getParent(void) const
Definition: mythgenerictree.cpp:371
GameUI::m_query
MetadataDownload * m_query
Definition: gameui.h:93
std
Definition: mythchrono.h:23
DialogCompletionEvent
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:41
GameUI::Create
bool Create() override
Definition: gameui.cpp:57
MythGenericTree
Definition: mythgenerictree.h:27
kMetadataGame
@ kMetadataGame
Definition: metadatacommon.h:46
GameUI::showImages
void showImages(void)
Definition: gameui.cpp:288
GameUI::m_imageDownload
MetadataImageDownload * m_imageDownload
Definition: gameui.h:94
GameUI::m_gameFavouriteState
MythUIStateType * m_gameFavouriteState
Definition: gameui.h:88
MythUIText::SetText
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:132
GetNotificationCenter
MythNotificationCenter * GetNotificationCenter(void)
Definition: mythmainwindow.cpp:124
mythcontext.h
DialogCompletionEvent::kEventType
static const Type kEventType
Definition: mythdialogbox.h:57
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:104
MThread::isRunning
bool isRunning(void) const
Definition: mthread.cpp:263
GameHandler::Launchgame
static void Launchgame(RomInfo *romdata, const QString &systemname)
Definition: gamehandler.cpp:819
GameUI::resetOtherTrees
void resetOtherTrees(MythGenericTree *node)
Definition: gameui.cpp:860
GameUI::clearRomInfo
void clearRomInfo(void)
Definition: gameui.cpp:350
build_compdb.action
action
Definition: build_compdb.py:9
GameUI::m_favouriteNode
MythGenericTree * m_favouriteNode
Definition: gameui.h:77
MythMainWindow::GetStack
MythScreenStack * GetStack(const QString &Stackname)
Definition: mythmainwindow.cpp:323
DownloadMap
QMap< VideoArtworkType, ArtworkInfo > DownloadMap
Definition: metadatacommon.h:84
GameUI::getFilter
static QString getFilter(MythGenericTree *node)
Definition: gameui.cpp:774
GameUI::getLevelsOnThisBranch
static int getLevelsOnThisBranch(MythGenericTree *node)
Definition: gameui.cpp:782
MetadataLookupEvent::kEventType
static const Type kEventType
Definition: metadatadownload.h:20
MythGenericTree::SetText
void SetText(const QString &text, const QString &name="", const QString &state="")
Definition: mythgenerictree.cpp:518
gameui.h
RomInfo::setField
void setField(const QString &field, const QString &data)
Definition: rominfo.cpp:172
GameUI::BuildTree
void BuildTree()
Definition: gameui.cpp:95
GameUI::m_showHashed
bool m_showHashed
Definition: gameui.h:73
GameTreeInfo::getFilter
const QString & getFilter() const
Definition: gameui.cpp:39
kArtworkScreenshot
@ kArtworkScreenshot
Definition: metadataimagehelper.h:14
MythUIImage::SetFilename
void SetFilename(const QString &filename)
Must be followed by a call to Load() to load the image.
Definition: mythuiimage.cpp:674
GameUI::searchStart
void searchStart(void)
Definition: gameui.cpp:452
ReferenceCounter::IncrRef
virtual int IncrRef(void)
Increments reference count.
Definition: referencecounter.cpp:101
build_compdb.filename
filename
Definition: build_compdb.py:21
mythmainwindow.h
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:52
GameUI::toggleFavorite
void toggleFavorite(void)
Definition: gameui.cpp:485
MetadataLookupEvent
Definition: metadatadownload.h:11
kArtworkCoverart
@ kArtworkCoverart
Definition: metadataimagehelper.h:11
gamehandler.h
MetadataLookup::SetStep
void SetStep(LookupStep step)
Definition: metadatacommon.h:244
RomInfo::Year
QString Year() const
Definition: rominfo.h:111
GameUI::fillNode
void fillNode(MythGenericTree *node)
Definition: gameui.cpp:796
gamedetails.h
MythUIStateType::DisplayState
bool DisplayState(const QString &name)
Definition: mythuistatetype.cpp:84
MythUIButtonTree::nodeChanged
void nodeChanged(MythGenericTree *node)
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:897
GameHandler::count
static uint count(void)
Definition: gamehandler.cpp:101
ArtworkInfo::url
QString url
Definition: metadataimagehelper.h:25
GameUI::m_boxImage
MythUIImage * m_boxImage
Definition: gameui.h:91
MetadataImageDownload::addDownloads
void addDownloads(MetadataLookup *lookup)
addLookup: Add lookup to bottom of the queue MetadataDownload::m_downloadList takes ownership of the ...
Definition: metadataimagedownload.cpp:54
GameUI::updateRomInfo
void updateRomInfo(RomInfo *rom)
Definition: gameui.cpp:312
MythNotificationCenter::Queue
bool Queue(const MythNotification &notification)
Queue a notification Queue() is thread-safe and can be called from anywhere.
Definition: mythnotificationcenter.cpp:1349