Skip to content

Commit

Permalink
Fix search / unsaved changes for setting arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
supermerill committed Aug 31, 2022
1 parent 8e8875a commit 3f8fcdf
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 33 deletions.
4 changes: 2 additions & 2 deletions src/slic3r/GUI/OptionsGroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -628,10 +628,10 @@ Option ConfigOptionsGroup::get_option(const std::string& opt_key, int opt_index
return Option(*m_config->def()->get(opt_key), opt_id);
}

void ConfigOptionsGroup::register_to_search(const std::string& opt_key, const ConfigOptionDef& option_def, int opt_index /*= -1*/)
void ConfigOptionsGroup::register_to_search(const std::string& opt_key, const ConfigOptionDef& option_def, int opt_index /*= -1*/, bool reset)
{ // fill group and category values just for options from Settings Tab
std::string opt_id = opt_index == -1 ? opt_key : opt_key + "#" + std::to_string(opt_index);
wxGetApp().sidebar().get_searcher().add_key(opt_id, static_cast<Preset::Type>(this->config_type()), this->title, this->config_category(), option_def);
wxGetApp().sidebar().get_searcher().add_key(opt_id, static_cast<Preset::Type>(this->config_type()), this->title, this->config_category(), option_def, reset);
}


Expand Down
4 changes: 2 additions & 2 deletions src/slic3r/GUI/OptionsGroup.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,11 @@ class ConfigOptionsGroup: public OptionsGroup {
bool has_option(const std::string& opt_key, int opt_index = -1);
// more like "create option from def"
Option get_option(const std::string& opt_key, int opt_index = -1);
void register_to_search(const std::string& opt_key, const ConfigOptionDef& option_def, int opt_index = -1);
void register_to_search(const std::string& opt_key, const ConfigOptionDef& option_def, int opt_index, bool reset);
Option get_option_and_register(const std::string& opt_key, int opt_index = -1) {
Option opt = get_option(opt_key, opt_index);
if(m_use_custom_ctrl) // fill group and category values just for options from Settings Tab
register_to_search(opt_key, opt.opt, opt_index);
register_to_search(opt_key, opt.opt, opt_index, true);
return opt;
}
Line create_single_option_line(const std::string& title, const std::string& path = std::string(), int idx = -1) /*const*/{
Expand Down
2 changes: 1 addition & 1 deletion src/slic3r/GUI/Plater.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1135,7 +1135,7 @@ void Sidebar::jump_to_option(size_t selected)
}
}

wxGetApp().get_tab(opt.type)->activate_option(opt.opt_key(), boost::nowide::narrow(opt.category));
wxGetApp().get_tab(opt.type)->activate_option(opt.opt_key_with_idx(), boost::nowide::narrow(opt.category));

// Switch to the Settings NotePad
// wxGetApp().mainframe->select_tab(MainFrame::ETabType::LastSettings);
Expand Down
71 changes: 50 additions & 21 deletions src/slic3r/GUI/Search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,13 @@ static char marker_by_type(Preset::Type type, PrinterTechnology pt)
}
}

std::string Option::opt_key() const
std::string Option::opt_key_with_idx() const
{
return boost::nowide::narrow(key);
std::string str = boost::nowide::narrow(key);
if (idx >= 0) {
str += "#" + std::to_string(idx);
}
return str;
}

void FoundOption::get_marked_label_and_tooltip(const char** label_, const char** tooltip_) const
Expand All @@ -74,20 +78,19 @@ void change_opt_key(std::string& opt_key, DynamicPrintConfig* config, int& cnt)
opt_key += "#" + std::to_string(0);
}

