mainwindow.cpp 8.16 KB
Newer Older
1
/*
2
3
4
5
    SPDX-FileCopyrightText: 2007 Dmitry Suzdalev <dimsuz@gmail.com>
    SPDX-FileCopyrightText: 2010 Brian Croom <brian.s.croom@gmail.com>

    SPDX-License-Identifier: GPL-2.0-or-later
6
*/
7

8
#include "mainwindow.h"
9
10

// own
11
#include "minefielditem.h"
12
#include "scene.h"
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
13
#include "settings.h"
Laurent Montel's avatar
Laurent Montel committed
14
#include "kmines_debug.h"
15
16
17
#include "ui_customgame.h"
#include "ui_generalopts.h"
// KDEGames
Mauricio Piacentini's avatar
Mauricio Piacentini committed
18
#include <KGameClock>
19
#include <KgDifficulty>
20
#include <KStandardGameAction>
21
#include <KgThemeSelector>
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
22
#include <KScoreDialog>
23
24
// KF
#include <KActionCollection>
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
25
#include <KConfigDialog>
26
27
#include <KLocalizedString>
// Qt
28
#include <QScreen>
29
#include <QStatusBar>
30
#include <QDesktopWidget>
Laurent Montel's avatar
Laurent Montel committed
31
#include <QMessageBox>
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
32

33
34
35
/*
 * Classes for config dlg pages
 */
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
36
37
class CustomGameConfig : public QWidget
{
38
39
    Q_OBJECT

Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
40
41
42
public:
    CustomGameConfig(QWidget *parent)
        : QWidget(parent)
43
44
    {
        ui.setupUi(this);
45
46
47
48
        connect(ui.kcfg_CustomWidth, QOverload<int>::of(&QSpinBox::valueChanged),
                this, &CustomGameConfig::updateMaxMines);
        connect(ui.kcfg_CustomHeight, QOverload<int>::of(&QSpinBox::valueChanged),
                this, &CustomGameConfig::updateMaxMines);
49
50
    }

51
private Q_SLOTS:
52
53
54
55
56
57
58
59
    void updateMaxMines()
    {
        int width = ui.kcfg_CustomWidth->value();
        int height = ui.kcfg_CustomHeight->value();
        int max = qMax(1, width * height - MineFieldItem::MINIMAL_FREE);
        ui.kcfg_CustomMines->setMaximum(max);
    }

Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
60
61
62
63
private:
    Ui::CustomGameConfig ui;
};

64
65
66
67
68
69
70
71
class GeneralOptsConfig : public QWidget
{
public:
    GeneralOptsConfig(QWidget *parent)
        : QWidget(parent)
    {
        ui.setupUi(this);
    }
72

73
74
75
76
77
78
79
80
private:
    Ui::GeneralOptsConfig ui;
};

/*
 * Main window
 */

81
82
KMinesMainWindow::KMinesMainWindow()
{
83
    m_scene = new KMinesScene(this);
Anuj Pahuja's avatar
Anuj Pahuja committed
84
    
85
86
87
    connect(m_scene, &KMinesScene::minesCountChanged, this, &KMinesMainWindow::onMinesCountChanged);
    connect(m_scene, &KMinesScene::gameOver, this, &KMinesMainWindow::onGameOver);
    connect(m_scene, &KMinesScene::firstClickDone, this, &KMinesMainWindow::onFirstClick);
88

Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
89
90
91
92
93
    m_view = new KMinesView( m_scene, this );
    m_view->setCacheMode( QGraphicsView::CacheBackground );
    m_view->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
    m_view->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
    m_view->setFrameStyle(QFrame::NoFrame);
94

95
    m_view->setOptimizationFlags( 
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
96
97
                                QGraphicsView::DontSavePainterState |
                                QGraphicsView::DontAdjustForAntialiasing );
98

99
100

    m_gameClock = new KGameClock(this, KGameClock::MinSecOnly);
101
    connect(m_gameClock, &KGameClock::timeChanged, this, &KMinesMainWindow::advanceTime);
102

103
104
105
106
107
    mineLabel->setText(i18n("Mines: 0/0"));
    timeLabel->setText(i18n("Time: 00:00"));
    
    statusBar()->insertPermanentWidget( 0, mineLabel );
    statusBar()->insertPermanentWidget( 1, timeLabel );
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
108
    setCentralWidget(m_view);
109
    setupActions();
110
111

    newGame();
112
113
114
115
}

