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/gamecontroller.h" 0021 0022 #include <QTimer> 0023 0024 #include "common/logcontroller.h" 0025 #include "common/remotelogcontroller.h" 0026 0027 #include "data/campaigneditor.h" 0028 0029 #include "data/media.h" 0030 #include "model/profilemodel.h" 0031 #include "preferences/preferencesmanager.h" 0032 #include "services/tipchecker.h" 0033 #include "services/updatechecker.h" 0034 #include "worker/autosavecontroller.h" 0035 #include "worker/iohelper.h" 0036 #include "worker/messagehelper.h" 0037 #include "worker/modelhelper.h" 0038 0039 #include "network/connectionprofile.h" 0040 0041 GameController::GameController(const QString& appname, const QString& version, QClipboard* clipboard, QObject* parent) 0042 : QObject(parent) 0043 , m_diceParser(new DiceRoller) 0044 , m_logController(new LogController(true)) 0045 , m_remoteLogCtrl(new RemoteLogController()) 0046 , m_networkCtrl(new NetworkController) 0047 , m_playerController(new PlayerController(m_networkCtrl.get())) 0048 , m_preferencesDialogController(new PreferencesController) 0049 , m_campaignManager(new campaign::CampaignManager(m_diceParser.get())) 0050 , m_contentCtrl(new ContentController(m_campaignManager.get(), m_playerController->model(), 0051 m_playerController->characterModel(), clipboard, m_networkCtrl.get())) 0052 , m_preferences(new PreferencesManager(appname, QString("%1_%2/preferences").arg(appname, version))) 0053 , m_instantMessagingCtrl(new InstantMessagingController(m_diceParser.get(), m_playerController->model())) 0054 , m_audioCtrl(new AudioController(m_campaignManager.get(), m_preferences.get())) 0055 , m_version(version) 0056 , m_undoStack(new QUndoStack) 0057 , m_autoSaveCtrl(new AutoSaveController(m_preferences.get())) 0058 { 0059 m_preferences->readSettings(); 0060 postSettingInit(); 0061 0062 m_networkCtrl->setGameController(this); 0063 m_playerController->setGameController(this); 0064 m_contentCtrl->setGameController(this); 0065 m_preferencesDialogController->setGameController(this); 0066 0067 connect(m_logController.get(), &LogController::sendOffMessage, m_remoteLogCtrl.get(), &RemoteLogController::addLog); 0068 connect(m_networkCtrl.get(), &NetworkController::connectedChanged, this, 0069 [this](bool b) 0070 { 0071 if(b) 0072 { 0073 m_campaignManager->shareModels(); 0074 } 0075 emit connectedChanged(b); 0076 }); 0077 0078 connect(m_campaignManager.get(), &campaign::CampaignManager::campaignChanged, this, 0079 [this]() 0080 { 0081 auto cm= m_campaignManager->campaign(); 0082 m_contentCtrl->setMediaRoot(cm->directory(campaign::Campaign::Place::MEDIA_ROOT)); 0083 m_logController->setCurrentPath(QString("%1/rolisteam.log").arg(cm->rootDirectory())); 0084 }); 0085 connect(m_campaignManager->campaign(), &campaign::Campaign::rootDirectoryChanged, this, 0086 [this]() 0087 { 0088 auto cm= m_campaignManager->campaign(); 0089 m_contentCtrl->setMediaRoot(cm->directory(campaign::Campaign::Place::MEDIA_ROOT)); 0090 emit campaignRootChanged(); 0091 }); 0092 connect(m_campaignManager->editor(), &campaign::CampaignEditor::performCommand, this, &GameController::addCommand); 0093 0094 // clang-format off 0095 connect(m_autoSaveCtrl.get(), &AutoSaveController::saveData, m_campaignManager.get(), &campaign::CampaignManager::saveCampaign); 0096 connect(m_playerController.get(), &PlayerController::gameMasterIdChanged, m_contentCtrl.get(), &ContentController::setGameMasterId); 0097 connect(m_playerController.get(), &PlayerController::performCommand, this, &GameController::addCommand); 0098 connect(m_playerController.get(), &PlayerController::localPlayerIdChanged, m_remoteLogCtrl.get(), &RemoteLogController::setLocalUuid); 0099 connect(m_playerController.get(), &PlayerController::localPlayerIdChanged, m_remoteLogCtrl.get(), &RemoteLogController::setLocalUuid); 0100 connect(m_playerController.get(), &PlayerController::localPlayerIdChanged, m_instantMessagingCtrl.get(), &InstantMessagingController::setLocalId); 0101 connect(m_playerController.get(), &PlayerController::localPlayerIdChanged, m_contentCtrl.get(), &ContentController::setLocalId); 0102 connect(m_playerController.get(), &PlayerController::localPlayerChanged, m_contentCtrl.get(), [this](){ 0103 auto local = m_playerController->localPlayer(); 0104 if(!local) 0105 return; 0106 m_contentCtrl->setLocalColor(local->getColor()); 0107 }); 0108 0109 connect(m_contentCtrl.get(), &ContentController::performCommand, this, &GameController::addCommand); 0110 auto popCommand = [this]() 0111 { 0112 m_undoStack->setIndex(m_undoStack->index()-1); 0113 }; 0114 connect(m_contentCtrl.get(), &ContentController::popCommand, this, popCommand); 0115 0116 connect(m_networkCtrl.get(), &NetworkController::isGMChanged, m_campaignManager.get(), &campaign::CampaignManager::setLocalIsGM); 0117 connect(m_networkCtrl.get(), &NetworkController::isGMChanged, m_audioCtrl.get(), &AudioController::setLocalIsGM); 0118 connect(m_campaignManager.get(), &campaign::CampaignManager::campaignLoaded, this, &GameController::dataLoaded); 0119 connect(m_campaignManager.get(), &campaign::CampaignManager::campaignLoaded, this, [this](){ 0120 m_campaignManager->diceparser(); 0121 }); 0122 // clang-format on 0123 0124 m_contentCtrl->setGameMasterId(m_playerController->gameMasterId()); 0125 m_remoteLogCtrl->setLocalUuid(m_playerController->localPlayerId()); 0126 m_contentCtrl->setLocalId(m_playerController->localPlayerId()); 0127 m_instantMessagingCtrl->setLocalId(m_playerController->localPlayerId()); 0128 m_audioCtrl->setLocalIsGM(m_networkCtrl->isGM()); 0129 m_campaignManager->setLocalIsGM(m_networkCtrl->isGM()); 0130 0131 m_remoteLogCtrl->setAppId(0); 0132 } 0133 GameController::~GameController()= default; 0134 0135 void GameController::clear() 0136 { 0137 m_playerController->clear(); 0138 m_undoStack->clear(); 0139 } 0140 0141 void GameController::postSettingInit() 0142 { 0143 // Log controller 0144 auto logDebug= m_preferences->value(QStringLiteral("LogDebug"), false).toBool(); 0145 // m_logController->setMessageHandler(logDebug); 0146 0147 auto LogResearch= m_preferences->value(QStringLiteral("LogResearch"), false).toBool(); 0148 auto dataCollection= m_preferences->value(QStringLiteral("dataCollection"), false).toBool(); 0149 m_logController->setSignalInspection(logDebug && (LogResearch || dataCollection)); 0150 0151 LogController::StorageModes mode= LogController::Gui | LogController::Console; 0152 0153 if(localIsGM()) 0154 mode|= LogController::File; 0155 0156 if((LogResearch && dataCollection)) 0157 { 0158 /* m_logController->listenObjects(this); 0159 mode= LogController::Gui | LogController::Network; 0160 setFocusPolicy(Qt::StrongFocus); 0161 auto clipboard= QGuiApplication::clipboard(); 0162 connect(clipboard, &QClipboard::dataChanged, this, [clipboard, this]() { 0163 auto text= clipboard->text(); 0164 auto mime= clipboard->mimeData(); 0165 text.append(QStringLiteral("\n%1").arg(mime->formats().join("|"))); 0166 m_logController->manageMessage(QStringLiteral("Clipboard data changed: %1").arg(text), 0167 LogController::Search); 0168 });*/ 0169 } 0170 m_logController->setCurrentModes(mode); 0171 } 0172 0173 PreferencesManager* GameController::preferencesManager() const 0174 { 0175 return m_preferences.get(); 0176 } 0177 0178 void GameController::setCampaignRoot(const QString& path) 0179 { 0180 auto campaign= m_campaignManager->campaign(); 0181 campaign->setRootDirectory(path); 0182 } 0183 0184 void GameController::setVersion(const QString& version) 0185 { 0186 if(version == m_version) 0187 return; 0188 m_version= version; 0189 emit versionChanged(); 0190 } 0191 0192 void GameController::setLocalPlayerId(const QString& id) 0193 { 0194 m_remoteLogCtrl->setLocalUuid(id); 0195 } 0196 0197 void GameController::newMedia(const std::map<QString, QVariant>& map) 0198 { 0199 m_contentCtrl->newMedia(m_campaignManager->editor(), map); 0200 } 0201 0202 void GameController::openMedia(const std::map<QString, QVariant>& map) 0203 { 0204 QMap<QString, QVariant> other(map); 0205 if(localIsGM()) 0206 { 0207 if(other.contains(Core::keys::KEY_URL) && !other.contains(Core::keys::KEY_INTERNAL)) 0208 { 0209 auto path= other.value(Core::keys::KEY_URL).toUrl().toLocalFile(); 0210 other[Core::keys::KEY_PATH]= m_campaignManager->importFile(QUrl::fromLocalFile(path)); 0211 } 0212 else if(other.contains(Core::keys::KEY_DATA)) 0213 { 0214 auto name= other.value(Core::keys::KEY_NAME).toString(); 0215 auto data= other.value(Core::keys::KEY_DATA).toByteArray(); 0216 other[Core::keys::KEY_PATH]= m_campaignManager->createFileFromData(name, data); 0217 } 0218 } 0219 m_contentCtrl->openMedia(other.toStdMap()); 0220 } 0221 0222 void GameController::save() 0223 { 0224 if(localIsGM()) 0225 { 0226 ModelHelper::saveSession(m_contentCtrl.get()); 0227 m_campaignManager->saveCampaign(); 0228 } 0229 ModelHelper::saveAudioController(m_audioCtrl.get()); 0230 } 0231 0232 void GameController::saveAs(const QString& path) 0233 { 0234 ModelHelper::saveSession(m_contentCtrl.get()); 0235 ModelHelper::saveAudioController(m_audioCtrl.get()); 0236 m_campaignManager->copyCampaign(path); 0237 } 0238 0239 void GameController::setUpdateAvailable(bool available) 0240 { 0241 if(available == m_updateAvailable) 0242 return; 0243 m_updateAvailable= available; 0244 emit updateAvailableChanged(); 0245 } 0246 0247 ContentController* GameController::contentController() const 0248 { 0249 return m_contentCtrl.get(); 0250 } 0251 0252 LogController* GameController::logController() const 0253 { 0254 return m_logController.get(); 0255 } 0256 0257 void GameController::addErrorLog(const QString& message, const QString& cat) 0258 { 0259 m_logController->manageMessage(message, cat, LogController::Error); 0260 } 0261 0262 void GameController::addWarningLog(const QString& message, const QString& cat) 0263 { 0264 m_logController->manageMessage(message, cat, LogController::Warning); 0265 } 0266 0267 void GameController::addFeatureLog(const QString& message, const QString& cat) 0268 { 0269 m_logController->manageMessage(message, cat, LogController::Features); 0270 } 0271 0272 void GameController::addInfoLog(const QString& message, const QString& cat) 0273 { 0274 m_logController->manageMessage(message, cat, LogController::Info); 0275 } 0276 0277 void GameController::addSearchLog(const QString& message, const QString& cat) 0278 { 0279 m_logController->manageMessage(message, cat, LogController::Search); 0280 } 0281 0282 NetworkController* GameController::networkController() const 0283 { 0284 return m_networkCtrl.get(); 0285 } 0286 0287 PlayerController* GameController::playerController() const 0288 { 0289 return m_playerController.get(); 0290 } 0291 0292 QString GameController::remoteVersion() const 0293 { 0294 return m_remoteVersion; 0295 } 0296 0297 void GameController::startCheckForUpdates() 0298 { 0299 if(!m_preferences->value(QStringLiteral("MainWindow::MustBeChecked"), true).toBool()) 0300 return; 0301 0302 auto updateChecker= new UpdateChecker(m_version, this); 0303 updateChecker->startChecking(); 0304 connect(updateChecker, &UpdateChecker::checkFinished, this, 0305 [this, updateChecker]() 0306 { 0307 setUpdateAvailable(updateChecker->needUpdate()); 0308 m_remoteVersion= updateChecker->getLatestVersion(); 0309 updateChecker->deleteLater(); 0310 }); 0311 } 0312 0313 void GameController::startIpRetriever() 0314 { 0315 if(m_preferences->value(QStringLiteral("MainWindow::neverDisplayTips"), false).toBool()) 0316 return; 0317 TipChecker* tipChecker= new TipChecker(this); 0318 tipChecker->startChecking(); 0319 0320 connect(tipChecker, &TipChecker::checkFinished, this, 0321 [=]() 0322 { 0323 auto id= m_preferences->value(QStringLiteral("MainWindow::lastTips"), 0).toInt(); 0324 if(tipChecker->hasArticle() && tipChecker->getId() + 1 > id) 0325 { 0326 m_tipOfTheDay= {tipChecker->getArticleTitle(), tipChecker->getArticleContent(), 0327 tipChecker->getUrl(), tipChecker->getId()}; 0328 0329 m_preferences->registerValue(QStringLiteral("MainWindow::lastTips"), m_tipOfTheDay.id); 0330 emit tipOfDayChanged(); 0331 } 0332 tipChecker->deleteLater(); 0333 }); 0334 } 0335 0336 TipOfDay GameController::tipOfDay() const 0337 { 0338 return m_tipOfTheDay; 0339 } 0340 0341 void GameController::startTipOfDay() {} 0342 0343 QString GameController::version() const 0344 { 0345 return m_version; 0346 } 0347 0348 QString GameController::campaignRoot() const 0349 { 0350 return m_campaignManager->campaignDir(); 0351 } 0352 0353 InstantMessagingController* GameController::instantMessagingController() const 0354 { 0355 return m_instantMessagingCtrl.get(); 0356 } 0357 0358 campaign::CampaignManager* GameController::campaignManager() const 0359 { 0360 return m_campaignManager.get(); 0361 } 0362 0363 campaign::Campaign* GameController::campaign() const 0364 { 0365 return m_campaignManager->campaign(); 0366 } 0367 0368 AudioController* GameController::audioController() const 0369 { 0370 return m_audioCtrl.get(); 0371 } 0372 0373 QString GameController::localPlayerId() const 0374 { 0375 return m_playerController->localPlayerId(); 0376 } 0377 0378 bool GameController::localIsGM() const 0379 { 0380 return m_networkCtrl->isGM(); 0381 } 0382 0383 bool GameController::updateAvailable() const 0384 { 0385 return m_updateAvailable; 0386 } 0387 0388 bool GameController::connected() const 0389 { 0390 return m_networkCtrl->connected(); 0391 } 0392 0393 QUndoStack* GameController::undoStack() const 0394 { 0395 return m_undoStack.get(); 0396 } 0397 0398 DiceRoller* GameController::diceParser() const 0399 { 0400 return m_diceParser.get(); 0401 } 0402 0403 void GameController::setDataFromProfile(int profileIndex) 0404 { 0405 auto profile= m_networkCtrl->profileModel()->getProfile(profileIndex); 0406 m_networkCtrl->setSelectedProfileIndex(profileIndex); 0407 0408 if(profile == nullptr) 0409 return; 0410 0411 auto local= m_playerController->localPlayer(); 0412 0413 local->setUuid(profile->playerId()); 0414 local->setName(profile->playerName()); 0415 local->setColor(profile->playerColor()); 0416 local->setAvatar(profile->playerAvatar()); 0417 local->setGM(profile->isGM()); 0418 if(!local->isGM()) 0419 { 0420 auto characters= profile->characters(); 0421 std::for_each( 0422 characters.begin(), characters.end(), 0423 [local](const connection::CharacterData& data) 0424 { local->addCharacter(data.m_uuid, data.m_name, data.m_color, data.m_avatarData, data.m_params, false); }); 0425 } 0426 /*m_networkCtrl->setHost(profile->address()); 0427 m_networkCtrl->setPort(profile->port()); 0428 m_networkCtrl->setServerPassword(profile->password()); 0429 m_networkCtrl->setIsGM(profile->isGM()); 0430 m_networkCtrl->setHosting(profile->isServer()); 0431 m_networkCtrl->setAskForGM(profile->isGM());*/ 0432 0433 m_playerController->addPlayer(local); 0434 if(profile->isGM()) 0435 { 0436 m_campaignManager->openCampaign(QUrl::fromLocalFile(profile->campaignPath())); 0437 } 0438 else 0439 { 0440 emit dataLoaded({}, {}); 0441 } 0442 } 0443 0444 void GameController::startConnection() 0445 { 0446 m_networkCtrl->startConnection(); 0447 } 0448 0449 void GameController::stopConnection() 0450 { 0451 networkController()->stopConnecting(); 0452 } 0453 0454 void GameController::postConnection() 0455 { 0456 // save data 0457 m_networkCtrl->saveData(); 0458 } 0459 0460 void GameController::aboutToClose() 0461 { 0462 save(); 0463 // save data 0464 m_networkCtrl->saveData(); 0465 0466 // close connection 0467 MessageHelper::sendOffGoodBye(); 0468 m_networkCtrl->closeServer(); 0469 m_preferences->writeSettings(); 0470 emit closingApp(); 0471 } 0472 0473 PreferencesController* GameController::preferencesController() const 0474 { 0475 return m_preferencesDialogController.get(); 0476 } 0477 void GameController::addCommand(QUndoCommand* cmd) 0478 { 0479 m_undoStack->push(cmd); 0480 }