key bindings and menu items visibility string packing/unpacking for scripts

New convenience functions are provided which simplify
manipulation of key bindings and menu item visibility
configuration strings. AbstractMenu#pack_key_binding
and AbstractMenu#unpack_key_binding turn a path/key
map into a single string and back. The string format
is the same than for the key-binding configuration key.

The same is provided for the menu item visibilily
with AbstractMenu#pack_menu_item_visible and
Abstract#unpack_menu_item_visible.
This commit is contained in:
Matthias Koefferlein 2019-08-17 19:54:03 +02:00
parent 7b163728ab
commit 9c3f70342b
6 changed files with 180 additions and 94 deletions

View File

@ -326,76 +326,6 @@ MainConfigPage5::commit (lay::PluginRoot *root)
// ------------------------------------------------------------
// The "key bindings" config page
std::vector<std::pair<std::string, std::string> >
unpack_key_binding (const std::string &packed)
{
tl::Extractor ex (packed.c_str ());
std::vector<std::pair<std::string, std::string> > key_bindings;
while (! ex.at_end ()) {
ex.test(";");
key_bindings.push_back (std::make_pair (std::string (), std::string ()));
ex.read_word_or_quoted (key_bindings.back ().first);
ex.test(":");
ex.read_word_or_quoted (key_bindings.back ().second);
}
return key_bindings;
}
std::string
pack_key_binding (const std::vector<std::pair<std::string, std::string> > &unpacked)
{
std::string packed;
for (std::vector<std::pair<std::string, std::string> >::const_iterator p = unpacked.begin (); p != unpacked.end (); ++p) {
if (! packed.empty ()) {
packed += ";";
}
packed += tl::to_word_or_quoted_string (p->first);
packed += ":";
packed += tl::to_word_or_quoted_string (p->second);
}
return packed;
}
std::vector<std::pair<std::string, bool> >
unpack_menu_items_hidden (const std::string &packed)
{
tl::Extractor ex (packed.c_str ());
std::vector<std::pair<std::string, bool> > hidden;
while (! ex.at_end ()) {
ex.test(";");
hidden.push_back (std::make_pair (std::string (), false));
ex.read_word_or_quoted (hidden.back ().first);
ex.test(":");
ex.read (hidden.back ().second);
}
return hidden;
}
std::string
pack_menu_items_hidden (const std::vector<std::pair<std::string, bool> > &unpacked)
{
std::string packed;
for (std::vector<std::pair<std::string, bool> >::const_iterator p = unpacked.begin (); p != unpacked.end (); ++p) {
if (! packed.empty ()) {
packed += ";";
}
packed += tl::to_word_or_quoted_string (p->first);
packed += ":";
packed += tl::to_string (p->second);
}
return packed;
}
CustomizeMenuConfigPage::CustomizeMenuConfigPage (QWidget *parent)
: lay::ConfigPage (parent), m_enable_event (true)
{

View File

@ -48,27 +48,6 @@ class QAction;
namespace lay
{
/**
* @brief A utility function to convert the packed key binding in the cfg_key_bindings string to a vector
*/
std::vector<std::pair<std::string, std::string> > unpack_key_binding (const std::string &packed);
/**
* @brief A utility function to convert the key binding (as path/shortcut pair vector) to a packed string for cfg_key_bindings
*/
std::string pack_key_binding (const std::vector<std::pair<std::string, std::string> > &unpacked);
/**
* @brief A utility function to convert the packed hidden flags in the cfg_menu_items_hidden string to a vector
*/
std::vector<std::pair<std::string, bool> > unpack_menu_items_hidden (const std::string &packed);
/**
* @brief A utility function to convert the hidde flags (as path/bool pair vector) to a packed string for cfg_menu_items_hidden
*/
std::string pack_menu_items_hidden (const std::vector<std::pair<std::string, bool> > &unpacked);
class ColorButton;
class MainConfigPage

View File

@ -28,7 +28,65 @@
namespace gsi
{
static std::string pack_key_binding (const std::map<std::string, std::string> &kb)
{
std::vector<std::pair<std::string, std::string> > v;
v.insert (v.end (), kb.begin (), kb.end ());
return lay::pack_key_binding (v);
}
static std::map<std::string, std::string> unpack_key_binding (const std::string &s)
{
std::vector<std::pair<std::string, std::string> > v = lay::unpack_key_binding (s);
std::map<std::string, std::string> kb;
kb.insert (v.begin (), v.end ());
return kb;
}
static std::string pack_menu_items_hidden (const std::map<std::string, bool> &kb)
{
std::vector<std::pair<std::string, bool> > v;
v.insert (v.end (), kb.begin (), kb.end ());
return lay::pack_menu_items_hidden (v);
}
static std::map<std::string, bool> unpack_menu_items_hidden (const std::string &s)
{
std::vector<std::pair<std::string, bool> > v = lay::unpack_menu_items_hidden (s);
std::map<std::string, bool> kb;
kb.insert (v.begin (), v.end ());
return kb;
}
Class<lay::AbstractMenu> decl_AbstractMenu ("lay", "AbstractMenu",
method ("pack_key_binding", &pack_key_binding, gsi::arg ("path_to_keys"),
"@brief Serializes a key binding definition into a single string\n"
"The serialized format is used by the 'key-bindings' config key. "
"This method will take an array of path/key definitions (including the \\Action#NoKeyBound option) "
"and convert it to a single string suitable for assigning to the config key.\n"
"\n"
"This method has been introduced in version 0.26."
) +
method ("unpack_key_binding", &unpack_key_binding, gsi::arg ("s"),
"@brief Deserializes a key binding definition\n"
"This method is the reverse of \\pack_key_binding.\n"
"\n"
"This method has been introduced in version 0.26."
) +
method ("pack_menu_items_hidden", &pack_menu_items_hidden, gsi::arg ("path_to_visibility"),
"@brief Serializes a menu item visibility definition into a single string\n"
"The serialized format is used by the 'menu-items-hidden' config key. "
"This method will take an array of path/visibility flag definitions "
"and convert it to a single string suitable for assigning to the config key.\n"
"\n"
"This method has been introduced in version 0.26."
) +
method ("unpack_menu_items_hidden", &unpack_menu_items_hidden, gsi::arg ("s"),
"@brief Deserializes a menu item visibility definition\n"
"This method is the reverse of \\pack_menu_items_hidden.\n"
"\n"
"This method has been introduced in version 0.26."
) +
method ("action", &lay::AbstractMenu::action,
"@brief Get the reference to a Action object associated with the given path\n"
"@args path\n"
@ -158,13 +216,13 @@ Class<lay::Action> decl_ActionBase ("lay", "ActionBase",
"@brief Sets the keyboard shortcut\n"
"@args shortcut\n"
"If the shortcut string is empty, the default shortcut will be used. If the string "
"is equal to \\Action#NoShortCut, no keyboard shortcut will be assigned.\n"
"is equal to \\Action#NoKeyBound, no keyboard shortcut will be assigned.\n"
"\n"
"@param shortcut The keyboard shortcut in Qt notation (i.e. \"Ctrl+C\")\n"
"\n"
"The NoShortCut option has been added in version 0.26."
"The NoKeyBound option has been added in version 0.26."
) +
constant ("NoShortCut", &lay::Action::no_shortcut,
constant ("NoKeyBound", &lay::Action::no_shortcut,
"@brief Gets a shortcut value indicating that no shortcut shall be assigned\n"
"This method has been introduced in version 0.26."
) +

View File

@ -65,6 +65,79 @@ static const bool s_can_move_menu = true;
#endif
// ---------------------------------------------------------------
// Serialization of key bindings and hidden menu state
std::vector<std::pair<std::string, std::string> >
unpack_key_binding (const std::string &packed)
{
tl::Extractor ex (packed.c_str ());
std::vector<std::pair<std::string, std::string> > key_bindings;
while (! ex.at_end ()) {
ex.test(";");
key_bindings.push_back (std::make_pair (std::string (), std::string ()));
ex.read_word_or_quoted (key_bindings.back ().first);
ex.test(":");
ex.read_word_or_quoted (key_bindings.back ().second);
}
return key_bindings;
}
std::string
pack_key_binding (const std::vector<std::pair<std::string, std::string> > &unpacked)
{
std::string packed;
for (std::vector<std::pair<std::string, std::string> >::const_iterator p = unpacked.begin (); p != unpacked.end (); ++p) {
if (! packed.empty ()) {
packed += ";";
}
packed += tl::to_word_or_quoted_string (p->first);
packed += ":";
packed += tl::to_word_or_quoted_string (p->second);
}
return packed;
}
std::vector<std::pair<std::string, bool> >
unpack_menu_items_hidden (const std::string &packed)
{
tl::Extractor ex (packed.c_str ());
std::vector<std::pair<std::string, bool> > hidden;
while (! ex.at_end ()) {
ex.test(";");
hidden.push_back (std::make_pair (std::string (), false));
ex.read_word_or_quoted (hidden.back ().first);
ex.test(":");
ex.read (hidden.back ().second);
}
return hidden;
}
std::string
pack_menu_items_hidden (const std::vector<std::pair<std::string, bool> > &unpacked)
{
std::string packed;
for (std::vector<std::pair<std::string, bool> >::const_iterator p = unpacked.begin (); p != unpacked.end (); ++p) {
if (! packed.empty ()) {
packed += ";";
}
packed += tl::to_word_or_quoted_string (p->first);
packed += ":";
packed += tl::to_string (p->second);
}
return packed;
}
// ---------------------------------------------------------------
// Helper function to parse a title with potential shortcut and
// icon specification

View File

@ -55,6 +55,26 @@ class Action;
class AbstractMenu;
class PluginRoot;
/**
* @brief A utility function to convert the packed key binding in the cfg_key_bindings string to a vector
*/
LAYBASIC_PUBLIC std::vector<std::pair<std::string, std::string> > unpack_key_binding (const std::string &packed);
/**
* @brief A utility function to convert the key binding (as path/shortcut pair vector) to a packed string for cfg_key_bindings
*/
LAYBASIC_PUBLIC std::string pack_key_binding (const std::vector<std::pair<std::string, std::string> > &unpacked);
/**
* @brief A utility function to convert the packed hidden flags in the cfg_menu_items_hidden string to a vector
*/
LAYBASIC_PUBLIC std::vector<std::pair<std::string, bool> > unpack_menu_items_hidden (const std::string &packed);
/**
* @brief A utility function to convert the hidde flags (as path/bool pair vector) to a packed string for cfg_menu_items_hidden
*/
LAYBASIC_PUBLIC std::string pack_menu_items_hidden (const std::vector<std::pair<std::string, bool> > &unpacked);
/**
* @brief A helper class that does reference counting for the QAction object
*/

View File

@ -59,6 +59,12 @@ class LAYMenuTest_TestClass < TestBase
assert_equal(b.shortcut, "")
assert_equal(b.effective_shortcut, "X")
a.shortcut = RBA::Action::NoKeyBound
assert_equal(a.default_shortcut, "X")
assert_equal(a.shortcut, "none")
assert_equal(a.effective_shortcut, "")
a.shortcut = ""
assert_equal(a.is_visible?, true)
a.hidden = false
@ -319,6 +325,26 @@ RESULT
end
def test_3
map = RBA::AbstractMenu::unpack_key_binding("'path.a':X;'path.b':''")
assert_equal(map["path.a"], "X")
assert_equal(map["path.b"], "")
assert_equal(map["path.c"], nil)
map2 = RBA::AbstractMenu::unpack_key_binding(RBA::AbstractMenu::pack_key_binding(map))
assert_equal(map == map2, true)
map = RBA::AbstractMenu::unpack_menu_items_hidden("'path.a':true;'path.b':false")
assert_equal(map["path.a"], true)
assert_equal(map["path.b"], false)
assert_equal(map["path.c"], nil)
map2 = RBA::AbstractMenu::unpack_menu_items_hidden(RBA::AbstractMenu::pack_menu_items_hidden(map))
assert_equal(map == map2, true)
end
end
load("test_epilogue.rb")