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 "plugins/engineplugin.h"
31 #include "plugins/pluginloader.h"
32 #include "serverapi/gameexeretriever.h"
33 #include "serverapi/gamecreateparams.h"
34 #include "serverapi/message.h"
35 #include "serverapi/server.h"
36 #include "serverapi/gamehost.h"
39 #include <QFileDialog>
41 #include <QMessageBox>
42 #include <QPushButton>
43 #include <QStandardItemModel>
54 DClass<DemoManagerDlg> :
public Ui::DemoManagerDlg
58 QStandardItemModel *demoModel;
59 QList<QList<Demo> > demoTree;
67 d->selectedDemo = NULL;
70 QPushButton *playButton = d->buttonBox->addButton(tr(
"Play"), QDialogButtonBox::ActionRole);
71 playButton->setIcon(QIcon(
":/icons/media-playback-start.png"));
73 d->demoModel =
new QStandardItemModel();
76 connect(d->buttonBox, SIGNAL( clicked(QAbstractButton *) ),
this, SLOT( performAction(QAbstractButton *) ));
77 connect(d->demoList->selectionModel(), SIGNAL( currentChanged(
const QModelIndex &,
const QModelIndex &) ),
this, SLOT( updatePreview(
const QModelIndex &) ));
80 DemoManagerDlg::~DemoManagerDlg()
84 void DemoManagerDlg::adjustDemoList()
87 QStringList demoExtensions;
88 for(
int i = 0;i < gPlugins->numPlugins();++i)
90 QString ext = QString(
"*.%1").arg(gPlugins->info(i)->data()->demoExtension);
92 if(!demoExtensions.contains(ext))
94 demoExtensions << ext;
100 QDate today = QDate::currentDate();
101 QTime referenceTime(23, 59, 59);
102 QDir demosDirectory(gDefaultDataPaths->demosDirectoryPath());
103 QStringList demos = demosDirectory.entryList(demoExtensions, QDir::Files);
104 typedef QMap<int, Demo> DemoMap;
105 QMap<int, DemoMap> demoMap;
106 foreach(
const QString &demoName, demos)
108 QStringList demoData;
109 QString metaData = demoName.left(demoName.lastIndexOf(
"."));
111 for(
unsigned int i = 0;i < metaData.length();++i)
113 if(metaData[i] ==
'_')
116 if(i+1 < metaData.length() && metaData[i+1] ==
'_')
123 demoData << metaData.left(i).replace(
"__",
"_");
124 metaData = metaData.mid(i+1);
129 demoData << metaData.replace(
"__",
"_");
130 if(demoData.size() < 3)
133 QDate date = QDate::fromString(demoData[1],
"dd.MM.yyyy");
134 QTime time = QTime::fromString(demoData[2],
"hh.mm.ss");
136 demo.filename = demoName;
137 demo.port = demoData[0];
138 demo.time = QDateTime(date, time);
139 if(demoData.size() >= 4)
140 demo.wads = demoData.mid(3);
145 gDefaultDataPaths->demosDirectoryPath() + QDir::separator() + demoName +
".ini",
146 QSettings::IniFormat);
148 Ini metaData(&settingsProvider);
149 demo.wads << metaData.retrieveSetting(
"meta",
"iwad");
150 QString pwads = metaData.retrieveSetting(
"meta",
"pwads");
151 if(pwads.length() > 0)
152 demo.wads << pwads.split(
";");
155 demoMap[date.daysTo(today)][time.secsTo(referenceTime)] = demo;
159 d->demoModel->clear();
161 foreach(
const DemoMap &demoDate, demoMap)
163 QStandardItem *item =
new QStandardItem(demoDate.begin().value().time.toString(
"ddd. MMM d, yyyy"));
164 QList<Demo> demoDateList;
165 foreach(
const Demo &demo, demoDate)
167 demoDateList << demo;
168 item->appendRow(
new QStandardItem(demo.time.toString(
"hh:mm:ss")));
170 d->demoTree << demoDateList;
171 d->demoModel->appendRow(item);
173 d->demoList->setModel(d->demoModel);
176 bool DemoManagerDlg::doRemoveDemo(
const QString &file)
178 if(!QFile::remove(file))
179 QMessageBox::critical(
this, tr(
"Unable to delete"), tr(
"Could not delete the selected demo."));
183 QFile::remove(file +
".ini");
184 d->selectedDemo = NULL;
190 void DemoManagerDlg::performAction(QAbstractButton *button)
192 if(button == d->buttonBox->button(QDialogButtonBox::Close))
194 else if(button == d->buttonBox->button(QDialogButtonBox::Save))
196 if(d->selectedDemo == NULL)
199 QFileDialog saveDialog(
this);
200 saveDialog.setAcceptMode(QFileDialog::AcceptSave);
201 saveDialog.selectFile(d->selectedDemo->filename);
202 if(saveDialog.exec() == QDialog::Accepted)
205 if(!QFile::copy(gDefaultDataPaths->demosDirectoryPath() + QDir::separator() + d->selectedDemo->filename, saveDialog.selectedFiles().first()))
206 QMessageBox::critical(
this, tr(
"Unable to save"), tr(
"Could not write to the specified location."));
209 else if(button == d->buttonBox->button(QDialogButtonBox::Discard))
211 if(QMessageBox::question(
this, tr(
"Delete demo?"), tr(
"Are you sure you want to delete the selected demo?"), QMessageBox::Yes|QMessageBox::Cancel) == QMessageBox::Yes)
213 QModelIndex index = d->demoList->selectionModel()->currentIndex();
214 if(d->selectedDemo == NULL)
216 int dateRow = index.row();
217 for(
int timeRow = 0;index.child(timeRow, 0).isValid();++timeRow)
219 if(doRemoveDemo(gDefaultDataPaths->demosDirectoryPath() + QDir::separator() + d->demoTree[dateRow][timeRow].filename))
221 d->demoModel->removeRow(timeRow, index);
222 d->demoTree[dateRow].removeAt(timeRow);
223 if(d->demoTree[dateRow].size() == 0)
225 d->demoModel->removeRow(dateRow);
226 d->demoTree.removeAt(dateRow);
237 if(doRemoveDemo(gDefaultDataPaths->demosDirectoryPath() + QDir::separator() + d->selectedDemo->filename))
240 int dateRow = index.parent().row();
241 int timeRow = index.row();
243 d->demoModel->removeRow(timeRow, index.parent());
244 d->demoTree[dateRow].removeAt(timeRow);
245 if(d->demoTree[dateRow].size() == 0)
247 d->demoModel->removeRow(dateRow);
248 d->demoTree.removeAt(dateRow);
256 if(d->selectedDemo == NULL)
261 for(
int i = 0;i < gPlugins->numPlugins();i++)
263 if (d->selectedDemo->port == gPlugins->info(i)->data()->name)
265 plugin = gPlugins->info(i);
270 QMessageBox::critical(
this, tr(
"No plugin"), tr(
"The \"%1\" plugin does not appear to be loaded.").arg(d->selectedDemo->port));
276 QString binPath =
GameExeRetriever(*plugin->gameExe()).pathToOfflineExe(binMessage);
284 QMessageBox::critical(
this, tr(
"Files not found"),
285 tr(
"The following files could not be located: ") + result.
missingFiles().join(
", "));
291 params.setDemoPath(gDefaultDataPaths->demosDirectoryPath() + QDir::separator() + d->selectedDemo->filename);
293 params.setPwadsPaths(result.
foundFiles().mid(1));
294 params.setHostMode(GameCreateParams::Demo);
295 params.setExecutablePath(binPath);
302 QMessageBox::critical(
this, tr(
"Doomseeker - error"), message.
contents());
309 void DemoManagerDlg::updatePreview(
const QModelIndex &index)
311 if(!index.isValid() || !index.parent().isValid())
313 d->preview->setText(
"");
314 d->selectedDemo = NULL;
318 int dateRow = index.parent().row();
319 int timeRow = index.row();
320 d->selectedDemo = &d->demoTree[dateRow][timeRow];
322 QString text =
"<b>" + tr(
"Port") +
":</b><p style=\"margin: 0px 0px 0px 10px\">" + d->selectedDemo->port +
"</p>" +
323 "<b>" + tr(
"WADs") +
":</b><p style=\"margin: 0px 0px 0px 10px\">";
324 foreach(
const QString &wad, d->selectedDemo->wads)
326 text += wad +
"<br />";
329 d->preview->setText(text);
Result of multiple file search operation done by PathFinder.
Game parametrization data used when creating new games.
Performs a case-insensitive (OS independent) file searches.
QStringList & missingFiles()
Names of not found files.
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.
QStringList & foundFiles()
Paths to found files.
PathFinderResult findFiles(const QStringList &files) const
Performs a search for multiple files, marking them as found or missing.
Dialog for managing demos recorded through Doomseeker.
Creates game servers, offline games or demo playbacks.
QString contents() const
Customized displayable contents of this Message.
Message host(const GameCreateParams ¶ms)
void addPrioritySearchDir(const QString &dir)