File indexing completed on 2024-04-28 04:04:48

0001 /***************************************************************************
0002  *   Copyright 2007      Johannes Bergmeier <johannes.bergmeier@gmx.net>   *
0003  *   Copyright 2015      Ian Wadham <iandw.au@gmail.com>                   *
0004  *                                                                         *
0005  *   This program is free software; you can redistribute it and/or modify  *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
0019  ***************************************************************************/
0020 #include "welcomescreen.h"
0021 
0022 
0023 #include <KConfigGroup>
0024 #include <KMessageBox>
0025 #include <KSharedConfig>
0026 
0027 #include "ksudokugame.h"
0028 #include "globals.h"
0029 #include "puzzle.h"
0030 
0031 Q_DECLARE_METATYPE(ksudoku::GameVariant*)
0032 
0033 namespace ksudoku {
0034 
0035 WelcomeScreen::WelcomeScreen(QWidget* parent, GameVariantCollection* collection)
0036     : QFrame(parent), m_collection(collection)
0037 {
0038     setupUi(this);  // Get gameListWidget by loading from welcomescreen.ui.
0039 
0040     // Set the screen to display a multi-column list of puzzle-types, with
0041     // vertical scrolling.  GameVariantDelegate::sizeHint() calculates the
0042     // number of columns and their width when it works out the size of the
0043     // item's display-area.
0044 
0045     QItemDelegate* delegate =
0046         new GameVariantDelegate(this, gameListWidget->viewport());
0047     gameListWidget->setWrapping(true);
0048     gameListWidget->setResizeMode(QListView::Adjust);
0049     gameListWidget->setUniformItemSizes(true);
0050     gameListWidget->setFlow(QListView::LeftToRight);
0051 
0052     // Avoid a resize loop (with the scrollbar appearing and disappearing)
0053     // if ever the number of items and display-columns hits a bad combo.
0054     gameListWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
0055 
0056     gameListWidget->setModel(m_collection);
0057     gameListWidget->setItemDelegate(delegate);
0058     gameListWidget->setVerticalScrollMode(QListView::ScrollPerPixel);
0059     gameListWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
0060     gameListWidget->setSelectionMode(QAbstractItemView::SingleSelection);
0061 
0062     // Get the previous puzzle configuration.
0063     KConfigGroup gameGroup (KSharedConfig::openConfig(), QStringLiteral("KSudokuGame"));
0064     m_selectedPuzzle = gameGroup.readEntry("SelectedPuzzle", 0);
0065     m_difficulty     = gameGroup.readEntry("Difficulty", (int) VeryEasy);
0066     m_symmetry       = gameGroup.readEntry("Symmetry"  , (int) CENTRAL);
0067 
0068     // This has to be a deferred call (presumably to allow the view's setup
0069     // to complete), otherwise the selection fails to appear.
0070     QMetaObject::invokeMethod (this, "setSelectedVariant",
0071                            Qt::QueuedConnection,
0072                    Q_ARG (int, m_selectedPuzzle));
0073 
0074     connect(gameListWidget->selectionModel(), &QItemSelectionModel::currentChanged, this, &WelcomeScreen::onCurrentVariantChange);
0075     
0076     connect(getNewGameButton, &QPushButton::clicked, this, &WelcomeScreen::getNewVariant);
0077     // TODO disabled due to missing per-game config dialog
0078 //  connect(configureGameButton, SIGNAL(clicked(bool)), this, SLOT(configureVariant()));
0079     // connect(playGameButton, SIGNAL(clicked(bool)), this, SLOT(playVariant()));           // Disable old create-game code.
0080     // connect(gameListWidget, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(playVariant()));  // Disable old create-game code.
0081 
0082     connect(startEmptyButton, &QPushButton::clicked, this, &WelcomeScreen::startEmptyGame);
0083     connect(puzzleGeneratorButton, &QPushButton::clicked, this, &WelcomeScreen::generatePuzzle);
0084     connect(gameListWidget, &QListView::doubleClicked, this, &WelcomeScreen::generatePuzzle);
0085 
0086     // GHNS is not implemented yet, so don't show an unuseful button
0087     getNewGameButton->hide();
0088 }
0089 
0090 GameVariant* WelcomeScreen::selectedVariant() const {
0091     QModelIndex index = gameListWidget->currentIndex();
0092     return m_collection->variant(index);
0093 }
0094 
0095 void WelcomeScreen::setSelectedVariant(int row) {
0096     gameListWidget->setCurrentIndex(gameListWidget->model()->index(row,0));
0097 }
0098 
0099 int WelcomeScreen::difficulty() const {
0100     return m_difficulty;
0101 }
0102 
0103 void WelcomeScreen::setDifficulty(int difficulty) {
0104     m_difficulty = difficulty;
0105 }
0106 
0107 int WelcomeScreen::symmetry() const {
0108     return m_symmetry;
0109 }
0110 
0111 void WelcomeScreen::setSymmetry(int symmetry) {
0112     m_symmetry = symmetry;
0113 }
0114 
0115 void WelcomeScreen::onCurrentVariantChange() {
0116     GameVariant* variant = selectedVariant();
0117     if(!variant) {
0118         // TODO disabled due to missing per-game config dialog
0119 //      configureGameButton->setEnabled(false);
0120         // playGameButton->setEnabled(false);
0121         puzzleGeneratorButton->setEnabled(false);
0122         return;
0123     }
0124     
0125     // TODO disabled due to missing per-game config dialog
0126 //  configureGameButton->setEnabled(variant->canConfigure());
0127     startEmptyButton->setEnabled(variant->canStartEmpty());
0128     // playGameButton->setEnabled(true);
0129     puzzleGeneratorButton->setEnabled(true);
0130 }
0131 
0132 void WelcomeScreen::getNewVariant() {
0133     KMessageBox::information(this, i18n("GetNewVariant not implemented"), QLatin1String(""));
0134 }
0135 
0136 void WelcomeScreen::configureVariant() {
0137     GameVariant* variant = selectedVariant();
0138     if(!variant) return;
0139     
0140     variant->configure();
0141 }
0142 
0143 void WelcomeScreen::startEmptyGame() {
0144     GameVariant* variant = selectedVariant();
0145     if(!variant) {
0146         KMessageBox::error(this, i18n("Please select a puzzle variant."), i18n("Unable to start puzzle"));
0147         return;
0148     }
0149     
0150     Game game = variant->startEmpty();
0151     if (! game.isValid()) {
0152         KMessageBox::error(this, i18n("Unable to create an empty puzzle of the chosen variant; please try another."), i18n("Unable to start puzzle"));
0153         return;
0154     }
0155     
0156     Q_EMIT newGameStarted(game, variant);
0157 }
0158 
0159 void WelcomeScreen::playVariant() {
0160     return;     // Disable old game-creation code.
0161     GameVariant* variant = selectedVariant();
0162     if(!variant) {
0163         KMessageBox::error(this, i18n("Please select a puzzle variant."), i18n("Unable to start puzzle"));
0164         return;
0165     }
0166     
0167     Game game = variant->createGame(difficulty(), 0);
0168     if(!game.isValid()) {
0169         KMessageBox::error(this, i18n("Unable to start a puzzle of the chosen variant; please try another."), i18n("Unable to start puzzle"));
0170         return;
0171     }
0172 
0173     Q_EMIT newGameStarted(game, variant);
0174 }
0175 
0176 void WelcomeScreen::generatePuzzle() {
0177     GameVariant* variant = selectedVariant();
0178     if(!variant) {
0179         KMessageBox::error(this, i18n("Please select a puzzle variant."), i18n("Unable to start puzzle"));
0180         return;
0181     }
0182 
0183     Game game = variant->createGame(difficulty(), symmetry());
0184     if(!game.isValid()) {
0185         KMessageBox::error(this, i18n("Unable to generate a puzzle of the chosen variant; please try another."), i18n("Unable to start puzzle"));
0186         return;
0187     }
0188 
0189     // Save the selected puzzle configuration.
0190     QModelIndex index = gameListWidget->currentIndex();
0191     m_selectedPuzzle = index.row();
0192 
0193     KConfigGroup gameGroup (KSharedConfig::openConfig(), QStringLiteral("KSudokuGame"));
0194     gameGroup.writeEntry("SelectedPuzzle", m_selectedPuzzle);
0195     gameGroup.writeEntry("Difficulty", m_difficulty);
0196     gameGroup.writeEntry("Symmetry"  , m_symmetry);
0197     gameGroup.sync();       // Ensure that the entry goes to disk.
0198 
0199     // If the user abandoned puzzle-generation, stay on the Welcome Screen
0200     // and allow the user to change the Difficulty, etc. of the puzzle.
0201     if (game.puzzle()->hasSolution()) {
0202         Q_EMIT newGameStarted(game, variant);       // OK, start playing.
0203     }
0204 }
0205 
0206 }
0207 
0208 #include "moc_welcomescreen.cpp"