Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. How to render shortcut text in custom button?
Forum Update on Monday, May 27th 2025

How to render shortcut text in custom button?

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
10 Posts 4 Posters 838 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    mnesarco
    wrote on last edited by
    #1

    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.

    MarkkyboyM 1 Reply Last reply
    0
    • fcarneyF Offline
      fcarneyF Offline
      fcarney
      wrote on last edited by
      #2

      You can use MenuItem:

      MenuItem {
              width: 100
              height: 30
              text: "&Start"
      }
      

      Docs say its a convenience item based upon AbstractButton.

      C++ is a perfectly valid school of magic.

      1 Reply Last reply
      0
      • M Offline
        M Offline
        mnesarco
        wrote on last edited by
        #3

        The whole point is not to use MenuItem, The idea is to create a custom Item.

        B 1 Reply Last reply
        0
        • M mnesarco

          The whole point is not to use MenuItem, The idea is to create a custom Item.

          B Offline
          B Offline
          Bob64
          wrote on last edited by
          #4

          @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) { ... }
                  }
          
          M 1 Reply Last reply
          0
          • M mnesarco

            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.

            MarkkyboyM Offline
            MarkkyboyM Offline
            Markkyboy
            wrote on last edited by
            #5

            @mnesarco - I copied your code and ran it but changed CustomButton to Button and it works, the 'S' is underlined

            button-text-underline-capital.JPG

            Don't just sit there standing around, pick up a shovel and sweep up!

            I live by the sea, not in it.

            M 1 Reply Last reply
            0
            • MarkkyboyM Markkyboy

              @mnesarco - I copied your code and ran it but changed CustomButton to Button and it works, the 'S' is underlined

              button-text-underline-capital.JPG

              M Offline
              M Offline
              mnesarco
              wrote on last edited by
              #6

              @Markkyboy this is funny, the Idea is to create a custom component not to use the builtin Button component that obviously works.

              1 Reply Last reply
              0
              • B Bob64

                @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) { ... }
                        }
                
                M Offline
                M Offline
                mnesarco
                wrote on last edited by
                #7

                @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.

                1 Reply Last reply
                0
                • M Offline
                  M Offline
                  mnesarco
                  wrote on last edited by
                  #8

                  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

                  1 Reply Last reply
                  0
                  • fcarneyF Offline
                    fcarneyF Offline
                    fcarney
                    wrote on last edited by
                    #9

                    @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.

                    C++ is a perfectly valid school of magic.

                    1 Reply Last reply
                    0
                    • M Offline
                      M Offline
                      mnesarco
                      wrote on last edited by
                      #10

                      Apparently there is no builtin solution for this. It must be done in application code. Do I have to mark this topic as Solved?

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved