New base for the database backend.
This commit is contained in:
		
							
								
								
									
										5
									
								
								qcma.pro
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								qcma.pro
									
									
									
									
									
								
							@@ -7,7 +7,8 @@
 | 
			
		||||
QT       += core \
 | 
			
		||||
            gui \
 | 
			
		||||
            widgets \
 | 
			
		||||
            network
 | 
			
		||||
            network \
 | 
			
		||||
            sql
 | 
			
		||||
 | 
			
		||||
TARGET = qcma
 | 
			
		||||
 | 
			
		||||
@@ -31,6 +32,7 @@ SOURCES += src/main.cpp \
 | 
			
		||||
    src/clientmanager.cpp \
 | 
			
		||||
    src/filterlineedit.cpp \
 | 
			
		||||
    src/dds.cpp \
 | 
			
		||||
    src/sqlitedb.cpp \
 | 
			
		||||
# forms
 | 
			
		||||
    src/forms/backupitem.cpp \
 | 
			
		||||
    src/forms/backupmanagerform.cpp \
 | 
			
		||||
@@ -56,6 +58,7 @@ HEADERS += \
 | 
			
		||||
    src/clientmanager.h \
 | 
			
		||||
    src/filterlineedit.h \
 | 
			
		||||
    src/dds.h \
 | 
			
		||||
    src/sqlitedb.h \
 | 
			
		||||
# forms
 | 
			
		||||
    src/forms/backupitem.h \
 | 
			
		||||
    src/forms/backupmanagerform.h \
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@
 | 
			
		||||
AVDecoder::AvInit init;
 | 
			
		||||
 | 
			
		||||
