PresetUpdater: Notify about Slic3r updates

This commit is contained in:
Vojtech Kral 2018-04-17 16:59:53 +02:00
parent 6286c9ee7c
commit df03b8e4e8
11 changed files with 119 additions and 87 deletions

View file

@ -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.

View file

@ -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();

View file

@ -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();

View file

@ -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);

View file

@ -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)

View file

@ -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);

View file

@ -14,7 +14,15 @@
#include <wx/app.h>
#include <wx/event.h>
#include <wx/msgdlg.h>
#include <wx/dialog.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/button.h>
#include <wx/hyperlink.h>
#include <wx/statbmp.h>
#include <wx/checkbox.h>
#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<std::string> &&bundles)
void PresetUpdater::install_bundles_rsrc(std::vector<std::string> &&bundles)
{
Updates updates;
@ -377,7 +463,7 @@ void PresetUpdater::install_bundles_rsrc(AppConfig *app_config, std::vector<std:
updates.emplace_back(std::move(path_in_rsrc), std::move(path_in_vendors));
}
p->perform_updates(app_config, std::move(updates));
p->perform_updates(std::move(updates));
}

View file

@ -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<std::string> &&bundles);
void sync(PresetBundle *preset_bundle);
void slic3r_update_notify();
void config_update() const;
void install_bundles_rsrc(std::vector<std::string> &&bundles);
private:
struct priv;
std::unique_ptr<priv> p;

View file

@ -43,5 +43,4 @@
void update_last_output_dir(char *dir);
void reset_selections();
bool slic3r_update_avail() const;
};

View file

@ -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 {

View file

@ -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();
};