├── .gitignore
├── EmojiView.qml
├── LICENSE
├── README.md
├── assets
├── sheet_apple_32.png
├── sheet_emojione_32.png
├── sheet_google_32.png
└── sheet_twitter_32.png
├── com_cutehacks_emooj.pri
├── com_cutehacks_emooj.qrc
├── com_cutehacks_emooj_apple.qrc
├── com_cutehacks_emooj_emojione.qrc
├── com_cutehacks_emooj_google.qrc
├── com_cutehacks_emooj_twitter.qrc
├── emoji-data.cpp
├── emoji-data.h
├── emojidatamodel.cpp
├── emojidatamodel.h
├── emojiimageprovider.cpp
├── emojiimageprovider.h
├── emooj.h
├── examples
└── completion
│ ├── completion.pro
│ ├── main.cpp
│ ├── main.qml
│ └── qml.qrc
├── qmldir
├── qpm.json
├── tools
└── gendata
│ ├── emoji_pretty.json
│ ├── gendata.pro
│ └── main.cpp
├── unicodeutils.cpp
├── unicodeutils.h
├── utilswrapper.cpp
└── utilswrapper.h
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pro.user
2 |
--------------------------------------------------------------------------------
/EmojiView.qml:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Cutehacks AS. All rights reserved.
2 | // License can be found in the LICENSE file.
3 | import QtQuick 2.0
4 |
5 | import com.cutehacks.emooj 1.0
6 |
7 | Rectangle {
8 | property int cellWidth: 32
9 | property int columnCount: 10
10 | property int rowCount: 10
11 | width: cellWidth * columnCount + grid.anchors.margins * 2
12 | height: cellWidth * rowCount + grid.anchors.margins * 2
13 | radius: 5
14 | border.color: "black"
15 |
16 | GridView {
17 | id: grid
18 | anchors.fill: parent
19 | clip: true
20 | cellWidth: 32
21 | cellHeight: 32
22 | anchors.margins: 10
23 |
24 | model: EmojiDataModel {
25 | id: emojiModel
26 | }
27 |
28 | delegate: Rectangle {
29 | width: 32
30 | height: 32
31 |
32 | // Text {
33 | // anchors.fill: parent
34 | // text: unicode
35 | // }
36 | Image {
37 | anchors.fill: parent
38 | source: decoration
39 | }
40 |
41 | MouseArea {
42 | anchors.fill: parent
43 | onClicked: {
44 | emojiModel.emitIMEvent(index);
45 | }
46 | }
47 | }
48 | }
49 |
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Jason Barron
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Emooj
2 |
3 | An Emoji helper module for Qt and QML.
4 |
5 | This package uses data from the https://github.com/iamcal/emoji-data project.
6 |
7 | TODO: Write docs :)
--------------------------------------------------------------------------------
/assets/sheet_apple_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cutehacks/Emooj/531fbd453c8e873c7041f1f227944bd5ccbdada3/assets/sheet_apple_32.png
--------------------------------------------------------------------------------
/assets/sheet_emojione_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cutehacks/Emooj/531fbd453c8e873c7041f1f227944bd5ccbdada3/assets/sheet_emojione_32.png
--------------------------------------------------------------------------------
/assets/sheet_google_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cutehacks/Emooj/531fbd453c8e873c7041f1f227944bd5ccbdada3/assets/sheet_google_32.png
--------------------------------------------------------------------------------
/assets/sheet_twitter_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cutehacks/Emooj/531fbd453c8e873c7041f1f227944bd5ccbdada3/assets/sheet_twitter_32.png
--------------------------------------------------------------------------------
/com_cutehacks_emooj.pri:
--------------------------------------------------------------------------------
1 |
2 | RESOURCES += \
3 | $$PWD/com_cutehacks_emooj.qrc
4 |
5 | isEmpty(EMOOJ_SHEETS) {
6 | EMOOJ_SHEETS = twitter
7 | ios|macx: EMOOJ_SHEETS += apple
8 | android: EMOOJ_SHEETS += google
9 | }
10 |
11 | contains(EMOOJ_SHEETS, apple) {
12 | RESOURCES += $$PWD/com_cutehacks_emooj_apple.qrc
13 | DEFINES += EMOOJ_APPLE
14 | }
15 | contains(EMOOJ_SHEETS, google) {
16 | RESOURCES += $$PWD/com_cutehacks_emooj_google.qrc
17 | DEFINES += EMOOJ_GOOGLE
18 | }
19 | contains(EMOOJ_SHEETS, emojione) {
20 | RESOURCES += $$PWD/com_cutehacks_emooj_emojione.qrc
21 | DEFINES += EMOOJ_EMOJIONE
22 | }
23 | contains(EMOOJ_SHEETS, twitter) {
24 | RESOURCES += $$PWD/com_cutehacks_emooj_twitter.qrc
25 | DEFINES += EMOOJ_TWITTER
26 | }
27 |
28 | HEADERS += \
29 | $$PWD/unicodeutils.h \
30 | $$PWD/emooj.h \
31 | $$PWD/emojidatamodel.h \
32 | $$PWD/utilswrapper.h \
33 | $$PWD/emoji-data.h \
34 | $$PWD/emojiimageprovider.h
35 |
36 | SOURCES += \
37 | $$PWD/unicodeutils.cpp \
38 | $$PWD/emojidatamodel.cpp \
39 | $$PWD/utilswrapper.cpp \
40 | $$PWD/emoji-data.cpp \
41 | $$PWD/emojiimageprovider.cpp
42 |
43 | INCLUDEPATH += $$PWD
44 |
--------------------------------------------------------------------------------
/com_cutehacks_emooj.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | qmldir
4 | EmojiView.qml
5 |
6 |
7 |
--------------------------------------------------------------------------------
/com_cutehacks_emooj_apple.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | assets/sheet_apple_32.png
4 |
5 |
6 |
--------------------------------------------------------------------------------
/com_cutehacks_emooj_emojione.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | assets/sheet_emojione_32.png
4 |
5 |
6 |
--------------------------------------------------------------------------------
/com_cutehacks_emooj_google.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | assets/sheet_google_32.png
4 |
5 |
6 |
--------------------------------------------------------------------------------
/com_cutehacks_emooj_twitter.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | assets/sheet_twitter_32.png
4 |
5 |
6 |
--------------------------------------------------------------------------------
/emoji-data.h:
--------------------------------------------------------------------------------
1 | #ifndef EMOJIDATA_H
2 | // Copyright 2016 Cutehacks AS. All rights reserved.
3 | // License can be found in the LICENSE file.
4 | #define EMOJIDATA_H
5 |
6 | #include
7 | #include
8 |
9 | namespace com { namespace cutehacks { namespace emooj {
10 |
11 | struct Emoji {
12 | QString unicode;
13 | QString name;
14 | QString shortName;
15 | QString category;
16 | int sheetX;
17 | int sheetY;
18 | };
19 |
20 | extern QHash emoticons;
21 | extern QVector emojis;
22 | extern QHash emojiData;
23 |
24 | } } }
25 |
26 | #endif // EMOJIDATA_H
27 |
28 |
--------------------------------------------------------------------------------
/emojidatamodel.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Cutehacks AS. All rights reserved.
2 | // License can be found in the LICENSE file.
3 | #include
4 | #include
5 |
6 | #include "emojidatamodel.h"
7 | #include "emoji-data.h"
8 | #include "emojiimageprovider.h"
9 |
10 | namespace com { namespace cutehacks { namespace emooj {
11 |
12 | static QHash roles {
13 | {Qt::DisplayRole, "display"},
14 | {Qt::DecorationRole, "decoration"},
15 | {EmojiDataModel::UnicodeRole, "unicode"},
16 | {EmojiDataModel::NameRole, "name"},
17 | {EmojiDataModel::ShortNameRole, "shortName"},
18 | {EmojiDataModel::CategoryRole, "category"},
19 | {EmojiDataModel::SheetXRole, "sheetX"},
20 | {EmojiDataModel::SheetYRole, "sheetY"}
21 | };
22 |
23 | EmojiDataModel::EmojiDataModel(QObject *parent) : QAbstractItemModel(parent)
24 | {
25 |
26 | }
27 |
28 | QModelIndex EmojiDataModel::index(int row, int, const QModelIndex &) const
29 | {
30 | return createIndex(row, 0);
31 | }
32 |
33 | QModelIndex EmojiDataModel::parent(const QModelIndex &) const
34 | {
35 | return QModelIndex();
36 | }
37 |
38 | int EmojiDataModel::rowCount(const QModelIndex &) const
39 | {
40 | return emojis.length();
41 | }
42 |
43 | int EmojiDataModel::columnCount(const QModelIndex &) const
44 | {
45 | return 1;
46 | }
47 |
48 | QVariant EmojiDataModel::data(const QModelIndex &index, int role) const
49 | {
50 | QString key = emojis[index.row()];
51 | if (role == UnicodeRole || role == Qt::DisplayRole)
52 | return key;
53 |
54 | Emoji data = emojiData[key];
55 | switch (role) {
56 | case Qt::ToolTipRole:
57 | case NameRole:
58 | return data.name;
59 | case Qt::EditRole: // Used for completion for QCompleter
60 | case ShortNameRole:
61 | return data.shortName;
62 | case CategoryRole:
63 | return data.category;
64 | case SheetXRole:
65 | return data.sheetX;
66 | case SheetYRole:
67 | return data.sheetY;
68 | case Qt::DecorationRole:
69 | return EmojiImageProvider::urlForCoords(data.sheetX, data.sheetY);
70 | break;
71 | }
72 | return key;
73 | }
74 |
75 |
76 | QHash EmojiDataModel::roleNames() const
77 | {
78 | return roles;
79 | }
80 |
81 | void EmojiDataModel::emitIMEvent(int i)
82 | {
83 | if (i >= 0 && i < emojis.length()) {
84 | QString key = emojis[i];
85 | Emoji data = emojiData[key];
86 | QInputMethodEvent *e = new QInputMethodEvent(
87 | QString(),
88 | QList());
89 | e->setCommitString(data.unicode);
90 | qApp->sendEvent(qApp->focusObject(), e);
91 | }
92 | }
93 |
94 | } } }
95 |
--------------------------------------------------------------------------------
/emojidatamodel.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Cutehacks AS. All rights reserved.
2 | // License can be found in the LICENSE file.
3 | #ifndef EMOJIDATAMODEL_H
4 | #define EMOJIDATAMODEL_H
5 |
6 | #include
7 |
8 | namespace com { namespace cutehacks { namespace emooj {
9 |
10 | class EmojiDataModel : public QAbstractItemModel
11 | {
12 | Q_OBJECT
13 |
14 | public:
15 | enum EmojiRoles {
16 | UnicodeRole = Qt::UserRole + 1000,
17 | NameRole,
18 | ShortNameRole,
19 | CategoryRole,
20 | SheetXRole,
21 | SheetYRole
22 | };
23 |
24 | EmojiDataModel(QObject *parent = 0);
25 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
26 | QModelIndex parent(const QModelIndex &child) const;
27 | int rowCount(const QModelIndex &parent) const;
28 | int columnCount(const QModelIndex &parent) const;
29 | QVariant data(const QModelIndex &index, int role) const;
30 | QHash roleNames() const;
31 |
32 | public slots:
33 | void emitIMEvent(int);
34 | };
35 |
36 | } } }
37 |
38 | #endif // EMOJIDATAMODEL_H
39 |
--------------------------------------------------------------------------------
/emojiimageprovider.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Cutehacks AS. All rights reserved.
2 | // License can be found in the LICENSE file.
3 | #include
4 |
5 | #include "emojiimageprovider.h"
6 |
7 | namespace com { namespace cutehacks { namespace emooj {
8 |
9 | static const QString SHEET_BASE(QStringLiteral(":/com/cutehacks/emooj/assets/"));
10 | static const QString SHEET_APPLE(SHEET_BASE % QStringLiteral("sheet_apple_32.png"));
11 | static const QString SHEET_GOOGLE(SHEET_BASE % QStringLiteral("sheet_google_32.png"));
12 | static const QString SHEET_EMOJIONE(SHEET_BASE % QStringLiteral("sheet_emojione_32.png"));
13 | static const QString SHEET_TWITTER(SHEET_BASE % QStringLiteral("sheet_twitter_32.png"));
14 |
15 | EmojiImageProvider::EmojiImageProvider() :
16 | QQuickImageProvider(QQuickImageProvider::Pixmap)
17 | {
18 | QString sheet;
19 | #ifdef EMOOJ_APPLE
20 | sheet = SHEET_APPLE;
21 | #elif defined(EMOOJ_GOOGLE)
22 | sheet = SHEET_GOOGLE;
23 | #elif defined(EMOOJ_EMOJIONE)
24 | sheet = SHEET_EMOJIONE;
25 | #elif defined(EMOOJ_TWITTER)
26 | sheet = SHEET_TWITTER;
27 | #endif
28 | if (!m_src.load(sheet))
29 | qWarning("Could not load emooj sheet.");
30 | }
31 |
32 | QPixmap EmojiImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &)
33 | {
34 | static const int SIZE = 32;
35 | QStringList parts = id.split("/");
36 | int coords[2];
37 | for (int i = 0; i < 2; i++)
38 | coords[i] = parts[i].toInt();
39 | int x = coords[0] * SIZE;
40 | int y = coords[1] * SIZE;
41 | if (size)
42 | *size = QSize(SIZE, SIZE);
43 | return m_src.copy(x, y, SIZE, SIZE);
44 | }
45 |
46 | QString EmojiImageProvider::urlForCoords(int sheetX, int sheetY)
47 | {
48 | return QString("image://com.cutehacks.emooj/%1/%2").arg(sheetX).arg(sheetY);
49 | }
50 |
51 | } } }
52 |
--------------------------------------------------------------------------------
/emojiimageprovider.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Cutehacks AS. All rights reserved.
2 | // License can be found in the LICENSE file.
3 | #ifndef EMOJIIMAGEPROVIDER_H
4 | #define EMOJIIMAGEPROVIDER_H
5 |
6 | #include
7 |
8 | namespace com { namespace cutehacks { namespace emooj {
9 |
10 | class EmojiImageProvider : public QQuickImageProvider
11 | {
12 | public:
13 | EmojiImageProvider();
14 | QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize);
15 |
16 | private:
17 | QPixmap m_src;
18 |
19 | public:
20 | static QString urlForCoords(int sheetX, int sheetY);
21 | };
22 |
23 | } } }
24 |
25 | #endif // EMOJIIMAGEPROVIDER_H
26 |
--------------------------------------------------------------------------------
/emooj.h:
--------------------------------------------------------------------------------
1 | #ifndef EMOOJ_H
2 | #define EMOOJ_H
3 |
4 | #include
5 | // Copyright 2016 Cutehacks AS. All rights reserved.
6 | // License can be found in the LICENSE file.
7 | #include
8 |
9 | #include "utilswrapper.h"
10 | #include "emojidatamodel.h"
11 | #include "emojiimageprovider.h"
12 |
13 | namespace com { namespace cutehacks { namespace emooj {
14 |
15 | static const char* EMOOJ_NS = "com.cutehacks.emooj";
16 |
17 | static QObject *utilsWrapperFactory(QQmlEngine *engine, QJSEngine *)
18 | {
19 | return new UtilsWrapper(engine);
20 | }
21 |
22 | static void registerEngine(QQmlEngine *engine)
23 | {
24 | qmlRegisterSingletonType(EMOOJ_NS,
25 | 1, 0, "UnicodeUtils", com::cutehacks::emooj::utilsWrapperFactory);
26 | qmlRegisterType(EMOOJ_NS, 1, 0, "EmojiDataModel");
27 | engine->addImageProvider(EMOOJ_NS, new EmojiImageProvider);
28 | }
29 |
30 |
31 | } } }
32 |
33 | #endif // EMOOJ_H
34 |
35 |
--------------------------------------------------------------------------------
/examples/completion/completion.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = app
2 |
3 | QT += qml quick
4 | CONFIG += c++11
5 |
6 | SOURCES += main.cpp
7 |
8 | RESOURCES += qml.qrc
9 |
10 | # Additional import path used to resolve QML modules in Qt Creator's code model
11 | QML_IMPORT_PATH =
12 |
13 | include(../../com_cutehacks_emooj.pri)
14 |
--------------------------------------------------------------------------------
/examples/completion/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include "emooj.h"
5 |
6 | int main(int argc, char *argv[])
7 | {
8 | QGuiApplication app(argc, argv);
9 |
10 | QQmlApplicationEngine engine;
11 | engine.addImportPath("qrc:/");
12 | com::cutehacks::emooj::registerEngine(&engine);
13 | engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
14 |
15 | return app.exec();
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/examples/completion/main.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.3
2 | import QtQuick.Window 2.2
3 | import QtQuick.Controls 1.4
4 |
5 | import com.cutehacks.emooj 1.0
6 |
7 | Window {
8 | visible: true
9 | width: 480
10 | height: 640
11 |
12 | ListView {
13 | id: list
14 |
15 | anchors {
16 | top: parent.top
17 | topMargin: 10
18 | left: parent.left
19 | right: parent.right
20 | bottom: input.top
21 | }
22 |
23 | delegate: Item {
24 | height: childrenRect.height + 10
25 | anchors {
26 | left: parent.left
27 | right: parent.right
28 | }
29 |
30 | Rectangle {
31 | id: rect
32 | color: "lightblue"
33 | radius: 5
34 | y: 10
35 | height: message.height * 2 + 5
36 | width: Math.min(parent.width - 20, message.implicitWidth + 20)
37 | anchors {
38 | right: parent.right
39 | rightMargin: 10
40 | }
41 | }
42 |
43 | Text {
44 | y: 20
45 | id: message
46 | text: content
47 | anchors {
48 | right: parent.right
49 | rightMargin: 20
50 | }
51 | wrapMode: Text.WordWrap
52 | textFormat: Qt.RichText
53 | verticalAlignment: Text.AlignVCenter
54 | horizontalAlignment: Text.AlignRight
55 | }
56 |
57 | Text {
58 | text: "length: " + UnicodeUtils.length(original)
59 | anchors.top: rect.bottom
60 | anchors.right: message.right
61 | font.pixelSize: message.font.pixelSize * .75
62 | color: "darkgray"
63 | }
64 |
65 | }
66 |
67 | model: ListModel { id: model }
68 | }
69 |
70 | TextField {
71 | id: input
72 | anchors {
73 | bottom: parent.bottom
74 | left: parent.left
75 | right: sendButton.left
76 | }
77 | focus: true
78 |
79 | ToolButton {
80 | id: openEmojis
81 | anchors {
82 | right: parent.right
83 | verticalCenter: parent.verticalCenter
84 | }
85 | text: "😃"
86 | onClicked: emojiView.visible = !emojiView.visible
87 | }
88 |
89 | EmojiView {
90 | id: emojiView
91 | visible: false
92 | anchors.right: openEmojis.right
93 | anchors.bottom: openEmojis.top
94 | }
95 | }
96 |
97 | Button {
98 | id: sendButton
99 | text: "Send"
100 | anchors {
101 | bottom: parent.bottom
102 | right: parent.right
103 | }
104 |
105 | onClicked: {
106 | console.log(input.text)
107 | var item = {
108 | original: input.text,
109 | content: UnicodeUtils.replaceEmojis(input.text, function(emoji) {
110 | console.log(JSON.stringify(emoji, null, 4));
111 | return "
"
115 | })
116 | };
117 | model.append(item);
118 | input.text = "";
119 | }
120 | }
121 | }
122 |
123 |
--------------------------------------------------------------------------------
/examples/completion/qml.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | main.qml
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/qmldir:
--------------------------------------------------------------------------------
1 | module com.cutehacks.emooj
2 | EmojiView 1.0 EmojiView.qml
3 |
4 |
--------------------------------------------------------------------------------
/qpm.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "com.cutehacks.emooj",
3 | "description": "Views, models and helpers for working with Emoji \uDCA9\uD83D",
4 | "author": {
5 | "name": "Jason Barron",
6 | "email": "jason@cutehacks.com"
7 | },
8 | "repository": {
9 | "type": "GITHUB",
10 | "url": "https://github.com/Cutehacks/emooj.git"
11 | },
12 | "version": {
13 | "label": "0.2.0"
14 | },
15 | "dependencies": [
16 | ],
17 | "license": "MIT",
18 | "pri_filename": "com_cutehacks_emooj.pri",
19 | "webpage": "https://github.com/Cutehacks/emooj"
20 | }
21 |
--------------------------------------------------------------------------------
/tools/gendata/gendata.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = app
2 | TARGET = gendata
3 | INCLUDEPATH += .
4 |
5 | SOURCES += main.cpp
6 |
7 | CONFIG += c++11
8 |
9 | DEFINES += SRCDIR=\\\"$$clean_path($$PWD/../..)\\\"
10 |
11 | macx:CONFIG -= app_bundle
12 | win32:CONFIG += console
13 |
--------------------------------------------------------------------------------
/tools/gendata/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 |
13 | #include "../../unicodeutils.h"
14 | using namespace com::cutehacks::emooj;
15 |
16 | #ifndef SRCDIR
17 | #define SRCDIR "."
18 | #endif
19 |
20 | static const QString EMOJI_FILE(QStringLiteral(SRCDIR) % "/tools/gendata/emoji_pretty.json");
21 | static const QString DEST_FILE(QStringLiteral(SRCDIR) % "/emoji-data.cpp");
22 | static const QRegularExpression escapeRe("[ \\-]");
23 |
24 | int main(int argc, char** argv)
25 | {
26 | QMap emoticons;
27 | QLinkedList > variables;
28 | QMap emojiData;
29 |
30 | QCoreApplication app(argc, argv);
31 | QFile src(EMOJI_FILE);
32 | if (!src.open(QIODevice::ReadOnly))
33 | qFatal(QString("Could not open file: %1").arg(src.fileName()).toLatin1());
34 |
35 | QJsonParseError err;
36 | QJsonDocument json = QJsonDocument::fromJson(src.readAll(), &err);
37 | if (err.error != QJsonParseError::NoError)
38 | qFatal(QString("JSON Parse Error: %1").arg(err.errorString()).toLatin1());
39 |
40 | if (!json.isArray())
41 | qFatal("JSON was not an array");
42 |
43 | QFile dest(DEST_FILE);
44 | if (!dest.open(QIODevice::WriteOnly))
45 | qFatal(QString("Could not open file: %1").arg(dest.fileName()).toLatin1());
46 |
47 | QTextStream out(&dest);
48 | out << "// This file is generated. Don't bother editing it." << endl;
49 | out << endl;
50 | out << "#include \"emoji-data.h\"" << endl;
51 | out << endl;
52 | out << "namespace com { namespace cutehacks { namespace emooj {" << endl;
53 |
54 | QJsonArray jsa = json.array();
55 | for (QJsonArray::const_iterator ita = jsa.constBegin(); ita != jsa.constEnd(); ita++) {
56 | QJsonObject emoji = (*ita).toObject();
57 |
58 | QString unified = emoji["unified"].toString();
59 | QStringList codePoints = unified.split("-");
60 | QString encoded;
61 | QString unicode;
62 | foreach (QString cp, codePoints) {
63 | bool ok;
64 | uint ucs4 = cp.toUInt(&ok, 16);
65 | if (ok) {
66 | unicode = unicode % QString::fromUcs4(&ucs4, 1);
67 | if (ucs4 >= 0x100) { // Windows won't let us use universal characters for basic chars
68 | encoded = encoded % QString("\\U%1").arg(ucs4, 8, 16, QLatin1Char('0'));
69 | } else {
70 | encoded = encoded % QString::fromUcs4(&ucs4, 1);
71 | }
72 | }
73 | }
74 |
75 | QString variable = emoji["name"].toString().replace(escapeRe, "_");
76 | if (variable.isEmpty())
77 | variable = emoji["short_name"].toString().toUpper().replace(escapeRe, "_");
78 | variables.append(QPair(variable, encoded));
79 |
80 | Emoji data = {
81 | variable,
82 | emoji["name"].toString(),
83 | emoji["short_name"].toString(),
84 | emoji["category"].toString(),
85 | emoji["sheet_x"].toInt(),
86 | emoji["sheet_y"].toInt()
87 | };
88 |
89 | emojiData.insert(variable, data);
90 |
91 | if (!emoji["skin-variations"].isUndefined()) {
92 | QJsonObject skinVariations = emoji["skin-variations"].toObject();
93 | }
94 |
95 | QJsonValue text = emoji["text"];
96 | if (!text.isUndefined() && !text.isNull()) {
97 | emoticons.insert(text.toString(), variable);
98 | }
99 |
100 | QJsonValue texts = emoji["texts"];
101 | if (texts.isArray()) {
102 | QJsonArray textsArray = texts.toArray();
103 | for (QJsonArray::const_iterator textsIt = textsArray.constBegin();
104 | textsIt != textsArray.constEnd(); textsIt++) {
105 |
106 | QString ascii = (*textsIt).toString();
107 | ascii.replace("\\", "\\\\");
108 |
109 | emoticons.insert(ascii, variable);
110 | }
111 | }
112 | }
113 |
114 | // Generate output file
115 |
116 | // Declare static string variables to reduce duplication
117 | out << endl;
118 | for (QLinkedList >::const_iterator vIt = variables.constBegin();
119 | vIt != variables.constEnd(); vIt++) {
120 |
121 | out << "static const QString " << (*vIt).first << "(QStringLiteral(\"" << (*vIt).second << "\"));" << endl;
122 | }
123 |
124 | // Declare a staticly initialized vector of all the strings
125 | out << endl << endl;
126 | out << "QVector emojis {" << endl;
127 | for (QLinkedList >::const_iterator vIt = variables.constBegin();
128 | vIt != variables.constEnd(); ) {
129 |
130 | out << " " << (*vIt).first;
131 | vIt++;
132 | if (vIt != variables.constEnd())
133 | out << ",";
134 | out << endl;
135 | }
136 | out << "};";
137 |
138 | // Declare a staticly initialized hashmap of the emoji data
139 | out << endl << endl;
140 | out << "QHash emojiData {" << endl;
141 | for (QMap::const_iterator eIt = emojiData.constBegin();
142 | eIt != emojiData.constEnd(); ) {
143 |
144 | Emoji data = eIt.value();
145 | out << " " << "{" << eIt.key() << ", Emoji {" << endl;
146 | out << " " << data.unicode << "," << endl;
147 | out << " \"" << data.name << "\"," << endl;
148 | out << " \"" << data.shortName << "\"," << endl;
149 | out << " \"" << data.category << "\"," << endl;
150 | out << " " << data.sheetX << "," << endl;
151 | out << " " << data.sheetY << "}" << endl;
152 | out << " }";
153 |
154 | eIt++;
155 | if (eIt != emojiData.constEnd())
156 | out << ",";
157 | out << endl;
158 | }
159 | out << "};";
160 |
161 |
162 | // Declare a static hash of ASCII emoticons to Unicode Emojis
163 | out << endl << endl;
164 | out << "QHash emoticons {" << endl;
165 | for (QMap::const_iterator eIt = emoticons.constBegin();
166 | eIt != emoticons.constEnd(); ) {
167 |
168 | out << " " << "{\"" << eIt.key() << "\", " << eIt.value() << "}";
169 | eIt++;
170 | if (eIt != emoticons.constEnd())
171 | out << ",";
172 | out << endl;
173 | }
174 | out << "};";
175 |
176 | out << endl;
177 | out << endl;
178 | out << "} } }" << endl;
179 |
180 | dest.close();
181 |
182 | return 0;
183 | }
184 |
--------------------------------------------------------------------------------
/unicodeutils.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Cutehacks AS. All rights reserved.
2 | // License can be found in the LICENSE file.
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "unicodeutils.h"
9 | #include "emoji-data.h"
10 |
11 | namespace com { namespace cutehacks { namespace emooj {
12 |
13 | // Following regex from Instagram: http://instagram-engineering.tumblr.com/post/118304328152/emojineering-part-2-implementing-hashtag-emoji
14 | static const QString pattern(QStringLiteral("[\U00002712\U00002714\U00002716\U0000271d\U00002721\U00002728\U00002733\U00002734\U00002744\U00002747\U0000274c\U0000274e\U00002753-\U00002755\U00002757\U00002763\U00002764\U00002795-\U00002797\U000027a1\U000027b0\U000027bf\U00002934\U00002935\U00002b05-\U00002b07\U00002b1b\U00002b1c\U00002b50\U00002b55\U00003030\U0000303d\U0001f004\U0001f0cf\U0001f170\U0001f171\U0001f17e\U0001f17f\U0001f18e\U0001f191-\U0001f19a\U0001f201\U0001f202\U0001f21a\U0001f22f\U0001f232-\U0001f23a\U0001f250\U0001f251\U0001f300-\U0001f321\U0001f324-\U0001f393\U0001f396\U0001f397\U0001f399-\U0001f39b\U0001f39e-\U0001f3f0\U0001f3f3-\U0001f3f5\U0001f3f7-\U0001f4fd\U0001f4ff-\U0001f53d\U0001f549-\U0001f54e\U0001f550-\U0001f567\U0001f56f\U0001f570\U0001f573-\U0001f579\U0001f587\U0001f58a-\U0001f58d\U0001f590\U0001f595\U0001f596\U0001f5a5\U0001f5a8\U0001f5b1\U0001f5b2\U0001f5bc\U0001f5c2-\U0001f5c4\U0001f5d1-\U0001f5d3\U0001f5dc-\U0001f5de\U0001f5e1\U0001f5e3\U0001f5ef\U0001f5f3\U0001f5fa-\U0001f64f\U0001f680-\U0001f6c5\U0001f6cb-\U0001f6d0\U0001f6e0-\U0001f6e5\U0001f6e9\U0001f6eb\U0001f6ec\U0001f6f0\U0001f6f3\U0001f910-\U0001f918\U0001f980-\U0001f984\U0001f9c0\U00003297\U00003299\U000000a9\U000000ae\U0000203c\U00002049\U00002122\U00002139\U00002194-\U00002199\U000021a9\U000021aa\U0000231a\U0000231b\U00002328\U00002388\U000023cf\U000023e9-\U000023f3\U000023f8-\U000023fa\U000024c2\U000025aa\U000025ab\U000025b6\U000025c0\U000025fb-\U000025fe\U00002600-\U00002604\U0000260e\U00002611\U00002614\U00002615\U00002618\U0000261d\U00002620\U00002622\U00002623\U00002626\U0000262a\U0000262e\U0000262f\U00002638-\U0000263a\U00002648-\U00002653\U00002660\U00002663\U00002665\U00002666\U00002668\U0000267b\U0000267f\U00002692-\U00002694\U00002696\U00002697\U00002699\U0000269b\U0000269c\U000026a0\U000026a1\U000026aa\U000026ab\U000026b0\U000026b1\U000026bd\U000026be\U000026c4\U000026c5\U000026c8\U000026ce\U000026cf\U000026d1\U000026d3\U000026d4\U000026e9\U000026ea\U000026f0-\U000026f5\U000026f7-\U000026fa\U000026fd\U00002702\U00002705\U00002708-\U0000270d\U0000270f]|[#]\U000020e3|[*]\U000020e3|[0]\U000020e3|[1]\U000020e3|[2]\U000020e3|[3]\U000020e3|[4]\U000020e3|[5]\U000020e3|[6]\U000020e3|[7]\U000020e3|[8]\U000020e3|[9]\U000020e3|\U0001f1e6[\U0001f1e8-\U0001f1ec\U0001f1ee\U0001f1f1\U0001f1f2\U0001f1f4\U0001f1f6-\U0001f1fa\U0001f1fc\U0001f1fd\U0001f1ff]|\U0001f1e7[\U0001f1e6\U0001f1e7\U0001f1e9-\U0001f1ef\U0001f1f1-\U0001f1f4\U0001f1f6-\U0001f1f9\U0001f1fb\U0001f1fc\U0001f1fe\U0001f1ff]|\U0001f1e8[\U0001f1e6\U0001f1e8\U0001f1e9\U0001f1eb-\U0001f1ee\U0001f1f0-\U0001f1f5\U0001f1f7\U0001f1fa-\U0001f1ff]|\U0001f1e9[\U0001f1ea\U0001f1ec\U0001f1ef\U0001f1f0\U0001f1f2\U0001f1f4\U0001f1ff]|\U0001f1ea[\U0001f1e6\U0001f1e8\U0001f1ea\U0001f1ec\U0001f1ed\U0001f1f7-\U0001f1fa]|\U0001f1eb[\U0001f1ee-\U0001f1f0\U0001f1f2\U0001f1f4\U0001f1f7]|\U0001f1ec[\U0001f1e6\U0001f1e7\U0001f1e9-\U0001f1ee\U0001f1f1-\U0001f1f3\U0001f1f5-\U0001f1fa\U0001f1fc\U0001f1fe]|\U0001f1ed[\U0001f1f0\U0001f1f2\U0001f1f3\U0001f1f7\U0001f1f9\U0001f1fa]|\U0001f1ee[\U0001f1e8-\U0001f1ea\U0001f1f1-\U0001f1f4\U0001f1f6-\U0001f1f9]|\U0001f1ef[\U0001f1ea\U0001f1f2\U0001f1f4\U0001f1f5]|\U0001f1f0[\U0001f1ea\U0001f1ec-\U0001f1ee\U0001f1f2\U0001f1f3\U0001f1f5\U0001f1f7\U0001f1fc\U0001f1fe\U0001f1ff]|\U0001f1f1[\U0001f1e6-\U0001f1e8\U0001f1ee\U0001f1f0\U0001f1f7-\U0001f1fb\U0001f1fe]|\U0001f1f2[\U0001f1e6\U0001f1e8-\U0001f1ed\U0001f1f0-\U0001f1ff]|\U0001f1f3[\U0001f1e6\U0001f1e8\U0001f1ea-\U0001f1ec\U0001f1ee\U0001f1f1\U0001f1f4\U0001f1f5\U0001f1f7\U0001f1fa\U0001f1ff]|\U0001f1f4\U0001f1f2|\U0001f1f5[\U0001f1e6\U0001f1ea-\U0001f1ed\U0001f1f0-\U0001f1f3\U0001f1f7-\U0001f1f9\U0001f1fc\U0001f1fe]|\U0001f1f6\U0001f1e6|\U0001f1f7[\U0001f1ea\U0001f1f4\U0001f1f8\U0001f1fa\U0001f1fc]|\U0001f1f8[\U0001f1e6-\U0001f1ea\U0001f1ec-\U0001f1f4\U0001f1f7-\U0001f1f9\U0001f1fb\U0001f1fd-\U0001f1ff]|\U0001f1f9[\U0001f1e6\U0001f1e8\U0001f1e9\U0001f1eb-\U0001f1ed\U0001f1ef-\U0001f1f4\U0001f1f7\U0001f1f9\U0001f1fb\U0001f1fc\U0001f1ff]|\U0001f1fa[\U0001f1e6\U0001f1ec\U0001f1f2\U0001f1f8\U0001f1fe\U0001f1ff]|\U0001f1fb[\U0001f1e6\U0001f1e8\U0001f1ea\U0001f1ec\U0001f1ee\U0001f1f3\U0001f1fa]|\U0001f1fc[\U0001f1eb\U0001f1f8]|\U0001f1fd\U0001f1f0|\U0001f1fe[\U0001f1ea\U0001f1f9]|\U0001f1ff[\U0001f1e6\U0001f1f2\U0001f1fc]"));
15 | QRegularExpression UnicodeUtils::emojiRe = QRegularExpression(pattern);
16 |
17 | QString UnicodeUtils::replaceEmojis(const QString &str, AbstractEmojiReplacer *replacer)
18 | {
19 | QString result = str;
20 | QRegularExpressionMatchIterator it = emojiRe.globalMatch(str);
21 | while (it.hasNext()) {
22 | QRegularExpressionMatch match = it.next();
23 | Emoji emoji = emojiData[match.captured()];
24 | QString replaceWith = replacer->replace(emoji);
25 | result.replace(match.captured(), replaceWith);
26 | }
27 |
28 | return result;
29 | }
30 |
31 | } } }
32 |
33 |
--------------------------------------------------------------------------------
/unicodeutils.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Cutehacks AS. All rights reserved.
2 | // License can be found in the LICENSE file.
3 | #ifndef UNICODEUTILS_H
4 | #define UNICODEUTILS_H
5 |
6 | #include
7 | #include
8 |
9 | #include "emoji-data.h"
10 |
11 | namespace com { namespace cutehacks { namespace emooj {
12 |
13 | class AbstractEmojiReplacer
14 | {
15 | public:
16 | virtual ~AbstractEmojiReplacer() {}
17 | virtual QString replace(const Emoji&) const = 0;
18 | };
19 |
20 | class UnicodeUtils
21 | {
22 | public:
23 | static QString replaceEmojis(const QString&, AbstractEmojiReplacer*);
24 |
25 | private:
26 | static QRegularExpression emojiRe;
27 | };
28 |
29 | } } }
30 |
31 | #endif // UNICODEUTILS_H
32 |
--------------------------------------------------------------------------------
/utilswrapper.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Cutehacks AS. All rights reserved.
2 | // License can be found in the LICENSE file.
3 | #include
4 | #include
5 |
6 | #include "utilswrapper.h"
7 | #include "unicodeutils.h"
8 |
9 | namespace com { namespace cutehacks { namespace emooj {
10 |
11 | class JSEmojiReplacer : public AbstractEmojiReplacer
12 | {
13 |
14 | public:
15 | JSEmojiReplacer(QQmlEngine * engine, const QJSValue& callback) :
16 | m_engine(engine),
17 | m_callback(callback)
18 | { }
19 |
20 | QString replace(const Emoji &emoji) const
21 | {
22 | if (m_callback.isCallable()) {
23 | QJSValue args = m_engine->newObject();
24 | args.setProperty("unicode", emoji.unicode);
25 | args.setProperty("name", emoji.name);
26 | args.setProperty("shortName", emoji.shortName);
27 | args.setProperty("sheetX", emoji.sheetX);
28 | args.setProperty("sheetY", emoji.sheetY);
29 | return m_callback.call(
30 | QJSValueList() << args
31 | ).toString();
32 | }
33 | qWarning("Second argument to UnicodeUtils.replaceEmojis should be a function");
34 | return m_callback.toString();
35 | }
36 |
37 | private:
38 | QQmlEngine *m_engine;
39 | mutable QJSValue m_callback;
40 | };
41 |
42 | UtilsWrapper::UtilsWrapper(QQmlEngine *engine) :
43 | QObject(engine),
44 | m_engine(engine)
45 | { }
46 |
47 | /*!
48 | Calculate the number of actual symbols in the QString and not
49 | just the length of the string.
50 | */
51 | int UtilsWrapper::length(const QString &str) const
52 | {
53 | return str.toUcs4().length();
54 | }
55 |
56 | /*!
57 | Find all emoijs in 'src' and replace them with the result returned by
58 | callback.
59 | */
60 | QString UtilsWrapper::replaceEmojis(const QString &src, QJSValue callback)
61 | {
62 | JSEmojiReplacer replacer(m_engine, callback);
63 | return UnicodeUtils::replaceEmojis(src, &replacer);
64 | }
65 |
66 | } } }
67 |
68 |
--------------------------------------------------------------------------------
/utilswrapper.h:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Cutehacks AS. All rights reserved.
2 | // License can be found in the LICENSE file.
3 | #ifndef UTILSWRAPPER_H
4 | #define UTILSWRAPPER_H
5 |
6 | #include
7 | #include
8 |
9 | class QQmlEngine;
10 |
11 | namespace com { namespace cutehacks { namespace emooj {
12 |
13 | class UtilsWrapper : public QObject
14 | {
15 | Q_OBJECT
16 |
17 | public:
18 | explicit UtilsWrapper(QQmlEngine *engine = 0);
19 |
20 | Q_INVOKABLE int length(const QString&) const;
21 | Q_INVOKABLE QString replaceEmojis(const QString&, QJSValue);
22 |
23 | private:
24 | QQmlEngine *m_engine;
25 | };
26 |
27 | } } }
28 |
29 | #endif // UTILSWRAPPER_H
30 |
--------------------------------------------------------------------------------