00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <QRadioButton>
00020 #include <QLayout>
00021
00022
00023 #include <kvbox.h>
00024 #include <kstandardgameaction.h>
00025 #include <kmessagebox.h>
00026 #include <kfiledialog.h>
00027 #include <klocale.h>
00028 #include <khelpmenu.h>
00029 #include <kconfig.h>
00030 #include <kdebug.h>
00031 #include <kstandardaction.h>
00032 #include <kaction.h>
00033 #include <kstatusbar.h>
00034 #include <kconfigdialog.h>
00035 #include <kactioncollection.h>
00036 #include <kbuttongroup.h>
00037 #include <kicon.h>
00038 #include <kstandarddirs.h>
00039 #include <kglobal.h>
00040
00041
00042 #include <kgamechat.h>
00043 #include <dialogs/kgamedialog.h>
00044 #include <dialogs/kgamedialogconfig.h>
00045 #include <dialogs/kgameconnectdialog.h>
00046 #include <dialogs/kgameerrordialog.h>
00047 #include <dialogs/kgamedebugdialog.h>
00048
00049
00050 #include "kwin4.h"
00051 #include "chatdlg.h"
00052 #include "kwin4doc.h"
00053 #include "kwin4view.h"
00054 #include "prefs.h"
00055 #include "ui_settings.h"
00056 #include "ui_statistics.h"
00057
00058
00059 #define ACTION(x) (actionCollection()->action(x))
00060 #define ID_STATUS_MSG 1003
00061 #define ID_STATUS_MOVER 1002
00062
00063
00064
00065 #include "config-src.h"
00066
00067
00068 KWin4App::KWin4App(QWidget *parent)
00069 : KMainWindow(parent), mView(0), mDoc(0), mMyChatDlg(0)
00070 {
00071 #ifdef SRC_DIR
00072 kDebug() << "Found SRC_DIR =" << SRC_DIR << endl;
00073 KGlobal::dirs()->addResourceDir("data",QString(SRC_DIR)+QString("/grafix/"));
00074 QString theme = KStandardDirs::locate("data", "default.rc");
00075 kDebug() << "theme =" << theme << endl;
00076 #endif
00077
00078 mThemeDirName = KGlobal::dirs()->findResourceDir("data","default.rc");
00079 kDebug() << "THEME DIR IS " << mThemeDirName << endl;
00080
00081
00082 initGUI();
00083 initStatusBar();
00084 initDocument();
00085
00086
00087 mScene = new QGraphicsScene(this);
00088
00089
00090 mTheme = new ThemeManager("default.rc", this);
00091
00092
00093 mView = new KWin4View(QSize(800,600),25,mScene,mTheme,this);
00094 mDoc->setView(mView);
00095
00096
00097 mDoc->initPlayers();
00098
00099
00100 setCentralWidget(mView);
00101 setupGUI();
00102
00103
00104 mDoc->readConfig(KGlobal::config().data());
00105
00106
00107 checkMenus();
00108 }
00109
00110
00111
00112 KWin4App::~KWin4App()
00113 {
00114 kDebug() << "~KWin4App()" << endl;
00115 if (mDoc) delete mDoc;
00116 if (mView) delete mView;
00117 if (mScene) delete mScene;
00118 if (mTheme) delete mTheme;
00119 if (mMyChatDlg) delete mMyChatDlg;
00120
00121 }
00122
00123
00124
00125
00126
00127
00128 void KWin4App::checkMenus(CheckFlags menu)
00129 {
00130 bool localgame=(!mDoc->isNetwork());
00131 bool isRunning = (mDoc->gameStatus()==KGame::Run);
00132
00133
00134 if (!menu || (menu&CheckFileMenu))
00135 {
00136 changeAction("hint", !(!isRunning && localgame));
00137 changeAction("new_game", !isRunning);
00138 changeAction("save", isRunning);
00139 changeAction("end_game", isRunning);
00140 }
00141
00142
00143 if (!menu || (menu&CheckEditMenu))
00144 {
00145 if (!isRunning || !localgame)
00146 {
00147 disableAction("edit_undo");
00148 }
00149 else if (mDoc->getHistoryCnt()==0)
00150 {
00151 disableAction("edit_undo");
00152 }
00153 else if (mDoc->getCurrentMove()<1 )
00154 {
00155 disableAction("edit_undo");
00156 }
00157 else
00158 {
00159 enableAction("edit_undo");
00160 }
00161
00162
00163 if (!isRunning || !localgame)
00164 {
00165 disableAction("edit_redo");
00166 }
00167 else if (mDoc->getHistoryCnt()==mDoc->getMaxMove())
00168 {
00169 disableAction("edit_redo");
00170 }
00171 else
00172 {
00173 enableAction("edit_redo");
00174 }
00175 }
00176 }
00177
00178
00179 void KWin4App::initGUI()
00180 {
00181 QAction* action;
00182
00183 action = KStandardGameAction::gameNew(this, SLOT(menuNewGame()), this);
00184 actionCollection()->addAction("new_game", action);
00185 ACTION("new_game")->setToolTip(i18n("Start a new game"));
00186
00187 action = KStandardGameAction::load(this, SLOT(menuOpenGame()), this);
00188 actionCollection()->addAction("open", action);
00189 ACTION("open")->setToolTip(i18n("Open a saved game..."));
00190
00191 action = KStandardGameAction::save(this, SLOT(menuSaveGame()), this);
00192 actionCollection()->addAction("save", action);
00193 ACTION("save")->setToolTip(i18n("Save a game..."));
00194
00195 action = KStandardGameAction::end(this, SLOT(endGame()), this);
00196 actionCollection()->addAction("end_game", action);
00197 ACTION("end_game")->setToolTip(i18n("Ending the current game..."));
00198 ACTION("end_game")->setWhatsThis(i18n("Aborts a currently played game. No winner will be declared."));
00199
00200 action = actionCollection()->addAction("network_conf");
00201 action->setText(i18n("&Network Configuration..."));
00202 connect(action, SIGNAL(triggered(bool) ), SLOT(configureNetwork()));
00203
00204 action = actionCollection()->addAction("network_chat");
00205 action->setText(i18n("Network Chat..."));
00206 connect(action, SIGNAL(triggered(bool) ), SLOT(configureChat()));
00207
00208 if (global_debug>0)
00209 {
00210 action = actionCollection()->addAction("file_debug");
00211 action->setText(i18n("Debug KGame"));
00212 connect(action, SIGNAL(triggered(bool) ), SLOT(debugKGame()));
00213 }
00214
00215 action = actionCollection()->addAction("statistics");
00216 action->setIcon(KIcon("flag"));
00217 action->setText(i18n("&Show Statistics"));
00218 connect(action, SIGNAL(triggered(bool)), SLOT(showStatistics()));
00219 ACTION("statistics")->setToolTip(i18n("Show statistics."));
00220
00221 action = KStandardGameAction::hint(this, SLOT(askForHint()), this);
00222 actionCollection()->addAction("hint", action);
00223 ACTION("hint")->setToolTip(i18n("Shows a hint on how to move."));
00224
00225 action = KStandardGameAction::quit(this, SLOT(close()), this);
00226 actionCollection()->addAction("game_exit", action);
00227 ACTION("game_exit")->setToolTip(i18n("Quits the program."));
00228
00229 action = KStandardGameAction::undo(this, SLOT(undoMove()), this);
00230 actionCollection()->addAction("edit_undo", action);
00231 ACTION("edit_undo")->setToolTip(i18n("Undo last move."));
00232
00233 action = KStandardGameAction::redo(this, SLOT(redoMove()), this);
00234 actionCollection()->addAction("edit_redo", action);
00235 ACTION("edit_redo")->setToolTip(i18n("Redo last move."));
00236
00237 actionCollection()->addAction(KStandardAction::Preferences, this, SLOT(configureSettings()));
00238
00239
00240 QDir dir(mThemeDirName);
00241 QStringList filters;
00242 filters.append("*.rc");
00243 QStringList rcFiles = dir.entryList(filters);
00244 kDebug() << "Theme dir = " << mThemeDirName << endl;
00245 kDebug() << "Available theme files="<<rcFiles<<endl;
00246
00247 action = actionCollection()->addAction("theme", new KSelectAction(i18n("Theme"), this));
00248 ((KSelectAction*)action)->setItems(rcFiles);
00249 connect( action, SIGNAL(triggered(const QString&)), SLOT(changeTheme(const QString&)) );
00250 }
00251
00252
00253
00254 void KWin4App::changeTheme(const QString& name)
00255 {
00256 QString theme = name;
00257 theme.replace("&","");
00258 mTheme->updateTheme(theme);
00259
00260 }
00261
00262
00263
00264 void KWin4App::initStatusBar()
00265 {
00266 statusBar()->insertPermanentItem(i18n("This leaves space for the mover"),ID_STATUS_MOVER,0);
00267 statusBar()->insertItem(i18n("Ready"), ID_STATUS_MSG);
00268
00269 displayStatusbarMover("");
00270 displayStatusMessage(i18n("Welcome to Four Wins"));
00271 }
00272
00273
00274
00275
00276 void KWin4App::initDocument()
00277 {
00278 mDoc = new KWin4Doc(this);
00279
00280
00281 connect(mDoc,SIGNAL(signalGameOver(int, KPlayer*,KGame*)),
00282 this,SLOT(slotGameOver(int, KPlayer*,KGame *)));
00283 connect(mDoc,SIGNAL(signalNextPlayer(int)),
00284 this,SLOT(moveDone(int)));
00285 connect(mDoc,SIGNAL(signalClientLeftGame(int, int,KGame*)),
00286 this,SLOT(networkBroken(int, int, KGame*)));
00287 connect(mDoc,SIGNAL(signalGameRun()),
00288 this,SLOT(gameRun()));
00289 }
00290
00291
00292
00293 void KWin4App::changeAction(const char* action, bool enable)
00294 {
00295 if (!action)
00296 {
00297 return;
00298 }
00299
00300 QAction* act=actionCollection()->action(action);
00301 if (act)
00302 {
00303 act->setEnabled(enable);
00304 }
00305 }
00306
00307
00308
00309 void KWin4App::saveProperties(KConfigGroup& )
00310 {
00311 QString filename = KStandardDirs::locateLocal("appdata", "current_game");
00312 mDoc->save(filename);
00313 }
00314
00315
00316 void KWin4App::readProperties(const KConfigGroup& )
00317 {
00318 QString filename = KStandardDirs::locateLocal("appdata", "current_game");
00319 if(QFile::exists(filename))
00320 {
00321 mDoc->load(filename);
00322 }
00323 }
00324
00325
00326
00327 void KWin4App::menuOpenGame()
00328 {
00329 QString dir(":<kwin4>");
00330 QString filter("*");
00331 QString file("/tmp/kwin.save");
00332 if (global_debug < 10)
00333 file=KFileDialog::getOpenFileName(dir,filter,this);
00334 mDoc->load(file,true);
00335 checkMenus();
00336 }
00337
00338
00339 void KWin4App::menuSaveGame()
00340 {
00341 QString dir(":<kwin4>");
00342 QString filter("*");
00343 QString file("/tmp/kwin.save");
00344 if (global_debug < 10)
00345 file=KFileDialog::getSaveFileName(dir,filter,this);
00346 mDoc->save(file);
00347 }
00348
00349
00350
00351 void KWin4App::menuNewGame()
00352 {
00353
00354 mDoc->setGameStatus(KWin4Doc::End);
00355
00356 mDoc->setGameStatus(KWin4Doc::Init);
00357
00358 mDoc->setGameStatus(KWin4Doc::Run);
00359
00360 displayStatusMessage(i18n("Game running..."));
00361 }
00362
00363
00364
00365 void KWin4App::gameRun()
00366 {
00367 updateStatusNames();
00368 checkMenus(All);
00369 }
00370
00371
00372
00373 void KWin4App::endGame()
00374 {
00375 mDoc->setGameStatus(KWin4Doc::Abort);
00376 }
00377
00378
00379
00380 void KWin4App::askForHint()
00381 {
00382 if (mDoc) mDoc->calculateHint();
00383 }
00384
00385
00386
00387 void KWin4App::showStatistics()
00388 {
00389 QDialog dlg(this);
00390 Ui::Statistics ui;
00391 ui.setupUi(&dlg);
00392
00393 ui.p1_name->setText(mDoc->getName(Yellow));
00394 ui.p1_won->display(mDoc->getStatistic(Yellow, TWin));
00395 ui.p1_drawn->display(mDoc->getStatistic(Yellow, TRemis));
00396 ui.p1_lost->display(mDoc->getStatistic(Yellow, TLost));
00397 ui.p1_aborted->display(mDoc->getStatistic(Yellow, TBrk));
00398 ui.p1_sum->display(mDoc->getStatistic(Yellow, TSum));
00399
00400 ui.p2_name->setText(mDoc->getName(Red));
00401 ui.p2_won->display(mDoc->getStatistic(Red, TWin));
00402 ui.p2_drawn->display(mDoc->getStatistic(Red, TRemis));
00403 ui.p2_lost->display(mDoc->getStatistic(Red, TLost));
00404 ui.p2_aborted->display(mDoc->getStatistic(Red, TBrk));
00405 ui.p2_sum->display(mDoc->getStatistic(Red, TSum));
00406
00407 if(dlg.exec() == QDialog::Rejected)
00408 {
00409 mDoc->resetStatistic();
00410 }
00411 }
00412
00413
00414
00415 void KWin4App::undoMove()
00416 {
00417 mDoc->undoMove();
00418
00419 if (mDoc->playedBy(mDoc->getCurrentPlayer())==KGameIO::ProcessIO)
00420 {
00421 mDoc->undoMove();
00422 }
00423
00424
00425 updateStatusNames();
00426 checkMenus(CheckEditMenu);
00427 }
00428
00429
00430 void KWin4App::redoMove()
00431 {
00432 mDoc->redoMove();
00433
00434 if (mDoc->playedBy(mDoc->getCurrentPlayer())==KGameIO::ProcessIO)
00435 {
00436 mDoc->redoMove();
00437 }
00438 updateStatusNames();
00439 checkMenus(CheckEditMenu);
00440 }
00441
00442
00443
00444 void KWin4App::displayStatusMessage(const QString &text)
00445 {
00446 statusBar()->clearMessage();
00447 statusBar()->changeItem(text, ID_STATUS_MSG);
00448 }
00449
00450
00451
00452
00453 void KWin4App::displayStatusbarMover(const QString& text)
00454 {
00455 statusBar()->clearMessage();
00456 statusBar()->changeItem(text, ID_STATUS_MOVER);
00457 }
00458
00459
00460
00461
00462 void KWin4App::EndGame(TABLE mode)
00463 {
00464 mDoc->endGame(mode);
00465 mDoc->switchStartPlayer();
00466 updateStatusNames();
00467 checkMenus();
00468 }
00469
00470
00471
00472 void KWin4App::updateStatusNames()
00473 {
00474 QString msg;
00475 if (!(mDoc->gameStatus()==KGame::Run))
00476 msg=i18n("No game ");
00477 else if (mDoc->getCurrentPlayer()==Yellow)
00478 msg=i18n(" %1 - Yellow ", mDoc->getName(Yellow));
00479 else if (mDoc->getCurrentPlayer())
00480 msg=i18n(" %1 - Red ", mDoc->getName(Red));
00481 else
00482 msg=i18n("Nobody ");
00483 displayStatusbarMover(msg);
00484 }
00485
00486
00487 void KWin4App::networkBroken(int , int oldstatus ,KGame * )
00488 {
00489 kDebug(12010) << "KWin4App::networkBroken("<<oldstatus<<")" << endl;
00490
00491
00492 if (mDoc->playedBy(Yellow)==0)
00493 mDoc->setPlayedBy(Yellow,KGameIO::MouseIO);
00494 if (mDoc->playedBy(Red)==0)
00495 mDoc->setPlayedBy(Red,KGameIO::MouseIO);
00496
00497 kDebug(12010) << "CurrrentPlayer=" << mDoc->getCurrentPlayer() << endl;
00498 kDebug(12010) << " " << mDoc->getPlayer(mDoc->getCurrentPlayer()) << endl;
00499
00500
00501 mDoc->getPlayer(mDoc->getCurrentPlayer())->setTurn(true,true);
00502
00503
00504 KMessageBox::information(this,i18n("The network game ended!\n"));
00505
00506
00507 mDoc->setGameStatus(oldstatus);
00508 }
00509
00510
00511
00512 void KWin4App::moveDone(int playerNumber)
00513 {
00514 checkMenus(CheckEditMenu);
00515 updateStatusNames();
00516 displayStatusMessage(i18n("Game running..."));
00517 }
00518
00519
00520 void KWin4App::slotGameOver(int status, KPlayer* p, KGame* )
00521 {
00522 kDebug() << "KWin4App::slotGameOver" << endl;
00523 if (status==-1)
00524 {
00525 EndGame(TRemis);
00526 displayStatusMessage(i18n("The game is drawn. Please restart next round."));
00527 }
00528 else if (status==1)
00529 {
00530 if (p->userId()==Yellow)
00531 EndGame(TWin);
00532 else
00533 EndGame(TLost);
00534 QString msg=i18n("%1 won the game. Please restart next round.", mDoc->getName(((COLOUR)p->userId())));
00535 displayStatusMessage(msg);
00536 }
00537 else if (status==2)
00538 {
00539 EndGame(TBrk);
00540 QString m=i18n(" Game aborted. Please restart next round.");
00541 displayStatusMessage(m);
00542 }
00543 else
00544 {
00545 kError() << "Gameover with status " << status << ". This is unexpected and a serious problem" << endl;
00546 }
00547 checkMenus(CheckEditMenu);
00548 }
00549
00550
00551
00552 void KWin4App::configureNetwork()
00553 {
00554 if (mDoc->gameStatus()==KWin4Doc::Intro)
00555 {
00556 mDoc->setGameStatus(KWin4Doc::Pause);
00557 }
00558
00559 QString host = Prefs::host();
00560 int port=Prefs::port();
00561
00562
00563 KGameDialog dlg(mDoc, 0, i18n("Network Configuration"), this,
00564 KGameDialog::NetworkConfig, 20000, true);
00565 dlg.networkConfig()->setDefaultNetworkInfo(host, port);
00566 dlg.networkConfig()->setDiscoveryInfo("_kwin4._tcp",Prefs::gamename());
00567
00568 KVBox *box=dlg.configPage(KGameDialog::NetworkConfig);
00569 QVBoxLayout *l=(QVBoxLayout *)(box->layout());
00570
00571 mColorGroup=new KButtonGroup(box);
00572 connect(mColorGroup, SIGNAL(clicked(int)), this, SLOT(remoteChanged(int)));
00573 connect(dlg.networkConfig(), SIGNAL(signalServerTypeChanged(int)), this, SLOT(serverTypeChanged(int)));
00574
00575 new QRadioButton(i18n("Yellow should be played by remote"), mColorGroup);
00576 new QRadioButton(i18n("Red should be played by remote"), mColorGroup);
00577 l->addWidget(mColorGroup);
00578 mColorGroup->setSelected(0);
00579 remoteChanged(0);
00580
00581 dlg.exec();
00582 }
00583
00584
00585
00586 void KWin4App::serverTypeChanged(int t)
00587 {
00588 mColorGroup->setDisabled(t);
00589 }
00590
00591
00592
00593 void KWin4App::remoteChanged(int button)
00594 {
00595 if (button==0)
00596 {
00597 mDoc->getPlayer(Yellow)->setNetworkPriority(0);
00598 mDoc->getPlayer(Red)->setNetworkPriority(10);
00599 }
00600 else
00601 {
00602 mDoc->getPlayer(Yellow)->setNetworkPriority(10);
00603 mDoc->getPlayer(Red)->setNetworkPriority(0);
00604 }
00605 }
00606
00607
00608
00609 void KWin4App::configureChat()
00610 {
00611 if (!mMyChatDlg)
00612 {
00613 mMyChatDlg=new ChatDlg(mDoc,this);
00614 KWin4Player *p=mDoc->getPlayer(Yellow);
00615 if (!p->isVirtual())
00616 mMyChatDlg->setPlayer(mDoc->getPlayer(Yellow));
00617 else
00618 mMyChatDlg->setPlayer(mDoc->getPlayer(Red));
00619 connect(mDoc,SIGNAL(signalChatChanged(KWin4Player *)),
00620 mMyChatDlg,SLOT(setPlayer(KWin4Player *)));
00621 }
00622
00623 if (mMyChatDlg->isHidden())
00624 mMyChatDlg->show();
00625 else
00626 mMyChatDlg->hide();
00627 }
00628
00629
00630
00631 void KWin4App::debugKGame()
00632 {
00633 KGameDebugDialog* debugWindow = new KGameDebugDialog(mDoc, this);
00634 debugWindow->show();
00635 }
00636
00637
00638
00639 void KWin4App::configureSettings()
00640 {
00641 if(KConfigDialog::showDialog("settings"))
00642 {
00643 return;
00644 }
00645
00646 KConfigDialog* dialog = new KConfigDialog(this, "settings", Prefs::self(), KPageDialog::Plain);
00647 Ui::Settings ui;
00648 QWidget* frame = new QWidget(dialog);
00649 ui.setupUi(frame);
00650 dialog->addPage(frame, i18n("General"), "package_settings");
00651 connect(dialog, SIGNAL(settingsChanged(const QString &)), mDoc, SLOT(loadSettings()));
00652 dialog->show();
00653 }
00654
00655 #include "kwin4.moc"