Skip to content
Snippets Groups Projects
Commit fcc543c6 authored by Wuttke, Joachim's avatar Wuttke, Joachim
Browse files

src pair Dirs.* extracted from ProjectManager

parent 5ae95b88
No related branches found
No related tags found
1 merge request!2410new global gDirs for default directories and filters; rm warnings from file loaders
......@@ -14,6 +14,7 @@
#include "App/AppOptions.h"
#include "Base/Util/Assert.h"
#include "GUI/Support/Data/Dirs.h"
#include "GUI/Support/Util/Path.h"
#include "GUI/View/Layout/ApplicationSettings.h"
#include "GUI/View/Main/MainWindow.h"
......@@ -28,6 +29,9 @@
#include <QtGlobal>
#include <iostream>
// Global variables
BA_GUI_API_ std::unique_ptr<Dirs> gDirs;
void custom_terminate_handler()
{
try {
......@@ -74,6 +78,8 @@ int main(int argc, char* argv[])
if (!QDir().exists(dir))
QDir().mkpath(dir);
gDirs = std::make_unique<Dirs>();
MainWindow win;
GUI::Global::mainWindow = &win;
......
......@@ -3,7 +3,7 @@
// BornAgain: simulate and fit reflection and scattering
//
//! @file GUI/Support/Data/Dirs.cpp
//! @brief Implements class ProjectManager.
//! @brief Implements class Dirs.
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
......@@ -12,30 +12,16 @@
//
// ************************************************************************************************
#include "GUI/View/Manager/ProjectManager.h"
#include "GUI/Support/Data/Dirs.h"
#include "Base/Util/Assert.h"
#include "GUI/Model/Project/ProjectUtil.h"
#include "GUI/Support/Util/MessageService.h"
#include "GUI/View/Info/MessageBox.h"
#include "GUI/View/Layout/ApplicationSettings.h"
#include "GUI/View/Layout/mainwindow_constants.h"
#include "GUI/View/Manager/AutosaveController.h"
#include "GUI/View/Manager/NewProjectDialog.h"
#include "GUI/View/Manager/ProjectLoadProblemDialog.h"
#include "GUI/View/Tool/Globals.h"
#include <QApplication>
#include <QDateTime>
#include <QFileDialog>
#include <QMessageBox>
#include <QDir>
#include <QFileInfo>
#include <QSettings>
#include <memory>
namespace {
const QString S_PROJECTMANAGER = "ProjectManager";
const QString S_AUTOSAVE = "EnableAutosave";
const QString S_DIRS = "Dirs";
const QString S_DEFAULTPROJECTPATH = "DefaultProjectPath";
const QString S_RECENTPROJECTS = "RecentProjects";
const QString S_LASTUSEDIMPORTDIR = "LastUsedImportDir";
const QString S_LASTUSEDIMPORFILTER1D = "LastUsedImportFilter1D";
const QString S_LASTUSEDIMPORFILTER2D = "LastUsedImportFilter2D";
......@@ -43,41 +29,26 @@ const QString S_LASTUSEDIMPORFILTER2D = "LastUsedImportFilter2D";
} // namespace
ProjectManager* ProjectManager::s_instance = nullptr;
ProjectManager::ProjectManager(QObject* parent)
: QObject(parent)
{
ASSERT(!s_instance); // it's a singleton
s_instance = this;
}
ProjectManager::~ProjectManager()
Dirs::Dirs()
{
s_instance = nullptr;
gDoc.release();
readSettings();
}
ProjectManager* ProjectManager::instance()
Dirs::~Dirs()
{
ASSERT(s_instance);
return s_instance;
writeSettings();
}
//! Reads settings of ProjectManager from global settings.
//! Reads settings of Dirs from global settings.
void ProjectManager::readSettings()
void Dirs::readSettings()
{
QSettings settings;
m_working_directory = QDir::homePath();
if (settings.childGroups().contains(S_PROJECTMANAGER)) {
settings.beginGroup(S_PROJECTMANAGER);
if (!settings.contains(S_AUTOSAVE))
settings.setValue(S_AUTOSAVE, true);
if (settings.childGroups().contains(S_DIRS)) {
settings.beginGroup(S_DIRS);
m_working_directory = settings.value(S_DEFAULTPROJECTPATH).toString();
m_recent_projects = settings.value(S_RECENTPROJECTS).toStringList();
if (settings.contains(S_LASTUSEDIMPORTDIR))
m_import_directory = settings.value(S_LASTUSEDIMPORTDIR, QString()).toString();
......@@ -85,20 +56,17 @@ void ProjectManager::readSettings()
m_import_filter1D = settings.value(S_LASTUSEDIMPORFILTER1D, m_import_filter1D).toString();
m_import_filter2D = settings.value(S_LASTUSEDIMPORFILTER2D, m_import_filter2D).toString();
setAutosaveEnabled(settings.value(S_AUTOSAVE).toBool());
settings.endGroup();
}
}
//! Saves settings of ProjectManager in global settings.
//! Saves settings of Dirs in global settings.
void ProjectManager::writeSettings()
void Dirs::writeSettings()
{
QSettings settings;
settings.beginGroup(S_PROJECTMANAGER);
settings.beginGroup(S_DIRS);
settings.setValue(S_DEFAULTPROJECTPATH, m_working_directory);
settings.setValue(S_RECENTPROJECTS, m_recent_projects);
if (!m_import_directory.isEmpty())
settings.setValue(S_LASTUSEDIMPORTDIR, m_import_directory);
......@@ -108,344 +76,24 @@ void ProjectManager::writeSettings()
settings.endGroup();
}
//! Returns list of recent projects, validates if projects still exists on disk.
QStringList ProjectManager::recentProjects()
{
QStringList updatedList;
for (const QString& fname : m_recent_projects)
if (QFile fin(fname); fin.exists())
updatedList.append(fname);
m_recent_projects = updatedList;
return m_recent_projects;
}
//! Returns name of the current project directory.
QString ProjectManager::projectDir() const
{
if (gDoc)
return gDoc->validProjectDir();
return "";
}
//! Returns directory name which was used by the user to import files.
QString ProjectManager::userImportDir() const
{
if (m_import_directory.isEmpty()) {
if (gDoc)
return gDoc->userExportDir();
return "";
}
return m_import_directory;
} //! Sets user import directory in system settings.
void ProjectManager::setImportDir(const QString& dirname)
void Dirs::setImportDir(const QString& dirname)
{
m_import_directory = dirname;
}
//! Sets user import directory in system settings.
void ProjectManager::setImportDirFromFilePath(const QString& filePath)
void Dirs::setImportDirFromFilePath(const QString& filePath)
{
m_import_directory = QFileInfo(filePath).absolutePath();
}
void ProjectManager::setRecentlyUsedImportFilter1D(const QString& filter)
void Dirs::setRecentlyUsedImportFilter1D(const QString& filter)
{
m_import_filter1D = filter;
}
void ProjectManager::setRecentlyUsedImportFilter2D(const QString& filter)
void Dirs::setRecentlyUsedImportFilter2D(const QString& filter)
{
m_import_filter2D = filter;
}
bool ProjectManager::isAutosaveEnabled() const
{
return static_cast<bool>(m_autosave);
}
AutosaveController* ProjectManager::autosaveController() const
{
return m_autosave.get();
}
void ProjectManager::setAutosaveEnabled(bool value)
{
if (value)
m_autosave = std::make_unique<AutosaveController>();
else
m_autosave.reset();
QSettings settings;
settings.setValue(S_PROJECTMANAGER + "/" + S_AUTOSAVE, value);
}
//! Clears list of recent projects.
void ProjectManager::clearRecentProjects()
{
m_recent_projects.clear();
emit recentListModified();
}
//! Processes new project request (close old project, rise dialog for project name, create project).
ProjectDocument* ProjectManager::newProject()
{
if (!closeCurrentProject())
return nullptr;
createNewProject();
emit documentOpenedOrClosed(true);
return gDoc.get();
}
//! Processes close current project request. Call save/discard/cancel dialog, if necessary.
//! Returns false if saving was canceled.
bool ProjectManager::closeCurrentProject()
{
if (!gDoc)
return true;
if (gDoc->isModified()) {
QMessageBox msgBox;
msgBox.setText("The project has been modified.");
msgBox.setInformativeText("Do you want to save your changes?");
msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Save);
switch (msgBox.exec()) {
case QMessageBox::Save:
if (!saveProject())
return false;
break;
case QMessageBox::Discard:
break;
case QMessageBox::Cancel:
return false;
default:
break;
}
}
deleteCurrentProject();
emit documentOpenedOrClosed(false);
return true;
}
//! Processes save project request.
bool ProjectManager::saveProject(QString projectPullPath)
{
if (projectPullPath.isEmpty()) {
if (gDoc->hasValidNameAndPath())
projectPullPath = gDoc->projectFullPath();
else
projectPullPath = acquireProjectPullPath();
}
if (projectPullPath.isEmpty())
return false;
gDoc->setProjectName(GUI::Util::Project::projectName(projectPullPath));
gDoc->setProjectDir(GUI::Util::Project::projectDir(projectPullPath));
try {
gDoc->saveProjectFileWithData(projectPullPath);
} catch (const std::exception& ex) {
QString message = QString("Failed to save project under '%1'. \n\n").arg(projectPullPath);
message.append("Exception was thrown.\n\n");
message.append(ex.what());
QMessageBox::warning(GUI::Global::mainWindow, "Error while saving project", message);
return false;
}
addToRecentProjects();
return true;
}
//! Processes 'save project as' request.
bool ProjectManager::saveProjectAs()
{
QString projectFileName = acquireProjectPullPath();
if (projectFileName.isEmpty())
return false;
return saveProject(projectFileName);
}
//! Opens existing project. If fname is empty, will popup file selection dialog.
void ProjectManager::openProject(QString projectPullPath)
{
if (!closeCurrentProject())
return;
if (projectPullPath.isEmpty()) {
const QString ext = QString(GUI::Util::Project::projectFileExtension);
projectPullPath = QFileDialog::getOpenFileName(
GUI::Global::mainWindow, "Open project file", workingDirectory(),
"BornAgain project Files (*" + ext + ")", nullptr,
appSettings->useNativeFileDialog() ? QFileDialog::Options()
: QFileDialog::DontUseNativeDialog);
if (projectPullPath.isEmpty())
return;
}
createNewProject();
MessageService messageService;
const auto readResult = loadProject(projectPullPath, messageService);
if (readResult == ProjectDocument::ReadResult::ok)
addToRecentProjects();
else if (readResult == ProjectDocument::ReadResult::error) {
riseProjectLoadFailedDialog(messageService);
deleteCurrentProject();
} else if (readResult == ProjectDocument::ReadResult::warning) {
riseProjectLoadProblemDialog(messageService);
addToRecentProjects();
}
if (gDoc)
emit documentOpenedOrClosed(true);
}
//! Calls dialog window to define project path and name.
void ProjectManager::createNewProject()
{
if (gDoc)
throw std::runtime_error("ProjectManager::createNewProject -> Project already exists");
gDoc.reset(new ProjectDocument);
if (m_autosave)
m_autosave->setDocument(gDoc.get());
gDoc->setProjectName("Untitled");
connect(gDoc.get(), &ProjectDocument::modifiedStateChanged, this,
&ProjectManager::documentModified);
}
void ProjectManager::deleteCurrentProject()
{
emit aboutToCloseDocument();
if (m_autosave)
m_autosave->removeAutosaveDir();
gDoc.release();
}
//! Load project data from file name. If autosave info exists, opens dialog for project restore.
ProjectDocument::ReadResult ProjectManager::loadProject(const QString& fullPathAndName,
MessageService& messageService)
{
auto readResult = ProjectDocument::ReadResult::ok;
const bool useAutosave = GUI::Util::Project::hasAutosavedData(fullPathAndName);
const QString autosaveFullPath = GUI::Util::Project::autosaveFullPath(fullPathAndName);
if (qApp)
QApplication::setOverrideCursor(Qt::WaitCursor);
if (useAutosave && restoreProjectDialog(fullPathAndName, autosaveFullPath)) {
readResult = gDoc->loadProjectFileWithData(autosaveFullPath, messageService);
gDoc->setProjectFullPath(fullPathAndName);
// restored project should be marked by '*'
gDoc->setModified();
} else {
readResult = gDoc->loadProjectFileWithData(fullPathAndName, messageService);
}
if (qApp)
QApplication::restoreOverrideCursor();
return readResult;
}
//! Returns project file name from dialog. Returns empty string if dialog was canceled.
QString ProjectManager::acquireProjectPullPath()
{
NewProjectDialog dialog(GUI::Global::mainWindow, workingDirectory(), untitledProjectName());
if (dialog.exec() != QDialog::Accepted)
return "";
m_working_directory = dialog.getWorkingDirectory();
return dialog.getProjectFileName();
}
//! Add name of the current project to the name of recent projects
void ProjectManager::addToRecentProjects()
{
QString fname = gDoc->projectFullPath();
m_recent_projects.removeAll(fname);
m_recent_projects.prepend(fname);
while (m_recent_projects.size() > GUI::Style::MAX_RECENT_PROJECTS)
m_recent_projects.removeLast();
emit recentListModified();
}
//! Returns default project path.
//! Will return 'Untitled' if the directory with such name doesn't exist in project
//! path. Otherwise will return Untitled1, Untitled2 etc.
QString ProjectManager::untitledProjectName()
{
QString result = "Untitled";
QDir projectDir = workingDirectory() + "/" + result;
if (projectDir.exists()) {
for (size_t i = 1; i < 99; ++i) {
result = QString("Untitled") + QString::number(i);
projectDir.setPath(workingDirectory() + "/" + result);
if (!projectDir.exists())
break;
}
}
return result;
}
void ProjectManager::riseProjectLoadFailedDialog(const MessageService& messageService)
{
QString message = QString("Failed to load the project '%1' \n\n").arg(gDoc->projectFullPath());
for (const auto& details : messageService.errors())
message.append(details + "\n");
QMessageBox::warning(GUI::Global::mainWindow, "Error while opening project file", message);
}
void ProjectManager::riseProjectLoadProblemDialog(const MessageService& messageService)
{
auto* problemDialog = new ProjectLoadProblemDialog(messageService.warnings(true));
problemDialog->show();
problemDialog->raise();
}
//! Rises dialog if the project should be restored from autosave. Returns true, if yes.
bool ProjectManager::restoreProjectDialog(const QString& projectFileName,
const QString autosaveName)
{
const QString title("Recover project");
const QString lmProject =
QFileInfo(projectFileName).lastModified().toString("hh:mm:ss, MMMM d, yyyy");
const QString lmAutoSave =
QFileInfo(autosaveName).lastModified().toString("hh:mm:ss, MMMM d, yyyy");
QString message = QString("Project '%1' contains autosaved data.\n\n"
"Project saved at %2\nAutosave from %3")
.arg(GUI::Util::Project::projectName(projectFileName))
.arg(lmProject)
.arg(lmAutoSave);
return GUI::Message::question(GUI::Global::mainWindow, title, message,
"\nDo you want to restore from autosave?\n",
"Yes, please restore.", "No, keep loading original");
}
......@@ -3,7 +3,7 @@
// BornAgain: simulate and fit reflection and scattering
//
//! @file GUI/Support/Data/Dirs.h
//! @brief Defines class ProjectManager.
//! @brief Defines class Dirs.
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
......@@ -15,26 +15,19 @@
#ifndef BORNAGAIN_GUI_SUPPORT_DATA_DIRS_H
#define BORNAGAIN_GUI_SUPPORT_DATA_DIRS_H
#include "GUI/Model/Project/ProjectDocument.h"
class AutosaveController;
#include "Wrap/WinDllMacros.h"
#include <QStringList>
//! Handles activity related to opening/save projects.
class ProjectManager : public QObject {
Q_OBJECT
class Dirs {
public:
ProjectManager(QObject* parent);
~ProjectManager() override;
Dirs();
~Dirs();
static ProjectManager* instance();
static Dirs* instance();
void readSettings();
void writeSettings();
QStringList recentProjects();
QString projectDir() const;
QString userImportDir() const;
QString recentlyUsedImportFilter1D() const { return m_import_filter1D; }
QString recentlyUsedImportFilter2D() const { return m_import_filter2D; }
void setImportDir(const QString& dirname);
......@@ -42,38 +35,11 @@ public:
void setRecentlyUsedImportFilter1D(const QString& filter);
void setRecentlyUsedImportFilter2D(const QString& filter);
bool isAutosaveEnabled() const;
AutosaveController* autosaveController() const;
signals:
void aboutToCloseDocument();
void documentOpenedOrClosed(bool opened);
void documentModified();
void recentListModified();
public slots:
void setAutosaveEnabled(bool value);
void clearRecentProjects();
ProjectDocument* newProject();
bool closeCurrentProject();
bool saveProject(QString projectPullPath = "");
bool saveProjectAs();
void openProject(QString projectPullPath = "");
private:
void createNewProject();
void deleteCurrentProject();
ProjectDocument::ReadResult loadProject(const QString& fullPathAndName,
MessageService& messageService);
QString acquireProjectPullPath();
void addToRecentProjects();
void readSettings();
void writeSettings();
QString workingDirectory() { return m_working_directory; }
QString untitledProjectName();
void riseProjectLoadFailedDialog(const MessageService& messageService);
void riseProjectLoadProblemDialog(const MessageService& messageService);
bool restoreProjectDialog(const QString& projectFileName, QString autosaveName);
//!< Name of directory where project directory was created.
QString m_working_directory;
......@@ -88,9 +54,10 @@ private:
QString m_import_filter2D;
QStringList m_recent_projects;
std::unique_ptr<AutosaveController> m_autosave;
static ProjectManager* s_instance;
static Dirs* s_instance;
};
BA_GUI_API_ extern std::unique_ptr<Dirs> gDirs;
#endif // BORNAGAIN_GUI_SUPPORT_DATA_DIRS_H
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment