summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2023-05-25 21:50:54 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2023-05-25 21:53:23 +0200
commit51084748ee4db5f7faab996147a85132cbb80031 (patch)
tree4bb744783aeddc95979a0b567a872a7cd480b95d
parentdd74bdc697fb0fe41c5b14694dec9cc028353d23 (diff)
Make default completer complete custom emoji
-rw-r--r--CMakeLists.txt2
-rw-r--r--man/nheko.1.adoc8
-rw-r--r--resources/qml/Completer.qml52
-rw-r--r--resources/qml/MessageInput.qml2
-rw-r--r--src/CombinedImagePackModel.cpp79
-rw-r--r--src/CombinedImagePackModel.h17
-rw-r--r--src/GridImagePackModel.cpp4
-rw-r--r--src/MainWindow.cpp4
-rw-r--r--src/emoji/EmojiModel.cpp78
-rw-r--r--src/emoji/EmojiModel.h40
-rw-r--r--src/emoji/Provider.h2
-rw-r--r--src/timeline/TimelineViewManager.cpp18
12 files changed, 80 insertions, 226 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dad4fb16..b7c02ffb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -356,8 +356,6 @@ set(SRC_FILES
src/dialogs/ReCaptcha.h
# Emoji
- src/emoji/EmojiModel.cpp
- src/emoji/EmojiModel.h
src/emoji/Provider.cpp
src/emoji/Provider.h
diff --git a/man/nheko.1.adoc b/man/nheko.1.adoc
index 690ed568..8327a061 100644
--- a/man/nheko.1.adoc
+++ b/man/nheko.1.adoc
@@ -91,11 +91,9 @@ Open username completer.
Open room completer.
*:*::
-Open unicode emoji picker.
-
-*~*::
-Open custom emoji picker. Requires an image pack with custom emojis. Selecting
-an emoji will add HTML code for the inline image into the input line.
+Open the emoji picker. Unicode emoji are inserted directly. Custom emoji will
+insert the HTML code for them into the input line. You can configure custom
+emoji in the room settings.
== KEYBOARD SHORTCUTS
diff --git a/resources/qml/Completer.qml b/resources/qml/Completer.qml
index cc1047a0..0a9c41ed 100644
--- a/resources/qml/Completer.qml
+++ b/resources/qml/Completer.qml
@@ -21,7 +21,7 @@ Control {
property int avatarHeight: 24
property int avatarWidth: 24
property int rowMargin: 0
- property int rowSpacing: 5
+ property int rowSpacing: Nheko.paddingSmall
property alias count: listView.count
signal completionClicked(string completion)
@@ -199,37 +199,32 @@ Control {
spacing: rowSpacing
Label {
+ visible: !!model.unicode
text: model.unicode
color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text
font: Settings.emojiFont
}
- Label {
- text: model.shortName
- color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text
+ Avatar {
+ visible: !model.unicode
+ height: popup.avatarHeight
+ width: popup.avatarWidth
+ displayName: model.shortcode
+ //userid: model.shortcode
+ url: (model.url ? model.url : "").replace("mxc://", "image://MxcImage/")
+ enabled: false
+ crop: false
}
- }
-
- }
-
- DelegateChoice {
- roleValue: "command"
-
- RowLayout {
- id: del
-
- anchors.centerIn: parent
- spacing: rowSpacing
-
Label {
- text: model.name
+ Layout.leftMargin: Nheko.paddingSmall
+ Layout.rightMargin: Nheko.paddingSmall
+ text: model.shortcode
color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text
- font.bold: true
}
Label {
- text: model.description
+ text: "(" + model.packname + ")"
color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.buttonText
}
@@ -238,7 +233,7 @@ Control {
}
DelegateChoice {
- roleValue: "customEmoji"
+ roleValue: "command"
RowLayout {
id: del
@@ -246,23 +241,14 @@ Control {
anchors.centerIn: parent
spacing: rowSpacing
- Avatar {
- height: popup.avatarHeight
- width: popup.avatarWidth
- displayName: model.shortcode
- //userid: model.shortcode
- url: model.url.replace("mxc://", "image://MxcImage/")
- enabled: false
- crop: false
- }
-
Label {
- text: model.shortcode
+ text: model.name
color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text
+ font.bold: true
}
Label {
- text: "(" + model.packname + ")"
+ text: model.description
color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.buttonText
}
diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml
index b810b9f0..8e72f458 100644
--- a/resources/qml/MessageInput.qml
+++ b/resources/qml/MessageInput.qml
@@ -169,8 +169,6 @@ Rectangle {
messageInput.openCompleter(selectionStart-1, "emoji");
} else if (lastChar == '#') {
messageInput.openCompleter(selectionStart-1, "roomAliases");
- } else if (lastChar == "~") {
- messageInput.openCompleter(selectionStart-1, "customEmoji");
} else if (lastChar == "/" && cursorPosition == 1) {
messageInput.openCompleter(selectionStart-1, "command");
}
diff --git a/src/CombinedImagePackModel.cpp b/src/CombinedImagePackModel.cpp
index 64deaeb9..23fb50f1 100644
--- a/src/CombinedImagePackModel.cpp
+++ b/src/CombinedImagePackModel.cpp
@@ -6,14 +6,13 @@
#include "Cache_p.h"
#include "CompletionModelRoles.h"
+#include "emoji/Provider.h"
-CombinedImagePackModel::CombinedImagePackModel(const std::string &roomId,
- bool stickers,
- QObject *parent)
+CombinedImagePackModel::CombinedImagePackModel(const std::string &roomId, QObject *parent)
: QAbstractListModel(parent)
, room_id(roomId)
{
- auto packs = cache::client()->getImagePacks(room_id, stickers);
+ auto packs = cache::client()->getImagePacks(room_id, false);
for (const auto &pack : packs) {
QString packname =
@@ -32,7 +31,7 @@ CombinedImagePackModel::CombinedImagePackModel(const std::string &roomId,
int
CombinedImagePackModel::rowCount(const QModelIndex &) const
{
- return (int)images.size();
+ return (int)(emoji::Provider::emoji.size() + images.size());
}
QHash<int, QByteArray>
@@ -46,36 +45,60 @@ CombinedImagePackModel::roleNames() const
{Roles::ShortCode, "shortcode"},
{Roles::Body, "body"},
{Roles::PackName, "packname"},
- {Roles::OriginalRow, "originalRow"},
+ {Roles::Unicode, "unicode"},
};
}
QVariant
CombinedImagePackModel::data(const QModelIndex &index, int role) const
{
+ using emoji::Provider;
if (hasIndex(index.row(), index.column(), index.parent())) {
- switch (role) {
- case CompletionModel::CompletionRole:
- return QStringLiteral(
- "<img data-mx-emoticon height=\"32\" src=\"%1\" alt=\"%2\" title=\"%2\">")
- .arg(QString::fromStdString(images[index.row()].image.url).toHtmlEscaped(),
- !images[index.row()].image.body.empty()
- ? QString::fromStdString(images[index.row()].image.body)
- : images[index.row()].shortcode);
- case Roles::Url:
- return QString::fromStdString(images[index.row()].image.url);
- case CompletionModel::SearchRole:
- case Roles::ShortCode:
- return images[index.row()].shortcode;
- case CompletionModel::SearchRole2:
- case Roles::Body:
- return QString::fromStdString(images[index.row()].image.body);
- case Roles::PackName:
- return images[index.row()].packname;
- case Roles::OriginalRow:
- return index.row();
- default:
- return {};
+ if (index.row() < (int)emoji::Provider::emoji.size()) {
+ switch (role) {
+ case CompletionModel::CompletionRole:
+ case Roles::Unicode:
+ return emoji::Provider::emoji[index.row()].unicode();
+
+ case Qt::ToolTipRole:
+ return Provider::emoji[index.row()].shortName() + ", " +
+ Provider::emoji[index.row()].unicodeName();
+ case CompletionModel::SearchRole2:
+ case Roles::Body:
+ return Provider::emoji[index.row()].unicodeName();
+ case CompletionModel::SearchRole:
+ case Roles::ShortCode:
+ return Provider::emoji[index.row()].shortName();
+ case Roles::PackName:
+ return emoji::categoryToName(Provider::emoji[index.row()].category);
+ default:
+ return {};
+ }
+ } else {
+ int row = index.row() - static_cast<int>(emoji::Provider::emoji.size());
+ switch (role) {
+ case CompletionModel::CompletionRole:
+ return QStringLiteral(
+ "<img data-mx-emoticon height=\"32\" src=\"%1\" alt=\"%2\" title=\"%2\">")
+ .arg(QString::fromStdString(images[row].image.url).toHtmlEscaped(),
+ !images[row].image.body.empty()
+ ? QString::fromStdString(images[row].image.body)
+ : images[row].shortcode);
+ case Roles::Url:
+ return QString::fromStdString(images[row].image.url);
+ case CompletionModel::SearchRole:
+ case Roles::ShortCode:
+ return images[row].shortcode;
+ case CompletionModel::SearchRole2:
+ case Roles::Body:
+ return QString::fromStdString(images[row].image.body);
+ case Roles::PackName:
+ return images[row].packname;
+ case Roles::Unicode:
+ return QString();
+ default:
+ return {};
+ }
}
}
return {};
diff --git a/src/CombinedImagePackModel.h b/src/CombinedImagePackModel.h
index 7e89da50..64387390 100644
--- a/src/CombinedImagePackModel.h
+++ b/src/CombinedImagePackModel.h
@@ -18,27 +18,14 @@ public:
ShortCode,
Body,
PackName,
- OriginalRow,
+ Unicode,
};
- CombinedImagePackModel(const std::string &roomId, bool stickers, QObject *parent = nullptr);
+ CombinedImagePackModel(const std::string &roomId, QObject *parent = nullptr);
QHash<int, QByteArray> roleNames() const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role) const override;
- mtx::events::msc2545::PackImage imageAt(int row)
- {
- if (row < 0 || static_cast<size_t>(row) >= images.size())
- return {};
- return images.at(static_cast<size_t>(row)).image;
- }
- QString shortcodeAt(int row)
- {
- if (row < 0 || static_cast<size_t>(row) >= images.size())
- return {};
- return images.at(static_cast<size_t>(row)).shortcode;
- }
-
private:
std::string room_id;
diff --git a/src/GridImagePackModel.cpp b/src/GridImagePackModel.cpp
index 469858a1..95cbd265 100644
--- a/src/GridImagePackModel.cpp
+++ b/src/GridImagePackModel.cpp
@@ -18,8 +18,8 @@ Q_DECLARE_METATYPE(TextEmoji)
Q_DECLARE_METATYPE(SectionDescription)
Q_DECLARE_METATYPE(QList<SectionDescription>)
-static QString
-categoryToName(emoji::Emoji::Category cat)
+QString
+emoji::categoryToName(emoji::Emoji::Category cat)
{
switch (cat) {
case emoji::Emoji::Category::People:
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index d9a03346..a8cc66b7 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -41,7 +41,6 @@
#include "UsersModel.h"
#include "Utils.h"
#include "dock/Dock.h"
-#include "emoji/EmojiModel.h"
#include "emoji/Provider.h"
#include "encryption/DeviceVerificationFlow.h"
#include "encryption/SelfVerificationStatus.h"
@@ -289,9 +288,6 @@ MainWindow::registerQmlTypes()
"FilteredCommunitiesModel",
QStringLiteral("Use Communities.filtered() to create a FilteredCommunitiesModel"));
- qmlRegisterType<emoji::EmojiModel>("im.nheko.EmojiModel", 1, 0, "EmojiModel");
- qmlRegisterUncreatableType<emoji::Emoji>(
- "im.nheko.EmojiModel", 1, 0, "Emoji", QStringLiteral("Used by emoji models"));
qmlRegisterUncreatableType<MediaUpload>(
"im.nheko", 1, 0, "MediaUpload", QStringLiteral("MediaUploads can not be created in Qml"));
qmlRegisterUncreatableMetaObject(emoji::staticMetaObject,
diff --git a/src/emoji/EmojiModel.cpp b/src/emoji/EmojiModel.cpp
deleted file mode 100644
index 814d17bb..00000000
--- a/src/emoji/EmojiModel.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-// SPDX-FileCopyrightText: Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#include "EmojiModel.h"
-
-#include <Cache.h>
-#include <MatrixClient.h>
-
-#include "CompletionModelRoles.h"
-
-using namespace emoji;
-
-int
-EmojiModel::categoryToIndex(int category)
-{
- auto dist = std::distance(
- Provider::emoji.begin(),
- std::lower_bound(Provider::emoji.begin(),
- Provider::emoji.end(),
- static_cast<Emoji::Category>(category),
- [](const struct Emoji &e, Emoji::Category c) { return e.category < c; }));
-
- return static_cast<int>(dist);
-}
-
-QHash<int, QByteArray>
-EmojiModel::roleNames() const
-{
- static QHash<int, QByteArray> roles;
-
- if (roles.isEmpty()) {
- roles = QAbstractListModel::roleNames();
- roles[static_cast<int>(EmojiModel::Roles::Unicode)] = QByteArrayLiteral("unicode");
- roles[static_cast<int>(EmojiModel::Roles::ShortName)] = QByteArrayLiteral("shortName");
- roles[static_cast<int>(EmojiModel::Roles::UnicodeName)] = QByteArrayLiteral("unicodeName");
- roles[static_cast<int>(EmojiModel::Roles::Category)] = QByteArrayLiteral("category");
- roles[static_cast<int>(EmojiModel::Roles::Emoji)] = QByteArrayLiteral("emoji");
- }
-
- return roles;
-}
-
-int
-EmojiModel::rowCount(const QModelIndex &parent) const
-{
- return parent == QModelIndex() ? (int)Provider::emoji.size() : 0;
-}
-
-QVariant
-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<int>(EmojiModel::Roles::Unicode):
- return Provider::emoji[index.row()].unicode();
-
- case Qt::ToolTipRole:
- return Provider::emoji[index.row()].shortName() + ", " +
- Provider::emoji[index.row()].unicodeName();
- case CompletionModel::SearchRole2:
- case static_cast<int>(EmojiModel::Roles::UnicodeName):
- return Provider::emoji[index.row()].unicodeName();
- case CompletionModel::SearchRole:
- case static_cast<int>(EmojiModel::Roles::ShortName):
- return Provider::emoji[index.row()].shortName();
- case static_cast<int>(EmojiModel::Roles::Category):
- return QVariant::fromValue(Provider::emoji[index.row()].category);
-
- case static_cast<int>(EmojiModel::Roles::Emoji):
- return QVariant::fromValue(Provider::emoji[index.row()]);
- }
- }
-
- return {};
-}
diff --git a/src/emoji/EmojiModel.h b/src/emoji/EmojiModel.h
deleted file mode 100644
index cb63cbf7..00000000
--- a/src/emoji/EmojiModel.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// SPDX-FileCopyrightText: Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#pragma once
-
-#include <QAbstractListModel>
-#include <QSet>
-#include <QSortFilterProxyModel>
-#include <QVector>
-
-#include "Provider.h"
-
-namespace emoji {
-
-/*
- * Provides access to the emojis in Provider.h to QML
- */
-class EmojiModel : public QAbstractListModel
-{
- Q_OBJECT
-public:
- enum Roles
- {
- Unicode = Qt::UserRole, // unicode of emoji
- Category, // category of emoji
- ShortName, // shortext of the emoji
- UnicodeName, // true unicode name of the emoji
- Emoji, // Contains everything from the Emoji
- };
-
- using QAbstractListModel::QAbstractListModel;
-
- Q_INVOKABLE int categoryToIndex(int category);
-
- QHash<int, QByteArray> roleNames() const override;
- int rowCount(const QModelIndex &parent = QModelIndex()) const override;
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
-};
-}
diff --git a/src/emoji/Provider.h b/src/emoji/Provider.h
index f8c74b08..5d8000a4 100644
--- a/src/emoji/Provider.h
+++ b/src/emoji/Provider.h
@@ -91,5 +91,7 @@ public:
static const std::array<Emoji, 3681> emoji;
};
+QString
+categoryToName(emoji::Emoji::Category cat);
} // namespace emoji
Q_DECLARE_METATYPE(emoji::Emoji)
diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index 4b6a791f..e062dde2 100644
--- a/src/timeline/TimelineViewManager.cpp
+++ b/src/timeline/TimelineViewManager.cpp
@@ -27,7 +27,6 @@
#include "UserSettingsPage.h"
#include "UsersModel.h"
#include "Utils.h"
-#include "emoji/EmojiModel.h"
#include "encryption/VerificationManager.h"
#include "voip/CallManager.h"
#include "voip/WebRTCSession.h"
@@ -454,15 +453,10 @@ TimelineViewManager::completerFor(const QString &completerName, const QString &r
userModel->setParent(proxy);
return proxy;
} else if (completerName == QLatin1String("emoji")) {
- auto emojiModel = new emoji::EmojiModel();
+ auto emojiModel = new CombinedImagePackModel(roomId.toStdString());
auto proxy = new CompletionProxyModel(emojiModel);
emojiModel->setParent(proxy);
return proxy;
- } else if (completerName == QLatin1String("allemoji")) {
- auto emojiModel = new emoji::EmojiModel();
- auto proxy = new CompletionProxyModel(emojiModel, 1, static_cast<size_t>(-1) / 4);
- emojiModel->setParent(proxy);
- return proxy;
} else if (completerName == QLatin1String("room")) {
auto roomModel = new RoomsModel(false);
auto proxy = new CompletionProxyModel(roomModel, 4);
@@ -473,22 +467,12 @@ TimelineViewManager::completerFor(const QString &completerName, const QString &r
auto proxy = new CompletionProxyModel(roomModel);
roomModel->setParent(proxy);
return proxy;
- } else if (completerName == QLatin1String("stickers")) {
- auto stickerModel = new CombinedImagePackModel(roomId.toStdString(), true);
- auto proxy = new CompletionProxyModel(stickerModel, 1, static_cast<size_t>(-1) / 4);
- stickerModel->setParent(proxy);
- return proxy;
} else if (completerName == QLatin1String("emojigrid")) {
auto stickerModel = new GridImagePackModel(roomId.toStdString(), false);
return stickerModel;
} else if (completerName == QLatin1String("stickergrid")) {
auto stickerModel = new GridImagePackModel(roomId.toStdString(), true);
return stickerModel;
- } else if (completerName == QLatin1String("customEmoji")) {
- auto stickerModel = new CombinedImagePackModel(roomId.toStdString(), false);
- auto proxy = new CompletionProxyModel(stickerModel);
- stickerModel->setParent(proxy);
- return proxy;
} else if (completerName == QLatin1String("command")) {
auto commandCompleter = new CommandCompleter();
auto proxy = new CompletionProxyModel(commandCompleter);