AVDecoder::AVDecoder() :
 | 
			
		||||
    pFormatCtx(NULL), file(NULL)
 | 
			
		||||
    pFormatCtx(NULL), pCodecCtx(NULL), file(NULL)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -95,6 +95,16 @@ bool AVDecoder::open(const QString filename)
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *AVDecoder::getMetadataEntry(const char *key, const char *default_value)
 | 
			
		||||
{
 | 
			
		||||
    AVDictionaryEntry *entry;
 | 
			
		||||
 | 
			
		||||
    if((entry = av_dict_get(pFormatCtx->metadata, key, NULL, 0)) != NULL) {
 | 
			
		||||
        return entry->value;
 | 
			
		||||
    }
 | 
			
		||||
    return default_value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AVDecoder::getAudioMetadata(metadata_t &metadata)
 | 
			
		||||
{
 | 
			
		||||
    AVDictionaryEntry *entry;
 | 
			
		||||
@@ -164,6 +174,42 @@ void AVDecoder::getVideoMetadata(metadata_t &metadata)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int AVDecoder::getWidth()
 | 
			
		||||
{
 | 
			
		||||
    return pCodecCtx->width;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int AVDecoder::getHeight()
 | 
			
		||||
{
 | 
			
		||||
    return pCodecCtx->height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int AVDecoder::getDuration()
 | 
			
		||||
{
 | 
			
		||||
    return pFormatCtx->duration / 1000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int AVDecoder::getBitrate()
 | 
			
		||||
{
 | 
			
		||||
    return pFormatCtx->bit_rate;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int AVDecoder::getCodecBitrate()
 | 
			
		||||
{
 | 
			
		||||
    return pCodecCtx->bit_rate;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool AVDecoder::loadCodec(codec_type codec)
 | 
			
		||||
{
 | 
			
		||||
    int stream_index = av_find_best_stream(pFormatCtx, (AVMediaType)codec, -1, -1, NULL, 0);
 | 
			
		||||
    if(stream_index >= 0) {
 | 
			
		||||
        pCodecCtx = pFormatCtx->streams[stream_index]->codec;
 | 
			
		||||
        return true;
 | 
			
		||||
    } else {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QByteArray AVDecoder::getAudioThumbnail(int width, int height)
 | 
			
		||||
{
 | 
			
		||||
    QByteArray data;
 | 
			
		||||
 
 | 
			
		||||
@@ -39,13 +39,23 @@ public:
 | 
			
		||||
    AVDecoder();
 | 
			
		||||
    ~AVDecoder();
 | 
			
		||||
 | 
			
		||||
    enum codec_type {CODEC_VIDEO = AVMEDIA_TYPE_VIDEO, CODEC_AUDIO = AVMEDIA_TYPE_AUDIO};
 | 
			
		||||
 | 
			
		||||
    bool open(const QString filename);
 | 
			
		||||
    void close();
 | 
			
		||||
    bool loadCodec(codec_type codec);
 | 
			
		||||
 | 
			
		||||
    QByteArray getAudioThumbnail(int width, int height);
 | 
			
		||||
    QByteArray getVideoThumbnail(int width, int height);
 | 
			
		||||
    void getAudioMetadata(metadata_t &metadata);
 | 
			
		||||
    void getVideoMetadata(metadata_t &metadata);
 | 
			
		||||
    const char *getMetadataEntry(const char *key, const char *default_value = NULL);
 | 
			
		||||
 | 
			
		||||
    int getWidth();
 | 
			
		||||
    int getHeight();
 | 
			
		||||
    int getDuration();
 | 
			
		||||
    int getBitrate();
 | 
			
		||||
    int getCodecBitrate();
 | 
			
		||||
 | 
			
		||||
    // simulate a static constructor to initialize libav only once
 | 
			
		||||
    class AvInit
 | 
			
		||||
@@ -66,6 +76,7 @@ private:
 | 
			
		||||
    static int64_t seekFunction(void* opaque, int64_t offset, int whence);
 | 
			
		||||
 | 
			
		||||
    AVFormatContext *pFormatCtx;
 | 
			
		||||
    AVCodecContext *pCodecCtx;
 | 
			
		||||
    QFile *file;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										810
									
								
								src/sqlitedb.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										810
									
								
								src/sqlitedb.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,810 @@
 | 
			
		||||
#include "sqlitedb.h"
 | 
			
		||||
#include "sforeader.h"
 | 
			
		||||
#include "avdecoder.h"
 | 
			
		||||
 | 
			
		||||
#include <QDateTime>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
 | 
			
		||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
 | 
			
		||||
#include <QStandardPaths>
 | 
			
		||||
#else
 | 
			
		||||
#include <QDesktopServices>
 | 
			
		||||
#define QStandardPaths QDesktopServices
 | 
			
		||||
#define writableLocation storageLocation
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <QSettings>
 | 
			
		||||
#include <QSqlQuery>
 | 
			
		||||
 | 
			
		||||
static const char create_adjacent[] = "CREATE TABLE IF NOT EXISTS adjacent_objects ("
 | 
			
		||||
                                      "parent_id INTEGER NOT NULL REFERENCES object_node(object_id) ON DELETE CASCADE,"
 | 
			
		||||
                                      "child_id INTEGER NOT NULL REFERENCES object_node(object_id) ON DELETE CASCADE)";
 | 
			
		||||
 | 
			
		||||
static const char create_obj_node[] = "CREATE TABLE IF NOT EXISTS object_node ("
 | 
			
		||||
                                      "object_id INTEGER PRIMARY KEY AUTOINCREMENT,"
 | 
			
		||||
                                      "type INTEGER NOT NULL,"
 | 
			
		||||
                                      "title TEXT,"
 | 
			
		||||
                                      "child_count INTEGER NOT NULL DEFAULT 0,"
 | 
			
		||||
                                      "reference_count INTEGER NOT NULL DEFAULT 0);";
 | 
			
		||||
 | 
			
		||||
static const char create_sources[] = "CREATE TABLE IF NOT EXISTS sources ("
 | 
			
		||||
                                     "object_id INTEGER PRIMARY KEY REFERENCES object_node(object_id) ON DELETE CASCADE,"
 | 
			
		||||
                                     "path TEXT UNIQUE NOT NULL CHECK (LENGTH(path) > 0),"
 | 
			
		||||
                                     "size INTEGER,"
 | 
			
		||||
                                     "date_created TIMESTAMP,"
 | 
			
		||||
                                     "date_modified TIMESTAMP)";
 | 
			
		||||
 | 
			
		||||
static const char create_music[] = "CREATE TABLE IF NOT EXISTS music ("
 | 
			
		||||
                                   "object_id INTEGER PRIMARY KEY REFERENCES object_node(object_id) ON DELETE CASCADE,"
 | 
			
		||||
                                   "file_format INTEGER,"
 | 
			
		||||
                                   "audio_bitrate INTEGER,"
 | 
			
		||||
                                   "audio_codec INTEGER,"
 | 
			
		||||
                                   "duration INTEGER,"
 | 
			
		||||
                                   "genre_id INTEGER REFERENCES object_node(object_id) ON DELETE SET NULL,"
 | 
			
		||||
                                   "track_id INTEGER REFERENCES object_node(object_id) ON DELETE SET NULL,"
 | 
			
		||||
                                   "artist_id INTEGER REFERENCES object_node(object_id) ON DELETE SET NULL,"
 | 
			
		||||
                                   "album_id INTEGER REFERENCES object_node(object_id) ON DELETE SET NULL,"
 | 
			
		||||
                                   "artist TEXT,"
 | 
			
		||||
                                   "album TEXT,"
 | 
			
		||||
                                   "track_number INTEGER)";
 | 
			
		||||
 | 
			
		||||
static const char create_photos[] = "CREATE TABLE IF NOT EXISTS photos ("
 | 
			
		||||
                                    "object_id INTEGER PRIMARY KEY REFERENCES object_node(object_id) ON DELETE CASCADE,"
 | 
			
		||||
                                    "date_created TIMESTAMP,"
 | 
			
		||||
                                    "file_format INTEGER,"
 | 
			
		||||
                                    "photo_codec INTEGER,"
 | 
			
		||||
                                    "width INTEGER,"
 | 
			
		||||
                                    "height INTEGER)";
 | 
			
		||||
 | 
			
		||||
static const char create_videos[] = "CREATE TABLE IF NOT EXISTS videos ("
 | 
			
		||||
                                    "object_id INTEGER PRIMARY KEY REFERENCES object_node(object_id) ON DELETE CASCADE,"
 | 
			
		||||
                                    "file_format INTEGER,"
 | 
			
		||||
                                    "parental_level INTEGER,"
 | 
			
		||||
                                    "explanation TEXT,"
 | 
			
		||||
                                    "copyright TEXT,"
 | 
			
		||||
                                    "width INTEGER,"
 | 
			
		||||
                                    "height INTEGER,"
 | 
			
		||||
                                    "video_codec INTEGER,"
 | 
			
		||||
                                    "video_bitrate INTEGER,"
 | 
			
		||||
                                    "audio_codec INTEGER,"
 | 
			
		||||
                                    "audio_bitrate INTEGER,"
 | 
			
		||||
                                    "duration INTEGER)";
 | 
			
		||||
 | 
			
		||||
static const char create_savedata[] = "CREATE TABLE IF NOT EXISTS savedata ("
 | 
			
		||||
                                      "object_id INTEGER PRIMARY KEY REFERENCES object_node(object_id) ON DELETE CASCADE,"
 | 
			
		||||
                                      "detail TEXT,"
 | 
			
		||||
                                      "dir_name TEXT,"
 | 
			
		||||
                                      "title TEXT,"
 | 
			
		||||
                                      "date_updated TIMESTAMP)";
 | 
			
		||||
 | 
			
		||||
static const char create_trigger_node[] = "CREATE TRIGGER IF NOT EXISTS trg_objnode_deletechilds BEFORE DELETE ON object_node "
 | 
			
		||||
                                          "FOR EACH ROW BEGIN "
 | 
			
		||||
                                            "DELETE FROM object_node WHERE object_id IN "
 | 
			
		||||
                                              "(SELECT child_id FROM adjacent_objects WHERE parent_id == OLD.object_id);"
 | 
			
		||||
                                          "END";
 | 
			
		||||
 | 
			
		||||
static const char create_trigger_adjins[] = "CREATE TRIGGER IF NOT EXISTS trg_adjacentobjects_ins AFTER INSERT ON adjacent_objects "
 | 
			
		||||
                                            "FOR EACH ROW BEGIN "
 | 
			
		||||
                                              "UPDATE object_node SET child_count = child_count + 1 WHERE object_id = NEW.parent_id;"
 | 
			
		||||
                                              "UPDATE object_node SET reference_count = reference_count + 1 WHERE object_id = NEW.child_id;"
 | 
			
		||||
                                            "END";
 | 
			
		||||
 | 
			
		||||
static const char create_trigger_adjdel[] = "CREATE TRIGGER IF NOT EXISTS trg_adjacentobjects_del AFTER DELETE ON adjacent_objects "
 | 
			
		||||
                                            "FOR EACH ROW BEGIN "
 | 
			
		||||
                                              "UPDATE object_node SET child_count = child_count - 1 WHERE object_id = OLD.parent_id;"
 | 
			
		||||
                                              "UPDATE object_node SET reference_count = reference_count - 1 WHERE object_id = OLD.child_id;"
 | 
			
		||||
                                              "DELETE FROM object_node WHERE object_id = OLD.parent_id AND child_count <= 0;"
 | 
			
		||||
                                              "DELETE FROM object_node WHERE object_id = OLD.child_id AND reference_count <= 0;"
 | 
			
		||||
                                            "END";
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    const char *file_ext;
 | 
			
		||||
    int file_format;
 | 
			
		||||
    int file_codec;
 | 
			
		||||
} file_type;
 | 
			
		||||
 | 
			
		||||
#define FILE_FORMAT_MP4 1
 | 
			
		||||
#define FILE_FORMAT_WAV 2
 | 
			
		||||
#define FILE_FORMAT_MP3 3
 | 
			
		||||
#define FILE_FORMAT_JPG 4
 | 
			
		||||
#define FILE_FORMAT_PNG 5
 | 
			
		||||
#define FILE_FORMAT_GIF 6
 | 
			
		||||
#define FILE_FORMAT_BMP 7
 | 
			
		||||
#define FILE_FORMAT_TIF 8
 | 
			
		||||
 | 
			
		||||
#define CODEC_TYPE_MPEG4 2
 | 
			
		||||
#define CODEC_TYPE_AVC 3
 | 
			
		||||
#define CODEC_TYPE_MP3 12
 | 
			
		||||
#define CODEC_TYPE_AAC 13
 | 
			
		||||
#define CODEC_TYPE_PCM 15
 | 
			
		||||
#define CODEC_TYPE_JPG 17
 | 
			
		||||
#define CODEC_TYPE_PNG 18
 | 
			
		||||
#define CODEC_TYPE_TIF 19
 | 
			
		||||
#define CODEC_TYPE_BMP 20
 | 
			
		||||
#define CODEC_TYPE_GIF 21
 | 
			
		||||
 | 
			
		||||
static const file_type audio_list[] = {
 | 
			
		||||
    {"mp3", FILE_FORMAT_MP3, CODEC_TYPE_MP3},
 | 
			
		||||
    {"mp4", FILE_FORMAT_MP4, CODEC_TYPE_AAC},
 | 
			
		||||
    {"wav", FILE_FORMAT_WAV, CODEC_TYPE_PCM}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const file_type photo_list[] = {
 | 
			
		||||
    {"jpg",  FILE_FORMAT_JPG, CODEC_TYPE_JPG},
 | 
			
		||||
    {"jpeg", FILE_FORMAT_JPG, CODEC_TYPE_JPG},
 | 
			
		||||
    {"png",  FILE_FORMAT_PNG, CODEC_TYPE_PNG},
 | 
			
		||||
    {"tif",  FILE_FORMAT_TIF, CODEC_TYPE_TIF},
 | 
			
		||||
    {"tiff", FILE_FORMAT_TIF, CODEC_TYPE_TIF},
 | 
			
		||||
    {"bmp",  FILE_FORMAT_BMP, CODEC_TYPE_BMP},
 | 
			
		||||
    {"gif",  FILE_FORMAT_GIF, CODEC_TYPE_GIF},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const file_type video_list[] = {
 | 
			
		||||
    {"mp4", FILE_FORMAT_MP4, 0}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static const char *table_list[] = {
 | 
			
		||||
    create_adjacent, create_obj_node, create_sources,
 | 
			
		||||
    create_music, create_photos, create_videos, create_savedata
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const char *trigger_list[] = {
 | 
			
		||||
    create_trigger_node, create_trigger_adjins, create_trigger_adjdel
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
SQLiteDB::SQLiteDB(QObject *parent) :
 | 
			
		||||
    QObject(parent)
 | 
			
		||||
{
 | 
			
		||||
    uuid = QSettings().value("lastAccountId", "ffffffffffffffff").toString();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SQLiteDB::~SQLiteDB()
 | 
			
		||||
{
 | 
			
		||||
    db.close();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SQLiteDB::open()
 | 
			
		||||
{
 | 
			
		||||
    // fetch a configured database path if it exists
 | 
			
		||||
    QString db_path = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
 | 
			
		||||
    db_path = QSettings().value("databasePath", db_path).toString();
 | 
			
		||||
    QDir(QDir::root()).mkpath(db_path);
 | 
			
		||||
 | 
			
		||||
    db = QSqlDatabase::addDatabase("QSQLITE");
 | 
			
		||||
    db.setDatabaseName(db_path + QDir::separator() + "qcma.sqlite");
 | 
			
		||||
 | 
			
		||||
    return db.open();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SQLiteDB::remove()
 | 
			
		||||
{
 | 
			
		||||
    QString db_path = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
 | 
			
		||||
    db_path = QSettings().value("databasePath", db_path).toString();
 | 
			
		||||
    QDir(QDir::root()).mkpath(db_path);
 | 
			
		||||
 | 
			
		||||
    QFile(db_path + QDir::separator() + "qcma.sqlite").remove();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SQLiteDB::initialize()
 | 
			
		||||
{
 | 
			
		||||
    if (!db.isOpen()) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    QSqlQuery query;
 | 
			
		||||
 | 
			
		||||
    for(unsigned int i = 0; i < sizeof(table_list) / sizeof(const char *); i++) {
 | 
			
		||||
        if(!query.exec(table_list[i])) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for(unsigned int i = 0; i < sizeof(trigger_list) / sizeof(const char *); i++) {
 | 
			
		||||
        if(!query.exec(trigger_list[i])) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // force object_id to start at 256
 | 
			
		||||
    if(query.exec("INSERT INTO object_node (object_id, type) VALUES (255, 0)")) {
 | 
			
		||||
        query.exec("DELETE FROM object_node WHERE object_id = 255");
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QSqlError SQLiteDB::getLastError()
 | 
			
		||||
{
 | 
			
		||||
    return db.lastError();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int SQLiteDB::checkFileType(const QString path, int ohfi_root)
 | 
			
		||||
{
 | 
			
		||||
    switch(ohfi_root) {
 | 
			
		||||
    case VITA_OHFI_MUSIC:
 | 
			
		||||
        for(int i = 0, max = sizeof(audio_list) / sizeof(file_type); i < max; i++) {
 | 
			
		||||
            if(path.endsWith(audio_list[i].file_ext, Qt::CaseInsensitive)) {
 | 
			
		||||
                return i;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case VITA_OHFI_PHOTO:
 | 
			
		||||
        for(int i = 0, max = sizeof(photo_list) / sizeof(file_type); i< max; i++) {
 | 
			
		||||
            if(path.endsWith(photo_list[i].file_ext, Qt::CaseInsensitive)) {
 | 
			
		||||
                return i;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case VITA_OHFI_VIDEO:
 | 
			
		||||
        for(int i = 0, max = sizeof(video_list) / sizeof(file_type); i< max; i++) {
 | 
			
		||||
            if(path.endsWith(video_list[i].file_ext, Qt::CaseInsensitive)) {
 | 
			
		||||
                return i;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int SQLiteDB::create()
 | 
			
		||||
{
 | 
			
		||||
    int total_objects = 0;
 | 
			
		||||
 | 
			
		||||
    const int ohfi_array[] = { VITA_OHFI_MUSIC, VITA_OHFI_VIDEO, VITA_OHFI_PHOTO,
 | 
			
		||||
                               VITA_OHFI_BACKUP, VITA_OHFI_VITAAPP, VITA_OHFI_PSPAPP,
 | 
			
		||||
                               VITA_OHFI_PSPSAVE, VITA_OHFI_PSXAPP, VITA_OHFI_PSMAPP
 | 
			
		||||
                             };
 | 
			
		||||
 | 
			
		||||
    QSettings settings;
 | 
			
		||||
    QString base_path;
 | 
			
		||||
 | 
			
		||||
    for(int i = 0, max = sizeof(ohfi_array) / sizeof(int); i < max; i++) {
 | 
			
		||||
        switch(ohfi_array[i]) {
 | 
			
		||||
        case VITA_OHFI_MUSIC:
 | 
			
		||||
            base_path = settings.value("musicPath").toString();
 | 
			
		||||
            break;
 | 
			
		||||
        case VITA_OHFI_VIDEO:
 | 
			
		||||
            base_path = settings.value("videoPath").toString();
 | 
			
		||||
            break;
 | 
			
		||||
        case VITA_OHFI_PHOTO:
 | 
			
		||||
            base_path = settings.value("photoPath").toString();
 | 
			
		||||
            break;
 | 
			
		||||
        case VITA_OHFI_BACKUP:
 | 
			
		||||
            continue;
 | 
			
		||||
            base_path = settings.value("appsPath").toString() + QDir::separator() + "SYSTEM" + QDir::separator() + uuid;
 | 
			
		||||
            break;
 | 
			
		||||
        case VITA_OHFI_VITAAPP:
 | 
			
		||||
            continue;
 | 
			
		||||
            base_path = settings.value("appsPath").toString() + QDir::separator() + "APP" + QDir::separator() + uuid;
 | 
			
		||||
            break;
 | 
			
		||||
        case VITA_OHFI_PSPAPP:
 | 
			
		||||
            continue;
 | 
			
		||||
            base_path = settings.value("appsPath").toString() + QDir::separator() + "PGAME" + QDir::separator() + uuid;
 | 
			
		||||
            break;
 | 
			
		||||
        case VITA_OHFI_PSPSAVE:
 | 
			
		||||
            base_path = settings.value("appsPath").toString() + QDir::separator() + "PSAVEDATA" + QDir::separator() + uuid;
 | 
			
		||||
            break;
 | 
			
		||||
        case VITA_OHFI_PSXAPP:
 | 
			
		||||
            continue;
 | 
			
		||||
            base_path = settings.value("appsPath").toString() + QDir::separator() + "PSGAME" + QDir::separator() + uuid;
 | 
			
		||||
            break;
 | 
			
		||||
        case VITA_OHFI_PSMAPP:
 | 
			
		||||
            continue;
 | 
			
		||||
            base_path = settings.value("appsPath").toString() + QDir::separator() + "PSM" + QDir::separator() + uuid;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        int dir_count = recursiveScanRootDirectory(base_path, ohfi_array[i], OBJECT_FOLDER);
 | 
			
		||||
 | 
			
		||||
        if(dir_count < 0) {
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        total_objects += dir_count;
 | 
			
		||||
    }
 | 
			
		||||
    return total_objects;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int SQLiteDB::recursiveScanRootDirectory(const QString &base_path, int parent, int parent_type)
 | 
			
		||||
{
 | 
			
		||||
    int total_objects = 0;
 | 
			
		||||
 | 
			
		||||
    QDir dir(base_path);
 | 
			
		||||
    dir.setSorting(QDir::Name);
 | 
			
		||||
    QFileInfoList qsl = dir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot);
 | 
			
		||||
 | 
			
		||||
    foreach(const QFileInfo &info, qsl) {
 | 
			
		||||
        qDebug() << "Processing " << info.fileName();
 | 
			
		||||
        if(info.isDir()) {
 | 
			
		||||
            int ohfi = insertDirectoryEntry(info.absoluteFilePath(), parent_type, parent);
 | 
			
		||||
            total_objects += recursiveScanRootDirectory(info.absoluteFilePath(), ohfi, parent_type);
 | 
			
		||||
        } else if(info.isFile()) {
 | 
			
		||||
            switch(parent_type) {
 | 
			
		||||
            case VITA_OHFI_MUSIC:
 | 
			
		||||
                insertMusicEntry(info.absoluteFilePath(), OBJECT_MUSIC | (parent_type & ~OBJECT_FOLDER), parent);
 | 
			
		||||
                break;
 | 
			
		||||
            case VITA_OHFI_PHOTO:
 | 
			
		||||
                insertPhotoEntry(info.absoluteFilePath(), OBJECT_PHOTO | (parent_type & ~OBJECT_FOLDER), parent);
 | 
			
		||||
                break;
 | 
			
		||||
            case VITA_OHFI_VIDEO:
 | 
			
		||||
                insertVideoEntry(info.absoluteFilePath(), OBJECT_VIDEO | (parent_type & ~OBJECT_FOLDER), parent);
 | 
			
		||||
                break;
 | 
			
		||||
            case VITA_OHFI_PSPSAVE:
 | 
			
		||||
                insertSavedataEntry(info.absoluteFilePath(), OBJECT_SAVEDATA | (parent_type & ~OBJECT_FOLDER), parent);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            total_objects++;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return total_objects;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int SQLiteDB::getPathId(const QString &path)
 | 
			
		||||
{
 | 
			
		||||
    if (!db.isOpen()) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    QSqlQuery query(QString("SELECT object_id from sources WHERE path = %1").arg(path));
 | 
			
		||||
    if(query.next()) {
 | 
			
		||||
        return query.value(0).toInt();
 | 
			
		||||
    } else {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString SQLiteDB::getPathFromId(int ohfi)
 | 
			
		||||
{
 | 
			
		||||
    if (!db.isOpen()) {
 | 
			
		||||
        return QString();
 | 
			
		||||
    }
 | 
			
		||||
    QSqlQuery query(QString("SELECT path FROM sources WHERE object_id = %1").arg(ohfi));
 | 
			
		||||
    if(query.next()) {
 | 
			
		||||
        return query.value(0).toString();
 | 
			
		||||
    } else {
 | 
			
		||||
        return QString();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SQLiteDB::updateSize(int ohfi, quint64 size)
 | 
			
		||||
{
 | 
			
		||||
    if (!db.isOpen()) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    QSqlQuery query(QString("UPDATE sources SET size = %1 WHERE object_id == %2").arg(size).arg(ohfi));
 | 
			
		||||
    return query.exec();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SQLiteDB::deleteEntry(int ohfi)
 | 
			
		||||
{
 | 
			
		||||
    QSqlQuery query(QString("DELETE FROM object_node WHERE object_id == %1").arg(ohfi));
 | 
			
		||||
    return query.exec();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SQLiteDB::deleteEntry(const QString &path)
 | 
			
		||||
{
 | 
			
		||||
    QSqlQuery query(QString("DELETE FROM object_node WHERE object_id == (SELECT object_id FROM sources WHERE path == %1)").arg(path));
 | 
			
		||||
    return query.exec();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SQLiteDB::updateAdjacencyList(int ohfi, int parent)
 | 
			
		||||
{
 | 
			
		||||
    QSqlQuery query;
 | 
			
		||||
    query.prepare("SELECT * FROM adjacent_objects WHERE parent_id == :parent_id AND child_id == :child_id");
 | 
			
		||||
    query.bindValue(0, parent);
 | 
			
		||||
    query.bindValue(1, ohfi);
 | 
			
		||||
 | 
			
		||||
    if(query.exec() && query.next()) {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    query.prepare("INSERT INTO adjacent_objects (parent_id, child_id)"
 | 
			
		||||
                  "VALUES (:parentid, :child_id)");
 | 
			
		||||
    query.bindValue(0, parent);
 | 
			
		||||
    query.bindValue(1, ohfi);
 | 
			
		||||
    return query.exec();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint SQLiteDB::insertDirectoryEntry(const QString &path, int type, int parent)
 | 
			
		||||
{
 | 
			
		||||
    uint ohfi;
 | 
			
		||||
    db.transaction();
 | 
			
		||||
    QString dirname = QFileInfo(path).fileName();
 | 
			
		||||
 | 
			
		||||
    if((ohfi = insertObjectEntry(dirname.toUtf8().constData(), type)) == 0) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(parent && !updateAdjacencyList(ohfi, parent)) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(!insertSourceEntry(ohfi, path)) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    db.commit();
 | 
			
		||||
    return ohfi;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint SQLiteDB::insertObjectEntry(const char *title, int type)
 | 
			
		||||
{
 | 
			
		||||
    QSqlQuery query;
 | 
			
		||||
 | 
			
		||||
    query.prepare("SELECT object_id FROM object_node WHERE type == :type and title == :title");
 | 
			
		||||
    query.bindValue(0, type);
 | 
			
		||||
    query.bindValue(1, title);    
 | 
			
		||||
 | 
			
		||||
    if(!query.exec() || !query.next()) {
 | 
			
		||||
        query.prepare("INSERT INTO object_node (type, title) VALUES (:type, :title)");
 | 
			
		||||
        query.bindValue(0, type);
 | 
			
		||||
        query.bindValue(1, title);
 | 
			
		||||
 | 
			
		||||
        if(!query.exec() || !query.exec("SELECT last_insert_rowid()") || !query.next()) {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return query.value(0).toInt();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SQLiteDB::insertSourceEntry(uint object_id, const QString &path)
 | 
			
		||||
{
 | 
			
		||||
    qint64 size;
 | 
			
		||||
    uint date_created, date_modified;
 | 
			
		||||
 | 
			
		||||
    QFileInfo info(path);
 | 
			
		||||
    size = info.size();
 | 
			
		||||
    date_created = info.created().toTime_t();
 | 
			
		||||
    date_modified = info.lastModified().toTime_t();
 | 
			
		||||
 | 
			
		||||
    QSqlQuery query;
 | 
			
		||||
    query.prepare("REPLACE INTO sources (object_id, path, size, date_created, date_modified)"
 | 
			
		||||
                  "VALUES (:object_id, :path, :size, :date_created, :date_modified)");
 | 
			
		||||
    query.bindValue(0, object_id);
 | 
			
		||||
    query.bindValue(1, path);
 | 
			
		||||
    query.bindValue(2, size);
 | 
			
		||||
    query.bindValue(3, date_created);
 | 
			
		||||
    query.bindValue(4, date_modified);
 | 
			
		||||
    return query.exec();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint SQLiteDB::insertMusicEntry(const QString &path, int type, int parent)
 | 
			
		||||
{
 | 
			
		||||
    bool ok;
 | 
			
		||||
    uint ohfi;
 | 
			
		||||
    AVDecoder decoder;
 | 
			
		||||
    quint64 duration;
 | 
			
		||||
    const char *artist, *album, *albumartist, *genre, *track, *title;
 | 
			
		||||
    int file_format, audio_codec, audio_bitrate, genre_id, artist_id, track_id, album_id, track_number;
 | 
			
		||||
 | 
			
		||||
    int file_type = checkFileType(path, type);
 | 
			
		||||
    if(file_type < 0) {
 | 
			
		||||
        qDebug() << "Excluding from database:" << path;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(!decoder.open(path)) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    album = decoder.getMetadataEntry("album");
 | 
			
		||||
    genre = decoder.getMetadataEntry("genre");
 | 
			
		||||
    artist = decoder.getMetadataEntry("artist");
 | 
			
		||||
    albumartist = decoder.getMetadataEntry("album_artist");
 | 
			
		||||
    track = decoder.getMetadataEntry("track");
 | 
			
		||||
 | 
			
		||||
    track_number = QString(track).toInt(&ok);
 | 
			
		||||
    if(!ok) {
 | 
			
		||||
        // set track number to 1 by default
 | 
			
		||||
        track_number = 1;
 | 
			
		||||
    }
 | 
			
		||||
    audio_bitrate = decoder.getBitrate();
 | 
			
		||||
    duration = decoder.getDuration();
 | 
			
		||||
 | 
			
		||||
    file_format = audio_list[file_type].file_format;
 | 
			
		||||
    audio_codec = audio_list[file_type].file_codec;
 | 
			
		||||
 | 
			
		||||
    QByteArray basename = QFileInfo(path).baseName().toUtf8();
 | 
			
		||||
    title = decoder.getMetadataEntry("title", basename.constData());
 | 
			
		||||
 | 
			
		||||
    db.transaction();
 | 
			
		||||
 | 
			
		||||
    if((ohfi = insertObjectEntry(title, type)) == 0) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(parent && !updateAdjacencyList(ohfi, parent)) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(!insertSourceEntry(ohfi, path)) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(genre) {
 | 
			
		||||
        genre_id = insertObjectEntry(genre, type | OBJECT_GENRE);
 | 
			
		||||
        if(!updateAdjacencyList(ohfi, genre_id)) {
 | 
			
		||||
            db.rollback();
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        genre_id = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(artist) {
 | 
			
		||||
        track_id = insertObjectEntry(artist, type | OBJECT_ARTIST);
 | 
			
		||||
        if(!updateAdjacencyList(ohfi, track_id)) {
 | 
			
		||||
            db.rollback();
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        track_id = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(albumartist) {
 | 
			
		||||
        artist_id = insertObjectEntry(albumartist, type | OBJECT_ALBUM_ARTIST);
 | 
			
		||||
        if(!updateAdjacencyList(ohfi, artist_id)) {
 | 
			
		||||
            db.rollback();
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        artist_id = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(album) {
 | 
			
		||||
        album_id = insertObjectEntry(album, type | OBJECT_ALBUM);
 | 
			
		||||
 | 
			
		||||
        if(track_id && !updateAdjacencyList(ohfi, album_id)) {
 | 
			
		||||
            db.rollback();
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        if(track_id && !updateAdjacencyList(album_id, track_id)) {
 | 
			
		||||
            db.rollback();
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        if(artist_id && !updateAdjacencyList(album_id, artist_id)) {
 | 
			
		||||
            db.rollback();
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        album_id = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QSqlQuery query;
 | 
			
		||||
    query.prepare("REPLACE INTO music"
 | 
			
		||||
    "(object_id, file_format, audio_codec, audio_bitrate, duration, genre_id, artist_id, album_id, track_id, artist, album, track_number)"
 | 
			
		||||
    "VALUES (:object_id, :file_format, :audio_codec, :audio_bitrate, :duration, :genre_id, :artist_id, :album_id, :track_id, :artist, :album, :track_number)");
 | 
			
		||||
 | 
			
		||||
    query.bindValue(0, ohfi);
 | 
			
		||||
    query.bindValue(1, file_format);
 | 
			
		||||
    query.bindValue(2, audio_codec);
 | 
			
		||||
    query.bindValue(3, audio_bitrate);
 | 
			
		||||
    query.bindValue(4, duration);
 | 
			
		||||
    query.bindValue(5, genre_id ? genre_id : QVariant(QVariant::Int));
 | 
			
		||||
    query.bindValue(6, artist_id ? artist_id : QVariant(QVariant::Int));
 | 
			
		||||
    query.bindValue(7, album_id ? album_id : QVariant(QVariant::Int));
 | 
			
		||||
    query.bindValue(8, track_id ? track_id : QVariant(QVariant::Int));
 | 
			
		||||
    query.bindValue(9, artist);
 | 
			
		||||
    query.bindValue(10, album);
 | 
			
		||||
    query.bindValue(11, track_number);
 | 
			
		||||
 | 
			
		||||
    if(!query.exec()) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    db.commit();
 | 
			
		||||
    return ohfi;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint SQLiteDB::insertVideoEntry(const QString &path, int type, int parent)
 | 
			
		||||
{
 | 
			
		||||
    int ohfi;
 | 
			
		||||
    AVDecoder decoder;
 | 
			
		||||
    quint64 duration;
 | 
			
		||||
    int file_format, parental_level, width, height, video_codec, video_bitrate, audio_codec, audio_bitrate;
 | 
			
		||||
    const char *explanation, *copyright, *title;
 | 
			
		||||
 | 
			
		||||
    if(!decoder.open(path) || !decoder.loadCodec(AVDecoder::CODEC_VIDEO)) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int file_type = checkFileType(path, type);
 | 
			
		||||
    if(file_type < 0) {
 | 
			
		||||
        qDebug() << "Excluding from database:" << path;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    parental_level = 0;
 | 
			
		||||
    explanation = decoder.getMetadataEntry("comments", "");
 | 
			
		||||
    copyright = decoder.getMetadataEntry("copyright", "");
 | 
			
		||||
    width = decoder.getWidth();
 | 
			
		||||
    height = decoder.getHeight();
 | 
			
		||||
    duration = decoder.getDuration();
 | 
			
		||||
    video_codec = 3;
 | 
			
		||||
    video_bitrate = decoder.getCodecBitrate();
 | 
			
		||||
    file_format = video_list[file_type].file_format;
 | 
			
		||||
 | 
			
		||||
    if(decoder.loadCodec(AVDecoder::CODEC_AUDIO)) {
 | 
			
		||||
        audio_codec = 13;
 | 
			
		||||
        audio_bitrate = decoder.getCodecBitrate();
 | 
			
		||||
    } else {
 | 
			
		||||
        audio_codec = 0;
 | 
			
		||||
        audio_bitrate = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QByteArray basename = QFileInfo(path).baseName().toUtf8();
 | 
			
		||||
    //title = decoder.getMetadataEntry("title", basename.constData());
 | 
			
		||||
    title = basename.constData();
 | 
			
		||||
 | 
			
		||||
    db.transaction();
 | 
			
		||||
 | 
			
		||||
    if((ohfi = insertObjectEntry(title, type)) == 0) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(parent && !updateAdjacencyList(ohfi, parent)) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(!insertSourceEntry(ohfi, path)) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QSqlQuery query;
 | 
			
		||||
    query.prepare("REPLACE INTO videos"
 | 
			
		||||
    "(object_id, file_format, parental_level, explanation, copyright, width, height, video_codec, video_bitrate, audio_codec, audio_bitrate, duration)"
 | 
			
		||||
    "VALUES (:object_id, :file_format, :parental_level, :explanation, :copyright, :width, :height, :video_codec, :video_bitrate, :audio_codec, :audio_bitrate, :duration)");
 | 
			
		||||
 | 
			
		||||
    query.bindValue(0, ohfi);
 | 
			
		||||
    query.bindValue(1, file_format);
 | 
			
		||||
    query.bindValue(2, parental_level);
 | 
			
		||||
    query.bindValue(3, explanation);
 | 
			
		||||
    query.bindValue(4, copyright);
 | 
			
		||||
    query.bindValue(5, width);
 | 
			
		||||
    query.bindValue(6, height);
 | 
			
		||||
    query.bindValue(7, video_codec);
 | 
			
		||||
    query.bindValue(8, video_bitrate);
 | 
			
		||||
    query.bindValue(9, audio_codec);
 | 
			
		||||
    query.bindValue(10, audio_bitrate);
 | 
			
		||||
    query.bindValue(11, duration);
 | 
			
		||||
 | 
			
		||||
    if(!query.exec()) {
 | 
			
		||||
        qDebug() << query.lastError().text();
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    db.commit();
 | 
			
		||||
    return ohfi;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint SQLiteDB::insertPhotoEntry(const QString &path, int type, int parent)
 | 
			
		||||
{
 | 
			
		||||
    int ohfi;
 | 
			
		||||
    QImage img;
 | 
			
		||||
    uint date_created;
 | 
			
		||||
    int width, height, file_format, photo_codec;
 | 
			
		||||
 | 
			
		||||
    int file_type = checkFileType(path, type);
 | 
			
		||||
    if(file_type < 0) {
 | 
			
		||||
        qDebug() << "Excluding from database:" << path;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(!img.load(path)) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    date_created = QFileInfo(path).created().toTime_t();
 | 
			
		||||
    width = img.width();
 | 
			
		||||
    height = img.height();
 | 
			
		||||
    file_format = photo_list[file_type].file_format;
 | 
			
		||||
    photo_codec = photo_list[file_type].file_codec;
 | 
			
		||||
 | 
			
		||||
    QByteArray basename = QFileInfo(path).baseName().toUtf8();
 | 
			
		||||
 | 
			
		||||
    db.transaction();
 | 
			
		||||
 | 
			
		||||
    if((ohfi = insertObjectEntry(basename.constData(), type)) == 0) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(parent && !updateAdjacencyList(ohfi, parent)) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(!insertSourceEntry(ohfi, path)) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QSqlQuery query;
 | 
			
		||||
    query.prepare("REPLACE INTO photos"
 | 
			
		||||
    "(object_id, date_created, file_format, photo_codec, width, height)"
 | 
			
		||||
    "VALUES (:object_id, :date_created, :file_format, :photo_codec, :width, :height)");
 | 
			
		||||
 | 
			
		||||
    query.bindValue(0, ohfi);
 | 
			
		||||
    query.bindValue(1, date_created);
 | 
			
		||||
    query.bindValue(2, file_format);
 | 
			
		||||
    query.bindValue(3, photo_codec);
 | 
			
		||||
    query.bindValue(4, width);
 | 
			
		||||
    query.bindValue(5, height);
 | 
			
		||||
 | 
			
		||||
    if(!query.exec()) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    db.commit();
 | 
			
		||||
    return ohfi;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint SQLiteDB::insertSavedataEntry(const QString &path, int type, int parent)
 | 
			
		||||
{
 | 
			
		||||
    int ohfi;
 | 
			
		||||
 | 
			
		||||
    uint date_updated;
 | 
			
		||||
    const char *title, *savedata_detail, *savedata_directory;
 | 
			
		||||
 | 
			
		||||
    SfoReader reader;
 | 
			
		||||
    QString base_name = QFileInfo(path).baseName();
 | 
			
		||||
    QString sfo_file = QDir(path).absoluteFilePath("PARAM.SFO");
 | 
			
		||||
 | 
			
		||||
    if(!reader.load(sfo_file)) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    title = reader.value("TITLE", base_name.toUtf8().constData());
 | 
			
		||||
    savedata_detail = reader.value("SAVEDATA_DETAIL", "");
 | 
			
		||||
    savedata_directory = reader.value("SAVEDATA_DIRECTORY", base_name.toUtf8().constData());
 | 
			
		||||
    date_updated = QFileInfo(sfo_file).lastModified().toTime_t();
 | 
			
		||||
 | 
			
		||||
    db.transaction();
 | 
			
		||||
 | 
			
		||||
    if((ohfi = insertObjectEntry(title, type)) == 0) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(parent && !updateAdjacencyList(ohfi, parent)) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(!insertSourceEntry(ohfi, path)) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QSqlQuery query;
 | 
			
		||||
    query.prepare("REPLACE INTO savedata"
 | 
			
		||||
        "(object_id, detail, dir_name, title, date_updated)"
 | 
			
		||||
        "VALUES (:object_id, :detail, :dir_name, :title, :updated)");
 | 
			
		||||
 | 
			
		||||
    query.bindValue(0, ohfi);
 | 
			
		||||
    query.bindValue(1, savedata_detail);
 | 
			
		||||
    query.bindValue(2, savedata_directory);
 | 
			
		||||
    query.bindValue(3, title);
 | 
			
		||||
    query.bindValue(4, date_updated);
 | 
			
		||||
 | 
			
		||||
    if(!query.exec()) {
 | 
			
		||||
        db.rollback();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    db.commit();
 | 
			
		||||
    return ohfi;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										66
									
								
								src/sqlitedb.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/sqlitedb.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
#ifndef SQLITEDB_H
 | 
			
		||||
#define SQLITEDB_H
 | 
			
		||||
 | 
			
		||||
#include <vitamtp.h>
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QSqlDatabase>
 | 
			
		||||
#include <QSqlError>
 | 
			
		||||
 | 
			
		||||
#define OBJECT_FILE 0x10000000
 | 
			
		||||
#define OBJECT_FOLDER 0x20000000
 | 
			
		||||
#define OBJECT_SPECIAL 0x40000000
 | 
			
		||||
 | 
			
		||||
#define OBJECT_MUSIC 0x00000100
 | 
			
		||||
#define OBJECT_PHOTO 0x00000200
 | 
			
		||||
#define OBJECT_VIDEO 0x00000400
 | 
			
		||||
 | 
			
		||||
#define OBJECT_ALBUM 0x00000002
 | 
			
		||||
#define OBJECT_ARTIST 0x00000005
 | 
			
		||||
#define OBJECT_ALBUM_ARTIST 0x00000008
 | 
			
		||||
#define OBJECT_GENRE 0x0000000B
 | 
			
		||||
 | 
			
		||||
#define OBJECT_SAVEDATA 0x00040000
 | 
			
		||||
#define OBJECT_SAVEDATA_FILE 0x00000002
 | 
			
		||||
 | 
			
		||||
class SQLiteDB : public QObject
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
public:
 | 
			
		||||
    explicit SQLiteDB(QObject *parent = 0);
 | 
			
		||||
    ~SQLiteDB();
 | 
			
		||||
 | 
			
		||||
    bool open();
 | 
			
		||||
    int create();
 | 
			
		||||
    void remove();
 | 
			
		||||
    bool initialize();
 | 
			
		||||
    QSqlError getLastError();
 | 
			
		||||
 | 
			
		||||
    int getPathId(const QString &path);
 | 
			
		||||
    QString getPathFromId(int ohfi);
 | 
			
		||||
    bool updateSize(int ohfi, quint64 size);
 | 
			
		||||
    bool deleteEntry(int ohfi);
 | 
			
		||||
    bool deleteEntry(const QString &path);
 | 
			
		||||
    uint insertObjectEntry(const char *title, int type);
 | 
			
		||||
    bool insertSourceEntry(uint object_id, const QString &path);
 | 
			
		||||
    uint insertMusicEntry(const QString &path, int type, int parent);
 | 
			
		||||
    uint insertVideoEntry(const QString &path, int type, int parent);
 | 
			
		||||
    uint insertPhotoEntry(const QString &path, int type, int parent);
 | 
			
		||||
    uint insertSavedataEntry(const QString &path, int type, int parent);
 | 
			
		||||
 | 
			
		||||
private:    
 | 
			
		||||
    int recursiveScanRootDirectory(const QString &base_path, int parent, int type);
 | 
			
		||||
    uint insertDirectoryEntry(const QString &path, int type, int parent);
 | 
			
		||||
    int checkFileType(const QString path, int ohfi_root);
 | 
			
		||||
    bool updateAdjacencyList(int ohfi, int parent);
 | 
			
		||||
 | 
			
		||||
    QString uuid;
 | 
			
		||||
    QSqlDatabase db;
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // SQLITEDB_H
 | 
			
		||||
		Reference in New Issue
	
	Block a user