File indexing completed on 2025-02-02 07:28:23
0001 /* 0002 Copyright (C) 2002-2005, Jason Katz-Brown <jasonkb@mit.edu> 0003 Copyright 2010 Stefan Majewsky <majewsky@gmx.net> 0004 0005 This program is free software; you can redistribute it and/or modify 0006 it under the terms of the GNU General Public License as published by 0007 the Free Software Foundation; either version 2 of the License, or 0008 (at your option) any later version. 0009 0010 This program is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 GNU General Public License for more details. 0014 0015 You should have received a copy of the GNU General Public License 0016 along with this program; if not, write to the Free Software 0017 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 0018 */ 0019 0020 #include "kolf.h" 0021 #include "editor.h" 0022 #include "landscape.h" 0023 #include "newgame.h" 0024 #include "objects.h" 0025 #include "obstacles.h" 0026 #include "scoreboard.h" 0027 0028 #include <KGameHighScoreDialog> 0029 #include <KGameStandardAction> 0030 0031 #include <KActionCollection> 0032 #include <KIO/FileCopyJob> 0033 #include <KJobWidgets> 0034 #include <KLocalizedString> 0035 #include <KMessageBox> 0036 #include <KSelectAction> 0037 #include <KSharedConfig> 0038 #include <KStandardAction> 0039 #include <KStandardGuiItem> 0040 #include <KToggleAction> 0041 0042 #include <QFileDialog> 0043 #include <QGridLayout> 0044 #include <QMimeDatabase> 0045 #include <QStandardPaths> 0046 #include <QStatusBar> 0047 #include <QTemporaryFile> 0048 #include <QTimer> 0049 0050 KolfWindow::KolfWindow() 0051 : KXmlGuiWindow(nullptr) 0052 { 0053 setObjectName( QStringLiteral("Kolf" )); 0054 competition = false; 0055 game = nullptr; 0056 editor = nullptr; 0057 spacer = nullptr; 0058 scoreboard = nullptr; 0059 isTutorial = false; 0060 0061 setupActions(); 0062 0063 m_itemFactory.registerType<Kolf::Slope>(QStringLiteral("slope"), i18n("Slope")); 0064 m_itemFactory.registerType<Kolf::Puddle>(QStringLiteral("puddle"), i18n("Puddle")); 0065 m_itemFactory.registerType<Kolf::Wall>(QStringLiteral("wall"), i18n("Wall")); 0066 m_itemFactory.registerType<Kolf::Cup>(QStringLiteral("cup"), i18n("Cup"), true); //true == addOnNewHole 0067 m_itemFactory.registerType<Kolf::Sand>(QStringLiteral("sand"), i18n("Sand")); 0068 m_itemFactory.registerType<Kolf::Windmill>(QStringLiteral("windmill"), i18n("Windmill")); 0069 m_itemFactory.registerType<Kolf::BlackHole>(QStringLiteral("blackhole"), i18n("Black Hole")); 0070 m_itemFactory.registerType<Kolf::Floater>(QStringLiteral("floater"), i18n("Floater")); 0071 m_itemFactory.registerType<Kolf::Bridge>(QStringLiteral("bridge"), i18n("Bridge")); 0072 m_itemFactory.registerType<Kolf::Sign>(QStringLiteral("sign"), i18n("Sign")); 0073 m_itemFactory.registerType<Kolf::Bumper>(QStringLiteral("bumper"), i18n("Bumper")); 0074 //NOTE: The plugin mechanism has been removed because it is not used anyway. 0075 0076 filename = QString(); 0077 dummy = new QWidget(this); 0078 setCentralWidget(dummy); 0079 layout = new QGridLayout(dummy); 0080 0081 resize(420, 480); 0082 } 0083 0084 KolfWindow::~KolfWindow() 0085 { 0086 } 0087 0088 void KolfWindow::setupActions() 0089 { 0090 // Game 0091 newAction = KGameStandardAction::gameNew(this, &KolfWindow::newGame, actionCollection()); 0092 endAction = KGameStandardAction::end(this, &KolfWindow::closeGame, actionCollection()); 0093 KGameStandardAction::quit(this, &KolfWindow::close, actionCollection()); 0094 0095 saveAction = actionCollection()->addAction(KStandardAction::Save, QStringLiteral("game_save"), this, &KolfWindow::save); 0096 saveAction->setText(i18n("Save &Course")); 0097 saveAsAction = actionCollection()->addAction(KStandardAction::SaveAs, QStringLiteral("game_save_as"), this, &KolfWindow::saveAs); 0098 saveAsAction->setText(i18n("Save &Course As...")); 0099 0100 saveGameAction = actionCollection()->addAction(QStringLiteral("savegame")); 0101 saveGameAction->setText(i18n("&Save Game")); 0102 connect(saveGameAction, &QAction::triggered, this, &KolfWindow::saveGame); 0103 saveGameAsAction = actionCollection()->addAction(QStringLiteral("savegameas")); 0104 saveGameAsAction->setText(i18n("&Save Game As...")); 0105 connect(saveGameAsAction, &QAction::triggered, this, &KolfWindow::saveGameAs); 0106 0107 loadGameAction = KGameStandardAction::load(this, &KolfWindow::loadGame, actionCollection()); 0108 highScoreAction = KGameStandardAction::highscores(this, &KolfWindow::showHighScores, actionCollection()); 0109 0110 // Hole 0111 editingAction = new KToggleAction(QIcon::fromTheme( QStringLiteral( "document-properties") ), i18n("&Edit"), this); 0112 actionCollection()->addAction(QStringLiteral("editing"), editingAction); 0113 connect(editingAction, &QAction::triggered, this, &KolfWindow::emptySlot); 0114 KActionCollection::setDefaultShortcut(editingAction, Qt::CTRL|Qt::Key_E); 0115 newHoleAction = actionCollection()->addAction(QStringLiteral("newhole")); 0116 newHoleAction->setIcon(QIcon::fromTheme( QStringLiteral( "document-new" ))); 0117 newHoleAction->setText(i18n("&New")); 0118 connect(newHoleAction, &QAction::triggered, this, &KolfWindow::emptySlot); 0119 KActionCollection::setDefaultShortcut(newHoleAction, Qt::CTRL|Qt::SHIFT|Qt::Key_N); 0120 clearHoleAction = actionCollection()->addAction(QStringLiteral("clearhole")); 0121 clearHoleAction->setIcon(QIcon::fromTheme( QStringLiteral( "edit-clear-locationbar-ltr" ))); 0122 clearHoleAction->setText(KStandardGuiItem::clear().text()); 0123 connect(clearHoleAction, &QAction::triggered, this, &KolfWindow::emptySlot); 0124 KActionCollection::setDefaultShortcut(clearHoleAction, Qt::CTRL|Qt::Key_Delete); 0125 resetHoleAction = actionCollection()->addAction(QStringLiteral("resethole")); 0126 resetHoleAction->setText(i18n("&Reset")); 0127 connect(resetHoleAction, &QAction::triggered, this, &KolfWindow::emptySlot); 0128 KActionCollection::setDefaultShortcut(resetHoleAction, Qt::CTRL|Qt::Key_R); 0129 undoShotAction = KStandardAction::undo(this, &KolfWindow::emptySlot, this); 0130 actionCollection()->addAction(QStringLiteral("undoshot"), undoShotAction); 0131 undoShotAction->setText(i18n("&Undo Shot")); 0132 //replayShotAction = new QAction(i18n("&Replay Shot"), 0, this, SLOT(emptySlot()), actionCollection(), "replay"); 0133 0134 // Go 0135 holeAction = new KSelectAction(i18n("Switch to Hole"), this); 0136 actionCollection()->addAction(QStringLiteral("switchhole"), holeAction); 0137 connect(holeAction, &QAction::triggered, this, &KolfWindow::emptySlot); 0138 nextAction = actionCollection()->addAction(QStringLiteral("nexthole")); 0139 nextAction->setIcon(QIcon::fromTheme( QStringLiteral( "go-next" ))); 0140 nextAction->setText(i18n("&Next Hole")); 0141 connect(nextAction, &QAction::triggered, this, &KolfWindow::emptySlot); 0142 KActionCollection::setDefaultShortcuts(nextAction, KStandardShortcut::forward()); 0143 prevAction = actionCollection()->addAction(QStringLiteral("prevhole")); 0144 prevAction->setIcon(QIcon::fromTheme( QStringLiteral( "go-previous" ))); 0145 prevAction->setText(i18n("&Previous Hole")); 0146 connect(prevAction, &QAction::triggered, this, &KolfWindow::emptySlot); 0147 KActionCollection::setDefaultShortcuts(prevAction, KStandardShortcut::back()); 0148 firstAction = actionCollection()->addAction(QStringLiteral("firsthole")); 0149 firstAction->setIcon(QIcon::fromTheme( QStringLiteral( "go-home" ))); 0150 firstAction->setText(i18n("&First Hole")); 0151 connect(firstAction, &QAction::triggered, this, &KolfWindow::emptySlot); 0152 KActionCollection::setDefaultShortcuts(firstAction, KStandardShortcut::begin()); 0153 lastAction = actionCollection()->addAction(QStringLiteral("lasthole")); 0154 lastAction->setText(i18n("&Last Hole")); 0155 connect(lastAction, &QAction::triggered, this, &KolfWindow::emptySlot); 0156 KActionCollection::setDefaultShortcut(lastAction, Qt::CTRL|Qt::SHIFT|Qt::Key_End); // why not KStandardShortcut::End (Ctrl+End)? 0157 randAction = actionCollection()->addAction(QStringLiteral("randhole")); 0158 randAction->setIcon(QIcon::fromTheme( QStringLiteral( "go-jump" ))); 0159 randAction->setText(i18n("&Random Hole")); 0160 connect(randAction, &QAction::triggered, this, &KolfWindow::emptySlot); 0161 0162 // Settings 0163 useMouseAction = new KToggleAction(i18n("Enable &Mouse for Moving Putter"), this); 0164 actionCollection()->addAction(QStringLiteral("usemouse"), useMouseAction); 0165 connect(useMouseAction, &QAction::triggered, this, &KolfWindow::emptySlot); 0166 connect(useMouseAction, &QAction::toggled, this, &KolfWindow::useMouseChanged); 0167 KConfigGroup configGroup(KSharedConfig::openConfig(), QStringLiteral("Settings")); 0168 useMouseAction->setChecked(configGroup.readEntry("useMouse", true)); 0169 0170 useAdvancedPuttingAction = new KToggleAction(i18n("Enable &Advanced Putting"), this); 0171 actionCollection()->addAction(QStringLiteral("useadvancedputting"), useAdvancedPuttingAction); 0172 connect(useAdvancedPuttingAction, &QAction::triggered, this, &KolfWindow::emptySlot); 0173 connect(useAdvancedPuttingAction, &QAction::toggled, this, &KolfWindow::useAdvancedPuttingChanged); 0174 useAdvancedPuttingAction->setChecked(configGroup.readEntry("useAdvancedPutting", false)); 0175 0176 showInfoAction = new KToggleAction(QIcon::fromTheme( QStringLiteral( "help-about")), i18n("Show &Info"), this); 0177 actionCollection()->addAction(QStringLiteral("showinfo"), showInfoAction); 0178 connect(showInfoAction, &QAction::triggered, this, &KolfWindow::emptySlot); 0179 KActionCollection::setDefaultShortcut(showInfoAction, Qt::CTRL|Qt::Key_I); 0180 connect(showInfoAction, &QAction::toggled, this, &KolfWindow::showInfoChanged); 0181 showInfoAction->setChecked(configGroup.readEntry("showInfo", true)); 0182 0183 showGuideLineAction = new KToggleAction(i18n("Show Putter &Guideline"), this); 0184 actionCollection()->addAction(QStringLiteral("showguideline"), showGuideLineAction); 0185 connect(showGuideLineAction, &QAction::triggered, this, &KolfWindow::emptySlot); 0186 connect(showGuideLineAction, &QAction::toggled, this, &KolfWindow::showGuideLineChanged); 0187 showGuideLineAction->setChecked(configGroup.readEntry("showGuideLine", true)); 0188 0189 KToggleAction *act = new KToggleAction(i18n("Enable All Dialog Boxes"), this); 0190 actionCollection()->addAction(QStringLiteral("enableAll"), act); 0191 connect(act, &QAction::triggered, this, &KolfWindow::enableAllMessages); 0192 0193 soundAction = new KToggleAction(i18n("Play &Sounds"), this); 0194 actionCollection()->addAction(QStringLiteral("sound"), soundAction); 0195 connect(soundAction, &QAction::triggered, this, &KolfWindow::emptySlot); 0196 connect(soundAction, &QAction::toggled, this, &KolfWindow::soundChanged); 0197 soundAction->setChecked(configGroup.readEntry("sound", true)); 0198 0199 aboutAction = actionCollection()->addAction(QStringLiteral("aboutcourse")); 0200 aboutAction->setText(i18n("&About Course...")); 0201 connect(aboutAction, &QAction::triggered, this, &KolfWindow::emptySlot); 0202 tutorialAction = actionCollection()->addAction(QStringLiteral("tutorial")); 0203 tutorialAction->setText(i18n("&Tutorial")); 0204 connect(tutorialAction, &QAction::triggered, this, &KolfWindow::tutorial); 0205 0206 setupGUI(); 0207 } 0208 0209 bool KolfWindow::queryClose() 0210 { 0211 if (game) 0212 if (game->askSave(true)) 0213 return false; 0214 return true; 0215 } 0216 0217 void KolfWindow::startNewGame() 0218 { 0219 NewGameDialog *dialog = nullptr; 0220 int firstHole = 1; 0221 0222 if (loadedGame.isNull()) 0223 { 0224 dialog = new NewGameDialog(filename.isNull()); 0225 if (dialog->exec() != QDialog::Accepted) { 0226 delete dialog; 0227 return; 0228 } 0229 } 0230 0231 players.clear(); 0232 delete scoreboard; 0233 scoreboard = new ScoreBoard(dummy); 0234 layout->addWidget(scoreboard, 1, 0); 0235 scoreboard->show(); 0236 0237 if (loadedGame.isNull()) 0238 { 0239 for (int newId = 1; newId <= dialog->players()->count(); ++newId) 0240 { 0241 players.append(Player()); 0242 players.last().ball()->setColor(dialog->players()->at(newId-1)->color()); 0243 players.last().setName(dialog->players()->at(newId-1)->name()); 0244 players.last().setId(newId); 0245 } 0246 0247 competition = dialog->competition(); 0248 filename = filename.isNull()? dialog->course() : filename; 0249 } 0250 else 0251 { 0252 KConfig config(loadedGame); 0253 KConfigGroup configGroup(config.group(QStringLiteral("0 Saved Game"))); 0254 0255 if (isTutorial) 0256 filename = QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("tutorial.kolf")); 0257 else 0258 filename = configGroup.readEntry("Course", QString()); 0259 0260 if (filename.isNull()) 0261 return; 0262 0263 competition = configGroup.readEntry("Competition", false); 0264 firstHole = configGroup.readEntry("Current Hole", 1); 0265 0266 players.clear(); 0267 KolfGame::scoresFromSaved(&config, players); 0268 } 0269 0270 for (PlayerList::Iterator it = players.begin(); it != players.end(); ++it) 0271 scoreboard->newPlayer((*it).name()); 0272 0273 delete spacer; 0274 spacer = nullptr; 0275 delete game; 0276 game = new KolfGame(m_itemFactory, &players, filename, dummy); 0277 game->setStrict(competition); 0278 0279 connect(game, &KolfGame::newHole, scoreboard, &ScoreBoard::newHole); 0280 connect(game, &KolfGame::scoreChanged, scoreboard, &ScoreBoard::setScore); 0281 connect(game, &KolfGame::parChanged, scoreboard, &ScoreBoard::parChanged); 0282 connect(game, &KolfGame::modifiedChanged, this, &KolfWindow::updateModified); 0283 connect(game, &KolfGame::newPlayersTurn, this, &KolfWindow::newPlayersTurn); 0284 connect(game, &KolfGame::holesDone, this, &KolfWindow::gameOver); 0285 connect(game, &KolfGame::checkEditing, this, &KolfWindow::checkEditing); 0286 connect(game, &KolfGame::editingStarted, this, &KolfWindow::editingStarted); 0287 connect(game, &KolfGame::editingEnded, this, &KolfWindow::editingEnded); 0288 connect(game, &KolfGame::inPlayStart, this, &KolfWindow::inPlayStart); 0289 connect(game, &KolfGame::inPlayEnd, this, &KolfWindow::inPlayEnd); 0290 connect(game, &KolfGame::maxStrokesReached, this, &KolfWindow::maxStrokesReached); 0291 connect(game, &KolfGame::largestHole, this, &KolfWindow::updateHoleMenu); 0292 connect(game, &KolfGame::titleChanged, this, &KolfWindow::titleChanged); 0293 connect(game, &KolfGame::newStatusText, this, &KolfWindow::newStatusText); 0294 connect(game, qOverload<int>(&KolfGame::currentHole), this, 0295 &KolfWindow::setCurrentHole); 0296 connect(holeAction, &QAction::triggered, game, 0297 qOverload<int>(&KolfGame::switchHole)); 0298 connect(nextAction, &QAction::triggered, game, &KolfGame::nextHole); 0299 connect(prevAction, &QAction::triggered, game, &KolfGame::prevHole); 0300 connect(firstAction, &QAction::triggered, game, &KolfGame::firstHole); 0301 connect(lastAction, &QAction::triggered, game, &KolfGame::lastHole); 0302 connect(randAction, &QAction::triggered, game, &KolfGame::randHole); 0303 connect(editingAction, &QAction::triggered, game, &KolfGame::toggleEditMode); 0304 connect(newHoleAction, &QAction::triggered, game, &KolfGame::addNewHole); 0305 connect(clearHoleAction, &QAction::triggered, game, &KolfGame::clearHole); 0306 connect(resetHoleAction, &QAction::triggered, game, &KolfGame::resetHole); 0307 connect(undoShotAction, &QAction::triggered, game, &KolfGame::undoShot); 0308 //connect(replayShotAction, &QAction::triggered, game, &KolfGame::replay); 0309 connect(aboutAction, &QAction::triggered, game, &KolfGame::showInfoDlg); 0310 connect(useMouseAction, &QAction::toggled, game, &KolfGame::setUseMouse); 0311 connect(useAdvancedPuttingAction, &QAction::toggled, game, &KolfGame::setUseAdvancedPutting); 0312 connect(soundAction, &QAction::toggled, game, &KolfGame::setSound); 0313 connect(showGuideLineAction, &QAction::toggled, game, &KolfGame::setShowGuideLine); 0314 connect(showInfoAction, &QAction::toggled, game, &KolfGame::setShowInfo); 0315 0316 game->setUseMouse(useMouseAction->isChecked()); 0317 game->setUseAdvancedPutting(useAdvancedPuttingAction->isChecked()); 0318 game->setShowInfo(showInfoAction->isChecked()); 0319 game->setShowGuideLine(showGuideLineAction->isChecked()); 0320 game->setSound(soundAction->isChecked()); 0321 0322 layout->addWidget(game, 0, 0);//, Qt::AlignCenter); 0323 0324 game->show(); 0325 game->setFocus(); 0326 0327 setEditingEnabled(true); 0328 endAction->setEnabled(true); 0329 setHoleMovementEnabled(true); 0330 setHoleOtherEnabled(true); 0331 aboutAction->setEnabled(true); 0332 highScoreAction->setEnabled(true); 0333 saveAction->setEnabled(true); 0334 saveAsAction->setEnabled(true); 0335 saveGameAction->setEnabled(true); 0336 saveGameAsAction->setEnabled(true); 0337 0338 clearHoleAction->setEnabled(false); 0339 newHoleAction->setEnabled(false); 0340 newAction->setEnabled(false); 0341 loadGameAction->setEnabled(false); 0342 tutorialAction->setEnabled(false); 0343 0344 // so game can do stuff that needs to be done 0345 // after things above are connected 0346 game->startFirstHole(firstHole); 0347 delete dialog; 0348 } 0349 0350 void KolfWindow::newGame() 0351 { 0352 isTutorial = false; 0353 filename = QString(); 0354 startNewGame(); 0355 } 0356 0357 void KolfWindow::tutorial() 0358 { 0359 QString newfilename = QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("tutorial.kolfgame")); 0360 if (newfilename.isNull()) 0361 return; 0362 0363 filename = QString(); 0364 loadedGame = newfilename; 0365 isTutorial = true; 0366 0367 startNewGame(); 0368 0369 loadedGame = QString(); 0370 } 0371 0372 void KolfWindow::closeGame() 0373 { 0374 if (game) 0375 { 0376 if (game->askSave(true)) 0377 return; 0378 game->pause(); 0379 } 0380 0381 filename = QString(); 0382 0383 editingEnded(); 0384 delete game; 0385 game = nullptr; 0386 loadedGame = QString(); 0387 0388 editingAction->setChecked(false); 0389 setEditingEnabled(false); 0390 endAction->setEnabled(false); 0391 aboutAction->setEnabled(false); 0392 highScoreAction->setEnabled(false); 0393 saveAction->setEnabled(false); 0394 saveAsAction->setEnabled(false); 0395 saveGameAction->setEnabled(false); 0396 saveGameAsAction->setEnabled(false); 0397 setHoleMovementEnabled(false); 0398 setHoleOtherEnabled(false); 0399 0400 clearHoleAction->setEnabled(false); 0401 newHoleAction->setEnabled(false); 0402 newAction->setEnabled(true); 0403 loadGameAction->setEnabled(true); 0404 tutorialAction->setEnabled(true); 0405 0406 titleChanged(QString()); 0407 updateModified(false); 0408 0409 QTimer::singleShot(100, this, &KolfWindow::createSpacer); 0410 } 0411 0412 void KolfWindow::createSpacer() 0413 { 0414 // make a player to play the spacer hole 0415 spacerPlayers.clear(); 0416 spacerPlayers.append(Player()); 0417 spacerPlayers.last().ball()->setColor(Qt::yellow); 0418 spacerPlayers.last().setName(QStringLiteral("player")); 0419 spacerPlayers.last().setId(1); 0420 0421 delete spacer; 0422 spacer = new KolfGame(m_itemFactory, &spacerPlayers, QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("intro")), dummy); 0423 spacer->setSound(false); 0424 layout->addWidget(spacer, 0, 0);//, Qt::AlignCenter); 0425 spacer->ignoreEvents(true); 0426 0427 spacer->show(); 0428 spacer->startFirstHole(1); 0429 spacer->hidePutter(); 0430 } 0431 0432 void KolfWindow::gameOver() 0433 { 0434 int curPar = 0; 0435 int lowScore = INT_MAX; // let's hope it doesn't stay this way! 0436 int curScore = 1; 0437 0438 // names of people who had the lowest score 0439 QStringList names; 0440 0441 HighScoreList highScores; 0442 int scoreBoardIndex = 1; 0443 0444 while (curScore != 0) 0445 { 0446 QString curName; 0447 0448 // name taken as a reference and filled out 0449 curScore = scoreboard->total(scoreBoardIndex, curName); 0450 0451 scoreBoardIndex++; 0452 0453 if (curName == i18n("Par")) 0454 { 0455 curPar = curScore; 0456 curScore = 0; 0457 continue; 0458 } 0459 0460 if (curScore == 0) 0461 continue; 0462 0463 // attempt to add everybody to the highscore list 0464 // (ignored if we aren't competing down below) 0465 highScores.append(HighScore(curName, curScore)); 0466 0467 if (curScore < lowScore) 0468 { 0469 names.clear(); 0470 lowScore = curScore; 0471 names.append(curName); 0472 } 0473 else if (curScore == lowScore) 0474 names.append(curName); 0475 } 0476 0477 // only announce a winner if more than two entries 0478 // (player and par) are on the scoreboard + one to go past end 0479 // + 1 for koodoo 0480 if (scoreBoardIndex > 4) 0481 { 0482 if (names.count() > 1) 0483 { 0484 QString winners = names.join( i18n(" and " )); 0485 KMessageBox::information(this, i18n("%1 tied", winners)); 0486 } 0487 else 0488 KMessageBox::information(this, i18n("%1 won!", names.first())); 0489 } 0490 0491 if (competition) 0492 { 0493 // deal with highscores 0494 // KGameHighScoreDialog makes it very easy :-)) 0495 0496 KGameHighScoreDialog *scoreDialog = new KGameHighScoreDialog(KGameHighScoreDialog::Name | KGameHighScoreDialog::Custom1 | KGameHighScoreDialog::Score, this); 0497 scoreDialog->addField(KGameHighScoreDialog::Custom1, i18n("Par"), QStringLiteral("Par")); 0498 0499 CourseInfo courseInfo; 0500 game->courseInfo(courseInfo, game->curFilename()); 0501 0502 scoreDialog->setConfigGroup(qMakePair(QByteArray(courseInfo.untranslatedName.toUtf8() + " Highscores"), i18n("High Scores for %1", courseInfo.name))); 0503 0504 for (HighScoreList::Iterator it = highScores.begin(); it != highScores.end(); ++it) 0505 { 0506 KGameHighScoreDialog::FieldInfo info; 0507 info[KGameHighScoreDialog::Name] = (*it).name; 0508 info[KGameHighScoreDialog::Score].setNum((*it).score); 0509 info[KGameHighScoreDialog::Custom1] = QString::number(curPar); 0510 0511 scoreDialog->addScore(info, KGameHighScoreDialog::LessIsMore); 0512 } 0513 0514 scoreDialog->setComment(i18n("High Scores for %1", courseInfo.name)); 0515 scoreDialog->show(); 0516 } 0517 0518 QTimer::singleShot(700, this, &KolfWindow::closeGame); 0519 } 0520 0521 void KolfWindow::showHighScores() 0522 { 0523 KGameHighScoreDialog *scoreDialog = new KGameHighScoreDialog(KGameHighScoreDialog::Name | KGameHighScoreDialog::Custom1 | KGameHighScoreDialog::Score, this); 0524 scoreDialog->addField(KGameHighScoreDialog::Custom1, i18n("Par"), QStringLiteral("Par")); 0525 0526 CourseInfo courseInfo; 0527 game->courseInfo(courseInfo, game->curFilename()); 0528 0529 scoreDialog->setConfigGroup(qMakePair(QByteArray(courseInfo.untranslatedName.toUtf8() + " Highscores"), i18n("High Scores for %1", courseInfo.name))); 0530 scoreDialog->setComment(i18n("High Scores for %1", courseInfo.name)); 0531 scoreDialog->show(); 0532 } 0533 0534 void KolfWindow::save() 0535 { 0536 if (filename.isNull()) 0537 { 0538 saveAs(); 0539 return; 0540 } 0541 0542 if (game) { 0543 game->save(); 0544 game->setFocus(); 0545 } 0546 } 0547 0548 void KolfWindow::saveAs() 0549 { 0550 QPointer<QFileDialog> fileSaveDialog = new QFileDialog(this); 0551 fileSaveDialog->setWindowTitle(i18nc("@title:window", "Pick Kolf Course to Save To")); 0552 fileSaveDialog->setMimeTypeFilters(QStringList(QStringLiteral("application/x-kourse"))); 0553 fileSaveDialog->setAcceptMode(QFileDialog::AcceptSave); 0554 if (fileSaveDialog->exec() == QDialog::Accepted) { 0555 QUrl newfile = fileSaveDialog->selectedUrls().first(); 0556 if (!newfile.isEmpty()) { 0557 filename = newfile.toLocalFile(); 0558 game->setFilename(filename); 0559 game->save(); 0560 game->setFocus(); 0561 } 0562 } 0563 delete fileSaveDialog; 0564 } 0565 0566 void KolfWindow::saveGameAs() 0567 { 0568 QPointer<QFileDialog> fileSaveDialog = new QFileDialog(this); 0569 fileSaveDialog->setWindowTitle(i18nc("@title:window", "Pick Saved Game to Save To")); 0570 fileSaveDialog->setMimeTypeFilters(QStringList(QStringLiteral("application/x-kolf"))); 0571 fileSaveDialog->setAcceptMode(QFileDialog::AcceptSave); 0572 if (fileSaveDialog->exec() == QDialog::Accepted) { 0573 QUrl newfile = fileSaveDialog->selectedUrls().first(); 0574 if (newfile.isEmpty()) { 0575 return; 0576 } 0577 else { 0578 loadedGame = newfile.toLocalFile(); 0579 saveGame(); 0580 } 0581 } 0582 delete fileSaveDialog; 0583 } 0584 0585 void KolfWindow::saveGame() 0586 { 0587 if (loadedGame.isNull()) 0588 { 0589 saveGameAs(); 0590 return; 0591 } 0592 0593 KConfig config(loadedGame); 0594 KConfigGroup configGroup(config.group(QStringLiteral("0 Saved Game"))); 0595 0596 configGroup.writeEntry("Competition", competition); 0597 configGroup.writeEntry("Course", filename); 0598 0599 game->saveScores(&config); 0600 0601 configGroup.sync(); 0602 } 0603 0604 void KolfWindow::loadGame() 0605 { 0606 QPointer<QFileDialog> fileLoadDialog = new QFileDialog(this); 0607 fileLoadDialog->setWindowTitle(i18nc("@title:window", "Pick Kolf Saved Game")); 0608 fileLoadDialog->setMimeTypeFilters(QStringList(QStringLiteral("application/x-kolf"))); 0609 fileLoadDialog->setAcceptMode(QFileDialog::AcceptOpen); 0610 fileLoadDialog->setFileMode(QFileDialog::ExistingFile); 0611 if (fileLoadDialog->exec() == QDialog::Accepted) { 0612 loadedGame = fileLoadDialog->selectedUrls().first().toLocalFile(); 0613 if (loadedGame.isEmpty()) { 0614 return; 0615 } 0616 else { 0617 isTutorial = false; 0618 startNewGame(); 0619 } 0620 } 0621 delete fileLoadDialog; 0622 } 0623 0624 // called by main for command line files 0625 void KolfWindow::openUrl(const QUrl &url) 0626 { 0627 QTemporaryFile tempFile; 0628 tempFile.open(); 0629 KIO::FileCopyJob *job = KIO::file_copy(url, QUrl::fromLocalFile(tempFile.fileName()), -1, KIO::Overwrite); 0630 KJobWidgets::setWindow(job, this); 0631 job->exec(); 0632 if (!job->error()) 0633 { 0634 isTutorial = false; 0635 QMimeDatabase db; 0636 QString mimeType = db.mimeTypeForFile(tempFile.fileName()).name(); 0637 if (mimeType == QLatin1String("application/x-kourse")) 0638 filename = tempFile.fileName(); 0639 else if (mimeType == QLatin1String("application/x-kolf")) 0640 loadedGame = tempFile.fileName(); 0641 else 0642 { 0643 closeGame(); 0644 return; 0645 } 0646 0647 QTimer::singleShot(10, this, &KolfWindow::startNewGame); 0648 } 0649 else 0650 closeGame(); 0651 } 0652 0653 void KolfWindow::newPlayersTurn(Player *player) 0654 { 0655 tempStatusBarText = i18n("%1's turn", player->name()); 0656 0657 if (showInfoAction->isChecked()) 0658 statusBar()->showMessage(tempStatusBarText, 5 * 1000); 0659 else 0660 statusBar()->showMessage(tempStatusBarText); 0661 0662 scoreboard->setCurrentCell(player->id() - 1, game->currentHole() - 1); 0663 } 0664 0665 void KolfWindow::newStatusText(const QString &text) 0666 { 0667 if (text.isEmpty()) 0668 statusBar()->showMessage(tempStatusBarText); 0669 else 0670 statusBar()->showMessage(text); 0671 } 0672 0673 void KolfWindow::editingStarted() 0674 { 0675 delete editor; 0676 editor = new Editor(m_itemFactory, dummy); 0677 editor->setObjectName( QStringLiteral( "Editor" ) ); 0678 connect(editor, &Editor::addNewItem, game, &KolfGame::addNewObject); 0679 connect(editor, &Editor::changed, game, &KolfGame::setModified); 0680 connect(editor, &Editor::addNewItem, this, &KolfWindow::setHoleFocus); 0681 connect(game, &KolfGame::newSelectedItem, editor, &Editor::setItem); 0682 0683 scoreboard->hide(); 0684 0685 layout->addWidget(editor, 1, 0); 0686 editor->show(); 0687 0688 clearHoleAction->setEnabled(true); 0689 newHoleAction->setEnabled(true); 0690 setHoleOtherEnabled(false); 0691 0692 game->setFocus(); 0693 } 0694 0695 void KolfWindow::editingEnded() 0696 { 0697 delete editor; 0698 editor = nullptr; 0699 0700 if (scoreboard) 0701 scoreboard->show(); 0702 0703 clearHoleAction->setEnabled(false); 0704 newHoleAction->setEnabled(false); 0705 setHoleOtherEnabled(true); 0706 0707 if (game) 0708 game->setFocus(); 0709 } 0710 0711 void KolfWindow::inPlayStart() 0712 { 0713 setEditingEnabled(false); 0714 setHoleOtherEnabled(false); 0715 setHoleMovementEnabled(false); 0716 } 0717 0718 void KolfWindow::inPlayEnd() 0719 { 0720 setEditingEnabled(true); 0721 setHoleOtherEnabled(true); 0722 setHoleMovementEnabled(true); 0723 } 0724 0725 void KolfWindow::maxStrokesReached(const QString &name) 0726 { 0727 KMessageBox::information(this, i18n("%1's score has reached the maximum for this hole.", name)); 0728 } 0729 0730 void KolfWindow::updateHoleMenu(int largest) 0731 { 0732 QStringList items; 0733 for (int i = 1; i <= largest; ++i) 0734 items.append(QString::number(i)); 0735 0736 // setItems for some reason enables the action 0737 bool shouldbe = holeAction->isEnabled(); 0738 holeAction->setItems(items); 0739 holeAction->setEnabled(shouldbe); 0740 } 0741 0742 void KolfWindow::setHoleMovementEnabled(bool yes) 0743 { 0744 if (competition) 0745 yes = false; 0746 0747 holeAction->setEnabled(yes); 0748 0749 nextAction->setEnabled(yes); 0750 prevAction->setEnabled(yes); 0751 firstAction->setEnabled(yes); 0752 lastAction->setEnabled(yes); 0753 randAction->setEnabled(yes); 0754 } 0755 0756 void KolfWindow::setHoleOtherEnabled(bool yes) 0757 { 0758 if (competition) 0759 yes = false; 0760 0761 resetHoleAction->setEnabled(yes); 0762 undoShotAction->setEnabled(yes); 0763 //replayShotAction->setEnabled(yes); 0764 } 0765 0766 void KolfWindow::setEditingEnabled(bool yes) 0767 { 0768 editingAction->setEnabled(competition? false : yes); 0769 } 0770 0771 void KolfWindow::checkEditing() 0772 { 0773 editingAction->setChecked(true); 0774 } 0775 0776 void KolfWindow::updateModified(bool mod) 0777 { 0778 courseModified = mod; 0779 titleChanged(title); 0780 } 0781 0782 void KolfWindow::titleChanged(const QString &newTitle) 0783 { 0784 title = newTitle; 0785 setCaption(title, courseModified); 0786 } 0787 0788 void KolfWindow::useMouseChanged(bool yes) 0789 { 0790 KConfigGroup configGroup(KSharedConfig::openConfig(), QStringLiteral("Settings")); configGroup.writeEntry("useMouse", yes); configGroup.sync(); 0791 } 0792 0793 void KolfWindow::useAdvancedPuttingChanged(bool yes) 0794 { 0795 KConfigGroup configGroup(KSharedConfig::openConfig(), QStringLiteral("Settings")); configGroup.writeEntry("useAdvancedPutting", yes); configGroup.sync(); 0796 } 0797 0798 void KolfWindow::showInfoChanged(bool yes) 0799 { 0800 KConfigGroup configGroup(KSharedConfig::openConfig(), QStringLiteral("Settings")); configGroup.writeEntry("showInfo", yes); configGroup.sync(); 0801 } 0802 0803 void KolfWindow::showGuideLineChanged(bool yes) 0804 { 0805 KConfigGroup configGroup(KSharedConfig::openConfig(), QStringLiteral("Settings")); configGroup.writeEntry("showGuideLine", yes); configGroup.sync(); 0806 } 0807 0808 void KolfWindow::soundChanged(bool yes) 0809 { 0810 KConfigGroup configGroup(KSharedConfig::openConfig(), QStringLiteral("Settings")); configGroup.writeEntry("sound", yes); configGroup.sync(); 0811 } 0812 0813 void KolfWindow::enableAllMessages() 0814 { 0815 KMessageBox::enableAllMessages(); 0816 } 0817 0818 void KolfWindow::setCurrentHole(int hole) 0819 { 0820 if (!holeAction || holeAction->items().count() < hole) 0821 return; 0822 // Golf is 1-based, KListAction is 0-based 0823 holeAction->setCurrentItem(hole - 1); 0824 } 0825 0826 #include "moc_kolf.cpp"