Create data objects (media image container and emulator) by EmuLauncher
[emufront] / src / db / dbmediaimagecontainer.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 <QDebug>
21 #include <QSqlRecord>
22 #include <QSqlQuery>
23 #include <QSqlRelationalTableModel>
24 #include <QSqlError>
25 #include "dbmediaimagecontainer.h"
26 #include "dbmediaimage.h"
27 //#include "dbsetup.h"
28 #include "dbfilepath.h"
29
30 DbMediaImageContainer::DbMediaImageContainer(QObject *parent)
31     : DbFile(parent) // DbQueryModelManager(parent)
32 {
33     dbMediaImage = new DbMediaImage(parent);
34     dbFilePath = new DbFilePath(parent);
35     //dbFile = new DbFile(parent);
36 }
37
38 bool DbMediaImageContainer::updateDataObjectToModel(const EmuFrontObject *efo)
39 {
40     // TODO
41     return false;
42 }
43
44 int DbMediaImageContainer::insertDataObjectToModel(const EmuFrontObject *efo)
45 {
46     const MediaImageContainer *mic
47         = dynamic_cast<const MediaImageContainer *>(efo);
48
49     // check if this media image container is already in the database
50     EmuFrontObject *o = getFileByChecksum(mic->getCheckSum());
51     int fileId = o ? o->getId() : -1;
52     /*int fileId = getMediaImageContainer(mic->getCheckSum());*/
53     if (fileId >= 0) {
54         qDebug() << "Media image container already in db with id " << fileId << ".";
55         return fileId;
56    }
57
58     if (!mic->getFilePath())
59         throw new EmuFrontException("Cannot install media image "
60             "container to database without a file path object!");
61
62     QList<MediaImage*> images = mic->getMediaImages();
63     QList<int> ids = dbMediaImage->storeMediaImages(images);
64
65     qDebug() << "Stored " << ids.count() << " media images.";
66
67     if (ids.count() <= 0)
68         return -1;
69
70     /* Contained Media images successfully stored to db,
71         storing media image container also */
72
73     try {
74
75         // Insert MediaImageContainer first as a EmuFrontFile object to file table.
76
77         // File id is used to store the media image container instance to database,
78         // file id is also the media image container id
79         fileId = DbFile::insertDataObjectToModel(mic);
80
81         qDebug() << "Inserted media image container to file table with id " << fileId << ".";
82
83         if (fileId < 0) {
84             // TODO: note we most surely need to catch the exception
85             // in the calling code block and clean
86             // all the media image and ...containers from
87             // the memory!
88             throw new EmuFrontException(
89                     QString(tr("Inserting media image container %1 to file database failed"))
90                     .arg(mic->getName()));
91         }
92
93         // Insert to mediaimagecontainer table
94
95         QSqlQuery q;
96         q.prepare("INSERT INTO mediaimagecontainer "
97                   "(fileid, filepathid, updatetime) "
98                   "VALUES (:fileid, :filepathid, :updatetime)");
99         q.bindValue(":fileid", fileId);
100         q.bindValue(":filepathid", mic->getFilePath()->getId());
101         q.bindValue(":updatetime", DatabaseManager::getCurrentTimeStamp());
102         if (!q.exec()){
103             DbFile::deleteDataObject(fileId);
104             throw new EmuFrontException("Failed inserting media image to database!");
105         }
106         qDebug() << "Inserted media image container " << fileId << " to mediaimagecontainer table.";
107         linkMediaImagesWithContainer(fileId, ids);
108         qDebug() << "Linked media image container with media images.";
109     } catch (EmuFrontException e) {
110         dbMediaImage->removeOrphanedMediaImages(ids);
111         throw e;
112     }
113
114     return fileId;
115 }
116
117 bool DbMediaImageContainer::deleteDataObjectFromModel(QModelIndex *i)
118 {
119     // TODO
120     return false;
121 }
122
123 int DbMediaImageContainer::countDataObjectRefs(int id) const
124 {
125     // TODO
126     return -1;
127 }
128
129 QString DbMediaImageContainer::constructSelect(QString whereClause) const
130 {
131     // TODO, for a usual search we need a "light" version of this select
132     // and MediaImageContainer (only id, name)
133     QString select = QString("SELECT file.id, file.name, file.checksum, file.size, "
134                 "        filepath.id, filepath.name, "
135                 "        setup.id, "
136                 "        platform.id, platform.name, "
137                 "        mediatype.id, mediatype.name "
138                 "FROM mediaimagecontainer "
139                 "INNER JOIN file ON mediaimagecontainer.fileid = file.id "
140                 "INNER JOIN filepath ON mediaimagecontainer.filepathid = filepath.id "
141                 "INNER JOIN setup ON filepath.setupid = setup.id "
142                 "INNER JOIN platform ON setup.platformid = platform.id "
143                 "INNER JOIN mediatype ON setup.mediatypeid = mediatype.id "
144                 "%1 "
145                 "ORDER BY file.name").arg(whereClause);
146     qDebug() << select;
147     return select;
148 }
149
150 QString DbMediaImageContainer::constructFilterById(int id) const
151 {
152     return QString("file.id = %1").arg(id);
153 }
154
155 QString DbMediaImageContainer::constructSelectById(int id) const
156 {
157     return constructSelect(
158         QString("WHERE %1").arg(constructFilterById(id))
159         );
160 }
161
162 EmuFrontObject* DbMediaImageContainer::recordToDataObject(const QSqlRecord *rec)
163 {
164     // TODO: checks!
165     MediaImageContainer *mic = 0;
166     if (!rec) return mic;
167     int id = rec->value(MIC_FileId).toInt();
168     QString name = rec->value(MIC_FileName).toString();
169     QString checksum = rec->value(MIC_FileCheckSum).toString();
170     int size = rec->value(MIC_FileSize).toInt();
171     int fpId = rec->value(MIC_FilePathId).toInt();
172     FilePathObject *fpo
173         = dynamic_cast<FilePathObject*>(dbFilePath->getDataObject(fpId));
174     //int supId = rec->value(MIC_SetupId).toInt();
175     //Setup *sup = dbSetup->getDataObject(supId)
176     QList<MediaImage*> images = dbMediaImage->getMediaImages(id);
177
178     mic = new MediaImageContainer(
179        id, name, checksum, size, images, fpo
180     );
181     return mic;
182 }
183
184 QSqlQueryModel* DbMediaImageContainer::getData()
185 {
186     QSqlQueryModel *model = new QSqlQueryModel(this);
187     if (sqlTableModel){
188         model->setQuery(sqlTableModel->query());
189     }
190     else
191         model->setQuery(constructSelect());
192     model->setHeaderData(MIC_FileId, Qt::Horizontal, tr("File id"));
193     model->setHeaderData(MIC_FileName, Qt::Horizontal, tr("File Name"));
194     model->setHeaderData(MIC_FileCheckSum, Qt::Horizontal, tr("File checksum"));
195     model->setHeaderData(MIC_FileSize, Qt::Horizontal, tr("File Size"));
196     model->setHeaderData(MIC_FilePathId, Qt::Horizontal, tr("File path id"));
197     model->setHeaderData(MIC_FilePathName, Qt::Horizontal, tr("File path name"));
198     model->setHeaderData(MIC_SetupId, Qt::Horizontal, tr("Setup id"));
199     model->setHeaderData(MIC_PlatformId, Qt::Horizontal, tr("Platform id"));
200     model->setHeaderData(MIC_PlatformName, Qt::Horizontal, tr("Platform name"));
201     model->setHeaderData(MIC_MediaTypeId, Qt::Horizontal, tr("Media type id"));
202     model->setHeaderData(MIC_MediaTypeName, Qt::Horizontal, tr("Media type name"));
203     return model;
204 }
205
206 /* Returns the id of a media image container with a given cheksum or -1 if not found */
207 int DbMediaImageContainer::getMediaImageContainer(QString checksum) const
208 {
209     QSqlQuery q;
210     q.prepare("SELECT id FROM file WHERE checksum=:checksum");
211     q.bindValue(":checksum", checksum);
212     int id = -1;
213     if (q.next())
214         id = q.value(0).toInt();
215     return id;
216 }
217
218
219 /**
220 * Stores media image containers, including the media images included
221 * to database.
222 */
223 void DbMediaImageContainer::storeContainers(QList<MediaImageContainer *> lst, FilePathObject *fpo)
224 {
225     qDebug() << "Storing media image containers to database.";
226     foreach(MediaImageContainer *mic, lst)
227     {
228         qDebug() << "Media image container " << mic->getName();
229         int micFileId = insertDataObjectToModel(mic);
230     }
231 }
232
233 void DbMediaImageContainer::linkMediaImagesWithContainer(int micId, QList<int> miIds)
234 {
235     if (micId < 0 || miIds.count() <= 0)
236         return;
237
238     QSqlQuery q;
239     q.prepare("INSERT INTO mediaimagecontainer_mediaimage "
240         "(mediaimagecontainerid, mediaimageid) "
241         "VALUES (:micid, :miid) ");
242     q.bindValue(":micid", micId);
243
244     foreach(int miid, miIds) {
245         qDebug() << "Linking media image container " << micId << " to media image " << miid  << ".";
246         q.bindValue(":miid", miid);
247         if (!q.exec()) {
248             throw new EmuFrontException(QString("Failed linking media "
249                 "image container %1 to a media image %2").arg(micId).arg(miid));
250         }
251     }
252 }
253
254 void DbMediaImageContainer::filter(int mediaTypeId, int platformId)
255 {
256     qDebug() << "Filtering media images with media type " << mediaTypeId
257         << " and platform " << platformId;
258     QList<QString> filters;
259     if (mediaTypeId >= 0)
260         filters.append(QString("mediatype.id=%1").arg(mediaTypeId));
261     if (platformId >= 0)
262         filters.append(QString("platform.id=%1").arg(platformId));
263     filterDataObjects(filters);
264 }
265