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 showImages();
242 else
243 {
244 if (m_gameImage)
246 if (m_fanartImage)
248 if (m_boxImage)
249 m_boxImage->Reset();
250 }
251 }
252}
253
255{
257 if (isLeaf(node))
258 {
259 auto *romInfo = node->GetData().value<RomInfo *>();
260 if (!romInfo)
261 return;
262 if (romInfo->RomCount() == 1)
263 {
264 GameHandler::Launchgame(romInfo, nullptr);
265 }
266 else
267 {
268 //: %1 is the game name
269 QString msg = tr("Choose System for:\n%1").arg(node->GetText());
270 MythScreenStack *popupStack = GetMythMainWindow()->
271 GetStack("popup stack");
272 auto *chooseSystemPopup = new MythDialogBox(
273 msg, popupStack, "chooseSystemPopup");
274
275 if (chooseSystemPopup->Create())
276 {
277 chooseSystemPopup->SetReturnEvent(this, "chooseSystemPopup");
278 QString all_systems = romInfo->AllSystems();
279 QStringList players = all_systems.split(',');
280 for (const auto & player : std::as_const(players))
281 chooseSystemPopup->AddButton(player);
282 popupStack->AddScreen(chooseSystemPopup);
283 }
284 else
285 {
286 delete chooseSystemPopup;
287 }
288 }
289 }
290}
291
293{
294 if (m_gameImage)
295 m_gameImage->Load();
296 if (m_fanartImage)
298 if (m_boxImage)
299 m_boxImage->Load();
300}
301
302void GameUI::searchComplete(const QString& string)
303{
305 return;
306
308 if (!parent)
309 return;
310
311 MythGenericTree *new_node = parent->getChildByName(string);
312 if (new_node)
313 m_gameUITree->SetCurrentNode(new_node);
314}
315
317{
318 if (m_gameTitleText)
322 if (m_gameYearText)
323 m_gameYearText->SetText(rom->Year());
324 if (m_gameGenreText)
326 if (m_gamePlotText)
327 m_gamePlotText->SetText(rom->Plot());
328
330 {
331 if (rom->Favorite())
333 else
335 }
336
337 if (m_gameImage)
338 {
341 }
342 if (m_fanartImage)
343 {
346 }
347 if (m_boxImage)
348 {
349 m_boxImage->Reset();
351 }
352}
353
355{
356 if (m_gameTitleText)
360 if (m_gameYearText)
362 if (m_gameGenreText)
364 if (m_gamePlotText)
368
369 if (m_gameImage)
371
372 if (m_fanartImage)
374
375 if (m_boxImage)
376 m_boxImage->Reset();
377}
378
379void GameUI::edit(void)
380{
382 if (isLeaf(node))
383 {
384 auto *romInfo = node->GetData().value<RomInfo *>();
385
386 MythScreenStack *screenStack = GetScreenStack();
387
388 auto *md_editor = new EditRomInfoDialog(screenStack,
389 "mythgameeditmetadata", romInfo);
390
391 if (md_editor->Create())
392 {
393 screenStack->AddScreen(md_editor);
394 md_editor->SetReturnEvent(this, "editMetadata");
395 }
396 else
397 {
398 delete md_editor;
399 }
400 }
401}
402
404{
406 if (isLeaf(node))
407 {
408 auto *romInfo = node->GetData().value<RomInfo *>();
409 if (!romInfo)
410 return;
412 auto *details_dialog = new GameDetailsPopup(mainStack, romInfo);
413
414 if (details_dialog->Create())
415 {
416 mainStack->AddScreen(details_dialog);
417 details_dialog->SetReturnEvent(this, "detailsPopup");
418 }
419 else
420 {
421 delete details_dialog;
422 }
423 }
424}
425
427{
429
430 MythScreenStack *popupStack = GetMythMainWindow()->
431 GetStack("popup stack");
432 auto *showMenuPopup =
433 new MythDialogBox(node->GetText(), popupStack, "showMenuPopup");
434
435 if (showMenuPopup->Create())
436 {
437 showMenuPopup->SetReturnEvent(this, "showMenuPopup");
438
439 showMenuPopup->AddButton(tr("Scan For Changes"));
440 if (isLeaf(node))
441 {
442 auto *romInfo = node->GetData().value<RomInfo *>();
443 if (romInfo)
444 {
445 showMenuPopup->AddButton(tr("Show Information"));
446 if (romInfo->Favorite())
447 showMenuPopup->AddButton(tr("Remove Favorite"));
448 else
449 showMenuPopup->AddButton(tr("Make Favorite"));
450 showMenuPopup->AddButton(tr("Retrieve Details"));
451 showMenuPopup->AddButton(tr("Edit Details"));
452 }
453 }
454 popupStack->AddScreen(showMenuPopup);
455 }
456 else
457 {
458 delete showMenuPopup;
459 }
460}
461
463{
465
466 if (parent != nullptr)
467 {
468 QStringList childList;
469 QList<MythGenericTree*>::iterator it;
470 QList<MythGenericTree*> *children = parent->getAllChildren();
471
472 for (it = children->begin(); it != children->end(); ++it)
473 {
474 MythGenericTree *child = *it;
475 childList << child->GetText();
476 }
477
478 MythScreenStack *popupStack =
479 GetMythMainWindow()->GetStack("popup stack");
480 auto *searchDialog = new MythUISearchDialog(popupStack,
481 tr("Game Search"), childList, true, "");
482
483 if (searchDialog->Create())
484 {
485 connect(searchDialog, &MythUISearchDialog::haveResult,
487
488 popupStack->AddScreen(searchDialog);
489 }
490 else
491 {
492 delete searchDialog;
493 }
494 }
495}
496
498{
500 if (isLeaf(node))
501 {
502 auto *romInfo = node->GetData().value<RomInfo *>();
503 romInfo->setFavorite(true);
504 updateChangedNode(node, romInfo);
505 }
506}
507
508void GameUI::customEvent(QEvent *event)
509{
510 if (event->type() == DialogCompletionEvent::kEventType)
511 {
512 auto *dce = dynamic_cast<DialogCompletionEvent*>(event);
513 if (dce == nullptr)
514 return;
515 QString resultid = dce->GetId();
516 QString resulttext = dce->GetResultText();
517
518 if (resultid == "showMenuPopup")
519 {
520 if (resulttext == tr("Edit Details"))
521 {
522 edit();
523 }
524 if (resulttext == tr("Scan For Changes"))
525 {
526 doScan();
527 }
528 else if (resulttext == tr("Show Information"))
529 {
530 showInfo();
531 }
532 else if (resulttext == tr("Make Favorite") ||
533 resulttext == tr("Remove Favorite"))
534 {
536 }
537 else if (resulttext == tr("Retrieve Details"))
538 {
539 gameSearch();
540 }
541 }
542 else if (resultid == "chooseSystemPopup")
543 {
544 if (!resulttext.isEmpty() && resulttext != tr("Cancel"))
545 {
547 auto *romInfo = node->GetData().value<RomInfo *>();
548 GameHandler::Launchgame(romInfo, resulttext);
549 }
550 }
551 else if (resultid == "editMetadata")
552 {
554 auto *oldRomInfo = node->GetData().value<RomInfo *>();
555 delete oldRomInfo;
556
557 auto *romInfo = dce->GetData().value<RomInfo *>();
558 node->SetData(QVariant::fromValue(romInfo));
559 node->SetText(romInfo->Gamename());
560
561 romInfo->SaveToDatabase();
562 updateChangedNode(node, romInfo);
563 }
564 else if (resultid == "detailsPopup")
565 {
566 // Play button pushed
567 itemClicked(nullptr);
568 }
569 }
570 if (event->type() == MetadataLookupEvent::kEventType)
571 {
572 auto *lue = dynamic_cast<MetadataLookupEvent *>(event);
573 if (lue == nullptr)
574 return;
575 MetadataLookupList lul = lue->m_lookupList;
576
577 if (m_busyPopup)
578 {
580 m_busyPopup = nullptr;
581 }
582
583 if (lul.isEmpty())
584 return;
585
586 if (lul.count() == 1)
587 {
588 OnGameSearchDone(lul[0]);
589 }
590 else
591 {
592 auto *resultsdialog =
594
595 connect(resultsdialog, &MetadataResultsDialog::haveResult,
597 Qt::QueuedConnection);
598
599 if (resultsdialog->Create())
600 m_popupStack->AddScreen(resultsdialog);
601 }
602 }
603 else if (event->type() == MetadataLookupFailure::kEventType)
604 {
605 auto *luf = dynamic_cast<MetadataLookupFailure *>(event);
606 if (luf == nullptr)
607 return;
608 MetadataLookupList lul = luf->m_lookupList;
609
610 if (m_busyPopup)
611 {
613 m_busyPopup = nullptr;
614 }
615
616 if (!lul.empty())
617 {
618 MetadataLookup *lookup = lul[0];
619 auto *node = lookup->GetData().value<MythGenericTree *>();
620 if (node)
621 {
622 auto *metadata = node->GetData().value<RomInfo *>();
623 if (metadata)
624 {
625 }
626 }
627 LOG(VB_GENERAL, LOG_ERR,
628 QString("No results found for %1").arg(lookup->GetTitle()));
629 }
630 }
631 else if (event->type() == ImageDLEvent::kEventType)
632 {
633 auto *ide = dynamic_cast<ImageDLEvent *>(event);
634 if (ide == nullptr)
635 return;
636 MetadataLookup *lookup = ide->m_item;
637
638 if (!lookup)
639 return;
640
642 }
643 else if (event->type() == ImageDLFailureEvent::kEventType)
644 {
645 MythErrorNotification n(tr("Failed to retrieve image(s)"),
646 sLocation,
647 tr("Check logs"));
649 }
650}
651
653{
654 QString layer = node->GetText();
655 int childDepth = node->getInt() + 1;
656 QString childLevel = getChildLevelString(node);
657 QString filter = getFilter(node);
658 bool childIsLeaf = childDepth == getLevelsOnThisBranch(node) + 1;
659 auto *romInfo = node->GetData().value<RomInfo *>();
660
661 if (childLevel.isEmpty())
662 childLevel = "gamename";
663
664 QString columns;
665 QString conj = "where ";
666
667 if (!filter.isEmpty())
668 {
669 filter = conj + filter;
670 conj = " and ";
671 }
672 if ((childLevel == "gamename") && (m_gameShowFileName))
673 {
674 columns = childIsLeaf
675 ? "romname,`system`,year,genre,gamename"
676 : "romname";
677
678 if (m_showHashed)
679 filter += " and romname like '" + layer + "%'";
680
681 }
682 else if ((childLevel == "gamename") && (layer.length() == 1))
683 {
684 columns = childIsLeaf
685 ? childLevel + ",`system`,year,genre,gamename"
686 : childLevel;
687
688 if (m_showHashed)
689 filter += " and gamename like '" + layer + "%'";
690
691 }
692 else if (childLevel == "hash")
693 {
694 columns = "left(gamename,1)";
695 }
696 else
697 {
698
699 columns = childIsLeaf
700 ? childLevel + ",`system`,year,genre,gamename"
701 : childLevel;
702 }
703
704 // this whole section ought to be in rominfo.cpp really, but I've put it
705 // in here for now to minimise the number of files changed by this mod
706 if (romInfo)
707 {
708 if (!romInfo->System().isEmpty())
709 {
710 filter += conj + "trim(system)=:SYSTEM";
711 conj = " and ";
712 }
713 if (!romInfo->Year().isEmpty())
714 {
715 filter += conj + "year=:YEAR";
716 conj = " and ";
717 }
718 if (!romInfo->Genre().isEmpty())
719 {
720 filter += conj + "trim(genre)=:GENRE";
721 conj = " and ";
722 }
723 if (!romInfo->Plot().isEmpty())
724 {
725 filter += conj + "plot=:PLOT";
726 conj = " and ";
727 }
728 if (!romInfo->Publisher().isEmpty())
729 {
730 filter += conj + "publisher=:PUBLISHER";
731 conj = " and ";
732 }
733 if (!romInfo->Gamename().isEmpty())
734 {
735 filter += conj + "trim(gamename)=:GAMENAME";
736 }
737
738 }
739
740 filter += conj + " display = 1 ";
741
742 QString sql;
743
744 if ((childLevel == "gamename") && (m_gameShowFileName))
745 {
746 sql = "select distinct "
747 + columns
748 + " from gamemetadata "
749 + filter
750 + " order by romname"
751 + ";";
752 }
753 else if (childLevel == "hash")
754 {
755 sql = "select distinct "
756 + columns
757 + " from gamemetadata "
758 + filter
759 + " order by gamename,romname"
760 + ";";
761 }
762 else
763 {
764 sql = "select distinct "
765 + columns
766 + " from gamemetadata "
767 + filter
768 + " order by "
769 + childLevel
770 + ";";
771 }
772
773 return sql;
774}
775
777{
778 unsigned this_level = node->getInt();
779 while (node->getInt() != 1)
780 node = node->getParent();
781
782 auto *gi = node->GetData().value<GameTreeInfo *>();
783 return gi ? gi->getLevel(this_level - 1) : "<invalid>";
784}
785
787{
788 while (node->getInt() != 1)
789 node = node->getParent();
790 auto *gi = node->GetData().value<GameTreeInfo *>();
791 return gi ? gi->getFilter() : "<invalid>";
792}
793
795{
796 while (node->getInt() != 1)
797 node = node->getParent();
798
799 auto *gi = node->GetData().value<GameTreeInfo *>();
800 return gi ? gi->getDepth() : 0;
801}
802
804{
805 return (node->getInt() - 1) == getLevelsOnThisBranch(node);
806}
807
809{
810// QString layername = node->GetText();
811 auto *romInfo = node->GetData().value<RomInfo *>();
812
814
815 query.prepare(getFillSql(node));
816
817 if (romInfo)
818 {
819 if (!romInfo->System().isEmpty())
820 query.bindValue(":SYSTEM", romInfo->System());
821 if (!romInfo->Year().isEmpty())
822 query.bindValue(":YEAR", romInfo->Year());
823 if (!romInfo->Genre().isEmpty())
824 query.bindValue(":GENRE", romInfo->Genre());
825 if (!romInfo->Plot().isEmpty())
826 query.bindValue(":PLOT", romInfo->Plot());
827 if (!romInfo->Publisher().isEmpty())
828 query.bindValue(":PUBLISHER", romInfo->Publisher());
829 if (!romInfo->Gamename().isEmpty())
830 query.bindValue(":GAMENAME", romInfo->Gamename());
831 }
832
833 bool IsLeaf = node->getInt() == getLevelsOnThisBranch(node);
834 if (query.exec() && query.size() > 0)
835 {
836 while (query.next())
837 {
838 QString current = query.value(0).toString().trimmed();
839 auto *new_node =
840 new MythGenericTree(current, node->getInt() + 1, false);
841 if (IsLeaf)
842 {
843 auto *temp = new RomInfo();
844 temp->setSystem(query.value(1).toString().trimmed());
845 temp->setYear(query.value(2).toString());
846 temp->setGenre(query.value(3).toString().trimmed());
847 temp->setGamename(query.value(4).toString().trimmed());
848 new_node->SetData(QVariant::fromValue(temp));
849 node->addNode(new_node);
850 }
851 else
852 {
853 RomInfo *newRomInfo = nullptr;
854 if (node->getInt() > 1)
855 {
856 auto *currentRomInfo = node->GetData().value<RomInfo *>();
857 newRomInfo = new RomInfo(*currentRomInfo);
858 }
859 else
860 {
861 newRomInfo = new RomInfo();
862 }
863 new_node->SetData(QVariant::fromValue(newRomInfo));
864 node->addNode(new_node);
865 if (getChildLevelString(node) != "hash")
866 newRomInfo->setField(getChildLevelString(node), current);
867 }
868 }
869 }
870}
871
873{
874 MythGenericTree *top_level = node;
875 while (top_level->getParent() != m_gameTree)
876 {
877 top_level = top_level->getParent();
878 }
879
880 QList<MythGenericTree*>::iterator it;
881 QList<MythGenericTree*> *children = m_gameTree->getAllChildren();
882
883 for (it = children->begin(); it != children->end(); ++it)
884 {
885 MythGenericTree *child = *it;
886 if (child != top_level)
887 {
888 child->deleteAllChildren();
889 }
890 }
891}
892
894{
895 resetOtherTrees(node);
896
897 if (node->getParent() == m_favouriteNode && !romInfo->Favorite())
898 {
899 // node is being removed
901 }
902 else
903 {
904 nodeChanged(node);
905 }
906}
907
909 bool automode)
910{
911 if (!node)
913
914 if (!node)
915 return;
916
917 auto *metadata = node->GetData().value<RomInfo *>();
918 if (!metadata)
919 return;
920
921 auto *lookup = new MetadataLookup();
922 lookup->SetStep(kLookupSearch);
923 lookup->SetType(kMetadataGame);
924 lookup->SetData(QVariant::fromValue(node));
925
926 if (automode)
927 {
928 lookup->SetAutomatic(true);
929 }
930
931 lookup->SetTitle(metadata->Gamename());
932 lookup->SetInetref(metadata->Inetref());
933 if (m_query->isRunning())
934 m_query->prependLookup(lookup);
935 else
936 m_query->addLookup(lookup);
937
938 if (!automode)
939 {
940 //: %1 is the game name
941 QString msg = tr("Fetching details for %1")
942 .arg(metadata->Gamename());
943 createBusyDialog(msg);
944 }
945}
946
947void GameUI::createBusyDialog(const QString& title)
948{
949 if (m_busyPopup)
950 return;
951
952 const QString& message = title;
953
955 "mythgamebusydialog");
956
957 if (m_busyPopup->Create())
959}
960
962{
963 if (!lookup)
964 return;
965
966 lookup->SetStep(kLookupData);
967 lookup->IncrRef();
968 m_query->prependLookup(lookup);
969}
970
972{
973 if (m_busyPopup)
974 {
976 m_busyPopup = nullptr;
977 }
978
979 if (!lookup)
980 return;
981
982 auto *node = lookup->GetData().value<MythGenericTree *>();
983 if (!node)
984 return;
985
986 auto *metadata = node->GetData().value<RomInfo *>();
987 if (!metadata)
988 return;
989
990 metadata->setGamename(lookup->GetTitle());
991 metadata->setYear(QString::number(lookup->GetYear()));
992 metadata->setPlot(lookup->GetDescription());
993 metadata->setSystem(lookup->GetSystem());
994
995 QStringList coverart;
996 QStringList fanart;
997 QStringList screenshot;
998
999 // Imagery
1000 ArtworkList coverartlist = lookup->GetArtwork(kArtworkCoverart);
1001 for (const auto & art : std::as_const(coverartlist))
1002 coverart.prepend(art.url);
1003 ArtworkList fanartlist = lookup->GetArtwork(kArtworkFanart);
1004 for (const auto & art : std::as_const(fanartlist))
1005 fanart.prepend(art.url);
1006 ArtworkList screenshotlist = lookup->GetArtwork(kArtworkScreenshot);
1007 for (const auto & art : std::as_const(screenshotlist))
1008 screenshot.prepend(art.url);
1009
1010 StartGameImageSet(node, coverart, fanart, screenshot);
1011
1012 metadata->SaveToDatabase();
1013 updateChangedNode(node, metadata);
1014}
1015
1016void GameUI::StartGameImageSet(MythGenericTree *node, QStringList coverart,
1017 QStringList fanart, QStringList screenshot)
1018{
1019 if (!node)
1020 return;
1021
1022 auto *metadata = node->GetData().value<RomInfo *>();
1023 if (!metadata)
1024 return;
1025
1026 DownloadMap map;
1027
1028 if (metadata->Boxart().isEmpty() && !coverart.empty())
1029 {
1031 info.url = coverart.takeAt(0).trimmed();
1032 map.insert(kArtworkCoverart, info);
1033 }
1034
1035 if (metadata->Fanart().isEmpty() && !fanart.empty())
1036 {
1038 info.url = fanart.takeAt(0).trimmed();
1039 map.insert(kArtworkFanart, info);
1040 }
1041
1042 if (metadata->Screenshot().isEmpty() && !screenshot.empty())
1043 {
1045 info.url = screenshot.takeAt(0).trimmed();
1046 map.insert(kArtworkScreenshot, info);
1047 }
1048
1049 auto *lookup = new MetadataLookup();
1050 lookup->SetTitle(metadata->Gamename());
1051 lookup->SetSystem(metadata->System());
1052 lookup->SetInetref(metadata->Inetref());
1053 lookup->SetType(kMetadataGame);
1054 lookup->SetDownloads(map);
1055 lookup->SetData(QVariant::fromValue(node));
1056
1058}
1059
1061{
1062 if (!lookup)
1063 return;
1064
1065 auto *node = lookup->GetData().value<MythGenericTree *>();
1066 if (!node)
1067 return;
1068
1069 auto *metadata = node->GetData().value<RomInfo *>();
1070 if (!metadata)
1071 return;
1072
1073 DownloadMap downloads = lookup->GetDownloads();
1074
1075 if (downloads.isEmpty())
1076 return;
1077
1078 for (DownloadMap::iterator i = downloads.begin();
1079 i != downloads.end(); ++i)
1080 {
1081 VideoArtworkType type = i.key();
1082 const ArtworkInfo& info = i.value();
1083 QString filename = info.url;
1084
1085 if (type == kArtworkCoverart)
1086 metadata->setBoxart(filename);
1087 else if (type == kArtworkFanart)
1088 metadata->setFanart(filename);
1089 else if (type == kArtworkScreenshot)
1090 metadata->setScreenshot(filename);
1091 }
1092
1093 metadata->SaveToDatabase();
1094 updateChangedNode(node, metadata);
1095}
1096
1098{
1099 if (!m_scanner)
1100 m_scanner = new GameScanner();
1103}
1104
1105void GameUI::reloadAllData(bool dbChanged)
1106{
1107 delete m_scanner;
1108 m_scanner = nullptr;
1109
1110 if (dbChanged)
1111 BuildTree();
1112}
1113
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:41
static const Type kEventType
Definition: mythdialogbox.h:56
static uint count(void)
Definition: gamehandler.cpp:97
static GameHandler * getHandler(uint i)
Definition: gamehandler.cpp:55
QString SystemName() const
Definition: gamehandler.h:105
static void Launchgame(RomInfo *romdata, const QString &systemname)
void doScanAll(void)
Definition: gamescan.cpp:232
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:803
MythUIButtonTree * m_gameUITree
Definition: gameui.h:82
void OnGameSearchListSelection(RefCountHandler< MetadataLookup > lookup)
Definition: gameui.cpp:961
MetadataDownload * m_query
Definition: gameui.h:93
void reloadAllData(bool dbchanged)
Definition: gameui.cpp:1105
bool Create() override
Definition: gameui.cpp:57
bool m_gameShowFileName
Definition: gameui.h:74
MythUIStateType * m_gameFavouriteState
Definition: gameui.h:88
MythUIBusyDialog * m_busyPopup
Definition: gameui.h:79
void nodeChanged(MythGenericTree *node)
Definition: gameui.cpp:217
static QString getChildLevelString(MythGenericTree *node)
Definition: gameui.cpp:776
void fillNode(MythGenericTree *node)
Definition: gameui.cpp:808
MythUIText * m_gamePlotText
Definition: gameui.h:87
void searchStart(void)
Definition: gameui.cpp:462
void gameSearch(MythGenericTree *node=nullptr, bool automode=false)
Definition: gameui.cpp:908
MythUIText * m_gameSystemText
Definition: gameui.h:84
void updateChangedNode(MythGenericTree *node, RomInfo *romInfo)
Definition: gameui.cpp:893
void showImages(void)
Definition: gameui.cpp:292
MythUIText * m_gameYearText
Definition: gameui.h:85
void StartGameImageSet(MythGenericTree *node, QStringList coverart, QStringList fanart, QStringList screenshot)
Definition: gameui.cpp:1016
MythUIText * m_gameTitleText
Definition: gameui.h:83
void BuildTree()
Definition: gameui.cpp:95
void createBusyDialog(const QString &title)
Definition: gameui.cpp:947
void edit(void)
Definition: gameui.cpp:379
MythUIText * m_gameGenreText
Definition: gameui.h:86
bool m_showHashed
Definition: gameui.h:73
static int getLevelsOnThisBranch(MythGenericTree *node)
Definition: gameui.cpp:794
void clearRomInfo(void)
Definition: gameui.cpp:354
QString getFillSql(MythGenericTree *node) const
Definition: gameui.cpp:652
MythScreenStack * m_popupStack
Definition: gameui.h:80
void searchComplete(const QString &string)
Definition: gameui.cpp:302
MetadataImageDownload * m_imageDownload
Definition: gameui.h:94
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: gameui.cpp:182
static QString getFilter(MythGenericTree *node)
Definition: gameui.cpp:786
MythUIImage * m_boxImage
Definition: gameui.h:91
void toggleFavorite(void)
Definition: gameui.cpp:497
void customEvent(QEvent *event) override
Definition: gameui.cpp:508
void doScan(void)
Definition: gameui.cpp:1097
void ShowMenu(void) override
Definition: gameui.cpp:426
void showInfo(void)
Definition: gameui.cpp:403
GameScanner * m_scanner
Definition: gameui.h:96
MythGenericTree * m_favouriteNode
Definition: gameui.h:77
void resetOtherTrees(MythGenericTree *node)
Definition: gameui.cpp:872
MythUIImage * m_fanartImage
Definition: gameui.h:90
void itemClicked(MythUIButtonListItem *item)
Definition: gameui.cpp:254
MythGenericTree * m_gameTree
Definition: gameui.h:76
void OnGameSearchDone(MetadataLookup *lookup)
Definition: gameui.cpp:971
void handleDownloadedImages(MetadataLookup *lookup)
Definition: gameui.cpp:1060
MythUIImage * m_gameImage
Definition: gameui.h:89
void updateRomInfo(RomInfo *rom)
Definition: gameui.cpp:316
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:550
bool isRunning(void) const
Definition: mthread.cpp:263
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:213
void setField(const QString &field, const QString &data)
Definition: rominfo.cpp:172
QString System() const
Definition: rominfo.h:75
QString Boxart() const
Definition: rominfo.h:69
void fillData()
Definition: rominfo.cpp:247
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
STL namespace.
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27