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> 52 QStringList optionalWads;
55 DClass<DemoManagerDlg> :
public Ui::DemoManagerDlg
59 QStandardItemModel *demoModel;
60 QList<QList<Demo> > demoTree;
68 d->selectedDemo = NULL;
70 d->demoModel =
new QStandardItemModel();
73 connect(d->demoList->selectionModel(), SIGNAL( currentChanged(
const QModelIndex &,
const QModelIndex &) ),
this, SLOT( updatePreview(
const QModelIndex &) ));
76 DemoManagerDlg::~DemoManagerDlg()
80 void DemoManagerDlg::adjustDemoList()
83 QStringList demoExtensions;
84 for(
unsigned i = 0;i < gPlugins->numPlugins();++i)
86 QString ext = QString(
"*.%1").arg(gPlugins->info(i)->data()->demoExtension);
88 if(!demoExtensions.contains(ext))
90 demoExtensions << ext;
96 QDate today = QDate::currentDate();
97 QTime referenceTime(23, 59, 59);
98 QDir demosDirectory(gDefaultDataPaths->demosDirectoryPath());
99 QStringList demos = demosDirectory.entryList(demoExtensions, QDir::Files);
100 typedef QMap<int, Demo> DemoMap;
101 QMap<int, DemoMap> demoMap;
102 foreach(
const QString &demoName, demos)
104 QStringList demoData;
105 QString metaData = demoName.left(demoName.lastIndexOf(
"."));
107 for(
int i = 0;i < metaData.length();++i)
109 if(metaData[i] ==
'_')
112 if(i+1 < metaData.length() && metaData[i+1] ==
'_')
119 demoData << metaData.left(i).replace(
"__",
"_");
120 metaData = metaData.mid(i+1);
125 demoData << metaData.replace(
"__",
"_");
126 if(demoData.size() < 3)
129 QDate date = QDate::fromString(demoData[1],
"dd.MM.yyyy");
130 QTime time = QTime::fromString(demoData[2],
"hh.mm.ss");
132 demo.filename = demoName;
133 demo.port = demoData[0];
134 demo.time = QDateTime(date, time);
135 if(demoData.size() >= 4)
136 demo.wads = demoData.mid(3);
141 gDefaultDataPaths->demosDirectoryPath() + QDir::separator() + demoName +
".ini",
142 QSettings::IniFormat);
144 Ini metaData(&settingsProvider);
145 demo.wads << metaData.retrieveSetting(
"meta",
"iwad");
146 QString pwads = metaData.retrieveSetting(
"meta",
"pwads");
147 if(pwads.length() > 0)
148 demo.wads << pwads.split(
";");
149 demo.optionalWads = metaData.retrieveSetting(
"meta",
"optionalPwads").value().toStringList();
152 demoMap[date.daysTo(today)][time.secsTo(referenceTime)] = demo;
156 d->demoModel->clear();
158 foreach(
const DemoMap &demoDate, demoMap)
160 QStandardItem *item =
new QStandardItem(demoDate.begin().value().time.toString(
"ddd. MMM d, yyyy"));
161 QList<Demo> demoDateList;
162 foreach(
const Demo &demo, demoDate)
164 demoDateList << demo;
165 item->appendRow(
new QStandardItem(demo.time.toString(
"hh:mm:ss")));
167 d->demoTree << demoDateList;
168 d->demoModel->appendRow(item);
170 d->demoList->setModel(d->demoModel);
173 bool DemoManagerDlg::doRemoveDemo(
const QString &file)
175 if(!QFile::remove(file))
176 QMessageBox::critical(
this, tr(
"Unable to delete"), tr(
"Could not delete the selected demo."));
180 QFile::remove(file +
".ini");
181 d->selectedDemo = NULL;
187 void DemoManagerDlg::deleteSelected()
189 if(QMessageBox::question(
this, tr(
"Delete demo?"),
190 tr(
"Are you sure you want to delete the selected demo?"),
191 QMessageBox::Yes|QMessageBox::Cancel) == QMessageBox::Yes)
193 QModelIndex index = d->demoList->selectionModel()->currentIndex();
194 if(d->selectedDemo == NULL)
196 int dateRow = index.row();
197 for(
int timeRow = 0;index.child(timeRow, 0).isValid();++timeRow)
199 if(doRemoveDemo(gDefaultDataPaths->demosDirectoryPath() + QDir::separator() + d->demoTree[dateRow][timeRow].filename))
201 d->demoModel->removeRow(timeRow, index);
202 d->demoTree[dateRow].removeAt(timeRow);
203 if(d->demoTree[dateRow].size() == 0)
205 d->demoModel->removeRow(dateRow);
206 d->demoTree.removeAt(dateRow);
217 if(doRemoveDemo(gDefaultDataPaths->demosDirectoryPath() + QDir::separator() + d->selectedDemo->filename))
220 int dateRow = index.parent().row();
221 int timeRow = index.row();
223 d->demoModel->removeRow(timeRow, index.parent());
224 d->demoTree[dateRow].removeAt(timeRow);
225 if(d->demoTree[dateRow].size() == 0)
227 d->demoModel->removeRow(dateRow);
228 d->demoTree.removeAt(dateRow);
235 void DemoManagerDlg::exportSelected()
237 if(d->selectedDemo == NULL)
240 QFileDialog saveDialog(
this);
241 saveDialog.setAcceptMode(QFileDialog::AcceptSave);
242 saveDialog.selectFile(d->selectedDemo->filename);
243 if(saveDialog.exec() == QDialog::Accepted)
246 if(!QFile::copy(gDefaultDataPaths->demosDirectoryPath() + QDir::separator() + d->selectedDemo->filename, saveDialog.selectedFiles().first()))
247 QMessageBox::critical(
this, tr(
"Unable to save"), tr(
"Could not write to the specified location."));
251 void DemoManagerDlg::playSelected()
253 if(d->selectedDemo == NULL)
258 for(
unsigned i = 0;i < gPlugins->numPlugins();i++)
260 if (d->selectedDemo->port == gPlugins->info(i)->data()->name)
262 plugin = gPlugins->info(i);
267 QMessageBox::critical(
this, tr(
"No plugin"),
268 tr(
"The \"%1\" plugin does not appear to be loaded.").arg(d->selectedDemo->port));
274 QString binPath =
GameExeRetriever(*plugin->gameExe()).pathToOfflineExe(binMessage);
282 QMessageBox::critical(
this, tr(
"Files not found"),
283 tr(
"The following files could not be located: ") + wadsPaths.
missingFiles().join(
", "));
290 params.setDemoPath(gDefaultDataPaths->demosDirectoryPath()
291 + QDir::separator() + d->selectedDemo->filename);
292 params.setIwadPath(wadsPaths.
foundFiles()[0]);
294 params.setHostMode(GameCreateParams::Demo);
295 params.setExecutablePath(binPath);
302 QMessageBox::critical(
this, tr(
"Doomseeker - error"), message.
contents());
310 void DemoManagerDlg::performAction(QAbstractButton *button)
312 if(button == d->buttonBox->button(QDialogButtonBox::Close))
316 void DemoManagerDlg::updatePreview(
const QModelIndex &index)
318 if(!index.isValid() || !index.parent().isValid())
320 d->preview->setText(
"");
321 d->selectedDemo = NULL;
325 int dateRow = index.parent().row();
326 int timeRow = index.row();
327 d->selectedDemo = &d->demoTree[dateRow][timeRow];
329 QString text =
"<b>" + tr(
"Port") +
":</b><p style=\"margin: 0px 0px 0px 10px\">" + d->selectedDemo->port +
"</p>" +
330 "<b>" + tr(
"WADs") +
":</b><p style=\"margin: 0px 0px 0px 10px\">";
331 foreach(
const QString &wad, d->selectedDemo->wads)
333 text += wad +
"<br />";
335 foreach(
const QString &wad, d->selectedDemo->optionalWads)
337 text +=
"[" + wad +
"]<br />";
340 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)