diff --git a/qcma.pro b/qcma.pro
index 84cf31c..4adebd9 100644
--- a/qcma.pro
+++ b/qcma.pro
@@ -20,7 +20,7 @@ SOURCES += src/main.cpp \
src/capability.cpp \
src/cmaobject.cpp \
src/cmarootobject.cpp \
- src/utils.cpp \
+ src/cmautils.cpp \
src/mainwidget.cpp \
src/singleapplication.cpp \
src/sforeader.cpp \
@@ -34,20 +34,20 @@ SOURCES += src/main.cpp \
src/sqlitedb.cpp \
src/httpdownloader.cpp \
src/qlistdb.cpp \
+ src/database.cpp \
# forms
src/forms/backupitem.cpp \
src/forms/backupmanagerform.cpp \
src/forms/configwidget.cpp \
src/forms/confirmdialog.cpp \
src/forms/pinform.cpp \
- src/forms/progressform.cpp \
- src/database.cpp
+ src/forms/progressform.cpp
HEADERS += \
src/capability.h \
src/cmaobject.h \
src/cmarootobject.h \
- src/utils.h \
+ src/cmautils.h \
src/mainwidget.h \
src/singleapplication.h \
src/sforeader.h \
@@ -61,14 +61,14 @@ HEADERS += \
src/sqlitedb.h \
src/httpdownloader.h \
src/qlistdb.h \
+ src/database.h \
# forms
src/forms/backupitem.h \
src/forms/backupmanagerform.h \
src/forms/configwidget.h \
src/forms/confirmdialog.h \
src/forms/pinform.h \
- src/forms/progressform.h \
- src/database.h
+ src/forms/progressform.h
FORMS += \
src/forms/configwidget.ui \
diff --git a/src/avdecoder.cpp b/src/avdecoder.cpp
index bcaf1d0..c5b0142 100644
--- a/src/avdecoder.cpp
+++ b/src/avdecoder.cpp
@@ -17,7 +17,7 @@
* along with this program. If not, see .
*/
-#include "utils.h"
+#include "cmautils.h"
#include "avdecoder.h"
#include "database.h"
diff --git a/src/clientmanager.cpp b/src/clientmanager.cpp
index 395fb47..7cce9d9 100644
--- a/src/clientmanager.cpp
+++ b/src/clientmanager.cpp
@@ -19,7 +19,7 @@
#include "clientmanager.h"
#include "cmaclient.h"
-#include "utils.h"
+#include "cmautils.h"
#include "forms/progressform.h"
#include
@@ -122,13 +122,12 @@ void ClientManager::start()
void ClientManager::refreshDatabase()
{
- bool prepared;
- if(!m_db->reload(prepared)) {
- if(prepared) {
- emit messageSent(tr("Cannot refresh the database while is in use"));
- } else {
- emit messageSent(tr("No PS Vita system has been registered"));
- }
+ if(m_db->load()) {
+ return;
+ }
+
+ if(!m_db->rescan()) {
+ emit messageSent(tr("No PS Vita system has been registered"));
} else {
progress.showDelayed(1000);
}
diff --git a/src/cmaclient.cpp b/src/cmaclient.cpp
index 1a4b23f..b843230 100644
--- a/src/cmaclient.cpp
+++ b/src/cmaclient.cpp
@@ -21,7 +21,7 @@
#include "capability.h"
#include "avdecoder.h"
#include "cmaevent.h"
-#include "utils.h"
+#include "cmautils.h"
#include
#include
diff --git a/src/cmaevent.cpp b/src/cmaevent.cpp
index d9c8f08..d504b67 100644
--- a/src/cmaevent.cpp
+++ b/src/cmaevent.cpp
@@ -18,7 +18,7 @@
*/
#include "cmaevent.h"
-#include "utils.h"
+#include "cmautils.h"
#include
#include
@@ -179,7 +179,8 @@ quint16 CmaEvent::processAllObjects(metadata_t &parent_metadata, quint32 handle)
m_db->deleteEntry(ohfi);
}
- QDir dir(m_db->getAbsolutePath(parent_metadata.ohfi));
+ QString fullpath = m_db->getAbsolutePath(parent_metadata.ohfi);
+ QDir dir(fullpath);
if(dataType & Folder) {
if(!dir.mkpath(name)) {
@@ -205,12 +206,10 @@ quint16 CmaEvent::processAllObjects(metadata_t &parent_metadata, quint32 handle)
}
}
- QFileInfo info(dir, name);
- int new_ohfi = m_db->insertObjectEntry(info.absoluteFilePath(), parent_metadata.ohfi);
+ int new_ohfi = m_db->insertObjectEntry(fullpath, name, parent_metadata.ohfi);
+ qDebug("Added object %s with OHFI %i to database", name, new_ohfi);
free(name);
- qDebug() << QString("Added object %1 with OHFI %2 to database").arg(info.absoluteFilePath(), QString::number(new_ohfi));
-
if(dataType & Folder) {
metadata_t folder_metadata;
m_db->getObjectMetadata(new_ohfi, folder_metadata);
@@ -389,6 +388,7 @@ void CmaEvent::vitaEventSendObjectMetadata(vita_event_t *event, int eventId)
} else {
VitaMTP_ReportResult(device, eventId, PTP_RC_OK);
}
+ m_db->freeMetadata(meta);
}
void CmaEvent::vitaEventSendObject(vita_event_t *event, int eventId)
@@ -470,6 +470,8 @@ void CmaEvent::vitaEventSendObject(vita_event_t *event, int eventId)
} while(metadata && metadata->ohfiParent >= OHFI_BASE_VALUE); // get everything under this "folder"
+ m_db->freeMetadata(start);
+
VitaMTP_ReportResultWithParam(device, eventId, PTP_RC_OK, handle);
VitaMTP_ReportResult(device, eventId, PTP_RC_VITA_Invalid_Data); // TODO: Send thumbnail
@@ -562,13 +564,14 @@ void CmaEvent::vitaEventSendObjectStatus(vita_event_t *event, int eventId)
QMutexLocker locker(&m_db->mutex);
+ qDebug("Checking for path %s under ohfi %i", objectstatus.title, objectstatus.ohfiRoot);
int ohfi = m_db->getPathId(objectstatus.title, objectstatus.ohfiRoot);
if(ohfi == 0) { // not in database, don't return metadata
qDebug("Object %s not in database (OHFI: %i). Sending OK response for non-existence", objectstatus.title, objectstatus.ohfiRoot);
VitaMTP_ReportResult(device, eventId, PTP_RC_OK);
} else {
- metadata_t metadata;
+ metadata_t metadata = metadata_t();
m_db->getObjectMetadata(ohfi, metadata);
metadata.next_metadata = NULL;
qDebug("Sending metadata for OHFI %d", ohfi);
@@ -780,7 +783,7 @@ void CmaEvent::vitaEventOperateObject(vita_event_t *event, int eventId)
qWarning("Unable to create temporary folder: %s", operateobject.title);
VitaMTP_ReportResult(device, eventId, PTP_RC_VITA_Failed_Operate_Object);
} else {
- int new_ohfi = m_db->insertObjectEntry(QDir(dir).absoluteFilePath(operateobject.title), operateobject.ohfi);
+ int new_ohfi = m_db->insertObjectEntry(fullpath, operateobject.title, operateobject.ohfi);
qDebug("Created folder %s with OHFI %d", operateobject.title, new_ohfi);
VitaMTP_ReportResultWithParam(device, eventId, PTP_RC_OK, new_ohfi);
}
@@ -794,7 +797,7 @@ void CmaEvent::vitaEventOperateObject(vita_event_t *event, int eventId)
qWarning("Unable to create temporary file: %s", operateobject.title);
VitaMTP_ReportResult(device, eventId, PTP_RC_VITA_Failed_Operate_Object);
} else {
- int new_ohfi = m_db->insertObjectEntry(file.fileName(), operateobject.ohfi);
+ int new_ohfi = m_db->insertObjectEntry(fullpath, operateobject.title, operateobject.ohfi);
//qDebug("Created file %s with OHFI %d under parent %s", newobj->metadata.path, new_ohfi, root->metadata.path);
VitaMTP_ReportResultWithParam(device, eventId, PTP_RC_OK, new_ohfi);
}
diff --git a/src/cmaobject.cpp b/src/cmaobject.cpp
index 68856a9..6e0a3fc 100644
--- a/src/cmaobject.cpp
+++ b/src/cmaobject.cpp
@@ -21,7 +21,7 @@
#include "sforeader.h"
#include "avdecoder.h"
#include "database.h"
-#include "utils.h"
+#include "cmautils.h"
#include
#include
diff --git a/src/utils.cpp b/src/cmautils.cpp
similarity index 98%
rename from src/utils.cpp
rename to src/cmautils.cpp
index 3e1680b..0275180 100644
--- a/src/utils.cpp
+++ b/src/cmautils.cpp
@@ -17,7 +17,7 @@
* along with this program. If not, see .
*/
-#include "utils.h"
+#include "cmautils.h"
#include "avdecoder.h"
#include
@@ -162,7 +162,7 @@ QByteArray getThumbnail(const QString &path, DataType type, metadata_t *metadata
return data;
}
-QString readable_size(quint64 size, bool use_gib)
+QString readable_size(qint64 size, bool use_gib)
{
QStringList list;
list << "KiB" << "MiB";
diff --git a/src/utils.h b/src/cmautils.h
similarity index 96%
rename from src/utils.h
rename to src/cmautils.h
index 35f690f..a69af6d 100644
--- a/src/utils.h
+++ b/src/cmautils.h
@@ -46,7 +46,7 @@ public:
#endif
bool removeRecursively(const QString &path);
-QString readable_size(quint64 size, bool use_gib = false);
+QString readable_size(qint64 size, bool use_gib = false);
bool getDiskSpace(const QString &dir, quint64 *free, quint64 *total);
QByteArray getThumbnail(const QString &path, DataType type, metadata_t *metadata);
diff --git a/src/database.cpp b/src/database.cpp
index c9785c2..2d415c9 100644
--- a/src/database.cpp
+++ b/src/database.cpp
@@ -2,6 +2,7 @@
#include "avdecoder.h"
#include
+#include
const file_type audio_list[] = {
{"mp3", FILE_FORMAT_MP3, CODEC_TYPE_MP3},
@@ -28,6 +29,33 @@ Database::Database(QObject *parent) :
mutex(QMutex::Recursive)
{
}
+#include
+void Database::process()
+{
+ qDebug("Starting database_thread: 0x%016" PRIxPTR, (uintptr_t)QThread::currentThreadId());
+ clear();
+ cancel_operation = false;
+ int count = create();
+ cancel_operation = false;
+ qDebug("Added %i entries to the database", count);
+ if(count < 0) {
+ clear();
+ }
+ emit updated(count);
+ mutex.unlock();
+}
+
+void Database::cancelOperation()
+{
+ QMutexLocker locker(&cancel);
+ cancel_operation = true;
+}
+
+bool Database::continueOperation()
+{
+ QMutexLocker locker(&cancel);
+ return !cancel_operation;
+}
int Database::checkFileType(const QString path, int ohfi_root)
{
diff --git a/src/database.h b/src/database.h
index 0f1851f..95b98f9 100644
--- a/src/database.h
+++ b/src/database.h
@@ -43,6 +43,11 @@ class Database : public QObject
Q_OBJECT
public:
explicit Database(QObject *parent = 0);
+
+ virtual bool load() = 0;
+ virtual bool rescan() = 0;
+ virtual void setUUID(const QString &uuid) = 0;
+
virtual int childObjectCount(int parent_ohfi) = 0;
virtual bool deleteEntry(int ohfi, int root_ohfi = 0) = 0;
virtual QString getAbsolutePath(int ohfi) = 0;
@@ -51,14 +56,12 @@ public:
virtual int getObjectMetadatas(int parent_ohfi, metadata_t **metadata, int index = 0, int max_number = 0) = 0;
virtual qint64 getObjectSize(int ohfi) = 0;
virtual int getPathId(const char *name, int ohfi) = 0;
- virtual int insertObjectEntry(const QString &path, int parent_ohfi) = 0;
+ virtual int insertObjectEntry(const QString &path, const QString &name, int parent_ohfi) = 0;
virtual bool renameObject(int ohfi, const QString &name) = 0;
virtual void setObjectSize(int ohfi, qint64 size) = 0;
virtual int getParentId(int ohfi) = 0;
virtual int getRootId(int ohfi) = 0;
-
- virtual bool reload(bool &prepared) = 0;
- virtual void setUUID(const QString uuid) = 0;
+ virtual void freeMetadata(metadata_t *metadata) = 0;
static int checkFileType(const QString path, int ohfi_root);
static void loadMusicMetadata(const QString &path, metadata_t &metadata);
@@ -66,6 +69,29 @@ public:
static void loadVideoMetadata(const QString &path, metadata_t &metadata);
QMutex mutex;
+
+protected:
+ bool continueOperation();
+
+private:
+
+ virtual void clear() = 0;
+ virtual int create() = 0;
+
+ // control variables
+ QMutex cancel;
+ bool cancel_operation;
+
+signals:
+ void fileAdded(QString);
+ void directoryAdded(QString);
+ void updated(int);
+
+protected slots:
+ void process();
+
+public slots:
+ void cancelOperation();
};
#endif // DATABASE_H
diff --git a/src/forms/backupitem.cpp b/src/forms/backupitem.cpp
index 3cb6198..8257ffb 100644
--- a/src/forms/backupitem.cpp
+++ b/src/forms/backupitem.cpp
@@ -19,7 +19,7 @@
#include "backupitem.h"
#include "ui_backupitem.h"
-#include "utils.h"
+#include "cmautils.h"
#include "dds.h"
#include
diff --git a/src/forms/backupmanagerform.cpp b/src/forms/backupmanagerform.cpp
index e8ec4e3..3f83244 100644
--- a/src/forms/backupmanagerform.cpp
+++ b/src/forms/backupmanagerform.cpp
@@ -22,7 +22,7 @@
#include "cmaobject.h"
#include "sforeader.h"
#include "confirmdialog.h"
-#include "utils.h"
+#include "cmautils.h"
#include "filterlineedit.h"
#include
@@ -83,7 +83,7 @@ void BackupManagerForm::removeEntry(BackupItem *item)
}
}
-void BackupManagerForm::setBackupUsage(quint64 size)
+void BackupManagerForm::setBackupUsage(qint64 size)
{
ui->usageLabel->setText(tr("Backup disk usage: %1").arg(readable_size(size, true)));
}
@@ -163,10 +163,12 @@ void BackupManagerForm::loadBackupListing(int index)
#else
horiz_header->setResizeMode(QHeaderView::Stretch);
#endif
- setBackupUsage(m_db->getObjectSize(ohfi));
+ qint64 backup_size = m_db->getObjectSize(ohfi);
+ setBackupUsage(backup_size);
QString path = m_db->getAbsolutePath(ohfi);
QList item_list;
+ metadata_t *first = meta;
while(meta) {
QString base_path = path + QDir::separator() + meta->name;
QString parent_path = sys_dir ? base_path + QDir::separator() + "sce_sys" : base_path;
@@ -215,6 +217,8 @@ void BackupManagerForm::loadBackupListing(int index)
meta = meta->next_metadata;
}
+ m_db->freeMetadata(first);
+
qSort(item_list.begin(), item_list.end(), BackupItem::lessThan);
int row;
diff --git a/src/forms/backupmanagerform.h b/src/forms/backupmanagerform.h
index 2290fbb..2613df3 100644
--- a/src/forms/backupmanagerform.h
+++ b/src/forms/backupmanagerform.h
@@ -41,7 +41,7 @@ public:
private:
void setupForm();
- void setBackupUsage(quint64 size);
+ void setBackupUsage(qint64 size);
Ui::BackupManagerForm *ui;
diff --git a/src/mainwidget.cpp b/src/mainwidget.cpp
index 1e8e494..e6c178e 100644
--- a/src/mainwidget.cpp
+++ b/src/mainwidget.cpp
@@ -19,7 +19,7 @@
#include "mainwidget.h"
#include "cmaclient.h"
-#include "utils.h"
+#include "cmautils.h"
#include "qlistdb.h"
#include "sqlitedb.h"
@@ -123,7 +123,7 @@ void MainWidget::prepareApplication()
if(QSettings().value("useMemoryStorage", true).toBool()) {
db = new QListDB();
} else {
- db = NULL; // new SQLiteDB();
+ db = new SQLiteDB();
}
configForm = new ConfigWidget(this);
@@ -267,4 +267,5 @@ MainWidget::~MainWidget()
#ifndef ENABLE_KDE_NOTIFIER
trayIcon->hide();
#endif
+ delete db;
}
diff --git a/src/qlistdb.cpp b/src/qlistdb.cpp
index 8b9aa01..b698551 100644
--- a/src/qlistdb.cpp
+++ b/src/qlistdb.cpp
@@ -17,7 +17,7 @@
* along with this program. If not, see .
*/
-#include "utils.h"
+#include "cmautils.h"
#include "qlistdb.h"
#include "cmaobject.h"
@@ -34,8 +34,8 @@ QListDB::QListDB(QObject *parent) :
QString uuid = QSettings().value("lastAccountId", "ffffffffffffffff").toString();
CMARootObject::uuid = uuid;
thread = new QThread();
- timer = new QTimer();
moveToThread(thread);
+ timer = new QTimer();
thread->start();
timer->setInterval(0);
@@ -45,7 +45,7 @@ QListDB::QListDB(QObject *parent) :
QListDB::~QListDB()
{
- destroy();
+ clear();
timer->stop();
delete timer;
thread->quit();
@@ -53,53 +53,41 @@ QListDB::~QListDB()
delete thread;
}
-void QListDB::setUUID(const QString uuid)
+void QListDB::setUUID(const QString &uuid)
{
CMARootObject::uuid = uuid;
QSettings().setValue("lastAccountId", uuid);
}
-bool QListDB::reload(bool &prepared)
+bool QListDB::load()
{
- if(mutex.tryLock()) {
+ // not implemented
+ return false;
+}
+
+bool QListDB::rescan()
+{
+ if(mutex.tryLock(1000)) {
if(CMARootObject::uuid != "ffffffffffffffff") {
timer->start();
- prepared = true;
+ return true;
} else {
mutex.unlock();
- prepared = false;
return false;
}
- return true;
- } else {
- return false;
}
+ return false;
}
-void QListDB::process()
+void QListDB::clear()
{
- destroy();
- cancel_operation = false;
- int count = create();
- cancel_operation = false;
- qDebug("Added %i entries to the database", count);
- if(count < 0) {
- destroy();
+ for(map_list::iterator root = object_list.begin(); root != object_list.end(); ++root) {
+ CMARootObject *first = static_cast((*root).takeFirst());
+ delete first;
+ qDeleteAll(*root);
}
- emit updated(count);
- mutex.unlock();
-}
-void QListDB::cancelOperation()
-{
- QMutexLocker locker(&cancel);
- cancel_operation = true;
-}
-
-bool QListDB::continueOperation()
-{
- QMutexLocker locker(&cancel);
- return !cancel_operation;
+ object_list.clear();
}
int QListDB::create()
@@ -147,6 +135,8 @@ int QListDB::create()
return -1;
}
+ qDebug("Added %i objects for OHFI %#02X", dir_count, ohfi_array[i]);
+
total_objects += dir_count;
object_list[ohfi_array[i]] = list;
}
@@ -236,19 +226,6 @@ int QListDB::recursiveScanRootDirectory(root_list &list, CMAObject *parent, int
return total_objects;
}
-void QListDB::destroy()
-{
- //QMutexLocker locker(&mutex);
-
- for(map_list::iterator root = object_list.begin(); root != object_list.end(); ++root) {
- CMARootObject *first = static_cast((*root).takeFirst());
- delete first;
- qDeleteAll(*root);
- }
-
- object_list.clear();
-}
-
bool QListDB::removeInternal(root_list &list, int ohfi)
{
bool found = false;
@@ -487,7 +464,7 @@ int QListDB::getPathId(const char *name, int ohfi)
return 0;
}
-int QListDB::insertObjectEntry(const QString &path, int parent_ohfi)
+int QListDB::insertObjectEntry(const QString &path, const QString &name, int parent_ohfi)
{
QMutexLocker locker(&mutex);
@@ -505,7 +482,8 @@ int QListDB::insertObjectEntry(const QString &path, int parent_ohfi)
parent_obj = parent_obj->parent;
}
- newobj->initObject(path, parent_obj->metadata.dataType);
+ QFileInfo info(path, name);
+ newobj->initObject(info, parent_obj->metadata.dataType);
cat_list->append(newobj);
return newobj->metadata.ohfi;
}
diff --git a/src/qlistdb.h b/src/qlistdb.h
index 9c6298f..da45c86 100644
--- a/src/qlistdb.h
+++ b/src/qlistdb.h
@@ -38,8 +38,13 @@ public:
explicit QListDB(QObject *parent = 0);
~QListDB();
+ bool load();
+ bool rescan();
+ void close();
+ void clear();
+
bool reload(bool &prepared);
- void setUUID(const QString uuid);
+ void setUUID(const QString &uuid);
int childObjectCount(int parent_ohfi);
bool deleteEntry(int ohfi, int root_ohfi = 0);
@@ -51,9 +56,12 @@ public:
int getPathId(const char *name, int ohfi);
QString getRelativePath(int ohfi);
int getRootId(int ohfi);
- int insertObjectEntry(const QString &path, int parent_ohfi);
+ int insertObjectEntry(const QString &path, const QString &name, int parent_ohfi);
bool renameObject(int ohfi, const QString &name);
void setObjectSize(int ohfi, qint64 size);
+ void freeMetadata(metadata_t *metadata) {
+ Q_UNUSED(metadata);
+ }
private:
typedef struct {
@@ -65,7 +73,6 @@ private:
typedef QMap map_list;
int create();
- void destroy();
int scanRootDirectory(root_list &list,int ohfi_type);
int recursiveScanRootDirectory(root_list &list, CMAObject *parent, int ohfi_type);
bool hasFilter(const CMARootObject *object,int ohfi);
@@ -78,26 +85,10 @@ private:
bool find(int ohfi, find_data &data);
int acceptFilteredObject(const CMAObject *parent, const CMAObject *current, int type);
CMAObject *ohfiToObject(int ohfi);
- bool continueOperation();
-
- // control variables
- QMutex cancel;
- bool cancel_operation;
QTimer *timer;
QThread *thread;
map_list object_list;
-
-signals:
- void fileAdded(QString);
- void directoryAdded(QString);
- void updated(int);
-
-protected slots:
- void process();
-
-public slots:
- void cancelOperation();
};
#endif // QLISTDB_H
diff --git a/src/sqlitedb.cpp b/src/sqlitedb.cpp
index 192a6fe..162dc04 100644
--- a/src/sqlitedb.cpp
+++ b/src/sqlitedb.cpp
@@ -1,4 +1,23 @@
-#include "utils.h"
+/*
+ * QCMA: Cross-platform content manager assistant for the PS Vita
+ *
+ * Copyright (C) 2014 Codestation
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see .
+ */
+
+#include "cmautils.h"
#include "sqlitedb.h"
#include "sforeader.h"
#include "avdecoder.h"
@@ -26,13 +45,14 @@ static const char create_adjacent[] = "CREATE TABLE IF NOT EXISTS adjacent_objec
static const char create_obj_node[] = "CREATE TABLE IF NOT EXISTS object_node ("
"object_id INTEGER PRIMARY KEY AUTOINCREMENT,"
"type INTEGER NOT NULL,"
+ "data_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),"
+ "path TEXT NOT NULL CHECK (LENGTH(path) > 0),"
"size INTEGER,"
"date_created TIMESTAMP,"
"date_modified TIMESTAMP)";
@@ -114,19 +134,23 @@ static const char *trigger_list[] = {
create_trigger_node, create_trigger_adjins, create_trigger_adjdel
};
+static const int ohfi_array[] = { VITA_OHFI_MUSIC, VITA_OHFI_PHOTO, VITA_OHFI_VIDEO,
+ VITA_OHFI_BACKUP, VITA_OHFI_VITAAPP, VITA_OHFI_PSPAPP,
+ VITA_OHFI_PSPSAVE, VITA_OHFI_PSXAPP, VITA_OHFI_PSMAPP
+ };
+
SQLiteDB::SQLiteDB(QObject *parent) :
Database(parent)
{
uuid = QSettings().value("lastAccountId", "ffffffffffffffff").toString();
-}
+ thread = new QThread();
+ moveToThread(thread);
+ timer = new QTimer();
+ thread->start();
+ timer->setInterval(0);
+ timer->setSingleShot(true);
+ connect(timer, SIGNAL(timeout()), this, SLOT(process()));
-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();
@@ -134,24 +158,66 @@ bool SQLiteDB::open()
db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(db_path + QDir::separator() + "qcma.sqlite");
-
- return db.open();
}
-void SQLiteDB::remove()
+SQLiteDB::~SQLiteDB()
{
+ db.close();
+ timer->stop();
+ delete timer;
+ thread->quit();
+ thread->wait();
+ delete thread;
+}
+
+
+void SQLiteDB::setUUID(const QString &uuid)
+{
+ this->uuid = uuid;
+ QSettings().setValue("lastAccountId", uuid);
+}
+
+bool SQLiteDB::load()
+{
+ bool success = false;
+
+ if(db.open()) {
+ qDebug() << "Database created/registered";
+ success = !initialize();
+ } else {
+ const QSqlError error = db.lastError();
+ qWarning() << "Error opening connection to the database:" << error.text();
+ }
+
+ return success;
+}
+
+bool SQLiteDB::rescan()
+{
+ if(mutex.tryLock(1000)) {
+ if(uuid != "ffffffffffffffff") {
+ timer->start();
+ return true;
+ } else {
+ mutex.unlock();
+ return false;
+ }
+ }
+ return false;
+}
+
+void SQLiteDB::clear()
+{
+ db.close();
+ //QSqlDatabase::removeDatabase("QSQLITE");
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();
+ load();
}
bool SQLiteDB::initialize()
{
- if (!db.isOpen()) {
- return false;
- }
QSqlQuery query;
for(unsigned int i = 0; i < sizeof(table_list) / sizeof(const char *); i++) {
@@ -169,7 +235,7 @@ bool SQLiteDB::initialize()
}
// force object_id to start at 256
- if(query.exec("INSERT INTO object_node (object_id, type) VALUES (255, 0)")) {
+ if(query.exec("INSERT INTO object_node (object_id, data_type, type) VALUES (255, 0, 0)")) {
query.exec("DELETE FROM object_node WHERE object_id = 255");
}
return true;
@@ -184,97 +250,160 @@ 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;
-
+ db.transaction();
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:
- base_path = settings.value("appsPath").toString() + QDir::separator() + "SYSTEM" + QDir::separator() + uuid;
- break;
- case VITA_OHFI_VITAAPP:
- base_path = settings.value("appsPath").toString() + QDir::separator() + "APP" + QDir::separator() + uuid;
- break;
- case VITA_OHFI_PSPAPP:
- 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:
- base_path = settings.value("appsPath").toString() + QDir::separator() + "PSGAME" + QDir::separator() + uuid;
- break;
- case VITA_OHFI_PSMAPP:
- base_path = settings.value("appsPath").toString() + QDir::separator() + "PSM" + QDir::separator() + uuid;
- break;
- }
-
- int dir_count = recursiveScanRootDirectory(base_path, ohfi_array[i], ohfi_array[i]);
+ QString base_path = getBasePath(ohfi_array[i]);
+ int dir_count = recursiveScanRootDirectory(base_path, NULL, ohfi_array[i], ohfi_array[i]);
if(dir_count < 0) {
+ db.rollback();
return -1;
}
+
+ //qDebug("Added %i objects for OHFI %#02X", dir_count, ohfi_array[i]);
+
total_objects += dir_count;
}
+ db.commit();
return total_objects;
}
-int SQLiteDB::recursiveScanRootDirectory(const QString &base_path, int parent, int parent_type)
+QString SQLiteDB::getBasePath(int root_ohfi)
+{
+ QString base_path;
+ QSettings settings;
+
+ switch(root_ohfi) {
+ 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:
+ base_path = settings.value("appsPath").toString() + "/SYSTEM/" + uuid;
+ break;
+ case VITA_OHFI_VITAAPP:
+ base_path = settings.value("appsPath").toString() + "/APP/" + uuid;
+ break;
+ case VITA_OHFI_PSPAPP:
+ base_path = settings.value("appsPath").toString() + "/PGAME/" + uuid;
+ break;
+ case VITA_OHFI_PSPSAVE:
+ base_path = settings.value("appsPath").toString() + "/PSAVEDATA/" + uuid;
+ break;
+ case VITA_OHFI_PSXAPP:
+ base_path = settings.value("appsPath").toString() + "/PSGAME/" + uuid;
+ break;
+ case VITA_OHFI_PSMAPP:
+ base_path = settings.value("appsPath").toString() + "/PSM/" + uuid;
+ break;
+ }
+ return base_path;
+}
+
+int SQLiteDB::recursiveScanRootDirectory(const QString &base_path, const QString &rel_path, int parent_ohfi, int root_ohfi)
{
int total_objects = 0;
- QDir dir(base_path);
+ QDir dir(base_path + "/" + rel_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;
- case VITA_OHFI_VITAAPP:
- case VITA_OHFI_PSPAPP:
- case VITA_OHFI_PSXAPP:
- case VITA_OHFI_PSMAPP:
- case VITA_OHFI_BACKUP:
- insertApplicationEntry(info.absoluteFilePath(), OBJECT_APPLICATION | (parent_type & ~OBJECT_FOLDER), parent, parent_type);
- }
- total_objects++;
+ if(!continueOperation()) {
+ return -1;
+ }
+
+ //qDebug() << "Processing " << info.fileName();
+
+ QString rel_name = rel_path.isNull() ? info.fileName() : rel_path + "/" + info.fileName();
+
+ int ohfi = insertObjectEntryInternal(base_path, rel_name, parent_ohfi, root_ohfi);
+
+ if(ohfi > 0) {
+ // update progress dialog
+ if(info.isDir()) {
+ emit directoryAdded(base_path + "/" + rel_name);
+ total_objects += recursiveScanRootDirectory(base_path, rel_name, ohfi, root_ohfi);
+ qint64 dirsize = getChildenTotalSize(ohfi);
+ setObjectSize(ohfi, dirsize);
+ } else if(info.isFile()) {
+ emit fileAdded(info.fileName());
+ total_objects++;
+ }
}
}
return total_objects;
}
+int SQLiteDB::insertObjectEntry(const QString &path, const QString &name, int parent_ohfi)
+{
+ int ohfi;
+ int type;
+
+ if((type = getObjectType(parent_ohfi)) == 0) {
+ return 0;
+ }
+ db.transaction();
+ if((ohfi = insertObjectEntryInternal(path, name, parent_ohfi, type)) == 0) {
+ db.rollback();
+ }
+ db.commit();
+
+ return ohfi;
+}
+
+int SQLiteDB::insertObjectEntryInternal(const QString &path, const QString &name, int parent_ohfi, int root_ohfi)
+{
+ int ohfi;
+ QFileInfo info(path, name);
+
+ if(info.isDir()) {
+ ohfi = insertDefaultEntry(path, name, info.fileName(), parent_ohfi, Folder);
+ } else {
+ ohfi = insertFileEntry(path, name, parent_ohfi, root_ohfi);
+ }
+
+ return ohfi;
+}
+
+int SQLiteDB::insertFileEntry(const QString &path, const QString &name, int parent_ohfi, int root_ohfi)
+{
+ int ohfi = 0;
+
+ switch(root_ohfi) {
+ case VITA_OHFI_MUSIC:
+ ohfi = insertMusicEntry(path, name, parent_ohfi, File | Music);
+ break;
+ case VITA_OHFI_PHOTO:
+ ohfi = insertPhotoEntry(path, name, parent_ohfi, File | Photo);
+ break;
+ case VITA_OHFI_VIDEO:
+ ohfi = insertVideoEntry(path, name, parent_ohfi, File | Video);
+ break;
+ case VITA_OHFI_PSPSAVE:
+ ohfi = insertSavedataEntry(path, name, parent_ohfi, File | SaveData);
+ break;
+ case VITA_OHFI_VITAAPP:
+ case VITA_OHFI_PSPAPP:
+ case VITA_OHFI_PSXAPP:
+ case VITA_OHFI_PSMAPP:
+ case VITA_OHFI_BACKUP:
+ ohfi = insertApplicationEntry(path, name, parent_ohfi, File | App, root_ohfi);
+ break;
+ default:
+ qFatal("Invalid parent type");
+ }
+
+ return ohfi;
+}
+
int SQLiteDB::getPathId(const QString &path)
{
QSqlQuery query(QString("SELECT object_id from sources WHERE path = %1").arg(path));
@@ -313,12 +442,6 @@ bool SQLiteDB::deleteEntry(int ohfi)
return ret;
}
-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;
@@ -328,8 +451,6 @@ bool SQLiteDB::updateAdjacencyList(int ohfi, int parent)
if(query.exec() && query.next()) {
return true;
- } else {
- qDebug() << query.lastError();
}
query.prepare("INSERT INTO adjacent_objects (parent_id, child_id)"
@@ -343,67 +464,61 @@ bool SQLiteDB::updateAdjacencyList(int ohfi, int parent)
return ret;
}
-uint SQLiteDB::insertDirectoryEntry(const QString &path, int type, int parent)
+int SQLiteDB::insertDefaultEntry(const QString &path, const QString &name, const QString &title, int parent, int type)
{
- uint ohfi;
- db.transaction();
- QString dirname = QFileInfo(path).fileName();
+ int ohfi = 0;
- if((ohfi = insertObjectEntry(dirname.toUtf8().constData(), type)) == 0) {
- db.rollback();
+ if((ohfi = insertNodeEntry(title, VITA_DIR_TYPE_MASK_REGULAR, type)) == 0) {
return 0;
}
if(parent && !updateAdjacencyList(ohfi, parent)) {
- db.rollback();
return 0;
}
- if(!insertSourceEntry(ohfi, path)) {
- db.rollback();
+ if(!name.isNull() && !insertSourceEntry(ohfi, path, name)) {
return 0;
}
- db.commit();
return ohfi;
}
-uint SQLiteDB::insertObjectEntry(const char *title, int type)
+int SQLiteDB::insertNodeEntry(const QString &title, int type, int data_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.prepare("INSERT INTO object_node (type, data_type, title) VALUES (:type, :data_type, :title)");
query.bindValue(0, type);
- query.bindValue(1, title);
+ query.bindValue(1, data_type);
+ query.bindValue(2, title);
if(!query.exec() || !query.exec("SELECT last_insert_rowid()") || !query.next()) {
qDebug() << query.lastError();
return 0;
}
- //}
return query.value(0).toInt();
}
-bool SQLiteDB::insertSourceEntry(uint object_id, const QString &path)
+bool SQLiteDB::insertSourceEntry(uint object_id, const QString &path, const QString &name)
{
- qint64 size;
- uint date_created, date_modified;
+ QVariant size, date_created, date_modified;
- QFileInfo info(path);
- size = info.size();
- date_created = info.created().toTime_t();
- date_modified = info.lastModified().toTime_t();
+ QFileInfo info(path, name);
+ if(info.isFile()) {
+ size = QVariant(info.size());
+ date_created = QVariant(info.created().toTime_t());
+ } else {
+ size = QVariant(QVariant::LongLong);
+ date_created = QVariant(QVariant::UInt);
+ }
+
+ date_modified = QVariant(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(1, name);
query.bindValue(2, size);
query.bindValue(3, date_created);
query.bindValue(4, date_modified);
@@ -414,22 +529,22 @@ bool SQLiteDB::insertSourceEntry(uint object_id, const QString &path)
return ret;
}
-uint SQLiteDB::insertMusicEntry(const QString &path, int type, int parent)
+uint SQLiteDB::insertMusicEntry(const QString &path, const QString &name, int parent, int type)
{
bool ok;
- uint ohfi;
+ int 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, VITA_OHFI_MUSIC);
+ int file_type = checkFileType(name, VITA_OHFI_MUSIC);
if(file_type < 0) {
- qDebug() << "Excluding from database:" << path;
+ //qDebug() << "Excluding from database:" << path;
return 0;
}
- if(!decoder.open(path)) {
+ if(!decoder.open(path + "/" + name)) {
return 0;
}
@@ -456,30 +571,16 @@ uint SQLiteDB::insertMusicEntry(const QString &path, int type, int parent)
file_format = audio_list[file_type].file_format;
audio_codec = audio_list[file_type].file_codec;
- QByteArray basename = QFileInfo(path).baseName().toUtf8();
+ QByteArray basename = QFileInfo(name).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();
+ if((ohfi = insertDefaultEntry(path, name, title, parent, type)) == 0) {
return 0;
}
if(genre) {
- genre_id = insertObjectEntry(genre, type | OBJECT_GENRE);
+ genre_id = insertNodeEntry(genre, VITA_DIR_TYPE_MASK_GENRES, type);
if(!updateAdjacencyList(ohfi, genre_id)) {
- db.rollback();
return 0;
}
} else {
@@ -487,9 +588,8 @@ uint SQLiteDB::insertMusicEntry(const QString &path, int type, int parent)
}
if(artist) {
- track_id = insertObjectEntry(artist, type | OBJECT_ARTIST);
+ track_id = insertNodeEntry(artist, VITA_DIR_TYPE_MASK_ARTISTS, type);
if(!updateAdjacencyList(ohfi, track_id)) {
- db.rollback();
return 0;
}
} else {
@@ -497,9 +597,8 @@ uint SQLiteDB::insertMusicEntry(const QString &path, int type, int parent)
}
if(albumartist) {
- artist_id = insertObjectEntry(albumartist, type | OBJECT_ALBUM_ARTIST);
+ artist_id = insertNodeEntry(albumartist, VITA_DIR_TYPE_MASK_REGULAR, type);
if(!updateAdjacencyList(ohfi, artist_id)) {
- db.rollback();
return 0;
}
} else {
@@ -507,18 +606,15 @@ uint SQLiteDB::insertMusicEntry(const QString &path, int type, int parent)
}
if(album) {
- album_id = insertObjectEntry(album, type | OBJECT_ALBUM);
+ album_id = insertNodeEntry(album, VITA_DIR_TYPE_MASK_ALBUMS, type);
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 {
@@ -544,15 +640,13 @@ uint SQLiteDB::insertMusicEntry(const QString &path, int type, int parent)
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)
+uint SQLiteDB::insertVideoEntry(const QString &path, const QString &name, int parent, int type)
{
int ohfi;
AVDecoder decoder;
@@ -560,13 +654,13 @@ uint SQLiteDB::insertVideoEntry(const QString &path, int type, int parent)
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)) {
+ if(!decoder.open(path + "/" + name) || !decoder.loadCodec(AVDecoder::CODEC_VIDEO)) {
return 0;
}
- int file_type = checkFileType(path, VITA_OHFI_VIDEO);
+ int file_type = checkFileType(name, VITA_OHFI_VIDEO);
if(file_type < 0) {
- qDebug() << "Excluding from database:" << path;
+ //qDebug() << "Excluding from database:" << path;
return 0;
}
@@ -588,24 +682,12 @@ uint SQLiteDB::insertVideoEntry(const QString &path, int type, int parent)
audio_bitrate = 0;
}
- QByteArray basename = QFileInfo(path).baseName().toUtf8();
+ QByteArray basename = QFileInfo(name).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();
+ if((ohfi = insertDefaultEntry(path, name, title, parent, type)) == 0) {
return 0;
}
@@ -629,53 +711,38 @@ uint SQLiteDB::insertVideoEntry(const QString &path, int type, int parent)
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)
+uint SQLiteDB::insertPhotoEntry(const QString &path, const QString &name, int parent, int type)
{
int ohfi;
QImage img;
uint date_created;
int width, height, file_format, photo_codec;
- int file_type = checkFileType(path, VITA_OHFI_PHOTO);
+ int file_type = checkFileType(name, VITA_OHFI_PHOTO);
if(file_type < 0) {
- qDebug() << "Excluding from database:" << path;
+ //qDebug() << "Excluding from database:" << path;
return 0;
}
- if(!img.load(path)) {
+ if(!img.load(path + "/" + name)) {
return 0;
}
- date_created = QFileInfo(path).created().toTime_t();
+ date_created = QFileInfo(path + "/" + name).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();
+ QByteArray basename = QFileInfo(name).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();
+ if((ohfi = insertDefaultEntry(path, name, basename, parent, type)) == 0) {
return 0;
}
@@ -692,15 +759,13 @@ uint SQLiteDB::insertPhotoEntry(const QString &path, int type, int parent)
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)
+uint SQLiteDB::insertSavedataEntry(const QString &path, const QString &name, int parent, int type)
{
int ohfi;
SfoReader reader;
@@ -709,39 +774,22 @@ uint SQLiteDB::insertSavedataEntry(const QString &path, int type, int parent)
const char *savedata_detail = NULL;
const char *savedata_directory = NULL;
- QString file_name = QFileInfo(path).fileName();
+ QString file_name = QFileInfo(name).fileName();
QByteArray utf8name = file_name.toUtf8();
- db.transaction();
-
- if(file_name.endsWith(".sfo", Qt::CaseInsensitive) && reader.load(path)) {
+ if(file_name.endsWith(".sfo", Qt::CaseInsensitive) && reader.load(path + "/" + name)) {
title = reader.value("TITLE", utf8name.constData());
savedata_detail = reader.value("SAVEDATA_DETAIL", "");
savedata_directory = reader.value("SAVEDATA_DIRECTORY", utf8name.constData());
- date_updated = QFileInfo(path).lastModified().toTime_t();
+ date_updated = QFileInfo(path + "/" + name).lastModified().toTime_t();
}
- 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(!path.endsWith(".sfo", Qt::CaseInsensitive)) {
+ if((ohfi = insertDefaultEntry(path, name, title, parent, type)) == 0) {
return 0;
}
if(!title) {
- return 0;
+ return ohfi;
}
QSqlQuery query;
@@ -756,36 +804,31 @@ uint SQLiteDB::insertSavedataEntry(const QString &path, int type, int parent)
query.bindValue(4, date_updated);
if(!query.exec()) {
- db.rollback();
return 0;
}
- db.commit();
return ohfi;
}
-uint SQLiteDB::insertApplicationEntry(const QString &path, int type, int parent, int app_type)
+uint SQLiteDB::insertApplicationEntry(const QString &path, const QString &name, int parent, int type, int app_type)
{
int ohfi;
+ QString title_id;
- QString base_name = QFileInfo(path).baseName();
+ if(name.endsWith(".sfo", Qt::CaseInsensitive)) {
+ QDir curdir(path + "/" + name);
+ if(curdir.cdUp() && curdir.cdUp()) {
+ title_id = QFileInfo(curdir.absolutePath()).fileName();
+ }
+ }
- db.transaction();
-
- if((ohfi = insertObjectEntry(base_name.toUtf8().constData(), type)) == 0) {
- db.rollback();
+ if((ohfi = insertDefaultEntry(path, name, QFileInfo(name).fileName(), parent, type)) == 0) {
return 0;
}
- if(parent && !updateAdjacencyList(ohfi, parent)) {
- db.rollback();
- return 0;
- }
-
- if(!insertSourceEntry(ohfi, path)) {
- db.rollback();
- return 0;
+ if(title_id.isNull()) {
+ return ohfi;
}
QSqlQuery query;
@@ -794,81 +837,341 @@ uint SQLiteDB::insertApplicationEntry(const QString &path, int type, int parent,
"VALUES (:object_id, :title, :app_type)");
query.bindValue(0, ohfi);
- query.bindValue(1, base_name);
+ query.bindValue(1, title_id);
query.bindValue(2, app_type);
if(!query.exec()) {
- db.rollback();
return 0;
}
- db.commit();
return ohfi;
}
-
-
-bool SQLiteDB::getObjectMetadata(int ohfi, metadata_t &metadata)
-{
- return false;
-}
-
int SQLiteDB::childObjectCount(int parent_ohfi)
{
- return 0;
+ QSqlQuery query;
+ query.prepare("SELECT count(child_id) FROM adjacent_objects WHERE parent_id = :object_id");
+ query.bindValue(0, parent_ohfi);
+ if(!query.exec() || !query.next()) {
+ qDebug() << query.lastError();
+ return -1;
+ } else {
+ return query.value(0).toInt();
+ }
}
bool SQLiteDB::deleteEntry(int ohfi, int root_ohfi)
{
- return false;
+ Q_UNUSED(root_ohfi);
+ qDebug("Deleting node: %i", ohfi);
+
+ QSqlQuery source_query("DELETE FROM sources WHERE object_id = :object_id");
+ source_query.bindValue(0, ohfi);
+
+ db.transaction();
+ if(!source_query.exec()) {
+ db.rollback();
+ return false;
+ }
+
+ QSqlQuery object_query("DELETE FROM object_node WHERE object_id = :object_id");
+ object_query.bindValue(0, ohfi);
+ if(!object_query.exec()) {
+ db.rollback();
+ return false;
+ }
+
+ db.commit();
+ return true;
+}
+
+void SQLiteDB::fillMetadata(const QSqlQuery &query, metadata_t &metadata)
+{
+ metadata.ohfi = query.value("ohfi").toInt();
+ metadata.ohfiParent = query.value("parent").toInt();
+ metadata.name = strdup(query.value("name").toByteArray().constData());
+ metadata.path = strdup(query.value("path").toByteArray().constData());
+ metadata.type = VITA_DIR_TYPE_MASK_REGULAR;
+ metadata.dataType = (DataType)query.value("data_type").toInt();
+ metadata.size = query.value("size").toULongLong();
+ metadata.dateTimeCreated = query.value("date_created").toInt();
+ metadata.next_metadata = NULL;
+}
+
+bool SQLiteDB::getObjectMetadata(int ohfi, metadata_t &metadata)
+{
+ QSqlQuery query(
+ "SELECT "
+ "t0.object_id as ohfi,"
+ "t1.parent_id as parent,"
+ "t2.path as path,"
+ "t0.title as name,"
+ "t0.type as type,"
+ "t0.data_type as data_type,"
+ "t2.size as size,"
+ "t2.date_created as date_created "
+ "FROM object_node t0 "
+ "JOIN adjacent_objects t1 ON t1.child_id = t0.object_id "
+ "JOIN sources t2 ON t2.object_id = t0.object_id "
+ "WHERE t0.object_id = :object_id");
+ query.bindValue(0, ohfi);
+
+ if(query.exec() && query.next()) {
+ fillMetadata(query, metadata);
+ return true;
+ } else {
+ qDebug() << query.lastError();
+ return false;
+ }
}
int SQLiteDB::getObjectMetadatas(int parent_ohfi, metadata_t **metadata, int index, int max_number)
{
- return 0;
+ if(metadata == NULL) {
+ return childObjectCount(parent_ohfi);
+ }
+
+ int count = 0;
+ QString query_str(
+ "SELECT "
+ "t0.child_id as ohfi,"
+ "t0.parent_id as parent,"
+ "t2.path as path,"
+ "t1.title as name,"
+ "t1.type as type,"
+ "t1.data_type as data_type,"
+ "t2.size as size,"
+ "t2.date_created as date_created "
+ "FROM adjacent_objects t0 "
+ "JOIN object_node t1 ON t0.child_id = t1.object_id "
+ "JOIN sources t2 ON t0.child_id = t2.object_id "
+ "WHERE t0.parent_id = :parent_id ");
+
+ if(max_number > 0) {
+ query_str += "LIMIT :limit OFFSET :offset";
+ }
+
+ QSqlQuery query(query_str);
+ query.bindValue(0, parent_ohfi);
+
+ if(max_number > 0) {
+ query.bindValue(1, max_number);
+ query.bindValue(2, index);
+ }
+
+ if(query.exec()) {
+ metadata_t **last = &*metadata;
+ while(query.next()) {
+ metadata_t *meta = new metadata_t();
+ fillMetadata(query, *meta);
+ *last = meta;
+ last = &meta->next_metadata;
+ count++;
+ }
+ } else {
+ qDebug() << query.lastError();
+ }
+ return count;
}
qint64 SQLiteDB::getObjectSize(int ohfi)
{
- return -1;
+ if(ohfi < OHFI_BASE_VALUE) {
+ return getChildenTotalSize(ohfi);
+ }
+
+ QSqlQuery query;
+ query.prepare("SELECT size FROM sources WHERE object_id = :object_id");
+ query.bindValue(0, ohfi);
+ if(!query.exec() || !query.next()) {
+ qDebug() << query.lastError();
+ return -1;
+ } else {
+ return query.value(0).toInt();
+ }
}
int SQLiteDB::getPathId(const char *name, int ohfi)
{
- return 0;
-}
+ //FIXME: use ohfi to filter by category
+ Q_UNUSED(ohfi);
+ QSqlQuery query;
-int SQLiteDB::insertObjectEntry(const QString &path, int parent_ohfi)
-{
- return 0;
+ query.prepare("SELECT object_id FROM sources WHERE path = :path");
+ query.bindValue(0, name);
+ if(!query.exec() || !query.next()) {
+ qDebug() << query.lastError();
+ return 0;
+ } else {
+ return query.value(0).toInt();
+ }
}
QString SQLiteDB::getAbsolutePath(int ohfi)
{
- return NULL;
+ int root_ohfi = ohfi < OHFI_BASE_VALUE ? ohfi : getRootId(ohfi);
+ QString base_path = getBasePath(root_ohfi);
+ QString rel_path = getRelativePath(ohfi);
+ return rel_path.isNull() ? base_path : base_path + "/" + rel_path;
}
QString SQLiteDB::getRelativePath(int ohfi)
{
- return NULL;
+ QSqlQuery query;
+ query.prepare("SELECT path FROM sources WHERE object_id = :object_id");
+ query.bindValue(0, ohfi);
+ if(!query.exec() || !query.next()) {
+ qDebug() << query.lastError();
+ return NULL;
+ } else {
+ return query.value(0).toString();
+ }
+}
+
+bool SQLiteDB::updateObjectPath(int ohfi, const QString &name)
+{
+ int parent_ohfi = getParentId(ohfi);
+ QString parent_path, file;
+
+ if(name.isNull()) {
+ QSqlQuery name_query("SELECT title FROM object_node WHERE object_id = :object_id");
+ name_query.bindValue(0, ohfi);
+ if(!name_query.exec() || !name_query.next()) {
+ return false;
+ }
+ file = name_query.value(0).toString();
+ } else {
+ file = name;
+ }
+
+ if(parent_ohfi >= OHFI_BASE_VALUE) {
+ parent_path = getRelativePath(parent_ohfi);
+ if(parent_path.isNull()) {
+ parent_path = file;
+ } else {
+ parent_path += "/" + file;
+ }
+ } else {
+ parent_path = file;
+ }
+
+ QSqlQuery query("UPDATE sources SET path = :path WHERE object_id = :object_id");
+ query.bindValue(0, parent_path);
+ query.bindValue(1, ohfi);
+
+ if(!query.exec()) {
+ return false;
+ }
+
+ DataType type = (DataType)getObjectType(ohfi);
+
+ if(type & Folder) {
+ QSqlQuery child_query("SELECT child_id, data_type FROM adjacent_objects "
+ "JOIN object_node ON object_id = child_id"
+ "WHERE parent_id = :parent_id");
+ child_query.bindValue(0, ohfi);
+
+ if(query.exec()) {
+ while(query.next()) {
+ int child_ohfi = query.value(0).toInt();
+ if(!updateObjectPath(child_ohfi, NULL)) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
}
bool SQLiteDB::renameObject(int ohfi, const QString &name)
{
- return false;
+ QSqlQuery query("UPDATE object_node SET title = :title WHERE object_id = :object_id");
+ query.bindValue(0, name);
+ query.bindValue(1, ohfi);
+
+ if(!query.exec()) {
+ return false;
+ }
+
+ return updateObjectPath(ohfi, name);
}
void SQLiteDB::setObjectSize(int ohfi, qint64 size)
{
+ QSqlQuery query;
+ query.prepare("UPDATE sources SET size = :size WHERE object_id = :object_id");
+ query.bindValue(0, size);
+ query.bindValue(1, ohfi);
+ if(!query.exec()) {
+ qDebug() << query.lastError();
+ }
+}
+qint64 SQLiteDB::getChildenTotalSize(int ohfi)
+{
+ QSqlQuery query;
+ query.prepare("SELECT SUM(t0.size) FROM sources t0 "
+ "JOIN adjacent_objects t1 ON t0.object_id = t1.child_id "
+ "where t1.parent_id = :parent_id");
+ query.bindValue(0, ohfi);
+ if(!query.exec() || !query.next()) {
+ qDebug() << query.lastError();
+ return -1;
+ } else {
+ return query.value(0).toLongLong();
+ }
}
int SQLiteDB::getRootId(int ohfi)
{
- return 0;
+ QSqlQuery query;
+ int root_ohfi = ohfi;
+
+ query.prepare("SELECT parent_id FROM adjacent_objects WHERE child_id = :child_id");
+ while(root_ohfi >= OHFI_BASE_VALUE) {
+ query.bindValue(0, root_ohfi);
+ if(!query.exec() || !query.next()) {
+ qDebug() << query.lastError();
+ root_ohfi = 0;
+ } else {
+ root_ohfi = query.value(0).toInt();
+ }
+ }
+ return root_ohfi;
+}
+
+int SQLiteDB::getObjectType(int ohfi)
+{
+ QSqlQuery query;
+ query.prepare("SELECT type FROM object_node WHERE object_id = :object_id");
+ query.bindValue(0, ohfi);
+ if(!query.exec() || !query.next()) {
+ qDebug() << query.lastError();
+ return 0;
+ } else {
+ return query.value(0).toInt();
+ }
}
int SQLiteDB::getParentId(int ohfi)
{
- return 0;
+ QSqlQuery query;
+ query.prepare("SELECT parent_id FROM adjacent_objects WHERE child_id = :child_id");
+ query.bindValue(0, ohfi);
+ if(!query.exec() || !query.next()) {
+ qDebug() << query.lastError();
+ return 0;
+ } else {
+ return query.value(0).toInt();
+ }
+}
+
+void SQLiteDB::freeMetadata(metadata_t *metadata)
+{
+ while(metadata) {
+ metadata_t *current = metadata;
+ metadata = metadata->next_metadata;
+ delete current;
+ }
}
diff --git a/src/sqlitedb.h b/src/sqlitedb.h
index 95ccf7f..c45cdf9 100644
--- a/src/sqlitedb.h
+++ b/src/sqlitedb.h
@@ -1,3 +1,22 @@
+/*
+ * QCMA: Cross-platform content manager assistant for the PS Vita
+ *
+ * Copyright (C) 2014 Codestation
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see .
+ */
+
#ifndef SQLITEDB_H
#define SQLITEDB_H
@@ -5,27 +24,11 @@
#include
+#include
#include
#include
#include
-
-#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
-
-#define OBJECT_APPLICATION 0x00080000
+#include
class SQLiteDB : public Database
{
@@ -34,9 +37,16 @@ public:
explicit SQLiteDB(QObject *parent = 0);
~SQLiteDB();
+ bool load();
+ bool rescan();
+ void close();
+
+ bool reload(bool &prepared);
+ void setUUID(const QString &uuid);
+
bool open();
int create();
- void remove();
+ void clear();
bool initialize();
QSqlError getLastError();
@@ -50,35 +60,40 @@ public:
int getPathId(const char *name, int ohfi);
QString getRelativePath(int ohfi);
int getRootId(int ohfi);
- int insertObjectEntry(const QString &path, int parent_ohfi);
+ int insertObjectEntry(const QString &path, const QString &name, int parent_ohfi);
bool renameObject(int ohfi, const QString &name);
void setObjectSize(int ohfi, qint64 size);
+ void freeMetadata(metadata_t *metadata);
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);
- uint insertApplicationEntry(const QString &path, int type, int parent, int app_type);
+ bool insertSourceEntry(uint object_id, const QString &path, const QString &name);
+ uint insertMusicEntry(const QString &path, const QString &name, int parent, int type);
+ uint insertVideoEntry(const QString &path, const QString &name, int parent, int type);
+ uint insertPhotoEntry(const QString &path, const QString &name, int parent, int type);
+ uint insertSavedataEntry(const QString &path, const QString &name, int parent, int type);
+ uint insertApplicationEntry(const QString &path, const QString &name, int parent, int type, int app_type);
private:
- int recursiveScanRootDirectory(const QString &base_path, int parent, int type);
- uint insertDirectoryEntry(const QString &path, int type, int parent);
+ int recursiveScanRootDirectory(const QString &base_path, const QString &rel_path, int parent_ohfi, int root_ohfi);
+ int insertObjectEntryInternal(const QString &path, const QString &name, int parent_ohfi, int type);
+ int insertDefaultEntry(const QString &path, const QString &name, const QString &title, int parent, int type);
+ int insertNodeEntry(const QString &title, int type, int data_type);
bool updateAdjacencyList(int ohfi, int parent);
+ QString getBasePath(int root_ohfi);
+ int insertFileEntry(const QString &path, const QString &name, int parent, int parent_type);
+ int getObjectType(int ohfi);
+ void fillMetadata(const QSqlQuery &query, metadata_t &metadata);
+ qint64 getChildenTotalSize(int ohfi);
+ bool updateObjectPath(int ohfi, const QString &name);
+
+ QTimer *timer;
+ QThread *thread;
QString uuid;
QSqlDatabase db;
-
-signals:
-
-public slots:
-
};
#endif // SQLITEDB_H