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"