I have QActions
added to a QToolBar
using addAction()
.
I want the toolbar button tooltips to show the shortcuts. e.g. Copy (Ctrl+C). Of course, i could statically set
action->setTooltip(QString("%1 (%2)").arg(action.toolTip(), action->shortcut().toString(QKeySequence::NativeText)));
However, this is quite cumbersome because there are lots of actions and the user can modify the shortcuts so that I would have to keep track of that and update accordingly. It would be much nicer if I could simply modify the QToolBar
tooltip behavior by subclassing QToolBar
similar to http://doc.qt.io/qt-5/qtwidgets-widgets-tooltips-example.html.
Unfortunately, it's not that simple. The tooltip is not generated by the QToolBar
itself, but apparently by a QToolButton
which is created internally when using addAction()
. So ideally I would inject my own subclass of QToolButton
. But that seems imposible because the actual instantiation of the toolbutton is done inside the private QToolBarLayout which I cannot access.
Any ideas how to solve this?
I've not been able to find a solution by subclassing QToolBar
or anything related. Therefore I have resorted to overwrite the tooltip of the QAction
. This is what it looks like in the end:
I've written functions to add/remove the shorcut information, so that the changes are reversible (e.g. required if the behavior should be switchable). If removal is not needed, addShortcutToToolTip()
can be simplified a bit.
/* guesses a descriptive text from a text suited for a menu entry
This is equivalent to QActions internal qt_strippedText()
*/
static QString strippedActionText(QString s) {
s.remove( QString::fromLatin1("...") );
for (int i = 0; i < s.size(); ++i) {
if (s.at(i) == QLatin1Char('&'))
s.remove(i, 1);
}
return s.trimmed();
}
/* Adds possible shortcut information to the tooltip of the action.
This provides consistent behavior both with default and custom tooltips
when used in combination with removeShortcutToToolTip()
*/
void addShortcutToToolTip(QAction *action)
{
if (!action->shortcut().isEmpty()) {
QString tooltip = action->property("tooltipBackup").toString();
if (tooltip.isEmpty()) {
tooltip = action->toolTip();
if (tooltip != strippedActionText(action->text())) {
action->setProperty("tooltipBackup", action->toolTip()); // action uses a custom tooltip. Backup so that we can restore it later.
}
}
QColor shortcutTextColor = QApplication::palette().color(QPalette::ToolTipText);
QString shortCutTextColorName;
if (shortcutTextColor.value() == 0) {
shortCutTextColorName = "gray"; // special handling for black because lighter() does not work there [QTBUG-9343].
} else {
int factor = (shortcutTextColor.value() < 128) ? 150 : 50;
shortCutTextColorName = shortcutTextColor.lighter(factor).name();
}
action->setToolTip(QString("<p style='white-space:pre'>%1 <code style='color:%2; font-size:small'>%3</code></p>")
.arg(tooltip, shortCutTextColorName, action->shortcut().toString(QKeySequence::NativeText)));
}
}
/* Removes possible shortcut information from the tooltip of the action.
This provides consistent behavior both with default and custom tooltips
when used in combination with addShortcutToToolTip()
*/
void removeShortcutFromToolTip(QAction *action)
{
action->setToolTip(action->property("tooltipBackup").toString());
action->setProperty("tooltipBackup", QVariant());
}