More exception handling.
[emufront] / src / db / databasemanager.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 version 2 as published by
9 // the Free Software Foundation and appearing in the file gpl.txt included in the
10 // packaging of this file.
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 "databasemanager.h"
21 #include <QObject>
22 #include <QSqlDatabase>
23 #include <QSqlTableModel>
24 #include <QSqlError>
25 #include <QSqlQuery>
26 #include <QSqlRecord>
27 #include <QFile>
28 #include <QDir>
29 #include <QVariant>
30 #include <QDebug>
31 #include <QDateTime>
32
33 const QString DatabaseManager::DB_FILENAME = QString("emufront.db.sqlite");
34 const QString DatabaseManager::DATABASE = QString("QSQLITE");
35 const QString DatabaseManager::DB_TABLE_NAME_MEDIATYPE = QString("mediatype");
36 const QString DatabaseManager::DB_TABLE_NAME_PLATFORM = QString("platform");
37 const QString DatabaseManager::DB_TABLE_NAME_FILE= QString("file");
38 const QString DatabaseManager::DB_TABLE_NAME_FILEPATH = QString("filepath");
39 const QString DatabaseManager::DB_TABLE_NAME_SETUP = QString("setup");
40 const QString DatabaseManager::DB_TABLE_MEDIAIMAGECONTAINER = QString("mediaimagecontainer");
41 const QString DatabaseManager::DB_TABLE_MEDIAIMAGECONTAINER_MEDIAIMAGE = QString("mediaimagecontainer_mediaimage");
42 const QString DatabaseManager::DB_TABLE_EXECUTABLE = QString("executable");
43
44 DatabaseManager::DatabaseManager(QObject *parent)
45         : QObject(parent)
46 {
47     sqlTableModel = 0;
48 }
49
50 DatabaseManager::~DatabaseManager()
51 {
52     // no need to explicitily destroy sqlTableModel
53     // because it is parented QObject and will
54     // be destroyed when parent is destroyed
55 }
56
57 /*
58  You may wanna set the possible filters (filterDataObjects) before calling getDataModel.
59  After filtering do not set update to true. Data model is already updated.
60 */
61 QSqlQueryModel* DatabaseManager::getDataModel(bool update)
62 {
63     if (!sqlTableModel) {
64         sqlTableModel = getData();
65     }
66     else if (update)
67         clearFilters();
68     return sqlTableModel;
69 }
70
71 bool DatabaseManager::openDB()
72 {
73     QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
74     db.setDatabaseName(DatabaseManager::getDbPath());
75     return db.open();
76 }
77
78 QString DatabaseManager::getDbPath()
79 {
80         QString path;
81 #ifdef Q_OS_LINUX
82         path.append(QDir::home().path());
83         path.append(QDir::separator()).append(DB_FILENAME);
84 #else
85         path.append(DB_FILENAME);       
86 #endif
87         return path;
88 }
89
90 void DatabaseManager::resetModel()
91 {
92     if (!sqlTableModel) return;
93     clearFilters();
94 }
95
96 // sql must return a count(*) value
97 int DatabaseManager::countRows(QString tableName, QString columnName, int id) const
98 {
99     QString sql = QString("SELECT COUNT(*) FROM %1 WHERE %2 = %3")
100         .arg(tableName).arg(columnName).arg(id);
101     int numEntries = 0;
102     QSqlQuery query(sql);
103     if (query.next())
104         numEntries = query.value(0).toInt();
105     return numEntries;
106 }
107
108
109 /* Throws EmuFrontException if filtered data was not found. */
110 EmuFrontObject* DatabaseManager::getDataObject(int id)
111 {
112     filterById(id);
113     return getFilteredDataObject();
114 }
115
116 /* Throws EmuFrontException if filtered data was not found. */
117 EmuFrontObject* DatabaseManager::getDataObject(QString filter)
118 {
119     QList<QString> filters;
120     filters.append(filter);
121     filterDataObjects(filters);
122     return getFilteredDataObject(); // throws EmuFrontException
123 }
124
125 /* Throws EmuFrontException if filtered data was not found. */
126 EmuFrontObject* DatabaseManager::getFilteredDataObject()
127 {
128     EmuFrontObject *plf = 0;
129     // TODO: if record has more than one the first instance is returned
130     // ... check if this is ok in all cases!
131     if (sqlTableModel->rowCount() >= 1)
132     {
133         QSqlRecord record = sqlTableModel->record(0);
134         if (record.isEmpty()) {
135             throw EmuFrontException(tr("No filtered data available"));
136         }
137         else plf = recordToDataObject(&record);
138     }
139      return plf;
140 }
141 /* Throws EmuFrontException */
142 EmuFrontObject* DatabaseManager::getDataObjectFromModel(QModelIndex *index)
143 {
144     if (!sqlTableModel) sqlTableModel = getDataModel();
145     QSqlRecord record = sqlTableModel->record(index->row());
146     return recordToDataObject(&record);
147 }
148
149 int DatabaseManager::getCurrentTimeStamp() {
150     return QDateTime::currentDateTime().toTime_t();
151 }
152
153 int DatabaseManager::countDataObjectRefs(int id) const
154 {
155     int ret = 0;
156     QSqlQuery q;
157     q.prepare(getCountRefsSelect(id));
158     q.exec();
159     QSqlRecord rec;
160     if (q.next()) {
161         rec = q.record();
162         ret = rec.value(0).toInt();
163     }
164     qDebug() << "Found " << ret << " references.";
165     return ret;
166 }