diff --git a/CustomModels/emojismodel.cpp b/CustomModels/emojismodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..da46ba0cc3fd8cc63cfd80d2e47e38453ea808a2 --- /dev/null +++ b/CustomModels/emojismodel.cpp @@ -0,0 +1,142 @@ +#include "emojismodel.h" + +EmojisModel::EmojisModel() +{ + +} + +int EmojisModel::rowCount( const QModelIndex &parent ) const +{ + if ( mData.contains( mCurrentCategory ) ) { + return mData[mCurrentCategory].size(); + } else { + return 0; + } +} + +QVariant EmojisModel::data( const QModelIndex &index, int role ) const +{ + int row = index.row(); + + auto list = mData[mCurrentCategory]; + auto emoji = list[row]; + + switch ( role ) { + case static_cast<int>( EmojiRoles::emojiText ): + return emoji->getIdentifier(); + + case static_cast<int>( EmojiRoles::image ): + return emoji->getFilePath(); + + case static_cast<int>( EmojiRoles::category ): + return emoji->getCategory(); + + case static_cast<int>( EmojiRoles::order ): + return emoji->getOrder(); + + case static_cast<int>( EmojiRoles::custom ): + if ( emoji->getCategory() == "custom" ) { + return true; + } else { + return false; + } + + default: + return QVariant(); + } +} + +void EmojisModel::addEmoji( QSharedPointer<Emoji> pEmoji ) +{ + if ( !mDuplicateCheck.contains( pEmoji->getIdentifier() ) ) { + auto category = pEmoji->getCategory(); + int order = pEmoji->getOrder(); + + if ( mData.contains( category ) ) { + auto list = mData[category]; + auto firstElem = list.first(); + auto lastElem = list.last(); + + if ( order <= firstElem->getOrder() ) { + list.prepend( pEmoji ); + } else if ( order >= lastElem->getOrder() ) { + list.append( pEmoji ); + } else { + int orderDiffLast = lastElem->getOrder() - order; + int listLength = list.length(); + + if ( orderDiffLast > order ) { + for ( int i = listLength; i >= 0; i-- ) { + if ( list[i]->getOrder() >= order ) { + list.insert( i - 1, pEmoji ); + } + } + } else { + for ( int i = 0; i < listLength; i++ ) { + if ( list[i]->getOrder() <= order ) { + list.insert( i, pEmoji ); + } + } + } + } + + } else { + mData.insert( category, {pEmoji} ); + } + + mDuplicateCheck.insert( pEmoji->getIdentifier() ); + } +} + +void EmojisModel::addEmojisByCategory( QString pCategory, QList<QSharedPointer<Emoji> > pList ) +{ + if ( mCurrentCategory == pCategory ) { + beginResetModel(); + } + + if ( !mData.contains( pCategory ) ) { + mData.insert( pCategory, QList<QSharedPointer<Emoji>>() ); + } + + for ( auto element : pList ) { + if ( !mDuplicateCheck.contains( element->getIdentifier() ) ) { + mData[pCategory].append( element ); + mDuplicateCheck.insert( element->getIdentifier() ); + } + } + + if ( mCurrentCategory == pCategory ) { + endResetModel(); + } + +} + +void EmojisModel::clear() +{ + mData.clear(); + mDuplicateCheck.clear(); + mCurrentCategory.clear(); +} + +QHash<int, QByteArray> EmojisModel::roleNames() const +{ + QHash<int, QByteArray> roles; + roles[static_cast<int>( EmojiRoles::emojiText )] = QByteArrayLiteral( "emojiText" ); + roles[static_cast<int>( EmojiRoles::category )] = QByteArrayLiteral( "category" ); + roles[static_cast<int>( EmojiRoles::image )] = QByteArrayLiteral( "image" ); + roles[static_cast<int>( EmojiRoles::order )] = QByteArrayLiteral( "order" ); + roles[static_cast<int>( EmojiRoles::custom )] = QByteArrayLiteral( "custom" ); + return roles; +} + +QString EmojisModel::currentCategory() const +{ + return mCurrentCategory; +} + +void EmojisModel::setCurrentCategory( const QString ¤tCategory ) +{ + beginResetModel(); + mCurrentCategory = currentCategory; + endResetModel(); +} diff --git a/CustomModels/emojismodel.h b/CustomModels/emojismodel.h new file mode 100644 index 0000000000000000000000000000000000000000..a077bc9a44fc197e1c000cd7cc88d7f4e966ed09 --- /dev/null +++ b/CustomModels/emojismodel.h @@ -0,0 +1,46 @@ +#ifndef EMOJISMODEL_H +#define EMOJISMODEL_H + +#include <QAbstractListModel> +#include <QSet> +#include <QMap> +#include <QSharedPointer> + +#include <repos/entities/emoji.h> + + + +class EmojisModel: public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY( QString currentCategory READ currentCategory WRITE setCurrentCategory NOTIFY currentCategoryChanged ) + public: + enum class EmojiRoles : int { + emojiText = Qt::UserRole, + image, + category, + order, + custom + }; + + EmojisModel(); + int rowCount( const QModelIndex &parent = QModelIndex() ) const; + QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const; + QString currentCategory() const; + void setCurrentCategory( const QString ¤tCategory ); + + public slots: + void addEmoji( QSharedPointer<Emoji> pEmoji ); + void addEmojisByCategory( QString pCategory, QList<QSharedPointer<Emoji>> pList ); + void clear(); + protected: + QHash<int, QByteArray> roleNames() const; + QString mCurrentCategory; + QSet<QString> mDuplicateCheck; + QMap<QString, QList<QSharedPointer<Emoji>>> mData; + signals: + void currentCategoryChanged( void ); + +}; + +#endif // EMOJISMODEL_H diff --git a/CustomModels/messagesearchresultsmodel.cpp b/CustomModels/messagesearchresultsmodel.cpp index 72f6886aada2c6950457c9c62ec5f315c125049e..b252cd1c67db61247d483f25e6fd3ce74e399e9e 100644 --- a/CustomModels/messagesearchresultsmodel.cpp +++ b/CustomModels/messagesearchresultsmodel.cpp @@ -12,67 +12,72 @@ void MessageSearchResultsModel::clear() endResetModel(); } -int MessageSearchResultsModel::rowCount(const QModelIndex &parent) const +int MessageSearchResultsModel::rowCount( const QModelIndex &parent ) const { - Q_UNUSED(parent) + Q_UNUSED( parent ) return mElements.length(); } -QVariant MessageSearchResultsModel::data(const QModelIndex &index, int role) const +QVariant MessageSearchResultsModel::data( const QModelIndex &index, int role ) const { QSharedPointer<RocketChatMessage> message; - if(mElements.size()){ - message = mElements.at(index.row()); - }else{ + + if ( mElements.size() ) { + message = mElements.at( index.row() ); + } else { return QVariant(); } - if(role == text){ + + if ( role == text ) { return message->getMessageString(); - }else if(role == author){ + } else if ( role == author ) { return message->getAuthor(); - }else if(role == authorId){ + } else if ( role == authorId ) { return message->getAuthorId(); - }else if(role == linkurl){ + } else if ( role == linkurl ) { if ( !message->getAttachments().empty() ) { return message->getAttachments().first()->getUrl(); } else { qWarning() << "linkurl not found"; } - }else if(role == type){ + } else if ( role == type ) { return message->getMessageType(); - }else if(role == date){ + } else if ( role == date ) { return message->getFormattedDate(); - }else if(role == time){ + } else if ( role == time ) { return message->getFormattedTime(); - }else if(role == ownMessage){ + } else if ( role == ownMessage ) { return message->getOwnMessage(); - }else if(role == height){ + } else if ( role == height ) { if ( !message->getAttachments().empty() ) { return message->getAttachments().first()->getHeight(); } else { qWarning() << "height not found"; } - }else if(role == width){ + } else if ( role == width ) { if ( !message->getAttachments().empty() ) { return message->getAttachments().first()->getWidth(); } else { qWarning() << "height not found"; } - }else if(role == formattedDate){ + } else if ( role == formattedDate ) { return message->getFormattedDate(); - }else if(role == formattedTime){ + } else if ( role == formattedTime ) { return message->getFormattedTime(); - }else if(role == messageType){ + } else if ( role == messageType ) { return message->getMessageType(); - }else if(role == blocked){ + } else if ( role == blocked ) { return false; - }else if(role == id){ + } else if ( role == id ) { return message->getId(); - }else if(role == rid){ + } else if ( role == rid ) { return message->getRoomId(); - }else if(role == timestamp){ + } else if ( role == timestamp ) { return message->getTimestamp(); } + + return QVariant(); + } QHash<int, QByteArray> MessageSearchResultsModel::roleNames() const @@ -93,13 +98,13 @@ QHash<int, QByteArray> MessageSearchResultsModel::roleNames() const roles[messageType] = QByteArrayLiteral( "messageType" ); roles[blocked] = QByteArrayLiteral( "blocked" ); roles[id] = QByteArrayLiteral( "id" ); - roles[rid] = QByteArrayLiteral("rid"); - roles[timestamp] = QByteArrayLiteral("timestamp"); + roles[rid] = QByteArrayLiteral( "rid" ); + roles[timestamp] = QByteArrayLiteral( "timestamp" ); return roles; } -void MessageSearchResultsModel::setSearchResults(MessageList pResults) +void MessageSearchResultsModel::setSearchResults( MessageList pResults ) { beginResetModel(); mElements.clear(); @@ -107,15 +112,18 @@ void MessageSearchResultsModel::setSearchResults(MessageList pResults) endResetModel(); } -int MessageSearchResultsModel::getPositionOfMessage(const QString &pId) +int MessageSearchResultsModel::getPositionOfMessage( const QString &pId ) { int pos = -1; - for(int i=0; i<mElements.size();i++){ - auto element = mElements.at(i); - if(element->getId()==pId){ + + for ( int i = 0; i < mElements.size(); i++ ) { + auto element = mElements.at( i ); + + if ( element->getId() == pId ) { pos = i; break; } } + return pos; } diff --git a/CustomModels/models.cpp b/CustomModels/models.cpp index 54fc37c568913505f38a3c321e922b6ae9529c97..e721c42454bda1b34114de3cee619178f74e31b9 100644 --- a/CustomModels/models.cpp +++ b/CustomModels/models.cpp @@ -8,28 +8,29 @@ ChannelModel *Models::mPrivateGroupsModel = nullptr; MessagesModel *Models::mMessagesModel = nullptr; MessageSearchResultsModel *Models::mMessagesSearchModel = nullptr; RoomSearchResultsModel *Models::mRoomsSearchModel = nullptr; +EmojisModel *Models::mEmojisModel = nullptr; -UserModel* Models::getUsersModel() +UserModel *Models::getUsersModel() { return mUserModel; } -LoginMethodsModel* Models::getLoginMethodsModel() +LoginMethodsModel *Models::getLoginMethodsModel() { return mLoginMethodsModel; } -ChannelModel* Models::getDirectChannelsModel() +ChannelModel *Models::getDirectChannelsModel() { return mDirectChannelsModel; } -ChannelModel* Models::getPublicGroupsModel() +ChannelModel *Models::getPublicGroupsModel() { return mPublicGroupsModel; } -ChannelModel* Models::getPrivateGroupsModel() +ChannelModel *Models::getPrivateGroupsModel() { return mPrivateGroupsModel; } @@ -57,34 +58,46 @@ void Models::resetModels() mPrivateGroupsModel->clear(); mMessagesSearchModel->clear(); mRoomsSearchModel->clear(); + mEmojisModel->clear(); } void Models::init() { - if(mDirectChannelsModel == nullptr){ + if ( mDirectChannelsModel == nullptr ) { mDirectChannelsModel = new ChannelModel(); } - if(mLoginMethodsModel == nullptr){ + + if ( mLoginMethodsModel == nullptr ) { mLoginMethodsModel = new LoginMethodsModel(); } - if(mPublicGroupsModel == nullptr){ + + if ( mPublicGroupsModel == nullptr ) { mPublicGroupsModel = new ChannelModel(); } - if(mPrivateGroupsModel == nullptr){ + + if ( mPrivateGroupsModel == nullptr ) { mPrivateGroupsModel = new ChannelModel(); } - if(mMessagesModel == nullptr){ + + if ( mMessagesModel == nullptr ) { mMessagesModel = new MessagesModel(); } - if(mUserModel == nullptr){ + + if ( mUserModel == nullptr ) { mUserModel = new UserModel(); } - if(mMessagesSearchModel == nullptr){ + + if ( mMessagesSearchModel == nullptr ) { mMessagesSearchModel = new MessageSearchResultsModel(); } - if(mRoomsSearchModel == nullptr){ + + if ( mRoomsSearchModel == nullptr ) { mRoomsSearchModel = new RoomSearchResultsModel(); } + + if ( mEmojisModel == nullptr ) { + mEmojisModel = new EmojisModel(); + } } Models::~Models() @@ -98,3 +111,8 @@ Models::~Models() Models::mMessagesSearchModel->deleteLater(); Models::mRoomsSearchModel->deleteLater(); } + +EmojisModel *Models::getEmojisModel() +{ + return mEmojisModel; +} diff --git a/CustomModels/models.h b/CustomModels/models.h index d358e4a838cd7e9bf207f984e39bae651c1a8a15..b6ec28dea10c0d68dee82f84d65ef1ca33c72794 100644 --- a/CustomModels/models.h +++ b/CustomModels/models.h @@ -7,6 +7,7 @@ #include "usermodel.h" #include "messagesearchresultsmodel.h" #include "roomsearchresultsmodel.h" +#include "emojismodel.h" class ChannelModel; class MessagesModel; @@ -15,32 +16,35 @@ class RoomSearchResultsModel; class Models { -public: - Models() = delete; - Models& operator=(const Models&) = delete; - - static UserModel* getUsersModel(); - static LoginMethodsModel* getLoginMethodsModel(); - static ChannelModel* getDirectChannelsModel(); - static ChannelModel* getPublicGroupsModel(); - static ChannelModel* getPrivateGroupsModel(); - static MessagesModel* getMessagesModel(); - static MessageSearchResultsModel *getMessagesSearchModel(); - static RoomSearchResultsModel *getRoomSearchModel(); - static void resetModels(); - static void init(); - - ~Models(); - -private: - static UserModel *mUserModel; - static LoginMethodsModel *mLoginMethodsModel; - static ChannelModel *mDirectChannelsModel; - static ChannelModel *mPublicGroupsModel; - static ChannelModel *mPrivateGroupsModel; - static MessagesModel *mMessagesModel; - static MessageSearchResultsModel *mMessagesSearchModel; - static RoomSearchResultsModel *mRoomsSearchModel; + public: + Models() = delete; + Models &operator=( const Models & ) = delete; + + static UserModel *getUsersModel(); + static LoginMethodsModel *getLoginMethodsModel(); + static ChannelModel *getDirectChannelsModel(); + static ChannelModel *getPublicGroupsModel(); + static ChannelModel *getPrivateGroupsModel(); + static MessagesModel *getMessagesModel(); + static MessageSearchResultsModel *getMessagesSearchModel(); + static RoomSearchResultsModel *getRoomSearchModel(); + static EmojisModel *getEmojisModel(); + static void resetModels(); + static void init(); + + ~Models(); + + + private: + static UserModel *mUserModel; + static LoginMethodsModel *mLoginMethodsModel; + static ChannelModel *mDirectChannelsModel; + static ChannelModel *mPublicGroupsModel; + static ChannelModel *mPrivateGroupsModel; + static MessagesModel *mMessagesModel; + static MessageSearchResultsModel *mMessagesSearchModel; + static RoomSearchResultsModel *mRoomsSearchModel; + static EmojisModel *mEmojisModel; }; #endif // MODELS_H diff --git a/engine.pro b/engine.pro index 2e07cbb46290f968b69c39d962d6f857aa8f6bfa..3a995a5fae5b9dc89a84af73b24469f7f9232d30 100644 --- a/engine.pro +++ b/engine.pro @@ -102,7 +102,8 @@ SOURCES += api/meteorddp.cpp \ repos/entities/rocketchatreplymessage.cpp \ ddpRequests/rocketchatcreatepublicgrouprequest.cpp \ ddpRequests/rocketchatchangeuserpresencestatus.cpp \ - ddpRequests/rocketchatsubscribeuserdata.cpp + ddpRequests/rocketchatsubscribeuserdata.cpp \ + CustomModels/emojismodel.cpp HEADERS += \ @@ -208,7 +209,8 @@ HEADERS += \ ddpRequests/rocketchatcreatepublicgrouprequest.h \ ddpRequests/rocketchatchangeuserpresencestatus.h \ ddpRequests/rocketchatchangeuserpresencedefaultstatus.h \ - ddpRequests/rocketchatsubscribeuserdata.h + ddpRequests/rocketchatsubscribeuserdata.h \ + CustomModels/emojismodel.h linux{ diff --git a/persistancelayer.cpp b/persistancelayer.cpp index f68c61c59400a116e05f3992a99be8bb7c38f84a..1274e217dc011d29b6e0dc5991b427777d04573c 100755 --- a/persistancelayer.cpp +++ b/persistancelayer.cpp @@ -1090,8 +1090,8 @@ QList<QJsonObject> PersistanceLayer::getMessagesByRid( const QString &pRid, qint QSqlQuery messages; messages.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid AND ts<=:from AND ts>=:to ORDER BY ts DESC LIMIT 50" ) ); messages.bindValue( QStringLiteral( ":rid" ), pRid ); - messages.bindValue( QStringLiteral( ":from" ), ( qint64 )( pFrom / 1000 ) ); - messages.bindValue( QStringLiteral( ":to" ), ( qint64 )( pTo / 1000 ) ); + messages.bindValue( QStringLiteral( ":from" ), static_cast<qint64>( pFrom / 1000 ) ); + messages.bindValue( QStringLiteral( ":to" ), static_cast<qint64>( pTo / 1000 ) ); QList<QJsonObject> rows; rows.reserve( 50 ); @@ -1130,7 +1130,7 @@ QList<QJsonObject > PersistanceLayer::getMessagesByRid( const QString &pRid, qin QSqlQuery messages; messages.prepare( QStringLiteral( "SELECT * FROM messages WHERE rid=:rid AND ts<=:from ORDER BY ts DESC LIMIT :limit" ) ); messages.bindValue( QStringLiteral( ":rid" ), pRid ); - messages.bindValue( QStringLiteral( ":from" ), ( qint64 )( pFrom ) ); + messages.bindValue( QStringLiteral( ":from" ), static_cast<qint64>( pFrom ) ); messages.bindValue( QStringLiteral( ":limit" ), pLimit ); QList<QJsonObject > rows; @@ -1244,7 +1244,7 @@ QList<QVariantHash> PersistanceLayer::getChannels( void ) QList< QHash<QString, QString > > PersistanceLayer::getCustomEmojis() { QSqlQuery emojiQuery; - emojiQuery.prepare( QStringLiteral( "SELECT id,file,html,category,unicode,sort_order FROM custom_emojis" ) ); + emojiQuery.prepare( QStringLiteral( "SELECT id,file,html,category,unicode,sort_order FROM custom_emojis ORDER BY sort_order ASC" ) ); QList<QHash<QString, QString> > returnList; returnList.reserve( 3000 ); @@ -1379,7 +1379,7 @@ QString PersistanceLayer::getNewVideoPath( void ) QDateTime dateTime = QDateTime::currentDateTime(); uint timeStamp = dateTime.toTime_t(); - QFile file( path + '/' + timeStamp + QStringLiteral( ".mp4" ) ); + QFile file( path + '/' + QString( timeStamp ) + QStringLiteral( ".mp4" ) ); if ( !file.exists() ) { //file.open( QIODevice::ReadWrite ); diff --git a/rocketchatserver.cpp b/rocketchatserver.cpp index c916b3c58dc20460185bc9b2750306c1860fb965..023d0c8b67c91b0a4b9da4bf4e576972d25fa71b 100755 --- a/rocketchatserver.cpp +++ b/rocketchatserver.cpp @@ -27,6 +27,7 @@ RocketChatServerData::RocketChatServerData( const QString &pId, QString pBaseUrl directModel( Models::getDirectChannelsModel() ), groupsModel( Models::getPublicGroupsModel() ) { qRegisterMetaType<User>( "User" ); + qRegisterMetaType<QList<QSharedPointer<Emoji>>>( "QList<QSharedPointer<Emoji>>" ); mUnsecureConnection = pUnsecure; @@ -180,8 +181,10 @@ void RocketChatServerData::loadEmojis() mStorage->addCustomEmoji(id,file,html,category,unicode,sort_orderInt); }*/ + auto emojiModel = Models::getEmojisModel(); auto emojiList = mEmojiService->loadEmojisFromDb(); + QMap<QString, QList<QSharedPointer<Emoji>>> emojisByCategory; for ( const auto &emoji : emojiList ) { if ( mEmojiRepo != nullptr && !emoji.isNull() ) { @@ -190,6 +193,20 @@ void RocketChatServerData::loadEmojis() // mCustomEmojisHash = Utils::hash(mCustomEmojis); // } } + + auto category = emoji->getCategory(); + + if ( !emojisByCategory.contains( category ) ) { + emojisByCategory.insert( category, QList<QSharedPointer<Emoji>>() ); + } + + emojisByCategory[category].append( emoji ); + } + + auto keys = emojisByCategory.keys(); + + for ( auto key : keys ) { + QMetaObject::invokeMethod( emojiModel, "addEmojisByCategory", Q_ARG( QString, key ), Q_ARG( QList<QSharedPointer<Emoji>>, emojisByCategory[key] ) ); } } @@ -597,18 +614,6 @@ QString RocketChatServerData::getBaseUrl() const return protocol + mBaseUrl; } -QVariantList RocketChatServerData::getEmojisByCategory() const -{ - QVariantList list; - auto emojiMap = mEmojiRepo->emojisOrdered(); - - for ( const auto &emoji : emojiMap ) { - list.append( emoji->toQVariantMap() ); - } - - return list; -} - void RocketChatServerData::login( const QString &pUsername, const QString &pPassword ) { QPair<QString, uint> tokenDb = mStorage->getToken(); @@ -1696,7 +1701,7 @@ void RocketChatServerData::sendMessage( const QString &pMessage, const QString & void RocketChatServerData::getCustomEmojis() { std::function<void ( QList<QSharedPointer<Emoji>> )> success = [ = ]( QList<QSharedPointer<Emoji>> pEmojiList ) { - QVariantList variantList; + auto emojiModel = Models::getEmojisModel(); if ( pEmojiList.size() ) { mStorage->transaction(); @@ -1706,18 +1711,18 @@ void RocketChatServerData::getCustomEmojis() mEmojiService->persistEmoji( emoji ); if ( !mEmojiRepo->contains( emoji->getIdentifier() ) ) { - mEmojiRepo->add( emoji->getIdentifier(), emoji ); - variantList.append( emoji->toQVariantMap() ); - } } } + QMetaObject::invokeMethod( emojiModel, "addEmojisByCategory", Q_ARG( QString, "custom" ), Q_ARG( QList<QSharedPointer<Emoji>>, pEmojiList ) ); + + mStorage->commit(); } - emit customEmojisReceived( getEmojisByCategory() ); + //emit customEmojisReceived( getEmojisByCategory() ); QSharedPointer<RocketChatSubscribeRoomsChanged> notifyRoomsChanged( new RocketChatSubscribeRoomsChanged( this->mUserId ) ); QSharedPointer<RocketChatSubscribeUserNotify> notifySubSubscription( new RocketChatSubscribeUserNotify( this->mUserId ) ); @@ -1812,16 +1817,6 @@ void RocketChatServerData::cancelUpload( const QString &pFileId ) } } -void RocketChatServerData::getRoomInformation( const QString &pRoomName ) -{ - QJsonArray params; - params.append( pRoomName ); - - QSharedPointer<RocketChatSubscribeChannelRequest> roomSubscription( new RocketChatSubscribeChannelRequest( pRoomName ) ); - - sendDdprequest( roomSubscription ); -} - void RocketChatServerData::getLoginMethods() { DdpCallback success = [ = ]( QJsonObject pResponse, MeteorDDP * pDdpApi ) { diff --git a/rocketchatserver.h b/rocketchatserver.h index fe5402be03f61fa0fa821e47949b0db1ad4bd039..806c77de5b8b4d04475665be867194ec3ec90a90 100755 --- a/rocketchatserver.h +++ b/rocketchatserver.h @@ -220,7 +220,6 @@ class RocketChatServerData : public MessageListener RocketChatChannelService *mChannelService; void handleChannelMessage( const QJsonObject &pMessage ); uint diffToLastDDPPing(); - QVariantList getEmojisByCategory() const; QString parseMessageReceived( const QString &pMessage ); void sendUnsentMessages( void ); void sendApiRequest( const RestApiRequest &pRequest, bool pRetry = true );