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

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 "data/campaign.h"
0021 
0022 #include <QFileInfo>
0023 
0024 #include <QFileInfo>
0025 
0026 #include "data/media.h"
0027 #include "diceparser/dicealias.h"
0028 #include "worker/characterfinder.h"
0029 
0030 namespace campaign
0031 {
0032 
0033 qint64 fileSize(const QString& path)
0034 {
0035     QFileInfo info(path);
0036     return info.size();
0037 }
0038 
0039 Campaign::Campaign(QObject* parent)
0040     : QObject(parent)
0041     , m_diceModel(new DiceAliasModel)
0042     , m_stateModel(new CharacterStateModel)
0043     , m_npcModel(new campaign::NonPlayableCharacterModel(m_stateModel.get()))
0044 {
0045     CharacterFinder::setNpcModel(m_npcModel.get());
0046     connect(this, &Campaign::mediaAdded, this, &Campaign::diskUsageChanged);
0047     connect(this, &Campaign::mediaRemoved, this, &Campaign::fileCountChanged);
0048     connect(this, &Campaign::mediaAdded, this, &Campaign::diskUsageChanged);
0049     connect(this, &Campaign::mediaRemoved, this, &Campaign::fileCountChanged);
0050     connect(this, &Campaign::rootDirectoryChanged, this,
0051             [this]() { m_npcModel->setNpcRoot(directory(Place::NPC_ROOT)); });
0052 }
0053 
0054 QString Campaign::name() const
0055 {
0056     return m_name.isEmpty() ? tr("Unknown") : m_name;
0057 }
0058 
0059 Campaign::~Campaign()= default;
0060 
0061 QString Campaign::rootDirectory() const
0062 {
0063     return m_root;
0064 }
0065 
0066 QString Campaign::currentChapter() const
0067 {
0068     return m_currentChapter;
0069 }
0070 
0071 DiceAliasModel* Campaign::diceAliases() const
0072 {
0073     return m_diceModel.get();
0074 }
0075 
0076 NonPlayableCharacterModel* Campaign::npcModel() const
0077 {
0078     return m_npcModel.get();
0079 }
0080 
0081 CharacterStateModel* Campaign::stateModel() const
0082 {
0083     return m_stateModel.get();
0084 }
0085 
0086 RolisteamTheme* Campaign::currentTheme() const
0087 {
0088     return m_theme.get();
0089 }
0090 
0091 Campaign::State Campaign::state() const
0092 {
0093     return m_state;
0094 }
0095 
0096 qint64 Campaign::diskUsage() const
0097 {
0098     qint64 res= 0;
0099     res= std::accumulate(std::begin(m_mediaList), std::end(m_mediaList), 0,
0100                          [](qint64 b, const std::unique_ptr<Media>& media) { return b + fileSize(media->path()); });
0101 
0102     return res;
0103 }
0104 
0105 int Campaign::fileCount() const
0106 {
0107     return static_cast<int>(m_mediaList.size());
0108 }
0109 
0110 QString Campaign::currentStorePath() const
0111 {
0112     QStringList list{m_root, m_currentChapter};
0113     return list.join("/");
0114 }
0115 
0116 void Campaign::addMedia(std::unique_ptr<Media>&& media)
0117 {
0118     if(nullptr != mediaFromPath(media->path()))
0119         return;
0120 
0121     auto p= media.get();
0122     m_mediaList.push_back(std::move(media));
0123     connect(p, &Media::pathChanged, this, &Campaign::mediaNameChanged);
0124     emit mediaAdded(p);
0125 }
0126 
0127 void Campaign::renameMedia(const QString& id, const QString& path)
0128 {
0129     auto it= std::find_if(std::begin(m_mediaList), std::end(m_mediaList),
0130                           [id](const std::unique_ptr<campaign::Media>& p) { return id == p->id(); });
0131 
0132     if(it == std::end(m_mediaList))
0133         return;
0134 
0135     (*it)->setPath(path);
0136     emit mediaNameChanged();
0137 }
0138 void Campaign::removeMedia(const QString& id)
0139 {
0140     auto it= std::find_if(std::begin(m_mediaList), std::end(m_mediaList),
0141                           [id](const std::unique_ptr<campaign::Media>& p) { return id == p->id(); });
0142     if(it == std::end(m_mediaList))
0143         return;
0144 
0145     emit mediaRemoved(id);
0146     m_mediaList.erase(it);
0147 }
0148 
0149 const std::vector<std::unique_ptr<Media>>& Campaign::medias() const
0150 {
0151     return m_mediaList;
0152 }
0153 
0154 Media* Campaign::mediaFromPath(const QString& path) const
0155 {
0156     auto it= std::find_if(std::begin(m_mediaList), std::end(m_mediaList),
0157                           [path](const std::unique_ptr<campaign::Media>& p) { return path == p->path(); });
0158 
0159     return (it != std::end(m_mediaList)) ? (*it).get() : nullptr;
0160 }
0161 
0162 Media* Campaign::mediaFromUuid(const QString& uuid) const
0163 {
0164     auto it= std::find_if(std::begin(m_mediaList), std::end(m_mediaList),
0165                           [uuid](const std::unique_ptr<campaign::Media>& p) { return uuid == p->id(); });
0166     return (it != std::end(m_mediaList)) ? (*it).get() : nullptr;
0167 }
0168 
0169 QString Campaign::pathFromUuid(const QString& uuid) const
0170 {
0171     auto it= std::find_if(std::begin(m_mediaList), std::end(m_mediaList),
0172                           [uuid](const std::unique_ptr<campaign::Media>& p) { return uuid == p->id(); });
0173 
0174     return (it != std::end(m_mediaList)) ? (*it)->path() : QString();
0175 }
0176 
0177 QString Campaign::directory(Place place) const
0178 {
0179     QString res;
0180     switch(place)
0181     {
0182     case campaign::Campaign::Place::DICE_MODEL:
0183         res= QString("%1/%2").arg(rootDirectory(), DICE_ALIAS_MODEL);
0184         break;
0185     case campaign::Campaign::Place::STATE_MODEL:
0186         res= QString("%1/%2").arg(rootDirectory(), STATE_MODEL);
0187         break;
0188     case Place::MEDIA_ROOT:
0189         res= QString("%1/%2").arg(rootDirectory(), MEDIA_ROOT);
0190         break;
0191     case Place::STATE_ROOT:
0192         res= QString("%1/%2").arg(rootDirectory(), STATE_ROOT);
0193         break;
0194     case Place::TRASH_ROOT:
0195         res= QString("%1/%2").arg(rootDirectory(), TRASH_FOLDER);
0196         break;
0197     case Place::NPC_ROOT:
0198         res= QString("%1/%2").arg(rootDirectory(), CHARACTER_ROOT);
0199         break;
0200     case Place::NPC_MODEL:
0201         res= QString("%1/%2").arg(rootDirectory(), CHARACTER_MODEL);
0202         break;
0203     case Place::FIRST_AUDIO_PLAYER_FILE:
0204         res= QString("%1/%2").arg(rootDirectory(), FIRST_AUDIO_PLAYER_FILE);
0205         break;
0206     case Place::SECOND_AUDIO_PLAYER_FILE:
0207         res= QString("%1/%2").arg(rootDirectory(), SECOND_AUDIO_PLAYER_FILE);
0208         break;
0209     case Place::THIRD_AUDIO_PLAYER_FILE:
0210         res= QString("%1/%2").arg(rootDirectory(), THIRD_AUDIO_PLAYER_FILE);
0211         break;
0212     case Place::THEME_FILE:
0213         res= QString("%1/%2").arg(rootDirectory(), THEME_FILE);
0214         break;
0215     }
0216     return res;
0217 }
0218 
0219 void Campaign::setRootDirectory(const QString& root)
0220 {
0221     if(m_root == root)
0222         return;
0223     m_root= root;
0224     emit rootDirectoryChanged();
0225 }
0226 
0227 void Campaign::setCurrentChapter(const QString& chapter)
0228 {
0229     if(m_currentChapter == chapter)
0230         return;
0231     m_currentChapter= chapter;
0232     emit currentChapterChanged();
0233 }
0234 
0235 void Campaign::setCurrentTheme(RolisteamTheme* themeuri)
0236 {
0237     if(themeuri == m_theme.get())
0238         return;
0239     m_theme.reset(themeuri);
0240     emit currentThemeChanged();
0241 }
0242 
0243 void Campaign::setState(State state)
0244 {
0245     if(state == m_state)
0246         return;
0247     m_state= state;
0248     emit stateChanged();
0249 }
0250 
0251 void Campaign::setName(const QString& name)
0252 {
0253     if(m_name == name)
0254         return;
0255     m_name= name;
0256     emit nameChanged();
0257 }
0258 
0259 void Campaign::postError(const QString& msg)
0260 {
0261     emit errorOccured(msg);
0262 }
0263 
0264 void Campaign::addAlias()
0265 {
0266     m_diceModel->appendAlias(DiceAlias{tr("Pattern"), tr("Command"), tr("Comment")});
0267 }
0268 
0269 void Campaign::deleteAlias(const QModelIndex& index)
0270 {
0271     m_diceModel->deleteAlias(index);
0272 }
0273 
0274 QString Campaign::convertAlias(const QString& str)
0275 {
0276     return m_diceModel->convert(str);
0277 }
0278 
0279 void Campaign::addState()
0280 {
0281     m_stateModel->appendState(CharacterState());
0282 }
0283 
0284 void Campaign::deleteState(const QModelIndex& index)
0285 {
0286     m_stateModel->deleteState(index);
0287 }
0288 
0289 void Campaign::moveState(const QModelIndex& index, Move move)
0290 {
0291     switch(move)
0292     {
0293     case campaign::Campaign::Move::UP:
0294         m_stateModel->upState(index);
0295         break;
0296     case campaign::Campaign::Move::DOWN:
0297         m_stateModel->downState(index);
0298         break;
0299     case campaign::Campaign::Move::TOP:
0300         m_stateModel->topState(index);
0301         break;
0302     case campaign::Campaign::Move::BOTTOM:
0303         m_stateModel->bottomState(index);
0304         break;
0305     }
0306 }
0307 
0308 void Campaign::moveAlias(const QModelIndex& index, Move move)
0309 {
0310     switch(move)
0311     {
0312     case campaign::Campaign::Move::UP:
0313         m_diceModel->upAlias(index);
0314         break;
0315     case campaign::Campaign::Move::DOWN:
0316         m_diceModel->downAlias(index);
0317         break;
0318     case campaign::Campaign::Move::TOP:
0319         m_diceModel->topAlias(index);
0320         break;
0321     case campaign::Campaign::Move::BOTTOM:
0322         m_diceModel->bottomAlias(index);
0323         break;
0324     }
0325 }
0326 
0327 void Campaign::addCharacter()
0328 {
0329     // TODO command
0330     m_npcModel->append();
0331 }
0332 
0333 void Campaign::removeCharacter(const QString& id)
0334 {
0335     // TODO command
0336     m_npcModel->removeNpc(id);
0337 }
0338 } // namespace campaign