Emitting a dataChanged signal from setData after succesful update and connecting...
[emufront] / src / models / filepathmodel.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 "filepathmodel.h"
23 #include "emufrontfile.h"
24 #include "emufrontexception.h"
25 #include "filepathobject.h"
26 #include "setup.h"
27 #include "setupmodel.h"
28 #include <QtSql>
29
30 FilePathModel::FilePathModel(QObject *parent) :
31     EmuFrontQueryModel(parent)
32 {
33     refresh();
34 }
35
36 void FilePathModel::refresh()
37 {
38     setQuery(constructSelect());
39     setHeaderData(FilePath_Id, Qt::Horizontal, tr("Id"));
40     setHeaderData(FilePath_Name, Qt::Horizontal, tr("Name"));
41     setHeaderData(FilePath_LastScanned, Qt::Horizontal, tr("Last scanned"));
42     setHeaderData(FilePath_SetupId, Qt::Horizontal, tr("Set up id"));
43     setHeaderData(FilePath_SetupName, Qt::Horizontal, tr("Set up"));
44 }
45
46 QString FilePathModel::constructSelect(QString where) const
47 {
48     return QString("SELECT "
49                    "filepath.id AS FilePathId, "
50                    "filepath.name AS Name, "
51                    "datetime(filepath.lastscanned, 'unixepoch') AS LastScanned, "
52                    "setup.id AS SetupId, "
53                    "platform.name || ' ' || mediatype.name AS SetupName, "
54                    "filepath.filetypeid "
55                    "FROM filepath "
56                    "INNER JOIN setup ON filepath.setupid=setup.id  "
57                    "INNER JOIN platform ON setup.platformid=platform.id "
58                    "INNER JOIN mediatype ON setup.mediatypeid=mediatype.id "
59                    "%1 "
60                    "ORDER BY SetupName").arg(where);
61 }
62
63 Qt::ItemFlags FilePathModel::flags(const QModelIndex &index) const
64 {
65     Qt::ItemFlags flags = QSqlQueryModel::flags(index);
66     int col = index.column();
67     if (col == FilePath_SetupId ||
68         col == FilePath_Name) {
69         flags |= Qt::ItemIsEditable;
70     }
71     return flags;
72 }
73
74 bool FilePathModel::setData(const QModelIndex &index, const QVariant &value, int role)
75 {
76     int col = index.column();
77     if (col != FilePath_SetupId &&
78         col != FilePath_Name) {
79         return false;
80     }
81
82     QModelIndex primaryKeyIndex = QSqlQueryModel::index(index.row(), FilePath_Id);
83
84     int id = data(primaryKeyIndex).toInt();
85     clear();
86
87     bool ok;
88     switch(index.column()) {
89     case FilePath_SetupId:
90         ok = setSetup(id, value.toInt());
91         break;
92     case FilePath_Name:
93         ok = setFilePath(id, value.toString());
94         break;
95     default:
96         ok = false;
97         qDebug() << "File path model, this shouldn't be happening!";
98     }
99         if (ok) emit dataChanged();
100     refresh();
101     return ok;
102 }
103
104 bool FilePathModel::insertRows(int row, int count, const QModelIndex &parent)
105 {
106     if (parent.isValid())
107         return false; // This is a flat model
108     if (rowCount() < row)
109         row = rowCount() + 1;
110     int supId = -1;
111     QSqlQuery q;
112     q.exec(QString("SELECT setup.id, "
113            // The following is to get the correct order:
114            "platform.name || ' ' || mediatype.name AS SetupName "
115            "FROM setup "
116            "INNER JOIN platform ON setup.platformid=platform.id "
117            "INNER JOIN mediatype ON setup.mediatypeid=mediatype.id "
118            "ORDER BY SetupName "
119            "LIMIT 1"));
120     if (q.first()) {
121         supId = q.value(0).toInt();
122         qDebug() << "Got id " << supId << " for default setup.";
123     }
124     else {
125         throw EmuFrontException(tr("No setups yet available for file path configuration!"));
126     }
127     q.prepare(QString("INSERT INTO filepath "
128         "(id, name, filetypeid, setupid, lastscanned) "
129         "VALUES (NULL, '', :filetype, :setupid, :lastscanned )"));
130     beginInsertRows(QModelIndex(), row, row + count - 1);
131     for(int i = 0; i < count; ++i) {
132         q.bindValue(":filetype", EmuFrontFile::FileType_MediaImageContainer);
133         q.bindValue(":setupid", supId);
134         q.bindValue(":lastscanned", 0);
135         if (!q.exec()) {
136             throw EmuFrontException(tr("Failed creating new filepath row: %1").
137                                     arg(q.lastError().text()));
138         }
139     }
140     endInsertRows();
141     refresh();
142     return true;
143 }
144
145 bool FilePathModel::removeRows(int row, int count, const QModelIndex &parent)
146 {
147     if (parent.isValid()) {
148         return false; // This is a flat model
149     }
150     if (rowCount() < row + count - 1)
151         return false;
152
153     QSqlQuery q;
154     q.prepare(QString("DELETE FROM filepath WHERE id=:id"));
155     QModelIndex primaryIndex;
156     int id = -1;
157     beginRemoveRows(QModelIndex(), row, row + count - 1);
158     for(int i = 0; i < count; ++i) {
159         primaryIndex = QSqlQueryModel::index(row + i, FilePath_Id);
160         id = data(primaryIndex).toInt();
161         qDebug() << "Removing data item with id " << id;
162         q.bindValue(":id", id);
163         q.exec();
164     }
165     endRemoveRows();
166     refresh();
167     return true;
168 }
169
170 bool FilePathModel::setSetup(int id, int setupId)
171 {
172     QSqlQuery q;
173     q.prepare(QString("UPDATE filepath SET setupid = :setupid WHERE id = :id"));
174     q.bindValue(":setupid", setupId);
175     q.bindValue(":id", id);
176     return q.exec();
177 }
178
179 bool FilePathModel::setFilePath(int id, QString filePath)
180 {
181     QSqlQuery q;
182     q.prepare(QString("UPDATE filepath SET name = :name WHERE id = :id"));
183     q.bindValue(":name", filePath);
184     q.bindValue(":id", id);
185     return q.exec();
186 }
187
188 bool FilePathModel::setScanned(int id)
189 {
190     QSqlQuery q;
191     q.prepare(QString("UPDATE filepath SET lastscanned = :timestamp WHERE id = :id"));
192     q.bindValue(":timestamp", getCurrentTimeStamp());
193     q.bindValue(":id", id);
194     return q.exec();
195 }
196
197 FilePathObject* FilePathModel::getFilePathObject(const QModelIndex &index)
198 {
199     if (!index.isValid()) return 0;
200     EmuFrontObject *efo = getDataObject(index);
201     return dynamic_cast<FilePathObject *>(efo);
202 }
203
204 EmuFrontObject* FilePathModel::recordToDataObject(const QSqlRecord* rec)
205 {
206     int id = rec->value(FilePath_Id).toInt();
207     QString fpath = rec->value(FilePath_Name).toString();
208     int setupId = rec->value(FilePath_SetupId).toInt();
209     int fileType = rec->value(FilePath_FileTypeId).toInt();
210     SetupModel supModel;
211     EmuFrontObject *efo = supModel.getDataObject(setupId);
212     Setup *sup = dynamic_cast<Setup*>(efo);
213     return new FilePathObject(id, fpath, fileType, sup);
214 }
215
216 QString FilePathModel::constructFilterById(int id) const
217 {
218     return QString("filepath.id = %1").arg(id);
219 }