1/*
2 * Copyright 2007-2008 Thomas Gallinari <tg8187@yahoo.fr>
3 * Copyright 2007-2008 Pierre-Benoit Bessse <besse@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "kapmanmainwindow.h"
20#include "gamescene.h"
21#include "settings.h"
22
23#include <QPointer>
24#include <KActionCollection>
25#include <KStandardGameAction>
26#include <KToggleAction>
27#include <KMessageBox>
28#include <KConfigDialog>
29#include <KInputDialog>
30#include <KLocale>
31#include <KStatusBar>
32#include <KgDifficulty>
33#include <KScoreDialog>
34
35#define USE_UNSTABLE_LIBKDEGAMESPRIVATE_API
36#include <libkdegamesprivate/kgamethemeselector.h>
37
38KapmanMainWindow::KapmanMainWindow() {
39 // Initialize the game
40 m_game = NULL;
41 m_view = NULL;
42 // Set the window menus
43 KStandardGameAction::gameNew(this, SLOT(newGame(bool)), actionCollection());
44 KStandardGameAction::highscores(this, SLOT(showHighscores()), actionCollection());
45 KStandardAction::preferences(this, SLOT(showSettings()), actionCollection());
46 KStandardGameAction::quit(this, SLOT(close()), actionCollection());
47 KAction* soundAction = new KToggleAction(i18n("&Play sounds"), this);
48 soundAction->setChecked(Settings::sounds());
49 actionCollection()->addAction( QLatin1String( "sounds" ), soundAction);
50 connect(soundAction, SIGNAL(triggered(bool)), this, SLOT(setSoundsEnabled(bool)));
51 KAction* levelAction = new KAction(i18n("&Change level"), this);
52 actionCollection()->addAction( QLatin1String( "level" ), levelAction);
53 connect(levelAction, SIGNAL(triggered(bool)), this, SLOT(changeLevel()));
54 // Add a statusbar to show level,score,lives information
55 m_statusBar = statusBar();
56 m_statusBar->insertItem(i18nc("Used to display the current level of play to the user", "Level: %1", 1), 1, 1);
57 m_statusBar->insertItem(i18nc("Used to inform the user of their current score", "Score: %1", 0), 2, 1);
58 m_statusBar->insertItem(i18nc("Used to tell the user how many lives they have left", "Lives: %1", initLives), 4, 1);
59
60
61 // Initialize the KgDifficulty singleton
62 Kg::difficulty()->addStandardLevelRange(
63 KgDifficultyLevel::Easy, KgDifficultyLevel::Hard, //range
64 KgDifficultyLevel::Medium //default
65 );
66 KgDifficultyGUI::init(this);
67 connect(Kg::difficulty(), SIGNAL(currentLevelChanged(const KgDifficultyLevel*)), SLOT(initGame()));
68 // Setup the window
69 setupGUI();
70
71 initGame();
72}
73
74KapmanMainWindow::~KapmanMainWindow() {
75 delete m_statusBar;
76 delete m_game;
77 delete m_view;
78}
79
80void KapmanMainWindow::initGame() {
81 // Create a new Game instance
82 delete m_game;
83 m_game = new Game();
84 connect(m_game, SIGNAL(gameOver(bool)), this, SLOT(newGame(bool))); // TODO Remove the useless bool parameter from gameOver()
85 connect(m_game, SIGNAL(levelChanged(uint)), this, SLOT(displayLevel(uint)));
86 connect(m_game, SIGNAL(scoreChanged(uint)), this, SLOT(displayScore(uint)));
87 connect(m_game, SIGNAL(livesChanged(uint)), this, SLOT(displayLives(uint)));
88
89
90 // Create a new GameView instance
91 delete m_view;
92 m_view = new GameView(m_game);
93 m_view->setBackgroundBrush(Qt::black);
94 setCentralWidget(m_view);
95 m_view->setFocus();
96 // For some reason, calling setFocus() immediately won't work after the
97 // score dialog has been shown, so do it again after an eventloop run.
98 QTimer::singleShot(0, m_view, SLOT(setFocus()));
99 resetStatusBar();
100}
101
102
103void KapmanMainWindow::newGame(const bool gameOver) {
104 bool gameRunning; // True if the game is running (game timer is active), false otherwise
105
106 gameRunning = m_game->getTimer()->isActive();
107 // If the game is running
108 if (gameRunning) {
109 // Pause the game
110 m_game->pause();
111 }
112 // If the game was not over
113 if (!gameOver){
114 // Confirm before starting a new game
115 if (KMessageBox::warningYesNo(this, i18n("Are you sure you want to quit the current game?"), i18n("New game")) == KMessageBox::Yes) {
116 // Start a new game
117 initGame();
118 }
119 else {
120 // If the game was running
121 if (gameRunning) {
122 // Resume the game
123 m_game->start();
124 }
125 }
126 }
127 else {
128 // Display the score information
129 KMessageBox::information(this, i18np("Your score is %1 point.", "Your score is %1 points.", m_game->getScore()), i18n("Game Over"));
130 // manage Highscores only if player did not cheat
131 if (m_game->isCheater()) {
132 KMessageBox::information(this, i18n("You cheated, no Highscore for you ;)"), i18n("Cheater!"));
133 }
134 else {
135 // Add the score to the highscores table
136 QPointer<KScoreDialog> dialog = new KScoreDialog(KScoreDialog::Name | KScoreDialog::Score | KScoreDialog::Level, this);
137 dialog->initFromDifficulty(Kg::difficulty());
138 KScoreDialog::FieldInfo scoreInfo;
139 scoreInfo[KScoreDialog::Level].setNum(m_game->getLevel());
140 scoreInfo[KScoreDialog::Score].setNum(m_game->getScore());
141 // If the new score is a highscore then display the highscore dialog
142 if (dialog->addScore(scoreInfo)) {
143 dialog->exec();
144 }
145 delete dialog;
146 }
147 // Start a new game
148 initGame();
149 }
150}
151
152void KapmanMainWindow::changeLevel() {
153 int newLevel = KInputDialog::getInteger(i18n("Change level"), i18nc("The number of the game level", "Level"), m_game->getLevel(), 1, 1000000, 1, 10, 0, this);
154 if (newLevel > 0) {
155 m_game->setLevel(newLevel);
156 }
157}
158
159void KapmanMainWindow::showHighscores() {
160 QPointer<KScoreDialog> dialog = new KScoreDialog(KScoreDialog::Name | KScoreDialog::Score | KScoreDialog::Level, this);
161 dialog->initFromDifficulty(Kg::difficulty());
162 dialog->exec();
163 delete dialog;
164}
165
166void KapmanMainWindow::setSoundsEnabled(bool p_enabled) {
167 m_game->setSoundsEnabled(p_enabled);
168}
169
170void KapmanMainWindow::showSettings() {
171 if (KConfigDialog::showDialog("settings")) {
172 return;
173 }
174 KConfigDialog* settingsDialog = new KConfigDialog(this, "settings", Settings::self());
175 settingsDialog->addPage(new KGameThemeSelector(settingsDialog, Settings::self(), KGameThemeSelector::NewStuffDisableDownload), i18n("Theme"), "kapman");
176 settingsDialog->setFaceType(KConfigDialog::Plain); //only one page -> no page selection necessary
177 connect(settingsDialog, SIGNAL(settingsChanged(QString)), this, SLOT(loadSettings()));
178 settingsDialog->show();
179}
180
181void KapmanMainWindow::loadSettings() {
182 ((GameScene*)m_view->scene())->loadTheme();
183}
184
185void KapmanMainWindow::close() {
186 bool gameRunning; // True if the game is running (game timer is active), false otherwise
187
188 gameRunning = m_game->getTimer()->isActive();
189 // If the game is running
190 if (gameRunning) {
191 // Pause the game
192 m_game->pause();
193 }
194 // Confirm before closing
195 if(KMessageBox::warningYesNo(this, i18n("Are you sure you want to quit Kapman?"), i18nc("To quit Kapman", "Quit")) == KMessageBox::Yes) {
196 KXmlGuiWindow::close();
197 }
198 else {
199 // If the game was running
200 if (gameRunning) {
201 // Resume the game
202 m_game->start();
203 }
204 }
205}
206
207void KapmanMainWindow::displayLevel(unsigned int p_level)
208{
209 m_statusBar->changeItem(i18nc(
210 "Used to display the current level of play to the user",
211 "Level: %1", p_level), 1);
212}
213
214void KapmanMainWindow::displayScore(unsigned int p_score)
215{
216 m_statusBar->changeItem(i18nc(
217 "Used to inform the user of their current score", "Score: %1",
218 p_score), 2);
219}
220
221void KapmanMainWindow::displayLives(unsigned int p_lives)
222{
223 m_statusBar->changeItem(i18nc(
224 "Used to tell the user how many lives they have left", "Lives: %1",
225 p_lives), 4);
226}
227
228void KapmanMainWindow::resetStatusBar()
229{
230 displayLevel(1);
231 displayScore(0);
232 displayLives(initLives);
233}
234