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