MythTV master
gamescan.cpp
Go to the documentation of this file.
1// C++
2#include <utility>
3
4// Qt
5#include <QApplication>
6#include <QImageReader>
7#include <QStringList>
8#include <QThread>
9#include <QUrl>
10
11// MythTV
20
21// MythGame
22#include "gamescan.h"
23#include "gamehandler.h"
24#include "rominfo.h"
25
27
29 MThread("GameScanner"),
30 m_hasGUI(gCoreContext->HasGUI())
31{
32}
33
35{
36 RunProlog();
37
38 LOG(VB_GENERAL, LOG_INFO, QString("Beginning Game Scan."));
39
40 m_files.clear();
41 m_remove.clear();
43
46 updateDB();
47
48 LOG(VB_GENERAL, LOG_INFO, QString("Finished Game Scan."));
49
50 RunEpilog();
51}
52
53
55{
57 if (info)
58 {
59 info->DeleteFromDatabase();
60 delete info;
61 info = nullptr;
62 }
63}
64
66{
67 int counter = 0;
68
69 if (m_hasGUI)
70 SendProgressEvent(counter, (uint)m_dbgames.count(),
71 GameScanner::tr("Verifying game files..."));
72
73 // For every file we know about, check to see if it still exists.
74 for (const auto *info : std::as_const(m_dbgames))
75 {
76 QString romfile = info->Romname();
77 QString gametype = info->GameType();
78 if (!romfile.isEmpty())
79 {
80 bool found = false;
81 // NOLINTNEXTLINE(modernize-loop-convert)
82 for (auto p2 = m_files.begin(); p2 != m_files.end(); ++p2)
83 {
84 if ((*p2).romfile == romfile &&
85 (*p2).gametype == gametype)
86 {
87 // We're done here, this file matches one in the DB
88 (*p2).indb = true;
89 found = true;
90 continue;
91 }
92 }
93 if (!found)
94 {
95 m_remove.append(info->Id());
96 }
97 }
98 if (m_hasGUI)
99 SendProgressEvent(++counter);
100
101 delete info;
102 info = nullptr;
103 }
104}
105
107{
108 uint counter = 0;
109 if (m_hasGUI)
110 SendProgressEvent(counter, (uint)(m_files.size() + m_remove.size()),
111 GameScanner::tr("Updating game database..."));
112
113 for (const auto & file : std::as_const(m_files))
114 {
115 if (!file.indb)
116 {
117 RomInfo add(0, file.romfile, file.system,
118 file.romname, "", "", false, file.rompath,
119 "", "", 0, file.gametype, 0, "", "", "",
120 "", "", "", "", "");
121 add.SaveToDatabase();
122 m_dbDataChanged = true;
123 }
124 if (m_hasGUI)
125 SendProgressEvent(++counter);
126 }
127
128 for (const uint & p : std::as_const(m_remove))
129 {
131 m_dbDataChanged = true;
132 }
133}
134
136{
137 if (m_handlers.empty())
138 return false;
139
140 int counter = 0;
141
142 if (m_hasGUI)
143 SendProgressEvent(counter, (uint)m_handlers.size(),
144 GameScanner::tr("Searching for games..."));
145
146 for (auto * handler : std::as_const(m_handlers))
147 {
148 QDir dir(handler->SystemRomPath());
149 QStringList extensions = handler->ValidExtensions();
150 QStringList filters;
151 for (const auto & ext : std::as_const(extensions))
152 {
153 filters.append(QString("*.%1").arg(ext));
154 }
155
156 dir.setNameFilters(filters);
157 dir.setFilter(QDir::Files | QDir::Readable | QDir::NoDotAndDotDot);
158
159 QStringList files = dir.entryList();
160 for (const auto & file : std::as_const(files))
161 {
163 info.system = handler->SystemName();
164 info.gametype = handler->GameType();
165 info.romfile = file;
166 info.rompath = handler->SystemRomPath();
167 info.romname = QFileInfo(file).baseName();
168 info.indb = false;
169 m_files.append(info);
170 }
171
172 if (m_hasGUI)
173 SendProgressEvent(++counter);
174 }
175
176 return true;
177}
178
180 QString message)
181{
182 if (!m_dialog)
183 return;
184
185 auto *pue = new ProgressUpdateEvent(progress, total, std::move(message));
186 QApplication::postEvent(m_dialog, pue);
187}
188
190 : m_scanThread(new GameScannerThread())
191{
192}
193
195{
197 delete m_scanThread;
198}
199
200void GameScanner::doScan(QList<GameHandler*> handlers)
201{
202 if (m_scanThread->isRunning())
203 return;
204
205 if (gCoreContext->HasGUI())
206 {
207 MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
208
209 auto *progressDlg = new MythUIProgressDialog("",
210 popupStack, "gamescanprogressdialog");
211
212 if (progressDlg->Create())
213 {
214 popupStack->AddScreen(progressDlg, false);
215 connect(m_scanThread->qthread(), &QThread::finished,
216 progressDlg, &MythScreenType::Close);
217 connect(m_scanThread->qthread(), &QThread::finished,
219 }
220 else
221 {
222 delete progressDlg;
223 progressDlg = nullptr;
224 }
225 m_scanThread->SetProgressDialog(progressDlg);
226 }
227
228 m_scanThread->SetHandlers(std::move(handlers));
230}
231
233{
234 QList<GameHandler*> hlist;
235
237 query.prepare("SELECT DISTINCT playername FROM gameplayers "
238 "WHERE playername <> '';");
239
240 if (!query.exec())
241 MythDB::DBError("doScanAll - selecting playername", query);
242
243 while (query.next())
244 {
245 QString name = query.value(0).toString();
247 if (hnd)
248 hlist.append(hnd);
249 }
250
251 doScan(hlist);
252}
253
255{
257}
258
static GameHandler * GetHandlerByName(const QString &systemname)
QList< uint > m_remove
Definition: gamescan.h:63
QList< GameHandler * > m_handlers
Definition: gamescan.h:60
RomFileInfoList m_files
Definition: gamescan.h:62
QList< RomInfo * > m_dbgames
Definition: gamescan.h:64
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: gamescan.cpp:34
void SetProgressDialog(MythUIProgressDialog *dialog)
Definition: gamescan.h:42
void SendProgressEvent(uint progress, uint total=0, QString message=QString())
Definition: gamescan.cpp:179
bool getDataChanged() const
Definition: gamescan.h:44
void verifyFiles()
Definition: gamescan.cpp:65
MythUIProgressDialog * m_dialog
Definition: gamescan.h:66
void SetHandlers(QList< GameHandler * > handlers)
Definition: gamescan.h:41
bool buildFileList()
Definition: gamescan.cpp:135
static void removeOrphan(int id)
Definition: gamescan.cpp:54
GameScannerThread(void)
Definition: gamescan.cpp:28
bool m_dbDataChanged
Definition: gamescan.h:68
void doScanAll(void)
Definition: gamescan.cpp:232
void finishedScan()
Definition: gamescan.cpp:254
GameScannerThread * m_scanThread
Definition: gamescan.h:89
void doScan(QList< GameHandler * > handlers)
Definition: gamescan.cpp:200
~GameScanner() override
Definition: gamescan.cpp:194
void finished(bool)
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:837
QVariant value(int i) const
Definition: mythdbcon.h:204
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:49
bool isRunning(void) const
Definition: mthread.cpp:263
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:196
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:209
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:300
QThread * qthread(void)
Returns the thread, this will always return the same pointer no matter how often you restart the thre...
Definition: mthread.cpp:233
bool HasGUI(void) const
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:226
MythScreenStack * GetStack(const QString &Stackname)
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
virtual void Close()
MythUIProgressDialog(QString message, MythScreenStack *parent, const char *name)
void SaveToDatabase() const
Definition: rominfo.cpp:20
static QList< RomInfo * > GetAllRomInfo()
Definition: rominfo.cpp:320
static RomInfo * GetRomInfoById(int id)
Definition: rominfo.cpp:368
unsigned int uint
Definition: freesurround.h:24
static QList< GameHandler * > * handlers
Definition: gamehandler.cpp:28
static guint32 * p2
Definition: goom_core.cpp:26
bool progress
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythMainWindow * GetMythMainWindow(void)
dictionary info
Definition: azlyrics.py:7