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