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

0001 /***************************************************************************
0002  *  Copyright (C) 2021 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 "controller/antagonistboardcontroller.h"
0021 
0022 #include <data/campaign.h>
0023 #include <data/campaigneditor.h>
0024 #include <data/character.h>
0025 #include <worker/iohelper.h>
0026 
0027 namespace campaign
0028 {
0029 
0030 template <typename T>
0031 QList<CharacterField*> convertToGeneric(QList<T> list)
0032 {
0033     QList<CharacterField*> res;
0034 
0035     std::transform(std::begin(list), std::end(list), std::back_inserter(res),
0036                    [](T type)
0037                    {
0038                        CharacterField* tmp= type;
0039                        return tmp;
0040                    });
0041 
0042     return res;
0043 }
0044 
0045 template <typename T>
0046 QList<T> convertToSpecific(QList<CharacterField*> list)
0047 {
0048     QList<T> res;
0049 
0050     std::transform(std::begin(list), std::end(list), std::back_inserter(res),
0051                    [](CharacterField* type) { return dynamic_cast<T>(type); });
0052 
0053     return res;
0054 }
0055 /*
0056 template <typename T>
0057 bool isNull(const T& value);
0058 
0059 template <>
0060 bool isNull(const QPixmap& value)
0061 {
0062     return value.isNull();
0063 }
0064 template <>
0065 bool isNull(const QString& value)
0066 {
0067     return value.isEmpty();
0068 }
0069 
0070 template <>
0071 bool isNull(const int& value)
0072 {
0073     return value == 0;
0074 }
0075 
0076 template <>
0077 bool isNull(const bool& value)
0078 {
0079     return !value;
0080 }
0081 
0082 template <typename T>
0083 bool isAccepted(FilteredCharacterModel::Definition def, T value)
0084 {
0085     if(def == FilteredCharacterModel::All)
0086     {
0087         return true;
0088     }
0089     else if(def == FilteredCharacterModel::With)
0090     {
0091         return !isNull(value);
0092     }
0093     else
0094     {
0095         return isNull(value);
0096     }
0097 }
0098 */
0099 AntagonistBoardController::AntagonistBoardController(campaign::CampaignEditor* editor, QObject* parent)
0100     : QObject(parent)
0101     , m_editor(editor)
0102     , m_models{{new GenericModel({QStringLiteral("Name"), QStringLiteral("Command")}, {}, this),
0103                 new GenericModel({QStringLiteral("Name"), QStringLiteral("Uri")}, {1}, this),
0104                 new GenericModel({QStringLiteral("Name"), QStringLiteral("Value")}, {}, this)}}
0105     , m_filteredModel(new FilteredCharacterModel)
0106     , m_colorModel(new ColorModel)
0107     , m_stateModel(new StateModel)
0108 {
0109     if(m_editor)
0110     {
0111         auto campaign= m_editor->campaign();
0112         m_filteredModel->setSourceModel(campaign->npcModel());
0113         m_colorModel->setSourceModel(campaign->npcModel());
0114         m_stateModel->setSourceModel(campaign->npcModel());
0115         connect(
0116             campaign->npcModel(), &campaign::NonPlayableCharacterModel::modelReset, m_colorModel.get(),
0117             [this]()
0118             {
0119                 auto campaign= m_editor->campaign();
0120                 if(!campaign)
0121                     return;
0122 
0123                 m_colorModel->setSourceModel(campaign->npcModel());
0124                 m_stateModel->setSourceModel(campaign->npcModel());
0125             },
0126             Qt::QueuedConnection);
0127 
0128         connect(m_filteredModel.get(), &FilteredCharacterModel::searchChanged, this,
0129                 &AntagonistBoardController::searchTextChanged);
0130         connect(campaign, &campaign::Campaign::stateModelChanged, this,
0131                 &AntagonistBoardController::characterStateModelChanged);
0132         connect(campaign, &campaign::Campaign::stateModelChanged, this, &AntagonistBoardController::stateModelChanged);
0133     }
0134 }
0135 
0136 QString AntagonistBoardController::searchText() const
0137 {
0138     return m_filteredModel->search();
0139 }
0140 
0141 FilteredCharacterModel* AntagonistBoardController::filteredModel() const
0142 {
0143     return m_filteredModel.get();
0144 }
0145 
0146 GenericModel* AntagonistBoardController::actionModel() const
0147 {
0148     return m_models[static_cast<int>(ModelType::Model_Action)];
0149 }
0150 
0151 GenericModel* AntagonistBoardController::shapeModel() const
0152 {
0153     return m_models[static_cast<int>(ModelType::Model_Shape)];
0154 }
0155 
0156 GenericModel* AntagonistBoardController::propertyModel() const
0157 {
0158     return m_models[static_cast<int>(ModelType::Model_Properties)];
0159 }
0160 
0161 bool AntagonistBoardController::editingCharacter() const
0162 {
0163     return !m_character.isNull();
0164 }
0165 NonPlayableCharacter* AntagonistBoardController::character() const
0166 {
0167     return m_character;
0168 }
0169 
0170 void AntagonistBoardController::removeData(const QModelIndex& index, campaign::ModelType type)
0171 {
0172     if(!index.isValid())
0173         return;
0174 
0175     m_models[static_cast<int>(type)]->removeData(index);
0176 }
0177 
0178 void AntagonistBoardController::appendData(ModelType type)
0179 {
0180     switch(type)
0181     {
0182     case ModelType::Model_Action:
0183         m_models[static_cast<int>(type)]->addData(new CharacterAction);
0184         break;
0185     case ModelType::Model_Properties:
0186         m_models[static_cast<int>(type)]->addData(new CharacterProperty);
0187         break;
0188     case ModelType::Model_Shape:
0189         m_models[static_cast<int>(type)]->addData(new CharacterShape);
0190         break;
0191     }
0192 }
0193 
0194 void AntagonistBoardController::editCharacter(const QString& id)
0195 {
0196     auto campaign= m_editor->campaign();
0197     auto const& list= campaign->npcModel()->npcList();
0198     auto it= std::find_if(std::begin(list), std::end(list),
0199                           [id](const std::unique_ptr<NonPlayableCharacter>& npc) { return npc->uuid() == id; });
0200 
0201     if(it == std::end(list))
0202         return;
0203 
0204     setCharacter((*it).get());
0205 }
0206 
0207 void AntagonistBoardController::setCharacter(NonPlayableCharacter* character)
0208 {
0209     if(character == m_character)
0210         return;
0211     m_character= character;
0212 
0213     if(m_character)
0214     {
0215         auto actMo= actionModel();
0216         actMo->resetData(convertToGeneric<CharacterAction*>(character->actionList()));
0217 
0218         auto pros= propertyModel();
0219         pros->resetData(convertToGeneric<CharacterProperty*>(character->propertiesList()));
0220 
0221         auto shapes= shapeModel();
0222         shapes->resetData(convertToGeneric<CharacterShape*>(character->shapeList()));
0223     }
0224 
0225     emit characterChanged();
0226 }
0227 
0228 void AntagonistBoardController::saveToken()
0229 {
0230     if(!m_character)
0231         return;
0232 
0233     m_character->defineActionList(convertToSpecific<CharacterAction*>(actionModel()->fields()));
0234     m_character->definePropertiesList(convertToSpecific<CharacterProperty*>(propertyModel()->fields()));
0235     m_character->defineShapeList(convertToSpecific<CharacterShape*>(shapeModel()->fields()));
0236 
0237     auto model= m_editor->campaign()->npcModel();
0238     model->refresh(m_character->uuid());
0239 
0240     setCharacter(nullptr);
0241 }
0242 
0243 void AntagonistBoardController::addCharacter()
0244 {
0245     m_editor->campaign()->addCharacter();
0246 }
0247 
0248 void AntagonistBoardController::changeImage(const QString& id, const QByteArray& data)
0249 {
0250     auto campaign= m_editor->campaign();
0251     auto const& model= campaign->npcModel();
0252     auto index= model->indexFromUuid(id);
0253     auto path= m_editor->saveAvatar(id, data);
0254     model->setData(index, data, NonPlayableCharacterModel::RoleAvatar);
0255     model->setData(index, path, NonPlayableCharacterModel::RoleAvatarPath);
0256 }
0257 
0258 QString AntagonistBoardController::imageFolder() const
0259 {
0260     return m_editor->campaign()->directory(campaign::Campaign::Place::MEDIA_ROOT);
0261 }
0262 
0263 void AntagonistBoardController::removeCharacter(const QString& id)
0264 {
0265     m_editor->campaign()->removeCharacter(id);
0266 }
0267 
0268 void AntagonistBoardController::setSearchText(const QString& text)
0269 {
0270     m_filteredModel->setSearch(text);
0271 }
0272 
0273 FilteredCharacterModel::Definition FilteredCharacterModel::gmdetailsDef() const
0274 {
0275     return m_gmdetailsDef;
0276 }
0277 
0278 void FilteredCharacterModel::setGmdetailsDef(FilteredCharacterModel::Definition newGmdetailsDef)
0279 {
0280     if(m_gmdetailsDef == newGmdetailsDef)
0281         return;
0282     m_gmdetailsDef= newGmdetailsDef;
0283     emit gmdetailsDefChanged();
0284 }
0285 
0286 const QString& FilteredCharacterModel::gmdetails() const
0287 {
0288     return m_gmdetails;
0289 }
0290 
0291 void FilteredCharacterModel::setGmdetails(const QString& newGmdetails)
0292 {
0293     if(m_gmdetails == newGmdetails)
0294         return;
0295     m_gmdetails= newGmdetails;
0296     emit gmdetailsChanged();
0297 }
0298 
0299 FilteredCharacterModel::HealthState FilteredCharacterModel::hlState() const
0300 {
0301     return m_hlState;
0302 }
0303 
0304 void FilteredCharacterModel::setHlState(FilteredCharacterModel::HealthState newHlState)
0305 {
0306     if(m_hlState == newHlState)
0307         return;
0308     m_hlState= newHlState;
0309     emit hlStateChanged();
0310 }
0311 
0312 ColorModel* AntagonistBoardController::colorModel() const
0313 {
0314     return m_colorModel.get();
0315 }
0316 
0317 StateModel* AntagonistBoardController::stateModel() const
0318 {
0319     return m_stateModel.get();
0320 }
0321 
0322 CharacterStateModel* AntagonistBoardController::characterStateModel() const
0323 {
0324     if(!m_editor)
0325         return nullptr;
0326 
0327     auto camp= m_editor->campaign();
0328     if(!camp)
0329         return nullptr;
0330 
0331     return camp->stateModel();
0332 }
0333 
0334 } // namespace campaign