File indexing completed on 2024-05-12 07:58:52
0001 /* 0002 SPDX-FileCopyrightText: 2003 Marco Krüger <grisuji@gmx.de> 0003 SPDX-FileCopyrightText: 2003, 2009 Ian Wadham <iandw.au@gmail.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "kgrglobals.h" 0009 0010 #include "kgrselector.h" 0011 0012 #include "kgrgameio.h" 0013 0014 #include <QGridLayout> 0015 #include <QHeaderView> 0016 #include <QScreen> 0017 #include <QLabel> 0018 #include <QPainter> 0019 #include <QPushButton> 0020 #include <QScrollBar> 0021 #include <QSpacerItem> 0022 #include <QSpinBox> 0023 #include <QTextEdit> 0024 #include <QVBoxLayout> 0025 #include <QDialogButtonBox> 0026 #include <KGuiItem> 0027 #include <KConfigGroup> 0028 #include <KSharedConfig> 0029 #include <KLocalizedString> 0030 /******************************************************************************/ 0031 /***************** DIALOG BOX TO SELECT A GAME AND LEVEL *****************/ 0032 /******************************************************************************/ 0033 0034 KGrSLDialog::KGrSLDialog (int action, int requestedLevel, int gameIndex, 0035 QList<KGrGameData *> & gameList, 0036 const QString & pSystemDir, const QString & pUserDir, 0037 QWidget * parent) 0038 : 0039 QDialog (parent), 0040 slAction (action), 0041 myGameList (gameList), 0042 defaultGame (gameIndex), 0043 defaultLevel (requestedLevel), 0044 systemDir (pSystemDir), 0045 userDir (pUserDir), 0046 slParent (parent) 0047 { 0048 setupWidgets(); 0049 } 0050 0051 KGrSLDialog::~KGrSLDialog() 0052 { 0053 } 0054 0055 bool KGrSLDialog::selectLevel (int & selectedGame, int & selectedLevel) 0056 { 0057 selectedGame = defaultGame; 0058 selectedLevel = 0; // 0 = no selection (Cancel) or invalid. 0059 0060 // Create and run a modal dialog box to select a game and level. 0061 while (exec() == QDialog::Accepted) { 0062 selectedGame = slGameIndex; 0063 selectedLevel = 0; // In case the selection is invalid. 0064 if (myGameList.at (selectedGame)->owner == SYSTEM) { 0065 switch (slAction) { 0066 case SL_CREATE: // Can save only in a USER collection. 0067 case SL_SAVE: 0068 case SL_MOVE: 0069 KGrMessage::information (slParent, i18n ("Select Level"), 0070 i18n ("Sorry, you can only save or move " 0071 "into one of your own games.")); 0072 continue; // Re-run the dialog box. 0073 break; 0074 case SL_DELETE: // Can delete only in a USER collection. 0075 KGrMessage::information (slParent, i18n ("Select Level"), 0076 i18n ("Sorry, you can only delete a level " 0077 "from one of your own games.")); 0078 continue; // Re-run the dialog box. 0079 break; 0080 case SL_UPD_GAME: // Can edit info only in a USER collection. 0081 KGrMessage::information (slParent, i18n ("Edit Game Info"), 0082 i18n ("Sorry, you can only edit the game " 0083 "information on your own games.")); 0084 continue; // Re-run the dialog box. 0085 break; 0086 default: 0087 break; 0088 } 0089 } 0090 0091 selectedLevel = number->value(); 0092 if ((selectedLevel > myGameList.at (selectedGame)->nLevels) && 0093 (slAction != SL_CREATE) && (slAction != SL_SAVE) && 0094 (slAction != SL_MOVE) && (slAction != SL_UPD_GAME)) { 0095 KGrMessage::information (slParent, i18n ("Select Level"), 0096 i18n ("There is no level %1 in \"%2\", " 0097 "so you cannot play or edit it.", 0098 selectedLevel, 0099 myGameList.at (selectedGame)->name)); 0100 selectedLevel = 0; // Set an invalid selection. 0101 continue; // Re-run the dialog box. 0102 } 0103 break; // Accepted and valid. 0104 } 0105 return (selectedLevel > 0); // 0 = cancelled or invalid. 0106 } 0107 0108 void KGrSLDialog::setupWidgets() 0109 { 0110 int margin = 0; 0111 int spacing = 0; 0112 QWidget * dad = new QWidget (this); 0113 0114 QVBoxLayout *layout = new QVBoxLayout; 0115 setLayout(layout); 0116 layout->addWidget(dad); 0117 0118 setWindowTitle (i18nc("@title:window", "Select Game")); 0119 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help); 0120 QVBoxLayout *buttonLayout = new QVBoxLayout; 0121 connect(buttonBox, &QDialogButtonBox::accepted, this, &KGrSLDialog::accept); 0122 connect(buttonBox, &QDialogButtonBox::rejected, this, &KGrSLDialog::reject); 0123 buttonLayout->addWidget(buttonBox); 0124 buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); 0125 layout->addWidget(buttonBox); 0126 0127 QVBoxLayout * mainLayout = new QVBoxLayout (dad); 0128 mainLayout->setSpacing (spacing); 0129 mainLayout->setContentsMargins(margin, margin, margin, margin); 0130 0131 gameL = new QLabel 0132 (i18n ("<html><b>Please select a game:</b></html>"), dad); 0133 mainLayout->addWidget (gameL, 5); 0134 0135 games = new QTreeWidget (dad); 0136 mainLayout->addWidget(games); 0137 mainLayout->addWidget (games, 50); 0138 games->setColumnCount (4); 0139 games->setHeaderLabels (QStringList() << 0140 i18n ("Name of Game") << 0141 i18n ("Rules") << 0142 i18n ("Levels") << 0143 i18n ("Skill")); 0144 games->setRootIsDecorated (false); 0145 0146 QHBoxLayout * hboxLayout1 = new QHBoxLayout(); 0147 hboxLayout1->setSpacing (6); 0148 hboxLayout1->setContentsMargins(0, 0, 0, 0); 0149 0150 gameN = new QLabel (dad); // Name of selected game. 0151 QFont f = gameN->font(); 0152 f.setBold (true); 0153 gameN->setFont (f); 0154 hboxLayout1->addWidget (gameN); 0155 0156 QSpacerItem * spacerItem1 = new QSpacerItem 0157 (21, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); 0158 hboxLayout1->addItem (spacerItem1); 0159 0160 gameD = new QLabel (dad); // Description of game. 0161 hboxLayout1->addWidget (gameD); 0162 mainLayout->addLayout (hboxLayout1, 5); 0163 0164 gameAbout = new QTextEdit (dad); 0165 gameAbout->setReadOnly (true); 0166 mainLayout->addWidget (gameAbout, 25); 0167 0168 QFrame * separator = new QFrame (dad); 0169 separator->setFrameShape (QFrame::HLine); 0170 mainLayout->addWidget (separator); 0171 0172 if ((slAction == SL_START) || (slAction == SL_UPD_GAME)) { 0173 dad-> setWindowTitle (i18nc("@title:window", "Select Game")); 0174 QLabel * startMsg = new QLabel 0175 (QStringLiteral("<b>") + i18n ("Level 1 of the selected game is:") + QStringLiteral("</b>"), dad); 0176 mainLayout->addWidget (startMsg, 5); 0177 } 0178 else { 0179 dad-> setWindowTitle (i18nc("@title:window", "Select Game/Level")); 0180 QLabel * selectLev = new QLabel 0181 (QStringLiteral("<b>") + i18n ("Please select a level:") + QStringLiteral("</b>"), dad); 0182 mainLayout->addWidget (selectLev, 5); 0183 } 0184 0185 QGridLayout * grid = new QGridLayout; 0186 mainLayout->addLayout (grid); 0187 0188 number = new QScrollBar (Qt::Vertical, dad); 0189 number->setRange (1, 150); 0190 number->setSingleStep (1); 0191 number->setPageStep (10); 0192 number->setValue (1); 0193 grid->addWidget (number, 1, 5, 4, 1); 0194 0195 QWidget * numberPair = new QWidget (dad); 0196 QHBoxLayout *hboxLayout2 = new QHBoxLayout (numberPair); 0197 hboxLayout2->setContentsMargins(0, 0, 0, 0); 0198 numberPair->setLayout (hboxLayout2); 0199 grid->addWidget (numberPair, 1, 1, 1, 3); 0200 numberL = new QLabel (i18n ("Level number:"), numberPair); 0201 display = new QSpinBox (numberPair); 0202 display->setRange (1, 150); 0203 hboxLayout2->addWidget (numberL); 0204 hboxLayout2->addWidget (display); 0205 0206 levelNH = new QPushButton (i18n ("Edit Level Name o&r Hint"), dad); 0207 mainLayout->addWidget (levelNH); 0208 0209 slName = new QLabel (dad); 0210 grid->addWidget (slName, 2, 1, 1, 4); 0211 thumbNail = new KGrThumbNail (dad); 0212 grid->addWidget (thumbNail, 1, 6, 4, 5); 0213 0214 // Set thumbnail cell size to about 1/5 of game cell size. 0215 int cellSize = slParent->width() / (5 * (FIELDWIDTH + 4)); 0216 cellSize = (cellSize < 4) ? 4 : cellSize; 0217 thumbNail-> setFixedWidth ((FIELDWIDTH * cellSize) + 2); 0218 thumbNail-> setFixedHeight ((FIELDHEIGHT * cellSize) + 2); 0219 0220 // Base the geometry of the dialog box on the playing area. 0221 int cell = slParent->width() / (FIELDWIDTH + 4); 0222 dad-> setMinimumSize ((FIELDWIDTH*cell/2), (FIELDHEIGHT-3)*cell); 0223 0224 // Avoid spilling into the Taskbar or Apple Dock area if they get too close. 0225 // Otherwise allow the dialog to choose its size and then be resizeable. 0226 const QSize maxSize = screen()->availableGeometry().size(); 0227 if ((maxSize.height() - slParent->height()) <= 120) { 0228 dad->setFixedHeight (slParent->height() - 120); // Keep 120 for buttons. 0229 } 0230 0231 // Set the default for the level-number in the scrollbar. 0232 number-> setTracking (true); 0233 number->setValue (defaultLevel); 0234 0235 slSetGames (defaultGame); 0236 0237 // Vary the dialog according to the action. 0238 QString OKText; 0239 switch (slAction) { 0240 case SL_START: // Must start at level 1, but can choose a game. 0241 OKText = i18n ("Start Game"); 0242 number->setValue (1); 0243 number->setEnabled (false); 0244 display->setEnabled (false); 0245 number->hide(); 0246 numberL->hide(); 0247 display->hide(); 0248 break; 0249 case SL_ANY: // Can start playing at any level in any game. 0250 OKText = i18n ("Play Level"); 0251 break; 0252 case SL_REPLAY: // Can ask to see a replay of any level in any game. 0253 OKText = i18n ("Replay Level"); 0254 break; 0255 case SL_SOLVE: // Can ask to see a solution of any level in any game. 0256 OKText = i18n ("Show Solution"); 0257 break; 0258 case SL_SAVE_SOLUTION: // Can ask to save a recording on a solution-file. 0259 OKText = i18n ("Save A Solution"); 0260 break; 0261 case SL_UPDATE: // Can use any level in any game as edit input. 0262 OKText = i18n ("Edit Level"); 0263 break; 0264 case SL_CREATE: // Can save a new level only in a USER game. 0265 OKText = i18n ("Save New"); 0266 break; 0267 case SL_SAVE: // Can save an edited level only in a USER game. 0268 OKText = i18n ("Save Change"); 0269 break; 0270 case SL_DELETE: // Can delete a level only in a USER game. 0271 OKText = i18n ("Delete Level"); 0272 break; 0273 case SL_MOVE: // Can move a level only into a USER game. 0274 OKText = i18n ("Move To..."); 0275 break; 0276 case SL_UPD_GAME: // Can only edit USER game details. 0277 OKText = i18n ("Edit Game Info"); 0278 number->setValue (1); 0279 number->setEnabled (false); 0280 display->setEnabled (false); 0281 number->hide(); 0282 numberL->hide(); 0283 display->hide(); 0284 break; 0285 0286 default: break; // Keep the default settings. 0287 } 0288 if (!OKText.isEmpty()) { 0289 KGuiItem::assign(levelNH, KGuiItem (OKText)); 0290 } 0291 0292 // Set value in the line-edit box. 0293 slShowLevel (number->value()); 0294 0295 if (display->isEnabled()) { 0296 display->setFocus(); // Set the keyboard input on. 0297 display->selectAll(); 0298 } 0299 0300 // Paint a thumbnail sketch of the level. 0301 thumbNail->setFrameStyle (QFrame::Box | QFrame::Plain); 0302 thumbNail->setLineWidth (1); 0303 slPaintLevel(); 0304 thumbNail->show(); 0305 0306 connect(games, &QTreeWidget::itemSelectionChanged, this, &KGrSLDialog::slGame); 0307 0308 connect(display, &QSpinBox::textChanged, this, &KGrSLDialog::slUpdate); 0309 connect(number, &QScrollBar::valueChanged, this, &KGrSLDialog::slShowLevel); 0310 0311 // Only enable name and hint dialog here if saving a new or edited level. 0312 // At other times the name and hint have not been loaded or initialised yet. 0313 if ((slAction == SL_CREATE) || (slAction == SL_SAVE)) { 0314 // Signal editNameAndHint() relays the click to a KGrEditor connection. 0315 connect(levelNH, &QPushButton::clicked, this, &KGrSLDialog::editNameAndHint); 0316 } 0317 else { 0318 levelNH->setEnabled (false); 0319 levelNH->hide(); 0320 } 0321 0322 connect(games, &QTreeWidget::itemSelectionChanged, this, &KGrSLDialog::slPaintLevel); 0323 connect(number, &QScrollBar::sliderReleased, this, &KGrSLDialog::slPaintLevel); 0324 0325 connect(buttonBox->button(QDialogButtonBox::Help), &QPushButton::clicked, this, &KGrSLDialog::slotHelp); 0326 } 0327 0328 /******************************************************************************/ 0329 /***************** LOAD THE LIST OF GAMES (COLLECTIONS) *****************/ 0330 /******************************************************************************/ 0331 0332 void KGrSLDialog::slSetGames (int cIndex) 0333 { 0334 int i; 0335 int imax = myGameList.count(); 0336 0337 // Set values in the table that holds details of available games. 0338 // The table is displayed in order of skill then the kind of rules. 0339 games->clear(); 0340 slGameIndex = -1; 0341 0342 QList<char> sortOrder1, sortOrder2; // Crude, but effective. 0343 sortOrder1 << 'N' << 'C' << 'T'; 0344 sortOrder2 << 'T' << 'K'; 0345 0346 for (char sortItem1 : std::as_const(sortOrder1)) { 0347 for (char sortItem2 : std::as_const(sortOrder2)) { 0348 for (i = 0; i < imax; ++i) { 0349 if ((myGameList.at (i)->skill == sortItem1) && 0350 (myGameList.at (i)->rules == sortItem2)) { 0351 QStringList data; 0352 data 0353 << myGameList.at (i)->name 0354 << ((myGameList.at (i)->rules == 'K') ? 0355 i18nc ("Rules", "KGoldrunner") : 0356 i18nc ("Rules", "Traditional")) 0357 << QString().setNum (myGameList.at (i)->nLevels) 0358 << ((myGameList.at (i)->skill == 'T') ? 0359 i18nc ("Skill Level", "Tutorial") : 0360 ((myGameList.at (i)->skill == 'N') ? 0361 i18nc ("Skill Level", "Normal") : 0362 i18nc ("Skill Level", "Championship"))); 0363 KGrGameListItem * thisGame = new KGrGameListItem (data, i); 0364 games->addTopLevelItem (thisGame); 0365 0366 if (slGameIndex < 0) { 0367 slGameIndex = i; // There is at least one game. 0368 } 0369 if (i == cIndex) { 0370 // Mark the currently selected game (default 0). 0371 games->setCurrentItem (thisGame); 0372 } 0373 } 0374 } // End "for" loop. 0375 } 0376 } 0377 0378 if (slGameIndex < 0) { 0379 return; // The game-list is empty (unlikely). 0380 } 0381 0382 // Fetch and display information on the selected game. 0383 slGame(); 0384 0385 // Make the column for the game's name a bit wider. 0386 games->header()->setSectionResizeMode (0, QHeaderView::ResizeToContents); 0387 games->header()->setSectionResizeMode (1, QHeaderView::ResizeToContents); 0388 games->header()->setSectionResizeMode (2, QHeaderView::ResizeToContents); 0389 } 0390 0391 /******************************************************************************/ 0392 /***************** SLOTS USED BY LEVEL SELECTION DIALOG *****************/ 0393 /******************************************************************************/ 0394 0395 void KGrSLDialog::slGame() 0396 { 0397 0398 if (slGameIndex < 0) { 0399 // Ignore the "highlighted" signal caused by inserting in an empty box. 0400 return; 0401 } 0402 0403 if (games->selectedItems().size() <= 0) { 0404 return; 0405 } 0406 0407 slGameIndex = (dynamic_cast<KGrGameListItem *> 0408 (games->selectedItems().first()))->id(); 0409 int n = slGameIndex; // Game selected. 0410 int N = defaultGame; // Current game. 0411 if (myGameList.at (n)->nLevels > 0) { 0412 number->setMaximum (myGameList.at (n)->nLevels); 0413 display->setMaximum (myGameList.at (n)->nLevels); 0414 } 0415 else { 0416 number->setMaximum (1); // Avoid range errors. 0417 display->setMaximum (1); 0418 } 0419 0420 KConfigGroup gameGroup (KSharedConfig::openConfig(), QStringLiteral("KDEGame")); 0421 int lev = 1; 0422 0423 // Set a default level number for the selected game. 0424 switch (slAction) { 0425 case SL_ANY: 0426 case SL_REPLAY: 0427 case SL_SOLVE: 0428 case SL_SAVE_SOLUTION: 0429 case SL_UPDATE: 0430 case SL_DELETE: 0431 case SL_UPD_GAME: 0432 // If selecting the current game, use the current level number. 0433 if (n == N) { 0434 number->setValue (defaultLevel); 0435 } 0436 // Else use the last level played in the selected game (from KConfig). 0437 else { 0438 lev = gameGroup.readEntry (QLatin1String("Level_") + myGameList.at (n)->prefix, 1); 0439 number->setValue (lev); // Else use level 1. 0440 } 0441 break; 0442 case SL_CREATE: 0443 case SL_SAVE: 0444 case SL_MOVE: 0445 if ((n == N) && (slAction != SL_CREATE)) { 0446 // Saving/moving level in current game: use current number. 0447 number->setValue (defaultLevel); 0448 } 0449 else { 0450 // Saving new/edited level or relocating a level: use "nLevels + 1". 0451 number->setMaximum (myGameList.at (n)->nLevels + 1); 0452 display->setMaximum (myGameList.at (n)->nLevels + 1); 0453 number->setValue (number->maximum()); 0454 } 0455 break; 0456 default: 0457 number->setValue (1); // Default is level 1. 0458 break; 0459 } 0460 0461 slShowLevel (number->value()); 0462 0463 int levCnt = myGameList.at (n)->nLevels; 0464 if (myGameList.at (n)->rules == 'K') 0465 gameD->setText (i18np ("1 level, uses KGoldrunner rules.", 0466 "%1 levels, uses KGoldrunner rules.", levCnt)); 0467 else 0468 gameD->setText (i18np ("1 level, uses Traditional rules.", 0469 "%1 levels, uses Traditional rules.", levCnt)); 0470 gameN->setText (myGameList.at (n)->name); 0471 QString s; 0472 if (myGameList.at (n)->about.isEmpty()) { 0473 s = i18n ("Sorry, there is no further information about this game."); 0474 } 0475 else { 0476 s = (i18n (myGameList.at (n)->about.constData())); 0477 } 0478 gameAbout->setText (s); 0479 } 0480 0481 void KGrSLDialog::slShowLevel (int i) 0482 { 0483 // Display the level number as the slider is moved. 0484 display->setValue (i); 0485 } 0486 0487 void KGrSLDialog::slUpdate (const QString & text) 0488 { 0489 // Move the slider when a valid level number is entered. 0490 QString s = text; 0491 bool ok = false; 0492 int n = s.toInt (&ok); 0493 if (ok) { 0494 number->setValue (n); 0495 slPaintLevel(); 0496 } 0497 else 0498 KGrMessage::information (this, i18n ("Select Level"), 0499 i18n ("This level number is not valid. It can not be used.")); 0500 } 0501 0502 void KGrSLDialog::slPaintLevel() 0503 { 0504 // Repaint the thumbnail sketch of the level whenever the level changes. 0505 if (slGameIndex < 0) { 0506 return; // Owner has no games. 0507 } 0508 // Fetch level-data and save layout, name and label in the thumbnail. 0509 QString dir = (myGameList.at (slGameIndex)->owner == USER) ? 0510 userDir : systemDir; 0511 thumbNail->setLevelData (dir, myGameList.at (slGameIndex)->prefix, 0512 number->value(), slName); 0513 thumbNail->repaint(); // Will call "paintEvent (e)". 0514 } 0515 0516 void KGrSLDialog::slotHelp() 0517 { 0518 // Help for "Select Game and Level" dialog box. 0519 QString s = 0520 i18n ("The main button at the bottom echoes the " 0521 "menu action you selected. Click it after choosing " 0522 "a game and level - or use \"Cancel\"."); 0523 0524 if (slAction == SL_START) { 0525 s += i18n ("\n\nIf this is your first time in KGoldrunner, select the " 0526 "tutorial game, which gives you hints as you go.\n\n" 0527 "Otherwise, just click on the name of a game in the table, " 0528 "then, to start at level 001, click on the main button at the " 0529 "bottom. Play begins when you move the mouse or press a key."); 0530 } 0531 else { 0532 switch (slAction) { 0533 case SL_UPDATE: 0534 s += i18n ("\n\nYou can select System levels for editing (or " 0535 "copying), but you must save the result in a game you have " 0536 "created. Use the left mouse-button as a paintbrush and the " 0537 "editor toolbar buttons as a palette. Use the 'Erase' button " 0538 "or the right mouse-button to erase. You can drag the mouse " 0539 "with a button held down and paint or erase multiple squares."); 0540 break; 0541 case SL_CREATE: 0542 s += i18n("\n\nYou can add a name and hint to your new level here, " 0543 "but you must save the level you have created into one of " 0544 "your own games. By default your new level will go at the " 0545 "end of your game, but you can also select a level number and " 0546 "save into the middle of your game."); 0547 break; 0548 case SL_SAVE: 0549 s += i18n("\n\nYou can create or edit a name and hint here, before " 0550 "saving. If you change the game or level, you can do a copy " 0551 "or \"Save As\", but you must always save into one of your " 0552 "own games. If you save a level into the middle of a series, " 0553 "the other levels are automatically re-numbered."); 0554 break; 0555 case SL_DELETE: 0556 s += i18n ("\n\nYou can only delete levels from one of your own " 0557 "games. If you delete a level from the middle of a series, " 0558 "the other levels are automatically re-numbered."); 0559 break; 0560 case SL_MOVE: 0561 s += i18n ("\n\nTo move (re-number) a level, you must first select " 0562 "it by using \"Edit Any Level...\", then you can use " 0563 "\"Move Level...\" to move it to a new number or even a " 0564 "different game. Other levels are automatically re-numbered as " 0565 "required. You can only move levels within your own games."); 0566 break; 0567 case SL_UPD_GAME: 0568 s += i18n ("\n\nWhen editing game info you only need to choose a " 0569 "game, then you can go to a dialog where you edit the " 0570 "details of the game."); 0571 break; 0572 default: 0573 break; 0574 } 0575 s += i18n ("\n\nClick on the table to choose a game. " 0576 "In the table and below it you can see more information about the " 0577 "selected game, including how many levels there are, how difficult " 0578 "the game is and what " 0579 "rules the enemies follow (see the KGoldrunner Handbook).\n\n" 0580 "You select " 0581 "a level number by typing it or using the spin box or scroll bar. " 0582 "As you vary the game or level, the thumbnail area shows a " 0583 "preview of your choice."); 0584 } 0585 0586 KGrMessage::information (slParent, i18n ("Help: Select Game & Level"), s); 0587 } 0588 0589 /******************************************************************************* 0590 ************************* ITEM FOR THE LIST OF GAMES ************************* 0591 *******************************************************************************/ 0592 0593 KGrGameListItem::KGrGameListItem (const QStringList & data, 0594 const int internalId) 0595 : QTreeWidgetItem (data) 0596 { 0597 mInternalId = internalId; 0598 } 0599 0600 int KGrGameListItem::id() const 0601 { 0602 return mInternalId; 0603 } 0604 0605 void KGrGameListItem::setId (const int internalId) 0606 { 0607 mInternalId = internalId; 0608 } 0609 0610 /******************************************************************************/ 0611 /********************** CLASS TO DISPLAY THUMBNAIL ***********************/ 0612 /******************************************************************************/ 0613 0614 KGrThumbNail::KGrThumbNail (QWidget * parent) 0615 : 0616 QFrame (parent), 0617 io (new KGrGameIO (parent)) 0618 { 0619 // Let the parent do all the work. We need a class here so that 0620 // QFrame::paintEvent (QPaintEvent *) can be re-implemented and 0621 // the thumbnail can be automatically re-painted when required. 0622 } 0623 0624 KGrThumbNail::~KGrThumbNail() 0625 { 0626 delete io; 0627 } 0628 0629 void KGrThumbNail::setLevelData (const QString & dir, const QString& prefix, 0630 int level, QLabel * sln) 0631 { 0632 KGrLevelData d; 0633 QString filePath; 0634 0635 IOStatus stat = io->fetchLevelData (dir, prefix, level, d, filePath); 0636 if (stat == OK) { 0637 // Keep a safe copy of the layout. Translate and display the name. 0638 levelLayout = d.layout; 0639 sln->setText ((d.name.size() > 0) ? i18n (d.name.constData()) : QString()); 0640 } 0641 else { 0642 // Level-data inaccessible or not found. 0643 levelLayout = ""; 0644 sln->setText (QString()); 0645 } 0646 } 0647 0648 void KGrThumbNail::paintEvent (QPaintEvent * /* event (unused) */) 0649 { 0650 QPainter p (this); 0651 QFile openFile; 0652 QPen pen = p.pen(); 0653 char obj = FREE; 0654 int fw = 1; // Set frame width. 0655 int n = width() / FIELDWIDTH; // Set thumbnail cell-size. 0656 0657 QColor backgroundColor = QColor ("#000038"); // Midnight blue. 0658 QColor brickColor = QColor ("#9c0f0f"); // Oxygen's brick-red. 0659 QColor concreteColor = QColor ("#585858"); // Dark grey. 0660 QColor ladderColor = QColor ("#a0a0a0"); // Steely grey. 0661 QColor poleColor = QColor ("#a0a0a0"); // Steely grey. 0662 QColor heroColor = QColor ("#00ff00"); // Green. 0663 QColor enemyColor = QColor ("#0080ff"); // Bright blue. 0664 QColor gold = QColor::fromString(QStringLiteral("gold")); // Gold. 0665 0666 pen.setColor (backgroundColor); 0667 p.setPen (pen); 0668 0669 if (levelLayout.isEmpty()) { 0670 // There is no file, so fill the thumbnail with "FREE" cells. 0671 p.drawRect (QRect (fw, fw, FIELDWIDTH*n, FIELDHEIGHT*n)); 0672 return; 0673 } 0674 0675 for (int j = 0; j < FIELDHEIGHT; j++) 0676 for (int i = 0; i < FIELDWIDTH; i++) { 0677 0678 obj = levelLayout.at (j*FIELDWIDTH + i); 0679 0680 // Set the colour of each object. 0681 switch (obj) { 0682 case BRICK: 0683 case FBRICK: 0684 pen.setColor (brickColor); p.setPen (pen); break; 0685 case CONCRETE: 0686 pen.setColor (concreteColor); p.setPen (pen); break; 0687 case LADDER: 0688 pen.setColor (ladderColor); p.setPen (pen); break; 0689 case BAR: 0690 pen.setColor (poleColor); p.setPen (pen); break; 0691 case HERO: 0692 pen.setColor (heroColor); p.setPen (pen); break; 0693 case ENEMY: 0694 pen.setColor (enemyColor); p.setPen (pen); break; 0695 default: 0696 // Set the background colour for FREE, HLADDER and NUGGET. 0697 pen.setColor (backgroundColor); p.setPen (pen); break; 0698 } 0699 0700 // Draw n x n pixels as n lines of length n. 0701 p.drawLine (i*n+fw, j*n+fw, i*n+(n-1)+fw, j*n+fw); 0702 if (obj == BAR) { 0703 // For a pole, only the top line is drawn in white. 0704 pen.setColor (backgroundColor); 0705 p.setPen (pen); 0706 } 0707 for (int k = 1; k < n; k++) { 0708 p.drawLine (i*n+fw, j*n+k+fw, i*n+(n-1)+fw, j*n+k+fw); 0709 } 0710 0711 // For a nugget, add just a vertical touch of yellow (2-3 pixels). 0712 if (obj == NUGGET) { 0713 int k = (n/2)+fw; 0714 pen.setColor (gold); // Gold. 0715 p.setPen (pen); 0716 p.drawLine (i*n+k, j*n+k, i*n+k, j*n+(n-1)+fw); 0717 p.drawLine (i*n+k+1, j*n+k, i*n+k+1, j*n+(n-1)+fw); 0718 } 0719 } 0720 0721 // Finally, draw a small black border around the outside of the thumbnail. 0722 pen.setColor (Qt::black); 0723 p.setPen (pen); 0724 p.drawRect (rect().left(), rect().top(), rect().right(), rect().bottom()); 0725 } 0726 0727 #include "moc_kgrselector.cpp"