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/campaigneditor.h"
0021 
0022 #include "data/campaign.h"
0023 #include "data/character.h"
0024 #include "data/media.h"
0025 #include "data/rolisteamtheme.h"
0026 #include "utils/iohelper.h"
0027 #include "model/characterstatemodel.h"
0028 #include "model/nonplayablecharactermodel.h"
0029 #include "worker/fileserializer.h"
0030 #include "worker/iohelper.h"
0031 #include "worker/modelhelper.h"
0032 #include "worker/utilshelper.h"
0033 
0034 #include <QFuture>
0035 #include <QFutureWatcher>
0036 #include <QtConcurrent>
0037 
0038 namespace campaign
0039 {
0040 namespace
0041 {
0042 void readCampaignInfo(const CampaignInfo& info, Campaign* manager)
0043 {
0044     if(!info.status || !manager)
0045         return;
0046     ModelHelper::fetchDiceModel(info.dices, manager->diceAliases());
0047     ModelHelper::fetchCharacterStateModel(info.states, manager->stateModel());
0048     ModelHelper::fetchNpcModel(info.npcs, manager->npcModel(), manager->rootDirectory());
0049     auto assets= info.asset;
0050     ModelHelper::fetchMedia(assets[Core::JsonKey::JSON_MEDIAS].toArray(), manager);
0051     manager->setName(assets[Core::JsonKey::JSON_NAME].toString());
0052     manager->setCurrentChapter(assets[Core::JsonKey::JSON_CURRENT_CHAPTER].toString());
0053     manager->setCurrentTheme(IOHelper::jsonToTheme(info.theme));
0054 
0055     auto const& states= manager->stateModel()->statesList();
0056     auto list= new QList<CharacterState*>();
0057     std::transform(std::begin(states), std::end(states), std::back_inserter(*list),
0058                    [](const std::unique_ptr<CharacterState>& item) { return item.get(); });
0059     Character::setListOfCharacterState(list);
0060 }
0061 } // namespace
0062 CampaignEditor::CampaignEditor(QObject* parent) : QObject(parent), m_campaign(new Campaign)
0063 {
0064     connect(m_campaign.get(), &Campaign::mediaAdded, this, &CampaignEditor::importedFile);
0065 }
0066 
0067 Campaign* CampaignEditor::campaign() const
0068 {
0069     return m_campaign.get();
0070 }
0071 
0072 bool CampaignEditor::open(const QString& from)
0073 {
0074     m_campaign->setRootDirectory(from);
0075     helper::utils::setContinuation<CampaignInfo>(
0076         QtConcurrent::run([from]() { return campaign::FileSerializer::readCampaignDirectory(from); }), m_campaign.get(),
0077         [this](const CampaignInfo& info)
0078         {
0079             readCampaignInfo(info, m_campaign.get());
0080             emit campaignLoaded(info.missingFiles, info.unmanagedFiles);
0081         });
0082     return true;
0083 }
0084 
0085 bool CampaignEditor::mergeAudioFile(const QString& source, const QString& dest)
0086 {
0087     return IOHelper::mergePlayList(source, dest);
0088 }
0089 
0090 /*bool CampaignEditor::copyArrayModelAndFile(const QString& source, const QString& srcDir, const QString& dest,
0091                                            const QString& destDir)
0092 {
0093     return IOHelper::copyArrayModelAndFile(source, srcDir, dest, destDir);
0094 }*/
0095 
0096 bool CampaignEditor::copyMedia(const QString& source, const QString& dest, Core::MediaType type)
0097 {
0098     auto listFile= IOHelper::mediaList(source, type);
0099     if(listFile.isEmpty())
0100         return false;
0101     for(auto const& file : listFile)
0102     {
0103         addMedia(QUuid::createUuid().toString(QUuid::WithoutBraces), QString("%1/%2").arg(dest, file),
0104                  utils::IOHelper::loadFile(QString("%1/%2").arg(source, file)));
0105     }
0106     return true;
0107 }
0108 
0109 bool CampaignEditor::copyTheme(const QString& source, const QString& dest)
0110 {
0111     auto res= utils::IOHelper::copyFile(source, dest);
0112     return !res.isEmpty();
0113 }
0114 
0115 bool CampaignEditor::mergeJsonArrayFile(const QString& source, const QString& dest)
0116 {
0117     bool ok;
0118     auto srcArray= IOHelper::loadJsonFileIntoArray(source, ok);
0119     if(!ok)
0120         return false;
0121     auto destArray= IOHelper::loadJsonFileIntoArray(dest, ok);
0122 
0123     if(!ok)
0124     {
0125         utils::IOHelper::copyFile(source, dest);
0126         return true;
0127     }
0128 
0129     destArray.append(srcArray);
0130     IOHelper::writeJsonArrayIntoFile(dest, destArray);
0131     return true;
0132 }
0133 
0134 bool CampaignEditor::loadDiceAlias(const QString& source)
0135 {
0136     if(!m_campaign)
0137         return false;
0138 
0139     bool ok;
0140     ModelHelper::fetchDiceModel(IOHelper::loadJsonFileIntoArray(source, ok), m_campaign->diceAliases());
0141     return ok;
0142 }
0143 
0144 bool CampaignEditor::loadStates(const QString& source, const QString& srcDir, const QString& dest,
0145                                 const QString& destDir)
0146 {
0147     if(!m_campaign)
0148         return false;
0149 
0150     bool ok;
0151     ModelHelper::fetchCharacterStateModel(IOHelper::loadJsonFileIntoArray(source, ok), m_campaign->stateModel());
0152     auto const& list= m_campaign->stateModel()->statesList();
0153 
0154     std::for_each(std::begin(list), std::end(list),
0155                   [srcDir, destDir](const std::unique_ptr<CharacterState>& state)
0156                   {
0157                       auto path= state->imagePath();
0158                       if(path.isEmpty())
0159                           return;
0160                       utils::IOHelper::copyFile(QString("%1/%2").arg(srcDir, path),
0161                                                 QString("%1/%2").arg(destDir, path));
0162                   });
0163     // todo manage images from states
0164     return ok;
0165 }
0166 
0167 bool CampaignEditor::loadNpcData(const QString& source, const QString& srcDir, const QString& dest,
0168                                  const QString& destDir)
0169 {
0170     if(!m_campaign)
0171         return false;
0172 
0173     bool ok;
0174     ModelHelper::fetchNpcModel(IOHelper::loadJsonFileIntoArray(source, ok), m_campaign->npcModel(), srcDir);
0175     auto const& list= m_campaign->npcModel()->npcList();
0176 
0177     std::for_each(std::begin(list), std::end(list),
0178                   [srcDir, destDir](const std::unique_ptr<NonPlayableCharacter>& npc)
0179                   {
0180                       auto path= npc->avatarPath();
0181                       if(path.isEmpty())
0182                           return;
0183                       utils::IOHelper::copyFile(QString("%1/%2").arg(srcDir, path),
0184                                                 QString("%1/%2").arg(destDir, path));
0185                   });
0186     // todo manage images from states
0187     return ok;
0188 }
0189 
0190 bool CampaignEditor::removeMedia(const QString& src)
0191 {
0192     // remove from campaign
0193     auto media= m_campaign->mediaFromPath(src);
0194 
0195     if(!media)
0196         return false;
0197 
0198     m_campaign->removeMedia(media->id());
0199 
0200     // remove file on disk
0201     return removeFile(src);
0202 }
0203 
0204 bool CampaignEditor::removeFile(const QString& src)
0205 {
0206     return utils::IOHelper::removeFile(src);
0207 }
0208 
0209 QString CampaignEditor::saveAvatar(const QString& id, const QByteArray& array)
0210 {
0211     auto dest= QString("%1/avatar_%2.png").arg(m_campaign->directory(campaign::Campaign::Place::NPC_ROOT), id);
0212     utils::IOHelper::writeFile(dest, array);
0213     return dest;
0214 }
0215 
0216 /*QString CampaignEditor::addFileIntoCharacters(const QString& src)
0217 {
0218     // TODO create command
0219     // IOHelper::copyFile();
0220     // IOHelper::writeFile(src, array, true);
0221 }
0222 
0223 bool CampaignEditor::removeFileFromCharacters(const QString& path)
0224 {
0225     // IOHelper::removeFile(path);
0226 }*/
0227 
0228 bool CampaignEditor::addMedia(const QString& id, const QString& dest, const QByteArray& array)
0229 {
0230     QFileInfo file(dest);
0231     std::unique_ptr<Media> media(new Media(id, file.baseName(), dest, FileSerializer::typeFromExtention(dest)));
0232     m_campaign->addMedia(std::move(media));
0233     utils::IOHelper::writeFile(dest, array, true);
0234     return true;
0235 }
0236 
0237 QString CampaignEditor::mediaFullPathWithExtension(const QString& file, Core::ContentType type) const
0238 {
0239     return mediaFullPath(campaign::FileSerializer::addExtention(file, type));
0240 }
0241 
0242 QString CampaignEditor::mediaFullPath(const QString& file) const
0243 {
0244     return QString("%1/%2").arg(m_campaign->directory(campaign::Campaign::Place::MEDIA_ROOT), file);
0245 }
0246 
0247 void CampaignEditor::doCommand(QUndoCommand* command)
0248 {
0249     emit performCommand(command);
0250 }
0251 
0252 QString campaign::CampaignEditor::campaignDir() const
0253 {
0254     return m_campaign->rootDirectory();
0255 }
0256 
0257 QString CampaignEditor::currentDir() const
0258 {
0259     return m_campaign->currentChapter();
0260 }
0261 } // namespace campaign