diff --git a/src/NotepadNext/ApplicationSettings.cpp b/src/NotepadNext/ApplicationSettings.cpp index 8914b3892..dbb840aa9 100644 --- a/src/NotepadNext/ApplicationSettings.cpp +++ b/src/NotepadNext/ApplicationSettings.cpp @@ -34,9 +34,18 @@ ApplicationSetting name{#group "/" #name, default};\ } +Settings::Settings(QObject *parent) + : QSettings{parent} +{ +} + +Settings::Settings(const QString &path, QSettings::Format format) + : QSettings(path, format) +{ +} ApplicationSettings::ApplicationSettings(QObject *parent) - : QSettings{parent} + : Settings{parent} { } diff --git a/src/NotepadNext/ApplicationSettings.h b/src/NotepadNext/ApplicationSettings.h index 50d2533b5..1480a346f 100644 --- a/src/NotepadNext/ApplicationSettings.h +++ b/src/NotepadNext/ApplicationSettings.h @@ -25,6 +25,7 @@ #include #include +#include "SessionManager.h" template class ApplicationSetting @@ -45,12 +46,30 @@ class ApplicationSetting inline T getDefault() const { return mCallable ? mCallable() : mDefault ; } inline const char * const key() const { return mKey; } -private: +protected: const char * const mKey; const T mDefault; std::function mCallable; }; +template +class SessionSetting : public ApplicationSetting +{ +}; + +// This macro should be used on any Qt class which uses session settings so they could be saved/reloaded +#define USE_SESSION_SETTINGS \ +public slots: \ + void onSettingsLoaded(const Settings &settings); \ + void onSettingsSaved(Settings &settings); \ +\ +protected: \ + template \ + void initSettingsListener(T *This, SessionManager *manager) \ + { \ + connect(manager, &SessionManager::onSessionSaved, This, &T::onSettingsSaved); \ + connect(manager, &SessionManager::onSessionLoaded, This, &T::onSettingsLoaded); \ + } #define DEFINE_SETTING(name, lname, type)\ public:\ @@ -61,12 +80,13 @@ Q_SIGNAL\ void lname##Changed(type lname);\ -class ApplicationSettings : public QSettings +class Settings : public QSettings { Q_OBJECT public: - explicit ApplicationSettings(QObject *parent = nullptr); + explicit Settings(QObject *parent = nullptr); + Settings(const QString &path, QSettings::Format format); public: template @@ -81,7 +101,15 @@ class ApplicationSettings : public QSettings void set(const ApplicationSetting &setting, const T &value) { setValue(QLatin1String(setting.key()), value); } +}; + +class ApplicationSettings: public Settings +{ + Q_OBJECT + public: + explicit ApplicationSettings(QObject *parent = nullptr); + DEFINE_SETTING(ShowMenuBar, showMenuBar, bool) DEFINE_SETTING(ShowToolBar, showToolBar, bool) DEFINE_SETTING(ShowTabBar, showTabBar, bool) diff --git a/src/NotepadNext/NotepadNext.pro b/src/NotepadNext/NotepadNext.pro index 2c0d66ce4..59807e61b 100644 --- a/src/NotepadNext/NotepadNext.pro +++ b/src/NotepadNext/NotepadNext.pro @@ -91,8 +91,8 @@ SOURCES += \ QRegexSearch.cpp \ widgets/QuickFindWidget.cpp \ RangeAllocator.cpp \ - RecentFilesListManager.cpp \ - RecentFilesListMenuBuilder.cpp \ + RecentListManager.cpp \ + RecentListMenuBuilder.cpp \ RtfConverter.cpp \ SciIFaceTable.cpp \ ScintillaCommenter.cpp \ @@ -170,8 +170,8 @@ HEADERS += \ QRegexSearch.h \ widgets/QuickFindWidget.h \ RangeAllocator.h \ - RecentFilesListManager.h \ - RecentFilesListMenuBuilder.h \ + RecentListManager.h \ + RecentListMenuBuilder.h \ RtfConverter.h \ SciIFaceTable.h \ ScintillaCommenter.h \ diff --git a/src/NotepadNext/NotepadNextApplication.cpp b/src/NotepadNext/NotepadNextApplication.cpp index 92a4e9ac8..c7e78830a 100644 --- a/src/NotepadNext/NotepadNextApplication.cpp +++ b/src/NotepadNext/NotepadNextApplication.cpp @@ -19,7 +19,7 @@ #include "MainWindow.h" #include "NotepadNextApplication.h" -#include "RecentFilesListManager.h" +#include "RecentListManager.h" #include "EditorManager.h" #include "LuaExtension.h" #include "DebugManager.h" @@ -44,6 +44,9 @@ #include #endif +#define RECENT_SESSIONS_KEY "App/RecentSessionsList" +#define RECENT_FILES_KEY "App/RecentFilesList" + const SingleApplication::Options opts = SingleApplication::ExcludeAppPath | SingleApplication::ExcludeAppVersion | SingleApplication::SecondaryNotification; template <> @@ -136,7 +139,8 @@ bool NotepadNextApplication::init() luaState = new LuaState(); - recentFilesListManager = new RecentFilesListManager(this); + recentFilesListManager = new RecentListManager(this); + recentSessionsListManager = new RecentListManager(this); editorManager = new EditorManager(settings, this); sessionManager = new SessionManager(this); @@ -227,7 +231,7 @@ bool NotepadNextApplication::init() if (settings->restorePreviousSession()) { qInfo("Restoring previous session"); - sessionManager->loadSession(window); + sessionManager->loadDefaultSession(window); } openFiles(parser.positionalArguments()); @@ -464,12 +468,14 @@ void NotepadNextApplication::openFiles(const QStringList &files) void NotepadNextApplication::loadSettings() { - recentFilesListManager->setFileList(getSettings()->value("App/RecentFilesList").toStringList()); + recentFilesListManager->setFileList(getSettings()->value(RECENT_FILES_KEY).toStringList()); + recentSessionsListManager->setFileList(getSettings()->value(RECENT_SESSIONS_KEY).toStringList()); } void NotepadNextApplication::saveSettings() { - getSettings()->setValue("App/RecentFilesList", recentFilesListManager->fileList()); + getSettings()->setValue(RECENT_FILES_KEY, recentFilesListManager->fileList()); + getSettings()->setValue(RECENT_SESSIONS_KEY, recentSessionsListManager->fileList()); } MainWindow *NotepadNextApplication::createNewWindow() @@ -491,7 +497,7 @@ MainWindow *NotepadNextApplication::createNewWindow() } } - getSessionManager()->saveSession(window); + getSessionManager()->saveCurrentSession(window); }); return window; diff --git a/src/NotepadNext/NotepadNextApplication.h b/src/NotepadNext/NotepadNextApplication.h index cdf48ca2c..8b94c0465 100644 --- a/src/NotepadNext/NotepadNextApplication.h +++ b/src/NotepadNext/NotepadNextApplication.h @@ -31,7 +31,7 @@ class MainWindow; class LuaState; class EditorManager; -class RecentFilesListManager; +class RecentListManager; class ScintillaNext; class SessionManager; class TranslationManager; @@ -46,7 +46,8 @@ class NotepadNextApplication : public SingleApplication bool init(); - RecentFilesListManager *getRecentFilesListManager() const { return recentFilesListManager; } + RecentListManager *getRecentFilesListManager() const { return recentFilesListManager; } + RecentListManager *getRecentSessionsListManager() const { return recentSessionsListManager; } EditorManager *getEditorManager() const { return editorManager; } SessionManager *getSessionManager() const; TranslationManager *getTranslationManager() const { return translationManager; }; @@ -82,7 +83,8 @@ private slots: void loadSettings(); EditorManager *editorManager; - RecentFilesListManager *recentFilesListManager; + RecentListManager *recentFilesListManager; + RecentListManager *recentSessionsListManager; ApplicationSettings *settings; SessionManager *sessionManager; TranslationManager *translationManager; diff --git a/src/NotepadNext/RecentFilesListManager.cpp b/src/NotepadNext/RecentListManager.cpp similarity index 71% rename from src/NotepadNext/RecentFilesListManager.cpp rename to src/NotepadNext/RecentListManager.cpp index 29759224d..080481027 100644 --- a/src/NotepadNext/RecentFilesListManager.cpp +++ b/src/NotepadNext/RecentListManager.cpp @@ -17,14 +17,14 @@ */ -#include "RecentFilesListManager.h" +#include "RecentListManager.h" -RecentFilesListManager::RecentFilesListManager(QObject *parent) : - QObject(parent) +RecentListManager::RecentListManager(QObject *parent) : + QObject(parent), limit(10) { } -void RecentFilesListManager::addFile(const QString &filePath) +void RecentListManager::addFile(const QString &filePath) { qInfo(Q_FUNC_INFO); @@ -32,37 +32,37 @@ void RecentFilesListManager::addFile(const QString &filePath) removeFile(filePath); // Set a limit on how many can be in the list - if (recentFiles.size() >= 10) { + if (recentFiles.size() >= limit) { recentFiles.removeLast(); } recentFiles.prepend(filePath); } -void RecentFilesListManager::removeFile(const QString &filePath) +void RecentListManager::removeFile(const QString &filePath) { recentFiles.removeOne(filePath); } -void RecentFilesListManager::clear() +void RecentListManager::clear() { // Clear the file list recentFiles.clear(); } -QString RecentFilesListManager::mostRecentFile() const +QString RecentListManager::mostRecentFile() const { Q_ASSERT(!recentFiles.empty()); return recentFiles.first(); } -QStringList RecentFilesListManager::fileList() const +QStringList RecentListManager::fileList() const { return recentFiles; } -void RecentFilesListManager::setFileList(const QStringList &list) +void RecentListManager::setFileList(const QStringList &list) { clear(); recentFiles.append(list); diff --git a/src/NotepadNext/RecentFilesListManager.h b/src/NotepadNext/RecentListManager.h similarity index 84% rename from src/NotepadNext/RecentFilesListManager.h rename to src/NotepadNext/RecentListManager.h index 74a40a1d7..0579c093c 100644 --- a/src/NotepadNext/RecentFilesListManager.h +++ b/src/NotepadNext/RecentListManager.h @@ -17,18 +17,18 @@ */ -#ifndef RECENTFILESLISTMANAGER_H -#define RECENTFILESLISTMANAGER_H +#ifndef RECENTLISTMANAGER_H +#define RECENTLISTMANAGER_H #include #include -class RecentFilesListManager : public QObject +class RecentListManager : public QObject { Q_OBJECT public: - explicit RecentFilesListManager(QObject *parent = Q_NULLPTR); + explicit RecentListManager(QObject *parent = Q_NULLPTR); QString mostRecentFile() const; QStringList fileList() const; @@ -43,6 +43,7 @@ public slots: private: QStringList recentFiles; + int limit; }; -#endif // RECENTFILESLISTMANAGER_H +#endif // RECENTLISTMANAGER_H diff --git a/src/NotepadNext/RecentFilesListMenuBuilder.cpp b/src/NotepadNext/RecentListMenuBuilder.cpp similarity index 74% rename from src/NotepadNext/RecentFilesListMenuBuilder.cpp rename to src/NotepadNext/RecentListMenuBuilder.cpp index a5a2d97ab..3238c1077 100644 --- a/src/NotepadNext/RecentFilesListMenuBuilder.cpp +++ b/src/NotepadNext/RecentListMenuBuilder.cpp @@ -17,29 +17,34 @@ */ -#include "RecentFilesListMenuBuilder.h" +#include "RecentListMenuBuilder.h" #include #include #include -RecentFilesListMenuBuilder::RecentFilesListMenuBuilder(RecentFilesListManager *manager) : +RecentListMenuBuilder::RecentListMenuBuilder(RecentListManager *manager, int limit) : QObject(manager), - manager(manager) + manager(manager), + limit(limit) { } -void RecentFilesListMenuBuilder::populateMenu(QMenu *menu) +void RecentListMenuBuilder::populateMenu(QMenu *menu) { int i = 0; + while (menu->actions().size() > limit) { + delete menu->actions().takeLast(); + } + QList recentFileListActions; for (const QString &file : manager->fileList()) { ++i; QAction *action = new QAction(QString("%1%2: %3").arg(i < 10 ? "&" : "").arg(i).arg(QDir::toNativeSeparators(file)), menu); action->setData(file); - connect(action, &QAction::triggered, this, &RecentFilesListMenuBuilder::recentFileActionTriggered); + connect(action, &QAction::triggered, this, &RecentListMenuBuilder::recentFileActionTriggered); recentFileListActions.append(action); } @@ -47,7 +52,7 @@ void RecentFilesListMenuBuilder::populateMenu(QMenu *menu) menu->addActions(recentFileListActions); } -void RecentFilesListMenuBuilder::recentFileActionTriggered() +void RecentListMenuBuilder::recentFileActionTriggered() { qInfo(Q_FUNC_INFO); diff --git a/src/NotepadNext/RecentFilesListMenuBuilder.h b/src/NotepadNext/RecentListMenuBuilder.h similarity index 78% rename from src/NotepadNext/RecentFilesListMenuBuilder.h rename to src/NotepadNext/RecentListMenuBuilder.h index 7112ae415..a6d6cb48b 100644 --- a/src/NotepadNext/RecentFilesListMenuBuilder.h +++ b/src/NotepadNext/RecentListMenuBuilder.h @@ -17,20 +17,20 @@ */ -#ifndef RECENTFILESLISTMENUBUILDER_H -#define RECENTFILESLISTMENUBUILDER_H +#ifndef RECENTLISTMENUBUILDER_H +#define RECENTLISTMENUBUILDER_H -#include "RecentFilesListManager.h" +#include "RecentListManager.h" #include class QMenu; -class RecentFilesListMenuBuilder : public QObject +class RecentListMenuBuilder : public QObject { Q_OBJECT public: - explicit RecentFilesListMenuBuilder(RecentFilesListManager *manager); + explicit RecentListMenuBuilder(RecentListManager *manager, int limit); void populateMenu(QMenu *menu); signals: @@ -40,7 +40,8 @@ private slots: void recentFileActionTriggered(); private: - RecentFilesListManager *manager; + RecentListManager *manager; + int limit; }; #endif // RECENTFILESLISTMENUBUILDER_H diff --git a/src/NotepadNext/SessionManager.cpp b/src/NotepadNext/SessionManager.cpp index 9249fcb27..da3543b49 100644 --- a/src/NotepadNext/SessionManager.cpp +++ b/src/NotepadNext/SessionManager.cpp @@ -28,6 +28,8 @@ #include #include +#define SETTINGS_FILE "session.ini" +#define SETTINGS_DIR ".nnsession" static QString RandomSessionFileName() { @@ -54,7 +56,7 @@ static QList QVariantListToQList(const QVariantList &variantList) { } SessionManager::SessionManager(NotepadNextApplication *app, SessionFileTypes types) - : app(app) + : app(app), useCustomSessionFolder(false) { setSessionFileTypes(types); } @@ -66,12 +68,22 @@ void SessionManager::setSessionFileTypes(SessionFileTypes types) QDir SessionManager::sessionDirectory() const { - QDir d(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); + if (useCustomSessionFolder) { + QDir d(customSessionPath); + if (!d.cd(SETTINGS_DIR)) + { + qCritical("Unable to open session dir %s", d.absolutePath().toUtf8().constData()); + } + return d; + } + else { + QDir d(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); - d.mkpath("session"); - d.cd("session"); + d.mkpath("session"); + d.cd("session"); - return d; + return d; + } } void SessionManager::saveIntoSessionDirectory(ScintillaNext *editor, const QString &sessionFileName) const @@ -101,17 +113,25 @@ SessionManager::SessionFileType SessionManager::determineType(ScintillaNext *edi void SessionManager::clear() const { - clearSettings(); + qInfo(Q_FUNC_INFO); + if (useCustomSessionFolder) { + QSettings *settings = new QSettings(sessionDirectory().absolutePath() + QDir::separator() + SETTINGS_FILE, + QSettings::IniFormat); + clearSettings(settings); + delete settings; + } + else { + ApplicationSettings appSettings; + clearSettings(&appSettings); + } clearDirectory(); } -void SessionManager::clearSettings() const +void SessionManager::clearSettings(QSettings *settings) const { - ApplicationSettings settings;; - // Clear everything out. There can be left over entries that are no longer needed - settings.beginGroup("CurrentSession"); - settings.remove(""); + settings->beginGroup("CurrentSession"); + settings->remove(""); } void SessionManager::clearDirectory() const @@ -119,11 +139,63 @@ void SessionManager::clearDirectory() const QDir d = sessionDirectory(); for (const QString &f : d.entryList()) { - d.remove(f); + if (f != SETTINGS_FILE) { + d.remove(f); + } } } -void SessionManager::saveSession(MainWindow *window) +bool SessionManager::saveSessionTo(MainWindow *window, const QString &path) +{ + useCustomSessionFolder = true; + customSessionPath = path; + SessionFileTypes tmp = fileTypes; + QDir dir(path); + dir.mkdir(SETTINGS_DIR); + if (!dir.cd(SETTINGS_DIR)) + { + return false; + } + + Settings settings(sessionDirectory().absolutePath() + QDir::separator() + SETTINGS_FILE, QSettings::IniFormat); + + settings.beginGroup("Session"); + + setSessionFileTypes(tmp | SavedFile); + saveSession(window, settings); + setSessionFileTypes(tmp); + settings.endGroup(); + + emit onSessionSaved(settings); + + settings.sync(); + + return true; +} + +void SessionManager::saveCurrentSession(MainWindow *window) +{ + if (useCustomSessionFolder) { + saveSessionTo(window, customSessionPath); + } + else { + saveDefaultSession(window); + } +} + +void SessionManager::saveDefaultSession(MainWindow *window) +{ + useCustomSessionFolder = false; + ApplicationSettings appSettings; + appSettings.beginGroup("CurrentSession"); + saveSession(window, appSettings); + appSettings.endGroup(); + + + emit onSessionSaved(appSettings); +} + +void SessionManager::saveSession(MainWindow *window, QSettings &settings) { qInfo(Q_FUNC_INFO); @@ -136,9 +208,7 @@ void SessionManager::saveSession(MainWindow *window) const ScintillaNext *currentEditor = window->currentEditor(); int currentEditorIndex = 0; - ApplicationSettings settings;; - - settings.beginGroup("CurrentSession"); + ApplicationSettings appSettings; settings.beginWriteArray("OpenedFiles"); @@ -173,22 +243,75 @@ void SessionManager::saveSession(MainWindow *window) settings.endArray(); settings.setValue("CurrentEditorIndex", currentEditorIndex); +} +void SessionManager::loadDefaultSession(MainWindow *window) +{ + ApplicationSettings settings; + + settings.beginGroup("CurrentSession"); + ScintillaNext *currentEditor = loadSession(window, settings); settings.endGroup(); + emit onSessionLoaded(settings); + + if (currentEditor) { + window->switchToEditor(currentEditor); + } } -void SessionManager::loadSession(MainWindow *window) +bool SessionManager::loadSessionFrom(MainWindow *window, const QString &path) { - qInfo(Q_FUNC_INFO); + SessionFileTypes tmp = fileTypes; + QDir dir(path); + if (!dir.cd(SETTINGS_DIR)) + { + return false; + } + useCustomSessionFolder = true; + customSessionPath = path; + if (!QFile::exists(dir.absolutePath() + QDir::separator() + SETTINGS_FILE)) + { + return false; + } + Settings settings(sessionDirectory().absolutePath() + QDir::separator() + SETTINGS_FILE, QSettings::IniFormat); - ApplicationSettings settings;; + settings.beginGroup("Session"); + ScintillaNext *currentEditor = loadSession(window, settings); + settings.endGroup(); - settings.beginGroup("CurrentSession"); + settings.beginGroup("FolderAsWorkspace"); + settings.value("RootPath"); + settings.endGroup(); + + emit onSessionLoaded(settings); + + if (currentEditor) { + window->switchToEditor(currentEditor); + } + return true; +} + +ScintillaNext *SessionManager::loadSession(MainWindow *window, QSettings &settings) +{ + qInfo(Q_FUNC_INFO); ScintillaNext *currentEditor = Q_NULLPTR; const int currentEditorIndex = settings.value("CurrentEditorIndex").toInt(); const int size = settings.beginReadArray("OpenedFiles"); + for (auto &editor : window->editors()) { + if (editor->isFile()) { + if (editor->isSavedToDisk()) { + editor->close(); + } + } + else { + if (!editor->modify()) { + editor->close(); + } + } + } + // NOTE: In theory the fileTypes should determine what is loaded, however if the session fileTypes // change from the last time it was saved then it means the settings were manually altered outside of the app, // which is non-standard behavior, so just load anything in the file @@ -226,12 +349,7 @@ void SessionManager::loadSession(MainWindow *window) } settings.endArray(); - - settings.endGroup(); - - if (currentEditor) { - window->switchToEditor(currentEditor); - } + return currentEditor; } bool SessionManager::willFileGetStoredInSession(ScintillaNext *editor) const diff --git a/src/NotepadNext/SessionManager.h b/src/NotepadNext/SessionManager.h index 86c2efc03..dce9b42fc 100644 --- a/src/NotepadNext/SessionManager.h +++ b/src/NotepadNext/SessionManager.h @@ -28,9 +28,12 @@ class ScintillaNext; class MainWindow; class NotepadNextApplication; +class Settings; -class SessionManager +class SessionManager: public QObject { + Q_OBJECT + public: enum SessionFileType { None = 0, @@ -47,19 +50,30 @@ class SessionManager void clear() const; - void saveSession(MainWindow *window); - void loadSession(MainWindow *window); + bool saveSessionTo(MainWindow *window, const QString &path); + void saveCurrentSession(MainWindow *window); + void loadDefaultSession(MainWindow *window); + bool loadSessionFrom(MainWindow *window, const QString &path); bool willFileGetStoredInSession(ScintillaNext *editor) const; -private: QDir sessionDirectory() const; + bool isCustomSessionFolder() const { return useCustomSessionFolder; } + +signals: + void onSessionSaved(Settings &settings); + void onSessionLoaded(Settings &settings); + +private: + void saveSession(MainWindow *window, QSettings &settings); + void saveDefaultSession(MainWindow *window); + ScintillaNext *loadSession(MainWindow *window, QSettings &settings); void saveIntoSessionDirectory(ScintillaNext *editor, const QString &sessionFileName) const; SessionFileType determineType(ScintillaNext *editor) const; - void clearSettings() const; + void clearSettings(QSettings *settings) const; void clearDirectory() const; void storeFileDetails(ScintillaNext *editor, QSettings &settings); @@ -76,6 +90,9 @@ class SessionManager NotepadNextApplication *app; SessionFileTypes fileTypes; + + bool useCustomSessionFolder; + QString customSessionPath; }; Q_DECLARE_OPERATORS_FOR_FLAGS(SessionManager::SessionFileTypes) diff --git a/src/NotepadNext/dialogs/MainWindow.cpp b/src/NotepadNext/dialogs/MainWindow.cpp index 1eb56c5a8..e08b77f4d 100644 --- a/src/NotepadNext/dialogs/MainWindow.cpp +++ b/src/NotepadNext/dialogs/MainWindow.cpp @@ -53,8 +53,8 @@ #include "ScintillaNext.h" -#include "RecentFilesListManager.h" -#include "RecentFilesListMenuBuilder.h" +#include "RecentListManager.h" +#include "RecentListMenuBuilder.h" #include "EditorManager.h" #include "LuaConsoleDock.h" @@ -182,20 +182,23 @@ MainWindow::MainWindow(NotepadNextApplication *app) : } }); - connect(ui->actionClearRecentFilesList, &QAction::triggered, app->getRecentFilesListManager(), &RecentFilesListManager::clear); + connect(ui->actionClearRecentFilesList, &QAction::triggered, app->getRecentFilesListManager(), &RecentListManager::clear); connect(ui->actionMoveToTrash, &QAction::triggered, this, &MainWindow::moveCurrentFileToTrash); - RecentFilesListMenuBuilder *recentFileListMenuBuilder = new RecentFilesListMenuBuilder(app->getRecentFilesListManager()); + // NOTE: its unfortunate that this has to be hard coded, but there's no way + // to easily determine what should or shouldn't be there + RecentListMenuBuilder *recentFileListMenuBuilder = new RecentListMenuBuilder(app->getRecentFilesListManager(), 4); connect(ui->menuRecentFiles, &QMenu::aboutToShow, this, [=]() { - // NOTE: its unfortunate that this has to be hard coded, but there's no way - // to easily determine what should or shouldn't be there - while (ui->menuRecentFiles->actions().size() > 4) { - delete ui->menuRecentFiles->actions().takeLast(); - } - recentFileListMenuBuilder->populateMenu(ui->menuRecentFiles); }); + connect(recentFileListMenuBuilder, &RecentListMenuBuilder::fileOpenRequest, this, &MainWindow::openFile); + + RecentListMenuBuilder *recentSessionsListMenuBuilder = new RecentListMenuBuilder(app->getRecentSessionsListManager(), 3); + connect(ui->menuSessions, &QMenu::aboutToShow, this, [=]() { + recentSessionsListMenuBuilder->populateMenu(ui->menuSessions); + }); + connect(recentSessionsListMenuBuilder, &RecentListMenuBuilder::fileOpenRequest, this, &MainWindow::loadSession); connect(ui->actionRestoreRecentlyClosedFile, &QAction::triggered, this, [=]() { if (app->getRecentFilesListManager()->count() > 0) { @@ -207,8 +210,6 @@ MainWindow::MainWindow(NotepadNextApplication *app) : openFileList(app->getRecentFilesListManager()->fileList()); }); - connect(recentFileListMenuBuilder, &RecentFilesListMenuBuilder::fileOpenRequest, this, &MainWindow::openFile); - QActionGroup *eolActionGroup = new QActionGroup(this); eolActionGroup->addAction(ui->actionWindows); eolActionGroup->addAction(ui->actionUnix); @@ -805,7 +806,7 @@ MainWindow::MainWindow(NotepadNextApplication *app) : hexViewerDock->toggleViewAction() }); - FolderAsWorkspaceDock *fawDock = new FolderAsWorkspaceDock(this); + FolderAsWorkspaceDock *fawDock = new FolderAsWorkspaceDock(app, this); fawDock->hide(); addDockWidget(Qt::LeftDockWidgetArea, fawDock); ui->menuView->addAction(fawDock->toggleViewAction()); @@ -968,6 +969,51 @@ ScintillaNext *MainWindow::getInitialEditor() return Q_NULLPTR; } +void MainWindow::on_actionOpenSessionFile_triggered() +{ + FolderAsWorkspaceDock *fawDock = findChild(); + // TODO: if there is active session - use it + QString dir = QFileDialog::getExistingDirectory(this, tr("Load Session From Folder"), fawDock->rootPath(), QFileDialog::ShowDirsOnly); + if (!dir.isEmpty()) { + app->getSessionManager()->saveCurrentSession(this); + if (!app->getSessionManager()->loadSessionFrom(this, dir)) + { + qCritical("Unable to load from %s", dir.toUtf8().constData()); + QMessageBox::critical(this, "Error", tr("Unable to load from %1").arg(dir)); + } + else { + app->getRecentSessionsListManager()->addFile(dir); + } + } +} + +void MainWindow::loadSession(const QString &filePath) +{ + app->getSessionManager()->saveCurrentSession(this); + if (!app->getSessionManager()->loadSessionFrom(this, filePath)) { + qCritical("Unable to load from %s", filePath.toUtf8().constData()); + app->getRecentSessionsListManager()->removeFile(filePath); + } +} + +void MainWindow::on_actionSaveSession_triggered() +{ + FolderAsWorkspaceDock *fawDock = findChild(); + // TODO: if there is active session - use it + SessionManager *sessionManager = app->getSessionManager(); + QString dir = QFileDialog::getExistingDirectory(this, tr("Save Session To Folder"), fawDock->rootPath(), QFileDialog::ShowDirsOnly); + if (!dir.isEmpty()) { + // TODO: save active session if any + if (!sessionManager->saveSessionTo(this, dir)) { + qCritical("Unable to save to %s", dir.toUtf8().constData()); + QMessageBox::critical(this, "Error", tr("Unable to save to %1").arg(dir)); + } + else { + app->getRecentSessionsListManager()->addFile(dir); + } + } +} + void MainWindow::openFileList(const QStringList &fileNames) { qInfo(Q_FUNC_INFO); diff --git a/src/NotepadNext/dialogs/MainWindow.h b/src/NotepadNext/dialogs/MainWindow.h index f6907bcf6..8fd7b6870 100644 --- a/src/NotepadNext/dialogs/MainWindow.h +++ b/src/NotepadNext/dialogs/MainWindow.h @@ -139,6 +139,9 @@ private slots: void languageMenuTriggered(); void checkForUpdatesFinished(QString url); void activateEditor(ScintillaNext *editor); + void on_actionSaveSession_triggered(); + void on_actionOpenSessionFile_triggered(); + void loadSession(const QString &filePath); private: Ui::MainWindow *ui = Q_NULLPTR; diff --git a/src/NotepadNext/dialogs/MainWindow.ui b/src/NotepadNext/dialogs/MainWindow.ui index d8885cb1d..760a5ed59 100644 --- a/src/NotepadNext/dialogs/MainWindow.ui +++ b/src/NotepadNext/dialogs/MainWindow.ui @@ -71,6 +71,15 @@ + + + Sessions + + + + + + @@ -90,6 +99,8 @@ + + @@ -1362,6 +1373,24 @@ Alt+Shift+9 + + + Save Session + + + + + Open Session File + + + + + false + + + No Recent Sessions + + Toggle Overtype diff --git a/src/NotepadNext/docks/FolderAsWorkspaceDock.cpp b/src/NotepadNext/docks/FolderAsWorkspaceDock.cpp index f1dd3ed5d..bbb0bbf21 100644 --- a/src/NotepadNext/docks/FolderAsWorkspaceDock.cpp +++ b/src/NotepadNext/docks/FolderAsWorkspaceDock.cpp @@ -18,14 +18,16 @@ #include "FolderAsWorkspaceDock.h" -#include "ApplicationSettings.h" #include "ui_FolderAsWorkspaceDock.h" +#include "ApplicationSettings.h" +#include "NotepadNextApplication.h" + #include -ApplicationSetting rootPathSetting{"FolderAsWorkspace/RootPath"}; +SessionSetting rootPathSetting{"FolderAsWorkspace/RootPath"}; -FolderAsWorkspaceDock::FolderAsWorkspaceDock(QWidget *parent) : +FolderAsWorkspaceDock::FolderAsWorkspaceDock(NotepadNextApplication* app, QWidget *parent) : QDockWidget(parent), ui(new Ui::FolderAsWorkspaceDock), model(new QFileSystemModel(this)) @@ -43,10 +45,22 @@ FolderAsWorkspaceDock::FolderAsWorkspaceDock(QWidget *parent) : } }); + initSettingsListener(this, app->getSessionManager()); + ApplicationSettings settings; setRootPath(settings.get(rootPathSetting)); } +void FolderAsWorkspaceDock::onSettingsSaved(Settings &settings) +{ + settings.set(rootPathSetting, rootPath()); +} + +void FolderAsWorkspaceDock::onSettingsLoaded(const Settings &settings) +{ + setRootPath(settings.get(rootPathSetting)); +} + FolderAsWorkspaceDock::~FolderAsWorkspaceDock() { delete ui; diff --git a/src/NotepadNext/docks/FolderAsWorkspaceDock.h b/src/NotepadNext/docks/FolderAsWorkspaceDock.h index 085254905..c406d8075 100644 --- a/src/NotepadNext/docks/FolderAsWorkspaceDock.h +++ b/src/NotepadNext/docks/FolderAsWorkspaceDock.h @@ -21,19 +21,23 @@ #define FOLDERASWORKSPACEDOCK_H #include +#include "ApplicationSettings.h" namespace Ui { class FolderAsWorkspaceDock; } class QFileSystemModel; +class NotepadNextApplication; class FolderAsWorkspaceDock : public QDockWidget { Q_OBJECT + USE_SESSION_SETTINGS + public: - explicit FolderAsWorkspaceDock(QWidget *parent = nullptr); + explicit FolderAsWorkspaceDock(NotepadNextApplication* app, QWidget *parent = nullptr); ~FolderAsWorkspaceDock(); void setRootPath(const QString dir);