diff options
author | bubnikv <bubnikv@gmail.com> | 2017-11-02 18:21:34 +0300 |
---|---|---|
committer | bubnikv <bubnikv@gmail.com> | 2017-11-02 18:21:34 +0300 |
commit | e8b6d92d4d5852e5731d21afb90362285b2dd6f2 (patch) | |
tree | 11dc25cfe40ed5824629a6f64d701090ff2d4cee /lib | |
parent | 95c284c76431fcd3e21764b206ba6100c3179c1e (diff) |
Looks like the reworked C++ preferences start to work again.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Slic3r.pm | 20 | ||||
-rw-r--r-- | lib/Slic3r/Config.pm | 65 | ||||
-rw-r--r-- | lib/Slic3r/GUI.pm | 156 | ||||
-rw-r--r-- | lib/Slic3r/GUI/Controller.pm | 2 | ||||
-rw-r--r-- | lib/Slic3r/GUI/Controller/PrinterPanel.pm | 2 | ||||
-rw-r--r-- | lib/Slic3r/GUI/MainFrame.pm | 112 | ||||
-rw-r--r-- | lib/Slic3r/GUI/OptionsGroup/Field.pm | 4 | ||||
-rw-r--r-- | lib/Slic3r/GUI/Plater.pm | 87 | ||||
-rw-r--r-- | lib/Slic3r/GUI/Plater/2D.pm | 7 | ||||
-rw-r--r-- | lib/Slic3r/GUI/Preferences.pm | 20 | ||||
-rw-r--r-- | lib/Slic3r/GUI/Tab.pm | 127 |
11 files changed, 188 insertions, 414 deletions
diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index dc870edf3..53b2e3663 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -23,25 +23,14 @@ sub debugf { our $loglevel = 0; # load threads before Moo as required by it -our $have_threads; BEGIN { # Test, whether the perl was compiled with ithreads support and ithreads actually work. use Config; - $have_threads = $Config{useithreads} && eval "use threads; use threads::shared; use Thread::Queue; 1"; - warn "threads.pm >= 1.96 is required, please update\n" if $have_threads && $threads::VERSION < 1.96; - - ### temporarily disable threads if using the broken Moo version use Moo; - $have_threads = 0 if $Moo::VERSION == 1.003000; - - # Disable multi threading completely by an environment value. - # This is useful for debugging as the Perl debugger does not work - # in multi-threaded context at all. - # A good interactive perl debugger is the ActiveState Komodo IDE - # or the EPIC http://www.epic-ide.org/ - $have_threads = 0 if (defined($ENV{'SLIC3R_SINGLETHREADED'}) && $ENV{'SLIC3R_SINGLETHREADED'} == 1); - print "Threading disabled\n" if !$have_threads; - + my $have_threads = $Config{useithreads} && eval "use threads; use threads::shared; use Thread::Queue; 1"; + die "Slic3r Prusa Edition requires working Perl threads.\n" if ! $have_threads; + die "threads.pm >= 1.96 is required, please update\n" if $threads::VERSION < 1.96; + die "Perl threading is broken with this Moo version: " . $Moo::VERSION . "\n" if $Moo::VERSION == 1.003000; $debug = 1 if (defined($ENV{'SLIC3R_DEBUGOUT'}) && $ENV{'SLIC3R_DEBUGOUT'} == 1); print "Debugging output enabled\n" if $debug; } @@ -164,6 +153,7 @@ sub thread_cleanup { *Slic3r::Surface::Collection::DESTROY = sub {}; *Slic3r::Print::SupportMaterial2::DESTROY = sub {}; *Slic3r::TriangleMesh::DESTROY = sub {}; + *Slic3r::GUI::AppConfig::DESTROY = sub {}; *Slic3r::GUI::PresetBundle::DESTROY = sub {}; return undef; # this prevents a "Scalars leaked" warning } diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index c5e49df6b..a9c822b96 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -12,14 +12,14 @@ use List::Util qw(first max); # The C++ counterpart is a constant singleton. our $Options = print_config_def(); -# overwrite the hard-coded readonly value (this information is not available in XS) -$Options->{threads}{readonly} = !$Slic3r::have_threads; - -# generate accessors +# Generate accessors. { no strict 'refs'; for my $opt_key (keys %$Options) { - *{$opt_key} = sub { $_[0]->get($opt_key) }; + *{$opt_key} = sub { + #print "Slic3r::Config::accessor $opt_key\n"; + $_[0]->get($opt_key) + }; } } @@ -64,61 +64,6 @@ sub new_from_cli { return $self; } -# CLASS METHODS: - -# Write a "Windows" style ini file with categories enclosed in squre brackets. -# Used by config-bundle-to-config.pl and to save slic3r.ini. -sub write_ini { - my $class = shift; - my ($file, $ini) = @_; - - Slic3r::open(\my $fh, '>', $file); - binmode $fh, ':utf8'; - my $localtime = localtime; - printf $fh "# generated by Slic3r $Slic3r::VERSION on %s\n", "$localtime"; - # make sure the _ category is the first one written - foreach my $category (sort { ($a eq '_') ? -1 : ($a cmp $b) } keys %$ini) { - printf $fh "\n[%s]\n", $category if $category ne '_'; - foreach my $key (sort keys %{$ini->{$category}}) { - printf $fh "%s = %s\n", $key, $ini->{$category}{$key}; - } - } - close $fh; -} - -# Parse a "Windows" style ini file with categories enclosed in squre brackets. -# Returns a hash of hashes over strings. -# {category}{name}=value -# Non-categorized entries are stored under a category '_'. -# Used by config-bundle-to-config.pl and to read slic3r.ini. -sub read_ini { - my $class = shift; - my ($file) = @_; - - local $/ = "\n"; - Slic3r::open(\my $fh, '<', $file) - or die "Unable to open $file: $!\n"; - binmode $fh, ':utf8'; - - my $ini = { _ => {} }; - my $category = '_'; - while (<$fh>) { - s/\R+$//; - next if /^\s+/; - next if /^$/; - next if /^\s*#/; - if (/^\[(.+?)\]$/) { - $category = $1; - next; - } - /^(\w+) *= *(.*)/ or die "Unreadable configuration file (invalid data at line $.)\n"; - $ini->{$category}{$1} = $2; - } - close $fh; - - return $ini; -} - package Slic3r::Config::Static; use parent 'Slic3r::Config'; diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index a75b0d83b..baba3baa7 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -53,25 +53,9 @@ use constant FILE_WILDCARDS => { use constant MODEL_WILDCARD => join '|', @{&FILE_WILDCARDS}{qw(known stl obj amf prusa)}; # If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden. -our $no_controller; our $no_plater; -our $autosave; our @cb; -our $Settings = { - _ => { - version_check => 1, - autocenter => 1, - # Disable background processing by default as it is not stable. - background_processing => 0, - # If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden. - # By default, Prusa has the controller hidden. - no_controller => 1, - # If set, the "- default -" selections of print/filament/printer are suppressed, if there is a valid preset available. - no_defaults => 1, - }, -}; - our $small_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); $small_font->SetPointSize(11) if &Wx::wxMAC; our $small_bold_font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); @@ -89,91 +73,47 @@ sub OnInit { Slic3r::debugf "wxWidgets version %s, Wx version %s\n", &Wx::wxVERSION_STRING, $Wx::VERSION; $self->{notifier} = Slic3r::GUI::Notifier->new; + $self->{app_config} = Slic3r::GUI::AppConfig->new; $self->{preset_bundle} = Slic3r::GUI::PresetBundle->new; # 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 - my $enc_datadir = Slic3r::encode_path(Slic3r::data_dir); - Slic3r::debugf "Data directory: %s\n", $enc_datadir; - my $run_wizard = (-d $enc_datadir && -e "$enc_datadir/slic3r.ini") ? 0 : 1; - foreach my $dir ($enc_datadir, "$enc_datadir/print", "$enc_datadir/filament", "$enc_datadir/printer") { - next if -d $dir; - if (!mkdir $dir) { - my $error = "Slic3r was unable to create its data directory at $dir ($!)."; - warn "$error\n"; - fatal_error(undef, $error); - } + eval { $self->{preset_bundle}->setup_directories() }; + if ($@) { + warn $@ . "\n"; + fatal_error(undef, $@); } - + my $run_wizard = ! $self->{app_config}->exists; # load settings - my $last_version; - if (-f "$enc_datadir/slic3r.ini") { - my $ini = eval { Slic3r::Config->read_ini(Slic3r::data_dir . "/slic3r.ini") }; - $Settings = $ini if $ini; - $last_version = $Settings->{_}{version}; - $Settings->{_}{autocenter} //= 1; - $Settings->{_}{background_processing} //= 1; - # If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden. - $Settings->{_}{no_controller} //= 1; - # If set, the "- default -" selections of print/filament/printer are suppressed, if there is a valid preset available. - $Settings->{_}{no_defaults} //= 1; - } - $Settings->{_}{version} = $Slic3r::VERSION; - $self->save_settings; + $self->{app_config}->load if ! $run_wizard; + $self->{app_config}->set('version', $Slic3r::VERSION); + $self->{app_config}->save; # Suppress the '- default -' presets. - $self->{preset_bundle}->set_default_suppressed($Slic3r::GUI::Settings->{_}{no_defaults} ? 1 : 0); - eval { $self->{preset_bundle}->load_presets(Slic3r::data_dir) }; + $self->{preset_bundle}->set_default_suppressed($self->{app_config}->get('no_defaults') ? 1 : 0); + eval { + $self->{preset_bundle}->load_presets(Slic3r::data_dir); + $self->{preset_bundle}->load_selections($self->{app_config}); + $run_wizard = 1 if $self->{preset_bundle}->has_defauls_only; + }; # application frame Wx::Image::AddHandler(Wx::PNGHandler->new); $self->{mainframe} = my $frame = Slic3r::GUI::MainFrame->new( # If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden. - no_controller => $no_controller // $Settings->{_}{no_controller}, + no_controller => $self->{app_config}->get('no_controller'), no_plater => $no_plater, ); $self->SetTopWindow($frame); - - # load init bundle - #FIXME this is undocumented and the use case is unclear. -# { -# my @dirs = ($FindBin::Bin); -# if (&Wx::wxMAC) { -# push @dirs, qw(); -# } elsif (&Wx::wxMSW) { -# push @dirs, qw(); -# } -# my $init_bundle = first { -e $_ } map "$_/.init_bundle.ini", @dirs; -# if ($init_bundle) { -# Slic3r::debugf "Loading config bundle from %s\n", $init_bundle; -# $self->{mainframe}->load_configbundle($init_bundle, 1); -# $run_wizard = 0; -# } -# } - - if (!$run_wizard && (!defined $last_version || $last_version ne $Slic3r::VERSION)) { - # user was running another Slic3r version on this computer - if (!defined $last_version || $last_version =~ /^0\./) { - show_info($self->{mainframe}, "Hello! Support material was improved since the " - . "last version of Slic3r you used. It is strongly recommended to revert " - . "your support material settings to the factory defaults and start from " - . "those. Enjoy and provide feedback!", "Support Material"); - } - if (!defined $last_version || $last_version =~ /^(?:0|1\.[01])\./) { - show_info($self->{mainframe}, "Hello! In this version a new Bed Shape option was " - . "added. If the bed coordinates in the plater preview screen look wrong, go " - . "to Print Settings and click the \"Set\" button next to \"Bed Shape\".", "Bed Shape"); - } - } if ($run_wizard) { $self->{mainframe}->config_wizard; - eval { $self->{preset_bundle}->load_presets(Slic3r::data_dir) }; } EVT_IDLE($frame, sub { while (my $cb = shift @cb) { $cb->(); } + $self->{app_config}->save if $self->{app_config}->dirty; }); return 1; @@ -265,11 +205,6 @@ sub notify { $self->{notifier}->notify($message); } -sub save_settings { - my ($self) = @_; - Slic3r::Config->write_ini(Slic3r::data_dir . "/slic3r.ini", $Settings); -} - # Called after the Preferences dialog is closed and the program settings are saved. # Update the UI based on the current preferences. sub update_ui_from_settings { @@ -277,22 +212,11 @@ sub update_ui_from_settings { $self->{mainframe}->update_ui_from_settings; } -sub output_path { - my ($self, $dir) = @_; - - return ($Settings->{_}{last_output_path} && $Settings->{_}{remember_output_path}) - ? $Settings->{_}{last_output_path} - : $dir; -} - sub open_model { my ($self, $window) = @_; - my $dir = $Slic3r::GUI::Settings->{recent}{skein_directory} - || $Slic3r::GUI::Settings->{recent}{config_directory} - || ''; - - my $dialog = Wx::FileDialog->new($window // $self->GetTopWindow, 'Choose one or more files (STL/OBJ/AMF/PRUSA):', $dir, "", + my $dialog = Wx::FileDialog->new($window // $self->GetTopWindow, 'Choose one or more files (STL/OBJ/AMF/PRUSA):', + $self->{app_config}->get_last_dir, "", MODEL_WILDCARD, wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST); if ($dialog->ShowModal != wxID_OK) { $dialog->Destroy; @@ -308,31 +232,6 @@ sub CallAfter { push @cb, $cb; } -sub scan_serial_ports { - my ($self) = @_; - - my @ports = (); - - if ($^O eq 'MSWin32') { - # Windows - if (eval "use Win32::TieRegistry; 1") { - my $ts = Win32::TieRegistry->new("HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM", - { Access => 'KEY_READ' }); - if ($ts) { - # when no serial ports are available, the registry key doesn't exist and - # TieRegistry->new returns undef - $ts->Tie(\my %reg); - push @ports, sort values %reg; - } - } - } else { - # UNIX and OS X - push @ports, glob '/dev/{ttyUSB,ttyACM,tty.,cu.,rfcomm}*'; - } - - return grep !/Bluetooth|FireFly/, @ports; -} - sub append_menu_item { my ($self, $menu, $string, $description, $cb, $id, $icon, $kind) = @_; @@ -369,25 +268,24 @@ sub set_menu_item_icon { sub save_window_pos { my ($self, $window, $name) = @_; - $Settings->{_}{"${name}_pos"} = join ',', $window->GetScreenPositionXY; - $Settings->{_}{"${name}_size"} = join ',', $window->GetSizeWH; - $Settings->{_}{"${name}_maximized"} = $window->IsMaximized; - $self->save_settings; + $self->{app_config}->set("${name}_pos", join ',', $window->GetScreenPositionXY); + $self->{app_config}->set("${name}_size", join ',', $window->GetSizeWH); + $self->{app_config}->set("${name}_maximized", $window->IsMaximized); + $self->{app_config}->save; } sub restore_window_pos { my ($self, $window, $name) = @_; - - if (defined $Settings->{_}{"${name}_pos"}) { - my $size = [ split ',', $Settings->{_}{"${name}_size"}, 2 ]; + if ($self->{app_config}->has("${name}_pos")) { + my $size = [ split ',', $self->{app_config}->get("${name}_size"), 2 ]; $window->SetSize($size); my $display = Wx::Display->new->GetClientArea(); - my $pos = [ split ',', $Settings->{_}{"${name}_pos"}, 2 ]; + my $pos = [ split ',', $self->{app_config}->get("${name}_pos"), 2 ]; if (($pos->[0] + $size->[0]/2) < $display->GetRight && ($pos->[1] + $size->[1]/2) < $display->GetBottom) { $window->Move($pos); } - $window->Maximize(1) if $Settings->{_}{"${name}_maximized"}; + $window->Maximize(1) if $self->{app_config}->get("${name}_maximized"); } } diff --git a/lib/Slic3r/GUI/Controller.pm b/lib/Slic3r/GUI/Controller.pm index c4a22cace..6f2636d20 100644 --- a/lib/Slic3r/GUI/Controller.pm +++ b/lib/Slic3r/GUI/Controller.pm @@ -121,7 +121,7 @@ sub OnActivate { } if (!%active) { # enable printers whose port is available - my %ports = map { $_ => 1 } wxTheApp->scan_serial_ports; + my %ports = map { $_ => 1 } Slic3r::GUI::scan_serial_ports; $active{$_} = 1 for grep exists $ports{$presets{$_}->serial_port}, keys %presets; } diff --git a/lib/Slic3r/GUI/Controller/PrinterPanel.pm b/lib/Slic3r/GUI/Controller/PrinterPanel.pm index 1bf46c456..794ea4e4e 100644 --- a/lib/Slic3r/GUI/Controller/PrinterPanel.pm +++ b/lib/Slic3r/GUI/Controller/PrinterPanel.pm @@ -348,7 +348,7 @@ sub update_serial_ports { my $cb = $self->{serial_port_combobox}; my $current = $cb->GetValue; $cb->Clear; - $cb->Append($_) for wxTheApp->scan_serial_ports; + $cb->Append($_) for Slic3r::GUI::scan_serial_ports; $cb->SetValue($current); } diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index a0a47c547..c7f3f1cf9 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -76,6 +76,9 @@ sub new { } # save window size wxTheApp->save_window_pos($self, "main_frame"); + # Save the slic3r.ini. Usually the ini file is saved from "on idle" callback, + # but in rare cases it may not have been called yet. + wxTheApp->{app_config}->save; # propagate event $event->Skip; }); @@ -140,9 +143,11 @@ sub _init_tabpanel { my ($group, $name) = @_; $self->{options_tabs}{$group}->select_preset($name); }); - # load initial config - $self->{plater}->on_config_change(wxTheApp->{preset_bundle}->full_config); + my $full_config = wxTheApp->{preset_bundle}->full_config; + $self->{plater}->on_config_change($full_config); + # Show a correct number of filament fields. + $self->{plater}->on_extruders_change(int(@{$full_config->nozzle_diameter})); } } @@ -340,14 +345,15 @@ sub quick_slice { my $progress_dialog; eval { # validate configuration - my $config = $self->config; + my $config = wxTheApp->{preset_bundle}->full_config(); $config->validate; # select input file my $input_file; - my $dir = $Slic3r::GUI::Settings->{recent}{skein_directory} || $Slic3r::GUI::Settings->{recent}{config_directory} || ''; if (!$params{reslice}) { - my $dialog = Wx::FileDialog->new($self, 'Choose a file to slice (STL/OBJ/AMF/PRUSA):', $dir, "", &Slic3r::GUI::MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST); + my $dialog = Wx::FileDialog->new($self, 'Choose a file to slice (STL/OBJ/AMF/PRUSA):', + wxTheApp->{app_config}->get_last_dir, "", + &Slic3r::GUI::MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST); if ($dialog->ShowModal != wxID_OK) { $dialog->Destroy; return; @@ -369,8 +375,7 @@ sub quick_slice { $input_file = $qs_last_input_file; } my $input_file_basename = basename($input_file); - $Slic3r::GUI::Settings->{recent}{skein_directory} = dirname($input_file); - wxTheApp->save_settings; + wxTheApp->{app_config}->update_skein_dir(dirname($input_file)); my $print_center; { @@ -392,11 +397,9 @@ sub quick_slice { $sprint->apply_config($config); $sprint->set_model($model); - { - my $extra = $self->extra_variables; - $sprint->placeholder_parser->set($_, $extra->{$_}) for keys %$extra; - } - + # Copy the names of active presets into the placeholder parser. + wxTheApp->{preset_bundle}->export_selections_pp($sprint->placeholder_parser); + # select output file my $output_file; if ($params{reslice}) { @@ -405,7 +408,7 @@ sub quick_slice { $output_file = $sprint->output_filepath; $output_file =~ s/\.[gG][cC][oO][dD][eE]$/.svg/ if $params{export_svg}; my $dlg = Wx::FileDialog->new($self, 'Save ' . ($params{export_svg} ? 'SVG' : 'G-code') . ' file as:', - wxTheApp->output_path(dirname($output_file)), + wxTheApp->{app_config}->get_last_output_dir(dirname($output_file)), basename($output_file), $params{export_svg} ? &Slic3r::GUI::FILE_WILDCARDS->{svg} : &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if ($dlg->ShowModal != wxID_OK) { $dlg->Destroy; @@ -413,8 +416,7 @@ sub quick_slice { } $output_file = $dlg->GetPath; $qs_last_output_file = $output_file unless $params{export_svg}; - $Slic3r::GUI::Settings->{_}{last_output_path} = dirname($output_file); - wxTheApp->save_settings; + wxTheApp->{app_config}->update_last_output_dir(dirname($output_file)); $dlg->Destroy; } @@ -457,8 +459,9 @@ sub repair_stl { my $input_file; { - my $dir = $Slic3r::GUI::Settings->{recent}{skein_directory} || $Slic3r::GUI::Settings->{recent}{config_directory} || ''; - my $dialog = Wx::FileDialog->new($self, 'Select the STL file to repair:', $dir, "", &Slic3r::GUI::FILE_WILDCARDS->{stl}, wxFD_OPEN | wxFD_FILE_MUST_EXIST); + my $dialog = Wx::FileDialog->new($self, 'Select the STL file to repair:', + wxTheApp->{app_config}->get_last_dir, "", + &Slic3r::GUI::FILE_WILDCARDS->{stl}, wxFD_OPEN | wxFD_FILE_MUST_EXIST); if ($dialog->ShowModal != wxID_OK) { $dialog->Destroy; return; @@ -487,15 +490,6 @@ sub repair_stl { Slic3r::GUI::show_info($self, "Your file was repaired.", "Repair"); } -# Extra variables for the placeholder parser generating a G-code. -sub extra_variables { - my $self = shift; - my %extra_variables = (); - $extra_variables{"${_}_preset"} = wxTheApp->{preset_bundle}->{$_}->get_current_preset_name - for qw(print filament printer); - return { %extra_variables }; -} - sub export_config { my $self = shift; # Generate a cummulative configuration for the selected print, filaments and printer. @@ -504,15 +498,14 @@ sub export_config { eval { $config->validate; }; Slic3r::GUI::catch_error($self) and return; # Ask user for the file name for the config file. - my $dir = $last_config ? dirname($last_config) : $Slic3r::GUI::Settings->{recent}{config_directory} || $Slic3r::GUI::Settings->{recent}{skein_directory} || ''; - my $filename = $last_config ? basename($last_config) : "config.ini"; - my $dlg = Wx::FileDialog->new($self, 'Save configuration as:', $dir, $filename, + my $dlg = Wx::FileDialog->new($self, 'Save configuration as:', + $last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir, + $last_config ? basename($last_config) : "config.ini", &Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); my $file = ($dlg->ShowModal == wxID_OK) ? $dlg->GetPath : undef; $dlg->Destroy; if (defined $file) { - $Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file); - wxTheApp->save_settings; + wxTheApp->{app_config}->update_config_dir(dirname($file)); $last_config = $file; $config->save($file); } @@ -523,9 +516,10 @@ sub load_config_file { my ($self, $file) = @_; if (!$file) { return unless $self->check_unsaved_changes; - my $dir = $last_config ? dirname($last_config) : $Slic3r::GUI::Settings->{recent}{config_directory} || $Slic3r::GUI::Settings->{recent}{skein_directory} || ''; - my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', $dir, "config.ini", - 'INI files (*.ini, *.gcode)|*.ini;*.INI;*.gcode;*.g', wxFD_OPEN | wxFD_FILE_MUST_EXIST); + my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', + $last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir, + "config.ini", + 'INI files (*.ini, *.gcode)|*.ini;*.INI;*.gcode;*.g', wxFD_OPEN | wxFD_FILE_MUST_EXIST); return unless $dlg->ShowModal == wxID_OK; $file = $dlg->GetPaths; $dlg->Destroy; @@ -534,49 +528,51 @@ sub load_config_file { # Dont proceed further if the config file cannot be loaded. return if Slic3r::GUI::catch_error($self); $_->load_current_preset for (values %{$self->{options_tabs}}); - $Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file); - wxTheApp->save_settings; + wxTheApp->{app_config}->update_config_dir(dirname($file)); $last_config = $file; } sub export_configbundle { - my $self = shift; + my ($self) = @_; + return unless $self->check_unsaved_changes; # validate current configuration in case it's dirty - eval { $self->config->validate; }; + eval { wxTheApp->{preset_bundle}->full_config->validate; }; Slic3r::GUI::catch_error($self) and return; # Ask user for a file name. - my $dir = $last_config ? dirname($last_config) : $Slic3r::GUI::Settings->{recent}{config_directory} || $Slic3r::GUI::Settings->{recent}{skein_directory} || ''; - my $filename = "Slic3r_config_bundle.ini"; - my $dlg = Wx::FileDialog->new($self, 'Save presets bundle as:', $dir, $filename, + my $dlg = Wx::FileDialog->new($self, 'Save presets bundle as:', + $last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir, + "Slic3r_config_bundle.ini", &Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); my $file = ($dlg->ShowModal == wxID_OK) ? $dlg->GetPath : undef; $dlg->Destroy; if (defined $file) { # Export the config bundle. - $Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file); - wxTheApp->save_settings; - eval { $self->{presets}->export_configbundle($file); }; + wxTheApp->{app_config}->update_config_dir(dirname($file)); + eval { wxTheApp->{preset_bundle}->export_configbundle($file); }; Slic3r::GUI::catch_error($self) and return; } } +# Loading a config bundle with an external file name used to be used +# to auto-install a config bundle on a fresh user account, +# but that behavior was not documented and likely buggy. sub load_configbundle { - my ($self, $file, $skip_no_id) = @_; - + my ($self, $file) = @_; + return unless $self->check_unsaved_changes; if (!$file) { - my $dir = $last_config ? dirname($last_config) : $Slic3r::GUI::Settings->{recent}{config_directory} || $Slic3r::GUI::Settings->{recent}{skein_directory} || ''; - my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', $dir, "config.ini", - &Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_OPEN | wxFD_FILE_MUST_EXIST); + my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', + $last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir, + "config.ini", + &Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_OPEN | wxFD_FILE_MUST_EXIST); return unless $dlg->ShowModal == wxID_OK; $file = $dlg->GetPaths; $dlg->Destroy; } - $Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file); - wxTheApp->save_settings; + wxTheApp->{app_config}->update_config_dir(dirname($file)); my $presets_imported = 0; - eval { $presets_imported = $self->{presets}->load_configbundle($file); }; + eval { $presets_imported = wxTheApp->{preset_bundle}->load_configbundle($file); }; Slic3r::GUI::catch_error($self) and return; # Load the currently selected preset into the GUI, update the preset selection box. @@ -597,16 +593,18 @@ sub load_config { } sub config_wizard { - my $self = shift; - + my ($self) = @_; + # Exit wizard if there are unsaved changes and the user cancels the action. return unless $self->check_unsaved_changes; if (my $config = Slic3r::GUI::ConfigWizard->new($self)->run) { for my $tab (values %{$self->{options_tabs}}) { - # Select the first visible preset. - $tab->select_preset(undef); + # Select the first visible preset, force. + $tab->select_preset(undef, 1); } + # Load the config over the previously selected defaults. $self->load_config($config); for my $tab (values %{$self->{options_tabs}}) { + # Save the settings under a new name, select the name. $tab->save_preset('My Settings'); } } @@ -666,7 +664,7 @@ sub _set_menu_item_icon { # Update the UI based on the current preferences. sub update_ui_from_settings { my ($self) = @_; - $self->{menu_item_reslice_now}->Enable(! $Slic3r::GUI::Settings->{_}{background_processing}); + $self->{menu_item_reslice_now}->Enable(! wxTheApp->{app_config}->get("background_processing")); $self->{plater}->update_ui_from_settings if ($self->{plater}); } diff --git a/lib/Slic3r/GUI/OptionsGroup/Field.pm b/lib/Slic3r/GUI/OptionsGroup/Field.pm index 531e13a5d..4ef2ce2ca 100644 --- a/lib/Slic3r/GUI/OptionsGroup/Field.pm +++ b/lib/Slic3r/GUI/OptionsGroup/Field.pm @@ -124,6 +124,10 @@ sub BUILD { }); } +sub get_value { + my ($self) = @_; + return $self->wxWindow->GetValue ? 1 : 0; +} package Slic3r::GUI::OptionsGroup::Field::SpinCtrl; use Moo; diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 91329e45e..06adbe525 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -63,12 +63,7 @@ sub new { $self->{print}->set_status_cb(sub { my ($percent, $message) = @_; - - if ($Slic3r::have_threads) { - Wx::PostEvent($self, Wx::PlThreadEvent->new(-1, $PROGRESS_BAR_EVENT, shared_clone([$percent, $message]))); - } else { - $self->on_progress_event($percent, $message); - } + Wx::PostEvent($self, Wx::PlThreadEvent->new(-1, $PROGRESS_BAR_EVENT, shared_clone([$percent, $message]))); }); # Initialize preview notebook @@ -119,7 +114,7 @@ sub new { $self->GetFrame->{options_tabs}{print}->load_config($cfg); }); $self->{canvas3D}->set_on_model_update(sub { - if ($Slic3r::GUI::Settings->{_}{background_processing}) { + if (wxTheApp->{app_config}->get("background_processing")) { $self->schedule_background_process; } else { # Hide the print info box, it is no more valid. @@ -330,7 +325,7 @@ sub new { $self->on_process_completed($event->GetData); }); - if ($Slic3r::have_threads) { + { my $timer_id = Wx::NewId(); $self->{apply_config_timer} = Wx::Timer->new($self, $timer_id); EVT_TIMER($self, $timer_id, sub { @@ -448,7 +443,6 @@ sub new { $self->{"print_info_$field"}->SetFont($Slic3r::GUI::small_font); $grid_sizer->Add($self->{"print_info_$field"}, 0); } - } my $buttons_sizer = Wx::BoxSizer->new(wxHORIZONTAL); @@ -510,13 +504,14 @@ sub _on_select_preset { wxTheApp->{preset_bundle}->set_filament_preset($idx, $choice->GetStringSelection); } if ($group eq 'filament' && @{$self->{preset_choosers}{filament}} > 1) { - wxTheApp->save_settings; wxTheApp->{preset_bundle}->update_platter_filament_ui_colors($idx, $choice); } else { # call GetSelection() in scalar context as it's context-aware $self->{on_select_preset}->($group, $choice->GetStringSelection) if $self->{on_select_preset}; } + # Synchronize config.ini with the current selections. + wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config}); # get new config and generate on_config_change() event for updating plater and other things $self->on_config_change(wxTheApp->{preset_bundle}->full_config); } @@ -548,8 +543,8 @@ sub GetFrame { sub update_ui_from_settings { my ($self) = @_; - if (defined($self->{btn_reslice}) && $self->{buttons_sizer}->IsShown($self->{btn_reslice}) != (! $Slic3r::GUI::Settings->{_}{background_processing})) { - $self->{buttons_sizer}->Show($self->{btn_reslice}, ! $Slic3r::GUI::Settings->{_}{background_processing}); + if (defined($self->{btn_reslice}) && $self->{buttons_sizer}->IsShown($self->{btn_reslice}) != (! wxTheApp->{app_config}->get("background_processing"))) { + $self->{buttons_sizer}->Show($self->{btn_reslice}, ! wxTheApp->{app_config}->get("background_processing")); $self->{buttons_sizer}->Layout; } } @@ -587,6 +582,8 @@ sub update_presets { $choice_idx += 1; } } + # Synchronize config.ini with the current selections. + wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config}); } sub add { @@ -655,8 +652,7 @@ sub load_files { } # Note the current directory for the file open dialog. - $Slic3r::GUI::Settings->{recent}{skein_directory} = dirname($input_files->[-1]); - wxTheApp->save_settings; + wxTheApp->{app_config}->update_skein_dir(dirname($input_files->[-1])); $process_dialog->Destroy; $self->statusbar->SetStatusText("Loaded " . join(',', @loaded_files)); @@ -704,7 +700,7 @@ sub load_model_objects { } # if user turned autocentering off, automatic arranging would disappoint them - if (!$Slic3r::GUI::Settings->{_}{autocenter}) { + if (! wxTheApp->{app_config}->get("autocenter")) { $need_arrange = 0; } @@ -817,7 +813,7 @@ sub increase { # only autoarrange if user has autocentering enabled $self->stop_background_process; - if ($Slic3r::GUI::Settings->{_}{autocenter}) { + if (wxTheApp->{app_config}->get("autocenter")) { $self->arrange; } else { $self->update; @@ -1130,7 +1126,7 @@ sub async_apply_config { # Hide the slicing results if the current slicing status is no more valid. $self->{"print_info_box_show"}->(0) if $invalidated; - if ($Slic3r::GUI::Settings->{_}{background_processing}) { + if (wxTheApp->{app_config}->get("background_processing")) { if ($invalidated) { # kill current thread if any $self->stop_background_process; @@ -1152,7 +1148,6 @@ sub async_apply_config { sub start_background_process { my ($self) = @_; - return if !$Slic3r::have_threads; return if !@{$self->{objects}}; return if $self->{process_thread}; @@ -1171,11 +1166,8 @@ sub start_background_process { return; } - # apply extra variables - { - my $extra = $self->GetFrame->extra_variables; - $self->{print}->placeholder_parser->set($_, $extra->{$_}) for keys %$extra; - } + # Copy the names of active presets into the placeholder parser. + wxTheApp->{preset_bundle}->export_selections_pp($self->{print}->placeholder_parser); # start thread @_ = (); @@ -1246,7 +1238,7 @@ sub reslice { # explicitly cancel a previous thread and start a new one. my ($self) = @_; # Don't reslice if export of G-code or sending to OctoPrint is running. - if ($Slic3r::have_threads && ! defined($self->{export_gcode_output_file}) && ! defined($self->{send_gcode_file})) { + if (! defined($self->{export_gcode_output_file}) && ! defined($self->{send_gcode_file})) { # Stop the background processing threads, stop the async update timer. $self->stop_background_process; # Rather perform one additional unnecessary update of the print object instead of skipping a pending async update. @@ -1289,52 +1281,41 @@ sub export_gcode { $self->{print}->apply_config($config); $self->{print}->validate; }; - if (!$Slic3r::have_threads) { - Slic3r::GUI::catch_error($self) and return; - } + Slic3r::GUI::catch_error($self) and return; # select output file if ($output_file) { $self->{export_gcode_output_file} = $self->{print}->output_filepath($output_file); } else { my $default_output_file = $self->{print}->output_filepath($main::opt{output} // ''); - my $dlg = Wx::FileDialog->new($self, 'Save G-code file as:', wxTheApp->output_path(dirname($default_output_file)), + my $dlg = Wx::FileDialog->new($self, 'Save G-code file as:', + wxTheApp->{app_config}->get_last_output_dir(dirname($default_output_file)), basename($default_output_file), &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if ($dlg->ShowModal != wxID_OK) { $dlg->Destroy; return; } my $path = $dlg->GetPath; - $Slic3r::GUI::Settings->{_}{last_output_path} = dirname($path); - wxTheApp->save_settings; + wxTheApp->{app_config}->update_last_output_dir(dirname($path)); $self->{export_gcode_output_file} = $path; $dlg->Destroy; } $self->statusbar->StartBusy; - if ($Slic3r::have_threads) { - $self->statusbar->SetCancelCallback(sub { - $self->stop_background_process; - $self->statusbar->SetStatusText("Export cancelled"); - $self->{export_gcode_output_file} = undef; - $self->{send_gcode_file} = undef; - - # this updates buttons status - $self->object_list_changed; - }); + $self->statusbar->SetCancelCallback(sub { + $self->stop_background_process; + $self->statusbar->SetStatusText("Export cancelled"); + $self->{export_gcode_output_file} = undef; + $self->{send_gcode_file} = undef; - # start background process, whose completion event handler - # will detect $self->{export_gcode_output_file} and proceed with export - $self->start_background_process; - } else { - eval { - $self->{print}->process; - $self->{print}->export_gcode(output_file => $self->{export_gcode_output_file}); - }; - my $result = !Slic3r::GUI::catch_error($self); - $self->on_export_completed($result); - } + # this updates buttons status + $self->object_list_changed; + }); + + # start background process, whose completion event handler + # will detect $self->{export_gcode_output_file} and proceed with export + $self->start_background_process; # this updates buttons status $self->object_list_changed; @@ -1577,7 +1558,7 @@ sub reset_thumbnail { sub update { my ($self, $force_autocenter) = @_; - if ($Slic3r::GUI::Settings->{_}{autocenter} || $force_autocenter) { + if (wxTheApp->{app_config}->get("autocenter") || $force_autocenter) { $self->{model}->center_instances_around_point($self->bed_centerf); } @@ -1604,9 +1585,7 @@ sub update { # and some reasonable default has to be selected for the additional extruders. sub on_extruders_change { my ($self, $num_extruders) = @_; - my $choices = $self->{preset_choosers}{filament}; - wxTheApp->{preset_bundle}->update_multi_material_filament_presets; while (int(@$choices) < $num_extruders) { # copy strings from first choice diff --git a/lib/Slic3r/GUI/Plater/2D.pm b/lib/Slic3r/GUI/Plater/2D.pm index 089b25947..a1e077591 100644 --- a/lib/Slic3r/GUI/Plater/2D.pm +++ b/lib/Slic3r/GUI/Plater/2D.pm @@ -9,7 +9,7 @@ use utf8; use List::Util qw(min max first); use Slic3r::Geometry qw(X Y scale unscale convex_hull); use Slic3r::Geometry::Clipper qw(offset JT_ROUND intersection_pl); -use Wx qw(:misc :pen :brush :sizer :font :cursor wxTAB_TRAVERSAL); +use Wx qw(wxTheApp :misc :pen :brush :sizer :font :cursor wxTAB_TRAVERSAL); use Wx::Event qw(EVT_MOUSE_EVENTS EVT_PAINT EVT_ERASE_BACKGROUND EVT_SIZE); use base 'Wx::Panel'; @@ -102,7 +102,7 @@ sub repaint { } # draw print center - if (@{$self->{objects}} && $Slic3r::GUI::Settings->{_}{autocenter}) { + if (@{$self->{objects}} && wxTheApp->{app_config}->get("autocenter")) { my $center = $self->unscaled_point_to_pixel($self->{print_center}); $dc->SetPen($self->{print_center_pen}); $dc->DrawLine($center->[X], 0, $center->[X], $size[Y]); @@ -197,7 +197,6 @@ sub repaint { sub mouse_event { my ($self, $event) = @_; - my $pos = $event->GetPosition; my $point = $self->point_to_model_units([ $pos->x, $pos->y ]); #]] if ($event->ButtonDown) { @@ -257,7 +256,7 @@ sub mouse_event { } sub update_bed_size { - my $self = shift; + my ($self) = @_; # when the canvas is not rendered yet, its GetSize() method returns 0,0 my $canvas_size = $self->GetSize; diff --git a/lib/Slic3r/GUI/Preferences.pm b/lib/Slic3r/GUI/Preferences.pm index 4b6c665b7..ca953e215 100644 --- a/lib/Slic3r/GUI/Preferences.pm +++ b/lib/Slic3r/GUI/Preferences.pm @@ -10,6 +10,7 @@ sub new { my $self = $class->SUPER::new($parent, -1, "Preferences", wxDefaultPosition, wxDefaultSize); $self->{values} = {}; + my $app_config = wxTheApp->{app_config}; my $optgroup; $optgroup = Slic3r::GUI::OptionsGroup->new( parent => $self, @@ -25,7 +26,7 @@ sub new { # type => 'bool', # label => 'Check for updates', # tooltip => 'If this is enabled, Slic3r will check for updates daily and display a reminder if a newer version is available.', -# default => $Slic3r::GUI::Settings->{_}{version_check} // 1, +# default => $app_config->get("version_check") // 1, # readonly => !wxTheApp->have_version_check, # )); $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new( @@ -33,36 +34,35 @@ sub new { type => 'bool', label => 'Remember output directory', tooltip => 'If this is enabled, Slic3r will prompt the last output directory instead of the one containing the input files.', - default => $Slic3r::GUI::Settings->{_}{remember_output_path}, + default => $app_config->get("remember_output_path"), )); $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new( opt_id => 'autocenter', type => 'bool', label => 'Auto-center parts', tooltip => 'If this is enabled, Slic3r will auto-center objects around the print bed center.', - default => $Slic3r::GUI::Settings->{_}{autocenter}, + default => $app_config->get("autocenter"), )); $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new( opt_id => 'background_processing', type => 'bool', label => 'Background processing', tooltip => 'If this is enabled, Slic3r will pre-process objects as soon as they\'re loaded in order to save time when exporting G-code.', - default => $Slic3r::GUI::Settings->{_}{background_processing}, - readonly => !$Slic3r::have_threads, + default => $app_config->get("background_processing"), )); $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new( opt_id => 'no_controller', type => 'bool', label => 'Disable USB/serial connection', tooltip => 'Disable communication with the printer over a serial / USB cable. This simplifies the user interface in case the printer is never attached to the computer.', - default => $Slic3r::GUI::Settings->{_}{no_controller}, + default => $app_config->get("no_controller"), )); $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new( opt_id => 'no_defaults', type => 'bool', label => 'Suppress "- default -" presets', tooltip => 'Suppress "- default -" presets in the Print / Filament / Printer selections once there are any other valid presets available.', - default => $Slic3r::GUI::Settings->{_}{no_defaults}, + default => $app_config->get("no_defaults"), )); my $sizer = Wx::BoxSizer->new(wxVERTICAL); @@ -79,15 +79,15 @@ sub new { } sub _accept { - my $self = shift; + my ($self) = @_; if (defined($self->{values}{no_controller}) || defined($self->{values}{no_defaults})) { Slic3r::GUI::warning_catcher($self)->("You need to restart Slic3r to make the changes effective."); } - $Slic3r::GUI::Settings->{_}{$_} = $self->{values}{$_} for keys %{$self->{values}}; - wxTheApp->save_settings; + my $app_config = wxTheApp->{app_config}; + $app_config->set($_, $self->{values}{$_}) for keys %{$self->{values}}; $self->EndModal(wxID_OK); $self->Close; # needed on Linux diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 1375bb92b..2718d4f5e 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -125,15 +125,9 @@ sub save_preset { $self->{treectrl}->SetFocus; if (!defined $name) { - my $preset = $self->{presets}->get_edited_preset; + my $preset = $self->{presets}->get_selected_preset; my $default_name = $preset->default ? 'Untitled' : $preset->name; $default_name =~ s/\.[iI][nN][iI]$//; - - my @prsts = @{$self->{presets}}; - print "Num of presets: ". int(@prsts) . "\n"; - for my $pr (@prsts) { - print "Name: " . $pr->name . " default " . $pr->default . "\n"; - } my $dlg = Slic3r::GUI::SavePresetWindow->new($self, title => lc($self->title), default => $default_name, @@ -156,16 +150,16 @@ sub delete_preset { my ($self) = @_; my $current_preset = $self->{presets}->get_selected_preset; # Don't let the user delete the '- default -' configuration. + my $msg = 'Are you sure you want to ' . ($current_preset->external ? 'remove' : 'delete') . ' the selected preset?'; + my $title = ($current_preset->external ? 'Remove' : 'Delete') . ' Preset'; return if $current_preset->default || - wxID_YES != Wx::MessageDialog->new($self, "Are you sure you want to delete the selected preset?", 'Delete Preset', wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION)->ShowModal; + wxID_YES != Wx::MessageDialog->new($self, $msg, $title, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION)->ShowModal; # Delete the file and select some other reasonable preset. # The 'external' presets will only be removed from the preset list, their files will not be deleted. eval { $self->{presets}->delete_current_preset; }; Slic3r::GUI::catch_error($self) and return; - # Delete the item from the UI component and activate another preset. - $self->{presets}->update_tab_ui($self->{presets_choice}); - # Update the selection boxes at the patter. - $self->_on_presets_changed; + # Load the newly selected preset into the UI, update selection combo boxes with their dirty flags. + $self->load_current_preset; } # Register the on_value_change callback. @@ -203,7 +197,6 @@ sub _update {} # to uddate number of "filament" selection boxes when the number of extruders change. sub _on_presets_changed { my ($self) = @_; - print "Tab::_on_presets_changed\n"; $self->{on_presets_changed}->($self->{presets}) if $self->{on_presets_changed}; } @@ -237,38 +230,34 @@ sub may_discard_current_preset_if_dirty } # Called by the UI combo box when the user switches profiles. -# Select a preset by a name. If ! defined(name), then the first visible preset is selected. +# 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. sub select_preset { my ($self, $name, $force) = @_; - print "select_preset 1\n"; - if (! $self->may_discard_current_preset_if_dirty) { + $force //= 0; + if (! $force && ! $self->may_discard_current_preset_if_dirty) { $self->{presets}->update_tab_ui($self->{presets_choice}); # Trigger the on_presets_changed event so that we also restore the previous value in the plater selector. $self->_on_presets_changed; return; } - print "select_preset 2\n"; - $self->{presets}->select_preset_by_name(defined $name ? $name : ""); - print "select_preset 3\n"; + if (defined $name) { + $self->{presets}->select_preset_by_name($name); + } else { + $self->{presets}->select_preset(0); + } # Initialize the UI from the current preset. $self->load_current_preset; - print "select_preset 4\n"; - # Save the current application settings with the newly selected preset name. - wxTheApp->save_settings; - print "select_preset 5\n"; } # Initialize the UI from the current preset. sub load_current_preset { my ($self) = @_; - print "load_current_preset 1\n"; $self->{presets}->update_tab_ui($self->{presets_choice}); - print "load_current_preset 2\n"; my $preset = $self->{presets}->get_current_preset; eval { local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self); - my $method = ($preset->default || $preset->external) ? 'Disable' : 'Enable'; + my $method = $preset->default ? 'Disable' : 'Enable'; $self->{btn_delete_preset}->$method; $self->_update; # For the printer profile, generate the extruder pages. @@ -281,8 +270,9 @@ sub load_current_preset { # preset dirty again # (not sure this is true anymore now that update_dirty is idempotent) wxTheApp->CallAfter(sub { - $self->_on_presets_changed; $self->update_dirty; + #the following is called by update_dirty + #$self->_on_presets_changed; }); } @@ -404,7 +394,7 @@ sub build { my $self = shift; $self->{presets} = wxTheApp->{preset_bundle}->print; - $self->{config} = $self->{presets}->get_edited_preset->config_ref; + $self->{config} = $self->{presets}->get_edited_preset->config; { my $page = $self->add_options_page('Layers and perimeters', 'layers.png'); @@ -608,7 +598,7 @@ sub build { $optgroup->append_single_option_line('clip_multipart_objects'); $optgroup->append_single_option_line('elefant_foot_compensation'); $optgroup->append_single_option_line('xy_size_compensation'); -# $optgroup->append_single_option_line('threads') if $Slic3r::have_threads; +# $optgroup->append_single_option_line('threads'); $optgroup->append_single_option_line('resolution'); } } @@ -675,7 +665,7 @@ sub _update { my ($self) = @_; $self->Freeze; - my $config = $self->{presets}->get_edited_preset->config_ref; + my $config = $self->{config}; if ($config->spiral_vase && !($config->perimeters == 1 && $config->top_solid_layers == 0 && $config->fill_density == 0)) { my $dialog = Wx::MessageDialog->new($self, @@ -882,7 +872,7 @@ sub build { my $self = shift; $self->{presets} = wxTheApp->{preset_bundle}->filament; - $self->{config} = $self->{presets}->get_edited_preset->config_ref; + $self->{config} = $self->{presets}->get_edited_preset->config; { my $page = $self->add_options_page('Filament', 'spool.png'); @@ -1061,8 +1051,9 @@ sub build { my ($self, %params) = @_; $self->{presets} = wxTheApp->{preset_bundle}->printer; - $self->{config} = $self->{presets}->get_edited_preset->config_ref; - + $self->{config} = $self->{presets}->get_edited_preset->config; + $self->{extruders_count} = scalar @{$self->{config}->nozzle_diameter}; + my $bed_shape_widget = sub { my ($parent) = @_; @@ -1086,9 +1077,7 @@ sub build { return $sizer; }; - - $self->{extruders_count} = 1; - + { my $page = $self->add_options_page('General', 'printer_empty.png'); { @@ -1117,13 +1106,16 @@ sub build { $optgroup->append_single_option_line('single_extruder_multi_material'); } $optgroup->on_change(sub { - my ($opt_id) = @_; - if ($opt_id eq 'extruders_count') { - wxTheApp->CallAfter(sub { + my ($opt_key, $value) = @_; + wxTheApp->CallAfter(sub { + if ($opt_key eq 'extruders_count') { $self->_extruders_count_changed($optgroup->get_value('extruders_count')); - }); - $self->update_dirty; - } + $self->update_dirty; + } else { + $self->update_dirty; + $self->_on_value_change($opt_key, $value); + } + }); }); } if (!$params{no_controller}) @@ -1326,43 +1318,23 @@ sub build { sub _update_serial_ports { my ($self) = @_; - $self->get_field('serial_port')->set_values([ wxTheApp->scan_serial_ports ]); + $self->get_field('serial_port')->set_values([ Slic3r::GUI::scan_serial_ports ]); } sub _extruders_count_changed { my ($self, $extruders_count) = @_; - $self->{extruders_count} = $extruders_count; + wxTheApp->{preset_bundle}->printer->get_edited_preset->set_num_extruders($extruders_count); + wxTheApp->{preset_bundle}->update_multi_material_filament_presets; $self->_build_extruder_pages; $self->_on_value_change('extruders_count', $extruders_count); } -sub _extruder_options { - qw(nozzle_diameter min_layer_height max_layer_height extruder_offset - retract_length retract_lift retract_lift_above retract_lift_below retract_speed deretract_speed - retract_before_wipe retract_restart_extra retract_before_travel wipe - retract_layer_change retract_length_toolchange retract_restart_extra_toolchange extruder_colour) } - sub _build_extruder_pages { - my $self = shift; - + my ($self) = @_; my $default_config = Slic3r::Config::Full->new; - + foreach my $extruder_idx (@{$self->{extruder_pages}} .. $self->{extruders_count}-1) { - # extend options - foreach my $opt_key ($self->_extruder_options) { - my $values = $self->{config}->get($opt_key); - if (!defined $values) { - $values = [ $default_config->get_at($opt_key, 0) ]; - } else { - # use last extruder's settings for the new one - my $last_value = $values->[-1]; - $values->[$extruder_idx] //= $last_value; - } - $self->{config}->set($opt_key, $values) - or die "Unable to extend $opt_key"; - } - # build page my $page = $self->{extruder_pages}[$extruder_idx] = $self->add_options_page("Extruder " . ($extruder_idx + 1), 'funnel.png'); { @@ -1412,14 +1384,6 @@ sub _build_extruder_pages { splice @{$self->{extruder_pages}}, $self->{extruders_count}; } - # remove extra config values - foreach my $opt_key ($self->_extruder_options) { - my $values = $self->{config}->get($opt_key); - splice @$values, $self->{extruders_count} if $self->{extruders_count} <= $#$values; - $self->{config}->set($opt_key, $values) - or die "Unable to truncate $opt_key"; - } - # rebuild page list my @pages_without_extruders = (grep $_->{title} !~ /^Extruder \d+/, @{$self->{pages}}); my $page_notes = pop @pages_without_extruders; @@ -1513,15 +1477,12 @@ sub _update { # this gets executed after preset is loaded and before GUI fields are updated sub on_preset_loaded { - my $self = shift; - + my ($self) = @_; # update the extruders count field - { - # update the GUI field according to the number of nozzle diameters supplied - my $extruders_count = scalar @{ $self->{config}->nozzle_diameter }; - $self->set_value('extruders_count', $extruders_count); - $self->_extruders_count_changed($extruders_count); - } + my $extruders_count = scalar @{ $self->{config}->nozzle_diameter }; + $self->set_value('extruders_count', $extruders_count); + # update the GUI field according to the number of nozzle diameters supplied + $self->_extruders_count_changed($extruders_count); } # Single Tab page containing a {vsizer} of {optgroups} |