diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index ec3e933384..c9f5bd0af0 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -1345,6 +1345,11 @@ const Preset* PrinterPresetCollection::find_by_model_id(const std::string &model // *** PhysicalPrinter *** // ------------------------- +std::string PhysicalPrinter::separator() +{ + return " * "; +} + const std::vector& PhysicalPrinter::printer_options() { static std::vector s_opts; @@ -1370,9 +1375,9 @@ const std::string& PhysicalPrinter::get_preset_name() const return config.opt_string("preset_name"); } -const std::string& PhysicalPrinter::get_printer_model() const +const std::set& PhysicalPrinter::get_preset_names() const { - return config.opt_string("printer_model"); + return preset_names; } bool PhysicalPrinter::has_empty_config() const @@ -1384,20 +1389,62 @@ bool PhysicalPrinter::has_empty_config() const config.opt_string("password" ).empty(); } +void PhysicalPrinter::update_preset_names_in_config() +{ + if (!preset_names.empty()) { + std::string name; + for (auto el : preset_names) + name += el + ";"; + name.pop_back(); + config.set_key_value("preset_name", new ConfigOptionString(name)); + } +} + +void PhysicalPrinter::save(const std::string& file_name_from, const std::string& file_name_to) +{ + // rename the file + boost::nowide::rename(file_name_from.data(), file_name_to.data()); + this->file = file_name_to; + // save configuration + this->config.save(this->file); +} + void PhysicalPrinter::update_from_preset(const Preset& preset) { config.apply_only(preset.config, printer_options(), false); - // add preset name to the options list - config.set_key_value("preset_name", new ConfigOptionString(preset.name)); + // add preset names to the options list + auto ret = preset_names.emplace(preset.name); + update_preset_names_in_config(); + update_full_name(); } void PhysicalPrinter::update_from_config(const DynamicPrintConfig& new_config) { config.apply_only(new_config, printer_options(), false); + + std::string str = config.opt_string("preset_name"); + std::set values{}; + if (!str.empty()) { + boost::split(values, str, boost::is_any_of(";")); + for (const std::string& val : values) + preset_names.emplace(val); + } + preset_names = values; + update_full_name(); } +void PhysicalPrinter::reset_presets() +{ + return preset_names.clear(); +} + +bool PhysicalPrinter::add_preset(const std::string& preset_name) +{ + return preset_names.emplace(preset_name).second; +} + PhysicalPrinter::PhysicalPrinter(const std::string& name, const Preset& preset) : name(name) { @@ -1412,16 +1459,23 @@ void PhysicalPrinter::set_name(const std::string& name) void PhysicalPrinter::update_full_name() { - full_name = name + " * " + get_preset_name(); + full_name = name + separator() + get_preset_name(); } std::string PhysicalPrinter::get_short_name(std::string full_name) { - int pos = full_name.find_first_of(" * "); + int pos = full_name.find(separator()); boost::erase_tail(full_name, full_name.length() - pos); return full_name; } +std::string PhysicalPrinter::get_preset_name(std::string full_name) +{ + int pos = full_name.find(separator()); + boost::erase_head(full_name, pos + 2); + return full_name; +} + // ----------------------------------- // *** PhysicalPrinterCollection *** @@ -1497,15 +1551,18 @@ std::string PhysicalPrinterCollection::path_from_name(const std::string& new_nam return (boost::filesystem::path(m_dir_path) / file_name).make_preferred().string(); } -void PhysicalPrinterCollection::save_printer(const PhysicalPrinter& edited_printer) +void PhysicalPrinterCollection::save_printer(const PhysicalPrinter& edited_printer, const std::string& renamed_from) { + std::string name = renamed_from.empty() ? edited_printer.name : renamed_from; // 1) Find the printer with a new_name or create a new one, // initialize it with the edited config. - auto it = this->find_printer_internal(edited_printer.name); - if (it != m_printers.end() && it->name == edited_printer.name) { + auto it = this->find_printer_internal(name); + if (it != m_printers.end() && it->name == name) { // Printer with the same name found. // Overwriting an existing preset. it->config = std::move(edited_printer.config); + it->name = edited_printer.name; + it->preset_names = edited_printer.preset_names; it->full_name = edited_printer.full_name; } else { @@ -1518,7 +1575,12 @@ void PhysicalPrinterCollection::save_printer(const PhysicalPrinter& edited_print PhysicalPrinter& printer = *it; if (printer.file.empty()) printer.file = this->path_from_name(printer.name); - printer.save(); + + if (printer.file == this->path_from_name(printer.name)) + printer.save(); + else + // if printer was renamed, we should rename a file and than save the config + printer.save(printer.file, this->path_from_name(printer.name)); // update idx_selected m_idx_selected = it - m_printers.begin(); diff --git a/src/libslic3r/Preset.hpp b/src/libslic3r/Preset.hpp index a076a9a217..d583bed20d 100644 --- a/src/libslic3r/Preset.hpp +++ b/src/libslic3r/Preset.hpp @@ -549,20 +549,33 @@ public: std::string file; // Configuration data, loaded from a file, or set from the defaults. DynamicPrintConfig config; + // set of presets used with this physical printer + std::set preset_names; + + static std::string separator(); // Has this profile been loaded? bool loaded = false; - static const std::vector& printer_options(); - const std::string& get_preset_name() const; - const std::string& get_printer_model() const; + static const std::vector& printer_options(); + const std::string& get_preset_name() const; + + const std::set& get_preset_names() const; + bool has_empty_config() const; + void update_preset_names_in_config(); void save() { this->config.save(this->file); } - void save_to(const std::string& file_name) const { this->config.save(file_name); } + void save(const std::string& file_name_from, const std::string& file_name_to); + void update_from_preset(const Preset& preset); void update_from_config(const DynamicPrintConfig &new_config); + // add preset to the preset_names + // return false, if preset with this name is already exist in the set + bool add_preset(const std::string& preset_name); + void reset_presets(); + // Return a printer technology, return ptFFF if the printer technology is not set. static PrinterTechnology printer_technology(const DynamicPrintConfig& cfg) { auto* opt = cfg.option>("printer_technology"); @@ -578,6 +591,9 @@ public: // get printer name from the full name uncluded preset name static std::string get_short_name(std::string full_name); + // get preset name from the full name uncluded printer name + static std::string get_preset_name(std::string full_name); + protected: friend class PhysicalPrinterCollection; }; @@ -615,7 +631,7 @@ public: // 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. // New printer is activated. - void save_printer(const PhysicalPrinter& printer); + void save_printer(const PhysicalPrinter& printer, const std::string& renamed_from); // Delete the current preset, activate the first visible preset. // returns true if the preset was deleted successfully. @@ -633,8 +649,6 @@ public: // Returns the full name of the selected preset, or an empty string if no preset is selected. std::string get_selected_full_printer_name() const { return (m_idx_selected == size_t(-1)) ? std::string() : this->get_selected_printer().full_name; } // Returns the printer model of the selected preset, or an empty string if no preset is selected. - std::string get_selected_printer_model() const { return (m_idx_selected == size_t(-1)) ? std::string() : this->get_selected_printer().get_printer_model(); } - // Returns the printer model of the selected preset, or an empty string if no preset is selected. std::string get_selected_printer_preset_name() const { return (m_idx_selected == size_t(-1)) ? std::string() : this->get_selected_printer().get_preset_name(); } // Returns the config of the selected preset, or nullptr if no preset is selected. DynamicPrintConfig* get_selected_printer_config() { return (m_idx_selected == size_t(-1)) ? nullptr : &(this->get_selected_printer().config); } diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index dc5365a139..1473bf6dab 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -41,6 +41,8 @@ static const std::pair THUMBNAIL_SIZE_3MF = { 256, 2 namespace Slic3r { namespace GUI { +#define BORDER_W 10 + // --------------------------------- // *** PresetComboBox *** // --------------------------------- @@ -762,8 +764,8 @@ void TabPresetComboBox::update() // check this value just for printer presets, when physical printer is selected if (m_type == Preset::TYPE_PRINTER && m_preset_bundle->physical_printers.has_selection()) { is_enabled = m_enable_all ? true : - preset.name == m_preset_bundle->physical_printers.get_selected_printer_preset_name() || - preset.config.opt_string("printer_model") == m_preset_bundle->physical_printers.get_selected_printer_model(); + preset.name == m_preset_bundle->physical_printers.get_selected_printer_preset_name()/* || + preset.config.opt_string("printer_model") == m_preset_bundle->physical_printers.get_selected_printer_model()*/; } std::string bitmap_key = "tab"; @@ -888,7 +890,7 @@ void TabPresetComboBox::update_dirty() // PresetForPrinter //------------------------------------------ -PresetForPrinter::PresetForPrinter(PhysicalPrinterDialog* parent, bool is_all_enable) : +PresetForPrinter::PresetForPrinter(PhysicalPrinterDialog* parent, const std::string& preset_name) : m_parent(parent) { m_sizer = new wxBoxSizer(wxVERTICAL); @@ -899,8 +901,7 @@ PresetForPrinter::PresetForPrinter(PhysicalPrinterDialog* parent, bool is_all_en m_delete_preset_btn->Bind(wxEVT_BUTTON, &PresetForPrinter::DeletePreset, this); m_presets_list = new TabPresetComboBox(parent, Preset::TYPE_PRINTER); - - if (is_all_enable) + if (preset_name.empty()) m_presets_list->set_enable_all(); m_presets_list->set_selection_changed_function([this](int selection) { @@ -921,22 +922,37 @@ PresetForPrinter::PresetForPrinter(PhysicalPrinterDialog* parent, bool is_all_en update_full_printer_name(); }); + m_presets_list->update(); + m_presets_list->SetStringSelection(from_u8(preset_name)); + + m_info_line = new wxStaticText(parent, wxID_ANY, _L("This printer will be shown in the presets list as") + ":"); m_full_printer_name = new wxStaticText(parent, wxID_ANY, ""); + m_full_printer_name->SetFont(wxGetApp().bold_font()); - m_presets_list->update(); + wxBoxSizer* preset_sizer = new wxBoxSizer(wxHORIZONTAL); + preset_sizer->Add(m_presets_list , 1, wxEXPAND); + preset_sizer->Add(m_delete_preset_btn , 0, wxEXPAND | wxLEFT, BORDER_W); + + wxBoxSizer* name_sizer = new wxBoxSizer(wxHORIZONTAL); + name_sizer->Add(m_info_line, 0, wxEXPAND); + name_sizer->Add(m_full_printer_name, 0, wxEXPAND | wxLEFT, BORDER_W); + + m_sizer->Add(preset_sizer , 0, wxEXPAND); + m_sizer->Add(name_sizer, 0, wxEXPAND); } PresetForPrinter::~PresetForPrinter() { m_presets_list->Destroy(); m_delete_preset_btn->Destroy(); + m_info_line->Destroy(); m_full_printer_name->Destroy(); } void PresetForPrinter::DeletePreset(wxEvent& event) { - + m_parent->DeletePreset(this); } void PresetForPrinter::update_full_printer_name() @@ -947,6 +963,22 @@ void PresetForPrinter::update_full_printer_name() m_full_printer_name->SetLabelText(printer_name + " * " + preset_name); } +std::string PresetForPrinter::get_preset_name() +{ + return into_u8(m_presets_list->GetString(m_presets_list->GetSelection())); +} + +void PresetForPrinter::DisableDeleteBtn() +{ + m_delete_preset_btn->Enable(false); +} + +void PresetForPrinter::EnableDeleteBtn() +{ + if (!m_delete_preset_btn->IsEnabled()) + m_delete_preset_btn->Enable(); +} + void PresetForPrinter::msw_rescale() { m_presets_list->msw_rescale(); @@ -965,22 +997,17 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxString printer_name) SetFont(wxGetApp().normal_font()); SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); - int border = 10; - m_info_string = _("This printer name will be shown in the presets list") + ":\n"; - - TabPresetComboBox* printer_presets = new TabPresetComboBox(this, Preset::TYPE_PRINTER); - if (printer_name.IsEmpty()) { printer_name = _L("My Printer Device"); // if printer_name is empty it means that new printer is created, so enable all items in the preset list - m_presets.emplace_back(new PresetForPrinter(this, true)); + m_presets.emplace_back(new PresetForPrinter(this, "")); } else { std::string full_name = into_u8(printer_name); printer_name = from_u8(PhysicalPrinter::get_short_name(full_name)); } - wxStaticText* label_top = new wxStaticText(this, wxID_ANY, _("Descriptive name for the printer device") + ":"); + wxStaticText* label_top = new wxStaticText(this, wxID_ANY, _L("Descriptive name for the printer device") + ":"); m_add_preset_btn = new ScalableButton(this, wxID_ANY, "add_copies", "", wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT); m_add_preset_btn->SetFont(wxGetApp().normal_font()); @@ -990,17 +1017,26 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxString printer_name) m_printer_name = new wxTextCtrl(this, wxID_ANY, printer_name, wxDefaultPosition, wxDefaultSize); m_printer_name->Bind(wxEVT_TEXT, [this](wxEvent&) { this->update_full_printer_names(); }); - update_full_printer_names(); - PhysicalPrinterCollection& printers = wxGetApp().preset_bundle->physical_printers; PhysicalPrinter* printer = printers.find_printer(into_u8(printer_name)); if (!printer) { const Preset& preset = wxGetApp().preset_bundle->printers.get_edited_preset(); printer = new PhysicalPrinter(into_u8(printer_name), preset); } + else + { + const std::set& preset_names = printer->get_preset_names(); + for (const std::string& preset_name : preset_names) + m_presets.emplace_back(new PresetForPrinter(this, preset_name)); + } assert(printer); m_printer = *printer; + if (m_presets.size() == 1) + m_presets.front()->DisableDeleteBtn(); + + update_full_printer_names(); + m_config = &m_printer.config; m_optgroup = new ConfigOptionsGroup(this, _L("Print Host upload"), m_config); @@ -1013,21 +1049,19 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxString printer_name) wxBoxSizer* nameSizer = new wxBoxSizer(wxHORIZONTAL); nameSizer->Add(m_printer_name, 1, wxEXPAND); - nameSizer->Add(m_add_preset_btn, 0, wxEXPAND | wxLEFT, border); + nameSizer->Add(m_add_preset_btn, 0, wxEXPAND | wxLEFT, BORDER_W); + + m_presets_sizer = new wxBoxSizer(wxVERTICAL); + for (PresetForPrinter* preset : m_presets) + m_presets_sizer->Add(preset->sizer(), 1, wxEXPAND | wxTOP, BORDER_W); wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL); - topSizer->Add(label_top , 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border); - topSizer->Add(nameSizer , 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border); - for (PresetForPrinter* preset : m_presets) - topSizer->Add(preset->sizer(), 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border);; - /* - topSizer->Add(m_printer_presets , 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border); - topSizer->Add(label_bottom , 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border); - topSizer->Add(m_full_printer_name , 0, wxEXPAND | wxLEFT | wxRIGHT, border); - */ - topSizer->Add(m_optgroup->sizer , 1, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border); - topSizer->Add(btns , 0, wxEXPAND | wxALL, border); + topSizer->Add(label_top , 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, BORDER_W); + topSizer->Add(nameSizer , 0, wxEXPAND | wxLEFT | wxRIGHT, BORDER_W); + topSizer->Add(m_presets_sizer , 0, wxEXPAND | wxLEFT | wxRIGHT, BORDER_W); + topSizer->Add(m_optgroup->sizer , 1, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, BORDER_W); + topSizer->Add(btns , 0, wxEXPAND | wxALL, BORDER_W); SetSizer(topSizer); topSizer->SetSizeHints(this); @@ -1203,7 +1237,7 @@ void PhysicalPrinterDialog::update() wxString PhysicalPrinterDialog::get_printer_name() { - return m_info_string + m_printer_name->GetValue() + "\t"; + return m_printer_name->GetValue(); } void PhysicalPrinterDialog::update_full_printer_names() @@ -1260,11 +1294,39 @@ void PhysicalPrinterDialog::OnOK(wxEvent& event) printers.delete_printer(into_u8(printer_name)); } + std::set repeat_presets; + m_printer.reset_presets(); + for (PresetForPrinter* preset : m_presets) { + if (!m_printer.add_preset(preset->get_preset_name())) + repeat_presets.emplace(preset->get_preset_name()); + } + // update preset_names in printer config + m_printer.update_preset_names_in_config(); + + if (!repeat_presets.empty()) + { + wxString repeatable_presets = "\n"; + for (const std::string& preset_name : repeat_presets) + repeatable_presets += " " + from_u8(preset_name) + "\n"; + repeatable_presets += "\n"; + + wxString msg_text = from_u8((boost::format(_u8L("Next printer preset(s) is(are) duplicated:%1%" + "It(they) will be added just once for the printer \"%2%\".")) % repeatable_presets % printer_name).str()); + wxMessageDialog dialog(nullptr, msg_text, _L("Infornation"), wxICON_INFORMATION | wxOK); + dialog.ShowModal(); + } + + std::string renamed_from; + // temporary save previous printer name if it was edited + if (m_printer.name != _u8L("My Printer Device") && + m_printer.name != into_u8(printer_name)) + renamed_from = m_printer.name; + //update printer name, if it was changed m_printer.set_name(into_u8(printer_name)); // save new physical printer - printers.save_printer(m_printer); + printers.save_printer(m_printer, renamed_from); // update selection on the tab only when it was changed /* @@ -1282,7 +1344,41 @@ void PhysicalPrinterDialog::OnOK(wxEvent& event) void PhysicalPrinterDialog::AddPreset(wxEvent& event) { + // if printer_name is empty it means that new printer is created, so enable all items in the preset list + m_presets.emplace_back(new PresetForPrinter(this, "")); + // enable DELETE button for the first preset, if was disabled + m_presets.front()->EnableDeleteBtn(); + m_presets_sizer->Add(m_presets.back()->sizer(), 1, wxEXPAND | wxTOP, BORDER_W); + update_full_printer_names(); + + this->Fit(); +} + +void PhysicalPrinterDialog::DeletePreset(PresetForPrinter* preset_for_printer) +{ + if (m_presets.size() == 1) { + wxString msg_text = _L("It's not possible to delete last related preset for the printer."); + wxMessageDialog dialog(nullptr, msg_text, _L("Infornation"), wxICON_INFORMATION | wxOK); + dialog.ShowModal(); + return; + } + + assert(preset_for_printer); + auto it = std::find(m_presets.begin(), m_presets.end(), preset_for_printer); + if (it == m_presets.end()) + return; + + const int remove_id = it - m_presets.begin(); + m_presets_sizer->Remove(remove_id); + delete preset_for_printer; + m_presets.erase(it); + + if (m_presets.size() == 1) + m_presets.front()->DisableDeleteBtn(); + + this->Layout(); + this->Fit(); } diff --git a/src/slic3r/GUI/PresetComboBoxes.hpp b/src/slic3r/GUI/PresetComboBoxes.hpp index 3d5ae298f0..c818b6b911 100644 --- a/src/slic3r/GUI/PresetComboBoxes.hpp +++ b/src/slic3r/GUI/PresetComboBoxes.hpp @@ -15,6 +15,7 @@ class wxString; class wxTextCtrl; class wxStaticText; class ScalableButton; +class wxBoxSizer; namespace Slic3r { @@ -169,6 +170,7 @@ public: //------------------------------------------ // PresetForPrinter //------------------------------------------ +static std::string g_info_string = " (modified)"; class PhysicalPrinterDialog; class PresetForPrinter { @@ -176,6 +178,7 @@ class PresetForPrinter TabPresetComboBox* m_presets_list { nullptr }; ScalableButton* m_delete_preset_btn { nullptr }; + wxStaticText* m_info_line { nullptr }; wxStaticText* m_full_printer_name { nullptr }; wxBoxSizer* m_sizer { nullptr }; @@ -183,11 +186,14 @@ class PresetForPrinter void DeletePreset(wxEvent& event); public: - PresetForPrinter(PhysicalPrinterDialog* parent, bool is_all_enable); + PresetForPrinter(PhysicalPrinterDialog* parent, const std::string& preset_name); ~PresetForPrinter(); wxBoxSizer* sizer() { return m_sizer; } void update_full_printer_name(); + std::string get_preset_name(); + void DisableDeleteBtn(); + void EnableDeleteBtn(); void msw_rescale(); void on_sys_color_changed() {}; @@ -203,7 +209,6 @@ class PhysicalPrinterDialog : public DPIDialog { PhysicalPrinter m_printer; DynamicPrintConfig* m_config { nullptr }; - wxString m_info_string; wxTextCtrl* m_printer_name { nullptr }; std::vector m_presets; @@ -215,6 +220,8 @@ class PhysicalPrinterDialog : public DPIDialog ScalableButton* m_printhost_test_btn {nullptr}; ScalableButton* m_printhost_cafile_browse_btn {nullptr}; + wxBoxSizer* m_presets_sizer {nullptr}; + void build_printhost_settings(ConfigOptionsGroup* optgroup); void OnOK(wxEvent& event); void AddPreset(wxEvent& event); @@ -228,6 +235,8 @@ public: void update_full_printer_names(); PhysicalPrinter* get_printer() {return &m_printer; } + void DeletePreset(PresetForPrinter* preset_for_printer); + protected: void on_dpi_changed(const wxRect& suggested_rect) override; void on_sys_color_changed() override {};