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 Updated to NodeBB v4.3 + New Features

How to render shortcut text in custom button?

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
10 Posts 4 Posters 848 Views 1 Watching
  • 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 3 Dec 2020, 22:37 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.

    M 1 Reply Last reply 4 Dec 2020, 11:38
    0
    • F Offline
      F Offline
      fcarney
      wrote on 3 Dec 2020, 23:29 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 4 Dec 2020, 02:08 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 4 Dec 2020, 09:32
        0
        • M mnesarco
          4 Dec 2020, 02:08

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

          B Offline
          B Offline
          Bob64
          wrote on 4 Dec 2020, 09:32 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 4 Dec 2020, 12:49
          0
          • M mnesarco
            3 Dec 2020, 22:37

            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.

            M Offline
            M Offline
            Markkyboy
            wrote on 4 Dec 2020, 11:38 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 4 Dec 2020, 12:47
            0
            • M Markkyboy
              4 Dec 2020, 11:38

              @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 4 Dec 2020, 12:47 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
                4 Dec 2020, 09:32

                @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 4 Dec 2020, 12:49 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 4 Dec 2020, 12:56 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
                  • F Offline
                    F Offline
                    fcarney
                    wrote on 4 Dec 2020, 17:53 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 7 Dec 2020, 13:58 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

                      2/10

                      3 Dec 2020, 23:29

                      topic:navigator.unread, 8
                      • Login

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