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

0001 /***************************************************************************
0002  *  Copyright (C) 2009 by Renaud Guezennec                             *
0003  *   https://rolisteam.org/contact                   *
0004  *                                                                         *
0005  *   Rolisteam 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/characterstatemodel.h"
0021 
0022 #include <QBuffer>
0023 #include <QColor>
0024 #include <QJsonArray>
0025 #include <QJsonObject>
0026 #include <algorithm>
0027 
0028 CharacterStateModel::CharacterStateModel(QObject* parent) : QAbstractListModel(parent)
0029 {
0030     m_header << tr("Label") << tr("Color") << tr("Image");
0031 }
0032 
0033 CharacterStateModel::~CharacterStateModel() {}
0034 
0035 int CharacterStateModel::columnCount(const QModelIndex&) const
0036 {
0037     return m_header.size();
0038 }
0039 QVariant CharacterStateModel::data(const QModelIndex& index, int role) const
0040 {
0041     if(!index.isValid())
0042         return {};
0043     QSet<int> allowedRole{Qt::EditRole, Qt::DisplayRole, Qt::BackgroundRole, LABEL, COLOR, PICTUREPATH, PICTURE, ID};
0044 
0045     if(!allowedRole.contains(role))
0046         return {};
0047 
0048     QVariant var;
0049     auto const& state= m_stateList[static_cast<std::size_t>(index.row())];
0050     auto c= index.column();
0051 
0052     int realRole= role;
0053     if(role < LABEL)
0054         realRole= LABEL + c;
0055 
0056     switch(realRole)
0057     {
0058     case LABEL:
0059         var= state->label();
0060         break;
0061     case ID:
0062         var= state->id();
0063         break;
0064     case COLOR:
0065         var= state->color();
0066         break;
0067     case PICTURE:
0068     {
0069         QPixmap map(state->imagePath());
0070         var= QVariant::fromValue(map);
0071     }
0072     break;
0073     case PICTUREPATH:
0074         var= state->imagePath();
0075         break;
0076     }
0077     return var;
0078 }
0079 int CharacterStateModel::rowCount(const QModelIndex& parent) const
0080 {
0081     if(!parent.isValid())
0082         return static_cast<int>(m_stateList.size());
0083     return 0;
0084 }
0085 
0086 QVariant CharacterStateModel::headerData(int section, Qt::Orientation orientation, int role) const
0087 {
0088     if(Qt::DisplayRole == role)
0089     {
0090         if(orientation == Qt::Horizontal)
0091         {
0092             return m_header.at(section);
0093         }
0094     }
0095     return QVariant();
0096 }
0097 int CharacterStateModel::indexFromId(const QString& id) const
0098 {
0099     auto it= std::find_if(std::begin(m_stateList), std::end(m_stateList),
0100                           [id](const std::unique_ptr<CharacterState>& state) { return id == state->id(); });
0101 
0102     if(it == std::end(m_stateList))
0103         return -1;
0104 
0105     return std::distance(std::begin(m_stateList), it);
0106 }
0107 /*void CharacterStateModel::setStates(QList<CharacterState*>* lst)
0108 {
0109     beginResetModel();
0110     std::transform(lst->begin(), lst->end(), std::back_inserter(m_stateList),
0111                    [](CharacterState* state) -> CharacterStateInfo {
0112                        CharacterStateInfo a= makeStateInfo(state, false);
0113                        // TODO c++14 list initializer
0114                        return a;
0115                    });
0116     endResetModel();
0117 }*/
0118 
0119 /*void CharacterStateModel::preferencesHasChanged(const QString& pref)
0120 {
0121     if(pref == "isPlayer")
0122     {
0123         // m_isGM= !PreferencesManager::getInstance()->value(pref, true).toBool();
0124     }
0125 }*/
0126 /*NetWorkReceiver::SendType CharacterStateModel::processMessage(NetworkMessageReader* msg)
0127 {
0128     NetWorkReceiver::SendType type= NetWorkReceiver::AllExceptSender;
0129 
0130     if(nullptr == msg)
0131         return NetWorkReceiver::NONE;
0132 
0133     switch(msg->action())
0134     {
0135     case NetMsg::addCharacterState:
0136         processAddState(msg);
0137         break;
0138     case NetMsg::removeCharacterState:
0139         processRemoveState(msg);
0140         break;
0141     case NetMsg::moveCharacterState:
0142         processMoveState(msg);
0143         break;
0144     case NetMsg::CharactereStateModel:
0145         processModelState(msg);
0146         break;
0147     default:
0148         break;
0149     }
0150 
0151     return type;
0152 }
0153 */
0154 
0155 void CharacterStateModel::appendState(CharacterState&& stateRef)
0156 {
0157     auto isInside= std::find_if(std::begin(m_stateList), std::end(m_stateList),
0158                                 [stateRef](const std::unique_ptr<CharacterState>& state)
0159                                 { return state->id() == stateRef.id(); });
0160 
0161     if(isInside != std::end(m_stateList))
0162         return;
0163 
0164     auto pos= static_cast<int>(m_stateList.size());
0165     beginInsertRows(QModelIndex(), pos, pos);
0166     m_stateList.push_back(std::make_unique<CharacterState>(stateRef));
0167     endInsertRows();
0168     auto const& it= m_stateList.end() - 1;
0169     emit characterStateAdded((*it).get(), pos);
0170 }
0171 Qt::ItemFlags CharacterStateModel::flags(const QModelIndex& index) const
0172 {
0173     if(!index.isValid())
0174         return Qt::NoItemFlags;
0175     return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled;
0176 }
0177 bool CharacterStateModel::setData(const QModelIndex& idx, const QVariant& value, int role)
0178 {
0179     bool result= false;
0180     if(!idx.isValid())
0181         return result;
0182 
0183     auto const& state= m_stateList[idx.row()];
0184     if(role != Qt::EditRole)
0185         return result;
0186 
0187     QVector<int> roles{LABEL, COLOR, PICTUREPATH, PICTURE, ID};
0188 
0189     switch(roles[idx.column()])
0190     {
0191     case LABEL:
0192         state->setLabel(value.toString());
0193         result= true;
0194         break;
0195     case COLOR:
0196         state->setColor(value.value<QColor>());
0197         result= true;
0198         break;
0199     case PICTUREPATH:
0200         state->setImagePath(value.toString());
0201         result= true;
0202         break;
0203     }
0204 
0205     emit dataChanged(index(idx.row(), 0), index(idx.row(), columnCount()),
0206                      QVector<int>() << role << roles[idx.column()]);
0207     emit stateChanged();
0208     return result;
0209 }
0210 
0211 const std::vector<std::unique_ptr<CharacterState>>& CharacterStateModel::statesList() const
0212 {
0213     return m_stateList;
0214 }
0215 void CharacterStateModel::deleteState(const QModelIndex& index)
0216 {
0217     if(!index.isValid())
0218         return;
0219     beginRemoveRows(QModelIndex(), index.row(), index.row());
0220     auto const& it= m_stateList.begin() + index.row();
0221     auto id= (*it)->id();
0222     m_stateList.erase(it);
0223     endRemoveRows();
0224 
0225     emit stateRemoved(id);
0226 }
0227 void CharacterStateModel::upState(const QModelIndex& index)
0228 {
0229     if(!index.isValid())
0230         return;
0231     if(index.row() == 0)
0232         return;
0233     if(beginMoveRows(QModelIndex(), index.row(), index.row(), QModelIndex(), index.row() - 1))
0234     {
0235         std::iter_swap(m_stateList.begin() + index.row(), m_stateList.begin() + index.row() - 1);
0236         endMoveRows();
0237         emit stateMoved(index.row(), index.row() - 1);
0238     }
0239 }
0240 
0241 void CharacterStateModel::downState(const QModelIndex& index)
0242 {
0243     if(!index.isValid())
0244         return;
0245 
0246     if(index.row() == static_cast<int>(m_stateList.size()) - 1)
0247         return;
0248 
0249     if(beginMoveRows(QModelIndex(), index.row(), index.row(), QModelIndex(), index.row() + 2))
0250     {
0251         std::iter_swap(m_stateList.begin() + index.row(), m_stateList.begin() + index.row() + 1);
0252         endMoveRows();
0253         emit stateMoved(index.row(), index.row() + 1);
0254     }
0255 }
0256 
0257 void CharacterStateModel::topState(const QModelIndex& index)
0258 {
0259     if(!index.isValid())
0260         return;
0261 
0262     if(index.row() == 0)
0263         return;
0264     if(beginMoveRows(QModelIndex(), index.row(), index.row(), QModelIndex(), 0))
0265     {
0266         std::iter_swap(m_stateList.begin(), m_stateList.begin() + index.row());
0267         endMoveRows();
0268         emit stateMoved(index.row(), 0);
0269     }
0270 }
0271 
0272 void CharacterStateModel::bottomState(const QModelIndex& index)
0273 {
0274     if(!index.isValid())
0275         return;
0276     auto size= static_cast<int>(m_stateList.size());
0277     if(index.row() == size - 1)
0278         return;
0279     if(beginMoveRows(QModelIndex(), index.row(), index.row(), QModelIndex(), size))
0280     {
0281         std::iter_swap(m_stateList.end() - 1, m_stateList.begin() + index.row());
0282         endMoveRows();
0283         emit stateMoved(index.row(), size);
0284     }
0285 }
0286 
0287 void CharacterStateModel::moveState(int from, int to)
0288 {
0289     if((from >= 0) && (from < static_cast<int>(m_stateList.size())))
0290     {
0291         beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
0292         std::iter_swap(m_stateList.begin() + to, m_stateList.begin() + from);
0293         endMoveRows();
0294     }
0295 }
0296 
0297 void CharacterStateModel::removeStateAt(int i)
0298 {
0299     deleteState(index(i, 0));
0300 }
0301 
0302 QString CharacterStateModel::stateLabelFromId(const QString& id)
0303 {
0304     if(id.isEmpty())
0305         return {};
0306 
0307     auto it= std::find_if(std::begin(m_stateList), std::end(m_stateList),
0308                           [id](const std::unique_ptr<CharacterState>& state) { return state->id() == id; });
0309 
0310     if(it == std::end(m_stateList))
0311         return {};
0312 
0313     return (*it)->label();
0314 }
0315 
0316 void CharacterStateModel::clear()
0317 {
0318     beginResetModel();
0319     m_stateList.clear();
0320     endResetModel();
0321 }
0322 /*
0323 void CharacterStateModel::processAddState(NetworkMessageReader* msg)
0324 {
0325     CharacterState* state= new CharacterState();
0326 
0327     quint64 id= msg->uint64();
0328     state->setLabel(msg->string32());
0329     state->setColor(msg->rgb());
0330     bool hasImage= static_cast<bool>(msg->uint8());
0331     if(hasImage)
0332     {
0333         QByteArray array= msg->byteArray32();
0334         QPixmap pix;
0335         pix.loadFromData(array);
0336         state->setImage(pix);
0337     }
0338     m_stateList.push_back(makeStateInfo(state, true));
0339 }
0340 void CharacterStateModel::processMoveState(NetworkMessageReader* msg)
0341 {
0342     int from= msg->int64();
0343     int to= msg->int64();
0344 
0345     if((from >= 0) && (from < m_stateList.size()))
0346     {
0347         beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
0348         std::iter_swap(m_stateList.begin() + to, m_stateList.begin() + from);
0349         endMoveRows();
0350     }
0351 }
0352 void CharacterStateModel::processRemoveState(NetworkMessageReader* msg)
0353 {
0354     int pos= static_cast<int>(msg->int64());
0355     if(m_stateList.size() < pos)
0356         return;
0357 
0358     beginRemoveRows(QModelIndex(), pos, pos);
0359     m_stateList.erase(m_stateList.begin() + pos);
0360     endRemoveRows();
0361 }
0362 
0363 void CharacterStateModel::sendOffAllCharacterState()
0364 {
0365      for(auto& state : *m_stateList)
0366       {
0367           NetworkMessageWriter msg(NetMsg::SharePreferencesCategory, NetMsg::addState);
0368           msg.uint64(m_stateList->indexOf(state));
0369           msg.string32(state->label());
0370           msg.rgb(state->getColor().rgb());
0371           if(state->hasImage())
0372           {
0373               msg.uint8(static_cast<quint8>(true));
0374 
0375               QByteArray array;
0376               QBuffer buffer(&array);
0377               if(!state->getPixmap()->save(&buffer, "PNG"))
0378               {
0379                   qWarning("error during encoding png");
0380               }
0381               msg.byteArray32(array);
0382           }
0383           else
0384           {
0385               msg.uint8(static_cast<quint8>(false));
0386           }
0387           msg.sendToServer();
0388       }
0389         if(result) // isGM
0390         {
0391             NetworkMessageWriter msg(NetMsg::SharePreferencesCategory, NetMsg::addCharacterState);
0392             msg.int64(index.row());
0393             msg.string32(stateInfo.state->label());
0394             msg.rgb(stateInfo.state->getColor().rgb());
0395             msg.uint8(stateInfo.state->hasImage());
0396             if(stateInfo.state->hasImage())
0397             {
0398                 auto img= stateInfo.state->getImage();
0399                 QByteArray array;
0400                 QBuffer buffer(&array);
0401                 img.save(&buffer, "PNG");
0402                 msg.byteArray32(array);
0403             }
0404             msg.sendToServer();
0405         }
0406 }*/
0407 
0408 // void CharacterStateModel::moveState(int from, int to)
0409 //{
0410 // if(m_isGM)
0411 // {
0412 /* NetworkMessageWriter msg(NetMsg::SharePreferencesCategory, NetMsg::moveCharacterState);
0413  msg.int64(from);
0414  msg.int64(to);
0415  msg.sendToServer();*/
0416 // }
0417 //}