/******************************************************************************************** * * * Copyright (C) 2017 Armin Felder, Dennis Beier * * This file is part of RocketChatMobileEngine <https://git.fairkom.net/chat/fairchat>. * * * * RocketChatMobileEngine is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * RocketChatMobileEngine is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with RocketChatMobileEngine. If not, see <http://www.gnu.org/licenses/>. * * * ********************************************************************************************/ #include "messagemodel.h" #include <repos/entities/rocketchatreplymessage.h> MessagesModel::MessagesModel() { duplicateCheck.reserve( 10000 ); } QVariant MessagesModel::data( const QModelIndex &index, int role ) const { int row = index.row(); QSharedPointer<RocketChatMessage> messageAtIndex = messagesOfCurrentChannel.at( row ); auto roleType = static_cast<MessageRoles>( role ); switch ( roleType ) { case MessageRoles::type: return messageAtIndex->getMessageType(); case MessageRoles::text: return messageAtIndex->getMessageString(); case MessageRoles::linkurl: if ( !messageAtIndex->getAttachments().empty() ) { return messageAtIndex->getAttachments().first()->getUrl(); } else { qWarning() << "linkurl not found"; } break; case MessageRoles::author: return messageAtIndex->getAuthor(); case MessageRoles::authorId: return messageAtIndex->getAuthorId(); case MessageRoles::date: return messageAtIndex->getFormattedDate(); case MessageRoles::time: return messageAtIndex->getFormattedTime(); case MessageRoles::ownMessage: return messageAtIndex->getOwnMessage(); case MessageRoles::width: if ( !messageAtIndex->getAttachments().empty() ) { return messageAtIndex->getAttachments().first()->getWidth(); } else { qWarning() << "width not found"; } break; case MessageRoles::height: if ( !messageAtIndex->getAttachments().empty() ) { return messageAtIndex->getAttachments().first()->getHeight(); } else { qWarning() << "height not found"; } break; case MessageRoles::formattedDate: return messageAtIndex->getFormattedDate(); case MessageRoles::formattedTime: return messageAtIndex->getFormattedTime(); case MessageRoles::messageType: return messageAtIndex->getMessageType(); case MessageRoles::blocked: return mBlockedUsers.contains( messageAtIndex->getAuthorId() ); case MessageRoles::id: return messageAtIndex->getId(); case MessageRoles::replyMessage: { QList<QSharedPointer<RocketChatAttachment> > attachments = messageAtIndex->getAttachments(); if ( attachments.size() ) { QSharedPointer<RocketChatAttachment> first = attachments.first(); QSharedPointer<RocketChatReplyMessage> msg = qSharedPointerCast<RocketChatReplyMessage>( first ); return msg->getMessageString(); } } break; case MessageRoles::replyAutor: { QList<QSharedPointer<RocketChatAttachment> > attachments = messageAtIndex->getAttachments(); if ( attachments.size() ) { QSharedPointer<RocketChatAttachment> first = attachments.first(); QSharedPointer<RocketChatReplyMessage> msg = qSharedPointerCast<RocketChatReplyMessage>( first ); return msg->getAuthor(); } } break; case MessageRoles::replyUrl: { QString server = messageAtIndex->getServer(); auto currentChannel = mChannelMap[current]; QString type = currentChannel->getType(); QString name = currentChannel->getName(); if ( type == "p" ) { type = "group"; } else if ( type == "c" ) { type = "channel"; } else if ( type == "d" ) { type = "direct"; name = currentChannel->getUsername(); } return server + "/" + type + "/" + name + "?msg=" + messageAtIndex->getId(); } case MessageRoles::replyDate: //TODO: implement or remove! break; } qWarning() << "MessagesModel data not found for row"; return QVariant(); } QString MessagesModel::getCurrent() const { return current; } void MessagesModel::setCurrent( const QString &value ) { QMutexLocker( &this->mutex ); current = value; beginResetModel(); if ( mChannelMap.contains( value ) ) { messagesOfCurrentChannel = mChannelMap[value]->getMessageRepo()->timestampIndex().values().toVector(); duplicateCheck.clear(); for ( auto currentMessage : messagesOfCurrentChannel ) { duplicateCheck.insert( currentMessage->getId() ); } } else { duplicateCheck.clear(); messagesOfCurrentChannel.clear(); /* QSharedPointer<RocketChatChannel> dummyChannel (new RocketChatChannel()); dummyChannel->setRoomId(value); addChannel(dummyChannel); */ } endResetModel(); emit countChanged(); } int MessagesModel::rowCount( const QModelIndex &parent ) const { Q_UNUSED( parent ); qDebug() << "number of messages in model" << messagesOfCurrentChannel.count(); int count = 0; if ( messagesOfCurrentChannel.isEmpty() ) { return 0; } count = messagesOfCurrentChannel.count(); return count; } int MessagesModel::getPositionOfMessage( const QString &pId ) { int pos = -1; for ( int i = 0; i < messagesOfCurrentChannel.size(); i++ ) { auto element = messagesOfCurrentChannel.at( i ); if ( element->getId() == pId ) { pos = i; break; } } return pos; } bool MessagesModel::addChannel( const QSharedPointer<RocketChatChannel> &channel ) { QString id = channel->getRoomId(); if ( mChannelMap.contains( id ) ) { return false; } mChannelMap.insert( id, channel ); connect( channel.data(), &RocketChatChannel::messageAdded, this, [ = ]( const QString & id, qint64 timestamp ) { Q_UNUSED( id ) onNewMessage( channel, timestamp ); } ); return true; } void MessagesModel::addBlockedUser( const QString &pUserId ) { beginResetModel(); mBlockedUsers.insert( pUserId ); endResetModel(); } QHash<int, QByteArray> MessagesModel::roleNames() const { QHash<int, QByteArray> roles; roles[static_cast<int>( MessageRoles::text )] = QByteArrayLiteral( "msg" ); roles[static_cast<int>( MessageRoles::author )] = QByteArrayLiteral( "author" ); roles[static_cast<int>( MessageRoles::authorId )] = QByteArrayLiteral( "authorId" ); roles[static_cast<int>( MessageRoles::linkurl )] = QByteArrayLiteral( "linkurl" ); roles[static_cast<int>( MessageRoles::type )] = QByteArrayLiteral( "type" ); roles[static_cast<int>( MessageRoles::date )] = QByteArrayLiteral( "date" ); roles[static_cast<int>( MessageRoles::time )] = QByteArrayLiteral( "time" ); roles[static_cast<int>( MessageRoles::ownMessage )] = QByteArrayLiteral( "ownMessage" ); roles[static_cast<int>( MessageRoles::height )] = QByteArrayLiteral( "height" ); roles[static_cast<int>( MessageRoles::width )] = QByteArrayLiteral( "width" ); roles[static_cast<int>( MessageRoles::formattedDate )] = QByteArrayLiteral( "formattedDate" ); roles[static_cast<int>( MessageRoles::formattedTime )] = QByteArrayLiteral( "formattedTime" ); roles[static_cast<int>( MessageRoles::messageType )] = QByteArrayLiteral( "messageType" ); roles[static_cast<int>( MessageRoles::blocked )] = QByteArrayLiteral( "blocked" ); roles[static_cast<int>( MessageRoles::id )] = QByteArrayLiteral( "id" ); roles[static_cast<int>( MessageRoles::replyMessage )] = QByteArrayLiteral( "replyMessage" ); roles[static_cast<int>( MessageRoles::replyAutor )] = QByteArrayLiteral( "replyAutor" ); roles[static_cast<int>( MessageRoles::replyDate )] = QByteArrayLiteral( "replyDate" ); roles[static_cast<int>( MessageRoles::replyUrl )] = QByteArrayLiteral( "replyUrl" ); return roles; } void MessagesModel::onNewMessage( const QSharedPointer<RocketChatChannel> &channel, qint64 timestamp ) { QMutexLocker( &this->mutex ); if ( timestamp == 0 ) { setCurrent( current ); } if ( channel->getRoomId() == current ) { auto message = channel->getMessageRepo()->timestampIndex()[timestamp]; if ( message.isNull() ) { return; } int row = messagesOfCurrentChannel.findPosition( message ); if ( !duplicateCheck.contains( message->getId() ) ) { beginInsertRows( QModelIndex(), row, row ); messagesOfCurrentChannel.insert( row, message ); mInsertCount++; endInsertRows(); duplicateCheck.insert( message->getId() ); } if ( !buffered ) { mInsertCount = 0; emit countChanged(); } } } void MessagesModel::onBeginInsertList( const QString &pChannelId ) { if ( pChannelId == current ) { buffered = true; mInsertCount = 0; } } void MessagesModel::onEndInsertList( const QString &pChannelId ) { if ( pChannelId == current ) { buffered = false; if ( mInsertCount ) { mInsertCount = 0; emit countChanged(); } } } void MessagesModel::addChannelSlot( const QSharedPointer<RocketChatChannel> &channel ) { addChannel( channel ); }