Updating: Detect legacy datadir, remove conflicting presets

This commit is contained in:
Vojtech Kral 2018-04-16 16:52:11 +02:00
parent 7dbb2ed6a3
commit c733e3151b
16 changed files with 232 additions and 96 deletions

View File

@ -95,14 +95,15 @@ sub OnInit {
warn $@ . "\n"; warn $@ . "\n";
fatal_error(undef, $@); fatal_error(undef, $@);
} }
my $run_wizard = ! $self->{app_config}->exists; my $app_conf_exists = $self->{app_config}->exists;
# load settings # load settings
$self->{app_config}->load if ! $run_wizard; $self->{app_config}->load if $app_conf_exists;
$self->{app_config}->set('version', $Slic3r::VERSION); $self->{app_config}->set('version', $Slic3r::VERSION);
$self->{app_config}->save; $self->{app_config}->save;
# my $version_check = $self->{app_config}->get('version_check'); # 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, $self->{app_config});
Slic3r::GUI::set_preset_updater($self->{preset_updater});
eval { $self->{preset_updater}->config_update($self->{app_config}) }; eval { $self->{preset_updater}->config_update($self->{app_config}) };
if ($@) { if ($@) {
warn $@ . "\n"; warn $@ . "\n";
@ -120,8 +121,6 @@ sub OnInit {
warn $@ . "\n"; warn $@ . "\n";
show_error(undef, $@); show_error(undef, $@);
} }
# TODO: check previously downloaded updates
$run_wizard = 1 if $self->{preset_bundle}->has_defauls_only;
Slic3r::GUI::set_preset_bundle($self->{preset_bundle}); Slic3r::GUI::set_preset_bundle($self->{preset_bundle});
@ -148,15 +147,7 @@ sub OnInit {
# On OSX the UI was not initialized correctly if the wizard was called # On OSX the UI was not initialized correctly if the wizard was called
# before the UI was up and running. # before the UI was up and running.
$self->CallAfter(sub { $self->CallAfter(sub {
# XXX: recreate_GUI ??? Slic3r::GUI::config_wizard_startup($app_conf_exists);
# if ($slic3r_update) {
# # TODO
# }
# XXX: ?
if ($run_wizard) {
# Run the config wizard, don't offer the "reset user profile" checkbox.
Slic3r::GUI::config_wizard(1);
}
# TODO: call periodically? # TODO: call periodically?
$self->{preset_updater}->sync($self->{app_config}, $self->{preset_bundle}); $self->{preset_updater}->sync($self->{app_config}, $self->{preset_bundle});
@ -209,15 +200,12 @@ sub recreate_GUI{
$self->{app_config}->save if $self->{app_config}->dirty; $self->{app_config}->save if $self->{app_config}->dirty;
}); });
my $run_wizard = 1 if $self->{preset_bundle}->has_defauls_only; # On OSX the UI was not initialized correctly if the wizard was called
if ($run_wizard) { # before the UI was up and running.
# On OSX the UI was not initialized correctly if the wizard was called $self->CallAfter(sub {
# before the UI was up and running. # Run the config wizard, don't offer the "reset user profile" checkbox.
$self->CallAfter(sub { Slic3r::GUI::config_wizard_startup(1);
# Run the config wizard, don't offer the "reset user profile" checkbox. });
Slic3r::GUI::config_wizard(1);
});
}
} }
sub system_info { sub system_info {

View File

@ -14,7 +14,7 @@
#include <boost/thread.hpp> #include <boost/thread.hpp>
#define SLIC3R_FORK_NAME "Slic3r Prusa Edition" #define SLIC3R_FORK_NAME "Slic3r Prusa Edition"
#define SLIC3R_VERSION "1.39.0" #define SLIC3R_VERSION "1.40.0"
#define SLIC3R_BUILD "UNKNOWN" #define SLIC3R_BUILD "UNKNOWN"
typedef int32_t coord_t; typedef int32_t coord_t;

View File

@ -97,7 +97,7 @@ public:
// Create a snapshot directory, copy the vendor config bundles, user print/filament/printer profiles, // Create a snapshot directory, copy the vendor config bundles, user print/filament/printer profiles,
// create an index. // create an index.
const Snapshot& take_snapshot(const AppConfig &app_config, Snapshot::Reason reason, const std::string &comment); const Snapshot& take_snapshot(const AppConfig &app_config, Snapshot::Reason reason, const std::string &comment = "");
void restore_snapshot(const std::string &id, AppConfig &app_config); void restore_snapshot(const std::string &id, AppConfig &app_config);
void restore_snapshot(const Snapshot &snapshot, AppConfig &app_config); void restore_snapshot(const Snapshot &snapshot, AppConfig &app_config);

View File

@ -98,6 +98,10 @@ void AppConfig::load()
} }
} }
// Figure out if datadir has legacy presets
auto ini_ver = Semver::parse(get("version"));
m_legacy_datadir = ini_ver ? *ini_ver < Semver(1, 40, 0) : true;
// Override missing or keys with their defaults. // Override missing or keys with their defaults.
this->set_defaults(); this->set_defaults();
m_dirty = false; m_dirty = false;
@ -240,7 +244,6 @@ bool AppConfig::slic3r_update_avail() const
Semver AppConfig::get_slic3r_version() const Semver AppConfig::get_slic3r_version() const
{ {
// TODO: move to Semver c-tor (???)
auto res = Semver::parse(get("version")); auto res = Semver::parse(get("version"));
if (! res) { if (! res) {
throw std::runtime_error(std::string("Could not parse Slic3r version string in application config.")); throw std::runtime_error(std::string("Could not parse Slic3r version string in application config."));

View File

@ -13,7 +13,7 @@ namespace Slic3r {
class AppConfig class AppConfig
{ {
public: public:
AppConfig() : m_dirty(false) { this->reset(); } AppConfig() : m_dirty(false), m_legacy_datadir(false) { this->reset(); }
// Clear and reset to defaults. // Clear and reset to defaults.
void reset(); void reset();
@ -99,6 +99,8 @@ public:
// Get the default config path from Slic3r::data_dir(). // Get the default config path from Slic3r::data_dir().
static std::string config_path(); static std::string config_path();
bool legacy_datadir() const { return m_legacy_datadir; }
// Does the config file exist? // Does the config file exist?
static bool exists(); static bool exists();
@ -109,6 +111,8 @@ private:
VendorMap m_vendors; VendorMap m_vendors;
// Has any value been modified since the config.ini has been last saved or loaded? // Has any value been modified since the config.ini has been last saved or loaded?
bool m_dirty; bool m_dirty;
// Whether the existing version is before system profiles & configuration updating
bool m_legacy_datadir;
}; };
}; // namespace Slic3r }; // namespace Slic3r

View File

@ -1,8 +1,8 @@
#include "ConfigWizard_private.hpp" #include "ConfigWizard_private.hpp"
#include <iostream> // XXX
#include <algorithm> #include <algorithm>
#include <utility> #include <utility>
#include <unordered_map>
#include <wx/settings.h> #include <wx/settings.h>
#include <wx/stattext.h> #include <wx/stattext.h>
@ -17,6 +17,7 @@
#include "GUI.hpp" #include "GUI.hpp"
#include "slic3r/Utils/PresetUpdater.hpp" #include "slic3r/Utils/PresetUpdater.hpp"
// TODO: Wizard vs Assistant
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
@ -54,48 +55,80 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, cons
const auto vendor_id = vendor.id; const auto vendor_id = vendor.id;
const auto &models = vendor.models; const auto &models = vendor.models;
auto *sizer = new wxBoxSizer(wxVERTICAL);
auto *printer_grid = new wxFlexGridSizer(models.size(), 0, 20); auto *printer_grid = new wxFlexGridSizer(models.size(), 0, 20);
printer_grid->SetFlexibleDirection(wxVERTICAL); printer_grid->SetFlexibleDirection(wxVERTICAL);
SetSizer(printer_grid); sizer->Add(printer_grid);
auto namefont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); auto namefont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
namefont.SetWeight(wxFONTWEIGHT_BOLD); namefont.SetWeight(wxFONTWEIGHT_BOLD);
for (const auto &model : models) { for (const auto &model : models) {
auto *panel = new wxPanel(this); auto *panel = new wxPanel(this);
auto *sizer = new wxBoxSizer(wxVERTICAL); auto *col_sizer = new wxBoxSizer(wxVERTICAL);
panel->SetSizer(sizer); panel->SetSizer(col_sizer);
auto *title = new wxStaticText(panel, wxID_ANY, model.name, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); auto *title = new wxStaticText(panel, wxID_ANY, model.name, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
title->SetFont(namefont); title->SetFont(namefont);
sizer->Add(title, 0, wxBOTTOM, 3); col_sizer->Add(title, 0, wxBOTTOM, 3);
auto bitmap_file = wxString::Format("printers/%s_%s.png", vendor.id, model.id); auto bitmap_file = wxString::Format("printers/%s_%s.png", vendor.id, model.id);
wxBitmap bitmap(GUI::from_u8(Slic3r::var(bitmap_file.ToStdString())), wxBITMAP_TYPE_PNG); wxBitmap bitmap(GUI::from_u8(Slic3r::var(bitmap_file.ToStdString())), wxBITMAP_TYPE_PNG);
auto *bitmap_widget = new wxStaticBitmap(panel, wxID_ANY, bitmap); auto *bitmap_widget = new wxStaticBitmap(panel, wxID_ANY, bitmap);
sizer->Add(bitmap_widget, 0, wxBOTTOM, 3); col_sizer->Add(bitmap_widget, 0, wxBOTTOM, 3);
sizer->AddSpacer(20); col_sizer->AddSpacer(20);
const auto model_id = model.id; const auto model_id = model.id;
for (const auto &variant : model.variants) { for (const auto &variant : model.variants) {
const auto variant_name = variant.name; const auto label = wxString::Format("%s %s %s", variant.name, _(L("mm")), _(L("nozzle")));
auto *cbox = new wxCheckBox(panel, wxID_ANY, wxString::Format("%s %s %s", variant.name, _(L("mm")), _(L("nozzle")))); auto *cbox = new Checkbox(panel, label, model_id, variant.name);
bool enabled = appconfig_vendors.get_variant("PrusaResearch", model_id, variant_name); const size_t idx = cboxes.size();
cboxes.push_back(cbox);
bool enabled = appconfig_vendors.get_variant("PrusaResearch", model_id, variant.name);
variants_checked += enabled; variants_checked += enabled;
cbox->SetValue(enabled); cbox->SetValue(enabled);
sizer->Add(cbox, 0, wxBOTTOM, 3); col_sizer->Add(cbox, 0, wxBOTTOM, 3);
cbox->Bind(wxEVT_CHECKBOX, [=](wxCommandEvent &event) { cbox->Bind(wxEVT_CHECKBOX, [this, idx](wxCommandEvent &event) {
this->variants_checked += event.IsChecked() ? 1 : -1; if (idx >= this->cboxes.size()) { return; }
PrinterPickerEvent evt(EVT_PRINTER_PICK, this->GetId(), std::move(vendor_id), std::move(model_id), std::move(variant_name), event.IsChecked()); this->on_checkbox(this->cboxes[idx], event.IsChecked());
this->AddPendingEvent(evt);
}); });
} }
printer_grid->Add(panel); printer_grid->Add(panel);
} }
auto *all_none_sizer = new wxBoxSizer(wxHORIZONTAL);
auto *sel_all = new wxButton(this, wxID_ANY, _(L("Select all")));
auto *sel_none = new wxButton(this, wxID_ANY, _(L("Select none")));
sel_all->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &event) { this->select_all(true); });
sel_none->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &event) { this->select_all(false); });
all_none_sizer->AddStretchSpacer();
all_none_sizer->Add(sel_all);
all_none_sizer->Add(sel_none);
sizer->AddStretchSpacer();
sizer->Add(all_none_sizer, 0, wxEXPAND);
SetSizer(sizer);
}
void PrinterPicker::select_all(bool select)
{
for (const auto &cb : cboxes) {
if (cb->GetValue() != select) {
cb->SetValue(select);
on_checkbox(cb, select);
}
}
}
void PrinterPicker::on_checkbox(const Checkbox *cbox, bool checked)
{
variants_checked += checked ? 1 : -1;
PrinterPickerEvent evt(EVT_PRINTER_PICK, GetId(), vendor_id, cbox->model, cbox->variant, checked);
AddPendingEvent(evt);
} }
@ -176,15 +209,10 @@ PageWelcome::PageWelcome(ConfigWizard *parent) :
{ {
append_text(_(L("Hello, welcome to Slic3r Prusa Edition! TODO: This text."))); append_text(_(L("Hello, welcome to Slic3r Prusa Edition! TODO: This text.")));
// const PresetBundle &bundle = wizard_p()->bundle_vendors;
// const auto &vendors = bundle.vendors;
const auto &vendors = wizard_p()->vendors; const auto &vendors = wizard_p()->vendors;
// const auto vendor_prusa = std::find(vendors.cbegin(), vendors.cend(), VendorProfile("PrusaResearch"));
const auto vendor_prusa = vendors.find("PrusaResearch"); const auto vendor_prusa = vendors.find("PrusaResearch");
if (vendor_prusa != vendors.cend()) { if (vendor_prusa != vendors.cend()) {
const auto &models = vendor_prusa->second.models;
AppConfig &appconfig_vendors = this->wizard_p()->appconfig_vendors; AppConfig &appconfig_vendors = this->wizard_p()->appconfig_vendors;
printer_picker = new PrinterPicker(this, vendor_prusa->second, appconfig_vendors); printer_picker = new PrinterPicker(this, vendor_prusa->second, appconfig_vendors);
@ -550,6 +578,17 @@ void ConfigWizardIndex::on_paint(wxPaintEvent & evt)
// priv // priv
static const std::unordered_map<std::string, std::pair<std::string, std::string>> legacy_preset_map {{
{ "Original Prusa i3 MK2.ini", std::make_pair("MK2S", "0.4") },
{ "Original Prusa i3 MK2 MM Single Mode.ini", std::make_pair("MK2S", "0.4") },
{ "Original Prusa i3 MK2 MM Single Mode 0.6 nozzle.ini", std::make_pair("MK2S", "0.6") },
{ "Original Prusa i3 MK2 MultiMaterial.ini", std::make_pair("MK2S", "0.4") },
{ "Original Prusa i3 MK2 MultiMaterial 0.6 nozzle.ini", std::make_pair("MK2S", "0.6") },
{ "Original Prusa i3 MK2 0.25 nozzle.ini", std::make_pair("MK2S", "0.25") },
{ "Original Prusa i3 MK2 0.6 nozzle.ini", std::make_pair("MK2S", "0.6") },
{ "Original Prusa i3 MK3.ini", std::make_pair("MK3", "0.4") },
}};
void ConfigWizard::priv::load_vendors() void ConfigWizard::priv::load_vendors()
{ {
const auto vendor_dir = fs::path(Slic3r::data_dir()) / "vendor"; const auto vendor_dir = fs::path(Slic3r::data_dir()) / "vendor";
@ -569,13 +608,28 @@ void ConfigWizard::priv::load_vendors()
const auto id = it->path().stem().string(); const auto id = it->path().stem().string();
if (vendors.find(id) == vendors.end()) { if (vendors.find(id) == vendors.end()) {
auto vp = VendorProfile::from_ini(it->path()); auto vp = VendorProfile::from_ini(it->path());
vendors_rsrc[vp.id] = it->path(); vendors_rsrc[vp.id] = it->path().filename().string();
vendors[vp.id] = std::move(vp); vendors[vp.id] = std::move(vp);
} }
} }
} }
appconfig_vendors.set_vendors(*GUI::get_app_config()); // Load up the set of vendors / models / variants the user has had enabled up till now
const AppConfig *app_config = GUI::get_app_config();
if (! app_config->legacy_datadir()) {
appconfig_vendors.set_vendors(*app_config);
} else {
// In case of legacy datadir, try to guess the preference based on the printer preset files that are present
const auto printer_dir = fs::path(Slic3r::data_dir()) / "printer";
for (fs::directory_iterator it(printer_dir); it != fs::directory_iterator(); ++it) {
auto needle = legacy_preset_map.find(it->path().filename().string());
if (needle == legacy_preset_map.end()) { continue; }
const auto &model = needle->second.first;
const auto &variant = needle->second.second;
appconfig_vendors.set_variant("PrusaResearch", model, variant, true);
}
}
} }
void ConfigWizard::priv::index_refresh() void ConfigWizard::priv::index_refresh()
@ -639,12 +693,15 @@ void ConfigWizard::priv::on_custom_setup()
set_page(page_firmware); set_page(page_firmware);
} }
void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *preset_bundle) void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *preset_bundle, PresetUpdater *updater)
{ {
const bool is_custom_setup = page_welcome->page_next() == page_firmware; const bool is_custom_setup = page_welcome->page_next() == page_firmware;
if (! is_custom_setup) { if (! is_custom_setup) {
const auto enabled_vendors = appconfig_vendors.vendors(); const auto enabled_vendors = appconfig_vendors.vendors();
// Install bundles from resources if needed:
std::vector<std::string> install_bundles;
for (const auto &vendor_rsrc : vendors_rsrc) { for (const auto &vendor_rsrc : vendors_rsrc) {
const auto vendor = enabled_vendors.find(vendor_rsrc.first); const auto vendor = enabled_vendors.find(vendor_rsrc.first);
if (vendor == enabled_vendors.end()) { continue; } if (vendor == enabled_vendors.end()) { continue; }
@ -654,7 +711,10 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
if (size_sum == 0) { continue; } if (size_sum == 0) { continue; }
// This vendor needs to be installed // This vendor needs to be installed
PresetBundle::install_vendor_configbundle(vendor_rsrc.second); install_bundles.emplace_back(vendor_rsrc.second);
}
if (install_bundles.size() > 0) {
updater->install_bundles_rsrc(app_config, std::move(install_bundles));
} }
app_config->set_vendors(appconfig_vendors); app_config->set_vendors(appconfig_vendors);
@ -732,14 +792,10 @@ ConfigWizard::ConfigWizard(wxWindow *parent) :
ConfigWizard::~ConfigWizard() {} ConfigWizard::~ConfigWizard() {}
bool ConfigWizard::run(wxWindow *parent, PresetBundle *preset_bundle) void ConfigWizard::run(PresetBundle *preset_bundle, PresetUpdater *updater)
{ {
ConfigWizard wizard(parent); if (ShowModal() == wxID_OK) {
if (wizard.ShowModal() == wxID_OK) { p->apply_config(GUI::get_app_config(), preset_bundle, updater);
wizard.p->apply_config(GUI::get_app_config(), preset_bundle);
return true;
} else {
return false;
} }
} }

View File

@ -8,6 +8,7 @@
namespace Slic3r { namespace Slic3r {
class PresetBundle; class PresetBundle;
class PresetUpdater;
namespace GUI { namespace GUI {
@ -22,7 +23,7 @@ public:
ConfigWizard &operator=(const ConfigWizard &) = delete; ConfigWizard &operator=(const ConfigWizard &) = delete;
~ConfigWizard(); ~ConfigWizard();
static bool run(wxWindow *parent, PresetBundle *preset_bundle); void run(PresetBundle *preset_bundle, PresetUpdater *updater);
private: private:
struct priv; struct priv;
std::unique_ptr<priv> p; std::unique_ptr<priv> p;

View File

@ -15,6 +15,7 @@
#include <wx/spinctrl.h> #include <wx/spinctrl.h>
#include "libslic3r/PrintConfig.hpp" #include "libslic3r/PrintConfig.hpp"
#include "slic3r/Utils/PresetUpdater.hpp"
#include "AppConfig.hpp" #include "AppConfig.hpp"
#include "Preset.hpp" #include "Preset.hpp"
#include "BedShapeDialog.hpp" #include "BedShapeDialog.hpp"
@ -24,8 +25,6 @@ namespace fs = boost::filesystem;
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
// typedef std::unordered_map<std::string, VendorProfile> VendorMap;
enum { enum {
CONTENT_WIDTH = 500, CONTENT_WIDTH = 500,
@ -38,9 +37,26 @@ enum {
struct PrinterPicker: wxPanel struct PrinterPicker: wxPanel
{ {
struct Checkbox : wxCheckBox
{
Checkbox(wxWindow *parent, const wxString &label, const std::string &model, const std::string &variant) :
wxCheckBox(parent, wxID_ANY, label),
model(model),
variant(variant)
{}
std::string model;
std::string variant;
};
const std::string vendor_id;
std::vector<Checkbox*> cboxes;
unsigned variants_checked; unsigned variants_checked;
PrinterPicker(wxWindow *parent, const VendorProfile &vendor, const AppConfig &appconfig_vendors); PrinterPicker(wxWindow *parent, const VendorProfile &vendor, const AppConfig &appconfig_vendors);
void select_all(bool select);
void on_checkbox(const Checkbox *cbox, bool checked);
}; };
struct ConfigWizardPage: wxPanel struct ConfigWizardPage: wxPanel
@ -174,7 +190,7 @@ struct ConfigWizard::priv
ConfigWizard *q; ConfigWizard *q;
AppConfig appconfig_vendors; // TODO: use order-preserving container AppConfig appconfig_vendors; // TODO: use order-preserving container
std::unordered_map<std::string, VendorProfile> vendors; // TODO: just set? std::unordered_map<std::string, VendorProfile> vendors; // TODO: just set?
std::unordered_map<std::string, fs::path> vendors_rsrc; std::unordered_map<std::string, std::string> vendors_rsrc;
std::unique_ptr<DynamicPrintConfig> custom_config; std::unique_ptr<DynamicPrintConfig> custom_config;
wxBoxSizer *topsizer = nullptr; wxBoxSizer *topsizer = nullptr;
@ -208,7 +224,7 @@ struct ConfigWizard::priv
void on_other_vendors(); void on_other_vendors();
void on_custom_setup(); void on_custom_setup();
void apply_config(AppConfig *app_config, PresetBundle *preset_bundle); void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, PresetUpdater *updater);
}; };

View File

@ -37,6 +37,7 @@
#include <wx/sizer.h> #include <wx/sizer.h>
#include <wx/combo.h> #include <wx/combo.h>
#include <wx/window.h> #include <wx/window.h>
#include <wx/msgdlg.h>
#include "wxExtensions.hpp" #include "wxExtensions.hpp"
@ -50,6 +51,7 @@
#include "Preferences.hpp" #include "Preferences.hpp"
#include "PresetBundle.hpp" #include "PresetBundle.hpp"
#include "../Utils/PresetUpdater.hpp"
#include "../Config/Snapshot.hpp" #include "../Config/Snapshot.hpp"
namespace Slic3r { namespace GUI { namespace Slic3r { namespace GUI {
@ -179,6 +181,7 @@ wxFrame *g_wxMainFrame = nullptr;
wxNotebook *g_wxTabPanel = nullptr; wxNotebook *g_wxTabPanel = nullptr;
AppConfig *g_AppConfig = nullptr; AppConfig *g_AppConfig = nullptr;
PresetBundle *g_PresetBundle= nullptr; PresetBundle *g_PresetBundle= nullptr;
PresetUpdater *g_PresetUpdater = nullptr;
std::vector<Tab *> g_tabs_list; std::vector<Tab *> g_tabs_list;
@ -212,6 +215,11 @@ void set_preset_bundle(PresetBundle *preset_bundle)
g_PresetBundle = preset_bundle; g_PresetBundle = preset_bundle;
} }
void set_preset_updater(PresetUpdater *updater)
{
g_PresetUpdater = updater;
}
std::vector<Tab *>& get_tabs_list() std::vector<Tab *>& get_tabs_list()
{ {
return g_tabs_list; return g_tabs_list;
@ -442,23 +450,51 @@ bool check_unsaved_changes()
return dialog->ShowModal() == wxID_YES; return dialog->ShowModal() == wxID_YES;
} }
bool config_wizard(bool fresh_start) void config_wizard_startup(bool app_config_exists)
{
if (! app_config_exists || g_PresetBundle->has_defauls_only()) {
config_wizard(true);
} else if (g_AppConfig->legacy_datadir()) {
// Looks like user has legacy pre-vendorbundle data directory,
// explain what this is and run the wizard
const auto msg = _(L("Configuration update"));
const auto ext_msg = _(L(
"Slic3r PE now uses an updated configuration structure.\n\n"
"So called 'System presets' have been introduced, which hold the built-in default settings for various "
"printers. These System presets cannot be modified, instead, users now may create their"
"own presets inheriting settings from one of the System presets.\n"
"An inheriting preset may either inherit a particular value from its parent or override it with a customized value.\n\n"
// TODO: Assistant vs Wizard
"Please proceed with the Configuration wizard that follows to set up the new presets "
"and to choose whether to enable automatic preset updates."
));
wxMessageDialog dlg(NULL, msg, _(L("Configuration update")), wxOK|wxCENTRE);
dlg.SetExtendedMessage(ext_msg);
const auto res = dlg.ShowModal();
config_wizard(true);
}
}
void config_wizard(bool fresh_start) // TODO: fresh_start useful ?
{ {
if (g_wxMainFrame == nullptr) if (g_wxMainFrame == nullptr)
throw std::runtime_error("Main frame not set"); throw std::runtime_error("Main frame not set");
// Exit wizard if there are unsaved changes and the user cancels the action. // Exit wizard if there are unsaved changes and the user cancels the action.
if (! check_unsaved_changes()) if (! check_unsaved_changes())
return false; return;
// TODO: Offer "reset user profile" ??? // TODO: Offer "reset user profile" ???
if (! ConfigWizard::run(g_wxMainFrame, g_PresetBundle)) ConfigWizard wizard(g_wxMainFrame);
return false; wizard.run(g_PresetBundle, g_PresetUpdater);
// Load the currently selected preset into the GUI, update the preset selection box. // Load the currently selected preset into the GUI, update the preset selection box.
for (Tab *tab : g_tabs_list) for (Tab *tab : g_tabs_list)
tab->load_current_preset(); tab->load_current_preset();
return true;
} }
void open_preferences_dialog(int event_preferences) void open_preferences_dialog(int event_preferences)

View File

@ -25,6 +25,7 @@ namespace Slic3r {
class PresetBundle; class PresetBundle;
class PresetCollection; class PresetCollection;
class AppConfig; class AppConfig;
class PresetUpdater;
class DynamicPrintConfig; class DynamicPrintConfig;
class TabIface; class TabIface;
@ -76,6 +77,7 @@ void set_main_frame(wxFrame *main_frame);
void set_tab_panel(wxNotebook *tab_panel); void set_tab_panel(wxNotebook *tab_panel);
void set_app_config(AppConfig *app_config); void set_app_config(AppConfig *app_config);
void set_preset_bundle(PresetBundle *preset_bundle); void set_preset_bundle(PresetBundle *preset_bundle);
void set_preset_updater(PresetUpdater *updater);
AppConfig* get_app_config(); AppConfig* get_app_config();
wxApp* get_app(); wxApp* get_app();
@ -88,8 +90,11 @@ 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. // to notify the user whether he is aware that some preset changes will be lost.
extern bool check_unsaved_changes(); extern bool check_unsaved_changes();
// Opens the first-time configuration wizard, returns true if wizard is finished & accepted. // Checks if configuration wizard needs to run, calls config_wizard if so
extern bool config_wizard(bool fresh_start); extern void config_wizard_startup(bool app_config_exists);
// Opens the configuration wizard, returns true if wizard is finished & accepted.
extern void config_wizard(bool fresh_start);
// Create "Preferences" dialog after selecting menu "Preferences" in Perl part // Create "Preferences" dialog after selecting menu "Preferences" in Perl part
extern void open_preferences_dialog(int event_preferences); extern void open_preferences_dialog(int event_preferences);

View File

@ -51,6 +51,11 @@ struct Update
version(version) version(version)
{} {}
Update(fs::path &&source, fs::path &&target) :
source(source),
target(std::move(target))
{}
std::string name() { return source.stem().string(); } std::string name() { return source.stem().string(); }
}; };
@ -83,6 +88,7 @@ struct PresetUpdater::priv
void check_install_indices() const; void check_install_indices() const;
Updates config_update() const; Updates config_update() const;
void perform_updates(AppConfig *app_config, Updates &&updates) const;
}; };
PresetUpdater::priv::priv(int event, AppConfig *app_config) : PresetUpdater::priv::priv(int event, AppConfig *app_config) :
@ -121,6 +127,7 @@ bool PresetUpdater::priv::get_file(const std::string &url, const fs::path &targe
.on_complete([&](std::string body, unsigned http_status) { .on_complete([&](std::string body, unsigned http_status) {
fs::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc); fs::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc);
file.write(body.c_str(), body.size()); file.write(body.c_str(), body.size());
file.close();
fs::rename(tmp_path, target_path); fs::rename(tmp_path, target_path);
res = true; res = true;
}) })
@ -269,6 +276,26 @@ Updates PresetUpdater::priv::config_update() const
return updates; return updates;
} }
void PresetUpdater::priv::perform_updates(AppConfig *app_config, Updates &&updates) const
{
SnapshotDB::singleton().take_snapshot(*app_config, Snapshot::SNAPSHOT_UPGRADE);
for (const auto &update : updates) {
fs::copy_file(update.source, update.target, fs::copy_option::overwrite_if_exists);
PresetBundle bundle;
bundle.load_configbundle(update.target.string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM);
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); }
}
}
PresetUpdater::PresetUpdater(int version_online_event, AppConfig *app_config) : PresetUpdater::PresetUpdater(int version_online_event, AppConfig *app_config) :
p(new priv(version_online_event, app_config)) p(new priv(version_online_event, app_config))
@ -306,7 +333,7 @@ void PresetUpdater::config_update(AppConfig *app_config)
{ {
if (! p->enabled_config_update) { return; } if (! p->enabled_config_update) { return; }
const auto updates = p->config_update(); auto updates = p->config_update();
if (updates.size() > 0) { if (updates.size() > 0) {
const auto msg = _(L("Configuration update is available. Would you like to install it?")); const auto msg = _(L("Configuration update is available. Would you like to install it?"));
@ -330,26 +357,23 @@ void PresetUpdater::config_update(AppConfig *app_config)
std::cerr << "After modal" << std::endl; std::cerr << "After modal" << std::endl;
if (res == wxID_YES) { if (res == wxID_YES) {
// User gave clearance, updates are go // User gave clearance, updates are go
p->perform_updates(app_config, std::move(updates));
SnapshotDB::singleton().take_snapshot(*app_config, Snapshot::SNAPSHOT_UPGRADE, "");
for (const auto &update : updates) {
fs::copy_file(update.source, update.target, fs::copy_option::overwrite_if_exists);
PresetBundle bundle;
bundle.load_configbundle(update.target.string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM);
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); }
}
} }
} }
} }
void PresetUpdater::install_bundles_rsrc(AppConfig *app_config, std::vector<std::string> &&bundles)
{
Updates updates;
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));
}
p->perform_updates(app_config, std::move(updates));
}
} }

