Check unsaved changes (#6991)
* Check Unsaved changes (partially related to #5903) + Allow create new project when Plater is empty, but some of presets are modified (related to #5903) + When creating new project allow Keep or Discard modification from previous project + Added check of changes: * before any load project (including DnD and "Load From Recent Projects") * before preset updater * when configuration is changing from the ConfigWizard + Dialog caption is added for each check + Create/Destroy ConfigWizard every time when it's called * Check Unsaved changes: Next Improvements + For dialog "Save project changes" added a reason of saving and name of the current project (or "Untitled") + UnsavedChangesDialog: Headers are extended to better explain the reason + Preferences: Fixed tooltiops for "Always ask for unsaved changes when..." + Suppress "Remember my choice" checkbox for actions which are not frequently used * Fixed behavior of the application when try to save changed project but "Cancel" button is selected in "Save file as..." dialog * Check unsaved changes: Improvements for Config Wizard - Check all cases when presets should be updated + Fixed info line for Materials pages. Text of the info relates to the printer technology now * Improved suggested name for a project when Application is closing * Fixed Linux/OSX build warnings
This commit is contained in:
parent
846b868215
commit
8f064dd155
17 changed files with 462 additions and 178 deletions
|
@ -139,6 +139,9 @@ void AppConfig::set_defaults()
|
|||
if (get("default_action_on_select_preset").empty())
|
||||
set("default_action_on_select_preset", "none"); // , "transfer", "discard" or "save"
|
||||
|
||||
if (get("default_action_on_new_project").empty())
|
||||
set("default_action_on_new_project", "none"); // , "keep(transfer)", "discard" or "save"
|
||||
|
||||
if (get("color_mapinulation_panel").empty())
|
||||
set("color_mapinulation_panel", "0");
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "format.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "UnsavedChangesDialog.hpp"
|
||||
|
||||
#if defined(__linux__) && defined(__WXGTK3__)
|
||||
#define wxLinux_gtk3 true
|
||||
|
@ -741,10 +742,10 @@ void PageMaterials::set_compatible_printers_html_window(const std::vector<std::s
|
|||
const auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue());
|
||||
const auto text_clr = wxGetApp().get_label_clr_default();//wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
|
||||
const auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue());
|
||||
wxString first_line = _L("Filaments marked with <b>*</b> are <b>not</b> compatible with some installed printers.");
|
||||
wxString first_line = format_wxstr(_L("%1% marked with <b>*</b> are <b>not</b> compatible with some installed printers."), materials->technology == T_FFF ? _L("Filaments") : _L("SLA materials"));
|
||||
wxString text;
|
||||
if (all_printers) {
|
||||
wxString second_line = _L("All installed printers are compatible with the selected filament.");
|
||||
wxString second_line = format_wxstr(_L("All installed printers are compatible with the selected %1%."), materials->technology == T_FFF ? _L("filament") : _L("SLA material"));
|
||||
text = wxString::Format(
|
||||
"<html>"
|
||||
"<style>"
|
||||
|
@ -764,7 +765,7 @@ void PageMaterials::set_compatible_printers_html_window(const std::vector<std::s
|
|||
, second_line
|
||||
);
|
||||
} else {
|
||||
wxString second_line = _L("Only the following installed printers are compatible with the selected filament:");
|
||||
wxString second_line = printer_names.empty() ? "" : format_wxstr(_L("Only the following installed printers are compatible with the selected %1%:"), materials->technology == T_FFF ? _L("filament") : _L("SLA material"));
|
||||
text = wxString::Format(
|
||||
"<html>"
|
||||
"<style>"
|
||||
|
@ -2473,8 +2474,16 @@ static std::string get_first_added_preset(const std::map<std::string, std::strin
|
|||
return *diff.begin();
|
||||
}
|
||||
|
||||
bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater)
|
||||
bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater, bool& apply_keeped_changes)
|
||||
{
|
||||
wxString header, caption = _L("Configuration is editing from ConfigWizard");
|
||||
bool check_unsaved_preset_changes = page_welcome->reset_user_profile();
|
||||
if (check_unsaved_preset_changes)
|
||||
header = _L("All user presets will be deleted.");
|
||||
int act_btns = UnsavedChangesDialog::ActionButtons::KEEP;
|
||||
if (!check_unsaved_preset_changes)
|
||||
act_btns |= UnsavedChangesDialog::ActionButtons::SAVE;
|
||||
|
||||
const auto enabled_vendors = appconfig_new.vendors();
|
||||
|
||||
// Install bundles from resources if needed:
|
||||
|
@ -2500,6 +2509,9 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
|||
install_bundles.emplace_back(pair.first);
|
||||
}
|
||||
}
|
||||
if (!check_unsaved_preset_changes)
|
||||
if ((check_unsaved_preset_changes = install_bundles.size() > 0))
|
||||
header = _L_PLURAL("New vendor was installed and one of its printer will be activated", "New vendors were installed and one of theirs printer will be activated", install_bundles.size());
|
||||
|
||||
#ifdef __linux__
|
||||
// Desktop integration on Linux
|
||||
|
@ -2531,6 +2543,10 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
|||
if (snapshot && ! take_config_snapshot_cancel_on_error(*app_config, snapshot_reason, "", _u8L("Continue with applying configuration changes?")))
|
||||
return false;
|
||||
|
||||
if (check_unsaved_preset_changes &&
|
||||
!wxGetApp().check_and_keep_current_preset_changes(caption, header, act_btns, &apply_keeped_changes))
|
||||
return false;
|
||||
|
||||
if (install_bundles.size() > 0) {
|
||||
// Install bundles from resources.
|
||||
// Don't create snapshot - we've already done that above if applicable.
|
||||
|
@ -2586,17 +2602,52 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
|||
}
|
||||
}
|
||||
|
||||
// if unsaved changes was not cheched till this moment
|
||||
if (!check_unsaved_preset_changes) {
|
||||
if ((check_unsaved_preset_changes = !preferred_model.empty())) {
|
||||
header = _L("A new Printer was installed and it will be activated.");
|
||||
if (!wxGetApp().check_and_keep_current_preset_changes(caption, header, act_btns, &apply_keeped_changes))
|
||||
return false;
|
||||
}
|
||||
else if ((check_unsaved_preset_changes = enabled_vendors_old != enabled_vendors)) {
|
||||
header = _L("Some Printers were uninstalled.");
|
||||
if (!wxGetApp().check_and_keep_current_preset_changes(caption, header, act_btns, &apply_keeped_changes))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string first_added_filament, first_added_sla_material;
|
||||
auto apply_section = [this, app_config](const std::string& section_name, std::string& first_added_preset) {
|
||||
auto get_first_added_material_preset = [this, app_config](const std::string& section_name, std::string& first_added_preset) {
|
||||
if (appconfig_new.has_section(section_name)) {
|
||||
// get first of new added preset names
|
||||
const std::map<std::string, std::string>& old_presets = app_config->has_section(section_name) ? app_config->get_section(section_name) : std::map<std::string, std::string>();
|
||||
first_added_preset = get_first_added_preset(old_presets, appconfig_new.get_section(section_name));
|
||||
app_config->set_section(section_name, appconfig_new.get_section(section_name));
|
||||
}
|
||||
};
|
||||
apply_section(AppConfig::SECTION_FILAMENTS, first_added_filament);
|
||||
apply_section(AppConfig::SECTION_MATERIALS, first_added_sla_material);
|
||||
get_first_added_material_preset(AppConfig::SECTION_FILAMENTS, first_added_filament);
|
||||
get_first_added_material_preset(AppConfig::SECTION_MATERIALS, first_added_sla_material);
|
||||
|
||||
// if unsaved changes was not cheched till this moment
|
||||
if (!check_unsaved_preset_changes) {
|
||||
if ((check_unsaved_preset_changes = !first_added_filament.empty() || !first_added_sla_material.empty())) {
|
||||
header = format_wxstr(_L("A new %1% was installed and it will be activated."), !first_added_filament.empty() ? _L("Filament") : _L("SLA material"));
|
||||
if (!wxGetApp().check_and_keep_current_preset_changes(caption, header, act_btns, &apply_keeped_changes))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
bool is_filaments_changed = app_config->get_section(AppConfig::SECTION_FILAMENTS) != appconfig_new.get_section(AppConfig::SECTION_FILAMENTS);
|
||||
bool is_sla_materials_changed = app_config->get_section(AppConfig::SECTION_MATERIALS) != appconfig_new.get_section(AppConfig::SECTION_MATERIALS);
|
||||
if ((check_unsaved_preset_changes = is_filaments_changed || is_sla_materials_changed)) {
|
||||
header = format_wxstr(_L("Some %1% were uninstalled."), is_filaments_changed ? _L("Filaments") : _L("SLA materials"));
|
||||
if (!wxGetApp().check_and_keep_current_preset_changes(caption, header, act_btns, &apply_keeped_changes))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// apply materials in app_config
|
||||
for (const std::string& section_name : {AppConfig::SECTION_FILAMENTS, AppConfig::SECTION_MATERIALS})
|
||||
app_config->set_section(section_name, appconfig_new.get_section(section_name));
|
||||
|
||||
app_config->set_vendors(appconfig_new);
|
||||
|
||||
|
@ -2624,10 +2675,16 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
|||
|
||||
page_mode->serialize_mode(app_config);
|
||||
|
||||
preset_bundle->load_presets(*app_config, ForwardCompatibilitySubstitutionRule::EnableSilentDisableSystem,
|
||||
{preferred_model, preferred_variant, first_added_filament, first_added_sla_material});
|
||||
if (check_unsaved_preset_changes)
|
||||
preset_bundle->load_presets(*app_config, ForwardCompatibilitySubstitutionRule::EnableSilentDisableSystem,
|
||||
{preferred_model, preferred_variant, first_added_filament, first_added_sla_material});
|
||||
|
||||
if (page_custom->custom_wanted()) {
|
||||
// if unsaved changes was not cheched till this moment
|
||||
if (!check_unsaved_preset_changes &&
|
||||
!wxGetApp().check_and_keep_current_preset_changes(caption, _L("Custom printer was installed and it will be activated."), act_btns, &apply_keeped_changes))
|
||||
return false;
|
||||
|
||||
page_firmware->apply_custom_config(*custom_config);
|
||||
page_bed->apply_custom_config(*custom_config);
|
||||
page_diams->apply_custom_config(*custom_config);
|
||||
|
@ -2851,8 +2908,13 @@ bool ConfigWizard::run(RunReason reason, StartPage start_page)
|
|||
p->set_start_page(start_page);
|
||||
|
||||
if (ShowModal() == wxID_OK) {
|
||||
if (! p->apply_config(app.app_config, app.preset_bundle, app.preset_updater))
|
||||
bool apply_keeped_changes = false;
|
||||
if (! p->apply_config(app.app_config, app.preset_bundle, app.preset_updater, apply_keeped_changes))
|
||||
return false;
|
||||
|
||||
if (apply_keeped_changes)
|
||||
app.apply_keeped_preset_modifications();
|
||||
|
||||
app.app_config->set_legacy_datadir(false);
|
||||
app.update_mode();
|
||||
app.obj_manipul()->update_ui_from_settings();
|
||||
|
|
|
@ -611,7 +611,7 @@ struct ConfigWizard::priv
|
|||
|
||||
bool on_bnt_finish();
|
||||
bool check_and_install_missing_materials(Technology technology, const std::string &only_for_model_id = std::string());
|
||||
bool apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater);
|
||||
bool apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater, bool& apply_keeped_changes);
|
||||
// #ys_FIXME_alise
|
||||
void update_presets_in_config(const std::string& section, const std::string& alias_key, bool add);
|
||||
#ifdef __linux__
|
||||
|
|
|
@ -323,15 +323,19 @@ wxWindow* BitmapChoiceRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelR
|
|||
|
||||
c_editor->SetSelection(atoi(data.GetText().c_str()));
|
||||
|
||||
// to avoid event propagation to other sidebar items
|
||||
c_editor->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& evt) {
|
||||
evt.StopPropagation();
|
||||
|
||||
#ifdef __linux__
|
||||
// FinishEditing grabs new selection and triggers config update. We better call
|
||||
// it explicitly, automatic update on KILL_FOCUS didn't work on Linux.
|
||||
this->FinishEditing();
|
||||
#endif
|
||||
c_editor->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& evt) {
|
||||
// to avoid event propagation to other sidebar items
|
||||
evt.StopPropagation();
|
||||
// FinishEditing grabs new selection and triggers config update. We better call
|
||||
// it explicitly, automatic update on KILL_FOCUS didn't work on Linux.
|
||||
this->FinishEditing();
|
||||
});
|
||||
#else
|
||||
// to avoid event propagation to other sidebar items
|
||||
c_editor->Bind(wxEVT_COMBOBOX, [](wxCommandEvent& evt) { evt.StopPropagation(); });
|
||||
#endif
|
||||
|
||||
return c_editor;
|
||||
}
|
||||
|
|
|
@ -694,7 +694,6 @@ GUI_App::GUI_App(EAppMode mode)
|
|||
, m_app_mode(mode)
|
||||
, m_em_unit(10)
|
||||
, m_imgui(new ImGuiWrapper())
|
||||
, m_wizard(nullptr)
|
||||
, m_removable_drive_manager(std::make_unique<RemovableDriveManager>())
|
||||
, m_other_instance_message_handler(std::make_unique<OtherInstanceMessageHandler>())
|
||||
{
|
||||
|
@ -1333,8 +1332,6 @@ void GUI_App::recreate_GUI(const wxString& msg_name)
|
|||
|
||||
dlg.Update(30, _L("Recreating") + dots);
|
||||
old_main_frame->Destroy();
|
||||
// For this moment ConfigWizard is deleted, invalidate it.
|
||||
m_wizard = nullptr;
|
||||
|
||||
dlg.Update(80, _L("Loading of current presets") + dots);
|
||||
m_printhost_job_queue.reset(new PrintHostJobQueue(mainframe->printhost_queue_dlg()));
|
||||
|
@ -1409,8 +1406,6 @@ void GUI_App::update_ui_from_settings()
|
|||
m_force_colors_update = false;
|
||||
mainframe->force_color_changed();
|
||||
mainframe->diff_dialog.force_color_changed();
|
||||
if (m_wizard)
|
||||
m_wizard->force_color_changed();
|
||||
}
|
||||
#endif
|
||||
mainframe->update_ui_from_settings();
|
||||
|
@ -1871,8 +1866,9 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
|
|||
#endif
|
||||
case ConfigMenuTakeSnapshot:
|
||||
// Take a configuration snapshot.
|
||||
if (check_and_save_current_preset_changes()) {
|
||||
wxTextEntryDialog dlg(nullptr, _L("Taking configuration snapshot"), _L("Snapshot name"));
|
||||
if (wxString action_name = _L("Taking a configuration snapshot");
|
||||
check_and_save_current_preset_changes(action_name, _L("Some presets are modified and the unsaved changes will not be captured by the configuration snapshot."), false, true)) {
|
||||
wxTextEntryDialog dlg(nullptr, action_name, _L("Snapshot name"));
|
||||
UpdateDlgDarkUI(&dlg);
|
||||
|
||||
// set current normal font for dialog children,
|
||||
|
@ -1888,7 +1884,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
|
|||
}
|
||||
break;
|
||||
case ConfigMenuSnapshots:
|
||||
if (check_and_save_current_preset_changes()) {
|
||||
if (check_and_save_current_preset_changes(_L("Loading a configuration snapshot"), "", false)) {
|
||||
std::string on_snapshot;
|
||||
if (Config::SnapshotDB::singleton().is_on_snapshot(*app_config))
|
||||
on_snapshot = app_config->get("on_snapshot");
|
||||
|
@ -1910,9 +1906,6 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
|
|||
|
||||
// Load the currently selected preset into the GUI, update the preset selection box.
|
||||
load_current_presets();
|
||||
|
||||
// update config wizard in respect to the new config
|
||||
update_wizard_from_config();
|
||||
} catch (std::exception &ex) {
|
||||
GUI::show_error(nullptr, _L("Failed to activate configuration snapshot.") + "\n" + into_u8(ex.what()));
|
||||
}
|
||||
|
@ -2081,13 +2074,28 @@ std::vector<std::pair<unsigned int, std::string>> GUI_App::get_selected_presets(
|
|||
return ret;
|
||||
}
|
||||
|
||||
// This is called when closing the application, when loading a config file or when starting the config wizard
|
||||
// to notify the user whether he is aware that some preset changes will be lost.
|
||||
bool GUI_App::check_and_save_current_preset_changes(const wxString& header, const wxString& caption)
|
||||
// To notify the user whether he is aware that some preset changes will be lost,
|
||||
// UnsavedChangesDialog: "Discard / Save / Cancel"
|
||||
// This is called when:
|
||||
// - Close Application & Current project isn't saved
|
||||
// - Load Project & Current project isn't saved
|
||||
// - Undo / Redo with change of print technologie
|
||||
// - Loading snapshot
|
||||
// - Loading config_file/bundle
|
||||
// UnsavedChangesDialog: "Don't save / Save / Cancel"
|
||||
// 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*/)
|
||||
{
|
||||
if (/*this->plater()->model().objects.empty() && */has_current_preset_changes()) {
|
||||
UnsavedChangesDialog dlg(header, caption);
|
||||
if (wxGetApp().app_config->get("default_action_on_close_application") == "none" && dlg.ShowModal() == wxID_CANCEL)
|
||||
if (has_current_preset_changes()) {
|
||||
const std::string app_config_key = remember_choice ? "default_action_on_close_application" : "";
|
||||
int act_buttons = UnsavedChangesDialog::ActionButtons::SAVE;
|
||||
if (dont_save_insted_of_discard)
|
||||
act_buttons |= UnsavedChangesDialog::ActionButtons::DONT_SAVE;
|
||||
UnsavedChangesDialog dlg(caption, header, app_config_key, act_buttons);
|
||||
std::string act = app_config_key.empty() ? "none" : wxGetApp().app_config->get(app_config_key);
|
||||
if (act == "none" && dlg.ShowModal() == wxID_CANCEL)
|
||||
return false;
|
||||
|
||||
if (dlg.save_preset()) // save selected changes
|
||||
|
@ -2095,18 +2103,122 @@ bool GUI_App::check_and_save_current_preset_changes(const wxString& header, cons
|
|||
for (const std::pair<std::string, Preset::Type>& nt : dlg.get_names_and_types())
|
||||
preset_bundle->save_changes_for_preset(nt.first, nt.second, dlg.get_unselected_options(nt.second));
|
||||
|
||||
load_current_presets(false);
|
||||
|
||||
// if we saved changes to the new presets, we should to
|
||||
// synchronize config.ini with the current selections.
|
||||
preset_bundle->export_selections(*app_config);
|
||||
|
||||
wxMessageBox(_L_PLURAL("The preset modifications are successfully saved",
|
||||
"The presets modifications are successfully saved", dlg.get_names_and_types().size()));
|
||||
MessageDialog(nullptr, _L_PLURAL("The preset modifications are successfully saved",
|
||||
"The presets modifications are successfully saved", dlg.get_names_and_types().size())).ShowModal();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GUI_App::apply_keeped_preset_modifications()
|
||||
{
|
||||
PrinterTechnology printer_technology = preset_bundle->printers.get_edited_preset().printer_technology();
|
||||
for (Tab* tab : tabs_list) {
|
||||
if (tab->supports_printer_technology(printer_technology))
|
||||
tab->apply_config_from_cache();
|
||||
}
|
||||
load_current_presets(false);
|
||||
}
|
||||
|
||||
// This is called when creating new project or load another project
|
||||
// OR close ConfigWizard
|
||||
// to ask the user what should we do with unsaved changes for presets.
|
||||
// New Project => Current project is saved => UnsavedChangesDialog: "Keep / Discard / Cancel"
|
||||
// => 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*/)
|
||||
{
|
||||
if (has_current_preset_changes()) {
|
||||
bool is_called_from_configwizard = postponed_apply_of_keeped_changes != nullptr;
|
||||
|
||||
const std::string app_config_key = is_called_from_configwizard ? "" : "default_action_on_new_project";
|
||||
UnsavedChangesDialog dlg(caption, header, app_config_key, action_buttons);
|
||||
std::string act = app_config_key.empty() ? "none" : wxGetApp().app_config->get(app_config_key);
|
||||
if (act == "none" && dlg.ShowModal() == wxID_CANCEL)
|
||||
return false;
|
||||
|
||||
auto reset_modifications = [this, is_called_from_configwizard]() {
|
||||
if (is_called_from_configwizard)
|
||||
return; // no need to discared changes. It will be done fromConfigWizard closing
|
||||
|
||||
PrinterTechnology printer_technology = preset_bundle->printers.get_edited_preset().printer_technology();
|
||||
for (const Tab* const tab : tabs_list) {
|
||||
if (tab->supports_printer_technology(printer_technology) && tab->current_preset_is_dirty())
|
||||
tab->m_presets->discard_current_changes();
|
||||
}
|
||||
load_current_presets(false);
|
||||
};
|
||||
|
||||
if (dlg.discard())
|
||||
reset_modifications();
|
||||
else // save selected changes
|
||||
{
|
||||
const auto& preset_names_and_types = dlg.get_names_and_types();
|
||||
if (dlg.save_preset()) {
|
||||
for (const std::pair<std::string, Preset::Type>& nt : preset_names_and_types)
|
||||
preset_bundle->save_changes_for_preset(nt.first, nt.second, dlg.get_unselected_options(nt.second));
|
||||
|
||||
// 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("The preset modifications are successfully saved",
|
||||
"The presets modifications are successfully saved", preset_names_and_types.size());
|
||||
if (!is_called_from_configwizard)
|
||||
text += "\n\n" + _L("For new project all modifications will be reseted");
|
||||
|
||||
MessageDialog(nullptr, text).ShowModal();
|
||||
reset_modifications();
|
||||
}
|
||||
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 std::pair<std::string, Preset::Type>& nt : preset_names_and_types) {
|
||||
Preset::Type type = nt.second;
|
||||
Tab* tab = get_tab(type);
|
||||
std::vector<std::string> 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<TabPrinter*>(tab)->cache_extruder_cnt();
|
||||
}
|
||||
}
|
||||
tab->cache_config_diff(selected_options);
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GUI_App::can_load_project()
|
||||
{
|
||||
int saved_project = plater()->save_project_if_dirty(_L("Loading a new project while the current project is modified."));
|
||||
if (saved_project == wxID_CANCEL ||
|
||||
(plater()->is_project_dirty() && saved_project == wxID_NO &&
|
||||
!check_and_save_current_preset_changes(_L("Project is loading"), _L("Loading a new project while some presets are modified."))))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GUI_App::check_print_host_queue()
|
||||
{
|
||||
wxString dirty;
|
||||
|
@ -2164,17 +2276,6 @@ void GUI_App::load_current_presets(bool check_printer_presets_ /*= true*/)
|
|||
}
|
||||
}
|
||||
|
||||
void GUI_App::update_wizard_from_config()
|
||||
{
|
||||
if (!m_wizard)
|
||||
return;
|
||||
// If ConfigWizard was created before changing of the configuration,
|
||||
// we have to destroy it to have possibility to create it again in respect to the new config's parameters
|
||||
m_wizard->Reparent(nullptr);
|
||||
m_wizard->Destroy();
|
||||
m_wizard = nullptr;
|
||||
}
|
||||
|
||||
bool GUI_App::OnExceptionInMainLoop()
|
||||
{
|
||||
generic_exception_handle();
|
||||
|
@ -2336,19 +2437,12 @@ bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage
|
|||
wxCHECK_MSG(mainframe != nullptr, false, "Internal error: Main frame not created / null");
|
||||
|
||||
if (reason == ConfigWizard::RR_USER) {
|
||||
wxString header = _L("Updates to Configuration Wizard may cause an another preset selection and lost of preset modification as a result.\n"
|
||||
"So, check unsaved changes and save them if necessary.") + "\n";
|
||||
if (!check_and_save_current_preset_changes(header, _L("ConfigWizard is opening")) ||
|
||||
preset_updater->config_update(app_config->orig_version(), PresetUpdater::UpdateParams::FORCED_BEFORE_WIZARD) == PresetUpdater::R_ALL_CANCELED)
|
||||
if (preset_updater->config_update(app_config->orig_version(), PresetUpdater::UpdateParams::FORCED_BEFORE_WIZARD) == PresetUpdater::R_ALL_CANCELED)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! m_wizard) {
|
||||
wxBusyCursor wait;
|
||||
m_wizard = new ConfigWizard(mainframe);
|
||||
}
|
||||
|
||||
const bool res = m_wizard->run(reason, start_page);
|
||||
auto wizard = new ConfigWizard(mainframe);
|
||||
const bool res = wizard->run(reason, start_page);
|
||||
|
||||
if (res) {
|
||||
load_current_presets();
|
||||
|
|
|
@ -150,7 +150,6 @@ private:
|
|||
|
||||
std::unique_ptr<ImGuiWrapper> m_imgui;
|
||||
std::unique_ptr<PrintHostJobQueue> m_printhost_job_queue;
|
||||
ConfigWizard* m_wizard; // Managed by wxWindow tree
|
||||
std::unique_ptr <OtherInstanceMessageHandler> m_other_instance_message_handler;
|
||||
std::unique_ptr <wxSingleInstanceChecker> m_single_instance_checker;
|
||||
std::string m_instance_hash_string;
|
||||
|
@ -246,11 +245,13 @@ public:
|
|||
bool has_current_preset_changes() const;
|
||||
void update_saved_preset_from_current_preset();
|
||||
std::vector<std::pair<unsigned int, std::string>> get_selected_presets() const;
|
||||
bool check_and_save_current_preset_changes(const wxString& header = wxString(), const wxString& caption = wxString());
|
||||
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);
|
||||
bool can_load_project();
|
||||
bool check_print_host_queue();
|
||||
bool checked_tab(Tab* tab);
|
||||
void load_current_presets(bool check_printer_presets = true);
|
||||
void update_wizard_from_config();
|
||||
|
||||
wxString current_language_code() const { return m_wxLocale->GetCanonicalName(); }
|
||||
// Translate the language code to a code, for which Prusa Research maintains translations. Defaults to "en_US".
|
||||
|
|
|
@ -4071,7 +4071,7 @@ void ObjectList::fix_through_netfabb()
|
|||
msg += ": " + from_u8(model_name) + "\n";
|
||||
else {
|
||||
msg += ":\n";
|
||||
for (size_t i = 0; i < model_names.size(); ++i)
|
||||
for (int i = 0; i < int(model_names.size()); ++i)
|
||||
msg += (i == model_idx ? " > " : " ") + from_u8(model_names[i]) + "\n";
|
||||
msg += "\n";
|
||||
}
|
||||
|
|
|
@ -222,13 +222,14 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
|
|||
}
|
||||
|
||||
if (m_plater != nullptr) {
|
||||
int saved_project = m_plater->save_project_if_dirty();
|
||||
int saved_project = m_plater->save_project_if_dirty(_L("Closing PrusaSlicer. Current project is modified."));
|
||||
if (saved_project == wxID_CANCEL) {
|
||||
event.Veto();
|
||||
return;
|
||||
}
|
||||
// check unsaved changes only if project wasn't saved
|
||||
else if (saved_project == wxID_NO && event.CanVeto() && !wxGetApp().check_and_save_current_preset_changes()) {
|
||||
else if (saved_project == wxID_NO && event.CanVeto() &&
|
||||
!wxGetApp().check_and_save_current_preset_changes(_L("PrusaSlicer is closing"), _L("Closing PrusaSlicer while some presets are modified."))) {
|
||||
event.Veto();
|
||||
return;
|
||||
}
|
||||
|
@ -820,7 +821,10 @@ bool MainFrame::is_active_and_shown_tab(Tab* tab)
|
|||
|
||||
bool MainFrame::can_start_new_project() const
|
||||
{
|
||||
return (m_plater != nullptr) && (!m_plater->get_project_filename(".3mf").IsEmpty() || GetTitle().StartsWith('*') || !m_plater->model().objects.empty());
|
||||
return m_plater && (!m_plater->get_project_filename(".3mf").IsEmpty() ||
|
||||
GetTitle().StartsWith('*')||
|
||||
wxGetApp().has_current_preset_changes() ||
|
||||
!m_plater->model().objects.empty() );
|
||||
}
|
||||
|
||||
bool MainFrame::can_save() const
|
||||
|
@ -852,13 +856,14 @@ void MainFrame::save_project()
|
|||
save_project_as(m_plater->get_project_filename(".3mf"));
|
||||
}
|
||||
|
||||
void MainFrame::save_project_as(const wxString& filename)
|
||||
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();
|
||||
m_plater->reset_project_dirty_after_save();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool MainFrame::can_export_model() const
|
||||
|
@ -1151,8 +1156,10 @@ void MainFrame::init_menubar_as_editor()
|
|||
Bind(wxEVT_MENU, [this](wxCommandEvent& evt) {
|
||||
size_t file_id = evt.GetId() - wxID_FILE1;
|
||||
wxString filename = m_recent_projects.GetHistoryFile(file_id);
|
||||
if (wxFileExists(filename))
|
||||
m_plater->load_project(filename);
|
||||
if (wxFileExists(filename)) {
|
||||
if (wxGetApp().can_load_project())
|
||||
m_plater->load_project(filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
//wxMessageDialog msg(this, _L("The selected project is no longer available.\nDo you want to remove it from the recent projects list?"), _L("Error"), wxYES_NO | wxYES_DEFAULT);
|
||||
|
@ -1772,7 +1779,7 @@ void MainFrame::export_config()
|
|||
// Load a config file containing a Print, Filament & Printer preset.
|
||||
void MainFrame::load_config_file()
|
||||
{
|
||||
if (!wxGetApp().check_and_save_current_preset_changes())
|
||||
if (!wxGetApp().check_and_save_current_preset_changes(_L("Loading of a configuration file"), "", false))
|
||||
return;
|
||||
wxFileDialog dlg(this, _L("Select configuration to load:"),
|
||||
!m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(),
|
||||
|
@ -1803,7 +1810,8 @@ bool MainFrame::load_config_file(const std::string &path)
|
|||
|
||||
void MainFrame::export_configbundle(bool export_physical_printers /*= false*/)
|
||||
{
|
||||
if (!wxGetApp().check_and_save_current_preset_changes())
|
||||
if (!wxGetApp().check_and_save_current_preset_changes(_L("Exporting configuration bundle"),
|
||||
_L("Some presets are modified and the unsaved changes will not be exported into configuration bundle."), false, true))
|
||||
return;
|
||||
// validate current configuration in case it's dirty
|
||||
auto err = wxGetApp().preset_bundle->full_config().validate();
|
||||
|
@ -1835,7 +1843,7 @@ void MainFrame::export_configbundle(bool export_physical_printers /*= false*/)
|
|||
// but that behavior was not documented and likely buggy.
|
||||
void MainFrame::load_configbundle(wxString file/* = wxEmptyString, const bool reset_user_profile*/)
|
||||
{
|
||||
if (!wxGetApp().check_and_save_current_preset_changes())
|
||||
if (!wxGetApp().check_and_save_current_preset_changes(_L("Loading of a configuration bundle"), "", false))
|
||||
return;
|
||||
if (file.IsEmpty()) {
|
||||
wxFileDialog dlg(this, _L("Select configuration to load:"),
|
||||
|
|
|
@ -190,7 +190,7 @@ public:
|
|||
bool can_save() const;
|
||||
bool can_save_as() const;
|
||||
void save_project();
|
||||
void save_project_as(const wxString& filename = wxString());
|
||||
bool save_project_as(const wxString& filename = wxString());
|
||||
|
||||
void add_to_recent_projects(const wxString& filename);
|
||||
void technology_changed();
|
||||
|
|
|
@ -1575,16 +1575,22 @@ struct Plater::priv
|
|||
|
||||
bool is_project_dirty() const { return dirty_state.is_dirty(); }
|
||||
void update_project_dirty_from_presets() { dirty_state.update_from_presets(); }
|
||||
int save_project_if_dirty() {
|
||||
int save_project_if_dirty(const wxString& reason) {
|
||||
int res = wxID_NO;
|
||||
if (dirty_state.is_dirty()) {
|
||||
MainFrame* mainframe = wxGetApp().mainframe;
|
||||
if (mainframe->can_save_as()) {
|
||||
//wxMessageDialog dlg(mainframe, _L("Do you want to save the changes to the current project ?"), wxString(SLIC3R_APP_NAME), wxYES_NO | wxCANCEL);
|
||||
MessageDialog dlg(mainframe, _L("Do you want to save the changes to the current project ?"), wxString(SLIC3R_APP_NAME), wxYES_NO | wxCANCEL);
|
||||
res = dlg.ShowModal();
|
||||
wxString suggested_project_name;
|
||||
wxString project_name = suggested_project_name = get_project_filename(".3mf");
|
||||
if (suggested_project_name.IsEmpty()) {
|
||||
fs::path output_file = get_export_file_path(FT_3MF);
|
||||
suggested_project_name = output_file.empty() ? _L("Untitled") : from_u8(output_file.stem().string());
|
||||
}
|
||||
res = MessageDialog(mainframe, reason + "\n" + format_wxstr(_L("Do you want to save the changes to \"%1%\"?"), suggested_project_name),
|
||||
wxString(SLIC3R_APP_NAME), wxYES_NO | wxCANCEL).ShowModal();
|
||||
if (res == wxID_YES)
|
||||
mainframe->save_project_as(wxGetApp().plater()->get_project_filename());
|
||||
if (!mainframe->save_project_as(project_name))
|
||||
res = wxID_CANCEL;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
@ -1644,6 +1650,7 @@ struct Plater::priv
|
|||
std::vector<size_t> load_files(const std::vector<fs::path>& input_files, bool load_model, bool load_config, bool used_inches = false);
|
||||
std::vector<size_t> load_model_objects(const ModelObjectPtrs& model_objects, bool allow_negative_z = false);
|
||||
|
||||
fs::path get_export_file_path(GUI::FileType file_type);
|
||||
wxString get_export_file(GUI::FileType file_type);
|
||||
|
||||
const Selection& get_selection() const;
|
||||
|
@ -2599,22 +2606,8 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs& mode
|
|||
return obj_idxs;
|
||||
}
|
||||
|
||||
wxString Plater::priv::get_export_file(GUI::FileType file_type)
|
||||
fs::path Plater::priv::get_export_file_path(GUI::FileType file_type)
|
||||
{
|
||||
wxString wildcard;
|
||||
switch (file_type) {
|
||||
case FT_STL:
|
||||
case FT_AMF:
|
||||
case FT_3MF:
|
||||
case FT_GCODE:
|
||||
case FT_OBJ:
|
||||
wildcard = file_wildcards(file_type);
|
||||
break;
|
||||
default:
|
||||
wildcard = file_wildcards(FT_MODEL);
|
||||
break;
|
||||
}
|
||||
|
||||
// Update printbility state of each of the ModelInstances.
|
||||
this->update_print_volume_state();
|
||||
|
||||
|
@ -2639,7 +2632,31 @@ wxString Plater::priv::get_export_file(GUI::FileType file_type)
|
|||
if (output_file.empty() && !model.objects.empty())
|
||||
// Find the file name of the first object.
|
||||
output_file = this->model.objects[0]->get_export_filename();
|
||||
|
||||
if (output_file.empty())
|
||||
// Use _L("Untitled") name
|
||||
output_file = into_path(_L("Untitled"));
|
||||
}
|
||||
return output_file;
|
||||
}
|
||||
|
||||
wxString Plater::priv::get_export_file(GUI::FileType file_type)
|
||||
{
|
||||
wxString wildcard;
|
||||
switch (file_type) {
|
||||
case FT_STL:
|
||||
case FT_AMF:
|
||||
case FT_3MF:
|
||||
case FT_GCODE:
|
||||
case FT_OBJ:
|
||||
wildcard = file_wildcards(file_type);
|
||||
break;
|
||||
default:
|
||||
wildcard = file_wildcards(FT_MODEL);
|
||||
break;
|
||||
}
|
||||
|
||||
fs::path output_file = get_export_file_path(file_type);
|
||||
|
||||
wxString dlg_title;
|
||||
switch (file_type) {
|
||||
|
@ -4714,8 +4731,10 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator
|
|||
if (printer_technology_changed) {
|
||||
// Switching the printer technology when jumping forwards / backwards in time. Switch to the last active printer profile of the other type.
|
||||
std::string s_pt = (it_snapshot->snapshot_data.printer_technology == ptFFF) ? "FFF" : "SLA";
|
||||
if (!wxGetApp().check_and_save_current_preset_changes(format_wxstr(_L(
|
||||
"%1% printer was active at the time the target Undo / Redo snapshot was taken. Switching to %1% printer requires reloading of %1% presets."), s_pt)))
|
||||
if (!wxGetApp().check_and_save_current_preset_changes(_L("Undo / Redo is processing"),
|
||||
// format_wxstr(_L("%1% printer was active at the time the target Undo / Redo snapshot was taken. Switching to %1% printer requires reloading of %1% presets."), s_pt)))
|
||||
format_wxstr(_L("Switching the printer technology from %1% to %2%.\n"
|
||||
"Some %1% presets were modified, which will be lost after switching the printer technology."), s_pt =="FFF" ? "SLA" : "FFF", s_pt), false))
|
||||
// Don't switch the profiles.
|
||||
return;
|
||||
}
|
||||
|
@ -4893,7 +4912,7 @@ Plater::Plater(wxWindow *parent, MainFrame *main_frame)
|
|||
|
||||
bool Plater::is_project_dirty() const { return p->is_project_dirty(); }
|
||||
void Plater::update_project_dirty_from_presets() { p->update_project_dirty_from_presets(); }
|
||||
int Plater::save_project_if_dirty() { return p->save_project_if_dirty(); }
|
||||
int Plater::save_project_if_dirty(const wxString& reason) { return p->save_project_if_dirty(reason); }
|
||||
void Plater::reset_project_dirty_after_save() { p->reset_project_dirty_after_save(); }
|
||||
void Plater::reset_project_dirty_initial_presets() { p->reset_project_dirty_initial_presets(); }
|
||||
#if ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
||||
|
@ -4910,8 +4929,20 @@ SLAPrint& Plater::sla_print() { return p->sla_print; }
|
|||
|
||||
void Plater::new_project()
|
||||
{
|
||||
if (p->save_project_if_dirty() == wxID_CANCEL)
|
||||
if (int saved_project = p->save_project_if_dirty(_L("Creating a new project while the current project is modified.")); saved_project == wxID_CANCEL)
|
||||
return;
|
||||
else {
|
||||
wxString header = _L("Creating a new project while some presets are modified.") + "\n" +
|
||||
(saved_project == wxID_YES ? _L("You can keep presets modifications to the new project or discard them") :
|
||||
_L("You can keep presets modifications to the new project, discard them or save changes as new presets.\n"
|
||||
"Note, if changes will be saved than new project wouldn't keep them"));
|
||||
using ab = UnsavedChangesDialog::ActionButtons;
|
||||
int act_buttons = ab::KEEP;
|
||||
if (saved_project == wxID_NO)
|
||||
act_buttons |= ab::SAVE;
|
||||
if (!wxGetApp().check_and_keep_current_preset_changes(_L("New Project is creating"), header, act_buttons))
|
||||
return;
|
||||
}
|
||||
|
||||
p->select_view_3D("3D");
|
||||
take_snapshot(_L("New Project"));
|
||||
|
@ -4923,7 +4954,7 @@ void Plater::new_project()
|
|||
|
||||
void Plater::load_project()
|
||||
{
|
||||
if (p->save_project_if_dirty() == wxID_CANCEL)
|
||||
if (!wxGetApp().can_load_project())
|
||||
return;
|
||||
|
||||
// Ask user for a project file name.
|
||||
|
@ -5219,7 +5250,8 @@ bool Plater::load_files(const wxArrayString& filenames)
|
|||
|
||||
switch (load_type) {
|
||||
case LoadType::OpenProject: {
|
||||
load_project(from_path(*it));
|
||||
if (wxGetApp().can_load_project())
|
||||
load_project(from_path(*it));
|
||||
break;
|
||||
}
|
||||
case LoadType::LoadGeometry: {
|
||||
|
|
|
@ -140,7 +140,7 @@ public:
|
|||
|
||||
bool is_project_dirty() const;
|
||||
void update_project_dirty_from_presets();
|
||||
int save_project_if_dirty();
|
||||
int save_project_if_dirty(const wxString& reason);
|
||||
void reset_project_dirty_after_save();
|
||||
void reset_project_dirty_initial_presets();
|
||||
#if ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
||||
|
|
|
@ -73,7 +73,7 @@ void PreferencesDialog::build(size_t selected_tab)
|
|||
// Add "General" tab
|
||||
m_optgroup_general = create_options_tab(_L("General"), tabs);
|
||||
m_optgroup_general->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
|
||||
if (opt_key == "default_action_on_close_application" || opt_key == "default_action_on_select_preset")
|
||||
if (opt_key == "default_action_on_close_application" || opt_key == "default_action_on_select_preset" || opt_key == "default_action_on_new_project")
|
||||
m_values[opt_key] = boost::any_cast<bool>(value) ? "none" : "discard";
|
||||
else
|
||||
m_values[opt_key] = boost::any_cast<bool>(value) ? "1" : "0";
|
||||
|
@ -186,19 +186,28 @@ void PreferencesDialog::build(size_t selected_tab)
|
|||
option = Option(def, "single_instance");
|
||||
m_optgroup_general->append_single_option_line(option);
|
||||
|
||||
def.label = L("Ask for unsaved changes when closing application");
|
||||
def.label = L("Ask for unsaved changes when closing application or loading new project");
|
||||
def.type = coBool;
|
||||
def.tooltip = L("When closing the application, always ask for unsaved changes");
|
||||
def.tooltip = L("Always ask for unsaved changes, when: \n"
|
||||
"- Closing PrusaSlicer while some presets are modified,\n"
|
||||
"- Loading a new project while some presets are modified");
|
||||
def.set_default_value(new ConfigOptionBool{ app_config->get("default_action_on_close_application") == "none" });
|
||||
option = Option(def, "default_action_on_close_application");
|
||||
m_optgroup_general->append_single_option_line(option);
|
||||
|
||||
def.label = L("Ask for unsaved changes when selecting new preset");
|
||||
def.type = coBool;
|
||||
def.tooltip = L("Always ask for unsaved changes when selecting new preset");
|
||||
def.tooltip = L("Always ask for unsaved changes when selecting new preset or resetting a preset");
|
||||
def.set_default_value(new ConfigOptionBool{ app_config->get("default_action_on_select_preset") == "none" });
|
||||
option = Option(def, "default_action_on_select_preset");
|
||||
m_optgroup_general->append_single_option_line(option);
|
||||
|
||||
def.label = L("Ask for unsaved changes when creating new project");
|
||||
def.type = coBool;
|
||||
def.tooltip = L("Always ask for unsaved changes when creating new project");
|
||||
def.set_default_value(new ConfigOptionBool{ app_config->get("default_action_on_new_project") == "none" });
|
||||
option = Option(def, "default_action_on_new_project");
|
||||
m_optgroup_general->append_single_option_line(option);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
else {
|
||||
|
|
|
@ -1216,12 +1216,20 @@ void Tab::cache_config_diff(const std::vector<std::string>& selected_options)
|
|||
|
||||
void Tab::apply_config_from_cache()
|
||||
{
|
||||
bool was_applied = false;
|
||||
// check and apply extruders count for printer preset
|
||||
if (m_type == Preset::TYPE_PRINTER)
|
||||
was_applied = static_cast<TabPrinter*>(this)->apply_extruder_cnt_from_cache();
|
||||
|
||||
if (!m_cache_config.empty()) {
|
||||
m_presets->get_edited_preset().config.apply(m_cache_config);
|
||||
m_cache_config.clear();
|
||||
|
||||
update_dirty();
|
||||
was_applied = true;
|
||||
}
|
||||
|
||||
if (was_applied)
|
||||
update_dirty();
|
||||
}
|
||||
|
||||
|
||||
|
@ -3322,10 +3330,6 @@ 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 and apply extruders count for printer preset
|
||||
if (m_type == Preset::TYPE_PRINTER)
|
||||
static_cast<TabPrinter*>(this)->apply_extruder_cnt_from_cache();
|
||||
|
||||
// check if there is something in the cache to move to the new selected preset
|
||||
apply_config_from_cache();
|
||||
|
||||
|
@ -3862,15 +3866,17 @@ void TabPrinter::cache_extruder_cnt()
|
|||
m_cache_extruder_count = m_extruders_count;
|
||||
}
|
||||
|
||||
void TabPrinter::apply_extruder_cnt_from_cache()
|
||||
bool TabPrinter::apply_extruder_cnt_from_cache()
|
||||
{
|
||||
if (m_presets->get_edited_preset().printer_technology() == ptSLA)
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (m_cache_extruder_count > 0) {
|
||||
m_presets->get_edited_preset().set_num_extruders(m_cache_extruder_count);
|
||||
m_cache_extruder_count = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Tab::validate_custom_gcodes()
|
||||
|
|
|
@ -469,7 +469,7 @@ public:
|
|||
|
||||
wxSizer* create_bed_shape_widget(wxWindow* parent);
|
||||
void cache_extruder_cnt();
|
||||
void apply_extruder_cnt_from_cache();
|
||||
bool apply_extruder_cnt_from_cache();
|
||||
};
|
||||
|
||||
class TabSLAMaterial : public Tab
|
||||
|
|
|
@ -727,14 +727,21 @@ void DiffViewCtrl::item_value_changed(wxDataViewEvent& event)
|
|||
m_empty_selection = selected_options().empty();
|
||||
}
|
||||
|
||||
std::vector<std::string> DiffViewCtrl::unselected_options(Preset::Type type)
|
||||
bool DiffViewCtrl::has_unselected_options()
|
||||
{
|
||||
for (auto item : m_items_map)
|
||||
if (!model->IsEnabledItem(item.first))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> DiffViewCtrl::options(Preset::Type type, bool selected)
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
|
||||
for (auto item : m_items_map) {
|
||||
if (item.second.opt_key == "extruders_count")
|
||||
continue;
|
||||
if (item.second.type == type && !model->IsEnabledItem(item.first))
|
||||
if (item.second.type == type && model->IsEnabledItem(item.first) == selected)
|
||||
ret.emplace_back(get_pure_opt_key(item.second.opt_key));
|
||||
}
|
||||
|
||||
|
@ -757,20 +764,24 @@ std::vector<std::string> DiffViewCtrl::selected_options()
|
|||
// UnsavedChangesDialog
|
||||
//------------------------------------------
|
||||
|
||||
UnsavedChangesDialog::UnsavedChangesDialog(const wxString& header, const wxString& caption/* = wxString()*/)
|
||||
: DPIDialog(static_cast<wxWindow*>(wxGetApp().mainframe), wxID_ANY, (caption.IsEmpty() ? _L("PrusaSlicer is closing") : caption) + ": " + _L("Unsaved Changes"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
{
|
||||
m_app_config_key = "default_action_on_close_application";
|
||||
static std::string none{"none"};
|
||||
|
||||
UnsavedChangesDialog::UnsavedChangesDialog(const wxString& caption, const wxString& header,
|
||||
const std::string& app_config_key, int act_buttons)
|
||||
: DPIDialog(static_cast<wxWindow*>(wxGetApp().mainframe), wxID_ANY, caption + ": " + _L("Unsaved Changes"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
|
||||
m_app_config_key(app_config_key),
|
||||
m_buttons(act_buttons)
|
||||
{
|
||||
build(Preset::TYPE_INVALID, nullptr, "", header);
|
||||
|
||||
const std::string& def_action = wxGetApp().app_config->get(m_app_config_key);
|
||||
if (def_action == "none")
|
||||
const std::string& def_action = m_app_config_key.empty() ? none : wxGetApp().app_config->get(m_app_config_key);
|
||||
if (def_action == none)
|
||||
this->CenterOnScreen();
|
||||
else {
|
||||
m_exit_action = def_action == ActSave ? Action::Save : Action::Discard;
|
||||
if (m_exit_action == Action::Save)
|
||||
save(nullptr);
|
||||
m_exit_action = def_action == ActTransfer ? Action::Transfer :
|
||||
def_action == ActSave ? Action::Save : Action::Discard;
|
||||
if (m_exit_action != Action::Discard)
|
||||
save(nullptr, m_exit_action == Action::Save);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -782,7 +793,7 @@ UnsavedChangesDialog::UnsavedChangesDialog(Preset::Type type, PresetCollection*
|
|||
build(type, dependent_presets, new_selected_preset);
|
||||
|
||||
const std::string& def_action = wxGetApp().app_config->get(m_app_config_key);
|
||||
if (def_action == "none") {
|
||||
if (def_action == none) {
|
||||
if (wxGetApp().mainframe->is_dlg_layout() && wxGetApp().mainframe->m_settings_dialog.HasFocus())
|
||||
this->SetPosition(wxGetApp().mainframe->m_settings_dialog.GetPosition());
|
||||
this->CenterOnScreen();
|
||||
|
@ -833,7 +844,8 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_
|
|||
|
||||
(*btn)->Bind(wxEVT_BUTTON, [this, close_act, dependent_presets](wxEvent&) {
|
||||
update_config(close_act);
|
||||
if (close_act == Action::Save && !save(dependent_presets))
|
||||
bool save_names_and_types = close_act == Action::Save || (close_act == Action::Transfer && ActionButtons::KEEP & m_buttons);
|
||||
if (save_names_and_types && !save(dependent_presets, close_act == Action::Save))
|
||||
return;
|
||||
close(close_act);
|
||||
});
|
||||
|
@ -842,13 +854,26 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_
|
|||
(*btn)->Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent& e) { show_info_line(Action::Undef); e.Skip(); });
|
||||
};
|
||||
|
||||
const PresetCollection* switched_presets = type == Preset::TYPE_INVALID ? nullptr : wxGetApp().get_tab(type)->get_presets();
|
||||
if (dependent_presets && switched_presets && (type == dependent_presets->type() ?
|
||||
dependent_presets->get_edited_preset().printer_technology() == dependent_presets->find_preset(new_selected_preset)->printer_technology() :
|
||||
switched_presets->get_edited_preset().printer_technology() == switched_presets->find_preset(new_selected_preset)->printer_technology()))
|
||||
add_btn(&m_transfer_btn, m_move_btn_id, "paste_menu", Action::Transfer, _L("Transfer"));
|
||||
add_btn(&m_discard_btn, m_continue_btn_id, dependent_presets ? "switch_presets" : "exit", Action::Discard, _L("Discard"), false);
|
||||
add_btn(&m_save_btn, m_save_btn_id, "save", Action::Save, _L("Save"));
|
||||
// "Transfer" / "Keep" button
|
||||
if (ActionButtons::TRANSFER & m_buttons) {
|
||||
const PresetCollection* switched_presets = type == Preset::TYPE_INVALID ? nullptr : wxGetApp().get_tab(type)->get_presets();
|
||||
if (dependent_presets && switched_presets && (type == dependent_presets->type() ?
|
||||
dependent_presets->get_edited_preset().printer_technology() == dependent_presets->find_preset(new_selected_preset)->printer_technology() :
|
||||
switched_presets->get_edited_preset().printer_technology() == switched_presets->find_preset(new_selected_preset)->printer_technology()))
|
||||
add_btn(&m_transfer_btn, m_move_btn_id, "paste_menu", Action::Transfer, switched_presets->get_edited_preset().name == new_selected_preset ? _L("Keep") : _L("Transfer"));
|
||||
}
|
||||
if (!m_transfer_btn && (ActionButtons::KEEP & m_buttons))
|
||||
add_btn(&m_transfer_btn, m_move_btn_id, "paste_menu", Action::Transfer, _L("Keep"));
|
||||
|
||||
{ // "Don't save" / "Discard" button
|
||||
std::string btn_icon = (ActionButtons::DONT_SAVE & m_buttons) ? "" : (dependent_presets || (ActionButtons::KEEP & m_buttons)) ? "switch_presets" : "exit";
|
||||
wxString btn_label = (ActionButtons::DONT_SAVE & m_buttons) ? _L("Don't save") : _L("Discard");
|
||||
add_btn(&m_discard_btn, m_continue_btn_id, btn_icon, Action::Discard, btn_label, false);
|
||||
}
|
||||
|
||||
// "Save" button
|
||||
if (ActionButtons::SAVE & m_buttons)
|
||||
add_btn(&m_save_btn, m_save_btn_id, "save", Action::Save, _L("Save"));
|
||||
|
||||
ScalableButton* cancel_btn = new ScalableButton(this, wxID_CANCEL, "cross", _L("Cancel"), wxDefaultSize, wxDefaultPosition, wxBORDER_DEFAULT, true, 24);
|
||||
buttons->Add(cancel_btn, 1, wxLEFT|wxRIGHT, 5);
|
||||
|
@ -859,34 +884,42 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_
|
|||
m_info_line->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold());
|
||||
m_info_line->Hide();
|
||||
|
||||
m_remember_choice = new wxCheckBox(this, wxID_ANY, _L("Remember my choice"));
|
||||
m_remember_choice->SetValue(wxGetApp().app_config->get(m_app_config_key) != "none");
|
||||
m_remember_choice->Bind(wxEVT_CHECKBOX, [type, this](wxCommandEvent& evt)
|
||||
{
|
||||
if (!evt.IsChecked())
|
||||
return;
|
||||
wxString preferences_item = type == Preset::TYPE_INVALID ? _L("Ask for unsaved changes when closing application") :
|
||||
_L("Ask for unsaved changes when selecting new preset");
|
||||
wxString msg =
|
||||
_L("PrusaSlicer will remember your action.") + "\n\n" +
|
||||
(type == Preset::TYPE_INVALID ?
|
||||
_L("You will not be asked about the unsaved changes the next time you close PrusaSlicer.") :
|
||||
_L("You will not be asked about the unsaved changes the next time you switch a preset.")) + "\n\n" +
|
||||
format_wxstr(_L("Visit \"Preferences\" and check \"%1%\"\nto be asked about unsaved changes again."), preferences_item);
|
||||
if (!m_app_config_key.empty()) {
|
||||
m_remember_choice = new wxCheckBox(this, wxID_ANY, _L("Remember my choice"));
|
||||
m_remember_choice->SetValue(wxGetApp().app_config->get(m_app_config_key) != none);
|
||||
m_remember_choice->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& evt)
|
||||
{
|
||||
if (!evt.IsChecked())
|
||||
return;
|
||||
wxString preferences_item = m_app_config_key == "default_action_on_new_project" ? _L("Ask for unsaved changes when creating new project") :
|
||||
m_app_config_key == "default_action_on_select_preset" ? _L("Ask for unsaved changes when selecting new preset") :
|
||||
_L("Ask for unsaved changes when ??closing application??") ;
|
||||
wxString action = m_app_config_key == "default_action_on_new_project" ? _L("You will not be asked about the unsaved changes the next time you create new project") :
|
||||
m_app_config_key == "default_action_on_select_preset" ? _L("You will not be asked about the unsaved changes the next time you switch a preset") :
|
||||
_L("You will not be asked about the unsaved changes the next time you: \n"
|
||||
"- close the application,\n"
|
||||
"- load project,\n"
|
||||
"- process Undo / Redo with change of print technologie,\n"
|
||||
"- take/load snapshot,\n"
|
||||
"- load config file/bundle,\n"
|
||||
"- export config_bundle") ;
|
||||
wxString msg = _L("PrusaSlicer will remember your action.") + "\n\n" + action + "\n\n" +
|
||||
format_wxstr(_L("Visit \"Preferences\" and check \"%1%\"\nto be asked about unsaved changes again."), preferences_item);
|
||||
|
||||
//wxMessageDialog dialog(nullptr, msg, _L("PrusaSlicer: Don't ask me again"), wxOK | wxCANCEL | wxICON_INFORMATION);
|
||||
MessageDialog dialog(nullptr, msg, _L("PrusaSlicer: Don't ask me again"), wxOK | wxCANCEL | wxICON_INFORMATION);
|
||||
if (dialog.ShowModal() == wxID_CANCEL)
|
||||
m_remember_choice->SetValue(false);
|
||||
});
|
||||
MessageDialog dialog(nullptr, msg, _L("PrusaSlicer: Don't ask me again"), wxOK | wxCANCEL | wxICON_INFORMATION);
|
||||
if (dialog.ShowModal() == wxID_CANCEL)
|
||||
m_remember_choice->SetValue(false);
|
||||
});
|
||||
}
|
||||
|
||||
wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
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 | wxLEFT | wxTOP | wxRIGHT, border);
|
||||
topSizer->Add(m_remember_choice, 0, wxEXPAND | wxALL, border);
|
||||
topSizer->Add(buttons, 0, wxEXPAND | wxALL, border);
|
||||
if (m_remember_choice)
|
||||
topSizer->Add(m_remember_choice, 0, wxEXPAND | wxLEFT | wxBOTTOM | wxRIGHT, border);
|
||||
|
||||
update(type, dependent_presets, new_selected_preset, header);
|
||||
|
||||
|
@ -905,10 +938,12 @@ void UnsavedChangesDialog::show_info_line(Action action, std::string preset_name
|
|||
if (action == Action::Undef)
|
||||
text = _L("Some fields are too long to fit. Right mouse click reveals the full text.");
|
||||
else if (action == Action::Discard)
|
||||
text = _L("All settings changes will be discarded.");
|
||||
text = ActionButtons::DONT_SAVE & m_buttons ? _L("All settings changes will not be saved") :_L("All settings changes will be discarded.");
|
||||
else {
|
||||
if (preset_name.empty())
|
||||
text = action == Action::Save ? _L("Save the selected options.") : _L("Transfer the selected settings to the newly selected preset.");
|
||||
text = action == Action::Save ? _L("Save the selected options.") :
|
||||
ActionButtons::KEEP & m_buttons ? _L("Keep the selected settings.") :
|
||||
_L("Transfer the selected settings to the newly selected preset.");
|
||||
else
|
||||
text = format_wxstr(
|
||||
action == Action::Save ?
|
||||
|
@ -927,7 +962,7 @@ void UnsavedChangesDialog::show_info_line(Action action, std::string preset_name
|
|||
|
||||
void UnsavedChangesDialog::update_config(Action action)
|
||||
{
|
||||
if (!m_remember_choice->GetValue())
|
||||
if (!m_remember_choice || !m_remember_choice->GetValue())
|
||||
return;
|
||||
|
||||
std::string act = action == Action::Transfer ? ActTransfer :
|
||||
|
@ -941,7 +976,7 @@ void UnsavedChangesDialog::close(Action action)
|
|||
this->EndModal(wxID_CLOSE);
|
||||
}
|
||||
|
||||
bool UnsavedChangesDialog::save(PresetCollection* dependent_presets)
|
||||
bool UnsavedChangesDialog::save(PresetCollection* dependent_presets, bool show_save_preset_dialog/* = true*/)
|
||||
{
|
||||
names_and_types.clear();
|
||||
|
||||
|
@ -979,7 +1014,7 @@ bool UnsavedChangesDialog::save(PresetCollection* dependent_presets)
|
|||
}
|
||||
|
||||
|
||||
if (!types_for_save.empty()) {
|
||||
if (show_save_preset_dialog && !types_for_save.empty()) {
|
||||
SavePresetDialog save_dlg(this, types_for_save);
|
||||
if (save_dlg.ShowModal() != wxID_OK) {
|
||||
m_exit_action = Action::Discard;
|
||||
|
@ -1164,16 +1199,24 @@ void UnsavedChangesDialog::update(Preset::Type type, PresetCollection* dependent
|
|||
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 ? presets->get_selected_preset().name : ""); e.Skip(); });
|
||||
if (m_save_btn)
|
||||
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_transfer_btn) {
|
||||
bool is_empty_name = type != dependent_presets->type();
|
||||
m_transfer_btn ->Bind(wxEVT_ENTER_WINDOW, [this, new_selected_preset, is_empty_name] (wxMouseEvent& e) { show_info_line(Action::Transfer, is_empty_name ? "" : new_selected_preset); e.Skip(); });
|
||||
bool is_empty_name = dependent_presets && type != dependent_presets->type();
|
||||
m_transfer_btn->Bind(wxEVT_ENTER_WINDOW, [this, new_selected_preset, is_empty_name](wxMouseEvent& e) { show_info_line(Action::Transfer, is_empty_name ? "" : new_selected_preset); e.Skip(); });
|
||||
}
|
||||
m_discard_btn ->Bind(wxEVT_ENTER_WINDOW, [this] (wxMouseEvent& e) { show_info_line(Action::Discard); e.Skip(); });
|
||||
|
||||
if (m_discard_btn)
|
||||
m_discard_btn ->Bind(wxEVT_ENTER_WINDOW, [this] (wxMouseEvent& e) { show_info_line(Action::Discard); e.Skip(); });
|
||||
|
||||
if (type == Preset::TYPE_INVALID) {
|
||||
m_action_line->SetLabel(header + "\n" + _L("The following presets were modified:"));
|
||||
PrinterTechnology printer_technology = wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology();
|
||||
int presets_cnt = 0;
|
||||
for (Tab* tab : wxGetApp().tabs_list)
|
||||
if (tab->supports_printer_technology(printer_technology) && tab->current_preset_is_dirty())
|
||||
presets_cnt++;
|
||||
m_action_line->SetLabel((header.IsEmpty() ? "" : header + "\n\n") + //_L("The following presets were modified:"));
|
||||
+ _L_PLURAL("The following preset was modified",
|
||||
"The following presets were modified", presets_cnt));
|
||||
}
|
||||
else {
|
||||
wxString action_msg;
|
||||
|
|
|
@ -220,8 +220,9 @@ public:
|
|||
void context_menu(wxDataViewEvent& event);
|
||||
void item_value_changed(wxDataViewEvent& event);
|
||||
void set_em_unit(int em) { m_em_unit = em; }
|
||||
bool has_unselected_options();
|
||||
|
||||
std::vector<std::string> unselected_options(Preset::Type type);
|
||||
std::vector<std::string> options(Preset::Type type, bool selected);
|
||||
std::vector<std::string> selected_options();
|
||||
};
|
||||
|
||||
|
@ -261,10 +262,22 @@ class UnsavedChangesDialog : public DPIDialog
|
|||
Action m_exit_action {Action::Undef};
|
||||
// preset names which are modified in SavePresetDialog and related types
|
||||
std::vector<std::pair<std::string, Preset::Type>> names_and_types;
|
||||
// additional action buttons used in dialog
|
||||
int m_buttons { ActionButtons::TRANSFER | ActionButtons::SAVE };
|
||||
|
||||
public:
|
||||
UnsavedChangesDialog(const wxString& header, const wxString& caption = wxString());
|
||||
// Discard and Cancel buttons are always but next buttons are optional
|
||||
enum ActionButtons {
|
||||
TRANSFER = 1,
|
||||
KEEP = 2,
|
||||
SAVE = 4,
|
||||
DONT_SAVE = 8,
|
||||
};
|
||||
|
||||
// show unsaved changes when preset is switching
|
||||
UnsavedChangesDialog(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset);
|
||||
// show unsaved changes for all another cases
|
||||
UnsavedChangesDialog(const wxString& caption, const wxString& header, const std::string& app_config_key, int act_buttons);
|
||||
~UnsavedChangesDialog() {}
|
||||
|
||||
void build(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset, const wxString& header = "");
|
||||
|
@ -273,7 +286,8 @@ public:
|
|||
void show_info_line(Action action, std::string preset_name = "");
|
||||
void update_config(Action action);
|
||||
void close(Action action);
|
||||
bool save(PresetCollection* dependent_presets);
|
||||
// save information about saved presets and their types to names_and_types and show SavePresetDialog to set the names for new presets
|
||||
bool save(PresetCollection* dependent_presets, bool show_save_preset_dialog = true);
|
||||
|
||||
bool save_preset() const { return m_exit_action == Action::Save; }
|
||||
bool transfer_changes() const { return m_exit_action == Action::Transfer; }
|
||||
|
@ -284,8 +298,10 @@ public:
|
|||
// short version of the previous function, for the case, when just one preset is modified
|
||||
std::string get_preset_name() { return names_and_types[0].first; }
|
||||
|
||||
std::vector<std::string> get_unselected_options(Preset::Type type) { return m_tree->unselected_options(type); }
|
||||
std::vector<std::string> get_unselected_options(Preset::Type type) { return m_tree->options(type, false); }
|
||||
std::vector<std::string> get_selected_options (Preset::Type type) { return m_tree->options(type, true); }
|
||||
std::vector<std::string> get_selected_options() { return m_tree->selected_options(); }
|
||||
bool has_unselected_options() { return m_tree->has_unselected_options(); }
|
||||
|
||||
protected:
|
||||
void on_dpi_changed(const wxRect& suggested_rect) override;
|
||||
|
|
|
@ -720,8 +720,13 @@ void PresetUpdater::slic3r_update_notify()
|
|||
}
|
||||
}
|
||||
|
||||
static void reload_configs_update_gui()
|
||||
static bool reload_configs_update_gui()
|
||||
{
|
||||
wxString header = _L("Configuration Updates causes a lost of preset modification.\n"
|
||||
"So, check unsaved changes and save them if necessary.");
|
||||
if (!GUI::wxGetApp().check_and_save_current_preset_changes(_L("Updater is processing"), header, false ))
|
||||
return false;
|
||||
|
||||
// Reload global configuration
|
||||
auto* app_config = GUI::wxGetApp().app_config;
|
||||
// System profiles should not trigger any substitutions, user profiles may trigger substitutions, but these substitutions
|
||||
|
@ -730,7 +735,8 @@ static void reload_configs_update_gui()
|
|||
GUI::wxGetApp().preset_bundle->load_presets(*app_config, ForwardCompatibilitySubstitutionRule::EnableSilentDisableSystem);
|
||||
GUI::wxGetApp().load_current_presets();
|
||||
GUI::wxGetApp().plater()->set_bed_shape();
|
||||
GUI::wxGetApp().update_wizard_from_config();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver& old_slic3r_version, UpdateParams params) const
|
||||
|
@ -803,9 +809,9 @@ PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver& old_slic3
|
|||
const auto res = dlg.ShowModal();
|
||||
if (res == wxID_OK) {
|
||||
BOOST_LOG_TRIVIAL(info) << "User wants to update...";
|
||||
if (! p->perform_updates(std::move(updates)))
|
||||
if (! p->perform_updates(std::move(updates)) ||
|
||||
! reload_configs_update_gui())
|
||||
return R_INCOMPAT_EXIT;
|
||||
reload_configs_update_gui();
|
||||
return R_UPDATE_INSTALLED;
|
||||
}
|
||||
else {
|
||||
|
@ -833,9 +839,9 @@ PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver& old_slic3
|
|||
const auto res = dlg.ShowModal();
|
||||
if (res == wxID_OK) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "User agreed to perform the update";
|
||||
if (! p->perform_updates(std::move(updates)))
|
||||
if (! p->perform_updates(std::move(updates)) ||
|
||||
! reload_configs_update_gui())
|
||||
return R_ALL_CANCELED;
|
||||
reload_configs_update_gui();
|
||||
return R_UPDATE_INSTALLED;
|
||||
}
|
||||
else {
|
||||
|
@ -886,8 +892,8 @@ void PresetUpdater::on_update_notification_confirm()
|
|||
const auto res = dlg.ShowModal();
|
||||
if (res == wxID_OK) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "User agreed to perform the update";
|
||||
if (p->perform_updates(std::move(p->waiting_updates))) {
|
||||
reload_configs_update_gui();
|
||||
if (p->perform_updates(std::move(p->waiting_updates)) &&
|
||||
reload_configs_update_gui()) {
|
||||
p->has_waiting_updates = false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue