1/* toplevel.cpp
2
3 Copyright (C) 1998 Andreas Wüst <AndreasWuest@gmx.de>
4 Copyright (C) 2006 Dmitry Suzdalev <dimsuz@gmail.com>
5 Copyright (C) 2007 Simon Hürlimann <simon.huerlimann@huerlisi.ch>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
21 */
22
23#include "toplevel.h"
24
25
26#include <klocale.h>
27#include <kconfig.h>
28#include <kstandarddirs.h>
29#include <kstandardaction.h>
30#include <kstandardgameaction.h>
31#include <kselectaction.h>
32#include <kactioncollection.h>
33#include <kdebug.h>
34#include <kicon.h>
35#include <kstatusbar.h>
36
37#include "gamewidget.h"
38#include "playfield.h"
39#include "prefs.h"
40#include "commondefs.h"
41#include "chooselevelsetdialog.h"
42
43static const int LEVEL_BAR_ID = 0;
44static const int CUR_SCORE_BAR_ID = 1;
45static const int HIGHSCORE_BAR_ID = 2;
46static const int MOLECULE_NAME_ID = 3;
47
48AtomTopLevel::AtomTopLevel()
49{
50 QString lastPlayedLevelSet = Preferences::lastPlayedLevelSet();
51 if (lastPlayedLevelSet.isEmpty())
52 lastPlayedLevelSet = DEFAULT_LEVELSET_NAME;
53
54 m_gameWid = new GameWidget( lastPlayedLevelSet, this);
55 m_gameWid->setObjectName( QLatin1String("gamewidget" ));
56 createMenu();
57 loadSettings();
58 setCentralWidget(m_gameWid);
59
60 statusBar()->insertItem( i18n("Level:"), LEVEL_BAR_ID , 1);
61 statusBar()->insertPermanentItem( i18n("Current score:"), CUR_SCORE_BAR_ID, 1);
62 statusBar()->insertPermanentItem( i18n("Highscore:"), HIGHSCORE_BAR_ID, 1 );
63 statusBar()->insertItem( QString(), MOLECULE_NAME_ID , 1);
64 statusBar()->setItemAlignment(0, Qt::AlignLeft | Qt::AlignVCenter);
65
66 updateStatusBar( m_gameWid->currentLevel(), m_gameWid->currentScore(), m_gameWid->currentHighScore() );
67
68 connect(m_gameWid, SIGNAL(statsChanged(int,int,int)), SLOT(updateStatusBar(int,int,int)));
69 connect(m_gameWid, SIGNAL(levelChanged(int)), SLOT(levelHasChanged(int)));
70
71 // update next/prev actions
72 levelHasChanged(m_gameWid->currentLevel());
73 setupGUI();
74}
75
76AtomTopLevel::~AtomTopLevel()
77{
78}
79
80bool AtomTopLevel::queryClose()
81{
82 // saves last played level and levelset
83 m_gameWid->saveLastPlayedLevel();
84 Preferences::self()->writeConfig();
85 return true;
86}
87
88void AtomTopLevel::createMenu()
89{
90 // Game
91 KStandardGameAction::restart(m_gameWid, SLOT(restartLevel()), actionCollection());
92 // FIXME: comment this until highscore dialog will be implemented.
93 // (katomic needs spesial one)
94// KStandardGameAction::highscores(m_gameWid, SLOT(showHighscores()), actionCollection());
95 KStandardGameAction::load(m_gameWid, SLOT(loadGame()), actionCollection());
96 KStandardGameAction::save(m_gameWid, SLOT(saveGame()), actionCollection());
97 KStandardGameAction::quit(this, SLOT(close()), actionCollection());
98
99 // Move
100 m_undoAct = KStandardGameAction::undo(m_gameWid->playfield(), SLOT(undo()), actionCollection());
101 m_redoAct = KStandardGameAction::redo(m_gameWid->playfield(), SLOT(redo()), actionCollection());
102
103
104 m_prevLevelAct = actionCollection()->addAction( QLatin1String( "prev_level" ) );
105 m_prevLevelAct->setIcon( KIcon( QLatin1String( "arrow-left" ) ) );
106 m_prevLevelAct->setText( i18n( "Previous Level" ) );
107 m_prevLevelAct->setShortcut( Qt::CTRL + Qt::Key_P );
108 addAction( m_prevLevelAct );
109 connect( m_prevLevelAct, SIGNAL(triggered(bool)), m_gameWid, SLOT(prevLevel()) );
110
111 m_nextLevelAct = actionCollection()->addAction( QLatin1String( "next_level" ) );
112 m_nextLevelAct->setIcon( KIcon( QLatin1String( "arrow-right" ) ) );
113 m_nextLevelAct->setText( i18n( "Next Level" ) );
114 m_nextLevelAct->setShortcut( Qt::CTRL + Qt::Key_N );
115 addAction( m_nextLevelAct );
116 connect( m_nextLevelAct, SIGNAL(triggered(bool)), m_gameWid, SLOT(nextLevel()) );
117
118 QAction* chooseLevelSet = actionCollection()->addAction( QLatin1String( "choose_level_set" ) );
119 chooseLevelSet->setText( i18n( "Choose level set..." ) );
120 addAction( chooseLevelSet );
121 connect( chooseLevelSet, SIGNAL(triggered(bool)), SLOT(chooseLevelSet()) );
122
123 m_animSpeedAct = new KSelectAction(i18n("Animation Speed"), this);
124 actionCollection()->addAction( QLatin1String( "anim_speed" ), m_animSpeedAct);
125 QStringList acts;
126 acts << i18n("Slow") << i18n("Normal") << i18n("Fast");
127 m_animSpeedAct->setItems(acts);
128 connect( m_animSpeedAct, SIGNAL(triggered(int)), SLOT(slotAnimSpeedChanged(int)) );
129
130 QAction *undoAll = actionCollection()->addAction( QLatin1String( "move_undo_all" ) );
131 undoAll->setIcon( KIcon( QLatin1String( "media-skip-backward" )) );
132 undoAll->setText( i18n("Undo All") );
133 connect( undoAll, SIGNAL(triggered(bool)), m_gameWid->playfield(), SLOT(undoAll()) );
134
135 QAction *redoAll = actionCollection()->addAction( QLatin1String( "move_redo_all" ) );
136 redoAll->setIcon( KIcon( QLatin1String( "media-skip-forward" )) );
137 redoAll->setText( i18n("Redo All") );
138 connect( redoAll, SIGNAL(triggered(bool)), m_gameWid->playfield(), SLOT(redoAll()) );
139
140 m_undoAct->setEnabled(false);
141 m_redoAct->setEnabled(false);
142 undoAll->setEnabled(false);
143 redoAll->setEnabled(false);
144
145 connect (m_gameWid->playfield(), SIGNAL (enableRedo(bool)), m_redoAct, SLOT(setEnabled(bool)));
146 connect (m_gameWid->playfield(), SIGNAL (enableUndo(bool)), m_undoAct, SLOT(setEnabled(bool)));
147 connect (m_gameWid->playfield(), SIGNAL (enableUndo(bool)), undoAll, SLOT(setEnabled(bool)));
148 connect (m_gameWid->playfield(), SIGNAL (enableRedo(bool)), redoAll, SLOT(setEnabled(bool)));
149
150 KAction* atomUpAct = actionCollection()->addAction( QLatin1String( "atom_up" ));
151 atomUpAct->setText(i18n("Atom Up"));
152 atomUpAct->setShortcut(Qt::Key_Up);
153 addAction(atomUpAct);
154 connect(atomUpAct, SIGNAL(triggered(bool)), m_gameWid, SLOT(moveUp()));
155
156 KAction* atomDownAct = actionCollection()->addAction( QLatin1String( "atom_down" ));
157 atomDownAct->setText(i18n("Atom Down"));
158 atomDownAct->setShortcut(Qt::Key_Down);
159 addAction(atomDownAct);
160 connect(atomDownAct, SIGNAL(triggered(bool)), m_gameWid, SLOT(moveDown()));
161
162 KAction* atomLeftAct = actionCollection()->addAction( QLatin1String( "atom_left" ));
163 atomLeftAct->setText(i18n("Atom Left"));
164 atomLeftAct->setShortcut(Qt::Key_Left);
165 addAction(atomLeftAct);
166 connect(atomLeftAct, SIGNAL(triggered(bool)), m_gameWid, SLOT(moveLeft()));
167
168 KAction* atomRightAct = actionCollection()->addAction( QLatin1String( "atom_right" ));
169 atomRightAct->setText(i18n("Atom Right"));
170 atomRightAct->setShortcut(Qt::Key_Right);
171 addAction(atomRightAct);
172 connect(atomRightAct, SIGNAL(triggered(bool)), m_gameWid, SLOT(moveRight()));
173
174 KAction* nextAtomAct = actionCollection()->addAction( QLatin1String( "next_atom" ));
175 nextAtomAct->setText(i18n("Next Atom"));
176 nextAtomAct->setShortcut(Qt::Key_Tab);
177 addAction(nextAtomAct);
178 connect(nextAtomAct, SIGNAL(triggered(bool)), m_gameWid->playfield(), SLOT(nextAtom()));
179
180 KAction* prevAtomAct = actionCollection()->addAction( QLatin1String( "prev_atom" ));
181 prevAtomAct->setText(i18n("Previous Atom"));
182 prevAtomAct->setShortcut(Qt::SHIFT+Qt::Key_Tab);
183 addAction(prevAtomAct);
184 connect(prevAtomAct, SIGNAL(triggered(bool)), m_gameWid->playfield(), SLOT(previousAtom()));
185}
186
187void AtomTopLevel::loadSettings()
188{
189 m_animSpeedAct->setCurrentItem( Preferences::animationSpeed() );
190 m_gameWid->playfield()->setAnimationSpeed( Preferences::animationSpeed() );
191}
192
193void AtomTopLevel::slotAnimSpeedChanged(int speed)
194{
195 m_gameWid->playfield()->setAnimationSpeed(speed);
196 Preferences::setAnimationSpeed(speed);
197 Preferences::self()->writeConfig();
198}
199
200void AtomTopLevel::updateStatusBar( int level, int score, int highscore )
201{
202 statusBar()->changeItem( i18n("Level: %1 (%2)", level, m_gameWid->levelSet().visibleName()), LEVEL_BAR_ID );
203 statusBar()->changeItem( i18n("Current score: %1", score), CUR_SCORE_BAR_ID );
204 QString str;
205 if(highscore == 0)
206 str = '-';
207 else
208 str.setNum(highscore);
209 statusBar()->changeItem( i18n("Highscore: %1", str), HIGHSCORE_BAR_ID );
210}
211
212void AtomTopLevel::enableHackMode()
213{
214 kDebug() << "Enabling hack mode";
215 m_prevLevelAct->setDisabled(false);
216 m_nextLevelAct->setDisabled(false);
217 m_gameWid->enableSwitchToAnyLevel();
218}
219
220void AtomTopLevel::levelHasChanged(int level)
221{
222 // Update level name
223 statusBar()->changeItem( m_gameWid->currentMolecule(), MOLECULE_NAME_ID);
224 // don't gray out actions in hackmode, else do
225 if(!m_gameWid->switchToAnyLevelAllowed())
226 updateActionsForLevel(level);
227}
228
229void AtomTopLevel::updateActionsForLevel(int)
230{
231 m_prevLevelAct->setEnabled( m_gameWid->isPrevLevelAvailable() );
232 m_nextLevelAct->setEnabled( m_gameWid->isNextLevelAvailable() );
233}
234
235void AtomTopLevel::chooseLevelSet()
236{
237 // will delete itself on close
238 ChooseLevelSetDialog* dlg = new ChooseLevelSetDialog(this);
239 connect(dlg, SIGNAL(levelSetChanged(QString)), SLOT(changeLevelSet(QString)));
240
241 dlg->setCurrentLevelSet(m_gameWid->levelSet().name());
242 dlg->show();
243}
244
245void AtomTopLevel::changeLevelSet(const QString& levelSet)
246{
247 if (!levelSet.isEmpty())
248 m_gameWid->setLevelSet(levelSet);
249}
250
251#include "toplevel.moc"
252