void KMinesMainWindow::setupActions()
{
116
117
    KStandardGameAction::gameNew(this, &KMinesMainWindow::newGame, actionCollection());
    KStandardGameAction::highscores(this, &KMinesMainWindow::showHighscores, actionCollection());
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
118

119
120
121
    KStandardGameAction::quit(this, &KMinesMainWindow::close, actionCollection());
    KStandardAction::preferences(this, &KMinesMainWindow::configureSettings, actionCollection());
    m_actionPause = KStandardGameAction::pause(this, &KMinesMainWindow::pauseGame, actionCollection());
122

123
124
125
126
127
128
129
    Kg::difficulty()->addStandardLevelRange(
        KgDifficultyLevel::Easy, KgDifficultyLevel::Hard
    );
    Kg::difficulty()->addLevel(new KgDifficultyLevel(1000,
        QByteArray( "Custom" ), i18n( "Custom" )
    ));
    KgDifficultyGUI::init(this);
130
    connect(Kg::difficulty(), &KgDifficulty::currentLevelChanged, this, &KMinesMainWindow::newGame);
131

132
    setupGUI(screen()->availableGeometry().size() * 0.4);
133
}
134
135
136

void KMinesMainWindow::onMinesCountChanged(int count)
{
137
    mineLabel->setText(i18n("Mines: %1/%2", count, m_scene->totalMines()));
138
}
139

140
141
void KMinesMainWindow::newGame()
{
Laurent Montel's avatar
Laurent Montel committed
142
    qCDebug(KMINES_LOG) << "Inside game";
143
144
    m_gameClock->restart();
    m_gameClock->pause(); // start only with the 1st click
Laurent Montel's avatar
Laurent Montel committed
145

146
147
148
149
150
151
152
    // some things to manage pause
    if( m_actionPause->isChecked() )
    {
            m_scene->setGamePaused(false);
            m_actionPause->setChecked(false);
    }
    m_actionPause->setEnabled(false);
Laurent Montel's avatar
Laurent Montel committed
153

154
155
    Kg::difficulty()->setGameRunning(false);
    switch(Kg::difficultyLevel())
156
    {
157
        case KgDifficultyLevel::Easy:
158
159
            m_scene->startNewGame(9, 9, 10);
            break;
160
        case KgDifficultyLevel::Medium:
161
162
            m_scene->startNewGame(16,16,40);
            break;
163
        case KgDifficultyLevel::Hard:
164
165
            m_scene->startNewGame(16,30,99);
            break;
166
        case KgDifficultyLevel::Custom:
167
168
169
            m_scene->startNewGame(Settings::customHeight(),
                                  Settings::customWidth(),
                                  Settings::customMines());
170
171
172
173
        default:
            //unsupported
            break;
    }
174
175
    
    timeLabel->setText(i18n("Time: 00:00"));
176
177
}

Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
178
void KMinesMainWindow::onGameOver(bool won)
179
180
{
    m_gameClock->pause();
181
    m_actionPause->setEnabled(false);
182
    Kg::difficulty()->setGameRunning(false);
183
    if(won && m_scene->canScore())
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
184
    {
185
186
187
        QPointer<KScoreDialog> scoreDialog = new KScoreDialog(KScoreDialog::Name | KScoreDialog::Time, this);
        scoreDialog->initFromDifficulty(Kg::difficulty());
        scoreDialog->hideField(KScoreDialog::Score);
Laurent Montel's avatar
Laurent Montel committed
188

Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
189
190
191
192
        KScoreDialog::FieldInfo scoreInfo;
        // score-in-seconds will be hidden
        scoreInfo[KScoreDialog::Score].setNum(m_gameClock->seconds());
        //score-as-time will be shown
193
        scoreInfo[KScoreDialog::Time] = m_gameClock->timeString();
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
194
195

        // we keep highscores as number of seconds
196
197
198
199
        if( scoreDialog->addScore(scoreInfo, KScoreDialog::LessIsMore) != 0 )
            scoreDialog->exec();

        delete scoreDialog;
Laurent Montel's avatar
Laurent Montel committed
200
201
202
203
204
205
206
    } else if (!won)
    {
        //ask to reset
        if (Settings::allowKminesReset() && QMessageBox::question(this, i18n("Reset?"), i18n("Reset the Game?")) == QMessageBox::Yes){
            m_scene->reset();
            m_gameClock->restart();
            m_actionPause->setEnabled(true);
207
            m_scene->setCanScore(!Settings::disableScoreOnReset());
Laurent Montel's avatar
Laurent Montel committed
208
        }
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
209
    }
210
211
212
213
}

