Skip to content

Commit

Permalink
Work for issue #114, adding automation key-name lookup to add key-nam…
Browse files Browse the repository at this point in the history
…e to tool-tips.
  • Loading branch information
ahlstromcj committed Aug 12, 2023
1 parent cef82bc commit e5c538c
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 16 deletions.
22 changes: 20 additions & 2 deletions libseq66/include/ctrl/keycontainer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* \library seq66 application
* \author Chris Ahlstrom
* \date 2018-11-18
* \updates 2023-04-12
* \updates 2023-08-12
* \license GNU GPLv2 or above
*
* This container holds a map of keycontrol objects keyed by a key ordinal
Expand Down Expand Up @@ -86,6 +86,14 @@ class keycontainer

using mutemap = std::map<int, std::string>;

/**
* An additional container to hold the automation numbers and the
* corresponding keystrokes to quickly look up the keystroke name based on
* the offset number.
*/

using automationmap = std::map<int, std::string>;

private:

/**
Expand Down Expand Up @@ -126,6 +134,13 @@ class keycontainer

mutemap m_mute_keys;

/**
* Reverse lookup map for automation number numbers. This map is useful
* in showing the keystroke in a tool-tip as per issue #114.
*/

automationmap m_automation_keys;

/**
* Indicates if the key values were loaded from an "rc" configuration
* file, as opposed to using the default values of the keys.
Expand Down Expand Up @@ -169,6 +184,7 @@ class keycontainer
m_container.clear();
m_pattern_keys.clear();
m_mute_keys.clear();
m_automation_keys.clear();
}

int count () const
Expand All @@ -179,9 +195,11 @@ class keycontainer
bool add (ctrlkey ordinal, const keycontrol & kc);
bool add_slot (const keycontrol & kc);
bool add_mute (const keycontrol & kc);
bool add_automation (const keycontrol & kc);
const keycontrol & control (ctrlkey ordinal) const;
std::string slot_key (int pattern_offset) const;
std::string mute_key (int mute_offset) const;
std::string automation_key (int ctrlcode) const;
keystroke mute_keystroke (int mute_offset) const;

bool loaded_from_rc () const
Expand Down Expand Up @@ -224,7 +242,7 @@ class keycontainer

void show () const;

static const std::string & automation_key_name (int index);
static const std::string & automation_default_key_name (int index);

private:

Expand Down
19 changes: 16 additions & 3 deletions libseq66/src/cfg/midicontrolfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* \library seq66 application
* \author Chris Ahlstrom
* \date 2018-11-13
* \updates 2023-05-11
* \updates 2023-08-12
* \license GNU GPLv2 or above
*
* This class handles the 'ctrl' file.
Expand Down Expand Up @@ -1256,7 +1256,7 @@ midicontrolfile::parse_control_stanza (automation::category opcat, int index)
}
else
{
keyname = keycontainer::automation_key_name(index);
keyname = keycontainer::automation_default_key_name(index);
ok = ! keyname.empty();
}
if (ok)
Expand All @@ -1269,6 +1269,13 @@ midicontrolfile::parse_control_stanza (automation::category opcat, int index)
else if (opcat == automation::category::automation)
opslot = opcontrol::set_slot(index);

#if defined SEQ66_PLATFORM_DEBUG_TMI
if (opcat == automation::category::automation)
{
printf("Key %d = '%s'\n", index, keyname.c_str());
}
#endif

/*
* Create control objects, whether active or not. We want to
* save all objects in the file, to avoid altering the user's
Expand Down Expand Up @@ -1312,15 +1319,21 @@ midicontrolfile::parse_control_stanza (automation::category opcat, int index)
"", keyname, opcat, automation::action::toggle, opslot, index
);
ctrlkey ordinal = qt_keyname_ordinal(keyname);
if (! is_invalid_ordinal(ordinal)) /* ca 2021-12-31 */
if (! is_invalid_ordinal(ordinal))
{
bool ok = m_temp_key_controls.add(ordinal, kc);
if (ok)
{
/*
* We now add automation codes for issue #114.
*/

if (opcat == automation::category::loop)
ok = m_temp_key_controls.add_slot(kc);
else if (opcat == automation::category::mute_group)
ok = m_temp_key_controls.add_mute(kc);
else if (opcat == automation::category::automation)
ok = m_temp_key_controls.add_automation(kc);
}
if (! ok)
(void) keycontrol_error_message(kc, ordinal, line_number());
Expand Down
76 changes: 68 additions & 8 deletions libseq66/src/ctrl/keycontainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* \library seq66 application
* \author Chris Ahlstrom
* \date 2018-11-18
* \updates 2023-04-26
* \updates 2023-08-12
* \license GNU GPLv2 or above
*
*/
Expand Down Expand Up @@ -53,6 +53,7 @@ keycontainer::keycontainer () :
m_container_name ("Default keys"),
m_pattern_keys (),
m_mute_keys (),
m_automation_keys (),
m_loaded_from_rc (false),
m_use_auto_shift (true),
m_kbd_layout (keyboard::layout::qwerty),
Expand All @@ -74,6 +75,7 @@ keycontainer::keycontainer (const std::string & name) :
m_container_name (name),
m_pattern_keys (),
m_mute_keys (),
m_automation_keys (),
m_loaded_from_rc (false),
m_use_auto_shift (true),
m_kbd_layout (keyboard::layout::qwerty),
Expand Down Expand Up @@ -153,10 +155,9 @@ keycontainer::add_slot (const keycontrol & op)
bool result = false;
int keyslot = op.control_code(); /* pattern offset */
std::string keyname = op.key_name();
auto sz = m_pattern_keys.size();
auto p = std::make_pair(keyslot, keyname);
(void) m_pattern_keys.insert(p);
result = m_pattern_keys.size() == (sz + 1);
auto r = m_pattern_keys.insert(p);
result = r.second;
if (result)
{
/* no code needed */
Expand Down Expand Up @@ -191,10 +192,36 @@ keycontainer::add_mute (const keycontrol & op)
bool result = false;
int keyslot = op.control_code(); /* pattern offset */
std::string keyname = op.key_name();
auto sz = m_mute_keys.size();
auto p = std::make_pair(keyslot, keyname);
(void) m_mute_keys.insert(p);
result = m_mute_keys.size() == (sz + 1);
auto r = m_mute_keys.insert(p);
result = r.second;
if (result)
{
/* no code needed */
}
else
{
std::cerr
<< "Duplicate mute slot #" << std::setw(3) << keyslot
<< " : '" << keyname << "'" << std::endl
;
}
return result;
}

/**
* Function added for issue #114.
*/

bool
keycontainer::add_automation (const keycontrol & op)
{
bool result = false;
int keyslot = op.control_code(); /* pattern offset */
std::string keyname = op.key_name();
auto p = std::make_pair(keyslot, keyname);
auto r = m_automation_keys.insert(p);
result = r.second;
if (result)
{
/* no code needed */
Expand Down Expand Up @@ -276,6 +303,31 @@ keycontainer::mute_key (int mute_offset) const
return result;
}

/**
* Function added for issue #114.
* Similar to slot_key().
*/

std::string
keycontainer::automation_key (int ctrlcode) const
{
std::string result;
auto p = m_automation_keys.find(ctrlcode);
if (p != m_automation_keys.end())
{
result = p->second;
if (result[0] == '0' && result[1] == 'x')
{
char ch = char(std::stoi(result, nullptr, 0));
result = ch;
}
}
else
result = "?";

return result;
}

/**
* This function was added in order to be able to get the keystroke from
* the mute-group in order to try to display that the mute-group learn worked
Expand Down Expand Up @@ -361,8 +413,13 @@ keycontainer::kbd_layout_to_string (keyboard::layout lay)
return result;
}

/**
* Static function to look up the default name of a key based on
* its index (actually a ctrlkey value).
*/

const std::string &
keycontainer::automation_key_name (int index)
keycontainer::automation_default_key_name (int index)
{
static std::string s_dummy;
const defaults & keylist = keys_automation();
Expand Down Expand Up @@ -609,6 +666,9 @@ keycontainer::add_defaults ()
keycontrol kc(nametag, keyname, c, a, s, auslot);
if (! add(ordinal, kc))
break;

if (! add_automation(kc)) /* provides mute number */
break;
}
}
m_defaults_loaded = true;
Expand Down
8 changes: 7 additions & 1 deletion seq_qt5/include/qt5_helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* \library seq66 application
* \author Chris Ahlstrom
* \date 2018-03-14
* \updates 2023-07-09
* \updates 2023-08-12
* \license GNU GPLv2 or above
*
*/
Expand Down Expand Up @@ -141,6 +141,12 @@ extern bool show_folder_dialog
const std::string & prompt = "",
bool forcehome = false
);
extern void tooltip_with_keystroke
(
QWidget * widget,
const std::string & keyname,
int duration = -1
);

} // namespace seq66

