mirror of
https://invent.kde.org/plasma/plasma-desktop.git
synced 2026-11-03 14:49:44 -09:00
You can now zoom with Ctrl+scroll, keyboard shortcuts, and toolbar buttons. This enlarges or shrinks the cells of the emoji grid, clamped between 1.5 and 8 grid units. Plain scrolling is unaffected and still scrolls the list. The glyph font size is derived from the cell height instead of a fixed point size, so it scales with the zoom (this also lets the inert minimumPointSize be dropped). Size changes are coalesced on a short throttle so a fast wheel spin triggers at most one relayout per frame instead of one per event. The skin-tone variant popup tracks the same size.
192 lines
4.7 KiB
C++
192 lines
4.7 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
|
|
|
|
SPDX-License-Identifier: LGPL-2.0-or-later
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <QAbstractItemModel>
|
|
#include <QSortFilterProxyModel>
|
|
|
|
#include <qqmlregistration.h>
|
|
|
|
#include "emojidict.h"
|
|
#include "emojiersettings.h"
|
|
|
|
class SkinTone : public QObject
|
|
{
|
|
Q_OBJECT
|
|
QML_ELEMENT
|
|
public:
|
|
enum _SkinTone {
|
|
Neutral = Tone::Neutral,
|
|
Light = Tone::Light,
|
|
MediumLight = Tone::MediumLight,
|
|
Medium = Tone::Medium,
|
|
MediumDark = Tone::MediumDark,
|
|
Dark = Tone::Dark
|
|
};
|
|
Q_ENUM(_SkinTone)
|
|
};
|
|
|
|
class AbstractEmojiModel : public QAbstractListModel
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
enum EmojiRole {
|
|
CategoryRole = Qt::UserRole + 1,
|
|
AnnotationsRole,
|
|
FallbackDescriptionRole,
|
|
twoToneIndexRole,
|
|
};
|
|
|
|
int rowCount(const QModelIndex &parent = {}) const override;
|
|
|
|
QVariant data(const QModelIndex &index, int role) const override;
|
|
|
|
protected:
|
|
QHash<int, QByteArray> roleNames() const override
|
|
{
|
|
return {{Qt::DisplayRole, "display"}, {Qt::ToolTipRole, "toolTip"}, {twoToneIndexRole, "twoToneIndex"}};
|
|
}
|
|
|
|
QList<Emoji> m_emoji;
|
|
QList<Emoji> m_tonedEmojis;
|
|
EmojierSettings m_settings;
|
|
};
|
|
|
|
class EmojiModel;
|
|
|
|
class TwoToneEmojiModel : public QAbstractListModel
|
|
{
|
|
Q_OBJECT
|
|
Q_PROPERTY(int twoToneIndex READ twoToneIndex WRITE setTwoToneIndex)
|
|
public:
|
|
TwoToneEmojiModel(QList<Emoji> twoToneEmojis, QList<Emoji> &tonedEmojis, EmojierSettings &settings)
|
|
: m_twoToneEmojis(twoToneEmojis)
|
|
, m_tonedEmojis(tonedEmojis)
|
|
, m_settings(settings)
|
|
{
|
|
}
|
|
|
|
int rowCount(const QModelIndex &parent = {}) const override;
|
|
|
|
QVariant data(const QModelIndex &index, int role) const override;
|
|
|
|
void twoToneDataChanged();
|
|
|
|
int twoToneIndex();
|
|
|
|
void setTwoToneIndex(int twoToneIndex);
|
|
|
|
private:
|
|
QList<Emoji> m_twoToneEmojis;
|
|
QList<Emoji> &m_tonedEmojis;
|
|
int m_twoToneIndex = 0;
|
|
|
|
EmojierSettings &m_settings;
|
|
|
|
QMap<int, QList<int>> twoToneSortFilterMap = {{Tone::Light, {0, 1, 2, 3, 4, 8, 12, 16}},
|
|
{Tone::MediumLight, {4, 5, 6, 7, 0, 9, 13, 17}},
|
|
{Tone::Medium, {8, 9, 10, 11, 1, 5, 14, 18}},
|
|
{Tone::MediumDark, {12, 13, 14, 15, 2, 6, 10, 19}},
|
|
{Tone::Dark, {16, 17, 18, 19, 3, 7, 11, 15}}};
|
|
};
|
|
|
|
class EmojiModel : public AbstractEmojiModel
|
|
{
|
|
Q_OBJECT
|
|
QML_ELEMENT
|
|
Q_PROPERTY(QStringList categories MEMBER m_categories CONSTANT)
|
|
Q_PROPERTY(int skinTone READ skinTone WRITE setSkinTone NOTIFY skinToneChanged)
|
|
Q_PROPERTY(qreal emojiZoom READ emojiZoom WRITE setEmojiZoom NOTIFY emojiZoomChanged)
|
|
Q_PROPERTY(QAbstractItemModel *twoToneEmojiModel MEMBER m_TwoToneEmojiModel CONSTANT)
|
|
public:
|
|
enum EmojiRole {
|
|
CategoryRole = Qt::UserRole + 1,
|
|
};
|
|
|
|
EmojiModel();
|
|
~EmojiModel();
|
|
|
|
Q_SCRIPTABLE QString findFirstEmojiForCategory(const QString &category);
|
|
|
|
int skinTone() const;
|
|
|
|
void setSkinTone(int skinTone);
|
|
|
|
Q_SIGNAL void skinToneChanged();
|
|
|
|
qreal emojiZoom() const;
|
|
|
|
void setEmojiZoom(qreal emojiZoom);
|
|
|
|
Q_SIGNAL void emojiZoomChanged();
|
|
|
|
private:
|
|
QStringList m_categories;
|
|
TwoToneEmojiModel *m_TwoToneEmojiModel;
|
|
};
|
|
|
|
class RecentEmojiModel : public AbstractEmojiModel
|
|
{
|
|
Q_OBJECT
|
|
QML_ELEMENT
|
|
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
|
public:
|
|
RecentEmojiModel();
|
|
|
|
Q_SCRIPTABLE void includeRecent(const QString &emoji, const QString &emojiDescription);
|
|
|
|
Q_INVOKABLE void clearHistory();
|
|
|
|
Q_SIGNAL void countChanged();
|
|
|
|
private:
|
|
void refresh();
|
|
};
|
|
|
|
class CategoryModelFilter : public QSortFilterProxyModel
|
|
{
|
|
Q_OBJECT
|
|
QML_ELEMENT
|
|
Q_PROPERTY(QString category READ category WRITE setCategory NOTIFY categoryChanged)
|
|
public:
|
|
QString category() const;
|
|
|
|
void setCategory(const QString &category);
|
|
|
|
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
|
|
|
|
Q_SIGNAL void categoryChanged();
|
|
|
|
private:
|
|
QString m_category;
|
|
};
|
|
|
|
class SearchModelFilter : public QSortFilterProxyModel
|
|
{
|
|
Q_OBJECT
|
|
QML_ELEMENT
|
|
Q_PROPERTY(QString search READ search WRITE setSearch)
|
|
public:
|
|
QString search() const;
|
|
|
|
void setSearch(const QString &search);
|
|
|
|
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
|
|
|
|
private:
|
|
QString m_search;
|
|
};
|
|
|
|
class CopyHelperPrivate : public QObject
|
|
{
|
|
Q_OBJECT
|
|
QML_ELEMENT
|
|
QML_NAMED_ELEMENT(CopyHelper)
|
|
QML_SINGLETON
|
|
public:
|
|
Q_INVOKABLE static void copyTextToClipboard(const QString &text);
|
|
};
|