mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	Another step towards the C++ presets.
This commit is contained in:
		
							parent
							
								
									ee645007f2
								
							
						
					
					
						commit
						5a99e694ce
					
				
					 11 changed files with 431 additions and 483 deletions
				
			
		|  | @ -133,14 +133,16 @@ sub _init_tabpanel { | |||
|                 } | ||||
|             } | ||||
|         }); | ||||
|         $tab->load_presets; | ||||
|         # Load the currently selected preset into the GUI, update the preset selection box. | ||||
|         $tab->load_current_preset; | ||||
|         $panel->AddPage($tab, $tab->title); | ||||
|     } | ||||
|      | ||||
|     if ($self->{plater}) { | ||||
|         $self->{plater}->on_select_preset(sub { | ||||
|             my ($group, $i) = @_; | ||||
| 	        $self->{options_tabs}{$group}->select_preset($i); | ||||
|             my ($group, $name) = @_; | ||||
|             print "MainFrame::on_select_preset callback, group: $group, name: $name\n"; | ||||
| 	        $self->{options_tabs}{$group}->select_preset($name); | ||||
|         }); | ||||
|          | ||||
|         # load initial config | ||||
|  | @ -503,19 +505,19 @@ sub extra_variables { | |||
| 
 | ||||
| sub export_config { | ||||
|     my $self = shift; | ||||
|      | ||||
|     my $config = $self->config; | ||||
|     eval { | ||||
|         # validate configuration | ||||
|         $config->validate; | ||||
|     }; | ||||
|     # Generate a cummulative configuration for the selected print, filaments and printer.     | ||||
|     my $config = wxTheApp->{preset_bundle}->full_config(); | ||||
|     # Validate the cummulative configuration. | ||||
|     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,  | ||||
|         &Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); | ||||
|     if ($dlg->ShowModal == wxID_OK) { | ||||
|     my $file = ($dlg->ShowModal == wxID_OK) ? $dlg->GetPath : undef; | ||||
|     $dlg->Destroy; | ||||
|     if (defined $file) { | ||||
|         my $file = $dlg->GetPath; | ||||
|         $Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file); | ||||
|         wxTheApp->save_settings; | ||||
|  | @ -537,10 +539,10 @@ sub load_config_file { | |||
|         $file = $dlg->GetPaths; | ||||
|         $dlg->Destroy; | ||||
|     } | ||||
|     for my $tab (values %{$self->{options_tabs}}) { | ||||
|         # Dont proceed further if the config file cannot be loaded. | ||||
|         return undef if ! $tab->load_config_file($file); | ||||
|     } | ||||
|     eval { wxTheApp->{preset_bundle}->load_config_file($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; | ||||
|     $last_config = $file; | ||||
|  | @ -548,38 +550,23 @@ sub load_config_file { | |||
| 
 | ||||
| sub export_configbundle { | ||||
|     my $self = shift; | ||||
|      | ||||
|     eval { | ||||
|         # validate current configuration in case it's dirty | ||||
|         $self->config->validate; | ||||
|     }; | ||||
|     # validate current configuration in case it's dirty | ||||
|     eval { $self->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,  | ||||
|         &Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); | ||||
|     if ($dlg->ShowModal == wxID_OK) { | ||||
|         my $file = $dlg->GetPath; | ||||
|     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; | ||||
|          | ||||
|         # leave default category empty to prevent the bundle from being parsed as a normal config file | ||||
|         my $ini = { _ => {} }; | ||||
|         $ini->{settings}{$_} = $Slic3r::GUI::Settings->{_}{$_} for qw(autocenter); | ||||
|         $ini->{presets} = $Slic3r::GUI::Settings->{presets}; | ||||
| 
 | ||||
|         foreach my $section (qw(print filament printer)) { | ||||
|             my $presets = wxTheApp->{preset_bundle}->$section->presets_hash; | ||||
|             foreach my $preset_name (keys %{$presets}) { | ||||
|                 my $config = Slic3r::Config->load($presets->{$preset_name}); | ||||
|                 $ini->{"$section:$preset_name"} = $config->as_ini->{_}; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         Slic3r::Config->write_ini($file, $ini); | ||||
|         eval { $self->{presets}->export_configbundle($file); }; | ||||
|         Slic3r::GUI::catch_error($self) and return; | ||||
|     } | ||||
|     $dlg->Destroy; | ||||
| } | ||||
| 
 | ||||
| sub load_configbundle { | ||||
|  | @ -596,46 +583,17 @@ sub load_configbundle { | |||
|      | ||||
|     $Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file); | ||||
|     wxTheApp->save_settings; | ||||
|      | ||||
|     # load .ini file | ||||
|     my $ini = Slic3r::Config->read_ini($file); | ||||
|      | ||||
|     if ($ini->{settings}) { | ||||
|         $Slic3r::GUI::Settings->{_}{$_} = $ini->{settings}{$_} for keys %{$ini->{settings}}; | ||||
|         wxTheApp->save_settings; | ||||
|     } | ||||
|     if ($ini->{presets}) { | ||||
|         $Slic3r::GUI::Settings->{presets} = $ini->{presets}; | ||||
|         wxTheApp->save_settings; | ||||
|     } | ||||
| 
 | ||||
|     my $imported = 0; | ||||
|     INI_BLOCK: foreach my $ini_category (sort keys %$ini) { | ||||
|         next unless $ini_category =~ /^(print|filament|printer):(.+)$/; | ||||
|         my ($section, $preset_name) = ($1, $2); | ||||
|         my $config = Slic3r::Config->load_ini_hash($ini->{$ini_category}); | ||||
|         next if $skip_no_id && !$config->get($section . "_settings_id"); | ||||
|          | ||||
|         { | ||||
|             my $current_presets = wxTheApp->{preset_bundle}->$section->presets_hash; | ||||
|             my %current_ids = map { $_ => 1 } | ||||
|                 grep $_, | ||||
|                 map Slic3r::Config->load($_)->get($section . "_settings_id"), | ||||
|                 values %{$current_presets}; | ||||
|             next INI_BLOCK if exists $current_ids{$config->get($section . "_settings_id")}; | ||||
|         } | ||||
|          | ||||
|         $config->save(sprintf Slic3r::data_dir . "/%s/%s.ini", $section, $preset_name); | ||||
|         Slic3r::debugf "Imported %s preset %s\n", $section, $preset_name; | ||||
|         $imported++; | ||||
|     } | ||||
|     my $presets_imported = 0; | ||||
|     eval { $presets_imported = $self->{presets}->load_configbundle($file); }; | ||||
|     Slic3r::GUI::catch_error($self) and return; | ||||
| 
 | ||||
|     # Load the currently selected preset into the GUI, update the preset selection box. | ||||
|     foreach my $tab (values %{$self->{options_tabs}}) { | ||||
|         $tab->load_presets; | ||||
|         $tab->load_current_preset; | ||||
|     } | ||||
|      | ||||
|     return if !$imported; | ||||
|      | ||||
|     my $message = sprintf "%d presets successfully imported.", $imported; | ||||
|     my $message = sprintf "%d presets successfully imported.", $presets_imported; | ||||
|     Slic3r::GUI::show_info($self, $message); | ||||
| } | ||||
| 
 | ||||
|  | @ -669,12 +627,6 @@ sub config_wizard { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| sub filament_preset_names { | ||||
|     my ($self) = @_; | ||||
|     return map $self->{options_tabs}{filament}->{presets}->preset($_)->name, | ||||
|         $self->{plater}->filament_presets; | ||||
| } | ||||
| 
 | ||||
| # This is called when closing the application, when loading a config file or when starting the config wizard | ||||
| # to notify the user whether he is aware that some preset changes will be lost. | ||||
| sub check_unsaved_changes { | ||||
|  |  | |||
|  | @ -366,20 +366,17 @@ sub new { | |||
|             # once a printer preset with multiple extruders is activated. | ||||
|             # $self->{preset_choosers}{$group}[$idx] | ||||
|             $self->{preset_choosers} = {}; | ||||
|             # Boolean indicating whether the '- default -' preset is shown by the combo box. | ||||
|             $self->{preset_choosers_default_suppressed} = {}; | ||||
|             for my $group (qw(print filament printer)) { | ||||
|                 my $text = Wx::StaticText->new($self, -1, "$group_labels{$group}:", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); | ||||
|                 $text->SetFont($Slic3r::GUI::small_font); | ||||
|                 my $choice = Wx::BitmapComboBox->new($self, -1, "", wxDefaultPosition, wxDefaultSize, [], wxCB_READONLY); | ||||
|                 EVT_LEFT_DOWN($choice, sub { $self->filament_color_box_lmouse_down(0, @_); } ); | ||||
|                 $self->{preset_choosers}{$group} = [$choice]; | ||||
|                 $self->{preset_choosers_default_suppressed}{$group} = 0; | ||||
|                 # setup the listener | ||||
|                 EVT_COMBOBOX($choice, $choice, sub { | ||||
|                     my ($choice) = @_; | ||||
|                     wxTheApp->CallAfter(sub { | ||||
|                         $self->_on_select_preset($group, $choice); | ||||
|                         $self->_on_select_preset($group, $choice, 0); | ||||
|                     }); | ||||
|                 }); | ||||
|                 $presets->Add($text, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxRIGHT, 4); | ||||
|  | @ -504,28 +501,23 @@ sub on_select_preset { | |||
|     $self->{on_select_preset} = $cb; | ||||
| } | ||||
| 
 | ||||
| # Called from the platter combo boxes selecting the active print, filament or printer. | ||||
| sub _on_select_preset { | ||||
| 	my $self = shift; | ||||
| 	my ($group, $choice) = @_; | ||||
| 	 | ||||
| 	my ($self, $group, $choice, $idx) = @_; | ||||
| 	# If user changed a filament preset and the selected machine is equipped with multiple extruders, | ||||
|     # there are multiple filament selection combo boxes shown at the platter. In that case | ||||
|     # don't propagate the filament selection changes to the tab. | ||||
|     my $default_suppressed = $self->{preset_choosers_default_suppressed}{$group}; | ||||
|     if ($group eq 'filament') { | ||||
|         wxTheApp->{preset_bundle}->set_filament_preset($idx, $choice->GetStringSelection); | ||||
|     } | ||||
| 	if ($group eq 'filament' && @{$self->{preset_choosers}{filament}} > 1) { | ||||
|         # Indices of the filaments selected. | ||||
| 		my @filament_presets = $self->filament_presets; | ||||
| 		$Slic3r::GUI::Settings->{presets}{filament} = $choice->GetString($filament_presets[0] - $default_suppressed) . ".ini"; | ||||
| 		$Slic3r::GUI::Settings->{presets}{"filament_${_}"} = $choice->GetString($filament_presets[$_] - $default_suppressed) | ||||
| 			for 1 .. $#filament_presets; | ||||
| 		wxTheApp->save_settings; | ||||
|         $self->update_filament_colors_preview($choice); | ||||
|         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, scalar($choice->GetSelection) + $default_suppressed) | ||||
|     	$self->{on_select_preset}->($group, $choice->GetStringSelection) | ||||
|     	    if $self->{on_select_preset}; | ||||
|     } | ||||
| 	 | ||||
| 	# get new config and generate on_config_change() event for updating plater and other things | ||||
| 	$self->on_config_change(wxTheApp->{preset_bundle}->full_config); | ||||
| } | ||||
|  | @ -572,127 +564,31 @@ sub update_ui_from_settings | |||
| # For Print settings and Printer, synchronize the selection index with their tabs. | ||||
| # For Filament, synchronize the selection index for a single extruder printer only, otherwise keep the selection. | ||||
| sub update_presets { | ||||
|     # $presets: one of qw(print filament printer) | ||||
|     # $selected: index of the selected preset in the array. This may not correspond | ||||
|     # with the index of selection in the UI element, where not all items are displayed. | ||||
|     my ($self, $group, $presets, $default_suppressed, $selected, $is_dirty) = @_; | ||||
| 
 | ||||
|     print "Plater.pm update_presets presets: $presets\n"; | ||||
| #    my @choosers = @{ $self->{preset_choosers}{$group} }; | ||||
| #    my $choice_idx = 0; | ||||
| #    foreach my $choice (@choosers) { | ||||
| #        if ($group eq 'filament' && @choosers > 1) { | ||||
|             # if we have more than one filament chooser, keep our selection | ||||
|             # instead of importing the one from the tab | ||||
| #            $selected = $choice->GetSelection + $self->{preset_choosers_default_suppressed}{$group}; | ||||
| #            $is_dirty = 0; | ||||
| #        } | ||||
| #        $choice->Clear; | ||||
| #        foreach my $preset (@{$presets}) { | ||||
| #            print "Prset of $presets: $preset\n"; | ||||
| #            next if ($preset->default && $default_suppressed); | ||||
| #            my $bitmap; | ||||
| #            if ($group eq 'filament') { | ||||
| #                $bitmap = Wx::Bitmap->new(Slic3r::var("spool.png"), wxBITMAP_TYPE_PNG); | ||||
| #            } elsif ($group eq 'print') { | ||||
| #                $bitmap = Wx::Bitmap->new(Slic3r::var("cog.png"), wxBITMAP_TYPE_PNG); | ||||
| #            } elsif ($group eq 'printer') { | ||||
| #                $bitmap = Wx::Bitmap->new(Slic3r::var("printer_empty.png"), wxBITMAP_TYPE_PNG); | ||||
| #            } | ||||
| #            $choice->AppendString($preset->name, $bitmap); | ||||
| #        } | ||||
|          | ||||
| #        if ($selected <= $#$presets) { | ||||
| #            my $idx = $selected - $default_suppressed; | ||||
| #            if ($idx >= 0) { | ||||
| #                if ($is_dirty) { | ||||
| #                    $choice->SetString($idx, $choice->GetString($idx) . " (modified)"); | ||||
| #                } | ||||
| #                # call SetSelection() only after SetString() otherwise the new string | ||||
| #                # won't be picked up as the visible string | ||||
| #                $choice->SetSelection($idx); | ||||
| #            } | ||||
| #        } | ||||
| #        $choice_idx += 1; | ||||
| #    } | ||||
| 
 | ||||
| #    $self->{preset_choosers_default_suppressed}{$group} = $default_suppressed; | ||||
| 
 | ||||
|     wxTheApp->CallAfter(sub { $self->update_filament_colors_preview }) if $group eq 'filament' || $group eq 'printer'; | ||||
| } | ||||
| 
 | ||||
| # Update the color icon in front of each filament selection on the platter. | ||||
| # If the extruder has a preview color assigned, apply the extruder color to the active selection. | ||||
| # Always apply the filament color to the non-active selections. | ||||
| sub update_filament_colors_preview { | ||||
|     my ($self, $extruder_idx) = shift; | ||||
| 
 | ||||
| #    my @choosers = @{$self->{preset_choosers}{filament}}; | ||||
| 
 | ||||
| #    if (ref $extruder_idx) { | ||||
|         # $extruder_idx is the chooser. | ||||
| #        foreach my $chooser (@choosers) { | ||||
| #            if ($extruder_idx == $chooser) { | ||||
| #                $extruder_idx = $chooser; | ||||
| #                last; | ||||
| #            } | ||||
| #        } | ||||
| #    } | ||||
| 
 | ||||
| #    my @extruder_colors = @{$self->{config}->extruder_colour}; | ||||
| 
 | ||||
| #    my @extruder_list; | ||||
| #    if (defined $extruder_idx) { | ||||
| #        @extruder_list = ($extruder_idx); | ||||
| #    } else { | ||||
|         # Collect extruder indices. | ||||
| #        @extruder_list = (0..$#extruder_colors); | ||||
| #    } | ||||
| 
 | ||||
| #    my $filament_tab       = $self->GetFrame->{options_tabs}{filament}; | ||||
| #    my $presets            = $filament_tab->{presets}; | ||||
| #    my $default_suppressed = $filament_tab->{default_suppressed}; | ||||
| 
 | ||||
| #    foreach my $extruder_idx (@extruder_list) { | ||||
| #        my $chooser = $choosers[$extruder_idx]; | ||||
| #        my $extruder_color = $self->{config}->extruder_colour->[$extruder_idx]; | ||||
| #        my $preset_idx = 0; | ||||
| #        my $selection_idx = $chooser->GetSelection; | ||||
| #        foreach my $preset (@$presets) { | ||||
| #            my $bitmap; | ||||
| #            if ($preset->default) { | ||||
| #                next if $default_suppressed; | ||||
| #            } else { | ||||
|                 # Assign an extruder color to the selected item if the extruder color is defined. | ||||
| #                my $filament_colour_cfg = $preset->config_ref->filament_colour; | ||||
| #                print $filament_colour_cfg . "\n"; | ||||
| #                my $filament_rgb = $filament_colour_cfg->[0]; | ||||
| #                my $extruder_rgb = ($preset_idx == $selection_idx && $extruder_color =~ m/^#[[:xdigit:]]{6}/) ? $extruder_color : $filament_rgb; | ||||
| #                $filament_rgb =~ s/^#//; | ||||
| #                $extruder_rgb =~ s/^#//; | ||||
| #                my $image = Wx::Image->new(24,16); | ||||
| #                if ($filament_rgb ne $extruder_rgb) { | ||||
| #                    my @rgb = unpack 'C*', pack 'H*', $extruder_rgb; | ||||
| #                    $image->SetRGB(Wx::Rect->new(0,0,16,16), @rgb); | ||||
| #                    @rgb = unpack 'C*', pack 'H*', $filament_rgb; | ||||
| #                    $image->SetRGB(Wx::Rect->new(16,0,8,16), @rgb); | ||||
| #                } else { | ||||
| #                    my @rgb = unpack 'C*', pack 'H*', $filament_rgb; | ||||
| #                    $image->SetRGB(Wx::Rect->new(0,0,24,16), @rgb); | ||||
| #                } | ||||
| #                $bitmap = Wx::Bitmap->new($image); | ||||
| #            } | ||||
| #            $chooser->SetItemBitmap($preset_idx, $bitmap) if $bitmap; | ||||
| #            $preset_idx += 1; | ||||
| #        } | ||||
| #    } | ||||
| } | ||||
| 
 | ||||
| # Return a vector of indices of filaments selected by the $self->{preset_choosers}{filament} combo boxes. | ||||
| sub filament_presets { | ||||
|     my $self = shift; | ||||
|     # force scalar context for GetSelection() as it's context-aware | ||||
|     return map scalar($_->GetSelection) + $self->{preset_choosers_default_suppressed}{filament}, @{ $self->{preset_choosers}{filament} }; | ||||
|     # $group: one of qw(print filament printer) | ||||
|     # $presets: PresetCollection | ||||
|     my ($self, $group, $presets) = @_; | ||||
|     print "Platter::update_presets\n"; | ||||
|     my @choosers = @{$self->{preset_choosers}{$group}}; | ||||
|     if ($group eq 'filament') { | ||||
|         my $choice_idx = 0; | ||||
|         if (int(@choosers) == 1) { | ||||
|             # Single filament printer, synchronize the filament presets. | ||||
|             wxTheApp->{preset_bundle}->set_filament_preset(0, wxTheApp->{preset_bundle}->filament->get_selected_preset->name); | ||||
|         } | ||||
|         foreach my $choice (@choosers) { | ||||
|             wxTheApp->{preset_bundle}->update_platter_filament_ui($choice_idx, $choice); | ||||
|             $choice_idx += 1; | ||||
|         } | ||||
|     } elsif ($group eq 'print') { | ||||
|         wxTheApp->{preset_bundle}->print->update_platter_ui($choosers[0]);         | ||||
|     } elsif ($group eq 'printer') { | ||||
|         wxTheApp->{preset_bundle}->printer->update_platter_ui($choosers[0]);         | ||||
|         my $choice_idx = 0; | ||||
|         foreach my $choice (@{$self->{preset_choosers}{filament}}) { | ||||
|             wxTheApp->{preset_bundle}->update_platter_filament_ui_colors($choice_idx, $choice); | ||||
|             $choice_idx += 1; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| sub add { | ||||
|  | @ -1557,7 +1453,7 @@ sub do_print { | |||
|     my $printer_panel = $controller->add_printer($printer_preset->name, $printer_preset->config); | ||||
|      | ||||
|     my $filament_stats = $self->{print}->filament_stats; | ||||
|     my @filament_names = $self->GetFrame->filament_preset_names; | ||||
|     my @filament_names = wxTheApp->{preset_bundle}->filament_presets; | ||||
|     $filament_stats = { map { $filament_names[$_] => $filament_stats->{$_} } keys %$filament_stats }; | ||||
|     $printer_panel->load_print_job($self->{print_file}, $filament_stats); | ||||
|      | ||||
|  | @ -1713,11 +1609,18 @@ sub update { | |||
| } | ||||
| 
 | ||||
| # When a number of extruders changes, the UI needs to be updated to show a single filament selection combo box per extruder. | ||||
| # Also the wxTheApp->{preset_bundle}->filament_presets needs to be resized accordingly | ||||
| # 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}; | ||||
|     while (@$choices < $num_extruders) { | ||||
|     print "on_extruders_change1 $num_extruders, current choices: " . int(@$choices) . "\n"; | ||||
|     wxTheApp->{preset_bundle}->update_multi_material_filament_presets; | ||||
|     print "on_extruders_change2 $num_extruders, current choices: " . int(@$choices) . "\n"; | ||||
| 
 | ||||
|     while (int(@$choices) < $num_extruders) { | ||||
|         print "Adding an extruder selection combo box\n"; | ||||
|         # copy strings from first choice | ||||
|         my @presets = $choices->[0]->GetStrings; | ||||
|          | ||||
|  | @ -1726,25 +1629,20 @@ sub on_extruders_change { | |||
|         my $extruder_idx = scalar @$choices; | ||||
|         EVT_LEFT_DOWN($choice, sub { $self->filament_color_box_lmouse_down($extruder_idx, @_); } ); | ||||
|         push @$choices, $choice; | ||||
|          | ||||
|         # copy icons from first choice | ||||
|         $choice->SetItemBitmap($_, $choices->[0]->GetItemBitmap($_)) for 0..$#presets; | ||||
|          | ||||
|         # insert new choice into sizer | ||||
|         $self->{presets_sizer}->Insert(4 + ($#$choices-1)*2, 0, 0); | ||||
|         $self->{presets_sizer}->Insert(5 + ($#$choices-1)*2, $choice, 0, wxEXPAND | wxBOTTOM, FILAMENT_CHOOSERS_SPACING); | ||||
|          | ||||
|         # setup the listener | ||||
|         EVT_COMBOBOX($choice, $choice, sub { | ||||
|             my ($choice) = @_; | ||||
|             wxTheApp->CallAfter(sub { | ||||
|                 $self->_on_select_preset('filament', $choice); | ||||
|                 $self->_on_select_preset('filament', $choice, $extruder_idx); | ||||
|             }); | ||||
|         }); | ||||
|          | ||||
|         # initialize selection | ||||
|         my $i = first { $choice->GetString($_) eq ($Slic3r::GUI::Settings->{presets}{"filament_" . $#$choices} || '') } 0 .. $#presets; | ||||
|         $choice->SetSelection($i || 0); | ||||
|         wxTheApp->{preset_bundle}->update_platter_filament_ui($extruder_idx, $choice); | ||||
|     } | ||||
|      | ||||
|     # remove unused choices if any | ||||
|  | @ -1758,8 +1656,7 @@ sub on_extruders_change { | |||
| } | ||||
| 
 | ||||
| sub on_config_change { | ||||
|     my $self = shift; | ||||
|     my ($config) = @_; | ||||
|     my ($self, $config) = @_; | ||||
|      | ||||
|     my $update_scheduled; | ||||
|     foreach my $opt_key (@{$self->{config}->diff($config)}) { | ||||
|  | @ -1864,7 +1761,7 @@ sub filament_color_box_lmouse_down | |||
|             $colors->[$extruder_idx] = $dialog->GetColourData->GetColour->GetAsString(wxC2S_HTML_SYNTAX); | ||||
|             $cfg->set('extruder_colour', $colors); | ||||
|             $self->GetFrame->{options_tabs}{printer}->load_config($cfg); | ||||
|             $self->update_filament_colors_preview($extruder_idx); | ||||
|             wxTheApp->{preset_bundle}->update_platter_filament_ui_colors($extruder_idx, $combobox); | ||||
|         } | ||||
|         $dialog->Destroy(); | ||||
|     } | ||||
|  | @ -1964,9 +1861,9 @@ sub object_list_changed { | |||
|         for grep $self->{"btn_$_"}, qw(reslice export_gcode print send_gcode); | ||||
| } | ||||
| 
 | ||||
| # Selection of an active 3D object changed. | ||||
| sub selection_changed { | ||||
|     my $self = shift; | ||||
|      | ||||
|     my ($obj_idx, $object) = $self->selected_object; | ||||
|     my $have_sel = defined $obj_idx; | ||||
|      | ||||
|  |  | |||
|  | @ -81,7 +81,8 @@ sub new { | |||
| sub _accept { | ||||
|     my $self = shift; | ||||
|      | ||||
|     if (defined($self->{values}{no_controller})) { | ||||
|     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."); | ||||
|     } | ||||
|      | ||||
|  |  | |||
|  | @ -68,8 +68,11 @@ sub new { | |||
|     $self->{treectrl} = Wx::TreeCtrl->new($self, -1, wxDefaultPosition, [185, -1], wxTR_NO_BUTTONS | wxTR_HIDE_ROOT | wxTR_SINGLE | wxTR_NO_LINES | wxBORDER_SUNKEN | wxWANTS_CHARS); | ||||
|     $left_sizer->Add($self->{treectrl}, 1, wxEXPAND); | ||||
|     $self->{icons} = Wx::ImageList->new(16, 16, 1); | ||||
|     # Map from an icon file name to its index in $self->{icons}. | ||||
|     $self->{icon_index} = {}; | ||||
|     # Index of the last icon inserted into $self->{icons}. | ||||
|     $self->{icon_count} = -1; | ||||
|     $self->{treectrl}->AssignImageList($self->{icons}); | ||||
|     $self->{iconcount} = -1; | ||||
|     $self->{treectrl}->AddRoot("root"); | ||||
|     $self->{pages} = []; | ||||
|     $self->{treectrl}->SetIndent(0); | ||||
|  | @ -94,7 +97,6 @@ sub new { | |||
|      | ||||
|     EVT_CHOICE($parent, $self->{presets_choice}, sub { | ||||
|         $self->select_preset($self->{presets_choice}->GetStringSelection); | ||||
|         $self->_on_presets_changed; | ||||
|     }); | ||||
|      | ||||
|     EVT_BUTTON($self, $self->{btn_save_preset}, sub { $self->save_preset }); | ||||
|  | @ -103,17 +105,17 @@ sub new { | |||
|     # Initialize the DynamicPrintConfig by default keys/values. | ||||
|     # Possible %params keys: no_controller | ||||
|     $self->build(%params); | ||||
|     $self->update_tree; | ||||
|     $self->rebuild_page_tree; | ||||
|     $self->_update; | ||||
|      | ||||
|     return $self; | ||||
| } | ||||
| 
 | ||||
| # Are the '- default -' selections suppressed by the Slic3r GUI preferences? | ||||
| sub no_defaults { | ||||
|     return $Slic3r::GUI::Settings->{_}{no_defaults} ? 1 : 0; | ||||
| } | ||||
| 
 | ||||
| # Save the current preset into file. | ||||
| # This removes the "dirty" flag of the preset, possibly creates a new preset under a new name, | ||||
| # and activates the new preset. | ||||
| # Wizard calls save_preset with a name "My Settings", otherwise no name is provided and this method | ||||
| # opens a Slic3r::GUI::SavePresetWindow dialog. | ||||
| sub save_preset { | ||||
|     my ($self, $name) = @_; | ||||
|      | ||||
|  | @ -127,18 +129,25 @@ sub save_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, | ||||
|             values  => [ map $_->name, grep !$_->default && !$_->external, @{$self->{presets}} ], | ||||
|         ); | ||||
|         return unless $dlg->ShowModal == wxID_OK; | ||||
|         $name = Slic3r::normalize_utf8_nfc($dlg->get_name); | ||||
|         $name = $dlg->get_name; | ||||
|     } | ||||
|      | ||||
|     $self->{config}->save(sprintf Slic3r::data_dir . "/%s/%s.ini", $self->name, $name); | ||||
|     $self->load_presets; | ||||
|     $self->select_preset($name); | ||||
|     # Save the preset into Slic3r::data_dir/section_name/preset_name.ini | ||||
|     eval { $self->{presets}->save_current_preset($name); }; | ||||
|     Slic3r::GUI::catch_error($self) and return; | ||||
|     # Add the new item into the UI component, remove dirty flags and activate the saved item. | ||||
|     $self->{presets}->update_tab_ui($self->{presets_choice}); | ||||
|     # Update the selection boxes at the platter. | ||||
|     $self->_on_presets_changed; | ||||
| } | ||||
| 
 | ||||
|  | @ -147,29 +156,35 @@ sub delete_preset { | |||
|     my ($self) = @_; | ||||
|     my $current_preset = $self->{presets}->get_selected_preset; | ||||
|     # Don't let the user delete the '- default -' configuration. | ||||
|     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; | ||||
|     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; | ||||
|     # Delete the file and select some other reasonable preset. | ||||
|     eval { $self->{presets}->delete_file($current_preset->name); }; | ||||
|     # 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. | ||||
|     $self->{presets}->update_platter_ui($self->{presets_choice}); | ||||
|     # 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; | ||||
| } | ||||
| 
 | ||||
| # Register the on_value_change callback. | ||||
| sub on_value_change { | ||||
|     my ($self, $cb) = @_; | ||||
|     $self->{on_value_change} = $cb; | ||||
| } | ||||
| 
 | ||||
| # Register the on_presets_changed callback. | ||||
| sub on_presets_changed { | ||||
|     my ($self, $cb) = @_; | ||||
|     $self->{on_presets_changed} = $cb; | ||||
| } | ||||
| 
 | ||||
| # This method is called whenever an option field is changed by the user. | ||||
| # Propagate event to the parent through the 'on_value_changed' callback | ||||
| # Propagate event to the parent through the 'on_value_change' callback | ||||
| # and call _update. | ||||
| # The on_value_change callback triggers Platter::on_config_change() to configure the 3D preview | ||||
| # (colors, wipe tower positon etc) and to restart the background slicing process. | ||||
| sub _on_value_change { | ||||
|     my ($self, $key, $value) = @_; | ||||
|     $self->{on_value_change}->($key, $value) if $self->{on_value_change}; | ||||
|  | @ -178,27 +193,28 @@ sub _on_value_change { | |||
| 
 | ||||
| # Override this to capture changes of configuration caused either by loading or switching a preset, | ||||
| # or by a user changing an option field. | ||||
| # This callback is useful for cross-validating configuration values of a single preset. | ||||
| sub _update {} | ||||
| 
 | ||||
| # Call a callback to update the selection of presets on the platter. | ||||
| # Call a callback to update the selection of presets on the platter: | ||||
| # To update the content of the selection boxes, | ||||
| # to update the filament colors of the selection boxes, | ||||
| # to update the "dirty" flags of the selection boxes, | ||||
| # to uddate number of "filament" selection boxes when the number of extruders change. | ||||
| sub _on_presets_changed { | ||||
|     my ($self) = @_; | ||||
|     $self->{on_presets_changed}->( | ||||
|         $self->{presets}, | ||||
|         $self->{default_suppressed}, | ||||
|         scalar($self->{presets_choice}->GetSelection) + $self->{default_suppressed}, | ||||
|         $self->{presets}->current_is_dirty, | ||||
|     ) if $self->{on_presets_changed}; | ||||
|     print "Tab::_on_presets_changed\n"; | ||||
|     $self->{on_presets_changed}->($self->{presets}) if $self->{on_presets_changed}; | ||||
| } | ||||
| 
 | ||||
| # For the printer profile, generate the extruder pages after a preset is loaded. | ||||
| sub on_preset_loaded {} | ||||
| 
 | ||||
| # 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. | ||||
| # If the current profile is modified, user is asked to save the changes. | ||||
| sub select_preset { | ||||
|     my ($self, $name) = @_; | ||||
| 
 | ||||
| # If the current preset is dirty, the user is asked whether the changes may be discarded. | ||||
| # if the current preset was not dirty, or the user agreed to discard the changes, 1 is returned. | ||||
| sub may_discard_current_preset_if_dirty | ||||
| { | ||||
|     my ($self) = @_; | ||||
|     if ($self->{presets}->current_is_dirty) { | ||||
|         # Display a dialog showing the dirty options in a human readable form. | ||||
|         my $old_preset = $self->{presets}->get_current_preset; | ||||
|  | @ -215,37 +231,52 @@ sub select_preset { | |||
|         my $changes = join "\n", map "- $_", @option_names; | ||||
|         my $confirm = Wx::MessageDialog->new($self, "$name has unsaved changes:\n$changes\n\nDiscard changes and continue anyway?", | ||||
|                                              'Unsaved Changes', wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION); | ||||
|         if ($confirm->ShowModal == wxID_NO) { | ||||
|             $self->{presets}->update_platter_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; | ||||
|         } | ||||
|         return 0 if $confirm->ShowModal == wxID_NO; | ||||
|     } | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
|     $self->{presets}->select_by_name_ui(defined $name ? $name : "", $self->{presets_choice}); | ||||
| # 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. | ||||
| # 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) { | ||||
|         $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"; | ||||
|     # 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; | ||||
|     my $preset_config = $preset->config; | ||||
|     eval { | ||||
|         local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self); | ||||
|         foreach my $opt_key (@{$self->{config}->get_keys}) { | ||||
|             if ($preset_config->has($opt_key) &&  | ||||
|                 $self->{config}->serialize($opt_key) ne $preset_config->serialize($opt_key)) { | ||||
|                 $self->{config}->set($opt_key, $preset_config->get($opt_key)); | ||||
|             } | ||||
|         } | ||||
|         ($preset->default || $preset->external) | ||||
|             ? $self->{btn_delete_preset}->Disable | ||||
|             : $self->{btn_delete_preset}->Enable; | ||||
|         my $method = ($preset->default || $preset->external) ? 'Disable' : 'Enable'; | ||||
|         $self->{btn_delete_preset}->$method; | ||||
|         $self->_update; | ||||
|         # For the printer profile, generate the extruder pages. | ||||
|         $self->on_preset_loaded; | ||||
|         # Reload preset pages with the new configuration values. | ||||
|         $self->reload_config; | ||||
|         # Use this preset the next time Slic3r starts. | ||||
|         $Slic3r::GUI::Settings->{presets}{$self->name} = $preset->file ? basename($preset->file) : ''; | ||||
|         $self->_reload_config; | ||||
|     }; | ||||
| 
 | ||||
|     # use CallAfter because some field triggers schedule on_change calls using CallAfter, | ||||
|     # and we don't want them to be called after this update_dirty() as they would mark the  | ||||
|     # preset dirty again | ||||
|  | @ -254,22 +285,25 @@ sub select_preset { | |||
|         $self->_on_presets_changed; | ||||
|         $self->update_dirty; | ||||
|     }); | ||||
|      | ||||
|     # Save the current application settings with the newly selected preset name. | ||||
|     wxTheApp->save_settings; | ||||
| } | ||||
| 
 | ||||
| sub add_options_page { | ||||
|     my $self = shift; | ||||
|     my ($title, $icon, %params) = @_; | ||||
|      | ||||
|     my ($self, $title, $icon, %params) = @_; | ||||
|     # Index of $icon in an icon list $self->{icons}. | ||||
|     my $icon_idx = 0; | ||||
|     if ($icon) { | ||||
|         my $bitmap = Wx::Bitmap->new(Slic3r::var($icon), wxBITMAP_TYPE_PNG); | ||||
|         $self->{icons}->Add($bitmap); | ||||
|         $self->{iconcount}++; | ||||
|         $icon_idx = $self->{icon_index}->{$icon}; | ||||
|         if (! defined $icon_idx) { | ||||
|             # Add a new icon to the icon list. | ||||
|             my $bitmap = Wx::Bitmap->new(Slic3r::var($icon), wxBITMAP_TYPE_PNG); | ||||
|             $self->{icons}->Add($bitmap); | ||||
|             $icon_idx = $self->{icon_count} + 1; | ||||
|             $self->{icon_count} = $icon_idx; | ||||
|             $self->{icon_index}->{$icon} = $icon_idx; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     my $page = Slic3r::GUI::Tab::Page->new($self, $title, $self->{iconcount}); | ||||
|     # Initialize the page. | ||||
|     my $page = Slic3r::GUI::Tab::Page->new($self, $title, $icon_idx); | ||||
|     $page->Hide; | ||||
|     $self->{hsizer}->Add($page, 1, wxEXPAND | wxLEFT, 5); | ||||
|     push @{$self->{pages}}, $page; | ||||
|  | @ -277,14 +311,16 @@ sub add_options_page { | |||
| } | ||||
| 
 | ||||
| # Reload current $self->{config} (aka $self->{presets}->edited_preset->config) into the UI fields. | ||||
| sub reload_config { | ||||
| sub _reload_config { | ||||
|     my ($self) = @_; | ||||
|     $_->reload_config for @{$self->{pages}}; | ||||
| } | ||||
| 
 | ||||
| sub update_tree { | ||||
| # Regerenerate content of the page tree. | ||||
| sub rebuild_page_tree { | ||||
|     my ($self) = @_; | ||||
|      | ||||
|     print "Tab::rebuild_page_tree " . $self->title . "\n"; | ||||
|     # get label of the currently selected item | ||||
|     my $selected = $self->{treectrl}->GetItemText($self->{treectrl}->GetSelection); | ||||
|      | ||||
|  | @ -315,40 +351,6 @@ sub update_dirty { | |||
|     $self->_on_presets_changed; | ||||
| } | ||||
| 
 | ||||
| # Search all ini files in the presets directory, add them into the list of $self->{presets} in the form of Slic3r::GUI::Tab::Preset. | ||||
| # Initialize the drop down list box. | ||||
| sub load_presets { | ||||
|     my ($self) = @_; | ||||
|      | ||||
|     print "Load presets, ui: " . $self->{presets_choice} . "\n"; | ||||
| #    $self->current_preset(undef); | ||||
| #    $self->{presets}->set_default_suppressed(Slic3r::GUI::Tab->no_defaults); | ||||
| #    $self->{presets_choice}->Clear; | ||||
| #    foreach my $preset (@{$self->{presets}}) { | ||||
| #        if ($preset->visible) { | ||||
| #            # Set client data of the choice item to $preset. | ||||
| #            $self->{presets_choice}->Append($preset->name, $preset); | ||||
| #        } | ||||
| #    } | ||||
| #    { | ||||
| #        # load last used preset | ||||
| #        my $i = first { basename($self->{presets}[$_]->file) eq ($Slic3r::GUI::Settings->{presets}{$self->name} || '') } 1 .. $#{$self->{presets}}; | ||||
| #        $self->select_preset($i || $self->{default_suppressed}); | ||||
| #    } | ||||
| 
 | ||||
|     $self->{presets}->update_platter_ui($self->{presets_choice}); | ||||
|     $self->_on_presets_changed; | ||||
| } | ||||
| 
 | ||||
| # Load a config file containing a Print, Filament & Printer preset. | ||||
| sub load_config_file { | ||||
|     my ($self, $file) = @_; | ||||
|     $self->{presets}->update_platter_ui($self->{presets_choice}); | ||||
|     $self->select_preset; | ||||
|     $self->_on_presets_changed; | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| # Load a provied DynamicConfig into the tab, modifying the active preset. | ||||
| # This could be used for example by setting a Wipe Tower position by interactive manipulation in the 3D view. | ||||
| sub load_config { | ||||
|  | @ -362,15 +364,16 @@ sub load_config { | |||
|     if ($modified) { | ||||
|         $self->update_dirty; | ||||
|         # Initialize UI components with the config values. | ||||
|         $self->reload_config; | ||||
|         $self->_reload_config; | ||||
|         $self->_update; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| # Find a field with an index over all pages of this tab. | ||||
| # This method is used often and everywhere, therefore it shall be quick. | ||||
| sub get_field { | ||||
|     my ($self, $opt_key, $opt_index) = @_; | ||||
|     foreach my $page (@{ $self->{pages} }) { | ||||
|     foreach my $page (@{$self->{pages}}) { | ||||
|         my $field = $page->get_field($opt_key, $opt_index); | ||||
|         return $field if defined $field; | ||||
|     } | ||||
|  | @ -378,10 +381,12 @@ sub get_field { | |||
| } | ||||
| 
 | ||||
| # Set a key/value pair on this page. Return true if the value has been modified. | ||||
| # Currently used for distributing extruders_count over preset pages of Slic3r::GUI::Tab::Printer | ||||
| # after a preset is loaded. | ||||
| sub set_value { | ||||
|     my ($self, $opt_key, $value) = @_; | ||||
|     my $changed = 0; | ||||
|     foreach my $page (@{ $self->{pages} }) { | ||||
|     foreach my $page (@{$self->{pages}}) { | ||||
|         $changed = 1 if $page->set_value($opt_key, $value); | ||||
|     } | ||||
|     return $changed; | ||||
|  | @ -660,10 +665,10 @@ sub build { | |||
| } | ||||
| 
 | ||||
| # Reload current $self->{config} (aka $self->{presets}->edited_preset->config) into the UI fields. | ||||
| sub reload_config { | ||||
| sub _reload_config { | ||||
|     my ($self) = @_; | ||||
| #    $self->_reload_compatible_printers_widget; | ||||
|     $self->SUPER::reload_config; | ||||
|     $self->SUPER::_reload_config; | ||||
| } | ||||
| 
 | ||||
| # Slic3r::GUI::Tab::Print::_update is called after a configuration preset is loaded or switched, or when a single option is modifed by the user. | ||||
|  | @ -1194,7 +1199,7 @@ sub build { | |||
|                             $self->{config}->set('octoprint_host', $value); | ||||
|                             $self->update_dirty; | ||||
|                             $self->_on_value_change('octoprint_host', $value); | ||||
|                             $self->reload_config; | ||||
|                             $self->_reload_config; | ||||
|                         } | ||||
|                     } else { | ||||
|                         Wx::MessageDialog->new($self, 'No Bonjour device found', 'Device Browser', wxOK | wxICON_INFORMATION)->ShowModal; | ||||
|  | @ -1421,7 +1426,7 @@ sub _build_extruder_pages { | |||
|         @{$self->{extruder_pages}}[ 0 .. $self->{extruders_count}-1 ], | ||||
|         $page_notes | ||||
|     ); | ||||
|     $self->update_tree; | ||||
|     $self->rebuild_page_tree; | ||||
| } | ||||
| 
 | ||||
| # Slic3r::GUI::Tab::Printer::_update is called after a configuration preset is loaded or switched, or when a single option is modifed by the user. | ||||
|  | @ -1580,6 +1585,8 @@ sub set_value { | |||
|     return $changed; | ||||
| } | ||||
| 
 | ||||
| # Dialog to select a new file name for a modified preset to be saved. | ||||
| # Called from Tab::save_preset(). | ||||
| package Slic3r::GUI::SavePresetWindow; | ||||
| use Wx qw(:combobox :dialog :id :misc :sizer); | ||||
| use Wx::Event qw(EVT_BUTTON EVT_TEXT_ENTER); | ||||
|  | @ -1612,7 +1619,7 @@ sub new { | |||
| 
 | ||||
| sub accept { | ||||
|     my ($self, $event) = @_; | ||||
|     if (($self->{chosen_name} = $self->{combo}->GetValue)) { | ||||
|     if (($self->{chosen_name} = Slic3r::normalize_utf8_nfc($self->{combo}->GetValue))) { | ||||
|         if ($self->{chosen_name} !~ /^[^<>:\/\\|?*\"]+$/) { | ||||
|             Slic3r::GUI::show_error($self, "The supplied name is not valid; the following characters are not allowed: <>:/\|?*\""); | ||||
|         } elsif ($self->{chosen_name} eq '- default -') { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bubnikv
						bubnikv