Lots of changes in the database model. Warning: only lightly tested for
authorMikko Keinänen <mikko.keinanen@gmail.com>
Fri, 22 Oct 2010 01:22:31 +0000 (04:22 +0300)
committerMikko Keinänen <mikko.keinanen@gmail.com>
Fri, 22 Oct 2010 01:22:31 +0000 (04:22 +0300)
the moment!

src/db/dbcreator.cpp
src/db/dbmediaimage.cpp
src/db/dbmediaimage.h
src/db/dbmediaimagecontainer.cpp
src/db/dbmediaimagecontainer.h
src/db/dbmultiinstancefile.cpp [new file with mode: 0644]
src/db/dbmultiinstancefile.h [new file with mode: 0644]
src/emufront.pro

index 825cd44..936601d 100644 (file)
@@ -118,10 +118,10 @@ bool DbCreator::createDB()
 
         qDebug() << "Creating TABLE mediaimagecontainer";
 
-        ret = query.exec("CREATE TABLE IF NOT EXISTS mediaimagecontainer " // mediaimagecontainer_filepath
+        ret = query.exec("CREATE TABLE IF NOT EXISTS mediaimagecontainer_filepath "
                         "(fileid INTEGER REFERENCES file(id), "
                         "filepathid INTEGER REFERENCES filepath(id), "
-                        // TODO: mediaimagecontainername -> filepath specific name for media image container!
+                        "mediaimagecontainername TEXT, " // filepath specific name for media image container
                         "updatetime NUMERIC)");
 
         if (!ret) throw QString("tbl mediaimagecontainer");
@@ -131,8 +131,9 @@ bool DbCreator::createDB()
 
         ret = query.exec("CREATE TABLE IF NOT EXISTS mediaimagecontainer_mediaimage "
                         "(mediaimagecontainerid INTEGER REFERENCES file(id), "
-                        // TODO: mediaimagename -> mediaimagecontainer specific name for media image!
-                        "mediaimageid INTEGER REFERENCES file(id))");
+                        "mediaimageid INTEGER REFERENCES file(id), "
+                        "mediaimagename TEXT " // mediaimagecontainer specific name for media image
+                        ")");
 
         if (!ret) throw QString("tbl mediaimagecontainer_mediaimage");
 
index 9a8fd1a..5d0443a 100644 (file)
@@ -35,15 +35,9 @@ DbMediaImage::DbMediaImage(QObject *parent)
 {
     // TODO
     return false;
-}
-
-bool DbMediaImage::insertDataObjectToModel(const EmuFrontObject *efo)
-{
-    // TODO
-    return false;
-}
+}*/
 