Expand Down
11 changes: 10 additions & 1 deletion seq_qt5/src/qsmainwnd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* \library seq66 application
* \author Chris Ahlstrom
* \date 2018-01-01
* \updates 2023-07-17
* \updates 2023-08-12
* \license GNU GPLv2 or above
*
* The main window is known as the "Patterns window" or "Patterns panel". It
Expand Down Expand Up @@ -576,6 +576,15 @@ qsmainwnd::qsmainwnd
connect(ui->btnPlay, SIGNAL(clicked(bool)), this, SLOT(start_playing()));
qt_set_icon(play2_xpm, ui->btnPlay);

/*
* Adding support bit by bit for showing the automation key in the
* tool-tips where applicable. Per issue #114.
*/

int index = slot_to_int_cast(automation::slot::start); // vs playback
std::string keyname = rc().key_controls().automation_key(index);
(void) tooltip_with_keystroke(ui->btnPlay, keyname);

/*
* L/R Loop button (and Text Underrun button hiding).
*/
Expand Down
48 changes: 47 additions & 1 deletion seq_qt5/src/qt5_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* \library seq66 application
* \author Chris Ahlstrom
* \date 2018-03-14
* \updates 2023-07-09
* \updates 2023-08-12
* \license GNU GPLv2 or above
*
* The items provided externally are:
Expand Down Expand Up @@ -739,6 +739,52 @@ show_folder_dialog
return result;
}

/**
* For issue #114, we want to append the keystroke as configured to the
* tool-tip.
*
* \param widget
* The QWidget whose tool-tip we want to modify.
*
* \param keyname
* The name of the key as provided by the caller. (We could change
* this parameter to an automation action that can be looked up here
* instead.)
*
* \param duration
* Provides the tool-tip duration in milliseconds. If -1 (the default),
* then duration depends on the length of the tool-tip (and this is still
* a bit too short.
*/

void
tooltip_with_keystroke
(
QWidget * widget,
const std::string & keyname,
int duration
)
{
if (! keyname.empty())
{
QString qtip = widget->toolTip();
std::string tip = qtip.toStdString();
if (tip.empty())
{
tip = "Key " + keyname;
}
else
{
tip += " [";
tip += keyname;
tip += "]";
}
qtip = qt(tip);
widget->setToolTip(qtip);
widget->setToolTipDuration(duration);
}
}

} // namespace seq66

/*
Expand Down

0 comments on commit e5c538c

Please sign in to comment.