From 35066900d1f8959c9090a38bb7b8fd948df3a2f5 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 28 Oct 2020 20:26:33 +0100 Subject: [PATCH 01/35] Disable scroll helper on mobile --- resources/qml/MessageView.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml index bc0acfa4..71c85276 100644 --- a/resources/qml/MessageView.qml +++ b/resources/qml/MessageView.qml @@ -28,6 +28,7 @@ ListView { ScrollHelper { flickable: parent anchors.fill: parent + enabled: !Settings.mobileMode } Shortcut { From 7a74b863402e5f67ce7fd0a99ab3ad64b7296344 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sat, 31 Oct 2020 23:24:07 +0100 Subject: [PATCH 02/35] Pasteable textinput --- CMakeLists.txt | 2 ++ resources/qml/MessageInput.qml | 24 +++++++++++++++++- resources/qml/TimelineView.qml | 4 +-- src/timeline/InputBar.cpp | 46 ++++++++++++++++++++++++++++++++++ src/timeline/InputBar.h | 25 ++++++++++++++++++ src/timeline/TimelineModel.cpp | 1 + src/timeline/TimelineModel.h | 5 ++++ 7 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 src/timeline/InputBar.cpp create mode 100644 src/timeline/InputBar.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b5bffd7..d8e048fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -252,6 +252,7 @@ set(SRC_FILES # Timeline src/timeline/EventStore.cpp + src/timeline/InputBar.cpp src/timeline/Reaction.cpp src/timeline/TimelineViewManager.cpp src/timeline/TimelineModel.cpp @@ -463,6 +464,7 @@ qt5_wrap_cpp(MOC_HEADERS # Timeline src/timeline/EventStore.h + src/timeline/InputBar.h src/timeline/Reaction.h src/timeline/TimelineViewManager.h src/timeline/TimelineModel.h diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index 71da9cae..3b424bb3 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -3,6 +3,8 @@ import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 import QtQuick.Window 2.2 +import im.nheko 1.0 + Rectangle { color: colors.window Layout.fillWidth: true @@ -44,16 +46,36 @@ Rectangle { Layout.fillWidth: true TextArea { + id: textArea + placeholderText: qsTr("Write a message...") placeholderTextColor: colors.buttonText color: colors.text wrapMode: TextEdit.Wrap + onTextChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) + onCursorPositionChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) + onSelectionStartChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) + onSelectionEndChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) + + Keys.onPressed: { + if (event.matches(StandardKey.Paste)) { + TimelineManager.timeline.input.paste(false) || textArea.paste() + event.accepted = true + } + else if (event.matches(StandardKey.InsertParagraphSeparator)) { + TimelineManager.timeline.input.send() + textArea.clear() + event.accepted = true + } + } + MouseArea { // workaround for wrong cursor shape on some platforms anchors.fill: parent - acceptedButtons: Qt.NoButton + acceptedButtons: Qt.MiddleButton cursorShape: Qt.IBeamCursor + onClicked: TimelineManager.timeline.input.paste(true) || textArea.paste() } background: Rectangle { diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 95143b18..d85167af 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -234,8 +234,8 @@ Page { ReplyPopup { } - //MessageInput { - //} + MessageInput { + } } diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp new file mode 100644 index 00000000..d128631d --- /dev/null +++ b/src/timeline/InputBar.cpp @@ -0,0 +1,46 @@ +#include "InputBar.h" + +#include +#include +#include + +#include "Logging.h" + +bool +InputBar::paste(bool fromMouse) +{ + const QMimeData *md = nullptr; + + if (fromMouse) { + if (QGuiApplication::clipboard()->supportsSelection()) { + md = QGuiApplication::clipboard()->mimeData(QClipboard::Selection); + } + } else { + md = QGuiApplication::clipboard()->mimeData(QClipboard::Clipboard); + } + + if (!md) + return false; + + if (md->hasImage()) { + return true; + } else { + nhlog::ui()->debug("formats: {}", md->formats().join(", ").toStdString()); + return false; + } +} + +void +InputBar::updateState(int selectionStart_, int selectionEnd_, int cursorPosition_, QString text_) +{ + selectionStart = selectionStart_; + selectionEnd = selectionEnd_; + cursorPosition = cursorPosition_; + text = text_; +} + +void +InputBar::send() +{ + nhlog::ui()->debug("Send: {}", text.toStdString()); +} diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h new file mode 100644 index 00000000..78b06960 --- /dev/null +++ b/src/timeline/InputBar.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +class TimelineModel; + +class InputBar : public QObject { + Q_OBJECT + +public: + InputBar(TimelineModel *parent) + : QObject() + , room(parent) + {} + +public slots: + void send(); + bool paste(bool fromMouse); + void updateState(int selectionStart, int selectionEnd, int cursorPosition, QString text); + +private: + TimelineModel *room; + QString text; + int selectionStart = 0, selectionEnd = 0, cursorPosition = 0; +}; diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 8b80ea51..aeb4e8f5 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -1567,3 +1567,4 @@ TimelineModel::roomTopic() const return utils::replaceEmoji(utils::linkifyMessage( utils::escapeBlacklistedHtml(QString::fromStdString(info[room_id_].topic)))); } + diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index e1fb9196..58a1496c 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -10,6 +10,7 @@ #include "CacheCryptoStructs.h" #include "EventStore.h" +#include "InputBar.h" #include "ui/UserProfile.h" namespace mtx::http { @@ -149,6 +150,7 @@ class TimelineModel : public QAbstractListModel Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged) Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY roomAvatarUrlChanged) Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged) + Q_PROPERTY(InputBar *input READ input) public: explicit TimelineModel(TimelineViewManager *manager, @@ -271,6 +273,7 @@ public slots: QString roomName() const; QString roomTopic() const; + InputBar *input() { return &input_; } QString roomAvatarUrl() const; QString roomId() const { return room_id_; } @@ -320,6 +323,8 @@ private: TimelineViewManager *manager_; + InputBar input_{this}; + friend struct SendMessageVisitor; }; From 0bb488563288da75566e7da883fda31914ecf281 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 9 Nov 2020 03:12:37 +0100 Subject: [PATCH 03/35] Basic text input in qml --- resources/qml/MessageInput.qml | 9 +- src/ChatPage.cpp | 48 -------- src/ChatPage.h | 2 +- src/TextInputWidget.cpp | 65 +---------- src/TextInputWidget.h | 5 - src/timeline/InputBar.cpp | 162 ++++++++++++++++++++++++++- src/timeline/InputBar.h | 15 ++- src/timeline/TimelineModel.cpp | 1 - src/timeline/TimelineViewManager.cpp | 75 ------------- src/timeline/TimelineViewManager.h | 8 -- 10 files changed, 179 insertions(+), 211 deletions(-) diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index 3b424bb3..b76a44f3 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -58,9 +58,14 @@ Rectangle { onSelectionStartChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) onSelectionEndChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) + Connections { + target: TimelineManager.timeline.input + function onInsertText(text_) { textArea.insert(textArea.cursorPosition, text_); } + } + Keys.onPressed: { if (event.matches(StandardKey.Paste)) { - TimelineManager.timeline.input.paste(false) || textArea.paste() + TimelineManager.timeline.input.paste(false) event.accepted = true } else if (event.matches(StandardKey.InsertParagraphSeparator)) { @@ -75,7 +80,7 @@ Rectangle { anchors.fill: parent acceptedButtons: Qt.MiddleButton cursorShape: Qt.IBeamCursor - onClicked: TimelineManager.timeline.input.paste(true) || textArea.paste() + onClicked: TimelineManager.timeline.input.paste(true) } background: Rectangle { diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index 78987fb9..6e1ed8ca 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -160,15 +160,6 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) trySync(); }); - connect(text_input_, - &TextInputWidget::clearRoomTimeline, - view_manager_, - &TimelineViewManager::clearCurrentRoomTimeline); - - connect(text_input_, &TextInputWidget::rotateMegolmSession, this, [this]() { - cache::dropOutboundMegolmSession(current_room_.toStdString()); - }); - connect( new QShortcut(QKeySequence("Ctrl+Down"), this), &QShortcut::activated, this, [this]() { if (isVisible()) @@ -277,45 +268,6 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) this, SIGNAL(unreadMessages(int))); - connect(text_input_, - &TextInputWidget::sendTextMessage, - view_manager_, - &TimelineViewManager::queueTextMessage); - - connect(text_input_, - &TextInputWidget::sendEmoteMessage, - view_manager_, - &TimelineViewManager::queueEmoteMessage); - - connect(text_input_, &TextInputWidget::sendJoinRoomRequest, this, &ChatPage::joinRoom); - - // invites and bans via quick command - connect(text_input_, &TextInputWidget::sendInviteRoomRequest, this, &ChatPage::inviteUser); - connect(text_input_, &TextInputWidget::sendKickRoomRequest, this, &ChatPage::kickUser); - connect(text_input_, &TextInputWidget::sendBanRoomRequest, this, &ChatPage::banUser); - connect(text_input_, &TextInputWidget::sendUnbanRoomRequest, this, &ChatPage::unbanUser); - - connect( - text_input_, &TextInputWidget::changeRoomNick, this, [this](const QString &displayName) { - mtx::events::state::Member member; - member.display_name = displayName.toStdString(); - member.avatar_url = - cache::avatarUrl(currentRoom(), - QString::fromStdString(http::client()->user_id().to_string())) - .toStdString(); - member.membership = mtx::events::state::Membership::Join; - - http::client()->send_state_event( - currentRoom().toStdString(), - http::client()->user_id().to_string(), - member, - [](mtx::responses::EventId, mtx::http::RequestErr err) { - if (err) - nhlog::net()->error("Failed to set room displayname: {}", - err->matrix_error.error); - }); - }); - connect( text_input_, &TextInputWidget::uploadMedia, diff --git a/src/ChatPage.h b/src/ChatPage.h index 0c12d89f..9a38fd6e 100644 --- a/src/ChatPage.h +++ b/src/ChatPage.h @@ -109,6 +109,7 @@ public: public slots: void leaveRoom(const QString &room_id); void createRoom(const mtx::requests::CreateRoom &req); + void joinRoom(const QString &room); void inviteUser(QString userid, QString reason); void kickUser(QString userid, QString reason); @@ -200,7 +201,6 @@ private slots: void removeRoom(const QString &room_id); void dropToLoginPage(const QString &msg); - void joinRoom(const QString &room); void sendTypingNotifications(); void handleSyncResponse(const mtx::responses::Sync &res); diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp index 454353fd..dec7a574 100644 --- a/src/TextInputWidget.cpp +++ b/src/TextInputWidget.cpp @@ -486,36 +486,7 @@ FilteredTextEdit::minimumSizeHint() const void FilteredTextEdit::submit() -{ - if (toPlainText().trimmed().isEmpty()) - return; - - if (true_history_.size() == INPUT_HISTORY_SIZE) - true_history_.pop_back(); - true_history_.push_front(toPlainText()); - working_history_ = true_history_; - working_history_.push_front(""); - history_index_ = 0; - - QString text = toPlainText(); - - if (text.startsWith('/')) { - int command_end = text.indexOf(' '); - if (command_end == -1) - command_end = text.size(); - auto name = text.mid(1, command_end - 1); - auto args = text.mid(command_end + 1); - if (name.isEmpty() || name == "/") { - message(args); - } else { - command(name, args); - } - } else { - message(std::move(text)); - } - - clear(); -} +{} void FilteredTextEdit::textChanged() @@ -653,8 +624,6 @@ TextInputWidget::TextInputWidget(QWidget *parent) #endif connect(sendMessageBtn_, &FlatButton::clicked, input_, &FilteredTextEdit::submit); connect(sendFileBtn_, SIGNAL(clicked()), this, SLOT(openFileSelection())); - connect(input_, &FilteredTextEdit::message, this, &TextInputWidget::sendTextMessage); - connect(input_, &FilteredTextEdit::command, this, &TextInputWidget::command); connect(input_, &FilteredTextEdit::media, this, &TextInputWidget::uploadMedia); connect(emojiBtn_, SIGNAL(emojiSelected(const QString &)), @@ -685,38 +654,6 @@ TextInputWidget::addSelectedEmoji(const QString &emoji) input_->show(); } -void -TextInputWidget::command(QString command, QString args) -{ - if (command == "me") { - emit sendEmoteMessage(args); - } else if (command == "join") { - emit sendJoinRoomRequest(args); - } else if (command == "invite") { - emit sendInviteRoomRequest(args.section(' ', 0, 0), args.section(' ', 1, -1)); - } else if (command == "kick") { - emit sendKickRoomRequest(args.section(' ', 0, 0), args.section(' ', 1, -1)); - } else if (command == "ban") { - emit sendBanRoomRequest(args.section(' ', 0, 0), args.section(' ', 1, -1)); - } else if (command == "unban") { - emit sendUnbanRoomRequest(args.section(' ', 0, 0), args.section(' ', 1, -1)); - } else if (command == "roomnick") { - emit changeRoomNick(args); - } else if (command == "shrug") { - emit sendTextMessage("¯\\_(ツ)_/¯" + (args.isEmpty() ? "" : " " + args)); - } else if (command == "fliptable") { - emit sendTextMessage("(╯°□°)╯︵ ┻━┻"); - } else if (command == "unfliptable") { - emit sendTextMessage(" ┯━┯╭( º _ º╭)"); - } else if (command == "sovietflip") { - emit sendTextMessage("ノ┬─┬ノ ︵ ( \\o°o)\\"); - } else if (command == "clear-timeline") { - emit clearRoomTimeline(); - } else if (command == "rotate-megolm-session") { - emit rotateMegolmSession(); - } -} - void TextInputWidget::openFileSelection() { diff --git a/src/TextInputWidget.h b/src/TextInputWidget.h index 7cc73e98..f9d84871 100644 --- a/src/TextInputWidget.h +++ b/src/TextInputWidget.h @@ -170,9 +170,6 @@ private slots: void addSelectedEmoji(const QString &emoji); signals: - void sendTextMessage(const QString &msg); - void sendEmoteMessage(QString msg); - void clearRoomTimeline(); void heightChanged(int height); void uploadMedia(const QSharedPointer data, @@ -186,7 +183,6 @@ signals: void sendBanRoomRequest(const QString &userid, const QString &reason); void sendUnbanRoomRequest(const QString &userid, const QString &reason); void changeRoomNick(const QString &displayname); - void rotateMegolmSession(); void startedTyping(); void stoppedTyping(); @@ -197,7 +193,6 @@ protected: private: void showUploadSpinner(); - void command(QString name, QString args); QHBoxLayout *topLayout_; FilteredTextEdit *input_; diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp index d128631d..dcd4a106 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp @@ -4,9 +4,19 @@ #include #include -#include "Logging.h" +#include -bool +#include "Cache.h" +#include "ChatPage.h" +#include "Logging.h" +#include "MatrixClient.h" +#include "TimelineModel.h" +#include "UserSettingsPage.h" +#include "Utils.h" + +static constexpr size_t INPUT_HISTORY_SIZE = 10; + +void InputBar::paste(bool fromMouse) { const QMimeData *md = nullptr; @@ -20,13 +30,13 @@ InputBar::paste(bool fromMouse) } if (!md) - return false; + return; if (md->hasImage()) { - return true; + } else if (md->hasText()) { + emit insertText(md->text()); } else { nhlog::ui()->debug("formats: {}", md->formats().join(", ").toStdString()); - return false; } } @@ -42,5 +52,147 @@ InputBar::updateState(int selectionStart_, int selectionEnd_, int cursorPosition void InputBar::send() { + if (text.trimmed().isEmpty()) + return; + + if (history_.size() == INPUT_HISTORY_SIZE) + history_.pop_back(); + history_.push_front(text); + history_index_ = 0; + + if (text.startsWith('/')) { + int command_end = text.indexOf(' '); + if (command_end == -1) + command_end = text.size(); + auto name = text.mid(1, command_end - 1); + auto args = text.mid(command_end + 1); + if (name.isEmpty() || name == "/") { + message(args); + } else { + command(name, args); + } + } else { + message(text); + } + nhlog::ui()->debug("Send: {}", text.toStdString()); } + +void +InputBar::message(QString msg) +{ + mtx::events::msg::Text text = {}; + text.body = msg.trimmed().toStdString(); + + if (ChatPage::instance()->userSettings()->markdown()) { + text.formatted_body = utils::markdownToHtml(msg).toStdString(); + + // Don't send formatted_body, when we don't need to + if (text.formatted_body.find("<") == std::string::npos) + text.formatted_body = ""; + else + text.format = "org.matrix.custom.html"; + } + + if (!room->reply().isEmpty()) { + auto related = room->relatedInfo(room->reply()); + + QString body; + bool firstLine = true; + for (const auto &line : related.quoted_body.split("\n")) { + if (firstLine) { + firstLine = false; + body = QString("> <%1> %2\n").arg(related.quoted_user).arg(line); + } else { + body = QString("%1\n> %2\n").arg(body).arg(line); + } + } + + text.body = QString("%1\n%2").arg(body).arg(msg).toStdString(); + + // NOTE(Nico): rich replies always need a formatted_body! + text.format = "org.matrix.custom.html"; + if (ChatPage::instance()->userSettings()->markdown()) + text.formatted_body = + utils::getFormattedQuoteBody(related, utils::markdownToHtml(msg)) + .toStdString(); + else + text.formatted_body = + utils::getFormattedQuoteBody(related, msg.toHtmlEscaped()).toStdString(); + + text.relates_to.in_reply_to.event_id = related.related_event; + room->resetReply(); + } + + room->sendMessageEvent(text, mtx::events::EventType::RoomMessage); +} + +void +InputBar::emote(QString msg) +{ + auto html = utils::markdownToHtml(msg); + + mtx::events::msg::Emote emote; + emote.body = msg.trimmed().toStdString(); + + if (html != msg.trimmed().toHtmlEscaped() && + ChatPage::instance()->userSettings()->markdown()) { + emote.formatted_body = html.toStdString(); + emote.format = "org.matrix.custom.html"; + } + + if (!room->reply().isEmpty()) { + emote.relates_to.in_reply_to.event_id = room->reply().toStdString(); + room->resetReply(); + } + + room->sendMessageEvent(emote, mtx::events::EventType::RoomMessage); +} + +void +InputBar::command(QString command, QString args) +{ + if (command == "me") { + emote(args); + } else if (command == "join") { + ChatPage::instance()->joinRoom(args); + } else if (command == "invite") { + ChatPage::instance()->inviteUser(args.section(' ', 0, 0), args.section(' ', 1, -1)); + } else if (command == "kick") { + ChatPage::instance()->kickUser(args.section(' ', 0, 0), args.section(' ', 1, -1)); + } else if (command == "ban") { + ChatPage::instance()->banUser(args.section(' ', 0, 0), args.section(' ', 1, -1)); + } else if (command == "unban") { + ChatPage::instance()->unbanUser(args.section(' ', 0, 0), args.section(' ', 1, -1)); + } else if (command == "roomnick") { + mtx::events::state::Member member; + member.display_name = args.toStdString(); + member.avatar_url = + cache::avatarUrl(room->roomId(), + QString::fromStdString(http::client()->user_id().to_string())) + .toStdString(); + member.membership = mtx::events::state::Membership::Join; + + http::client()->send_state_event( + room->roomId().toStdString(), + http::client()->user_id().to_string(), + member, + [](mtx::responses::EventId, mtx::http::RequestErr err) { + if (err) + nhlog::net()->error("Failed to set room displayname: {}", + err->matrix_error.error); + }); + } else if (command == "shrug") { + message("¯\\_(ツ)_/¯" + (args.isEmpty() ? "" : " " + args)); + } else if (command == "fliptable") { + message("(╯°□°)╯︵ ┻━┻"); + } else if (command == "unfliptable") { + message(" ┯━┯╭( º _ º╭)"); + } else if (command == "sovietflip") { + message("ノ┬─┬ノ ︵ ( \\o°o)\\"); + } else if (command == "clear-timeline") { + room->clearTimeline(); + } else if (command == "rotate-megolm-session") { + cache::dropOutboundMegolmSession(room->roomId().toStdString()); + } +} diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h index 78b06960..f3a38c2e 100644 --- a/src/timeline/InputBar.h +++ b/src/timeline/InputBar.h @@ -1,10 +1,12 @@ #pragma once #include +#include class TimelineModel; -class InputBar : public QObject { +class InputBar : public QObject +{ Q_OBJECT public: @@ -15,11 +17,20 @@ public: public slots: void send(); - bool paste(bool fromMouse); + void paste(bool fromMouse); void updateState(int selectionStart, int selectionEnd, int cursorPosition, QString text); +signals: + void insertText(QString text); + private: + void message(QString body); + void emote(QString body); + void command(QString name, QString args); + TimelineModel *room; QString text; + std::deque history_; + std::size_t history_index_ = 0; int selectionStart = 0, selectionEnd = 0, cursorPosition = 0; }; diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index aeb4e8f5..8b80ea51 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -1567,4 +1567,3 @@ TimelineModel::roomTopic() const return utils::replaceEmoji(utils::linkifyMessage( utils::escapeBlacklistedHtml(QString::fromStdString(info[room_id_].topic)))); } - diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 3b80d020..f949498d 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -474,81 +474,6 @@ TimelineViewManager::initWithMessages(const std::vector &roomIds) addRoom(roomId); } -void -TimelineViewManager::queueTextMessage(const QString &msg) -{ - if (!timeline_) - return; - - mtx::events::msg::Text text = {}; - text.body = msg.trimmed().toStdString(); - - if (ChatPage::instance()->userSettings()->markdown()) { - text.formatted_body = utils::markdownToHtml(msg).toStdString(); - - // Don't send formatted_body, when we don't need to - if (text.formatted_body.find("<") == std::string::npos) - text.formatted_body = ""; - else - text.format = "org.matrix.custom.html"; - } - - if (!timeline_->reply().isEmpty()) { - auto related = timeline_->relatedInfo(timeline_->reply()); - - QString body; - bool firstLine = true; - for (const auto &line : related.quoted_body.split("\n")) { - if (firstLine) { - firstLine = false; - body = QString("> <%1> %2\n").arg(related.quoted_user).arg(line); - } else { - body = QString("%1\n> %2\n").arg(body).arg(line); - } - } - - text.body = QString("%1\n%2").arg(body).arg(msg).toStdString(); - - // NOTE(Nico): rich replies always need a formatted_body! - text.format = "org.matrix.custom.html"; - if (ChatPage::instance()->userSettings()->markdown()) - text.formatted_body = - utils::getFormattedQuoteBody(related, utils::markdownToHtml(msg)) - .toStdString(); - else - text.formatted_body = - utils::getFormattedQuoteBody(related, msg.toHtmlEscaped()).toStdString(); - - text.relates_to.in_reply_to.event_id = related.related_event; - timeline_->resetReply(); - } - - timeline_->sendMessageEvent(text, mtx::events::EventType::RoomMessage); -} - -void -TimelineViewManager::queueEmoteMessage(const QString &msg) -{ - auto html = utils::markdownToHtml(msg); - - mtx::events::msg::Emote emote; - emote.body = msg.trimmed().toStdString(); - - if (html != msg.trimmed().toHtmlEscaped() && - ChatPage::instance()->userSettings()->markdown()) { - emote.formatted_body = html.toStdString(); - emote.format = "org.matrix.custom.html"; - } - - if (!timeline_->reply().isEmpty()) { - emote.relates_to.in_reply_to.event_id = timeline_->reply().toStdString(); - timeline_->resetReply(); - } - - if (timeline_) - timeline_->sendMessageEvent(emote, mtx::events::EventType::RoomMessage); -} - void TimelineViewManager::queueReactionMessage(const QString &reactedEvent, const QString &reactionKey) { diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index f330d870..02e0e132 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -104,8 +104,6 @@ public slots: void setHistoryView(const QString &room_id); void updateColorPalette(); void queueReactionMessage(const QString &reactedEvent, const QString &reactionKey); - void queueTextMessage(const QString &msg); - void queueEmoteMessage(const QString &msg); void queueImageMessage(const QString &roomid, const QString &filename, const std::optional &file, @@ -139,12 +137,6 @@ public slots: void updateEncryptedDescriptions(); - void clearCurrentRoomTimeline() - { - if (timeline_) - timeline_->clearTimeline(); - } - void enableBackButton() { if (isNarrowView_) From a31d3d08165646738d6ae624ac4eff6971207058 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sun, 15 Nov 2020 04:52:49 +0100 Subject: [PATCH 04/35] Add file uploading --- resources/qml/ActiveCallBar.qml | 11 +- resources/qml/MessageInput.qml | 45 ++-- resources/qml/NhekoBusyIndicator.qml | 64 ++++++ resources/qml/TimelineView.qml | 5 +- resources/qml/VideoCall.qml | 3 +- resources/res.qrc | 1 + src/ChatPage.cpp | 120 ---------- src/ChatPage.h | 11 - src/TextInputWidget.cpp | 146 ------------ src/TextInputWidget.h | 14 -- src/Utils.cpp | 5 +- src/Utils.h | 2 +- src/dialogs/PreviewUploadOverlay.cpp | 5 +- src/dialogs/PreviewUploadOverlay.h | 1 + src/timeline/InputBar.cpp | 317 ++++++++++++++++++++++++++- src/timeline/InputBar.h | 41 ++++ src/timeline/TimelineModel.h | 2 +- 17 files changed, 475 insertions(+), 318 deletions(-) create mode 100644 resources/qml/NhekoBusyIndicator.qml diff --git a/resources/qml/ActiveCallBar.qml b/resources/qml/ActiveCallBar.qml index 282cac81..cbe36e6d 100644 --- a/resources/qml/ActiveCallBar.qml +++ b/resources/qml/ActiveCallBar.qml @@ -12,8 +12,11 @@ Rectangle { MouseArea { anchors.fill: parent - onClicked: if (TimelineManager.onVideoCall) - stackLayout.currentIndex = stackLayout.currentIndex ? 0 : 1; + onClicked: { + if (TimelineManager.onVideoCall) + stackLayout.currentIndex = stackLayout.currentIndex ? 0 : 1; + + } } RowLayout { @@ -39,8 +42,7 @@ Rectangle { Image { Layout.preferredWidth: 24 Layout.preferredHeight: 24 - source: TimelineManager.onVideoCall ? - "qrc:/icons/icons/ui/video-call.png" : "qrc:/icons/icons/ui/place-call.png" + source: TimelineManager.onVideoCall ? "qrc:/icons/icons/ui/video-call.png" : "qrc:/icons/icons/ui/place-call.png" } Label { @@ -69,6 +71,7 @@ Rectangle { callTimer.startTime = Math.floor(d.getTime() / 1000); if (TimelineManager.onVideoCall) stackLayout.currentIndex = 1; + break; case WebRTCState.DISCONNECTED: callStateLabel.text = ""; diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index b76a44f3..a1220599 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -2,7 +2,6 @@ import QtQuick 2.9 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 import QtQuick.Window 2.2 - import im.nheko 1.0 Rectangle { @@ -36,6 +35,20 @@ Rectangle { image: ":/icons/icons/ui/paper-clip-outline.png" Layout.topMargin: 8 Layout.bottomMargin: 8 + onClicked: TimelineManager.timeline.input.openFileSelection() + + Rectangle { + anchors.fill: parent + color: colors.window + visible: TimelineManager.timeline.input.uploading + + NhekoBusyIndicator { + anchors.fill: parent + running: parent.visible + } + + } + } ScrollView { @@ -52,27 +65,27 @@ Rectangle { placeholderTextColor: colors.buttonText color: colors.text wrapMode: TextEdit.Wrap - onTextChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) onCursorPositionChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) onSelectionStartChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) onSelectionEndChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) - - Connections { - target: TimelineManager.timeline.input - function onInsertText(text_) { textArea.insert(textArea.cursorPosition, text_); } - } - Keys.onPressed: { if (event.matches(StandardKey.Paste)) { - TimelineManager.timeline.input.paste(false) - event.accepted = true + TimelineManager.timeline.input.paste(false); + event.accepted = true; + } else if (event.matches(StandardKey.InsertParagraphSeparator)) { + TimelineManager.timeline.input.send(); + textArea.clear(); + event.accepted = true; } - else if (event.matches(StandardKey.InsertParagraphSeparator)) { - TimelineManager.timeline.input.send() - textArea.clear() - event.accepted = true + } + + Connections { + function onInsertText(text_) { + textArea.insert(textArea.cursorPosition, text_); } + + target: TimelineManager.timeline.input } MouseArea { @@ -110,6 +123,10 @@ Rectangle { Layout.topMargin: 8 Layout.bottomMargin: 8 Layout.rightMargin: 16 + onClicked: { + TimelineManager.timeline.input.send(); + textArea.clear(); + } } } diff --git a/resources/qml/NhekoBusyIndicator.qml b/resources/qml/NhekoBusyIndicator.qml new file mode 100644 index 00000000..8889989a --- /dev/null +++ b/resources/qml/NhekoBusyIndicator.qml @@ -0,0 +1,64 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Layouts 1.2 + +BusyIndicator { + id: control + + contentItem: Item { + implicitWidth: Math.min(parent.height, parent.width) + implicitHeight: implicitWidth + + Item { + id: item + + height: Math.min(parent.height, parent.width) + width: height + opacity: control.running ? 1 : 0 + + RotationAnimator { + target: item + running: control.visible && control.running + from: 0 + to: 360 + loops: Animation.Infinite + duration: 2000 + } + + Repeater { + id: repeater + + model: 6 + + Rectangle { + implicitWidth: radius * 2 + implicitHeight: radius * 2 + radius: item.height / 6 + color: colors.text + opacity: (index + 2) / (repeater.count + 2) + transform: [ + Translate { + y: -Math.min(item.width, item.height) * 0.5 + item.height / 6 + }, + Rotation { + angle: index / repeater.count * 360 + origin.x: item.height / 2 + origin.y: item.height / 2 + } + ] + } + + } + + Behavior on opacity { + OpacityAnimator { + duration: 250 + } + + } + + } + + } + +} diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index d85167af..5fce0846 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -192,13 +192,15 @@ Page { StackLayout { id: stackLayout + currentIndex: 0 Connections { - target: TimelineManager function onActiveTimelineChanged() { stackLayout.currentIndex = 0; } + + target: TimelineManager } MessageView { @@ -210,6 +212,7 @@ Page { source: TimelineManager.onVideoCall ? "VideoCall.qml" : "" onLoaded: TimelineManager.setVideoCallItem() } + } TypingIndicator { diff --git a/resources/qml/VideoCall.qml b/resources/qml/VideoCall.qml index 69fc1a2b..14408b6e 100644 --- a/resources/qml/VideoCall.qml +++ b/resources/qml/VideoCall.qml @@ -1,7 +1,6 @@ import QtQuick 2.9 - import org.freedesktop.gstreamer.GLVideoItem 1.0 GstGLVideoItem { - objectName: "videoCallItem" + objectName: "videoCallItem" } diff --git a/resources/res.qrc b/resources/res.qrc index efb9c907..02f31498 100644 --- a/resources/res.qrc +++ b/resources/res.qrc @@ -132,6 +132,7 @@ qml/Avatar.qml qml/ImageButton.qml qml/MatrixText.qml + qml/NhekoBusyIndicator.qml qml/StatusIndicator.qml qml/EncryptionIndicator.qml qml/Reactions.qml diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index 6e1ed8ca..e09041e7 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -268,126 +268,6 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) this, SIGNAL(unreadMessages(int))); - connect( - text_input_, - &TextInputWidget::uploadMedia, - this, - [this](QSharedPointer dev, QString mimeClass, const QString &fn) { - if (!dev->open(QIODevice::ReadOnly)) { - emit uploadFailed( - QString("Error while reading media: %1").arg(dev->errorString())); - return; - } - - auto bin = dev->readAll(); - QMimeDatabase db; - QMimeType mime = db.mimeTypeForData(bin); - - auto payload = std::string(bin.data(), bin.size()); - std::optional encryptedFile; - if (cache::isRoomEncrypted(current_room_.toStdString())) { - mtx::crypto::BinaryBuf buf; - std::tie(buf, encryptedFile) = mtx::crypto::encrypt_file(payload); - payload = mtx::crypto::to_string(buf); - } - - QSize dimensions; - QString blurhash; - if (mimeClass == "image") { - QImage img = utils::readImage(&bin); - - dimensions = img.size(); - if (img.height() > 200 && img.width() > 360) - img = img.scaled(360, 200, Qt::KeepAspectRatioByExpanding); - std::vector data; - for (int y = 0; y < img.height(); y++) { - for (int x = 0; x < img.width(); x++) { - auto p = img.pixel(x, y); - data.push_back(static_cast(qRed(p))); - data.push_back(static_cast(qGreen(p))); - data.push_back(static_cast(qBlue(p))); - } - } - blurhash = QString::fromStdString( - blurhash::encode(data.data(), img.width(), img.height(), 4, 3)); - } - - http::client()->upload( - payload, - encryptedFile ? "application/octet-stream" : mime.name().toStdString(), - QFileInfo(fn).fileName().toStdString(), - [this, - room_id = current_room_, - filename = fn, - encryptedFile, - mimeClass, - mime = mime.name(), - size = payload.size(), - dimensions, - blurhash](const mtx::responses::ContentURI &res, mtx::http::RequestErr err) { - if (err) { - emit uploadFailed( - tr("Failed to upload media. Please try again.")); - nhlog::net()->warn("failed to upload media: {} {} ({})", - err->matrix_error.error, - to_string(err->matrix_error.errcode), - static_cast(err->status_code)); - return; - } - - emit mediaUploaded(room_id, - filename, - encryptedFile, - QString::fromStdString(res.content_uri), - mimeClass, - mime, - size, - dimensions, - blurhash); - }); - }); - - connect(this, &ChatPage::uploadFailed, this, [this](const QString &msg) { - text_input_->hideUploadSpinner(); - emit showNotification(msg); - }); - connect(this, - &ChatPage::mediaUploaded, - this, - [this](QString roomid, - QString filename, - std::optional encryptedFile, - QString url, - QString mimeClass, - QString mime, - qint64 dsize, - QSize dimensions, - QString blurhash) { - text_input_->hideUploadSpinner(); - - if (encryptedFile) - encryptedFile->url = url.toStdString(); - - if (mimeClass == "image") - view_manager_->queueImageMessage(roomid, - filename, - encryptedFile, - url, - mime, - dsize, - dimensions, - blurhash); - else if (mimeClass == "audio") - view_manager_->queueAudioMessage( - roomid, filename, encryptedFile, url, mime, dsize); - else if (mimeClass == "video") - view_manager_->queueVideoMessage( - roomid, filename, encryptedFile, url, mime, dsize); - else - view_manager_->queueFileMessage( - roomid, filename, encryptedFile, url, mime, dsize); - }); - connect(text_input_, &TextInputWidget::callButtonPress, this, [this]() { if (callManager_->onActiveCall()) { callManager_->hangUp(); diff --git a/src/ChatPage.h b/src/ChatPage.h index 9a38fd6e..41c6f276 100644 --- a/src/ChatPage.h +++ b/src/ChatPage.h @@ -126,17 +126,6 @@ signals: void highlightedNotifsRetrieved(const mtx::responses::Notifications &, const QPoint widgetPos); - void uploadFailed(const QString &msg); - void mediaUploaded(const QString &roomid, - const QString &filename, - const std::optional &file, - const QString &url, - const QString &mimeClass, - const QString &mime, - qint64 dsize, - const QSize &dimensions, - const QString &blurhash); - void contentLoaded(); void closing(); void changeWindowTitle(const int); diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp index dec7a574..232c0cad 100644 --- a/src/TextInputWidget.cpp +++ b/src/TextInputWidget.cpp @@ -88,10 +88,6 @@ FilteredTextEdit::FilteredTextEdit(QWidget *parent) typingTimer_->setSingleShot(true); connect(typingTimer_, &QTimer::timeout, this, &FilteredTextEdit::stopTyping); - connect(&previewDialog_, - &dialogs::PreviewUploadOverlay::confirmUpload, - this, - &FilteredTextEdit::uploadData); connect(this, &FilteredTextEdit::resultsRetrieved, this, &FilteredTextEdit::showResults); connect( @@ -355,81 +351,6 @@ FilteredTextEdit::keyPressEvent(QKeyEvent *event) } } -bool -FilteredTextEdit::canInsertFromMimeData(const QMimeData *source) const -{ - return (source->hasImage() || QTextEdit::canInsertFromMimeData(source)); -} - -void -FilteredTextEdit::insertFromMimeData(const QMimeData *source) -{ - qInfo() << "Got mime formats: \n" << source->formats(); - const auto formats = source->formats().filter("/"); - const auto image = formats.filter("image/", Qt::CaseInsensitive); - const auto audio = formats.filter("audio/", Qt::CaseInsensitive); - const auto video = formats.filter("video/", Qt::CaseInsensitive); - - if (!image.empty() && source->hasImage()) { - QImage img = qvariant_cast(source->imageData()); - previewDialog_.setPreview(img, image.front()); - } else if (!audio.empty()) { - showPreview(source, audio); - } else if (!video.empty()) { - showPreview(source, video); - } else if (source->hasUrls()) { - // Generic file path for any platform. - QString path; - for (auto &&u : source->urls()) { - if (u.isLocalFile()) { - path = u.toLocalFile(); - break; - } - } - - if (!path.isEmpty() && QFileInfo{path}.exists()) { - previewDialog_.setPreview(path); - } else { - qWarning() - << "Clipboard does not contain any valid file paths:" << source->urls(); - } - } else if (source->hasFormat("x-special/gnome-copied-files")) { - // Special case for X11 users. See "Notes for X11 Users" in source. - // Source: http://doc.qt.io/qt-5/qclipboard.html - - // This MIME type returns a string with multiple lines separated by '\n'. The first - // line is the command to perform with the clipboard (not useful to us). The - // following lines are the file URIs. - // - // Source: the nautilus source code in file 'src/nautilus-clipboard.c' in function - // nautilus_clipboard_get_uri_list_from_selection_data() - // https://github.com/GNOME/nautilus/blob/master/src/nautilus-clipboard.c - - auto data = source->data("x-special/gnome-copied-files").split('\n'); - if (data.size() < 2) { - qWarning() << "MIME format is malformed, cannot perform paste."; - return; - } - - QString path; - for (int i = 1; i < data.size(); ++i) { - QUrl url{data[i]}; - if (url.isLocalFile()) { - path = url.toLocalFile(); - break; - } - } - - if (!path.isEmpty()) { - previewDialog_.setPreview(path); - } else { - qWarning() << "Clipboard does not contain any valid file paths:" << data; - } - } else { - QTextEdit::insertFromMimeData(source); - } -} - void FilteredTextEdit::stopTyping() { @@ -494,28 +415,6 @@ FilteredTextEdit::textChanged() working_history_[history_index_] = toPlainText(); } -void -FilteredTextEdit::uploadData(const QByteArray data, - const QString &mediaType, - const QString &filename) -{ - QSharedPointer buffer{new QBuffer{this}}; - buffer->setData(data); - - emit startedUpload(); - - emit media(buffer, mediaType, filename); -} - -void -FilteredTextEdit::showPreview(const QMimeData *source, const QStringList &formats) -{ - // Retrieve data as MIME type. - auto const &mime = formats.first(); - QByteArray data = source->data(mime); - previewDialog_.setPreview(data, mime); -} - TextInputWidget::TextInputWidget(QWidget *parent) : QWidget(parent) { @@ -624,7 +523,6 @@ TextInputWidget::TextInputWidget(QWidget *parent) #endif connect(sendMessageBtn_, &FlatButton::clicked, input_, &FilteredTextEdit::submit); connect(sendFileBtn_, SIGNAL(clicked()), this, SLOT(openFileSelection())); - connect(input_, &FilteredTextEdit::media, this, &TextInputWidget::uploadMedia); connect(emojiBtn_, SIGNAL(emojiSelected(const QString &)), this, @@ -633,9 +531,6 @@ TextInputWidget::TextInputWidget(QWidget *parent) connect(input_, &FilteredTextEdit::startedTyping, this, &TextInputWidget::startedTyping); connect(input_, &FilteredTextEdit::stoppedTyping, this, &TextInputWidget::stoppedTyping); - - connect( - input_, &FilteredTextEdit::startedUpload, this, &TextInputWidget::showUploadSpinner); } void @@ -654,47 +549,6 @@ TextInputWidget::addSelectedEmoji(const QString &emoji) input_->show(); } -void -TextInputWidget::openFileSelection() -{ - const QString homeFolder = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); - const auto fileName = - QFileDialog::getOpenFileName(this, tr("Select a file"), homeFolder, tr("All Files (*)")); - - if (fileName.isEmpty()) - return; - - QMimeDatabase db; - QMimeType mime = db.mimeTypeForFile(fileName, QMimeDatabase::MatchContent); - - const auto format = mime.name().split("/")[0]; - - QSharedPointer file{new QFile{fileName, this}}; - - emit uploadMedia(file, format, QFileInfo(fileName).fileName()); - - showUploadSpinner(); -} - -void -TextInputWidget::showUploadSpinner() -{ - topLayout_->removeWidget(sendFileBtn_); - sendFileBtn_->hide(); - - topLayout_->insertWidget(1, spinner_); - spinner_->start(); -} - -void -TextInputWidget::hideUploadSpinner() -{ - topLayout_->removeWidget(spinner_); - topLayout_->insertWidget(1, sendFileBtn_); - sendFileBtn_->show(); - spinner_->stop(); -} - void TextInputWidget::stopTyping() { diff --git a/src/TextInputWidget.h b/src/TextInputWidget.h index f9d84871..44419547 100644 --- a/src/TextInputWidget.h +++ b/src/TextInputWidget.h @@ -57,9 +57,6 @@ signals: void startedTyping(); void stoppedTyping(); void startedUpload(); - void message(QString msg); - void command(QString name, QString args); - void media(QSharedPointer data, QString mimeClass, const QString &filename); //! Trigger the suggestion popup. void showSuggestions(const QString &query); @@ -73,8 +70,6 @@ public slots: protected: void keyPressEvent(QKeyEvent *event) override; - bool canInsertFromMimeData(const QMimeData *source) const override; - void insertFromMimeData(const QMimeData *source) override; void focusOutEvent(QFocusEvent *event) override { suggestionsPopup_.hide(); @@ -131,9 +126,7 @@ private: void insertCompletion(QString completion); void textChanged(); - void uploadData(const QByteArray data, const QString &media, const QString &filename); void afterCompletion(int); - void showPreview(const QMimeData *source, const QStringList &formats); }; class TextInputWidget : public QWidget @@ -161,8 +154,6 @@ public: } public slots: - void openFileSelection(); - void hideUploadSpinner(); void focusLineEdit() { input_->setFocus(); } void changeCallButtonState(webrtc::State); @@ -172,9 +163,6 @@ private slots: signals: void heightChanged(int height); - void uploadMedia(const QSharedPointer data, - QString mimeClass, - const QString &filename); void callButtonPress(); void sendJoinRoomRequest(const QString &room); @@ -192,8 +180,6 @@ protected: void paintEvent(QPaintEvent *) override; private: - void showUploadSpinner(); - QHBoxLayout *topLayout_; FilteredTextEdit *input_; diff --git a/src/Utils.cpp b/src/Utils.cpp index 38dbba22..2896e773 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -677,9 +677,10 @@ utils::restoreCombobox(QComboBox *combo, const QString &value) } QImage -utils::readImage(QByteArray *data) +utils::readImage(const QByteArray *data) { - QBuffer buf(data); + QBuffer buf; + buf.setData(*data); QImageReader reader(&buf); reader.setAutoTransform(true); return reader.read(); diff --git a/src/Utils.h b/src/Utils.h index 5e7fb601..f59e8673 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -303,5 +303,5 @@ restoreCombobox(QComboBox *combo, const QString &value); //! Read image respecting exif orientation QImage -readImage(QByteArray *data); +readImage(const QByteArray *data); } diff --git a/src/dialogs/PreviewUploadOverlay.cpp b/src/dialogs/PreviewUploadOverlay.cpp index 20959b0a..e03993c7 100644 --- a/src/dialogs/PreviewUploadOverlay.cpp +++ b/src/dialogs/PreviewUploadOverlay.cpp @@ -60,7 +60,10 @@ PreviewUploadOverlay::PreviewUploadOverlay(QWidget *parent) emit confirmUpload(data_, mediaType_, fileName_.text()); close(); }); - connect(&cancel_, &QPushButton::clicked, this, &PreviewUploadOverlay::close); + connect(&cancel_, &QPushButton::clicked, this, [this]() { + emit aborted(); + close(); + }); } void diff --git a/src/dialogs/PreviewUploadOverlay.h b/src/dialogs/PreviewUploadOverlay.h index 11cd49bc..5139e3f2 100644 --- a/src/dialogs/PreviewUploadOverlay.h +++ b/src/dialogs/PreviewUploadOverlay.h @@ -40,6 +40,7 @@ public: signals: void confirmUpload(const QByteArray data, const QString &media, const QString &filename); + void aborted(); private: void init(); diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp index dcd4a106..bd8f6414 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp @@ -1,18 +1,27 @@ #include "InputBar.h" #include +#include #include #include +#include +#include +#include #include +#include #include "Cache.h" #include "ChatPage.h" #include "Logging.h" #include "MatrixClient.h" +#include "Olm.h" #include "TimelineModel.h" #include "UserSettingsPage.h" #include "Utils.h" +#include "dialogs/PreviewUploadOverlay.h" + +#include "blurhash.hpp" static constexpr size_t INPUT_HISTORY_SIZE = 10; @@ -32,7 +41,66 @@ InputBar::paste(bool fromMouse) if (!md) return; - if (md->hasImage()) { + nhlog::ui()->debug("Got mime formats: {}", md->formats().join(", ").toStdString()); + const auto formats = md->formats().filter("/"); + const auto image = formats.filter("image/", Qt::CaseInsensitive); + const auto audio = formats.filter("audio/", Qt::CaseInsensitive); + const auto video = formats.filter("video/", Qt::CaseInsensitive); + + if (!image.empty() && md->hasImage()) { + showPreview(*md, "", image); + } else if (!audio.empty()) { + showPreview(*md, "", audio); + } else if (!video.empty()) { + showPreview(*md, "", video); + } else if (md->hasUrls()) { + // Generic file path for any platform. + QString path; + for (auto &&u : md->urls()) { + if (u.isLocalFile()) { + path = u.toLocalFile(); + break; + } + } + + if (!path.isEmpty() && QFileInfo{path}.exists()) { + showPreview(*md, path, formats); + } else { + nhlog::ui()->warn("Clipboard does not contain any valid file paths."); + } + } else if (md->hasFormat("x-special/gnome-copied-files")) { + // Special case for X11 users. See "Notes for X11 Users" in md. + // Source: http://doc.qt.io/qt-5/qclipboard.html + + // This MIME type returns a string with multiple lines separated by '\n'. The first + // line is the command to perform with the clipboard (not useful to us). The + // following lines are the file URIs. + // + // Source: the nautilus source code in file 'src/nautilus-clipboard.c' in function + // nautilus_clipboard_get_uri_list_from_selection_data() + // https://github.com/GNOME/nautilus/blob/master/src/nautilus-clipboard.c + + auto data = md->data("x-special/gnome-copied-files").split('\n'); + if (data.size() < 2) { + nhlog::ui()->warn("MIME format is malformed, cannot perform paste."); + return; + } + + QString path; + for (int i = 1; i < data.size(); ++i) { + QUrl url{data[i]}; + if (url.isLocalFile()) { + path = url.toLocalFile(); + break; + } + } + + if (!path.isEmpty()) { + showPreview(*md, path, formats); + } else { + nhlog::ui()->warn("Clipboard does not contain any valid file paths: {}", + data.join(", ").toStdString()); + } } else if (md->hasText()) { emit insertText(md->text()); } else { @@ -78,6 +146,37 @@ InputBar::send() nhlog::ui()->debug("Send: {}", text.toStdString()); } +void +InputBar::openFileSelection() +{ + const QString homeFolder = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); + const auto fileName = QFileDialog::getOpenFileName( + ChatPage::instance(), tr("Select a file"), homeFolder, tr("All Files (*)")); + + if (fileName.isEmpty()) + return; + + QMimeDatabase db; + QMimeType mime = db.mimeTypeForFile(fileName, QMimeDatabase::MatchContent); + + QFile file{fileName}; + + if (!file.open(QIODevice::ReadOnly)) { + emit ChatPage::instance()->showNotification( + QString("Error while reading media: %1").arg(file.errorString())); + return; + } + + setUploading(true); + + auto bin = file.readAll(); + + QMimeData data; + data.setData(mime.name(), bin); + + showPreview(data, fileName, QStringList{mime.name()}); +} + void InputBar::message(QString msg) { @@ -149,6 +248,112 @@ InputBar::emote(QString msg) room->sendMessageEvent(emote, mtx::events::EventType::RoomMessage); } +void +InputBar::image(const QString &filename, + const std::optional &file, + const QString &url, + const QString &mime, + uint64_t dsize, + const QSize &dimensions, + const QString &blurhash) +{ + mtx::events::msg::Image image; + image.info.mimetype = mime.toStdString(); + image.info.size = dsize; + image.info.blurhash = blurhash.toStdString(); + image.body = filename.toStdString(); + image.info.h = dimensions.height(); + image.info.w = dimensions.width(); + + if (file) + image.file = file; + else + image.url = url.toStdString(); + + if (!room->reply().isEmpty()) { + image.relates_to.in_reply_to.event_id = room->reply().toStdString(); + room->resetReply(); + } + + room->sendMessageEvent(image, mtx::events::EventType::RoomMessage); +} + +void +InputBar::file(const QString &filename, + const std::optional &encryptedFile, + const QString &url, + const QString &mime, + uint64_t dsize) +{ + mtx::events::msg::File file; + file.info.mimetype = mime.toStdString(); + file.info.size = dsize; + file.body = filename.toStdString(); + + if (encryptedFile) + file.file = encryptedFile; + else + file.url = url.toStdString(); + + if (!room->reply().isEmpty()) { + file.relates_to.in_reply_to.event_id = room->reply().toStdString(); + room->resetReply(); + } + + room->sendMessageEvent(file, mtx::events::EventType::RoomMessage); +} + +void +InputBar::audio(const QString &filename, + const std::optional &file, + const QString &url, + const QString &mime, + uint64_t dsize) +{ + mtx::events::msg::Audio audio; + audio.info.mimetype = mime.toStdString(); + audio.info.size = dsize; + audio.body = filename.toStdString(); + audio.url = url.toStdString(); + + if (file) + audio.file = file; + else + audio.url = url.toStdString(); + + if (!room->reply().isEmpty()) { + audio.relates_to.in_reply_to.event_id = room->reply().toStdString(); + room->resetReply(); + } + + room->sendMessageEvent(audio, mtx::events::EventType::RoomMessage); +} + +void +InputBar::video(const QString &filename, + const std::optional &file, + const QString &url, + const QString &mime, + uint64_t dsize) +{ + mtx::events::msg::Video video; + video.info.mimetype = mime.toStdString(); + video.info.size = dsize; + video.body = filename.toStdString(); + + if (file) + video.file = file; + else + video.url = url.toStdString(); + + if (!room->reply().isEmpty()) { + video.relates_to.in_reply_to.event_id = room->reply().toStdString(); + room->resetReply(); + } + + room->sendMessageEvent(video, mtx::events::EventType::RoomMessage); +} + void InputBar::command(QString command, QString args) { @@ -196,3 +401,113 @@ InputBar::command(QString command, QString args) cache::dropOutboundMegolmSession(room->roomId().toStdString()); } } + +void +InputBar::showPreview(const QMimeData &source, QString path, const QStringList &formats) +{ + dialogs::PreviewUploadOverlay *previewDialog_ = + new dialogs::PreviewUploadOverlay(ChatPage::instance()); + previewDialog_->setAttribute(Qt::WA_DeleteOnClose); + + if (source.hasImage()) + previewDialog_->setPreview(qvariant_cast(source.imageData()), + formats.front()); + else if (!path.isEmpty()) + previewDialog_->setPreview(path); + else if (!formats.isEmpty()) { + auto mime = formats.first(); + previewDialog_->setPreview(source.data(mime), mime); + } else { + setUploading(false); + previewDialog_->deleteLater(); + return; + } + + connect(previewDialog_, &dialogs::PreviewUploadOverlay::aborted, this, [this]() { + setUploading(false); + }); + + connect( + previewDialog_, + &dialogs::PreviewUploadOverlay::confirmUpload, + this, + [this](const QByteArray data, const QString &mime, const QString &fn) { + setUploading(true); + + auto payload = std::string(data.data(), data.size()); + std::optional encryptedFile; + if (cache::isRoomEncrypted(room->roomId().toStdString())) { + mtx::crypto::BinaryBuf buf; + std::tie(buf, encryptedFile) = mtx::crypto::encrypt_file(payload); + payload = mtx::crypto::to_string(buf); + } + + QSize dimensions; + QString blurhash; + auto mimeClass = mime.split("/")[0]; + if (mimeClass == "image") { + QImage img = utils::readImage(&data); + + dimensions = img.size(); + if (img.height() > 200 && img.width() > 360) + img = img.scaled(360, 200, Qt::KeepAspectRatioByExpanding); + std::vector data; + for (int y = 0; y < img.height(); y++) { + for (int x = 0; x < img.width(); x++) { + auto p = img.pixel(x, y); + data.push_back(static_cast(qRed(p))); + data.push_back(static_cast(qGreen(p))); + data.push_back(static_cast(qBlue(p))); + } + } + blurhash = QString::fromStdString( + blurhash::encode(data.data(), img.width(), img.height(), 4, 3)); + } + + http::client()->upload( + payload, + encryptedFile ? "application/octet-stream" : mime.toStdString(), + QFileInfo(fn).fileName().toStdString(), + [this, + filename = fn, + encryptedFile = std::move(encryptedFile), + mimeClass, + mime, + size = payload.size(), + dimensions, + blurhash](const mtx::responses::ContentURI &res, + mtx::http::RequestErr err) mutable { + if (err) { + emit ChatPage::instance()->showNotification( + tr("Failed to upload media. Please try again.")); + nhlog::net()->warn("failed to upload media: {} {} ({})", + err->matrix_error.error, + to_string(err->matrix_error.errcode), + static_cast(err->status_code)); + setUploading(false); + return; + } + + auto url = QString::fromStdString(res.content_uri); + if (encryptedFile) + encryptedFile->url = res.content_uri; + + if (mimeClass == "image") + image(filename, + encryptedFile, + url, + mime, + size, + dimensions, + blurhash); + else if (mimeClass == "audio") + audio(filename, encryptedFile, url, mime, size); + else if (mimeClass == "video") + video(filename, encryptedFile, url, mime, size); + else + file(filename, encryptedFile, url, mime, size); + + setUploading(false); + }); + }); +} diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h index f3a38c2e..35e3f8a4 100644 --- a/src/timeline/InputBar.h +++ b/src/timeline/InputBar.h @@ -3,11 +3,17 @@ #include #include +#include +#include + class TimelineModel; +class QMimeData; +class QStringList; class InputBar : public QObject { Q_OBJECT + Q_PROPERTY(bool uploading READ uploading NOTIFY uploadingChanged) public: InputBar(TimelineModel *parent) @@ -19,18 +25,53 @@ public slots: void send(); void paste(bool fromMouse); void updateState(int selectionStart, int selectionEnd, int cursorPosition, QString text); + void openFileSelection(); + bool uploading() const { return uploading_; } signals: void insertText(QString text); + void uploadingChanged(bool value); private: void message(QString body); void emote(QString body); void command(QString name, QString args); + void image(const QString &filename, + const std::optional &file, + const QString &url, + const QString &mime, + uint64_t dsize, + const QSize &dimensions, + const QString &blurhash); + void file(const QString &filename, + const std::optional &encryptedFile, + const QString &url, + const QString &mime, + uint64_t dsize); + void audio(const QString &filename, + const std::optional &file, + const QString &url, + const QString &mime, + uint64_t dsize); + void video(const QString &filename, + const std::optional &file, + const QString &url, + const QString &mime, + uint64_t dsize); + + void showPreview(const QMimeData &source, QString path, const QStringList &formats); + void setUploading(bool value) + { + if (value != uploading_) { + uploading_ = value; + emit uploadingChanged(value); + } + } TimelineModel *room; QString text; std::deque history_; std::size_t history_index_ = 0; int selectionStart = 0, selectionEnd = 0, cursorPosition = 0; + bool uploading_ = false; }; diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index 58a1496c..16a2565e 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -150,7 +150,7 @@ class TimelineModel : public QAbstractListModel Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged) Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY roomAvatarUrlChanged) Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged) - Q_PROPERTY(InputBar *input READ input) + Q_PROPERTY(InputBar *input READ input CONSTANT) public: explicit TimelineModel(TimelineViewManager *manager, From d1af1a86691290c67ad9e2b6ae9440b1254a2c0b Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sun, 15 Nov 2020 23:14:47 +0100 Subject: [PATCH 05/35] Move calls to new input bar --- resources/qml/MessageInput.qml | 13 ++- resources/qml/NhekoBusyIndicator.qml | 4 +- src/ChatPage.cpp | 32 ------- src/ChatPage.h | 1 + src/TextInputWidget.cpp | 30 ------ src/TextInputWidget.h | 5 - src/timeline/InputBar.cpp | 45 +++++++++ src/timeline/InputBar.h | 1 + src/timeline/TimelineViewManager.cpp | 136 ++++----------------------- src/timeline/TimelineViewManager.h | 31 +----- 10 files changed, 86 insertions(+), 212 deletions(-) diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index a1220599..17e1198d 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -17,14 +17,18 @@ Rectangle { spacing: 16 ImageButton { + visible: TimelineManager.callsSupported Layout.alignment: Qt.AlignBottom hoverEnabled: true width: 22 height: 22 - image: ":/icons/icons/ui/place-call.png" + image: TimelineManager.isOnCall ? ":/icons/icons/ui/end-call.png" : ":/icons/icons/ui/place-call.png" + ToolTip.visible: hovered + ToolTip.text: TimelineManager.isOnCall ? qsTr("Hang up") : qsTr("Place a call") Layout.topMargin: 8 Layout.bottomMargin: 8 Layout.leftMargin: 16 + onClicked: TimelineManager.timeline.input.callButton() } ImageButton { @@ -35,7 +39,10 @@ Rectangle { image: ":/icons/icons/ui/paper-clip-outline.png" Layout.topMargin: 8 Layout.bottomMargin: 8 + Layout.leftMargin: TimelineManager.callsSupported ? 0 : 16 onClicked: TimelineManager.timeline.input.openFileSelection() + ToolTip.visible: hovered + ToolTip.text: qsTr("Send a file") Rectangle { anchors.fill: parent @@ -112,6 +119,8 @@ Rectangle { image: ":/icons/icons/ui/smile.png" Layout.topMargin: 8 Layout.bottomMargin: 8 + ToolTip.visible: hovered + ToolTip.text: qsTr("Emoji") } ImageButton { @@ -123,6 +132,8 @@ Rectangle { Layout.topMargin: 8 Layout.bottomMargin: 8 Layout.rightMargin: 16 + ToolTip.visible: hovered + ToolTip.text: qsTr("Send") onClicked: { TimelineManager.timeline.input.send(); textArea.clear(); diff --git a/resources/qml/NhekoBusyIndicator.qml b/resources/qml/NhekoBusyIndicator.qml index 8889989a..89a40dd5 100644 --- a/resources/qml/NhekoBusyIndicator.qml +++ b/resources/qml/NhekoBusyIndicator.qml @@ -6,8 +6,8 @@ BusyIndicator { id: control contentItem: Item { - implicitWidth: Math.min(parent.height, parent.width) - implicitHeight: implicitWidth + implicitWidth: 64 + implicitHeight: 64 Item { id: item diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index e09041e7..c703d95f 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -268,38 +268,6 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) this, SIGNAL(unreadMessages(int))); - connect(text_input_, &TextInputWidget::callButtonPress, this, [this]() { - if (callManager_->onActiveCall()) { - callManager_->hangUp(); - } else { - if (auto roomInfo = cache::singleRoomInfo(current_room_.toStdString()); - roomInfo.member_count != 2) { - showNotification("Calls are limited to 1:1 rooms."); - } else { - std::vector members( - cache::getMembers(current_room_.toStdString())); - const RoomMember &callee = - members.front().user_id == utils::localUser() ? members.back() - : members.front(); - auto dialog = new dialogs::PlaceCall( - callee.user_id, - callee.display_name, - QString::fromStdString(roomInfo.name), - QString::fromStdString(roomInfo.avatar_url), - userSettings_, - MainWindow::instance()); - connect(dialog, &dialogs::PlaceCall::voice, this, [this]() { - callManager_->sendInvite(current_room_, false); - }); - connect(dialog, &dialogs::PlaceCall::video, this, [this]() { - callManager_->sendInvite(current_room_, true); - }); - utils::centerWidget(dialog, MainWindow::instance()); - dialog->show(); - } - } - }); - connect( this, &ChatPage::updateGroupsInfo, communitiesList_, &CommunitiesList::setCommunities); diff --git a/src/ChatPage.h b/src/ChatPage.h index 41c6f276..7eb37f04 100644 --- a/src/ChatPage.h +++ b/src/ChatPage.h @@ -88,6 +88,7 @@ public: static ChatPage *instance() { return instance_; } QSharedPointer userSettings() { return userSettings_; } + CallManager *callManager() { return callManager_; } void deleteConfigs(); CommunitiesList *communitiesList() { return communitiesList_; } diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp index 232c0cad..1a856abb 100644 --- a/src/TextInputWidget.cpp +++ b/src/TextInputWidget.cpp @@ -431,15 +431,6 @@ TextInputWidget::TextInputWidget(QWidget *parent) topLayout_->setSpacing(0); topLayout_->setContentsMargins(13, 1, 13, 0); -#ifdef GSTREAMER_AVAILABLE - callBtn_ = new FlatButton(this); - changeCallButtonState(webrtc::State::DISCONNECTED); - connect(&WebRTCSession::instance(), - &WebRTCSession::stateChanged, - this, - &TextInputWidget::changeCallButtonState); -#endif - QIcon send_file_icon; send_file_icon.addFile(":/icons/icons/ui/paper-clip-outline.png"); @@ -508,9 +499,6 @@ TextInputWidget::TextInputWidget(QWidget *parent) emojiBtn_->setIcon(emoji_icon); emojiBtn_->setIconSize(QSize(ButtonHeight, ButtonHeight)); -#ifdef GSTREAMER_AVAILABLE - topLayout_->addWidget(callBtn_); -#endif topLayout_->addWidget(sendFileBtn_); topLayout_->addWidget(input_); topLayout_->addWidget(emojiBtn_); @@ -518,9 +506,6 @@ TextInputWidget::TextInputWidget(QWidget *parent) setLayout(topLayout_); -#ifdef GSTREAMER_AVAILABLE - connect(callBtn_, &FlatButton::clicked, this, &TextInputWidget::callButtonPress); -#endif connect(sendMessageBtn_, &FlatButton::clicked, input_, &FilteredTextEdit::submit); connect(sendFileBtn_, SIGNAL(clicked()), this, SLOT(openFileSelection())); connect(emojiBtn_, @@ -570,18 +555,3 @@ TextInputWidget::paintEvent(QPaintEvent *) style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } - -void -TextInputWidget::changeCallButtonState(webrtc::State state) -{ - QIcon icon; - if (state == webrtc::State::ICEFAILED || state == webrtc::State::DISCONNECTED) { - callBtn_->setToolTip(tr("Place a call")); - icon.addFile(":/icons/icons/ui/place-call.png"); - } else { - callBtn_->setToolTip(tr("Hang up")); - icon.addFile(":/icons/icons/ui/end-call.png"); - } - callBtn_->setIcon(icon); - callBtn_->setIconSize(QSize(ButtonHeight * 1.1, ButtonHeight * 1.1)); -} diff --git a/src/TextInputWidget.h b/src/TextInputWidget.h index 44419547..9613f209 100644 --- a/src/TextInputWidget.h +++ b/src/TextInputWidget.h @@ -26,7 +26,6 @@ #include #include -#include "WebRTCSession.h" #include "dialogs/PreviewUploadOverlay.h" #include "emoji/PickButton.h" #include "popups/SuggestionsPopup.h" @@ -155,7 +154,6 @@ public: public slots: void focusLineEdit() { input_->setFocus(); } - void changeCallButtonState(webrtc::State); private slots: void addSelectedEmoji(const QString &emoji); @@ -163,8 +161,6 @@ private slots: signals: void heightChanged(int height); - void callButtonPress(); - void sendJoinRoomRequest(const QString &room); void sendInviteRoomRequest(const QString &userid, const QString &reason); void sendKickRoomRequest(const QString &userid, const QString &reason); @@ -185,7 +181,6 @@ private: LoadingIndicator *spinner_; - FlatButton *callBtn_; FlatButton *sendFileBtn_; FlatButton *sendMessageBtn_; emoji::PickButton *emojiBtn_; diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp index bd8f6414..dc287f94 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp @@ -12,13 +12,16 @@ #include #include "Cache.h" +#include "CallManager.h" #include "ChatPage.h" #include "Logging.h" +#include "MainWindow.h" #include "MatrixClient.h" #include "Olm.h" #include "TimelineModel.h" #include "UserSettingsPage.h" #include "Utils.h" +#include "dialogs/PlaceCall.h" #include "dialogs/PreviewUploadOverlay.h" #include "blurhash.hpp" @@ -511,3 +514,45 @@ InputBar::showPreview(const QMimeData &source, QString path, const QStringList & }); }); } + +void +InputBar::callButton() +{ + auto callManager_ = ChatPage::instance()->callManager(); + if (callManager_->onActiveCall()) { + callManager_->hangUp(); + } else { + auto current_room_ = room->roomId(); + if (auto roomInfo = cache::singleRoomInfo(current_room_.toStdString()); + roomInfo.member_count != 2) { + ChatPage::instance()->showNotification("Calls are limited to 1:1 rooms."); + } else { + std::vector members( + cache::getMembers(current_room_.toStdString())); + const RoomMember &callee = members.front().user_id == utils::localUser() + ? members.back() + : members.front(); + auto dialog = + new dialogs::PlaceCall(callee.user_id, + callee.display_name, + QString::fromStdString(roomInfo.name), + QString::fromStdString(roomInfo.avatar_url), + ChatPage::instance()->userSettings(), + MainWindow::instance()); + connect(dialog, + &dialogs::PlaceCall::voice, + callManager_, + [callManager_, current_room_]() { + callManager_->sendInvite(current_room_, false); + }); + connect(dialog, + &dialogs::PlaceCall::video, + callManager_, + [callManager_, current_room_]() { + callManager_->sendInvite(current_room_, true); + }); + utils::centerWidget(dialog, MainWindow::instance()); + dialog->show(); + } + } +} diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h index 35e3f8a4..a52a3904 100644 --- a/src/timeline/InputBar.h +++ b/src/timeline/InputBar.h @@ -27,6 +27,7 @@ public slots: void updateState(int selectionStart, int selectionEnd, int cursorPosition, QString text); void openFileSelection(); bool uploading() const { return uploading_; } + void callButton(); signals: void insertText(QString text); diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index f949498d..1392c505 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -244,6 +244,26 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par &CallManager::newVideoCallState, this, &TimelineViewManager::videoCallChanged); + + connect(&WebRTCSession::instance(), + &WebRTCSession::stateChanged, + this, + &TimelineViewManager::onCallChanged); +} + +bool +TimelineViewManager::isOnCall() const +{ + return callManager_->onActiveCall(); +} +bool +TimelineViewManager::callsSupported() const +{ +#ifdef GSTREAMER_AVAILABLE + return true; +#else + return false; +#endif } void @@ -506,122 +526,6 @@ TimelineViewManager::queueReactionMessage(const QString &reactedEvent, const QSt timeline_->redactEvent(selfReactedEvent); } } - -void -TimelineViewManager::queueImageMessage(const QString &roomid, - const QString &filename, - const std::optional &file, - const QString &url, - const QString &mime, - uint64_t dsize, - const QSize &dimensions, - const QString &blurhash) -{ - mtx::events::msg::Image image; - image.info.mimetype = mime.toStdString(); - image.info.size = dsize; - image.info.blurhash = blurhash.toStdString(); - image.body = filename.toStdString(); - image.info.h = dimensions.height(); - image.info.w = dimensions.width(); - - if (file) - image.file = file; - else - image.url = url.toStdString(); - - auto model = models.value(roomid); - if (!model->reply().isEmpty()) { - image.relates_to.in_reply_to.event_id = model->reply().toStdString(); - model->resetReply(); - } - - model->sendMessageEvent(image, mtx::events::EventType::RoomMessage); -} - -void -TimelineViewManager::queueFileMessage( - const QString &roomid, - const QString &filename, - const std::optional &encryptedFile, - const QString &url, - const QString &mime, - uint64_t dsize) -{ - mtx::events::msg::File file; - file.info.mimetype = mime.toStdString(); - file.info.size = dsize; - file.body = filename.toStdString(); - - if (encryptedFile) - file.file = encryptedFile; - else - file.url = url.toStdString(); - - auto model = models.value(roomid); - if (!model->reply().isEmpty()) { - file.relates_to.in_reply_to.event_id = model->reply().toStdString(); - model->resetReply(); - } - - model->sendMessageEvent(file, mtx::events::EventType::RoomMessage); -} - -void -TimelineViewManager::queueAudioMessage(const QString &roomid, - const QString &filename, - const std::optional &file, - const QString &url, - const QString &mime, - uint64_t dsize) -{ - mtx::events::msg::Audio audio; - audio.info.mimetype = mime.toStdString(); - audio.info.size = dsize; - audio.body = filename.toStdString(); - audio.url = url.toStdString(); - - if (file) - audio.file = file; - else - audio.url = url.toStdString(); - - auto model = models.value(roomid); - if (!model->reply().isEmpty()) { - audio.relates_to.in_reply_to.event_id = model->reply().toStdString(); - model->resetReply(); - } - - model->sendMessageEvent(audio, mtx::events::EventType::RoomMessage); -} - -void -TimelineViewManager::queueVideoMessage(const QString &roomid, - const QString &filename, - const std::optional &file, - const QString &url, - const QString &mime, - uint64_t dsize) -{ - mtx::events::msg::Video video; - video.info.mimetype = mime.toStdString(); - video.info.size = dsize; - video.body = filename.toStdString(); - - if (file) - video.file = file; - else - video.url = url.toStdString(); - - auto model = models.value(roomid); - if (!model->reply().isEmpty()) { - video.relates_to.in_reply_to.event_id = model->reply().toStdString(); - model->resetReply(); - } - - model->sendMessageEvent(video, mtx::events::EventType::RoomMessage); -} - void TimelineViewManager::queueCallMessage(const QString &roomid, const mtx::events::msg::CallInvite &callInvite) diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 02e0e132..371e9af2 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -41,6 +41,8 @@ class TimelineViewManager : public QObject Q_PROPERTY(QString callPartyName READ callPartyName NOTIFY callPartyChanged) Q_PROPERTY(QString callPartyAvatarUrl READ callPartyAvatarUrl NOTIFY callPartyChanged) Q_PROPERTY(bool isMicMuted READ isMicMuted NOTIFY micMuteChanged) + Q_PROPERTY(bool isOnCall READ isOnCall NOTIFY onCallChanged) + Q_PROPERTY(bool callsSupported READ callsSupported CONSTANT) public: TimelineViewManager(CallManager *callManager, ChatPage *parent = nullptr); @@ -95,6 +97,7 @@ signals: void videoCallChanged(); void callPartyChanged(); void micMuteChanged(); + void onCallChanged(); public slots: void updateReadReceipts(const QString &room_id, const std::vector &event_ids); @@ -104,38 +107,14 @@ public slots: void setHistoryView(const QString &room_id); void updateColorPalette(); void queueReactionMessage(const QString &reactedEvent, const QString &reactionKey); - void queueImageMessage(const QString &roomid, - const QString &filename, - const std::optional &file, - const QString &url, - const QString &mime, - uint64_t dsize, - const QSize &dimensions, - const QString &blurhash); - void queueFileMessage(const QString &roomid, - const QString &filename, - const std::optional &file, - const QString &url, - const QString &mime, - uint64_t dsize); - void queueAudioMessage(const QString &roomid, - const QString &filename, - const std::optional &file, - const QString &url, - const QString &mime, - uint64_t dsize); - void queueVideoMessage(const QString &roomid, - const QString &filename, - const std::optional &file, - const QString &url, - const QString &mime, - uint64_t dsize); void queueCallMessage(const QString &roomid, const mtx::events::msg::CallInvite &); void queueCallMessage(const QString &roomid, const mtx::events::msg::CallCandidates &); void queueCallMessage(const QString &roomid, const mtx::events::msg::CallAnswer &); void queueCallMessage(const QString &roomid, const mtx::events::msg::CallHangUp &); void updateEncryptedDescriptions(); + bool isOnCall() const; + bool callsSupported() const; void enableBackButton() { From 2bec5d083cc9d1b527d0b822ec520855805933f3 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 16 Nov 2020 00:39:50 +0100 Subject: [PATCH 06/35] Use old style connection (for Qt5.12) --- resources/qml/MessageInput.qml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index 17e1198d..e9f3a6b9 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -88,9 +88,7 @@ Rectangle { } Connections { - function onInsertText(text_) { - textArea.insert(textArea.cursorPosition, text_); - } + onInsertText: textArea.insert(textArea.cursorPosition, text); target: TimelineManager.timeline.input } From 82c441dddd9d57f858c62c9fd3c8718d44ca3d7b Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 16 Nov 2020 18:41:29 +0100 Subject: [PATCH 07/35] Move emoji picker to qml --- CMakeLists.txt | 9 - resources/qml/MessageInput.qml | 8 +- resources/qml/TimelineView.qml | 4 +- resources/qml/emoji/EmojiButton.qml | 4 +- resources/qml/emoji/EmojiPicker.qml | 12 +- src/TextInputWidget.cpp | 35 - src/TextInputWidget.h | 6 - src/emoji/Category.cpp | 95 - src/emoji/Category.h | 67 - src/emoji/ItemDelegate.cpp | 66 - src/emoji/ItemDelegate.h | 43 - src/emoji/Panel.cpp | 231 - src/emoji/Panel.h | 66 - src/emoji/PickButton.cpp | 82 - src/emoji/PickButton.h | 55 - src/emoji/Provider.cpp | 7734 --------------------------- src/emoji/Provider.h | 8 - 17 files changed, 18 insertions(+), 8507 deletions(-) delete mode 100644 src/emoji/Category.cpp delete mode 100644 src/emoji/Category.h delete mode 100644 src/emoji/ItemDelegate.cpp delete mode 100644 src/emoji/ItemDelegate.h delete mode 100644 src/emoji/Panel.cpp delete mode 100644 src/emoji/Panel.h delete mode 100644 src/emoji/PickButton.cpp delete mode 100644 src/emoji/PickButton.h delete mode 100644 src/emoji/Provider.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d8e048fb..2b918be7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -241,12 +241,7 @@ set(SRC_FILES src/dialogs/RoomSettings.cpp # Emoji - src/emoji/Category.cpp src/emoji/EmojiModel.cpp - src/emoji/ItemDelegate.cpp - src/emoji/Panel.cpp - src/emoji/PickButton.cpp - src/emoji/Provider.cpp src/emoji/Provider_new.cpp @@ -455,11 +450,7 @@ qt5_wrap_cpp(MOC_HEADERS src/dialogs/RoomSettings.h # Emoji - src/emoji/Category.h src/emoji/EmojiModel.h - src/emoji/ItemDelegate.h - src/emoji/Panel.h - src/emoji/PickButton.h src/emoji/Provider.h # Timeline diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index e9f3a6b9..da76c6ac 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -88,8 +88,7 @@ Rectangle { } Connections { - onInsertText: textArea.insert(textArea.cursorPosition, text); - + onInsertText: textArea.insert(textArea.cursorPosition, text) target: TimelineManager.timeline.input } @@ -110,6 +109,8 @@ Rectangle { } ImageButton { + id: emojiButton + Layout.alignment: Qt.AlignRight | Qt.AlignBottom hoverEnabled: true width: 22 @@ -119,6 +120,9 @@ Rectangle { Layout.bottomMargin: 8 ToolTip.visible: hovered ToolTip.text: qsTr("Emoji") + onClicked: emojiPopup.visible ? emojiPopup.close() : emojiPopup.show(emojiButton, function(emoji) { + textArea.insert(textArea.cursorPosition, emoji); + }) } ImageButton { diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 5fce0846..c23564c1 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -72,7 +72,9 @@ Page { MenuItem { text: qsTr("React") - onClicked: emojiPopup.show(messageContextMenu.parent, messageContextMenu.eventId) + onClicked: emojiPopup.show(messageContextMenu.parent, function(emoji) { + TimelineManager.queueReactionMessage(messageContextMenu.eventId, emoji); + }) } MenuItem { diff --git a/resources/qml/emoji/EmojiButton.qml b/resources/qml/emoji/EmojiButton.qml index 1fcfc0c5..928d6226 100644 --- a/resources/qml/emoji/EmojiButton.qml +++ b/resources/qml/emoji/EmojiButton.qml @@ -12,5 +12,7 @@ ImageButton { property string event_id image: ":/icons/icons/ui/smile.png" - onClicked: emojiPicker.visible ? emojiPicker.close() : emojiPicker.show(emojiButton, event_id) + onClicked: emojiPicker.visible ? emojiPicker.close() : emojiPicker.show(emojiButton, function(emoji) { + TimelineManager.queueReactionMessage(event_id, emoji); + }) } diff --git a/resources/qml/emoji/EmojiPicker.qml b/resources/qml/emoji/EmojiPicker.qml index afe16350..e0e1ceaf 100644 --- a/resources/qml/emoji/EmojiPicker.qml +++ b/resources/qml/emoji/EmojiPicker.qml @@ -9,7 +9,7 @@ import im.nheko.EmojiModel 1.0 Popup { id: emojiPopup - property string event_id + property var callback property var colors property alias model: gridView.model property var textArea @@ -18,14 +18,14 @@ Popup { property real highlightSat: colors.highlight.hslSaturation property real highlightLight: colors.highlight.hslLightness - function show(showAt, event_id) { - console.debug("Showing emojiPicker for " + event_id); + function show(showAt, callback) { + console.debug("Showing emojiPicker"); if (showAt) { parent = showAt; x = Math.round((showAt.width - width) / 2); y = showAt.height; } - emojiPopup.event_id = event_id; + emojiPopup.callback = callback; open(); } @@ -70,9 +70,9 @@ Popup { ToolTip.visible: hovered // TODO: maybe add favorites at some point? onClicked: { - console.debug("Picked " + model.unicode + "in response to " + emojiPopup.event_id); + console.debug("Picked " + model.unicode); emojiPopup.close(); - TimelineManager.queueReactionMessage(emojiPopup.event_id, model.unicode); + callback(model.unicode); } // give the emoji a little oomf diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp index 1a856abb..92449231 100644 --- a/src/TextInputWidget.cpp +++ b/src/TextInputWidget.cpp @@ -486,54 +486,19 @@ TextInputWidget::TextInputWidget(QWidget *parent) sendMessageBtn_->setIcon(send_message_icon); sendMessageBtn_->setIconSize(QSize(ButtonHeight, ButtonHeight)); - emojiBtn_ = new emoji::PickButton(this); - emojiBtn_->setToolTip(tr("Emoji")); - -#if defined(Q_OS_MAC) - // macOS has a native emoji picker. - emojiBtn_->hide(); -#endif - - QIcon emoji_icon; - emoji_icon.addFile(":/icons/icons/ui/smile.png"); - emojiBtn_->setIcon(emoji_icon); - emojiBtn_->setIconSize(QSize(ButtonHeight, ButtonHeight)); - topLayout_->addWidget(sendFileBtn_); topLayout_->addWidget(input_); - topLayout_->addWidget(emojiBtn_); topLayout_->addWidget(sendMessageBtn_); setLayout(topLayout_); connect(sendMessageBtn_, &FlatButton::clicked, input_, &FilteredTextEdit::submit); connect(sendFileBtn_, SIGNAL(clicked()), this, SLOT(openFileSelection())); - connect(emojiBtn_, - SIGNAL(emojiSelected(const QString &)), - this, - SLOT(addSelectedEmoji(const QString &))); - connect(input_, &FilteredTextEdit::startedTyping, this, &TextInputWidget::startedTyping); connect(input_, &FilteredTextEdit::stoppedTyping, this, &TextInputWidget::stoppedTyping); } -void -TextInputWidget::addSelectedEmoji(const QString &emoji) -{ - QTextCursor cursor = input_->textCursor(); - - QTextCharFormat charfmt; - input_->setCurrentCharFormat(charfmt); - - input_->insertPlainText(emoji); - cursor.movePosition(QTextCursor::End); - - input_->setCurrentCharFormat(charfmt); - - input_->show(); -} - void TextInputWidget::stopTyping() { diff --git a/src/TextInputWidget.h b/src/TextInputWidget.h index 9613f209..afd29439 100644 --- a/src/TextInputWidget.h +++ b/src/TextInputWidget.h @@ -27,7 +27,6 @@ #include #include "dialogs/PreviewUploadOverlay.h" -#include "emoji/PickButton.h" #include "popups/SuggestionsPopup.h" struct SearchResult; @@ -155,9 +154,6 @@ public: public slots: void focusLineEdit() { input_->setFocus(); } -private slots: - void addSelectedEmoji(const QString &emoji); - signals: void heightChanged(int height); @@ -183,7 +179,5 @@ private: FlatButton *sendFileBtn_; FlatButton *sendMessageBtn_; - emoji::PickButton *emojiBtn_; - QColor borderColor_; }; diff --git a/src/emoji/Category.cpp b/src/emoji/Category.cpp deleted file mode 100644 index 5197c474..00000000 --- a/src/emoji/Category.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * nheko Copyright (C) 2017 Konstantinos Sideris - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include -#include - -#include "Config.h" - -#include "emoji/Category.h" - -using namespace emoji; - -Category::Category(QString category, std::vector emoji, QWidget *parent) - : QWidget(parent) -{ - mainLayout_ = new QVBoxLayout(this); - mainLayout_->setMargin(0); - mainLayout_->setSpacing(0); - - emojiListView_ = new QListView(); - itemModel_ = new QStandardItemModel(this); - - delegate_ = new ItemDelegate(this); - data_ = new Emoji; - - emojiListView_->setItemDelegate(delegate_); - emojiListView_->setModel(itemModel_); - emojiListView_->setViewMode(QListView::IconMode); - emojiListView_->setFlow(QListView::LeftToRight); - emojiListView_->setResizeMode(QListView::Adjust); - emojiListView_->setMouseTracking(true); - emojiListView_->verticalScrollBar()->setEnabled(false); - emojiListView_->horizontalScrollBar()->setEnabled(false); - - const int cols = 7; - const int rows = emoji.size() / 7 + 1; - - const int emojiSize = 48; - const int gridSize = emojiSize + 4; - // TODO: Be precise here. Take the parent into consideration. - emojiListView_->setFixedSize(cols * gridSize + 20, rows * gridSize); - emojiListView_->setGridSize(QSize(gridSize, gridSize)); - emojiListView_->setDragEnabled(false); - emojiListView_->setEditTriggers(QAbstractItemView::NoEditTriggers); - - for (const auto &e : emoji) { - data_->unicode = e.unicode; - - auto item = new QStandardItem; - item->setSizeHint(QSize(emojiSize, emojiSize)); - - QVariant unicode(data_->unicode); - item->setData(unicode.toString(), Qt::UserRole); - - itemModel_->appendRow(item); - } - - QFont font; - font.setWeight(QFont::Medium); - - category_ = new QLabel(category, this); - category_->setFont(font); - - mainLayout_->addWidget(category_); - mainLayout_->addWidget(emojiListView_); - - connect(emojiListView_, &QListView::clicked, this, &Category::clickIndex); -} - -void -Category::paintEvent(QPaintEvent *) -{ - QStyleOption opt; - opt.init(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); -} diff --git a/src/emoji/Category.h b/src/emoji/Category.h deleted file mode 100644 index 79e616ee..00000000 --- a/src/emoji/Category.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * nheko Copyright (C) 2017 Konstantinos Sideris - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include - -#include "ItemDelegate.h" - -class QLabel; -class QListView; -class QStandardItemModel; -class QVBoxLayout; - -namespace emoji { - -class Category : public QWidget -{ - Q_OBJECT - Q_PROPERTY( - QColor hoverBackgroundColor READ hoverBackgroundColor WRITE setHoverBackgroundColor) - -public: - Category(QString category, std::vector emoji, QWidget *parent = nullptr); - QColor hoverBackgroundColor() const { return hoverBackgroundColor_; } - void setHoverBackgroundColor(QColor color) { hoverBackgroundColor_ = color; } - -signals: - void emojiSelected(const QString &emoji); - -protected: - void paintEvent(QPaintEvent *event) override; - -private slots: - void clickIndex(const QModelIndex &index) - { - emit emojiSelected(index.data(Qt::UserRole).toString()); - }; - -private: - QVBoxLayout *mainLayout_; - - QStandardItemModel *itemModel_; - QListView *emojiListView_; - - emoji::Emoji *data_; - emoji::ItemDelegate *delegate_; - - QLabel *category_; - - QColor hoverBackgroundColor_; -}; -} // namespace emoji diff --git a/src/emoji/ItemDelegate.cpp b/src/emoji/ItemDelegate.cpp deleted file mode 100644 index afa01625..00000000 --- a/src/emoji/ItemDelegate.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * nheko Copyright (C) 2017 Konstantinos Sideris - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include - -#include "emoji/ItemDelegate.h" - -using namespace emoji; - -ItemDelegate::ItemDelegate(QObject *parent) - : QStyledItemDelegate(parent) -{ - data_ = new Emoji; -} - -ItemDelegate::~ItemDelegate() { delete data_; } - -void -ItemDelegate::paint(QPainter *painter, - const QStyleOptionViewItem &option, - const QModelIndex &index) const -{ - Q_UNUSED(index); - - painter->save(); - - QStyleOptionViewItem viewOption(option); - - auto emoji = index.data(Qt::UserRole).toString(); - - QSettings settings; - - QFont font; - QString userFontFamily = settings.value("user/emoji_font_family", "emoji").toString(); - if (!userFontFamily.isEmpty()) { - font.setFamily(userFontFamily); - } else { - font.setFamily("emoji"); - } - - font.setPixelSize(36); - painter->setFont(font); - if (option.state & QStyle::State_MouseOver) { - painter->setBackgroundMode(Qt::OpaqueMode); - QColor hoverColor = parent()->property("hoverBackgroundColor").value(); - painter->setBackground(hoverColor); - } - painter->drawText(viewOption.rect, Qt::AlignCenter, emoji); - - painter->restore(); -} diff --git a/src/emoji/ItemDelegate.h b/src/emoji/ItemDelegate.h deleted file mode 100644 index d6b9b9d7..00000000 --- a/src/emoji/ItemDelegate.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * nheko Copyright (C) 2017 Konstantinos Sideris - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include -#include -#include - -#include "Provider.h" - -namespace emoji { - -class ItemDelegate : public QStyledItemDelegate -{ - Q_OBJECT - -public: - explicit ItemDelegate(QObject *parent = nullptr); - ~ItemDelegate() override; - - void paint(QPainter *painter, - const QStyleOptionViewItem &option, - const QModelIndex &index) const override; - -private: - Emoji *data_; -}; -} // namespace emoji diff --git a/src/emoji/Panel.cpp b/src/emoji/Panel.cpp deleted file mode 100644 index f0e4449d..00000000 --- a/src/emoji/Panel.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/* - * nheko Copyright (C) 2017 Konstantinos Sideris - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include - -#include "ui/DropShadow.h" -#include "ui/FlatButton.h" - -#include "emoji/Category.h" -#include "emoji/Panel.h" - -using namespace emoji; - -Panel::Panel(QWidget *parent) - : QWidget(parent) - , shadowMargin_{2} - , width_{370} - , height_{350} - , categoryIconSize_{20} -{ - setAttribute(Qt::WA_ShowWithoutActivating, true); - setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint); - - auto mainWidget = new QWidget(this); - mainWidget->setMaximumSize(width_, height_); - - auto topLayout = new QVBoxLayout(this); - topLayout->addWidget(mainWidget); - topLayout->setMargin(shadowMargin_); - topLayout->setSpacing(0); - - auto contentLayout = new QVBoxLayout(mainWidget); - contentLayout->setMargin(0); - contentLayout->setSpacing(0); - - auto emojiCategories = new QFrame(mainWidget); - - auto categoriesLayout = new QHBoxLayout(emojiCategories); - categoriesLayout->setSpacing(0); - categoriesLayout->setMargin(0); - - QIcon icon; - - auto peopleCategory = new FlatButton(emojiCategories); - icon.addFile(":/icons/icons/emoji-categories/people.png"); - peopleCategory->setIcon(icon); - peopleCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_)); - - auto natureCategory_ = new FlatButton(emojiCategories); - icon.addFile(":/icons/icons/emoji-categories/nature.png"); - natureCategory_->setIcon(icon); - natureCategory_->setIconSize(QSize(categoryIconSize_, categoryIconSize_)); - - auto foodCategory_ = new FlatButton(emojiCategories); - icon.addFile(":/icons/icons/emoji-categories/foods.png"); - foodCategory_->setIcon(icon); - foodCategory_->setIconSize(QSize(categoryIconSize_, categoryIconSize_)); - - auto activityCategory = new FlatButton(emojiCategories); - icon.addFile(":/icons/icons/emoji-categories/activity.png"); - activityCategory->setIcon(icon); - activityCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_)); - - auto travelCategory = new FlatButton(emojiCategories); - icon.addFile(":/icons/icons/emoji-categories/travel.png"); - travelCategory->setIcon(icon); - travelCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_)); - - auto objectsCategory = new FlatButton(emojiCategories); - icon.addFile(":/icons/icons/emoji-categories/objects.png"); - objectsCategory->setIcon(icon); - objectsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_)); - - auto symbolsCategory = new FlatButton(emojiCategories); - icon.addFile(":/icons/icons/emoji-categories/symbols.png"); - symbolsCategory->setIcon(icon); - symbolsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_)); - - auto flagsCategory = new FlatButton(emojiCategories); - icon.addFile(":/icons/icons/emoji-categories/flags.png"); - flagsCategory->setIcon(icon); - flagsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_)); - - categoriesLayout->addWidget(peopleCategory); - categoriesLayout->addWidget(natureCategory_); - categoriesLayout->addWidget(foodCategory_); - categoriesLayout->addWidget(activityCategory); - categoriesLayout->addWidget(travelCategory); - categoriesLayout->addWidget(objectsCategory); - categoriesLayout->addWidget(symbolsCategory); - categoriesLayout->addWidget(flagsCategory); - - scrollArea_ = new QScrollArea(this); - scrollArea_->setWidgetResizable(true); - scrollArea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - auto scrollWidget = new QWidget(this); - auto scrollLayout = new QVBoxLayout(scrollWidget); - - scrollLayout->setMargin(0); - scrollLayout->setSpacing(0); - scrollArea_->setWidget(scrollWidget); - - auto peopleEmoji = - new Category(tr("Smileys & People"), emoji_provider_.people, scrollWidget); - scrollLayout->addWidget(peopleEmoji); - - auto natureEmoji = - new Category(tr("Animals & Nature"), emoji_provider_.nature, scrollWidget); - scrollLayout->addWidget(natureEmoji); - - auto foodEmoji = new Category(tr("Food & Drink"), emoji_provider_.food, scrollWidget); - scrollLayout->addWidget(foodEmoji); - - auto activityEmoji = new Category(tr("Activity"), emoji_provider_.activity, scrollWidget); - scrollLayout->addWidget(activityEmoji); - - auto travelEmoji = - new Category(tr("Travel & Places"), emoji_provider_.travel, scrollWidget); - scrollLayout->addWidget(travelEmoji); - - auto objectsEmoji = new Category(tr("Objects"), emoji_provider_.objects, scrollWidget); - scrollLayout->addWidget(objectsEmoji); - - auto symbolsEmoji = new Category(tr("Symbols"), emoji_provider_.symbols, scrollWidget); - scrollLayout->addWidget(symbolsEmoji); - - auto flagsEmoji = new Category(tr("Flags"), emoji_provider_.flags, scrollWidget); - scrollLayout->addWidget(flagsEmoji); - - contentLayout->addWidget(scrollArea_); - contentLayout->addWidget(emojiCategories); - - connect(peopleEmoji, &Category::emojiSelected, this, &Panel::emojiSelected); - connect(peopleCategory, &QPushButton::clicked, [this, peopleEmoji]() { - this->showCategory(peopleEmoji); - }); - - connect(natureEmoji, &Category::emojiSelected, this, &Panel::emojiSelected); - connect(natureCategory_, &QPushButton::clicked, [this, natureEmoji]() { - this->showCategory(natureEmoji); - }); - - connect(foodEmoji, &Category::emojiSelected, this, &Panel::emojiSelected); - connect(foodCategory_, &QPushButton::clicked, [this, foodEmoji]() { - this->showCategory(foodEmoji); - }); - - connect(activityEmoji, &Category::emojiSelected, this, &Panel::emojiSelected); - connect(activityCategory, &QPushButton::clicked, [this, activityEmoji]() { - this->showCategory(activityEmoji); - }); - - connect(travelEmoji, &Category::emojiSelected, this, &Panel::emojiSelected); - connect(travelCategory, &QPushButton::clicked, [this, travelEmoji]() { - this->showCategory(travelEmoji); - }); - - connect(objectsEmoji, &Category::emojiSelected, this, &Panel::emojiSelected); - connect(objectsCategory, &QPushButton::clicked, [this, objectsEmoji]() { - this->showCategory(objectsEmoji); - }); - - connect(symbolsEmoji, &Category::emojiSelected, this, &Panel::emojiSelected); - connect(symbolsCategory, &QPushButton::clicked, [this, symbolsEmoji]() { - this->showCategory(symbolsEmoji); - }); - - connect(flagsEmoji, &Category::emojiSelected, this, &Panel::emojiSelected); - connect(flagsCategory, &QPushButton::clicked, [this, flagsEmoji]() { - this->showCategory(flagsEmoji); - }); -} - -void -Panel::showCategory(const Category *category) -{ - auto posToGo = category->mapToParent(QPoint()).y(); - auto current = scrollArea_->verticalScrollBar()->value(); - - if (current == posToGo) - return; - - // HACK - // We want the top of the category to be visible, so scroll to the top first and then to the - // category - if (current > posToGo) - this->scrollArea_->ensureVisible(0, 0, 0, 0); - - posToGo += scrollArea_->height(); - this->scrollArea_->ensureVisible(0, posToGo, 0, 0); -} - -void -Panel::paintEvent(QPaintEvent *event) -{ - Q_UNUSED(event); - - QStyleOption opt; - opt.init(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); - - DropShadow::draw(p, - shadowMargin_, - 4.0, - QColor(120, 120, 120, 92), - QColor(255, 255, 255, 0), - 0.0, - 1.0, - 0.6, - width(), - height()); -} diff --git a/src/emoji/Panel.h b/src/emoji/Panel.h deleted file mode 100644 index ad233c27..00000000 --- a/src/emoji/Panel.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * nheko Copyright (C) 2017 Konstantinos Sideris - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include - -#include "Provider.h" - -namespace emoji { - -class Category; - -class Panel : public QWidget -{ - Q_OBJECT - -public: - Panel(QWidget *parent = nullptr); - -signals: - void mouseLeft(); - void emojiSelected(const QString &emoji); - -protected: - void leaveEvent(QEvent *event) override - { - emit leaving(); - QWidget::leaveEvent(event); - } - - void paintEvent(QPaintEvent *event) override; - -signals: - void leaving(); - -private: - void showCategory(const Category *category); - - Provider emoji_provider_; - - QScrollArea *scrollArea_; - - int shadowMargin_; - - // Panel dimensions. - int width_; - int height_; - - int categoryIconSize_; -}; -} // namespace emoji diff --git a/src/emoji/PickButton.cpp b/src/emoji/PickButton.cpp deleted file mode 100644 index 608b4fa2..00000000 --- a/src/emoji/PickButton.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * nheko Copyright (C) 2017 Konstantinos Sideris - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include "emoji/Panel.h" -#include "emoji/PickButton.h" - -using namespace emoji; - -// Number of milliseconds after which the panel will be hidden -// if the mouse cursor is not on top of the widget. -constexpr int HIDE_TIMEOUT = 300; - -PickButton::PickButton(QWidget *parent) - : FlatButton(parent) - , panel_{nullptr} -{ - connect(&hideTimer_, &QTimer::timeout, this, &PickButton::hidePanel); - connect(this, &QPushButton::clicked, this, [this]() { - if (panel_ && panel_->isVisible()) { - hidePanel(); - return; - } - - showPanel(); - }); -} - -void -PickButton::hidePanel() -{ - if (panel_ && !panel_->underMouse()) { - hideTimer_.stop(); - panel_->hide(); - } -} - -void -PickButton::showPanel() -{ - if (panel_.isNull()) { - panel_ = QSharedPointer(new Panel(this)); - connect(panel_.data(), &Panel::emojiSelected, this, &PickButton::emojiSelected); - connect(panel_.data(), &Panel::leaving, this, [this]() { panel_->hide(); }); - } - - if (panel_->isVisible()) - return; - - QPoint pos(rect().x(), rect().y()); - pos = this->mapToGlobal(pos); - - auto panel_size = panel_->sizeHint(); - - auto x = pos.x() - panel_size.width() + horizontal_distance_; - auto y = pos.y() - panel_size.height() - vertical_distance_; - - panel_->move(x, y); - panel_->show(); -} - -void -PickButton::leaveEvent(QEvent *e) -{ - hideTimer_.start(HIDE_TIMEOUT); - FlatButton::leaveEvent(e); -} diff --git a/src/emoji/PickButton.h b/src/emoji/PickButton.h deleted file mode 100644 index 97ed8c37..00000000 --- a/src/emoji/PickButton.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * nheko Copyright (C) 2017 Konstantinos Sideris - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include -#include -#include - -#include "ui/FlatButton.h" - -namespace emoji { - -class Panel; - -class PickButton : public FlatButton -{ - Q_OBJECT -public: - explicit PickButton(QWidget *parent = nullptr); - -signals: - void emojiSelected(const QString &emoji); - -protected: - void leaveEvent(QEvent *e) override; - -private: - void showPanel(); - void hidePanel(); - - // Vertical distance from panel's bottom. - int vertical_distance_ = 10; - - // Horizontal distance from panel's bottom right corner. - int horizontal_distance_ = 70; - - QSharedPointer panel_; - QTimer hideTimer_; -}; -} // namespace emoji diff --git a/src/emoji/Provider.cpp b/src/emoji/Provider.cpp deleted file mode 100644 index 0e11be4a..00000000 --- a/src/emoji/Provider.cpp +++ /dev/null @@ -1,7734 +0,0 @@ -/* - * nheko Copyright (C) 2017 Konstantinos Sideris - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "emoji/Provider.h" - -using namespace emoji; - -const std::vector emoji::Provider::people = { - // People - Emoji{QString::fromUtf8("\xf0\x9f\x98\x80"), "grinning face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x83"), - "grinning face with big eyes", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x84"), - "grinning face with smiling eyes", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x81"), - "beaming face with smiling eyes", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x86"), - "grinning squinting face", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x85"), - "grinning face with sweat", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa3"), - "rolling on the floor laughing", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x82"), - "face with tears of joy", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x82"), - "slightly smiling face", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x83"), "upside-down face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x89"), "winking face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x8a"), - "smiling face with smiling eyes", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x87"), - "smiling face with halo", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xb0"), - "smiling face with hearts", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x8d"), - "smiling face with heart-eyes", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa9"), "star-struck", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x98"), "face blowing a kiss", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x97"), "kissing face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x98\xba"), "smiling face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x9a"), - "kissing face with closed eyes", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x99"), - "kissing face with smiling eyes", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xb2"), - "smiling face with tear", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x8b"), "face savoring food", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x9b"), "face with tongue", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x9c"), - "winking face with tongue", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xaa"), "zany face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x9d"), - "squinting face with tongue", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x91"), "money-mouth face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x97"), "hugging face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xad"), - "face with hand over mouth", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xab"), "shushing face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x94"), "thinking face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x90"), "zipper-mouth face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa8"), - "face with raised eyebrow", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x90"), "neutral face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x91"), "expressionless face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb6"), "face without mouth", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x8f"), "smirking face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x92"), "unamused face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x84"), - "face with rolling eyes", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xac"), "grimacing face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa5"), "lying face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x8c"), "relieved face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x94"), "pensive face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xaa"), "sleepy face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa4"), "drooling face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb4"), "sleeping face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb7"), - "face with medical mask", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x92"), - "face with thermometer", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x95"), - "face with head-bandage", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa2"), "nauseated face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xae"), "face vomiting", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa7"), "sneezing face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xb5"), "hot face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xb6"), "cold face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xb4"), "woozy face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb5"), "dizzy face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xaf"), "exploding head", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa0"), "cowboy hat face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xb3"), "partying face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xb8"), "disguised face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x8e"), - "smiling face with sunglasses", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x93"), "nerd face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x90"), "face with monocle", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x95"), "confused face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x9f"), "worried face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x81"), - "slightly frowning face", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x98\xb9"), "frowning face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xae"), - "face with open mouth", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xaf"), "hushed face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb2"), "astonished face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb3"), "flushed face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xba"), "pleading face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xa6"), - "frowning face with open mouth", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xa7"), "anguished face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xa8"), "fearful face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb0"), - "anxious face with sweat", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xa5"), - "sad but relieved face", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xa2"), "crying face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xad"), "loudly crying face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb1"), - "face screaming in fear", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x96"), "confounded face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xa3"), "persevering face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x9e"), "disappointed face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x93"), - "downcast face with sweat", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xa9"), "weary face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xab"), "tired face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xb1"), "yawning face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xa4"), - "face with steam from nose", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xa1"), "pouting face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xa0"), "angry face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xac"), - "face with symbols on mouth", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\x88"), - "smiling face with horns", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xbf"), - "angry face with horns", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x80"), "skull", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x98\xa0"), "skull and crossbones", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xa9"), "pile of poo", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa1"), "clown face", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb9"), "ogre", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xba"), "goblin", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xbb"), "ghost", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xbd"), "alien", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xbe"), "alien monster", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x96"), "robot", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xba"), "grinning cat", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb8"), - "grinning cat with smiling eyes", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb9"), - "cat with tears of joy", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xbb"), - "smiling cat with heart-eyes", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xbc"), "cat with wry smile", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xbd"), "kissing cat", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x80"), "weary cat", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xbf"), "crying cat", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x98\xbe"), "pouting cat", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x88"), "see-no-evil monkey", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x89"), "hear-no-evil monkey", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8a"), - "speak-no-evil monkey", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x8b"), "kiss mark", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x8c"), "love letter", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x98"), "heart with arrow", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x9d"), "heart with ribbon", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x96"), "sparkling heart", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x97"), "growing heart", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x93"), "beating heart", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x9e"), "revolving hearts", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x95"), "two hearts", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x9f"), "heart decoration", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9d\xa3"), "heart exclamation", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x94"), "broken heart", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9d\xa4"), "red heart", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xa1"), "orange heart", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x9b"), "yellow heart", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x9a"), "green heart", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x99"), "blue heart", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x9c"), "purple heart", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x8e"), "brown heart", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\xa4"), "black heart", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x8d"), "white heart", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xaf"), "hundred points", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xa2"), "anger symbol", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xa5"), "collision", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xab"), "dizzy", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xa6"), "sweat droplets", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xa8"), "dashing away", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb3"), "hole", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xa3"), "bomb", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xac"), "speech balloon", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x81\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f\x97\xa8"), - "eye in speech bubble", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x81\xe2\x80\x8d\xf0\x9f\x97\xa8"), - "eye in speech bubble", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\xa8"), "left speech bubble", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\xaf"), "right anger bubble", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xad"), "thought balloon", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xa4"), "zzz", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8b"), "waving hand", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8b\xf0\x9f\x8f\xbb"), - "waving hand: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8b\xf0\x9f\x8f\xbc"), - "waving hand: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8b\xf0\x9f\x8f\xbd"), - "waving hand: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8b\xf0\x9f\x8f\xbe"), - "waving hand: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8b\xf0\x9f\x8f\xbf"), - "waving hand: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9a"), "raised back of hand", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9a\xf0\x9f\x8f\xbb"), - "raised back of hand: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9a\xf0\x9f\x8f\xbc"), - "raised back of hand: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9a\xf0\x9f\x8f\xbd"), - "raised back of hand: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9a\xf0\x9f\x8f\xbe"), - "raised back of hand: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9a\xf0\x9f\x8f\xbf"), - "raised back of hand: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x90"), - "hand with fingers splayed", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x90\xf0\x9f\x8f\xbb"), - "hand with fingers splayed: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x90\xf0\x9f\x8f\xbc"), - "hand with fingers splayed: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x90\xf0\x9f\x8f\xbd"), - "hand with fingers splayed: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x90\xf0\x9f\x8f\xbe"), - "hand with fingers splayed: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x90\xf0\x9f\x8f\xbf"), - "hand with fingers splayed: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8b"), "raised hand", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8b\xf0\x9f\x8f\xbb"), - "raised hand: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8b\xf0\x9f\x8f\xbc"), - "raised hand: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8b\xf0\x9f\x8f\xbd"), - "raised hand: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8b\xf0\x9f\x8f\xbe"), - "raised hand: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8b\xf0\x9f\x8f\xbf"), - "raised hand: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x96"), "vulcan salute", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x96\xf0\x9f\x8f\xbb"), - "vulcan salute: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x96\xf0\x9f\x8f\xbc"), - "vulcan salute: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x96\xf0\x9f\x8f\xbd"), - "vulcan salute: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x96\xf0\x9f\x8f\xbe"), - "vulcan salute: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x96\xf0\x9f\x8f\xbf"), - "vulcan salute: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8c"), "OK hand", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8c\xf0\x9f\x8f\xbb"), - "OK hand: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8c\xf0\x9f\x8f\xbc"), - "OK hand: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8c\xf0\x9f\x8f\xbd"), - "OK hand: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8c\xf0\x9f\x8f\xbe"), - "OK hand: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8c\xf0\x9f\x8f\xbf"), - "OK hand: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x8c"), "pinched fingers", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x8c\xf0\x9f\x8f\xbb"), - "pinched fingers: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x8c\xf0\x9f\x8f\xbc"), - "pinched fingers: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x8c\xf0\x9f\x8f\xbd"), - "pinched fingers: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x8c\xf0\x9f\x8f\xbe"), - "pinched fingers: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x8c\xf0\x9f\x8f\xbf"), - "pinched fingers: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x8f"), "pinching hand", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x8f\xf0\x9f\x8f\xbb"), - "pinching hand: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x8f\xf0\x9f\x8f\xbc"), - "pinching hand: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x8f\xf0\x9f\x8f\xbd"), - "pinching hand: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x8f\xf0\x9f\x8f\xbe"), - "pinching hand: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x8f\xf0\x9f\x8f\xbf"), - "pinching hand: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8c"), "victory hand", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8c\xf0\x9f\x8f\xbb"), - "victory hand: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8c\xf0\x9f\x8f\xbc"), - "victory hand: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8c\xf0\x9f\x8f\xbd"), - "victory hand: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8c\xf0\x9f\x8f\xbe"), - "victory hand: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8c\xf0\x9f\x8f\xbf"), - "victory hand: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9e"), "crossed fingers", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9e\xf0\x9f\x8f\xbb"), - "crossed fingers: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9e\xf0\x9f\x8f\xbc"), - "crossed fingers: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9e\xf0\x9f\x8f\xbd"), - "crossed fingers: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9e\xf0\x9f\x8f\xbe"), - "crossed fingers: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9e\xf0\x9f\x8f\xbf"), - "crossed fingers: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9f"), "love-you gesture", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9f\xf0\x9f\x8f\xbb"), - "love-you gesture: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9f\xf0\x9f\x8f\xbc"), - "love-you gesture: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9f\xf0\x9f\x8f\xbd"), - "love-you gesture: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9f\xf0\x9f\x8f\xbe"), - "love-you gesture: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9f\xf0\x9f\x8f\xbf"), - "love-you gesture: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x98"), "sign of the horns", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x98\xf0\x9f\x8f\xbb"), - "sign of the horns: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x98\xf0\x9f\x8f\xbc"), - "sign of the horns: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x98\xf0\x9f\x8f\xbd"), - "sign of the horns: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x98\xf0\x9f\x8f\xbe"), - "sign of the horns: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x98\xf0\x9f\x8f\xbf"), - "sign of the horns: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x99"), "call me hand", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x99\xf0\x9f\x8f\xbb"), - "call me hand: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x99\xf0\x9f\x8f\xbc"), - "call me hand: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x99\xf0\x9f\x8f\xbd"), - "call me hand: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x99\xf0\x9f\x8f\xbe"), - "call me hand: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x99\xf0\x9f\x8f\xbf"), - "call me hand: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x88"), - "backhand index pointing left", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x88\xf0\x9f\x8f\xbb"), - "backhand index pointing left: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x88\xf0\x9f\x8f\xbc"), - "backhand index pointing left: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x88\xf0\x9f\x8f\xbd"), - "backhand index pointing left: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x88\xf0\x9f\x8f\xbe"), - "backhand index pointing left: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x88\xf0\x9f\x8f\xbf"), - "backhand index pointing left: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x89"), - "backhand index pointing right", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x89\xf0\x9f\x8f\xbb"), - "backhand index pointing right: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x89\xf0\x9f\x8f\xbc"), - "backhand index pointing right: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x89\xf0\x9f\x8f\xbd"), - "backhand index pointing right: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x89\xf0\x9f\x8f\xbe"), - "backhand index pointing right: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x89\xf0\x9f\x8f\xbf"), - "backhand index pointing right: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x86"), - "backhand index pointing up", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x86\xf0\x9f\x8f\xbb"), - "backhand index pointing up: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x86\xf0\x9f\x8f\xbc"), - "backhand index pointing up: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x86\xf0\x9f\x8f\xbd"), - "backhand index pointing up: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x86\xf0\x9f\x8f\xbe"), - "backhand index pointing up: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x86\xf0\x9f\x8f\xbf"), - "backhand index pointing up: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x95"), "middle finger", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x95\xf0\x9f\x8f\xbb"), - "middle finger: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x95\xf0\x9f\x8f\xbc"), - "middle finger: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x95\xf0\x9f\x8f\xbd"), - "middle finger: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x95\xf0\x9f\x8f\xbe"), - "middle finger: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x95\xf0\x9f\x8f\xbf"), - "middle finger: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x87"), - "backhand index pointing down", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x87\xf0\x9f\x8f\xbb"), - "backhand index pointing down: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x87\xf0\x9f\x8f\xbc"), - "backhand index pointing down: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x87\xf0\x9f\x8f\xbd"), - "backhand index pointing down: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x87\xf0\x9f\x8f\xbe"), - "backhand index pointing down: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x87\xf0\x9f\x8f\xbf"), - "backhand index pointing down: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x98\x9d"), "index pointing up", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x98\x9d\xf0\x9f\x8f\xbb"), - "index pointing up: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x98\x9d\xf0\x9f\x8f\xbc"), - "index pointing up: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x98\x9d\xf0\x9f\x8f\xbd"), - "index pointing up: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x98\x9d\xf0\x9f\x8f\xbe"), - "index pointing up: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x98\x9d\xf0\x9f\x8f\xbf"), - "index pointing up: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8d"), "thumbs up", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8d\xf0\x9f\x8f\xbb"), - "thumbs up: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8d\xf0\x9f\x8f\xbc"), - "thumbs up: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8d\xf0\x9f\x8f\xbd"), - "thumbs up: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8d\xf0\x9f\x8f\xbe"), - "thumbs up: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8d\xf0\x9f\x8f\xbf"), - "thumbs up: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8e"), "thumbs down", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8e\xf0\x9f\x8f\xbb"), - "thumbs down: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8e\xf0\x9f\x8f\xbc"), - "thumbs down: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8e\xf0\x9f\x8f\xbd"), - "thumbs down: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8e\xf0\x9f\x8f\xbe"), - "thumbs down: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8e\xf0\x9f\x8f\xbf"), - "thumbs down: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8a"), "raised fist", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8a\xf0\x9f\x8f\xbb"), - "raised fist: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8a\xf0\x9f\x8f\xbc"), - "raised fist: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8a\xf0\x9f\x8f\xbd"), - "raised fist: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8a\xf0\x9f\x8f\xbe"), - "raised fist: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8a\xf0\x9f\x8f\xbf"), - "raised fist: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8a"), "oncoming fist", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8a\xf0\x9f\x8f\xbb"), - "oncoming fist: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8a\xf0\x9f\x8f\xbc"), - "oncoming fist: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8a\xf0\x9f\x8f\xbd"), - "oncoming fist: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8a\xf0\x9f\x8f\xbe"), - "oncoming fist: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8a\xf0\x9f\x8f\xbf"), - "oncoming fist: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9b"), "left-facing fist", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9b\xf0\x9f\x8f\xbb"), - "left-facing fist: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9b\xf0\x9f\x8f\xbc"), - "left-facing fist: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9b\xf0\x9f\x8f\xbd"), - "left-facing fist: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9b\xf0\x9f\x8f\xbe"), - "left-facing fist: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9b\xf0\x9f\x8f\xbf"), - "left-facing fist: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9c"), "right-facing fist", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9c\xf0\x9f\x8f\xbb"), - "right-facing fist: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9c\xf0\x9f\x8f\xbc"), - "right-facing fist: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9c\xf0\x9f\x8f\xbd"), - "right-facing fist: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9c\xf0\x9f\x8f\xbe"), - "right-facing fist: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9c\xf0\x9f\x8f\xbf"), - "right-facing fist: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8f"), "clapping hands", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8f\xf0\x9f\x8f\xbb"), - "clapping hands: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8f\xf0\x9f\x8f\xbc"), - "clapping hands: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8f\xf0\x9f\x8f\xbd"), - "clapping hands: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8f\xf0\x9f\x8f\xbe"), - "clapping hands: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8f\xf0\x9f\x8f\xbf"), - "clapping hands: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8c"), "raising hands", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8c\xf0\x9f\x8f\xbb"), - "raising hands: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8c\xf0\x9f\x8f\xbc"), - "raising hands: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8c\xf0\x9f\x8f\xbd"), - "raising hands: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8c\xf0\x9f\x8f\xbe"), - "raising hands: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8c\xf0\x9f\x8f\xbf"), - "raising hands: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x90"), "open hands", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x90\xf0\x9f\x8f\xbb"), - "open hands: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x90\xf0\x9f\x8f\xbc"), - "open hands: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x90\xf0\x9f\x8f\xbd"), - "open hands: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x90\xf0\x9f\x8f\xbe"), - "open hands: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x90\xf0\x9f\x8f\xbf"), - "open hands: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb2"), "palms up together", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb2\xf0\x9f\x8f\xbb"), - "palms up together: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb2\xf0\x9f\x8f\xbc"), - "palms up together: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb2\xf0\x9f\x8f\xbd"), - "palms up together: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb2\xf0\x9f\x8f\xbe"), - "palms up together: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb2\xf0\x9f\x8f\xbf"), - "palms up together: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9d"), "handshake", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8f"), "folded hands", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8f\xf0\x9f\x8f\xbb"), - "folded hands: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8f\xf0\x9f\x8f\xbc"), - "folded hands: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8f\xf0\x9f\x8f\xbd"), - "folded hands: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8f\xf0\x9f\x8f\xbe"), - "folded hands: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8f\xf0\x9f\x8f\xbf"), - "folded hands: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8d"), "writing hand", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8d\xf0\x9f\x8f\xbb"), - "writing hand: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8d\xf0\x9f\x8f\xbc"), - "writing hand: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8d\xf0\x9f\x8f\xbd"), - "writing hand: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8d\xf0\x9f\x8f\xbe"), - "writing hand: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9c\x8d\xf0\x9f\x8f\xbf"), - "writing hand: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x85"), "nail polish", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x85\xf0\x9f\x8f\xbb"), - "nail polish: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x85\xf0\x9f\x8f\xbc"), - "nail polish: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x85\xf0\x9f\x8f\xbd"), - "nail polish: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x85\xf0\x9f\x8f\xbe"), - "nail polish: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x85\xf0\x9f\x8f\xbf"), - "nail polish: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb3"), "selfie", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb3\xf0\x9f\x8f\xbb"), - "selfie: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb3\xf0\x9f\x8f\xbc"), - "selfie: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb3\xf0\x9f\x8f\xbd"), - "selfie: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb3\xf0\x9f\x8f\xbe"), - "selfie: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb3\xf0\x9f\x8f\xbf"), - "selfie: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xaa"), "flexed biceps", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xaa\xf0\x9f\x8f\xbb"), - "flexed biceps: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xaa\xf0\x9f\x8f\xbc"), - "flexed biceps: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xaa\xf0\x9f\x8f\xbd"), - "flexed biceps: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xaa\xf0\x9f\x8f\xbe"), - "flexed biceps: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xaa\xf0\x9f\x8f\xbf"), - "flexed biceps: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xbe"), "mechanical arm", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xbf"), "mechanical leg", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb5"), "leg", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb5\xf0\x9f\x8f\xbb"), - "leg: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb5\xf0\x9f\x8f\xbc"), - "leg: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb5\xf0\x9f\x8f\xbd"), - "leg: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb5\xf0\x9f\x8f\xbe"), - "leg: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb5\xf0\x9f\x8f\xbf"), - "leg: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb6"), "foot", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb6\xf0\x9f\x8f\xbb"), - "foot: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb6\xf0\x9f\x8f\xbc"), - "foot: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb6\xf0\x9f\x8f\xbd"), - "foot: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb6\xf0\x9f\x8f\xbe"), - "foot: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb6\xf0\x9f\x8f\xbf"), - "foot: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x82"), "ear", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x82\xf0\x9f\x8f\xbb"), - "ear: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x82\xf0\x9f\x8f\xbc"), - "ear: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x82\xf0\x9f\x8f\xbd"), - "ear: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x82\xf0\x9f\x8f\xbe"), - "ear: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x82\xf0\x9f\x8f\xbf"), - "ear: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xbb"), - "ear with hearing aid", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xbb\xf0\x9f\x8f\xbb"), - "ear with hearing aid: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xbb\xf0\x9f\x8f\xbc"), - "ear with hearing aid: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xbb\xf0\x9f\x8f\xbd"), - "ear with hearing aid: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xbb\xf0\x9f\x8f\xbe"), - "ear with hearing aid: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xbb\xf0\x9f\x8f\xbf"), - "ear with hearing aid: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x83"), "nose", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x83\xf0\x9f\x8f\xbb"), - "nose: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x83\xf0\x9f\x8f\xbc"), - "nose: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x83\xf0\x9f\x8f\xbd"), - "nose: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x83\xf0\x9f\x8f\xbe"), - "nose: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x83\xf0\x9f\x8f\xbf"), - "nose: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xa0"), "brain", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xab\x80"), "anatomical heart", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xab\x81"), "lungs", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb7"), "tooth", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb4"), "bone", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x80"), "eyes", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x81"), "eye", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x85"), "tongue", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x84"), "mouth", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb6"), "baby", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb6\xf0\x9f\x8f\xbb"), - "baby: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb6\xf0\x9f\x8f\xbc"), - "baby: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb6\xf0\x9f\x8f\xbd"), - "baby: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb6\xf0\x9f\x8f\xbe"), - "baby: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb6\xf0\x9f\x8f\xbf"), - "baby: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x92"), "child", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x92\xf0\x9f\x8f\xbb"), - "child: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x92\xf0\x9f\x8f\xbc"), - "child: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x92\xf0\x9f\x8f\xbd"), - "child: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x92\xf0\x9f\x8f\xbe"), - "child: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x92\xf0\x9f\x8f\xbf"), - "child: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa6"), "boy", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa6\xf0\x9f\x8f\xbb"), - "boy: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa6\xf0\x9f\x8f\xbc"), - "boy: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa6\xf0\x9f\x8f\xbd"), - "boy: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa6\xf0\x9f\x8f\xbe"), - "boy: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa6\xf0\x9f\x8f\xbf"), - "boy: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa7"), "girl", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa7\xf0\x9f\x8f\xbb"), - "girl: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa7\xf0\x9f\x8f\xbc"), - "girl: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa7\xf0\x9f\x8f\xbd"), - "girl: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa7\xf0\x9f\x8f\xbe"), - "girl: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa7\xf0\x9f\x8f\xbf"), - "girl: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91"), "person", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb"), - "person: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc"), - "person: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd"), - "person: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe"), - "person: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf"), - "person: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1"), "person: blond hair", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1\xf0\x9f\x8f\xbb"), - "person: light skin tone, blond hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1\xf0\x9f\x8f\xbc"), - "person: medium-light skin tone, blond hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1\xf0\x9f\x8f\xbd"), - "person: medium skin tone, blond hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1\xf0\x9f\x8f\xbe"), - "person: medium-dark skin tone, blond hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1\xf0\x9f\x8f\xbf"), - "person: dark skin tone, blond hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8"), "man", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb"), - "man: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc"), - "man: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd"), - "man: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe"), - "man: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf"), - "man: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x94"), "man: beard", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x94\xf0\x9f\x8f\xbb"), - "man: light skin tone, beard", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x94\xf0\x9f\x8f\xbc"), - "man: medium-light skin tone, beard", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x94\xf0\x9f\x8f\xbd"), - "man: medium skin tone, beard", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x94\xf0\x9f\x8f\xbe"), - "man: medium-dark skin tone, beard", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x94\xf0\x9f\x8f\xbf"), - "man: dark skin tone, beard", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "man: red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "man: light skin tone, red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "man: medium-light skin tone, red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "man: medium skin tone, red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "man: medium-dark skin tone, red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "man: dark skin tone, red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "man: curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "man: light skin tone, curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "man: medium-light skin tone, curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "man: medium skin tone, curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "man: medium-dark skin tone, curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "man: dark skin tone, curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "man: white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "man: light skin tone, white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "man: medium-light skin tone, white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "man: medium skin tone, white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "man: medium-dark skin tone, white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "man: dark skin tone, white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "man: bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "man: light skin tone, bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "man: medium-light skin tone, bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "man: medium skin tone, bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "man: medium-dark skin tone, bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "man: dark skin tone, bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9"), "woman", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb"), - "woman: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc"), - "woman: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd"), - "woman: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe"), - "woman: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf"), - "woman: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "woman: red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "woman: light skin tone, red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "woman: medium-light skin tone, red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "woman: medium skin tone, red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "woman: medium-dark skin tone, red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "woman: dark skin tone, red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "person: red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "person: light skin tone, red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "person: medium-light skin tone, red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "person: medium skin tone, red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "person: medium-dark skin tone, red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xb0"), - "person: dark skin tone, red hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "woman: curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "woman: light skin tone, curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "woman: medium-light skin tone, curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "woman: medium skin tone, curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "woman: medium-dark skin tone, curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "woman: dark skin tone, curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "person: curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "person: light skin tone, curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "person: medium-light skin tone, curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "person: medium skin tone, curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "person: medium-dark skin tone, curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xb1"), - "person: dark skin tone, curly hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "woman: white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "woman: light skin tone, white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "woman: medium-light skin tone, white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "woman: medium skin tone, white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "woman: medium-dark skin tone, white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "woman: dark skin tone, white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "person: white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "person: light skin tone, white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "person: medium-light skin tone, white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "person: medium skin tone, white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "person: medium-dark skin tone, white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xb3"), - "person: dark skin tone, white hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "woman: bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "woman: light skin tone, bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "woman: medium-light skin tone, bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "woman: medium skin tone, bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "woman: medium-dark skin tone, bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "woman: dark skin tone, bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "person: bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "person: light skin tone, bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "person: medium-light skin tone, bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "person: medium skin tone, bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "person: medium-dark skin tone, bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xb2"), - "person: dark skin tone, bald", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1\xe2\x80\x8d\xe2\x99\x80"), - "woman: blond hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman: light skin tone, blond hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman: medium-light skin tone, blond hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman: medium skin tone, blond hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman: medium-dark skin tone, blond hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman: dark skin tone, blond hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1\xe2\x80\x8d\xe2\x99\x82"), - "man: blond hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man: light skin tone, blond hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man: medium-light skin tone, blond hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man: medium skin tone, blond hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man: medium-dark skin tone, blond hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man: dark skin tone, blond hair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x93"), "older person", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x93\xf0\x9f\x8f\xbb"), - "older person: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x93\xf0\x9f\x8f\xbc"), - "older person: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x93\xf0\x9f\x8f\xbd"), - "older person: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x93\xf0\x9f\x8f\xbe"), - "older person: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x93\xf0\x9f\x8f\xbf"), - "older person: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb4"), "old man", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb4\xf0\x9f\x8f\xbb"), - "old man: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb4\xf0\x9f\x8f\xbc"), - "old man: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb4\xf0\x9f\x8f\xbd"), - "old man: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb4\xf0\x9f\x8f\xbe"), - "old man: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb4\xf0\x9f\x8f\xbf"), - "old man: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb5"), "old woman", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb5\xf0\x9f\x8f\xbb"), - "old woman: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb5\xf0\x9f\x8f\xbc"), - "old woman: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb5\xf0\x9f\x8f\xbd"), - "old woman: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb5\xf0\x9f\x8f\xbe"), - "old woman: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb5\xf0\x9f\x8f\xbf"), - "old woman: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d"), "person frowning", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d\xf0\x9f\x8f\xbb"), - "person frowning: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d\xf0\x9f\x8f\xbc"), - "person frowning: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d\xf0\x9f\x8f\xbd"), - "person frowning: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d\xf0\x9f\x8f\xbe"), - "person frowning: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d\xf0\x9f\x8f\xbf"), - "person frowning: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d\xe2\x80\x8d\xe2\x99\x82"), - "man frowning", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man frowning: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man frowning: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man frowning: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man frowning: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man frowning: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d\xe2\x80\x8d\xe2\x99\x80"), - "woman frowning", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman frowning: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman frowning: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman frowning: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman frowning: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman frowning: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e"), "person pouting", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e\xf0\x9f\x8f\xbb"), - "person pouting: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e\xf0\x9f\x8f\xbc"), - "person pouting: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e\xf0\x9f\x8f\xbd"), - "person pouting: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e\xf0\x9f\x8f\xbe"), - "person pouting: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e\xf0\x9f\x8f\xbf"), - "person pouting: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e\xe2\x80\x8d\xe2\x99\x82"), - "man pouting", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man pouting: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man pouting: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man pouting: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man pouting: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man pouting: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e\xe2\x80\x8d\xe2\x99\x80"), - "woman pouting", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman pouting: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman pouting: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman pouting: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman pouting: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman pouting: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85"), "person gesturing NO", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85\xf0\x9f\x8f\xbb"), - "person gesturing NO: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85\xf0\x9f\x8f\xbc"), - "person gesturing NO: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85\xf0\x9f\x8f\xbd"), - "person gesturing NO: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85\xf0\x9f\x8f\xbe"), - "person gesturing NO: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85\xf0\x9f\x8f\xbf"), - "person gesturing NO: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85\xe2\x80\x8d\xe2\x99\x82"), - "man gesturing NO", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man gesturing NO: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man gesturing NO: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man gesturing NO: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man gesturing NO: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man gesturing NO: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85\xe2\x80\x8d\xe2\x99\x80"), - "woman gesturing NO", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman gesturing NO: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman gesturing NO: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman gesturing NO: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman gesturing NO: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman gesturing NO: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86"), "person gesturing OK", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86\xf0\x9f\x8f\xbb"), - "person gesturing OK: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86\xf0\x9f\x8f\xbc"), - "person gesturing OK: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86\xf0\x9f\x8f\xbd"), - "person gesturing OK: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86\xf0\x9f\x8f\xbe"), - "person gesturing OK: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86\xf0\x9f\x8f\xbf"), - "person gesturing OK: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86\xe2\x80\x8d\xe2\x99\x82"), - "man gesturing OK", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man gesturing OK: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man gesturing OK: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man gesturing OK: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man gesturing OK: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man gesturing OK: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86\xe2\x80\x8d\xe2\x99\x80"), - "woman gesturing OK", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman gesturing OK: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman gesturing OK: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman gesturing OK: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman gesturing OK: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman gesturing OK: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81"), "person tipping hand", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81\xf0\x9f\x8f\xbb"), - "person tipping hand: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81\xf0\x9f\x8f\xbc"), - "person tipping hand: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81\xf0\x9f\x8f\xbd"), - "person tipping hand: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81\xf0\x9f\x8f\xbe"), - "person tipping hand: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81\xf0\x9f\x8f\xbf"), - "person tipping hand: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81\xe2\x80\x8d\xe2\x99\x82"), - "man tipping hand", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man tipping hand: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man tipping hand: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man tipping hand: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man tipping hand: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man tipping hand: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81\xe2\x80\x8d\xe2\x99\x80"), - "woman tipping hand", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman tipping hand: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman tipping hand: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman tipping hand: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman tipping hand: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x81\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman tipping hand: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b"), "person raising hand", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b\xf0\x9f\x8f\xbb"), - "person raising hand: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b\xf0\x9f\x8f\xbc"), - "person raising hand: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b\xf0\x9f\x8f\xbd"), - "person raising hand: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b\xf0\x9f\x8f\xbe"), - "person raising hand: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b\xf0\x9f\x8f\xbf"), - "person raising hand: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b\xe2\x80\x8d\xe2\x99\x82"), - "man raising hand", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man raising hand: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man raising hand: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man raising hand: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man raising hand: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man raising hand: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b\xe2\x80\x8d\xe2\x99\x80"), - "woman raising hand", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman raising hand: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman raising hand: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman raising hand: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman raising hand: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman raising hand: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f"), "deaf person", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f\xf0\x9f\x8f\xbb"), - "deaf person: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f\xf0\x9f\x8f\xbc"), - "deaf person: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f\xf0\x9f\x8f\xbd"), - "deaf person: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f\xf0\x9f\x8f\xbe"), - "deaf person: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f\xf0\x9f\x8f\xbf"), - "deaf person: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f\xe2\x80\x8d\xe2\x99\x82"), - "deaf man", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "deaf man: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "deaf man: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "deaf man: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "deaf man: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "deaf man: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f\xe2\x80\x8d\xe2\x99\x80"), - "deaf woman", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "deaf woman: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "deaf woman: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "deaf woman: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "deaf woman: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8f\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "deaf woman: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87"), "person bowing", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87\xf0\x9f\x8f\xbb"), - "person bowing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87\xf0\x9f\x8f\xbc"), - "person bowing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87\xf0\x9f\x8f\xbd"), - "person bowing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87\xf0\x9f\x8f\xbe"), - "person bowing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87\xf0\x9f\x8f\xbf"), - "person bowing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87\xe2\x80\x8d\xe2\x99\x82"), - "man bowing", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man bowing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man bowing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man bowing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man bowing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man bowing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87\xe2\x80\x8d\xe2\x99\x80"), - "woman bowing", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman bowing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman bowing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman bowing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman bowing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x99\x87\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman bowing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6"), "person facepalming", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6\xf0\x9f\x8f\xbb"), - "person facepalming: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6\xf0\x9f\x8f\xbc"), - "person facepalming: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6\xf0\x9f\x8f\xbd"), - "person facepalming: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6\xf0\x9f\x8f\xbe"), - "person facepalming: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6\xf0\x9f\x8f\xbf"), - "person facepalming: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6\xe2\x80\x8d\xe2\x99\x82"), - "man facepalming", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man facepalming: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man facepalming: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man facepalming: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man facepalming: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man facepalming: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6\xe2\x80\x8d\xe2\x99\x80"), - "woman facepalming", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman facepalming: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman facepalming: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman facepalming: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman facepalming: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman facepalming: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7"), "person shrugging", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7\xf0\x9f\x8f\xbb"), - "person shrugging: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7\xf0\x9f\x8f\xbc"), - "person shrugging: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7\xf0\x9f\x8f\xbd"), - "person shrugging: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7\xf0\x9f\x8f\xbe"), - "person shrugging: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7\xf0\x9f\x8f\xbf"), - "person shrugging: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7\xe2\x80\x8d\xe2\x99\x82"), - "man shrugging", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man shrugging: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man shrugging: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man shrugging: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man shrugging: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man shrugging: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7\xe2\x80\x8d\xe2\x99\x80"), - "woman shrugging", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman shrugging: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman shrugging: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman shrugging: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman shrugging: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman shrugging: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xe2\x9a\x95"), - "health worker", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x9a\x95"), - "health worker: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x9a\x95"), - "health worker: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x9a\x95"), - "health worker: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x9a\x95"), - "health worker: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x9a\x95"), - "health worker: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xe2\x9a\x95"), - "man health worker", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x9a\x95"), - "man health worker: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x9a\x95"), - "man health worker: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x9a\x95"), - "man health worker: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x9a\x95"), - "man health worker: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x9a\x95"), - "man health worker: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9a\x95"), - "woman health worker", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x9a\x95"), - "woman health worker: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x9a\x95"), - "woman health worker: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x9a\x95"), - "woman health worker: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x9a\x95"), - "woman health worker: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x9a\x95"), - "woman health worker: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "student", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "student: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "student: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "student: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "student: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "student: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "man student", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "man student: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "man student: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "man student: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "man student: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "man student: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "woman student", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "woman student: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "woman student: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "woman student: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "woman student: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8e\x93"), - "woman student: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "teacher", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "teacher: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "teacher: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "teacher: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "teacher: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "teacher: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "man teacher", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "man teacher: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "man teacher: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "man teacher: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "man teacher: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "man teacher: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "woman teacher", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "woman teacher: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "woman teacher: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "woman teacher: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "woman teacher: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8f\xab"), - "woman teacher: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xe2\x9a\x96"), - "judge", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x9a\x96"), - "judge: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x9a\x96"), - "judge: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x9a\x96"), - "judge: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x9a\x96"), - "judge: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x9a\x96"), - "judge: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xe2\x9a\x96"), - "man judge", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x9a\x96"), - "man judge: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x9a\x96"), - "man judge: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x9a\x96"), - "man judge: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x9a\x96"), - "man judge: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x9a\x96"), - "man judge: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9a\x96"), - "woman judge", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x9a\x96"), - "woman judge: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x9a\x96"), - "woman judge: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x9a\x96"), - "woman judge: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x9a\x96"), - "woman judge: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x9a\x96"), - "woman judge: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "farmer", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "farmer: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "farmer: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "farmer: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "farmer: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "farmer: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "man farmer", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "man farmer: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "man farmer: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "man farmer: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "man farmer: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "man farmer: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "woman farmer", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "woman farmer: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "woman farmer: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "woman farmer: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "woman farmer: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8c\xbe"), - "woman farmer: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "cook", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "cook: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "cook: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "cook: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "cook: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "cook: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "man cook", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "man cook: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "man cook: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "man cook: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "man cook: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "man cook: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "woman cook", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "woman cook: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "woman cook: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "woman cook: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "woman cook: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8d\xb3"), - "woman cook: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "mechanic", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "mechanic: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "mechanic: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "mechanic: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "mechanic: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "mechanic: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "man mechanic", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "man mechanic: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "man mechanic: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "man mechanic: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "man mechanic: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "man mechanic: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "woman mechanic", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "woman mechanic: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "woman mechanic: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "woman mechanic: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "woman mechanic: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x94\xa7"), - "woman mechanic: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "factory worker", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "factory worker: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "factory worker: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "factory worker: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "factory worker: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "factory worker: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "man factory worker", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "man factory worker: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "man factory worker: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "man factory worker: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "man factory worker: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "man factory worker: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "woman factory worker", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "woman factory worker: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "woman factory worker: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "woman factory worker: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "woman factory worker: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8f\xad"), - "woman factory worker: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "office worker", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "office worker: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "office worker: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "office worker: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "office worker: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "office worker: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "man office worker", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "man office worker: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "man office worker: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "man office worker: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "man office worker: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "man office worker: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "woman office worker", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "woman office worker: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "woman office worker: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "woman office worker: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "woman office worker: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x92\xbc"), - "woman office worker: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x94\xac"), - "scientist", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x94\xac"), - "scientist: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x94\xac"), - "scientist: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x94\xac"), - "scientist: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x94\xac"), - "scientist: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x94\xac"), - "scientist: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x94\xac"), - "man scientist", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x94\xac"), - "man scientist: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x94\xac"), - "man scientist: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x94\xac"), - "man scientist: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x94\xac"), - "man scientist: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x94\xac"), - "man scientist: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x94\xac"), - "woman scientist", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x94\xac"), - "woman scientist: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x94\xac"), - "woman scientist: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x94\xac"), - "woman scientist: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x94\xac"), - "woman scientist: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x94\xac"), - "woman scientist: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "technologist", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "technologist: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "technologist: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "technologist: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "technologist: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "technologist: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "man technologist", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "man technologist: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "man technologist: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "man technologist: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "man technologist: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "man technologist: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "woman technologist", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "woman technologist: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "woman technologist: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "woman technologist: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "woman technologist: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x92\xbb"), - "woman technologist: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "singer", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "singer: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "singer: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "singer: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "singer: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "singer: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "man singer", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "man singer: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "man singer: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "man singer: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "man singer: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "man singer: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "woman singer", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "woman singer: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "woman singer: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "woman singer: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "woman singer: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8e\xa4"), - "woman singer: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "artist", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "artist: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "artist: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "artist: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "artist: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "artist: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "man artist", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "man artist: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "man artist: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "man artist: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "man artist: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "man artist: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "woman artist", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "woman artist: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "woman artist: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "woman artist: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "woman artist: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8e\xa8"), - "woman artist: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xe2\x9c\x88"), - "pilot", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x9c\x88"), - "pilot: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x9c\x88"), - "pilot: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x9c\x88"), - "pilot: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x9c\x88"), - "pilot: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x9c\x88"), - "pilot: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xe2\x9c\x88"), - "man pilot", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x9c\x88"), - "man pilot: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x9c\x88"), - "man pilot: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x9c\x88"), - "man pilot: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x9c\x88"), - "man pilot: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x9c\x88"), - "man pilot: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9c\x88"), - "woman pilot", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x9c\x88"), - "woman pilot: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x9c\x88"), - "woman pilot: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x9c\x88"), - "woman pilot: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x9c\x88"), - "woman pilot: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x9c\x88"), - "woman pilot: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "astronaut", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "astronaut: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "astronaut: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "astronaut: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "astronaut: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "astronaut: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "man astronaut", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "man astronaut: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "man astronaut: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "man astronaut: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "man astronaut: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "man astronaut: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "woman astronaut", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "woman astronaut: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "woman astronaut: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "woman astronaut: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "woman astronaut: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x9a\x80"), - "woman astronaut: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "firefighter", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "firefighter: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "firefighter: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "firefighter: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "firefighter: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "firefighter: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "man firefighter", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "man firefighter: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "man firefighter: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "man firefighter: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "man firefighter: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "man firefighter: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "woman firefighter", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "woman firefighter: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "woman firefighter: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "woman firefighter: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "woman firefighter: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x9a\x92"), - "woman firefighter: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae"), "police officer", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae\xf0\x9f\x8f\xbb"), - "police officer: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae\xf0\x9f\x8f\xbc"), - "police officer: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae\xf0\x9f\x8f\xbd"), - "police officer: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae\xf0\x9f\x8f\xbe"), - "police officer: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae\xf0\x9f\x8f\xbf"), - "police officer: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae\xe2\x80\x8d\xe2\x99\x82"), - "man police officer", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man police officer: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man police officer: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man police officer: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man police officer: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man police officer: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae\xe2\x80\x8d\xe2\x99\x80"), - "woman police officer", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman police officer: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman police officer: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman police officer: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman police officer: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xae\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman police officer: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5"), "detective", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xf0\x9f\x8f\xbb"), - "detective: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xf0\x9f\x8f\xbc"), - "detective: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xf0\x9f\x8f\xbd"), - "detective: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xf0\x9f\x8f\xbe"), - "detective: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xf0\x9f\x8f\xbf"), - "detective: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x82"), - "man detective", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xe2\x80\x8d\xe2\x99\x82"), - "man detective", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man detective: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man detective: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man detective: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man detective: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man detective: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x80"), - "woman detective", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xe2\x80\x8d\xe2\x99\x80"), - "woman detective", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman detective: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman detective: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman detective: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman detective: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman detective: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82"), "guard", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82\xf0\x9f\x8f\xbb"), - "guard: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82\xf0\x9f\x8f\xbc"), - "guard: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82\xf0\x9f\x8f\xbd"), - "guard: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82\xf0\x9f\x8f\xbe"), - "guard: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82\xf0\x9f\x8f\xbf"), - "guard: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82\xe2\x80\x8d\xe2\x99\x82"), - "man guard", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man guard: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man guard: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man guard: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man guard: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man guard: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82\xe2\x80\x8d\xe2\x99\x80"), - "woman guard", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman guard: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman guard: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman guard: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman guard: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman guard: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7"), "construction worker", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7\xf0\x9f\x8f\xbb"), - "construction worker: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7\xf0\x9f\x8f\xbc"), - "construction worker: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7\xf0\x9f\x8f\xbd"), - "construction worker: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7\xf0\x9f\x8f\xbe"), - "construction worker: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7\xf0\x9f\x8f\xbf"), - "construction worker: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7\xe2\x80\x8d\xe2\x99\x82"), - "man construction worker", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man construction worker: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man construction worker: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man construction worker: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man construction worker: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man construction worker: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7\xe2\x80\x8d\xe2\x99\x80"), - "woman construction worker", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman construction worker: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman construction worker: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman construction worker: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman construction worker: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman construction worker: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb4"), "prince", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb4\xf0\x9f\x8f\xbb"), - "prince: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb4\xf0\x9f\x8f\xbc"), - "prince: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb4\xf0\x9f\x8f\xbd"), - "prince: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb4\xf0\x9f\x8f\xbe"), - "prince: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb4\xf0\x9f\x8f\xbf"), - "prince: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb8"), "princess", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb8\xf0\x9f\x8f\xbb"), - "princess: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb8\xf0\x9f\x8f\xbc"), - "princess: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb8\xf0\x9f\x8f\xbd"), - "princess: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb8\xf0\x9f\x8f\xbe"), - "princess: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb8\xf0\x9f\x8f\xbf"), - "princess: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3"), - "person wearing turban", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3\xf0\x9f\x8f\xbb"), - "person wearing turban: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3\xf0\x9f\x8f\xbc"), - "person wearing turban: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3\xf0\x9f\x8f\xbd"), - "person wearing turban: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3\xf0\x9f\x8f\xbe"), - "person wearing turban: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3\xf0\x9f\x8f\xbf"), - "person wearing turban: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3\xe2\x80\x8d\xe2\x99\x82"), - "man wearing turban", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man wearing turban: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man wearing turban: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man wearing turban: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man wearing turban: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man wearing turban: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3\xe2\x80\x8d\xe2\x99\x80"), - "woman wearing turban", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman wearing turban: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman wearing turban: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman wearing turban: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman wearing turban: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman wearing turban: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb2"), "man with skullcap", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb2\xf0\x9f\x8f\xbb"), - "man with skullcap: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb2\xf0\x9f\x8f\xbc"), - "man with skullcap: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb2\xf0\x9f\x8f\xbd"), - "man with skullcap: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb2\xf0\x9f\x8f\xbe"), - "man with skullcap: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb2\xf0\x9f\x8f\xbf"), - "man with skullcap: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x95"), - "woman with headscarf", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x95\xf0\x9f\x8f\xbb"), - "woman with headscarf: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x95\xf0\x9f\x8f\xbc"), - "woman with headscarf: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x95\xf0\x9f\x8f\xbd"), - "woman with headscarf: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x95\xf0\x9f\x8f\xbe"), - "woman with headscarf: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x95\xf0\x9f\x8f\xbf"), - "woman with headscarf: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5"), "man in tuxedo", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5\xf0\x9f\x8f\xbb"), - "man in tuxedo: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5\xf0\x9f\x8f\xbc"), - "man in tuxedo: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5\xf0\x9f\x8f\xbd"), - "man in tuxedo: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5\xf0\x9f\x8f\xbe"), - "man in tuxedo: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5\xf0\x9f\x8f\xbf"), - "man in tuxedo: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5\xe2\x80\x8d\xe2\x99\x82"), - "man in tuxedo", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man in tuxedo: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man in tuxedo: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man in tuxedo: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man in tuxedo: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man in tuxedo: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5\xe2\x80\x8d\xe2\x99\x80"), - "woman in tuxedo", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman in tuxedo: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman in tuxedo: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman in tuxedo: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman in tuxedo: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman in tuxedo: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0"), "bride with veil", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0\xf0\x9f\x8f\xbb"), - "bride with veil: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0\xf0\x9f\x8f\xbc"), - "bride with veil: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0\xf0\x9f\x8f\xbd"), - "bride with veil: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0\xf0\x9f\x8f\xbe"), - "bride with veil: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0\xf0\x9f\x8f\xbf"), - "bride with veil: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0\xe2\x80\x8d\xe2\x99\x82"), - "man with veil", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man with veil: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man with veil: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man with veil: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man with veil: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man with veil: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0\xe2\x80\x8d\xe2\x99\x80"), - "woman with veil", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman with veil: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman with veil: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman with veil: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman with veil: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman with veil: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb0"), "pregnant woman", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb0\xf0\x9f\x8f\xbb"), - "pregnant woman: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb0\xf0\x9f\x8f\xbc"), - "pregnant woman: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb0\xf0\x9f\x8f\xbd"), - "pregnant woman: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb0\xf0\x9f\x8f\xbe"), - "pregnant woman: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb0\xf0\x9f\x8f\xbf"), - "pregnant woman: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb1"), "breast-feeding", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb1\xf0\x9f\x8f\xbb"), - "breast-feeding: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb1\xf0\x9f\x8f\xbc"), - "breast-feeding: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb1\xf0\x9f\x8f\xbd"), - "breast-feeding: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb1\xf0\x9f\x8f\xbe"), - "breast-feeding: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb1\xf0\x9f\x8f\xbf"), - "breast-feeding: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "woman feeding baby", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "woman feeding baby: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "woman feeding baby: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "woman feeding baby: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "woman feeding baby: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "woman feeding baby: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "man feeding baby", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "man feeding baby: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "man feeding baby: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "man feeding baby: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "man feeding baby: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "man feeding baby: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "person feeding baby", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "person feeding baby: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "person feeding baby: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "person feeding baby: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "person feeding baby: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8d\xbc"), - "person feeding baby: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xbc"), "baby angel", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xbc\xf0\x9f\x8f\xbb"), - "baby angel: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xbc\xf0\x9f\x8f\xbc"), - "baby angel: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xbc\xf0\x9f\x8f\xbd"), - "baby angel: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xbc\xf0\x9f\x8f\xbe"), - "baby angel: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xbc\xf0\x9f\x8f\xbf"), - "baby angel: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x85"), "Santa Claus", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x85\xf0\x9f\x8f\xbb"), - "Santa Claus: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x85\xf0\x9f\x8f\xbc"), - "Santa Claus: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x85\xf0\x9f\x8f\xbd"), - "Santa Claus: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x85\xf0\x9f\x8f\xbe"), - "Santa Claus: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x85\xf0\x9f\x8f\xbf"), - "Santa Claus: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb6"), "Mrs. Claus", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb6\xf0\x9f\x8f\xbb"), - "Mrs. Claus: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb6\xf0\x9f\x8f\xbc"), - "Mrs. Claus: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb6\xf0\x9f\x8f\xbd"), - "Mrs. Claus: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb6\xf0\x9f\x8f\xbe"), - "Mrs. Claus: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb6\xf0\x9f\x8f\xbf"), - "Mrs. Claus: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\x8e\x84"), - "mx claus", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\x8e\x84"), - "mx claus: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\x8e\x84"), - "mx claus: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\x8e\x84"), - "mx claus: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\x8e\x84"), - "mx claus: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\x8e\x84"), - "mx claus: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8"), "superhero", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8\xf0\x9f\x8f\xbb"), - "superhero: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8\xf0\x9f\x8f\xbc"), - "superhero: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8\xf0\x9f\x8f\xbd"), - "superhero: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8\xf0\x9f\x8f\xbe"), - "superhero: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8\xf0\x9f\x8f\xbf"), - "superhero: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8\xe2\x80\x8d\xe2\x99\x82"), - "man superhero", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man superhero: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man superhero: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man superhero: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man superhero: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man superhero: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8\xe2\x80\x8d\xe2\x99\x80"), - "woman superhero", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman superhero: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman superhero: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman superhero: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman superhero: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman superhero: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9"), "supervillain", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9\xf0\x9f\x8f\xbb"), - "supervillain: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9\xf0\x9f\x8f\xbc"), - "supervillain: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9\xf0\x9f\x8f\xbd"), - "supervillain: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9\xf0\x9f\x8f\xbe"), - "supervillain: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9\xf0\x9f\x8f\xbf"), - "supervillain: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9\xe2\x80\x8d\xe2\x99\x82"), - "man supervillain", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man supervillain: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man supervillain: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man supervillain: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man supervillain: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man supervillain: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9\xe2\x80\x8d\xe2\x99\x80"), - "woman supervillain", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman supervillain: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman supervillain: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman supervillain: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman supervillain: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xb9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman supervillain: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99"), "mage", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99\xf0\x9f\x8f\xbb"), - "mage: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99\xf0\x9f\x8f\xbc"), - "mage: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99\xf0\x9f\x8f\xbd"), - "mage: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99\xf0\x9f\x8f\xbe"), - "mage: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99\xf0\x9f\x8f\xbf"), - "mage: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99\xe2\x80\x8d\xe2\x99\x82"), - "man mage", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man mage: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man mage: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man mage: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man mage: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man mage: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99\xe2\x80\x8d\xe2\x99\x80"), - "woman mage", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman mage: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman mage: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman mage: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman mage: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x99\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman mage: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a"), "fairy", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a\xf0\x9f\x8f\xbb"), - "fairy: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a\xf0\x9f\x8f\xbc"), - "fairy: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a\xf0\x9f\x8f\xbd"), - "fairy: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a\xf0\x9f\x8f\xbe"), - "fairy: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a\xf0\x9f\x8f\xbf"), - "fairy: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a\xe2\x80\x8d\xe2\x99\x82"), - "man fairy", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man fairy: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man fairy: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man fairy: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man fairy: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man fairy: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a\xe2\x80\x8d\xe2\x99\x80"), - "woman fairy", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman fairy: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman fairy: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman fairy: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman fairy: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9a\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman fairy: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b"), "vampire", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b\xf0\x9f\x8f\xbb"), - "vampire: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b\xf0\x9f\x8f\xbc"), - "vampire: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b\xf0\x9f\x8f\xbd"), - "vampire: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b\xf0\x9f\x8f\xbe"), - "vampire: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b\xf0\x9f\x8f\xbf"), - "vampire: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b\xe2\x80\x8d\xe2\x99\x82"), - "man vampire", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man vampire: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man vampire: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man vampire: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man vampire: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man vampire: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b\xe2\x80\x8d\xe2\x99\x80"), - "woman vampire", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman vampire: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman vampire: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman vampire: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman vampire: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9b\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman vampire: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c"), "merperson", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c\xf0\x9f\x8f\xbb"), - "merperson: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c\xf0\x9f\x8f\xbc"), - "merperson: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c\xf0\x9f\x8f\xbd"), - "merperson: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c\xf0\x9f\x8f\xbe"), - "merperson: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c\xf0\x9f\x8f\xbf"), - "merperson: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c\xe2\x80\x8d\xe2\x99\x82"), - "merman", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "merman: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "merman: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "merman: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "merman: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "merman: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c\xe2\x80\x8d\xe2\x99\x80"), - "mermaid", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "mermaid: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "mermaid: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "mermaid: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "mermaid: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9c\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "mermaid: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d"), "elf", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d\xf0\x9f\x8f\xbb"), - "elf: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d\xf0\x9f\x8f\xbc"), - "elf: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d\xf0\x9f\x8f\xbd"), - "elf: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d\xf0\x9f\x8f\xbe"), - "elf: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d\xf0\x9f\x8f\xbf"), - "elf: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d\xe2\x80\x8d\xe2\x99\x82"), - "man elf", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man elf: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man elf: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man elf: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man elf: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man elf: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d\xe2\x80\x8d\xe2\x99\x80"), - "woman elf", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman elf: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman elf: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman elf: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman elf: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9d\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman elf: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9e"), "genie", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9e\xe2\x80\x8d\xe2\x99\x82"), - "man genie", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9e\xe2\x80\x8d\xe2\x99\x80"), - "woman genie", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9f"), "zombie", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9f\xe2\x80\x8d\xe2\x99\x82"), - "man zombie", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x9f\xe2\x80\x8d\xe2\x99\x80"), - "woman zombie", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86"), - "person getting massage", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86\xf0\x9f\x8f\xbb"), - "person getting massage: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86\xf0\x9f\x8f\xbc"), - "person getting massage: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86\xf0\x9f\x8f\xbd"), - "person getting massage: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86\xf0\x9f\x8f\xbe"), - "person getting massage: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86\xf0\x9f\x8f\xbf"), - "person getting massage: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86\xe2\x80\x8d\xe2\x99\x82"), - "man getting massage", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man getting massage: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man getting massage: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man getting massage: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man getting massage: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man getting massage: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86\xe2\x80\x8d\xe2\x99\x80"), - "woman getting massage", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman getting massage: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman getting massage: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman getting massage: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman getting massage: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman getting massage: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87"), - "person getting haircut", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87\xf0\x9f\x8f\xbb"), - "person getting haircut: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87\xf0\x9f\x8f\xbc"), - "person getting haircut: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87\xf0\x9f\x8f\xbd"), - "person getting haircut: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87\xf0\x9f\x8f\xbe"), - "person getting haircut: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87\xf0\x9f\x8f\xbf"), - "person getting haircut: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87\xe2\x80\x8d\xe2\x99\x82"), - "man getting haircut", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man getting haircut: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man getting haircut: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man getting haircut: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man getting haircut: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man getting haircut: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87\xe2\x80\x8d\xe2\x99\x80"), - "woman getting haircut", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman getting haircut: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman getting haircut: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman getting haircut: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman getting haircut: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman getting haircut: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6"), "person walking", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6\xf0\x9f\x8f\xbb"), - "person walking: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6\xf0\x9f\x8f\xbc"), - "person walking: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6\xf0\x9f\x8f\xbd"), - "person walking: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6\xf0\x9f\x8f\xbe"), - "person walking: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6\xf0\x9f\x8f\xbf"), - "person walking: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6\xe2\x80\x8d\xe2\x99\x82"), - "man walking", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man walking: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man walking: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man walking: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man walking: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man walking: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6\xe2\x80\x8d\xe2\x99\x80"), - "woman walking", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman walking: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman walking: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman walking: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman walking: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman walking: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d"), "person standing", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d\xf0\x9f\x8f\xbb"), - "person standing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d\xf0\x9f\x8f\xbc"), - "person standing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d\xf0\x9f\x8f\xbd"), - "person standing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d\xf0\x9f\x8f\xbe"), - "person standing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d\xf0\x9f\x8f\xbf"), - "person standing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d\xe2\x80\x8d\xe2\x99\x82"), - "man standing", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man standing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man standing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man standing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man standing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man standing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d\xe2\x80\x8d\xe2\x99\x80"), - "woman standing", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman standing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman standing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman standing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman standing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8d\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman standing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e"), "person kneeling", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e\xf0\x9f\x8f\xbb"), - "person kneeling: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e\xf0\x9f\x8f\xbc"), - "person kneeling: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e\xf0\x9f\x8f\xbd"), - "person kneeling: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e\xf0\x9f\x8f\xbe"), - "person kneeling: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e\xf0\x9f\x8f\xbf"), - "person kneeling: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e\xe2\x80\x8d\xe2\x99\x82"), - "man kneeling", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man kneeling: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man kneeling: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man kneeling: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man kneeling: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man kneeling: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e\xe2\x80\x8d\xe2\x99\x80"), - "woman kneeling", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman kneeling: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman kneeling: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman kneeling: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman kneeling: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8e\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman kneeling: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "person with probing cane", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "person with probing cane: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "person with probing cane: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "person with probing cane: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "person with probing cane: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "person with probing cane: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "man with probing cane", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "man with probing cane: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "man with probing cane: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "man with probing cane: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "man with probing cane: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "man with probing cane: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "woman with probing cane", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "woman with probing cane: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "woman with probing cane: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "woman with probing cane: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "woman with probing cane: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xaf"), - "woman with probing cane: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "person in motorized wheelchair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "person in motorized wheelchair: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "person in motorized wheelchair: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "person in motorized wheelchair: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "person in motorized wheelchair: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "person in motorized wheelchair: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "man in motorized wheelchair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "man in motorized wheelchair: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "man in motorized wheelchair: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "man in motorized wheelchair: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "man in motorized wheelchair: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "man in motorized wheelchair: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "woman in motorized wheelchair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "woman in motorized wheelchair: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "woman in motorized wheelchair: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "woman in motorized wheelchair: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "woman in motorized wheelchair: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xbc"), - "woman in motorized wheelchair: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "person in manual wheelchair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "person in manual wheelchair: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "person in manual wheelchair: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "person in manual wheelchair: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "person in manual wheelchair: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "person in manual wheelchair: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "man in manual wheelchair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "man in manual wheelchair: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "man in manual wheelchair: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "man in manual wheelchair: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "man in manual wheelchair: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "man in manual wheelchair: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "woman in manual wheelchair", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "woman in manual wheelchair: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "woman in manual wheelchair: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "woman in manual wheelchair: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "woman in manual wheelchair: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa6\xbd"), - "woman in manual wheelchair: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83"), "person running", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83\xf0\x9f\x8f\xbb"), - "person running: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83\xf0\x9f\x8f\xbc"), - "person running: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83\xf0\x9f\x8f\xbd"), - "person running: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83\xf0\x9f\x8f\xbe"), - "person running: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83\xf0\x9f\x8f\xbf"), - "person running: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83\xe2\x80\x8d\xe2\x99\x82"), - "man running", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man running: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man running: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man running: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man running: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man running: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83\xe2\x80\x8d\xe2\x99\x80"), - "woman running", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman running: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman running: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman running: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman running: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman running: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x83"), "woman dancing", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x83\xf0\x9f\x8f\xbb"), - "woman dancing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x83\xf0\x9f\x8f\xbc"), - "woman dancing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x83\xf0\x9f\x8f\xbd"), - "woman dancing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x83\xf0\x9f\x8f\xbe"), - "woman dancing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x83\xf0\x9f\x8f\xbf"), - "woman dancing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xba"), "man dancing", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xba\xf0\x9f\x8f\xbb"), - "man dancing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xba\xf0\x9f\x8f\xbc"), - "man dancing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xba\xf0\x9f\x8f\xbd"), - "man dancing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xba\xf0\x9f\x8f\xbe"), - "man dancing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xba\xf0\x9f\x8f\xbf"), - "man dancing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb4"), - "man in suit levitating", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb4\xf0\x9f\x8f\xbb"), - "man in suit levitating: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb4\xf0\x9f\x8f\xbc"), - "man in suit levitating: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb4\xf0\x9f\x8f\xbd"), - "man in suit levitating: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb4\xf0\x9f\x8f\xbe"), - "man in suit levitating: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb4\xf0\x9f\x8f\xbf"), - "man in suit levitating: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xaf"), - "people with bunny ears", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xaf\xe2\x80\x8d\xe2\x99\x82"), - "men with bunny ears", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xaf\xe2\x80\x8d\xe2\x99\x80"), - "women with bunny ears", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96"), - "person in steamy room", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96\xf0\x9f\x8f\xbb"), - "person in steamy room: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96\xf0\x9f\x8f\xbc"), - "person in steamy room: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96\xf0\x9f\x8f\xbd"), - "person in steamy room: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96\xf0\x9f\x8f\xbe"), - "person in steamy room: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96\xf0\x9f\x8f\xbf"), - "person in steamy room: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96\xe2\x80\x8d\xe2\x99\x82"), - "man in steamy room", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man in steamy room: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man in steamy room: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man in steamy room: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man in steamy room: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man in steamy room: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96\xe2\x80\x8d\xe2\x99\x80"), - "woman in steamy room", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman in steamy room: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman in steamy room: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman in steamy room: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman in steamy room: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x96\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman in steamy room: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97"), "person climbing", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97\xf0\x9f\x8f\xbb"), - "person climbing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97\xf0\x9f\x8f\xbc"), - "person climbing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97\xf0\x9f\x8f\xbd"), - "person climbing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97\xf0\x9f\x8f\xbe"), - "person climbing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97\xf0\x9f\x8f\xbf"), - "person climbing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97\xe2\x80\x8d\xe2\x99\x82"), - "man climbing", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man climbing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man climbing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man climbing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man climbing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man climbing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97\xe2\x80\x8d\xe2\x99\x80"), - "woman climbing", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman climbing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman climbing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman climbing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman climbing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x97\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman climbing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xb7"), "ninja", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xba"), "person fencing", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x87"), "horse racing", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbb"), - "horse racing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbc"), - "horse racing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbd"), - "horse racing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbe"), - "horse racing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbf"), - "horse racing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb7"), "skier", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x82"), "snowboarder", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x82\xf0\x9f\x8f\xbb"), - "snowboarder: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x82\xf0\x9f\x8f\xbc"), - "snowboarder: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x82\xf0\x9f\x8f\xbd"), - "snowboarder: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x82\xf0\x9f\x8f\xbe"), - "snowboarder: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x82\xf0\x9f\x8f\xbf"), - "snowboarder: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c"), "person golfing", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xf0\x9f\x8f\xbb"), - "person golfing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xf0\x9f\x8f\xbc"), - "person golfing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xf0\x9f\x8f\xbd"), - "person golfing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xf0\x9f\x8f\xbe"), - "person golfing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xf0\x9f\x8f\xbf"), - "person golfing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x82"), - "man golfing", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xe2\x80\x8d\xe2\x99\x82"), - "man golfing", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man golfing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man golfing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man golfing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man golfing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man golfing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x80"), - "woman golfing", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xe2\x80\x8d\xe2\x99\x80"), - "woman golfing", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman golfing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman golfing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman golfing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman golfing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman golfing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84"), "person surfing", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbb"), - "person surfing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbc"), - "person surfing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbd"), - "person surfing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbe"), - "person surfing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbf"), - "person surfing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xe2\x80\x8d\xe2\x99\x82"), - "man surfing", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man surfing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man surfing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man surfing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man surfing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man surfing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xe2\x80\x8d\xe2\x99\x80"), - "woman surfing", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman surfing: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman surfing: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman surfing: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman surfing: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman surfing: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3"), "person rowing boat", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbb"), - "person rowing boat: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbc"), - "person rowing boat: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbd"), - "person rowing boat: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbe"), - "person rowing boat: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbf"), - "person rowing boat: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xe2\x80\x8d\xe2\x99\x82"), - "man rowing boat", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man rowing boat: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man rowing boat: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man rowing boat: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man rowing boat: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man rowing boat: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xe2\x80\x8d\xe2\x99\x80"), - "woman rowing boat", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman rowing boat: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman rowing boat: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman rowing boat: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman rowing boat: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman rowing boat: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a"), "person swimming", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbb"), - "person swimming: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbc"), - "person swimming: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbd"), - "person swimming: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbe"), - "person swimming: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbf"), - "person swimming: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xe2\x80\x8d\xe2\x99\x82"), - "man swimming", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man swimming: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man swimming: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man swimming: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man swimming: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man swimming: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xe2\x80\x8d\xe2\x99\x80"), - "woman swimming", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman swimming: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman swimming: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman swimming: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman swimming: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman swimming: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9"), "person bouncing ball", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbb"), - "person bouncing ball: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbc"), - "person bouncing ball: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbd"), - "person bouncing ball: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbe"), - "person bouncing ball: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbf"), - "person bouncing ball: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x82"), - "man bouncing ball", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xe2\x80\x8d\xe2\x99\x82"), - "man bouncing ball", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man bouncing ball: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man bouncing ball: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man bouncing ball: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man bouncing ball: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man bouncing ball: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x80"), - "woman bouncing ball", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xe2\x80\x8d\xe2\x99\x80"), - "woman bouncing ball", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman bouncing ball: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman bouncing ball: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman bouncing ball: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman bouncing ball: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman bouncing ball: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b"), - "person lifting weights", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbb"), - "person lifting weights: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbc"), - "person lifting weights: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbd"), - "person lifting weights: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbe"), - "person lifting weights: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbf"), - "person lifting weights: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x82"), - "man lifting weights", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xe2\x80\x8d\xe2\x99\x82"), - "man lifting weights", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man lifting weights: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man lifting weights: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man lifting weights: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man lifting weights: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man lifting weights: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xef\xb8\x8f\xe2\x80\x8d\xe2\x99\x80"), - "woman lifting weights", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xe2\x80\x8d\xe2\x99\x80"), - "woman lifting weights", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman lifting weights: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman lifting weights: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman lifting weights: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman lifting weights: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman lifting weights: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4"), "person biking", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbb"), - "person biking: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbc"), - "person biking: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbd"), - "person biking: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbe"), - "person biking: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbf"), - "person biking: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xe2\x80\x8d\xe2\x99\x82"), - "man biking", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man biking: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man biking: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man biking: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man biking: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man biking: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xe2\x80\x8d\xe2\x99\x80"), - "woman biking", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman biking: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman biking: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman biking: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman biking: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman biking: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5"), - "person mountain biking", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbb"), - "person mountain biking: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbc"), - "person mountain biking: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbd"), - "person mountain biking: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbe"), - "person mountain biking: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbf"), - "person mountain biking: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xe2\x80\x8d\xe2\x99\x82"), - "man mountain biking", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man mountain biking: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man mountain biking: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man mountain biking: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man mountain biking: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man mountain biking: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xe2\x80\x8d\xe2\x99\x80"), - "woman mountain biking", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman mountain biking: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman mountain biking: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman mountain biking: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman mountain biking: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman mountain biking: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8"), "person cartwheeling", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbb"), - "person cartwheeling: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbc"), - "person cartwheeling: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbd"), - "person cartwheeling: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbe"), - "person cartwheeling: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbf"), - "person cartwheeling: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xe2\x80\x8d\xe2\x99\x82"), - "man cartwheeling", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man cartwheeling: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man cartwheeling: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man cartwheeling: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man cartwheeling: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man cartwheeling: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xe2\x80\x8d\xe2\x99\x80"), - "woman cartwheeling", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman cartwheeling: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman cartwheeling: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman cartwheeling: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman cartwheeling: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman cartwheeling: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbc"), "people wrestling", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbc\xe2\x80\x8d\xe2\x99\x82"), - "men wrestling", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbc\xe2\x80\x8d\xe2\x99\x80"), - "women wrestling", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd"), - "person playing water polo", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbb"), - "person playing water polo: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbc"), - "person playing water polo: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbd"), - "person playing water polo: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbe"), - "person playing water polo: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbf"), - "person playing water polo: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man playing water polo", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man playing water polo: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man playing water polo: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man playing water polo: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man playing water polo: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man playing water polo: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman playing water polo", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman playing water polo: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman playing water polo: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman playing water polo: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman playing water polo: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman playing water polo: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe"), - "person playing handball", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbb"), - "person playing handball: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbc"), - "person playing handball: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbd"), - "person playing handball: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbe"), - "person playing handball: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbf"), - "person playing handball: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man playing handball", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man playing handball: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man playing handball: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man playing handball: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man playing handball: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man playing handball: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman playing handball", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman playing handball: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman playing handball: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman playing handball: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman playing handball: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman playing handball: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9"), "person juggling", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbb"), - "person juggling: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbc"), - "person juggling: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbd"), - "person juggling: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbe"), - "person juggling: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbf"), - "person juggling: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xe2\x80\x8d\xe2\x99\x82"), - "man juggling", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man juggling: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man juggling: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man juggling: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man juggling: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man juggling: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xe2\x80\x8d\xe2\x99\x80"), - "woman juggling", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman juggling: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman juggling: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman juggling: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman juggling: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman juggling: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98"), - "person in lotus position", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98\xf0\x9f\x8f\xbb"), - "person in lotus position: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98\xf0\x9f\x8f\xbc"), - "person in lotus position: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98\xf0\x9f\x8f\xbd"), - "person in lotus position: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98\xf0\x9f\x8f\xbe"), - "person in lotus position: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98\xf0\x9f\x8f\xbf"), - "person in lotus position: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98\xe2\x80\x8d\xe2\x99\x82"), - "man in lotus position", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x82"), - "man in lotus position: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x82"), - "man in lotus position: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x82"), - "man in lotus position: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x82"), - "man in lotus position: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x82"), - "man in lotus position: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98\xe2\x80\x8d\xe2\x99\x80"), - "woman in lotus position", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98\xf0\x9f\x8f\xbb\xe2\x80\x8d\xe2\x99\x80"), - "woman in lotus position: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98\xf0\x9f\x8f\xbc\xe2\x80\x8d\xe2\x99\x80"), - "woman in lotus position: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98\xf0\x9f\x8f\xbd\xe2\x80\x8d\xe2\x99\x80"), - "woman in lotus position: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98\xf0\x9f\x8f\xbe\xe2\x80\x8d\xe2\x99\x80"), - "woman in lotus position: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x98\xf0\x9f\x8f\xbf\xe2\x80\x8d\xe2\x99\x80"), - "woman in lotus position: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x80"), "person taking bath", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbb"), - "person taking bath: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbc"), - "person taking bath: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbd"), - "person taking bath: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbe"), - "person taking bath: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbf"), - "person taking bath: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x8c"), "person in bed", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x8c\xf0\x9f\x8f\xbb"), - "person in bed: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x8c\xf0\x9f\x8f\xbc"), - "person in bed: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x8c\xf0\x9f\x8f\xbd"), - "person in bed: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x8c\xf0\x9f\x8f\xbe"), - "person in bed: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x8c\xf0\x9f\x8f\xbf"), - "person in bed: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{ - QString::fromUtf8("\xf0\x9f\xa7\x91\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d\xf0\x9f\xa7\x91"), - "people holding hands", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb"), - "people holding hands: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc"), - "people holding hands: light skin tone, medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd"), - "people holding hands: light skin tone, medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe"), - "people holding hands: light skin tone, medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf"), - "people holding hands: light skin tone, dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb"), - "people holding hands: medium-light skin tone, light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc"), - "people holding hands: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd"), - "people holding hands: medium-light skin tone, medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe"), - "people holding hands: medium-light skin tone, medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf"), - "people holding hands: medium-light skin tone, dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb"), - "people holding hands: medium skin tone, light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc"), - "people holding hands: medium skin tone, medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd"), - "people holding hands: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe"), - "people holding hands: medium skin tone, medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf"), - "people holding hands: medium skin tone, dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb"), - "people holding hands: medium-dark skin tone, light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc"), - "people holding hands: medium-dark skin tone, medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd"), - "people holding hands: medium-dark skin tone, medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe"), - "people holding hands: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf"), - "people holding hands: medium-dark skin tone, dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbb"), - "people holding hands: dark skin tone, light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbc"), - "people holding hands: dark skin tone, medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbd"), - "people holding hands: dark skin tone, medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbe"), - "people holding hands: dark skin tone, medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\xa7\x91\xf0\x9f\x8f\xbf"), - "people holding hands: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xad"), "women holding hands", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xad\xf0\x9f\x8f\xbb"), - "women holding hands: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc"), - "women holding hands: light skin tone, medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd"), - "women holding hands: light skin tone, medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe"), - "women holding hands: light skin tone, medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf"), - "women holding hands: light skin tone, dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb"), - "women holding hands: medium-light skin tone, light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xad\xf0\x9f\x8f\xbc"), - "women holding hands: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd"), - "women holding hands: medium-light skin tone, medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe"), - "women holding hands: medium-light skin tone, medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf"), - "women holding hands: medium-light skin tone, dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb"), - "women holding hands: medium skin tone, light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc"), - "women holding hands: medium skin tone, medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xad\xf0\x9f\x8f\xbd"), - "women holding hands: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe"), - "women holding hands: medium skin tone, medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf"), - "women holding hands: medium skin tone, dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb"), - "women holding hands: medium-dark skin tone, light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc"), - "women holding hands: medium-dark skin tone, medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd"), - "women holding hands: medium-dark skin tone, medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xad\xf0\x9f\x8f\xbe"), - "women holding hands: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf"), - "women holding hands: medium-dark skin tone, dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb"), - "women holding hands: dark skin tone, light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc"), - "women holding hands: dark skin tone, medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd"), - "women holding hands: dark skin tone, medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe"), - "women holding hands: dark skin tone, medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xad\xf0\x9f\x8f\xbf"), - "women holding hands: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xab"), - "woman and man holding hands", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xab\xf0\x9f\x8f\xbb"), - "woman and man holding hands: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc"), - "woman and man holding hands: light skin tone, medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd"), - "woman and man holding hands: light skin tone, medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe"), - "woman and man holding hands: light skin tone, medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf"), - "woman and man holding hands: light skin tone, dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb"), - "woman and man holding hands: medium-light skin tone, light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xab\xf0\x9f\x8f\xbc"), - "woman and man holding hands: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd"), - "woman and man holding hands: medium-light skin tone, medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe"), - "woman and man holding hands: medium-light skin tone, medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf"), - "woman and man holding hands: medium-light skin tone, dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb"), - "woman and man holding hands: medium skin tone, light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc"), - "woman and man holding hands: medium skin tone, medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xab\xf0\x9f\x8f\xbd"), - "woman and man holding hands: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe"), - "woman and man holding hands: medium skin tone, medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf"), - "woman and man holding hands: medium skin tone, dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb"), - "woman and man holding hands: medium-dark skin tone, light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc"), - "woman and man holding hands: medium-dark skin tone, medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd"), - "woman and man holding hands: medium-dark skin tone, medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xab\xf0\x9f\x8f\xbe"), - "woman and man holding hands: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf"), - "woman and man holding hands: medium-dark skin tone, dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb"), - "woman and man holding hands: dark skin tone, light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc"), - "woman and man holding hands: dark skin tone, medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd"), - "woman and man holding hands: dark skin tone, medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe"), - "woman and man holding hands: dark skin tone, medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xab\xf0\x9f\x8f\xbf"), - "woman and man holding hands: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xac"), "men holding hands", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xac\xf0\x9f\x8f\xbb"), - "men holding hands: light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc"), - "men holding hands: light skin tone, medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd"), - "men holding hands: light skin tone, medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe"), - "men holding hands: light skin tone, medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf"), - "men holding hands: light skin tone, dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb"), - "men holding hands: medium-light skin tone, light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xac\xf0\x9f\x8f\xbc"), - "men holding hands: medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd"), - "men holding hands: medium-light skin tone, medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe"), - "men holding hands: medium-light skin tone, medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf"), - "men holding hands: medium-light skin tone, dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb"), - "men holding hands: medium skin tone, light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc"), - "men holding hands: medium skin tone, medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xac\xf0\x9f\x8f\xbd"), - "men holding hands: medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe"), - "men holding hands: medium skin tone, medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf"), - "men holding hands: medium skin tone, dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb"), - "men holding hands: medium-dark skin tone, light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc"), - "men holding hands: medium-dark skin tone, medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd"), - "men holding hands: medium-dark skin tone, medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xac\xf0\x9f\x8f\xbe"), - "men holding hands: medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf"), - "men holding hands: medium-dark skin tone, dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbb"), - "men holding hands: dark skin tone, light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbc"), - "men holding hands: dark skin tone, medium-light skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbd"), - "men holding hands: dark skin tone, medium skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbf\xe2\x80\x8d\xf0\x9f\xa4\x9d\xe2\x80\x8d" - "\xf0\x9f\x91\xa8\xf0\x9f\x8f\xbe"), - "men holding hands: dark skin tone, medium-dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xac\xf0\x9f\x8f\xbf"), - "men holding hands: dark skin tone", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x8f"), "kiss", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9d\xa4\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f" - "\x92\x8b\xe2\x80\x8d\xf0\x9f\x91\xa8"), - "kiss: woman, man", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9d\xa4\xe2\x80\x8d\xf0\x9f\x92\x8b\xe2" - "\x80\x8d\xf0\x9f\x91\xa8"), - "kiss: woman, man", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xe2\x9d\xa4\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f" - "\x92\x8b\xe2\x80\x8d\xf0\x9f\x91\xa8"), - "kiss: man, man", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xe2\x9d\xa4\xe2\x80\x8d\xf0\x9f\x92\x8b\xe2" - "\x80\x8d\xf0\x9f\x91\xa8"), - "kiss: man, man", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9d\xa4\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f" - "\x92\x8b\xe2\x80\x8d\xf0\x9f\x91\xa9"), - "kiss: woman, woman", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9d\xa4\xe2\x80\x8d\xf0\x9f\x92\x8b\xe2" - "\x80\x8d\xf0\x9f\x91\xa9"), - "kiss: woman, woman", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x91"), "couple with heart", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8( - "\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9d\xa4\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f\x91\xa8"), - "couple with heart: woman, man", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9d\xa4\xe2\x80\x8d\xf0\x9f\x91\xa8"), - "couple with heart: woman, man", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8( - "\xf0\x9f\x91\xa8\xe2\x80\x8d\xe2\x9d\xa4\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f\x91\xa8"), - "couple with heart: man, man", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xe2\x9d\xa4\xe2\x80\x8d\xf0\x9f\x91\xa8"), - "couple with heart: man, man", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8( - "\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9d\xa4\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f\x91\xa9"), - "couple with heart: woman, woman", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xe2\x9d\xa4\xe2\x80\x8d\xf0\x9f\x91\xa9"), - "couple with heart: woman, woman", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xaa"), "family", emoji::EmojiCategory::People}, - Emoji{ - QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa6"), - "family: man, woman, boy", - emoji::EmojiCategory::People}, - Emoji{ - QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7"), - "family: man, woman, girl", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7" - "\xe2\x80\x8d\xf0\x9f\x91\xa6"), - "family: man, woman, girl, boy", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa6" - "\xe2\x80\x8d\xf0\x9f\x91\xa6"), - "family: man, woman, boy, boy", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7" - "\xe2\x80\x8d\xf0\x9f\x91\xa7"), - "family: man, woman, girl, girl", - emoji::EmojiCategory::People}, - Emoji{ - QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa6"), - "family: man, man, boy", - emoji::EmojiCategory::People}, - Emoji{ - QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa7"), - "family: man, man, girl", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa7" - "\xe2\x80\x8d\xf0\x9f\x91\xa6"), - "family: man, man, girl, boy", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa6" - "\xe2\x80\x8d\xf0\x9f\x91\xa6"), - "family: man, man, boy, boy", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa7" - "\xe2\x80\x8d\xf0\x9f\x91\xa7"), - "family: man, man, girl, girl", - emoji::EmojiCategory::People}, - Emoji{ - QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa6"), - "family: woman, woman, boy", - emoji::EmojiCategory::People}, - Emoji{ - QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7"), - "family: woman, woman, girl", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7" - "\xe2\x80\x8d\xf0\x9f\x91\xa6"), - "family: woman, woman, girl, boy", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa6" - "\xe2\x80\x8d\xf0\x9f\x91\xa6"), - "family: woman, woman, boy, boy", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7" - "\xe2\x80\x8d\xf0\x9f\x91\xa7"), - "family: woman, woman, girl, girl", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa6"), - "family: man, boy", - emoji::EmojiCategory::People}, - Emoji{ - QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa6\xe2\x80\x8d\xf0\x9f\x91\xa6"), - "family: man, boy, boy", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa7"), - "family: man, girl", - emoji::EmojiCategory::People}, - Emoji{ - QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa7\xe2\x80\x8d\xf0\x9f\x91\xa6"), - "family: man, girl, boy", - emoji::EmojiCategory::People}, - Emoji{ - QString::fromUtf8("\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa7\xe2\x80\x8d\xf0\x9f\x91\xa7"), - "family: man, girl, girl", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa6"), - "family: woman, boy", - emoji::EmojiCategory::People}, - Emoji{ - QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa6\xe2\x80\x8d\xf0\x9f\x91\xa6"), - "family: woman, boy, boy", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7"), - "family: woman, girl", - emoji::EmojiCategory::People}, - Emoji{ - QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7\xe2\x80\x8d\xf0\x9f\x91\xa6"), - "family: woman, girl, boy", - emoji::EmojiCategory::People}, - Emoji{ - QString::fromUtf8("\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7\xe2\x80\x8d\xf0\x9f\x91\xa7"), - "family: woman, girl, girl", - emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\xa3"), "speaking head", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa4"), "bust in silhouette", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa5"), "busts in silhouette", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\xab\x82"), "people hugging", emoji::EmojiCategory::People}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa3"), "footprints", emoji::EmojiCategory::People}, -}; - -const std::vector emoji::Provider::nature = { - // Nature - Emoji{QString::fromUtf8("\xf0\x9f\x90\xb5"), "monkey face", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x92"), "monkey", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x8d"), "gorilla", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xa7"), "orangutan", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xb6"), "dog face", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x95"), "dog", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xae"), "guide dog", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x95\xe2\x80\x8d\xf0\x9f\xa6\xba"), - "service dog", - emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa9"), "poodle", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xba"), "wolf", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x8a"), "fox", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x9d"), "raccoon", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xb1"), "cat face", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x88"), "cat", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x88\xe2\x80\x8d\xe2\xac\x9b"), - "black cat", - emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x81"), "lion", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xaf"), "tiger face", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x85"), "tiger", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x86"), "leopard", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xb4"), "horse face", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x8e"), "horse", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x84"), "unicorn", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x93"), "zebra", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x8c"), "deer", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xac"), "bison", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xae"), "cow face", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x82"), "ox", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x83"), "water buffalo", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x84"), "cow", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xb7"), "pig face", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x96"), "pig", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x97"), "boar", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xbd"), "pig nose", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x8f"), "ram", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x91"), "ewe", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x90"), "goat", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xaa"), "camel", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xab"), "two-hump camel", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x99"), "llama", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x92"), "giraffe", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x98"), "elephant", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xa3"), "mammoth", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x8f"), "rhinoceros", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x9b"), "hippopotamus", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xad"), "mouse face", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x81"), "mouse", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x80"), "rat", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xb9"), "hamster", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xb0"), "rabbit face", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x87"), "rabbit", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xbf"), "chipmunk", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xab"), "beaver", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x94"), "hedgehog", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x87"), "bat", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xbb"), "bear", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xbb\xe2\x80\x8d\xe2\x9d\x84"), - "polar bear", - emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa8"), "koala", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xbc"), "panda", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xa5"), "sloth", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xa6"), "otter", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xa8"), "skunk", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x98"), "kangaroo", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xa1"), "badger", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xbe"), "paw prints", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x83"), "turkey", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x94"), "chicken", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x93"), "rooster", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa3"), "hatching chick", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa4"), "baby chick", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa5"), - "front-facing baby chick", - emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa6"), "bird", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa7"), "penguin", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x8a"), "dove", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x85"), "eagle", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x86"), "duck", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xa2"), "swan", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x89"), "owl", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xa4"), "dodo", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\xb6"), "feather", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xa9"), "flamingo", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x9a"), "peacock", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x9c"), "parrot", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xb8"), "frog", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x8a"), "crocodile", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa2"), "turtle", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x8e"), "lizard", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x8d"), "snake", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xb2"), "dragon face", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x89"), "dragon", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x95"), "sauropod", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x96"), "T-Rex", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xb3"), "spouting whale", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x8b"), "whale", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xac"), "dolphin", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xad"), "seal", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x9f"), "fish", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa0"), "tropical fish", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa1"), "blowfish", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x88"), "shark", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x99"), "octopus", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x9a"), "spiral shell", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x8c"), "snail", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x8b"), "butterfly", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x9b"), "bug", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x9c"), "ant", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x9d"), "honeybee", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\xb2"), "beetle", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x90\x9e"), "lady beetle", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x97"), "cricket", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\xb3"), "cockroach", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb7"), "spider", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb8"), "spider web", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x82"), "scorpion", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x9f"), "mosquito", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\xb0"), "fly", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\xb1"), "worm", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xa0"), "microbe", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x90"), "bouquet", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb8"), "cherry blossom", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xae"), "white flower", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb5"), "rosette", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb9"), "rose", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x80"), "wilted flower", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xba"), "hibiscus", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xbb"), "sunflower", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xbc"), "blossom", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb7"), "tulip", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb1"), "seedling", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\xb4"), "potted plant", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb2"), "evergreen tree", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb3"), "deciduous tree", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb4"), "palm tree", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb5"), "cactus", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xbe"), "sheaf of rice", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xbf"), "herb", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xe2\x98\x98"), "shamrock", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x80"), "four leaf clover", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x81"), "maple leaf", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x82"), "fallen leaf", emoji::EmojiCategory::Nature}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x83"), - "leaf fluttering in wind", - emoji::EmojiCategory::Nature}, -}; - -const std::vector emoji::Provider::food = { - // Food - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x87"), "grapes", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x88"), "melon", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x89"), "watermelon", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x8a"), "tangerine", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x8b"), "lemon", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x8c"), "banana", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x8d"), "pineapple", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xad"), "mango", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x8e"), "red apple", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x8f"), "green apple", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x90"), "pear", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x91"), "peach", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x92"), "cherries", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x93"), "strawberry", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xab\x90"), "blueberries", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x9d"), "kiwi fruit", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x85"), "tomato", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xab\x92"), "olive", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xa5"), "coconut", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x91"), "avocado", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x86"), "eggplant", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x94"), "potato", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x95"), "carrot", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xbd"), "ear of corn", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb6"), "hot pepper", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xab\x91"), "bell pepper", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x92"), "cucumber", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xac"), "leafy green", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xa6"), "broccoli", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x84"), "garlic", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x85"), "onion", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x84"), "mushroom", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x9c"), "peanuts", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb0"), "chestnut", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x9e"), "bread", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x90"), "croissant", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x96"), "baguette bread", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xab\x93"), "flatbread", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xa8"), "pretzel", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xaf"), "bagel", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x9e"), "pancakes", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x87"), "waffle", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x80"), "cheese wedge", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x96"), "meat on bone", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x97"), "poultry leg", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xa9"), "cut of meat", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x93"), "bacon", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x94"), "hamburger", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x9f"), "french fries", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x95"), "pizza", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xad"), "hot dog", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xaa"), "sandwich", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xae"), "taco", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xaf"), "burrito", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xab\x94"), "tamale", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x99"), "stuffed flatbread", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x86"), "falafel", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x9a"), "egg", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb3"), "cooking", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x98"), "shallow pan of food", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb2"), "pot of food", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xab\x95"), "fondue", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xa3"), "bowl with spoon", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x97"), "green salad", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xbf"), "popcorn", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x88"), "butter", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x82"), "salt", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xab"), "canned food", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb1"), "bento box", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x98"), "rice cracker", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x99"), "rice ball", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x9a"), "cooked rice", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x9b"), "curry rice", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x9c"), "steaming bowl", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x9d"), "spaghetti", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa0"), "roasted sweet potato", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa2"), "oden", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa3"), "sushi", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa4"), "fried shrimp", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa5"), "fish cake with swirl", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xae"), "moon cake", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa1"), "dango", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x9f"), "dumpling", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xa0"), "fortune cookie", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xa1"), "takeout box", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x80"), "crab", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x9e"), "lobster", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x90"), "shrimp", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x91"), "squid", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xaa"), "oyster", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa6"), "soft ice cream", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa7"), "shaved ice", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa8"), "ice cream", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa9"), "doughnut", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xaa"), "cookie", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x82"), "birthday cake", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb0"), "shortcake", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x81"), "cupcake", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xa7"), "pie", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xab"), "chocolate bar", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xac"), "candy", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xad"), "lollipop", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xae"), "custard", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xaf"), "honey pot", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xbc"), "baby bottle", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x9b"), "glass of milk", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xe2\x98\x95"), "hot beverage", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xab\x96"), "teapot", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb5"), "teacup without handle", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb6"), "sake", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xbe"), - "bottle with popping cork", - emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb7"), "wine glass", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb8"), "cocktail glass", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb9"), "tropical drink", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xba"), "beer mug", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xbb"), "clinking beer mugs", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x82"), "clinking glasses", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x83"), "tumbler glass", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xa4"), "cup with straw", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8b"), "bubble tea", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x83"), "beverage box", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x89"), "mate", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x8a"), "ice", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xa2"), "chopsticks", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xbd"), - "fork and knife with plate", - emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb4"), "fork and knife", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x84"), "spoon", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xaa"), "kitchen knife", emoji::EmojiCategory::Food}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xba"), "amphora", emoji::EmojiCategory::Food}, -}; - -const std::vector emoji::Provider::activity = { - // Activity - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x83"), "jack-o-lantern", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x84"), "Christmas tree", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x86"), "fireworks", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x87"), "sparkler", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xa8"), "firecracker", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xe2\x9c\xa8"), "sparkles", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x88"), "balloon", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x89"), "party popper", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x8a"), "confetti ball", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x8b"), "tanabata tree", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x8d"), "pine decoration", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x8e"), "Japanese dolls", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x8f"), "carp streamer", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x90"), "wind chime", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x91"), - "moon viewing ceremony", - emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xa7"), "red envelope", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x80"), "ribbon", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x81"), "wrapped gift", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x97"), "reminder ribbon", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x9f"), "admission tickets", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xab"), "ticket", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x96"), "military medal", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x86"), "trophy", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x85"), "sports medal", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x87"), "1st place medal", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x88"), "2nd place medal", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x89"), "3rd place medal", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xe2\x9a\xbd"), "soccer ball", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xe2\x9a\xbe"), "baseball", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x8e"), "softball", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x80"), "basketball", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x90"), "volleyball", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x88"), "american football", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x89"), "rugby football", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xbe"), "tennis", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x8f"), "flying disc", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb3"), "bowling", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8f"), "cricket game", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x91"), "field hockey", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x92"), "ice hockey", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x8d"), "lacrosse", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x93"), "ping pong", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb8"), "badminton", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x8a"), "boxing glove", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x8b"), - "martial arts uniform", - emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x85"), "goal net", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xe2\x9b\xb3"), "flag in hole", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xe2\x9b\xb8"), "ice skate", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa3"), "fishing pole", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbf"), "diving mask", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xbd"), "running shirt", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xbf"), "skis", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xb7"), "sled", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x8c"), "curling stone", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xaf"), "direct hit", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x80"), "yo-yo", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x81"), "kite", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb1"), "pool 8 ball", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xae"), "crystal ball", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x84"), "magic wand", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xbf"), "nazar amulet", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xae"), "video game", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb9"), "joystick", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb0"), "slot machine", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb2"), "game die", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xa9"), "puzzle piece", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xb8"), "teddy bear", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x85"), "piñata", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x86"), "nesting dolls", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xe2\x99\xa0"), "spade suit", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xe2\x99\xa5"), "heart suit", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xe2\x99\xa6"), "diamond suit", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xe2\x99\xa3"), "club suit", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xe2\x99\x9f"), "chess pawn", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x83\x8f"), "joker", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x80\x84"), - "mahjong red dragon", - emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb4"), - "flower playing cards", - emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xad"), "performing arts", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\xbc"), "framed picture", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa8"), "artist palette", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xb5"), "thread", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\xa1"), "sewing needle", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xb6"), "yarn", emoji::EmojiCategory::Activity}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\xa2"), "knot", emoji::EmojiCategory::Activity}, -}; - -const std::vector emoji::Provider::travel = { - // Travel - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x8d"), - "globe showing Europe-Africa", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x8e"), - "globe showing Americas", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x8f"), - "globe showing Asia-Australia", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x90"), - "globe with meridians", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\xba"), "world map", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\xbe"), "map of Japan", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xad"), "compass", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x94"), - "snow-capped mountain", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x9b\xb0"), "mountain", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x8b"), "volcano", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\xbb"), "mount fuji", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x95"), "camping", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x96"), "beach with umbrella", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x9c"), "desert", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x9d"), "desert island", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x9e"), "national park", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x9f"), "stadium", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x9b"), "classical building", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x97"), - "building construction", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xb1"), "brick", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\xa8"), "rock", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\xb5"), "wood", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x96"), "hut", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x98"), "houses", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x9a"), "derelict house", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa0"), "house", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa1"), "house with garden", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa2"), "office building", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa3"), - "Japanese post office", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa4"), "post office", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa5"), "hospital", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa6"), "bank", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa8"), "hotel", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa9"), "love hotel", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xaa"), "convenience store", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xab"), "school", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xac"), "department store", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xad"), "factory", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xaf"), "Japanese castle", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb0"), "castle", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x92"), "wedding", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\xbc"), "Tokyo tower", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\xbd"), "Statue of Liberty", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x9b\xaa"), "church", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x8c"), "mosque", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x95"), "hindu temple", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x8d"), "synagogue", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x9b\xa9"), "shinto shrine", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x8b"), "kaaba", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x9b\xb2"), "fountain", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x9b\xba"), "tent", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x81"), "foggy", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x83"), "night with stars", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x99"), "cityscape", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x84"), - "sunrise over mountains", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x85"), "sunrise", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x86"), "cityscape at dusk", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x87"), "sunset", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x89"), "bridge at night", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x99\xa8"), "hot springs", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa0"), "carousel horse", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa1"), "ferris wheel", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa2"), "roller coaster", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x88"), "barber pole", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xaa"), "circus tent", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x82"), "locomotive", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x83"), "railway car", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x84"), "high-speed train", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x85"), "bullet train", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x86"), "train", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x87"), "metro", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x88"), "light rail", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x89"), "station", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x8a"), "tram", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x9d"), "monorail", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x9e"), "mountain railway", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x8b"), "tram car", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x8c"), "bus", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x8d"), "oncoming bus", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x8e"), "trolleybus", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x90"), "minibus", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x91"), "ambulance", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x92"), "fire engine", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x93"), "police car", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x94"), "oncoming police car", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x95"), "taxi", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x96"), "oncoming taxi", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x97"), "automobile", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x98"), "oncoming automobile", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x99"), - "sport utility vehicle", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xbb"), "pickup truck", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x9a"), "delivery truck", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x9b"), "articulated lorry", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x9c"), "tractor", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8e"), "racing car", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8d"), "motorcycle", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xb5"), "motor scooter", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xbd"), "manual wheelchair", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xbc"), - "motorized wheelchair", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xba"), "auto rickshaw", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb2"), "bicycle", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xb4"), "kick scooter", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xb9"), "skateboard", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xbc"), "roller skate", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x8f"), "bus stop", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xa3"), "motorway", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xa4"), "railway track", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xa2"), "oil drum", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x9b\xbd"), "fuel pump", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa8"), "police car light", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa5"), - "horizontal traffic light", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa6"), - "vertical traffic light", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x91"), "stop sign", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa7"), "construction", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x9a\x93"), "anchor", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x9b\xb5"), "sailboat", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xb6"), "canoe", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa4"), "speedboat", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xb3"), "passenger ship", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x9b\xb4"), "ferry", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xa5"), "motor boat", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa2"), "ship", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x9c\x88"), "airplane", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xa9"), "small airplane", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xab"), "airplane departure", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xac"), "airplane arrival", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x82"), "parachute", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xba"), "seat", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x81"), "helicopter", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x9f"), "suspension railway", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa0"), "mountain cableway", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa1"), "aerial tramway", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xb0"), "satellite", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x80"), "rocket", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xb8"), "flying saucer", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x8e"), "bellhop bell", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xb3"), "luggage", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x8c\x9b"), "hourglass done", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x8f\xb3"), "hourglass not done", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x8c\x9a"), "watch", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x8f\xb0"), "alarm clock", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x8f\xb1"), "stopwatch", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x8f\xb2"), "timer clock", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb0"), "mantelpiece clock", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x9b"), "twelve o’clock", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xa7"), "twelve-thirty", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x90"), "one o’clock", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x9c"), "one-thirty", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x91"), "two o’clock", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x9d"), "two-thirty", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x92"), "three o’clock", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x9e"), "three-thirty", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x93"), "four o’clock", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x9f"), "four-thirty", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x94"), "five o’clock", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xa0"), "five-thirty", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x95"), "six o’clock", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xa1"), "six-thirty", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x96"), "seven o’clock", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xa2"), "seven-thirty", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x97"), "eight o’clock", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xa3"), "eight-thirty", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x98"), "nine o’clock", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xa4"), "nine-thirty", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x99"), "ten o’clock", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xa5"), "ten-thirty", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x9a"), "eleven o’clock", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xa6"), "eleven-thirty", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x91"), "new moon", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x92"), - "waxing crescent moon", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x93"), "first quarter moon", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x94"), "waxing gibbous moon", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x95"), "full moon", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x96"), "waning gibbous moon", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x97"), "last quarter moon", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x98"), - "waning crescent moon", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x99"), "crescent moon", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x9a"), "new moon face", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x9b"), - "first quarter moon face", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x9c"), - "last quarter moon face", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xa1"), "thermometer", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x98\x80"), "sun", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x9d"), "full moon face", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x9e"), "sun with face", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x90"), "ringed planet", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\xad\x90"), "star", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x9f"), "glowing star", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xa0"), "shooting star", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x8c"), "milky way", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x98\x81"), "cloud", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x9b\x85"), "sun behind cloud", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x9b\x88"), - "cloud with lightning and rain", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xa4"), - "sun behind small cloud", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xa5"), - "sun behind large cloud", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xa6"), - "sun behind rain cloud", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xa7"), "cloud with rain", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xa8"), "cloud with snow", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xa9"), - "cloud with lightning", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xaa"), "tornado", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xab"), "fog", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xac"), "wind face", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x80"), "cyclone", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x88"), "rainbow", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x82"), "closed umbrella", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x98\x82"), "umbrella", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x98\x94"), - "umbrella with rain drops", - emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x9b\xb1"), "umbrella on ground", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x9a\xa1"), "high voltage", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x9d\x84"), "snowflake", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x98\x83"), "snowman", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x9b\x84"), "snowman without snow", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xe2\x98\x84"), "comet", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xa5"), "fire", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xa7"), "droplet", emoji::EmojiCategory::Travel}, - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x8a"), "water wave", emoji::EmojiCategory::Travel}, -}; - -const std::vector emoji::Provider::objects = { - // Objects - Emoji{QString::fromUtf8("\xf0\x9f\x91\x93"), "glasses", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb6"), "sunglasses", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xbd"), "goggles", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xbc"), "lab coat", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xba"), "safety vest", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x94"), "necktie", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x95"), "t-shirt", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x96"), "jeans", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xa3"), "scarf", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xa4"), "gloves", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xa5"), "coat", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xa6"), "socks", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x97"), "dress", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x98"), "kimono", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xbb"), "sari", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa9\xb1"), "one-piece swimsuit", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa9\xb2"), "briefs", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa9\xb3"), "shorts", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x99"), "bikini", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x9a"), "woman’s clothes", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x9b"), "purse", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x9c"), "handbag", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x9d"), "clutch bag", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x8d"), "shopping bags", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x92"), "backpack", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa9\xb4"), "thong sandal", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x9e"), "man’s shoe", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x9f"), "running shoe", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xbe"), "hiking boot", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\xbf"), "flat shoe", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa0"), "high-heeled shoe", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa1"), "woman’s sandal", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa9\xb0"), "ballet shoes", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa2"), "woman’s boot", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x91"), "crown", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x91\x92"), "woman’s hat", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa9"), "top hat", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x93"), "graduation cap", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xa2"), "billed cap", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x96"), "military helmet", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xe2\x9b\x91"), "rescue worker’s helmet", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xbf"), "prayer beads", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x84"), "lipstick", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x8d"), "ring", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x8e"), "gem stone", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x87"), "muted speaker", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x88"), "speaker low volume", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x89"), - "speaker medium volume", - emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x8a"), - "speaker high volume", - emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa2"), "loudspeaker", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa3"), "megaphone", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xaf"), "postal horn", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x94"), "bell", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x95"), "bell with slash", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xbc"), "musical score", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb5"), "musical note", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb6"), "musical notes", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x99"), "studio microphone", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x9a"), "level slider", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x9b"), "control knobs", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa4"), "microphone", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa7"), "headphone", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xbb"), "radio", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb7"), "saxophone", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x97"), "accordion", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb8"), "guitar", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb9"), "musical keyboard", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xba"), "trumpet", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xbb"), "violin", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x95"), "banjo", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x81"), "drum", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x98"), "long drum", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb1"), "mobile phone", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb2"), - "mobile phone with arrow", - emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xe2\x98\x8e"), "telephone", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x9e"), "telephone receiver", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x9f"), "pager", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa0"), "fax machine", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x8b"), "battery", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x8c"), "electric plug", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xbb"), "laptop", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\xa5"), "desktop computer", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\xa8"), "printer", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xe2\x8c\xa8"), "keyboard", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\xb1"), "computer mouse", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\xb2"), "trackball", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xbd"), "computer disk", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xbe"), "floppy disk", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xbf"), "optical disk", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x80"), "dvd", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xae"), "abacus", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa5"), "movie camera", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x9e"), "film frames", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xbd"), "film projector", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xac"), "clapper board", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xba"), "television", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb7"), "camera", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb8"), "camera with flash", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb9"), "video camera", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xbc"), "videocassette", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x8d"), - "magnifying glass tilted left", - emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x8e"), - "magnifying glass tilted right", - emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\xaf"), "candle", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xa1"), "light bulb", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xa6"), "flashlight", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xae"), "red paper lantern", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x94"), "diya lamp", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x94"), - "notebook with decorative cover", - emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x95"), "closed book", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x96"), "open book", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x97"), "green book", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x98"), "blue book", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x99"), "orange book", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x9a"), "books", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x93"), "notebook", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x92"), "ledger", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x83"), "page with curl", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x9c"), "scroll", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x84"), "page facing up", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb0"), "newspaper", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\x9e"), - "rolled-up newspaper", - emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x91"), "bookmark tabs", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x96"), "bookmark", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb7"), "label", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb0"), "money bag", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x99"), "coin", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb4"), "yen banknote", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb5"), "dollar banknote", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb6"), "euro banknote", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb7"), "pound banknote", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb8"), "money with wings", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb3"), "credit card", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xbe"), "receipt", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb9"), - "chart increasing with yen", - emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb1"), "currency exchange", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb2"), "heavy dollar sign", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xe2\x9c\x89"), "envelope", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa7"), "e-mail", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa8"), "incoming envelope", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa9"), - "envelope with arrow", - emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa4"), "outbox tray", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa5"), "inbox tray", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa6"), "package", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xab"), - "closed mailbox with raised flag", - emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xaa"), - "closed mailbox with lowered flag", - emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xac"), - "open mailbox with raised flag", - emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xad"), - "open mailbox with lowered flag", - emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xae"), "postbox", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\xb3"), - "ballot box with ballot", - emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xe2\x9c\x8f"), "pencil", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xe2\x9c\x92"), "black nib", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x8b"), "fountain pen", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x8a"), "pen", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x8c"), "paintbrush", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x8d"), "crayon", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x9d"), "memo", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xbc"), "briefcase", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x81"), "file folder", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x82"), "open file folder", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\x82"), - "card index dividers", - emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x85"), "calendar", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x86"), "tear-off calendar", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\x92"), "spiral notepad", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\x93"), "spiral calendar", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x87"), "card index", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x88"), "chart increasing", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x89"), "chart decreasing", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x8a"), "bar chart", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x8b"), "clipboard", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x8c"), "pushpin", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x8d"), "round pushpin", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x8e"), "paperclip", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x96\x87"), "linked paperclips", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x8f"), "straight ruler", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x90"), "triangular ruler", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xe2\x9c\x82"), "scissors", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\x83"), "card file box", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\x84"), "file cabinet", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\x91"), "wastebasket", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x92"), "locked", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x93"), "unlocked", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x8f"), "locked with pen", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x90"), "locked with key", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x91"), "key", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\x9d"), "old key", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xa8"), "hammer", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x93"), "axe", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xe2\x9b\x8f"), "pick", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xe2\x9a\x92"), "hammer and pick", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xa0"), "hammer and wrench", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\xa1"), "dagger", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xe2\x9a\x94"), "crossed swords", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xab"), "pistol", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x83"), "boomerang", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb9"), "bow and arrow", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xa1"), "shield", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x9a"), "carpentry saw", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xa7"), "wrench", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x9b"), "screwdriver", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xa9"), "nut and bolt", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xe2\x9a\x99"), "gear", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\x9c"), "clamp", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xe2\x9a\x96"), "balance scale", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa6\xaf"), "probing cane", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x97"), "link", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xe2\x9b\x93"), "chains", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x9d"), "hook", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xb0"), "toolbox", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xb2"), "magnet", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x9c"), "ladder", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xe2\x9a\x97"), "alembic", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xaa"), "test tube", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xab"), "petri dish", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xac"), "dna", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xac"), "microscope", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xad"), "telescope", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa1"), "satellite antenna", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x89"), "syringe", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa9\xb8"), "drop of blood", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\x8a"), "pill", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa9\xb9"), "adhesive bandage", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa9\xba"), "stethoscope", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xaa"), "door", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x97"), "elevator", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x9e"), "mirror", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x9f"), "window", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x8f"), "bed", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x8b"), "couch and lamp", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x91"), "chair", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xbd"), "toilet", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\xa0"), "plunger", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xbf"), "shower", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x81"), "bathtub", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\xa4"), "mouse trap", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\x92"), "razor", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xb4"), "lotion bottle", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xb7"), "safety pin", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xb9"), "broom", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xba"), "basket", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xbb"), "roll of paper", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\xa3"), "bucket", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xbc"), "soap", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\xa5"), "toothbrush", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xbd"), "sponge", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xa7\xaf"), "fire extinguisher", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x92"), "shopping cart", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xac"), "cigarette", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xe2\x9a\xb0"), "coffin", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\xa6"), "headstone", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xe2\x9a\xb1"), "funeral urn", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\x97\xbf"), "moai", emoji::EmojiCategory::Objects}, - Emoji{QString::fromUtf8("\xf0\x9f\xaa\xa7"), "placard", emoji::EmojiCategory::Objects}, -}; - -const std::vector emoji::Provider::symbols = { - // Symbols - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa7"), "ATM sign", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xae"), "litter in bin sign", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb0"), "potable water", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x99\xbf"), "wheelchair symbol", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb9"), "men’s room", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xba"), "women’s room", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xbb"), "restroom", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xbc"), "baby symbol", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xbe"), "water closet", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x82"), "passport control", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x83"), "customs", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x84"), "baggage claim", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x85"), "left luggage", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9a\xa0"), "warning", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb8"), "children crossing", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9b\x94"), "no entry", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xab"), "prohibited", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb3"), "no bicycles", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xad"), "no smoking", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xaf"), "no littering", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb1"), "non-potable water", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb7"), "no pedestrians", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb5"), "no mobile phones", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x9e"), - "no one under eighteen", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x98\xa2"), "radioactive", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x98\xa3"), "biohazard", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\xac\x86"), "up arrow", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x86\x97"), "up-right arrow", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9e\xa1"), "right arrow", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x86\x98"), "down-right arrow", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\xac\x87"), "down arrow", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x86\x99"), "down-left arrow", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\xac\x85"), "left arrow", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x86\x96"), "up-left arrow", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x86\x95"), "up-down arrow", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x86\x94"), "left-right arrow", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x86\xa9"), - "right arrow curving left", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x86\xaa"), - "left arrow curving right", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\xa4\xb4"), "right arrow curving up", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\xa4\xb5"), - "right arrow curving down", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x83"), - "clockwise vertical arrows", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x84"), - "counterclockwise arrows button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x99"), "BACK arrow", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x9a"), "END arrow", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x9b"), "ON! arrow", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x9c"), "SOON arrow", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x9d"), "TOP arrow", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x90"), "place of worship", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9a\x9b"), "atom symbol", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x89"), "om", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9c\xa1"), "star of David", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x98\xb8"), "wheel of dharma", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x98\xaf"), "yin yang", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9c\x9d"), "latin cross", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x98\xa6"), "orthodox cross", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x98\xaa"), "star and crescent", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x98\xae"), "peace symbol", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x95\x8e"), "menorah", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xaf"), - "dotted six-pointed star", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x99\x88"), "Aries", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x99\x89"), "Taurus", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x99\x8a"), "Gemini", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x99\x8b"), "Cancer", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x99\x8c"), "Leo", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x99\x8d"), "Virgo", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x99\x8e"), "Libra", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x99\x8f"), "Scorpio", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x99\x90"), "Sagittarius", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x99\x91"), "Capricorn", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x99\x92"), "Aquarius", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x99\x93"), "Pisces", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9b\x8e"), "Ophiuchus", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x80"), - "shuffle tracks button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x81"), "repeat button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x82"), - "repeat single button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x96\xb6"), "play button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x8f\xa9"), "fast-forward button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x8f\xad"), "next track button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x8f\xaf"), "play or pause button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x97\x80"), "reverse button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x8f\xaa"), "fast reverse button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x8f\xae"), "last track button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xbc"), "upwards button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x8f\xab"), "fast up button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xbd"), "downwards button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x8f\xac"), "fast down button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x8f\xb8"), "pause button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x8f\xb9"), "stop button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x8f\xba"), "record button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x8f\x8f"), "eject button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa6"), "cinema", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x85"), "dim button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x86"), "bright button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb6"), "antenna bars", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb3"), "vibration mode", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb4"), "mobile phone off", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x99\x80"), "female sign", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x99\x82"), "male sign", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9a\xa7"), "transgender symbol", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9a\x95"), "medical symbol", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x99\xbe"), "infinity", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x99\xbb"), "recycling symbol", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9a\x9c"), "fleur-de-lis", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb1"), "trident emblem", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x93\x9b"), "name badge", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb0"), - "Japanese symbol for beginner", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\xad\x95"), "hollow red circle", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9c\x85"), "check mark button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x98\x91"), "check box with check", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9c\x94"), "check mark", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9c\x96"), "multiplication sign", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9d\x8c"), "cross mark", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9d\x8e"), "cross mark button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9e\x95"), "plus sign", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9e\x96"), "minus sign", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9e\x97"), "division sign", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9e\xb0"), "curly loop", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9e\xbf"), "double curly loop", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe3\x80\xbd"), "part alternation mark", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9c\xb3"), "eight-spoked asterisk", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9c\xb4"), "eight-pointed star", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9d\x87"), "sparkle", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x80\xbc"), - "double exclamation mark", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x81\x89"), - "exclamation question mark", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9d\x93"), "question mark", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9d\x94"), "white question mark", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9d\x95"), "white exclamation mark", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9d\x97"), "exclamation mark", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe3\x80\xb0"), "wavy dash", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xc2\xa9"), "copyright", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xc2\xae"), "registered", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x84\xa2"), "trade mark", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("#\xef\xb8\x8f\xe2\x83\xa3"), "keycap: #", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("#\xe2\x83\xa3"), "keycap: #", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("*\xef\xb8\x8f\xe2\x83\xa3"), "keycap: *", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("*\xe2\x83\xa3"), "keycap: *", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("0\xef\xb8\x8f\xe2\x83\xa3"), "keycap: 0", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("0\xe2\x83\xa3"), "keycap: 0", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("1\xef\xb8\x8f\xe2\x83\xa3"), "keycap: 1", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("1\xe2\x83\xa3"), "keycap: 1", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("2\xef\xb8\x8f\xe2\x83\xa3"), "keycap: 2", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("2\xe2\x83\xa3"), "keycap: 2", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("3\xef\xb8\x8f\xe2\x83\xa3"), "keycap: 3", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("3\xe2\x83\xa3"), "keycap: 3", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("4\xef\xb8\x8f\xe2\x83\xa3"), "keycap: 4", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("4\xe2\x83\xa3"), "keycap: 4", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("5\xef\xb8\x8f\xe2\x83\xa3"), "keycap: 5", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("5\xe2\x83\xa3"), "keycap: 5", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("6\xef\xb8\x8f\xe2\x83\xa3"), "keycap: 6", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("6\xe2\x83\xa3"), "keycap: 6", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("7\xef\xb8\x8f\xe2\x83\xa3"), "keycap: 7", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("7\xe2\x83\xa3"), "keycap: 7", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("8\xef\xb8\x8f\xe2\x83\xa3"), "keycap: 8", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("8\xe2\x83\xa3"), "keycap: 8", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("9\xef\xb8\x8f\xe2\x83\xa3"), "keycap: 9", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("9\xe2\x83\xa3"), "keycap: 9", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x9f"), "keycap: 10", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xa0"), - "input latin uppercase", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xa1"), - "input latin lowercase", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xa2"), "input numbers", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xa3"), "input symbols", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xa4"), - "input latin letters", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x85\xb0"), - "A button (blood type)", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x86\x8e"), - "AB button (blood type)", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x85\xb1"), - "B button (blood type)", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x86\x91"), "CL button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x86\x92"), "COOL button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x86\x93"), "FREE button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x84\xb9"), "information", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x86\x94"), "ID button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x93\x82"), "circled M", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x86\x95"), "NEW button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x86\x96"), "NG button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x85\xbe"), - "O button (blood type)", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x86\x97"), "OK button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x85\xbf"), "P button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x86\x98"), "SOS button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x86\x99"), "UP! button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x86\x9a"), "VS button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x88\x81"), - "Japanese “here” button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x88\x82"), - "Japanese “service charge” button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x88\xb7"), - "Japanese “monthly amount” button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x88\xb6"), - "Japanese “not free of charge” button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x88\xaf"), - "Japanese “reserved” button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x89\x90"), - "Japanese “bargain” button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x88\xb9"), - "Japanese “discount” button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x88\x9a"), - "Japanese “free of charge” button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x88\xb2"), - "Japanese “prohibited” button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x89\x91"), - "Japanese “acceptable” button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x88\xb8"), - "Japanese “application” button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x88\xb4"), - "Japanese “passing grade” button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x88\xb3"), - "Japanese “vacancy” button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe3\x8a\x97"), - "Japanese “congratulations” button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe3\x8a\x99"), - "Japanese “secret” button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x88\xba"), - "Japanese “open for business” button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x88\xb5"), - "Japanese “no vacancy” button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb4"), "red circle", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9f\xa0"), "orange circle", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9f\xa1"), "yellow circle", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9f\xa2"), "green circle", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb5"), "blue circle", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9f\xa3"), "purple circle", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9f\xa4"), "brown circle", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9a\xab"), "black circle", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x9a\xaa"), "white circle", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9f\xa5"), "red square", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9f\xa7"), "orange square", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9f\xa8"), "yellow square", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9f\xa9"), "green square", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9f\xa6"), "blue square", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9f\xaa"), "purple square", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x9f\xab"), "brown square", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\xac\x9b"), "black large square", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\xac\x9c"), "white large square", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x97\xbc"), "black medium square", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x97\xbb"), "white medium square", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x97\xbe"), - "black medium-small square", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x97\xbd"), - "white medium-small square", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x96\xaa"), "black small square", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xe2\x96\xab"), "white small square", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb6"), - "large orange diamond", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb7"), "large blue diamond", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb8"), - "small orange diamond", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb9"), "small blue diamond", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xba"), - "red triangle pointed up", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xbb"), - "red triangle pointed down", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x92\xa0"), "diamond with a dot", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\x98"), "radio button", emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb3"), - "white square button", - emoji::EmojiCategory::Symbols}, - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb2"), - "black square button", - emoji::EmojiCategory::Symbols}, -}; - -const std::vector emoji::Provider::flags = { - // Flags - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x81"), "chequered flag", emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa9"), "triangular flag", emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x8c"), "crossed flags", emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb4"), "black flag", emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb3"), "white flag", emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb3\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f\x8c\x88"), - "rainbow flag", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb3\xe2\x80\x8d\xf0\x9f\x8c\x88"), - "rainbow flag", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb3\xef\xb8\x8f\xe2\x80\x8d\xe2\x9a\xa7"), - "transgender flag", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb3\xe2\x80\x8d\xe2\x9a\xa7"), - "transgender flag", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb4\xe2\x80\x8d\xe2\x98\xa0"), - "pirate flag", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xa8"), - "flag: Ascension Island", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xa9"), - "flag: Andorra", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xaa"), - "flag: United Arab Emirates", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xab"), - "flag: Afghanistan", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xac"), - "flag: Antigua & Barbuda", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xae"), - "flag: Anguilla", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb1"), - "flag: Albania", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb2"), - "flag: Armenia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb4"), - "flag: Angola", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb6"), - "flag: Antarctica", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb7"), - "flag: Argentina", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb8"), - "flag: American Samoa", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb9"), - "flag: Austria", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xba"), - "flag: Australia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xbc"), - "flag: Aruba", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xbd"), - "flag: Åland Islands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xbf"), - "flag: Azerbaijan", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xa6"), - "flag: Bosnia & Herzegovina", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xa7"), - "flag: Barbados", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xa9"), - "flag: Bangladesh", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xaa"), - "flag: Belgium", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xab"), - "flag: Burkina Faso", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xac"), - "flag: Bulgaria", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xad"), - "flag: Bahrain", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xae"), - "flag: Burundi", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xaf"), - "flag: Benin", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb1"), - "flag: St. Barthélemy", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb2"), - "flag: Bermuda", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb3"), - "flag: Brunei", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb4"), - "flag: Bolivia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb6"), - "flag: Caribbean Netherlands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb7"), - "flag: Brazil", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb8"), - "flag: Bahamas", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb9"), - "flag: Bhutan", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xbb"), - "flag: Bouvet Island", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xbc"), - "flag: Botswana", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xbe"), - "flag: Belarus", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xbf"), - "flag: Belize", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xa6"), - "flag: Canada", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xa8"), - "flag: Cocos (Keeling) Islands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xa9"), - "flag: Congo - Kinshasa", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xab"), - "flag: Central African Republic", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xac"), - "flag: Congo - Brazzaville", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xad"), - "flag: Switzerland", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xae"), - "flag: Côte d’Ivoire", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb0"), - "flag: Cook Islands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb1"), - "flag: Chile", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb2"), - "flag: Cameroon", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb3"), - "flag: China", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb4"), - "flag: Colombia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb5"), - "flag: Clipperton Island", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb7"), - "flag: Costa Rica", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xba"), - "flag: Cuba", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbb"), - "flag: Cape Verde", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbc"), - "flag: Curaçao", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbd"), - "flag: Christmas Island", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbe"), - "flag: Cyprus", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbf"), - "flag: Czechia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xaa"), - "flag: Germany", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xac"), - "flag: Diego Garcia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xaf"), - "flag: Djibouti", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xb0"), - "flag: Denmark", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xb2"), - "flag: Dominica", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xb4"), - "flag: Dominican Republic", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xbf"), - "flag: Algeria", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xa6"), - "flag: Ceuta & Melilla", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xa8"), - "flag: Ecuador", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xaa"), - "flag: Estonia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xac"), - "flag: Egypt", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xad"), - "flag: Western Sahara", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xb7"), - "flag: Eritrea", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xb8"), - "flag: Spain", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xb9"), - "flag: Ethiopia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xba"), - "flag: European Union", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xae"), - "flag: Finland", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xaf"), - "flag: Fiji", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xb0"), - "flag: Falkland Islands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xb2"), - "flag: Micronesia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xb4"), - "flag: Faroe Islands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xb7"), - "flag: France", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xa6"), - "flag: Gabon", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xa7"), - "flag: United Kingdom", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xa9"), - "flag: Grenada", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xaa"), - "flag: Georgia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xab"), - "flag: French Guiana", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xac"), - "flag: Guernsey", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xad"), - "flag: Ghana", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xae"), - "flag: Gibraltar", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb1"), - "flag: Greenland", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb2"), - "flag: Gambia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb3"), - "flag: Guinea", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb5"), - "flag: Guadeloupe", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb6"), - "flag: Equatorial Guinea", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb7"), - "flag: Greece", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb8"), - "flag: South Georgia & South Sandwich Islands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb9"), - "flag: Guatemala", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xba"), - "flag: Guam", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xbc"), - "flag: Guinea-Bissau", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xbe"), - "flag: Guyana", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb0"), - "flag: Hong Kong SAR China", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb2"), - "flag: Heard & McDonald Islands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb3"), - "flag: Honduras", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb7"), - "flag: Croatia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb9"), - "flag: Haiti", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xba"), - "flag: Hungary", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xa8"), - "flag: Canary Islands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xa9"), - "flag: Indonesia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xaa"), - "flag: Ireland", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb1"), - "flag: Israel", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb2"), - "flag: Isle of Man", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb3"), - "flag: India", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb4"), - "flag: British Indian Ocean Territory", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb6"), - "flag: Iraq", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb7"), - "flag: Iran", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb8"), - "flag: Iceland", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb9"), - "flag: Italy", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xaf\xf0\x9f\x87\xaa"), - "flag: Jersey", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xaf\xf0\x9f\x87\xb2"), - "flag: Jamaica", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xaf\xf0\x9f\x87\xb4"), - "flag: Jordan", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xaf\xf0\x9f\x87\xb5"), - "flag: Japan", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xaa"), - "flag: Kenya", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xac"), - "flag: Kyrgyzstan", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xad"), - "flag: Cambodia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xae"), - "flag: Kiribati", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xb2"), - "flag: Comoros", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xb3"), - "flag: St. Kitts & Nevis", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xb5"), - "flag: North Korea", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xb7"), - "flag: South Korea", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xbc"), - "flag: Kuwait", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xbe"), - "flag: Cayman Islands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xbf"), - "flag: Kazakhstan", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xa6"), - "flag: Laos", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xa7"), - "flag: Lebanon", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xa8"), - "flag: St. Lucia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xae"), - "flag: Liechtenstein", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xb0"), - "flag: Sri Lanka", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xb7"), - "flag: Liberia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xb8"), - "flag: Lesotho", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xb9"), - "flag: Lithuania", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xba"), - "flag: Luxembourg", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xbb"), - "flag: Latvia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xbe"), - "flag: Libya", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xa6"), - "flag: Morocco", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xa8"), - "flag: Monaco", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xa9"), - "flag: Moldova", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xaa"), - "flag: Montenegro", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xab"), - "flag: St. Martin", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xac"), - "flag: Madagascar", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xad"), - "flag: Marshall Islands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb0"), - "flag: North Macedonia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb1"), - "flag: Mali", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb2"), - "flag: Myanmar (Burma)", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb3"), - "flag: Mongolia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb4"), - "flag: Macao SAR China", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb5"), - "flag: Northern Mariana Islands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb6"), - "flag: Martinique", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb7"), - "flag: Mauritania", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb8"), - "flag: Montserrat", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb9"), - "flag: Malta", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xba"), - "flag: Mauritius", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbb"), - "flag: Maldives", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbc"), - "flag: Malawi", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbd"), - "flag: Mexico", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbe"), - "flag: Malaysia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbf"), - "flag: Mozambique", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xa6"), - "flag: Namibia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xa8"), - "flag: New Caledonia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xaa"), - "flag: Niger", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xab"), - "flag: Norfolk Island", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xac"), - "flag: Nigeria", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xae"), - "flag: Nicaragua", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xb1"), - "flag: Netherlands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xb4"), - "flag: Norway", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xb5"), - "flag: Nepal", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xb7"), - "flag: Nauru", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xba"), - "flag: Niue", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xbf"), - "flag: New Zealand", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb4\xf0\x9f\x87\xb2"), - "flag: Oman", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xa6"), - "flag: Panama", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xaa"), - "flag: Peru", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xab"), - "flag: French Polynesia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xac"), - "flag: Papua New Guinea", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xad"), - "flag: Philippines", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb0"), - "flag: Pakistan", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb1"), - "flag: Poland", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb2"), - "flag: St. Pierre & Miquelon", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb3"), - "flag: Pitcairn Islands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb7"), - "flag: Puerto Rico", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb8"), - "flag: Palestinian Territories", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb9"), - "flag: Portugal", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xbc"), - "flag: Palau", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xbe"), - "flag: Paraguay", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb6\xf0\x9f\x87\xa6"), - "flag: Qatar", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xaa"), - "flag: Réunion", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xb4"), - "flag: Romania", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xb8"), - "flag: Serbia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xba"), - "flag: Russia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xbc"), - "flag: Rwanda", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xa6"), - "flag: Saudi Arabia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xa7"), - "flag: Solomon Islands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xa8"), - "flag: Seychelles", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xa9"), - "flag: Sudan", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xaa"), - "flag: Sweden", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xac"), - "flag: Singapore", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xad"), - "flag: St. Helena", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xae"), - "flag: Slovenia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xaf"), - "flag: Svalbard & Jan Mayen", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb0"), - "flag: Slovakia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb1"), - "flag: Sierra Leone", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb2"), - "flag: San Marino", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb3"), - "flag: Senegal", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb4"), - "flag: Somalia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb7"), - "flag: Suriname", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb8"), - "flag: South Sudan", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb9"), - "flag: São Tomé & Príncipe", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xbb"), - "flag: El Salvador", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xbd"), - "flag: Sint Maarten", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xbe"), - "flag: Syria", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xbf"), - "flag: Eswatini", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xa6"), - "flag: Tristan da Cunha", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xa8"), - "flag: Turks & Caicos Islands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xa9"), - "flag: Chad", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xab"), - "flag: French Southern Territories", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xac"), - "flag: Togo", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xad"), - "flag: Thailand", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xaf"), - "flag: Tajikistan", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb0"), - "flag: Tokelau", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb1"), - "flag: Timor-Leste", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb2"), - "flag: Turkmenistan", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb3"), - "flag: Tunisia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb4"), - "flag: Tonga", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb7"), - "flag: Turkey", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb9"), - "flag: Trinidad & Tobago", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xbb"), - "flag: Tuvalu", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xbc"), - "flag: Taiwan", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xbf"), - "flag: Tanzania", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xa6"), - "flag: Ukraine", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xac"), - "flag: Uganda", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xb2"), - "flag: U.S. Outlying Islands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xb3"), - "flag: United Nations", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xb8"), - "flag: United States", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xbe"), - "flag: Uruguay", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xbf"), - "flag: Uzbekistan", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xa6"), - "flag: Vatican City", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xa8"), - "flag: St. Vincent & Grenadines", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xaa"), - "flag: Venezuela", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xac"), - "flag: British Virgin Islands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xae"), - "flag: U.S. Virgin Islands", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xb3"), - "flag: Vietnam", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xba"), - "flag: Vanuatu", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xbc\xf0\x9f\x87\xab"), - "flag: Wallis & Futuna", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xbc\xf0\x9f\x87\xb8"), - "flag: Samoa", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xbd\xf0\x9f\x87\xb0"), - "flag: Kosovo", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xbe\xf0\x9f\x87\xaa"), - "flag: Yemen", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xbe\xf0\x9f\x87\xb9"), - "flag: Mayotte", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xbf\xf0\x9f\x87\xa6"), - "flag: South Africa", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xbf\xf0\x9f\x87\xb2"), - "flag: Zambia", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x87\xbf\xf0\x9f\x87\xbc"), - "flag: Zimbabwe", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb4\xf3\xa0\x81\xa7\xf3\xa0\x81\xa2\xf3\xa0\x81\xa5\xf3\xa0" - "\x81\xae\xf3\xa0\x81\xa7\xf3\xa0\x81\xbf"), - "flag: England", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb4\xf3\xa0\x81\xa7\xf3\xa0\x81\xa2\xf3\xa0\x81\xb3\xf3\xa0" - "\x81\xa3\xf3\xa0\x81\xb4\xf3\xa0\x81\xbf"), - "flag: Scotland", - emoji::EmojiCategory::Flags}, - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb4\xf3\xa0\x81\xa7\xf3\xa0\x81\xa2\xf3\xa0\x81\xb7\xf3\xa0" - "\x81\xac\xf3\xa0\x81\xb3\xf3\xa0\x81\xbf"), - "flag: Wales", - emoji::EmojiCategory::Flags}, -}; diff --git a/src/emoji/Provider.h b/src/emoji/Provider.h index ed77b5ac..ad03eb26 100644 --- a/src/emoji/Provider.h +++ b/src/emoji/Provider.h @@ -59,14 +59,6 @@ class Provider public: // all emoji for QML purposes static const QVector emoji; - static const std::vector people; - static const std::vector nature; - static const std::vector food; - static const std::vector activity; - static const std::vector travel; - static const std::vector objects; - static const std::vector symbols; - static const std::vector flags; }; } // namespace emoji From 921379a4cc3bc6381c4562bfdb9ce0dcde6b1f2c Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Tue, 17 Nov 2020 02:37:43 +0100 Subject: [PATCH 08/35] Send typing updates from QML --- src/ChatPage.cpp | 47 ---------------------------------- src/ChatPage.h | 4 --- src/TextInputWidget.cpp | 30 ---------------------- src/TextInputWidget.h | 10 -------- src/timeline/InputBar.cpp | 41 +++++++++++++++++++++++++++++ src/timeline/InputBar.h | 16 +++++++++++- src/timeline/TimelineModel.cpp | 1 - 7 files changed, 56 insertions(+), 93 deletions(-) diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index c703d95f..1b235a95 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -141,9 +141,6 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) text_input_ = new TextInputWidget(this); contentLayout_->addWidget(text_input_); - typingRefresher_ = new QTimer(this); - typingRefresher_->setInterval(TYPING_REFRESH_TIMEOUT); - connect(this, &ChatPage::connectionLost, this, [this]() { nhlog::net()->info("connectivity lost"); isConnected_ = false; @@ -221,9 +218,7 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) connect(room_list_, &RoomList::roomChanged, this, [this](QString room_id) { this->current_room_ = room_id; }); - connect(room_list_, &RoomList::roomChanged, text_input_, &TextInputWidget::stopTyping); connect(room_list_, &RoomList::roomChanged, splitter, &Splitter::showChatView); - connect(room_list_, &RoomList::roomChanged, text_input_, &TextInputWidget::focusLineEdit); connect( room_list_, &RoomList::roomChanged, view_manager_, &TimelineViewManager::setHistoryView); @@ -237,27 +232,6 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) room_list_->removeRoom(room_id, currentRoom() == room_id); }); - connect( - text_input_, &TextInputWidget::startedTyping, this, &ChatPage::sendTypingNotifications); - connect(typingRefresher_, &QTimer::timeout, this, &ChatPage::sendTypingNotifications); - connect(text_input_, &TextInputWidget::stoppedTyping, this, [this]() { - if (!userSettings_->typingNotifications()) - return; - - typingRefresher_->stop(); - - if (current_room_.isEmpty()) - return; - - http::client()->stop_typing( - current_room_.toStdString(), [](mtx::http::RequestErr err) { - if (err) { - nhlog::net()->warn("failed to stop typing notifications: {}", - err->matrix_error.error); - } - }); - }); - connect(view_manager_, &TimelineViewManager::updateRoomsLastMessage, room_list_, @@ -435,12 +409,6 @@ ChatPage::resetUI() emit unreadMessages(0); } -void -ChatPage::focusMessageInput() -{ - this->text_input_->focusLineEdit(); -} - void ChatPage::deleteConfigs() { @@ -1099,21 +1067,6 @@ ChatPage::receivedSessionKey(const std::string &room_id, const std::string &sess view_manager_->receivedSessionKey(room_id, session_id); } -void -ChatPage::sendTypingNotifications() -{ - if (!userSettings_->typingNotifications()) - return; - - http::client()->start_typing( - current_room_.toStdString(), 10'000, [](mtx::http::RequestErr err) { - if (err) { - nhlog::net()->warn("failed to send typing notification: {}", - err->matrix_error.error); - } - }); -} - QString ChatPage::status() const { diff --git a/src/ChatPage.h b/src/ChatPage.h index 7eb37f04..37abafa0 100644 --- a/src/ChatPage.h +++ b/src/ChatPage.h @@ -100,7 +100,6 @@ public: //! Show the room/group list (if it was visible). void showSideBars(); void initiateLogout(); - void focusMessageInput(); QString status() const; void setStatus(const QString &status); @@ -191,7 +190,6 @@ private slots: void removeRoom(const QString &room_id); void dropToLoginPage(const QString &msg); - void sendTypingNotifications(); void handleSyncResponse(const mtx::responses::Sync &res); private: @@ -265,8 +263,6 @@ private: popups::UserMentions *user_mentions_popup_; - QTimer *typingRefresher_; - // Global user settings. QSharedPointer userSettings_; diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp index 92449231..30589b61 100644 --- a/src/TextInputWidget.cpp +++ b/src/TextInputWidget.cpp @@ -83,12 +83,6 @@ FilteredTextEdit::FilteredTextEdit(QWidget *parent) insertCompletion(emoji); }); - typingTimer_ = new QTimer(this); - typingTimer_->setInterval(1000); - typingTimer_->setSingleShot(true); - - connect(typingTimer_, &QTimer::timeout, this, &FilteredTextEdit::stopTyping); - connect(this, &FilteredTextEdit::resultsRetrieved, this, &FilteredTextEdit::showResults); connect( &suggestionsPopup_, &SuggestionsPopup::itemSelected, this, [this](const QString &text) { @@ -164,13 +158,6 @@ FilteredTextEdit::keyPressEvent(QKeyEvent *event) if (event->modifiers() == Qt::ControlModifier && event->key() == Qt::Key_U) QTextEdit::setText(""); - if (!isModifier) { - if (!typingTimer_->isActive()) - emit startedTyping(); - - typingTimer_->start(); - } - // calculate the new query if (textCursor().position() < atTriggerPosition_ || !isAnchorValid()) { resetAnchor(); @@ -264,7 +251,6 @@ FilteredTextEdit::keyPressEvent(QKeyEvent *event) } if (!(event->modifiers() & Qt::ShiftModifier)) { - stopTyping(); submit(); } else { QTextEdit::keyPressEvent(event); @@ -351,13 +337,6 @@ FilteredTextEdit::keyPressEvent(QKeyEvent *event) } } -void -FilteredTextEdit::stopTyping() -{ - typingTimer_->stop(); - emit stoppedTyping(); -} - QRect FilteredTextEdit::completerRect() { @@ -494,15 +473,6 @@ TextInputWidget::TextInputWidget(QWidget *parent) connect(sendMessageBtn_, &FlatButton::clicked, input_, &FilteredTextEdit::submit); connect(sendFileBtn_, SIGNAL(clicked()), this, SLOT(openFileSelection())); - connect(input_, &FilteredTextEdit::startedTyping, this, &TextInputWidget::startedTyping); - - connect(input_, &FilteredTextEdit::stoppedTyping, this, &TextInputWidget::stoppedTyping); -} - -void -TextInputWidget::stopTyping() -{ - input_->stopTyping(); } void diff --git a/src/TextInputWidget.h b/src/TextInputWidget.h index afd29439..c62a98be 100644 --- a/src/TextInputWidget.h +++ b/src/TextInputWidget.h @@ -43,8 +43,6 @@ class FilteredTextEdit : public QTextEdit public: explicit FilteredTextEdit(QWidget *parent = nullptr); - void stopTyping(); - QSize sizeHint() const override; QSize minimumSizeHint() const override; @@ -52,8 +50,6 @@ public: signals: void heightChanged(int height); - void startedTyping(); - void stoppedTyping(); void startedUpload(); //! Trigger the suggestion popup. @@ -81,7 +77,6 @@ private: int trigger_pos_; // Where emoji completer was triggered size_t history_index_; QCompleter *completer_; - QTimer *typingTimer_; SuggestionsPopup suggestionsPopup_; @@ -136,8 +131,6 @@ class TextInputWidget : public QWidget public: TextInputWidget(QWidget *parent = nullptr); - void stopTyping(); - QColor borderColor() const { return borderColor_; } void setBorderColor(QColor &color) { borderColor_ = color; } void disableInput() @@ -164,9 +157,6 @@ signals: void sendUnbanRoomRequest(const QString &userid, const QString &reason); void changeRoomNick(const QString &displayname); - void startedTyping(); - void stoppedTyping(); - protected: void focusInEvent(QFocusEvent *event) override; void paintEvent(QPaintEvent *) override; diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp index dc287f94..6603287b 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp @@ -114,6 +114,11 @@ InputBar::paste(bool fromMouse) void InputBar::updateState(int selectionStart_, int selectionEnd_, int cursorPosition_, QString text_) { + if (text_.isEmpty()) + stopTyping(); + else + startTyping(); + selectionStart = selectionStart_; selectionEnd = selectionEnd_; cursorPosition = cursorPosition_; @@ -556,3 +561,39 @@ InputBar::callButton() } } } + +void +InputBar::startTyping() +{ + if (!typingRefresh_.isActive()) { + typingRefresh_.start(); + + if (ChatPage::instance()->userSettings()->typingNotifications()) { + http::client()->start_typing( + room->roomId().toStdString(), 10'000, [](mtx::http::RequestErr err) { + if (err) { + nhlog::net()->warn( + "failed to send typing notification: {}", + err->matrix_error.error); + } + }); + } + } + typingTimeout_.start(); +} +void +InputBar::stopTyping() +{ + typingRefresh_.stop(); + typingTimeout_.stop(); + + if (!ChatPage::instance()->userSettings()->typingNotifications()) + return; + + http::client()->stop_typing(room->roomId().toStdString(), [](mtx::http::RequestErr err) { + if (err) { + nhlog::net()->warn("failed to stop typing notifications: {}", + err->matrix_error.error); + } + }); +} diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h index a52a3904..0e9ef592 100644 --- a/src/timeline/InputBar.h +++ b/src/timeline/InputBar.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -19,7 +20,14 @@ public: InputBar(TimelineModel *parent) : QObject() , room(parent) - {} + { + typingRefresh_.setInterval(10'000); + typingRefresh_.setSingleShot(true); + typingTimeout_.setInterval(5'000); + typingTimeout_.setSingleShot(true); + connect(&typingRefresh_, &QTimer::timeout, this, &InputBar::startTyping); + connect(&typingTimeout_, &QTimer::timeout, this, &InputBar::stopTyping); + } public slots: void send(); @@ -29,6 +37,10 @@ public slots: bool uploading() const { return uploading_; } void callButton(); +private slots: + void startTyping(); + void stopTyping(); + signals: void insertText(QString text); void uploadingChanged(bool value); @@ -69,6 +81,8 @@ private: } } + QTimer typingRefresh_; + QTimer typingTimeout_; TimelineModel *room; QString text; std::deque history_; diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 8b80ea51..4cbd5777 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -800,7 +800,6 @@ void TimelineModel::replyAction(QString id) { setReply(id); - ChatPage::instance()->focusMessageInput(); } RelatedInfo From d14a5f80676a695b3a087bd1378e8057fc7ffc13 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Tue, 17 Nov 2020 13:25:16 +0100 Subject: [PATCH 09/35] Reimplement message history --- resources/qml/MessageInput.qml | 5 ++- src/timeline/InputBar.cpp | 66 ++++++++++++++++++++++++++-------- src/timeline/InputBar.h | 5 ++- 3 files changed, 60 insertions(+), 16 deletions(-) diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index da76c6ac..236cc009 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -84,7 +84,10 @@ Rectangle { TimelineManager.timeline.input.send(); textArea.clear(); event.accepted = true; - } + } else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_P) + textArea.text = TimelineManager.timeline.input.previousText(); + else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_N) + textArea.text = TimelineManager.timeline.input.nextText(); } Connections { diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp index 6603287b..1eaaaa64 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp @@ -119,39 +119,77 @@ InputBar::updateState(int selectionStart_, int selectionEnd_, int cursorPosition else startTyping(); + if (text_ != text()) { + if (history_.empty()) + history_.push_front(text_); + else + history_.front() = text_; + history_index_ = 0; + } + selectionStart = selectionStart_; selectionEnd = selectionEnd_; cursorPosition = cursorPosition_; - text = text_; +} + +QString +InputBar::text() const +{ + if (history_index_ < history_.size()) + return history_.at(history_index_); + + return ""; +} + +QString +InputBar::previousText() +{ + history_index_++; + if (history_index_ >= INPUT_HISTORY_SIZE) + history_index_ = INPUT_HISTORY_SIZE; + else if (text().isEmpty()) + history_index_--; + + return text(); +} + +QString +InputBar::nextText() +{ + history_index_--; + if (history_index_ >= INPUT_HISTORY_SIZE) + history_index_ = 0; + + return text(); } void InputBar::send() { - if (text.trimmed().isEmpty()) + if (text().trimmed().isEmpty()) return; - if (history_.size() == INPUT_HISTORY_SIZE) - history_.pop_back(); - history_.push_front(text); - history_index_ = 0; - - if (text.startsWith('/')) { - int command_end = text.indexOf(' '); + if (text().startsWith('/')) { + int command_end = text().indexOf(' '); if (command_end == -1) - command_end = text.size(); - auto name = text.mid(1, command_end - 1); - auto args = text.mid(command_end + 1); + command_end = text().size(); + auto name = text().mid(1, command_end - 1); + auto args = text().mid(command_end + 1); if (name.isEmpty() || name == "/") { message(args); } else { command(name, args); } } else { - message(text); + message(text()); } - nhlog::ui()->debug("Send: {}", text.toStdString()); + nhlog::ui()->debug("Send: {}", text().toStdString()); + + if (history_.size() == INPUT_HISTORY_SIZE) + history_.pop_back(); + history_.push_front(""); + history_index_ = 0; } void diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h index 0e9ef592..5e66e86f 100644 --- a/src/timeline/InputBar.h +++ b/src/timeline/InputBar.h @@ -30,6 +30,10 @@ public: } public slots: + QString text() const; + QString previousText(); + QString nextText(); + void send(); void paste(bool fromMouse); void updateState(int selectionStart, int selectionEnd, int cursorPosition, QString text); @@ -84,7 +88,6 @@ private: QTimer typingRefresh_; QTimer typingTimeout_; TimelineModel *room; - QString text; std::deque history_; std::size_t history_index_ = 0; int selectionStart = 0, selectionEnd = 0, cursorPosition = 0; From 9d68d594656fe88cc21f2d6b355c2a537653d762 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Thu, 19 Nov 2020 17:15:28 +0100 Subject: [PATCH 10/35] Reenable Ctrl+U --- resources/qml/MessageInput.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index 236cc009..a5c84a17 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -84,7 +84,9 @@ Rectangle { TimelineManager.timeline.input.send(); textArea.clear(); event.accepted = true; - } else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_P) + } else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_U) + textArea.clear(); + else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_P) textArea.text = TimelineManager.timeline.input.previousText(); else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_N) textArea.text = TimelineManager.timeline.input.nextText(); From cabeb1464c85d911eea427bd48e8188facde8e56 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 20 Nov 2020 01:22:36 +0100 Subject: [PATCH 11/35] WIP Qml completer --- resources/qml/Completer.qml | 107 +++++++++++++++++++++++++++++++++ resources/qml/MessageInput.qml | 58 +++++++++++++++--- resources/res.qrc | 15 ++--- src/timeline/InputBar.cpp | 6 ++ src/timeline/InputBar.h | 2 + 5 files changed, 174 insertions(+), 14 deletions(-) create mode 100644 resources/qml/Completer.qml diff --git a/resources/qml/Completer.qml b/resources/qml/Completer.qml new file mode 100644 index 00000000..d53eae62 --- /dev/null +++ b/resources/qml/Completer.qml @@ -0,0 +1,107 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import QtQuick.Layouts 1.2 +import im.nheko 1.0 + +Popup { + id: popup + + property int currentIndex: -1 + property string completerName + property var completer + + function up() { + currentIndex = currentIndex - 1; + if (currentIndex == -2) + currentIndex = repeater.count - 1; + + } + + function down() { + currentIndex = currentIndex + 1; + if (currentIndex >= repeater.count) + currentIndex = -1; + + } + + function currentCompletion() { + if (currentIndex > -1 && currentIndex < repeater.count) + return completer.completionAt(currentIndex); + else + return null; + } + + onCompleterNameChanged: { + if (completerName) + completer = TimelineManager.timeline.input.completerFor(completerName); + + } + padding: 0 + onAboutToShow: currentIndex = -1 + + ColumnLayout { + anchors.fill: parent + spacing: 0 + + Repeater { + id: repeater + + model: completer + + delegate: Rectangle { + color: model.index == popup.currentIndex ? colors.window : colors.base + height: del.implicitHeight + 4 + width: del.implicitWidth + 4 + + RowLayout { + id: del + + anchors.centerIn: parent + + Avatar { + height: 24 + width: 24 + displayName: model.displayName + url: model.avatarUrl.replace("mxc://", "image://MxcImage/") + } + + Label { + text: model.displayName + color: colors.text + } + + } + + } + + } + + } + + enter: Transition { + NumberAnimation { + property: "opacity" + from: 0 + to: 1 + duration: 100 + } + + } + + exit: Transition { + NumberAnimation { + property: "opacity" + from: 1 + to: 0 + duration: 100 + } + + } + + background: Rectangle { + color: colors.base + implicitHeight: popup.contentHeight + implicitWidth: popup.contentWidth + } + +} diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index a5c84a17..a4a47a3e 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -68,28 +68,72 @@ Rectangle { TextArea { id: textArea + property int completerTriggeredAt: -1 + placeholderText: qsTr("Write a message...") placeholderTextColor: colors.buttonText color: colors.text wrapMode: TextEdit.Wrap onTextChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) - onCursorPositionChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) + onCursorPositionChanged: { + TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text); + if (cursorPosition < completerTriggeredAt) { + completerTriggeredAt = -1; + popup.close(); + } + } onSelectionStartChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) onSelectionEndChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) + // Ensure that we get escape key press events first. + Keys.onShortcutOverride: event.accepted = (completerTriggeredAt != -1 && (event.key === Qt.Key_Escape || event.key === Qt.Key_Tab || event.key === Qt.Key_Enter)) Keys.onPressed: { if (event.matches(StandardKey.Paste)) { TimelineManager.timeline.input.paste(false); event.accepted = true; + } else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_U) { + textArea.clear(); + } else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_P) { + textArea.text = TimelineManager.timeline.input.previousText(); + } else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_N) { + textArea.text = TimelineManager.timeline.input.nextText(); + } else if (event.key == Qt.Key_At) { + completerTriggeredAt = cursorPosition + 1; + popup.completerName = "user"; + popup.open(); + } else if (event.key == Qt.Key_Escape && popup.opened) { + completerTriggeredAt = -1; + event.accepted = true; + popup.close(); + } else if (event.matches(StandardKey.InsertParagraphSeparator) && popup.opened) { + var currentCompletion = popup.currentCompletion(); + popup.close(); + if (currentCompletion) { + textArea.remove(completerTriggeredAt - 1, cursorPosition); + textArea.insert(cursorPosition, currentCompletion); + event.accepted = true; + return ; + } + } else if (event.key == Qt.Key_Tab && popup.opened) { + event.accepted = true; + popup.down(); + } else if (event.key == Qt.Key_Up && popup.opened) { + event.accepted = true; + popup.up(); + } else if (event.key == Qt.Key_Down && popup.opened) { + event.accepted = true; + popup.down(); } else if (event.matches(StandardKey.InsertParagraphSeparator)) { TimelineManager.timeline.input.send(); textArea.clear(); event.accepted = true; - } else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_U) - textArea.clear(); - else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_P) - textArea.text = TimelineManager.timeline.input.previousText(); - else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_N) - textArea.text = TimelineManager.timeline.input.nextText(); + } + } + + Completer { + id: popup + + x: textArea.positionToRectangle(textArea.completerTriggeredAt).x + y: textArea.positionToRectangle(textArea.completerTriggeredAt).y - height } Connections { diff --git a/resources/res.qrc b/resources/res.qrc index 02f31498..a01907ec 100644 --- a/resources/res.qrc +++ b/resources/res.qrc @@ -123,21 +123,22 @@ qtquickcontrols2.conf qml/TimelineView.qml - qml/TopBar.qml - qml/MessageView.qml - qml/MessageInput.qml - qml/TypingIndicator.qml - qml/ReplyPopup.qml qml/ActiveCallBar.qml qml/Avatar.qml + qml/Completer.qml + qml/EncryptionIndicator.qml qml/ImageButton.qml qml/MatrixText.qml + qml/MessageInput.qml + qml/MessageView.qml qml/NhekoBusyIndicator.qml - qml/StatusIndicator.qml - qml/EncryptionIndicator.qml qml/Reactions.qml + qml/ReplyPopup.qml qml/ScrollHelper.qml + qml/StatusIndicator.qml qml/TimelineRow.qml + qml/TopBar.qml + qml/TypingIndicator.qml qml/VideoCall.qml qml/emoji/EmojiButton.qml qml/emoji/EmojiPicker.qml diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp index 1eaaaa64..82649faa 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp @@ -163,6 +163,12 @@ InputBar::nextText() return text(); } +QObject * +InputBar::completerFor(QString completerName) +{ + return nullptr; +} + void InputBar::send() { diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h index 5e66e86f..939e8dad 100644 --- a/src/timeline/InputBar.h +++ b/src/timeline/InputBar.h @@ -41,6 +41,8 @@ public slots: bool uploading() const { return uploading_; } void callButton(); + QObject *completerFor(QString completerName); + private slots: void startTyping(); void stopTyping(); From 748bf0cd988c103e66919db753d40fe19a784022 Mon Sep 17 00:00:00 2001 From: Jussi Kuokkanen Date: Wed, 2 Sep 2020 13:32:57 +0300 Subject: [PATCH 12/35] rename CompletionModel to CompletionProxyModel --- src/CompletionProxyModel.h | 20 ++++++++++++++++++++ src/TextInputWidget.cpp | 4 ++-- src/TextInputWidget.h | 4 ++-- 3 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 src/CompletionProxyModel.h diff --git a/src/CompletionProxyModel.h b/src/CompletionProxyModel.h new file mode 100644 index 00000000..ee38075e --- /dev/null +++ b/src/CompletionProxyModel.h @@ -0,0 +1,20 @@ +#pragma once + +// Class for showing a limited amount of completions at a time + +#include + +class CompletionProxyModel : public QSortFilterProxyModel +{ +public: + CompletionProxyModel(QAbstractItemModel *model, QObject *parent = nullptr) + : QSortFilterProxyModel(parent) + { + setSourceModel(model); + } + int rowCount(const QModelIndex &parent) const override + { + auto row_count = QSortFilterProxyModel::rowCount(parent); + return (row_count < 7) ? row_count : 7; + } +}; diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp index 30589b61..b46f0e5a 100644 --- a/src/TextInputWidget.cpp +++ b/src/TextInputWidget.cpp @@ -30,7 +30,7 @@ #include "Cache.h" #include "ChatPage.h" -#include "CompletionModel.h" +#include "CompletionProxyModel.h" #include "Logging.h" #include "TextInputWidget.h" #include "Utils.h" @@ -70,7 +70,7 @@ FilteredTextEdit::FilteredTextEdit(QWidget *parent) completer_->setWidget(this); auto model = new emoji::EmojiSearchModel(this); model->sort(0, Qt::AscendingOrder); - completer_->setModel((emoji_completion_model_ = new CompletionModel(model, this))); + completer_->setModel((emoji_completion_model_ = new CompletionProxyModel(model, this))); completer_->setModelSorting(QCompleter::UnsortedModel); completer_->popup()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); completer_->popup()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); diff --git a/src/TextInputWidget.h b/src/TextInputWidget.h index c62a98be..19462f70 100644 --- a/src/TextInputWidget.h +++ b/src/TextInputWidget.h @@ -31,7 +31,7 @@ struct SearchResult; -class CompletionModel; +class CompletionProxyModel; class FlatButton; class LoadingIndicator; class QCompleter; @@ -72,7 +72,7 @@ protected: private: bool emoji_popup_open_ = false; - CompletionModel *emoji_completion_model_; + CompletionProxyModel *emoji_completion_model_; std::deque true_history_, working_history_; int trigger_pos_; // Where emoji completer was triggered size_t history_index_; From 00bc87b55017f135efffb2637f2b5d009488c3df Mon Sep 17 00:00:00 2001 From: Jussi Kuokkanen Date: Thu, 3 Sep 2020 16:53:41 +0300 Subject: [PATCH 13/35] add completer interface (item roles) --- src/CompletionModelRoles.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/CompletionModelRoles.h diff --git a/src/CompletionModelRoles.h b/src/CompletionModelRoles.h new file mode 100644 index 00000000..bd6c4114 --- /dev/null +++ b/src/CompletionModelRoles.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +// Interface for completion models +namespace CompletionModel { + +// Start at Qt::UserRole * 2 to prevent clashes +enum Roles +{ + CompletionRole = Qt::UserRole * 2, // The string to replace the active completion + SearchRole, // String completer uses for search +}; + +} From 07259b9cb736469262acbb450fd451233e150c2c Mon Sep 17 00:00:00 2001 From: Jussi Kuokkanen Date: Fri, 4 Sep 2020 12:56:36 +0300 Subject: [PATCH 14/35] use completion interface in emoji completions --- src/TextInputWidget.cpp | 10 +++++++--- src/emoji/EmojiSearchModel.h | 14 ++++++++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp index b46f0e5a..6d1fdc7a 100644 --- a/src/TextInputWidget.cpp +++ b/src/TextInputWidget.cpp @@ -30,6 +30,7 @@ #include "Cache.h" #include "ChatPage.h" +#include "CompletionModelRoles.h" #include "CompletionProxyModel.h" #include "Logging.h" #include "TextInputWidget.h" @@ -71,6 +72,7 @@ FilteredTextEdit::FilteredTextEdit(QWidget *parent) auto model = new emoji::EmojiSearchModel(this); model->sort(0, Qt::AscendingOrder); completer_->setModel((emoji_completion_model_ = new CompletionProxyModel(model, this))); + emoji_completion_model_->setFilterRole(CompletionModel::SearchRole); completer_->setModelSorting(QCompleter::UnsortedModel); completer_->popup()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); completer_->popup()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); @@ -79,8 +81,8 @@ FilteredTextEdit::FilteredTextEdit(QWidget *parent) QOverload::of(&QCompleter::activated), [this](auto &index) { emoji_popup_open_ = false; - auto emoji = index.data(emoji::EmojiModel::Unicode).toString(); - insertCompletion(emoji); + auto text = index.data(CompletionModel::CompletionRole).toString(); + insertCompletion(text); }); connect(this, &FilteredTextEdit::resultsRetrieved, this, &FilteredTextEdit::showResults); @@ -297,7 +299,9 @@ FilteredTextEdit::keyPressEvent(QKeyEvent *event) if (emoji_popup_open_ && textAfterPosition(trigger_pos_).length() > 2) { // Update completion - emoji_completion_model_->setFilterRegExp(textAfterPosition(trigger_pos_)); + // Don't include the trigger token in the search + emoji_completion_model_->setFilterWildcard( + textAfterPosition(trigger_pos_).remove(0, 1)); completer_->complete(completerRect()); } diff --git a/src/emoji/EmojiSearchModel.h b/src/emoji/EmojiSearchModel.h index 13a03934..7dbe6732 100644 --- a/src/emoji/EmojiSearchModel.h +++ b/src/emoji/EmojiSearchModel.h @@ -2,6 +2,7 @@ #include "EmojiModel.h" +#include #include #include #include @@ -19,12 +20,21 @@ public: } QVariant data(const QModelIndex &index, int role = Qt::UserRole + 1) const override { - if (role == Qt::DisplayRole) { + switch (role) { + case Qt::DisplayRole: { auto emoji = QSortFilterProxyModel::data(index, role).toString(); return emoji + " :" + toShortcode(data(index, EmojiModel::ShortName).toString()) + ":"; } - return QSortFilterProxyModel::data(index, role); + case CompletionModel::CompletionRole: + return QSortFilterProxyModel::data(index, EmojiModel::Unicode); + case CompletionModel::SearchRole: { + return toShortcode( + QSortFilterProxyModel::data(index, EmojiModel::ShortName).toString()); + } + default: + return QSortFilterProxyModel::data(index, role); + } } private: From a3c4fece7e012d865ac3343ed2c5a273ac0f238f Mon Sep 17 00:00:00 2001 From: Jussi Kuokkanen Date: Mon, 7 Sep 2020 12:51:28 +0300 Subject: [PATCH 15/35] add per-room user model --- CMakeLists.txt | 1 + src/UsersModel.cpp | 28 ++++++++++++++++++++++++++++ src/UsersModel.h | 24 ++++++++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 src/UsersModel.cpp create mode 100644 src/UsersModel.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b918be7..aa81f285 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -303,6 +303,7 @@ set(SRC_FILES src/TrayIcon.cpp src/UserInfoWidget.cpp src/UserSettingsPage.cpp + src/UsersModel.cpp src/Utils.cpp src/WebRTCSession.cpp src/WelcomePage.cpp diff --git a/src/UsersModel.cpp b/src/UsersModel.cpp new file mode 100644 index 00000000..c63292bb --- /dev/null +++ b/src/UsersModel.cpp @@ -0,0 +1,28 @@ +#include "UsersModel.h" + +#include "Cache.h" +#include "CompletionModelRoles.h" + +#include + +UsersModel::UsersModel(const std::string &roomId, QObject *parent) + : QAbstractListModel(parent) +{ + roomMembers_ = cache::getMembers(roomId, 0, 9999); +} + +QVariant +UsersModel::data(const QModelIndex &index, int role) const +{ + if (hasIndex(index.row(), index.column(), index.parent())) { + switch (role) { + case CompletionModel::CompletionRole: + case CompletionModel::SearchRole: + case Qt::DisplayRole: + return roomMembers_[index.row()].display_name; + case Avatar: + return roomMembers_[index.row()].avatar; + } + } + return {}; +} diff --git a/src/UsersModel.h b/src/UsersModel.h new file mode 100644 index 00000000..09ccbf25 --- /dev/null +++ b/src/UsersModel.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +class RoomMember; + +class UsersModel : public QAbstractListModel +{ +public: + enum Roles + { + Avatar = Qt::UserRole // QImage avatar + }; + + UsersModel(const std::string &roomId, QObject *parent = nullptr); + int rowCount(const QModelIndex &parent = QModelIndex()) const override + { + return (parent == QModelIndex()) ? roomMembers_.size() : 0; + } + QVariant data(const QModelIndex &index, int role) const override; + +private: + std::vector roomMembers_; +}; From add5903fb0abc76d77ce4369c4679a95be03b433 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 20 Nov 2020 02:38:08 +0100 Subject: [PATCH 16/35] Working User completer --- CMakeLists.txt | 2 ++ resources/qml/Completer.qml | 8 +++++++- resources/qml/MessageInput.qml | 20 ++++++++++++++++---- src/CompletionModel.h | 20 -------------------- src/CompletionModelRoles.h | 2 +- src/CompletionProxyModel.h | 21 ++++++++++++++++++++- src/UsersModel.cpp | 28 ++++++++++++++++++++++------ src/UsersModel.h | 12 +++++++----- src/timeline/InputBar.cpp | 8 ++++++++ 9 files changed, 83 insertions(+), 38 deletions(-) delete mode 100644 src/CompletionModel.h diff --git a/CMakeLists.txt b/CMakeLists.txt index aa81f285..7e68db77 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -492,6 +492,7 @@ qt5_wrap_cpp(MOC_HEADERS src/ChatPage.h src/CommunitiesList.h src/CommunitiesListItem.h + src/CompletionProxyModel.h src/DeviceVerificationFlow.h src/InviteeItem.h src/LoginPage.h @@ -508,6 +509,7 @@ qt5_wrap_cpp(MOC_HEADERS src/TrayIcon.h src/UserInfoWidget.h src/UserSettingsPage.h + src/UsersModel.h src/WebRTCSession.h src/WelcomePage.h src/popups/PopupItem.h diff --git a/resources/qml/Completer.qml b/resources/qml/Completer.qml index d53eae62..2c520dec 100644 --- a/resources/qml/Completer.qml +++ b/resources/qml/Completer.qml @@ -34,11 +34,17 @@ Popup { onCompleterNameChanged: { if (completerName) completer = TimelineManager.timeline.input.completerFor(completerName); - + else + completer = undefined; } padding: 0 onAboutToShow: currentIndex = -1 + Connections { + onTimelineChanged: completer = null + target: TimelineManager + } + ColumnLayout { anchors.fill: parent spacing: 0 diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index a4a47a3e..50ff7324 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -77,14 +77,13 @@ Rectangle { onTextChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) onCursorPositionChanged: { TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text); - if (cursorPosition < completerTriggeredAt) { + if (cursorPosition <= completerTriggeredAt) { completerTriggeredAt = -1; popup.close(); } } onSelectionStartChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) onSelectionEndChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) - // Ensure that we get escape key press events first. Keys.onShortcutOverride: event.accepted = (completerTriggeredAt != -1 && (event.key === Qt.Key_Escape || event.key === Qt.Key_Tab || event.key === Qt.Key_Enter)) Keys.onPressed: { if (event.matches(StandardKey.Paste)) { @@ -97,18 +96,20 @@ Rectangle { } else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_N) { textArea.text = TimelineManager.timeline.input.nextText(); } else if (event.key == Qt.Key_At) { - completerTriggeredAt = cursorPosition + 1; + completerTriggeredAt = cursorPosition; popup.completerName = "user"; popup.open(); } else if (event.key == Qt.Key_Escape && popup.opened) { completerTriggeredAt = -1; + popup.completerName = ""; event.accepted = true; popup.close(); } else if (event.matches(StandardKey.InsertParagraphSeparator) && popup.opened) { var currentCompletion = popup.currentCompletion(); + popup.completerName = ""; popup.close(); if (currentCompletion) { - textArea.remove(completerTriggeredAt - 1, cursorPosition); + textArea.remove(completerTriggeredAt, cursorPosition); textArea.insert(cursorPosition, currentCompletion); event.accepted = true; return ; @@ -129,6 +130,17 @@ Rectangle { } } + Connections { + onTimelineChanged: { + textArea.clear(); + textArea.append(TimelineManager.timeline.input.text()); + textArea.completerTriggeredAt = -1; + popup.completerName = ""; + } + target: TimelineManager + } + // Ensure that we get escape key press events first. + Completer { id: popup diff --git a/src/CompletionModel.h b/src/CompletionModel.h deleted file mode 100644 index ed021051..00000000 --- a/src/CompletionModel.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -// Class for showing a limited amount of completions at a time - -#include - -class CompletionModel : public QSortFilterProxyModel -{ -public: - CompletionModel(QAbstractItemModel *model, QObject *parent = nullptr) - : QSortFilterProxyModel(parent) - { - setSourceModel(model); - } - int rowCount(const QModelIndex &parent) const override - { - auto row_count = QSortFilterProxyModel::rowCount(parent); - return (row_count < 7) ? row_count : 7; - } -}; diff --git a/src/CompletionModelRoles.h b/src/CompletionModelRoles.h index bd6c4114..7c7307d3 100644 --- a/src/CompletionModelRoles.h +++ b/src/CompletionModelRoles.h @@ -10,6 +10,6 @@ enum Roles { CompletionRole = Qt::UserRole * 2, // The string to replace the active completion SearchRole, // String completer uses for search + SearchRole2, // Secondary string completer uses for search }; - } diff --git a/src/CompletionProxyModel.h b/src/CompletionProxyModel.h index ee38075e..757aa990 100644 --- a/src/CompletionProxyModel.h +++ b/src/CompletionProxyModel.h @@ -4,17 +4,36 @@ #include +#include "CompletionModelRoles.h" + class CompletionProxyModel : public QSortFilterProxyModel { + Q_OBJECT + public: CompletionProxyModel(QAbstractItemModel *model, QObject *parent = nullptr) : QSortFilterProxyModel(parent) { setSourceModel(model); } - int rowCount(const QModelIndex &parent) const override + + QHash roleNames() const override + { + return this->sourceModel()->roleNames(); + } + + int rowCount(const QModelIndex &parent = QModelIndex()) const override { auto row_count = QSortFilterProxyModel::rowCount(parent); return (row_count < 7) ? row_count : 7; } + +public slots: + QVariant completionAt(int i) const + { + if (i >= 0 && i < rowCount()) + return data(index(i, 0), CompletionModel::CompletionRole); + else + return {}; + } }; diff --git a/src/UsersModel.cpp b/src/UsersModel.cpp index c63292bb..f102cff1 100644 --- a/src/UsersModel.cpp +++ b/src/UsersModel.cpp @@ -3,12 +3,23 @@ #include "Cache.h" #include "CompletionModelRoles.h" -#include - UsersModel::UsersModel(const std::string &roomId, QObject *parent) : QAbstractListModel(parent) + , room_id(roomId) { - roomMembers_ = cache::getMembers(roomId, 0, 9999); + roomMembers_ = cache::roomMembers(roomId); +} + +QHash +UsersModel::roleNames() const +{ + return { + {CompletionModel::CompletionRole, "completionRole"}, + {CompletionModel::SearchRole, "searchRole"}, + {CompletionModel::SearchRole2, "searchRole2"}, + {Roles::DisplayName, "displayName"}, + {Roles::AvatarUrl, "avatarUrl"}, + }; } QVariant @@ -19,9 +30,14 @@ UsersModel::data(const QModelIndex &index, int role) const case CompletionModel::CompletionRole: case CompletionModel::SearchRole: case Qt::DisplayRole: - return roomMembers_[index.row()].display_name; - case Avatar: - return roomMembers_[index.row()].avatar; + case Roles::DisplayName: + return QString::fromStdString( + cache::displayName(room_id, roomMembers_[index.row()])); + case CompletionModel::SearchRole2: + return QString::fromStdString(roomMembers_[index.row()]); + case Roles::AvatarUrl: + return cache::avatarUrl(QString::fromStdString(room_id), + QString::fromStdString(roomMembers_[index.row()])); } } return {}; diff --git a/src/UsersModel.h b/src/UsersModel.h index 09ccbf25..6ee8261f 100644 --- a/src/UsersModel.h +++ b/src/UsersModel.h @@ -2,23 +2,25 @@ #include -class RoomMember; - class UsersModel : public QAbstractListModel { public: enum Roles { - Avatar = Qt::UserRole // QImage avatar + AvatarUrl = Qt::UserRole, + DisplayName, }; UsersModel(const std::string &roomId, QObject *parent = nullptr); + QHash roleNames() const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override { - return (parent == QModelIndex()) ? roomMembers_.size() : 0; + (void)parent; + return roomMembers_.size(); } QVariant data(const QModelIndex &index, int role) const override; private: - std::vector roomMembers_; + std::string room_id; + std::vector roomMembers_; }; diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp index 82649faa..641d8379 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp @@ -14,12 +14,14 @@ #include "Cache.h" #include "CallManager.h" #include "ChatPage.h" +#include "CompletionProxyModel.h" #include "Logging.h" #include "MainWindow.h" #include "MatrixClient.h" #include "Olm.h" #include "TimelineModel.h" #include "UserSettingsPage.h" +#include "UsersModel.h" #include "Utils.h" #include "dialogs/PlaceCall.h" #include "dialogs/PreviewUploadOverlay.h" @@ -166,6 +168,12 @@ InputBar::nextText() QObject * InputBar::completerFor(QString completerName) { + if (completerName == "user") { + auto userModel = new UsersModel(room->roomId().toStdString()); + auto proxy = new CompletionProxyModel(userModel); + userModel->setParent(proxy); + return proxy; + } return nullptr; } From ecc7759973ae49ea718aea34c5469d2d1ba205d1 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 20 Nov 2020 04:05:31 +0100 Subject: [PATCH 17/35] Custom completer filtering --- resources/qml/MessageInput.qml | 3 ++ src/CompletionProxyModel.h | 96 ++++++++++++++++++++++++++++++++++ src/UsersModel.cpp | 9 ++-- src/UsersModel.h | 2 + 4 files changed, 107 insertions(+), 3 deletions(-) diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index 50ff7324..d9592e14 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -128,6 +128,9 @@ Rectangle { textArea.clear(); event.accepted = true; } + if (popup.opened) + popup.completer.setSearchString(textArea.getText(completerTriggeredAt, cursorPosition)); + } Connections { diff --git a/src/CompletionProxyModel.h b/src/CompletionProxyModel.h index 757aa990..ee8236e3 100644 --- a/src/CompletionProxyModel.h +++ b/src/CompletionProxyModel.h @@ -5,6 +5,7 @@ #include #include "CompletionModelRoles.h" +#include "Utils.h" class CompletionProxyModel : public QSortFilterProxyModel { @@ -15,6 +16,20 @@ public: : QSortFilterProxyModel(parent) { setSourceModel(model); + sort(0, Qt::AscendingOrder); + setFilterRole(CompletionModel::SearchRole); + + connect( + this, + &CompletionProxyModel::newSearchString, + this, + [this](QString s) { + s.remove(":"); + s.remove("@"); + searchString = s.toLower(); + invalidate(); + }, + Qt::QueuedConnection); } QHash roleNames() const override @@ -28,6 +43,79 @@ public: return (row_count < 7) ? row_count : 7; } + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const + { + if (searchString.size() < 1) + return true; + + auto source_index = sourceModel()->index(source_row, 0, source_parent); + auto role1 = sourceModel() + ->data(source_index, CompletionModel::SearchRole) + .toString() + .toLower(); + + if (role1.contains(searchString)) + return true; + // auto score = + // utils::levenshtein_distance(searchString, role1.toLower().toStdString()); + // if ((size_t)role1.size() >= searchString.size() && + // ((size_t)score) < (size_t)role1.size() - searchString.size() + 2) + // return true; + + auto role2 = sourceModel() + ->data(source_index, CompletionModel::SearchRole2) + .toString() + .toLower(); + if (role2.contains(searchString)) + return true; + // if (!role2.isEmpty()) { + // score = + // utils::levenshtein_distance(searchString, + // role2.toLower().toStdString()); + // if ((size_t)role2.size() >= searchString.size() && + // ((size_t)score) < (size_t)role2.size() - searchString.size() + 2) + // return true; + //} + + return false; + } + + bool lessThan(const QModelIndex &source_left, + const QModelIndex &source_right) const override + { + if (searchString.size() < 1) + return false; + + auto left1 = + sourceModel()->data(source_left, CompletionModel::SearchRole).toString(); + auto left2 = + sourceModel()->data(source_left, CompletionModel::SearchRole2).toString(); + auto left = left1.toLower().indexOf(searchString); + // utils::levenshtein_distance(searchString, left1.toLower().toStdString()); + if (!left2.isEmpty()) { + // left = std::min( + // utils::levenshtein_distance(searchString, + // left2.toLower().toStdString()), left); + left = std::min(left2.toLower().indexOf(searchString), left); + } + + auto right1 = + sourceModel()->data(source_right, CompletionModel::SearchRole).toString(); + auto right2 = + sourceModel()->data(source_right, CompletionModel::SearchRole2).toString(); + auto right = right1.toLower().indexOf(searchString); + // auto right = + // utils::levenshtein_distance(searchString, right1.toLower().toStdString()); + if (!right2.isEmpty()) { + // right = std::min( + // utils::levenshtein_distance(searchString, + // right2.toLower().toStdString()), right); + right = std::min(right2.toLower().indexOf(searchString), right); + } + + return left < right; + } + public slots: QVariant completionAt(int i) const { @@ -36,4 +124,12 @@ public slots: else return {}; } + + void setSearchString(QString s) { emit newSearchString(s); } + +signals: + void newSearchString(QString); + +private: + QString searchString; }; diff --git a/src/UsersModel.cpp b/src/UsersModel.cpp index f102cff1..cb9f8f75 100644 --- a/src/UsersModel.cpp +++ b/src/UsersModel.cpp @@ -8,6 +8,10 @@ UsersModel::UsersModel(const std::string &roomId, QObject *parent) , room_id(roomId) { roomMembers_ = cache::roomMembers(roomId); + for (const auto &m : roomMembers_) { + displayNames.push_back(QString::fromStdString(cache::displayName(room_id, m))); + userids.push_back(QString::fromStdString(m)); + } } QHash @@ -31,10 +35,9 @@ UsersModel::data(const QModelIndex &index, int role) const case CompletionModel::SearchRole: case Qt::DisplayRole: case Roles::DisplayName: - return QString::fromStdString( - cache::displayName(room_id, roomMembers_[index.row()])); + return displayNames[index.row()]; case CompletionModel::SearchRole2: - return QString::fromStdString(roomMembers_[index.row()]); + return userids[index.row()]; case Roles::AvatarUrl: return cache::avatarUrl(QString::fromStdString(room_id), QString::fromStdString(roomMembers_[index.row()])); diff --git a/src/UsersModel.h b/src/UsersModel.h index 6ee8261f..cddcdd84 100644 --- a/src/UsersModel.h +++ b/src/UsersModel.h @@ -23,4 +23,6 @@ public: private: std::string room_id; std::vector roomMembers_; + std::vector displayNames; + std::vector userids; }; From 67dcc74c79aebc3d6f117f1cc08a44a778b1192e Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 20 Nov 2020 04:14:19 +0100 Subject: [PATCH 18/35] Simple prefix match for completions --- resources/qml/MessageInput.qml | 2 +- src/CompletionProxyModel.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index d9592e14..1366689c 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -129,7 +129,7 @@ Rectangle { event.accepted = true; } if (popup.opened) - popup.completer.setSearchString(textArea.getText(completerTriggeredAt, cursorPosition)); + popup.completer.setSearchString(textArea.getText(completerTriggeredAt, cursorPosition) + event.text); } diff --git a/src/CompletionProxyModel.h b/src/CompletionProxyModel.h index ee8236e3..2bc22875 100644 --- a/src/CompletionProxyModel.h +++ b/src/CompletionProxyModel.h @@ -90,27 +90,27 @@ public: sourceModel()->data(source_left, CompletionModel::SearchRole).toString(); auto left2 = sourceModel()->data(source_left, CompletionModel::SearchRole2).toString(); - auto left = left1.toLower().indexOf(searchString); + auto left = (size_t)left1.toLower().indexOf(searchString); // utils::levenshtein_distance(searchString, left1.toLower().toStdString()); if (!left2.isEmpty()) { // left = std::min( // utils::levenshtein_distance(searchString, // left2.toLower().toStdString()), left); - left = std::min(left2.toLower().indexOf(searchString), left); + left = std::min((size_t)left2.toLower().indexOf(searchString), left); } auto right1 = sourceModel()->data(source_right, CompletionModel::SearchRole).toString(); auto right2 = sourceModel()->data(source_right, CompletionModel::SearchRole2).toString(); - auto right = right1.toLower().indexOf(searchString); + auto right = (size_t)right1.toLower().indexOf(searchString); // auto right = // utils::levenshtein_distance(searchString, right1.toLower().toStdString()); if (!right2.isEmpty()) { // right = std::min( // utils::levenshtein_distance(searchString, // right2.toLower().toStdString()), right); - right = std::min(right2.toLower().indexOf(searchString), right); + right = std::min((size_t)right2.toLower().indexOf(searchString), right); } return left < right; From 094c0b09abba70e5e4cec5740f918ae56971f3e7 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 20 Nov 2020 04:33:11 +0100 Subject: [PATCH 19/35] Qml emoji completer --- resources/qml/Completer.qml | 60 +++++++++++++++++++++++++++------- resources/qml/MessageInput.qml | 4 +++ src/emoji/EmojiModel.cpp | 4 +++ src/timeline/InputBar.cpp | 6 ++++ 4 files changed, 62 insertions(+), 12 deletions(-) diff --git a/resources/qml/Completer.qml b/resources/qml/Completer.qml index 2c520dec..0557a2e7 100644 --- a/resources/qml/Completer.qml +++ b/resources/qml/Completer.qml @@ -56,24 +56,60 @@ Popup { delegate: Rectangle { color: model.index == popup.currentIndex ? colors.window : colors.base - height: del.implicitHeight + 4 - width: del.implicitWidth + 4 + height: chooser.childrenRect.height + 4 + width: chooser.childrenRect.width + 4 - RowLayout { - id: del + DelegateChooser { + id: chooser + roleValue: popup.completerName anchors.centerIn: parent - Avatar { - height: 24 - width: 24 - displayName: model.displayName - url: model.avatarUrl.replace("mxc://", "image://MxcImage/") + DelegateChoice { + roleValue: "user" + + RowLayout { + id: del + + anchors.centerIn: parent + + Avatar { + height: 24 + width: 24 + displayName: model.displayName + url: model.avatarUrl.replace("mxc://", "image://MxcImage/") + } + + Label { + text: model.displayName + color: colors.text + } + + } + } - Label { - text: model.displayName - color: colors.text + DelegateChoice { + roleValue: "emoji" + + RowLayout { + id: del + + anchors.centerIn: parent + + Label { + text: model.unicode + color: colors.text + font: Settings.emojiFont + } + + Label { + text: model.shortName + color: colors.text + } + + } + } } diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index 1366689c..ac91e46c 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -99,6 +99,10 @@ Rectangle { completerTriggeredAt = cursorPosition; popup.completerName = "user"; popup.open(); + } else if (event.key == Qt.Key_Colon) { + completerTriggeredAt = cursorPosition; + popup.completerName = "emoji"; + popup.open(); } else if (event.key == Qt.Key_Escape && popup.opened) { completerTriggeredAt = -1; popup.completerName = ""; diff --git a/src/emoji/EmojiModel.cpp b/src/emoji/EmojiModel.cpp index b6a985b8..85c2dd34 100644 --- a/src/emoji/EmojiModel.cpp +++ b/src/emoji/EmojiModel.cpp @@ -3,6 +3,8 @@ #include #include +#include "CompletionModelRoles.h" + using namespace emoji; QHash @@ -35,10 +37,12 @@ EmojiModel::data(const QModelIndex &index, int role) const if (hasIndex(index.row(), index.column(), index.parent())) { switch (role) { case Qt::DisplayRole: + case CompletionModel::CompletionRole: case static_cast(EmojiModel::Roles::Unicode): return Provider::emoji[index.row()].unicode; case Qt::ToolTipRole: + case CompletionModel::SearchRole: case static_cast(EmojiModel::Roles::ShortName): return Provider::emoji[index.row()].shortName; diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp index 641d8379..5c8f0f11 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp @@ -25,6 +25,7 @@ #include "Utils.h" #include "dialogs/PlaceCall.h" #include "dialogs/PreviewUploadOverlay.h" +#include "emoji/EmojiModel.h" #include "blurhash.hpp" @@ -173,6 +174,11 @@ InputBar::completerFor(QString completerName) auto proxy = new CompletionProxyModel(userModel); userModel->setParent(proxy); return proxy; + } else if (completerName == "emoji") { + auto emojiModel = new emoji::EmojiModel(); + auto proxy = new CompletionProxyModel(emojiModel); + emojiModel->setParent(proxy); + return proxy; } return nullptr; } From b47d2a809c533d74eddce67683c0cbda8ca71446 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 20 Nov 2020 04:36:13 +0100 Subject: [PATCH 20/35] Remove old Textinput --- CMakeLists.txt | 2 - src/ChatPage.cpp | 7 - src/ChatPage.h | 3 - src/TextInputWidget.cpp | 496 ---------------------------------------- src/TextInputWidget.h | 173 -------------- 5 files changed, 681 deletions(-) delete mode 100644 src/TextInputWidget.cpp delete mode 100644 src/TextInputWidget.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e68db77..52527312 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -299,7 +299,6 @@ set(SRC_FILES src/SSOHandler.cpp src/SideBarActions.cpp src/Splitter.cpp - src/TextInputWidget.cpp src/TrayIcon.cpp src/UserInfoWidget.cpp src/UserSettingsPage.cpp @@ -505,7 +504,6 @@ qt5_wrap_cpp(MOC_HEADERS src/SSOHandler.h src/SideBarActions.h src/Splitter.h - src/TextInputWidget.h src/TrayIcon.h src/UserInfoWidget.h src/UserSettingsPage.h diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index 1b235a95..1fd9b9bc 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -39,7 +39,6 @@ #include "RoomList.h" #include "SideBarActions.h" #include "Splitter.h" -#include "TextInputWidget.h" #include "UserInfoWidget.h" #include "UserSettingsPage.h" #include "Utils.h" @@ -138,18 +137,13 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) splitter->addWidget(content_); splitter->restoreSizes(parent->width()); - text_input_ = new TextInputWidget(this); - contentLayout_->addWidget(text_input_); - connect(this, &ChatPage::connectionLost, this, [this]() { nhlog::net()->info("connectivity lost"); isConnected_ = false; http::client()->shutdown(); - text_input_->disableInput(); }); connect(this, &ChatPage::connectionRestored, this, [this]() { nhlog::net()->info("trying to re-connect"); - text_input_->enableInput(); isConnected_ = true; // Drop all pending connections. @@ -573,7 +567,6 @@ ChatPage::showQuickSwitcher() connect(dialog, &QuickSwitcher::roomSelected, room_list_, &RoomList::highlightSelectedRoom); connect(dialog, &QuickSwitcher::closing, this, [this]() { MainWindow::instance()->hideOverlay(); - text_input_->setFocus(Qt::FocusReason::PopupFocusReason); }); MainWindow::instance()->showTransparentOverlayModal(dialog); diff --git a/src/ChatPage.h b/src/ChatPage.h index 37abafa0..273ba4af 100644 --- a/src/ChatPage.h +++ b/src/ChatPage.h @@ -46,7 +46,6 @@ class QuickSwitcher; class RoomList; class SideBarActions; class Splitter; -class TextInputWidget; class TimelineViewManager; class UserInfoWidget; class UserSettings; @@ -251,8 +250,6 @@ private: TimelineViewManager *view_manager_; SideBarActions *sidebarActions_; - TextInputWidget *text_input_; - QTimer connectivityTimer_; std::atomic_bool isConnected_; diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp deleted file mode 100644 index 6d1fdc7a..00000000 --- a/src/TextInputWidget.cpp +++ /dev/null @@ -1,496 +0,0 @@ -/* - * nheko Copyright (C) 2017 Konstantinos Sideris - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Cache.h" -#include "ChatPage.h" -#include "CompletionModelRoles.h" -#include "CompletionProxyModel.h" -#include "Logging.h" -#include "TextInputWidget.h" -#include "Utils.h" -#include "emoji/EmojiSearchModel.h" -#include "emoji/Provider.h" -#include "ui/FlatButton.h" -#include "ui/LoadingIndicator.h" - -#if defined(Q_OS_MAC) -#include "emoji/MacHelper.h" -#endif - -static constexpr size_t INPUT_HISTORY_SIZE = 127; -static constexpr int MAX_TEXTINPUT_HEIGHT = 120; -static constexpr int ButtonHeight = 22; - -FilteredTextEdit::FilteredTextEdit(QWidget *parent) - : QTextEdit{parent} - , history_index_{0} - , suggestionsPopup_{parent} - , previewDialog_{parent} -{ - setFrameStyle(QFrame::NoFrame); - connect(document()->documentLayout(), - &QAbstractTextDocumentLayout::documentSizeChanged, - this, - &FilteredTextEdit::updateGeometry); - connect(document()->documentLayout(), - &QAbstractTextDocumentLayout::documentSizeChanged, - this, - [this]() { emit heightChanged(document()->size().toSize().height()); }); - working_history_.push_back(""); - connect(this, &QTextEdit::textChanged, this, &FilteredTextEdit::textChanged); - setAcceptRichText(false); - - completer_ = new QCompleter(this); - completer_->setWidget(this); - auto model = new emoji::EmojiSearchModel(this); - model->sort(0, Qt::AscendingOrder); - completer_->setModel((emoji_completion_model_ = new CompletionProxyModel(model, this))); - emoji_completion_model_->setFilterRole(CompletionModel::SearchRole); - completer_->setModelSorting(QCompleter::UnsortedModel); - completer_->popup()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - completer_->popup()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - connect(completer_, - QOverload::of(&QCompleter::activated), - [this](auto &index) { - emoji_popup_open_ = false; - auto text = index.data(CompletionModel::CompletionRole).toString(); - insertCompletion(text); - }); - - connect(this, &FilteredTextEdit::resultsRetrieved, this, &FilteredTextEdit::showResults); - connect( - &suggestionsPopup_, &SuggestionsPopup::itemSelected, this, [this](const QString &text) { - suggestionsPopup_.hide(); - - auto cursor = textCursor(); - const int end = cursor.position(); - - cursor.setPosition(atTriggerPosition_, QTextCursor::MoveAnchor); - cursor.setPosition(end, QTextCursor::KeepAnchor); - cursor.removeSelectedText(); - cursor.insertText(text); - }); - - // For cycling through the suggestions by hitting tab. - connect(this, - &FilteredTextEdit::selectNextSuggestion, - &suggestionsPopup_, - &SuggestionsPopup::selectNextSuggestion); - connect(this, - &FilteredTextEdit::selectPreviousSuggestion, - &suggestionsPopup_, - &SuggestionsPopup::selectPreviousSuggestion); - connect(this, &FilteredTextEdit::selectHoveredSuggestion, this, [this]() { - suggestionsPopup_.selectHoveredSuggestion(); - }); - - previewDialog_.hide(); -} - -void -FilteredTextEdit::insertCompletion(QString completion) -{ - // Paint the current word and replace it with 'completion' - auto cur_text = textAfterPosition(trigger_pos_); - auto tc = textCursor(); - tc.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor, cur_text.length()); - tc.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, cur_text.length()); - tc.insertText(completion); - setTextCursor(tc); -} - -void -FilteredTextEdit::showResults(const std::vector &results) -{ - QPoint pos; - - if (isAnchorValid()) { - auto cursor = textCursor(); - cursor.setPosition(atTriggerPosition_); - pos = viewport()->mapToGlobal(cursorRect(cursor).topLeft()); - } else { - auto rect = cursorRect(); - pos = viewport()->mapToGlobal(rect.topLeft()); - } - - suggestionsPopup_.addUsers(results); - suggestionsPopup_.move(pos.x(), pos.y() - suggestionsPopup_.height() - 10); - suggestionsPopup_.show(); -} - -void -FilteredTextEdit::keyPressEvent(QKeyEvent *event) -{ - const bool isModifier = (event->modifiers() != Qt::NoModifier); - -#if defined(Q_OS_MAC) - if (event->modifiers() == (Qt::ControlModifier | Qt::MetaModifier) && - event->key() == Qt::Key_Space) - MacHelper::showEmojiWindow(); -#endif - - if (event->modifiers() == Qt::ControlModifier && event->key() == Qt::Key_U) - QTextEdit::setText(""); - - // calculate the new query - if (textCursor().position() < atTriggerPosition_ || !isAnchorValid()) { - resetAnchor(); - closeSuggestions(); - } - - if (suggestionsPopup_.isVisible()) { - switch (event->key()) { - case Qt::Key_Down: - case Qt::Key_Tab: - emit selectNextSuggestion(); - return; - case Qt::Key_Enter: - case Qt::Key_Return: - emit selectHoveredSuggestion(); - return; - case Qt::Key_Escape: - closeSuggestions(); - return; - case Qt::Key_Up: - case Qt::Key_Backtab: { - emit selectPreviousSuggestion(); - return; - } - default: - break; - } - } - - if (emoji_popup_open_) { - auto fake_key = (event->key() == Qt::Key_Backtab) ? Qt::Key_Up : Qt::Key_Down; - switch (event->key()) { - case Qt::Key_Backtab: - case Qt::Key_Tab: { - // Simulate up/down arrow press - auto ev = new QKeyEvent(QEvent::KeyPress, fake_key, Qt::NoModifier); - QCoreApplication::postEvent(completer_->popup(), ev); - return; - } - default: - break; - } - } - - switch (event->key()) { - case Qt::Key_At: - atTriggerPosition_ = textCursor().position(); - anchorType_ = AnchorType::Sigil; - - QTextEdit::keyPressEvent(event); - break; - case Qt::Key_Tab: { - auto cursor = textCursor(); - const int initialPos = cursor.position(); - - cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor); - auto word = cursor.selectedText(); - - const int startOfWord = cursor.position(); - - // There is a word to complete. - if (initialPos != startOfWord) { - atTriggerPosition_ = startOfWord; - anchorType_ = AnchorType::Tab; - - emit showSuggestions(word); - } else { - QTextEdit::keyPressEvent(event); - } - - break; - } - case Qt::Key_Colon: { - QTextEdit::keyPressEvent(event); - trigger_pos_ = textCursor().position() - 1; - emoji_completion_model_->setFilterRegExp(""); - emoji_popup_open_ = true; - break; - } - case Qt::Key_Return: - case Qt::Key_Enter: - if (emoji_popup_open_) { - if (!completer_->popup()->currentIndex().isValid()) { - // No completion to select, do normal behavior - completer_->popup()->hide(); - emoji_popup_open_ = false; - } else { - event->ignore(); - return; - } - } - - if (!(event->modifiers() & Qt::ShiftModifier)) { - submit(); - } else { - QTextEdit::keyPressEvent(event); - } - break; - case Qt::Key_Up: { - auto initial_cursor = textCursor(); - QTextEdit::keyPressEvent(event); - - if (textCursor() == initial_cursor && textCursor().atStart() && - history_index_ + 1 < working_history_.size()) { - ++history_index_; - setPlainText(working_history_[history_index_]); - moveCursor(QTextCursor::End); - } else if (textCursor() == initial_cursor) { - // Move to the start of the text if there aren't any lines to move up to. - initial_cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor, 1); - setTextCursor(initial_cursor); - } - - break; - } - case Qt::Key_Down: { - auto initial_cursor = textCursor(); - QTextEdit::keyPressEvent(event); - - if (textCursor() == initial_cursor && textCursor().atEnd() && history_index_ > 0) { - --history_index_; - setPlainText(working_history_[history_index_]); - moveCursor(QTextCursor::End); - } else if (textCursor() == initial_cursor) { - // Move to the end of the text if there aren't any lines to move down to. - initial_cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor, 1); - setTextCursor(initial_cursor); - } - - break; - } - default: - QTextEdit::keyPressEvent(event); - - if (isModifier) - return; - - if (emoji_popup_open_ && textAfterPosition(trigger_pos_).length() > 2) { - // Update completion - // Don't include the trigger token in the search - emoji_completion_model_->setFilterWildcard( - textAfterPosition(trigger_pos_).remove(0, 1)); - completer_->complete(completerRect()); - } - - if (emoji_popup_open_ && (completer_->completionCount() < 1 || - !textAfterPosition(trigger_pos_) - .contains(QRegularExpression(":[^\r\n\t\f\v :]+$")))) { - // No completions for this word or another word than the completer was - // started with - emoji_popup_open_ = false; - completer_->popup()->hide(); - } - - if (textCursor().position() == 0) { - resetAnchor(); - closeSuggestions(); - return; - } - - // Check if the current word should be autocompleted. - auto cursor = textCursor(); - cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor); - auto word = cursor.selectedText(); - - if (hasAnchor(cursor.position(), anchorType_) && isAnchorValid()) { - if (word.isEmpty()) { - closeSuggestions(); - return; - } - - emit showSuggestions(word); - } else { - resetAnchor(); - closeSuggestions(); - } - - break; - } -} - -QRect -FilteredTextEdit::completerRect() -{ - // Move left edge to the beginning of the word - auto cursor = textCursor(); - auto rect = cursorRect(); - cursor.movePosition( - QTextCursor::Left, QTextCursor::MoveAnchor, textAfterPosition(trigger_pos_).length()); - auto cursor_global_x = viewport()->mapToGlobal(cursorRect(cursor).topLeft()).x(); - auto rect_global_left = viewport()->mapToGlobal(rect.bottomLeft()).x(); - auto dx = qAbs(rect_global_left - cursor_global_x); - rect.moveLeft(rect.left() - dx); - - auto item_height = completer_->popup()->sizeHintForRow(0); - auto max_height = item_height * completer_->maxVisibleItems(); - auto height = (completer_->completionCount() > completer_->maxVisibleItems()) - ? max_height - : completer_->completionCount() * item_height; - rect.setWidth(completer_->popup()->sizeHintForColumn(0)); - rect.moveBottom(-height); - return rect; -} - -QSize -FilteredTextEdit::sizeHint() const -{ - ensurePolished(); - auto margins = viewportMargins(); - margins += document()->documentMargin(); - QSize size = document()->size().toSize(); - size.rwidth() += margins.left() + margins.right(); - size.rheight() += margins.top() + margins.bottom(); - return size; -} - -QSize -FilteredTextEdit::minimumSizeHint() const -{ - ensurePolished(); - auto margins = viewportMargins(); - margins += document()->documentMargin(); - margins += contentsMargins(); - QSize size(fontMetrics().averageCharWidth() * 10, - fontMetrics().lineSpacing() + margins.top() + margins.bottom()); - return size; -} - -void -FilteredTextEdit::submit() -{} - -void -FilteredTextEdit::textChanged() -{ - working_history_[history_index_] = toPlainText(); -} - -TextInputWidget::TextInputWidget(QWidget *parent) - : QWidget(parent) -{ - QFont f; - f.setPointSizeF(f.pointSizeF()); - const int fontHeight = QFontMetrics(f).height(); - const int contentHeight = static_cast(fontHeight * 2.5); - const int InputHeight = static_cast(fontHeight * 1.5); - - setFixedHeight(contentHeight); - setCursor(Qt::ArrowCursor); - - topLayout_ = new QHBoxLayout(); - topLayout_->setSpacing(0); - topLayout_->setContentsMargins(13, 1, 13, 0); - - QIcon send_file_icon; - send_file_icon.addFile(":/icons/icons/ui/paper-clip-outline.png"); - - sendFileBtn_ = new FlatButton(this); - sendFileBtn_->setToolTip(tr("Send a file")); - sendFileBtn_->setIcon(send_file_icon); - sendFileBtn_->setIconSize(QSize(ButtonHeight, ButtonHeight)); - - spinner_ = new LoadingIndicator(this); - spinner_->setFixedHeight(InputHeight); - spinner_->setFixedWidth(InputHeight); - spinner_->setObjectName("FileUploadSpinner"); - spinner_->hide(); - - input_ = new FilteredTextEdit(this); - input_->setFixedHeight(InputHeight); - input_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - input_->setPlaceholderText(tr("Write a message...")); - - connect(input_, - &FilteredTextEdit::heightChanged, - this, - [this, InputHeight, contentHeight](int height) { - int widgetHeight = - std::min(MAX_TEXTINPUT_HEIGHT, std::max(height, contentHeight)); - int textInputHeight = - std::min(widgetHeight - 1, std::max(height, InputHeight)); - - setFixedHeight(widgetHeight); - input_->setFixedHeight(textInputHeight); - - emit heightChanged(widgetHeight); - }); - connect(input_, &FilteredTextEdit::showSuggestions, this, [this](const QString &q) { - if (q.isEmpty()) - return; - - QtConcurrent::run([this, q = q.toLower().toStdString()]() { - try { - emit input_->resultsRetrieved(cache::searchUsers( - ChatPage::instance()->currentRoom().toStdString(), q)); - } catch (const lmdb::error &e) { - nhlog::db()->error("Suggestion retrieval failed: {}", e.what()); - } - }); - }); - - sendMessageBtn_ = new FlatButton(this); - sendMessageBtn_->setToolTip(tr("Send a message")); - - QIcon send_message_icon; - send_message_icon.addFile(":/icons/icons/ui/cursor.png"); - sendMessageBtn_->setIcon(send_message_icon); - sendMessageBtn_->setIconSize(QSize(ButtonHeight, ButtonHeight)); - - topLayout_->addWidget(sendFileBtn_); - topLayout_->addWidget(input_); - topLayout_->addWidget(sendMessageBtn_); - - setLayout(topLayout_); - - connect(sendMessageBtn_, &FlatButton::clicked, input_, &FilteredTextEdit::submit); - connect(sendFileBtn_, SIGNAL(clicked()), this, SLOT(openFileSelection())); -} - -void -TextInputWidget::focusInEvent(QFocusEvent *event) -{ - input_->setFocus(event->reason()); -} - -void -TextInputWidget::paintEvent(QPaintEvent *) -{ - QStyleOption opt; - opt.init(this); - QPainter p(this); - - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); -} diff --git a/src/TextInputWidget.h b/src/TextInputWidget.h deleted file mode 100644 index 19462f70..00000000 --- a/src/TextInputWidget.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * nheko Copyright (C) 2017 Konstantinos Sideris - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include -#include - -#include -#include -#include -#include -#include - -#include "dialogs/PreviewUploadOverlay.h" -#include "popups/SuggestionsPopup.h" - -struct SearchResult; - -class CompletionProxyModel; -class FlatButton; -class LoadingIndicator; -class QCompleter; - -class FilteredTextEdit : public QTextEdit -{ - Q_OBJECT - -public: - explicit FilteredTextEdit(QWidget *parent = nullptr); - - QSize sizeHint() const override; - QSize minimumSizeHint() const override; - - void submit(); - -signals: - void heightChanged(int height); - void startedUpload(); - - //! Trigger the suggestion popup. - void showSuggestions(const QString &query); - void resultsRetrieved(const std::vector &results); - void selectNextSuggestion(); - void selectPreviousSuggestion(); - void selectHoveredSuggestion(); - -public slots: - void showResults(const std::vector &results); - -protected: - void keyPressEvent(QKeyEvent *event) override; - void focusOutEvent(QFocusEvent *event) override - { - suggestionsPopup_.hide(); - QTextEdit::focusOutEvent(event); - } - -private: - bool emoji_popup_open_ = false; - CompletionProxyModel *emoji_completion_model_; - std::deque true_history_, working_history_; - int trigger_pos_; // Where emoji completer was triggered - size_t history_index_; - QCompleter *completer_; - - SuggestionsPopup suggestionsPopup_; - - enum class AnchorType - { - Tab = 0, - Sigil = 1, - }; - - AnchorType anchorType_ = AnchorType::Sigil; - - int anchorWidth(AnchorType anchor) { return static_cast(anchor); } - - void closeSuggestions() { suggestionsPopup_.hide(); } - void resetAnchor() { atTriggerPosition_ = -1; } - bool isAnchorValid() { return atTriggerPosition_ != -1; } - bool hasAnchor(int pos, AnchorType anchor) - { - return pos == atTriggerPosition_ + anchorWidth(anchor); - } - QRect completerRect(); - QString query() - { - auto cursor = textCursor(); - cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor); - return cursor.selectedText(); - } - QString textAfterPosition(int pos) - { - auto tc = textCursor(); - tc.setPosition(pos); - tc.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); - return tc.selectedText(); - } - - dialogs::PreviewUploadOverlay previewDialog_; - - //! Latest position of the '@' character that triggers the username completer. - int atTriggerPosition_ = -1; - - void insertCompletion(QString completion); - void textChanged(); - void afterCompletion(int); -}; - -class TextInputWidget : public QWidget -{ - Q_OBJECT - - Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor) - -public: - TextInputWidget(QWidget *parent = nullptr); - - QColor borderColor() const { return borderColor_; } - void setBorderColor(QColor &color) { borderColor_ = color; } - void disableInput() - { - input_->setEnabled(false); - input_->setPlaceholderText(tr("Connection lost. Nheko is trying to re-connect...")); - } - void enableInput() - { - input_->setEnabled(true); - input_->setPlaceholderText(tr("Write a message...")); - } - -public slots: - void focusLineEdit() { input_->setFocus(); } - -signals: - void heightChanged(int height); - - void sendJoinRoomRequest(const QString &room); - void sendInviteRoomRequest(const QString &userid, const QString &reason); - void sendKickRoomRequest(const QString &userid, const QString &reason); - void sendBanRoomRequest(const QString &userid, const QString &reason); - void sendUnbanRoomRequest(const QString &userid, const QString &reason); - void changeRoomNick(const QString &displayname); - -protected: - void focusInEvent(QFocusEvent *event) override; - void paintEvent(QPaintEvent *) override; - -private: - QHBoxLayout *topLayout_; - FilteredTextEdit *input_; - - LoadingIndicator *spinner_; - - FlatButton *sendFileBtn_; - FlatButton *sendMessageBtn_; - QColor borderColor_; -}; From c8fa40a2dffad4814bf96248bad0e60c1b2209e9 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 23 Nov 2020 05:08:17 +0100 Subject: [PATCH 21/35] Use a trie for filtering completions (not fuzzy yet) --- resources/qml/Completer.qml | 4 +- src/CompletionProxyModel.h | 203 +++++++++++++++++++++++------------- 2 files changed, 132 insertions(+), 75 deletions(-) diff --git a/resources/qml/Completer.qml b/resources/qml/Completer.qml index 0557a2e7..dda5b896 100644 --- a/resources/qml/Completer.qml +++ b/resources/qml/Completer.qml @@ -55,7 +55,7 @@ Popup { model: completer delegate: Rectangle { - color: model.index == popup.currentIndex ? colors.window : colors.base + color: model.index == popup.currentIndex ? colors.window : colors.alternateBase height: chooser.childrenRect.height + 4 width: chooser.childrenRect.width + 4 @@ -141,7 +141,7 @@ Popup { } background: Rectangle { - color: colors.base + color: colors.alternateBase implicitHeight: popup.contentHeight implicitWidth: popup.contentWidth } diff --git a/src/CompletionProxyModel.h b/src/CompletionProxyModel.h index 2bc22875..fa22c61e 100644 --- a/src/CompletionProxyModel.h +++ b/src/CompletionProxyModel.h @@ -2,22 +2,106 @@ // Class for showing a limited amount of completions at a time -#include +#include #include "CompletionModelRoles.h" +#include "Logging.h" #include "Utils.h" -class CompletionProxyModel : public QSortFilterProxyModel +template +struct trie +{ + std::vector values; + std::map next; + + void insert(const QVector &keys, const Value &v) + { + auto t = this; + for (const auto k : keys) { + t = &t->next[k]; + } + + t->values.push_back(v); + } + + std::vector valuesAndSubvalues(size_t limit = -1) const + { + std::vector ret; + if (limit < 200) + ret.reserve(limit); + + for (const auto &v : values) { + if (ret.size() >= limit) + return ret; + else + ret.push_back(v); + } + + for (const auto &[k, t] : next) { + (void)k; + if (ret.size() >= limit) + return ret; + else { + auto temp = t.valuesAndSubvalues(limit - ret.size()); + ret.insert(ret.end(), temp.begin(), temp.end()); + } + } + + return ret; + } + + std::vector search(const QVector &keys, size_t limit) const + { + std::vector ret; + auto t = this; + int i = 0; + for (; i < (int)keys.size(); i++) { + if (auto e = t->next.find(keys[i]); e != t->next.end()) { + t = &e->second; + } else { + t = nullptr; + break; + } + } + + if (t) { + ret = t->valuesAndSubvalues(limit); + } + + return ret; + } +}; + +class CompletionProxyModel : public QAbstractProxyModel { Q_OBJECT public: CompletionProxyModel(QAbstractItemModel *model, QObject *parent = nullptr) - : QSortFilterProxyModel(parent) + : QAbstractProxyModel(parent) { setSourceModel(model); - sort(0, Qt::AscendingOrder); - setFilterRole(CompletionModel::SearchRole); + + for (int i = 0; i < sourceModel()->rowCount(); i++) { + if (i < 7) + mapping.push_back(i); + + auto string1 = + sourceModel() + ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole) + .toString() + .toLower(); + trie_.insert(string1.toUcs4(), i); + + auto string2 = + sourceModel() + ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole2) + .toString() + .toLower(); + + if (!string2.isEmpty()) + trie_.insert(string2.toUcs4(), i); + } connect( this, @@ -32,6 +116,20 @@ public: Qt::QueuedConnection); } + void invalidate() + { + auto key = searchString.toUcs4(); + beginResetModel(); + mapping = trie_.search(key, 7); + endResetModel(); + + std::string temp; + for (auto v : mapping) { + temp += std::to_string(v) + ", "; + } + nhlog::ui()->debug("mapping: {}", temp); + }; + QHash roleNames() const override { return this->sourceModel()->roleNames(); @@ -39,83 +137,40 @@ public: int rowCount(const QModelIndex &parent = QModelIndex()) const override { - auto row_count = QSortFilterProxyModel::rowCount(parent); - return (row_count < 7) ? row_count : 7; + (void)parent; + return (int)mapping.size(); } - bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const + QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override { - if (searchString.size() < 1) - return true; - - auto source_index = sourceModel()->index(source_row, 0, source_parent); - auto role1 = sourceModel() - ->data(source_index, CompletionModel::SearchRole) - .toString() - .toLower(); - - if (role1.contains(searchString)) - return true; - // auto score = - // utils::levenshtein_distance(searchString, role1.toLower().toStdString()); - // if ((size_t)role1.size() >= searchString.size() && - // ((size_t)score) < (size_t)role1.size() - searchString.size() + 2) - // return true; - - auto role2 = sourceModel() - ->data(source_index, CompletionModel::SearchRole2) - .toString() - .toLower(); - if (role2.contains(searchString)) - return true; - // if (!role2.isEmpty()) { - // score = - // utils::levenshtein_distance(searchString, - // role2.toLower().toStdString()); - // if ((size_t)role2.size() >= searchString.size() && - // ((size_t)score) < (size_t)role2.size() - searchString.size() + 2) - // return true; - //} - - return false; + for (int i = 0; i < (int)mapping.size(); i++) { + if (mapping[i] == sourceIndex.row()) { + return index(i, 0); + } + } + return QModelIndex(); } - bool lessThan(const QModelIndex &source_left, - const QModelIndex &source_right) const override + QModelIndex mapToSource(const QModelIndex &proxyIndex) const override { - if (searchString.size() < 1) - return false; + auto row = proxyIndex.row(); + if (row < 0 || row >= (int)mapping.size()) + return QModelIndex(); - auto left1 = - sourceModel()->data(source_left, CompletionModel::SearchRole).toString(); - auto left2 = - sourceModel()->data(source_left, CompletionModel::SearchRole2).toString(); - auto left = (size_t)left1.toLower().indexOf(searchString); - // utils::levenshtein_distance(searchString, left1.toLower().toStdString()); - if (!left2.isEmpty()) { - // left = std::min( - // utils::levenshtein_distance(searchString, - // left2.toLower().toStdString()), left); - left = std::min((size_t)left2.toLower().indexOf(searchString), left); - } - - auto right1 = - sourceModel()->data(source_right, CompletionModel::SearchRole).toString(); - auto right2 = - sourceModel()->data(source_right, CompletionModel::SearchRole2).toString(); - auto right = (size_t)right1.toLower().indexOf(searchString); - // auto right = - // utils::levenshtein_distance(searchString, right1.toLower().toStdString()); - if (!right2.isEmpty()) { - // right = std::min( - // utils::levenshtein_distance(searchString, - // right2.toLower().toStdString()), right); - right = std::min((size_t)right2.toLower().indexOf(searchString), right); - } - - return left < right; + return sourceModel()->index(mapping[row], 0); } + QModelIndex index(int row, + int column, + const QModelIndex &parent = QModelIndex()) const override + { + (void)parent; + return createIndex(row, column); + } + + QModelIndex parent(const QModelIndex &) const override { return QModelIndex{}; } + int columnCount(const QModelIndex &) const override { return sourceModel()->columnCount(); } + public slots: QVariant completionAt(int i) const { @@ -132,4 +187,6 @@ signals: private: QString searchString; + trie trie_; + std::vector mapping; }; From c2eea5cb5508ce0ec090b84dc9a2c9fd25b4dd88 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 23 Nov 2020 18:19:24 +0100 Subject: [PATCH 22/35] Fix mimetype of media messages --- src/dialogs/PreviewUploadOverlay.cpp | 8 ++++---- src/timeline/InputBar.cpp | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/dialogs/PreviewUploadOverlay.cpp b/src/dialogs/PreviewUploadOverlay.cpp index e03993c7..bd207642 100644 --- a/src/dialogs/PreviewUploadOverlay.cpp +++ b/src/dialogs/PreviewUploadOverlay.cpp @@ -118,7 +118,7 @@ PreviewUploadOverlay::init() void PreviewUploadOverlay::setLabels(const QString &type, const QString &mime, uint64_t upload_size) { - if (mediaType_ == "image") { + if (mediaType_.split('/')[0] == "image") { if (!image_.loadFromData(data_)) { titleLabel_.setText(QString{tr(ERR_MSG)}.arg(type)); } else { @@ -154,7 +154,7 @@ PreviewUploadOverlay::setPreview(const QImage &src, const QString &mime) else titleLabel_.setText(QString{tr(ERR_MSG)}.arg(type)); - mediaType_ = split[0]; + mediaType_ = mime; filePath_ = "clipboard." + type; image_.convertFromImage(src); isImage_ = true; @@ -170,7 +170,7 @@ PreviewUploadOverlay::setPreview(const QByteArray data, const QString &mime) auto const &type = split[1]; data_ = data; - mediaType_ = split[0]; + mediaType_ = mime; filePath_ = "clipboard." + type; isImage_ = false; @@ -202,7 +202,7 @@ PreviewUploadOverlay::setPreview(const QString &path) auto const &split = mime.name().split('/'); - mediaType_ = split[0]; + mediaType_ = mime.name(); filePath_ = file.fileName(); isImage_ = false; diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp index 5c8f0f11..b0d555b7 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp @@ -511,6 +511,7 @@ InputBar::showPreview(const QMimeData &source, QString path, const QStringList & QSize dimensions; QString blurhash; auto mimeClass = mime.split("/")[0]; + nhlog::ui()->debug("Mime: {}", mime.toStdString()); if (mimeClass == "image") { QImage img = utils::readImage(&data); From 29625ae25307aa6746df90cdecc208adc2c36ccb Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Tue, 24 Nov 2020 02:35:38 +0100 Subject: [PATCH 23/35] Fix some issues with completer --- resources/qml/ActiveCallBar.qml | 1 - resources/qml/Completer.qml | 123 ++++++++++++++++++-------------- resources/qml/MessageView.qml | 1 - resources/qml/TimelineView.qml | 2 - src/CompletionProxyModel.h | 89 +++++++++++++++++++---- 5 files changed, 146 insertions(+), 70 deletions(-) diff --git a/resources/qml/ActiveCallBar.qml b/resources/qml/ActiveCallBar.qml index cbe36e6d..49c0e255 100644 --- a/resources/qml/ActiveCallBar.qml +++ b/resources/qml/ActiveCallBar.qml @@ -53,7 +53,6 @@ Rectangle { Connections { target: TimelineManager - onCallStateChanged: { switch (state) { case WebRTCState.INITIATING: diff --git a/resources/qml/Completer.qml b/resources/qml/Completer.qml index dda5b896..7074de81 100644 --- a/resources/qml/Completer.qml +++ b/resources/qml/Completer.qml @@ -9,105 +9,120 @@ Popup { property int currentIndex: -1 property string completerName property var completer + property bool bottomToTop: true function up() { - currentIndex = currentIndex - 1; - if (currentIndex == -2) - currentIndex = repeater.count - 1; - + if (bottomToTop) + down_(); + else + up_(); } function down() { + if (bottomToTop) + up_(); + else + down_(); + } + + function up_() { + currentIndex = currentIndex - 1; + if (currentIndex == -2) + currentIndex = listView.count - 1; + + } + + function down_() { currentIndex = currentIndex + 1; - if (currentIndex >= repeater.count) + if (currentIndex >= listView.count) currentIndex = -1; } function currentCompletion() { - if (currentIndex > -1 && currentIndex < repeater.count) + if (currentIndex > -1 && currentIndex < listView.count) return completer.completionAt(currentIndex); else return null; } onCompleterNameChanged: { - if (completerName) + if (completerName) { completer = TimelineManager.timeline.input.completerFor(completerName); - else + completer.setSearchString(""); + } else { completer = undefined; + } } padding: 0 onAboutToShow: currentIndex = -1 + height: listView.contentHeight Connections { onTimelineChanged: completer = null target: TimelineManager } - ColumnLayout { + ListView { + id: listView + anchors.fill: parent - spacing: 0 + implicitWidth: contentItem.childrenRect.width + model: completer + verticalLayoutDirection: popup.bottomToTop ? ListView.BottomToTop : ListView.TopToBottom - Repeater { - id: repeater + delegate: Rectangle { + color: model.index == popup.currentIndex ? colors.highlight : colors.base + height: chooser.childrenRect.height + 4 + implicitWidth: chooser.childrenRect.width + 4 - model: completer + DelegateChooser { + id: chooser - delegate: Rectangle { - color: model.index == popup.currentIndex ? colors.window : colors.alternateBase - height: chooser.childrenRect.height + 4 - width: chooser.childrenRect.width + 4 + roleValue: popup.completerName + anchors.centerIn: parent - DelegateChooser { - id: chooser + DelegateChoice { + roleValue: "user" - roleValue: popup.completerName - anchors.centerIn: parent + RowLayout { + id: del - DelegateChoice { - roleValue: "user" + anchors.centerIn: parent - RowLayout { - id: del - - anchors.centerIn: parent - - Avatar { - height: 24 - width: 24 - displayName: model.displayName - url: model.avatarUrl.replace("mxc://", "image://MxcImage/") - } - - Label { - text: model.displayName - color: colors.text - } + Avatar { + height: 24 + width: 24 + displayName: model.displayName + url: model.avatarUrl.replace("mxc://", "image://MxcImage/") + } + Label { + text: model.displayName + color: model.index == popup.currentIndex ? colors.highlightedText : colors.text } } - DelegateChoice { - roleValue: "emoji" + } - RowLayout { - id: del + DelegateChoice { + roleValue: "emoji" - anchors.centerIn: parent + RowLayout { + id: del - Label { - text: model.unicode - color: colors.text - font: Settings.emojiFont - } + anchors.centerIn: parent - Label { - text: model.shortName - color: colors.text - } + Label { + text: model.unicode + color: model.index == popup.currentIndex ? colors.highlightedText : colors.text + font: Settings.emojiFont + } + Label { + text: model.shortName + color: model.index == popup.currentIndex ? colors.highlightedText : colors.text } } @@ -141,7 +156,7 @@ Popup { } background: Rectangle { - color: colors.alternateBase + color: colors.base implicitHeight: popup.contentHeight implicitWidth: popup.contentWidth } diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml index 71c85276..679c1f50 100644 --- a/resources/qml/MessageView.qml +++ b/resources/qml/MessageView.qml @@ -182,7 +182,6 @@ ListView { Connections { target: chat - onMovementEnded: { if (y + height + 2 * chat.spacing > chat.contentY + chat.height && y < chat.contentY + chat.height) chat.model.currentIndex = index; diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index c23564c1..ac998a81 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -131,7 +131,6 @@ Page { Connections { target: TimelineManager - onNewDeviceVerificationRequest: { var dialog = deviceVerificationDialog.createObject(timelineRoot, { "flow": flow @@ -142,7 +141,6 @@ Page { Connections { target: TimelineManager.timeline - onOpenProfile: { var userProfile = userProfileComponent.createObject(timelineRoot, { "profile": profile diff --git a/src/CompletionProxyModel.h b/src/CompletionProxyModel.h index fa22c61e..ba28e84c 100644 --- a/src/CompletionProxyModel.h +++ b/src/CompletionProxyModel.h @@ -43,29 +43,94 @@ struct trie return ret; else { auto temp = t.valuesAndSubvalues(limit - ret.size()); - ret.insert(ret.end(), temp.begin(), temp.end()); + for (auto &&v : temp) { + if (ret.size() >= limit) + return ret; + + if (std::find(ret.begin(), ret.end(), v) == ret.end()) { + ret.push_back(std::move(v)); + } + } } } return ret; } - std::vector search(const QVector &keys, size_t limit) const + std::vector search(const QVector &keys, + size_t limit, + size_t max_distance = 2) const { std::vector ret; - auto t = this; - int i = 0; - for (; i < (int)keys.size(); i++) { - if (auto e = t->next.find(keys[i]); e != t->next.end()) { - t = &e->second; - } else { - t = nullptr; - break; + if (!limit) + return ret; + + auto append = [&ret, limit](std::vector &&in) { + for (auto &&v : in) { + if (ret.size() >= limit) + return; + + if (std::find(ret.begin(), ret.end(), v) == ret.end()) { + ret.push_back(std::move(v)); + } + } + }; + + { + auto t = this; + int i = 0; + for (; i < (int)keys.size(); i++) { + if (auto e = t->next.find(keys[i]); e != t->next.end()) { + t = &e->second; + } else { + t = nullptr; + break; + } + } + + if (t) { + ret = t->valuesAndSubvalues(limit); } } - if (t) { - ret = t->valuesAndSubvalues(limit); + if (max_distance && keys.size() < static_cast(limit) && keys.size() > 1) { + max_distance -= 1; + + // swap chars case + if (keys.size() >= 2) { + auto t = this; + for (int i = 1; i >= 0; i--) { + if (auto e = t->next.find(keys[i]); e != t->next.end()) { + t = &e->second; + } else { + t = nullptr; + break; + } + } + + if (t) { + append(t->search( + keys.mid(2), (limit - ret.size()) * 2, max_distance)); + } + } + + // delete character case + append(this->search(keys.mid(1), (limit - ret.size()) * 2, max_distance)); + + // substitute and insert cases + for (const auto &[k, t] : this->next) { + if (k == keys[0] || ret.size() >= limit) + break; + + // substitute + append(this->search(keys.mid(1), limit - ret.size(), max_distance)); + + if (ret.size() >= limit) + break; + + // insert + append(this->search(keys, limit - ret.size(), max_distance)); + } } return ret; From 8922a4777683e08dc0cccfaaff37bb693bd642a6 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Tue, 24 Nov 2020 02:56:14 +0100 Subject: [PATCH 24/35] Fix completer fuzzy match not applying after prefix match and insert being broken --- src/CompletionProxyModel.h | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/CompletionProxyModel.h b/src/CompletionProxyModel.h index ba28e84c..91f937a4 100644 --- a/src/CompletionProxyModel.h +++ b/src/CompletionProxyModel.h @@ -57,7 +57,7 @@ struct trie return ret; } - std::vector search(const QVector &keys, + std::vector search(const QVector &keys, //< TODO(Nico): replace this with a span size_t limit, size_t max_distance = 2) const { @@ -65,6 +65,9 @@ struct trie if (!limit) return ret; + if (keys.isEmpty()) + return valuesAndSubvalues(limit); + auto append = [&ret, limit](std::vector &&in) { for (auto &&v : in) { if (ret.size() >= limit) @@ -76,24 +79,11 @@ struct trie } }; - { - auto t = this; - int i = 0; - for (; i < (int)keys.size(); i++) { - if (auto e = t->next.find(keys[i]); e != t->next.end()) { - t = &e->second; - } else { - t = nullptr; - break; - } - } - - if (t) { - ret = t->valuesAndSubvalues(limit); - } + if (auto e = this->next.find(keys[0]); e != this->next.end()) { + append(e->second.search(keys.mid(1), limit, max_distance)); } - if (max_distance && keys.size() < static_cast(limit) && keys.size() > 1) { + if (max_distance && ret.size() < limit) { max_distance -= 1; // swap chars case @@ -123,13 +113,13 @@ struct trie break; // substitute - append(this->search(keys.mid(1), limit - ret.size(), max_distance)); + append(t.search(keys.mid(1), limit - ret.size(), max_distance)); if (ret.size() >= limit) break; // insert - append(this->search(keys, limit - ret.size(), max_distance)); + append(t.search(keys, limit - ret.size(), max_distance)); } } From 90ce4f23abe752134346f7e90d4251f4922f50b4 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Tue, 24 Nov 2020 03:06:24 +0100 Subject: [PATCH 25/35] Fix index out of range on backspace in completer --- resources/qml/MessageInput.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index ac91e46c..4f5b4b4c 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -81,6 +81,9 @@ Rectangle { completerTriggeredAt = -1; popup.close(); } + if (popup.opened) + popup.completer.setSearchString(textArea.getText(completerTriggeredAt, cursorPosition)); + } onSelectionStartChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) onSelectionEndChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) @@ -132,9 +135,6 @@ Rectangle { textArea.clear(); event.accepted = true; } - if (popup.opened) - popup.completer.setSearchString(textArea.getText(completerTriggeredAt, cursorPosition) + event.text); - } Connections { From 9c8850a46c8f8f16bb476fcd7d3d529e82796048 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Tue, 24 Nov 2020 13:40:23 +0100 Subject: [PATCH 26/35] Match on each word in the completer --- src/CompletionProxyModel.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/CompletionProxyModel.h b/src/CompletionProxyModel.h index 91f937a4..f4ec6a96 100644 --- a/src/CompletionProxyModel.h +++ b/src/CompletionProxyModel.h @@ -3,6 +3,7 @@ // Class for showing a limited amount of completions at a time #include +#include #include "CompletionModelRoles.h" #include "Logging.h" @@ -136,6 +137,7 @@ public: : QAbstractProxyModel(parent) { setSourceModel(model); + QRegularExpression splitPoints("\\s+|-"); for (int i = 0; i < sourceModel()->rowCount(); i++) { if (i < 7) @@ -148,14 +150,23 @@ public: .toLower(); trie_.insert(string1.toUcs4(), i); + for (const auto &e : string1.split(splitPoints, Qt::SkipEmptyParts)) { + trie_.insert(e.toUcs4(), i); + } + auto string2 = sourceModel() ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole2) .toString() .toLower(); - if (!string2.isEmpty()) + if (!string2.isEmpty()) { trie_.insert(string2.toUcs4(), i); + for (const auto &e : + string2.split(splitPoints, Qt::SkipEmptyParts)) { + trie_.insert(e.toUcs4(), i); + } + } } connect( From 7cf66ea4f30a9f6daa15e79300292dd5e720c970 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Tue, 24 Nov 2020 15:35:56 +0100 Subject: [PATCH 27/35] Split completion model into header and source --- CMakeLists.txt | 1 + src/CompletionProxyModel.cpp | 133 +++++++++++++++++++++++++++++++++++ src/CompletionProxyModel.h | 121 +++---------------------------- 3 files changed, 145 insertions(+), 110 deletions(-) create mode 100644 src/CompletionProxyModel.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 52527312..bd42938a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -283,6 +283,7 @@ set(SRC_FILES src/ColorImageProvider.cpp src/CommunitiesList.cpp src/CommunitiesListItem.cpp + src/CompletionProxyModel.cpp src/DeviceVerificationFlow.cpp src/EventAccessors.cpp src/InviteeItem.cpp diff --git a/src/CompletionProxyModel.cpp b/src/CompletionProxyModel.cpp new file mode 100644 index 00000000..c520bb68 --- /dev/null +++ b/src/CompletionProxyModel.cpp @@ -0,0 +1,133 @@ +#include "CompletionProxyModel.h" + +#include + +#include "CompletionModelRoles.h" +#include "Logging.h" +#include "Utils.h" + +CompletionProxyModel::CompletionProxyModel(QAbstractItemModel *model, QObject *parent) + : QAbstractProxyModel(parent) +{ + setSourceModel(model); + QRegularExpression splitPoints("\\s+|-"); + + for (int i = 0; i < sourceModel()->rowCount(); i++) { + if (i < 7) + mapping.push_back(i); + + auto string1 = sourceModel() + ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole) + .toString() + .toLower(); + trie_.insert(string1.toUcs4(), i); + + for (const auto &e : string1.split(splitPoints, Qt::SkipEmptyParts)) { + trie_.insert(e.toUcs4(), i); + } + + auto string2 = sourceModel() + ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole2) + .toString() + .toLower(); + + if (!string2.isEmpty()) { + trie_.insert(string2.toUcs4(), i); + for (const auto &e : string2.split(splitPoints, Qt::SkipEmptyParts)) { + trie_.insert(e.toUcs4(), i); + } + } + } + + connect( + this, + &CompletionProxyModel::newSearchString, + this, + [this](QString s) { + s.remove(":"); + s.remove("@"); + searchString = s.toLower(); + invalidate(); + }, + Qt::QueuedConnection); +} + +void +CompletionProxyModel::invalidate() +{ + auto key = searchString.toUcs4(); + beginResetModel(); + mapping = trie_.search(key, 7); + endResetModel(); + + std::string temp; + for (auto v : mapping) { + temp += std::to_string(v) + ", "; + } + nhlog::ui()->debug("mapping: {}", temp); +} + +QHash +CompletionProxyModel::roleNames() const +{ + return this->sourceModel()->roleNames(); +} + +int +CompletionProxyModel::rowCount(const QModelIndex &) const +{ + return (int)mapping.size(); +} + +QModelIndex +CompletionProxyModel::mapFromSource(const QModelIndex &sourceIndex) const +{ + for (int i = 0; i < (int)mapping.size(); i++) { + if (mapping[i] == sourceIndex.row()) { + return index(i, 0); + } + } + return QModelIndex(); +} + +QModelIndex +CompletionProxyModel::mapToSource(const QModelIndex &proxyIndex) const +{ + auto row = proxyIndex.row(); + if (row < 0 || row >= (int)mapping.size()) + return QModelIndex(); + + return sourceModel()->index(mapping[row], 0); +} + +QModelIndex +CompletionProxyModel::index(int row, int column, const QModelIndex &) const +{ + return createIndex(row, column); +} + +QModelIndex +CompletionProxyModel::parent(const QModelIndex &) const +{ + return QModelIndex{}; +} +int +CompletionProxyModel::columnCount(const QModelIndex &) const +{ + return sourceModel()->columnCount(); +} + +QVariant +CompletionProxyModel::completionAt(int i) const +{ + if (i >= 0 && i < rowCount()) + return data(index(i, 0), CompletionModel::CompletionRole); + else + return {}; +} + +void +CompletionProxyModel::setSearchString(QString s) +{ + emit newSearchString(s); +} diff --git a/src/CompletionProxyModel.h b/src/CompletionProxyModel.h index f4ec6a96..1517505f 100644 --- a/src/CompletionProxyModel.h +++ b/src/CompletionProxyModel.h @@ -3,11 +3,6 @@ // Class for showing a limited amount of completions at a time #include -#include - -#include "CompletionModelRoles.h" -#include "Logging.h" -#include "Utils.h" template struct trie @@ -133,120 +128,26 @@ class CompletionProxyModel : public QAbstractProxyModel Q_OBJECT public: - CompletionProxyModel(QAbstractItemModel *model, QObject *parent = nullptr) - : QAbstractProxyModel(parent) - { - setSourceModel(model); - QRegularExpression splitPoints("\\s+|-"); + CompletionProxyModel(QAbstractItemModel *model, QObject *parent = nullptr); - for (int i = 0; i < sourceModel()->rowCount(); i++) { - if (i < 7) - mapping.push_back(i); + void invalidate(); - auto string1 = - sourceModel() - ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole) - .toString() - .toLower(); - trie_.insert(string1.toUcs4(), i); + QHash roleNames() const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &) const override; - for (const auto &e : string1.split(splitPoints, Qt::SkipEmptyParts)) { - trie_.insert(e.toUcs4(), i); - } - - auto string2 = - sourceModel() - ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole2) - .toString() - .toLower(); - - if (!string2.isEmpty()) { - trie_.insert(string2.toUcs4(), i); - for (const auto &e : - string2.split(splitPoints, Qt::SkipEmptyParts)) { - trie_.insert(e.toUcs4(), i); - } - } - } - - connect( - this, - &CompletionProxyModel::newSearchString, - this, - [this](QString s) { - s.remove(":"); - s.remove("@"); - searchString = s.toLower(); - invalidate(); - }, - Qt::QueuedConnection); - } - - void invalidate() - { - auto key = searchString.toUcs4(); - beginResetModel(); - mapping = trie_.search(key, 7); - endResetModel(); - - std::string temp; - for (auto v : mapping) { - temp += std::to_string(v) + ", "; - } - nhlog::ui()->debug("mapping: {}", temp); - }; - - QHash roleNames() const override - { - return this->sourceModel()->roleNames(); - } - - int rowCount(const QModelIndex &parent = QModelIndex()) const override - { - (void)parent; - return (int)mapping.size(); - } - - QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override - { - for (int i = 0; i < (int)mapping.size(); i++) { - if (mapping[i] == sourceIndex.row()) { - return index(i, 0); - } - } - return QModelIndex(); - } - - QModelIndex mapToSource(const QModelIndex &proxyIndex) const override - { - auto row = proxyIndex.row(); - if (row < 0 || row >= (int)mapping.size()) - return QModelIndex(); - - return sourceModel()->index(mapping[row], 0); - } + QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override; + QModelIndex mapToSource(const QModelIndex &proxyIndex) const override; QModelIndex index(int row, int column, - const QModelIndex &parent = QModelIndex()) const override - { - (void)parent; - return createIndex(row, column); - } - - QModelIndex parent(const QModelIndex &) const override { return QModelIndex{}; } - int columnCount(const QModelIndex &) const override { return sourceModel()->columnCount(); } + const QModelIndex &parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex &) const override; public slots: - QVariant completionAt(int i) const - { - if (i >= 0 && i < rowCount()) - return data(index(i, 0), CompletionModel::CompletionRole); - else - return {}; - } + QVariant completionAt(int i) const; - void setSearchString(QString s) { emit newSearchString(s); } + void setSearchString(QString s); signals: void newSearchString(QString); From 0cf556fa20b6cf9037517ed7bbbea5d3da820ce8 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Tue, 24 Nov 2020 17:32:45 +0100 Subject: [PATCH 28/35] Mouse selection of completions --- resources/qml/Completer.qml | 9 +++++++++ resources/qml/MessageInput.qml | 15 ++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/resources/qml/Completer.qml b/resources/qml/Completer.qml index 7074de81..647e4d85 100644 --- a/resources/qml/Completer.qml +++ b/resources/qml/Completer.qml @@ -11,6 +11,8 @@ Popup { property var completer property bool bottomToTop: true + signal completionClicked(string completion) + function up() { if (bottomToTop) down_(); @@ -76,6 +78,13 @@ Popup { height: chooser.childrenRect.height + 4 implicitWidth: chooser.childrenRect.width + 4 + MouseArea { + anchors.fill: parent + hoverEnabled: true + onEntered: popup.currentIndex = model.index + onClicked: popup.completionClicked(completer.completionAt(model.index)) + } + DelegateChooser { id: chooser diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index 4f5b4b4c..7a033f5b 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -70,6 +70,11 @@ Rectangle { property int completerTriggeredAt: -1 + function insertCompletion(completion) { + textArea.remove(completerTriggeredAt, cursorPosition); + textArea.insert(cursorPosition, completion); + } + placeholderText: qsTr("Write a message...") placeholderTextColor: colors.buttonText color: colors.text @@ -87,6 +92,7 @@ Rectangle { } onSelectionStartChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) onSelectionEndChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) + // Ensure that we get escape key press events first. Keys.onShortcutOverride: event.accepted = (completerTriggeredAt != -1 && (event.key === Qt.Key_Escape || event.key === Qt.Key_Tab || event.key === Qt.Key_Enter)) Keys.onPressed: { if (event.matches(StandardKey.Paste)) { @@ -116,8 +122,7 @@ Rectangle { popup.completerName = ""; popup.close(); if (currentCompletion) { - textArea.remove(completerTriggeredAt, cursorPosition); - textArea.insert(cursorPosition, currentCompletion); + textArea.insertCompletion(currentCompletion); event.accepted = true; return ; } @@ -146,7 +151,11 @@ Rectangle { } target: TimelineManager } - // Ensure that we get escape key press events first. + + Connections { + onCompletionClicked: textArea.insertCompletion(completion) + target: popup + } Completer { id: popup From c07c3261414b537a21c0493f73d9790c36dde219 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Tue, 24 Nov 2020 19:01:52 +0100 Subject: [PATCH 29/35] Linkify username completion --- src/UsersModel.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/UsersModel.cpp b/src/UsersModel.cpp index cb9f8f75..aeabf467 100644 --- a/src/UsersModel.cpp +++ b/src/UsersModel.cpp @@ -32,6 +32,9 @@ UsersModel::data(const QModelIndex &index, int role) const if (hasIndex(index.row(), index.column(), index.parent())) { switch (role) { case CompletionModel::CompletionRole: + return QString("[%1](https://matrix.to/#/%2)") + .arg(displayNames[index.row()]) + .arg(userids[index.row()]); case CompletionModel::SearchRole: case Qt::DisplayRole: case Roles::DisplayName: From 37df79f7964795e03ffca10c4623cb9061aa3b9c Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Tue, 24 Nov 2020 19:06:31 +0100 Subject: [PATCH 30/35] Show userid in completer --- resources/qml/Completer.qml | 5 +++++ src/UsersModel.cpp | 3 +++ src/UsersModel.h | 1 + 3 files changed, 9 insertions(+) diff --git a/resources/qml/Completer.qml b/resources/qml/Completer.qml index 647e4d85..9703da64 100644 --- a/resources/qml/Completer.qml +++ b/resources/qml/Completer.qml @@ -111,6 +111,11 @@ Popup { color: model.index == popup.currentIndex ? colors.highlightedText : colors.text } + Label { + text: "(" + model.userid + ")" + color: model.index == popup.currentIndex ? colors.highlightedText : colors.buttonText + } + } } diff --git a/src/UsersModel.cpp b/src/UsersModel.cpp index aeabf467..4be37503 100644 --- a/src/UsersModel.cpp +++ b/src/UsersModel.cpp @@ -23,6 +23,7 @@ UsersModel::roleNames() const {CompletionModel::SearchRole2, "searchRole2"}, {Roles::DisplayName, "displayName"}, {Roles::AvatarUrl, "avatarUrl"}, + {Roles::UserID, "userid"}, }; } @@ -44,6 +45,8 @@ UsersModel::data(const QModelIndex &index, int role) const case Roles::AvatarUrl: return cache::avatarUrl(QString::fromStdString(room_id), QString::fromStdString(roomMembers_[index.row()])); + case Roles::UserID: + return userids[index.row()]; } } return {}; diff --git a/src/UsersModel.h b/src/UsersModel.h index cddcdd84..c60b34b8 100644 --- a/src/UsersModel.h +++ b/src/UsersModel.h @@ -9,6 +9,7 @@ public: { AvatarUrl = Qt::UserRole, DisplayName, + UserID, }; UsersModel(const std::string &roomId, QObject *parent = nullptr); From bc93f24a22ca18232bec27134eedeb1316fb5e88 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 25 Nov 2020 02:10:09 +0100 Subject: [PATCH 31/35] Remove redundant user search suggestion code --- src/Cache.cpp | 42 ------------------- src/Cache.h | 2 - src/CacheStructs.h | 6 --- src/Cache_p.h | 3 -- src/QuickSwitcher.cpp | 2 +- src/popups/SuggestionsPopup.cpp | 73 ++++++++++++++++----------------- src/popups/SuggestionsPopup.h | 36 +++------------- 7 files changed, 42 insertions(+), 122 deletions(-) diff --git a/src/Cache.cpp b/src/Cache.cpp index b37f69b3..3a6b0ca9 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -85,8 +85,6 @@ constexpr auto OUTBOUND_MEGOLM_SESSIONS_DB("outbound_megolm_sessions"); using CachedReceipts = std::multimap>; using Receipts = std::map>; -Q_DECLARE_METATYPE(SearchResult) -Q_DECLARE_METATYPE(std::vector) Q_DECLARE_METATYPE(RoomMember) Q_DECLARE_METATYPE(mtx::responses::Timeline) Q_DECLARE_METATYPE(RoomSearchResult) @@ -2334,39 +2332,6 @@ Cache::searchRooms(const std::string &query, std::uint8_t max_items) return results; } -std::vector -Cache::searchUsers(const std::string &room_id, const std::string &query, std::uint8_t max_items) -{ - std::multimap> items; - - auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); - auto cursor = lmdb::cursor::open(txn, getMembersDb(txn, room_id)); - - std::string user_id, user_data; - while (cursor.get(user_id, user_data, MDB_NEXT)) { - const auto display_name = displayName(room_id, user_id); - const int score = utils::levenshtein_distance(query, display_name); - - items.emplace(score, std::make_pair(user_id, display_name)); - } - - auto end = items.begin(); - - if (items.size() >= max_items) - std::advance(end, max_items); - else if (items.size() > 0) - std::advance(end, items.size()); - - std::vector results; - for (auto it = items.begin(); it != end; it++) { - const auto user = it->second; - results.push_back(SearchResult{QString::fromStdString(user.first), - QString::fromStdString(user.second)}); - } - - return results; -} - std::vector Cache::getMembers(const std::string &room_id, std::size_t startIndex, std::size_t len) { @@ -3762,8 +3727,6 @@ namespace cache { void init(const QString &user_id) { - qRegisterMetaType(); - qRegisterMetaType>(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); @@ -4075,11 +4038,6 @@ calculateRoomReadStatus() instance_->calculateRoomReadStatus(); } -std::vector -searchUsers(const std::string &room_id, const std::string &query, std::uint8_t max_items) -{ - return instance_->searchUsers(room_id, query, max_items); -} std::vector searchRooms(const std::string &query, std::uint8_t max_items) { diff --git a/src/Cache.h b/src/Cache.h index 4c4f7071..573ab700 100644 --- a/src/Cache.h +++ b/src/Cache.h @@ -194,8 +194,6 @@ calculateRoomReadStatus(const std::string &room_id); void calculateRoomReadStatus(); -std::vector -searchUsers(const std::string &room_id, const std::string &query, std::uint8_t max_items = 5); std::vector searchRooms(const std::string &query, std::uint8_t max_items = 5); diff --git a/src/CacheStructs.h b/src/CacheStructs.h index ef08cfcb..b3d9acf1 100644 --- a/src/CacheStructs.h +++ b/src/CacheStructs.h @@ -24,12 +24,6 @@ struct RoomMember QImage avatar; }; -struct SearchResult -{ - QString user_id; - QString display_name; -}; - //! Used to uniquely identify a list of read receipts. struct ReadReceiptKey { diff --git a/src/Cache_p.h b/src/Cache_p.h index 05e13128..ffa7d509 100644 --- a/src/Cache_p.h +++ b/src/Cache_p.h @@ -164,9 +164,6 @@ public: bool calculateRoomReadStatus(const std::string &room_id); void calculateRoomReadStatus(); - std::vector searchUsers(const std::string &room_id, - const std::string &query, - std::uint8_t max_items = 5); std::vector searchRooms(const std::string &query, std::uint8_t max_items = 5); diff --git a/src/QuickSwitcher.cpp b/src/QuickSwitcher.cpp index 05a9f431..046c774d 100644 --- a/src/QuickSwitcher.cpp +++ b/src/QuickSwitcher.cpp @@ -118,7 +118,7 @@ QuickSwitcher::QuickSwitcher(QWidget *parent) connect(roomSearch_, &RoomSearchInput::hiding, this, [this]() { popup_.hide(); }); connect(roomSearch_, &QLineEdit::returnPressed, this, [this]() { reset(); - popup_.selectHoveredSuggestion(); + popup_.selectHoveredSuggestion(); }); } diff --git a/src/popups/SuggestionsPopup.cpp b/src/popups/SuggestionsPopup.cpp index e84435b7..2650b5e6 100644 --- a/src/popups/SuggestionsPopup.cpp +++ b/src/popups/SuggestionsPopup.cpp @@ -6,6 +6,8 @@ #include "../Utils.h" #include "../ui/Avatar.h" #include "../ui/DropShadow.h" +#include "ChatPage.h" +#include "PopupItem.h" #include "SuggestionsPopup.h" SuggestionsPopup::SuggestionsPopup(QWidget *parent) @@ -65,44 +67,6 @@ SuggestionsPopup::addRooms(const std::vector &rooms) selectNextSuggestion(); } -void -SuggestionsPopup::addUsers(const std::vector &users) -{ - if (users.empty()) { - hide(); - return; - } - - const size_t layoutCount = layout_->count(); - const size_t userCount = users.size(); - - // Remove the extra widgets from the layout. - if (userCount < layoutCount) - removeLayoutItemsAfter(userCount - 1); - - for (size_t i = 0; i < userCount; ++i) { - auto item = layout_->itemAt(i); - - // Create a new widget if there isn't already one in that - // layout position. - if (!item) { - auto user = new UserItem(this, users.at(i).user_id); - connect(user, &UserItem::clicked, this, &SuggestionsPopup::itemSelected); - layout_->addWidget(user); - } else { - // Update the current widget with the new data. - auto userWidget = qobject_cast(item->widget()); - if (userWidget) - userWidget->updateItem(users.at(i).user_id); - } - } - - resetSelection(); - adjustSize(); - - selectNextSuggestion(); -} - void SuggestionsPopup::hoverSelection() { @@ -111,6 +75,19 @@ SuggestionsPopup::hoverSelection() update(); } +void +SuggestionsPopup::selectHoveredSuggestion() +{ + const auto item = layout_->itemAt(selectedItem_); + if (!item) + return; + + const auto &widget = qobject_cast(item->widget()); + emit itemSelected(displayName(ChatPage::instance()->currentRoom(), widget->selectedText())); + + resetSelection(); +} + void SuggestionsPopup::selectNextSuggestion() { @@ -160,3 +137,23 @@ SuggestionsPopup::paintEvent(QPaintEvent *) QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } + +void +SuggestionsPopup::selectLastItem() +{ + selectedItem_ = layout_->count() - 1; +} + +void +SuggestionsPopup::removeLayoutItemsAfter(size_t startingPos) +{ + size_t posToRemove = layout_->count() - 1; + + QLayoutItem *item; + while (startingPos <= posToRemove && (item = layout_->takeAt(posToRemove)) != nullptr) { + delete item->widget(); + delete item; + + posToRemove = layout_->count() - 1; + } +} diff --git a/src/popups/SuggestionsPopup.h b/src/popups/SuggestionsPopup.h index c66f2903..6a0157a1 100644 --- a/src/popups/SuggestionsPopup.h +++ b/src/popups/SuggestionsPopup.h @@ -3,8 +3,9 @@ #include #include "CacheStructs.h" -#include "ChatPage.h" -#include "PopupItem.h" + +class QVBoxLayout; +class QLayoutItem; class SuggestionsPopup : public QWidget { @@ -13,22 +14,9 @@ class SuggestionsPopup : public QWidget public: explicit SuggestionsPopup(QWidget *parent = nullptr); - template - void selectHoveredSuggestion() - { - const auto item = layout_->itemAt(selectedItem_); - if (!item) - return; - - const auto &widget = qobject_cast(item->widget()); - emit itemSelected( - displayName(ChatPage::instance()->currentRoom(), widget->selectedText())); - - resetSelection(); - } + void selectHoveredSuggestion(); public slots: - void addUsers(const std::vector &users); void addRooms(const std::vector &rooms); //! Move to the next available suggestion item. @@ -51,20 +39,8 @@ private: void hoverSelection(); void resetSelection() { selectedItem_ = -1; } void selectFirstItem() { selectedItem_ = 0; } - void selectLastItem() { selectedItem_ = layout_->count() - 1; } - void removeLayoutItemsAfter(size_t startingPos) - { - size_t posToRemove = layout_->count() - 1; - - QLayoutItem *item; - while (startingPos <= posToRemove && - (item = layout_->takeAt(posToRemove)) != nullptr) { - delete item->widget(); - delete item; - - posToRemove = layout_->count() - 1; - } - } + void selectLastItem(); + void removeLayoutItemsAfter(size_t startingPos); QVBoxLayout *layout_; From 0eb8d4126b50a2e7d11998dbe60a8d04035827f8 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 25 Nov 2020 02:20:42 +0100 Subject: [PATCH 32/35] Fix enter when no completion available --- resources/qml/MessageInput.qml | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index 7a033f5b..76eac5b3 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -117,15 +117,20 @@ Rectangle { popup.completerName = ""; event.accepted = true; popup.close(); - } else if (event.matches(StandardKey.InsertParagraphSeparator) && popup.opened) { - var currentCompletion = popup.currentCompletion(); - popup.completerName = ""; - popup.close(); - if (currentCompletion) { - textArea.insertCompletion(currentCompletion); - event.accepted = true; - return ; + } else if (event.matches(StandardKey.InsertParagraphSeparator)) { + if (popup.opened) { + var currentCompletion = popup.currentCompletion(); + popup.completerName = ""; + popup.close(); + if (currentCompletion) { + textArea.insertCompletion(currentCompletion); + event.accepted = true; + return ; + } } + TimelineManager.timeline.input.send(); + textArea.clear(); + event.accepted = true; } else if (event.key == Qt.Key_Tab && popup.opened) { event.accepted = true; popup.down(); @@ -135,10 +140,6 @@ Rectangle { } else if (event.key == Qt.Key_Down && popup.opened) { event.accepted = true; popup.down(); - } else if (event.matches(StandardKey.InsertParagraphSeparator)) { - TimelineManager.timeline.input.send(); - textArea.clear(); - event.accepted = true; } } From c74077a41f5e89c0331d682b481408ad22d7ec78 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 25 Nov 2020 17:02:23 +0100 Subject: [PATCH 33/35] Implement Qml drag and drop --- CMakeLists.txt | 12 +++++---- resources/qml/MessageInput.qml | 5 ++++ src/ChatPage.h | 1 + src/timeline/InputBar.cpp | 8 ++++++ src/timeline/InputBar.h | 2 ++ src/timeline/TimelineViewManager.cpp | 3 +++ src/timeline/TimelineViewManager.h | 9 +++++++ src/ui/NhekoDropArea.cpp | 39 ++++++++++++++++++++++++++++ src/ui/NhekoDropArea.h | 30 +++++++++++++++++++++ 9 files changed, 104 insertions(+), 5 deletions(-) create mode 100644 src/ui/NhekoDropArea.cpp create mode 100644 src/ui/NhekoDropArea.h diff --git a/CMakeLists.txt b/CMakeLists.txt index bd42938a..e8570c77 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -257,22 +257,23 @@ set(SRC_FILES src/ui/Avatar.cpp src/ui/Badge.cpp src/ui/DropShadow.cpp - src/ui/LoadingIndicator.cpp - src/ui/InfoMessage.cpp src/ui/FlatButton.cpp src/ui/FloatingButton.cpp + src/ui/InfoMessage.cpp src/ui/Label.cpp + src/ui/LoadingIndicator.cpp + src/ui/NhekoDropArea.cpp src/ui/OverlayModal.cpp - src/ui/SnackBar.cpp + src/ui/OverlayWidget.cpp src/ui/RaisedButton.cpp src/ui/Ripple.cpp src/ui/RippleOverlay.cpp - src/ui/OverlayWidget.cpp + src/ui/SnackBar.cpp src/ui/TextField.cpp src/ui/TextLabel.cpp - src/ui/ToggleButton.cpp src/ui/Theme.cpp src/ui/ThemeManager.cpp + src/ui/ToggleButton.cpp src/ui/UserProfile.cpp src/AvatarProvider.cpp @@ -471,6 +472,7 @@ qt5_wrap_cpp(MOC_HEADERS src/ui/Label.h src/ui/FloatingButton.h src/ui/Menu.h + src/ui/NhekoDropArea.h src/ui/OverlayWidget.h src/ui/SnackBar.h src/ui/RaisedButton.h diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index 76eac5b3..812c450e 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -178,6 +178,11 @@ Rectangle { onClicked: TimelineManager.timeline.input.paste(true) } + NhekoDropArea { + anchors.fill: parent + roomid: TimelineManager.timeline.roomId() + } + background: Rectangle { color: colors.window } diff --git a/src/ChatPage.h b/src/ChatPage.h index 273ba4af..5b336cbb 100644 --- a/src/ChatPage.h +++ b/src/ChatPage.h @@ -88,6 +88,7 @@ public: QSharedPointer userSettings() { return userSettings_; } CallManager *callManager() { return callManager_; } + TimelineViewManager *timelineManager() { return view_manager_; } void deleteConfigs(); CommunitiesList *communitiesList() { return communitiesList_; } diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp index b0d555b7..46bbd9a2 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp @@ -1,6 +1,7 @@ #include "InputBar.h" #include +#include #include #include #include @@ -44,6 +45,13 @@ InputBar::paste(bool fromMouse) md = QGuiApplication::clipboard()->mimeData(QClipboard::Clipboard); } + if (md) + insertMimeData(md); +} + +void +InputBar::insertMimeData(const QMimeData *md) +{ if (!md) return; diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h index 939e8dad..27aa4bc3 100644 --- a/src/timeline/InputBar.h +++ b/src/timeline/InputBar.h @@ -9,6 +9,7 @@ class TimelineModel; class QMimeData; +class QDropEvent; class QStringList; class InputBar : public QObject @@ -36,6 +37,7 @@ public slots: void send(); void paste(bool fromMouse); + void insertMimeData(const QMimeData *data); void updateState(int selectionStart, int selectionEnd, int cursorPosition, QString text); void openFileSelection(); bool uploading() const { return uploading_; } diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 1392c505..866e7c51 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -1,6 +1,7 @@ #include "TimelineViewManager.h" #include +#include #include #include #include @@ -20,6 +21,7 @@ #include "dialogs/ImageOverlay.h" #include "emoji/EmojiModel.h" #include "emoji/Provider.h" +#include "ui/NhekoDropArea.h" #include //only for debugging @@ -115,6 +117,7 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par qmlRegisterType("im.nheko", 1, 0, "DelegateChoice"); qmlRegisterType("im.nheko", 1, 0, "DelegateChooser"); + qmlRegisterType("im.nheko", 1, 0, "NhekoDropArea"); qmlRegisterUncreatableType( "im.nheko", 1, 0, "DeviceVerificationFlow", "Can't create verification flow from QML!"); qmlRegisterUncreatableType( diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 371e9af2..b9febf75 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -105,6 +105,15 @@ public slots: void initWithMessages(const std::vector &roomIds); void setHistoryView(const QString &room_id); + TimelineModel *getHistoryView(const QString &room_id) + { + auto room = models.find(room_id); + if (room != models.end()) + return room.value().data(); + else + return nullptr; + } + void updateColorPalette(); void queueReactionMessage(const QString &reactedEvent, const QString &reactionKey); void queueCallMessage(const QString &roomid, const mtx::events::msg::CallInvite &); diff --git a/src/ui/NhekoDropArea.cpp b/src/ui/NhekoDropArea.cpp new file mode 100644 index 00000000..14b71524 --- /dev/null +++ b/src/ui/NhekoDropArea.cpp @@ -0,0 +1,39 @@ +#include "NhekoDropArea.h" + +#include + +#include "ChatPage.h" +#include "timeline/InputBar.h" +#include "timeline/TimelineModel.h" +#include "timeline/TimelineViewManager.h" + +#include "Logging.h" + +NhekoDropArea::NhekoDropArea(QQuickItem *parent) + : QQuickItem(parent) +{ + setFlags(ItemAcceptsDrops); +} + +void +NhekoDropArea::dragEnterEvent(QDragEnterEvent *event) +{ + event->acceptProposedAction(); +} + +void +NhekoDropArea::dragMoveEvent(QDragMoveEvent *event) +{ + event->acceptProposedAction(); +} + +void +NhekoDropArea::dropEvent(QDropEvent *event) +{ + if (event) { + auto model = ChatPage::instance()->timelineManager()->getHistoryView(roomid_); + if (model) { + model->input()->insertMimeData(event->mimeData()); + } + } +} diff --git a/src/ui/NhekoDropArea.h b/src/ui/NhekoDropArea.h new file mode 100644 index 00000000..b03620f2 --- /dev/null +++ b/src/ui/NhekoDropArea.h @@ -0,0 +1,30 @@ +#include + +class NhekoDropArea : public QQuickItem +{ + Q_OBJECT + Q_PROPERTY(QString roomid READ roomid WRITE setRoomid NOTIFY roomidChanged) +public: + NhekoDropArea(QQuickItem *parent = nullptr); + +signals: + void roomidChanged(QString roomid); + +public slots: + void setRoomid(QString roomid) + { + if (roomid_ != roomid) { + roomid_ = roomid; + emit roomidChanged(roomid); + } + } + QString roomid() const { return roomid_; } + +protected: + void dragEnterEvent(QDragEnterEvent *event) override; + void dragMoveEvent(QDragMoveEvent *event) override; + void dropEvent(QDropEvent *event) override; + +private: + QString roomid_; +}; From 08e94616113921dbbbf3bcfe2ec4cee7e28eaf1b Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 25 Nov 2020 17:38:06 +0100 Subject: [PATCH 34/35] Fix input focus when pressing reply button --- resources/qml/ImageButton.qml | 1 + resources/qml/MatrixText.qml | 1 + resources/qml/MessageInput.qml | 1 + resources/qml/TimelineView.qml | 1 + src/timeline/TimelineViewManager.cpp | 1 + 5 files changed, 5 insertions(+) diff --git a/resources/qml/ImageButton.qml b/resources/qml/ImageButton.qml index 49ddf671..4ebda680 100644 --- a/resources/qml/ImageButton.qml +++ b/resources/qml/ImageButton.qml @@ -8,6 +8,7 @@ AbstractButton { property color highlightColor: colors.highlight property color buttonTextColor: colors.buttonText + focusPolicy: Qt.NoFocus width: 16 height: 16 diff --git a/resources/qml/MatrixText.qml b/resources/qml/MatrixText.qml index a5781c73..bb3b4296 100644 --- a/resources/qml/MatrixText.qml +++ b/resources/qml/MatrixText.qml @@ -5,6 +5,7 @@ import im.nheko 1.0 TextEdit { textFormat: TextEdit.RichText readOnly: true + focus: false wrapMode: Text.Wrap selectByMouse: !Settings.mobileMode color: colors.text diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index 812c450e..c221cf3e 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -79,6 +79,7 @@ Rectangle { placeholderTextColor: colors.buttonText color: colors.text wrapMode: TextEdit.Wrap + focus: true onTextChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) onCursorPositionChanged: { TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text); diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index ac998a81..4234bb6d 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -97,6 +97,7 @@ Page { } MenuItem { + // TODO(Nico): Fix this still being iterated over, when using keyboard to select options visible: messageContextMenu.isEncrypted height: visible ? implicitHeight : 0 text: qsTr("View decrypted raw message") diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 866e7c51..d0356e15 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -336,6 +336,7 @@ TimelineViewManager::setHistoryView(const QString &room_id) if (room != models.end()) { timeline_ = room.value().data(); emit activeTimelineChanged(timeline_); + container->setFocus(); nhlog::ui()->info("Activated room {}", room_id.toStdString()); } } From b7505fe562b695ff6798a5443dba79956d685fd8 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 25 Nov 2020 19:03:22 +0100 Subject: [PATCH 35/35] Open completer on tab --- .gitignore | 1 + resources/qml/MessageInput.qml | 35 ++++++++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 5f6725db..e91866ed 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,7 @@ ui_*.h # Vim *.swp *.swo +*.swn #####=== CMake ===##### diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index c221cf3e..ae95cbb6 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -75,6 +75,13 @@ Rectangle { textArea.insert(cursorPosition, completion); } + function openCompleter(pos, type) { + completerTriggeredAt = pos; + popup.completerName = type; + popup.open(); + popup.completer.setSearchString(textArea.getText(completerTriggeredAt, cursorPosition)); + } + placeholderText: qsTr("Write a message...") placeholderTextColor: colors.buttonText color: colors.text @@ -106,12 +113,10 @@ Rectangle { } else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_N) { textArea.text = TimelineManager.timeline.input.nextText(); } else if (event.key == Qt.Key_At) { - completerTriggeredAt = cursorPosition; - popup.completerName = "user"; + textArea.openCompleter(cursorPosition, "user"); popup.open(); } else if (event.key == Qt.Key_Colon) { - completerTriggeredAt = cursorPosition; - popup.completerName = "emoji"; + textArea.openCompleter(cursorPosition, "emoji"); popup.open(); } else if (event.key == Qt.Key_Escape && popup.opened) { completerTriggeredAt = -1; @@ -132,9 +137,27 @@ Rectangle { TimelineManager.timeline.input.send(); textArea.clear(); event.accepted = true; - } else if (event.key == Qt.Key_Tab && popup.opened) { + } else if (event.key == Qt.Key_Tab) { event.accepted = true; - popup.down(); + if (popup.opened) { + popup.up(); + } else { + var pos = cursorPosition - 1; + while (pos > -1) { + var t = textArea.getText(pos, pos + 1); + console.log('"' + t + '"'); + if (t == '@' || t == ' ' || t == '\t') { + textArea.openCompleter(pos, "user"); + return ; + } else if (t == ':') { + textArea.openCompleter(pos, "emoji"); + return ; + } + pos = pos - 1; + } + // At start of input + textArea.openCompleter(0, "user"); + } } else if (event.key == Qt.Key_Up && popup.opened) { event.accepted = true; popup.up();