missingwadsdialog.cpp
1 //------------------------------------------------------------------------------
2 // missingwadsdialog.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 "missingwadsdialog.h"
24 
25 #include "application.h"
26 #include "gui/mainwindow.h"
27 #include "gui/wadseekerinterface.h"
28 #include "plugins/engineplugin.h"
30 #include "ui_missingwadsdialog.h"
31 #include <QListWidgetItem>
32 #include <wadseeker/entities/modfile.h>
33 #include <wadseeker/freedoom.h>
34 #include <wadseeker/wadseeker.h>
35 
36 DClass<MissingWadsDialog> : public Ui::MissingWadsDialog
37 {
38 public:
39  ::MissingWadsDialog::MissingWadsProceed decision;
40  QList<PWad> missingWads;
41  QList<PWad> incompatibleWads;
42  EnginePlugin *plugin = nullptr;
43 };
44 DPointeredNoCopy(MissingWadsDialog)
45 
46 MissingWadsDialog::MissingWadsDialog(const QList<PWad> &missingWads, const QList<PWad> &incompatibleWads, EnginePlugin *plugin, QWidget *parent)
47  : QDialog(parent)
48 {
49  d->setupUi(this);
50  d->decision = Cancel;
51  d->missingWads = missingWads;
52  d->incompatibleWads = incompatibleWads;
53  d->plugin = plugin;
54  setup();
55  adjustSize();
56 }
57 
58 MissingWadsDialog::~MissingWadsDialog()
59 {
60 }
61 
62 void MissingWadsDialog::setAllowIgnore(bool allow)
63 {
64  d->btnIgnore->setVisible(allow);
65  d->lblUseIgnore->setVisible(allow);
66  d->lblUseIgnoreCantRun->setVisible(allow);
67 }
68 
69 void MissingWadsDialog::setup()
70 {
71  d->btnInstallFreedoom->hide();
72  if (WadseekerInterface::isInstantiated())
73  setupWadseekerIsRunning();
74  else
75  setupWadseekerNotRunning();
76 }
77 
78 void MissingWadsDialog::setupWadseekerIsRunning()
79 {
80  d->areaWadseekerAlreadyRunning->show();
81  d->areaWadseekerCanBeRun->hide();
82  d->btnInstall->hide();
83 }
84 
85 void MissingWadsDialog::setupWadseekerNotRunning()
86 {
87  d->areaWadseekerAlreadyRunning->hide();
88  d->areaWadseekerCanBeRun->show();
89 
90  setupForbiddenFilesArea();
91  setupDownloadableFilesArea();
92  setupOptionalFilesArea();
93  setupIncompatibleFilesArea();
94 
95  d->btnInstall->setVisible(hasAnyAllowedFile());
96  setAllowIgnore(((optionalFiles().size() == d->missingWads.size()) ||
97  d->missingWads.size() == 0 || // there are only incompatible files
98  (d->plugin != nullptr && d->plugin->data()->inGameFileDownloads)));
99 }
100 
101 void MissingWadsDialog::setupForbiddenFilesArea()
102 {
103  QList<PWad> files = forbiddenFiles();
104  if (!files.isEmpty())
105  {
106  d->areaCantBeDownloaded->show();
107  QStringList names;
108  for (PWad file : files)
109  {
110  names << file.name();
111  }
112  d->lblCantBeDownloadedFiles->setText(names.join(", "));
113 
114  bool installFreedoom = isFreedoomReplaceableOnList(names);
115  d->lblInstallFreedoom->setVisible(installFreedoom);
116  d->btnInstallFreedoom->setVisible(installFreedoom);
117  }
118  else
119  d->areaCantBeDownloaded->hide();
120 }
121 
122 void MissingWadsDialog::setupDownloadableFilesArea()
123 {
124  QList<PWad> files = downloadableFiles();
125  if (!files.isEmpty())
126  {
127  d->areaCanBeDownloadedFiles->show();
128  QStringList names;
129  for (PWad file : files)
130  {
131  names << file.name();
132  }
133  d->lblCanBeDownloadedFiles->setText(names.join(", "));
134  }
135  else
136  d->areaCanBeDownloadedFiles->hide();
137 }
138 
139 void MissingWadsDialog::setupOptionalFilesArea()
140 {
141  QList<PWad> files = optionalFiles();
142  if (!files.isEmpty())
143  {
144  d->areaOptionalFiles->show();
145  for (const PWad &file : files)
146  {
147  auto item = new QListWidgetItem(file.name(), d->optionalFilesList);
148  item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
149  item->setCheckState(Qt::Checked);
150  }
151  }
152  else
153  d->areaOptionalFiles->hide();
154 }
155 
156 void MissingWadsDialog::setupIncompatibleFilesArea()
157 {
158  QList<PWad> files = incompatibleFiles();
159  if (!files.isEmpty())
160  {
161  d->areaIncompatibleFiles->show();
162  for (const PWad &file : files)
163  {
164  auto item = new QListWidgetItem(file.name(), d->incompatibleFilesList);
165  item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
166  item->setCheckState(Qt::Checked);
167  }
168  }
169  else
170  d->areaIncompatibleFiles->hide();
171 }
172 
173 bool MissingWadsDialog::isFreedoomReplaceableOnList(const QStringList &files) const
174 {
175  for (const QString &file : files)
176  {
177  if (Freedoom::hasFreedoomReplacement(file))
178  return true;
179  }
180  return false;
181 }
182 
183 void MissingWadsDialog::updateStateAccordingToFileSelection()
184 {
185  d->btnInstall->setEnabled(!filesToDownload().isEmpty());
186 }
187 
188 void MissingWadsDialog::ignoreMissingFiles()
189 {
190  d->decision = Ignore;
191  accept();
192 }
193 
194 void MissingWadsDialog::installFreedoom()
195 {
196  QTimer::singleShot(0, gApp->mainWindow(), SLOT(showInstallFreedoomDialog()));
197  accept();
198 }
199 
200 void MissingWadsDialog::installMissingFiles()
201 {
202  d->decision = Install;
203  accept();
204 }
205 
206 QList<PWad> MissingWadsDialog::downloadableFiles() const
207 {
208  QList<PWad> result;
209  for (PWad file : d->missingWads)
210  {
211  if (!Wadseeker::isForbiddenWad(file) && !file.isOptional())
212  result << file;
213  }
214  return result;
215 }
216 
217 QList<PWad> MissingWadsDialog::forbiddenFiles() const
218 {
219  QList<PWad> result;
220  QList<PWad> wads;
221  wads << d->missingWads << d->incompatibleWads;
222  for (const PWad &file : wads)
223  {
224  if (Wadseeker::isForbiddenWad(file.name()))
225  result << file;
226  }
227  return result;
228 }
229 
230 QList<PWad> MissingWadsDialog::optionalFiles() const
231 {
232  QList<PWad> result;
233  for (const PWad &file : d->missingWads)
234  {
235  if (!Wadseeker::isForbiddenWad(file.name()) && file.isOptional())
236  result << file;
237  }
238  return result;
239 }
240 
241 QList<PWad> MissingWadsDialog::incompatibleFiles() const
242 {
243  QList<PWad> result;
244  for (const PWad &file : d->incompatibleWads)
245  {
246  if (!Wadseeker::isForbiddenWad(file.name()))
247  result << file;
248  }
249  return result;
250 }
251 
252 QList<PWad> MissingWadsDialog::filesToDownload() const
253 {
254  QList<PWad> result = downloadableFiles();
255  result << selectedOptionalFiles();
256  result << selectedIncompatibleFiles();
257  return result;
258 }
259 
260 QList<PWad> MissingWadsDialog::selectedOptionalFiles() const
261 {
262  QStringList result;
263  for (int i = 0; i < d->optionalFilesList->count(); ++i)
264  {
265  QListWidgetItem *item = d->optionalFilesList->item(i);
266  if (item->checkState() == Qt::Checked)
267  result << item->text();
268  }
269  return filenamesToPwads(result, optionalFiles());
270 }
271 
272 QList<PWad> MissingWadsDialog::selectedIncompatibleFiles() const
273 {
274  QStringList result;
275  for (int i = 0; i < d->incompatibleFilesList->count(); ++i)
276  {
277  QListWidgetItem *item = d->incompatibleFilesList->item(i);
278  if (item->checkState() == Qt::Checked)
279  result << item->text();
280  }
281  return filenamesToPwads(result, incompatibleFiles());
282 }
283 
284 QList<PWad> MissingWadsDialog::filenamesToPwads(const QStringList &names, QList<PWad> files) const
285 {
286  QList<PWad> result;
287  for (QString name : names)
288  {
289  for (int i = 0; i < files.size(); ++i)
290  {
291  if (files[i].name() == name)
292  {
293  result << files[i];
294  files.removeAt(i);
295  break;
296  }
297  }
298  }
299  return result;
300 }
301 
302 bool MissingWadsDialog::hasAnyAllowedFile() const
303 {
304  return !downloadableFiles().isEmpty() ||
305  !optionalFiles().isEmpty() ||
306  !incompatibleFiles().isEmpty();
307 }
308 
309 MissingWadsDialog::MissingWadsProceed MissingWadsDialog::decision() const
310 {
311  return d->decision;
312 }