Commit c648f861 authored by Nicolas Hadacek's avatar Nicolas Hadacek
Browse files

- color configuration (for B&W monitor)

- statusbar
- "better field" at end of game
- no more (unstandard) title in dialogs
- and ... XMLGUI versionning ! :)

result : no more thing in my TODO list :) ... :(

svn path=/trunk/kdegames/kmines/; revision=53235
parent 4c87a36b
2.0.5
* default for mouse binding changed
* added color configuration for numbers, flag and explosion (for B&W monitors)
* 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
2.0.4
* hack to resize correctly when menu is hidden (due to bugs
in KTMainWindow)
* nicer (and simpler) custom level with KNumIntInput
* nicer (and simpler) custom level dialog with KNumIntInput
* kstatusbar in place of the label
* remove the title in dialogs (more consistent with other apps)
2.0.3
* use kkeydialog for actions
......
......@@ -4,13 +4,12 @@ Copyright (c) 1996-2000 Nicolas HADACEK (hadacek@kde.org)
Distributed under the GNU General Public License
This is a very classical minesweeper written from scratch.
- 3 predefined levels :
Easy : 8x8 with 10 mines
Normal : 16x16 with 40 mines
Expert : 30x16 with 99 mines
- custom levels
This is a very classical minesweeper written from scratch
with three predefined levels + custom levels.
Easy : 8x8 with 10 mines
Normal : 16x16 with 40 mines
Expert : 30x16 with 99 mines
Requirements : uptodate KDE and QT libraries.
IDEAS:
* do you have any idea ?
* kstatusbar ? (we need to be sure the text is completely visible :
should be ok since it is not long texts)
* option to change number of mines colors for B&W/strange display
KNOWN BUGS:
......
#include "defines.h"
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_MOUSE_BINDINGS[3]
= { "mouse left", "mouse mid", "mouse right" };
const char *HS_NAME = "Name";
const char *HS_MIN = "Min";
const char *HS_SEC = "Sec";
const char *HS_GRP[3] = { "Easy level", "Normal level", "Expert level" };
const uint CASE_SIZE = 20;
const uint MIN_CASE_SIZE = 20;
const uint MAX_CASE_SIZE = 100;
const Level LEVELS[NbLevels-1] = {
{8, 8, 10, Easy },
{16, 16, 40, Normal},
......
#ifndef DEFINES_H
#define DEFINES_H
#include <qglobal.h>
/* Strings for the configuration file */
extern const char *OP_GRP;
extern const char *OP_UMARK;
extern const char *OP_MENUBAR;
extern const char *OP_LEVEL;
extern const char *OP_CASE_SIZE;
extern const char *OP_KEYBOARD;
extern const char *OP_MOUSE_BINDINGS[3];
extern const char *HS_NAME;
extern const char *HS_MIN;
extern const char *HS_SEC;
/* States of a case (unsigned int) */
#define NOTHING 0
#define MINE 1
#define COVERED 2
#define UNCERTAIN 4
#define MARKED 8
#define UNCOVERED 16
#define EXPLODED 32
#define ERROR 64
/* Default case size */
extern const uint CASE_SIZE;
extern const uint MIN_CASE_SIZE;
extern const uint MAX_CASE_SIZE;
#include <qcolor.h>
enum CaseState { Covered, Uncovered, Uncertain, Marked, Exploded, Error };
struct Case {
bool mine;
CaseState state;
};
enum GameType { Easy = 0, Normal, Expert, Custom, NbLevels };
enum GameState { Stopped, Playing, Paused, GameOver };
enum MouseAction { Reveal = 0, Mark, AutoReveal, UMark };
enum MouseAction { Reveal = 0, AutoReveal, Mark, UMark };
enum MouseButton { Left = 0, Mid, Right };
struct Level {
......@@ -41,11 +19,18 @@ struct Level {
GameType type;
};
extern const Level LEVELS[NbLevels-1];
extern const char *HS_GRP[NbLevels-1];
struct Score {
uint sec, min;
GameType type;
};
#define NB_NUMBER_COLORS 8
struct CaseProperties {
uint size;
QColor numberColors[NB_NUMBER_COLORS];
QColor flagColor, explosionColor, errorColor;
};
#endif // DEFINES_H
......@@ -5,6 +5,8 @@
#include <qpushbutton.h>
#include <qfont.h>
#include <qvgroupbox.h>
#include <qlayout.h>
#include <qhbox.h>
#include <kapp.h>
#include <klocale.h>
......@@ -39,8 +41,8 @@ LCDNumber::LCDNumber(QWidget *parent, const char *name)
QPalette p = palette();
p.setColor(QColorGroup::Foreground, white);
setPalette(p);
state = TRUE;
setState(FALSE);
state = true;
setState(false);
}
void LCDNumber::setState(bool _state)
......@@ -68,7 +70,7 @@ void DigitalClock::timerEvent( QTimerEvent *)
_sec = 0;
}
showTime();
if ( toSec(_sec, _min)==max_secs ) setState(TRUE);
if ( toSec(_sec, _min)==max_secs ) setState(true);
}
}
......@@ -87,41 +89,22 @@ void DigitalClock::zero()
{
killTimers();
stop = TRUE;
stop = true;
_sec = 0; _min = 0;
startTimer(1000); // 1 seconde
setState(FALSE);
setState(false);
showTime();
}
//-----------------------------------------------------------------------------
DialogBase::DialogBase(const QString &caption, int buttonMask,
ButtonCode defaultButton,
QWidget *parent, const char *name)
: KDialogBase(Plain, caption, buttonMask ,defaultButton, parent, name, TRUE,
TRUE)
{
// top layout
top = new QVBoxLayout(plainPage(), spacingHint());
top->setResizeMode(QLayout::Fixed);
// title
QLabel *lab = new QLabel(caption, plainPage());
QFont f( font() );
f.setBold(TRUE);
lab->setFont(f);
lab->setAlignment(AlignCenter);
lab->setFrameStyle(QFrame::Panel | QFrame::Raised);
top->addWidget(lab);
top->addSpacing(2*spacingHint());
}
//-----------------------------------------------------------------------------
CustomDialog::CustomDialog(Level &_lev, QWidget *parent)
: DialogBase(i18n("Customize your game"), Ok|Cancel, Cancel, parent),
: KDialogBase(Plain, i18n("Customize your game"), Ok|Cancel, Cancel,
parent, 0, true, true),
lev(_lev), initLev(_lev)
{
QVBoxLayout *top = new QVBoxLayout(plainPage(), spacingHint());
// width
KIntNumInput *ki = new KIntNumInput(lev.width, plainPage());
ki->setLabel(i18n("Width"));
......@@ -171,6 +154,12 @@ void CustomDialog::updateNbMines()
}
//-----------------------------------------------------------------------------
const char *HS_NAME = "Name";
const char *HS_MIN = "Min";
const char *HS_SEC = "Sec";
const char *HS_GRP[NbLevels-1] =
{ "Easy level", "Normal level", "Expert level" };
uint WHighScores::time(GameType type)
{
KConfig *conf = kapp->config();
......@@ -184,7 +173,9 @@ uint WHighScores::time(GameType type)
}
WHighScores::WHighScores(QWidget *parent, const Score *score)
: DialogBase(i18n("Hall of Fame"), Close, Close, parent), qle(0)
: KDialogBase(Plain, i18n("Hall of Fame"), Close, Close,
parent, 0, true, true),
qle(0)
{
KConfig *conf = kapp->config();
......@@ -198,7 +189,9 @@ WHighScores::WHighScores(QWidget *parent, const Score *score)
QLabel *lab;
QFont f( font() );
f.setBold(TRUE);
f.setBold(true);
QVBoxLayout *top = new QVBoxLayout(plainPage(), spacingHint());
/* Grid layout */
QGridLayout *gl = new QGridLayout(3, 4, spacingHint());
......@@ -221,7 +214,7 @@ WHighScores::WHighScores(QWidget *parent, const Score *score)
conf->setGroup(HS_GRP[k]);
int min = conf->readNumEntry(HS_MIN, 0);
int sec = conf->readNumEntry(HS_SEC, 0);
bool no_score = FALSE;
bool no_score = false;
if ( !score || (k!=type) ) {
lab = new QLabel(plainPage());
......@@ -262,7 +255,7 @@ WHighScores::WHighScores(QWidget *parent, const Score *score)
gl->addWidget(lab, k, 3);
}
if (score) enableButton(Close, FALSE);
if (score) enableButton(Close, false);
}
void WHighScores::writeName()
......@@ -274,47 +267,85 @@ void WHighScores::writeName()
conf->sync();
str = conf->readEntry(HS_NAME);
qle->setText(str);
enableButton(Close, TRUE);
enableButton(Close, true);
}
void WHighScores::reject()
{
if ( qle && qle->isEnabled() ) {
qle->setEnabled(FALSE);
focusNextPrevChild(TRUE); // sort of hack (wonder why its call in
// setEnabled(FALSE) does nothing ...)
} else DialogBase::reject();
qle->setEnabled(false);
focusNextPrevChild(true); // sort of hack (wonder why its call in
// setEnabled(false) does nothing ...)
} else KDialogBase::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_MOUSE_BINDINGS[3] =
{ "mouse left", "mouse mid", "mouse right" };
const char *OP_NUMBER_COLOR = "color #";
const char *OP_FLAG_COLOR = "flag color";
const char *OP_EXPLOSION_COLOR = "explosion color";
const char *OP_ERROR_COLOR = "error color";
#define NCName(i) QString("%1%2").arg(OP_NUMBER_COLOR).arg(i)
const uint MIN_CASE_SIZE = 20;
const uint DEFAULT_CASE_SIZE = MIN_CASE_SIZE;
const uint MAX_CASE_SIZE = 100;
const QColor DEFAULT_NUMBER_COLORS[NB_NUMBER_COLORS] =
{ Qt::blue, Qt::darkGreen, Qt::darkYellow, Qt::darkMagenta, Qt::red,
Qt::darkRed, Qt::black, Qt::black };
const QColor DEFAULT_FLAG_COLOR = Qt::red;
const QColor DEFAULT_EXPLOSION_COLOR = Qt::red;
const QColor DEFAULT_ERROR_COLOR = Qt::red;
OptionDialog::OptionDialog(QWidget *parent)
: DialogBase(i18n("Settings"), Ok|Cancel, Cancel, parent)
: KDialogBase(Tabbed, i18n("Settings"), Ok|Cancel|Default, Cancel,
parent, 0, true, true)
{
ni = new KIntNumInput(readCaseSize(), plainPage());
mainPage();
casePage();
}
void OptionDialog::mainPage()
{
QFrame *page = addPage(i18n("Main settings"));
QVBoxLayout *top = new QVBoxLayout(page, spacingHint());
ni = new KIntNumInput(readCaseSize(), page);
ni->setRange(MIN_CASE_SIZE, MAX_CASE_SIZE);
ni->setLabel(i18n("Case size"));
top->addWidget(ni);
top->addSpacing(spacingHint());
um = new QCheckBox(i18n("Enable ? mark"), plainPage());
um = new QCheckBox(i18n("Enable ? mark"), page);
um->setChecked(readUMark());
top->addWidget(um);
keyb = new QCheckBox(i18n("Enable keyboard"), plainPage());
keyb = new QCheckBox(i18n("Enable keyboard"), page);
keyb->setChecked(readKeyboard());
top->addWidget(keyb);
top->addSpacing(spacingHint());
QVGroupBox *gb = new QVGroupBox(i18n("Mouse bindings"), plainPage());
QVGroupBox *gb = new QVGroupBox(i18n("Mouse bindings"), page);
top->addWidget(gb);
QGrid *grid = new QGrid(2, gb);
grid->setSpacing(spacingHint());
QLabel *lab = new QLabel(i18n("Left button"), grid);
cb[Left] = new QComboBox(FALSE, grid);
cb[Left] = new QComboBox(false, grid);
lab = new QLabel(i18n("Mid button"), grid);
cb[Mid] = new QComboBox(FALSE, grid);
cb[Mid] = new QComboBox(false, grid);
lab = new QLabel(i18n("Right button"), grid);
cb[Right] = new QComboBox(FALSE, grid);
cb[Right] = new QComboBox(false, grid);
top->addStretch(1);
for (uint i=0; i<3; i++) {
cb[i]->insertItem(i18n("reveal"), 0);
......@@ -325,6 +356,38 @@ OptionDialog::OptionDialog(QWidget *parent)
}
}
void OptionDialog::casePage()
{
QFrame *page = addPage(i18n("Color settings"));
QVBoxLayout *top = new QVBoxLayout(page, spacingHint());
CaseProperties cp = readCaseProperties();
QHBox *hbox = new QHBox(page);
top->addWidget(hbox);
(void)new QLabel(i18n("Flag color"), hbox);
flagButton = new KColorButton(cp.flagColor, hbox);
hbox = new QHBox(page);
top->addWidget(hbox);
(void)new QLabel(i18n("Explosion color"), hbox);
explosionButton = new KColorButton(cp.explosionColor, hbox);
hbox = new QHBox(page);
top->addWidget(hbox);
(void)new QLabel(i18n("Error color"), hbox);
errorButton = new KColorButton(cp.errorColor, hbox);
numberButtons.resize(NB_NUMBER_COLORS);
for (uint i=0; i<NB_NUMBER_COLORS; i++) {
hbox = new QHBox(page);
top->addWidget(hbox);
(void)new QLabel(i==0 ? i18n("One mine color")
: i18n("%1 mines color").arg(i+1), hbox);
numberButtons[i] = new KColorButton(cp.numberColors[i], hbox);
}
}
KConfig *OptionDialog::config()
{
KConfig *conf = kapp->config();
......@@ -335,29 +398,28 @@ KConfig *OptionDialog::config()
void OptionDialog::accept()
{
KConfig *conf = config();
conf->writeEntry(OP_CASE_SIZE, ni->value());
conf->writeEntry(OP_UMARK, um->isChecked());
conf->writeEntry(OP_KEYBOARD, keyb->isChecked());
for (uint i=0; i<3; i++)
conf->writeEntry(OP_MOUSE_BINDINGS[i], cb[i]->currentItem());
conf->writeEntry(OP_CASE_SIZE, ni->value());
conf->writeEntry(OP_FLAG_COLOR, flagButton->color());
conf->writeEntry(OP_EXPLOSION_COLOR, explosionButton->color());
conf->writeEntry(OP_ERROR_COLOR, errorButton->color());
for (uint i=0; i<NB_NUMBER_COLORS; i++)
conf->writeEntry(NCName(i), numberButtons[i]->color());
DialogBase::accept();
}
uint OptionDialog::readCaseSize()
{
uint cs = config()->readUnsignedNumEntry(OP_CASE_SIZE, CASE_SIZE);
return QMAX(QMIN(cs, MAX_CASE_SIZE), MIN_CASE_SIZE);
KDialogBase::accept();
}
bool OptionDialog::readUMark()
{
return config()->readBoolEntry(OP_UMARK, TRUE);
return config()->readBoolEntry(OP_UMARK, true);
}
bool OptionDialog::readKeyboard()
{
return config()->readBoolEntry(OP_KEYBOARD, TRUE);
return config()->readBoolEntry(OP_KEYBOARD, true);
}
GameType OptionDialog::readLevel()
......@@ -374,7 +436,7 @@ void OptionDialog::writeLevel(GameType lev)
bool OptionDialog::readMenuVisible()
{
return config()->readBoolEntry(OP_MENUBAR, TRUE);
return config()->readBoolEntry(OP_MENUBAR, true);
}
void OptionDialog::writeMenuVisible(bool visible)
......@@ -388,3 +450,40 @@ MouseAction OptionDialog::readMouseBinding(MouseButton mb)
->readUnsignedNumEntry(OP_MOUSE_BINDINGS[mb], mb);
return ma>UMark ? Reveal : ma;
}
QColor OptionDialog::readColor(const char *key, QColor defaultColor)
{
return config()->readColorEntry(key, &defaultColor);
}
uint OptionDialog::readCaseSize()
{
uint cs = config()->readUnsignedNumEntry(OP_CASE_SIZE, DEFAULT_CASE_SIZE);
cs = QMAX(QMIN(cs, MAX_CASE_SIZE), MIN_CASE_SIZE);
return cs;
}
CaseProperties OptionDialog::readCaseProperties()
{
CaseProperties cp;
cp.size = readCaseSize();
cp.flagColor = readColor(OP_FLAG_COLOR, DEFAULT_FLAG_COLOR);
cp.explosionColor = readColor(OP_EXPLOSION_COLOR, DEFAULT_EXPLOSION_COLOR);
cp.errorColor = readColor(OP_ERROR_COLOR, DEFAULT_ERROR_COLOR);
for (uint i=0; i<NB_NUMBER_COLORS; i++)
cp.numberColors[i] = readColor(NCName(i), DEFAULT_NUMBER_COLORS[i]);
return cp;
}
void OptionDialog::slotDefault()
{
ni->setValue(DEFAULT_CASE_SIZE);
um->setChecked(true);
keyb->setChecked(true);
for (uint i=0; i<3; i++) cb[i]->setCurrentItem(i);
flagButton->setColor(DEFAULT_FLAG_COLOR);
explosionButton->setColor(DEFAULT_EXPLOSION_COLOR);
errorButton->setColor(DEFAULT_ERROR_COLOR);
for (uint i=0; i<NB_NUMBER_COLORS; i++)
numberButtons[i]->setColor(DEFAULT_NUMBER_COLORS[i]);
}
......@@ -5,13 +5,13 @@
#include <qscrollbar.h>
#include <qlineedit.h>
#include <qlcdnumber.h>
#include <qlayout.h>
#include <qcheckbox.h>
#include <qcombobox.h>
#include <kdialogbase.h>
#include <knuminput.h>
#include <kconfig.h>
#include <kcolorbtn.h>
#include "defines.h"
......@@ -64,8 +64,8 @@ class DigitalClock : public LCDNumber
public slots:
void zero();
void freeze() { stop = TRUE; }
void start() { stop = FALSE; }
void freeze() { stop = true; }
void start() { stop = false; }
private:
uint _sec, _min, max_secs;
......@@ -75,21 +75,7 @@ class DigitalClock : public LCDNumber
};
//-----------------------------------------------------------------------------
class DialogBase : public KDialogBase
{
Q_OBJECT
public:
DialogBase(const QString &caption, int buttonMask,
ButtonCode defaultButton,
QWidget *parent, const char *name = 0);
protected:
QVBoxLayout *top;
};
//-----------------------------------------------------------------------------
class CustomDialog : public DialogBase
class CustomDialog : public KDialogBase
{
Q_OBJECT
......@@ -109,7 +95,7 @@ class CustomDialog : public DialogBase
};
//-----------------------------------------------------------------------------
class WHighScores : public DialogBase
class WHighScores : public KDialogBase
{
Q_OBJECT
......@@ -127,14 +113,14 @@ class WHighScores : public DialogBase
};
//-----------------------------------------------------------------------------
class OptionDialog : public DialogBase
class OptionDialog : public KDialogBase
{
Q_OBJECT
public:
OptionDialog(QWidget *parent);
static uint readCaseSize();
static CaseProperties readCaseProperties();
static bool readUMark();
static bool readKeyboard();
static GameType readLevel();
......@@ -150,8 +136,16 @@ class OptionDialog : public DialogBase
KIntNumInput *ni;
QCheckBox *um, *keyb;
QComboBox *cb[3];
KColorButton *flagButton, *explosionButton, *errorButton;
QArray<KColorButton *> numberButtons;
static KConfig *config();
static uint readCaseSize();
static QColor readColor(const char *key, QColor defaultColor);
void mainPage();
void casePage();
void slotDefault();
};
#endif // DIALOGS_H
......@@ -8,7 +8,7 @@
Field::Field(QWidget *parent, const char *name)
: QFrame(parent, name), lev(LEVELS[0]), random(0), state(Stopped),
u_mark(FALSE), cursor(FALSE), _reveal(FALSE), _autoreveal(FALSE)
u_mark(false), cursor(false), _reveal(false), _autoreveal(false)
{
setFrameStyle( QFrame::Box | QFrame::Raised );
setLineWidth(2);
......@@ -31,41 +31,41 @@ Field::Field(QWidget *parent, const char *name)
void Field::readSettings()
{
setCaseSize(OptionDialog::readCaseSize());
setCaseProperties(OptionDialog::readCaseProperties());
setUMark(OptionDialog::readUMark());
setCursor(OptionDialog::readKeyboard());
for (uint i=0; i<3; i++)
mb[i] = OptionDialog::readMouseBinding((MouseButton)i);
}
void Field::setCaseSize(uint cs)
void Field::setCaseProperties(const CaseProperties &_cp)
{
_caseSize = cs;
cp = _cp;
QBitmap mask;
flagPixmap(mask, TRUE);
flagPixmap(pm_flag, FALSE);
flagPixmap(mask, true);
flagPixmap(pm_flag, false);
pm_flag.setMask(mask);
minePixmap(mask, TRUE, MINE);
minePixmap(pm_mine, FALSE, MINE);
minePixmap(mask, true, Covered);
minePixmap(pm_mine, false, Covered);
pm_mine.setMask(mask);
minePixmap(mask, TRUE, EXPLODED);
minePixmap(pm_exploded, FALSE, EXPLODED);
minePixmap(mask, true, Exploded);
minePixmap(pm_exploded, false, Exploded);