File indexing completed on 2024-05-05 05:40:24
0001 /*************************************************************************** 0002 * Copyright (C) 2019 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/contentcontroller.h" 0021 0022 #include <QFileInfo> 0023 0024 #include "controller/view_controller/charactersheetcontroller.h" 0025 #include "controller/view_controller/imagecontroller.h" 0026 #include "controller/view_controller/mindmapcontroller.h" 0027 #include "controller/view_controller/sharednotecontroller.h" 0028 #include "controller/view_controller/vectorialmapcontroller.h" 0029 0030 #include "updater/media/charactersheetupdater.h" 0031 #include "updater/media/genericupdater.h" 0032 #include "updater/media/mediaupdaterinterface.h" 0033 #include "updater/media/mindmapupdater.h" 0034 #include "updater/media/sharednotecontrollerupdater.h" 0035 #include "updater/media/vmapupdater.h" 0036 #include "updater/media/webviewupdater.h" 0037 #include "updater/vmapitem/vmapitemcontrollerupdater.h" 0038 0039 #include "data/campaignmanager.h" 0040 0041 #include "controller/gamecontroller.h" 0042 #include "media/mediafactory.h" 0043 #include "model/contentmodel.h" 0044 #include "model/playermodel.h" 0045 #include "model/remoteplayermodel.h" 0046 #include "network/networkmessage.h" 0047 #include "network/networkmessagereader.h" 0048 #include "preferences/preferencesmanager.h" 0049 #include "undoCmd/newmediacontroller.h" 0050 #include "undoCmd/openmediacontroller.h" 0051 #include "worker/iohelper.h" 0052 #include "worker/messagehelper.h" 0053 0054 0055 void sendOffMediaController(MediaControllerBase* ctrl) 0056 { 0057 if(!ctrl->localIsOwner() || ctrl->remote()) 0058 return; 0059 0060 switch(ctrl->contentType()) 0061 { 0062 case Core::ContentType::PICTURE: 0063 MessageHelper::sendOffImage(dynamic_cast<ImageController*>(ctrl)); 0064 break; 0065 case Core::ContentType::VECTORIALMAP: 0066 MessageHelper::sendOffVMap(dynamic_cast<VectorialMapController*>(ctrl)); 0067 break; 0068 default: 0069 break; 0070 } 0071 } 0072 0073 ContentController::ContentController(campaign::CampaignManager* campaign, PlayerModel* playerModel, 0074 CharacterModel* characterModel, QClipboard* clipboard, QObject* parent) 0075 : AbstractControllerInterface(parent) 0076 , m_sessionModel(new QFileSystemModel()) 0077 , m_contentModel(new ContentModel) 0078 , m_historyModel(new history::HistoryModel) 0079 , m_clipboard(clipboard) 0080 { 0081 CharacterSheetController::setCharacterModel(characterModel); 0082 SharedNoteController::setPlayerModel(playerModel); 0083 CharacterFinder::setPlayerModel(playerModel); 0084 MindMapController::setRemotePlayerModel(new RemotePlayerModel(playerModel)); 0085 0086 connect(m_sessionModel.get(), &QFileSystemModel::rootPathChanged, this, &ContentController::mediaRootChanged); 0087 0088 ReceiveEvent::registerNetworkReceiver(NetMsg::MediaCategory, this); 0089 0090 auto fModel= new FilteredContentModel(Core::ContentType::VECTORIALMAP); 0091 fModel->setSourceModel(m_contentModel.get()); 0092 0093 auto fModel2= new FilteredContentModel(Core::ContentType::SHAREDNOTE); 0094 fModel2->setSourceModel(m_contentModel.get()); 0095 0096 auto fModel3= new FilteredContentModel(Core::ContentType::MINDMAP); 0097 fModel3->setSourceModel(m_contentModel.get()); 0098 0099 std::unique_ptr<VMapUpdater> vmapUpdater(new VMapUpdater(campaign, fModel)); 0100 std::unique_ptr<SharedNoteControllerUpdater> sharedNoteUpdater(new SharedNoteControllerUpdater(fModel2, campaign)); 0101 std::unique_ptr<WebViewUpdater> webviewUpdater(new WebViewUpdater(campaign)); 0102 std::unique_ptr<MindMapUpdater> mindMapUpdater(new MindMapUpdater(fModel3, campaign)); 0103 std::unique_ptr<GenericUpdater> imageUpdater(new GenericUpdater(campaign)); 0104 std::unique_ptr<GenericUpdater> notesUpdater(new GenericUpdater(campaign)); 0105 std::unique_ptr<CharacterSheetUpdater> characterSheetUpdater(new CharacterSheetUpdater(campaign)); 0106 std::unique_ptr<GenericUpdater> pdfUpdater(new GenericUpdater(campaign)); 0107 MindMapController::setMindMapUpdater(mindMapUpdater.get()); 0108 0109 m_mediaUpdaters.insert({Core::ContentType::VECTORIALMAP, std::move(vmapUpdater)}); 0110 m_mediaUpdaters.insert({Core::ContentType::SHAREDNOTE, std::move(sharedNoteUpdater)}); 0111 m_mediaUpdaters.insert({Core::ContentType::WEBVIEW, std::move(webviewUpdater)}); 0112 m_mediaUpdaters.insert({Core::ContentType::MINDMAP, std::move(mindMapUpdater)}); 0113 m_mediaUpdaters.insert({Core::ContentType::PICTURE, std::move(imageUpdater)}); 0114 m_mediaUpdaters.insert({Core::ContentType::NOTES, std::move(notesUpdater)}); 0115 m_mediaUpdaters.insert({Core::ContentType::CHARACTERSHEET, std::move(characterSheetUpdater)}); 0116 m_mediaUpdaters.insert({Core::ContentType::PDF, std::move(pdfUpdater)}); 0117 0118 connect(m_contentModel.get(), &ContentModel::mediaControllerAdded, this, 0119 [this](MediaControllerBase* ctrl) 0120 { 0121 if(nullptr == ctrl) 0122 return; 0123 connect(ctrl, &MediaControllerBase::performCommand, this, &ContentController::performCommand); 0124 connect(ctrl, &MediaControllerBase::popCommand, this, &ContentController::popCommand); 0125 emit mediaControllerCreated(ctrl); 0126 sendOffMediaController(ctrl); 0127 auto it= m_mediaUpdaters.find(ctrl->contentType()); 0128 if(it != m_mediaUpdaters.end()) 0129 it->second->addMediaController(ctrl); 0130 if(!localIsGM()) 0131 m_historyModel->addLink(ctrl->url(), ctrl->name(), ctrl->contentType()); 0132 }); 0133 0134 connect(m_clipboard, &QClipboard::dataChanged, this, [this]() { emit canPasteChanged(canPaste()); }); 0135 0136 connect(m_historyModel.get(), &history::HistoryModel::modelReset, this, &ContentController::historyChanged); 0137 connect(m_historyModel.get(), &history::HistoryModel::rowsInserted, this, &ContentController::historyChanged); 0138 connect(m_historyModel.get(), &history::HistoryModel::rowsRemoved, this, &ContentController::historyChanged); 0139 } 0140 0141 ContentController::~ContentController()= default; 0142 0143 void ContentController::setGameController(GameController* game) 0144 { 0145 m_preferences= game->preferencesManager(); 0146 m_preferences->registerListener("BackGroundPositioning", this); 0147 m_preferences->registerListener("PathOfBackgroundImage", this); 0148 m_preferences->registerListener("BackGroundColor", this); 0149 m_preferences->registerListener("shortNameInTabMode", this); 0150 m_preferences->registerListener("MaxLengthTabName", this); 0151 } 0152 0153 void ContentController::preferencesHasChanged(const QString& key) 0154 { 0155 if(key == QStringLiteral("BackGroundPositioning")) 0156 emit workspacePositioningChanged(); 0157 else if(key == QStringLiteral("PathOfBackgroundImage")) 0158 emit workspaceFilenameChanged(); 0159 else if(key == QStringLiteral("BackGroundColor")) 0160 emit workspaceColorChanged(); 0161 else if(key == QStringLiteral("shortNameInTabMode")) 0162 emit shortTitleTabChanged(); 0163 else if(key == QStringLiteral("MaxLengthTabName")) 0164 emit maxLengthTabNameChanged(); 0165 } 0166 0167 void ContentController::newMedia(campaign::CampaignEditor* editor, const std::map<QString, QVariant>& params) 0168 { 0169 auto arg= params; 0170 arg.insert({Core::keys::KEY_OWNERID, m_localId}); 0171 arg.insert({Core::keys::KEY_LOCALID, m_localId}); 0172 arg.insert({Core::keys::KEY_GMID, m_gameMasterId}); 0173 emit performCommand(new NewMediaController(m_contentModel.get(), arg, localColor(), localIsGM(), editor)); 0174 } 0175 0176 void ContentController::openMedia(const std::map<QString, QVariant>& args) 0177 { 0178 auto it= args.find(Core::keys::KEY_TYPE); 0179 0180 if(it == args.end()) 0181 return; 0182 0183 auto type= it->second.value<Core::ContentType>(); 0184 0185 emit performCommand(new OpenMediaController(m_contentModel.get(), type, args, localColor(), localIsGM())); 0186 } 0187 0188 QFileSystemModel* ContentController::sessionModel() const 0189 { 0190 return m_sessionModel.get(); 0191 } 0192 0193 ContentModel* ContentController::contentModel() const 0194 { 0195 return m_contentModel.get(); 0196 } 0197 0198 history::HistoryModel* ContentController::historyModel() const 0199 { 0200 return m_historyModel.get(); 0201 } 0202 0203 int ContentController::contentCount() const 0204 { 0205 return m_contentModel->rowCount(); 0206 } 0207 0208 void ContentController::setMediaRoot(const QString& path) 0209 { 0210 qDebug()<< "PathMedia root:" << path << m_sessionModel->rootPath(); 0211 if(m_sessionModel->rootPath() == path) 0212 return; 0213 m_sessionModel->setRootPath(path); 0214 emit mediaRootChanged(); 0215 } 0216 0217 QString ContentController::gameMasterId() const 0218 { 0219 return m_gameMasterId; 0220 } 0221 0222 QString ContentController::currentMediaId() const 0223 { 0224 return m_contentModel->activeMediaId(); 0225 } 0226 0227 MediaControllerBase* ContentController::media(const QString& id) const 0228 { 0229 return m_contentModel->media(id); 0230 } 0231 0232 QString ContentController::localId() const 0233 { 0234 return m_localId; 0235 } 0236 0237 bool ContentController::localIsGM() const 0238 { 0239 return m_localId == m_gameMasterId; 0240 } 0241 0242 void ContentController::setGameMasterId(const QString& id) 0243 { 0244 if(id == m_gameMasterId) 0245 return; 0246 m_gameMasterId= id; 0247 emit gameMasterIdChanged(m_gameMasterId); 0248 } 0249 0250 void ContentController::setLocalId(const QString& id) 0251 { 0252 if(m_localId == id) 0253 return; 0254 m_localId= id; 0255 Media::MediaFactory::setLocalId(id); 0256 emit localIdChanged(m_localId); 0257 } 0258 0259 void ContentController::clear() 0260 { 0261 m_contentModel->clearData(); 0262 } 0263 0264 void ContentController::clearHistory() 0265 { 0266 m_historyModel->clear(); 0267 } 0268 0269 void ContentController::closeCurrentMedia() 0270 { 0271 m_contentModel->removeMedia(m_contentModel->activeMediaId()); 0272 } 0273 0274 int ContentController::maxLengthTabName() const 0275 { 0276 return m_preferences->value(QStringLiteral("MaxLengthTabName"), 20).toInt(); 0277 } 0278 0279 bool ContentController::shortTitleTab() const 0280 { 0281 return m_preferences->value(QStringLiteral("shortNameInTabMode"), false).toBool(); 0282 } 0283 QString ContentController::workspaceFilename() const 0284 { 0285 return m_preferences->value(QStringLiteral("PathOfBackgroundImage"), 20).toString(); 0286 } 0287 QColor ContentController::workspaceColor() const 0288 { 0289 return m_preferences->value(QStringLiteral("BackGroundColor"), QColor(191, 191, 191)).value<QColor>(); 0290 } 0291 int ContentController::workspacePositioning() const 0292 { 0293 return m_preferences->value(QStringLiteral("BackGroundPositioning"), 0).toInt(); 0294 } 0295 0296 NetWorkReceiver::SendType ContentController::processMessage(NetworkMessageReader* msg) 0297 { 0298 NetWorkReceiver::SendType result= NetWorkReceiver::NONE; 0299 std::set<NetMsg::Action> actions({NetMsg::AddMedia, NetMsg::UpdateMediaProperty, NetMsg::CloseMedia, 0300 NetMsg::AddSubImage, NetMsg::RemoveSubImage}); 0301 0302 if(actions.find(msg->action()) == actions.end()) 0303 return result; 0304 0305 QSet<NetMsg::Action> subActions{NetMsg::UpdateMediaProperty, NetMsg::AddSubImage, NetMsg::RemoveSubImage}; 0306 0307 if(msg->action() == NetMsg::CloseMedia) 0308 { 0309 Q_UNUSED(static_cast<Core::ContentType>(msg->uint8())); 0310 auto id= MessageHelper::readMediaId(msg); 0311 m_contentModel->removeMedia(id); 0312 } 0313 else if(msg->action() == NetMsg::AddMedia) 0314 { 0315 auto type= static_cast<Core::ContentType>(msg->uint8()); 0316 auto media= Media::MediaFactory::createRemoteMedia(type, msg, localColor(), localIsGM()); 0317 m_contentModel->appendMedia(media); 0318 } 0319 else if(subActions.contains(msg->action())) 0320 { 0321 auto type= static_cast<Core::ContentType>(msg->uint8()); 0322 auto it= m_mediaUpdaters.find(type); 0323 if(it != m_mediaUpdaters.end()) 0324 { 0325 auto updater= it->second.get(); 0326 updater->processMessage(msg); 0327 } 0328 else 0329 { 0330 QString mediaId= msg->string8(); 0331 } 0332 } 0333 return result; 0334 } 0335 0336 void ContentController::copyData() {} 0337 0338 void ContentController::pasteData() 0339 { 0340 auto mediaCtrl= m_contentModel->media(m_contentModel->activeMediaId()); 0341 if(!m_clipboard) 0342 return; 0343 const QMimeData* mimeData= m_clipboard->mimeData(); 0344 if(!mimeData) 0345 return; 0346 0347 bool accepted= false; 0348 if(mediaCtrl) 0349 accepted= mediaCtrl->pasteData(*mimeData); 0350 0351 if(!accepted) 0352 readMimeData(*mimeData); 0353 } 0354 0355 void ContentController::readMimeData(const QMimeData& data) 0356 { 0357 if(data.hasImage()) 0358 { 0359 auto pix= qvariant_cast<QPixmap>(data.imageData()); 0360 if(pix.isNull()) 0361 return; 0362 auto imageBytes= IOHelper::pixmapToData(pix); 0363 QString name(IOHelper::htmlToTitle(data, tr("Copied Image"))); 0364 0365 openMedia({{"type", QVariant::fromValue(Core::ContentType::PICTURE)}, 0366 {"ownerId", m_localId}, 0367 {"data", imageBytes}, 0368 {"name", name}}); 0369 } 0370 else if(data.hasUrls()) 0371 { 0372 // qDebug() << "hasURL"; 0373 } 0374 else if(data.hasHtml()) 0375 { 0376 // qDebug() << "hasHTML"; 0377 // setText(data.html()); 0378 // setTextFormat(Qt::RichText); 0379 } 0380 else if(data.hasText()) 0381 { 0382 // qDebug() << "hasTEXT"; 0383 // setText(data.text()); 0384 // setTextFormat(Qt::PlainText); 0385 } 0386 else 0387 { 0388 // qDebug() << "nothing"; 0389 // setText(tr("Cannot display data")); 0390 } 0391 } 0392 0393 bool ContentController::canPaste() const 0394 { 0395 bool res= false; 0396 0397 if(!m_clipboard) 0398 return res; 0399 0400 auto data= m_clipboard->mimeData(); 0401 if(!data) 0402 return res; 0403 0404 res= data->hasImage(); 0405 return res; 0406 } 0407 0408 bool ContentController::canCopy() const 0409 { 0410 return false; 0411 } 0412 0413 QString ContentController::mediaRoot() const 0414 { 0415 return m_sessionModel->rootPath(); 0416 } 0417 /*void ContentController::setActiveMediaController(AbstractMediaContainerController* mediaCtrl) 0418 { 0419 std::find_if(m_mediaControllers.begin(), m_mediaControllers.end(), 0420 [this](const std::pair<Core::ContentType, MediaControllerInterface*>& pair) { 0421 0422 }); 0423 if() 0424 }*/ 0425 0426 const QColor& ContentController::localColor() const 0427 { 0428 return m_localColor; 0429 } 0430 0431 void ContentController::setLocalColor(const QColor& newLocalColor) 0432 { 0433 if(m_localColor == newLocalColor) 0434 return; 0435 m_localColor= newLocalColor; 0436 emit localColorChanged(); 0437 }