File indexing completed on 2024-04-28 04:02:29
0001 /* 0002 SPDX-FileCopyrightText: 2007 Dmitry Suzdalev <dimsuz@gmail.com> 0003 SPDX-FileCopyrightText: 2010 Brian Croom <brian.s.croom@gmail.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "mainwindow.h" 0009 0010 // own 0011 #include "minefielditem.h" 0012 #include "scene.h" 0013 #include "settings.h" 0014 #include "kmines_debug.h" 0015 #include "ui_customgame.h" 0016 #include "ui_generalopts.h" 0017 // KDEGames 0018 #include <KGameClock> 0019 #include <KGameDifficulty> 0020 #include <KGameHighScoreDialog> 0021 #include <KGameStandardAction> 0022 #include <KGameThemeSelector> 0023 // KF 0024 #include <KActionCollection> 0025 #include <KConfigDialog> 0026 #include <KLocalizedString> 0027 #include <KMessageBox> 0028 // Qt 0029 #include <QStatusBar> 0030 #include <QScreen> 0031 /* 0032 * Classes for config dlg pages 0033 */ 0034 class CustomGameConfig : public QWidget 0035 { 0036 Q_OBJECT 0037 0038 public: 0039 CustomGameConfig(QWidget *parent) 0040 : QWidget(parent) 0041 { 0042 ui.setupUi(this); 0043 connect(ui.kcfg_CustomWidth, &QSpinBox::valueChanged, 0044 this, &CustomGameConfig::updateMaxMines); 0045 connect(ui.kcfg_CustomHeight, &QSpinBox::valueChanged, 0046 this, &CustomGameConfig::updateMaxMines); 0047 } 0048 0049 private Q_SLOTS: 0050 void updateMaxMines() 0051 { 0052 int width = ui.kcfg_CustomWidth->value(); 0053 int height = ui.kcfg_CustomHeight->value(); 0054 int max = qMax(1, width * height - MineFieldItem::MINIMAL_FREE); 0055 ui.kcfg_CustomMines->setMaximum(max); 0056 } 0057 0058 private: 0059 Ui::CustomGameConfig ui; 0060 }; 0061 0062 class GeneralOptsConfig : public QWidget 0063 { 0064 public: 0065 GeneralOptsConfig(QWidget *parent) 0066 : QWidget(parent) 0067 { 0068 ui.setupUi(this); 0069 } 0070 0071 private: 0072 Ui::GeneralOptsConfig ui; 0073 }; 0074 0075 /* 0076 * Main window 0077 */ 0078 0079 KMinesMainWindow::KMinesMainWindow() 0080 { 0081 m_scene = new KMinesScene(this); 0082 0083 connect(m_scene, &KMinesScene::minesCountChanged, this, &KMinesMainWindow::onMinesCountChanged); 0084 connect(m_scene, &KMinesScene::gameOver, this, &KMinesMainWindow::onGameOver); 0085 connect(m_scene, &KMinesScene::firstClickDone, this, &KMinesMainWindow::onFirstClick); 0086 0087 m_view = new KMinesView( m_scene, this ); 0088 m_view->setCacheMode( QGraphicsView::CacheBackground ); 0089 m_view->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); 0090 m_view->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); 0091 m_view->setFrameStyle(QFrame::NoFrame); 0092 0093 m_view->setOptimizationFlags( 0094 QGraphicsView::DontSavePainterState | 0095 QGraphicsView::DontAdjustForAntialiasing ); 0096 0097 0098 m_gameClock = new KGameClock(this, KGameClock::FlexibleHourMinSec); 0099 connect(m_gameClock, &KGameClock::timeChanged, this, &KMinesMainWindow::advanceTime); 0100 0101 mineLabel->setText(i18n("Mines: 0/0")); 0102 timeLabel->setText(i18n("Time: 00:00")); 0103 0104 statusBar()->insertPermanentWidget( 0, mineLabel ); 0105 statusBar()->insertPermanentWidget( 1, timeLabel ); 0106 setCentralWidget(m_view); 0107 setupActions(); 0108 0109 newGame(); 0110 } 0111 0112 void KMinesMainWindow::setupActions() 0113 { 0114 KGameStandardAction::gameNew(this, &KMinesMainWindow::newGame, actionCollection()); 0115 KGameStandardAction::highscores(this, &KMinesMainWindow::showHighscores, actionCollection()); 0116 0117 KGameStandardAction::quit(this, &KMinesMainWindow::close, actionCollection()); 0118 KStandardAction::preferences(this, &KMinesMainWindow::configureSettings, actionCollection()); 0119 m_actionPause = KGameStandardAction::pause(this, &KMinesMainWindow::pauseGame, actionCollection()); 0120 0121 KGameDifficulty::global()->addStandardLevelRange( 0122 KGameDifficultyLevel::Easy, KGameDifficultyLevel::Hard 0123 ); 0124 KGameDifficulty::global()->addLevel(new KGameDifficultyLevel(1000, 0125 QByteArray( "Custom" ), i18n( "Custom" ) 0126 )); 0127 KGameDifficultyGUI::init(this); 0128 connect(KGameDifficulty::global(), &KGameDifficulty::currentLevelChanged, this, &KMinesMainWindow::newGame); 0129 0130 setupGUI(screen()->availableGeometry().size() * 0.4); 0131 } 0132 0133 void KMinesMainWindow::onMinesCountChanged(int count) 0134 { 0135 mineLabel->setText(i18n("Mines: %1/%2", count, m_scene->totalMines())); 0136 } 0137 0138 void KMinesMainWindow::newGame() 0139 { 0140 qCDebug(KMINES_LOG) << "Inside game"; 0141 m_gameClock->restart(); 0142 m_gameClock->pause(); // start only with the 1st click 0143 0144 // some things to manage pause 0145 if( m_actionPause->isChecked() ) 0146 { 0147 m_scene->setGamePaused(false); 0148 m_actionPause->setChecked(false); 0149 } 0150 m_actionPause->setEnabled(false); 0151 0152 KGameDifficulty::global()->setGameRunning(false); 0153 switch(KGameDifficulty::globalLevel()) 0154 { 0155 case KGameDifficultyLevel::Easy: 0156 m_scene->startNewGame(9, 9, 10); 0157 break; 0158 case KGameDifficultyLevel::Medium: 0159 m_scene->startNewGame(16,16,40); 0160 break; 0161 case KGameDifficultyLevel::Hard: 0162 m_scene->startNewGame(16,30,99); 0163 break; 0164 case KGameDifficultyLevel::Custom: 0165 m_scene->startNewGame(Settings::customHeight(), 0166 Settings::customWidth(), 0167 Settings::customMines()); 0168 default: 0169 //unsupported 0170 break; 0171 } 0172 0173 timeLabel->setText(i18n("Time: 00:00")); 0174 } 0175 0176 void KMinesMainWindow::onGameOver(bool won) 0177 { 0178 m_gameClock->pause(); 0179 m_actionPause->setEnabled(false); 0180 KGameDifficulty::global()->setGameRunning(false); 0181 if(won && m_scene->canScore()) 0182 { 0183 QPointer<KGameHighScoreDialog> scoreDialog = new KGameHighScoreDialog(KGameHighScoreDialog::Name | KGameHighScoreDialog::Time, this); 0184 scoreDialog->initFromDifficulty(KGameDifficulty::global()); 0185 scoreDialog->hideField(KGameHighScoreDialog::Score); 0186 0187 KGameHighScoreDialog::FieldInfo scoreInfo; 0188 // score-in-seconds will be hidden 0189 scoreInfo[KGameHighScoreDialog::Score].setNum(m_gameClock->seconds()); 0190 //score-as-time will be shown 0191 scoreInfo[KGameHighScoreDialog::Time] = m_gameClock->timeString(); 0192 0193 // we keep highscores as number of seconds 0194 if( scoreDialog->addScore(scoreInfo, KGameHighScoreDialog::LessIsMore) != 0 ) 0195 scoreDialog->exec(); 0196 0197 delete scoreDialog; 0198 } else if (!won) 0199 { 0200 //ask to reset 0201 if (Settings::allowKminesReset() && 0202 KMessageBox::questionTwoActions(this, 0203 i18n("Reset the Game?"), 0204 QString(), 0205 KGuiItem(i18nc("@action;button", "Reset"), QStringLiteral("view-refresh")), 0206 KStandardGuiItem::cancel()) == KMessageBox::PrimaryAction) { 0207 m_scene->reset(); 0208 m_gameClock->restart(); 0209 m_actionPause->setEnabled(true); 0210 m_scene->setCanScore(!Settings::disableScoreOnReset()); 0211 } 0212 } 0213 } 0214 0215 void KMinesMainWindow::advanceTime(const QString& timeStr) 0216 { 0217 timeLabel->setText(i18n("Time: %1", timeStr)); 0218 } 0219 0220 void KMinesMainWindow::onFirstClick() 0221 { 0222 // enable pause action 0223 m_actionPause->setEnabled(true); 0224 // start clock 0225 m_gameClock->resume(); 0226 KGameDifficulty::global()->setGameRunning(true); 0227 } 0228 0229 void KMinesMainWindow::showHighscores() 0230 { 0231 QPointer<KGameHighScoreDialog> scoreDialog = new KGameHighScoreDialog(KGameHighScoreDialog::Name | KGameHighScoreDialog::Time, this); 0232 scoreDialog->initFromDifficulty(KGameDifficulty::global()); 0233 scoreDialog->hideField(KGameHighScoreDialog::Score); 0234 scoreDialog->exec(); 0235 delete scoreDialog; 0236 } 0237 0238 void KMinesMainWindow::configureSettings() 0239 { 0240 if ( KConfigDialog::showDialog( QStringLiteral( "settings" ) ) ) 0241 return; 0242 auto *dialog = new KConfigDialog( this, QStringLiteral( "settings" ), Settings::self() ); 0243 dialog->addPage( new GeneralOptsConfig( dialog ), i18n("General"), QStringLiteral( "games-config-options" )); 0244 dialog->addPage( new KGameThemeSelector( m_scene->renderer().themeProvider() ), i18n( "Theme" ), QStringLiteral( "games-config-theme" )); 0245 dialog->addPage( new CustomGameConfig( dialog ), i18n("Custom Game"), QStringLiteral( "games-config-custom" )); 0246 connect( m_scene->renderer().themeProvider(), &KGameThemeProvider::currentThemeChanged, this, &KMinesMainWindow::loadSettings ); 0247 connect(dialog, &KConfigDialog::settingsChanged, this, &KMinesMainWindow::loadSettings); 0248 0249 dialog->show(); 0250 } 0251 0252 void KMinesMainWindow::pauseGame(bool paused) 0253 { 0254 m_scene->setGamePaused( paused ); 0255 if( paused ) 0256 m_gameClock->pause(); 0257 else 0258 m_gameClock->resume(); 0259 } 0260 0261 void KMinesMainWindow::loadSettings() 0262 { 0263 m_view->resetCachedContent(); 0264 // trigger complete redraw 0265 m_scene->resizeScene( (int)m_scene->sceneRect().width(), 0266 (int)m_scene->sceneRect().height() ); 0267 } 0268 0269 #include "mainwindow.moc" 0270 #include "moc_mainwindow.cpp"