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