File indexing completed on 2024-04-21 04:02:01

0001 /*
0002     SPDX-FileCopyrightText: 1998 Andreas Wüst <AndreasWuest@gmx.de>
0003     SPDX-FileCopyrightText: 2006 Dmitry Suzdalev <dimsuz@gmail.com>
0004     SPDX-FileCopyrightText: 2007 Simon Hürlimann <simon.huerlimann@huerlisi.ch>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #include "toplevel.h"
0010 
0011 #include "gamewidget.h"
0012 #include "playfield.h"
0013 #include "prefs.h"
0014 #include "commondefs.h"
0015 #include "chooselevelsetdialog.h"
0016 #include "katomic_debug.h"
0017 
0018 #include <KGameStandardAction>
0019 
0020 #include <KLocalizedString>
0021 #include <KSelectAction>
0022 #include <KActionCollection>
0023 
0024 #include <QIcon>
0025 #include <QStatusBar>
0026 #include <QLabel>
0027 
0028 
0029 AtomTopLevel::AtomTopLevel()
0030 {
0031     QString lastPlayedLevelSet = Preferences::lastPlayedLevelSet();
0032     if (lastPlayedLevelSet.isEmpty())
0033         lastPlayedLevelSet = QStringLiteral(DEFAULT_LEVELSET_NAME);
0034 
0035     m_gameWid = new GameWidget( lastPlayedLevelSet, this);
0036     m_gameWid->setObjectName( QStringLiteral("gamewidget" ));
0037     createMenu();
0038     loadSettings();
0039     setCentralWidget(m_gameWid);
0040 
0041     mLevel = new QLabel(i18n("Level:"));
0042     mCurrentScore = new QLabel(i18n("Current score:"));
0043     mHighScore = new QLabel(i18n("Highscore:"));
0044     mMoleculeName = new QLabel;
0045     statusBar()->addWidget(mLevel);
0046     statusBar()->addPermanentWidget(mCurrentScore);
0047     statusBar()->addPermanentWidget(mHighScore);
0048     statusBar()->addWidget(mMoleculeName);
0049 
0050     updateStatusBar( m_gameWid->currentLevel(), m_gameWid->currentScore(), m_gameWid->currentHighScore() );
0051 
0052     connect(m_gameWid, &GameWidget::statsChanged, this, &AtomTopLevel::updateStatusBar);
0053     connect(m_gameWid, &GameWidget::levelChanged, this, &AtomTopLevel::levelHasChanged);
0054 
0055     // update next/prev actions
0056     levelHasChanged(m_gameWid->currentLevel());
0057     setupGUI();
0058 }
0059 
0060 AtomTopLevel::~AtomTopLevel()
0061 {
0062 }
0063 
0064 bool AtomTopLevel::queryClose()
0065 {
0066     // saves last played level and levelset
0067     m_gameWid->saveLastPlayedLevel();
0068     Preferences::self()->save();
0069     return true;
0070 }
0071 
0072 void AtomTopLevel::createMenu()
0073 {
0074     // Game
0075     KGameStandardAction::restart(m_gameWid, &GameWidget::restartLevel, actionCollection());
0076     // FIXME: comment this until highscore dialog will be implemented.
0077     // (katomic needs special one)
0078     //    KGameStandardAction::highscores(m_gameWid, &GameWidget::showHighscores, actionCollection());
0079     KGameStandardAction::load(m_gameWid, &GameWidget::loadGame, actionCollection());
0080     KGameStandardAction::save(m_gameWid, &GameWidget::saveGame, actionCollection());
0081     KGameStandardAction::quit(this, &QWidget::close, actionCollection());
0082 
0083     // Move
0084     m_undoAct = KGameStandardAction::undo(m_gameWid->playfield(), &PlayField::undo, actionCollection());
0085     m_redoAct = KGameStandardAction::redo(m_gameWid->playfield(), &PlayField::redo, actionCollection());
0086 
0087 
0088     m_prevLevelAct = actionCollection()->addAction( QStringLiteral(  "prev_level" ) );
0089     m_prevLevelAct->setIcon( QIcon::fromTheme( QStringLiteral(  "arrow-left" ) ) );
0090     m_prevLevelAct->setText( i18n( "Previous Level" ) );
0091     KActionCollection::setDefaultShortcut(m_prevLevelAct, Qt::CTRL | Qt::Key_P );
0092     addAction( m_prevLevelAct );
0093     connect( m_prevLevelAct, &QAction::triggered, m_gameWid, &GameWidget::prevLevel );
0094 
0095     m_nextLevelAct = actionCollection()->addAction( QStringLiteral(  "next_level" ) );
0096     m_nextLevelAct->setIcon( QIcon::fromTheme( QStringLiteral(  "arrow-right" ) ) );
0097     m_nextLevelAct->setText( i18n( "Next Level" ) );
0098     KActionCollection::setDefaultShortcut(m_nextLevelAct, Qt::CTRL | Qt::Key_N );
0099     addAction( m_nextLevelAct );
0100     connect( m_nextLevelAct, &QAction::triggered, m_gameWid, &GameWidget::nextLevel );
0101 
0102     QAction* chooseLevelSet = actionCollection()->addAction( QStringLiteral(  "choose_level_set" ) );
0103     chooseLevelSet->setText( i18n( "Choose level set..." ) );
0104     addAction( chooseLevelSet );
0105     connect(chooseLevelSet, &QAction::triggered, this, &AtomTopLevel::chooseLevelSet);
0106 
0107     m_animSpeedAct = new KSelectAction(i18n("Animation Speed"), this);
0108     actionCollection()->addAction( QStringLiteral( "anim_speed" ), m_animSpeedAct);
0109     const QStringList acts{
0110         i18n("Slow"),
0111         i18n("Normal"),
0112         i18n("Fast"),
0113     };
0114     m_animSpeedAct->setItems(acts);
0115     connect(m_animSpeedAct, &KSelectAction::indexTriggered,
0116             this, &AtomTopLevel::slotAnimSpeedChanged);
0117 
0118     QAction *undoAll = actionCollection()->addAction( QStringLiteral(  "move_undo_all" ) );
0119     undoAll->setIcon( QIcon::fromTheme( QStringLiteral( "media-skip-backward" )) );
0120     undoAll->setText( i18n("Undo All") );
0121     connect( undoAll, &QAction::triggered, m_gameWid->playfield(), &PlayField::undoAll );
0122 
0123     QAction *redoAll = actionCollection()->addAction( QStringLiteral(  "move_redo_all" ) );
0124     redoAll->setIcon( QIcon::fromTheme( QStringLiteral( "media-skip-forward" )) );
0125     redoAll->setText( i18n("Redo All") );
0126     connect( redoAll, &QAction::triggered, m_gameWid->playfield(), &PlayField::redoAll );
0127 
0128     m_undoAct->setEnabled(false);
0129     m_redoAct->setEnabled(false);
0130     undoAll->setEnabled(false);
0131     redoAll->setEnabled(false);
0132 
0133     connect (m_gameWid->playfield(), &PlayField::enableRedo, m_redoAct, &QAction::setEnabled);
0134     connect (m_gameWid->playfield(), &PlayField::enableUndo, m_undoAct, &QAction::setEnabled);
0135     connect (m_gameWid->playfield(), &PlayField::enableUndo, undoAll, &QAction::setEnabled);
0136     connect (m_gameWid->playfield(), &PlayField::enableRedo, redoAll, &QAction::setEnabled);
0137 
0138     QAction * atomUpAct = actionCollection()->addAction( QStringLiteral( "atom_up" ));
0139     atomUpAct->setText(i18n("Atom Up"));
0140     KActionCollection::setDefaultShortcut(atomUpAct, Qt::Key_Up);
0141     addAction(atomUpAct);
0142     connect(atomUpAct, &QAction::triggered, m_gameWid, &GameWidget::moveUp);
0143 
0144     QAction * atomDownAct = actionCollection()->addAction( QStringLiteral( "atom_down" ));
0145     atomDownAct->setText(i18n("Atom Down"));
0146     KActionCollection::setDefaultShortcut(atomDownAct,Qt::Key_Down);
0147     addAction(atomDownAct);
0148     connect(atomDownAct, &QAction::triggered, m_gameWid, &GameWidget::moveDown);
0149 
0150     QAction * atomLeftAct = actionCollection()->addAction( QStringLiteral( "atom_left" ));
0151     atomLeftAct->setText(i18n("Atom Left"));
0152     KActionCollection::setDefaultShortcut(atomLeftAct,Qt::Key_Left);
0153     addAction(atomLeftAct);
0154     connect(atomLeftAct, &QAction::triggered, m_gameWid, &GameWidget::moveLeft);
0155 
0156     QAction * atomRightAct = actionCollection()->addAction( QStringLiteral( "atom_right" ));
0157     atomRightAct->setText(i18n("Atom Right"));
0158     KActionCollection::setDefaultShortcut(atomRightAct,Qt::Key_Right);
0159     addAction(atomRightAct);
0160     connect(atomRightAct, &QAction::triggered, m_gameWid, &GameWidget::moveRight);
0161 
0162     QAction * nextAtomAct = actionCollection()->addAction( QStringLiteral( "next_atom" ));
0163     nextAtomAct->setText(i18n("Next Atom"));
0164     KActionCollection::setDefaultShortcut(nextAtomAct,Qt::Key_Tab);
0165     addAction(nextAtomAct);
0166     connect(nextAtomAct, &QAction::triggered, m_gameWid->playfield(), &PlayField::nextAtom);
0167 
0168     QAction * prevAtomAct = actionCollection()->addAction( QStringLiteral( "prev_atom" ));
0169     prevAtomAct->setText(i18n("Previous Atom"));
0170     KActionCollection::setDefaultShortcut(prevAtomAct, Qt::SHIFT | Qt::Key_Tab);
0171     addAction(prevAtomAct);
0172     connect(prevAtomAct, &QAction::triggered, m_gameWid->playfield(), &PlayField::previousAtom);
0173 }
0174 
0175 void AtomTopLevel::loadSettings()
0176 {
0177     m_animSpeedAct->setCurrentItem( Preferences::animationSpeed() );
0178     m_gameWid->playfield()->setAnimationSpeed( Preferences::animationSpeed() );
0179 }
0180 
0181 void AtomTopLevel::slotAnimSpeedChanged(int speed)
0182 {
0183     m_gameWid->playfield()->setAnimationSpeed(speed);
0184     Preferences::setAnimationSpeed(speed);
0185     Preferences::self()->save();
0186 }
0187 
0188 void AtomTopLevel::updateStatusBar( int level, int score, int highscore )
0189 {
0190     mLevel->setText(i18n("Level: %1 (%2)", level, m_gameWid->levelSet().visibleName()));
0191     mCurrentScore->setText(i18n("Current score: %1", score));
0192     QString str;
0193     if(highscore == 0)
0194         str = QLatin1Char('-');
0195     else
0196         str.setNum(highscore);
0197     mHighScore->setText(i18n("Highscore: %1", str));
0198 }
0199 
0200 void AtomTopLevel::enableHackMode()
0201 {
0202     //qCDebug(KATOMIC_LOG) << "Enabling hack mode";
0203     m_prevLevelAct->setDisabled(false);
0204     m_nextLevelAct->setDisabled(false);
0205     m_gameWid->enableSwitchToAnyLevel();
0206 }
0207 
0208 void AtomTopLevel::levelHasChanged(int level)
0209 {
0210     // Update level name
0211     mMoleculeName->setText(m_gameWid->currentMolecule());
0212     // don't gray out actions in hackmode, else do
0213     if(!m_gameWid->switchToAnyLevelAllowed())
0214         updateActionsForLevel(level);
0215 }
0216 
0217 void AtomTopLevel::updateActionsForLevel(int)
0218 {
0219     m_prevLevelAct->setEnabled( m_gameWid->isPrevLevelAvailable() );
0220     m_nextLevelAct->setEnabled( m_gameWid->isNextLevelAvailable() );
0221 }
0222 
0223 void AtomTopLevel::chooseLevelSet()
0224 {
0225     // will delete itself on close
0226     ChooseLevelSetDialog* dlg = new ChooseLevelSetDialog(this);
0227     connect(dlg, &ChooseLevelSetDialog::levelSetChanged, this, &AtomTopLevel::changeLevelSet);
0228 
0229     dlg->setCurrentLevelSet(m_gameWid->levelSet().name());
0230     dlg->show();
0231 }
0232 
0233 void AtomTopLevel::changeLevelSet(const QString& levelSet)
0234 {
0235     if (!levelSet.isEmpty())
0236         m_gameWid->setLevelSet(levelSet);
0237 }
0238 
0239 #include "moc_toplevel.cpp"