Fixed handling of print and filament presets incompatible

with the newly selected print profile,
fixed loading of print and filament tab pages after the print or filament
preset has been changed to be compatible with a newly selected printer.
This commit is contained in:
bubnikv 2017-12-13 14:00:14 +01:00
parent 91e847cb76
commit 21b4e62e6e
5 changed files with 81 additions and 64 deletions

View file

@ -7,7 +7,7 @@ use utf8;
use File::Basename qw(basename dirname);
use FindBin;
use List::Util qw(min);
use List::Util qw(min first);
use Slic3r::Geometry qw(X Y);
use Wx qw(:frame :bitmap :id :misc :notebook :panel :sizer :menu :dialog :filedialog
:font :icon wxTheApp);
@ -132,12 +132,14 @@ sub _init_tabpanel {
$self->{plater}->update_presets($tab_name, @_);
if ($tab_name eq 'printer') {
# Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors.
wxTheApp->{preset_bundle}->print->update_tab_ui(
$self->{options_tabs}{'print'}->{presets_choice},
$self->{options_tabs}{'print'}->{show_incompatible_presets});
wxTheApp->{preset_bundle}->filament->update_tab_ui(
$self->{options_tabs}{'filament'}->{presets_choice},
$self->{options_tabs}{'filament'}->{show_incompatible_presets});
my ($presets, $reload_dependent_tabs) = @_;
for my $tab_name_other (qw(print filament)) {
# If the printer tells us that the print or filament preset has been switched or invalidated,
# refresh the print or filament tab page. Otherwise just refresh the combo box.
my $update_action = ($reload_dependent_tabs && (first { $_ eq $tab_name_other } (@{$reload_dependent_tabs})))
? 'load_current_preset' : 'update_tab_ui';
$self->{options_tabs}{$tab_name_other}->$update_action;
}
# Update the controller printers.
$self->{controller}->update_presets(@_) if $self->{controller};
}

View file

@ -506,6 +506,7 @@ sub _on_select_preset {
wxTheApp->{preset_bundle}->set_filament_preset($idx, $choice->GetStringSelection);
}
if ($group eq 'filament' && @{$self->{preset_choosers}{filament}} > 1) {
# Only update the platter UI for the 2nd and other filaments.
wxTheApp->{preset_bundle}->update_platter_filament_ui($idx, $choice);
} else {
# call GetSelection() in scalar context as it's context-aware

View file

@ -151,7 +151,7 @@ sub save_preset {
eval { $self->{presets}->save_current_preset($name); };
Slic3r::GUI::catch_error($self) and return;
# Add the new item into the UI component, remove dirty flags and activate the saved item.
$self->{presets}->update_tab_ui($self->{presets_choice}, $self->{show_incompatible_presets});
$self->update_tab_ui;
# Update the selection boxes at the platter.
$self->_on_presets_changed;
}
@ -177,7 +177,7 @@ sub _toggle_show_hide_incompatible {
my ($self) = @_;
$self->{show_incompatible_presets} = ! $self->{show_incompatible_presets};
$self->_update_show_hide_incompatible_button;
$self->{presets}->update_tab_ui($self->{presets_choice}, $self->{show_incompatible_presets});
$self->update_tab_ui;
}
sub _update_show_hide_incompatible_button {
@ -223,8 +223,9 @@ sub _update {}
# to update the "dirty" flags of the selection boxes,
# to uddate number of "filament" selection boxes when the number of extruders change.
sub _on_presets_changed {
my ($self) = @_;
$self->{on_presets_changed}->($self->{presets}) if $self->{on_presets_changed};
my ($self, $reload_dependent_tabs) = @_;
$self->{on_presets_changed}->($self->{presets}, $reload_dependent_tabs)
if $self->{on_presets_changed};
}
# For the printer profile, generate the extruder pages after a preset is loaded.
@ -237,11 +238,12 @@ sub may_discard_current_dirty_preset
my ($self, $presets, $new_printer_name) = @_;
$presets //= $self->{presets};
# Display a dialog showing the dirty options in a human readable form.
my $old_preset = $presets->get_current_preset;
my $type_name = $presets->name;
my $name = $old_preset->default ?
my $old_preset = $presets->get_current_preset;
my $type_name = $presets->name;
my $tab = ' ';
my $name = $old_preset->default ?
('Default ' . $type_name . ' preset') :
($type_name . " preset \"" . $old_preset->name . "\"");
($type_name . " preset\n$tab" . $old_preset->name);
# Collect descriptions of the dirty options.
my @option_names = ();
foreach my $opt_key (@{$presets->current_dirty_options}) {
@ -251,10 +253,10 @@ sub may_discard_current_dirty_preset
push @option_names, $name;
}
# Show a confirmation dialog with the list of dirty options.
my $changes = join "\n", map "- $_", @option_names;
my $changes = join "\n", map "$tab$_", @option_names;
my $message = (defined $new_printer_name) ?
"$name is not compatible with printer \"$new_printer_name\"\n and it has unsaved changes:" :
"$name has unsaved changes:";
"$name\n\nis not compatible with printer\n$tab$new_printer_name\n\nand it has the following unsaved changes:" :
"$name\n\nhas the following unsaved changes:";
my $confirm = Wx::MessageDialog->new($self,
$message . "\n$changes\n\nDiscard changes and continue anyway?",
'Unsaved Changes', wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION);
@ -267,9 +269,11 @@ sub may_discard_current_dirty_preset
sub select_preset {
my ($self, $name, $force) = @_;
$force //= 0;
my $current_dirty = $self->{presets}->current_is_dirty;
my $canceled = 0;
my $printer_tab = $self->{presets}->name eq 'printer';
my $presets = $self->{presets};
my $current_dirty = $presets->current_is_dirty;
my $canceled = 0;
my $printer_tab = $presets->name eq 'printer';
my @reload_dependent_tabs = ();
if (! $force && $current_dirty && ! $self->may_discard_current_dirty_preset) {
$canceled = 1;
} elsif ($printer_tab) {
@ -278,49 +282,57 @@ sub select_preset {
# If they are not compatible and the the current print or filament are dirty, let user decide
# whether to discard the changes or keep the current printer selection.
my $new_printer_name = $name // '';
my $new_printer_preset = $self->{presets}->find_preset($new_printer_name, 1);
# my $new_nozzle_dmrs = $new_printer_preset->config->get('nozzle_diameter');
my $print_presets = wxTheApp->{preset_bundle}->print;
if ($print_presets->current_is_dirty &&
! $print_presets->get_edited_preset->is_compatible_with_printer($new_printer_name)) {
if ($self->may_discard_current_dirty_preset($print_presets, $new_printer_name)) {
$canceled = 1;
} else {
$print_presets->discard_current_changes;
}
my $new_printer_preset = $presets->find_preset($new_printer_name, 1);
my $print_presets = wxTheApp->{preset_bundle}->print;
my $print_preset_dirty = $print_presets->current_is_dirty;
my $print_preset_compatible = $print_presets->get_edited_preset->is_compatible_with_printer($new_printer_name);
$canceled = $print_preset_dirty && ! $print_preset_compatible &&
! $self->may_discard_current_dirty_preset($print_presets, $new_printer_name);
my $filament_presets = wxTheApp->{preset_bundle}->filament;
my $filament_preset_dirty = $filament_presets->current_is_dirty;
my $filament_preset_compatible = $filament_presets->get_edited_preset->is_compatible_with_printer($new_printer_name);
if (! $canceled) {
$canceled = $filament_preset_dirty && ! $filament_preset_compatible &&
! $self->may_discard_current_dirty_preset($filament_presets, $new_printer_name);
}
my $filament_presets = wxTheApp->{preset_bundle}->filament;
# if ((@$new_nozzle_dmrs <= 1) &&
if (! $canceled && $filament_presets->current_is_dirty &&
! $filament_presets->get_edited_preset->is_compatible_with_printer($new_printer_name)) {
if ($self->may_discard_current_dirty_preset($filament_presets, $new_printer_name)) {
$canceled = 1;
} else {
$filament_presets->discard_current_changes;
if (! $canceled) {
if (! $print_preset_compatible) {
# The preset will be switched to a different, compatible preset, or the '-- default --'.
push @reload_dependent_tabs, 'print';
$print_presets->discard_current_changes if $print_preset_dirty;
}
if (! $filament_preset_compatible) {
# The preset will be switched to a different, compatible preset, or the '-- default --'.
push @reload_dependent_tabs, 'filament';
$filament_presets->discard_current_changes if $filament_preset_dirty;
}
}
}
if ($canceled) {
$self->{presets}->update_tab_ui($self->{presets_choice}, $self->{show_incompatible_presets});
# Trigger the on_presets_changed event so that we also restore the previous value in the plater selector.
$self->update_tab_ui;
# Trigger the on_presets_changed event so that we also restore the previous value in the plater selector,
# if this action was initiated from the platter.
$self->_on_presets_changed;
} else {
$presets->discard_current_changes if $current_dirty;
if (defined $name) {
$self->{presets}->select_preset_by_name($name);
$presets->select_preset_by_name($name);
} else {
$self->{presets}->select_preset(0);
$presets->select_preset(0);
}
# Mark the print & filament enabled if they are compatible with the currently selected preset.
# The following method should not discard changes of current print or filament presets on change of a printer profile,
# if they are compatible with the current printer.
wxTheApp->{preset_bundle}->update_compatible_with_printer(1)
if $current_dirty || $printer_tab;
# Initialize the UI from the current preset.
$self->load_current_preset;
$self->load_current_preset(\@reload_dependent_tabs);
}
}
# Initialize the UI from the current preset.
sub load_current_preset {
my ($self) = @_;
my ($self, $dependent_tab_names) = @_;
my $preset = $self->{presets}->get_current_preset;
eval {
local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self);
@ -337,8 +349,8 @@ sub load_current_preset {
# preset dirty again
# (not sure this is true anymore now that update_dirty is idempotent)
wxTheApp->CallAfter(sub {
$self->{presets}->update_tab_ui($self->{presets_choice}, $self->{show_incompatible_presets});
$self->_on_presets_changed;
$self->update_tab_ui;
$self->_on_presets_changed($dependent_tab_names);
});
}
@ -430,8 +442,13 @@ sub _load_key_value {
$self->{config}->set($opt_key, $value);
# Mark the print & filament enabled if they are compatible with the currently selected preset.
if ($opt_key eq 'compatible_printers') {
my $was_compatible = $self->{presets}->get_edited_preset->compatible;
wxTheApp->{preset_bundle}->update_compatible_with_printer(0);
$self->{presets}->update_tab_ui($self->{presets_choice}, $self->{show_incompatible_presets});
if ($was_compatible != $self->{presets}->get_edited_preset->compatible) {
# This is certainly not a tab page.
# Trigger the on_presets_changed event so that we also update the "compatible" flag at the plater selector.
$self->_on_presets_changed;
}
} else {
$self->{presets}->update_dirty_ui($self->{presets_choice});
}
@ -538,10 +555,14 @@ sub update_ui_from_settings {
} else {
if ($self->{show_incompatible_presets}) {
$self->{show_incompatible_presets} = 0;
$self->{presets}->update_tab_ui($self->{presets_choice}, 0);
$self->update_tab_ui;
}
}
}
sub update_tab_ui {
my ($self) = @_;
$self->{presets}->update_tab_ui($self->{presets_choice}, $self->{show_incompatible_presets})
}
package Slic3r::GUI::Tab::Print;
use base 'Slic3r::GUI::Tab';

View file

@ -397,29 +397,19 @@ void PresetCollection::set_default_suppressed(bool default_suppressed)
void PresetCollection::update_compatible_with_printer(const std::string &active_printer, bool select_other_if_incompatible)
{
size_t num_visible = 0;
for (size_t idx_preset = 1; idx_preset < m_presets.size(); ++ idx_preset) {
bool selected = idx_preset == m_idx_selected;
Preset &preset_selected = m_presets[idx_preset];
Preset &preset_edited = selected ? m_edited_preset : preset_selected;
if (preset_edited.update_compatible_with_printer(active_printer))
// Mark compatible presets as visible.
preset_selected.is_visible = true;
else if (selected && select_other_if_incompatible) {
preset_selected.is_visible = false;
if (! preset_edited.update_compatible_with_printer(active_printer) &&
selected && select_other_if_incompatible)
m_idx_selected = (size_t)-1;
}
if (selected)
preset_selected.is_compatible = preset_edited.is_compatible;
if (preset_selected.is_visible)
++ num_visible;
}
if (m_idx_selected == (size_t)-1)
// Find some other visible preset.
this->select_preset(first_visible_idx());
else if (num_visible == 0)
// Show the "-- default --" preset.
m_presets.front().is_visible = true;
// Find some other compatible preset, or the "-- default --" preset.
this->select_preset(first_compatible_idx());
}
// Save the preset under a new name. If the name is different from the old one,
@ -460,7 +450,7 @@ void PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompatibl
ui->Clear();
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 (! show_incompatible && ! preset.is_compatible && i != m_idx_selected)
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()),
@ -494,6 +484,8 @@ bool PresetCollection::update_dirty_ui(wxBitmapComboBox *ui)
return was_dirty != is_dirty;
}
// Select a new preset. This resets all the edits done to the currently selected preset.
// If the preset with index idx does not exist, a first visible preset is selected.
Preset& PresetCollection::select_preset(size_t idx)
{
for (Preset &preset : m_presets)

View file

@ -14,6 +14,7 @@
bool external() %code%{ RETVAL = THIS->is_external; %};
bool visible() %code%{ RETVAL = THIS->is_visible; %};
bool dirty() %code%{ RETVAL = THIS->is_dirty; %};
bool compatible() %code%{ RETVAL = THIS->is_compatible; %};
bool is_compatible_with_printer(char *active_printer) const;
const char* name() %code%{ RETVAL = THIS->name.c_str(); %};