Unsaved Changes : improvement for the GUI_App::check_unsaved_changes()

Added use of UnsavedChangesDialog
This commit is contained in:
YuSanka 2020-08-14 18:17:16 +02:00
parent 8f15efbf9a
commit 618f04717f
8 changed files with 228 additions and 98 deletions

View file

@ -327,6 +327,32 @@ const std::string& PresetBundle::get_preset_name_by_alias( const Preset::Type& p
return presets.get_preset_name_by_alias(alias); return presets.get_preset_name_by_alias(alias);
} }
void PresetBundle::save_changes_for_preset(const std::string& new_name, Preset::Type type,
const std::vector<std::string>& unselected_options)
{
PresetCollection& presets = type == Preset::TYPE_PRINT ? prints :
type == Preset::TYPE_SLA_PRINT ? sla_prints :
type == Preset::TYPE_FILAMENT ? filaments :
type == Preset::TYPE_SLA_MATERIAL ? sla_materials : printers;
// if we want to save just some from selected options
if (!unselected_options.empty()) {
// revert unselected options to the old values
presets.get_edited_preset().config.apply_only(presets.get_selected_preset().config, unselected_options);
}
// Save the preset into Slic3r::data_dir / presets / section_name / preset_name.ini
presets.save_current_preset(new_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.
update_compatible(PresetSelectCompatibleType::Never);
if (type == Preset::TYPE_FILAMENT) {
// synchronize the first filament presets.
set_filament_preset(0, filaments.get_selected_preset_name());
}
}
void PresetBundle::load_installed_filaments(AppConfig &config) void PresetBundle::load_installed_filaments(AppConfig &config)
{ {
if (! config.has_section(AppConfig::SECTION_FILAMENTS)) { if (! config.has_section(AppConfig::SECTION_FILAMENTS)) {

View file

@ -130,6 +130,10 @@ public:
const std::string& get_preset_name_by_alias(const Preset::Type& preset_type, const std::string& alias) const; const std::string& get_preset_name_by_alias(const Preset::Type& preset_type, const std::string& alias) const;
// Save current preset of a required type under a new name. If the name is different from the old one,
// Unselected option would be reverted to the beginning values
void save_changes_for_preset(const std::string& new_name, Preset::Type type, const std::vector<std::string>& unselected_options);
static const char *PRUSA_BUNDLE; static const char *PRUSA_BUNDLE;
private: private:
std::string load_system_presets(); std::string load_system_presets();

View file

@ -57,6 +57,8 @@
#include "RemovableDriveManager.hpp" #include "RemovableDriveManager.hpp"
#include "InstanceCheck.hpp" #include "InstanceCheck.hpp"
#include "NotificationManager.hpp" #include "NotificationManager.hpp"
#include "UnsavedChangesDialog.hpp"
#include "PresetComboBoxes.hpp"
#ifdef __WXMSW__ #ifdef __WXMSW__
#include <dbt.h> #include <dbt.h>
@ -1157,29 +1159,66 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
// to notify the user whether he is aware that some preset changes will be lost. // to notify the user whether he is aware that some preset changes will be lost.
bool GUI_App::check_unsaved_changes(const wxString &header) bool GUI_App::check_unsaved_changes(const wxString &header)
{ {
wxString dirty;
PrinterTechnology printer_technology = preset_bundle->printers.get_edited_preset().printer_technology(); PrinterTechnology printer_technology = preset_bundle->printers.get_edited_preset().printer_technology();
for (Tab *tab : tabs_list)
bool has_unsaved_changes = false;
for (Tab* tab : tabs_list)
if (tab->supports_printer_technology(printer_technology) && tab->current_preset_is_dirty()) { if (tab->supports_printer_technology(printer_technology) && tab->current_preset_is_dirty()) {
if (dirty.empty()) has_unsaved_changes = true;
dirty = tab->title(); break;
else
dirty += wxString(", ") + tab->title();
} }
if (dirty.empty()) if (has_unsaved_changes)
// No changes, the application may close or reload presets. {
return true; UnsavedChangesDialog dlg(header);
// Ask the user. if (dlg.ShowModal() == wxID_CANCEL)
wxString message; return false;
if (! header.empty())
message = header + "\n\n"; if (dlg.save_preset()) // save selected changes
message += _(L("The presets on the following tabs were modified")) + ": " + dirty + "\n\n" + _(L("Discard changes and continue anyway?")); {
wxMessageDialog dialog(mainframe, struct NameType
message, {
wxString(SLIC3R_APP_NAME) + " - " + _(L("Unsaved Presets")), std::string name;
wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT); Preset::Type type {Preset::TYPE_INVALID};
return dialog.ShowModal() == wxID_YES; };
std::vector<NameType> names_and_types;
// for system/default/external presets we should take an edited name
std::vector<Preset::Type> types;
for (Tab* tab : tabs_list)
if (tab->supports_printer_technology(printer_technology) && tab->current_preset_is_dirty())
{
const Preset& preset = tab->get_presets()->get_edited_preset();
if (preset.is_system || preset.is_default || preset.is_external)
types.emplace_back(preset.type);
names_and_types.emplace_back(NameType{ preset.name, preset.type });
}
if (!types.empty()) {
SavePresetDialog save_dlg(types);
if (save_dlg.ShowModal() != wxID_OK)
return false;
for (NameType& nt : names_and_types) {
const std::string name = save_dlg.get_name(nt.type);
if (!name.empty())
nt.name = name;
}
}
for (const NameType& nt : names_and_types)
preset_bundle->save_changes_for_preset(nt.name, nt.type, dlg.get_unselected_options(nt.type));
// if we saved changes to the new presets, we should to
// synchronize config.ini with the current selections.
preset_bundle->export_selections(*app_config);
}
}
return true;
} }
bool GUI_App::checked_tab(Tab* tab) bool GUI_App::checked_tab(Tab* tab)

View file

@ -1170,8 +1170,26 @@ void SavePresetDialog::Item::accept()
// SavePresetDialog // SavePresetDialog
//----------------------------------------------- //-----------------------------------------------
SavePresetDialog::SavePresetDialog(Preset::Type type, const std::string& suffix) SavePresetDialog::SavePresetDialog(Preset::Type type, std::string suffix)
: DPIDialog(nullptr, wxID_ANY, _L("Save preset"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING | wxRESIZE_BORDER) : DPIDialog(nullptr, wxID_ANY, _L("Save preset"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING | wxRESIZE_BORDER)
{
build(std::vector<Preset::Type>{type}, suffix);
}
SavePresetDialog::SavePresetDialog(std::vector<Preset::Type> types, std::string suffix)
: DPIDialog(nullptr, wxID_ANY, _L("Save preset"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING | wxRESIZE_BORDER)
{
build(types, suffix);
}
SavePresetDialog::~SavePresetDialog()
{
for (auto item : m_items) {
delete item;
}
}
void SavePresetDialog::build(std::vector<Preset::Type> types, std::string suffix)
{ {
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT #if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
@ -1179,14 +1197,18 @@ SavePresetDialog::SavePresetDialog(Preset::Type type, const std::string& suffix)
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts, // Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT // From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
#endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT #endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
if (suffix.empty())
suffix = _CTX_utf8(L_CONTEXT("Copy", "PresetName"), "PresetName");
wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);
m_presets_sizer = new wxBoxSizer(wxVERTICAL); m_presets_sizer = new wxBoxSizer(wxVERTICAL);
// Add first item // Add first item
m_items.emplace_back(type, suffix, m_presets_sizer, this); for (Preset::Type type : types)
AddItem(type, suffix);
// Add dialog's buttons // Add dialog's buttons
wxStdDialogButtonSizer* btns = this->CreateStdDialogButtonSizer(wxOK | wxCANCEL); wxStdDialogButtonSizer* btns = this->CreateStdDialogButtonSizer(wxOK | wxCANCEL);
@ -1203,26 +1225,26 @@ SavePresetDialog::SavePresetDialog(Preset::Type type, const std::string& suffix)
void SavePresetDialog::AddItem(Preset::Type type, const std::string& suffix) void SavePresetDialog::AddItem(Preset::Type type, const std::string& suffix)
{ {
m_items.emplace_back(type, suffix, m_presets_sizer, this); m_items.emplace_back(new Item{type, suffix, m_presets_sizer, this});
} }
std::string SavePresetDialog::get_name() std::string SavePresetDialog::get_name()
{ {
return m_items.front().preset_name(); return m_items.front()->preset_name();
} }
std::string SavePresetDialog::get_name(Preset::Type type) std::string SavePresetDialog::get_name(Preset::Type type)
{ {
for (Item& item : m_items) for (const Item* item : m_items)
if (item.type() == type) if (item->type() == type)
return item.preset_name(); return item->preset_name();
return ""; return "";
} }
bool SavePresetDialog::enable_ok_btn() const bool SavePresetDialog::enable_ok_btn() const
{ {
for (Item item : m_items) for (const Item* item : m_items)
if (!item.is_valid()) if (!item->is_valid())
return false; return false;
return true; return true;
@ -1291,8 +1313,8 @@ void SavePresetDialog::on_dpi_changed(const wxRect& suggested_rect)
msw_buttons_rescale(this, em, { wxID_OK, wxID_CANCEL }); msw_buttons_rescale(this, em, { wxID_OK, wxID_CANCEL });
for (Item& item : m_items) for (Item* item : m_items)
item.update_valid_bmp(); item->update_valid_bmp();
//const wxSize& size = wxSize(45 * em, 35 * em); //const wxSize& size = wxSize(45 * em, 35 * em);
SetMinSize(/*size*/wxSize(100, 50)); SetMinSize(/*size*/wxSize(100, 50));
@ -1331,10 +1353,10 @@ void SavePresetDialog::update_physical_printers(const std::string& preset_name)
void SavePresetDialog::accept() void SavePresetDialog::accept()
{ {
for (Item& item : m_items) { for (Item* item : m_items) {
item.accept(); item->accept();
if (item.type() == Preset::TYPE_PRINTER) if (item->type() == Preset::TYPE_PRINTER)
update_physical_printers(item.preset_name()); update_physical_printers(item->preset_name());
} }
EndModal(wxID_OK); EndModal(wxID_OK);

View file

@ -235,7 +235,7 @@ class SavePresetDialog : public DPIDialog
void update(); void update();
}; };
std::vector<Item> m_items; std::vector<Item*> m_items;
wxBoxSizer* m_presets_sizer {nullptr}; wxBoxSizer* m_presets_sizer {nullptr};
wxStaticText* m_label {nullptr}; wxStaticText* m_label {nullptr};
@ -248,8 +248,9 @@ class SavePresetDialog : public DPIDialog
public: public:
SavePresetDialog(Preset::Type type, const std::string& suffix); SavePresetDialog(Preset::Type type, std::string suffix = "");
~SavePresetDialog() {} SavePresetDialog(std::vector<Preset::Type> types, std::string suffix = "");
~SavePresetDialog();
void AddItem(Preset::Type type, const std::string& suffix); void AddItem(Preset::Type type, const std::string& suffix);
@ -266,6 +267,7 @@ protected:
void on_sys_color_changed() override {} void on_sys_color_changed() override {}
private: private:
void build(std::vector<Preset::Type> types, std::string suffix = "");
void update_physical_printers(const std::string& preset_name); void update_physical_printers(const std::string& preset_name);
void accept(); void accept();
}; };

View file

@ -3146,36 +3146,27 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr
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(presets->type());
const Preset& preset = presets->get_edited_preset(); const Preset& preset = presets->get_edited_preset();
std::string name = preset.name; std::string name = preset.name;
// 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(preset.type, _CTX_utf8(L_CONTEXT("Copy", "PresetName"), "PresetName")); SavePresetDialog save_dlg(preset.type);
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();
} }
// if we want to save just some from selected options if (m_type == presets->type()) // save changes for the current preset from this tab
if (!unselected_options.empty())
{ {
DynamicPrintConfig& old_config = presets->get_selected_preset().config;
// revert unselected options to the old values // revert unselected options to the old values
for (const std::string& opt_key : unselected_options) presets->get_edited_preset().config.apply_only(presets->get_selected_preset().config, unselected_options);
presets->get_edited_preset().config.set_key_value(opt_key, old_config.option(opt_key)->clone());
}
if (m_type == presets->type()) // save changes for the current preset
save_preset(name); save_preset(name);
else // save changes for dependent preset }
else
{ {
// Save the preset into Slic3r::data_dir / presets / section_name / preset_name.ini m_preset_bundle->save_changes_for_preset(name, presets->type(), unselected_options);
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);
/* If filament preset is saved for multi-material printer preset, /* If filament preset is saved for multi-material printer preset,
* there are cases when filament comboboxs are updated for old (non-modified) colors, * there are cases when filament comboboxs are updated for old (non-modified) colors,
@ -3283,10 +3274,8 @@ void Tab::save_preset(std::string name /*= ""*/, bool detach)
// focus currently.is there anything better than this ? // focus currently.is there anything better than this ?
//! m_treectrl->OnSetFocus(); //! m_treectrl->OnSetFocus();
std::string suffix = detach ? _utf8(L("Detached")) : _CTX_utf8(L_CONTEXT("Copy", "PresetName"), "PresetName");
if (name.empty()) { if (name.empty()) {
SavePresetDialog dlg(m_type, suffix); SavePresetDialog dlg(m_type, detach ? _u8L("Detached") : "");
if (dlg.ShowModal() != wxID_OK) if (dlg.ShowModal() != wxID_OK)
return; return;
name = dlg.get_name(); name = dlg.get_name();

View file

@ -514,8 +514,19 @@ void UnsavedChangesModel::Rescale()
// UnsavedChangesDialog // UnsavedChangesDialog
//------------------------------------------ //------------------------------------------
UnsavedChangesDialog::UnsavedChangesDialog(const wxString& header)
: DPIDialog(nullptr, wxID_ANY, _L("Unsaved Changes"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
build(Preset::TYPE_INVALID, nullptr, "", header);
}
UnsavedChangesDialog::UnsavedChangesDialog(Preset::Type type, PresetCollection* dependent_presets, 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)
{
build(type, dependent_presets, new_selected_preset);
}
void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset, const wxString& header)
{ {
wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
SetBackgroundColour(bgr_clr); SetBackgroundColour(bgr_clr);
@ -579,7 +590,8 @@ UnsavedChangesDialog::UnsavedChangesDialog(Preset::Type type, PresetCollection*
int btn_idx = 0; int btn_idx = 0;
add_btn(&m_save_btn, m_save_btn_id, "save", Action::Save, btn_idx++); add_btn(&m_save_btn, m_save_btn_id, "save", Action::Save, btn_idx++);
if (type == dependent_presets->type()) if (type != Preset::TYPE_INVALID && type == dependent_presets->type() &&
dependent_presets->get_edited_preset().printer_technology() == dependent_presets->find_preset(new_selected_preset)->printer_technology())
add_btn(&m_move_btn, m_move_btn_id, "paste_menu", Action::Move, btn_idx++); 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); add_btn(&m_continue_btn, m_continue_btn_id, "cross", Action::Continue, btn_idx, false);
@ -594,7 +606,7 @@ UnsavedChangesDialog::UnsavedChangesDialog(Preset::Type type, PresetCollection*
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, dependent_presets, new_selected_preset); update(type, dependent_presets, new_selected_preset, header);
SetSizer(topSizer); SetSizer(topSizer);
topSizer->SetSizeHints(this); topSizer->SetSizeHints(this);
@ -654,8 +666,12 @@ void UnsavedChangesDialog::show_info_line(Action action, std::string preset_name
else if (action == Action::Continue) else if (action == Action::Continue)
text = _L("All changed options will be reverted."); text = _L("All changed options will be reverted.");
else { else {
std::string act_string = action == Action::Save ? _u8L("saved") : _u8L("moved"); if (action == Action::Save && preset_name.empty())
text = from_u8((boost::format("After press this button selected options will be %1% to the preset \"%2%\".") % act_string % preset_name).str()); text = _L("After press this button selected options will be saved");
else {
std::string act_string = action == Action::Save ? _u8L("saved") : _u8L("moved");
text = from_u8((boost::format("After press this button selected options will be %1% to the preset \"%2%\".") % act_string % preset_name).str());
}
text += "\n" + _L("Unselected options will be reverted."); text += "\n" + _L("Unselected options will be reverted.");
} }
m_info_line->SetLabel(text); m_info_line->SetLabel(text);
@ -815,64 +831,92 @@ wxString UnsavedChangesDialog::get_short_string(wxString full_string)
return full_string + dots; return full_string + dots;
} }
void UnsavedChangesDialog::update(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset) void UnsavedChangesDialog::update(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset, const wxString& header)
{ {
PresetCollection* presets = dependent_presets; PresetCollection* presets = dependent_presets;
// activate buttons and labels // 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(); }); m_save_btn ->Bind(wxEVT_ENTER_WINDOW, [this, presets] (wxMouseEvent& e) { show_info_line(Action::Save, presets ? presets->get_selected_preset().name : ""); e.Skip(); });
if (m_move_btn) 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_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_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")); m_continue_btn->SetLabel(_L("Continue without changes"));
wxString action_msg; if (type == Preset::TYPE_INVALID) {
if (type == dependent_presets->type()) { m_action_line ->SetLabel(header + "\n" + _L("Next presets have the following unsaved changes:"));
action_msg = _L("has the following unsaved changes:"); m_save_btn ->SetLabel(_L("Save selected"));
m_move_btn->SetLabel(from_u8((boost::format(_u8L("Move selected to preset: %1%")) % ("\"" + new_selected_preset + "\"")).str()));
} }
else { else {
action_msg = type == Preset::TYPE_PRINTER ? wxString action_msg;
_L("is not compatible with printer") : if (type == dependent_presets->type()) {
_L("is not compatible with print profile"); action_msg = _L("has the following unsaved changes:");
action_msg += " \"" + from_u8(new_selected_preset) + "\" "; if (m_move_btn)
action_msg += _L("and it 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) + "\"\n";
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()));
m_save_btn->SetLabel(from_u8((boost::format(_u8L("Save selected to preset: %1%")) % ("\"" + presets->get_selected_preset().name + "\"")).str()));
} }
m_action_line->SetLabel(from_u8((boost::format(_utf8(L("Preset \"%1%\" %2%"))) % _utf8(presets->get_edited_preset().name) % action_msg).str()));
// Display a dialog showing the dirty options in a human readable form. update_tree(type, presets);
const DynamicPrintConfig& old_config = presets->get_selected_preset().config; }
const DynamicPrintConfig& new_config = presets->get_edited_preset().config;
m_tree_model->AddPreset(type, from_u8(presets->get_edited_preset().name));
void UnsavedChangesDialog::update_tree(Preset::Type type, PresetCollection* presets_)
{
Search::OptionsSearcher& searcher = wxGetApp().sidebar().get_searcher(); Search::OptionsSearcher& searcher = wxGetApp().sidebar().get_searcher();
searcher.sort_options_by_opt_key(); searcher.sort_options_by_opt_key();
// Collect dirty options. // list of the presets with unsaved changes
for (const std::string& opt_key : presets->current_dirty_options()) { std::vector<PresetCollection*> presets_list;
const Search::Option& option = searcher.get_option(opt_key); if (type == Preset::TYPE_INVALID)
{
PrinterTechnology printer_technology = wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology();
ItemData item_data = { opt_key, option.label_local, get_string_value(opt_key, old_config), get_string_value(opt_key, new_config) }; for (Tab* tab : wxGetApp().tabs_list)
if (tab->supports_printer_technology(printer_technology) && tab->current_preset_is_dirty())
presets_list.emplace_back(tab->get_presets());
}
else
presets_list.emplace_back(presets_);
wxString old_val = get_short_string(item_data.old_val); // Display a dialog showing the dirty options in a human readable form.
wxString new_val = get_short_string(item_data.new_val); for (PresetCollection* presets : presets_list)
if (old_val != item_data.old_val || new_val != item_data.new_val) {
item_data.is_long = true; const DynamicPrintConfig& old_config = presets->get_selected_preset().config;
const DynamicPrintConfig& new_config = presets->get_edited_preset().config;
type = presets->type();
m_items_map.emplace(m_tree_model->AddOption(type, option.category_local, option.group_local, option.label_local, old_val, new_val), item_data); m_tree_model->AddPreset(type, from_u8(presets->get_edited_preset().name));
// Collect dirty options.
for (const std::string& opt_key : presets->current_dirty_options()) {
const Search::Option& option = searcher.get_option(opt_key);
ItemData item_data = { opt_key, option.label_local, get_string_value(opt_key, old_config), get_string_value(opt_key, new_config), type };
wxString old_val = get_short_string(item_data.old_val);
wxString new_val = get_short_string(item_data.new_val);
if (old_val != item_data.old_val || new_val != item_data.new_val)
item_data.is_long = true;
m_items_map.emplace(m_tree_model->AddOption(type, option.category_local, option.group_local, option.label_local, old_val, new_val), item_data);
}
} }
} }
std::vector<std::string> UnsavedChangesDialog::get_unselected_options() std::vector<std::string> UnsavedChangesDialog::get_unselected_options(Preset::Type type)
{ {
std::vector<std::string> ret; std::vector<std::string> ret;
for (auto item : m_items_map) for (auto item : m_items_map)
if (!m_tree_model->IsEnabledItem(item.first)) if (item.second.type == type && !m_tree_model->IsEnabledItem(item.first))
ret.emplace_back(item.second.opt_key); ret.emplace_back(item.second.opt_key);
return ret; return ret;

View file

@ -217,22 +217,26 @@ class UnsavedChangesDialog : public DPIDialog
struct ItemData struct ItemData
{ {
std::string opt_key; std::string opt_key;
wxString opt_name; wxString opt_name;
wxString old_val; wxString old_val;
wxString new_val; wxString new_val;
bool is_long {false}; Preset::Type type;
bool is_long {false};
}; };
// tree items related to the options // tree items related to the options
std::map<wxDataViewItem, ItemData> m_items_map; std::map<wxDataViewItem, ItemData> m_items_map;
public: public:
UnsavedChangesDialog(const wxString& header);
UnsavedChangesDialog(Preset::Type type, PresetCollection* dependent_presets, 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, PresetCollection* dependent_presets, const std::string& new_selected_preset); void build(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset, const wxString& header = "");
void update(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset, const wxString& header);
void update_tree(Preset::Type type, PresetCollection *presets);
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 = "");
@ -242,7 +246,7 @@ public:
bool move_preset() const { return m_exit_action == Action::Move; } bool move_preset() const { return m_exit_action == Action::Move; }
bool just_continue() const { return m_exit_action == Action::Continue; } bool just_continue() const { return m_exit_action == Action::Continue; }
std::vector<std::string> get_unselected_options(); std::vector<std::string> get_unselected_options(Preset::Type type);
std::vector<std::string> get_selected_options(); std::vector<std::string> get_selected_options();
protected: protected: