diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index c81f4c6448..f70d678d21 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -535,7 +535,7 @@ Option ConfigOptionsGroup::get_option(const std::string& opt_key, int opt_index m_opt_map.emplace(opt_id, pair); if (m_use_custom_ctrl) // fill group and category values just for options from Settings Tab - wxGetApp().sidebar().get_searcher().add_key(opt_id, title, this->config_category()); + wxGetApp().sidebar().get_searcher().add_key(opt_id, static_cast(this->config_type()), title, this->config_category()); return Option(*m_config->def()->get(opt_key), opt_id); } diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index f19a3e0336..11a52d6485 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -224,10 +224,11 @@ public: ConfigOptionsGroup( wxWindow* parent) : OptionsGroup(parent, wxEmptyString, true, nullptr) {} - const std::string& config_category() const throw() { return m_config_category; } + const wxString& config_category() const throw() { return m_config_category; } + int config_type() const throw() { return m_config_type; } const t_opt_map& opt_map() const throw() { return m_opt_map; } - void set_config_category(const std::string &category) { this->m_config_category = category; } + void set_config_category_and_type(const wxString &category, int type) { this->m_config_category = category; this->m_config_type = type; } void set_config(DynamicPrintConfig* config) { m_config = config; m_modelconfig = nullptr; } Option get_option(const std::string& opt_key, int opt_index = -1); Line create_single_option_line(const std::string& title, const wxString& path = wxEmptyString, int idx = -1) /*const*/{ @@ -274,7 +275,8 @@ private: // If the config is modelconfig, then ModelConfig::touch() has to be called after value change. ModelConfig* m_modelconfig { nullptr }; t_opt_map m_opt_map; - std::string m_config_category; + wxString m_config_category; + int m_config_type; // Change an option on m_config, possibly call ModelConfig::touch(). void change_opt_value(const t_config_option_key& opt_key, const boost::any& value, int opt_index = 0); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index d7224cedc2..f8ec2584c1 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -992,7 +992,7 @@ void Sidebar::search() void Sidebar::jump_to_option(size_t selected) { const Search::Option& opt = p->searcher.get_option(selected); - wxGetApp().get_tab(opt.type)->activate_option(boost::nowide::narrow(opt.opt_key), boost::nowide::narrow(opt.category)); + wxGetApp().get_tab(opt.type)->activate_option(opt.opt_key(), boost::nowide::narrow(opt.category)); // Switch to the Settings NotePad // wxGetApp().mainframe->select_tab(); diff --git a/src/slic3r/GUI/Search.cpp b/src/slic3r/GUI/Search.cpp index 03aa11eb69..9ff4e82a16 100644 --- a/src/slic3r/GUI/Search.cpp +++ b/src/slic3r/GUI/Search.cpp @@ -63,24 +63,29 @@ void change_opt_key(std::string& opt_key, DynamicPrintConfig* config, int& cnt) opt_key += "#" + std::to_string(0); } +static std::string get_key(const std::string& opt_key, Preset::Type type) +{ + return std::to_string(int(type)) + ";" + opt_key; +} + void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type type, ConfigOptionMode mode) { - auto emplace = [this, type](const std::string opt_key, const wxString& label) + auto emplace = [this, type](const std::string key, const wxString& label) { - const GroupAndCategory& gc = groups_and_categories[opt_key]; + const GroupAndCategory& gc = groups_and_categories[key]; if (gc.group.IsEmpty() || gc.category.IsEmpty()) return; wxString suffix; wxString suffix_local; if (gc.category == "Machine limits") { - suffix = opt_key.back()=='1' ? L("Stealth") : L("Normal"); + suffix = key.back()=='1' ? L("Stealth") : L("Normal"); suffix_local = " " + _(suffix); suffix = " " + suffix; } if (!label.IsEmpty()) - options.emplace_back(Option{ boost::nowide::widen(opt_key), type, + options.emplace_back(Option{ boost::nowide::widen(key), type, (label + suffix).ToStdWstring(), (_(label) + suffix_local).ToStdWstring(), gc.group.ToStdWstring(), _(gc.group).ToStdWstring(), gc.category.ToStdWstring(), GUI::Tab::translate_category(gc.category, type).ToStdWstring() }); @@ -108,12 +113,13 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty wxString label = opt.full_label.empty() ? opt.label : opt.full_label; + std::string key = get_key(opt_key, type); if (cnt == 0) - emplace(opt_key, label); + emplace(key, label); else for (int i = 0; i < cnt; ++i) // ! It's very important to use "#". opt_key#n is a real option key used in GroupAndCategory - emplace(opt_key + "#" + std::to_string(i), label); + emplace(key + "#" + std::to_string(i), label); } } @@ -237,10 +243,10 @@ bool OptionsSearcher::search(const std::string& search, bool force/* = false*/) int score2; matches.clear(); fuzzy_match(wsearch, label, score, matches); - if (fuzzy_match(wsearch, opt.opt_key, score2, matches2) && score2 > score) { + if (fuzzy_match(wsearch, opt.key, score2, matches2) && score2 > score) { for (fts::pos_type &pos : matches2) pos += label.size() + 1; - label += L"(" + opt.opt_key + L")"; + label += L"(" + opt.key + L")"; append(matches, matches2); score = score2; } @@ -318,9 +324,9 @@ const Option& OptionsSearcher::get_option(size_t pos_in_filter) const return options[found[pos_in_filter].option_idx]; } -const Option& OptionsSearcher::get_option(const std::string& opt_key) const +const Option& OptionsSearcher::get_option(const std::string& opt_key, Preset::Type type) const { - auto it = std::lower_bound(options.begin(), options.end(), Option({ boost::nowide::widen(opt_key) })); + auto it = std::lower_bound(options.begin(), options.end(), Option({ boost::nowide::widen(get_key(opt_key, type)) })); assert(it != options.end()); return options[it - options.begin()]; @@ -342,7 +348,7 @@ static Option create_option(const std::string& opt_key, const wxString& label, P category = wxString::Format("%s %d", "Extruder", atoi(opt_idx.c_str()) + 1); } - return Option{ boost::nowide::widen(opt_key), type, + return Option{ boost::nowide::widen(get_key(opt_key, type)), type, (label + suffix).ToStdWstring(), (_(label) + suffix_local).ToStdWstring(), gc.group.ToStdWstring(), _(gc.group).ToStdWstring(), gc.category.ToStdWstring(), GUI::Tab::translate_category(category, type).ToStdWstring() }; @@ -350,15 +356,16 @@ static Option create_option(const std::string& opt_key, const wxString& label, P Option OptionsSearcher::get_option(const std::string& opt_key, const wxString& label, Preset::Type type) const { - auto it = std::lower_bound(options.begin(), options.end(), Option({ boost::nowide::widen(opt_key) })); - if(it->opt_key == boost::nowide::widen(opt_key)) + std::string key = get_key(opt_key, type); + auto it = std::lower_bound(options.begin(), options.end(), Option({ boost::nowide::widen(key) })); + if(it->key == boost::nowide::widen(key)) return options[it - options.begin()]; - if (groups_and_categories.find(opt_key) == groups_and_categories.end()) { - size_t pos = opt_key.find('#'); + if (groups_and_categories.find(key) == groups_and_categories.end()) { + size_t pos = key.find('#'); if (pos == std::string::npos) return options[it - options.begin()]; - std::string zero_opt_key = opt_key.substr(0, pos + 1) + "0"; + std::string zero_opt_key = key.substr(0, pos + 1) + "0"; if(groups_and_categories.find(zero_opt_key) == groups_and_categories.end()) return options[it - options.begin()]; @@ -366,16 +373,16 @@ Option OptionsSearcher::get_option(const std::string& opt_key, const wxString& l return create_option(opt_key, label, type, groups_and_categories.at(zero_opt_key)); } - const GroupAndCategory& gc = groups_and_categories.at(opt_key); + const GroupAndCategory& gc = groups_and_categories.at(key); if (gc.group.IsEmpty() || gc.category.IsEmpty()) return options[it - options.begin()]; return create_option(opt_key, label, type, gc); } -void OptionsSearcher::add_key(const std::string& opt_key, const wxString& group, const wxString& category) +void OptionsSearcher::add_key(const std::string& opt_key, Preset::Type type, const wxString& group, const wxString& category) { - groups_and_categories[opt_key] = GroupAndCategory{group, category}; + groups_and_categories[get_key(opt_key, type)] = GroupAndCategory{group, category}; } diff --git a/src/slic3r/GUI/Search.hpp b/src/slic3r/GUI/Search.hpp index 1f2909564d..30b9691125 100644 --- a/src/slic3r/GUI/Search.hpp +++ b/src/slic3r/GUI/Search.hpp @@ -38,11 +38,11 @@ struct GroupAndCategory { struct Option { // bool operator<(const Option& other) const { return other.label > this->label; } - bool operator<(const Option& other) const { return other.opt_key > this->opt_key; } + bool operator<(const Option& other) const { return other.key > this->key; } // Fuzzy matching works at a character level. Thus matching with wide characters is a safer bet than with short characters, // though for some languages (Chinese?) it may not work correctly. - std::wstring opt_key; + std::wstring key; Preset::Type type {Preset::TYPE_INVALID}; std::wstring label; std::wstring label_local; @@ -50,6 +50,8 @@ struct Option { std::wstring group_local; std::wstring category; std::wstring category_local; + + std::string opt_key() const { return boost::nowide::narrow(key).substr(2); } }; struct FoundOption { @@ -110,13 +112,13 @@ public: bool search(); bool search(const std::string& search, bool force = false); - void add_key(const std::string& opt_key, const wxString& group, const wxString& category); + void add_key(const std::string& opt_key, Preset::Type type, const wxString& group, const wxString& category); size_t size() const { return found_size(); } const FoundOption& operator[](const size_t pos) const noexcept { return found[pos]; } const Option& get_option(size_t pos_in_filter) const; - const Option& get_option(const std::string& opt_key) const; + const Option& get_option(const std::string& opt_key, Preset::Type type) const; Option get_option(const std::string& opt_key, const wxString& label, Preset::Type type) const; const std::vector& found_options() { return found; } @@ -125,10 +127,11 @@ public: void set_printer_technology(PrinterTechnology pt) { printer_technology = pt; } - void sort_options_by_opt_key() { + void sort_options_by_key() { std::sort(options.begin(), options.end(), [](const Option& o1, const Option& o2) { - return o1.opt_key < o2.opt_key; }); + return o1.key < o2.key; }); } + void sort_options_by_label() { sort_options(); } }; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index de2e84515e..74b54478e7 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -3802,8 +3802,8 @@ wxSizer* TabPrinter::create_bed_shape_widget(wxWindow* parent) { Search::OptionsSearcher& searcher = wxGetApp().sidebar().get_searcher(); const Search::GroupAndCategory& gc = searcher.get_group_and_category("bed_shape"); - searcher.add_key("bed_custom_texture", gc.group, gc.category); - searcher.add_key("bed_custom_model", gc.group, gc.category); + searcher.add_key("bed_custom_texture", m_type, gc.group, gc.category); + searcher.add_key("bed_custom_model", m_type, gc.group, gc.category); } return sizer; @@ -4044,7 +4044,6 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la { //! config_ have to be "right" ConfigOptionsGroupShp optgroup = std::make_shared(m_parent, title, m_config, true); - optgroup->set_config_category(m_title.ToStdString()); if (noncommon_label_width >= 0) optgroup->label_width = noncommon_label_width; @@ -4053,6 +4052,7 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la #else auto tab = parent()->GetParent();// GetParent(); #endif + optgroup->set_config_category_and_type(m_title, static_cast(tab)->type()); optgroup->m_on_change = [tab](t_config_option_key opt_key, boost::any value) { //! This function will be called from OptionGroup. //! Using of CallAfter is redundant. diff --git a/src/slic3r/GUI/UnsavedChangesDialog.cpp b/src/slic3r/GUI/UnsavedChangesDialog.cpp index 7c0be76a4a..0a0a3dc60f 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.cpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.cpp @@ -833,10 +833,10 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_ (*btn)->Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent& e) { show_info_line(Action::Undef); e.Skip(); }); }; - const PresetCollection& printers = wxGetApp().preset_bundle->printers; - if (dependent_presets && (type == dependent_presets->type() ? + const PresetCollection* switched_presets = type == Preset::TYPE_INVALID ? nullptr : wxGetApp().get_tab(type)->get_presets(); + if (dependent_presets && switched_presets && (type == dependent_presets->type() ? dependent_presets->get_edited_preset().printer_technology() == dependent_presets->find_preset(new_selected_preset)->printer_technology() : - printers.get_edited_preset().printer_technology() == printers.find_preset(new_selected_preset)->printer_technology())) + switched_presets->get_edited_preset().printer_technology() == switched_presets->find_preset(new_selected_preset)->printer_technology())) add_btn(&m_transfer_btn, m_move_btn_id, "paste_menu", Action::Transfer, _L("Transfer")); add_btn(&m_discard_btn, m_continue_btn_id, dependent_presets ? "switch_presets" : "exit", Action::Discard, _L("Discard"), false); add_btn(&m_save_btn, m_save_btn_id, "save", Action::Save, _L("Save")); @@ -1185,7 +1185,7 @@ void UnsavedChangesDialog::update(Preset::Type type, PresetCollection* dependent void UnsavedChangesDialog::update_tree(Preset::Type type, PresetCollection* presets_) { Search::OptionsSearcher& searcher = wxGetApp().sidebar().get_searcher(); - searcher.sort_options_by_opt_key(); + searcher.sort_options_by_key(); // list of the presets with unsaved changes std::vector presets_list; @@ -1227,8 +1227,8 @@ void UnsavedChangesDialog::update_tree(Preset::Type type, PresetCollection* pres } for (const std::string& opt_key : dirty_options) { - const Search::Option& option = searcher.get_option(opt_key); - if (option.opt_key != boost::nowide::widen(opt_key)) { + const Search::Option& option = searcher.get_option(opt_key, type); + if (option.opt_key() != opt_key) { // When founded option isn't the correct one. // It can be for dirty_options: "default_print_profile", "printer_model", "printer_settings_id", // because of they don't exist in searcher @@ -1239,6 +1239,9 @@ void UnsavedChangesDialog::update_tree(Preset::Type type, PresetCollection* pres get_string_value(opt_key, old_config), get_string_value(opt_key, new_config), category_icon_map.at(option.category)); } } + + // Revert sort of searcher back + searcher.sort_options_by_label(); } void UnsavedChangesDialog::on_dpi_changed(const wxRect& suggested_rect) @@ -1546,7 +1549,7 @@ void DiffPresetDialog::update_presets(Preset::Type type) void DiffPresetDialog::update_tree() { Search::OptionsSearcher& searcher = wxGetApp().sidebar().get_searcher(); - searcher.sort_options_by_opt_key(); + searcher.sort_options_by_key(); m_tree->Clear(); wxString bottom_info = ""; @@ -1617,7 +1620,7 @@ void DiffPresetDialog::update_tree() wxString right_val = get_string_value(opt_key, right_congig); Search::Option option = searcher.get_option(opt_key, get_full_label(opt_key, left_config), type); - if (option.opt_key != boost::nowide::widen(opt_key)) { + if (option.opt_key() != opt_key) { // temporary solution, just for testing m_tree->Append(opt_key, type, _L("Undef category"), _L("Undef group"), opt_key, left_val, right_val, "question"); // When founded option isn't the correct one. @@ -1642,6 +1645,9 @@ void DiffPresetDialog::update_tree() Fit(); Refresh(); } + + // Revert sort of searcher back + searcher.sort_options_by_label(); } void DiffPresetDialog::on_dpi_changed(const wxRect&)