|
|
|
/* Yo Emacs, this is -*- C++ -*-
|
|
|
|
*******************************************************************
|
|
|
|
*******************************************************************
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* KSHISEN
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*******************************************************************
|
|
|
|
*
|
|
|
|
* A japanese game similar to mahjongg
|
|
|
|
*
|
|
|
|
*******************************************************************
|
|
|
|
*
|
|
|
|
* created 1997 by Mario Weilguni <mweilguni@sime.com>
|
|
|
|
*
|
|
|
|
*******************************************************************
|
|
|
|
*
|
|
|
|
* This file is part of the KDE project "KSHISEN"
|
|
|
|
*
|
|
|
|
* KSHISEN is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* KSHISEN is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with KSHISEN; see the file COPYING. If not, write to
|
|
|
|
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
*******************************************************************
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <kapplication.h>
|
|
|
|
#include <kseparator.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
#include <kconfig.h>
|
|
|
|
#include <kaction.h>
|
|
|
|
#include <kstdgameaction.h>
|
|
|
|
#include <khighscore.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kkeydialog.h>
|
|
|
|
#include <kpopupmenu.h>
|
|
|
|
#include <kstatusbar.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kpushbutton.h>
|
|
|
|
#include <kstdguiitem.h>
|
|
|
|
#include <kconfigdialog.h>
|
|
|
|
|
|
|
|
#include <tqlayout.h>
|
|
|
|
#include <tqtimer.h>
|
|
|
|
#include <tqlineedit.h>
|
|
|
|
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
#include "app.h"
|
|
|
|
#include "prefs.h"
|
|
|
|
#include "settings.h"
|
|
|
|
|
|
|
|
App::App(TQWidget *tqparent, const char *name) : KMainWindow(tqparent, name),
|
|
|
|
cheat(false)
|
|
|
|
{
|
|
|
|
highscoreTable = new KHighscore(TQT_TQOBJECT(this));
|
|
|
|
|
|
|
|
// TODO?
|
|
|
|
// Would it make sense long term to have a kconfig update rather then
|
|
|
|
// havin both formats supported in the code?
|
|
|
|
if(highscoreTable->hasTable())
|
|
|
|
readHighscore();
|
|
|
|
else
|
|
|
|
readOldHighscore();
|
|
|
|
|
|
|
|
statusBar()->insertItem("", SBI_TIME);
|
|
|
|
statusBar()->insertItem("", SBI_TILES);
|
|
|
|
statusBar()->insertFixedItem(i18n(" Cheat mode "), SBI_CHEAT);
|
|
|
|
statusBar()->changeItem("", SBI_CHEAT);
|
|
|
|
|
|
|
|
initKAction();
|
|
|
|
|
|
|
|
board = new Board(this, "board");
|
|
|
|
loadSettings();
|
|
|
|
|
|
|
|
setCentralWidget(board);
|
|
|
|
|
|
|
|
setupGUI();
|
|
|
|
|
|
|
|
connect(board, TQT_SIGNAL(changed()), TQT_TQOBJECT(this), TQT_SLOT(enableItems()));
|
|
|
|
|
|
|
|
TQTimer *t = new TQTimer(this);
|
|
|
|
t->start(1000);
|
|
|
|
connect(t, TQT_SIGNAL(timeout()), TQT_TQOBJECT(this), TQT_SLOT(updateScore()));
|
|
|
|
connect(board, TQT_SIGNAL(endOfGame()), TQT_TQOBJECT(this), TQT_SLOT(slotEndOfGame()));
|
|
|
|
connect(board, TQT_SIGNAL(resized()), TQT_TQOBJECT(this), TQT_SLOT(boardResized()));
|
|
|
|
|
|
|
|
kapp->processEvents();
|
|
|
|
|
|
|
|
updateScore();
|
|
|
|
enableItems();
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::initKAction()
|
|
|
|
{
|
|
|
|
// Game
|
|
|
|
KStdGameAction::gameNew(TQT_TQOBJECT(this), TQT_SLOT(newGame()), actionCollection());
|
|
|
|
KStdGameAction::restart(TQT_TQOBJECT(this), TQT_SLOT(restartGame()), actionCollection());
|
|
|
|
KStdGameAction::pause(TQT_TQOBJECT(this), TQT_SLOT(pause()), actionCollection());
|
|
|
|
KStdGameAction::highscores(TQT_TQOBJECT(this), TQT_SLOT(hallOfFame()), actionCollection());
|
|
|
|
KStdGameAction::quit(TQT_TQOBJECT(this), TQT_SLOT(quitGame()), actionCollection());
|
|
|
|
|
|
|
|
// Move
|
|
|
|
KStdGameAction::undo(TQT_TQOBJECT(this), TQT_SLOT(undo()), actionCollection());
|
|
|
|
KStdGameAction::redo(TQT_TQOBJECT(this), TQT_SLOT(redo()), actionCollection());
|
|
|
|
KStdGameAction::hint(TQT_TQOBJECT(this), TQT_SLOT(hint()), actionCollection());
|
|
|
|
//new KAction(i18n("Is Game Solvable?"), 0, this,
|
|
|
|
// TQT_SLOT(isSolvable()), actionCollection(), "move_solvable");
|
|
|
|
|
|
|
|
#ifdef DEBUGGING
|
|
|
|
(void)new KAction(i18n("&Finish"), 0, board, TQT_SLOT(finish()), actionCollection(), "move_finish");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Settings
|
|
|
|
KStdAction::preferences(TQT_TQOBJECT(this), TQT_SLOT(showSettings()), actionCollection());
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::hallOfFame()
|
|
|
|
{
|
|
|
|
showHighscore();
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::newGame()
|
|
|
|
{
|
|
|
|
board->newGame();
|
|
|
|
resetCheatMode();
|
|
|
|
enableItems();
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::quitGame()
|
|
|
|
{
|
|
|
|
kapp->quit();
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::restartGame()
|
|
|
|
{
|
|
|
|
board->setUpdatesEnabled(false);
|
|
|
|
while(board->canUndo())
|
|
|
|
board->undo();
|
|
|
|
board->setUpdatesEnabled(true);
|
|
|
|
board->update();
|
|
|
|
enableItems();
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::isSolvable()
|
|
|
|
{
|
|
|
|
if(board->solvable())
|
|
|
|
KMessageBox::information(this, i18n("This game is solvable."));
|
|
|
|
else
|
|
|
|
KMessageBox::information(this, i18n("This game is NOT solvable."));
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::pause()
|
|
|
|
{
|
|
|
|
bool paused = board->pause();
|
|
|
|
lockMenus(paused);
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::undo()
|
|
|
|
{
|
|
|
|
if(board->canUndo())
|
|
|
|
{
|
|
|
|
board->undo();
|
|
|
|
setCheatMode();
|
|
|
|
enableItems();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::redo()
|
|
|
|
{
|
|
|
|
if(board->canRedo())
|
|
|
|
board->redo();
|
|
|
|
enableItems();
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::hint()
|
|
|
|
{
|
|
|
|
#ifdef DEBUGGING
|
|
|
|
board->makeHintMove();
|
|
|
|
#else
|
|
|
|
board->showHint();
|
|
|
|
setCheatMode();
|
|
|
|
#endif
|
|
|
|
enableItems();
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::loadSettings()
|
|
|
|
{
|
|
|
|
// Setting 'Prefer Unscaled Tiles' to on is known to fail in the following
|
|
|
|
// situation: The Keramik window decoration is in use AND caption bubbles
|
|
|
|
// stick out above the title bar (i.e. Keramik's 'Draw small caption
|
|
|
|
// bubbles on active windows' configuration entry is set to off) AND the
|
|
|
|
// kshisen window is maximized.
|
|
|
|
//
|
|
|
|
// The user can work-around this situation by un-maximizing the window first.
|
|
|
|
if(Prefs::unscaled())
|
|
|
|
{
|
|
|
|
TQSize s = board->unscaledSize();
|
|
|
|
|
|
|
|
// We would have liked to have used KMainWindow::sizeForCentralWidgetSize(),
|
|
|
|
// but this function does not seem to work when the toolbar is docked on the
|
|
|
|
// left. sizeForCentralWidgetSize() even reports a value 1 pixel too small
|
|
|
|
// when the toolbar is docked at the top...
|
|
|
|
// These bugs present in KDE: 3.1.90 (CVS >= 20030225)
|
|
|
|
//resize(sizeForCentralWidgetSize(s));
|
|
|
|
|
|
|
|
s += size() - board->size(); // compensate for chrome (toolbars, statusbars etc.)
|
|
|
|
resize(s);
|
|
|
|
//kdDebug() << "App::preferUnscaled() set size to: " << s.width() << " x " << s.height() << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::lockMenus(bool lock)
|
|
|
|
{
|
|
|
|
// Disable all actions apart from (un)pause, quit and those that are help-related.
|
|
|
|
// (Only undo/redo and hint actually *need* to be disabled, but disabling everything
|
|
|
|
// provides a good visual hint to the user, that they need to unpause to continue.
|
|
|
|
KPopupMenu* help = dynamic_cast<KPopupMenu*>(child("help", "KPopupMenu", false));
|
|
|
|
KActionPtrList actions = actionCollection()->actions();
|
|
|
|
KActionPtrList::iterator actionIter = actions.begin();
|
|
|
|
KActionPtrList::iterator actionIterEnd = actions.end();
|
|
|
|
|
|
|
|
while(actionIter != actionIterEnd)
|
|
|
|
{
|
|
|
|
KAction* a = *actionIter;
|
|
|
|
if(!a->isPlugged(help))
|
|
|
|
a->setEnabled(!lock);
|
|
|
|
++actionIter;
|
|
|
|
}
|
|
|
|
|
|
|
|
actionCollection()->action(KStdGameAction::name(KStdGameAction::Pause))->setEnabled(true);
|
|
|
|
actionCollection()->action(KStdGameAction::name(KStdGameAction::Quit))->setEnabled(true);
|
|
|
|
|
|
|
|
enableItems();
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::enableItems()
|
|
|
|
{
|
|
|
|
if(!board->isPaused())
|
|
|
|
{
|
|
|
|
actionCollection()->action(KStdGameAction::name(KStdGameAction::Undo))->setEnabled(board->canUndo());
|
|
|
|
actionCollection()->action(KStdGameAction::name(KStdGameAction::Redo))->setEnabled(board->canRedo());
|
|
|
|
actionCollection()->action(KStdGameAction::name(KStdGameAction::Restart))->setEnabled(board->canUndo());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::boardResized()
|
|
|
|
{
|
|
|
|
// If the board has been resized to a size that requires scaled tiles, then the
|
|
|
|
// 'Prefer Unscaled Tiles' option should be set to off.
|
|
|
|
|
|
|
|
//kdDebug() << "App::boardResized " << b->width() << " x " << b->height() << endl;
|
|
|
|
bool unscaled = Prefs::unscaled();
|
|
|
|
if(unscaled && board->size() != board->unscaledSize())
|
|
|
|
Prefs::setUnscaled(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::slotEndOfGame()
|
|
|
|
{
|
|
|
|
if(board->tilesLeft() > 0)
|
|
|
|
{
|
|
|
|
KMessageBox::information(this, i18n("No more moves possible!"), i18n("End of Game"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// create highscore entry
|
|
|
|
HighScore hs;
|
|
|
|
hs.seconds = board->getTimeForGame();
|
|
|
|
hs.x = board->x_tiles();
|
|
|
|
hs.y = board->y_tiles();
|
|
|
|
hs.gravity = (int)board->gravityFlag();
|
|
|
|
|
|
|
|
// check if we made it into Top10
|
|
|
|
bool isHighscore = false;
|
|
|
|
if(highscore.size() < HIGHSCORE_MAX)
|
|
|
|
isHighscore = true;
|
|
|
|
else if(isBetter(hs, highscore[HIGHSCORE_MAX-1]))
|
|
|
|
isHighscore = true;
|
|
|
|
|
|
|
|
if(isHighscore && !cheat)
|
|
|
|
{
|
|
|
|
hs.name = getPlayerName();
|
|
|
|
hs.date = time((time_t*)0);
|
|
|
|
int rank = insertHighscore(hs);
|
|
|
|
showHighscore(rank);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TQString s = i18n("Congratulations! You made it in %1:%2:%3")
|
|
|
|
.tqarg(TQString().sprintf("%02d", board->getTimeForGame()/3600))
|
|
|
|
.tqarg(TQString().sprintf("%02d", (board->getTimeForGame() / 60) % 60))
|
|
|
|
.tqarg(TQString().sprintf("%02d", board->getTimeForGame() % 60));
|
|
|
|
|
|
|
|
KMessageBox::information(this, s, i18n("End of Game"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
resetCheatMode();
|
|
|
|
board->newGame();
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::updateScore()
|
|
|
|
{
|
|
|
|
int t = board->getTimeForGame();
|
|
|
|
TQString s = i18n(" Your time: %1:%2:%3 %4")
|
|
|
|
.tqarg(TQString().sprintf("%02d", t / 3600 ))
|
|
|
|
.tqarg(TQString().sprintf("%02d", (t / 60) % 60 ))
|
|
|
|
.tqarg(TQString().sprintf("%02d", t % 60 ))
|
|
|
|
.tqarg(board->isPaused()?i18n("(Paused) "):TQString());
|
|
|
|
|
|
|
|
statusBar()->changeItem(s, SBI_TIME);
|
|
|
|
|
|
|
|
// Number of tiles
|
|
|
|
int tl = (board->x_tiles() * board->y_tiles());
|
|
|
|
s = i18n(" Removed: %1/%2 ")
|
|
|
|
.tqarg(TQString().sprintf("%d", tl - board->tilesLeft()))
|
|
|
|
.tqarg(TQString().sprintf("%d", tl ));
|
|
|
|
|
|
|
|
statusBar()->changeItem(s, SBI_TILES);
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::setCheatMode()
|
|
|
|
{
|
|
|
|
// set the cheat mode if not set
|
|
|
|
if(!cheat)
|
|
|
|
{
|
|
|
|
cheat = true;
|
|
|
|
statusBar()->changeItem(i18n(" Cheat mode "), SBI_CHEAT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::resetCheatMode()
|
|
|
|
{
|
|
|
|
// reset cheat mode if set
|
|
|
|
if(cheat)
|
|
|
|
{
|
|
|
|
cheat = false;
|
|
|
|
statusBar()->changeItem("", SBI_CHEAT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString App::getPlayerName()
|
|
|
|
{
|
|
|
|
TQDialog *dlg = new TQDialog(this, "Hall of Fame", true);
|
|
|
|
|
|
|
|
TQLabel *l1 = new TQLabel(i18n("You've made it into the \"Hall Of Fame\". Type in\nyour name so mankind will always remember\nyour cool rating."), dlg);
|
|
|
|
l1->setFixedSize(l1->tqsizeHint());
|
|
|
|
|
|
|
|
TQLabel *l2 = new TQLabel(i18n("Your name:"), dlg);
|
|
|
|
l2->setFixedSize(l2->tqsizeHint());
|
|
|
|
|
|
|
|
TQLineEdit *e = new TQLineEdit(dlg);
|
|
|
|
e->setText("XXXXXXXXXXXXXXXX");
|
|
|
|
e->setMinimumWidth(e->tqsizeHint().width());
|
|
|
|
e->setFixedHeight(e->tqsizeHint().height());
|
|
|
|
e->setText( lastPlayerName );
|
|
|
|
e->setFocus();
|
|
|
|
|
|
|
|
TQPushButton *b = new KPushButton(KStdGuiItem::ok(), dlg);
|
|
|
|
b->setDefault(true);
|
|
|
|
b->setFixedSize(b->tqsizeHint());
|
|
|
|
|
|
|
|
connect(b, TQT_SIGNAL(released()), dlg, TQT_SLOT(accept()));
|
|
|
|
connect(e, TQT_SIGNAL(returnPressed()), dlg, TQT_SLOT(accept()));
|
|
|
|
|
|
|
|
// create tqlayout
|
|
|
|
TQVBoxLayout *tl = new TQVBoxLayout(dlg, 10);
|
|
|
|
TQHBoxLayout *tl1 = new TQHBoxLayout();
|
|
|
|
tl->addWidget(l1);
|
|
|
|
tl->addSpacing(5);
|
|
|
|
tl->addLayout(tl1);
|
|
|
|
tl1->addWidget(l2);
|
|
|
|
tl1->addWidget(e);
|
|
|
|
tl->addSpacing(5);
|
|
|
|
tl->addWidget(b);
|
|
|
|
tl->activate();
|
|
|
|
tl->freeze();
|
|
|
|
|
|
|
|
dlg->exec();
|
|
|
|
|
|
|
|
lastPlayerName = e->text();
|
|
|
|
delete dlg;
|
|
|
|
|
|
|
|
if(lastPlayerName.isEmpty())
|
|
|
|
return " ";
|
|
|
|
return lastPlayerName;
|
|
|
|
}
|
|
|
|
|
|
|
|
int App::getScore(const HighScore &hs)
|
|
|
|
{
|
|
|
|
double ntiles = hs.x*hs.y;
|
|
|
|
double tilespersec = ntiles/(double)hs.seconds;
|
|
|
|
|
|
|
|
double sizebonus = std::sqrt(ntiles/(double)(14.0 * 6.0));
|
|
|
|
double points = tilespersec / 0.14 * 100.0;
|
|
|
|
|
|
|
|
if(hs.gravity)
|
|
|
|
return (int)(2.0 * points * sizebonus);
|
|
|
|
else
|
|
|
|
return (int)(points * sizebonus);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool App::isBetter(const HighScore &hs, const HighScore &than)
|
|
|
|
{
|
|
|
|
if(getScore(hs) > getScore(than))
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int App::insertHighscore(const HighScore &hs)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if(highscore.size() == 0)
|
|
|
|
{
|
|
|
|
highscore.resize(1);
|
|
|
|
highscore[0] = hs;
|
|
|
|
writeHighscore();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
HighScore last = highscore[highscore.size() - 1];
|
|
|
|
if(isBetter(hs, last) || (highscore.size() < HIGHSCORE_MAX))
|
|
|
|
{
|
|
|
|
if(highscore.size() == HIGHSCORE_MAX)
|
|
|
|
{
|
|
|
|
highscore[HIGHSCORE_MAX - 1] = hs;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
highscore.resize(highscore.size()+1);
|
|
|
|
highscore[highscore.size() - 1] = hs;
|
|
|
|
}
|
|
|
|
|
|
|
|
// sort in new entry
|
|
|
|
int bestsofar = highscore.size() - 1;
|
|
|
|
for(i = highscore.size() - 1; i > 0; i--)
|
|
|
|
{
|
|
|
|
if(isBetter(highscore[i], highscore[i-1]))
|
|
|
|
{
|
|
|
|
// swap entries
|
|
|
|
HighScore temp = highscore[i-1];
|
|
|
|
highscore[i-1] = highscore[i];
|
|
|
|
highscore[i] = temp;
|
|
|
|
bestsofar = i - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
writeHighscore();
|
|
|
|
return bestsofar;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::readHighscore()
|
|
|
|
{
|
|
|
|
TQStringList hi_x, hi_y, hi_sec, hi_date, hi_grav, hi_name;
|
|
|
|
hi_x = highscoreTable->readList("x", HIGHSCORE_MAX);
|
|
|
|
hi_y = highscoreTable->readList("y", HIGHSCORE_MAX);
|
|
|
|
hi_sec = highscoreTable->readList("seconds", HIGHSCORE_MAX);
|
|
|
|
hi_date = highscoreTable->readList("date", HIGHSCORE_MAX);
|
|
|
|
hi_grav = highscoreTable->readList("gravity", HIGHSCORE_MAX);
|
|
|
|
hi_name = highscoreTable->readList("name", HIGHSCORE_MAX);
|
|
|
|
|
|
|
|
highscore.resize(0);
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < hi_x.count(); i++)
|
|
|
|
{
|
|
|
|
highscore.resize(i+1);
|
|
|
|
|
|
|
|
HighScore hs;
|
|
|
|
|
|
|
|
hs.x = hi_x[i].toInt();
|
|
|
|
hs.y = hi_y[i].toInt();
|
|
|
|
hs.seconds = hi_sec[i].toInt();
|
|
|
|
hs.date = hi_date[i].toInt();
|
|
|
|
hs.date = hi_date[i].toInt();
|
|
|
|
hs.gravity = hi_grav[i].toInt();
|
|
|
|
hs.name = hi_name[i];
|
|
|
|
|
|
|
|
highscore[i] = hs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::readOldHighscore()
|
|
|
|
{
|
|
|
|
// this is for before-KHighscore-highscores
|
|
|
|
int i;
|
|
|
|
TQString s, e, grp;
|
|
|
|
KConfig *conf = kapp->config();
|
|
|
|
|
|
|
|
highscore.resize(0);
|
|
|
|
i = 0;
|
|
|
|
bool eol = false;
|
|
|
|
grp = conf->group();
|
|
|
|
conf->setGroup("Hall of Fame");
|
|
|
|
while ((i < (int)HIGHSCORE_MAX) && !eol)
|
|
|
|
{
|
|
|
|
s.sprintf("Highscore_%d", i);
|
|
|
|
if(conf->hasKey(s))
|
|
|
|
{
|
|
|
|
e = conf->readEntry(s);
|
|
|
|
highscore.resize(i+1);
|
|
|
|
|
|
|
|
HighScore hs;
|
|
|
|
|
|
|
|
TQStringList e = conf->readListEntry(s, ' ');
|
|
|
|
int nelem = e.count();
|
|
|
|
hs.x = (*e.at(0)).toInt();
|
|
|
|
hs.y = (*e.at(1)).toInt();
|
|
|
|
hs.seconds = (*e.at(2)).toInt();
|
|
|
|
hs.date = (*e.at(3)).toInt();
|
|
|
|
|
|
|
|
if(nelem == 4) // old version <= 1.1
|
|
|
|
{
|
|
|
|
hs.gravity = 0;
|
|
|
|
hs.name = *e.at(4);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hs.gravity = (*e.at(4)).toInt();
|
|
|
|
hs.name = *e.at(5);
|
|
|
|
}
|
|
|
|
|
|
|
|
highscore[i] = hs;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
eol = true;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// // freshly installed, add my own highscore
|
|
|
|
// if(highscore.size() == 0)
|
|
|
|
// {
|
|
|
|
// HighScore hs;
|
|
|
|
// hs.x = 28;
|
|
|
|
// hs.y = 16;
|
|
|
|
// hs.seconds = 367;
|
|
|
|
// hs.name = "Mario";
|
|
|
|
// highscore.resize(1);
|
|
|
|
// highscore[0] = hs;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// restore old group
|
|
|
|
conf->setGroup(grp);
|
|
|
|
|
|
|
|
// write in new KHighscore format
|
|
|
|
writeHighscore();
|
|
|
|
// read form KHighscore format
|
|
|
|
readHighscore();
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::writeHighscore()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
TQStringList hi_x, hi_y, hi_sec, hi_date, hi_grav, hi_name;
|
|
|
|
for(i = 0; i < (int)highscore.size(); i++)
|
|
|
|
{
|
|
|
|
HighScore hs = highscore[i];
|
|
|
|
hi_x.append(TQString::number(hs.x));
|
|
|
|
hi_y.append(TQString::number(hs.y));
|
|
|
|
hi_sec.append(TQString::number(hs.seconds));
|
|
|
|
hi_date.append(TQString::number(hs.date));
|
|
|
|
hi_grav.append(TQString::number(hs.gravity));
|
|
|
|
hi_name.append(hs.name);
|
|
|
|
}
|
|
|
|
highscoreTable->writeList("x", hi_x);
|
|
|
|
highscoreTable->writeList("y", hi_y);
|
|
|
|
highscoreTable->writeList("seconds", hi_sec);
|
|
|
|
highscoreTable->writeList("date", hi_date);
|
|
|
|
highscoreTable->writeList("gravity", hi_grav);
|
|
|
|
highscoreTable->writeList("name", hi_name);
|
|
|
|
highscoreTable->sync();
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::showHighscore(int focusitem)
|
|
|
|
{
|
|
|
|
// this may look a little bit confusing...
|
|
|
|
TQDialog *dlg = new TQDialog(0, "hall_Of_fame", true);
|
|
|
|
dlg->setCaption(i18n("Hall of Fame"));
|
|
|
|
|
|
|
|
TQVBoxLayout *tl = new TQVBoxLayout(dlg, 10);
|
|
|
|
|
|
|
|
TQLabel *l = new TQLabel(i18n("Hall of Fame"), dlg);
|
|
|
|
TQFont f = font();
|
|
|
|
f.setPointSize(24);
|
|
|
|
f.setBold(true);
|
|
|
|
l->setFont(f);
|
|
|
|
l->setFixedSize(l->tqsizeHint());
|
|
|
|
l->setFixedWidth(l->width() + 32);
|
|
|
|
l->tqsetAlignment(AlignCenter);
|
|
|
|
tl->addWidget(l);
|
|
|
|
|
|
|
|
// insert highscores in a gridtqlayout
|
|
|
|
TQGridLayout *table = new TQGridLayout(12, 5, 5);
|
|
|
|
tl->addLayout(table, 1);
|
|
|
|
|
|
|
|
// add a separator line
|
|
|
|
KSeparator *sep = new KSeparator(dlg);
|
|
|
|
table->addMultiCellWidget(sep, 1, 1, 0, 4);
|
|
|
|
|
|
|
|
// add titles
|
|
|
|
f = font();
|
|
|
|
f.setBold(true);
|
|
|
|
l = new TQLabel(i18n("Rank"), dlg);
|
|
|
|
l->setFont(f);
|
|
|
|
l->setMinimumSize(l->tqsizeHint());
|
|
|
|
table->addWidget(l, 0, 0);
|
|
|
|
l = new TQLabel(i18n("Name"), dlg);
|
|
|
|
l->setFont(f);
|
|
|
|
l->setMinimumSize(l->tqsizeHint());
|
|
|
|
table->addWidget(l, 0, 1);
|
|
|
|
l = new TQLabel(i18n("Time"), dlg);
|
|
|
|
l->setFont(f);
|
|
|
|
l->setMinimumSize(l->tqsizeHint());
|
|
|
|
table->addWidget(l, 0, 2);
|
|
|
|
l = new TQLabel(i18n("Size"), dlg);
|
|
|
|
l->setFont(f);
|
|
|
|
l->setMinimumSize(l->tqsizeHint());
|
|
|
|
table->addWidget(l, 0, 3);
|
|
|
|
l = new TQLabel(i18n("Score"), dlg);
|
|
|
|
l->setFont(f);
|
|
|
|
l->setMinimumSize(l->tqsizeHint().width()*3, l->tqsizeHint().height());
|
|
|
|
table->addWidget(l, 0, 4);
|
|
|
|
|
|
|
|
TQString s;
|
|
|
|
TQLabel *e[10][5];
|
|
|
|
unsigned i, j;
|
|
|
|
|
|
|
|
for(i = 0; i < 10; i++)
|
|
|
|
{
|
|
|
|
HighScore hs;
|
|
|
|
if(i < highscore.size())
|
|
|
|
hs = highscore[i];
|
|
|
|
|
|
|
|
// insert rank
|
|
|
|
s.sprintf("%d", i+1);
|
|
|
|
e[i][0] = new TQLabel(s, dlg);
|
|
|
|
|
|
|
|
// insert name
|
|
|
|
if(i < highscore.size())
|
|
|
|
e[i][1] = new TQLabel(hs.name, dlg);
|
|
|
|
else
|
|
|
|
e[i][1] = new TQLabel("", dlg);
|
|
|
|
|
|
|
|
// insert time
|
|
|
|
TQTime ti(0,0,0);
|
|
|
|
if(i < highscore.size())
|
|
|
|
{
|
|
|
|
ti = ti.addSecs(hs.seconds);
|
|
|
|
s.sprintf("%02d:%02d:%02d", ti.hour(), ti.minute(), ti.second());
|
|
|
|
e[i][2] = new TQLabel(s, dlg);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
e[i][2] = new TQLabel("", dlg);
|
|
|
|
}
|
|
|
|
|
|
|
|
// insert size
|
|
|
|
if(i < highscore.size())
|
|
|
|
s.sprintf("%d x %d", hs.x, hs.y);
|
|
|
|
else
|
|
|
|
s = "";
|
|
|
|
|
|
|
|
e[i][3] = new TQLabel(s, dlg);
|
|
|
|
|
|
|
|
// insert score
|
|
|
|
if(i < highscore.size())
|
|
|
|
{
|
|
|
|
s = TQString("%1 %2")
|
|
|
|
.tqarg(getScore(hs))
|
|
|
|
.tqarg(hs.gravity ? i18n("(gravity)") : TQString(""));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
s = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
e[i][4] = new TQLabel(s, dlg);
|
|
|
|
e[i][4]->tqsetAlignment(AlignRight);
|
|
|
|
}
|
|
|
|
|
|
|
|
f = font();
|
|
|
|
f.setBold(true);
|
|
|
|
f.setItalic(true);
|
|
|
|
for(i = 0; i < 10; i++)
|
|
|
|
{
|
|
|
|
for(j = 0; j < 5; j++)
|
|
|
|
{
|
|
|
|
e[i][j]->setMinimumHeight(e[i][j]->tqsizeHint().height());
|
|
|
|
|
|
|
|
if(j == 1)
|
|
|
|
e[i][j]->setMinimumWidth(std::max(e[i][j]->tqsizeHint().width(), 100));
|
|
|
|
else
|
|
|
|
e[i][j]->setMinimumWidth(std::max(e[i][j]->tqsizeHint().width(), 60));
|
|
|
|
|
|
|
|
if((int)i == focusitem)
|
|
|
|
e[i][j]->setFont(f);
|
|
|
|
|
|
|
|
table->addWidget(e[i][j], i+2, j, AlignCenter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQPushButton *b = new KPushButton(KStdGuiItem::close(), dlg);
|
|
|
|
|
|
|
|
b->setFixedSize(b->tqsizeHint());
|
|
|
|
|
|
|
|
// connect the "Close"-button to done
|
|
|
|
connect(b, TQT_SIGNAL(clicked()), dlg, TQT_SLOT(accept()));
|
|
|
|
b->setDefault(true);
|
|
|
|
b->setFocus();
|
|
|
|
|
|
|
|
// make tqlayout
|
|
|
|
tl->addSpacing(10);
|
|
|
|
tl->addWidget(b);
|
|
|
|
tl->activate();
|
|
|
|
tl->freeze();
|
|
|
|
|
|
|
|
dlg->exec();
|
|
|
|
delete dlg;
|
|
|
|
}
|
|
|
|
|
|
|
|
void App::keyBindings()
|
|
|
|
{
|
|
|
|
KKeyDialog::configure(actionCollection(), this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Show Settings dialog.
|
|
|
|
*/
|
|
|
|
void App::showSettings(){
|
|
|
|
if(KConfigDialog::showDialog("settings"))
|
|
|
|
return;
|
|
|
|
|
|
|
|
KConfigDialog *dialog = new KConfigDialog(this, "settings", Prefs::self(), KDialogBase::Swallow);
|
|
|
|
Settings *general = new Settings(0, "General");
|
|
|
|
dialog->addPage(general, i18n("General"), "package_settings");
|
|
|
|
connect(dialog, TQT_SIGNAL(settingsChanged()), TQT_TQOBJECT(this), TQT_SLOT(loadSettings()));
|
|
|
|
connect(dialog, TQT_SIGNAL(settingsChanged()), board, TQT_SLOT(loadSettings()));
|
|
|
|
dialog->show();
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "app.moc"
|