Skip to content

Commit

Permalink
#5729: Move the autosave timer part to a separate class which will re…
Browse files Browse the repository at this point in the history
…main in the UI module, whereas the rest of the algorithm will be moved to the core module.
  • Loading branch information
codereader committed Aug 28, 2021
1 parent fd1f78c commit 367e26c
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 100 deletions.
1 change: 1 addition & 0 deletions radiant/CMakeLists.txt
Expand Up @@ -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
Expand Down
96 changes: 96 additions & 0 deletions 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<bool>(RKEY_AUTOSAVE_ENABLED);
_interval = registry::getValue<int>(RKEY_AUTOSAVE_INTERVAL) * 60;

// Start the timer with the new interval
if (_enabled)
{
startTimer();
}
}

void AutoSaveTimer::startTimer()
{
if (!_timer) return;

_timer->Start(static_cast<int>(_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();
}
}

}
42 changes: 42 additions & 0 deletions radiant/map/AutoSaveTimer.h
@@ -0,0 +1,42 @@
#pragma once

#include <wx/timer.h>
#include <sigc++/trackable.h>

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<wxTimer> _timer;

public:
AutoSaveTimer();
~AutoSaveTimer();

void initialise();

// Starts/stops the autosave "countdown"
void startTimer();
void stopTimer();

private:
void registryKeyChanged();
void onIntervalReached(wxTimerEvent& ev);
};

}
84 changes: 7 additions & 77 deletions radiant/map/AutoSaver.cpp
Expand Up @@ -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)
Expand All @@ -56,52 +54,20 @@ 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<bool>(RKEY_AUTOSAVE_ENABLED);
_snapshotsEnabled = registry::getValue<bool>(RKEY_AUTOSAVE_SNAPSHOTS_ENABLED);
_interval = registry::getValue<int>(RKEY_AUTOSAVE_INTERVAL) * 60;

// Start the timer with the new interval
if (_enabled)
{
startTimer();
}
}

void AutoMapSaver::clearChanges()
{
_changes = 0;
}

void AutoMapSaver::startTimer()
{
if (!_timer) return;

_timer->Start(static_cast<int>(_interval * 1000));
}

void AutoMapSaver::stopTimer()
{
if (!_timer) return;

_timer->Stop();
}

void AutoMapSaver::saveSnapshot()
{
// Original GtkRadiant comments:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand All @@ -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()
Expand All @@ -402,20 +344,8 @@ void AutoMapSaver::shutdownModule()
}

_signalConnections.clear();

_enabled = false;
stopTimer();

// Destroy the timer
_timer.reset();
}

module::StaticModule<AutoMapSaver> staticAutoSaverModule;

AutoMapSaver& AutoSaver()
{
return *std::static_pointer_cast<AutoMapSaver>(
module::GlobalModuleRegistry().getModule(MODULE_AUTOSAVER));
}

} // namespace map
24 changes: 1 addition & 23 deletions radiant/map/AutoSaver.h
Expand Up @@ -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<wxTimer> _timer;

std::size_t _changes;

std::vector<sigc::connection> _signalConnections;
Expand All @@ -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();

Expand All @@ -66,7 +51,6 @@ class AutoMapSaver final :
void performAutosave() override;

private:
// Adds the elements to the according preference page
void constructPreferences();

void registryKeyChanged();
Expand All @@ -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<int, std::string>& existingSnapshots,
const fs::path& snapshotPath, const std::string& mapName);

Expand All @@ -87,7 +68,4 @@ class AutoMapSaver final :

}; // class AutoMapSaver

// The accessor function for the static AutoSaver instance
AutoMapSaver& AutoSaver();

} // namespace map
5 changes: 5 additions & 0 deletions radiant/ui/UserInterfaceModule.cpp
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions radiant/ui/UserInterfaceModule.h
Expand Up @@ -22,6 +22,7 @@
#include "messages/NotificationMessage.h"
#include "ui/mru/MRUMenu.h"
#include "DispatchEvent.h"
#include "map/AutoSaveTimer.h"

namespace ui
{
Expand Down Expand Up @@ -59,6 +60,8 @@ class UserInterfaceModule :

std::unique_ptr<MRUMenu> _mruMenu;

std::unique_ptr<map::AutoSaveTimer> _autosaveTimer;

public:
// RegisterableModule
const std::string & getName() const override;
Expand Down

0 comments on commit 367e26c

Please sign in to comment.