#include "SettingsIndex.hpp" #include #include #include #include #include #include #include "GUI.hpp" #include "I18N.hpp" #include "Tab.hpp" #include "libslic3r/PrintConfig.hpp" namespace Slic3r { using GUI::into_u8; namespace Search { static std::string get_key(const std::string &opt_key, Preset::Type type) { return std::to_string(int(type)) + ";" + opt_key; } std::string Option::opt_key() const { return key.size() < 2 ? std::string() : into_u8(key).substr(2); } template // void change_opt_key(std::string& opt_key, DynamicPrintConfig* config) void change_opt_key(std::string &opt_key, DynamicPrintConfig *config, int &cnt) { T *opt_cur = static_cast(config->option(opt_key)); cnt = opt_cur->values.size(); return; if (opt_cur->values.size() > 0) opt_key += "#" + std::to_string(0); } // Single assembler for an indexed Option, shared by append_options() and create_option(), so a new // Option field is only wired up in one place. static Option make_option(const std::string &key, Preset::Type type, const wxString &label, const GroupAndCategory &gc, ConfigOptionMode mode, const std::string &tooltip, bool rewrite_extruder_category) { wxString suffix; wxString suffix_local; if (gc.category == "Machine limits") { //suffix = key.back() == '1' ? L("Stealth") : L("Normal"); suffix = key.back() == '1' ? wxEmptyString : wxEmptyString; suffix_local = " " + _(suffix); suffix = " " + suffix; } wxString category = gc.category; if (rewrite_extruder_category && type == Preset::TYPE_PRINTER && category.Contains("Extruder ")) { std::string opt_idx = key.substr(key.find("#") + 1); category = wxString::Format("%s %d", "Extruder", atoi(opt_idx.c_str()) + 1); } Option option{boost::nowide::widen(key), type, (label + suffix).ToStdWstring(), (_(label) + suffix_local).ToStdWstring(), gc.group.ToStdWstring(), _(gc.group).ToStdWstring(), into_u8(gc.icon), gc.category.ToStdWstring(), GUI::Tab::translate_category(category, type).ToStdWstring(), false, mode, tooltip, gc.path, // The settings page draws Line::label; carrying it lets the Speed Dial name a setting // the way the page does. `label`/`label_local` stay the search-oriented name. into_u8(gc.line_label)}; return option; } void SettingsIndex::append_options(DynamicPrintConfig *config, Preset::Type type, ConfigOptionMode mode) { for (std::string opt_key : config->keys()) { const ConfigOptionDef &opt = config->def()->options.at(opt_key); const bool in_filtered = opt.mode <= mode; int cnt = 0; if ((type == Preset::TYPE_SLA_MATERIAL || type == Preset::TYPE_PRINTER || type == Preset::TYPE_PRINT) && opt_key != "printable_area") switch (config->option(opt_key)->type()) { case coInts: change_opt_key(opt_key, config, cnt); break; case coBools: change_opt_key(opt_key, config, cnt); break; case coFloats: change_opt_key(opt_key, config, cnt); break; case coStrings: change_opt_key(opt_key, config, cnt); break; case coPercents: change_opt_key(opt_key, config, cnt); break; case coFloatsOrPercents: change_opt_key>(opt_key, config, cnt); break; case coPoints: change_opt_key(opt_key, config, cnt); break; // BBS case coEnums: change_opt_key(opt_key, config, cnt); break; default: break; } if (type == Preset::TYPE_FILAMENT && filament_options_with_variant.find(opt_key) != filament_options_with_variant.end()) opt_key += "#0"; wxString label = opt.full_label.empty() ? opt.label : opt.full_label; std::string key = get_key(opt_key, type); auto add = [&](const std::string &k) { const GroupAndCategory &gc = m_groups_and_categories[k]; if (gc.group.IsEmpty() || gc.category.IsEmpty() || label.IsEmpty()) return; const std::string tooltip = into_u8(_(opt.tooltip)); if (in_filtered) m_options.emplace_back(make_option(k, type, label, gc, opt.mode, tooltip, false)); m_all_modes.emplace_back(make_option(k, type, label, gc, opt.mode, tooltip, false)); }; if (cnt == 0) add(key); 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 add(key + "#" + std::to_string(i)); } } void SettingsIndex::sort_options() { // Both views are label-sorted and multi_category-marked. They are separate consumers (the sidebar // search and the Speed Dial); keeping them in sync here prevents the all-modes view from silently // diverging in order or flags. auto sort_and_mark = [](std::vector