void KMinesMainWindow::advanceTime(const QString& timeStr)
{
214
    timeLabel->setText(i18n("Time: %1", timeStr));
215
216
217
218
}

void KMinesMainWindow::onFirstClick()
{
219
220
221
    // enable pause action
    m_actionPause->setEnabled(true);
    // start clock
222
    m_gameClock->resume();
223
    Kg::difficulty()->setGameRunning(true);
224
}
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
225
226
227

void KMinesMainWindow::showHighscores()
{
228
229
230
231
232
    QPointer<KScoreDialog> scoreDialog = new KScoreDialog(KScoreDialog::Name | KScoreDialog::Time, this);
    scoreDialog->initFromDifficulty(Kg::difficulty());
    scoreDialog->hideField(KScoreDialog::Score);
    scoreDialog->exec();
    delete scoreDialog;
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
233
}
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
234
235
236

void KMinesMainWindow::configureSettings()
{
237
    if ( KConfigDialog::showDialog( QStringLiteral(  "settings" ) ) )
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
238
        return;
239
240
241
242
243
    KConfigDialog *dialog = new KConfigDialog( this, QStringLiteral( "settings" ), Settings::self() );
    dialog->addPage( new GeneralOptsConfig( dialog ), i18n("General"), QStringLiteral( "games-config-options" ));
    dialog->addPage( new KgThemeSelector( m_scene->renderer().themeProvider() ), i18n( "Theme" ), QStringLiteral( "games-config-theme" ));
    dialog->addPage( new CustomGameConfig( dialog ), i18n("Custom Game"), QStringLiteral( "games-config-custom" ));
    connect( m_scene->renderer().themeProvider(), &KgThemeProvider::currentThemeChanged, this, &KMinesMainWindow::loadSettings );
244
    connect(dialog, &KConfigDialog::settingsChanged, this, &KMinesMainWindow::loadSettings);
Anuj Pahuja's avatar
Anuj Pahuja committed
245
    
Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
246
247
248
    dialog->show();
}

249
250
251
252
253
254
255
256
257
void KMinesMainWindow::pauseGame(bool paused)
{
    m_scene->setGamePaused( paused );
    if( paused )
        m_gameClock->pause();
    else
        m_gameClock->resume();
}

Dmitry Suzdalev's avatar
Dmitry Suzdalev committed
258
259
260
261
262
263
264
void KMinesMainWindow::loadSettings()
{
    m_view->resetCachedContent();
    // trigger complete redraw
    m_scene->resizeScene( (int)m_scene->sceneRect().width(),
                          (int)m_scene->sceneRect().height() );
}
Laurent Montel's avatar
Laurent Montel committed
265
266

#include "mainwindow.moc"
267
#include "moc_mainwindow.cpp"