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)