2 // Copyright 2010 Mikko Keinänen
4 // This file is part of EmuFront.
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.
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.
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/>.
23 #include <QSqlRelationalTableModel>
25 #include "dbmediaimagecontainer.h"
26 #include "dbmediaimage.h"
27 //#include "dbsetup.h"
28 #include "dbfilepath.h"
30 DbMediaImageContainer::DbMediaImageContainer(QObject *parent)
31 : DbFile(parent) // DbQueryModelManager(parent)
33 dbMediaImage = new DbMediaImage(parent);
34 dbFilePath = new DbFilePath(parent);
35 tableName = DbMediaImageContainer::DB_TABLE_MEDIAIMAGECONTAINER;
36 //dbFile = new DbFile(parent);
39 bool DbMediaImageContainer::updateDataObjectToModel(const EmuFrontObject *efo)
46 int DbMediaImageContainer::storeMediaImageContainer(EmuFrontObject *efo)
48 MediaImageContainer *mic
49 = dynamic_cast<MediaImageContainer *>(efo);
51 if (!mic->getFilePath())
52 throw new EmuFrontException("Cannot install media image "
53 "container to database without a file path object!");
55 // check if this media image container is already in the database
57 // multiple media image containers with matching checksum will be stored
58 // if each instance is in a different file path
60 EmuFrontObject *o = getMediaImageContainerByChecksum(mic->getCheckSum());
61 int fileId = o ? o->getId() : -1;
63 qDebug() << "Media image container already in db with id " << fileId << ".";
64 // ok, we have a matching file
65 MediaImageContainer *tmpMic = dynamic_cast<MediaImageContainer*>(o);
66 // this will test if media image container is already in given path (media image container has a path spesific name!)
67 QString name = getMediaImageContainerName(mic->getFilePath()->getId(), mic->getId());
69 // if file path differs, link the existing media image container to this file path with mic->getName() name
70 linkMediaImageContainerToPath(mic);
72 else if (name != mic->getName()) {
73 // if the file path is same but the file name differs update the mediaimagecontainer_filepath table entry
74 updateMediaImageContainerToPath(mic);
80 QMap<QString, EmuFrontObject*> images = mic->getMediaImages();
81 QList<int> ids = dbMediaImage->storeMediaImages(images);
83 qDebug() << "Stored " << ids.count() << " media images.";
88 /* Contained Media images successfully stored to db,
89 storing media image container also */
93 // Insert MediaImageContainer first as a EmuFrontFile object to file table.
95 // File id is used to store the media image container instance to database,
96 // file id is also the media image container id
98 fileId = insertDataObjectToModel(mic);
100 qDebug() << "Inserted media image container to file table with id " << fileId << ".";
103 // TODO: note we most surely need to catch the exception
104 // in the calling code block and clean
105 // all the media image and ...containers from
107 throw new EmuFrontException(
108 QString(tr("Inserting media image container %1 to file database failed"))
109 .arg(mic->getName()));
114 if (!linkMediaImageContainerToPath(mic)){
115 DbFile::deleteDataObject(fileId);
116 throw new EmuFrontException("Failed inserting media image to database!");
118 qDebug() << "Inserted media image container " << fileId << " to mediaimagecontainer table.";
119 linkMediaImagesWithContainer(fileId, images.values());
120 qDebug() << "Linked media image container with media images.";
121 } catch (EmuFrontException e) {
122 dbMediaImage->removeOrphanedMediaImages(ids);
129 bool DbMediaImageContainer::deleteDataObjectFromModel(QModelIndex *i)
135 QString DbMediaImageContainer::constructSelect(QString whereClause) const
137 // TODO, for a usual search we need a "light" version of this select
138 // and MediaImageContainer (only id, name)
139 QString select = QString("SELECT file.id, mediaimagecontainer_filepath.mediaimagecontainername, file.checksum, file.size, "
140 " filepath.id, filepath.name, "
142 " platform.id, platform.name, "
143 " mediatype.id, mediatype.name "
145 "INNER JOIN mediaimagecontainer_filepath ON mediaimagecontainer_filepath.fileid = file.id "
146 "INNER JOIN filepath ON mediaimagecontainer_filepath.filepathid = filepath.id "
147 "INNER JOIN setup ON filepath.setupid = setup.id "
148 "INNER JOIN platform ON setup.platformid = platform.id "
149 "INNER JOIN mediatype ON setup.mediatypeid = mediatype.id "
151 "ORDER BY file.name").arg(whereClause);
156 QString DbMediaImageContainer::constructFilterById(int id) const
158 return QString("file.id = %1").arg(id);
161 QString DbMediaImageContainer::constructSelectById(int id) const
163 return constructSelect(
164 QString("WHERE %1").arg(constructFilterById(id))
168 EmuFrontObject* DbMediaImageContainer::recordToDataObject(const QSqlRecord *rec)
171 MediaImageContainer *mic = 0;
172 if (!rec) return mic;
173 int id = rec->value(MIC_FileId).toInt();
174 QString name = rec->value(MIC_FileName).toString();
175 QString checksum = rec->value(MIC_FileCheckSum).toString();
176 int size = rec->value(MIC_FileSize).toInt();
177 int fpId = rec->value(MIC_FilePathId).toInt();
179 = dynamic_cast<FilePathObject*>(dbFilePath->getDataObject(fpId));
180 //int supId = rec->value(MIC_SetupId).toInt();
181 //Setup *sup = dbSetup->getDataObject(supId)
182 QMap<QString, EmuFrontObject*> images = dbMediaImage->getMediaImages(id);
184 mic = new MediaImageContainer(
185 id, name, checksum, size, images, fpo
190 QSqlQueryModel* DbMediaImageContainer::getData()
192 QSqlQueryModel *model = new QSqlQueryModel(this);
194 model->setQuery(sqlTableModel->query());
197 model->setQuery(constructSelect());
198 model->setHeaderData(MIC_FileId, Qt::Horizontal, tr("File id"));
199 model->setHeaderData(MIC_FileName, Qt::Horizontal, tr("File Name"));
200 model->setHeaderData(MIC_FileCheckSum, Qt::Horizontal, tr("File checksum"));
201 model->setHeaderData(MIC_FileSize, Qt::Horizontal, tr("File Size"));
202 model->setHeaderData(MIC_FilePathId, Qt::Horizontal, tr("File path id"));
203 model->setHeaderData(MIC_FilePathName, Qt::Horizontal, tr("File path name"));
204 model->setHeaderData(MIC_SetupId, Qt::Horizontal, tr("Setup id"));
205 model->setHeaderData(MIC_PlatformId, Qt::Horizontal, tr("Platform id"));
206 model->setHeaderData(MIC_PlatformName, Qt::Horizontal, tr("Platform name"));
207 model->setHeaderData(MIC_MediaTypeId, Qt::Horizontal, tr("Media type id"));
208 model->setHeaderData(MIC_MediaTypeName, Qt::Horizontal, tr("Media type name"));
212 /* Returns the id of a media image container with a given cheksum or -1 if not found */
213 int DbMediaImageContainer::getMediaImageContainer(QString checksum) const
216 q.prepare("SELECT id FROM file WHERE checksum=:checksum");
217 q.bindValue(":checksum", checksum);
220 id = q.value(0).toInt();
226 * Stores media image containers, including the media images included
229 void DbMediaImageContainer::storeContainers(QList<MediaImageContainer *> lst, FilePathObject *fpo)
231 qDebug() << "Storing media image containers to database.";
232 foreach(MediaImageContainer *mic, lst)
234 qDebug() << "Media image container " << mic->getName();
235 int micFileId = storeMediaImageContainer(mic);
239 void DbMediaImageContainer::linkMediaImagesWithContainer(int micId, QList<EmuFrontObject*> mediaImages)
241 if (micId < 0 || mediaImages.count() <= 0)
245 foreach(EmuFrontObject *efo, mediaImages) {
246 mi = dynamic_cast<MediaImage*>(efo);
247 qDebug() << "Linking media image container " << micId
248 << " to media image " << mi->getId() << ", " << mi->getName() << ".";
249 QString name = getMediaImageContainerName(micId, mi->getId());
250 if (name.isEmpty() && !linkMediaImageToMediaImageContainer(mi, micId)) {
251 throw new EmuFrontException(QString("Failed linking media "
252 "image container %1 to a media image %2").arg(micId).arg(mi->getId()));
254 else if (name != mi->getName() && !updateMediaImageToMediaImageContainer(mi, micId)) {
255 throw new EmuFrontException(QString("Failed updating media "
256 "image container %1 to a media image %2").arg(micId).arg(mi->getId()));
258 // else already linked and name is up to date.
262 void DbMediaImageContainer::filter(int mediaTypeId, int platformId)
264 qDebug() << "Filtering media images with media type " << mediaTypeId
265 << " and platform " << platformId;
266 QList<QString> filters;
267 if (mediaTypeId >= 0)
268 filters.append(QString("mediatype.id=%1").arg(mediaTypeId));
270 filters.append(QString("platform.id=%1").arg(platformId));
271 filterDataObjects(filters);
274 QString DbMediaImageContainer::getCountRefsSelect(int id) const
276 /* we need to count file references to give media image container */
278 select count(*) from mediaimagecontainer
279 INNER JOIN mediaimagecontainer_mediaimage
280 ON mediaimagecontainer_mediaimage.mediaimagecontainerid
281 = mediaimagecontainer.fileid
282 WHERE mediaimagecontainer.fileid=589;
284 return QString("SELECT count(*) FROM mediaimagecontainer "
285 "INNER JOIN mediaimagecontainer_mediaimage "
286 "ON mediaimagecontainer_mediaimage.mediaimagecontainerid "
287 " =mediaimagecontainer.fileid "
288 "WHERE mediaimagecontainer.fileid=%1").arg(id);
291 QString DbMediaImageContainer::getDeleteObjectSql() const
293 // The trigger will take care of deleting
294 // the reference from the mediaimagecontainer
295 // and mediaimage_mediaimagecontainer tables.
296 // there is also a trigger that will delete
297 // all the files linked to mediaimagecontainer
298 // using mediaimage_mediaimagecontainer (the actual
300 return QString("DELETE FROM file WHERE id=:id");
303 EmuFrontObject* DbMediaImageContainer::getMediaImageContainerByChecksum(QString checksum)
305 return getDataObject(QString("file.checksum LIKE '%1'").arg(checksum));
308 bool DbMediaImageContainer::linkMediaImageContainerToPath(const MediaImageContainer *mic) const
311 q.prepare("INSERT INTO mediaimagecontainer_filepath "
312 "(fileid, filepathid, mediaimagecontainername, updatetime) "
313 "VALUES (:fileid, :filepathid, :mediaimagecontainername, :updatetime)");
314 q.bindValue(":fileid", mic->getId());
315 q.bindValue(":filepathid", mic->getFilePath()->getId());
316 q.bindValue(":mediaimagecontainername", mic->getName());
317 q.bindValue(":updatetime", DatabaseManager::getCurrentTimeStamp());
321 bool DbMediaImageContainer::updateMediaImageContainerToPath(const MediaImageContainer *mic) const
324 q.prepare("UPDATE mediaimagecontainer_filepath "
325 "SET mediaimagecontainername=:mediaimagecontainername, "
326 "updatetime=:updatetime "
327 "WHERE fileid=:fileid AND filepathid=:filepathid");
328 q.bindValue(":fileid", mic->getId());
329 q.bindValue(":filepathid", mic->getFilePath()->getId());
330 q.bindValue(":mediaimagecontainername", mic->getName());
331 q.bindValue(":updatetime", DatabaseManager::getCurrentTimeStamp());
335 QString DbMediaImageContainer::getMediaImageContainerName(int filePathId, int micId) const
339 q.prepare("SELECT mediaimagecontainername FROM mediaimagecontainer_filepath "
340 "WHERE fileid=:fileid AND filepathid=:filepathid");
341 q.bindValue(":fileid", micId);
342 q.bindValue(":filepathid", filePathId);
345 name = q.value(0).toString();
349 bool DbMediaImageContainer::linkMediaImageToMediaImageContainer(const MediaImage *mi, int micId) const
352 q.prepare("INSERT INTO mediaimagecontainer_mediaimage "
353 "(mediaimagecontainerid, mediaimageid, mediaimagename) "
354 "VALUES (:micid, :miid, :miname) ");
355 q.bindValue(":micid", micId);
356 q.bindValue(":miid", mi->getId());
357 q.bindValue(":miname", mi->getName());
361 bool DbMediaImageContainer::updateMediaImageToMediaImageContainer(const MediaImage *mi, int micId) const
364 q.prepare("UPDATE mediaimagecontainer_mediaimage "
365 " SET mediaimagename=:miname "
366 " WHERE mediaimagecontainerid=:micid AND mediaimageid=:miid");
367 q.bindValue(":micid", micId);
368 q.bindValue(":miid", mi->getId());
369 q.bindValue(":miname", mi->getName());