gameexecutablepicker.cpp
1 //------------------------------------------------------------------------------
2 // gameexecutablepicker.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301 USA
19 //
20 //------------------------------------------------------------------------------
21 // Copyright (C) 2015 "Zalewa" <zalewapl@gmail.com>
22 //------------------------------------------------------------------------------
23 #include "gameexecutablepicker.h"
24 
25 #include "configuration/doomseekerconfig.h"
26 #include "datapaths.h"
27 #include "filefilter.h"
28 #include "gui/commongui.h"
29 #include "ini/ini.h"
30 #include "plugins/engineplugin.h"
31 #include "serverapi/exefile.h"
32 #include "serverapi/gameexefactory.h"
33 #include "serverapi/gamefile.h"
34 #include "templatedpathresolver.h"
35 #include "ui_gameexecutablepicker.h"
36 #include <QFileDialog>
37 #include <QStyle>
38 
39 DClass<GameExecutablePicker> : public Ui::GameExecutablePicker
40 {
41 public:
42  int allowedExecs;
43  EnginePlugin *plugin;
44 };
45 DPointered(GameExecutablePicker)
46 
48  : QWidget(parent)
49 {
50  d->setupUi(this);
51  d->allowedExecs = 0;
52  d->plugin = nullptr;
53 
54  d->btnBrowse->setIcon(style()->standardIcon(QStyle::SP_DirOpenIcon));
55 
56  showWarning("");
57 }
58 
59 GameExecutablePicker::~GameExecutablePicker()
60 {
61 }
62 
63 void GameExecutablePicker::add(const QString &path)
64 {
65  if (!path.trimmed().isEmpty() && d->executableInput->findText(path) < 0)
66  d->executableInput->addItem(path);
67 }
68 
69 void GameExecutablePicker::browse()
70 {
71  showWarning("");
72  QString dialogDir = gConfig.doomseeker.previousCreateServerExecDir;
73  QString path = QFileDialog::getOpenFileName(this, tr("Doomseeker - Browse executable"),
74  dialogDir, FileFilter::executableFilesFilter());
75 
76  if (!path.isEmpty())
77  {
78  path = gDefaultDataPaths->portablizePath(path);
79  gConfig.doomseeker.previousCreateServerExecDir = path;
80  d->executableInput->setCurrentText(path);
81  add(path);
82  }
83 }
84 
85 
86 GameFileList GameExecutablePicker::gameExecutables() const
87 {
88  GameFileList files = d->plugin->gameExe()->gameFiles();
89  GameFileList candidates = GameFiles::allFlagMatchExecutables(files, d->allowedExecs);
90  if (d->allowedExecs & GameFile::Client)
91  candidates.prepend(GameFiles::defaultClientExecutable(files));
92  else if (d->allowedExecs & GameFile::Server)
93  candidates.prepend(GameFiles::defaultServerExecutable(files));
94  else if (d->allowedExecs & GameFile::Offline)
95  candidates.prepend(GameFiles::defaultOfflineExecutable(files));
96  return candidates;
97 }
98 
99 QString GameExecutablePicker::path() const
100 {
101  return d->executableInput->currentText();
102 }
103 
104 void GameExecutablePicker::setPath(const QString &path)
105 {
106  d->executableInput->setCurrentText(path);
107 }
108 
109 void GameExecutablePicker::setExecutableToDefault()
110 {
111  showWarning("");
112  IniSection *cfg = d->plugin->data()->pConfig;
113  if (cfg == nullptr)
114  {
115  showWarning(tr("Plugin doesn't support configuration."));
116  return;
117  }
118 
119  GameFileList execs = gameExecutables();
120  if (execs.isEmpty())
121  {
122  showWarning(tr("Game doesn't define any executables for this game setup."));
123  return;
124  }
125 
126  for (const GameFile &candidate : execs.asQList())
127  {
128  const QString path = cfg->value(candidate.configName()).toString();
129  if (!path.isEmpty())
130  {
131  d->executableInput->setCurrentText(path);
132  return;
133  }
134  }
135  showWarning(tr("Default executable for this game isn't configured."));
136 }
137 
139 {
140  d->allowedExecs = execs;
141  reloadExecutables();
142 }
143 
144 void GameExecutablePicker::setPlugin(EnginePlugin *plugin)
145 {
146  d->plugin = plugin;
147  reloadExecutables();
148 }
149 
150 void GameExecutablePicker::showWarning(const QString &msg)
151 {
152  d->lblWarning->setVisible(!msg.trimmed().isEmpty());
153  d->lblWarning->setToolTip(msg);
154 }
155 
156 void GameExecutablePicker::reloadExecutables()
157 {
158  showWarning("");
159  if (d->plugin == nullptr)
160  {
161  showWarning(tr("Game plugin not set."));
162  return;
163  }
164  QString currentExec = d->executableInput->currentText();
165  d->executableInput->clear();
166  IniSection *cfg = d->plugin->data()->pConfig;
167  if (cfg == nullptr)
168  {
169  d->executableInput->setCurrentText(currentExec);
170  return;
171  }
172 
173  GameFileList files = gameExecutables();
174  for (const GameFile &file : files.asQList())
175  {
176  add(cfg->value(file.configName()).toString());
177  }
178  for (const ExeFilePath &exe : d->plugin->gameExe()->additionalExecutables(d->allowedExecs))
179  {
180  QFileInfo fileInfo(gDoomseekerTemplatedPathResolver().resolve(exe.path()));
181  if (fileInfo.isFile())
182  add(gDefaultDataPaths->portablizePath(exe.path()));
183  }
184 
185  if (d->executableInput->findText(currentExec) >= 0)
186  d->executableInput->setCurrentText(currentExec);
187  else
188  setExecutableToDefault();
189 }