24 #include "datapaths.h"
25 #include "demomanager.h"
27 #include "ini/settingsproviderqt.h"
28 #include "pathfinder/pathfinder.h"
29 #include "pathfinder/wadpathfinder.h"
30 #include "plugins/engineplugin.h"
31 #include "plugins/pluginloader.h"
32 #include "serverapi/gamecreateparams.h"
33 #include "serverapi/gameexeretriever.h"
34 #include "serverapi/gamehost.h"
35 #include "serverapi/message.h"
36 #include "serverapi/server.h"
37 #include "ui_demomanager.h"
40 #include <QFileDialog>
42 #include <QMessageBox>
43 #include <QPushButton>
44 #include <QStandardItemModel>
53 QStringList optionalWads;
56 DClass<DemoManagerDlg> :
public Ui::DemoManagerDlg
60 QStandardItemModel *demoModel;
61 QList<QList<Demo> > demoTree;
69 d->selectedDemo =
nullptr;
71 d->demoModel =
new QStandardItemModel();
74 connect(d->demoList->selectionModel(), SIGNAL(currentChanged(
const QModelIndex&,
const QModelIndex&)),
this, SLOT(updatePreview(
const QModelIndex&)));
77 DemoManagerDlg::~DemoManagerDlg()
81 void DemoManagerDlg::adjustDemoList()
84 QStringList demoExtensions;
85 for (
unsigned i = 0; i < gPlugins->numPlugins(); ++i)
87 QString ext = QString(
"*.%1").arg(gPlugins->info(i)->data()->demoExtension);
89 if (!demoExtensions.contains(ext))
90 demoExtensions << ext;
95 QDate today = QDate::currentDate();
96 QTime referenceTime(23, 59, 59);
97 QDir demosDirectory(gDefaultDataPaths->demosDirectoryPath());
98 QStringList demos = demosDirectory.entryList(demoExtensions, QDir::Files);
99 typedef QMap<int, Demo> DemoMap;
100 QMap<int, DemoMap> demoMap;
101 for (
const QString &demoName : demos)
103 QStringList demoData;
104 QString metaData = demoName.left(demoName.lastIndexOf(
"."));
106 for (
int i = 0; i < metaData.length(); ++i)
108 if (metaData[i] ==
'_')
111 if (i + 1 < metaData.length() && metaData[i + 1] ==
'_')
118 demoData << metaData.left(i).replace(
"__",
"_");
119 metaData = metaData.mid(i + 1);
124 demoData << metaData.replace(
"__",
"_");
125 if (demoData.size() < 3)
128 QDate date = QDate::fromString(demoData[1],
"dd.MM.yyyy");
129 QTime time = QTime::fromString(demoData[2],
"hh.mm.ss");
131 demo.filename = demoName;
132 demo.port = demoData[0];
133 demo.time = QDateTime(date, time);
134 if (demoData.size() >= 4)
135 demo.wads = demoData.mid(3);
140 gDefaultDataPaths->demosDirectoryPath() + QDir::separator() + demoName +
".ini",
141 QSettings::IniFormat);
143 Ini metaData(&settingsProvider);
144 demo.wads << metaData.retrieveSetting(
"meta",
"iwad");
145 QString pwads = metaData.retrieveSetting(
"meta",
"pwads");
146 if (pwads.length() > 0)
147 demo.wads << pwads.split(
";");
148 demo.optionalWads = metaData.retrieveSetting(
"meta",
"optionalPwads").value().toStringList();
151 demoMap[date.daysTo(today)][time.secsTo(referenceTime)] = demo;
155 d->demoModel->clear();
157 for (
const DemoMap &demoDate : demoMap)
159 QStandardItem *item =
new QStandardItem(demoDate.begin().value().time.toString(
"ddd. MMM d, yyyy"));
160 QList<Demo> demoDateList;
161 for (
const Demo &demo : demoDate)
163 demoDateList << demo;
164 item->appendRow(
new QStandardItem(demo.time.toString(
"hh:mm:ss")));
166 d->demoTree << demoDateList;
167 d->demoModel->appendRow(item);
169 d->demoList->setModel(d->demoModel);
172 bool DemoManagerDlg::doRemoveDemo(
const QString &file)
174 if (!QFile::remove(file))
175 QMessageBox::critical(
this, tr(
"Unable to delete"), tr(
"Could not delete the selected demo."));
179 QFile::remove(file +
".ini");
180 d->selectedDemo =
nullptr;
186 void DemoManagerDlg::deleteSelected()
188 if (QMessageBox::question(
this, tr(
"Delete demo?"),
189 tr(
"Are you sure you want to delete the selected demo?"),
190 QMessageBox::Yes | QMessageBox::Cancel) == QMessageBox::Yes)
192 QModelIndex index = d->demoList->selectionModel()->currentIndex();
193 if (d->selectedDemo ==
nullptr)
195 int dateRow = index.row();
196 for (
int timeRow = 0; index.model()->index(timeRow, 0).isValid(); ++timeRow)
198 if (doRemoveDemo(gDefaultDataPaths->demosDirectoryPath() + QDir::separator() + d->demoTree[dateRow][timeRow].filename))
200 d->demoModel->removeRow(timeRow, index);
201 d->demoTree[dateRow].removeAt(timeRow);
202 if (d->demoTree[dateRow].size() == 0)
204 d->demoModel->removeRow(dateRow);
205 d->demoTree.removeAt(dateRow);
216 if (doRemoveDemo(gDefaultDataPaths->demosDirectoryPath() + QDir::separator() + d->selectedDemo->filename))
219 int dateRow = index.parent().row();
220 int timeRow = index.row();
222 d->demoModel->removeRow(timeRow, index.parent());
223 d->demoTree[dateRow].removeAt(timeRow);
224 if (d->demoTree[dateRow].size() == 0)
226 d->demoModel->removeRow(dateRow);
227 d->demoTree.removeAt(dateRow);
234 void DemoManagerDlg::exportSelected()
236 if (d->selectedDemo ==
nullptr)
239 QFileDialog saveDialog(
this);
240 saveDialog.setAcceptMode(QFileDialog::AcceptSave);
241 saveDialog.selectFile(d->selectedDemo->filename);
242 if (saveDialog.exec() == QDialog::Accepted)
245 if (!QFile::copy(gDefaultDataPaths->demosDirectoryPath() + QDir::separator() + d->selectedDemo->filename, saveDialog.selectedFiles().first()))
246 QMessageBox::critical(
this, tr(
"Unable to save"), tr(
"Could not write to the specified location."));
250 void DemoManagerDlg::playSelected()
252 if (d->selectedDemo ==
nullptr)
257 for (
unsigned i = 0; i < gPlugins->numPlugins(); i++)
259 if (d->selectedDemo->port == gPlugins->info(i)->data()->name)
260 plugin = gPlugins->info(i);
262 if (plugin ==
nullptr)
264 QMessageBox::critical(
this, tr(
"No plugin"),
265 tr(
"The \"%1\" plugin does not appear to be loaded.").arg(d->selectedDemo->port));
271 QString binPath =
GameExeRetriever(*plugin->gameExe()).pathToOfflineExe(binMessage);
278 QStringList missingWads;
279 QStringList wadPaths;
281 for (
const QString &wad : d->selectedDemo->wads)
284 if (findResult.isValid())
285 wadPaths << findResult.path();
290 if (!missingWads.isEmpty())
292 QMessageBox::critical(
this, tr(
"Files not found"),
293 tr(
"The following files could not be located: ") + missingWads.join(
", "));
296 QStringList optionalWadPaths;
297 for (
const QString &wad : d->selectedDemo->optionalWads)
300 if (findResult.isValid())
301 optionalWadPaths << findResult.path();
306 params.setDemoPath(gDefaultDataPaths->demosDirectoryPath()
307 + QDir::separator() + d->selectedDemo->filename);
308 params.setIwadPath(wadPaths[0]);
309 params.setPwadsPaths(wadPaths.mid(1) + optionalWadPaths);
310 params.setHostMode(GameCreateParams::Demo);
311 params.setExecutablePath(binPath);
317 QMessageBox::critical(
this, tr(
"Doomseeker - error"), message.
contents());
323 void DemoManagerDlg::performAction(QAbstractButton *button)
325 if (button == d->buttonBox->button(QDialogButtonBox::Close))
329 void DemoManagerDlg::updatePreview(
const QModelIndex &index)
331 if (!index.isValid() || !index.parent().isValid())
333 d->preview->setText(
"");
334 d->selectedDemo =
nullptr;
338 int dateRow = index.parent().row();
339 int timeRow = index.row();
340 d->selectedDemo = &d->demoTree[dateRow][timeRow];
342 QString text =
"<b>" + tr(
"Port") +
":</b><p style=\"margin: 0px 0px 0px 10px\">" + d->selectedDemo->port +
"</p>" +
343 "<b>" + tr(
"WADs") +
":</b><p style=\"margin: 0px 0px 0px 10px\">";
344 for (
const QString &wad : d->selectedDemo->wads)
346 text += wad +
"<br />";
348 for (
const QString &wad : d->selectedDemo->optionalWads)
350 text +=
"[" + wad +
"]<br />";
353 d->preview->setText(text);