mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-12 02:11:39 +00:00
Support searching the Speed Dial by English names in any UI language (#16369)
This commit is contained in:
@@ -4,16 +4,23 @@
|
||||
|
||||
#include <catch2/catch_message.hpp>
|
||||
#include "slic3r/GUI/ActionRegistry.hpp"
|
||||
#include "slic3r/GUI/GUI_Factories.hpp"
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
#include "slic3r/GUI/NativeCommands.hpp"
|
||||
#include "slic3r/GUI/OptionsGroup.hpp"
|
||||
#include "slic3r/GUI/SettingsIndex.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include "libslic3r/Config.hpp"
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using Slic3r::GUI::AppAction;
|
||||
@@ -27,7 +34,9 @@ namespace {
|
||||
class TestAppAction final : public AppAction
|
||||
{
|
||||
public:
|
||||
TestAppAction() : AppAction("test", "Action title", "src-key", "Action source") {}
|
||||
explicit TestAppAction(std::string title = "Action title", std::string source_name = "Action source")
|
||||
: AppAction("test", std::move(title), "src-key", std::move(source_name))
|
||||
{}
|
||||
|
||||
AppActionRunResult run(const std::string& param = {}) const override { return {}; }
|
||||
};
|
||||
@@ -93,7 +102,9 @@ TEST_CASE("Command actions are keyed by catalog key, not display title", "[Actio
|
||||
}
|
||||
|
||||
// The real catalog -> action mapping keys by the stable catalog key and copies presentation from the
|
||||
// catalog, so a rename or a UI-language switch never re-keys the action.
|
||||
// catalog, so a rename or a UI-language switch never re-keys the action. The catalog's English title
|
||||
// and group become the action's English search aliases; no translation catalog is loaded in the tests,
|
||||
// so the displayed title and group equal them.
|
||||
TEST_CASE("Command action construction keys by catalog key", "[ActionSource][SpeedDial]")
|
||||
{
|
||||
const std::vector<Slic3r::GUI::NativeCommand>& commands = Slic3r::GUI::NativeCommands::catalog();
|
||||
@@ -106,6 +117,8 @@ TEST_CASE("Command action construction keys by catalog key", "[ActionSource][Spe
|
||||
CHECK(action->id() != AppAction::compose_id("orca_command", c.title, "orca"));
|
||||
CHECK(action->title() == c.title);
|
||||
CHECK(action->group == c.group);
|
||||
CHECK(action->title_en == c.title);
|
||||
CHECK(action->group_en == c.group);
|
||||
CHECK(action->input == c.input);
|
||||
CHECK(action->icon == c.icon);
|
||||
}
|
||||
@@ -171,6 +184,7 @@ TEST_CASE("Native command catalog has unique keys and present titles", "[ActionS
|
||||
for (const auto& c : commands) {
|
||||
CHECK_FALSE(c.key.empty());
|
||||
CHECK_FALSE(c.title.empty());
|
||||
CHECK_FALSE(c.group.empty());
|
||||
// A duplicated key would silently shadow the earlier command in the palette.
|
||||
CHECK(seen.insert(c.key).second);
|
||||
}
|
||||
@@ -288,6 +302,16 @@ TEST_CASE("Native command catalog covers the Add menus", "[ActionSource][SpeedDi
|
||||
REQUIRE(group != nullptr);
|
||||
CHECK(*group == *handy_group);
|
||||
}
|
||||
|
||||
// A handy model's command is titled by the English label its Add-menu entry is built from, so it is
|
||||
// searchable in English in any UI language.
|
||||
for (const auto& model : Slic3r::GUI::MenuFactory::handy_models()) {
|
||||
const std::string key = "add_handy_" + std::string(model.key);
|
||||
INFO(key);
|
||||
const auto it = std::find_if(commands.begin(), commands.end(), [&key](const auto& c) { return c.key == key; });
|
||||
REQUIRE(it != commands.end());
|
||||
CHECK(it->title == model.label);
|
||||
}
|
||||
}
|
||||
|
||||
// A setting action is named like its settings row, not the ConfigOptionDef label: the row's
|
||||
@@ -319,6 +343,61 @@ TEST_CASE("Setting display labels mirror the settings row", "[ActionSource][Spee
|
||||
CHECK(resolve_setting_title(L"", L"", false).IsEmpty());
|
||||
}
|
||||
|
||||
// The page receives an English alias only where it differs from the displayed text, so an English UI
|
||||
// (where every alias equals its text) receives none and searches exactly the displayed text.
|
||||
TEST_CASE("Action JSON sends English aliases only when they differ from the displayed text", "[ActionSource][SpeedDial]")
|
||||
{
|
||||
const char* aliases[] = {"title_en", "group_en", "source_en", "full_label_en"};
|
||||
|
||||
TestAppAction english("Reverse on even", "Process : Quality : Overhangs");
|
||||
english.full_label = "Overhang reversal";
|
||||
english.title_en = english.title();
|
||||
english.source_en = english.source_name();
|
||||
english.full_label_en = english.full_label;
|
||||
const nlohmann::json same = Slic3r::GUI::action_json(english);
|
||||
for (const char* key : aliases) {
|
||||
INFO(key);
|
||||
CHECK_FALSE(same.contains(key));
|
||||
}
|
||||
CHECK(same.at("title") == "Reverse on even");
|
||||
|
||||
// A translated action (German stands in for any UI language) carries each differing English name.
|
||||
TestAppAction localized("Bei geraden Schichten umkehren", "Prozess : Qualitaet : Ueberhaenge");
|
||||
localized.group = "Befehle";
|
||||
localized.full_label = "Ueberhangumkehr";
|
||||
localized.title_en = "Reverse on even";
|
||||
localized.group_en = "Commands";
|
||||
localized.source_en = "Process : Quality : Overhangs";
|
||||
localized.full_label_en = "Overhang reversal";
|
||||
const nlohmann::json differs = Slic3r::GUI::action_json(localized);
|
||||
CHECK(differs.at("title_en") == "Reverse on even");
|
||||
CHECK(differs.at("group_en") == "Commands");
|
||||
CHECK(differs.at("source_en") == "Process : Quality : Overhangs");
|
||||
CHECK(differs.at("full_label_en") == "Overhang reversal");
|
||||
CHECK(differs.at("title") == "Bei geraden Schichten umkehren");
|
||||
|
||||
// No English counterpart (a plugin, a file name) sends nothing.
|
||||
const nlohmann::json none = Slic3r::GUI::action_json(TestAppAction("Optimize", "Gcode Optimizer"));
|
||||
for (const char* key : aliases) {
|
||||
INFO(key);
|
||||
CHECK_FALSE(none.contains(key));
|
||||
}
|
||||
}
|
||||
|
||||
// A settings row keeps the untranslated English of its label, from the ctor and from a runtime
|
||||
// rename, so the Speed Dial can offer the row's English name in any UI language. No catalog is loaded
|
||||
// in the tests, so the displayed label equals the English.
|
||||
TEST_CASE("Settings rows keep the English of their label", "[ActionSource][SpeedDial]")
|
||||
{
|
||||
Slic3r::GUI::Line line{L("Cool Plate"), ""};
|
||||
CHECK(line.label_en == "Cool Plate");
|
||||
CHECK(line.label == "Cool Plate");
|
||||
|
||||
line.set_label(L("Brim ear radius"));
|
||||
CHECK(line.label_en == "Brim ear radius");
|
||||
CHECK(line.label == "Brim ear radius");
|
||||
}
|
||||
|
||||
// A setting whose mode is above the user's current mode must be prompted before it can be edited.
|
||||
// Developer settings (comDevelop) are above every non-developer mode, so they always prompt then.
|
||||
TEST_CASE("Settings above the current mode require a switch", "[ActionSource][SpeedDial]")
|
||||
|
||||
Reference in New Issue
Block a user