diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index 7539f3616..7a9ea582a 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -1123,10 +1123,12 @@ void SavePresetDialog::Item::update() info_line = _L("Cannot overwrite a system profile."); m_valid_type = NoValid; } + if (m_valid_type == Valid && existing && (existing->is_external)) { info_line = _L("Cannot overwrite an external profile."); m_valid_type = NoValid; } + if (m_valid_type == Valid && existing && m_preset_name != m_presets->get_selected_preset_name()) { info_line = from_u8((boost::format(_u8L("Preset with name \"%1%\" already exists.")) % m_preset_name).str()) + "\n" + @@ -1134,6 +1136,11 @@ void SavePresetDialog::Item::update() m_valid_type = Warning; } + if (m_valid_type == Valid && m_preset_name.empty()) { + info_line = _L("The empty name is not available."); + m_valid_type = NoValid; + } + m_valid_label->SetLabel(info_line); m_valid_label->Show(!info_line.IsEmpty()); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 5c54e9e46..ef124e0e6 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -3124,6 +3124,12 @@ void Tab::select_preset(std::string preset_name, bool delete_current /*=false*/, m_dependent_tabs = { Preset::Type::TYPE_SLA_PRINT, Preset::Type::TYPE_SLA_MATERIAL }; } + // check if there is something in the cache to move to the new selected preset + if (!m_cache_config.empty()) { + m_presets->get_edited_preset().config.apply(m_cache_config); + m_cache_config.clear(); + } + load_current_preset(); } } @@ -3134,11 +3140,10 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr { if (presets == nullptr) presets = m_presets; - UnsavedChangesDialog dlg(m_type, new_printer_name); + UnsavedChangesDialog dlg(m_type, presets, new_printer_name); if (dlg.ShowModal() == wxID_CANCEL) return false; - if (dlg.just_continue()) - return true; + if (dlg.save_preset()) // save selected changes { std::vector unselected_options = dlg.get_unselected_options(); @@ -3147,7 +3152,7 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr // for system/default/external presets we should take an edited name if (preset.is_system || preset.is_default || preset.is_external) { - SavePresetDialog save_dlg(m_type, _CTX_utf8(L_CONTEXT("Copy", "PresetName"), "PresetName")); + SavePresetDialog save_dlg(preset.type, _CTX_utf8(L_CONTEXT("Copy", "PresetName"), "PresetName")); if (save_dlg.ShowModal() != wxID_OK) return false; name = save_dlg.get_name(); @@ -3157,56 +3162,35 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr if (!unselected_options.empty()) { DynamicPrintConfig& old_config = presets->get_selected_preset().config; - + // revert unselected options to the old values for (const std::string& opt_key : unselected_options) - m_config->set_key_value(opt_key, old_config.option(opt_key)->clone()); + presets->get_edited_preset().config.set_key_value(opt_key, old_config.option(opt_key)->clone()); } - - save_preset(name); - return true; - } - if (dlg.move_preset()) - // move selected changes - return false; - return false; -/* - // Display a dialog showing the dirty options in a human readable form. - const Preset& old_preset = presets->get_edited_preset(); - std::string type_name = presets->name(); - wxString tab = " "; - wxString name = old_preset.is_default ? - from_u8((boost::format(_utf8(L("Default preset (%s)"))) % _utf8(type_name)).str()) : - from_u8((boost::format(_utf8(L("Preset (%s)"))) % _utf8(type_name)).str()) + "\n" + tab + old_preset.name; + if (m_type == presets->type()) // save changes for the current preset + save_preset(name); + else // save changes for dependent preset + { + // Save the preset into Slic3r::data_dir / presets / section_name / preset_name.ini + presets->save_current_preset(name); + // Mark the print & filament enabled if they are compatible with the currently selected preset. + // If saving the preset changes compatibility with other presets, keep the now incompatible dependent presets selected, however with a "red flag" icon showing that they are no more compatible. + m_preset_bundle->update_compatible(PresetSelectCompatibleType::Never); - // Collect descriptions of the dirty options. - wxString changes; - for (const std::string &opt_key : presets->current_dirty_options()) { - const ConfigOptionDef &opt = m_config->def()->options.at(opt_key); - wxString name = ""; - if (! opt.category.empty()) - name += _(opt.category) + " > "; - name += !opt.full_label.empty() ? - _(opt.full_label) : - _(opt.label); - changes += tab + (name) + "\n"; + /* If filament preset is saved for multi-material printer preset, + * there are cases when filament comboboxs are updated for old (non-modified) colors, + * but in full_config a filament_colors option aren't.*/ + if (presets->type() == Preset::TYPE_FILAMENT && wxGetApp().extruders_edited_cnt() > 1) + wxGetApp().plater()->force_filament_colors_update(); + } } - // Show a confirmation dialog with the list of dirty options. - wxString message = name + "\n\n"; - if (new_printer_name.empty()) - message += _(L("has the following unsaved changes:")); - else { - message += (m_type == Slic3r::Preset::TYPE_PRINTER) ? - _(L("is not compatible with printer")) : - _(L("is not compatible with print profile")); - message += wxString("\n") + tab + from_u8(new_printer_name) + "\n\n"; - message += _(L("and it has the following unsaved changes:")); + else if (dlg.move_preset()) // move selected changes + { + // copy selected options to the cache from edited preset + m_cache_config.apply_only(*m_config, dlg.get_selected_options()); } - wxMessageDialog confirm(parent(), - message + "\n" + changes + "\n\n" + _(L("Discard changes and continue anyway?")), - _(L("Unsaved Changes")), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION); - return confirm.ShowModal() == wxID_YES; - */ + + return true; } // If we are switching from the FFF-preset to the SLA, we should to control the printed objects if they have a part(s). diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 24f25e2d7..c9639bd00 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -236,6 +236,7 @@ public: bool m_show_btn_incompatible_presets = false; PresetCollection* m_presets; DynamicPrintConfig* m_config; + DynamicPrintConfig m_cache_config; ogStaticText* m_parent_preset_description_line; ScalableButton* m_detach_preset_btn = nullptr; diff --git a/src/slic3r/GUI/UnsavedChangesDialog.cpp b/src/slic3r/GUI/UnsavedChangesDialog.cpp index f93aa35c2..67ccc6b6a 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.cpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.cpp @@ -514,7 +514,7 @@ void UnsavedChangesModel::Rescale() // UnsavedChangesDialog //------------------------------------------ -UnsavedChangesDialog::UnsavedChangesDialog(Preset::Type type, const std::string& new_selected_preset) +UnsavedChangesDialog::UnsavedChangesDialog(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset) : DPIDialog(nullptr, wxID_ANY, _L("Unsaved Changes"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); @@ -530,6 +530,9 @@ UnsavedChangesDialog::UnsavedChangesDialog(Preset::Type type, const std::string& int border = 10; int em = em_unit(); + m_action_line = new wxStaticText(this, wxID_ANY, ""); + m_action_line->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold()); + m_tree = new wxDataViewCtrl(this, wxID_ANY, wxDefaultPosition, wxSize(em * 80, em * 30), wxBORDER_SIMPLE | wxDV_VARIABLE_LINE_HEIGHT | wxDV_ROW_LINES); m_tree_model = new UnsavedChangesModel(this); m_tree->AssociateModel(m_tree_model); @@ -561,36 +564,24 @@ UnsavedChangesDialog::UnsavedChangesDialog(Preset::Type type, const std::string& m_tree->Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, &UnsavedChangesDialog::context_menu, this); // Add Buttons - wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxCANCEL); + wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxCANCEL); - Tab* tab = wxGetApp().get_tab(type); - assert(tab); - PresetCollection* presets = tab->get_presets(); + auto add_btn = [this, buttons](ScalableButton** btn, int& btn_id, const std::string& icon_name, Action close_act, int idx, bool process_enable = true) + { + *btn = new ScalableButton(this, btn_id = NewControlId(), icon_name, "", wxDefaultSize, wxDefaultPosition, wxBORDER_DEFAULT, true); + buttons->Insert(idx, *btn, 0, wxLEFT, 5); - wxString label= from_u8((boost::format(_u8L("Save selected to preset: %1%"))% ("\"" + presets->get_selected_preset().name + "\"")).str()); - m_save_btn = new ScalableButton(this, m_save_btn_id = NewControlId(), "save", label, wxDefaultSize, wxDefaultPosition, wxBORDER_DEFAULT, true); - buttons->Insert(0, m_save_btn, 0, wxLEFT, 5); + (*btn)->Bind(wxEVT_BUTTON, [this, close_act](wxEvent&) { close(close_act); }); + if (process_enable) + (*btn)->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(!m_empty_selection); }); + (*btn)->Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent& e) { show_info_line(Action::Undef); e.Skip(); }); + }; - m_save_btn->Bind(wxEVT_BUTTON, [this](wxEvent&) { close(Action::Save); }); - m_save_btn->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(!m_empty_selection); }); - m_save_btn->Bind(wxEVT_ENTER_WINDOW,[this, presets](wxMouseEvent& e){ show_info_line(Action::Save, presets->get_selected_preset().name); e.Skip(); }); - m_save_btn->Bind(wxEVT_LEAVE_WINDOW,[this ](wxMouseEvent& e){ show_info_line(Action::Undef); e.Skip(); }); - - label = from_u8((boost::format(_u8L("Move selected to preset: %1%"))% ("\"" + from_u8(new_selected_preset) + "\"")).str()); - m_move_btn = new ScalableButton(this, m_move_btn_id = NewControlId(), "paste_menu", label, wxDefaultSize, wxDefaultPosition, wxBORDER_DEFAULT, true); - buttons->Insert(1, m_move_btn, 0, wxLEFT, 5); - - m_move_btn->Bind(wxEVT_BUTTON, [this](wxEvent&) { close(Action::Move); }); - m_move_btn->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(!m_empty_selection); }); - m_move_btn->Bind(wxEVT_ENTER_WINDOW,[this, new_selected_preset](wxMouseEvent& e){ show_info_line(Action::Move, new_selected_preset); e.Skip(); }); - m_move_btn->Bind(wxEVT_LEAVE_WINDOW,[this ](wxMouseEvent& e){ show_info_line(Action::Undef); e.Skip(); }); - - label = _L("Continue without changes"); - m_continue_btn = new ScalableButton(this, m_continue_btn_id = NewControlId(), "cross", label, wxDefaultSize, wxDefaultPosition, wxBORDER_DEFAULT, true); - buttons->Insert(2, m_continue_btn, 0, wxLEFT, 5); - m_continue_btn->Bind(wxEVT_BUTTON, [this](wxEvent&) { close(Action::Continue); }); - m_continue_btn->Bind(wxEVT_ENTER_WINDOW,[this](wxMouseEvent& e){ show_info_line(Action::Continue); e.Skip(); }); - m_continue_btn->Bind(wxEVT_LEAVE_WINDOW,[this](wxMouseEvent& e){ show_info_line(Action::Undef); e.Skip(); }); + int btn_idx = 0; + add_btn(&m_save_btn, m_save_btn_id, "save", Action::Save, btn_idx++); + if (type == dependent_presets->type()) + add_btn(&m_move_btn, m_move_btn_id, "paste_menu", Action::Move, btn_idx++); + add_btn(&m_continue_btn, m_continue_btn_id, "cross", Action::Continue, btn_idx, false); m_info_line = new wxStaticText(this, wxID_ANY, ""); m_info_line->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold()); @@ -598,12 +589,12 @@ UnsavedChangesDialog::UnsavedChangesDialog(Preset::Type type, const std::string& wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL); - topSizer->Add(new wxStaticText(this, wxID_ANY, _L("There are unsaved changes for") + (": \"" + tab->title() + "\"")), 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border); + topSizer->Add(m_action_line,0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border); topSizer->Add(m_tree, 1, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border); topSizer->Add(m_info_line, 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, 2*border); topSizer->Add(buttons, 0, wxEXPAND | wxALL, border); - update(type); + update(type, dependent_presets, new_selected_preset); SetSizer(topSizer); topSizer->SetSizeHints(this); @@ -824,12 +815,34 @@ wxString UnsavedChangesDialog::get_short_string(wxString full_string) return full_string + dots; } -void UnsavedChangesDialog::update(Preset::Type type) +void UnsavedChangesDialog::update(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset) { - Tab* tab = wxGetApp().get_tab(type); - assert(tab); + PresetCollection* presets = dependent_presets; + + // activate buttons and labels + m_save_btn ->Bind(wxEVT_ENTER_WINDOW, [this, presets] (wxMouseEvent& e) { show_info_line(Action::Save, presets->get_selected_preset().name); e.Skip(); }); + if (m_move_btn) + m_move_btn ->Bind(wxEVT_ENTER_WINDOW, [this, new_selected_preset] (wxMouseEvent& e) { show_info_line(Action::Move, new_selected_preset); e.Skip(); }); + m_continue_btn ->Bind(wxEVT_ENTER_WINDOW, [this] (wxMouseEvent& e) { show_info_line(Action::Continue); e.Skip(); }); + + m_save_btn->SetLabel(from_u8((boost::format(_u8L("Save selected to preset: %1%")) % ("\"" + presets->get_selected_preset().name + "\"")).str())); + m_continue_btn->SetLabel(_L("Continue without changes")); + + wxString action_msg; + if (type == dependent_presets->type()) { + action_msg = _L("has the following unsaved changes:"); + + m_move_btn->SetLabel(from_u8((boost::format(_u8L("Move selected to preset: %1%")) % ("\"" + new_selected_preset + "\"")).str())); + } + else { + action_msg = type == Preset::TYPE_PRINTER ? + _L("is not compatible with printer") : + _L("is not compatible with print profile"); + action_msg += " \"" + from_u8(new_selected_preset) + "\" "; + action_msg += _L("and it has the following unsaved changes:"); + } + m_action_line->SetLabel(from_u8((boost::format(_utf8(L("Preset \"%1%\" %2%"))) % _utf8(presets->get_edited_preset().name) % action_msg).str())); - PresetCollection* presets = tab->get_presets(); // Display a dialog showing the dirty options in a human readable form. const DynamicPrintConfig& old_config = presets->get_selected_preset().config; const DynamicPrintConfig& new_config = presets->get_edited_preset().config; diff --git a/src/slic3r/GUI/UnsavedChangesDialog.hpp b/src/slic3r/GUI/UnsavedChangesDialog.hpp index 271d7595b..afb73a4f9 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.hpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.hpp @@ -193,6 +193,7 @@ class UnsavedChangesDialog : public DPIDialog ScalableButton* m_save_btn { nullptr }; ScalableButton* m_move_btn { nullptr }; ScalableButton* m_continue_btn { nullptr }; + wxStaticText* m_action_line { nullptr }; wxStaticText* m_info_line { nullptr }; bool m_empty_selection { false }; @@ -226,12 +227,12 @@ class UnsavedChangesDialog : public DPIDialog std::map m_items_map; public: - UnsavedChangesDialog(Preset::Type type, const std::string& new_selected_preset); + UnsavedChangesDialog(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset); ~UnsavedChangesDialog() {} wxString get_short_string(wxString full_string); - void update(Preset::Type type); + void update(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset); void item_value_changed(wxDataViewEvent &event); void context_menu(wxDataViewEvent &event); void show_info_line(Action action, std::string preset_name = "");