File indexing completed on 2024-03-24 04:05:15
0001 /* 0002 SPDX-FileCopyrightText: 1997 Mathias Mueller <in5y158@public.uni-hamburg.de> 0003 SPDX-FileCopyrightText: 2006 Mauricio Piacentini <mauricio@tabuleiro.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 // own 0009 #include "editor.h" 0010 0011 // Qt 0012 #include <QAction> 0013 #include <QFileDialog> 0014 #include <QFileInfo> 0015 #include <QGridLayout> 0016 #include <QIcon> 0017 #include <QLabel> 0018 #include <QPainter> 0019 #include <QResizeEvent> 0020 #include <QActionGroup> 0021 0022 // KF 0023 #include <KActionCollection> 0024 #include <KLocalizedString> 0025 #include <KMessageBox> 0026 #include <KStandardAction> 0027 #include <KToggleAction> 0028 0029 // KMahjongg 0030 #include "prefs.h" 0031 0032 Editor::Editor(QWidget * parent) 0033 : QDialog(parent) 0034 , m_mode(EditMode::insert) 0035 , m_borderLeft(0) 0036 , m_borderTop(0) 0037 , m_numTiles(0) 0038 , m_clean(true) 0039 , m_drawFrame(nullptr) 0040 , m_tiles() 0041 , m_theLabel(nullptr) 0042 , m_topToolbar(nullptr) 0043 , m_actionCollection(nullptr) 0044 { 0045 setModal(true); 0046 0047 QWidget * mainWidget = new QWidget(this); 0048 0049 QVBoxLayout * mainLayout = new QVBoxLayout(this); 0050 mainLayout->addWidget(mainWidget); 0051 0052 resize(QSize(800, 400)); 0053 0054 QGridLayout * gridLayout = new QGridLayout(mainWidget); 0055 QVBoxLayout * layout = new QVBoxLayout(); 0056 0057 setupToolbar(); 0058 layout->addWidget(m_topToolbar); 0059 0060 m_drawFrame = new FrameImage(this, QSize(0, 0)); 0061 m_drawFrame->setFocusPolicy(Qt::NoFocus); 0062 m_drawFrame->setMouseTracking(true); 0063 0064 layout->addWidget(m_drawFrame); 0065 gridLayout->addLayout(layout, 0, 0, 1, 1); 0066 0067 //toolbar will set our minimum height 0068 setMinimumHeight(120); 0069 0070 // tell the user what we do 0071 setWindowTitle(i18nc("@title:window", "Edit Board Layout")); 0072 0073 connect(m_drawFrame, &FrameImage::mousePressed, this, &Editor::drawFrameMousePressEvent); 0074 connect(m_drawFrame, &FrameImage::mouseMoved, this, &Editor::drawFrameMouseMovedEvent); 0075 0076 statusChanged(); 0077 0078 update(); 0079 } 0080 0081 Editor::~Editor() 0082 { 0083 } 0084 0085 void Editor::updateTileSize(const QSize size) 0086 { 0087 const int width = m_theBoard.getWidth(); 0088 const int height = m_theBoard.getHeight(); 0089 const QSize tileSize = m_tiles.preferredTileSize(size, width / 2, height / 2); 0090 0091 m_tiles.reloadTileset(tileSize); 0092 m_borderLeft = (m_drawFrame->size().width() - (width * m_tiles.qWidth())) / 2; 0093 m_borderTop = (m_drawFrame->size().height() - (height * m_tiles.qHeight())) / 2; 0094 } 0095 0096 void Editor::resizeEvent(QResizeEvent * event) 0097 { 0098 updateTileSize(event->size()); 0099 } 0100 0101 void Editor::setupToolbar() 0102 { 0103 m_topToolbar = new KToolBar(QStringLiteral("editToolBar"), this); 0104 m_topToolbar->setToolButtonStyle(Qt::ToolButtonIconOnly); 0105 0106 m_actionCollection = new KActionCollection(this); 0107 0108 // new game 0109 QAction * newBoard = m_actionCollection->addAction(QStringLiteral("new_board")); 0110 newBoard->setIcon(QIcon::fromTheme(QStringLiteral("document-new"))); 0111 newBoard->setText(i18n("New board")); 0112 connect(newBoard, &QAction::triggered, this, &Editor::newBoard); 0113 m_topToolbar->addAction(newBoard); 0114 0115 // open game 0116 QAction * openBoard = m_actionCollection->addAction(QStringLiteral("open_board")); 0117 openBoard->setIcon(QIcon::fromTheme(QStringLiteral("document-open"))); 0118 openBoard->setText(i18n("Open board")); 0119 connect(openBoard, &QAction::triggered, this, &Editor::loadBoard); 0120 m_topToolbar->addAction(openBoard); 0121 0122 // save game 0123 QAction * saveBoard = m_actionCollection->addAction(QStringLiteral("save_board")); 0124 saveBoard->setIcon(QIcon::fromTheme(QStringLiteral("document-save"))); 0125 saveBoard->setText(i18n("Save board")); 0126 connect(saveBoard, &QAction::triggered, this, &Editor::saveBoard); 0127 m_topToolbar->addAction(saveBoard); 0128 0129 m_topToolbar->addSeparator(); 0130 0131 #ifdef FUTURE_OPTIONS 0132 // Select 0133 QAction * select = actionCollection->addAction(QLatin1String("select")); 0134 select->setIcon(QIcon::fromTheme(QLatin1String("rectangle_select"))); 0135 select->setText(i18n("Select")); 0136 topToolbar->addAction(select); 0137 0138 QAction * cut = actionCollection->addAction(QLatin1String("edit_cut")); 0139 cut->setIcon(QIcon::fromTheme(QLatin1String("edit-cut"))); 0140 cut->setText(i18n("Cut")); 0141 topToolbar->addAction(cut); 0142 0143 QAction * copy = actionCollection->addAction(QLatin1String("edit_copy")); 0144 copy->setIcon(QIcon::fromTheme(QLatin1String("edit-copy"))); 0145 copy->setText(i18n("Copy")); 0146 topToolbar->addAction(copy); 0147 0148 QAction * paste = actionCollection->addAction(QLatin1String("edit_paste")); 0149 paste->setIcon(QIcon::fromTheme(QLatin1String("edit-paste"))); 0150 paste->setText(i18n("Paste")); 0151 topToolbar->addAction(paste); 0152 0153 topToolbar->addSeparator(); 0154 0155 QAction * moveTiles = actionCollection->addAction(QLatin1String("move_tiles")); 0156 moveTiles->setIcon(QIcon::fromTheme(QLatin1String("move"))); 0157 moveTiles->setText(i18n("Move tiles")); 0158 topToolbar->addAction(moveTiles); 0159 #endif 0160 0161 KToggleAction * addTiles = new KToggleAction(QIcon::fromTheme(QStringLiteral("draw-freehand")), i18n("Add tiles"), this); 0162 m_actionCollection->addAction(QStringLiteral("add_tiles"), addTiles); 0163 m_topToolbar->addAction(addTiles); 0164 KToggleAction * delTiles = new KToggleAction(QIcon::fromTheme(QStringLiteral("edit-delete")), i18n("Remove tiles"), this); 0165 m_actionCollection->addAction(QStringLiteral("del_tiles"), delTiles); 0166 m_topToolbar->addAction(delTiles); 0167 0168 QActionGroup * radioGrp = new QActionGroup(this); 0169 radioGrp->setExclusive(true); 0170 radioGrp->addAction(addTiles); 0171 addTiles->setChecked(true); 0172 0173 #ifdef FUTURE_OPTIONS 0174 radioGrp->addAction(moveTiles); 0175 #endif 0176 0177 radioGrp->addAction(delTiles); 0178 connect(radioGrp, &QActionGroup::triggered, this, &Editor::slotModeChanged); 0179 0180 // board shift 0181 0182 m_topToolbar->addSeparator(); 0183 0184 // NOTE: maybe join shiftActions in QActionGroup and create one slot(QAction*) instead of 4 slots? ;) 0185 // Does this makes sense? dimsuz 0186 QAction * shiftLeft = m_actionCollection->addAction(QStringLiteral("shift_left")); 0187 shiftLeft->setIcon(QIcon::fromTheme(QStringLiteral("go-previous"))); 0188 shiftLeft->setText(i18n("Shift left")); 0189 connect(shiftLeft, &QAction::triggered, this, &Editor::slotShiftLeft); 0190 m_topToolbar->addAction(shiftLeft); 0191 0192 QAction * shiftUp = m_actionCollection->addAction(QStringLiteral("shift_up")); 0193 shiftUp->setIcon(QIcon::fromTheme(QStringLiteral("go-up"))); 0194 shiftUp->setText(i18n("Shift up")); 0195 connect(shiftUp, &QAction::triggered, this, &Editor::slotShiftUp); 0196 m_topToolbar->addAction(shiftUp); 0197 0198 QAction * shiftDown = m_actionCollection->addAction(QStringLiteral("shift_down")); 0199 shiftDown->setIcon(QIcon::fromTheme(QStringLiteral("go-down"))); 0200 shiftDown->setText(i18n("Shift down")); 0201 connect(shiftDown, &QAction::triggered, this, &Editor::slotShiftDown); 0202 m_topToolbar->addAction(shiftDown); 0203 0204 QAction * shiftRight = m_actionCollection->addAction(QStringLiteral("shift_right")); 0205 shiftRight->setIcon(QIcon::fromTheme(QStringLiteral("go-next"))); 0206 shiftRight->setText(i18n("Shift right")); 0207 connect(shiftRight, &QAction::triggered, this, &Editor::slotShiftRight); 0208 m_topToolbar->addAction(shiftRight); 0209 0210 m_topToolbar->addSeparator(); 0211 QAction * quit = m_actionCollection->addAction(KStandardAction::Quit, QStringLiteral("quit")); 0212 connect(quit, &QAction::triggered, this, &Editor::close); 0213 m_topToolbar->addAction(quit); 0214 0215 // status in the toolbar for now (ick) 0216 QWidget * hbox = new QWidget(m_topToolbar); 0217 QHBoxLayout * layout = new QHBoxLayout(hbox); 0218 layout->setContentsMargins(0, 0, 0, 0); 0219 layout->setSpacing(0); 0220 layout->addStretch(); 0221 0222 m_theLabel = new QLabel(statusText(), hbox); 0223 layout->addWidget(m_theLabel); 0224 m_topToolbar->addWidget(hbox); 0225 0226 m_topToolbar->adjustSize(); 0227 setMinimumWidth(m_topToolbar->width()); 0228 } 0229 0230 void Editor::statusChanged() const 0231 { 0232 const bool canSave = ((m_numTiles != 0) && ((m_numTiles & 1) == 0)); 0233 m_theLabel->setText(statusText()); 0234 m_actionCollection->action(QStringLiteral("save_board"))->setEnabled(canSave); 0235 } 0236 0237 void Editor::slotShiftLeft() 0238 { 0239 m_theBoard.shiftLeft(); 0240 update(); 0241 } 0242 0243 void Editor::slotShiftRight() 0244 { 0245 m_theBoard.shiftRight(); 0246 update(); 0247 } 0248 0249 void Editor::slotShiftUp() 0250 { 0251 m_theBoard.shiftUp(); 0252 update(); 0253 } 0254 0255 void Editor::slotShiftDown() 0256 { 0257 m_theBoard.shiftDown(); 0258 update(); 0259 } 0260 0261 void Editor::slotModeChanged(QAction * act) 0262 { 0263 if (act == m_actionCollection->action(QStringLiteral("move_tiles"))) { 0264 m_mode = EditMode::move; 0265 } else if (act == m_actionCollection->action(QStringLiteral("del_tiles"))) { 0266 m_mode = EditMode::remove; 0267 } else if (act == m_actionCollection->action(QStringLiteral("add_tiles"))) { 0268 m_mode = EditMode::insert; 0269 } 0270 } 0271 0272 QString Editor::statusText() const 0273 { 0274 int x = m_curPos.x; 0275 int y = m_curPos.y; 0276 int z = m_curPos.z; 0277 0278 if (z == 100) { 0279 z = 0; 0280 } else { 0281 z = z + 1; 0282 } 0283 0284 if (x >= m_theBoard.getWidth() || x < 0 || y >= m_theBoard.getHeight() || y < 0) { 0285 x = y = z = 0; 0286 } 0287 0288 return i18n("Tiles: %1 Pos: %2,%3,%4", m_numTiles, x, y, z); 0289 } 0290 0291 void Editor::loadBoard() 0292 { 0293 if (!testSave()) { 0294 return; 0295 } 0296 0297 const QString filename = QFileDialog::getOpenFileName(this, i18n("Open Board Layout"), QString(), 0298 i18n("Board Layout (*.layout);;All Files (*)")); 0299 0300 if (filename.isEmpty()) { 0301 return; 0302 } 0303 0304 m_theBoard.loadBoardLayout(filename); 0305 update(); 0306 } 0307 0308 void Editor::newBoard() 0309 { 0310 // Clear out the contents of the board. Repaint the screen 0311 // set values to their defaults. 0312 0313 if (!testSave()) { 0314 return; 0315 } 0316 0317 m_theBoard.clearBoardLayout(); 0318 0319 m_clean = true; 0320 m_numTiles = 0; 0321 0322 statusChanged(); 0323 update(); 0324 } 0325 0326 bool Editor::saveBoard() 0327 { 0328 if (!((m_numTiles != 0) && ((m_numTiles & 1) == 0))) { 0329 KMessageBox::error(this, i18n("You can only save with a even number of tiles.")); 0330 0331 return false; 0332 } 0333 0334 // get a save file name 0335 const QString filename = QFileDialog::getSaveFileName(this, i18n("Save Board Layout"), QString(), 0336 i18n("Board Layout (*.layout);;All Files (*)")); 0337 0338 if (filename.isEmpty()) { 0339 return false; 0340 } 0341 0342 const QFileInfo f(filename); 0343 if (f.exists()) { 0344 // if it already exists, query the user for replacement 0345 int res = KMessageBox::warningContinueCancel(this, 0346 i18n("A file with that name already exists. Do you wish to overwrite it?"), 0347 i18n("Save Board Layout"), KStandardGuiItem::save()); 0348 0349 if (res != KMessageBox::Continue) { 0350 return false; 0351 } 0352 } 0353 0354 bool result = m_theBoard.saveBoardLayout(filename); 0355 0356 if (result == true) { 0357 m_clean = true; 0358 0359 return true; 0360 } else { 0361 return false; 0362 } 0363 } 0364 0365 bool Editor::testSave() 0366 { 0367 // test if a save is required and return true if the app is to continue 0368 // false if cancel is selected. (if ok then call out to save the board 0369 0370 if (m_clean) { 0371 return true; 0372 } 0373 0374 const int res = KMessageBox::warningTwoActionsCancel(this, 0375 i18n("The board has been modified. Would you like to save the changes?"), 0376 QString(), KStandardGuiItem::save(), KStandardGuiItem::dontSave()); 0377 0378 if (res == KMessageBox::PrimaryAction) { 0379 // yes to save 0380 if (saveBoard()) { 0381 return true; 0382 } else { 0383 KMessageBox::error(this, i18n("Save failed. Aborting operation.")); 0384 0385 return false; 0386 } 0387 } else { 0388 return (res != KMessageBox::Cancel); 0389 } 0390 return true; 0391 } 0392 0393 void Editor::paintEvent(QPaintEvent *) 0394 { 0395 // The main paint event, draw in the grid and blit in 0396 // the tiles as specified by the layout. 0397 0398 // first we layer on a background grid 0399 QPixmap buff; 0400 QPixmap * dest = m_drawFrame->getPreviewPixmap(); 0401 buff = QPixmap(dest->width(), dest->height()); 0402 drawBackground(&buff); 0403 drawTiles(&buff); 0404 QPainter p(dest); 0405 p.drawPixmap(0, 0, buff); 0406 p.end(); 0407 0408 m_drawFrame->update(); 0409 } 0410 0411 void Editor::drawBackground(QPixmap * pixmap) const 0412 { 0413 const int width = m_theBoard.getWidth(); 0414 const int height = m_theBoard.getHeight(); 0415 QPainter p(pixmap); 0416 0417 // blast in a white background 0418 p.fillRect(0, 0, pixmap->width(), pixmap->height(), Qt::white); 0419 0420 // now put in a grid of tile quarter width squares 0421 for (int y = 0; y <= height; ++y) { 0422 int nextY = m_borderTop + (y * m_tiles.qHeight()); 0423 p.drawLine(m_borderLeft, nextY, m_borderLeft + (width * m_tiles.qWidth()), nextY); 0424 } 0425 0426 for (int x = 0; x <= width; ++x) { 0427 int nextX = m_borderLeft + (x * m_tiles.qWidth()); 0428 p.drawLine(nextX, m_borderTop, nextX, m_borderTop + (height * m_tiles.qHeight())); 0429 } 0430 } 0431 0432 void Editor::drawTiles(QPixmap * dest) 0433 { 0434 QPainter p(dest); 0435 0436 const int width = m_theBoard.getWidth(); 0437 const int height = m_theBoard.getHeight(); 0438 const int depth = m_theBoard.getDepth(); 0439 const int shadowX = m_tiles.width() - m_tiles.qWidth() * 2 - m_tiles.levelOffsetX(); 0440 const int shadowY = m_tiles.height() - m_tiles.qHeight() * 2 - m_tiles.levelOffsetY(); 0441 short tile = 0; 0442 0443 int xOffset = -shadowX; 0444 int yOffset = -m_tiles.levelOffsetY(); 0445 0446 // we iterate over the depth stacking order. Each successive level is 0447 // drawn one indent up and to the right. The indent is the width 0448 // of the 3d relief on the tile left (tile shadow width) 0449 for (int z = 0; z < depth; ++z) { 0450 // we draw down the board so the tile below over rights our border 0451 for (int y = 0; y < height; ++y) { 0452 // drawing right to left to prevent border overwrite 0453 for (int x = width - 1; x >= 0; --x) { 0454 int sx = x * m_tiles.qWidth() + xOffset + m_borderLeft; 0455 int sy = y * m_tiles.qHeight() + yOffset + m_borderTop; 0456 0457 if (m_theBoard.getBoardData(z, y, x) != '1') { 0458 continue; 0459 } 0460 0461 QPixmap t; 0462 tile = (z * depth) + (y * height) + (x * width); 0463 t = m_tiles.unselectedTile(0); 0464 0465 // Only one complication. Since we render top to bottom , left 0466 // to right situations arise where...: 0467 // there exists a tile one q height above and to the left 0468 // in this situation we would draw our top left border over it 0469 // we simply split the tile draw so the top half is drawn 0470 // minus border 0471 if ((x > 1) && (y > 0) && m_theBoard.getBoardData(z, y - 1, x - 2) == '1') { 0472 p.drawPixmap(sx, sy, t, 0, 0, t.width(), t.height()); 0473 0474 p.drawPixmap(sx - m_tiles.qWidth() + shadowX + m_tiles.levelOffsetX(), sy, t, 0475 t.width() - m_tiles.qWidth(), 0476 t.height() - m_tiles.qHeight() - m_tiles.levelOffsetX() - shadowY, 0477 m_tiles.qWidth(), m_tiles.qHeight() + m_tiles.levelOffsetX()); 0478 } else { 0479 p.drawPixmap(sx, sy, t, 0, 0, t.width(), t.height()); 0480 } 0481 0482 ++tile; 0483 tile = tile % 143; 0484 } 0485 } 0486 0487 xOffset += m_tiles.levelOffsetX(); 0488 yOffset -= m_tiles.levelOffsetY(); 0489 } 0490 } 0491 0492 void Editor::transformPointToPosition(const QPoint & point, POSITION & mouseClickPos, bool align) const 0493 { 0494 // convert mouse position on screen to a tile z y x coord 0495 // different to the one in kmahjongg.cpp since if we hit ground 0496 // we return a result too. 0497 0498 short z = 0; 0499 short y = 0; 0500 short x = 0; 0501 mouseClickPos.z = 100; 0502 0503 // iterate over z coordinate from top to bottom 0504 for (z = m_theBoard.getDepth() - 1; z >= 0; --z) { 0505 // calculate mouse coordinates --> position in game board 0506 // the factor -theTiles.width()/2 must keep track with the 0507 // offset for blitting in the print event (FIX ME) 0508 x = ((point.x() - m_borderLeft) - (z + 1) * m_tiles.levelOffsetX()) / m_tiles.qWidth(); 0509 y = ((point.y() - m_borderTop) + z * m_tiles.levelOffsetX()) / m_tiles.qHeight(); 0510 0511 // skip when position is illegal 0512 if (x < 0 || x >= m_theBoard.getWidth() || y < 0 || y >= m_theBoard.getHeight()) { 0513 continue; 0514 } 0515 0516 switch (m_theBoard.getBoardData(z, y, x)) { 0517 case static_cast<UCHAR>('3'): 0518 if (align) { 0519 --x; 0520 --y; 0521 } 0522 0523 break; 0524 0525 case static_cast<UCHAR>('2'): 0526 if (align) { 0527 --x; 0528 } 0529 0530 break; 0531 0532 case static_cast<UCHAR>('4'): 0533 if (align) { 0534 --y; 0535 } 0536 0537 break; 0538 0539 case static_cast<UCHAR>('1'): 0540 break; 0541 0542 default: 0543 continue; 0544 } 0545 0546 // if gameboard is empty, skip 0547 if (!m_theBoard.getBoardData(z, y, x)) { 0548 continue; 0549 } 0550 0551 // here, position is legal 0552 mouseClickPos.z = z; 0553 mouseClickPos.y = y; 0554 mouseClickPos.x = x; 0555 mouseClickPos.f = m_theBoard.getBoardData(z, y, x); 0556 0557 break; 0558 } 0559 0560 if (mouseClickPos.z == 100) { 0561 mouseClickPos.x = x; 0562 mouseClickPos.y = y; 0563 mouseClickPos.f = 0; 0564 } 0565 } 0566 0567 void Editor::drawFrameMousePressEvent(QMouseEvent * e) 0568 { 0569 // we swallow the draw frames mouse clicks and process here 0570 0571 POSITION mousePos; 0572 transformPointToPosition(e->pos(), mousePos, (m_mode == EditMode::remove)); 0573 0574 switch (m_mode) { 0575 case EditMode::remove: 0576 if (!m_theBoard.tileAbove(mousePos) && mousePos.z < m_theBoard.getDepth() && m_theBoard.isTileAt(mousePos)) { 0577 m_theBoard.deleteTile(mousePos); 0578 --m_numTiles; 0579 statusChanged(); 0580 drawFrameMouseMovedEvent(e); 0581 update(); 0582 } 0583 0584 break; 0585 case EditMode::insert: { 0586 POSITION n = mousePos; 0587 0588 if (n.z == 100) { 0589 n.z = 0; 0590 } else { 0591 n.z += 1; 0592 } 0593 0594 if (canInsert(n)) { 0595 m_theBoard.insertTile(n); 0596 m_clean = false; 0597 ++m_numTiles; 0598 statusChanged(); 0599 update(); 0600 } 0601 0602 break; 0603 } 0604 default: 0605 break; 0606 } 0607 } 0608 0609 void Editor::drawCursor(POSITION & p, bool visible) 0610 { 0611 int x = m_borderLeft + (p.z * m_tiles.levelOffsetX()) + (p.x * m_tiles.qWidth()); 0612 const int y = m_borderTop - ((p.z + 1) * m_tiles.levelOffsetY()) + (p.y * m_tiles.qHeight()); 0613 const int w = (m_tiles.qWidth() * 2) + m_tiles.levelOffsetX(); 0614 const int h = (m_tiles.qHeight() * 2) + m_tiles.levelOffsetY(); 0615 0616 if (p.z == 100 || !visible) { 0617 x = -1; 0618 } 0619 0620 m_drawFrame->setRect(x, y, w, h, m_tiles.levelOffsetX(), static_cast<int>(m_mode) - static_cast<int>(EditMode::remove)); 0621 m_drawFrame->update(); 0622 } 0623 0624 void Editor::drawFrameMouseMovedEvent(QMouseEvent * e) 0625 { 0626 // we swallow the draw frames mouse moves and process here 0627 0628 POSITION mousePos; 0629 transformPointToPosition(e->pos(), mousePos, (m_mode == EditMode::remove)); 0630 0631 if ((mousePos.x == m_curPos.x) && (mousePos.y == m_curPos.y) && (mousePos.z == m_curPos.z)) { 0632 return; 0633 } 0634 0635 m_curPos = mousePos; 0636 0637 statusChanged(); 0638 0639 switch (m_mode) { 0640 case EditMode::insert: { 0641 POSITION next; 0642 next = m_curPos; 0643 0644 if (next.z == 100) { 0645 next.z = 0; 0646 } else { 0647 next.z += 1; 0648 } 0649 0650 drawCursor(next, canInsert(next)); 0651 0652 break; 0653 } 0654 case EditMode::remove: 0655 drawCursor(m_curPos, 1); 0656 0657 break; 0658 case EditMode::move: 0659 break; 0660 } 0661 } 0662 0663 bool Editor::canInsert(POSITION & p) const 0664 { 0665 // can we inser a tile here. We can iff 0666 // there are tiles in all positions below us (or we are a ground level) 0667 // there are no tiles intersecting with us on this level 0668 0669 if (p.z >= m_theBoard.getDepth()) { 0670 return false; 0671 } 0672 0673 if (p.y > m_theBoard.getHeight() - 2) { 0674 return false; 0675 } 0676 0677 if (p.x > m_theBoard.getWidth() - 2) { 0678 return false; 0679 } 0680 0681 POSITION n = p; 0682 0683 if (p.z != 0) { 0684 n.z -= 1; 0685 if (!m_theBoard.allFilled(n)) { 0686 return false; 0687 } 0688 } 0689 0690 return !m_theBoard.anyFilled(p); 0691 } 0692 0693 void Editor::closeEvent(QCloseEvent * e) 0694 { 0695 if (testSave()) { 0696 m_theBoard.clearBoardLayout(); 0697 m_clean = true; 0698 m_numTiles = 0; 0699 statusChanged(); 0700 update(); 0701 0702 // Save the window geometry. 0703 Prefs::setEditorGeometry(geometry()); 0704 Prefs::self()->save(); 0705 0706 e->accept(); 0707 } else { 0708 e->ignore(); 0709 } 0710 } 0711 0712 void Editor::setTilesetFromSettings() 0713 { 0714 const QString tileset(Prefs::tileSet()); 0715 0716 // Exit if the tileset is already set. 0717 if (tileset == m_tileset) { 0718 return; 0719 } 0720 0721 // Try to load the new tileset. 0722 if (!m_tiles.loadTileset(tileset)) { 0723 // Try to load the old one. 0724 if (!m_tiles.loadTileset(m_tileset)) { 0725 m_tiles.loadDefault(); 0726 } 0727 } else { 0728 // If loading the new tileset was ok, set the new tileset name. 0729 m_tileset = tileset; 0730 } 0731 0732 // Must be called to load the graphics and its information. 0733 m_tiles.loadGraphics(); 0734 0735 updateTileSize(size()); 0736 } 0737 0738 #include "moc_editor.cpp"