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