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