From fea560340967e782849880079013014a32d3971c Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 24 Apr 2018 18:06:42 +0200 Subject: [PATCH] PresetUpdater: Bundle incompatibility / Slic3r downgrade scnario --- lib/Slic3r/GUI.pm | 17 +- resources/icons/Slic3r_192px_grayscale.png | Bin 0 -> 19251 bytes xs/CMakeLists.txt | 2 + xs/src/slic3r/GUI/ConfigWizard.cpp | 27 ++- xs/src/slic3r/GUI/ConfigWizard.hpp | 13 +- xs/src/slic3r/GUI/ConfigWizard_private.hpp | 5 +- xs/src/slic3r/GUI/GUI.cpp | 23 +- xs/src/slic3r/GUI/GUI.hpp | 9 +- xs/src/slic3r/GUI/UpdateDialogs.cpp | 203 +++++++++++++++++ xs/src/slic3r/GUI/UpdateDialogs.hpp | 92 ++++++++ xs/src/slic3r/Utils/PresetUpdater.cpp | 240 ++++++++++----------- xs/src/slic3r/Utils/PresetUpdater.hpp | 5 +- xs/xsp/GUI.xsp | 4 +- xs/xsp/Utils_PresetUpdater.xsp | 2 +- 14 files changed, 480 insertions(+), 162 deletions(-) create mode 100644 resources/icons/Slic3r_192px_grayscale.png create mode 100644 xs/src/slic3r/GUI/UpdateDialogs.cpp create mode 100644 xs/src/slic3r/GUI/UpdateDialogs.hpp diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 10375a9dc..89a8e7974 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -86,8 +86,9 @@ sub OnInit { Slic3r::GUI::set_wxapp($self); $self->{app_config} = Slic3r::GUI::AppConfig->new; - $self->{preset_bundle} = Slic3r::GUI::PresetBundle->new; Slic3r::GUI::set_app_config($self->{app_config}); + $self->{preset_bundle} = Slic3r::GUI::PresetBundle->new; + Slic3r::GUI::set_preset_bundle($self->{preset_bundle}); # just checking for existence of Slic3r::data_dir is not enough: it may be an empty directory # supplied as argument to --datadir; in that case we should still run the wizard @@ -104,7 +105,11 @@ sub OnInit { $self->{preset_updater} = Slic3r::PresetUpdater->new($VERSION_ONLINE_EVENT); Slic3r::GUI::set_preset_updater($self->{preset_updater}); - eval { $self->{preset_updater}->config_update(); }; + eval { + if (! $self->{preset_updater}->config_update()) { + exit 0; + } + }; if ($@) { warn $@ . "\n"; fatal_error(undef, $@); @@ -120,8 +125,6 @@ sub OnInit { show_error(undef, $@); } - Slic3r::GUI::set_preset_bundle($self->{preset_bundle}); - # application frame print STDERR "Creating main frame...\n"; Wx::Image::FindHandlerType(wxBITMAP_TYPE_PNG) || Wx::Image::AddHandler(Wx::PNGHandler->new); @@ -144,8 +147,10 @@ sub OnInit { # On OSX the UI was not initialized correctly if the wizard was called # before the UI was up and running. $self->CallAfter(sub { - Slic3r::GUI::config_wizard_startup($app_conf_exists); - $self->{preset_updater}->slic3r_update_notify(); + if (! Slic3r::GUI::config_wizard_startup($app_conf_exists)) { + # Only notify if there was not wizard so as not to bother too much ... + $self->{preset_updater}->slic3r_update_notify(); + } $self->{preset_updater}->sync($self->{preset_bundle}); }); diff --git a/resources/icons/Slic3r_192px_grayscale.png b/resources/icons/Slic3r_192px_grayscale.png new file mode 100644 index 0000000000000000000000000000000000000000..910f941870510c4fcc8c7c5cf728f9758af3e1d6 GIT binary patch literal 19251 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 && wizard_p()->flag_empty_datadir) { + if (wizard_p()->run_reason == ConfigWizard::RR_DATA_EMPTY) { wxString::Format(_(L("Run %s")), ConfigWizard::name()); append_text(wxString::Format( _(L("Hello, welcome to Slic3r Prusa Edition! This %s helps you with the initial configuration; just a few settings and you will be ready to print.")), @@ -709,7 +709,7 @@ void ConfigWizard::priv::on_custom_setup() set_page(page_firmware); } -void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *preset_bundle, PresetUpdater *updater) +void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater) { const bool is_custom_setup = page_welcome->page_next() == page_firmware; @@ -730,8 +730,14 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese install_bundles.emplace_back(vendor_rsrc.second); } - // If the datadir was empty don't take a snapshot (it would just be an empty snapshot) - const bool snapshot = !flag_empty_datadir || page_welcome->reset_user_profile(); + // Decide whether to create snapshot based on run_reason and the reset profile checkbox + bool snapshot = true; + switch (run_reason) { + case ConfigWizard::RR_DATA_EMPTY: snapshot = false; break; + case ConfigWizard::RR_DATA_LEGACY: snapshot = true; break; + case ConfigWizard::RR_DATA_INCOMPAT: snapshot = false; break; // In this case snapshot is done by PresetUpdater with the appropriate reason + case ConfigWizard::RR_USER: snapshot = page_welcome->reset_user_profile(); break; + } if (install_bundles.size() > 0) { // Install bundles from resources. updater->install_bundles_rsrc(std::move(install_bundles), snapshot); @@ -744,8 +750,7 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese app_config->set_vendors(appconfig_vendors); app_config->set("version_check", page_update->version_check ? "1" : "0"); app_config->set("preset_update", page_update->preset_update ? "1" : "0"); - if (flag_startup) - app_config->reset_selections(); + app_config->reset_selections(); // ^ TODO: replace with appropriate printer selection preset_bundle->load_presets(*app_config); } else { @@ -760,12 +765,11 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese // Public -ConfigWizard::ConfigWizard(wxWindow *parent, bool startup, bool empty_datadir) : +ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) : wxDialog(parent, wxID_ANY, name(), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), p(new priv(this)) { - p->flag_startup = startup; - p->flag_empty_datadir = empty_datadir; + p->run_reason = reason; p->load_vendors(); p->custom_config.reset(DynamicPrintConfig::new_from_defaults_keys({ @@ -822,10 +826,13 @@ ConfigWizard::ConfigWizard(wxWindow *parent, bool startup, bool empty_datadir) : ConfigWizard::~ConfigWizard() {} -void ConfigWizard::run(PresetBundle *preset_bundle, PresetUpdater *updater) +bool ConfigWizard::run(PresetBundle *preset_bundle, const PresetUpdater *updater) { if (ShowModal() == wxID_OK) { p->apply_config(GUI::get_app_config(), preset_bundle, updater); + return true; + } else { + return false; } } diff --git a/xs/src/slic3r/GUI/ConfigWizard.hpp b/xs/src/slic3r/GUI/ConfigWizard.hpp index eeb64c57f..73fce7cd2 100644 --- a/xs/src/slic3r/GUI/ConfigWizard.hpp +++ b/xs/src/slic3r/GUI/ConfigWizard.hpp @@ -16,14 +16,23 @@ namespace GUI { class ConfigWizard: public wxDialog { public: - ConfigWizard(wxWindow *parent, bool startup, bool empty_datadir); + // Why is the Wizard run + enum RunReason { + RR_DATA_EMPTY, // No or empty datadir + RR_DATA_LEGACY, // Pre-updating datadir + RR_DATA_INCOMPAT, // Incompatible datadir - Slic3r downgrade situation + RR_USER, // User requested the Wizard from the menus + }; + + ConfigWizard(wxWindow *parent, RunReason run_reason); ConfigWizard(ConfigWizard &&) = delete; ConfigWizard(const ConfigWizard &) = delete; ConfigWizard &operator=(ConfigWizard &&) = delete; ConfigWizard &operator=(const ConfigWizard &) = delete; ~ConfigWizard(); - void run(PresetBundle *preset_bundle, PresetUpdater *updater); + // Run the Wizard. Return whether it was completed. + bool run(PresetBundle *preset_bundle, const PresetUpdater *updater); static const wxString& name(); private: diff --git a/xs/src/slic3r/GUI/ConfigWizard_private.hpp b/xs/src/slic3r/GUI/ConfigWizard_private.hpp index cdab2eb3c..474394bc3 100644 --- a/xs/src/slic3r/GUI/ConfigWizard_private.hpp +++ b/xs/src/slic3r/GUI/ConfigWizard_private.hpp @@ -190,8 +190,7 @@ private: struct ConfigWizard::priv { ConfigWizard *q; - bool flag_startup; - bool flag_empty_datadir; + ConfigWizard::RunReason run_reason; AppConfig appconfig_vendors; std::unordered_map vendors; std::unordered_map vendors_rsrc; @@ -228,7 +227,7 @@ struct ConfigWizard::priv void on_other_vendors(); void on_custom_setup(); - void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, PresetUpdater *updater); + void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater); }; diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 88c3f421b..bd74e118e 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -390,7 +390,7 @@ void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_l local_menu->Bind(wxEVT_MENU, [config_id_base, event_language_change, event_preferences_changed](wxEvent &event){ switch (event.GetId() - config_id_base) { case ConfigMenuWizard: - config_wizard(false, false); + config_wizard(ConfigWizard::RR_USER); break; case ConfigMenuTakeSnapshot: // Take a configuration snapshot. @@ -469,10 +469,11 @@ bool check_unsaved_changes() return dialog->ShowModal() == wxID_YES; } -void config_wizard_startup(bool app_config_exists) +bool config_wizard_startup(bool app_config_exists) { if (! app_config_exists || g_PresetBundle->has_defauls_only()) { - config_wizard(true, true); + config_wizard(ConfigWizard::RR_DATA_EMPTY); + return true; } else if (g_AppConfig->legacy_datadir()) { // Looks like user has legacy pre-vendorbundle data directory, // explain what this is and run the wizard @@ -496,20 +497,19 @@ void config_wizard_startup(bool app_config_exists) dlg.SetExtendedMessage(ext_msg); const auto res = dlg.ShowModal(); - config_wizard(true, false); + config_wizard(ConfigWizard::RR_DATA_LEGACY); + return true; } + return false; } -void config_wizard(bool startup, bool empty_datadir) +void config_wizard(int reason) { - if (g_wxMainFrame == nullptr) - throw std::runtime_error("Main frame not set"); - // Exit wizard if there are unsaved changes and the user cancels the action. if (! check_unsaved_changes()) return; - ConfigWizard wizard(g_wxMainFrame, startup, empty_datadir); + ConfigWizard wizard(nullptr, static_cast(reason)); wizard.run(g_PresetBundle, g_PresetUpdater); // Load the currently selected preset into the GUI, update the preset selection box. @@ -686,6 +686,11 @@ wxApp* get_app(){ return g_wxApp; } +PresetBundle* get_preset_bundle() +{ + return g_PresetBundle; +} + const wxColour& get_modified_label_clr() { return g_color_label_modified; } diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp index 92a6e6ebb..a8bbdccc7 100644 --- a/xs/src/slic3r/GUI/GUI.hpp +++ b/xs/src/slic3r/GUI/GUI.hpp @@ -82,6 +82,7 @@ void set_preset_updater(PresetUpdater *updater); AppConfig* get_app_config(); wxApp* get_app(); +PresetBundle* get_preset_bundle(); const wxColour& get_modified_label_clr(); const wxColour& get_sys_label_clr(); @@ -93,11 +94,13 @@ extern void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int // to notify the user whether he is aware that some preset changes will be lost. extern bool check_unsaved_changes(); -// Checks if configuration wizard needs to run, calls config_wizard if so -extern void config_wizard_startup(bool app_config_exists); +// Checks if configuration wizard needs to run, calls config_wizard if so. +// Returns whether the Wizard ran. +extern bool config_wizard_startup(bool app_config_exists); // Opens the configuration wizard, returns true if wizard is finished & accepted. -extern void config_wizard(bool startup, bool empty_datadir); +// The run_reason argument is actually ConfigWizard::RunReason, but int is used here because of Perl. +extern void config_wizard(int run_reason); // Create "Preferences" dialog after selecting menu "Preferences" in Perl part extern void open_preferences_dialog(int event_preferences); diff --git a/xs/src/slic3r/GUI/UpdateDialogs.cpp b/xs/src/slic3r/GUI/UpdateDialogs.cpp new file mode 100644 index 000000000..076554e23 --- /dev/null +++ b/xs/src/slic3r/GUI/UpdateDialogs.cpp @@ -0,0 +1,203 @@ +#include "UpdateDialogs.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libslic3r/libslic3r.h" +#include "libslic3r/Utils.hpp" +#include "GUI.hpp" + +namespace Slic3r { +namespace GUI { + + +enum { + CONTENT_WIDTH = 400, + BORDER = 30, + VERT_SPACING = 15, + HORIZ_SPACING = 5, +}; + + +MsgDialog::MsgDialog(const wxString &title, const wxString &headline, wxWindowID button_id) : + MsgDialog(title, headline, wxBitmap(from_u8(Slic3r::var("Slic3r_192px.png")), wxBITMAP_TYPE_PNG), button_id) +{} + +MsgDialog::MsgDialog(const wxString &title, const wxString &headline, wxBitmap bitmap, wxWindowID button_id) : + wxDialog(nullptr, wxID_ANY, title), + boldfont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)), + content_sizer(new wxBoxSizer(wxVERTICAL)), + btn_sizer(new wxBoxSizer(wxHORIZONTAL)) +{ + boldfont.SetWeight(wxFONTWEIGHT_BOLD); + + auto *topsizer = new wxBoxSizer(wxHORIZONTAL); + auto *rightsizer = new wxBoxSizer(wxVERTICAL); + + auto *headtext = new wxStaticText(this, wxID_ANY, headline); + headtext->SetFont(boldfont); + headtext->Wrap(CONTENT_WIDTH); + rightsizer->Add(headtext); + rightsizer->AddSpacer(VERT_SPACING); + + rightsizer->Add(content_sizer); + + if (button_id != wxID_NONE) { + auto *button = new wxButton(this, button_id); + button->SetFocus(); + btn_sizer->Add(button); + } + + rightsizer->Add(btn_sizer, 0, wxALIGN_CENTRE_HORIZONTAL); + + auto *logo = new wxStaticBitmap(this, wxID_ANY, std::move(bitmap)); + + topsizer->Add(logo, 0, wxALL, BORDER); + topsizer->Add(rightsizer, 0, wxALL, BORDER); + + SetSizerAndFit(topsizer); +} + +MsgDialog::~MsgDialog() {} + + +// MsgUpdateSlic3r + +MsgUpdateSlic3r::MsgUpdateSlic3r(const Semver &ver_current, const Semver &ver_online) : + MsgDialog(_(L("Update available")), _(L("New version of Slic3r PE is available"))), + ver_current(ver_current), + ver_online(ver_online) +{ + const auto url = wxString::Format("https://github.com/prusa3d/Slic3r/releases/tag/version_%s", ver_online.to_string()); + auto *link = new wxHyperlinkCtrl(this, wxID_ANY, url, url); + + auto *text = new wxStaticText(this, wxID_ANY, _(L("To download, follow the link below."))); + const auto link_width = link->GetSize().GetWidth(); + text->Wrap(CONTENT_WIDTH > link_width ? CONTENT_WIDTH : link_width); + content_sizer->Add(text); + content_sizer->AddSpacer(VERT_SPACING); + + auto *versions = new wxFlexGridSizer(2, 0, VERT_SPACING); + versions->Add(new wxStaticText(this, wxID_ANY, _(L("Current version:")))); + versions->Add(new wxStaticText(this, wxID_ANY, ver_current.to_string())); + versions->Add(new wxStaticText(this, wxID_ANY, _(L("New version:")))); + versions->Add(new wxStaticText(this, wxID_ANY, ver_online.to_string())); + content_sizer->Add(versions); + content_sizer->AddSpacer(VERT_SPACING); + + content_sizer->Add(link); + content_sizer->AddSpacer(2*VERT_SPACING); + + cbox = new wxCheckBox(this, wxID_ANY, _(L("Don't notify about new releases any more"))); + content_sizer->Add(cbox); + content_sizer->AddSpacer(VERT_SPACING); + + Fit(); +} + +MsgUpdateSlic3r::~MsgUpdateSlic3r() {} + +bool MsgUpdateSlic3r::disable_version_check() const +{ + return cbox->GetValue(); +} + + +// MsgUpdateConfig + +MsgUpdateConfig::MsgUpdateConfig(const std::unordered_map &updates) : + MsgDialog(_(L("Configuration update")), _(L("Configuration update is available")), wxID_NONE) +{ + auto *text = new wxStaticText(this, wxID_ANY, _(L( + "Would you like to install it?\n\n" + "Note that a full configuration snapshot will be created first. It can then be restored at any time " + "should there be a problem with the new version.\n\n" + "Updated configuration bundles:" + ))); + text->Wrap(CONTENT_WIDTH); + content_sizer->Add(text); + content_sizer->AddSpacer(VERT_SPACING); + + auto *versions = new wxFlexGridSizer(2, 0, VERT_SPACING); + for (const auto &update : updates) { + auto *text_vendor = new wxStaticText(this, wxID_ANY, update.first); + text_vendor->SetFont(boldfont); + versions->Add(text_vendor); + versions->Add(new wxStaticText(this, wxID_ANY, update.second)); + } + + content_sizer->Add(versions); + content_sizer->AddSpacer(2*VERT_SPACING); + + auto *btn_cancel = new wxButton(this, wxID_CANCEL); + btn_sizer->Add(btn_cancel); + btn_sizer->AddSpacer(HORIZ_SPACING); + auto *btn_ok = new wxButton(this, wxID_YES); + btn_sizer->Add(btn_ok); + btn_ok->SetFocus(); + + Fit(); +} + +MsgUpdateConfig::~MsgUpdateConfig() {} + + +// MsgDataIncompatible + +MsgDataIncompatible::MsgDataIncompatible(const std::unordered_map &incompats) : + MsgDialog(_(L("Slic3r incompatibility")), _(L("Slic3r configuration is incompatible")), wxBitmap(from_u8(Slic3r::var("Slic3r_192px_grayscale.png"))), wxID_NONE) +{ + auto *text = new wxStaticText(this, wxID_ANY, _(L( + "This version of Slic3r PE is not compatible with currently installed configuration bundles.\n" + "This probably happened as a result of running an older Slic3r PE after using a newer one.\n\n" + "TODO: more instrs\n" + ))); + text->Wrap(CONTENT_WIDTH); + content_sizer->Add(text); + + auto *text2 = new wxStaticText(this, wxID_ANY, wxString::Format(_(L("This Slic3r PE version: %s")), SLIC3R_VERSION)); + text2->Wrap(CONTENT_WIDTH); + content_sizer->Add(text2); + content_sizer->AddSpacer(VERT_SPACING); + + auto *text3 = new wxStaticText(this, wxID_ANY, _(L("Incompatible bundles:"))); + text3->Wrap(CONTENT_WIDTH); + content_sizer->Add(text3); + content_sizer->AddSpacer(VERT_SPACING); + + auto *versions = new wxFlexGridSizer(2, 0, VERT_SPACING); + for (const auto &incompat : incompats) { + auto *text_vendor = new wxStaticText(this, wxID_ANY, incompat.first); + text_vendor->SetFont(boldfont); + versions->Add(text_vendor); + versions->Add(new wxStaticText(this, wxID_ANY, incompat.second)); + } + + content_sizer->Add(versions); + content_sizer->AddSpacer(2*VERT_SPACING); + + auto *btn_exit = new wxButton(this, wxID_EXIT, _(L("Exit Slic3r"))); + btn_sizer->Add(btn_exit); + btn_sizer->AddSpacer(HORIZ_SPACING); + auto *btn_reconf = new wxButton(this, wxID_REPLACE, _(L("Re-configure"))); + btn_sizer->Add(btn_reconf); + btn_exit->SetFocus(); + + auto exiter = [this](const wxCommandEvent& evt) { this->EndModal(evt.GetId()); }; + btn_exit->Bind(wxEVT_BUTTON, exiter); + btn_reconf->Bind(wxEVT_BUTTON, exiter); + + Fit(); +} + +MsgDataIncompatible::~MsgDataIncompatible() {} + + +} +} diff --git a/xs/src/slic3r/GUI/UpdateDialogs.hpp b/xs/src/slic3r/GUI/UpdateDialogs.hpp new file mode 100644 index 000000000..ae949b8dd --- /dev/null +++ b/xs/src/slic3r/GUI/UpdateDialogs.hpp @@ -0,0 +1,92 @@ +#ifndef slic3r_UpdateDialogs_hpp_ +#define slic3r_UpdateDialogs_hpp_ + +#include +#include + +#include +#include +#include + +#include "slic3r/Utils/Semver.hpp" + +class wxBoxSizer; +class wxCheckBox; + +namespace Slic3r { + +namespace GUI { + + +// A message / query dialog with a bitmap on the left and any content on the right +// with buttons underneath. +struct MsgDialog : wxDialog +{ + MsgDialog(MsgDialog &&) = delete; + MsgDialog(const MsgDialog &) = delete; + MsgDialog &operator=(MsgDialog &&) = delete; + MsgDialog &operator=(const MsgDialog &) = delete; + virtual ~MsgDialog(); + +protected: + // button_id is an id of a button that can be added by default, use wxID_NONE to disable + MsgDialog(const wxString &title, const wxString &headline, wxWindowID button_id = wxID_OK); + MsgDialog(const wxString &title, const wxString &headline, wxBitmap bitmap, wxWindowID button_id = wxID_OK); + + wxFont boldfont; + wxBoxSizer *content_sizer; + wxBoxSizer *btn_sizer; +}; + +// A confirmation dialog listing configuration updates +class MsgUpdateSlic3r : public MsgDialog +{ +public: + MsgUpdateSlic3r(const Semver &ver_current, const Semver &ver_online); + MsgUpdateSlic3r(MsgUpdateSlic3r &&) = delete; + MsgUpdateSlic3r(const MsgUpdateSlic3r &) = delete; + MsgUpdateSlic3r &operator=(MsgUpdateSlic3r &&) = delete; + MsgUpdateSlic3r &operator=(const MsgUpdateSlic3r &) = delete; + virtual ~MsgUpdateSlic3r(); + + // Tells whether the user checked the "don't bother me again" checkbox + bool disable_version_check() const; + +private: + const Semver &ver_current; + const Semver &ver_online; + wxCheckBox *cbox; +}; + + +// Confirmation dialog informing about configuration update. Lists updated bundles & their versions. +class MsgUpdateConfig : public MsgDialog +{ +public: + // updates is a map of "vendor name" -> "version (comment)" + MsgUpdateConfig(const std::unordered_map &updates); + MsgUpdateConfig(MsgUpdateConfig &&) = delete; + MsgUpdateConfig(const MsgUpdateConfig &) = delete; + MsgUpdateConfig &operator=(MsgUpdateConfig &&) = delete; + MsgUpdateConfig &operator=(const MsgUpdateConfig &) = delete; + ~MsgUpdateConfig(); +}; + +// Informs about currently installed bundles not being compatible with the running Slic3r. Asks about action. +class MsgDataIncompatible : public MsgDialog +{ +public: + // incompats is a map of "vendor name" -> "version restrictions" + MsgDataIncompatible(const std::unordered_map &incompats); + MsgDataIncompatible(MsgDataIncompatible &&) = delete; + MsgDataIncompatible(const MsgDataIncompatible &) = delete; + MsgDataIncompatible &operator=(MsgDataIncompatible &&) = delete; + MsgDataIncompatible &operator=(const MsgDataIncompatible &) = delete; + ~MsgDataIncompatible(); +}; + + +} +} + +#endif diff --git a/xs/src/slic3r/Utils/PresetUpdater.cpp b/xs/src/slic3r/Utils/PresetUpdater.cpp index 8dd974537..ec152df63 100644 --- a/xs/src/slic3r/Utils/PresetUpdater.cpp +++ b/xs/src/slic3r/Utils/PresetUpdater.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include #include @@ -14,18 +14,13 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include #include "libslic3r/libslic3r.h" #include "libslic3r/Utils.hpp" #include "slic3r/GUI/GUI.hpp" #include "slic3r/GUI/PresetBundle.hpp" +#include "slic3r/GUI/UpdateDialogs.hpp" +#include "slic3r/GUI/ConfigWizard.hpp" #include "slic3r/Utils/Http.hpp" #include "slic3r/Config/Version.hpp" #include "slic3r/Config/Snapshot.hpp" @@ -48,90 +43,49 @@ static const char *INDEX_FILENAME = "index.idx"; static const char *TMP_EXTENSION = ".download"; -// A confirmation dialog listing configuration updates -struct UpdateNotification : wxDialog -{ - // If this dialog gets any more complex, it should probably be factored out... - - enum { - CONTENT_WIDTH = 400, - BORDER = 30, - SPACING = 15, - }; - - wxCheckBox *cbox; - - UpdateNotification(const Semver &ver_current, const Semver &ver_online) : wxDialog(nullptr, wxID_ANY, _(L("Update available"))) - { - auto *topsizer = new wxBoxSizer(wxHORIZONTAL); - auto *sizer = new wxBoxSizer(wxVERTICAL); - - const auto url = wxString::Format("https://github.com/prusa3d/Slic3r/releases/tag/version_%s", ver_online.to_string()); - auto *link = new wxHyperlinkCtrl(this, wxID_ANY, url, url); - - auto *text = new wxStaticText(this, wxID_ANY, - _(L("New version of Slic3r PE is available. To download, follow the link below."))); - const auto link_width = link->GetSize().GetWidth(); - text->Wrap(CONTENT_WIDTH > link_width ? CONTENT_WIDTH : link_width); - sizer->Add(text); - sizer->AddSpacer(SPACING); - - auto *versions = new wxFlexGridSizer(2, 0, SPACING); - versions->Add(new wxStaticText(this, wxID_ANY, _(L("Current version:")))); - versions->Add(new wxStaticText(this, wxID_ANY, ver_current.to_string())); - versions->Add(new wxStaticText(this, wxID_ANY, _(L("New version:")))); - versions->Add(new wxStaticText(this, wxID_ANY, ver_online.to_string())); - sizer->Add(versions); - sizer->AddSpacer(SPACING); - - sizer->Add(link); - sizer->AddSpacer(2*SPACING); - - cbox = new wxCheckBox(this, wxID_ANY, _(L("Don't notify about new releases any more"))); - sizer->Add(cbox); - sizer->AddSpacer(SPACING); - - auto *ok = new wxButton(this, wxID_OK); - ok->SetFocus(); - sizer->Add(ok, 0, wxALIGN_CENTRE_HORIZONTAL); - - auto *logo = new wxStaticBitmap(this, wxID_ANY, wxBitmap(GUI::from_u8(Slic3r::var("Slic3r_192px.png")), wxBITMAP_TYPE_PNG)); - - topsizer->Add(logo, 0, wxALL, BORDER); - topsizer->Add(sizer, 0, wxALL, BORDER); - - SetSizerAndFit(topsizer); - } - - bool disable_version_check() const { return cbox->GetValue(); } -}; - struct Update { fs::path source; fs::path target; Version version; - Update(fs::path &&source, const fs::path &target, const Version &version) : - source(source), + Update(fs::path &&source, fs::path &&target, const Version &version) : + source(std::move(source)), target(std::move(target)), version(version) {} - Update(fs::path &&source, fs::path &&target) : - source(source), - target(std::move(target)) - {} + std::string name() const { return source.stem().string(); } - std::string name() { return source.stem().string(); } - - friend std::ostream& operator<<(std::ostream& os , const Update &update) { - os << "Update(" << update.source.string() << " -> " << update.target.string() << ')'; + friend std::ostream& operator<<(std::ostream& os , const Update &self) { + os << "Update(" << self.source.string() << " -> " << self.target.string() << ')'; return os; } }; -typedef std::vector Updates; +struct Incompat +{ + fs::path bundle; + Version version; + + Incompat(fs::path &&bundle, const Version &version) : + bundle(std::move(bundle)), + version(version) + {} + + std::string name() const { return bundle.stem().string(); } + + friend std::ostream& operator<<(std::ostream& os , const Incompat &self) { + os << "Incompat(" << self.bundle.string() << ')'; + return os; + } +}; + +struct Updates +{ + std::vector incompats; + std::vector updates; +}; struct PresetUpdater::priv @@ -206,7 +160,7 @@ bool PresetUpdater::priv::get_file(const std::string &url, const fs::path &targe BOOST_LOG_TRIVIAL(error) << boost::format("Error getting: `%1%`: HTTP %2%, %3%") % url % http_status - % body; + % error; }) .on_complete([&](std::string body, unsigned http_status) { fs::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc); @@ -248,7 +202,7 @@ void PresetUpdater::priv::sync_version() const BOOST_LOG_TRIVIAL(error) << boost::format("Error getting: `%1%`: HTTP %2%, %3%") % version_check_url % http_status - % body; + % error; }) .on_complete([&](std::string body, unsigned http_status) { boost::trim(body); @@ -354,7 +308,7 @@ Updates PresetUpdater::priv::get_config_updates() const BOOST_LOG_TRIVIAL(info) << "Checking for cached configuration updates..."; for (const auto idx : index_db) { - const auto bundle_path = vendor_path / (idx.vendor() + ".ini"); + auto bundle_path = vendor_path / (idx.vendor() + ".ini"); if (! fs::exists(bundle_path)) { BOOST_LOG_TRIVIAL(info) << "Bundle not present for index, skipping: " << idx.vendor(); @@ -377,14 +331,12 @@ Updates PresetUpdater::priv::get_config_updates() const BOOST_LOG_TRIVIAL(debug) << boost::format("Vendor: %1%, version installed: %2%, version cached: %3%") % vp.name - % recommended->config_version.to_string() - % ver_current->config_version.to_string(); + % ver_current->config_version.to_string() + % recommended->config_version.to_string(); if (! ver_current->is_current_slic3r_supported()) { BOOST_LOG_TRIVIAL(warning) << "Current Slic3r incompatible with installed bundle: " << bundle_path.string(); - - // TODO: Downgrade situation - + updates.incompats.emplace_back(std::move(bundle_path), *ver_current); } else if (recommended->config_version > ver_current->config_version) { // Config bundle update situation @@ -406,7 +358,7 @@ Updates PresetUpdater::priv::get_config_updates() const const auto cached_vp = VendorProfile::from_ini(path_in_cache, false); if (cached_vp.config_version == recommended->config_version) { - updates.emplace_back(std::move(path_in_cache), bundle_path, *recommended); + updates.updates.emplace_back(std::move(path_in_cache), std::move(bundle_path), *recommended); } } } @@ -416,28 +368,43 @@ Updates PresetUpdater::priv::get_config_updates() const void PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) const { - BOOST_LOG_TRIVIAL(info) << boost::format("Performing %1% updates") % updates.size(); + if (updates.incompats.size() > 0) { + if (snapshot) { + BOOST_LOG_TRIVIAL(info) << "Taking a snapshot..."; + SnapshotDB::singleton().take_snapshot(*GUI::get_app_config(), Snapshot::SNAPSHOT_DOWNGRADE); + } - if (snapshot) { - BOOST_LOG_TRIVIAL(info) << "Taking a snapshot..."; - SnapshotDB::singleton().take_snapshot(*GUI::get_app_config(), Snapshot::SNAPSHOT_UPGRADE); + BOOST_LOG_TRIVIAL(info) << boost::format("Deleting %1% incompatible bundles") % updates.incompats.size(); + + for (const auto &incompat : updates.incompats) { + BOOST_LOG_TRIVIAL(info) << '\t' << incompat; + fs::remove(incompat.bundle); + } } + else if (updates.updates.size() > 0) { + if (snapshot) { + BOOST_LOG_TRIVIAL(info) << "Taking a snapshot..."; + SnapshotDB::singleton().take_snapshot(*GUI::get_app_config(), Snapshot::SNAPSHOT_UPGRADE); + } - for (const auto &update : updates) { - BOOST_LOG_TRIVIAL(info) << '\t' << update; + BOOST_LOG_TRIVIAL(info) << boost::format("Performing %1% updates") % updates.updates.size(); - fs::copy_file(update.source, update.target, fs::copy_option::overwrite_if_exists); + for (const auto &update : updates.updates) { + BOOST_LOG_TRIVIAL(info) << '\t' << update; - PresetBundle bundle; - bundle.load_configbundle(update.target.string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM); + fs::copy_file(update.source, update.target, fs::copy_option::overwrite_if_exists); - auto preset_remover = [](const Preset &preset) { - fs::remove(preset.file); - }; + PresetBundle bundle; + bundle.load_configbundle(update.target.string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM); - for (const auto &preset : bundle.prints) { preset_remover(preset); } - for (const auto &preset : bundle.filaments) { preset_remover(preset); } - for (const auto &preset : bundle.printers) { preset_remover(preset); } + auto preset_remover = [](const Preset &preset) { + fs::remove(preset.file); + }; + + for (const auto &preset : bundle.prints) { preset_remover(preset); } + for (const auto &preset : bundle.filaments) { preset_remover(preset); } + for (const auto &preset : bundle.printers) { preset_remover(preset); } + } } } @@ -497,7 +464,7 @@ void PresetUpdater::slic3r_update_notify() if (ver_online) { // Only display the notification if the version available online is newer AND if we haven't seen it before if (*ver_online > *ver_slic3r && (! ver_online_seen || *ver_online_seen < *ver_online)) { - UpdateNotification notification(*ver_slic3r, *ver_online); + GUI::MsgUpdateSlic3r notification(*ver_slic3r, *ver_online); notification.ShowModal(); if (notification.disable_version_check()) { app_config->set("version_check", "0"); @@ -508,32 +475,55 @@ void PresetUpdater::slic3r_update_notify() } } -void PresetUpdater::config_update() const +bool PresetUpdater::config_update() const { - if (! p->enabled_config_update) { return; } + if (! p->enabled_config_update) { return true; } auto updates = p->get_config_updates(); - if (updates.size() > 0) { - BOOST_LOG_TRIVIAL(info) << boost::format("Update of %1% bundles available. Asking for confirmation ...") % updates.size(); + if (updates.incompats.size() > 0) { + BOOST_LOG_TRIVIAL(info) << boost::format("%1% bundles incompatible. Asking for action...") % updates.incompats.size(); - const auto msg = _(L("Configuration update is available. Would you like to install it?")); - - auto ext_msg = _(L( - "Note that a full configuration snapshot will be created first. It can then be restored at any time " - "should there be a problem with the new version.\n\n" - "Updated configuration bundles:\n" - )); - - for (const auto &update : updates) { - ext_msg += update.target.stem().string() + " " + update.version.config_version.to_string(); - if (! update.version.comment.empty()) { - ext_msg += std::string(" (") + update.version.comment + ")"; - } - ext_msg += "\n"; + std::unordered_map incompats_map; + for (const auto &incompat : updates.incompats) { + auto vendor = incompat.name(); + auto restrictions = wxString::Format(_(L("requires min. %s and max. %s")), + incompat.version.min_slic3r_version.to_string(), + incompat.version.max_slic3r_version.to_string() + ); + incompats_map.emplace(std::move(vendor), std::move(restrictions)); } - wxMessageDialog dlg(NULL, msg, _(L("Configuration update")), wxYES_NO|wxCENTRE); - dlg.SetExtendedMessage(ext_msg); + GUI::MsgDataIncompatible dlg(std::move(incompats_map)); + const auto res = dlg.ShowModal(); + if (res == wxID_REPLACE) { + BOOST_LOG_TRIVIAL(info) << "User wants to re-configure..."; + p->perform_updates(std::move(updates)); + GUI::ConfigWizard wizard(nullptr, GUI::ConfigWizard::RR_DATA_INCOMPAT); + if (wizard.run(GUI::get_preset_bundle(), this)) { + p->had_config_update = true; + } else { + return false; + } + } else { + BOOST_LOG_TRIVIAL(info) << "User wants to exit Slic3r, bye..."; + return false; + } + } + else if (updates.updates.size() > 0) { + BOOST_LOG_TRIVIAL(info) << boost::format("Update of %1% bundles available. Asking for confirmation ...") % updates.updates.size(); + + std::unordered_map updates_map; + for (const auto &update : updates.updates) { + auto vendor = update.name(); + auto ver_str = update.version.config_version.to_string(); + if (! update.version.comment.empty()) { + ver_str += std::string(" (") + update.version.comment + ")"; + } + updates_map.emplace(std::move(vendor), std::move(ver_str)); + } + + GUI::MsgUpdateConfig dlg(std::move(updates_map)); + const auto res = dlg.ShowModal(); if (res == wxID_YES) { BOOST_LOG_TRIVIAL(debug) << "User agreed to perform the update"; @@ -546,9 +536,11 @@ void PresetUpdater::config_update() const } else { BOOST_LOG_TRIVIAL(info) << "No configuration updates available."; } + + return true; } -void PresetUpdater::install_bundles_rsrc(std::vector bundles, bool snapshot) +void PresetUpdater::install_bundles_rsrc(std::vector bundles, bool snapshot) const { Updates updates; @@ -557,7 +549,7 @@ void PresetUpdater::install_bundles_rsrc(std::vector bundles, bool for (const auto &bundle : bundles) { auto path_in_rsrc = p->rsrc_path / bundle; auto path_in_vendors = p->vendor_path / bundle; - updates.emplace_back(std::move(path_in_rsrc), std::move(path_in_vendors)); + updates.updates.emplace_back(std::move(path_in_rsrc), std::move(path_in_vendors), Version()); } p->perform_updates(std::move(updates), snapshot); diff --git a/xs/src/slic3r/Utils/PresetUpdater.hpp b/xs/src/slic3r/Utils/PresetUpdater.hpp index 287f20652..6a53cca81 100644 --- a/xs/src/slic3r/Utils/PresetUpdater.hpp +++ b/xs/src/slic3r/Utils/PresetUpdater.hpp @@ -27,10 +27,11 @@ public: void slic3r_update_notify(); // If updating is enabled, check if updates are available in cache, if so, ask about installation. - void config_update() const; + // A false return value implies Slic3r should exit due to incompatibility of configuration. + bool config_update() const; // "Update" a list of bundles from resources (behaves like an online update). - void install_bundles_rsrc(std::vector bundles, bool snapshot = true); + void install_bundles_rsrc(std::vector bundles, bool snapshot = true) const; private: struct priv; std::unique_ptr p; diff --git a/xs/xsp/GUI.xsp b/xs/xsp/GUI.xsp index 0d9f0b62e..ca90c54f2 100644 --- a/xs/xsp/GUI.xsp +++ b/xs/xsp/GUI.xsp @@ -60,10 +60,10 @@ void set_app_config(AppConfig *app_config) bool check_unsaved_changes() %code%{ RETVAL=Slic3r::GUI::check_unsaved_changes(); %}; -void config_wizard_startup(int app_config_exists) +bool config_wizard_startup(int app_config_exists) %code%{ try { - Slic3r::GUI::config_wizard_startup(app_config_exists != 0); + RETVAL=Slic3r::GUI::config_wizard_startup(app_config_exists != 0); } catch (std::exception& e) { croak("%s\n", e.what()); } diff --git a/xs/xsp/Utils_PresetUpdater.xsp b/xs/xsp/Utils_PresetUpdater.xsp index 53c3aa985..dc874acab 100644 --- a/xs/xsp/Utils_PresetUpdater.xsp +++ b/xs/xsp/Utils_PresetUpdater.xsp @@ -9,5 +9,5 @@ PresetUpdater(int version_online_event); void sync(PresetBundle* preset_bundle); void slic3r_update_notify(); - void config_update(); + bool config_update(); };