Updated the git clone command.
[emufront] / src / models / mediaimagecontainermodel.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 "mediaimagecontainer.h"
23 #include "mediaimagecontainermodel.h"
24 #include "filepathmodel.h"
25 #include "mediaimagemodel.h"
26 #include "emufrontexception.h"
27 #include <QtSql>
28
29 MediaImageContainerModel::MediaImageContainerModel(QObject *parent) :
30     FileModel(parent)
31 {
32 }
33
34 QString MediaImageContainerModel::constructSelect(QString where) const
35 {
36     // TODO, for a usual search need a "light" version of this select
37     // and MediaImageContainer (only id, name)
38     return QString(
39         "SELECT file.id, file.name, file.checksum, file.size, "
40         "        filepath.id, filepath.name, "
41         "        setup.id, "
42         "        platform.id, platform.name, "
43         "        mediatype.id, mediatype.name "
44         "FROM file "
45         "INNER JOIN mediaimagecontainer_filepath ON mediaimagecontainer_filepath.fileid = file.id "
46         "INNER JOIN filepath ON mediaimagecontainer_filepath.filepathid = filepath.id "
47         "INNER JOIN setup ON filepath.setupid = setup.id "
48         "INNER JOIN platform ON setup.platformid = platform.id "
49         "INNER JOIN mediatype ON setup.mediatypeid = mediatype.id "
50         "%1 "
51         "ORDER BY file.name"
52     ).arg(where);
53 }
54
55 QString MediaImageContainerModel::constructFilterById(int id) const
56 {
57     return QString("file.id = %1").arg(id);
58 }
59
60 void MediaImageContainerModel::refresh()
61 {
62     //setQuery(constructSelect());
63     setHeaderData(MIC_FileId, Qt::Horizontal, tr("File id"));
64     setHeaderData(MIC_FileName, Qt::Horizontal, tr("File Name"));
65     setHeaderData(MIC_FileCheckSum, Qt::Horizontal, tr("File checksum"));
66     setHeaderData(MIC_FileSize, Qt::Horizontal, tr("File Size"));
67     setHeaderData(MIC_FilePathId, Qt::Horizontal, tr("File path id"));
68     setHeaderData(MIC_FilePathName, Qt::Horizontal, tr("File path name"));
69     setHeaderData(MIC_SetupId, Qt::Horizontal, tr("Setup id"));
70     setHeaderData(MIC_PlatformId, Qt::Horizontal, tr("Platform id"));
71     setHeaderData(MIC_PlatformName, Qt::Horizontal, tr("Platform name"));
72     setHeaderData(MIC_MediaTypeId, Qt::Horizontal, tr("Media type id"));
73     setHeaderData(MIC_MediaTypeName, Qt::Horizontal, tr("Media type name"));
74 }
75
76 EmuFrontObject* MediaImageContainerModel::recordToDataObject(const QSqlRecord *rec)
77 {
78     // TODO: checks!
79     MediaImageContainer *mic = 0;
80     if (!rec) return mic;
81     int id = rec->value(MIC_FileId).toInt();
82     QString name = rec->value(MIC_FileName).toString();
83     QString checksum = rec->value(MIC_FileCheckSum).toString();
84     int size = rec->value(MIC_FileSize).toInt();
85     int fpId = rec->value(MIC_FilePathId).toInt();
86     FilePathModel fpModel;
87     EmuFrontObject *efo = fpModel.getDataObject(fpId);
88     FilePathObject *fpo = dynamic_cast<FilePathObject*>(efo);
89     if (!fpo) return 0;
90     //int supId = rec->value(MIC_SetupId).toInt();
91     //Setup *sup = dbSetup->getDataObject(supId)
92     MediaImageModel miModel;
93     QMap<QString, EmuFrontObject*> images = miModel.getMediaImages(id);
94     mic = new MediaImageContainer(
95        id, name, checksum, size, images, fpo
96     );
97     return mic;
98 }
99
100 void MediaImageContainerModel::filterBySetup(int setupId)
101 {
102     QList<QString> filters;
103     filters.append(QString("setup.id = %1").arg(setupId));
104     filterDataObjects(filters);
105 }
106
107 bool MediaImageContainerModel::removeFromFilePath(int filePathId) const
108 {
109     QSqlQuery q;
110     q.prepare("DELETE FROM mediaimagecontainer_filepath "
111         "WHERE filepathid=:filepathid");
112     q.bindValue(":filepathid", filePathId);
113     return q.exec();
114 }
115
116 void MediaImageContainerModel::storeContainers(QList<MediaImageContainer *> lst, FilePathObject *fpo)
117 {
118     foreach(MediaImageContainer *mic, lst) {
119         int micFileId = storeMediaImageContainer(mic);
120     }
121 }
122
123 int MediaImageContainerModel::storeMediaImageContainer(EmuFrontObject *efo)
124 {
125     MediaImageContainer *mic
126         = dynamic_cast<MediaImageContainer *>(efo);
127
128     if (!mic->getFilePath())
129         throw EmuFrontException("Cannot install media image "
130             "container to database without a file path object!");
131
132     // multiple media image containers with matching checksum will be stored
133     //       if each instance is in a different file path
134
135     int fileId = -1;
136     QMap<QString, EmuFrontObject*> images = mic->getMediaImages();
137     MediaImageModel miModel;
138     QList<int> ids = miModel.storeMediaImages(images);
139
140     //qDebug() << "Stored " << ids.count() << " media images.";
141
142     if (ids.count() <= 0)
143         return -1;
144
145     /* Contained Media images successfully stored to db,
146         storing media image container also */
147
148     try {
149
150         // Insert MediaImageContainer first as a EmuFrontFile object to file table.
151
152         // File id is used to store the media image container instance to database,
153         // file id is also the media image container id
154
155         // TODO: if this fails, the remove the media images in ids
156         fileId = insertDataObject(mic);
157
158         //qDebug() << "Inserted media image container to file table with id " << fileId << ".";
159
160         if (fileId < 0) {
161             // TODO: note we most surely need to catch the exception
162             // in the calling code block and clean
163             // all the media image and ...containers from
164             // the memory!
165             throw EmuFrontException(
166                     QString(tr("Inserting media image container %1 to file database failed"))
167                     .arg(mic->getName()));
168         }
169
170         mic->setId(fileId);
171
172         if (!linkMediaImageContainerToPath(mic)){
173             deleteDataObject(fileId);
174             throw EmuFrontException("Failed inserting media image to database!");
175         }
176         //qDebug() << "Inserted media image container " << fileId << " to mediaimagecontainer table.";
177         linkMediaImagesWithContainer(fileId, images.values());
178         //qDebug() << "Linked media image container with media images.";
179     } catch (EmuFrontException e) {
180         miModel.removeOrphanedMediaImages(ids);
181         throw e;
182     }
183
184     return fileId;
185 }
186
187 /* Throws EmuFrontException */
188 void MediaImageContainerModel::linkMediaImagesWithContainer(int micId, QList<EmuFrontObject*> mediaImages)
189 {
190     if (micId < 0 || mediaImages.count() <= 0)
191         return;
192
193     MediaImage *mi = 0;
194     foreach(EmuFrontObject *efo, mediaImages) {
195         mi = dynamic_cast<MediaImage*>(efo);
196         /*qDebug() << "Linking media image container " << micId
197             << " to media image " << mi->getId()  << ", " << mi->getName() << ".";*/
198         if (!linkMediaImageToMediaImageContainer(mi, micId)) {
199                 throw EmuFrontException(QString("Failed linking media "
200                                                     "image container %1 to a media image %2").arg(micId).arg(mi->getId()));
201         }
202     }
203 }
204
205 bool MediaImageContainerModel::linkMediaImageContainerToPath(const MediaImageContainer *mic) const
206 {
207     QSqlQuery q;
208     q.prepare("INSERT INTO mediaimagecontainer_filepath "
209               "(fileid, filepathid, updatetime) "
210               "VALUES (:fileid, :filepathid, :updatetime)");
211     q.bindValue(":fileid", mic->getId());
212     q.bindValue(":filepathid", mic->getFilePath()->getId());
213     q.bindValue(":updatetime", getCurrentTimeStamp());
214     return q.exec();
215 }
216
217 bool MediaImageContainerModel::linkMediaImageToMediaImageContainer(const MediaImage *mi, int micId) const
218 {
219     QSqlQuery q;
220     q.prepare("INSERT INTO mediaimagecontainer_mediaimage "
221         "(mediaimagecontainerid, mediaimageid) "
222         "VALUES (:micid, :miid) ");
223     q.bindValue(":micid", micId);
224     q.bindValue(":miid", mi->getId());
225     return q.exec();
226 }
227