static Option create_option(const std::string& opt_key, Preset::Type type, const GroupAndCategory& gc)
static Option create_option(const std::string& opt_key, const int16_t opt_idx, Preset::Type type, const GroupAndCategory& gc)
{
wxString suffix;
wxString suffix_local;
if (gc.category == "Machine limits") {
suffix = opt_key.back() == '1' ? L("Stealth") : L("Normal");
suffix = opt_idx == 1 ? L("Stealth") : L("Normal");
suffix_local = " " + _(suffix);
suffix = " " + suffix;
}

wxString category = gc.category;
if (type == Preset::TYPE_PRINTER && category.Contains("Extruder ")) {
std::string opt_idx = opt_key.substr(opt_key.find("#") + 1);
category = wxString::Format("%s %d", "Extruder", atoi(opt_idx.c_str()) + 1);
category = wxString::Format("%s %d", "Extruder", opt_idx + 1);
}

const ConfigOptionDef& opt = gc.gui_opt;
Expand All @@ -108,7 +111,7 @@ static Option create_option(const std::string& opt_key, Preset::Type type, const
}

if (!label.IsEmpty())
return Option{ boost::nowide::widen(opt.opt_key), type, opt.mode,
return Option{ boost::nowide::widen(opt.opt_key), type, opt_idx, opt.mode,
(label + suffix).ToStdWstring(), (local_label + suffix_local).ToStdWstring(),
gc.group.ToStdWstring(), _(gc.group).ToStdWstring(),
category.ToStdWstring(), GUI::Tab::translate_category(category, type).ToStdWstring() ,
Expand Down Expand Up @@ -148,15 +151,15 @@ const GroupAndCategory& OptionsSearcher::get_group_and_category(const std::strin
void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type type)
{
const ConfigDef* defs = config->def();
auto emplace = [this, type](const std::string grp_key)
auto emplace_option = [this, type](const std::string grp_key, const int16_t idx)
{
for (const GroupAndCategory& gc : groups_and_categories[grp_key]) {
if (gc.group.IsEmpty() || gc.category.IsEmpty())
return;

Option option = create_option(gc.gui_opt.opt_key, type, gc);
Option option = create_option(gc.gui_opt.opt_key, idx, type, gc);
if (!option.label.empty()) {
options.emplace_back(option);
options.push_back(std::move(option));
}

//wxString suffix;
Expand Down Expand Up @@ -214,11 +217,11 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty
//}

if (cnt == 0)
emplace(key);
emplace_option(key, -1);
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(key + "#" + std::to_string(i));
emplace_option(key + "#" + std::to_string(i), i);
}
}

Expand Down Expand Up @@ -503,19 +506,41 @@ const Option& OptionsSearcher::get_option(size_t pos_in_filter) 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), type }));
assert(it != options.end());
int16_t idx = -1;
size_t pos_hash = opt_key.find('#');
if (pos_hash == std::string::npos) {
auto it = std::lower_bound(options.begin(), options.end(), Option({ boost::nowide::widen(opt_key), type, idx }));
assert(it != options.end());
return options[it - options.begin()];
} else {
std::string raw_opt_key = opt_key.substr(0, pos_hash);
std::string opt_idx = opt_key.substr(pos_hash + 1);
idx = atoi(opt_idx.c_str());
auto it = std::lower_bound(options.begin(), options.end(), Option({ boost::nowide::widen(raw_opt_key), type, idx }));
assert(it != options.end());
return options[it - options.begin()];
}

return options[it - options.begin()];
}

Option OptionsSearcher::get_option_names(const std::string& opt_key, Preset::Type type) const
{
auto it = std::lower_bound(options.begin(), options.end(), Option({ boost::nowide::widen(opt_key), type }));
if (it != options.end() && it->key == boost::nowide::widen(opt_key))
int16_t idx = -1;
size_t pos_hash = opt_key.find('#');
std::vector<Search::Option>::const_iterator it;
if (pos_hash == std::string::npos) {
it = std::lower_bound(options.begin(), options.end(), Option({ boost::nowide::widen(opt_key), type, idx }));
} else {
std::string raw_opt_key = opt_key.substr(0, pos_hash);
std::string opt_idx = opt_key.substr(pos_hash + 1);
idx = atoi(opt_idx.c_str());
it = std::lower_bound(options.begin(), options.end(), Option({ boost::nowide::widen(raw_opt_key), type, idx }));
}
if (it != options.end() && it->opt_key_with_idx() == opt_key)
return *it;
std::string key = get_key(opt_key, type);
if (it != options.end() && groups_and_categories.find(key) == groups_and_categories.end()) {
//TODO check why needed
size_t pos = key.find('#');
if (pos == std::string::npos)
return *it;
Expand All @@ -525,15 +550,15 @@ Option OptionsSearcher::get_option_names(const std::string& opt_key, Preset::Typ
if(groups_and_categories.find(zero_opt_key) == groups_and_categories.end())
return *it;

return create_option(opt_key, type, get_group_and_category(zero_opt_key, ConfigOptionMode::comNone));
return create_option(opt_key, idx, type, get_group_and_category(zero_opt_key, ConfigOptionMode::comNone));
}


const GroupAndCategory& gc = get_group_and_category(key, ConfigOptionMode::comNone);
if (gc.group.IsEmpty() || gc.category.IsEmpty())
return *it;

return create_option(opt_key, type, gc);
return create_option(opt_key, idx, type, gc);
}

void OptionsSearcher::show_dialog()
Expand Down Expand Up @@ -564,14 +589,18 @@ void OptionsSearcher::dlg_msw_rescale()
search_dialog->msw_rescale();
}

