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

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/participantmodel.h"
0021 
0022 #include <QDebug>
0023 #include <QFont>
0024 #include <QJsonArray>
0025 #include <QJsonObject>
0026 
0027 #include "data/person.h"
0028 #include "data/player.h"
0029 #include "model/playermodel.h"
0030 
0031 Player* findPlayer(const QString& id, PlayerModel* model)
0032 {
0033     if(model == nullptr)
0034         return nullptr;
0035 
0036     return model->playerById(id);
0037 }
0038 
0039 ParticipantItem* findItem(const QString& id, ParticipantItem* root)
0040 {
0041     ParticipantItem* wantedItem= nullptr;
0042     for(int i= 0; i < root->childCount(); ++i)
0043     {
0044         auto item= root->childAt(i);
0045         for(int j= 0; j < item->childCount(); ++j)
0046         {
0047             auto child= item->childAt(j);
0048             if(nullptr == child)
0049                 continue;
0050             if(child->player()->uuid() == id)
0051             {
0052                 wantedItem= child;
0053             }
0054         }
0055     }
0056     return wantedItem;
0057 }
0058 ParticipantItem::ParticipantItem(const QString& name) : m_name(name) {}
0059 
0060 ParticipantItem::ParticipantItem(Player* player) : m_player(player) {}
0061 
0062 bool ParticipantItem::isLeaf() const
0063 {
0064     return (m_player != nullptr);
0065 }
0066 
0067 QString ParticipantItem::name() const
0068 {
0069     return isLeaf() ? m_player->name() : m_name;
0070 }
0071 
0072 QString ParticipantItem::uuid() const
0073 {
0074     return isLeaf() ? m_player->uuid() : QString();
0075 }
0076 
0077 Player* ParticipantItem::player() const
0078 {
0079     return m_player;
0080 }
0081 
0082 int ParticipantItem::indexOf(ParticipantItem* child)
0083 {
0084     return m_children.indexOf(child);
0085 }
0086 
0087 int ParticipantItem::childCount() const
0088 {
0089     return m_children.size();
0090 }
0091 
0092 ParticipantItem* ParticipantItem::childAt(int pos)
0093 {
0094     if(qBound(0, pos, m_children.size() - 1) != pos)
0095         return nullptr;
0096     return m_children.at(pos);
0097 }
0098 
0099 void ParticipantItem::appendChild(ParticipantItem* item)
0100 {
0101     m_children.append(item);
0102     item->setParent(this);
0103 }
0104 
0105 void ParticipantItem::removeChild(ParticipantItem* item)
0106 {
0107     m_children.removeOne(item);
0108 }
0109 
0110 ParticipantItem* ParticipantItem::parent() const
0111 {
0112     return m_parent;
0113 }
0114 
0115 void ParticipantItem::setParent(ParticipantItem* parent)
0116 {
0117     m_parent= parent;
0118 }
0119 
0120 ParticipantModel::ParticipantModel(const QString& ownerId, PlayerModel* model, QObject* parent)
0121     : QAbstractItemModel(parent), m_playerList(model), m_root(new ParticipantItem(QString())), m_ownerId(ownerId)
0122 {
0123     connect(model, &PlayerModel::playerJoin, this, &ParticipantModel::addNewPlayer);
0124     connect(model, &PlayerModel::playerLeft, this, &ParticipantModel::removePlayer);
0125 
0126     m_root->appendChild(new ParticipantItem(tr("Read Write")));
0127     m_root->appendChild(new ParticipantItem(tr("Read Only")));
0128     m_root->appendChild(new ParticipantItem(tr("Hidden")));
0129 
0130     initModel();
0131 }
0132 
0133 QVariant ParticipantModel::headerData(int section, Qt::Orientation orientation, int role) const
0134 {
0135     return QVariant();
0136 }
0137 
0138 void ParticipantModel::initModel()
0139 {
0140     if(m_ownerId.isEmpty())
0141         return;
0142 
0143     beginResetModel();
0144     auto c= m_playerList->rowCount();
0145     for(int i= 0; i < c; ++i)
0146     {
0147         auto idx= m_playerList->index(i, 0, QModelIndex());
0148         auto uuid= idx.data(PlayerModel::IdentifierRole).toString();
0149         auto player= dynamic_cast<Player*>(idx.data(PlayerModel::PersonPtrRole).value<Person*>());
0150 
0151         auto dest= m_root->childAt(hidden);
0152         if(uuid == m_ownerId)
0153             dest= m_root->childAt(readWrite);
0154 
0155         dest->appendChild(new ParticipantItem(player));
0156     }
0157     endResetModel();
0158 }
0159 
0160 QModelIndex ParticipantModel::index(int row, int column, const QModelIndex& parent) const
0161 {
0162     if(!parent.isValid())
0163     {
0164         auto p= m_root->childAt(row);
0165         return createIndex(row, column, p);
0166     }
0167     else
0168     {
0169 
0170         auto p= m_root->childAt(parent.row());
0171         auto data= p->childAt(row);
0172         return createIndex(row, column, data);
0173     }
0174 }
0175 
0176 QModelIndex ParticipantModel::parent(const QModelIndex& index) const
0177 {
0178     if(!index.isValid())
0179         return QModelIndex();
0180 
0181     auto item= static_cast<ParticipantItem*>(index.internalPointer());
0182 
0183     if(item == nullptr)
0184         return {};
0185 
0186     if(!item->isLeaf())
0187         return QModelIndex();
0188 
0189     auto parentItem= item->parent();
0190 
0191     if(parentItem == nullptr)
0192         return {};
0193 
0194     return createIndex(m_root->indexOf(parentItem), 0, parentItem);
0195 }
0196 
0197 int ParticipantModel::rowCount(const QModelIndex& parent) const
0198 {
0199     if(!parent.isValid())
0200         return m_root->childCount();
0201 
0202     auto item= static_cast<ParticipantItem*>(parent.internalPointer());
0203 
0204     if(item->isLeaf())
0205         return 0;
0206 
0207     return item->childCount();
0208 }
0209 
0210 int ParticipantModel::columnCount(const QModelIndex& parent) const
0211 {
0212     return 1;
0213 }
0214 
0215 QVariant ParticipantModel::data(const QModelIndex& index, int role) const
0216 {
0217     if(!index.isValid())
0218         return QVariant();
0219 
0220     if(role != Qt::DisplayRole && role != Qt::EditRole && role != Qt::FontRole)
0221         return {};
0222 
0223     auto item= static_cast<ParticipantItem*>(index.internalPointer());
0224 
0225     if(item->uuid() == m_ownerId && role == Qt::FontRole)
0226     {
0227         QFont font;
0228         font.setBold(true);
0229         return font;
0230     }
0231     else if(role == Qt::FontRole)
0232         return {};
0233 
0234     return item->name();
0235 }
0236 
0237 Qt::ItemFlags ParticipantModel::flags(const QModelIndex& index) const
0238 {
0239     if(!index.isValid())
0240         return Qt::NoItemFlags;
0241     if(index.parent().isValid())
0242         return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled;
0243     else
0244         return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
0245 }
0246 
0247 void ParticipantModel::addNewPlayer(Player* player)
0248 {
0249     if(nullptr == player)
0250         return;
0251 
0252     auto catInt= hidden;
0253     if(player->uuid() == m_ownerId)
0254         catInt= readWrite;
0255     auto permData= m_root->childAt(catInt);
0256     auto parent= createIndex(static_cast<int>(catInt), 0, permData);
0257     beginInsertRows(parent, permData->childCount(), permData->childCount());
0258     permData->appendChild(new ParticipantItem(player));
0259     endInsertRows();
0260 }
0261 
0262 void ParticipantModel::removePlayer(Player* player)
0263 {
0264     if(nullptr == player)
0265         return;
0266 
0267     ParticipantItem* origin= nullptr;
0268     ParticipantItem* parent= nullptr;
0269     for(int i= 0; i < m_root->childCount(); ++i)
0270     {
0271         auto item= m_root->childAt(i);
0272         for(int j= 0; j < item->childCount(); ++j)
0273         {
0274             auto child= item->childAt(j);
0275             if(child->player() == player)
0276             {
0277                 origin= child;
0278                 parent= item;
0279             }
0280         }
0281     }
0282 
0283     if(origin == nullptr || parent == nullptr)
0284         return;
0285 
0286     auto pos= parent->indexOf(origin);
0287     auto parentIdx= createIndex(m_root->indexOf(parent), 0, parent);
0288     beginRemoveRows(parentIdx, pos, pos);
0289     parent->removeChild(origin);
0290     endRemoveRows();
0291 }
0292 
0293 int ParticipantModel::promotePlayer(const QModelIndex& index)
0294 {
0295     ParticipantModel::Permission perm= permissionFor(index);
0296     switch(perm)
0297     {
0298     case readOnly:
0299     case hidden:
0300         setPlayerInto(index, static_cast<Permission>(perm - 1));
0301         return static_cast<Permission>(perm - 1);
0302     default:
0303         break;
0304     }
0305     return -1;
0306 }
0307 
0308 int ParticipantModel::demotePlayer(const QModelIndex& index)
0309 {
0310     if(!index.isValid())
0311         return 0;
0312 
0313     ParticipantModel::Permission perm= permissionFor(index);
0314     switch(perm)
0315     {
0316     case readOnly:
0317     case readWrite:
0318         setPlayerInto(index, static_cast<Permission>(perm + 1));
0319         return static_cast<Permission>(perm + 1);
0320     default:
0321         break;
0322     }
0323     return -1;
0324 }
0325 QString ParticipantModel::getOwner() const
0326 {
0327     return m_ownerId;
0328 }
0329 
0330 void ParticipantModel::setOwner(const QString& owner)
0331 {
0332     if(owner == m_ownerId)
0333         return;
0334     m_ownerId= owner;
0335     initModel();
0336 }
0337 ParticipantModel::Permission ParticipantModel::permissionFor(const QModelIndex& index)
0338 {
0339     if(!index.isValid())
0340         return hidden;
0341 
0342     auto parent= index.parent();
0343     if(!parent.isValid())
0344         return hidden;
0345 
0346     return static_cast<Permission>(parent.row());
0347 }
0348 
0349 ParticipantModel::Permission ParticipantModel::permissionFor(const QString& id)
0350 {
0351     auto item= findItem(id, m_root.get());
0352     if(!item)
0353         return hidden;
0354     auto parent= item->parent();
0355     auto val= m_root->indexOf(parent);
0356 
0357     if(val < 0)
0358         return hidden;
0359 
0360     return static_cast<ParticipantModel::Permission>(val);
0361 }
0362 
0363 void ParticipantModel::setPlayerInto(const QModelIndex& index, Permission level)
0364 {
0365     QModelIndex parent= index.parent();
0366     if(!parent.isValid())
0367         return;
0368 
0369     auto item= static_cast<ParticipantItem*>(index.internalPointer());
0370     if(item == nullptr)
0371         return;
0372 
0373     QModelIndex destParent= createIndex(static_cast<int>(level), 0, m_root.get());
0374 
0375     auto r= rowCount(destParent);
0376     auto perm= m_root->childAt(level);
0377     auto permSource= static_cast<ParticipantItem*>(parent.internalPointer());
0378 
0379     QString id;
0380     auto p= item->player();
0381     if(nullptr != p)
0382         id= p->uuid();
0383 
0384     if(id == m_ownerId)
0385         return;
0386 
0387     beginMoveRows(parent, index.row(), index.row(), destParent, r);
0388     permSource->removeChild(item);
0389     perm->appendChild(item);
0390     endMoveRows();
0391 
0392     auto hideRoot= m_root->childAt(hidden);
0393     auto roRoot= m_root->childAt(readOnly);
0394     auto rwRoot= m_root->childAt(readWrite);
0395 
0396     if(permSource == hideRoot && perm == roRoot)
0397         emit userReadPermissionChanged(id, true);
0398     else if(permSource == roRoot && perm == hideRoot)
0399         emit userReadPermissionChanged(id, false);
0400 
0401     if(permSource == roRoot && perm == rwRoot)
0402         emit userWritePermissionChanged(id, true);
0403     else if(permSource == rwRoot && perm == roRoot)
0404         emit userWritePermissionChanged(id, false);
0405 }
0406 
0407 void ParticipantModel::setPlayerPermission(const QString& id, ParticipantModel::Permission level)
0408 {
0409     auto item= findItem(id, m_root.get());
0410     if(!item)
0411         return;
0412     auto parent= item->parent();
0413     auto parentIdx= index(m_root->indexOf(parent), 0, QModelIndex());
0414     auto itemIdx= index(parent->indexOf(item), 0, parentIdx);
0415     setPlayerInto(itemIdx, level);
0416 }
0417 
0418 void ParticipantModel::saveModel(QJsonObject& root)
0419 {
0420 
0421     QJsonArray array;
0422     for(int i= 0; i < m_root->childCount(); ++i)
0423     {
0424         auto child= m_root->childAt(i);
0425         auto perm= readWrite;
0426         if(i == 1)
0427             perm= readOnly;
0428         else if(i == 2)
0429             perm= hidden;
0430 
0431         for(int j= 0; j < child->childCount(); ++j)
0432         {
0433             auto leaf= child->childAt(j);
0434             QJsonObject obj;
0435             obj["id"]= leaf->uuid();
0436             obj["perm"]= perm;
0437             array.append(obj);
0438         }
0439     }
0440     root["data"]= array;
0441 }
0442 void ParticipantModel::loadModel(QJsonObject& root)
0443 {
0444     /*PlayerModel* playerList= PlayerModel::instance();
0445 
0446     QJsonArray hidden= root["hidden"].toArray();
0447     QJsonArray readOnly= root["readOnly"].toArray();
0448     QJsonArray readWrite= root["readWrite"].toArray();
0449 
0450     beginResetModel();
0451 
0452     m_hidden.clear();
0453     m_readOnly.clear();
0454     m_readWrite.clear();
0455 
0456     for(auto playerId : hidden)
0457     {
0458         Player* p= dynamic_cast<Player*>(playerList->getPerson(playerId.toString()));
0459         m_hidden.append(p);
0460     }
0461 
0462     for(auto playerId : readOnly)
0463     {
0464         Player* p= dynamic_cast<Player*>(playerList->getPerson(playerId.toString()));
0465         m_readOnly.append(p);
0466     }
0467 
0468     for(auto playerId : readWrite)
0469     {
0470         Player* p= dynamic_cast<Player*>(playerList->getPerson(playerId.toString()));
0471         m_readWrite.append(p);
0472     }
0473     endResetModel();*/
0474 }