1 | /* |
2 | Copyright (C) 2002-2005, Jason Katz-Brown <jasonkb@mit.edu> |
3 | Copyright 2010 Stefan Majewsky <majewsky@gmx.net> |
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 | |
20 | #include "kolf.h" |
21 | #include "editor.h" |
22 | #include "landscape.h" |
23 | #include "newgame.h" |
24 | #include "objects.h" |
25 | #include "obstacles.h" |
26 | #include "scoreboard.h" |
27 | |
28 | #include <KActionCollection> |
29 | #include <KFileDialog> |
30 | #include <KIO/NetAccess> |
31 | #include <KMessageBox> |
32 | #include <KScoreDialog> |
33 | #include <KSelectAction> |
34 | #include <KStandardDirs> |
35 | #include <KStatusBar> |
36 | #include <KStandardAction> |
37 | #include <KStandardGameAction> |
38 | #include <KStandardGuiItem> |
39 | #include <KToggleAction> |
40 | |
41 | #include <QGridLayout> |
42 | #include <QTimer> |
43 | |
44 | KolfWindow::KolfWindow() |
45 | : KXmlGuiWindow(0) |
46 | { |
47 | setObjectName( QLatin1String("Kolf" )); |
48 | competition = false; |
49 | game = 0; |
50 | editor = 0; |
51 | spacer = 0; |
52 | scoreboard = 0; |
53 | isTutorial = false; |
54 | |
55 | setupActions(); |
56 | |
57 | m_itemFactory.registerType<Kolf::Slope>("slope" , i18n("Slope" )); |
58 | m_itemFactory.registerType<Kolf::Puddle>("puddle" , i18n("Puddle" )); |
59 | m_itemFactory.registerType<Kolf::Wall>("wall" , i18n("Wall" )); |
60 | m_itemFactory.registerType<Kolf::Cup>("cup" , i18n("Cup" ), true); //true == addOnNewHole |
61 | m_itemFactory.registerType<Kolf::Sand>("sand" , i18n("Sand" )); |
62 | m_itemFactory.registerType<Kolf::Windmill>("windmill" , i18n("Windmill" )); |
63 | m_itemFactory.registerType<Kolf::BlackHole>("blackhole" , i18n("Black Hole" )); |
64 | m_itemFactory.registerType<Kolf::Floater>("floater" , i18n("Floater" )); |
65 | m_itemFactory.registerType<Kolf::Bridge>("bridge" , i18n("Bridge" )); |
66 | m_itemFactory.registerType<Kolf::Sign>("sign" , i18n("Sign" )); |
67 | m_itemFactory.registerType<Kolf::Bumper>("bumper" , i18n("Bumper" )); |
68 | //NOTE: The plugin mechanism has been removed because it is not used anyway. |
69 | |
70 | filename = QString(); |
71 | dummy = new QWidget(this); |
72 | setCentralWidget(dummy); |
73 | layout = new QGridLayout(dummy); |
74 | |
75 | resize(420, 480); |
76 | } |
77 | |
78 | KolfWindow::~KolfWindow() |
79 | { |
80 | } |
81 | |
82 | void KolfWindow::setupActions() |
83 | { |
84 | // Game |
85 | newAction = KStandardGameAction::gameNew(this, SLOT(newGame()), actionCollection()); |
86 | endAction = KStandardGameAction::end(this, SLOT(closeGame()), actionCollection()); |
87 | KStandardGameAction::quit(this, SLOT(close()), actionCollection()); |
88 | |
89 | saveAction = actionCollection()->addAction(KStandardAction::Save, "game_save" , this, SLOT(save())); |
90 | saveAction->setText(i18n("Save &Course" )); |
91 | saveAsAction = actionCollection()->addAction(KStandardAction::SaveAs, "game_save_as" , this, SLOT(saveAs())); |
92 | saveAsAction->setText(i18n("Save &Course As..." )); |
93 | |
94 | saveGameAction = actionCollection()->addAction("savegame" ); |
95 | saveGameAction->setText(i18n("&Save Game" )); |
96 | connect(saveGameAction, SIGNAL(triggered(bool)), SLOT(saveGame())); |
97 | saveGameAsAction = actionCollection()->addAction("savegameas" ); |
98 | saveGameAsAction->setText(i18n("&Save Game As..." )); |
99 | connect(saveGameAsAction, SIGNAL(triggered(bool)), SLOT(saveGameAs())); |
100 | |
101 | loadGameAction = KStandardGameAction::load(this, SLOT(loadGame()), actionCollection()); |
102 | highScoreAction = KStandardGameAction::highscores(this, SLOT(showHighScores()), actionCollection()); |
103 | |
104 | // Hole |
105 | editingAction = new KToggleAction(KIcon( QLatin1String( "document-properties" ) ), i18n("&Edit" ), this); |
106 | actionCollection()->addAction("editing" , editingAction); |
107 | connect(editingAction, SIGNAL(triggered(bool)), SLOT(emptySlot())); |
108 | editingAction->setShortcut(Qt::CTRL+Qt::Key_E); |
109 | newHoleAction = actionCollection()->addAction("newhole" ); |
110 | newHoleAction->setIcon(KIcon( QLatin1String( "document-new" ))); |
111 | newHoleAction->setText(i18n("&New" )); |
112 | connect(newHoleAction, SIGNAL(triggered(bool)), SLOT(emptySlot())); |
113 | newHoleAction->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_N); |
114 | clearHoleAction = actionCollection()->addAction("clearhole" ); |
115 | clearHoleAction->setIcon(KIcon( QLatin1String( "edit-clear-locationbar-ltr" ))); |
116 | clearHoleAction->setText(KStandardGuiItem::clear().text()); |
117 | connect(clearHoleAction, SIGNAL(triggered(bool)), SLOT(emptySlot())); |
118 | clearHoleAction->setShortcut(Qt::CTRL+Qt::Key_Delete); |
119 | resetHoleAction = actionCollection()->addAction("resethole" ); |
120 | resetHoleAction->setText(i18n("&Reset" )); |
121 | connect(resetHoleAction, SIGNAL(triggered(bool)), SLOT(emptySlot())); |
122 | resetHoleAction->setShortcut(Qt::CTRL+Qt::Key_R); |
123 | undoShotAction = KStandardAction::undo(this, SLOT(emptySlot()), this); |
124 | actionCollection()->addAction("undoshot" , undoShotAction); |
125 | undoShotAction->setText(i18n("&Undo Shot" )); |
126 | //replayShotAction = new KAction(i18n("&Replay Shot"), 0, this, SLOT(emptySlot()), actionCollection(), "replay"); |
127 | |
128 | // Go |
129 | holeAction = new KSelectAction(i18n("Switch to Hole" ), this); |
130 | actionCollection()->addAction("switchhole" , holeAction); |
131 | connect(holeAction, SIGNAL(triggered(bool)), SLOT(emptySlot())); |
132 | nextAction = actionCollection()->addAction("nexthole" ); |
133 | nextAction->setIcon(KIcon( QLatin1String( "go-next" ))); |
134 | nextAction->setText(i18n("&Next Hole" )); |
135 | connect(nextAction, SIGNAL(triggered(bool)), SLOT(emptySlot())); |
136 | nextAction->setShortcuts(KStandardShortcut::shortcut(KStandardShortcut::Forward)); |
137 | prevAction = actionCollection()->addAction("prevhole" ); |
138 | prevAction->setIcon(KIcon( QLatin1String( "go-previous" ))); |
139 | prevAction->setText(i18n("&Previous Hole" )); |
140 | connect(prevAction, SIGNAL(triggered(bool)), SLOT(emptySlot())); |
141 | prevAction->setShortcuts(KStandardShortcut::shortcut(KStandardShortcut::Back)); |
142 | firstAction = actionCollection()->addAction("firsthole" ); |
143 | firstAction->setIcon(KIcon( QLatin1String( "go-home" ))); |
144 | firstAction->setText(i18n("&First Hole" )); |
145 | connect(firstAction, SIGNAL(triggered(bool)), SLOT(emptySlot())); |
146 | firstAction->setShortcuts(KStandardShortcut::shortcut(KStandardShortcut::Begin)); |
147 | lastAction = actionCollection()->addAction("lasthole" ); |
148 | lastAction->setText(i18n("&Last Hole" )); |
149 | connect(lastAction, SIGNAL(triggered(bool)), SLOT(emptySlot())); |
150 | lastAction->setShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_End); // why not KStandardShortcut::End (Ctrl+End)? |
151 | randAction = actionCollection()->addAction("randhole" ); |
152 | randAction->setIcon(KIcon( QLatin1String( "go-jump" ))); |
153 | randAction->setText(i18n("&Random Hole" )); |
154 | connect(randAction, SIGNAL(triggered(bool)), SLOT(emptySlot())); |
155 | |
156 | // Settings |
157 | useMouseAction = new KToggleAction(i18n("Enable &Mouse for Moving Putter" ), this); |
158 | actionCollection()->addAction("usemouse" , useMouseAction); |
159 | connect(useMouseAction, SIGNAL(triggered(bool)), SLOT(emptySlot())); |
160 | connect(useMouseAction, SIGNAL(toggled(bool)), this, SLOT(useMouseChanged(bool))); |
161 | KConfigGroup configGroup(KGlobal::config(), "Settings" ); |
162 | useMouseAction->setChecked(configGroup.readEntry("useMouse" , true)); |
163 | |
164 | useAdvancedPuttingAction = new KToggleAction(i18n("Enable &Advanced Putting" ), this); |
165 | actionCollection()->addAction("useadvancedputting" , useAdvancedPuttingAction); |
166 | connect(useAdvancedPuttingAction, SIGNAL(triggered(bool)), SLOT(emptySlot())); |
167 | connect(useAdvancedPuttingAction, SIGNAL(toggled(bool)), this, SLOT(useAdvancedPuttingChanged(bool))); |
168 | useAdvancedPuttingAction->setChecked(configGroup.readEntry("useAdvancedPutting" , false)); |
169 | |
170 | showInfoAction = new KToggleAction(KIcon( QLatin1String( "help-about" )), i18n("Show &Info" ), this); |
171 | actionCollection()->addAction("showinfo" , showInfoAction); |
172 | connect(showInfoAction, SIGNAL(triggered(bool)), SLOT(emptySlot())); |
173 | showInfoAction->setShortcut(Qt::CTRL+Qt::Key_I); |
174 | connect(showInfoAction, SIGNAL(toggled(bool)), this, SLOT(showInfoChanged(bool))); |
175 | showInfoAction->setChecked(configGroup.readEntry("showInfo" , true)); |
176 | |
177 | showGuideLineAction = new KToggleAction(i18n("Show Putter &Guideline" ), this); |
178 | actionCollection()->addAction("showguideline" , showGuideLineAction); |
179 | connect(showGuideLineAction, SIGNAL(triggered(bool)), SLOT(emptySlot())); |
180 | connect(showGuideLineAction, SIGNAL(toggled(bool)), this, SLOT(showGuideLineChanged(bool))); |
181 | showGuideLineAction->setChecked(configGroup.readEntry("showGuideLine" , true)); |
182 | |
183 | KToggleAction *act = new KToggleAction(i18n("Enable All Dialog Boxes" ), this); |
184 | actionCollection()->addAction("enableAll" , act); |
185 | connect(act, SIGNAL(triggered(bool)), SLOT(enableAllMessages())); |
186 | |
187 | soundAction = new KToggleAction(i18n("Play &Sounds" ), this); |
188 | actionCollection()->addAction("sound" , soundAction); |
189 | connect(soundAction, SIGNAL(triggered(bool)), SLOT(emptySlot())); |
190 | connect(soundAction, SIGNAL(toggled(bool)), this, SLOT(soundChanged(bool))); |
191 | soundAction->setChecked(configGroup.readEntry("sound" , true)); |
192 | |
193 | aboutAction = actionCollection()->addAction("aboutcourse" ); |
194 | aboutAction->setText(i18n("&About Course" )); |
195 | connect(aboutAction, SIGNAL(triggered(bool)), SLOT(emptySlot())); |
196 | tutorialAction = actionCollection()->addAction("tutorial" ); |
197 | tutorialAction->setText(i18n("&Tutorial" )); |
198 | connect(tutorialAction, SIGNAL(triggered(bool)), SLOT(tutorial())); |
199 | |
200 | setupGUI(); |
201 | } |
202 | |
203 | bool KolfWindow::queryClose() |
204 | { |
205 | if (game) |
206 | if (game->askSave(true)) |
207 | return false; |
208 | return true; |
209 | } |
210 | |
211 | void KolfWindow::startNewGame() |
212 | { |
213 | NewGameDialog *dialog = 0; |
214 | int firstHole = 1; |
215 | |
216 | if (loadedGame.isNull()) |
217 | { |
218 | dialog = new NewGameDialog(filename.isNull()); |
219 | if (dialog->exec() != QDialog::Accepted) |
220 | goto end; |
221 | } |
222 | |
223 | players.clear(); |
224 | delete scoreboard; |
225 | scoreboard = new ScoreBoard(dummy); |
226 | layout->addWidget(scoreboard, 1, 0); |
227 | scoreboard->show(); |
228 | |
229 | if (loadedGame.isNull()) |
230 | { |
231 | PlayerEditor *curEditor = 0; |
232 | int newId = 1; |
233 | for (curEditor = dialog->players()->at(newId-1); newId <= dialog->players()->count(); ++newId) |
234 | { |
235 | players.append(Player()); |
236 | players.last().ball()->setColor(dialog->players()->at(newId-1)->color()); |
237 | players.last().setName(dialog->players()->at(newId-1)->name()); |
238 | players.last().setId(newId); |
239 | } |
240 | |
241 | competition = dialog->competition(); |
242 | filename = filename.isNull()? dialog->course() : filename; |
243 | } |
244 | else |
245 | { |
246 | KConfig config(loadedGame); |
247 | KConfigGroup configGroup(config.group("0 Saved Game" )); |
248 | |
249 | if (isTutorial) |
250 | filename = KGlobal::dirs()->findResource("appdata" , "tutorial.kolf" ); |
251 | else |
252 | filename = configGroup.readEntry("Course" , QString()); |
253 | |
254 | if (filename.isNull()) |
255 | return; |
256 | |
257 | competition = configGroup.readEntry("Competition" , false); |
258 | firstHole = configGroup.readEntry("Current Hole" , 1); |
259 | |
260 | players.clear(); |
261 | KolfGame::scoresFromSaved(&config, players); |
262 | } |
263 | |
264 | for (PlayerList::Iterator it = players.begin(); it != players.end(); ++it) |
265 | scoreboard->newPlayer((*it).name()); |
266 | |
267 | delete spacer; |
268 | spacer = 0; |
269 | delete game; |
270 | game = new KolfGame(m_itemFactory, &players, filename, dummy); |
271 | game->setStrict(competition); |
272 | |
273 | connect(game, SIGNAL(newHole(int)), scoreboard, SLOT(newHole(int))); |
274 | connect(game, SIGNAL(scoreChanged(int,int,int)), scoreboard, SLOT(setScore(int,int,int))); |
275 | connect(game, SIGNAL(parChanged(int,int)), scoreboard, SLOT(parChanged(int,int))); |
276 | connect(game, SIGNAL(modifiedChanged(bool)), this, SLOT(updateModified(bool))); |
277 | connect(game, SIGNAL(newPlayersTurn(Player*)), this, SLOT(newPlayersTurn(Player*))); |
278 | connect(game, SIGNAL(holesDone()), this, SLOT(gameOver())); |
279 | connect(game, SIGNAL(checkEditing()), this, SLOT(checkEditing())); |
280 | connect(game, SIGNAL(editingStarted()), this, SLOT(editingStarted())); |
281 | connect(game, SIGNAL(editingEnded()), this, SLOT(editingEnded())); |
282 | connect(game, SIGNAL(inPlayStart()), this, SLOT(inPlayStart())); |
283 | connect(game, SIGNAL(inPlayEnd()), this, SLOT(inPlayEnd())); |
284 | connect(game, SIGNAL(maxStrokesReached(QString)), this, SLOT(maxStrokesReached(QString))); |
285 | connect(game, SIGNAL(largestHole(int)), this, SLOT(updateHoleMenu(int))); |
286 | connect(game, SIGNAL(titleChanged(QString)), this, SLOT(titleChanged(QString))); |
287 | connect(game, SIGNAL(newStatusText(QString)), this, SLOT(newStatusText(QString))); |
288 | connect(game, SIGNAL(currentHole(int)), this, SLOT(setCurrentHole(int))); |
289 | connect(holeAction, SIGNAL(triggered(QString)), game, SLOT(switchHole(QString))); |
290 | connect(nextAction, SIGNAL(triggered(bool)), game, SLOT(nextHole())); |
291 | connect(prevAction, SIGNAL(triggered(bool)), game, SLOT(prevHole())); |
292 | connect(firstAction, SIGNAL(triggered(bool)), game, SLOT(firstHole())); |
293 | connect(lastAction, SIGNAL(triggered(bool)), game, SLOT(lastHole())); |
294 | connect(randAction, SIGNAL(triggered(bool)), game, SLOT(randHole())); |
295 | connect(editingAction, SIGNAL(triggered(bool)), game, SLOT(toggleEditMode())); |
296 | connect(newHoleAction, SIGNAL(triggered(bool)), game, SLOT(addNewHole())); |
297 | connect(clearHoleAction, SIGNAL(triggered(bool)), game, SLOT(clearHole())); |
298 | connect(resetHoleAction, SIGNAL(triggered(bool)), game, SLOT(resetHole())); |
299 | connect(undoShotAction, SIGNAL(triggered(bool)), game, SLOT(undoShot())); |
300 | //connect(replayShotAction, SIGNAL(triggered(bool)), game, SLOT(replay())); |
301 | connect(aboutAction, SIGNAL(triggered(bool)), game, SLOT(showInfoDlg())); |
302 | connect(useMouseAction, SIGNAL(toggled(bool)), game, SLOT(setUseMouse(bool))); |
303 | connect(useAdvancedPuttingAction, SIGNAL(toggled(bool)), game, SLOT(setUseAdvancedPutting(bool))); |
304 | connect(soundAction, SIGNAL(toggled(bool)), game, SLOT(setSound(bool))); |
305 | connect(showGuideLineAction, SIGNAL(toggled(bool)), game, SLOT(setShowGuideLine(bool))); |
306 | connect(showInfoAction, SIGNAL(toggled(bool)), game, SLOT(setShowInfo(bool))); |
307 | |
308 | game->setUseMouse(useMouseAction->isChecked()); |
309 | game->setUseAdvancedPutting(useAdvancedPuttingAction->isChecked()); |
310 | game->setShowInfo(showInfoAction->isChecked()); |
311 | game->setShowGuideLine(showGuideLineAction->isChecked()); |
312 | game->setSound(soundAction->isChecked()); |
313 | |
314 | layout->addWidget(game, 0, 0);//, Qt::AlignCenter); |
315 | |
316 | game->show(); |
317 | game->setFocus(); |
318 | |
319 | setEditingEnabled(true); |
320 | endAction->setEnabled(true); |
321 | setHoleMovementEnabled(true); |
322 | setHoleOtherEnabled(true); |
323 | aboutAction->setEnabled(true); |
324 | highScoreAction->setEnabled(true); |
325 | saveAction->setEnabled(true); |
326 | saveAsAction->setEnabled(true); |
327 | saveGameAction->setEnabled(true); |
328 | saveGameAsAction->setEnabled(true); |
329 | |
330 | clearHoleAction->setEnabled(false); |
331 | newHoleAction->setEnabled(false); |
332 | newAction->setEnabled(false); |
333 | loadGameAction->setEnabled(false); |
334 | tutorialAction->setEnabled(false); |
335 | |
336 | // so game can do stuff that needs to be done |
337 | // after things above are connected |
338 | game->startFirstHole(firstHole); |
339 | |
340 | end: |
341 | delete dialog; |
342 | } |
343 | |
344 | void KolfWindow::newGame() |
345 | { |
346 | isTutorial = false; |
347 | filename = QString(); |
348 | startNewGame(); |
349 | } |
350 | |
351 | void KolfWindow::tutorial() |
352 | { |
353 | QString newfilename = KGlobal::dirs()->findResource("appdata" , "tutorial.kolfgame" ); |
354 | if (newfilename.isNull()) |
355 | return; |
356 | |
357 | filename = QString(); |
358 | loadedGame = newfilename; |
359 | isTutorial = true; |
360 | |
361 | startNewGame(); |
362 | |
363 | loadedGame = QString(); |
364 | } |
365 | |
366 | void KolfWindow::closeGame() |
367 | { |
368 | if (game) |
369 | { |
370 | if (game->askSave(true)) |
371 | return; |
372 | game->pause(); |
373 | } |
374 | |
375 | filename = QString(); |
376 | |
377 | editingEnded(); |
378 | delete game; |
379 | game = 0; |
380 | loadedGame = QString(); |
381 | |
382 | editingAction->setChecked(false); |
383 | setEditingEnabled(false); |
384 | endAction->setEnabled(false); |
385 | aboutAction->setEnabled(false); |
386 | highScoreAction->setEnabled(false); |
387 | saveAction->setEnabled(false); |
388 | saveAsAction->setEnabled(false); |
389 | saveGameAction->setEnabled(false); |
390 | saveGameAsAction->setEnabled(false); |
391 | setHoleMovementEnabled(false); |
392 | setHoleOtherEnabled(false); |
393 | |
394 | clearHoleAction->setEnabled(false); |
395 | newHoleAction->setEnabled(false); |
396 | newAction->setEnabled(true); |
397 | loadGameAction->setEnabled(true); |
398 | tutorialAction->setEnabled(true); |
399 | |
400 | titleChanged(QString()); |
401 | updateModified(false); |
402 | |
403 | QTimer::singleShot(100, this, SLOT(createSpacer())); |
404 | } |
405 | |
406 | void KolfWindow::createSpacer() |
407 | { |
408 | // make a player to play the spacer hole |
409 | spacerPlayers.clear(); |
410 | spacerPlayers.append(Player()); |
411 | spacerPlayers.last().ball()->setColor(Qt::yellow); |
412 | spacerPlayers.last().setName("player" ); |
413 | spacerPlayers.last().setId(1); |
414 | |
415 | delete spacer; |
416 | spacer = new KolfGame(m_itemFactory, &spacerPlayers, KGlobal::dirs()->findResource("appdata" , "intro" ), dummy); |
417 | spacer->setSound(false); |
418 | layout->addWidget(spacer, 0, 0);//, Qt::AlignCenter); |
419 | spacer->ignoreEvents(true); |
420 | |
421 | spacer->show(); |
422 | spacer->startFirstHole(1); |
423 | spacer->hidePutter(); |
424 | } |
425 | |
426 | void KolfWindow::gameOver() |
427 | { |
428 | int curPar = 0; |
429 | int lowScore = INT_MAX; // let's hope it doesn't stay this way! |
430 | int curScore = 1; |
431 | |
432 | // names of people who had the lowest score |
433 | QStringList names; |
434 | |
435 | HighScoreList highScores; |
436 | int scoreBoardIndex = 1; |
437 | |
438 | while (curScore != 0) |
439 | { |
440 | QString curName; |
441 | |
442 | // name taken as a reference and filled out |
443 | curScore = scoreboard->total(scoreBoardIndex, curName); |
444 | |
445 | scoreBoardIndex++; |
446 | |
447 | if (curName == i18n("Par" )) |
448 | { |
449 | curPar = curScore; |
450 | curScore = 0; |
451 | continue; |
452 | } |
453 | |
454 | if (curScore == 0) |
455 | continue; |
456 | |
457 | // attempt to add everybody to the highscore list |
458 | // (ignored if we aren't competing down below) |
459 | highScores.append(HighScore(curName, curScore)); |
460 | |
461 | if (curScore < lowScore) |
462 | { |
463 | names.clear(); |
464 | lowScore = curScore; |
465 | names.append(curName); |
466 | } |
467 | else if (curScore == lowScore) |
468 | names.append(curName); |
469 | } |
470 | |
471 | // only announce a winner if more than two entries |
472 | // (player and par) are on the scoreboard + one to go past end |
473 | // + 1 for koodoo |
474 | if (scoreBoardIndex > 4) |
475 | { |
476 | if (names.count() > 1) |
477 | { |
478 | QString winners = names.join( i18n(" and " )); |
479 | KMessageBox::information(this, i18n("%1 tied" , winners)); |
480 | } |
481 | else |
482 | KMessageBox::information(this, i18n("%1 won!" , names.first())); |
483 | } |
484 | |
485 | if (competition) |
486 | { |
487 | // deal with highscores |
488 | // KScoreDialog makes it very easy :-)) |
489 | |
490 | KScoreDialog *scoreDialog = new KScoreDialog(KScoreDialog::Name | KScoreDialog::Custom1 | KScoreDialog::Score, this); |
491 | scoreDialog->addField(KScoreDialog::Custom1, i18n("Par" ), "Par" ); |
492 | |
493 | CourseInfo courseInfo; |
494 | game->courseInfo(courseInfo, game->curFilename()); |
495 | |
496 | scoreDialog->setConfigGroup(courseInfo.untranslatedName + QString(" Highscores" )); |
497 | |
498 | for (HighScoreList::Iterator it = highScores.begin(); it != highScores.end(); ++it) |
499 | { |
500 | KScoreDialog::FieldInfo info; |
501 | info[KScoreDialog::Name] = (*it).name; |
502 | info[KScoreDialog::Score].setNum((*it).score); |
503 | info[KScoreDialog::Custom1] = QString::number(curPar); |
504 | |
505 | scoreDialog->addScore(info, KScoreDialog::LessIsMore); |
506 | } |
507 | |
508 | scoreDialog->setComment(i18n("High Scores for %1" , courseInfo.name)); |
509 | scoreDialog->show(); |
510 | } |
511 | |
512 | QTimer::singleShot(700, this, SLOT(closeGame())); |
513 | } |
514 | |
515 | void KolfWindow::showHighScores() |
516 | { |
517 | KScoreDialog *scoreDialog = new KScoreDialog(KScoreDialog::Name | KScoreDialog::Custom1 | KScoreDialog::Score, this); |
518 | scoreDialog->addField(KScoreDialog::Custom1, i18n("Par" ), "Par" ); |
519 | |
520 | CourseInfo courseInfo; |
521 | game->courseInfo(courseInfo, game->curFilename()); |
522 | |
523 | scoreDialog->setConfigGroup(courseInfo.untranslatedName + QString(" Highscores" )); |
524 | scoreDialog->setComment(i18n("High Scores for %1" , courseInfo.name)); |
525 | scoreDialog->show(); |
526 | } |
527 | |
528 | void KolfWindow::save() |
529 | { |
530 | if (filename.isNull()) |
531 | { |
532 | saveAs(); |
533 | return; |
534 | } |
535 | |
536 | if (game) { |
537 | game->save(); |
538 | game->setFocus(); |
539 | } |
540 | } |
541 | |
542 | void KolfWindow::saveAs() |
543 | { |
544 | QString newfilename = KFileDialog::getSaveFileName( KUrl("kfiledialog:///kourses" ), |
545 | "application/x-kourse" , this, i18n("Pick Kolf Course to Save To" )); |
546 | if (!newfilename.isNull()) |
547 | { |
548 | filename = newfilename; |
549 | game->setFilename(filename); |
550 | game->save(); |
551 | game->setFocus(); |
552 | } |
553 | } |
554 | |
555 | void KolfWindow::saveGameAs() |
556 | { |
557 | QString newfilename = KFileDialog::getSaveFileName( KUrl("kfiledialog:///savedkolf" ), |
558 | "application/x-kolf" , this, i18n("Pick Saved Game to Save To" )); |
559 | if (newfilename.isNull()) |
560 | return; |
561 | |
562 | loadedGame = newfilename; |
563 | |
564 | saveGame(); |
565 | } |
566 | |
567 | void KolfWindow::saveGame() |
568 | { |
569 | if (loadedGame.isNull()) |
570 | { |
571 | saveGameAs(); |
572 | return; |
573 | } |
574 | |
575 | KConfig config(loadedGame); |
576 | KConfigGroup configGroup(config.group("0 Saved Game" )); |
577 | |
578 | configGroup.writeEntry("Competition" , competition); |
579 | configGroup.writeEntry("Course" , filename); |
580 | |
581 | game->saveScores(&config); |
582 | |
583 | configGroup.sync(); |
584 | } |
585 | |
586 | void KolfWindow::loadGame() |
587 | { |
588 | loadedGame = KFileDialog::getOpenFileName( KUrl("kfiledialog:///savedkolf" ), |
589 | QLatin1String("application/x-kolf" ), this, i18n("Pick Kolf Saved Game" )); |
590 | |
591 | if (loadedGame.isNull()) |
592 | return; |
593 | |
594 | isTutorial = false; |
595 | startNewGame(); |
596 | } |
597 | |
598 | // called by main for command line files |
599 | void KolfWindow::openUrl(KUrl url) |
600 | { |
601 | QString target; |
602 | if (KIO::NetAccess::download(url, target, this)) |
603 | { |
604 | isTutorial = false; |
605 | QString mimeType = KMimeType::findByPath(target)->name(); |
606 | if (mimeType == "application/x-kourse" ) |
607 | filename = target; |
608 | else if (mimeType == "application/x-kolf" ) |
609 | loadedGame = target; |
610 | else |
611 | { |
612 | closeGame(); |
613 | return; |
614 | } |
615 | |
616 | QTimer::singleShot(10, this, SLOT(startNewGame())); |
617 | } |
618 | else |
619 | closeGame(); |
620 | } |
621 | |
622 | void KolfWindow::newPlayersTurn(Player *player) |
623 | { |
624 | tempStatusBarText = i18n("%1's turn" , player->name()); |
625 | |
626 | if (showInfoAction->isChecked()) |
627 | statusBar()->showMessage(tempStatusBarText, 5 * 1000); |
628 | else |
629 | statusBar()->showMessage(tempStatusBarText); |
630 | |
631 | scoreboard->setCurrentCell(player->id() - 1, game->currentHole() - 1); |
632 | } |
633 | |
634 | void KolfWindow::newStatusText(const QString &text) |
635 | { |
636 | if (text.isEmpty()) |
637 | statusBar()->showMessage(tempStatusBarText); |
638 | else |
639 | statusBar()->showMessage(text); |
640 | } |
641 | |
642 | void KolfWindow::editingStarted() |
643 | { |
644 | delete editor; |
645 | editor = new Editor(m_itemFactory, dummy); |
646 | editor->setObjectName( QLatin1String( "Editor" ) ); |
647 | connect(editor, SIGNAL(addNewItem(QString)), game, SLOT(addNewObject(QString))); |
648 | connect(editor, SIGNAL(changed()), game, SLOT(setModified())); |
649 | connect(editor, SIGNAL(addNewItem(QString)), this, SLOT(setHoleFocus())); |
650 | connect(game, SIGNAL(newSelectedItem(CanvasItem*)), editor, SLOT(setItem(CanvasItem*))); |
651 | |
652 | scoreboard->hide(); |
653 | |
654 | layout->addWidget(editor, 1, 0); |
655 | editor->show(); |
656 | |
657 | clearHoleAction->setEnabled(true); |
658 | newHoleAction->setEnabled(true); |
659 | setHoleOtherEnabled(false); |
660 | |
661 | game->setFocus(); |
662 | } |
663 | |
664 | void KolfWindow::editingEnded() |
665 | { |
666 | delete editor; |
667 | editor = 0; |
668 | |
669 | if (scoreboard) |
670 | scoreboard->show(); |
671 | |
672 | clearHoleAction->setEnabled(false); |
673 | newHoleAction->setEnabled(false); |
674 | setHoleOtherEnabled(true); |
675 | |
676 | if (game) |
677 | game->setFocus(); |
678 | } |
679 | |
680 | void KolfWindow::inPlayStart() |
681 | { |
682 | setEditingEnabled(false); |
683 | setHoleOtherEnabled(false); |
684 | setHoleMovementEnabled(false); |
685 | } |
686 | |
687 | void KolfWindow::inPlayEnd() |
688 | { |
689 | setEditingEnabled(true); |
690 | setHoleOtherEnabled(true); |
691 | setHoleMovementEnabled(true); |
692 | } |
693 | |
694 | void KolfWindow::maxStrokesReached(const QString &name) |
695 | { |
696 | KMessageBox::sorry(this, i18n("%1's score has reached the maximum for this hole." , name)); |
697 | } |
698 | |
699 | void KolfWindow::(int largest) |
700 | { |
701 | QStringList items; |
702 | for (int i = 1; i <= largest; ++i) |
703 | items.append(QString::number(i)); |
704 | |
705 | // setItems for some reason enables the action |
706 | bool shouldbe = holeAction->isEnabled(); |
707 | holeAction->setItems(items); |
708 | holeAction->setEnabled(shouldbe); |
709 | } |
710 | |
711 | void KolfWindow::setHoleMovementEnabled(bool yes) |
712 | { |
713 | if (competition) |
714 | yes = false; |
715 | |
716 | holeAction->setEnabled(yes); |
717 | |
718 | nextAction->setEnabled(yes); |
719 | prevAction->setEnabled(yes); |
720 | firstAction->setEnabled(yes); |
721 | lastAction->setEnabled(yes); |
722 | randAction->setEnabled(yes); |
723 | } |
724 | |
725 | void KolfWindow::setHoleOtherEnabled(bool yes) |
726 | { |
727 | if (competition) |
728 | yes = false; |
729 | |
730 | resetHoleAction->setEnabled(yes); |
731 | undoShotAction->setEnabled(yes); |
732 | //replayShotAction->setEnabled(yes); |
733 | } |
734 | |
735 | void KolfWindow::setEditingEnabled(bool yes) |
736 | { |
737 | editingAction->setEnabled(competition? false : yes); |
738 | } |
739 | |
740 | void KolfWindow::checkEditing() |
741 | { |
742 | editingAction->setChecked(true); |
743 | } |
744 | |
745 | void KolfWindow::updateModified(bool mod) |
746 | { |
747 | courseModified = mod; |
748 | titleChanged(title); |
749 | } |
750 | |
751 | void KolfWindow::titleChanged(const QString &newTitle) |
752 | { |
753 | title = newTitle; |
754 | setCaption(title, courseModified); |
755 | } |
756 | |
757 | void KolfWindow::useMouseChanged(bool yes) |
758 | { |
759 | KConfigGroup configGroup(KGlobal::config(), "Settings" ); configGroup.writeEntry("useMouse" , yes); configGroup.sync(); |
760 | } |
761 | |
762 | void KolfWindow::useAdvancedPuttingChanged(bool yes) |
763 | { |
764 | KConfigGroup configGroup(KGlobal::config(), "Settings" ); configGroup.writeEntry("useAdvancedPutting" , yes); configGroup.sync(); |
765 | } |
766 | |
767 | void KolfWindow::showInfoChanged(bool yes) |
768 | { |
769 | KConfigGroup configGroup(KGlobal::config(), "Settings" ); configGroup.writeEntry("showInfo" , yes); configGroup.sync(); |
770 | } |
771 | |
772 | void KolfWindow::showGuideLineChanged(bool yes) |
773 | { |
774 | KConfigGroup configGroup(KGlobal::config(), "Settings" ); configGroup.writeEntry("showGuideLine" , yes); configGroup.sync(); |
775 | } |
776 | |
777 | void KolfWindow::soundChanged(bool yes) |
778 | { |
779 | KConfigGroup configGroup(KGlobal::config(), "Settings" ); configGroup.writeEntry("sound" , yes); configGroup.sync(); |
780 | } |
781 | |
782 | void KolfWindow::enableAllMessages() |
783 | { |
784 | KMessageBox::enableAllMessages(); |
785 | } |
786 | |
787 | void KolfWindow::setCurrentHole(int hole) |
788 | { |
789 | if (!holeAction || holeAction->items().count() < hole) |
790 | return; |
791 | // Golf is 1-based, KListAction is 0-based |
792 | holeAction->setCurrentItem(hole - 1); |
793 | } |
794 | |
795 | #include "kolf.moc" |
796 | |