From db554557bfaeb46b024911a68e8cfbe94ab3d0bf Mon Sep 17 00:00:00 2001 From: Martin Rotter Date: Sat, 12 Oct 2013 17:00:25 +0200 Subject: [PATCH] New database stuff. --- CMakeLists.txt | 2 + src/core/databasefactory.cpp | 122 +++++++++++++++++++++++++++++++++++ src/core/databasefactory.h | 47 ++++++++++++++ src/core/settings.h | 14 ++-- src/core/textfactory.cpp | 36 ++++++++++- src/core/textfactory.h | 9 ++- src/gui/webbrowser.h | 2 +- 7 files changed, 221 insertions(+), 11 deletions(-) create mode 100644 src/core/databasefactory.cpp create mode 100644 src/core/databasefactory.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d68828684..14b4a0d2a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -204,6 +204,7 @@ set(APP_SOURCES src/core/basewebpage.cpp src/core/webbrowsernetworkaccessmanager.cpp src/core/textfactory.cpp + src/core/databasefactory.cpp # Basic application sources. src/main.cpp @@ -244,6 +245,7 @@ set(APP_HEADERS src/core/basenetworkaccessmanager.h src/core/webbrowsernetworkaccessmanager.h src/core/basewebpage.h + src/core/databasefactory.h ) # Add form files. diff --git a/src/core/databasefactory.cpp b/src/core/databasefactory.cpp new file mode 100644 index 000000000..4ff85d082 --- /dev/null +++ b/src/core/databasefactory.cpp @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include + +#include "core/databasefactory.h" + + +QPointer DatabaseFactory::s_instance; + +DatabaseFactory::DatabaseFactory(QObject *parent) : QObject(parent) { + assemblyDatabaseFilePath(); +} + +DatabaseFactory::~DatabaseFactory() { + qDebug("Destroying DatabaseFactory object."); +} + +DatabaseFactory *DatabaseFactory::getInstance() { + if (s_instance.isNull()) { + s_instance = new DatabaseFactory(qApp); + } + + return s_instance; +} + +void DatabaseFactory::assemblyDatabaseFilePath() { + // TODO: Fill m_databasePath with correct path (portable or non-portable). +} + +QString DatabaseFactory::getDatabasePath() { + return m_databasePath; +} + +QSqlDatabase DatabaseFactory::initialize(const QString &connection_name) { + // Prepare file paths. + QDir db_path(getDatabasePath()); + QFile db_file(db_path.absoluteFilePath("database.db")); + + // Check if database directory exists. + if (!db_path.exists()) { + if (!db_path.mkpath(db_path.absolutePath())) { + // Failure when create database file path. + qFatal("Directory for database file '%s' was NOT created." + "This is HUGE problem.", + qPrintable(db_file.symLinkTarget())); + } + } + + // Folders are created. Create new QSQLDatabase object. + QSqlDatabase database = QSqlDatabase::addDatabase("QSQLITE", connection_name); + + // Setup database file path. + database.setDatabaseName(db_file.symLinkTarget()); + + if (!database.open()) { + qFatal("Database was NOT opened. Delivered error message: '%s'", + qPrintable(database.lastError().databaseText())); + } + else { + database.exec("PRAGMA synchronous = OFF"); + database.exec("PRAGMA journal_mode = MEMORY"); + database.exec("PRAGMA count_changes = OFF"); + database.exec("PRAGMA temp_store = MEMORY"); + //database.exec("PRAGMA foreign_keys = ON"); + + QSqlQuery q = database.exec("SELECT value FROM rssg_information WHERE key = 'schema_version'"); + + if (q.lastError().isValid()) { + qWarning("Error occurred. Database is not initialized. Initializing now."); + + QFile file_init(":/database/init.sql"); + file_init.open(QIODevice::ReadOnly | QIODevice::Text); + + QStringList statements = QString(file_init.readAll()).split("-- !\n");//--\n"); + database.exec("begin transaction"); + + foreach(QString i, statements) { + q = database.exec(i); + if (q.lastError().isValid()) { + if (q.lastError().number() != -1) { + break; + } + } + } + + database.exec("commit"); + qWarning("Database backend should be ready now."); + } + else { + q.next(); + qDebug("Database connection '%s' to file %s seems to be loaded.", + qPrintable(connection_name), + qPrintable(QDir::toNativeSeparators(database.databaseName()))); + qDebug("Database has version %s.", qPrintable(q.value(0).toString())); + } + q.finish(); + } + + return database; +} + +QSqlDatabase DatabaseFactory::addConnection(const QString &connection_name) { + QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", connection_name); + + if (!m_initialized) { + return initialize(connection_name); + } + else { + return QSqlDatabase::addDatabase("QSQLITE", connection_name); + } +} + +QSqlDatabase DatabaseFactory::getConnection(const QString &connection_name) { + return QSqlDatabase::database(connection_name); +} + +void DatabaseFactory::removeConnection(const QString &connection_name) { + qDebug("Removing database connection '%s'.", qPrintable(connection_name)); + QSqlDatabase::removeDatabase(connection_name); +} diff --git a/src/core/databasefactory.h b/src/core/databasefactory.h new file mode 100644 index 000000000..3239d59ea --- /dev/null +++ b/src/core/databasefactory.h @@ -0,0 +1,47 @@ +#ifndef DATABASEFACTORY_H +#define DATABASEFACTORY_H + +#include +#include +#include + + +class DatabaseFactory : public QObject { + Q_OBJECT + + private: + // Conctructor. + explicit DatabaseFactory(QObject *parent = 0); + + // Assemblies database file path. + void assemblyDatabaseFilePath(); + + // Returns true if database was initialized, otherwise false. + QSqlDatabase initialize(const QString &connection_name); + + // Path to database file. + QString m_databasePath; + + // True if database file is initialized, otherwise false. + bool m_initialized; + + // Private singleton value. + static QPointer s_instance; + + public: + // Destructor. + virtual ~DatabaseFactory(); + + // Returns absolute file path to database file. + QString getDatabasePath(); + + // Database manipulators. + QSqlDatabase addConnection(const QString &connection_name); + QSqlDatabase getConnection(const QString &connection_name); + void removeConnection(const QString &connection_name); + + // Singleton getter. + static DatabaseFactory *getInstance(); +}; + +#endif // DATABASEFACTORY_H diff --git a/src/core/settings.h b/src/core/settings.h index 6821559e5..7bffc2702 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -9,14 +9,20 @@ class Settings : public QSettings { Q_OBJECT private: + // Constructor. + Settings(const QString & file_name, Format format, QObject * parent = 0); + + // Creates settings file in correct location. + static QSettings::Status setupSettings(); + + // Private singleton value. static QPointer s_instance; public: // Singleton getter. static Settings *getInstance(); - // Constructor and destructor. - Settings(const QString & file_name, Format format, QObject * parent = 0); + // Destructor. virtual ~Settings(); // Getter/setter for settings values. @@ -30,10 +36,6 @@ class Settings : public QSettings { // Synchronises settings. QSettings::Status checkSettings(); - - protected: - // Creates settings file in correct location. - static QSettings::Status setupSettings(); }; #endif // SETTINGS_H diff --git a/src/core/textfactory.cpp b/src/core/textfactory.cpp index 32faf4750..7f8213338 100644 --- a/src/core/textfactory.cpp +++ b/src/core/textfactory.cpp @@ -1,4 +1,8 @@ #include +#include +#include +#include +#include #include "core/defs.h" #include "core/textfactory.h" @@ -10,9 +14,35 @@ TextFactory::TextFactory() { TextFactory::~TextFactory() { } -QString TextFactory::shorten(const QString &input) { - if (input.size() > TEXT_TITLE_LIMIT) { - return input.left(TEXT_TITLE_LIMIT - 3) + QString(3, '.'); +QDateTime TextFactory::parseDateTime(const QString &date_time) { + QString date = date_time.simplified(); + QDateTime dt; + QString temp; + QLocale locale(QLocale::C); + QStringList date_patterns; + date_patterns << "yyyy-MM-ddTHH:mm:ss" << "MMM dd yyyy hh:mm:ss" << + "MMM hd yyyy hh:mm:ss" << "ddd, dd MMM yyyy HH:mm:ss" << + "dd MMM yyyy" << "yyyy-MM-dd HH:mm:ss.z" << "yyyy-MM-dd" << + "YYYY" << "YYYY-MM" << "YYYY-MM-DD" << "YYYY-MM-DDThh:mmTZD" << + "YYYY-MM-DDThh:mm:ssTZD"; + + // Iterate over patterns and check if input date/time matches the pattern. + foreach (QString pattern, date_patterns) { + temp = date.left(pattern.size()); + dt = locale.toDateTime(temp, pattern); + if (dt.isValid()) { + return dt; + } + } + + qWarning("Problem with parsing date '%s', returning invalid QDateTime instance.", + qPrintable(date)); + return QDateTime(); +} + +QString TextFactory::shorten(const QString &input, int text_length_limit) { + if (input.size() > text_length_limit) { + return input.left(text_length_limit - 3) + QString(3, '.'); } else { return input; diff --git a/src/core/textfactory.h b/src/core/textfactory.h index 3644dd130..cee3e66aa 100644 --- a/src/core/textfactory.h +++ b/src/core/textfactory.h @@ -1,6 +1,8 @@ #ifndef TEXTFACTORY_H #define TEXTFACTORY_H +#include "core/defs.h" + class TextFactory { private: @@ -9,7 +11,12 @@ class TextFactory { public: virtual ~TextFactory(); - static QString shorten(const QString &input); + // Tries to parse input textual date/time representation. + // Returns invalid date/time if processing fails. + static QDateTime parseDateTime(const QString &date_time); + + // Shortens input string according to given length limit. + static QString shorten(const QString &input, int text_length_limit = TEXT_TITLE_LIMIT); }; #endif // TEXTFACTORY_H diff --git a/src/gui/webbrowser.h b/src/gui/webbrowser.h index 23529836a..25597567e 100644 --- a/src/gui/webbrowser.h +++ b/src/gui/webbrowser.h @@ -40,7 +40,7 @@ class WebBrowser : public TabContent { WebBrowser *webBrowser(); // Returns global menu for this web browser. - QList globalMenu(); + virtual QList globalMenu(); // Returns pointer to global network access manager // for web browsers.