diff --git a/.gitignore b/.gitignore index c1a50b278..ffe8fc3de 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ build - -.DS_Store \ No newline at end of file +.clang-format +.DS_Store diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c4d1a545..74236107d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,8 @@ find_package(ECM ${REQUIRED_KF5_VERSION} REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${ECM_MODULE_PATH}) +include(KDEClangFormat) + set(IDENTIFIER "org.kde.neochat") set(COPYRIGHT "Copyright © 2018-2019 bhat@encom.eu.org, 2020 KDE Community") @@ -255,3 +257,7 @@ if(LINUX) DESTINATION ${CMAKE_INSTALL_DATADIR}/icons ) endif(LINUX) + +# add clang-format target for all our real source files +file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES *.cpp *.h) +kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES}) diff --git a/src/accountlistmodel.cpp b/src/accountlistmodel.cpp index 7a7da12e1..84dcd715d 100644 --- a/src/accountlistmodel.cpp +++ b/src/accountlistmodel.cpp @@ -7,86 +7,88 @@ #include "room.h" -AccountListModel::AccountListModel(QObject* parent) - : QAbstractListModel(parent) {} - -void AccountListModel::setController(Controller* value) { - if (m_controller == value) { - return; - } - - beginResetModel(); - - m_connections.clear(); - m_controller = value; - m_connections += m_controller->connections(); - - connect(m_controller, &Controller::connectionAdded, this, - [=](Connection* conn) { - if (!conn) { - return; - } - beginInsertRows(QModelIndex(), m_connections.count(), - m_connections.count()); - m_connections.append(conn); - endInsertRows(); - }); - connect(m_controller, &Controller::connectionDropped, this, - [=](Connection* conn) { - qDebug() << "Dropping connection" << conn->userId(); - if (!conn) { - qDebug() << "Trying to remove null connection"; - return; - } - conn->disconnect(this); - const auto it = - std::find(m_connections.begin(), m_connections.end(), conn); - if (it == m_connections.end()) - return; // Already deleted, nothing to do - const int row = it - m_connections.begin(); - beginRemoveRows(QModelIndex(), row, row); - m_connections.erase(it); - endRemoveRows(); - }); - emit controllerChanged(); +AccountListModel::AccountListModel(QObject *parent) + : QAbstractListModel(parent) +{ } -QVariant AccountListModel::data(const QModelIndex& index, int role) const { - if (!index.isValid()) { +void AccountListModel::setController(Controller *value) +{ + if (m_controller == value) { + return; + } + + beginResetModel(); + + m_connections.clear(); + m_controller = value; + m_connections += m_controller->connections(); + + connect(m_controller, &Controller::connectionAdded, this, [=](Connection *conn) { + if (!conn) { + return; + } + beginInsertRows(QModelIndex(), m_connections.count(), m_connections.count()); + m_connections.append(conn); + endInsertRows(); + }); + connect(m_controller, &Controller::connectionDropped, this, [=](Connection *conn) { + qDebug() << "Dropping connection" << conn->userId(); + if (!conn) { + qDebug() << "Trying to remove null connection"; + return; + } + conn->disconnect(this); + const auto it = std::find(m_connections.begin(), m_connections.end(), conn); + if (it == m_connections.end()) + return; // Already deleted, nothing to do + const int row = it - m_connections.begin(); + beginRemoveRows(QModelIndex(), row, row); + m_connections.erase(it); + endRemoveRows(); + }); + emit controllerChanged(); +} + +QVariant AccountListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) { + return {}; + } + + if (index.row() >= m_connections.count()) { + qDebug() << "AccountListModel, something's wrong: index.row() >= " + "m_users.count()"; + return {}; + } + + auto m_connection = m_connections.at(index.row()); + + if (role == UserRole) { + return QVariant::fromValue(m_connection->user()); + } + if (role == ConnectionRole) { + return QVariant::fromValue(m_connection); + } + return {}; - } - - if (index.row() >= m_connections.count()) { - qDebug() << "AccountListModel, something's wrong: index.row() >= " - "m_users.count()"; - return {}; - } - - auto m_connection = m_connections.at(index.row()); - - if (role == UserRole) { - return QVariant::fromValue(m_connection->user()); - } - if (role == ConnectionRole) { - return QVariant::fromValue(m_connection); - } - - return {}; } -int AccountListModel::rowCount(const QModelIndex& parent) const { - if (parent.isValid()) { - return 0; - } +int AccountListModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } - return m_connections.count(); + return m_connections.count(); } -QHash AccountListModel::roleNames() const { - QHash roles; +QHash AccountListModel::roleNames() const +{ + QHash roles; - roles[UserRole] = "user"; - roles[ConnectionRole] = "connection"; + roles[UserRole] = "user"; + roles[ConnectionRole] = "connection"; - return roles; + return roles; } diff --git a/src/accountlistmodel.h b/src/accountlistmodel.h index 09255ba4e..4dbdc3acf 100644 --- a/src/accountlistmodel.h +++ b/src/accountlistmodel.h @@ -11,29 +11,32 @@ #include #include -class AccountListModel : public QAbstractListModel { - Q_OBJECT - Q_PROPERTY(Controller* controller READ controller WRITE setController NOTIFY - controllerChanged) - public: - enum EventRoles { UserRole = Qt::UserRole + 1, ConnectionRole }; +class AccountListModel : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(Controller *controller READ controller WRITE setController NOTIFY controllerChanged) +public: + enum EventRoles { UserRole = Qt::UserRole + 1, ConnectionRole }; - AccountListModel(QObject* parent = nullptr); + AccountListModel(QObject *parent = nullptr); - QVariant data(const QModelIndex& index, int role = UserRole) const override; - int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = UserRole) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; - QHash roleNames() const override; + QHash roleNames() const override; - Controller* controller() const { return m_controller; } - void setController(Controller* value); + Controller *controller() const + { + return m_controller; + } + void setController(Controller *value); - private: - Controller* m_controller = nullptr; - QVector m_connections; +private: + Controller *m_controller = nullptr; + QVector m_connections; - signals: - void controllerChanged(); +signals: + void controllerChanged(); }; -#endif // ACCOUNTLISTMODEL_H +#endif // ACCOUNTLISTMODEL_H diff --git a/src/controller.cpp b/src/controller.cpp index 6d04554d9..ae0ee6c37 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -37,362 +37,355 @@ #include "spectraluser.h" #include "utils.h" -Controller::Controller(QObject* parent) : QObject(parent) { - QApplication::setQuitOnLastWindowClosed(false); +Controller::Controller(QObject *parent) + : QObject(parent) +{ + QApplication::setQuitOnLastWindowClosed(false); - Connection::setRoomType(); - Connection::setUserType(); + Connection::setRoomType(); + Connection::setUserType(); - connect(&m_ncm, &QNetworkConfigurationManager::onlineStateChanged, this, - &Controller::isOnlineChanged); + connect(&m_ncm, &QNetworkConfigurationManager::onlineStateChanged, this, &Controller::isOnlineChanged); - QTimer::singleShot(0, this, [=] { invokeLogin(); }); -} - -Controller::~Controller() { - for (auto c : m_connections) { - c->stopSync(); - c->saveState(); - } -} - -inline QString accessTokenFileName(const AccountSettings& account) { - QString fileName = account.userId(); - fileName.replace(':', '_'); - return QStandardPaths::writableLocation( - QStandardPaths::AppLocalDataLocation) + - '/' + fileName; -} - -void Controller::loginWithCredentials(QString serverAddr, - QString user, - QString pass, - QString deviceName) { - if (user.isEmpty() || pass.isEmpty()) { - return; - } - - if (deviceName.isEmpty()) { - deviceName = "Spectral " + QSysInfo::machineHostName() + " " + - QSysInfo::productType() + " " + QSysInfo::productVersion() + - " " + QSysInfo::currentCpuArchitecture(); - } - - QUrl serverUrl(serverAddr); - - auto conn = new Connection(this); - if (serverUrl.isValid()) { - conn->setHomeserver(serverUrl); - } - conn->connectToServer(user, pass, deviceName, ""); - - connect(conn, &Connection::connected, [=] { - AccountSettings account(conn->userId()); - account.setKeepLoggedIn(true); - account.clearAccessToken(); // Drop the legacy - just in case - account.setHomeserver(conn->homeserver()); - account.setDeviceId(conn->deviceId()); - account.setDeviceName(deviceName); - if (!saveAccessTokenToKeyChain(account, conn->accessToken())) - qWarning() << "Couldn't save access token"; - account.sync(); - addConnection(conn); - setConnection(conn); - }); - connect(conn, &Connection::networkError, - [=](QString error, QString, int, int) { - emit errorOccured("Network Error", error); - }); - connect(conn, &Connection::loginError, [=](QString error, QString) { - emit errorOccured("Login Failed", error); - }); -} - -void Controller::loginWithAccessToken(QString serverAddr, - QString user, - QString token, - QString deviceName) { - if (user.isEmpty() || token.isEmpty()) { - return; - } - - QUrl serverUrl(serverAddr); - - auto conn = new Connection(this); - if (serverUrl.isValid()) { - conn->setHomeserver(serverUrl); - } - - connect(conn, &Connection::connected, [=] { - AccountSettings account(conn->userId()); - account.setKeepLoggedIn(true); - account.clearAccessToken(); // Drop the legacy - just in case - account.setHomeserver(conn->homeserver()); - account.setDeviceId(conn->deviceId()); - account.setDeviceName(deviceName); - if (!saveAccessTokenToKeyChain(account, conn->accessToken())) - qWarning() << "Couldn't save access token"; - account.sync(); - addConnection(conn); - setConnection(conn); - }); - connect(conn, &Connection::networkError, - [=](QString error, QString, int, int) { - emit errorOccured("Network Error", error); - }); - conn->connectWithToken(user, token, deviceName); -} - -void Controller::logout(Connection* conn) { - if (!conn) { - qCritical() << "Attempt to logout null connection"; - return; - } - - SettingsGroup("Accounts").remove(conn->userId()); - QFile(accessTokenFileName(AccountSettings(conn->userId()))).remove(); - - QKeychain::DeletePasswordJob job(qAppName()); - job.setAutoDelete(true); - job.setKey(conn->userId()); - QEventLoop loop; - QKeychain::DeletePasswordJob::connect(&job, &QKeychain::Job::finished, &loop, - &QEventLoop::quit); - job.start(); - loop.exec(); - - auto logoutJob = conn->callApi(); - connect(logoutJob, &LogoutJob::finished, conn, [=] { - conn->stopSync(); - emit conn->stateChanged(); - emit conn->loggedOut(); - if (!m_connections.isEmpty()) - setConnection(m_connections[0]); - }); - connect(logoutJob, &LogoutJob::failure, this, [=] { - emit errorOccured("Server-side Logout Failed", logoutJob->errorString()); - }); -} - -void Controller::addConnection(Connection* c) { - Q_ASSERT_X(c, __FUNCTION__, "Attempt to add a null connection"); - - m_connections += c; - - c->setLazyLoading(true); - - connect(c, &Connection::syncDone, this, [=] { - setBusy(false); - - emit syncDone(); - - c->sync(30000); - c->saveState(); - }); - connect(c, &Connection::loggedOut, this, [=] { dropConnection(c); }); - connect(&m_ncm, &QNetworkConfigurationManager::onlineStateChanged, - [=](bool status) { - if (!status) { - return; - } - - c->stopSync(); - c->sync(30000); - }); - - using namespace Quotient; - - setBusy(true); - - c->sync(); - - emit connectionAdded(c); -} - -void Controller::dropConnection(Connection* c) { - Q_ASSERT_X(c, __FUNCTION__, "Attempt to drop a null connection"); - m_connections.removeOne(c); - - emit connectionDropped(c); - c->deleteLater(); -} - -void Controller::invokeLogin() { - using namespace Quotient; - const auto accounts = SettingsGroup("Accounts").childGroups(); - for (const auto& accountId : accounts) { - AccountSettings account{accountId}; - if (!account.homeserver().isEmpty()) { - auto accessToken = loadAccessTokenFromKeyChain(account); - - auto c = new Connection(account.homeserver(), this); - auto deviceName = account.deviceName(); - connect(c, &Connection::connected, this, [=] { - c->loadState(); - addConnection(c); - }); - connect(c, &Connection::loginError, [=](QString error, QString) { - emit errorOccured("Login Failed", error); - logout(c); - }); - connect(c, &Connection::networkError, - [=](QString error, QString, int, int) { - emit errorOccured("Network Error", error); - }); - c->connectWithToken(account.userId(), accessToken, account.deviceId()); - } - } - - if (!m_connections.isEmpty()) { - setConnection(m_connections[0]); - } - - emit initiated(); -} - -QByteArray Controller::loadAccessTokenFromFile(const AccountSettings& account) { - QFile accountTokenFile{accessTokenFileName(account)}; - if (accountTokenFile.open(QFile::ReadOnly)) { - if (accountTokenFile.size() < 1024) - return accountTokenFile.readAll(); - - qWarning() << "File" << accountTokenFile.fileName() << "is" - << accountTokenFile.size() - << "bytes long - too long for a token, ignoring it."; - } - qWarning() << "Could not open access token file" - << accountTokenFile.fileName(); - - return {}; -} - -QByteArray Controller::loadAccessTokenFromKeyChain( - const AccountSettings& account) { - qDebug() << "Read the access token from the keychain for " - << account.userId(); - QKeychain::ReadPasswordJob job(qAppName()); - job.setAutoDelete(false); - job.setKey(account.userId()); - QEventLoop loop; - QKeychain::ReadPasswordJob::connect(&job, &QKeychain::Job::finished, &loop, - &QEventLoop::quit); - job.start(); - loop.exec(); - - if (job.error() == QKeychain::Error::NoError) { - return job.binaryData(); - } - - qWarning() << "Could not read the access token from the keychain: " - << qPrintable(job.errorString()); - // no access token from the keychain, try token file - auto accessToken = loadAccessTokenFromFile(account); - if (job.error() == QKeychain::Error::EntryNotFound) { - if (!accessToken.isEmpty()) { - qDebug() << "Migrating the access token from file to the keychain for " - << account.userId(); - bool removed = false; - bool saved = saveAccessTokenToKeyChain(account, accessToken); - if (saved) { - QFile accountTokenFile{accessTokenFileName(account)}; - removed = accountTokenFile.remove(); - } - if (!(saved && removed)) { - qDebug() << "Migrating the access token from the file to the keychain " - "failed"; - } - } - } - - return accessToken; -} - -bool Controller::saveAccessTokenToFile(const AccountSettings& account, - const QByteArray& accessToken) { - // (Re-)Make a dedicated file for access_token. - QFile accountTokenFile{accessTokenFileName(account)}; - accountTokenFile.remove(); // Just in case - - auto fileDir = QFileInfo(accountTokenFile).dir(); - if (!((fileDir.exists() || fileDir.mkpath(".")) && - accountTokenFile.open(QFile::WriteOnly))) { - emit errorOccured("I/O Denied", "Cannot save access token."); - } else { - accountTokenFile.write(accessToken); - return true; - } - return false; -} - -bool Controller::saveAccessTokenToKeyChain(const AccountSettings& account, - const QByteArray& accessToken) { - qDebug() << "Save the access token to the keychain for " << account.userId(); - QKeychain::WritePasswordJob job(qAppName()); - job.setAutoDelete(false); - job.setKey(account.userId()); - job.setBinaryData(accessToken); - QEventLoop loop; - QKeychain::WritePasswordJob::connect(&job, &QKeychain::Job::finished, &loop, - &QEventLoop::quit); - job.start(); - loop.exec(); - - if (job.error()) { - qWarning() << "Could not save access token to the keychain: " - << qPrintable(job.errorString()); - return saveAccessTokenToFile(account, accessToken); - } - - return true; -} - -void Controller::joinRoom(Connection* c, const QString& alias) { - if (!alias.contains(":")) - return; - - auto knownServer = alias.mid(alias.indexOf(":") + 1); - auto joinRoomJob = c->joinRoom(alias, QStringList{knownServer}); - joinRoomJob->connect(joinRoomJob, &JoinRoomJob::failure, [=] { - emit errorOccured("Join Room Failed", joinRoomJob->errorString()); - }); -} - -void Controller::createRoom(Connection* c, - const QString& name, - const QString& topic) { - auto createRoomJob = - c->createRoom(Connection::PublishRoom, "", name, topic, QStringList()); - createRoomJob->connect(createRoomJob, &CreateRoomJob::failure, [=] { - emit errorOccured("Create Room Failed", createRoomJob->errorString()); - }); -} - -void Controller::createDirectChat(Connection* c, const QString& userID) { - auto createRoomJob = c->createDirectChat(userID); - createRoomJob->connect(createRoomJob, &CreateRoomJob::failure, [=] { - emit errorOccured("Create Direct Chat Failed", - createRoomJob->errorString()); - }); -} - -void Controller::playAudio(QUrl localFile) { - auto player = new QMediaPlayer; - player->setMedia(localFile); - player->play(); - connect(player, &QMediaPlayer::stateChanged, [=] { player->deleteLater(); }); -} - -void Controller::changeAvatar(Connection* conn, QUrl localFile) { - auto job = conn->uploadFile(localFile.toLocalFile()); - if (isJobRunning(job)) { - connect(job, &BaseJob::success, this, [conn, job] { - conn->callApi(conn->userId(), job->contentUri()); + QTimer::singleShot(0, this, [=] { + invokeLogin(); }); - } } -void Controller::markAllMessagesAsRead(Connection* conn) { - for (auto room : conn->allRooms()) { - room->markAllMessagesAsRead(); - } +Controller::~Controller() +{ + for (auto c : m_connections) { + c->stopSync(); + c->saveState(); + } +} + +inline QString accessTokenFileName(const AccountSettings &account) +{ + QString fileName = account.userId(); + fileName.replace(':', '_'); + return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + '/' + fileName; +} + +void Controller::loginWithCredentials(QString serverAddr, QString user, QString pass, QString deviceName) +{ + if (user.isEmpty() || pass.isEmpty()) { + return; + } + + if (deviceName.isEmpty()) { + deviceName = "Spectral " + QSysInfo::machineHostName() + " " + QSysInfo::productType() + " " + QSysInfo::productVersion() + " " + QSysInfo::currentCpuArchitecture(); + } + + QUrl serverUrl(serverAddr); + + auto conn = new Connection(this); + if (serverUrl.isValid()) { + conn->setHomeserver(serverUrl); + } + conn->connectToServer(user, pass, deviceName, ""); + + connect(conn, &Connection::connected, [=] { + AccountSettings account(conn->userId()); + account.setKeepLoggedIn(true); + account.clearAccessToken(); // Drop the legacy - just in case + account.setHomeserver(conn->homeserver()); + account.setDeviceId(conn->deviceId()); + account.setDeviceName(deviceName); + if (!saveAccessTokenToKeyChain(account, conn->accessToken())) + qWarning() << "Couldn't save access token"; + account.sync(); + addConnection(conn); + setConnection(conn); + }); + connect(conn, &Connection::networkError, [=](QString error, QString, int, int) { + emit errorOccured("Network Error", error); + }); + connect(conn, &Connection::loginError, [=](QString error, QString) { + emit errorOccured("Login Failed", error); + }); +} + +void Controller::loginWithAccessToken(QString serverAddr, QString user, QString token, QString deviceName) +{ + if (user.isEmpty() || token.isEmpty()) { + return; + } + + QUrl serverUrl(serverAddr); + + auto conn = new Connection(this); + if (serverUrl.isValid()) { + conn->setHomeserver(serverUrl); + } + + connect(conn, &Connection::connected, [=] { + AccountSettings account(conn->userId()); + account.setKeepLoggedIn(true); + account.clearAccessToken(); // Drop the legacy - just in case + account.setHomeserver(conn->homeserver()); + account.setDeviceId(conn->deviceId()); + account.setDeviceName(deviceName); + if (!saveAccessTokenToKeyChain(account, conn->accessToken())) + qWarning() << "Couldn't save access token"; + account.sync(); + addConnection(conn); + setConnection(conn); + }); + connect(conn, &Connection::networkError, [=](QString error, QString, int, int) { + emit errorOccured("Network Error", error); + }); + conn->connectWithToken(user, token, deviceName); +} + +void Controller::logout(Connection *conn) +{ + if (!conn) { + qCritical() << "Attempt to logout null connection"; + return; + } + + SettingsGroup("Accounts").remove(conn->userId()); + QFile(accessTokenFileName(AccountSettings(conn->userId()))).remove(); + + QKeychain::DeletePasswordJob job(qAppName()); + job.setAutoDelete(true); + job.setKey(conn->userId()); + QEventLoop loop; + QKeychain::DeletePasswordJob::connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); + job.start(); + loop.exec(); + + auto logoutJob = conn->callApi(); + connect(logoutJob, &LogoutJob::finished, conn, [=] { + conn->stopSync(); + emit conn->stateChanged(); + emit conn->loggedOut(); + if (!m_connections.isEmpty()) + setConnection(m_connections[0]); + }); + connect(logoutJob, &LogoutJob::failure, this, [=] { + emit errorOccured("Server-side Logout Failed", logoutJob->errorString()); + }); +} + +void Controller::addConnection(Connection *c) +{ + Q_ASSERT_X(c, __FUNCTION__, "Attempt to add a null connection"); + + m_connections += c; + + c->setLazyLoading(true); + + connect(c, &Connection::syncDone, this, [=] { + setBusy(false); + + emit syncDone(); + + c->sync(30000); + c->saveState(); + }); + connect(c, &Connection::loggedOut, this, [=] { + dropConnection(c); + }); + connect(&m_ncm, &QNetworkConfigurationManager::onlineStateChanged, [=](bool status) { + if (!status) { + return; + } + + c->stopSync(); + c->sync(30000); + }); + + using namespace Quotient; + + setBusy(true); + + c->sync(); + + emit connectionAdded(c); +} + +void Controller::dropConnection(Connection *c) +{ + Q_ASSERT_X(c, __FUNCTION__, "Attempt to drop a null connection"); + m_connections.removeOne(c); + + emit connectionDropped(c); + c->deleteLater(); +} + +void Controller::invokeLogin() +{ + using namespace Quotient; + const auto accounts = SettingsGroup("Accounts").childGroups(); + for (const auto &accountId : accounts) { + AccountSettings account {accountId}; + if (!account.homeserver().isEmpty()) { + auto accessToken = loadAccessTokenFromKeyChain(account); + + auto c = new Connection(account.homeserver(), this); + auto deviceName = account.deviceName(); + connect(c, &Connection::connected, this, [=] { + c->loadState(); + addConnection(c); + }); + connect(c, &Connection::loginError, [=](QString error, QString) { + emit errorOccured("Login Failed", error); + logout(c); + }); + connect(c, &Connection::networkError, [=](QString error, QString, int, int) { + emit errorOccured("Network Error", error); + }); + c->connectWithToken(account.userId(), accessToken, account.deviceId()); + } + } + + if (!m_connections.isEmpty()) { + setConnection(m_connections[0]); + } + + emit initiated(); +} + +QByteArray Controller::loadAccessTokenFromFile(const AccountSettings &account) +{ + QFile accountTokenFile {accessTokenFileName(account)}; + if (accountTokenFile.open(QFile::ReadOnly)) { + if (accountTokenFile.size() < 1024) + return accountTokenFile.readAll(); + + qWarning() << "File" << accountTokenFile.fileName() << "is" << accountTokenFile.size() << "bytes long - too long for a token, ignoring it."; + } + qWarning() << "Could not open access token file" << accountTokenFile.fileName(); + + return {}; +} + +QByteArray Controller::loadAccessTokenFromKeyChain(const AccountSettings &account) +{ + qDebug() << "Read the access token from the keychain for " << account.userId(); + QKeychain::ReadPasswordJob job(qAppName()); + job.setAutoDelete(false); + job.setKey(account.userId()); + QEventLoop loop; + QKeychain::ReadPasswordJob::connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); + job.start(); + loop.exec(); + + if (job.error() == QKeychain::Error::NoError) { + return job.binaryData(); + } + + qWarning() << "Could not read the access token from the keychain: " << qPrintable(job.errorString()); + // no access token from the keychain, try token file + auto accessToken = loadAccessTokenFromFile(account); + if (job.error() == QKeychain::Error::EntryNotFound) { + if (!accessToken.isEmpty()) { + qDebug() << "Migrating the access token from file to the keychain for " << account.userId(); + bool removed = false; + bool saved = saveAccessTokenToKeyChain(account, accessToken); + if (saved) { + QFile accountTokenFile {accessTokenFileName(account)}; + removed = accountTokenFile.remove(); + } + if (!(saved && removed)) { + qDebug() << "Migrating the access token from the file to the keychain " + "failed"; + } + } + } + + return accessToken; +} + +bool Controller::saveAccessTokenToFile(const AccountSettings &account, const QByteArray &accessToken) +{ + // (Re-)Make a dedicated file for access_token. + QFile accountTokenFile {accessTokenFileName(account)}; + accountTokenFile.remove(); // Just in case + + auto fileDir = QFileInfo(accountTokenFile).dir(); + if (!((fileDir.exists() || fileDir.mkpath(".")) && accountTokenFile.open(QFile::WriteOnly))) { + emit errorOccured("I/O Denied", "Cannot save access token."); + } else { + accountTokenFile.write(accessToken); + return true; + } + return false; +} + +bool Controller::saveAccessTokenToKeyChain(const AccountSettings &account, const QByteArray &accessToken) +{ + qDebug() << "Save the access token to the keychain for " << account.userId(); + QKeychain::WritePasswordJob job(qAppName()); + job.setAutoDelete(false); + job.setKey(account.userId()); + job.setBinaryData(accessToken); + QEventLoop loop; + QKeychain::WritePasswordJob::connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); + job.start(); + loop.exec(); + + if (job.error()) { + qWarning() << "Could not save access token to the keychain: " << qPrintable(job.errorString()); + return saveAccessTokenToFile(account, accessToken); + } + + return true; +} + +void Controller::joinRoom(Connection *c, const QString &alias) +{ + if (!alias.contains(":")) + return; + + auto knownServer = alias.mid(alias.indexOf(":") + 1); + auto joinRoomJob = c->joinRoom(alias, QStringList {knownServer}); + joinRoomJob->connect(joinRoomJob, &JoinRoomJob::failure, [=] { + emit errorOccured("Join Room Failed", joinRoomJob->errorString()); + }); +} + +void Controller::createRoom(Connection *c, const QString &name, const QString &topic) +{ + auto createRoomJob = c->createRoom(Connection::PublishRoom, "", name, topic, QStringList()); + createRoomJob->connect(createRoomJob, &CreateRoomJob::failure, [=] { + emit errorOccured("Create Room Failed", createRoomJob->errorString()); + }); +} + +void Controller::createDirectChat(Connection *c, const QString &userID) +{ + auto createRoomJob = c->createDirectChat(userID); + createRoomJob->connect(createRoomJob, &CreateRoomJob::failure, [=] { + emit errorOccured("Create Direct Chat Failed", createRoomJob->errorString()); + }); +} + +void Controller::playAudio(QUrl localFile) +{ + auto player = new QMediaPlayer; + player->setMedia(localFile); + player->play(); + connect(player, &QMediaPlayer::stateChanged, [=] { + player->deleteLater(); + }); +} + +void Controller::changeAvatar(Connection *conn, QUrl localFile) +{ + auto job = conn->uploadFile(localFile.toLocalFile()); + if (isJobRunning(job)) { + connect(job, &BaseJob::success, this, [conn, job] { + conn->callApi(conn->userId(), job->contentUri()); + }); + } +} + +void Controller::markAllMessagesAsRead(Connection *conn) +{ + for (auto room : conn->allRooms()) { + room->markAllMessagesAsRead(); + } } diff --git a/src/controller.h b/src/controller.h index 80127309e..28652c3e0 100644 --- a/src/controller.h +++ b/src/controller.h @@ -22,109 +22,122 @@ using namespace Quotient; -class Controller : public QObject { - Q_OBJECT - Q_PROPERTY(int accountCount READ accountCount NOTIFY connectionAdded NOTIFY - connectionDropped) - Q_PROPERTY(bool quitOnLastWindowClosed READ quitOnLastWindowClosed WRITE - setQuitOnLastWindowClosed NOTIFY quitOnLastWindowClosedChanged) - Q_PROPERTY(Connection* connection READ connection WRITE setConnection NOTIFY - connectionChanged) - Q_PROPERTY(bool isOnline READ isOnline NOTIFY isOnlineChanged) - Q_PROPERTY(bool busy READ busy WRITE setBusy NOTIFY busyChanged) +class Controller : public QObject +{ + Q_OBJECT + Q_PROPERTY(int accountCount READ accountCount NOTIFY connectionAdded NOTIFY connectionDropped) + Q_PROPERTY(bool quitOnLastWindowClosed READ quitOnLastWindowClosed WRITE setQuitOnLastWindowClosed NOTIFY quitOnLastWindowClosedChanged) + Q_PROPERTY(Connection *connection READ connection WRITE setConnection NOTIFY connectionChanged) + Q_PROPERTY(bool isOnline READ isOnline NOTIFY isOnlineChanged) + Q_PROPERTY(bool busy READ busy WRITE setBusy NOTIFY busyChanged) - public: - explicit Controller(QObject* parent = nullptr); - ~Controller(); +public: + explicit Controller(QObject *parent = nullptr); + ~Controller(); - Q_INVOKABLE void loginWithCredentials(QString, QString, QString, QString); - Q_INVOKABLE void loginWithAccessToken(QString, QString, QString, QString); + Q_INVOKABLE void loginWithCredentials(QString, QString, QString, QString); + Q_INVOKABLE void loginWithAccessToken(QString, QString, QString, QString); - QVector connections() const { return m_connections; } - - // All the non-Q_INVOKABLE functions. - void addConnection(Connection* c); - void dropConnection(Connection* c); - - // All the Q_PROPERTYs. - int accountCount() { return m_connections.count(); } - - bool quitOnLastWindowClosed() const { - return QApplication::quitOnLastWindowClosed(); - } - void setQuitOnLastWindowClosed(bool value) { - if (quitOnLastWindowClosed() != value) { - QApplication::setQuitOnLastWindowClosed(value); - - emit quitOnLastWindowClosedChanged(); + QVector connections() const + { + return m_connections; } - } - bool isOnline() const { return m_ncm.isOnline(); } + // All the non-Q_INVOKABLE functions. + void addConnection(Connection *c); + void dropConnection(Connection *c); - bool busy() const { return m_busy; } - void setBusy(bool busy) { - if (m_busy == busy) { - return; + // All the Q_PROPERTYs. + int accountCount() + { + return m_connections.count(); } - m_busy = busy; - emit busyChanged(); - } - Connection* connection() const { - if (m_connection.isNull()) - return nullptr; + bool quitOnLastWindowClosed() const + { + return QApplication::quitOnLastWindowClosed(); + } + void setQuitOnLastWindowClosed(bool value) + { + if (quitOnLastWindowClosed() != value) { + QApplication::setQuitOnLastWindowClosed(value); - return m_connection; - } + emit quitOnLastWindowClosedChanged(); + } + } - void setConnection(Connection* conn) { - if (conn == m_connection) - return; - m_connection = conn; - emit connectionChanged(); - } + bool isOnline() const + { + return m_ncm.isOnline(); + } - private: - QVector m_connections; - QPointer m_connection; - QNetworkConfigurationManager m_ncm; - bool m_busy = false; + bool busy() const + { + return m_busy; + } + void setBusy(bool busy) + { + if (m_busy == busy) { + return; + } + m_busy = busy; + emit busyChanged(); + } - QByteArray loadAccessTokenFromFile(const AccountSettings& account); - QByteArray loadAccessTokenFromKeyChain(const AccountSettings& account); + Connection *connection() const + { + if (m_connection.isNull()) + return nullptr; - bool saveAccessTokenToFile(const AccountSettings& account, - const QByteArray& accessToken); - bool saveAccessTokenToKeyChain(const AccountSettings& account, - const QByteArray& accessToken); - void loadSettings(); - void saveSettings() const; + return m_connection; + } - private slots: - void invokeLogin(); + void setConnection(Connection *conn) + { + if (conn == m_connection) + return; + m_connection = conn; + emit connectionChanged(); + } - signals: - void busyChanged(); - void errorOccured(QString error, QString detail); - void syncDone(); - void connectionAdded(Connection* conn); - void connectionDropped(Connection* conn); - void initiated(); - void notificationClicked(const QString roomId, const QString eventId); - void quitOnLastWindowClosedChanged(); - void unreadCountChanged(); - void connectionChanged(); - void isOnlineChanged(); +private: + QVector m_connections; + QPointer m_connection; + QNetworkConfigurationManager m_ncm; + bool m_busy = false; - public slots: - void logout(Connection* conn); - void joinRoom(Connection* c, const QString& alias); - void createRoom(Connection* c, const QString& name, const QString& topic); - void createDirectChat(Connection* c, const QString& userID); - void playAudio(QUrl localFile); - void changeAvatar(Connection* conn, QUrl localFile); - void markAllMessagesAsRead(Connection* conn); + QByteArray loadAccessTokenFromFile(const AccountSettings &account); + QByteArray loadAccessTokenFromKeyChain(const AccountSettings &account); + + bool saveAccessTokenToFile(const AccountSettings &account, const QByteArray &accessToken); + bool saveAccessTokenToKeyChain(const AccountSettings &account, const QByteArray &accessToken); + void loadSettings(); + void saveSettings() const; + +private slots: + void invokeLogin(); + +signals: + void busyChanged(); + void errorOccured(QString error, QString detail); + void syncDone(); + void connectionAdded(Connection *conn); + void connectionDropped(Connection *conn); + void initiated(); + void notificationClicked(const QString roomId, const QString eventId); + void quitOnLastWindowClosedChanged(); + void unreadCountChanged(); + void connectionChanged(); + void isOnlineChanged(); + +public slots: + void logout(Connection *conn); + void joinRoom(Connection *c, const QString &alias); + void createRoom(Connection *c, const QString &name, const QString &topic); + void createDirectChat(Connection *c, const QString &userID); + void playAudio(QUrl localFile); + void changeAvatar(Connection *conn, QUrl localFile); + void markAllMessagesAsRead(Connection *conn); }; -#endif // CONTROLLER_H +#endif // CONTROLLER_H diff --git a/src/emojimodel.cpp b/src/emojimodel.cpp index 5008086c3..cc2214094 100644 --- a/src/emojimodel.cpp +++ b/src/emojimodel.cpp @@ -9,2768 +9,1398 @@ #include "emojimodel.h" -QVariantList EmojiModel::history() { - return m_settings->value("Editor/emojis", QVariantList()).toList(); +QVariantList EmojiModel::history() +{ + return m_settings->value("Editor/emojis", QVariantList()).toList(); } -QVariantList EmojiModel::filterModel(const QString& filter) { - QVariantList result; +QVariantList EmojiModel::filterModel(const QString &filter) +{ + QVariantList result; - for (QVariant e : people) { - auto emoji = qvariant_cast(e); - if (emoji.shortname.startsWith(filter)) { - result.append(e); + for (QVariant e : people) { + auto emoji = qvariant_cast(e); + if (emoji.shortname.startsWith(filter)) { + result.append(e); + } } - } - for (QVariant e : nature) { - auto emoji = qvariant_cast(e); - if (emoji.shortname.startsWith(filter)) { - result.append(e); + for (QVariant e : nature) { + auto emoji = qvariant_cast(e); + if (emoji.shortname.startsWith(filter)) { + result.append(e); + } } - } - for (QVariant e : food) { - auto emoji = qvariant_cast(e); - if (emoji.shortname.startsWith(filter)) { - result.append(e); + for (QVariant e : food) { + auto emoji = qvariant_cast(e); + if (emoji.shortname.startsWith(filter)) { + result.append(e); + } } - } - for (QVariant e : activity) { - auto emoji = qvariant_cast(e); - if (emoji.shortname.startsWith(filter)) { - result.append(e); + for (QVariant e : activity) { + auto emoji = qvariant_cast(e); + if (emoji.shortname.startsWith(filter)) { + result.append(e); + } } - } - for (QVariant e : travel) { - auto emoji = qvariant_cast(e); - if (emoji.shortname.startsWith(filter)) { - result.append(e); + for (QVariant e : travel) { + auto emoji = qvariant_cast(e); + if (emoji.shortname.startsWith(filter)) { + result.append(e); + } } - } - for (QVariant e : objects) { - auto emoji = qvariant_cast(e); - if (emoji.shortname.startsWith(filter)) { - result.append(e); + for (QVariant e : objects) { + auto emoji = qvariant_cast(e); + if (emoji.shortname.startsWith(filter)) { + result.append(e); + } } - } - for (QVariant e : symbols) { - auto emoji = qvariant_cast(e); - if (emoji.shortname.startsWith(filter)) { - result.append(e); + for (QVariant e : symbols) { + auto emoji = qvariant_cast(e); + if (emoji.shortname.startsWith(filter)) { + result.append(e); + } } - } - for (QVariant e : flags) { - auto emoji = qvariant_cast(e); - if (emoji.shortname.startsWith(filter)) { - result.append(e); + for (QVariant e : flags) { + auto emoji = qvariant_cast(e); + if (emoji.shortname.startsWith(filter)) { + result.append(e); + } } - } - return result; + return result; } -void EmojiModel::emojiUsed(QVariant modelData) { - QVariantList list = history(); +void EmojiModel::emojiUsed(QVariant modelData) +{ + QVariantList list = history(); - auto it = list.begin(); - while (it != list.end()) { - if ((*it).value().unicode == modelData.value().unicode) { - it = list.erase(it); - } else - it++; - } + auto it = list.begin(); + while (it != list.end()) { + if ((*it).value().unicode == modelData.value().unicode) { + it = list.erase(it); + } else + it++; + } - list.push_front(modelData); - m_settings->setValue("Editor/emojis", list); + list.push_front(modelData); + m_settings->setValue("Editor/emojis", list); - emit historyChanged(); + emit historyChanged(); } const QVariantList EmojiModel::people = { - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x80"), ":grinning:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x98\x81"), ":grin:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x98\x82"), ":joy:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa3"), ":rofl:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x83"), ":smiley:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x84"), ":smile:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x85"), ":sweat_smile:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x86"), ":laughing:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x98\x89"), ":wink:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x8a"), ":blush:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x98\x8b"), ":yum:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x8e"), ":sunglasses:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x8d"), ":heart_eyes:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x98"), ":kissing_heart:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x97"), ":kissing:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x99"), ":kissing_smiling_eyes:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x9a"), ":kissing_closed_eyes:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x98\xba"), ":relaxed:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x99\x82"), ":slight_smile:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x97"), ":hugging:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x94"), ":thinking:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x90"), ":neutral_face:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x91"), ":expressionless:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb6"), ":no_mouth:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x99\x84"), ":rolling_eyes:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x8f"), ":smirk:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xa3"), ":persevere:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x98\xa5"), - ":disappointed_relieved:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xae"), ":open_mouth:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x90"), ":zipper_mouth:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xaf"), ":hushed:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xaa"), ":sleepy:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xab"), ":tired_face:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb4"), ":sleeping:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x8c"), ":relieved:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\xa4\x93"), ":nerd:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x9b"), ":stuck_out_tongue:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x98\x9c"), - ":stuck_out_tongue_winking_eye:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x98\x9d"), - ":stuck_out_tongue_closed_eyes:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa4"), ":drooling_face:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x92"), ":unamused:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x93"), ":sweat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x94"), ":pensive:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x95"), ":confused:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x99\x83"), ":upside_down:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x91"), ":money_mouth:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb2"), ":astonished:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x98\xb9"), ":frowning2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x99\x81"), ":slight_frown:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x96"), ":confounded:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x9e"), ":disappointed:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x9f"), ":worried:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xa4"), ":triumph:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x98\xa2"), ":cry:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x98\xad"), ":sob:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xa6"), ":frowning:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xa7"), ":anguished:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xa8"), ":fearful:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xa9"), ":weary:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xac"), ":grimacing:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb0"), ":cold_sweat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb1"), ":scream:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb3"), ":flushed:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb5"), ":dizzy_face:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x98\xa1"), ":rage:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xa0"), ":angry:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x87"), ":innocent:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa0"), ":cowboy:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa1"), ":clown:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa5"), ":lying_face:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x98\xb7"), ":mask:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x92"), ":thermometer_face:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x95"), ":head_bandage:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa2"), ":nauseated_face:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa7"), ":sneezing_face:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\x88"), ":smiling_imp:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x91\xbf"), ":imp:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb9"), ":japanese_ogre:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xba"), ":japanese_goblin:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x80"), ":skull:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xbb"), ":ghost:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xbd"), ":alien:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x96"), ":robot:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x92\xa9"), ":poop:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xba"), ":smiley_cat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb8"), ":smile_cat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xb9"), ":joy_cat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xbb"), ":heart_eyes_cat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xbc"), ":smirk_cat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xbd"), ":kissing_cat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x99\x80"), ":scream_cat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xbf"), ":crying_cat_face:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x98\xbe"), ":pouting_cat:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x91\xa6"), ":boy:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x91\xa7"), ":girl:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x91\xa8"), ":man:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa9"), ":woman:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb4"), ":older_man:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb5"), ":older_woman:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x91\xb6"), ":baby:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xbc"), ":angel:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x91\xae"), ":cop:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x95\xb5"), ":spy:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x82"), ":guardsman:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb7"), ":construction_worker:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb3"), ":man_with_turban:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x91\xb1"), - ":person_with_blond_hair:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x85"), ":santa:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb6"), ":mrs_claus:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb8"), ":princess:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb4"), ":prince:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb0"), ":bride_with_veil:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb5"), ":man_in_tuxedo:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb0"), ":pregnant_woman:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xb2"), ":man_with_gua_pi_mao:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8d"), ":person_frowning:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x99\x8e"), - ":person_with_pouting_face:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x99\x85"), ":no_good:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x99\x86"), ":ok_woman:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x92\x81"), - ":information_desk_person:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8b"), ":raising_hand:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x99\x87"), ":bow:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xa6"), ":face_palm:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb7"), ":shrug:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x86"), ":massage:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x87"), ":haircut:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb6"), ":walking:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x83"), ":runner:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x83"), ":dancer:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\xba"), ":man_dancing:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xaf"), ":dancers:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\xa3"), ":speaking_head:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa4"), ":bust_in_silhouette:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa5"), ":busts_in_silhouette:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xab"), ":couple:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x91\xac"), - ":two_men_holding_hands:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x91\xad"), - ":two_women_holding_hands:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x8f"), ":couplekiss:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x91"), ":couple_with_heart:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xaa"), ":family:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xaa"), ":muscle:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb3"), ":selfie:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x88"), ":point_left:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x89"), ":point_right:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x98\x9d"), ":point_up:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x86"), ":point_up_2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x96\x95"), ":middle_finger:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x87"), ":point_down:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9c\x8c"), ":v:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9e"), ":fingers_crossed:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x96\x96"), ":vulcan:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x98"), ":metal:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x99"), ":call_me:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x96\x90"), ":hand_splayed:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9c\x8b"), ":raised_hand:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8c"), ":ok_hand:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8d"), ":thumbsup:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8e"), ":thumbsdown:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9c\x8a"), ":fist:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x8a"), ":punch:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9b"), ":left_facing_fist:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9c"), ":right_facing_fist:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9a"), ":raised_back_of_hand:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x91\x8b"), ":wave:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x91\x8f"), ":clap:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9c\x8d"), ":writing_hand:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x90"), ":open_hands:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8c"), ":raised_hands:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x99\x8f"), ":pray:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\x9d"), ":handshake:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x85"), ":nail_care:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x91\x82"), ":ear:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x91\x83"), ":nose:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa3"), ":footprints:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x91\x80"), ":eyes:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x91\x81"), ":eye:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x85"), ":tongue:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x91\x84"), ":lips:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x92\x8b"), ":kiss:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x92\xa4"), ":zzz:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x93"), ":eyeglasses:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb6"), ":dark_sunglasses:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x94"), ":necktie:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x95"), ":shirt:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x96"), ":jeans:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x97"), ":dress:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x98"), ":kimono:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x99"), ":bikini:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x9a"), ":womans_clothes:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x9b"), ":purse:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x9c"), ":handbag:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x9d"), ":pouch:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x92"), ":school_satchel:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x9e"), ":mans_shoe:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x9f"), ":athletic_shoe:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa0"), ":high_heel:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xa1"), ":sandal:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x91\xa2"), ":boot:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x91"), ":crown:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x92"), ":womans_hat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa9"), ":tophat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x93"), ":mortar_board:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9b\x91"), ":helmet_with_cross:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x84"), ":lipstick:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x92\x8d"), ":ring:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x82"), ":closed_umbrella:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xbc"), ":briefcase:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x80"), ":grinning:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x81"), ":grin:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x82"), ":joy:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xa3"), ":rofl:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x83"), ":smiley:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x84"), ":smile:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x85"), ":sweat_smile:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x86"), ":laughing:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x89"), ":wink:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x8a"), ":blush:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x8b"), ":yum:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x8e"), ":sunglasses:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x8d"), ":heart_eyes:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x98"), ":kissing_heart:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x97"), ":kissing:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x99"), ":kissing_smiling_eyes:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x9a"), ":kissing_closed_eyes:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\xba"), ":relaxed:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x99\x82"), ":slight_smile:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\x97"), ":hugging:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\x94"), ":thinking:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x90"), ":neutral_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x91"), ":expressionless:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xb6"), ":no_mouth:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x99\x84"), ":rolling_eyes:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x8f"), ":smirk:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xa3"), ":persevere:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xa5"), ":disappointed_relieved:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xae"), ":open_mouth:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\x90"), ":zipper_mouth:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xaf"), ":hushed:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xaa"), ":sleepy:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xab"), ":tired_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xb4"), ":sleeping:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x8c"), ":relieved:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\x93"), ":nerd:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x9b"), ":stuck_out_tongue:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x9c"), ":stuck_out_tongue_winking_eye:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x9d"), ":stuck_out_tongue_closed_eyes:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xa4"), ":drooling_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x92"), ":unamused:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x93"), ":sweat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x94"), ":pensive:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x95"), ":confused:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x99\x83"), ":upside_down:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\x91"), ":money_mouth:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xb2"), ":astonished:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\xb9"), ":frowning2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x99\x81"), ":slight_frown:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x96"), ":confounded:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x9e"), ":disappointed:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x9f"), ":worried:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xa4"), ":triumph:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xa2"), ":cry:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xad"), ":sob:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xa6"), ":frowning:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xa7"), ":anguished:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xa8"), ":fearful:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xa9"), ":weary:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xac"), ":grimacing:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xb0"), ":cold_sweat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xb1"), ":scream:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xb3"), ":flushed:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xb5"), ":dizzy_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xa1"), ":rage:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xa0"), ":angry:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x87"), ":innocent:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xa0"), ":cowboy:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xa1"), ":clown:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xa5"), ":lying_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xb7"), ":mask:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\x92"), ":thermometer_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\x95"), ":head_bandage:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xa2"), ":nauseated_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xa7"), ":sneezing_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\x88"), ":smiling_imp:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xbf"), ":imp:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xb9"), ":japanese_ogre:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xba"), ":japanese_goblin:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x80"), ":skull:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xbb"), ":ghost:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xbd"), ":alien:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\x96"), ":robot:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xa9"), ":poop:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xba"), ":smiley_cat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xb8"), ":smile_cat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xb9"), ":joy_cat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xbb"), ":heart_eyes_cat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xbc"), ":smirk_cat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xbd"), ":kissing_cat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x99\x80"), ":scream_cat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xbf"), ":crying_cat_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x98\xbe"), ":pouting_cat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xa6"), ":boy:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xa7"), ":girl:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xa8"), ":man:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xa9"), ":woman:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xb4"), ":older_man:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xb5"), ":older_woman:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xb6"), ":baby:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xbc"), ":angel:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xae"), ":cop:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xb5"), ":spy:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x82"), ":guardsman:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xb7"), ":construction_worker:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xb3"), ":man_with_turban:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xb1"), ":person_with_blond_hair:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x85"), ":santa:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb6"), ":mrs_claus:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xb8"), ":princess:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb4"), ":prince:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xb0"), ":bride_with_veil:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb5"), ":man_in_tuxedo:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb0"), ":pregnant_woman:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xb2"), ":man_with_gua_pi_mao:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x99\x8d"), ":person_frowning:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x99\x8e"), ":person_with_pouting_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x99\x85"), ":no_good:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x99\x86"), ":ok_woman:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x81"), ":information_desk_person:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x99\x8b"), ":raising_hand:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x99\x87"), ":bow:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xa6"), ":face_palm:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb7"), ":shrug:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x86"), ":massage:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x87"), ":haircut:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb6"), ":walking:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x83"), ":runner:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x83"), ":dancer:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xba"), ":man_dancing:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xaf"), ":dancers:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\xa3"), ":speaking_head:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xa4"), ":bust_in_silhouette:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xa5"), ":busts_in_silhouette:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xab"), ":couple:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xac"), ":two_men_holding_hands:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xad"), ":two_women_holding_hands:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x8f"), ":couplekiss:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x91"), ":couple_with_heart:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xaa"), ":family:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xaa"), ":muscle:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb3"), ":selfie:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x88"), ":point_left:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x89"), ":point_right:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\x9d"), ":point_up:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x86"), ":point_up_2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x96\x95"), ":middle_finger:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x87"), ":point_down:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9c\x8c"), ":v:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\x9e"), ":fingers_crossed:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x96\x96"), ":vulcan:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\x98"), ":metal:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\x99"), ":call_me:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x96\x90"), ":hand_splayed:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9c\x8b"), ":raised_hand:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x8c"), ":ok_hand:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x8d"), ":thumbsup:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x8e"), ":thumbsdown:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9c\x8a"), ":fist:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x8a"), ":punch:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\x9b"), ":left_facing_fist:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\x9c"), ":right_facing_fist:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\x9a"), ":raised_back_of_hand:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x8b"), ":wave:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x8f"), ":clap:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9c\x8d"), ":writing_hand:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x90"), ":open_hands:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x99\x8c"), ":raised_hands:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x99\x8f"), ":pray:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\x9d"), ":handshake:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x85"), ":nail_care:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x82"), ":ear:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x83"), ":nose:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xa3"), ":footprints:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x80"), ":eyes:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x81"), ":eye:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x85"), ":tongue:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x84"), ":lips:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x8b"), ":kiss:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xa4"), ":zzz:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x93"), ":eyeglasses:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xb6"), ":dark_sunglasses:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x94"), ":necktie:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x95"), ":shirt:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x96"), ":jeans:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x97"), ":dress:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x98"), ":kimono:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x99"), ":bikini:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x9a"), ":womans_clothes:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x9b"), ":purse:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x9c"), ":handbag:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x9d"), ":pouch:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x92"), ":school_satchel:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x9e"), ":mans_shoe:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x9f"), ":athletic_shoe:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xa0"), ":high_heel:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xa1"), ":sandal:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xa2"), ":boot:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x91"), ":crown:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x92"), ":womans_hat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xa9"), ":tophat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x93"), ":mortar_board:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\x91"), ":helmet_with_cross:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x84"), ":lipstick:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x8d"), ":ring:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x82"), ":closed_umbrella:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xbc"), ":briefcase:"}), }; const QVariantList EmojiModel::nature = { - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x99\x88"), ":see_no_evil:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x99\x89"), ":hear_no_evil:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x99\x8a"), ":speak_no_evil:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xa6"), ":sweat_drops:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x92\xa8"), ":dash:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xb5"), ":monkey_face:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x92"), ":monkey:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x8d"), ":gorilla:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\xb6"), ":dog:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\x95"), ":dog2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa9"), ":poodle:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\xba"), ":wolf:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\xa6\x8a"), ":fox:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\xb1"), ":cat:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\x88"), ":cat2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x81"), ":lion_face:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xaf"), ":tiger:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x85"), ":tiger2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x86"), ":leopard:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xb4"), ":horse:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x8e"), ":racehorse:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\xa6\x8c"), ":deer:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x84"), ":unicorn:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\xae"), ":cow:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\x82"), ":ox:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x83"), ":water_buffalo:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\x84"), ":cow2:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\xb7"), ":pig:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\x96"), ":pig2:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\x97"), ":boar:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xbd"), ":pig_nose:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\x8f"), ":ram:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x91"), ":sheep:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\x90"), ":goat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xaa"), ":dromedary_camel:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xab"), ":camel:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x98"), ":elephant:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x8f"), ":rhino:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xad"), ":mouse:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x81"), ":mouse2:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\x80"), ":rat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xb9"), ":hamster:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xb0"), ":rabbit:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x87"), ":rabbit2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xbf"), ":chipmunk:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\xa6\x87"), ":bat:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\xbb"), ":bear:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa8"), ":koala:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xbc"), ":panda_face:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\xbe"), ":feet:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x83"), ":turkey:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x94"), ":chicken:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x93"), ":rooster:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa3"), ":hatching_chick:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa4"), ":baby_chick:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa5"), ":hatched_chick:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\xa6"), ":bird:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa7"), ":penguin:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x95\x8a"), ":dove:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x85"), ":eagle:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\xa6\x86"), ":duck:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\xa6\x89"), ":owl:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\xb8"), ":frog:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x8a"), ":crocodile:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa2"), ":turtle:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x8e"), ":lizard:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x8d"), ":snake:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xb2"), ":dragon_face:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x89"), ":dragon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xb3"), ":whale:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x8b"), ":whale2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xac"), ":dolphin:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\x9f"), ":fish:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa0"), ":tropical_fish:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\xa1"), ":blowfish:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x88"), ":shark:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x99"), ":octopus:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x9a"), ":shell:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\xa6\x80"), ":crab:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x90"), ":shrimp:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x91"), ":squid:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x8b"), ":butterfly:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x8c"), ":snail:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\x9b"), ":bug:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\x9c"), ":ant:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x90\x9d"), ":bee:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x90\x9e"), ":beetle:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb7"), ":spider:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb8"), ":spider_web:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa6\x82"), ":scorpion:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x90"), ":bouquet:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb8"), ":cherry_blossom:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb5"), ":rosette:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb9"), ":rose:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x80"), ":wilted_rose:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xba"), ":hibiscus:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xbb"), ":sunflower:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xbc"), ":blossom:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb7"), ":tulip:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb1"), ":seedling:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb2"), ":evergreen_tree:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb3"), ":deciduous_tree:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb4"), ":palm_tree:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb5"), ":cactus:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xbe"), ":ear_of_rice:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8c\xbf"), ":herb:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x98\x98"), ":shamrock:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x80"), ":four_leaf_clover:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x81"), ":maple_leaf:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x82"), ":fallen_leaf:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x83"), ":leaves:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x84"), ":mushroom:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb0"), ":chestnut:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x8d"), ":earth_africa:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x8e"), ":earth_americas:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x8f"), ":earth_asia:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x91"), ":new_moon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x92"), ":waxing_crescent_moon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x93"), ":first_quarter_moon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x94"), ":waxing_gibbous_moon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x95"), ":full_moon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x96"), ":waning_gibbous_moon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x97"), ":last_quarter_moon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x98"), ":waning_crescent_moon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x99"), ":crescent_moon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x9a"), ":new_moon_with_face:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8c\x9b"), - ":first_quarter_moon_with_face:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8c\x9c"), - ":last_quarter_moon_with_face:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x98\x80"), ":sunny:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x9d"), ":full_moon_with_face:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x9e"), ":sun_with_face:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\xad\x90"), ":star:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x9f"), ":star2:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x98\x81"), ":cloud:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9b\x85"), ":partly_sunny:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9b\x88"), ":thunder_cloud_rain:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8c\xa4"), - ":white_sun_small_cloud:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xa5"), ":white_sun_cloud:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xa6"), ":white_sun_rain_cloud:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xa7"), ":cloud_rain:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xa8"), ":cloud_snow:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xa9"), ":cloud_lightning:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xaa"), ":cloud_tornado:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8c\xab"), ":fog:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xac"), ":wind_blowing_face:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x98\x82"), ":umbrella2:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x98\x94"), ":umbrella:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9a\xa1"), ":zap:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9d\x84"), ":snowflake:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x98\x83"), ":snowman2:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\x84"), ":snowman:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x98\x84"), ":comet:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\xa5"), ":fire:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xa7"), ":droplet:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x8a"), ":ocean:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x83"), ":jack_o_lantern:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x84"), ":christmas_tree:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9c\xa8"), ":sparkles:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x8b"), ":tanabata_tree:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x8d"), ":bamboo:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x99\x88"), ":see_no_evil:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x99\x89"), ":hear_no_evil:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x99\x8a"), ":speak_no_evil:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xa6"), ":sweat_drops:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xa8"), ":dash:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xb5"), ":monkey_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x92"), ":monkey:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x8d"), ":gorilla:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xb6"), ":dog:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x95"), ":dog2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xa9"), ":poodle:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xba"), ":wolf:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x8a"), ":fox:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xb1"), ":cat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x88"), ":cat2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x81"), ":lion_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xaf"), ":tiger:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x85"), ":tiger2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x86"), ":leopard:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xb4"), ":horse:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x8e"), ":racehorse:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x8c"), ":deer:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x84"), ":unicorn:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xae"), ":cow:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x82"), ":ox:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x83"), ":water_buffalo:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x84"), ":cow2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xb7"), ":pig:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x96"), ":pig2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x97"), ":boar:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xbd"), ":pig_nose:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x8f"), ":ram:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x91"), ":sheep:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x90"), ":goat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xaa"), ":dromedary_camel:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xab"), ":camel:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x98"), ":elephant:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x8f"), ":rhino:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xad"), ":mouse:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x81"), ":mouse2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x80"), ":rat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xb9"), ":hamster:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xb0"), ":rabbit:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x87"), ":rabbit2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xbf"), ":chipmunk:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x87"), ":bat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xbb"), ":bear:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xa8"), ":koala:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xbc"), ":panda_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xbe"), ":feet:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x83"), ":turkey:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x94"), ":chicken:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x93"), ":rooster:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xa3"), ":hatching_chick:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xa4"), ":baby_chick:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xa5"), ":hatched_chick:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xa6"), ":bird:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xa7"), ":penguin:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x8a"), ":dove:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x85"), ":eagle:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x86"), ":duck:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x89"), ":owl:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xb8"), ":frog:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x8a"), ":crocodile:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xa2"), ":turtle:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x8e"), ":lizard:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x8d"), ":snake:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xb2"), ":dragon_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x89"), ":dragon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xb3"), ":whale:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x8b"), ":whale2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xac"), ":dolphin:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x9f"), ":fish:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xa0"), ":tropical_fish:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\xa1"), ":blowfish:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x88"), ":shark:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x99"), ":octopus:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x9a"), ":shell:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x80"), ":crab:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x90"), ":shrimp:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x91"), ":squid:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x8b"), ":butterfly:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x8c"), ":snail:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x9b"), ":bug:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x9c"), ":ant:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x9d"), ":bee:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x90\x9e"), ":beetle:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xb7"), ":spider:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xb8"), ":spider_web:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa6\x82"), ":scorpion:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x90"), ":bouquet:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xb8"), ":cherry_blossom:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xb5"), ":rosette:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xb9"), ":rose:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x80"), ":wilted_rose:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xba"), ":hibiscus:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xbb"), ":sunflower:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xbc"), ":blossom:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xb7"), ":tulip:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xb1"), ":seedling:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xb2"), ":evergreen_tree:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xb3"), ":deciduous_tree:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xb4"), ":palm_tree:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xb5"), ":cactus:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xbe"), ":ear_of_rice:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xbf"), ":herb:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\x98"), ":shamrock:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x80"), ":four_leaf_clover:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x81"), ":maple_leaf:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x82"), ":fallen_leaf:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x83"), ":leaves:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x84"), ":mushroom:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xb0"), ":chestnut:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x8d"), ":earth_africa:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x8e"), ":earth_americas:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x8f"), ":earth_asia:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x91"), ":new_moon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x92"), ":waxing_crescent_moon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x93"), ":first_quarter_moon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x94"), ":waxing_gibbous_moon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x95"), ":full_moon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x96"), ":waning_gibbous_moon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x97"), ":last_quarter_moon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x98"), ":waning_crescent_moon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x99"), ":crescent_moon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x9a"), ":new_moon_with_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x9b"), ":first_quarter_moon_with_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x9c"), ":last_quarter_moon_with_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\x80"), ":sunny:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x9d"), ":full_moon_with_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x9e"), ":sun_with_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\xad\x90"), ":star:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x9f"), ":star2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\x81"), ":cloud:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\x85"), ":partly_sunny:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\x88"), ":thunder_cloud_rain:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xa4"), ":white_sun_small_cloud:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xa5"), ":white_sun_cloud:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xa6"), ":white_sun_rain_cloud:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xa7"), ":cloud_rain:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xa8"), ":cloud_snow:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xa9"), ":cloud_lightning:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xaa"), ":cloud_tornado:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xab"), ":fog:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xac"), ":wind_blowing_face:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\x82"), ":umbrella2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\x94"), ":umbrella:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9a\xa1"), ":zap:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9d\x84"), ":snowflake:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\x83"), ":snowman2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\x84"), ":snowman:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\x84"), ":comet:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xa5"), ":fire:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xa7"), ":droplet:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x8a"), ":ocean:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x83"), ":jack_o_lantern:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x84"), ":christmas_tree:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9c\xa8"), ":sparkles:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x8b"), ":tanabata_tree:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x8d"), ":bamboo:"}), }; const QVariantList EmojiModel::food = { - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x87"), ":grapes:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x88"), ":melon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x89"), ":watermelon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x8a"), ":tangerine:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x8b"), ":lemon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x8c"), ":banana:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x8d"), ":pineapple:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x8e"), ":apple:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x8f"), ":green_apple:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8d\x90"), ":pear:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x91"), ":peach:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x92"), ":cherries:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x93"), ":strawberry:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\xa5\x9d"), ":kiwi:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x85"), ":tomato:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x91"), ":avocado:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x86"), ":eggplant:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x94"), ":potato:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x95"), ":carrot:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8c\xbd"), ":corn:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xb6"), ":hot_pepper:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x92"), ":cucumber:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x9c"), ":peanuts:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x9e"), ":bread:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x90"), ":croissant:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x96"), ":french_bread:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x9e"), ":pancakes:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa7\x80"), ":cheese:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x96"), ":meat_on_bone:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x97"), ":poultry_leg:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x93"), ":bacon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x94"), ":hamburger:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x9f"), ":fries:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x95"), ":pizza:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xad"), ":hotdog:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8c\xae"), ":taco:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xaf"), ":burrito:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x99"), ":stuffed_flatbread:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\xa5\x9a"), ":egg:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb3"), ":cooking:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x98"), ":shallow_pan_of_food:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb2"), ":stew:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x97"), ":salad:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xbf"), ":popcorn:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb1"), ":bento:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x98"), ":rice_cracker:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x99"), ":rice_ball:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8d\x9a"), ":rice:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x9b"), ":curry:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x9c"), ":ramen:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\x9d"), ":spaghetti:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa0"), ":sweet_potato:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa2"), ":oden:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa3"), ":sushi:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa4"), ":fried_shrimp:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa5"), ":fish_cake:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa1"), ":dango:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa6"), ":icecream:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa7"), ":shaved_ice:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa8"), ":ice_cream:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xa9"), ":doughnut:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xaa"), ":cookie:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x82"), ":birthday:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb0"), ":cake:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xab"), ":chocolate_bar:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xac"), ":candy:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xad"), ":lollipop:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xae"), ":custard:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xaf"), ":honey_pot:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xbc"), ":baby_bottle:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\xa5\x9b"), ":milk:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x98\x95"), ":coffee:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb5"), ":tea:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb6"), ":sake:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xbe"), ":champagne:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb7"), ":wine_glass:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb8"), ":cocktail:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb9"), ":tropical_drink:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8d\xba"), ":beer:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xbb"), ":beers:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x82"), ":champagne_glass:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x83"), ":tumbler_glass:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xbd"), ":fork_knife_plate:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8d\xb4"), ":fork_and_knife:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x84"), ":spoon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x87"), ":grapes:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x88"), ":melon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x89"), ":watermelon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x8a"), ":tangerine:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x8b"), ":lemon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x8c"), ":banana:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x8d"), ":pineapple:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x8e"), ":apple:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x8f"), ":green_apple:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x90"), ":pear:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x91"), ":peach:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x92"), ":cherries:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x93"), ":strawberry:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x9d"), ":kiwi:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x85"), ":tomato:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x91"), ":avocado:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x86"), ":eggplant:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x94"), ":potato:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x95"), ":carrot:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xbd"), ":corn:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xb6"), ":hot_pepper:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x92"), ":cucumber:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x9c"), ":peanuts:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x9e"), ":bread:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x90"), ":croissant:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x96"), ":french_bread:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x9e"), ":pancakes:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa7\x80"), ":cheese:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x96"), ":meat_on_bone:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x97"), ":poultry_leg:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x93"), ":bacon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x94"), ":hamburger:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x9f"), ":fries:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x95"), ":pizza:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xad"), ":hotdog:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xae"), ":taco:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xaf"), ":burrito:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x99"), ":stuffed_flatbread:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x9a"), ":egg:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xb3"), ":cooking:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x98"), ":shallow_pan_of_food:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xb2"), ":stew:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x97"), ":salad:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xbf"), ":popcorn:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xb1"), ":bento:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x98"), ":rice_cracker:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x99"), ":rice_ball:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x9a"), ":rice:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x9b"), ":curry:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x9c"), ":ramen:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\x9d"), ":spaghetti:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xa0"), ":sweet_potato:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xa2"), ":oden:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xa3"), ":sushi:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xa4"), ":fried_shrimp:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xa5"), ":fish_cake:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xa1"), ":dango:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xa6"), ":icecream:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xa7"), ":shaved_ice:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xa8"), ":ice_cream:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xa9"), ":doughnut:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xaa"), ":cookie:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x82"), ":birthday:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xb0"), ":cake:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xab"), ":chocolate_bar:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xac"), ":candy:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xad"), ":lollipop:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xae"), ":custard:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xaf"), ":honey_pot:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xbc"), ":baby_bottle:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x9b"), ":milk:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\x95"), ":coffee:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xb5"), ":tea:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xb6"), ":sake:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xbe"), ":champagne:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xb7"), ":wine_glass:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xb8"), ":cocktail:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xb9"), ":tropical_drink:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xba"), ":beer:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xbb"), ":beers:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x82"), ":champagne_glass:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x83"), ":tumbler_glass:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xbd"), ":fork_knife_plate:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8d\xb4"), ":fork_and_knife:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x84"), ":spoon:"}), }; const QVariantList EmojiModel::activity = { - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\xbe"), ":space_invader:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb4"), ":levitate:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xba"), ":fencer:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x87"), ":horse_racing:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbb"), - ":horse_racing_tone1:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbc"), - ":horse_racing_tone2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbd"), - ":horse_racing_tone3:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbe"), - ":horse_racing_tone4:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbf"), - ":horse_racing_tone5:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\xb7"), ":skier:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x82"), ":snowboarder:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8c"), ":golfer:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84"), ":surfer:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbb"), - ":surfer_tone1:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbc"), - ":surfer_tone2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbd"), - ":surfer_tone3:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbe"), - ":surfer_tone4:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbf"), - ":surfer_tone5:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3"), ":rowboat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbb"), - ":rowboat_tone1:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbc"), - ":rowboat_tone2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbd"), - ":rowboat_tone3:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbe"), - ":rowboat_tone4:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbf"), - ":rowboat_tone5:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a"), ":swimmer:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbb"), - ":swimmer_tone1:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbc"), - ":swimmer_tone2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbd"), - ":swimmer_tone3:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbe"), - ":swimmer_tone4:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbf"), - ":swimmer_tone5:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9b\xb9"), ":basketball_player:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbb"), - ":basketball_player_tone1:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbc"), - ":basketball_player_tone2:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbd"), - ":basketball_player_tone3:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbe"), - ":basketball_player_tone4:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbf"), - ":basketball_player_tone5:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b"), ":lifter:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbb"), - ":lifter_tone1:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbc"), - ":lifter_tone2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbd"), - ":lifter_tone3:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbe"), - ":lifter_tone4:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbf"), - ":lifter_tone5:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4"), ":bicyclist:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbb"), - ":bicyclist_tone1:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbc"), - ":bicyclist_tone2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbd"), - ":bicyclist_tone3:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbe"), - ":bicyclist_tone4:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbf"), - ":bicyclist_tone5:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5"), ":mountain_bicyclist:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbb"), - ":mountain_bicyclist_tone1:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbc"), - ":mountain_bicyclist_tone2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbd"), - ":mountain_bicyclist_tone3:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbe"), - ":mountain_bicyclist_tone4:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbf"), - ":mountain_bicyclist_tone5:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8"), ":cartwheel:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbb"), - ":cartwheel_tone1:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbc"), - ":cartwheel_tone2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbd"), - ":cartwheel_tone3:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbe"), - ":cartwheel_tone4:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbf"), - ":cartwheel_tone5:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbc"), ":wrestlers:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbc\xf0\x9f\x8f\xbb"), - ":wrestlers_tone1:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbc\xf0\x9f\x8f\xbc"), - ":wrestlers_tone2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbc\xf0\x9f\x8f\xbd"), - ":wrestlers_tone3:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbc\xf0\x9f\x8f\xbe"), - ":wrestlers_tone4:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbc\xf0\x9f\x8f\xbf"), - ":wrestlers_tone5:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd"), ":water_polo:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbb"), - ":water_polo_tone1:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbc"), - ":water_polo_tone2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbd"), - ":water_polo_tone3:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbe"), - ":water_polo_tone4:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbf"), - ":water_polo_tone5:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe"), ":handball:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbb"), - ":handball_tone1:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbc"), - ":handball_tone2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbd"), - ":handball_tone3:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbe"), - ":handball_tone4:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbf"), - ":handball_tone5:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9"), ":juggling:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbb"), - ":juggling_tone1:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbc"), - ":juggling_tone2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbd"), - ":juggling_tone3:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbe"), - ":juggling_tone4:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbf"), - ":juggling_tone5:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xaa"), ":circus_tent:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xad"), ":performing_arts:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa8"), ":art:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb0"), ":slot_machine:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x9b\x80"), ":bath:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbb"), ":bath_tone1:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbc"), ":bath_tone2:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbd"), ":bath_tone3:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbe"), ":bath_tone4:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbf"), ":bath_tone5:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x97"), ":reminder_ribbon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x9f"), ":tickets:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xab"), ":ticket:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x96"), ":military_medal:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x86"), ":trophy:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x85"), ":medal:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x87"), ":first_place:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x88"), ":second_place:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x89"), ":third_place:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9a\xbd"), ":soccer:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9a\xbe"), ":baseball:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x80"), ":basketball:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x90"), ":volleyball:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x88"), ":football:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x89"), ":rugby_football:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xbe"), ":tennis:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb1"), ":8ball:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb3"), ":bowling:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8f"), ":cricket:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x91"), ":field_hockey:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x92"), ":hockey:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x93"), ":ping_pong:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb8"), ":badminton:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x8a"), ":boxing_glove:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\xa5\x8b"), ":martial_arts_uniform:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\xa5\x85"), ":goal:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8e\xaf"), ":dart:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\xb3"), ":golf:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9b\xb8"), ":ice_skate:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa3"), - ":fishing_pole_and_fish:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8e\xbd"), - ":running_shirt_with_sash:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8e\xbf"), ":ski:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xae"), ":video_game:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb2"), ":game_die:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xbc"), ":musical_score:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa4"), ":microphone:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa7"), ":headphones:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb7"), ":saxophone:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb8"), ":guitar:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb9"), ":musical_keyboard:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xba"), ":trumpet:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xbb"), ":violin:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\xa5\x81"), ":drum:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xac"), ":clapper:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb9"), ":bow_and_arrow:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\xbe"), ":space_invader:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xb4"), ":levitate:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xba"), ":fencer:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x87"), ":horse_racing:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbb"), ":horse_racing_tone1:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbc"), ":horse_racing_tone2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbd"), ":horse_racing_tone3:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbe"), ":horse_racing_tone4:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x87\xf0\x9f\x8f\xbf"), ":horse_racing_tone5:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xb7"), ":skier:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x82"), ":snowboarder:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x8c"), ":golfer:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x84"), ":surfer:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbb"), ":surfer_tone1:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbc"), ":surfer_tone2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbd"), ":surfer_tone3:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbe"), ":surfer_tone4:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x84\xf0\x9f\x8f\xbf"), ":surfer_tone5:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xa3"), ":rowboat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbb"), ":rowboat_tone1:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbc"), ":rowboat_tone2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbd"), ":rowboat_tone3:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbe"), ":rowboat_tone4:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xa3\xf0\x9f\x8f\xbf"), ":rowboat_tone5:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x8a"), ":swimmer:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbb"), ":swimmer_tone1:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbc"), ":swimmer_tone2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbd"), ":swimmer_tone3:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbe"), ":swimmer_tone4:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x8a\xf0\x9f\x8f\xbf"), ":swimmer_tone5:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xb9"), ":basketball_player:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbb"), ":basketball_player_tone1:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbc"), ":basketball_player_tone2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbd"), ":basketball_player_tone3:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbe"), ":basketball_player_tone4:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xb9\xf0\x9f\x8f\xbf"), ":basketball_player_tone5:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x8b"), ":lifter:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbb"), ":lifter_tone1:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbc"), ":lifter_tone2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbd"), ":lifter_tone3:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbe"), ":lifter_tone4:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x8b\xf0\x9f\x8f\xbf"), ":lifter_tone5:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb4"), ":bicyclist:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbb"), ":bicyclist_tone1:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbc"), ":bicyclist_tone2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbd"), ":bicyclist_tone3:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbe"), ":bicyclist_tone4:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb4\xf0\x9f\x8f\xbf"), ":bicyclist_tone5:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb5"), ":mountain_bicyclist:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbb"), ":mountain_bicyclist_tone1:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbc"), ":mountain_bicyclist_tone2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbd"), ":mountain_bicyclist_tone3:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbe"), ":mountain_bicyclist_tone4:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb5\xf0\x9f\x8f\xbf"), ":mountain_bicyclist_tone5:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb8"), ":cartwheel:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbb"), ":cartwheel_tone1:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbc"), ":cartwheel_tone2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbd"), ":cartwheel_tone3:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbe"), ":cartwheel_tone4:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb8\xf0\x9f\x8f\xbf"), ":cartwheel_tone5:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbc"), ":wrestlers:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbc\xf0\x9f\x8f\xbb"), ":wrestlers_tone1:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbc\xf0\x9f\x8f\xbc"), ":wrestlers_tone2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbc\xf0\x9f\x8f\xbd"), ":wrestlers_tone3:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbc\xf0\x9f\x8f\xbe"), ":wrestlers_tone4:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbc\xf0\x9f\x8f\xbf"), ":wrestlers_tone5:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbd"), ":water_polo:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbb"), ":water_polo_tone1:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbc"), ":water_polo_tone2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbd"), ":water_polo_tone3:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbe"), ":water_polo_tone4:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbd\xf0\x9f\x8f\xbf"), ":water_polo_tone5:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbe"), ":handball:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbb"), ":handball_tone1:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbc"), ":handball_tone2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbd"), ":handball_tone3:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbe"), ":handball_tone4:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xbe\xf0\x9f\x8f\xbf"), ":handball_tone5:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb9"), ":juggling:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbb"), ":juggling_tone1:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbc"), ":juggling_tone2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbd"), ":juggling_tone3:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbe"), ":juggling_tone4:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa4\xb9\xf0\x9f\x8f\xbf"), ":juggling_tone5:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xaa"), ":circus_tent:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xad"), ":performing_arts:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xa8"), ":art:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xb0"), ":slot_machine:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x80"), ":bath:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbb"), ":bath_tone1:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbc"), ":bath_tone2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbd"), ":bath_tone3:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbe"), ":bath_tone4:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x80\xf0\x9f\x8f\xbf"), ":bath_tone5:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x97"), ":reminder_ribbon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x9f"), ":tickets:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xab"), ":ticket:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x96"), ":military_medal:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x86"), ":trophy:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x85"), ":medal:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x87"), ":first_place:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x88"), ":second_place:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x89"), ":third_place:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9a\xbd"), ":soccer:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9a\xbe"), ":baseball:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x80"), ":basketball:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x90"), ":volleyball:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x88"), ":football:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x89"), ":rugby_football:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xbe"), ":tennis:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xb1"), ":8ball:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xb3"), ":bowling:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x8f"), ":cricket:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x91"), ":field_hockey:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x92"), ":hockey:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x93"), ":ping_pong:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xb8"), ":badminton:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x8a"), ":boxing_glove:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x8b"), ":martial_arts_uniform:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x85"), ":goal:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xaf"), ":dart:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xb3"), ":golf:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xb8"), ":ice_skate:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xa3"), ":fishing_pole_and_fish:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xbd"), ":running_shirt_with_sash:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xbf"), ":ski:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xae"), ":video_game:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xb2"), ":game_die:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xbc"), ":musical_score:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xa4"), ":microphone:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xa7"), ":headphones:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xb7"), ":saxophone:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xb8"), ":guitar:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xb9"), ":musical_keyboard:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xba"), ":trumpet:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xbb"), ":violin:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\xa5\x81"), ":drum:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xac"), ":clapper:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xb9"), ":bow_and_arrow:"}), }; const QVariantList EmojiModel::travel = { - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8e"), ":race_car:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x8d"), ":motorcycle:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\xbe"), ":japan:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x94"), ":mountain_snow:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\xb0"), ":mountain:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x8b"), ":volcano:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\xbb"), ":mount_fuji:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x95"), ":camping:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x96"), ":beach:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x9c"), ":desert:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x9d"), ":island:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8f\x9e"), ":park:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x9f"), ":stadium:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x9b"), ":classical_building:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x97"), ":construction_site:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x98"), ":homes:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x99"), ":cityscape:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x9a"), ":house_abandoned:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa0"), ":house:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa1"), ":house_with_garden:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa2"), ":office:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa3"), ":post_office:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa4"), ":european_post_office:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa5"), ":hospital:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa6"), ":bank:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa8"), ":hotel:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa9"), ":love_hotel:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xaa"), ":convenience_store:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xab"), ":school:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xac"), ":department_store:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xad"), ":factory:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xaf"), ":japanese_castle:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb0"), ":european_castle:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x92"), ":wedding:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\xbc"), ":tokyo_tower:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\xbd"), ":statue_of_liberty:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\xaa"), ":church:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x8c"), ":mosque:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x8d"), ":synagogue:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9b\xa9"), ":shinto_shrine:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x8b"), ":kaaba:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\xb2"), ":fountain:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\xba"), ":tent:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x81"), ":foggy:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x83"), ":night_with_stars:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8c\x84"), - ":sunrise_over_mountains:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x85"), ":sunrise:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x86"), ":city_dusk:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x87"), ":city_sunset:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x89"), ":bridge_at_night:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x8c"), ":milky_way:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa0"), ":carousel_horse:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa1"), ":ferris_wheel:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa2"), ":roller_coaster:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x82"), ":steam_locomotive:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x83"), ":railway_car:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x84"), ":bullettrain_side:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x85"), ":bullettrain_front:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x86"), ":train2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x87"), ":metro:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x88"), ":light_rail:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x89"), ":station:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x9a\x8a"), ":tram:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x9d"), ":monorail:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x9e"), ":mountain_railway:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x8b"), ":train:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x9a\x8c"), ":bus:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x8d"), ":oncoming_bus:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x8e"), ":trolleybus:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x90"), ":minibus:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x91"), ":ambulance:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x92"), ":fire_engine:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x93"), ":police_car:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x94"), ":oncoming_police_car:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x9a\x95"), ":taxi:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x96"), ":oncoming_taxi:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x97"), ":red_car:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x98"), ":oncoming_automobile:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x99"), ":blue_car:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x9a"), ":truck:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x9b"), ":articulated_lorry:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x9c"), ":tractor:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb2"), ":bike:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xb4"), ":scooter:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xb5"), ":motor_scooter:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x8f"), ":busstop:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xa3"), ":motorway:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xa4"), ":railway_track:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\xbd"), ":fuelpump:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa8"), ":rotating_light:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa5"), ":traffic_light:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa6"), - ":vertical_traffic_light:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa7"), ":construction:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9a\x93"), ":anchor:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\xb5"), ":sailboat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xb6"), ":canoe:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa4"), ":speedboat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xb3"), ":cruise_ship:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\xb4"), ":ferry:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xa5"), ":motorboat:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa2"), ":ship:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9c\x88"), ":airplane:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xa9"), ":airplane_small:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xab"), ":airplane_departure:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xac"), ":airplane_arriving:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x92\xba"), ":seat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x81"), ":helicopter:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x9f"), ":suspension_railway:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa0"), ":mountain_cableway:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa1"), ":aerial_tramway:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\x80"), ":rocket:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xb0"), ":satellite_orbital:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xa0"), ":stars:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x88"), ":rainbow:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x86"), ":fireworks:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x87"), ":sparkler:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x91"), ":rice_scene:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\x81"), ":checkered_flag:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x8e"), ":race_car:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x8d"), ":motorcycle:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\xbe"), ":japan:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x94"), ":mountain_snow:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xb0"), ":mountain:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x8b"), ":volcano:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\xbb"), ":mount_fuji:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x95"), ":camping:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x96"), ":beach:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x9c"), ":desert:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x9d"), ":island:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x9e"), ":park:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x9f"), ":stadium:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x9b"), ":classical_building:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x97"), ":construction_site:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x98"), ":homes:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x99"), ":cityscape:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x9a"), ":house_abandoned:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xa0"), ":house:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xa1"), ":house_with_garden:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xa2"), ":office:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xa3"), ":post_office:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xa4"), ":european_post_office:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xa5"), ":hospital:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xa6"), ":bank:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xa8"), ":hotel:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xa9"), ":love_hotel:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xaa"), ":convenience_store:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xab"), ":school:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xac"), ":department_store:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xad"), ":factory:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xaf"), ":japanese_castle:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xb0"), ":european_castle:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x92"), ":wedding:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\xbc"), ":tokyo_tower:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\xbd"), ":statue_of_liberty:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xaa"), ":church:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x8c"), ":mosque:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x8d"), ":synagogue:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xa9"), ":shinto_shrine:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x8b"), ":kaaba:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xb2"), ":fountain:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xba"), ":tent:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x81"), ":foggy:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x83"), ":night_with_stars:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x84"), ":sunrise_over_mountains:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x85"), ":sunrise:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x86"), ":city_dusk:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x87"), ":city_sunset:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x89"), ":bridge_at_night:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x8c"), ":milky_way:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xa0"), ":carousel_horse:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xa1"), ":ferris_wheel:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xa2"), ":roller_coaster:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x82"), ":steam_locomotive:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x83"), ":railway_car:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x84"), ":bullettrain_side:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x85"), ":bullettrain_front:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x86"), ":train2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x87"), ":metro:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x88"), ":light_rail:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x89"), ":station:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x8a"), ":tram:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x9d"), ":monorail:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x9e"), ":mountain_railway:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x8b"), ":train:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x8c"), ":bus:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x8d"), ":oncoming_bus:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x8e"), ":trolleybus:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x90"), ":minibus:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x91"), ":ambulance:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x92"), ":fire_engine:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x93"), ":police_car:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x94"), ":oncoming_police_car:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x95"), ":taxi:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x96"), ":oncoming_taxi:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x97"), ":red_car:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x98"), ":oncoming_automobile:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x99"), ":blue_car:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x9a"), ":truck:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x9b"), ":articulated_lorry:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x9c"), ":tractor:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb2"), ":bike:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\xb4"), ":scooter:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\xb5"), ":motor_scooter:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x8f"), ":busstop:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\xa3"), ":motorway:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\xa4"), ":railway_track:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xbd"), ":fuelpump:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xa8"), ":rotating_light:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xa5"), ":traffic_light:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xa6"), ":vertical_traffic_light:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xa7"), ":construction:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9a\x93"), ":anchor:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xb5"), ":sailboat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\xb6"), ":canoe:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xa4"), ":speedboat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\xb3"), ":cruise_ship:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xb4"), ":ferry:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\xa5"), ":motorboat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xa2"), ":ship:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9c\x88"), ":airplane:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\xa9"), ":airplane_small:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\xab"), ":airplane_departure:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\xac"), ":airplane_arriving:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xba"), ":seat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x81"), ":helicopter:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x9f"), ":suspension_railway:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xa0"), ":mountain_cableway:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xa1"), ":aerial_tramway:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\x80"), ":rocket:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\xb0"), ":satellite_orbital:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xa0"), ":stars:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x88"), ":rainbow:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x86"), ":fireworks:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x87"), ":sparkler:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x91"), ":rice_scene:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\x81"), ":checkered_flag:"}), }; const QVariantList EmojiModel::objects = { - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x98\xa0"), ":skull_crossbones:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x8c"), ":love_letter:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x92\xa3"), ":bomb:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x95\xb3"), ":hole:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x8d"), ":shopping_bags:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xbf"), ":prayer_beads:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x92\x8e"), ":gem:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xaa"), ":knife:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xba"), ":amphora:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x97\xba"), ":map:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x88"), ":barber:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x96\xbc"), ":frame_photo:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x8e"), ":bellhop:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x9a\xaa"), ":door:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x9b\x8c"), - ":sleeping_accommodation:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x9b\x8f"), ":bed:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x8b"), ":couch:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xbd"), ":toilet:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xbf"), ":shower:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x81"), ":bathtub:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x8c\x9b"), ":hourglass:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x8f\xb3"), ":hourglass_flowing_sand:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x8c\x9a"), ":watch:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x8f\xb0"), ":alarm_clock:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x8f\xb1"), ":stopwatch:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x8f\xb2"), ":timer:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb0"), ":clock:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\xa1"), ":thermometer:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9b\xb1"), ":beach_umbrella:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x88"), ":balloon:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8e\x89"), ":tada:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x8a"), ":confetti_ball:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x8e"), ":dolls:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x8f"), ":flags:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x90"), ":wind_chime:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x80"), ":ribbon:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8e\x81"), ":gift:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\xb9"), ":joystick:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xaf"), ":postal_horn:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x99"), ":microphone2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x9a"), ":level_slider:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x9b"), ":control_knobs:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xbb"), ":radio:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb1"), ":iphone:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb2"), ":calling:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x98\x8e"), ":telephone:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x9e"), ":telephone_receiver:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x9f"), ":pager:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x93\xa0"), ":fax:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x8b"), ":battery:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x8c"), ":electric_plug:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xbb"), ":computer:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x96\xa5"), ":desktop:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x96\xa8"), ":printer:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x8c\xa8"), ":keyboard:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x96\xb1"), ":mouse_three_button:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x96\xb2"), ":trackball:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xbd"), ":minidisc:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xbe"), ":floppy_disk:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x92\xbf"), ":cd:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x93\x80"), ":dvd:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa5"), ":movie_camera:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x9e"), ":film_frames:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xbd"), ":projector:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x93\xba"), ":tv:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb7"), ":camera:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb8"), ":camera_with_flash:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb9"), ":video_camera:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x93\xbc"), ":vhs:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\x8d"), ":mag:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x8e"), ":mag_right:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xac"), ":microscope:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xad"), ":telescope:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa1"), ":satellite:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\xaf"), ":candle:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x92\xa1"), ":bulb:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xa6"), ":flashlight:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xae"), ":izakaya_lantern:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x93\x94"), - ":notebook_with_decorative_cover:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x95"), ":closed_book:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x93\x96"), ":book:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x97"), ":green_book:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x98"), ":blue_book:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x99"), ":orange_book:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x9a"), ":books:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x93"), ":notebook:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x92"), ":ledger:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x83"), ":page_with_curl:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x9c"), ":scroll:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x84"), ":page_facing_up:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb0"), ":newspaper:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\x9e"), ":newspaper2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x91"), ":bookmark_tabs:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x96"), ":bookmark:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb7"), ":label:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb0"), ":moneybag:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x92\xb4"), ":yen:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb5"), ":dollar:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x92\xb6"), ":euro:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb7"), ":pound:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb8"), ":money_with_wings:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb3"), ":credit_card:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9c\x89"), ":envelope:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa7"), ":e-mail:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa8"), ":incoming_envelope:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa9"), ":envelope_with_arrow:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa4"), ":outbox_tray:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa5"), ":inbox_tray:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa6"), ":package:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xab"), ":mailbox:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xaa"), ":mailbox_closed:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xac"), ":mailbox_with_mail:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xad"), ":mailbox_with_no_mail:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xae"), ":postbox:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\xb3"), ":ballot_box:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9c\x8f"), ":pencil2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9c\x92"), ":black_nib:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x96\x8b"), ":pen_fountain:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x96\x8a"), ":pen_ballpoint:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x96\x8c"), ":paintbrush:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x96\x8d"), ":crayon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x9d"), ":pencil:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x81"), ":file_folder:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x82"), ":open_file_folder:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\x82"), ":dividers:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x93\x85"), ":date:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x86"), ":calendar:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\x92"), ":notepad_spiral:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\x93"), ":calendar_spiral:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x87"), ":card_index:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x93\x88"), - ":chart_with_upwards_trend:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x93\x89"), - ":chart_with_downwards_trend:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x8a"), ":bar_chart:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x8b"), ":clipboard:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x8c"), ":pushpin:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x8d"), ":round_pushpin:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x8e"), ":paperclip:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x96\x87"), ":paperclips:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x8f"), ":straight_ruler:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x90"), ":triangular_ruler:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9c\x82"), ":scissors:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\x83"), ":card_box:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\x84"), ":file_cabinet:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\x91"), ":wastebasket:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\x92"), ":lock:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x93"), ":unlock:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x8f"), ":lock_with_ink_pen:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x90"), ":closed_lock_with_key:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\x91"), ":key:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x97\x9d"), ":key2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xa8"), ":hammer:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\x8f"), ":pick:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9a\x92"), ":hammer_pick:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xa0"), ":tools:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\xa1"), ":dagger:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9a\x94"), ":crossed_swords:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\xab"), ":gun:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\xa1"), ":shield:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xa7"), ":wrench:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xa9"), ":nut_and_bolt:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9a\x99"), ":gear:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\x9c"), ":compression:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9a\x97"), ":alembic:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9a\x96"), ":scales:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\x97"), ":link:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\x93"), ":chains:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x89"), ":syringe:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x92\x8a"), ":pill:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xac"), ":smoking:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9a\xb0"), ":coffin:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9a\xb1"), ":urn:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\xbf"), ":moyai:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x9b\xa2"), ":oil:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xae"), ":crystal_ball:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x92"), ":shopping_cart:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x9a\xa9"), - ":triangular_flag_on_post:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\x8c"), ":crossed_flags:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb4"), ":flag_black:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb3"), ":flag_white:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8f\xb3\xf0\x9f\x8c\x88"), - ":rainbow_flag:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\xa0"), ":skull_crossbones:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x8c"), ":love_letter:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xa3"), ":bomb:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xb3"), ":hole:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x8d"), ":shopping_bags:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xbf"), ":prayer_beads:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x8e"), ":gem:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xaa"), ":knife:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xba"), ":amphora:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\xba"), ":map:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x88"), ":barber:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x96\xbc"), ":frame_photo:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x8e"), ":bellhop:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xaa"), ":door:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x8c"), ":sleeping_accommodation:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x8f"), ":bed:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x8b"), ":couch:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xbd"), ":toilet:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xbf"), ":shower:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x81"), ":bathtub:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8c\x9b"), ":hourglass:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8f\xb3"), ":hourglass_flowing_sand:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8c\x9a"), ":watch:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8f\xb0"), ":alarm_clock:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8f\xb1"), ":stopwatch:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8f\xb2"), ":timer:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xb0"), ":clock:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\xa1"), ":thermometer:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\xb1"), ":beach_umbrella:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x88"), ":balloon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x89"), ":tada:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x8a"), ":confetti_ball:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x8e"), ":dolls:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x8f"), ":flags:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x90"), ":wind_chime:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x80"), ":ribbon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x81"), ":gift:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xb9"), ":joystick:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xaf"), ":postal_horn:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x99"), ":microphone2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x9a"), ":level_slider:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x9b"), ":control_knobs:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xbb"), ":radio:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xb1"), ":iphone:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xb2"), ":calling:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\x8e"), ":telephone:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x9e"), ":telephone_receiver:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x9f"), ":pager:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xa0"), ":fax:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x8b"), ":battery:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x8c"), ":electric_plug:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xbb"), ":computer:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x96\xa5"), ":desktop:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x96\xa8"), ":printer:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8c\xa8"), ":keyboard:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x96\xb1"), ":mouse_three_button:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x96\xb2"), ":trackball:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xbd"), ":minidisc:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xbe"), ":floppy_disk:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xbf"), ":cd:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x80"), ":dvd:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xa5"), ":movie_camera:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x9e"), ":film_frames:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xbd"), ":projector:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xba"), ":tv:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xb7"), ":camera:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xb8"), ":camera_with_flash:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xb9"), ":video_camera:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xbc"), ":vhs:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x8d"), ":mag:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x8e"), ":mag_right:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xac"), ":microscope:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xad"), ":telescope:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xa1"), ":satellite:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xaf"), ":candle:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xa1"), ":bulb:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xa6"), ":flashlight:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xae"), ":izakaya_lantern:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x94"), ":notebook_with_decorative_cover:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x95"), ":closed_book:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x96"), ":book:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x97"), ":green_book:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x98"), ":blue_book:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x99"), ":orange_book:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x9a"), ":books:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x93"), ":notebook:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x92"), ":ledger:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x83"), ":page_with_curl:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x9c"), ":scroll:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x84"), ":page_facing_up:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xb0"), ":newspaper:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\x9e"), ":newspaper2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x91"), ":bookmark_tabs:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x96"), ":bookmark:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xb7"), ":label:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xb0"), ":moneybag:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xb4"), ":yen:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xb5"), ":dollar:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xb6"), ":euro:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xb7"), ":pound:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xb8"), ":money_with_wings:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xb3"), ":credit_card:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9c\x89"), ":envelope:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xa7"), ":e-mail:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xa8"), ":incoming_envelope:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xa9"), ":envelope_with_arrow:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xa4"), ":outbox_tray:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xa5"), ":inbox_tray:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xa6"), ":package:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xab"), ":mailbox:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xaa"), ":mailbox_closed:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xac"), ":mailbox_with_mail:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xad"), ":mailbox_with_no_mail:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xae"), ":postbox:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\xb3"), ":ballot_box:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9c\x8f"), ":pencil2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9c\x92"), ":black_nib:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x96\x8b"), ":pen_fountain:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x96\x8a"), ":pen_ballpoint:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x96\x8c"), ":paintbrush:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x96\x8d"), ":crayon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x9d"), ":pencil:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x81"), ":file_folder:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x82"), ":open_file_folder:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\x82"), ":dividers:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x85"), ":date:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x86"), ":calendar:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\x92"), ":notepad_spiral:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\x93"), ":calendar_spiral:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x87"), ":card_index:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x88"), ":chart_with_upwards_trend:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x89"), ":chart_with_downwards_trend:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x8a"), ":bar_chart:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x8b"), ":clipboard:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x8c"), ":pushpin:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x8d"), ":round_pushpin:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x8e"), ":paperclip:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x96\x87"), ":paperclips:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x8f"), ":straight_ruler:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x90"), ":triangular_ruler:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9c\x82"), ":scissors:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\x83"), ":card_box:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\x84"), ":file_cabinet:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\x91"), ":wastebasket:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x92"), ":lock:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x93"), ":unlock:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x8f"), ":lock_with_ink_pen:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x90"), ":closed_lock_with_key:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x91"), ":key:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\x9d"), ":key2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xa8"), ":hammer:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\x8f"), ":pick:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9a\x92"), ":hammer_pick:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\xa0"), ":tools:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\xa1"), ":dagger:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9a\x94"), ":crossed_swords:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xab"), ":gun:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\xa1"), ":shield:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xa7"), ":wrench:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xa9"), ":nut_and_bolt:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9a\x99"), ":gear:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\x9c"), ":compression:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9a\x97"), ":alembic:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9a\x96"), ":scales:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x97"), ":link:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\x93"), ":chains:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x89"), ":syringe:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x8a"), ":pill:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xac"), ":smoking:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9a\xb0"), ":coffin:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9a\xb1"), ":urn:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\xbf"), ":moyai:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\xa2"), ":oil:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xae"), ":crystal_ball:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x92"), ":shopping_cart:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xa9"), ":triangular_flag_on_post:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\x8c"), ":crossed_flags:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xb4"), ":flag_black:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xb3"), ":flag_white:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xb3\xf0\x9f\x8c\x88"), ":rainbow_flag:"}), }; const QVariantList EmojiModel::symbols = { - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x91\x81\xf0\x9f\x97\xa8"), - ":eye_in_speech_bubble:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x98"), ":cupid:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9d\xa4"), ":heart:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x93"), ":heartbeat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x94"), ":broken_heart:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x95"), ":two_hearts:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x96"), ":sparkling_heart:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x97"), ":heartpulse:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x99"), ":blue_heart:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x9a"), ":green_heart:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x9b"), ":yellow_heart:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x9c"), ":purple_heart:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x96\xa4"), ":black_heart:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x9d"), ":gift_heart:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x9e"), ":revolving_hearts:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\x9f"), ":heart_decoration:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9d\xa3"), ":heart_exclamation:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xa2"), ":anger:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x92\xa5"), ":boom:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xab"), ":dizzy:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xac"), ":speech_balloon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\xa8"), ":speech_left:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x97\xaf"), ":anger_right:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xad"), ":thought_balloon:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xae"), ":white_flower:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x90"), ":globe_with_meridians:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x99\xa8"), ":hotsprings:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x91"), ":octagonal_sign:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x9b"), ":clock12:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\xa7"), ":clock1230:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x90"), ":clock1:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x9c"), ":clock130:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x91"), ":clock2:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x9d"), ":clock230:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x92"), ":clock3:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x9e"), ":clock330:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x93"), ":clock4:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x9f"), ":clock430:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x94"), ":clock5:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\xa0"), ":clock530:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x95"), ":clock6:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\xa1"), ":clock630:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x96"), ":clock7:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\xa2"), ":clock730:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x97"), ":clock8:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\xa3"), ":clock830:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x98"), ":clock9:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\xa4"), ":clock930:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x99"), ":clock10:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\xa5"), ":clock1030:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x9a"), ":clock11:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\xa6"), ":clock1130:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8c\x80"), ":cyclone:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x99\xa0"), ":spades:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x99\xa5"), ":hearts:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x99\xa6"), ":diamonds:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x99\xa3"), ":clubs:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x83\x8f"), ":black_joker:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x80\x84"), ":mahjong:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb4"), ":flower_playing_cards:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\x87"), ":mute:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x88"), ":speaker:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x89"), ":sound:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x8a"), ":loud_sound:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xa2"), ":loudspeaker:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x93\xa3"), ":mega:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\x94"), ":bell:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x95"), ":no_bell:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb5"), ":musical_note:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xb6"), ":notes:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb9"), ":chart:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb1"), ":currency_exchange:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x92\xb2"), ":heavy_dollar_sign:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x8f\xa7"), ":atm:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x9a\xae"), - ":put_litter_in_its_place:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb0"), ":potable_water:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x99\xbf"), ":wheelchair:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb9"), ":mens:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xba"), ":womens:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xbb"), ":restroom:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xbc"), ":baby_symbol:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x9a\xbe"), ":wc:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x82"), ":passport_control:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x83"), ":customs:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x84"), ":baggage_claim:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x85"), ":left_luggage:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9a\xa0"), ":warning:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb8"), ":children_crossing:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9b\x94"), ":no_entry:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xab"), ":no_entry_sign:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb3"), ":no_bicycles:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xad"), ":no_smoking:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xaf"), ":do_not_litter:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb1"), ":non-potable_water:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9a\xb7"), ":no_pedestrians:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb5"), ":no_mobile_phones:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x9e"), ":underage:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x98\xa2"), ":radioactive:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x98\xa3"), ":biohazard:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\xac\x86"), ":arrow_up:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x86\x97"), ":arrow_upper_right:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9e\xa1"), ":arrow_right:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x86\x98"), ":arrow_lower_right:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\xac\x87"), ":arrow_down:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x86\x99"), ":arrow_lower_left:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\xac\x85"), ":arrow_left:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x86\x96"), ":arrow_upper_left:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x86\x95"), ":arrow_up_down:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x86\x94"), ":left_right_arrow:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x86\xa9"), - ":leftwards_arrow_with_hook:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x86\xaa"), ":arrow_right_hook:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\xa4\xb4"), ":arrow_heading_up:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\xa4\xb5"), ":arrow_heading_down:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x83"), ":arrows_clockwise:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\x84"), - ":arrows_counterclockwise:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\x99"), ":back:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\x9a"), ":end:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\x9b"), ":on:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\x9c"), ":soon:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\x9d"), ":top:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x9b\x90"), ":place_of_worship:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9a\x9b"), ":atom:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x89"), ":om_symbol:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9c\xa1"), ":star_of_david:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x98\xb8"), ":wheel_of_dharma:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x98\xaf"), ":yin_yang:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9c\x9d"), ":cross:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x98\xa6"), ":orthodox_cross:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x98\xaa"), ":star_and_crescent:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x98\xae"), ":peace:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x95\x8e"), ":menorah:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xaf"), ":six_pointed_star:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x99\x88"), ":aries:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x99\x89"), ":taurus:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x99\x8a"), ":gemini:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x99\x8b"), ":cancer:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x99\x8c"), ":leo:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x99\x8d"), ":virgo:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x99\x8e"), ":libra:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x99\x8f"), ":scorpius:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x99\x90"), ":sagittarius:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x99\x91"), ":capricorn:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x99\x92"), ":aquarius:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x99\x93"), ":pisces:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9b\x8e"), ":ophiuchus:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\x80"), - ":twisted_rightwards_arrows:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x81"), ":repeat:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x82"), ":repeat_one:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x96\xb6"), ":arrow_forward:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x8f\xa9"), ":fast_forward:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x8f\xad"), ":track_next:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x8f\xaf"), ":play_pause:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x97\x80"), ":arrow_backward:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x8f\xaa"), ":rewind:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x8f\xae"), ":track_previous:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xbc"), ":arrow_up_small:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x8f\xab"), ":arrow_double_up:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xbd"), ":arrow_down_small:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x8f\xac"), ":arrow_double_down:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x8f\xb8"), ":pause_button:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x8f\xb9"), ":stop_button:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x8f\xba"), ":record_button:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x8f\x8f"), ":eject:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x8e\xa6"), ":cinema:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x85"), ":low_brightness:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x86"), ":high_brightness:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb6"), ":signal_strength:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb3"), ":vibration_mode:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\xb4"), ":mobile_phone_off:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x99\xbb"), ":recycle:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x93\x9b"), ":name_badge:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9a\x9c"), ":fleur-de-lis:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb0"), ":beginner:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb1"), ":trident:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\xad\x95"), ":o:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9c\x85"), ":white_check_mark:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x98\x91"), ":ballot_box_with_check:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9c\x94"), ":heavy_check_mark:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9c\x96"), ":heavy_multiplication_x:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9d\x8c"), ":x:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9d\x8e"), - ":negative_squared_cross_mark:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9e\x95"), ":heavy_plus_sign:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9e\x96"), ":heavy_minus_sign:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9e\x97"), ":heavy_division_sign:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9e\xb0"), ":curly_loop:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9e\xbf"), ":loop:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe3\x80\xbd"), ":part_alternation_mark:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9c\xb3"), ":eight_spoked_asterisk:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9c\xb4"), ":eight_pointed_black_star:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9d\x87"), ":sparkle:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x80\xbc"), ":bangbang:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x81\x89"), ":interrobang:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x9d\x93"), ":question:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9d\x94"), ":grey_question:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9d\x95"), ":grey_exclamation:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9d\x97"), ":exclamation:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe3\x80\xb0"), ":wavy_dash:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xc2\xa9"), ":copyright:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xc2\xae"), ":registered:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x84\xa2"), ":tm:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("#\xe2\x83\xa3"), ":hash:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("*\xe2\x83\xa3"), ":asterisk:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("0\xe2\x83\xa3"), ":zero:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("1\xe2\x83\xa3"), ":one:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("2\xe2\x83\xa3"), ":two:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("3\xe2\x83\xa3"), ":three:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("4\xe2\x83\xa3"), ":four:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("5\xe2\x83\xa3"), ":five:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("6\xe2\x83\xa3"), ":six:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("7\xe2\x83\xa3"), ":seven:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("8\xe2\x83\xa3"), ":eight:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("9\xe2\x83\xa3"), ":nine:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x9f"), ":keycap_ten:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x92\xaf"), ":100:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xa0"), ":capital_abcd:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\xa1"), ":abcd:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\xa2"), ":1234:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xa3"), ":symbols:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\xa4"), ":abc:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x85\xb0"), ":a:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x86\x8e"), ":ab:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x85\xb1"), ":b:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x86\x91"), ":cl:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x86\x92"), ":cool:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x86\x93"), ":free:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x84\xb9"), ":information_source:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x86\x94"), ":id:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x93\x82"), ":m:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x86\x95"), ":new:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x86\x96"), ":ng:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x85\xbe"), ":o2:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x86\x97"), ":ok:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x85\xbf"), ":parking:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x86\x98"), ":sos:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x86\x99"), ":up:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x86\x9a"), ":vs:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x88\x81"), ":koko:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x88\x82"), ":sa:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x88\xb7"), ":u6708:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x88\xb6"), ":u6709:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x88\xaf"), ":u6307:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x89\x90"), ":ideograph_advantage:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x88\xb9"), ":u5272:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x88\x9a"), ":u7121:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x88\xb2"), ":u7981:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x89\x91"), ":accept:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x88\xb8"), ":u7533:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x88\xb4"), ":u5408:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x88\xb3"), ":u7a7a:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe3\x8a\x97"), ":congratulations:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe3\x8a\x99"), ":secret:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x88\xba"), ":u55b6:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x88\xb5"), ":u6e80:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x96\xaa"), ":black_small_square:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x96\xab"), ":white_small_square:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x97\xbb"), ":white_medium_square:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x97\xbc"), ":black_medium_square:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x97\xbd"), - ":white_medium_small_square:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xe2\x97\xbe"), - ":black_medium_small_square:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\xac\x9b"), ":black_large_square:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\xac\x9c"), ":white_large_square:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb6"), ":large_orange_diamond:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb7"), ":large_blue_diamond:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb8"), ":small_orange_diamond:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb9"), ":small_blue_diamond:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xba"), ":small_red_triangle:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x94\xbb"), - ":small_red_triangle_down:"}), - QVariant::fromValue(Emoji{QString::fromUtf8("\xf0\x9f\x92\xa0"), - ":diamond_shape_with_a_dot_inside:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\x98"), ":radio_button:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb2"), ":black_square_button:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb3"), ":white_square_button:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9a\xaa"), ":white_circle:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xe2\x9a\xab"), ":black_circle:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb4"), ":red_circle:"}), - QVariant::fromValue( - Emoji{QString::fromUtf8("\xf0\x9f\x94\xb5"), ":blue_circle:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x91\x81\xf0\x9f\x97\xa8"), ":eye_in_speech_bubble:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x98"), ":cupid:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9d\xa4"), ":heart:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x93"), ":heartbeat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x94"), ":broken_heart:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x95"), ":two_hearts:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x96"), ":sparkling_heart:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x97"), ":heartpulse:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x99"), ":blue_heart:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x9a"), ":green_heart:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x9b"), ":yellow_heart:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x9c"), ":purple_heart:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x96\xa4"), ":black_heart:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x9d"), ":gift_heart:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x9e"), ":revolving_hearts:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\x9f"), ":heart_decoration:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9d\xa3"), ":heart_exclamation:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xa2"), ":anger:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xa5"), ":boom:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xab"), ":dizzy:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xac"), ":speech_balloon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\xa8"), ":speech_left:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x97\xaf"), ":anger_right:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xad"), ":thought_balloon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xae"), ":white_flower:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x90"), ":globe_with_meridians:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\xa8"), ":hotsprings:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x91"), ":octagonal_sign:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x9b"), ":clock12:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xa7"), ":clock1230:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x90"), ":clock1:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x9c"), ":clock130:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x91"), ":clock2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x9d"), ":clock230:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x92"), ":clock3:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x9e"), ":clock330:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x93"), ":clock4:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x9f"), ":clock430:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x94"), ":clock5:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xa0"), ":clock530:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x95"), ":clock6:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xa1"), ":clock630:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x96"), ":clock7:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xa2"), ":clock730:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x97"), ":clock8:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xa3"), ":clock830:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x98"), ":clock9:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xa4"), ":clock930:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x99"), ":clock10:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xa5"), ":clock1030:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x9a"), ":clock11:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\xa6"), ":clock1130:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8c\x80"), ":cyclone:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\xa0"), ":spades:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\xa5"), ":hearts:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\xa6"), ":diamonds:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\xa3"), ":clubs:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x83\x8f"), ":black_joker:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x80\x84"), ":mahjong:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xb4"), ":flower_playing_cards:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x87"), ":mute:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x88"), ":speaker:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x89"), ":sound:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x8a"), ":loud_sound:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xa2"), ":loudspeaker:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xa3"), ":mega:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x94"), ":bell:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x95"), ":no_bell:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xb5"), ":musical_note:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xb6"), ":notes:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xb9"), ":chart:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xb1"), ":currency_exchange:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xb2"), ":heavy_dollar_sign:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8f\xa7"), ":atm:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xae"), ":put_litter_in_its_place:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb0"), ":potable_water:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\xbf"), ":wheelchair:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb9"), ":mens:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xba"), ":womens:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xbb"), ":restroom:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xbc"), ":baby_symbol:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xbe"), ":wc:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x82"), ":passport_control:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x83"), ":customs:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x84"), ":baggage_claim:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x85"), ":left_luggage:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9a\xa0"), ":warning:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb8"), ":children_crossing:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\x94"), ":no_entry:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xab"), ":no_entry_sign:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb3"), ":no_bicycles:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xad"), ":no_smoking:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xaf"), ":do_not_litter:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb1"), ":non-potable_water:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9a\xb7"), ":no_pedestrians:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xb5"), ":no_mobile_phones:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x9e"), ":underage:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\xa2"), ":radioactive:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\xa3"), ":biohazard:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\xac\x86"), ":arrow_up:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x86\x97"), ":arrow_upper_right:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9e\xa1"), ":arrow_right:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x86\x98"), ":arrow_lower_right:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\xac\x87"), ":arrow_down:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x86\x99"), ":arrow_lower_left:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\xac\x85"), ":arrow_left:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x86\x96"), ":arrow_upper_left:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x86\x95"), ":arrow_up_down:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x86\x94"), ":left_right_arrow:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x86\xa9"), ":leftwards_arrow_with_hook:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x86\xaa"), ":arrow_right_hook:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\xa4\xb4"), ":arrow_heading_up:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\xa4\xb5"), ":arrow_heading_down:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x83"), ":arrows_clockwise:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x84"), ":arrows_counterclockwise:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x99"), ":back:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x9a"), ":end:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x9b"), ":on:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x9c"), ":soon:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x9d"), ":top:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x9b\x90"), ":place_of_worship:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9a\x9b"), ":atom:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x89"), ":om_symbol:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9c\xa1"), ":star_of_david:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\xb8"), ":wheel_of_dharma:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\xaf"), ":yin_yang:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9c\x9d"), ":cross:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\xa6"), ":orthodox_cross:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\xaa"), ":star_and_crescent:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\xae"), ":peace:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x95\x8e"), ":menorah:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xaf"), ":six_pointed_star:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\x88"), ":aries:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\x89"), ":taurus:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\x8a"), ":gemini:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\x8b"), ":cancer:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\x8c"), ":leo:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\x8d"), ":virgo:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\x8e"), ":libra:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\x8f"), ":scorpius:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\x90"), ":sagittarius:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\x91"), ":capricorn:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\x92"), ":aquarius:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\x93"), ":pisces:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9b\x8e"), ":ophiuchus:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x80"), ":twisted_rightwards_arrows:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x81"), ":repeat:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x82"), ":repeat_one:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x96\xb6"), ":arrow_forward:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8f\xa9"), ":fast_forward:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8f\xad"), ":track_next:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8f\xaf"), ":play_pause:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x97\x80"), ":arrow_backward:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8f\xaa"), ":rewind:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8f\xae"), ":track_previous:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xbc"), ":arrow_up_small:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8f\xab"), ":arrow_double_up:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xbd"), ":arrow_down_small:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8f\xac"), ":arrow_double_down:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8f\xb8"), ":pause_button:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8f\xb9"), ":stop_button:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8f\xba"), ":record_button:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x8f\x8f"), ":eject:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x8e\xa6"), ":cinema:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x85"), ":low_brightness:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x86"), ":high_brightness:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xb6"), ":signal_strength:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xb3"), ":vibration_mode:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\xb4"), ":mobile_phone_off:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x99\xbb"), ":recycle:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x93\x9b"), ":name_badge:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9a\x9c"), ":fleur-de-lis:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xb0"), ":beginner:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xb1"), ":trident:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\xad\x95"), ":o:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9c\x85"), ":white_check_mark:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x98\x91"), ":ballot_box_with_check:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9c\x94"), ":heavy_check_mark:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9c\x96"), ":heavy_multiplication_x:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9d\x8c"), ":x:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9d\x8e"), ":negative_squared_cross_mark:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9e\x95"), ":heavy_plus_sign:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9e\x96"), ":heavy_minus_sign:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9e\x97"), ":heavy_division_sign:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9e\xb0"), ":curly_loop:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9e\xbf"), ":loop:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe3\x80\xbd"), ":part_alternation_mark:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9c\xb3"), ":eight_spoked_asterisk:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9c\xb4"), ":eight_pointed_black_star:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9d\x87"), ":sparkle:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x80\xbc"), ":bangbang:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x81\x89"), ":interrobang:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9d\x93"), ":question:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9d\x94"), ":grey_question:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9d\x95"), ":grey_exclamation:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9d\x97"), ":exclamation:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe3\x80\xb0"), ":wavy_dash:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xc2\xa9"), ":copyright:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xc2\xae"), ":registered:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x84\xa2"), ":tm:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("#\xe2\x83\xa3"), ":hash:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("*\xe2\x83\xa3"), ":asterisk:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("0\xe2\x83\xa3"), ":zero:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("1\xe2\x83\xa3"), ":one:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("2\xe2\x83\xa3"), ":two:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("3\xe2\x83\xa3"), ":three:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("4\xe2\x83\xa3"), ":four:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("5\xe2\x83\xa3"), ":five:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("6\xe2\x83\xa3"), ":six:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("7\xe2\x83\xa3"), ":seven:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("8\xe2\x83\xa3"), ":eight:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("9\xe2\x83\xa3"), ":nine:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x9f"), ":keycap_ten:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xaf"), ":100:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xa0"), ":capital_abcd:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xa1"), ":abcd:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xa2"), ":1234:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xa3"), ":symbols:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xa4"), ":abc:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x85\xb0"), ":a:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x86\x8e"), ":ab:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x85\xb1"), ":b:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x86\x91"), ":cl:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x86\x92"), ":cool:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x86\x93"), ":free:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x84\xb9"), ":information_source:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x86\x94"), ":id:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x93\x82"), ":m:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x86\x95"), ":new:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x86\x96"), ":ng:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x85\xbe"), ":o2:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x86\x97"), ":ok:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x85\xbf"), ":parking:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x86\x98"), ":sos:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x86\x99"), ":up:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x86\x9a"), ":vs:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x88\x81"), ":koko:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x88\x82"), ":sa:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x88\xb7"), ":u6708:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x88\xb6"), ":u6709:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x88\xaf"), ":u6307:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x89\x90"), ":ideograph_advantage:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x88\xb9"), ":u5272:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x88\x9a"), ":u7121:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x88\xb2"), ":u7981:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x89\x91"), ":accept:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x88\xb8"), ":u7533:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x88\xb4"), ":u5408:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x88\xb3"), ":u7a7a:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe3\x8a\x97"), ":congratulations:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe3\x8a\x99"), ":secret:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x88\xba"), ":u55b6:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x88\xb5"), ":u6e80:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x96\xaa"), ":black_small_square:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x96\xab"), ":white_small_square:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x97\xbb"), ":white_medium_square:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x97\xbc"), ":black_medium_square:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x97\xbd"), ":white_medium_small_square:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x97\xbe"), ":black_medium_small_square:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\xac\x9b"), ":black_large_square:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\xac\x9c"), ":white_large_square:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xb6"), ":large_orange_diamond:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xb7"), ":large_blue_diamond:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xb8"), ":small_orange_diamond:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xb9"), ":small_blue_diamond:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xba"), ":small_red_triangle:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xbb"), ":small_red_triangle_down:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x92\xa0"), ":diamond_shape_with_a_dot_inside:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\x98"), ":radio_button:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xb2"), ":black_square_button:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xb3"), ":white_square_button:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9a\xaa"), ":white_circle:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xe2\x9a\xab"), ":black_circle:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xb4"), ":red_circle:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x94\xb5"), ":blue_circle:"}), }; const QVariantList EmojiModel::flags = { - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xa8"), ":flag_ac:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xa9"), ":flag_ad:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xaa"), ":flag_ae:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xab"), ":flag_af:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xac"), ":flag_ag:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xae"), ":flag_ai:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb1"), ":flag_al:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb2"), ":flag_am:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb4"), ":flag_ao:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb6"), ":flag_aq:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb7"), ":flag_ar:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb8"), ":flag_as:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb9"), ":flag_at:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xba"), ":flag_au:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xbc"), ":flag_aw:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xbd"), ":flag_ax:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xbf"), ":flag_az:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xa6"), ":flag_ba:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xa7"), ":flag_bb:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xa9"), ":flag_bd:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xaa"), ":flag_be:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xab"), ":flag_bf:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xac"), ":flag_bg:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xad"), ":flag_bh:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xae"), ":flag_bi:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xaf"), ":flag_bj:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb1"), ":flag_bl:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb2"), ":flag_bm:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb3"), ":flag_bn:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb4"), ":flag_bo:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb6"), ":flag_bq:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb7"), ":flag_br:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb8"), ":flag_bs:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb9"), ":flag_bt:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xbb"), ":flag_bv:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xbc"), ":flag_bw:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xbe"), ":flag_by:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xbf"), ":flag_bz:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xa6"), ":flag_ca:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xa8"), ":flag_cc:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xa9"), ":flag_cd:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xab"), ":flag_cf:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xac"), ":flag_cg:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xad"), ":flag_ch:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xae"), ":flag_ci:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb0"), ":flag_ck:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb1"), ":flag_cl:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb2"), ":flag_cm:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb3"), ":flag_cn:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb4"), ":flag_co:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb5"), ":flag_cp:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb7"), ":flag_cr:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xba"), ":flag_cu:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbb"), ":flag_cv:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbc"), ":flag_cw:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbd"), ":flag_cx:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbe"), ":flag_cy:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbf"), ":flag_cz:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xaa"), ":flag_de:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xac"), ":flag_dg:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xaf"), ":flag_dj:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xb0"), ":flag_dk:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xb2"), ":flag_dm:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xb4"), ":flag_do:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xbf"), ":flag_dz:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xa6"), ":flag_ea:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xa8"), ":flag_ec:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xaa"), ":flag_ee:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xac"), ":flag_eg:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xad"), ":flag_eh:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xb7"), ":flag_er:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xb8"), ":flag_es:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xb9"), ":flag_et:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xba"), ":flag_eu:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xae"), ":flag_fi:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xaf"), ":flag_fj:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xb0"), ":flag_fk:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xb2"), ":flag_fm:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xb4"), ":flag_fo:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xb7"), ":flag_fr:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xa6"), ":flag_ga:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xa7"), ":flag_gb:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xa9"), ":flag_gd:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xaa"), ":flag_ge:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xab"), ":flag_gf:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xac"), ":flag_gg:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xad"), ":flag_gh:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xae"), ":flag_gi:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb1"), ":flag_gl:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb2"), ":flag_gm:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb3"), ":flag_gn:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb5"), ":flag_gp:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb6"), ":flag_gq:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb7"), ":flag_gr:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb8"), ":flag_gs:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb9"), ":flag_gt:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xba"), ":flag_gu:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xbc"), ":flag_gw:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xbe"), ":flag_gy:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb0"), ":flag_hk:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb2"), ":flag_hm:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb3"), ":flag_hn:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb7"), ":flag_hr:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb9"), ":flag_ht:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xba"), ":flag_hu:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xa8"), ":flag_ic:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xa9"), ":flag_id:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xaa"), ":flag_ie:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb1"), ":flag_il:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb2"), ":flag_im:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb3"), ":flag_in:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb4"), ":flag_io:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb6"), ":flag_iq:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb7"), ":flag_ir:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb8"), ":flag_is:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb9"), ":flag_it:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xaf\xf0\x9f\x87\xaa"), ":flag_je:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xaf\xf0\x9f\x87\xb2"), ":flag_jm:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xaf\xf0\x9f\x87\xb4"), ":flag_jo:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xaf\xf0\x9f\x87\xb5"), ":flag_jp:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xaa"), ":flag_ke:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xac"), ":flag_kg:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xad"), ":flag_kh:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xae"), ":flag_ki:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xb2"), ":flag_km:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xb3"), ":flag_kn:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xb5"), ":flag_kp:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xb7"), ":flag_kr:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xbc"), ":flag_kw:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xbe"), ":flag_ky:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xbf"), ":flag_kz:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xa6"), ":flag_la:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xa7"), ":flag_lb:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xa8"), ":flag_lc:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xae"), ":flag_li:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xb0"), ":flag_lk:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xb7"), ":flag_lr:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xb8"), ":flag_ls:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xb9"), ":flag_lt:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xba"), ":flag_lu:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xbb"), ":flag_lv:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xbe"), ":flag_ly:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xa6"), ":flag_ma:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xa8"), ":flag_mc:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xa9"), ":flag_md:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xaa"), ":flag_me:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xab"), ":flag_mf:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xac"), ":flag_mg:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xad"), ":flag_mh:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb0"), ":flag_mk:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb1"), ":flag_ml:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb2"), ":flag_mm:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb3"), ":flag_mn:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb4"), ":flag_mo:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb5"), ":flag_mp:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb6"), ":flag_mq:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb7"), ":flag_mr:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb8"), ":flag_ms:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb9"), ":flag_mt:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xba"), ":flag_mu:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbb"), ":flag_mv:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbc"), ":flag_mw:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbd"), ":flag_mx:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbe"), ":flag_my:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbf"), ":flag_mz:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xa6"), ":flag_na:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xa8"), ":flag_nc:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xaa"), ":flag_ne:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xab"), ":flag_nf:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xac"), ":flag_ng:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xae"), ":flag_ni:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xb1"), ":flag_nl:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xb4"), ":flag_no:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xb5"), ":flag_np:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xb7"), ":flag_nr:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xba"), ":flag_nu:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xbf"), ":flag_nz:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb4\xf0\x9f\x87\xb2"), ":flag_om:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xa6"), ":flag_pa:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xaa"), ":flag_pe:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xab"), ":flag_pf:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xac"), ":flag_pg:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xad"), ":flag_ph:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb0"), ":flag_pk:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb1"), ":flag_pl:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb2"), ":flag_pm:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb3"), ":flag_pn:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb7"), ":flag_pr:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb8"), ":flag_ps:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb9"), ":flag_pt:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xbc"), ":flag_pw:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xbe"), ":flag_py:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb6\xf0\x9f\x87\xa6"), ":flag_qa:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xaa"), ":flag_re:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xb4"), ":flag_ro:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xb8"), ":flag_rs:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xba"), ":flag_ru:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xbc"), ":flag_rw:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xa6"), ":flag_sa:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xa7"), ":flag_sb:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xa8"), ":flag_sc:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xa9"), ":flag_sd:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xaa"), ":flag_se:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xac"), ":flag_sg:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xad"), ":flag_sh:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xae"), ":flag_si:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xaf"), ":flag_sj:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb0"), ":flag_sk:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb1"), ":flag_sl:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb2"), ":flag_sm:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb3"), ":flag_sn:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb4"), ":flag_so:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb7"), ":flag_sr:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb8"), ":flag_ss:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb9"), ":flag_st:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xbb"), ":flag_sv:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xbd"), ":flag_sx:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xbe"), ":flag_sy:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xbf"), ":flag_sz:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xa6"), ":flag_ta:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xa8"), ":flag_tc:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xa9"), ":flag_td:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xab"), ":flag_tf:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xac"), ":flag_tg:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xad"), ":flag_th:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xaf"), ":flag_tj:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb0"), ":flag_tk:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb1"), ":flag_tl:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb2"), ":flag_tm:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb3"), ":flag_tn:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb4"), ":flag_to:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb7"), ":flag_tr:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb9"), ":flag_tt:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xbb"), ":flag_tv:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xbc"), ":flag_tw:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xbf"), ":flag_tz:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xa6"), ":flag_ua:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xac"), ":flag_ug:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xb2"), ":flag_um:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xb8"), ":flag_us:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xbe"), ":flag_uy:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xbf"), ":flag_uz:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xa6"), ":flag_va:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xa8"), ":flag_vc:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xaa"), ":flag_ve:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xac"), ":flag_vg:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xae"), ":flag_vi:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xb3"), ":flag_vn:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xba"), ":flag_vu:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xbc\xf0\x9f\x87\xab"), ":flag_wf:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xbc\xf0\x9f\x87\xb8"), ":flag_ws:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xbd\xf0\x9f\x87\xb0"), ":flag_xk:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xbe\xf0\x9f\x87\xaa"), ":flag_ye:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xbe\xf0\x9f\x87\xb9"), ":flag_yt:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xbf\xf0\x9f\x87\xa6"), ":flag_za:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xbf\xf0\x9f\x87\xb2"), ":flag_zm:"}), - QVariant::fromValue(Emoji{ - QString::fromUtf8("\xf0\x9f\x87\xbf\xf0\x9f\x87\xbc"), ":flag_zw:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xa8"), ":flag_ac:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xa9"), ":flag_ad:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xaa"), ":flag_ae:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xab"), ":flag_af:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xac"), ":flag_ag:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xae"), ":flag_ai:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb1"), ":flag_al:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb2"), ":flag_am:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb4"), ":flag_ao:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb6"), ":flag_aq:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb7"), ":flag_ar:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb8"), ":flag_as:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xb9"), ":flag_at:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xba"), ":flag_au:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xbc"), ":flag_aw:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xbd"), ":flag_ax:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa6\xf0\x9f\x87\xbf"), ":flag_az:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xa6"), ":flag_ba:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xa7"), ":flag_bb:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xa9"), ":flag_bd:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xaa"), ":flag_be:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xab"), ":flag_bf:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xac"), ":flag_bg:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xad"), ":flag_bh:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xae"), ":flag_bi:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xaf"), ":flag_bj:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb1"), ":flag_bl:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb2"), ":flag_bm:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb3"), ":flag_bn:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb4"), ":flag_bo:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb6"), ":flag_bq:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb7"), ":flag_br:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb8"), ":flag_bs:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xb9"), ":flag_bt:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xbb"), ":flag_bv:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xbc"), ":flag_bw:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xbe"), ":flag_by:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa7\xf0\x9f\x87\xbf"), ":flag_bz:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xa6"), ":flag_ca:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xa8"), ":flag_cc:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xa9"), ":flag_cd:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xab"), ":flag_cf:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xac"), ":flag_cg:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xad"), ":flag_ch:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xae"), ":flag_ci:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb0"), ":flag_ck:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb1"), ":flag_cl:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb2"), ":flag_cm:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb3"), ":flag_cn:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb4"), ":flag_co:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb5"), ":flag_cp:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xb7"), ":flag_cr:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xba"), ":flag_cu:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbb"), ":flag_cv:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbc"), ":flag_cw:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbd"), ":flag_cx:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbe"), ":flag_cy:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa8\xf0\x9f\x87\xbf"), ":flag_cz:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xaa"), ":flag_de:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xac"), ":flag_dg:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xaf"), ":flag_dj:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xb0"), ":flag_dk:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xb2"), ":flag_dm:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xb4"), ":flag_do:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xa9\xf0\x9f\x87\xbf"), ":flag_dz:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xa6"), ":flag_ea:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xa8"), ":flag_ec:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xaa"), ":flag_ee:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xac"), ":flag_eg:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xad"), ":flag_eh:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xb7"), ":flag_er:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xb8"), ":flag_es:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xb9"), ":flag_et:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xaa\xf0\x9f\x87\xba"), ":flag_eu:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xae"), ":flag_fi:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xaf"), ":flag_fj:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xb0"), ":flag_fk:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xb2"), ":flag_fm:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xb4"), ":flag_fo:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xab\xf0\x9f\x87\xb7"), ":flag_fr:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xa6"), ":flag_ga:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xa7"), ":flag_gb:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xa9"), ":flag_gd:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xaa"), ":flag_ge:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xab"), ":flag_gf:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xac"), ":flag_gg:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xad"), ":flag_gh:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xae"), ":flag_gi:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb1"), ":flag_gl:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb2"), ":flag_gm:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb3"), ":flag_gn:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb5"), ":flag_gp:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb6"), ":flag_gq:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb7"), ":flag_gr:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb8"), ":flag_gs:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xb9"), ":flag_gt:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xba"), ":flag_gu:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xbc"), ":flag_gw:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xac\xf0\x9f\x87\xbe"), ":flag_gy:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb0"), ":flag_hk:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb2"), ":flag_hm:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb3"), ":flag_hn:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb7"), ":flag_hr:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xb9"), ":flag_ht:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xad\xf0\x9f\x87\xba"), ":flag_hu:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xa8"), ":flag_ic:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xa9"), ":flag_id:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xaa"), ":flag_ie:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb1"), ":flag_il:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb2"), ":flag_im:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb3"), ":flag_in:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb4"), ":flag_io:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb6"), ":flag_iq:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb7"), ":flag_ir:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb8"), ":flag_is:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xae\xf0\x9f\x87\xb9"), ":flag_it:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xaf\xf0\x9f\x87\xaa"), ":flag_je:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xaf\xf0\x9f\x87\xb2"), ":flag_jm:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xaf\xf0\x9f\x87\xb4"), ":flag_jo:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xaf\xf0\x9f\x87\xb5"), ":flag_jp:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xaa"), ":flag_ke:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xac"), ":flag_kg:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xad"), ":flag_kh:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xae"), ":flag_ki:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xb2"), ":flag_km:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xb3"), ":flag_kn:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xb5"), ":flag_kp:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xb7"), ":flag_kr:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xbc"), ":flag_kw:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xbe"), ":flag_ky:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb0\xf0\x9f\x87\xbf"), ":flag_kz:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xa6"), ":flag_la:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xa7"), ":flag_lb:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xa8"), ":flag_lc:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xae"), ":flag_li:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xb0"), ":flag_lk:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xb7"), ":flag_lr:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xb8"), ":flag_ls:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xb9"), ":flag_lt:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xba"), ":flag_lu:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xbb"), ":flag_lv:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb1\xf0\x9f\x87\xbe"), ":flag_ly:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xa6"), ":flag_ma:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xa8"), ":flag_mc:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xa9"), ":flag_md:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xaa"), ":flag_me:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xab"), ":flag_mf:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xac"), ":flag_mg:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xad"), ":flag_mh:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb0"), ":flag_mk:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb1"), ":flag_ml:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb2"), ":flag_mm:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb3"), ":flag_mn:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb4"), ":flag_mo:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb5"), ":flag_mp:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb6"), ":flag_mq:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb7"), ":flag_mr:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb8"), ":flag_ms:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xb9"), ":flag_mt:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xba"), ":flag_mu:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbb"), ":flag_mv:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbc"), ":flag_mw:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbd"), ":flag_mx:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbe"), ":flag_my:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb2\xf0\x9f\x87\xbf"), ":flag_mz:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xa6"), ":flag_na:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xa8"), ":flag_nc:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xaa"), ":flag_ne:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xab"), ":flag_nf:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xac"), ":flag_ng:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xae"), ":flag_ni:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xb1"), ":flag_nl:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xb4"), ":flag_no:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xb5"), ":flag_np:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xb7"), ":flag_nr:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xba"), ":flag_nu:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb3\xf0\x9f\x87\xbf"), ":flag_nz:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb4\xf0\x9f\x87\xb2"), ":flag_om:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xa6"), ":flag_pa:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xaa"), ":flag_pe:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xab"), ":flag_pf:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xac"), ":flag_pg:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xad"), ":flag_ph:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb0"), ":flag_pk:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb1"), ":flag_pl:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb2"), ":flag_pm:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb3"), ":flag_pn:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb7"), ":flag_pr:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb8"), ":flag_ps:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xb9"), ":flag_pt:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xbc"), ":flag_pw:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb5\xf0\x9f\x87\xbe"), ":flag_py:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb6\xf0\x9f\x87\xa6"), ":flag_qa:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xaa"), ":flag_re:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xb4"), ":flag_ro:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xb8"), ":flag_rs:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xba"), ":flag_ru:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb7\xf0\x9f\x87\xbc"), ":flag_rw:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xa6"), ":flag_sa:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xa7"), ":flag_sb:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xa8"), ":flag_sc:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xa9"), ":flag_sd:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xaa"), ":flag_se:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xac"), ":flag_sg:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xad"), ":flag_sh:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xae"), ":flag_si:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xaf"), ":flag_sj:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb0"), ":flag_sk:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb1"), ":flag_sl:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb2"), ":flag_sm:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb3"), ":flag_sn:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb4"), ":flag_so:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb7"), ":flag_sr:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb8"), ":flag_ss:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xb9"), ":flag_st:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xbb"), ":flag_sv:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xbd"), ":flag_sx:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xbe"), ":flag_sy:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb8\xf0\x9f\x87\xbf"), ":flag_sz:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xa6"), ":flag_ta:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xa8"), ":flag_tc:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xa9"), ":flag_td:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xab"), ":flag_tf:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xac"), ":flag_tg:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xad"), ":flag_th:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xaf"), ":flag_tj:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb0"), ":flag_tk:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb1"), ":flag_tl:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb2"), ":flag_tm:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb3"), ":flag_tn:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb4"), ":flag_to:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb7"), ":flag_tr:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xb9"), ":flag_tt:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xbb"), ":flag_tv:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xbc"), ":flag_tw:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xb9\xf0\x9f\x87\xbf"), ":flag_tz:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xa6"), ":flag_ua:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xac"), ":flag_ug:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xb2"), ":flag_um:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xb8"), ":flag_us:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xbe"), ":flag_uy:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xba\xf0\x9f\x87\xbf"), ":flag_uz:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xa6"), ":flag_va:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xa8"), ":flag_vc:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xaa"), ":flag_ve:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xac"), ":flag_vg:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xae"), ":flag_vi:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xb3"), ":flag_vn:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xbb\xf0\x9f\x87\xba"), ":flag_vu:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xbc\xf0\x9f\x87\xab"), ":flag_wf:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xbc\xf0\x9f\x87\xb8"), ":flag_ws:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xbd\xf0\x9f\x87\xb0"), ":flag_xk:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xbe\xf0\x9f\x87\xaa"), ":flag_ye:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xbe\xf0\x9f\x87\xb9"), ":flag_yt:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xbf\xf0\x9f\x87\xa6"), ":flag_za:"}), QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xbf\xf0\x9f\x87\xb2"), ":flag_zm:"}), + QVariant::fromValue(Emoji {QString::fromUtf8("\xf0\x9f\x87\xbf\xf0\x9f\x87\xbc"), ":flag_zw:"}), }; diff --git a/src/emojimodel.h b/src/emojimodel.h index 88ce00b95..07036e299 100644 --- a/src/emojimodel.h +++ b/src/emojimodel.h @@ -12,69 +12,81 @@ #include struct Emoji { - Emoji(const QString& u, const QString& s) : unicode(u), shortname(s) {} - Emoji() {} + Emoji(const QString &u, const QString &s) + : unicode(u) + , shortname(s) + { + } + Emoji() + { + } - friend QDataStream& operator<<(QDataStream& arch, const Emoji& object) { - arch << object.unicode; - arch << object.shortname; - return arch; - } + friend QDataStream &operator<<(QDataStream &arch, const Emoji &object) + { + arch << object.unicode; + arch << object.shortname; + return arch; + } - friend QDataStream& operator>>(QDataStream& arch, Emoji& object) { - arch >> object.unicode; - arch >> object.shortname; - return arch; - } + friend QDataStream &operator>>(QDataStream &arch, Emoji &object) + { + arch >> object.unicode; + arch >> object.shortname; + return arch; + } - QString unicode; - QString shortname; + QString unicode; + QString shortname; - Q_GADGET - Q_PROPERTY(QString unicode MEMBER unicode) - Q_PROPERTY(QString shortname MEMBER shortname) + Q_GADGET + Q_PROPERTY(QString unicode MEMBER unicode) + Q_PROPERTY(QString shortname MEMBER shortname) }; Q_DECLARE_METATYPE(Emoji) -class EmojiModel : public QObject { - Q_OBJECT +class EmojiModel : public QObject +{ + Q_OBJECT - Q_PROPERTY(QVariantList history READ history NOTIFY historyChanged) + Q_PROPERTY(QVariantList history READ history NOTIFY historyChanged) - Q_PROPERTY(QVariantList people MEMBER people CONSTANT) - Q_PROPERTY(QVariantList nature MEMBER nature CONSTANT) - Q_PROPERTY(QVariantList food MEMBER food CONSTANT) - Q_PROPERTY(QVariantList activity MEMBER activity CONSTANT) - Q_PROPERTY(QVariantList travel MEMBER travel CONSTANT) - Q_PROPERTY(QVariantList objects MEMBER objects CONSTANT) - Q_PROPERTY(QVariantList symbols MEMBER symbols CONSTANT) - Q_PROPERTY(QVariantList flags MEMBER flags CONSTANT) + Q_PROPERTY(QVariantList people MEMBER people CONSTANT) + Q_PROPERTY(QVariantList nature MEMBER nature CONSTANT) + Q_PROPERTY(QVariantList food MEMBER food CONSTANT) + Q_PROPERTY(QVariantList activity MEMBER activity CONSTANT) + Q_PROPERTY(QVariantList travel MEMBER travel CONSTANT) + Q_PROPERTY(QVariantList objects MEMBER objects CONSTANT) + Q_PROPERTY(QVariantList symbols MEMBER symbols CONSTANT) + Q_PROPERTY(QVariantList flags MEMBER flags CONSTANT) - public: - explicit EmojiModel(QObject* parent = nullptr) - : QObject(parent), m_settings(new QSettings()) {} +public: + explicit EmojiModel(QObject *parent = nullptr) + : QObject(parent) + , m_settings(new QSettings()) + { + } - Q_INVOKABLE QVariantList history(); - Q_INVOKABLE QVariantList filterModel(const QString& filter); + Q_INVOKABLE QVariantList history(); + Q_INVOKABLE QVariantList filterModel(const QString &filter); - signals: - void historyChanged(); +signals: + void historyChanged(); - public slots: - void emojiUsed(QVariant modelData); +public slots: + void emojiUsed(QVariant modelData); - private: - static const QVariantList people; - static const QVariantList nature; - static const QVariantList food; - static const QVariantList activity; - static const QVariantList travel; - static const QVariantList objects; - static const QVariantList symbols; - static const QVariantList flags; +private: + static const QVariantList people; + static const QVariantList nature; + static const QVariantList food; + static const QVariantList activity; + static const QVariantList travel; + static const QVariantList objects; + static const QVariantList symbols; + static const QVariantList flags; - QSettings* m_settings; + QSettings *m_settings; }; -#endif // EMOJIMODEL_H +#endif // EMOJIMODEL_H diff --git a/src/imageclipboard.cpp b/src/imageclipboard.cpp index a9f8e76ae..28ba13e80 100644 --- a/src/imageclipboard.cpp +++ b/src/imageclipboard.cpp @@ -11,36 +11,40 @@ #include #include -ImageClipboard::ImageClipboard(QObject* parent) - : QObject(parent), m_clipboard(QGuiApplication::clipboard()) { - connect(m_clipboard, &QClipboard::changed, this, - &ImageClipboard::imageChanged); +ImageClipboard::ImageClipboard(QObject *parent) + : QObject(parent) + , m_clipboard(QGuiApplication::clipboard()) +{ + connect(m_clipboard, &QClipboard::changed, this, &ImageClipboard::imageChanged); } -bool ImageClipboard::hasImage() const { - return !image().isNull(); +bool ImageClipboard::hasImage() const +{ + return !image().isNull(); } -QImage ImageClipboard::image() const { - return m_clipboard->image(); +QImage ImageClipboard::image() const +{ + return m_clipboard->image(); } -bool ImageClipboard::saveImage(const QUrl& localPath) { - if (!localPath.isLocalFile()) - return false; +bool ImageClipboard::saveImage(const QUrl &localPath) +{ + if (!localPath.isLocalFile()) + return false; - auto i = image(); + auto i = image(); - if (i.isNull()) - return false; + if (i.isNull()) + return false; - QString path = QFileInfo(localPath.toLocalFile()).absolutePath(); - QDir dir; - if (!dir.exists(path)) { - dir.mkpath(path); - } + QString path = QFileInfo(localPath.toLocalFile()).absolutePath(); + QDir dir; + if (!dir.exists(path)) { + dir.mkpath(path); + } - i.save(localPath.toLocalFile()); + i.save(localPath.toLocalFile()); - return true; + return true; } diff --git a/src/imageclipboard.h b/src/imageclipboard.h index 1cdf32849..2f52ec35d 100644 --- a/src/imageclipboard.h +++ b/src/imageclipboard.h @@ -10,24 +10,25 @@ #include #include -class ImageClipboard : public QObject { - Q_OBJECT - Q_PROPERTY(bool hasImage READ hasImage NOTIFY imageChanged) - Q_PROPERTY(QImage image READ image NOTIFY imageChanged) +class ImageClipboard : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool hasImage READ hasImage NOTIFY imageChanged) + Q_PROPERTY(QImage image READ image NOTIFY imageChanged) - public: - explicit ImageClipboard(QObject* parent = nullptr); +public: + explicit ImageClipboard(QObject *parent = nullptr); - bool hasImage() const; - QImage image() const; + bool hasImage() const; + QImage image() const; - Q_INVOKABLE bool saveImage(const QUrl& localPath); + Q_INVOKABLE bool saveImage(const QUrl &localPath); - private: - QClipboard* m_clipboard; +private: + QClipboard *m_clipboard; - signals: - void imageChanged(); +signals: + void imageChanged(); }; -#endif // IMAGECLIPBOARD_H +#endif // IMAGECLIPBOARD_H diff --git a/src/main.cpp b/src/main.cpp index 36dfd0c13..266a4de20 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,59 +30,56 @@ using namespace Quotient; -int main(int argc, char* argv[]) { - QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +int main(int argc, char *argv[]) +{ + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QNetworkProxyFactory::setUseSystemConfiguration(true); + QNetworkProxyFactory::setUseSystemConfiguration(true); - QApplication app(argc, argv); + QApplication app(argc, argv); - app.setOrganizationName("ENCOM"); - app.setOrganizationDomain("encom.eu.org"); - app.setApplicationName("Spectral"); - app.setWindowIcon(QIcon(":/assets/img/icon.png")); + app.setOrganizationName("ENCOM"); + app.setOrganizationDomain("encom.eu.org"); + app.setApplicationName("Spectral"); + app.setWindowIcon(QIcon(":/assets/img/icon.png")); - qmlRegisterType("Spectral", 0, 1, "Controller"); - qmlRegisterType("Spectral", 0, 1, "AccountListModel"); - qmlRegisterType("Spectral", 0, 1, "RoomListModel"); - qmlRegisterType("Spectral", 0, 1, "UserListModel"); - qmlRegisterType("Spectral", 0, 1, "MessageEventModel"); - qmlRegisterType("Spectral", 0, 1, "PublicRoomListModel"); - qmlRegisterType("Spectral", 0, 1, - "UserDirectoryListModel"); - qmlRegisterType("Spectral", 0, 1, "EmojiModel"); - qmlRegisterType("Spectral", 0, 1, - "NotificationsManager"); - qmlRegisterType("Spectral", 0, 1, "TrayIcon"); - qmlRegisterType("Spectral", 0, 1, "ImageClipboard"); - qmlRegisterUncreatableType("Spectral", 0, 1, - "RoomMessageEvent", "ENUM"); - qmlRegisterUncreatableType("Spectral", 0, 1, "RoomType", "ENUM"); - qmlRegisterUncreatableType("Spectral", 0, 1, "UserType", "ENUM"); + qmlRegisterType("Spectral", 0, 1, "Controller"); + qmlRegisterType("Spectral", 0, 1, "AccountListModel"); + qmlRegisterType("Spectral", 0, 1, "RoomListModel"); + qmlRegisterType("Spectral", 0, 1, "UserListModel"); + qmlRegisterType("Spectral", 0, 1, "MessageEventModel"); + qmlRegisterType("Spectral", 0, 1, "PublicRoomListModel"); + qmlRegisterType("Spectral", 0, 1, "UserDirectoryListModel"); + qmlRegisterType("Spectral", 0, 1, "EmojiModel"); + qmlRegisterType("Spectral", 0, 1, "NotificationsManager"); + qmlRegisterType("Spectral", 0, 1, "TrayIcon"); + qmlRegisterType("Spectral", 0, 1, "ImageClipboard"); + qmlRegisterUncreatableType("Spectral", 0, 1, "RoomMessageEvent", "ENUM"); + qmlRegisterUncreatableType("Spectral", 0, 1, "RoomType", "ENUM"); + qmlRegisterUncreatableType("Spectral", 0, 1, "UserType", "ENUM"); - qRegisterMetaType("User*"); - qRegisterMetaType("const User*"); - qRegisterMetaType("const Quotient::User*"); - qRegisterMetaType("Room*"); - qRegisterMetaType("Connection*"); - qRegisterMetaType("MessageEventType"); - qRegisterMetaType("SpectralRoom*"); - qRegisterMetaType("SpectralUser*"); - qRegisterMetaType("GetRoomEventsJob*"); + qRegisterMetaType("User*"); + qRegisterMetaType("const User*"); + qRegisterMetaType("const Quotient::User*"); + qRegisterMetaType("Room*"); + qRegisterMetaType("Connection*"); + qRegisterMetaType("MessageEventType"); + qRegisterMetaType("SpectralRoom*"); + qRegisterMetaType("SpectralUser*"); + qRegisterMetaType("GetRoomEventsJob*"); - qRegisterMetaTypeStreamOperators(); + qRegisterMetaTypeStreamOperators(); - QQmlApplicationEngine engine; + QQmlApplicationEngine engine; - engine.addImportPath("qrc:/imports"); - MatrixImageProvider* matrixImageProvider = new MatrixImageProvider(); - engine.rootContext()->setContextProperty("imageProvider", - matrixImageProvider); - engine.addImageProvider(QLatin1String("mxc"), matrixImageProvider); + engine.addImportPath("qrc:/imports"); + MatrixImageProvider *matrixImageProvider = new MatrixImageProvider(); + engine.rootContext()->setContextProperty("imageProvider", matrixImageProvider); + engine.addImageProvider(QLatin1String("mxc"), matrixImageProvider); - engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); - if (engine.rootObjects().isEmpty()) - return -1; + engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); + if (engine.rootObjects().isEmpty()) + return -1; - return app.exec(); + return app.exec(); } diff --git a/src/matriximageprovider.cpp b/src/matriximageprovider.cpp index 5b939ac29..c0d6cda74 100644 --- a/src/matriximageprovider.cpp +++ b/src/matriximageprovider.cpp @@ -14,113 +14,108 @@ using Quotient::BaseJob; -ThumbnailResponse::ThumbnailResponse(Quotient::Connection* c, - QString id, - const QSize& size) - : c(c), - mediaId(std::move(id)), - requestedSize(size), - localFile(QStringLiteral("%1/image_provider/%2-%3x%4.png") - .arg(QStandardPaths::writableLocation( - QStandardPaths::CacheLocation), - mediaId, - QString::number(requestedSize.width()), - QString::number(requestedSize.height()))), - errorStr("Image request hasn't started") { - if (requestedSize.isEmpty()) { - errorStr.clear(); - emit finished(); - return; - } - if (mediaId.count('/') != 1) { - errorStr = - tr("Media id '%1' doesn't follow server/mediaId pattern").arg(mediaId); - emit finished(); - return; - } - - QImage cachedImage; - if (cachedImage.load(localFile)) { - image = cachedImage; - errorStr.clear(); - emit finished(); - return; - } - - if (!c) { - qWarning() << "Current connection is null"; - return; - } - - // Execute a request on the main thread asynchronously - moveToThread(c->thread()); - QMetaObject::invokeMethod(this, &ThumbnailResponse::startRequest, - Qt::QueuedConnection); -} - -void ThumbnailResponse::startRequest() { - // Runs in the main thread, not QML thread - Q_ASSERT(QThread::currentThread() == c->thread()); - job = c->getThumbnail(mediaId, requestedSize); - // Connect to any possible outcome including abandonment - // to make sure the QML thread is not left stuck forever. - connect(job, &BaseJob::finished, this, &ThumbnailResponse::prepareResult); -} - -void ThumbnailResponse::prepareResult() { - Q_ASSERT(QThread::currentThread() == job->thread()); - Q_ASSERT(job->error() != BaseJob::Pending); - { - QWriteLocker _(&lock); - if (job->error() == BaseJob::Success) { - image = job->thumbnail(); - - QString localPath = QFileInfo(localFile).absolutePath(); - QDir dir; - if (!dir.exists(localPath)) - dir.mkpath(localPath); - - image.save(localFile); - - errorStr.clear(); - } else if (job->error() == BaseJob::Abandoned) { - errorStr = tr("Image request has been cancelled"); - qDebug() << "ThumbnailResponse: cancelled for" << mediaId; - } else { - errorStr = job->errorString(); - qWarning() << "ThumbnailResponse: no valid image for" << mediaId << "-" - << errorStr; +ThumbnailResponse::ThumbnailResponse(Quotient::Connection *c, QString id, const QSize &size) + : c(c) + , mediaId(std::move(id)) + , requestedSize(size) + , localFile(QStringLiteral("%1/image_provider/%2-%3x%4.png").arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation), mediaId, QString::number(requestedSize.width()), QString::number(requestedSize.height()))) + , errorStr("Image request hasn't started") +{ + if (requestedSize.isEmpty()) { + errorStr.clear(); + emit finished(); + return; } - job = nullptr; - } - emit finished(); + if (mediaId.count('/') != 1) { + errorStr = tr("Media id '%1' doesn't follow server/mediaId pattern").arg(mediaId); + emit finished(); + return; + } + + QImage cachedImage; + if (cachedImage.load(localFile)) { + image = cachedImage; + errorStr.clear(); + emit finished(); + return; + } + + if (!c) { + qWarning() << "Current connection is null"; + return; + } + + // Execute a request on the main thread asynchronously + moveToThread(c->thread()); + QMetaObject::invokeMethod(this, &ThumbnailResponse::startRequest, Qt::QueuedConnection); } -void ThumbnailResponse::doCancel() { - // Runs in the main thread, not QML thread - if (job) { +void ThumbnailResponse::startRequest() +{ + // Runs in the main thread, not QML thread + Q_ASSERT(QThread::currentThread() == c->thread()); + job = c->getThumbnail(mediaId, requestedSize); + // Connect to any possible outcome including abandonment + // to make sure the QML thread is not left stuck forever. + connect(job, &BaseJob::finished, this, &ThumbnailResponse::prepareResult); +} + +void ThumbnailResponse::prepareResult() +{ Q_ASSERT(QThread::currentThread() == job->thread()); - job->abandon(); - } + Q_ASSERT(job->error() != BaseJob::Pending); + { + QWriteLocker _(&lock); + if (job->error() == BaseJob::Success) { + image = job->thumbnail(); + + QString localPath = QFileInfo(localFile).absolutePath(); + QDir dir; + if (!dir.exists(localPath)) + dir.mkpath(localPath); + + image.save(localFile); + + errorStr.clear(); + } else if (job->error() == BaseJob::Abandoned) { + errorStr = tr("Image request has been cancelled"); + qDebug() << "ThumbnailResponse: cancelled for" << mediaId; + } else { + errorStr = job->errorString(); + qWarning() << "ThumbnailResponse: no valid image for" << mediaId << "-" << errorStr; + } + job = nullptr; + } + emit finished(); } -QQuickTextureFactory* ThumbnailResponse::textureFactory() const { - QReadLocker _(&lock); - return QQuickTextureFactory::textureFactoryForImage(image); +void ThumbnailResponse::doCancel() +{ + // Runs in the main thread, not QML thread + if (job) { + Q_ASSERT(QThread::currentThread() == job->thread()); + job->abandon(); + } } -QString ThumbnailResponse::errorString() const { - QReadLocker _(&lock); - return errorStr; +QQuickTextureFactory *ThumbnailResponse::textureFactory() const +{ + QReadLocker _(&lock); + return QQuickTextureFactory::textureFactoryForImage(image); } -void ThumbnailResponse::cancel() { - QMetaObject::invokeMethod(this, &ThumbnailResponse::doCancel, - Qt::QueuedConnection); +QString ThumbnailResponse::errorString() const +{ + QReadLocker _(&lock); + return errorStr; } -QQuickImageResponse* MatrixImageProvider::requestImageResponse( - const QString& id, - const QSize& requestedSize) { - return new ThumbnailResponse(m_connection.loadRelaxed(), id, requestedSize); +void ThumbnailResponse::cancel() +{ + QMetaObject::invokeMethod(this, &ThumbnailResponse::doCancel, Qt::QueuedConnection); +} + +QQuickImageResponse *MatrixImageProvider::requestImageResponse(const QString &id, const QSize &requestedSize) +{ + return new ThumbnailResponse(m_connection.loadRelaxed(), id, requestedSize); } diff --git a/src/matriximageprovider.h b/src/matriximageprovider.h index 6def9cf54..179124752 100644 --- a/src/matriximageprovider.h +++ b/src/matriximageprovider.h @@ -16,61 +16,63 @@ #include #include -namespace Quotient { +namespace Quotient +{ class Connection; } -class ThumbnailResponse : public QQuickImageResponse { - Q_OBJECT - public: - ThumbnailResponse(Quotient::Connection* c, - QString mediaId, - const QSize& requestedSize); - ~ThumbnailResponse() override = default; +class ThumbnailResponse : public QQuickImageResponse +{ + Q_OBJECT +public: + ThumbnailResponse(Quotient::Connection *c, QString mediaId, const QSize &requestedSize); + ~ThumbnailResponse() override = default; - private slots: - void startRequest(); - void prepareResult(); - void doCancel(); +private slots: + void startRequest(); + void prepareResult(); + void doCancel(); - private: - Quotient::Connection* c; - const QString mediaId; - const QSize requestedSize; - const QString localFile; - Quotient::MediaThumbnailJob* job = nullptr; +private: + Quotient::Connection *c; + const QString mediaId; + const QSize requestedSize; + const QString localFile; + Quotient::MediaThumbnailJob *job = nullptr; - QImage image; - QString errorStr; - mutable QReadWriteLock lock; // Guards ONLY these two members above + QImage image; + QString errorStr; + mutable QReadWriteLock lock; // Guards ONLY these two members above - QQuickTextureFactory* textureFactory() const override; - QString errorString() const override; - void cancel() override; + QQuickTextureFactory *textureFactory() const override; + QString errorString() const override; + void cancel() override; }; -class MatrixImageProvider : public QObject, public QQuickAsyncImageProvider { - Q_OBJECT - Q_PROPERTY(Quotient::Connection* connection READ connection WRITE - setConnection NOTIFY connectionChanged) - public: - explicit MatrixImageProvider() = default; +class MatrixImageProvider : public QObject, public QQuickAsyncImageProvider +{ + Q_OBJECT + Q_PROPERTY(Quotient::Connection *connection READ connection WRITE setConnection NOTIFY connectionChanged) +public: + explicit MatrixImageProvider() = default; - QQuickImageResponse* requestImageResponse( - const QString& id, - const QSize& requestedSize) override; + QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override; - Quotient::Connection* connection() { return m_connection; } - void setConnection(Quotient::Connection* connection) { - m_connection.storeRelaxed(connection); - emit connectionChanged(); - } + Quotient::Connection *connection() + { + return m_connection; + } + void setConnection(Quotient::Connection *connection) + { + m_connection.storeRelaxed(connection); + emit connectionChanged(); + } - signals: - void connectionChanged(); +signals: + void connectionChanged(); - private: - QAtomicPointer m_connection; +private: + QAtomicPointer m_connection; }; -#endif // MatrixImageProvider_H +#endif // MatrixImageProvider_H diff --git a/src/messageeventmodel.cpp b/src/messageeventmodel.cpp index edc73b17c..07fd99ec5 100644 --- a/src/messageeventmodel.cpp +++ b/src/messageeventmodel.cpp @@ -10,528 +10,482 @@ #include #include -#include // for qmlRegisterType() +#include // for qmlRegisterType() #include "utils.h" -QHash MessageEventModel::roleNames() const { - QHash roles = QAbstractItemModel::roleNames(); - roles[EventTypeRole] = "eventType"; - roles[MessageRole] = "message"; - roles[EventIdRole] = "eventId"; - roles[TimeRole] = "time"; - roles[SectionRole] = "section"; - roles[AuthorRole] = "author"; - roles[ContentRole] = "content"; - roles[ContentTypeRole] = "contentType"; - roles[HighlightRole] = "highlight"; - roles[ReadMarkerRole] = "readMarker"; - roles[SpecialMarksRole] = "marks"; - roles[LongOperationRole] = "progressInfo"; - roles[AnnotationRole] = "annotation"; - roles[EventResolvedTypeRole] = "eventResolvedType"; - roles[ReplyRole] = "reply"; - roles[UserMarkerRole] = "userMarker"; - roles[ShowAuthorRole] = "showAuthor"; - roles[ShowSectionRole] = "showSection"; - roles[ReactionRole] = "reaction"; - return roles; +QHash MessageEventModel::roleNames() const +{ + QHash roles = QAbstractItemModel::roleNames(); + roles[EventTypeRole] = "eventType"; + roles[MessageRole] = "message"; + roles[EventIdRole] = "eventId"; + roles[TimeRole] = "time"; + roles[SectionRole] = "section"; + roles[AuthorRole] = "author"; + roles[ContentRole] = "content"; + roles[ContentTypeRole] = "contentType"; + roles[HighlightRole] = "highlight"; + roles[ReadMarkerRole] = "readMarker"; + roles[SpecialMarksRole] = "marks"; + roles[LongOperationRole] = "progressInfo"; + roles[AnnotationRole] = "annotation"; + roles[EventResolvedTypeRole] = "eventResolvedType"; + roles[ReplyRole] = "reply"; + roles[UserMarkerRole] = "userMarker"; + roles[ShowAuthorRole] = "showAuthor"; + roles[ShowSectionRole] = "showSection"; + roles[ReactionRole] = "reaction"; + return roles; } -MessageEventModel::MessageEventModel(QObject* parent) - : QAbstractListModel(parent), m_currentRoom(nullptr) { - using namespace Quotient; - qmlRegisterType(); - qRegisterMetaType(); - qmlRegisterUncreatableType( - "Spectral", 0, 1, "EventStatus", "EventStatus is not an creatable type"); -} - -MessageEventModel::~MessageEventModel() {} - -void MessageEventModel::setRoom(SpectralRoom* room) { - if (room == m_currentRoom) - return; - - beginResetModel(); - if (m_currentRoom) { - m_currentRoom->disconnect(this); - } - - m_currentRoom = room; - if (room) { - lastReadEventId = room->readMarkerEventId(); - +MessageEventModel::MessageEventModel(QObject *parent) + : QAbstractListModel(parent) + , m_currentRoom(nullptr) +{ using namespace Quotient; - connect(m_currentRoom, &Room::aboutToAddNewMessages, this, - [=](RoomEventsRange events) { - beginInsertRows({}, timelineBaseIndex(), - timelineBaseIndex() + int(events.size()) - 1); - }); - connect(m_currentRoom, &Room::aboutToAddHistoricalMessages, this, - [=](RoomEventsRange events) { - if (rowCount() > 0) - rowBelowInserted = rowCount() - 1; // See #312 - beginInsertRows({}, rowCount(), - rowCount() + int(events.size()) - 1); - }); - connect(m_currentRoom, &Room::addedMessages, this, - [=](int lowest, int biggest) { - endInsertRows(); - if (biggest < m_currentRoom->maxTimelineIndex()) { - auto rowBelowInserted = m_currentRoom->maxTimelineIndex() - - biggest + timelineBaseIndex() - 1; - refreshEventRoles(rowBelowInserted, - {ShowAuthorRole}); - } - for (auto i = m_currentRoom->maxTimelineIndex() - biggest; - i <= m_currentRoom->maxTimelineIndex() - lowest; ++i) + qmlRegisterType(); + qRegisterMetaType(); + qmlRegisterUncreatableType("Spectral", 0, 1, "EventStatus", "EventStatus is not an creatable type"); +} + +MessageEventModel::~MessageEventModel() +{ +} + +void MessageEventModel::setRoom(SpectralRoom *room) +{ + if (room == m_currentRoom) + return; + + beginResetModel(); + if (m_currentRoom) { + m_currentRoom->disconnect(this); + } + + m_currentRoom = room; + if (room) { + lastReadEventId = room->readMarkerEventId(); + + using namespace Quotient; + connect(m_currentRoom, &Room::aboutToAddNewMessages, this, [=](RoomEventsRange events) { + beginInsertRows({}, timelineBaseIndex(), timelineBaseIndex() + int(events.size()) - 1); + }); + connect(m_currentRoom, &Room::aboutToAddHistoricalMessages, this, [=](RoomEventsRange events) { + if (rowCount() > 0) + rowBelowInserted = rowCount() - 1; // See #312 + beginInsertRows({}, rowCount(), rowCount() + int(events.size()) - 1); + }); + connect(m_currentRoom, &Room::addedMessages, this, [=](int lowest, int biggest) { + endInsertRows(); + if (biggest < m_currentRoom->maxTimelineIndex()) { + auto rowBelowInserted = m_currentRoom->maxTimelineIndex() - biggest + timelineBaseIndex() - 1; + refreshEventRoles(rowBelowInserted, {ShowAuthorRole}); + } + for (auto i = m_currentRoom->maxTimelineIndex() - biggest; i <= m_currentRoom->maxTimelineIndex() - lowest; ++i) refreshLastUserEvents(i); - }); - connect(m_currentRoom, &Room::pendingEventAboutToAdd, this, - [this] { beginInsertRows({}, 0, 0); }); - connect(m_currentRoom, &Room::pendingEventAdded, this, &MessageEventModel::endInsertRows); - connect(m_currentRoom, &Room::pendingEventAboutToMerge, this, - [this](RoomEvent*, int i) { - if (i == 0) - return; // No need to move anything, just refresh + }); + connect(m_currentRoom, &Room::pendingEventAboutToAdd, this, [this] { + beginInsertRows({}, 0, 0); + }); + connect(m_currentRoom, &Room::pendingEventAdded, this, &MessageEventModel::endInsertRows); + connect(m_currentRoom, &Room::pendingEventAboutToMerge, this, [this](RoomEvent *, int i) { + if (i == 0) + return; // No need to move anything, just refresh - movingEvent = true; - // Reverse i because row 0 is bottommost in the model - const auto row = timelineBaseIndex() - i - 1; - Q_ASSERT(beginMoveRows({}, row, row, {}, timelineBaseIndex())); - }); - connect(m_currentRoom, &Room::pendingEventMerged, this, [this] { - if (movingEvent) { - endMoveRows(); - movingEvent = false; - } - refreshRow(timelineBaseIndex()); // Refresh the looks - refreshLastUserEvents(0); - if (m_currentRoom->timelineSize() > 1) // Refresh above - refreshEventRoles(timelineBaseIndex() + 1, {ReadMarkerRole}); - if (timelineBaseIndex() > 0) // Refresh below, see #312 - refreshEventRoles(timelineBaseIndex() - 1, - {ShowAuthorRole}); - }); - connect(m_currentRoom, &Room::pendingEventChanged, this, - &MessageEventModel::refreshRow); - connect(m_currentRoom, &Room::pendingEventAboutToDiscard, this, - [this](int i) { beginRemoveRows({}, i, i); }); - connect(m_currentRoom, &Room::pendingEventDiscarded, this, - &MessageEventModel::endRemoveRows); - connect(m_currentRoom, &Room::readMarkerMoved, this, [this] { - refreshEventRoles( - std::exchange(lastReadEventId, m_currentRoom->readMarkerEventId()), - {ReadMarkerRole}); - refreshEventRoles(lastReadEventId, {ReadMarkerRole}); - }); - connect(m_currentRoom, &Room::replacedEvent, this, - [this](const RoomEvent* newEvent) { - refreshLastUserEvents(refreshEvent(newEvent->id()) - - timelineBaseIndex()); - }); - connect(m_currentRoom, &Room::updatedEvent, this, - [this](const QString& eventId) { - if (eventId.isEmpty()) { // How did we get here? + movingEvent = true; + // Reverse i because row 0 is bottommost in the model + const auto row = timelineBaseIndex() - i - 1; + Q_ASSERT(beginMoveRows({}, row, row, {}, timelineBaseIndex())); + }); + connect(m_currentRoom, &Room::pendingEventMerged, this, [this] { + if (movingEvent) { + endMoveRows(); + movingEvent = false; + } + refreshRow(timelineBaseIndex()); // Refresh the looks + refreshLastUserEvents(0); + if (m_currentRoom->timelineSize() > 1) // Refresh above + refreshEventRoles(timelineBaseIndex() + 1, {ReadMarkerRole}); + if (timelineBaseIndex() > 0) // Refresh below, see #312 + refreshEventRoles(timelineBaseIndex() - 1, {ShowAuthorRole}); + }); + connect(m_currentRoom, &Room::pendingEventChanged, this, &MessageEventModel::refreshRow); + connect(m_currentRoom, &Room::pendingEventAboutToDiscard, this, [this](int i) { + beginRemoveRows({}, i, i); + }); + connect(m_currentRoom, &Room::pendingEventDiscarded, this, &MessageEventModel::endRemoveRows); + connect(m_currentRoom, &Room::readMarkerMoved, this, [this] { + refreshEventRoles(std::exchange(lastReadEventId, m_currentRoom->readMarkerEventId()), {ReadMarkerRole}); + refreshEventRoles(lastReadEventId, {ReadMarkerRole}); + }); + connect(m_currentRoom, &Room::replacedEvent, this, [this](const RoomEvent *newEvent) { + refreshLastUserEvents(refreshEvent(newEvent->id()) - timelineBaseIndex()); + }); + connect(m_currentRoom, &Room::updatedEvent, this, [this](const QString &eventId) { + if (eventId.isEmpty()) { // How did we get here? return; - } - refreshEventRoles(eventId, {ReactionRole, Qt::DisplayRole}); - }); - connect(m_currentRoom, &Room::fileTransferProgress, this, - &MessageEventModel::refreshEvent); - connect(m_currentRoom, &Room::fileTransferCompleted, this, - &MessageEventModel::refreshEvent); - connect(m_currentRoom, &Room::fileTransferFailed, this, - &MessageEventModel::refreshEvent); - connect(m_currentRoom, &Room::fileTransferCancelled, this, - &MessageEventModel::refreshEvent); - connect(m_currentRoom, &Room::readMarkerForUserMoved, this, - [=](User*, QString fromEventId, QString toEventId) { - refreshEventRoles(fromEventId, {UserMarkerRole}); - refreshEventRoles(toEventId, {UserMarkerRole}); - }); - connect(m_currentRoom->connection(), &Connection::ignoredUsersListChanged, - this, [=] { - beginResetModel(); - endResetModel(); - }); - qDebug() << "Connected to room" << room->id() << "as" - << room->localUser()->id(); - } else - lastReadEventId.clear(); - endResetModel(); + } + refreshEventRoles(eventId, {ReactionRole, Qt::DisplayRole}); + }); + connect(m_currentRoom, &Room::fileTransferProgress, this, &MessageEventModel::refreshEvent); + connect(m_currentRoom, &Room::fileTransferCompleted, this, &MessageEventModel::refreshEvent); + connect(m_currentRoom, &Room::fileTransferFailed, this, &MessageEventModel::refreshEvent); + connect(m_currentRoom, &Room::fileTransferCancelled, this, &MessageEventModel::refreshEvent); + connect(m_currentRoom, &Room::readMarkerForUserMoved, this, [=](User *, QString fromEventId, QString toEventId) { + refreshEventRoles(fromEventId, {UserMarkerRole}); + refreshEventRoles(toEventId, {UserMarkerRole}); + }); + connect(m_currentRoom->connection(), &Connection::ignoredUsersListChanged, this, [=] { + beginResetModel(); + endResetModel(); + }); + qDebug() << "Connected to room" << room->id() << "as" << room->localUser()->id(); + } else + lastReadEventId.clear(); + endResetModel(); } -int MessageEventModel::refreshEvent(const QString& eventId) { - return refreshEventRoles(eventId); +int MessageEventModel::refreshEvent(const QString &eventId) +{ + return refreshEventRoles(eventId); } -void MessageEventModel::refreshRow(int row) { - refreshEventRoles(row); +void MessageEventModel::refreshRow(int row) +{ + refreshEventRoles(row); } -int MessageEventModel::timelineBaseIndex() const { - return m_currentRoom ? int(m_currentRoom->pendingEvents().size()) : 0; +int MessageEventModel::timelineBaseIndex() const +{ + return m_currentRoom ? int(m_currentRoom->pendingEvents().size()) : 0; } -void MessageEventModel::refreshEventRoles(int row, const QVector& roles) { - const auto idx = index(row); - emit dataChanged(idx, idx, roles); +void MessageEventModel::refreshEventRoles(int row, const QVector &roles) +{ + const auto idx = index(row); + emit dataChanged(idx, idx, roles); } -int MessageEventModel::refreshEventRoles(const QString& id, - const QVector& roles) { - // On 64-bit platforms, difference_type for std containers is long long - // but Qt uses int throughout its interfaces; hence casting to int below. - int row = -1; - // First try pendingEvents because it is almost always very short. - const auto pendingIt = m_currentRoom->findPendingEvent(id); - if (pendingIt != m_currentRoom->pendingEvents().end()) - row = int(pendingIt - m_currentRoom->pendingEvents().begin()); - else { - const auto timelineIt = m_currentRoom->findInTimeline(id); - if (timelineIt == m_currentRoom->timelineEdge()) { - qWarning() << "Trying to refresh inexistent event:" << id; - return -1; +int MessageEventModel::refreshEventRoles(const QString &id, const QVector &roles) +{ + // On 64-bit platforms, difference_type for std containers is long long + // but Qt uses int throughout its interfaces; hence casting to int below. + int row = -1; + // First try pendingEvents because it is almost always very short. + const auto pendingIt = m_currentRoom->findPendingEvent(id); + if (pendingIt != m_currentRoom->pendingEvents().end()) + row = int(pendingIt - m_currentRoom->pendingEvents().begin()); + else { + const auto timelineIt = m_currentRoom->findInTimeline(id); + if (timelineIt == m_currentRoom->timelineEdge()) { + qWarning() << "Trying to refresh inexistent event:" << id; + return -1; + } + row = int(timelineIt - m_currentRoom->messageEvents().rbegin()) + timelineBaseIndex(); } - row = int(timelineIt - m_currentRoom->messageEvents().rbegin()) + - timelineBaseIndex(); - } - refreshEventRoles(row, roles); - return row; + refreshEventRoles(row, roles); + return row; } -inline bool hasValidTimestamp(const Quotient::TimelineItem& ti) { - return ti->originTimestamp().isValid(); +inline bool hasValidTimestamp(const Quotient::TimelineItem &ti) +{ + return ti->originTimestamp().isValid(); } -QDateTime MessageEventModel::makeMessageTimestamp( - const Quotient::Room::rev_iter_t& baseIt) const { - const auto& timeline = m_currentRoom->messageEvents(); - auto ts = baseIt->event()->originTimestamp(); - if (ts.isValid()) - return ts; +QDateTime MessageEventModel::makeMessageTimestamp(const Quotient::Room::rev_iter_t &baseIt) const +{ + const auto &timeline = m_currentRoom->messageEvents(); + auto ts = baseIt->event()->originTimestamp(); + if (ts.isValid()) + return ts; - // The event is most likely redacted or just invalid. - // Look for the nearest date around and slap zero time to it. - using Quotient::TimelineItem; - auto rit = std::find_if(baseIt, timeline.rend(), hasValidTimestamp); - if (rit != timeline.rend()) - return {rit->event()->originTimestamp().date(), {0, 0}, Qt::LocalTime}; - auto it = std::find_if(baseIt.base(), timeline.end(), hasValidTimestamp); - if (it != timeline.end()) - return {it->event()->originTimestamp().date(), {0, 0}, Qt::LocalTime}; + // The event is most likely redacted or just invalid. + // Look for the nearest date around and slap zero time to it. + using Quotient::TimelineItem; + auto rit = std::find_if(baseIt, timeline.rend(), hasValidTimestamp); + if (rit != timeline.rend()) + return {rit->event()->originTimestamp().date(), {0, 0}, Qt::LocalTime}; + auto it = std::find_if(baseIt.base(), timeline.end(), hasValidTimestamp); + if (it != timeline.end()) + return {it->event()->originTimestamp().date(), {0, 0}, Qt::LocalTime}; - // What kind of room is that?.. - qCritical() << "No valid timestamps in the room timeline!"; - return {}; -} - -QString MessageEventModel::renderDate(QDateTime timestamp) const { - auto date = timestamp.toLocalTime().date(); - if (date == QDate::currentDate()) - return tr("Today"); - if (date == QDate::currentDate().addDays(-1)) - return tr("Yesterday"); - if (date == QDate::currentDate().addDays(-2)) - return tr("The day before yesterday"); - if (date > QDate::currentDate().addDays(-7)) - return date.toString("dddd"); - - return QLocale::system().toString(date, QLocale::ShortFormat); -} - -void MessageEventModel::refreshLastUserEvents(int baseTimelineRow) { - if (!m_currentRoom || m_currentRoom->timelineSize() <= baseTimelineRow) - return; - - const auto& timelineBottom = m_currentRoom->messageEvents().rbegin(); - const auto& lastSender = (*(timelineBottom + baseTimelineRow))->senderId(); - const auto limit = timelineBottom + std::min(baseTimelineRow + 10, - m_currentRoom->timelineSize()); - for (auto it = timelineBottom + std::max(baseTimelineRow - 10, 0); - it != limit; ++it) { - if ((*it)->senderId() == lastSender) { - auto idx = index(it - timelineBottom); - emit dataChanged(idx, idx); - } - } -} - -int MessageEventModel::rowCount(const QModelIndex& parent) const { - if (!m_currentRoom || parent.isValid()) - return 0; - return m_currentRoom->timelineSize(); -} - -inline QVariantMap userAtEvent(SpectralUser* user, - SpectralRoom* room, - const RoomEvent& evt) { - return QVariantMap{ - {"isLocalUser", user->id() == room->localUser()->id()}, - {"id", user->id()}, - {"avatarMediaId", user->avatarMediaId(room)}, - {"avatarUrl", user->avatarUrl(room)}, - {"displayName", user->displayname(room)}, - {"color", user->color()}, - {"object", QVariant::fromValue(user)}, - }; -} - -QVariant MessageEventModel::data(const QModelIndex& idx, int role) const { - const auto row = idx.row(); - - if (!m_currentRoom || row < 0 || - row >= int(m_currentRoom->pendingEvents().size()) + - m_currentRoom->timelineSize()) + // What kind of room is that?.. + qCritical() << "No valid timestamps in the room timeline!"; return {}; +} - bool isPending = row < timelineBaseIndex(); - const auto timelineIt = m_currentRoom->messageEvents().crbegin() + - std::max(0, row - timelineBaseIndex()); - const auto pendingIt = m_currentRoom->pendingEvents().crbegin() + - std::min(row, timelineBaseIndex()); - const auto& evt = isPending ? **pendingIt : **timelineIt; +QString MessageEventModel::renderDate(QDateTime timestamp) const +{ + auto date = timestamp.toLocalTime().date(); + if (date == QDate::currentDate()) + return tr("Today"); + if (date == QDate::currentDate().addDays(-1)) + return tr("Yesterday"); + if (date == QDate::currentDate().addDays(-2)) + return tr("The day before yesterday"); + if (date > QDate::currentDate().addDays(-7)) + return date.toString("dddd"); - if (role == Qt::DisplayRole) { - return m_currentRoom->eventToString(evt, Qt::RichText); - } + return QLocale::system().toString(date, QLocale::ShortFormat); +} - if (role == MessageRole) { - return m_currentRoom->eventToString(evt); - } +void MessageEventModel::refreshLastUserEvents(int baseTimelineRow) +{ + if (!m_currentRoom || m_currentRoom->timelineSize() <= baseTimelineRow) + return; - if (role == Qt::ToolTipRole) { - return evt.originalJson(); - } - - if (role == EventTypeRole) { - if (auto e = eventCast(&evt)) { - switch (e->msgtype()) { - case MessageEventType::Emote: - return "emote"; - case MessageEventType::Notice: - return "notice"; - case MessageEventType::Image: - return "image"; - case MessageEventType::Audio: - return "audio"; - case MessageEventType::Video: - return "video"; - default: - break; - } - if (e->hasFileContent()) { - return "file"; - } - - return "message"; + const auto &timelineBottom = m_currentRoom->messageEvents().rbegin(); + const auto &lastSender = (*(timelineBottom + baseTimelineRow))->senderId(); + const auto limit = timelineBottom + std::min(baseTimelineRow + 10, m_currentRoom->timelineSize()); + for (auto it = timelineBottom + std::max(baseTimelineRow - 10, 0); it != limit; ++it) { + if ((*it)->senderId() == lastSender) { + auto idx = index(it - timelineBottom); + emit dataChanged(idx, idx); + } } - if (evt.isStateEvent()) - return "state"; +} - return "other"; - } +int MessageEventModel::rowCount(const QModelIndex &parent) const +{ + if (!m_currentRoom || parent.isValid()) + return 0; + return m_currentRoom->timelineSize(); +} - if (role == EventResolvedTypeRole) - return EventTypeRegistry::getMatrixType(evt.type()); - - if (role == AuthorRole) { - auto author = static_cast( - isPending ? m_currentRoom->localUser() - : m_currentRoom->user(evt.senderId())); - return userAtEvent(author, m_currentRoom, evt); - } - - if (role == ContentTypeRole) { - if (auto e = eventCast(&evt)) { - const auto& contentType = e->mimeType().name(); - return contentType == "text/plain" ? QStringLiteral("text/html") - : contentType; - } - return QStringLiteral("text/plain"); - } - - if (role == ContentRole) { - if (evt.isRedacted()) { - auto reason = evt.redactedBecause()->reason(); - return (reason.isEmpty()) - ? tr("[REDACTED]") - : tr("[REDACTED: %1]").arg(evt.redactedBecause()->reason()); - } - - if (auto e = eventCast(&evt)) { - // Cannot use e.contentJson() here because some - // EventContent classes inject values into the copy of the - // content JSON stored in EventContent::Base - return e->hasFileContent() - ? QVariant::fromValue(e->content()->originalJson) - : QVariant(); +inline QVariantMap userAtEvent(SpectralUser *user, SpectralRoom *room, const RoomEvent &evt) +{ + return QVariantMap { + {"isLocalUser", user->id() == room->localUser()->id()}, + {"id", user->id()}, + {"avatarMediaId", user->avatarMediaId(room)}, + {"avatarUrl", user->avatarUrl(room)}, + {"displayName", user->displayname(room)}, + {"color", user->color()}, + {"object", QVariant::fromValue(user)}, }; - } - - if (role == HighlightRole) - return m_currentRoom->isEventHighlighted(&evt); - - if (role == ReadMarkerRole) - return evt.id() == lastReadEventId && row > timelineBaseIndex(); - - if (role == SpecialMarksRole) { - if (isPending) - return pendingIt->deliveryStatus(); - - auto* memberEvent = timelineIt->viewAs(); - if (memberEvent) { - if ((memberEvent->isJoin() || memberEvent->isLeave()) && - !Settings().value("UI/show_joinleave", true).toBool()) - return EventStatus::Hidden; - } - - if (is(evt) || is(evt)) - return EventStatus::Hidden; - if (evt.isRedacted()) - return EventStatus::Hidden; - - if (evt.isStateEvent() && - static_cast(evt).repeatsState()) - return EventStatus::Hidden; - - if (auto e = eventCast(&evt)) { - if (!e->replacedEvent().isEmpty() && e->replacedEvent() != e->id()) { - return EventStatus::Hidden; - } - } - - if (m_currentRoom->connection()->isIgnored( - m_currentRoom->user(evt.senderId()))) - return EventStatus::Hidden; - - return EventStatus::Normal; - } - - if (role == EventIdRole) - return !evt.id().isEmpty() ? evt.id() : evt.transactionId(); - - if (role == LongOperationRole) { - if (auto e = eventCast(&evt)) - if (e->hasFileContent()) - return QVariant::fromValue(m_currentRoom->fileTransferInfo(e->id())); - } - - if (role == AnnotationRole) - if (isPending) - return pendingIt->annotation(); - - if (role == TimeRole || role == SectionRole) { - auto ts = - isPending ? pendingIt->lastUpdated() : makeMessageTimestamp(timelineIt); - return role == TimeRole ? QVariant(ts) : renderDate(ts); - } - - if (role == UserMarkerRole) { - QVariantList variantList; - for (User* user : m_currentRoom->usersAtEventId(evt.id())) { - if (user == m_currentRoom->localUser()) - continue; - variantList.append(QVariant::fromValue(user)); - } - return variantList; - } - - if (role == ReplyRole) { - const QString& replyEventId = evt.contentJson()["m.relates_to"] - .toObject()["m.in_reply_to"] - .toObject()["event_id"] - .toString(); - if (replyEventId.isEmpty()) - return {}; - const auto replyIt = m_currentRoom->findInTimeline(replyEventId); - if (replyIt == m_currentRoom->timelineEdge()) - return {}; - const auto& replyEvt = **replyIt; - - return QVariantMap{ - {"eventId", replyEventId}, - {"display", m_currentRoom->eventToString(replyEvt, Qt::RichText)}, - {"author", userAtEvent(static_cast( - m_currentRoom->user(replyEvt.senderId())), - m_currentRoom, evt)}}; - } - - if (role == ShowAuthorRole) { - for (auto r = row + 1; r < rowCount(); ++r) { - auto i = index(r); - if (data(i, SpecialMarksRole) != EventStatus::Hidden) { - return data(i, AuthorRole) != data(idx, AuthorRole) || - data(i, EventTypeRole) != data(idx, EventTypeRole) || - data(idx, TimeRole) - .toDateTime() - .msecsTo(data(i, TimeRole).toDateTime()) > 600000; - } - } - - return true; - } - - if (role == ShowSectionRole) { - for (auto r = row + 1; r < rowCount(); ++r) { - auto i = index(r); - if (data(i, SpecialMarksRole) != EventStatus::Hidden) { - return data(i, TimeRole) - .toDateTime() - .msecsTo(data(idx, TimeRole).toDateTime()) > 600000; - } - } - - return true; - } - - if (role == ReactionRole) { - const auto& annotations = - m_currentRoom->relatedEvents(evt, EventRelation::Annotation()); - if (annotations.isEmpty()) - return {}; - QMap> reactions = {}; - for (const auto& a : annotations) { - if (a->isRedacted()) // Just in case? - continue; - if (auto e = eventCast(a)) - reactions[e->relation().key].append( - static_cast(m_currentRoom->user(e->senderId()))); - } - - if (reactions.isEmpty()) { - return {}; - } - - QVariantList res = {}; - auto i = reactions.constBegin(); - while (i != reactions.constEnd()) { - QVariantList authors; - for (auto author : i.value()) { - authors.append(userAtEvent(author, m_currentRoom, evt)); - } - bool hasLocalUser = i.value().contains( - static_cast(m_currentRoom->localUser())); - res.append(QVariantMap{{"reaction", i.key()}, - {"count", i.value().count()}, - {"authors", authors}, - {"hasLocalUser", hasLocalUser}}); - ++i; - } - - return res; - } - - return {}; } -int MessageEventModel::eventIDToIndex(const QString& eventID) const { - const auto it = m_currentRoom->findInTimeline(eventID); - if (it == m_currentRoom->timelineEdge()) { - qWarning() << "Trying to find inexistent event:" << eventID; - return -1; - } - return it - m_currentRoom->messageEvents().rbegin() + timelineBaseIndex(); +QVariant MessageEventModel::data(const QModelIndex &idx, int role) const +{ + const auto row = idx.row(); + + if (!m_currentRoom || row < 0 || row >= int(m_currentRoom->pendingEvents().size()) + m_currentRoom->timelineSize()) + return {}; + + bool isPending = row < timelineBaseIndex(); + const auto timelineIt = m_currentRoom->messageEvents().crbegin() + std::max(0, row - timelineBaseIndex()); + const auto pendingIt = m_currentRoom->pendingEvents().crbegin() + std::min(row, timelineBaseIndex()); + const auto &evt = isPending ? **pendingIt : **timelineIt; + + if (role == Qt::DisplayRole) { + return m_currentRoom->eventToString(evt, Qt::RichText); + } + + if (role == MessageRole) { + return m_currentRoom->eventToString(evt); + } + + if (role == Qt::ToolTipRole) { + return evt.originalJson(); + } + + if (role == EventTypeRole) { + if (auto e = eventCast(&evt)) { + switch (e->msgtype()) { + case MessageEventType::Emote: + return "emote"; + case MessageEventType::Notice: + return "notice"; + case MessageEventType::Image: + return "image"; + case MessageEventType::Audio: + return "audio"; + case MessageEventType::Video: + return "video"; + default: + break; + } + if (e->hasFileContent()) { + return "file"; + } + + return "message"; + } + if (evt.isStateEvent()) + return "state"; + + return "other"; + } + + if (role == EventResolvedTypeRole) + return EventTypeRegistry::getMatrixType(evt.type()); + + if (role == AuthorRole) { + auto author = static_cast(isPending ? m_currentRoom->localUser() : m_currentRoom->user(evt.senderId())); + return userAtEvent(author, m_currentRoom, evt); + } + + if (role == ContentTypeRole) { + if (auto e = eventCast(&evt)) { + const auto &contentType = e->mimeType().name(); + return contentType == "text/plain" ? QStringLiteral("text/html") : contentType; + } + return QStringLiteral("text/plain"); + } + + if (role == ContentRole) { + if (evt.isRedacted()) { + auto reason = evt.redactedBecause()->reason(); + return (reason.isEmpty()) ? tr("[REDACTED]") : tr("[REDACTED: %1]").arg(evt.redactedBecause()->reason()); + } + + if (auto e = eventCast(&evt)) { + // Cannot use e.contentJson() here because some + // EventContent classes inject values into the copy of the + // content JSON stored in EventContent::Base + return e->hasFileContent() ? QVariant::fromValue(e->content()->originalJson) : QVariant(); + }; + } + + if (role == HighlightRole) + return m_currentRoom->isEventHighlighted(&evt); + + if (role == ReadMarkerRole) + return evt.id() == lastReadEventId && row > timelineBaseIndex(); + + if (role == SpecialMarksRole) { + if (isPending) + return pendingIt->deliveryStatus(); + + auto *memberEvent = timelineIt->viewAs(); + if (memberEvent) { + if ((memberEvent->isJoin() || memberEvent->isLeave()) && !Settings().value("UI/show_joinleave", true).toBool()) + return EventStatus::Hidden; + } + + if (is(evt) || is(evt)) + return EventStatus::Hidden; + if (evt.isRedacted()) + return EventStatus::Hidden; + + if (evt.isStateEvent() && static_cast(evt).repeatsState()) + return EventStatus::Hidden; + + if (auto e = eventCast(&evt)) { + if (!e->replacedEvent().isEmpty() && e->replacedEvent() != e->id()) { + return EventStatus::Hidden; + } + } + + if (m_currentRoom->connection()->isIgnored(m_currentRoom->user(evt.senderId()))) + return EventStatus::Hidden; + + return EventStatus::Normal; + } + + if (role == EventIdRole) + return !evt.id().isEmpty() ? evt.id() : evt.transactionId(); + + if (role == LongOperationRole) { + if (auto e = eventCast(&evt)) + if (e->hasFileContent()) + return QVariant::fromValue(m_currentRoom->fileTransferInfo(e->id())); + } + + if (role == AnnotationRole) + if (isPending) + return pendingIt->annotation(); + + if (role == TimeRole || role == SectionRole) { + auto ts = isPending ? pendingIt->lastUpdated() : makeMessageTimestamp(timelineIt); + return role == TimeRole ? QVariant(ts) : renderDate(ts); + } + + if (role == UserMarkerRole) { + QVariantList variantList; + for (User *user : m_currentRoom->usersAtEventId(evt.id())) { + if (user == m_currentRoom->localUser()) + continue; + variantList.append(QVariant::fromValue(user)); + } + return variantList; + } + + if (role == ReplyRole) { + const QString &replyEventId = evt.contentJson()["m.relates_to"].toObject()["m.in_reply_to"].toObject()["event_id"].toString(); + if (replyEventId.isEmpty()) + return {}; + const auto replyIt = m_currentRoom->findInTimeline(replyEventId); + if (replyIt == m_currentRoom->timelineEdge()) + return {}; + const auto &replyEvt = **replyIt; + + return QVariantMap {{"eventId", replyEventId}, {"display", m_currentRoom->eventToString(replyEvt, Qt::RichText)}, {"author", userAtEvent(static_cast(m_currentRoom->user(replyEvt.senderId())), m_currentRoom, evt)}}; + } + + if (role == ShowAuthorRole) { + for (auto r = row + 1; r < rowCount(); ++r) { + auto i = index(r); + if (data(i, SpecialMarksRole) != EventStatus::Hidden) { + return data(i, AuthorRole) != data(idx, AuthorRole) || data(i, EventTypeRole) != data(idx, EventTypeRole) || data(idx, TimeRole).toDateTime().msecsTo(data(i, TimeRole).toDateTime()) > 600000; + } + } + + return true; + } + + if (role == ShowSectionRole) { + for (auto r = row + 1; r < rowCount(); ++r) { + auto i = index(r); + if (data(i, SpecialMarksRole) != EventStatus::Hidden) { + return data(i, TimeRole).toDateTime().msecsTo(data(idx, TimeRole).toDateTime()) > 600000; + } + } + + return true; + } + + if (role == ReactionRole) { + const auto &annotations = m_currentRoom->relatedEvents(evt, EventRelation::Annotation()); + if (annotations.isEmpty()) + return {}; + QMap> reactions = {}; + for (const auto &a : annotations) { + if (a->isRedacted()) // Just in case? + continue; + if (auto e = eventCast(a)) + reactions[e->relation().key].append(static_cast(m_currentRoom->user(e->senderId()))); + } + + if (reactions.isEmpty()) { + return {}; + } + + QVariantList res = {}; + auto i = reactions.constBegin(); + while (i != reactions.constEnd()) { + QVariantList authors; + for (auto author : i.value()) { + authors.append(userAtEvent(author, m_currentRoom, evt)); + } + bool hasLocalUser = i.value().contains(static_cast(m_currentRoom->localUser())); + res.append(QVariantMap {{"reaction", i.key()}, {"count", i.value().count()}, {"authors", authors}, {"hasLocalUser", hasLocalUser}}); + ++i; + } + + return res; + } + + return {}; +} + +int MessageEventModel::eventIDToIndex(const QString &eventID) const +{ + const auto it = m_currentRoom->findInTimeline(eventID); + if (it == m_currentRoom->timelineEdge()) { + qWarning() << "Trying to find inexistent event:" << eventID; + return -1; + } + return it - m_currentRoom->messageEvents().rbegin() + timelineBaseIndex(); } diff --git a/src/messageeventmodel.h b/src/messageeventmodel.h index 97fc45be7..4a67b5cc0 100644 --- a/src/messageeventmodel.h +++ b/src/messageeventmodel.h @@ -6,80 +6,82 @@ #include "room.h" #include "spectralroom.h" -class MessageEventModel : public QAbstractListModel { - Q_OBJECT - Q_PROPERTY(SpectralRoom* room READ room WRITE setRoom NOTIFY roomChanged) +class MessageEventModel : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(SpectralRoom *room READ room WRITE setRoom NOTIFY roomChanged) - public: - enum EventRoles { - EventTypeRole = Qt::UserRole + 1, - MessageRole, - EventIdRole, - TimeRole, - SectionRole, - AuthorRole, - ContentRole, - ContentTypeRole, - HighlightRole, - ReadMarkerRole, - SpecialMarksRole, - LongOperationRole, - AnnotationRole, - UserMarkerRole, +public: + enum EventRoles { + EventTypeRole = Qt::UserRole + 1, + MessageRole, + EventIdRole, + TimeRole, + SectionRole, + AuthorRole, + ContentRole, + ContentTypeRole, + HighlightRole, + ReadMarkerRole, + SpecialMarksRole, + LongOperationRole, + AnnotationRole, + UserMarkerRole, - ReplyRole, + ReplyRole, - ShowAuthorRole, - ShowSectionRole, + ShowAuthorRole, + ShowSectionRole, - ReactionRole, + ReactionRole, - // For debugging - EventResolvedTypeRole, - }; - Q_ENUM(EventRoles) + // For debugging + EventResolvedTypeRole, + }; + Q_ENUM(EventRoles) - enum BubbleShapes { - NoShape = 0, - BeginShape, - MiddleShape, - EndShape, - }; + enum BubbleShapes { + NoShape = 0, + BeginShape, + MiddleShape, + EndShape, + }; - explicit MessageEventModel(QObject* parent = nullptr); - ~MessageEventModel() override; + explicit MessageEventModel(QObject *parent = nullptr); + ~MessageEventModel() override; - SpectralRoom* room() const { return m_currentRoom; } - void setRoom(SpectralRoom* room); + SpectralRoom *room() const + { + return m_currentRoom; + } + void setRoom(SpectralRoom *room); - int rowCount(const QModelIndex& parent = QModelIndex()) const override; - QVariant data(const QModelIndex& index, - int role = Qt::DisplayRole) const override; - QHash roleNames() const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QHash roleNames() const override; - Q_INVOKABLE int eventIDToIndex(const QString& eventID) const; + Q_INVOKABLE int eventIDToIndex(const QString &eventID) const; - private slots: - int refreshEvent(const QString& eventId); - void refreshRow(int row); +private slots: + int refreshEvent(const QString &eventId); + void refreshRow(int row); - private: - SpectralRoom* m_currentRoom = nullptr; - QString lastReadEventId; - int rowBelowInserted = -1; - bool movingEvent = 0; +private: + SpectralRoom *m_currentRoom = nullptr; + QString lastReadEventId; + int rowBelowInserted = -1; + bool movingEvent = 0; - int timelineBaseIndex() const; - QDateTime makeMessageTimestamp( - const Quotient::Room::rev_iter_t& baseIt) const; - QString renderDate(QDateTime timestamp) const; + int timelineBaseIndex() const; + QDateTime makeMessageTimestamp(const Quotient::Room::rev_iter_t &baseIt) const; + QString renderDate(QDateTime timestamp) const; - void refreshLastUserEvents(int baseRow); - void refreshEventRoles(int row, const QVector& roles = {}); - int refreshEventRoles(const QString& eventId, const QVector& roles = {}); + void refreshLastUserEvents(int baseRow); + void refreshEventRoles(int row, const QVector &roles = {}); + int refreshEventRoles(const QString &eventId, const QVector &roles = {}); - signals: - void roomChanged(); +signals: + void roomChanged(); }; -#endif // MESSAGEEVENTMODEL_H +#endif // MESSAGEEVENTMODEL_H diff --git a/src/notifications/manager.h b/src/notifications/manager.h index 8b6973bd5..fa801d6c7 100644 --- a/src/notifications/manager.h +++ b/src/notifications/manager.h @@ -12,45 +12,39 @@ #endif struct roomEventId { - QString roomId; - QString eventId; + QString roomId; + QString eventId; }; -class NotificationsManager : public QObject { - Q_OBJECT - public: - NotificationsManager(QObject* parent = nullptr); +class NotificationsManager : public QObject +{ + Q_OBJECT +public: + NotificationsManager(QObject *parent = nullptr); - signals: - void notificationClicked(const QString roomId, const QString eventId); +signals: + void notificationClicked(const QString roomId, const QString eventId); - private: +private: #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) - QDBusInterface dbus; - bool serverSupportsHtml = false; - uint showNotification(const QString summary, - const QString text, - const QImage image); + QDBusInterface dbus; + bool serverSupportsHtml = false; + uint showNotification(const QString summary, const QString text, const QImage image); #endif - // notification ID to (room ID, event ID) - QMap notificationIds; + // notification ID to (room ID, event ID) + QMap notificationIds; - // these slots are platform specific (D-Bus only) - // but Qt slot declarations can not be inside an ifdef! - public slots: - void actionInvoked(uint id, QString action); - void notificationClosed(uint id, uint reason); + // these slots are platform specific (D-Bus only) + // but Qt slot declarations can not be inside an ifdef! +public slots: + void actionInvoked(uint id, QString action); + void notificationClosed(uint id, uint reason); - void postNotification(const QString& roomId, - const QString& eventId, - const QString& roomName, - const QString& senderName, - const QString& text, - const QImage& icon); + void postNotification(const QString &roomId, const QString &eventId, const QString &roomName, const QString &senderName, const QString &text, const QImage &icon); }; #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) -QDBusArgument& operator<<(QDBusArgument& arg, const QImage& image); -const QDBusArgument& operator>>(const QDBusArgument& arg, QImage&); +QDBusArgument &operator<<(QDBusArgument &arg, const QImage &image); +const QDBusArgument &operator>>(const QDBusArgument &arg, QImage &); #endif diff --git a/src/notifications/managerlinux.cpp b/src/notifications/managerlinux.cpp index a87dc56bb..db2d8ef69 100644 --- a/src/notifications/managerlinux.cpp +++ b/src/notifications/managerlinux.cpp @@ -8,36 +8,28 @@ #include NotificationsManager::NotificationsManager(QObject *parent) - : QObject(parent), - dbus("org.freedesktop.Notifications", "/org/freedesktop/Notifications", - "org.freedesktop.Notifications", QDBusConnection::sessionBus(), - this) { - qDBusRegisterMetaType(); + : QObject(parent) + , dbus("org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications", QDBusConnection::sessionBus(), this) +{ + qDBusRegisterMetaType(); - const QDBusReply capabilitiesReply = dbus.call("GetCapabilities"); + const QDBusReply capabilitiesReply = dbus.call("GetCapabilities"); - if (capabilitiesReply.isValid()) { - const QStringList capabilities = capabilitiesReply.value(); - serverSupportsHtml = capabilities.contains("body-markup"); - } else { - qWarning() << "Could not get notification server capabilities" << capabilitiesReply.error(); - } + if (capabilitiesReply.isValid()) { + const QStringList capabilities = capabilitiesReply.value(); + serverSupportsHtml = capabilities.contains("body-markup"); + } else { + qWarning() << "Could not get notification server capabilities" << capabilitiesReply.error(); + } - QDBusConnection::sessionBus().connect( - "org.freedesktop.Notifications", "/org/freedesktop/Notifications", - "org.freedesktop.Notifications", "ActionInvoked", this, - SLOT(actionInvoked(uint, QString))); - QDBusConnection::sessionBus().connect( - "org.freedesktop.Notifications", "/org/freedesktop/Notifications", - "org.freedesktop.Notifications", "NotificationClosed", this, - SLOT(notificationClosed(uint, uint))); + QDBusConnection::sessionBus().connect("org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications", "ActionInvoked", this, SLOT(actionInvoked(uint, QString))); + QDBusConnection::sessionBus().connect("org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications", "NotificationClosed", this, SLOT(notificationClosed(uint, uint))); } -void NotificationsManager::postNotification( - const QString &roomid, const QString &eventid, const QString &roomname, - const QString &sender, const QString &text, const QImage &icon) { - uint id = showNotification(sender + " (" + roomname + ")", text, icon); - notificationIds[id] = roomEventId{roomid, eventid}; +void NotificationsManager::postNotification(const QString &roomid, const QString &eventid, const QString &roomname, const QString &sender, const QString &text, const QImage &icon) +{ + uint id = showNotification(sender + " (" + roomname + ")", text, icon); + notificationIds[id] = roomEventId {roomid, eventid}; } /** * This function is based on code from @@ -45,63 +37,59 @@ void NotificationsManager::postNotification( * Copyright (C) 2012 Roland Hieber * Licensed under the GNU General Public License, version 3 */ -uint NotificationsManager::showNotification(const QString summary, - const QString text, - const QImage image) { - QImage croppedImage; - QRect rect = image.rect(); - if (rect.width() != rect.height()) { - if (rect.width() > rect.height()) { - QRect crop((rect.width() - rect.height()) / 2, 0, rect.height(), - rect.height()); - croppedImage = image.copy(crop); +uint NotificationsManager::showNotification(const QString summary, const QString text, const QImage image) +{ + QImage croppedImage; + QRect rect = image.rect(); + if (rect.width() != rect.height()) { + if (rect.width() > rect.height()) { + QRect crop((rect.width() - rect.height()) / 2, 0, rect.height(), rect.height()); + croppedImage = image.copy(crop); + } else { + QRect crop(0, (rect.height() - rect.width()) / 2, rect.width(), rect.width()); + croppedImage = image.copy(crop); + } } else { - QRect crop(0, (rect.height() - rect.width()) / 2, rect.width(), - rect.width()); - croppedImage = image.copy(crop); + croppedImage = image; } - } else { - croppedImage = image; - } - const QString body = serverSupportsHtml ? text.toHtmlEscaped() : text; + const QString body = serverSupportsHtml ? text.toHtmlEscaped() : text; - QVariantMap hints; - hints["image-data"] = croppedImage; - hints["desktop-entry"] = "org.eu.encom.spectral"; - QList argumentList; - argumentList << "Spectral"; // app_name - argumentList << uint(0); // replace_id - argumentList << ""; // app_icon - argumentList << summary; // summary - argumentList << body; // body - argumentList << (QStringList("default") << "reply"); // actions - argumentList << hints; // hints - argumentList << int(-1); // timeout in ms + QVariantMap hints; + hints["image-data"] = croppedImage; + hints["desktop-entry"] = "org.eu.encom.spectral"; + QList argumentList; + argumentList << "Spectral"; // app_name + argumentList << uint(0); // replace_id + argumentList << ""; // app_icon + argumentList << summary; // summary + argumentList << body; // body + argumentList << (QStringList("default") << "reply"); // actions + argumentList << hints; // hints + argumentList << int(-1); // timeout in ms - static QDBusInterface notifyApp("org.freedesktop.Notifications", - "/org/freedesktop/Notifications", - "org.freedesktop.Notifications"); - QDBusMessage reply = - notifyApp.callWithArgumentList(QDBus::AutoDetect, "Notify", argumentList); - if (reply.type() == QDBusMessage::ErrorMessage) { - qDebug() << "D-Bus Error:" << reply.errorMessage(); - return 0; - } else { - return reply.arguments().first().toUInt(); - } + static QDBusInterface notifyApp("org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications"); + QDBusMessage reply = notifyApp.callWithArgumentList(QDBus::AutoDetect, "Notify", argumentList); + if (reply.type() == QDBusMessage::ErrorMessage) { + qDebug() << "D-Bus Error:" << reply.errorMessage(); + return 0; + } else { + return reply.arguments().first().toUInt(); + } } -void NotificationsManager::actionInvoked(uint id, QString action) { - if (action == "default" && notificationIds.contains(id)) { - roomEventId idEntry = notificationIds[id]; - emit notificationClicked(idEntry.roomId, idEntry.eventId); - } +void NotificationsManager::actionInvoked(uint id, QString action) +{ + if (action == "default" && notificationIds.contains(id)) { + roomEventId idEntry = notificationIds[id]; + emit notificationClicked(idEntry.roomId, idEntry.eventId); + } } -void NotificationsManager::notificationClosed(uint id, uint reason) { - Q_UNUSED(reason); - notificationIds.remove(id); +void NotificationsManager::notificationClosed(uint id, uint reason) +{ + Q_UNUSED(reason); + notificationIds.remove(id); } /** @@ -113,50 +101,52 @@ void NotificationsManager::notificationClosed(uint id, uint reason) { * * Copyright 2010, David Sansome */ -QDBusArgument &operator<<(QDBusArgument &arg, const QImage &image) { - if (image.isNull()) { - arg.beginStructure(); - arg << 0 << 0 << 0 << false << 0 << 0 << QByteArray(); - arg.endStructure(); - return arg; - } +QDBusArgument &operator<<(QDBusArgument &arg, const QImage &image) +{ + if (image.isNull()) { + arg.beginStructure(); + arg << 0 << 0 << 0 << false << 0 << 0 << QByteArray(); + arg.endStructure(); + return arg; + } - QImage scaled = image.scaledToHeight(100, Qt::SmoothTransformation); - scaled = scaled.convertToFormat(QImage::Format_ARGB32); + QImage scaled = image.scaledToHeight(100, Qt::SmoothTransformation); + scaled = scaled.convertToFormat(QImage::Format_ARGB32); #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - // ABGR -> ARGB - QImage i = scaled.rgbSwapped(); + // ABGR -> ARGB + QImage i = scaled.rgbSwapped(); #else - // ABGR -> GBAR - QImage i(scaled.size(), scaled.format()); - for (int y = 0; y < i.height(); ++y) { - QRgb *p = (QRgb *)scaled.scanLine(y); - QRgb *q = (QRgb *)i.scanLine(y); - QRgb *end = p + scaled.width(); - while (p < end) { - *q = qRgba(qGreen(*p), qBlue(*p), qAlpha(*p), qRed(*p)); - p++; - q++; + // ABGR -> GBAR + QImage i(scaled.size(), scaled.format()); + for (int y = 0; y < i.height(); ++y) { + QRgb *p = (QRgb *)scaled.scanLine(y); + QRgb *q = (QRgb *)i.scanLine(y); + QRgb *end = p + scaled.width(); + while (p < end) { + *q = qRgba(qGreen(*p), qBlue(*p), qAlpha(*p), qRed(*p)); + p++; + q++; + } } - } #endif - arg.beginStructure(); - arg << i.width(); - arg << i.height(); - arg << i.bytesPerLine(); - arg << i.hasAlphaChannel(); - int channels = i.isGrayscale() ? 1 : (i.hasAlphaChannel() ? 4 : 3); - arg << i.depth() / channels; - arg << channels; - arg << QByteArray(reinterpret_cast(i.bits()), i.sizeInBytes()); - arg.endStructure(); - return arg; + arg.beginStructure(); + arg << i.width(); + arg << i.height(); + arg << i.bytesPerLine(); + arg << i.hasAlphaChannel(); + int channels = i.isGrayscale() ? 1 : (i.hasAlphaChannel() ? 4 : 3); + arg << i.depth() / channels; + arg << channels; + arg << QByteArray(reinterpret_cast(i.bits()), i.sizeInBytes()); + arg.endStructure(); + return arg; } -const QDBusArgument &operator>>(const QDBusArgument &arg, QImage &) { - // This is needed to link but shouldn't be called. - Q_ASSERT(0); - return arg; +const QDBusArgument &operator>>(const QDBusArgument &arg, QImage &) +{ + // This is needed to link but shouldn't be called. + Q_ASSERT(0); + return arg; } diff --git a/src/notifications/managerwin.cpp b/src/notifications/managerwin.cpp index b6bf61ab3..a7d04f90e 100644 --- a/src/notifications/managerwin.cpp +++ b/src/notifications/managerwin.cpp @@ -5,79 +5,89 @@ using namespace WinToastLib; -class CustomHandler : public IWinToastHandler { - public: - CustomHandler(uint id, NotificationsManager *parent) - : notificationID(id), notificationsManager(parent) {} - void toastActivated() { - notificationsManager->actionInvoked(notificationID, ""); - } - void toastActivated(int) { - notificationsManager->actionInvoked(notificationID, ""); - } - void toastFailed() { - std::wcout << L"Error showing current toast" << std::endl; - } - void toastDismissed(WinToastDismissalReason) { - notificationsManager->notificationClosed(notificationID, 0); - } +class CustomHandler : public IWinToastHandler +{ +public: + CustomHandler(uint id, NotificationsManager *parent) + : notificationID(id) + , notificationsManager(parent) + { + } + void toastActivated() + { + notificationsManager->actionInvoked(notificationID, ""); + } + void toastActivated(int) + { + notificationsManager->actionInvoked(notificationID, ""); + } + void toastFailed() + { + std::wcout << L"Error showing current toast" << std::endl; + } + void toastDismissed(WinToastDismissalReason) + { + notificationsManager->notificationClosed(notificationID, 0); + } - private: - uint notificationID; - NotificationsManager *notificationsManager; +private: + uint notificationID; + NotificationsManager *notificationsManager; }; -namespace { +namespace +{ bool isInitialized = false; uint count = 0; -void init() { - isInitialized = true; +void init() +{ + isInitialized = true; - WinToast::instance()->setAppName(L"Spectral"); - WinToast::instance()->setAppUserModelId( - WinToast::configureAUMI(L"Spectral", L"Spectral")); - if (!WinToast::instance()->initialize()) - std::wcout << "Your system in not compatible with toast notifications\n"; + WinToast::instance()->setAppName(L"Spectral"); + WinToast::instance()->setAppUserModelId(WinToast::configureAUMI(L"Spectral", L"Spectral")); + if (!WinToast::instance()->initialize()) + std::wcout << "Your system in not compatible with toast notifications\n"; } -} // namespace +} // namespace -NotificationsManager::NotificationsManager(QObject *parent) : QObject(parent) {} - -void NotificationsManager::postNotification( - const QString &room_id, const QString &event_id, const QString &room_name, - const QString &sender, const QString &text, const QImage &icon) { - Q_UNUSED(room_id) - Q_UNUSED(event_id) - Q_UNUSED(icon) - - if (!isInitialized) init(); - - auto templ = WinToastTemplate(WinToastTemplate::ImageAndText02); - if (room_name != sender) - templ.setTextField( - QString("%1 - %2").arg(sender).arg(room_name).toStdWString(), - WinToastTemplate::FirstLine); - else - templ.setTextField(QString("%1").arg(sender).toStdWString(), - WinToastTemplate::FirstLine); - templ.setTextField(QString("%1").arg(text).toStdWString(), - WinToastTemplate::SecondLine); - - count++; - CustomHandler *customHandler = new CustomHandler(count, this); - notificationIds[count] = roomEventId{room_id, event_id}; - - WinToast::instance()->showToast(templ, customHandler); +NotificationsManager::NotificationsManager(QObject *parent) + : QObject(parent) +{ } -void NotificationsManager::actionInvoked(uint id, QString action) { - if (notificationIds.contains(id)) { - roomEventId idEntry = notificationIds[id]; - emit notificationClicked(idEntry.roomId, idEntry.eventId); - } +void NotificationsManager::postNotification(const QString &room_id, const QString &event_id, const QString &room_name, const QString &sender, const QString &text, const QImage &icon) +{ + Q_UNUSED(room_id) + Q_UNUSED(event_id) + Q_UNUSED(icon) + + if (!isInitialized) + init(); + + auto templ = WinToastTemplate(WinToastTemplate::ImageAndText02); + if (room_name != sender) + templ.setTextField(QString("%1 - %2").arg(sender).arg(room_name).toStdWString(), WinToastTemplate::FirstLine); + else + templ.setTextField(QString("%1").arg(sender).toStdWString(), WinToastTemplate::FirstLine); + templ.setTextField(QString("%1").arg(text).toStdWString(), WinToastTemplate::SecondLine); + + count++; + CustomHandler *customHandler = new CustomHandler(count, this); + notificationIds[count] = roomEventId {room_id, event_id}; + + WinToast::instance()->showToast(templ, customHandler); } -void NotificationsManager::notificationClosed(uint id, uint reason) { - notificationIds.remove(id); +void NotificationsManager::actionInvoked(uint id, QString action) +{ + if (notificationIds.contains(id)) { + roomEventId idEntry = notificationIds[id]; + emit notificationClicked(idEntry.roomId, idEntry.eventId); + } +} + +void NotificationsManager::notificationClosed(uint id, uint reason) +{ + notificationIds.remove(id); } diff --git a/src/notifications/wintoastlib.cpp b/src/notifications/wintoastlib.cpp index 2dc8dabb9..43d152dd4 100644 --- a/src/notifications/wintoastlib.cpp +++ b/src/notifications/wintoastlib.cpp @@ -1,14 +1,19 @@ #include "wintoastlib.h" -#include #include +#include -#pragma comment(lib,"shlwapi") -#pragma comment(lib,"user32") +#pragma comment(lib, "shlwapi") +#pragma comment(lib, "user32") #ifdef NDEBUG - #define DEBUG_MSG(str) do { } while ( false ) - #else - #define DEBUG_MSG(str) do { std::wcout << str << std::endl; } while( false ) +#define DEBUG_MSG(str) \ + do { \ + } while (false) +#else +#define DEBUG_MSG(str) \ + do { \ + std::wcout << str << std::endl; \ + } while (false) #endif // Thanks: https://stackoverflow.com/a/36545162/4297146 @@ -17,21 +22,22 @@ typedef LONG NTSTATUS, *PNTSTATUS; #define STATUS_SUCCESS (0x00000000) -typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); +typedef NTSTATUS(WINAPI *RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); -RTL_OSVERSIONINFOW GetRealOSVersion() { +RTL_OSVERSIONINFOW GetRealOSVersion() +{ HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll"); if (hMod) { RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion"); if (fxPtr != nullptr) { - RTL_OSVERSIONINFOW rovi = { 0 }; + RTL_OSVERSIONINFOW rovi = {0}; rovi.dwOSVersionInfoSize = sizeof(rovi); if (STATUS_SUCCESS == fxPtr(&rovi)) { return rovi; } } } - RTL_OSVERSIONINFOW rovi = { 0 }; + RTL_OSVERSIONINFOW rovi = {0}; return rovi; } @@ -39,84 +45,90 @@ RTL_OSVERSIONINFOW GetRealOSVersion() { // https://blogs.msdn.microsoft.com/tiles_and_toasts/2015/10/16/quickstart-handling-toast-activations-from-win32-apps-in-windows-10/ using namespace WinToastLib; -namespace DllImporter { - - // Function load a function from library - template - HRESULT loadFunctionFromLibrary(HINSTANCE library, LPCSTR name, Function &func) { - if (!library) { - return E_INVALIDARG; - } - func = reinterpret_cast(GetProcAddress(library, name)); - return (func != nullptr) ? S_OK : E_FAIL; - } - - typedef HRESULT(FAR STDAPICALLTYPE *f_SetCurrentProcessExplicitAppUserModelID)(__in PCWSTR AppID); - typedef HRESULT(FAR STDAPICALLTYPE *f_PropVariantToString)(_In_ REFPROPVARIANT propvar, _Out_writes_(cch) PWSTR psz, _In_ UINT cch); - typedef HRESULT(FAR STDAPICALLTYPE *f_RoGetActivationFactory)(_In_ HSTRING activatableClassId, _In_ REFIID iid, _COM_Outptr_ void ** factory); - typedef HRESULT(FAR STDAPICALLTYPE *f_WindowsCreateStringReference)(_In_reads_opt_(length + 1) PCWSTR sourceString, UINT32 length, _Out_ HSTRING_HEADER * hstringHeader, _Outptr_result_maybenull_ _Result_nullonfailure_ HSTRING * string); - typedef PCWSTR(FAR STDAPICALLTYPE *f_WindowsGetStringRawBuffer)(_In_ HSTRING string, _Out_ UINT32 *length); - typedef HRESULT(FAR STDAPICALLTYPE *f_WindowsDeleteString)(_In_opt_ HSTRING string); - - static f_SetCurrentProcessExplicitAppUserModelID SetCurrentProcessExplicitAppUserModelID; - static f_PropVariantToString PropVariantToString; - static f_RoGetActivationFactory RoGetActivationFactory; - static f_WindowsCreateStringReference WindowsCreateStringReference; - static f_WindowsGetStringRawBuffer WindowsGetStringRawBuffer; - static f_WindowsDeleteString WindowsDeleteString; - - - template - _Check_return_ __inline HRESULT _1_GetActivationFactory(_In_ HSTRING activatableClassId, _COM_Outptr_ T** factory) { - return RoGetActivationFactory(activatableClassId, IID_INS_ARGS(factory)); - } - - template - inline HRESULT Wrap_GetActivationFactory(_In_ HSTRING activatableClassId, _Inout_ Details::ComPtrRef factory) throw() { - return _1_GetActivationFactory(activatableClassId, factory.ReleaseAndGetAddressOf()); - } - - inline HRESULT initialize() { - HINSTANCE LibShell32 = LoadLibraryW(L"SHELL32.DLL"); - HRESULT hr = loadFunctionFromLibrary(LibShell32, "SetCurrentProcessExplicitAppUserModelID", SetCurrentProcessExplicitAppUserModelID); - if (SUCCEEDED(hr)) { - HINSTANCE LibPropSys = LoadLibraryW(L"PROPSYS.DLL"); - hr = loadFunctionFromLibrary(LibPropSys, "PropVariantToString", PropVariantToString); - if (SUCCEEDED(hr)) { - HINSTANCE LibComBase = LoadLibraryW(L"COMBASE.DLL"); - const bool succeded = SUCCEEDED(loadFunctionFromLibrary(LibComBase, "RoGetActivationFactory", RoGetActivationFactory)) - && SUCCEEDED(loadFunctionFromLibrary(LibComBase, "WindowsCreateStringReference", WindowsCreateStringReference)) - && SUCCEEDED(loadFunctionFromLibrary(LibComBase, "WindowsGetStringRawBuffer", WindowsGetStringRawBuffer)) - && SUCCEEDED(loadFunctionFromLibrary(LibComBase, "WindowsDeleteString", WindowsDeleteString)); - return succeded ? S_OK : E_FAIL; - } - } - return hr; +namespace DllImporter +{ +// Function load a function from library +template HRESULT loadFunctionFromLibrary(HINSTANCE library, LPCSTR name, Function &func) +{ + if (!library) { + return E_INVALIDARG; } + func = reinterpret_cast(GetProcAddress(library, name)); + return (func != nullptr) ? S_OK : E_FAIL; } -class WinToastStringWrapper { +typedef HRESULT(FAR STDAPICALLTYPE *f_SetCurrentProcessExplicitAppUserModelID)(__in PCWSTR AppID); +typedef HRESULT(FAR STDAPICALLTYPE *f_PropVariantToString)(_In_ REFPROPVARIANT propvar, _Out_writes_(cch) PWSTR psz, _In_ UINT cch); +typedef HRESULT(FAR STDAPICALLTYPE *f_RoGetActivationFactory)(_In_ HSTRING activatableClassId, _In_ REFIID iid, _COM_Outptr_ void **factory); +typedef HRESULT(FAR STDAPICALLTYPE *f_WindowsCreateStringReference)(_In_reads_opt_(length + 1) PCWSTR sourceString, UINT32 length, _Out_ HSTRING_HEADER *hstringHeader, _Outptr_result_maybenull_ _Result_nullonfailure_ HSTRING *string); +typedef PCWSTR(FAR STDAPICALLTYPE *f_WindowsGetStringRawBuffer)(_In_ HSTRING string, _Out_ UINT32 *length); +typedef HRESULT(FAR STDAPICALLTYPE *f_WindowsDeleteString)(_In_opt_ HSTRING string); + +static f_SetCurrentProcessExplicitAppUserModelID SetCurrentProcessExplicitAppUserModelID; +static f_PropVariantToString PropVariantToString; +static f_RoGetActivationFactory RoGetActivationFactory; +static f_WindowsCreateStringReference WindowsCreateStringReference; +static f_WindowsGetStringRawBuffer WindowsGetStringRawBuffer; +static f_WindowsDeleteString WindowsDeleteString; + +template _Check_return_ __inline HRESULT _1_GetActivationFactory(_In_ HSTRING activatableClassId, _COM_Outptr_ T **factory) +{ + return RoGetActivationFactory(activatableClassId, IID_INS_ARGS(factory)); +} + +template inline HRESULT Wrap_GetActivationFactory(_In_ HSTRING activatableClassId, _Inout_ Details::ComPtrRef factory) throw() +{ + return _1_GetActivationFactory(activatableClassId, factory.ReleaseAndGetAddressOf()); +} + +inline HRESULT initialize() +{ + HINSTANCE LibShell32 = LoadLibraryW(L"SHELL32.DLL"); + HRESULT hr = loadFunctionFromLibrary(LibShell32, "SetCurrentProcessExplicitAppUserModelID", SetCurrentProcessExplicitAppUserModelID); + if (SUCCEEDED(hr)) { + HINSTANCE LibPropSys = LoadLibraryW(L"PROPSYS.DLL"); + hr = loadFunctionFromLibrary(LibPropSys, "PropVariantToString", PropVariantToString); + if (SUCCEEDED(hr)) { + HINSTANCE LibComBase = LoadLibraryW(L"COMBASE.DLL"); + const bool succeded = SUCCEEDED(loadFunctionFromLibrary(LibComBase, "RoGetActivationFactory", RoGetActivationFactory)) && + SUCCEEDED(loadFunctionFromLibrary(LibComBase, "WindowsCreateStringReference", WindowsCreateStringReference)) && SUCCEEDED(loadFunctionFromLibrary(LibComBase, "WindowsGetStringRawBuffer", WindowsGetStringRawBuffer)) && + SUCCEEDED(loadFunctionFromLibrary(LibComBase, "WindowsDeleteString", WindowsDeleteString)); + return succeded ? S_OK : E_FAIL; + } + } + return hr; +} +} + +class WinToastStringWrapper +{ public: - WinToastStringWrapper(_In_reads_(length) PCWSTR stringRef, _In_ UINT32 length) throw() { + WinToastStringWrapper(_In_reads_(length) PCWSTR stringRef, _In_ UINT32 length) throw() + { HRESULT hr = DllImporter::WindowsCreateStringReference(stringRef, length, &_header, &_hstring); if (!SUCCEEDED(hr)) { RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); } } - WinToastStringWrapper(_In_ const std::wstring &stringRef) throw() { + WinToastStringWrapper(_In_ const std::wstring &stringRef) throw() + { HRESULT hr = DllImporter::WindowsCreateStringReference(stringRef.c_str(), static_cast(stringRef.length()), &_header, &_hstring); if (FAILED(hr)) { RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); } } - ~WinToastStringWrapper() { + ~WinToastStringWrapper() + { DllImporter::WindowsDeleteString(_hstring); } - inline HSTRING Get() const throw() { return _hstring; } + inline HSTRING Get() const throw() + { + return _hstring; + } + private: HSTRING _hstring; HSTRING_HEADER _header; - }; class MyDateTime : public IReference @@ -125,263 +137,275 @@ protected: DateTime _dateTime; public: - static INT64 Now() { + static INT64 Now() + { FILETIME now; GetSystemTimeAsFileTime(&now); return ((((INT64)now.dwHighDateTime) << 32) | now.dwLowDateTime); } - MyDateTime(DateTime dateTime) : _dateTime(dateTime) {} + MyDateTime(DateTime dateTime) + : _dateTime(dateTime) + { + } - MyDateTime(INT64 millisecondsFromNow) { + MyDateTime(INT64 millisecondsFromNow) + { _dateTime.UniversalTime = Now() + millisecondsFromNow * 10000; } - operator INT64() { + operator INT64() + { return _dateTime.UniversalTime; } - HRESULT STDMETHODCALLTYPE get_Value(DateTime *dateTime) { + HRESULT STDMETHODCALLTYPE get_Value(DateTime *dateTime) + { *dateTime = _dateTime; return S_OK; } - HRESULT STDMETHODCALLTYPE QueryInterface(const IID& riid, void** ppvObject) { + HRESULT STDMETHODCALLTYPE QueryInterface(const IID &riid, void **ppvObject) + { if (!ppvObject) { return E_POINTER; } if (riid == __uuidof(IUnknown) || riid == __uuidof(IReference)) { - *ppvObject = static_cast(static_cast*>(this)); + *ppvObject = static_cast(static_cast *>(this)); return S_OK; } return E_NOINTERFACE; } - ULONG STDMETHODCALLTYPE Release() { + ULONG STDMETHODCALLTYPE Release() + { return 1; } - ULONG STDMETHODCALLTYPE AddRef() { + ULONG STDMETHODCALLTYPE AddRef() + { return 2; } - HRESULT STDMETHODCALLTYPE GetIids(ULONG*, IID**) { + HRESULT STDMETHODCALLTYPE GetIids(ULONG *, IID **) + { return E_NOTIMPL; } - HRESULT STDMETHODCALLTYPE GetRuntimeClassName(HSTRING*) { + HRESULT STDMETHODCALLTYPE GetRuntimeClassName(HSTRING *) + { return E_NOTIMPL; } - HRESULT STDMETHODCALLTYPE GetTrustLevel(TrustLevel*) { + HRESULT STDMETHODCALLTYPE GetTrustLevel(TrustLevel *) + { return E_NOTIMPL; } }; -namespace Util { - inline HRESULT defaultExecutablePath(_In_ WCHAR* path, _In_ DWORD nSize = MAX_PATH) { - DWORD written = GetModuleFileNameExW(GetCurrentProcess(), nullptr, path, nSize); - DEBUG_MSG("Default executable path: " << path); - return (written > 0) ? S_OK : E_FAIL; +namespace Util +{ +inline HRESULT defaultExecutablePath(_In_ WCHAR *path, _In_ DWORD nSize = MAX_PATH) +{ + DWORD written = GetModuleFileNameExW(GetCurrentProcess(), nullptr, path, nSize); + DEBUG_MSG("Default executable path: " << path); + return (written > 0) ? S_OK : E_FAIL; +} + +inline HRESULT defaultShellLinksDirectory(_In_ WCHAR *path, _In_ DWORD nSize = MAX_PATH) +{ + DWORD written = GetEnvironmentVariableW(L"APPDATA", path, nSize); + HRESULT hr = written > 0 ? S_OK : E_INVALIDARG; + if (SUCCEEDED(hr)) { + errno_t result = wcscat_s(path, nSize, DEFAULT_SHELL_LINKS_PATH); + hr = (result == 0) ? S_OK : E_INVALIDARG; + DEBUG_MSG("Default shell link path: " << path); } + return hr; +} +inline HRESULT defaultShellLinkPath(const std::wstring &appname, _In_ WCHAR *path, _In_ DWORD nSize = MAX_PATH) +{ + HRESULT hr = defaultShellLinksDirectory(path, nSize); + if (SUCCEEDED(hr)) { + const std::wstring appLink(appname + DEFAULT_LINK_FORMAT); + errno_t result = wcscat_s(path, nSize, appLink.c_str()); + hr = (result == 0) ? S_OK : E_INVALIDARG; + DEBUG_MSG("Default shell link file path: " << path); + } + return hr; +} - inline HRESULT defaultShellLinksDirectory(_In_ WCHAR* path, _In_ DWORD nSize = MAX_PATH) { - DWORD written = GetEnvironmentVariableW(L"APPDATA", path, nSize); - HRESULT hr = written > 0 ? S_OK : E_INVALIDARG; +inline PCWSTR AsString(ComPtr &xmlDocument) +{ + HSTRING xml; + ComPtr ser; + HRESULT hr = xmlDocument.As(&ser); + hr = ser->GetXml(&xml); + if (SUCCEEDED(hr)) + return DllImporter::WindowsGetStringRawBuffer(xml, NULL); + return NULL; +} + +inline PCWSTR AsString(HSTRING hstring) +{ + return DllImporter::WindowsGetStringRawBuffer(hstring, NULL); +} + +inline HRESULT setNodeStringValue(const std::wstring &string, IXmlNode *node, IXmlDocument *xml) +{ + ComPtr textNode; + HRESULT hr = xml->CreateTextNode(WinToastStringWrapper(string).Get(), &textNode); + if (SUCCEEDED(hr)) { + ComPtr stringNode; + hr = textNode.As(&stringNode); if (SUCCEEDED(hr)) { - errno_t result = wcscat_s(path, nSize, DEFAULT_SHELL_LINKS_PATH); - hr = (result == 0) ? S_OK : E_INVALIDARG; - DEBUG_MSG("Default shell link path: " << path); + ComPtr appendedChild; + hr = node->AppendChild(stringNode.Get(), &appendedChild); } - return hr; } + return hr; +} - inline HRESULT defaultShellLinkPath(const std::wstring& appname, _In_ WCHAR* path, _In_ DWORD nSize = MAX_PATH) { - HRESULT hr = defaultShellLinksDirectory(path, nSize); +inline HRESULT setEventHandlers(_In_ IToastNotification *notification, _In_ std::shared_ptr eventHandler, _In_ INT64 expirationTime) +{ + EventRegistrationToken activatedToken, dismissedToken, failedToken; + HRESULT hr = notification->add_Activated(Callback, ITypedEventHandler>>([eventHandler](IToastNotification *, IInspectable *inspectable) { + IToastActivatedEventArgs *activatedEventArgs; + HRESULT hr = inspectable->QueryInterface(&activatedEventArgs); + if (SUCCEEDED(hr)) { + HSTRING argumentsHandle; + hr = activatedEventArgs->get_Arguments(&argumentsHandle); + if (SUCCEEDED(hr)) { + PCWSTR arguments = Util::AsString(argumentsHandle); + if (arguments && *arguments) { + eventHandler->toastActivated((int)wcstol(arguments, NULL, 10)); + return S_OK; + } + } + } + eventHandler->toastActivated(); + return S_OK; + }).Get(), + &activatedToken); + + if (SUCCEEDED(hr)) { + hr = notification->add_Dismissed( + Callback, ITypedEventHandler>>([eventHandler, expirationTime](IToastNotification *, IToastDismissedEventArgs *e) { + ToastDismissalReason reason; + if (SUCCEEDED(e->get_Reason(&reason))) { + if (reason == ToastDismissalReason_UserCanceled && expirationTime && MyDateTime::Now() >= expirationTime) + reason = ToastDismissalReason_TimedOut; + eventHandler->toastDismissed(static_cast(reason)); + } + return S_OK; + }).Get(), + &dismissedToken); if (SUCCEEDED(hr)) { - const std::wstring appLink(appname + DEFAULT_LINK_FORMAT); - errno_t result = wcscat_s(path, nSize, appLink.c_str()); - hr = (result == 0) ? S_OK : E_INVALIDARG; - DEBUG_MSG("Default shell link file path: " << path); + hr = notification->add_Failed(Callback, ITypedEventHandler>>([eventHandler](IToastNotification *, IToastFailedEventArgs *) { + eventHandler->toastFailed(); + return S_OK; + }).Get(), + &failedToken); } - return hr; } + return hr; +} - - inline PCWSTR AsString(ComPtr &xmlDocument) { - HSTRING xml; - ComPtr ser; - HRESULT hr = xmlDocument.As(&ser); - hr = ser->GetXml(&xml); - if (SUCCEEDED(hr)) - return DllImporter::WindowsGetStringRawBuffer(xml, NULL); - return NULL; - } - - inline PCWSTR AsString(HSTRING hstring) { - return DllImporter::WindowsGetStringRawBuffer(hstring, NULL); - } - - inline HRESULT setNodeStringValue(const std::wstring& string, IXmlNode *node, IXmlDocument *xml) { - ComPtr textNode; - HRESULT hr = xml->CreateTextNode( WinToastStringWrapper(string).Get(), &textNode); +inline HRESULT addAttribute(_In_ IXmlDocument *xml, const std::wstring &name, IXmlNamedNodeMap *attributeMap) +{ + ComPtr srcAttribute; + HRESULT hr = xml->CreateAttribute(WinToastStringWrapper(name).Get(), &srcAttribute); + if (SUCCEEDED(hr)) { + ComPtr node; + hr = srcAttribute.As(&node); if (SUCCEEDED(hr)) { - ComPtr stringNode; - hr = textNode.As(&stringNode); + ComPtr pNode; + hr = attributeMap->SetNamedItem(node.Get(), &pNode); + } + } + return hr; +} + +inline HRESULT createElement(_In_ IXmlDocument *xml, _In_ const std::wstring &root_node, _In_ const std::wstring &element_name, _In_ const std::vector &attribute_names) +{ + ComPtr rootList; + HRESULT hr = xml->GetElementsByTagName(WinToastStringWrapper(root_node).Get(), &rootList); + if (SUCCEEDED(hr)) { + ComPtr root; + hr = rootList->Item(0, &root); + if (SUCCEEDED(hr)) { + ComPtr audioElement; + hr = xml->CreateElement(WinToastStringWrapper(element_name).Get(), &audioElement); if (SUCCEEDED(hr)) { - ComPtr appendedChild; - hr = node->AppendChild(stringNode.Get(), &appendedChild); - } - } - return hr; - } - - inline HRESULT setEventHandlers(_In_ IToastNotification* notification, _In_ std::shared_ptr eventHandler, _In_ INT64 expirationTime) { - EventRegistrationToken activatedToken, dismissedToken, failedToken; - HRESULT hr = notification->add_Activated( - Callback < Implements < RuntimeClassFlags, - ITypedEventHandler> >( - [eventHandler](IToastNotification*, IInspectable* inspectable) - { - IToastActivatedEventArgs *activatedEventArgs; - HRESULT hr = inspectable->QueryInterface(&activatedEventArgs); - if (SUCCEEDED(hr)) { - HSTRING argumentsHandle; - hr = activatedEventArgs->get_Arguments(&argumentsHandle); - if (SUCCEEDED(hr)) { - PCWSTR arguments = Util::AsString(argumentsHandle); - if (arguments && *arguments) { - eventHandler->toastActivated((int)wcstol(arguments, NULL, 10)); - return S_OK; - } - } - } - eventHandler->toastActivated(); - return S_OK; - }).Get(), &activatedToken); - - if (SUCCEEDED(hr)) { - hr = notification->add_Dismissed(Callback < Implements < RuntimeClassFlags, - ITypedEventHandler> >( - [eventHandler, expirationTime](IToastNotification*, IToastDismissedEventArgs* e) - { - ToastDismissalReason reason; - if (SUCCEEDED(e->get_Reason(&reason))) - { - if (reason == ToastDismissalReason_UserCanceled && expirationTime && MyDateTime::Now() >= expirationTime) - reason = ToastDismissalReason_TimedOut; - eventHandler->toastDismissed(static_cast(reason)); - } - return S_OK; - }).Get(), &dismissedToken); - if (SUCCEEDED(hr)) { - hr = notification->add_Failed(Callback < Implements < RuntimeClassFlags, - ITypedEventHandler> >( - [eventHandler](IToastNotification*, IToastFailedEventArgs*) - { - eventHandler->toastFailed(); - return S_OK; - }).Get(), &failedToken); - } - } - return hr; - } - - inline HRESULT addAttribute(_In_ IXmlDocument *xml, const std::wstring &name, IXmlNamedNodeMap *attributeMap) { - ComPtr srcAttribute; - HRESULT hr = xml->CreateAttribute(WinToastStringWrapper(name).Get(), &srcAttribute); - if (SUCCEEDED(hr)) { - ComPtr node; - hr = srcAttribute.As(&node); - if (SUCCEEDED(hr)) { - ComPtr pNode; - hr = attributeMap->SetNamedItem(node.Get(), &pNode); - } - } - return hr; - } - - inline HRESULT createElement(_In_ IXmlDocument *xml, _In_ const std::wstring& root_node, _In_ const std::wstring& element_name, _In_ const std::vector& attribute_names) { - ComPtr rootList; - HRESULT hr = xml->GetElementsByTagName(WinToastStringWrapper(root_node).Get(), &rootList); - if (SUCCEEDED(hr)) { - ComPtr root; - hr = rootList->Item(0, &root); - if (SUCCEEDED(hr)) { - ComPtr audioElement; - hr = xml->CreateElement(WinToastStringWrapper(element_name).Get(), &audioElement); + ComPtr audioNodeTmp; + hr = audioElement.As(&audioNodeTmp); if (SUCCEEDED(hr)) { - ComPtr audioNodeTmp; - hr = audioElement.As(&audioNodeTmp); + ComPtr audioNode; + hr = root->AppendChild(audioNodeTmp.Get(), &audioNode); if (SUCCEEDED(hr)) { - ComPtr audioNode; - hr = root->AppendChild(audioNodeTmp.Get(), &audioNode); + ComPtr attributes; + hr = audioNode->get_Attributes(&attributes); if (SUCCEEDED(hr)) { - ComPtr attributes; - hr = audioNode->get_Attributes(&attributes); - if (SUCCEEDED(hr)) { - for (auto it : attribute_names) { - hr = addAttribute(xml, it, attributes.Get()); - } + for (auto it : attribute_names) { + hr = addAttribute(xml, it, attributes.Get()); } } } } } } - return hr; } + return hr; +} } -WinToast* WinToast::instance() { +WinToast *WinToast::instance() +{ static WinToast instance; return &instance; } -WinToast::WinToast() : - _isInitialized(false), - _hasCoInitialized(false) +WinToast::WinToast() + : _isInitialized(false) + , _hasCoInitialized(false) { if (!isCompatible()) { DEBUG_MSG(L"Warning: Your system is not compatible with this library "); } } -WinToast::~WinToast() { +WinToast::~WinToast() +{ if (_hasCoInitialized) { CoUninitialize(); } } -void WinToast::setAppName(_In_ const std::wstring& appName) { +void WinToast::setAppName(_In_ const std::wstring &appName) +{ _appName = appName; } - -void WinToast::setAppUserModelId(_In_ const std::wstring& aumi) { +void WinToast::setAppUserModelId(_In_ const std::wstring &aumi) +{ _aumi = aumi; DEBUG_MSG(L"Default App User Model Id: " << _aumi.c_str()); } -bool WinToast::isCompatible() { +bool WinToast::isCompatible() +{ DllImporter::initialize(); - return !((DllImporter::SetCurrentProcessExplicitAppUserModelID == nullptr) - || (DllImporter::PropVariantToString == nullptr) - || (DllImporter::RoGetActivationFactory == nullptr) - || (DllImporter::WindowsCreateStringReference == nullptr) - || (DllImporter::WindowsDeleteString == nullptr)); + return !((DllImporter::SetCurrentProcessExplicitAppUserModelID == nullptr) || (DllImporter::PropVariantToString == nullptr) || (DllImporter::RoGetActivationFactory == nullptr) || (DllImporter::WindowsCreateStringReference == nullptr) || + (DllImporter::WindowsDeleteString == nullptr)); } -bool WinToastLib::WinToast::isSupportingModernFeatures() { +bool WinToastLib::WinToast::isSupportingModernFeatures() +{ RTL_OSVERSIONINFOW tmp = GetRealOSVersion(); return tmp.dwMajorVersion > 6; - } -std::wstring WinToast::configureAUMI(_In_ const std::wstring &companyName, - _In_ const std::wstring &productName, - _In_ const std::wstring &subProduct, - _In_ const std::wstring &versionInformation) +std::wstring WinToast::configureAUMI(_In_ const std::wstring &companyName, _In_ const std::wstring &productName, _In_ const std::wstring &subProduct, _In_ const std::wstring &versionInformation) { std::wstring aumi = companyName; aumi += L"." + productName; @@ -398,8 +422,8 @@ std::wstring WinToast::configureAUMI(_In_ const std::wstring &companyName, return aumi; } - -enum WinToast::ShortcutResult WinToast::createShortcut() { +enum WinToast::ShortcutResult WinToast::createShortcut() +{ if (_aumi.empty() || _appName.empty()) { DEBUG_MSG(L"Error: App User Model Id or Appname is empty!"); return SHORTCUT_MISSING_PARAMETERS; @@ -416,8 +440,7 @@ enum WinToast::ShortcutResult WinToast::createShortcut() { if (FAILED(initHr) && initHr != S_FALSE) { DEBUG_MSG(L"Error on COM library initialization!"); return SHORTCUT_COM_INIT_FAILURE; - } - else { + } else { _hasCoInitialized = true; } } @@ -432,7 +455,8 @@ enum WinToast::ShortcutResult WinToast::createShortcut() { return SUCCEEDED(hr) ? SHORTCUT_WAS_CREATED : SHORTCUT_CREATE_FAILED; } -bool WinToast::initialize(_Out_ WinToastError* error) { +bool WinToast::initialize(_Out_ WinToastError *error) +{ _isInitialized = false; setError(error, WinToastError::NoError); @@ -442,7 +466,6 @@ bool WinToast::initialize(_Out_ WinToastError* error) { return false; } - if (_aumi.empty() || _appName.empty()) { setError(error, WinToastError::InvalidParameters); DEBUG_MSG(L"Error while initializing, did you set up a valid AUMI and App name?"); @@ -465,21 +488,24 @@ bool WinToast::initialize(_Out_ WinToastError* error) { return _isInitialized; } -bool WinToast::isInitialized() const { +bool WinToast::isInitialized() const +{ return _isInitialized; } -const std::wstring& WinToast::appName() const { +const std::wstring &WinToast::appName() const +{ return _appName; } -const std::wstring& WinToast::appUserModelId() const { +const std::wstring &WinToast::appUserModelId() const +{ return _aumi; } - -HRESULT WinToast::validateShellLinkHelper(_Out_ bool& wasChanged) { - WCHAR path[MAX_PATH] = { L'\0' }; +HRESULT WinToast::validateShellLinkHelper(_Out_ bool &wasChanged) +{ + WCHAR path[MAX_PATH] = {L'\0'}; Util::defaultShellLinkPath(_appName, path); // Check if the file exist DWORD attr = GetFileAttributesW(path); @@ -535,11 +561,10 @@ HRESULT WinToast::validateShellLinkHelper(_Out_ bool& wasChanged) { return hr; } - - -HRESULT WinToast::createShellLinkHelper() { - WCHAR exePath[MAX_PATH]{L'\0'}; - WCHAR slPath[MAX_PATH]{L'\0'}; +HRESULT WinToast::createShellLinkHelper() +{ + WCHAR exePath[MAX_PATH] {L'\0'}; + WCHAR slPath[MAX_PATH] {L'\0'}; Util::defaultShellLinkPath(_appName, slPath); Util::defaultExecutablePath(exePath); ComPtr shellLink; @@ -578,7 +603,8 @@ HRESULT WinToast::createShellLinkHelper() { return hr; } -INT64 WinToast::showToast(_In_ const WinToastTemplate& toast, _In_ IWinToastHandler* handler, _Out_ WinToastError* error) { +INT64 WinToast::showToast(_In_ const WinToastTemplate &toast, _In_ IWinToastHandler *handler, _Out_ WinToastError *error) +{ setError(error, WinToastError::NoError); INT64 id = -1; if (!isInitialized()) { @@ -611,11 +637,9 @@ INT64 WinToast::showToast(_In_ const WinToastTemplate& toast, _In_ IWinToastHan // Modern feature are supported Windows > Windows 10 if (SUCCEEDED(hr) && isSupportingModernFeatures()) { - // Note that we do this *after* using toast.textFieldsCount() to // iterate/fill the template's text fields, since we're adding yet another text field. - if (SUCCEEDED(hr) - && !toast.attributionText().empty()) { + if (SUCCEEDED(hr) && !toast.attributionText().empty()) { hr = setAttributionTextFieldHelper(xmlDocument.Get(), toast.attributionText()); } @@ -627,13 +651,11 @@ INT64 WinToast::showToast(_In_ const WinToastTemplate& toast, _In_ IWinToastHan } if (SUCCEEDED(hr)) { - hr = (toast.audioPath().empty() && toast.audioOption() == WinToastTemplate::AudioOption::Default) - ? hr : setAudioFieldHelper(xmlDocument.Get(), toast.audioPath(), toast.audioOption()); + hr = (toast.audioPath().empty() && toast.audioOption() == WinToastTemplate::AudioOption::Default) ? hr : setAudioFieldHelper(xmlDocument.Get(), toast.audioPath(), toast.audioOption()); } if (SUCCEEDED(hr) && toast.duration() != WinToastTemplate::Duration::System) { - hr = addDurationHelper(xmlDocument.Get(), - (toast.duration() == WinToastTemplate::Duration::Short) ? L"short" : L"long"); + hr = addDurationHelper(xmlDocument.Get(), (toast.duration() == WinToastTemplate::Duration::Short) ? L"short" : L"long"); } } else { @@ -683,7 +705,8 @@ INT64 WinToast::showToast(_In_ const WinToastTemplate& toast, _In_ IWinToastHan return FAILED(hr) ? -1 : id; } -ComPtr WinToast::notifier(_In_ bool* succeded) const { +ComPtr WinToast::notifier(_In_ bool *succeded) const +{ ComPtr notificationManager; ComPtr notifier; HRESULT hr = DllImporter::Wrap_GetActivationFactory(WinToastStringWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), ¬ificationManager); @@ -694,7 +717,8 @@ ComPtr WinToast::notifier(_In_ bool* succeded) const { return notifier; } -bool WinToast::hideToast(_In_ INT64 id) { +bool WinToast::hideToast(_In_ INT64 id) +{ if (!isInitialized()) { DEBUG_MSG("Error when hiding the toast. WinToast is not initialized."); return false; @@ -711,7 +735,8 @@ bool WinToast::hideToast(_In_ INT64 id) { return find; } -void WinToast::clear() { +void WinToast::clear() +{ bool succeded = false; ComPtr notify = notifier(&succeded); if (succeded) { @@ -730,8 +755,9 @@ void WinToast::clear() { // NOTE: This will add a new text field, so be aware when iterating over // the toast's text fields or getting a count of them. // -HRESULT WinToast::setAttributionTextFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& text) { - Util::createElement(xml, L"binding", L"text", { L"placement" }); +HRESULT WinToast::setAttributionTextFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring &text) +{ + Util::createElement(xml, L"binding", L"text", {L"placement"}); ComPtr nodeList; HRESULT hr = xml->GetElementsByTagName(WinToastStringWrapper(L"text").Get(), &nodeList); if (SUCCEEDED(hr)) { @@ -764,7 +790,8 @@ HRESULT WinToast::setAttributionTextFieldHelper(_In_ IXmlDocument *xml, _In_ con return hr; } -HRESULT WinToast::addDurationHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& duration) { +HRESULT WinToast::addDurationHelper(_In_ IXmlDocument *xml, _In_ const std::wstring &duration) +{ ComPtr nodeList; HRESULT hr = xml->GetElementsByTagName(WinToastStringWrapper(L"toast").Get(), &nodeList); if (SUCCEEDED(hr)) { @@ -777,8 +804,7 @@ HRESULT WinToast::addDurationHelper(_In_ IXmlDocument *xml, _In_ const std::wstr ComPtr toastElement; hr = toastNode.As(&toastElement); if (SUCCEEDED(hr)) { - hr = toastElement->SetAttribute(WinToastStringWrapper(L"duration").Get(), - WinToastStringWrapper(duration).Get()); + hr = toastElement->SetAttribute(WinToastStringWrapper(L"duration").Get(), WinToastStringWrapper(duration).Get()); } } } @@ -786,7 +812,8 @@ HRESULT WinToast::addDurationHelper(_In_ IXmlDocument *xml, _In_ const std::wstr return hr; } -HRESULT WinToast::setTextFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& text, _In_ int pos) { +HRESULT WinToast::setTextFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring &text, _In_ int pos) +{ ComPtr nodeList; HRESULT hr = xml->GetElementsByTagName(WinToastStringWrapper(L"text").Get(), &nodeList); if (SUCCEEDED(hr)) { @@ -799,8 +826,8 @@ HRESULT WinToast::setTextFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wst return hr; } - -HRESULT WinToast::setImageFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& path) { +HRESULT WinToast::setImageFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring &path) +{ wchar_t imagePath[MAX_PATH] = L"file:///"; HRESULT hr = StringCchCatW(imagePath, MAX_PATH, path.c_str()); if (SUCCEEDED(hr)) { @@ -809,7 +836,7 @@ HRESULT WinToast::setImageFieldHelper(_In_ IXmlDocument *xml, _In_ const std::ws if (SUCCEEDED(hr)) { ComPtr node; hr = nodeList->Item(0, &node); - if (SUCCEEDED(hr)) { + if (SUCCEEDED(hr)) { ComPtr attributes; hr = node->get_Attributes(&attributes); if (SUCCEEDED(hr)) { @@ -825,11 +852,15 @@ HRESULT WinToast::setImageFieldHelper(_In_ IXmlDocument *xml, _In_ const std::ws return hr; } -HRESULT WinToast::setAudioFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& path, _In_opt_ WinToastTemplate::AudioOption option) { +HRESULT WinToast::setAudioFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring &path, _In_opt_ WinToastTemplate::AudioOption option) +{ std::vector attrs; - if (!path.empty()) attrs.push_back(L"src"); - if (option == WinToastTemplate::AudioOption::Loop) attrs.push_back(L"loop"); - if (option == WinToastTemplate::AudioOption::Silent) attrs.push_back(L"silent"); + if (!path.empty()) + attrs.push_back(L"src"); + if (option == WinToastTemplate::AudioOption::Loop) + attrs.push_back(L"loop"); + if (option == WinToastTemplate::AudioOption::Silent) + attrs.push_back(L"silent"); Util::createElement(xml, L"toast", L"audio", attrs); ComPtr nodeList; @@ -874,7 +905,8 @@ HRESULT WinToast::setAudioFieldHelper(_In_ IXmlDocument *xml, _In_ const std::ws return hr; } -HRESULT WinToast::addActionHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& content, _In_ const std::wstring& arguments) { +HRESULT WinToast::addActionHelper(_In_ IXmlDocument *xml, _In_ const std::wstring &content, _In_ const std::wstring &arguments) +{ ComPtr nodeList; HRESULT hr = xml->GetElementsByTagName(WinToastStringWrapper(L"actions").Get(), &nodeList); if (SUCCEEDED(hr)) { @@ -895,9 +927,9 @@ HRESULT WinToast::addActionHelper(_In_ IXmlDocument *xml, _In_ const std::wstrin ComPtr toastElement; hr = toastNode.As(&toastElement); if (SUCCEEDED(hr)) - hr = toastElement->SetAttribute(WinToastStringWrapper(L"template").Get(), WinToastStringWrapper(L"ToastGeneric").Get()); + hr = toastElement->SetAttribute(WinToastStringWrapper(L"template").Get(), WinToastStringWrapper(L"ToastGeneric").Get()); if (SUCCEEDED(hr)) - hr = toastElement->SetAttribute(WinToastStringWrapper(L"duration").Get(), WinToastStringWrapper(L"long").Get()); + hr = toastElement->SetAttribute(WinToastStringWrapper(L"duration").Get(), WinToastStringWrapper(L"long").Get()); if (SUCCEEDED(hr)) { ComPtr actionsElement; hr = xml->CreateElement(WinToastStringWrapper(L"actions").Get(), &actionsElement); @@ -934,102 +966,126 @@ HRESULT WinToast::addActionHelper(_In_ IXmlDocument *xml, _In_ const std::wstrin return hr; } -void WinToast::setError(_Out_ WinToastError* error, _In_ WinToastError value) { +void WinToast::setError(_Out_ WinToastError *error, _In_ WinToastError value) +{ if (error) { *error = value; } } -WinToastTemplate::WinToastTemplate(_In_ WinToastTemplateType type) : _type(type) { - static const std::size_t TextFieldsCount[] = { 1, 2, 2, 3, 1, 2, 2, 3}; +WinToastTemplate::WinToastTemplate(_In_ WinToastTemplateType type) + : _type(type) +{ + static const std::size_t TextFieldsCount[] = {1, 2, 2, 3, 1, 2, 2, 3}; _textFields = std::vector(TextFieldsCount[type], L""); } -WinToastTemplate::~WinToastTemplate() { +WinToastTemplate::~WinToastTemplate() +{ _textFields.clear(); } -void WinToastTemplate::setTextField(_In_ const std::wstring& txt, _In_ WinToastTemplate::TextField pos) { +void WinToastTemplate::setTextField(_In_ const std::wstring &txt, _In_ WinToastTemplate::TextField pos) +{ _textFields[pos] = txt; } -void WinToastTemplate::setImagePath(_In_ const std::wstring& imgPath) { +void WinToastTemplate::setImagePath(_In_ const std::wstring &imgPath) +{ _imagePath = imgPath; } -void WinToastTemplate::setAudioPath(_In_ const std::wstring& audioPath) { +void WinToastTemplate::setAudioPath(_In_ const std::wstring &audioPath) +{ _audioPath = audioPath; } -void WinToastTemplate::setAudioOption(_In_ WinToastTemplate::AudioOption audioOption) { +void WinToastTemplate::setAudioOption(_In_ WinToastTemplate::AudioOption audioOption) +{ _audioOption = audioOption; } -void WinToastTemplate::setDuration(_In_ Duration duration) { +void WinToastTemplate::setDuration(_In_ Duration duration) +{ _duration = duration; } -void WinToastTemplate::setExpiration(_In_ INT64 millisecondsFromNow) { +void WinToastTemplate::setExpiration(_In_ INT64 millisecondsFromNow) +{ _expiration = millisecondsFromNow; } -void WinToastTemplate::setAttributionText(_In_ const std::wstring& attributionText) { +void WinToastTemplate::setAttributionText(_In_ const std::wstring &attributionText) +{ _attributionText = attributionText; } -void WinToastTemplate::addAction(_In_ const std::wstring & label) +void WinToastTemplate::addAction(_In_ const std::wstring &label) { _actions.push_back(label); } -std::size_t WinToastTemplate::textFieldsCount() const { +std::size_t WinToastTemplate::textFieldsCount() const +{ return _textFields.size(); } -std::size_t WinToastTemplate::actionsCount() const { +std::size_t WinToastTemplate::actionsCount() const +{ return _actions.size(); } -bool WinToastTemplate::hasImage() const { - return _type < WinToastTemplateType::Text01; +bool WinToastTemplate::hasImage() const +{ + return _type < WinToastTemplateType::Text01; } -const std::vector& WinToastTemplate::textFields() const { +const std::vector &WinToastTemplate::textFields() const +{ return _textFields; } -const std::wstring& WinToastTemplate::textField(_In_ TextField pos) const { +const std::wstring &WinToastTemplate::textField(_In_ TextField pos) const +{ return _textFields[pos]; } -const std::wstring& WinToastTemplate::actionLabel(_In_ int pos) const { +const std::wstring &WinToastTemplate::actionLabel(_In_ int pos) const +{ return _actions[pos]; } -const std::wstring& WinToastTemplate::imagePath() const { +const std::wstring &WinToastTemplate::imagePath() const +{ return _imagePath; } -const std::wstring& WinToastTemplate::audioPath() const { +const std::wstring &WinToastTemplate::audioPath() const +{ return _audioPath; } -const std::wstring& WinToastTemplate::attributionText() const { +const std::wstring &WinToastTemplate::attributionText() const +{ return _attributionText; } -INT64 WinToastTemplate::expiration() const { +INT64 WinToastTemplate::expiration() const +{ return _expiration; } -WinToastTemplate::WinToastTemplateType WinToastTemplate::type() const { +WinToastTemplate::WinToastTemplateType WinToastTemplate::type() const +{ return _type; } -WinToastTemplate::AudioOption WinToastTemplate::audioOption() const { +WinToastTemplate::AudioOption WinToastTemplate::audioOption() const +{ return _audioOption; } -WinToastTemplate::Duration WinToastTemplate::duration() const { +WinToastTemplate::Duration WinToastTemplate::duration() const +{ return _duration; } diff --git a/src/notifications/wintoastlib.h b/src/notifications/wintoastlib.h index 710d2dbd2..6457ae49d 100644 --- a/src/notifications/wintoastlib.h +++ b/src/notifications/wintoastlib.h @@ -1,164 +1,156 @@ #ifndef WINTOASTLIB_H #define WINTOASTLIB_H -#include -#include -#include -#include -#include -#include -#include -#include #include +#include #include -#include -#include +#include +#include #include #include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace Microsoft::WRL; using namespace ABI::Windows::Data::Xml::Dom; using namespace ABI::Windows::Foundation; using namespace ABI::Windows::UI::Notifications; using namespace Windows::Foundation; -#define DEFAULT_SHELL_LINKS_PATH L"\\Microsoft\\Windows\\Start Menu\\Programs\\" -#define DEFAULT_LINK_FORMAT L".lnk" -namespace WinToastLib { +#define DEFAULT_SHELL_LINKS_PATH L"\\Microsoft\\Windows\\Start Menu\\Programs\\" +#define DEFAULT_LINK_FORMAT L".lnk" +namespace WinToastLib +{ +class IWinToastHandler +{ +public: + enum WinToastDismissalReason { + UserCanceled = ToastDismissalReason::ToastDismissalReason_UserCanceled, + ApplicationHidden = ToastDismissalReason::ToastDismissalReason_ApplicationHidden, + TimedOut = ToastDismissalReason::ToastDismissalReason_TimedOut + }; + virtual ~IWinToastHandler() + { + } + virtual void toastActivated() = 0; + virtual void toastActivated(int actionIndex) = 0; + virtual void toastDismissed(WinToastDismissalReason state) = 0; + virtual void toastFailed() = 0; +}; - class IWinToastHandler { - public: - enum WinToastDismissalReason { - UserCanceled = ToastDismissalReason::ToastDismissalReason_UserCanceled, - ApplicationHidden = ToastDismissalReason::ToastDismissalReason_ApplicationHidden, - TimedOut = ToastDismissalReason::ToastDismissalReason_TimedOut - }; - virtual ~IWinToastHandler() {} - virtual void toastActivated() = 0; - virtual void toastActivated(int actionIndex) = 0; - virtual void toastDismissed(WinToastDismissalReason state) = 0; - virtual void toastFailed() = 0; +class WinToastTemplate +{ +public: + enum Duration { System, Short, Long }; + enum AudioOption { Default = 0, Silent = 1, Loop = 2 }; + enum TextField { FirstLine = 0, SecondLine, ThirdLine }; + enum WinToastTemplateType { + ImageAndText01 = ToastTemplateType::ToastTemplateType_ToastImageAndText01, + ImageAndText02 = ToastTemplateType::ToastTemplateType_ToastImageAndText02, + ImageAndText03 = ToastTemplateType::ToastTemplateType_ToastImageAndText03, + ImageAndText04 = ToastTemplateType::ToastTemplateType_ToastImageAndText04, + Text01 = ToastTemplateType::ToastTemplateType_ToastText01, + Text02 = ToastTemplateType::ToastTemplateType_ToastText02, + Text03 = ToastTemplateType::ToastTemplateType_ToastText03, + Text04 = ToastTemplateType::ToastTemplateType_ToastText04, + WinToastTemplateTypeCount }; - class WinToastTemplate { - public: - enum Duration { System, Short, Long }; - enum AudioOption { Default = 0, Silent = 1, Loop = 2 }; - enum TextField { FirstLine = 0, SecondLine, ThirdLine }; - enum WinToastTemplateType { - ImageAndText01 = ToastTemplateType::ToastTemplateType_ToastImageAndText01, - ImageAndText02 = ToastTemplateType::ToastTemplateType_ToastImageAndText02, - ImageAndText03 = ToastTemplateType::ToastTemplateType_ToastImageAndText03, - ImageAndText04 = ToastTemplateType::ToastTemplateType_ToastImageAndText04, - Text01 = ToastTemplateType::ToastTemplateType_ToastText01, - Text02 = ToastTemplateType::ToastTemplateType_ToastText02, - Text03 = ToastTemplateType::ToastTemplateType_ToastText03, - Text04 = ToastTemplateType::ToastTemplateType_ToastText04, - WinToastTemplateTypeCount - }; + WinToastTemplate(_In_ WinToastTemplateType type = WinToastTemplateType::ImageAndText02); + ~WinToastTemplate(); - WinToastTemplate(_In_ WinToastTemplateType type = WinToastTemplateType::ImageAndText02); - ~WinToastTemplate(); + void setTextField(_In_ const std::wstring &txt, _In_ TextField pos); + void setImagePath(_In_ const std::wstring &imgPath); + void setAudioPath(_In_ const std::wstring &audioPath); + void setAttributionText(_In_ const std::wstring &attributionText); + void addAction(_In_ const std::wstring &label); + void setAudioOption(_In_ WinToastTemplate::AudioOption audioOption); + void setDuration(_In_ Duration duration); + void setExpiration(_In_ INT64 millisecondsFromNow); + std::size_t textFieldsCount() const; + std::size_t actionsCount() const; + bool hasImage() const; + const std::vector &textFields() const; + const std::wstring &textField(_In_ TextField pos) const; + const std::wstring &actionLabel(_In_ int pos) const; + const std::wstring &imagePath() const; + const std::wstring &audioPath() const; + const std::wstring &attributionText() const; + INT64 expiration() const; + WinToastTemplateType type() const; + WinToastTemplate::AudioOption audioOption() const; + Duration duration() const; - void setTextField(_In_ const std::wstring& txt, _In_ TextField pos); - void setImagePath(_In_ const std::wstring& imgPath); - void setAudioPath(_In_ const std::wstring& audioPath); - void setAttributionText(_In_ const std::wstring & attributionText); - void addAction(_In_ const std::wstring& label); - void setAudioOption(_In_ WinToastTemplate::AudioOption audioOption); - void setDuration(_In_ Duration duration); - void setExpiration(_In_ INT64 millisecondsFromNow); - std::size_t textFieldsCount() const; - std::size_t actionsCount() const; - bool hasImage() const; - const std::vector& textFields() const; - const std::wstring& textField(_In_ TextField pos) const; - const std::wstring& actionLabel(_In_ int pos) const; - const std::wstring& imagePath() const; - const std::wstring& audioPath() const; - const std::wstring& attributionText() const; - INT64 expiration() const; - WinToastTemplateType type() const; - WinToastTemplate::AudioOption audioOption() const; - Duration duration() const; - private: - std::vector _textFields; - std::vector _actions; - std::wstring _imagePath = L""; - std::wstring _audioPath = L""; - std::wstring _attributionText = L""; - INT64 _expiration = 0; - AudioOption _audioOption = WinToastTemplate::AudioOption::Default; - WinToastTemplateType _type = WinToastTemplateType::Text01; - Duration _duration = Duration::System; +private: + std::vector _textFields; + std::vector _actions; + std::wstring _imagePath = L""; + std::wstring _audioPath = L""; + std::wstring _attributionText = L""; + INT64 _expiration = 0; + AudioOption _audioOption = WinToastTemplate::AudioOption::Default; + WinToastTemplateType _type = WinToastTemplateType::Text01; + Duration _duration = Duration::System; +}; + +class WinToast +{ +public: + enum WinToastError { NoError = 0, NotInitialized, SystemNotSupported, ShellLinkNotCreated, InvalidAppUserModelID, InvalidParameters, InvalidHandler, NotDisplayed, UnknownError }; + + enum ShortcutResult { + SHORTCUT_UNCHANGED = 0, + SHORTCUT_WAS_CHANGED = 1, + SHORTCUT_WAS_CREATED = 2, + + SHORTCUT_MISSING_PARAMETERS = -1, + SHORTCUT_INCOMPATIBLE_OS = -2, + SHORTCUT_COM_INIT_FAILURE = -3, + SHORTCUT_CREATE_FAILED = -4 }; - class WinToast { - public: - enum WinToastError { - NoError = 0, - NotInitialized, - SystemNotSupported, - ShellLinkNotCreated, - InvalidAppUserModelID, - InvalidParameters, - InvalidHandler, - NotDisplayed, - UnknownError - }; + WinToast(void); + virtual ~WinToast(); + static WinToast *instance(); + static bool isCompatible(); + static bool isSupportingModernFeatures(); + static std::wstring configureAUMI(_In_ const std::wstring &companyName, _In_ const std::wstring &productName, _In_ const std::wstring &subProduct = std::wstring(), _In_ const std::wstring &versionInformation = std::wstring()); + virtual bool initialize(_Out_ WinToastError *error = nullptr); + virtual bool isInitialized() const; + virtual bool hideToast(_In_ INT64 id); + virtual INT64 showToast(_In_ const WinToastTemplate &toast, _In_ IWinToastHandler *handler, _Out_ WinToastError *error = nullptr); + virtual void clear(); + virtual enum ShortcutResult createShortcut(); - enum ShortcutResult { - SHORTCUT_UNCHANGED = 0, - SHORTCUT_WAS_CHANGED = 1, - SHORTCUT_WAS_CREATED = 2, + const std::wstring &appName() const; + const std::wstring &appUserModelId() const; + void setAppUserModelId(_In_ const std::wstring &appName); + void setAppName(_In_ const std::wstring &appName); - SHORTCUT_MISSING_PARAMETERS = -1, - SHORTCUT_INCOMPATIBLE_OS = -2, - SHORTCUT_COM_INIT_FAILURE = -3, - SHORTCUT_CREATE_FAILED = -4 - }; +protected: + bool _isInitialized; + bool _hasCoInitialized; + std::wstring _appName; + std::wstring _aumi; + std::map> _buffer; - WinToast(void); - virtual ~WinToast(); - static WinToast* instance(); - static bool isCompatible(); - static bool isSupportingModernFeatures(); - static std::wstring configureAUMI(_In_ const std::wstring& companyName, - _In_ const std::wstring& productName, - _In_ const std::wstring& subProduct = std::wstring(), - _In_ const std::wstring& versionInformation = std::wstring() - ); - virtual bool initialize(_Out_ WinToastError* error = nullptr); - virtual bool isInitialized() const; - virtual bool hideToast(_In_ INT64 id); - virtual INT64 showToast(_In_ const WinToastTemplate& toast, _In_ IWinToastHandler* handler, _Out_ WinToastError* error = nullptr); - virtual void clear(); - virtual enum ShortcutResult createShortcut(); - - const std::wstring& appName() const; - const std::wstring& appUserModelId() const; - void setAppUserModelId(_In_ const std::wstring& appName); - void setAppName(_In_ const std::wstring& appName); - - protected: - bool _isInitialized; - bool _hasCoInitialized; - std::wstring _appName; - std::wstring _aumi; - std::map> _buffer; - - HRESULT validateShellLinkHelper(_Out_ bool& wasChanged); - HRESULT createShellLinkHelper(); - HRESULT setImageFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& path); - HRESULT setAudioFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& path, _In_opt_ WinToastTemplate::AudioOption option = WinToastTemplate::AudioOption::Default); - HRESULT setTextFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& text, _In_ int pos); - HRESULT setAttributionTextFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& text); - HRESULT addActionHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& action, _In_ const std::wstring& arguments); - HRESULT addDurationHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& duration); - ComPtr notifier(_In_ bool* succeded) const; - void setError(_Out_ WinToastError* error, _In_ WinToastError value); - }; + HRESULT validateShellLinkHelper(_Out_ bool &wasChanged); + HRESULT createShellLinkHelper(); + HRESULT setImageFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring &path); + HRESULT setAudioFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring &path, _In_opt_ WinToastTemplate::AudioOption option = WinToastTemplate::AudioOption::Default); + HRESULT setTextFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring &text, _In_ int pos); + HRESULT setAttributionTextFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring &text); + HRESULT addActionHelper(_In_ IXmlDocument *xml, _In_ const std::wstring &action, _In_ const std::wstring &arguments); + HRESULT addDurationHelper(_In_ IXmlDocument *xml, _In_ const std::wstring &duration); + ComPtr notifier(_In_ bool *succeded) const; + void setError(_Out_ WinToastError *error, _In_ WinToastError value); +}; } #endif // WINTOASTLIB_H diff --git a/src/publicroomlistmodel.cpp b/src/publicroomlistmodel.cpp index 29ff97d4d..95e2062d8 100644 --- a/src/publicroomlistmodel.cpp +++ b/src/publicroomlistmodel.cpp @@ -1,218 +1,226 @@ #include "publicroomlistmodel.h" -PublicRoomListModel::PublicRoomListModel(QObject* parent) - : QAbstractListModel(parent) {} - -void PublicRoomListModel::setConnection(Connection* conn) { - if (m_connection == conn) - return; - - beginResetModel(); - - nextBatch = ""; - attempted = false; - rooms.clear(); - m_server.clear(); - - if (m_connection) { - m_connection->disconnect(this); - } - - endResetModel(); - - m_connection = conn; - - if (job) { - job->abandon(); - job = nullptr; - } - - if (m_connection) { - next(); - } - - emit connectionChanged(); - emit serverChanged(); - emit hasMoreChanged(); +PublicRoomListModel::PublicRoomListModel(QObject *parent) + : QAbstractListModel(parent) +{ } -void PublicRoomListModel::setServer(const QString& value) { - if (m_server == value) - return; +void PublicRoomListModel::setConnection(Connection *conn) +{ + if (m_connection == conn) + return; - m_server = value; + beginResetModel(); - beginResetModel(); + nextBatch = ""; + attempted = false; + rooms.clear(); + m_server.clear(); - nextBatch = ""; - attempted = false; - rooms.clear(); - - endResetModel(); - - if (job) { - job->abandon(); - job = nullptr; - } - - if (m_connection) { - next(); - } - - emit serverChanged(); - emit hasMoreChanged(); -} - -void PublicRoomListModel::setKeyword(const QString& value) { - if (m_keyword == value) - return; - - m_keyword = value; - - beginResetModel(); - - nextBatch = ""; - attempted = false; - rooms.clear(); - - endResetModel(); - - if (job) { - job->abandon(); - job = nullptr; - } - - if (m_connection) { - next(); - } - - emit keywordChanged(); - emit hasMoreChanged(); -} - -void PublicRoomListModel::next(int count) { - if (count < 1) - return; - - if (job) { - qDebug() << "PublicRoomListModel: Other jobs running, ignore"; - - return; - } - - if (!hasMore()) - return; - - job = m_connection->callApi( - m_server, count, nextBatch, QueryPublicRoomsJob::Filter{m_keyword}); - - connect(job, &BaseJob::finished, this, [=] { - attempted = true; - - if (job->status() == BaseJob::Success) { - nextBatch = job->nextBatch(); - - this->beginInsertRows({}, rooms.count(), - rooms.count() + job->chunk().count() - 1); - rooms.append(job->chunk()); - this->endInsertRows(); - - if (job->nextBatch().isEmpty()) { - emit hasMoreChanged(); - } + if (m_connection) { + m_connection->disconnect(this); } - this->job = nullptr; - }); + endResetModel(); + + m_connection = conn; + + if (job) { + job->abandon(); + job = nullptr; + } + + if (m_connection) { + next(); + } + + emit connectionChanged(); + emit serverChanged(); + emit hasMoreChanged(); } -QVariant PublicRoomListModel::data(const QModelIndex& index, int role) const { - if (!index.isValid()) - return QVariant(); +void PublicRoomListModel::setServer(const QString &value) +{ + if (m_server == value) + return; + + m_server = value; + + beginResetModel(); + + nextBatch = ""; + attempted = false; + rooms.clear(); + + endResetModel(); + + if (job) { + job->abandon(); + job = nullptr; + } + + if (m_connection) { + next(); + } + + emit serverChanged(); + emit hasMoreChanged(); +} + +void PublicRoomListModel::setKeyword(const QString &value) +{ + if (m_keyword == value) + return; + + m_keyword = value; + + beginResetModel(); + + nextBatch = ""; + attempted = false; + rooms.clear(); + + endResetModel(); + + if (job) { + job->abandon(); + job = nullptr; + } + + if (m_connection) { + next(); + } + + emit keywordChanged(); + emit hasMoreChanged(); +} + +void PublicRoomListModel::next(int count) +{ + if (count < 1) + return; + + if (job) { + qDebug() << "PublicRoomListModel: Other jobs running, ignore"; + + return; + } + + if (!hasMore()) + return; + + job = m_connection->callApi(m_server, count, nextBatch, QueryPublicRoomsJob::Filter {m_keyword}); + + connect(job, &BaseJob::finished, this, [=] { + attempted = true; + + if (job->status() == BaseJob::Success) { + nextBatch = job->nextBatch(); + + this->beginInsertRows({}, rooms.count(), rooms.count() + job->chunk().count() - 1); + rooms.append(job->chunk()); + this->endInsertRows(); + + if (job->nextBatch().isEmpty()) { + emit hasMoreChanged(); + } + } + + this->job = nullptr; + }); +} + +QVariant PublicRoomListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (index.row() >= rooms.count()) { + qDebug() << "PublicRoomListModel, something's wrong: index.row() >= " + "rooms.count()"; + return {}; + } + auto room = rooms.at(index.row()); + if (role == NameRole) { + auto displayName = room.name; + if (!displayName.isEmpty()) { + return displayName; + } + + displayName = room.canonicalAlias; + if (!displayName.isEmpty()) { + return displayName; + } + + if (!room.aliases.isEmpty()) { + displayName = room.aliases.front(); + } + + if (!displayName.isEmpty()) { + return displayName; + } + + return room.roomId; + } + if (role == AvatarRole) { + auto avatarUrl = room.avatarUrl; + + if (avatarUrl.isEmpty()) { + return ""; + } + + return avatarUrl.remove(0, 6); + } + if (role == TopicRole) { + return room.topic; + } + if (role == RoomIDRole) { + return room.roomId; + } + if (role == MemberCountRole) { + return room.numJoinedMembers; + } + if (role == AllowGuestsRole) { + return room.guestCanJoin; + } + if (role == WorldReadableRole) { + return room.worldReadable; + } + if (role == IsJoinedRole) { + if (!m_connection) + return {}; + + return m_connection->room(room.roomId, JoinState::Join) != nullptr; + } - if (index.row() >= rooms.count()) { - qDebug() << "PublicRoomListModel, something's wrong: index.row() >= " - "rooms.count()"; return {}; - } - auto room = rooms.at(index.row()); - if (role == NameRole) { - auto displayName = room.name; - if (!displayName.isEmpty()) { - return displayName; - } - - displayName = room.canonicalAlias; - if (!displayName.isEmpty()) { - return displayName; - } - - if (!room.aliases.isEmpty()) { - displayName = room.aliases.front(); - } - - if (!displayName.isEmpty()) { - return displayName; - } - - return room.roomId; - } - if (role == AvatarRole) { - auto avatarUrl = room.avatarUrl; - - if (avatarUrl.isEmpty()) { - return ""; - } - - return avatarUrl.remove(0, 6); - } - if (role == TopicRole) { - return room.topic; - } - if (role == RoomIDRole) { - return room.roomId; - } - if (role == MemberCountRole) { - return room.numJoinedMembers; - } - if (role == AllowGuestsRole) { - return room.guestCanJoin; - } - if (role == WorldReadableRole) { - return room.worldReadable; - } - if (role == IsJoinedRole) { - if (!m_connection) - return {}; - - return m_connection->room(room.roomId, JoinState::Join) != nullptr; - } - - return {}; } -QHash PublicRoomListModel::roleNames() const { - QHash roles; +QHash PublicRoomListModel::roleNames() const +{ + QHash roles; - roles[NameRole] = "name"; - roles[AvatarRole] = "avatar"; - roles[TopicRole] = "topic"; - roles[RoomIDRole] = "roomID"; - roles[MemberCountRole] = "memberCount"; - roles[AllowGuestsRole] = "allowGuests"; - roles[WorldReadableRole] = "worldReadable"; - roles[IsJoinedRole] = "isJoined"; + roles[NameRole] = "name"; + roles[AvatarRole] = "avatar"; + roles[TopicRole] = "topic"; + roles[RoomIDRole] = "roomID"; + roles[MemberCountRole] = "memberCount"; + roles[AllowGuestsRole] = "allowGuests"; + roles[WorldReadableRole] = "worldReadable"; + roles[IsJoinedRole] = "isJoined"; - return roles; + return roles; } -int PublicRoomListModel::rowCount(const QModelIndex& parent) const { - if (parent.isValid()) - return 0; +int PublicRoomListModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; - return rooms.count(); + return rooms.count(); } -bool PublicRoomListModel::hasMore() const { - return !(attempted && nextBatch.isEmpty()); +bool PublicRoomListModel::hasMore() const +{ + return !(attempted && nextBatch.isEmpty()); } diff --git a/src/publicroomlistmodel.h b/src/publicroomlistmodel.h index 24add9887..d84221fea 100644 --- a/src/publicroomlistmodel.h +++ b/src/publicroomlistmodel.h @@ -10,64 +10,72 @@ using namespace Quotient; -class PublicRoomListModel : public QAbstractListModel { - Q_OBJECT - Q_PROPERTY(Connection* connection READ connection WRITE setConnection NOTIFY - connectionChanged) - Q_PROPERTY(QString server READ server WRITE setServer NOTIFY serverChanged) - Q_PROPERTY( - QString keyword READ keyword WRITE setKeyword NOTIFY keywordChanged) - Q_PROPERTY(bool hasMore READ hasMore NOTIFY hasMoreChanged) +class PublicRoomListModel : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(Connection *connection READ connection WRITE setConnection NOTIFY connectionChanged) + Q_PROPERTY(QString server READ server WRITE setServer NOTIFY serverChanged) + Q_PROPERTY(QString keyword READ keyword WRITE setKeyword NOTIFY keywordChanged) + Q_PROPERTY(bool hasMore READ hasMore NOTIFY hasMoreChanged) - public: - enum EventRoles { - NameRole = Qt::DisplayRole + 1, - AvatarRole, - TopicRole, - RoomIDRole, - MemberCountRole, - AllowGuestsRole, - WorldReadableRole, - IsJoinedRole, - }; +public: + enum EventRoles { + NameRole = Qt::DisplayRole + 1, + AvatarRole, + TopicRole, + RoomIDRole, + MemberCountRole, + AllowGuestsRole, + WorldReadableRole, + IsJoinedRole, + }; - PublicRoomListModel(QObject* parent = nullptr); + PublicRoomListModel(QObject *parent = nullptr); - QVariant data(const QModelIndex& index, int role = NameRole) const override; - int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = NameRole) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; - QHash roleNames() const override; + QHash roleNames() const override; - Connection* connection() const { return m_connection; } - void setConnection(Connection* value); + Connection *connection() const + { + return m_connection; + } + void setConnection(Connection *value); - QString server() const { return m_server; } - void setServer(const QString& value); + QString server() const + { + return m_server; + } + void setServer(const QString &value); - QString keyword() const { return m_keyword; } - void setKeyword(const QString& value); + QString keyword() const + { + return m_keyword; + } + void setKeyword(const QString &value); - bool hasMore() const; + bool hasMore() const; - Q_INVOKABLE void next(int count = 50); + Q_INVOKABLE void next(int count = 50); - private: - Connection* m_connection = nullptr; - QString m_server; - QString m_keyword; +private: + Connection *m_connection = nullptr; + QString m_server; + QString m_keyword; - bool attempted = false; - QString nextBatch; + bool attempted = false; + QString nextBatch; - QVector rooms; + QVector rooms; - QueryPublicRoomsJob* job = nullptr; + QueryPublicRoomsJob *job = nullptr; - signals: - void connectionChanged(); - void serverChanged(); - void keywordChanged(); - void hasMoreChanged(); +signals: + void connectionChanged(); + void serverChanged(); + void keywordChanged(); + void hasMoreChanged(); }; -#endif // PUBLICROOMLISTMODEL_H +#endif // PUBLICROOMLISTMODEL_H diff --git a/src/roomlistmodel.cpp b/src/roomlistmodel.cpp index aa6ec8115..f497b2cae 100644 --- a/src/roomlistmodel.cpp +++ b/src/roomlistmodel.cpp @@ -11,251 +11,268 @@ #include #include -RoomListModel::RoomListModel(QObject* parent) : QAbstractListModel(parent) {} +RoomListModel::RoomListModel(QObject *parent) + : QAbstractListModel(parent) +{ +} -RoomListModel::~RoomListModel() {} +RoomListModel::~RoomListModel() +{ +} -void RoomListModel::setConnection(Connection* connection) { - if (connection == m_connection) - return; - if (m_connection) - m_connection->disconnect(this); - if (!connection) { - qDebug() << "Removing current connection..."; - m_connection = nullptr; +void RoomListModel::setConnection(Connection *connection) +{ + if (connection == m_connection) + return; + if (m_connection) + m_connection->disconnect(this); + if (!connection) { + qDebug() << "Removing current connection..."; + m_connection = nullptr; + beginResetModel(); + m_rooms.clear(); + endResetModel(); + return; + } + + m_connection = connection; + + for (SpectralRoom *room : m_rooms) + room->disconnect(this); + + connect(connection, &Connection::connected, this, &RoomListModel::doResetModel); + connect(connection, &Connection::invitedRoom, this, &RoomListModel::updateRoom); + connect(connection, &Connection::joinedRoom, this, &RoomListModel::updateRoom); + connect(connection, &Connection::leftRoom, this, &RoomListModel::updateRoom); + connect(connection, &Connection::aboutToDeleteRoom, this, &RoomListModel::deleteRoom); + connect(connection, &Connection::directChatsListChanged, this, [=](Quotient::DirectChatsMap additions, Quotient::DirectChatsMap removals) { + for (QString roomID : additions.values() + removals.values()) { + auto room = connection->room(roomID); + if (room) + refresh(static_cast(room)); + } + }); + + doResetModel(); +} + +void RoomListModel::doResetModel() +{ beginResetModel(); m_rooms.clear(); - endResetModel(); - return; - } - - m_connection = connection; - - for (SpectralRoom* room : m_rooms) - room->disconnect(this); - - connect(connection, &Connection::connected, this, - &RoomListModel::doResetModel); - connect(connection, &Connection::invitedRoom, this, - &RoomListModel::updateRoom); - connect(connection, &Connection::joinedRoom, this, - &RoomListModel::updateRoom); - connect(connection, &Connection::leftRoom, this, &RoomListModel::updateRoom); - connect(connection, &Connection::aboutToDeleteRoom, this, - &RoomListModel::deleteRoom); - connect(connection, &Connection::directChatsListChanged, this, - [=](Quotient::DirectChatsMap additions, - Quotient::DirectChatsMap removals) { - for (QString roomID : additions.values() + removals.values()) { - auto room = connection->room(roomID); - if (room) - refresh(static_cast(room)); - } - }); - - doResetModel(); -} - -void RoomListModel::doResetModel() { - beginResetModel(); - m_rooms.clear(); - for (auto r : m_connection->allRooms()) { - doAddRoom(r); - } - endResetModel(); - refreshNotificationCount(); -} - -SpectralRoom* RoomListModel::roomAt(int row) const { - return m_rooms.at(row); -} - -void RoomListModel::doAddRoom(Room* r) { - if (auto room = static_cast(r)) { - m_rooms.append(room); - connectRoomSignals(room); - emit roomAdded(room); - } else { - qCritical() << "Attempt to add nullptr to the room list"; - Q_ASSERT(false); - } -} - -void RoomListModel::connectRoomSignals(SpectralRoom* room) { - connect(room, &Room::displaynameChanged, this, [=] { refresh(room); }); - connect(room, &Room::unreadMessagesChanged, this, [=] { refresh(room); }); - connect(room, &Room::notificationCountChanged, this, [=] { refresh(room); }); - connect(room, &Room::avatarChanged, this, - [this, room] { refresh(room, {AvatarRole}); }); - connect(room, &Room::tagsChanged, this, [=] { refresh(room); }); - connect(room, &Room::joinStateChanged, this, [=] { refresh(room); }); - connect(room, &Room::addedMessages, this, - [=] { refresh(room, {LastEventRole}); }); - connect(room, &Room::notificationCountChanged, this, [=] { - if (room->notificationCount() == 0) - return; - if (room->timelineSize() == 0) - return; - const RoomEvent* lastEvent = room->messageEvents().rbegin()->get(); - if (lastEvent->isStateEvent()) - return; - User* sender = room->user(lastEvent->senderId()); - if (sender == room->localUser()) - return; - emit newMessage(room->id(), lastEvent->id(), room->displayName(), - sender->displayname(), room->eventToString(*lastEvent), - room->avatar(128)); - }); - connect(room, &Room::highlightCountChanged, this, [=] { - if (room->highlightCount() == 0) - return; - if (room->timelineSize() == 0) - return; - const RoomEvent* lastEvent = room->messageEvents().rbegin()->get(); - if (lastEvent->isStateEvent()) - return; - User* sender = room->user(lastEvent->senderId()); - if (sender == room->localUser()) - return; - emit newHighlight(room->id(), lastEvent->id(), room->displayName(), - sender->displayname(), room->eventToString(*lastEvent), - room->avatar(128)); - }); - connect(room, &Room::notificationCountChanged, this, - &RoomListModel::refreshNotificationCount); -} - -void RoomListModel::refreshNotificationCount() { - int count = 0; - for (auto room : m_rooms) { - count += room->notificationCount(); - } - m_notificationCount = count; - emit notificationCountChanged(); -} - -void RoomListModel::updateRoom(Room* room, Room* prev) { - // There are two cases when this method is called: - // 1. (prev == nullptr) adding a new room to the room list - // 2. (prev != nullptr) accepting/rejecting an invitation or inviting to - // the previously left room (in both cases prev has the previous state). - if (prev == room) { - qCritical() << "RoomListModel::updateRoom: room tried to replace itself"; - refresh(static_cast(room)); - return; - } - if (prev && room->id() != prev->id()) { - qCritical() << "RoomListModel::updateRoom: attempt to update room" - << room->id() << "to" << prev->id(); - // That doesn't look right but technically we still can do it. - } - // Ok, we're through with pre-checks, now for the real thing. - auto newRoom = static_cast(room); - const auto it = std::find_if( - m_rooms.begin(), m_rooms.end(), - [=](const SpectralRoom* r) { return r == prev || r == newRoom; }); - if (it != m_rooms.end()) { - const int row = it - m_rooms.begin(); - // There's no guarantee that prev != newRoom - if (*it == prev && *it != newRoom) { - prev->disconnect(this); - m_rooms.replace(row, newRoom); - connectRoomSignals(newRoom); + for (auto r : m_connection->allRooms()) { + doAddRoom(r); } - emit dataChanged(index(row), index(row)); - } else { - beginInsertRows(QModelIndex(), m_rooms.count(), m_rooms.count()); - doAddRoom(newRoom); - endInsertRows(); - } + endResetModel(); + refreshNotificationCount(); } -void RoomListModel::deleteRoom(Room* room) { - qDebug() << "Deleting room" << room->id(); - const auto it = std::find(m_rooms.begin(), m_rooms.end(), room); - if (it == m_rooms.end()) - return; // Already deleted, nothing to do - qDebug() << "Erasing room" << room->id(); - const int row = it - m_rooms.begin(); - beginRemoveRows(QModelIndex(), row, row); - m_rooms.erase(it); - endRemoveRows(); +SpectralRoom *RoomListModel::roomAt(int row) const +{ + return m_rooms.at(row); } -int RoomListModel::rowCount(const QModelIndex& parent) const { - if (parent.isValid()) - return 0; - return m_rooms.count(); +void RoomListModel::doAddRoom(Room *r) +{ + if (auto room = static_cast(r)) { + m_rooms.append(room); + connectRoomSignals(room); + emit roomAdded(room); + } else { + qCritical() << "Attempt to add nullptr to the room list"; + Q_ASSERT(false); + } } -QVariant RoomListModel::data(const QModelIndex& index, int role) const { - if (!index.isValid()) +void RoomListModel::connectRoomSignals(SpectralRoom *room) +{ + connect(room, &Room::displaynameChanged, this, [=] { + refresh(room); + }); + connect(room, &Room::unreadMessagesChanged, this, [=] { + refresh(room); + }); + connect(room, &Room::notificationCountChanged, this, [=] { + refresh(room); + }); + connect(room, &Room::avatarChanged, this, [this, room] { + refresh(room, {AvatarRole}); + }); + connect(room, &Room::tagsChanged, this, [=] { + refresh(room); + }); + connect(room, &Room::joinStateChanged, this, [=] { + refresh(room); + }); + connect(room, &Room::addedMessages, this, [=] { + refresh(room, {LastEventRole}); + }); + connect(room, &Room::notificationCountChanged, this, [=] { + if (room->notificationCount() == 0) + return; + if (room->timelineSize() == 0) + return; + const RoomEvent *lastEvent = room->messageEvents().rbegin()->get(); + if (lastEvent->isStateEvent()) + return; + User *sender = room->user(lastEvent->senderId()); + if (sender == room->localUser()) + return; + emit newMessage(room->id(), lastEvent->id(), room->displayName(), sender->displayname(), room->eventToString(*lastEvent), room->avatar(128)); + }); + connect(room, &Room::highlightCountChanged, this, [=] { + if (room->highlightCount() == 0) + return; + if (room->timelineSize() == 0) + return; + const RoomEvent *lastEvent = room->messageEvents().rbegin()->get(); + if (lastEvent->isStateEvent()) + return; + User *sender = room->user(lastEvent->senderId()); + if (sender == room->localUser()) + return; + emit newHighlight(room->id(), lastEvent->id(), room->displayName(), sender->displayname(), room->eventToString(*lastEvent), room->avatar(128)); + }); + connect(room, &Room::notificationCountChanged, this, &RoomListModel::refreshNotificationCount); +} + +void RoomListModel::refreshNotificationCount() +{ + int count = 0; + for (auto room : m_rooms) { + count += room->notificationCount(); + } + m_notificationCount = count; + emit notificationCountChanged(); +} + +void RoomListModel::updateRoom(Room *room, Room *prev) +{ + // There are two cases when this method is called: + // 1. (prev == nullptr) adding a new room to the room list + // 2. (prev != nullptr) accepting/rejecting an invitation or inviting to + // the previously left room (in both cases prev has the previous state). + if (prev == room) { + qCritical() << "RoomListModel::updateRoom: room tried to replace itself"; + refresh(static_cast(room)); + return; + } + if (prev && room->id() != prev->id()) { + qCritical() << "RoomListModel::updateRoom: attempt to update room" << room->id() << "to" << prev->id(); + // That doesn't look right but technically we still can do it. + } + // Ok, we're through with pre-checks, now for the real thing. + auto newRoom = static_cast(room); + const auto it = std::find_if(m_rooms.begin(), m_rooms.end(), [=](const SpectralRoom *r) { + return r == prev || r == newRoom; + }); + if (it != m_rooms.end()) { + const int row = it - m_rooms.begin(); + // There's no guarantee that prev != newRoom + if (*it == prev && *it != newRoom) { + prev->disconnect(this); + m_rooms.replace(row, newRoom); + connectRoomSignals(newRoom); + } + emit dataChanged(index(row), index(row)); + } else { + beginInsertRows(QModelIndex(), m_rooms.count(), m_rooms.count()); + doAddRoom(newRoom); + endInsertRows(); + } +} + +void RoomListModel::deleteRoom(Room *room) +{ + qDebug() << "Deleting room" << room->id(); + const auto it = std::find(m_rooms.begin(), m_rooms.end(), room); + if (it == m_rooms.end()) + return; // Already deleted, nothing to do + qDebug() << "Erasing room" << room->id(); + const int row = it - m_rooms.begin(); + beginRemoveRows(QModelIndex(), row, row); + m_rooms.erase(it); + endRemoveRows(); +} + +int RoomListModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; + return m_rooms.count(); +} + +QVariant RoomListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (index.row() >= m_rooms.count()) { + qDebug() << "UserListModel: something wrong here..."; + return QVariant(); + } + SpectralRoom *room = m_rooms.at(index.row()); + if (role == NameRole) + return room->displayName(); + if (role == AvatarRole) + return room->avatarMediaId(); + if (role == TopicRole) + return room->topic(); + if (role == CategoryRole) { + if (room->joinState() == JoinState::Invite) + return RoomType::Invited; + if (room->isFavourite()) + return RoomType::Favorite; + if (room->isDirectChat()) + return RoomType::Direct; + if (room->isLowPriority()) + return RoomType::Deprioritized; + return RoomType::Normal; + } + if (role == UnreadCountRole) + return room->unreadCount(); + if (role == NotificationCountRole) + return room->notificationCount(); + if (role == HighlightCountRole) + return room->highlightCount(); + if (role == LastEventRole) + return room->lastEvent(); + if (role == LastActiveTimeRole) + return room->lastActiveTime(); + if (role == JoinStateRole) { + if (!room->successorId().isEmpty()) + return QStringLiteral("upgraded"); + return toCString(room->joinState()); + } + if (role == CurrentRoomRole) + return QVariant::fromValue(room); return QVariant(); - - if (index.row() >= m_rooms.count()) { - qDebug() << "UserListModel: something wrong here..."; - return QVariant(); - } - SpectralRoom* room = m_rooms.at(index.row()); - if (role == NameRole) - return room->displayName(); - if (role == AvatarRole) - return room->avatarMediaId(); - if (role == TopicRole) - return room->topic(); - if (role == CategoryRole) { - if (room->joinState() == JoinState::Invite) - return RoomType::Invited; - if (room->isFavourite()) - return RoomType::Favorite; - if (room->isDirectChat()) - return RoomType::Direct; - if (room->isLowPriority()) - return RoomType::Deprioritized; - return RoomType::Normal; - } - if (role == UnreadCountRole) - return room->unreadCount(); - if (role == NotificationCountRole) - return room->notificationCount(); - if (role == HighlightCountRole) - return room->highlightCount(); - if (role == LastEventRole) - return room->lastEvent(); - if (role == LastActiveTimeRole) - return room->lastActiveTime(); - if (role == JoinStateRole) { - if (!room->successorId().isEmpty()) - return QStringLiteral("upgraded"); - return toCString(room->joinState()); - } - if (role == CurrentRoomRole) - return QVariant::fromValue(room); - return QVariant(); } -void RoomListModel::refresh(SpectralRoom* room, const QVector& roles) { - const auto it = std::find(m_rooms.begin(), m_rooms.end(), room); - if (it == m_rooms.end()) { - qCritical() << "Room" << room->id() << "not found in the room list"; - return; - } - const auto idx = index(it - m_rooms.begin()); - emit dataChanged(idx, idx, roles); +void RoomListModel::refresh(SpectralRoom *room, const QVector &roles) +{ + const auto it = std::find(m_rooms.begin(), m_rooms.end(), room); + if (it == m_rooms.end()) { + qCritical() << "Room" << room->id() << "not found in the room list"; + return; + } + const auto idx = index(it - m_rooms.begin()); + emit dataChanged(idx, idx, roles); } -QHash RoomListModel::roleNames() const { - QHash roles; - roles[NameRole] = "name"; - roles[AvatarRole] = "avatar"; - roles[TopicRole] = "topic"; - roles[CategoryRole] = "category"; - roles[UnreadCountRole] = "unreadCount"; - roles[NotificationCountRole] = "notificationCount"; - roles[HighlightCountRole] = "highlightCount"; - roles[LastEventRole] = "lastEvent"; - roles[LastActiveTimeRole] = "lastActiveTime"; - roles[JoinStateRole] = "joinState"; - roles[CurrentRoomRole] = "currentRoom"; - return roles; +QHash RoomListModel::roleNames() const +{ + QHash roles; + roles[NameRole] = "name"; + roles[AvatarRole] = "avatar"; + roles[TopicRole] = "topic"; + roles[CategoryRole] = "category"; + roles[UnreadCountRole] = "unreadCount"; + roles[NotificationCountRole] = "notificationCount"; + roles[HighlightCountRole] = "highlightCount"; + roles[LastEventRole] = "lastEvent"; + roles[LastActiveTimeRole] = "lastActiveTime"; + roles[JoinStateRole] = "joinState"; + roles[CurrentRoomRole] = "currentRoom"; + return roles; } diff --git a/src/roomlistmodel.h b/src/roomlistmodel.h index 59ef3b70d..68d3730b6 100644 --- a/src/roomlistmodel.h +++ b/src/roomlistmodel.h @@ -10,92 +10,87 @@ using namespace Quotient; -class RoomType : public QObject { - Q_OBJECT +class RoomType : public QObject +{ + Q_OBJECT - public: - enum Types { - Invited = 1, - Favorite, - Direct, - Normal, - Deprioritized, - }; - Q_ENUMS(Types) +public: + enum Types { + Invited = 1, + Favorite, + Direct, + Normal, + Deprioritized, + }; + Q_ENUMS(Types) }; -class RoomListModel : public QAbstractListModel { - Q_OBJECT - Q_PROPERTY(Connection* connection READ connection WRITE setConnection) - Q_PROPERTY(int notificationCount READ notificationCount NOTIFY - notificationCountChanged) +class RoomListModel : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(Connection *connection READ connection WRITE setConnection) + Q_PROPERTY(int notificationCount READ notificationCount NOTIFY notificationCountChanged) - public: - enum EventRoles { - NameRole = Qt::UserRole + 1, - AvatarRole, - TopicRole, - CategoryRole, - UnreadCountRole, - NotificationCountRole, - HighlightCountRole, - LastEventRole, - LastActiveTimeRole, - JoinStateRole, - CurrentRoomRole, - }; - Q_ENUM(EventRoles) +public: + enum EventRoles { + NameRole = Qt::UserRole + 1, + AvatarRole, + TopicRole, + CategoryRole, + UnreadCountRole, + NotificationCountRole, + HighlightCountRole, + LastEventRole, + LastActiveTimeRole, + JoinStateRole, + CurrentRoomRole, + }; + Q_ENUM(EventRoles) - RoomListModel(QObject* parent = nullptr); - virtual ~RoomListModel() override; + RoomListModel(QObject *parent = nullptr); + virtual ~RoomListModel() override; - Connection* connection() const { return m_connection; } - void setConnection(Connection* connection); - void doResetModel(); + Connection *connection() const + { + return m_connection; + } + void setConnection(Connection *connection); + void doResetModel(); - Q_INVOKABLE SpectralRoom* roomAt(int row) const; + Q_INVOKABLE SpectralRoom *roomAt(int row) const; - QVariant data(const QModelIndex& index, - int role = Qt::DisplayRole) const override; - Q_INVOKABLE int rowCount( - const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + Q_INVOKABLE int rowCount(const QModelIndex &parent = QModelIndex()) const override; - QHash roleNames() const override; + QHash roleNames() const override; - int notificationCount() const { return m_notificationCount; } + int notificationCount() const + { + return m_notificationCount; + } - private slots: - void doAddRoom(Room* room); - void updateRoom(Room* room, Room* prev); - void deleteRoom(Room* room); - void refresh(SpectralRoom* room, const QVector& roles = {}); - void refreshNotificationCount(); +private slots: + void doAddRoom(Room *room); + void updateRoom(Room *room, Room *prev); + void deleteRoom(Room *room); + void refresh(SpectralRoom *room, const QVector &roles = {}); + void refreshNotificationCount(); - private: - Connection* m_connection = nullptr; - QList m_rooms; +private: + Connection *m_connection = nullptr; + QList m_rooms; - int m_notificationCount = 0; + int m_notificationCount = 0; - void connectRoomSignals(SpectralRoom* room); + void connectRoomSignals(SpectralRoom *room); - signals: - void connectionChanged(); - void notificationCountChanged(); +signals: + void connectionChanged(); + void notificationCountChanged(); - void roomAdded(SpectralRoom* room); - void newMessage(const QString& roomId, - const QString& eventId, - const QString& roomName, - const QString& senderName, - const QString& text, - const QImage& icon); - void newHighlight(const QString& roomId, - const QString& eventId, - const QString& roomName, - const QString& senderName, - const QString& text, - const QImage& icon); + void roomAdded(SpectralRoom *room); + void newMessage(const QString &roomId, const QString &eventId, const QString &roomName, const QString &senderName, const QString &text, const QImage &icon); + void newHighlight(const QString &roomId, const QString &eventId, const QString &roomName, const QString &senderName, const QString &text, const QImage &icon); }; -#endif // ROOMLISTMODEL_H +#endif // ROOMLISTMODEL_H diff --git a/src/spectralroom.cpp b/src/spectralroom.cpp index 3c8f5847d..025c98125 100644 --- a/src/spectralroom.cpp +++ b/src/spectralroom.cpp @@ -19,475 +19,441 @@ #include "csapi/typing.h" #include "events/accountdataevents.h" #include "events/reactionevent.h" -#include "events/roommessageevent.h" -#include "events/typingevent.h" -#include "events/roompowerlevelsevent.h" #include "events/roomcanonicalaliasevent.h" +#include "events/roommessageevent.h" +#include "events/roompowerlevelsevent.h" +#include "events/typingevent.h" #include "jobs/downloadfilejob.h" #include "user.h" #include "utils.h" -SpectralRoom::SpectralRoom(Connection* connection, - QString roomId, - JoinState joinState) - : Room(connection, std::move(roomId), joinState) { - connect(this, &SpectralRoom::notificationCountChanged, this, - &SpectralRoom::countChanged); - connect(this, &SpectralRoom::highlightCountChanged, this, - &SpectralRoom::countChanged); - connect(this, &Room::fileTransferCompleted, this, [=] { - setFileUploadingProgress(0); - setHasFileUploading(false); - }); -} - -void SpectralRoom::uploadFile(const QUrl& url, const QString& body) { - if (url.isEmpty()) - return; - - QString txnId = postFile(body.isEmpty() ? url.fileName() : body, url, false); - setHasFileUploading(true); - connect(this, &Room::fileTransferCompleted, - [=](QString id, QUrl /*localFile*/, QUrl /*mxcUrl*/) { - if (id == txnId) { - setFileUploadingProgress(0); - setHasFileUploading(false); - } - }); - connect(this, &Room::fileTransferFailed, [=](QString id, QString /*error*/) { - if (id == txnId) { - setFileUploadingProgress(0); - setHasFileUploading(false); - } - }); - connect( - this, &Room::fileTransferProgress, - [=](QString id, qint64 progress, qint64 total) { - if (id == txnId) { - qDebug() << "Progress:" << progress << total; - setFileUploadingProgress(int(float(progress) / float(total) * 100)); - } - }); -} - -void SpectralRoom::acceptInvitation() { - connection()->joinRoom(id()); -} - -void SpectralRoom::forget() { - connection()->forgetRoom(id()); -} - -QVariantList SpectralRoom::getUsersTyping() const { - auto users = usersTyping(); - users.removeAll(localUser()); - QVariantList userVariants; - for (User* user : users) { - userVariants.append(QVariant::fromValue(user)); - } - return userVariants; -} - -void SpectralRoom::sendTypingNotification(bool isTyping) { - connection()->callApi(BackgroundRequest, localUser()->id(), - id(), isTyping, 10000); -} - -QString SpectralRoom::lastEvent() const { - for (auto i = messageEvents().rbegin(); i < messageEvents().rend(); i++) { - const RoomEvent* evt = i->get(); - - if (is(*evt) || is(*evt)) - continue; - if (evt->isRedacted()) - continue; - - if (evt->isStateEvent() && - static_cast(*evt).repeatsState()) - continue; - - if (auto e = eventCast(evt)) { - if (!e->replacedEvent().isEmpty() && e->replacedEvent() != e->id()) { - continue; - } - } - - if (connection()->isIgnored(user(evt->senderId()))) - continue; - - return user(evt->senderId())->displayname() + - (evt->isStateEvent() ? " " : ": ") + eventToString(*evt); - } - return ""; -} - -bool SpectralRoom::isEventHighlighted(const RoomEvent* e) const { - return highlights.contains(e); -} - -void SpectralRoom::checkForHighlights(const Quotient::TimelineItem& ti) { - auto localUserId = localUser()->id(); - if (ti->senderId() == localUserId) - return; - if (auto* e = ti.viewAs()) { - const auto& text = e->plainBody(); - if (text.contains(localUserId) || - text.contains(roomMembername(localUserId))) - highlights.insert(e); - } -} - -void SpectralRoom::onAddNewTimelineEvents(timeline_iter_t from) { - std::for_each(from, messageEvents().cend(), - [this](const TimelineItem& ti) { checkForHighlights(ti); }); -} - -void SpectralRoom::onAddHistoricalTimelineEvents(rev_iter_t from) { - std::for_each(from, messageEvents().crend(), - [this](const TimelineItem& ti) { checkForHighlights(ti); }); -} - -void SpectralRoom::onRedaction(const RoomEvent& prevEvent, - const RoomEvent& /*after*/) { - if (const auto& e = eventCast(&prevEvent)) { - if (auto relatedEventId = e->relation().eventId; - !relatedEventId.isEmpty()) { - emit updatedEvent(relatedEventId); - } - } -} - -void SpectralRoom::countChanged() { - if (displayed() && !hasUnreadMessages()) { - resetNotificationCount(); - resetHighlightCount(); - } -} - -QDateTime SpectralRoom::lastActiveTime() const { - if (timelineSize() == 0) - return QDateTime(); - return messageEvents().rbegin()->get()->originTimestamp(); -} - -int SpectralRoom::savedTopVisibleIndex() const { - return firstDisplayedMarker() == timelineEdge() - ? 0 - : int(firstDisplayedMarker() - messageEvents().rbegin()); -} - -int SpectralRoom::savedBottomVisibleIndex() const { - return lastDisplayedMarker() == timelineEdge() - ? 0 - : int(lastDisplayedMarker() - messageEvents().rbegin()); -} - -void SpectralRoom::saveViewport(int topIndex, int bottomIndex) { - if (topIndex == -1 || bottomIndex == -1 || - (bottomIndex == savedBottomVisibleIndex() && - (bottomIndex == 0 || topIndex == savedTopVisibleIndex()))) - return; - if (bottomIndex == 0) { - setFirstDisplayedEventId({}); - setLastDisplayedEventId({}); - return; - } - setFirstDisplayedEvent(maxTimelineIndex() - topIndex); - setLastDisplayedEvent(maxTimelineIndex() - bottomIndex); -} - -QVariantList SpectralRoom::getUsers(const QString& keyword) const { - const auto userList = users(); - QVariantList matchedList; - for (const auto u : userList) - if (u->displayname(this).contains(keyword, Qt::CaseInsensitive)) { - matchedList.append(QVariant::fromValue(u)); - } - - return matchedList; -} - -QUrl SpectralRoom::urlToMxcUrl(QUrl mxcUrl) { - return DownloadFileJob::makeRequestUrl(connection()->homeserver(), mxcUrl); -} - -QString SpectralRoom::avatarMediaId() const { - if (const auto avatar = Room::avatarMediaId(); !avatar.isEmpty()) { - return avatar; - } - - // Use the first (excluding self) user's avatar for direct chats - const auto dcUsers = directChatUsers(); - for (const auto u : dcUsers) { - if (u != localUser()) { - return u->avatarMediaId(); - } - } - - return {}; -} - -QString SpectralRoom::eventToString(const RoomEvent& evt, - Qt::TextFormat format, - bool removeReply) const { - const bool prettyPrint = (format == Qt::RichText); - - using namespace Quotient; - return visit( - evt, - [prettyPrint, removeReply](const RoomMessageEvent& e) { - using namespace MessageEventContent; - - // 1. prettyPrint/HTML - if (prettyPrint && e.hasTextContent() && - e.mimeType().name() != "text/plain") { - auto htmlBody = static_cast(e.content())->body; - if (removeReply) { - htmlBody.remove(utils::removeRichReplyRegex); - } - htmlBody.replace(utils::userPillRegExp, "\\1"); - htmlBody.replace(utils::strikethroughRegExp, "\\1"); - - return htmlBody; - } - - if (e.hasFileContent()) { - auto fileCaption = - e.content()->fileInfo()->originalName.toHtmlEscaped(); - if (fileCaption.isEmpty()) { - fileCaption = prettyPrint ? Quotient::prettyPrint(e.plainBody()) - : e.plainBody(); - } else if (e.content()->fileInfo()->originalName != e.plainBody()) { - fileCaption = e.plainBody() + " | " + fileCaption; - } - return !fileCaption.isEmpty() ? fileCaption : tr("a file"); - } - - // 2. prettyPrint/text 3. plainText/HTML 4. plainText/text - QString plainBody; - if (e.hasTextContent() && e.content() && e.mimeType().name() == "text/plain") { // 2/4 - plainBody = static_cast(e.content())->body; - } else { // 3 - plainBody = e.plainBody(); - } - - if (prettyPrint) { - if (removeReply) { - plainBody.remove(utils::removeReplyRegex); - } - return Quotient::prettyPrint(plainBody); - } - if (removeReply) { - return plainBody.remove(utils::removeReplyRegex); - } - return plainBody; - }, - [this](const RoomMemberEvent& e) { - // FIXME: Rewind to the name that was at the time of this event - auto subjectName = this->user(e.userId())->displayname(); - // The below code assumes senderName output in AuthorRole - switch (e.membership()) { - case MembershipType::Invite: - if (e.repeatsState()) - return tr("reinvited %1 to the room").arg(subjectName); - case MembershipType::Join: { - if (e.repeatsState()) - return tr("joined the room (repeated)"); - if (!e.prevContent() || - e.membership() != e.prevContent()->membership) { - return e.membership() == MembershipType::Invite - ? tr("invited %1 to the room").arg(subjectName) - : tr("joined the room"); - } - QString text{}; - if (e.isRename()) { - if (e.displayName().isEmpty()) - text = tr("cleared their display name"); - else - text = tr("changed their display name to %1") - .arg(e.displayName().toHtmlEscaped()); - } - if (e.isAvatarUpdate()) { - if (!text.isEmpty()) - text += " and "; - if (e.avatarUrl().isEmpty()) - text += tr("cleared their avatar"); - else if (e.prevContent()->avatarUrl.isEmpty()) - text += tr("set an avatar"); - else - text += tr("updated their avatar"); - } - return text; - } - case MembershipType::Leave: - if (e.prevContent() && - e.prevContent()->membership == MembershipType::Invite) { - return (e.senderId() != e.userId()) - ? tr("withdrew %1's invitation").arg(subjectName) - : tr("rejected the invitation"); - } - - if (e.prevContent() && - e.prevContent()->membership == MembershipType::Ban) { - return (e.senderId() != e.userId()) - ? tr("unbanned %1").arg(subjectName) - : tr("self-unbanned"); - } - return (e.senderId() != e.userId()) - ? tr("has put %1 out of the room: %2") - .arg(subjectName, e.contentJson()["reason"_ls] - .toString() - .toHtmlEscaped()) - : tr("left the room"); - case MembershipType::Ban: - return (e.senderId() != e.userId()) - ? tr("banned %1 from the room: %2") - .arg(subjectName, e.contentJson()["reason"_ls] - .toString() - .toHtmlEscaped()) - : tr("self-banned from the room"); - case MembershipType::Knock: - return tr("knocked"); - default:; - } - return tr("made something unknown"); - }, - [](const RoomCanonicalAliasEvent& e) { - return (e.alias().isEmpty()) - ? tr("cleared the room main alias") - : tr("set the room main alias to: %1").arg(e.alias()); - }, - [](const RoomNameEvent& e) { - return (e.name().isEmpty()) ? tr("cleared the room name") - : tr("set the room name to: %1") - .arg(e.name().toHtmlEscaped()); - }, - [prettyPrint](const RoomTopicEvent& e) { - return (e.topic().isEmpty()) - ? tr("cleared the topic") - : tr("set the topic to: %1") - .arg(prettyPrint ? Quotient::prettyPrint(e.topic()) - : e.topic()); - }, - [](const RoomAvatarEvent&) { return tr("changed the room avatar"); }, - [](const EncryptionEvent&) { - return tr("activated End-to-End Encryption"); - }, - [](const RoomCreateEvent& e) { - return (e.isUpgrade() ? tr("upgraded the room to version %1") - : tr("created the room, version %1")) - .arg(e.version().isEmpty() ? "1" : e.version().toHtmlEscaped()); - }, - [](const StateEventBase& e) { - // A small hack for state events from TWIM bot - return e.stateKey() == "twim" - ? tr("updated the database", "TWIM bot updated the database") - : e.stateKey().isEmpty() - ? tr("updated %1 state", "%1 - Matrix event type") - .arg(e.matrixType()) - : tr("updated %1 state for %2", - "%1 - Matrix event type, %2 - state key") - .arg(e.matrixType(), - e.stateKey().toHtmlEscaped()); - }, - tr("Unknown event")); -} - -void SpectralRoom::changeAvatar(QUrl localFile) { - const auto job = connection()->uploadFile(localFile.toLocalFile()); - if (isJobRunning(job)) { - connect(job, &BaseJob::success, this, [this, job] { - connection()->callApi( - id(), "m.room.avatar", localUser()->id(), QJsonObject{{"url", job->contentUri()}}); +SpectralRoom::SpectralRoom(Connection *connection, QString roomId, JoinState joinState) + : Room(connection, std::move(roomId), joinState) +{ + connect(this, &SpectralRoom::notificationCountChanged, this, &SpectralRoom::countChanged); + connect(this, &SpectralRoom::highlightCountChanged, this, &SpectralRoom::countChanged); + connect(this, &Room::fileTransferCompleted, this, [=] { + setFileUploadingProgress(0); + setHasFileUploading(false); }); - } } -void SpectralRoom::addLocalAlias(const QString& alias) { - auto a = aliases(); - if (a.contains(alias)) - return; +void SpectralRoom::uploadFile(const QUrl &url, const QString &body) +{ + if (url.isEmpty()) + return; - a += alias; - - setLocalAliases(a); + QString txnId = postFile(body.isEmpty() ? url.fileName() : body, url, false); + setHasFileUploading(true); + connect(this, &Room::fileTransferCompleted, [=](QString id, QUrl /*localFile*/, QUrl /*mxcUrl*/) { + if (id == txnId) { + setFileUploadingProgress(0); + setHasFileUploading(false); + } + }); + connect(this, &Room::fileTransferFailed, [=](QString id, QString /*error*/) { + if (id == txnId) { + setFileUploadingProgress(0); + setHasFileUploading(false); + } + }); + connect(this, &Room::fileTransferProgress, [=](QString id, qint64 progress, qint64 total) { + if (id == txnId) { + qDebug() << "Progress:" << progress << total; + setFileUploadingProgress(int(float(progress) / float(total) * 100)); + } + }); } -void SpectralRoom::removeLocalAlias(const QString& alias) { - auto a = aliases(); - if (!a.contains(alias)) - return; - - a.removeAll(alias); - - setLocalAliases(a); +void SpectralRoom::acceptInvitation() +{ + connection()->joinRoom(id()); } -QString SpectralRoom::markdownToHTML(const QString& markdown) { - const auto str = markdown.toUtf8(); - char* tmp_buf = - cmark_markdown_to_html(str.constData(), str.size(), CMARK_OPT_DEFAULT); - - const std::string html(tmp_buf); - - free(tmp_buf); - - auto result = QString::fromStdString(html).trimmed(); - - result.replace("

", ""); - result.replace("

", ""); - - return result; +void SpectralRoom::forget() +{ + connection()->forgetRoom(id()); } -void SpectralRoom::postArbitaryMessage(const QString& text, - MessageEventType type, - const QString& replyEventId) { - const auto parsedHTML = markdownToHTML(text); - const bool isRichText = Qt::mightBeRichText(parsedHTML); - - if (isRichText) { // Markdown - postHtmlMessage(text, parsedHTML, type, replyEventId); - } else { // Plain text - postPlainMessage(text, type, replyEventId); - } +QVariantList SpectralRoom::getUsersTyping() const +{ + auto users = usersTyping(); + users.removeAll(localUser()); + QVariantList userVariants; + for (User *user : users) { + userVariants.append(QVariant::fromValue(user)); + } + return userVariants; } -QString msgTypeToString(MessageEventType msgType) { - switch (msgType) { +void SpectralRoom::sendTypingNotification(bool isTyping) +{ + connection()->callApi(BackgroundRequest, localUser()->id(), id(), isTyping, 10000); +} + +QString SpectralRoom::lastEvent() const +{ + for (auto i = messageEvents().rbegin(); i < messageEvents().rend(); i++) { + const RoomEvent *evt = i->get(); + + if (is(*evt) || is(*evt)) + continue; + if (evt->isRedacted()) + continue; + + if (evt->isStateEvent() && static_cast(*evt).repeatsState()) + continue; + + if (auto e = eventCast(evt)) { + if (!e->replacedEvent().isEmpty() && e->replacedEvent() != e->id()) { + continue; + } + } + + if (connection()->isIgnored(user(evt->senderId()))) + continue; + + return user(evt->senderId())->displayname() + (evt->isStateEvent() ? " " : ": ") + eventToString(*evt); + } + return ""; +} + +bool SpectralRoom::isEventHighlighted(const RoomEvent *e) const +{ + return highlights.contains(e); +} + +void SpectralRoom::checkForHighlights(const Quotient::TimelineItem &ti) +{ + auto localUserId = localUser()->id(); + if (ti->senderId() == localUserId) + return; + if (auto *e = ti.viewAs()) { + const auto &text = e->plainBody(); + if (text.contains(localUserId) || text.contains(roomMembername(localUserId))) + highlights.insert(e); + } +} + +void SpectralRoom::onAddNewTimelineEvents(timeline_iter_t from) +{ + std::for_each(from, messageEvents().cend(), [this](const TimelineItem &ti) { + checkForHighlights(ti); + }); +} + +void SpectralRoom::onAddHistoricalTimelineEvents(rev_iter_t from) +{ + std::for_each(from, messageEvents().crend(), [this](const TimelineItem &ti) { + checkForHighlights(ti); + }); +} + +void SpectralRoom::onRedaction(const RoomEvent &prevEvent, const RoomEvent & /*after*/) +{ + if (const auto &e = eventCast(&prevEvent)) { + if (auto relatedEventId = e->relation().eventId; !relatedEventId.isEmpty()) { + emit updatedEvent(relatedEventId); + } + } +} + +void SpectralRoom::countChanged() +{ + if (displayed() && !hasUnreadMessages()) { + resetNotificationCount(); + resetHighlightCount(); + } +} + +QDateTime SpectralRoom::lastActiveTime() const +{ + if (timelineSize() == 0) + return QDateTime(); + return messageEvents().rbegin()->get()->originTimestamp(); +} + +int SpectralRoom::savedTopVisibleIndex() const +{ + return firstDisplayedMarker() == timelineEdge() ? 0 : int(firstDisplayedMarker() - messageEvents().rbegin()); +} + +int SpectralRoom::savedBottomVisibleIndex() const +{ + return lastDisplayedMarker() == timelineEdge() ? 0 : int(lastDisplayedMarker() - messageEvents().rbegin()); +} + +void SpectralRoom::saveViewport(int topIndex, int bottomIndex) +{ + if (topIndex == -1 || bottomIndex == -1 || (bottomIndex == savedBottomVisibleIndex() && (bottomIndex == 0 || topIndex == savedTopVisibleIndex()))) + return; + if (bottomIndex == 0) { + setFirstDisplayedEventId({}); + setLastDisplayedEventId({}); + return; + } + setFirstDisplayedEvent(maxTimelineIndex() - topIndex); + setLastDisplayedEvent(maxTimelineIndex() - bottomIndex); +} + +QVariantList SpectralRoom::getUsers(const QString &keyword) const +{ + const auto userList = users(); + QVariantList matchedList; + for (const auto u : userList) + if (u->displayname(this).contains(keyword, Qt::CaseInsensitive)) { + matchedList.append(QVariant::fromValue(u)); + } + + return matchedList; +} + +QUrl SpectralRoom::urlToMxcUrl(QUrl mxcUrl) +{ + return DownloadFileJob::makeRequestUrl(connection()->homeserver(), mxcUrl); +} + +QString SpectralRoom::avatarMediaId() const +{ + if (const auto avatar = Room::avatarMediaId(); !avatar.isEmpty()) { + return avatar; + } + + // Use the first (excluding self) user's avatar for direct chats + const auto dcUsers = directChatUsers(); + for (const auto u : dcUsers) { + if (u != localUser()) { + return u->avatarMediaId(); + } + } + + return {}; +} + +QString SpectralRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format, bool removeReply) const +{ + const bool prettyPrint = (format == Qt::RichText); + + using namespace Quotient; + return visit( + evt, + [prettyPrint, removeReply](const RoomMessageEvent &e) { + using namespace MessageEventContent; + + // 1. prettyPrint/HTML + if (prettyPrint && e.hasTextContent() && e.mimeType().name() != "text/plain") { + auto htmlBody = static_cast(e.content())->body; + if (removeReply) { + htmlBody.remove(utils::removeRichReplyRegex); + } + htmlBody.replace(utils::userPillRegExp, "\\1"); + htmlBody.replace(utils::strikethroughRegExp, "\\1"); + + return htmlBody; + } + + if (e.hasFileContent()) { + auto fileCaption = e.content()->fileInfo()->originalName.toHtmlEscaped(); + if (fileCaption.isEmpty()) { + fileCaption = prettyPrint ? Quotient::prettyPrint(e.plainBody()) : e.plainBody(); + } else if (e.content()->fileInfo()->originalName != e.plainBody()) { + fileCaption = e.plainBody() + " | " + fileCaption; + } + return !fileCaption.isEmpty() ? fileCaption : tr("a file"); + } + + // 2. prettyPrint/text 3. plainText/HTML 4. plainText/text + QString plainBody; + if (e.hasTextContent() && e.content() && e.mimeType().name() == "text/plain") { // 2/4 + plainBody = static_cast(e.content())->body; + } else { // 3 + plainBody = e.plainBody(); + } + + if (prettyPrint) { + if (removeReply) { + plainBody.remove(utils::removeReplyRegex); + } + return Quotient::prettyPrint(plainBody); + } + if (removeReply) { + return plainBody.remove(utils::removeReplyRegex); + } + return plainBody; + }, + [this](const RoomMemberEvent &e) { + // FIXME: Rewind to the name that was at the time of this event + auto subjectName = this->user(e.userId())->displayname(); + // The below code assumes senderName output in AuthorRole + switch (e.membership()) { + case MembershipType::Invite: + if (e.repeatsState()) + return tr("reinvited %1 to the room").arg(subjectName); + case MembershipType::Join: { + if (e.repeatsState()) + return tr("joined the room (repeated)"); + if (!e.prevContent() || e.membership() != e.prevContent()->membership) { + return e.membership() == MembershipType::Invite ? tr("invited %1 to the room").arg(subjectName) : tr("joined the room"); + } + QString text {}; + if (e.isRename()) { + if (e.displayName().isEmpty()) + text = tr("cleared their display name"); + else + text = tr("changed their display name to %1").arg(e.displayName().toHtmlEscaped()); + } + if (e.isAvatarUpdate()) { + if (!text.isEmpty()) + text += " and "; + if (e.avatarUrl().isEmpty()) + text += tr("cleared their avatar"); + else if (e.prevContent()->avatarUrl.isEmpty()) + text += tr("set an avatar"); + else + text += tr("updated their avatar"); + } + return text; + } + case MembershipType::Leave: + if (e.prevContent() && e.prevContent()->membership == MembershipType::Invite) { + return (e.senderId() != e.userId()) ? tr("withdrew %1's invitation").arg(subjectName) : tr("rejected the invitation"); + } + + if (e.prevContent() && e.prevContent()->membership == MembershipType::Ban) { + return (e.senderId() != e.userId()) ? tr("unbanned %1").arg(subjectName) : tr("self-unbanned"); + } + return (e.senderId() != e.userId()) ? tr("has put %1 out of the room: %2").arg(subjectName, e.contentJson()["reason"_ls].toString().toHtmlEscaped()) : tr("left the room"); + case MembershipType::Ban: + return (e.senderId() != e.userId()) ? tr("banned %1 from the room: %2").arg(subjectName, e.contentJson()["reason"_ls].toString().toHtmlEscaped()) : tr("self-banned from the room"); + case MembershipType::Knock: + return tr("knocked"); + default:; + } + return tr("made something unknown"); + }, + [](const RoomCanonicalAliasEvent &e) { + return (e.alias().isEmpty()) ? tr("cleared the room main alias") : tr("set the room main alias to: %1").arg(e.alias()); + }, + [](const RoomNameEvent &e) { + return (e.name().isEmpty()) ? tr("cleared the room name") : tr("set the room name to: %1").arg(e.name().toHtmlEscaped()); + }, + [prettyPrint](const RoomTopicEvent &e) { + return (e.topic().isEmpty()) ? tr("cleared the topic") : tr("set the topic to: %1").arg(prettyPrint ? Quotient::prettyPrint(e.topic()) : e.topic()); + }, + [](const RoomAvatarEvent &) { + return tr("changed the room avatar"); + }, + [](const EncryptionEvent &) { + return tr("activated End-to-End Encryption"); + }, + [](const RoomCreateEvent &e) { + return (e.isUpgrade() ? tr("upgraded the room to version %1") : tr("created the room, version %1")).arg(e.version().isEmpty() ? "1" : e.version().toHtmlEscaped()); + }, + [](const StateEventBase &e) { + // A small hack for state events from TWIM bot + return e.stateKey() == "twim" + ? tr("updated the database", "TWIM bot updated the database") + : e.stateKey().isEmpty() ? tr("updated %1 state", "%1 - Matrix event type").arg(e.matrixType()) : tr("updated %1 state for %2", "%1 - Matrix event type, %2 - state key").arg(e.matrixType(), e.stateKey().toHtmlEscaped()); + }, + tr("Unknown event")); +} + +void SpectralRoom::changeAvatar(QUrl localFile) +{ + const auto job = connection()->uploadFile(localFile.toLocalFile()); + if (isJobRunning(job)) { + connect(job, &BaseJob::success, this, [this, job] { + connection()->callApi(id(), "m.room.avatar", localUser()->id(), QJsonObject {{"url", job->contentUri()}}); + }); + } +} + +void SpectralRoom::addLocalAlias(const QString &alias) +{ + auto a = aliases(); + if (a.contains(alias)) + return; + + a += alias; + + setLocalAliases(a); +} + +void SpectralRoom::removeLocalAlias(const QString &alias) +{ + auto a = aliases(); + if (!a.contains(alias)) + return; + + a.removeAll(alias); + + setLocalAliases(a); +} + +QString SpectralRoom::markdownToHTML(const QString &markdown) +{ + const auto str = markdown.toUtf8(); + char *tmp_buf = cmark_markdown_to_html(str.constData(), str.size(), CMARK_OPT_DEFAULT); + + const std::string html(tmp_buf); + + free(tmp_buf); + + auto result = QString::fromStdString(html).trimmed(); + + result.replace("

", ""); + result.replace("

", ""); + + return result; +} + +void SpectralRoom::postArbitaryMessage(const QString &text, MessageEventType type, const QString &replyEventId) +{ + const auto parsedHTML = markdownToHTML(text); + const bool isRichText = Qt::mightBeRichText(parsedHTML); + + if (isRichText) { // Markdown + postHtmlMessage(text, parsedHTML, type, replyEventId); + } else { // Plain text + postPlainMessage(text, type, replyEventId); + } +} + +QString msgTypeToString(MessageEventType msgType) +{ + switch (msgType) { case MessageEventType::Text: - return "m.text"; + return "m.text"; case MessageEventType::File: - return "m.file"; + return "m.file"; case MessageEventType::Audio: - return "m.audio"; + return "m.audio"; case MessageEventType::Emote: - return "m.emote"; + return "m.emote"; case MessageEventType::Image: - return "m.image"; + return "m.image"; case MessageEventType::Video: - return "m.video"; + return "m.video"; case MessageEventType::Notice: - return "m.notice"; + return "m.notice"; case MessageEventType::Location: - return "m.location"; + return "m.location"; default: - return "m.text"; - } + return "m.text"; + } } -void SpectralRoom::postPlainMessage(const QString& text, - MessageEventType type, - const QString& replyEventId) { - bool isReply = !replyEventId.isEmpty(); - const auto replyIt = findInTimeline(replyEventId); - if (replyIt == timelineEdge()) - isReply = false; +void SpectralRoom::postPlainMessage(const QString &text, MessageEventType type, const QString &replyEventId) +{ + bool isReply = !replyEventId.isEmpty(); + const auto replyIt = findInTimeline(replyEventId); + if (replyIt == timelineEdge()) + isReply = false; - if (isReply) { - const auto& replyEvt = **replyIt; + if (isReply) { + const auto &replyEvt = **replyIt; - // clang-format off + // clang-format off QJsonObject json{ {"msgtype", msgTypeToString(type)}, {"body", "> <" + replyEvt.senderId() + "> " + eventToString(replyEvt) + "\n\n" + text}, @@ -511,29 +477,27 @@ void SpectralRoom::postPlainMessage(const QString& text, "" + text } }; - // clang-format on + // clang-format on - postJson("m.room.message", json); + postJson("m.room.message", json); - return; - } + return; + } - Room::postMessage(text, type); + Room::postMessage(text, type); } -void SpectralRoom::postHtmlMessage(const QString& text, - const QString& html, - MessageEventType type, - const QString& replyEventId) { - bool isReply = !replyEventId.isEmpty(); - const auto replyIt = findInTimeline(replyEventId); - if (replyIt == timelineEdge()) - isReply = false; +void SpectralRoom::postHtmlMessage(const QString &text, const QString &html, MessageEventType type, const QString &replyEventId) +{ + bool isReply = !replyEventId.isEmpty(); + const auto replyIt = findInTimeline(replyEventId); + if (replyIt == timelineEdge()) + isReply = false; - if (isReply) { - const auto& replyEvt = **replyIt; + if (isReply) { + const auto &replyEvt = **replyIt; - // clang-format off + // clang-format off QJsonObject json{ {"msgtype", msgTypeToString(type)}, {"body", "> <" + replyEvt.senderId() + "> " + eventToString(replyEvt) + "\n\n" + text}, @@ -557,74 +521,77 @@ void SpectralRoom::postHtmlMessage(const QString& text, "" + html } }; - // clang-format on + // clang-format on - postJson("m.room.message", json); + postJson("m.room.message", json); - return; - } + return; + } - Room::postHtmlMessage(text, html, type); + Room::postHtmlMessage(text, html, type); } -void SpectralRoom::toggleReaction(const QString& eventId, - const QString& reaction) { - if (eventId.isEmpty() || reaction.isEmpty()) - return; +void SpectralRoom::toggleReaction(const QString &eventId, const QString &reaction) +{ + if (eventId.isEmpty() || reaction.isEmpty()) + return; - const auto eventIt = findInTimeline(eventId); - if (eventIt == timelineEdge()) - return; + const auto eventIt = findInTimeline(eventId); + if (eventIt == timelineEdge()) + return; - const auto& evt = **eventIt; + const auto &evt = **eventIt; - QStringList redactEventIds; // What if there are multiple reaction events? + QStringList redactEventIds; // What if there are multiple reaction events? - const auto& annotations = relatedEvents(evt, EventRelation::Annotation()); - if (!annotations.isEmpty()) { - for (const auto& a : annotations) { - if (auto e = eventCast(a)) { - if (e->relation().key != reaction) - continue; + const auto &annotations = relatedEvents(evt, EventRelation::Annotation()); + if (!annotations.isEmpty()) { + for (const auto &a : annotations) { + if (auto e = eventCast(a)) { + if (e->relation().key != reaction) + continue; - if (e->senderId() == localUser()->id()) { - redactEventIds.push_back(e->id()); - break; + if (e->senderId() == localUser()->id()) { + redactEventIds.push_back(e->id()); + break; + } + } } - } } - } - if (!redactEventIds.isEmpty()) { - for (const auto& redactEventId : redactEventIds) { - redactEvent(redactEventId); + if (!redactEventIds.isEmpty()) { + for (const auto &redactEventId : redactEventIds) { + redactEvent(redactEventId); + } + } else { + postReaction(eventId, reaction); } - } else { - postReaction(eventId, reaction); - } } -bool SpectralRoom::containsUser(QString userID) const { - auto u = Room::user(userID); +bool SpectralRoom::containsUser(QString userID) const +{ + auto u = Room::user(userID); - if (!u) - return false; + if (!u) + return false; - return Room::memberJoinState(u) != JoinState::Leave; + return Room::memberJoinState(u) != JoinState::Leave; } -bool SpectralRoom::canSendEvent(const QString& eventType) const { - auto plEvent = getCurrentState(); - auto pl = plEvent->powerLevelForEvent(eventType); - auto currentPl = plEvent->powerLevelForUser(localUser()->id()); +bool SpectralRoom::canSendEvent(const QString &eventType) const +{ + auto plEvent = getCurrentState(); + auto pl = plEvent->powerLevelForEvent(eventType); + auto currentPl = plEvent->powerLevelForUser(localUser()->id()); - return currentPl >= pl; + return currentPl >= pl; } -bool SpectralRoom::canSendState(const QString& eventType) const { - auto plEvent = getCurrentState(); - auto pl = plEvent->powerLevelForState(eventType); - auto currentPl = plEvent->powerLevelForUser(localUser()->id()); +bool SpectralRoom::canSendState(const QString &eventType) const +{ + auto plEvent = getCurrentState(); + auto pl = plEvent->powerLevelForState(eventType); + auto currentPl = plEvent->powerLevelForUser(localUser()->id()); - return currentPl >= pl; + return currentPl >= pl; } diff --git a/src/spectralroom.h b/src/spectralroom.h index 308673502..af63afdfc 100644 --- a/src/spectralroom.h +++ b/src/spectralroom.h @@ -18,110 +18,105 @@ using namespace Quotient; -class SpectralRoom : public Room { - Q_OBJECT - Q_PROPERTY(QVariantList usersTyping READ getUsersTyping NOTIFY typingChanged) - Q_PROPERTY(QString cachedInput MEMBER m_cachedInput NOTIFY cachedInputChanged) - Q_PROPERTY(bool hasFileUploading READ hasFileUploading WRITE - setHasFileUploading NOTIFY hasFileUploadingChanged) - Q_PROPERTY(int fileUploadingProgress READ fileUploadingProgress NOTIFY - fileUploadingProgressChanged) - Q_PROPERTY(QString avatarMediaId READ avatarMediaId NOTIFY avatarChanged - STORED false) +class SpectralRoom : public Room +{ + Q_OBJECT + Q_PROPERTY(QVariantList usersTyping READ getUsersTyping NOTIFY typingChanged) + Q_PROPERTY(QString cachedInput MEMBER m_cachedInput NOTIFY cachedInputChanged) + Q_PROPERTY(bool hasFileUploading READ hasFileUploading WRITE setHasFileUploading NOTIFY hasFileUploadingChanged) + Q_PROPERTY(int fileUploadingProgress READ fileUploadingProgress NOTIFY fileUploadingProgressChanged) + Q_PROPERTY(QString avatarMediaId READ avatarMediaId NOTIFY avatarChanged STORED false) - public: - explicit SpectralRoom(Connection* connection, - QString roomId, - JoinState joinState = {}); +public: + explicit SpectralRoom(Connection *connection, QString roomId, JoinState joinState = {}); - QVariantList getUsersTyping() const; + QVariantList getUsersTyping() const; - QString lastEvent() const; - bool isEventHighlighted(const Quotient::RoomEvent* e) const; + QString lastEvent() const; + bool isEventHighlighted(const Quotient::RoomEvent *e) const; - QDateTime lastActiveTime() const; + QDateTime lastActiveTime() const; - bool hasFileUploading() const { return m_hasFileUploading; } - void setHasFileUploading(bool value) { - if (value == m_hasFileUploading) { - return; + bool hasFileUploading() const + { + return m_hasFileUploading; } - m_hasFileUploading = value; - emit hasFileUploadingChanged(); - } - - int fileUploadingProgress() const { return m_fileUploadingProgress; } - void setFileUploadingProgress(int value) { - if (m_fileUploadingProgress == value) { - return; + void setHasFileUploading(bool value) + { + if (value == m_hasFileUploading) { + return; + } + m_hasFileUploading = value; + emit hasFileUploadingChanged(); } - m_fileUploadingProgress = value; - emit fileUploadingProgressChanged(); - } - Q_INVOKABLE int savedTopVisibleIndex() const; - Q_INVOKABLE int savedBottomVisibleIndex() const; - Q_INVOKABLE void saveViewport(int topIndex, int bottomIndex); + int fileUploadingProgress() const + { + return m_fileUploadingProgress; + } + void setFileUploadingProgress(int value) + { + if (m_fileUploadingProgress == value) { + return; + } + m_fileUploadingProgress = value; + emit fileUploadingProgressChanged(); + } - Q_INVOKABLE QVariantList getUsers(const QString& keyword) const; + Q_INVOKABLE int savedTopVisibleIndex() const; + Q_INVOKABLE int savedBottomVisibleIndex() const; + Q_INVOKABLE void saveViewport(int topIndex, int bottomIndex); - Q_INVOKABLE QUrl urlToMxcUrl(QUrl mxcUrl); + Q_INVOKABLE QVariantList getUsers(const QString &keyword) const; - QString avatarMediaId() const; + Q_INVOKABLE QUrl urlToMxcUrl(QUrl mxcUrl); - QString eventToString(const RoomEvent& evt, - Qt::TextFormat format = Qt::PlainText, - bool removeReply = true) const; + QString avatarMediaId() const; - Q_INVOKABLE bool containsUser(QString userID) const; + QString eventToString(const RoomEvent &evt, Qt::TextFormat format = Qt::PlainText, bool removeReply = true) const; - Q_INVOKABLE bool canSendEvent(const QString& eventType) const; - Q_INVOKABLE bool canSendState(const QString& eventType) const; + Q_INVOKABLE bool containsUser(QString userID) const; - private: - QString m_cachedInput; - QSet highlights; + Q_INVOKABLE bool canSendEvent(const QString &eventType) const; + Q_INVOKABLE bool canSendState(const QString &eventType) const; - bool m_hasFileUploading = false; - int m_fileUploadingProgress = 0; +private: + QString m_cachedInput; + QSet highlights; - void checkForHighlights(const Quotient::TimelineItem& ti); + bool m_hasFileUploading = false; + int m_fileUploadingProgress = 0; - void onAddNewTimelineEvents(timeline_iter_t from) override; - void onAddHistoricalTimelineEvents(rev_iter_t from) override; - void onRedaction(const RoomEvent& prevEvent, const RoomEvent& after) override; + void checkForHighlights(const Quotient::TimelineItem &ti); - static QString markdownToHTML(const QString& plaintext); + void onAddNewTimelineEvents(timeline_iter_t from) override; + void onAddHistoricalTimelineEvents(rev_iter_t from) override; + void onRedaction(const RoomEvent &prevEvent, const RoomEvent &after) override; - private slots: - void countChanged(); + static QString markdownToHTML(const QString &plaintext); - signals: - void cachedInputChanged(); - void busyChanged(); - void hasFileUploadingChanged(); - void fileUploadingProgressChanged(); - void backgroundChanged(); +private slots: + void countChanged(); - public slots: - void uploadFile(const QUrl& url, const QString& body = ""); - void acceptInvitation(); - void forget(); - void sendTypingNotification(bool isTyping); - void postArbitaryMessage(const QString& text, - MessageEventType type = MessageEventType::Text, - const QString& replyEventId = ""); - void postPlainMessage(const QString& text, - MessageEventType type = MessageEventType::Text, - const QString& replyEventId = ""); - void postHtmlMessage(const QString& text, - const QString& html, - MessageEventType type = MessageEventType::Text, - const QString& replyEventId = ""); - void changeAvatar(QUrl localFile); - void addLocalAlias(const QString& alias); - void removeLocalAlias(const QString& alias); - void toggleReaction(const QString& eventId, const QString& reaction); +signals: + void cachedInputChanged(); + void busyChanged(); + void hasFileUploadingChanged(); + void fileUploadingProgressChanged(); + void backgroundChanged(); + +public slots: + void uploadFile(const QUrl &url, const QString &body = ""); + void acceptInvitation(); + void forget(); + void sendTypingNotification(bool isTyping); + void postArbitaryMessage(const QString &text, MessageEventType type = MessageEventType::Text, const QString &replyEventId = ""); + void postPlainMessage(const QString &text, MessageEventType type = MessageEventType::Text, const QString &replyEventId = ""); + void postHtmlMessage(const QString &text, const QString &html, MessageEventType type = MessageEventType::Text, const QString &replyEventId = ""); + void changeAvatar(QUrl localFile); + void addLocalAlias(const QString &alias); + void removeLocalAlias(const QString &alias); + void toggleReaction(const QString &eventId, const QString &reaction); }; -#endif // SpectralRoom_H +#endif // SpectralRoom_H diff --git a/src/spectraluser.cpp b/src/spectraluser.cpp index 613aebf1b..d3d620aa5 100644 --- a/src/spectraluser.cpp +++ b/src/spectraluser.cpp @@ -1,5 +1,6 @@ #include "spectraluser.h" -QColor SpectralUser::color() { - return QColor::fromHslF(hueF(), 0.7, 0.5, 1); +QColor SpectralUser::color() +{ + return QColor::fromHslF(hueF(), 0.7, 0.5, 1); } diff --git a/src/spectraluser.h b/src/spectraluser.h index 93dec4bdc..fbee36c93 100644 --- a/src/spectraluser.h +++ b/src/spectraluser.h @@ -8,14 +8,17 @@ using namespace Quotient; -class SpectralUser : public User { - Q_OBJECT - Q_PROPERTY(QColor color READ color CONSTANT) - public: - SpectralUser(QString userId, Connection* connection) - : User(userId, connection) {} +class SpectralUser : public User +{ + Q_OBJECT + Q_PROPERTY(QColor color READ color CONSTANT) +public: + SpectralUser(QString userId, Connection *connection) + : User(userId, connection) + { + } - QColor color(); + QColor color(); }; -#endif // SpectralUser_H +#endif // SpectralUser_H diff --git a/src/trayicon.cpp b/src/trayicon.cpp index 33576f1f6..d7b1c1f59 100644 --- a/src/trayicon.cpp +++ b/src/trayicon.cpp @@ -12,168 +12,168 @@ #include #endif -MsgCountComposedIcon::MsgCountComposedIcon(const QString& filename) - : QIconEngine() { - icon_ = QIcon(filename); +MsgCountComposedIcon::MsgCountComposedIcon(const QString &filename) + : QIconEngine() +{ + icon_ = QIcon(filename); } -void MsgCountComposedIcon::paint(QPainter* painter, - const QRect& rect, - QIcon::Mode mode, - QIcon::State state) { - painter->setRenderHint(QPainter::TextAntialiasing); - painter->setRenderHint(QPainter::SmoothPixmapTransform); - painter->setRenderHint(QPainter::Antialiasing); +void MsgCountComposedIcon::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) +{ + painter->setRenderHint(QPainter::TextAntialiasing); + painter->setRenderHint(QPainter::SmoothPixmapTransform); + painter->setRenderHint(QPainter::Antialiasing); - icon_.paint(painter, rect, Qt::AlignCenter, mode, state); + icon_.paint(painter, rect, Qt::AlignCenter, mode, state); - if (isOnline && msgCount <= 0) - return; + if (isOnline && msgCount <= 0) + return; - QColor backgroundColor("red"); - QColor textColor("white"); + QColor backgroundColor("red"); + QColor textColor("white"); - QBrush brush; - brush.setStyle(Qt::SolidPattern); - brush.setColor(backgroundColor); + QBrush brush; + brush.setStyle(Qt::SolidPattern); + brush.setColor(backgroundColor); - painter->setBrush(brush); - painter->setPen(Qt::NoPen); - painter->setFont(QFont("Open Sans", 8, QFont::Black)); + painter->setBrush(brush); + painter->setPen(Qt::NoPen); + painter->setFont(QFont("Open Sans", 8, QFont::Black)); - QRectF bubble(rect.width() - BubbleDiameter, rect.height() - BubbleDiameter, - BubbleDiameter, BubbleDiameter); - painter->drawEllipse(bubble); - painter->setPen(QPen(textColor)); - painter->setBrush(Qt::NoBrush); - if (!isOnline) { - painter->drawText(bubble, Qt::AlignCenter, "x"); - } else if (msgCount >= 100) { - painter->drawText(bubble, Qt::AlignCenter, "99+"); - } else { - painter->drawText(bubble, Qt::AlignCenter, QString::number(msgCount)); - } + QRectF bubble(rect.width() - BubbleDiameter, rect.height() - BubbleDiameter, BubbleDiameter, BubbleDiameter); + painter->drawEllipse(bubble); + painter->setPen(QPen(textColor)); + painter->setBrush(Qt::NoBrush); + if (!isOnline) { + painter->drawText(bubble, Qt::AlignCenter, "x"); + } else if (msgCount >= 100) { + painter->drawText(bubble, Qt::AlignCenter, "99+"); + } else { + painter->drawText(bubble, Qt::AlignCenter, QString::number(msgCount)); + } } -QIconEngine* MsgCountComposedIcon::clone() const { - return new MsgCountComposedIcon(*this); +QIconEngine *MsgCountComposedIcon::clone() const +{ + return new MsgCountComposedIcon(*this); } -QList MsgCountComposedIcon::availableSizes(QIcon::Mode mode, - QIcon::State state) const { - Q_UNUSED(mode) - Q_UNUSED(state) - QList sizes; - sizes.append(QSize(24, 24)); - sizes.append(QSize(32, 32)); - sizes.append(QSize(48, 48)); - sizes.append(QSize(64, 64)); - sizes.append(QSize(128, 128)); - sizes.append(QSize(256, 256)); - return sizes; +QList MsgCountComposedIcon::availableSizes(QIcon::Mode mode, QIcon::State state) const +{ + Q_UNUSED(mode) + Q_UNUSED(state) + QList sizes; + sizes.append(QSize(24, 24)); + sizes.append(QSize(32, 32)); + sizes.append(QSize(48, 48)); + sizes.append(QSize(64, 64)); + sizes.append(QSize(128, 128)); + sizes.append(QSize(256, 256)); + return sizes; } -QPixmap MsgCountComposedIcon::pixmap(const QSize& size, - QIcon::Mode mode, - QIcon::State state) { - QImage img(size, QImage::Format_ARGB32); - img.fill(qRgba(0, 0, 0, 0)); - QPixmap result = QPixmap::fromImage(img, Qt::NoFormatConversion); - { - QPainter painter(&result); - paint(&painter, QRect(QPoint(0, 0), size), mode, state); - } - return result; +QPixmap MsgCountComposedIcon::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) +{ + QImage img(size, QImage::Format_ARGB32); + img.fill(qRgba(0, 0, 0, 0)); + QPixmap result = QPixmap::fromImage(img, Qt::NoFormatConversion); + { + QPainter painter(&result); + paint(&painter, QRect(QPoint(0, 0), size), mode, state); + } + return result; } -TrayIcon::TrayIcon(QObject* parent) : QSystemTrayIcon(parent) { - QMenu* menu = new QMenu(); - viewAction_ = new QAction(tr("Show"), parent); - quitAction_ = new QAction(tr("Quit"), parent); +TrayIcon::TrayIcon(QObject *parent) + : QSystemTrayIcon(parent) +{ + QMenu *menu = new QMenu(); + viewAction_ = new QAction(tr("Show"), parent); + quitAction_ = new QAction(tr("Quit"), parent); - connect(viewAction_, &QAction::triggered, this, &TrayIcon::showWindow); - connect(quitAction_, &QAction::triggered, this, QApplication::quit); + connect(viewAction_, &QAction::triggered, this, &TrayIcon::showWindow); + connect(quitAction_, &QAction::triggered, this, QApplication::quit); - menu->addAction(viewAction_); - menu->addAction(quitAction_); + menu->addAction(viewAction_); + menu->addAction(quitAction_); - setContextMenu(menu); + setContextMenu(menu); } -void TrayIcon::setNotificationCount(int count) { - m_notificationCount = count; +void TrayIcon::setNotificationCount(int count) +{ + m_notificationCount = count; // Use the native badge counter in MacOS. #if defined(Q_OS_MAC) - auto labelText = count == 0 ? "" : QString::number(count); + auto labelText = count == 0 ? "" : QString::number(count); - if (labelText == QtMac::badgeLabelText()) - return; + if (labelText == QtMac::badgeLabelText()) + return; - QtMac::setBadgeLabelText(labelText); + QtMac::setBadgeLabelText(labelText); #elif defined(Q_OS_WIN) // FIXME: Find a way to use Windows apis for the badge counter (if any). #else - if (!icon_ || count == icon_->msgCount) - return; + if (!icon_ || count == icon_->msgCount) + return; - // Custom drawing on Linux. - MsgCountComposedIcon* tmp = - static_cast(icon_->clone()); - tmp->msgCount = count; + // Custom drawing on Linux. + MsgCountComposedIcon *tmp = static_cast(icon_->clone()); + tmp->msgCount = count; - setIcon(QIcon(tmp)); + setIcon(QIcon(tmp)); - icon_ = tmp; + icon_ = tmp; #endif - emit notificationCountChanged(); + emit notificationCountChanged(); } -void TrayIcon::setIsOnline(bool online) { - m_isOnline = online; +void TrayIcon::setIsOnline(bool online) +{ + m_isOnline = online; #if defined(Q_OS_MAC) - if (online) { - auto labelText = - m_notificationCount == 0 ? "" : QString::number(m_notificationCount); + if (online) { + auto labelText = m_notificationCount == 0 ? "" : QString::number(m_notificationCount); - if (labelText == QtMac::badgeLabelText()) - return; + if (labelText == QtMac::badgeLabelText()) + return; - QtMac::setBadgeLabelText(labelText); - } else { - auto labelText = "x"; + QtMac::setBadgeLabelText(labelText); + } else { + auto labelText = "x"; - if (labelText == QtMac::badgeLabelText()) - return; + if (labelText == QtMac::badgeLabelText()) + return; - QtMac::setBadgeLabelText(labelText); - } + QtMac::setBadgeLabelText(labelText); + } #elif defined(Q_OS_WIN) // FIXME: Find a way to use Windows apis for the badge counter (if any). #else - if (!icon_ || online == icon_->isOnline) - return; + if (!icon_ || online == icon_->isOnline) + return; - // Custom drawing on Linux. - MsgCountComposedIcon* tmp = - static_cast(icon_->clone()); - tmp->isOnline = online; + // Custom drawing on Linux. + MsgCountComposedIcon *tmp = static_cast(icon_->clone()); + tmp->isOnline = online; - setIcon(QIcon(tmp)); + setIcon(QIcon(tmp)); - icon_ = tmp; + icon_ = tmp; #endif - emit isOnlineChanged(); + emit isOnlineChanged(); } -void TrayIcon::setIconSource(const QString& source) { - m_iconSource = source; +void TrayIcon::setIconSource(const QString &source) +{ + m_iconSource = source; #if defined(Q_OS_MAC) || defined(Q_OS_WIN) - setIcon(QIcon(source)); + setIcon(QIcon(source)); #else - icon_ = new MsgCountComposedIcon(source); - setIcon(QIcon(icon_)); - icon_->isOnline = m_isOnline; - icon_->msgCount = m_notificationCount; + icon_ = new MsgCountComposedIcon(source); + setIcon(QIcon(icon_)); + icon_->isOnline = m_isOnline; + icon_->msgCount = m_notificationCount; #endif - emit iconSourceChanged(); + emit iconSourceChanged(); } diff --git a/src/trayicon.h b/src/trayicon.h index 4e4d8e98e..c6814b7cc 100644 --- a/src/trayicon.h +++ b/src/trayicon.h @@ -10,65 +10,68 @@ #include #include -class MsgCountComposedIcon : public QIconEngine { - public: - MsgCountComposedIcon(const QString& filename); +class MsgCountComposedIcon : public QIconEngine +{ +public: + MsgCountComposedIcon(const QString &filename); - virtual void paint(QPainter* p, - const QRect& rect, - QIcon::Mode mode, - QIcon::State state); - virtual QIconEngine* clone() const; - virtual QList availableSizes(QIcon::Mode mode, - QIcon::State state) const; - virtual QPixmap pixmap(const QSize& size, - QIcon::Mode mode, - QIcon::State state); + virtual void paint(QPainter *p, const QRect &rect, QIcon::Mode mode, QIcon::State state); + virtual QIconEngine *clone() const; + virtual QList availableSizes(QIcon::Mode mode, QIcon::State state) const; + virtual QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state); - int msgCount = 0; - bool isOnline = true; // Default to false? + int msgCount = 0; + bool isOnline = true; // Default to false? - private: - const int BubbleDiameter = 14; +private: + const int BubbleDiameter = 14; - QIcon icon_; + QIcon icon_; }; -class TrayIcon : public QSystemTrayIcon { - Q_OBJECT - Q_PROPERTY(QString iconSource READ iconSource WRITE setIconSource NOTIFY - iconSourceChanged) - Q_PROPERTY(int notificationCount READ notificationCount WRITE - setNotificationCount NOTIFY notificationCountChanged) +class TrayIcon : public QSystemTrayIcon +{ + Q_OBJECT + Q_PROPERTY(QString iconSource READ iconSource WRITE setIconSource NOTIFY iconSourceChanged) + Q_PROPERTY(int notificationCount READ notificationCount WRITE setNotificationCount NOTIFY notificationCountChanged) Q_PROPERTY(bool isOnline READ isOnline WRITE setIsOnline NOTIFY isOnlineChanged) - public: - TrayIcon(QObject* parent = nullptr); +public: + TrayIcon(QObject *parent = nullptr); - QString iconSource() { return m_iconSource; } - void setIconSource(const QString& source); + QString iconSource() + { + return m_iconSource; + } + void setIconSource(const QString &source); - int notificationCount() { return m_notificationCount; } - void setNotificationCount(int count); + int notificationCount() + { + return m_notificationCount; + } + void setNotificationCount(int count); - bool isOnline() { return m_isOnline; } - void setIsOnline(bool online); + bool isOnline() + { + return m_isOnline; + } + void setIsOnline(bool online); - signals: - void notificationCountChanged(); - void iconSourceChanged(); - void isOnlineChanged(); +signals: + void notificationCountChanged(); + void iconSourceChanged(); + void isOnlineChanged(); - void showWindow(); + void showWindow(); - private: - QString m_iconSource; - int m_notificationCount = 0; - bool m_isOnline = true; +private: + QString m_iconSource; + int m_notificationCount = 0; + bool m_isOnline = true; - QAction* viewAction_; - QAction* quitAction_; + QAction *viewAction_; + QAction *quitAction_; - MsgCountComposedIcon* icon_ = nullptr; + MsgCountComposedIcon *icon_ = nullptr; }; -#endif // TRAYICON_H +#endif // TRAYICON_H diff --git a/src/userdirectorylistmodel.cpp b/src/userdirectorylistmodel.cpp index b109f2bb1..afe7826fb 100644 --- a/src/userdirectorylistmodel.cpp +++ b/src/userdirectorylistmodel.cpp @@ -1,156 +1,163 @@ #include "userdirectorylistmodel.h" -UserDirectoryListModel::UserDirectoryListModel(QObject* parent) - : QAbstractListModel(parent) {} - -void UserDirectoryListModel::setConnection(Connection* conn) { - if (m_connection == conn) - return; - - beginResetModel(); - - m_limited = false; - attempted = false; - users.clear(); - - if (m_connection) { - m_connection->disconnect(this); - } - - endResetModel(); - - m_connection = conn; - - if (job) { - job->abandon(); - job = nullptr; - } - - emit connectionChanged(); - emit limitedChanged(); +UserDirectoryListModel::UserDirectoryListModel(QObject *parent) + : QAbstractListModel(parent) +{ } -void UserDirectoryListModel::setKeyword(const QString& value) { - if (m_keyword == value) - return; +void UserDirectoryListModel::setConnection(Connection *conn) +{ + if (m_connection == conn) + return; - m_keyword = value; + beginResetModel(); - m_limited = false; - attempted = false; + m_limited = false; + attempted = false; + users.clear(); - if (job) { - job->abandon(); - job = nullptr; - } - - emit keywordChanged(); - emit limitedChanged(); -} - -void UserDirectoryListModel::search(int count) { - if (count < 1) - return; - - if (job) { - qDebug() << "UserDirectoryListModel: Other jobs running, ignore"; - - return; - } - - if (attempted) - return; - - job = m_connection->callApi(m_keyword, count); - - connect(job, &BaseJob::finished, this, [=] { - attempted = true; - - if (job->status() == BaseJob::Success) { - auto users = job->results(); - - this->beginResetModel(); - - this->users = users; - this->m_limited = job->limited(); - - this->endResetModel(); + if (m_connection) { + m_connection->disconnect(this); } - this->job = nullptr; + endResetModel(); + m_connection = conn; + + if (job) { + job->abandon(); + job = nullptr; + } + + emit connectionChanged(); emit limitedChanged(); - }); } -QVariant UserDirectoryListModel::data(const QModelIndex& index, - int role) const { - if (!index.isValid()) - return QVariant(); +void UserDirectoryListModel::setKeyword(const QString &value) +{ + if (m_keyword == value) + return; + + m_keyword = value; + + m_limited = false; + attempted = false; + + if (job) { + job->abandon(); + job = nullptr; + } + + emit keywordChanged(); + emit limitedChanged(); +} + +void UserDirectoryListModel::search(int count) +{ + if (count < 1) + return; + + if (job) { + qDebug() << "UserDirectoryListModel: Other jobs running, ignore"; + + return; + } + + if (attempted) + return; + + job = m_connection->callApi(m_keyword, count); + + connect(job, &BaseJob::finished, this, [=] { + attempted = true; + + if (job->status() == BaseJob::Success) { + auto users = job->results(); + + this->beginResetModel(); + + this->users = users; + this->m_limited = job->limited(); + + this->endResetModel(); + } + + this->job = nullptr; + + emit limitedChanged(); + }); +} + +QVariant UserDirectoryListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (index.row() >= users.count()) { + qDebug() << "UserDirectoryListModel, something's wrong: index.row() >= " + "users.count()"; + return {}; + } + auto user = users.at(index.row()); + if (role == NameRole) { + auto displayName = user.displayName; + if (!displayName.isEmpty()) { + return displayName; + } + + displayName = user.userId; + if (!displayName.isEmpty()) { + return displayName; + } + + return "Unknown User"; + } + if (role == AvatarRole) { + auto avatarUrl = user.avatarUrl; + + if (avatarUrl.isEmpty()) { + return ""; + } + + return avatarUrl.remove(0, 6); + } + if (role == UserIDRole) { + return user.userId; + } + if (role == DirectChatsRole) { + if (!m_connection) + return {}; + + auto userObj = m_connection->user(user.userId); + auto directChats = m_connection->directChats(); + + if (userObj && directChats.contains(userObj)) { + auto directChatsForUser = directChats.values(userObj); + if (!directChatsForUser.isEmpty()) { + return QVariant::fromValue(directChatsForUser); + } + } + } - if (index.row() >= users.count()) { - qDebug() << "UserDirectoryListModel, something's wrong: index.row() >= " - "users.count()"; return {}; - } - auto user = users.at(index.row()); - if (role == NameRole) { - auto displayName = user.displayName; - if (!displayName.isEmpty()) { - return displayName; - } - - displayName = user.userId; - if (!displayName.isEmpty()) { - return displayName; - } - - return "Unknown User"; - } - if (role == AvatarRole) { - auto avatarUrl = user.avatarUrl; - - if (avatarUrl.isEmpty()) { - return ""; - } - - return avatarUrl.remove(0, 6); - } - if (role == UserIDRole) { - return user.userId; - } - if (role == DirectChatsRole) { - if (!m_connection) - return {}; - - auto userObj = m_connection->user(user.userId); - auto directChats = m_connection->directChats(); - - if (userObj && directChats.contains(userObj)) { - auto directChatsForUser = directChats.values(userObj); - if (!directChatsForUser.isEmpty()) { - return QVariant::fromValue(directChatsForUser); - } - } - } - - return {}; } -QHash UserDirectoryListModel::roleNames() const { - QHash roles; +QHash UserDirectoryListModel::roleNames() const +{ + QHash roles; - roles[NameRole] = "name"; - roles[AvatarRole] = "avatar"; - roles[UserIDRole] = "userID"; - roles[DirectChatsRole] = "directChats"; + roles[NameRole] = "name"; + roles[AvatarRole] = "avatar"; + roles[UserIDRole] = "userID"; + roles[DirectChatsRole] = "directChats"; - return roles; + return roles; } -int UserDirectoryListModel::rowCount(const QModelIndex& parent) const { - if (parent.isValid()) - return 0; +int UserDirectoryListModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; - return users.count(); + return users.count(); } diff --git a/src/userdirectorylistmodel.h b/src/userdirectorylistmodel.h index be76b4902..38c1c1a43 100644 --- a/src/userdirectorylistmodel.h +++ b/src/userdirectorylistmodel.h @@ -9,54 +9,62 @@ using namespace Quotient; -class UserDirectoryListModel : public QAbstractListModel { - Q_OBJECT - Q_PROPERTY(Connection* connection READ connection WRITE setConnection NOTIFY - connectionChanged) - Q_PROPERTY( - QString keyword READ keyword WRITE setKeyword NOTIFY keywordChanged) - Q_PROPERTY(bool limited READ limited NOTIFY limitedChanged) +class UserDirectoryListModel : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(Connection *connection READ connection WRITE setConnection NOTIFY connectionChanged) + Q_PROPERTY(QString keyword READ keyword WRITE setKeyword NOTIFY keywordChanged) + Q_PROPERTY(bool limited READ limited NOTIFY limitedChanged) - public: - enum EventRoles { - NameRole = Qt::DisplayRole + 1, - AvatarRole, - UserIDRole, - DirectChatsRole, - }; +public: + enum EventRoles { + NameRole = Qt::DisplayRole + 1, + AvatarRole, + UserIDRole, + DirectChatsRole, + }; - UserDirectoryListModel(QObject* parent = nullptr); + UserDirectoryListModel(QObject *parent = nullptr); - QVariant data(const QModelIndex& index, int role = NameRole) const override; - int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = NameRole) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; - QHash roleNames() const override; + QHash roleNames() const override; - Connection* connection() const { return m_connection; } - void setConnection(Connection* value); + Connection *connection() const + { + return m_connection; + } + void setConnection(Connection *value); - QString keyword() const { return m_keyword; } - void setKeyword(const QString& value); + QString keyword() const + { + return m_keyword; + } + void setKeyword(const QString &value); - bool limited() const { return m_limited; } + bool limited() const + { + return m_limited; + } - Q_INVOKABLE void search(int count = 50); + Q_INVOKABLE void search(int count = 50); - private: - Connection* m_connection = nullptr; - QString m_keyword; - bool m_limited = false; +private: + Connection *m_connection = nullptr; + QString m_keyword; + bool m_limited = false; - bool attempted = false; + bool attempted = false; - QVector users; + QVector users; - SearchUserDirectoryJob* job = nullptr; + SearchUserDirectoryJob *job = nullptr; - signals: - void connectionChanged(); - void keywordChanged(); - void limitedChanged(); +signals: + void connectionChanged(); + void keywordChanged(); + void limitedChanged(); }; -#endif // USERDIRECTORYLISTMODEL_H +#endif // USERDIRECTORYLISTMODEL_H diff --git a/src/userlistmodel.cpp b/src/userlistmodel.cpp index 372c542a9..fdf84b632 100644 --- a/src/userlistmodel.cpp +++ b/src/userlistmodel.cpp @@ -12,170 +12,185 @@ #include "spectraluser.h" -UserListModel::UserListModel(QObject* parent) - : QAbstractListModel(parent), m_currentRoom(nullptr) {} - -void UserListModel::setRoom(Quotient::Room* room) { - if (m_currentRoom == room) - return; - - using namespace Quotient; - beginResetModel(); - if (m_currentRoom) { - m_currentRoom->disconnect(this); - // m_currentRoom->connection()->disconnect(this); - for (User* user : m_users) - user->disconnect(this); - m_users.clear(); - } - m_currentRoom = room; - if (m_currentRoom) { - connect(m_currentRoom, &Room::userAdded, this, &UserListModel::userAdded); - connect(m_currentRoom, &Room::userRemoved, this, - &UserListModel::userRemoved); - connect(m_currentRoom, &Room::memberAboutToRename, this, - &UserListModel::userRemoved); - connect(m_currentRoom, &Room::memberRenamed, this, - &UserListModel::userAdded); - { - m_users = m_currentRoom->users(); - std::sort(m_users.begin(), m_users.end(), room->memberSorter()); - } - for (User* user : m_users) { - connect(user, &User::defaultAvatarChanged, this, [user, this](){avatarChanged(user);}); - } - connect(m_currentRoom->connection(), &Connection::loggedOut, this, - [=] { setRoom(nullptr); }); - qDebug() << m_users.count() << "user(s) in the room"; - } - endResetModel(); - emit roomChanged(); +UserListModel::UserListModel(QObject *parent) + : QAbstractListModel(parent) + , m_currentRoom(nullptr) +{ } -Quotient::User* UserListModel::userAt(QModelIndex index) const { - if (index.row() < 0 || index.row() >= m_users.size()) - return nullptr; - return m_users.at(index.row()); +void UserListModel::setRoom(Quotient::Room *room) +{ + if (m_currentRoom == room) + return; + + using namespace Quotient; + beginResetModel(); + if (m_currentRoom) { + m_currentRoom->disconnect(this); + // m_currentRoom->connection()->disconnect(this); + for (User *user : m_users) + user->disconnect(this); + m_users.clear(); + } + m_currentRoom = room; + if (m_currentRoom) { + connect(m_currentRoom, &Room::userAdded, this, &UserListModel::userAdded); + connect(m_currentRoom, &Room::userRemoved, this, &UserListModel::userRemoved); + connect(m_currentRoom, &Room::memberAboutToRename, this, &UserListModel::userRemoved); + connect(m_currentRoom, &Room::memberRenamed, this, &UserListModel::userAdded); + { + m_users = m_currentRoom->users(); + std::sort(m_users.begin(), m_users.end(), room->memberSorter()); + } + for (User *user : m_users) { + connect(user, &User::defaultAvatarChanged, this, [user, this]() { + avatarChanged(user); + }); + } + connect(m_currentRoom->connection(), &Connection::loggedOut, this, [=] { + setRoom(nullptr); + }); + qDebug() << m_users.count() << "user(s) in the room"; + } + endResetModel(); + emit roomChanged(); } -QVariant UserListModel::data(const QModelIndex& index, int role) const { - if (!index.isValid()) - return QVariant(); +Quotient::User *UserListModel::userAt(QModelIndex index) const +{ + if (index.row() < 0 || index.row() >= m_users.size()) + return nullptr; + return m_users.at(index.row()); +} + +QVariant UserListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (index.row() >= m_users.count()) { + qDebug() << "UserListModel, something's wrong: index.row() >= m_users.count()"; + return {}; + } + auto user = m_users.at(index.row()); + if (role == NameRole) { + return user->displayname(m_currentRoom); + } + if (role == UserIDRole) { + return user->id(); + } + if (role == AvatarRole) { + return user->avatarMediaId(m_currentRoom); + } + if (role == ObjectRole) { + return QVariant::fromValue(user); + } + if (role == PermRole) { + auto pl = m_currentRoom->getCurrentState(); + auto userPl = pl->powerLevelForUser(user->id()); + + if (userPl == pl->content().usersDefault) { // Shortcut + return UserType::Member; + } + + if (userPl < pl->powerLevelForState("m.room.message")) { + return UserType::Muted; + } + + auto userPls = pl->users(); + + int highestPl = pl->usersDefault(); + QHash::const_iterator i = userPls.constBegin(); + while (i != userPls.constEnd()) { + if (i.value() > highestPl) { + highestPl = i.value(); + } + + ++i; + } + + if (userPl == highestPl) { + return UserType::Owner; + } + + if (userPl >= pl->powerLevelForState("m.room.power_levels")) { + return UserType::Admin; + } + + if (userPl >= pl->ban() || userPl >= pl->kick() || userPl >= pl->redact()) { + return UserType::Moderator; + } + + return UserType::Member; + } - if (index.row() >= m_users.count()) { - qDebug() - << "UserListModel, something's wrong: index.row() >= m_users.count()"; return {}; - } - auto user = m_users.at(index.row()); - if (role == NameRole) { - return user->displayname(m_currentRoom); - } - if (role == UserIDRole) { - return user->id(); - } - if (role == AvatarRole) { - return user->avatarMediaId(m_currentRoom); - } - if (role == ObjectRole) { - return QVariant::fromValue(user); - } - if (role == PermRole) { - auto pl = m_currentRoom->getCurrentState(); - auto userPl = pl->powerLevelForUser(user->id()); - - if (userPl == pl->content().usersDefault) { // Shortcut - return UserType::Member; - } - - if (userPl < pl->powerLevelForState("m.room.message")) { - return UserType::Muted; - } - - auto userPls = pl->users(); - - int highestPl = pl->usersDefault(); - QHash::const_iterator i = userPls.constBegin(); - while (i != userPls.constEnd()) { - if (i.value() > highestPl) { - highestPl = i.value(); - } - - ++i; - } - - if (userPl == highestPl) { - return UserType::Owner; - } - - if (userPl >= pl->powerLevelForState("m.room.power_levels")) { - return UserType::Admin; - } - - if (userPl >= pl->ban() || userPl >= pl->kick() || userPl >= pl->redact()) { - return UserType::Moderator; - } - - return UserType::Member; - } - - return {}; } -int UserListModel::rowCount(const QModelIndex& parent) const { - if (parent.isValid()) - return 0; +int UserListModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; - return m_users.count(); + return m_users.count(); } -void UserListModel::userAdded(Quotient::User* user) { - auto pos = findUserPos(user); - beginInsertRows(QModelIndex(), pos, pos); - m_users.insert(pos, user); - endInsertRows(); - connect(user, &Quotient::User::defaultAvatarChanged, this, [user, this](){avatarChanged(user);}); +void UserListModel::userAdded(Quotient::User *user) +{ + auto pos = findUserPos(user); + beginInsertRows(QModelIndex(), pos, pos); + m_users.insert(pos, user); + endInsertRows(); + connect(user, &Quotient::User::defaultAvatarChanged, this, [user, this]() { + avatarChanged(user); + }); } -void UserListModel::userRemoved(Quotient::User* user) { - auto pos = findUserPos(user); - if (pos != m_users.size()) { - beginRemoveRows(QModelIndex(), pos, pos); - m_users.removeAt(pos); - endRemoveRows(); - user->disconnect(this); - } else - qWarning() << "Trying to remove a room member not in the user list"; +void UserListModel::userRemoved(Quotient::User *user) +{ + auto pos = findUserPos(user); + if (pos != m_users.size()) { + beginRemoveRows(QModelIndex(), pos, pos); + m_users.removeAt(pos); + endRemoveRows(); + user->disconnect(this); + } else + qWarning() << "Trying to remove a room member not in the user list"; } -void UserListModel::refresh(Quotient::User* user, QVector roles) { - auto pos = findUserPos(user); - if (pos != m_users.size()) - emit dataChanged(index(pos), index(pos), roles); - else - qWarning() << "Trying to access a room member not in the user list"; +void UserListModel::refresh(Quotient::User *user, QVector roles) +{ + auto pos = findUserPos(user); + if (pos != m_users.size()) + emit dataChanged(index(pos), index(pos), roles); + else + qWarning() << "Trying to access a room member not in the user list"; } -void UserListModel::avatarChanged(Quotient::User* user) { +void UserListModel::avatarChanged(Quotient::User *user) +{ refresh(user, {AvatarRole}); } -int UserListModel::findUserPos(User* user) const { - return findUserPos(m_currentRoom->roomMembername(user)); +int UserListModel::findUserPos(User *user) const +{ + return findUserPos(m_currentRoom->roomMembername(user)); } -int UserListModel::findUserPos(const QString& username) const { - return m_currentRoom->memberSorter().lowerBoundIndex(m_users, username); +int UserListModel::findUserPos(const QString &username) const +{ + return m_currentRoom->memberSorter().lowerBoundIndex(m_users, username); } -QHash UserListModel::roleNames() const { - QHash roles; +QHash UserListModel::roleNames() const +{ + QHash roles; - roles[NameRole] = "name"; - roles[UserIDRole] = "userId"; - roles[AvatarRole] = "avatar"; - roles[ObjectRole] = "user"; - roles[PermRole] = "perm"; + roles[NameRole] = "name"; + roles[UserIDRole] = "userId"; + roles[AvatarRole] = "avatar"; + roles[ObjectRole] = "user"; + roles[PermRole] = "perm"; - return roles; + return roles; } diff --git a/src/userlistmodel.h b/src/userlistmodel.h index 74b2af70e..3f9d7394f 100644 --- a/src/userlistmodel.h +++ b/src/userlistmodel.h @@ -6,65 +6,70 @@ #include #include -namespace Quotient { +namespace Quotient +{ class Connection; class Room; class User; -} // namespace Quotient +} // namespace Quotient -class UserType : public QObject { - Q_OBJECT +class UserType : public QObject +{ + Q_OBJECT - public: +public: enum Types { - Owner = 1, - Admin, - Moderator, - Member, - Muted, + Owner = 1, + Admin, + Moderator, + Member, + Muted, }; Q_ENUMS(Types) }; -class UserListModel : public QAbstractListModel { - Q_OBJECT - Q_PROPERTY( - Quotient::Room* room READ room WRITE setRoom NOTIFY roomChanged) - public: - enum EventRoles { - NameRole = Qt::UserRole + 1, - UserIDRole, - AvatarRole, - ObjectRole, - PermRole, - }; +class UserListModel : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(Quotient::Room *room READ room WRITE setRoom NOTIFY roomChanged) +public: + enum EventRoles { + NameRole = Qt::UserRole + 1, + UserIDRole, + AvatarRole, + ObjectRole, + PermRole, + }; - UserListModel(QObject* parent = nullptr); + UserListModel(QObject *parent = nullptr); - Quotient::Room* room() const { return m_currentRoom; } - void setRoom(Quotient::Room* room); - Quotient::User* userAt(QModelIndex index) const; + Quotient::Room *room() const + { + return m_currentRoom; + } + void setRoom(Quotient::Room *room); + Quotient::User *userAt(QModelIndex index) const; - QVariant data(const QModelIndex& index, int role = NameRole) const override; - int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = NameRole) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; - QHash roleNames() const override; + QHash roleNames() const override; - signals: - void roomChanged(); +signals: + void roomChanged(); - private slots: - void userAdded(Quotient::User* user); - void userRemoved(Quotient::User* user); - void refresh(Quotient::User* user, QVector roles = {}); - void avatarChanged(Quotient::User* user); +private slots: + void userAdded(Quotient::User *user); + void userRemoved(Quotient::User *user); + void refresh(Quotient::User *user, QVector roles = {}); + void avatarChanged(Quotient::User *user); - private: - Quotient::Room* m_currentRoom; - QList m_users; +private: + Quotient::Room *m_currentRoom; + QList m_users; - int findUserPos(Quotient::User* user) const; - int findUserPos(const QString& username) const; + int findUserPos(Quotient::User *user) const; + int findUserPos(const QString &username) const; }; -#endif // USERLISTMODEL_H +#endif // USERLISTMODEL_H diff --git a/src/utils.h b/src/utils.h index f9282d90f..8d4efe7bf 100644 --- a/src/utils.h +++ b/src/utils.h @@ -13,18 +13,13 @@ #include #include -namespace utils { -static const QRegularExpression removeReplyRegex{ - "> <.*?>.*?\\n\\n", QRegularExpression::DotMatchesEverythingOption}; -static const QRegularExpression removeRichReplyRegex{ - ".*?", QRegularExpression::DotMatchesEverythingOption}; -static const QRegularExpression codePillRegExp{ - "
]*>(.*?)
", QRegularExpression::DotMatchesEverythingOption}; -static const QRegularExpression userPillRegExp{ - "(.*?)", - QRegularExpression::DotMatchesEverythingOption}; -static const QRegularExpression strikethroughRegExp{ - "(.*?)", QRegularExpression::DotMatchesEverythingOption}; -} // namespace utils +namespace utils +{ +static const QRegularExpression removeReplyRegex {"> <.*?>.*?\\n\\n", QRegularExpression::DotMatchesEverythingOption}; +static const QRegularExpression removeRichReplyRegex {".*?", QRegularExpression::DotMatchesEverythingOption}; +static const QRegularExpression codePillRegExp {"
]*>(.*?)
", QRegularExpression::DotMatchesEverythingOption}; +static const QRegularExpression userPillRegExp {"(.*?)", QRegularExpression::DotMatchesEverythingOption}; +static const QRegularExpression strikethroughRegExp {"(.*?)", QRegularExpression::DotMatchesEverythingOption}; +} // namespace utils #endif