Removed a hard coded option.
[emufront] / src / emulauncher.cpp
1 // EmuFront
2 // Copyright 2010 Mikko Keinänen
3 //
4 // This file is part of EmuFront.
5 //
6 //
7 // EmuFront is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // EmuFront is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with EmuFront.  If not, see <http://www.gnu.org/licenses/>.
19
20 #include <QtGui>
21 #include <QProcess>
22 #include <QSqlTableModel>
23 #include "utils/OSDaB-Zip/unzip.h"
24 #include "emulauncher.h"
25 #include "db/dbmediatype.h"
26 #include "db/dbplatform.h"
27 #include "db/dbexecutable.h"
28 #include "db/dbmediaimagecontainer.h"
29 #include "widgets/effileobjectcombobox.h"
30 #include "widgets/executablecombobox.h"
31 #include "dataobjects/executable.h"
32
33 EmuLauncher::EmuLauncher(QWidget *parent) :
34     QWidget(parent)
35 {
36     dbPlatform = new DbPlatform(this);
37     dbMediaType = new DbMediaType(this);
38     dbExec = new DbExecutable(this);
39     dbMic = 0;
40     proc = 0;
41     initWidgets();
42     layout();
43     connectSignals();
44 }
45
46 EmuLauncher::~EmuLauncher()
47 {
48     if (proc) {
49         proc->kill(); // TODO: do this in a more sophisticated way
50         delete proc;
51     }
52 }
53
54 void EmuLauncher::updateData()
55 {
56     platformSelectBox->updateDataModel();
57     mediaTypeSelectBox->updateDataModel();
58     execSelectBox->updateDataModel();
59 }
60
61 void EmuLauncher::initWidgets()
62 {
63     micTable = new QTableView(this);
64     micTable->setSelectionMode(QAbstractItemView::SingleSelection);
65     mediaTypeSelectBox = new EFFileObjectComboBox(dbMediaType, this);
66     platformSelectBox = new EFFileObjectComboBox(dbPlatform, this);
67     execSelectBox = new ExecutableComboBox(dbExec, this);
68     selectButton = new QPushButton(tr("&Update"));
69     launchButton = new QPushButton(tr("&Launch"));
70 }
71
72 void EmuLauncher::layout()
73 {
74     QGridLayout *grid = new QGridLayout;
75     grid->addWidget(platformSelectBox, 0, 0);
76     grid->addWidget(mediaTypeSelectBox, 1, 0);
77     grid->addWidget(selectButton, 1, 1);
78     grid->addWidget(micTable, 2, 0, 1, 2);
79     grid->addWidget(execSelectBox, 3, 0);
80     grid->addWidget(launchButton, 3, 1);
81     setLayout(grid);
82 }
83
84 void EmuLauncher::connectSignals()
85 {
86     connect(selectButton, SIGNAL(clicked()), this, SLOT(updateMediaImageContainers()));
87     connect(launchButton, SIGNAL(clicked()),this, SLOT(launchEmu()));
88 }
89
90 void EmuLauncher::updateMediaImageContainers()
91 {
92     qDebug() << "updateMediaImageContainers slot";
93     int mtid = mediaTypeSelectBox->getSelected()
94         ? mediaTypeSelectBox->getSelected()->getId()
95         : -1;
96     int plfid = platformSelectBox->getSelected()
97         ? platformSelectBox->getSelected()->getId()
98         : -1;
99
100     if (!dbMic) dbMic = new DbMediaImageContainer(this);
101     dbMic->filter(mtid, plfid);
102     micTable->setModel(dbMic->getDataModel());
103     micTable->resizeColumnsToContents();
104     platformSelectBox->updateDataModel();
105     mediaTypeSelectBox->updateDataModel();
106 }
107
108 void EmuLauncher::launchEmu()
109 {
110     try {
111         if (!micTable || !micTable->model()) {
112             throw EmuFrontException(tr("No search results available!"));
113         }
114         if (!execSelectBox || execSelectBox->currentIndex() == -1) {
115             throw EmuFrontException(tr("Emulator not selected!"));
116         }
117         // TODO: multiple media image container selection
118         QModelIndex mindex = micTable->currentIndex();
119         if (!mindex.isValid()) {
120             throw EmuFrontException(tr("Media image container not selected!"));
121         }
122         EmuFrontObject *obImg = dbMic->getDataObjectFromModel(&mindex);
123         if (!obImg) {
124             throw EmuFrontException(tr("Failed fetching selected media image container."));
125         }
126         MediaImageContainer *mic = dynamic_cast<MediaImageContainer*>(obImg);
127         if (!mic) {
128             throw EmuFrontException(tr("Failed creating media image container object!"));
129         }
130         EmuFrontObject *obExe = execSelectBox->getSelected();
131         if (!obExe) {
132             throw EmuFrontException(tr("Failed fetching selected emulator!"));
133         }
134         Executable *exe = dynamic_cast<Executable*>(obExe);
135         if (!exe) {
136             throw EmuFrontException(tr("Failed creating Emulator object!"));
137         }
138         qDebug() << "Selected media image container "
139                 << mic->getName() << " and emulator "
140                 << obExe->getName() << ".";
141         if (mic->getMediaImages().count() > 0) {
142             // TODO
143             // 1. Launch media image
144             // 2. If 2 or more media images in container
145             //    show a diaglog for choosing the boot image
146             // 3. If 2 or more media image containers selected
147             //    from a list show a dialog listing all the media
148             //    images in those container for choosing the
149             //    boot image
150             // 4. If selected emulator command line containes more
151             //    than one media image placeholder ($1, $2, ...)
152             //    show a dialog for ordering the media images to
153             //    right order.
154             QList<MediaImage*> ls = mic->getMediaImages();
155             foreach(MediaImage *mi, ls) {
156                 qDebug() << "Media image " << mi->getName();
157             }
158             launch(exe, mic);
159         }
160     } catch (EmuFrontException efe) {
161         QMessageBox::information(this, tr("Launching emulator"),
162                                  efe.what(), QMessageBox::Ok);
163         return;
164     }
165 }
166
167 void EmuLauncher::launch(const Executable * ex, const MediaImageContainer * mic)
168 {
169     // extract the media image container to tmp folder
170     // (TODO: tmp folder configuration)
171     UnZip unz;
172
173     QString fp;
174     fp.append(mic->getFilePath()->getName());
175     if (!fp.endsWith('/')) fp.append("/");
176     fp.append(mic->getName());
177     unz.openArchive(fp);
178     int err = unz.extractAll("/tmp/"); // TODO: this must be set dynamically
179     qDebug() << "extractAll to " << fp << " : " << err;
180     // launch the 1st media image in the media image list of ex
181     // or if emulator command options has a place for more than one
182     // media image assign the media images in the list order
183     // to emulator command line.
184     QString cmdWithParams;
185     cmdWithParams.append(ex->getExecutable());
186     // TODO: tmp will be set dynamically
187     // TODO: command parameters and assigning multiple media images
188     cmdWithParams.append(" \"/tmp/").append(mic->getMediaImages().first()->getName()).append("\"");
189     qDebug() << "Command with params " << cmdWithParams;
190     if (!proc) proc = new QProcess(this); // This has to be done in the heap
191     proc->start(cmdWithParams, QIODevice::ReadOnly);
192 }