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