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