From df03b8e4e891918b95d9accad90c2e071ce088dd Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 17 Apr 2018 16:59:53 +0200 Subject: [PATCH] PresetUpdater: Notify about Slic3r updates --- lib/Slic3r/GUI.pm | 11 ++- xs/src/slic3r/GUI/AppConfig.cpp | 29 +------ xs/src/slic3r/GUI/AppConfig.hpp | 6 -- xs/src/slic3r/GUI/ConfigWizard.cpp | 2 +- xs/src/slic3r/GUI/PresetBundle.cpp | 13 --- xs/src/slic3r/GUI/PresetBundle.hpp | 4 - xs/src/slic3r/Utils/PresetUpdater.cpp | 116 ++++++++++++++++++++++---- xs/src/slic3r/Utils/PresetUpdater.hpp | 9 +- xs/xsp/GUI_AppConfig.xsp | 1 - xs/xsp/GUI_Preset.xsp | 8 -- xs/xsp/Utils_PresetUpdater.xsp | 7 +- 11 files changed, 119 insertions(+), 87 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 473fc6b90..5ff8fdde1 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -87,6 +87,7 @@ sub OnInit { $self->{app_config} = Slic3r::GUI::AppConfig->new; $self->{preset_bundle} = Slic3r::GUI::PresetBundle->new; + Slic3r::GUI::set_app_config($self->{app_config}); # 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 @@ -102,16 +103,18 @@ sub OnInit { $self->{app_config}->save; # my $version_check = $self->{app_config}->get('version_check'); - $self->{preset_updater} = Slic3r::PresetUpdater->new($VERSION_ONLINE_EVENT, $self->{app_config}); + $self->{preset_updater} = Slic3r::PresetUpdater->new($VERSION_ONLINE_EVENT); Slic3r::GUI::set_preset_updater($self->{preset_updater}); - eval { $self->{preset_updater}->config_update($self->{app_config}) }; + eval { + $self->{preset_updater}->slic3r_update_notify(); + $self->{preset_updater}->config_update(); + }; if ($@) { warn $@ . "\n"; fatal_error(undef, $@); } # my $slic3r_update = $self->{app_config}->slic3r_update_avail; - Slic3r::GUI::set_app_config($self->{app_config}); Slic3r::GUI::load_language(); # Suppress the '- default -' presets. @@ -150,7 +153,7 @@ sub OnInit { Slic3r::GUI::config_wizard_startup($app_conf_exists); # TODO: call periodically? - $self->{preset_updater}->sync($self->{app_config}, $self->{preset_bundle}); + $self->{preset_updater}->sync($self->{preset_bundle}); }); # The following event is emited by the C++ menu implementation of application language change. diff --git a/xs/src/slic3r/GUI/AppConfig.cpp b/xs/src/slic3r/GUI/AppConfig.cpp index 5104078b1..100b2d69b 100644 --- a/xs/src/slic3r/GUI/AppConfig.cpp +++ b/xs/src/slic3r/GUI/AppConfig.cpp @@ -51,7 +51,7 @@ void AppConfig::set_defaults() set("version_check", "1"); // TODO: proper URL if (get("version_check_url").empty()) - set("version_check_url", "https://gist.githubusercontent.com/vojtechkral/4d8fd4a3b8699a01ec892c264178461c/raw/e9187c3e15ceaf1a90f29b7c43cf3ccc746140f0/slic3rPE.version"); + set("version_check_url", "https://gist.githubusercontent.com/vojtechkral/4d8fd4a3b8699a01ec892c264178461c/raw/2f05a64db19e45a7f8fe2cedeff555d544af679b/slic3rPE.version"); if (get("preset_update").empty()) set("preset_update", "1"); @@ -230,33 +230,6 @@ void AppConfig::reset_selections() } } -bool AppConfig::version_check_enabled() const -{ - return get("version_check") == "1"; -} - -bool AppConfig::slic3r_update_avail() const -{ - // FIXME: Update with Semver - // TODO: probably need to move semver to libslic3r - return version_check_enabled() && get("version_online") != SLIC3R_VERSION; -} - -Semver AppConfig::get_slic3r_version() const -{ - auto res = Semver::parse(get("version")); - if (! res) { - throw std::runtime_error(std::string("Could not parse Slic3r version string in application config.")); - } else { - return *res; - } -} - -void AppConfig::set_slic3r_version(const Semver &version) -{ - set("version", version.to_string()); -} - std::string AppConfig::config_path() { return (boost::filesystem::path(Slic3r::data_dir()) / "slic3r.ini").make_preferred().string(); diff --git a/xs/src/slic3r/GUI/AppConfig.hpp b/xs/src/slic3r/GUI/AppConfig.hpp index 88ba0a662..6dcfec046 100644 --- a/xs/src/slic3r/GUI/AppConfig.hpp +++ b/xs/src/slic3r/GUI/AppConfig.hpp @@ -90,12 +90,6 @@ public: // the first non-default preset when called. void reset_selections(); - // Whether the Slic3r version available online differs from this one - bool version_check_enabled() const; - bool slic3r_update_avail() const; - Semver get_slic3r_version() const; - void set_slic3r_version(const Semver &version); - // Get the default config path from Slic3r::data_dir(). static std::string config_path(); diff --git a/xs/src/slic3r/GUI/ConfigWizard.cpp b/xs/src/slic3r/GUI/ConfigWizard.cpp index 00f8399e6..c4ca7a886 100644 --- a/xs/src/slic3r/GUI/ConfigWizard.cpp +++ b/xs/src/slic3r/GUI/ConfigWizard.cpp @@ -721,7 +721,7 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese install_bundles.emplace_back(vendor_rsrc.second); } if (install_bundles.size() > 0) { - updater->install_bundles_rsrc(app_config, std::move(install_bundles)); + updater->install_bundles_rsrc(std::move(install_bundles)); } app_config->set_vendors(appconfig_vendors); diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index beec4fe07..6f0754a03 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -695,19 +695,6 @@ static void flatten_configbundle_hierarchy(boost::property_tree::ptree &tree) flatten_configbundle_hierarchy(tree, "printer"); } -// Load a config bundle file, into presets and store the loaded presets into separate files -// of the local configuration directory. -void PresetBundle::install_vendor_configbundle(const std::string &src_path0) -{ - boost::filesystem::path src_path(src_path0); - install_vendor_configbundle(src_path); -} - -void PresetBundle::install_vendor_configbundle(const boost::filesystem::path &src_path) -{ - boost::filesystem::copy_file(src_path, (boost::filesystem::path(data_dir()) / "vendor" / src_path.filename()).make_preferred(), boost::filesystem::copy_option::overwrite_if_exists); -} - // Load a config bundle file, into presets and store the loaded presets into separate files // of the local configuration directory. size_t PresetBundle::load_configbundle(const std::string &path, unsigned int flags) diff --git a/xs/src/slic3r/GUI/PresetBundle.hpp b/xs/src/slic3r/GUI/PresetBundle.hpp index 651b95701..27add21ee 100644 --- a/xs/src/slic3r/GUI/PresetBundle.hpp +++ b/xs/src/slic3r/GUI/PresetBundle.hpp @@ -92,10 +92,6 @@ public: // Load the config bundle, store it to the user profile directory by default. size_t load_configbundle(const std::string &path, unsigned int flags = LOAD_CFGBNDLE_SAVE); - // Install the Vendor specific config bundle into user's directory. - void install_vendor_configbundle(const std::string &src_path); - static void install_vendor_configbundle(const boost::filesystem::path &src_path); - // Export a config bundle file containing all the presets and the names of the active presets. void export_configbundle(const std::string &path); // , const DynamicPrintConfig &settings); diff --git a/xs/src/slic3r/Utils/PresetUpdater.cpp b/xs/src/slic3r/Utils/PresetUpdater.cpp index 939be863c..439a619c6 100644 --- a/xs/src/slic3r/Utils/PresetUpdater.cpp +++ b/xs/src/slic3r/Utils/PresetUpdater.cpp @@ -14,7 +14,15 @@ #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" @@ -40,6 +48,63 @@ static const char *INDEX_FILENAME = "index.idx"; static const char *TMP_EXTENSION = ".download"; +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 versions 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; @@ -79,7 +144,7 @@ struct PresetUpdater::priv bool cancel; std::thread thread; - priv(int event, AppConfig *app_config); + priv(int version_online_event); void set_download_prefs(AppConfig *app_config); bool get_file(const std::string &url, const fs::path &target_path) const; @@ -89,17 +154,17 @@ struct PresetUpdater::priv void check_install_indices() const; Updates config_update() const; - void perform_updates(AppConfig *app_config, Updates &&updates) const; + void perform_updates(Updates &&updates) const; }; -PresetUpdater::priv::priv(int event, AppConfig *app_config) : - version_online_event(event), +PresetUpdater::priv::priv(int version_online_event) : + version_online_event(version_online_event), cache_path(fs::path(Slic3r::data_dir()) / "cache"), rsrc_path(fs::path(resources_dir()) / "profiles"), vendor_path(fs::path(Slic3r::data_dir()) / "vendor"), cancel(false) { - set_download_prefs(app_config); + set_download_prefs(GUI::get_app_config()); check_install_indices(); index_db = std::move(Index::load_db()); } @@ -281,9 +346,9 @@ Updates PresetUpdater::priv::config_update() const return updates; } -void PresetUpdater::priv::perform_updates(AppConfig *app_config, Updates &&updates) const +void PresetUpdater::priv::perform_updates(Updates &&updates) const { - SnapshotDB::singleton().take_snapshot(*app_config, Snapshot::SNAPSHOT_UPGRADE); + SnapshotDB::singleton().take_snapshot(*GUI::get_app_config(), Snapshot::SNAPSHOT_UPGRADE); for (const auto &update : updates) { fs::copy_file(update.source, update.target, fs::copy_option::overwrite_if_exists); @@ -302,8 +367,8 @@ void PresetUpdater::priv::perform_updates(AppConfig *app_config, Updates &&updat } -PresetUpdater::PresetUpdater(int version_online_event, AppConfig *app_config) : - p(new priv(version_online_event, app_config)) +PresetUpdater::PresetUpdater(int version_online_event) : + p(new priv(version_online_event)) {} @@ -317,9 +382,9 @@ PresetUpdater::~PresetUpdater() } } -void PresetUpdater::sync(AppConfig *app_config, PresetBundle *preset_bundle) +void PresetUpdater::sync(PresetBundle *preset_bundle) { - p->set_download_prefs(app_config); + p->set_download_prefs(GUI::get_app_config()); if (!p->enabled_version_check && !p->enabled_config_update) { return; } // Copy the whole vendors data for use in the background thread @@ -334,7 +399,28 @@ void PresetUpdater::sync(AppConfig *app_config, PresetBundle *preset_bundle) })); } -void PresetUpdater::config_update(AppConfig *app_config) +void PresetUpdater::slic3r_update_notify() +{ + if (! p->enabled_version_check) { return; } + + auto* app_config = GUI::get_app_config(); + const auto ver_slic3r = Semver::parse(SLIC3R_VERSION); + const auto ver_online = Semver::parse(app_config->get("version_online")); + if (! ver_slic3r) { + throw std::runtime_error("Could not parse Slic3r version string: " SLIC3R_VERSION); + } + + if (ver_online && *ver_online > *ver_slic3r) { + UpdateNotification notification(*ver_slic3r, *ver_online); + notification.ShowModal(); + if (notification.disable_version_check()) { + app_config->set("version_check", "0"); + p->enabled_version_check = false; + } + } +} + +void PresetUpdater::config_update() const { if (! p->enabled_config_update) { return; } @@ -362,12 +448,12 @@ void PresetUpdater::config_update(AppConfig *app_config) std::cerr << "After modal" << std::endl; if (res == wxID_YES) { // User gave clearance, updates are go - p->perform_updates(app_config, std::move(updates)); + p->perform_updates(std::move(updates)); } } } -void PresetUpdater::install_bundles_rsrc(AppConfig *app_config, std::vector &&bundles) +void PresetUpdater::install_bundles_rsrc(std::vector &&bundles) { Updates updates; @@ -377,7 +463,7 @@ void PresetUpdater::install_bundles_rsrc(AppConfig *app_config, std::vectorperform_updates(app_config, std::move(updates)); + p->perform_updates(std::move(updates)); } diff --git a/xs/src/slic3r/Utils/PresetUpdater.hpp b/xs/src/slic3r/Utils/PresetUpdater.hpp index 1499570db..a53ed86eb 100644 --- a/xs/src/slic3r/Utils/PresetUpdater.hpp +++ b/xs/src/slic3r/Utils/PresetUpdater.hpp @@ -13,16 +13,17 @@ class PresetBundle; class PresetUpdater { public: - PresetUpdater(int version_online_event, AppConfig *app_config); + PresetUpdater(int version_online_event); PresetUpdater(PresetUpdater &&) = delete; PresetUpdater(const PresetUpdater &) = delete; PresetUpdater &operator=(PresetUpdater &&) = delete; PresetUpdater &operator=(const PresetUpdater &) = delete; ~PresetUpdater(); - void sync(AppConfig *app_config, PresetBundle *preset_bundle); - void config_update(AppConfig *app_config); - void install_bundles_rsrc(AppConfig *app_config, std::vector &&bundles); + void sync(PresetBundle *preset_bundle); + void slic3r_update_notify(); + void config_update() const; + void install_bundles_rsrc(std::vector &&bundles); private: struct priv; std::unique_ptr p; diff --git a/xs/xsp/GUI_AppConfig.xsp b/xs/xsp/GUI_AppConfig.xsp index de0e5a22b..08a88883d 100644 --- a/xs/xsp/GUI_AppConfig.xsp +++ b/xs/xsp/GUI_AppConfig.xsp @@ -43,5 +43,4 @@ void update_last_output_dir(char *dir); void reset_selections(); - bool slic3r_update_avail() const; }; diff --git a/xs/xsp/GUI_Preset.xsp b/xs/xsp/GUI_Preset.xsp index ecf6f5a22..2c63db10c 100644 --- a/xs/xsp/GUI_Preset.xsp +++ b/xs/xsp/GUI_Preset.xsp @@ -117,14 +117,6 @@ PresetCollection::arrayref() croak("Loading of a config bundle %s failed:\n%s\n", path, e.what()); } %}; - void install_vendor_configbundle(const char *path) - %code%{ - try { - THIS->install_vendor_configbundle(std::string(path)); - } catch (std::exception& e) { - croak("Installing a vendor config bundle %s failed:\n%s\n", path, e.what()); - } - %}; void export_configbundle(char *path) %code%{ try { diff --git a/xs/xsp/Utils_PresetUpdater.xsp b/xs/xsp/Utils_PresetUpdater.xsp index 3a4d55a01..53c3aa985 100644 --- a/xs/xsp/Utils_PresetUpdater.xsp +++ b/xs/xsp/Utils_PresetUpdater.xsp @@ -6,7 +6,8 @@ %} %name{Slic3r::PresetUpdater} class PresetUpdater { - PresetUpdater(int version_online_event, AppConfig *app_config); - void sync(AppConfig *app_config, PresetBundle* preset_bundle); - void config_update(AppConfig *app_config); + PresetUpdater(int version_online_event); + void sync(PresetBundle* preset_bundle); + void slic3r_update_notify(); + void config_update(); };