File indexing completed on 2024-05-05 05:40:28

0001 /***************************************************************************
0002  *  Copyright (C) 2020 by Renaud Guezennec                               *
0003  *   http://www.rolisteam.org/contact                                      *
0004  *                                                                         *
0005  *   This software is free software; you can redistribute it and/or modify *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 #include "model/instantmessagingmodel.h"
0021 
0022 #include <QDebug>
0023 #include <set>
0024 
0025 #include "data/chatroom.h"
0026 #include "data/chatroomfactory.h"
0027 #include "instantmessaging/messageinterface.h"
0028 #include "model/playermodel.h"
0029 #include <diceparser_qobject/diceroller.h>
0030 
0031 namespace InstantMessaging
0032 {
0033 namespace
0034 {
0035 bool isClosable(ChatRoom* chatroom)
0036 {
0037     return (chatroom->type() == ChatRoom::EXTRA
0038             || (chatroom->type() == ChatRoom::GLOBAL && chatroom->uuid() != QStringLiteral("global")));
0039 }
0040 } // namespace
0041 InstantMessagingModel::InstantMessagingModel(DiceRoller* diceRoller, PlayerModel* playerModel, QObject* parent)
0042     : QAbstractListModel(parent), m_personModel(playerModel), m_diceParser(diceRoller)
0043 {
0044 }
0045 
0046 InstantMessagingModel::~InstantMessagingModel()= default;
0047 
0048 int InstantMessagingModel::rowCount(const QModelIndex& parent) const
0049 {
0050     if(parent.isValid())
0051         return 0;
0052 
0053     return static_cast<int>(m_chats.size());
0054 }
0055 
0056 QVariant InstantMessagingModel::data(const QModelIndex& index, int role) const
0057 {
0058     if(!index.isValid())
0059         return QVariant();
0060 
0061     int item= role;
0062     if(role == Qt::DisplayRole)
0063         item= TitleRole;
0064 
0065     std::set<int> map({TitleRole, ChatRole, RecipiantCountRole, IdRole, HasUnreadMessageRole, ClosableRole});
0066 
0067     if(map.find(item) == map.end())
0068         return {};
0069 
0070     QVariant var;
0071     auto chatroom= m_chats[static_cast<std::size_t>(index.row())].get();
0072 
0073     switch(item)
0074     {
0075     case TitleRole:
0076         var= chatroom->title();
0077         break;
0078     case ChatRole:
0079         var= QVariant::fromValue(chatroom);
0080         break;
0081     case IdRole:
0082         var= chatroom->uuid();
0083         break;
0084     case TypeRole:
0085         var= chatroom->type();
0086         break;
0087     case HasUnreadMessageRole:
0088         var= chatroom->unreadMessage();
0089         break;
0090     case RecipiantCountRole:
0091         var= chatroom->recipiantCount();
0092         break;
0093     case ClosableRole:
0094         var= isClosable(chatroom);
0095         break;
0096     }
0097 
0098     return var;
0099 }
0100 
0101 QHash<int, QByteArray> InstantMessagingModel::roleNames() const
0102 {
0103     return QHash<int, QByteArray>({{TitleRole, "title"},
0104                                    {ChatRole, "chatroom"},
0105                                    {IdRole, "id"},
0106                                    {ClosableRole, "closable"},
0107                                    {HasUnreadMessageRole, "unread"},
0108                                    {RecipiantCountRole, "recipiantCount"}});
0109 }
0110 
0111 InstantMessaging::ChatRoom* InstantMessagingModel::globalChatRoom() const
0112 {
0113     Q_ASSERT(m_chats.size() > 0);
0114     return m_chats[0].get();
0115 }
0116 
0117 QString InstantMessagingModel::localId() const
0118 {
0119     return m_localId;
0120 }
0121 
0122 bool InstantMessagingModel::unread() const
0123 {
0124     return std::any_of(std::begin(m_chats), std::end(m_chats),
0125                        [](const std::unique_ptr<ChatRoom>& room) { return room->unreadMessage(); });
0126 }
0127 
0128 void InstantMessagingModel::insertGlobalChatroom(const QString& title, const QString& uuid)
0129 {
0130     addChatRoom(ChatRoomFactory::createChatRoom(title, QStringList(), uuid, InstantMessaging::ChatRoom::GLOBAL,
0131                                                 localId(), m_personModel, this),
0132                 !uuid.isEmpty());
0133 }
0134 
0135 void InstantMessagingModel::insertIndividualChatroom(const QString& playerId, const QString& playerName)
0136 {
0137     addChatRoom(ChatRoomFactory::createChatRoom(playerName, {playerId, localId()}, playerId,
0138                                                 InstantMessaging::ChatRoom::SINGLEPLAYER, localId(), m_personModel,
0139                                                 this));
0140 }
0141 
0142 void InstantMessagingModel::insertExtraChatroom(const QString& title, const QStringList& playerIds, bool remote,
0143                                                 const QString& uuid)
0144 {
0145     addChatRoom(ChatRoomFactory::createChatRoom(title, playerIds, uuid, InstantMessaging::ChatRoom::EXTRA, localId(),
0146                                                 m_personModel, this),
0147                 remote);
0148 }
0149 
0150 void InstantMessagingModel::addChatRoom(ChatRoom* room, bool remote)
0151 {
0152     if(!room)
0153         return;
0154 
0155     std::unique_ptr<ChatRoom> chatroom(room);
0156     connect(this, &InstantMessagingModel::localIdChanged, chatroom.get(), &ChatRoom::setLocalId);
0157 
0158     connect(room, &ChatRoom::unreadMessageChanged, this,
0159             [room, this]()
0160             {
0161                 auto it= std::find_if(m_chats.begin(), m_chats.end(),
0162                                       [room](const std::unique_ptr<ChatRoom>& chatRoom)
0163                                       { return room == chatRoom.get(); });
0164                 auto idx= static_cast<int>(std::distance(m_chats.begin(), it));
0165                 emit dataChanged(index(idx, 0, QModelIndex()), index(idx, 0, QModelIndex()),
0166                                  {HasUnreadMessageRole, TitleRole});
0167                 emit unreadChanged();
0168             });
0169     chatroom->setLocalId(localId());
0170     chatroom->setDiceParser(m_diceParser);
0171 
0172     auto size= static_cast<int>(m_chats.size());
0173     beginInsertRows(QModelIndex(), size, size);
0174     m_chats.push_back(std::move(chatroom));
0175     endInsertRows();
0176 
0177     emit chatRoomCreated(room, remote);
0178 }
0179 
0180 void InstantMessagingModel::setLocalId(const QString& id)
0181 {
0182     if(m_localId == id)
0183         return;
0184     m_localId= id;
0185     emit localIdChanged(m_localId);
0186 }
0187 
0188 void InstantMessagingModel::addMessageIntoChatroom(MessageInterface* message, ChatRoom::ChatRoomType type,
0189                                                    const QString& uuid)
0190 { // from network
0191     auto it= std::find_if(m_chats.begin(), m_chats.end(),
0192                           [type, uuid, message](const std::unique_ptr<ChatRoom>& chatRoom)
0193                           {
0194                               bool val= false;
0195                               if(chatRoom->uuid() == uuid) // global and Extra chatrom
0196                                   val= true;
0197                               else if(type == ChatRoom::SINGLEPLAYER && type == chatRoom->type()
0198                                       && chatRoom->uuid() == message->owner()) // SinglePlayer chat room
0199                                   val= true;
0200                               return val;
0201                           });
0202 
0203     if(it == m_chats.end())
0204         return;
0205 
0206     (*it)->addMessageInterface(message);
0207     /*  auto idx = std::distance(m_chats.begin(), it);
0208       emit dataChanged(index(idx, 0, QModelIndex()), index(idx, 0, QModelIndex()),
0209           {HasUnreadMessageRole, TitleRole});*/
0210 }
0211 
0212 void InstantMessagingModel::removePlayer(const QString& id)
0213 {
0214     auto it= std::find_if(m_chats.begin(), m_chats.end(),
0215                           [id](const std::unique_ptr<ChatRoom>& chatRoom)
0216                           { return (chatRoom->uuid() == id && ChatRoom::SINGLEPLAYER && chatRoom->type()); });
0217 
0218     if(it == m_chats.end())
0219         return;
0220 
0221     auto idx= static_cast<int>(std::distance(m_chats.begin(), it));
0222 
0223     beginRemoveRows(QModelIndex(), idx, idx);
0224     m_chats.erase(it);
0225     endRemoveRows();
0226 }
0227 
0228 void InstantMessagingModel::setDiceParser(DiceRoller* diceParser)
0229 {
0230     m_diceParser= diceParser;
0231     std::for_each(m_chats.begin(), m_chats.end(),
0232                   [this](const std::unique_ptr<ChatRoom>& chatRoom) { chatRoom->setDiceParser(m_diceParser); });
0233 }
0234 } // namespace InstantMessaging