diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 7e30831fe..c7acf8f49 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -1383,13 +1383,14 @@ const std::vector& PhysicalPrinter::print_host_options() return s_opts; } -bool PhysicalPrinter::has_print_host_information(const PrinterPresetCollection& printer_presets) +std::vector PhysicalPrinter::presets_with_print_host_information(const PrinterPresetCollection& printer_presets) { + std::vector presets; for (const Preset& preset : printer_presets) if (has_print_host_information(preset.config)) - return true; + presets.emplace_back(preset.name); - return false; + return presets; } bool PhysicalPrinter::has_print_host_information(const DynamicPrintConfig& config) @@ -1564,7 +1565,7 @@ void PhysicalPrinterCollection::load_printers(const std::string& dir_path, const // if there is saved user presets, contains information about "Print Host upload", // Create default printers with this presets // Note! "Print Host upload" options will be cleared after physical printer creations -void PhysicalPrinterCollection::load_printers_from_presets(PrinterPresetCollection& printer_presets, std::string def_printer_name) +void PhysicalPrinterCollection::load_printers_from_presets(PrinterPresetCollection& printer_presets) { int cnt=0; for (Preset& preset: printer_presets) { @@ -1579,8 +1580,12 @@ void PhysicalPrinterCollection::load_printers_from_presets(PrinterPresetCollecti // just add preset for this printer existed_printer->add_preset(preset.name); else { + std::string new_printer_name = (boost::format("Printer %1%") % ++cnt ).str(); + while (find_printer(new_printer_name)) + new_printer_name = (boost::format("Printer %1%") % ++cnt).str(); + // create new printer from this preset - PhysicalPrinter printer((boost::format("%1% %2%") % def_printer_name % ++cnt ).str(), preset); + PhysicalPrinter printer(new_printer_name, preset); printer.loaded = true; save_printer(printer); } @@ -1699,33 +1704,51 @@ bool PhysicalPrinterCollection::delete_selected_printer() return true; } -bool PhysicalPrinterCollection::delete_preset_from_printers( const std::string& preset_name, bool first_check /*=true*/) +bool PhysicalPrinterCollection::delete_preset_from_printers( const std::string& preset_name) { - if (first_check) { - for (auto printer: m_printers) - if (printer.preset_names.size()==1 && *printer.preset_names.begin() == preset_name) - return false; - } - std::vector printers_for_delete; - for (PhysicalPrinter& printer : m_printers) + for (PhysicalPrinter& printer : m_printers) { if (printer.preset_names.size() == 1 && *printer.preset_names.begin() == preset_name) printers_for_delete.emplace_back(printer.name); - else if (printer.delete_preset(preset_name)) { - if (printer.name == get_selected_printer_name() && - preset_name == get_selected_printer_preset_name()) - select_printer(printer); + else if (printer.delete_preset(preset_name)) save_printer(printer); - } + } - if (!printers_for_delete.empty()) { + if (!printers_for_delete.empty()) for (const std::string& printer_name : printers_for_delete) delete_printer(printer_name); - unselect_printer(); - } + + unselect_printer(); return true; } +// Get list of printers which have more than one preset and "preset_name" preset is one of them +std::vector PhysicalPrinterCollection::get_printers_with_preset(const std::string& preset_name) +{ + std::vector printers; + + for (auto printer : m_printers) { + if (printer.preset_names.size() == 1) + continue; + if (printer.preset_names.find(preset_name) != printer.preset_names.end()) + printers.emplace_back(printer.name); + } + + return printers; +} + +// Get list of printers which has only "preset_name" preset +std::vector PhysicalPrinterCollection::get_printers_with_only_preset(const std::string& preset_name) +{ + std::vector printers; + + for (auto printer : m_printers) + if (printer.preset_names.size() == 1 && *printer.preset_names.begin() == preset_name) + printers.emplace_back(printer.name); + + return printers; +} + std::string PhysicalPrinterCollection::get_selected_full_printer_name() const { return (m_idx_selected == size_t(-1)) ? std::string() : this->get_selected_printer().get_full_name(m_selected_preset); diff --git a/src/libslic3r/Preset.hpp b/src/libslic3r/Preset.hpp index 6b5a2a511..e34fca4dd 100644 --- a/src/libslic3r/Preset.hpp +++ b/src/libslic3r/Preset.hpp @@ -555,7 +555,7 @@ public: static std::string separator(); static const std::vector& printer_options(); static const std::vector& print_host_options(); - static bool has_print_host_information(const PrinterPresetCollection& printer_presets); + static std::vector presets_with_print_host_information(const PrinterPresetCollection& printer_presets); static bool has_print_host_information(const DynamicPrintConfig& config); const std::set& get_preset_names() const; @@ -629,7 +629,7 @@ public: // Load ini files of the particular type from the provided directory path. void load_printers(const std::string& dir_path, const std::string& subdir); - void load_printers_from_presets(PrinterPresetCollection &printer_presets, std::string def_printer_name); + void load_printers_from_presets(PrinterPresetCollection &printer_presets); // Save the printer under a new name. If the name is different from the old one, // a new printer is stored into the list of printers. @@ -645,7 +645,12 @@ public: // Delete preset_name preset from all printers: // If there is last preset for the printer and first_check== false, then delete this printer // returns true if all presets were deleted successfully. - bool delete_preset_from_printers(const std::string& preset_name, bool first_check = true); + bool delete_preset_from_printers(const std::string& preset_name); + + // Get list of printers which have more than one preset and "preset_name" preset is one of them + std::vector get_printers_with_preset( const std::string &preset_name); + // Get list of printers which has only "preset_name" preset + std::vector get_printers_with_only_preset( const std::string &preset_name); // Return the selected preset, without the user modifications applied. PhysicalPrinter& get_selected_printer() { return m_printers[m_idx_selected]; } diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 1b7278bd7..410614b94 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -635,38 +635,22 @@ void GUI_App::set_auto_toolbar_icon_scale(float scale) const // check user printer_presets for the containing information about "Print Host upload" void GUI_App::check_printer_presets() { - if (!PhysicalPrinter::has_print_host_information(preset_bundle->printers)) + std::vector preset_names = PhysicalPrinter::presets_with_print_host_information(preset_bundle->printers); + if (preset_names.empty()) return; - wxString msg_text = _L("You have presets with saved options for \"Print Host upload\".\n" - "But from this version of PrusaSlicer we don't show/use this information in Printer Settings.\n" + wxString msg_text = _L("You have next presets with saved options for \"Print Host upload\"") + ":"; + for (const std::string& preset_name : preset_names) + msg_text += "\n \"" + from_u8(preset_name) + "\","; + msg_text.RemoveLast(); + msg_text += "\n\n" + _L("But from this version of PrusaSlicer we don't show/use this information in Printer Settings.\n" "Now, this information will be exposed in physical printers settings.") + "\n\n" + - _L("Enter the name for the Printer device used by default during its creation.\n" - "Note: This name can be changed later from the physical printers settings") + ":"; - wxString msg_header = _L("Name for printer device"); + _L("By default new Printer devices will be named as \"Printer N\" during its creation.\n" + "Note: This name can be changed later from the physical printers settings"); - // get custom gcode - wxTextEntryDialog dlg(nullptr, msg_text, msg_header, _L("Printer"), wxTextEntryDialogStyle); + wxMessageDialog(nullptr, msg_text, _L("Information"), wxOK | wxICON_INFORMATION).ShowModal(); - // detect TextCtrl and OK button - wxTextCtrl* textctrl{ nullptr }; - wxWindowList& dlg_items = dlg.GetChildren(); - for (auto item : dlg_items) { - textctrl = dynamic_cast(item); - if (textctrl) - break; - } - - if (textctrl) { - textctrl->SetSelection(0, textctrl->GetLastPosition()); - - wxButton* btn_OK = static_cast(dlg.FindWindowById(wxID_OK)); - btn_OK->Bind(wxEVT_UPDATE_UI, [textctrl](wxUpdateUIEvent& evt) { - evt.Enable(!textctrl->IsEmpty()); - }, btn_OK->GetId()); - } - if (dlg.ShowModal() == wxID_OK) - preset_bundle->physical_printers.load_printers_from_presets(preset_bundle->printers, into_u8(dlg.GetValue())); + preset_bundle->physical_printers.load_printers_from_presets(preset_bundle->printers); } void GUI_App::recreate_GUI(const wxString& msg_name) diff --git a/src/slic3r/GUI/PhysicalPrinterDialog.cpp b/src/slic3r/GUI/PhysicalPrinterDialog.cpp index 7d3c92c13..f14f49801 100644 --- a/src/slic3r/GUI/PhysicalPrinterDialog.cpp +++ b/src/slic3r/GUI/PhysicalPrinterDialog.cpp @@ -510,6 +510,8 @@ void PhysicalPrinterDialog::OnOK(wxEvent& event) // refresh preset list on Printer Settings Tab wxGetApp().get_tab(Preset::TYPE_PRINTER)->select_preset(printers.get_selected_printer_preset_name()); } + else + wxGetApp().get_tab(Preset::TYPE_PRINTER)->update_preset_choice(); event.Skip(); } diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index 01c83921a..666f10194 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -171,7 +171,7 @@ void PresetComboBox::update_selection() SetToolTip(GetString(m_last_selected)); } -void PresetComboBox::update(const std::string& select_preset_name) +void PresetComboBox::update(std::string select_preset_name) { Freeze(); Clear(); @@ -192,6 +192,8 @@ void PresetComboBox::update(const std::string& select_preset_name) // marker used for disable incompatible printer models for the selected physical printer bool is_enabled = m_type == Preset::TYPE_PRINTER && printer_technology != ptAny ? preset.printer_technology() == printer_technology : true; + if (select_preset_name.empty() && is_enabled) + select_preset_name = preset.name; std::string bitmap_key = "cb"; if (m_type == Preset::TYPE_PRINTER) { @@ -208,7 +210,7 @@ void PresetComboBox::update(const std::string& select_preset_name) int item_id = Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), *bmp); if (!is_enabled) set_label_marker(item_id, LABEL_ITEM_DISABLED); - validate_selection(preset.name == select_preset_name || (select_preset_name.empty() && is_enabled)); + validate_selection(preset.name == select_preset_name); } else { @@ -659,6 +661,13 @@ void PlaterPresetComboBox::show_edit_menu() wxTheApp->CallAfter([]() { wxGetApp().run_wizard(ConfigWizard::RR_USER, ConfigWizard::SP_PRINTERS); }); }, "edit_uni", menu, []() { return true; }, wxGetApp().plater()); + append_menu_item(menu, wxID_ANY, _L("Add physical printer"), "", + [this](wxCommandEvent&) { + PhysicalPrinterDialog dlg(wxEmptyString); + if (dlg.ShowModal() == wxID_OK) + update(); + }, "edit_uni", menu, []() { return true; }, wxGetApp().plater()); + wxGetApp().plater()->PopupMenu(menu); } @@ -784,7 +793,7 @@ void PlaterPresetComboBox::update() } } - if (/*m_type == Preset::TYPE_PRINTER || */m_type == Preset::TYPE_SLA_MATERIAL) { + if (m_type == Preset::TYPE_PRINTER || m_type == Preset::TYPE_SLA_MATERIAL) { wxBitmap* bmp = get_bmp("edit_preset_list", wide_icons, "edit_uni"); assert(bmp); diff --git a/src/slic3r/GUI/PresetComboBoxes.hpp b/src/slic3r/GUI/PresetComboBoxes.hpp index fa4554a5e..a30d9f6e9 100644 --- a/src/slic3r/GUI/PresetComboBoxes.hpp +++ b/src/slic3r/GUI/PresetComboBoxes.hpp @@ -55,7 +55,7 @@ public: // and next internal selection was accomplished bool selection_is_changed_according_to_physical_printers(); - void update(const std::string& select_preset); + void update(std::string select_preset); virtual void update(); virtual void msw_rescale(); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index a97c10f7d..4dbe7cc74 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -35,6 +35,7 @@ #include "Plater.hpp" #include "MainFrame.hpp" #include "format.hpp" +#include "PhysicalPrinterDialog.hpp" namespace Slic3r { namespace GUI { @@ -180,6 +181,8 @@ void Tab::create_preset_tab() add_scaled_button(panel, &m_btn_save_preset, "save"); add_scaled_button(panel, &m_btn_delete_preset, "cross"); + if (m_type == Preset::Type::TYPE_PRINTER) + add_scaled_button(panel, &m_btn_edit_ph_printer, "cog"); m_show_incompatible_presets = false; add_scaled_bitmap(this, m_bmp_show_incompatible_presets, "flag_red"); @@ -191,6 +194,8 @@ void Tab::create_preset_tab() m_btn_save_preset->SetToolTip(from_u8((boost::format(_utf8(L("Save current %s"))) % m_title).str())); m_btn_delete_preset->SetToolTip(_(L("Delete this preset"))); m_btn_delete_preset->Disable(); + if (m_btn_edit_ph_printer) + m_btn_edit_ph_printer->Disable(); add_scaled_button(panel, &m_question_btn, "question"); m_question_btn->SetToolTip(_(L("Hover the cursor over buttons to find more information \n" @@ -245,6 +250,10 @@ void Tab::create_preset_tab() m_hsizer->Add(m_btn_save_preset, 0, wxALIGN_CENTER_VERTICAL); m_hsizer->AddSpacer(int(4 * scale_factor)); m_hsizer->Add(m_btn_delete_preset, 0, wxALIGN_CENTER_VERTICAL); + if (m_btn_edit_ph_printer) { + m_hsizer->AddSpacer(int(4 * scale_factor)); + m_hsizer->Add(m_btn_edit_ph_printer, 0, wxALIGN_CENTER_VERTICAL); + } m_hsizer->AddSpacer(int(/*16*/8 * scale_factor)); m_hsizer->Add(m_btn_hide_incompatible_presets, 0, wxALIGN_CENTER_VERTICAL); m_hsizer->AddSpacer(int(8 * scale_factor)); @@ -291,6 +300,13 @@ void Tab::create_preset_tab() toggle_show_hide_incompatible(); })); + if (m_btn_edit_ph_printer) + m_btn_edit_ph_printer->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { + PhysicalPrinterDialog dlg(m_presets_choice->GetString(m_presets_choice->GetSelection())); + if (dlg.ShowModal() == wxID_OK) + update_tab_ui(); + })); + // Fill cache for mode bitmaps m_mode_bitmap_cache.reserve(3); m_mode_bitmap_cache.push_back(ScalableBitmap(this, "mode_simple" , mode_icon_px_size())); @@ -2786,8 +2802,7 @@ void Tab::load_current_preset() { const Preset& preset = m_presets->get_edited_preset(); -// (preset.is_default || preset.is_system) ? m_btn_delete_preset->Disable() : m_btn_delete_preset->Enable(true); - update_delete_preset_btn(); + update_btns_enabling(); update(); if (m_type == Slic3r::Preset::TYPE_PRINTER) { @@ -2924,23 +2939,25 @@ void Tab::update_page_tree_visibility() } -void Tab::update_delete_preset_btn() +void Tab::update_btns_enabling() { - if (m_type == Preset::TYPE_PRINTER && m_presets_choice->is_selected_physical_printer() && - m_preset_bundle->physical_printers.has_selection()) { - // we can't delete last preset from the physical printer + // we can't delete last preset from the physical printer + if (m_type == Preset::TYPE_PRINTER && m_preset_bundle->physical_printers.has_selection()) m_btn_delete_preset->Enable(m_preset_bundle->physical_printers.get_selected_printer().preset_names.size() > 1); - } else { const Preset& preset = m_presets->get_edited_preset(); m_btn_delete_preset->Enable(!preset.is_default && !preset.is_system); } + + // we can edit physical printer only if it's selected in the list + if (m_btn_edit_ph_printer) + m_btn_edit_ph_printer->Enable(m_preset_bundle->physical_printers.has_selection()); } void Tab::update_preset_choice() { m_presets_choice->update(); - update_delete_preset_btn(); + update_btns_enabling(); } // Called by the UI combo box when the user switches profiles, and also to delete the current profile. @@ -2950,55 +2967,16 @@ void Tab::select_preset(std::string preset_name, bool delete_current /*=false*/, { if (preset_name.empty()) { if (delete_current) { - PhysicalPrinterCollection& physical_printers = m_preset_bundle->physical_printers; - if (m_presets_choice->is_selected_physical_printer()) { - PhysicalPrinter& printer = physical_printers.get_selected_printer(); - - if (printer.preset_names.size()==1) { - wxMessageDialog dialog(nullptr, _L("It's a last for this physical printer. We can't delete it"), _L("Information"), wxICON_INFORMATION | wxOK); - dialog.ShowModal(); - } - else { - // just delete this preset from the current physical printer - printer.delete_preset(m_presets->get_edited_preset().name); - // select first from the possible presets for this printer - physical_printers.select_printer(printer); - - preset_name = physical_printers.get_selected_printer_preset_name(); - // revert delete_current value to avoid deleting of the new selected preset - delete_current = false; - } - } - else { - // Check preset for delete in physical printers - // Ask a customer about next action , if there is a printer with just one preset and this preset is equal to delete - if (m_type == Preset::TYPE_PRINTER && !physical_printers.empty() ) - { - // try to delete selected preset from the all printers it has - if (!physical_printers.delete_preset_from_printers(m_presets->get_edited_preset().name)) - { - wxMessageDialog dialog(nullptr, _L("There is/are a physical printer(s), which has/have one and only this printer preset.\n" - "This/Those printer(s) will be deleted after deleting of the selected preset.\n" - "Are you sure you want to delete the selected preset?"), _L("Warning"), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION); - if (dialog.ShowModal() == wxID_NO) - return; - - // delete selected preset from printers and printer, if it's needed - physical_printers.delete_preset_from_printers(m_presets->get_edited_preset().name, false); - } - } - - // Find an alternate preset to be selected after the current preset is deleted. - const std::deque &presets = this->m_presets->get_presets(); - size_t idx_current = this->m_presets->get_idx_selected(); - // Find the next visible preset. - size_t idx_new = idx_current + 1; - if (idx_new < presets.size()) - for (; idx_new < presets.size() && ! presets[idx_new].is_visible; ++ idx_new) ; - if (idx_new == presets.size()) - for (idx_new = idx_current - 1; idx_new > 0 && ! presets[idx_new].is_visible; -- idx_new); - preset_name = presets[idx_new].name; - } + // Find an alternate preset to be selected after the current preset is deleted. + const std::deque &presets = this->m_presets->get_presets(); + size_t idx_current = this->m_presets->get_idx_selected(); + // Find the next visible preset. + size_t idx_new = idx_current + 1; + if (idx_new < presets.size()) + for (; idx_new < presets.size() && ! presets[idx_new].is_visible; ++ idx_new) ; + if (idx_new == presets.size()) + for (idx_new = idx_current - 1; idx_new > 0 && ! presets[idx_new].is_visible; -- idx_new); + preset_name = presets[idx_new].name; } else { // If no name is provided, select the "-- default --" preset. preset_name = m_presets->default_preset().name; @@ -3349,15 +3327,70 @@ void Tab::delete_preset() // Don't let the user delete the ' - default - ' configuration. std::string action = current_preset.is_external ? _utf8(L("remove")) : _utf8(L("delete")); // TRN remove/delete - const wxString msg = m_presets_choice->is_selected_physical_printer() ? - from_u8((boost::format(_utf8(L("Are you sure you want to delete \"%1%\" preset from the physical printer?"))) % current_preset.name).str()) : - from_u8((boost::format(_utf8(L("Are you sure you want to %1% the selected preset?"))) % action).str()); + + PhysicalPrinterCollection& physical_printers = m_preset_bundle->physical_printers; + wxString msg; + if (m_presets_choice->is_selected_physical_printer()) + msg = from_u8((boost::format(_u8L("Are you sure you want to delete \"%1%\" preset from the physical printer \"%2%\"?")) + % current_preset.name % physical_printers.get_selected_printer_name()).str()); + else + { + if (m_type == Preset::TYPE_PRINTER && !physical_printers.empty()) + { + // Check preset for delete in physical printers + // Ask a customer about next action, if there is a printer with just one preset and this preset is equal to delete + std::vector ph_printers = physical_printers.get_printers_with_preset(current_preset.name); + std::vector ph_printers_only = physical_printers.get_printers_with_only_preset(current_preset.name); + + if (!ph_printers.empty()) { + msg += _L("Next physical printer(s) has/have selected preset") + ":"; + for (const std::string& printer : ph_printers) + msg += "\n \"" + from_u8(printer) + "\","; + msg.RemoveLast(); + msg += "\n" + _L("Note, that selected preset will be deleted from this/those printer(s) too.")+ "\n\n"; + } + + if (!ph_printers_only.empty()) { + msg += _L("Next physical printer(s) has/have one and only selected preset") + ":"; + for (const std::string& printer : ph_printers_only) + msg += "\n \"" + from_u8(printer) + "\","; + msg.RemoveLast(); + msg += "\n" + _L("Note, that this/those printer(s) will be deleted after deleting of the selected preset.") + "\n\n"; + } + } + + msg += from_u8((boost::format(_u8L("Are you sure you want to %1% the selected preset?")) % action).str()); + } + action = current_preset.is_external ? _utf8(L("Remove")) : _utf8(L("Delete")); // TRN Remove/Delete wxString title = from_u8((boost::format(_utf8(L("%1% Preset"))) % action).str()); //action + _(L(" Preset")); if (current_preset.is_default || wxID_YES != wxMessageDialog(parent(), msg, title, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION).ShowModal()) return; + + // if we just delete preset from the physical printer + if (m_presets_choice->is_selected_physical_printer()) { + PhysicalPrinter& printer = physical_printers.get_selected_printer(); + + if (printer.preset_names.size() == 1) { + wxMessageDialog dialog(nullptr, _L("It's a last for this physical printer. We can't delete it"), _L("Information"), wxICON_INFORMATION | wxOK); + dialog.ShowModal(); + return; + } + // just delete this preset from the current physical printer + printer.delete_preset(m_presets->get_edited_preset().name); + // select first from the possible presets for this printer + physical_printers.select_printer(printer); + + this->select_preset(physical_printers.get_selected_printer_preset_name()); + return; + } + + // delete selected preset from printers and printer, if it's needed + if (m_type == Preset::TYPE_PRINTER && !physical_printers.empty()) + physical_printers.delete_preset_from_printers(current_preset.name); + // Select will handle of the preset dependencies, of saving & closing the depending profiles, and // finally of deleting the preset. this->select_preset("", true); diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 57129955b..24f25e2d7 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -119,6 +119,7 @@ protected: ScalableButton* m_search_btn; ScalableButton* m_btn_save_preset; ScalableButton* m_btn_delete_preset; + ScalableButton* m_btn_edit_ph_printer {nullptr}; ScalableButton* m_btn_hide_incompatible_presets; wxBoxSizer* m_hsizer; wxBoxSizer* m_left_sizer; @@ -275,7 +276,7 @@ public: void load_current_preset(); void rebuild_page_tree(); void update_page_tree_visibility(); - void update_delete_preset_btn(); + void update_btns_enabling(); void update_preset_choice(); // Select a new preset, possibly delete the current one. void select_preset(std::string preset_name = "", bool delete_current = false, const std::string& last_selected_ph_printer_name = "");