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"
31 DbMediaImageContainer::DbMediaImageContainer(QObject *parent)
32 : DbFile(parent) // DbQueryModelManager(parent)
34 dbMediaImage = new DbMediaImage(parent);
35 dbFilePath = new DbFilePath(parent);
36 tableName = DbMediaImageContainer::DB_TABLE_MEDIAIMAGECONTAINER;
37 //dbFile = new DbFile(parent);
40 bool DbMediaImageContainer::updateDataObjectToModel(const EmuFrontObject *efo)
47 int DbMediaImageContainer::storeMediaImageContainer(EmuFrontObject *efo)
49 MediaImageContainer *mic
50 = dynamic_cast<MediaImageContainer *>(efo);
52 if (!mic->getFilePath())
53 throw new EmuFrontException("Cannot install media image "
54 "container to database without a file path object!");
56 // check if this media image container is already in the database
58 // multiple media image containers with matching checksum will be stored
59 // if each instance is in a different file path
61 EmuFrontObject *o = getMediaImageContainerByChecksum(mic->getCheckSum());
62 int fileId = o ? o->getId() : -1;
64 qDebug() << "Media image container already in db with id " << fileId << ".";
65 // ok, we have a matching file
66 MediaImageContainer *tmpMic = dynamic_cast<MediaImageContainer*>(o);
67 // this will test if media image container is already in given path (media image container has a path spesific name!)
68 QString name = getMediaImageContainerName(mic->getFilePath()->getId(), mic->getId());
70 // if file path differs, link the existing media image container to this file path with mic->getName() name
71 linkMediaImageContainerToPath(mic);
73 else if (name != mic->getName()) {
74 // if the file path is same but the file name differs update the mediaimagecontainer_filepath table entry
75 updateMediaImageContainerToPath(mic);
81 QMap<QString, EmuFrontObject*> images = mic->getMediaImages();
82 QList<int> ids = dbMediaImage->storeMediaImages(images);
84 qDebug() << "Stored " << ids.count() << " media images.";
89 /* Contained Media images successfully stored to db,
90 storing media image container also */
94 // Insert MediaImageContainer first as a EmuFrontFile object to file table.
96 // File id is used to store the media image container instance to database,
97 // file id is also the media image container id
99 fileId = insertDataObjectToModel(mic);
101 qDebug() << "Inserted media image container to file table with id " << fileId << ".";
104 // TODO: note we most surely need to catch the exception
105 // in the calling code block and clean
106 // all the media image and ...containers from
108 throw new EmuFrontException(
109 QString(tr("Inserting media image container %1 to file database failed"))
110 .arg(mic->getName()));
115 if (!linkMediaImageContainerToPath(mic)){
116 DbFile::deleteDataObject(fileId);
117 throw new EmuFrontException("Failed inserting media image to database!");
119 qDebug() << "Inserted media image container " << fileId << " to mediaimagecontainer table.";
120 linkMediaImagesWithContainer(fileId, images.values());
121 qDebug() << "Linked media image container with media images.";
122 } catch (EmuFrontException e) {
123 dbMediaImage->removeOrphanedMediaImages(ids);
130 bool DbMediaImageContainer::deleteDataObjectFromModel(QModelIndex *i)
136 QString DbMediaImageContainer::constructSelect(QString whereClause) const
138 // TODO, for a usual search we need a "light" version of this select
139 // and MediaImageContainer (only id, name)
140 QString select = QString("SELECT file.id, mediaimagecontainer_filepath.mediaimagecontainername, file.checksum, file.size, "
141 " filepath.id, filepath.name, "
143 " platform.id, platform.name, "
144 " mediatype.id, mediatype.name "
146 "INNER JOIN mediaimagecontainer_filepath ON mediaimagecontainer_filepath.fileid = file.id "
147 "INNER JOIN filepath ON mediaimagecontainer_filepath.filepathid = filepath.id "
148 "INNER JOIN setup ON filepath.setupid = setup.id "
149 "INNER JOIN platform ON setup.platformid = platform.id "
150 "INNER JOIN mediatype ON setup.mediatypeid = mediatype.id "
152 "ORDER BY file.name").arg(whereClause);
157 QString DbMediaImageContainer::constructFilterById(int id) const
159 return QString("file.id = %1").arg(id);
162 QString DbMediaImageContainer::constructSelectById(int id) const
164 return constructSelect(
165 QString("WHERE %1").arg(constructFilterById(id))
169 EmuFrontObject* DbMediaImageContainer::recordToDataObject(const QSqlRecord *rec)
172 MediaImageContainer *mic = 0;
173 if (!rec) return mic;
174 int id = rec->value(MIC_FileId).toInt();
175 QString name = rec->value(MIC_FileName).toString();
176 QString checksum = rec->value(MIC_FileCheckSum).toString();
177 int size = rec->value(MIC_FileSize).toInt();
178 int fpId = rec->value(MIC_FilePathId).toInt();
180 = dynamic_cast<FilePathObject*>(dbFilePath->getDataObject(fpId));
181 //int supId = rec->value(MIC_SetupId).toInt();
182 //Setup *sup = dbSetup->getDataObject(supId)
183 QMap<QString, EmuFrontObject*> images = dbMediaImage->getMediaImages(id);
185 mic = new MediaImageContainer(
186 id, name, checksum, size, images, fpo
191 QSqlQueryModel* DbMediaImageContainer::getData()
193 QSqlQueryModel *model = new QSqlQueryModel(this);
195 model->setQuery(sqlTableModel->query());
198 model->setQuery(constructSelect());
199 model->setHeaderData(MIC_FileId, Qt::Horizontal, tr("File id"));
200 model->setHeaderData(MIC_FileName, Qt::Horizontal, tr("File Name"));
201 model->setHeaderData(MIC_FileCheckSum, Qt::Horizontal, tr("File checksum"));
202 model->setHeaderData(MIC_FileSize, Qt::Horizontal, tr("File Size"));
203 model->setHeaderData(MIC_FilePathId, Qt::Horizontal, tr("File path id"));
204 model->setHeaderData(MIC_FilePathName, Qt::Horizontal, tr("File path name"));
205 model->setHeaderData(MIC_SetupId, Qt::Horizontal, tr("Setup id"));
206 model->setHeaderData(MIC_PlatformId, Qt::Horizontal, tr("Platform id"));
207 model->setHeaderData(MIC_PlatformName, Qt::Horizontal, tr("Platform name"));
208 model->setHeaderData(MIC_MediaTypeId, Qt::Horizontal, tr("Media type id"));
209 model->setHeaderData(MIC_MediaTypeName, Qt::Horizontal, tr("Media type name"));
213 /* Returns the id of a media image container with a given cheksum or -1 if not found */
214 int DbMediaImageContainer::getMediaImageContainer(QString checksum) const
217 q.prepare("SELECT id FROM file WHERE checksum=:checksum");
218 q.bindValue(":checksum", checksum);
221 id = q.value(0).toInt();
227 * Stores media image containers, including the media images included
230 void DbMediaImageContainer::storeContainers(QList<MediaImageContainer *> lst, FilePathObject *fpo)
232 qDebug() << "Storing media image containers to database.";
233 foreach(MediaImageContainer *mic, lst)
235 qDebug() << "Media image container " << mic->getName();
236 int micFileId = storeMediaImageContainer(mic);
240 void DbMediaImageContainer::linkMediaImagesWithContainer(int micId, QList<EmuFrontObject*> mediaImages)
242 if (micId < 0 || mediaImages.count() <= 0)
246 foreach(EmuFrontObject *efo, mediaImages) {
247 mi = dynamic_cast<MediaImage*>(efo);
248 qDebug() << "Linking media image container " << micId
249 << " to media image " << mi->getId() << ", " << mi->getName() << ".";
250 QString name = getMediaImageContainerName(micId, mi->getId());
251 if (name.isEmpty() && !linkMediaImageToMediaImageContainer(mi, micId)) {
252 throw new EmuFrontException(QString("Failed linking media "
253 "image container %1 to a media image %2").arg(micId).arg(mi->getId()));
255 else if (name != mi->getName() && !updateMediaImageToMediaImageContainer(mi, micId)) {
256 throw new EmuFrontException(QString("Failed updating media "
257 "image container %1 to a media image %2").arg(micId).arg(mi->getId()));
259 // else already linked and name is up to date.
263 void DbMediaImageContainer::filter(int mediaTypeId, int platformId)
265 qDebug() << "Filtering media images with media type " << mediaTypeId
266 << " and platform " << platformId;
267 QList<QString> filters;
268 if (mediaTypeId >= 0)
269 filters.append(QString("mediatype.id=%1").arg(mediaTypeId));
271 filters.append(QString("platform.id=%1").arg(platformId));
272 filterDataObjects(filters);
275 QString DbMediaImageContainer::getCountRefsSelect(int id) const
277 /* we need to count file references to give media image container */
279 select count(*) from mediaimagecontainer
280 INNER JOIN mediaimagecontainer_mediaimage
281 ON mediaimagecontainer_mediaimage.mediaimagecontainerid
282 = mediaimagecontainer.fileid
283 WHERE mediaimagecontainer.fileid=589;
285 return QString("SELECT count(*) FROM mediaimagecontainer "
286 "INNER JOIN mediaimagecontainer_mediaimage "
287 "ON mediaimagecontainer_mediaimage.mediaimagecontainerid "
288 " =mediaimagecontainer.fileid "
289 "WHERE mediaimagecontainer.fileid=%1").arg(id);
292 QString DbMediaImageContainer::getDeleteObjectSql() const
294 // The trigger will take care of deleting
295 // the reference from the mediaimagecontainer
296 // and mediaimage_mediaimagecontainer tables.
297 // there is also a trigger that will delete
298 // all the files linked to mediaimagecontainer
299 // using mediaimage_mediaimagecontainer (the actual
301 return QString("DELETE FROM file WHERE id=:id");
304 EmuFrontObject* DbMediaImageContainer::getMediaImageContainerByChecksum(QString checksum)
306 return getDataObject(QString("file.checksum LIKE '%1'").arg(checksum));
309 bool DbMediaImageContainer::linkMediaImageContainerToPath(const MediaImageContainer *mic) const
312 q.prepare("INSERT INTO mediaimagecontainer_filepath "
313 "(fileid, filepathid, mediaimagecontainername, updatetime) "
314 "VALUES (:fileid, :filepathid, :mediaimagecontainername, :updatetime)");
315 q.bindValue(":fileid", mic->getId());
316 q.bindValue(":filepathid", mic->getFilePath()->getId());
317 q.bindValue(":mediaimagecontainername", mic->getName());
318 q.bindValue(":updatetime", DatabaseManager::getCurrentTimeStamp());
322 bool DbMediaImageContainer::updateMediaImageContainerToPath(const MediaImageContainer *mic) const
325 q.prepare("UPDATE mediaimagecontainer_filepath "
326 "SET mediaimagecontainername=:mediaimagecontainername, "
327 "updatetime=:updatetime "
328 "WHERE fileid=:fileid AND filepathid=:filepathid");
329 q.bindValue(":fileid", mic->getId());
330 q.bindValue(":filepathid", mic->getFilePath()->getId());
331 q.bindValue(":mediaimagecontainername", mic->getName());
332 q.bindValue(":updatetime", DatabaseManager::getCurrentTimeStamp());
336 QString DbMediaImageContainer::getMediaImageContainerName(int filePathId, int micId) const
340 q.prepare("SELECT mediaimagecontainername FROM mediaimagecontainer_filepath "
341 "WHERE fileid=:fileid AND filepathid=:filepathid");
342 q.bindValue(":fileid", micId);
343 q.bindValue(":filepathid", filePathId);
346 name = q.value(0).toString();
350 bool DbMediaImageContainer::linkMediaImageToMediaImageContainer(const MediaImage *mi, int micId) const
353 q.prepare("INSERT INTO mediaimagecontainer_mediaimage "
354 "(mediaimagecontainerid, mediaimageid, mediaimagename) "
355 "VALUES (:micid, :miid, :miname) ");
356 q.bindValue(":micid", micId);
357 q.bindValue(":miid", mi->getId());
358 q.bindValue(":miname", mi->getName());
362 bool DbMediaImageContainer::updateMediaImageToMediaImageContainer(const MediaImage *mi, int micId) const
365 q.prepare("UPDATE mediaimagecontainer_mediaimage "
366 " SET mediaimagename=:miname "
367 " WHERE mediaimagecontainerid=:micid AND mediaimageid=:miid");
368 q.bindValue(":micid", micId);
369 q.bindValue(":miid", mi->getId());
370 q.bindValue(":miname", mi->getName());