MythTV master
gamesettings.cpp
Go to the documentation of this file.
1// C++
2#include <array>
3
4// Qt
5#include <QCoreApplication>
6
7// MythTV
11
12// MythGame
13#include "gamesettings.h"
14
15struct GameTypes {
16 QString m_nameStr;
17 QString m_idStr;
18 QString m_extensions;
19};
20
21const std::array<GameTypes,12> GameTypeList
22{{
23 { QT_TRANSLATE_NOOP("(GameTypes)", "OTHER"), "OTHER", "" },
24 { QT_TRANSLATE_NOOP("(GameTypes)", "AMIGA"), "AMIGA", "adf,ipf" },
25 { QT_TRANSLATE_NOOP("(GameTypes)", "ATARI"), "ATARI", "bin,a26" },
26 { QT_TRANSLATE_NOOP("(GameTypes)", "GAMEGEAR"), "GAMEGEAR", "gg" },
27 { QT_TRANSLATE_NOOP("(GameTypes)", "GENESIS/MEGADRIVE"), "GENESIS", "smd,bin,md" },
28 { QT_TRANSLATE_NOOP("(GameTypes)", "MAME"), "MAME", "" },
29 { QT_TRANSLATE_NOOP("(GameTypes)", "N64"), "N64", "v64,n64" },
30 { QT_TRANSLATE_NOOP("(GameTypes)", "NES"), "NES", "zip,nes" },
31 { QT_TRANSLATE_NOOP("(GameTypes)", "PC GAME"), "PC", "" },
32 { QT_TRANSLATE_NOOP("(GameTypes)", "PCE/TG16"),"PCE", "pce" },
33 { QT_TRANSLATE_NOOP("(GameTypes)", "SEGA/MASTER SYSTEM"), "SEGA", "sms" },
34 { QT_TRANSLATE_NOOP("(GameTypes)", "SNES"), "SNES", "zip,smc,sfc,fig,swc" }
35}};
36
37QString GetGameTypeName(const QString &GameType)
38{
39 auto sametype = [GameType](const auto & console)
40 { return console.m_idStr == GameType; };
41 const auto *const con = std::find_if(GameTypeList.cbegin(), GameTypeList.cend(), sametype);
42 return (con != GameTypeList.cend())
43 ? QCoreApplication::translate("(GameTypes)", con->m_nameStr.toUtf8())
44 : "";
45}
46
47QString GetGameTypeExtensions(const QString &GameType)
48{
49 auto sametype = [GameType](const auto & console)
50 { return console.m_idStr == GameType; };
51 const auto *const con = std::find_if(GameTypeList.cbegin(), GameTypeList.cend(), sametype);
52 return (con != GameTypeList.cend()) ? con->m_extensions : "";
53}
54
55// -----------------------------------------------------------------------
56
57// General Settings
58#undef TR
59#define TR GameGeneralSettings::tr
60
62{
63 auto *gc = new HostTextEditSetting("GameAllTreeLevels");
64 gc->setLabel(TR("Game display order"));
65 gc->setValue("system gamename");
66 gc->setHelpText(TR("Order in which to sort the "
67 "games - this is for all "
68 "systems. Available choices: "
69 "system, year, genre and "
70 "gamename"));
71 return gc;
72}
73
75{
76 auto *gc = new HostTextEditSetting("GameFavTreeLevels");
77 gc->setLabel(TR("Favorite display order"));
78 gc->setValue("gamename");
79 gc->setHelpText(TR("Order in which to sort the "
80 "games marked as favorites "
81 "- this is for all systems. "
82 "Available choices: system, "
83 "year, genre and gamename"));
84 return gc;
85}
86
88{
89 auto *gc = new HostCheckBoxSetting("GameDeepScan");
90 gc->setLabel(TR("Indepth Game Scan"));
91 gc->setHelpText(
92 TR("Enabling this causes a game scan to "
93 "gather CRC values and attempt to find out "
94 "more detailed information about the game: "
95 "NOTE this can greatly increase the time a "
96 "game scan takes based on the amount of "
97 "games scanned."));
98 return gc;
99}
100
102{
103 auto *gc = new HostCheckBoxSetting("GameRemovalPrompt");
104 gc->setLabel(TR("Prompt for removal of deleted ROM(s)"));
105 gc->setHelpText(TR("This enables a prompt for "
106 "removing deleted ROMs from "
107 "the database during a game "
108 "scan"));
109
110 return gc;
111}
112
114{
115 auto *gc = new HostCheckBoxSetting("GameShowFileNames");
116 gc->setLabel(TR("Display Files Names in Game "
117 "Tree"));
118 gc->setHelpText(TR("Enabling this causes the "
119 "filenames to be displayed in "
120 "the game tree rather than the "
121 "trimmed/looked up game name"));
122 return gc;
123}
124
126{
127 auto *gc = new HostCheckBoxSetting("GameTreeView");
128 gc->setLabel(TR("Hash filenames in display"));
129 gc->setValue(0);
130 gc->setHelpText(TR("Enable hashing of names in "
131 "the display tree. This can "
132 "make navigating long lists "
133 "a little faster"));
134 return gc;
135}
136
138{
139 auto *gc = new HostTextEditSetting("mythgame.screenshotdir");
140 gc->setLabel(TR("Directory where Game Screenshots "
141 "are stored"));
142 gc->setValue(GetConfDir() + "/MythGame/Screenshots");
143 gc->setHelpText(TR("This directory will be the "
144 "default browse location when "
145 "assigning screenshots."));
146 return gc;
147}
148
150{
151 auto *gc = new HostTextEditSetting("mythgame.fanartdir");
152 gc->setLabel(TR("Directory where Game Fanart is "
153 "stored"));
154 gc->setValue(GetConfDir() + "/MythGame/Fanart");
155 gc->setHelpText(TR("This directory will be the "
156 "default browse location when "
157 "assigning fanart."));
158 return gc;
159}
160
162{
163 auto *gc = new HostTextEditSetting("mythgame.boxartdir");
164 gc->setLabel(TR("Directory where Game Boxart is "
165 "stored"));
166 gc->setValue(GetConfDir() + "/MythGame/Boxart");
167 gc->setHelpText(TR("This directory will be the "
168 "default browse location when "
169 "assigning boxart."));
170 return gc;
171}
172
174{
175 setLabel(tr("MythGame Settings -- General"));
185}
186
187// -----------------------------------------------------------------------
188
189// Player Settings
190#undef TR
191#define TR GamePlayerSetting::tr
192
195{
196 GameDBStorage(StorageUser *user, const PlayerId &id, const QString &name)
197 : SimpleDBStorage(user, "gameplayers", name), m_id(id) {}
198protected:
200
201 QString GetWhereClause(MSqlBindings &bindings) const override // SimpleStorage
202 {
203 bindings.insert(":PLAYERID", m_id.Value());
204 return "gameplayerid = :PLAYERID";
205 }
206
207 QString GetSetClause(MSqlBindings &bindings) const override // SimpleStorage
208 {
209 bindings.insert(":SETPLAYERID", m_id.Value());
210 bindings.insert(":SETCOLUMN", m_user->GetDBValue());
211 return QString("gameplayerid = :SETPLAYERID, "
212 "%2 = :SETCOLUMN").arg(GetColumnName());
213 }
214};
215
218{
219 explicit TextEdit(const PlayerId &parent, const QString& column) :
220 MythUITextEditSetting(new GameDBStorage(this, parent, column))
221 {}
222};
223
224struct Name : public TextEdit
225{
226 explicit Name(const PlayerId &parent)
227 : TextEdit(parent, "playername")
228 {
229 setLabel(TR("Player Name"));
230 setHelpText(TR("Name of this Game and or Emulator"));
231 }
232};
233
234struct Command : public TextEdit
235{
236 explicit Command(const PlayerId &parent)
237 : TextEdit(parent, "commandline")
238 {
239 setLabel(TR("Command"));
240 setHelpText(TR("Binary and optional parameters. Multiple commands "
241 "separated with \';\' . Use \%s for the ROM name. "
242 "\%d1, \%d2, \%d3 and \%d4 represent disks in a "
243 "multidisk/game. %s auto appended if not specified"));
244 }
245};
246
248{
249 explicit GameType(const PlayerId &parent) :
250 MythUIComboBoxSetting(new GameDBStorage(this, parent, "gametype"))
251 {
252 //: Game type
253 setLabel(TR("Type"));
254 for (const auto & console : GameTypeList)
255 {
256 addSelection(QCoreApplication::translate("(GameTypes)",
257 console.m_nameStr.toUtf8()),
258 console.m_idStr);
259 }
260 setValue(0);
261 setHelpText(TR("Type of Game/Emulator. Mostly for informational "
262 "purposes and has little effect on the "
263 "function of your system."));
264 }
265};
266
267struct RomPath : public TextEdit
268{
269 explicit RomPath(const PlayerId &parent)
270 : TextEdit(parent, "rompath")
271 {
272 setLabel(TR("ROM Path"));
273 setHelpText(TR("Location of the ROM files for this emulator"));
274 }
275};
276
278{
279 explicit WorkingDirPath(const PlayerId &parent)
280 : TextEdit(parent, "workingpath")
281 {
282 setLabel(TR("Working Directory"));
283 setHelpText(TR("Directory to change to before launching emulator. "
284 "Blank is usually fine"));
285 }
286};
287
288struct Extensions : public TextEdit
289{
290 explicit Extensions(const PlayerId &parent)
291 : TextEdit(parent, "extensions")
292 {
293 setLabel(TR("File Extensions"));
294 setHelpText(TR("A comma separated list of all file extensions for this "
295 "emulator. Blank means any file under ROM PATH is "
296 "considered to be used with this emulator"));
297 }
298};
299
301{
302 explicit AllowMultipleRoms(const PlayerId &parent) :
303 MythUICheckBoxSetting(new GameDBStorage(this, parent, "spandisks"))
304 {
305 setLabel(TR("Allow games to span multiple ROMs/disks"));
306 setHelpText(TR("This setting means that we will look for items like "
307 "game.1.rom, game.2.rom and consider them a single game."));
308 }
309};
310
313 : m_id(id)
314{
315 setName(name);
316
317 // Pre-set name for new players
318 auto *nameChild = new Name(m_id);
319 nameChild->setValue(name);
320
321 addChild(nameChild);
322 addChild(new GameType(m_id));
323 addChild(new Command(m_id));
324 addChild(new RomPath(m_id));
328}
329
331{
332 // Allocate id for new player
333 m_id.Save();
335}
336
338{
340 query.prepare("DELETE FROM gameplayers "
341 "WHERE gameplayerid = :PLAYERID");
342
343 query.bindValue(":PLAYERID", m_id.Value());
344
345 if (!query.exec() || !query.isActive())
346 MythDB::DBError("Deleting MythGamePlayerSettings:", query);
347}
348
349// -----------------------------------------------------------------------
350
352{
353 setLabel(tr("Game Players"));
354}
355
357{
359
360 auto *newPlayer = new ButtonStandardSetting(tr("(New Game Player)"));
361 addChild(newPlayer);
362 connect(newPlayer, &ButtonStandardSetting::clicked,
364
365 //: %1 is the player/emulator name, %2 is the type of player/emulator
366 QString playerDisp = tr("%1 (%2)", "Game player/emulator display");
367
369 query.prepare("SELECT gameplayerid, playername, gametype "
370 "FROM gameplayers "
371 "WHERE playername <> '' "
372 "ORDER BY playername;");
373
374 if (!query.exec() || !query.isActive())
375 {
376 MythDB::DBError("GamePlayersSetting::Load", query);
377 }
378 else
379 {
380 while (query.next())
381 {
382 int id = query.value(0).toInt();
383 QString name = query.value(1).toString();
384 QString type = query.value(2).toString();
385
386 auto *child = new GamePlayerSetting(name, id);
387 addChild(child);
388 child->setLabel(playerDisp.arg(name, GetGameTypeName(type)));
389 }
390 }
391
393}
394
396{
397 MythScreenStack *stack = GetMythMainWindow()->GetStack("popup stack");
398 auto *nameDialog = new MythTextInputDialog(stack, tr("Player Name"));
399
400 if (nameDialog->Create())
401 {
402 stack->AddScreen(nameDialog);
403 connect(nameDialog, &MythTextInputDialog::haveResult,
405 }
406 else
407 {
408 delete nameDialog;
409 }
410}
411
412void GamePlayersList::CreateNewPlayer(const QString& name)
413{
414 if (name.isEmpty())
415 return;
416
417 // Database name must be unique
418 for (StandardSetting* child : std::as_const(*getSubSettings()))
419 {
420 if (child->getName() == name)
421 {
422 LOG(VB_GENERAL, LOG_ERR,
423 QString("Player name %1 is already used").arg(name));
424 return;
425 }
426 }
427
428 addChild(new GamePlayerSetting(name));
429
430 // Redraw list
431 setVisible(true);
432}
void Save(void) override
QString GetColumnName(void) const
Definition: mythstorage.h:47
StorageUser * m_user
Definition: mythstorage.h:50
GamePlayerSetting(const QString &name, uint id=0)
Settings for a game player.
void Save() override
void deleteEntry() override
void NewPlayerDialog() const
void Load() override
void CreateNewPlayer(const QString &name)
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 isActive(void) const
Definition: mythdbcon.h:215
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:888
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
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)
Dialog prompting the user to enter a text string.
void haveResult(QString)
void addSelection(const QString &label, QString value=QString(), bool select=false)
void setValue(int value) override
Name(const PlayerId &parent)
virtual void addChild(StandardSetting *child)
virtual void Save(void)
virtual void Load(void)
virtual void setName(const QString &name)
virtual void clearSettings()
virtual void setHelpText(const QString &str)
void setVisible(bool visible)
virtual QList< StandardSetting * > * getSubSettings()
virtual void setLabel(QString str)
virtual QString GetDBValue(void) const =0
unsigned int uint
Definition: freesurround.h:24
static HostTextEditSetting * GameFavTreeLevels()
#define TR
static HostTextEditSetting * GetBoxartDir()
static HostTextEditSetting * GetFanartDir()
QString GetGameTypeName(const QString &GameType)
const std::array< GameTypes, 12 > GameTypeList
QString GetGameTypeExtensions(const QString &GameType)
static HostTextEditSetting * GameAllTreeLevels()
static HostCheckBoxSetting * GameShowFileNames()
static HostCheckBoxSetting * GameDeepScan()
static HostTextEditSetting * GetScreenshotDir()
static HostCheckBoxSetting * GameRemovalPrompt()
static HostCheckBoxSetting * GameTreeView()
QMap< QString, QVariant > MSqlBindings
typedef for a map of string -> string bindings for generic queries.
Definition: mythdbcon.h:100
QString GetConfDir(void)
Definition: mythdirs.cpp:263
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythMainWindow * GetMythMainWindow(void)
AllowMultipleRoms(const PlayerId &parent)
Command(const PlayerId &parent)
Extensions(const PlayerId &parent)
Game player database table reader/writer.
QString GetSetClause(MSqlBindings &bindings) const override
QString GetWhereClause(MSqlBindings &bindings) const override
const PlayerId & m_id
GameDBStorage(StorageUser *user, const PlayerId &id, const QString &name)
GameType(const PlayerId &parent)
QString m_extensions
QString m_nameStr
QString m_idStr
int Value() const
Definition: gamesettings.h:23
RomPath(const PlayerId &parent)
Base for Game textual settings.
TextEdit(const PlayerId &parent, const QString &column)
WorkingDirPath(const PlayerId &parent)