• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kmahjongg

Editor.cpp

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 1997 Mathias Mueller   <in5y158@public.uni-hamburg.de>
00003     Copyright (C) 2006 Mauricio Piacentini   <mauricio@tabuleiro.com>
00004 
00005     Kmahjongg is free software; you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or
00008     (at your option) any later version.
00009 
00010     This program is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with this program; if not, write to the Free Software
00017     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018 */
00019 
00020 #include "Editor.h"
00021 
00022 #include <QLabel>
00023 #include <qevent.h>
00024 #include <qpainter.h>
00025 
00026 #include "prefs.h"
00027 
00028 #include <kmessagebox.h>
00029 #include <kcomponentdata.h>
00030 #include <klocale.h>     // Needed to use KLocale
00031 #include <kstandarddirs.h>
00032 #include <kaction.h>
00033 #include <kactioncollection.h>
00034 #include <ktoggleaction.h>
00035 #include <kstandardaction.h>
00036 #include <kicon.h>
00037 
00038 // When we assign a tile to draw in a slot we do it in order from te following
00039 // table, wrapping on the tile number. It makes the tile layout look more
00040 // random.
00041 
00042 
00043 Editor::Editor ( QWidget* parent)
00044     : KDialog( parent ), tiles()
00045 {
00046     setModal(true);
00047     clean= true;
00048     numTiles=0;
00049     mode = insert;
00050 
00051     QString tile = Prefs::tileSet();
00052     if (!tiles.loadTileset(tile)) tiles.loadDefault();
00053 
00054     //TODO delay this initialization, must define board dimensions
00055     int sWidth = ( theBoard.m_width+2)*(tiles.qWidth());
00056     int sHeight =( theBoard.m_height+2)*tiles.qHeight();
00057 
00058     sWidth += 4*tiles.levelOffsetX();
00059 
00060     drawFrame = new FrameImage( this, QSize(sWidth, sHeight) );
00061     drawFrame->setGeometry( 10, 40 ,sWidth ,sHeight);
00062     drawFrame->setMinimumSize( 0, 0 );
00063     drawFrame->setMaximumSize( 32767, 32767 );
00064     drawFrame->setFocusPolicy( Qt::NoFocus );
00065     //drawFrame->setFrameStyle( 49 );
00066     drawFrame->setMouseTracking(true);
00067 
00068     // setup the tool bar
00069     setupToolbar();
00070 
00071     QVBoxLayout *layout = new QVBoxLayout(this);
00072     layout->addWidget(topToolbar,0);
00073     layout->addWidget(drawFrame,1);
00074     layout->activate();
00075 
00076     resize( sWidth+60, sHeight+60);
00077     //toolbar will set our minimum height
00078     setMinimumHeight(120);
00079 
00080     // tell the user what we do
00081     setCaption(i18n("Edit Board Layout"));
00082 
00083     connect( drawFrame, SIGNAL(mousePressed(QMouseEvent *) ),
00084              SLOT(drawFrameMousePressEvent(QMouseEvent *)));
00085     connect( drawFrame, SIGNAL(mouseMoved(QMouseEvent *) ),
00086              SLOT(drawFrameMouseMovedEvent(QMouseEvent *)));
00087 
00088     statusChanged();
00089 
00090     update();
00091 }
00092 
00093 
00094 
00095 Editor::~Editor()
00096 {
00097 }
00098 
00099 void Editor::resizeEvent ( QResizeEvent * event )
00100 {
00101     QSize newtiles = tiles.preferredTileSize(event->size(), (theBoard.m_width+2)/2,( theBoard.m_height+2)/2);
00102     tiles.reloadTileset(newtiles);
00103 }
00104 
00105 // ---------------------------------------------------------
00106 void Editor::setupToolbar()
00107 {
00108 
00109     topToolbar = new KToolBar( this, "editToolBar" );
00110     topToolbar->setToolButtonStyle( Qt::ToolButtonIconOnly );
00111 
00112     actionCollection = new KActionCollection(this);
00113     // new game
00114     QAction* newBoard = actionCollection->addAction("new_board");
00115     newBoard->setIcon(KIcon("document-new"));
00116     newBoard->setText(i18n("New board"));
00117     connect(newBoard, SIGNAL(triggered(bool)), SLOT(newBoard()));
00118     topToolbar->addAction(newBoard);
00119     // open game
00120     QAction* openBoard = actionCollection->addAction("open_board");
00121     openBoard->setIcon(KIcon("document-open"));
00122     openBoard->setText(i18n("Open board"));
00123     connect(openBoard, SIGNAL(triggered(bool)), SLOT(loadBoard()));
00124     topToolbar->addAction(openBoard);
00125     // save game
00126     QAction* saveBoard = actionCollection->addAction("save_board");
00127     saveBoard->setIcon(KIcon("document-save"));
00128     saveBoard->setText(i18n("Save board"));
00129     connect(saveBoard, SIGNAL(triggered(bool)), SLOT(saveBoard()));
00130     topToolbar->addAction(saveBoard);
00131     // NOTE dimsuz: how to port this? is it even needed?
00132     //topToolbar->setButtonIconSet(ID_TOOL_SAVE,loader->loadIconSet("document-save", KIconLoader::Toolbar));
00133 
00134     topToolbar->addSeparator();
00135 #ifdef FUTURE_OPTIONS
00136     // Select
00137     QAction* select = actionCollection->addAction("select");
00138     select->setIcon(KIcon("rectangle_select"));
00139     select->setText(i18n("Select"));
00140     topToolbar->addAction(select);
00141 
00142     // NOTE: use kstandarddactions?
00143     QAction* cut = actionCollection->addAction("edit_cut");
00144     cut->setIcon(KIcon("edit-cut"));
00145     cut->setText(i18n("Cut"));
00146     topToolbar->addAction(cut);
00147 
00148     QAction* copy = actionCollection->addAction("edit_copy");
00149     copy->setIcon(KIcon("edit-copy"));
00150     copy->setText(i18n("Copy"));
00151     topToolbar->addAction(copy);
00152 
00153     QAction* paste = actionCollection->addAction("edit_paste");
00154     paste->setIcon(KIcon("edit-paste"));
00155     paste->setText(i18n("Paste"));
00156     topToolbar->addAction(paste);
00157 
00158     topToolbar->addSeparator();
00159 
00160     QAction* moveTiles = actionCollection->addAction("move_tiles");
00161     moveTiles->setIcon(KIcon("move"));
00162     moveTiles->setText(i18n("Move tiles"));
00163     topToolbar->addAction(moveTiles);
00164 #endif
00165     KToggleAction* addTiles = new KToggleAction(KIcon("draw-freehand"), i18n("Add tiles"), this);
00166     actionCollection->addAction("add_tiles", addTiles);
00167     topToolbar->addAction(addTiles);
00168     KToggleAction* delTiles = new KToggleAction(KIcon("edit-delete"), i18n("Remove tiles"), this);
00169     actionCollection->addAction("del_tiles", delTiles);
00170     topToolbar->addAction(delTiles);
00171 
00172     QActionGroup* radioGrp = new QActionGroup(this);
00173     radioGrp->setExclusive(true);
00174     radioGrp->addAction(addTiles);
00175     addTiles->setChecked(true);
00176 #ifdef FUTURE_OPTIONS
00177     radioGrp->addAction(moveTiles);
00178 #endif
00179     radioGrp->addAction(delTiles);
00180     connect(radioGrp, SIGNAL(triggered(QAction*)), SLOT(slotModeChanged(QAction*)));
00181 
00182     // board shift
00183 
00184     topToolbar->addSeparator();
00185 
00186     // NOTE: maybe join shiftActions in QActionGroup and create one slot(QAction*) instead of 4 slots? ;)
00187     // Does this makes sense? dimsuz
00188     QAction* shiftLeft = actionCollection->addAction("shift_left");
00189     shiftLeft->setIcon(KIcon("go-previous"));
00190     shiftLeft->setText(i18n("Shift left"));
00191     connect(shiftLeft, SIGNAL(triggered(bool)), SLOT(slotShiftLeft()));
00192     topToolbar->addAction(shiftLeft);
00193 
00194     QAction* shiftUp = actionCollection->addAction("shift_up");
00195     shiftUp->setIcon(KIcon("go-up"));
00196     shiftUp->setText(i18n("Shift up"));
00197     connect(shiftUp, SIGNAL(triggered(bool)), SLOT(slotShiftUp()));
00198     topToolbar->addAction(shiftUp);
00199 
00200     QAction* shiftDown = actionCollection->addAction("shift_down");
00201     shiftDown->setIcon(KIcon("go-down"));
00202     shiftDown->setText(i18n("Shift down"));
00203     connect(shiftDown, SIGNAL(triggered(bool)), SLOT(slotShiftDown()));
00204     topToolbar->addAction(shiftDown);
00205 
00206     QAction* shiftRight = actionCollection->addAction("shift_right");
00207     shiftRight->setIcon(KIcon("go-next"));
00208     shiftRight->setText(i18n("Shift right"));
00209     connect(shiftRight, SIGNAL(triggered(bool)), SLOT(slotShiftRight()));
00210     topToolbar->addAction(shiftRight);
00211 
00212     topToolbar->addSeparator();
00213     QAction* quit = actionCollection->addAction(KStandardAction::Quit, "quit",
00214                                                 this, SLOT(close()));
00215     topToolbar->addAction(quit);
00216 
00217     // status in the toolbar for now (ick)
00218 
00219     QWidget *hbox = new QWidget(topToolbar);
00220     QHBoxLayout *layout = new QHBoxLayout(hbox);
00221     layout->setMargin(0);
00222     layout->setSpacing(0);
00223     layout->addStretch();
00224 
00225     theLabel = new QLabel(statusText(), hbox);
00226     layout->addWidget(theLabel);
00227     topToolbar->addWidget(hbox);
00228 
00229     topToolbar->adjustSize();
00230     setMinimumWidth(topToolbar->width());
00231 }
00232 
00233 void Editor::statusChanged() {
00234     bool canSave = ((numTiles !=0) && ((numTiles & 1) == 0));
00235     theLabel->setText(statusText());
00236     actionCollection->action("save_board")->setEnabled(canSave);
00237 }
00238 
00239 void Editor::slotShiftLeft()
00240 {
00241     theBoard.shiftLeft();
00242     update();
00243 }
00244 
00245 void Editor::slotShiftRight()
00246 {
00247     theBoard.shiftRight();
00248     update();
00249 }
00250 
00251 void Editor::slotShiftUp()
00252 {
00253     theBoard.shiftUp();
00254     update();
00255 }
00256 
00257 void Editor::slotShiftDown()
00258 {
00259     theBoard.shiftDown();
00260     update();
00261 }
00262 
00263 void Editor::slotModeChanged(QAction* act)
00264 {
00265     if(act == actionCollection->action("move_tiles"))
00266     {
00267         mode = move;
00268     }
00269     else if(act == actionCollection->action("del_tiles"))
00270     {
00271         mode = remove;
00272     }
00273     else if(act == actionCollection->action("add_tiles"))
00274     {
00275         mode = insert;
00276     }
00277 }
00278 
00279 QString Editor::statusText() {
00280     QString buf;
00281 
00282     int x=currPos.x;
00283     int y=currPos.y;
00284     int z= currPos.e;
00285 
00286     if (z == 100)
00287         z = 0;
00288     else
00289         z=z+1;
00290 
00291     if (x >= theBoard.m_width || x <0 || y >=theBoard.m_height || y <0)
00292         x = y = z = 0;
00293 
00294     buf = i18n("Tiles: %1 Pos: %2,%3,%4", numTiles, x, y, z);
00295     return buf;
00296 }
00297 
00298 
00299 void Editor::loadBoard() {
00300 
00301     if ( !testSave() )
00302     return;
00303 
00304     KUrl url = KFileDialog::getOpenUrl(
00305                 KUrl(),
00306                 i18n("*.layout|Board Layout (*.layout)\n"
00307                 "*|All Files"),
00308                 this,
00309                 i18n("Open Board Layout" ));
00310 
00311    if ( url.isEmpty() )
00312         return;
00313 
00314 
00315     theBoard.loadBoardLayout( url.path() );
00316     update();
00317 }
00318 
00319 
00320 // Clear out the contents of the board. Repaint the screen
00321 // set values to their defaults.
00322 void Editor::newBoard() {
00323     if (!testSave())
00324     return;
00325 
00326     theBoard.clearBoardLayout();
00327 
00328     clean=true;
00329     numTiles=0;
00330     statusChanged();
00331     update();
00332 }
00333 
00334 bool Editor::saveBoard() {
00335     // get a save file name
00336     KUrl url = KFileDialog::getSaveUrl(
00337                 KUrl(),
00338                 i18n("*.layout|Board Layout (*.layout)\n"
00339                 "*|All Files"),
00340                 this,
00341                 i18n("Save Board Layout" ));
00342 
00343    if ( url.isEmpty() )
00344        return false;
00345 
00346    if( !url.isLocalFile() )
00347    {
00348       KMessageBox::sorry( this, i18n( "Only saving to local files currently supported." ) );
00349       return false;
00350    }
00351 
00352 
00353     QFileInfo f( url.path() );
00354     if ( f.exists() ) {
00355     // if it already exists, querie the user for replacement
00356     int res=KMessageBox::warningContinueCancel(this,
00357             i18n("A file with that name "
00358                        "already exists. Do you "
00359                        "wish to overwrite it?"),
00360                     i18n("Save Board Layout" ), KStandardGuiItem::save());
00361     if (res != KMessageBox::Continue)
00362         return false;
00363     }
00364 
00365     bool result = theBoard.saveBoardLayout( url.path() );
00366     if (result==true){
00367         clean = true;
00368         return true;
00369     } else {
00370     return false;
00371     }
00372 }
00373 
00374 // test if a save is required and return true if the app is to continue
00375 // false if cancel is selected. (if ok then call out to save the board
00376 bool Editor::testSave()
00377 {
00378 
00379     if (clean)
00380     return(true);
00381 
00382     int res;
00383     res=KMessageBox::warningYesNoCancel(this,
00384     i18n("The board has been modified. Would you "
00385         "like to save the changes?"), QString(), KStandardGuiItem::save(),KStandardGuiItem::dontSave());
00386 
00387     if (res == KMessageBox::Yes) {
00388     // yes to save
00389     if (saveBoard()) {
00390         return true;
00391     } else {
00392         KMessageBox::sorry(this, i18n("Save failed. Aborting operation."));
00393     }
00394     } else {
00395     return (res != KMessageBox::Cancel);
00396     }
00397     return(true);
00398 }
00399 
00400 
00401 // The main paint event, draw in the grid and blit in
00402 // the tiles as specified by the layout.
00403 
00404 void Editor::paintEvent( QPaintEvent*  ) {
00405     // first we layer on a background grid
00406     QPixmap buff;
00407     QPixmap *dest=drawFrame->getPreviewPixmap();
00408     buff = QPixmap(dest->width(), dest->height());
00409     drawBackground(&buff);
00410     drawTiles(&buff);
00411     QPainter p(dest);
00412     p.drawPixmap(0,0, buff);
00413     p.end();
00414 
00415     drawFrame->update();
00416 }
00417 
00418 void Editor::drawBackground(QPixmap *pixmap) {
00419 
00420     QPainter p(pixmap);
00421 
00422     // blast in a white background
00423     p.fillRect(0,0,pixmap->width(), pixmap->height(), Qt::white);
00424 
00425 
00426     // now put in a grid of tile quater width squares
00427     int sy = (tiles.height()/2)+tiles.levelOffsetX();
00428     int sx = (tiles.width()/2);
00429 
00430     for (int y=0; y<=theBoard.m_height; y++) {
00431     int nextY=sy+(y*tiles.qHeight());
00432     p.drawLine(sx, nextY,sx+(theBoard.m_width*tiles.qWidth()), nextY);
00433     }
00434 
00435     for (int x=0; x<=theBoard.m_width; x++) {
00436     int nextX=sx+(x*tiles.qWidth());
00437     p.drawLine(nextX, sy, nextX, sy+theBoard.m_height*tiles.qHeight());
00438     }
00439 }
00440 
00441 void Editor::drawTiles(QPixmap *dest) {
00442 
00443     QPainter p(dest);
00444 
00445     int xOffset = tiles.width()/2;
00446     int yOffset = tiles.height()/2;
00447     short tile = 0;
00448 
00449     // we iterate over the depth stacking order. Each successive level is
00450     // drawn one indent up and to the right. The indent is the width
00451     // of the 3d relief on the tile left (tile shadow width)
00452     for (int z=0; z< theBoard.m_depth; z++) {
00453         // we draw down the board so the tile below over rights our border
00454         for (int y = 0; y < theBoard.m_height; y++) {
00455             // drawing right to left to prevent border overwrite
00456             for (int x= theBoard.m_width-1; x>=0; x--) {
00457                 int sx = x*(tiles.qWidth()  )+xOffset;
00458                 int sy = y*(tiles.qHeight()  )+yOffset;
00459                 if (theBoard.getBoardData(z, y, x) != '1') {
00460                     continue;
00461                 }
00462         QPixmap t;
00463         tile=(z*theBoard.m_depth)+
00464             (y*theBoard.m_height)+
00465                 (x*theBoard.m_width);
00466 //      if (mode==remove && currPos.x==x && currPos.y==y && currPos.e==z) {
00467 //                   t = tiles.selectedPixmaps(44));
00468 //      } else {
00469                    t = tiles.unselectedTile(0);
00470 //      }
00471 
00472                 // Only one compilcation. Since we render top to bottom , left
00473                 // to right situations arise where...:
00474                 // there exists a tile one q height above and to the left
00475                 // in this situation we would draw our top left border over it
00476                 // we simply split the tile draw so the top half is drawn
00477                 // minus border
00478                 if ((x>1) && (y>0) && theBoard.getBoardData(z,y-1,x-2)=='1'){
00479                     p.drawPixmap( sx+tiles.levelOffsetX(), sy,
00480                             t, tiles.levelOffsetX() ,0,
00481                             t.width()-tiles.levelOffsetX(),
00482                             t.height()/2);
00483 
00484 
00485                     p.drawPixmap( sx, sy+t.height()/2,
00486                         t, 0,t.height()/2,t.width(),t.height()/2);
00487                 } else {
00488 
00489                 p.drawPixmap(sx, sy,
00490                     t, 0,0, t.width(), t.height());
00491                 }
00492 
00493 
00494                 tile++;
00495                 tile = tile % 143;
00496             }
00497         }
00498         xOffset +=tiles.levelOffsetX();
00499         yOffset -=tiles.levelOffsetY();
00500     }
00501 }
00502 
00503 
00504 // convert mouse position on screen to a tile z y x coord
00505 // different to the one in kmahjongg.cpp since if we hit ground
00506 // we return a result too.
00507 
00508 void Editor::transformPointToPosition(
00509         const QPoint& point,
00510         POSITION& MouseClickPos,
00511     bool align)
00512 {
00513 
00514     short z = 0; // shut the compiler up about maybe uninitialised errors
00515     short y = 0;
00516     short x = 0;
00517     MouseClickPos.e = 100;
00518 
00519     // iterate over z coordinate from top to bottom
00520     for( z=theBoard.m_depth-1; z>=0; z-- )
00521     {
00522         // calculate mouse coordiantes --> position in game board
00523     // the factor -theTiles.width()/2 must keep track with the
00524     // offset for blitting in the print zvent (FIX ME)
00525         x = ((point.x()-tiles.width()/2)-(z+1)*tiles.levelOffsetX())/ tiles.qWidth();
00526         y = ((point.y()-tiles.height()/2)+ z*tiles.levelOffsetX()) / tiles.qHeight();
00527 
00528 
00529         // skip when position is illegal
00530         if (x<0 || x>=theBoard.m_width || y<0 || y>=theBoard.m_height)
00531         continue;
00532 
00533         //
00534         switch( theBoard.getBoardData(z,y,x) )
00535         {
00536     case (UCHAR)'3':    if (align) {
00537                     x--;
00538                                     y--;
00539                             }
00540                                 break;
00541 
00542             case (UCHAR)'2':    if (align)
00543                     x--;
00544                                 break;
00545 
00546             case (UCHAR)'4':    if (align)
00547                     y--;
00548                                 break;
00549 
00550             case (UCHAR)'1':    break;
00551 
00552             default :           continue;
00553         }
00554         // if gameboard is empty, skip
00555         if ( ! theBoard.getBoardData(z,y,x) )
00556         continue;
00557 
00558         // here, position is legal
00559         MouseClickPos.e = z;
00560         MouseClickPos.y = y;
00561         MouseClickPos.x = x;
00562         MouseClickPos.f = theBoard.getBoardData(z,y,x);
00563     break;
00564     }
00565     if (MouseClickPos.e == 100) {
00566         MouseClickPos.x = x;
00567         MouseClickPos.y = y;
00568         MouseClickPos.f=0;
00569     }
00570 }
00571 
00572 
00573 // we swallow the draw frames mouse clicks and process here
00574 void Editor::drawFrameMousePressEvent( QMouseEvent* e )
00575 {
00576 
00577     POSITION mPos;
00578     transformPointToPosition(e->pos(), mPos, (mode == remove));
00579 
00580     switch (mode) {
00581         case remove:
00582             if (!theBoard.tileAbove(mPos) && mPos.e < theBoard.m_depth && theBoard.isTileAt(mPos) ) {
00583             theBoard.deleteTile(mPos);
00584             numTiles--;
00585             statusChanged();
00586             drawFrameMouseMovedEvent(e);
00587                         update();
00588             }
00589         break;
00590         case insert: {
00591             POSITION n = mPos;
00592             if (n.e == 100)
00593             n.e = 0;
00594             else
00595             n.e += 1;
00596             if (canInsert(n)) {
00597             theBoard.insertTile(n);
00598             numTiles++;
00599             statusChanged();
00600             update();
00601             }
00602           }
00603         break;
00604         default:
00605         break;
00606     }
00607 
00608 }
00609 
00610 
00611 void Editor::drawCursor(POSITION &p, bool visible)
00612 {
00613     int x = (tiles.width()/2)+(p.e*tiles.levelOffsetX())+(p.x * tiles.qWidth());
00614     int y = (tiles.height()/2)-(p.e*tiles.levelOffsetX())+(p.y * tiles.qHeight());
00615     int w = tiles.width();
00616     int h = tiles.height();
00617 
00618 
00619     if (p.e==100 || !visible)
00620     x = -1;
00621     drawFrame->setRect(x,y,w,h, tiles.levelOffsetX(), mode-remove);
00622     drawFrame->update();
00623 }
00624 
00625 
00626 
00627 // we swallow the draw frames mouse moves and process here
00628 void Editor::drawFrameMouseMovedEvent( QMouseEvent* e ){
00629 
00630     POSITION mPos;
00631     transformPointToPosition(e->pos(), mPos, (mode == remove));
00632 
00633     if ((mPos.x==currPos.x) && (mPos.y==currPos.y) && (mPos.e==currPos.e))
00634     return;
00635     currPos = mPos;
00636 
00637     statusChanged();
00638 
00639     switch(mode) {
00640     case insert: {
00641         POSITION next;
00642         next = currPos;
00643         if (next.e == 100)
00644             next.e = 0;
00645         else
00646             next.e += 1;
00647 
00648         drawCursor(next, canInsert(next));
00649     break;
00650     }
00651     case remove:
00652             drawCursor(currPos, 1);
00653     break;
00654 
00655     case move:
00656 
00657     break;
00658 
00659     }
00660 }
00661 
00662 // can we inser a tile here. We can iff
00663 //  there are tiles in all positions below us (or we are a ground level)
00664 //  there are no tiles intersecting with us on this level
00665 
00666 bool Editor::canInsert(POSITION &p) {
00667 
00668 
00669     if (p.e >= theBoard.m_depth)
00670     return (false);
00671     if (p.y >theBoard.m_height-2)
00672     return false;
00673     if (p.x >theBoard.m_width-2)
00674     return false;
00675 
00676     POSITION n = p;
00677     if (p.e != 0) {
00678     n.e -= 1;
00679     if (!theBoard.allFilled(n)) {
00680         return(false);
00681     }
00682     }
00683     int any = theBoard.anyFilled(p);
00684     return(!any);
00685 
00686 }
00687 
00688 
00689 
00690 #include "Editor.moc"

kmahjongg

Skip menu "kmahjongg"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members

API Reference

Skip menu "API Reference"
  • kblackbox
  • kgoldrunner
  • kmahjongg
  • ksquares
  • libkdegames
  •   highscore
  •   kgame
  •   kggzgames
  •   kggzmod
  •   kggznet
  • libkmahjongg
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal