From fca5562c6c35e2b3c087f2457fc2c60984330e25 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 19 Jul 2019 10:02:52 +0200 Subject: [PATCH 1/3] Process start_filament_gcode in case of usual single extruder printer Reported in https://github.com/prusa3d/PrusaSlicer/issues/2652 --- src/libslic3r/GCode.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 37a14d42c..d5ee6a048 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2784,7 +2784,17 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z) // if we are running a single-extruder setup, just set the extruder and return nothing if (!m_writer.multiple_extruders) { m_placeholder_parser.set("current_extruder", extruder_id); - return m_writer.toolchange(extruder_id); + + std::string gcode; + // Append the filament start G-code. + const std::string &start_filament_gcode = m_config.start_filament_gcode.get_at(extruder_id); + if (! start_filament_gcode.empty()) { + // Process the start_filament_gcode for the filament. + gcode += this->placeholder_parser_process("start_filament_gcode", start_filament_gcode, extruder_id); + check_add_eol(gcode); + } + gcode += m_writer.toolchange(extruder_id); + return gcode; } // prepend retraction on the current extruder From d9c325c7f067cff2bf997e67b205860025e32807 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 19 Jul 2019 10:29:06 +0200 Subject: [PATCH 2/3] Adding a generic bitmap "flags" attrib to the Undo / Redo snapshot. using this new "flags" attrib to store & recover the "Layers editing active" flag and restoring the "Layers editing" tool state. --- src/slic3r/GUI/Plater.cpp | 41 +++++++++++++++++++++++++---------- src/slic3r/Utils/UndoRedo.cpp | 22 +++++++++---------- src/slic3r/Utils/UndoRedo.hpp | 15 +++++++++---- 3 files changed, 51 insertions(+), 27 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 559145eba..f1be5c9f2 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1641,17 +1641,7 @@ struct Plater::priv void split_volume(); void scale_selection_to_fit_print_volume(); - void take_snapshot(const std::string& snapshot_name) - { - if (this->m_prevent_snapshots > 0) - return; - assert(this->m_prevent_snapshots >= 0); - this->undo_redo_stack.take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection(), view3D->get_canvas3d()->get_gizmos_manager(), this->printer_technology); - this->undo_redo_stack.release_least_recently_used(); - // Save the last active preset name of a particular printer technology. - ((this->printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name) = wxGetApp().preset_bundle->printers.get_selected_preset_name(); - BOOST_LOG_TRIVIAL(info) << "Undo / Redo snapshot taken: " << snapshot_name << ", Undo / Redo stack memory: " << Slic3r::format_memsize_MB(this->undo_redo_stack.memsize()) << log_memory_info(); - } + void take_snapshot(const std::string& snapshot_name); void take_snapshot(const wxString& snapshot_name) { this->take_snapshot(std::string(snapshot_name.ToUTF8().data())); } int get_active_snapshot_index(); void undo(); @@ -3588,6 +3578,21 @@ int Plater::priv::get_active_snapshot_index() return it - ss_stack.begin(); } +void Plater::priv::take_snapshot(const std::string& snapshot_name) +{ + if (this->m_prevent_snapshots > 0) + return; + assert(this->m_prevent_snapshots >= 0); + unsigned int flags = 0; + if (this->view3D->is_layers_editing_enabled()) + flags |= UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE; + this->undo_redo_stack.take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection(), view3D->get_canvas3d()->get_gizmos_manager(), this->printer_technology, flags); + this->undo_redo_stack.release_least_recently_used(); + // Save the last active preset name of a particular printer technology. + ((this->printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name) = wxGetApp().preset_bundle->printers.get_selected_preset_name(); + BOOST_LOG_TRIVIAL(info) << "Undo / Redo snapshot taken: " << snapshot_name << ", Undo / Redo stack memory: " << Slic3r::format_memsize_MB(this->undo_redo_stack.memsize()) << log_memory_info(); +} + void Plater::priv::undo() { const std::vector &snapshots = this->undo_redo_stack.snapshots(); @@ -3627,9 +3632,18 @@ void Plater::priv::undo_redo_to(std::vector::const_iterator } // Save the last active preset name of a particular printer technology. ((this->printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name) = wxGetApp().preset_bundle->printers.get_selected_preset_name(); + // Flags made of Snapshot::Flags enum values. + unsigned int new_flags = it_snapshot->flags; + unsigned int top_snapshot_flags = 0; + if (this->view3D->is_layers_editing_enabled()) + top_snapshot_flags |= UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE; + bool new_variable_layer_editing_active = (new_flags & UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE) != 0; + // Disable layer editing before the Undo / Redo jump. + if (! new_variable_layer_editing_active && view3D->is_layers_editing_enabled()) + view3D->enable_layers_editing(false); // Do the jump in time. if (it_snapshot->timestamp < this->undo_redo_stack.active_snapshot_time() ? - this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager(), this->printer_technology, it_snapshot->timestamp) : + this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager(), this->printer_technology, top_snapshot_flags, it_snapshot->timestamp) : this->undo_redo_stack.redo(model, this->view3D->get_canvas3d()->get_gizmos_manager(), it_snapshot->timestamp)) { if (printer_technology_changed) { // Switch to the other printer technology. Switch to the last printer active for that particular technology. @@ -3641,6 +3655,9 @@ void Plater::priv::undo_redo_to(std::vector::const_iterator wxGetApp().load_current_presets(); } this->update_after_undo_redo(temp_snapshot_was_taken); + // Enable layer editing after the Undo / Redo jump. + if (! view3D->is_layers_editing_enabled() && this->layers_height_allowed() && new_variable_layer_editing_active) + view3D->enable_layers_editing(true); } } diff --git a/src/slic3r/Utils/UndoRedo.cpp b/src/slic3r/Utils/UndoRedo.cpp index c4a082fb6..efbdb767a 100644 --- a/src/slic3r/Utils/UndoRedo.cpp +++ b/src/slic3r/Utils/UndoRedo.cpp @@ -495,12 +495,12 @@ public: } // Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time. - void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, Slic3r::PrinterTechnology printer_technology); + void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, Slic3r::PrinterTechnology printer_technology, unsigned int flags); void load_snapshot(size_t timestamp, Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos); bool has_undo_snapshot() const; bool has_redo_snapshot() const; - bool undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, Slic3r::GUI::GLGizmosManager &gizmos, PrinterTechnology printer_technology, size_t jump_to_time); + bool undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, Slic3r::GUI::GLGizmosManager &gizmos, PrinterTechnology printer_technology, unsigned int flags, size_t jump_to_time); bool redo(Slic3r::Model &model, Slic3r::GUI::GLGizmosManager &gizmos, size_t jump_to_time); void release_least_recently_used(); @@ -788,7 +788,7 @@ template void StackImpl::load_mutable_object(const Sl } // Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time. -void StackImpl::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, Slic3r::PrinterTechnology printer_technology) +void StackImpl::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, Slic3r::PrinterTechnology printer_technology, unsigned int flags) { // Release old snapshot data. assert(m_active_snapshot_time <= m_current_time); @@ -808,11 +808,11 @@ void StackImpl::take_snapshot(const std::string& snapshot_name, const Slic3r::Mo this->save_mutable_object(m_selection); this->save_mutable_object(gizmos); // Save the snapshot info. - m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id, printer_technology); + m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id, printer_technology, flags); m_active_snapshot_time = m_current_time; // Save snapshot info of the last "current" aka "top most" state, that is only being serialized // if undoing an action. Such a snapshot has an invalid Model ID assigned if it was not taken yet. - m_snapshots.emplace_back(topmost_snapshot_name, m_active_snapshot_time, 0, printer_technology); + m_snapshots.emplace_back(topmost_snapshot_name, m_active_snapshot_time, 0, printer_technology, flags); // Release empty objects from the history. this->collect_garbage(); assert(this->valid()); @@ -858,7 +858,7 @@ bool StackImpl::has_redo_snapshot() const return ++ it != m_snapshots.end(); } -bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, Slic3r::GUI::GLGizmosManager &gizmos, PrinterTechnology printer_technology, size_t time_to_load) +bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, Slic3r::GUI::GLGizmosManager &gizmos, PrinterTechnology printer_technology, unsigned int flags, size_t time_to_load) { assert(this->valid()); if (time_to_load == SIZE_MAX) { @@ -872,7 +872,7 @@ bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selecti bool new_snapshot_taken = false; if (m_active_snapshot_time == m_snapshots.back().timestamp && ! m_snapshots.back().is_topmost_captured()) { // The current state is temporary. The current state needs to be captured to be redoable. - this->take_snapshot(topmost_snapshot_name, model, selection, gizmos, printer_technology); + this->take_snapshot(topmost_snapshot_name, model, selection, gizmos, printer_technology, flags); // The line above entered another topmost_snapshot_name. assert(m_snapshots.back().is_topmost()); assert(! m_snapshots.back().is_topmost_captured()); @@ -1020,12 +1020,12 @@ Stack::~Stack() {} void Stack::set_memory_limit(size_t memsize) { pimpl->set_memory_limit(memsize); } size_t Stack::memsize() const { return pimpl->memsize(); } void Stack::release_least_recently_used() { pimpl->release_least_recently_used(); } -void Stack::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, Slic3r::PrinterTechnology printer_technology) - { pimpl->take_snapshot(snapshot_name, model, selection, gizmos, printer_technology); } +void Stack::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, Slic3r::PrinterTechnology printer_technology, unsigned int flags) + { pimpl->take_snapshot(snapshot_name, model, selection, gizmos, printer_technology, flags); } bool Stack::has_undo_snapshot() const { return pimpl->has_undo_snapshot(); } bool Stack::has_redo_snapshot() const { return pimpl->has_redo_snapshot(); } -bool Stack::undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, PrinterTechnology printer_technology, size_t time_to_load) - { return pimpl->undo(model, selection, gizmos, printer_technology, time_to_load); } +bool Stack::undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, PrinterTechnology printer_technology, unsigned int flags, size_t time_to_load) + { return pimpl->undo(model, selection, gizmos, printer_technology, flags, time_to_load); } bool Stack::redo(Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load) { return pimpl->redo(model, gizmos, time_to_load); } const Selection& Stack::selection_deserialized() const { return pimpl->selection_deserialized(); } diff --git a/src/slic3r/Utils/UndoRedo.hpp b/src/slic3r/Utils/UndoRedo.hpp index 96b539f18..28ba31a00 100644 --- a/src/slic3r/Utils/UndoRedo.hpp +++ b/src/slic3r/Utils/UndoRedo.hpp @@ -24,13 +24,20 @@ namespace UndoRedo { struct Snapshot { Snapshot(size_t timestamp) : timestamp(timestamp) {} - Snapshot(const std::string &name, size_t timestamp, size_t model_id, Slic3r::PrinterTechnology printer_technology) : - name(name), timestamp(timestamp), model_id(model_id), printer_technology(printer_technology) {} + Snapshot(const std::string &name, size_t timestamp, size_t model_id, Slic3r::PrinterTechnology printer_technology, unsigned int flags) : + name(name), timestamp(timestamp), model_id(model_id), printer_technology(printer_technology), flags(flags) {} + + // Bitmask of various binary flags to be stored with the snapshot. + enum Flags { + VARIABLE_LAYER_EDITING_ACTIVE = 1, + }; std::string name; size_t timestamp; size_t model_id; PrinterTechnology printer_technology; + // Bitmap of Flags (see the Flags enum). + unsigned int flags; bool operator< (const Snapshot &rhs) const { return this->timestamp < rhs.timestamp; } bool operator==(const Snapshot &rhs) const { return this->timestamp == rhs.timestamp; } @@ -69,7 +76,7 @@ public: void release_least_recently_used(); // Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time. - void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, Slic3r::PrinterTechnology printer_technology); + void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, Slic3r::PrinterTechnology printer_technology, unsigned int flags); // To be queried to enable / disable the Undo / Redo buttons at the UI. bool has_undo_snapshot() const; @@ -77,7 +84,7 @@ public: // Roll back the time. If time_to_load is SIZE_MAX, the previous snapshot is activated. // Undoing an action may need to take a snapshot of the current application state, so that redo to the current state is possible. - bool undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, PrinterTechnology printer_technology, size_t time_to_load = SIZE_MAX); + bool undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, PrinterTechnology printer_technology, unsigned int flags, size_t time_to_load = SIZE_MAX); // Jump forward in time. If time_to_load is SIZE_MAX, the next snapshot is activated. bool redo(Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load = SIZE_MAX); From 2de6d95322430ba2835495f18dde302b3128001c Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 19 Jul 2019 11:12:38 +0200 Subject: [PATCH 3/3] Memory statistics (total memory, memory usage, Undo / Redo stack size) into the System INfo dialog. --- src/slic3r/GUI/Plater.cpp | 12 +++------- src/slic3r/GUI/Plater.hpp | 6 +++++ src/slic3r/GUI/SysInfoDialog.cpp | 38 +++++++++++++++++++++++++++++++- src/slic3r/Utils/UndoRedo.cpp | 2 ++ src/slic3r/Utils/UndoRedo.hpp | 1 + 5 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f1be5c9f2..74636bbdc 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -4564,15 +4564,9 @@ bool Plater::can_copy_to_clipboard() const return true; } -bool Plater::can_undo() const -{ - return p->undo_redo_stack.has_undo_snapshot(); -} - -bool Plater::can_redo() const -{ - return p->undo_redo_stack.has_redo_snapshot(); -} +bool Plater::can_undo() const { return p->undo_redo_stack.has_undo_snapshot(); } +bool Plater::can_redo() const { return p->undo_redo_stack.has_redo_snapshot(); } +const UndoRedo::Stack& Plater::undo_redo_stack() const { return p->undo_redo_stack; } SuppressBackgroundProcessingUpdate::SuppressBackgroundProcessingUpdate() : m_was_running(wxGetApp().plater()->is_background_process_running()) diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index a4ced64a0..d7e91f516 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -27,6 +27,11 @@ class ModelObject; class Print; class SLAPrint; +namespace UndoRedo { + class Stack; + struct Snapshot; +}; + namespace GUI { class MainFrame; @@ -191,6 +196,7 @@ public: void undo_to(int selection); void redo_to(int selection); bool undo_redo_string_getter(const bool is_undo, int idx, const char** out_text); + const Slic3r::UndoRedo::Stack& undo_redo_stack() const; void on_extruders_change(int extruders_count); void on_config_change(const DynamicPrintConfig &config); diff --git a/src/slic3r/GUI/SysInfoDialog.cpp b/src/slic3r/GUI/SysInfoDialog.cpp index bd19c38c3..96a3e9a81 100644 --- a/src/slic3r/GUI/SysInfoDialog.cpp +++ b/src/slic3r/GUI/SysInfoDialog.cpp @@ -2,6 +2,7 @@ #include "I18N.hpp" #include "3DScene.hpp" #include "GUI.hpp" +#include "../Utils/UndoRedo.hpp" #include @@ -10,6 +11,14 @@ #include "GUI_App.hpp" #include "wxExtensions.hpp" +#ifdef _WIN32 + // The standard Windows includes. + #define WIN32_LEAN_AND_MEAN + #define NOMINMAX + #include + #include +#endif /* _WIN32 */ + namespace Slic3r { namespace GUI { @@ -36,10 +45,37 @@ std::string get_main_info(bool format_as_html) "System Version: " #endif << b_end << wxPlatformInfo::Get().GetOperatingSystemDescription() << line_end; + out << b_start << "Total RAM size [MB]: " << b_end << Slic3r::format_memsize_MB(Slic3r::total_physical_memory()); return out.str(); } +std::string get_mem_info(bool format_as_html) +{ + std::stringstream out; + + std::string b_start = format_as_html ? "" : ""; + std::string b_end = format_as_html ? "" : ""; + std::string line_end = format_as_html ? "
" : "\n"; + + const Slic3r::UndoRedo::Stack &stack = wxGetApp().plater()->undo_redo_stack(); + out << b_start << "RAM size reserved for the Undo / Redo stack [MB]: " << b_end << Slic3r::format_memsize_MB(stack.get_memory_limit()) << line_end; + out << b_start << "RAM size occupied by the Undo / Redo stack [MB]: " << b_end << Slic3r::format_memsize_MB(stack.memsize()) << line_end << line_end; + +#ifdef _WIN32 + HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ::GetCurrentProcessId()); + if (hProcess != nullptr) { + PROCESS_MEMORY_COUNTERS_EX pmc; + if (GetProcessMemoryInfo(hProcess, (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) + out << b_start << "WorkingSet [MB]: " << b_end << format_memsize_MB(pmc.WorkingSetSize) << line_end + << b_start << "PrivateBytes [MB]: " << b_end << format_memsize_MB(pmc.PrivateUsage) << line_end + << b_start << "Pagefile(peak) [MB]: " << b_end << format_memsize_MB(pmc.PagefileUsage) << "(" << format_memsize_MB(pmc.PeakPagefileUsage) << ")" << line_end; + CloseHandle(hProcess); + } +#endif + return out.str(); +} + SysInfoDialog::SysInfoDialog() : DPIDialog(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(L("System Information")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) { @@ -111,7 +147,7 @@ SysInfoDialog::SysInfoDialog() "" "" "", bgr_clr_str, text_clr_str, text_clr_str, - _3DScene::get_gl_info(true, true)); + get_mem_info(true) + "
" + _3DScene::get_gl_info(true, true)); m_opengl_info_html->SetPage(text); main_sizer->Add(m_opengl_info_html, 1, wxEXPAND | wxBOTTOM, 15); } diff --git a/src/slic3r/Utils/UndoRedo.cpp b/src/slic3r/Utils/UndoRedo.cpp index efbdb767a..2605bd2a7 100644 --- a/src/slic3r/Utils/UndoRedo.cpp +++ b/src/slic3r/Utils/UndoRedo.cpp @@ -486,6 +486,7 @@ public: StackImpl() : m_memory_limit(std::min(Slic3r::total_physical_memory() / 10, size_t(1 * 16384 * 65536 / UNDO_REDO_DEBUG_LOW_MEM_FACTOR))), m_active_snapshot_time(0), m_current_time(0) {} void set_memory_limit(size_t memsize) { m_memory_limit = memsize; } + size_t get_memory_limit() const { return m_memory_limit; } size_t memsize() const { size_t memsize = 0; @@ -1018,6 +1019,7 @@ void StackImpl::release_least_recently_used() Stack::Stack() : pimpl(new StackImpl()) {} Stack::~Stack() {} void Stack::set_memory_limit(size_t memsize) { pimpl->set_memory_limit(memsize); } +size_t Stack::get_memory_limit() const { return pimpl->get_memory_limit(); } size_t Stack::memsize() const { return pimpl->memsize(); } void Stack::release_least_recently_used() { pimpl->release_least_recently_used(); } void Stack::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, Slic3r::PrinterTechnology printer_technology, unsigned int flags) diff --git a/src/slic3r/Utils/UndoRedo.hpp b/src/slic3r/Utils/UndoRedo.hpp index 28ba31a00..916e44aa2 100644 --- a/src/slic3r/Utils/UndoRedo.hpp +++ b/src/slic3r/Utils/UndoRedo.hpp @@ -68,6 +68,7 @@ public: // Set maximum memory threshold. If the threshold is exceeded, least recently used snapshots are released. void set_memory_limit(size_t memsize); + size_t get_memory_limit() const; // Estimate size of the RAM consumed by the Undo / Redo stack. size_t memsize() const;