diff options
Diffstat (limited to 'libksirtet/base')
-rw-r--r-- | libksirtet/base/Makefile.am | 16 | ||||
-rw-r--r-- | libksirtet/base/README | 1 | ||||
-rw-r--r-- | libksirtet/base/baseprefs.kcfgc | 7 | ||||
-rw-r--r-- | libksirtet/base/board.cpp | 429 | ||||
-rw-r--r-- | libksirtet/base/board.h | 134 | ||||
-rw-r--r-- | libksirtet/base/factory.cpp | 52 | ||||
-rw-r--r-- | libksirtet/base/factory.h | 60 | ||||
-rw-r--r-- | libksirtet/base/field.cpp | 162 | ||||
-rw-r--r-- | libksirtet/base/field.h | 66 | ||||
-rw-r--r-- | libksirtet/base/gtetris.cpp | 241 | ||||
-rw-r--r-- | libksirtet/base/gtetris.h | 178 | ||||
-rw-r--r-- | libksirtet/base/highscores.cpp | 19 | ||||
-rw-r--r-- | libksirtet/base/highscores.h | 13 | ||||
-rw-r--r-- | libksirtet/base/inter.cpp | 15 | ||||
-rw-r--r-- | libksirtet/base/inter.h | 23 | ||||
-rw-r--r-- | libksirtet/base/kzoommainwindow.cpp | 115 | ||||
-rw-r--r-- | libksirtet/base/kzoommainwindow.h | 128 | ||||
-rw-r--r-- | libksirtet/base/libksirtet1.kcfg | 38 | ||||
-rw-r--r-- | libksirtet/base/main.cpp | 131 | ||||
-rw-r--r-- | libksirtet/base/main.h | 49 | ||||
-rw-r--r-- | libksirtet/base/piece.cpp | 274 | ||||
-rw-r--r-- | libksirtet/base/piece.h | 155 | ||||
-rw-r--r-- | libksirtet/base/settings.cpp | 84 | ||||
-rw-r--r-- | libksirtet/base/settings.h | 33 |
24 files changed, 2423 insertions, 0 deletions
diff --git a/libksirtet/base/Makefile.am b/libksirtet/base/Makefile.am new file mode 100644 index 00000000..bb8b2365 --- /dev/null +++ b/libksirtet/base/Makefile.am @@ -0,0 +1,16 @@ +INCLUDES = -I$(top_srcdir)/libkdegames -I$(top_srcdir)/libkdegames/highscore $(all_includes) + +# Don't compile with hidden symbols since we are a library. +if disable_VISIBILITY +KDE_CXXFLAGS = -fvisibility=default +endif + +noinst_LTLIBRARIES = libksirtetbase.la +libksirtetbase_la_LDFLAGS = $(all_libraries) + +noinst_HEADERS = kzoommainwindow.h piece.h gtetris.h factory.h highscores.h \ + board.h settings.h field.h inter.h main.h +libksirtetbase_la_SOURCES = kzoommainwindow.cpp main.cpp field.cpp piece.cpp highscores.cpp \ + factory.cpp gtetris.cpp board.cpp settings.cpp \ + inter.cpp baseprefs.kcfgc +METASOURCES = AUTO diff --git a/libksirtet/base/README b/libksirtet/base/README new file mode 100644 index 00000000..a16060b1 --- /dev/null +++ b/libksirtet/base/README @@ -0,0 +1 @@ +This directory contains code shared between ksirtet, kfouleggs and klickety. diff --git a/libksirtet/base/baseprefs.kcfgc b/libksirtet/base/baseprefs.kcfgc new file mode 100644 index 00000000..41c852af --- /dev/null +++ b/libksirtet/base/baseprefs.kcfgc @@ -0,0 +1,7 @@ +# Code generation options for kconfig_compiler +File=libksirtet1.kcfg +#IncludeFiles=defines.h +ClassName=BasePrefs +Singleton=true +#CustomAdditions=true +Mutators=MenubarVisible,BlockSize diff --git a/libksirtet/base/board.cpp b/libksirtet/base/board.cpp new file mode 100644 index 00000000..257e72c3 --- /dev/null +++ b/libksirtet/base/board.cpp @@ -0,0 +1,429 @@ +#include "board.h" +#include "board.moc" + +#include <knotifyclient.h> +#include <klocale.h> +#include <kzoommainwindow.h> + +#include "piece.h" +#include "factory.h" +#include "baseprefs.h" + +using namespace KGrid2D; + +//----------------------------------------------------------------------------- +FixedCanvasView::FixedCanvasView(QWidget *parent, const char *name) + : QCanvasView(parent, name, WNoAutoErase) +{} + +QSize FixedCanvasView::sizeHint() const +{ + if ( canvas()==0 ) return QSize(); + return canvas()->size() + 2 * QSize(frameWidth(), frameWidth()); +} + +void FixedCanvasView::adjustSize() +{ + setFixedSize(sizeHint()); +} + +//----------------------------------------------------------------------------- +const BaseBoard::DirectionData BaseBoard::DIRECTION_DATA[Nb_Direction] = { + { SquareBase::Left, Left }, + { SquareBase::Right, Right }, + { SquareBase::Down, Up }, + { SquareBase::Up, Down } +}; + +BaseBoard::BaseBoard(bool graphic, QWidget *parent) +: FixedCanvasView(parent, "board"), + GenericTetris(bfactory->bbi.width, bfactory->bbi.height, + bfactory->bbi.withPieces, graphic), + state(GameOver), timer(this), sequences(0), main(0), _next(0), + _arcade(false) +{ + if (graphic) { + setVScrollBarMode(AlwaysOff); + setHScrollBarMode(AlwaysOff); + setFrameStyle( QFrame::Panel | QFrame::Sunken ); + + sequences = new SequenceArray; + main = new BlockInfo(*sequences); + setCanvas(main); + if (bfactory->bbi.withPieces) + _next = new BlockInfo(*sequences); + setBlockInfo(main, _next); + + connect(&timer, SIGNAL(timeout()), SLOT(timeout())); + + Piece::info().loadColors(); + KZoomMainWindow::addWidget(this); + } +} + +void BaseBoard::copy(const GenericTetris &g) +{ + GenericTetris::copy(g); + state = static_cast<const BaseBoard &>(g).state; +} + +void BaseBoard::settingsChanged() +{ + Q_ASSERT( graphic() ); + Piece::info().loadColors(); +} + +void BaseBoard::adjustSize() +{ + int size = BasePrefs::blockSize(); + + sequences->setBlockSize(size); + main->resize(matrix().width() * size, matrix().height() * size); + for (uint i=0; i<matrix().width(); i++) + for (uint j=0; j<firstClearLine(); j++) { + Coord c(i, j); + if ( matrix()[c]==0 ) continue; + partialMoveBlock(c, QPoint(0, 0)); + } + + if (_next) { + Coord c = Piece::info().maxSize() + Coord(2, 2); + _next->resize(c.first * size, c.second * size); + _nextPiece->moveCenter(); + } + + FixedCanvasView::adjustSize(); +} + +BaseBoard::~BaseBoard() +{ + if ( graphic() ) { + setBlockInfo(0, 0); // destruct all sprites before deleting canvas + delete _next; + delete main; + delete sequences; + } +} + +void BaseBoard::init(bool arcade) +{ + _arcade = arcade; + _arcadeStageDone = false; +} + +void BaseBoard::start(const GTInitData &data) +{ + Q_ASSERT( graphic() ); + if ( !_arcadeStageDone || _arcadeStage==bfactory->bbi.nbArcadeStages ) + _arcadeStage = 0; + _arcadeStageDone = false; + state = Normal; + GenericTetris::start(data); // NB: the timer is started by updateLevel ! + if (_arcade) arcadePrepare(); +} + +void BaseBoard::stop() +{ + timer.stop(); + state = GameOver; +} + +void BaseBoard::pause() +{ + Q_ASSERT( graphic() ); + timer.stop(); + _oldState = state; + state = Paused; + showBoard(false); +} + +void BaseBoard::gameOver() +{ + stop(); + emit gameOverSignal(); +} + +void BaseBoard::showCanvas(QCanvas *c, bool show) +{ + QCanvasItemList l = c->allItems(); + QCanvasItemList::Iterator it; + for (it=l.begin(); it!=l.end(); ++it) { + if (show) (*it)->show(); + else (*it)->hide(); + } + c->update(); +} + +void BaseBoard::showBoard(bool show) +{ + showCanvas(main, show); +} + +void BaseBoard::unpause() +{ + Q_ASSERT( graphic() ); + showBoard(true); + state = _oldState; + startTimer(); +} + +void BaseBoard::updateRemoved(uint newRemoved) +{ + GenericTetris::updateRemoved(newRemoved); + emit removedUpdated(); +} + +void BaseBoard::updateScore(uint newScore) +{ + GenericTetris::updateScore(newScore); + emit scoreUpdated(); +} + +int BaseBoard::firstColumnBlock(uint col) const +{ + for (int j=firstClearLine()-1; j>=0; j--) { + Coord c(col, j); + if ( matrix()[c]!=0 ) return j; + } + return -1; +} + +//----------------------------------------------------------------------------- +void BaseBoard::_beforeRemove(bool first) +{ + if ( graphic() ) { + state = ( beforeRemove(first) ? BeforeRemove : Normal ); + if ( state==BeforeRemove ) { + startTimer(); + return; + } + } + remove(); + _afterRemove(true); +} + +void BaseBoard::remove() +{ + for (uint j=0; j<firstClearLine(); j++) + for (uint i=0; i<matrix().width(); i++) { + Coord c(i, j); + if ( matrix()[c]==0 || !toBeRemoved(c) ) continue; + removeBlock(c); + } + computeInfos(); + if ( graphic() ) { + main->update(); + KNotifyClient::event(winId(), "removed", i18n("Blocks removed")); + } +} + +bool BaseBoard::doFall(bool doAll, bool first, bool lineByLine) +{ + Q_ASSERT( !lineByLine || !doAll ); + + if ( !doAll ) { + if (first) loop = 0; + else loop++; + } + bool final = (doAll || lineByLine + || loop==bfactory->bbi.nbFallStages); + + for (uint i=0; i<matrix().width(); i++) { + // compute heights + // we must separate this computation since toFall() can depend + // directly on the disposition of blocks under the current one + // (for e.g. in kfouleggs) + // we do not rely on firstClearLine() here since this method is + // used in kfouleggs to make gift blocks fall down ... + uint h = 0; + QMemArray<uint> heights(matrix().height()); + for (uint j=1; j<matrix().height(); j++) { // first line cannot fall + Coord src(i, j); + if ( toFall(src) ) h++; + heights[j] = h; + } + + // do move + for (uint j=1; j<matrix().height(); j++) { + Coord src(i, j); + if( heights[j]==0 || matrix()[src]==0 ) continue; + if (lineByLine) final = false; + uint k = j - (lineByLine ? 1 : heights[j]); + Coord dest(i, k); + if ( final || lineByLine ) moveBlock(src, dest); + else partialBlockFall(src, dest); + } + } + + if (final) computeInfos(); + return final; +} + +void BaseBoard::_afterRemove(bool first) +{ + AfterRemoveResult r = afterRemove(!graphic(), first); + switch (r) { + case Done: + state = Normal; + _afterAfterRemove(); + return; + case NeedAfterRemove: + state = AfterRemove; + startTimer(); + return; + case NeedRemoving: + _beforeRemove(true); + return; + } +} + +BaseBoard::AfterRemoveResult BaseBoard::afterRemove(bool doAll, bool first) +{ + return (doFall(doAll, first, false) ? Done : NeedAfterRemove); +} + +void BaseBoard::_afterAfterRemove() +{ + if ( isArcade() && arcadeDone()>=arcadeTodo() ) { + _arcadeStage++; + _arcadeStageDone = true; + gameOver(); + return; + } + if ( !afterAfterRemove() ) gameOver(); + else if ( graphic() ) startTimer(); +} + +bool BaseBoard::timeout() +{ + Q_ASSERT( graphic() ); + if ( state==GameOver ) return true; + switch (state) { + case BeforeRemove: _beforeRemove(FALSE); break; + case AfterRemove: _afterRemove(FALSE); break; + default: return false; + } + main->update(); + return true; +} + +bool BaseBoard::startTimer() +{ + Q_ASSERT( graphic() ); + if ( state==GameOver ) return true; + switch (state) { + case BeforeRemove: + timer.start(bfactory->bbi.beforeRemoveTime, true); + break; + case AfterRemove: + timer.start(bfactory->bbi.afterRemoveTime, true); + break; + default: + return false; + } + return true; +} + +bool BaseBoard::beforeRemove(bool first) +{ + if (first) loop = 0; + else loop++; + + for (uint j=0; j<firstClearLine(); j++) + for (uint i=0; i<matrix().width(); i++) { + Coord c(i, j); + if ( toBeRemoved(c) ) matrix()[c]->toggleLight(); + } + + return ( loop!=bfactory->bbi.nbToggles ); +} + + +//----------------------------------------------------------------------------- +void BaseBoard::partialBlockFall(const Coord &src, const Coord &dest) +{ + Q_ASSERT( loop<bfactory->bbi.nbFallStages ); + + float c = float(loop+1) / bfactory->bbi.nbFallStages * BasePrefs::blockSize(); + int xdec = dest.first - src.first; + int ydec = src.second - dest.second; + QPoint p(int(xdec * c), int(ydec * c)); + partialMoveBlock(src, p); +} + +uint BaseBoard::findGroup(Square<int> &field, const Coord &c) const +{ + uint nb = 0; + _findGroup(field, c, nb, false); + return nb; +} + +void BaseBoard::setGroup(Square<int> &field, const Coord &c, uint nb) const +{ + _findGroup(field, c, nb, true); +} + +void BaseBoard::_findGroup(Square<int> &field, const Coord &c, + uint &nb, bool set) const +{ + if (!set) nb++; + field[c] = (set ? (int)nb : -1); + uint value = matrix()[c]->value(); + CoordList n = matrix().neighbours(c, true, true); + for (CoordList::const_iterator i = n.begin(); i!=n.end(); ++i) + blockInGroup(field, *i, value, nb, set); +} + +void BaseBoard::blockInGroup(Square<int> &field, const Coord &c, uint value, + uint &nb, bool set) const +{ + if ( matrix()[c]==0 ) return; + if ( matrix()[c]->value()!=value ) return; + if ( field[c]!=(set ? -1 : 0) ) return; + _findGroup(field, c, nb, set); +} + +QMemArray<uint> BaseBoard::findGroups(Square<int> &field, uint minSize, + bool exitAtFirstFound) const +{ + field.fill(0); + QMemArray<uint> groups; + for (uint j=0; j<firstClearLine(); j++) + for (uint i=0; i<matrix().width(); i++) { + Coord c(i, j); + if ( matrix()[c]==0 || matrix()[c]->isGarbage() ) continue; + if ( field[c]!=0 ) continue; + uint nb = findGroup(field, c); + setGroup(field, c, nb); + if ( nb>=minSize ) { + uint s = groups.size(); + groups.resize(s+1); + groups[s] = nb; + if (exitAtFirstFound) return groups; + } + } + return groups; +} + +uint BaseBoard::drawCode(const Coord &c) const +{ + uint v = matrix()[c]->value(); + uint code = 0; + for (uint i=0; i<Nb_Direction; i++) { + Coord nc = SquareBase::neighbour(c, DIRECTION_DATA[i].neighbour); + if ( !matrix().inside(nc) || matrix()[nc]==0 + || matrix()[nc]->value()!=v ) continue; + code |= DIRECTION_DATA[i].direction; + } + return code; +} + +void BaseBoard::computeNeighbours() +{ + for (uint j=0; j<firstClearLine(); j++) + for (uint i=0; i<matrix().width(); i++) { + Coord c(i, j); + if ( matrix()[c]==0 || matrix()[c]->isGarbage() ) continue; + matrix()[c]->sprite()->setFrame( drawCode(c) ); + } +} diff --git a/libksirtet/base/board.h b/libksirtet/base/board.h new file mode 100644 index 00000000..443c6532 --- /dev/null +++ b/libksirtet/base/board.h @@ -0,0 +1,134 @@ +#ifndef BASE_BOARD_H +#define BASE_BOARD_H + +#include <qtimer.h> +#include <qcanvas.h> + +#include "gtetris.h" + +#include <kdemacros.h> + +class SequenceArray; +class BlockInfo; + +//----------------------------------------------------------------------------- +class KDE_EXPORT FixedCanvasView : public QCanvasView +{ + Q_OBJECT +public: + FixedCanvasView(QWidget *parent = 0, const char *name = 0); + + virtual QSize sizeHint() const; + +public slots: + virtual void adjustSize(); +}; + +//----------------------------------------------------------------------------- +class KDE_EXPORT BaseBoard : public FixedCanvasView, public GenericTetris +{ + Q_OBJECT + public: + enum Direction { Left = 1, Right = 2, Up = 4, Down = 8, Nb_Direction = 4 }; + private: + struct DirectionData { + KGrid2D::SquareBase::Neighbour neighbour; + Direction direction; + }; + static const DirectionData DIRECTION_DATA[Nb_Direction]; + + public: + BaseBoard(bool graphic, QWidget *parent); + virtual ~BaseBoard(); + void copy(const GenericTetris &); + + void init(bool arcade); + virtual void start(const GTInitData &); + virtual void pause(); + virtual void unpause(); + virtual void stop(); + bool isGameOver() const { return state==GameOver; } + bool isPaused() const { return state==Paused; } + + bool isArcade() const { return _arcade; } + uint arcadeStage() const { return _arcadeStage; } + bool arcadeStageDone() const { return _arcadeStageDone; } + virtual uint arcadeTodo() const { return 0; } + virtual uint arcadeDone() const { return 0; } + + virtual void settingsChanged(); + BlockInfo *next() const { return _next; } + + int firstColumnBlock(uint column) const; + + public slots: + virtual void adjustSize(); + + protected slots: + virtual bool timeout(); // return true if treated + + signals: + void updatePieceConfigSignal(); + void removedUpdated(); + void scoreUpdated(); + void gameOverSignal(); + + protected: + virtual bool beforeRemove(bool first); + void _beforeRemove(bool first); + enum AfterRemoveResult { Done, NeedAfterRemove, NeedRemoving }; + virtual AfterRemoveResult afterRemove(bool doAll, bool first); + void _afterAfterRemove(); + virtual bool afterAfterRemove() = 0; + virtual bool startTimer(); // return true if treated + virtual bool toBeRemoved(const KGrid2D::Coord &) const = 0; + virtual void remove(); + virtual bool toFall(const KGrid2D::Coord &) const = 0;//height>0 when called + virtual bool doFall(bool doAll, bool first, bool lineByLine); + virtual void gameOver(); + virtual void arcadePrepare() {} + + uint drawCode(const KGrid2D::Coord &) const; + void computeNeighbours(); + void partialBlockFall(const KGrid2D::Coord &src, const KGrid2D::Coord &dest); + + // return the sizes of the groups (>=minSize) + QMemArray<uint> findGroups(KGrid2D::Square<int> &field, uint minSize, + bool exitAtFirstFound = false) const; + // find group size and put -1 in the corresponding blocks (these blocks + // should be 0 at start) + uint findGroup(KGrid2D::Square<int> &field, const KGrid2D::Coord &) const; + // set the size of the group in the blocks (these blocks should be -1 + // at start ie you should have called findGroup() before) + void setGroup(KGrid2D::Square<int> &field, const KGrid2D::Coord &c, + uint nb) const; + + void updateRemoved(uint newRemoved); + void updateScore(uint newScore); + + virtual void showBoard(bool show); + void showCanvas(QCanvas *c, bool show); + + enum BoardState { GameOver, Normal, Paused, + DropDown, BeforeGlue, AfterGlue, BeforeRemove, + AfterRemove, AfterGift }; + BoardState state, _oldState; + QTimer timer; + SequenceArray *sequences; + BlockInfo *main, *_next; + uint loop; + + private: + bool _arcade, _arcadeStageDone; + uint _arcadeStage; + + void _afterRemove(bool first); + void updatePieceConfig() { emit updatePieceConfigSignal(); } + + void _findGroup(KGrid2D::Square<int> &field, const KGrid2D::Coord &c, + uint &nb, bool set) const; + void blockInGroup(KGrid2D::Square<int> &field, const KGrid2D::Coord &c, + uint value, uint &nb, bool ser) const; +}; + +#endif diff --git a/libksirtet/base/factory.cpp b/libksirtet/base/factory.cpp new file mode 100644 index 00000000..55850f0b --- /dev/null +++ b/libksirtet/base/factory.cpp @@ -0,0 +1,52 @@ +#include "factory.h" + +#include <kaboutdata.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <kglobal.h> +#include <klocale.h> + +#include "settings.h" + + +BaseFactory *BaseFactory::_self = 0; + +BaseFactory::BaseFactory(const MainData &md, const BaseBoardInfo &bi) + : mainData(md), bbi(bi) +{ + Q_ASSERT( _self==0 ); + _self = this; + _aboutData = + new KAboutData(md.appName, md.trName, md.longVersion, md.description, + KAboutData::License_GPL, + "(c) 1995, Eirik Eng\n(c) 1996-2004, Nicolas Hadacek", + 0, md.homepage); + _aboutData->addAuthor("Nicolas Hadacek", 0, "hadacek@kde.org"); + _aboutData->addCredit("Eirik Eng", I18N_NOOP("Core engine")); +} + +void BaseFactory::init(int argc, char **argv) +{ + KCmdLineArgs::init(argc, argv, _aboutData); + (void)new KApplication; + KGlobal::locale()->insertCatalogue("libkdegames"); + KGlobal::locale()->insertCatalogue("libksirtet"); +} + +BaseFactory::~BaseFactory() +{ + delete kapp; + delete _aboutData; + Q_ASSERT(_self); + _self = 0; +} + +QWidget *BaseFactory::createAppearanceConfig() +{ + return new BaseAppearanceConfig; +} + +QWidget *BaseFactory::createColorConfig() +{ + return new ColorConfig; +} diff --git a/libksirtet/base/factory.h b/libksirtet/base/factory.h new file mode 100644 index 00000000..b542205e --- /dev/null +++ b/libksirtet/base/factory.h @@ -0,0 +1,60 @@ +#ifndef BASE_FACTORY_H +#define BASE_FACTORY_H + +#include <qglobal.h> + +#include <kdemacros.h> + +struct MainData { + const char *appName, *trName, *description, *homepage, *removedLabel, + *version, *longVersion; +}; + +struct BaseBoardInfo { + uint width, height; + bool withPieces; + + uint beforeRemoveTime, afterRemoveTime; + uint nbToggles, nbFallStages; + + uint nbArcadeStages; + + const uint *histogram; + uint histogramSize; + bool scoreBound; +}; + +class BaseBoard; +class BaseInterface; +class QWidget; +class KAboutData; + +#define bfactory BaseFactory::self() + +class KDE_EXPORT BaseFactory +{ + public: + BaseFactory(const MainData &, const BaseBoardInfo &); + virtual ~BaseFactory(); + void init(int argc, char **argv); + + static BaseFactory *self() { return _self; } + + const MainData &mainData; + const BaseBoardInfo &bbi; + + virtual BaseBoard *createBoard(bool graphic, QWidget *parent) = 0; + virtual BaseInterface *createInterface(QWidget *parent) = 0; + + virtual QWidget *createAppearanceConfig(); + virtual QWidget *createColorConfig(); + virtual QWidget *createGameConfig() { return 0; } + + protected: + KAboutData *_aboutData; + + private: + static BaseFactory *_self; +}; + +#endif diff --git a/libksirtet/base/field.cpp b/libksirtet/base/field.cpp new file mode 100644 index 00000000..53f6220a --- /dev/null +++ b/libksirtet/base/field.cpp @@ -0,0 +1,162 @@ +#include "field.h" + +#include <qwhatsthis.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qpushbutton.h> + +#include <klocale.h> +#include <kcanvasrootpixmap.h> +#include <knotifyclient.h> +#include <kgamelcd.h> + +#include "factory.h" +#include "board.h" +#include "baseprefs.h" + + +const char *BaseField::BUTTON_TEXTS[NB_BUTTON_TYPE] = { + I18N_NOOP("Start"), I18N_NOOP("Resume"), I18N_NOOP("Proceed") +}; + +BaseField::BaseField(QWidget *w) + : _widget(w), _boardLayout(0), _label(0), _button(0) +{ + top = new QGridLayout(w, 3, 5, 10); + + lcds = new QGridLayout(7, 1, 5); + top->addLayout(lcds, 1, 0); + lcds->setRowStretch(1, 0); + + board = bfactory->createBoard(true, w); + _boardRootPixmap = new KCanvasRootPixmap(board); + _boardRootPixmap->start(); + top->addWidget(board, 1, 2); +} + +void BaseField::init(bool AI, bool multiplayer, bool server, bool first, + const QString &name) +{ + _flags.AI = AI; + _flags.multiplayer = multiplayer; + _flags.server = server; + _flags.first = first; + QString text = (AI ? i18n("%1\n(AI player)").arg(name) + : (multiplayer ? i18n("%1\n(Human player)").arg(name) + : QString::null)); + if ( first && !server ) text += i18n("\nWaiting for server"); + setMessage(text, (first && server ? StartButton : NoButton)); + showScore->resetColor(); + board->init(false); +} + +void BaseField::setArcade() +{ + board->init(true); + setMessage(i18n("Stage #1"), StartButton); +} + +bool BaseField::isArcade() const +{ + return board->isArcade(); +} + +void BaseField::setMessage(const QString &label, ButtonType type) +{ + delete _label; + _label = 0; + delete _button; + _button = 0; + delete _boardLayout; + _boardLayout = 0; + + if ( label.isEmpty() && type==NoButton ) { + _widget->setFocus(); + return; + } + + _boardLayout = new QVBoxLayout(board); + _boardLayout->addStretch(3); + if ( !label.isEmpty() ) { + QString str = (isArcade() ? i18n("Arcade game") + '\n' + : QString::null) + label; + _label = new QLabel(str, board); + _label->setAlignment(Qt::AlignCenter); + _label->setFrameStyle( QFrame::Panel | QFrame::Sunken ); + _boardLayout->addWidget(_label, 0, Qt::AlignCenter); + _label->show(); + } + _boardLayout->addStretch(1); + if ( type!=NoButton ) { + _button = new QPushButton(i18n(BUTTON_TEXTS[type]), board); + _button->setFocus(); + const char *slot = (type==ResumeButton ? SLOT(pause()) + : SLOT(start())); + _button->connect(_button, SIGNAL(clicked()), + _widget->parent(), slot); + _boardLayout->addWidget(_button, 0, Qt::AlignCenter); + _button->show(); + } + _boardLayout->addStretch(3); +} + +void BaseField::start(const GTInitData &data) +{ + _firstScore = KExtHighscore::firstScore(); + _lastScore = KExtHighscore::lastScore(); + hideMessage(); + board->start(data); +} + +void BaseField::pause(bool pause) +{ + if (pause) { + board->pause(); + setMessage(i18n("Game paused"), ResumeButton); + } else { + board->unpause(); + hideMessage(); + } +} + +void BaseField::stop(bool gameover) +{ + board->stop(); + ButtonType button = StartButton; + QString msg = (gameover ? i18n("Game over") : QString::null); + if ( board->isArcade() && board->arcadeStageDone() ) { + if ( board->arcadeStage()==bfactory->bbi.nbArcadeStages ) + msg = i18n("The End"); + else { + msg = i18n("Stage #%1 done").arg(board->arcadeStage()); + button = ProceedButton; + } + } + setMessage(msg, button); +} + +void BaseField::gameOver(const KExtHighscore::Score &score, QWidget *parent) +{ + KNotifyClient::event(parent->winId(), "game over", i18n("Game Over")); + KExtHighscore::submitScore(score, parent); +} + +void BaseField::scoreUpdated() +{ + showScore->display( (int)board->score() ); + if (_flags.multiplayer) return; + + QColor color; + if ( _firstScore<currentScore() ) color = Qt::red; + else if ( _lastScore<currentScore() ) color = Qt::blue; + showScore->setColor(color); +} + +void BaseField::settingsChanged() +{ + QColor color = BasePrefs::fadeColor(); + double s = BasePrefs::fadeIntensity(); + _boardRootPixmap->setFadeEffect(s, color); + board->canvas()->setBackgroundColor(color); + board->settingsChanged(); +} diff --git a/libksirtet/base/field.h b/libksirtet/base/field.h new file mode 100644 index 00000000..d006a052 --- /dev/null +++ b/libksirtet/base/field.h @@ -0,0 +1,66 @@ +#ifndef BASE_FIELD_H +#define BASE_FIELD_H + +#include <kexthighscore.h> + +#include <kdemacros.h> + +class QVBoxLayout; +class QGridLayout; +class KGameLCD; +class KGameLCDList; +class BaseBoard; +class QLabel; +class QButton; +class GTInitData; +class KCanvasRootPixmap; + +class KDE_EXPORT BaseField +{ + public: + BaseField(QWidget *widget); + virtual ~BaseField() {} + + virtual KExtHighscore::Score currentScore() const = 0; + static void gameOver(const KExtHighscore::Score &, QWidget *parent); + + virtual void setArcade(); + bool isArcade() const; + + protected: + QGridLayout *top, *lcds; + KGameLCD *showScore; + KGameLCDList *removedList, *scoreList; + BaseBoard *board; + + virtual void scoreUpdated(); + virtual void init(bool AI, bool multiplayer, bool server, bool first, + const QString &name); + virtual void start(const GTInitData &); + virtual void pause(bool pause); + virtual void stop(bool gameover); + virtual void settingsChanged(); + + private: + QWidget *_widget; + struct Flags { + bool AI, multiplayer, server, first; + }; + Flags _flags; + uint _arcadeStage; + QVBoxLayout *_boardLayout; + QLabel *_label; + QButton *_button; + KCanvasRootPixmap *_boardRootPixmap; + KExtHighscore::Score _firstScore, _lastScore; + + enum ButtonType { StartButton = 0, ResumeButton, ProceedButton, + NB_BUTTON_TYPE, NoButton = NB_BUTTON_TYPE }; + static const char *BUTTON_TEXTS[NB_BUTTON_TYPE]; + + bool hasButton() const { return _flags.server && _flags.first; } + void setMessage(const QString &label, ButtonType); + void hideMessage() { setMessage(QString::null, NB_BUTTON_TYPE); } +}; + +#endif diff --git a/libksirtet/base/gtetris.cpp b/libksirtet/base/gtetris.cpp new file mode 100644 index 00000000..2141f9ef --- /dev/null +++ b/libksirtet/base/gtetris.cpp @@ -0,0 +1,241 @@ +#include "gtetris.h" + +#include "piece.h" + + +using namespace KGrid2D; + +GenericTetris::GenericTetris(uint width, uint height, bool withPieces, + bool graphic) + : _nextPiece(0), _currentPiece(0), _score(0), _nbRemoved(0), + _nbClearLines(height), _main(0), + _graphic(graphic), _matrix(width, height) +{ + if (withPieces) { + _nextPiece = new Piece; + _currentPiece = new Piece; + } + _matrix.fill(0); +} + +void GenericTetris::copy(const GenericTetris &g) +{ + Q_ASSERT(_currentPiece); + // copy to non graphic + _score = g._score; + _level = g._level; + _nbRemoved = g._nbRemoved; + _nbClearLines = g._nbClearLines; + _currentPos = g._currentPos; + _nextPiece->copy(g._nextPiece); + _currentPiece->copy(g._currentPiece); + for (uint i=0; i<_matrix.size(); i++) { + Coord c = _matrix.coord(i); + delete _matrix[c]; + if ( g._matrix[c] ) _matrix[c] = new Block(g._matrix[c]->value()); + else _matrix[c] = 0; + } +} + +void GenericTetris::clear() +{ + _currentPos = Coord(0, -1); + for (uint i=0; i<_matrix.size(); i++) removeBlock(_matrix.coord(i)); + computeInfos(); +} + +GenericTetris::~GenericTetris() +{ + // everything should already be done by setBlockInfo(0, 0); +} + +void GenericTetris::setBlockInfo(BlockInfo *main, BlockInfo *next) +{ + Q_ASSERT( _graphic ); + if (main) { + _main = main; + if (_currentPiece) { + Q_ASSERT(next); + _nextPiece->setBlockInfo(next); + _currentPiece->setBlockInfo(main); + } + } else { // before destruction + clear(); + delete _currentPiece; + delete _nextPiece; + } +} + +void GenericTetris::start(const GTInitData &data) +{ + Q_ASSERT( _graphic ); + _random.setSeed(data.seed); + _initLevel = data.initLevel; + updateScore(0); + updateLevel(_initLevel); + updateRemoved(0); + clear(); + if (_nextPiece) { + _nextPiece->setRandomSequence(&_random); + _nextPiece->generateNext(); + newPiece(); + } +} + +void GenericTetris::dropDown() +{ + uint dropHeight = moveTo(Coord(0, -_currentPos.second)); + pieceDropped(dropHeight); +} + +void GenericTetris::oneLineDown() +{ + if ( moveTo(Coord(0, -1))==0 ) pieceDropped(0); +} + +bool GenericTetris::newPiece() +{ + Q_ASSERT(_currentPiece); + Coord min = _nextPiece->min(); + _currentPos.second = _matrix.height() - 1 + min.second; + _currentPos.first = (_matrix.width() - _nextPiece->size().first)/2 + - min.first; + if ( !canPosition(_currentPos, _nextPiece)) { + _currentPos.second = -1; + return false; + } + _currentPiece->copy(_nextPiece); + if (_graphic) { + _currentPiece->move(toPoint(_currentPos)); + _currentPiece->show(true); + updatePieceConfig(); + } + _nextPiece->generateNext(); + if (_graphic) { + _nextPiece->moveCenter(); + _nextPiece->show(true); + updateNextPiece(); + } + return true; +} + +bool GenericTetris::canPosition(const Coord &pos, const Piece *piece) const +{ + for(uint k=0; k<piece->nbBlocks(); k++) { + Coord c(piece->pos(k, pos)); + if ( !_matrix.inside(c) || _matrix[c]!=0 ) + return false; // outside or something in the way + } + return true; +} + +uint GenericTetris::moveTo(const Coord &dec) +{ + Q_ASSERT(_currentPiece); + Q_ASSERT(dec.first==0 || dec.second==0); + + Coord newPos = _currentPos; + Coord d(0, 0); + uint n, i; + + if (dec.first) { + d.first = (dec.first<0 ? -1 : 1); + n = kAbs(dec.first); + } else { + d.second = (dec.second<0 ? -1 : 1); + n = kAbs(dec.second); + } + + for (i=0; i<n; i++) { + if ( !canPosition(newPos + d, _currentPiece) ) break; + newPos = newPos + d; + } + if ( i!=0 ) { // piece can be moved + _currentPos = newPos; + if (_graphic) { + _currentPiece->move(toPoint(newPos)); + updatePieceConfig(); + } + } + return i; +} + +bool GenericTetris::rotate(bool left) +{ + Q_ASSERT(_currentPiece); + + Piece tmp; + tmp.copy(_currentPiece); + QPoint p(0, 0); + tmp.rotate(left, p); + if ( canPosition(_currentPos, &tmp) ) { + if (_graphic) p = toPoint(_currentPos); + _currentPiece->rotate(left, p); + if (_graphic) updatePieceConfig(); + return true; + } + return false; +} + +void GenericTetris::computeInfos() +{ + _nbClearLines = 0; + for (uint j=_matrix.height(); j>0; j--) { + for (uint i=0; i<_matrix.width(); i++) + if ( _matrix[Coord(i, j-1)]!=0 ) return; + _nbClearLines++; + } +} + +void GenericTetris::setBlock(const Coord &c, Block *b) +{ + Q_ASSERT( b && _matrix[c]==0 ); + _matrix[c] = b; + if (_graphic) { + QPoint p = toPoint(c); + b->sprite()->move(p.x(), p.y()); + } +} + +void GenericTetris::removeBlock(const Coord &c) +{ + delete _matrix[c]; + _matrix[c] = 0; +} + +void GenericTetris::moveBlock(const Coord &src, const Coord &dest) +{ + Q_ASSERT( _matrix[dest]==0 ); + if ( _matrix[src] ) { + setBlock(dest, _matrix[src]); + _matrix[src] = 0; + } +} + +QPoint GenericTetris::toPoint(const Coord &c) const +{ + return _main->toPoint(Coord(c.first, _matrix.height() - 1 - c.second)); +} + +void GenericTetris::gluePiece() +{ + Q_ASSERT(_currentPiece); + + for(uint k=0; k<_currentPiece->nbBlocks(); k++) + setBlock(_currentPiece->pos(k, _currentPos), + _currentPiece->takeBlock(k)); + computeInfos(); +} + +void GenericTetris::bumpCurrentPiece(int dec) +{ + Q_ASSERT( _graphic && _currentPiece ); + _currentPiece->move(toPoint(_currentPos) + QPoint(0, dec)); +} + +void GenericTetris::partialMoveBlock(const Coord &c, const QPoint &dec) +{ + Q_ASSERT( _graphic && _matrix[c]!=0 ); + QPoint p = toPoint(c) + dec; + _matrix[c]->sprite()->move(p.x(), p.y()); +} diff --git a/libksirtet/base/gtetris.h b/libksirtet/base/gtetris.h new file mode 100644 index 00000000..48aefb9d --- /dev/null +++ b/libksirtet/base/gtetris.h @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Definition of GenericTetris, a generic class for implementing Tetris. +** +** Author : Eirik Eng +** Created : 940126 +** Modified by Nicolas Hadacek +** +** Copyright (C) 1994 by Eirik Eng. All rights reserved. +** +**--------------------------------------------------------------------------- +** +** The GenericTetris class is an abstract class that can be used to implement +** the well known game of Tetris. It is totally independent of any hardware +** platform or user interface mechanism. It has no notion of time, so you +** have to supply the timer ticks (or heartbeat) of the game. Apart from +** that this is a complete Tetris implementation. +** +** In the following it is assumed that the reader is familiar with the game +** of Tetris. +** +** The class operates on a grid of squares (referred to as the "board" below), +** where each of the different types of pieces in Tetris covers 4 squares. The +** width and height of the board can be specified in the constructor (default +** is 10x22). The coordinate (0,0) is at the TOP LEFT corner. The class +** assumes that it has total control over the board and uses this to optimize +** drawing of the board. If you need to update parts of the board +** (e.g. if you are using a window system), use the updateBoard() function. +** +** An implementation of the game must subclass from TetrisBoard and must +** implement these abstract functions: +** +** virtual void drawSquare(int x,int y,int value) +** +** This function is called when a square needs to be drawn +** on the Tetris board. A value of 0 means that the square +** should be erased. Values of 1 to 7 indicate the different +** types of pieces. (Thus a minimal implementation can +** draw 0 in one way and 1-7 in a second way). The x and y +** values are coordinates on the Tetris board (see above). +** +** virtual void gameOver() +** +** This function is called when it is impossible to put a new +** piece at the top of the board. +** +** To get a working minimal implementation of Tetris the following functions +** must be called from the user interface: +** +** void startGame() +** +** Clears the board and starts a new game. +** +** void moveLeft() +** void moveRight() +** void rotateLeft() +** void rotateRight() +** +** The standard Tetris controls for moving and rotating the +** falling pieces. +** +** void dropDown(); +** +** Another Tetris control, drops the falling piece and calls the +** virtual function pieceDropped(), whose default implementation is +** to create a new block which appears at the top of the board. +** +** void oneLineDown(); +** +** This is where you supply the timer ticks, or heartbeat, of the +** game. This function moves the current falling piece one line down +** on the board, or, if that cannot be done, calls the virtual +** function pieceDropped() (see dropDown() above). The time between +** each call to this function directly affects the difficulty of the +** game. If you want to pause the game, simply block calls to the +** user control functions above and stop calling this function (you +** might want to call hideBoard() also). +** +** And that's it! There are several other public functions you can call +** and virtual functions you can overload to modify or extend the game. +** +** Do whatever you want with this code (i.e. the files gtetris.h, +** gtetris.cpp, tpiece.h and tpiece.cpp). It is basically a weekend hack +** and it would bring joy to my heart if anyone in any way would find +** it useful. +** +** Nostalgia, comments and/or praise can be sent to: Eirik.Eng@troll.no +** +****************************************************************************/ + +#ifndef GTETRIS_H +#define GTETRIS_H + +#include <qpoint.h> + +#include <krandomsequence.h> +#include <kgrid2d.h> + +#include <kdemacros.h> + +class Piece; +class BlockInfo; +class Block; + +struct GTInitData { + int seed; + uint initLevel; +}; + +class KDE_EXPORT GenericTetris +{ + public: + GenericTetris(uint width, uint height, bool withPieces, bool graphic); + virtual ~GenericTetris(); + virtual void copy(const GenericTetris &); + + void setBlockInfo(BlockInfo *main, BlockInfo *next); + virtual void start(const GTInitData &); + + uint moveLeft(int steps = 1) { return moveTo(KGrid2D::Coord(-steps, 0)); } + uint moveRight(int steps = 1) { return moveTo(KGrid2D::Coord(steps, 0)); } + bool rotateLeft() { return rotate(true); } + bool rotateRight() { return rotate(false); } + virtual void oneLineDown(); + virtual void dropDown(); + + KRandomSequence &randomSequence() { return _random; } + uint score() const { return _score; } + uint level() const { return _level; } + uint nbClearLines() const { return _nbClearLines; } + uint nbRemoved() const { return _nbRemoved; } + bool graphic() const { return _graphic; } + uint firstClearLine() const { return _matrix.height() - _nbClearLines; } + const KGrid2D::Coord ¤tPos() const { return _currentPos; } + const Piece *nextPiece() const { return _nextPiece; } + const Piece *currentPiece() const { return _currentPiece; } + const KGrid2D::Square<Block *> &matrix() const { return _matrix; } + + protected: + Piece *_nextPiece, *_currentPiece; + + virtual void pieceDropped(uint /*dropHeight*/) {} + virtual bool newPiece(); // return false if cannot place new piece + virtual void gluePiece(); + virtual void computeInfos(); + + virtual void updateRemoved(uint newNbRemoved) { _nbRemoved = newNbRemoved;} + virtual void updateScore(uint newScore) { _score = newScore; } + virtual void updateLevel(uint newLevel) { _level = newLevel; } + + void setBlock(const KGrid2D::Coord &, Block *); + virtual void removeBlock(const KGrid2D::Coord &); + void moveBlock(const KGrid2D::Coord &src, const KGrid2D::Coord &dest); + + virtual void updateNextPiece() {} + virtual void updatePieceConfig() {} + void bumpCurrentPiece(int dec); + void partialMoveBlock(const KGrid2D::Coord &, const QPoint &dec); + + private: + QPoint toPoint(const KGrid2D::Coord &) const; + uint moveTo(const KGrid2D::Coord &dec); + bool rotate(bool left); + void clear(); + bool canPosition(const KGrid2D::Coord &newPos, const Piece *newPiece) const; + + GenericTetris(const GenericTetris &); // disabled + + uint _score, _level, _nbRemoved; + uint _nbClearLines, _initLevel; + KGrid2D::Coord _currentPos; + BlockInfo *_main; + bool _graphic; + KGrid2D::Square<Block *> _matrix; + KRandomSequence _random; +}; + +#endif diff --git a/libksirtet/base/highscores.cpp b/libksirtet/base/highscores.cpp new file mode 100644 index 00000000..2b3596d7 --- /dev/null +++ b/libksirtet/base/highscores.cpp @@ -0,0 +1,19 @@ +#include "highscores.h" + +#include <kurl.h> + +#include "factory.h" + + +using namespace KExtHighscore; + +BaseHighscores::BaseHighscores() +{ + setWWHighscores(KURL( bfactory->mainData.homepage ), bfactory->mainData.version); + const BaseBoardInfo &bi = bfactory->bbi; + if ( bi.histogramSize!=0 ) { + QMemArray<uint> a; + a.duplicate(bi.histogram, bi.histogramSize); + setScoreHistogram(a, bi.scoreBound ? ScoreBound : ScoreNotBound); + } +} diff --git a/libksirtet/base/highscores.h b/libksirtet/base/highscores.h new file mode 100644 index 00000000..b3e7b99e --- /dev/null +++ b/libksirtet/base/highscores.h @@ -0,0 +1,13 @@ +#ifndef BASE_HIGHSCORES_H +#define BASE_HIGHSCORES_H + +#include <kexthighscore.h> +#include <kdemacros.h> + +class KDE_EXPORT BaseHighscores : public KExtHighscore::Manager +{ + public: + BaseHighscores(); +}; + +#endif diff --git a/libksirtet/base/inter.cpp b/libksirtet/base/inter.cpp new file mode 100644 index 00000000..4f40b63f --- /dev/null +++ b/libksirtet/base/inter.cpp @@ -0,0 +1,15 @@ +#include "inter.h" + +#include <kexthighscore.h> + + +void BaseInterface::showHighscores(QWidget *parent) +{ + if ( !_isPaused() ) _pause(); + _showHighscores(parent); +} + +void BaseInterface::_showHighscores(QWidget *parent) +{ + KExtHighscore::show(parent); +} diff --git a/libksirtet/base/inter.h b/libksirtet/base/inter.h new file mode 100644 index 00000000..446a77d3 --- /dev/null +++ b/libksirtet/base/inter.h @@ -0,0 +1,23 @@ +#ifndef BASE_INTER_H +#define BASE_INTER_H + +class QWidget; + + +class BaseInterface +{ +public: + BaseInterface() {} + virtual ~BaseInterface() {} + + virtual void _start() = 0; + virtual void _pause() = 0; + virtual bool _isPaused() const = 0; + + void showHighscores(QWidget *parent); + +protected: + virtual void _showHighscores(QWidget *parent); +}; + +#endif diff --git a/libksirtet/base/kzoommainwindow.cpp b/libksirtet/base/kzoommainwindow.cpp new file mode 100644 index 00000000..115d5175 --- /dev/null +++ b/libksirtet/base/kzoommainwindow.cpp @@ -0,0 +1,115 @@ +/* + This file is part of the KDE games library + Copyright (C) 2004 Nicolas Hadacek (hadacek@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kzoommainwindow.h" +#include "kzoommainwindow.moc" + +#include <kaction.h> +#include <kstdaction.h> +#include <kmenubar.h> +#include <kcmenumngr.h> + +KZoomMainWindow::KZoomMainWindow(uint min, uint max, uint step, const char *name) + : KMainWindow(0, name), _zoomStep(step), _minZoom(min), _maxZoom(max) +{ + installEventFilter(this); + + _zoomInAction = KStdAction::zoomIn(this, SLOT(zoomIn()), actionCollection()); + _zoomOutAction = + KStdAction::zoomOut(this, SLOT(zoomOut()), actionCollection()); + _menu = + KStdAction::showMenubar(this, SLOT(toggleMenubar()), actionCollection()); +} + +void KZoomMainWindow::init(const char *popupName) +{ + // zoom + setZoom(readZoomSetting()); + + // menubar + _menu->setChecked( menubarVisibleSetting() ); + toggleMenubar(); + + // context popup + if (popupName) { + QPopupMenu *popup = + static_cast<QPopupMenu *>(factory()->container(popupName, this)); + Q_ASSERT(popup); + if (popup) KContextMenuManager::insert(this, popup); + } +} + +void KZoomMainWindow::addWidget(QWidget *widget) +{ + widget->adjustSize(); + QWidget *tlw = widget->topLevelWidget(); + KZoomMainWindow *zm = + static_cast<KZoomMainWindow *>(tlw->qt_cast("KZoomMainWindow")); + Q_ASSERT(zm); + zm->_widgets.append(widget); + connect(widget, SIGNAL(destroyed()), zm, SLOT(widgetDestroyed())); +} + +void KZoomMainWindow::widgetDestroyed() +{ + _widgets.remove(static_cast<const QWidget *>(sender())); +} + +bool KZoomMainWindow::eventFilter(QObject *o, QEvent *e) +{ + if ( e->type()==QEvent::LayoutHint ) + setFixedSize(minimumSize()); // because K/QMainWindow + // does not manage fixed central widget + // with hidden menubar... + return KMainWindow::eventFilter(o, e); +} + +void KZoomMainWindow::setZoom(uint zoom) +{ + _zoom = zoom; + writeZoomSetting(_zoom); + QPtrListIterator<QWidget> it(_widgets); + for (; it.current(); ++it) + (*it)->adjustSize();; + _zoomOutAction->setEnabled( _zoom>_minZoom ); + _zoomInAction->setEnabled( _zoom<_maxZoom ); +} + +void KZoomMainWindow::zoomIn() +{ + setZoom(_zoom + _zoomStep); +} + +void KZoomMainWindow::zoomOut() +{ + Q_ASSERT( _zoom>=_zoomStep ); + setZoom(_zoom - _zoomStep); +} + +void KZoomMainWindow::toggleMenubar() +{ + if ( _menu->isChecked() ) menuBar()->show(); + else menuBar()->hide(); +} + +bool KZoomMainWindow::queryExit() +{ + writeMenubarVisibleSetting(_menu->isChecked()); + return KMainWindow::queryExit(); +} diff --git a/libksirtet/base/kzoommainwindow.h b/libksirtet/base/kzoommainwindow.h new file mode 100644 index 00000000..14f780fb --- /dev/null +++ b/libksirtet/base/kzoommainwindow.h @@ -0,0 +1,128 @@ +/* + This file is part of the KDE games library + Copyright (C) 2004 Nicolas Hadacek (hadacek@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KZOOMMAINWINDOW_H +#define KZOOMMAINWINDOW_H + +#include <kmainwindow.h> +#include <kdemacros.h> + + +class KToggleAction; + +/** + * KZoomMainWindow is a main window of fixed size. Its size can be + * modified with the "zoom in"/"zoom out" actions. + * + * It manages one or several widgets: their adjustSize() method is + * called whenever the zoom level is changed. + * The usual implementation for those widget is to redefine adjustSize() + * with code like: + * /code + * setFixedSize(newsize); + * /endcode + * + * This class also has a "show/hide menubar" action and allows the use + * of a context popup menu (useful to restore the menubar when hidden). + */ +class KDE_EXPORT KZoomMainWindow : public KMainWindow +{ + Q_OBJECT +public: + /** Constructor. */ + KZoomMainWindow(uint minZoom, uint maxZoom, uint zoomStep, + const char *name = 0); + + /** Add a widget to be managed i.e. the adjustSize() method of the + * widget is called whenever the zoom is changed. + * This function assumes that the topLevelWidget() is the KZoomMainWindow. + */ + static void addWidget(QWidget *widget); + + uint zoom() const { return _zoom; } + +public slots: + void zoomIn(); + void zoomOut(); + void toggleMenubar(); + +protected: + /** You need to call this after the createGUI or setupGUI method + * is called. + * @param popupName is the name of the context popup menu as defined in + * the ui.rc file. + */ + void init(const char *popupName = 0); + + virtual void setZoom(uint zoom); + virtual bool eventFilter(QObject *o, QEvent *e); + virtual bool queryExit(); + + /** You need to implement this method since different application + * use different setting class names and keys. + * Use something like: + * /code + * Settings::setZoom(zoom); + * Settings::writeConfig(); + * /endcode + */ + virtual void writeZoomSetting(uint zoom) = 0; + + /** Youneed to implement this method since different application + * use different setting class names and keys. + * Use something like: + * /code + * return Settings::zoom(); + * /endcode + */ + virtual uint readZoomSetting() const = 0; + + /** You need to implement this method since different application + * use different setting class names and keys. + * Use something like: + * /code + * Settings::setMenubarVisible(visible); + * Settings::writeConfig(); + * /endcode + */ + virtual void writeMenubarVisibleSetting(bool visible) = 0; + + /** You need to implement this method since different application + * use different setting class names and keys. + * Use something like: + * /code + * Settings::menubarVisible(); + * /endcode + */ + virtual bool menubarVisibleSetting() const = 0; + +private slots: + void widgetDestroyed(); + +private: + uint _zoom, _zoomStep, _minZoom, _maxZoom; + QPtrList<QWidget> _widgets; + KAction *_zoomInAction, *_zoomOutAction; + KToggleAction *_menu; + + class KZoomMainWindowPrivate; + KZoomMainWindowPrivate *d; +}; + +#endif diff --git a/libksirtet/base/libksirtet1.kcfg b/libksirtet/base/libksirtet1.kcfg new file mode 100644 index 00000000..684de57f --- /dev/null +++ b/libksirtet/base/libksirtet1.kcfg @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <include>factory.h</include> + <include>piece.h</include> + <group name="Options"> + <entry name="BlockSize" type="Int" key="block size"> + <label>Size of the blocks.</label> + <min>4</min> + <max>100</max> + <default>15</default> + </entry> + <entry name="FadeIntensity" type="Double" key="fade intensity"> + <label>Fade intensity.</label> + <default>1.0</default> + </entry> + <entry name="FadeColor" type="Color" key="fade color"> + <label>Fade color.</label> + <default>black</default> + </entry> + <entry name="AnimationsEnabled" type="Bool" key="enable animations"> + <label>Animations enabled.</label> + <default>true</default> + </entry> + <entry name="MenubarVisible" type="Bool" key="menubar visible"> + <label>Menubar visible.</label> + <default>true</default> + </entry> + <entry name="Color$(Number)" type="Color" key="color #$(Number)"> + <parameter name="Number" type="Int" max="10"/> + <label>Block colors.</label> +<!-- TODO: max, default is dynamic --> + <default code="true">Piece::info().defaultColor($(Number))</default> + </entry> + </group> +</kcfg> diff --git a/libksirtet/base/main.cpp b/libksirtet/base/main.cpp new file mode 100644 index 00000000..4b5a4160 --- /dev/null +++ b/libksirtet/base/main.cpp @@ -0,0 +1,131 @@ +#include "main.h" +#include "main.moc" + +#include <kaction.h> +#include <kstdaction.h> +#include <kmenubar.h> +#include <kstdgameaction.h> +#include <kcmenumngr.h> +#include <kkeydialog.h> +#include <klocale.h> +#include <knotifyclient.h> +#include <knotifydialog.h> +#include <kexthighscore.h> +#include <kconfigdialog.h> + +#include "inter.h" +#include "factory.h" +#include "settings.h" +#include "baseprefs.h" + +BaseMainWindow::BaseMainWindow() + : KZoomMainWindow(4, 100, 1, "main_window") +{ + KNotifyClient::startDaemon(); + + // File & Popup + KStdGameAction::gameNew(this, SLOT(start()), actionCollection()); + _pause = KStdGameAction::pause(this, SLOT(pause()), actionCollection()); + _pause->setEnabled(false); + KStdGameAction::highscores(this, SLOT(showHighscores()), + actionCollection()); + KStdGameAction::quit(qApp, SLOT(quit()), actionCollection()); + + // Settings + KStdAction::preferences(this, SLOT(configureSettings()), + actionCollection()); + KStdAction::keyBindings(this, SLOT(configureKeys()), actionCollection()); + KStdAction::configureNotifications(this, SLOT(configureNotifications()), + actionCollection()); + KStdGameAction::configureHighscores(this, SLOT(configureHighscores()), + actionCollection()); + + _inter = bfactory->createInterface(this); +} + +void BaseMainWindow::buildGUI(QWidget *widget) +{ + createGUI(); + setCentralWidget(widget); + init("popup"); +} + +BaseMainWindow::~BaseMainWindow() +{ + delete _inter; +} + +void BaseMainWindow::showHighscores() +{ + _inter->showHighscores(this); +} + +void BaseMainWindow::start() +{ + _inter->_start(); +} + +void BaseMainWindow::pause() +{ + _inter->_pause(); +} + +void BaseMainWindow::configureHighscores() +{ + KExtHighscore::configure(this); +} + +void BaseMainWindow::configureSettings() +{ + if ( !_inter->_isPaused() ) _inter->_pause(); + if ( KConfigDialog::showDialog("settings") ) return; + + KConfigDialog *dialog = new KConfigDialog(this, "settings", BasePrefs::self() ); + QWidget *w = bfactory->createGameConfig(); + if (w) dialog->addPage(w, i18n("Game"), "package_system"); + w = bfactory->createAppearanceConfig(); + if (w) dialog->addPage(w, i18n("Appearance"), "style"); + w = bfactory->createColorConfig(); + if (w) dialog->addPage(w, i18n("Colors"), "colorize"); +// dialog->addPage(new BackgroundConfigWidget, i18n("Background"), "background"); + addConfig(dialog); + connect(dialog, SIGNAL(settingsChanged()), SIGNAL(settingsChanged())); + dialog->show(); +} + +void BaseMainWindow::configureKeys() +{ + KKeyDialog d(true, this); + addKeys(d); + d.insert(actionCollection()); + d.configure(false); + actionCollection()->writeShortcutSettings(); + saveKeys(); +} + +void BaseMainWindow::configureNotifications() +{ + KNotifyDialog::configure(this); +} + +void BaseMainWindow::writeZoomSetting(uint zoom) +{ + BasePrefs::setBlockSize(zoom); + BasePrefs::writeConfig(); +} + +uint BaseMainWindow::readZoomSetting() const +{ + return BasePrefs::blockSize(); +} + +void BaseMainWindow::writeMenubarVisibleSetting(bool visible) +{ + BasePrefs::setMenubarVisible(visible); + BasePrefs::writeConfig(); +} + +bool BaseMainWindow::menubarVisibleSetting() const +{ + return BasePrefs::menubarVisible(); +} diff --git a/libksirtet/base/main.h b/libksirtet/base/main.h new file mode 100644 index 00000000..d2e108aa --- /dev/null +++ b/libksirtet/base/main.h @@ -0,0 +1,49 @@ +#ifndef BASE_MAIN_H +#define BASE_MAIN_H + +#include "kzoommainwindow.h" + +#include <kdemacros.h> + +class BaseInterface; +class KToggleAction; +class KKeyDialog; +class KConfigDialog; + +class KDE_EXPORT BaseMainWindow : public KZoomMainWindow +{ + Q_OBJECT +public: + BaseMainWindow(); + virtual ~BaseMainWindow(); + +signals: + void settingsChanged(); + +private slots: + void start(); + void pause(); + void showHighscores(); + void configureSettings(); + void configureKeys(); + void configureHighscores(); + void configureNotifications(); + +protected: + BaseInterface *_inter; + + void buildGUI(QWidget *widget); + virtual void addConfig(KConfigDialog *) {} + virtual void addKeys(KKeyDialog &) {} + virtual void saveKeys() {} + + virtual void writeZoomSetting(uint zoom); + virtual uint readZoomSetting() const; + virtual void writeMenubarVisibleSetting(bool visible); + virtual bool menubarVisibleSetting() const; + +private: + KToggleAction *_pause; +}; + +#endif diff --git a/libksirtet/base/piece.cpp b/libksirtet/base/piece.cpp new file mode 100644 index 00000000..25aed934 --- /dev/null +++ b/libksirtet/base/piece.cpp @@ -0,0 +1,274 @@ +#include "piece.h" + +#include <kglobal.h> +#include <krandomsequence.h> + +#include "baseprefs.h" + +using namespace KGrid2D; + +QPoint operator *(const Coord &c, int i) +{ + return QPoint(c.first * i, c.second * i); +} + +//----------------------------------------------------------------------------- +GPieceInfo::GPieceInfo() +{ + Piece::setPieceInfo(this); +} + +QPixmap *GPieceInfo::pixmap(uint blockSize, uint blockType, uint blockMode, + bool lighted) const +{ + QPixmap *pixmap = new QPixmap(blockSize, blockSize); + draw(pixmap, blockType, blockMode, lighted); + setMask(pixmap, blockMode); + return pixmap; +} + +Coord GPieceInfo::maxSize() const +{ + Coord min, max; + Coord size(0, 0); + for (uint n=0; n<nbForms(); n++) { + min = max = Coord(i(n, 0)[0], j(n, 0)[0]); + for (uint k=0; k<nbBlocks(); k++) { + Coord tmp = Coord(i(n, 0)[k], j(n, 0)[k]); + max = maximum(max, tmp); + min = minimum(min, tmp); + } + size = maximum(size, max - min); + } + return size; +} + +uint GPieceInfo::generateType(KRandomSequence *random) const +{ + return random->getLong( nbTypes() ); +} + +uint GPieceInfo::generateGarbageBlockType(KRandomSequence *random) const +{ + return nbNormalBlockTypes() + random->getLong( nbGarbageBlockTypes() ); +} + +void GPieceInfo::loadColors() +{ + _colors.resize(nbColors()); + for (uint i=0; i<_colors.size(); i++) + _colors[i] = BasePrefs::color(i); +} + + +//----------------------------------------------------------------------------- +SequenceArray::SequenceArray() +: _size(0) +{ + const GPieceInfo &pinfo = Piece::info(); + fill(0, pinfo.nbNormalBlockTypes() + pinfo.nbGarbageBlockTypes()); +} + +void SequenceArray::setBlockSize(uint bsize) +{ + _size = bsize; + const GPieceInfo &pinfo = Piece::info(); + QPtrList<QPixmap> pixmaps; + pixmaps.setAutoDelete(TRUE); + QPtrList<QPoint> points; + points.setAutoDelete(TRUE); + uint nm = pinfo.nbBlockModes(); + for (uint i=0; i<size(); i++) { + for (uint k=0; k<2; k++) + for (uint j=0; j<nm; j++) { + QPoint *po = new QPoint(0, 0); + QPixmap *pi = pinfo.pixmap(bsize, i, j, k==1); + if ( at(i) ) { + at(i)->setImage(k*nm + j, new QCanvasPixmap(*pi, *po)); + delete po; + delete pi; + } else { + points.append(po); + pixmaps.append(pi); + } + } + if ( at(i)==0 ) { + at(i) = new QCanvasPixmapArray(pixmaps, points); + pixmaps.clear(); + points.clear(); + } + } +} + +SequenceArray::~SequenceArray() +{ + for (uint i=0; i<size(); i++) delete at(i); +} + +//----------------------------------------------------------------------------- +BlockInfo::BlockInfo(const SequenceArray &s) +: _sequences(s) +{} + +QPoint BlockInfo::toPoint(const Coord &pos) const +{ + return pos * _sequences.blockSize(); +} + +//----------------------------------------------------------------------------- +Block::Block(uint value) +: _value(value), _sprite(0) +{} + +Block::~Block() +{ + delete _sprite; +} + +void Block::setValue(uint value, BlockInfo *binfo) +{ + _value = value; + if (binfo) { + QCanvasPixmapArray *seq = binfo->sequences()[value]; + if (_sprite) _sprite->setSequence(seq); + else { + _sprite = new QCanvasSprite(seq, binfo); + _sprite->setZ(0); + } + } +} + +void Block::toggleLight() +{ + const GPieceInfo &pinfo = Piece::info(); + uint f = _sprite->frame() + pinfo.nbBlockModes() + * (_sprite->frame()>=(int)pinfo.nbBlockModes() ? -1 : 1); + _sprite->setFrame(f); +} + +bool Block::isGarbage() const +{ + return Piece::info().isGarbage(_value); +} + + +//----------------------------------------------------------------------------- +GPieceInfo *Piece::_info = 0; + +Piece::Piece() + : _binfo(0), _i(0), _j(0) +{ + _blocks.setAutoDelete(true); +} + +void Piece::rotate(bool left, const QPoint &p) +{ + if (left) { + if ( _rotation==0 ) _rotation = 3; + else _rotation--; + } else { + if ( _rotation==3 ) _rotation = 0; + else _rotation++; + } + + uint form = _info->form(_type); + _i = _info->i(form, _rotation); + _j = _info->j(form, _rotation); + if (_binfo) move(p); +} + +Coord Piece::min() const +{ + if ( _i==0 || _j==0 ) return Coord(0, 0); + Coord min = coord(0); + for(uint k=1; k<_info->nbBlocks(); k++) + min = minimum(min, coord(k)); + return min; +} + +Coord Piece::max() const +{ + if ( _i==0 || _j==0 ) return Coord(0, 0); + Coord max = coord(0); + for(uint k=1; k<_info->nbBlocks(); k++) + max = maximum(max, coord(k)); + return max; +} + +void Piece::copy(const Piece *p) +{ + if ( p->_blocks.size()!=0 ) { + _blocks.resize(p->_blocks.size()); + for (uint k=0; k<_blocks.size(); k++) { + if ( _blocks[k]==0 ) _blocks.insert(k, new Block); + _blocks[k]->setValue(p->_blocks[k]->value(), _binfo); + } + } + _type = p->_type; + _random = p->_random; + _rotation = p->_rotation; + _i = p->_i; + _j = p->_j; +} + +void Piece::generateNext(int type) +{ + if ( _blocks.size()==0 ) { + _blocks.resize(_info->nbBlocks()); + for (uint k=0; k<_blocks.size(); k++) _blocks.insert(k, new Block); + } + _type = (type==-1 ? _info->generateType(_random) : (uint)type ); + _rotation = 0; + + uint form = _info->form(_type); + _i = _info->i(form, _rotation); + _j = _info->j(form, _rotation); + + for (uint k=0; k<_blocks.size(); k++) + _blocks[k]->setValue(_info->value(_type, k), _binfo); +} + +void Piece::moveCenter() +{ + uint s = _binfo->sequences().blockSize(); + QPoint p = QPoint(_binfo->width(), _binfo->height()) - size() * s; + move(p/2 - min() * s); +} + +Coord Piece::pos(uint k, const Coord &pos) const +{ + return Coord(pos.first + coord(k).first, pos.second - coord(k).second); +} + +void Piece::move(const QPoint &p) +{ + for (uint k=0; k<_blocks.size(); k++) moveBlock(k, p); +} + +void Piece::moveBlock(uint k, const QPoint &p) +{ + QPoint po = p + _binfo->toPoint(coord(k)); + _blocks[k]->sprite()->move(po.x(), po.y()); +} + +Block *Piece::garbageBlock() const +{ + Block *b = new Block; + b->setValue(_info->generateGarbageBlockType(_random), _binfo); + return b; +} + +Block *Piece::takeBlock(uint k) +{ + Block *b = _blocks.take(k); + _blocks.insert(k, new Block); + return b; +} + +void Piece::show(bool show) +{ + for (uint k=0; k<_blocks.size(); k++) { + if (show) _blocks[k]->sprite()->show(); + else _blocks[k]->sprite()->hide(); + } +} diff --git a/libksirtet/base/piece.h b/libksirtet/base/piece.h new file mode 100644 index 00000000..4c0486a8 --- /dev/null +++ b/libksirtet/base/piece.h @@ -0,0 +1,155 @@ +#ifndef BASE_PIECE_H +#define BASE_PIECE_H + +#include <qcanvas.h> +#include <qptrvector.h> + +#include <kgrid2d.h> + + +class KRandomSequence; + +//----------------------------------------------------------------------------- +class GPieceInfo +{ + public: + GPieceInfo(); + virtual ~GPieceInfo() {} + + virtual uint nbBlocks() const = 0; // nb of blocks in a piece + virtual uint nbTypes() const = 0; // nb of combin. of types in piece + virtual uint nbForms() const = 0; // nb of geometrical form of piece + + virtual const int *i(uint form, uint rotation) const = 0; + virtual const int *j(uint form, uint rotation) const = 0; + virtual uint value(uint type, uint n) const = 0; + virtual uint form(uint type) const = 0; + virtual uint nbConfigurations(uint type) const = 0; + uint generateType(KRandomSequence *) const; + + KGrid2D::Coord maxSize() const; + + QPixmap *pixmap(uint blockSize, uint blockType, uint blockMode, + bool lighted) const; + + virtual uint nbNormalBlockTypes() const = 0; + virtual uint nbGarbageBlockTypes() const = 0; + virtual uint nbBlockModes() const = 0; // nb of modes per block + bool isGarbage(uint type) const { return type>=nbNormalBlockTypes(); } + uint generateGarbageBlockType(KRandomSequence *) const; + + virtual uint nbColors() const = 0; + virtual QString colorLabel(uint i) const = 0; + QCString colorKey(uint i) const; + virtual QColor defaultColor(uint i) const = 0; + void loadColors(); + + protected: + QColor color(uint i) const { return _colors[i]; } + + virtual void draw(QPixmap *, uint blockType, uint blockMode, + bool lighted) const = 0; + virtual void setMask(QPixmap *, uint /*blockMode*/) const {} + + private: + QValueVector<QColor> _colors; +}; + +class SequenceArray : public QMemArray<QCanvasPixmapArray *> +{ + public: + SequenceArray(); + ~SequenceArray(); + + void setBlockSize(uint size); + uint blockSize() const { return _size; } + + private: + uint _size; +}; + +//----------------------------------------------------------------------------- +class BlockInfo : public QCanvas +{ + public: + BlockInfo(const SequenceArray &); + const SequenceArray &sequences() const { return _sequences; } + + QPoint toPoint(const KGrid2D::Coord &) const; + + private: + const SequenceArray &_sequences; +}; + +//----------------------------------------------------------------------------- +class Block +{ + public: + Block(uint value = 0); + ~Block(); + + void setValue(uint, BlockInfo *); + uint value() const { return _value; } + bool isGarbage() const; + void toggleLight(); + QCanvasSprite *sprite() const { return _sprite; } + + private: + uint _value; + QCanvasSprite *_sprite; + + Block(const Block &); // disabled + Block &operator =(const Block &); // disabled +}; + +//----------------------------------------------------------------------------- +class Piece +{ + public: + Piece(); + + void copy(const Piece *); + void setBlockInfo(BlockInfo *bi) { _binfo = bi; } + static void setPieceInfo(GPieceInfo *pi) { _info = pi; } + static GPieceInfo &info() { return *_info; } + + uint type() const { return _type; } + uint nbBlocks() const { return _blocks.size(); } + uint nbConfigurations() const { return _info->nbConfigurations(_type); } + + int value(uint k) const { return _blocks[k]->value(); } + KGrid2D::Coord pos(uint k, const KGrid2D::Coord &) const; + + KGrid2D::Coord min() const; + KGrid2D::Coord max() const; + KGrid2D::Coord size() const { return max() - min() + KGrid2D::Coord(1, 1); } + + void generateNext(int type = -1); + void rotate(bool left, const QPoint &); + void move(const QPoint &); + void moveCenter(); + void show(bool show); + + void setRandomSequence(KRandomSequence *random) { _random = random; } + + Block *garbageBlock() const; + Block *takeBlock(uint k); + + private: + QPtrVector<Block> _blocks; + uint _type; + KRandomSequence *_random; + static GPieceInfo *_info; + BlockInfo *_binfo; + uint _rotation; + int const *_i; + int const *_j; + + Piece(const Piece &); // disabled + Piece &operator =(const Piece &); // disabled + + KGrid2D::Coord coord(uint k) const { return KGrid2D::Coord(_i[k], _j[k]); } + void moveBlock(uint k, const QPoint &); +}; + +#endif diff --git a/libksirtet/base/settings.cpp b/libksirtet/base/settings.cpp new file mode 100644 index 00000000..1ea3b16a --- /dev/null +++ b/libksirtet/base/settings.cpp @@ -0,0 +1,84 @@ +#include "settings.h" +#include "settings.moc" + +#include <qlabel.h> +#include <qhbox.h> +#include <qlayout.h> +#include <qcheckbox.h> +#include <qhgroupbox.h> + +#include <klocale.h> +#include <knuminput.h> +#include <kcolorbutton.h> +#include <kapplication.h> +#include <kdialogbase.h> + +#include "piece.h" +#include "factory.h" + + +//----------------------------------------------------------------------------- +BaseAppearanceConfig::BaseAppearanceConfig() + : QWidget(0, "appearance_config") +{ + QVBoxLayout *top = new QVBoxLayout(this); + + // upper part + _main = new QWidget(this); + top->addWidget(_main); + _grid = new QGridLayout(_main, 3, 2, 0, KDialog::spacingHint()); + _grid->setColStretch(1, 1); + + QCheckBox *chb = + new QCheckBox(i18n("Enable animations"), _main, "kcfg_AnimationsEnabled"); + _grid->addMultiCellWidget(chb, 2, 2, 0, 1); + + top->addSpacing(KDialog::spacingHint()); + + // lower part + QHGroupBox *gbox = new QHGroupBox(i18n("Background"), this); + top->addWidget(gbox); + QWidget *widget = new QWidget(gbox); + QGridLayout *grid = + new QGridLayout(widget, 2, 3, 0, KDialog::spacingHint()); + grid->setColStretch(2, 1); + QLabel *label = new QLabel(i18n("Color:"), widget); + grid->addWidget(label, 0, 0); + KColorButton *cob = new KColorButton(widget, "kcfg_FadeColor"); + cob->setFixedWidth(100); + grid->addWidget(cob, 0, 1); + label = new QLabel(i18n("Opacity:"), widget); + grid->addWidget(label, 1, 0); + KDoubleNumInput *dn = new KDoubleNumInput(widget, "kcfg_FadeIntensity"); + dn->setRange(0.0, 1.0, 0.01); + grid->addMultiCellWidget(dn, 1, 1, 1, 2); + + top->addStretch(1); +} + +//----------------------------------------------------------------------------- +ColorConfig::ColorConfig() + : QWidget(0, "color_config") +{ + const GPieceInfo &info = Piece::info(); + QVBoxLayout *top = new QVBoxLayout(this); + uint nb = info.nbColors(); + QGridLayout *grid = new QGridLayout(top, nb+1, 3, KDialog::spacingHint()); + grid->setColStretch(2, 1); + for (uint i=0; i<nb; i++) { + QLabel *label = new QLabel(info.colorLabel(i), this); + grid->addWidget(label, i, 0); + KColorButton *cob = new KColorButton(this, colorKey(i)); + cob->setFixedWidth(100); + grid->addWidget(cob, i, 1); + } + grid->setRowStretch(nb, 1); +} + +QCString ColorConfig::colorKey(uint i) +{ + QCString s; + s.setNum(i); + return "kcfg_Color" + s; +} + diff --git a/libksirtet/base/settings.h b/libksirtet/base/settings.h new file mode 100644 index 00000000..c64bfd5b --- /dev/null +++ b/libksirtet/base/settings.h @@ -0,0 +1,33 @@ +#ifndef BASE_SETTINGS_H +#define BASE_SETTINGS_H + +#include <qwidget.h> +#include <kconfig.h> + +class QGridLayout; + + +//----------------------------------------------------------------------------- +class BaseAppearanceConfig : public QWidget +{ + Q_OBJECT +public: + BaseAppearanceConfig(); + +protected: + QWidget *_main; + QGridLayout *_grid; +}; + +//----------------------------------------------------------------------------- +class ColorConfig : public QWidget +{ + Q_OBJECT +public: + ColorConfig(); + +private: + static QCString colorKey(uint i); +}; + +#endif |