Imported needed functionality from (soon) deprecated database
[emufront] / src / models / setupmodel.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 #include "setup.h"
22 #include "setupmodel.h"
23 #include "platform.h"
24 #include "mediatype.h"
25 #include "platformmodel.h"
26 #include "mediatypemodel.h"
27 #include "emufrontexception.h"
28 #include <QtSql>
29
30 const QString SetupModel::FILE_TYPE_EXTENSION_SEPARATOR = QString("|");
31
32 SetupModel::SetupModel(QObject *parent) :
33     EmuFrontQueryModel(parent)
34 {
35     refresh();
36 }
37
38 void SetupModel::refresh()
39 {
40     setQuery(constructSelect());
41     setHeaderData(Setup_Id, Qt::Horizontal, tr("Id"));
42     setHeaderData(Setup_PlatformId, Qt::Horizontal, tr("Platform id"));
43     setHeaderData(Setup_MediaTypeId, Qt::Horizontal, tr("Media type id"));
44     setHeaderData(Setup_FileTypeExtensions, Qt::Horizontal, tr("File types"));
45     setHeaderData(Setup_Name, Qt::Horizontal, tr("Name"));
46 }
47
48 QString SetupModel::constructSelect(QString where) const
49 {
50     return QString(
51         "SELECT setup.id AS SetupId, "
52         "setup.platformid AS PlatformId, "
53         "setup.mediatypeid AS MediaTypeId, "
54         "setup.filetypeextensions AS SupportedFileTypeExtensions, "
55         "platform.name || ' ' || mediatype.name AS SetupName "
56         "FROM setup "
57         "INNER JOIN platform ON setup.platformid=platform.id "
58         "INNER JOIN mediatype ON setup.mediatypeid=mediatype.id %1 "
59         "ORDER BY SetupName"
60         ).arg(where);
61 }
62
63 Qt::ItemFlags SetupModel::flags(const QModelIndex &index) const
64 {
65     Qt::ItemFlags flags = QSqlQueryModel::flags(index);
66     int col = index.column();
67     if (col == Setup_PlatformId ||
68         col == Setup_MediaTypeId ||
69         col == Setup_FileTypeExtensions) {
70         flags |= Qt::ItemIsEditable;
71     }
72     return flags;
73 }
74
75 bool SetupModel::setData(const QModelIndex &index, const QVariant &value, int /*role*/)
76 {
77     int col = index.column();
78     if(col != Setup_PlatformId &&
79         col != Setup_MediaTypeId &&
80         col != Setup_FileTypeExtensions)
81         return false;
82
83     QModelIndex primaryKeyIndex
84         = QSqlQueryModel::index(index.row(), Setup_Id);
85
86     int id = data(primaryKeyIndex).toInt();
87     clear();
88
89     bool ok;
90     switch(index.column()) {
91
92     case Setup_PlatformId:
93         ok = setPlatform(id, value.toInt());
94         break;
95
96     case Setup_MediaTypeId:
97         ok = setMediaType(id, value.toInt());
98         break;
99
100     case Setup_FileTypeExtensions:
101         ok = setSupportedExtensions(id, value.toString());
102         break;
103
104     default:
105         ok = false;
106         qDebug() << "Setup model, this shouldn't be happening!";
107     };
108     refresh();
109     return ok;
110 }
111
112 bool SetupModel::setPlatform(int id, int platformId)
113 {
114     QSqlQuery query;
115     query.prepare(QString("update setup set platformid = :platformid where id = :id"));
116     query.bindValue(":platformid", platformId);
117     query.bindValue(":id", id);
118     return query.exec();
119 }
120
121 bool SetupModel::setMediaType(int id, int mediaTypeId)
122 {
123     QSqlQuery query;
124     query.prepare(QString("update setup set mediatypeid = :mediatypeid where id = :id"));
125     query.bindValue(":mediatypeid", mediaTypeId);
126     query.bindValue(":id", id);
127     return query.exec();
128 }
129
130 bool SetupModel::setSupportedExtensions(int id, QString exts)
131 {
132     QSqlQuery query;
133     query.prepare(QString("update setup set filetypeextensions = :exts where id = :id"));
134     query.bindValue(":exts", exts);
135     query.bindValue(":id", id);
136     return query.exec();
137 }
138
139 bool SetupModel::insertRows(int row, int count, const QModelIndex &parent)
140 {
141     if (parent.isValid())
142         return false; // This is a flat model
143     if (rowCount() < row)
144         row = rowCount() + 1;
145     // we need a default value for platformid and mediatypeid and if none is yet
146     // available an error message must be shown!
147     int plfId = -1;
148     int mdtId = -1;
149     QSqlQuery q;
150     q.exec(QString("SELECT id FROM platform ORDER BY name LIMIT 1"));
151     if (q.first()){
152         plfId = q.value(0).toInt();
153         qDebug() << "Got id " << plfId << " for default platform.";
154     }
155     else {
156         throw EmuFrontException(tr("No platforms yet available for setup configuration!"));
157     }
158     q.exec(QString("SELECT id FROM mediatype ORDER BY name LIMIT 1"));
159     if (q.first()) {
160         mdtId = q.value(0).toInt();
161         qDebug() << "Got id " << mdtId << " for default media type.";
162     }
163     else {
164         throw EmuFrontException(tr("No media types yet available for setup configuration!"));
165     }
166     q.prepare(QString("INSERT INTO setup (id, platformid, mediatypeid, filetypeextensions) "
167         " VALUES (NULL, :plfid, :mdtid, '') "));
168     beginInsertRows(QModelIndex(), row, row + count - 1);
169     for (int i = 0; i < count; ++i) {
170         q.bindValue(":plfid", plfId);
171         q.bindValue(":mdtid", mdtId);
172         if (!q.exec()) {
173             throw EmuFrontException(tr("Failed creating new setup: %1").
174                 arg(q.lastError().text()));
175         }
176     }
177     endInsertRows();
178     refresh();
179     return true;
180 }
181
182 bool SetupModel::removeRows(int row, int count, const QModelIndex &parent)
183 {
184     if (parent.isValid()) {
185         return false; // This is a flat model
186     }
187     if (rowCount() < row + count - 1)
188         return false;
189
190     QSqlQuery q;
191     q.prepare(QString("DELETE FROM setup WHERE id=:id"));
192     QModelIndex primaryIndex;
193     int id = -1;
194     beginRemoveRows(QModelIndex(), row, row + count - 1);
195     for(int i = 0; i < count; ++i) {
196         primaryIndex = QSqlQueryModel::index(row + i, Setup_Id);
197         id = data(primaryIndex).toInt();
198         qDebug() << "Removing data item with id " << id;
199         q.bindValue(":id", id);
200         q.exec();
201     }
202     endRemoveRows();
203     refresh();
204     return true;
205 }
206
207 // Implemented for EmuFrontQueryModel:
208 EmuFrontObject* SetupModel::recordToDataObject(const QSqlRecord *rec)
209 {
210     Setup *s = 0;
211     if (!rec) return s;
212
213     int id = rec->value(Setup_Id).toInt();
214     QString extensions = rec->value(Setup_FileTypeExtensions).toString().trimmed();
215     QStringList list;
216     if (!extensions.isEmpty())
217         list = extensions.split(FILE_TYPE_EXTENSION_SEPARATOR);
218     int plfId = rec->value(Setup_PlatformId).toInt();
219     int mtId = rec->value(Setup_MediaTypeId).toInt();
220     PlatformModel plfModel;
221     EmuFrontObject *efo_plf = plfModel.getDataObject(plfId);
222     Platform *plf = dynamic_cast<Platform*>(efo_plf);
223
224     MediaTypeModel mdtModel;
225     EmuFrontObject *efo_mdt = mdtModel.getDataObject(mtId);
226     MediaType *mt = dynamic_cast<MediaType*>(efo_mdt);
227
228     s = new Setup(id, plf, mt, list);
229     return s;
230 }
231
232 QString SetupModel::constructFilterById(int id) const
233 {
234      return QString("setup.id = %1").arg(id);
235 }
236