logic: Ask user before reparsing the project
While the message box with the question is visible the ui is blocked. A message appears when: * when project was edited * when preferences were edited * when project file has more recent changes than db * when db has a different version than Coati
This commit is contained in:
+82
-9
@@ -92,7 +92,7 @@ bool Application::hasGUI()
|
||||
return m_hasGUI;
|
||||
}
|
||||
|
||||
void Application::loadProject(const FilePath& projectSettingsFilePath)
|
||||
void Application::createAndLoadProject(const FilePath& projectSettingsFilePath)
|
||||
{
|
||||
MessageStatus("Loading Project: " + projectSettingsFilePath.str(), false, true).dispatch();
|
||||
|
||||
@@ -102,20 +102,63 @@ void Application::loadProject(const FilePath& projectSettingsFilePath)
|
||||
m_storageCache->clear();
|
||||
|
||||
m_project = Project::create(m_storageCache.get());
|
||||
m_project->load(projectSettingsFilePath);
|
||||
loadProject(projectSettingsFilePath);
|
||||
|
||||
if (m_hasGUI)
|
||||
{
|
||||
m_mainView->setTitle(
|
||||
"Coati - " +
|
||||
projectSettingsFilePath.fileName());
|
||||
|
||||
m_mainView->setTitle("Coati - " + projectSettingsFilePath.fileName());
|
||||
m_mainView->updateRecentProjectMenu();
|
||||
m_mainView->hideStartScreen();
|
||||
|
||||
m_componentManager->refreshViews();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::loadProject(const FilePath& projectSettingsFilePath)
|
||||
{
|
||||
bool reparse = false;
|
||||
|
||||
Project::ProjectState state = m_project->load(projectSettingsFilePath);
|
||||
if (state == Project::PROJECT_OUTDATED)
|
||||
{
|
||||
if (m_hasGUI)
|
||||
{
|
||||
std::vector<std::string> options;
|
||||
options.push_back("Yes");
|
||||
options.push_back("No");
|
||||
int result = m_mainView->confirm(
|
||||
"The project file was changed after the last analysis. The project needs to get fully reanalysed to "
|
||||
"reflect the current project state. Do you want to reanalyze the project?", options);
|
||||
|
||||
reparse = (result == 0);
|
||||
}
|
||||
}
|
||||
else if (state == Project::PROJECT_OUTVERSIONED)
|
||||
{
|
||||
MessageStatus("Can't load project").dispatch();
|
||||
|
||||
reparse = true;
|
||||
|
||||
if (m_hasGUI)
|
||||
{
|
||||
std::vector<std::string> options;
|
||||
options.push_back("Yes");
|
||||
options.push_back("No");
|
||||
int result = m_mainView->confirm(
|
||||
"This project was analyzed with a different version of Coati. It needs to be fully reanalyzed to be used "
|
||||
"with this version of Coati. Do you want to reanalyze the project?", options);
|
||||
|
||||
reparse = (result == 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (reparse)
|
||||
{
|
||||
m_project->clearStorage();
|
||||
m_project->load(projectSettingsFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::refreshProject()
|
||||
{
|
||||
MessageStatus("Refreshing Project").dispatch();
|
||||
@@ -126,7 +169,12 @@ void Application::refreshProject()
|
||||
m_componentManager->refreshViews();
|
||||
}
|
||||
|
||||
m_project->reload();
|
||||
Project::ProjectState state = m_project->reload();
|
||||
if (state != Project::PROJECT_LOADED)
|
||||
{
|
||||
MessageStatus("Can't refresh project").dispatch();
|
||||
loadProject(m_project->getProjectSettingsFilePath());
|
||||
}
|
||||
}
|
||||
|
||||
void Application::saveProject(const FilePath& projectSettingsFilePath)
|
||||
@@ -156,18 +204,43 @@ void Application::handleMessage(MessageFinishedParsing* message)
|
||||
|
||||
void Application::handleMessage(MessageLoadProject* message)
|
||||
{
|
||||
FilePath projectSettingsFilePath(message->projectSettingsFilePath);
|
||||
if (projectSettingsFilePath.empty())
|
||||
{
|
||||
projectSettingsFilePath = m_project->getProjectSettingsFilePath();
|
||||
if (projectSettingsFilePath.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (message->forceRefresh)
|
||||
{
|
||||
if (m_hasGUI)
|
||||
{
|
||||
std::vector<std::string> options;
|
||||
options.push_back("Yes");
|
||||
options.push_back("No");
|
||||
int result = m_mainView->confirm(
|
||||
"Some settings were changed, the project needs to be fully reanalyzed. "
|
||||
"Do you want to reanalyze the project?", options);
|
||||
|
||||
if (result == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_project->clearStorage();
|
||||
}
|
||||
else if (FilePath(message->projectSettingsFilePath) == m_project->getProjectSettingsFilePath())
|
||||
else if (projectSettingsFilePath == m_project->getProjectSettingsFilePath())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
loadProject(message->projectSettingsFilePath);
|
||||
createAndLoadProject(projectSettingsFilePath);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
||||
@@ -33,6 +33,7 @@ public:
|
||||
|
||||
~Application();
|
||||
|
||||
void createAndLoadProject(const FilePath& projectSettingsFilePath);
|
||||
void loadProject(const FilePath& projectSettingsFilePath);
|
||||
void refreshProject();
|
||||
void saveProject(const FilePath& projectSettingsFilePath);
|
||||
|
||||
+80
-32
@@ -30,29 +30,62 @@ const FilePath& Project::getProjectSettingsFilePath() const
|
||||
return m_projectSettingsFilepath;
|
||||
}
|
||||
|
||||
bool Project::load(const FilePath& projectSettingsFile)
|
||||
Project::ProjectState Project::load(const FilePath& projectSettingsFile)
|
||||
{
|
||||
bool success = ProjectSettings::getInstance()->load(projectSettingsFile);
|
||||
m_state = PROJECT_NONE;
|
||||
|
||||
bool success = true;
|
||||
if (!projectSettingsFile.empty() && projectSettingsFile != m_projectSettingsFilepath)
|
||||
{
|
||||
success = ProjectSettings::getInstance()->load(projectSettingsFile);
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
setProjectSettingsFilePath(projectSettingsFile);
|
||||
updateFileManager();
|
||||
|
||||
switch (m_state)
|
||||
{
|
||||
case PROJECT_NONE:
|
||||
break;
|
||||
|
||||
case PROJECT_EMPTY:
|
||||
parseCode();
|
||||
break;
|
||||
|
||||
case PROJECT_LOADED:
|
||||
case PROJECT_OUTDATED:
|
||||
m_storage->finishParsing();
|
||||
MessageFinishedParsing(0, 0, 0, true).dispatch();
|
||||
break;
|
||||
|
||||
case PROJECT_OUTVERSIONED:
|
||||
m_storage.reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_storageWasLoaded)
|
||||
return m_state;
|
||||
}
|
||||
|
||||
Project::ProjectState Project::reload()
|
||||
{
|
||||
if (m_state == PROJECT_LOADED &&
|
||||
FileSystem::getFileInfoForPath(m_projectSettingsFilepath).lastWriteTime >
|
||||
FileSystem::getFileInfoForPath(m_storage->getDbFilePath()).lastWriteTime)
|
||||
{
|
||||
m_storage->startParsing();
|
||||
m_storage->finishParsing();
|
||||
MessageFinishedParsing(0, 0, 0, true).dispatch();
|
||||
m_state = PROJECT_OUTDATED;
|
||||
}
|
||||
else
|
||||
else if (!m_projectSettingsFilepath.empty() && (m_state == PROJECT_EMPTY || m_state == PROJECT_LOADED))
|
||||
{
|
||||
ProjectSettings::getInstance()->load(m_projectSettingsFilepath);
|
||||
updateFileManager();
|
||||
|
||||
parseCode();
|
||||
}
|
||||
|
||||
m_storageWasLoaded = true;
|
||||
|
||||
return success;
|
||||
return m_state;
|
||||
}
|
||||
|
||||
bool Project::save(const FilePath& projectSettingsFile)
|
||||
@@ -74,25 +107,17 @@ bool Project::save(const FilePath& projectSettingsFile)
|
||||
return true;
|
||||
}
|
||||
|
||||
void Project::reload()
|
||||
{
|
||||
if (!m_projectSettingsFilepath.empty())
|
||||
{
|
||||
ProjectSettings::getInstance()->load(m_projectSettingsFilepath);
|
||||
updateFileManager();
|
||||
|
||||
setProjectSettingsFilePath(m_projectSettingsFilepath);
|
||||
}
|
||||
|
||||
parseCode();
|
||||
}
|
||||
|
||||
void Project::clearStorage()
|
||||
{
|
||||
if (m_state == PROJECT_OUTVERSIONED)
|
||||
{
|
||||
loadStorage(m_projectSettingsFilepath);
|
||||
}
|
||||
|
||||
if (m_storage)
|
||||
{
|
||||
m_storage->clear();
|
||||
m_storageWasLoaded = false;
|
||||
m_state = PROJECT_EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,6 +158,8 @@ void Project::parseCode()
|
||||
));
|
||||
|
||||
Task::dispatch(taskGroup);
|
||||
|
||||
m_state = PROJECT_LOADED;
|
||||
}
|
||||
|
||||
void Project::logStats() const
|
||||
@@ -142,21 +169,33 @@ void Project::logStats() const
|
||||
|
||||
void Project::setProjectSettingsFilePath(const FilePath& path)
|
||||
{
|
||||
m_storageWasLoaded = false;
|
||||
|
||||
if (path.empty())
|
||||
{
|
||||
m_storage.reset();
|
||||
m_state = PROJECT_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
FilePath dbPath = FilePath(path).replaceExtension("coatidb");
|
||||
m_storageWasLoaded = dbPath.exists();
|
||||
loadStorage(path);
|
||||
|
||||
if (!m_storage || !dbPath.exists())
|
||||
Version version = m_storage->getVersion();
|
||||
if (version.isEmpty())
|
||||
{
|
||||
m_storage = std::make_shared<Storage>(dbPath);
|
||||
m_storageWasLoaded = m_storage->init();
|
||||
m_state = PROJECT_EMPTY;
|
||||
m_storage->init();
|
||||
}
|
||||
else if (version.isDifferentStorageVersionThan(Version::getApplicationVersion()))
|
||||
{
|
||||
m_state = PROJECT_OUTVERSIONED;
|
||||
m_storage.reset();
|
||||
}
|
||||
else if (FileSystem::getFileInfoForPath(path).lastWriteTime > FileSystem::getFileInfoForPath(m_storage->getDbFilePath()).lastWriteTime)
|
||||
{
|
||||
m_state = PROJECT_OUTDATED;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state = PROJECT_LOADED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,6 +203,15 @@ void Project::setProjectSettingsFilePath(const FilePath& path)
|
||||
m_projectSettingsFilepath = path;
|
||||
}
|
||||
|
||||
void Project::loadStorage(const FilePath& path)
|
||||
{
|
||||
FilePath dbPath = FilePath(path).replaceExtension("coatidb");
|
||||
if (!m_storage || path != m_projectSettingsFilepath || !dbPath.exists())
|
||||
{
|
||||
m_storage = std::make_shared<Storage>(dbPath);
|
||||
}
|
||||
}
|
||||
|
||||
void Project::updateFileManager()
|
||||
{
|
||||
std::shared_ptr<ProjectSettings> projSettings = ProjectSettings::getInstance();
|
||||
@@ -226,6 +274,6 @@ Parser::Arguments Project::getParserArguments() const
|
||||
|
||||
Project::Project(StorageAccessProxy* storageAccessProxy)
|
||||
: m_storageAccessProxy(storageAccessProxy)
|
||||
, m_storageWasLoaded(false)
|
||||
, m_state(PROJECT_NONE)
|
||||
{
|
||||
}
|
||||
|
||||
+15
-3
@@ -13,15 +13,25 @@ class StorageAccessProxy;
|
||||
class Project
|
||||
{
|
||||
public:
|
||||
enum ProjectState
|
||||
{
|
||||
PROJECT_NONE,
|
||||
PROJECT_EMPTY,
|
||||
PROJECT_LOADED,
|
||||
PROJECT_OUTDATED,
|
||||
PROJECT_OUTVERSIONED
|
||||
};
|
||||
|
||||
static std::shared_ptr<Project> create(StorageAccessProxy* storageAccessProxy);
|
||||
|
||||
~Project();
|
||||
|
||||
const FilePath& getProjectSettingsFilePath() const;
|
||||
|
||||
bool load(const FilePath& projectSettingsFile);
|
||||
ProjectState load(const FilePath& projectSettingsFile);
|
||||
ProjectState reload();
|
||||
|
||||
bool save(const FilePath& projectSettingsFile);
|
||||
void reload();
|
||||
|
||||
void clearStorage();
|
||||
|
||||
@@ -35,17 +45,19 @@ private:
|
||||
void parseCode();
|
||||
|
||||
void setProjectSettingsFilePath(const FilePath& path);
|
||||
void loadStorage(const FilePath& path);
|
||||
void updateFileManager();
|
||||
|
||||
Parser::Arguments getParserArguments() const;
|
||||
|
||||
StorageAccessProxy* const m_storageAccessProxy;
|
||||
|
||||
ProjectState m_state;
|
||||
|
||||
FilePath m_projectSettingsFilepath;
|
||||
FileManager m_fileManager;
|
||||
|
||||
std::shared_ptr<Storage> m_storage;
|
||||
bool m_storageWasLoaded;
|
||||
};
|
||||
|
||||
#endif // PROJECT_H
|
||||
|
||||
@@ -7,3 +7,8 @@ MainView::MainView()
|
||||
MainView::~MainView()
|
||||
{
|
||||
}
|
||||
|
||||
int MainView::confirm(const std::string& message)
|
||||
{
|
||||
return confirm(message, std::vector<std::string>());
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define MAIN_VIEW_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "component/view/ViewLayout.h"
|
||||
|
||||
@@ -16,6 +17,9 @@ public:
|
||||
virtual void setTitle(const std::string& title) = 0;
|
||||
virtual void activateWindow() = 0;
|
||||
virtual void updateRecentProjectMenu() = 0;
|
||||
|
||||
virtual int confirm(const std::string& message);
|
||||
virtual int confirm(const std::string& message, const std::vector<std::string>& options) = 0;
|
||||
};
|
||||
|
||||
#endif // MAIN_VIEW_H
|
||||
|
||||
@@ -10,9 +10,10 @@
|
||||
#include "utility/utilityString.h"
|
||||
#include "utility/Version.h"
|
||||
|
||||
SqliteStorage::SqliteStorage(const std::string& dbFilePath)
|
||||
SqliteStorage::SqliteStorage(const FilePath& dbFilePath)
|
||||
: m_dbFilePath(dbFilePath)
|
||||
{
|
||||
m_database.open(dbFilePath.c_str());
|
||||
m_database.open(m_dbFilePath.str().c_str());
|
||||
|
||||
m_database.execDML("PRAGMA foreign_keys=ON;");
|
||||
}
|
||||
@@ -22,23 +23,17 @@ SqliteStorage::~SqliteStorage()
|
||||
m_database.close();
|
||||
}
|
||||
|
||||
bool SqliteStorage::init()
|
||||
void SqliteStorage::init()
|
||||
{
|
||||
Version version = getVersion();
|
||||
|
||||
if (version.isEmpty())
|
||||
{
|
||||
setup();
|
||||
return false;
|
||||
}
|
||||
else if (version.isDifferentStorageVersionThan(Version::getApplicationVersion()))
|
||||
{
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +66,11 @@ void SqliteStorage::rollbackTransaction()
|
||||
m_database.execDML("ROLLBACK TRANSACTION;");
|
||||
}
|
||||
|
||||
FilePath SqliteStorage::getDbFilePath() const
|
||||
{
|
||||
return m_dbFilePath;
|
||||
}
|
||||
|
||||
Version SqliteStorage::getVersion() const
|
||||
{
|
||||
std::string versionStr = getMetaValue("version");
|
||||
|
||||
@@ -20,10 +20,10 @@ class Version;
|
||||
class SqliteStorage
|
||||
{
|
||||
public:
|
||||
SqliteStorage(const std::string& dbFilePath);
|
||||
SqliteStorage(const FilePath& dbFilePath);
|
||||
~SqliteStorage();
|
||||
|
||||
bool init();
|
||||
void init();
|
||||
void setup();
|
||||
void clear();
|
||||
|
||||
@@ -31,6 +31,8 @@ public:
|
||||
void commitTransaction();
|
||||
void rollbackTransaction();
|
||||
|
||||
FilePath getDbFilePath() const;
|
||||
|
||||
Version getVersion() const;
|
||||
void setVersion(const Version& version);
|
||||
|
||||
@@ -129,6 +131,7 @@ private:
|
||||
ResultType getFirstResult(const std::string& query) const;
|
||||
|
||||
mutable CppSQLite3DB m_database;
|
||||
FilePath m_dbFilePath;
|
||||
};
|
||||
|
||||
template <typename ResultType>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "settings/ApplicationSettings.h"
|
||||
|
||||
Storage::Storage(const FilePath& dbPath)
|
||||
: m_sqliteStorage(dbPath.str())
|
||||
: m_sqliteStorage(dbPath)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -33,18 +33,23 @@ Storage::~Storage()
|
||||
{
|
||||
}
|
||||
|
||||
FilePath Storage::getDbFilePath() const
|
||||
{
|
||||
return m_sqliteStorage.getDbFilePath();
|
||||
}
|
||||
|
||||
Version Storage::getVersion() const
|
||||
{
|
||||
return m_sqliteStorage.getVersion();
|
||||
}
|
||||
|
||||
bool Storage::init()
|
||||
void Storage::init()
|
||||
{
|
||||
m_commandIndex.addNode(0, NameHierarchy(SearchMatch::getCommandName(SearchMatch::COMMAND_ALL)));
|
||||
m_commandIndex.addNode(0, NameHierarchy(SearchMatch::getCommandName(SearchMatch::COMMAND_ERROR)));
|
||||
m_commandIndex.finishSetup();
|
||||
|
||||
return m_sqliteStorage.init();
|
||||
m_sqliteStorage.init();
|
||||
}
|
||||
|
||||
void Storage::clear()
|
||||
|
||||
@@ -22,9 +22,10 @@ public:
|
||||
Storage(const FilePath& dbPath);
|
||||
virtual ~Storage();
|
||||
|
||||
FilePath getDbFilePath() const;
|
||||
Version getVersion() const;
|
||||
|
||||
bool init();
|
||||
void init();
|
||||
void clear();
|
||||
void clearCaches();
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "settings/ApplicationSettings.h"
|
||||
|
||||
#include "utility/ResourcePaths.h"
|
||||
#include "utility/utility.h"
|
||||
|
||||
std::shared_ptr<ApplicationSettings> ApplicationSettings::s_instance;
|
||||
|
||||
@@ -14,10 +15,21 @@ std::shared_ptr<ApplicationSettings> ApplicationSettings::getInstance()
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
ApplicationSettings::ApplicationSettings()
|
||||
{
|
||||
}
|
||||
|
||||
ApplicationSettings::~ApplicationSettings()
|
||||
{
|
||||
}
|
||||
|
||||
bool ApplicationSettings::operator==(const ApplicationSettings& other) const
|
||||
{
|
||||
return
|
||||
utility::isPermutation<FilePath>(getHeaderSearchPaths(), other.getHeaderSearchPaths()) &&
|
||||
utility::isPermutation<FilePath>(getFrameworkSearchPaths(), other.getFrameworkSearchPaths());
|
||||
}
|
||||
|
||||
int ApplicationSettings::getMaxRecentProjectsCount() const
|
||||
{
|
||||
return 7;
|
||||
@@ -161,10 +173,6 @@ void ApplicationSettings::setCodeSnippetExpandRange(int range)
|
||||
setValue<int>("code/snippet/expand_range", range);
|
||||
}
|
||||
|
||||
ApplicationSettings::ApplicationSettings()
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<FilePath> ApplicationSettings::getRecentProjects() const
|
||||
{
|
||||
std::vector<FilePath> recentProjects;
|
||||
|
||||
@@ -10,8 +10,11 @@ class ApplicationSettings
|
||||
{
|
||||
public:
|
||||
static std::shared_ptr<ApplicationSettings> getInstance();
|
||||
ApplicationSettings();
|
||||
~ApplicationSettings();
|
||||
|
||||
bool operator==(const ApplicationSettings& other) const;
|
||||
|
||||
int getMaxRecentProjectsCount() const;
|
||||
|
||||
// source
|
||||
@@ -77,7 +80,6 @@ public:
|
||||
void setLicenseCheck(const std::string& hash);
|
||||
|
||||
private:
|
||||
ApplicationSettings();
|
||||
ApplicationSettings(const ApplicationSettings&);
|
||||
void operator=(const ApplicationSettings&);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user