diff --git a/radiant/CMakeLists.txt b/radiant/CMakeLists.txt index 7e738e9e40..90dede42a3 100644 --- a/radiant/CMakeLists.txt +++ b/radiant/CMakeLists.txt @@ -15,6 +15,7 @@ add_executable(darkradiant log/Console.cpp main.cpp map/AutoSaver.cpp + map/AutoSaveTimer.cpp map/StartupMapLoader.cpp RadiantApp.cpp selection/ManipulateMouseTool.cpp diff --git a/radiant/map/AutoSaveTimer.cpp b/radiant/map/AutoSaveTimer.cpp new file mode 100644 index 0000000000..7b1a78c5ee --- /dev/null +++ b/radiant/map/AutoSaveTimer.cpp @@ -0,0 +1,96 @@ +#include "AutoSaveTimer.h" + +#include "iautosaver.h" +#include "registry/registry.h" + +namespace map +{ + +namespace +{ + constexpr const char* const RKEY_AUTOSAVE_INTERVAL = "user/ui/map/autoSaveInterval"; + constexpr const char* const RKEY_AUTOSAVE_ENABLED = "user/ui/map/autoSaveEnabled"; +} + +AutoSaveTimer::AutoSaveTimer() : + _enabled(false), + _interval(5 * 60) +{} + +AutoSaveTimer::~AutoSaveTimer() +{ + _enabled = false; + stopTimer(); + + // Destroy the timer + _timer.reset(); +} + +void AutoSaveTimer::initialise() +{ + // Add a page to the given group + IPreferencePage& page = GlobalPreferenceSystem().getPage(_("Settings/Autosave")); + + // Add the checkboxes and connect them with the registry key + page.appendCheckBox(_("Enable Autosave"), RKEY_AUTOSAVE_ENABLED); + page.appendSlider(_("Autosave Interval (in minutes)"), RKEY_AUTOSAVE_INTERVAL, 1, 61, 1, 1); + + _timer.reset(new wxTimer(this)); + + Bind(wxEVT_TIMER, &AutoSaveTimer::onIntervalReached, this); + + GlobalRegistry().signalForKey(RKEY_AUTOSAVE_INTERVAL).connect( + sigc::mem_fun(this, &AutoSaveTimer::registryKeyChanged) + ); + GlobalRegistry().signalForKey(RKEY_AUTOSAVE_ENABLED).connect( + sigc::mem_fun(this, &AutoSaveTimer::registryKeyChanged) + ); + + // Refresh all values from the registry right now (this might also start the timer) + registryKeyChanged(); +} + +void AutoSaveTimer::registryKeyChanged() +{ + // Stop the current timer + stopTimer(); + + _enabled = registry::getValue(RKEY_AUTOSAVE_ENABLED); + _interval = registry::getValue(RKEY_AUTOSAVE_INTERVAL) * 60; + + // Start the timer with the new interval + if (_enabled) + { + startTimer(); + } +} + +void AutoSaveTimer::startTimer() +{ + if (!_timer) return; + + _timer->Start(static_cast(_interval * 1000)); +} + +void AutoSaveTimer::stopTimer() +{ + if (!_timer) return; + + _timer->Stop(); +} + +void AutoSaveTimer::onIntervalReached(wxTimerEvent& ev) +{ + if (_enabled && GlobalAutoSaver().runAutosaveCheck()) + { + // Stop the timer before saving + stopTimer(); + + GlobalAutoSaver().performAutosave(); + + // Re-start the timer after saving has finished + startTimer(); + } +} + +} diff --git a/radiant/map/AutoSaveTimer.h b/radiant/map/AutoSaveTimer.h new file mode 100644 index 0000000000..d8cb9cd69a --- /dev/null +++ b/radiant/map/AutoSaveTimer.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include + +namespace map +{ + +/** + * Timer object which repeatedly triggers the automatic map save algorithms + * in the configured intervals. + */ +class AutoSaveTimer final : + public wxEvtHandler, + public sigc::trackable +{ +private: + // TRUE, if autosaving is enabled + bool _enabled; + + // The autosave interval stored in seconds + unsigned long _interval; + + // The timer object that triggers the callback + wxSharedPtr _timer; + +public: + AutoSaveTimer(); + ~AutoSaveTimer(); + + void initialise(); + + // Starts/stops the autosave "countdown" + void startTimer(); + void stopTimer(); + +private: + void registryKeyChanged(); + void onIntervalReached(wxTimerEvent& ev); +}; + +} diff --git a/radiant/map/AutoSaver.cpp b/radiant/map/AutoSaver.cpp index c1d15ef996..689c5436d6 100644 --- a/radiant/map/AutoSaver.cpp +++ b/radiant/map/AutoSaver.cpp @@ -34,8 +34,6 @@ namespace map namespace { // Registry key names - const char* RKEY_AUTOSAVE_ENABLED = "user/ui/map/autoSaveEnabled"; - const char* RKEY_AUTOSAVE_INTERVAL = "user/ui/map/autoSaveInterval"; const char* GKEY_MAP_EXTENSION = "/mapFormat/fileExtension"; std::string constructSnapshotName(const fs::path& snapshotPath, const std::string& mapName, int num) @@ -56,31 +54,13 @@ namespace } AutoMapSaver::AutoMapSaver() : - _enabled(false), _snapshotsEnabled(false), - _interval(5*60), _changes(0) {} -AutoMapSaver::~AutoMapSaver() +void AutoMapSaver::registryKeyChanged() { - assert(!_timer); -} - -void AutoMapSaver::registryKeyChanged() -{ - // Stop the current timer - stopTimer(); - - _enabled = registry::getValue(RKEY_AUTOSAVE_ENABLED); _snapshotsEnabled = registry::getValue(RKEY_AUTOSAVE_SNAPSHOTS_ENABLED); - _interval = registry::getValue(RKEY_AUTOSAVE_INTERVAL) * 60; - - // Start the timer with the new interval - if (_enabled) - { - startTimer(); - } } void AutoMapSaver::clearChanges() @@ -88,20 +68,6 @@ void AutoMapSaver::clearChanges() _changes = 0; } -void AutoMapSaver::startTimer() -{ - if (!_timer) return; - - _timer->Start(static_cast(_interval * 1000)); -} - -void AutoMapSaver::stopTimer() -{ - if (!_timer) return; - - _timer->Stop(); -} - void AutoMapSaver::saveSnapshot() { // Original GtkRadiant comments: @@ -304,29 +270,11 @@ void AutoMapSaver::constructPreferences() // Add a page to the given group IPreferencePage& page = GlobalPreferenceSystem().getPage(_("Settings/Autosave")); - // Add the checkboxes and connect them with the registry key and the according observer - page.appendCheckBox(_("Enable Autosave"), RKEY_AUTOSAVE_ENABLED); - page.appendSlider(_("Autosave Interval (in minutes)"), RKEY_AUTOSAVE_INTERVAL, 1, 61, 1, 1); - page.appendCheckBox(_("Save Snapshots"), RKEY_AUTOSAVE_SNAPSHOTS_ENABLED); page.appendEntry(_("Snapshot folder (relative to map folder)"), RKEY_AUTOSAVE_SNAPSHOTS_FOLDER); page.appendEntry(_("Max total Snapshot size per map (MB)"), RKEY_AUTOSAVE_MAX_SNAPSHOT_FOLDER_SIZE); } -void AutoMapSaver::onIntervalReached(wxTimerEvent& ev) -{ - if (_enabled && runAutosaveCheck()) - { - // Stop the timer before saving - stopTimer(); - - performAutosave(); - - // Re-start the timer after saving has finished - startTimer(); - } -} - void AutoMapSaver::onMapEvent(IMap::MapEvent ev) { // We reset our change count regardless of whether a map @@ -368,21 +316,9 @@ void AutoMapSaver::initialiseModule(const IApplicationContext& ctx) { rMessage() << getName() << "::initialiseModule called." << std::endl; - _timer.reset(new wxTimer(this)); - - Bind(wxEVT_TIMER, &AutoMapSaver::onIntervalReached, this); - - constructPreferences(); - - _signalConnections.push_back(GlobalRegistry().signalForKey(RKEY_AUTOSAVE_INTERVAL).connect( - sigc::mem_fun(this, &AutoMapSaver::registryKeyChanged) - )); _signalConnections.push_back(GlobalRegistry().signalForKey(RKEY_AUTOSAVE_SNAPSHOTS_ENABLED).connect( sigc::mem_fun(this, &AutoMapSaver::registryKeyChanged) )); - _signalConnections.push_back(GlobalRegistry().signalForKey(RKEY_AUTOSAVE_ENABLED).connect( - sigc::mem_fun(this, &AutoMapSaver::registryKeyChanged) - )); // Get notified when the map is loaded afresh _signalConnections.push_back(GlobalMapModule().signal_mapEvent().connect( @@ -391,6 +327,12 @@ void AutoMapSaver::initialiseModule(const IApplicationContext& ctx) // Refresh all values from the registry right now (this might also start the timer) registryKeyChanged(); + + // Add the autosave options after all the modules are done. A cheap solution to let + // the options appear below the Enabled / Interval setting added by the UI + module::GlobalModuleRegistry().signal_allModulesInitialised().connect( + sigc::mem_fun(*this, &AutoMapSaver::constructPreferences) + ); } void AutoMapSaver::shutdownModule() @@ -402,20 +344,8 @@ void AutoMapSaver::shutdownModule() } _signalConnections.clear(); - - _enabled = false; - stopTimer(); - - // Destroy the timer - _timer.reset(); } module::StaticModule staticAutoSaverModule; -AutoMapSaver& AutoSaver() -{ - return *std::static_pointer_cast( - module::GlobalModuleRegistry().getModule(MODULE_AUTOSAVER)); -} - } // namespace map diff --git a/radiant/map/AutoSaver.h b/radiant/map/AutoSaver.h index 8799f98df1..88ae89959a 100644 --- a/radiant/map/AutoSaver.h +++ b/radiant/map/AutoSaver.h @@ -21,21 +21,12 @@ namespace map { class AutoMapSaver final : - public wxEvtHandler, public IAutomaticMapSaver { - // TRUE, if autosaving is enabled - bool _enabled; - +private: // TRUE, if the autosaver generates snapshots bool _snapshotsEnabled; - // The autosave interval stored in seconds - unsigned long _interval; - - // The timer object that triggers the callback - wxSharedPtr _timer; - std::size_t _changes; std::vector _signalConnections; @@ -50,12 +41,6 @@ class AutoMapSaver final : void initialiseModule(const IApplicationContext& ctx) override; void shutdownModule() override; - ~AutoMapSaver(); - - // Starts/stops the autosave "countdown" - void startTimer(); - void stopTimer(); - // Clears the _changes member variable that indicates how many changes have been made void clearChanges(); @@ -66,7 +51,6 @@ class AutoMapSaver final : void performAutosave() override; private: - // Adds the elements to the according preference page void constructPreferences(); void registryKeyChanged(); @@ -76,9 +60,6 @@ class AutoMapSaver final : // Saves a snapshot of the currently active map (only named maps) void saveSnapshot(); - // This gets called when the interval time is over - void onIntervalReached(wxTimerEvent& ev); - void collectExistingSnapshots(std::map& existingSnapshots, const fs::path& snapshotPath, const std::string& mapName); @@ -87,7 +68,4 @@ class AutoMapSaver final : }; // class AutoMapSaver -// The accessor function for the static AutoSaver instance -AutoMapSaver& AutoSaver(); - } // namespace map diff --git a/radiant/ui/UserInterfaceModule.cpp b/radiant/ui/UserInterfaceModule.cpp index 040530db68..edfdd549bd 100644 --- a/radiant/ui/UserInterfaceModule.cpp +++ b/radiant/ui/UserInterfaceModule.cpp @@ -227,10 +227,15 @@ void UserInterfaceModule::initialiseModule(const IApplicationContext& ctx) _mapEditModeChangedConn = GlobalMapModule().signal_editModeChanged().connect( sigc::ptr_fun(&MergeControlDialog::OnMapEditModeChanged) ); + + _autosaveTimer.reset(new map::AutoSaveTimer); + _autosaveTimer->initialise(); } void UserInterfaceModule::shutdownModule() { + _autosaveTimer.reset(); + wxTheApp->Unbind(DISPATCH_EVENT, &UserInterfaceModule::onDispatchEvent, this); GlobalRadiantCore().getMessageBus().removeListener(_textureChangedListener); diff --git a/radiant/ui/UserInterfaceModule.h b/radiant/ui/UserInterfaceModule.h index e31c91ed29..f3b6c4bfc9 100644 --- a/radiant/ui/UserInterfaceModule.h +++ b/radiant/ui/UserInterfaceModule.h @@ -22,6 +22,7 @@ #include "messages/NotificationMessage.h" #include "ui/mru/MRUMenu.h" #include "DispatchEvent.h" +#include "map/AutoSaveTimer.h" namespace ui { @@ -59,6 +60,8 @@ class UserInterfaceModule : std::unique_ptr _mruMenu; + std::unique_ptr _autosaveTimer; + public: // RegisterableModule const std::string & getName() const override; diff --git a/tools/msvc/DarkRadiant.vcxproj b/tools/msvc/DarkRadiant.vcxproj index fdcc6de90e..88c010a075 100644 --- a/tools/msvc/DarkRadiant.vcxproj +++ b/tools/msvc/DarkRadiant.vcxproj @@ -206,6 +206,7 @@ + Create @@ -407,6 +408,7 @@ + diff --git a/tools/msvc/DarkRadiant.vcxproj.filters b/tools/msvc/DarkRadiant.vcxproj.filters index 49766b74bd..a6ff114cfe 100644 --- a/tools/msvc/DarkRadiant.vcxproj.filters +++ b/tools/msvc/DarkRadiant.vcxproj.filters @@ -727,6 +727,9 @@ src\ui\modelexport + + src\map + @@ -1407,6 +1410,9 @@ src\ui\modelexport + + src\map +