Unsaved Changes : implemented "move" and improved "save"

UnsavedChangesDialog : some code refactoring

SavePresetDialog : processed empty name for the preset
This commit is contained in:
YuSanka 2020-08-13 15:45:16 +02:00
parent 491e7b16f9
commit d7176c64bd
5 changed files with 90 additions and 84 deletions

View File

@ -1123,10 +1123,12 @@ void SavePresetDialog::Item::update()
info_line = _L("Cannot overwrite a system profile."); info_line = _L("Cannot overwrite a system profile.");
m_valid_type = NoValid; m_valid_type = NoValid;
} }
if (m_valid_type == Valid && existing && (existing->is_external)) { if (m_valid_type == Valid && existing && (existing->is_external)) {
info_line = _L("Cannot overwrite an external profile."); info_line = _L("Cannot overwrite an external profile.");
m_valid_type = NoValid; m_valid_type = NoValid;
} }
if (m_valid_type == Valid && existing && m_preset_name != m_presets->get_selected_preset_name()) 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" + 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; 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->SetLabel(info_line);
m_valid_label->Show(!info_line.IsEmpty()); m_valid_label->Show(!info_line.IsEmpty());

View File

@ -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 }; 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(); load_current_preset();
} }
} }
@ -3134,11 +3140,10 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr
{ {
if (presets == nullptr) presets = m_presets; 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) if (dlg.ShowModal() == wxID_CANCEL)
return false; return false;
if (dlg.just_continue())
return true;
if (dlg.save_preset()) // save selected changes if (dlg.save_preset()) // save selected changes
{ {
std::vector<std::string> unselected_options = dlg.get_unselected_options(); std::vector<std::string> 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 // for system/default/external presets we should take an edited name
if (preset.is_system || preset.is_default || preset.is_external) { 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) if (save_dlg.ShowModal() != wxID_OK)
return false; return false;
name = save_dlg.get_name(); name = save_dlg.get_name();
@ -3157,56 +3162,35 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr
if (!unselected_options.empty()) if (!unselected_options.empty())
{ {
DynamicPrintConfig& old_config = presets->get_selected_preset().config; DynamicPrintConfig& old_config = presets->get_selected_preset().config;
// revert unselected options to the old values
for (const std::string& opt_key : unselected_options) 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; if (m_type == presets->type()) // save changes for the current preset
/* save_preset(name);
// Display a dialog showing the dirty options in a human readable form. else // save changes for dependent preset
const Preset& old_preset = presets->get_edited_preset(); {
std::string type_name = presets->name(); // Save the preset into Slic3r::data_dir / presets / section_name / preset_name.ini
wxString tab = " "; presets->save_current_preset(name);
wxString name = old_preset.is_default ? // Mark the print & filament enabled if they are compatible with the currently selected preset.
from_u8((boost::format(_utf8(L("Default preset (%s)"))) % _utf8(type_name)).str()) : // 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.
from_u8((boost::format(_utf8(L("Preset (%s)"))) % _utf8(type_name)).str()) + "\n" + tab + old_preset.name; m_preset_bundle->update_compatible(PresetSelectCompatibleType::Never);
// Collect descriptions of the dirty options. /* If filament preset is saved for multi-material printer preset,
wxString changes; * there are cases when filament comboboxs are updated for old (non-modified) colors,
for (const std::string &opt_key : presets->current_dirty_options()) { * but in full_config a filament_colors option aren't.*/
const ConfigOptionDef &opt = m_config->def()->options.at(opt_key); if (presets->type() == Preset::TYPE_FILAMENT && wxGetApp().extruders_edited_cnt() > 1)
wxString name = ""; wxGetApp().plater()->force_filament_colors_update();
if (! opt.category.empty()) }
name += _(opt.category) + " > ";
name += !opt.full_label.empty() ?
_(opt.full_label) :
_(opt.label);
changes += tab + (name) + "\n";
} }
// Show a confirmation dialog with the list of dirty options. else if (dlg.move_preset()) // move selected changes
wxString message = name + "\n\n"; {
if (new_printer_name.empty()) // copy selected options to the cache from edited preset
message += _(L("has the following unsaved changes:")); m_cache_config.apply_only(*m_config, dlg.get_selected_options());
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:"));
} }
wxMessageDialog confirm(parent(),
message + "\n" + changes + "\n\n" + _(L("Discard changes and continue anyway?")), return true;
_(L("Unsaved Changes")), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION);
return confirm.ShowModal() == wxID_YES;
*/
} }
// If we are switching from the FFF-preset to the SLA, we should to control the printed objects if they have a part(s). // If we are switching from the FFF-preset to the SLA, we should to control the printed objects if they have a part(s).

View File