-bool DbMediaImage::deleteDataObjectFromModel(QModelIndex *i)
+/*bool DbMediaImage::deleteDataObjectFromModel(QModelIndex *i)
 {
     // TODO
     return false;
@@ -107,13 +101,11 @@ QList<int> DbMediaImage::storeMediaImages(QMap<QString, EmuFrontObject*> images)
         if (id >= 0)
         {
             qDebug() << "This media image already exists with id " << id;
+
+            // this media image is already stored to db
+            // we will append the id of this media image to the list of media images
+            // and we will link this media image to the container later
             delete o;
-            // this media image is already in the database
-            // TODO: what if the name differs? (cannot update to database, since the same media image
-            // might be inside another container...
-            // possible solution:
-            // * store media image names in different
-            //   table linked to the media image container
         }
         else if (id < 0)
         {
index 5486616..e0225c4 100644 (file)
@@ -32,7 +32,6 @@ public:
     void removeOrphanedMediaImages(QList<int> ids);
     QMap<QString, EmuFrontObject*> getMediaImages(int id) const;
     /*virtual bool updateDataObjectToModel(const EmuFrontObject *);
-    virtual bool insertDataObjectToModel(const EmuFrontObject *);
     virtual bool deleteDataObjectFromModel(QModelIndex *);
     int getMediaImage(QString checksum) const;
     int insertMediaImage(const MediaImage*);
index a141eac..cbe3821 100644 (file)
@@ -43,10 +43,11 @@ bool DbMediaImageContainer::updateDataObjectToModel(const EmuFrontObject *efo)
     return false;
 }
 
-int DbMediaImageContainer::insertDataObjectToModel(const EmuFrontObject *efo)
+
+int DbMediaImageContainer::storeMediaImageContainer(EmuFrontObject *efo)
 {
-    const MediaImageContainer *mic
-        = dynamic_cast<const MediaImageContainer *>(efo);
+    MediaImageContainer *mic
+        = dynamic_cast<MediaImageContainer *>(efo);
 
     if (!mic->getFilePath())
         throw new EmuFrontException("Cannot install media image "
@@ -54,18 +55,26 @@ int DbMediaImageContainer::insertDataObjectToModel(const EmuFrontObject *efo)
 
     // check if this media image container is already in the database
 
-    // Two possible solutions:
-    // * multiple media image containers with matching checksum will not be stored at all
-    //   (only the first instance will be stored)
-    // * multiple media image containers with matching checksum will be stored
-    //   if each instance is in a different file path
+    // multiple media image containers with matching checksum will be stored
+    //       if each instance is in a different file path
 
-    EmuFrontObject *o = getFileByChecksum(mic->getCheckSum());
+    EmuFrontObject *o = getMediaImageContainerByChecksum(mic->getCheckSum());
     int fileId = o ? o->getId() : -1;
     if (fileId >= 0) {
-        // ok, we have a matching file, we could still create a new media image instance to the database
         qDebug() << "Media image container already in db with id " << fileId << ".";
-        delete o;
+        // ok, we have a matching file
+        MediaImageContainer *tmpMic = dynamic_cast<MediaImageContainer*>(o);
+        // this will test if media image container is already in given path (media image container has a path spesific name!)
+        QString name = getMediaImageContainerName(mic->getFilePath()->getId(), mic->getId());
+        if (name.isEmpty()) {
+            // if file path differs, link the existing media image container to this file path with mic->getName() name
+            linkMediaImageContainerToPath(mic);
+        }
+        else if (name != mic->getName()) {
+            // if the file path is same but the file name differs update the mediaimagecontainer_filepath table entry
+            updateMediaImageContainerToPath(mic);
+        }
+        delete tmpMic;
         return fileId;
    }
 
@@ -86,7 +95,8 @@ int DbMediaImageContainer::insertDataObjectToModel(const EmuFrontObject *efo)
 
         // File id is used to store the media image container instance to database,
         // file id is also the media image container id
-        fileId = DbFile::insertDataObjectToModel(mic);
+
+        fileId = insertDataObjectToModel(mic);
 
         qDebug() << "Inserted media image container to file table with id " << fileId << ".";
 
@@ -100,21 +110,14 @@ int DbMediaImageContainer::insertDataObjectToModel(const EmuFrontObject *efo)
                     .arg(mic->getName()));
         }
 
-        // Insert to mediaimagecontainer table
+        mic->setId(fileId);
 
-        QSqlQuery q;
-        q.prepare("INSERT INTO mediaimagecontainer "
-                  "(fileid, filepathid, updatetime) "
-                  "VALUES (:fileid, :filepathid, :updatetime)");
-        q.bindValue(":fileid", fileId);
-        q.bindValue(":filepathid", mic->getFilePath()->getId());
-        q.bindValue(":updatetime", DatabaseManager::getCurrentTimeStamp());
-        if (!q.exec()){
+        if (!linkMediaImageContainerToPath(mic)){
             DbFile::deleteDataObject(fileId);
             throw new EmuFrontException("Failed inserting media image to database!");
         }
         qDebug() << "Inserted media image container " << fileId << " to mediaimagecontainer table.";
-        linkMediaImagesWithContainer(fileId, ids);
+        linkMediaImagesWithContainer(fileId, images.values());
         qDebug() << "Linked media image container with media images.";
     } catch (EmuFrontException e) {
         dbMediaImage->removeOrphanedMediaImages(ids);
@@ -134,14 +137,14 @@ QString DbMediaImageContainer::constructSelect(QString whereClause) const
 {
     // TODO, for a usual search we need a "light" version of this select
     // and MediaImageContainer (only id, name)
-    QString select = QString("SELECT file.id, file.name, file.checksum, file.size, "
+    QString select = QString("SELECT file.id, mediaimagecontainer_filepath.mediaimagecontainername, file.checksum, file.size, "
                 "        filepath.id, filepath.name, "
                 "        setup.id, "
                 "        platform.id, platform.name, "
                 "        mediatype.id, mediatype.name "
-                "FROM mediaimagecontainer "
-                "INNER JOIN file ON mediaimagecontainer.fileid = file.id "
-                "INNER JOIN filepath ON mediaimagecontainer.filepathid = filepath.id "
+                "FROM file "
+                "INNER JOIN mediaimagecontainer_filepath ON mediaimagecontainer_filepath.fileid = file.id "
+                "INNER JOIN filepath ON mediaimagecontainer_filepath.filepathid = filepath.id "
                 "INNER JOIN setup ON filepath.setupid = setup.id "
                 "INNER JOIN platform ON setup.platformid = platform.id "
                 "INNER JOIN mediatype ON setup.mediatypeid = mediatype.id "
@@ -230,28 +233,30 @@ void DbMediaImageContainer::storeContainers(QList<MediaImageContainer *> lst, Fi
     foreach(MediaImageContainer *mic, lst)
     {
         qDebug() << "Media image container " << mic->getName();
-        int micFileId = insertDataObjectToModel(mic);
+        int micFileId = storeMediaImageContainer(mic);
     }
 }
 
-void DbMediaImageContainer::linkMediaImagesWithContainer(int micId, QList<int> miIds)
+void DbMediaImageContainer::linkMediaImagesWithContainer(int micId, QList<EmuFrontObject*> mediaImages)
 {
-    if (micId < 0 || miIds.count() <= 0)
+    if (micId < 0 || mediaImages.count() <= 0)
         return;
 
-    QSqlQuery q;
-    q.prepare("INSERT INTO mediaimagecontainer_mediaimage "
-        "(mediaimagecontainerid, mediaimageid) "
-        "VALUES (:micid, :miid) ");
-    q.bindValue(":micid", micId);
-
-    foreach(int miid, miIds) {
-        qDebug() << "Linking media image container " << micId << " to media image " << miid  << ".";
-        q.bindValue(":miid", miid);
-        if (!q.exec()) {
-            throw new EmuFrontException(QString("Failed linking media "
-                "image container %1 to a media image %2").arg(micId).arg(miid));
+    MediaImage *mi = 0;
+    foreach(EmuFrontObject *efo, mediaImages) {
+        mi = dynamic_cast<MediaImage*>(efo);
+        qDebug() << "Linking media image container " << micId
+            << " to media image " << mi->getId()  << ", " << mi->getName() << ".";
+        QString name = getMediaImageContainerName(micId, mi->getId());
+        if (name.isEmpty() && !linkMediaImageToMediaImageContainer(mi, micId)) {
+                throw new EmuFrontException(QString("Failed linking media "
+                                                    "image container %1 to a media image %2").arg(micId).arg(mi->getId()));
+        }
+        else if (name != mi->getName() && !updateMediaImageToMediaImageContainer(mi, micId)) {
+                throw new EmuFrontException(QString("Failed updating media "
+                                                    "image container %1 to a media image %2").arg(micId).arg(mi->getId()));
         }
+        // else already linked and name is up to date.
     }
 }
 
@@ -295,3 +300,73 @@ QString DbMediaImageContainer::getDeleteObjectSql() const
        // mediaimages).
        return QString("DELETE FROM file WHERE id=:id");
 }
+
+EmuFrontObject* DbMediaImageContainer::getMediaImageContainerByChecksum(QString checksum)
+{
+    return getDataObject(QString("file.checksum LIKE '%1'").arg(checksum));
+}
+
+bool DbMediaImageContainer::linkMediaImageContainerToPath(const MediaImageContainer *mic) const
+{
+    QSqlQuery q;
+    q.prepare("INSERT INTO mediaimagecontainer_filepath "
+              "(fileid, filepathid, mediaimagecontainername, updatetime) "
+              "VALUES (:fileid, :filepathid, :mediaimagecontainername, :updatetime)");
+    q.bindValue(":fileid", mic->getId());
+    q.bindValue(":filepathid", mic->getFilePath()->getId());
+    q.bindValue(":mediaimagecontainername", mic->getName());
+    q.bindValue(":updatetime", DatabaseManager::getCurrentTimeStamp());
+    return q.exec();
+}
+
+bool DbMediaImageContainer::updateMediaImageContainerToPath(const MediaImageContainer *mic) const
+{
+    QSqlQuery q;
+    q.prepare("UPDATE mediaimagecontainer_filepath "
+                "SET mediaimagecontainername=:mediaimagecontainername, "
+                "updatetime=:updatetime "
+                "WHERE fileid=:fileid AND filepathid=:filepathid");
+    q.bindValue(":fileid", mic->getId());
+    q.bindValue(":filepathid", mic->getFilePath()->getId());
+    q.bindValue(":mediaimagecontainername", mic->getName());
+    q.bindValue(":updatetime", DatabaseManager::getCurrentTimeStamp());
+    return q.exec();
+}
+
+QString DbMediaImageContainer::getMediaImageContainerName(int filePathId, int micId) const
+{
+    QString name = "";
+    QSqlQuery q;
+    q.prepare("SELECT mediaimagecontainername FROM mediaimagecontainer_filepath "
+        "WHERE fileid=:fileid AND filepathid=:filepathid");
+    q.bindValue(":fileid", micId);
+    q.bindValue(":filepathid", filePathId);
+    q.exec();
+    if (q.next())
+        name = q.value(0).toString();
+    return name;
+}
+
+bool DbMediaImageContainer::linkMediaImageToMediaImageContainer(const MediaImage *mi, int micId) const
+{
+    QSqlQuery q;
+    q.prepare("INSERT INTO mediaimagecontainer_mediaimage "
+        "(mediaimagecontainerid, mediaimageid, mediaimagename) "
+        "VALUES (:micid, :miid, :miname) ");
+    q.bindValue(":micid", micId);
+    q.bindValue(":miid", mi->getId());
+    q.bindValue(":miname", mi->getName());
+    return q.exec();
+}
+
+bool DbMediaImageContainer::updateMediaImageToMediaImageContainer(const MediaImage *mi, int micId) const
+{
+    QSqlQuery q;
+    q.prepare("UPDATE mediaimagecontainer_mediaimage "
+        " SET mediaimagename=:miname "
+        " WHERE mediaimagecontainerid=:micid AND mediaimageid=:miid");
+    q.bindValue(":micid", micId);
+    q.bindValue(":miid", mi->getId());
+    q.bindValue(":miname", mi->getName());
+    return q.exec();
+}
index bbfdcd7..4fb21bf 100644 (file)
@@ -36,7 +36,6 @@ class DbMediaImageContainer : public DbFile // DbQueryModelManager
 public:
     DbMediaImageContainer(QObject *parent);
     virtual bool updateDataObjectToModel(const EmuFrontObject *);
-    virtual int insertDataObjectToModel(const EmuFrontObject *);
     virtual bool deleteDataObjectFromModel(QModelIndex *);
     void storeContainers(QList<MediaImageContainer*>, FilePathObject*);
     int getMediaImageContainer(QString checksum) const;
@@ -55,21 +54,25 @@ public:
         MIC_MediaTypeName
    };
 
-
 protected:
     virtual QString constructSelect(QString whereClause = "") const;
     virtual QString constructSelectById(int id) const;
     virtual QString constructFilterById(int id) const;
     virtual EmuFrontObject* recordToDataObject(const QSqlRecord *);
+    EmuFrontObject* getMediaImageContainerByChecksum(QString checksum);
 private:
     virtual QSqlQueryModel* getData();
-    void linkMediaImagesWithContainer(int, QList<int>);
+    int storeMediaImageContainer(EmuFrontObject *efo);
+    void linkMediaImagesWithContainer(int, QList<EmuFrontObject*>);
+    bool linkMediaImageContainerToPath(const MediaImageContainer*) const;
+    bool updateMediaImageContainerToPath(const MediaImageContainer *) const;
+    bool linkMediaImageToMediaImageContainer(const MediaImage*, int micId) const;
+    bool updateMediaImageToMediaImageContainer(const MediaImage*, int micId) const;
+    QString getMediaImageContainerName(int filePathId, int micId) const;
     DbMediaImage *dbMediaImage;
     DbFilePath *dbFilePath;
     virtual QString getCountRefsSelect(int) const;
     virtual QString getDeleteObjectSql() const;
-    // DbSetup *dbSetup;
-    // DbFile *dbFile;
 };
 
 #endif // DBMEDIAIMAGECONTAINER_H
diff --git a/src/db/dbmultiinstancefile.cpp b/src/db/dbmultiinstancefile.cpp
new file mode 100644 (file)
index 0000000..1b3e1d0
--- /dev/null
@@ -0,0 +1,45 @@
+// EmuFront
+// Copyright 2010 Mikko Keinänen
+//
+// This file is part of EmuFront.
+//
+//
+// EmuFront is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation and appearing in the file gpl.txt included in the
+// packaging of this file.
+//
+// EmuFront is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with EmuFront.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QSqlRecord>
+#include <QSqlQuery>
+#include <QSqlRelationalTableModel>
+#include "dbmultiinstancefile.h"
+
+DbMultiInstanceFile::DbMultiInstanceFile(QObject *parent) :
+    DbFile(parent)
+{
+}
+
+int DbMultiInstanceFile::insertDataObjectToModel(const EmuFrontObject *efo)
+{
+    const EmuFrontFile *fi = dynamic_cast<const EmuFrontFile*>(efo);
+    QSqlQuery q;
+    q.prepare("INSERT INTO file "
+              "(id, name, type, checksum, size, updatetime) "
+              "VALUES (NULL, "", :type, :checksum, :size, :updatetime)"); // NOTE: in this class it is ok to leave the name field empty!
+    q.bindValue(":type", fi->getType());
+    q.bindValue(":checksum", fi->getCheckSum());
+    q.bindValue(":size", fi->getSize());
+    q.bindValue(":updatetime", DatabaseManager::getCurrentTimeStamp());
+    int id = -1;
+    if (q.exec())
+        id = q.lastInsertId().toInt();
+    return id;
+}
diff --git a/src/db/dbmultiinstancefile.h b/src/db/dbmultiinstancefile.h
new file mode 100644 (file)
index 0000000..e97f95a
--- /dev/null
@@ -0,0 +1,39 @@
+// EmuFront
+// Copyright 2010 Mikko Keinänen
+//
+// This file is part of EmuFront.
+//
+//
+// EmuFront is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation and appearing in the file gpl.txt included in the
+// packaging of this file.
+//
+// EmuFront is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with EmuFront.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef DBMULTIINSTANCEFILE_H
+#define DBMULTIINSTANCEFILE_H
+
+#include "dbfile.h"
+
+class DbMultiInstanceFile : public DbFile
+{
+    Q_OBJECT
+public:
+    explicit DbMultiInstanceFile(QObject *parent = 0);
+    virtual int insertDataObjectToModel(const EmuFrontObject *);
+
+
+signals:
+
+public slots:
+
+};
+
+#endif // DBMULTIINSTANCEFILE_H
index 53879e5..e2e0051 100644 (file)
@@ -63,7 +63,8 @@ HEADERS += mainwindow.h \
     utils/unziphelper.h \
     utils/emuhelper.h \
     dialogs/listdialog.h \
-    dialogs/emufrontinputdialog.h
+    dialogs/emufrontinputdialog.h \
+    db/dbmultiinstancefile.h
 SOURCES += main.cpp \
     mainwindow.cpp \
     db/databasemanager.cpp \
@@ -116,5 +117,6 @@ SOURCES += main.cpp \
     utils/unziphelper.cpp \
     utils/emuhelper.cpp \
     dialogs/listdialog.cpp \
-    dialogs/emufrontinputdialog.cpp
+    dialogs/emufrontinputdialog.cpp \
+    db/dbmultiinstancefile.cpp
 OTHER_FILES +=