X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=src%2Femulauncher.cpp;h=0e15d4649235a0f79a88e2ea2cb88423302aacc0;hb=6bd5521ba6eedac17d194df82eda4e36de2ccb20;hp=063cccd76d0757dde4f04ba062fa06176888538e;hpb=d79e79c9de669d9d96905853bb35b1f64767c4bd;p=emufront diff --git a/src/emulauncher.cpp b/src/emulauncher.cpp index 063cccd..0e15d46 100644 --- a/src/emulauncher.cpp +++ b/src/emulauncher.cpp @@ -1,45 +1,41 @@ -// EmuFront -// Copyright 2010 Mikko Keinänen -// -// This file is part of EmuFront. -// -// -// EmuFront is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 2 as published by -// the Free Software Foundation and appearing in the file gpl.txt included in the -// packaging of this file. -// -// EmuFront is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with EmuFront. If not, see . - +/* +** EmuFront +** Copyright 2010 Mikko Keinänen +** +** This file is part of EmuFront. +** +** +** EmuFront is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License version 2 as published by +** the Free Software Foundation and appearing in the file gpl.txt included in the +** packaging of this file. +** +** EmuFront is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with EmuFront. If not, see . +*/ #include #include #include #include #include "emulauncher.h" -#include "db/dbmediatype.h" -#include "db/dbplatform.h" -#include "db/dbexecutable.h" -#include "db/dbmediaimagecontainer.h" -#include "widgets/effileobjectcombobox.h" -#include "widgets/executablecombobox.h" -#include "dataobjects/executable.h" -#include "utils/emuhelper.h" -#include "dialogs/emufrontinputdialog.h" - -EmuLauncher::EmuLauncher(QWidget *parent) : - QWidget(parent) +#include "setupmodel.h" +#include "externalexecutablemodel.h" +#include "dbmediaimagecontainer.h" +#include "effileobjectcombobox.h" +#include "executablecombobox.h" +#include "executable.h" +#include "emuhelper.h" +#include "emufrontinputdialog.h" + +EmuLauncher::EmuLauncher(QErrorMessage *errorMessage, QWidget *parent, QString tmp) : + QWidget(parent), tmpDirPath(tmp), errorMessage(errorMessage) { - dbPlatform = new DbPlatform(this); - dbMediaType = new DbMediaType(this); - dbExec = new DbExecutable(this); dbMic = 0; - proc = 0; emuHelper = new EmuHelper(this); initWidgets(); layout(); @@ -48,39 +44,51 @@ EmuLauncher::EmuLauncher(QWidget *parent) : EmuLauncher::~EmuLauncher() { - if (proc) { - proc->kill(); // TODO: do this in a more sophisticated way - delete proc; - } + if (emuHelper) { + qDebug() << "EmuLauncher destructor"; + if (emuHelper->state() == EmuHelper::Running) + qDebug() << "EmuHelper process is running, killing..."; + emuHelper->kill(); + } } void EmuLauncher::updateData() { - platformSelectBox->updateDataModel(); - mediaTypeSelectBox->updateDataModel(); - execSelectBox->updateDataModel(); } void EmuLauncher::initWidgets() { micTable = new QTableView(this); - micTable->setSelectionMode(QAbstractItemView::MultiSelection); - mediaTypeSelectBox = new EFFileObjectComboBox(dbMediaType, this); - platformSelectBox = new EFFileObjectComboBox(dbPlatform, this); - execSelectBox = new ExecutableComboBox(dbExec, this); - selectButton = new QPushButton(tr("&Update")); - launchButton = new QPushButton(tr("&Launch")); + micTable->setSelectionMode(QAbstractItemView::ExtendedSelection); + micTable->setCornerButtonEnabled(false); + micTable->verticalHeader()->setVisible(false); + micTable->horizontalHeader()->setClickable(false); + + SetupModel *supModel = new SetupModel(this); + setupSelectBox = new QComboBox(this); + setupSelectBox->setModel(supModel); + setupSelectBox->setModelColumn(SetupModel::Setup_Name); + + ExternalExecutableModel *emuModel = new ExternalExecutableModel(this); + execSelectBox = new QComboBox(this); + execSelectBox->setModel(emuModel); + execSelectBox->setModelColumn(ExternalExecutableModel::Executable_Name); + + selectButton = new QPushButton(tr("&Update"), this); + launchButton = new QPushButton(tr("&Launch"), this); } void EmuLauncher::layout() { QGridLayout *grid = new QGridLayout; - grid->addWidget(platformSelectBox, 0, 0); - grid->addWidget(mediaTypeSelectBox, 1, 0); - grid->addWidget(selectButton, 1, 1); - grid->addWidget(micTable, 2, 0, 1, 2); - grid->addWidget(execSelectBox, 3, 0); - grid->addWidget(launchButton, 3, 1); + grid->addWidget(setupSelectBox, 0, 0, 1, 2); + grid->addWidget(selectButton, 0, 2); + grid->setColumnStretch(3, 1); + + grid->addWidget(micTable, 1, 0, 1, 4); + grid->addWidget(execSelectBox, 2, 0); + grid->addWidget(launchButton, 2, 1); + // grid will be implicitly parented to this setLayout(grid); } @@ -94,27 +102,54 @@ void EmuLauncher::connectSignals() void EmuLauncher::updateMediaImageContainers() { - qDebug() << "updateMediaImageContainers slot"; - int mtid = mediaTypeSelectBox->getSelected() - ? mediaTypeSelectBox->getSelected()->getId() - : -1; - int plfid = platformSelectBox->getSelected() - ? platformSelectBox->getSelected()->getId() - : -1; + if (setupSelectBox->currentIndex() == -1) return; + + // 1. get selected platform and media type id + QAbstractItemModel *setupAbsModel = setupSelectBox->model(); + SetupModel *supModel = qobject_cast(setupAbsModel); + if (!supModel) return; + QModelIndex plfInd = + supModel->index(setupSelectBox->currentIndex(), SetupModel::Setup_PlatformId); + int plfid = supModel->data(plfInd).toInt(); + QModelIndex mtInd = + supModel->index(setupSelectBox->currentIndex(), SetupModel::Setup_MediaTypeId); + int mtid = supModel->data(mtInd).toInt(); + if (mtid < 0 || plfid < 0) return; + + // 2. fetch available media image containers if (!dbMic) dbMic = new DbMediaImageContainer(this); dbMic->filter(mtid, plfid); micTable->setModel(dbMic->getDataModel()); + micTable->hideColumn(DbMediaImageContainer::MIC_FileId); + micTable->hideColumn(DbMediaImageContainer::MIC_FileSize); + micTable->hideColumn(DbMediaImageContainer::MIC_FileCheckSum); + micTable->hideColumn(DbMediaImageContainer::MIC_FilePathId); + micTable->hideColumn(DbMediaImageContainer::MIC_FilePathName); + micTable->hideColumn(DbMediaImageContainer::MIC_SetupId); + micTable->hideColumn(DbMediaImageContainer::MIC_PlatformName); + micTable->hideColumn(DbMediaImageContainer::MIC_PlatformId); + micTable->hideColumn(DbMediaImageContainer::MIC_MediaTypeName); + micTable->hideColumn(DbMediaImageContainer::MIC_MediaTypeId); micTable->resizeColumnsToContents(); - platformSelectBox->updateDataModel(); - mediaTypeSelectBox->updateDataModel(); + + // 3. filter available emulators + QModelIndex supInd = + supModel->index(setupSelectBox->currentIndex(), SetupModel::Setup_Id); + int supid = supModel->data(supInd).toInt(); + QAbstractItemModel *execAbsModel = execSelectBox->model(); + ExternalExecutableModel *execModel = qobject_cast(execAbsModel); + if (!execModel) return; + execModel->filterBySetup(supid); } void EmuLauncher::launchEmu() { + // if selected emulator has no extensions configured, it's assumed to be a M.A.M.E. or similar and + // map of media images will be no be used QMap mediaImages; QList mediaImageContainers; - Executable *exe; + Executable *exe = 0; try { if (!micTable || !micTable->model()) { throw EmuFrontException(tr("No search results available!")); @@ -129,18 +164,34 @@ void EmuLauncher::launchEmu() } qDebug() << listMIndex.count() << " items selected."; - EmuFrontObject *obExe = execSelectBox->getSelected(); + // TODO: write a method to ExternalExecutable to return an Executable object of a selected row. + // TODO2: rewrite ExecutableComboBox and reimplement getSelected? + /*EmuFrontObject *obExe = execSelectBox->getSelected(); if (!obExe) { throw EmuFrontException(tr("Failed fetching selected emulator!")); } exe = dynamic_cast(obExe); if (!exe) { throw EmuFrontException(tr("Failed creating Emulator object!")); + }*/ + + qDebug() << "File types; " << exe->getSetup()->getSupportedFileTypeExtensions().count(); + + bool mame = exe->getSetup()->getSupportedFileTypeExtensions().isEmpty(); + + if (mame && listMIndex.count() > 1) { + throw EmuFrontException(tr("No supported file types configured for this emulator configuration. " + "Assuming emulator support container files as is. " + "Only one container can be selected without configuring supported file types." + )); } + // Now we have one or more media image containers and an emulator selected, + // let's fetch the media image container data. + foreach(QModelIndex mind, listMIndex) { if (!mind.isValid()) continue; - EmuFrontObject *obImg = dbMic->getDataObjectFromModel(&mind); + EmuFrontObject *obImg = dbMic->getDataObjectFromModel(&mind); // throws EmuFrontException if (!obImg) { qDebug() << "Failed creating media image container at row " << mind.row(); continue; @@ -156,67 +207,92 @@ void EmuLauncher::launchEmu() mediaImages.unite(contained); } - if (mediaImages.count() < 1) { - throw EmuFrontException("No media images available!"); + if (mame) { + emuHelper->launch(exe, mediaImageContainers); + return; } + else { + // mediaImageContainers list contains all the selected media image containers and + // mediaImages list contains all the media images inside all the selected containers - // check if command options have slots for nr media images > 1 e.g. "-diska $1 -diskb $2 ..." - QString opts = exe->getOptions(); - QRegExp rx("(\\s\\$\\d+)"); - QStringList list; - int pos = 0; - while ((pos = rx.indexIn(opts, pos)) != -1) { - list << rx.cap(1); - pos += rx.matchedLength(); - } + QList selectedImages; + if (mediaImages.count() < 1) { + throw EmuFrontException("No media images available!"); + } - bool ok; - QList selectedImages; - if (list.count() > mediaImages.count()) { - throw EmuFrontException(tr("Select %1 media images for this emulator configuration").arg(list.count())); - } - if (list.count() > 1) { - int lim = list.count() == mediaImages.count() ? list.count() - 1 : list.count(); - for(int i = 0; i < lim; i++) { + // check if command options have slots for nr media images > 1 e.g. "-diska $1 -diskb $2 ..." + QString opts = exe->getOptions(); + QRegExp rx("(\\$\\d+)"); + QStringList list; + int pos = 0; + while ((pos = rx.indexIn(opts, pos)) != -1) { + list << rx.cap(1); + pos += rx.matchedLength(); + } + bool ok; + + if (list.count() > mediaImages.count()) { + throw EmuFrontException(tr("Select %1 media images for this emulator configuration").arg(list.count())); + } + if (list.count() > 1) { + // more than one placeholder for media image in the command line ($1, $2, ...) + int lim = list.count() == mediaImages.count() ? list.count() - 1 : list.count(); + // user sets the order of media images + for(int i = 0; i < lim; i++) { + EmuFrontObject *efo = EmuFrontInputDialog::getItem( + this, tr("Select image no. %1").arg(i+1), tr("Select"), mediaImages.values(), 0, false, &ok); + if (!ok) { + throw EmuFrontException(tr("Boot image selection was canceled, aborting.")); + } + selectedImages << efo; + MediaImage *mi = dynamic_cast(efo); + QString key = mi->getCheckSum(); + mediaImages.remove(key); + } + // there should be at least one media image left in mediaImages map... + /*if (mediaImages.count() == 1) { + selectedImages << mediaImages.values().first(); + } ... this is added later-> */ + } + else if (mediaImages.count() > 1) { + // show select boot image dialog EmuFrontObject *efo = EmuFrontInputDialog::getItem( - this, tr("Select image no. %1").arg(i+1), tr("Select"), mediaImages.values(), 0, false, &ok); + this, tr("Select boot image"), tr("Select"), mediaImages.values(), 0, false, &ok); if (!ok) { throw EmuFrontException(tr("Boot image selection was canceled, aborting.")); } selectedImages << efo; MediaImage *mi = dynamic_cast(efo); - mediaImages.remove(mi->getCheckSum()); + QString key = mi->getCheckSum(); + mediaImages.remove(key); } - if (list.count() == mediaImages.count() && mediaImages.count() == 1) { - // there should be only one media image left in mediaImages map - selectedImages << mediaImages.values().first(); + else if (mediaImages.count() == 1) { + EmuFrontObject *efo = mediaImages.values().first(); + selectedImages << efo; + MediaImage *mi = dynamic_cast(efo); + QString key = mi->getCheckSum(); + mediaImages.remove(key); } - } - else if (mediaImages.count() > 1) { - // show select boot image dialog - EmuFrontObject *efo = EmuFrontInputDialog::getItem( - this, tr("Select boot image"), tr("Select"), mediaImages.values(), 0, false, &ok); - if (!ok) { - throw EmuFrontException(tr("Boot image selection was canceled, aborting.")); + // in all the both cases the (ordered) list of media images will be passed to emuHelper + + // wee also keep the rest of the mediaimages in the selected containers for reference! + foreach(EmuFrontObject *efo, mediaImages) { + selectedImages << efo; } - selectedImages << efo; - } - else if (mediaImages.count() == 1) - selectedImages << mediaImages.values().first(); - // in the both cases the (ordered) list of media images will be passed to emuHelper - if (selectedImages.count() < 1) - throw EmuFrontException(tr("No media images selected")); + if (selectedImages.count() < 1) + throw EmuFrontException(tr("No media images selected")); - emuHelper->launch(exe, mediaImageContainers, selectedImages); + emuHelper->launch(exe, mediaImageContainers, selectedImages, list.count(), tmpDirPath); + } } catch (EmuFrontException efe) { - delete exe; - qDeleteAll(mediaImageContainers); - //qDeleteAll(mediaImages); these are already deleted along with containers - QMessageBox::information(this, tr("Launching emulator"), - efe.what(), QMessageBox::Ok); - return; + errorMessage->showMessage(efe.what()); } + + micTable->clearSelection(); + if (exe) delete exe; + qDeleteAll(mediaImageContainers); + //qDeleteAll(mediaImages); these are already deleted along with containers } void EmuLauncher::processError(QProcess::ProcessError e) @@ -225,7 +301,7 @@ void EmuLauncher::processError(QProcess::ProcessError e) QString stdErr = emuHelper->readAllStandardError(); QMessageBox::warning(this, tr("Emulator"), tr("Launching emulator failed with: %1.\n").arg(e) - .append(";\n").append(proc->errorString().append(";\n") + .append(";\n").append(emuHelper->errorString().append(";\n") .append(stdErr)), QMessageBox::Ok ); } @@ -236,7 +312,7 @@ void EmuLauncher::processFinished(int a) QString stdErr = emuHelper->readAllStandardError(); QString stdMsg = emuHelper->readAllStandardOutput(); QString msg = tr("Emulator has finished with: %1.\n").arg(a).append(stdMsg); - if (a) msg.append("; ").append(proc->errorString()).append(";\n").append(stdErr); + if (a) msg.append("; ").append(emuHelper->errorString()).append(";\n").append(stdErr); QMessageBox::information(this, tr("Emulator finished"), msg, QMessageBox::Ok); } @@ -244,3 +320,8 @@ void EmuLauncher::cleanTmp() { // TODO } + +void EmuLauncher::setTmpDirPath(QString tmp) +{ + tmpDirPath = tmp; +}