fix ebn warnings regarding includes
[kdegames.git] / kubrick / src / kubrick.cpp
blob721bcd5055d68619ab80596871194c5cab54b43c
1 /*******************************************************************************
2 Copyright 2008 Ian Wadham <ianw2@optusnet.com.au>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *******************************************************************************/
19 // Own header
20 #include "kubrick.h"
22 // Qt includes.
23 #include <QDir>
24 #include <QLineEdit>
25 #include <QString>
26 #include <QAction>
27 #include <QSignalMapper>
28 #include <QGLFormat>
30 // KDE includes.
31 #include <KLocale>
32 #include <kstandardgameaction.h>
33 #include <KToggleAction>
34 #include <KActionCollection>
35 #include <KStatusBar>
36 #include <KStandardDirs>
37 #include <KMessageBox>
38 #include <KDebug>
39 #include <KShortcutsDialog>
41 // Local includes.
42 #include "game.h"
43 #include "gameglview.h"
45 // Shorthand for reference to actions.
46 #define ACTION(x) (actionCollection()->action(x))
48 Kubrick::Kubrick () :
49 singmasterMoves (0)
51 // Window title.
52 // setCaption("Rubik's Cube"); // DELETED - This is a *trademark*.
54 // use multi-sample (anti-aliased) OpenGL if available
55 QGLFormat defFormat = QGLFormat::defaultFormat();
56 defFormat.setSampleBuffers(true);
57 QGLFormat::setDefaultFormat(defFormat);
59 game = new Game (this);
61 gameView = new GameGLView (game, this);
63 // Set the view as the central widget
64 setCentralWidget(gameView);
66 // Set up the menus, keystrokes, etc.
67 initGUI();
69 // Enable the help menu.
70 setHelpMenuEnabled (true);
72 // Load the GUI from the kubrickui.rc file.
73 setupGUI ();
75 // Set up a status bar.
76 statusBar()->show ();
77 statusBar()->insertItem (i18n("Welcome to Kubrick"), 1001, 1);
79 // Set a larger font than toolbar-default for the Singmaster-moves display.
80 QFont f = statusBar()->font();
81 f.setPointSize (f.pointSize()); // Needed to force a size-change.
82 singmasterLabel->setFont (f);
83 singmasterMoves->setFont (f);
85 adjustSize ();
87 // Save GUI settings.
88 setAutoSaveSettings ();
90 // Start the game with a randomised demo.
91 game->initGame (gameView, this);
95 Kubrick::~Kubrick ()
100 const Kubrick::PuzzleItem Kubrick::easyItems [] = {
101 {I18N_NOOP("2x2x1 mat, 1 move"), 2, 2, 1, 1, 1, 1},
102 {I18N_NOOP("2x2x1 mat, 2 moves"), 2, 2, 1, 2, 1, 1},
103 {I18N_NOOP("2x2x1 mat, 3 moves"), 2, 2, 1, 3, 1, 1},
104 {I18N_NOOP("2x2x2 cube, 2 moves"), 2, 2, 2, 2, 1, 1},
105 {I18N_NOOP("2x2x2 cube, 3 moves"), 2, 2, 2, 3, 1, 1},
106 {I18N_NOOP("2x2x2 cube, 4 moves"), 2, 2, 2, 4, 1, 0},
107 {I18N_NOOP("3x3x1 mat, 4 moves"), 3, 3, 1, 4, 1, 0},
108 {I18N_NOOP("3x3x3 cube, 3 moves"), 3, 3, 3, 3, 1, 0},
109 {I18N_NOOP("3x3x3 cube, 4 moves"), 3, 3, 3, 4, 1, 0},
110 {"END", 0, 0, 0, 0, 0, 0}
114 const Kubrick::PuzzleItem Kubrick::notSoEasyItems [] = {
115 {I18N_NOOP("3x3x3 cube, 3 moves"), 3, 3, 3, 3, 0, 0},
116 {I18N_NOOP("3x3x3 cube, 4 moves"), 3, 3, 3, 4, 0, 0},
117 {I18N_NOOP("4x4x4 cube, 4 moves"), 4, 4, 4, 4, 0, 0},
118 {I18N_NOOP("5x5x5 cube, 4 moves"), 5, 5, 5, 4, 0, 0},
119 {I18N_NOOP("6x3x2 brick, 4 moves"), 6, 3, 2, 4, 0, 0},
120 {"END", 0, 0, 0, 0, 0, 0}
124 const Kubrick::PuzzleItem Kubrick::hardItems [] = {
125 {I18N_NOOP("3x3x3 cube, 7 moves"), 3, 3, 3, 7, 0, 0},
126 {I18N_NOOP("4x4x4 cube, 5 moves"), 4, 4, 4, 5, 0, 0},
127 {I18N_NOOP("5x5x5 cube, 6 moves"), 5, 5, 5, 6, 0, 0},
128 {I18N_NOOP("6x6x6 cube, 6 moves"), 6, 6, 6, 6, 0, 0},
129 {I18N_NOOP("6x4x1 mat, 9 moves"), 6, 4, 1, 9, 0, 0},
130 {I18N_NOOP("6x3x2 brick, 6 moves"), 6, 3, 2, 7, 0, 0},
131 {"END", 0, 0, 0, 0, 0, 0}
135 const Kubrick::PuzzleItem Kubrick::veryHardItems [] = {
136 {I18N_NOOP("3x3x3 cube, 12 moves"), 3, 3, 3, 12, 0, 0},
137 {I18N_NOOP("3x3x3 cube, 15 moves"), 3, 3, 3, 15, 0, 0},
138 {I18N_NOOP("3x3x3 cube, 20 moves"), 3, 3, 3, 20, 0, 0},
139 {I18N_NOOP("4x4x4 cube, 12 moves"), 4, 4, 4, 12, 0, 0},
140 {I18N_NOOP("5x5x5 cube, 15 moves"), 5, 5, 5, 15, 0, 0},
141 {I18N_NOOP("6x6x6 cube, 25 moves"), 6, 6, 6, 25, 0, 0},
142 {"END", 0, 0, 0, 0, 0, 0}
146 const QString Kubrick::patternMovesInfo = I18N_NOOP(
147 "Rubik's Cube can be moved into many interesting patterns. Here are "
148 "a few from David Singmaster's classic book 'Notes on Rubik's Magic Cube, "
149 "Fifth Edition', pages 47-49, published in 1981. After a pattern has "
150 "formed, you can use the Solve action (default key S) to undo and redo it "
151 "as often as you like."
155 const Kubrick::DemoItem Kubrick::patterns [] = {
156 {"", I18N_NOOP("Info")},
157 {"p333X6.kbk", I18N_NOOP("3x3x3, 6 X")},
158 {"p333X2.kbk", I18N_NOOP("3x3x3, 2 X")},
159 {"p333Spot6.kbk", I18N_NOOP("3x3x3, 6 Spot")},
160 {"p333Spot4.kbk", I18N_NOOP("3x3x3, 4 Spot")},
161 {"p333Plus4.kbk", I18N_NOOP("3x3x3, 4 Plus")},
162 {"p333Bar4.kbk", I18N_NOOP("3x3x3, 4 Bar")},
163 {"p333U6.kbk", I18N_NOOP("3x3x3, 6 U")},
164 {"p333U4.kbk", I18N_NOOP("3x3x3, 4 U")},
165 {"p333Snake.kbk", I18N_NOOP("3x3x3, Snake")},
166 {"p333Worm.kbk", I18N_NOOP("3x3x3, Worm")},
167 {"p333Tricolor6.kbk", I18N_NOOP("3x3x3, Tricolor")},
168 {"p333DoubleCube.kbk", I18N_NOOP("3x3x3, Double Cube")},
169 {"END", ""}
173 const QString Kubrick::solvingMovesInfo = I18N_NOOP(
174 "<qt>Mathematicians calculate that a 3x3x3 cube can be shuffled into "
175 "43,252,003,274,489,856,000 different patterns, yet they conjecture "
176 "that all positions can be solved in 20 moves or less. The method "
177 "that can do that (as yet undiscovered) is called God's Algorithm."
178 "<br><br>"
179 "Many longer methods are known (see <a href=en.wikipedia.org>Optimal "
180 "Solutions for Rubik's Cube at en.wikipedia.org</a>)."
181 "<br><br>"
182 "Several methods work systematically by building the solution one layer "
183 "at a time, using sequences of moves that solve a few pieces without "
184 "disturbing what has already been done. The 'Beginner Solution' "
185 "demonstrated here is from "
186 "<a href=www.geocities.com/jasmine_ellen/RubiksCubeSolution.html>"
187 "www.geocities.com/jasmine_ellen/RubiksCubeSolution.html</a> (see that "
188 "site for a full description and other solution ideas). Just over "
189 "100 moves solve a cube that is shuffled in 20.</qt>"
191 // Setup the GUI, menus, ...
192 const Kubrick::DemoItem Kubrick::solvingMoves [] = {
193 {"", I18N_NOOP("Info")},
194 {"m333Layer1.kbk", I18N_NOOP("3x3x3 Layer 1, Edges First")},
195 {"m333MEdge1.kbk", I18N_NOOP("3x3x3 Layer 2, Edge from Bottom Right")},
196 {"m333MEdge2.kbk", I18N_NOOP("3x3x3 Layer 2, Edge from Bottom Left")},
197 {"m333LLEdgeFlip.kbk", I18N_NOOP("3x3x3 Layer 3, Flip Edge Pieces")},
198 {"m333LLCornerPos.kbk", I18N_NOOP("3x3x3 Layer 3, Place Corners")},
199 {"m333LLCornerRot.kbk", I18N_NOOP("3x3x3 Layer 3, Twist Corners")},
200 {"m333LLEdgePos.kbk", I18N_NOOP("3x3x3 Layer 3, Place Edges and DONE!")},
201 {"m333Complete.kbk", I18N_NOOP("3x3x3 Cube, Complete Solution")},
202 {"m333E2prX.kbk", I18N_NOOP("3x3x3 Swap 2 Pairs of Edges")},
203 {"m333CTwirl2.kbk", I18N_NOOP("3x3x3 Untwist 2 Corners")},
204 {"m333EFlip2.kbk", I18N_NOOP("3x3x3 Flip 2 Edges")},
205 {"END", ""}
209 // Create an action and set some help text for all menu items
210 // See also the *ui.rc file for the XML definitions
211 void Kubrick::initGUI()
213 // Game menu.
214 QAction * newAction = KStandardGameAction::gameNew (
215 game, SLOT (newPuzzle()), this);
216 actionCollection()->addAction (newAction->objectName(), newAction);
217 newAction->setText (i18n("&New Puzzle"));
218 newAction->setToolTip (i18n("Start a new puzzle."));
219 newAction->setWhatsThis (i18n("Finish the puzzle you are working on "
220 "and start a new puzzle with the same "
221 "dimensions and number of shuffling moves."));
223 QAction *
224 a = KStandardGameAction::load (
225 game, SLOT (load()), this);
226 actionCollection()->addAction (a->objectName(), a);
227 a->setText (i18n("&Load Puzzle..."));
228 a->setToolTip (i18n("Reload a saved puzzle from a file."));
229 a->setWhatsThis (i18n("Reload a puzzle you have previously "
230 "saved on a file, including its dimensions, "
231 "settings, current state and history of "
232 "moves."));
234 a = KStandardGameAction::save (
235 game, SLOT (save()), this);
236 actionCollection()->addAction (a->objectName(), a);
237 a->setText (i18n("&Save Puzzle..."));
238 a->setToolTip (i18n("Save the puzzle on a file."));
239 a->setWhatsThis (i18n("Save the puzzle on a file, including "
240 "its dimensions, settings, current state and "
241 "history of moves."));
243 a = KStandardGameAction::saveAs (
244 game, SLOT (saveAs()), this);
245 actionCollection()->addAction (a->objectName(), a);
246 a->setText (i18n("&Save Puzzle As..."));
248 a = KStandardGameAction::
249 restart (game, SLOT (undoAll()), this);
250 actionCollection()->addAction (a->objectName(), a);
251 a->setText (i18n("Restart &Puzzle..."));
252 a->setToolTip (i18n("Undo all previous moves and start "
253 "again."));
254 a->setWhatsThis (i18n("Undo all previous moves and start "
255 "again."));
257 a = KStandardGameAction::
258 quit (this, SLOT (close()), this);
259 actionCollection()->addAction (a->objectName(), a);
260 // NOTE: KXmlGuiWindow::close() calls Kubrick::queryClose(), our real "quit"
262 // Move menu.
263 a = KStandardGameAction::
264 undo (game, SLOT (undoMove()), this);
265 actionCollection()->addAction (a->objectName(), a);
266 a->setToolTip (i18n("Undo the last move."));
267 a->setWhatsThis (i18n("Undo the last move."));
269 a = KStandardGameAction::
270 redo (game, SLOT (redoMove()), this);
271 actionCollection()->addAction (a->objectName(), a);
272 a->setToolTip (i18n("Redo a previously undone move."));
273 a->setWhatsThis (i18n("Redo a previously undone move "
274 "(repeatedly from the start if required)."));
276 a = KStandardGameAction::
277 solve (game, SLOT (solveCube()), this);
278 actionCollection()->addAction (a->objectName(), a);
279 a->setToolTip (i18n("Show the solution of the puzzle."));
280 a->setWhatsThis (i18n("Show the solution of the puzzle by "
281 "undoing and re-doing all shuffling moves."));
283 a = KStandardGameAction::
284 demo (game, SLOT (toggleDemo()), this);
285 actionCollection()->addAction (a->objectName(), a);
286 a->setText (i18n("Main &Demo"));
287 a->setToolTip (i18n("Run a demonstration of puzzle moves."));
288 a->setWhatsThis (i18n("Run a demonstration of puzzle moves, "
289 "in which randomly chosen cubes, bricks or "
290 "mats are shuffled and solved."));
292 a = actionCollection()->addAction ("standard_view");
293 a->setText (i18n("Realign Cube"));
294 a->setToolTip (i18n("Realign the cube so that the top, "
295 "front and right faces are visible together."));
296 a->setWhatsThis (i18n("Realign the cube so that the top, "
297 "front and right faces are visible together "
298 "and the cube's axes are parallel to the XYZ "
299 "axes, thus making keyboard moves properly "
300 "meaningful."));
301 a->setIcon (KIcon("go-home"));
302 a->setShortcut (Qt::Key_Home);
303 connect (a, SIGNAL (triggered (bool)), game, SLOT (setStandardView()));
305 a = actionCollection()->addAction ("redo_all");
306 a->setText (i18n("Redo All"));
307 a->setShortcut (Qt::SHIFT + Qt::Key_R);
308 connect (a, SIGNAL (triggered (bool)), game, SLOT (redoAll()));
310 // Read-only display of Singmaster moves on the toolbar.
311 singmasterLabel = new QLabel (i18n("Singmaster Moves"), this);
312 singmasterMoves = new QLineEdit (this);
314 KAction * w = new KAction (this);
315 actionCollection()->addAction ("singmaster_label", w);
316 w->setDefaultWidget (singmasterLabel);
318 w = new KAction (this);
319 actionCollection()->addAction ("singmaster_moves", w);
320 w->setDefaultWidget (singmasterMoves);
322 QString singmasterToolTip = i18n("This area shows Singmaster moves.");
323 QString singmasterWhatsThis = i18nc("The letters RLFBUD are mathematical "
324 "notation based on English words. Please leave those "
325 "letters and words untranslated in some form.",
327 "This area shows Singmaster moves. "
328 "They are based on the letters RLFBUD, representing "
329 "(in English) the Right, Left, Front, Back, Up and "
330 "Down faces. In normal view, the letters RFU represent "
331 "clockwise moves of the three visible faces and LBD "
332 "appear as anticlockwise moves of the hidden faces. "
333 "Adding a ' (apostrophe) to a letter gives the reverse "
334 "of that letter's move. To move inner slices, add "
335 "periods (or dots) before the letter of the nearest "
336 "face.");
338 singmasterLabel->setToolTip (singmasterToolTip);
339 singmasterLabel->setWhatsThis (singmasterWhatsThis);
340 singmasterMoves->setToolTip (singmasterToolTip);
341 singmasterMoves->setWhatsThis (singmasterWhatsThis);
343 singmasterMoves->setReadOnly (true);
344 singmasterLabel->setBuddy (singmasterMoves);
345 singmasterMoves->show();
346 singmasterLabel->show();
347 singmasterMoves->setFocusPolicy (Qt::NoFocus);
348 singmasterMoves->clearFocus();
350 // "Choose Puzzle Type" sub-menu.
351 easyList = new KSelectAction (i18n("&Easy"), this);
352 actionCollection()->addAction ("easy_list", easyList);
353 fillPuzzleList (easyList, easyItems);
354 connect (easyList, SIGNAL(triggered(int)), SLOT(easySelected(int)));
356 notSoEasyList = new KSelectAction (i18n("&Not So Easy"), this);
357 actionCollection()->addAction ("not_easy_list", notSoEasyList);
358 fillPuzzleList (notSoEasyList, notSoEasyItems);
359 connect (notSoEasyList,SIGNAL(triggered(int)),SLOT(notSoEasySelected(int)));
361 hardList = new KSelectAction (i18n("&Hard"), this);
362 actionCollection()->addAction ("hard_list", hardList);
363 fillPuzzleList (hardList, hardItems);
364 connect (hardList, SIGNAL(triggered(int)), SLOT(hardSelected(int)));
366 veryHardList = new KSelectAction (i18n("&Very Hard"), this);
367 actionCollection()->addAction ("very_hard_list", veryHardList);
368 fillPuzzleList (veryHardList, veryHardItems);
369 connect (veryHardList, SIGNAL(triggered(int)), SLOT(veryHardSelected(int)));
371 a = actionCollection()->addAction ("new_cube");
372 a->setText (i18n("Make your own..."));
373 connect (a, SIGNAL (triggered (bool)), game, SLOT (newCubeDialog()));
375 // View menu.
376 KToggleAction * b;
377 QActionGroup * viewGroup = new QActionGroup (this);
378 viewGroup->setExclusive (true);
380 QSignalMapper * viewMapper = new QSignalMapper (this);
381 connect (viewMapper, SIGNAL (mapped (const int)),
382 game, SLOT (changeScene (const int)));
384 b = new KToggleAction (i18n ("1 Cube"), this);
385 actionCollection()->addAction ("scene_1", b);
386 b->setToolTip (i18n ("Show one view of this cube."));
387 b->setWhatsThis (i18n ("Show one view of this cube, "
388 "from the front."));
389 b->setIcon (KIcon("arrow-left")); // IDW - Temporary.
390 connect (b, SIGNAL(triggered (bool)), viewMapper, SLOT(map()));
391 b->setChecked (true);
392 viewMapper->setMapping (b, OneCube);
393 viewGroup->addAction (b);
395 b = new KToggleAction (i18n ("2 Cubes"), this);
396 actionCollection()->addAction ("scene_2", b);
397 b->setToolTip (i18n ("Show two views of this cube."));
398 b->setWhatsThis (i18n ("Show two views of this cube, from "
399 "the front and the back. Both can rotate."));
400 b->setIcon (KIcon("arrow-up")); // IDW - Temporary.
401 connect (b, SIGNAL(triggered (bool)), viewMapper, SLOT(map()));
402 viewMapper->setMapping (b, TwoCubes);
403 viewGroup->addAction (b);
405 b = new KToggleAction (i18n ("3 Cubes"), this);
406 actionCollection()->addAction ("scene_3", b);
407 b->setToolTip (i18n ("Show three views of this cube."));
408 b->setWhatsThis (i18n ("Show three views of this cube, a "
409 "large one, from the front, and two small "
410 "ones, from the front and the back. Only "
411 "the large one can rotate."));
412 b->setIcon (KIcon("arrow-right")); // IDW - Temporary.
413 connect (b, SIGNAL(triggered (bool)), viewMapper, SLOT(map()));
414 viewMapper->setMapping (b, ThreeCubes);
415 viewGroup->addAction (b);
417 // Demos menu.
418 patternList = new KSelectAction (i18n("&Pretty Patterns"), this);
419 actionCollection()->addAction ("patterns_list", patternList);
420 maxPatternsIndex = fillDemoList (patternList, patterns);
421 connect (patternList, SIGNAL(triggered(int)), SLOT(patternSelected(int)));
423 movesList = new KSelectAction (i18n("&Solution Moves"), this);
424 actionCollection()->addAction ("demo_moves_list", movesList);
425 maxMovesIndex = fillDemoList (movesList, solvingMoves);
426 connect (movesList, SIGNAL(triggered(int)), SLOT(movesSelected(int)));
428 // Settings menu.
429 b = new KToggleAction (i18n("&Watch Shuffling"), this);
430 actionCollection()->addAction ("watch_shuffling", b);
431 b->setShortcut (Qt::Key_W);
432 connect (b, SIGNAL (triggered (bool)), game, SLOT (watchShuffling()));
434 b = new KToggleAction (i18n("Watch Your &Own Moves"), this);
435 actionCollection()->addAction ("watch_moves", b);
436 b->setShortcut (Qt::Key_O);
437 connect (b, SIGNAL (triggered (bool)), game, SLOT (watchMoves()));
439 // DISCONTINUED a = actionCollection()->addAction ("enable_messages");
440 // a->setText (i18n("Show Beginners' &Messages"));
441 // connect (a, SIGNAL (triggered (bool)), game, SLOT (enableMessages()));
443 // Sorry to be "non-standard" (below), but I am an English-speaker, born and
444 // bred, and I just don't find the KDE standard texts "Configure Kubrick"
445 // and "Configure Shortcuts" to be meaningful in everyday language. Neither
446 // would my wife, children and friends, I am sure.
448 a = KStandardAction::preferences (game, SLOT(optionsDialog()),
449 actionCollection());
450 a->setText (i18n("Kubri&ck Game Settings"));
452 // Configure Shortcuts...
453 a = KStandardAction::keyBindings (this, SLOT(optionsConfigureKeys()),
454 actionCollection());
455 a->setText (i18n("Keyboard S&hortcut Settings"));
457 /**************************************************************************/
458 /************************** KEYSTROKE ACTIONS **************************/
459 /**************************************************************************/
461 // Keys to choose the axis for a slice move (X, Y or Z).
462 QSignalMapper * moveAxis = new QSignalMapper (this);
464 a = actionCollection()->addAction ("x_axis");
465 a->setText (i18n("X Axis"));
466 a->setShortcut (Qt::Key_X);
467 connect (a, SIGNAL (triggered (bool)), moveAxis, SLOT (map()));
468 moveAxis->setMapping (a, 0);
470 a = actionCollection()->addAction ("y_axis");
471 a->setText (i18n("Y Axis"));
472 a->setShortcut (Qt::Key_Y);
473 connect (a, SIGNAL (triggered (bool)), moveAxis, SLOT (map()));
474 moveAxis->setMapping (a, 1);
476 a = actionCollection()->addAction ("z_axis");
477 a->setText (i18n("Z Axis"));
478 a->setShortcut (Qt::Key_Z);
479 connect (a, SIGNAL (triggered (bool)), moveAxis, SLOT (map()));
480 moveAxis->setMapping (a, 2);
482 connect (moveAxis, SIGNAL (mapped (int)), game, SLOT (setMoveAxis (int)));
484 // Keys to choose the slice number for a slice move.
485 QSignalMapper * moveSlice = new QSignalMapper (this);
487 char ident [10];
488 strcpy (ident, "slice n");
489 for (int i = 1; i <= 6; i++) {
490 sprintf (ident, "slice %d", i);
491 a = actionCollection()->addAction (ident);
492 a->setText (i18n("Slice %1", i));
493 a->setShortcut (Qt::Key_0 + i);
494 connect (a, SIGNAL (triggered (bool)), moveSlice, SLOT (map()));
495 moveSlice->setMapping (a, i);
498 // Key to select a rotation of the whole cube (mapped as "slice 0").
499 a = actionCollection()->addAction ("turn_cube");
500 a->setText (i18n("Turn whole cube"));
501 a->setShortcut (Qt::Key_C);
502 connect (a, SIGNAL (triggered (bool)), moveSlice, SLOT (map()));
503 moveSlice->setMapping (a, 0);
505 connect (moveSlice, SIGNAL (mapped (int)), game, SLOT (setMoveSlice(int)));
507 // Keys to choose the direction for a slice move (clock or anti-clock).
508 QSignalMapper * moveDirection = new QSignalMapper (this);
510 a = actionCollection()->addAction ("anti_clockwise");
511 a->setText (i18n("Anti-clockwise"));
512 a->setShortcut (Qt::Key_Left);
513 connect (a, SIGNAL (triggered (bool)), moveDirection, SLOT (map()));
514 moveDirection->setMapping (a, 0);
516 a = actionCollection()->addAction ("clockwise");
517 a->setText (i18n("Clockwise"));
518 a->setShortcut (Qt::Key_Right);
519 connect (a, SIGNAL (triggered (bool)), moveDirection, SLOT (map()));
520 moveDirection->setMapping (a, 1);
522 connect (moveDirection, SIGNAL (mapped (int)),
523 game, SLOT (setMoveDirection (int)));
525 // Keys for Singmaster (sm) moves.
526 QSignalMapper * smMove = new QSignalMapper (this);
527 a = mapAction (smMove, "sm_u", i18n("Move 'Up' face"),
528 Qt::Key_U, SM_UP);
529 a = mapAction (smMove, "sm_d", i18n("Move 'Down' face"),
530 Qt::Key_E, SM_DOWN);
531 // IDW Qt::Key_D, SM_DOWN);
532 a = mapAction (smMove, "sm_l", i18n("Move 'Left' face"),
533 Qt::Key_L, SM_LEFT);
534 a = mapAction (smMove, "sm_r", i18n("Move 'Right' face"),
535 Qt::Key_R, SM_RIGHT);
536 a = mapAction (smMove, "sm_f", i18n("Move 'Front' face"),
537 Qt::Key_F, SM_FRONT);
538 a = mapAction (smMove, "sm_b", i18n("Move 'Back' face"),
539 Qt::Key_B, SM_BACK);
540 a = mapAction (smMove, "sm_anti", i18n("Anti-clockwise move"),
541 Qt::Key_Apostrophe, SM_ANTICLOCKWISE);
542 a = mapAction (smMove, "sm_plus", i18n("Singmaster two-slice move"),
543 Qt::Key_Plus, SM_2_SLICE);
544 a = mapAction (smMove, "sm_minus", i18n("Singmaster anti-slice move"),
545 Qt::Key_Minus, SM_ANTISLICE);
546 a = mapAction (smMove, "sm_dot", i18n("Move an inner slice"),
547 Qt::Key_Period, SM_INNER);
548 a = mapAction (smMove, "sm_return", i18n("Complete a Singmaster move"),
549 Qt::Key_Return, SM_EXECUTE);
550 a = mapAction (smMove, "sm_enter", i18n("Complete a Singmaster move"),
551 Qt::Key_Enter, SM_EXECUTE);
552 a = mapAction (smMove, "sm_space", i18n("Add space to Singmaster moves"),
553 Qt::Key_Space, SM_SPACER);
554 connect (smMove, SIGNAL (mapped (int)), game, SLOT (smInput (int)));
558 QAction * Kubrick::mapAction (QSignalMapper * mapper, const QString & name,
559 const QString & text, const Qt::Key key, SingmasterMove mapping)
561 QAction * a;
562 a = actionCollection()->addAction (name);
563 kDebug() << name << text << key << mapping;
564 a->setText (text);
565 a->setShortcut (key);
566 connect (a, SIGNAL (triggered (bool)), mapper, SLOT (map()));
567 mapper->setMapping (a, mapping);
568 return a;
572 void Kubrick::setToggle (const char * actionName, bool onOff)
574 ((KToggleAction *) ACTION (actionName))->setChecked (onOff);
578 void Kubrick::setAvail (const char * actionName, bool onOff)
580 ((KAction *) ACTION (actionName))->setEnabled (onOff);
584 void Kubrick::setSingmaster (const QString & smString)
586 singmasterMoves->setText (smString);
590 void Kubrick::setSingmasterSelection (const int start, const int length)
592 kDebug() << "Set selection" << start << length;
593 singmasterMoves->setSelection (start, length);
597 int Kubrick::fillPuzzleList (KSelectAction * s, const PuzzleItem itemList [])
599 QStringList list;
601 for (uint i=0; (strcmp (itemList[i].menuText, "END") != 0); i++) {
602 list.append (i18n(itemList[i].menuText));
604 list.append ("."); // Add dummy item to hold unwanted checkbox.
605 s->setItems(list);
606 return (list.count() - 1);
610 int Kubrick::fillDemoList (KSelectAction * s, const DemoItem itemList [])
612 QStringList list;
614 for (uint i=0; (strcmp (itemList[i].filename, "END") != 0); i++) {
615 list.append (i18n(itemList[i].menuText));
617 list.append ("."); // Add dummy item to hold unwanted checkbox.
618 s->setItems(list);
619 return (list.count() - 1);
623 void Kubrick::easySelected (int index)
625 statusBar()->changeItem (easyItems [index].menuText, 1001);
626 game->changePuzzle (easyItems [index]);
630 void Kubrick::notSoEasySelected (int index)
632 statusBar()->changeItem (notSoEasyItems [index].menuText, 1001);
633 game->changePuzzle (notSoEasyItems [index]);
637 void Kubrick::hardSelected (int index)
639 statusBar()->changeItem (hardItems [index].menuText, 1001);
640 game->changePuzzle (hardItems [index]);
644 void Kubrick::veryHardSelected (int index)
646 statusBar()->changeItem (veryHardItems [index].menuText, 1001);
647 game->changePuzzle (veryHardItems [index]);
651 void Kubrick::patternSelected (int index)
653 kDebug() << "Pattern" << index;
654 if (index > 0) {
655 game->loadDemo (patterns[index].filename);
656 statusBar()->changeItem (patterns[index].menuText, 1001);
658 else {
659 KMessageBox::information (this,
660 patternMovesInfo,
661 i18n("Pretty Patterns"));
663 // Kludge to make the unwanted KSelectAction checkbox go onto a dummy item.
664 patternList->setCurrentItem (maxPatternsIndex);
668 void Kubrick::movesSelected (int index)
670 if (index > 0) {
671 game->loadDemo (solvingMoves[index].filename);
672 statusBar()->changeItem (solvingMoves[index].menuText, 1001);
674 else {
675 KMessageBox::information (this,
676 solvingMovesInfo,
677 i18n("Solution Moves"));
679 // Kludge to make the unwanted KSelectAction checkbox go onto a dummy item.
680 movesList->setCurrentItem (maxMovesIndex);
684 void Kubrick::describePuzzle (int xDim, int yDim, int zDim, int shMoves)
686 QString descr;
687 if ((xDim == yDim) && (yDim == zDim)) {
688 descr = i18n ("%1x%2x%3 cube, %4 moves", xDim, yDim, zDim, shMoves);
690 else if ((xDim != 1) && (yDim != 1) && (zDim != 1)) {
691 descr = i18n ("%1x%2x%3 brick, %4 moves", xDim, yDim, zDim, shMoves);
693 else {
694 descr = i18n ("%1x%2x%3 mat, %4 moves", xDim, yDim, zDim, shMoves);
696 statusBar()->changeItem (descr, 1001);
700 void Kubrick::optionsConfigureKeys()
702 KShortcutsDialog::configure(actionCollection());
706 // This method is invoked by KXmlGuiWindow when the window is closed, whether by
707 // selecting the "Quit" action or by clicking the "X" widget at the top right.
709 bool Kubrick::queryClose ()
711 game->saveState (); // Save the current state of the cube.
712 return (true);
715 #include "kubrick.moc"