Warning, file /games/kfourinline/src/kwin4.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
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 <KStandardGameAction> 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(QStringList() << 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, "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("move_hint", !(!isRunning && localgame)); 0211 changeAction("game_new", !isRunning); 0212 changeAction("game_save", isRunning); 0213 changeAction("game_end", isRunning); 0214 } 0215 0216 // Edit menu 0217 if (!menu || (menu & CheckEditMenu)) { 0218 if (!isRunning || !localgame) { 0219 disableAction("move_undo"); 0220 } else if (mDoc->getHistoryCnt() == 0) { 0221 disableAction("move_undo"); 0222 } else if (mDoc->getCurrentMove() < 1) { 0223 disableAction("move_undo"); 0224 } else { 0225 enableAction("move_undo"); 0226 } 0227 0228 // Show redo 0229 if (!isRunning || !localgame) { 0230 disableAction("move_redo"); 0231 } else if (mDoc->getHistoryCnt() == mDoc->getMaxMove()) { 0232 disableAction("move_redo"); 0233 } else { 0234 enableAction("move_redo"); 0235 } 0236 } 0237 0238 // Disable some menus in demo mode 0239 if (global_demo_mode) { 0240 disableAction(KStandardAction::name(KStandardAction::Preferences)); 0241 disableAction("move_undo"); 0242 disableAction("move_redo"); 0243 disableAction("game_new"); 0244 disableAction("game_end"); 0245 disableAction("game_save"); 0246 disableAction("game_open"); 0247 disableAction("network_conf"); 0248 disableAction("network_chat"); 0249 disableAction("statistics"); 0250 disableAction("move_hint"); 0251 } 0252 } 0253 0254 // Create the actions for the menu. This works together with the xml guirc file 0255 void KWin4App::initGUI() 0256 { 0257 QAction *action; 0258 0259 // Game 0260 KStandardGameAction::gameNew(this, &KWin4App::menuNewGame, actionCollection()); 0261 KStandardGameAction::load(this, &KWin4App::menuOpenGame, actionCollection()); 0262 KStandardGameAction::save(this, &KWin4App::menuSaveGame, actionCollection()); 0263 action = KStandardGameAction::end(this, &KWin4App::endGame, actionCollection()); 0264 action->setWhatsThis(i18n("Ends a currently played game. No winner will be declared.")); 0265 KStandardGameAction::hint(this, &KWin4App::askForHint, actionCollection()); 0266 KStandardGameAction::quit(this, &KWin4App::close, actionCollection()); 0267 0268 action = actionCollection()->addAction(QStringLiteral("network_conf")); 0269 action->setText(i18n("&Network Configuration...")); 0270 connect(action, &QAction::triggered, this, &KWin4App::configureNetwork); 0271 0272 action = actionCollection()->addAction(QStringLiteral("network_chat")); 0273 action->setText(i18n("Network Chat...")); 0274 connect(action, &QAction::triggered, this, &KWin4App::configureChat); 0275 0276 action = actionCollection()->addAction(QStringLiteral("statistics")); 0277 action->setIcon(QIcon::fromTheme(QStringLiteral("view-statistics"))); 0278 action->setText(i18n("&Show Statistics")); 0279 connect(action, &QAction::triggered, this, &KWin4App::showStatistics); 0280 action->setToolTip(i18n("Show statistics.")); 0281 0282 // Move 0283 KStandardGameAction::undo(this, &KWin4App::undoMove, actionCollection()); 0284 KStandardGameAction::redo(this, &KWin4App::redoMove, actionCollection()); 0285 0286 KStandardAction::preferences(this, &KWin4App::configureSettings, actionCollection()); 0287 0288 // Add all theme files to the menu 0289 QStringList themes(mThemeFiles.keys()); 0290 themes.sort(); 0291 0292 KSelectAction *themeAction = new KSelectAction(i18n("Theme"), this); 0293 actionCollection()->addAction(QStringLiteral("theme"), themeAction); 0294 themeAction->setIcon(QIcon::fromTheme(QStringLiteral("games-config-theme"))); 0295 themeAction->setItems(themes); 0296 connect(themeAction, &KSelectAction::indexTriggered, this, &KWin4App::changeTheme); 0297 qCDebug(KFOURINLINE_LOG) << "Setting current theme item to" << mThemeIndexNo; 0298 themeAction->setCurrentItem(mThemeIndexNo); 0299 0300 // Debug 0301 if (global_debug > 0) { 0302 action = actionCollection()->addAction(QStringLiteral("file_debug")); 0303 action->setText(i18n("Debug KGame")); 0304 connect(action, &QAction::triggered, this, &KWin4App::debugKGame); 0305 } 0306 } 0307 0308 // Change the theme of the game 0309 void KWin4App::changeTheme(int idx) 0310 { 0311 mThemeIndexNo = idx; 0312 QString themeFile = themefileFromIdx(idx); 0313 qCDebug(KFOURINLINE_LOG) << "Select theme" << themeFile; 0314 mTheme->updateTheme(themeFile); 0315 updateStatusNames(); 0316 } 0317 0318 // Create the status bar with the message part, the player part. 0319 void KWin4App::initStatusBar() 0320 { 0321 mStatusMsg = new QLabel(); 0322 mStatusMover = new QLabel(); 0323 statusBar()->addWidget(mStatusMsg); 0324 statusBar()->addPermanentWidget(mStatusMover); 0325 0326 displayStatusMessage(i18n("Welcome to Four Wins")); 0327 } 0328 0329 // Set up the document, i.e. the KGame object 0330 // and connect all signals emitted by it 0331 void KWin4App::connectDocument() 0332 { 0333 // KGame signals 0334 connect(mDoc, &KWin4Doc::signalGameOver, this, &KWin4App::slotGameOver); 0335 connect(mDoc, &KWin4Doc::signalNextPlayer, this, &KWin4App::moveDone); 0336 connect(mDoc, &KWin4Doc::signalClientLeftGame, this, &KWin4App::networkBroken); 0337 connect(mDoc, &KWin4Doc::signalGameRun, this, &KWin4App::gameRun); 0338 } 0339 0340 // Enable or disable an action 0341 void KWin4App::changeAction(const char *action, bool enable) 0342 { 0343 if (!action) { 0344 return; 0345 } 0346 0347 QAction *act = actionCollection()->action(QLatin1String(action)); 0348 if (act) { 0349 act->setEnabled(enable); 0350 } 0351 } 0352 0353 // Save instance-specific properties. The function is 0354 void KWin4App::saveProperties(KConfigGroup &grp) 0355 { 0356 qCDebug(KFOURINLINE_LOG) << "SAVE PROPERTIES for GROUP" << grp.name(); 0357 0358 // Save current game? 0359 QString name = QStringLiteral("current_game") + grp.name(); 0360 QString filename = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QLatin1Char('/') + name; 0361 bool isRunning = (mDoc->gameStatus() == KGame::Run); 0362 if (isRunning) { 0363 qCDebug(KFOURINLINE_LOG) << "Saving" << filename; 0364 mDoc->save(filename); 0365 grp.writeEntry("CurrentGame", filename); 0366 } else { 0367 QFile file(filename); 0368 qCDebug(KFOURINLINE_LOG) << "Deleting" << file.fileName(); 0369 file.remove(); 0370 grp.deleteEntry("CurrentGame"); 0371 } 0372 } 0373 0374 // Read instance-specific properties. 0375 void KWin4App::readProperties(const KConfigGroup &grp) 0376 { 0377 qCDebug(KFOURINLINE_LOG) << "READ PROPERTIES for GROUP" << grp.name(); 0378 0379 QString filename = grp.readEntry("CurrentGame", QString()); 0380 qCDebug(KFOURINLINE_LOG) << "Filename is" << filename; 0381 0382 if (!filename.isNull() && QFile::exists(filename)) { 0383 qCDebug(KFOURINLINE_LOG) << "Loading" << filename; 0384 // TODO: CRASHES mDoc->load(filename); 0385 qCDebug(KFOURINLINE_LOG) << "Loading" << filename << "done"; 0386 } 0387 } 0388 0389 // Store the current game 0390 void KWin4App::saveProperties() 0391 { 0392 KConfig *config = KSharedConfig::openConfig().data(); 0393 0394 // Program data 0395 KConfigGroup cfg = config->group("ProgramData"); 0396 cfg.writeEntry("ThemeIndexNo", mThemeIndexNo); 0397 0398 mDoc->writeConfig(config); 0399 0400 config->sync(); 0401 qCDebug(KFOURINLINE_LOG) << "SAVED PROPERTIES"; 0402 } 0403 0404 // Load current game back 0405 void KWin4App::readProperties() 0406 { 0407 KConfig *config = KSharedConfig::openConfig().data(); 0408 0409 // Program data 0410 KConfigGroup cfg = config->group("ProgramData"); 0411 mThemeIndexNo = cfg.readEntry("ThemeIndexNo", themeIdxFromName(mThemeDefault)); 0412 if (mThemeIndexNo >= mThemeFiles.size()) 0413 mThemeIndexNo = 0; 0414 qCDebug(KFOURINLINE_LOG) << "Index = " << mThemeIndexNo << " def index=" << themeIdxFromName(mThemeDefault); 0415 0416 qCDebug(KFOURINLINE_LOG) << "LOADED PROPERTIES"; 0417 } 0418 0419 // Load a game menu 0420 void KWin4App::menuOpenGame() 0421 { 0422 const QString file = (global_debug < 1) ? QFileDialog::getOpenFileName(this) : QStringLiteral("/tmp/kwin.save"); 0423 mDoc->load(file, true); 0424 checkMenus(); 0425 } 0426 0427 // Save game menu 0428 void KWin4App::menuSaveGame() 0429 { 0430 const QString file = (global_debug < 1) ? QFileDialog::getSaveFileName(this) : QStringLiteral("/tmp/kwin.save"); 0431 mDoc->save(file); 0432 } 0433 0434 // Received quick start command from view 0435 void KWin4App::quickStart(COLOUR startPlayer, KGameIO::IOMode input0, KGameIO::IOMode input1, int level) 0436 { 0437 if (startPlayer == Yellow) { 0438 Prefs::setStartcolourred(false); 0439 Prefs::setStartcolouryellow(true); 0440 } else if (startPlayer == Red) { 0441 Prefs::setStartcolourred(true); 0442 Prefs::setStartcolouryellow(false); 0443 } 0444 if (level >= 0) { 0445 Prefs::setLevel(level); 0446 } 0447 if (input0 == KGameIO::MouseIO) { 0448 Prefs::setInput0mouse(true); 0449 Prefs::setInput0key(false); 0450 Prefs::setInput0ai(false); 0451 } 0452 if (input0 == KGameIO::ProcessIO) { 0453 Prefs::setInput0mouse(false); 0454 Prefs::setInput0key(false); 0455 Prefs::setInput0ai(true); 0456 } 0457 if (input1 == KGameIO::MouseIO) { 0458 Prefs::setInput1mouse(true); 0459 Prefs::setInput1key(false); 0460 Prefs::setInput1ai(false); 0461 } 0462 if (input1 == KGameIO::ProcessIO) { 0463 Prefs::setInput1mouse(false); 0464 Prefs::setInput1key(false); 0465 Prefs::setInput1ai(true); 0466 } 0467 0468 // Reload settings 0469 mDoc->loadSettings(); 0470 0471 // Start game (direct call will crash as intro object will be deleted) 0472 QTimer::singleShot(0, this, &KWin4App::menuNewGame); 0473 } 0474 0475 // Start a new game menu 0476 void KWin4App::menuNewGame() 0477 { 0478 qCDebug(KFOURINLINE_LOG) << "MENU NEW GAME"; 0479 // End the intro if it is running 0480 mDoc->setGameStatus(KWin4Doc::End); 0481 // Init the board and Clear the old game out 0482 mDoc->setGameStatus(KWin4Doc::Init); 0483 // Run it 0484 mDoc->setGameStatus(KWin4Doc::Run); 0485 // Display game status 0486 displayStatusMessage(i18n("Game running...")); 0487 } 0488 0489 // Slot: Noticed that a new game started...update menus 0490 void KWin4App::gameRun() 0491 { 0492 updateStatusNames(); 0493 checkMenus(All); 0494 } 0495 0496 // Abort a running game 0497 void KWin4App::endGame() 0498 { 0499 mDoc->setGameStatus(KWin4Doc::Abort); 0500 } 0501 0502 // Menu to ask for a game hint 0503 void KWin4App::askForHint() 0504 { 0505 if (mDoc) 0506 mDoc->calculateHint(); 0507 } 0508 0509 // Show statistics dialog 0510 void KWin4App::showStatistics() 0511 { 0512 QPointer<QDialog> dlg = new QDialog(this); 0513 Ui::Statistics ui; 0514 ui.setupUi(dlg); 0515 0516 ui.p1_name->setText(mDoc->getName(Yellow)); 0517 ui.p1_won->display(mDoc->getStatistic(Yellow, TWin)); 0518 ui.p1_drawn->display(mDoc->getStatistic(Yellow, TRemis)); 0519 ui.p1_lost->display(mDoc->getStatistic(Yellow, TLost)); 0520 ui.p1_aborted->display(mDoc->getStatistic(Yellow, TBrk)); 0521 ui.p1_sum->display(mDoc->getStatistic(Yellow, TSum)); 0522 0523 ui.p2_name->setText(mDoc->getName(Red)); 0524 ui.p2_won->display(mDoc->getStatistic(Red, TWin)); 0525 ui.p2_drawn->display(mDoc->getStatistic(Red, TRemis)); 0526 ui.p2_lost->display(mDoc->getStatistic(Red, TLost)); 0527 ui.p2_aborted->display(mDoc->getStatistic(Red, TBrk)); 0528 ui.p2_sum->display(mDoc->getStatistic(Red, TSum)); 0529 0530 if (dlg->exec() == QDialog::Rejected) { 0531 mDoc->resetStatistic(); 0532 } 0533 delete dlg; 0534 } 0535 0536 // Undo menu call 0537 void KWin4App::undoMove() 0538 { 0539 mDoc->undoMove(); 0540 // Undo twice if computer is moving to keep player as input 0541 if (mDoc->playedBy(mDoc->getCurrentPlayer()) == KGameIO::ProcessIO) { 0542 mDoc->undoMove(); 0543 } else { 0544 // Make sure the current player has the turn 0545 // without this it can happen that the AI still think has the turn and plays 0546 // instead of the human player 0547 mDoc->getPlayer(mDoc->getCurrentPlayer())->setTurn(true); 0548 } 0549 0550 // Refresh menus 0551 updateStatusNames(); 0552 checkMenus(CheckEditMenu); 0553 } 0554 0555 // Redo menu call 0556 void KWin4App::redoMove() 0557 { 0558 mDoc->redoMove(); 0559 // Redo twice if computer is moving to keep player as input 0560 if (mDoc->playedBy(mDoc->getCurrentPlayer()) == KGameIO::ProcessIO) { 0561 mDoc->redoMove(); 0562 } 0563 updateStatusNames(); 0564 checkMenus(CheckEditMenu); 0565 } 0566 0567 // Set the given text into the statusbar change status message permanently 0568 void KWin4App::displayStatusMessage(const QString &text) 0569 { 0570 mStatusMsg->setText(text); 0571 } 0572 0573 // Set the string in the statusbar window for 0574 // the player currently moving change status mover permanently 0575 void KWin4App::displayStatusbarMover(const QString &text) 0576 { 0577 mStatusMover->setText(text); 0578 } 0579 0580 // Ends the current game. 0581 // Called by the gameover signal 0582 void KWin4App::EndGame(TABLE mode) 0583 { 0584 mDoc->endGame(mode); 0585 mDoc->switchStartPlayer(); 0586 updateStatusNames(); 0587 checkMenus(); 0588 0589 // Automatically restart game in demo mode 0590 if (global_demo_mode) { 0591 QTimer::singleShot(10000, this, &KWin4App::menuNewGame); 0592 } 0593 } 0594 0595 // Set the names in the mover field 0596 void KWin4App::updateStatusNames() 0597 { 0598 QString msg; 0599 if (!(mDoc->gameStatus() == KGame::Run)) 0600 msg = i18n("No game "); 0601 else if (mDoc->getCurrentPlayer() == Yellow) 0602 msg = i18n(" %1 - %2 ", mDoc->getName(Yellow), mTheme->colorNamePlayer(0)); 0603 else if (mDoc->getCurrentPlayer()) 0604 msg = i18n(" %1 - %2 ", mDoc->getName(Red), mTheme->colorNamePlayer(1)); 0605 else 0606 msg = i18n("Nobody "); 0607 displayStatusbarMover(msg); 0608 } 0609 0610 // Notification that the network connection is lost. 0611 void KWin4App::networkBroken(int /*id*/, int oldstatus, KGame * /*game */) 0612 { 0613 qCDebug(KFOURINLINE_LOG) << "KWin4App::networkBroken(" << oldstatus << ")"; 0614 0615 // Set all input devices back to default 0616 if (mDoc->playedBy(Yellow) == 0) 0617 mDoc->setPlayedBy(Yellow, KGameIO::MouseIO); 0618 if (mDoc->playedBy(Red) == 0) 0619 mDoc->setPlayedBy(Red, KGameIO::MouseIO); 0620 0621 qCDebug(KFOURINLINE_LOG) << "CurrrentPlayer=" << mDoc->getCurrentPlayer(); 0622 qCDebug(KFOURINLINE_LOG) << " " << mDoc->getPlayer(mDoc->getCurrentPlayer()); 0623 0624 // Activate input device 0625 mDoc->getPlayer(mDoc->getCurrentPlayer())->setTurn(true, true); 0626 0627 // Issue message 0628 KMessageBox::information(this, i18n("The network game ended!\n")); 0629 0630 // Restore status 0631 mDoc->setGameStatus(oldstatus); 0632 } 0633 0634 // A move is done. Update status display. 0635 void KWin4App::moveDone(int /*playerNumber*/) 0636 { 0637 checkMenus(CheckEditMenu); 0638 updateStatusNames(); 0639 displayStatusMessage(i18n("Game running...")); 0640 } 0641 0642 // The game is over or aborted. Set status and display it. 0643 void KWin4App::slotGameOver(int status, KPlayer *p, KGame * /*me*/) 0644 { 0645 qCDebug(KFOURINLINE_LOG) << "KWin4App::slotGameOver"; 0646 if (status == -1) // remis 0647 { 0648 EndGame(TRemis); 0649 displayStatusMessage(i18n("The game is drawn. Please restart next round.")); 0650 } else if (status == 1) // One of the players won 0651 { 0652 if (p->userId() == Yellow) 0653 EndGame(TWin); 0654 else 0655 EndGame(TLost); 0656 QString msg = i18n("%1 won the game. Please restart next round.", mDoc->getName(((COLOUR)p->userId()))); 0657 displayStatusMessage(msg); 0658 } else if (status == 2) // Abort 0659 { 0660 EndGame(TBrk); 0661 QString m = i18n(" Game ended. Please restart next round."); 0662 displayStatusMessage(m); 0663 } else { 0664 qCCritical(KFOURINLINE_LOG) << "Gameover with status" << status << ". This is unexpected and a serious problem"; 0665 } 0666 checkMenus(CheckEditMenu); 0667 } 0668 0669 // Show the network configuration dialog 0670 void KWin4App::configureNetwork() 0671 { 0672 if (mDoc->gameStatus() == KWin4Doc::Intro) { 0673 mDoc->setGameStatus(KWin4Doc::Pause); 0674 } 0675 0676 QString host = Prefs::host(); 0677 int port = Prefs::port(); 0678 0679 // just for testing - should be non-modal 0680 KGameDialog dlg(mDoc, nullptr, i18n("Network Configuration"), this); 0681 dlg.networkConfig()->setDefaultNetworkInfo(host, port); 0682 dlg.networkConfig()->setDiscoveryInfo(QStringLiteral("_kfourinline._tcp"), Prefs::gamename()); 0683 0684 QWidget *box = dlg.configPage(); 0685 QLayout *l = box->layout(); 0686 0687 mColorGroup = new QGroupBox(box); 0688 QVBoxLayout *grouplay = new QVBoxLayout(mColorGroup); 0689 connect(dlg.networkConfig(), &KGameDialogNetworkConfig::signalServerTypeChanged, this, &KWin4App::serverTypeChanged); 0690 0691 QRadioButton *b1 = new QRadioButton(i18n("Black should be played by remote player"), mColorGroup); 0692 QRadioButton *b2 = new QRadioButton(i18n("Red should be played by remote player"), mColorGroup); 0693 grouplay->addWidget(b1); 0694 grouplay->addWidget(b2); 0695 l->addWidget(mColorGroup); 0696 b1->setChecked(true); 0697 remoteChanged(0); 0698 0699 connect(b1, &QAbstractButton::toggled, this, [this](bool toggled) { 0700 if (toggled) 0701 remoteChanged(0); 0702 }); 0703 connect(b2, &QAbstractButton::toggled, this, [this](bool toggled) { 0704 if (toggled) 0705 remoteChanged(1); 0706 }); 0707 0708 dlg.adjustSize(); 0709 dlg.exec(); // note: we don't have to check for the result - maybe a bug 0710 } 0711 0712 // Can't get rid of this function in KGame's current state. 0713 // Can't pass a int signal to a bool slot, so this must be here 0714 void KWin4App::serverTypeChanged(int t) 0715 { 0716 mColorGroup->setDisabled(t); 0717 } 0718 0719 // The remote player in the network dialog has changed. Adapt priorities. 0720 void KWin4App::remoteChanged(int button) 0721 { 0722 if (button == 0) { 0723 mDoc->getPlayer(Yellow)->setNetworkPriority(0); 0724 mDoc->getPlayer(Red)->setNetworkPriority(10); 0725 } else { 0726 mDoc->getPlayer(Yellow)->setNetworkPriority(10); 0727 mDoc->getPlayer(Red)->setNetworkPriority(0); 0728 } 0729 } 0730 0731 // Show the chat dialog. 0732 void KWin4App::configureChat() 0733 { 0734 if (!mMyChatDlg) { 0735 mMyChatDlg = new ChatDlg(mDoc, this); 0736 KWin4Player *p = mDoc->getPlayer(Yellow); 0737 if (!p->isVirtual()) 0738 mMyChatDlg->setPlayer(mDoc->getPlayer(Yellow)); 0739 else 0740 mMyChatDlg->setPlayer(mDoc->getPlayer(Red)); 0741 connect(mDoc, &KWin4Doc::signalChatChanged, mMyChatDlg, &ChatDlg::setPlayer); 0742 } 0743 0744 if (mMyChatDlg->isHidden()) 0745 mMyChatDlg->show(); 0746 else 0747 mMyChatDlg->hide(); 0748 } 0749 0750 // Show the KGame debug window. 0751 void KWin4App::debugKGame() 0752 { 0753 KGameDebugDialog *debugWindow = new KGameDebugDialog(mDoc, this); 0754 debugWindow->show(); 0755 } 0756 0757 // Show Configure dialog. 0758 void KWin4App::configureSettings() 0759 { 0760 static Ui::Settings ui; // Dialog is internally static anyway 0761 if (KConfigDialog::showDialog(QStringLiteral("settings"))) { 0762 // The dialog need to refresh the buttons as they are not connectable via a signal-slot 0763 // in KConfigDialog 0764 ui.kcfg_startcolourred->setChecked(Prefs::startcolourred()); 0765 ui.kcfg_startcolourred->setText(mTheme->colorNamePlayer(0)); 0766 ui.kcfg_startcolouryellow->setChecked(Prefs::startcolouryellow()); 0767 ui.kcfg_startcolouryellow->setText(mTheme->colorNamePlayer(1)); 0768 ui.kcfg_level->setValue(Prefs::level()); 0769 ui.Input0->setTitle(i18n("%1 Plays With", mTheme->colorNamePlayer(0))); 0770 ui.Input1->setTitle(i18n("%1 Plays With", mTheme->colorNamePlayer(1))); 0771 ui.kcfg_input0mouse->setChecked(Prefs::input0mouse()); 0772 ui.kcfg_input0key->setChecked(Prefs::input0key()); 0773 ui.kcfg_input0ai->setChecked(Prefs::input0ai()); 0774 ui.kcfg_input1mouse->setChecked(Prefs::input1mouse()); 0775 ui.kcfg_input1key->setChecked(Prefs::input1key()); 0776 ui.kcfg_input1ai->setChecked(Prefs::input1ai()); 0777 0778 return; 0779 } 0780 0781 KConfigDialog *dialog = new KConfigDialog(this, QStringLiteral("settings"), Prefs::self()); 0782 dialog->setFaceType(KPageDialog::Plain); 0783 dialog->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel | QDialogButtonBox::Help); 0784 dialog->button(QDialogButtonBox::Ok)->setDefault(true); 0785 dialog->setModal(true); 0786 // QT5 dialog->setHelp(QString(),"kfourinline"); 0787 QWidget *frame = new QWidget(dialog); 0788 ui.setupUi(frame); 0789 ui.kcfg_startcolourred->setText(mTheme->colorNamePlayer(0)); 0790 ui.kcfg_startcolouryellow->setText(mTheme->colorNamePlayer(1)); 0791 ui.Input0->setTitle(i18n("%1 Plays With", mTheme->colorNamePlayer(0))); 0792 ui.Input1->setTitle(i18n("%1 Plays With", mTheme->colorNamePlayer(1))); 0793 dialog->addPage(frame, i18n("General"), QStringLiteral("games-config-options")); 0794 connect(dialog, &KConfigDialog::settingsChanged, mDoc, &KWin4Doc::loadSettings); 0795 dialog->show(); 0796 } 0797 0798 #include "moc_kwin4.cpp"