void OptionsSearcher::add_key(const std::string& opt_key, Preset::Type type, const wxString& group, const wxString& category, const ConfigOptionDef& gui_opt)
void OptionsSearcher::add_key(const std::string& opt_key, Preset::Type type, const wxString& group, const wxString& category, const ConfigOptionDef& gui_opt, bool reset)
{
std::string key = get_key(opt_key, type);
auto it = groups_and_categories.find(key);
if (it == groups_and_categories.end()) {
groups_and_categories[key] = { GroupAndCategory{group, category, gui_opt} };
} else {
it->second.push_back(GroupAndCategory{ group, category, gui_opt });
//remove all entry from old presets
if (reset)
it->second.clear();
//add new preset (multiple for tags)
it->second.push_back(GroupAndCategory{ group, category, gui_opt});
}
}

Expand Down
13 changes: 9 additions & 4 deletions src/slic3r/GUI/Search.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,19 @@ struct Option {
// bool operator<(const Option& other) const { return other.label > this->label; }
bool operator<(const Option& other) const {
if (this->type == other.type)
return this->key < other.key;
return this->type < other.type;
if (this->key == other.key)
return this->idx < other.idx;
else
return this->key < other.key;
else
return this->type < other.type;
}

// 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 key;
Preset::Type type {Preset::TYPE_INVALID};
int16_t idx;
ConfigOptionMode tags;
std::wstring label;
std::wstring label_local;
Expand All @@ -67,7 +72,7 @@ struct Option {
std::wstring tooltip_local;
std::wstring tooltip_lowercase;
std::wstring tooltip_local_lowercase;
std::string opt_key() const;
std::string opt_key_with_idx() const;
};

struct FoundOption {
Expand Down Expand Up @@ -131,7 +136,7 @@ class OptionsSearcher
bool search();
bool search(const std::string& search, bool force = false);

void add_key(const std::string& opt_key, Preset::Type type, const wxString& group, const wxString& category, const ConfigOptionDef& gui_opt);
void add_key(const std::string& opt_key, Preset::Type type, const wxString& group, const wxString& category, const ConfigOptionDef& gui_opt, bool reset = false);

size_t size() const { return found_size(); }

Expand Down
2 changes: 1 addition & 1 deletion src/slic3r/GUI/Tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2192,7 +2192,7 @@ std::vector<Slic3r::GUI::PageShp> Tab::create_pages(std::string setting_type_nam
}


current_group->register_to_search(option.opt.opt_key, option.opt, id);
current_group->register_to_search(option.opt.opt_key, option.opt, id, false);
//if (need_to_notified_search)
// Search::OptionsSearcher::register_label_override(option.opt.opt_key, option.opt.label, option.opt.full_label, option.opt.tooltip);

Expand Down
4 changes: 2 additions & 2 deletions src/slic3r/GUI/UnsavedChangesDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1309,7 +1309,7 @@ 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, type);
if (option.opt_key() != opt_key) {
if (option.opt_key_with_idx() != 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
Expand Down Expand Up @@ -1699,7 +1699,7 @@ void DiffPresetDialog::update_tree()
wxString right_val = get_string_value(opt_key, right_congig);

Search::Option option = searcher.get_option_names(opt_key/*, get_full_label(opt_key, left_config)*/, type);
if (option.opt_key() != opt_key) {
if (option.opt_key_with_idx() != 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.
Expand Down

0 comments on commit 3f8fcdf

Please sign in to comment.