View File

@ -2,6 +2,7 @@
#define slic3r_PresetUpdate_hpp_ #define slic3r_PresetUpdate_hpp_
#include <memory> #include <memory>
#include <vector>
namespace Slic3r { namespace Slic3r {
@ -20,8 +21,8 @@ public:
~PresetUpdater(); ~PresetUpdater();
void sync(AppConfig *app_config, PresetBundle *preset_bundle); void sync(AppConfig *app_config, PresetBundle *preset_bundle);
void config_update(AppConfig *app_config); void config_update(AppConfig *app_config);
void install_bundles_rsrc(AppConfig *app_config, std::vector<std::string> &&bundles);
private: private:
struct priv; struct priv;
std::unique_ptr<priv> p; std::unique_ptr<priv> p;

View File

@ -32,8 +32,6 @@ public:
ver.prerelease = prerelease ? std::strcpy(ver.prerelease, prerelease->c_str()) : nullptr; ver.prerelease = prerelease ? std::strcpy(ver.prerelease, prerelease->c_str()) : nullptr;
} }
// TODO: throwing ctor ???
static boost::optional<Semver> parse(const std::string &str) static boost::optional<Semver> parse(const std::string &str)
{ {
semver_t ver = semver_zero(); semver_t ver = semver_zero();

View File

@ -60,10 +60,10 @@ void set_app_config(AppConfig *app_config)
bool check_unsaved_changes() bool check_unsaved_changes()
%code%{ RETVAL=Slic3r::GUI::check_unsaved_changes(); %}; %code%{ RETVAL=Slic3r::GUI::check_unsaved_changes(); %};
bool config_wizard(int fresh_start) void config_wizard_startup(int app_config_exists)
%code%{ %code%{
try { try {
RETVAL = Slic3r::GUI::config_wizard(fresh_start != 0); Slic3r::GUI::config_wizard_startup(app_config_exists != 0);
} catch (std::exception& e) { } catch (std::exception& e) {
croak("%s\n", e.what()); croak("%s\n", e.what());
} }
@ -75,6 +75,9 @@ void open_preferences_dialog(int preferences_event)
void set_preset_bundle(PresetBundle *preset_bundle) void set_preset_bundle(PresetBundle *preset_bundle)
%code%{ Slic3r::GUI::set_preset_bundle(preset_bundle); %}; %code%{ Slic3r::GUI::set_preset_bundle(preset_bundle); %};
void set_preset_updater(PresetUpdater* updater)
%code%{ Slic3r::GUI::set_preset_updater(updater); %};
void add_frequently_changed_parameters(SV *ui_parent, SV *ui_sizer, SV *ui_p_sizer) void add_frequently_changed_parameters(SV *ui_parent, SV *ui_sizer, SV *ui_p_sizer)
%code%{ Slic3r::GUI::add_frequently_changed_parameters((wxWindow*)wxPli_sv_2_object(aTHX_ ui_parent, "Wx::Window"), %code%{ Slic3r::GUI::add_frequently_changed_parameters((wxWindow*)wxPli_sv_2_object(aTHX_ ui_parent, "Wx::Window"),
(wxBoxSizer*)wxPli_sv_2_object(aTHX_ ui_sizer, "Wx::BoxSizer"), (wxBoxSizer*)wxPli_sv_2_object(aTHX_ ui_sizer, "Wx::BoxSizer"),

View File

@ -238,7 +238,6 @@ Ref<TabIface> O_OBJECT_SLIC3R_T
PresetUpdater* O_OBJECT_SLIC3R PresetUpdater* O_OBJECT_SLIC3R
Ref<PresetUpdater> O_OBJECT_SLIC3R_T Ref<PresetUpdater> O_OBJECT_SLIC3R_T
Clone<PresetUpdater> O_OBJECT_SLIC3R_T
OctoPrint* O_OBJECT_SLIC3R OctoPrint* O_OBJECT_SLIC3R
Ref<OctoPrint> O_OBJECT_SLIC3R_T Ref<OctoPrint> O_OBJECT_SLIC3R_T

View File

@ -208,6 +208,8 @@
%typemap{Ref<PresetCollection>}{simple}; %typemap{Ref<PresetCollection>}{simple};
%typemap{PresetBundle*}; %typemap{PresetBundle*};
%typemap{Ref<PresetBundle>}{simple}; %typemap{Ref<PresetBundle>}{simple};
%typemap{PresetUpdater*};
%typemap{Ref<PresetUpdater>}{simple};
%typemap{PresetHints*}; %typemap{PresetHints*};
%typemap{Ref<PresetHints>}{simple}; %typemap{Ref<PresetHints>}{simple};
%typemap{TabIface*}; %typemap{TabIface*};