Unsolved How to render shortcut text in custom button?
-
Hi Friends,
I am creating a custom Button that receives an Action, something like this:CustomButton { action: Action { icon.width: 24 icon.height: 24 icon.source: "/icons/save.svg" text: qsTr("&Save") onTriggered: { console.log("onTriggered"); } } }
In the custom button I have a Text Item with the action's text:
Text { height: root.action.icon.height text: root.action.text verticalAlignment: Text.AlignVCenter color: area.containsMouse ? palette.brightText : palette.highlightedText }
The problem is that the text is rendered as it is "&Save" and I need it to be rendered as "Save" with "S" underlined. As it is with builtin menus and buttons.
Does anyone knows how to do that?
Thanks.
-
You can use MenuItem:
MenuItem { width: 100 height: 30 text: "&Start" }
Docs say its a convenience item based upon AbstractButton.
-
The whole point is not to use MenuItem, The idea is to create a custom Item.
-
@mnesarco Could you add a bit of code in your custom button - specifically in the
Text
item - to parse the action text into a rich text string? So "&Save" would be transformed to "<b>S</b>ave".Text { height: root.action.icon.height text: transformText(root.action.text) ... def transformText(t) { ... } }
-
@mnesarco - I copied your code and ran it but changed CustomButton to Button and it works, the 'S' is underlined
-
@Markkyboy this is funny, the Idea is to create a custom component not to use the builtin Button component that obviously works.
-
@Bob64 That is what I do right now as a workaround. But I wonder if there is a way to do it calling some builtin functionality.
-
I have found this class in Qt sources: QQuickMnemonicLabel it has a function that translate the mnemonic text into the undelined version. But this class is private.
This is the whole class source:
#include "qquickmnemoniclabel_p.h" #include <QtQuick/private/qquicktext_p_p.h> QT_BEGIN_NAMESPACE QQuickMnemonicLabel::QQuickMnemonicLabel(QQuickItem *parent) : QQuickText(parent) { } QString QQuickMnemonicLabel::text() const { return m_fullText; } void QQuickMnemonicLabel::setText(const QString &text) { if (m_fullText == text) return; m_fullText = text; updateMnemonic(); } bool QQuickMnemonicLabel::isMnemonicVisible() const { return m_mnemonicVisible; } void QQuickMnemonicLabel::setMnemonicVisible(bool visible) { if (m_mnemonicVisible == visible) return; m_mnemonicVisible = visible; updateMnemonic(); if (isComponentComplete()) forceLayout(); } static QTextLayout::FormatRange underlineRange(int start, int length = 1) { QTextLayout::FormatRange range; range.start = start; range.length = length; range.format.setFontUnderline(true); return range; } // based on QPlatformTheme::removeMnemonics() void QQuickMnemonicLabel::updateMnemonic() { QString text(m_fullText.size(), QChar::Null); int idx = 0; int pos = 0; int len = m_fullText.length(); QList<QTextLayout::FormatRange> formats; while (len) { if (m_fullText.at(pos) == QLatin1Char('&') && (len == 1 || m_fullText.at(pos + 1) != QLatin1Char('&'))) { if (m_mnemonicVisible && (pos == 0 || m_fullText.at(pos - 1) != QLatin1Char('&'))) formats += underlineRange(pos); ++pos; --len; if (len == 0) break; } else if (m_fullText.at(pos) == QLatin1Char('(') && len >= 4 && m_fullText.at(pos + 1) == QLatin1Char('&') && m_fullText.at(pos + 2) != QLatin1Char('&') && m_fullText.at(pos + 3) == QLatin1Char(')')) { // a mnemonic with format "\s*(&X)" if (m_mnemonicVisible) { formats += underlineRange(pos + 1); } else { int n = 0; while (idx > n && text.at(idx - n - 1).isSpace()) ++n; idx -= n; pos += 4; len -= 4; continue; } } text[idx] = m_fullText.at(pos); ++pos; ++idx; --len; } text.truncate(idx); QQuickTextPrivate::get(this)->layout.setFormats(formats); QQuickText::setText(text); } QT_END_NAMESPACE
So, I am afraid that the javascript function solution is the only way to go, ugly but works. There is also a StackOverflow post about this: https://stackoverflow.com/questions/54736428/how-to-style-menubaritem-with-mnemonics-strings-in-qml
-
@mnesarco said in How to render shortcut text in custom button?:
This is the whole class source:
That does replace the text, but I don't see it generating a keyboard action. I would have thought the default buttons actually generate a keyboard action shortcut.
-
Apparently there is no builtin solution for this. It must be done in application code. Do I have to mark this topic as Solved?