File indexing completed on 2024-09-29 06:37:38
0001 /* 0002 SPDX-FileCopyrightText: 2007-2008 Thomas Gallinari <tg8187@yahoo.fr> 0003 SPDX-FileCopyrightText: 2007-2008 Pierre-Benoit Bessse <besse@gmail.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "kapmanmainwindow.h" 0009 #include "gamescene.h" 0010 #include "settings.h" 0011 // KDEGames 0012 #include <KGameDifficulty> 0013 #include <KGameHighScoreDialog> 0014 #include <KGameStandardAction> 0015 #include <KGameThemeProvider> 0016 #include <KGameThemeSelector> 0017 // KF 0018 #include <KStandardGuiItem> 0019 #include <KActionCollection> 0020 #include <KLocalizedString> 0021 #include <KMessageBox> 0022 #include <KToggleAction> 0023 #include <KToggleFullScreenAction> 0024 // Qt 0025 #include <QAction> 0026 #include <QInputDialog> 0027 #include <QLabel> 0028 #include <QPointer> 0029 #include <QStatusBar> 0030 #include <QMenuBar> 0031 0032 KapmanMainWindow::KapmanMainWindow() 0033 { 0034 m_themeProvider = new KGameThemeProvider(QByteArray(), this); // empty config key to disable internal config 0035 m_themeProvider->discoverThemes( 0036 QStringLiteral("themes"), // theme data location 0037 QStringLiteral("default")); // default theme name 0038 0039 const QByteArray themeIdentifier = Settings::theme().toUtf8(); 0040 const QList<const KGameTheme *> themes = m_themeProvider->themes(); 0041 for (auto* theme : themes) { 0042 if (theme->identifier() == themeIdentifier) { 0043 m_themeProvider->setCurrentTheme(theme); 0044 break; 0045 } 0046 } 0047 connect(m_themeProvider, &KGameThemeProvider::currentThemeChanged, this, &KapmanMainWindow::onThemeChanged); 0048 0049 m_themeSelector = new KGameThemeSelector(m_themeProvider); 0050 0051 // Initialize the game 0052 m_game = nullptr; 0053 m_view = nullptr; 0054 // Set the window menus 0055 KGameStandardAction::gameNew(this, &KapmanMainWindow::newGame, actionCollection()); 0056 KGameStandardAction::highscores(this, &KapmanMainWindow::showHighscores, actionCollection()); 0057 KStandardAction::preferences(this, &KapmanMainWindow::showSettings, actionCollection()); 0058 0059 KStandardAction::fullScreen(this, &KapmanMainWindow::viewFullScreen, this, actionCollection()); 0060 0061 KGameStandardAction::quit(this, &KapmanMainWindow::close, actionCollection()); 0062 auto soundAction = new KToggleAction(i18n("&Play Sounds"), this); 0063 soundAction->setChecked(Settings::sounds()); 0064 actionCollection()->addAction(QStringLiteral("sounds"), soundAction); 0065 connect(soundAction, &KToggleAction::triggered, this, &KapmanMainWindow::setSoundsEnabled); 0066 auto levelAction = new QAction(i18n("&Change Level"), this); 0067 actionCollection()->addAction(QStringLiteral("level"), levelAction); 0068 connect(levelAction, &QAction::triggered, this, &KapmanMainWindow::changeLevel); 0069 // Add a statusbar to show level,score,lives information 0070 m_statusBar = statusBar(); 0071 mLevel = new QLabel(i18nc("Used to display the current level of play to the user", "Level: %1", 1)); 0072 m_statusBar->addPermanentWidget(mLevel); 0073 mScore = new QLabel(i18nc("Used to inform the user of their current score", "Score: %1", 0)); 0074 m_statusBar->addPermanentWidget(mScore); 0075 mLives = new QLabel(i18nc("Used to tell the user how many lives they have left", "Lives: %1", initLives)); 0076 m_statusBar->addPermanentWidget(mLives); 0077 0078 // Initialize the KGameDifficulty singleton 0079 KGameDifficulty::global()->addStandardLevelRange(KGameDifficultyLevel::Easy, 0080 KGameDifficultyLevel::Hard, // range 0081 KGameDifficultyLevel::Medium // default 0082 ); 0083 KGameDifficultyGUI::init(this); 0084 connect(KGameDifficulty::global(), &KGameDifficulty::currentLevelChanged, this, &KapmanMainWindow::initGame); 0085 // Set up the window 0086 setupGUI(); 0087 0088 menuBar()->setVisible(!isFullScreen()); 0089 statusBar()->setVisible(!isFullScreen()); 0090 0091 initGame(); 0092 } 0093 0094 KapmanMainWindow::~KapmanMainWindow() 0095 { 0096 delete m_themeSelector; 0097 delete m_statusBar; 0098 delete m_game; 0099 delete m_view; 0100 } 0101 0102 void KapmanMainWindow::initGame() 0103 { 0104 // Create a new Game instance 0105 delete m_game; 0106 m_game = new Game(); 0107 connect(m_game, &Game::gameOver, this, &KapmanMainWindow::handleGameOver); 0108 connect(m_game, &Game::levelChanged, this, &KapmanMainWindow::displayLevel); 0109 connect(m_game, &Game::scoreChanged, this, &KapmanMainWindow::displayScore); 0110 connect(m_game, &Game::livesChanged, this, &KapmanMainWindow::displayLives); 0111 0112 // Create a new GameView instance 0113 delete m_view; 0114 m_view = new GameView(m_game, m_themeProvider->currentTheme()); 0115 m_view->setBackgroundBrush(Qt::black); 0116 setCentralWidget(m_view); 0117 m_view->setFocus(); 0118 // For some reason, calling setFocus() immediately won't work after the 0119 // score dialog has been shown, so do it again after an eventloop run. 0120 QTimer::singleShot(0, m_view, qOverload<>(&QWidget::setFocus)); 0121 resetStatusBar(); 0122 } 0123 0124 void KapmanMainWindow::newGame() 0125 { 0126 bool gameRunning; // True if the game is running (game timer is active), false otherwise 0127 0128 gameRunning = m_game->getTimer()->isActive(); 0129 // If the game is running 0130 if (gameRunning) { 0131 // Pause the game 0132 m_game->pause(); 0133 } 0134 0135 // Confirm before starting a new game 0136 if (KMessageBox::warningTwoActions(this, 0137 i18n("Are you sure you want to quit the current game?"), 0138 i18nc("@title:window", "New Game"), 0139 KGuiItem(i18nc("@action;button", "Quit Game"), QStringLiteral("window-close")), 0140 KStandardGuiItem::cancel()) 0141 == KMessageBox::PrimaryAction) { 0142 // Start a new game 0143 initGame(); 0144 } else { 0145 // If the game was running 0146 if (gameRunning) { 0147 // Resume the game 0148 m_game->start(); 0149 } 0150 } 0151 } 0152 0153 void KapmanMainWindow::handleGameOver() 0154 { 0155 bool gameRunning; // True if the game is running (game timer is active), false otherwise 0156 0157 gameRunning = m_game->getTimer()->isActive(); 0158 // If the game is running 0159 if (gameRunning) { 0160 // Pause the game 0161 m_game->pause(); 0162 } 0163 // Display the score information 0164 KMessageBox::information(this, i18np("Your score is %1 point.", "Your score is %1 points.", m_game->getScore()), i18n("Game Over")); 0165 // manage Highscores only if player did not cheat 0166 if (m_game->isCheater()) { 0167 KMessageBox::information(this, i18n("You cheated, no Highscore for you ;)"), i18n("Cheater!")); 0168 } else { 0169 // Add the score to the highscores table 0170 QPointer<KGameHighScoreDialog> dialog = new KGameHighScoreDialog(KGameHighScoreDialog::Name | KGameHighScoreDialog::Score | KGameHighScoreDialog::Level, this); 0171 dialog->initFromDifficulty(KGameDifficulty::global()); 0172 KGameHighScoreDialog::FieldInfo scoreInfo; 0173 scoreInfo[KGameHighScoreDialog::Level].setNum(m_game->getLevel()); 0174 scoreInfo[KGameHighScoreDialog::Score].setNum(m_game->getScore()); 0175 // If the new score is a highscore then display the highscore dialog 0176 if (dialog->addScore(scoreInfo)) { 0177 dialog->exec(); 0178 } 0179 delete dialog; 0180 } 0181 // Start a new game 0182 initGame(); 0183 } 0184 0185 void KapmanMainWindow::changeLevel() 0186 { 0187 const int newLevel = QInputDialog::getInt(this, i18n("Change Level"), i18nc("The number of the game level", "Level"), m_game->getLevel(), 1, 1000000, 1); 0188 if (newLevel > 0) { 0189 m_game->setLevel(newLevel); 0190 } 0191 } 0192 0193 void KapmanMainWindow::showHighscores() 0194 { 0195 QPointer<KGameHighScoreDialog> dialog = new KGameHighScoreDialog(KGameHighScoreDialog::Name | KGameHighScoreDialog::Score | KGameHighScoreDialog::Level, this); 0196 dialog->initFromDifficulty(KGameDifficulty::global()); 0197 dialog->exec(); 0198 delete dialog; 0199 } 0200 0201 void KapmanMainWindow::setSoundsEnabled(bool p_enabled) 0202 { 0203 m_game->setSoundsEnabled(p_enabled); 0204 } 0205 0206 void KapmanMainWindow::showSettings() 0207 { 0208 m_themeSelector->showAsDialog(); 0209 } 0210 0211 void KapmanMainWindow::onThemeChanged(const KGameTheme *theme) 0212 { 0213 // sync to settings store 0214 Settings::setTheme(QString::fromUtf8(theme->identifier())); 0215 Settings::self()->save(); 0216 // trigger update of resources, then display 0217 ((GameScene *)m_view->scene())->loadTheme(theme); 0218 } 0219 0220 void KapmanMainWindow::close() 0221 { 0222 bool gameRunning; // True if the game is running (game timer is active), false otherwise 0223 0224 gameRunning = m_game->getTimer()->isActive(); 0225 // If the game is running 0226 if (gameRunning) { 0227 // Pause the game 0228 m_game->pause(); 0229 } 0230 // Confirm before closing 0231 if (KMessageBox::warningTwoActions(this, 0232 i18n("Are you sure you want to quit Kapman?"), 0233 i18nc("To quit Kapman", "Quit"), 0234 KStandardGuiItem::quit(), KStandardGuiItem::cancel()) 0235 == KMessageBox::PrimaryAction) { 0236 KXmlGuiWindow::close(); 0237 } else { 0238 // If the game was running 0239 if (gameRunning) { 0240 // Resume the game 0241 m_game->start(); 0242 } 0243 } 0244 } 0245 0246 void KapmanMainWindow::displayLevel(unsigned int p_level) 0247 { 0248 mLevel->setText(i18nc("Used to display the current level of play to the user", "Level: %1", p_level)); 0249 } 0250 0251 void KapmanMainWindow::displayScore(unsigned int p_score) 0252 { 0253 mScore->setText(i18nc("Used to inform the user of their current score", "Score: %1", p_score)); 0254 } 0255 0256 void KapmanMainWindow::displayLives(unsigned int p_lives) 0257 { 0258 mLives->setText(i18nc("Used to tell the user how many lives they have left", "Lives: %1", p_lives)); 0259 } 0260 0261 void KapmanMainWindow::resetStatusBar() 0262 { 0263 displayLevel(1); 0264 displayScore(0); 0265 displayLives(initLives); 0266 } 0267 0268 void KapmanMainWindow::viewFullScreen(bool fullScreen) 0269 { 0270 KToggleFullScreenAction::setFullScreen(this, fullScreen); 0271 0272 menuBar()->setVisible(!fullScreen); 0273 statusBar()->setVisible(!fullScreen); 0274 } 0275 0276 #include "moc_kapmanmainwindow.cpp"