diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index 8d587820c..cc4867ac2 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -297,6 +297,10 @@ void AppConfig::set_defaults() set("units", "0"); } + if (get("auto_transfer_when_switch_preset").empty()) { + set("auto_transfer_when_switch_preset", "true"); + } + if (get("sync_user_preset").empty()) { set_bool("sync_user_preset", false); } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f911c2ae9..1c6778311 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -126,12 +126,13 @@ float RetinaHelper::get_scale_factor() { return float(m_window->GetContentScaleF #endif -std::string& get_object_limited_text() { - static std::string object_limited_text = _u8L("An object is laid on the left/right nozzle only area.\n" +std::string get_object_limited_text() { + std::string object_limited_text = _u8L("An object is laid on the left/right nozzle only area.\n" "Please make sure the filaments used by this object on this area are not mapped to the other nozzles."); return object_limited_text; } +// serve as a text container, not the real text std::string& get_object_clashed_text() { static std::string object_clashed_text = _u8L("An object is laid over the boundary of plate or exceeds the height limit.\n" "Please solve the problem by moving it totally on or off the plate, and confirming that the height is within the build volume."); @@ -9997,7 +9998,7 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) SLICING_LIMIT_ERROR, SLICING_HEIGHT_OUTSIDE }; - const static std::vector extruder_name_list= {_u8L("left nozzle"), _u8L("right nozzle")}; // in ui, we treat extruder as nozzle + const std::vector extruder_name_list= {_u8L("left nozzle"), _u8L("right nozzle")}; // in ui, we treat extruder as nozzle std::string text; ErrorType error = ErrorType::PLATER_WARNING; const ModelObject* conflictObj=nullptr; diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 88de30b76..40d34eae7 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -6221,7 +6221,7 @@ std::vector> GUI_App::get_selected_presets( // This is called when: // - Exporting config_bundle // - Taking snapshot -bool GUI_App::check_and_save_current_preset_changes(const wxString& caption, const wxString& header, bool remember_choice/* = true*/, bool dont_save_insted_of_discard/* = false*/) +bool GUI_App::check_and_save_current_preset_changes(const wxString& caption, const wxString& header, bool remember_choice/* = true*/, bool dont_save_insted_of_discard/* = false*/, ForceOption force_op/* = Discard*/) { if (has_current_preset_changes()) { int act_buttons = UnsavedChangesDialog::ActionButtons::SAVE; @@ -6230,11 +6230,8 @@ bool GUI_App::check_and_save_current_preset_changes(const wxString& caption, con if (remember_choice) act_buttons |= UnsavedChangesDialog::ActionButtons::REMEMBER_CHOISE; UnsavedChangesDialog dlg(caption, header, "", act_buttons); - if (dlg.ShowModal() == wxID_CANCEL) - return false; - if (dlg.save_preset()) // save selected changes - { + auto handle_save_action = [this,&dlg](){ //BBS: add project embedded preset relate logic for (const UnsavedChangesDialog::PresetData& nt : dlg.get_names_and_types()) preset_bundle->save_changes_for_preset(nt.name, nt.type, dlg.get_unselected_options(nt.type), nt.save_to_project); @@ -6249,6 +6246,21 @@ bool GUI_App::check_and_save_current_preset_changes(const wxString& caption, con //MessageDialog(nullptr, _L_PLURAL("Modifications to the preset have been saved", // "Modifications to the presets have been saved", dlg.get_names_and_types().size())).ShowModal(); + }; + + if (force_op == ForceOption::fopDiscard) + return true; + if (force_op == ForceOption::fopSave) { + handle_save_action(); + return true; + } + + if (dlg.ShowModal() == wxID_CANCEL) + return false; + + if (dlg.save_preset()) // save selected changes + { + handle_save_action(); } } @@ -6272,14 +6284,12 @@ void GUI_App::apply_keeped_preset_modifications() // => Current project isn't saved => UnsavedChangesDialog: "Keep / Discard / Save / Cancel" // Close ConfigWizard => Current project is saved => UnsavedChangesDialog: "Keep / Discard / Save / Cancel" // Note: no_nullptr postponed_apply_of_keeped_changes indicates that thie function is called after ConfigWizard is closed -bool GUI_App::check_and_keep_current_preset_changes(const wxString& caption, const wxString& header, int action_buttons, bool* postponed_apply_of_keeped_changes/* = nullptr*/) +bool GUI_App::check_and_keep_current_preset_changes(const wxString& caption, const wxString& header, int action_buttons, bool* postponed_apply_of_keeped_changes/* = nullptr*/, ForceOption force_op) { if (has_current_preset_changes()) { bool is_called_from_configwizard = postponed_apply_of_keeped_changes != nullptr; - UnsavedChangesDialog dlg(caption, header, "", action_buttons); - if (dlg.ShowModal() == wxID_CANCEL) - return false; + auto reset_modifications = [this, is_called_from_configwizard]() { //if (is_called_from_configwizard) @@ -6291,59 +6301,89 @@ bool GUI_App::check_and_keep_current_preset_changes(const wxString& caption, con tab->m_presets->discard_current_changes(); } load_current_presets(false); - }; + }; + + auto handle_discard_option = [ this, reset_modifications](){ + reset_modifications(); + }; + + auto handle_save_option = [this,&dlg, reset_modifications]() { + const auto& preset_names_and_types = dlg.get_names_and_types(); + for (const UnsavedChangesDialog::PresetData& nt : preset_names_and_types) + preset_bundle->save_changes_for_preset(nt.name, nt.type, dlg.get_unselected_options(nt.type), nt.save_to_project); + + // if we saved changes to the new presets, we should to + // synchronize config.ini with the current selections. + preset_bundle->export_selections(*app_config); + + //wxString text = _L_PLURAL("Modifications to the preset have been saved", + // "Modifications to the presets have been saved", preset_names_and_types.size()); + //if (!is_called_from_configwizard) + // text += "\n\n" + _L("All modifications will be discarded for new project."); + + //MessageDialog(nullptr, text).ShowModal(); + reset_modifications(); + }; + + auto handle_transfer_option = [this, &dlg, is_called_from_configwizard, postponed_apply_of_keeped_changes, reset_modifications]() { + const auto& preset_names_and_types = dlg.get_names_and_types(); + // execute this part of code only if not all modifications are keeping to the new project + // OR this function is called when ConfigWizard is closed and "Keep modifications" is selected + for (const UnsavedChangesDialog::PresetData& nt : preset_names_and_types) { + Preset::Type type = nt.type; + Tab* tab = get_tab(type); + std::vector selected_options = dlg.get_selected_options(type); + if (type == Preset::TYPE_PRINTER) { + auto it = std::find(selected_options.begin(), selected_options.end(), "extruders_count"); + if (it != selected_options.end()) { + // erase "extruders_count" option from the list + selected_options.erase(it); + // cache the extruders count + static_cast(tab)->cache_extruder_cnt(); + } + } + std::vector selected_options2; + std::transform(selected_options.begin(), selected_options.end(), std::back_inserter(selected_options2), [](auto& o) { + auto i = o.find('#'); + return i != std::string::npos ? o.substr(0, i) : o; + }); + tab->cache_config_diff(selected_options2); + if (!is_called_from_configwizard) + tab->m_presets->discard_current_changes(); + } + if (is_called_from_configwizard) + *postponed_apply_of_keeped_changes = true; + else + apply_keeped_preset_modifications(); + }; + + if (force_op == ForceOption::fopDiscard) { + handle_discard_option(); + return true; + } + if (force_op == ForceOption::fopTransfer) { + handle_transfer_option(); + return true; + } + if (force_op == ForceOption::fopSave) { + handle_save_option(); + return true; + } + + if (dlg.ShowModal() == wxID_CANCEL) + return false; if (dlg.discard()) - reset_modifications(); + handle_discard_option(); else // save selected changes { //BBS: add project embedded preset relate logic const auto& preset_names_and_types = dlg.get_names_and_types(); if (dlg.save_preset()) { - for (const UnsavedChangesDialog::PresetData& nt : preset_names_and_types) - preset_bundle->save_changes_for_preset(nt.name, nt.type, dlg.get_unselected_options(nt.type), nt.save_to_project); - - // if we saved changes to the new presets, we should to - // synchronize config.ini with the current selections. - preset_bundle->export_selections(*app_config); - - //wxString text = _L_PLURAL("Modifications to the preset have been saved", - // "Modifications to the presets have been saved", preset_names_and_types.size()); - //if (!is_called_from_configwizard) - // text += "\n\n" + _L("All modifications will be discarded for new project."); - - //MessageDialog(nullptr, text).ShowModal(); - reset_modifications(); + handle_save_option(); } else if (dlg.transfer_changes() && (dlg.has_unselected_options() || is_called_from_configwizard)) { - // execute this part of code only if not all modifications are keeping to the new project - // OR this function is called when ConfigWizard is closed and "Keep modifications" is selected - for (const UnsavedChangesDialog::PresetData& nt : preset_names_and_types) { - Preset::Type type = nt.type; - Tab* tab = get_tab(type); - std::vector selected_options = dlg.get_selected_options(type); - if (type == Preset::TYPE_PRINTER) { - auto it = std::find(selected_options.begin(), selected_options.end(), "extruders_count"); - if (it != selected_options.end()) { - // erase "extruders_count" option from the list - selected_options.erase(it); - // cache the extruders count - static_cast(tab)->cache_extruder_cnt(); - } - } - std::vector selected_options2; - std::transform(selected_options.begin(), selected_options.end(), std::back_inserter(selected_options2), [](auto & o) { - auto i = o.find('#'); - return i != std::string::npos ? o.substr(0, i) : o; - }); - tab->cache_config_diff(selected_options2); - if (!is_called_from_configwizard) - tab->m_presets->discard_current_changes(); - } - if (is_called_from_configwizard) - *postponed_apply_of_keeped_changes = true; - else - apply_keeped_preset_modifications(); + handle_transfer_option(); } } } diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index c6e422842..b67792ca3 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -18,6 +18,7 @@ #include "slic3r/GUI/HMS.hpp" #include "slic3r/GUI/Jobs/UpgradeNetworkJob.hpp" #include "slic3r/GUI/HttpServer.hpp" +#include "slic3r/GUI/UnsavedChangesDialog.hpp" #include "../Utils/PrintHost.hpp" #include "slic3r/GUI/GLEnums.hpp" @@ -52,7 +53,6 @@ class wxBookCtrlBase; class Notebook; struct wxLanguageInfo; - namespace Slic3r { class AppConfig; @@ -518,9 +518,9 @@ public: bool has_current_preset_changes() const; void update_saved_preset_from_current_preset(); std::vector> get_selected_presets() 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); + 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, ForceOption force_op = ForceOption::fopDiscard); 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); + bool check_and_keep_current_preset_changes(const wxString& caption, const wxString& header, int action_buttons, bool* postponed_apply_of_keeped_changes = nullptr, ForceOption force_op = ForceOption::fopDiscard); bool can_load_project(); bool check_print_host_queue(); bool checked_tab(Tab* tab); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 0e8d7d9d8..62d3ad047 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2665,7 +2665,9 @@ bool Sidebar::is_new_project_in_gcode3mf() confirm_dlg.update_text(filename + " " + _L("will be closed before modify filament. Do you want to continue?")); confirm_dlg.on_show(); - if (!is_cancle) { + if (is_cancle) { + this->printer_combox()->update(); + } else { p->plater->new_project(); } return is_cancle; @@ -5485,51 +5487,6 @@ std::vector Plater::priv::load_files(const std::vector& input_ } } - if (load_config) { - DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); - if (dev) { - MachineObject *obj = dev->get_selected_machine(); - if (obj && obj->is_info_ready()) { - if (obj->m_extder_data.extders.size() > 0) { - PresetBundle *preset_bundle = wxGetApp().preset_bundle; - Preset &printer_preset = preset_bundle->printers.get_selected_preset(); - - double preset_nozzle_diameter = 0.4; - const ConfigOption *opt = printer_preset.config.option("nozzle_diameter"); - if (opt) preset_nozzle_diameter = static_cast(opt)->values[0]; - float machine_nozzle_diameter = obj->m_extder_data.extders[0].current_nozzle_diameter; - - std::string machine_type = obj->printer_type; - if (obj->is_support_upgrade_kit && obj->installed_upgrade_kit) machine_type = "C12"; - - if (printer_preset.get_current_printer_type(preset_bundle) != machine_type || !is_approx((float) preset_nozzle_diameter, machine_nozzle_diameter)) { - Preset *machine_preset = get_printer_preset(obj); - if (machine_preset != nullptr) { - std::string printer_model = machine_preset->config.option("printer_model")->value; - bool sync_printer_info = false; - if (!wxGetApp().app_config->has("sync_after_load_file_show_flag")) { - wxString tips = from_u8((boost::format(_u8L("Connected printer is %s. It must match the project preset for printing.\n")) % printer_model).str()); - - tips += _L("Do you want to sync the printer information and automatically switch the preset?"); - TipsDialog dlg(wxGetApp().mainframe, _L("Tips"), tips, "sync_after_load_file_show_flag", wxYES_NO); - if (dlg.ShowModal() == wxID_YES) { sync_printer_info = true; } - } - else { - sync_printer_info = wxGetApp().app_config->get("sync_after_load_file_show_flag") == "true"; - } - if (sync_printer_info) { - update_objects_position_when_select_preset([&obj, machine_preset]() { - Tab *printer_tab = GUI::wxGetApp().get_tab(Preset::Type::TYPE_PRINTER); - printer_tab->select_preset(machine_preset->name); - if (obj->is_multi_extruders()) GUI::wxGetApp().sidebar().sync_extruder_list(); - }); - } - } - } - } - } - } - } if (new_model) delete new_model; @@ -10492,6 +10449,70 @@ int Plater::new_project(bool skip_confirm, bool silent, const wxString &project_ +bool Plater::try_sync_preset_with_connected_printer() +{ + DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); + if (!dev) + return false; + + MachineObject* obj = dev->get_selected_machine(); + if (!obj || !obj->is_info_ready() || obj->m_extder_data.extders.size() <= 0) + return false; + + PresetBundle* preset_bundle = wxGetApp().preset_bundle; + Preset& printer_preset = preset_bundle->printers.get_selected_preset(); + double preset_nozzle_diameter = 0.4; + if (auto opt = printer_preset.config.option("nozzle_diameter"); opt) { + preset_nozzle_diameter = static_cast(opt)->values[0]; + } + float machine_nozzle_diameter = obj->m_extder_data.extders[0].current_nozzle_diameter; + + std::string printer_type = obj->printer_type; + // handle p1p with upgraded kit + if (obj->is_support_upgrade_kit && obj->installed_upgrade_kit) + printer_type = "C12"; + + // same printer and same nozzle diameter, return false + if (printer_preset.get_current_printer_type(preset_bundle) == printer_type && is_approx((float)(preset_nozzle_diameter), machine_nozzle_diameter)) + return false; + + // can not find the preset for connected printer, return false + Preset* machine_preset = get_printer_preset(obj); + if (!machine_preset) + return false; + + std::string printer_model = machine_preset->config.option("printer_model")->value; + bool sync_printer_info = false; + bool is_multi_extruder = machine_preset->config.option("nozzle_diameter")->values.size() > 1; + if (!wxGetApp().app_config->has("sync_after_load_file_show_flag")) { + wxString tips; + + if (is_multi_extruder) { + tips=from_u8((boost::format(_u8L("The currently connected printer, %s, is a %s model.\nTo use this printer for printing, please switch the printer model of the project file to %s,\nand sync the nozzle type and AMS quantity information from the connected printer.")) %obj->dev_name% printer_model%printer_model).str()); + } + else { + tips = from_u8((boost::format(_u8L("The currently connected printer, %s, is a %s model.\nTo use this printer for printing, please switch the printer model of project file to %s.")) % obj->dev_name % printer_model % printer_model).str()); + + } + TipsDialog dlg(wxGetApp().mainframe, _L("Tips"), tips, "sync_after_load_file_show_flag", wxYES_NO); + if (dlg.ShowModal() == wxID_YES) { sync_printer_info = true; } + } + else { + sync_printer_info = wxGetApp().app_config->get("sync_after_load_file_show_flag") == "true"; + } + if (!sync_printer_info) + return false; + + update_objects_position_when_select_preset([&obj, machine_preset]() { + Tab* printer_tab = GUI::wxGetApp().get_tab(Preset::Type::TYPE_PRINTER); + printer_tab->select_preset(machine_preset->name); + if (obj->is_multi_extruders()) GUI::wxGetApp().sidebar().sync_extruder_list(); + }); + return true; +} + + + // BBS: FIXME, missing resotre logic int Plater::load_project(wxString const &filename2, wxString const& originfile) @@ -10611,6 +10632,11 @@ int Plater::load_project(wxString const &filename2, BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << " load project done"; m_loading_project = false; + + // only pop up in 3mf + if (!this->m_exported_file && !this->m_only_gcode){ + try_sync_preset_with_connected_printer(); + } return wx_dlg_id; } @@ -15489,7 +15515,7 @@ int Plater::select_sliced_plate(int plate_index) return ret; } -extern std::string& get_object_limited_text(); +extern std::string get_object_limited_text(); extern std::string& get_object_clashed_text(); void Plater::validate_current_plate(bool& model_fits, bool& validate_error) diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index e85195153..8f7dac1af 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -239,6 +239,8 @@ public: void render_project_state_debug_window() const; #endif // ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW + bool try_sync_preset_with_connected_printer(); + Sidebar& sidebar(); const Model& model() const; Model& model(); diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 3503eb526..df57955c0 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -1158,7 +1158,8 @@ wxWindow* PreferencesDialog::create_general_page() #endif 50, "single_instance"); - auto item_bed_type_follow_preset = create_item_checkbox(_L("Auto plate type"), page, + auto item_auto_transfer_when_switch_preset = create_item_checkbox(_L("Automatically transfer modified value when switching process and filament presets"), page,_L("Default behavior for handling modified values when switching process and filament presets. After closing, a popup will appear to ask each time"), 50, "auto_transfer_when_switch_preset"); + auto item_bed_type_follow_preset = create_item_checkbox(_L("Auto plate type"), page, _L("Studio will remember build plate selected last time for certain printer model."), 50, "user_bed_type"); //auto item_hints = create_item_checkbox(_L("Show \"Tip of the day\" notification after start"), page, _L("If enabled, useful hints are displayed at startup."), 50, "show_hints"); @@ -1271,6 +1272,7 @@ wxWindow* PreferencesDialog::create_general_page() sizer_page->Add(item_multi_machine, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_step_mesh_setting, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_beta_version_update, 0, wxTOP, FromDIP(3)); + sizer_page->Add(item_auto_transfer_when_switch_preset, 0, wxTOP, FromDIP(3)); sizer_page->Add(_3d_settings, 0, wxTOP | wxEXPAND, FromDIP(20)); sizer_page->Add(item_mouse_zoom_settings, 0, wxTOP, FromDIP(3)); sizer_page->Add(item_show_shells_in_preview_settings, 0, wxTOP, FromDIP(3)); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 88df5f59f..354c85258 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -33,7 +33,6 @@ #include "Plater.hpp" #include "MainFrame.hpp" #include "format.hpp" -#include "UnsavedChangesDialog.hpp" #include "SavePresetDialog.hpp" #include "MsgDialog.hpp" #include "Notebook.hpp" @@ -4745,6 +4744,9 @@ void Tab::update_preset_choice() bool Tab::select_preset( std::string preset_name, bool delete_current /*=false*/, const std::string &last_selected_ph_printer_name /* =""*/, bool force_select, bool force_no_transfer) { + auto app_config = wxGetApp().app_config; + bool auto_transfer = app_config->get("auto_transfer_when_switch_preset") == "true"; + ForceOption option = auto_transfer ? ForceOption::fopTransfer : ForceOption::fopNone; BOOST_LOG_TRIVIAL(info) << boost::format("select preset, name %1%, delete_current %2%") %preset_name %delete_current; if (preset_name.empty()) { @@ -4809,7 +4811,11 @@ bool Tab::select_preset( if (force_no_transfer) { no_transfer = true; } - if (current_dirty && ! may_discard_current_dirty_preset(nullptr, preset_name, no_transfer) && !force_select) { + ForceOption option_for_dirty_preset = ForceOption::fopNone; + if (current_dirty && print_tab) { + option_for_dirty_preset = option; + } + if (current_dirty && ! may_discard_current_dirty_preset(nullptr, preset_name, no_transfer,false,option_for_dirty_preset) && !force_select) { canceled = true; BOOST_LOG_TRIVIAL(info) << boost::format("current dirty and cancelled"); } else if (print_tab) { @@ -4824,7 +4830,7 @@ bool Tab::select_preset( bool new_preset_compatible = is_compatible_with_print(dependent.get_edited_preset_with_vendor_profile(), m_presets->get_preset_with_vendor_profile(*m_presets->find_preset(preset_name, true)), printer_profile); if (! canceled) - canceled = old_preset_dirty && ! new_preset_compatible && ! may_discard_current_dirty_preset(&dependent, preset_name) && !force_select; + canceled = old_preset_dirty && ! new_preset_compatible && ! may_discard_current_dirty_preset(&dependent, preset_name,false,false,option) && !force_select; if (! canceled) { // The preset will be switched to a different, compatible preset, or the '-- default --'. m_dependent_tabs.emplace_back((printer_technology == ptFFF) ? Preset::Type::TYPE_FILAMENT : Preset::Type::TYPE_SLA_MATERIAL); @@ -4869,7 +4875,7 @@ bool Tab::select_preset( pu.old_preset_dirty = (old_printer_technology == pu.technology) && pu.presets->current_is_dirty(); pu.new_preset_compatible = (new_printer_technology == pu.technology) && is_compatible_with_printer(pu.presets->get_edited_preset_with_vendor_profile(), new_printer_preset_with_vendor_profile); if (!canceled) - canceled = pu.old_preset_dirty && !pu.new_preset_compatible && !may_discard_current_dirty_preset(pu.presets, preset_name, false, no_transfer_variant) && !force_select; + canceled = pu.old_preset_dirty && !pu.new_preset_compatible && !may_discard_current_dirty_preset(pu.presets, preset_name, false, no_transfer_variant,option) && !force_select; } if (!canceled) { for (PresetUpdate &pu : updates) { @@ -5042,16 +5048,13 @@ bool Tab::select_preset( // If the current preset is dirty, the user is asked whether the changes may be discarded. // if the current preset was not dirty, or the user agreed to discard the changes, 1 is returned. -bool Tab::may_discard_current_dirty_preset(PresetCollection *presets /*= nullptr*/, const std::string &new_printer_name /*= ""*/, bool no_transfer, bool no_transfer_variant) +bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr*/, const std::string& new_printer_name /*= ""*/, bool no_transfer, bool no_transfer_variant, ForceOption force_op) { if (presets == nullptr) presets = m_presets; UnsavedChangesDialog dlg(m_type, presets, new_printer_name, no_transfer); - if (dlg.ShowModal() == wxID_CANCEL) - return false; - if (dlg.save_preset()) // save selected changes - { + auto handle_save_action = [&dlg, this, presets]() { const std::vector& unselected_options = dlg.get_unselected_options(presets->type()); const std::string& name = dlg.get_preset_name(); //BBS: add project embedded preset relate logic @@ -5077,14 +5080,14 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection *presets /*= nullptr if (presets->type() == Preset::TYPE_FILAMENT && wxGetApp().extruders_edited_cnt() > 1) wxGetApp().plater()->force_filament_colors_update(); } - } - else if (dlg.transfer_changes()) // move selected changes - { + }; + + auto handle_transfer_action = [&dlg, this, presets, no_transfer, no_transfer_variant]() { std::vector selected_options = dlg.get_selected_options(); if (!no_transfer && no_transfer_variant) { - auto & options_list = wxGetApp().get_tab(presets->type())->m_options_list; + auto& options_list = wxGetApp().get_tab(presets->type())->m_options_list; bool has_variants = false; - for (auto &opt : selected_options) { + for (auto& opt : selected_options) { if (auto n = opt.find('#'); n != std::string::npos) { auto iter = options_list.lower_bound(opt.substr(0, n)); if (iter == options_list.end() || opt.compare(0, n, iter->first)) { @@ -5117,6 +5120,26 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection *presets /*= nullptr } else wxGetApp().get_tab(presets->type())->cache_config_diff(selected_options); + }; + + if (force_op == ForceOption::fopSave) { + handle_save_action(); + return true; + } + + if (force_op == ForceOption::fopTransfer) { + handle_transfer_action(); + return true; + } + + if (dlg.ShowModal() == wxID_CANCEL) + return false; + + if (dlg.save_preset()) { + handle_save_action(); + } + else if (dlg.transfer_changes()) { + handle_transfer_action(); } return true; diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 482b0284e..eeffbf234 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -40,6 +40,7 @@ #include "ParamsPanel.hpp" #include "Widgets/RoundedRectangle.hpp" #include "Widgets/TextInput.hpp" +#include "UnsavedChangesDialog.hpp" class TabCtrl; class ComboBox; @@ -334,7 +335,7 @@ public: void update_preset_choice(); // Select a new preset, possibly delete the current one. bool select_preset(std::string preset_name = "", bool delete_current = false, const std::string &last_selected_ph_printer_name = "", bool force_select = false, bool force_no_transfer = false); - bool may_discard_current_dirty_preset(PresetCollection* presets = nullptr, const std::string& new_printer_name = "", bool no_transfer = false, bool no_transfer_variant = false); + bool may_discard_current_dirty_preset(PresetCollection* presets = nullptr, const std::string& new_printer_name = "", bool no_transfer = false, bool no_transfer_variant = false, ForceOption force_op = ForceOption::fopNone); virtual void clear_pages(); virtual void update_description_lines(); diff --git a/src/slic3r/GUI/UnsavedChangesDialog.hpp b/src/slic3r/GUI/UnsavedChangesDialog.hpp index b1bfbd0eb..218ff4757 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.hpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.hpp @@ -245,6 +245,12 @@ struct PresetItem wxString new_value; }; +enum ForceOption { + fopTransfer, + fopSave, + fopDiscard, + fopNone +}; class UnsavedChangesDialog : public DPIDialog {