diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index e90f1ddb2..5e373b2ab 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -6189,13 +6189,13 @@ void Tab::sync_excluder() return m_config->get_index_for_extruder(extruder_id + 1, variant_keys.first, ExtruderType(extruders->values[extruder_id]), NozzleVolumeType(nozzle_volumes->values[extruder_id]), variant_keys.second); }; - int left_index = get_index_for_extruder(0); - int right_index = get_index_for_extruder(1); int active_index = int(intptr_t(m_extruder_switch->GetClientData())); - auto left_str = std::to_string(left_index); - auto right_str = std::to_string(right_index); + int from_index = get_index_for_extruder(active_index); + int dest_index = get_index_for_extruder(1 - active_index); + auto from_str = std::to_string(from_index); + auto dest_str = std::to_string(dest_index); auto dirty_options = m_presets->current_dirty_options(true); - wxString left_copy_sumary, right_copy_sumary; + DynamicConfig config_origin, config_to_apply; for (int i = 0; i < dirty_options.size(); ++i) { auto &opt = dirty_options[i]; auto n= opt.find('#'); @@ -6206,43 +6206,42 @@ void Tab::sync_excluder() if (field == nullptr || line == nullptr) continue; ++n; - bool left = opt.substr(n) == left_str; - bool right = opt.substr(n) == right_str; + bool dirty = opt.substr(n) == from_str; while (i + 1 < dirty_options.size() && dirty_options[i + 1].compare(0, n, opt, 0, n) == 0) { - left |= dirty_options[i + 1].substr(n) == left_str; - right |= dirty_options[i + 1].substr(n) == right_str; + dirty |= dirty_options[i + 1].substr(n) == from_str; ++i; } - if (left == right) - continue; - auto option = dynamic_cast(m_config->option(opt.substr(0, n - 1))); - if (left) - option->set_at(option, right_index, left_index); - else - option->set_at(option, left_index, right_index); - std::string value = option->vserialize()[left_index]; - auto & copy_sumary = left ? right_copy_sumary : left_copy_sumary; - copy_sumary.Append(wxString::Format("\n%c %s: %s", left ? '>' : '<', _L(line->label), from_u8(value))); + if (dirty) { + auto key = opt.substr(0, n - 1); + auto option = dynamic_cast(m_config->option(key)); + auto option2 = dynamic_cast(option->clone()); + option2->set_at(option, dest_index, from_index); + if (*option == *option2) { + delete option2; + continue; + } + config_origin.set_key_value(key, option->clone()); + config_to_apply.set_key_value(key, option2); + } } - wxString sumary = _L("No modifications need to be copied."); - if (!left_copy_sumary.IsEmpty() || !right_copy_sumary.IsEmpty()) { + if (config_to_apply.empty()) { + MessageDialog md(wxGetApp().plater(), _L("No modifications need to be copied."), _L("Copy paramters"), wxICON_INFORMATION | wxOK); + md.ShowModal(); + return; + } + wxString header = active_index == 1 ? _L("Copy the following parameters to the left nozzle:") : + _L("Copy the following parameters to the right nozzle:"); + UnsavedChangesDialog dlg(_L("Copy paramters"), header, &config_origin, from_index, dest_index); + dlg.ShowModal(); + if (dlg.transfer_changes()) { + m_config->apply(config_to_apply); reload_config(); update_changed_ui(); update(); if (m_active_page) m_active_page->update_visibility(m_mode, true); m_page_view->GetParent()->Layout(); - if (!left_copy_sumary.IsEmpty()) - sumary = _L("Copied the following parameters to the left nozzle:") + left_copy_sumary; - else - sumary.Clear(); - if (!right_copy_sumary.IsEmpty()) { - if (!sumary.IsEmpty()) sumary.Append('\n'); - sumary.Append(_L("Copied the following parameters to the right nozzle:") + right_copy_sumary); - } } - MessageDialog md(wxGetApp().plater(), sumary, _L("Copy paramters"), wxICON_INFORMATION | wxOK); - md.ShowModal(); } void Tab::compatible_widget_reload(PresetDependencies &deps) diff --git a/src/slic3r/GUI/UnsavedChangesDialog.cpp b/src/slic3r/GUI/UnsavedChangesDialog.cpp index 2a6f44090..66c5b6c7f 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.cpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.cpp @@ -806,6 +806,28 @@ UnsavedChangesDialog::UnsavedChangesDialog(const wxString &caption, const wxStri wxGetApp().UpdateDlgDarkUI(this); } +struct SyncExtruderParams +{ + DynamicConfig *config; + int from; + int to; +}; + +UnsavedChangesDialog::UnsavedChangesDialog(const wxString &caption, const wxString &header, DynamicConfig *config, int from, int to) + : DPIDialog(static_cast(wxGetApp().mainframe), + wxID_ANY, + caption, + wxDefaultPosition, + wxDefaultSize, + wxCAPTION | wxCLOSE_BOX) + , m_buttons(ActionButtons::SAVE | ActionButtons::DONT_SAVE) +{ + SyncExtruderParams params { config, from, to }; + build(Preset::TYPE_PRINT, reinterpret_cast(¶ms), "SyncExtruderParams", header); + this->CenterOnScreen(); + wxGetApp().UpdateDlgDarkUI(this); +} + UnsavedChangesDialog::UnsavedChangesDialog(Preset::Type type, PresetCollection *dependent_presets, const std::string &new_selected_preset, bool no_transfer) : m_new_selected_preset_name(new_selected_preset) , DPIDialog(static_cast(wxGetApp().mainframe), @@ -870,8 +892,14 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection *dependent_ m_sizer_main->Add(0, 0, 0, wxTOP, 12); - if (dependent_presets && - ((dependent_presets->type() != Preset::Type::TYPE_FILAMENT && dependent_presets->type() != Preset::Type::TYPE_PRINTER) || !dependent_presets->find_preset(new_selected_preset))) { + SyncExtruderParams *params = nullptr; + if (new_selected_preset == "SyncExtruderParams") { + params = reinterpret_cast(dependent_presets); + dependent_presets = nullptr; + } + + if (params || (dependent_presets && + ((dependent_presets->type() != Preset::Type::TYPE_FILAMENT && dependent_presets->type() != Preset::Type::TYPE_PRINTER) || !dependent_presets->find_preset(new_selected_preset)))) { m_panel_tab = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(UNSAVE_CHANGE_DIALOG_SCROLL_WINDOW_SIZE.x, -1), wxTAB_TRAVERSAL); m_panel_tab->SetBackgroundColour(GREY200); wxBoxSizer *m_sizer_tab = new wxBoxSizer(wxVERTICAL); @@ -904,7 +932,7 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection *dependent_ wxBoxSizer *top_title_oldv = new wxBoxSizer(wxVERTICAL); wxBoxSizer *top_title_oldv_h = new wxBoxSizer(wxHORIZONTAL); - static_oldv_title = new wxStaticText(m_panel_oldv, wxID_ANY, _L("Preset(Old)"), wxDefaultPosition, wxDefaultSize, 0); + static_oldv_title = new wxStaticText(m_panel_oldv, wxID_ANY, params ? _L("Current Value") : _L("Preset(Old)"), wxDefaultPosition, wxDefaultSize, 0); static_oldv_title->SetFont(::Label::Body_13); static_oldv_title->Wrap(-1); static_oldv_title->SetForegroundColour(*wxWHITE); @@ -923,7 +951,7 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection *dependent_ wxBoxSizer *top_title_newv = new wxBoxSizer(wxVERTICAL); wxBoxSizer *top_title_newv_h = new wxBoxSizer(wxHORIZONTAL); - static_newv_title = new wxStaticText(m_panel_newv, wxID_ANY, _L("Modified Value(New)"), wxDefaultPosition, wxDefaultSize, 0); + static_newv_title = new wxStaticText(m_panel_newv, wxID_ANY, params ? _L("New Value") : _L("Modified Value(New)"), wxDefaultPosition, wxDefaultSize, 0); static_newv_title->SetFont(::Label::Body_13); static_newv_title->Wrap(-1); static_newv_title->SetForegroundColour(*wxWHITE); @@ -1012,12 +1040,13 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection *dependent_ m_sizer_button->Add(*btn, 0, wxLEFT, 5); }; + bool is_copy = new_selected_preset == "SyncExtruderParams"; // "Save" button - if (ActionButtons::SAVE & m_buttons) add_btn(&m_save_btn, m_save_btn_id, Action::Save, _L("Save"), true); + if (ActionButtons::SAVE & m_buttons) add_btn(&m_save_btn, m_save_btn_id, is_copy ? Action::Transfer : Action::Save, is_copy ? _L("Copy") : _L("Save"), true); { // "Don't save" / "Discard" button std::string btn_icon = (ActionButtons::DONT_SAVE & m_buttons) ? "" : (dependent_presets || (ActionButtons::KEEP & m_buttons)) ? "blank_16" : "exit"; - wxString btn_label = (ActionButtons::TRANSFER & m_buttons) ? _L("Discard Modified Value") : _L("Don't save"); + wxString btn_label = (ActionButtons::TRANSFER & m_buttons) ? _L("Discard Modified Value") : is_copy ? _L("Cancel") : _L("Don't save"); add_btn(&m_discard_btn, m_continue_btn_id, Action::Discard, btn_label, false); } @@ -1054,8 +1083,13 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection *dependent_ Fit(); Centre(wxBOTH); - - update(type, dependent_presets, new_selected_preset, header); + if (params) { + update_tree(type, params->config, params->from, params->to); + update_list(); + m_action_line->SetLabel(header); + } else { + update(type, dependent_presets, new_selected_preset, header); + } //SetSizer(topSizer); //topSizer->SetSizeHints(this); @@ -1433,7 +1467,7 @@ void UnsavedChangesDialog::update(Preset::Type type, PresetCollection* dependent } wxString action_msg; - + if (dependent_presets) { action_msg = format_wxstr(_L("You have changed the preset \"%1%\". "), dependent_presets->get_edited_preset().name); if (m_transfer_btn) { @@ -1646,7 +1680,7 @@ void UnsavedChangesDialog::update_list() // +2: Ensure that there is at least one line and that the content contains '\n' int rows = int(text_size.GetWidth() / width) + 2; int height = rows * text_size.GetHeight(); - m_action_line->SetMinSize(wxSize(width, height)); + m_action_line->SetMinSize(wxSize(width, height)); m_action_line->Wrap(UNSAVE_CHANGE_DIALOG_ACTION_LINE_SIZE.GetWidth());*/ Layout(); Fit(); @@ -1663,6 +1697,23 @@ std::string UnsavedChangesDialog::subreplace(std::string resource_str, std::stri return dst_str; } +void UnsavedChangesDialog::update_tree(Preset::Type type, DynamicConfig * config, int from, int to) +{ + Search::OptionsSearcher &searcher = wxGetApp().sidebar().get_searcher(); + searcher.sort_options_by_key(); + + for (const std::string &opt_key : config->keys()) { + int variant_index = -2; + const Search::Option &option = searcher.get_option(opt_key, type, variant_index); + auto category = option.category_local; + auto opt = dynamic_cast(config->option(opt_key)); + std::string value_from = opt->vserialize()[from]; + std::string value_to = opt->vserialize()[to]; + PresetItem pi = {type, opt_key, category, option.group_local, option.label_local, into_u8(value_to), into_u8(value_from)}; + m_presetitems.push_back(pi); + } +} + void UnsavedChangesDialog::update_tree(Preset::Type type, PresetCollection* presets_) { Search::OptionsSearcher& searcher = wxGetApp().sidebar().get_searcher(); diff --git a/src/slic3r/GUI/UnsavedChangesDialog.hpp b/src/slic3r/GUI/UnsavedChangesDialog.hpp index 218ff4757..2f988effe 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.hpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.hpp @@ -333,6 +333,7 @@ public: UnsavedChangesDialog(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset, bool no_transfer = false); // show unsaved changes for all another cases UnsavedChangesDialog(const wxString& caption, const wxString& header, const std::string& app_config_key, int act_buttons); + UnsavedChangesDialog(const wxString &caption, const wxString &header, DynamicConfig *config, int from, int to); ~UnsavedChangesDialog(){}; int ShowModal(); @@ -342,6 +343,7 @@ public: void update_list(); std::string subreplace(std::string resource_str, std::string sub_str, std::string new_str); void update_tree(Preset::Type type, PresetCollection *presets); + void update_tree(Preset::Type type, DynamicConfig *config, int from, int to); void show_info_line(Action action, std::string preset_name = ""); void update_config(Action action); void close(Action action);