1 | /* |
2 | Copyright 2007 Dmitry Suzdalev <dimsuz@gmail.com> |
3 | Copyright 2010 Brian Croom <brian.s.croom@gmail.com> |
4 | |
5 | This program is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published by |
7 | the Free Software Foundation; either version 2 of the License, or |
8 | (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, write to the Free Software |
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
18 | */ |
19 | #include "mainwindow.h" |
20 | #include "minefielditem.h" |
21 | #include "scene.h" |
22 | #include "settings.h" |
23 | |
24 | #include <KGameClock> |
25 | #include <KgDifficulty> |
26 | #include <KStandardGameAction> |
27 | #include <KActionCollection> |
28 | #include <KToggleAction> |
29 | #include <KStatusBar> |
30 | #include <KScoreDialog> |
31 | #include <KConfigDialog> |
32 | #include <KgThemeSelector> |
33 | #include <KMessageBox> |
34 | #include <KLocale> |
35 | #include <QDesktopWidget> |
36 | #include <QPointer> |
37 | |
38 | #include "ui_customgame.h" |
39 | #include "ui_generalopts.h" |
40 | |
41 | /* |
42 | * Classes for config dlg pages |
43 | */ |
44 | class CustomGameConfig : public QWidget |
45 | { |
46 | Q_OBJECT |
47 | |
48 | public: |
49 | CustomGameConfig(QWidget *parent) |
50 | : QWidget(parent) |
51 | { |
52 | ui.setupUi(this); |
53 | connect(ui.kcfg_CustomWidth, SIGNAL(valueChanged(int)), this, SLOT(updateMaxMines())); |
54 | connect(ui.kcfg_CustomHeight, SIGNAL(valueChanged(int)), this, SLOT(updateMaxMines())); |
55 | } |
56 | |
57 | private slots: |
58 | void updateMaxMines() |
59 | { |
60 | int width = ui.kcfg_CustomWidth->value(); |
61 | int height = ui.kcfg_CustomHeight->value(); |
62 | int max = qMax(1, width * height - MineFieldItem::MINIMAL_FREE); |
63 | ui.kcfg_CustomMines->setMaximum(max); |
64 | } |
65 | |
66 | private: |
67 | Ui::CustomGameConfig ui; |
68 | }; |
69 | |
70 | class GeneralOptsConfig : public QWidget |
71 | { |
72 | public: |
73 | GeneralOptsConfig(QWidget *parent) |
74 | : QWidget(parent) |
75 | { |
76 | ui.setupUi(this); |
77 | } |
78 | |
79 | private: |
80 | Ui::GeneralOptsConfig ui; |
81 | }; |
82 | |
83 | /* |
84 | * Main window |
85 | */ |
86 | |
87 | KMinesMainWindow::KMinesMainWindow() |
88 | { |
89 | m_scene = new KMinesScene(this); |
90 | connect(m_scene, SIGNAL(minesCountChanged(int)), SLOT(onMinesCountChanged(int))); |
91 | connect(m_scene, SIGNAL(gameOver(bool)), SLOT(onGameOver(bool))); |
92 | connect(m_scene, SIGNAL(firstClickDone()), SLOT(onFirstClick())); |
93 | |
94 | m_view = new KMinesView( m_scene, this ); |
95 | m_view->setCacheMode( QGraphicsView::CacheBackground ); |
96 | m_view->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); |
97 | m_view->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); |
98 | m_view->setFrameStyle(QFrame::NoFrame); |
99 | |
100 | m_view->setOptimizationFlags( QGraphicsView::DontClipPainter | |
101 | QGraphicsView::DontSavePainterState | |
102 | QGraphicsView::DontAdjustForAntialiasing ); |
103 | |
104 | |
105 | m_gameClock = new KGameClock(this, KGameClock::MinSecOnly); |
106 | connect(m_gameClock, SIGNAL(timeChanged(QString)), SLOT(advanceTime(QString))); |
107 | |
108 | statusBar()->insertItem( i18n("Mines: 0/0" ), 0 ); |
109 | statusBar()->insertItem( i18n("Time: 00:00" ), 1); |
110 | setCentralWidget(m_view); |
111 | setupActions(); |
112 | |
113 | newGame(); |
114 | } |
115 | |
116 | void KMinesMainWindow::setupActions() |
117 | { |
118 | KStandardGameAction::gameNew(this, SLOT(newGame()), actionCollection()); |
119 | KStandardGameAction::highscores(this, SLOT(showHighscores()), actionCollection()); |
120 | |
121 | KStandardGameAction::quit(this, SLOT(close()), actionCollection()); |
122 | KStandardAction::preferences( this, SLOT(configureSettings()), actionCollection() ); |
123 | m_actionPause = KStandardGameAction::pause( this, SLOT(pauseGame(bool)), actionCollection() ); |
124 | |
125 | Kg::difficulty()->addStandardLevelRange( |
126 | KgDifficultyLevel::Easy, KgDifficultyLevel::Hard |
127 | ); |
128 | Kg::difficulty()->addLevel(new KgDifficultyLevel(1000, |
129 | QByteArray( "Custom" ), i18n( "Custom" ) |
130 | )); |
131 | KgDifficultyGUI::init(this); |
132 | connect(Kg::difficulty(), SIGNAL(currentLevelChanged(const KgDifficultyLevel*)), SLOT(newGame())); |
133 | |
134 | setupGUI(qApp->desktop()->availableGeometry().size()*0.4); |
135 | } |
136 | |
137 | void KMinesMainWindow::onMinesCountChanged(int count) |
138 | { |
139 | statusBar()->changeItem( i18n("Mines: %1/%2" , count, m_scene->totalMines()), 0 ); |
140 | } |
141 | |
142 | void KMinesMainWindow::newGame() |
143 | { |
144 | m_gameClock->restart(); |
145 | m_gameClock->pause(); // start only with the 1st click |
146 | |
147 | // some things to manage pause |
148 | if( m_actionPause->isChecked() ) |
149 | { |
150 | m_scene->setGamePaused(false); |
151 | m_actionPause->setChecked(false); |
152 | } |
153 | m_actionPause->setEnabled(false); |
154 | |
155 | Kg::difficulty()->setGameRunning(false); |
156 | switch(Kg::difficultyLevel()) |
157 | { |
158 | case KgDifficultyLevel::Easy: |
159 | m_scene->startNewGame(9, 9, 10); |
160 | break; |
161 | case KgDifficultyLevel::Medium: |
162 | m_scene->startNewGame(16,16,40); |
163 | break; |
164 | case KgDifficultyLevel::Hard: |
165 | m_scene->startNewGame(16,30,99); |
166 | break; |
167 | case KgDifficultyLevel::Custom: |
168 | m_scene->startNewGame(Settings::customHeight(), |
169 | Settings::customWidth(), |
170 | Settings::customMines()); |
171 | default: |
172 | //unsupported |
173 | break; |
174 | } |
175 | statusBar()->changeItem( i18n("Time: 00:00" ), 1); |
176 | } |
177 | |
178 | void KMinesMainWindow::onGameOver(bool won) |
179 | { |
180 | m_gameClock->pause(); |
181 | m_actionPause->setEnabled(false); |
182 | Kg::difficulty()->setGameRunning(false); |
183 | if(won) |
184 | { |
185 | QPointer<KScoreDialog> scoreDialog = new KScoreDialog(KScoreDialog::Name | KScoreDialog::Time, this); |
186 | scoreDialog->initFromDifficulty(Kg::difficulty()); |
187 | scoreDialog->hideField(KScoreDialog::Score); |
188 | |
189 | KScoreDialog::FieldInfo scoreInfo; |
190 | // score-in-seconds will be hidden |
191 | scoreInfo[KScoreDialog::Score].setNum(m_gameClock->seconds()); |
192 | //score-as-time will be shown |
193 | scoreInfo[KScoreDialog::Time] = m_gameClock->timeString(); |
194 | |
195 | // we keep highscores as number of seconds |
196 | if( scoreDialog->addScore(scoreInfo, KScoreDialog::LessIsMore) != 0 ) |
197 | scoreDialog->exec(); |
198 | |
199 | delete scoreDialog; |
200 | } |
201 | } |
202 | |
203 | void KMinesMainWindow::advanceTime(const QString& timeStr) |
204 | { |
205 | statusBar()->changeItem( i18n("Time: %1" , timeStr), 1 ); |
206 | } |
207 | |
208 | void KMinesMainWindow::onFirstClick() |
209 | { |
210 | // enable pause action |
211 | m_actionPause->setEnabled(true); |
212 | // start clock |
213 | m_gameClock->resume(); |
214 | Kg::difficulty()->setGameRunning(true); |
215 | } |
216 | |
217 | void KMinesMainWindow::showHighscores() |
218 | { |
219 | QPointer<KScoreDialog> scoreDialog = new KScoreDialog(KScoreDialog::Name | KScoreDialog::Time, this); |
220 | scoreDialog->initFromDifficulty(Kg::difficulty()); |
221 | scoreDialog->hideField(KScoreDialog::Score); |
222 | scoreDialog->exec(); |
223 | delete scoreDialog; |
224 | } |
225 | |
226 | void KMinesMainWindow::configureSettings() |
227 | { |
228 | if ( KConfigDialog::showDialog( QLatin1String( "settings" ) ) ) |
229 | return; |
230 | KConfigDialog *dialog = new KConfigDialog( this, QLatin1String( "settings" ), Settings::self() ); |
231 | dialog->addPage( new GeneralOptsConfig( dialog ), i18n("General" ), QLatin1String( "games-config-options" )); |
232 | dialog->addPage( new KgThemeSelector( m_scene->renderer().themeProvider() ), i18n( "Theme" ), QLatin1String( "games-config-theme" )); |
233 | dialog->addPage( new CustomGameConfig( dialog ), i18n("Custom Game" ), QLatin1String( "games-config-custom" )); |
234 | connect( m_scene->renderer().themeProvider(), SIGNAL(currentThemeChanged(const KgTheme*)), SLOT(loadSettings()) ); |
235 | connect( dialog, SIGNAL(settingsChanged(QString)), this, SLOT(loadSettings()) ); |
236 | dialog->setHelp(QString(),QLatin1String( "kmines" )); |
237 | dialog->show(); |
238 | } |
239 | |
240 | void KMinesMainWindow::pauseGame(bool paused) |
241 | { |
242 | m_scene->setGamePaused( paused ); |
243 | if( paused ) |
244 | m_gameClock->pause(); |
245 | else |
246 | m_gameClock->resume(); |
247 | } |
248 | |
249 | void KMinesMainWindow::loadSettings() |
250 | { |
251 | m_view->resetCachedContent(); |
252 | // trigger complete redraw |
253 | m_scene->resizeScene( (int)m_scene->sceneRect().width(), |
254 | (int)m_scene->sceneRect().height() ); |
255 | } |
256 | |
257 | #include "mainwindow.moc" |
258 | #include "moc_mainwindow.cpp" |
259 | |