File indexing completed on 2024-10-06 06:47:15
0001 /* 0002 This file is part of the KDE games kwin4 program 0003 SPDX-FileCopyrightText: 1995-2007 Martin Heni <kde@heni-online.de> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "kwin4.h" 0009 0010 // own 0011 #include "chatdlg.h" 0012 #include "kfourinline_debug.h" 0013 #include "kgamedebugdialog.h" 0014 #include "kgamedialog.h" 0015 #include "kgamedialogconfig.h" 0016 #include "kwin4doc.h" 0017 #include "kwin4view.h" 0018 #include "prefs.h" 0019 #include "reflectiongraphicsscene.h" 0020 #include "ui_settings.h" 0021 #include "ui_statistics.h" 0022 // KDEGames 0023 #define USE_UNSTABLE_LIBKDEGAMESPRIVATE_API 0024 #include <libkdegamesprivate/kgame/kgamechat.h> 0025 // KF 0026 #include <KActionCollection> 0027 #include <KConfig> 0028 #include <KConfigDialog> 0029 #include <KLocalizedString> 0030 #include <KMessageBox> 0031 #include <KSelectAction> 0032 #include <KStandardAction> 0033 #include <KGameStandardAction> 0034 // Qt 0035 #include <QFileDialog> 0036 #include <QGroupBox> 0037 #include <QIcon> 0038 #include <QLayout> 0039 #include <QRadioButton> 0040 #include <QStatusBar> 0041 #include <QTimer> 0042 #include <QVBoxLayout> 0043 0044 // Abbreviations 0045 #define ACTION(x) (actionCollection()->action(x)) 0046 #define ID_STATUS_MSG 1003 0047 #define ID_STATUS_MOVER 1002 0048 0049 #define UPDATE_TIME 25 /* [ms] */ 0050 0051 // Configuration file 0052 #include "config-src.h" 0053 0054 // Construct the main application window 0055 KWin4App::KWin4App(QWidget *parent) 0056 : KXmlGuiWindow(parent) 0057 , mTheme() 0058 , mView() 0059 , mDoc() 0060 , mScene() 0061 , mColorGroup() 0062 , mMyChatDlg() 0063 , mStatusMsg() 0064 , mStatusMover() 0065 { 0066 // Read theme files 0067 QStringList themeList; 0068 const QString dir = QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("grafix"), QStandardPaths::LocateDirectory); 0069 const QStringList fileNames = QDir(dir).entryList({QStringLiteral("*.desktop")}); 0070 for (const QString &file : fileNames) 0071 themeList.append(dir + QLatin1Char('/') + file); 0072 0073 if (themeList.isEmpty()) { 0074 KMessageBox::error(this, i18n("Installation error: No theme list found.")); 0075 QTimer::singleShot(0, this, &QWidget::close); 0076 return; 0077 } 0078 0079 // Read theme files 0080 for (int i = 0; i < themeList.size(); i++) { 0081 KConfig themeInfo(themeList.at(i), KConfig::SimpleConfig); 0082 KConfigGroup themeGroup(&themeInfo, QStringLiteral("Theme")); 0083 QString name = themeGroup.readEntry("Name", QString()); 0084 QString file = themeGroup.readEntry("File", QString()); 0085 bool isDefault = themeGroup.readEntry("Default", false); 0086 if (mThemeDefault.isNull()) 0087 mThemeDefault = name; 0088 if (isDefault) 0089 mThemeDefault = name; 0090 mThemeFiles[name] = file; 0091 qCDebug(KFOURINLINE_LOG) << "Found theme(" << i << "): " << themeList.at(i) << " Name(i18n)=" << name << " File=" << file << " default=" << isDefault; 0092 } 0093 mThemeIndexNo = themeIdxFromName(mThemeDefault); 0094 0095 // Setup application 0096 mDoc = new KWin4Doc(this); 0097 qCDebug(KFOURINLINE_LOG) << "Init doc"; 0098 QString aiEngine = mDoc->findProcessName(); 0099 qCDebug(KFOURINLINE_LOG) << "Init AI" << aiEngine; 0100 if (aiEngine.isEmpty()) { 0101 KMessageBox::error(this, i18n("Installation error: No AI engine found. Continue without AI.")); 0102 } 0103 0104 // Read properties (before GUI and thememanager but after new document) 0105 qCDebug(KFOURINLINE_LOG) << "read prop"; 0106 readProperties(); 0107 0108 // Scene 0109 mScene = new ReflectionGraphicsScene(UPDATE_TIME, this); 0110 0111 // Theme 0112 QString themeFile = themefileFromIdx(mThemeIndexNo); 0113 qCDebug(KFOURINLINE_LOG) << "Loading theme" << themeFile << " #" << mThemeIndexNo; 0114 mTheme = new ThemeManager(themeFile, this); 0115 if (mTheme->checkTheme() != 0) { 0116 KMessageBox::error(this, i18n("Installation error: Theme file error.")); 0117 QTimer::singleShot(0, this, &QWidget::close); 0118 return; 0119 } 0120 0121 // View 0122 mView = new KWin4View(UPDATE_TIME, QSize(800, 600), mScene, mTheme, this); 0123 mDoc->setView(mView); 0124 connect(mView, &KWin4View::signalQuickStart, this, &KWin4App::quickStart); 0125 0126 // Players (after view) 0127 qCDebug(KFOURINLINE_LOG) << "Init pl"; 0128 mDoc->initPlayers(); 0129 0130 // Init GUI 0131 initGUI(); 0132 initStatusBar(); 0133 0134 // Adjust GUI 0135 setCentralWidget(mView); 0136 setupGUI(); 0137 0138 // Connect signals 0139 connectDocument(); 0140 // Read global config for document (after initPlayers) 0141 mDoc->readConfig(KSharedConfig::openConfig().data()); 0142 0143 // Check menus 0144 checkMenus(); 0145 0146 // Skip intro? 0147 if (global_skip_intro) { 0148 menuNewGame(); 0149 } 0150 // Start game automatically in demo mode 0151 else if (global_demo_mode) { 0152 QTimer::singleShot(11500, this, &KWin4App::menuNewGame); 0153 } 0154 } 0155 0156 // Destruct application 0157 KWin4App::~KWin4App() 0158 { 0159 qCDebug(KFOURINLINE_LOG) << "~KWin4App()"; 0160 delete mDoc; 0161 delete mView; 0162 delete mScene; 0163 delete mTheme; 0164 delete mMyChatDlg; 0165 qCDebug(KFOURINLINE_LOG) << "~KWin4App()"; 0166 } 0167 0168 // Called by Qt when the window is closed 0169 void KWin4App::closeEvent(QCloseEvent *event) 0170 { 0171 endGame(); 0172 saveProperties(); 0173 KXmlGuiWindow::closeEvent(event); 0174 } 0175 0176 // Retrieve a theme file name from the menu index number 0177 QString KWin4App::themefileFromIdx(int idx) 0178 { 0179 QStringList list(mThemeFiles.keys()); 0180 list.sort(); 0181 QString themeFile = mThemeFiles[list.at(idx)]; 0182 return themeFile; 0183 } 0184 0185 // Retrieve a theme idx from a theme name 0186 int KWin4App::themeIdxFromName(const QString &name) 0187 { 0188 QStringList list(mThemeFiles.keys()); 0189 list.sort(); 0190 for (int i = 0; i < list.size(); ++i) { 0191 if (list[i] == name) 0192 return i; 0193 } 0194 qCCritical(KFOURINLINE_LOG) << "Theme index lookup failed for " << name; 0195 return 0; 0196 } 0197 0198 // This method is called from various places 0199 // and signals to check, uncheck and enable 0200 // or disable all menu items. 0201 // The menu parameter can limit this operation 0202 // to one or more of the main menus (File,View,...) 0203 void KWin4App::checkMenus(CheckFlags menu) 0204 { 0205 bool localgame = (!mDoc->isNetwork()); 0206 bool isRunning = (mDoc->gameStatus() == KGame::Run); 0207 0208 // Check file menu 0209 if (!menu || (menu & CheckFileMenu)) { 0210 changeAction(KGameStandardAction::name(KGameStandardAction::Hint), !(!isRunning && localgame)); 0211 changeAction(KGameStandardAction::name(KGameStandardAction::New), !isRunning); 0212 changeAction(KGameStandardAction::name(KGameStandardAction::Save), isRunning); 0213 changeAction(KGameStandardAction::name(KGameStandardAction::End), isRunning); 0214 } 0215 0216 // Edit menu 0217 if (!menu || (menu & CheckEditMenu)) { 0218 const QString moveUndoActionId = KGameStandardAction::name(KGameStandardAction::Undo); 0219 if (!isRunning || !localgame) { 0220 disableAction(moveUndoActionId); 0221 } else if (mDoc->getHistoryCnt() == 0) { 0222 disableAction(moveUndoActionId); 0223 } else if (mDoc->getCurrentMove() < 1) { 0224 disableAction(moveUndoActionId); 0225 } else { 0226 enableAction(moveUndoActionId); 0227 } 0228 0229 // Show redo 0230 const QString moveRedoActionId = KGameStandardAction::name(KGameStandardAction::Redo); 0231 if (!isRunning || !localgame) { 0232 disableAction(moveRedoActionId); 0233 } else if (mDoc->getHistoryCnt() == mDoc->getMaxMove()) { 0234 disableAction(moveRedoActionId); 0235 } else { 0236 enableAction(moveRedoActionId); 0237 } 0238 } 0239 0240 // Disable some menus in demo mode 0241 if (global_demo_mode) { 0242 disableAction(KStandardAction::name(KStandardAction::Preferences)); 0243 disableAction(KGameStandardAction::name(KGameStandardAction::Undo)); 0244 disableAction(KGameStandardAction::name(KGameStandardAction::Redo)); 0245 disableAction(KGameStandardAction::name(KGameStandardAction::New)); 0246 disableAction(KGameStandardAction::name(KGameStandardAction::End)); 0247 disableAction(KGameStandardAction::name(KGameStandardAction::Save)); 0248 disableAction(KGameStandardAction::name(KGameStandardAction::Load)); 0249 disableAction(QStringLiteral("network_conf")); 0250 disableAction(QStringLiteral("network_chat")); 0251 disableAction(QStringLiteral("statistics")); 0252 disableAction(KGameStandardAction::name(KGameStandardAction::Hint)); 0253 } 0254 } 0255 0256 // Create the actions for the menu. This works together with the xml guirc file 0257 void KWin4App::initGUI() 0258 { 0259 QAction *action; 0260 0261 // Game 0262 KGameStandardAction::gameNew(this, &KWin4App::menuNewGame, actionCollection()); 0263 KGameStandardAction::load(this, &KWin4App::menuOpenGame, actionCollection()); 0264 KGameStandardAction::save(this, &KWin4App::menuSaveGame, actionCollection()); 0265 action = KGameStandardAction::end(this, &KWin4App::endGame, actionCollection()); 0266 action->setWhatsThis(i18n("Ends a currently played game. No winner will be declared.")); 0267 KGameStandardAction::hint(this, &KWin4App::askForHint, actionCollection()); 0268 KGameStandardAction::quit(this, &KWin4App::close, actionCollection()); 0269 0270 action = actionCollection()->addAction(QStringLiteral("network_conf")); 0271 action->setText(i18n("&Network Configuration...")); 0272 connect(action, &QAction::triggered, this, &KWin4App::configureNetwork); 0273 0274 action = actionCollection()->addAction(QStringLiteral("network_chat")); 0275 action->setText(i18n("Network Chat...")); 0276 connect(action, &QAction::triggered, this, &KWin4App::configureChat); 0277 0278 action = actionCollection()->addAction(QStringLiteral("statistics")); 0279 action->setIcon(QIcon::fromTheme(QStringLiteral("view-statistics"))); 0280 action->setText(i18n("&Show Statistics")); 0281 connect(action, &QAction::triggered, this, &KWin4App::showStatistics); 0282 action->setToolTip(i18n("Show statistics.")); 0283 0284 // Move 0285 KGameStandardAction::undo(this, &KWin4App::undoMove, actionCollection()); 0286 KGameStandardAction::redo(this, &KWin4App::redoMove, actionCollection()); 0287 0288 KStandardAction::preferences(this, &KWin4App::configureSettings, actionCollection()); 0289 0290 // Add all theme files to the menu 0291 QStringList themes(mThemeFiles.keys()); 0292 themes.sort(); 0293 0294 KSelectAction *themeAction = new KSelectAction(i18n("Theme"), this); 0295 actionCollection()->addAction(QStringLiteral("theme"), themeAction); 0296 themeAction->setIcon(QIcon::fromTheme(QStringLiteral("games-config-theme"))); 0297 themeAction->setItems(themes); 0298 connect(themeAction, &KSelectAction::indexTriggered, this, &KWin4App::changeTheme); 0299 qCDebug(KFOURINLINE_LOG) << "Setting current theme item to" << mThemeIndexNo; 0300 themeAction->setCurrentItem(mThemeIndexNo); 0301 0302 // Debug 0303 if (global_debug > 0) { 0304 action = actionCollection()->addAction(QStringLiteral("file_debug")); 0305 action->setText(i18n("Debug KGame")); 0306 connect(action, &QAction::triggered, this, &KWin4App::debugKGame); 0307 } 0308 } 0309 0310 // Change the theme of the game 0311 void KWin4App::changeTheme(int idx) 0312 { 0313 mThemeIndexNo = idx; 0314 QString themeFile = themefileFromIdx(idx); 0315 qCDebug(KFOURINLINE_LOG) << "Select theme" << themeFile; 0316 mTheme->updateTheme(themeFile); 0317 updateStatusNames(); 0318 } 0319 0320 // Create the status bar with the message part, the player part. 0321 void KWin4App::initStatusBar() 0322 { 0323 mStatusMsg = new QLabel(); 0324 mStatusMover = new QLabel(); 0325 statusBar()->addWidget(mStatusMsg); 0326 statusBar()->addPermanentWidget(mStatusMover); 0327 0328 displayStatusMessage(i18n("Welcome to Four Wins")); 0329 } 0330 0331 // Set up the document, i.e. the KGame object 0332 // and connect all signals emitted by it 0333 void KWin4App::connectDocument() 0334 { 0335 // KGame signals 0336 connect(mDoc, &KWin4Doc::signalGameOver, this, &KWin4App::slotGameOver); 0337 connect(mDoc, &KWin4Doc::signalNextPlayer, this, &KWin4App::moveDone); 0338 connect(mDoc, &KWin4Doc::signalClientLeftGame, this, &KWin4App::networkBroken); 0339 connect(mDoc, &KWin4Doc::signalGameRun, this, &KWin4App::gameRun); 0340 } 0341 0342 // Enable or disable an action 0343 void KWin4App::changeAction(const QString &action, bool enable) 0344 { 0345 QAction *act = actionCollection()->action(action); 0346 if (act) { 0347 act->setEnabled(enable); 0348 } 0349 } 0350 0351 // Save instance-specific properties. The function is 0352 void KWin4App::saveProperties(KConfigGroup &grp) 0353 { 0354 qCDebug(KFOURINLINE_LOG) << "SAVE PROPERTIES for GROUP" << grp.name(); 0355 0356 // Save current game? 0357 QString name = QStringLiteral("current_game") + grp.name(); 0358 QString filename = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QLatin1Char('/') + name; 0359 bool isRunning = (mDoc->gameStatus() == KGame::Run); 0360 if (isRunning) { 0361 qCDebug(KFOURINLINE_LOG) << "Saving" << filename; 0362 mDoc->save(filename); 0363 grp.writeEntry("CurrentGame", filename); 0364 } else { 0365 QFile file(filename); 0366 qCDebug(KFOURINLINE_LOG) << "Deleting" << file.fileName(); 0367 file.remove(); 0368 grp.deleteEntry("CurrentGame"); 0369 } 0370 } 0371 0372 // Read instance-specific properties. 0373 void KWin4App::readProperties(const KConfigGroup &grp) 0374 { 0375 qCDebug(KFOURINLINE_LOG) << "READ PROPERTIES for GROUP" << grp.name(); 0376 0377 QString filename = grp.readEntry("CurrentGame", QString()); 0378 qCDebug(KFOURINLINE_LOG) << "Filename is" << filename; 0379 0380 if (!filename.isNull() && QFile::exists(filename)) { 0381 qCDebug(KFOURINLINE_LOG) << "Loading" << filename; 0382 // TODO: CRASHES mDoc->load(filename); 0383 qCDebug(KFOURINLINE_LOG) << "Loading" << filename << "done"; 0384 } 0385 } 0386 0387 // Store the current game 0388 void KWin4App::saveProperties() 0389 { 0390 KConfig *config = KSharedConfig::openConfig().data(); 0391 0392 // Program data 0393 KConfigGroup cfg = config->group(QStringLiteral("ProgramData")); 0394 cfg.writeEntry("ThemeIndexNo", mThemeIndexNo); 0395 0396 mDoc->writeConfig(config); 0397 0398 config->sync(); 0399 qCDebug(KFOURINLINE_LOG) << "SAVED PROPERTIES"; 0400 } 0401 0402 // Load current game back 0403 void KWin4App::readProperties() 0404 { 0405 KConfig *config = KSharedConfig::openConfig().data(); 0406 0407 // Program data 0408 KConfigGroup cfg = config->group(QStringLiteral("ProgramData")); 0409 mThemeIndexNo = cfg.readEntry("ThemeIndexNo", themeIdxFromName(mThemeDefault)); 0410 if (mThemeIndexNo >= mThemeFiles.size()) 0411 mThemeIndexNo = 0; 0412 qCDebug(KFOURINLINE_LOG) << "Index = " << mThemeIndexNo << " def index=" << themeIdxFromName(mThemeDefault); 0413 0414 qCDebug(KFOURINLINE_LOG) << "LOADED PROPERTIES"; 0415 } 0416 0417 // Load a game menu 0418 void KWin4App::menuOpenGame() 0419 { 0420 const QString file = (global_debug < 1) ? QFileDialog::getOpenFileName(this) : QStringLiteral("/tmp/kwin.save"); 0421 mDoc->load(file, true); 0422 checkMenus(); 0423 } 0424 0425 // Save game menu 0426 void KWin4App::menuSaveGame() 0427 { 0428 const QString file = (global_debug < 1) ? QFileDialog::getSaveFileName(this) : QStringLiteral("/tmp/kwin.save"); 0429 mDoc->save(file); 0430 } 0431 0432 // Received quick start command from view 0433 void KWin4App::quickStart(COLOUR startPlayer, KGameIO::IOMode input0, KGameIO::IOMode input1, int level) 0434 { 0435 if (startPlayer == Yellow) { 0436 Prefs::setStartcolourred(false); 0437 Prefs::setStartcolouryellow(true); 0438 } else if (startPlayer == Red) { 0439 Prefs::setStartcolourred(true); 0440 Prefs::setStartcolouryellow(false); 0441 } 0442 if (level >= 0) { 0443 Prefs::setLevel(level); 0444 } 0445 if (input0 == KGameIO::MouseIO) { 0446 Prefs::setInput0mouse(true); 0447 Prefs::setInput0key(false); 0448 Prefs::setInput0ai(false); 0449 } 0450 if (input0 == KGameIO::ProcessIO) { 0451 Prefs::setInput0mouse(false); 0452 Prefs::setInput0key(false); 0453 Prefs::setInput0ai(true); 0454 } 0455 if (input1 == KGameIO::MouseIO) { 0456 Prefs::setInput1mouse(true); 0457 Prefs::setInput1key(false); 0458 Prefs::setInput1ai(false); 0459 } 0460 if (input1 == KGameIO::ProcessIO) { 0461 Prefs::setInput1mouse(false); 0462 Prefs::setInput1key(false); 0463 Prefs::setInput1ai(true); 0464 } 0465 0466 // Reload settings 0467 mDoc->loadSettings(); 0468 0469 // Start game (direct call will crash as intro object will be deleted) 0470 QTimer::singleShot(0, this, &KWin4App::menuNewGame); 0471 } 0472 0473 // Start a new game menu 0474 void KWin4App::menuNewGame() 0475 { 0476 qCDebug(KFOURINLINE_LOG) << "MENU NEW GAME"; 0477 // End the intro if it is running 0478 mDoc->setGameStatus(KWin4Doc::End); 0479 // Init the board and Clear the old game out 0480 mDoc->setGameStatus(KWin4Doc::Init); 0481 // Run it 0482 mDoc->setGameStatus(KWin4Doc::Run); 0483 // Display game status 0484 displayStatusMessage(i18n("Game running...")); 0485 } 0486 0487 // Slot: Noticed that a new game started...update menus 0488 void KWin4App::gameRun() 0489 { 0490 updateStatusNames(); 0491 checkMenus(All); 0492 } 0493 0494 // Abort a running game 0495 void KWin4App::endGame() 0496 { 0497 mDoc->setGameStatus(KWin4Doc::Abort); 0498 } 0499 0500 // Menu to ask for a game hint 0501 void KWin4App::askForHint() 0502 { 0503 if (mDoc) 0504 mDoc->calculateHint(); 0505 } 0506 0507 // Show statistics dialog 0508 void KWin4App::showStatistics() 0509 { 0510 QPointer<QDialog> dlg = new QDialog(this); 0511 Ui::Statistics ui; 0512 ui.setupUi(dlg); 0513 0514 ui.p1_name->setText(mDoc->getName(Yellow)); 0515 ui.p1_won->display(mDoc->getStatistic(Yellow, TWin)); 0516 ui.p1_drawn->display(mDoc->getStatistic(Yellow, TRemis)); 0517 ui.p1_lost->display(mDoc->getStatistic(Yellow, TLost)); 0518 ui.p1_aborted->display(mDoc->getStatistic(Yellow, TBrk)); 0519 ui.p1_sum->display(mDoc->getStatistic(Yellow, TSum)); 0520 0521 ui.p2_name->setText(mDoc->getName(Red)); 0522 ui.p2_won->display(mDoc->getStatistic(Red, TWin)); 0523 ui.p2_drawn->display(mDoc->getStatistic(Red, TRemis)); 0524 ui.p2_lost->display(mDoc->getStatistic(Red, TLost)); 0525 ui.p2_aborted->display(mDoc->getStatistic(Red, TBrk)); 0526 ui.p2_sum->display(mDoc->getStatistic(Red, TSum)); 0527 0528 if (dlg->exec() == QDialog::Rejected) { 0529 mDoc->resetStatistic(); 0530 } 0531 delete dlg; 0532 } 0533 0534 // Undo menu call 0535 void KWin4App::undoMove() 0536 { 0537 mDoc->undoMove(); 0538 // Undo twice if computer is moving to keep player as input 0539 if (mDoc->playedBy(mDoc->getCurrentPlayer()) == KGameIO::ProcessIO) { 0540 mDoc->undoMove(); 0541 } else { 0542 // Make sure the current player has the turn 0543 // without this it can happen that the AI still think has the turn and plays 0544 // instead of the human player 0545 mDoc->getPlayer(mDoc->getCurrentPlayer())->setTurn(true); 0546 } 0547 0548 // Refresh menus 0549 updateStatusNames(); 0550 checkMenus(CheckEditMenu); 0551 } 0552 0553 // Redo menu call 0554 void KWin4App::redoMove() 0555 { 0556 mDoc->redoMove(); 0557 // Redo twice if computer is moving to keep player as input 0558 if (mDoc->playedBy(mDoc->getCurrentPlayer()) == KGameIO::ProcessIO) { 0559 mDoc->redoMove(); 0560 } 0561 updateStatusNames(); 0562 checkMenus(CheckEditMenu); 0563 } 0564 0565 // Set the given text into the statusbar change status message permanently 0566 void KWin4App::displayStatusMessage(const QString &text) 0567 { 0568 mStatusMsg->setText(text); 0569 } 0570 0571 // Set the string in the statusbar window for 0572 // the player currently moving change status mover permanently 0573 void KWin4App::displayStatusbarMover(const QString &text) 0574 { 0575 mStatusMover->setText(text); 0576 } 0577 0578 // Ends the current game. 0579 // Called by the gameover signal 0580 void KWin4App::EndGame(TABLE mode) 0581 { 0582 mDoc->endGame(mode); 0583 mDoc->switchStartPlayer(); 0584 updateStatusNames(); 0585 checkMenus(); 0586 0587 // Automatically restart game in demo mode 0588 if (global_demo_mode) { 0589 QTimer::singleShot(10000, this, &KWin4App::menuNewGame); 0590 } 0591 } 0592 0593 // Set the names in the mover field 0594 void KWin4App::updateStatusNames() 0595 { 0596 QString msg; 0597 if (!(mDoc->gameStatus() == KGame::Run)) 0598 msg = i18n("No game "); 0599 else if (mDoc->getCurrentPlayer() == Yellow) 0600 msg = i18n(" %1 - %2 ", mDoc->getName(Yellow), mTheme->colorNamePlayer(0)); 0601 else if (mDoc->getCurrentPlayer()) 0602 msg = i18n(" %1 - %2 ", mDoc->getName(Red), mTheme->colorNamePlayer(1)); 0603 else 0604 msg = i18n("Nobody "); 0605 displayStatusbarMover(msg); 0606 } 0607 0608 // Notification that the network connection is lost. 0609 void KWin4App::networkBroken(int /*id*/, int oldstatus, KGame * /*game */) 0610 { 0611 qCDebug(KFOURINLINE_LOG) << "KWin4App::networkBroken(" << oldstatus << ")"; 0612 0613 // Set all input devices back to default 0614 if (mDoc->playedBy(Yellow) == 0) 0615 mDoc->setPlayedBy(Yellow, KGameIO::MouseIO); 0616 if (mDoc->playedBy(Red) == 0) 0617 mDoc->setPlayedBy(Red, KGameIO::MouseIO); 0618 0619 qCDebug(KFOURINLINE_LOG) << "CurrrentPlayer=" << mDoc->getCurrentPlayer(); 0620 qCDebug(KFOURINLINE_LOG) << " " << mDoc->getPlayer(mDoc->getCurrentPlayer()); 0621 0622 // Activate input device 0623 mDoc->getPlayer(mDoc->getCurrentPlayer())->setTurn(true, true); 0624 0625 // Issue message 0626 KMessageBox::information(this, i18n("The network game ended!\n")); 0627 0628 // Restore status 0629 mDoc->setGameStatus(oldstatus); 0630 } 0631 0632 // A move is done. Update status display. 0633 void KWin4App::moveDone(int /*playerNumber*/) 0634 { 0635 checkMenus(CheckEditMenu); 0636 updateStatusNames(); 0637 displayStatusMessage(i18n("Game running...")); 0638 } 0639 0640 // The game is over or aborted. Set status and display it. 0641 void KWin4App::slotGameOver(int status, KPlayer *p, KGame * /*me*/) 0642 { 0643 qCDebug(KFOURINLINE_LOG) << "KWin4App::slotGameOver"; 0644 if (status == -1) // remis 0645 { 0646 EndGame(TRemis); 0647 displayStatusMessage(i18n("The game is drawn. Please restart next round.")); 0648 } else if (status == 1) // One of the players won 0649 { 0650 if (p->userId() == Yellow) 0651 EndGame(TWin); 0652 else 0653 EndGame(TLost); 0654 QString msg = i18n("%1 won the game. Please restart next round.", mDoc->getName(((COLOUR)p->userId()))); 0655 displayStatusMessage(msg); 0656 } else if (status == 2) // Abort 0657 { 0658 EndGame(TBrk); 0659 QString m = i18n(" Game ended. Please restart next round."); 0660 displayStatusMessage(m); 0661 } else { 0662 qCCritical(KFOURINLINE_LOG) << "Gameover with status" << status << ". This is unexpected and a serious problem"; 0663 } 0664 checkMenus(CheckEditMenu); 0665 } 0666 0667 // Show the network configuration dialog 0668 void KWin4App::configureNetwork() 0669 { 0670 if (mDoc->gameStatus() == KWin4Doc::Intro) { 0671 mDoc->setGameStatus(KWin4Doc::Pause); 0672 } 0673 0674 QString host = Prefs::host(); 0675 int port = Prefs::port(); 0676 0677 // just for testing - should be non-modal 0678 KGameDialog dlg(mDoc, nullptr, i18n("Network Configuration"), this); 0679 dlg.networkConfig()->setDefaultNetworkInfo(host, port); 0680 dlg.networkConfig()->setDiscoveryInfo(QStringLiteral("_kfourinline._tcp"), Prefs::gamename()); 0681 0682 QWidget *box = dlg.configPage(); 0683 QLayout *l = box->layout(); 0684 0685 mColorGroup = new QGroupBox(box); 0686 QVBoxLayout *grouplay = new QVBoxLayout(mColorGroup); 0687 connect(dlg.networkConfig(), &KGameDialogNetworkConfig::signalServerTypeChanged, this, &KWin4App::serverTypeChanged); 0688 0689 QRadioButton *b1 = new QRadioButton(i18n("Black should be played by remote player"), mColorGroup); 0690 QRadioButton *b2 = new QRadioButton(i18n("Red should be played by remote player"), mColorGroup); 0691 grouplay->addWidget(b1); 0692 grouplay->addWidget(b2); 0693 l->addWidget(mColorGroup); 0694 b1->setChecked(true); 0695 remoteChanged(0); 0696 0697 connect(b1, &QAbstractButton::toggled, this, [this](bool toggled) { 0698 if (toggled) 0699 remoteChanged(0); 0700 }); 0701 connect(b2, &QAbstractButton::toggled, this, [this](bool toggled) { 0702 if (toggled) 0703 remoteChanged(1); 0704 }); 0705 0706 dlg.adjustSize(); 0707 dlg.exec(); // note: we don't have to check for the result - maybe a bug 0708 } 0709 0710 // Can't get rid of this function in KGame's current state. 0711 // Can't pass a int signal to a bool slot, so this must be here 0712 void KWin4App::serverTypeChanged(int t) 0713 { 0714 mColorGroup->setDisabled(t); 0715 } 0716 0717 // The remote player in the network dialog has changed. Adapt priorities. 0718 void KWin4App::remoteChanged(int button) 0719 { 0720 if (button == 0) { 0721 mDoc->getPlayer(Yellow)->setNetworkPriority(0); 0722 mDoc->getPlayer(Red)->setNetworkPriority(10); 0723 } else { 0724 mDoc->getPlayer(Yellow)->setNetworkPriority(10); 0725 mDoc->getPlayer(Red)->setNetworkPriority(0); 0726 } 0727 } 0728 0729 // Show the chat dialog. 0730 void KWin4App::configureChat() 0731 { 0732 if (!mMyChatDlg) { 0733 mMyChatDlg = new ChatDlg(mDoc, this); 0734 KWin4Player *p = mDoc->getPlayer(Yellow); 0735 if (!p->isVirtual()) 0736 mMyChatDlg->setPlayer(mDoc->getPlayer(Yellow)); 0737 else 0738 mMyChatDlg->setPlayer(mDoc->getPlayer(Red)); 0739 connect(mDoc, &KWin4Doc::signalChatChanged, mMyChatDlg, &ChatDlg::setPlayer); 0740 } 0741 0742 if (mMyChatDlg->isHidden()) 0743 mMyChatDlg->show(); 0744 else 0745 mMyChatDlg->hide(); 0746 } 0747 0748 // Show the KGame debug window. 0749 void KWin4App::debugKGame() 0750 { 0751 KGameDebugDialog *debugWindow = new KGameDebugDialog(mDoc, this); 0752 debugWindow->show(); 0753 } 0754 0755 // Show Configure dialog. 0756 void KWin4App::configureSettings() 0757 { 0758 static Ui::Settings ui; // Dialog is internally static anyway 0759 if (KConfigDialog::showDialog(QStringLiteral("settings"))) { 0760 // The dialog need to refresh the buttons as they are not connectable via a signal-slot 0761 // in KConfigDialog 0762 ui.kcfg_startcolourred->setChecked(Prefs::startcolourred()); 0763 ui.kcfg_startcolourred->setText(mTheme->colorNamePlayer(0)); 0764 ui.kcfg_startcolouryellow->setChecked(Prefs::startcolouryellow()); 0765 ui.kcfg_startcolouryellow->setText(mTheme->colorNamePlayer(1)); 0766 ui.kcfg_level->setValue(Prefs::level()); 0767 ui.Input0->setTitle(i18n("%1 Plays With", mTheme->colorNamePlayer(0))); 0768 ui.Input1->setTitle(i18n("%1 Plays With", mTheme->colorNamePlayer(1))); 0769 ui.kcfg_input0mouse->setChecked(Prefs::input0mouse()); 0770 ui.kcfg_input0key->setChecked(Prefs::input0key()); 0771 ui.kcfg_input0ai->setChecked(Prefs::input0ai()); 0772 ui.kcfg_input1mouse->setChecked(Prefs::input1mouse()); 0773 ui.kcfg_input1key->setChecked(Prefs::input1key()); 0774 ui.kcfg_input1ai->setChecked(Prefs::input1ai()); 0775 0776 return; 0777 } 0778 0779 KConfigDialog *dialog = new KConfigDialog(this, QStringLiteral("settings"), Prefs::self()); 0780 dialog->setFaceType(KPageDialog::Plain); 0781 dialog->button(QDialogButtonBox::Ok)->setDefault(true); 0782 dialog->setModal(true); 0783 // QT5 dialog->setHelp(QString(),"kfourinline"); 0784 QWidget *frame = new QWidget(dialog); 0785 ui.setupUi(frame); 0786 ui.kcfg_startcolourred->setText(mTheme->colorNamePlayer(0)); 0787 ui.kcfg_startcolouryellow->setText(mTheme->colorNamePlayer(1)); 0788 ui.Input0->setTitle(i18n("%1 Plays With", mTheme->colorNamePlayer(0))); 0789 ui.Input1->setTitle(i18n("%1 Plays With", mTheme->colorNamePlayer(1))); 0790 dialog->addPage(frame, i18n("General"), QStringLiteral("games-config-options")); 0791 connect(dialog, &KConfigDialog::settingsChanged, mDoc, &KWin4Doc::loadSettings); 0792 dialog->show(); 0793 } 0794 0795 #include "moc_kwin4.cpp"