From a062a889d87a7ccc11bf8f8d5b6e1a2c067c94c6 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 14 Feb 2022 14:13:41 +0100 Subject: [PATCH] Follow-up to a1746e3e660cc54f1e26ff33f007525767648a49 Fix for #7849 - "Save Project" command doesn't work properly --- src/libslic3r/Preset.cpp | 5 +++-- src/libslic3r/Preset.hpp | 1 + src/slic3r/GUI/GUI_App.cpp | 17 ++++++++--------- src/slic3r/GUI/GUI_App.hpp | 2 +- src/slic3r/GUI/MainFrame.cpp | 5 ++++- src/slic3r/GUI/Plater.cpp | 7 +++++++ src/slic3r/GUI/ProjectDirtyStateManager.cpp | 20 +++++++++++--------- src/slic3r/GUI/Tab.cpp | 1 + src/slic3r/GUI/Tab.hpp | 1 + 9 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 95211ca4f..e07b97e2b 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -612,7 +612,7 @@ PresetCollection::PresetCollection(Preset::Type type, const std::vectoradd_default_preset(keys, defaults, default_name); m_edited_preset.config.apply(m_presets.front().config); -//? update_saved_preset_from_current_preset(); + update_saved_preset_from_current_preset(); } void PresetCollection::reset(bool delete_files) @@ -793,7 +793,8 @@ std::pair PresetCollection::load_external_preset( // The source config may contain keys from many possible preset types. Just copy those that relate to this preset. this->get_edited_preset().config.apply_only(combined_config, keys, true); this->update_dirty(); - update_saved_preset_from_current_preset(); + // Don't save the newly loaded project as a "saved into project" state. + //update_saved_preset_from_current_preset(); assert(this->get_edited_preset().is_dirty); return std::make_pair(&(*it), this->get_edited_preset().is_dirty); } diff --git a/src/libslic3r/Preset.hpp b/src/libslic3r/Preset.hpp index f4e4c1471..2f55aa676 100644 --- a/src/libslic3r/Preset.hpp +++ b/src/libslic3r/Preset.hpp @@ -395,6 +395,7 @@ public: void discard_current_changes() { m_presets[m_idx_selected].reset_dirty(); m_edited_preset = m_presets[m_idx_selected]; + // Don't save the resetted preset state as a "saved into project" state. // update_saved_preset_from_current_preset(); } diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index fe3de3909..be2cfb601 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1283,11 +1283,13 @@ bool GUI_App::on_init_inner() else load_current_presets(); - // set saved presets for initial project + // Save the active profiles as a "saved into project". update_saved_preset_from_current_preset(); if (plater_ != nullptr) { + // Save the names of active presets and project specific config into ProjectDirtyStateManager. plater_->reset_project_dirty_initial_presets(); + // Update Project dirty state, update application title bar. plater_->update_project_dirty_from_presets(); } @@ -2484,16 +2486,13 @@ void GUI_App::update_saved_preset_from_current_preset() } } -std::vector> GUI_App::get_selected_presets() const +std::vector GUI_App::get_active_preset_collections() const { - std::vector> ret; + std::vector ret; PrinterTechnology printer_technology = preset_bundle->printers.get_edited_preset().printer_technology(); - for (Tab* tab : tabs_list) { - if (tab->supports_printer_technology(printer_technology)) { - const PresetCollection* presets = tab->get_presets(); - ret.push_back({ static_cast(presets->type()), presets->get_selected_preset_name() }); - } - } + for (const Tab* tab : tabs_list) + if (tab->supports_printer_technology(printer_technology)) + ret.push_back(tab->get_presets()); return ret; } diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 0dcf65512..f8b159957 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -251,7 +251,7 @@ public: bool has_unsaved_preset_changes() const; bool has_current_preset_changes() const; void update_saved_preset_from_current_preset(); - std::vector> get_selected_presets() const; + std::vector get_active_preset_collections() const; bool check_and_save_current_preset_changes(const wxString& caption, const wxString& header, bool remember_choice = true, bool use_dont_save_insted_of_discard = false); void apply_keeped_preset_modifications(); bool check_and_keep_current_preset_changes(const wxString& caption, const wxString& header, int action_buttons, bool* postponed_apply_of_keeped_changes = nullptr); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index fe96136e6..5c544c86a 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -856,7 +856,10 @@ bool MainFrame::save_project_as(const wxString& filename) { bool ret = (m_plater != nullptr) ? m_plater->export_3mf(into_path(filename)) : false; if (ret) { -// wxGetApp().update_saved_preset_from_current_preset(); + // Make a copy of the active presets for detecting changes in preset values. + wxGetApp().update_saved_preset_from_current_preset(); + // Save the names of active presets and project specific config into ProjectDirtyStateManager. + // Reset ProjectDirtyStateManager's state as saved, mark active UndoRedo step as saved with project. m_plater->reset_project_dirty_after_save(); } return ret; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index e5df97ac5..34b811b19 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -495,6 +495,7 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) : std::vector extruders = dlg.get_extruders(); (project_config.option("wiping_volumes_matrix"))->values = std::vector(matrix.begin(), matrix.end()); (project_config.option("wiping_volumes_extruders"))->values = std::vector(extruders.begin(), extruders.end()); + // Update Project dirty state, update application title bar. wxGetApp().plater()->update_project_dirty_from_presets(); wxPostEvent(parent, SimpleEvent(EVT_SCHEDULE_BACKGROUND_PROCESS, parent)); } @@ -5086,8 +5087,11 @@ void Plater::new_project() take_snapshot(_L("New Project"), UndoRedo::SnapshotType::ProjectSeparator); Plater::SuppressSnapshots suppress(this); reset(); + // Save the names of active presets and project specific config into ProjectDirtyStateManager. reset_project_dirty_initial_presets(); + // Make a copy of the active presets for detecting changes in preset values. wxGetApp().update_saved_preset_from_current_preset(); + // Update Project dirty state, update application title bar. update_project_dirty_from_presets(); } @@ -5116,8 +5120,11 @@ void Plater::load_project(const wxString& filename) if (! load_files({ into_path(filename) }).empty()) { // At least one file was loaded. p->set_project_filename(filename); + // Save the names of active presets and project specific config into ProjectDirtyStateManager. reset_project_dirty_initial_presets(); + // Make a copy of the active presets for detecting changes in preset values. wxGetApp().update_saved_preset_from_current_preset(); + // Update Project dirty state, update application title bar. update_project_dirty_from_presets(); } } diff --git a/src/slic3r/GUI/ProjectDirtyStateManager.cpp b/src/slic3r/GUI/ProjectDirtyStateManager.cpp index c79ac0c39..89c13b640 100644 --- a/src/slic3r/GUI/ProjectDirtyStateManager.cpp +++ b/src/slic3r/GUI/ProjectDirtyStateManager.cpp @@ -17,9 +17,11 @@ namespace GUI { void ProjectDirtyStateManager::update_from_undo_redo_stack(bool dirty) { - m_plater_dirty = dirty; - if (const Plater *plater = wxGetApp().plater(); plater && wxGetApp().initialized()) - wxGetApp().mainframe->update_title(); + if (m_plater_dirty != dirty) { + m_plater_dirty = dirty; + if (const Plater *plater = wxGetApp().plater(); plater && wxGetApp().initialized()) + wxGetApp().mainframe->update_title(); + } } void ProjectDirtyStateManager::update_from_presets() @@ -27,11 +29,11 @@ void ProjectDirtyStateManager::update_from_presets() m_presets_dirty = false; // check switching of the presets only for exist/loaded project, but not for new GUI_App &app = wxGetApp(); - if (!app.plater()->get_project_filename().IsEmpty()) { - for (const auto& [type, name] : app.get_selected_presets()) - m_presets_dirty |= !m_initial_presets[type].empty() && m_initial_presets[type] != name; + bool has_project = ! app.plater()->get_project_filename().IsEmpty(); + for (const PresetCollection *preset_collection : app.get_active_preset_collections()) { + auto type = preset_collection->type(); + m_presets_dirty |= (has_project && !m_initial_presets[type].empty() && m_initial_presets[type] != preset_collection->get_selected_preset_name()) || preset_collection->saved_is_dirty(); } - m_presets_dirty |= app.has_unsaved_preset_changes(); m_project_config_dirty = m_initial_project_config != app.preset_bundle->project_config; app.mainframe->update_title(); } @@ -49,8 +51,8 @@ void ProjectDirtyStateManager::reset_initial_presets() { m_initial_presets.fill(std::string{}); GUI_App &app = wxGetApp(); - for (const auto& [type, name] : app.get_selected_presets()) - m_initial_presets[type] = name; + for (const PresetCollection *preset_collection : app.get_active_preset_collections()) + m_initial_presets[preset_collection->type()] = preset_collection->get_selected_preset_name(); m_initial_project_config = app.preset_bundle->project_config; } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 9bfc091e4..8737cc9a8 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1289,6 +1289,7 @@ void Tab::on_presets_changed() // to avoid needless preset loading from update() function m_dependent_tabs.clear(); + // Update Project dirty state, update application title bar. wxGetApp().plater()->update_project_dirty_from_presets(); } diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index d1b0f44bf..8e2293bdc 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -386,6 +386,7 @@ public: DynamicPrintConfig* get_config() { return m_config; } PresetCollection* get_presets() { return m_presets; } + const PresetCollection* get_presets() const { return m_presets; } void on_value_change(const std::string& opt_key, const boost::any& value);