24 #include "demomanager.h" 25 #include "ui_demomanager.h" 27 #include "ini/settingsproviderqt.h" 28 #include "datapaths.h" 29 #include "pathfinder/pathfinder.h" 30 #include "pathfinder/wadpathfinder.h" 31 #include "plugins/engineplugin.h" 32 #include "plugins/pluginloader.h" 33 #include "serverapi/gameexeretriever.h" 34 #include "serverapi/gamecreateparams.h" 35 #include "serverapi/message.h" 36 #include "serverapi/server.h" 37 #include "serverapi/gamehost.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 = NULL;
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))
91 demoExtensions << ext;
97 QDate today = QDate::currentDate();
98 QTime referenceTime(23, 59, 59);
99 QDir demosDirectory(gDefaultDataPaths->demosDirectoryPath());
100 QStringList demos = demosDirectory.entryList(demoExtensions, QDir::Files);
101 typedef QMap<int, Demo> DemoMap;
102 QMap<int, DemoMap> demoMap;
103 foreach(
const QString &demoName, demos)
105 QStringList demoData;
106 QString metaData = demoName.left(demoName.lastIndexOf(
"."));
108 for(
int i = 0;i < metaData.length();++i)
110 if(metaData[i] ==
'_')
113 if(i+1 < metaData.length() && metaData[i+1] ==
'_')
120 demoData << metaData.left(i).replace(
"__",
"_");
121 metaData = metaData.mid(i+1);
126 demoData << metaData.replace(
"__",
"_");
127 if(demoData.size() < 3)
130 QDate date = QDate::fromString(demoData[1],
"dd.MM.yyyy");
131 QTime time = QTime::fromString(demoData[2],
"hh.mm.ss");
133 demo.filename = demoName;
134 demo.port = demoData[0];
135 demo.time = QDateTime(date, time);
136 if(demoData.size() >= 4)
137 demo.wads = demoData.mid(3);
142 gDefaultDataPaths->demosDirectoryPath() + QDir::separator() + demoName +
".ini",
143 QSettings::IniFormat);
145 Ini metaData(&settingsProvider);
146 demo.wads << metaData.retrieveSetting(
"meta",
"iwad");
147 QString pwads = metaData.retrieveSetting(
"meta",
"pwads");
148 if(pwads.length() > 0)
149 demo.wads << pwads.split(
";");
150 demo.optionalWads = metaData.retrieveSetting(
"meta",
"optionalPwads").value().toStringList();
153 demoMap[date.daysTo(today)][time.secsTo(referenceTime)] = demo;
157 d->demoModel->clear();
159 foreach(
const DemoMap &demoDate, demoMap)
161 QStandardItem *item =
new QStandardItem(demoDate.begin().value().time.toString(
"ddd. MMM d, yyyy"));
162 QList<Demo> demoDateList;
163 foreach(
const Demo &demo, demoDate)
165 demoDateList << demo;
166 item->appendRow(
new QStandardItem(demo.time.toString(
"hh:mm:ss")));
168 d->demoTree << demoDateList;
169 d->demoModel->appendRow(item);
171 d->demoList->setModel(d->demoModel);
174 bool DemoManagerDlg::doRemoveDemo(
const QString &file)
176 if(!QFile::remove(file))
177 QMessageBox::critical(
this, tr(
"Unable to delete"), tr(
"Could not delete the selected demo."));
181 QFile::remove(file +
".ini");
182 d->selectedDemo = NULL;
188 void DemoManagerDlg::deleteSelected()
190 if(QMessageBox::question(
this, tr(
"Delete demo?"),
191 tr(
"Are you sure you want to delete the selected demo?"),
192 QMessageBox::Yes|QMessageBox::Cancel) == QMessageBox::Yes)
194 QModelIndex index = d->demoList->selectionModel()->currentIndex();
195 if(d->selectedDemo == NULL)
197 int dateRow = index.row();
198 for(
int timeRow = 0;index.child(timeRow, 0).isValid();++timeRow)
200 if(doRemoveDemo(gDefaultDataPaths->demosDirectoryPath() + QDir::separator() + d->demoTree[dateRow][timeRow].filename))
202 d->demoModel->removeRow(timeRow, index);
203 d->demoTree[dateRow].removeAt(timeRow);
204 if(d->demoTree[dateRow].size() == 0)
206 d->demoModel->removeRow(dateRow);
207 d->demoTree.removeAt(dateRow);
218 if(doRemoveDemo(gDefaultDataPaths->demosDirectoryPath() + QDir::separator() + d->selectedDemo->filename))
221 int dateRow = index.parent().row();
222 int timeRow = index.row();
224 d->demoModel->removeRow(timeRow, index.parent());
225 d->demoTree[dateRow].removeAt(timeRow);
226 if(d->demoTree[dateRow].size() == 0)
228 d->demoModel->removeRow(dateRow);
229 d->demoTree.removeAt(dateRow);
236 void DemoManagerDlg::exportSelected()
238 if(d->selectedDemo == NULL)
241 QFileDialog saveDialog(
this);
242 saveDialog.setAcceptMode(QFileDialog::AcceptSave);
243 saveDialog.selectFile(d->selectedDemo->filename);
244 if(saveDialog.exec() == QDialog::Accepted)
247 if(!QFile::copy(gDefaultDataPaths->demosDirectoryPath() + QDir::separator() + d->selectedDemo->filename, saveDialog.selectedFiles().first()))
248 QMessageBox::critical(
this, tr(
"Unable to save"), tr(
"Could not write to the specified location."));
252 void DemoManagerDlg::playSelected()
254 if(d->selectedDemo == NULL)
259 for(
unsigned i = 0;i < gPlugins->numPlugins();i++)
261 if (d->selectedDemo->port == gPlugins->info(i)->data()->name)
263 plugin = gPlugins->info(i);
268 QMessageBox::critical(
this, tr(
"No plugin"),
269 tr(
"The \"%1\" plugin does not appear to be loaded.").arg(d->selectedDemo->port));
275 QString binPath =
GameExeRetriever(*plugin->gameExe()).pathToOfflineExe(binMessage);
282 QStringList missingWads;
283 QStringList wadPaths;
285 foreach (
const QString &wad, d->selectedDemo->wads)
288 if (findResult.isValid())
289 wadPaths << findResult.path();
294 if(!missingWads.isEmpty())
296 QMessageBox::critical(
this, tr(
"Files not found"),
297 tr(
"The following files could not be located: ") + missingWads.join(
", "));
300 QStringList optionalWadPaths;
301 foreach (
const QString &wad, d->selectedDemo->optionalWads)
304 if (findResult.isValid())
305 optionalWadPaths << findResult.path();
310 params.setDemoPath(gDefaultDataPaths->demosDirectoryPath()
311 + QDir::separator() + d->selectedDemo->filename);
312 params.setIwadPath(wadPaths[0]);
313 params.setPwadsPaths(wadPaths.mid(1) + optionalWadPaths);
314 params.setHostMode(GameCreateParams::Demo);
315 params.setExecutablePath(binPath);
322 QMessageBox::critical(
this, tr(
"Doomseeker - error"), message.
contents());
329 void DemoManagerDlg::performAction(QAbstractButton *button)
331 if(button == d->buttonBox->button(QDialogButtonBox::Close))
335 void DemoManagerDlg::updatePreview(
const QModelIndex &index)
337 if(!index.isValid() || !index.parent().isValid())
339 d->preview->setText(
"");
340 d->selectedDemo = NULL;
344 int dateRow = index.parent().row();
345 int timeRow = index.row();
346 d->selectedDemo = &d->demoTree[dateRow][timeRow];
348 QString text =
"<b>" + tr(
"Port") +
":</b><p style=\"margin: 0px 0px 0px 10px\">" + d->selectedDemo->port +
"</p>" +
349 "<b>" + tr(
"WADs") +
":</b><p style=\"margin: 0px 0px 0px 10px\">";
350 foreach(
const QString &wad, d->selectedDemo->wads)
352 text += wad +
"<br />";
354 foreach(
const QString &wad, d->selectedDemo->optionalWads)
356 text +=
"[" + wad +
"]<br />";
359 d->preview->setText(text);
Game parametrization data used when creating new games.
Performs a case-insensitive (OS independent) file searches.
Message object used to pass messages throughout the Doomseeker's system.
virtual GameHost * gameHost()
Creates an instance of GameHost derivative class.
A convenience wrapper class for GameExeFactory.
bool isError() const
True if type() is equal to or greater than CUSTOM_ERROR.
Dialog for managing demos recorded through Doomseeker.
Creates game servers, offline games or demo playbacks.
Wrapper for PathFinder that specializes in findings WADs.
QString contents() const
Customized displayable contents of this Message.
Message host(const GameCreateParams ¶ms)
void addPrioritySearchDir(const QString &dir)