File indexing completed on 2024-05-12 04:06:06

0001 /*
0002     SPDX-FileCopyrightText: 1998 Sandro Sigala <ssigala@globalnet.it>.
0003     SPDX-FileCopyrightText: 2001 Waldo Bastian <bastian@kde.org>
0004     SPDX-FileCopyrightText: 2007 Matt Williams <matt@milliams.com>
0005 
0006     SPDX-License-Identifier: ICS
0007 */
0008 
0009 #include "kgamehighscoredialog.h"
0010 
0011 // own
0012 #include "../kgamedifficulty.h"
0013 #include "kgamehighscore.h"
0014 #include <kdegames_highscore_logging.h>
0015 // KF
0016 #include <KConfig>
0017 #include <KLineEdit>
0018 #include <KLocalizedString>
0019 #include <KSeparator>
0020 #include <KUser>
0021 // Qt
0022 #include <QApplication>
0023 #include <QByteArray>
0024 #include <QDialogButtonBox>
0025 #include <QGridLayout>
0026 #include <QKeyEvent>
0027 #include <QLabel>
0028 #include <QLayout>
0029 #include <QList>
0030 #include <QPushButton>
0031 #include <QStackedWidget>
0032 #include <QStyle>
0033 #include <QTabWidget>
0034 #include <QTimer>
0035 // Std
0036 #include <utility>
0037 
0038 typedef QList<KGameHighScoreDialog::FieldInfo> GroupScores; ///< The list of scores in a group
0039 
0040 class KGameHighScoreDialogPrivate
0041 {
0042 public:
0043     // QList<FieldInfo*> scores;
0044     QMap<QByteArray, GroupScores> scores; ///< Maps config group name to GroupScores
0045     QList<QByteArray> hiddenGroups; /// Groups that should not be shown in the dialog
0046     QMap<int, QByteArray> configGroupWeights; /// Weights of the groups, defines ordering
0047     QTabWidget *tabWidget;
0048     // QWidget *page;
0049     // QGridLayout *layout;
0050     KLineEdit *edit; ///< The line edit for entering player name
0051     QMap<QByteArray, QList<QStackedWidget *>> stack;
0052     QMap<QByteArray, QList<QLabel *>> labels; ///< For each group, the labels along each row in turn starting from "#1"
0053     QLabel *commentLabel;
0054     QString comment;
0055     int fields;
0056     int hiddenFields;
0057     QPair<QByteArray, int> newName; // index of the new name to add (groupKey, position)
0058     QPair<QByteArray, int> latest; // index of the latest addition (groupKey, position)
0059     int nrCols;
0060     bool loaded;
0061     QByteArray configGroup;
0062     KGameHighscore *highscoreObject;
0063     QMap<QByteArray, QString> translatedGroupNames; ///< List of the translated group names.
0064     QMap<QByteArray, QWidget *> tabs;
0065 
0066     QMap<int, int> col;
0067     QMap<int, QString> header; ///< Header for fields. Maps field index to a string
0068     QMap<int, QString> key; ///< Keys for fields. Maps field index to a string
0069     QString player;
0070     int lastHighPosition; /// remember the position to delete if the user wants to forget
0071 
0072     QDialogButtonBox *buttonBox;
0073 
0074     KGameHighScoreDialog *const q;
0075 
0076 public:
0077     // Q-Pointer
0078     explicit KGameHighScoreDialogPrivate(KGameHighScoreDialog *parent)
0079         : q(parent)
0080     {
0081     }
0082 
0083     // Functions
0084     void loadScores();
0085     void saveScores();
0086 
0087     void setupDialog();
0088     void setupGroup(const QByteArray &groupName);
0089     void aboutToShow();
0090 
0091     QString findTranslatedGroupName(const QByteArray &name);
0092 };
0093 
0094 KGameHighScoreDialog::KGameHighScoreDialog(int fields, QWidget *parent)
0095     : QDialog(parent)
0096     , d_ptr(new KGameHighScoreDialogPrivate(this))
0097 {
0098     Q_D(KGameHighScoreDialog);
0099 
0100     setWindowTitle(i18n("High Scores"));
0101     setModal(true);
0102     d->highscoreObject = new KGameHighscore();
0103     d->edit = nullptr;
0104     fields |= Score; // Make 'Score' field automatic (it can be hidden if necessary)
0105     d->fields = fields;
0106     d->hiddenFields = 0;
0107     d->newName = QPair<QByteArray, int>(QByteArray(), -1);
0108     d->latest = QPair<QByteArray, int>("Null", -1);
0109     d->loaded = false;
0110     d->nrCols = 0;
0111     d->configGroup = QByteArray();
0112 
0113     // Set up the default table headers
0114     d->header[Name] = i18n("Name");
0115     d->key[Name] = QStringLiteral("Name");
0116     d->header[Date] = i18n("Date");
0117     d->key[Date] = QStringLiteral("Date");
0118     d->header[Level] = i18n("Level");
0119     d->key[Level] = QStringLiteral("Level");
0120     d->header[Score] = i18n("Score");
0121     d->key[Score] = QStringLiteral("Score");
0122     d->header[Time] = i18n("Time");
0123     d->key[Time] = QStringLiteral("Time");
0124 
0125     // d->page = new QWidget(this);
0126 
0127     d->tabWidget = new QTabWidget(this);
0128     d->tabWidget->setTabPosition(QTabWidget::West);
0129 
0130     QVBoxLayout *mainLayout = new QVBoxLayout;
0131     setLayout(mainLayout);
0132     mainLayout->addWidget(d->tabWidget);
0133 
0134     d->buttonBox = new QDialogButtonBox(this);
0135 
0136     d->buttonBox->setStandardButtons(QDialogButtonBox::Close);
0137     connect(d->buttonBox, &QDialogButtonBox::rejected, this, &KGameHighScoreDialog::reject);
0138 
0139     mainLayout->addWidget(d->buttonBox);
0140 }
0141 
0142 KGameHighScoreDialog::~KGameHighScoreDialog()
0143 {
0144     Q_D(KGameHighScoreDialog);
0145 
0146     delete d->highscoreObject;
0147 }
0148 
0149 void KGameHighScoreDialog::setConfigGroup(const QPair<QByteArray, QString> &group)
0150 {
0151     Q_D(KGameHighScoreDialog);
0152 
0153     d->configGroup = group.first; // untranslated string
0154     addLocalizedConfigGroupName(group); // add the translation to the list
0155     d->loaded = false;
0156 }
0157 
0158 void KGameHighScoreDialog::addLocalizedConfigGroupName(const QPair<QByteArray, QString> &group)
0159 {
0160     Q_D(KGameHighScoreDialog);
0161 
0162     if (!d->translatedGroupNames.contains(group.first)) {
0163         d->translatedGroupNames.insert(group.first, group.second);
0164         qCDebug(KDEGAMES_HIGHSCORE_LOG) << "adding" << group.first << "->" << group.second;
0165     }
0166 }
0167 
0168 void KGameHighScoreDialog::addLocalizedConfigGroupNames(const QMap<QByteArray, QString> &groups)
0169 {
0170     Q_D(KGameHighScoreDialog);
0171 
0172     QMap<QByteArray, QString>::const_iterator it = groups.begin();
0173     for (; it != groups.end(); ++it) {
0174         addLocalizedConfigGroupName(qMakePair(it.key(), it.value()));
0175     }
0176 }
0177 
0178 void KGameHighScoreDialog::initFromDifficulty(const KGameDifficulty *diff, bool doSetConfigGroup)
0179 {
0180     QMap<QByteArray, QString> localizedLevelStrings;
0181     QMap<int, QByteArray> levelWeights;
0182     const auto levels = diff->levels();
0183     for (const KGameDifficultyLevel *level : levels) {
0184         localizedLevelStrings.insert(level->key(), level->title());
0185         levelWeights.insert(level->hardness(), level->key());
0186     }
0187     addLocalizedConfigGroupNames(localizedLevelStrings);
0188     setConfigGroupWeights(levelWeights);
0189     if (doSetConfigGroup) {
0190         const KGameDifficultyLevel *curLvl = diff->currentLevel();
0191         setConfigGroup(qMakePair(curLvl->key(), curLvl->title()));
0192     }
0193 }
0194 
0195 void KGameHighScoreDialog::setHiddenConfigGroups(const QList<QByteArray> &hiddenGroups)
0196 {
0197     Q_D(KGameHighScoreDialog);
0198 
0199     d->hiddenGroups = hiddenGroups;
0200 }
0201 
0202 void KGameHighScoreDialog::setConfigGroupWeights(const QMap<int, QByteArray> &weights)
0203 {
0204     Q_D(KGameHighScoreDialog);
0205 
0206     d->configGroupWeights = weights;
0207 }
0208 
0209 QString KGameHighScoreDialogPrivate::findTranslatedGroupName(const QByteArray &name)
0210 {
0211     const QString lookupResult = translatedGroupNames.value(name);
0212     // If it wasn't found then just try i18n( to see if it happens to be in the database
0213     return lookupResult.isEmpty() ? i18n(name.constData()) : lookupResult; // FIXME?
0214 }
0215 
0216 void KGameHighScoreDialog::setComment(const QString &comment)
0217 {
0218     Q_D(KGameHighScoreDialog);
0219 
0220     d->comment = comment;
0221 }
0222 
0223 void KGameHighScoreDialog::addField(int field, const QString &header, const QString &key)
0224 {
0225     Q_D(KGameHighScoreDialog);
0226 
0227     d->fields |= field;
0228     d->header[field] = header;
0229     d->key[field] = key;
0230 }
0231 
0232 void KGameHighScoreDialog::hideField(int field)
0233 {
0234     Q_D(KGameHighScoreDialog);
0235 
0236     d->hiddenFields |= field;
0237 }
0238 
0239 /*
0240 Create the widgets and layouts etc. for the dialog
0241 */
0242 void KGameHighScoreDialogPrivate::setupDialog()
0243 {
0244     nrCols = 1;
0245     for (int field = 1; field < fields; field = field * 2) {
0246         if ((fields & field) && !(hiddenFields & field))
0247             col[field] = nrCols++;
0248     }
0249 
0250     tabWidget->clear();
0251     QList<QByteArray> keysToConfigure = scores.keys();
0252     for (const QByteArray &groupName : std::as_const(configGroupWeights)) {
0253         int index = keysToConfigure.indexOf(groupName);
0254         if (index != -1) {
0255             setupGroup(groupName);
0256             keysToConfigure.removeAt(index);
0257         }
0258     }
0259     for (const QByteArray &groupName : std::as_const(keysToConfigure)) {
0260         setupGroup(groupName);
0261     }
0262 }
0263 
0264 void KGameHighScoreDialogPrivate::setupGroup(const QByteArray &groupKey)
0265 {
0266     if (hiddenGroups.contains(groupKey))
0267         return;
0268     QWidget *widget = new QWidget(q);
0269     tabs[groupKey] = widget;
0270 
0271     QString tabName = groupKey.isEmpty() ? i18n("High Scores") : findTranslatedGroupName(groupKey);
0272     tabWidget->addTab(widget, tabName);
0273 
0274     QGridLayout *layout = new QGridLayout(widget);
0275     // layout->setObjectName( QLatin1String("ScoreTab-" )+groupName);
0276     // layout->setMargin(QApplication::style()->pixelMetric(QStyle::PM_DefaultChildMargin)+20);
0277     // layout->setSpacing(QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
0278     layout->addItem(new QSpacerItem(0, 15), 4, 0);
0279 
0280     commentLabel = new QLabel(tabWidget);
0281     commentLabel->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
0282 
0283     QFont bold = q->font();
0284     bold.setBold(true);
0285 
0286     QLabel *label;
0287     layout->addItem(new QSpacerItem(50, 0), 0, 0);
0288     label = new QLabel(i18n("Rank"), widget);
0289     layout->addWidget(label, 3, 0);
0290     label->setFont(bold);
0291 
0292     for (int field = 1; field < fields; field = field * 2) {
0293         if ((fields & field) && !(hiddenFields & field)) // If it's used and not hidden
0294         {
0295             layout->addItem(new QSpacerItem(50, 0), 0, col[field]);
0296             label = new QLabel(header[field], widget);
0297             layout->addWidget(label, 3, col[field], field <= KGameHighScoreDialog::Name ? Qt::AlignLeft : Qt::AlignRight);
0298             label->setFont(bold);
0299         }
0300     }
0301 
0302     KSeparator *sep = new KSeparator(Qt::Horizontal, tabWidget->widget(tabWidget->currentIndex()));
0303     layout->addWidget(sep, 4, 0, 1, nrCols);
0304 
0305     QString num;
0306     for (int i = 1; i <= 10; ++i) {
0307         QLabel *label;
0308         num.setNum(i);
0309         label = new QLabel(i18nc("Enumeration (#1, #2 ...) of the highscore entries", "#%1", num), widget);
0310         labels[groupKey].insert((i - 1) * nrCols + 0, label); // Fill up column zero
0311         layout->addWidget(label, i + 4, 0);
0312         if (fields & KGameHighScoreDialog::Name) // If we have a Name field
0313         {
0314             QStackedWidget *localStack = new QStackedWidget(widget);
0315             stack[groupKey].insert(i - 1, localStack);
0316             layout->addWidget(localStack, i + 4, col[KGameHighScoreDialog::Name]);
0317             label = new QLabel(localStack);
0318             labels[groupKey].insert((i - 1) * nrCols + col[KGameHighScoreDialog::Name], label);
0319             localStack->addWidget(label);
0320             localStack->setCurrentWidget(label);
0321         }
0322         for (int field = KGameHighScoreDialog::Name * 2; field < fields; field = field * 2) {
0323             if ((fields & field) && !(hiddenFields & field)) // Maybe disable for Name?
0324             {
0325                 label = new QLabel(widget);
0326                 labels[groupKey].insert((i - 1) * nrCols + col[field], label);
0327                 layout->addWidget(label, i + 4, col[field], Qt::AlignRight);
0328             }
0329         }
0330     }
0331 }
0332 
0333 /*
0334 Fill the dialog with the correct data
0335 */
0336 void KGameHighScoreDialogPrivate::aboutToShow()
0337 {
0338     if (!loaded)
0339         loadScores();
0340 
0341     if (!nrCols)
0342         setupDialog();
0343 
0344     int tabIndex = 0; // Index of the current tab
0345 
0346     QMap<QByteArray, GroupScores>::const_iterator it = scores.constBegin();
0347     for (; it != scores.constEnd(); ++it) {
0348         const QByteArray &groupKey = it.key();
0349         if (hiddenGroups.contains(groupKey))
0350             continue;
0351         qCDebug(KDEGAMES_HIGHSCORE_LOG) << latest.first << tabWidget->tabText(tabIndex);
0352 
0353         // Only display the comment on the page with the new score (or) this one if there's only one tab
0354         if (latest.first == groupKey || (latest.first.isEmpty() && groupKey == "High Scores")) {
0355             QWidget *widget = tabs.value(groupKey);
0356             QGridLayout *layout = qobject_cast<QGridLayout *>(widget->layout());
0357 
0358             commentLabel->setText(comment);
0359             if (comment.isEmpty()) {
0360                 commentLabel->setMinimumSize(QSize(1, 1));
0361                 commentLabel->hide();
0362                 layout->addItem(new QSpacerItem(0, -15), 0, 0);
0363                 layout->addItem(new QSpacerItem(0, -15), 2, 0);
0364             } else {
0365                 layout->addWidget(commentLabel, 1, 0, 1, nrCols);
0366                 commentLabel->setMinimumSize(commentLabel->sizeHint());
0367                 commentLabel->show();
0368                 layout->addItem(new QSpacerItem(0, -10), 0, 0);
0369                 layout->addItem(new QSpacerItem(0, 10), 2, 0);
0370             }
0371             comment.clear();
0372 
0373             tabWidget->setCurrentWidget(widget);
0374         }
0375 
0376         QFont normal = q->font();
0377         QFont bold = normal;
0378         bold.setBold(true);
0379 
0380         QString num;
0381         for (int i = 1; i <= 10; ++i) {
0382             QLabel *label;
0383             num.setNum(i);
0384 
0385             // qCDebug(KDEGAMES_HIGHSCORE_LOG) << "groupName:" << groupName << "id:" << i-1;
0386 
0387             KGameHighScoreDialog::FieldInfo score = scores[groupKey].at(i - 1);
0388             label = labels[groupKey].at((i - 1) * nrCols + 0); // crash! FIXME
0389             if ((i == latest.second) && (groupKey == latest.first))
0390                 label->setFont(bold);
0391             else
0392                 label->setFont(normal);
0393 
0394             if (fields & KGameHighScoreDialog::Name) {
0395                 if ((newName.second == i) && (groupKey == newName.first)) {
0396                     QStackedWidget *localStack = stack[groupKey].at(i - 1);
0397                     edit = new KLineEdit(player, localStack);
0398                     edit->setMinimumWidth(40);
0399                     localStack->addWidget(edit);
0400                     localStack->setCurrentWidget(edit);
0401                     edit->setFocus();
0402                     QObject::connect(edit, &KLineEdit::returnKeyPressed, q, &KGameHighScoreDialog::slotGotReturn);
0403                 } else {
0404                     label = labels[groupKey].at((i - 1) * nrCols + col[KGameHighScoreDialog::Name]);
0405                     if ((i == latest.second) && (groupKey == latest.first))
0406                         label->setFont(bold);
0407                     else
0408                         label->setFont(normal);
0409                     label->setText(score[KGameHighScoreDialog::Name]);
0410                 }
0411             }
0412             for (int field = KGameHighScoreDialog::Name * 2; field < fields; field = field * 2) {
0413                 if ((fields & field) && !(hiddenFields & field)) {
0414                     label = labels[groupKey].at((i - 1) * nrCols + col[field]);
0415                     if ((i == latest.second) && (groupKey == latest.first))
0416                         label->setFont(bold);
0417                     else
0418                         label->setFont(normal);
0419                     label->setText(score[field]);
0420                 }
0421             }
0422         }
0423         tabIndex++;
0424     }
0425     int configGroupIndex = tabWidget->indexOf(tabs.value(configGroup));
0426     if (!hiddenGroups.contains(configGroup) && configGroupIndex > -1) {
0427         tabWidget->setCurrentIndex(configGroupIndex);
0428     }
0429     latest = QPair<QByteArray, int>(QByteArray(), -1);
0430     q->setFixedSize(q->minimumSizeHint()); // NOTE Remove this line to make dialog resizable
0431 }
0432 
0433 void KGameHighScoreDialogPrivate::loadScores()
0434 {
0435     scores.clear();
0436 
0437     QList<QByteArray> groupKeyList; // This will be a list of all the groups in the config file
0438     const auto groupStrings = highscoreObject->groupList();
0439     for (const QString &groupString : groupStrings) {
0440         groupKeyList << groupString.toUtf8(); // Convert all the QStrings to QByteArrays
0441     }
0442 
0443     QByteArray tempCurrentGroup = configGroup; // temp to store the user-set group name
0444 
0445     if (!groupKeyList.contains(configGroup)) // If the current group doesn't have any entries, add it to the list to process
0446     {
0447         qCDebug(KDEGAMES_HIGHSCORE_LOG) << "The current high score group " << configGroup << " isn't in the list, adding it";
0448         groupKeyList << configGroup;
0449         setupGroup(configGroup);
0450     }
0451 
0452     for (const QByteArray &groupKey : std::as_const(groupKeyList)) {
0453         highscoreObject->setHighscoreGroup(QLatin1String(groupKey));
0454         player = highscoreObject->readEntry(0, QStringLiteral("LastPlayer")); // FIXME
0455 
0456         for (int i = 1; i <= 10; ++i) {
0457             KGameHighScoreDialog::FieldInfo score;
0458             for (int field = 1; field < fields; field = field * 2) {
0459                 if (fields & field) {
0460                     score[field] = highscoreObject->readEntry(i, key[field], QStringLiteral("-"));
0461                 }
0462             }
0463             scores[groupKey].append(score);
0464         }
0465     }
0466     highscoreObject->setHighscoreGroup(QLatin1String(tempCurrentGroup)); // reset to the user-set group name
0467     const auto groupKeys = scores.keys();
0468     for (const QByteArray &groupKey : groupKeys) {
0469         if ((scores[groupKey][0].value(KGameHighScoreDialog::Score) == QLatin1String("-")) && (scores.size() > 1) && (latest.first != groupKey)) {
0470             qCDebug(KDEGAMES_HIGHSCORE_LOG) << "Removing group " << groupKey << " since it's unused.";
0471             scores.remove(groupKey);
0472         }
0473     }
0474     loaded = true;
0475 }
0476 
0477 void KGameHighScoreDialogPrivate::saveScores()
0478 {
0479     highscoreObject->setHighscoreGroup(QLatin1String(configGroup));
0480 
0481     highscoreObject->writeEntry(0, QStringLiteral("LastPlayer"), player);
0482 
0483     for (int i = 1; i <= 10; ++i) {
0484         KGameHighScoreDialog::FieldInfo score = scores[configGroup].at(i - 1);
0485         for (int field = 1; field < fields; field = field * 2) {
0486             if (fields & field) {
0487                 highscoreObject->writeEntry(i, key[field], score[field]);
0488             }
0489         }
0490     }
0491     highscoreObject->writeAndUnlock();
0492 }
0493 
0494 int KGameHighScoreDialog::addScore(const FieldInfo &newInfo, AddScoreFlags flags)
0495 {
0496     Q_D(KGameHighScoreDialog);
0497 
0498     qCDebug(KDEGAMES_HIGHSCORE_LOG) << "adding new score";
0499 
0500     bool askName = false, lessIsMore = false;
0501     if (flags.testFlag(KGameHighScoreDialog::AskName))
0502         askName = true;
0503     if (flags.testFlag(KGameHighScoreDialog::LessIsMore))
0504         lessIsMore = true;
0505 
0506     d->latest.first = d->configGroup; // Temporarily set this so loadScores() knows not to delete this group
0507     if (!d->loaded)
0508         d->loadScores();
0509     d->latest.first = "Null"; // and reset it.
0510 
0511     for (int i = 0; i < d->scores[d->configGroup].size(); i++) {
0512         FieldInfo score = d->scores[d->configGroup].at(i); // First look at the score in the config file
0513         bool ok; // will be false if there isn't any score yet in position i
0514         int num_score = score[Score].toLong(&ok); // test if the stored score is a number
0515 
0516         score = FieldInfo(newInfo); // now look at the submitted score
0517         int newScore = score[Score].toInt();
0518 
0519         qCDebug(KDEGAMES_HIGHSCORE_LOG) << "num_score =" << num_score << " - newScore =" << newScore;
0520 
0521         if (((newScore > num_score) && !lessIsMore) || ((newScore < num_score) && lessIsMore) || !ok) {
0522             d->latest = QPair<QByteArray, int>(d->configGroup, i + 1);
0523             d->scores[d->configGroup].insert(i, score);
0524             // Save the position to delete in case of Forget
0525             d->lastHighPosition = i;
0526 
0527             if (score[Name].isEmpty()) // If we don't have a name, prompt the player.
0528             {
0529                 if (!d->player.isEmpty()) // d->player should be filled out by d->loadScores()
0530                 {
0531                     score[Name] = d->player;
0532                 } else {
0533                     KUser user;
0534                     score[Name] = user.property(KUser::FullName).toString();
0535                     if (score[Name].isEmpty()) {
0536                         score[Name] = user.loginName();
0537                     }
0538                 }
0539                 askName = true;
0540             }
0541 
0542             if (askName) {
0543                 d->player = score[Name];
0544                 d->newName = QPair<QByteArray, int>(d->configGroup, i + 1);
0545 
0546                 d->buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
0547 
0548                 d->buttonBox->button(QDialogButtonBox::Ok)->setText(i18n("&Remember"));
0549                 d->buttonBox->button(QDialogButtonBox::Cancel)->setText(i18n("&Forget"));
0550                 d->buttonBox->button(QDialogButtonBox::Ok)->setToolTip(i18n("Remember this high score"));
0551                 d->buttonBox->button(QDialogButtonBox::Cancel)->setToolTip(i18n("Forget this high score"));
0552 
0553                 connect(d->buttonBox, &QDialogButtonBox::accepted, this, &KGameHighScoreDialog::slotGotName);
0554                 connect(d->buttonBox, &QDialogButtonBox::rejected, this, &KGameHighScoreDialog::slotForgetScore);
0555             } else
0556                 d->saveScores();
0557 
0558             if (i == 0)
0559                 d->comment = i18n("Excellent!\nYou have a new high score!");
0560             else
0561                 d->comment = i18n("Well done!\nYou made it to the high score list!");
0562             return i + 1;
0563         }
0564     }
0565     d->latest = qMakePair(d->configGroup, 0);
0566     return 0;
0567 }
0568 
0569 int KGameHighScoreDialog::addScore(int newScore, AddScoreFlags flags)
0570 {
0571     FieldInfo scoreInfo;
0572     scoreInfo[Score] = QString::number(newScore);
0573     return addScore(scoreInfo, AskName | flags);
0574 }
0575 
0576 void KGameHighScoreDialog::show()
0577 {
0578     Q_D(KGameHighScoreDialog);
0579 
0580     d->aboutToShow();
0581     QDialog::show();
0582 }
0583 
0584 int KGameHighScoreDialog::exec()
0585 {
0586     Q_D(KGameHighScoreDialog);
0587 
0588     d->aboutToShow();
0589     return QDialog::exec();
0590 }
0591 
0592 void KGameHighScoreDialog::slotGotReturn()
0593 {
0594     QTimer::singleShot(0, this, &KGameHighScoreDialog::slotGotName);
0595     // TODO: Is it better to hide the window, as if any button where pressed?
0596 }
0597 
0598 void KGameHighScoreDialog::slotGotName()
0599 {
0600     Q_D(KGameHighScoreDialog);
0601 
0602     if (d->newName.second == -1)
0603         return;
0604 
0605     d->player = d->edit->text();
0606 
0607     d->scores[d->newName.first][d->newName.second - 1][Name] = d->player;
0608     d->saveScores();
0609 
0610     QFont bold = font();
0611     bold.setBold(true);
0612 
0613     QLabel *label = d->labels[d->newName.first].at((d->newName.second - 1) * d->nrCols + d->col[Name]);
0614     label->setFont(bold);
0615     label->setText(d->player);
0616     d->stack[d->newName.first].at((d->newName.second - 1))->setCurrentWidget(label);
0617     d->stack[d->newName.first].at((d->newName.second - 1))->removeWidget(d->edit);
0618     delete d->edit;
0619     d->edit = nullptr;
0620     d->newName = QPair<QByteArray, int>(QByteArray(), -1);
0621     d->scores[d->configGroup].removeAt(10);
0622     d->comment.clear(); // hide the congratulations
0623     d->commentLabel->hide();
0624 
0625     d->buttonBox->setStandardButtons(QDialogButtonBox::Close);
0626     connect(d->buttonBox, &QDialogButtonBox::rejected, this, &KGameHighScoreDialog::reject);
0627 }
0628 
0629 void KGameHighScoreDialog::slotForgetScore()
0630 {
0631     Q_D(KGameHighScoreDialog);
0632 
0633     if (d->newName.second == -1)
0634         return;
0635     // remove the editor from the stack
0636     d->stack[d->newName.first].at((d->newName.second - 1))->removeWidget(d->edit);
0637     // delete the editor
0638     delete d->edit;
0639     d->edit = nullptr;
0640     // avoid to recreate the KTextEdit widget
0641     d->newName = QPair<QByteArray, int>(QByteArray(), -1);
0642     // delete the highscore to forget
0643     d->scores[d->configGroup].removeAt(d->lastHighPosition);
0644     d->comment.clear();
0645     d->commentLabel->hide();
0646 
0647     d->buttonBox->setStandardButtons(QDialogButtonBox::Close);
0648     connect(d->buttonBox, &QDialogButtonBox::rejected, this, &KGameHighScoreDialog::reject);
0649 }
0650 
0651 int KGameHighScoreDialog::highScore()
0652 {
0653     Q_D(KGameHighScoreDialog);
0654 
0655     if (!d->loaded)
0656         d->loadScores();
0657 
0658     if (!d->scores[d->configGroup].isEmpty())
0659         return d->scores[d->configGroup].first()[Score].toInt();
0660     else
0661         return 0;
0662 }
0663 
0664 void KGameHighScoreDialog::keyPressEvent(QKeyEvent *ev)
0665 {
0666     Q_D(KGameHighScoreDialog);
0667 
0668     if ((d->newName.second != -1) && (ev->key() == Qt::Key_Return)) {
0669         ev->ignore();
0670         return;
0671     }
0672     QDialog::keyPressEvent(ev);
0673 }
0674 
0675 #include "moc_kgamehighscoredialog.cpp"