Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Porting QML emoji picker project to 100% C++ Widgets

Porting QML emoji picker project to 100% C++ Widgets

Scheduled Pinned Locked Moved Unsolved General and Desktop
8 Posts 5 Posters 439 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.
  • P Offline
    P Offline
    Pedro Vicente
    wrote on 23 Apr 2024, 01:01 last edited by
    #1

    I am interested in doing an "emoji picker" similar to the one shown in the image

    Untitled.png

    this is from an open source project

    https://github.com/AmirHosseinCH/EmojiPicker

    and the QML is simple as

    import QtQuick 2.15
    import QtQuick.Controls 2.5
    import QtQuick.Layouts 1.3
    import EmojiModel 1.0
    
    Item {
        id: container
        property var editor
        property EmojiModel model
        property var categories: ['Smileys & Emotion', 'People & Body', 'Animals & Nature',
            'Food & Drink', 'Activities', 'Travel & Places', 'Objects', 'Symbols', 'Flags']
        property var searchModel: ListModel {}
        property bool searchMode: false
        property int skinColor: -1
        function changeSkinColor(index) {
            if (index !== skinColors.current) {
                skinColors.itemAt(skinColors.current + 1).scale = 0.6
                skinColors.itemAt(index + 1).scale = 1
                skinColors.current = index
                container.skinColor = index
            }
        }
        function refreshSearchModel() {
            searchModel.clear()
            var searchResult = model.search(searchField.text, skinColor)
            for (var i = 0; i < searchResult.length; ++i) {
                searchModel.append({path: searchResult[i]})
            }
        }
        ColumnLayout {
            anchors.fill: parent
            RowLayout {
                id: categoriesRow
                Layout.preferredWidth: parent.width - 15
                Layout.preferredHeight: 35
                Layout.leftMargin: 5
                Layout.alignment: Qt.AlignCenter
                spacing: searchField.widthSize > 0 ? 7 : 17
                clip: true
                Image {
                    id: searchIcon
                    source: 'icons/search.svg'
                    sourceSize: Qt.size(21, 21)
                    visible: !container.searchMode
                    MouseArea {
                        anchors.fill: parent
                        cursorShape: Qt.PointingHandCursor
                        onClicked: {
                            container.searchMode = true
                            searchField.widthSize = categoriesRow.width - 25
                            list.model = 1
                            searchField.focus = true
                        }
                    }
                }
                Image {
                    id: closeIcon
                    source: 'icons/close.svg'
                    sourceSize: Qt.size(21, 21)
                    visible: container.searchMode
                    MouseArea {
                        anchors.fill: parent
                        cursorShape: Qt.PointingHandCursor
                        onClicked: {
                            container.searchMode = false
                            searchField.widthSize = 0
                            list.model = container.categories
                            searchField.clear()
                        }
                    }
                }
                TextField {
                    id: searchField
                    property int widthSize: 0
                    Layout.preferredWidth: widthSize
                    Layout.preferredHeight: 28
                    visible: widthSize > 0 ? true : false
                    placeholderText: 'Search Emoji'
                    Behavior on widthSize {
                        NumberAnimation {
                            duration: 400
                        }
                    }
                    background: Rectangle {
                        radius: 10
                        border.color: '#68c8ed'
                    }
                    onTextChanged: {
                        text.length > 0 ? container.refreshSearchModel() : container.searchModel.clear()
                    }
                }
                Repeater {
                    id: cateIcons
                    property var blackSvg: ['emoji-smiley.svg', 'emoji-people.svg', 'emoji-animal.svg', 'emoji-food.svg',
                        'emoji-activity.svg', 'emoji-travel.svg', 'emoji-object.svg', 'emoji-symbol.svg', 'emoji-flag.svg']
                    property var blueSvg: ['emoji-smiley-blue.svg', 'emoji-people-blue.svg', 'emoji-animal-blue.svg',
                        'emoji-food-blue.svg', 'emoji-activity-blue.svg', 'emoji-travel-blue.svg', 'emoji-object-blue.svg',
                        'emoji-symbol-blue.svg', 'emoji-flag-blue.svg']
                    property int current: 0
                    model: 9
                    delegate: Image {
                        id: icon
                        source: 'icons/' + cateIcons.blackSvg[index]
                        sourceSize: Qt.size(20, 20)
                        MouseArea {
                            anchors.fill: parent
                            cursorShape: Qt.PointingHandCursor
                            onClicked: {
                                if (cateIcons.current !== index) {
                                    icon.source = 'icons/' + cateIcons.blueSvg[index]
                                    cateIcons.itemAt(cateIcons.current).source = 'icons/' + cateIcons.blackSvg[cateIcons.current]
                                    cateIcons.current = index
                                }
                                list.positionViewAtIndex(index, ListView.Beginning)
                            }
                        }
                    }
                    Component.onCompleted: {
                        itemAt(0).source = 'icons/' + cateIcons.blueSvg[0]
                    }
                }
            }
            ListView {
                id: list
                Layout.fillWidth: true
                Layout.fillHeight: true
                model: container.categories
                spacing: 30
                topMargin: 7
                bottomMargin: 7
                leftMargin: 12
                clip: true
                delegate: GridLayout {
                    id: grid
                    property string category: container.searchMode ? 'Search Result' : modelData
                    property int columnCount: list.width / 50
                    property int sc: grid.category === 'People & Body' ? container.skinColor : -1
                    columns: columnCount
                    columnSpacing: 8
                    Text {
                        Layout.fillWidth: true
                        Layout.preferredHeight: 20
                        text: grid.category
                        color: Qt.rgba(0, 0, 0, 0.5)
                        font.pixelSize: 15
                        horizontalAlignment: Text.AlignLeft
                        leftPadding: 6
                        Layout.columnSpan: grid.columnCount != 0 ? grid.columnCount : 1
                        Layout.bottomMargin: 8
                    }
                    Repeater {
                        model: container.searchMode ? container.searchModel : container.model.count(grid.category)
                        delegate: Rectangle  {
                            property alias es: emojiSvg
                            Layout.preferredWidth: 40
                            Layout.preferredHeight: 40
                            radius: 40
                            color: mouseArea.containsMouse ? '#e6e6e6' : '#ffffff'
                            Image {
                                id: emojiSvg
                                source: container.searchMode ? path : container.model.path(grid.category, index, grid.sc)
                                sourceSize: Qt.size(30, 30)
                                anchors.centerIn: parent
                                asynchronous: true
                            }
                            MouseArea {
                                id: mouseArea
                                anchors.fill: parent
                                hoverEnabled: true
                                cursorShape: Qt.PointingHandCursor
                                onClicked: {
                                    var tag = "<img src = '%1' width = '20' height = '20' align = 'top'>"
                                    container.editor.insert(container.editor.cursorPosition, tag.arg(emojiSvg.source))
                                }
                            }
                        }
                    }
                }
                onContentYChanged: {
                    var index = list.indexAt(0, contentY + 15)
                    if (index !== -1 && index !== cateIcons.current) {
                        cateIcons.itemAt(index).source = 'icons/' + cateIcons.blueSvg[index]
                        cateIcons.itemAt(cateIcons.current).source = 'icons/' + cateIcons.blackSvg[cateIcons.current]
                        cateIcons.current = index
                    }
                }
            }
            RowLayout {
                Layout.preferredHeight: 35
                Layout.alignment: Qt.AlignCenter
                spacing: 10
                Repeater {
                    id: skinColors
                    property var colors: ['#ffb84d', '#ffdab3', '#d2a479', '#ac7139', '#734b26', '#26190d']
                    property int current: -1
                    model: 6
                    delegate: Rectangle {
                        id: colorRect
                        Layout.preferredWidth: 30
                        Layout.preferredHeight: 30
                        Layout.bottomMargin: 3
                        radius: 30
                        scale: 0.65
                        color: skinColors.colors[index]
                        Behavior on scale {
                            NumberAnimation {
                                duration: 100
                            }
                        }
                        MouseArea {
                            anchors.fill: parent
                            cursorShape: Qt.PointingHandCursor
                            onClicked: {
                                container.changeSkinColor(index - 1)
                                if (container.searchMode) {
                                    container.refreshSearchModel();
                                }
                            }
                        }
                    }
                    Component.onCompleted: {
                        itemAt(0).scale = 1
                    }
                }
            }
        }
    }
    

    Would it be possible to have the same effects in 100% C++? It shows effects like an input text expanding for search, rounded text edits, etc

    Unfortunately, there is not an automatic conversion tool from QML to C++, except for this one I found, but was not able to compile it, it uses an old Qt version

    https://github.com/Qt-QML/Cpp-Model-Generator-Tool?tab=readme-ov-file

    thanks

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on 23 Apr 2024, 21:46 last edited by
      #2

      Hi,

      You should take a look at the Graphics View Framework.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      P GrecKoG 3 Replies Last reply 23 Apr 2024, 22:55
      0
      • SGaistS SGaist
        23 Apr 2024, 21:46

        Hi,

        You should take a look at the Graphics View Framework.

        P Offline
        P Offline
        Pedro Vicente
        wrote on 23 Apr 2024, 22:55 last edited by
        #3

        @SGaist👍 🫡

        1 Reply Last reply
        0
        • SGaistS SGaist
          23 Apr 2024, 21:46

          Hi,

          You should take a look at the Graphics View Framework.

          P Offline
          P Offline
          Pedro Vicente
          wrote on 24 Apr 2024, 02:55 last edited by
          #4

          @SGaist thanks

          this simple program loads an SVG

          f495c33f-a76e-4a00-9507-2b463b8ba4bc-image.png

          int main(int argc, char* argv[]) 
          {
            QApplication app(argc, argv);
          
            QGraphicsScene scene;
            QGraphicsView view(&scene);
            view.show();
          
            QString path = qApp->applicationDirPath() + "/1f0cf.svg";
            QSvgRenderer renderer(path);
          
            QGraphicsSvgItem* item = new QGraphicsSvgItem();
            item->setSharedRenderer(&renderer);
          
            scene.addItem(item);
          
            return app.exec();
          }
          
          

          Is there a way to display this in a layout (like QGridLayout)
          using addWidget or similar

          https://doc.qt.io/qt-6/qgridlayout.html#addWidget-1

          P jeremy_kJ 2 Replies Last reply 24 Apr 2024, 03:28
          0
          • P Pedro Vicente
            24 Apr 2024, 02:55

            @SGaist thanks

            this simple program loads an SVG

            f495c33f-a76e-4a00-9507-2b463b8ba4bc-image.png

            int main(int argc, char* argv[]) 
            {
              QApplication app(argc, argv);
            
              QGraphicsScene scene;
              QGraphicsView view(&scene);
              view.show();
            
              QString path = qApp->applicationDirPath() + "/1f0cf.svg";
              QSvgRenderer renderer(path);
            
              QGraphicsSvgItem* item = new QGraphicsSvgItem();
              item->setSharedRenderer(&renderer);
            
              scene.addItem(item);
            
              return app.exec();
            }
            
            

            Is there a way to display this in a layout (like QGridLayout)
            using addWidget or similar

            https://doc.qt.io/qt-6/qgridlayout.html#addWidget-1

            P Offline
            P Offline
            Pedro Vicente
            wrote on 24 Apr 2024, 03:28 last edited by
            #5

            @Pedro-Vicente there is a setPos(x, y); function

             for (int row = 0; row < nbr_rows; ++row)
             {
               for (int col = 0; col < nbr_cols; ++col)
               {
                 int x = col * (item_width + item_space);
                 int y = row * (item_height + item_space);
                 QString path = qApp->applicationDirPath() + "/1f0cf.svg";
                 QGraphicsSvgItem* svgItem = new QGraphicsSvgItem(path);
                 svgItem->setPos(x, y);
                 scene.addItem(svgItem);
               }
             }
            
            1 Reply Last reply
            0
            • P Pedro Vicente
              24 Apr 2024, 02:55

              @SGaist thanks

              this simple program loads an SVG

              f495c33f-a76e-4a00-9507-2b463b8ba4bc-image.png

              int main(int argc, char* argv[]) 
              {
                QApplication app(argc, argv);
              
                QGraphicsScene scene;
                QGraphicsView view(&scene);
                view.show();
              
                QString path = qApp->applicationDirPath() + "/1f0cf.svg";
                QSvgRenderer renderer(path);
              
                QGraphicsSvgItem* item = new QGraphicsSvgItem();
                item->setSharedRenderer(&renderer);
              
                scene.addItem(item);
              
                return app.exec();
              }
              
              

              Is there a way to display this in a layout (like QGridLayout)
              using addWidget or similar

              https://doc.qt.io/qt-6/qgridlayout.html#addWidget-1

              jeremy_kJ Offline
              jeremy_kJ Offline
              jeremy_k
              wrote on 24 Apr 2024, 09:16 last edited by
              #6

              @Pedro-Vicente said in Porting QML emoji picker project to 100% C++ Widgets:

              Is there a way to display this in a layout (like QGridLayout)
              using addWidget or similar

              https://doc.qt.io/qt-6/qgraphicsgridlayout.html

              Asking a question about code? http://eel.is/iso-c++/testcase/

              1 Reply Last reply
              0
              • SGaistS SGaist
                23 Apr 2024, 21:46

                Hi,

                You should take a look at the Graphics View Framework.

                GrecKoG Offline
                GrecKoG Offline
                GrecKo
                Qt Champions 2018
                wrote on 24 Apr 2024, 09:32 last edited by GrecKo
                #7

                @SGaist said in Porting QML emoji picker project to 100% C++ Widgets:

                You should take a look at the Graphics View Framework.

                What about using QQuickWidget instead? That seems like the saner choice to me.

                @Pedro-Vicente Is the 100 C++ Widgets an ideological requirement or is it so it can be used in QWidgets?

                Also why is the linked projects using SVGs instead of a proper font kinda baffles me.

                JoeCFDJ 1 Reply Last reply 25 Apr 2024, 15:49
                1
                • GrecKoG GrecKo
                  24 Apr 2024, 09:32

                  @SGaist said in Porting QML emoji picker project to 100% C++ Widgets:

                  You should take a look at the Graphics View Framework.

                  What about using QQuickWidget instead? That seems like the saner choice to me.

                  @Pedro-Vicente Is the 100 C++ Widgets an ideological requirement or is it so it can be used in QWidgets?

                  Also why is the linked projects using SVGs instead of a proper font kinda baffles me.

                  JoeCFDJ Offline
                  JoeCFDJ Offline
                  JoeCFD
                  wrote on 25 Apr 2024, 15:49 last edited by
                  #8

                  @GrecKo Actually, good idea!

                  1 Reply Last reply
                  0

                  1/8

                  23 Apr 2024, 01:01

                  • Login

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