Commit 9162ed88 authored by Waldo Bastian's avatar Waldo Bastian
Browse files

WABA: bug fixes for kmines (some showstoppers, some not)

Patch by Nicolas HADACEK <azhyd@free.fr>

svn path=/trunk/kdegames/kmines/; revision=61775
parent 49e9ac47
2.0.6
* use of KMainWindow (replace KTMainWindow) but this does not solve the
resizing problems :(
* pause game when high scores requested
* custom game settings are saved [feature suggested by Toan Nguyen,
Williaw Barnes and François-Xavier Duranceau]
* solve the resizing problems by intercepting the Layout Hint event ...
(due to limitations in K/QMainWindow IMHO)
2.0.5
* default for mouse binding changed
* added color configuration for numbers, flag and explosion (for B&W monitors)
* added color configuration for numbers, flag and explosion (for B&W monitors
and few-colors themes) [feature suggested by Hume Smith and François-Xavier
Duranceau]
* moved around some things about configuration (cleaned up "defines.h")
* case state is now more clean (but some bugs might have crept in)
* properly mark all the flagged cases with no mine to error on game end
* versioning the XMLGUI file
2.0.4
* hack to resize correctly when menu is hidden (due to bugs
......
......@@ -5,7 +5,7 @@ Distributed under the GNU General Public License
This is a very classical minesweeper written from scratch
with three predefined levels + custom levels.
with three predefined levels and custom levels.
Easy : 8x8 with 10 mines
Normal : 16x16 with 40 mines
......
IDEAS:
* 3 button mouse emulation [someone needed it for wheel mouse : I think
it should be done at a higher level ...]
* do you have any idea ?
KNOWN BUGS:
* none !
* remove the comment around the I18N_NOOP call in main.cpp after 2.0
......@@ -98,24 +98,29 @@ void DigitalClock::zero()
}
//-----------------------------------------------------------------------------
const uint MIN_CUSTOM_SIZE = 8;
const uint MAX_CUSTOM_SIZE = 50;
CustomDialog::CustomDialog(Level &_lev, QWidget *parent)
: KDialogBase(Plain, i18n("Customize your game"), Ok|Cancel, Cancel,
parent, 0, true, true),
lev(_lev), initLev(_lev)
{
lev.type = Custom;
QVBoxLayout *top = new QVBoxLayout(plainPage(), spacingHint());
// width
KIntNumInput *ki = new KIntNumInput(lev.width, plainPage());
ki->setLabel(i18n("Width"));
ki->setRange(8, 50);
ki->setRange(MIN_CUSTOM_SIZE, MAX_CUSTOM_SIZE);
connect(ki, SIGNAL(valueChanged(int)), SLOT(widthChanged(int)));
top->addWidget(ki);
// height
ki = new KIntNumInput(lev.height, plainPage());
ki->setLabel(i18n("Height"));
ki->setRange(8, 50);
ki->setRange(MIN_CUSTOM_SIZE, MAX_CUSTOM_SIZE);
connect(ki, SIGNAL(valueChanged(int)), SLOT(heightChanged(int)));
top->addWidget(ki);
......@@ -146,13 +151,18 @@ void CustomDialog::nbMinesChanged(int n)
void CustomDialog::updateNbMines()
{
km->setRange(1, maxNbMines(lev.width, lev.height));
uint nb = lev.width * lev.height;
km->setRange(1, nb - 2);
km->setLabel(i18n("Mines (%1%)").arg(100*lev.nbMines/nb));
enableButton(Ok, lev.width!=initLev.width || lev.height!=initLev.height
|| lev.nbMines!=initLev.nbMines);
}
uint CustomDialog::maxNbMines(uint width, uint height)
{
return width*height - 2;
}
//-----------------------------------------------------------------------------
const char *HS_NAME = "Name";
const char *HS_MIN = "Min";
......@@ -280,12 +290,15 @@ void WHighScores::reject()
}
//-----------------------------------------------------------------------------
const char *OP_GRP = "Options";
const char *OP_UMARK = "? mark";
const char *OP_MENUBAR = "menubar visible";
const char *OP_LEVEL = "Level";
const char *OP_CASE_SIZE = "case size";
const char *OP_KEYBOARD = "keyboard game";
const char *OP_GRP = "Options";
const char *OP_UMARK = "? mark";
const char *OP_MENUBAR = "menubar visible";
const char *OP_LEVEL = "Level";
const char *OP_CUSTOM_WIDTH = "custom width";
const char *OP_CUSTOM_HEIGHT = "custom height";
const char *OP_CUSTOM_MINES = "custom mines";
const char *OP_CASE_SIZE = "case size";
const char *OP_KEYBOARD = "keyboard game";
const char *OP_MOUSE_BINDINGS[3] =
{ "mouse left", "mouse mid", "mouse right" };
const char *OP_NUMBER_COLOR = "color #";
......@@ -422,16 +435,33 @@ bool OptionDialog::readKeyboard()
return config()->readBoolEntry(OP_KEYBOARD, true);
}
GameType OptionDialog::readLevel()
Level OptionDialog::readLevel()
{
GameType lev = (GameType)config()->readUnsignedNumEntry(OP_LEVEL, 0);
return lev>=Custom ? Easy : lev;
Level l;
l.type = (GameType)config()->readUnsignedNumEntry(OP_LEVEL, 0);
if ( l.type>Custom ) l.type = Easy;
if ( l.type==Custom ) {
l.width = config()->readUnsignedNumEntry(OP_CUSTOM_WIDTH, 0);
l.width = QMAX(QMIN(l.width, MAX_CUSTOM_SIZE), MIN_CUSTOM_SIZE);
l.height = config()->readUnsignedNumEntry(OP_CUSTOM_HEIGHT, 0);
l.height = QMAX(QMIN(l.height, MAX_CUSTOM_SIZE), MIN_CUSTOM_SIZE);
l.nbMines = config()->readUnsignedNumEntry(OP_CUSTOM_MINES, 0);
l.nbMines = QMAX(QMIN(l.nbMines,
CustomDialog::maxNbMines(l.width, l.height)), 1);
} else l = LEVELS[l.type];
return l;
}
void OptionDialog::writeLevel(GameType lev)
void OptionDialog::writeLevel(const Level &l)
{
if ( lev>=Custom ) return;
config()->writeEntry(OP_LEVEL, (uint)lev);
if ( l.type==Custom ) {
config()->writeEntry(OP_CUSTOM_WIDTH, l.width);
config()->writeEntry(OP_CUSTOM_HEIGHT, l.height);
config()->writeEntry(OP_CUSTOM_MINES, l.nbMines);
}
config()->writeEntry(OP_LEVEL, (uint)l.type);
}
bool OptionDialog::readMenuVisible()
......
......@@ -82,6 +82,8 @@ class CustomDialog : public KDialogBase
public:
CustomDialog(Level &lev, QWidget *parent);
static uint maxNbMines(uint width, uint height);
private slots:
void widthChanged(int);
void heightChanged(int);
......@@ -123,8 +125,8 @@ class OptionDialog : public KDialogBase
static CaseProperties readCaseProperties();
static bool readUMark();
static bool readKeyboard();
static GameType readLevel();
static void writeLevel(GameType);
static Level readLevel();
static void writeLevel(const Level &);
static bool readMenuVisible();
static void writeMenuVisible(bool visible);
static MouseAction readMouseBinding(MouseButton);
......
......@@ -244,7 +244,7 @@ int Field::jToY(uint j) const
int Field::xToI(int x) const
{
// the cast is necessary when x-frameWidth() is negative ( ?? )
// the cast is necessary when x-frameWidth() is negative ( ? )
return (int)((double)(x - frameWidth())/cp.size) + 1;
}
......
......@@ -18,7 +18,7 @@
#include "status.h"
MainWidget::MainWidget()
: levelAction(NbLevels)
: KMainWindow(0), levelAction(NbLevels)
{
installEventFilter(this);
......@@ -29,7 +29,7 @@ MainWidget::MainWidget()
connect(status, SIGNAL(gameStateChanged(GameState)),
SLOT(gameStateChanged(GameState)));
connect(status, SIGNAL(message(const QString &)),
SLOT(message(const QString &)));
statusBar(), SLOT(message(const QString &)));
// Game & Popup
KStdAction::openNew(status, SLOT(restartGame()),
......@@ -97,8 +97,7 @@ MainWidget::MainWidget()
createGUI();
readSettings();
setView(status);
updateRects(); // #### should be in KTMainWindow::setView
setCentralWidget(status);
}
#define MENUBAR_ACTION \
......@@ -108,9 +107,9 @@ MainWidget::MainWidget()
void MainWidget::readSettings()
{
GameType type = OptionDialog::readLevel();
levelAction[type]->setChecked(true);
status->newGame(type);
Level l = OptionDialog::readLevel();
if ( l.type!=Custom ) levelAction[l.type]->setChecked(true);
status->newGame(l);
bool visible = OptionDialog::readMenuVisible();
MENUBAR_ACTION->setChecked(visible);
......@@ -122,25 +121,39 @@ void MainWidget::readSettings()
void MainWidget::changeLevel(uint i)
{
if ( !levelAction[i]->isChecked() ) return;
GameType lev = (GameType)i;
if ( !status->newGame(lev) ) { // level unchanged
levelAction[lev]->setChecked(true);
return;
}
OptionDialog::writeLevel(lev);
GameType type = (GameType)i;
Level l;
if ( type==Custom ) {
levelAction[Custom]->setChecked(false);
l = status->currentLevel();
type = l.type;
CustomDialog cu(l, this);
if ( !cu.exec() ) { // level unchanged
if ( type!=Custom ) levelAction[type]->setChecked(true);
return;
}
} else l = LEVELS[i];
status->newGame(l);
OptionDialog::writeLevel(l);
}
bool MainWidget::eventFilter(QObject *, QEvent *e)
{
QPopupMenu *popup;
switch (e->type()) {
case QEvent::MouseButtonPress :
case QEvent::MouseButtonPress :
if ( ((QMouseEvent *)e)->button()!=RightButton ) return false;
popup = (QPopupMenu*)factory()->container("popup", this);
if ( popup ) popup->popup(QCursor::pos());
return true;
default : return false;
case QEvent::LayoutHint:
setFixedSize(minimumSize()); // because QMainWindow and KMainWindow
// do not manage fixed central widget and
// hidden menubar ...
return false;
default : return false;
}
}
......@@ -148,15 +161,7 @@ void MainWidget::toggleMenubar()
{
bool b = MENUBAR_ACTION->isChecked();
if (b) menuBar()->show();
else {
menuBar()->hide();
// #### sort of hack : because KTMainWindow does not manage correctly
// main widget with a fixed layout
updateRects();
adjustSize();
}
else menuBar()->hide();
OptionDialog::writeMenuVisible(b);
}
......@@ -192,11 +197,6 @@ void MainWidget::gameStateChanged(GameState s)
}
}
void MainWidget::message(const QString &text)
{
statusBar()->message(text);
}
//----------------------------------------------------------------------------
static const char *DESCRIPTION
= I18N_NOOP("KMines is a classical mine sweeper game.");
......@@ -206,8 +206,8 @@ int main(int argc, char **argv)
KAboutData aboutData("kmines", I18N_NOOP("KMines"), LONG_VERSION,
DESCRIPTION, KAboutData::License_GPL,
COPYLEFT, 0, HOMEPAGE);
aboutData.addAuthor("Nicolas Hadacek", 0, "hadacek@kde.org");
aboutData.addCredit("Andreas Zehender", "Smiley pixmaps");
aboutData.addAuthor("Nicolas Hadacek", 0, EMAIL);
aboutData.addCredit("Andreas Zehender", /*I18N_NOOP(*/"Smiley pixmaps"/*)*/);
KCmdLineArgs::init(argc, argv, &aboutData);
KApplication a;
......
#ifndef MAIN_H
#define MAIN_H
#include <ktmainwindow.h>
#include <kmainwindow.h>
#include <kaction.h>
#include "defines.h"
class Status;
class MainWidget : public KTMainWindow
class MainWidget : public KMainWindow
{
Q_OBJECT
......@@ -23,7 +23,6 @@ class MainWidget : public KTMainWindow
void toggleMenubar();
void configureKeys();
void setKeyboardEnabled(bool);
void message(const QString &);
void gameStateChanged(GameState);
protected:
......
......@@ -95,22 +95,10 @@ void Status::restartGame()
initGame();
}
bool Status::newGame(GameType &t)
void Status::newGame(const Level &l)
{
Level lev;
if ( t==Custom ) {
lev = field->level();
CustomDialog cu(lev, this);
if ( !cu.exec() ) {
t = lev.type;
return false;
}
lev.type = Custom;
} else lev = LEVELS[t];
field->setLevel(lev);
field->setLevel(l);
initGame();
return true;
}
void Status::changeCase(CaseState cs, uint inc)
......@@ -160,6 +148,14 @@ void Status::_endGame(bool win)
}
}
void Status::showHighScores()
{
field->pause();
WHighScores whs(this, 0);
whs.exec();
field->pause();
}
void Status::highScores(const Score *score)
{
WHighScores whs(this, score);
......
......@@ -20,7 +20,8 @@ class Status : public QWidget
public :
Status(QWidget *parent=0, const char *name=0);
bool newGame(GameType &);
void newGame(const Level &);
const Level &currentLevel() const { return field->level(); }
signals:
void keyboardEnabled(bool);
......@@ -32,7 +33,7 @@ class Status : public QWidget
void changeCase(CaseState, uint inc);
void update(bool);
void endGame() { _endGame(false); }
void showHighScores() { highScores(0); }
void showHighScores();
void pauseGame() { field->pause(); }
void print();
void preferences();
......
#define VERSION "2.0.5"
#define LONG_VERSION "2.0.5 (14 June 2000)"
#define VERSION "2.0.6"
#define LONG_VERSION "2.0.6 (21 August 2000)"
#define COPYLEFT "(c) 1996-2000, Nicolas Hadacek"
#define EMAIL "hadacek@kde.org"
#define HOMEPAGE "http://azhyd.free.fr/KDE/kmines.php3"
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment