Implemented all the necessary methods in ExternalExecutableModel.
[emufront] / src / models / externalexecutablemodel.cpp
1 /*
2 ** EmuFront
3 ** Copyright 2010 Mikko Keinänen
4 **
5 ** This file is part of EmuFront.
6 **
7 **
8 ** EmuFront is free software: you can redistribute it and/or modify
9 ** it under the terms of the GNU General Public License version 2 as published by
10 ** the Free Software Foundation and appearing in the file gpl.txt included in the
11 ** packaging of this file.
12 **
13 ** EmuFront is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ** GNU General Public License for more details.
17 **
18 ** You should have received a copy of the GNU General Public License
19 ** along with EmuFront.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "externalexecutablemodel.h"
23 #include "executable.h"
24 #include "emufrontexception.h"
25 #include <QtSql>
26
27 ExternalExecutableModel::ExternalExecutableModel(QObject *parent) :
28     EmuFrontQueryModel(parent)
29 {
30     editableColumns << Executable_Name;
31     editableColumns << Executable_Options;
32     editableColumns << Executable_Executable;
33     editableColumns << Executable_SetupId;
34     refresh();
35 }
36
37 void ExternalExecutableModel::refresh()
38 {
39     setQuery(constructSelect());
40     setHeaderData(Executable_Id, Qt::Horizontal, tr("Id"));
41     setHeaderData(Executable_Name, Qt::Horizontal, tr("Name"));
42     setHeaderData(Executable_Executable, Qt::Horizontal, tr("Executable"));
43     setHeaderData(Executable_Options, Qt::Horizontal, tr("Options"));
44     setHeaderData(Executable_TypeId, Qt::Horizontal, tr("Type"));
45     setHeaderData(Executable_SetupId, Qt::Horizontal, tr("Setup id"));
46     setHeaderData(Executable_SetupName, Qt::Horizontal, tr("Setup"));
47 }
48
49 QString ExternalExecutableModel::constructSelect(QString where) const
50 {
51     return QString("SELECT "
52                    "executable.id AS ExecutableId, "
53                    "executable.name AS ExecutableName, "
54                    "executable.executable AS Executable, "
55                    "executable.options AS ExecutableOptions, "
56                    "executable.type AS ExecutableType, "
57                    "setup.id As ExecutableSetupId, "
58                    "platform.name || ' ' || mediatype.name AS SetupName "
59                    "FROM executable "
60                    "INNER JOIN setup ON executable.setupid = setup.id "
61                    "INNER JOIN platform ON setup.platformid=platform.id "
62                    "INNER JOIN mediatype ON setup.mediatypeid=mediatype.id "
63                    "%1 "
64                    "ORDER BY executable.name").arg(where);
65 }
66
67 Qt::ItemFlags ExternalExecutableModel::flags(const QModelIndex &index) const
68 {
69     Qt::ItemFlags flags = QSqlQueryModel::flags(index);
70     int col = index.column();
71     if (editableColumns.contains(index.column())) {
72        flags  |= Qt::ItemIsEditable;
73     }
74     return flags;
75 }
76
77 bool ExternalExecutableModel::setData(const QModelIndex &index, const QVariant &value, int role)
78 {
79     if (!editableColumns.contains(index.column()))
80         return false;
81
82     QModelIndex primaryKeyIndex = QSqlQueryModel::index(index.row(), Executable_Id);
83     int id = data(primaryKeyIndex).toInt();
84     clear();
85     bool ok;
86     switch(index.column())
87     {
88         case Executable_Name:
89             ok = setExecutableName(id, value.toString());
90             break;
91         case Executable_Executable:
92             ok = setExecutable(id, value.toString());
93             break;
94         case Executable_Options:
95             ok = setOptions(id, value.toString());
96             break;
97         case Executable_SetupId:
98             ok = setSetup(id, value.toInt());
99             break;
100         default:
101             ok = false;
102     }
103     refresh();
104     return ok;
105 }
106
107 bool ExternalExecutableModel::insertRows(int row, int count, const QModelIndex &parent)
108 {
109     if (parent.isValid())
110         return false; // This is a flat model
111     if (rowCount() < row)
112         row = rowCount() + 1;
113
114     // Fetch a setup for an initial selection
115     int supId = -1;
116     QSqlQuery q;
117     q.exec(QString("SELECT setup.id, "
118            // The following is to get the correct order:
119            "platform.name || ' ' || mediatype.name AS SetupName "
120            "FROM setup "
121            "INNER JOIN platform ON setup.platformid=platform.id "
122            "INNER JOIN mediatype ON setup.mediatypeid=mediatype.id "
123            "ORDER BY SetupName "
124            "LIMIT 1"));
125     if (q.first()) {
126         supId = q.value(0).toInt();
127         qDebug() << "Got id " << supId << " for default setup.";
128     }
129     else {
130         throw EmuFrontException(tr("No setups yet available for file path configuration!"));
131     }
132     q.prepare(QString("INSERT INTO executable "
133         "(id, name, executable, options, type, setupid) "
134         "VALUES (NULL, '', '', '', :type, :supid)"
135     ));
136     beginInsertRows(QModelIndex(), row, row + count - 1);
137     for(int i = 0; i < count; ++i) {
138         q.bindValue(":supid", supId);
139         q.bindValue(":type", Executable::ExecutableType_Emulator);
140         if (!q.exec()) {
141             throw EmuFrontException(tr("Failed creating new external executable row: %1").
142                                     arg(q.lastError().text()));
143         }
144     }
145     endInsertRows();
146     refresh();
147     return true;
148 }
149
150 bool ExternalExecutableModel::removeRows(int row, int count, const QModelIndex &parent)
151 {
152     if (parent.isValid()) {
153         return false; // This is a flat model
154     }
155     if (rowCount() < row + count - 1)
156         return false;
157
158     QSqlQuery q;
159     q.prepare(QString("DELETE FROM executable WHERE id=:id"));
160     QModelIndex primaryIndex;
161     int id = -1;
162     beginRemoveRows(QModelIndex(), row, row + count - 1);
163     for(int i = 0; i < count; ++i) {
164         primaryIndex = QSqlQueryModel::index(row + i, Executable_Id);
165         id = data(primaryIndex).toInt();
166         qDebug() << "Removing data item with id " << id;
167         q.bindValue(":id", id);
168         q.exec();
169     }
170     endRemoveRows();
171     refresh();
172     return true;
173 }
174
175 bool ExternalExecutableModel::setSetup(int id, int setupId)
176 {
177     QSqlQuery q;
178     q.prepare(QString("UPDATE executable SET setupid = :supid WHERE id = :id"));
179     q.bindValue(":supid", setupId);
180     q.bindValue(":id", id);
181     return q.exec();
182 }
183
184 bool ExternalExecutableModel::setExecutable(int id, QString name)
185 {
186     QSqlQuery q;
187     q.prepare(QString("UPDATE executable SET executable = :exec WHERE id = :id"));
188     q.bindValue(":exec", name);
189     q.bindValue(":id", id);
190     return q.exec();
191 }
192
193 bool ExternalExecutableModel::setOptions(int id, QString options)
194 {
195     QSqlQuery q;
196     q.prepare(QString("UPDATE executable SET options = :opts WHERE id = :id"));
197     q.bindValue(":opts", options);
198     q.bindValue(":id", id);
199     return q.exec();
200 }
201
202 bool ExternalExecutableModel::setExecutableName(int id, QString name)
203 {
204     QSqlQuery q;
205     q.prepare(QString("UPDATE executable SET name = :name WHERE id = :id"));
206     q.bindValue(":name", name);
207     q.bindValue(":id", id);
208     return q.exec();
209 }