diff --git a/src/app/main.cpp b/src/app/main.cpp index 72e9feef..c69c558a 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -5,6 +5,7 @@ #include "utility/logging/ConsoleLogger.h" #include "utility/logging/FileLogger.h" #include "utility/logging/LogManager.h" +#include "utility/Version.h" #include "Application.h" #include "includes.h" // defines 'void setup(int argc, char *argv[])' @@ -31,6 +32,8 @@ void init() int main(int argc, char *argv[]) { + Version version = Version::fromString(GIT_VERSION_NUMBER); + setup(argc, argv); QApplication qtApp(argc, argv); @@ -41,7 +44,7 @@ int main(int argc, char *argv[]) QtSplashScreen* splash = new QtSplashScreen(whitePixmap, Qt::WindowStaysOnTopHint); splash->setMessage("Loading UI"); - splash->setVersion(GIT_VERSION_NUMBER); + splash->setVersion(version.toDisplayString().c_str()); splash->exec(qtApp); init(); @@ -49,7 +52,7 @@ int main(int argc, char *argv[]) QtViewFactory viewFactory; QtNetworkFactory networkFactory; - std::shared_ptr app = Application::create(&viewFactory, &networkFactory); + std::shared_ptr app = Application::create(version, &viewFactory, &networkFactory); if (splash) { diff --git a/src/app/qt/window/QtAbout.cpp b/src/app/qt/window/QtAbout.cpp index 0a78f17d..69539452 100644 --- a/src/app/qt/window/QtAbout.cpp +++ b/src/app/qt/window/QtAbout.cpp @@ -4,7 +4,7 @@ #include #include -#include "version.h" +#include "utility/Version.h" QtAbout::QtAbout(QWidget *parent) : QtSettingsWindow(parent) @@ -46,7 +46,7 @@ void QtAbout::populateForm(QFormLayout* layout) acknowledgementsLabel->setAlignment(Qt::AlignTop); layout->addRow(acknowledgementsName, acknowledgementsLabel); - layout->addRow(QString("Version:"), new QLabel(GIT_VERSION_NUMBER)); + layout->addRow(QString("Version:"), new QLabel(Version::getApplicationVersion().toDisplayString().c_str())); } void QtAbout::handleCancelButtonPress() diff --git a/src/lib/Application.cpp b/src/lib/Application.cpp index 79584d42..bfceeb67 100644 --- a/src/lib/Application.cpp +++ b/src/lib/Application.cpp @@ -5,6 +5,7 @@ #include "utility/messaging/type/MessageActivateNodes.h" #include "utility/messaging/type/MessageStatus.h" #include "utility/scheduling/TaskScheduler.h" +#include "utility/Version.h" #include "component/view/GraphViewStyle.h" #include "component/controller/NetworkFactory.h" @@ -14,8 +15,11 @@ #include "settings/ApplicationSettings.h" #include "settings/ColorScheme.h" -std::shared_ptr Application::create(ViewFactory* viewFactory, NetworkFactory* networkFactory) -{ +std::shared_ptr Application::create( + const Version& version, ViewFactory* viewFactory, NetworkFactory* networkFactory +){ + Version::setApplicationVersion(version); + loadSettings(); std::shared_ptr ptr(new Application()); diff --git a/src/lib/Application.h b/src/lib/Application.h index f2266295..6f9a5ad0 100644 --- a/src/lib/Application.h +++ b/src/lib/Application.h @@ -16,6 +16,7 @@ class NetworkFactory; class ViewFactory; class MainView; class StorageCache; +class Version; class Application : public MessageListener @@ -24,7 +25,7 @@ class Application , public MessageListener { public: - static std::shared_ptr create(ViewFactory* viewFactory, NetworkFactory* networkFactory); + static std::shared_ptr create(const Version& version, ViewFactory* viewFactory, NetworkFactory* networkFactory); static void loadSettings(); ~Application(); @@ -50,8 +51,6 @@ private: std::shared_ptr m_componentManager; std::shared_ptr m_ideCommunicationController; - - bool m_isInitialParse; }; #endif // APPLICATION_H diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index dcf32d40..0c8bac6f 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -58,7 +58,7 @@ add_files( component/controller/FeatureController.h component/controller/GraphController.cpp component/controller/GraphController.h - + component/controller/IDECommunicationController.cpp component/controller/IDECommunicationController.h component/controller/NetworkFactory.cpp @@ -307,6 +307,8 @@ add_files( utility/utility.h utility/utilityString.cpp utility/utilityString.h + utility/Version.cpp + utility/Version.h Application.cpp Application.h diff --git a/src/lib/Project.cpp b/src/lib/Project.cpp index f86a9f32..2beedf13 100644 --- a/src/lib/Project.cpp +++ b/src/lib/Project.cpp @@ -1,8 +1,11 @@ #include "Project.h" +#include "utility/file/FileSystem.h" #include "utility/logging/logging.h" #include "utility/messaging/type/MessageFinishedParsing.h" +#include "utility/scheduling/TaskGroupSequential.h" #include "utility/utility.h" +#include "utility/Version.h" #include "data/access/StorageAccessProxy.h" #include "data/graph/Token.h" @@ -11,8 +14,6 @@ #include "data/TaskCleanStorage.h" #include "settings/ApplicationSettings.h" #include "settings/ProjectSettings.h" -#include "utility/file/FileSystem.h" -#include "utility/scheduling/TaskGroupSequential.h" std::shared_ptr Project::create(StorageAccessProxy* storageAccessProxy) { @@ -144,6 +145,12 @@ void Project::setProjectSettingsFilePath(const FilePath& path) FilePath dbPath = FilePath(path).replaceExtension("sqlite"); m_storageWasLoaded = dbPath.exists(); m_storage = std::make_shared(dbPath); + + if (m_storageWasLoaded && m_storage->getVersion().isOlderStorageVersionThan(Version::getApplicationVersion())) + { + m_storage->clear(); + m_storageWasLoaded = false; + } } m_storageAccessProxy->setSubject(m_storage.get()); diff --git a/src/lib/data/SqliteStorage.cpp b/src/lib/data/SqliteStorage.cpp index 8639ae87..57c9c8ba 100644 --- a/src/lib/data/SqliteStorage.cpp +++ b/src/lib/data/SqliteStorage.cpp @@ -6,6 +6,7 @@ #include "utility/text/TextAccess.h" #include "utility/utility.h" #include "utility/utilityString.h" +#include "utility/Version.h" SqliteStorage::SqliteStorage(const std::string& dbFilePath) { @@ -47,6 +48,23 @@ void SqliteStorage::rollbackTransaction() m_database.execDML("ROLLBACK TRANSACTION;"); } +Version SqliteStorage::getVersion() const +{ + std::string versionStr = getMetaValue("version"); + + if (versionStr.size()) + { + return Version::fromString(versionStr); + } + + return Version(); +} + +void SqliteStorage::setVersion(const Version& version) +{ + insertOrUpdateMetaValue("version", version.toString()); +} + Id SqliteStorage::addEdge(int type, Id sourceNodeId, Id targetNodeId) { m_database.execDML( @@ -708,10 +726,19 @@ void SqliteStorage::clearTables() m_database.execDML("DROP TABLE IF EXISTS main.node;"); m_database.execDML("DROP TABLE IF EXISTS main.edge;"); m_database.execDML("DROP TABLE IF EXISTS main.element;"); + m_database.execDML("DROP TABLE IF EXISTS main.meta;"); } void SqliteStorage::setupTables() { + m_database.execDML( + "CREATE TABLE IF NOT EXISTS meta(" + "id INTEGER, " + "key TEXT, " + "value TEXT, " + "PRIMARY KEY(id));" + ); + m_database.execDML( "CREATE TABLE IF NOT EXISTS element(" "id INTEGER, " @@ -793,6 +820,43 @@ void SqliteStorage::setupTables() ); } +bool SqliteStorage::hasTable(const std::string& tableName) const +{ + CppSQLite3Query q = m_database.execQuery(( + "SELECT name FROM sqlite_master WHERE type='table' AND name='" + tableName + "';" + ).c_str()); + + if (!q.eof()) + { + return q.getStringField(0, "") == tableName; + } + + return false; +} + +std::string SqliteStorage::getMetaValue(const std::string& key) const +{ + if (hasTable("meta")) + { + CppSQLite3Query q = m_database.execQuery(("SELECT value FROM meta WHERE key = '" + key + "';").c_str()); + + if (!q.eof()) + { + return q.getStringField(0, ""); + } + } + + return ""; +} + +void SqliteStorage::insertOrUpdateMetaValue(const std::string& key, const std::string& value) +{ + m_database.execDML(( + "INSERT OR REPLACE INTO meta(id, key, value) " + "VALUES( (SELECT id FROM meta WHERE key = '" + key + "'), '" + key + "', '" + value + "');" + ).c_str()); +} + StorageFile SqliteStorage::getFirstFile(const std::string& query) const { CppSQLite3Query q = m_database.execQuery(query.c_str()); diff --git a/src/lib/data/SqliteStorage.h b/src/lib/data/SqliteStorage.h index 8c412fc4..51c608f6 100644 --- a/src/lib/data/SqliteStorage.h +++ b/src/lib/data/SqliteStorage.h @@ -15,6 +15,7 @@ #include "data/StorageTypes.h" class TextAccess; +class Version; class SqliteStorage { @@ -29,6 +30,9 @@ public: void commitTransaction(); void rollbackTransaction(); + Version getVersion() const; + void setVersion(const Version& version); + Id addEdge(int type, Id sourceNodeId, Id targetNodeId); Id addNode(int type, Id nameId, bool defined); Id addFile(Id nameId, const std::string& filePath, const std::string& modificationTime); @@ -107,6 +111,11 @@ private: void clearTables(); void setupTables(); + bool hasTable(const std::string& tableName) const; + + std::string getMetaValue(const std::string& key) const; + void insertOrUpdateMetaValue(const std::string& key, const std::string& value); + StorageFile getFirstFile(const std::string& query) const; std::vector getAllFiles(const std::string& query) const; StorageSourceLocation getFirstSourceLocation(const std::string& query) const; diff --git a/src/lib/data/Storage.cpp b/src/lib/data/Storage.cpp index 3d296bf1..94eba30f 100644 --- a/src/lib/data/Storage.cpp +++ b/src/lib/data/Storage.cpp @@ -19,6 +19,7 @@ #include "data/parser/ParseVariable.h" #include "data/type/DataType.h" #include "settings/ApplicationSettings.h" +#include "utility/Version.h" Storage::Storage(const FilePath& dbPath) : m_sqliteStorage(dbPath.str()) @@ -29,6 +30,11 @@ Storage::~Storage() { } +Version Storage::getVersion() const +{ + return m_sqliteStorage.getVersion(); +} + void Storage::clear() { m_sqliteStorage.clear(); @@ -148,6 +154,7 @@ void Storage::logStats() const void Storage::startParsing() { + m_sqliteStorage.setVersion(Version::getApplicationVersion()); } void Storage::finishParsing() diff --git a/src/lib/data/Storage.h b/src/lib/data/Storage.h index 8b24b6ae..abd16a8d 100644 --- a/src/lib/data/Storage.h +++ b/src/lib/data/Storage.h @@ -23,6 +23,8 @@ public: Storage(const FilePath& dbPath); virtual ~Storage(); + Version getVersion() const; + void clear(); void clearCaches(); diff --git a/src/lib/utility/Version.cpp b/src/lib/utility/Version.cpp new file mode 100644 index 00000000..2b329966 --- /dev/null +++ b/src/lib/utility/Version.cpp @@ -0,0 +1,114 @@ +#include "utility/Version.h" + +#include "utility/utilityString.h" +#include "utility/logging/logging.h" + +Version Version::s_version; + +Version Version::fromString(const std::string& versionString) +{ + Version version; + std::vector components = utility::splitToVector(versionString, '-'); + + if (components.size() != 3) + { + LOG_ERROR("Version string is invalid: " + versionString); + return version; + } + + std::vector numbers = utility::splitToVector(components[0], '.'); + if (numbers.size() > 0) + { + version.m_majorNumber = std::stoi(numbers[0]); + } + if (numbers.size() > 1) + { + version.m_minorNumber = std::stoi(numbers[1]); + } + if (numbers.size() > 2) + { + version.m_refreshNumber = std::stoi(numbers[2]); + } + + version.m_commitNumber = std::stoi(components[1]); + version.m_commitHash = components[2]; + + return version; +} + +void Version::setApplicationVersion(const Version& version) +{ + s_version = version; +} + +const Version& Version::getApplicationVersion() +{ + return s_version; +} + +Version::Version() + : m_majorNumber(0) + , m_minorNumber(0) + , m_refreshNumber(0) + , m_commitNumber(0) +{ +} + +bool Version::operator<(const Version& other) +{ + if (m_majorNumber != other.m_majorNumber) + { + return m_majorNumber < other.m_majorNumber; + } + else if (m_minorNumber != other.m_minorNumber) + { + return m_minorNumber < other.m_minorNumber; + } + else if (m_refreshNumber != other.m_refreshNumber) + { + return m_refreshNumber < other.m_refreshNumber; + } + else if (m_commitNumber != other.m_commitNumber) + { + return m_commitNumber < other.m_commitNumber; + } + else + { + return false; + } +} + +bool Version::isOlderStorageVersionThan(const Version& other) +{ + if (m_majorNumber != other.m_majorNumber) + { + return m_majorNumber < other.m_majorNumber; + } + else if (m_minorNumber != other.m_minorNumber) + { + return m_minorNumber < other.m_minorNumber; + } + else if (m_refreshNumber != other.m_refreshNumber) + { + return m_refreshNumber < other.m_refreshNumber; + } + else + { + return false; + } +} + +std::string Version::toString() const +{ + std::stringstream ss; + ss << m_majorNumber << '.' << m_minorNumber << '.' << m_refreshNumber; + ss << '-' << m_commitNumber << '-' << m_commitHash; + return ss.str(); +} + +std::string Version::toDisplayString() const +{ + std::stringstream ss; + ss << m_majorNumber << '.' << m_minorNumber << '.' << m_refreshNumber << '.' << m_commitNumber; + return ss.str(); +} diff --git a/src/lib/utility/Version.h b/src/lib/utility/Version.h new file mode 100644 index 00000000..c2014e5f --- /dev/null +++ b/src/lib/utility/Version.h @@ -0,0 +1,33 @@ +#ifndef VERSION_H +#define VERSION_H + +#include + +class Version +{ +public: + static Version fromString(const std::string& versionString); + + static void setApplicationVersion(const Version& version); + static const Version& getApplicationVersion(); + + Version(); + + bool operator<(const Version& other); + bool isOlderStorageVersionThan(const Version& other); + + std::string toString() const; + std::string toDisplayString() const; + +private: + static Version s_version; + + int m_majorNumber; + int m_minorNumber; + int m_refreshNumber; + int m_commitNumber; + + std::string m_commitHash; +}; + +#endif // VERSION_H