@ -236,6 +236,7 @@ public:
bool m_show_btn_incompatible_presets = false; bool m_show_btn_incompatible_presets = false;
PresetCollection* m_presets; PresetCollection* m_presets;
DynamicPrintConfig* m_config; DynamicPrintConfig* m_config;
DynamicPrintConfig m_cache_config;
ogStaticText* m_parent_preset_description_line; ogStaticText* m_parent_preset_description_line;
ScalableButton* m_detach_preset_btn = nullptr; ScalableButton* m_detach_preset_btn = nullptr;

View File

@ -514,7 +514,7 @@ void UnsavedChangesModel::Rescale()
// UnsavedChangesDialog // 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) : DPIDialog(nullptr, wxID_ANY, _L("Unsaved Changes"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{ {
wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
@ -530,6 +530,9 @@ UnsavedChangesDialog::UnsavedChangesDialog(Preset::Type type, const std::string&
int border = 10; int border = 10;
int em = em_unit(); 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 = 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_model = new UnsavedChangesModel(this);
m_tree->AssociateModel(m_tree_model); 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); m_tree->Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, &UnsavedChangesDialog::context_menu, this);
// Add Buttons // Add Buttons
wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxCANCEL); wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxCANCEL);
Tab* tab = wxGetApp().get_tab(type); auto add_btn = [this, buttons](ScalableButton** btn, int& btn_id, const std::string& icon_name, Action close_act, int idx, bool process_enable = true)
assert(tab); {
PresetCollection* presets = tab->get_presets(); *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()); (*btn)->Bind(wxEVT_BUTTON, [this, close_act](wxEvent&) { close(close_act); });
m_save_btn = new ScalableButton(this, m_save_btn_id = NewControlId(), "save", label, wxDefaultSize, wxDefaultPosition, wxBORDER_DEFAULT, true); if (process_enable)
buttons->Insert(0, m_save_btn, 0, wxLEFT, 5); (*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); }); int btn_idx = 0;
m_save_btn->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(!m_empty_selection); }); add_btn(&m_save_btn, m_save_btn_id, "save", Action::Save, btn_idx++);
m_save_btn->Bind(wxEVT_ENTER_WINDOW,[this, presets](wxMouseEvent& e){ show_info_line(Action::Save, presets->get_selected_preset().name); e.Skip(); }); if (type == dependent_presets->type())
m_save_btn->Bind(wxEVT_LEAVE_WINDOW,[this ](wxMouseEvent& e){ show_info_line(Action::Undef); e.Skip(); }); 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);
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(); });
m_info_line = new wxStaticText(this, wxID_ANY, ""); m_info_line = new wxStaticText(this, wxID_ANY, "");
m_info_line->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold()); 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); 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_tree, 1, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border);
topSizer->Add(m_info_line, 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, 2*border); topSizer->Add(m_info_line, 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, 2*border);
topSizer->Add(buttons, 0, wxEXPAND | wxALL, border); topSizer->Add(buttons, 0, wxEXPAND | wxALL, border);
update(type); update(type, dependent_presets, new_selected_preset);
SetSizer(topSizer); SetSizer(topSizer);
topSizer->SetSizeHints(this); topSizer->SetSizeHints(this);
@ -824,12 +815,34 @@ wxString UnsavedChangesDialog::get_short_string(wxString full_string)
return full_string + dots; 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); PresetCollection* presets = dependent_presets;
assert(tab);
// 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. // Display a dialog showing the dirty options in a human readable form.
const DynamicPrintConfig& old_config = presets->get_selected_preset().config; const DynamicPrintConfig& old_config = presets->get_selected_preset().config;
const DynamicPrintConfig& new_config = presets->get_edited_preset().config; const DynamicPrintConfig& new_config = presets->get_edited_preset().config;

View File

@ -193,6 +193,7 @@ class UnsavedChangesDialog : public DPIDialog
ScalableButton* m_save_btn { nullptr }; ScalableButton* m_save_btn { nullptr };
ScalableButton* m_move_btn { nullptr }; ScalableButton* m_move_btn { nullptr };
ScalableButton* m_continue_btn { nullptr }; ScalableButton* m_continue_btn { nullptr };
wxStaticText* m_action_line { nullptr };
wxStaticText* m_info_line { nullptr }; wxStaticText* m_info_line { nullptr };
bool m_empty_selection { false }; bool m_empty_selection { false };
@ -226,12 +227,12 @@ class UnsavedChangesDialog : public DPIDialog
std::map<wxDataViewItem, ItemData> m_items_map; std::map<wxDataViewItem, ItemData> m_items_map;
public: 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() {} ~UnsavedChangesDialog() {}
wxString get_short_string(wxString full_string); 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 item_value_changed(wxDataViewEvent &event);
void context_menu(wxDataViewEvent &event); void context_menu(wxDataViewEvent &event);
void show_info_line(Action action, std::string preset_name = ""); void show_info_line(Action action, std::string preset_name = "");