diff --git a/cmake/msvc/xs.wperl64d.props b/cmake/msvc/xs.wperl.props.in similarity index 61% rename from cmake/msvc/xs.wperl64d.props rename to cmake/msvc/xs.wperl.props.in index b604a56e2..5c7461dc7 100644 --- a/cmake/msvc/xs.wperl64d.props +++ b/cmake/msvc/xs.wperl.props.in @@ -1,18 +1,22 @@ + - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH);c:\wperl64d\bin\; + $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH);${PROPS_PERL_BIN_PATH}\; - C:\wperl64d\bin\perl.exe + ${PROPS_PERL_EXECUTABLE} slic3r.pl WindowsLocalDebugger - ..\.. + ${PROPS_CMAKE_SOURCE_DIR} diff --git a/doc/updating/Updatig.md b/doc/updating/Updatig.md new file mode 100644 index 000000000..3ce1f109c --- /dev/null +++ b/doc/updating/Updatig.md @@ -0,0 +1,52 @@ +# Slic3r PE 1.40 configuration update + +Slic3r PE 1.40.0 comes with a major re-work of the way configuration presets work. +There are three new features: + ++ A two-tier system of presets being divided into _System_ and _User_ groups ++ Configuration snapshots ++ Configuration updating from the internet + +## System and User presets + +- _System preset_: These are the presets that come with Slic3r PE installation. They come from a vendor configuration bundle (not individual files like before). They are **read-only** – a user cannot modify them, but may instead create a derived User preset based on a System preset +- _User preset_: These are regular presets stored in files just like before. Additionally, they may be derived (inherited) from one of the System presets + +A derived User preset keeps track of wich settings are inherited from the parent System preset and which are modified by the user. When a system preset is updated (either via installation of a new Slic3r or automatically from the internet), in a User preset the settings that are modified by the user will stay that way, while the ones that are inherited reflect the updated System preset. + +This system ensures that we don't overwrite user's settings when there is an update to the built in presets. + +Slic3r GUI now displays accurately which settings are inherited and which are modified. +A setting derived from a System preset is represeted by green label and a locked lock icon: + +![a system setting](setting_sys.png) + +A settings modified in a User preset has an open lock icon: + +![a user setting](setting_user.png) + +Clickign the open lock icon restored the system setting. + +Additionaly, any setting that is modified but not yet saved onto disk is represented by orange label and a back-arrow: + +![a modified setting](setting_mod.png) + +Clicking the back-arrow restores the value that was previously saved in this Preset. + +## Configuration snapshots + +Configuration snapshots can now be taken via the _Configuration_ menu. +A snapshot contains complete configuration from the point when the snapshot was taken. +Users may move back and forth between snapshots at will using a dialog: + +![snapshots dialog](snapshots_dialog.png) + + +# Updating from the internet + +Slic3r PE 1.40.0 checks for updates of the built-in System presets and downloads them. +The first-time configuration assistant will ask you if you want to enable this feature - it is **not** mandatory. + +Updates are checked for and downloaded in the background. If there's is an update, Slic3r will prompt about it +next time it is launched, never during normal program operation. An update may be either accepted or refused. +Before any update is applied a configuration snapshot (as described above) is taken. diff --git a/doc/updating/setting_mod.png b/doc/updating/setting_mod.png new file mode 100644 index 000000000..e4d3b7e7b Binary files /dev/null and b/doc/updating/setting_mod.png differ diff --git a/doc/updating/setting_sys.png b/doc/updating/setting_sys.png new file mode 100644 index 000000000..842a8bf73 Binary files /dev/null and b/doc/updating/setting_sys.png differ diff --git a/doc/updating/setting_user.png b/doc/updating/setting_user.png new file mode 100644 index 000000000..ffec5e0f3 Binary files /dev/null and b/doc/updating/setting_user.png differ diff --git a/doc/updating/snapshots_dialog.png b/doc/updating/snapshots_dialog.png new file mode 100644 index 000000000..d4d289550 Binary files /dev/null and b/doc/updating/snapshots_dialog.png differ diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 8d827896a..0c6c81bb5 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -161,8 +161,13 @@ sub thread_cleanup { *Slic3r::Print::SupportMaterial2::DESTROY = sub {}; *Slic3r::TriangleMesh::DESTROY = sub {}; *Slic3r::GUI::AppConfig::DESTROY = sub {}; + *Slic3r::GUI::GCodePreviewData::DESTROY = sub {}; *Slic3r::GUI::PresetBundle::DESTROY = sub {}; *Slic3r::GUI::Tab::DESTROY = sub {}; + *Slic3r::GUI::PresetHints::DESTROY = sub {}; + *Slic3r::GUI::TabIface::DESTROY = sub {}; + *Slic3r::OctoPrint::DESTROY = sub {}; + *Slic3r::PresetUpdater::DESTROY = sub {}; return undef; # this prevents a "Scalars leaked" warning } diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 10375a9dc..04dc80323 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -86,8 +86,9 @@ sub OnInit { Slic3r::GUI::set_wxapp($self); $self->{app_config} = Slic3r::GUI::AppConfig->new; - $self->{preset_bundle} = Slic3r::GUI::PresetBundle->new; Slic3r::GUI::set_app_config($self->{app_config}); + $self->{preset_bundle} = Slic3r::GUI::PresetBundle->new; + Slic3r::GUI::set_preset_bundle($self->{preset_bundle}); # 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 @@ -104,7 +105,11 @@ sub OnInit { $self->{preset_updater} = Slic3r::PresetUpdater->new($VERSION_ONLINE_EVENT); Slic3r::GUI::set_preset_updater($self->{preset_updater}); - eval { $self->{preset_updater}->config_update(); }; + eval { + if (! $self->{preset_updater}->config_update()) { + exit 0; + } + }; if ($@) { warn $@ . "\n"; fatal_error(undef, $@); @@ -120,8 +125,6 @@ sub OnInit { show_error(undef, $@); } - Slic3r::GUI::set_preset_bundle($self->{preset_bundle}); - # application frame print STDERR "Creating main frame...\n"; Wx::Image::FindHandlerType(wxBITMAP_TYPE_PNG) || Wx::Image::AddHandler(Wx::PNGHandler->new); @@ -144,8 +147,10 @@ sub OnInit { # On OSX the UI was not initialized correctly if the wizard was called # before the UI was up and running. $self->CallAfter(sub { - Slic3r::GUI::config_wizard_startup($app_conf_exists); - $self->{preset_updater}->slic3r_update_notify(); + if (! Slic3r::GUI::config_wizard_startup($app_conf_exists)) { + # Only notify if there was not wizard so as not to bother too much ... + $self->{preset_updater}->slic3r_update_notify(); + } $self->{preset_updater}->sync($self->{preset_bundle}); }); @@ -244,7 +249,7 @@ sub catch_error { # static method accepting a wxWindow object as first parameter sub show_error { my ($parent, $message) = @_; - Wx::MessageDialog->new($parent, $message, 'Error', wxOK | wxICON_ERROR)->ShowModal; + Slic3r::GUI::show_error_id($parent ? $parent->GetId() : 0, $message); } # static method accepting a wxWindow object as first parameter diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index ff6d73399..1b6adf800 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -389,7 +389,7 @@ sub mouse_event { $self->_mouse_dragging($e->Dragging); - if ($e->Entering && &Wx::wxMSW) { + if ($e->Entering && (&Wx::wxMSW || $^O eq 'linux')) { # wxMSW needs focus in order to catch mouse wheel events $self->SetFocus; $self->_drag_start_xy(undef); @@ -687,7 +687,7 @@ sub select_view { } sub get_zoom_to_bounding_box_factor { - my ($self, $bb) = @_; + my ($self, $bb) = @_; my $max_bb_size = max(@{ $bb->size }); return undef if ($max_bb_size == 0); @@ -760,6 +760,8 @@ sub get_zoom_to_bounding_box_factor { $max_y = max($max_y, $margin_factor * 2 * abs($y_on_plane)); } + return undef if (($max_x == 0) || ($max_y == 0)); + my ($cw, $ch) = $self->GetSizeWH; my $min_ratio = min($cw / $max_x, $ch / $max_y); @@ -906,6 +908,9 @@ sub deselect_volumes { sub select_volume { my ($self, $volume_idx) = @_; + + return if ($volume_idx >= scalar(@{$self->volumes})); + $self->volumes->[$volume_idx]->set_selected(1) if $volume_idx != -1; } @@ -1112,7 +1117,7 @@ sub Resize { # is only a workaround for an incorrectly set camera. # This workaround harms Z-buffer accuracy! # my $depth = 1.05 * $self->max_bounding_box->radius(); - my $depth = max(@{ $self->max_bounding_box->size }); + my $depth = 5.0 * max(@{ $self->max_bounding_box->size }); glOrtho( -$x/2, $x/2, -$y/2, $y/2, -$depth, $depth, @@ -1150,6 +1155,8 @@ sub InitGL { $self->volumes->finalize_geometry(1) if ($^O eq 'linux' && $self->UseVBOs); + $self->zoom_to_bed; + glClearColor(0, 0, 0, 1); glColor3f(1, 0, 0); glEnable(GL_DEPTH_TEST); diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 886c8f419..fbcd34a3f 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -149,6 +149,7 @@ sub _init_tabpanel { if (defined $presets){ my $reload_dependent_tabs = $tab->get_dependent_tabs; $self->{plater}->update_presets($tab_name, $reload_dependent_tabs, $presets); + $self->{plater}->{"selected_item_$tab_name"} = $tab->get_selected_preset_item; if ($tab_name eq 'printer') { # Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors. for my $tab_name_other (qw(print filament)) { diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index f41394ccc..a0fbf1547 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -486,7 +486,7 @@ sub new { my $right_sizer = Wx::BoxSizer->new(wxVERTICAL); $right_sizer->Add($presets, 0, wxEXPAND | wxTOP, 10) if defined $presets; - $right_sizer->Add($frequently_changed_parameters_sizer, 0, wxEXPAND | wxTOP, 10) if defined $frequently_changed_parameters_sizer; + $right_sizer->Add($frequently_changed_parameters_sizer, 0, wxEXPAND | wxTOP, 0) if defined $frequently_changed_parameters_sizer; $right_sizer->Add($buttons_sizer, 0, wxEXPAND | wxBOTTOM, 5); $right_sizer->Add($self->{list}, 1, wxEXPAND, 5); $right_sizer->Add($object_info_sizer, 0, wxEXPAND, 0); @@ -514,6 +514,13 @@ sub new { $self->SetSizer($sizer); } + # Last correct selected item for each preset + { + $self->{selected_item_print} = 0; + $self->{selected_item_filament} = 0; + $self->{selected_item_printer} = 0; + } + $self->update_ui_from_settings(); return $self; @@ -538,9 +545,21 @@ sub _on_select_preset { # Only update the platter UI for the 2nd and other filaments. wxTheApp->{preset_bundle}->update_platter_filament_ui($idx, $choice); } else { + my $selected_item = $choice->GetSelection(); + return if ($selected_item == $self->{"selected_item_$group"}); + + my $selected_string = $choice->GetString($selected_item); + if ($selected_string eq ("------- ".L("System presets")." -------") || + $selected_string eq ("------- ".L("User presets")." -------") ){ + $choice->SetSelection($self->{"selected_item_$group"}); + return; + } + # call GetSelection() in scalar context as it's context-aware - $self->{on_select_preset}->($group, $choice->GetStringSelection) - if $self->{on_select_preset}; +# $self->{on_select_preset}->($group, $choice->GetStringSelection) + $self->{on_select_preset}->($group, $selected_string) + if $self->{on_select_preset}; + $self->{"selected_item_$group"} = $selected_item; } # Synchronize config.ini with the current selections. wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config}); @@ -1786,22 +1805,24 @@ sub on_config_change { sub list_item_deselected { my ($self, $event) = @_; return if $PreventListEvents; + $self->{_lecursor} = Wx::BusyCursor->new(); if ($self->{list}->GetFirstSelected == -1) { $self->select_object(undef); $self->{canvas}->Refresh; - #FIXME VBOs are being refreshed just to change a selection color? - $self->{canvas3D}->reload_scene if $self->{canvas3D}; + $self->{canvas3D}->deselect_volumes if $self->{canvas3D}; } + undef $self->{_lecursor}; } sub list_item_selected { my ($self, $event) = @_; return if $PreventListEvents; + $self->{_lecursor} = Wx::BusyCursor->new(); my $obj_idx = $event->GetIndex; $self->select_object($obj_idx); $self->{canvas}->Refresh; - #FIXME VBOs are being refreshed just to change a selection color? - $self->{canvas3D}->reload_scene if $self->{canvas3D}; + $self->{canvas3D}->update_volumes_selection if $self->{canvas3D}; + undef $self->{_lecursor}; } sub list_item_activated { @@ -1935,7 +1956,8 @@ sub selection_changed { my ($self) = @_; my ($obj_idx, $object) = $self->selected_object; my $have_sel = defined $obj_idx; - + + $self->Freeze; if ($self->{htoolbar}) { # On OSX or Linux $self->{htoolbar}->EnableTool($_, $have_sel) @@ -1986,12 +2008,20 @@ sub selection_changed { # prepagate the event to the frame (a custom Wx event would be cleaner) $self->GetFrame->on_plater_selection_changed($have_sel); + $self->Thaw; } sub select_object { my ($self, $obj_idx) = @_; + + # remove current selection + foreach my $o (0..$#{$self->{objects}}) { + $PreventListEvents = 1; + $self->{objects}->[$o]->selected(0); + $self->{list}->Select($o, 0); + $PreventListEvents = 0; + } - $_->selected(0) for @{ $self->{objects} }; if (defined $obj_idx) { $self->{objects}->[$obj_idx]->selected(1); # We use this flag to avoid circular event handling diff --git a/lib/Slic3r/GUI/Plater/3D.pm b/lib/Slic3r/GUI/Plater/3D.pm index dce60e2c4..ced6fb82e 100644 --- a/lib/Slic3r/GUI/Plater/3D.pm +++ b/lib/Slic3r/GUI/Plater/3D.pm @@ -31,7 +31,9 @@ sub new { $self->{on_select_object} = sub {}; $self->{on_instances_moved} = sub {}; $self->{on_wipe_tower_moved} = sub {}; - + + $self->{objects_volumes_idxs} = (); + $self->on_select(sub { my ($volume_idx) = @_; $self->{on_select_object}->(($volume_idx == -1) ? undef : $self->volumes->[$volume_idx]->object_idx) @@ -181,6 +183,17 @@ sub set_on_enable_action_buttons { $self->on_enable_action_buttons($cb); } +sub update_volumes_selection { + my ($self) = @_; + + foreach my $obj_idx (0..$#{$self->{model}->objects}) { + if ($self->{objects}[$obj_idx]->selected) { + my @volume_idxs = @{$self->{objects_volumes_idxs}[$obj_idx]}; + $self->select_volume($_) for @volume_idxs; + } + } +} + sub reload_scene { my ($self, $force) = @_; @@ -194,12 +207,14 @@ sub reload_scene { $self->{reload_delayed} = 0; + $self->{objects_volumes_idxs} = (); foreach my $obj_idx (0..$#{$self->{model}->objects}) { my @volume_idxs = $self->load_object($self->{model}, $self->{print}, $obj_idx); - if ($self->{objects}[$obj_idx]->selected) { - $self->select_volume($_) for @volume_idxs; - } + push(@{$self->{objects_volumes_idxs}}, \@volume_idxs); } + + $self->update_volumes_selection; + if (defined $self->{config}->nozzle_diameter) { # Should the wipe tower be visualized? my $extruders_count = scalar @{ $self->{config}->nozzle_diameter }; diff --git a/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm b/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm index 7b5752cd2..4d55e313a 100644 --- a/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm +++ b/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm @@ -116,7 +116,6 @@ sub new { $canvas->set_auto_bed_shape; $canvas->SetSize([500,500]); $canvas->SetMinSize($canvas->GetSize); - $canvas->zoom_to_volumes; } $self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL); @@ -227,12 +226,14 @@ sub _update { push @objects, $self->{model_object}; } + my $z_cut = $z + $self->{model_object}->bounding_box->z_min; + # get section contour my @expolygons = (); foreach my $volume (@{$self->{model_object}->volumes}) { next if !$volume->mesh; next if $volume->modifier; - my $expp = $volume->mesh->slice([ $z + $volume->mesh->bounding_box->z_min ])->[0]; + my $expp = $volume->mesh->slice([ $z_cut ])->[0]; push @expolygons, @$expp; } foreach my $expolygon (@expolygons) { diff --git a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm index f7e38ed87..28e3bf92b 100644 --- a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm +++ b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm @@ -163,7 +163,6 @@ sub new { $canvas->set_auto_bed_shape; $canvas->SetSize([500,700]); $canvas->update_volumes_colors_by_extruder($self->GetParent->GetParent->GetParent->{config}); - $canvas->zoom_to_volumes; } $self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL); diff --git a/resources/icons/Slic3r_192px_grayscale.png b/resources/icons/Slic3r_192px_grayscale.png new file mode 100644 index 000000000..910f94187 Binary files /dev/null and b/resources/icons/Slic3r_192px_grayscale.png differ diff --git a/resources/icons/action_undo.png b/resources/icons/action_undo.png index 877f15986..06bb98b22 100644 Binary files a/resources/icons/action_undo.png and b/resources/icons/action_undo.png differ diff --git a/resources/icons/action_undo_grey.png b/resources/icons/action_undo_grey.png new file mode 100644 index 000000000..eaa1593e3 Binary files /dev/null and b/resources/icons/action_undo_grey.png differ diff --git a/resources/icons/question_mark_01.png b/resources/icons/question_mark_01.png new file mode 100644 index 000000000..25814a61d Binary files /dev/null and b/resources/icons/question_mark_01.png differ diff --git a/resources/icons/sys_unlock_grey.png b/resources/icons/sys_unlock_grey.png new file mode 100644 index 000000000..0dedf4dee Binary files /dev/null and b/resources/icons/sys_unlock_grey.png differ diff --git a/resources/localization/Slic3rPE.pot b/resources/localization/Slic3rPE.pot index 0282e7aae..e4b9e2567 100644 --- a/resources/localization/Slic3rPE.pot +++ b/resources/localization/Slic3rPE.pot @@ -3,20 +3,26 @@ # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-03-14 15:32+0100\n" +"POT-Creation-Date: 2018-05-02 15:27+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" -"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +#: xs/src/slic3r/GUI/AboutDialog.cpp:32 +msgid "About Slic3r" +msgstr "" + +#: xs/src/slic3r/GUI/AboutDialog.cpp:60 +msgid "Version" +msgstr "" + #: xs/src/slic3r/GUI/BedShapeDialog.cpp:39 msgid "Shape" msgstr "" @@ -25,8 +31,8 @@ msgstr "" msgid "Rectangular" msgstr "" -#: xs/src/slic3r/GUI/BedShapeDialog.cpp:50 xs/src/slic3r/GUI/Tab.cpp:1270 -#: lib/Slic3r/GUI/Plater.pm:411 +#: xs/src/slic3r/GUI/BedShapeDialog.cpp:50 xs/src/slic3r/GUI/Tab.cpp:1738 +#: lib/Slic3r/GUI/Plater.pm:421 msgid "Size" msgstr "" @@ -48,25 +54,34 @@ msgstr "" msgid "Circular" msgstr "" -#: xs/src/slic3r/GUI/BedShapeDialog.cpp:65 xs/src/libslic3r/PrintConfig.cpp:129 -#: xs/src/libslic3r/PrintConfig.cpp:200 xs/src/libslic3r/PrintConfig.cpp:211 -#: xs/src/libslic3r/PrintConfig.cpp:325 xs/src/libslic3r/PrintConfig.cpp:336 -#: xs/src/libslic3r/PrintConfig.cpp:355 xs/src/libslic3r/PrintConfig.cpp:434 -#: xs/src/libslic3r/PrintConfig.cpp:781 xs/src/libslic3r/PrintConfig.cpp:801 -#: xs/src/libslic3r/PrintConfig.cpp:860 xs/src/libslic3r/PrintConfig.cpp:878 -#: xs/src/libslic3r/PrintConfig.cpp:896 xs/src/libslic3r/PrintConfig.cpp:1051 -#: xs/src/libslic3r/PrintConfig.cpp:1059 xs/src/libslic3r/PrintConfig.cpp:1101 -#: xs/src/libslic3r/PrintConfig.cpp:1110 xs/src/libslic3r/PrintConfig.cpp:1120 -#: xs/src/libslic3r/PrintConfig.cpp:1128 xs/src/libslic3r/PrintConfig.cpp:1136 -#: xs/src/libslic3r/PrintConfig.cpp:1222 xs/src/libslic3r/PrintConfig.cpp:1428 -#: xs/src/libslic3r/PrintConfig.cpp:1498 xs/src/libslic3r/PrintConfig.cpp:1534 -#: xs/src/libslic3r/PrintConfig.cpp:1711 xs/src/libslic3r/PrintConfig.cpp:1718 -#: xs/src/libslic3r/PrintConfig.cpp:1725 xs/src/libslic3r/PrintConfig.cpp:1734 -#: xs/src/libslic3r/PrintConfig.cpp:1744 xs/src/libslic3r/PrintConfig.cpp:1754 +#: xs/src/slic3r/GUI/BedShapeDialog.cpp:65 +#: xs/src/slic3r/GUI/ConfigWizard.cpp:85 +#: xs/src/slic3r/GUI/ConfigWizard.cpp:432 +#: xs/src/slic3r/GUI/ConfigWizard.cpp:446 +#: xs/src/slic3r/GUI/RammingChart.cpp:86 +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:84 +#: xs/src/libslic3r/PrintConfig.cpp:129 xs/src/libslic3r/PrintConfig.cpp:172 +#: xs/src/libslic3r/PrintConfig.cpp:180 xs/src/libslic3r/PrintConfig.cpp:228 +#: xs/src/libslic3r/PrintConfig.cpp:239 xs/src/libslic3r/PrintConfig.cpp:353 +#: xs/src/libslic3r/PrintConfig.cpp:364 xs/src/libslic3r/PrintConfig.cpp:383 +#: xs/src/libslic3r/PrintConfig.cpp:496 xs/src/libslic3r/PrintConfig.cpp:850 +#: xs/src/libslic3r/PrintConfig.cpp:870 xs/src/libslic3r/PrintConfig.cpp:878 +#: xs/src/libslic3r/PrintConfig.cpp:936 xs/src/libslic3r/PrintConfig.cpp:954 +#: xs/src/libslic3r/PrintConfig.cpp:972 xs/src/libslic3r/PrintConfig.cpp:1034 +#: xs/src/libslic3r/PrintConfig.cpp:1151 xs/src/libslic3r/PrintConfig.cpp:1159 +#: xs/src/libslic3r/PrintConfig.cpp:1201 xs/src/libslic3r/PrintConfig.cpp:1210 +#: xs/src/libslic3r/PrintConfig.cpp:1220 xs/src/libslic3r/PrintConfig.cpp:1228 +#: xs/src/libslic3r/PrintConfig.cpp:1236 xs/src/libslic3r/PrintConfig.cpp:1322 +#: xs/src/libslic3r/PrintConfig.cpp:1528 xs/src/libslic3r/PrintConfig.cpp:1598 +#: xs/src/libslic3r/PrintConfig.cpp:1632 xs/src/libslic3r/PrintConfig.cpp:1828 +#: xs/src/libslic3r/PrintConfig.cpp:1835 xs/src/libslic3r/PrintConfig.cpp:1842 +#: xs/src/libslic3r/PrintConfig.cpp:1856 xs/src/libslic3r/PrintConfig.cpp:1866 +#: xs/src/libslic3r/PrintConfig.cpp:1876 msgid "mm" msgstr "" -#: xs/src/slic3r/GUI/BedShapeDialog.cpp:66 xs/src/libslic3r/PrintConfig.cpp:431 +#: xs/src/slic3r/GUI/BedShapeDialog.cpp:66 +#: xs/src/libslic3r/PrintConfig.cpp:493 msgid "Diameter" msgstr "" @@ -77,8 +92,8 @@ msgid "" msgstr "" #: xs/src/slic3r/GUI/BedShapeDialog.cpp:71 -#: xs/src/libslic3r/GCode/PreviewData.cpp:150 -#: lib/Slic3r/GUI/Plater/3DPreview.pm:92 +#: xs/src/libslic3r/GCode/PreviewData.cpp:170 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:95 msgid "Custom" msgstr "" @@ -90,300 +105,730 @@ msgstr "" msgid "Settings" msgstr "" -#: xs/src/slic3r/GUI/BedShapeDialog.cpp:298 +#: xs/src/slic3r/GUI/BedShapeDialog.cpp:299 msgid "Choose a file to import bed shape from (STL/OBJ/AMF/3MF/PRUSA):" msgstr "" -#: xs/src/slic3r/GUI/BedShapeDialog.cpp:315 +#: xs/src/slic3r/GUI/BedShapeDialog.cpp:316 msgid "Error! " msgstr "" -#: xs/src/slic3r/GUI/BedShapeDialog.cpp:324 +#: xs/src/slic3r/GUI/BedShapeDialog.cpp:325 msgid "The selected file contains no geometry." msgstr "" -#: xs/src/slic3r/GUI/BedShapeDialog.cpp:328 +#: xs/src/slic3r/GUI/BedShapeDialog.cpp:329 msgid "" "The selected file contains several disjoint areas. This is not supported." msgstr "" -#: xs/src/slic3r/GUI/BedShapeDialog.hpp:42 +#: xs/src/slic3r/GUI/BedShapeDialog.hpp:44 +#: xs/src/slic3r/GUI/ConfigWizard.cpp:395 msgid "Bed Shape" msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:234 +#: xs/src/slic3r/GUI/BonjourDialog.cpp:53 +msgid "Network lookup" +msgstr "" + +#: xs/src/slic3r/GUI/BonjourDialog.cpp:66 +msgid "Address" +msgstr "" + +#: xs/src/slic3r/GUI/BonjourDialog.cpp:67 +msgid "Hostname" +msgstr "" + +#: xs/src/slic3r/GUI/BonjourDialog.cpp:68 +msgid "Service name" +msgstr "" + +#: xs/src/slic3r/GUI/BonjourDialog.cpp:69 +msgid "OctoPrint version" +msgstr "" + +#: xs/src/slic3r/GUI/BonjourDialog.cpp:187 +msgid "Searching for devices" +msgstr "" + +#: xs/src/slic3r/GUI/BonjourDialog.cpp:194 +msgid "Finished" +msgstr "" + +#: xs/src/slic3r/GUI/ButtonsDescription.cpp:13 +msgid "Buttons And Text Colors Description" +msgstr "" + +#: xs/src/slic3r/GUI/ButtonsDescription.cpp:38 +msgid "Value is the same as the system value" +msgstr "" + +#: xs/src/slic3r/GUI/ButtonsDescription.cpp:55 +msgid "" +"Value was changed and is not equal to the system value or the last saved " +"preset" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:15 +msgid "Upgrade" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:17 +msgid "Downgrade" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:19 +msgid "Before roll back" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:21 +msgid "User" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:24 +msgid "Unknown" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:36 +msgid "Active: " +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:42 +msgid "slic3r version" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:43 +msgid "print" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:44 +msgid "filaments" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:45 +msgid "printer" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:49 xs/src/slic3r/GUI/Tab.cpp:755 +msgid "vendor" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:49 +msgid "version" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:50 +msgid "min slic3r version" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:52 +msgid "max slic3r version" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:55 +msgid "model" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:55 +msgid "variants" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:67 +msgid "Incompatible with this Slic3r" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:70 +msgid "Activate" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:96 xs/src/slic3r/GUI/GUI.cpp:402 +msgid "Configuration Snapshots" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:85 +msgid "nozzle" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:103 +msgid "Select all" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:104 +msgid "Select none" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:205 +#, possible-c-format +msgid "Welcome to the Slic3r %s" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:205 +msgid "Welcome" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:211 xs/src/slic3r/GUI/GUI.cpp:399 +#, possible-c-format +msgid "Run %s" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:213 +#, possible-c-format +msgid "" +"Hello, welcome to Slic3r Prusa Edition! This %s helps you with the initial " +"configuration; just a few settings and you will be ready to print." +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:217 +msgid "" +"Remove user profiles - install from scratch (a snapshot will be taken " +"beforehand)" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:238 +msgid "Other vendors" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:240 +msgid "Custom setup" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:264 +msgid "Automatic updates" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:264 +msgid "Updates" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:272 xs/src/slic3r/GUI/Preferences.cpp:59 +msgid "Check for application updates" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:275 xs/src/slic3r/GUI/Preferences.cpp:61 +msgid "" +"If enabled, Slic3r checks for new versions of Slic3r PE online. When a new " +"version becomes available a notification is displayed at the next " +"application startup (never during program usage). This is only a " +"notification mechanisms, no automatic installation is done." +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:279 xs/src/slic3r/GUI/Preferences.cpp:67 +msgid "Update built-in Presets automatically" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:282 xs/src/slic3r/GUI/Preferences.cpp:69 +msgid "" +"If enabled, Slic3r downloads updates of built-in system presets in the " +"background. These updates are downloaded into a separate temporary location. " +"When a new preset version becomes available it is offered at application " +"startup." +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:283 +msgid "" +"Updates are never applied without user's consent and never overwrite user's " +"customized settings." +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:288 +msgid "" +"Additionally a backup snapshot of the whole configuration is created before " +"an update is applied." +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:295 +msgid "Other Vendors" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:297 +msgid "Pick another vendor supported by Slic3r PE:" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:356 +msgid "Firmware Type" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:356 xs/src/slic3r/GUI/Tab.cpp:1625 +msgid "Firmware" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:360 +msgid "Choose the type of firmware used by your printer." +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:395 +msgid "Bed Shape and Size" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:398 +msgid "Set the shape of your printer's bed." +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:412 +msgid "Filament and Nozzle Diameters" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:412 +msgid "Print Diameters" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:428 +msgid "Enter the diameter of your printer's hot end nozzle." +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:431 +msgid "Nozzle Diameter:" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:441 +msgid "Enter the diameter of your filament." +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:442 +msgid "" +"Good precision is required, so use a caliper and do multiple measurements " +"along the filament, then compute the average." +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:445 +msgid "Filament Diameter:" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:463 +msgid "Extruder and Bed Temperatures" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:463 +msgid "Temperatures" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:479 +msgid "Enter the temperature needed for extruding your filament." +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:480 +msgid "A rule of thumb is 160 to 230 °C for PLA, and 215 to 250 °C for ABS." +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:483 +msgid "Extrusion Temperature:" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:484 +#: xs/src/slic3r/GUI/ConfigWizard.cpp:498 +msgid "°C" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:493 +msgid "" +"Enter the bed temperature needed for getting your filament to stick to your " +"heated bed." +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:494 +msgid "" +"A rule of thumb is 60 °C for PLA and 110 °C for ABS. Leave zero if you have " +"no heated bed." +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:497 +msgid "Bed Temperature:" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:791 +msgid "&Finish" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:844 +msgid "Configuration Wizard" +msgstr "" + +#: xs/src/slic3r/GUI/ConfigWizard.cpp:846 +msgid "Configuration Assistant" +msgstr "" + +#: xs/src/slic3r/GUI/GUI.cpp:285 msgid "Array of language names and identifiers should have the same size." msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:245 +#: xs/src/slic3r/GUI/GUI.cpp:296 msgid "Select the language" msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:245 +#: xs/src/slic3r/GUI/GUI.cpp:296 msgid "Language" msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:312 xs/src/libslic3r/PrintConfig.cpp:170 +#: xs/src/slic3r/GUI/GUI.cpp:363 xs/src/libslic3r/PrintConfig.cpp:186 msgid "Default" msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:337 +#: xs/src/slic3r/GUI/GUI.cpp:402 +msgid "Inspect / activate configuration snapshots" +msgstr "" + +#: xs/src/slic3r/GUI/GUI.cpp:403 +msgid "Take Configuration Snapshot" +msgstr "" + +#: xs/src/slic3r/GUI/GUI.cpp:403 +msgid "Capture a configuration snapshot" +msgstr "" + +#: xs/src/slic3r/GUI/GUI.cpp:404 +msgid "Check for updates" +msgstr "" + +#: xs/src/slic3r/GUI/GUI.cpp:404 +msgid "Check for configuration updates" +msgstr "" + +#: xs/src/slic3r/GUI/GUI.cpp:406 xs/src/slic3r/GUI/Preferences.cpp:9 +msgid "Preferences" +msgstr "" + +#: xs/src/slic3r/GUI/GUI.cpp:406 +msgid "Application preferences" +msgstr "" + +#: xs/src/slic3r/GUI/GUI.cpp:408 msgid "Change Application Language" msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:344 +#: xs/src/slic3r/GUI/GUI.cpp:417 +msgid "Taking configuration snapshot" +msgstr "" + +#: xs/src/slic3r/GUI/GUI.cpp:417 +msgid "Snapshot name" +msgstr "" + +#: xs/src/slic3r/GUI/GUI.cpp:456 msgid "Application will be restarted" msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:344 +#: xs/src/slic3r/GUI/GUI.cpp:456 msgid "Attention!" msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:351 -msgid "&Localization" +#: xs/src/slic3r/GUI/GUI.cpp:466 +msgid "&Configuration" msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:494 lib/Slic3r/GUI/MainFrame.pm:465 -#: lib/Slic3r/GUI/Plater.pm:1304 -msgid "Error" +#: xs/src/slic3r/GUI/GUI.cpp:485 +msgid "You have unsaved changes " msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:499 +#: xs/src/slic3r/GUI/GUI.cpp:485 +msgid ". Discard changes and continue anyway?" +msgstr "" + +#: xs/src/slic3r/GUI/GUI.cpp:486 +msgid "Unsaved Presets" +msgstr "" + +#: xs/src/slic3r/GUI/GUI.cpp:683 msgid "Notice" msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:504 -msgid "GLUquadricObjPtr | Attempt to free unreferenced scalar" +#: xs/src/slic3r/GUI/GUI.cpp:688 +msgid "Attempt to free unreferenced scalar" msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:506 +#: xs/src/slic3r/GUI/GUI.cpp:690 xs/src/slic3r/GUI/WipeTowerDialog.cpp:44 +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:326 msgid "Warning" msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:655 +#: xs/src/slic3r/GUI/GUI.cpp:879 msgid "Support" msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:658 +#: xs/src/slic3r/GUI/GUI.cpp:882 msgid "Select what kind of support do you need" msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:659 xs/src/libslic3r/GCode/PreviewData.cpp:137 +#: xs/src/slic3r/GUI/GUI.cpp:883 xs/src/libslic3r/GCode/PreviewData.cpp:157 msgid "None" msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:660 xs/src/libslic3r/PrintConfig.cpp:1415 +#: xs/src/slic3r/GUI/GUI.cpp:884 xs/src/libslic3r/PrintConfig.cpp:1515 msgid "Support on build plate only" msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:661 +#: xs/src/slic3r/GUI/GUI.cpp:885 msgid "Everywhere" msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:673 xs/src/slic3r/GUI/Tab.cpp:441 +#: xs/src/slic3r/GUI/GUI.cpp:897 xs/src/slic3r/GUI/Tab.cpp:869 msgid "Brim" msgstr "" -#: xs/src/slic3r/GUI/GUI.cpp:675 +#: xs/src/slic3r/GUI/GUI.cpp:899 msgid "" "This flag enables the brim that will be printed around each object on the " "first layer." msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:57 +#: xs/src/slic3r/GUI/GUI.cpp:908 +msgid "Purging volumes" +msgstr "" + +#: xs/src/slic3r/GUI/GUI.cpp:950 +msgid "Export print config" +msgstr "" + +#: xs/src/slic3r/GUI/MsgDialog.cpp:64 +msgid "Slic3r error" +msgstr "" + +#: xs/src/slic3r/GUI/MsgDialog.cpp:64 +msgid "Slic3r has encountered an error" +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:100 msgid "Save current " msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:58 +#: xs/src/slic3r/GUI/Tab.cpp:101 msgid "Delete this preset" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:383 +#: xs/src/slic3r/GUI/Tab.cpp:113 +msgid "" +"Hover the cursor over buttons to find more information \n" +"or click this button." +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:741 +msgid "It's a default preset." +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:742 +msgid "It's a system preset." +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:743 +msgid "Current preset is inherited from " +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:748 +msgid "It can't be deleted or modified. " +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:749 +msgid "" +"Any modifications should be saved as a new preset inherited from this one. " +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:750 +msgid "To do that please specify a new name for the preset." +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:754 +msgid "Additional information:" +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:762 +msgid "printer model" +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:764 +msgid "default print profile" +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:767 +msgid "default filament profile" +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:811 msgid "Layers and perimeters" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:384 xs/src/libslic3r/PrintConfig.cpp:777 +#: xs/src/slic3r/GUI/Tab.cpp:812 xs/src/libslic3r/PrintConfig.cpp:846 msgid "Layer height" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:388 +#: xs/src/slic3r/GUI/Tab.cpp:816 msgid "Vertical shells" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:399 +#: xs/src/slic3r/GUI/Tab.cpp:827 msgid "Horizontal shells" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:400 xs/src/libslic3r/PrintConfig.cpp:1321 +#: xs/src/slic3r/GUI/Tab.cpp:828 xs/src/libslic3r/PrintConfig.cpp:1421 msgid "Solid layers" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:405 +#: xs/src/slic3r/GUI/Tab.cpp:833 msgid "Quality (slower slicing)" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:412 xs/src/slic3r/GUI/Tab.cpp:426 -#: xs/src/slic3r/GUI/Tab.cpp:519 xs/src/slic3r/GUI/Tab.cpp:522 -#: xs/src/slic3r/GUI/Tab.cpp:905 xs/src/slic3r/GUI/Tab.cpp:1191 -#: xs/src/libslic3r/PrintConfig.cpp:107 xs/src/libslic3r/PrintConfig.cpp:208 -#: xs/src/libslic3r/PrintConfig.cpp:736 xs/src/libslic3r/PrintConfig.cpp:1740 +#: xs/src/slic3r/GUI/Tab.cpp:840 xs/src/slic3r/GUI/Tab.cpp:854 +#: xs/src/slic3r/GUI/Tab.cpp:948 xs/src/slic3r/GUI/Tab.cpp:951 +#: xs/src/slic3r/GUI/Tab.cpp:1300 xs/src/slic3r/GUI/Tab.cpp:1628 +#: xs/src/libslic3r/PrintConfig.cpp:107 xs/src/libslic3r/PrintConfig.cpp:236 +#: xs/src/libslic3r/PrintConfig.cpp:798 xs/src/libslic3r/PrintConfig.cpp:1862 msgid "Advanced" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:416 xs/src/slic3r/GUI/Tab.cpp:417 -#: xs/src/slic3r/GUI/Tab.cpp:735 xs/src/libslic3r/PrintConfig.cpp:87 -#: xs/src/libslic3r/PrintConfig.cpp:247 xs/src/libslic3r/PrintConfig.cpp:488 -#: xs/src/libslic3r/PrintConfig.cpp:502 xs/src/libslic3r/PrintConfig.cpp:540 -#: xs/src/libslic3r/PrintConfig.cpp:681 xs/src/libslic3r/PrintConfig.cpp:691 -#: xs/src/libslic3r/PrintConfig.cpp:709 xs/src/libslic3r/PrintConfig.cpp:727 -#: xs/src/libslic3r/PrintConfig.cpp:746 xs/src/libslic3r/PrintConfig.cpp:1270 -#: xs/src/libslic3r/PrintConfig.cpp:1287 +#: xs/src/slic3r/GUI/Tab.cpp:844 xs/src/slic3r/GUI/Tab.cpp:845 +#: xs/src/slic3r/GUI/Tab.cpp:1152 xs/src/libslic3r/PrintConfig.cpp:87 +#: xs/src/libslic3r/PrintConfig.cpp:275 xs/src/libslic3r/PrintConfig.cpp:550 +#: xs/src/libslic3r/PrintConfig.cpp:564 xs/src/libslic3r/PrintConfig.cpp:602 +#: xs/src/libslic3r/PrintConfig.cpp:743 xs/src/libslic3r/PrintConfig.cpp:753 +#: xs/src/libslic3r/PrintConfig.cpp:771 xs/src/libslic3r/PrintConfig.cpp:789 +#: xs/src/libslic3r/PrintConfig.cpp:808 xs/src/libslic3r/PrintConfig.cpp:1370 +#: xs/src/libslic3r/PrintConfig.cpp:1387 msgid "Infill" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:422 +#: xs/src/slic3r/GUI/Tab.cpp:850 msgid "Reducing printing time" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:434 +#: xs/src/slic3r/GUI/Tab.cpp:862 msgid "Skirt and brim" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:435 xs/src/libslic3r/GCode/PreviewData.cpp:146 -#: lib/Slic3r/GUI/Plater/3DPreview.pm:88 +#: xs/src/slic3r/GUI/Tab.cpp:863 xs/src/libslic3r/GCode/PreviewData.cpp:166 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:91 msgid "Skirt" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:444 xs/src/slic3r/GUI/Tab.cpp:445 -#: xs/src/libslic3r/PrintConfig.cpp:191 xs/src/libslic3r/PrintConfig.cpp:1037 -#: xs/src/libslic3r/PrintConfig.cpp:1387 xs/src/libslic3r/PrintConfig.cpp:1394 -#: xs/src/libslic3r/PrintConfig.cpp:1406 xs/src/libslic3r/PrintConfig.cpp:1416 -#: xs/src/libslic3r/PrintConfig.cpp:1424 xs/src/libslic3r/PrintConfig.cpp:1439 -#: xs/src/libslic3r/PrintConfig.cpp:1460 xs/src/libslic3r/PrintConfig.cpp:1471 -#: xs/src/libslic3r/PrintConfig.cpp:1487 xs/src/libslic3r/PrintConfig.cpp:1496 -#: xs/src/libslic3r/PrintConfig.cpp:1505 xs/src/libslic3r/PrintConfig.cpp:1516 -#: xs/src/libslic3r/PrintConfig.cpp:1532 xs/src/libslic3r/PrintConfig.cpp:1540 -#: xs/src/libslic3r/PrintConfig.cpp:1541 xs/src/libslic3r/PrintConfig.cpp:1550 -#: xs/src/libslic3r/PrintConfig.cpp:1558 xs/src/libslic3r/PrintConfig.cpp:1572 -#: xs/src/libslic3r/GCode/PreviewData.cpp:147 -#: lib/Slic3r/GUI/Plater/3DPreview.pm:89 +#: xs/src/slic3r/GUI/Tab.cpp:872 xs/src/slic3r/GUI/Tab.cpp:873 +#: xs/src/libslic3r/PrintConfig.cpp:219 xs/src/libslic3r/PrintConfig.cpp:1137 +#: xs/src/libslic3r/PrintConfig.cpp:1487 xs/src/libslic3r/PrintConfig.cpp:1494 +#: xs/src/libslic3r/PrintConfig.cpp:1506 xs/src/libslic3r/PrintConfig.cpp:1516 +#: xs/src/libslic3r/PrintConfig.cpp:1524 xs/src/libslic3r/PrintConfig.cpp:1539 +#: xs/src/libslic3r/PrintConfig.cpp:1560 xs/src/libslic3r/PrintConfig.cpp:1571 +#: xs/src/libslic3r/PrintConfig.cpp:1587 xs/src/libslic3r/PrintConfig.cpp:1596 +#: xs/src/libslic3r/PrintConfig.cpp:1605 xs/src/libslic3r/PrintConfig.cpp:1616 +#: xs/src/libslic3r/PrintConfig.cpp:1630 xs/src/libslic3r/PrintConfig.cpp:1638 +#: xs/src/libslic3r/PrintConfig.cpp:1639 xs/src/libslic3r/PrintConfig.cpp:1648 +#: xs/src/libslic3r/PrintConfig.cpp:1656 xs/src/libslic3r/PrintConfig.cpp:1670 +#: xs/src/libslic3r/GCode/PreviewData.cpp:167 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:92 msgid "Support material" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:450 +#: xs/src/slic3r/GUI/Tab.cpp:878 msgid "Raft" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:454 +#: xs/src/slic3r/GUI/Tab.cpp:882 msgid "Options for support material and raft" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:468 xs/src/libslic3r/PrintConfig.cpp:118 -#: xs/src/libslic3r/PrintConfig.cpp:278 xs/src/libslic3r/PrintConfig.cpp:635 -#: xs/src/libslic3r/PrintConfig.cpp:747 xs/src/libslic3r/PrintConfig.cpp:986 -#: xs/src/libslic3r/PrintConfig.cpp:1208 xs/src/libslic3r/PrintConfig.cpp:1258 -#: xs/src/libslic3r/PrintConfig.cpp:1309 xs/src/libslic3r/PrintConfig.cpp:1632 -#: lib/Slic3r/GUI/Plater/3DPreview.pm:71 +#: xs/src/slic3r/GUI/Tab.cpp:896 xs/src/libslic3r/PrintConfig.cpp:118 +#: xs/src/libslic3r/PrintConfig.cpp:306 xs/src/libslic3r/PrintConfig.cpp:697 +#: xs/src/libslic3r/PrintConfig.cpp:809 xs/src/libslic3r/PrintConfig.cpp:1071 +#: xs/src/libslic3r/PrintConfig.cpp:1308 xs/src/libslic3r/PrintConfig.cpp:1358 +#: xs/src/libslic3r/PrintConfig.cpp:1409 xs/src/libslic3r/PrintConfig.cpp:1730 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:70 msgid "Speed" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:469 +#: xs/src/slic3r/GUI/Tab.cpp:897 msgid "Speed for print moves" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:481 +#: xs/src/slic3r/GUI/Tab.cpp:909 msgid "Speed for non-print moves" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:484 +#: xs/src/slic3r/GUI/Tab.cpp:912 msgid "Modifiers" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:487 +#: xs/src/slic3r/GUI/Tab.cpp:915 msgid "Acceleration control (advanced)" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:494 +#: xs/src/slic3r/GUI/Tab.cpp:922 msgid "Autospeed (advanced)" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:500 +#: xs/src/slic3r/GUI/Tab.cpp:928 msgid "Multiple Extruders" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:501 xs/src/slic3r/GUI/Tab.cpp:1040 -#: xs/src/libslic3r/PrintConfig.cpp:308 xs/src/libslic3r/PrintConfig.cpp:702 -#: xs/src/libslic3r/PrintConfig.cpp:965 xs/src/libslic3r/PrintConfig.cpp:1279 -#: xs/src/libslic3r/PrintConfig.cpp:1452 xs/src/libslic3r/PrintConfig.cpp:1478 +#: xs/src/slic3r/GUI/Tab.cpp:929 xs/src/slic3r/GUI/Tab.cpp:1470 +#: xs/src/libslic3r/PrintConfig.cpp:336 xs/src/libslic3r/PrintConfig.cpp:764 +#: xs/src/libslic3r/PrintConfig.cpp:1050 xs/src/libslic3r/PrintConfig.cpp:1379 +#: xs/src/libslic3r/PrintConfig.cpp:1552 xs/src/libslic3r/PrintConfig.cpp:1578 msgid "Extruders" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:508 +#: xs/src/slic3r/GUI/Tab.cpp:936 msgid "Ooze prevention" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:512 xs/src/libslic3r/GCode/PreviewData.cpp:149 -#: lib/Slic3r/GUI/Plater/3DPreview.pm:91 +#: xs/src/slic3r/GUI/Tab.cpp:940 xs/src/libslic3r/GCode/PreviewData.cpp:169 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:94 msgid "Wipe tower" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:523 +#: xs/src/slic3r/GUI/Tab.cpp:952 msgid "Extrusion width" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:533 +#: xs/src/slic3r/GUI/Tab.cpp:962 msgid "Overlap" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:536 +#: xs/src/slic3r/GUI/Tab.cpp:965 msgid "Flow" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:539 +#: xs/src/slic3r/GUI/Tab.cpp:968 msgid "Other" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:546 +#: xs/src/slic3r/GUI/Tab.cpp:975 msgid "Output options" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:547 +#: xs/src/slic3r/GUI/Tab.cpp:976 msgid "Sequential printing" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:549 +#: xs/src/slic3r/GUI/Tab.cpp:978 msgid "Extruder clearance (mm)" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:558 +#: xs/src/slic3r/GUI/Tab.cpp:987 msgid "Output file" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:564 xs/src/libslic3r/PrintConfig.cpp:1008 +#: xs/src/slic3r/GUI/Tab.cpp:993 xs/src/libslic3r/PrintConfig.cpp:1093 msgid "Post-processing scripts" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:570 xs/src/slic3r/GUI/Tab.cpp:571 -#: xs/src/slic3r/GUI/Tab.cpp:933 xs/src/slic3r/GUI/Tab.cpp:934 -#: xs/src/slic3r/GUI/Tab.cpp:1234 xs/src/slic3r/GUI/Tab.cpp:1235 +#: xs/src/slic3r/GUI/Tab.cpp:999 xs/src/slic3r/GUI/Tab.cpp:1000 +#: xs/src/slic3r/GUI/Tab.cpp:1349 xs/src/slic3r/GUI/Tab.cpp:1350 +#: xs/src/slic3r/GUI/Tab.cpp:1671 xs/src/slic3r/GUI/Tab.cpp:1672 msgid "Notes" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:577 xs/src/slic3r/GUI/Tab.cpp:941 +#: xs/src/slic3r/GUI/Tab.cpp:1006 xs/src/slic3r/GUI/Tab.cpp:1357 +#: xs/src/slic3r/GUI/Tab.cpp:1678 msgid "Dependencies" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:578 xs/src/slic3r/GUI/Tab.cpp:942 +#: xs/src/slic3r/GUI/Tab.cpp:1007 xs/src/slic3r/GUI/Tab.cpp:1358 +#: xs/src/slic3r/GUI/Tab.cpp:1679 msgid "Profile dependencies" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:579 xs/src/slic3r/GUI/Tab.cpp:943 -#: xs/src/slic3r/GUI/Tab.cpp:1746 xs/src/libslic3r/PrintConfig.cpp:143 +#: xs/src/slic3r/GUI/Tab.cpp:1008 xs/src/slic3r/GUI/Tab.cpp:1359 +#: xs/src/slic3r/GUI/Tab.cpp:2241 xs/src/libslic3r/PrintConfig.cpp:143 msgid "Compatible printers" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:603 -#, possible-c-format +#: xs/src/slic3r/GUI/Tab.cpp:1041 +#, no-c-format msgid "" "The Spiral Vase mode requires:\n" "- one perimeter\n" @@ -395,25 +840,11 @@ msgid "" "Shall I adjust those settings in order to enable Spiral Vase?" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:610 +#: xs/src/slic3r/GUI/Tab.cpp:1048 msgid "Spiral Vase" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:630 -msgid "" -"The Wipe Tower currently supports only:\n" -"- first layer height 0.2mm\n" -"- layer height from 0.15mm to 0.35mm\n" -"\n" -"Shall I adjust those settings in order to enable the Wipe Tower?" -msgstr "" - -#: xs/src/slic3r/GUI/Tab.cpp:634 xs/src/slic3r/GUI/Tab.cpp:656 -#: xs/src/slic3r/GUI/Tab.cpp:673 -msgid "Wipe Tower" -msgstr "" - -#: xs/src/slic3r/GUI/Tab.cpp:652 +#: xs/src/slic3r/GUI/Tab.cpp:1069 msgid "" "The Wipe Tower currently supports the non-soluble supports only\n" "if they are printed with the current extruder without triggering a tool " @@ -424,7 +855,11 @@ msgid "" "Shall I adjust those settings in order to enable the Wipe Tower?" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:670 +#: xs/src/slic3r/GUI/Tab.cpp:1073 xs/src/slic3r/GUI/Tab.cpp:1090 +msgid "Wipe Tower" +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:1087 msgid "" "For the Wipe Tower to work with the soluble supports, the support layers\n" "need to be synchronized with the object layers.\n" @@ -432,7 +867,7 @@ msgid "" "Shall I synchronize support layers in order to enable the Wipe Tower?" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:688 +#: xs/src/slic3r/GUI/Tab.cpp:1105 msgid "" "Supports work better, if the following feature is enabled:\n" "- Detect bridging perimeters\n" @@ -440,355 +875,479 @@ msgid "" "Shall I adjust those settings for supports?" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:691 +#: xs/src/slic3r/GUI/Tab.cpp:1108 msgid "Support Generator" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:733 +#: xs/src/slic3r/GUI/Tab.cpp:1150 msgid "The " msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:733 -#, possible-c-format +#: xs/src/slic3r/GUI/Tab.cpp:1150 +#, no-c-format msgid "" " infill pattern is not supposed to work at 100% density.\n" "\n" "Shall I switch to rectilinear fill pattern?" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:860 xs/src/slic3r/GUI/Tab.cpp:861 -#: lib/Slic3r/GUI/Plater.pm:368 +#: xs/src/slic3r/GUI/Tab.cpp:1255 xs/src/slic3r/GUI/Tab.cpp:1256 +#: lib/Slic3r/GUI/Plater.pm:378 msgid "Filament" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:868 +#: xs/src/slic3r/GUI/Tab.cpp:1263 msgid "Temperature " msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:869 xs/src/slic3r/GUI/Tab.cpp:1313 -#: xs/src/libslic3r/PrintConfig.cpp:307 +#: xs/src/slic3r/GUI/Tab.cpp:1264 xs/src/libslic3r/PrintConfig.cpp:335 msgid "Extruder" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:874 +#: xs/src/slic3r/GUI/Tab.cpp:1269 msgid "Bed" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:879 +#: xs/src/slic3r/GUI/Tab.cpp:1274 msgid "Cooling" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:880 xs/src/libslic3r/PrintConfig.cpp:929 -#: xs/src/libslic3r/PrintConfig.cpp:1702 +#: xs/src/slic3r/GUI/Tab.cpp:1275 xs/src/libslic3r/PrintConfig.cpp:1005 +#: xs/src/libslic3r/PrintConfig.cpp:1800 msgid "Enable" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:891 +#: xs/src/slic3r/GUI/Tab.cpp:1286 msgid "Fan settings" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:892 +#: xs/src/slic3r/GUI/Tab.cpp:1287 msgid "Fan speed" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:900 +#: xs/src/slic3r/GUI/Tab.cpp:1295 msgid "Cooling thresholds" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:906 +#: xs/src/slic3r/GUI/Tab.cpp:1301 msgid "Filament properties" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:910 +#: xs/src/slic3r/GUI/Tab.cpp:1305 msgid "Print speed override" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:920 xs/src/slic3r/GUI/Tab.cpp:1197 +#: xs/src/slic3r/GUI/Tab.cpp:1315 +msgid "Toolchange behaviour" +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:1319 +msgid "Ramming" +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:1321 +msgid "Ramming settings" +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:1336 xs/src/slic3r/GUI/Tab.cpp:1634 msgid "Custom G-code" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:921 xs/src/slic3r/GUI/Tab.cpp:1198 -#: xs/src/libslic3r/PrintConfig.cpp:1349 xs/src/libslic3r/PrintConfig.cpp:1364 +#: xs/src/slic3r/GUI/Tab.cpp:1337 xs/src/slic3r/GUI/Tab.cpp:1635 +#: xs/src/libslic3r/PrintConfig.cpp:1449 xs/src/libslic3r/PrintConfig.cpp:1464 msgid "Start G-code" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:927 xs/src/slic3r/GUI/Tab.cpp:1204 -#: xs/src/libslic3r/PrintConfig.cpp:217 xs/src/libslic3r/PrintConfig.cpp:227 +#: xs/src/slic3r/GUI/Tab.cpp:1343 xs/src/slic3r/GUI/Tab.cpp:1641 +#: xs/src/libslic3r/PrintConfig.cpp:245 xs/src/libslic3r/PrintConfig.cpp:255 msgid "End G-code" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1011 xs/src/slic3r/GUI/Preferences.cpp:11 +#: xs/src/slic3r/GUI/Tab.cpp:1438 xs/src/slic3r/GUI/Preferences.cpp:17 msgid "General" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1012 +#: xs/src/slic3r/GUI/Tab.cpp:1439 msgid "Size and coordinates" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1014 xs/src/libslic3r/PrintConfig.cpp:34 +#: xs/src/slic3r/GUI/Tab.cpp:1441 xs/src/libslic3r/PrintConfig.cpp:34 msgid "Bed shape" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1016 xs/src/slic3r/GUI/Tab.cpp:1715 +#: xs/src/slic3r/GUI/Tab.cpp:1443 xs/src/slic3r/GUI/Tab.cpp:2209 msgid " Set " msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1036 +#: xs/src/slic3r/GUI/Tab.cpp:1466 msgid "Capabilities" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1041 +#: xs/src/slic3r/GUI/Tab.cpp:1471 msgid "Number of extruders of the printer." msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1063 +#: xs/src/slic3r/GUI/Tab.cpp:1496 msgid "USB/Serial connection" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1064 xs/src/libslic3r/PrintConfig.cpp:1200 +#: xs/src/slic3r/GUI/Tab.cpp:1497 xs/src/libslic3r/PrintConfig.cpp:1300 msgid "Serial port" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1069 +#: xs/src/slic3r/GUI/Tab.cpp:1502 msgid "Rescan serial ports" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1078 xs/src/slic3r/GUI/Tab.cpp:1125 +#: xs/src/slic3r/GUI/Tab.cpp:1511 xs/src/slic3r/GUI/Tab.cpp:1558 msgid "Test" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1091 +#: xs/src/slic3r/GUI/Tab.cpp:1524 msgid "Connection to printer works correctly." msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1091 xs/src/slic3r/GUI/Tab.cpp:1135 +#: xs/src/slic3r/GUI/Tab.cpp:1524 xs/src/slic3r/GUI/Tab.cpp:1568 msgid "Success!" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1094 +#: xs/src/slic3r/GUI/Tab.cpp:1527 msgid "Connection failed." msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1106 +#: xs/src/slic3r/GUI/Tab.cpp:1539 xs/src/slic3r/Utils/OctoPrint.cpp:50 msgid "OctoPrint upload" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1109 xs/src/slic3r/GUI/Tab.cpp:1156 +#: xs/src/slic3r/GUI/Tab.cpp:1542 xs/src/slic3r/GUI/Tab.cpp:1591 msgid " Browse " msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1135 lib/Slic3r/GUI/MainFrame.pm:209 +#: xs/src/slic3r/GUI/Tab.cpp:1568 msgid "Connection to OctoPrint works correctly." msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1138 +#: xs/src/slic3r/GUI/Tab.cpp:1571 msgid "Could not connect to OctoPrint" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1138 +#: xs/src/slic3r/GUI/Tab.cpp:1571 msgid "Note: OctoPrint version at least 1.1.0 is required." msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1162 +#: xs/src/slic3r/GUI/Tab.cpp:1597 msgid "Certificate files (*.crt, *.pem)|*.crt;*.pem|All files|*.*" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1163 +#: xs/src/slic3r/GUI/Tab.cpp:1598 msgid "Open CA certificate file" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1177 +#: xs/src/slic3r/GUI/Tab.cpp:1612 msgid "" "HTTPS CA file is optional. It is only needed if you use HTTPS with a self-" "signed certificate." msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1188 -msgid "Firmware" -msgstr "" - -#: xs/src/slic3r/GUI/Tab.cpp:1210 xs/src/libslic3r/PrintConfig.cpp:48 +#: xs/src/slic3r/GUI/Tab.cpp:1647 xs/src/libslic3r/PrintConfig.cpp:48 msgid "Before layer change G-code" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1216 xs/src/libslic3r/PrintConfig.cpp:766 +#: xs/src/slic3r/GUI/Tab.cpp:1653 xs/src/libslic3r/PrintConfig.cpp:835 msgid "After layer change G-code" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1222 xs/src/libslic3r/PrintConfig.cpp:1609 +#: xs/src/slic3r/GUI/Tab.cpp:1659 xs/src/libslic3r/PrintConfig.cpp:1707 msgid "Tool change G-code" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1228 +#: xs/src/slic3r/GUI/Tab.cpp:1665 msgid "Between objects G-code (for sequential printing)" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1266 xs/src/libslic3r/GCode/PreviewData.cpp:400 +#: xs/src/slic3r/GUI/Tab.cpp:1716 xs/src/slic3r/GUI/Tab.cpp:1722 +msgid "Single extruder MM setup" +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:1723 +msgid "Single extruder multimaterial parameters" +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:1734 xs/src/libslic3r/GCode/PreviewData.cpp:440 #, possible-c-format msgid "Extruder %d" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1273 +#: xs/src/slic3r/GUI/Tab.cpp:1741 msgid "Layer height limits" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1278 +#: xs/src/slic3r/GUI/Tab.cpp:1746 msgid "Position (for multi-extruder printers)" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1281 +#: xs/src/slic3r/GUI/Tab.cpp:1749 msgid "Retraction" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1284 +#: xs/src/slic3r/GUI/Tab.cpp:1752 msgid "Only lift Z" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1297 +#: xs/src/slic3r/GUI/Tab.cpp:1765 msgid "" "Retraction when tool is disabled (advanced settings for multi-extruder " "setups)" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1301 lib/Slic3r/GUI/Plater.pm:150 -#: lib/Slic3r/GUI/Plater.pm:2095 +#: xs/src/slic3r/GUI/Tab.cpp:1769 lib/Slic3r/GUI/Plater.pm:160 +#: lib/Slic3r/GUI/Plater.pm:2154 msgid "Preview" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1386 +#: xs/src/slic3r/GUI/Tab.cpp:1848 msgid "" "The Wipe option is not available when using the Firmware Retraction mode.\n" "\n" "Shall I disable it in order to enable Firmware Retraction?" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1388 +#: xs/src/slic3r/GUI/Tab.cpp:1850 msgid "Firmware Retraction" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1547 +#: xs/src/slic3r/GUI/Tab.cpp:2022 msgid "Default " msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1547 +#: xs/src/slic3r/GUI/Tab.cpp:2022 msgid " preset" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1548 +#: xs/src/slic3r/GUI/Tab.cpp:2023 msgid " preset\n" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1566 +#: xs/src/slic3r/GUI/Tab.cpp:2041 msgid "" "\n" "\n" "is not compatible with printer\n" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1566 +#: xs/src/slic3r/GUI/Tab.cpp:2041 msgid "" "\n" "\n" "and it has the following unsaved changes:" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1567 +#: xs/src/slic3r/GUI/Tab.cpp:2042 msgid "" "\n" "\n" "has the following unsaved changes:" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1569 +#: xs/src/slic3r/GUI/Tab.cpp:2044 msgid "" "\n" "\n" "Discard changes and continue anyway?" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1570 +#: xs/src/slic3r/GUI/Tab.cpp:2045 msgid "Unsaved Changes" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1638 +#: xs/src/slic3r/GUI/Tab.cpp:2119 msgid "The supplied name is empty. It can't be saved." msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1658 +#: xs/src/slic3r/GUI/Tab.cpp:2124 +msgid "Cannot overwrite a system profile." +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:2128 +msgid "Cannot overwrite an external." +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:2152 msgid "remove" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1658 +#: xs/src/slic3r/GUI/Tab.cpp:2152 msgid "delete" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1659 +#: xs/src/slic3r/GUI/Tab.cpp:2153 msgid "Are you sure you want to " msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1659 +#: xs/src/slic3r/GUI/Tab.cpp:2153 msgid " the selected preset?" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1660 +#: xs/src/slic3r/GUI/Tab.cpp:2154 msgid "Remove" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1660 lib/Slic3r/GUI/Plater.pm:178 -#: lib/Slic3r/GUI/Plater.pm:196 lib/Slic3r/GUI/Plater.pm:1991 +#: xs/src/slic3r/GUI/Tab.cpp:2154 lib/Slic3r/GUI/Plater.pm:188 +#: lib/Slic3r/GUI/Plater.pm:206 lib/Slic3r/GUI/Plater.pm:2050 msgid "Delete" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1661 +#: xs/src/slic3r/GUI/Tab.cpp:2155 msgid " Preset" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1714 +#: xs/src/slic3r/GUI/Tab.cpp:2208 msgid "All" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1745 +#: xs/src/slic3r/GUI/Tab.cpp:2240 msgid "Select the printers this profile is compatible with." msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1834 lib/Slic3r/GUI/MainFrame.pm:509 -#: lib/Slic3r/GUI/Plater.pm:1615 +#: xs/src/slic3r/GUI/Tab.cpp:2286 xs/src/slic3r/GUI/Tab.cpp:2372 +#: xs/src/slic3r/GUI/Preset.cpp:605 xs/src/slic3r/GUI/Preset.cpp:645 +#: xs/src/slic3r/GUI/Preset.cpp:670 xs/src/slic3r/GUI/Preset.cpp:702 +#: xs/src/slic3r/GUI/PresetBundle.cpp:1069 +#: xs/src/slic3r/GUI/PresetBundle.cpp:1122 lib/Slic3r/GUI/Plater.pm:552 +msgid "System presets" +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:2287 xs/src/slic3r/GUI/Tab.cpp:2373 +msgid "Default presets" +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:2442 +msgid "" +"LOCKED LOCK;indicates that the settings are the same as the system values " +"for the current option group" +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:2445 +msgid "" +"UNLOCKED LOCK;indicates that some settings were changed and are not equal to " +"the system values for the current option group.\n" +"Click the UNLOCKED LOCK icon to reset all settings for current option group " +"to the system values." +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:2451 +msgid "" +"WHITE BULLET;for the left button: \tindicates a non-system preset,\n" +"for the right button: \tindicates that the settings hasn't been modified." +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:2455 +msgid "" +"BACK ARROW;indicates that the settings were changed and are not equal to the " +"last saved preset for the current option group.\n" +"Click the BACK ARROW icon to reset all settings for the current option group " +"to the last saved preset." +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:2481 +msgid "" +"LOCKED LOCK icon indicates that the settings are the same as the system " +"values for the current option group" +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:2483 +msgid "" +"UNLOCKED LOCK icon indicates that some settings were changed and are not " +"equal to the system values for the current option group.\n" +"Click to reset all settings for current option group to the system values." +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:2486 +msgid "WHITE BULLET icon indicates a non system preset." +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:2489 +msgid "" +"WHITE BULLET icon indicates that the settings are the same as in the last " +"saved preset for the current option group." +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:2491 +msgid "" +"BACK ARROW icon indicates that the settings were changed and are not equal " +"to the last saved preset for the current option group.\n" +"Click to reset all settings for the current option group to the last saved " +"preset." +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:2497 +msgid "" +"LOCKED LOCK icon indicates that the value is the same as the system value." +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:2498 +msgid "" +"UNLOCKED LOCK icon indicates that the value was changed and is not equal to " +"the system value.\n" +"Click to reset current value to the system value." +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:2504 +msgid "" +"WHITE BULLET icon indicates that the value is the same as in the last saved " +"preset." +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:2505 +msgid "" +"BACK ARROW icon indicates that the value was changed and is not equal to the " +"last saved preset.\n" +"Click to reset current value to the last saved preset." +msgstr "" + +#: xs/src/slic3r/GUI/Tab.cpp:2575 lib/Slic3r/GUI/MainFrame.pm:445 +#: lib/Slic3r/GUI/Plater.pm:1660 msgid "Save " msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1834 +#: xs/src/slic3r/GUI/Tab.cpp:2575 msgid " as:" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1868 +#: xs/src/slic3r/GUI/Tab.cpp:2609 msgid "" "The supplied name is not valid; the following characters are not allowed:" msgstr "" -#: xs/src/slic3r/GUI/Tab.cpp:1871 +#: xs/src/slic3r/GUI/Tab.cpp:2612 msgid "The supplied name is not available." msgstr "" -#: xs/src/slic3r/GUI/Tab.hpp:185 +#: xs/src/slic3r/GUI/Tab.hpp:283 msgid "Print Settings" msgstr "" -#: xs/src/slic3r/GUI/Tab.hpp:205 +#: xs/src/slic3r/GUI/Tab.hpp:303 msgid "Filament Settings" msgstr "" -#: xs/src/slic3r/GUI/Tab.hpp:226 +#: xs/src/slic3r/GUI/Tab.hpp:325 msgid "Printer Settings" msgstr "" -#: xs/src/slic3r/GUI/Tab.hpp:240 +#: xs/src/slic3r/GUI/Tab.hpp:340 msgid "Save preset" msgstr "" -#: xs/src/slic3r/GUI/Field.cpp:59 +#: xs/src/slic3r/GUI/Field.cpp:72 msgid "default" msgstr "" +#: xs/src/slic3r/GUI/Preset.cpp:649 xs/src/slic3r/GUI/Preset.cpp:706 +#: xs/src/slic3r/GUI/PresetBundle.cpp:1127 lib/Slic3r/GUI/Plater.pm:553 +msgid "User presets" +msgstr "" + #: xs/src/slic3r/GUI/PresetHints.cpp:27 #, possible-c-format msgid "" @@ -915,123 +1474,300 @@ msgstr "" msgid "%d lines: %.2lf mm" msgstr "" -#: xs/src/slic3r/GUI/Preferences.hpp:17 -msgid "Preferences" -msgstr "" - -#: xs/src/slic3r/GUI/Preferences.cpp:27 +#: xs/src/slic3r/GUI/Preferences.cpp:34 msgid "Remember output directory" msgstr "" -#: xs/src/slic3r/GUI/Preferences.cpp:29 +#: xs/src/slic3r/GUI/Preferences.cpp:36 msgid "" "If this is enabled, Slic3r will prompt the last output directory instead of " "the one containing the input files." msgstr "" -#: xs/src/slic3r/GUI/Preferences.cpp:35 +#: xs/src/slic3r/GUI/Preferences.cpp:42 msgid "Auto-center parts" msgstr "" -#: xs/src/slic3r/GUI/Preferences.cpp:37 +#: xs/src/slic3r/GUI/Preferences.cpp:44 msgid "" "If this is enabled, Slic3r will auto-center objects around the print bed " "center." msgstr "" -#: xs/src/slic3r/GUI/Preferences.cpp:43 +#: xs/src/slic3r/GUI/Preferences.cpp:50 msgid "Background processing" msgstr "" -#: xs/src/slic3r/GUI/Preferences.cpp:45 +#: xs/src/slic3r/GUI/Preferences.cpp:52 msgid "" "If this is enabled, Slic3r will pre-process objects as soon as they're " "loaded in order to save time when exporting G-code." msgstr "" -#: xs/src/slic3r/GUI/Preferences.cpp:51 +#: xs/src/slic3r/GUI/Preferences.cpp:74 msgid "Disable USB/serial connection" msgstr "" -#: xs/src/slic3r/GUI/Preferences.cpp:53 +#: xs/src/slic3r/GUI/Preferences.cpp:76 msgid "" "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." msgstr "" -#: xs/src/slic3r/GUI/Preferences.cpp:59 +#: xs/src/slic3r/GUI/Preferences.cpp:82 msgid "Suppress \" - default - \" presets" msgstr "" -#: xs/src/slic3r/GUI/Preferences.cpp:61 +#: xs/src/slic3r/GUI/Preferences.cpp:84 msgid "" "Suppress \" - default - \" presets in the Print / Filament / Printer " "selections once there are any other valid presets available." msgstr "" -#: xs/src/slic3r/GUI/Preferences.cpp:67 +#: xs/src/slic3r/GUI/Preferences.cpp:90 msgid "Show incompatible print and filament presets" msgstr "" -#: xs/src/slic3r/GUI/Preferences.cpp:69 +#: xs/src/slic3r/GUI/Preferences.cpp:92 msgid "" "When checked, the print and filament presets are shown in the preset editor " "even if they are marked as incompatible with the active printer" msgstr "" -#: xs/src/slic3r/GUI/Preferences.cpp:75 +#: xs/src/slic3r/GUI/Preferences.cpp:98 msgid "Use legacy OpenGL 1.1 rendering" msgstr "" -#: xs/src/slic3r/GUI/Preferences.cpp:77 +#: xs/src/slic3r/GUI/Preferences.cpp:100 msgid "" "If you have rendering issues caused by a buggy OpenGL 2.0 driver, you may " "try to check this checkbox. This will disable the layer height editing and " "anti aliasing, so it is likely better to upgrade your graphics driver." msgstr "" -#: xs/src/slic3r/GUI/Preferences.cpp:101 +#: xs/src/slic3r/GUI/Preferences.cpp:124 msgid "You need to restart Slic3r to make the changes effective." msgstr "" -#: xs/src/slic3r/GUI/BonjourDialog.cpp:53 -msgid "Network lookup" +#: xs/src/slic3r/GUI/RammingChart.cpp:28 +msgid "NO RAMMING AT ALL" msgstr "" -#: xs/src/slic3r/GUI/BonjourDialog.cpp:66 -msgid "Address" +#: xs/src/slic3r/GUI/RammingChart.cpp:81 +msgid "Time" msgstr "" -#: xs/src/slic3r/GUI/BonjourDialog.cpp:67 -msgid "Hostname" +#: xs/src/slic3r/GUI/RammingChart.cpp:81 xs/src/slic3r/GUI/RammingChart.cpp:86 +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:82 +#: xs/src/libslic3r/PrintConfig.cpp:480 +msgid "s" msgstr "" -#: xs/src/slic3r/GUI/BonjourDialog.cpp:68 -msgid "Service name" +#: xs/src/slic3r/GUI/RammingChart.cpp:86 +msgid "Volumetric speed" msgstr "" -#: xs/src/slic3r/GUI/BonjourDialog.cpp:69 -msgid "OctoPrint version" +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:27 +msgid "Update available" msgstr "" -#: xs/src/slic3r/GUI/BonjourDialog.cpp:187 -msgid "Searching for devices" +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:27 +msgid "New version of Slic3r PE is available" msgstr "" -#: xs/src/slic3r/GUI/BonjourDialog.cpp:194 -msgid "Finished." +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:34 +msgid "To download, follow the link below." msgstr "" -#: xs/src/slic3r/Utils/OctoPrint.cpp:53 -msgid "G-code file successfully uploaded to the OctoPrint server" +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:41 +msgid "Current version:" msgstr "" -#: xs/src/slic3r/Utils/OctoPrint.cpp:67 +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:43 +msgid "New version:" +msgstr "" + +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:51 +msgid "Don't notify about new releases any more" +msgstr "" + +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:69 +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:161 +msgid "Configuration update" +msgstr "" + +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:69 +msgid "Configuration update is available" +msgstr "" + +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:72 +msgid "" +"Would you like to install it?\n" +"\n" +"Note that a full configuration snapshot will be created first. It can then " +"be restored at any time should there be a problem with the new version.\n" +"\n" +"Updated configuration bundles:" +msgstr "" + +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:108 +msgid "Slic3r incompatibility" +msgstr "" + +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:108 +msgid "Slic3r configuration is incompatible" +msgstr "" + +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:111 +msgid "" +"This version of Slic3r PE is not compatible with currently installed " +"configuration bundles.\n" +"This probably happened as a result of running an older Slic3r PE after using " +"a newer one.\n" +"\n" +"You may either exit Slic3r and try again with a newer version, or you may re-" +"run the initial configuration. Doing so will create a backup snapshot of the " +"existing configuration before installing files compatible with this Slic3r.\n" +msgstr "" + +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:120 +#, possible-c-format +msgid "This Slic3r PE version: %s" +msgstr "" + +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:125 +msgid "Incompatible bundles:" +msgstr "" + +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:141 +msgid "Exit Slic3r" +msgstr "" + +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:144 +msgid "Re-configure" +msgstr "" + +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:165 +#, possible-c-format +msgid "" +"Slic3r PE now uses an updated configuration structure.\n" +"\n" +"So called 'System presets' have been introduced, which hold the built-in " +"default settings for various printers. These System presets cannot be " +"modified, instead, users now may create their own presets inheriting " +"settings from one of the System presets.\n" +"An inheriting preset may either inherit a particular value from its parent " +"or override it with a customized value.\n" +"\n" +"Please proceed with the %s that follows to set up the new presets and to " +"choose whether to enable automatic preset updates." +msgstr "" + +#: xs/src/slic3r/GUI/UpdateDialogs.cpp:181 +msgid "For more information please visit our wiki page:" +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:14 +msgid "Ramming customization" +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:40 +msgid "" +"Ramming denotes the rapid extrusion just before a tool change in a single-" +"extruder MM printer. Its purpose is to properly shape the end of the " +"unloaded filament so it does not prevent insertion of the new filament and " +"can itself be reinserted later. This phase is important and different " +"materials can require different extrusion speeds to get the good shape. For " +"this reason, the extrusion rates during ramming are adjustable.\n" +"\n" +"This is an expert-level setting, incorrect adjustment will likely lead to " +"jams, extruder wheel grinding into filament etc." +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:82 +msgid "Total ramming time" +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:84 +msgid "Total rammed volume" +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:88 +msgid "Ramming line width" +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:90 +msgid "Ramming line spacing" +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:142 +msgid "Wipe tower - Purging volume adjustment" +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:223 +#, possible-c-format +msgid "" +"Here you can adjust required purging volume (mm%s) for any given pair of " +"tools." +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:224 +msgid "Extruder changed to" +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:232 +msgid "unloaded" +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:233 +msgid "loaded" +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:238 +msgid "Tool #" +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:245 +msgid "" +"Total purging volume is calculated by summing two values below, depending on " +"which tools are loaded/unloaded." +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:246 +#, possible-c-format +msgid "Volume to purge (mm%s) when the filament is being" +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:260 +msgid "From" +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:325 +msgid "" +"Switching to simple settings will discard changes done in the advanced " +"mode!\n" +"\n" +"Do you want to proceed?" +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:337 +msgid "Show simplified settings" +msgstr "" + +#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:337 +msgid "Show advanced settings" +msgstr "" + +#: xs/src/slic3r/Utils/OctoPrint.cpp:47 msgid "Error while uploading to the OctoPrint server" msgstr "" -#: xs/src/slic3r/Utils/OctoPrint.cpp:102 +#: xs/src/slic3r/Utils/OctoPrint.cpp:51 lib/Slic3r/GUI/Plater.pm:1493 +msgid "Sending G-code file to the OctoPrint server..." +msgstr "" + +#: xs/src/slic3r/Utils/OctoPrint.cpp:120 msgid "Invalid API key" msgstr "" @@ -1046,7 +1782,7 @@ msgid "" "feature slows down both the print and the G-code generation." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:38 xs/src/libslic3r/PrintConfig.cpp:1579 +#: xs/src/libslic3r/PrintConfig.cpp:38 xs/src/libslic3r/PrintConfig.cpp:1677 msgid "Other layers" msgstr "" @@ -1077,20 +1813,20 @@ msgid "" "default extruder and bed temperature are reset using non-wait command; " "however if M104, M109, M140 or M190 are detected in this custom code, Slic3r " "will not add temperature commands. Note that you can use placeholder " -"variables for all Slic3r settings, so you can put a \"M109 " -"S[first_layer_temperature]\" command wherever you want." +"variables for all Slic3r settings, so you can put a \"M109 S" +"[first_layer_temperature]\" command wherever you want." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:68 lib/Slic3r/GUI/MainFrame.pm:364 +#: xs/src/libslic3r/PrintConfig.cpp:68 lib/Slic3r/GUI/MainFrame.pm:307 msgid "Bottom" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:69 xs/src/libslic3r/PrintConfig.cpp:239 -#: xs/src/libslic3r/PrintConfig.cpp:290 xs/src/libslic3r/PrintConfig.cpp:298 -#: xs/src/libslic3r/PrintConfig.cpp:604 xs/src/libslic3r/PrintConfig.cpp:762 -#: xs/src/libslic3r/PrintConfig.cpp:778 xs/src/libslic3r/PrintConfig.cpp:948 -#: xs/src/libslic3r/PrintConfig.cpp:996 xs/src/libslic3r/PrintConfig.cpp:1159 -#: xs/src/libslic3r/PrintConfig.cpp:1590 xs/src/libslic3r/PrintConfig.cpp:1646 +#: xs/src/libslic3r/PrintConfig.cpp:69 xs/src/libslic3r/PrintConfig.cpp:267 +#: xs/src/libslic3r/PrintConfig.cpp:318 xs/src/libslic3r/PrintConfig.cpp:326 +#: xs/src/libslic3r/PrintConfig.cpp:666 xs/src/libslic3r/PrintConfig.cpp:831 +#: xs/src/libslic3r/PrintConfig.cpp:847 xs/src/libslic3r/PrintConfig.cpp:1024 +#: xs/src/libslic3r/PrintConfig.cpp:1081 xs/src/libslic3r/PrintConfig.cpp:1259 +#: xs/src/libslic3r/PrintConfig.cpp:1688 xs/src/libslic3r/PrintConfig.cpp:1744 msgid "Layers and Perimeters" msgstr "" @@ -1112,9 +1848,9 @@ msgid "" "disable acceleration control for bridges." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:80 xs/src/libslic3r/PrintConfig.cpp:174 -#: xs/src/libslic3r/PrintConfig.cpp:576 xs/src/libslic3r/PrintConfig.cpp:684 -#: xs/src/libslic3r/PrintConfig.cpp:959 +#: xs/src/libslic3r/PrintConfig.cpp:80 xs/src/libslic3r/PrintConfig.cpp:190 +#: xs/src/libslic3r/PrintConfig.cpp:638 xs/src/libslic3r/PrintConfig.cpp:746 +#: xs/src/libslic3r/PrintConfig.cpp:1044 msgid "mm/s²" msgstr "" @@ -1129,9 +1865,9 @@ msgid "" "bridges. Use 180° for zero angle." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:91 xs/src/libslic3r/PrintConfig.cpp:492 -#: xs/src/libslic3r/PrintConfig.cpp:1177 xs/src/libslic3r/PrintConfig.cpp:1188 -#: xs/src/libslic3r/PrintConfig.cpp:1408 xs/src/libslic3r/PrintConfig.cpp:1564 +#: xs/src/libslic3r/PrintConfig.cpp:91 xs/src/libslic3r/PrintConfig.cpp:554 +#: xs/src/libslic3r/PrintConfig.cpp:1277 xs/src/libslic3r/PrintConfig.cpp:1288 +#: xs/src/libslic3r/PrintConfig.cpp:1508 xs/src/libslic3r/PrintConfig.cpp:1662 msgid "°" msgstr "" @@ -1143,9 +1879,9 @@ msgstr "" msgid "This fan speed is enforced during all bridges and overhangs." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:99 xs/src/libslic3r/PrintConfig.cpp:504 -#: xs/src/libslic3r/PrintConfig.cpp:789 xs/src/libslic3r/PrintConfig.cpp:850 -#: xs/src/libslic3r/PrintConfig.cpp:1067 +#: xs/src/libslic3r/PrintConfig.cpp:99 xs/src/libslic3r/PrintConfig.cpp:566 +#: xs/src/libslic3r/PrintConfig.cpp:858 xs/src/libslic3r/PrintConfig.cpp:926 +#: xs/src/libslic3r/PrintConfig.cpp:1167 msgid "%" msgstr "" @@ -1169,11 +1905,12 @@ msgstr "" msgid "Speed for printing bridges." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:120 xs/src/libslic3r/PrintConfig.cpp:638 -#: xs/src/libslic3r/PrintConfig.cpp:749 xs/src/libslic3r/PrintConfig.cpp:811 -#: xs/src/libslic3r/PrintConfig.cpp:868 xs/src/libslic3r/PrintConfig.cpp:988 -#: xs/src/libslic3r/PrintConfig.cpp:1144 xs/src/libslic3r/PrintConfig.cpp:1153 -#: xs/src/libslic3r/PrintConfig.cpp:1543 xs/src/libslic3r/PrintConfig.cpp:1656 +#: xs/src/libslic3r/PrintConfig.cpp:120 xs/src/libslic3r/PrintConfig.cpp:461 +#: xs/src/libslic3r/PrintConfig.cpp:470 xs/src/libslic3r/PrintConfig.cpp:700 +#: xs/src/libslic3r/PrintConfig.cpp:811 xs/src/libslic3r/PrintConfig.cpp:887 +#: xs/src/libslic3r/PrintConfig.cpp:944 xs/src/libslic3r/PrintConfig.cpp:1073 +#: xs/src/libslic3r/PrintConfig.cpp:1244 xs/src/libslic3r/PrintConfig.cpp:1253 +#: xs/src/libslic3r/PrintConfig.cpp:1641 xs/src/libslic3r/PrintConfig.cpp:1754 msgid "mm/s" msgstr "" @@ -1231,65 +1968,103 @@ msgid "" "fan speed according to layer printing time." msgstr "" +#: xs/src/libslic3r/PrintConfig.cpp:170 +msgid "Cooling tube position" +msgstr "" + #: xs/src/libslic3r/PrintConfig.cpp:171 +msgid "Distance of the center-point of the cooling tube from the extruder tip " +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:178 +msgid "Cooling tube length" +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:179 +msgid "Length of the cooling tube to limit space for cooling moves inside it " +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:187 msgid "" "This is the acceleration your printer will be reset to after the role-" "specific acceleration values are used (perimeter/infill). Set zero to " "prevent resetting acceleration at all." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:180 +#: xs/src/libslic3r/PrintConfig.cpp:196 +msgid "Default filament profile" +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:197 +msgid "" +"Default filament profile associated with the current printer profile. On " +"selection of the current printer profile, this filament profile will be " +"activated." +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:202 +msgid "Default print profile" +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:203 +msgid "" +"Default print profile associated with the current printer profile. On " +"selection of the current printer profile, this print profile will be " +"activated." +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:208 msgid "Disable fan for the first" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:181 +#: xs/src/libslic3r/PrintConfig.cpp:209 msgid "" "You can set this to a positive value to disable fan at all during the first " "layers, so that it does not make adhesion worse." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:183 xs/src/libslic3r/PrintConfig.cpp:694 -#: xs/src/libslic3r/PrintConfig.cpp:1040 xs/src/libslic3r/PrintConfig.cpp:1231 -#: xs/src/libslic3r/PrintConfig.cpp:1292 xs/src/libslic3r/PrintConfig.cpp:1444 -#: xs/src/libslic3r/PrintConfig.cpp:1489 +#: xs/src/libslic3r/PrintConfig.cpp:211 xs/src/libslic3r/PrintConfig.cpp:756 +#: xs/src/libslic3r/PrintConfig.cpp:1140 xs/src/libslic3r/PrintConfig.cpp:1331 +#: xs/src/libslic3r/PrintConfig.cpp:1392 xs/src/libslic3r/PrintConfig.cpp:1544 +#: xs/src/libslic3r/PrintConfig.cpp:1589 msgid "layers" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:190 +#: xs/src/libslic3r/PrintConfig.cpp:218 msgid "Don't support bridges" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:192 +#: xs/src/libslic3r/PrintConfig.cpp:220 msgid "" "Experimental option for preventing support material from being generated " "under bridged areas." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:198 +#: xs/src/libslic3r/PrintConfig.cpp:226 msgid "Distance between copies" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:199 +#: xs/src/libslic3r/PrintConfig.cpp:227 msgid "Distance used for the auto-arrange feature of the plater." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:207 +#: xs/src/libslic3r/PrintConfig.cpp:235 msgid "Elephant foot compensation" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:209 +#: xs/src/libslic3r/PrintConfig.cpp:237 msgid "" "The first layer will be shrunk in the XY plane by the configured value to " "compensate for the 1st layer squish aka an Elephant Foot effect." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:218 +#: xs/src/libslic3r/PrintConfig.cpp:246 msgid "" "This end procedure is inserted at the end of the output file. Note that you " "can use placeholder variables for all Slic3r settings." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:228 +#: xs/src/libslic3r/PrintConfig.cpp:256 msgid "" "This end procedure is inserted at the end of the output file, before the " "printer end gcode. Note that you can use placeholder variables for all " @@ -1297,38 +2072,38 @@ msgid "" "extruder order." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:238 +#: xs/src/libslic3r/PrintConfig.cpp:266 msgid "Ensure vertical shell thickness" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:240 +#: xs/src/libslic3r/PrintConfig.cpp:268 msgid "" "Add solid infill near sloping surfaces to guarantee the vertical shell " "thickness (top+bottom solid layers)." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:246 +#: xs/src/libslic3r/PrintConfig.cpp:274 msgid "Top/bottom fill pattern" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:248 +#: xs/src/libslic3r/PrintConfig.cpp:276 msgid "" "Fill pattern for top/bottom infill. This only affects the external visible " "layer, and not its adjacent solid shells." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:267 xs/src/libslic3r/PrintConfig.cpp:277 +#: xs/src/libslic3r/PrintConfig.cpp:295 xs/src/libslic3r/PrintConfig.cpp:305 msgid "External perimeters" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:268 xs/src/libslic3r/PrintConfig.cpp:377 -#: xs/src/libslic3r/PrintConfig.cpp:592 xs/src/libslic3r/PrintConfig.cpp:710 -#: xs/src/libslic3r/PrintConfig.cpp:974 xs/src/libslic3r/PrintConfig.cpp:1299 -#: xs/src/libslic3r/PrintConfig.cpp:1461 xs/src/libslic3r/PrintConfig.cpp:1621 +#: xs/src/libslic3r/PrintConfig.cpp:296 xs/src/libslic3r/PrintConfig.cpp:405 +#: xs/src/libslic3r/PrintConfig.cpp:654 xs/src/libslic3r/PrintConfig.cpp:772 +#: xs/src/libslic3r/PrintConfig.cpp:1059 xs/src/libslic3r/PrintConfig.cpp:1399 +#: xs/src/libslic3r/PrintConfig.cpp:1561 xs/src/libslic3r/PrintConfig.cpp:1719 msgid "Extrusion Width" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:269 +#: xs/src/libslic3r/PrintConfig.cpp:297 msgid "" "Set this to a non-zero value to set a manual extrusion width for external " "perimeters. If left zero, default extrusion width will be used if set, " @@ -1336,60 +2111,60 @@ msgid "" "(for example 200%), it will be computed over layer height." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:272 xs/src/libslic3r/PrintConfig.cpp:597 -#: xs/src/libslic3r/PrintConfig.cpp:715 xs/src/libslic3r/PrintConfig.cpp:979 -#: xs/src/libslic3r/PrintConfig.cpp:1303 xs/src/libslic3r/PrintConfig.cpp:1465 -#: xs/src/libslic3r/PrintConfig.cpp:1626 +#: xs/src/libslic3r/PrintConfig.cpp:300 xs/src/libslic3r/PrintConfig.cpp:659 +#: xs/src/libslic3r/PrintConfig.cpp:777 xs/src/libslic3r/PrintConfig.cpp:1064 +#: xs/src/libslic3r/PrintConfig.cpp:1403 xs/src/libslic3r/PrintConfig.cpp:1565 +#: xs/src/libslic3r/PrintConfig.cpp:1724 msgid "mm or % (leave 0 for default)" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:279 +#: xs/src/libslic3r/PrintConfig.cpp:307 msgid "" "This separate setting will affect the speed of external perimeters (the " "visible ones). If expressed as percentage (for example: 80%) it will be " "calculated on the perimeters speed setting above. Set to zero for auto." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:282 xs/src/libslic3r/PrintConfig.cpp:619 -#: xs/src/libslic3r/PrintConfig.cpp:1262 xs/src/libslic3r/PrintConfig.cpp:1313 -#: xs/src/libslic3r/PrintConfig.cpp:1508 xs/src/libslic3r/PrintConfig.cpp:1638 +#: xs/src/libslic3r/PrintConfig.cpp:310 xs/src/libslic3r/PrintConfig.cpp:681 +#: xs/src/libslic3r/PrintConfig.cpp:1362 xs/src/libslic3r/PrintConfig.cpp:1413 +#: xs/src/libslic3r/PrintConfig.cpp:1608 xs/src/libslic3r/PrintConfig.cpp:1736 msgid "mm/s or %" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:289 +#: xs/src/libslic3r/PrintConfig.cpp:317 msgid "External perimeters first" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:291 +#: xs/src/libslic3r/PrintConfig.cpp:319 msgid "" "Print contour perimeters from the outermost one to the innermost one instead " "of the default inverse order." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:297 +#: xs/src/libslic3r/PrintConfig.cpp:325 msgid "Extra perimeters if needed" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:299 -#, possible-c-format +#: xs/src/libslic3r/PrintConfig.cpp:327 +#, no-c-format msgid "" "Add more perimeters when needed for avoiding gaps in sloping walls. Slic3r " "keeps adding perimeters, until more than 70% of the loop immediately above " "is supported." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:309 +#: xs/src/libslic3r/PrintConfig.cpp:337 msgid "" "The extruder to use (unless more specific extruder settings are specified). " "This value overrides perimeter and infill extruders, but not the support " "extruders." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:320 lib/Slic3r/GUI/Plater/3DPreview.pm:69 +#: xs/src/libslic3r/PrintConfig.cpp:348 lib/Slic3r/GUI/Plater/3DPreview.pm:68 msgid "Height" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:321 +#: xs/src/libslic3r/PrintConfig.cpp:349 msgid "" "Set this to the vertical distance between your nozzle tip and (usually) the " "X carriage rods. In other words, this is the height of the clearance " @@ -1397,30 +2172,30 @@ msgid "" "extruder can peek before colliding with other printed objects." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:331 +#: xs/src/libslic3r/PrintConfig.cpp:359 msgid "Radius" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:332 +#: xs/src/libslic3r/PrintConfig.cpp:360 msgid "" "Set this to the clearance radius around your extruder. If the extruder is " "not centered, choose the largest value for safety. This setting is used to " "check for collisions and to display the graphical preview in the plater." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:342 +#: xs/src/libslic3r/PrintConfig.cpp:370 msgid "Extruder Color" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:343 xs/src/libslic3r/PrintConfig.cpp:406 +#: xs/src/libslic3r/PrintConfig.cpp:371 xs/src/libslic3r/PrintConfig.cpp:434 msgid "This is only used in the Slic3r interface as a visual help." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:350 +#: xs/src/libslic3r/PrintConfig.cpp:378 msgid "Extruder offset" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:351 +#: xs/src/libslic3r/PrintConfig.cpp:379 msgid "" "If your firmware doesn't handle the extruder displacement you need the G-" "code to take it into account. This option lets you specify the displacement " @@ -1428,21 +2203,21 @@ msgid "" "coordinates (they will be subtracted from the XY coordinate)." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:360 +#: xs/src/libslic3r/PrintConfig.cpp:388 msgid "Extrusion axis" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:361 +#: xs/src/libslic3r/PrintConfig.cpp:389 msgid "" "Use this option to set the axis letter associated to your printer's extruder " "(usually E but some printers use A)." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:367 +#: xs/src/libslic3r/PrintConfig.cpp:395 msgid "Extrusion multiplier" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:368 +#: xs/src/libslic3r/PrintConfig.cpp:396 msgid "" "This factor changes the amount of flow proportionally. You may need to tweak " "this setting to get nice surface finish and correct single wall widths. " @@ -1450,11 +2225,11 @@ msgid "" "more, check filament diameter and your firmware E steps." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:376 +#: xs/src/libslic3r/PrintConfig.cpp:404 msgid "Default extrusion width" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:378 +#: xs/src/libslic3r/PrintConfig.cpp:406 msgid "" "Set this to a non-zero value to allow a manual extrusion width. If left to " "zero, Slic3r derives extrusion widths from the nozzle diameter (see the " @@ -1463,74 +2238,113 @@ msgid "" "height." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:382 +#: xs/src/libslic3r/PrintConfig.cpp:410 msgid "mm or % (leave 0 for auto)" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:387 +#: xs/src/libslic3r/PrintConfig.cpp:415 msgid "Keep fan always on" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:388 +#: xs/src/libslic3r/PrintConfig.cpp:416 msgid "" "If this is enabled, fan will never be disabled and will be kept running at " "least at its minimum speed. Useful for PLA, harmful for ABS." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:394 +#: xs/src/libslic3r/PrintConfig.cpp:422 msgid "Enable fan if layer print time is below" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:395 +#: xs/src/libslic3r/PrintConfig.cpp:423 msgid "" "If layer print time is estimated below this number of seconds, fan will be " "enabled and its speed will be calculated by interpolating the minimum and " "maximum speeds." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:397 xs/src/libslic3r/PrintConfig.cpp:1249 +#: xs/src/libslic3r/PrintConfig.cpp:425 xs/src/libslic3r/PrintConfig.cpp:1349 msgid "approximate seconds" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:405 +#: xs/src/libslic3r/PrintConfig.cpp:433 msgid "Color" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:412 +#: xs/src/libslic3r/PrintConfig.cpp:440 msgid "Filament notes" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:413 +#: xs/src/libslic3r/PrintConfig.cpp:441 msgid "You can put your notes regarding the filament here." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:421 xs/src/libslic3r/PrintConfig.cpp:817 +#: xs/src/libslic3r/PrintConfig.cpp:449 xs/src/libslic3r/PrintConfig.cpp:893 msgid "Max volumetric speed" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:422 +#: xs/src/libslic3r/PrintConfig.cpp:450 msgid "" "Maximum volumetric speed allowed for this filament. Limits the maximum " "volumetric speed of a print to the minimum of print and filament volumetric " "speed. Set to zero for no limit." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:425 xs/src/libslic3r/PrintConfig.cpp:820 +#: xs/src/libslic3r/PrintConfig.cpp:453 xs/src/libslic3r/PrintConfig.cpp:896 msgid "mm³/s" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:432 +#: xs/src/libslic3r/PrintConfig.cpp:459 +msgid "Loading speed" +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:460 +msgid "Speed used for loading the filament on the wipe tower. " +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:467 +msgid "Unloading speed" +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:468 +msgid "" +"Speed used for unloading the filament on the wipe tower (does not affect " +"initial part of unloading just after ramming). " +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:476 +msgid "Delay after unloading" +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:477 +msgid "" +"Time to wait after the filament is unloaded. May help to get reliable " +"toolchanges with flexible materials that may need more time to shrink to " +"original dimensions. " +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:486 +msgid "Ramming parameters" +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:487 +msgid "" +"This string is edited by RammingDialog and contains ramming specific " +"parameters " +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:494 msgid "" "Enter your filament diameter here. Good precision is required, so use a " "caliper and do multiple measurements along the filament, then compute the " "average." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:440 +#: xs/src/libslic3r/PrintConfig.cpp:502 msgid "Density" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:441 +#: xs/src/libslic3r/PrintConfig.cpp:503 msgid "" "Enter your filament density here. This is only for statistical information. " "A decent way is to weigh a known length of filament and compute the ratio of " @@ -1538,15 +2352,15 @@ msgid "" "displacement." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:444 +#: xs/src/libslic3r/PrintConfig.cpp:506 msgid "g/cm³" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:450 +#: xs/src/libslic3r/PrintConfig.cpp:512 msgid "Filament type" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:451 xs/src/libslic3r/PrintConfig.cpp:1009 +#: xs/src/libslic3r/PrintConfig.cpp:513 xs/src/libslic3r/PrintConfig.cpp:1094 msgid "" "If you want to process the output G-code through custom scripts, just list " "their absolute paths here. Separate multiple scripts with a semicolon. " @@ -1555,73 +2369,74 @@ msgid "" "environment variables." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:470 +#: xs/src/libslic3r/PrintConfig.cpp:532 msgid "Soluble material" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:471 +#: xs/src/libslic3r/PrintConfig.cpp:533 msgid "Soluble material is most likely used for a soluble support." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:476 lib/Slic3r/GUI/Plater.pm:453 +#: xs/src/libslic3r/PrintConfig.cpp:538 lib/Slic3r/GUI/Plater.pm:463 msgid "Cost" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:477 +#: xs/src/libslic3r/PrintConfig.cpp:539 msgid "" "Enter your filament cost per kg here. This is only for statistical " "information." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:478 +#: xs/src/libslic3r/PrintConfig.cpp:540 msgid "money/kg" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:487 +#: xs/src/libslic3r/PrintConfig.cpp:549 msgid "Fill angle" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:489 +#: xs/src/libslic3r/PrintConfig.cpp:551 msgid "" "Default base angle for infill orientation. Cross-hatching will be applied to " "this. Bridges will be infilled using the best direction Slic3r can detect, " "so this setting does not affect them." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:501 +#: xs/src/libslic3r/PrintConfig.cpp:563 msgid "Fill density" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:503 +#: xs/src/libslic3r/PrintConfig.cpp:565 +#, possible-c-format msgid "Density of internal infill, expressed in the range 0% - 100%." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:539 +#: xs/src/libslic3r/PrintConfig.cpp:601 msgid "Fill pattern" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:541 +#: xs/src/libslic3r/PrintConfig.cpp:603 msgid "Fill pattern for general low-density infill." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:573 xs/src/libslic3r/PrintConfig.cpp:582 -#: xs/src/libslic3r/PrintConfig.cpp:591 xs/src/libslic3r/PrintConfig.cpp:625 +#: xs/src/libslic3r/PrintConfig.cpp:635 xs/src/libslic3r/PrintConfig.cpp:644 +#: xs/src/libslic3r/PrintConfig.cpp:653 xs/src/libslic3r/PrintConfig.cpp:687 msgid "First layer" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:574 +#: xs/src/libslic3r/PrintConfig.cpp:636 msgid "" "This is the acceleration your printer will use for first layer. Set zero to " "disable acceleration control for first layer." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:583 +#: xs/src/libslic3r/PrintConfig.cpp:645 msgid "" "Heated build plate temperature for the first layer. Set this to zero to " "disable bed temperature control commands in the output." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:593 +#: xs/src/libslic3r/PrintConfig.cpp:655 msgid "" "Set this to a non-zero value to set a manual extrusion width for first " "layer. You can use this to force fatter extrudates for better adhesion. If " @@ -1629,11 +2444,11 @@ msgid "" "layer height. If set to zero, it will use the default extrusion width." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:603 +#: xs/src/libslic3r/PrintConfig.cpp:665 msgid "First layer height" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:605 +#: xs/src/libslic3r/PrintConfig.cpp:667 msgid "" "When printing with very low layer heights, you might still want to print a " "thicker bottom layer to improve adhesion and tolerance for non perfect build " @@ -1641,58 +2456,58 @@ msgid "" "example: 150%) over the default layer height." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:609 xs/src/libslic3r/PrintConfig.cpp:740 -#: xs/src/libslic3r/PrintConfig.cpp:1397 +#: xs/src/libslic3r/PrintConfig.cpp:671 xs/src/libslic3r/PrintConfig.cpp:802 +#: xs/src/libslic3r/PrintConfig.cpp:1497 msgid "mm or %" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:615 +#: xs/src/libslic3r/PrintConfig.cpp:677 msgid "First layer speed" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:616 +#: xs/src/libslic3r/PrintConfig.cpp:678 msgid "" "If expressed as absolute value in mm/s, this speed will be applied to all " "the print moves of the first layer, regardless of their type. If expressed " "as a percentage (for example: 40%) it will scale the default speeds." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:626 +#: xs/src/libslic3r/PrintConfig.cpp:688 msgid "" "Extruder temperature for first layer. If you want to control temperature " "manually during print, set this to zero to disable temperature control " "commands in the output file." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:634 -#: xs/src/libslic3r/GCode/PreviewData.cpp:145 -#: lib/Slic3r/GUI/Plater/3DPreview.pm:87 +#: xs/src/libslic3r/PrintConfig.cpp:696 +#: xs/src/libslic3r/GCode/PreviewData.cpp:165 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:90 msgid "Gap fill" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:636 +#: xs/src/libslic3r/PrintConfig.cpp:698 msgid "" "Speed for filling small gaps using short zigzag moves. Keep this reasonably " "low to avoid too much shaking and resonance issues. Set zero to disable gaps " "filling." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:644 +#: xs/src/libslic3r/PrintConfig.cpp:706 msgid "Verbose G-code" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:645 +#: xs/src/libslic3r/PrintConfig.cpp:707 msgid "" "Enable this to get a commented G-code file, with each line explained by a " "descriptive text. If you print from SD card, the additional weight of the " "file could make your firmware slow down." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:652 +#: xs/src/libslic3r/PrintConfig.cpp:714 msgid "G-code flavor" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:653 +#: xs/src/libslic3r/PrintConfig.cpp:715 msgid "" "Some G/M-code commands, including temperature control and others, are not " "universal. Set this option to your printer's firmware to get a compatible " @@ -1700,35 +2515,35 @@ msgid "" "extrusion value at all." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:682 +#: xs/src/libslic3r/PrintConfig.cpp:744 msgid "" "This is the acceleration your printer will use for infill. Set zero to " "disable acceleration control for infill." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:690 +#: xs/src/libslic3r/PrintConfig.cpp:752 msgid "Combine infill every" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:692 +#: xs/src/libslic3r/PrintConfig.cpp:754 msgid "" "This feature allows to combine infill and speed up your print by extruding " "thicker infill layers while preserving thin perimeters, thus accuracy." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:696 +#: xs/src/libslic3r/PrintConfig.cpp:758 msgid "Combine infill every n layers" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:701 +#: xs/src/libslic3r/PrintConfig.cpp:763 msgid "Infill extruder" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:703 +#: xs/src/libslic3r/PrintConfig.cpp:765 msgid "The extruder to use when printing infill." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:711 +#: xs/src/libslic3r/PrintConfig.cpp:773 msgid "" "Set this to a non-zero value to set a manual extrusion width for infill. If " "left zero, default extrusion width will be used if set, otherwise 1.125 x " @@ -1737,32 +2552,32 @@ msgid "" "example 90%) it will be computed over layer height." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:720 +#: xs/src/libslic3r/PrintConfig.cpp:782 msgid "Infill before perimeters" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:721 +#: xs/src/libslic3r/PrintConfig.cpp:783 msgid "" "This option will switch the print order of perimeters and infill, making the " "latter first." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:726 +#: xs/src/libslic3r/PrintConfig.cpp:788 msgid "Only infill where needed" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:728 +#: xs/src/libslic3r/PrintConfig.cpp:790 msgid "" "This option will limit infill to the areas actually needed for supporting " "ceilings (it will act as internal support material). If enabled, slows down " "the G-code generation due to the multiple checks involved." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:735 +#: xs/src/libslic3r/PrintConfig.cpp:797 msgid "Infill/perimeters overlap" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:737 +#: xs/src/libslic3r/PrintConfig.cpp:799 msgid "" "This setting applies an additional overlap between infill and perimeters for " "better bonding. Theoretically this shouldn't be needed, but backlash might " @@ -1770,22 +2585,30 @@ msgid "" "perimeter extrusion width." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:748 +#: xs/src/libslic3r/PrintConfig.cpp:810 msgid "Speed for printing the internal fill. Set to zero for auto." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:757 +#: xs/src/libslic3r/PrintConfig.cpp:819 +msgid "Inherits profile" +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:820 +msgid "Name of the profile, from which this profile inherits." +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:826 msgid "Interface shells" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:758 +#: xs/src/libslic3r/PrintConfig.cpp:827 msgid "" "Force the generation of solid shells between adjacent materials/volumes. " "Useful for multi-extruder prints with translucent materials or manual " "soluble support material." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:767 +#: xs/src/libslic3r/PrintConfig.cpp:836 msgid "" "This custom code is inserted at every layer change, right after the Z move " "and before the extruder moves to the first layer point. Note that you can " @@ -1793,22 +2616,22 @@ msgid "" "[layer_z]." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:779 +#: xs/src/libslic3r/PrintConfig.cpp:848 msgid "" "This setting controls the height (and thus the total number) of the slices/" "layers. Thinner layers give better accuracy but take more time to print." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:787 xs/src/libslic3r/PrintConfig.cpp:796 +#: xs/src/libslic3r/PrintConfig.cpp:856 xs/src/libslic3r/PrintConfig.cpp:865 msgid "Max" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:788 +#: xs/src/libslic3r/PrintConfig.cpp:857 msgid "This setting represents the maximum speed of your fan." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:797 -#, possible-c-format +#: xs/src/libslic3r/PrintConfig.cpp:866 +#, no-c-format msgid "" "This is the highest printable layer height for this extruder, used to cap " "the variable layer height and support layer height. Maximum recommended " @@ -1816,28 +2639,38 @@ msgid "" "adhesion. If set to 0, layer height is limited to 75% of the nozzle diameter." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:807 +#: xs/src/libslic3r/PrintConfig.cpp:876 +msgid "Max print height" +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:877 +msgid "" +"Set this to the maximum height that can be reached by your extruder while " +"printing." +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:883 msgid "Max print speed" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:808 +#: xs/src/libslic3r/PrintConfig.cpp:884 msgid "" "When setting other speed settings to 0 Slic3r will autocalculate the optimal " "speed in order to keep constant extruder pressure. This experimental setting " "is used to set the highest print speed you want to allow." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:818 +#: xs/src/libslic3r/PrintConfig.cpp:894 msgid "" "This experimental setting is used to set the maximum volumetric speed your " "extruder supports." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:826 +#: xs/src/libslic3r/PrintConfig.cpp:902 msgid "Max volumetric slope positive" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:827 xs/src/libslic3r/PrintConfig.cpp:838 +#: xs/src/libslic3r/PrintConfig.cpp:903 xs/src/libslic3r/PrintConfig.cpp:914 msgid "" "This experimental setting is used to limit the speed of change in extrusion " "rate. A value of 1.8 mm³/s² ensures, that a change from the extrusion rate " @@ -1845,109 +2678,109 @@ msgid "" "s) to 5.4 mm³/s (feedrate 60 mm/s) will take at least 2 seconds." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:831 xs/src/libslic3r/PrintConfig.cpp:842 +#: xs/src/libslic3r/PrintConfig.cpp:907 xs/src/libslic3r/PrintConfig.cpp:918 msgid "mm³/s²" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:837 +#: xs/src/libslic3r/PrintConfig.cpp:913 msgid "Max volumetric slope negative" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:848 xs/src/libslic3r/PrintConfig.cpp:857 +#: xs/src/libslic3r/PrintConfig.cpp:924 xs/src/libslic3r/PrintConfig.cpp:933 msgid "Min" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:849 +#: xs/src/libslic3r/PrintConfig.cpp:925 msgid "This setting represents the minimum PWM your fan needs to work." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:858 +#: xs/src/libslic3r/PrintConfig.cpp:934 msgid "" "This is the lowest printable layer height for this extruder and limits the " "resolution for variable layer height. Typical values are between 0.05 mm and " "0.1 mm." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:866 +#: xs/src/libslic3r/PrintConfig.cpp:942 msgid "Min print speed" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:867 +#: xs/src/libslic3r/PrintConfig.cpp:943 msgid "Slic3r will not scale speed down below this speed." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:874 +#: xs/src/libslic3r/PrintConfig.cpp:950 msgid "Minimum extrusion length" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:875 +#: xs/src/libslic3r/PrintConfig.cpp:951 msgid "" "Generate no less than the number of skirt loops required to consume the " "specified amount of filament on the bottom layer. For multi-extruder " "machines, this minimum applies to each extruder." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:884 +#: xs/src/libslic3r/PrintConfig.cpp:960 msgid "Configuration notes" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:885 +#: xs/src/libslic3r/PrintConfig.cpp:961 msgid "" "You can put here your personal notes. This text will be added to the G-code " "header comments." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:894 +#: xs/src/libslic3r/PrintConfig.cpp:970 msgid "Nozzle diameter" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:895 +#: xs/src/libslic3r/PrintConfig.cpp:971 msgid "" "This is the diameter of your extruder nozzle (for example: 0.5, 0.35 etc.)" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:901 +#: xs/src/libslic3r/PrintConfig.cpp:977 msgid "API Key" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:902 +#: xs/src/libslic3r/PrintConfig.cpp:978 msgid "" "Slic3r can upload G-code files to OctoPrint. This field should contain the " "API Key required for authentication." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:915 +#: xs/src/libslic3r/PrintConfig.cpp:991 msgid "Hostname, IP or URL" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:916 +#: xs/src/libslic3r/PrintConfig.cpp:992 msgid "" "Slic3r can upload G-code files to OctoPrint. This field should contain the " "hostname, IP address or URL of the OctoPrint instance." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:922 +#: xs/src/libslic3r/PrintConfig.cpp:998 msgid "Only retract when crossing perimeters" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:923 +#: xs/src/libslic3r/PrintConfig.cpp:999 msgid "" "Disables retraction when the travel path does not exceed the upper layer's " "perimeters (and thus any ooze will be probably invisible)." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:930 +#: xs/src/libslic3r/PrintConfig.cpp:1006 msgid "" "This option will drop the temperature of the inactive extruders to prevent " "oozing. It will enable a tall skirt automatically and move extruders outside " "such skirt when changing temperatures." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:937 +#: xs/src/libslic3r/PrintConfig.cpp:1013 msgid "Output filename format" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:938 +#: xs/src/libslic3r/PrintConfig.cpp:1014 msgid "" "You can use all configuration options as variables inside this template. For " "example: [layer_height], [fill_density] etc. You can also use [timestamp], " @@ -1955,38 +2788,48 @@ msgid "" "[input_filename], [input_filename_base]." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:947 +#: xs/src/libslic3r/PrintConfig.cpp:1023 msgid "Detect bridging perimeters" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:949 +#: xs/src/libslic3r/PrintConfig.cpp:1025 msgid "" "Experimental option to adjust flow for overhangs (bridge flow will be used), " "to apply bridge speed to them and enable fan." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:955 xs/src/libslic3r/PrintConfig.cpp:973 -#: xs/src/libslic3r/PrintConfig.cpp:985 xs/src/libslic3r/PrintConfig.cpp:995 +#: xs/src/libslic3r/PrintConfig.cpp:1031 +msgid "Filament parking position" +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:1032 +msgid "" +"Distance of the extruder tip from the position where the filament is parked " +"when unloaded. This should match the value in printer firmware. " +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:1040 xs/src/libslic3r/PrintConfig.cpp:1058 +#: xs/src/libslic3r/PrintConfig.cpp:1070 xs/src/libslic3r/PrintConfig.cpp:1080 msgid "Perimeters" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:956 +#: xs/src/libslic3r/PrintConfig.cpp:1041 msgid "" "This is the acceleration your printer will use for perimeters. A high value " "like 9000 usually gives good results if your hardware is up to the job. Set " "zero to disable acceleration control for perimeters." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:964 +#: xs/src/libslic3r/PrintConfig.cpp:1049 msgid "Perimeter extruder" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:966 +#: xs/src/libslic3r/PrintConfig.cpp:1051 msgid "" "The extruder to use when printing perimeters and brim. First extruder is 1." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:975 +#: xs/src/libslic3r/PrintConfig.cpp:1060 msgid "" "Set this to a non-zero value to set a manual extrusion width for perimeters. " "You may want to use thinner extrudates to get more accurate surfaces. If " @@ -1995,12 +2838,12 @@ msgid "" "it will be computed over layer height." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:987 +#: xs/src/libslic3r/PrintConfig.cpp:1072 msgid "" "Speed for perimeters (contours, aka vertical shells). Set to zero for auto." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:997 +#: xs/src/libslic3r/PrintConfig.cpp:1082 msgid "" "This option sets the number of perimeters to generate for each layer. Note " "that Slic3r may increase this number automatically when it detects sloping " @@ -2008,33 +2851,59 @@ msgid "" "Perimeters option is enabled." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1001 +#: xs/src/libslic3r/PrintConfig.cpp:1086 msgid "(minimum)" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1021 +#: xs/src/libslic3r/PrintConfig.cpp:1106 +msgid "Printer type" +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:1107 +msgid "Type of the printer." +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:1111 msgid "Printer notes" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1022 +#: xs/src/libslic3r/PrintConfig.cpp:1112 msgid "You can put your notes regarding the printer here." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1036 +#: xs/src/libslic3r/PrintConfig.cpp:1120 +msgid "Printer vendor" +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:1121 +msgid "Name of the printer vendor." +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:1125 +msgid "Printer variant" +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:1126 +msgid "" +"Name of the printer variant. For example, the printer variants may be " +"differentiated by a nozzle diameter." +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:1136 msgid "Raft layers" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1038 +#: xs/src/libslic3r/PrintConfig.cpp:1138 msgid "" "The object will be raised by this number of layers, and support material " "will be generated under it." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1046 +#: xs/src/libslic3r/PrintConfig.cpp:1146 msgid "Resolution" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1047 +#: xs/src/libslic3r/PrintConfig.cpp:1147 msgid "" "Minimum detail resolution, used to simplify the input file for speeding up " "the slicing job and reducing memory usage. High-resolution models often " @@ -2042,266 +2911,266 @@ msgid "" "simplification and use full resolution from input." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1057 +#: xs/src/libslic3r/PrintConfig.cpp:1157 msgid "Minimum travel after retraction" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1058 +#: xs/src/libslic3r/PrintConfig.cpp:1158 msgid "" "Retraction is not triggered when travel moves are shorter than this length." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1064 +#: xs/src/libslic3r/PrintConfig.cpp:1164 msgid "Retract amount before wipe" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1065 +#: xs/src/libslic3r/PrintConfig.cpp:1165 msgid "" "With bowden extruders, it may be wise to do some amount of quick retract " "before doing the wipe movement." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1072 +#: xs/src/libslic3r/PrintConfig.cpp:1172 msgid "Retract on layer change" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1073 +#: xs/src/libslic3r/PrintConfig.cpp:1173 msgid "This flag enforces a retraction whenever a Z move is done." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1078 xs/src/libslic3r/PrintConfig.cpp:1087 +#: xs/src/libslic3r/PrintConfig.cpp:1178 xs/src/libslic3r/PrintConfig.cpp:1187 msgid "Length" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1079 +#: xs/src/libslic3r/PrintConfig.cpp:1179 msgid "Retraction Length" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1080 +#: xs/src/libslic3r/PrintConfig.cpp:1180 msgid "" "When retraction is triggered, filament is pulled back by the specified " "amount (the length is measured on raw filament, before it enters the " "extruder)." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1082 xs/src/libslic3r/PrintConfig.cpp:1092 +#: xs/src/libslic3r/PrintConfig.cpp:1182 xs/src/libslic3r/PrintConfig.cpp:1192 msgid "mm (zero to disable)" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1088 +#: xs/src/libslic3r/PrintConfig.cpp:1188 msgid "Retraction Length (Toolchange)" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1089 +#: xs/src/libslic3r/PrintConfig.cpp:1189 msgid "" "When retraction is triggered before changing tool, filament is pulled back " "by the specified amount (the length is measured on raw filament, before it " "enters the extruder)." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1097 +#: xs/src/libslic3r/PrintConfig.cpp:1197 msgid "Lift Z" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1098 +#: xs/src/libslic3r/PrintConfig.cpp:1198 msgid "" "If you set this to a positive value, Z is quickly raised every time a " "retraction is triggered. When using multiple extruders, only the setting for " "the first extruder will be considered." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1106 +#: xs/src/libslic3r/PrintConfig.cpp:1206 msgid "Above Z" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1107 +#: xs/src/libslic3r/PrintConfig.cpp:1207 msgid "Only lift Z above" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1108 +#: xs/src/libslic3r/PrintConfig.cpp:1208 msgid "" "If you set this to a positive value, Z lift will only take place above the " "specified absolute Z. You can tune this setting for skipping lift on the " "first layers." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1115 +#: xs/src/libslic3r/PrintConfig.cpp:1215 msgid "Below Z" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1116 +#: xs/src/libslic3r/PrintConfig.cpp:1216 msgid "Only lift Z below" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1117 +#: xs/src/libslic3r/PrintConfig.cpp:1217 msgid "" "If you set this to a positive value, Z lift will only take place below the " "specified absolute Z. You can tune this setting for limiting lift to the " "first layers." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1125 xs/src/libslic3r/PrintConfig.cpp:1133 +#: xs/src/libslic3r/PrintConfig.cpp:1225 xs/src/libslic3r/PrintConfig.cpp:1233 msgid "Extra length on restart" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1126 +#: xs/src/libslic3r/PrintConfig.cpp:1226 msgid "" "When the retraction is compensated after the travel move, the extruder will " "push this additional amount of filament. This setting is rarely needed." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1134 +#: xs/src/libslic3r/PrintConfig.cpp:1234 msgid "" "When the retraction is compensated after changing tool, the extruder will " "push this additional amount of filament." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1141 xs/src/libslic3r/PrintConfig.cpp:1142 +#: xs/src/libslic3r/PrintConfig.cpp:1241 xs/src/libslic3r/PrintConfig.cpp:1242 msgid "Retraction Speed" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1143 +#: xs/src/libslic3r/PrintConfig.cpp:1243 msgid "The speed for retractions (it only applies to the extruder motor)." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1149 xs/src/libslic3r/PrintConfig.cpp:1150 +#: xs/src/libslic3r/PrintConfig.cpp:1249 xs/src/libslic3r/PrintConfig.cpp:1250 msgid "Deretraction Speed" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1151 +#: xs/src/libslic3r/PrintConfig.cpp:1251 msgid "" "The speed for loading of a filament into extruder after retraction (it only " "applies to the extruder motor). If left to zero, the retraction speed is " "used." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1158 +#: xs/src/libslic3r/PrintConfig.cpp:1258 msgid "Seam position" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1160 +#: xs/src/libslic3r/PrintConfig.cpp:1260 msgid "Position of perimeters starting points." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1176 +#: xs/src/libslic3r/PrintConfig.cpp:1276 msgid "Direction" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1178 +#: xs/src/libslic3r/PrintConfig.cpp:1278 msgid "Preferred direction of the seam" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1179 +#: xs/src/libslic3r/PrintConfig.cpp:1279 msgid "Seam preferred direction" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1187 +#: xs/src/libslic3r/PrintConfig.cpp:1287 msgid "Jitter" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1189 +#: xs/src/libslic3r/PrintConfig.cpp:1289 msgid "Seam preferred direction jitter" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1190 +#: xs/src/libslic3r/PrintConfig.cpp:1290 msgid "Preferred direction of the seam - jitter" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1201 +#: xs/src/libslic3r/PrintConfig.cpp:1301 msgid "USB/serial port for printer connection." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1209 +#: xs/src/libslic3r/PrintConfig.cpp:1309 msgid "Serial port speed" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1210 +#: xs/src/libslic3r/PrintConfig.cpp:1310 msgid "Speed (baud) of USB/serial port for printer connection." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1219 +#: xs/src/libslic3r/PrintConfig.cpp:1319 msgid "Distance from object" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1220 +#: xs/src/libslic3r/PrintConfig.cpp:1320 msgid "" "Distance between skirt and object(s). Set this to zero to attach the skirt " "to the object(s) and get a brim for better adhesion." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1228 +#: xs/src/libslic3r/PrintConfig.cpp:1328 msgid "Skirt height" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1229 +#: xs/src/libslic3r/PrintConfig.cpp:1329 msgid "" "Height of skirt expressed in layers. Set this to a tall value to use skirt " "as a shield against drafts." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1236 +#: xs/src/libslic3r/PrintConfig.cpp:1336 msgid "Loops (minimum)" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1237 +#: xs/src/libslic3r/PrintConfig.cpp:1337 msgid "Skirt Loops" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1238 +#: xs/src/libslic3r/PrintConfig.cpp:1338 msgid "" "Number of loops for the skirt. If the Minimum Extrusion Length option is " "set, the number of loops might be greater than the one configured here. Set " "this to zero to disable skirt completely." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1246 +#: xs/src/libslic3r/PrintConfig.cpp:1346 msgid "Slow down if layer print time is below" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1247 +#: xs/src/libslic3r/PrintConfig.cpp:1347 msgid "" "If layer print time is estimated below this number of seconds, print moves " "speed will be scaled down to extend duration to this value." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1257 +#: xs/src/libslic3r/PrintConfig.cpp:1357 msgid "Small perimeters" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1259 +#: xs/src/libslic3r/PrintConfig.cpp:1359 msgid "" "This separate setting will affect the speed of perimeters having radius <= " "6.5mm (usually holes). If expressed as percentage (for example: 80%) it will " "be calculated on the perimeters speed setting above. Set to zero for auto." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1269 +#: xs/src/libslic3r/PrintConfig.cpp:1369 msgid "Solid infill threshold area" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1271 +#: xs/src/libslic3r/PrintConfig.cpp:1371 msgid "" "Force solid infill for regions having a smaller area than the specified " "threshold." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1272 +#: xs/src/libslic3r/PrintConfig.cpp:1372 msgid "mm²" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1278 +#: xs/src/libslic3r/PrintConfig.cpp:1378 msgid "Solid infill extruder" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1280 +#: xs/src/libslic3r/PrintConfig.cpp:1380 msgid "The extruder to use when printing solid infill." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1286 +#: xs/src/libslic3r/PrintConfig.cpp:1386 msgid "Solid infill every" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1288 +#: xs/src/libslic3r/PrintConfig.cpp:1388 msgid "" "This feature allows to force a solid layer every given number of layers. " "Zero to disable. You can set this to any value (for example 9999); Slic3r " @@ -2309,13 +3178,13 @@ msgid "" "according to nozzle diameter and layer height." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1298 xs/src/libslic3r/PrintConfig.cpp:1308 -#: xs/src/libslic3r/GCode/PreviewData.cpp:142 -#: lib/Slic3r/GUI/Plater/3DPreview.pm:84 +#: xs/src/libslic3r/PrintConfig.cpp:1398 xs/src/libslic3r/PrintConfig.cpp:1408 +#: xs/src/libslic3r/GCode/PreviewData.cpp:162 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:87 msgid "Solid infill" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1300 +#: xs/src/libslic3r/PrintConfig.cpp:1400 msgid "" "Set this to a non-zero value to set a manual extrusion width for infill for " "solid surfaces. If left zero, default extrusion width will be used if set, " @@ -2323,22 +3192,22 @@ msgid "" "(for example 90%) it will be computed over layer height." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1310 +#: xs/src/libslic3r/PrintConfig.cpp:1410 msgid "" "Speed for printing solid regions (top/bottom/internal horizontal shells). " "This can be expressed as a percentage (for example: 80%) over the default " "infill speed above. Set to zero for auto." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1322 +#: xs/src/libslic3r/PrintConfig.cpp:1422 msgid "Number of solid layers to generate on top and bottom surfaces." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1329 +#: xs/src/libslic3r/PrintConfig.cpp:1429 msgid "Spiral vase" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1330 +#: xs/src/libslic3r/PrintConfig.cpp:1430 msgid "" "This feature will raise Z gradually while printing a single-walled object in " "order to remove any visible seam. This option requires a single perimeter, " @@ -2347,18 +3216,18 @@ msgid "" "when printing more than an object." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1339 +#: xs/src/libslic3r/PrintConfig.cpp:1439 msgid "Temperature variation" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1340 +#: xs/src/libslic3r/PrintConfig.cpp:1440 msgid "" "Temperature difference to be applied when an extruder is not active. Enables " "a full-height \"sacrificial\" skirt on which the nozzles are periodically " "wiped." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1350 +#: xs/src/libslic3r/PrintConfig.cpp:1450 msgid "" "This start procedure is inserted at the beginning, after bed has reached the " "target temperature and extruder just started heating, and before extruder " @@ -2369,76 +3238,76 @@ msgid "" "\"M109 S[first_layer_temperature]\" command wherever you want." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1365 +#: xs/src/libslic3r/PrintConfig.cpp:1465 msgid "" "This start procedure is inserted at the beginning, after any printer start " "gcode. This is used to override settings for a specific filament. If Slic3r " "detects M104, M109, M140 or M190 in your custom codes, such commands will " "not be prepended automatically so you're free to customize the order of " "heating commands and other custom actions. Note that you can use placeholder " -"variables for all Slic3r settings, so you can put a \"M109 " -"S[first_layer_temperature]\" command wherever you want. If you have multiple " +"variables for all Slic3r settings, so you can put a \"M109 S" +"[first_layer_temperature]\" command wherever you want. If you have multiple " "extruders, the gcode is processed in extruder order." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1380 +#: xs/src/libslic3r/PrintConfig.cpp:1480 msgid "Single Extruder Multi Material" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1381 +#: xs/src/libslic3r/PrintConfig.cpp:1481 msgid "The printer multiplexes filaments into a single hot end." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1386 +#: xs/src/libslic3r/PrintConfig.cpp:1486 msgid "Generate support material" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1388 +#: xs/src/libslic3r/PrintConfig.cpp:1488 msgid "Enable support material generation." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1393 +#: xs/src/libslic3r/PrintConfig.cpp:1493 msgid "XY separation between an object and its support" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1395 +#: xs/src/libslic3r/PrintConfig.cpp:1495 msgid "" "XY separation between an object and its support. If expressed as percentage " "(for example 50%), it will be calculated over external perimeter width." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1405 +#: xs/src/libslic3r/PrintConfig.cpp:1505 msgid "Pattern angle" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1407 +#: xs/src/libslic3r/PrintConfig.cpp:1507 msgid "" "Use this setting to rotate the support material pattern on the horizontal " "plane." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1417 +#: xs/src/libslic3r/PrintConfig.cpp:1517 msgid "" "Only create support if it lies on a build plate. Don't create support on a " "print." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1423 +#: xs/src/libslic3r/PrintConfig.cpp:1523 msgid "Contact Z distance" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1425 +#: xs/src/libslic3r/PrintConfig.cpp:1525 msgid "" "The vertical distance between object and support material interface. Setting " "this to 0 will also prevent Slic3r from using bridge flow and speed for the " "first object layer." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1438 +#: xs/src/libslic3r/PrintConfig.cpp:1538 msgid "Enforce support for the first" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1440 +#: xs/src/libslic3r/PrintConfig.cpp:1540 msgid "" "Generate support material for the specified number of layers counting from " "bottom, regardless of whether normal support material is enabled or not and " @@ -2446,21 +3315,21 @@ msgid "" "of objects having a very thin or poor footprint on the build plate." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1446 +#: xs/src/libslic3r/PrintConfig.cpp:1546 msgid "Enforce support for the first n layers" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1451 +#: xs/src/libslic3r/PrintConfig.cpp:1551 msgid "Support material/raft/skirt extruder" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1453 +#: xs/src/libslic3r/PrintConfig.cpp:1553 msgid "" "The extruder to use when printing support material, raft and skirt (1+, 0 to " "use the current extruder to minimize tool changes)." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1462 +#: xs/src/libslic3r/PrintConfig.cpp:1562 msgid "" "Set this to a non-zero value to set a manual extrusion width for support " "material. If left zero, default extrusion width will be used if set, " @@ -2468,91 +3337,91 @@ msgid "" "example 90%) it will be computed over layer height." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1470 +#: xs/src/libslic3r/PrintConfig.cpp:1570 msgid "Interface loops" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1472 +#: xs/src/libslic3r/PrintConfig.cpp:1572 msgid "" "Cover the top contact layer of the supports with loops. Disabled by default." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1477 +#: xs/src/libslic3r/PrintConfig.cpp:1577 msgid "Support material/raft interface extruder" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1479 +#: xs/src/libslic3r/PrintConfig.cpp:1579 msgid "" "The extruder to use when printing support material interface (1+, 0 to use " "the current extruder to minimize tool changes). This affects raft too." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1486 +#: xs/src/libslic3r/PrintConfig.cpp:1586 msgid "Interface layers" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1488 +#: xs/src/libslic3r/PrintConfig.cpp:1588 msgid "" "Number of interface layers to insert between the object(s) and support " "material." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1495 +#: xs/src/libslic3r/PrintConfig.cpp:1595 msgid "Interface pattern spacing" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1497 +#: xs/src/libslic3r/PrintConfig.cpp:1597 msgid "Spacing between interface lines. Set zero to get a solid interface." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1504 -#: xs/src/libslic3r/GCode/PreviewData.cpp:148 -#: lib/Slic3r/GUI/Plater/3DPreview.pm:90 +#: xs/src/libslic3r/PrintConfig.cpp:1604 +#: xs/src/libslic3r/GCode/PreviewData.cpp:168 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:93 msgid "Support material interface" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1506 +#: xs/src/libslic3r/PrintConfig.cpp:1606 msgid "" "Speed for printing support material interface layers. If expressed as " "percentage (for example 50%) it will be calculated over support material " "speed." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1515 +#: xs/src/libslic3r/PrintConfig.cpp:1615 msgid "Pattern" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1517 +#: xs/src/libslic3r/PrintConfig.cpp:1617 msgid "Pattern used to generate support material." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1531 +#: xs/src/libslic3r/PrintConfig.cpp:1629 msgid "Pattern spacing" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1533 +#: xs/src/libslic3r/PrintConfig.cpp:1631 msgid "Spacing between support material lines." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1542 +#: xs/src/libslic3r/PrintConfig.cpp:1640 msgid "Speed for printing support material." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1549 +#: xs/src/libslic3r/PrintConfig.cpp:1647 msgid "Synchronize with object layers" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1551 +#: xs/src/libslic3r/PrintConfig.cpp:1649 msgid "" "Synchronize support layers with the object print layers. This is useful with " "multi-material printers, where the extruder switch is expensive." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1557 +#: xs/src/libslic3r/PrintConfig.cpp:1655 msgid "Overhang threshold" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1559 +#: xs/src/libslic3r/PrintConfig.cpp:1657 msgid "" "Support material will not be generated for overhangs whose slope angle (90° " "= vertical) is above the given threshold. In other words, this value " @@ -2561,60 +3430,60 @@ msgid "" "detection (recommended)." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1571 +#: xs/src/libslic3r/PrintConfig.cpp:1669 msgid "With sheath around the support" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1573 +#: xs/src/libslic3r/PrintConfig.cpp:1671 msgid "" "Add a sheath (a single perimeter line) around the base support. This makes " "the support more reliable, but also more difficult to remove." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1580 +#: xs/src/libslic3r/PrintConfig.cpp:1678 msgid "" "Extruder temperature for layers after the first one. Set this to zero to " "disable temperature control commands in the output." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1583 +#: xs/src/libslic3r/PrintConfig.cpp:1681 msgid "Temperature" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1589 +#: xs/src/libslic3r/PrintConfig.cpp:1687 msgid "Detect thin walls" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1591 +#: xs/src/libslic3r/PrintConfig.cpp:1689 msgid "" "Detect single-width walls (parts where two extrusions don't fit and we need " "to collapse them into a single trace)." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1597 +#: xs/src/libslic3r/PrintConfig.cpp:1695 msgid "Threads" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1598 +#: xs/src/libslic3r/PrintConfig.cpp:1696 msgid "" "Threads are used to parallelize long-running tasks. Optimal threads number " "is slightly above the number of available cores/processors." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1610 +#: xs/src/libslic3r/PrintConfig.cpp:1708 msgid "" "This custom code is inserted right before every extruder change. Note that " "you can use placeholder variables for all Slic3r settings as well as " "[previous_extruder] and [next_extruder]." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1620 xs/src/libslic3r/PrintConfig.cpp:1631 -#: xs/src/libslic3r/GCode/PreviewData.cpp:143 -#: lib/Slic3r/GUI/Plater/3DPreview.pm:85 +#: xs/src/libslic3r/PrintConfig.cpp:1718 xs/src/libslic3r/PrintConfig.cpp:1729 +#: xs/src/libslic3r/GCode/PreviewData.cpp:163 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:88 msgid "Top solid infill" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1622 +#: xs/src/libslic3r/PrintConfig.cpp:1720 msgid "" "Set this to a non-zero value to set a manual extrusion width for infill for " "top surfaces. You may want to use thinner extrudates to fill all narrow " @@ -2623,7 +3492,7 @@ msgid "" "percentage (for example 90%) it will be computed over layer height." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1633 +#: xs/src/libslic3r/PrintConfig.cpp:1731 msgid "" "Speed for printing top solid layers (it only applies to the uppermost " "external layers and not to their internal solid layers). You may want to " @@ -2632,51 +3501,51 @@ msgid "" "for auto." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1645 lib/Slic3r/GUI/MainFrame.pm:363 +#: xs/src/libslic3r/PrintConfig.cpp:1743 lib/Slic3r/GUI/MainFrame.pm:306 msgid "Top" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1647 +#: xs/src/libslic3r/PrintConfig.cpp:1745 msgid "Number of solid layers to generate on top surfaces." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1649 +#: xs/src/libslic3r/PrintConfig.cpp:1747 msgid "Top solid layers" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1654 lib/Slic3r/GUI/Plater/3DPreview.pm:95 +#: xs/src/libslic3r/PrintConfig.cpp:1752 lib/Slic3r/GUI/Plater/3DPreview.pm:98 msgid "Travel" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1655 +#: xs/src/libslic3r/PrintConfig.cpp:1753 msgid "Speed for travel moves (jumps between distant extrusion points)." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1663 +#: xs/src/libslic3r/PrintConfig.cpp:1761 msgid "Use firmware retraction" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1664 +#: xs/src/libslic3r/PrintConfig.cpp:1762 msgid "" "This experimental setting uses G10 and G11 commands to have the firmware " "handle the retraction. This is only supported in recent Marlin." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1670 +#: xs/src/libslic3r/PrintConfig.cpp:1768 msgid "Use relative E distances" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1671 +#: xs/src/libslic3r/PrintConfig.cpp:1769 msgid "" "If your firmware requires relative E values, check this, otherwise leave it " "unchecked. Most firmwares use absolute values." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1677 +#: xs/src/libslic3r/PrintConfig.cpp:1775 msgid "Use volumetric E" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1678 +#: xs/src/libslic3r/PrintConfig.cpp:1776 msgid "" "This experimental setting uses outputs the E values in cubic millimeters " "instead of linear millimeters. If your firmware doesn't already know " @@ -2686,83 +3555,113 @@ msgid "" "only supported in recent Marlin." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1688 +#: xs/src/libslic3r/PrintConfig.cpp:1786 msgid "Enable variable layer height feature" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1689 +#: xs/src/libslic3r/PrintConfig.cpp:1787 msgid "" "Some printers or printer setups may have difficulties printing with a " "variable layer height. Enabled by default." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1695 +#: xs/src/libslic3r/PrintConfig.cpp:1793 msgid "Wipe while retracting" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1696 +#: xs/src/libslic3r/PrintConfig.cpp:1794 msgid "" "This flag will move the nozzle while retracting to minimize the possible " "blob on leaky extruders." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1703 +#: xs/src/libslic3r/PrintConfig.cpp:1801 msgid "" "Multi material printers may need to prime or purge extruders on tool " "changes. Extrude the excess material into the wipe tower." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1709 +#: xs/src/libslic3r/PrintConfig.cpp:1807 +msgid "Purging volumes - load/unload volumes" +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:1808 +msgid "" +"This vector saves required volumes to change from/to each tool used on the " +"wipe tower. These values are used to simplify creation of the full purging " +"volumes below. " +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:1815 +msgid "Purging volumes - matrix" +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:1816 +msgid "" +"This matrix describes volumes (in cubic milimetres) required to purge the " +"new filament on the wipe tower for any given pair of tools. " +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:1826 msgid "Position X" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1710 +#: xs/src/libslic3r/PrintConfig.cpp:1827 msgid "X coordinate of the left front corner of a wipe tower" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1716 +#: xs/src/libslic3r/PrintConfig.cpp:1833 msgid "Position Y" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1717 +#: xs/src/libslic3r/PrintConfig.cpp:1834 msgid "Y coordinate of the left front corner of a wipe tower" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1723 lib/Slic3r/GUI/Plater/3DPreview.pm:70 +#: xs/src/libslic3r/PrintConfig.cpp:1840 lib/Slic3r/GUI/Plater/3DPreview.pm:69 msgid "Width" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1724 +#: xs/src/libslic3r/PrintConfig.cpp:1841 msgid "Width of a wipe tower" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1730 -msgid "Per color change depth" +#: xs/src/libslic3r/PrintConfig.cpp:1847 +msgid "Wipe tower rotation angle" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1731 -msgid "" -"Depth of a wipe color per color change. For N colors, there will be maximum " -"(N-1) tool switches performed, therefore the total depth of the wipe tower " -"will be (N-1) times this value." +#: xs/src/libslic3r/PrintConfig.cpp:1848 +msgid "Wipe tower rotation angle with respect to x-axis " msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1739 +#: xs/src/libslic3r/PrintConfig.cpp:1849 +msgid "degrees" +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:1854 +msgid "Maximal bridging distance" +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:1855 +msgid "Maximal distance between supports on sparse infill sections. " +msgstr "" + +#: xs/src/libslic3r/PrintConfig.cpp:1861 msgid "XY Size Compensation" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1741 +#: xs/src/libslic3r/PrintConfig.cpp:1863 msgid "" "The object will be grown/shrunk in the XY plane by the configured value " "(negative = inwards, positive = outwards). This might be useful for fine-" "tuning hole sizes." msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1749 +#: xs/src/libslic3r/PrintConfig.cpp:1871 msgid "Z offset" msgstr "" -#: xs/src/libslic3r/PrintConfig.cpp:1750 +#: xs/src/libslic3r/PrintConfig.cpp:1872 msgid "" "This value will be added (or subtracted) from all the Z coordinates in the " "output G-code. It is used to compensate for bad Z endstop position: for " @@ -2770,980 +3669,946 @@ msgid "" "print bed, set this to -0.3 (or fix your endstop)." msgstr "" -#: xs/src/libslic3r/GCode/PreviewData.cpp:138 -#: lib/Slic3r/GUI/Plater/3DPreview.pm:80 +#: xs/src/libslic3r/GCode/PreviewData.cpp:158 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:83 msgid "Perimeter" msgstr "" -#: xs/src/libslic3r/GCode/PreviewData.cpp:139 -#: lib/Slic3r/GUI/Plater/3DPreview.pm:81 +#: xs/src/libslic3r/GCode/PreviewData.cpp:159 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:84 msgid "External perimeter" msgstr "" -#: xs/src/libslic3r/GCode/PreviewData.cpp:140 -#: lib/Slic3r/GUI/Plater/3DPreview.pm:82 +#: xs/src/libslic3r/GCode/PreviewData.cpp:160 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:85 msgid "Overhang perimeter" msgstr "" -#: xs/src/libslic3r/GCode/PreviewData.cpp:141 -#: lib/Slic3r/GUI/Plater/3DPreview.pm:83 +#: xs/src/libslic3r/GCode/PreviewData.cpp:161 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:86 msgid "Internal infill" msgstr "" -#: xs/src/libslic3r/GCode/PreviewData.cpp:144 -#: lib/Slic3r/GUI/Plater/3DPreview.pm:86 +#: xs/src/libslic3r/GCode/PreviewData.cpp:164 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:89 msgid "Bridge infill" msgstr "" -#: xs/src/libslic3r/GCode/PreviewData.cpp:151 +#: xs/src/libslic3r/GCode/PreviewData.cpp:171 msgid "Mixed" msgstr "" -#: xs/src/libslic3r/GCode/PreviewData.cpp:330 -#: lib/Slic3r/GUI/Plater/3DPreview.pm:68 +#: xs/src/libslic3r/GCode/PreviewData.cpp:362 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:67 msgid "Feature type" msgstr "" -#: xs/src/libslic3r/GCode/PreviewData.cpp:332 +#: xs/src/libslic3r/GCode/PreviewData.cpp:364 msgid "Height (mm)" msgstr "" -#: xs/src/libslic3r/GCode/PreviewData.cpp:334 +#: xs/src/libslic3r/GCode/PreviewData.cpp:366 msgid "Width (mm)" msgstr "" -#: xs/src/libslic3r/GCode/PreviewData.cpp:336 +#: xs/src/libslic3r/GCode/PreviewData.cpp:368 msgid "Speed (mm/s)" msgstr "" -#: xs/src/libslic3r/GCode/PreviewData.cpp:338 +#: xs/src/libslic3r/GCode/PreviewData.cpp:370 +msgid "Volumetric flow rate (mm3/s)" +msgstr "" + +#: xs/src/libslic3r/GCode/PreviewData.cpp:372 #: lib/Slic3r/GUI/Plater/3DPreview.pm:72 msgid "Tool" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:66 +#: lib/Slic3r/GUI.pm:303 +msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):" +msgstr "" + +#: lib/Slic3r/GUI/MainFrame.pm:62 msgid "Version " msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:66 +#: lib/Slic3r/GUI/MainFrame.pm:62 msgid "" " - Remember to check for updates at http://github.com/prusa3d/slic3r/releases" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:118 +#: lib/Slic3r/GUI/MainFrame.pm:114 msgid "Plater" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:120 +#: lib/Slic3r/GUI/MainFrame.pm:116 msgid "Controller" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:191 -msgid "No Bonjour device found" -msgstr "" - -#: lib/Slic3r/GUI/MainFrame.pm:191 -msgid "Device Browser" -msgstr "" - -#: lib/Slic3r/GUI/MainFrame.pm:212 -msgid "I wasn't able to connect to OctoPrint (" -msgstr "" - -#: lib/Slic3r/GUI/MainFrame.pm:213 -msgid "). Check hostname and OctoPrint version (at least 1.1.0 is required)." -msgstr "" - -#: lib/Slic3r/GUI/MainFrame.pm:245 +#: lib/Slic3r/GUI/MainFrame.pm:194 msgid "Open STL/OBJ/AMF…\tCtrl+O" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:245 +#: lib/Slic3r/GUI/MainFrame.pm:194 msgid "Open a model" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:248 +#: lib/Slic3r/GUI/MainFrame.pm:197 msgid "&Load Config…\tCtrl+L" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:248 +#: lib/Slic3r/GUI/MainFrame.pm:197 msgid "Load exported configuration file" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:251 +#: lib/Slic3r/GUI/MainFrame.pm:200 msgid "&Export Config…\tCtrl+E" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:251 +#: lib/Slic3r/GUI/MainFrame.pm:200 msgid "Export current configuration to file" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:254 +#: lib/Slic3r/GUI/MainFrame.pm:203 msgid "&Load Config Bundle…" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:254 +#: lib/Slic3r/GUI/MainFrame.pm:203 msgid "Load presets from a bundle" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:257 +#: lib/Slic3r/GUI/MainFrame.pm:206 msgid "&Export Config Bundle…" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:257 +#: lib/Slic3r/GUI/MainFrame.pm:206 msgid "Export all presets to file" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:262 +#: lib/Slic3r/GUI/MainFrame.pm:211 msgid "Q&uick Slice…\tCtrl+U" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:262 +#: lib/Slic3r/GUI/MainFrame.pm:211 msgid "Slice a file into a G-code" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:268 +#: lib/Slic3r/GUI/MainFrame.pm:217 msgid "Quick Slice and Save &As…\tCtrl+Alt+U" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:268 +#: lib/Slic3r/GUI/MainFrame.pm:217 msgid "Slice a file into a G-code, save as" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:274 +#: lib/Slic3r/GUI/MainFrame.pm:223 msgid "&Repeat Last Quick Slice\tCtrl+Shift+U" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:274 +#: lib/Slic3r/GUI/MainFrame.pm:223 msgid "Repeat last quick slice" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:281 +#: lib/Slic3r/GUI/MainFrame.pm:230 msgid "Slice to SV&G…\tCtrl+G" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:281 +#: lib/Slic3r/GUI/MainFrame.pm:230 msgid "Slice file to a multi-layer SVG" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:285 +#: lib/Slic3r/GUI/MainFrame.pm:234 msgid "(&Re)Slice Now\tCtrl+S" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:285 +#: lib/Slic3r/GUI/MainFrame.pm:234 msgid "Start new slicing process" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:288 +#: lib/Slic3r/GUI/MainFrame.pm:237 msgid "Repair STL file…" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:288 +#: lib/Slic3r/GUI/MainFrame.pm:237 msgid "Automatically repair an STL file" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:293 -msgid "Preferences…\tCtrl+," -msgstr "" - -#: lib/Slic3r/GUI/MainFrame.pm:293 -msgid "Application preferences" -msgstr "" - -#: lib/Slic3r/GUI/MainFrame.pm:298 +#: lib/Slic3r/GUI/MainFrame.pm:241 msgid "&Quit" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:298 +#: lib/Slic3r/GUI/MainFrame.pm:241 msgid "Quit Slic3r" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:308 +#: lib/Slic3r/GUI/MainFrame.pm:251 msgid "Export G-code..." msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:308 +#: lib/Slic3r/GUI/MainFrame.pm:251 msgid "Export current plate as G-code" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:311 +#: lib/Slic3r/GUI/MainFrame.pm:254 msgid "Export plate as STL..." msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:311 +#: lib/Slic3r/GUI/MainFrame.pm:254 msgid "Export current plate as STL" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:314 +#: lib/Slic3r/GUI/MainFrame.pm:257 msgid "Export plate as AMF..." msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:314 +#: lib/Slic3r/GUI/MainFrame.pm:257 msgid "Export current plate as AMF" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:317 +#: lib/Slic3r/GUI/MainFrame.pm:260 msgid "Export plate as 3MF..." msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:317 +#: lib/Slic3r/GUI/MainFrame.pm:260 msgid "Export current plate as 3MF" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:330 +#: lib/Slic3r/GUI/MainFrame.pm:273 msgid "Select &Plater Tab\tCtrl+1" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:330 +#: lib/Slic3r/GUI/MainFrame.pm:273 msgid "Show the plater" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:336 +#: lib/Slic3r/GUI/MainFrame.pm:279 msgid "Select &Controller Tab\tCtrl+T" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:336 +#: lib/Slic3r/GUI/MainFrame.pm:279 msgid "Show the printer controller" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:344 +#: lib/Slic3r/GUI/MainFrame.pm:287 msgid "Select P&rint Settings Tab\tCtrl+2" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:344 +#: lib/Slic3r/GUI/MainFrame.pm:287 msgid "Show the print settings" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:347 +#: lib/Slic3r/GUI/MainFrame.pm:290 msgid "Select &Filament Settings Tab\tCtrl+3" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:347 +#: lib/Slic3r/GUI/MainFrame.pm:290 msgid "Show the filament settings" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:350 +#: lib/Slic3r/GUI/MainFrame.pm:293 msgid "Select Print&er Settings Tab\tCtrl+4" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:350 +#: lib/Slic3r/GUI/MainFrame.pm:293 msgid "Show the printer settings" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:362 +#: lib/Slic3r/GUI/MainFrame.pm:305 msgid "Iso" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:362 +#: lib/Slic3r/GUI/MainFrame.pm:305 msgid "Iso View" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:363 +#: lib/Slic3r/GUI/MainFrame.pm:306 msgid "Top View" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:364 +#: lib/Slic3r/GUI/MainFrame.pm:307 msgid "Bottom View" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:365 +#: lib/Slic3r/GUI/MainFrame.pm:308 msgid "Front" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:365 +#: lib/Slic3r/GUI/MainFrame.pm:308 msgid "Front View" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:366 +#: lib/Slic3r/GUI/MainFrame.pm:309 msgid "Rear" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:366 +#: lib/Slic3r/GUI/MainFrame.pm:309 msgid "Rear View" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:367 +#: lib/Slic3r/GUI/MainFrame.pm:310 msgid "Left" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:367 +#: lib/Slic3r/GUI/MainFrame.pm:310 msgid "Left View" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:368 +#: lib/Slic3r/GUI/MainFrame.pm:311 msgid "Right" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:368 +#: lib/Slic3r/GUI/MainFrame.pm:311 msgid "Right View" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:374 -msgid "&Configuration " -msgstr "" - -#: lib/Slic3r/GUI/MainFrame.pm:374 -msgid "Run Configuration " -msgstr "" - -#: lib/Slic3r/GUI/MainFrame.pm:379 +#: lib/Slic3r/GUI/MainFrame.pm:317 msgid "Prusa 3D Drivers" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:379 +#: lib/Slic3r/GUI/MainFrame.pm:317 msgid "Open the Prusa3D drivers download page in your browser" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:382 +#: lib/Slic3r/GUI/MainFrame.pm:320 msgid "Prusa Edition Releases" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:382 +#: lib/Slic3r/GUI/MainFrame.pm:320 msgid "Open the Prusa Edition releases page in your browser" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:389 +#: lib/Slic3r/GUI/MainFrame.pm:327 msgid "Slic3r &Website" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:389 +#: lib/Slic3r/GUI/MainFrame.pm:327 msgid "Open the Slic3r website in your browser" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:392 +#: lib/Slic3r/GUI/MainFrame.pm:330 msgid "Slic3r &Manual" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:392 +#: lib/Slic3r/GUI/MainFrame.pm:330 msgid "Open the Slic3r manual in your browser" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:396 +#: lib/Slic3r/GUI/MainFrame.pm:334 msgid "System Info" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:396 +#: lib/Slic3r/GUI/MainFrame.pm:334 msgid "Show system information" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:399 +#: lib/Slic3r/GUI/MainFrame.pm:337 msgid "Report an Issue" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:399 +#: lib/Slic3r/GUI/MainFrame.pm:337 msgid "Report an issue on the Slic3r Prusa Edition" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:402 +#: lib/Slic3r/GUI/MainFrame.pm:340 msgid "&About Slic3r" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:402 +#: lib/Slic3r/GUI/MainFrame.pm:340 msgid "Show about dialog" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:412 +#: lib/Slic3r/GUI/MainFrame.pm:350 msgid "&File" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:413 +#: lib/Slic3r/GUI/MainFrame.pm:351 msgid "&Plater" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:414 +#: lib/Slic3r/GUI/MainFrame.pm:352 msgid "&Object" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:415 +#: lib/Slic3r/GUI/MainFrame.pm:353 msgid "&Window" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:416 +#: lib/Slic3r/GUI/MainFrame.pm:354 msgid "&View" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:420 +#: lib/Slic3r/GUI/MainFrame.pm:357 msgid "&Help" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:452 +#: lib/Slic3r/GUI/MainFrame.pm:388 msgid "Choose a file to slice (STL/OBJ/AMF/3MF/PRUSA):" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:464 +#: lib/Slic3r/GUI/MainFrame.pm:400 msgid "No previously sliced file." msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:469 +#: lib/Slic3r/GUI/MainFrame.pm:401 lib/Slic3r/GUI/Plater.pm:1342 +msgid "Error" +msgstr "" + +#: lib/Slic3r/GUI/MainFrame.pm:405 msgid "Previously sliced file (" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:469 +#: lib/Slic3r/GUI/MainFrame.pm:405 msgid ") not found." msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:470 +#: lib/Slic3r/GUI/MainFrame.pm:406 msgid "File Not Found" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:509 +#: lib/Slic3r/GUI/MainFrame.pm:445 msgid "SVG" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:509 +#: lib/Slic3r/GUI/MainFrame.pm:445 msgid "G-code" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:509 lib/Slic3r/GUI/Plater.pm:1615 +#: lib/Slic3r/GUI/MainFrame.pm:445 lib/Slic3r/GUI/Plater.pm:1660 msgid " file as:" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:523 +#: lib/Slic3r/GUI/MainFrame.pm:459 msgid "Slicing…" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:523 +#: lib/Slic3r/GUI/MainFrame.pm:459 msgid "Processing " msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:543 +#: lib/Slic3r/GUI/MainFrame.pm:479 msgid " was successfully sliced." msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:545 +#: lib/Slic3r/GUI/MainFrame.pm:481 msgid "Slicing Done!" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:561 +#: lib/Slic3r/GUI/MainFrame.pm:497 msgid "Select the STL file to repair:" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:575 +#: lib/Slic3r/GUI/MainFrame.pm:511 msgid "Save OBJ file (less prone to coordinate errors than STL) as:" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:589 +#: lib/Slic3r/GUI/MainFrame.pm:525 msgid "Your file was repaired." msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:589 +#: lib/Slic3r/GUI/MainFrame.pm:525 msgid "Repair" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:600 +#: lib/Slic3r/GUI/MainFrame.pm:536 msgid "Save configuration as:" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:618 lib/Slic3r/GUI/MainFrame.pm:662 +#: lib/Slic3r/GUI/MainFrame.pm:554 lib/Slic3r/GUI/MainFrame.pm:598 msgid "Select configuration to load:" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:641 +#: lib/Slic3r/GUI/MainFrame.pm:577 msgid "Save presets bundle as:" msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:682 +#: lib/Slic3r/GUI/MainFrame.pm:618 #, possible-perl-format msgid "%d presets successfully imported." msgstr "" -#: lib/Slic3r/GUI/MainFrame.pm:744 -msgid "You have unsaved changes " -msgstr "" - -#: lib/Slic3r/GUI/MainFrame.pm:744 -msgid ". Discard changes and continue anyway?" -msgstr "" - -#: lib/Slic3r/GUI/MainFrame.pm:745 -msgid "Unsaved Presets" -msgstr "" - -#: lib/Slic3r/GUI/Plater.pm:104 lib/Slic3r/GUI/Plater.pm:2094 +#: lib/Slic3r/GUI/Plater.pm:112 lib/Slic3r/GUI/Plater.pm:2153 msgid "3D" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:138 +#: lib/Slic3r/GUI/Plater.pm:148 msgid "2D" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:157 +#: lib/Slic3r/GUI/Plater.pm:167 msgid "Layers" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:177 lib/Slic3r/GUI/Plater.pm:195 +#: lib/Slic3r/GUI/Plater.pm:187 lib/Slic3r/GUI/Plater.pm:205 msgid "Add…" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:179 lib/Slic3r/GUI/Plater.pm:197 +#: lib/Slic3r/GUI/Plater.pm:189 lib/Slic3r/GUI/Plater.pm:207 msgid "Delete All" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:180 lib/Slic3r/GUI/Plater.pm:198 +#: lib/Slic3r/GUI/Plater.pm:190 lib/Slic3r/GUI/Plater.pm:208 msgid "Arrange" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:182 +#: lib/Slic3r/GUI/Plater.pm:192 msgid "More" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:183 +#: lib/Slic3r/GUI/Plater.pm:193 msgid "Fewer" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:185 +#: lib/Slic3r/GUI/Plater.pm:195 msgid "45° ccw" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:186 +#: lib/Slic3r/GUI/Plater.pm:196 msgid "45° cw" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:187 lib/Slic3r/GUI/Plater.pm:203 +#: lib/Slic3r/GUI/Plater.pm:197 lib/Slic3r/GUI/Plater.pm:213 msgid "Scale…" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:188 lib/Slic3r/GUI/Plater.pm:204 -#: lib/Slic3r/GUI/Plater.pm:2069 +#: lib/Slic3r/GUI/Plater.pm:198 lib/Slic3r/GUI/Plater.pm:214 +#: lib/Slic3r/GUI/Plater.pm:2128 msgid "Split" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:189 lib/Slic3r/GUI/Plater.pm:205 -#: lib/Slic3r/GUI/Plater.pm:2072 +#: lib/Slic3r/GUI/Plater.pm:199 lib/Slic3r/GUI/Plater.pm:215 +#: lib/Slic3r/GUI/Plater.pm:2131 msgid "Cut…" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:191 lib/Slic3r/GUI/Plater.pm:206 -#: lib/Slic3r/GUI/Plater.pm:2076 +#: lib/Slic3r/GUI/Plater.pm:201 lib/Slic3r/GUI/Plater.pm:216 +#: lib/Slic3r/GUI/Plater.pm:2135 msgid "Settings…" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:192 +#: lib/Slic3r/GUI/Plater.pm:202 msgid "Layer Editing" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:207 +#: lib/Slic3r/GUI/Plater.pm:217 msgid "Layer editing" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:220 +#: lib/Slic3r/GUI/Plater.pm:230 msgid "Name" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:221 lib/Slic3r/GUI/Plater.pm:904 +#: lib/Slic3r/GUI/Plater.pm:231 lib/Slic3r/GUI/Plater.pm:942 msgid "Copies" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:222 lib/Slic3r/GUI/Plater.pm:1060 -#: lib/Slic3r/GUI/Plater.pm:1065 lib/Slic3r/GUI/Plater.pm:2038 +#: lib/Slic3r/GUI/Plater.pm:232 lib/Slic3r/GUI/Plater.pm:1098 +#: lib/Slic3r/GUI/Plater.pm:1103 lib/Slic3r/GUI/Plater.pm:2097 msgid "Scale" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:236 +#: lib/Slic3r/GUI/Plater.pm:246 msgid "Export G-code…" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:237 +#: lib/Slic3r/GUI/Plater.pm:247 msgid "Slice now" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:238 +#: lib/Slic3r/GUI/Plater.pm:248 msgid "Print…" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:239 +#: lib/Slic3r/GUI/Plater.pm:249 msgid "Send to printer" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:240 +#: lib/Slic3r/GUI/Plater.pm:250 msgid "Export STL…" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:367 +#: lib/Slic3r/GUI/Plater.pm:377 msgid "Print settings" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:369 +#: lib/Slic3r/GUI/Plater.pm:379 msgid "Printer" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:401 +#: lib/Slic3r/GUI/Plater.pm:411 msgid "Info" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:412 +#: lib/Slic3r/GUI/Plater.pm:422 msgid "Volume" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:413 +#: lib/Slic3r/GUI/Plater.pm:423 msgid "Facets" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:414 +#: lib/Slic3r/GUI/Plater.pm:424 msgid "Materials" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:415 +#: lib/Slic3r/GUI/Plater.pm:425 msgid "Manifold" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:441 +#: lib/Slic3r/GUI/Plater.pm:451 msgid "Sliced Info" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:450 +#: lib/Slic3r/GUI/Plater.pm:460 msgid "Used Filament (m)" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:451 +#: lib/Slic3r/GUI/Plater.pm:461 msgid "Used Filament (mm³)" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:452 +#: lib/Slic3r/GUI/Plater.pm:462 msgid "Used Filament (g)" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:454 +#: lib/Slic3r/GUI/Plater.pm:464 msgid "Estimated printing time" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:633 +#: lib/Slic3r/GUI/Plater.pm:662 msgid "Loading…" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:633 lib/Slic3r/GUI/Plater.pm:647 +#: lib/Slic3r/GUI/Plater.pm:662 lib/Slic3r/GUI/Plater.pm:676 msgid "Processing input file\n" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:667 +#: lib/Slic3r/GUI/Plater.pm:699 msgid "" "This file contains several objects positioned at multiple heights. Instead " "of considering them as multiple objects, should I consider\n" "this file as a single object having multiple parts?\n" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:670 lib/Slic3r/GUI/Plater.pm:687 +#: lib/Slic3r/GUI/Plater.pm:702 lib/Slic3r/GUI/Plater.pm:719 msgid "Multi-part object detected" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:684 +#: lib/Slic3r/GUI/Plater.pm:716 msgid "" "Multiple objects were loaded for a multi-material printer.\n" "Instead of considering them as multiple objects, should I consider\n" "these files to represent a single object having multiple parts?\n" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:696 +#: lib/Slic3r/GUI/Plater.pm:728 msgid "Loaded " msgstr "" -#: lib/Slic3r/GUI/Plater.pm:748 +#: lib/Slic3r/GUI/Plater.pm:786 msgid "" "Your object appears to be too large, so it was automatically scaled down to " "fit your print bed." msgstr "" -#: lib/Slic3r/GUI/Plater.pm:749 +#: lib/Slic3r/GUI/Plater.pm:787 msgid "Object too large?" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:904 +#: lib/Slic3r/GUI/Plater.pm:942 msgid "Enter the number of copies of the selected object:" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:931 +#: lib/Slic3r/GUI/Plater.pm:969 msgid "" "\n" "Non-positive value." msgstr "" -#: lib/Slic3r/GUI/Plater.pm:932 +#: lib/Slic3r/GUI/Plater.pm:970 msgid "" "\n" "Not a numeric value." msgstr "" -#: lib/Slic3r/GUI/Plater.pm:933 +#: lib/Slic3r/GUI/Plater.pm:971 msgid "Slic3r Error" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1034 +#: lib/Slic3r/GUI/Plater.pm:992 +msgid "Enter the rotation angle:" +msgstr "" + +#: lib/Slic3r/GUI/Plater.pm:992 +msgid "Rotate around " +msgstr "" + +#: lib/Slic3r/GUI/Plater.pm:992 +msgid "Invalid rotation angle entered" +msgstr "" + +#: lib/Slic3r/GUI/Plater.pm:1072 #, possible-perl-format msgid "Enter the new size for the selected object (print bed: %smm):" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1035 lib/Slic3r/GUI/Plater.pm:1039 +#: lib/Slic3r/GUI/Plater.pm:1073 lib/Slic3r/GUI/Plater.pm:1077 msgid "Scale along " msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1035 lib/Slic3r/GUI/Plater.pm:1039 -#: lib/Slic3r/GUI/Plater.pm:1060 lib/Slic3r/GUI/Plater.pm:1065 +#: lib/Slic3r/GUI/Plater.pm:1073 lib/Slic3r/GUI/Plater.pm:1077 +#: lib/Slic3r/GUI/Plater.pm:1098 lib/Slic3r/GUI/Plater.pm:1103 msgid "Invalid scaling value entered" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1039 lib/Slic3r/GUI/Plater.pm:1065 -#, possible-perl-format +#: lib/Slic3r/GUI/Plater.pm:1077 lib/Slic3r/GUI/Plater.pm:1103 +#, no-perl-format msgid "Enter the scale % for the selected object:" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1060 +#: lib/Slic3r/GUI/Plater.pm:1098 msgid "Enter the new max size for the selected object:" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1116 +#: lib/Slic3r/GUI/Plater.pm:1154 msgid "" "The selected object can't be split because it contains more than one volume/" "material." msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1125 +#: lib/Slic3r/GUI/Plater.pm:1163 msgid "" "The selected object couldn't be split because it contains only one part." msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1290 +#: lib/Slic3r/GUI/Plater.pm:1328 msgid "Slicing cancelled" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1304 +#: lib/Slic3r/GUI/Plater.pm:1342 msgid "Another export job is currently running." msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1335 -msgid "Save G-code file as:" -msgstr "" - -#: lib/Slic3r/GUI/Plater.pm:1352 -msgid "Export cancelled" -msgstr "" - -#: lib/Slic3r/GUI/Plater.pm:1449 +#: lib/Slic3r/GUI/Plater.pm:1490 msgid "File added to print queue" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1452 -msgid "Sending G-code file to the OctoPrint server..." -msgstr "" - -#: lib/Slic3r/GUI/Plater.pm:1455 +#: lib/Slic3r/GUI/Plater.pm:1496 msgid "G-code file exported to " msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1458 +#: lib/Slic3r/GUI/Plater.pm:1499 msgid "Export failed" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1509 lib/Slic3r/GUI/Plater.pm:1551 +#: lib/Slic3r/GUI/Plater.pm:1511 +msgid "OctoPrint upload finished." +msgstr "" + +#: lib/Slic3r/GUI/Plater.pm:1554 lib/Slic3r/GUI/Plater.pm:1596 msgid "STL file exported to " msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1562 +#: lib/Slic3r/GUI/Plater.pm:1607 msgid "AMF file exported to " msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1566 +#: lib/Slic3r/GUI/Plater.pm:1611 msgid "Error exporting AMF file " msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1578 +#: lib/Slic3r/GUI/Plater.pm:1623 msgid "3MF file exported to " msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1582 +#: lib/Slic3r/GUI/Plater.pm:1627 msgid "Error exporting 3MF file " msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1818 -msgid "" -"Please install the OpenGL modules to use this feature (see build " -"instructions)." -msgstr "" - -#: lib/Slic3r/GUI/Plater.pm:1928 +#: lib/Slic3r/GUI/Plater.pm:1985 #, possible-perl-format msgid "%d (%d shells)" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1930 +#: lib/Slic3r/GUI/Plater.pm:1987 #, possible-perl-format msgid "Auto-repaired (%d errors)" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1935 +#: lib/Slic3r/GUI/Plater.pm:1992 #, possible-perl-format msgid "" "%d degenerate facets, %d edges fixed, %d facets removed, %d facets added, %d " "facets reversed, %d backwards edges" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1940 +#: lib/Slic3r/GUI/Plater.pm:1997 msgid "Yes" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1991 +#: lib/Slic3r/GUI/Plater.pm:2050 msgid "Remove the selected object" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1994 +#: lib/Slic3r/GUI/Plater.pm:2053 msgid "Increase copies" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1994 +#: lib/Slic3r/GUI/Plater.pm:2053 msgid "Place one more copy of the selected object" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1997 +#: lib/Slic3r/GUI/Plater.pm:2056 msgid "Decrease copies" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:1997 +#: lib/Slic3r/GUI/Plater.pm:2056 msgid "Remove one copy of the selected object" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2000 +#: lib/Slic3r/GUI/Plater.pm:2059 msgid "Set number of copies…" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2000 +#: lib/Slic3r/GUI/Plater.pm:2059 msgid "Change the number of copies of the selected object" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2004 +#: lib/Slic3r/GUI/Plater.pm:2063 msgid "Rotate 45° clockwise" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2004 +#: lib/Slic3r/GUI/Plater.pm:2063 msgid "Rotate the selected object by 45° clockwise" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2007 +#: lib/Slic3r/GUI/Plater.pm:2066 msgid "Rotate 45° counter-clockwise" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2007 +#: lib/Slic3r/GUI/Plater.pm:2066 msgid "Rotate the selected object by 45° counter-clockwise" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2012 +#: lib/Slic3r/GUI/Plater.pm:2071 msgid "Rotate" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2012 +#: lib/Slic3r/GUI/Plater.pm:2071 msgid "Rotate the selected object by an arbitrary angle" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2014 +#: lib/Slic3r/GUI/Plater.pm:2073 msgid "Around X axis…" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2014 +#: lib/Slic3r/GUI/Plater.pm:2073 msgid "Rotate the selected object by an arbitrary angle around X axis" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2017 +#: lib/Slic3r/GUI/Plater.pm:2076 msgid "Around Y axis…" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2017 +#: lib/Slic3r/GUI/Plater.pm:2076 msgid "Rotate the selected object by an arbitrary angle around Y axis" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2020 +#: lib/Slic3r/GUI/Plater.pm:2079 msgid "Around Z axis…" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2020 +#: lib/Slic3r/GUI/Plater.pm:2079 msgid "Rotate the selected object by an arbitrary angle around Z axis" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2025 +#: lib/Slic3r/GUI/Plater.pm:2084 msgid "Mirror" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2025 +#: lib/Slic3r/GUI/Plater.pm:2084 msgid "Mirror the selected object" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2027 lib/Slic3r/GUI/Plater.pm:2043 -#: lib/Slic3r/GUI/Plater.pm:2059 +#: lib/Slic3r/GUI/Plater.pm:2086 lib/Slic3r/GUI/Plater.pm:2102 +#: lib/Slic3r/GUI/Plater.pm:2118 msgid "Along X axis…" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2027 +#: lib/Slic3r/GUI/Plater.pm:2086 msgid "Mirror the selected object along the X axis" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2030 lib/Slic3r/GUI/Plater.pm:2046 -#: lib/Slic3r/GUI/Plater.pm:2062 +#: lib/Slic3r/GUI/Plater.pm:2089 lib/Slic3r/GUI/Plater.pm:2105 +#: lib/Slic3r/GUI/Plater.pm:2121 msgid "Along Y axis…" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2030 +#: lib/Slic3r/GUI/Plater.pm:2089 msgid "Mirror the selected object along the Y axis" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2033 lib/Slic3r/GUI/Plater.pm:2049 -#: lib/Slic3r/GUI/Plater.pm:2065 +#: lib/Slic3r/GUI/Plater.pm:2092 lib/Slic3r/GUI/Plater.pm:2108 +#: lib/Slic3r/GUI/Plater.pm:2124 msgid "Along Z axis…" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2033 +#: lib/Slic3r/GUI/Plater.pm:2092 msgid "Mirror the selected object along the Z axis" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2038 lib/Slic3r/GUI/Plater.pm:2054 +#: lib/Slic3r/GUI/Plater.pm:2097 lib/Slic3r/GUI/Plater.pm:2113 msgid "Scale the selected object along a single axis" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2040 lib/Slic3r/GUI/Plater.pm:2056 +#: lib/Slic3r/GUI/Plater.pm:2099 lib/Slic3r/GUI/Plater.pm:2115 msgid "Uniformly…" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2040 lib/Slic3r/GUI/Plater.pm:2056 +#: lib/Slic3r/GUI/Plater.pm:2099 lib/Slic3r/GUI/Plater.pm:2115 msgid "Scale the selected object along the XYZ axes" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2043 lib/Slic3r/GUI/Plater.pm:2059 +#: lib/Slic3r/GUI/Plater.pm:2102 lib/Slic3r/GUI/Plater.pm:2118 msgid "Scale the selected object along the X axis" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2046 lib/Slic3r/GUI/Plater.pm:2062 +#: lib/Slic3r/GUI/Plater.pm:2105 lib/Slic3r/GUI/Plater.pm:2121 msgid "Scale the selected object along the Y axis" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2049 lib/Slic3r/GUI/Plater.pm:2065 +#: lib/Slic3r/GUI/Plater.pm:2108 lib/Slic3r/GUI/Plater.pm:2124 msgid "Scale the selected object along the Z axis" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2054 +#: lib/Slic3r/GUI/Plater.pm:2113 msgid "Scale to size" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2069 +#: lib/Slic3r/GUI/Plater.pm:2128 msgid "Split the selected object into individual parts" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2072 +#: lib/Slic3r/GUI/Plater.pm:2131 msgid "Open the 3D cutting tool" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2076 +#: lib/Slic3r/GUI/Plater.pm:2135 msgid "Open the object editor dialog" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2080 +#: lib/Slic3r/GUI/Plater.pm:2139 msgid "Reload from Disk" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2080 +#: lib/Slic3r/GUI/Plater.pm:2139 msgid "Reload the selected file from Disk" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2083 +#: lib/Slic3r/GUI/Plater.pm:2142 msgid "Export object as STL…" msgstr "" -#: lib/Slic3r/GUI/Plater.pm:2083 +#: lib/Slic3r/GUI/Plater.pm:2142 msgid "Export this single object as STL file" msgstr "" @@ -3755,30 +4620,34 @@ msgstr "" msgid "Drag your objects here" msgstr "" -#: lib/Slic3r/GUI/Plater/3DPreview.pm:63 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:62 msgid "1 Layer" msgstr "" -#: lib/Slic3r/GUI/Plater/3DPreview.pm:65 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:64 msgid "View" msgstr "" -#: lib/Slic3r/GUI/Plater/3DPreview.pm:75 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:71 +msgid "Volumetric flow rate" +msgstr "" + +#: lib/Slic3r/GUI/Plater/3DPreview.pm:78 msgid "Show" msgstr "" -#: lib/Slic3r/GUI/Plater/3DPreview.pm:78 lib/Slic3r/GUI/Plater/3DPreview.pm:79 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:81 lib/Slic3r/GUI/Plater/3DPreview.pm:82 msgid "Feature types" msgstr "" -#: lib/Slic3r/GUI/Plater/3DPreview.pm:96 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:99 msgid "Retractions" msgstr "" -#: lib/Slic3r/GUI/Plater/3DPreview.pm:97 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:100 msgid "Unretractions" msgstr "" -#: lib/Slic3r/GUI/Plater/3DPreview.pm:98 +#: lib/Slic3r/GUI/Plater/3DPreview.pm:101 msgid "Shells" msgstr "" diff --git a/resources/localization/list.txt b/resources/localization/list.txt index 292549545..2112d67c3 100644 --- a/resources/localization/list.txt +++ b/resources/localization/list.txt @@ -1,15 +1,23 @@ +xs/src/slic3r/GUI/AboutDialog.cpp xs/src/slic3r/GUI/BedShapeDialog.cpp xs/src/slic3r/GUI/BedShapeDialog.hpp +xs/src/slic3r/GUI/BonjourDialog.cpp +xs/src/slic3r/GUI/ButtonsDescription.cpp +xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp +xs/src/slic3r/GUI/ConfigWizard.cpp xs/src/slic3r/GUI/GUI.cpp +xs/src/slic3r/GUI/MsgDialog.cpp xs/src/slic3r/GUI/Tab.cpp xs/src/slic3r/GUI/Tab.hpp xs/src/slic3r/GUI/Field.cpp xs/src/slic3r/GUI/OptionsGroup.cpp -xs/src/slic3r/GUI/2DBed.cpp +xs/src/slic3r/GUI/Preset.cpp +xs/src/slic3r/GUI/PresetBundle.cpp xs/src/slic3r/GUI/PresetHints.cpp -xs/src/slic3r/GUI/Preferences.hpp xs/src/slic3r/GUI/Preferences.cpp -xs/src/slic3r/GUI/BonjourDialog.cpp +xs/src/slic3r/GUI/RammingChart.cpp +xs/src/slic3r/GUI/UpdateDialogs.cpp +xs/src/slic3r/GUI/WipeTowerDialog.cpp xs/src/slic3r/Utils/OctoPrint.cpp xs/src/libslic3r/PrintConfig.cpp xs/src/libslic3r/GCode/PreviewData.cpp diff --git a/resources/profiles/PrusaResearch.idx b/resources/profiles/PrusaResearch.idx index b43e26663..f07d8b280 100644 --- a/resources/profiles/PrusaResearch.idx +++ b/resources/profiles/PrusaResearch.idx @@ -1,15 +1 @@ -# This is an example configuration version index. -# The index contains version numbers -min_slic3r_version =1.39.0 -1.1.1 -1.1.0 -0.2.0-alpha "some test comment" -max_slic3r_version= 1.39.4 -0.1.0 another test comment - -# some empty lines - -# version without a comment -min_slic3r_version = 1.0.0 -max_slic3r_version = 1.1.0 -0.0.1 +0.1.0 Initial diff --git a/resources/profiles/PrusaResearch.ini b/resources/profiles/PrusaResearch.ini index 0da7f22d1..d82921fd8 100644 --- a/resources/profiles/PrusaResearch.ini +++ b/resources/profiles/PrusaResearch.ini @@ -7,13 +7,13 @@ name = Prusa Research # This means, the server may force the Slic3r configuration to be downgraded. config_version = 0.1.0 # Where to get the updates from? -# TODO: proper URL -config_update_url = https://raw.githubusercontent.com/vojtechkral/slic3r-settings-tmp/master/PrusaResearch +config_update_url = https://raw.githubusercontent.com/prusa3d/Slic3r-settings/master/live/PrusaResearch/ # The printer models will be shown by the Configuration Wizard in this order, # also the first model installed & the first nozzle installed will be activated after install. #TODO: One day we may differentiate variants of the nozzles / hot ends, #for example by the melt zone size, or whether the nozzle is hardened. +# Printer model name will be shown by the installation wizard. [printer_model:MK3] name = Original Prusa i3 MK3 variants = 0.4; 0.25; 0.6 @@ -23,7 +23,6 @@ name = Original Prusa i3 MK2S variants = 0.4; 0.25; 0.6 [printer_model:MK2SMM] -# Printer model name will be shown by the installation wizard. name = Original Prusa i3 MK2SMM variants = 0.4; 0.6 @@ -69,6 +68,7 @@ infill_first = 0 infill_only_where_needed = 0 infill_overlap = 25% interface_shells = 0 +max_print_height = 200 max_print_speed = 100 max_volumetric_extrusion_rate_slope_negative = 0 max_volumetric_extrusion_rate_slope_positive = 0 @@ -120,7 +120,7 @@ thin_walls = 0 top_infill_extrusion_width = 0.45 top_solid_infill_speed = 40 travel_speed = 180 -wipe_tower = 0 +wipe_tower = 1 wipe_tower_per_color_wipe = 20 wipe_tower_width = 60 wipe_tower_x = 180 @@ -939,6 +939,8 @@ inherits = *multimaterial* end_gcode = G1 E-4 F2100.00000\nG91\nG1 Z1 F7200.000\nG90\nG1 X245 Y1\nG1 X240 E4\nG1 F4000\nG1 X190 E2.7 \nG1 F4600\nG1 X110 E2.8\nG1 F5200\nG1 X40 E3 \nG1 E-15.0000 F5000\nG1 E-50.0000 F5400\nG1 E-15.0000 F3000\nG1 E-12.0000 F2000\nG1 F1600\nG1 X0 Y1 E3.0000\nG1 X50 Y1 E-5.0000\nG1 F2000\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-3.0000\nG4 S0\nM107 ; fan off\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nG28 X0 ; home X axis\nM84 ; disable motors\n\n printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN start_gcode = M115 U3.1.0 ; tell printer latest fw version\nM201 X9000 Y9000 Z500 E10000 ; sets maximum accelerations, mm/sec^2\nM203 X500 Y500 Z12 E120 ; sets maximum feedrates, mm/sec\nM204 S1500 T1500 ; sets acceleration (S) and retract acceleration (T)\nM205 X10 Y10 Z0.2 E2.5 ; sets the jerk limits, mm/sec\nM205 S0 T0 ; sets the minimum extruding and travel feed rate, mm/sec\n; Start G-Code sequence START\nT?\nM104 S[first_layer_temperature]\nM140 S[first_layer_bed_temperature]\nM109 S[first_layer_temperature]\nM190 S[first_layer_bed_temperature]\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100\nM92 E140\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\nG1 E-4 F1000.0\nG92 E0.0 +default_print_profile = 0.15mm OPTIMAL +default_filament_profile = Prusa PLA [printer:*mm-multi*] inherits = *multimaterial* @@ -948,10 +950,11 @@ nozzle_diameter = 0.4,0.4,0.4,0.4 printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN start_gcode = M115 U3.1.0 ; tell printer latest fw version\nM201 X9000 Y9000 Z500 E10000 ; sets maximum accelerations, mm/sec^2\nM203 X500 Y500 Z12 E120 ; sets maximum feedrates, mm/sec\nM204 S1500 T1500 ; sets acceleration (S) and retract acceleration (T)\nM205 X10 Y10 Z0.2 E2.5 ; sets the jerk limits, mm/sec\nM205 S0 T0 ; sets the minimum extruding and travel feed rate, mm/sec\n; Start G-Code sequence START\nT[initial_tool]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100 ; set max feedrate\nM92 E140 ; E-steps per filament milimeter\n{if not has_wipe_tower}\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\nG1 E-4 F1000.0\n{endif}\nG92 E0.0 variable_layer_height = 0 +default_print_profile = 0.15mm OPTIMAL +default_filament_profile = Prusa PLA [printer:Original Prusa i3 MK2] inherits = *common* -default_print_profile = 0.15mm OPTIMAL [printer:Original Prusa i3 MK2 0.25 nozzle] inherits = *common* @@ -989,12 +992,14 @@ nozzle_diameter = 0.4,0.4,0.4,0.4 inherits = *mm-multi* nozzle_diameter = 0.6,0.6,0.6,0.6 printer_variant = 0.6 +default_print_profile = 0.20mm NORMAL 0.6 nozzle [printer:Original Prusa i3 MK3] inherits = *common* end_gcode = G4 ; wait\nM221 S100\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n retract_lift_below = 209 +max_print_height = 210 start_gcode = M115 U3.1.1-RC5 ; tell printer latest fw version\nM201 X1000 Y1000 Z200 E5000 ; sets maximum accelerations, mm/sec^2\nM203 X200 Y200 Z12 E120 ; sets maximum feedrates, mm/sec\nM204 S1250 T1250 ; sets acceleration (S) and retract acceleration (T)\nM205 X10 Y10 Z0.4 E2.5 ; sets the jerk limits, mm/sec\nM205 S0 T0 ; sets the minimum extruding and travel feed rate, mm/sec\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height==0.05}100{else}95{endif} printer_model = MK3 default_print_profile = 0.15mm OPTIMAL MK3 @@ -1002,21 +1007,21 @@ default_print_profile = 0.15mm OPTIMAL MK3 [printer:Original Prusa i3 MK3 0.25 nozzle] inherits = *common* nozzle_diameter = 0.25 -printer_variant = 0.25 end_gcode = G4 ; wait\nM221 S100\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n retract_lift_below = 209 +max_print_height = 210 start_gcode = M115 U3.1.1-RC5 ; tell printer latest fw version\nM201 X1000 Y1000 Z200 E5000 ; sets maximum accelerations, mm/sec^2\nM203 X200 Y200 Z12 E120 ; sets maximum feedrates, mm/sec\nM204 S1250 T1250 ; sets acceleration (S) and retract acceleration (T)\nM205 X10 Y10 Z0.4 E2.5 ; sets the jerk limits, mm/sec\nM205 S0 T0 ; sets the minimum extruding and travel feed rate, mm/sec\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height==0.05}100{else}95{endif} printer_model = MK3 -default_print_profile = 0.10mm DETAIL MK3 +default_print_profile = 0.10mm DETAIL 0.25 nozzle MK3 [printer:Original Prusa i3 MK3 0.6 nozzle] inherits = *common* nozzle_diameter = 0.6 -printer_variant = 0.6 end_gcode = G4 ; wait\nM221 S100\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n retract_lift_below = 209 +max_print_height = 210 start_gcode = M115 U3.1.1-RC5 ; tell printer latest fw version\nM201 X1000 Y1000 Z200 E5000 ; sets maximum accelerations, mm/sec^2\nM203 X200 Y200 Z12 E120 ; sets maximum feedrates, mm/sec\nM204 S1250 T1250 ; sets acceleration (S) and retract acceleration (T)\nM205 X10 Y10 Z0.4 E2.5 ; sets the jerk limits, mm/sec\nM205 S0 T0 ; sets the minimum extruding and travel feed rate, mm/sec\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height==0.05}100{else}95{endif} printer_model = MK3 -default_print_profile = 0.15mm OPTIMAL MK3 +default_print_profile = 0.15mm OPTIMAL 0.6 nozzle MK3 diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index 7798333fb..4f97c0acf 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -212,6 +212,8 @@ add_library(libslic3r_gui STATIC ${LIBDIR}/slic3r/GUI/RammingChart.hpp ${LIBDIR}/slic3r/GUI/BonjourDialog.cpp ${LIBDIR}/slic3r/GUI/BonjourDialog.hpp + ${LIBDIR}/slic3r/GUI/ButtonsDescription.cpp + ${LIBDIR}/slic3r/GUI/ButtonsDescription.hpp ${LIBDIR}/slic3r/Config/Snapshot.cpp ${LIBDIR}/slic3r/Config/Snapshot.hpp ${LIBDIR}/slic3r/Config/Version.cpp @@ -220,6 +222,10 @@ add_library(libslic3r_gui STATIC ${LIBDIR}/slic3r/Utils/ASCIIFolding.hpp ${LIBDIR}/slic3r/GUI/ConfigWizard.cpp ${LIBDIR}/slic3r/GUI/ConfigWizard.hpp + ${LIBDIR}/slic3r/GUI/MsgDialog.cpp + ${LIBDIR}/slic3r/GUI/MsgDialog.hpp + ${LIBDIR}/slic3r/GUI/UpdateDialogs.cpp + ${LIBDIR}/slic3r/GUI/UpdateDialogs.hpp ${LIBDIR}/slic3r/Utils/Http.cpp ${LIBDIR}/slic3r/Utils/Http.hpp ${LIBDIR}/slic3r/Utils/OctoPrint.cpp @@ -634,6 +640,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E copy "$" "${PERL_LOCAL_LIB_DIR}/auto/Slic3r/XS/" COMMAND ${CMAKE_COMMAND} -E make_directory "${PERL_LOCAL_LIB_DIR}/Slic3r/" COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/xs/lib/Slic3r/XS.pm" "${PERL_LOCAL_LIB_DIR}/Slic3r/" + COMMENT "Installing XS.pm and XS.{so,dll,bundle} into the local-lib directory ..." ) if(APPLE) add_custom_command( @@ -658,7 +665,12 @@ endif () if (MSVC) # Here we associate some additional properties with the MSVC project to enable compilation and debugging out of the box. - set_target_properties(XS PROPERTIES VS_USER_PROPS "${PROJECT_SOURCE_DIR}/cmake/msvc/xs.wperl64d.props") + get_filename_component(PROPS_PERL_BIN_PATH "${PERL_EXECUTABLE}" DIRECTORY) + string(REPLACE "/" "\\" PROPS_PERL_BIN_PATH "${PROPS_PERL_BIN_PATH}") + string(REPLACE "/" "\\" PROPS_PERL_EXECUTABLE "${PERL_EXECUTABLE}") + string(REPLACE "/" "\\" PROPS_CMAKE_SOURCE_DIR "${CMAKE_SOURCE_DIR}") + configure_file("${PROJECT_SOURCE_DIR}/cmake/msvc/xs.wperl.props.in" "${CMAKE_BINARY_DIR}/xs.wperl.props" NEWLINE_STYLE CRLF) + set_target_properties(XS PROPERTIES VS_USER_PROPS "${CMAKE_BINARY_DIR}/xs.wperl.props") endif() # l10n diff --git a/xs/src/libslic3r/Config.cpp b/xs/src/libslic3r/Config.cpp index a4eaf3072..8c1349e08 100644 --- a/xs/src/libslic3r/Config.cpp +++ b/xs/src/libslic3r/Config.cpp @@ -206,6 +206,44 @@ t_config_option_keys ConfigBase::diff(const ConfigBase &other) const return diff; } +template +void add_correct_opts_to_diff(const std::string &opt_key, t_config_option_keys& vec, const ConfigBase &other, const ConfigBase *this_c) +{ + const T* opt_init = static_cast(other.option(opt_key)); + const T* opt_cur = static_cast(this_c->option(opt_key)); + int opt_init_max_id = opt_init->values.size() - 1; + for (int i = 0; i < opt_cur->values.size(); i++) + { + int init_id = i <= opt_init_max_id ? i : 0; + if (opt_cur->values[i] != opt_init->values[init_id]) + vec.emplace_back(opt_key + "#" + std::to_string(i)); + } +} + +t_config_option_keys ConfigBase::deep_diff(const ConfigBase &other) const +{ + t_config_option_keys diff; + for (const t_config_option_key &opt_key : this->keys()) { + const ConfigOption *this_opt = this->option(opt_key); + const ConfigOption *other_opt = other.option(opt_key); + if (this_opt != nullptr && other_opt != nullptr && *this_opt != *other_opt) + { + if (opt_key == "bed_shape"){ diff.emplace_back(opt_key); continue; } + switch (other_opt->type()) + { + case coInts: add_correct_opts_to_diff(opt_key, diff, other, this); break; + case coBools: add_correct_opts_to_diff(opt_key, diff, other, this); break; + case coFloats: add_correct_opts_to_diff(opt_key, diff, other, this); break; + case coStrings: add_correct_opts_to_diff(opt_key, diff, other, this); break; + case coPercents:add_correct_opts_to_diff(opt_key, diff, other, this); break; + case coPoints: add_correct_opts_to_diff(opt_key, diff, other, this); break; + default: diff.emplace_back(opt_key); break; + } + } + } + return diff; +} + t_config_option_keys ConfigBase::equal(const ConfigBase &other) const { t_config_option_keys equal; diff --git a/xs/src/libslic3r/Config.hpp b/xs/src/libslic3r/Config.hpp index 06db9efef..14050c6cc 100644 --- a/xs/src/libslic3r/Config.hpp +++ b/xs/src/libslic3r/Config.hpp @@ -1047,6 +1047,9 @@ public: void apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false); bool equals(const ConfigBase &other) const { return this->diff(other).empty(); } t_config_option_keys diff(const ConfigBase &other) const; + // Use deep_diff to correct return of changed options, + // considering individual options for each extruder + t_config_option_keys deep_diff(const ConfigBase &other) const; t_config_option_keys equal(const ConfigBase &other) const; std::string serialize(const t_config_option_key &opt_key) const; // Set a configuration value from a string, it will call an overridable handle_legacy() diff --git a/xs/src/libslic3r/Format/3mf.cpp b/xs/src/libslic3r/Format/3mf.cpp index 7b5bf7e8a..0467962c3 100644 --- a/xs/src/libslic3r/Format/3mf.cpp +++ b/xs/src/libslic3r/Format/3mf.cpp @@ -16,6 +16,12 @@ #include #include +// VERSION NUMBERS +// 0 : .3mf, files saved by older slic3r or other applications. No version definition in them. +// 1 : Introduction of 3mf versioning. No other change in data saved into 3mf files. +const unsigned int VERSION_3MF = 1; +const char* SLIC3RPE_3MF_VERSION = "slic3rpe:Version3mf"; // definition of the metadata name saved into .model file + const std::string MODEL_FOLDER = "3D/"; const std::string MODEL_EXTENSION = ".model"; const std::string MODEL_FILE = "3D/3dmodel.model"; // << this is the only format of the string which works with CURA @@ -23,6 +29,7 @@ const std::string CONTENT_TYPES_FILE = "[Content_Types].xml"; const std::string RELATIONSHIPS_FILE = "_rels/.rels"; const std::string PRINT_CONFIG_FILE = "Metadata/Slic3r_PE.config"; const std::string MODEL_CONFIG_FILE = "Metadata/Slic3r_PE_model.config"; +const std::string LAYER_HEIGHTS_PROFILE_FILE = "Metadata/Slic3r_PE_layer_heights_profile.txt"; const char* MODEL_TAG = "model"; const char* RESOURCES_TAG = "resources"; @@ -36,9 +43,9 @@ const char* COMPONENTS_TAG = "components"; const char* COMPONENT_TAG = "component"; const char* BUILD_TAG = "build"; const char* ITEM_TAG = "item"; +const char* METADATA_TAG = "metadata"; const char* CONFIG_TAG = "config"; -const char* METADATA_TAG = "metadata"; const char* VOLUME_TAG = "volume"; const char* UNIT_ATTR = "unit"; @@ -315,6 +322,10 @@ namespace Slic3r { typedef std::vector InstancesList; typedef std::map IdToMetadataMap; typedef std::map IdToGeometryMap; + typedef std::map> IdToLayerHeightsProfileMap; + + // Version of the 3mf file + unsigned int m_version; XML_Parser m_xml_parser; Model* m_model; @@ -326,6 +337,9 @@ namespace Slic3r { IdToGeometryMap m_geometries; CurrentConfig m_curr_config; IdToMetadataMap m_objects_metadata; + IdToLayerHeightsProfileMap m_layer_heights_profiles; + std::string m_curr_metadata_name; + std::string m_curr_characters; public: _3MF_Importer(); @@ -339,12 +353,14 @@ namespace Slic3r { bool _load_model_from_file(const std::string& filename, Model& model, PresetBundle& bundle); bool _extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat); - bool _extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, PresetBundle& bundle, const std::string& archive_filename); + void _extract_layer_heights_profile_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat); + void _extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, PresetBundle& bundle, const std::string& archive_filename); bool _extract_model_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, Model& model); // handlers to parse the .model file void _handle_start_model_xml_element(const char* name, const char** attributes); void _handle_end_model_xml_element(const char* name); + void _handle_model_xml_characters(const XML_Char* s, int len); // handlers to parse the MODEL_CONFIG_FILE file void _handle_start_config_xml_element(const char* name, const char** attributes); @@ -386,6 +402,9 @@ namespace Slic3r { bool _handle_start_item(const char** attributes, unsigned int num_attributes); bool _handle_end_item(); + bool _handle_start_metadata(const char** attributes, unsigned int num_attributes); + bool _handle_end_metadata(); + bool _create_object_instance(int object_id, const Matrix4x4& matrix, unsigned int recur_counter); void _apply_transform(ModelInstance& instance, const Matrix4x4& matrix); @@ -407,6 +426,7 @@ namespace Slic3r { // callbacks to parse the .model file static void XMLCALL _handle_start_model_xml_element(void* userData, const char* name, const char** attributes); static void XMLCALL _handle_end_model_xml_element(void* userData, const char* name); + static void XMLCALL _handle_model_xml_characters(void* userData, const XML_Char* s, int len); // callbacks to parse the MODEL_CONFIG_FILE file static void XMLCALL _handle_start_config_xml_element(void* userData, const char* name, const char** attributes); @@ -414,9 +434,12 @@ namespace Slic3r { }; _3MF_Importer::_3MF_Importer() - : m_xml_parser(nullptr) + : m_version(0) + , m_xml_parser(nullptr) , m_model(nullptr) , m_unit_factor(1.0f) + , m_curr_metadata_name("") + , m_curr_characters("") { } @@ -427,6 +450,7 @@ namespace Slic3r { bool _3MF_Importer::load_model_from_file(const std::string& filename, Model& model, PresetBundle& bundle) { + m_version = 0; m_model = &model; m_unit_factor = 1.0f; m_curr_object.reset(); @@ -437,6 +461,9 @@ namespace Slic3r { m_curr_config.object_id = -1; m_curr_config.volume_id = -1; m_objects_metadata.clear(); + m_layer_heights_profiles.clear(); + m_curr_metadata_name.clear(); + m_curr_characters.clear(); clear_errors(); return _load_model_from_file(filename, model, bundle); @@ -472,6 +499,8 @@ namespace Slic3r { mz_uint num_entries = mz_zip_reader_get_num_files(&archive); mz_zip_archive_file_stat stat; + + // we first loop the entries to read from the archive the .model file only, in order to extract the version from it for (mz_uint i = 0; i < num_entries; ++i) { if (mz_zip_reader_file_stat(&archive, i, &stat)) @@ -489,15 +518,26 @@ namespace Slic3r { return false; } } + } + } + + // we then loop again the entries to read other files stored in the archive + for (mz_uint i = 0; i < num_entries; ++i) + { + if (mz_zip_reader_file_stat(&archive, i, &stat)) + { + std::string name(stat.m_filename); + std::replace(name.begin(), name.end(), '\\', '/'); + + if (boost::algorithm::iequals(name, LAYER_HEIGHTS_PROFILE_FILE)) + { + // extract slic3r lazer heights profile file + _extract_layer_heights_profile_config_from_archive(archive, stat); + } else if (boost::algorithm::iequals(name, PRINT_CONFIG_FILE)) { // extract slic3r print config file - if (!_extract_print_config_from_archive(archive, stat, bundle, filename)) - { - mz_zip_reader_end(&archive); - add_error("Archive does not contain a valid print config"); - return false; - } + _extract_print_config_from_archive(archive, stat, bundle, filename); } else if (boost::algorithm::iequals(name, MODEL_CONFIG_FILE)) { @@ -526,6 +566,13 @@ namespace Slic3r { return false; } + IdToLayerHeightsProfileMap::iterator obj_layer_heights_profile = m_layer_heights_profiles.find(object.first); + if (obj_layer_heights_profile != m_layer_heights_profiles.end()) + { + object.second->layer_height_profile = obj_layer_heights_profile->second; + object.second->layer_height_profile_valid = true; + } + IdToMetadataMap::iterator obj_metadata = m_objects_metadata.find(object.first); if (obj_metadata != m_objects_metadata.end()) { @@ -583,6 +630,7 @@ namespace Slic3r { XML_SetUserData(m_xml_parser, (void*)this); XML_SetElementHandler(m_xml_parser, _3MF_Importer::_handle_start_model_xml_element, _3MF_Importer::_handle_end_model_xml_element); + XML_SetCharacterDataHandler(m_xml_parser, _3MF_Importer::_handle_model_xml_characters); void* parser_buffer = XML_GetBuffer(m_xml_parser, (int)stat.m_uncomp_size); if (parser_buffer == nullptr) @@ -609,23 +657,90 @@ namespace Slic3r { return true; } - bool _3MF_Importer::_extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, PresetBundle& bundle, const std::string& archive_filename) + void _3MF_Importer::_extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, PresetBundle& bundle, const std::string& archive_filename) { if (stat.m_uncomp_size > 0) { - std::vector buffer((size_t)stat.m_uncomp_size + 1, 0); + std::string buffer((size_t)stat.m_uncomp_size, 0); mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0); if (res == 0) { add_error("Error while reading config data to buffer"); - return false; + return; } - - buffer.back() = '\0'; bundle.load_config_string(buffer.data(), archive_filename.c_str()); } + } - return true; + void _3MF_Importer::_extract_layer_heights_profile_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat) + { + if (stat.m_uncomp_size > 0) + { + std::string buffer((size_t)stat.m_uncomp_size, 0); + mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0); + if (res == 0) + { + add_error("Error while reading layer heights profile data to buffer"); + return; + } + + if (buffer.back() == '\n') + buffer.pop_back(); + + std::vector objects; + boost::split(objects, buffer, boost::is_any_of("\n"), boost::token_compress_off); + + for (const std::string& object : objects) + { + std::vector object_data; + boost::split(object_data, object, boost::is_any_of("|"), boost::token_compress_off); + if (object_data.size() != 2) + { + add_error("Error while reading object data"); + continue; + } + + std::vector object_data_id; + boost::split(object_data_id, object_data[0], boost::is_any_of("="), boost::token_compress_off); + if (object_data_id.size() != 2) + { + add_error("Error while reading object id"); + continue; + } + + int object_id = std::atoi(object_data_id[1].c_str()); + if (object_id == 0) + { + add_error("Found invalid object id"); + continue; + } + + IdToLayerHeightsProfileMap::iterator object_item = m_layer_heights_profiles.find(object_id); + if (object_item != m_layer_heights_profiles.end()) + { + add_error("Found duplicated layer heights profile"); + continue; + } + + std::vector object_data_profile; + boost::split(object_data_profile, object_data[1], boost::is_any_of(";"), boost::token_compress_off); + if ((object_data_profile.size() <= 4) || (object_data_profile.size() % 2 != 0)) + { + add_error("Found invalid layer heights profile"); + continue; + } + + std::vector profile; + profile.reserve(object_data_profile.size()); + + for (const std::string& value : object_data_profile) + { + profile.push_back((coordf_t)std::atof(value.c_str())); + } + + m_layer_heights_profiles.insert(IdToLayerHeightsProfileMap::value_type(object_id, profile)); + } + } } bool _3MF_Importer::_extract_model_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, Model& model) @@ -705,6 +820,8 @@ namespace Slic3r { res = _handle_start_build(attributes, num_attributes); else if (::strcmp(ITEM_TAG, name) == 0) res = _handle_start_item(attributes, num_attributes); + else if (::strcmp(METADATA_TAG, name) == 0) + res = _handle_start_metadata(attributes, num_attributes); if (!res) _stop_xml_parser(); @@ -741,11 +858,18 @@ namespace Slic3r { res = _handle_end_build(); else if (::strcmp(ITEM_TAG, name) == 0) res = _handle_end_item(); + else if (::strcmp(METADATA_TAG, name) == 0) + res = _handle_end_metadata(); if (!res) _stop_xml_parser(); } + void _3MF_Importer::_handle_model_xml_characters(const XML_Char* s, int len) + { + m_curr_characters.append(s, len); + } + void _3MF_Importer::_handle_start_config_xml_element(const char* name, const char** attributes) { if (m_xml_parser == nullptr) @@ -1052,6 +1176,25 @@ namespace Slic3r { return true; } + bool _3MF_Importer::_handle_start_metadata(const char** attributes, unsigned int num_attributes) + { + m_curr_characters.clear(); + + std::string name = get_attribute_value_string(attributes, num_attributes, NAME_ATTR); + if (!name.empty()) + m_curr_metadata_name = name; + + return true; + } + + bool _3MF_Importer::_handle_end_metadata() + { + if (m_curr_metadata_name == SLIC3RPE_3MF_VERSION) + m_version = (unsigned int)atoi(m_curr_characters.c_str()); + + return true; + } + bool _3MF_Importer::_create_object_instance(int object_id, const Matrix4x4& matrix, unsigned int recur_counter) { static const unsigned int MAX_RECURSIONS = 10; @@ -1358,6 +1501,13 @@ namespace Slic3r { importer->_handle_end_model_xml_element(name); } + void XMLCALL _3MF_Importer::_handle_model_xml_characters(void* userData, const XML_Char* s, int len) + { + _3MF_Importer* importer = (_3MF_Importer*)userData; + if (importer != nullptr) + importer->_handle_model_xml_characters(s, len); + } + void XMLCALL _3MF_Importer::_handle_start_config_xml_element(void* userData, const char* name, const char** attributes) { _3MF_Importer* importer = (_3MF_Importer*)userData; @@ -1429,6 +1579,7 @@ namespace Slic3r { bool _add_object_to_model_stream(std::stringstream& stream, unsigned int& object_id, ModelObject& object, BuildItemsList& build_items, VolumeToOffsetsMap& volumes_offsets); bool _add_mesh_to_object_stream(std::stringstream& stream, ModelObject& object, VolumeToOffsetsMap& volumes_offsets); bool _add_build_to_model_stream(std::stringstream& stream, const BuildItemsList& build_items); + bool _add_layer_height_profile_file_to_archive(mz_zip_archive& archive, Model& model); bool _add_print_config_file_to_archive(mz_zip_archive& archive, const Print& print); bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model); }; @@ -1477,6 +1628,14 @@ namespace Slic3r { return false; } + // adds layer height profile file + if (!_add_layer_height_profile_file_to_archive(archive, model)) + { + mz_zip_writer_end(&archive); + boost::filesystem::remove(filename); + return false; + } + // adds slic3r print config file if (export_print_config) { @@ -1552,7 +1711,8 @@ namespace Slic3r { { std::stringstream stream; stream << "\n"; - stream << "<" << MODEL_TAG << " unit=\"millimeter\" xml:lang=\"en-US\" xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\">\n"; + stream << "<" << MODEL_TAG << " unit=\"millimeter\" xml:lang=\"en-US\" xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\" xmlns:slic3rpe=\"http://schemas.slic3r.org/3mf/2017/06\">\n"; + stream << " <" << METADATA_TAG << " name=\"" << SLIC3RPE_3MF_VERSION << "\">" << VERSION_3MF << "\n"; stream << " <" << RESOURCES_TAG << ">\n"; BuildItemsList build_items; @@ -1736,6 +1896,44 @@ namespace Slic3r { return true; } + bool _3MF_Exporter::_add_layer_height_profile_file_to_archive(mz_zip_archive& archive, Model& model) + { + std::string out = ""; + char buffer[1024]; + + unsigned int count = 0; + for (const ModelObject* object : model.objects) + { + ++count; + std::vector layer_height_profile = object->layer_height_profile_valid ? object->layer_height_profile : std::vector(); + if ((layer_height_profile.size() >= 4) && ((layer_height_profile.size() % 2) == 0)) + { + sprintf(buffer, "object_id=%d|", count); + out += buffer; + + // Store the layer height profile as a single semicolon separated list. + for (size_t i = 0; i < layer_height_profile.size(); ++i) + { + sprintf(buffer, (i == 0) ? "%f" : ";%f", layer_height_profile[i]); + out += buffer; + } + + out += "\n"; + } + } + + if (!out.empty()) + { + if (!mz_zip_writer_add_mem(&archive, LAYER_HEIGHTS_PROFILE_FILE.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION)) + { + add_error("Unable to add layer heights profile file to archive"); + return false; + } + } + + return true; + } + bool _3MF_Exporter::_add_print_config_file_to_archive(mz_zip_archive& archive, const Print& print) { char buffer[1024]; @@ -1744,10 +1942,13 @@ namespace Slic3r { GCode::append_full_config(print, out); - if (!mz_zip_writer_add_mem(&archive, PRINT_CONFIG_FILE.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION)) + if (!out.empty()) { - add_error("Unable to add print config file to archive"); - return false; + if (!mz_zip_writer_add_mem(&archive, PRINT_CONFIG_FILE.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION)) + { + add_error("Unable to add print config file to archive"); + return false; + } } return true; @@ -1832,10 +2033,7 @@ namespace Slic3r { _3MF_Importer importer; bool res = importer.load_model_from_file(path, *model, *bundle); - - if (!res) - importer.log_errors(); - + importer.log_errors(); return res; } diff --git a/xs/src/libslic3r/Format/AMF.cpp b/xs/src/libslic3r/Format/AMF.cpp index 98683cd8a..b446f456b 100644 --- a/xs/src/libslic3r/Format/AMF.cpp +++ b/xs/src/libslic3r/Format/AMF.cpp @@ -24,6 +24,12 @@ #include +// VERSION NUMBERS +// 0 : .amf, .amf.xml and .zip.amf files saved by older slic3r. No version definition in them. +// 1 : Introduction of amf versioning. No other change in data saved into amf files. +const unsigned int VERSION_AMF = 1; +const char* SLIC3RPE_AMF_VERSION = "slic3rpe_amf_version"; + const char* SLIC3R_CONFIG_TYPE = "slic3rpe_config"; namespace Slic3r @@ -32,6 +38,7 @@ namespace Slic3r struct AMFParserContext { AMFParserContext(XML_Parser parser, const std::string& archive_filename, PresetBundle* preset_bundle, Model *model) : + m_version(0), m_parser(parser), m_model(*model), m_object(nullptr), @@ -137,6 +144,8 @@ struct AMFParserContext std::vector instances; }; + // Version of the amf file + unsigned int m_version; // Current Expat XML parser instance. XML_Parser m_parser; // Model to receive objects extracted from an AMF file. @@ -360,9 +369,9 @@ void AMFParserContext::endElement(const char * /* name */) case NODE_TYPE_VERTEX: assert(m_object); // Parse the vertex data - m_object_vertices.emplace_back(atof(m_value[0].c_str())); - m_object_vertices.emplace_back(atof(m_value[1].c_str())); - m_object_vertices.emplace_back(atof(m_value[2].c_str())); + m_object_vertices.emplace_back((float)atof(m_value[0].c_str())); + m_object_vertices.emplace_back((float)atof(m_value[1].c_str())); + m_object_vertices.emplace_back((float)atof(m_value[2].c_str())); m_value[0].clear(); m_value[1].clear(); m_value[2].clear(); @@ -462,6 +471,10 @@ void AMFParserContext::endElement(const char * /* name */) if (m_volume && m_value[0] == "name") m_volume->name = std::move(m_value[1]); } + else if (strncmp(m_value[0].c_str(), SLIC3RPE_AMF_VERSION, strlen(SLIC3RPE_AMF_VERSION)) == 0) { + m_version = (unsigned int)atoi(m_value[1].c_str()); + } + m_value[0].clear(); m_value[1].clear(); break; @@ -543,46 +556,8 @@ bool load_amf_file(const char *path, PresetBundle* bundle, Model *model) return result; } -// Load an AMF archive into a provided model. -bool load_amf_archive(const char *path, PresetBundle* bundle, Model *model) +bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, const char* path, PresetBundle* bundle, Model* model, unsigned int& version) { - if ((path == nullptr) || (model == nullptr)) - return false; - - mz_zip_archive archive; - mz_zip_zero_struct(&archive); - - mz_bool res = mz_zip_reader_init_file(&archive, path, 0); - if (res == 0) - { - printf("Unable to init zip reader\n"); - return false; - } - - mz_uint num_entries = mz_zip_reader_get_num_files(&archive); - if (num_entries != 1) - { - printf("Found invalid number of entries\n"); - mz_zip_reader_end(&archive); - return false; - } - - mz_zip_archive_file_stat stat; - res = mz_zip_reader_file_stat(&archive, 0, &stat); - if (res == 0) - { - printf("Unable to extract entry statistics\n"); - mz_zip_reader_end(&archive); - return false; - } - - if (!boost::iends_with(stat.m_filename, ".amf")) - { - printf("Found invalid internal filename\n"); - mz_zip_reader_end(&archive); - return false; - } - if (stat.m_uncomp_size == 0) { printf("Found invalid size\n"); @@ -610,7 +585,7 @@ bool load_amf_archive(const char *path, PresetBundle* bundle, Model *model) return false; } - res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, parser_buffer, (size_t)stat.m_uncomp_size, 0); + mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, parser_buffer, (size_t)stat.m_uncomp_size, 0); if (res == 0) { printf("Error while reading model data to buffer\n"); @@ -627,6 +602,62 @@ bool load_amf_archive(const char *path, PresetBundle* bundle, Model *model) ctx.endDocument(); + version = ctx.m_version; + + return true; +} + +// Load an AMF archive into a provided model. +bool load_amf_archive(const char *path, PresetBundle* bundle, Model *model) +{ + if ((path == nullptr) || (model == nullptr)) + return false; + + unsigned int version = 0; + + mz_zip_archive archive; + mz_zip_zero_struct(&archive); + + mz_bool res = mz_zip_reader_init_file(&archive, path, 0); + if (res == 0) + { + printf("Unable to init zip reader\n"); + return false; + } + + mz_uint num_entries = mz_zip_reader_get_num_files(&archive); + + mz_zip_archive_file_stat stat; + // we first loop the entries to read from the archive the .amf file only, in order to extract the version from it + for (mz_uint i = 0; i < num_entries; ++i) + { + if (mz_zip_reader_file_stat(&archive, i, &stat)) + { + if (boost::iends_with(stat.m_filename, ".amf")) + { + if (!extract_model_from_archive(archive, stat, path, bundle, model, version)) + { + mz_zip_reader_end(&archive); + printf("Archive does not contain a valid model"); + return false; + } + + break; + } + } + } + +#if 0 // forward compatibility + // we then loop again the entries to read other files stored in the archive + for (mz_uint i = 0; i < num_entries; ++i) + { + if (mz_zip_reader_file_stat(&archive, i, &stat)) + { + // add code to extract the file + } + } +#endif // forward compatibility + mz_zip_reader_end(&archive); return true; } @@ -664,6 +695,7 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c stream << "\n"; stream << "\n"; stream << "Slic3r " << SLIC3R_VERSION << "\n"; + stream << "" << VERSION_AMF << "\n"; if (export_print_config) { diff --git a/xs/src/libslic3r/GCode/Analyzer.cpp b/xs/src/libslic3r/GCode/Analyzer.cpp index 799bd6661..b7ecee5a4 100644 --- a/xs/src/libslic3r/GCode/Analyzer.cpp +++ b/xs/src/libslic3r/GCode/Analyzer.cpp @@ -718,10 +718,10 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ Helper::store_polyline(polyline, data, z, preview_data); // updates preview ranges data - preview_data.ranges.height.set_from(height_range); - preview_data.ranges.width.set_from(width_range); - preview_data.ranges.feedrate.set_from(feedrate_range); - preview_data.ranges.volumetric_rate.set_from(volumetric_rate_range); + preview_data.ranges.height.update_from(height_range); + preview_data.ranges.width.update_from(width_range); + preview_data.ranges.feedrate.update_from(feedrate_range); + preview_data.ranges.volumetric_rate.update_from(volumetric_rate_range); } void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data) @@ -790,9 +790,9 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data) Helper::store_polyline(polyline, type, direction, feedrate, extruder_id, preview_data); // updates preview ranges data - preview_data.ranges.height.set_from(height_range); - preview_data.ranges.width.set_from(width_range); - preview_data.ranges.feedrate.set_from(feedrate_range); + preview_data.ranges.height.update_from(height_range); + preview_data.ranges.width.update_from(width_range); + preview_data.ranges.feedrate.update_from(feedrate_range); } void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_data) diff --git a/xs/src/libslic3r/GCode/PreviewData.cpp b/xs/src/libslic3r/GCode/PreviewData.cpp index 69fd3524d..d431708c1 100644 --- a/xs/src/libslic3r/GCode/PreviewData.cpp +++ b/xs/src/libslic3r/GCode/PreviewData.cpp @@ -99,17 +99,31 @@ void GCodePreviewData::Range::set_from(const Range& other) float GCodePreviewData::Range::step_size() const { - return (max - min) / (float)Colors_Count; + return (max - min) / (float)(Colors_Count - 1); } -const GCodePreviewData::Color& GCodePreviewData::Range::get_color_at_max() const +GCodePreviewData::Color GCodePreviewData::Range::get_color_at(float value) const { - return colors[Colors_Count - 1]; -} + if (empty()) + return Color::Dummy; -const GCodePreviewData::Color& GCodePreviewData::Range::get_color_at(float value) const -{ - return empty() ? get_color_at_max() : colors[clamp((unsigned int)0, Colors_Count - 1, (unsigned int)((value - min) / step_size()))]; + float global_t = (value - min) / step_size(); + + unsigned int low = (unsigned int)global_t; + unsigned int high = clamp((unsigned int)0, Colors_Count - 1, low + 1); + + Color color_low = colors[low]; + Color color_high = colors[high]; + + float local_t = global_t - (float)low; + + // interpolate in RGB space + Color ret; + for (unsigned int i = 0; i < 4; ++i) + { + ret.rgba[i] = lerp(color_low.rgba[i], color_high.rgba[i], local_t); + } + return ret; } GCodePreviewData::LegendItem::LegendItem(const std::string& text, const GCodePreviewData::Color& color) @@ -266,22 +280,22 @@ const GCodePreviewData::Color& GCodePreviewData::get_extrusion_role_color(Extrus return extrusion.role_colors[role]; } -const GCodePreviewData::Color& GCodePreviewData::get_height_color(float height) const +GCodePreviewData::Color GCodePreviewData::get_height_color(float height) const { return ranges.height.get_color_at(height); } -const GCodePreviewData::Color& GCodePreviewData::get_width_color(float width) const +GCodePreviewData::Color GCodePreviewData::get_width_color(float width) const { return ranges.width.get_color_at(width); } -const GCodePreviewData::Color& GCodePreviewData::get_feedrate_color(float feedrate) const +GCodePreviewData::Color GCodePreviewData::get_feedrate_color(float feedrate) const { return ranges.feedrate.get_color_at(feedrate); } -const GCodePreviewData::Color& GCodePreviewData::get_volumetric_rate_color(float rate) const +GCodePreviewData::Color GCodePreviewData::get_volumetric_rate_color(float rate) const { return ranges.volumetric_rate.get_color_at(rate); } @@ -370,10 +384,10 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std:: list.reserve(Range::Colors_Count); float step = range.step_size(); - for (unsigned int i = 0; i < Range::Colors_Count; ++i) + for (int i = Range::Colors_Count - 1; i >= 0; --i) { char buf[1024]; - sprintf(buf, "%.*f/%.*f", decimals, scale_factor * (range.min + (float)i * step), decimals, scale_factor * (range.min + (float)(i + 1) * step)); + sprintf(buf, "%.*f", decimals, scale_factor * (range.min + (float)i * step)); list.emplace_back(buf, range.colors[i]); } } @@ -408,7 +422,7 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std:: } case Extrusion::Feedrate: { - Helper::FillListFromRange(items, ranges.feedrate, 0, 1.0f); + Helper::FillListFromRange(items, ranges.feedrate, 1, 1.0f); break; } case Extrusion::VolumetricRate: diff --git a/xs/src/libslic3r/GCode/PreviewData.hpp b/xs/src/libslic3r/GCode/PreviewData.hpp index e9c5f7515..a7d77e0b9 100644 --- a/xs/src/libslic3r/GCode/PreviewData.hpp +++ b/xs/src/libslic3r/GCode/PreviewData.hpp @@ -41,8 +41,7 @@ public: void set_from(const Range& other); float step_size() const; - const Color& get_color_at(float value) const; - const Color& get_color_at_max() const; + Color get_color_at(float value) const; }; struct Ranges @@ -189,10 +188,10 @@ public: bool empty() const; const Color& get_extrusion_role_color(ExtrusionRole role) const; - const Color& get_height_color(float height) const; - const Color& get_width_color(float width) const; - const Color& get_feedrate_color(float feedrate) const; - const Color& get_volumetric_rate_color(float rate) const; + Color get_height_color(float height) const; + Color get_width_color(float width) const; + Color get_feedrate_color(float feedrate) const; + Color get_volumetric_rate_color(float rate) const; void set_extrusion_role_color(const std::string& role_name, float red, float green, float blue, float alpha); void set_extrusion_paths_colors(const std::vector& colors); diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp index aaea863e8..a43bf0221 100644 --- a/xs/src/libslic3r/Model.cpp +++ b/xs/src/libslic3r/Model.cpp @@ -269,6 +269,10 @@ TriangleMesh Model::mesh() const static bool _arrange(const Pointfs &sizes, coordf_t dist, const BoundingBoxf* bb, Pointfs &out) { + if (sizes.empty()) + // return if the list is empty or the following call to BoundingBoxf constructor will lead to a crash + return true; + // we supply unscaled data to arrange() bool result = Slic3r::Geometry::arrange( sizes.size(), // number of parts diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index e692b1e9e..80f68c51b 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -598,10 +598,10 @@ std::string Print::validate() const return "The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1)."; SlicingParameters slicing_params0 = this->objects.front()->slicing_parameters(); - const PrintObject* most_layered_object = this->objects.front(); // object with highest layer_height_profile.size() encountered so far + const PrintObject* tallest_object = this->objects.front(); // let's find the tallest object for (const auto* object : objects) - if (object->layer_height_profile.size() > most_layered_object->layer_height_profile.size()) - most_layered_object = object; + if (*(object->layer_height_profile.end()-2) > *(tallest_object->layer_height_profile.end()-2) ) + tallest_object = object; for (PrintObject *object : this->objects) { SlicingParameters slicing_params = object->slicing_parameters(); @@ -618,17 +618,26 @@ std::string Print::validate() const object->update_layer_height_profile(); object->layer_height_profile_valid = was_layer_height_profile_valid; - if ( this->config.variable_layer_height ) { - int i = 0; - while ( i < object->layer_height_profile.size() ) { - if (std::abs(most_layered_object->layer_height_profile[i] - object->layer_height_profile[i]) > EPSILON) - return "The Wipe tower is only supported if all objects have the same layer height profile"; - ++i; - if (i == object->layer_height_profile.size()-2) // this element contains the objects max z, if the other object is taller, - // it does not have to match - we will step over it - if (most_layered_object->layer_height_profile[i] > object->layer_height_profile[i]) - ++i; + if ( this->config.variable_layer_height ) { // comparing layer height profiles + bool failed = false; + if (tallest_object->layer_height_profile.size() >= object->layer_height_profile.size() ) { + int i = 0; + while ( i < object->layer_height_profile.size() && i < tallest_object->layer_height_profile.size()) { + if (std::abs(tallest_object->layer_height_profile[i] - object->layer_height_profile[i])) { + failed = true; + break; + } + ++i; + if (i == object->layer_height_profile.size()-2) // this element contains this objects max z + if (tallest_object->layer_height_profile[i] > object->layer_height_profile[i]) // the difference does not matter in this case + ++i; + } } + else + failed = true; + + if (failed) + return "The Wipe tower is only supported if all objects have the same layer height profile"; } /*for (size_t i = 5; i < object->layer_height_profile.size(); i += 2) diff --git a/xs/src/libslic3r/TriangleMesh.cpp b/xs/src/libslic3r/TriangleMesh.cpp index aecb39662..45e4b6f5d 100644 --- a/xs/src/libslic3r/TriangleMesh.cpp +++ b/xs/src/libslic3r/TriangleMesh.cpp @@ -51,9 +51,6 @@ TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector& fa for (int i = 0; i < stl.stats.number_of_facets; i++) { stl_facet facet; - facet.normal.x = 0; - facet.normal.y = 0; - facet.normal.z = 0; const Pointf3& ref_f1 = points[facets[i].x]; facet.vertex[0].x = ref_f1.x; @@ -73,6 +70,13 @@ TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector& fa facet.extra[0] = 0; facet.extra[1] = 0; + float normal[3]; + stl_calculate_normal(normal, &facet); + stl_normalize_vector(normal); + facet.normal.x = normal[0]; + facet.normal.y = normal[1]; + facet.normal.z = normal[2]; + stl.facet_start[i] = facet; } stl_get_size(&stl); diff --git a/xs/src/libslic3r/Utils.hpp b/xs/src/libslic3r/Utils.hpp index f900137d3..0066aa5e6 100644 --- a/xs/src/libslic3r/Utils.hpp +++ b/xs/src/libslic3r/Utils.hpp @@ -62,6 +62,9 @@ extern std::string timestamp_str(); // to be placed at the top of Slic3r generated files. inline std::string header_slic3r_generated() { return std::string("generated by " SLIC3R_FORK_NAME " " SLIC3R_VERSION " " ) + timestamp_str(); } +// getpid platform wrapper +extern unsigned get_current_pid(); + // Compute the next highest power of 2 of 32-bit v // http://graphics.stanford.edu/~seander/bithacks.html template diff --git a/xs/src/libslic3r/utils.cpp b/xs/src/libslic3r/utils.cpp index 733757e25..f2415ac07 100644 --- a/xs/src/libslic3r/utils.cpp +++ b/xs/src/libslic3r/utils.cpp @@ -1,6 +1,12 @@ #include #include +#ifdef WIN32 +#include +#else +#include +#endif + #include #include #include @@ -271,4 +277,13 @@ std::string timestamp_str() return buf; } +unsigned get_current_pid() +{ +#ifdef WIN32 + return GetCurrentProcessId(); +#else + return ::getpid(); +#endif +} + }; // namespace Slic3r diff --git a/xs/src/semver/semver.c b/xs/src/semver/semver.c index a19354403..527738644 100644 --- a/xs/src/semver/semver.c +++ b/xs/src/semver/semver.c @@ -620,7 +620,7 @@ semver_numeric (semver_t *x) { return num; } -static char *semver_strdup(const char *src) { +char *semver_strdup(const char *src) { if (src == NULL) return NULL; size_t len = strlen(src) + 1; char *res = malloc(len); diff --git a/xs/src/semver/semver.h b/xs/src/semver/semver.h index 7251f51e3..01a15fc43 100644 --- a/xs/src/semver/semver.h +++ b/xs/src/semver/semver.h @@ -98,6 +98,9 @@ semver_is_valid (const char *s); int semver_clean (char *s); +char * +semver_strdup(const char *src); + semver_t semver_copy(const semver_t *ver); diff --git a/xs/src/slic3r/Config/Snapshot.cpp b/xs/src/slic3r/Config/Snapshot.cpp index 18329aa5c..704fbcfa1 100644 --- a/xs/src/slic3r/Config/Snapshot.cpp +++ b/xs/src/slic3r/Config/Snapshot.cpp @@ -117,11 +117,11 @@ void Snapshot::load_ini(const std::string &path) if (! semver) throw_on_parse_error("invalid " + kvp.first + " format for " + section.first); if (kvp.first == "version") - vc.version = *semver; + vc.version.config_version = *semver; else if (kvp.first == "min_slic3r_version") - vc.min_slic3r_version = *semver; + vc.version.min_slic3r_version = *semver; else - vc.max_slic3r_version = *semver; + vc.version.max_slic3r_version = *semver; } else if (boost::starts_with(kvp.first, key_prefix_model) && kvp.first.size() > key_prefix_model.size()) { // Parse the printer variants installed for the current model. auto &set_variants = vc.models_variants_installed[kvp.first.substr(key_prefix_model.size())]; @@ -181,9 +181,9 @@ void Snapshot::save_ini(const std::string &path) // Export the vendor configs. for (const VendorConfig &vc : this->vendor_configs) { c << std::endl << "[Vendor:" << vc.name << "]" << std::endl; - c << "version = " << vc.version.to_string() << std::endl; - c << "min_slic3r_version = " << vc.min_slic3r_version.to_string() << std::endl; - c << "max_slic3r_version = " << vc.max_slic3r_version.to_string() << std::endl; + c << "version = " << vc.version.config_version.to_string() << std::endl; + c << "min_slic3r_version = " << vc.version.min_slic3r_version.to_string() << std::endl; + c << "max_slic3r_version = " << vc.version.max_slic3r_version.to_string() << std::endl; // Export installed printer models and their variants. for (const auto &model : vc.models_variants_installed) { if (model.second.size() == 0) @@ -326,10 +326,10 @@ void SnapshotDB::update_slic3r_versions(std::vector &index_db) for (Snapshot::VendorConfig &vendor_config : snapshot.vendor_configs) { auto it = std::find_if(index_db.begin(), index_db.end(), [&vendor_config](const Index &idx) { return idx.vendor() == vendor_config.name; }); if (it != index_db.end()) { - Index::const_iterator it_version = it->find(vendor_config.version); + Index::const_iterator it_version = it->find(vendor_config.version.config_version); if (it_version != it->end()) { - vendor_config.min_slic3r_version = it_version->min_slic3r_version; - vendor_config.max_slic3r_version = it_version->max_slic3r_version; + vendor_config.version.min_slic3r_version = it_version->min_slic3r_version; + vendor_config.version.max_slic3r_version = it_version->max_slic3r_version; } } } @@ -395,16 +395,16 @@ const Snapshot& SnapshotDB::take_snapshot(const AppConfig &app_config, Snapshot: bundle.load_configbundle((data_dir / "vendor" / (cfg.name + ".ini")).string(), PresetBundle::LOAD_CFGBUNDLE_VENDOR_ONLY); for (const VendorProfile &vp : bundle.vendors) if (vp.id == cfg.name) - cfg.version = vp.config_version; + cfg.version.config_version = vp.config_version; // Fill-in the min/max slic3r version from the config index, if possible. try { // Load the config index for the vendor. Index index; index.load(data_dir / "vendor" / (cfg.name + ".idx")); - auto it = index.find(cfg.version); + auto it = index.find(cfg.version.config_version); if (it != index.end()) { - cfg.min_slic3r_version = it->min_slic3r_version; - cfg.max_slic3r_version = it->max_slic3r_version; + cfg.version.min_slic3r_version = it->min_slic3r_version; + cfg.version.max_slic3r_version = it->max_slic3r_version; } } catch (const std::runtime_error &err) { } @@ -476,7 +476,7 @@ SnapshotDB::const_iterator SnapshotDB::snapshot_with_vendor_preset(const std::st auto it_vendor_config = std::lower_bound(snapshot.vendor_configs.begin(), snapshot.vendor_configs.end(), key, [](const Snapshot::VendorConfig &cfg1, const Snapshot::VendorConfig &cfg2) { return cfg1.name < cfg2.name; }); if (it_vendor_config != snapshot.vendor_configs.end() && it_vendor_config->name == vendor_name && - config_version == it_vendor_config->version) { + config_version == it_vendor_config->version.config_version) { // Vendor config found with the correct version. // Save it, but continue searching, as we want the newest snapshot. it_found = it; diff --git a/xs/src/slic3r/Config/Snapshot.hpp b/xs/src/slic3r/Config/Snapshot.hpp index 77aee3e21..a916dfe92 100644 --- a/xs/src/slic3r/Config/Snapshot.hpp +++ b/xs/src/slic3r/Config/Snapshot.hpp @@ -18,7 +18,6 @@ class AppConfig; namespace GUI { namespace Config { -class Version; class Index; // A snapshot contains: @@ -76,12 +75,8 @@ public: struct VendorConfig { // Name of the vendor contained in this snapshot. std::string name; - // Version of the vendor config contained in this snapshot. - Semver version = Semver::invalid(); - // Minimum Slic3r version compatible with this vendor configuration. - Semver min_slic3r_version = Semver::zero(); - // Maximum Slic3r version compatible with this vendor configuration, or empty. - Semver max_slic3r_version = Semver::inf(); + // Version of the vendor config contained in this snapshot, along with compatibility data. + Version version; // Which printer models of this vendor were installed, and which variants of the models? std::map> models_variants_installed; }; diff --git a/xs/src/slic3r/Config/Version.cpp b/xs/src/slic3r/Config/Version.cpp index dc09ac870..a85322eca 100644 --- a/xs/src/slic3r/Config/Version.cpp +++ b/xs/src/slic3r/Config/Version.cpp @@ -13,7 +13,7 @@ namespace Slic3r { namespace GUI { namespace Config { -static boost::optional s_current_slic3r_semver = Semver::parse(SLIC3R_VERSION); +static const Semver s_current_slic3r_semver(SLIC3R_VERSION); // Optimized lexicographic compare of two pre-release versions, ignoring the numeric suffix. static int compare_prerelease(const char *p1, const char *p2) @@ -62,7 +62,7 @@ bool Version::is_slic3r_supported(const Semver &slic3r_version) const bool Version::is_current_slic3r_supported() const { - return this->is_slic3r_supported(*s_current_slic3r_semver); + return this->is_slic3r_supported(s_current_slic3r_semver); } #if 0 diff --git a/xs/src/slic3r/GUI/2DBed.hpp b/xs/src/slic3r/GUI/2DBed.hpp index a170b708a..4b14986a2 100644 --- a/xs/src/slic3r/GUI/2DBed.hpp +++ b/xs/src/slic3r/GUI/2DBed.hpp @@ -1,3 +1,6 @@ +#ifndef slic3r_2DBed_hpp_ +#define slic3r_2DBed_hpp_ + #include #include "Config.hpp" @@ -45,3 +48,5 @@ public: } // GUI } // Slic3r + +#endif /* slic3r_2DBed_hpp_ */ diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index 7f5e632bb..6b2f5c830 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -443,13 +443,16 @@ std::vector GLVolumeCollection::load_object( int GLVolumeCollection::load_wipe_tower_preview( int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs) { - float color[4] = { 1.0f, 1.0f, 0.0f, 0.5f }; + float color[4] = { 0.5f, 0.5f, 0.0f, 0.5f }; this->volumes.emplace_back(new GLVolume(color)); GLVolume &v = *this->volumes.back(); - auto mesh = make_cube(width, depth, height); - mesh.translate(-width/2.f,-depth/2.f,0.f); - Point origin_of_rotation(0.f,0.f); + if (height == 0.0f) + height = 0.1f; + + auto mesh = make_cube(width, depth, height); + mesh.translate(-width / 2.f, -depth / 2.f, 0.f); + Point origin_of_rotation(0.f, 0.f); mesh.rotate(rotation_angle,&origin_of_rotation); if (use_VBOs) @@ -751,7 +754,10 @@ std::vector GLVolumeCollection::get_current_print_zs() const // Collect layer top positions of all volumes. std::vector print_zs; for (GLVolume *vol : this->volumes) - append(print_zs, vol->print_zs); + { + if (vol->is_active) + append(print_zs, vol->print_zs); + } std::sort(print_zs.begin(), print_zs.end()); // Replace intervals of layers with similar top positions with their average value. @@ -1757,6 +1763,11 @@ void _3DScene::load_gcode_preview(const Print* print, const GCodePreviewData* pr { _generate_legend_texture(*preview_data, tool_colors); _load_shells(*print, *volumes, use_VBOs); + + // removes empty volumes + volumes->volumes.erase(std::remove_if(volumes->volumes.begin(), volumes->volumes.end(), + [](const GLVolume *volume) { return volume->print_zs.empty(); }), + volumes->volumes.end()); } } diff --git a/xs/src/slic3r/GUI/AboutDialog.cpp b/xs/src/slic3r/GUI/AboutDialog.cpp index 664bbd1bb..e3c452872 100644 --- a/xs/src/slic3r/GUI/AboutDialog.cpp +++ b/xs/src/slic3r/GUI/AboutDialog.cpp @@ -31,13 +31,14 @@ void AboutDialogLogo::onRepaint(wxEvent &event) AboutDialog::AboutDialog() : wxDialog(NULL, wxID_ANY, _(L("About Slic3r")), wxDefaultPosition, wxSize(600, 340), wxCAPTION) { - this->SetBackgroundColour(*wxWHITE); - + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)/**wxWHITE*/); wxBoxSizer* hsizer = new wxBoxSizer(wxHORIZONTAL); this->SetSizer(hsizer); // logo - AboutDialogLogo* logo = new AboutDialogLogo(this); +// AboutDialogLogo* logo = new AboutDialogLogo(this); + wxBitmap logo_bmp = wxBitmap(from_u8(Slic3r::var("Slic3r_192px.png")), wxBITMAP_TYPE_PNG); + auto *logo = new wxStaticBitmap(this, wxID_ANY, std::move(logo_bmp)); hsizer->Add(logo, 0, wxEXPAND | wxLEFT | wxRIGHT, 30); wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL); @@ -56,7 +57,7 @@ AboutDialog::AboutDialog() // version { - auto version_string = _(L("Version ")) + std::string(SLIC3R_VERSION); + auto version_string = _(L("Version"))+ " " + std::string(SLIC3R_VERSION); wxStaticText* version = new wxStaticText(this, wxID_ANY, version_string.c_str(), wxDefaultPosition, wxDefaultSize); wxFont version_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); #ifdef __WXMSW__ @@ -78,6 +79,7 @@ AboutDialog::AboutDialog() int size[] = {11,11,11,11,11,11,11}; #endif html->SetFonts(font.GetFaceName(), font.GetFaceName(), size); + html->SetHTMLBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); html->SetBorders(2); const char* text = "" @@ -106,7 +108,6 @@ AboutDialog::AboutDialog() this->Bind(wxEVT_LEFT_DOWN, &AboutDialog::onCloseDialog, this); logo->Bind(wxEVT_LEFT_DOWN, &AboutDialog::onCloseDialog, this); - html->Bind(wxEVT_LEFT_DOWN, &AboutDialog::onCloseDialog, this); } void AboutDialog::onLinkClicked(wxHtmlLinkEvent &event) diff --git a/xs/src/slic3r/GUI/AppConfig.cpp b/xs/src/slic3r/GUI/AppConfig.cpp index 100b2d69b..70f4ba110 100644 --- a/xs/src/slic3r/GUI/AppConfig.cpp +++ b/xs/src/slic3r/GUI/AppConfig.cpp @@ -21,6 +21,7 @@ namespace Slic3r { static const std::string VENDOR_PREFIX = "vendor:"; static const std::string MODEL_PREFIX = "model:"; +static const std::string VERSION_CHECK_URL = "https://raw.githubusercontent.com/prusa3d/Slic3r-settings/master/live/Slic3rPE.version"; void AppConfig::reset() { @@ -49,9 +50,6 @@ void AppConfig::set_defaults() if (get("version_check").empty()) set("version_check", "1"); - // TODO: proper URL - if (get("version_check_url").empty()) - set("version_check_url", "https://gist.githubusercontent.com/vojtechkral/4d8fd4a3b8699a01ec892c264178461c/raw/2f05a64db19e45a7f8fe2cedeff555d544af679b/slic3rPE.version"); if (get("preset_update").empty()) set("preset_update", "1"); @@ -100,7 +98,13 @@ void AppConfig::load() // Figure out if datadir has legacy presets auto ini_ver = Semver::parse(get("version")); - m_legacy_datadir = ini_ver ? *ini_ver < Semver(1, 40, 0) : true; + m_legacy_datadir = false; + if (ini_ver) { + // Make 1.40.0 alphas compare well + ini_ver->set_metadata(boost::none); + ini_ver->set_prerelease(boost::none); + m_legacy_datadir = ini_ver < Semver(1, 40, 0); + } // Override missing or keys with their defaults. this->set_defaults(); @@ -235,6 +239,12 @@ std::string AppConfig::config_path() return (boost::filesystem::path(Slic3r::data_dir()) / "slic3r.ini").make_preferred().string(); } +std::string AppConfig::version_check_url() const +{ + auto from_settings = get("version_check_url"); + return from_settings.empty() ? VERSION_CHECK_URL : from_settings; +} + bool AppConfig::exists() { return boost::filesystem::exists(AppConfig::config_path()); diff --git a/xs/src/slic3r/GUI/AppConfig.hpp b/xs/src/slic3r/GUI/AppConfig.hpp index 6dcfec046..16469f0e9 100644 --- a/xs/src/slic3r/GUI/AppConfig.hpp +++ b/xs/src/slic3r/GUI/AppConfig.hpp @@ -92,9 +92,14 @@ public: // Get the default config path from Slic3r::data_dir(). static std::string config_path(); - + + // Returns true if the user's data directory comes from before Slic3r 1.40.0 (no updating) bool legacy_datadir() const { return m_legacy_datadir; } + // Get the Slic3r version check url. + // This returns a hardcoded string unless it is overriden by "version_check_url" in the ini file. + std::string version_check_url() const; + // Does the config file exist? static bool exists(); diff --git a/xs/src/slic3r/GUI/BedShapeDialog.hpp b/xs/src/slic3r/GUI/BedShapeDialog.hpp index f4614c342..5ff488063 100644 --- a/xs/src/slic3r/GUI/BedShapeDialog.hpp +++ b/xs/src/slic3r/GUI/BedShapeDialog.hpp @@ -1,3 +1,5 @@ +#ifndef slic3r_BedShapeDialog_hpp_ +#define slic3r_BedShapeDialog_hpp_ // The bed shape dialog. // The dialog opens from Print Settins tab->Bed Shape : Set... @@ -49,3 +51,6 @@ public: } // GUI } // Slic3r + + +#endif /* slic3r_BedShapeDialog_hpp_ */ diff --git a/xs/src/slic3r/GUI/BonjourDialog.cpp b/xs/src/slic3r/GUI/BonjourDialog.cpp index 34fac9a91..11cfea642 100644 --- a/xs/src/slic3r/GUI/BonjourDialog.cpp +++ b/xs/src/slic3r/GUI/BonjourDialog.cpp @@ -191,7 +191,7 @@ void BonjourDialog::on_timer(wxTimerEvent &) label->SetLabel(wxString::Format("%s %s", search_str, dots)); timer_state = (timer_state) % 3 + 1; } else { - label->SetLabel(wxString::Format("%s: %s", search_str, _(L("Finished.")))); + label->SetLabel(wxString::Format("%s: %s", search_str, _(L("Finished"))+".")); timer->Stop(); } } diff --git a/xs/src/slic3r/GUI/ButtonsDescription.cpp b/xs/src/slic3r/GUI/ButtonsDescription.cpp new file mode 100644 index 000000000..5739fc90e --- /dev/null +++ b/xs/src/slic3r/GUI/ButtonsDescription.cpp @@ -0,0 +1,84 @@ +#include "ButtonsDescription.hpp" +#include +#include +#include +#include + +#include "GUI.hpp" + +namespace Slic3r { +namespace GUI { + +ButtonsDescription::ButtonsDescription(wxWindow* parent, t_icon_descriptions* icon_descriptions) : + wxDialog(parent, wxID_ANY, _(L("Buttons And Text Colors Description")), wxDefaultPosition, wxDefaultSize), + m_icon_descriptions(icon_descriptions) +{ + auto grid_sizer = new wxFlexGridSizer(3, 20, 20); + + auto main_sizer = new wxBoxSizer(wxVERTICAL); + main_sizer->Add(grid_sizer, 0, wxEXPAND | wxALL, 20); + + // Icon description + for (auto pair : *m_icon_descriptions) + { + auto icon = new wxStaticBitmap(this, wxID_ANY, *pair.first); + grid_sizer->Add(icon, -1, wxALIGN_CENTRE_VERTICAL); + + std::istringstream f(pair.second); + std::string s; + getline(f, s, ';'); + auto description = new wxStaticText(this, wxID_ANY, _(s)); + grid_sizer->Add(description, -1, wxALIGN_CENTRE_VERTICAL); + getline(f, s, ';'); + description = new wxStaticText(this, wxID_ANY, _(s)); + grid_sizer->Add(description, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND); + } + + // Text color description + auto sys_label = new wxStaticText(this, wxID_ANY, _(L("Value is the same as the system value"))); + sys_label->SetForegroundColour(get_label_clr_sys()); + auto sys_colour = new wxColourPickerCtrl(this, wxID_ANY, get_label_clr_sys()); + sys_colour->Bind(wxEVT_COLOURPICKER_CHANGED, ([sys_colour, sys_label](wxCommandEvent e) + { + sys_label->SetForegroundColour(sys_colour->GetColour()); + sys_label->Refresh(); + })); + size_t t= 0; + while (t < 3){ + grid_sizer->Add(new wxStaticText(this, wxID_ANY, ""), -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND); + ++t; + } + grid_sizer->Add(0, -1, wxALIGN_CENTRE_VERTICAL); + grid_sizer->Add(sys_colour, -1, wxALIGN_CENTRE_VERTICAL); + grid_sizer->Add(sys_label, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND); + + auto mod_label = new wxStaticText(this, wxID_ANY, _(L("Value was changed and is not equal to the system value or the last saved preset"))); + mod_label->SetForegroundColour(get_label_clr_modified()); + auto mod_colour = new wxColourPickerCtrl(this, wxID_ANY, get_label_clr_modified()); + mod_colour->Bind(wxEVT_COLOURPICKER_CHANGED, ([mod_colour, mod_label](wxCommandEvent e) + { + mod_label->SetForegroundColour(mod_colour->GetColour()); + mod_label->Refresh(); + })); + grid_sizer->Add(0, -1, wxALIGN_CENTRE_VERTICAL); + grid_sizer->Add(mod_colour, -1, wxALIGN_CENTRE_VERTICAL); + grid_sizer->Add(mod_label, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND); + + + auto buttons = CreateStdDialogButtonSizer(wxOK|wxCANCEL); + main_sizer->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10); + + wxButton* btn = static_cast(FindWindowById(wxID_OK, this)); + btn->Bind(wxEVT_BUTTON, [sys_colour, mod_colour, this](wxCommandEvent&) { + set_label_clr_sys(sys_colour->GetColour()); + set_label_clr_modified(mod_colour->GetColour()); + EndModal(wxID_OK); + }); + + SetSizer(main_sizer); + main_sizer->SetSizeHints(this); +} + +} // GUI +} // Slic3r + diff --git a/xs/src/slic3r/GUI/ButtonsDescription.hpp b/xs/src/slic3r/GUI/ButtonsDescription.hpp new file mode 100644 index 000000000..4858eaaea --- /dev/null +++ b/xs/src/slic3r/GUI/ButtonsDescription.hpp @@ -0,0 +1,27 @@ +#ifndef slic3r_ButtonsDescription_hpp +#define slic3r_ButtonsDescription_hpp + +#include +#include + +namespace Slic3r { +namespace GUI { + +using t_icon_descriptions = std::vector>; + +class ButtonsDescription : public wxDialog +{ + t_icon_descriptions* m_icon_descriptions; +public: + ButtonsDescription(wxWindow* parent, t_icon_descriptions* icon_descriptions); + ~ButtonsDescription(){} + + +}; + +} // GUI +} // Slic3r + + +#endif + diff --git a/xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp b/xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp index 99af707e1..efcbf05bd 100644 --- a/xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp +++ b/xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp @@ -8,49 +8,48 @@ namespace Slic3r { namespace GUI { -static std::string format_reason(const Config::Snapshot::Reason reason) +static wxString format_reason(const Config::Snapshot::Reason reason) { switch (reason) { case Config::Snapshot::SNAPSHOT_UPGRADE: - return std::string(_(L("Upgrade"))); + return wxString(_(L("Upgrade"))); case Config::Snapshot::SNAPSHOT_DOWNGRADE: - return std::string(_(L("Downgrade"))); + return wxString(_(L("Downgrade"))); case Config::Snapshot::SNAPSHOT_BEFORE_ROLLBACK: - return std::string(_(L("Before roll back"))); + return wxString(_(L("Before roll back"))); case Config::Snapshot::SNAPSHOT_USER: - return std::string(_(L("User"))); + return wxString(_(L("User"))); case Config::Snapshot::SNAPSHOT_UNKNOWN: default: - return std::string(_(L("Unknown"))); + return wxString(_(L("Unknown"))); } } -static std::string generate_html_row(const Config::Snapshot &snapshot, bool row_even, bool snapshot_active) +static wxString generate_html_row(const Config::Snapshot &snapshot, bool row_even, bool snapshot_active) { // Start by declaring a row with an alternating background color. - std::string text = ""; text += ""; // Format the row header. - text += std::string("") + (snapshot_active ? _(L("Active: ")) : "") + + text += wxString("") + (snapshot_active ? _(L("Active: ")) : "") + Utils::format_local_date_time(snapshot.time_captured) + ": " + format_reason(snapshot.reason); if (! snapshot.comment.empty()) text += " (" + snapshot.comment + ")"; text += "
"; // End of row header. -// text += _(L("ID:")) + " " + snapshot.id + "
"; - // text += _(L("time captured:")) + " " + Utils::format_local_date_time(snapshot.time_captured) + "
"; text += _(L("slic3r version")) + ": " + snapshot.slic3r_version_captured.to_string() + "
"; -// text += "reason: " + snapshot.reason + "
"; text += _(L("print")) + ": " + snapshot.print + "
"; text += _(L("filaments")) + ": " + snapshot.filaments.front() + "
"; text += _(L("printer")) + ": " + snapshot.printer + "
"; + bool compatible = true; for (const Config::Snapshot::VendorConfig &vc : snapshot.vendor_configs) { - text += _(L("vendor")) + ": " + vc.name + ", ver: " + vc.version.to_string() + ", min slic3r ver: " + vc.min_slic3r_version.to_string(); - if (vc.max_slic3r_version != Semver::inf()) - text += ", max slic3r ver: " + vc.max_slic3r_version.to_string(); + text += _(L("vendor")) + ": " + vc.name +", " + _(L("version")) + ": " + vc.version.config_version.to_string() + + ", " + _(L("min slic3r version")) + ": " + vc.version.min_slic3r_version.to_string(); + if (vc.version.max_slic3r_version != Semver::inf()) + text += ", " + _(L("max slic3r version")) + ": " + vc.version.max_slic3r_version.to_string(); text += "
"; for (const std::pair> &model : vc.models_variants_installed) { text += _(L("model")) + ": " + model.first + ", " + _(L("variants")) + ": "; @@ -61,18 +60,22 @@ static std::string generate_html_row(const Config::Snapshot &snapshot, bool row_ } text += "
"; } + if (! vc.version.is_current_slic3r_supported()) { compatible = false; } } - if (! snapshot_active) + if (! compatible) { + text += "

" + _(L("Incompatible with this Slic3r")) + "

"; + } + else if (! snapshot_active) text += "

" + _(L("Activate")) + "

"; text += ""; text += ""; return text; } -static std::string generate_html_page(const Config::SnapshotDB &snapshot_db, const std::string &on_snapshot) +static wxString generate_html_page(const Config::SnapshotDB &snapshot_db, const wxString &on_snapshot) { - std::string text = + wxString text = "" "" ""; @@ -89,7 +92,7 @@ static std::string generate_html_page(const Config::SnapshotDB &snapshot_db, con return text; } -ConfigSnapshotDialog::ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db, const std::string &on_snapshot) +ConfigSnapshotDialog::ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db, const wxString &on_snapshot) : wxDialog(NULL, wxID_ANY, _(L("Configuration Snapshots")), wxDefaultPosition, wxSize(600, 500), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX) { this->SetBackgroundColour(*wxWHITE); @@ -108,8 +111,8 @@ ConfigSnapshotDialog::ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db #endif html->SetFonts(font.GetFaceName(), font.GetFaceName(), size); html->SetBorders(2); - std::string text = generate_html_page(snapshot_db, on_snapshot); - html->SetPage(text.c_str()); + wxString text = generate_html_page(snapshot_db, on_snapshot); + html->SetPage(text); vsizer->Add(html, 1, wxEXPAND | wxALIGN_LEFT | wxRIGHT | wxBOTTOM, 0); html->Bind(wxEVT_HTML_LINK_CLICKED, &ConfigSnapshotDialog::onLinkClicked, this); } diff --git a/xs/src/slic3r/GUI/ConfigSnapshotDialog.hpp b/xs/src/slic3r/GUI/ConfigSnapshotDialog.hpp index 943601e73..f43fb8ed1 100644 --- a/xs/src/slic3r/GUI/ConfigSnapshotDialog.hpp +++ b/xs/src/slic3r/GUI/ConfigSnapshotDialog.hpp @@ -17,7 +17,7 @@ namespace Config { class ConfigSnapshotDialog : public wxDialog { public: - ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db, const std::string &id); + ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db, const wxString &id); const std::string& snapshot_to_activate() const { return m_snapshot_to_activate; } private: diff --git a/xs/src/slic3r/GUI/ConfigWizard.cpp b/xs/src/slic3r/GUI/ConfigWizard.cpp index 0eee234db..1217f8683 100644 --- a/xs/src/slic3r/GUI/ConfigWizard.cpp +++ b/xs/src/slic3r/GUI/ConfigWizard.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include #include #include @@ -205,15 +207,16 @@ PageWelcome::PageWelcome(ConfigWizard *parent) : ConfigWizardPage(parent, wxString::Format(_(L("Welcome to the Slic3r %s")), ConfigWizard::name()), _(L("Welcome"))), printer_picker(nullptr), others_buttons(new wxPanel(parent)), - cbox_reset(new wxCheckBox(this, wxID_ANY, _(L("Remove user profiles - install from scratch (a snapshot will be taken beforehand)")))) + cbox_reset(nullptr) { - if (wizard_p()->flag_startup && wizard_p()->flag_empty_datadir) { + if (wizard_p()->run_reason == ConfigWizard::RR_DATA_EMPTY) { wxString::Format(_(L("Run %s")), ConfigWizard::name()); append_text(wxString::Format( _(L("Hello, welcome to Slic3r Prusa Edition! This %s helps you with the initial configuration; just a few settings and you will be ready to print.")), ConfigWizard::name()) ); } else { + cbox_reset = new wxCheckBox(this, wxID_ANY, _(L("Remove user profiles - install from scratch (a snapshot will be taken beforehand)"))); append(cbox_reset); } @@ -708,7 +711,7 @@ void ConfigWizard::priv::on_custom_setup() set_page(page_firmware); } -void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *preset_bundle, PresetUpdater *updater) +void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater) { const bool is_custom_setup = page_welcome->page_next() == page_firmware; @@ -729,22 +732,30 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese install_bundles.emplace_back(vendor_rsrc.second); } - // If the datadir was empty don't take a snapshot (it would just be an empty snapshot) - const bool snapshot = !flag_empty_datadir || page_welcome->reset_user_profile(); + // Decide whether to create snapshot based on run_reason and the reset profile checkbox + bool snapshot = true; + switch (run_reason) { + case ConfigWizard::RR_DATA_EMPTY: snapshot = false; break; + case ConfigWizard::RR_DATA_LEGACY: snapshot = true; break; + case ConfigWizard::RR_DATA_INCOMPAT: snapshot = false; break; // In this case snapshot is done by PresetUpdater with the appropriate reason + case ConfigWizard::RR_USER: snapshot = page_welcome->reset_user_profile(); break; + } if (install_bundles.size() > 0) { // Install bundles from resources. updater->install_bundles_rsrc(std::move(install_bundles), snapshot); + } else { + BOOST_LOG_TRIVIAL(info) << "No bundles need to be installed from resources"; } if (page_welcome->reset_user_profile()) { + BOOST_LOG_TRIVIAL(info) << "Resetting user profiles..."; preset_bundle->reset(true); } app_config->set_vendors(appconfig_vendors); app_config->set("version_check", page_update->version_check ? "1" : "0"); app_config->set("preset_update", page_update->preset_update ? "1" : "0"); - if (flag_startup) - app_config->reset_selections(); + app_config->reset_selections(); // ^ TODO: replace with appropriate printer selection preset_bundle->load_presets(*app_config); } else { @@ -759,12 +770,11 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese // Public -ConfigWizard::ConfigWizard(wxWindow *parent, bool startup, bool empty_datadir) : +ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) : wxDialog(parent, wxID_ANY, name(), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), p(new priv(this)) { - p->flag_startup = startup; - p->flag_empty_datadir = empty_datadir; + p->run_reason = reason; p->load_vendors(); p->custom_config.reset(DynamicPrintConfig::new_from_defaults_keys({ @@ -821,10 +831,16 @@ ConfigWizard::ConfigWizard(wxWindow *parent, bool startup, bool empty_datadir) : ConfigWizard::~ConfigWizard() {} -void ConfigWizard::run(PresetBundle *preset_bundle, PresetUpdater *updater) +bool ConfigWizard::run(PresetBundle *preset_bundle, const PresetUpdater *updater) { + BOOST_LOG_TRIVIAL(info) << "Running ConfigWizard, reason: " << p->run_reason; if (ShowModal() == wxID_OK) { p->apply_config(GUI::get_app_config(), preset_bundle, updater); + BOOST_LOG_TRIVIAL(info) << "ConfigWizard applied"; + return true; + } else { + BOOST_LOG_TRIVIAL(info) << "ConfigWizard cancelled"; + return false; } } diff --git a/xs/src/slic3r/GUI/ConfigWizard.hpp b/xs/src/slic3r/GUI/ConfigWizard.hpp index eeb64c57f..73fce7cd2 100644 --- a/xs/src/slic3r/GUI/ConfigWizard.hpp +++ b/xs/src/slic3r/GUI/ConfigWizard.hpp @@ -16,14 +16,23 @@ namespace GUI { class ConfigWizard: public wxDialog { public: - ConfigWizard(wxWindow *parent, bool startup, bool empty_datadir); + // Why is the Wizard run + enum RunReason { + RR_DATA_EMPTY, // No or empty datadir + RR_DATA_LEGACY, // Pre-updating datadir + RR_DATA_INCOMPAT, // Incompatible datadir - Slic3r downgrade situation + RR_USER, // User requested the Wizard from the menus + }; + + ConfigWizard(wxWindow *parent, RunReason run_reason); ConfigWizard(ConfigWizard &&) = delete; ConfigWizard(const ConfigWizard &) = delete; ConfigWizard &operator=(ConfigWizard &&) = delete; ConfigWizard &operator=(const ConfigWizard &) = delete; ~ConfigWizard(); - void run(PresetBundle *preset_bundle, PresetUpdater *updater); + // Run the Wizard. Return whether it was completed. + bool run(PresetBundle *preset_bundle, const PresetUpdater *updater); static const wxString& name(); private: diff --git a/xs/src/slic3r/GUI/ConfigWizard_private.hpp b/xs/src/slic3r/GUI/ConfigWizard_private.hpp index 8e43ac3ac..474394bc3 100644 --- a/xs/src/slic3r/GUI/ConfigWizard_private.hpp +++ b/xs/src/slic3r/GUI/ConfigWizard_private.hpp @@ -107,7 +107,7 @@ struct PageWelcome: ConfigWizardPage virtual wxPanel* extra_buttons() { return others_buttons; } virtual void on_page_set(); - bool reset_user_profile() const { return cbox_reset->GetValue(); } + bool reset_user_profile() const { return cbox_reset != nullptr ? cbox_reset->GetValue() : false; } void on_variant_checked(); }; @@ -190,8 +190,7 @@ private: struct ConfigWizard::priv { ConfigWizard *q; - bool flag_startup; - bool flag_empty_datadir; + ConfigWizard::RunReason run_reason; AppConfig appconfig_vendors; std::unordered_map vendors; std::unordered_map vendors_rsrc; @@ -228,7 +227,7 @@ struct ConfigWizard::priv void on_other_vendors(); void on_custom_setup(); - void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, PresetUpdater *updater); + void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater); }; diff --git a/xs/src/slic3r/GUI/Field.cpp b/xs/src/slic3r/GUI/Field.cpp index c68b2304c..5cae9172e 100644 --- a/xs/src/slic3r/GUI/Field.cpp +++ b/xs/src/slic3r/GUI/Field.cpp @@ -20,21 +20,22 @@ namespace Slic3r { namespace GUI { void Field::PostInitialize(){ auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - m_Undo_btn = new wxButton(m_parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); - m_Undo_to_sys_btn = new wxButton(m_parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); + m_Undo_btn = new MyButton(m_parent, wxID_ANY, "", wxDefaultPosition,wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); + m_Undo_to_sys_btn = new MyButton(m_parent, wxID_ANY, "", wxDefaultPosition,wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); if (wxMSW) { m_Undo_btn->SetBackgroundColour(color); m_Undo_to_sys_btn->SetBackgroundColour(color); } - m_Undo_btn->SetBitmap(wxBitmap(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG)); m_Undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_initial_value(); })); m_Undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_sys_value(); })); - BUILD(); - } + //set default bitmap + wxBitmap bmp; + bmp.LoadFile(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG); + set_undo_bitmap(&bmp); + set_undo_to_sys_bitmap(&bmp); - void Field::set_nonsys_btn_icon(const std::string& icon){ - m_Undo_to_sys_btn->SetBitmap(wxBitmap(from_u8(var(icon)), wxBITMAP_TYPE_PNG)); + BUILD(); } void Field::on_kill_focus(wxEvent& event) { @@ -81,12 +82,13 @@ namespace Slic3r { namespace GUI { return std::regex_match(string, regex_pattern); } - boost::any Field::get_value_by_opt_type(wxString& str) +// boost::any Field::get_value_by_opt_type(wxString& str) + void Field::get_value_by_opt_type(wxString& str) { - boost::any ret_val; +// boost::any m_value; switch (m_opt.type){ case coInt: - ret_val = wxAtoi(str); + m_value = wxAtoi(str); break; case coPercent: case coPercents: @@ -96,18 +98,18 @@ namespace Slic3r { namespace GUI { str.RemoveLast(); double val; str.ToCDouble(&val); - ret_val = val; + m_value = val; break; } case coString: case coStrings: case coFloatOrPercent: - ret_val = str.ToStdString(); + m_value = str.ToStdString(); break; default: break; } - return ret_val; +// return m_value; } void TextCtrl::BUILD() { @@ -183,12 +185,12 @@ namespace Slic3r { namespace GUI { window = dynamic_cast(temp); } - boost::any TextCtrl::get_value() + boost::any& TextCtrl::get_value() { wxString ret_str = static_cast(window)->GetValue(); - boost::any ret_val = get_value_by_opt_type(ret_str); + /*boost::any ret_val*/get_value_by_opt_type(ret_str); - return ret_val; + return m_value;//ret_val; } void TextCtrl::enable() { dynamic_cast(window)->Enable(); dynamic_cast(window)->SetEditable(true); } @@ -216,15 +218,15 @@ void CheckBox::BUILD() { window = dynamic_cast(temp); } -boost::any CheckBox::get_value() +boost::any& CheckBox::get_value() { - boost::any ret_val; +// boost::any m_value; bool value = dynamic_cast(window)->GetValue(); if (m_opt.type == coBool) - ret_val = static_cast(value); + m_value = static_cast(value); else - ret_val = static_cast(value); - return ret_val; + m_value = static_cast(value); + return m_value; } int undef_spin_val = -9999; //! Probably, It's not necessary @@ -424,7 +426,33 @@ void Choice::set_value(const boost::any& value, bool change_event) break; } case coEnum:{ - dynamic_cast(window)->SetSelection(boost::any_cast(value)); + int val = boost::any_cast(value); + if (m_opt_id.compare("external_fill_pattern") == 0) + { + if (!m_opt.enum_values.empty()){ + std::string key; + t_config_enum_values map_names = ConfigOptionEnum::get_enum_values(); + for (auto it : map_names) { + if (val == it.second) { + key = it.first; + break; + } + } + + size_t idx = 0; + for (auto el : m_opt.enum_values) + { + if (el.compare(key) == 0) + break; + ++idx; + } + + val = idx == m_opt.enum_values.size() ? 0 : idx; + } + else + val = 0; + } + dynamic_cast(window)->SetSelection(val); break; } default: @@ -454,16 +482,16 @@ void Choice::set_values(const std::vector& values) m_disable_change_event = false; } -boost::any Choice::get_value() +boost::any& Choice::get_value() { - boost::any ret_val; +// boost::any m_value; wxString ret_str = static_cast(window)->GetValue(); if (m_opt_id == "support") - return ret_str; + return m_value = boost::any(ret_str);//ret_str; if (m_opt.type != coEnum) - ret_val = get_value_by_opt_type(ret_str); + /*m_value = */get_value_by_opt_type(ret_str); else { int ret_enum = static_cast(window)->GetSelection(); @@ -474,22 +502,22 @@ boost::any Choice::get_value() t_config_enum_values map_names = ConfigOptionEnum::get_enum_values(); int value = map_names.at(key); - ret_val = static_cast(value); + m_value = static_cast(value); } else - ret_val = static_cast(0); + m_value = static_cast(0); } if (m_opt_id.compare("fill_pattern") == 0) - ret_val = static_cast(ret_enum); + m_value = static_cast(ret_enum); else if (m_opt_id.compare("gcode_flavor") == 0) - ret_val = static_cast(ret_enum); + m_value = static_cast(ret_enum); else if (m_opt_id.compare("support_material_pattern") == 0) - ret_val = static_cast(ret_enum); + m_value = static_cast(ret_enum); else if (m_opt_id.compare("seam_position") == 0) - ret_val = static_cast(ret_enum); + m_value = static_cast(ret_enum); } - return ret_val; + return m_value; } void ColourPicker::BUILD() @@ -509,14 +537,14 @@ void ColourPicker::BUILD() temp->SetToolTip(get_tooltip_text(clr)); } -boost::any ColourPicker::get_value(){ - boost::any ret_val; +boost::any& ColourPicker::get_value(){ +// boost::any m_value; auto colour = static_cast(window)->GetColour(); auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), colour.Red(), colour.Green(), colour.Blue()); - ret_val = clr_str.ToStdString(); + m_value = clr_str.ToStdString(); - return ret_val; + return m_value; } void PointCtrl::BUILD() @@ -580,7 +608,7 @@ void PointCtrl::set_value(const boost::any& value, bool change_event) set_value(pt, change_event); } -boost::any PointCtrl::get_value() +boost::any& PointCtrl::get_value() { Pointf ret_point; double val; @@ -588,7 +616,7 @@ boost::any PointCtrl::get_value() ret_point.x = val; y_textctrl->GetValue().ToDouble(&val); ret_point.y = val; - return ret_point; + return m_value = ret_point; } } // GUI diff --git a/xs/src/slic3r/GUI/Field.hpp b/xs/src/slic3r/GUI/Field.hpp index cdc7c0d81..729f73d16 100644 --- a/xs/src/slic3r/GUI/Field.hpp +++ b/xs/src/slic3r/GUI/Field.hpp @@ -36,6 +36,24 @@ using t_back_to_init = std::function; wxString double_to_string(double const value); +class MyButton : public wxButton +{ +public: + MyButton() {} + MyButton(wxWindow* parent, wxWindowID id, const wxString& label = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxTextCtrlNameStr) + { + this->Create(parent, id, label, pos, size, style, validator, name); + } + + // overridden from wxWindow base class + virtual bool + AcceptsFocusFromKeyboard() const { return false; } +}; + class Field { protected: // factory function to defer and enforce creation of derived type. @@ -85,22 +103,18 @@ public: /// Gets a boost::any representing this control. /// subclasses should overload with a specific version - virtual boost::any get_value() = 0; + virtual boost::any& get_value() = 0; virtual void enable() = 0; virtual void disable() = 0; - wxStaticText* m_Label = nullptr; - wxButton* m_Undo_btn = nullptr; - wxButton* m_Undo_to_sys_btn = nullptr; - - /// Fires the enable or disable function, based on the input. + /// Fires the enable or disable function, based on the input. inline void toggle(bool en) { en ? enable() : disable(); } virtual wxString get_tooltip_text(const wxString& default_string); // set icon to "UndoToSystemValue" button according to an inheritance of preset - void set_nonsys_btn_icon(const std::string& icon); +// void set_nonsys_btn_icon(const wxBitmap& icon); Field(const ConfigOptionDef& opt, const t_config_option_key& id) : m_opt(opt), m_opt_id(id) {}; Field(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : m_parent(parent), m_opt(opt), m_opt_id(id) {}; @@ -110,7 +124,8 @@ public: virtual wxWindow* getWindow() { return nullptr; } bool is_matched(const std::string& string, const std::string& pattern); - boost::any get_value_by_opt_type(wxString& str); +// boost::any get_value_by_opt_type(wxString& str); + void get_value_by_opt_type(wxString& str); /// Factory method for generating new derived classes. template @@ -120,6 +135,78 @@ public: p->PostInitialize(); return std::move(p); //!p; } + + bool set_undo_bitmap(const wxBitmap *bmp) { + if (m_undo_bitmap != bmp) { + m_undo_bitmap = bmp; + m_Undo_btn->SetBitmap(*bmp); + return true; + } + return false; + } + + bool set_undo_to_sys_bitmap(const wxBitmap *bmp) { + if (m_undo_to_sys_bitmap != bmp) { + m_undo_to_sys_bitmap = bmp; + m_Undo_to_sys_btn->SetBitmap(*bmp); + return true; + } + return false; + } + + bool set_label_colour(const wxColour *clr) { + if (m_Label == nullptr) return false; + if (m_label_color != clr) { + m_label_color = clr; + m_Label->SetForegroundColour(*clr); + m_Label->Refresh(true); + } + return false; + } + + bool set_label_colour_force(const wxColour *clr) { + if (m_Label == nullptr) return false; + m_Label->SetForegroundColour(*clr); + m_Label->Refresh(true); + return false; + } + + bool set_undo_tooltip(const wxString *tip) { + if (m_undo_tooltip != tip) { + m_undo_tooltip = tip; + m_Undo_btn->SetToolTip(*tip); + return true; + } + return false; + } + + bool set_undo_to_sys_tooltip(const wxString *tip) { + if (m_undo_to_sys_tooltip != tip) { + m_undo_to_sys_tooltip = tip; + m_Undo_to_sys_btn->SetToolTip(*tip); + return true; + } + return false; + } + +protected: + MyButton* m_Undo_btn = nullptr; + // Bitmap and Tooltip text for m_Undo_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one. + const wxBitmap* m_undo_bitmap = nullptr; + const wxString* m_undo_tooltip = nullptr; + MyButton* m_Undo_to_sys_btn = nullptr; + // Bitmap and Tooltip text for m_Undo_to_sys_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one. + const wxBitmap* m_undo_to_sys_bitmap = nullptr; + const wxString* m_undo_to_sys_tooltip = nullptr; + + wxStaticText* m_Label = nullptr; + // Color for Label. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one. + const wxColour* m_label_color = nullptr; + + // current value + boost::any m_value; + + friend class OptionsGroup; }; /// Convenience function, accepts a const reference to t_field and checks to see whether @@ -153,7 +240,7 @@ public: m_disable_change_event = false; } - boost::any get_value() override; + boost::any& get_value() override; virtual void enable(); virtual void disable(); @@ -180,7 +267,7 @@ public: dynamic_cast(window)->SetValue(boost::any_cast(value)); m_disable_change_event = false; } - boost::any get_value() override; + boost::any& get_value() override; void enable() override { dynamic_cast(window)->Enable(); } void disable() override { dynamic_cast(window)->Disable(); } @@ -210,8 +297,9 @@ public: dynamic_cast(window)->SetValue(tmp_value); m_disable_change_event = false; } - boost::any get_value() override { - return boost::any(tmp_value); + boost::any& get_value() override { +// return boost::any(tmp_value); + return m_value = tmp_value; } void enable() override { dynamic_cast(window)->Enable(); } @@ -233,7 +321,7 @@ public: void set_value(const std::string& value, bool change_event = false); void set_value(const boost::any& value, bool change_event = false); void set_values(const std::vector &values); - boost::any get_value() override; + boost::any& get_value() override; void enable() override { dynamic_cast(window)->Enable(); }; void disable() override{ dynamic_cast(window)->Disable(); }; @@ -261,7 +349,7 @@ public: m_disable_change_event = false; } - boost::any get_value() override; + boost::any& get_value() override; void enable() override { dynamic_cast(window)->Enable(); }; void disable() override{ dynamic_cast(window)->Disable(); }; @@ -283,7 +371,7 @@ public: void set_value(const Pointf& value, bool change_event = false); void set_value(const boost::any& value, bool change_event = false); - boost::any get_value() override; + boost::any& get_value() override; void enable() override { x_textctrl->Enable(); diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 88c3f421b..4789f4590 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -50,9 +50,11 @@ #include "AppConfig.hpp" #include "ConfigSnapshotDialog.hpp" #include "Utils.hpp" +#include "MsgDialog.hpp" #include "ConfigWizard.hpp" #include "Preferences.hpp" #include "PresetBundle.hpp" +#include "UpdateDialogs.hpp" #include "../Utils/PresetUpdater.hpp" #include "../Config/Snapshot.hpp" @@ -187,6 +189,7 @@ PresetBundle *g_PresetBundle= nullptr; PresetUpdater *g_PresetUpdater = nullptr; wxColour g_color_label_modified; wxColour g_color_label_sys; +wxColour g_color_label_default; std::vector g_tabs_list; @@ -200,12 +203,28 @@ static void init_label_colours() { auto luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); if (luma >= 128) { - g_color_label_modified = wxColour(253, 88, 0); + g_color_label_modified = wxColour(252, 77, 1); g_color_label_sys = wxColour(26, 132, 57); } else { g_color_label_modified = wxColour(253, 111, 40); g_color_label_sys = wxColour(115, 220, 103); } + g_color_label_default = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); +} + +void update_label_colours_from_appconfig() +{ + if (g_AppConfig->has("label_clr_sys")){ + auto str = g_AppConfig->get("label_clr_sys"); + if (str != "") + g_color_label_sys = wxColour(str); + } + + if (g_AppConfig->has("label_clr_modified")){ + auto str = g_AppConfig->get("label_clr_modified"); + if (str != "") + g_color_label_modified = wxColour(str); + } } void set_wxapp(wxApp *app) @@ -290,22 +309,18 @@ bool select_language(wxArrayString & names, bool load_language() { - long language; - if (!g_AppConfig->has("translation_language")) - language = wxLANGUAGE_UNKNOWN; - else { - auto str_language = g_AppConfig->get("translation_language"); - language = str_language != "" ? stol(str_language) : wxLANGUAGE_UNKNOWN; - } + wxString language = wxEmptyString; + if (g_AppConfig->has("translation_language")) + language = g_AppConfig->get("translation_language"); - if (language == wxLANGUAGE_UNKNOWN) + if (language.IsEmpty()) return false; wxArrayString names; wxArrayLong identifiers; get_installed_languages(names, identifiers); for (size_t i = 0; i < identifiers.Count(); i++) { - if (identifiers[i] == language) + if (wxLocale::GetLanguageCanonicalName(identifiers[i]) == language) { g_wxLocale = new wxLocale; g_wxLocale->Init(identifiers[i]); @@ -320,12 +335,11 @@ bool load_language() void save_language() { - long language = wxLANGUAGE_UNKNOWN; - if (g_wxLocale) { - language = g_wxLocale->GetLanguage(); - } - std::string str_language = std::to_string(language); - g_AppConfig->set("translation_language", str_language); + wxString language = wxEmptyString; + if (g_wxLocale) + language = g_wxLocale->GetCanonicalName(); + + g_AppConfig->set("translation_language", language.ToStdString()); g_AppConfig->save(); } @@ -379,18 +393,18 @@ void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_l const auto config_wizard_tooltip = wxString::Format(_(L("Run %s")), ConfigWizard::name()); // Cmd+, is standard on OS X - what about other operating systems? - local_menu->Append(config_id_base + ConfigMenuWizard, ConfigWizard::name() + "\u2026", config_wizard_tooltip); - local_menu->Append(config_id_base + ConfigMenuSnapshots, _(L("Configuration Snapshots\u2026")), _(L("Inspect / activate configuration snapshots"))); - local_menu->Append(config_id_base + ConfigMenuTakeSnapshot, _(L("Take Configuration Snapshot")), _(L("Capture a configuration snapshot"))); - local_menu->Append(config_id_base + ConfigMenuUpdate, _(L("Check for updates")), _(L("Check for configuration updates"))); + local_menu->Append(config_id_base + ConfigMenuWizard, ConfigWizard::name() + "\u2026", config_wizard_tooltip); + local_menu->Append(config_id_base + ConfigMenuSnapshots, _(L("Configuration Snapshots"))+"\u2026", _(L("Inspect / activate configuration snapshots"))); + local_menu->Append(config_id_base + ConfigMenuTakeSnapshot, _(L("Take Configuration Snapshot")), _(L("Capture a configuration snapshot"))); + local_menu->Append(config_id_base + ConfigMenuUpdate, _(L("Check for updates")), _(L("Check for configuration updates"))); local_menu->AppendSeparator(); - local_menu->Append(config_id_base + ConfigMenuPreferences, _(L("Preferences\u2026\tCtrl+,")), _(L("Application preferences"))); + local_menu->Append(config_id_base + ConfigMenuPreferences, _(L("Preferences"))+"\u2026\tCtrl+,", _(L("Application preferences"))); local_menu->AppendSeparator(); local_menu->Append(config_id_base + ConfigMenuLanguage, _(L("Change Application Language"))); local_menu->Bind(wxEVT_MENU, [config_id_base, event_language_change, event_preferences_changed](wxEvent &event){ switch (event.GetId() - config_id_base) { case ConfigMenuWizard: - config_wizard(false, false); + config_wizard(ConfigWizard::RR_USER); break; case ConfigMenuTakeSnapshot: // Take a configuration snapshot. @@ -469,47 +483,31 @@ bool check_unsaved_changes() return dialog->ShowModal() == wxID_YES; } -void config_wizard_startup(bool app_config_exists) +bool config_wizard_startup(bool app_config_exists) { if (! app_config_exists || g_PresetBundle->has_defauls_only()) { - config_wizard(true, true); + config_wizard(ConfigWizard::RR_DATA_EMPTY); + return true; } else if (g_AppConfig->legacy_datadir()) { // Looks like user has legacy pre-vendorbundle data directory, // explain what this is and run the wizard - const auto msg = _(L("Configuration update")); - const auto ext_msg = wxString::Format( - _(L( - "Slic3r PE now uses an updated configuration structure.\n\n" + MsgDataLegacy dlg; + dlg.ShowModal(); - "So called 'System presets' have been introduced, which hold the built-in default settings for various " - "printers. These System presets cannot be modified, instead, users now may create their" - "own presets inheriting settings from one of the System presets.\n" - "An inheriting preset may either inherit a particular value from its parent or override it with a customized value.\n\n" - - "Please proceed with the %s that follows to set up the new presets " - "and to choose whether to enable automatic preset updates." - )), - ConfigWizard::name() - ); - wxMessageDialog dlg(NULL, msg, _(L("Configuration update")), wxOK|wxCENTRE); - dlg.SetExtendedMessage(ext_msg); - const auto res = dlg.ShowModal(); - - config_wizard(true, false); + config_wizard(ConfigWizard::RR_DATA_LEGACY); + return true; } + return false; } -void config_wizard(bool startup, bool empty_datadir) +void config_wizard(int reason) { - if (g_wxMainFrame == nullptr) - throw std::runtime_error("Main frame not set"); - // Exit wizard if there are unsaved changes and the user cancels the action. if (! check_unsaved_changes()) return; - ConfigWizard wizard(g_wxMainFrame, startup, empty_datadir); + ConfigWizard wizard(nullptr, static_cast(reason)); wizard.run(g_PresetBundle, g_PresetUpdater); // Load the currently selected preset into the GUI, update the preset selection box. @@ -525,6 +523,7 @@ void open_preferences_dialog(int event_preferences) void create_preset_tabs(bool no_controller, int event_value_change, int event_presets_changed) { + update_label_colours_from_appconfig(); add_created_tab(new TabPrint (g_wxTabPanel, no_controller)); add_created_tab(new TabFilament (g_wxTabPanel, no_controller)); add_created_tab(new TabPrinter (g_wxTabPanel, no_controller)); @@ -665,35 +664,65 @@ void add_created_tab(Tab* panel) g_wxTabPanel->AddPage(panel, panel->title()); } -void show_error(wxWindow* parent, const wxString& message){ - auto msg_wingow = new wxMessageDialog(parent, message, _(L("Error")), wxOK | wxICON_ERROR); - msg_wingow->ShowModal(); +void show_error(wxWindow* parent, const wxString& message) { + ErrorDialog msg(parent, message); + msg.ShowModal(); +} + +void show_error_id(int id, const std::string& message) { + auto *parent = id != 0 ? wxWindow::FindWindowById(id) : nullptr; + show_error(parent, message); } void show_info(wxWindow* parent, const wxString& message, const wxString& title){ - auto msg_wingow = new wxMessageDialog(parent, message, title.empty() ? _(L("Notice")) : title, wxOK | wxICON_INFORMATION); - msg_wingow->ShowModal(); + wxMessageDialog msg_wingow(parent, message, title.empty() ? _(L("Notice")) : title, wxOK | wxICON_INFORMATION); + msg_wingow.ShowModal(); } void warning_catcher(wxWindow* parent, const wxString& message){ - if (message == _(L("GLUquadricObjPtr | Attempt to free unreferenced scalar")) ) + if (message == "GLUquadricObjPtr | " + _(L("Attempt to free unreferenced scalar")) ) return; - auto msg = new wxMessageDialog(parent, message, _(L("Warning")), wxOK | wxICON_WARNING); - msg->ShowModal(); + wxMessageDialog msg(parent, message, _(L("Warning")), wxOK | wxICON_WARNING); + msg.ShowModal(); } wxApp* get_app(){ return g_wxApp; } -const wxColour& get_modified_label_clr() { +PresetBundle* get_preset_bundle() +{ + return g_PresetBundle; +} + +const wxColour& get_label_clr_modified() { return g_color_label_modified; } -const wxColour& get_sys_label_clr() { +const wxColour& get_label_clr_sys() { return g_color_label_sys; } +void set_label_clr_modified(const wxColour& clr) { + g_color_label_modified = clr; + auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), clr.Red(), clr.Green(), clr.Blue()); + std::string str = clr_str.ToStdString(); + g_AppConfig->set("label_clr_modified", str); + g_AppConfig->save(); +} + +void set_label_clr_sys(const wxColour& clr) { + g_color_label_sys = clr; + auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), clr.Red(), clr.Green(), clr.Blue()); + std::string str = clr_str.ToStdString(); + g_AppConfig->set("label_clr_sys", str); + g_AppConfig->save(); +} + +const wxColour& get_label_clr_default() { + return g_color_label_default; +} + unsigned get_colour_approx_luma(const wxColour &colour) { double r = colour.Red(); @@ -780,8 +809,8 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl { DynamicPrintConfig* config = &g_PresetBundle->prints.get_edited_preset().config; m_optgroup = std::make_shared(parent, "", config); - const wxArrayInt& ar = preset_sizer->GetColWidths(); - m_optgroup->label_width = ar.IsEmpty() ? 100 : ar.front(); +// const wxArrayInt& ar = preset_sizer->GetColWidths(); +// m_optgroup->label_width = ar.IsEmpty() ? 100 : ar.front(); // doesn't work m_optgroup->m_on_change = [config](t_config_option_key opt_key, boost::any value){ TabPrint* tab_print = nullptr; for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++i) { @@ -835,10 +864,9 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl tab_print->update_dirty(); }; - const int width = 250; Option option = m_optgroup->get_option("fill_density"); option.opt.sidetext = ""; - option.opt.width = width; + option.opt.full_width = true; m_optgroup->append_single_option_line(option); ConfigOptionDef def; @@ -857,7 +885,7 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl "Everywhere"; def.default_value = new ConfigOptionStrings { selection }; option = Option(def, "support"); - option.opt.width = width; + option.opt.full_width = true; m_optgroup->append_single_option_line(option); m_brim_width = config->opt_float("brim_width"); @@ -870,7 +898,7 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl m_optgroup->append_single_option_line(option); - Line line = { _(L("")), "" }; + Line line = { "", "" }; line.widget = [config](wxWindow* parent){ g_wiping_dialog_button = new wxButton(parent, wxID_ANY, _(L("Purging volumes")) + "\u2026", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); auto sizer = new wxBoxSizer(wxHORIZONTAL); @@ -896,7 +924,7 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl - sizer->Add(m_optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxBottom, 1); + sizer->Add(m_optgroup->sizer, 1, wxEXPAND | wxBOTTOM, 2); } ConfigOptionsGroup* get_optgroup() @@ -915,6 +943,7 @@ wxWindow* export_option_creator(wxWindow* parent) wxPanel* panel = new wxPanel(parent, -1); wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL); wxCheckBox* cbox = new wxCheckBox(panel, wxID_HIGHEST + 1, L("Export print config")); + cbox->SetValue(true); sizer->AddSpacer(5); sizer->Add(cbox, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); panel->SetSizer(sizer); diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp index 92a6e6ebb..3752b5a7a 100644 --- a/xs/src/slic3r/GUI/GUI.hpp +++ b/xs/src/slic3r/GUI/GUI.hpp @@ -82,10 +82,14 @@ void set_preset_updater(PresetUpdater *updater); AppConfig* get_app_config(); wxApp* get_app(); +PresetBundle* get_preset_bundle(); -const wxColour& get_modified_label_clr(); -const wxColour& get_sys_label_clr(); +const wxColour& get_label_clr_modified(); +const wxColour& get_label_clr_sys(); +const wxColour& get_label_clr_default(); unsigned get_colour_approx_luma(const wxColour &colour); +void set_label_clr_modified(const wxColour& clr); +void set_label_clr_sys(const wxColour& clr); extern void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_language_change); @@ -93,11 +97,13 @@ extern void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int // to notify the user whether he is aware that some preset changes will be lost. extern bool check_unsaved_changes(); -// Checks if configuration wizard needs to run, calls config_wizard if so -extern void config_wizard_startup(bool app_config_exists); +// Checks if configuration wizard needs to run, calls config_wizard if so. +// Returns whether the Wizard ran. +extern bool config_wizard_startup(bool app_config_exists); // Opens the configuration wizard, returns true if wizard is finished & accepted. -extern void config_wizard(bool startup, bool empty_datadir); +// The run_reason argument is actually ConfigWizard::RunReason, but int is used here because of Perl. +extern void config_wizard(int run_reason); // Create "Preferences" dialog after selecting menu "Preferences" in Perl part extern void open_preferences_dialog(int event_preferences); @@ -112,6 +118,7 @@ void add_created_tab(Tab* panel); void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt_key, const boost::any& value, int opt_index = 0); void show_error(wxWindow* parent, const wxString& message); +void show_error_id(int id, const std::string& message); // For Perl void show_info(wxWindow* parent, const wxString& message, const wxString& title); void warning_catcher(wxWindow* parent, const wxString& message); diff --git a/xs/src/slic3r/GUI/MsgDialog.cpp b/xs/src/slic3r/GUI/MsgDialog.cpp new file mode 100644 index 000000000..6fba47a37 --- /dev/null +++ b/xs/src/slic3r/GUI/MsgDialog.cpp @@ -0,0 +1,87 @@ +#include "MsgDialog.hpp" + +#include +#include +#include +#include +#include +#include + +#include "libslic3r/libslic3r.h" +#include "libslic3r/Utils.hpp" +#include "GUI.hpp" +#include "ConfigWizard.hpp" + +namespace Slic3r { +namespace GUI { + + +MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxWindowID button_id) : + MsgDialog(parent, title, headline, wxBitmap(from_u8(Slic3r::var("Slic3r_192px.png")), wxBITMAP_TYPE_PNG), button_id) +{} + +MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxBitmap bitmap, wxWindowID button_id) : + wxDialog(parent, wxID_ANY, title), + boldfont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)), + content_sizer(new wxBoxSizer(wxVERTICAL)), + btn_sizer(new wxBoxSizer(wxHORIZONTAL)) +{ + boldfont.SetWeight(wxFONTWEIGHT_BOLD); + + auto *topsizer = new wxBoxSizer(wxHORIZONTAL); + auto *rightsizer = new wxBoxSizer(wxVERTICAL); + + auto *headtext = new wxStaticText(this, wxID_ANY, headline); + headtext->SetFont(boldfont); + headtext->Wrap(CONTENT_WIDTH); + rightsizer->Add(headtext); + rightsizer->AddSpacer(VERT_SPACING); + + rightsizer->Add(content_sizer, 1, wxEXPAND); + + if (button_id != wxID_NONE) { + auto *button = new wxButton(this, button_id); + button->SetFocus(); + btn_sizer->Add(button); + } + + rightsizer->Add(btn_sizer, 0, wxALIGN_CENTRE_HORIZONTAL); + + auto *logo = new wxStaticBitmap(this, wxID_ANY, std::move(bitmap)); + + topsizer->Add(logo, 0, wxALL, BORDER); + topsizer->Add(rightsizer, 1, wxALL | wxEXPAND, BORDER); + + SetSizerAndFit(topsizer); +} + +MsgDialog::~MsgDialog() {} + + +// ErrorDialog + +ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg) : + MsgDialog(parent, _(L("Slic3r error")), _(L("Slic3r has encountered an error")), wxBitmap(from_u8(Slic3r::var("Slic3r_192px_grayscale.png")), wxBITMAP_TYPE_PNG)) +{ + auto *panel = new wxScrolledWindow(this); + auto *p_sizer = new wxBoxSizer(wxVERTICAL); + panel->SetSizer(p_sizer); + + auto *text = new wxStaticText(panel, wxID_ANY, msg); + text->Wrap(CONTENT_WIDTH); + p_sizer->Add(text, 1, wxEXPAND); + + panel->SetMinSize(wxSize(CONTENT_WIDTH, CONTENT_HEIGHT)); + panel->SetScrollRate(0, 5); + + content_sizer->Add(panel, 1, wxEXPAND); + + Fit(); +} + +ErrorDialog::~ErrorDialog() {} + + + +} +} diff --git a/xs/src/slic3r/GUI/MsgDialog.hpp b/xs/src/slic3r/GUI/MsgDialog.hpp new file mode 100644 index 000000000..a01127023 --- /dev/null +++ b/xs/src/slic3r/GUI/MsgDialog.hpp @@ -0,0 +1,65 @@ +#ifndef slic3r_MsgDialog_hpp_ +#define slic3r_MsgDialog_hpp_ + +#include +#include + +#include +#include +#include + +#include "slic3r/Utils/Semver.hpp" + +class wxBoxSizer; +class wxCheckBox; + +namespace Slic3r { + +namespace GUI { + + +// A message / query dialog with a bitmap on the left and any content on the right +// with buttons underneath. +struct MsgDialog : wxDialog +{ + MsgDialog(MsgDialog &&) = delete; + MsgDialog(const MsgDialog &) = delete; + MsgDialog &operator=(MsgDialog &&) = delete; + MsgDialog &operator=(const MsgDialog &) = delete; + virtual ~MsgDialog(); + +protected: + enum { + CONTENT_WIDTH = 500, + CONTENT_HEIGHT = 300, + BORDER = 30, + VERT_SPACING = 15, + HORIZ_SPACING = 5, + }; + + // button_id is an id of a button that can be added by default, use wxID_NONE to disable + MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxWindowID button_id = wxID_OK); + MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxBitmap bitmap, wxWindowID button_id = wxID_OK); + + wxFont boldfont; + wxBoxSizer *content_sizer; + wxBoxSizer *btn_sizer; +}; + + +// Generic error dialog, used for displaying exceptions +struct ErrorDialog : MsgDialog +{ + ErrorDialog(wxWindow *parent, const wxString &msg); + ErrorDialog(ErrorDialog &&) = delete; + ErrorDialog(const ErrorDialog &) = delete; + ErrorDialog &operator=(ErrorDialog &&) = delete; + ErrorDialog &operator=(const ErrorDialog &) = delete; + virtual ~ErrorDialog(); +}; + + +} +} + +#endif diff --git a/xs/src/slic3r/GUI/OptionsGroup.cpp b/xs/src/slic3r/GUI/OptionsGroup.cpp index 168ffcdc9..657ad03c0 100644 --- a/xs/src/slic3r/GUI/OptionsGroup.cpp +++ b/xs/src/slic3r/GUI/OptionsGroup.cpp @@ -22,13 +22,13 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co // is the normal type. if (opt.gui_type.compare("select") == 0) { } else if (opt.gui_type.compare("select_open") == 0) { - m_fields.emplace(id, STDMOVE(Choice::Create(m_parent, opt, id))); + m_fields.emplace(id, STDMOVE(Choice::Create(parent(), opt, id))); } else if (opt.gui_type.compare("color") == 0) { - m_fields.emplace(id, STDMOVE(ColourPicker::Create(m_parent, opt, id))); + m_fields.emplace(id, STDMOVE(ColourPicker::Create(parent(), opt, id))); } else if (opt.gui_type.compare("f_enum_open") == 0 || opt.gui_type.compare("i_enum_open") == 0 || opt.gui_type.compare("i_enum_closed") == 0) { - m_fields.emplace(id, STDMOVE(Choice::Create(m_parent, opt, id))); + m_fields.emplace(id, STDMOVE(Choice::Create(parent(), opt, id))); } else if (opt.gui_type.compare("slider") == 0) { } else if (opt.gui_type.compare("i_spin") == 0) { // Spinctrl } else { @@ -40,21 +40,21 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co case coPercents: case coString: case coStrings: - m_fields.emplace(id, STDMOVE(TextCtrl::Create(m_parent, opt, id))); + m_fields.emplace(id, STDMOVE(TextCtrl::Create(parent(), opt, id))); break; case coBool: case coBools: - m_fields.emplace(id, STDMOVE(CheckBox::Create(m_parent, opt, id))); + m_fields.emplace(id, STDMOVE(CheckBox::Create(parent(), opt, id))); break; case coInt: case coInts: - m_fields.emplace(id, STDMOVE(SpinCtrl::Create(m_parent, opt, id))); + m_fields.emplace(id, STDMOVE(SpinCtrl::Create(parent(), opt, id))); break; case coEnum: - m_fields.emplace(id, STDMOVE(Choice::Create(m_parent, opt, id))); + m_fields.emplace(id, STDMOVE(Choice::Create(parent(), opt, id))); break; case coPoints: - m_fields.emplace(id, STDMOVE(PointCtrl::Create(m_parent, opt, id))); + m_fields.emplace(id, STDMOVE(PointCtrl::Create(parent(), opt, id))); break; case coNone: break; default: @@ -90,8 +90,8 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co field->m_Undo_btn->Hide(); field->m_Undo_to_sys_btn->Hide(); } - if (nonsys_btn_icon != nullptr) - field->set_nonsys_btn_icon(nonsys_btn_icon()); +// if (nonsys_btn_icon != nullptr) +// field->set_nonsys_btn_icon(*nonsys_btn_icon); // assign function objects for callbacks, etc. return field; @@ -118,30 +118,43 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/* if (option_set.size() == 1 && label_width == 0 && option_set.front().opt.full_width && option_set.front().opt.sidetext.size() == 0 && option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0) { + wxSizer* tmp_sizer; +#ifdef __WXGTK__ + tmp_sizer = new wxBoxSizer(wxVERTICAL); + m_panel->SetSizer(tmp_sizer); + m_panel->Layout(); +#else + tmp_sizer = sizer; +#endif /* __WXGTK__ */ + const auto& option = option_set.front(); const auto& field = build_field(option); auto btn_sizer = new wxBoxSizer(wxHORIZONTAL); btn_sizer->Add(field->m_Undo_to_sys_btn); btn_sizer->Add(field->m_Undo_btn); - sizer->Add(btn_sizer, 0, wxEXPAND | wxALL, 0); + tmp_sizer->Add(btn_sizer, 0, wxEXPAND | wxALL, 0); if (is_window_field(field)) - sizer->Add(field->getWindow(), 0, wxEXPAND | wxALL, wxOSX ? 0 : 5); + tmp_sizer->Add(field->getWindow(), 0, wxEXPAND | wxALL, wxOSX ? 0 : 5); if (is_sizer_field(field)) - sizer->Add(field->getSizer(), 0, wxEXPAND | wxALL, wxOSX ? 0 : 5); + tmp_sizer->Add(field->getSizer(), 0, wxEXPAND | wxALL, wxOSX ? 0 : 5); return; } auto grid_sizer = m_grid_sizer; +#ifdef __WXGTK__ + m_panel->SetSizer(m_grid_sizer); + m_panel->Layout(); +#endif /* __WXGTK__ */ // Build a label if we have it wxStaticText* label=nullptr; if (label_width != 0) { - label = new wxStaticText(parent(), wxID_ANY, line.label + (line.label.IsEmpty() ? "" : ":"), - wxDefaultPosition, wxSize(label_width, -1)); + label = new wxStaticText(parent(), wxID_ANY, line.label + (line.label.IsEmpty() ? "" : ": "), + wxDefaultPosition, staticbox ? wxSize(label_width, -1) : wxDefaultSize); label->SetFont(label_font); label->Wrap(label_width); // avoid a Linux/GTK bug - grid_sizer->Add(label, 0, wxALIGN_CENTER_VERTICAL,0); + grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT) | wxALIGN_CENTER_VERTICAL, 0); if (line.label_tooltip.compare("") != 0) label->SetToolTip(line.label_tooltip); } @@ -149,7 +162,8 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/* // If there's a widget, build it and add the result to the sizer. if (line.widget != nullptr) { auto wgt = line.widget(parent()); - grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, wxOSX ? 0 : 5); + // If widget doesn't have label, don't use border + grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, (wxOSX || line.label.IsEmpty()) ? 0 : 5); if (colored_Label != nullptr) *colored_Label = label; return; } @@ -165,7 +179,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/* sizer->Add(field->m_Undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL); sizer->Add(field->m_Undo_btn, 0, wxALIGN_CENTER_VERTICAL); if (is_window_field(field)) - sizer->Add(field->getWindow(), 0, (option.opt.full_width ? wxEXPAND : 0) | + sizer->Add(field->getWindow(), option.opt.full_width ? 1 : 0, (option.opt.full_width ? wxEXPAND : 0) | wxBOTTOM | wxTOP | wxALIGN_CENTER_VERTICAL, wxOSX ? 0 : 2); if (is_sizer_field(field)) sizer->Add(field->getSizer(), 0, (option.opt.full_width ? wxEXPAND : 0) | wxALIGN_CENTER_VERTICAL, 0); @@ -467,10 +481,10 @@ Field* ConfigOptionsGroup::get_fieldc(const t_config_option_key& opt_key, int op return opt_id.empty() ? nullptr : get_field(opt_id); } -void ogStaticText::SetText(const wxString& value) +void ogStaticText::SetText(const wxString& value, bool wrap/* = true*/) { SetLabel(value); - Wrap(400); + if (wrap) Wrap(400); GetParent()->Layout(); } diff --git a/xs/src/slic3r/GUI/OptionsGroup.hpp b/xs/src/slic3r/GUI/OptionsGroup.hpp index dd6d48f46..83b5b1233 100644 --- a/xs/src/slic3r/GUI/OptionsGroup.hpp +++ b/xs/src/slic3r/GUI/OptionsGroup.hpp @@ -1,3 +1,6 @@ +#ifndef slic3r_OptionsGroup_hpp_ +#define slic3r_OptionsGroup_hpp_ + #include #include #include @@ -86,12 +89,18 @@ public: wxFont sidetext_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) }; wxFont label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) }; - std::function nonsys_btn_icon{ nullptr }; +// std::function nonsys_btn_icon{ nullptr }; /// Returns a copy of the pointer of the parent wxWindow. /// Accessor function is because users are not allowed to change the parent /// but defining it as const means a lot of const_casts to deal with wx functions. - inline wxWindow* parent() const { return m_parent; } + inline wxWindow* parent() const { +#ifdef __WXGTK__ + return m_panel; +#else + return m_parent; +#endif /* __WXGTK__ */ + } void append_line(const Line& line, wxStaticText** colored_Label = nullptr); Line create_single_option_line(const Option& option) const; @@ -127,8 +136,13 @@ public: m_grid_sizer = new wxFlexGridSizer(0, num_columns, 0,0); static_cast(m_grid_sizer)->SetFlexibleDirection(wxHORIZONTAL); static_cast(m_grid_sizer)->AddGrowableCol(label_width != 0); - - sizer->Add(m_grid_sizer, 0, wxEXPAND | wxALL, wxOSX ? 0: 5); +#ifdef __WXGTK__ + m_panel = new wxPanel( _parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + sizer->Fit(m_panel); + sizer->Add(m_panel, 0, wxEXPAND | wxALL, wxOSX||!staticbox ? 0: 5); +#else + sizer->Add(m_grid_sizer, 0, wxEXPAND | wxALL, wxOSX||!staticbox ? 0: 5); +#endif /* __WXGTK__ */ } protected: @@ -144,6 +158,13 @@ protected: // "true" if option is created in preset tabs bool m_is_tab_opt{ false }; + // This panel is needed for correct showing of the ToolTips for Button, StaticText and CheckBox + // Tooltips on GTK doesn't work inside wxStaticBoxSizer unless you insert a panel + // inside it before you insert the other controls. +#ifdef __WXGTK__ + wxPanel* m_panel {nullptr}; +#endif /* __WXGTK__ */ + /// Generate a wxSizer or wxWindow from a configuration option /// Precondition: opt resolves to a known ConfigOption /// Postcondition: fields contains a wx gui object. @@ -200,7 +221,9 @@ public: ogStaticText(wxWindow* parent, const char *text) : wxStaticText(parent, wxID_ANY, text, wxDefaultPosition, wxDefaultSize){} ~ogStaticText(){} - void SetText(const wxString& value); + void SetText(const wxString& value, bool wrap = true); }; }} + +#endif /* slic3r_OptionsGroup_hpp_ */ diff --git a/xs/src/slic3r/GUI/Preferences.cpp b/xs/src/slic3r/GUI/Preferences.cpp index 4c60577d5..cb7ac92a6 100644 --- a/xs/src/slic3r/GUI/Preferences.cpp +++ b/xs/src/slic3r/GUI/Preferences.cpp @@ -5,6 +5,12 @@ namespace Slic3r { namespace GUI { +PreferencesDialog::PreferencesDialog(wxWindow* parent, int event_preferences) : + wxDialog(parent, wxID_ANY, _(L("Preferences")), wxDefaultPosition, wxDefaultSize), + m_event_preferences(event_preferences) { + build(); + } + void PreferencesDialog::build() { auto app_config = get_app_config(); diff --git a/xs/src/slic3r/GUI/Preferences.hpp b/xs/src/slic3r/GUI/Preferences.hpp index c30e94d22..d01d78b70 100644 --- a/xs/src/slic3r/GUI/Preferences.hpp +++ b/xs/src/slic3r/GUI/Preferences.hpp @@ -1,3 +1,6 @@ +#ifndef slic3r_Preferences_hpp_ +#define slic3r_Preferences_hpp_ + #include "GUI.hpp" #include @@ -14,8 +17,7 @@ class PreferencesDialog : public wxDialog std::shared_ptr m_optgroup; int m_event_preferences; public: - PreferencesDialog(wxWindow* parent, int event_preferences) : wxDialog(parent, wxID_ANY, _(L("Preferences")), - wxDefaultPosition, wxDefaultSize), m_event_preferences(event_preferences) { build(); } + PreferencesDialog(wxWindow* parent, int event_preferences); ~PreferencesDialog(){ } void build(); @@ -25,3 +27,5 @@ public: } // GUI } // Slic3r + +#endif /* slic3r_Preferences_hpp_ */ diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 640fcaaaf..1388c3510 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -3,6 +3,7 @@ #include "Preset.hpp" #include "AppConfig.hpp" +#include "BitmapCache.hpp" #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include #include @@ -119,14 +121,15 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem model.id = section.first.substr(printer_model_key.size()); model.name = section.second.get("name", model.id); section.second.get("variants", ""); + const auto variants_field = section.second.get("variants", ""); std::vector variants; - if (Slic3r::unescape_strings_cstyle(section.second.get("variants", ""), variants)) { + if (Slic3r::unescape_strings_cstyle(variants_field, variants)) { for (const std::string &variant_name : variants) { if (model.variant(variant_name) == nullptr) model.variants.emplace_back(VendorProfile::PrinterVariant(variant_name)); } } else { - // Log error? // XXX + BOOST_LOG_TRIVIAL(error) << boost::format("Vendor bundle: `%1%`: Malformed variants field: `%2%`") % id % variants_field; } if (! model.id.empty() && ! model.variants.empty()) res.models.push_back(std::move(model)); @@ -340,7 +343,8 @@ PresetCollection::PresetCollection(Preset::Type type, const std::vectorfind_preset(name, false)) { - errors_cummulative += "The user preset \"" + name + "\" cannot be loaded. A system preset of the same name has already been loaded."; + // This happens when there's is a preset (most likely legacy one) with the same name as a system preset + // that's already been loaded from a bundle. + BOOST_LOG_TRIVIAL(warning) << "Preset already present, not loading: " << name; continue; } try { @@ -585,17 +593,41 @@ void PresetCollection::update_platter_ui(wxBitmapComboBox *ui) // Otherwise fill in the list from scratch. ui->Freeze(); ui->Clear(); - std::map nonsys_presets; + + const Preset &selected_preset = this->get_selected_preset(); + // Show wide icons if the currently selected preset is not compatible with the current printer, + // and draw a red flag in front of the selected preset. + bool wide_icons = !selected_preset.is_compatible && m_bitmap_incompatible != nullptr; + + std::map nonsys_presets; wxString selected = ""; - for (size_t i = this->m_presets.front().is_visible ? 0 : 1; i < this->m_presets.size(); ++ i) { + if (!this->m_presets.front().is_visible) + ui->Append("------- " +_(L("System presets")) + " -------", wxNullBitmap); + for (size_t i = this->m_presets.front().is_visible ? 0 : 1; i < this->m_presets.size(); ++i) { const Preset &preset = this->m_presets[i]; if (! preset.is_visible || (! preset.is_compatible && i != m_idx_selected)) continue; - const wxBitmap *bmp = (i == 0 || preset.is_compatible) ? m_bitmap_main_frame : m_bitmap_incompatible; -// ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), -// (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); -// if (i == m_idx_selected) -// ui->SetSelection(ui->GetCount() - 1); + std::string bitmap_key = ""; + // If the filament preset is not compatible and there is a "red flag" icon loaded, show it left + // to the filament color image. + if (wide_icons) + bitmap_key += preset.is_compatible ? ",cmpt" : ",ncmpt"; + bitmap_key += (preset.is_system || preset.is_default) ? ",syst" : ",nsyst"; + wxBitmap *bmp = m_bitmap_cache->find(bitmap_key); + if (bmp == nullptr) { + // Create the bitmap with color bars. + std::vector bmps; + if (wide_icons) + // Paint a red flag for incompatible presets. + bmps.emplace_back(preset.is_compatible ? m_bitmap_cache->mkclear(16, 16) : *m_bitmap_incompatible); + // Paint the color bars. + bmps.emplace_back(m_bitmap_cache->mkclear(4, 16)); + bmps.emplace_back(*m_bitmap_main_frame); + // Paint a lock at the system presets. + bmps.emplace_back(m_bitmap_cache->mkclear(6, 16)); + bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmap_lock : m_bitmap_cache->mkclear(16, 16)); + bmp = m_bitmap_cache->insert(bitmap_key, bmps); + } if (preset.is_default || preset.is_system){ ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), @@ -605,20 +637,18 @@ void PresetCollection::update_platter_ui(wxBitmapComboBox *ui) } else { - nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), preset.is_compatible); + nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), bmp/*preset.is_compatible*/); if (i == m_idx_selected) selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()); } if (preset.is_default) - ui->Append("------------------------------------", wxNullBitmap); + ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap); } if (!nonsys_presets.empty()) { - ui->Append("------------------------------------", wxNullBitmap); - for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { - const wxBitmap *bmp = it->second ? m_bitmap_compatible : m_bitmap_incompatible; - ui->Append(it->first, - (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); + ui->Append("------- " + _(L("User presets")) + " -------", wxNullBitmap); + for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { + ui->Append(it->first, *it->second); if (it->first == selected) ui->SetSelection(ui->GetCount() - 1); } @@ -626,51 +656,63 @@ void PresetCollection::update_platter_ui(wxBitmapComboBox *ui) ui->Thaw(); } -void PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible) +size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible) { if (ui == nullptr) - return; + return 0; ui->Freeze(); ui->Clear(); - std::map nonsys_presets; + size_t selected_preset_item = 0; + + std::map nonsys_presets; wxString selected = ""; - for (size_t i = this->m_presets.front().is_visible ? 0 : 1; i < this->m_presets.size(); ++ i) { + if (!this->m_presets.front().is_visible) + ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap); + for (size_t i = this->m_presets.front().is_visible ? 0 : 1; i < this->m_presets.size(); ++i) { const Preset &preset = this->m_presets[i]; if (! preset.is_visible || (! show_incompatible && ! preset.is_compatible && i != m_idx_selected)) continue; - const wxBitmap *bmp = preset.is_compatible ? m_bitmap_compatible : m_bitmap_incompatible; -// ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), -// (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); -// if (i == m_idx_selected) -// ui->SetSelection(ui->GetCount() - 1); + std::string bitmap_key = "tab"; + bitmap_key += preset.is_compatible ? ",cmpt" : ",ncmpt"; + bitmap_key += (preset.is_system || preset.is_default) ? ",syst" : ",nsyst"; + wxBitmap *bmp = m_bitmap_cache->find(bitmap_key); + if (bmp == nullptr) { + // Create the bitmap with color bars. + std::vector bmps; + const wxBitmap* tmp_bmp = preset.is_compatible ? m_bitmap_compatible : m_bitmap_incompatible; + bmps.emplace_back((tmp_bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *tmp_bmp); + // Paint a lock at the system presets. + bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmap_lock : m_bitmap_cache->mkclear(16, 16)); + bmp = m_bitmap_cache->insert(bitmap_key, bmps); + } if (preset.is_default || preset.is_system){ ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); if (i == m_idx_selected) - ui->SetSelection(ui->GetCount() - 1); + selected_preset_item = ui->GetCount() - 1; } else { - nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), preset.is_compatible); + nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), bmp/*preset.is_compatible*/); if (i == m_idx_selected) selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()); } if (preset.is_default) - ui->Append("------------------------------------", wxNullBitmap); + ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap); } if (!nonsys_presets.empty()) { - ui->Append("------------------------------------", wxNullBitmap); - for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { - const wxBitmap *bmp = it->second ? m_bitmap_compatible : m_bitmap_incompatible; - ui->Append(it->first, - (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); + ui->Append("------- " + _(L("User presets")) + " -------", wxNullBitmap); + for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { + ui->Append(it->first, *it->second); if (it->first == selected) - ui->SetSelection(ui->GetCount() - 1); + selected_preset_item = ui->GetCount() - 1; } } + ui->SetSelection(selected_preset_item); ui->Thaw(); + return selected_preset_item; } // Update a dirty floag of the current preset, update the labels of the UI component accordingly. @@ -703,11 +745,13 @@ bool PresetCollection::update_dirty_ui(wxBitmapComboBox *ui) return was_dirty != is_dirty; } -std::vector PresetCollection::dirty_options(const Preset *edited, const Preset *reference) +std::vector PresetCollection::dirty_options(const Preset *edited, const Preset *reference, const bool is_printer_type /*= false*/) { std::vector changed; - if (edited != nullptr && reference != nullptr) { - changed = reference->config.diff(edited->config); + if (edited != nullptr && reference != nullptr) { + changed = is_printer_type ? + reference->config.deep_diff(edited->config) : + reference->config.diff(edited->config); // The "compatible_printers" option key is handled differently from the others: // It is not mandatory. If the key is missing, it means it is compatible with any printer. // If the key exists and it is empty, it means it is compatible with no printer. diff --git a/xs/src/slic3r/GUI/Preset.hpp b/xs/src/slic3r/GUI/Preset.hpp index e80f138ee..ab01a48ff 100644 --- a/xs/src/slic3r/GUI/Preset.hpp +++ b/xs/src/slic3r/GUI/Preset.hpp @@ -20,6 +20,10 @@ namespace Slic3r { class AppConfig; class PresetBundle; +namespace GUI { + class BitmapCache; +} + enum ConfigFileType { CONFIG_FILE_TYPE_UNKNOWN, @@ -302,18 +306,18 @@ public: // Compare the content of get_selected_preset() with get_edited_preset() configs, return true if they differ. bool current_is_dirty() const { return ! this->current_dirty_options().empty(); } // Compare the content of get_selected_preset() with get_edited_preset() configs, return the list of keys where they differ. - std::vector current_dirty_options() const - { return dirty_options(&this->get_edited_preset(), &this->get_selected_preset()); } + std::vector current_dirty_options(const bool is_printer_type = false) const + { return dirty_options(&this->get_edited_preset(), &this->get_selected_preset(), is_printer_type); } // Compare the content of get_selected_preset() with get_edited_preset() configs, return the list of keys where they differ. - std::vector current_different_from_parent_options() const - { return dirty_options(&this->get_edited_preset(), this->get_selected_preset_parent()); } + std::vector current_different_from_parent_options(const bool is_printer_type = false) const + { return dirty_options(&this->get_edited_preset(), this->get_selected_preset_parent(), is_printer_type); } // Compare the content of get_selected_preset() with get_selected_preset_parent() configs, return the list of keys where they equal. std::vector system_equal_options() const; // Update the choice UI from the list of presets. // If show_incompatible, all presets are shown, otherwise only the compatible presets are shown. // If an incompatible preset is selected, it is shown as well. - void update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible); + size_t update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible); // Update the choice UI from the list of presets. // Only the compatible presets are shown. // If an incompatible preset is selected, it is shown as well. @@ -358,7 +362,7 @@ private: size_t update_compatible_with_printer_internal(const Preset &active_printer, bool unselect_if_incompatible); - static std::vector dirty_options(const Preset *edited, const Preset *reference); + static std::vector dirty_options(const Preset *edited, const Preset *reference, const bool is_printer_type = false); // Type of this PresetCollection: TYPE_PRINT, TYPE_FILAMENT or TYPE_PRINTER. Preset::Type m_type; @@ -384,6 +388,9 @@ private: // Path to the directory to store the config files into. std::string m_dir_path; + // Caching color bitmaps for the filament combo box. + GUI::BitmapCache *m_bitmap_cache = nullptr; + // to access select_preset_by_name_strict() friend class PresetBundle; }; diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp index 717e7a6f0..63b6a4e0c 100644 --- a/xs/src/slic3r/GUI/PresetBundle.cpp +++ b/xs/src/slic3r/GUI/PresetBundle.cpp @@ -1011,6 +1011,9 @@ void PresetBundle::export_configbundle(const std::string &path) //, const Dynami // an optional "(modified)" suffix will be removed from the filament name. void PresetBundle::set_filament_preset(size_t idx, const std::string &name) { + if (name.find_first_of("-------") == 0) + return; + if (idx >= filament_presets.size()) filament_presets.resize(idx + 1, filaments.default_preset().name); filament_presets[idx] = Preset::remove_suffix_modified(name); @@ -1059,9 +1062,11 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, wxBitma // and draw a red flag in front of the selected preset. bool wide_icons = selected_preset != nullptr && ! selected_preset->is_compatible && m_bitmapIncompatible != nullptr; assert(selected_preset != nullptr); - std::map nonsys_presets; + std::map nonsys_presets; wxString selected_str = ""; - for (int i = this->filaments().front().is_visible ? 0 : 1; i < int(this->filaments().size()); ++ i) { + if (!this->filaments().front().is_visible) + ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap); + for (int i = this->filaments().front().is_visible ? 0 : 1; i < int(this->filaments().size()); ++i) { const Preset &preset = this->filaments.preset(i); bool selected = this->filament_presets[idx_extruder] == preset.name; if (! preset.is_visible || (! preset.is_compatible && ! selected)) @@ -1093,14 +1098,11 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, wxBitma bmps.emplace_back(m_bitmapCache->mksolid(8, 16, rgb)); } // Paint a lock at the system presets. - bmps.emplace_back(m_bitmapCache->mkclear(4, 16)); - bmps.emplace_back((preset.is_system || preset.is_default) ? - (preset.is_dirty ? *m_bitmapLockOpen : *m_bitmapLock) : m_bitmapCache->mkclear(16, 16)); + bmps.emplace_back(m_bitmapCache->mkclear(2, 16)); + bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmapLock : m_bitmapCache->mkclear(16, 16)); +// (preset.is_dirty ? *m_bitmapLockOpen : *m_bitmapLock) : m_bitmapCache->mkclear(16, 16)); bitmap = m_bitmapCache->insert(bitmap_key, bmps); } -// ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), (bitmap == 0) ? wxNullBitmap : *bitmap); -// if (selected) -// ui->SetSelection(ui->GetCount() - 1); if (preset.is_default || preset.is_system){ ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), @@ -1111,19 +1113,19 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, wxBitma else { nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), - (bitmap == 0) ? wxNullBitmap : *bitmap); + (bitmap == 0) ? &wxNullBitmap : bitmap); if (selected) selected_str = wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()); } if (preset.is_default) - ui->Append("------------------------------------", wxNullBitmap); + ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap); } if (!nonsys_presets.empty()) { - ui->Append("------------------------------------", wxNullBitmap); - for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { - ui->Append(it->first, it->second); + ui->Append("------- " + _(L("User presets")) + " -------", wxNullBitmap); + for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { + ui->Append(it->first, *it->second); if (it->first == selected_str) ui->SetSelection(ui->GetCount() - 1); } diff --git a/xs/src/slic3r/GUI/RammingChart.cpp b/xs/src/slic3r/GUI/RammingChart.cpp index 1ef43be02..97a6b7712 100644 --- a/xs/src/slic3r/GUI/RammingChart.cpp +++ b/xs/src/slic3r/GUI/RammingChart.cpp @@ -25,7 +25,7 @@ void Chart::draw() { dc.DrawRectangle(m_rect); if (visible_area.m_width < 0.499) { - dc.DrawText("NO RAMMING AT ALL",wxPoint(m_rect.GetLeft()+m_rect.GetWidth()/2-50,m_rect.GetBottom()-m_rect.GetHeight()/2)); + dc.DrawText(_(L("NO RAMMING AT ALL")),wxPoint(m_rect.GetLeft()+m_rect.GetWidth()/2-50,m_rect.GetBottom()-m_rect.GetHeight()/2)); return; } @@ -78,12 +78,12 @@ void Chart::draw() { } // axis labels: - wxString label = L("Time (s)"); + wxString label = _(L("Time")) + " ("+_(L("s"))+")"; int text_width = 0; int text_height = 0; dc.GetTextExtent(label,&text_width,&text_height); dc.DrawText(label,wxPoint(0.5*(m_rect.GetRight()+m_rect.GetLeft())-text_width/2.f, m_rect.GetBottom()+25)); - label = L("Volumetric speed (mm\u00B3/s)"); + label = _(L("Volumetric speed")) + " (" + _(L("mm")) + "\u00B3/" + _(L("s")) + ")"; dc.GetTextExtent(label,&text_width,&text_height); dc.DrawRotatedText(label,wxPoint(0,0.5*(m_rect.GetBottom()+m_rect.GetTop())+text_width/2.f),90); } diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index b7aaa78b7..ed86fac51 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -8,6 +8,7 @@ #include "slic3r/Utils/OctoPrint.hpp" #include "BonjourDialog.hpp" #include "WipeTowerDialog.hpp" +#include "ButtonsDescription.hpp" #include #include @@ -23,6 +24,9 @@ #include #include "wxExtensions.hpp" +#include + +#include namespace Slic3r { namespace GUI { @@ -88,9 +92,9 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle) if (wxMSW) m_btn_delete_preset->SetBackgroundColour(color); m_show_incompatible_presets = false; - m_bmp_show_incompatible_presets = new wxBitmap(from_u8(Slic3r::var("flag-red-icon.png")), wxBITMAP_TYPE_PNG); - m_bmp_hide_incompatible_presets = new wxBitmap(from_u8(Slic3r::var("flag-green-icon.png")), wxBITMAP_TYPE_PNG); - m_btn_hide_incompatible_presets = new wxBitmapButton(panel, wxID_ANY, *m_bmp_hide_incompatible_presets, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); + m_bmp_show_incompatible_presets.LoadFile(from_u8(Slic3r::var("flag-red-icon.png")), wxBITMAP_TYPE_PNG); + m_bmp_hide_incompatible_presets.LoadFile(from_u8(Slic3r::var("flag-green-icon.png")), wxBITMAP_TYPE_PNG); + m_btn_hide_incompatible_presets = new wxBitmapButton(panel, wxID_ANY, m_bmp_hide_incompatible_presets, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); if (wxMSW) m_btn_hide_incompatible_presets->SetBackgroundColour(color); m_btn_save_preset->SetToolTip(_(L("Save current ")) + m_title); @@ -99,14 +103,52 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle) m_undo_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); m_undo_to_sys_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); + m_question_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); if (wxMSW) { m_undo_btn->SetBackgroundColour(color); m_undo_to_sys_btn->SetBackgroundColour(color); + m_question_btn->SetBackgroundColour(color); } - m_undo_btn->SetBitmap(wxBitmap(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG)); - m_undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_initial_value(); })); - m_undo_to_sys_btn->SetBitmap(wxBitmap(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG)); - m_undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_sys_value(); })); + + m_question_btn->SetToolTip(_(L("Hover the cursor over buttons to find more information \n" + "or click this button."))); + + // Determine the theme color of OS (dark or light) + auto luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + // Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field. + m_bmp_value_lock .LoadFile(from_u8(var("sys_lock.png")), wxBITMAP_TYPE_PNG); + m_bmp_value_unlock .LoadFile(from_u8(var(luma >= 128 ? "sys_unlock.png" : "sys_unlock_grey.png")), wxBITMAP_TYPE_PNG); + m_bmp_non_system = &m_bmp_white_bullet; + // Bitmaps to be shown on the "Undo user changes" button next to each input field. + m_bmp_value_revert .LoadFile(from_u8(var(luma >= 128 ? "action_undo.png" : "action_undo_grey.png")), wxBITMAP_TYPE_PNG); + m_bmp_white_bullet .LoadFile(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG); + m_bmp_question .LoadFile(from_u8(var("question_mark_01.png")), wxBITMAP_TYPE_PNG); + + fill_icon_descriptions(); + set_tooltips_text(); + + m_undo_btn->SetBitmap(m_bmp_white_bullet); + m_undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_roll_back_value(); })); + m_undo_to_sys_btn->SetBitmap(m_bmp_white_bullet); + m_undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_roll_back_value(true); })); + m_question_btn->SetBitmap(m_bmp_question); + m_question_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) + { + auto dlg = new ButtonsDescription(this, &m_icon_descriptions); + if (dlg->ShowModal() == wxID_OK){ + // Colors for ui "decoration" + for (Tab *tab : get_tabs_list()){ + tab->m_sys_label_clr = get_label_clr_sys(); + tab->m_modified_label_clr = get_label_clr_modified(); + tab->update_labels_colour(); + } + } + })); + + // Colors for ui "decoration" + m_sys_label_clr = get_label_clr_sys(); + m_modified_label_clr = get_label_clr_modified(); + m_default_text_clr = get_label_clr_default(); m_hsizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(m_hsizer, 0, wxBOTTOM, 3); @@ -120,7 +162,8 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle) m_hsizer->AddSpacer(64); m_hsizer->Add(m_undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL); m_hsizer->Add(m_undo_btn, 0, wxALIGN_CENTER_VERTICAL); -// m_hsizer->AddSpacer(64); + m_hsizer->AddSpacer(32); + m_hsizer->Add(m_question_btn, 0, wxALIGN_CENTER_VERTICAL); // m_hsizer->Add(m_cc_presets_choice, 1, wxLEFT | wxRIGHT | wxTOP | wxALIGN_CENTER_VERTICAL, 3); //Horizontal sizer to hold the tree and the selected page. @@ -183,8 +226,17 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle) //! select_preset(m_presets_choice->GetStringSelection().ToStdString()); //! we doing next: int selected_item = m_presets_choice->GetSelection(); + if (m_selected_preset_item == selected_item && !m_presets->current_is_dirty()) + return; if (selected_item >= 0){ std::string selected_string = m_presets_choice->GetString(selected_item).ToUTF8().data(); + if (selected_string.find_first_of("-------") == 0 + /*selected_string == "------- System presets -------" || + selected_string == "------- User presets -------"*/){ + m_presets_choice->SetSelection(m_selected_preset_item); + return; + } + m_selected_preset_item = selected_item; select_preset(selected_string); } })); @@ -204,8 +256,9 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle) void Tab::load_initial_data() { m_config = &m_presets->get_edited_preset().config; - m_nonsys_btn_icon = m_presets->get_selected_preset_parent() == nullptr ? - "bullet_white.png" : "sys_unlock.png"; + m_bmp_non_system = m_presets->get_selected_preset_parent() ? &m_bmp_value_unlock : &m_bmp_white_bullet; + m_ttg_non_system = m_presets->get_selected_preset_parent() ? &m_ttg_value_unlock : &m_ttg_white_bullet_ns; + m_tt_non_system = m_presets->get_selected_preset_parent() ? &m_tt_value_unlock : &m_ttg_white_bullet_ns; } PageShp Tab::add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages/* = false*/) @@ -234,140 +287,128 @@ PageShp Tab::add_options_page(const wxString& title, const std::string& icon, bo return page; } -template -void add_correct_opts_to_dirty_options(const std::string &opt_key, std::vector *vec, TabPrinter *tab) +void Tab::update_labels_colour() { - auto opt_init = static_cast(tab->m_presets->get_selected_preset().config.option(opt_key)); - auto opt_cur = static_cast(tab->m_config->option(opt_key)); - int opt_init_max_id = opt_init->values.size()-1; - for (int i = 0; i < opt_cur->values.size(); i++) + Freeze(); + //update options "decoration" + for (const auto opt : m_options_list) { - int init_id = i <= opt_init_max_id ? i : 0; - if (opt_cur->values[i] != opt_init->values[init_id]) - vec->emplace_back(opt_key + "#" + std::to_string(i)); - } -} + const wxColour *color = &m_sys_label_clr; -template -void add_correct_opts_to_sys_options(const std::string &opt_key, std::vector *vec, TabPrinter *tab) -{ - const Preset* sys_preset = tab->m_presets->get_selected_preset_parent(); - if (sys_preset == nullptr) - return; - T *opt_cur = static_cast(tab->m_config->option(opt_key)); - const T *opt_sys = static_cast(sys_preset->config.option(opt_key)); - int opt_max_id = opt_sys->values.size()-1; - for (int i = 0; i < opt_cur->values.size(); i++) - { - int init_id = i <= opt_max_id ? i : 0; - if (opt_cur->values[i] == opt_sys->values[init_id]) - vec->emplace_back(opt_key + "#" + std::to_string(i)); + // value isn't equal to system value + if ((opt.second & osSystemValue) == 0){ + // value is equal to last saved + if ((opt.second & osInitValue) != 0) + color = &m_default_text_clr; + // value is modified + else + color = &m_modified_label_clr; + } + if (opt.first == "bed_shape" || opt.first == "compatible_printers") { + if (m_colored_Label != nullptr) { + m_colored_Label->SetForegroundColour(*color); + m_colored_Label->Refresh(true); + } + continue; + } + + Field* field = get_field(opt.first); + if (field == nullptr) continue; + field->set_label_colour_force(color); + } + Thaw(); + + auto cur_item = m_treectrl->GetFirstVisibleItem(); + while (cur_item){ + auto title = m_treectrl->GetItemText(cur_item); + for (auto page : m_pages) + { + if (page->title() != title) + continue; + + const wxColor *clr = !page->m_is_nonsys_values ? &m_sys_label_clr : + page->m_is_modified_values ? &m_modified_label_clr : + &m_default_text_clr; + + m_treectrl->SetItemTextColour(cur_item, *clr); + break; + } + cur_item = m_treectrl->GetNextVisible(cur_item); } } // Update UI according to changes void Tab::update_changed_ui() { - auto dirty_options = m_presets->current_dirty_options(); + if (m_postpone_update_ui) + return; - if (name() == "printer"){ - // Update dirty_options in case changes of Extruder's options + const bool is_printer_type = (name() == "printer"); + auto dirty_options = m_presets->current_dirty_options(is_printer_type); + auto nonsys_options = m_presets->current_different_from_parent_options(is_printer_type); + if (is_printer_type){ TabPrinter* tab = static_cast(this); - m_dirty_options.resize(0); - for (auto opt_key : dirty_options) - { - if (opt_key == "bed_shape"){ m_dirty_options.emplace_back(opt_key); continue; } - switch (m_config->option(opt_key)->type()) - { - case coInts: add_correct_opts_to_dirty_options(opt_key, &m_dirty_options, tab); break; - case coBools: add_correct_opts_to_dirty_options(opt_key, &m_dirty_options, tab); break; - case coFloats: add_correct_opts_to_dirty_options(opt_key, &m_dirty_options, tab); break; - case coStrings: add_correct_opts_to_dirty_options(opt_key, &m_dirty_options, tab); break; - case coPercents:add_correct_opts_to_dirty_options(opt_key, &m_dirty_options, tab); break; - case coPoints: add_correct_opts_to_dirty_options(opt_key, &m_dirty_options, tab); break; - default: m_dirty_options.emplace_back(opt_key); break; - } - } if (tab->m_initial_extruders_count != tab->m_extruders_count) - m_dirty_options.emplace_back("extruders_count"); - - m_sys_options.resize(0); - const auto sys_preset = m_presets->get_selected_preset_parent(); - if (sys_preset){ - for (auto opt_key : m_config->keys()) - { - if (opt_key == "bed_shape"){ - if (*tab->m_config->option(opt_key) == *sys_preset->config.option(opt_key)) - m_sys_options.emplace_back(opt_key); - continue; - } - switch (m_config->option(opt_key)->type()) - { - case coInts: add_correct_opts_to_sys_options(opt_key, &m_sys_options, tab); break; - case coBools: add_correct_opts_to_sys_options(opt_key, &m_sys_options, tab); break; - case coFloats: add_correct_opts_to_sys_options(opt_key, &m_sys_options, tab); break; - case coStrings: add_correct_opts_to_sys_options(opt_key, &m_sys_options, tab); break; - case coPercents:add_correct_opts_to_sys_options(opt_key, &m_sys_options, tab); break; - case coPoints: add_correct_opts_to_sys_options(opt_key, &m_sys_options, tab); break; - default:{ - const ConfigOption *opt_cur = tab->m_config->option(opt_key); - const ConfigOption *opt_sys = sys_preset->config.option(opt_key); - if (opt_cur != nullptr && opt_sys != nullptr && *opt_cur == *opt_sys) - m_sys_options.emplace_back(opt_key); - break; - } - } - } - - if (tab->m_sys_extruders_count == tab->m_extruders_count) - m_sys_options.emplace_back("extruders_count"); - } - } - else{ - m_sys_options = m_presets->system_equal_options(); - m_dirty_options = dirty_options; + dirty_options.emplace_back("extruders_count"); + if (tab->m_sys_extruders_count != tab->m_extruders_count) + nonsys_options.emplace_back("extruders_count"); } + for (auto& it : m_options_list) + it.second = m_opt_status_value; + + for (auto opt_key : dirty_options) m_options_list[opt_key] &= ~osInitValue; + for (auto opt_key : nonsys_options) m_options_list[opt_key] &= ~osSystemValue; + Freeze(); //update options "decoration" - for (const auto opt_key : m_full_options_list) + for (const auto opt : m_options_list) { bool is_nonsys_value = false; bool is_modified_value = true; - std::string sys_icon = "sys_lock.png"; - std::string icon = "action_undo.png"; - wxColour color = get_sys_label_clr(); - if (find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end()) { + const wxBitmap *sys_icon = &m_bmp_value_lock; + const wxBitmap *icon = &m_bmp_value_revert; + + const wxColour *color = &m_sys_label_clr; + + const wxString *sys_tt = &m_tt_value_lock; + const wxString *tt = &m_tt_value_revert; + + // value isn't equal to system value + if ((opt.second & osSystemValue) == 0){ is_nonsys_value = true; - sys_icon = m_nonsys_btn_icon; - if(find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) == m_dirty_options.end()) - color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); + sys_icon = m_bmp_non_system; + sys_tt = m_tt_non_system; + // value is equal to last saved + if ((opt.second & osInitValue) != 0) + color = &m_default_text_clr; + // value is modified else - color = get_modified_label_clr(); + color = &m_modified_label_clr; } - if (find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) == m_dirty_options.end()) + if ((opt.second & osInitValue) != 0) { is_modified_value = false; - icon = "bullet_white.png"; + icon = &m_bmp_white_bullet; + tt = &m_tt_white_bullet; } - if (opt_key == "bed_shape" || opt_key == "compatible_printers") { + if (opt.first == "bed_shape" || opt.first == "compatible_printers") { if (m_colored_Label != nullptr) { - m_colored_Label->SetForegroundColour(color); + m_colored_Label->SetForegroundColour(*color); m_colored_Label->Refresh(true); } continue; } - Field* field = get_field(opt_key); + Field* field = get_field(opt.first); if (field == nullptr) continue; field->m_is_nonsys_value = is_nonsys_value; field->m_is_modified_value = is_modified_value; - field->m_Undo_btn->SetBitmap(wxBitmap(from_u8(var(icon)), wxBITMAP_TYPE_PNG)); - field->m_Undo_to_sys_btn->SetBitmap(wxBitmap(from_u8(var(sys_icon)), wxBITMAP_TYPE_PNG)); - if (field->m_Label != nullptr){ - field->m_Label->SetForegroundColour(color); - field->m_Label->Refresh(true); - } + field->set_undo_bitmap(icon); + field->set_undo_to_sys_bitmap(sys_icon); + field->set_undo_tooltip(tt); + field->set_undo_to_sys_tooltip(sys_tt); + field->set_label_colour(color); } Thaw(); @@ -376,67 +417,53 @@ void Tab::update_changed_ui() }); } +void Tab::init_options_list() +{ + if (!m_options_list.empty()) + m_options_list.clear(); + + for (const auto opt_key : m_config->keys()) + m_options_list.emplace(opt_key, m_opt_status_value); +} + template -void add_correct_opts_to_full_options_list(const std::string &opt_key, std::vector *vec, TabPrinter *tab) +void add_correct_opts_to_options_list(const std::string &opt_key, std::map& map, TabPrinter *tab, const int& value) { T *opt_cur = static_cast(tab->m_config->option(opt_key)); for (int i = 0; i < opt_cur->values.size(); i++) - vec->emplace_back(opt_key + "#" + std::to_string(i)); + map.emplace(opt_key + "#" + std::to_string(i), value); } -void Tab::update_full_options_list() +void TabPrinter::init_options_list() { - if (!m_full_options_list.empty()) - m_full_options_list.resize(0); + if (!m_options_list.empty()) + m_options_list.clear(); - if (m_name != "printer"){ - m_full_options_list = m_config->keys(); - return; - } - - TabPrinter* tab = static_cast(this); for (const auto opt_key : m_config->keys()) { if (opt_key == "bed_shape"){ - m_full_options_list.emplace_back(opt_key); + m_options_list.emplace(opt_key, m_opt_status_value); continue; } switch (m_config->option(opt_key)->type()) { - case coInts: add_correct_opts_to_full_options_list(opt_key, &m_full_options_list, tab); break; - case coBools: add_correct_opts_to_full_options_list(opt_key, &m_full_options_list, tab); break; - case coFloats: add_correct_opts_to_full_options_list(opt_key, &m_full_options_list, tab); break; - case coStrings: add_correct_opts_to_full_options_list(opt_key, &m_full_options_list, tab); break; - case coPercents:add_correct_opts_to_full_options_list(opt_key, &m_full_options_list, tab); break; - case coPoints: add_correct_opts_to_full_options_list(opt_key, &m_full_options_list, tab); break; - default: m_full_options_list.emplace_back(opt_key); break; + case coInts: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + case coBools: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + case coFloats: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + case coStrings: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + case coPercents:add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + case coPoints: add_correct_opts_to_options_list(opt_key, m_options_list, this, m_opt_status_value); break; + default: m_options_list.emplace(opt_key, m_opt_status_value); break; } } - m_full_options_list.emplace_back("extruders_count"); -} - -void Tab::update_sys_ui_after_sel_preset() -{ - for (const auto opt_key : m_full_options_list){ - Field* field = get_field(opt_key); - if (field != nullptr){ - field->m_Undo_to_sys_btn->SetBitmap(wxBitmap(from_u8(var(m_nonsys_btn_icon)), wxBITMAP_TYPE_PNG)); - field->m_is_nonsys_value = true; - if (field->m_Label != nullptr){ - field->m_Label->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); - field->m_Label->Refresh(true); - } - } - } - m_sys_options.resize(0); + m_options_list.emplace("extruders_count", m_opt_status_value); } void Tab::get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool& modified_page) { - if (sys_page && find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end()) - sys_page = false; - if (!modified_page && find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) != m_dirty_options.end()) - modified_page = true; + auto opt = m_options_list.find(opt_key); + if (sys_page) sys_page = (opt->second & osSystemValue) != 0; + if (!modified_page) modified_page = (opt->second & osInitValue) == 0; } void Tab::update_changed_tree_ui() @@ -457,7 +484,7 @@ void Tab::update_changed_tree_ui() get_sys_and_mod_flags(opt_key, sys_page, modified_page); } } - if (title == _("Dependencies")){ + if (title == _("Dependencies") && name() != "printer"){ get_sys_and_mod_flags("compatible_printers", sys_page, modified_page); } for (auto group : page->m_optgroups) @@ -469,12 +496,13 @@ void Tab::update_changed_tree_ui() get_sys_and_mod_flags(opt_key, sys_page, modified_page); } } - if (sys_page) - m_treectrl->SetItemTextColour(cur_item, get_sys_label_clr()); - else if (modified_page) - m_treectrl->SetItemTextColour(cur_item, get_modified_label_clr()); - else - m_treectrl->SetItemTextColour(cur_item, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); + + const wxColor *clr = sys_page ? &m_sys_label_clr : + modified_page ? &m_modified_label_clr : + &m_default_text_clr; + + if (page->set_item_colour(clr)) + m_treectrl->SetItemTextColour(cur_item, *clr); page->m_is_nonsys_values = !sys_page; page->m_is_modified_values = modified_page; @@ -493,80 +521,62 @@ void Tab::update_changed_tree_ui() void Tab::update_undo_buttons() { - const std::string& undo_icon = !m_is_modified_values ? "bullet_white.png" : "action_undo.png"; - const std::string& undo_to_sys_icon = m_is_nonsys_values ? m_nonsys_btn_icon : "sys_lock.png"; + m_undo_btn->SetBitmap(m_is_modified_values ? m_bmp_value_revert : m_bmp_white_bullet); + m_undo_to_sys_btn->SetBitmap(m_is_nonsys_values ? *m_bmp_non_system : m_bmp_value_lock); - m_undo_btn->SetBitmap(wxBitmap(from_u8(var(undo_icon)), wxBITMAP_TYPE_PNG)); - m_undo_to_sys_btn->SetBitmap(wxBitmap(from_u8(var(undo_to_sys_icon)), wxBITMAP_TYPE_PNG)); + m_undo_btn->SetToolTip(m_is_modified_values ? m_ttg_value_revert : m_ttg_white_bullet); + m_undo_to_sys_btn->SetToolTip(m_is_nonsys_values ? *m_ttg_non_system : m_ttg_value_lock); } -void Tab::on_back_to_initial_value() +void Tab::on_roll_back_value(const bool to_sys /*= true*/) { - if (!m_is_modified_values) return; + int os; + if (to_sys) { + if (!m_is_nonsys_values) return; + os = osSystemValue; + } + else { + if (!m_is_modified_values) return; + os = osInitValue; + } + + m_postpone_update_ui = true; auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection()); for (auto page : m_pages) if (page->title() == selection) { for (auto group : page->m_optgroups){ if (group->title == _("Capabilities")){ - if (find(m_dirty_options.begin(), m_dirty_options.end(), "extruders_count") != m_dirty_options.end()) - group->back_to_initial_value("extruders_count"); + if ((m_options_list["extruders_count"] & os) == 0) + to_sys ? group->back_to_sys_value("extruders_count") : group->back_to_initial_value("extruders_count"); } if (group->title == _("Size and coordinates")){ - if (find(m_dirty_options.begin(), m_dirty_options.end(), "bed_shape") != m_dirty_options.end()) - group->back_to_initial_value("bed_shape"); - } - if (group->title == _("Profile dependencies")){ - if (find(m_dirty_options.begin(), m_dirty_options.end(), "compatible_printers") != m_dirty_options.end()) - group->back_to_initial_value("compatible_printers"); + if ((m_options_list["bed_shape"] & os) == 0){ + to_sys ? group->back_to_sys_value("bed_shape") : group->back_to_initial_value("bed_shape"); + load_key_value("bed_shape", true/*some value*/, true); + } - bool is_empty = m_config->option("compatible_printers")->values.empty(); - m_compatible_printers_checkbox->SetValue(is_empty); - is_empty ? m_compatible_printers_btn->Disable() : m_compatible_printers_btn->Enable(); + } + if (group->title == _("Profile dependencies") && name() != "printer"){ + if ((m_options_list["compatible_printers"] & os) == 0){ + to_sys ? group->back_to_sys_value("compatible_printers") : group->back_to_initial_value("compatible_printers"); + load_key_value("compatible_printers", true/*some value*/, true); + + bool is_empty = m_config->option("compatible_printers")->values.empty(); + m_compatible_printers_checkbox->SetValue(is_empty); + is_empty ? m_compatible_printers_btn->Disable() : m_compatible_printers_btn->Enable(); + } } for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) { const std::string& opt_key = it->first; - if (find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) != m_dirty_options.end()) - group->back_to_initial_value(opt_key); + if ((m_options_list[opt_key] & os) == 0) + to_sys ? group->back_to_sys_value(opt_key) : group->back_to_initial_value(opt_key); } } break; } - update_changed_ui(); -} -void Tab::on_back_to_sys_value() -{ - if (!m_is_nonsys_values) return; - - auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection()); - for (auto page : m_pages) - if (page->title() == selection) { - for (auto group : page->m_optgroups) { - if (group->title == _("Capabilities")){ - if (find(m_sys_options.begin(), m_sys_options.end(), "extruders_count") == m_sys_options.end()) - group->back_to_sys_value("extruders_count"); - } - if (group->title == _("Size and coordinates")){ - if (find(m_sys_options.begin(), m_sys_options.end(), "bed_shape") == m_sys_options.end()) - group->back_to_sys_value("bed_shape"); - } - if (group->title == _("Profile dependencies")){ - if (find(m_sys_options.begin(), m_sys_options.end(), "compatible_printers") == m_sys_options.end()) - group->back_to_sys_value("compatible_printers"); - - bool is_empty = m_config->option("compatible_printers")->values.empty(); - m_compatible_printers_checkbox->SetValue(is_empty); - is_empty ? m_compatible_printers_btn->Disable() : m_compatible_printers_btn->Enable(); - } - for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) { - const std::string& opt_key = it->first; - if (find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end()) - group->back_to_sys_value(opt_key); - } - } - break; - } + m_postpone_update_ui = false; update_changed_ui(); } @@ -581,7 +591,7 @@ void Tab::update_dirty(){ void Tab::update_tab_ui() { - m_presets->update_tab_ui(m_presets_choice, m_show_incompatible_presets); + m_selected_preset_item = m_presets->update_tab_ui(m_presets_choice, m_show_incompatible_presets); // update_tab_presets(m_cc_presets_choice, m_show_incompatible_presets); // update_presetsctrl(m_presetctrl, m_show_incompatible_presets); } @@ -636,9 +646,11 @@ bool Tab::set_value(const t_config_option_key& opt_key, const boost::any& value) // To be called by custom widgets, load a value into a config, // update the preset selection boxes (the dirty flags) -void Tab::load_key_value(const std::string& opt_key, const boost::any& value) +// If value is saved before calling this function, put saved_value = true, +// and value can be some random value because in this case it will not been used +void Tab::load_key_value(const std::string& opt_key, const boost::any& value, bool saved_value /*= false*/) { - change_opt_value(*m_config, opt_key, value); + if (!saved_value) change_opt_value(*m_config, opt_key, value); // Mark the print & filament enabled if they are compatible with the currently selected preset. if (opt_key.compare("compatible_printers") == 0) { // Don't select another profile if this profile happens to become incompatible. @@ -717,13 +729,52 @@ void Tab::on_presets_changed() event.SetString(m_name); g_wxMainFrame->ProcessWindowEvent(event); } + update_preset_description_line(); +} +void Tab::update_preset_description_line() +{ const Preset* parent = m_presets->get_selected_preset_parent(); - const wxString description_line = parent == nullptr ? - _(L("It's default preset")) : parent == &m_presets->get_selected_preset() ? - _(L("It's system preset")) : - _(L("Current preset is inherited from")) + ":\n" + parent->name; - m_parent_preset_description_line->SetText(description_line); + const Preset& preset = m_presets->get_edited_preset(); + + wxString description_line = preset.is_default ? + _(L("It's a default preset.")) : preset.is_system ? + _(L("It's a system preset.")) : + _(L("Current preset is inherited from ")) + (parent == nullptr ? + "default preset." : + ":\n\t" + parent->name); + + if (preset.is_default || preset.is_system) + description_line += "\n\t" + _(L("It can't be deleted or modified. ")) + + "\n\t" + _(L("Any modifications should be saved as a new preset inherited from this one. ")) + + "\n\t" + _(L("To do that please specify a new name for the preset.")); + + if (parent && parent->vendor) + { + description_line += "\n\n" + _(L("Additional information:")) + "\n"; + description_line += "\t" + _(L("vendor")) + ": " + (name()=="printer" ? "\n\t\t" : "") + parent->vendor->name + + ", ver: " + parent->vendor->config_version.to_string(); + if (name() == "printer"){ + const std::string &printer_model = preset.config.opt_string("printer_model"); + const std::string &default_print_profile = preset.config.opt_string("default_print_profile"); + const std::vector &default_filament_profiles = preset.config.option("default_filament_profile")->values; + if (!printer_model.empty()) + description_line += "\n\n\t" + _(L("printer model")) + ": \n\t\t" + printer_model; + if (!default_print_profile.empty()) + description_line += "\n\n\t" + _(L("default print profile")) + ": \n\t\t" + default_print_profile; + if (!default_filament_profiles.empty()) + { + description_line += "\n\n\t" + _(L("default filament profile")) + ": \n\t\t"; + for (auto& profile : default_filament_profiles){ + if (&profile != &*default_filament_profiles.begin()) + description_line += ", "; + description_line += profile; + } + } + } + } + + m_parent_preset_description_line->SetText(description_line, false); } void Tab::update_frequently_changed_parameters() @@ -1012,29 +1063,6 @@ void TabPrint::update() on_value_change("fill_density", fill_density); } - auto first_layer_height = m_config->option("first_layer_height")->value; - auto layer_height = m_config->opt_float("layer_height"); - if (m_config->opt_bool("wipe_tower") && - (first_layer_height != 0.2 || layer_height < 0.15 || layer_height > 0.35)) { - wxString msg_text = _(L("The Wipe Tower currently supports only:\n" - "- first layer height 0.2mm\n" - "- layer height from 0.15mm to 0.35mm\n" - "\nShall I adjust those settings in order to enable the Wipe Tower?")); - auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Wipe Tower")), wxICON_WARNING | wxYES | wxNO); - DynamicPrintConfig new_conf = *m_config; - if (dialog->ShowModal() == wxID_YES) { - const auto &val = *m_config->option("first_layer_height"); - auto percent = val.percent; - new_conf.set_key_value("first_layer_height", new ConfigOptionFloatOrPercent(0.2, percent)); - - if (m_config->opt_float("layer_height") < 0.15) new_conf.set_key_value("layer_height", new ConfigOptionFloat(0.15)); - if (m_config->opt_float("layer_height") > 0.35) new_conf.set_key_value("layer_height", new ConfigOptionFloat(0.35)); - } - else - new_conf.set_key_value("wipe_tower", new ConfigOptionBool(false)); - load_config(new_conf); - } - if (m_config->opt_bool("wipe_tower") && m_config->opt_bool("support_material") && m_config->opt_float("support_material_contact_distance") > 0. && (m_config->opt_int("support_material_extruder") != 0 || m_config->opt_int("support_material_interface_extruder") != 0)) { @@ -1284,7 +1312,7 @@ void TabFilament::build() }; optgroup->append_line(line); - optgroup = page->new_optgroup(_(L("Toolchange behaviour"))); + optgroup = page->new_optgroup(_(L("Toolchange parameters with single extruder MM printers"))); optgroup->append_single_option_line("filament_loading_speed"); optgroup->append_single_option_line("filament_unloading_speed"); optgroup->append_single_option_line("filament_toolchange_delay"); @@ -1354,6 +1382,7 @@ void TabFilament::reload_config(){ void TabFilament::update() { + Freeze(); wxString text = from_u8(PresetHints::cooling_description(m_presets->get_edited_preset())); m_cooling_description_line->SetText(text); text = from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle)); @@ -1367,6 +1396,7 @@ void TabFilament::update() for (auto el : { "min_fan_speed", "disable_fan_first_layers" }) get_field(el)->toggle(fan_always_on); + Thaw(); } void TabFilament::OnActivate() @@ -1382,7 +1412,7 @@ wxSizer* Tab::description_line_widget(wxWindow* parent, ogStaticText* *StaticTex (*StaticText)->SetFont(font); auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(*StaticText); + sizer->Add(*StaticText, 1, wxEXPAND|wxALL, 0); return sizer; } @@ -1396,6 +1426,9 @@ void TabPrinter::build() m_presets = &m_preset_bundle->printers; load_initial_data(); + // to avoid redundant memory allocation / deallocation during extruders count changing + m_pages.reserve(30); + auto *nozzle_diameter = dynamic_cast(m_config->option("nozzle_diameter")); m_initial_extruders_count = m_extruders_count = nozzle_diameter->values.size(); const Preset* parent_preset = m_presets->get_selected_preset_parent(); @@ -1673,12 +1706,34 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){ } void TabPrinter::build_extruder_pages(){ - for (auto extruder_idx = m_extruder_pages.size(); extruder_idx < m_extruders_count; ++extruder_idx){ + size_t n_before_extruders = 2; // Count of pages before Extruder pages + size_t n_after_single_extruder_MM = 2; // Count of pages after single_extruder_multi_material page + + if (m_extruders_count_old == m_extruders_count || m_extruders_count <= 2) + { + // if we have a single extruder MM setup, add a page with configuration options: + for (int i = 0; i < m_pages.size(); ++i) // first make sure it's not there already + if (m_pages[i]->title().find(_(L("Single extruder MM setup"))) != std::string::npos) { + m_pages.erase(m_pages.begin() + i); + break; + } + if (m_extruders_count > 1 && m_config->opt_bool("single_extruder_multi_material")) { + // create a page, but pretend it's an extruder page, so we can add it to m_pages ourselves + auto page = add_options_page(_(L("Single extruder MM setup")), "printer_empty.png", true); + auto optgroup = page->new_optgroup(_(L("Single extruder multimaterial parameters"))); + optgroup->append_single_option_line("cooling_tube_retraction"); + optgroup->append_single_option_line("cooling_tube_length"); + optgroup->append_single_option_line("parking_pos_retraction"); + m_pages.insert(m_pages.end() - n_after_single_extruder_MM, page); + } + } + + for (auto extruder_idx = m_extruders_count_old; extruder_idx < m_extruders_count; ++extruder_idx){ //# build page char buf[MIN_BUF_LENGTH_FOR_L]; sprintf(buf, _CHB(L("Extruder %d")), extruder_idx + 1); auto page = add_options_page(from_u8(buf), "funnel.png", true); - m_extruder_pages.push_back(page); + m_pages.insert(m_pages.begin() + n_before_extruders + extruder_idx, page); auto optgroup = page->new_optgroup(_(L("Size"))); optgroup->append_single_option_line("nozzle_diameter", extruder_idx); @@ -1716,36 +1771,11 @@ void TabPrinter::build_extruder_pages(){ } // # remove extra pages - if (m_extruders_count <= m_extruder_pages.size()) { - m_extruder_pages.resize(m_extruders_count); - } + if (m_extruders_count < m_extruders_count_old) + m_pages.erase( m_pages.begin() + n_before_extruders + m_extruders_count, + m_pages.begin() + n_before_extruders + m_extruders_count_old); - // # rebuild page list - PageShp page_note = m_pages.back(); - m_pages.pop_back(); - while (m_pages.back()->title().find(_(L("Extruder"))) != std::string::npos) - m_pages.pop_back(); - for (auto page_extruder : m_extruder_pages) - m_pages.push_back(page_extruder); - m_pages.push_back(page_note); - - { - // if we have a single extruder MM setup, add a page with configuration options: - for (int i=0;ititle().find(_(L("Single extruder MM setup"))) != std::string::npos) { - m_pages.erase(m_pages.begin()+i); - break; - } - if ( m_extruder_pages.size()>1 && m_config->opt_bool("single_extruder_multi_material")) { - // create a page, but pretend it's an extruder page, so we can add it to m_pages ourselves - auto page = add_options_page(_(L("Single extruder MM setup")), "printer_empty.png",true); - auto optgroup = page->new_optgroup(_(L("Single extruder multimaterial parameters"))); - optgroup->append_single_option_line("cooling_tube_retraction"); - optgroup->append_single_option_line("cooling_tube_length"); - optgroup->append_single_option_line("parking_pos_retraction"); - m_pages.insert(m_pages.begin()+1,page); - } - } + m_extruders_count_old = m_extruders_count; rebuild_page_tree(); } @@ -1847,14 +1877,15 @@ void Tab::load_current_preset() { auto preset = m_presets->get_edited_preset(); - preset.is_default ? m_btn_delete_preset->Disable() : m_btn_delete_preset->Enable(true); + (preset.is_default || preset.is_system) ? m_btn_delete_preset->Disable() : m_btn_delete_preset->Enable(true); update(); // For the printer profile, generate the extruder pages. on_preset_loaded(); // Reload preset pages with the new configuration values. reload_config(); - const Preset* parent = m_presets->get_selected_preset_parent(); - m_nonsys_btn_icon = parent == nullptr ? "bullet_white.png" : "sys_unlock.png"; + m_bmp_non_system = m_presets->get_selected_preset_parent() ? &m_bmp_value_unlock : &m_bmp_white_bullet; + m_ttg_non_system = m_presets->get_selected_preset_parent() ? &m_ttg_value_unlock : &m_ttg_white_bullet_ns; + m_tt_non_system = m_presets->get_selected_preset_parent() ? &m_tt_value_unlock : &m_ttg_white_bullet_ns; // 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 @@ -1875,8 +1906,8 @@ void Tab::load_current_preset() static_cast(this)->m_sys_extruders_count = parent_preset == nullptr ? 0 : static_cast(parent_preset->config.option("nozzle_diameter"))->values.size(); } - update_sys_ui_after_sel_preset(); - update_full_options_list(); + m_opt_status_value = (m_presets->get_selected_preset_parent() ? osSystemValue : 0) | osInitValue; + init_options_list(); update_changed_ui(); }); } @@ -1888,11 +1919,13 @@ void Tab::rebuild_page_tree() // get label of the currently selected item auto selected = m_treectrl->GetItemText(m_treectrl->GetSelection()); auto rootItem = m_treectrl->GetRootItem(); - m_treectrl->DeleteChildren(rootItem); + auto have_selection = 0; + m_treectrl->DeleteChildren(rootItem); for (auto p : m_pages) { auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID()); + m_treectrl->SetItemTextColour(itemId, p->get_item_colour()); if (p->title() == selected) { m_disable_tree_sel_changed_event = 1; m_treectrl->SelectItem(itemId); @@ -1900,7 +1933,7 @@ void Tab::rebuild_page_tree() have_selection = 1; } } - + if (!have_selection) { // this is triggered on first load, so we don't disable the sel change event m_treectrl->SelectItem(m_treectrl->GetFirstVisibleItem());//! (treectrl->GetFirstChild(rootItem)); @@ -2016,6 +2049,8 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr void Tab::OnTreeSelChange(wxTreeEvent& event) { if (m_disable_tree_sel_changed_event) return; + wxWindowUpdateLocker noUpdates(this); + Page* page = nullptr; auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection()); for (auto p : m_pages) @@ -2142,7 +2177,7 @@ void Tab::toggle_show_hide_incompatible() void Tab::update_show_hide_incompatible_button() { m_btn_hide_incompatible_presets->SetBitmap(m_show_incompatible_presets ? - *m_bmp_show_incompatible_presets : *m_bmp_hide_incompatible_presets); + m_bmp_show_incompatible_presets : m_bmp_hide_incompatible_presets); m_btn_hide_incompatible_presets->SetToolTip(m_show_incompatible_presets ? "Both compatible an incompatible presets are shown. Click to hide presets not compatible with the current printer." : "Only compatible presets are shown. Click to show both the presets compatible and not compatible with the current printer."); @@ -2402,6 +2437,75 @@ void Tab::update_tab_presets(wxComboCtrl* ui, bool show_incompatible) ui->Thaw(); } +void Tab::fill_icon_descriptions() +{ + m_icon_descriptions.push_back(t_icon_description(&m_bmp_value_lock, L("LOCKED LOCK;" + "indicates that the settings are the same as the system values for the current option group"))); + + m_icon_descriptions.push_back(t_icon_description(&m_bmp_value_unlock, L("UNLOCKED LOCK;" + "indicates that some settings were changed and are not equal to the system values for " + "the current option group.\n" + "Click the UNLOCKED LOCK icon to reset all settings for current option group to " + "the system values."))); + + m_icon_descriptions.push_back(t_icon_description(&m_bmp_white_bullet, L("WHITE BULLET;" + "for the left button: \tindicates a non-system preset,\n" + "for the right button: \tindicates that the settings hasn't been modified."))); + + m_icon_descriptions.push_back(t_icon_description(&m_bmp_value_revert, L("BACK ARROW;" + "indicates that the settings were changed and are not equal to the last saved preset for " + "the current option group.\n" + "Click the BACK ARROW icon to reset all settings for the current option group to " + "the last saved preset."))); +} + +void Tab::set_tooltips_text() +{ +// m_undo_to_sys_btn->SetToolTip(_(L( "LOCKED LOCK icon indicates that the settings are the same as the system values " +// "for the current option group.\n" +// "UNLOCKED LOCK icon indicates that some settings were changed and are not equal " +// "to the system values for the current option group.\n" +// "WHITE BULLET icon indicates a non system preset.\n\n" +// "Click the UNLOCKED LOCK icon to reset all settings for current option group to " +// "the system values."))); +// +// m_undo_btn->SetToolTip(_(L( "WHITE BULLET icon indicates that the settings are the same as in the last saved" +// "preset for the current option group.\n" +// "BACK ARROW icon indicates that the settings were changed and are not equal to " +// "the last saved preset for the current option group.\n\n" +// "Click the BACK ARROW icon to reset all settings for the current option group to " +// "the last saved preset."))); + + // --- Tooltip text for reset buttons (for whole options group) + // Text to be shown on the "Revert to system" aka "Lock to system" button next to each input field. + m_ttg_value_lock = _(L("LOCKED LOCK icon indicates that the settings are the same as the system values " + "for the current option group")); + m_ttg_value_unlock = _(L("UNLOCKED LOCK icon indicates that some settings were changed and are not equal " + "to the system values for the current option group.\n" + "Click to reset all settings for current option group to the system values.")); + m_ttg_white_bullet_ns = _(L("WHITE BULLET icon indicates a non system preset.")); + m_ttg_non_system = &m_ttg_white_bullet_ns; + // Text to be shown on the "Undo user changes" button next to each input field. + m_ttg_white_bullet = _(L("WHITE BULLET icon indicates that the settings are the same as in the last saved " + "preset for the current option group.")); + m_ttg_value_revert = _(L("BACK ARROW icon indicates that the settings were changed and are not equal to " + "the last saved preset for the current option group.\n" + "Click to reset all settings for the current option group to the last saved preset.")); + + // --- Tooltip text for reset buttons (for each option in group) + // Text to be shown on the "Revert to system" aka "Lock to system" button next to each input field. + m_tt_value_lock = _(L("LOCKED LOCK icon indicates that the value is the same as the system value.")); + m_tt_value_unlock = _(L("UNLOCKED LOCK icon indicates that the value was changed and is not equal " + "to the system value.\n" + "Click to reset current value to the system value.")); + // m_tt_white_bullet_ns= _(L("WHITE BULLET icon indicates a non system preset.")); + m_tt_non_system = &m_ttg_white_bullet_ns; + // Text to be shown on the "Undo user changes" button next to each input field. + m_tt_white_bullet = _(L("WHITE BULLET icon indicates that the value is the same as in the last saved preset.")); + m_tt_value_revert = _(L("BACK ARROW icon indicates that the value was changed and is not equal to the last saved preset.\n" + "Click to reset current value to the last saved preset.")); +} + void Page::reload_config() { for (auto group : m_optgroups) @@ -2460,10 +2564,6 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la return static_cast(GetParent())->m_presets->get_selected_preset_parent() != nullptr; }; - optgroup->nonsys_btn_icon = [this](){ - return static_cast(GetParent())->m_nonsys_btn_icon; - }; - vsizer()->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10); m_optgroups.push_back(optgroup); diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp index f9ee4f363..62030bce3 100644 --- a/xs/src/slic3r/GUI/Tab.hpp +++ b/xs/src/slic3r/GUI/Tab.hpp @@ -1,3 +1,6 @@ +#ifndef slic3r_Tab_hpp_ +#define slic3r_Tab_hpp_ + // The "Expert" tab at the right of the main tabbed window. // // This file implements following packages: @@ -34,6 +37,9 @@ namespace Slic3r { namespace GUI { +typedef std::pair t_icon_description; +typedef std::vector> t_icon_descriptions; + // Single Tab page containing a{ vsizer } of{ optgroups } // package Slic3r::GUI::Tab::Page; using ConfigOptionsGroupShp = std::shared_ptr; @@ -51,6 +57,7 @@ public: { Create(m_parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); m_vsizer = new wxBoxSizer(wxVERTICAL); + m_item_color = &get_label_clr_default(); SetSizer(m_vsizer); } ~Page(){} @@ -71,6 +78,22 @@ public: Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const; bool set_value(const t_config_option_key& opt_key, const boost::any& value); ConfigOptionsGroupShp new_optgroup(const wxString& title, int noncommon_label_width = -1); + + bool set_item_colour(const wxColour *clr) { + if (m_item_color != clr) { + m_item_color = clr; + return true; + } + return false; + } + + const wxColour get_item_colour() { + return *m_item_color; + } + +protected: + // Color of TreeCtrlItem. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one. + const wxColour* m_item_color; }; // Slic3r::GUI::Tab; @@ -85,8 +108,6 @@ protected: wxBitmapComboBox* m_presets_choice; wxBitmapButton* m_btn_save_preset; wxBitmapButton* m_btn_delete_preset; - wxBitmap* m_bmp_show_incompatible_presets; - wxBitmap* m_bmp_hide_incompatible_presets; wxBitmapButton* m_btn_hide_incompatible_presets; wxBoxSizer* m_hsizer; wxBoxSizer* m_left_sizer; @@ -96,10 +117,51 @@ protected: wxButton* m_compatible_printers_btn; wxButton* m_undo_btn; wxButton* m_undo_to_sys_btn; + wxButton* m_question_btn; + wxComboCtrl* m_cc_presets_choice; wxDataViewTreeCtrl* m_presetctrl; wxImageList* m_preset_icons; + // Cached bitmaps. + // A "flag" icon to be displayned next to the preset name in the Tab's combo box. + wxBitmap m_bmp_show_incompatible_presets; + wxBitmap m_bmp_hide_incompatible_presets; + // Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field. + wxBitmap m_bmp_value_lock; + wxBitmap m_bmp_value_unlock; + wxBitmap m_bmp_white_bullet; + // The following bitmap points to either m_bmp_value_unlock or m_bmp_white_bullet, depending on whether the current preset has a parent preset. + wxBitmap *m_bmp_non_system; + // Bitmaps to be shown on the "Undo user changes" button next to each input field. + wxBitmap m_bmp_value_revert; +// wxBitmap m_bmp_value_unmodified; + wxBitmap m_bmp_question; + + // Colors for ui "decoration" + wxColour m_sys_label_clr; + wxColour m_modified_label_clr; + wxColour m_default_text_clr; + + // Tooltip text for reset buttons (for whole options group) + wxString m_ttg_value_lock; + wxString m_ttg_value_unlock; + wxString m_ttg_white_bullet_ns; + // The following text points to either m_ttg_value_unlock or m_ttg_white_bullet_ns, depending on whether the current preset has a parent preset. + wxString *m_ttg_non_system; + // Tooltip text to be shown on the "Undo user changes" button next to each input field. + wxString m_ttg_white_bullet; + wxString m_ttg_value_revert; + + // Tooltip text for reset buttons (for each option in group) + wxString m_tt_value_lock; + wxString m_tt_value_unlock; + // The following text points to either m_tt_value_unlock or m_ttg_white_bullet_ns, depending on whether the current preset has a parent preset. + wxString *m_tt_non_system; + // Tooltip text to be shown on the "Undo user changes" button next to each input field. + wxString m_tt_white_bullet; + wxString m_tt_value_revert; + int m_icon_count; std::map m_icon_index; // Map from an icon file name to its index std::vector m_pages; @@ -108,9 +170,11 @@ protected: bool m_no_controller; std::vector m_reload_dependent_tabs = {}; - std::vector m_dirty_options = {}; - std::vector m_sys_options = {}; - std::vector m_full_options_list = {}; + enum OptStatus { osSystemValue = 1, osInitValue = 2 }; + std::map m_options_list; + int m_opt_status_value; + + t_icon_descriptions m_icon_descriptions = {}; // The two following two event IDs are generated at Plater.pm by calling Wx::NewEventType. wxEventType m_event_value_change = 0; @@ -118,13 +182,15 @@ protected: bool m_is_modified_values{ false }; bool m_is_nonsys_values{ true }; + bool m_postpone_update_ui {false}; + + size_t m_selected_preset_item{ 0 }; public: PresetBundle* m_preset_bundle; bool m_show_btn_incompatible_presets = false; PresetCollection* m_presets; DynamicPrintConfig* m_config; - std::string m_nonsys_btn_icon; ogStaticText* m_parent_preset_description_line; wxStaticText* m_colored_Label = nullptr; @@ -135,7 +201,9 @@ public: Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL); get_tabs_list().push_back(this); } - ~Tab() { delete_tab_from_list(this); } + ~Tab(){ + delete_tab_from_list(this); + } wxWindow* parent() const { return m_parent; } wxString title() const { return m_title; } @@ -153,7 +221,7 @@ public: wxSizer* compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox, wxButton** btn); void update_presetsctrl(wxDataViewTreeCtrl* ui, bool show_incompatible); - void load_key_value(const std::string& opt_key, const boost::any& value); + void load_key_value(const std::string& opt_key, const boost::any& value, bool saved_value = false); void reload_compatible_printers_widget(); void OnTreeSelChange(wxTreeEvent& event); @@ -164,15 +232,13 @@ public: void toggle_show_hide_incompatible(); void update_show_hide_incompatible_button(); void update_ui_from_settings(); + void update_labels_colour(); void update_changed_ui(); - void update_full_options_list(); - void update_sys_ui_after_sel_preset(); void get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool& modified_page); void update_changed_tree_ui(); void update_undo_buttons(); - void on_back_to_initial_value(); - void on_back_to_sys_value(); + void on_roll_back_value(const bool to_sys = false); PageShp add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages = false); @@ -180,6 +246,7 @@ public: virtual void on_preset_loaded(){} virtual void build() = 0; virtual void update() = 0; + virtual void init_options_list(); void load_initial_data(); void update_dirty(); void update_tab_ui(); @@ -189,20 +256,22 @@ public: bool set_value(const t_config_option_key& opt_key, const boost::any& value); wxSizer* description_line_widget(wxWindow* parent, ogStaticText** StaticText); bool current_preset_is_dirty(); + DynamicPrintConfig* get_config() { return m_config; } - PresetCollection* get_presets() - { - return m_presets; - } + PresetCollection* get_presets() { return m_presets; } std::vector get_dependent_tabs() { return m_reload_dependent_tabs; } + size_t get_selected_preset_item() { return m_selected_preset_item; } void on_value_change(const std::string& opt_key, const boost::any& value); protected: void on_presets_changed(); + void update_preset_description_line(); void update_frequently_changed_parameters(); void update_wiping_button_visibility(); void update_tab_presets(wxComboCtrl* ui, bool show_incompatible); + void fill_icon_descriptions(); + void set_tooltips_text(); }; //Slic3r::GUI::Tab::Print; @@ -248,9 +317,9 @@ public: wxButton* m_octoprint_host_test_btn; size_t m_extruders_count; + size_t m_extruders_count_old = 0; size_t m_initial_extruders_count; size_t m_sys_extruders_count; - std::vector m_extruder_pages; TabPrinter() {} TabPrinter(wxNotebook* parent, bool no_controller) : Tab(parent, _(L("Printer Settings")), "printer", no_controller) {} @@ -262,6 +331,7 @@ public: void extruders_count_changed(size_t extruders_count); void build_extruder_pages(); void on_preset_loaded() override; + void init_options_list() override; }; class SavePresetWindow :public wxDialog @@ -280,3 +350,5 @@ public: } // GUI } // Slic3r + +#endif /* slic3r_Tab_hpp_ */ diff --git a/xs/src/slic3r/GUI/TabIface.cpp b/xs/src/slic3r/GUI/TabIface.cpp index 4df0e72e5..29833322b 100644 --- a/xs/src/slic3r/GUI/TabIface.cpp +++ b/xs/src/slic3r/GUI/TabIface.cpp @@ -11,6 +11,7 @@ void TabIface::load_config(DynamicPrintConfig* config) { m_tab->load_config(*con void TabIface::load_key_value(char* opt_key, char* value){ m_tab->load_key_value(opt_key, static_cast(value)); } bool TabIface::current_preset_is_dirty() { return m_tab->current_preset_is_dirty();} void TabIface::OnActivate() { return m_tab->OnActivate();} +size_t TabIface::get_selected_preset_item() { return m_tab->get_selected_preset_item(); } std::string TabIface::title() { return m_tab->title().ToUTF8().data(); } DynamicPrintConfig* TabIface::get_config() { return m_tab->get_config(); } PresetCollection* TabIface::get_presets() { return m_tab!=nullptr ? m_tab->get_presets() : nullptr; } diff --git a/xs/src/slic3r/GUI/TabIface.hpp b/xs/src/slic3r/GUI/TabIface.hpp index 0325c855c..2f7f4e8e7 100644 --- a/xs/src/slic3r/GUI/TabIface.hpp +++ b/xs/src/slic3r/GUI/TabIface.hpp @@ -1,3 +1,6 @@ +#ifndef slic3r_TabIface_hpp_ +#define slic3r_TabIface_hpp_ + #include #include @@ -27,9 +30,12 @@ public: DynamicPrintConfig* get_config(); PresetCollection* get_presets(); std::vector get_dependent_tabs(); + size_t get_selected_preset_item(); protected: GUI::Tab *m_tab; -}; +}; // namespace GUI }; // namespace Slic3r + +#endif /* slic3r_TabIface_hpp_ */ diff --git a/xs/src/slic3r/GUI/UpdateDialogs.cpp b/xs/src/slic3r/GUI/UpdateDialogs.cpp new file mode 100644 index 000000000..70d9c851c --- /dev/null +++ b/xs/src/slic3r/GUI/UpdateDialogs.cpp @@ -0,0 +1,196 @@ +#include "UpdateDialogs.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libslic3r/libslic3r.h" +#include "libslic3r/Utils.hpp" +#include "GUI.hpp" +#include "ConfigWizard.hpp" + +namespace Slic3r { +namespace GUI { + + +static const std::string CONFIG_UPDATE_WIKI_URL("https://github.com/prusa3d/Slic3r/wiki/Slic3r-PE-1.40-configuration-update"); + + +// MsgUpdateSlic3r + +MsgUpdateSlic3r::MsgUpdateSlic3r(const Semver &ver_current, const Semver &ver_online) : + MsgDialog(nullptr, _(L("Update available")), _(L("New version of Slic3r PE is available"))), + ver_current(ver_current), + ver_online(ver_online) +{ + const auto url = wxString::Format("https://github.com/prusa3d/Slic3r/releases/tag/version_%s", ver_online.to_string()); + auto *link = new wxHyperlinkCtrl(this, wxID_ANY, url, url); + + auto *text = new wxStaticText(this, wxID_ANY, _(L("To download, follow the link below."))); + const auto link_width = link->GetSize().GetWidth(); + text->Wrap(CONTENT_WIDTH > link_width ? CONTENT_WIDTH : link_width); + content_sizer->Add(text); + content_sizer->AddSpacer(VERT_SPACING); + + auto *versions = new wxFlexGridSizer(2, 0, VERT_SPACING); + versions->Add(new wxStaticText(this, wxID_ANY, _(L("Current version:")))); + versions->Add(new wxStaticText(this, wxID_ANY, ver_current.to_string())); + versions->Add(new wxStaticText(this, wxID_ANY, _(L("New version:")))); + versions->Add(new wxStaticText(this, wxID_ANY, ver_online.to_string())); + content_sizer->Add(versions); + content_sizer->AddSpacer(VERT_SPACING); + + content_sizer->Add(link); + content_sizer->AddSpacer(2*VERT_SPACING); + + cbox = new wxCheckBox(this, wxID_ANY, _(L("Don't notify about new releases any more"))); + content_sizer->Add(cbox); + content_sizer->AddSpacer(VERT_SPACING); + + Fit(); +} + +MsgUpdateSlic3r::~MsgUpdateSlic3r() {} + +bool MsgUpdateSlic3r::disable_version_check() const +{ + return cbox->GetValue(); +} + + +// MsgUpdateConfig + +MsgUpdateConfig::MsgUpdateConfig(const std::unordered_map &updates) : + MsgDialog(nullptr, _(L("Configuration update")), _(L("Configuration update is available")), wxID_NONE) +{ + auto *text = new wxStaticText(this, wxID_ANY, _(L( + "Would you like to install it?\n\n" + "Note that a full configuration snapshot will be created first. It can then be restored at any time " + "should there be a problem with the new version.\n\n" + "Updated configuration bundles:" + ))); + text->Wrap(CONTENT_WIDTH); + content_sizer->Add(text); + content_sizer->AddSpacer(VERT_SPACING); + + auto *versions = new wxFlexGridSizer(2, 0, VERT_SPACING); + for (const auto &update : updates) { + auto *text_vendor = new wxStaticText(this, wxID_ANY, update.first); + text_vendor->SetFont(boldfont); + versions->Add(text_vendor); + versions->Add(new wxStaticText(this, wxID_ANY, update.second)); + } + + content_sizer->Add(versions); + content_sizer->AddSpacer(2*VERT_SPACING); + + auto *btn_cancel = new wxButton(this, wxID_CANCEL); + btn_sizer->Add(btn_cancel); + btn_sizer->AddSpacer(HORIZ_SPACING); + auto *btn_ok = new wxButton(this, wxID_OK); + btn_sizer->Add(btn_ok); + btn_ok->SetFocus(); + + Fit(); +} + +MsgUpdateConfig::~MsgUpdateConfig() {} + + +// MsgDataIncompatible + +MsgDataIncompatible::MsgDataIncompatible(const std::unordered_map &incompats) : + MsgDialog(nullptr, _(L("Slic3r incompatibility")), _(L("Slic3r configuration is incompatible")), wxBitmap(from_u8(Slic3r::var("Slic3r_192px_grayscale.png")), wxBITMAP_TYPE_PNG), wxID_NONE) +{ + auto *text = new wxStaticText(this, wxID_ANY, _(L( + "This version of Slic3r PE is not compatible with currently installed configuration bundles.\n" + "This probably happened as a result of running an older Slic3r PE after using a newer one.\n\n" + + "You may either exit Slic3r and try again with a newer version, or you may re-run the initial configuration. " + "Doing so will create a backup snapshot of the existing configuration before installing files compatible with this Slic3r.\n" + ))); + text->Wrap(CONTENT_WIDTH); + content_sizer->Add(text); + + auto *text2 = new wxStaticText(this, wxID_ANY, wxString::Format(_(L("This Slic3r PE version: %s")), SLIC3R_VERSION)); + text2->Wrap(CONTENT_WIDTH); + content_sizer->Add(text2); + content_sizer->AddSpacer(VERT_SPACING); + + auto *text3 = new wxStaticText(this, wxID_ANY, _(L("Incompatible bundles:"))); + text3->Wrap(CONTENT_WIDTH); + content_sizer->Add(text3); + content_sizer->AddSpacer(VERT_SPACING); + + auto *versions = new wxFlexGridSizer(2, 0, VERT_SPACING); + for (const auto &incompat : incompats) { + auto *text_vendor = new wxStaticText(this, wxID_ANY, incompat.first); + text_vendor->SetFont(boldfont); + versions->Add(text_vendor); + versions->Add(new wxStaticText(this, wxID_ANY, incompat.second)); + } + + content_sizer->Add(versions); + content_sizer->AddSpacer(2*VERT_SPACING); + + auto *btn_exit = new wxButton(this, wxID_EXIT, _(L("Exit Slic3r"))); + btn_sizer->Add(btn_exit); + btn_sizer->AddSpacer(HORIZ_SPACING); + auto *btn_reconf = new wxButton(this, wxID_REPLACE, _(L("Re-configure"))); + btn_sizer->Add(btn_reconf); + btn_exit->SetFocus(); + + auto exiter = [this](const wxCommandEvent& evt) { this->EndModal(evt.GetId()); }; + btn_exit->Bind(wxEVT_BUTTON, exiter); + btn_reconf->Bind(wxEVT_BUTTON, exiter); + + Fit(); +} + +MsgDataIncompatible::~MsgDataIncompatible() {} + + +// MsgDataLegacy + +MsgDataLegacy::MsgDataLegacy() : + MsgDialog(nullptr, _(L("Configuration update")), _(L("Configuration update"))) +{ + auto *text = new wxStaticText(this, wxID_ANY, wxString::Format( + _(L( + "Slic3r PE now uses an updated configuration structure.\n\n" + + "So called 'System presets' have been introduced, which hold the built-in default settings for various " + "printers. These System presets cannot be modified, instead, users now may create their " + "own presets inheriting settings from one of the System presets.\n" + "An inheriting preset may either inherit a particular value from its parent or override it with a customized value.\n\n" + + "Please proceed with the %s that follows to set up the new presets " + "and to choose whether to enable automatic preset updates." + )), + ConfigWizard::name() + )); + text->Wrap(CONTENT_WIDTH); + content_sizer->Add(text); + content_sizer->AddSpacer(VERT_SPACING); + + auto *text2 = new wxStaticText(this, wxID_ANY, _(L("For more information please visit our wiki page:"))); + static const wxString url("https://github.com/prusa3d/Slic3r/wiki/Slic3r-PE-1.40-configuration-update"); + // The wiki page name is intentionally not localized: + auto *link = new wxHyperlinkCtrl(this, wxID_ANY, "Slic3r PE 1.40 configuration update", CONFIG_UPDATE_WIKI_URL); + content_sizer->Add(text2); + content_sizer->Add(link); + content_sizer->AddSpacer(VERT_SPACING); + + Fit(); +} + +MsgDataLegacy::~MsgDataLegacy() {} + + +} +} diff --git a/xs/src/slic3r/GUI/UpdateDialogs.hpp b/xs/src/slic3r/GUI/UpdateDialogs.hpp new file mode 100644 index 000000000..62548b98b --- /dev/null +++ b/xs/src/slic3r/GUI/UpdateDialogs.hpp @@ -0,0 +1,81 @@ +#ifndef slic3r_UpdateDialogs_hpp_ +#define slic3r_UpdateDialogs_hpp_ + +#include +#include + +#include "slic3r/Utils/Semver.hpp" +#include "MsgDialog.hpp" + +class wxBoxSizer; +class wxCheckBox; + +namespace Slic3r { + +namespace GUI { + + +// A confirmation dialog listing configuration updates +class MsgUpdateSlic3r : public MsgDialog +{ +public: + MsgUpdateSlic3r(const Semver &ver_current, const Semver &ver_online); + MsgUpdateSlic3r(MsgUpdateSlic3r &&) = delete; + MsgUpdateSlic3r(const MsgUpdateSlic3r &) = delete; + MsgUpdateSlic3r &operator=(MsgUpdateSlic3r &&) = delete; + MsgUpdateSlic3r &operator=(const MsgUpdateSlic3r &) = delete; + virtual ~MsgUpdateSlic3r(); + + // Tells whether the user checked the "don't bother me again" checkbox + bool disable_version_check() const; + +private: + const Semver &ver_current; + const Semver &ver_online; + wxCheckBox *cbox; +}; + + +// Confirmation dialog informing about configuration update. Lists updated bundles & their versions. +class MsgUpdateConfig : public MsgDialog +{ +public: + // updates is a map of "vendor name" -> "version (comment)" + MsgUpdateConfig(const std::unordered_map &updates); + MsgUpdateConfig(MsgUpdateConfig &&) = delete; + MsgUpdateConfig(const MsgUpdateConfig &) = delete; + MsgUpdateConfig &operator=(MsgUpdateConfig &&) = delete; + MsgUpdateConfig &operator=(const MsgUpdateConfig &) = delete; + ~MsgUpdateConfig(); +}; + +// Informs about currently installed bundles not being compatible with the running Slic3r. Asks about action. +class MsgDataIncompatible : public MsgDialog +{ +public: + // incompats is a map of "vendor name" -> "version restrictions" + MsgDataIncompatible(const std::unordered_map &incompats); + MsgDataIncompatible(MsgDataIncompatible &&) = delete; + MsgDataIncompatible(const MsgDataIncompatible &) = delete; + MsgDataIncompatible &operator=(MsgDataIncompatible &&) = delete; + MsgDataIncompatible &operator=(const MsgDataIncompatible &) = delete; + ~MsgDataIncompatible(); +}; + +// Informs about a legacy data directory - an update from Slic3r PE < 1.40 +class MsgDataLegacy : public MsgDialog +{ +public: + MsgDataLegacy(); + MsgDataLegacy(MsgDataLegacy &&) = delete; + MsgDataLegacy(const MsgDataLegacy &) = delete; + MsgDataLegacy &operator=(MsgDataLegacy &&) = delete; + MsgDataLegacy &operator=(const MsgDataLegacy &) = delete; + ~MsgDataLegacy(); +}; + + +} +} + +#endif diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.cpp b/xs/src/slic3r/GUI/WipeTowerDialog.cpp index b34de0745..4b25ccd3a 100644 --- a/xs/src/slic3r/GUI/WipeTowerDialog.cpp +++ b/xs/src/slic3r/GUI/WipeTowerDialog.cpp @@ -79,15 +79,15 @@ RammingPanel::RammingPanel(wxWindow* parent, const std::string& parameters) m_widget_ramming_step_multiplicator = new wxSpinCtrl(this,wxID_ANY,wxEmptyString,wxDefaultPosition,wxSize(75, -1),wxSP_ARROW_KEYS,10,200,100); auto gsizer_param = new wxFlexGridSizer(2, 5, 15); - gsizer_param->Add(new wxStaticText(this, wxID_ANY, wxString(_(L("Total ramming time (s):")))), 0, wxALIGN_CENTER_VERTICAL); + gsizer_param->Add(new wxStaticText(this, wxID_ANY, wxString(_(L("Total ramming time")) + " (" + _(L("s")) + "):")), 0, wxALIGN_CENTER_VERTICAL); gsizer_param->Add(m_widget_time); - gsizer_param->Add(new wxStaticText(this, wxID_ANY, wxString(_(L("Total rammed volume (mm"))+"\u00B3):")), 0, wxALIGN_CENTER_VERTICAL); + gsizer_param->Add(new wxStaticText(this, wxID_ANY, wxString(_(L("Total rammed volume")) + " (" + _(L("mm")) + "\u00B3):")), 0, wxALIGN_CENTER_VERTICAL); gsizer_param->Add(m_widget_volume); gsizer_param->AddSpacer(20); gsizer_param->AddSpacer(20); - gsizer_param->Add(new wxStaticText(this, wxID_ANY, wxString(_(L("Ramming line width (%):")))), 0, wxALIGN_CENTER_VERTICAL); + gsizer_param->Add(new wxStaticText(this, wxID_ANY, wxString(_(L("Ramming line width")) + " (%):")), 0, wxALIGN_CENTER_VERTICAL); gsizer_param->Add(m_widget_ramming_line_width_multiplicator); - gsizer_param->Add(new wxStaticText(this, wxID_ANY, wxString(_(L("Ramming line spacing (%):")))), 0, wxALIGN_CENTER_VERTICAL); + gsizer_param->Add(new wxStaticText(this, wxID_ANY, wxString(_(L("Ramming line spacing")) + " (%):")), 0, wxALIGN_CENTER_VERTICAL); gsizer_param->Add(m_widget_ramming_step_multiplicator); sizer_param->Add(gsizer_param, 0, wxTOP, 100); @@ -220,7 +220,7 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, con // collect and format sizer format_sizer(m_sizer_advanced, m_page_advanced, m_gridsizer_advanced, - _(L("Here you can adjust required purging volume (mm\u00B3) for any given pair of tools.")), + wxString::Format(_(L("Here you can adjust required purging volume (mm%s) for any given pair of tools.")), "\u00B3"), _(L("Extruder changed to"))); // Hide preview page before new page creating @@ -243,7 +243,7 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector& matrix, con // collect and format sizer format_sizer(m_sizer_simple, m_page_simple, gridsizer_simple, _(L("Total purging volume is calculated by summing two values below, depending on which tools are loaded/unloaded.")), - _(L("Volume to purge (mm\u00B3) when the filament is being")), 50); + wxString::Format(_(L("Volume to purge (mm%s) when the filament is being")), "\u00B3"), 50); m_sizer = new wxBoxSizer(wxVERTICAL); m_sizer->Add(m_page_simple, 0, wxEXPAND | wxALL, 25); diff --git a/xs/src/slic3r/Utils/PresetUpdater.cpp b/xs/src/slic3r/Utils/PresetUpdater.cpp index bf9e1eb44..3b74b0c6b 100644 --- a/xs/src/slic3r/Utils/PresetUpdater.cpp +++ b/xs/src/slic3r/Utils/PresetUpdater.cpp @@ -1,9 +1,9 @@ #include "PresetUpdater.hpp" -#include // XXX #include #include -#include +#include +#include #include #include #include @@ -14,18 +14,13 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include #include "libslic3r/libslic3r.h" #include "libslic3r/Utils.hpp" #include "slic3r/GUI/GUI.hpp" #include "slic3r/GUI/PresetBundle.hpp" +#include "slic3r/GUI/UpdateDialogs.hpp" +#include "slic3r/GUI/ConfigWizard.hpp" #include "slic3r/Utils/Http.hpp" #include "slic3r/Config/Version.hpp" #include "slic3r/Config/Snapshot.hpp" @@ -48,84 +43,49 @@ static const char *INDEX_FILENAME = "index.idx"; static const char *TMP_EXTENSION = ".download"; -struct UpdateNotification : wxDialog -{ - // If this dialog gets any more complex, it should probably be factored out... - - enum { - CONTENT_WIDTH = 400, - BORDER = 30, - SPACING = 15, - }; - - wxCheckBox *cbox; - - UpdateNotification(const Semver &ver_current, const Semver &ver_online) : wxDialog(nullptr, wxID_ANY, _(L("Update available"))) - { - auto *topsizer = new wxBoxSizer(wxHORIZONTAL); - auto *sizer = new wxBoxSizer(wxVERTICAL); - - const auto url = wxString::Format("https://github.com/prusa3d/Slic3r/releases/tag/version_%s", ver_online.to_string()); - auto *link = new wxHyperlinkCtrl(this, wxID_ANY, url, url); - - auto *text = new wxStaticText(this, wxID_ANY, - _(L("New version of Slic3r PE is available. To download, follow the link below."))); - const auto link_width = link->GetSize().GetWidth(); - text->Wrap(CONTENT_WIDTH > link_width ? CONTENT_WIDTH : link_width); - sizer->Add(text); - sizer->AddSpacer(SPACING); - - auto *versions = new wxFlexGridSizer(2, 0, SPACING); - versions->Add(new wxStaticText(this, wxID_ANY, _(L("Current version:")))); - versions->Add(new wxStaticText(this, wxID_ANY, ver_current.to_string())); - versions->Add(new wxStaticText(this, wxID_ANY, _(L("New version:")))); - versions->Add(new wxStaticText(this, wxID_ANY, ver_online.to_string())); - sizer->Add(versions); - sizer->AddSpacer(SPACING); - - sizer->Add(link); - sizer->AddSpacer(2*SPACING); - - cbox = new wxCheckBox(this, wxID_ANY, _(L("Don't notify about new releases any more"))); - sizer->Add(cbox); - sizer->AddSpacer(SPACING); - - auto *ok = new wxButton(this, wxID_OK); - ok->SetFocus(); - sizer->Add(ok, 0, wxALIGN_CENTRE_HORIZONTAL); - - auto *logo = new wxStaticBitmap(this, wxID_ANY, wxBitmap(GUI::from_u8(Slic3r::var("Slic3r_192px.png")), wxBITMAP_TYPE_PNG)); - - topsizer->Add(logo, 0, wxALL, BORDER); - topsizer->Add(sizer, 0, wxALL, BORDER); - - SetSizerAndFit(topsizer); - } - - bool disable_version_check() const { return cbox->GetValue(); } -}; - struct Update { fs::path source; fs::path target; Version version; - Update(fs::path &&source, const fs::path &target, const Version &version) : - source(source), + Update(fs::path &&source, fs::path &&target, const Version &version) : + source(std::move(source)), target(std::move(target)), version(version) {} - Update(fs::path &&source, fs::path &&target) : - source(source), - target(std::move(target)) - {} + std::string name() const { return source.stem().string(); } - std::string name() { return source.stem().string(); } + friend std::ostream& operator<<(std::ostream& os , const Update &self) { + os << "Update(" << self.source.string() << " -> " << self.target.string() << ')'; + return os; + } }; -typedef std::vector Updates; +struct Incompat +{ + fs::path bundle; + Version version; + + Incompat(fs::path &&bundle, const Version &version) : + bundle(std::move(bundle)), + version(version) + {} + + std::string name() const { return bundle.stem().string(); } + + friend std::ostream& operator<<(std::ostream& os , const Incompat &self) { + os << "Incompat(" << self.bundle.string() << ')'; + return os; + } +}; + +struct Updates +{ + std::vector incompats; + std::vector updates; +}; struct PresetUpdater::priv @@ -154,7 +114,7 @@ struct PresetUpdater::priv void sync_config(const std::set vendors) const; void check_install_indices() const; - Updates config_update() const; + Updates get_config_updates() const; void perform_updates(Updates &&updates, bool snapshot = true) const; }; @@ -171,25 +131,37 @@ PresetUpdater::priv::priv(int version_online_event) : index_db = std::move(Index::load_db()); } +// Pull relevant preferences from AppConfig void PresetUpdater::priv::set_download_prefs(AppConfig *app_config) { enabled_version_check = app_config->get("version_check") == "1"; - version_check_url = app_config->get("version_check_url"); + version_check_url = app_config->version_check_url(); enabled_config_update = app_config->get("preset_update") == "1"; } +// Downloads a file (http get operation). Cancels if the Updater is being destroyed. bool PresetUpdater::priv::get_file(const std::string &url, const fs::path &target_path) const { - std::cerr << "get_file(): " << url << " -> " << target_path << std::endl; - bool res = false; fs::path tmp_path = target_path; - tmp_path += TMP_EXTENSION; + tmp_path += (boost::format(".%1%%2%") % get_current_pid() % TMP_EXTENSION).str(); + + BOOST_LOG_TRIVIAL(info) << boost::format("Get: `%1%`\n\t-> `%2%`\n\tvia tmp path `%3%`") + % url + % target_path.string() + % tmp_path.string(); Http::get(url) .on_progress([this](Http::Progress, bool &cancel) { if (cancel) { cancel = true; } }) + .on_error([&](std::string body, std::string error, unsigned http_status) { + (void)body; + BOOST_LOG_TRIVIAL(error) << boost::format("Error getting: `%1%`: HTTP %2%, %3%") + % url + % http_status + % error; + }) .on_complete([&](std::string body, unsigned http_status) { fs::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc); file.write(body.c_str(), body.size()); @@ -202,26 +174,39 @@ bool PresetUpdater::priv::get_file(const std::string &url, const fs::path &targe return res; } +// Remove leftover paritally downloaded files, if any. void PresetUpdater::priv::prune_tmps() const { for (fs::directory_iterator it(cache_path); it != fs::directory_iterator(); ++it) { if (it->path().extension() == TMP_EXTENSION) { + BOOST_LOG_TRIVIAL(debug) << "Cache prune: " << it->path().string(); fs::remove(it->path()); } } } +// Get Slic3rPE version available online, save in AppConfig. void PresetUpdater::priv::sync_version() const { if (! enabled_version_check) { return; } + BOOST_LOG_TRIVIAL(info) << boost::format("Downloading Slic3rPE online version from: `%1%`") % version_check_url; + Http::get(version_check_url) .size_limit(SLIC3R_VERSION_BODY_MAX) .on_progress([this](Http::Progress, bool &cancel) { cancel = this->cancel; }) + .on_error([&](std::string body, std::string error, unsigned http_status) { + (void)body; + BOOST_LOG_TRIVIAL(error) << boost::format("Error getting: `%1%`: HTTP %2%, %3%") + % version_check_url + % http_status + % error; + }) .on_complete([&](std::string body, unsigned http_status) { boost::trim(body); + BOOST_LOG_TRIVIAL(info) << boost::format("Got Slic3rPE online version: `%1%`. Sending to GUI thread...") % body; wxCommandEvent* evt = new wxCommandEvent(version_online_event); evt->SetString(body); GUI::get_app()->QueueEvent(evt); @@ -229,9 +214,11 @@ void PresetUpdater::priv::sync_version() const .perform_sync(); } +// Download vendor indices. Also download new bundles if an index indicates there's a new one available. +// Both are saved in cache. void PresetUpdater::priv::sync_config(const std::set vendors) const { - std::cerr << "sync_config()" << std::endl; + BOOST_LOG_TRIVIAL(info) << "Syncing configuration cache"; if (!enabled_config_update) { return; } @@ -239,54 +226,65 @@ void PresetUpdater::priv::sync_config(const std::set vendors) con for (const auto &index : index_db) { if (cancel) { return; } - std::cerr << "Index: " << index.vendor() << std::endl; - const auto vendor_it = vendors.find(VendorProfile(index.vendor())); - if (vendor_it == vendors.end()) { continue; } + if (vendor_it == vendors.end()) { + BOOST_LOG_TRIVIAL(warning) << "No such vendor: " << index.vendor(); + continue; + } const VendorProfile &vendor = *vendor_it; - if (vendor.config_update_url.empty()) { continue; } + if (vendor.config_update_url.empty()) { + BOOST_LOG_TRIVIAL(info) << "Vendor has no config_update_url: " << vendor.name; + continue; + } // Download a fresh index + BOOST_LOG_TRIVIAL(info) << "Downloading index for vendor: " << vendor.name; const auto idx_url = vendor.config_update_url + "/" + INDEX_FILENAME; const auto idx_path = cache_path / (vendor.id + ".idx"); if (! get_file(idx_url, idx_path)) { continue; } if (cancel) { return; } - std::cerr << "Got a new index: " << idx_path << std::endl; - // Load the fresh index up Index new_index; new_index.load(idx_path); // See if a there's a new version to download const auto recommended_it = new_index.recommended(); - if (recommended_it == new_index.end()) { continue; } + if (recommended_it == new_index.end()) { + BOOST_LOG_TRIVIAL(error) << boost::format("No recommended version for vendor: %1%, invalid index?") % vendor.name; + continue; + } const auto recommended = recommended_it->config_version; - std::cerr << "Current vendor version: " << vendor.config_version.to_string() << std::endl; - std::cerr << "Recommended version:\t" << recommended.to_string() << std::endl; + BOOST_LOG_TRIVIAL(debug) << boost::format("New index for vendor: %1%: current version: %2%, recommended version: %3%") + % vendor.name + % vendor.config_version.to_string() + % recommended.to_string(); if (vendor.config_version >= recommended) { continue; } // Download a fresh bundle + BOOST_LOG_TRIVIAL(info) << "Downloading new bundle for vendor: " << vendor.name; const auto bundle_url = (boost::format("%1%/%2%.ini") % vendor.config_update_url % recommended.to_string()).str(); const auto bundle_path = cache_path / (vendor.id + ".ini"); if (! get_file(bundle_url, bundle_path)) { continue; } if (cancel) { return; } - - std::cerr << "Got a new bundle: " << bundle_path << std::endl; } } +// Install indicies from resources. Only installs those that are either missing or older than in resources. void PresetUpdater::priv::check_install_indices() const { + BOOST_LOG_TRIVIAL(info) << "Checking if indices need to be installed from resources..."; + for (fs::directory_iterator it(rsrc_path); it != fs::directory_iterator(); ++it) { const auto &path = it->path(); if (path.extension() == ".idx") { const auto path_in_cache = cache_path / path.filename(); if (! fs::exists(path_in_cache)) { + BOOST_LOG_TRIVIAL(info) << "Install index from resources: " << path.filename(); fs::copy_file(path, path_in_cache, fs::copy_option::overwrite_if_exists); } else { Index idx_rsrc, idx_cache; @@ -294,6 +292,7 @@ void PresetUpdater::priv::check_install_indices() const idx_cache.load(path_in_cache); if (idx_cache.version() < idx_rsrc.version()) { + BOOST_LOG_TRIVIAL(info) << "Update index from resources: " << path.filename(); fs::copy_file(path, path_in_cache, fs::copy_option::overwrite_if_exists); } } @@ -301,14 +300,18 @@ void PresetUpdater::priv::check_install_indices() const } } -Updates PresetUpdater::priv::config_update() const +// Generates a list of bundle updates that are to be performed +Updates PresetUpdater::priv::get_config_updates() const { Updates updates; + BOOST_LOG_TRIVIAL(info) << "Checking for cached configuration updates..."; + for (const auto idx : index_db) { - const auto bundle_path = vendor_path / (idx.vendor() + ".ini"); + auto bundle_path = vendor_path / (idx.vendor() + ".ini"); if (! fs::exists(bundle_path)) { + BOOST_LOG_TRIVIAL(info) << "Bundle not present for index, skipping: " << idx.vendor(); continue; } @@ -317,30 +320,50 @@ Updates PresetUpdater::priv::config_update() const const auto ver_current = idx.find(vp.config_version); if (ver_current == idx.end()) { - BOOST_LOG_TRIVIAL(warning) << boost::format("Preset bundle (`%1%`) version not found in index: %2%") % idx.vendor() % vp.config_version.to_string(); + BOOST_LOG_TRIVIAL(error) << boost::format("Preset bundle (`%1%`) version not found in index: %2%") % idx.vendor() % vp.config_version.to_string(); continue; } const auto recommended = idx.recommended(); if (recommended == idx.end()) { - throw std::runtime_error((boost::format("Invalid index: `%1%`") % idx.vendor()).str()); + BOOST_LOG_TRIVIAL(error) << boost::format("No recommended version for vendor: %1%, invalid index?") % idx.vendor(); } + BOOST_LOG_TRIVIAL(debug) << boost::format("Vendor: %1%, version installed: %2%, version cached: %3%") + % vp.name + % ver_current->config_version.to_string() + % recommended->config_version.to_string(); + if (! ver_current->is_current_slic3r_supported()) { - - // TODO: Downgrade situation - + BOOST_LOG_TRIVIAL(warning) << "Current Slic3r incompatible with installed bundle: " << bundle_path.string(); + updates.incompats.emplace_back(std::move(bundle_path), *ver_current); } else if (recommended->config_version > ver_current->config_version) { // Config bundle update situation + // Check if the update is already present in a snapshot + const auto recommended_snap = SnapshotDB::singleton().snapshot_with_vendor_preset(vp.name, recommended->config_version); + if (recommended_snap != SnapshotDB::singleton().end()) { + BOOST_LOG_TRIVIAL(info) << boost::format("Bundle update %1% %2% already found in snapshot %3%, skipping...") + % vp.name + % recommended->config_version.to_string() + % recommended_snap->id; + continue; + } + auto path_in_cache = cache_path / (idx.vendor() + ".ini"); if (! fs::exists(path_in_cache)) { + BOOST_LOG_TRIVIAL(warning) << "Index indicates update, but new bundle not found in cache: " << path_in_cache.string(); continue; } const auto cached_vp = VendorProfile::from_ini(path_in_cache, false); if (cached_vp.config_version == recommended->config_version) { - updates.emplace_back(std::move(path_in_cache), bundle_path, *recommended); + updates.updates.emplace_back(std::move(path_in_cache), std::move(bundle_path), *recommended); + } else { + BOOST_LOG_TRIVIAL(warning) << boost::format("Vendor: %1%: Index indicates update (%2%) but cached bundle has a different version: %3%") + % idx.vendor() + % recommended->config_version.to_string() + % cached_vp.config_version.to_string(); } } } @@ -350,23 +373,43 @@ Updates PresetUpdater::priv::config_update() const void PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) const { - if (snapshot) { - SnapshotDB::singleton().take_snapshot(*GUI::get_app_config(), Snapshot::SNAPSHOT_UPGRADE); + if (updates.incompats.size() > 0) { + if (snapshot) { + BOOST_LOG_TRIVIAL(info) << "Taking a snapshot..."; + SnapshotDB::singleton().take_snapshot(*GUI::get_app_config(), Snapshot::SNAPSHOT_DOWNGRADE); + } + + BOOST_LOG_TRIVIAL(info) << boost::format("Deleting %1% incompatible bundles") % updates.incompats.size(); + + for (const auto &incompat : updates.incompats) { + BOOST_LOG_TRIVIAL(info) << '\t' << incompat; + fs::remove(incompat.bundle); + } } + else if (updates.updates.size() > 0) { + if (snapshot) { + BOOST_LOG_TRIVIAL(info) << "Taking a snapshot..."; + SnapshotDB::singleton().take_snapshot(*GUI::get_app_config(), Snapshot::SNAPSHOT_UPGRADE); + } - for (const auto &update : updates) { - fs::copy_file(update.source, update.target, fs::copy_option::overwrite_if_exists); + BOOST_LOG_TRIVIAL(info) << boost::format("Performing %1% updates") % updates.updates.size(); - PresetBundle bundle; - bundle.load_configbundle(update.target.string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM); + for (const auto &update : updates.updates) { + BOOST_LOG_TRIVIAL(info) << '\t' << update; - auto preset_remover = [](const Preset &preset) { - fs::remove(preset.file); - }; + fs::copy_file(update.source, update.target, fs::copy_option::overwrite_if_exists); - for (const auto &preset : bundle.prints) { preset_remover(preset); } - for (const auto &preset : bundle.filaments) { preset_remover(preset); } - for (const auto &preset : bundle.printers) { preset_remover(preset); } + PresetBundle bundle; + bundle.load_configbundle(update.target.string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM); + + auto preset_remover = [](const Preset &preset) { + fs::remove(preset.file); + }; + + for (const auto &preset : bundle.prints) { preset_remover(preset); } + for (const auto &preset : bundle.filaments) { preset_remover(preset); } + for (const auto &preset : bundle.printers) { preset_remover(preset); } + } } } @@ -381,6 +424,8 @@ PresetUpdater::PresetUpdater(int version_online_event) : PresetUpdater::~PresetUpdater() { if (p && p->thread.joinable()) { + // This will stop transfers being done by the thread, if any. + // Cancelling takes some time, but should complete soon enough. p->cancel = true; p->thread.join(); } @@ -405,69 +450,111 @@ void PresetUpdater::sync(PresetBundle *preset_bundle) void PresetUpdater::slic3r_update_notify() { - if (! p->enabled_version_check || p->had_config_update) { return; } - // ^ We don't want to bother the user with updates multiple times, put off till next time. + if (! p->enabled_version_check) { return; } + + if (p->had_config_update) { + BOOST_LOG_TRIVIAL(info) << "New Slic3r version available, but there was a configuration update, notification won't be displayed"; + return; + } auto* app_config = GUI::get_app_config(); const auto ver_slic3r = Semver::parse(SLIC3R_VERSION); - const auto ver_online = Semver::parse(app_config->get("version_online")); + const auto ver_online_str = app_config->get("version_online"); + const auto ver_online = Semver::parse(ver_online_str); + const auto ver_online_seen = Semver::parse(app_config->get("version_online_seen")); if (! ver_slic3r) { throw std::runtime_error("Could not parse Slic3r version string: " SLIC3R_VERSION); } - if (ver_online && *ver_online > *ver_slic3r) { - UpdateNotification notification(*ver_slic3r, *ver_online); - notification.ShowModal(); - if (notification.disable_version_check()) { - app_config->set("version_check", "0"); - p->enabled_version_check = false; + if (ver_online) { + // Only display the notification if the version available online is newer AND if we haven't seen it before + if (*ver_online > *ver_slic3r && (! ver_online_seen || *ver_online_seen < *ver_online)) { + GUI::MsgUpdateSlic3r notification(*ver_slic3r, *ver_online); + notification.ShowModal(); + if (notification.disable_version_check()) { + app_config->set("version_check", "0"); + p->enabled_version_check = false; + } } + app_config->set("version_online_seen", ver_online_str); } } -void PresetUpdater::config_update() const +bool PresetUpdater::config_update() const { - if (! p->enabled_config_update) { return; } + if (! p->enabled_config_update) { return true; } - auto updates = p->config_update(); - if (updates.size() > 0) { - const auto msg = _(L("Configuration update is available. Would you like to install it?")); + auto updates = p->get_config_updates(); + if (updates.incompats.size() > 0) { + BOOST_LOG_TRIVIAL(info) << boost::format("%1% bundles incompatible. Asking for action...") % updates.incompats.size(); - auto ext_msg = _(L( - "Note that a full configuration snapshot will be created first. It can then be restored at any time " - "should there be a problem with the new version.\n\n" - "Updated configuration bundles:\n" - )); - - for (const auto &update : updates) { - ext_msg += update.target.stem().string() + " " + update.version.config_version.to_string(); - if (! update.version.comment.empty()) { - ext_msg += std::string(" (") + update.version.comment + ")"; - } - ext_msg += "\n"; + std::unordered_map incompats_map; + for (const auto &incompat : updates.incompats) { + auto vendor = incompat.name(); + auto restrictions = wxString::Format(_(L("requires min. %s and max. %s")), + incompat.version.min_slic3r_version.to_string(), + incompat.version.max_slic3r_version.to_string() + ); + incompats_map.emplace(std::make_pair(std::move(vendor), std::move(restrictions))); } - wxMessageDialog dlg(NULL, msg, _(L("Configuration update")), wxYES_NO|wxCENTRE); - dlg.SetExtendedMessage(ext_msg); + GUI::MsgDataIncompatible dlg(std::move(incompats_map)); const auto res = dlg.ShowModal(); - std::cerr << "After modal" << std::endl; - if (res == wxID_YES) { - // User gave clearance, updates are go + if (res == wxID_REPLACE) { + BOOST_LOG_TRIVIAL(info) << "User wants to re-configure..."; p->perform_updates(std::move(updates)); + GUI::ConfigWizard wizard(nullptr, GUI::ConfigWizard::RR_DATA_INCOMPAT); + if (wizard.run(GUI::get_preset_bundle(), this)) { + p->had_config_update = true; + } else { + return false; + } + } else { + BOOST_LOG_TRIVIAL(info) << "User wants to exit Slic3r, bye..."; + return false; + } + } + else if (updates.updates.size() > 0) { + BOOST_LOG_TRIVIAL(info) << boost::format("Update of %1% bundles available. Asking for confirmation ...") % updates.updates.size(); + + std::unordered_map updates_map; + for (const auto &update : updates.updates) { + auto vendor = update.name(); + auto ver_str = update.version.config_version.to_string(); + if (! update.version.comment.empty()) { + ver_str += std::string(" (") + update.version.comment + ")"; + } + updates_map.emplace(std::make_pair(std::move(vendor), std::move(ver_str))); + } + + GUI::MsgUpdateConfig dlg(std::move(updates_map)); + + const auto res = dlg.ShowModal(); + if (res == wxID_OK) { + BOOST_LOG_TRIVIAL(debug) << "User agreed to perform the update"; + p->perform_updates(std::move(updates)); + } else { + BOOST_LOG_TRIVIAL(info) << "User refused the update"; } p->had_config_update = true; + } else { + BOOST_LOG_TRIVIAL(info) << "No configuration updates available."; } + + return true; } -void PresetUpdater::install_bundles_rsrc(std::vector &&bundles, bool snapshot) +void PresetUpdater::install_bundles_rsrc(std::vector bundles, bool snapshot) const { Updates updates; + BOOST_LOG_TRIVIAL(info) << boost::format("Installing %1% bundles from resources ...") % bundles.size(); + for (const auto &bundle : bundles) { auto path_in_rsrc = p->rsrc_path / bundle; auto path_in_vendors = p->vendor_path / bundle; - updates.emplace_back(std::move(path_in_rsrc), std::move(path_in_vendors)); + updates.updates.emplace_back(std::move(path_in_rsrc), std::move(path_in_vendors), Version()); } p->perform_updates(std::move(updates), snapshot); diff --git a/xs/src/slic3r/Utils/PresetUpdater.hpp b/xs/src/slic3r/Utils/PresetUpdater.hpp index 8fe3e021d..6a53cca81 100644 --- a/xs/src/slic3r/Utils/PresetUpdater.hpp +++ b/xs/src/slic3r/Utils/PresetUpdater.hpp @@ -20,10 +20,18 @@ public: PresetUpdater &operator=(const PresetUpdater &) = delete; ~PresetUpdater(); + // If either version check or config updating is enabled, get the appropriate data in the background and cache it. void sync(PresetBundle *preset_bundle); + + // If version check is enabled, check if chaced online slic3r version is newer, notify if so. void slic3r_update_notify(); - void config_update() const; - void install_bundles_rsrc(std::vector &&bundles, bool snapshot = true); + + // If updating is enabled, check if updates are available in cache, if so, ask about installation. + // A false return value implies Slic3r should exit due to incompatibility of configuration. + bool config_update() const; + + // "Update" a list of bundles from resources (behaves like an online update). + void install_bundles_rsrc(std::vector bundles, bool snapshot = true) const; private: struct priv; std::unique_ptr p; diff --git a/xs/src/slic3r/Utils/Semver.hpp b/xs/src/slic3r/Utils/Semver.hpp index bf3c78964..736f9b891 100644 --- a/xs/src/slic3r/Utils/Semver.hpp +++ b/xs/src/slic3r/Utils/Semver.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -22,14 +23,25 @@ public: Semver() : ver(semver_zero()) {} Semver(int major, int minor, int patch, - boost::optional metadata = boost::none, - boost::optional prerelease = boost::none) + boost::optional metadata = boost::none, + boost::optional prerelease = boost::none) + : ver(semver_zero()) { ver.major = major; ver.minor = minor; ver.patch = patch; - ver.metadata = metadata ? std::strcpy(ver.metadata, metadata->c_str()) : nullptr; - ver.prerelease = prerelease ? std::strcpy(ver.prerelease, prerelease->c_str()) : nullptr; + set_metadata(metadata); + set_prerelease(prerelease); + } + + Semver(const std::string &str) : ver(semver_zero()) + { + auto parsed = parse(str); + if (! parsed) { + throw std::runtime_error(std::string("Could not parse version string: ") + str); + } + ver = parsed->ver; + parsed->ver = semver_zero(); } static boost::optional parse(const std::string &str) @@ -82,6 +94,13 @@ public: int patch() const { return ver.patch; } const char* prerelease() const { return ver.prerelease; } const char* metadata() const { return ver.metadata; } + + // Setters + void set_maj(int maj) { ver.major = maj; } + void set_min(int min) { ver.minor = min; } + void set_patch(int patch) { ver.patch = patch; } + void set_metadata(boost::optional meta) { ver.metadata = meta ? strdup(*meta) : nullptr; } + void set_prerelease(boost::optional pre) { ver.prerelease = pre ? strdup(*pre) : nullptr; } // Comparison bool operator<(const Semver &b) const { return ::semver_compare(ver, b.ver) == -1; } @@ -124,6 +143,7 @@ private: Semver(semver_t ver) : ver(ver) {} static semver_t semver_zero() { return { 0, 0, 0, nullptr, nullptr }; } + static char * strdup(const std::string &str) { return ::semver_strdup(const_cast(str.c_str())); } }; diff --git a/xs/xsp/GUI.xsp b/xs/xsp/GUI.xsp index 2378cb4de..aa95bd647 100644 --- a/xs/xsp/GUI.xsp +++ b/xs/xsp/GUI.xsp @@ -42,6 +42,9 @@ void add_config_menu(SV *ui, int event_preferences_changed, int event_language_c void create_preset_tabs(bool no_controller, int event_value_change, int event_presets_changed) %code%{ Slic3r::GUI::create_preset_tabs(no_controller, event_value_change, event_presets_changed); %}; +void show_error_id(int id, std::string msg) + %code%{ Slic3r::GUI::show_error_id(id, msg); %}; + TabIface* get_preset_tab(char *name) %code%{ RETVAL=Slic3r::GUI::get_preset_tab_iface(name); %}; @@ -60,10 +63,10 @@ void set_app_config(AppConfig *app_config) bool check_unsaved_changes() %code%{ RETVAL=Slic3r::GUI::check_unsaved_changes(); %}; -void config_wizard_startup(int app_config_exists) +bool config_wizard_startup(int app_config_exists) %code%{ try { - Slic3r::GUI::config_wizard_startup(app_config_exists != 0); + RETVAL=Slic3r::GUI::config_wizard_startup(app_config_exists != 0); } catch (std::exception& e) { croak("%s\n", e.what()); } diff --git a/xs/xsp/GUI_Tab.xsp b/xs/xsp/GUI_Tab.xsp index 9cacac74f..bcbdc0d9f 100644 --- a/xs/xsp/GUI_Tab.xsp +++ b/xs/xsp/GUI_Tab.xsp @@ -16,6 +16,7 @@ bool current_preset_is_dirty(); void load_key_value(char* opt_key, char* value); void OnActivate(); + size_t get_selected_preset_item(); std::string title(); Ref get_config(); Ref get_presets(); diff --git a/xs/xsp/Utils_PresetUpdater.xsp b/xs/xsp/Utils_PresetUpdater.xsp index 53c3aa985..dc874acab 100644 --- a/xs/xsp/Utils_PresetUpdater.xsp +++ b/xs/xsp/Utils_PresetUpdater.xsp @@ -9,5 +9,5 @@ PresetUpdater(int version_online_event); void sync(PresetBundle* preset_bundle); void slic3r_update_notify(); - void config_update(); + bool config_update(); };