diff --git a/lib/Slic3r/GUI/ConfigWizard.pm b/lib/Slic3r/GUI/ConfigWizard.pm deleted file mode 100644 index a32d345ed..000000000 --- a/lib/Slic3r/GUI/ConfigWizard.pm +++ /dev/null @@ -1,458 +0,0 @@ -# The config wizard is executed when the Slic3r is first started. -# The wizard helps the user to specify the 3D printer properties. - -package Slic3r::GUI::ConfigWizard; -use strict; -use warnings; -use utf8; - -use Wx; -use base 'Wx::Wizard'; - -# adhere to various human interface guidelines -our $wizard = 'Wizard'; -$wizard = 'Assistant' if &Wx::wxMAC || &Wx::wxGTK; - -sub new { - my ($class, $parent, $presets, $fresh_start) = @_; - my $self = $class->SUPER::new($parent, -1, "Configuration $wizard"); - - # initialize an empty repository - $self->{config} = Slic3r::Config->new; - - my $welcome_page = Slic3r::GUI::ConfigWizard::Page::Welcome->new($self, $fresh_start); - $self->add_page($welcome_page); - $self->add_page(Slic3r::GUI::ConfigWizard::Page::Firmware->new($self)); - $self->add_page(Slic3r::GUI::ConfigWizard::Page::Bed->new($self)); - $self->add_page(Slic3r::GUI::ConfigWizard::Page::Nozzle->new($self)); - $self->add_page(Slic3r::GUI::ConfigWizard::Page::Filament->new($self)); - $self->add_page(Slic3r::GUI::ConfigWizard::Page::Temperature->new($self)); - $self->add_page(Slic3r::GUI::ConfigWizard::Page::BedTemperature->new($self)); - $self->add_page(Slic3r::GUI::ConfigWizard::Page::Finished->new($self)); - - $_->build_index for @{$self->{pages}}; - - $welcome_page->set_selection_presets([@{$presets}, 'Other']); - - return $self; -} - -sub add_page { - my ($self, $page) = @_; - - my $n = push @{$self->{pages}}, $page; - # add first page to the page area sizer - $self->GetPageAreaSizer->Add($page) if $n == 1; - # link pages - $self->{pages}[$n-2]->set_next_page($page) if $n >= 2; - $page->set_previous_page($self->{pages}[$n-2]) if $n >= 2; -} - -sub run { - my ($self) = @_; - my $result; - if (Wx::Wizard::RunWizard($self, $self->{pages}[0])) { - my $preset_name = $self->{pages}[0]->{preset_name}; - $result = { - preset_name => $preset_name, - reset_user_profile => $self->{pages}[0]->{reset_user_profile} - }; - if ($preset_name eq 'Other') { - # it would be cleaner to have these defined inside each page class, - # in some event getting called before leaving the page - # set first_layer_height + layer_height based on nozzle_diameter - my $nozzle = $self->{config}->nozzle_diameter; - $self->{config}->set('first_layer_height', $nozzle->[0]); - $self->{config}->set('layer_height', $nozzle->[0] - 0.1); - - # set first_layer_temperature to temperature + 5 - $self->{config}->set('first_layer_temperature', [$self->{config}->temperature->[0] + 5]); - - # set first_layer_bed_temperature to temperature + 5 - $self->{config}->set('first_layer_bed_temperature', - [ ($self->{config}->bed_temperature->[0] > 0) ? ($self->{config}->bed_temperature->[0] + 5) : 0 ]); - $result->{config} = $self->{config}; - } - } - $self->Destroy; - return $result; -} - -package Slic3r::GUI::ConfigWizard::Index; -use Wx qw(:bitmap :dc :font :misc :sizer :systemsettings :window); -use Wx::Event qw(EVT_ERASE_BACKGROUND EVT_PAINT); -use base 'Wx::Panel'; - -sub new { - my $class = shift; - my ($parent, $title) = @_; - my $self = $class->SUPER::new($parent); - - push @{$self->{titles}}, $title; - $self->{own_index} = 0; - - $self->{bullets}->{before} = Wx::Bitmap->new(Slic3r::var("bullet_black.png"), wxBITMAP_TYPE_PNG); - $self->{bullets}->{own} = Wx::Bitmap->new(Slic3r::var("bullet_blue.png"), wxBITMAP_TYPE_PNG); - $self->{bullets}->{after} = Wx::Bitmap->new(Slic3r::var("bullet_white.png"), wxBITMAP_TYPE_PNG); - - $self->{background} = Wx::Bitmap->new(Slic3r::var("Slic3r_192px_transparent.png"), wxBITMAP_TYPE_PNG); - $self->SetMinSize(Wx::Size->new($self->{background}->GetWidth, $self->{background}->GetHeight)); - - EVT_PAINT($self, \&repaint); - - return $self; -} - -sub repaint { - my ($self, $event) = @_; - my $size = $self->GetClientSize; - my $gap = 5; - - my $dc = Wx::PaintDC->new($self); - $dc->SetBackgroundMode(wxTRANSPARENT); - $dc->SetFont($self->GetFont); - $dc->SetTextForeground($self->GetForegroundColour); - - my $background_h = $self->{background}->GetHeight; - my $background_w = $self->{background}->GetWidth; - $dc->DrawBitmap($self->{background}, ($size->GetWidth - $background_w) / 2, ($size->GetHeight - $background_h) / 2, 1); - - my $label_h = $self->{bullets}->{own}->GetHeight; - $label_h = $dc->GetCharHeight if $dc->GetCharHeight > $label_h; - my $label_w = $size->GetWidth; - - my $i = 0; - foreach (@{$self->{titles}}) { - my $bullet = $self->{bullets}->{own}; - $bullet = $self->{bullets}->{before} if $i < $self->{own_index}; - $bullet = $self->{bullets}->{after} if $i > $self->{own_index}; - - $dc->SetTextForeground(Wx::Colour->new(128, 128, 128)) if $i > $self->{own_index}; - $dc->DrawLabel($_, $bullet, Wx::Rect->new(0, $i * ($label_h + $gap), $label_w, $label_h)); - # Only show the first bullet if this is the only wizard page to be displayed. - last if $i == 0 && $self->{just_welcome}; - $i++; - } - - $event->Skip; -} - -sub prepend_title { - my $self = shift; - my ($title) = @_; - - unshift @{$self->{titles}}, $title; - $self->{own_index}++; - $self->Refresh; -} - -sub append_title { - my $self = shift; - my ($title) = @_; - - push @{$self->{titles}}, $title; - $self->Refresh; -} - -package Slic3r::GUI::ConfigWizard::Page; -use Wx qw(:font :misc :sizer :staticline :systemsettings); -use base 'Wx::WizardPage'; - -sub new { - my $class = shift; - my ($parent, $title, $short_title) = @_; - my $self = $class->SUPER::new($parent); - - my $sizer = Wx::FlexGridSizer->new(0, 2, 10, 10); - $sizer->AddGrowableCol(1, 1); - $sizer->AddGrowableRow(1, 1); - $sizer->AddStretchSpacer(0); - $self->SetSizer($sizer); - - # title - my $text = Wx::StaticText->new($self, -1, $title, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); - my $bold_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); - $bold_font->SetWeight(wxFONTWEIGHT_BOLD); - $bold_font->SetPointSize(14); - $text->SetFont($bold_font); - $sizer->Add($text, 0, wxALIGN_LEFT, 0); - - # index - $self->{short_title} = $short_title ? $short_title : $title; - $self->{index} = Slic3r::GUI::ConfigWizard::Index->new($self, $self->{short_title}); - $sizer->Add($self->{index}, 1, wxEXPAND | wxTOP | wxRIGHT, 10); - - # contents - $self->{width} = 430; - $self->{vsizer} = Wx::BoxSizer->new(wxVERTICAL); - $sizer->Add($self->{vsizer}, 1); - - return $self; -} - -sub append_text { - my $self = shift; - my ($text) = @_; - - my $para = Wx::StaticText->new($self, -1, $text, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); - $para->Wrap($self->{width}); - $para->SetMinSize([$self->{width}, -1]); - $self->{vsizer}->Add($para, 0, wxALIGN_LEFT | wxTOP | wxBOTTOM, 10); -} - -sub append_option { - my $self = shift; - my ($full_key) = @_; - - # populate repository with the factory default - my ($opt_key, $opt_index) = split /#/, $full_key, 2; - $self->config->apply(Slic3r::Config::new_from_defaults_keys([$opt_key])); - - # draw the control - my $optgroup = Slic3r::GUI::ConfigOptionsGroup->new( - parent => $self, - title => '', - config => $self->config, - full_labels => 1, - ); - $optgroup->append_single_option_line($opt_key, $opt_index); - $self->{vsizer}->Add($optgroup->sizer, 0, wxEXPAND | wxTOP | wxBOTTOM, 10); -} - -sub append_panel { - my ($self, $panel) = @_; - $self->{vsizer}->Add($panel, 0, wxEXPAND | wxTOP | wxBOTTOM, 10); -} - -sub set_previous_page { - my $self = shift; - my ($previous_page) = @_; - $self->{previous_page} = $previous_page; -} - -sub GetPrev { - my $self = shift; - return $self->{previous_page}; -} - -sub set_next_page { - my $self = shift; - my ($next_page) = @_; - $self->{next_page} = $next_page; -} - -sub GetNext { - my $self = shift; - return $self->{next_page}; -} - -sub get_short_title { - my $self = shift; - return $self->{short_title}; -} - -sub build_index { - my $self = shift; - - my $page = $self; - $self->{index}->prepend_title($page->get_short_title) while ($page = $page->GetPrev); - $page = $self; - $self->{index}->append_title($page->get_short_title) while ($page = $page->GetNext); -} - -sub config { - my ($self) = @_; - return $self->GetParent->{config}; -} - -package Slic3r::GUI::ConfigWizard::Page::Welcome; -use base 'Slic3r::GUI::ConfigWizard::Page'; -use Wx qw(:misc :sizer wxID_FORWARD); -use Wx::Event qw(EVT_ACTIVATE EVT_CHOICE EVT_CHECKBOX); - -sub new { - my ($class, $parent, $fresh_start) = @_; - my $self = $class->SUPER::new($parent, "Welcome to the Slic3r Configuration $wizard", 'Welcome'); - $self->{full_wizard_workflow} = 1; - $self->{reset_user_profile} = 0; - - # Test for the existence of the old config path. - my $message_has_legacy; - { - my $datadir = Slic3r::data_dir; - if ($datadir =~ /Slic3rPE/) { - # Check for existence of the legacy Slic3r directory. - my $datadir_legacy = substr $datadir, 0, -2; - my $dir_enc = Slic3r::encode_path($datadir_legacy); - if (-e $dir_enc && -d $dir_enc && - -e ($dir_enc . '/print') && -d ($dir_enc . '/print') && - -e ($dir_enc . '/filament') && -d ($dir_enc . '/filament') && - -e ($dir_enc . '/printer') && -d ($dir_enc . '/printer') && - -e ($dir_enc . '/slic3r.ini')) { - $message_has_legacy = "Starting with Slic3r 1.38.4, the user profile directory has been renamed to $datadir. You may consider closing Slic3r and renaming $datadir_legacy to $datadir."; - } - } - } - - $self->append_text('Hello, welcome to Slic3r Prusa Edition! This '.lc($wizard).' helps you with the initial configuration; just a few settings and you will be ready to print.'); - $self->append_text('Please select your printer vendor and printer type. If your printer is not listed, you may try your luck and select a similar one. If you select "Other", this ' . lc($wizard) . ' will let you set the basic 3D printer parameters.'); - $self->append_text($message_has_legacy) if defined $message_has_legacy; - # To import an existing configuration instead, cancel this '.lc($wizard).' and use the Open Config menu item found in the File menu.'); - $self->append_text('If you received a configuration file or a config bundle from your 3D printer vendor, cancel this '.lc($wizard).' and use the "File->Load Config" or "File->Load Config Bundle" menu.'); - - $self->{choice} = my $choice = Wx::Choice->new($self, -1, wxDefaultPosition, wxDefaultSize, []); - $self->{vsizer}->Add($choice, 0, wxEXPAND | wxTOP | wxBOTTOM, 10); - if (! $fresh_start) { - $self->{reset_checkbox} = Wx::CheckBox->new($self, -1, "Reset user profile, install from scratch"); - $self->{vsizer}->Add($self->{reset_checkbox}, 0, wxEXPAND | wxTOP | wxBOTTOM, 10); - } - - EVT_CHOICE($parent, $choice, sub { - my $sel = $self->{choice}->GetStringSelection; - $self->{preset_name} = $sel; - $self->set_full_wizard_workflow(($sel eq 'Other') || ($sel eq '')); - }); - - if (! $fresh_start) { - EVT_CHECKBOX($self, $self->{reset_checkbox}, sub { - $self->{reset_user_profile} = $self->{reset_checkbox}->GetValue(); - }); - } - - EVT_ACTIVATE($parent, sub { - $self->set_full_wizard_workflow($self->{preset_name} eq 'Other'); - }); - - return $self; -} - -sub set_full_wizard_workflow { - my ($self, $full_workflow) = @_; - $self->{full_wizard_workflow} = $full_workflow; - $self->{index}->{just_welcome} = !$full_workflow; - $self->{index}->Refresh; - my $next_button = $self->GetParent->FindWindow(wxID_FORWARD); - $next_button->SetLabel($full_workflow ? "&Next >" : "&Finish"); -} - -# Set the preset names, select the first item. -sub set_selection_presets { - my ($self, $names) = @_; - $self->{choice}->Append($names); - $self->{choice}->SetSelection(0); - $self->{preset_name} = $names->[0]; -} - -sub GetNext { - my $self = shift; - return $self->{full_wizard_workflow} ? $self->{next_page} : undef; -} - -package Slic3r::GUI::ConfigWizard::Page::Firmware; -use base 'Slic3r::GUI::ConfigWizard::Page'; - -sub new { - my $class = shift; - my ($parent) = @_; - my $self = $class->SUPER::new($parent, 'Firmware Type'); - - $self->append_text('Choose the type of firmware used by your printer, then click Next.'); - $self->append_option('gcode_flavor'); - - return $self; -} - -package Slic3r::GUI::ConfigWizard::Page::Bed; -use base 'Slic3r::GUI::ConfigWizard::Page'; - -sub new { - my $class = shift; - my ($parent) = @_; - my $self = $class->SUPER::new($parent, 'Bed Size'); - - $self->append_text('Set the shape of your printer\'s bed, then click Next.'); - - $self->config->apply(Slic3r::Config::new_from_defaults_keys(['bed_shape'])); - $self->{bed_shape_panel} = my $panel = Slic3r::GUI::BedShapePanel->new($self, $self->config->bed_shape); - $self->{bed_shape_panel}->on_change(sub { - $self->config->set('bed_shape', $self->{bed_shape_panel}->GetValue); - }); - $self->append_panel($self->{bed_shape_panel}); - return $self; -} - -package Slic3r::GUI::ConfigWizard::Page::Nozzle; -use base 'Slic3r::GUI::ConfigWizard::Page'; - -sub new { - my $class = shift; - my ($parent) = @_; - my $self = $class->SUPER::new($parent, 'Nozzle Diameter'); - - $self->append_text('Enter the diameter of your printer\'s hot end nozzle, then click Next.'); - $self->append_option('nozzle_diameter#0'); - - return $self; -} - -package Slic3r::GUI::ConfigWizard::Page::Filament; -use base 'Slic3r::GUI::ConfigWizard::Page'; - -sub new { - my $class = shift; - my ($parent) = @_; - my $self = $class->SUPER::new($parent, 'Filament Diameter'); - - $self->append_text('Enter the diameter of your filament, then click Next.'); - $self->append_text('Good precision is required, so use a caliper and do multiple measurements along the filament, then compute the average.'); - $self->append_option('filament_diameter#0'); - - return $self; -} - -package Slic3r::GUI::ConfigWizard::Page::Temperature; -use base 'Slic3r::GUI::ConfigWizard::Page'; - -sub new { - my $class = shift; - my ($parent) = @_; - my $self = $class->SUPER::new($parent, 'Extrusion Temperature'); - - $self->append_text('Enter the temperature needed for extruding your filament, then click Next.'); - $self->append_text('A rule of thumb is 160 to 230 °C for PLA, and 215 to 250 °C for ABS.'); - $self->append_option('temperature#0'); - - return $self; -} - -package Slic3r::GUI::ConfigWizard::Page::BedTemperature; -use base 'Slic3r::GUI::ConfigWizard::Page'; - -sub new { - my $class = shift; - my ($parent) = @_; - my $self = $class->SUPER::new($parent, 'Bed Temperature'); - - $self->append_text('Enter the bed temperature needed for getting your filament to stick to your heated bed, then click Next.'); - $self->append_text('A rule of thumb is 60 °C for PLA and 110 °C for ABS. Leave zero if you have no heated bed.'); - $self->append_option('bed_temperature#0'); - - return $self; -} - -package Slic3r::GUI::ConfigWizard::Page::Finished; -use base 'Slic3r::GUI::ConfigWizard::Page'; - -sub new { - my $class = shift; - my ($parent) = @_; - my $self = $class->SUPER::new($parent, 'Congratulations!', 'Finish'); - - $self->append_text("You have successfully completed the Slic3r Configuration $wizard. " . - 'Slic3r is now configured for your printer and filament.'); - $self->append_text('To close this '.lc($wizard).' and apply the newly created configuration, click Finish.'); - - return $self; -} - -1; diff --git a/resources/profiles/PrusaResearch.idx b/resources/profiles/PrusaResearch.idx index 28f17f10a..3bc2aeffd 100644 --- a/resources/profiles/PrusaResearch.idx +++ b/resources/profiles/PrusaResearch.idx @@ -1,6 +1,9 @@ # This is an example configuration version index. # The index contains version numbers min_slic3r_version =1.39.0 +max_slic3r_version= 1.39.5 +1.1.1 +1.1.0 0.2.0-alpha "some test comment" max_slic3r_version= 1.39.4 0.1.0 another test comment diff --git a/xs/src/perlglue.cpp b/xs/src/perlglue.cpp index 9706ced2c..205eec218 100644 --- a/xs/src/perlglue.cpp +++ b/xs/src/perlglue.cpp @@ -62,7 +62,6 @@ REGISTER_CLASS(GLVolumeCollection, "GUI::_3DScene::GLVolume::Collection"); REGISTER_CLASS(Preset, "GUI::Preset"); REGISTER_CLASS(PresetCollection, "GUI::PresetCollection"); REGISTER_CLASS(PresetBundle, "GUI::PresetBundle"); -REGISTER_CLASS(PresetHints, "GUI::PresetHints"); REGISTER_CLASS(TabIface, "GUI::Tab"); REGISTER_CLASS(PresetUpdater, "PresetUpdater"); REGISTER_CLASS(OctoPrint, "OctoPrint"); diff --git a/xs/src/semver/semver.c b/xs/src/semver/semver.c index 3e4a30e3a..68d18af09 100644 --- a/xs/src/semver/semver.c +++ b/xs/src/semver/semver.c @@ -175,6 +175,9 @@ semver_parse_version (const char *str, semver_t *ver) { slice = (char *) str; index = 0; + // non mandatory + ver->patch = 0; + while (slice != NULL && index++ < 4) { next = strchr(slice, DELIMITER[0]); if (next == NULL) @@ -200,7 +203,8 @@ semver_parse_version (const char *str, semver_t *ver) { slice = next + 1; } - return (index == 3) ? 0 : -1; + // Major and minor versions are mandatory, patch version is not mandatory. + return (index == 2 || index == 3) ? 0 : -1; } static int @@ -632,4 +636,5 @@ semver_copy(const semver_t *ver) { if (ver->prerelease != NULL) { res.prerelease = strdup(ver->prerelease); } + return res; } \ No newline at end of file diff --git a/xs/src/slic3r/Config/Version.cpp b/xs/src/slic3r/Config/Version.cpp index 95b3caf1a..a80b0b6e9 100644 --- a/xs/src/slic3r/Config/Version.cpp +++ b/xs/src/slic3r/Config/Version.cpp @@ -141,6 +141,15 @@ size_t Index::load(const boost::filesystem::path &path) return m_configs.size(); } +Semver Index::version() const +{ + Semver ver = Semver::zero(); + for (const Version &cv : m_configs) + if (cv.config_version >= ver) + ver = cv.config_version; + return ver; +} + Index::const_iterator Index::find(const Semver &ver) { Version key; diff --git a/xs/src/slic3r/Config/Version.hpp b/xs/src/slic3r/Config/Version.hpp index 43512e82f..c4243ca75 100644 --- a/xs/src/slic3r/Config/Version.hpp +++ b/xs/src/slic3r/Config/Version.hpp @@ -59,6 +59,9 @@ public: size_t load(const boost::filesystem::path &path); const std::string& vendor() const { return m_vendor; } + // Returns version of the index as the highest version of all the configs. + // If there is no config, Semver::zero() is returned. + Semver version() const; const_iterator begin() const { return m_configs.begin(); } const_iterator end() const { return m_configs.end(); } diff --git a/xs/src/slic3r/GUI/ConfigWizard.cpp b/xs/src/slic3r/GUI/ConfigWizard.cpp index 52a896704..30d1bf4e3 100644 --- a/xs/src/slic3r/GUI/ConfigWizard.cpp +++ b/xs/src/slic3r/GUI/ConfigWizard.cpp @@ -619,7 +619,7 @@ void ConfigWizard::priv::on_custom_setup() 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, bool fresh_start) { const bool is_custom_setup = page_welcome->page_next() == page_firmware; @@ -627,7 +627,8 @@ 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"); - app_config->reset_selections(); // XXX: only on "fresh start"? + if (fresh_start) + app_config->reset_selections(); preset_bundle->load_presets(*app_config); } else { for (ConfigWizardPage *page = page_firmware; page != nullptr; page = page->page_next()) { @@ -635,6 +636,8 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese } preset_bundle->load_config("My Settings", *custom_config); } + // Update the selections from the compatibilty. + preset_bundle->export_selections(*app_config); } // Public @@ -698,11 +701,11 @@ ConfigWizard::ConfigWizard(wxWindow *parent) : ConfigWizard::~ConfigWizard() {} -bool ConfigWizard::run(wxWindow *parent, PresetBundle *preset_bundle) +bool ConfigWizard::run(wxWindow *parent, PresetBundle *preset_bundle, bool fresh_start) { ConfigWizard wizard(parent); if (wizard.ShowModal() == wxID_OK) { - wizard.p->apply_config(GUI::get_app_config(), preset_bundle); + wizard.p->apply_config(GUI::get_app_config(), preset_bundle, fresh_start); return true; } else { return false; diff --git a/xs/src/slic3r/GUI/ConfigWizard.hpp b/xs/src/slic3r/GUI/ConfigWizard.hpp index 40ecf09a1..4e791e279 100644 --- a/xs/src/slic3r/GUI/ConfigWizard.hpp +++ b/xs/src/slic3r/GUI/ConfigWizard.hpp @@ -22,7 +22,7 @@ public: ConfigWizard &operator=(const ConfigWizard &) = delete; ~ConfigWizard(); - static bool run(wxWindow *parent, PresetBundle *preset_bundle); + static bool run(wxWindow *parent, PresetBundle *preset_bundle, bool fresh_start); private: struct priv; std::unique_ptr p; diff --git a/xs/src/slic3r/GUI/ConfigWizard_private.hpp b/xs/src/slic3r/GUI/ConfigWizard_private.hpp index 652328aaa..6881f6f55 100644 --- a/xs/src/slic3r/GUI/ConfigWizard_private.hpp +++ b/xs/src/slic3r/GUI/ConfigWizard_private.hpp @@ -202,7 +202,7 @@ struct ConfigWizard::priv void on_other_vendors(); void on_custom_setup(); - void apply_config(AppConfig *app_config, PresetBundle *preset_bundle); + void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, bool fresh_start); }; diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index d70b47840..036e08993 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -452,7 +452,7 @@ bool config_wizard(bool fresh_start) return false; // TODO: Offer "reset user profile" ??? - if (! ConfigWizard::run(g_wxMainFrame, g_PresetBundle)) + if (! ConfigWizard::run(g_wxMainFrame, g_PresetBundle, fresh_start)) return false; // Load the currently selected preset into the GUI, update the preset selection box. diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 39bfbd398..853c229ff 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -521,18 +521,6 @@ size_t PresetCollection::first_visible_idx() const return idx; } -// Return index of the first compatible preset. Certainly at least the '- default -' preset shall be compatible. -size_t PresetCollection::first_compatible_idx() const -{ - size_t idx = m_default_suppressed ? 1 : 0; - for (; idx < this->m_presets.size(); ++ idx) - if (m_presets[idx].is_compatible) - break; - if (idx == this->m_presets.size()) - idx = 0; - return idx; -} - void PresetCollection::set_default_suppressed(bool default_suppressed) { if (m_default_suppressed != default_suppressed) { @@ -541,7 +529,7 @@ void PresetCollection::set_default_suppressed(bool default_suppressed) } } -void PresetCollection::update_compatible_with_printer(const Preset &active_printer, bool select_other_if_incompatible) +size_t PresetCollection::update_compatible_with_printer_internal(const Preset &active_printer, bool unselect_if_incompatible) { DynamicPrintConfig config; config.set_key_value("printer_preset", new ConfigOptionString(active_printer.name)); @@ -552,14 +540,12 @@ void PresetCollection::update_compatible_with_printer(const Preset &active_print Preset &preset_selected = m_presets[idx_preset]; Preset &preset_edited = selected ? m_edited_preset : preset_selected; if (! preset_edited.update_compatible_with_printer(active_printer, &config) && - selected && select_other_if_incompatible) + selected && unselect_if_incompatible) m_idx_selected = (size_t)-1; if (selected) preset_selected.is_compatible = preset_edited.is_compatible; } - if (m_idx_selected == (size_t)-1) - // Find some other compatible preset, or the "-- default --" preset. - this->select_preset(first_compatible_idx()); + return m_idx_selected; } // Save the preset under a new name. If the name is different from the old one, @@ -689,8 +675,8 @@ bool PresetCollection::select_preset_by_name(const std::string &name_w_suffix, b // 1) Try to find the preset by its name. auto it = this->find_preset_internal(name); size_t idx = 0; - if (it != m_presets.end() && it->name == name) - // Preset found by its name. + if (it != m_presets.end() && it->name == name && it->is_visible) + // Preset found by its name and it is visible. idx = it - m_presets.begin(); else { // Find the first visible preset. @@ -711,6 +697,23 @@ bool PresetCollection::select_preset_by_name(const std::string &name_w_suffix, b return false; } +bool PresetCollection::select_preset_by_name_strict(const std::string &name) +{ + // 1) Try to find the preset by its name. + auto it = this->find_preset_internal(name); + size_t idx = (size_t)-1; + if (it != m_presets.end() && it->name == name && it->is_visible) + // Preset found by its name. + idx = it - m_presets.begin(); + // 2) Select the new preset. + if (idx != (size_t)-1) { + this->select_preset(idx); + return true; + } + m_idx_selected = idx; + return false; +} + std::string PresetCollection::name() const { switch (this->type()) { diff --git a/xs/src/slic3r/GUI/Preset.hpp b/xs/src/slic3r/GUI/Preset.hpp index d6ccfd450..08caf4d4e 100644 --- a/xs/src/slic3r/GUI/Preset.hpp +++ b/xs/src/slic3r/GUI/Preset.hpp @@ -18,6 +18,7 @@ class wxItemContainer; namespace Slic3r { class AppConfig; +class PresetBundle; enum ConfigFileType { @@ -243,19 +244,49 @@ public: { return const_cast(this)->find_preset(name, first_visible_if_not_found); } size_t first_visible_idx() const; - size_t first_compatible_idx() const; + // Return index of the first compatible preset. Certainly at least the '- default -' preset shall be compatible. + // If one of the prefered_alternates is compatible, select it. + template + size_t first_compatible_idx(PreferedCondition prefered_condition) const + { + size_t i = m_default_suppressed ? 1 : 0; + size_t n = this->m_presets.size(); + size_t i_compatible = n; + for (; i < n; ++ i) + if (m_presets[i].is_compatible) { + if (prefered_condition(m_presets[i].name)) + return i; + if (i_compatible == n) + // Store the first compatible profile into i_compatible. + i_compatible = i; + } + return (i_compatible == n) ? 0 : i_compatible; + } + // Return index of the first compatible preset. Certainly at least the '- default -' preset shall be compatible. + size_t first_compatible_idx() const { return this->first_compatible_idx([](const std::string&){return true;}); } + // Return index of the first visible preset. Certainly at least the '- default -' preset shall be visible. // Return the first visible preset. Certainly at least the '- default -' preset shall be visible. Preset& first_visible() { return this->preset(this->first_visible_idx()); } const Preset& first_visible() const { return this->preset(this->first_visible_idx()); } Preset& first_compatible() { return this->preset(this->first_compatible_idx()); } + template + Preset& first_compatible(PreferedCondition prefered_condition) { return this->preset(this->first_compatible_idx(prefered_condition)); } const Preset& first_compatible() const { return this->preset(this->first_compatible_idx()); } // Return number of presets including the "- default -" preset. size_t size() const { return this->m_presets.size(); } // For Print / Filament presets, disable those, which are not compatible with the printer. - void update_compatible_with_printer(const Preset &active_printer, bool select_other_if_incompatible); + template + void update_compatible_with_printer(const Preset &active_printer, bool select_other_if_incompatible, PreferedCondition prefered_condition) + { + if (this->update_compatible_with_printer_internal(active_printer, select_other_if_incompatible) == (size_t)-1) + // Find some other compatible preset, or the "-- default --" preset. + this->select_preset(this->first_compatible_idx(prefered_condition)); + } + void update_compatible_with_printer(const Preset &active_printer, bool select_other_if_incompatible) + { this->update_compatible_with_printer(active_printer, select_other_if_incompatible, [](const std::string&){return true;}); } size_t num_visible() const { return std::count_if(m_presets.begin(), m_presets.end(), [](const Preset &preset){return preset.is_visible;}); } @@ -291,6 +322,11 @@ public: // Generate a file path from a profile name. Add the ".ini" suffix if it is missing. std::string path_from_name(const std::string &new_name) const; +protected: + // Select a preset, if it exists. If it does not exist, select an invalid (-1) index. + // This is a temporary state, which shall be fixed immediately by the following step. + bool select_preset_by_name_strict(const std::string &name); + private: PresetCollection(); PresetCollection(const PresetCollection &other); @@ -308,6 +344,8 @@ private: std::deque::const_iterator find_preset_internal(const std::string &name) const { return const_cast(this)->find_preset_internal(name); } + size_t update_compatible_with_printer_internal(const Preset &active_printer, bool unselect_if_incompatible); + static std::vector dirty_options(const Preset *edited, const Preset *reference); // Type of this PresetCollection: TYPE_PRINT, TYPE_FILAMENT or TYPE_PRINTER. @@ -333,6 +371,9 @@ private: wxBitmap *m_bitmap_main_frame; // Path to the directory to store the config files into. std::string m_dir_path; + + // to access select_preset_by_name_strict() + friend class PresetBundle; }; } // namespace Slic3r diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index ad27bf8c6..244915864 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -209,22 +209,34 @@ void PresetBundle::load_installed_printers(const AppConfig &config) // This is done just once on application start up. void PresetBundle::load_selections(const AppConfig &config) { - prints.select_preset_by_name(remove_ini_suffix(config.get("presets", "print")), true); - filaments.select_preset_by_name(remove_ini_suffix(config.get("presets", "filament")), true); - printers.select_preset_by_name(remove_ini_suffix(config.get("presets", "printer")), true); + // Update visibility of presets based on application vendor / model / variant configuration. + this->load_installed_printers(config); + + // Parse the initial print / filament / printer profile names. + std::string initial_print_profile_name = remove_ini_suffix(config.get("presets", "print")); + std::vector initial_filament_profile_names; + std::string initial_printer_profile_name = remove_ini_suffix(config.get("presets", "printer")); + auto *nozzle_diameter = dynamic_cast(printers.get_selected_preset().config.option("nozzle_diameter")); size_t num_extruders = nozzle_diameter->values.size(); - this->set_filament_preset(0, filaments.get_selected_preset().name); + initial_filament_profile_names.emplace_back(remove_ini_suffix(config.get("presets", "filament"))); + this->set_filament_preset(0, initial_filament_profile_names.back()); for (unsigned int i = 1; i < (unsigned int)num_extruders; ++ i) { char name[64]; sprintf(name, "filament_%d", i); if (! config.has("presets", name)) break; - this->set_filament_preset(i, remove_ini_suffix(config.get("presets", name))); + initial_filament_profile_names.emplace_back(remove_ini_suffix(config.get("presets", name))); + this->set_filament_preset(i, initial_filament_profile_names.back()); } - // Update visibility of presets based on application vendor / model / variant configuration. - this->load_installed_printers(config); + // Activate print / filament / printer profiles from the config. + // If the printer profile enumerated by the config are not visible, select an alternate preset. + // Do not select alternate profiles for the print / filament profiles as those presets + // will be selected by the following call of this->update_compatible_with_printer(true). + prints.select_preset_by_name_strict(initial_print_profile_name); + filaments.select_preset_by_name_strict(initial_filament_profile_names.front()); + printers.select_preset_by_name(initial_printer_profile_name, true); // Update visibility of presets based on their compatibility with the active printer. // Always try to select a compatible print and filament preset to the current printer preset, @@ -861,14 +873,35 @@ void PresetBundle::update_multi_material_filament_presets() void PresetBundle::update_compatible_with_printer(bool select_other_if_incompatible) { - this->prints.update_compatible_with_printer(this->printers.get_edited_preset(), select_other_if_incompatible); - this->filaments.update_compatible_with_printer(this->printers.get_edited_preset(), select_other_if_incompatible); + const Preset &printer_preset = this->printers.get_edited_preset(); + const std::string &prefered_print_profile = printer_preset.config.opt_string("default_print_profile"); + const std::vector &prefered_filament_profiles = printer_preset.config.option("default_filament_profile")->values; + prefered_print_profile.empty() ? + this->prints.update_compatible_with_printer(printer_preset, select_other_if_incompatible) : + this->prints.update_compatible_with_printer(printer_preset, select_other_if_incompatible, + [&prefered_print_profile](const std::string& profile_name){ return profile_name == prefered_print_profile; }); + prefered_filament_profiles.empty() ? + this->filaments.update_compatible_with_printer(printer_preset, select_other_if_incompatible) : + this->filaments.update_compatible_with_printer(printer_preset, select_other_if_incompatible, + [&prefered_filament_profiles](const std::string& profile_name) + { return std::find(prefered_filament_profiles.begin(), prefered_filament_profiles.end(), profile_name) != prefered_filament_profiles.end(); }); if (select_other_if_incompatible) { // Verify validity of the current filament presets. - for (std::string &filament_name : this->filament_presets) { - Preset *preset = this->filaments.find_preset(filament_name, false); - if (preset == nullptr || ! preset->is_compatible) - filament_name = this->filaments.first_compatible().name; + this->filament_presets.front() = this->filaments.get_edited_preset().name; + for (size_t idx = 1; idx < this->filament_presets.size(); ++ idx) { + std::string &filament_name = this->filament_presets[idx]; + Preset *preset = this->filaments.find_preset(filament_name, false); + if (preset == nullptr || ! preset->is_compatible) { + // Pick a compatible profile. If there are prefered_filament_profiles, use them. + if (prefered_filament_profiles.empty()) + filament_name = this->filaments.first_compatible().name; + else { + const std::string &preferred = (idx < prefered_filament_profiles.size()) ? + prefered_filament_profiles[idx] : prefered_filament_profiles.front(); + filament_name = this->filaments.first_compatible( + [&preferred](const std::string& profile_name){ return profile_name == preferred; }).name; + } + } } } } diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 940987536..ed2b4b951 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -540,7 +540,8 @@ void Tab::load_key_value(std::string opt_key, boost::any value) change_opt_value(*m_config, opt_key, value); // Mark the print & filament enabled if they are compatible with the currently selected preset. if (opt_key.compare("compatible_printers") == 0) { - m_preset_bundle->update_compatible_with_printer(0); + // Don't select another profile if this profile happens to become incompatible. + m_preset_bundle->update_compatible_with_printer(false); } m_presets->update_dirty_ui(m_presets_choice); on_presets_changed(); @@ -1772,7 +1773,7 @@ void Tab::rebuild_page_tree() // Called by the UI combo box when the user switches profiles. // Select a preset by a name.If !defined(name), then the default preset is selected. // If the current profile is modified, user is asked to save the changes. -void Tab::select_preset(std::string preset_name /*= ""*/) +void Tab::select_preset(const std::string &preset_name /*= ""*/) { std::string name = preset_name; auto force = false; diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp index f39ff728c..bd9672bb2 100644 --- a/xs/src/slic3r/GUI/Tab.hpp +++ b/xs/src/slic3r/GUI/Tab.hpp @@ -143,7 +143,7 @@ public: void create_preset_tab(PresetBundle *preset_bundle); void load_current_preset(); void rebuild_page_tree(); - void select_preset(std::string preset_name = ""); + void select_preset(const std::string &preset_name = ""); bool may_discard_current_dirty_preset(PresetCollection* presets = nullptr, std::string new_printer_name = ""); wxSizer* compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox, wxButton** btn); diff --git a/xs/xsp/GUI_Preset.xsp b/xs/xsp/GUI_Preset.xsp index 1187a1cf5..d0d4057b2 100644 --- a/xs/xsp/GUI_Preset.xsp +++ b/xs/xsp/GUI_Preset.xsp @@ -44,9 +44,6 @@ Ref find_preset(char *name, bool first_visible_if_not_found = false) %code%{ RETVAL = THIS->find_preset(name, first_visible_if_not_found); %}; - bool current_is_dirty(); - std::vector current_dirty_options(); - void update_tab_ui(SV *ui, bool show_incompatible) %code%{ auto cb = (wxBitmapComboBox*)wxPli_sv_2_object( aTHX_ ui, "Wx::BitmapComboBox" ); THIS->update_tab_ui(cb, show_incompatible); %}; @@ -55,30 +52,6 @@ %code%{ auto cb = (wxBitmapComboBox*)wxPli_sv_2_object( aTHX_ ui, "Wx::BitmapComboBox" ); THIS->update_platter_ui(cb); %}; - bool update_dirty_ui(SV *ui) - %code%{ RETVAL = THIS->update_dirty_ui((wxBitmapComboBox*)wxPli_sv_2_object(aTHX_ ui, "Wx::BitmapComboBox")); %}; - - void select_preset(int idx); - bool select_preset_by_name(char *name) %code%{ RETVAL = THIS->select_preset_by_name(name, true); %}; - void discard_current_changes(); - - void save_current_preset(char *new_name) - %code%{ - try { - THIS->save_current_preset(new_name); - } catch (std::exception& e) { - croak("Error saving a preset %s:\n%s\n", new_name, e.what()); - } - %}; - void delete_current_preset() - %code%{ - try { - THIS->delete_current_preset(); - } catch (std::exception& e) { - croak("Error deleting a preset file %s:\n%s\n", THIS->get_selected_preset().file.c_str(), e.what()); - } - %}; - %{ SV* @@ -173,9 +146,6 @@ PresetCollection::arrayref() std::vector filament_presets() %code%{ RETVAL = THIS->filament_presets; %}; void set_filament_preset(int idx, const char *name); - void update_multi_material_filament_presets(); - - void update_compatible_with_printer(bool select_other_if_incompatible); Clone full_config() %code%{ RETVAL = THIS->full_config(); %}; @@ -183,15 +153,3 @@ PresetCollection::arrayref() %code%{ auto cb = (wxBitmapComboBox*)wxPli_sv_2_object(aTHX_ ui, "Wx::BitmapComboBox"); THIS->update_platter_filament_ui(extruder_idx, cb); %}; }; - -%name{Slic3r::GUI::PresetHints} class PresetHints { - PresetHints(); - ~PresetHints(); - - static std::string cooling_description(Preset *preset) - %code%{ RETVAL = PresetHints::cooling_description(*preset); %}; - static std::string maximum_volumetric_flow_description(PresetBundle *preset) - %code%{ RETVAL = PresetHints::maximum_volumetric_flow_description(*preset); %}; - static std::string recommended_thin_wall_thickness(PresetBundle *preset) - %code%{ RETVAL = PresetHints::recommended_thin_wall_thickness(*preset); %}; -}; diff --git a/xs/xsp/my.map b/xs/xsp/my.map index c1ca58827..79b71143b 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -231,8 +231,6 @@ PresetCollection* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T PresetBundle* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T -PresetHints* O_OBJECT_SLIC3R -Ref O_OBJECT_SLIC3R_T TabIface* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index 0214a158d..a2bca2c7b 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -208,8 +208,6 @@ %typemap{Ref}{simple}; %typemap{PresetBundle*}; %typemap{Ref}{simple}; -%typemap{PresetHints*}; -%typemap{Ref}{simple}; %typemap{TabIface*}; %typemap{Ref}{simple};