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