mainwindow.cpp

Go to the documentation of this file.
00001 /*
00002    This file is part of the KDE games lskat program
00003    Copyright (c) 2006 Martin Heni <kde@heni-online.de>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018    Boston, MA 02110-1301, USA.
00019 */
00020 
00021 // Include files for Qt
00022 
00023 #include <QDir>
00024 #include <QFile>
00025 
00026 // Include files for KDE
00027 #include <kstandardgameaction.h>
00028 #include <kmessagebox.h>
00029 #include <kfiledialog.h>
00030 #include <khelpmenu.h>
00031 #include <kdebug.h>
00032 #include <kstandardaction.h>
00033 #include <kaction.h>
00034 #include <kactioncollection.h>
00035 #include <kstatusbar.h>
00036 #include <kstandarddirs.h>
00037 #include <kicon.h>
00038 #include <kmenubar.h>
00039 #include <klocale.h>
00040 #include <kcarddialog.h>
00041 #include <krandom.h>
00042 #include <kglobal.h>
00043 #include <ktoolbar.h>
00044 #include <kselectaction.h>
00045 
00046 // Application specific includes
00047 #include "mainwindow.h"
00048 #include "lskatglobal.h"
00049 #include "gameview.h"
00050 #include "abstractengine.h"
00051 #include "engine_two.h"
00052 #include "display_two.h"
00053 #include "config_two.h"
00054 #include "display_intro.h"
00055 #include "deck.h"
00056 #include "player.h"
00057 #include "mouseinput.h"
00058 #include "aiinput.h"
00059 #include "namedialogwidget.h"
00060 
00061 // Configuration file
00062 #include "config-src.h"
00063 
00064 // Forward declarations
00065 #define ADVANCE_PERDIOD 20
00066 
00067 // Shortcut to access the actions
00068 #define ACTION(x)   (actionCollection()->action(x))
00069 
00070 using namespace InputDevice;
00071 
00072 
00073 // Construct the main application window
00074 Mainwindow::Mainwindow(QWidget* parent)
00075           : KXmlGuiWindow(parent)
00076 {
00077   // Reset stuff
00078   mDeck    = 0;
00079   mEngine  = 0;
00080   mDisplay = 0;
00081   mView    = 0;
00082 
00083   #ifdef SRC_DIR
00084   kDebug() << "Found SRC_DIR =" << SRC_DIR << endl;
00085   KGlobal::dirs()->addResourceDir("data",QString(SRC_DIR)+QString("/grafix/"));
00086   QString theme = KStandardDirs::locate("data", "default.rc");
00087   kDebug() << "theme =" << theme << endl;
00088   #endif
00089 
00090   // Theme file
00091   mThemeDirName = KGlobal::dirs()->findResourceDir("data","default.rc");
00092   kDebug() << "THEME DIR IS " << mThemeDirName << endl;
00093 
00094   // Create menus etc
00095   initGUI();
00096 
00097   // The LSkat config
00098   mLSkatConfig = new ConfigTwo(this);
00099   connect(mLSkatConfig, SIGNAL(signalInputType(int,InputDeviceType)),
00100           this, SLOT(setInputType(int,InputDeviceType)));
00101   mLSkatConfig->reset();
00102 
00103   // Read game properties and set default values (after config)
00104   readProperties();
00105 
00106 
00107   // Get the card deck
00108   long seed = KRandom::random();
00109   if (global_debug > 0) kDebug() << "Random seed " << seed << endl;
00110   mDeck = new Deck(seed, this);
00111 
00112   // Theme manager
00113   mTheme  = new ThemeManager(mCardDir, mDeckGrafix, "default.rc", this);
00114 
00115   // Overall view
00116   mCanvas        = new QGraphicsScene(this);
00117   mView          = new GameView(QSize(880, 675), ADVANCE_PERDIOD, mCanvas, mTheme, this);
00118 
00119   // Create intro
00120   mGameMode      = Intro;
00121   mDisplay       = new DisplayIntro(mDeck, mCanvas, mTheme, ADVANCE_PERDIOD, mView);
00122   setCentralWidget(mView);
00123 
00124   // Create GUI
00125   setupGUI();
00126   toolBar()->hide();
00127   statusBar()->show();
00128   setAutoSaveSettings();
00129 
00130   statusBar()->showMessage(i18n("Welcome to Skat! Please start a new game."));
00131 
00132   // Skip intro?
00133   if (global_skip_intro)
00134   {
00135     menuNewLSkatGame();
00136   }
00137   // Start game automatically in demo mode
00138   else if (global_demo_mode)
00139   {
00140     // Start intro
00141     mDisplay->start();
00142     QTimer::singleShot(12500, this,SLOT(menuNewLSkatGame()));
00143   }
00144   else
00145   {
00146     // Start intro
00147     mDisplay->start();
00148   }
00149 
00150 }
00151 
00152 // Destructor
00153 Mainwindow::~Mainwindow()
00154 {
00155   saveProperties();
00156   if (mEngine) delete mEngine;
00157   if (mDisplay) delete mDisplay;
00158   if (mLSkatConfig) delete mLSkatConfig;
00159   if (mDeck) delete mDeck;
00160   if (mView) delete mView;
00161   if (mCanvas) delete mCanvas;
00162   if (mTheme) delete mTheme;
00163 }
00164 
00165 
00166 // Called by KMainWindow when the last window of the application is
00167 bool Mainwindow::queryExit()
00168 {
00169   if (mEngine)
00170   {
00171     mEngine->stopGame();
00172   }
00173   saveProperties();
00174   return true;
00175 }
00176 
00177 
00178 // Save properties
00179 void Mainwindow::saveProperties()
00180 {
00181   KConfig *config = KGlobal::config().data();
00182 
00183   // Program data
00184   KConfigGroup cfg = config->group("ProgramData");
00185   cfg.writePathEntry("carddir", mCardDir);
00186   cfg.writePathEntry("deck",    mDeckGrafix);
00187   cfg.writeEntry("startplayer", mStartPlayer);
00188 
00189   // LSkat data
00190   mLSkatConfig->save(config);
00191   config->sync();
00192 }
00193 
00194 
00195 // Load properties
00196 void Mainwindow::readProperties()
00197 {
00198   KConfig *config = KGlobal::config().data();
00199 
00200   // Program data
00201   KConfigGroup cfg = config->group("ProgramData");
00202 
00203   // Get default card data
00204   QString dcd = KCardDialog::getDefaultCardDir();
00205   dcd = KGlobal::dirs()->findResourceDir("cards", dcd)+dcd;
00206   QString dd = KCardDialog::getDefaultDeck();
00207   dd = KGlobal::dirs()->findResourceDir("cards", dd)+dd;
00208 
00209   // Read card path
00210   mCardDir    = cfg.readPathEntry("carddir", dcd);
00211   mDeckGrafix = cfg.readPathEntry("deck", dd);
00212 
00213   // Check for path existence
00214   QFile file(mDeckGrafix);
00215   if (!file.exists()) mDeckGrafix = dd;
00216   QDir dir(mCardDir);
00217   if (!dir.exists()) mCardDir = dcd;
00218 
00219   if (global_debug > 0)
00220   {
00221     kDebug() << "set mDeckGrafix=" << mDeckGrafix << endl;
00222     kDebug() << "set mCardDir=" << mCardDir << endl;
00223   }
00224 
00225   int no = cfg.readEntry("startplayer", 0);
00226   setStartPlayer(no);
00227   mLSkatConfig->load(config);
00228 }
00229 
00230 
00231 // Create a input with the given type
00232 AbstractInput* Mainwindow::createInput(
00233                                  InputDeviceType inputType,
00234                                  AbstractDisplay* display,
00235                                  AbstractEngine* engine)
00236 {
00237    AbstractInput* input = 0;
00238 
00239   // Always use AI input in demo mode
00240   if (global_demo_mode)
00241   {
00242     inputType = TypeAiInput;
00243   }
00244 
00245   // Create the player input
00246   if (inputType == TypeMouseInput)
00247   {
00248     MouseInput* mouseInput = new MouseInput(this);
00249     connect((QObject*)mView, SIGNAL(signalLeftMousePress(QPoint)),
00250             mouseInput, SLOT(mousePress(QPoint)));
00251     connect(mouseInput, SIGNAL(signalConvertMousePress(QPoint,int&,int&)),
00252             display, SLOT(convertMousePress(QPoint,int&,int&)));
00253     connect(mouseInput, SIGNAL(signalPlayerInput(int,int,int)),
00254             engine, SLOT(playerInput(int,int,int) ));
00255     input = mouseInput;
00256     if (global_debug > 0) kDebug() << "Create MOUSE INPUT " << endl;
00257   }
00258   else if (inputType == TypeAiInput)
00259   {
00260     AiInput* aiInput = new AiInput((EngineTwo*)engine, this);
00261     connect(aiInput, SIGNAL(signalPlayerInput(int,int,int)),
00262             engine, SLOT(playerInput(int,int,int) ));
00263     input = aiInput;
00264     if (global_debug > 0) kDebug() << "Create AI INPUT " << endl;
00265   }
00266   else
00267   {
00268     kFatal() << "Unpupported input device type " << inputType << endl;
00269   }
00270 
00271   return input;
00272 }
00273 
00274 
00275 // Start a new game
00276 void Mainwindow::startGame()
00277 {
00278   // Enable game action
00279   ACTION("end_game")->setEnabled(true);
00280 
00281   // Deal cards to player - Shuffle card deck and reset pile
00282   mDeck->shuffle();
00283 
00284   // Draw Trump
00285   Suite trump = mDeck->randomTrump();
00286 
00287   // Loop all players in the game
00288   QHashIterator<int,Player*> it = mLSkatConfig->playerIterator();
00289   while(it.hasNext())
00290   {
00291     it.next();
00292     Player* player = it.value();
00293     player->setDeck(mDeck);
00294     // Deal cards
00295     player->deal(16);
00296     // Store trump
00297     player->setTrump(trump);
00298   }
00299 
00300   // Start display
00301   mDisplay->start();
00302 
00303   // Start the game engine
00304   mEngine->startGame(trump, mStartPlayer);
00305 
00306   // Start player for next game
00307   setStartPlayer(1-mStartPlayer);
00308 
00309   //  statusBar()->clearMessage();
00310 }
00311 
00312 
00313 // Here a game over is signalled
00314 void Mainwindow::gameOver(int /*winner*/)
00315 {
00316   ACTION("end_game")->setEnabled(false);
00317   statusBar()->showMessage(i18n("Game Over. Please start a new game."));
00318 
00319   // Automatically restart game in demo mode
00320   if (global_demo_mode)
00321   {
00322     QTimer::singleShot(10000, this,SLOT(menuNewLSkatGame()));
00323   }
00324 }
00325 
00326 
00327 // Show next player
00328 void Mainwindow::nextPlayer(Player* player)
00329 {
00330   int no       = player->id()+1;
00331   QString name = player->name();
00332   statusBar()->showMessage(i18nc("Player name and number","Next move for %1 (player %2)", name, no));
00333 }
00334 
00335 
00336 // Setup the GUI
00337 void Mainwindow::initGUI()
00338 {
00339   QAction *action;
00340 
00341   // Start a new game
00342   action = KStandardGameAction::gameNew(this, SLOT(menuNewLSkatGame()), this);
00343   actionCollection()->addAction("new_game", action);
00344   ACTION("new_game")->setToolTip(i18n("Starting a new game..."));
00345   ACTION("new_game")->setWhatsThis(i18n("Start a new game."));
00346   if (global_demo_mode) action->setEnabled(false);
00347 
00348   // Clear all time statistics
00349   action = actionCollection()->addAction("clear_statistics");
00350   ACTION("clear_statistics")->setIcon(KIcon("flag"));
00351   ACTION("clear_statistics")->setText(i18n("&Clear Statistics"));
00352   connect(ACTION("clear_statistics"), SIGNAL(triggered(bool)), this, SLOT(menuClearStatistics()));
00353   ACTION("clear_statistics")->setToolTip(i18n("Delete all time statistics..."));
00354   ACTION("clear_statistics")->setWhatsThis(i18n("Clears the all time statistics which is kept in all sessions."));
00355   if (global_demo_mode) ACTION("clear_statistics")->setEnabled(false);
00356 
00357   // End a game
00358   action = actionCollection()->addAction("end_game");
00359   ACTION("end_game")->setIcon(KIcon("process-stop"));
00360   ACTION("end_game")->setText(i18n("End game"));
00361   connect(ACTION("end_game"), SIGNAL(triggered(bool)), this, SLOT(menuEndGame()));
00362   ACTION("end_game")->setToolTip(i18n("Ending the current game..."));
00363   ACTION("end_game")->setWhatsThis(i18n("Aborts a currently played game. No winner will be declared."));
00364   if (global_demo_mode) ACTION("end_game")->setEnabled(false);
00365   else ACTION("end_game")->setEnabled(false);
00366 
00367   // Quite the program
00368   action = KStandardGameAction::quit(this, SLOT(close()), this);
00369   actionCollection()->addAction("game_exit", action);
00370   ACTION("game_exit")->setToolTip(i18n("Exiting..."));
00371   ACTION("game_exit")->setWhatsThis(i18n("Quits the program."));
00372 
00373 
00374   // Determine start player
00375   KSelectAction* startPlayerAct = new KSelectAction(i18n("Starting Player"), this);
00376   actionCollection()->addAction("startplayer", startPlayerAct);
00377   connect(startPlayerAct, SIGNAL(triggered(int)), this, SLOT(menuStartplayer()));
00378   startPlayerAct->setToolTip(i18n("Changing starting player..."));
00379   startPlayerAct->setWhatsThis(i18n("Chooses which player begins the next game."));
00380   QStringList list;
00381   list.clear();
00382   list.append(i18n("Player &1"));
00383   list.append(i18n("Player &2"));
00384   startPlayerAct->setItems(list);
00385   if (global_demo_mode) startPlayerAct->setEnabled(false);
00386 
00387 
00388   // Determine who player player 1
00389   KSelectAction* player1Act = new KSelectAction(i18n("Player &1 Played By"), this);
00390   actionCollection()->addAction("player1", player1Act);
00391   connect(player1Act, SIGNAL(triggered(int)), this, SLOT(menuPlayer1By()));
00392   player1Act->setToolTip(i18n("Changing who plays player 1..."));
00393   player1Act->setWhatsThis(i18n("Changing who plays player 1."));
00394   list.clear();
00395   list.append(i18n("&Mouse"));
00396   list.append(i18n("&Computer"));
00397   player1Act->setItems(list);
00398   if (global_demo_mode) player1Act->setEnabled(false);
00399 
00400   // Determine who player player 2
00401   KSelectAction* player2Act = new KSelectAction(i18n("Player &2 Played By"), this);
00402   actionCollection()->addAction("player2", player2Act);
00403   connect(player2Act, SIGNAL(triggered(int)), this, SLOT(menuPlayer2By()));
00404   player2Act->setToolTip(i18n("Changing who plays player 2..."));
00405   player2Act->setWhatsThis(i18n("Changing who plays player 2."));
00406   player2Act->setItems(list);
00407   if (global_demo_mode) player2Act->setEnabled(false);
00408 
00409   // Choose card deck
00410   action = actionCollection()->addAction("select_carddeck");
00411   ACTION("select_carddeck")->setText(i18n("Select &Card Deck..."));
00412   connect(ACTION("select_carddeck"), SIGNAL(triggered(bool)), this, SLOT(menuCardDeck()));
00413   ACTION("select_carddeck")->setToolTip(i18n("Configure card decks..."));
00414   ACTION("select_carddeck")->setWhatsThis(i18n("Choose how the cards should look."));
00415 
00416   // Change player names
00417   action = actionCollection()->addAction("change_names");
00418   ACTION("change_names")->setText(i18n("&Change Player Names"));
00419   connect(ACTION("change_names"), SIGNAL(triggered(bool)), this, SLOT(menuPlayerNames()));
00420   if (global_demo_mode) ACTION("change_names")->setEnabled(false);
00421 }
00422 
00423 
00424 // Choose start player
00425 void Mainwindow::menuStartplayer()
00426 {
00427   int i=((KSelectAction *)ACTION("startplayer"))->currentItem();
00428   setStartPlayer(i);
00429 }
00430 
00431 
00432 // Select input for player 1
00433 void Mainwindow::menuPlayer1By()
00434 {
00435   int i = ((KSelectAction *)ACTION("player1"))->currentItem();
00436   mLSkatConfig->setInputType(0, (InputDeviceType)i);
00437 }
00438 
00439 
00440 // Select input for player 2
00441 void Mainwindow::menuPlayer2By()
00442 {
00443   int i = ((KSelectAction *)ACTION("player2"))->currentItem();
00444   mLSkatConfig->setInputType(1, (InputDeviceType)i);
00445 }
00446 
00447 
00448 // Choose a card deck
00449 void Mainwindow::menuCardDeck()
00450 {
00451   QString s1,s2;
00452   int result;
00453 
00454   KCardDialog::CardFlags flags = KCardDialog::CardFlags(KCardDialog::Both|KCardDialog::SVGCards);
00455   result=KCardDialog::getCardDeck(s1,s2, this, flags);
00456   if (result==QDialog::Accepted)
00457   {
00458     if (global_debug > 0) kDebug() << "NEW CARDDECK: " << s1 << " and " << s2 << endl;
00459     bool change = false; // Avoid unnecessary changes
00460     if (!s1.isEmpty() && s1 != mDeckGrafix)
00461     {
00462       mDeckGrafix = s1;
00463       change = true;
00464     }
00465     if (!s2.isEmpty() && s2 != mCardDir)
00466     {
00467       mCardDir    = s2;
00468       change = true;
00469     }
00470     if (change)
00471     {
00472       mTheme->updateCardTheme(mCardDir, mDeckGrafix);
00473       mView->update(); // Be on the safe side and update
00474     }
00475   }
00476 }
00477 
00478 
00479 // Clear all time statistics
00480 void Mainwindow::menuClearStatistics()
00481 {
00482    QString message;
00483    message=i18n("Do you really want to clear the all time "
00484                 "statistical data?");
00485 
00486   if (KMessageBox::Yes==KMessageBox::questionYesNo(this,
00487                                                    message,
00488                                                    QString::null,
00489                                                    KStandardGuiItem::clear()))
00490   {
00491     QHashIterator<int,Player*> it = mLSkatConfig->playerIterator();
00492     while(it.hasNext())
00493     {
00494       it.next();
00495       Player* player = it.value();
00496       player->clear();
00497     }
00498   }
00499 }
00500 
00501 
00502 // Abort a game
00503 void Mainwindow::menuEndGame()
00504 {
00505   if (mEngine)
00506   {
00507     mEngine->stopGame();
00508   }
00509 
00510 }
00511 
00512 
00513 // Start a new game
00514 void Mainwindow::menuNewLSkatGame()
00515 {
00516   Player* p1 = mLSkatConfig->player(0);
00517   Player* p2 = mLSkatConfig->player(1);
00518 
00519   // Stop running games
00520   if (mEngine)
00521   {
00522     mEngine->stopGame();
00523   }
00524 
00525   // Get rid of old stuff?
00526   if (mGameMode != LSkat)
00527   {
00528     // Set new game mode
00529     mGameMode = LSkat;
00530 
00531     // Start deleting
00532     if (mDisplay) delete mDisplay;
00533     if (mEngine) delete mEngine;
00534 
00535     mDisplay     = new DisplayTwo(mDeck, mCanvas, mTheme, ADVANCE_PERDIOD, mView);
00536     mEngine  = new EngineTwo(this, mDeck, (DisplayTwo*)mDisplay);
00537     connect(mEngine, SIGNAL(signalGameOver(int)), this, SLOT(gameOver(int)));
00538     connect(mEngine, SIGNAL(signalNextPlayer(Player*)), this, SLOT(nextPlayer(Player*)));
00539 
00540     // Connect player score widget updates
00541     connect(p1, SIGNAL(signalUpdate(Player*)), mDisplay, SLOT(updatePlayer(Player*)));
00542     connect(p2, SIGNAL(signalUpdate(Player*)), mDisplay, SLOT(updatePlayer(Player*)));
00543 
00544     mEngine->addPlayer(0, p1);
00545     mEngine->addPlayer(1, p2);
00546   }// end if
00547 
00548   // Create inputs and store in player
00549   AbstractInput* input1 = createInput(mLSkatConfig->inputType(0), mDisplay, mEngine);
00550   p1->setInput(input1);
00551   AbstractInput* input2 = createInput(mLSkatConfig->inputType(1), mDisplay, mEngine);
00552   p2->setInput(input2);
00553 
00554   statusBar()->showMessage(i18n("Dealing cards..."));
00555 
00556   // Start game
00557   startGame();
00558 }
00559 
00560 
00561 // Change the player names in a dialog
00562 void Mainwindow::menuPlayerNames()
00563 {
00564   NameDialogWidget dlg(this);
00565   for (int i=0;i<2;i++)
00566   {
00567     Player* p = mLSkatConfig->player(i);
00568     dlg.setName(i, p->name());
00569   }
00570 
00571   int result = dlg.exec();
00572 
00573   if (result == QDialog::Accepted)
00574   {
00575     for (int i=0;i<2;i++)
00576     {
00577       Player* p = mLSkatConfig->player(i);
00578       p->setName(dlg.name(i));
00579     }
00580   }
00581 }
00582 
00583 
00584 // Set the start player.
00585 void Mainwindow::setStartPlayer(int no)
00586 {
00587   mStartPlayer = no;
00588   ((KSelectAction *)ACTION("startplayer"))->setCurrentItem(mStartPlayer);
00589 }
00590 
00591 
00592 // Set the input type for a given player number.
00593 void Mainwindow::setInputType(int no, InputDeviceType type)
00594 {
00595   Player* p = 0;
00596   // Player 1
00597   if (no == 0)
00598   {
00599     ((KSelectAction *)ACTION("player1"))->setCurrentItem((int)type);
00600     p = mLSkatConfig->player(0);
00601   }
00602   else if (no == 1)
00603   {
00604     ((KSelectAction *)ACTION("player2"))->setCurrentItem((int)type);
00605     p = mLSkatConfig->player(1);
00606   }
00607 
00608   // Exchange player input at runtime
00609   if (mEngine && p && mDisplay && mEngine->isGameRunning())
00610   {
00611     AbstractInput* input = createInput(type, mDisplay, mEngine);
00612     p->setInput(input);
00613   }
00614 
00615 }
00616 
00617 
00618 #include "mainwindow.moc"

Generated on Tue May 1 09:34:40 2007 for LSkat by  doxygen 1.4.6