freedoomdialog.cpp
1 //------------------------------------------------------------------------------
2 // freedoomdialog.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 "freedoomdialog.h"
24 
25 #include "ui_freedoomdialog.h"
26 #include "configuration/doomseekerconfig.h"
27 #include "pathfinder/filesearchpath.h"
28 #include "pathfinder/pathfinder.h"
29 #include "pathfinder/wadpathfinder.h"
30 #include "fileutils.h"
31 #include <wadseeker/entities/modset.h>
32 #include <wadseeker/freedoom.h>
33 #include <wadseeker/modinstall.h>
34 #include <QCheckBox>
35 #include <QCompleter>
36 #include <QDirModel>
37 #include <QMessageBox>
38 
39 DClass<FreedoomDialog> : public Ui::FreedoomDialog
40 {
41 public:
42  Freedoom *freedoom;
43  ModInstall *modInstall;
44  QString targetDir;
45 };
46 DPointered(FreedoomDialog)
47 
48 FreedoomDialog::FreedoomDialog(QWidget *parent)
49 : QDialog(parent)
50 {
51  d->setupUi(this);
52 
53  d->freedoom = new Freedoom(this);
54  this->connect(d->freedoom, SIGNAL(finished()), SLOT(applyFreedoomVersionInfo()));
55 
56  d->modInstall = new ModInstall(this);
57  this->connect(d->modInstall, SIGNAL(finished()), SLOT(onModInstallFinished()));
58  this->connect(d->modInstall, SIGNAL(fileDownloadProgress(QString, qint64, qint64)),
59  SLOT(showFileDownloadProgress(QString, qint64, qint64)));
60 
61  d->btnInstall->setEnabled(false);
62  setupInstallPaths();
63  setupWadsTable();
64  fetchInfo();
65 }
66 
67 FreedoomDialog::~FreedoomDialog()
68 {
69 }
70 
71 void FreedoomDialog::accept()
72 {
73  ModSet modSet = selectedModFiles();
74  if (modSet.isEmpty())
75  {
76  QMessageBox::critical(this, tr("Install Freedoom"),
77  tr("Select at least one file."));
78  return;
79  }
80  resetProgressBar();
81  showStatus(tr("Downloading & installing ..."));
82  d->targetDir = d->cboInstallPath->currentText();
83  d->modInstall->install(d->targetDir, modSet);
84 }
85 
86 void FreedoomDialog::onModInstallFinished()
87 {
88  if (!d->modInstall->isError())
89  {
90  updateConfig();
91  fetchInfo();
92  }
93  else
94  {
95  showError(d->modInstall->error());
96  }
97 }
98 
99 void FreedoomDialog::updateConfig()
100 {
101  gConfig.doomseeker.enableFreedoomInstallation(d->targetDir);
102  gConfig.saveToFile();
103 }
104 
105 void FreedoomDialog::fetchInfo()
106 {
107  resetProgressBar();
108  d->btnRetry->hide();
109  showStatus(tr("Downloading Freedoom version info ..."));
110  d->freedoom->requestModSet();
111 }
112 
113 void FreedoomDialog::resetProgressBar()
114 {
115  d->progressBar->setFormat(tr("Working ..."));
116  d->progressBar->show();
117  d->progressBar->setMaximum(0);
118  d->progressBar->setValue(0);
119 }
120 
121 void FreedoomDialog::applyFreedoomVersionInfo()
122 {
123  if (!d->freedoom->isError())
124  {
125  showModInfo(d->freedoom->modSet());
126  }
127  else
128  {
129  showError(tr("Error: %1").arg(d->freedoom->error()));
130  }
131 }
132 
133 void FreedoomDialog::showModInfo(const ModSet &modSet)
134 {
135  d->wadsArea->show();
136  d->workInProgressArea->hide();
137 
138  d->wadsTable->setSortingEnabled(false);
139  d->wadsTable->clearContents();
140  while (d->wadsTable->rowCount() > 0)
141  {
142  d->wadsTable->removeRow(d->wadsTable->rowCount() - 1);
143  }
144  foreach (const ModFile &file, modSet.modFiles())
145  {
146  insertModFile(file);
147  }
148  d->wadsTable->setSortingEnabled(true);
149  d->btnInstall->setEnabled(true);
150 }
151 
152 void FreedoomDialog::insertModFile(const ModFile &file)
153 {
154  WadPathFinder pathFinder = WadPathFinder(PathFinder());
155  pathFinder.setAllowAliases(false);
156  QString location = pathFinder.find(file.fileName()).path();
157 
158  QString status = tr("OK");
159  bool needsInstall = false;
160  if (location.isEmpty())
161  {
162  needsInstall = true;
163  status = tr("Missing");
164  }
165  else
166  {
167  QString md5 = FileUtils::md5(location).toHex();
168  if (md5.compare(file.md5(), Qt::CaseInsensitive) != 0)
169  {
170  status = tr("Different");
171  needsInstall = true;
172  }
173  }
174  if (file.fileName().compare("freedm.wad", Qt::CaseInsensitive) == 0)
175  {
176  needsInstall = false;
177  }
178 
179  d->wadsTable->insertRow(d->wadsTable->rowCount());
180  int row = d->wadsTable->rowCount() - 1;
181  d->wadsTable->setItem(row, ColName, new QTableWidgetItem(file.fileName()));
182  d->wadsTable->setItem(row, ColStatus, new QTableWidgetItem(status));
183 
184  QCheckBox *checkBox = new QCheckBox();
185  checkBox->setChecked(needsInstall);
186  d->wadsTable->setCellWidget(row, ColInstall, checkBox);
187 
188  QString tooltip = tr("<p>File: %1<br>Version: %2<br>"
189  "Description: %3<br>Location: %4</p>")
190  .arg(file.name(), file.version(), file.description(), location);
191 
192  for (int col = 0; col < d->wadsTable->columnCount(); ++col)
193  {
194  QTableWidgetItem *item = d->wadsTable->item(row, col);
195  if (item != NULL)
196  {
197  item->setToolTip(tooltip);
198  }
199  }
200 }
201 
202 void FreedoomDialog::showError(const QString &text)
203 {
204  d->btnRetry->setVisible(true);
205  showStatus(text);
206  d->progressBar->hide();
207 }
208 
209 void FreedoomDialog::showStatus(const QString &text)
210 {
211  d->wadsArea->hide();
212  d->workInProgressArea->show();
213  d->btnInstall->setEnabled(false);
214  d->lblWorkInProgress->setText(text);
215 }
216 
217 ModSet FreedoomDialog::selectedModFiles() const
218 {
219  ModSet modSet;
220  for (int row = 0; row < d->wadsTable->rowCount(); ++row)
221  {
222  QCheckBox *checkbox = static_cast<QCheckBox*>(d->wadsTable->cellWidget(row, ColInstall));
223  if (checkbox->isChecked())
224  {
225  QString fileName = d->wadsTable->item(row, ColName)->text();
226  modSet.addModFile(d->freedoom->modSet().findFileName(fileName));
227  }
228  }
229  return modSet;
230 }
231 
232 void FreedoomDialog::setupInstallPaths()
233 {
234  QCompleter *completer = new QCompleter(this);
235  completer->setModel(new QDirModel(completer));
236  d->cboInstallPath->setCompleter(completer);
237 
238  foreach (const FileSearchPath &path, gConfig.combinedWadseekPaths())
239  {
240  d->cboInstallPath->addItem(path.path());
241  }
242 #if QT_VERSION >= 0x050000
243  d->cboInstallPath->setCurrentText(gConfig.wadseeker.targetDirectory);
244 #else
245  // This is basically what the Qt5 function above does. Could use it there
246  // but I figured I would #if it for when we eventually drop Qt4 we won't be
247  // reinventing the wheel.
248  const int item = d->cboInstallPath->findText(gConfig.wadseeker.targetDirectory);
249  if(item >= 0)
250  d->cboInstallPath->setCurrentIndex(item);
251  else
252  d->cboInstallPath->setEditText(gConfig.wadseeker.targetDirectory);
253 #endif
254 }
255 
256 void FreedoomDialog::setupWadsTable()
257 {
258  QHeaderView *header = d->wadsTable->horizontalHeader();
259 #if QT_VERSION >= 0x050000
260  header->setSectionResizeMode(ColName, QHeaderView::Stretch);
261  header->setSectionResizeMode(ColStatus, QHeaderView::ResizeToContents);
262  header->setSectionResizeMode(ColInstall, QHeaderView::ResizeToContents);
263 #else
264  header->setResizeMode(ColName, QHeaderView::Stretch);
265  header->setResizeMode(ColStatus, QHeaderView::ResizeToContents);
266  header->setResizeMode(ColInstall, QHeaderView::ResizeToContents);
267 #endif
268  d->wadsTable->setColumnWidth(ColName, 150);
269 }
270 
271 void FreedoomDialog::showFileDownloadProgress(const QString &file,
272  qint64 current, qint64 total)
273 {
274  d->progressBar->setFormat(tr("%1 %p%").arg(file));
275  d->progressBar->setMaximum(total);
276  d->progressBar->setValue(current);
277 }
Performs a case-insensitive (OS independent) file searches.
Definition: pathfinder.h:81
void setAllowAliases(bool allowed)
Can disable WAD aliasing for contexts where only specific WADs should be found.
Wrapper for PathFinder that specializes in findings WADs.
Definition: wadpathfinder.h:76