mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 19:08:58 +03:00
Use one CompletionProxy for everything including EmojiPicker
This commit is contained in:
parent
1b0af04cc8
commit
c2e625756c
9 changed files with 144 additions and 258 deletions
|
@ -36,15 +36,7 @@ Page {
|
||||||
id: emojiPopup
|
id: emojiPopup
|
||||||
|
|
||||||
colors: palette
|
colors: palette
|
||||||
|
model: TimelineManager.completerFor("allemoji", "")
|
||||||
model: EmojiProxyModel {
|
|
||||||
category: Emoji.Category.People
|
|
||||||
|
|
||||||
sourceModel: EmojiModel {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
|
|
|
@ -49,6 +49,54 @@ Menu {
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.topMargin: 2
|
anchors.topMargin: 2
|
||||||
|
|
||||||
|
// Search field
|
||||||
|
TextField {
|
||||||
|
id: emojiSearch
|
||||||
|
|
||||||
|
//width: gridView.width - 6
|
||||||
|
Layout.topMargin: 3
|
||||||
|
Layout.preferredWidth: 7 * 52 + 20 - 6
|
||||||
|
placeholderText: qsTr("Search")
|
||||||
|
selectByMouse: true
|
||||||
|
rightPadding: clearSearch.width
|
||||||
|
onTextChanged: searchTimer.restart()
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (visible)
|
||||||
|
forceActiveFocus();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: searchTimer
|
||||||
|
|
||||||
|
interval: 350 // tweak as needed?
|
||||||
|
onTriggered: {
|
||||||
|
emojiPopup.model.searchString = emojiSearch.text;
|
||||||
|
emojiPopup.model.category = Emoji.Category.Search;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolButton {
|
||||||
|
id: clearSearch
|
||||||
|
|
||||||
|
visible: emojiSearch.text !== ''
|
||||||
|
icon.source: "image://colorimage/:/icons/icons/ui/round-remove-button.png?" + (clearSearch.hovered ? colors.highlight : colors.buttonText)
|
||||||
|
focusPolicy: Qt.NoFocus
|
||||||
|
onClicked: emojiSearch.clear()
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
// clear the default hover effects.
|
||||||
|
|
||||||
|
background: Item {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// emoji grid
|
// emoji grid
|
||||||
GridView {
|
GridView {
|
||||||
id: gridView
|
id: gridView
|
||||||
|
@ -104,54 +152,6 @@ Menu {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search field
|
|
||||||
header: TextField {
|
|
||||||
id: emojiSearch
|
|
||||||
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: emojiScroll.width + 4
|
|
||||||
placeholderText: qsTr("Search")
|
|
||||||
selectByMouse: true
|
|
||||||
rightPadding: clearSearch.width
|
|
||||||
onTextChanged: searchTimer.restart()
|
|
||||||
onVisibleChanged: {
|
|
||||||
if (visible)
|
|
||||||
forceActiveFocus();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: searchTimer
|
|
||||||
|
|
||||||
interval: 350 // tweak as needed?
|
|
||||||
onTriggered: {
|
|
||||||
emojiPopup.model.filter = emojiSearch.text;
|
|
||||||
emojiPopup.model.category = Emoji.Category.Search;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ToolButton {
|
|
||||||
id: clearSearch
|
|
||||||
|
|
||||||
visible: emojiSearch.text !== ''
|
|
||||||
icon.source: "image://colorimage/:/icons/icons/ui/round-remove-button.png?" + (clearSearch.hovered ? colors.highlight : colors.buttonText)
|
|
||||||
focusPolicy: Qt.NoFocus
|
|
||||||
onClicked: emojiSearch.clear()
|
|
||||||
|
|
||||||
anchors {
|
|
||||||
verticalCenter: parent.verticalCenter
|
|
||||||
right: parent.right
|
|
||||||
}
|
|
||||||
// clear the default hover effects.
|
|
||||||
|
|
||||||
background: Item {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ScrollBar.vertical: ScrollBar {
|
ScrollBar.vertical: ScrollBar {
|
||||||
id: emojiScroll
|
id: emojiScroll
|
||||||
}
|
}
|
||||||
|
@ -160,6 +160,7 @@ Menu {
|
||||||
|
|
||||||
// Separator
|
// Separator
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
visible: emojiSearch.text === ''
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: 1
|
Layout.preferredHeight: 1
|
||||||
color: emojiPopup.colors.alternateBase
|
color: emojiPopup.colors.alternateBase
|
||||||
|
@ -167,6 +168,7 @@ Menu {
|
||||||
|
|
||||||
// Category picker row
|
// Category picker row
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
visible: emojiSearch.text === ''
|
||||||
Layout.bottomMargin: 0
|
Layout.bottomMargin: 0
|
||||||
Layout.preferredHeight: 42
|
Layout.preferredHeight: 42
|
||||||
implicitHeight: 42
|
implicitHeight: 42
|
||||||
|
@ -245,7 +247,8 @@ Menu {
|
||||||
}
|
}
|
||||||
ToolTip.visible: hovered
|
ToolTip.visible: hovered
|
||||||
onClicked: {
|
onClicked: {
|
||||||
emojiPopup.model.category = model.category;
|
//emojiPopup.model.category = model.category;
|
||||||
|
gridView.positionViewAtIndex(emojiPopup.model.sourceModel.categoryToIndex(model.category), GridView.Beginning);
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
@ -276,56 +279,6 @@ Menu {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Separator
|
|
||||||
Rectangle {
|
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.preferredWidth: 1
|
|
||||||
implicitWidth: 1
|
|
||||||
height: parent.height
|
|
||||||
color: emojiPopup.colors.alternateBase
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search Button is special
|
|
||||||
AbstractButton {
|
|
||||||
id: searchBtn
|
|
||||||
|
|
||||||
hoverEnabled: true
|
|
||||||
Layout.alignment: Qt.AlignRight
|
|
||||||
Layout.bottomMargin: 0
|
|
||||||
ToolTip.text: qsTr("Search")
|
|
||||||
ToolTip.visible: hovered
|
|
||||||
onClicked: {
|
|
||||||
// clear any filters
|
|
||||||
emojiPopup.model.category = Emoji.Category.Search;
|
|
||||||
gridView.positionViewAtBeginning();
|
|
||||||
emojiSearch.forceActiveFocus();
|
|
||||||
}
|
|
||||||
Layout.preferredWidth: 36
|
|
||||||
Layout.preferredHeight: 36
|
|
||||||
implicitWidth: 36
|
|
||||||
implicitHeight: 36
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: mouseArea
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
onPressed: mouse.accepted = false
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
}
|
|
||||||
|
|
||||||
contentItem: Image {
|
|
||||||
anchors.right: parent.right
|
|
||||||
horizontalAlignment: Image.AlignHCenter
|
|
||||||
verticalAlignment: Image.AlignVCenter
|
|
||||||
sourceSize.width: 32
|
|
||||||
sourceSize.height: 32
|
|
||||||
fillMode: Image.Pad
|
|
||||||
smooth: true
|
|
||||||
source: "image://colorimage/:/icons/icons/ui/search.png?" + (parent.hovered ? colors.highlight : colors.buttonText)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -405,6 +405,50 @@ private:
|
||||||
event);
|
event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::optional<mtx::events::StateEvent<T>> getStateEvent(lmdb::txn txn,
|
||||||
|
const std::string &room_id,
|
||||||
|
std::string_view state_key = "")
|
||||||
|
{
|
||||||
|
constexpr auto type = mtx::events::state_content_to_type<T>;
|
||||||
|
static_assert(type != mtx::events::EventType::Unsupported,
|
||||||
|
"Not a supported type in state events.");
|
||||||
|
|
||||||
|
if (room_id.empty())
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
std::string_view value;
|
||||||
|
if (state_key.empty()) {
|
||||||
|
auto db = getStatesDb(txn, room_id);
|
||||||
|
if (!db.get(txn, to_string(type), value)) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto db = getStatesKeyDb(txn, room_id);
|
||||||
|
std::string d = json::object({{"key", state_key}}).dump();
|
||||||
|
std::string_view data = d;
|
||||||
|
|
||||||
|
auto cursor = lmdb::cursor::open(txn, db);
|
||||||
|
if (!cursor.get(state_key, data, MDB_GET_BOTH))
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto eventsDb = getEventsDb(txn, room_id);
|
||||||
|
if (!eventsDb.get(
|
||||||
|
txn, json::parse(data)["id"].get<std::string>(), value))
|
||||||
|
return std::nullopt;
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return json::parse(value).get<mtx::events::StateEvent<T>>();
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void saveInvites(lmdb::txn &txn,
|
void saveInvites(lmdb::txn &txn,
|
||||||
const std::map<std::string, mtx::responses::InvitedRoom> &rooms);
|
const std::map<std::string, mtx::responses::InvitedRoom> &rooms);
|
||||||
|
|
||||||
|
|
|
@ -12,16 +12,18 @@
|
||||||
|
|
||||||
CompletionProxyModel::CompletionProxyModel(QAbstractItemModel *model,
|
CompletionProxyModel::CompletionProxyModel(QAbstractItemModel *model,
|
||||||
int max_mistakes,
|
int max_mistakes,
|
||||||
|
size_t max_completions,
|
||||||
QObject *parent)
|
QObject *parent)
|
||||||
: QAbstractProxyModel(parent)
|
: QAbstractProxyModel(parent)
|
||||||
, maxMistakes_(max_mistakes)
|
, maxMistakes_(max_mistakes)
|
||||||
|
, max_completions_(max_completions)
|
||||||
{
|
{
|
||||||
setSourceModel(model);
|
setSourceModel(model);
|
||||||
QRegularExpression splitPoints("\\s+|-");
|
QRegularExpression splitPoints("\\s+|-");
|
||||||
|
|
||||||
// insert all the full texts
|
// insert all the full texts
|
||||||
for (int i = 0; i < sourceModel()->rowCount(); i++) {
|
for (int i = 0; i < sourceModel()->rowCount(); i++) {
|
||||||
if (i < 7)
|
if (static_cast<size_t>(i) < max_completions_)
|
||||||
mapping.push_back(i);
|
mapping.push_back(i);
|
||||||
|
|
||||||
auto string1 = sourceModel()
|
auto string1 = sourceModel()
|
||||||
|
@ -82,14 +84,9 @@ CompletionProxyModel::invalidate()
|
||||||
{
|
{
|
||||||
auto key = searchString_.toUcs4();
|
auto key = searchString_.toUcs4();
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
mapping = trie_.search(key, 7, maxMistakes_);
|
if (!key.empty()) // return default model data, if no search string
|
||||||
|
mapping = trie_.search(key, max_completions_, maxMistakes_);
|
||||||
endResetModel();
|
endResetModel();
|
||||||
|
|
||||||
std::string temp;
|
|
||||||
for (auto v : mapping) {
|
|
||||||
temp += std::to_string(v) + ", ";
|
|
||||||
}
|
|
||||||
nhlog::ui()->debug("mapping: {}", temp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash<int, QByteArray>
|
QHash<int, QByteArray>
|
||||||
|
@ -101,12 +98,22 @@ CompletionProxyModel::roleNames() const
|
||||||
int
|
int
|
||||||
CompletionProxyModel::rowCount(const QModelIndex &) const
|
CompletionProxyModel::rowCount(const QModelIndex &) const
|
||||||
{
|
{
|
||||||
|
if (searchString_.isEmpty())
|
||||||
|
return std::min(static_cast<int>(std::min<size_t>(max_completions_,
|
||||||
|
std::numeric_limits<int>::max())),
|
||||||
|
sourceModel()->rowCount());
|
||||||
|
else
|
||||||
return (int)mapping.size();
|
return (int)mapping.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex
|
QModelIndex
|
||||||
CompletionProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
|
CompletionProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
|
||||||
{
|
{
|
||||||
|
// return default model data, if no search string
|
||||||
|
if (searchString_.isEmpty()) {
|
||||||
|
return index(sourceIndex.row(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < (int)mapping.size(); i++) {
|
for (int i = 0; i < (int)mapping.size(); i++) {
|
||||||
if (mapping[i] == sourceIndex.row()) {
|
if (mapping[i] == sourceIndex.row()) {
|
||||||
return index(i, 0);
|
return index(i, 0);
|
||||||
|
@ -119,6 +126,12 @@ QModelIndex
|
||||||
CompletionProxyModel::mapToSource(const QModelIndex &proxyIndex) const
|
CompletionProxyModel::mapToSource(const QModelIndex &proxyIndex) const
|
||||||
{
|
{
|
||||||
auto row = proxyIndex.row();
|
auto row = proxyIndex.row();
|
||||||
|
|
||||||
|
// return default model data, if no search string
|
||||||
|
if (searchString_.isEmpty()) {
|
||||||
|
return index(row, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (row < 0 || row >= (int)mapping.size())
|
if (row < 0 || row >= (int)mapping.size())
|
||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
|
|
||||||
|
|
|
@ -154,6 +154,7 @@ class CompletionProxyModel : public QAbstractProxyModel
|
||||||
public:
|
public:
|
||||||
CompletionProxyModel(QAbstractItemModel *model,
|
CompletionProxyModel(QAbstractItemModel *model,
|
||||||
int max_mistakes = 2,
|
int max_mistakes = 2,
|
||||||
|
size_t max_completions = 7,
|
||||||
QObject *parent = nullptr);
|
QObject *parent = nullptr);
|
||||||
|
|
||||||
void invalidate();
|
void invalidate();
|
||||||
|
@ -184,4 +185,5 @@ private:
|
||||||
trie<uint, int> trie_;
|
trie<uint, int> trie_;
|
||||||
std::vector<int> mapping;
|
std::vector<int> mapping;
|
||||||
int maxMistakes_;
|
int maxMistakes_;
|
||||||
|
size_t max_completions_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,20 @@
|
||||||
|
|
||||||
using namespace emoji;
|
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>
|
QHash<int, QByteArray>
|
||||||
EmojiModel::roleNames() const
|
EmojiModel::roleNames() const
|
||||||
{
|
{
|
||||||
|
@ -60,59 +74,3 @@ EmojiModel::data(const QModelIndex &index, int role) const
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
EmojiProxyModel::EmojiProxyModel(QObject *parent)
|
|
||||||
: QSortFilterProxyModel(parent)
|
|
||||||
{}
|
|
||||||
|
|
||||||
EmojiProxyModel::~EmojiProxyModel() {}
|
|
||||||
|
|
||||||
Emoji::Category
|
|
||||||
EmojiProxyModel::category() const
|
|
||||||
{
|
|
||||||
return category_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
EmojiProxyModel::setCategory(Emoji::Category cat)
|
|
||||||
{
|
|
||||||
if (category_ == cat) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
category_ = cat;
|
|
||||||
emit categoryChanged();
|
|
||||||
|
|
||||||
invalidateFilter();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString
|
|
||||||
EmojiProxyModel::filter() const
|
|
||||||
{
|
|
||||||
return filterRegExp().pattern();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
EmojiProxyModel::setFilter(const QString &filter)
|
|
||||||
{
|
|
||||||
if (filterRegExp().pattern() == filter) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setFilterWildcard(filter);
|
|
||||||
emit filterChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
EmojiProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
|
||||||
{
|
|
||||||
const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
|
|
||||||
const Emoji emoji = index.data(static_cast<int>(EmojiModel::Roles::Emoji)).value<Emoji>();
|
|
||||||
|
|
||||||
// TODO: Add favorites / recently used
|
|
||||||
if (category_ != Emoji::Category::Search) {
|
|
||||||
return emoji.category == category_;
|
|
||||||
}
|
|
||||||
|
|
||||||
return filterRegExp().isEmpty() ? true : filterRegExp().indexIn(emoji.shortName) != -1;
|
|
||||||
}
|
|
||||||
|
|
|
@ -30,38 +30,10 @@ public:
|
||||||
|
|
||||||
using QAbstractListModel::QAbstractListModel;
|
using QAbstractListModel::QAbstractListModel;
|
||||||
|
|
||||||
|
Q_INVOKABLE int categoryToIndex(int category);
|
||||||
|
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EmojiProxyModel : public QSortFilterProxyModel
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(
|
|
||||||
emoji::Emoji::Category category READ category WRITE setCategory NOTIFY categoryChanged)
|
|
||||||
Q_PROPERTY(QString filter READ filter WRITE setFilter NOTIFY filterChanged)
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit EmojiProxyModel(QObject *parent = nullptr);
|
|
||||||
~EmojiProxyModel() override;
|
|
||||||
|
|
||||||
Emoji::Category category() const;
|
|
||||||
void setCategory(Emoji::Category cat);
|
|
||||||
|
|
||||||
QString filter() const;
|
|
||||||
void setFilter(const QString &filter);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void categoryChanged();
|
|
||||||
void filterChanged();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Emoji::Category category_ = Emoji::Category::Search;
|
|
||||||
emoji::Provider emoji_provider_;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "EmojiModel.h"
|
|
||||||
|
|
||||||
#include <CompletionModelRoles.h>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QEvent>
|
|
||||||
#include <QSortFilterProxyModel>
|
|
||||||
|
|
||||||
namespace emoji {
|
|
||||||
|
|
||||||
// Map emoji data to searchable data
|
|
||||||
class EmojiSearchModel : public QSortFilterProxyModel
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
EmojiSearchModel(QObject *parent = nullptr)
|
|
||||||
: QSortFilterProxyModel(parent)
|
|
||||||
{
|
|
||||||
setSourceModel(new EmojiModel(this));
|
|
||||||
}
|
|
||||||
QVariant data(const QModelIndex &index, int role = Qt::UserRole + 1) const override
|
|
||||||
{
|
|
||||||
switch (role) {
|
|
||||||
case Qt::DisplayRole: {
|
|
||||||
auto emoji = QSortFilterProxyModel::data(index, role).toString();
|
|
||||||
return emoji + " :" +
|
|
||||||
toShortcode(data(index, EmojiModel::ShortName).toString()) + ":";
|
|
||||||
}
|
|
||||||
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:
|
|
||||||
QString toShortcode(QString shortname) const
|
|
||||||
{
|
|
||||||
return shortname.replace(" ", "-").replace(":", "-").replace("--", "-").toLower();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -172,9 +172,6 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par
|
||||||
qRegisterMetaType<std::vector<DeviceInfo>>();
|
qRegisterMetaType<std::vector<DeviceInfo>>();
|
||||||
|
|
||||||
qmlRegisterType<emoji::EmojiModel>("im.nheko.EmojiModel", 1, 0, "EmojiModel");
|
qmlRegisterType<emoji::EmojiModel>("im.nheko.EmojiModel", 1, 0, "EmojiModel");
|
||||||
qmlRegisterType<emoji::EmojiProxyModel>("im.nheko.EmojiModel", 1, 0, "EmojiProxyModel");
|
|
||||||
qmlRegisterUncreatableType<QAbstractItemModel>(
|
|
||||||
"im.nheko.EmojiModel", 1, 0, "QAbstractItemModel", "Used by proxy models");
|
|
||||||
qmlRegisterUncreatableType<emoji::Emoji>(
|
qmlRegisterUncreatableType<emoji::Emoji>(
|
||||||
"im.nheko.EmojiModel", 1, 0, "Emoji", "Used by emoji models");
|
"im.nheko.EmojiModel", 1, 0, "Emoji", "Used by emoji models");
|
||||||
qmlRegisterUncreatableMetaObject(emoji::staticMetaObject,
|
qmlRegisterUncreatableMetaObject(emoji::staticMetaObject,
|
||||||
|
@ -595,6 +592,11 @@ TimelineViewManager::completerFor(QString completerName, QString roomId)
|
||||||
auto proxy = new CompletionProxyModel(emojiModel);
|
auto proxy = new CompletionProxyModel(emojiModel);
|
||||||
emojiModel->setParent(proxy);
|
emojiModel->setParent(proxy);
|
||||||
return proxy;
|
return proxy;
|
||||||
|
} else if (completerName == "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 == "room") {
|
} else if (completerName == "room") {
|
||||||
auto roomModel = new RoomsModel(false);
|
auto roomModel = new RoomsModel(false);
|
||||||
auto proxy = new CompletionProxyModel(roomModel, 4);
|
auto proxy = new CompletionProxyModel(roomModel, 4);
|
||||||
|
|
Loading…
Reference in a new issue