File indexing completed on 2024-04-14 03:59:29

0001 /*
0002     SPDX-FileCopyrightText: 2008-2010 Stefan Majewsky <majewsky@gmx.net>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "mainwindow.h"
0008 #include "game.h"
0009 #include "infobar.h"
0010 #include "settings.h"
0011 #include "view.h"
0012 // KDEGames
0013 #include <KGameDifficulty>
0014 #include <KGameGraphicsViewRenderer>
0015 #include <KGameHighScoreDialog>
0016 #include <KGameStandardAction>
0017 // KF
0018 #include <KActionCollection>
0019 #include <KActionMenu>
0020 #include <KLocalizedString>
0021 #include <KNotifyConfigWidget>
0022 #include <KStandardAction>
0023 // Qt
0024 #include <QAction>
0025 #include <QPointer>
0026 
0027 namespace KDiamond
0028 {
0029 class ThemeProvider : public KGameThemeProvider
0030 {
0031 public:
0032     explicit ThemeProvider(QObject *parent = nullptr)
0033         : KGameThemeProvider("Theme", parent)
0034     {
0035         discoverThemes(QStringLiteral("themes"));
0036     }
0037 };
0038 
0039 class Renderer : public KGameGraphicsViewRenderer
0040 {
0041 public:
0042     Renderer() : KGameGraphicsViewRenderer(new ThemeProvider, 10)
0043     {
0044         setFrameSuffix(QStringLiteral("-%1"));
0045     }
0046 };
0047 }
0048 
0049 MainWindow::MainWindow(QWidget *parent)
0050     : KXmlGuiWindow(parent)
0051     , m_gameState(new KDiamond::GameState)
0052     , m_game(nullptr)
0053     , m_view(new KDiamond::View)
0054     , m_infoBar(nullptr)
0055     , m_newAct(new KActionMenu(QIcon::fromTheme(QStringLiteral("document-new")), i18nc("new game", "&New"), this))
0056     , m_newTimedAct(new QAction(i18n("Timed game"), this))
0057     , m_newUntimedAct(new QAction(i18n("Untimed game"), this))
0058     , m_renderer(new KDiamond::Renderer())
0059     , m_selector(m_renderer->themeProvider(), KGameThemeSelector::EnableNewStuffDownload)
0060 {
0061     m_renderer->setDefaultPrimaryView(m_view);
0062     //init GUI - "New Action"
0063     m_newAct->setToolTip(i18n("Start a new game"));
0064     m_newAct->setWhatsThis(i18n("Start a new game."));
0065     actionCollection()->addAction(QStringLiteral("game_new"), m_newAct);
0066     KActionCollection::setDefaultShortcuts(m_newAct, KStandardShortcut::openNew());
0067     connect(m_newAct, &KActionMenu::triggered, this, &MainWindow::startGameDispatcher);
0068     m_newAct->addAction(m_newTimedAct);
0069     connect(m_newTimedAct, &QAction::triggered, this, &MainWindow::startGameDispatcher);
0070     m_newAct->addAction(m_newUntimedAct);
0071     connect(m_newUntimedAct, &QAction::triggered, this, &MainWindow::startGameDispatcher);
0072     //init GUI - the other actions
0073     KGameStandardAction::highscores(this, &MainWindow::showHighscores, actionCollection());
0074     m_pauseAct = KGameStandardAction::pause(this, &MainWindow::pausedAction, actionCollection());
0075     KGameStandardAction::quit(this, &QWidget::close, actionCollection());
0076     m_hintAct = KGameStandardAction::hint(nullptr, nullptr, actionCollection());
0077     KStandardAction::preferences(this, &MainWindow::showPreferences, actionCollection());
0078     KStandardAction::configureNotifications(this, &MainWindow::configureNotifications, actionCollection());
0079     //difficulty
0080     KGameDifficultyGUI::init(this);
0081     connect(KGameDifficulty::global(), &KGameDifficulty::currentLevelChanged, this, &MainWindow::startGameDispatcher);
0082     //late GUI initialisation
0083     setupGUI(QSize(300, 400)); //TODO: find better solution for a minimum size
0084     setCaption(i18nc("The application's name", "KDiamond"));
0085     setCentralWidget(m_view);
0086     //init statusbar
0087     m_infoBar = new KDiamond::InfoBar(statusBar());
0088     connect(m_gameState, &KDiamond::GameState::stateChanged, this, &MainWindow::stateChange);
0089     connect(m_gameState, &KDiamond::GameState::pointsChanged, m_infoBar, &KDiamond::InfoBar::updatePoints);
0090     connect(m_gameState, &KDiamond::GameState::leftTimeChanged, m_infoBar, &KDiamond::InfoBar::updateRemainingTime);
0091     //init game
0092     startGameDispatcher();
0093 }
0094 
0095 MainWindow::~MainWindow()
0096 {
0097     Settings::self()->save();
0098     delete m_renderer;
0099     delete m_game;
0100     delete m_gameState;
0101 }
0102 
0103 void MainWindow::startGameDispatcher()
0104 {
0105     if (sender() == m_newUntimedAct) {
0106         startGame(KDiamond::UntimedGame);
0107     } else if (sender() == m_newTimedAct) {
0108         startGame(KDiamond::NormalGame);
0109     } else
0110         //attention: this may also be used by KGameDifficulty and the ctor
0111     {
0112         startGame(Settings::untimed() ? KDiamond::UntimedGame : KDiamond::NormalGame);
0113     }
0114 }
0115 
0116 void MainWindow::startGame(KDiamond::Mode mode)
0117 {
0118     //delete old board
0119     delete m_game;
0120     //start new game
0121     m_gameState->startNewGame();
0122     m_gameState->setMode(mode);
0123     m_game = new Game(m_gameState, m_renderer);
0124     connect(m_gameState, &KDiamond::GameState::stateChanged, m_game, &Game::stateChange);
0125     connect(m_gameState, &KDiamond::GameState::message, m_game, &Game::message);
0126     connect(m_game, &Game::numberMoves, m_infoBar, &KDiamond::InfoBar::updateMoves);
0127     connect(m_game, &Game::pendingAnimationsFinished, this, &MainWindow::gameIsOver);
0128     connect(m_hintAct, &QAction::triggered, m_game, &Game::showHint);
0129     m_view->setScene(m_game);
0130     //reset status bar
0131     m_infoBar->setUntimed(mode == KDiamond::UntimedGame);
0132     m_infoBar->updatePoints(0);
0133     m_infoBar->updateRemainingTime(KDiamond::GameDuration);
0134 }
0135 
0136 void MainWindow::stateChange(KDiamond::State state)
0137 {
0138     m_pauseAct->setEnabled(state != KDiamond::Finished);
0139     m_pauseAct->setChecked(state == KDiamond::Paused);
0140     m_hintAct->setEnabled(state == KDiamond::Playing);
0141 }
0142 
0143 void MainWindow::gameIsOver()
0144 {
0145     //create score info
0146     KGameHighScoreDialog::FieldInfo scoreInfo;
0147     scoreInfo[KGameHighScoreDialog::Score].setNum(m_gameState->points());
0148     scoreInfo[KGameHighScoreDialog::Custom1] = m_gameState->mode() == KDiamond::UntimedGame ? i18n("Untimed") : i18n("Timed");
0149     //report score
0150     QPointer<KGameHighScoreDialog> dialog = new KGameHighScoreDialog(KGameHighScoreDialog::Name | KGameHighScoreDialog::Score, this);
0151     dialog->addField(KGameHighScoreDialog::Custom1, i18n("Mode"), QStringLiteral("mode"));
0152     dialog->initFromDifficulty(KGameDifficulty::global());
0153     dialog->addScore(scoreInfo);
0154     dialog->exec();
0155     delete dialog;
0156 }
0157 
0158 void MainWindow::showHighscores()
0159 {
0160     //pause game if necessary
0161     m_gameState->setState(KDiamond::Paused);
0162     if (m_gameState->state() != KDiamond::Finished) {
0163         actionCollection()->action(QStringLiteral("game_pause"))->setChecked(true);
0164     }
0165     //show dialog
0166     QPointer<KGameHighScoreDialog> dialog = new KGameHighScoreDialog(KGameHighScoreDialog::Name | KGameHighScoreDialog::Score, this);
0167     dialog->addField(KGameHighScoreDialog::Custom1, i18n("Mode"), QStringLiteral("mode"));
0168     dialog->initFromDifficulty(KGameDifficulty::global());
0169     dialog->exec();
0170     delete dialog;
0171 }
0172 
0173 void MainWindow::showPreferences()
0174 {
0175     m_selector.showAsDialog();
0176 }
0177 
0178 
0179 void MainWindow::pausedAction(bool paused)
0180 {
0181     m_gameState->setState(paused ? KDiamond::Paused : KDiamond::Playing);
0182 }
0183 
0184 void MainWindow::configureNotifications()
0185 {
0186     KNotifyConfigWidget::configure(this);
0187 }
0188 
0189 #include "moc_mainwindow.cpp"