engineconfigpage.cpp
1 //------------------------------------------------------------------------------
2 // engineconfigpage.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) 2010 Braden "Blzut3" Obrzut <admin@maniacsvault.net>
22 //------------------------------------------------------------------------------
23 
24 #include "engineconfigpage.h"
25 #include "filefilter.h"
26 #include "gui/widgets/filepickwidget.h"
27 #include "ini/ini.h"
28 #include "plugins/engineplugin.h"
29 #include "serverapi/gameexefactory.h"
30 #include "serverapi/gamefile.h"
31 #include "ui_engineconfigpage.h"
32 
33 #include <QFileDialog>
34 #include <QTimer>
35 
36 DClass<EngineConfigPage> : public Ui::EngineConfigPage
37 {
38 public:
39  class KnownNeighbours : public FilePickWidget::NeighbourStrategy
40  {
41  public:
43  KnownNeighbours(DPtr< ::EngineConfigPage> *wrapper)
44  {
45  this->wrapper = wrapper;
46  }
47  QStringList neighbours() override
48  {
49  return (*wrapper)->parent->collectKnownGameFilePaths();
50  }
51  };
52 
53 
54  ::EngineConfigPage *parent;
55  IniSection *config;
56  EnginePlugin *plugin;
57  bool clientOnly;
58  QList<FilePickWidget *> filePickers;
59  QTimer errorTimer;
60 
61  QStringList readStoredCustomParameters() const
62  {
63  return config->value("StoredCustomParameters").toStringList();
64  }
65 
66  void saveStoredCustomParameters(const QStringList &params)
67  {
68  config->setValue("StoredCustomParameters", params);
69  }
70 
71  bool existsInStoredCustomParameters(const QString &text) const
72  {
73  return readStoredCustomParameters().contains(text);
74  }
75 };
76 
77 DPointeredNoCopy(EngineConfigPage)
78 
79 
80 EngineConfigPage::EngineConfigPage(EnginePlugin *plugin, IniSection &cfg, QWidget *parent)
81  : ConfigPage(parent)
82 {
83  d->parent = this;
84  d->plugin = plugin;
85  d->config = &cfg;
86  d->setupUi(this);
87 
88  d->lblError->hide();
89  d->errorTimer.setInterval(5000);
90  d->errorTimer.setSingleShot(true);
91  this->connect(&d->errorTimer, SIGNAL(timeout()), d->lblError, SLOT(hide()));
92 
93  // Prevent combo box stretching.
94  d->cboCustomParameters->setMinimumContentsLength(25);
95  d->cboCustomParameters->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
96 
97  makeFileBrowsers();
98 
99  if (!plugin->data()->hasMasterClient())
100  d->masterAddressBox->hide();
101 }
102 
103 EngineConfigPage::~EngineConfigPage()
104 {
105 }
106 
107 void EngineConfigPage::addWidget(QWidget *widget)
108 {
109  layout()->removeItem(d->verticalSpacer);
110  layout()->addWidget(widget);
111  layout()->addItem(d->verticalSpacer);
112 }
113 
114 void EngineConfigPage::autoFindNeighbouringPaths()
115 {
116  auto picker = qobject_cast<FilePickWidget *>(sender());
117  if (QFileInfo(picker->path()).isFile())
118  {
119  QStringList knownPaths = collectKnownGameFilePaths();
120  for (FilePickWidget *picker : d->filePickers)
121  {
122  if (picker->isEmpty())
123  {
124  picker->blockSignals(true);
125  picker->findPath();
126  picker->blockSignals(false);
127  }
128  }
129  }
130  emit validationRequested();
131 }
132 
133 QStringList EngineConfigPage::collectKnownGameFilePaths() const
134 {
135  QStringList knownPaths;
136  for (const FilePickWidget *picker : d->filePickers)
137  {
138  if (!picker->isEmpty())
139  knownPaths << picker->path();
140  }
141  return knownPaths;
142 }
143 
144 QString EngineConfigPage::currentCustomParameters() const
145 {
146  return d->cboCustomParameters->currentText().trimmed();
147 }
148 
150 {
151  return d->plugin->icon();
152 }
153 
154 void EngineConfigPage::makeFileBrowsers()
155 {
156  QSharedPointer<FilePickWidget::NeighbourStrategy> neighbours(
158  QList<GameFile> files = d->plugin->gameExe()->gameFiles().asQList();
159  for (const GameFile &file : files)
160  {
161  auto widget = new FilePickWidget(d->exePickArea);
162  widget->setFile(file);
163  widget->setNeighbourStrategy(neighbours);
164  this->connect(widget, SIGNAL(findFailed()), SLOT(showFindFailError()));
165  this->connect(widget, SIGNAL(pathChanged()), SLOT(autoFindNeighbouringPaths()));
166  this->connect(widget, SIGNAL(pathChanged()), SIGNAL(validationRequested()));
167 
168  d->exePickArea->layout()->addWidget(widget);
169  d->filePickers << widget;
170  }
171 }
172 
173 QString EngineConfigPage::name() const
174 {
175  return d->plugin->data()->name;
176 }
177 
179 {
180  return d->plugin;
181 }
182 
184 {
185  for (FilePickWidget *filePicker : d->filePickers)
186  {
187  filePicker->blockSignals(true);
188  filePicker->load(*d->config);
189  filePicker->blockSignals(false);
190  }
191 
192  d->cboCustomParameters->clear();
193  d->cboCustomParameters->addItems(d->readStoredCustomParameters());
194  d->cboCustomParameters->setEditText(d->config->value("CustomParameters").toString());
195  if (d->plugin->data()->hasMasterClient())
196  d->leMasterserverAddress->setText(d->config->value("Masterserver").toString());
197 
198  updateCustomParametersSaveState();
199 }
200 
201 void EngineConfigPage::removeCurrentCustomParametersFromStorage()
202 {
203  QString currentParams = currentCustomParameters();
204  removeStoredCustomParametersFromConfig(currentParams);
205  removeStoredCustomParametersFromWidget(currentParams);
206  updateCustomParametersSaveState();
207 }
208 
209 void EngineConfigPage::removeStoredCustomParametersFromConfig(const QString &parameters)
210 {
211  QStringList storedParameters = d->readStoredCustomParameters();
212  storedParameters.removeAll(parameters);
213  d->saveStoredCustomParameters(storedParameters);
214 }
215 
216 void EngineConfigPage::removeStoredCustomParametersFromWidget(const QString &parameters)
217 {
218  int indexInWidget = d->cboCustomParameters->findText(parameters);
219  if (indexInWidget >= 0)
220  {
221  d->cboCustomParameters->removeItem(indexInWidget);
222  d->cboCustomParameters->setEditText(parameters);
223  }
224 }
225 
226 void EngineConfigPage::saveCustomParameters()
227 {
228  if (!d->existsInStoredCustomParameters(currentCustomParameters()))
229  {
230  QStringList parameters = d->readStoredCustomParameters();
231  parameters << currentCustomParameters();
232  d->saveStoredCustomParameters(parameters);
233  d->cboCustomParameters->addItem(currentCustomParameters());
234  }
235  updateCustomParametersSaveState();
236 }
237 
239 {
240  for (FilePickWidget *filePicker : d->filePickers)
241  {
242  filePicker->save(*d->config);
243  }
244  d->config->setValue("CustomParameters", currentCustomParameters());
245  if (d->plugin->data()->hasMasterClient())
246  d->config->setValue("Masterserver", d->leMasterserverAddress->text());
247 }
248 
249 void EngineConfigPage::showError(const QString &error)
250 {
251  d->lblError->setText(error);
252  d->lblError->show();
253  d->errorTimer.start();
254 }
255 
256 void EngineConfigPage::showFindFailError()
257 {
258  showError(tr("Failed to automatically find file.\nYou may need to use the browse button."));
259 }
260 
261 QString EngineConfigPage::title() const
262 {
263  return tr("Game - %1").arg(name());
264 }
265 
266 void EngineConfigPage::updateCustomParametersSaveState()
267 {
268  bool paramExists = d->existsInStoredCustomParameters(currentCustomParameters());
269  bool isEmpty = currentCustomParameters().isEmpty();
270  d->btnSaveCustomParameters->setVisible(!isEmpty && !paramExists);
271  d->btnDeleteCustomParameters->setVisible(!isEmpty && paramExists);
272 }
273 
275 {
276  bool allFilesOk = true;
277  for (FilePickWidget *filePicker : d->filePickers)
278  {
279  bool thisFileOk = filePicker->validate();
280  allFilesOk = allFilesOk && thisFileOk;
281  }
282  return allFilesOk ? VALIDATION_OK : VALIDATION_ERROR;
283 }