28 #include "../kgdifficulty.h"
35 #include <KConfigGroup>
40 #include <QtCore/QTimer>
41 #include <QtCore/QList>
42 #include <QtCore/QByteArray>
43 #include <QtGui/QGridLayout>
44 #include <QtGui/QKeyEvent>
45 #include <QtGui/QLabel>
46 #include <QtGui/QLayout>
47 #include <QtGui/QStackedWidget>
49 #define DEFAULT_GROUP_NAME I18N_NOOP("High Scores")
53 class KScoreDialog::KScoreDialogPrivate
57 QMap<QByteArray, GroupScores> scores;
58 QList<QByteArray> hiddenGroups;
59 QMap<int, QByteArray> configGroupWeights;
60 KTabWidget *tabWidget;
64 QMap<QByteArray, QList<QStackedWidget*> > stack;
65 QMap<QByteArray, QList<QLabel*> > labels;
70 QPair<QByteArray, int> newName;
71 QPair<QByteArray, int> latest;
74 QByteArray configGroup;
76 QMap<QByteArray, QString> translatedGroupNames;
77 QMap<QByteArray, QWidget*> tabs;
80 QMap<int, QString> header;
81 QMap<int, QString> key;
94 void setupGroup(
const QByteArray& groupName);
97 QString findTranslatedGroupName(
const QByteArray& name);
102 :
KDialog(parent), d(new KScoreDialogPrivate(this))
111 d->newName = QPair<QByteArray,int>(QByteArray(),-1);
112 d->latest = QPair<QByteArray,int>(
"Null",-1);
115 d->configGroup=QByteArray();
118 d->header[
Name] = i18n(
"Name");
119 d->key[
Name] = QLatin1String(
"Name" );
120 d->header[
Date] = i18n(
"Date");
121 d->key[
Date] = QLatin1String(
"Date" );
122 d->header[
Level] = i18n(
"Level");
123 d->key[
Level] = QLatin1String(
"Level" );
124 d->header[
Score] = i18n(
"Score");
125 d->key[
Score] = QLatin1String(
"Score" );
126 d->header[
Time] = i18n(
"Time");
127 d->key[
Time] = QLatin1String(
"Time" );
131 d->tabWidget =
new KTabWidget(
this);
132 d->tabWidget->setTabPosition(QTabWidget::West);
134 setMainWidget(d->tabWidget);
135 if(d->newName.second == -1)
139 setButtons(Ok|Cancel);
140 connect(
this, SIGNAL(okClicked()), SLOT(slotGotName()));
146 delete d->highscoreObject;
153 d->configGroup = group.toUtf8();
159 d->configGroup = group.first;
166 if (!d->translatedGroupNames.contains(group.first))
168 d->translatedGroupNames.insert(group.first, group.second);
169 kDebug() <<
"adding" << group.first <<
"->" << group.second;
175 QMap<QByteArray, QString>::const_iterator it = groups.begin();
176 for (; it != groups.end(); ++it)
184 QMap<QByteArray, QString> localizedLevelStrings;
185 QMap<int, QByteArray> levelWeights;
186 foreach (
const KgDifficultyLevel* level, diff->levels())
188 localizedLevelStrings.insert(level->key(), level->title());
189 levelWeights.insert(level->hardness(), level->key());
193 if (doSetConfigGroup)
195 const KgDifficultyLevel* curLvl = diff->currentLevel();
202 d->hiddenGroups = hiddenGroups;
207 d->configGroupWeights = weights;
210 QString KScoreDialog::KScoreDialogPrivate::findTranslatedGroupName(
const QByteArray& name)
212 const QString lookupResult = translatedGroupNames.value(name);
214 return lookupResult.isEmpty() ? i18n(name) : lookupResult;
219 d->comment = comment;
225 d->header[field] = header;
231 d->hiddenFields |= field;
238 void KScoreDialog::KScoreDialogPrivate::setupDialog()
241 for(
int field = 1; field < fields; field = field * 2)
243 if ( (fields & field) && !(hiddenFields & field ) )
244 col[field] = nrCols++;
248 QList<QByteArray> keysToConfigure = scores.keys();
249 foreach(
const QByteArray &groupName, configGroupWeights)
251 int index = keysToConfigure.indexOf(groupName);
254 setupGroup(groupName);
255 keysToConfigure.removeAt(index);
258 foreach(
const QByteArray &groupName, keysToConfigure)
260 setupGroup(groupName);
264 void KScoreDialog::KScoreDialogPrivate::setupGroup(
const QByteArray& groupKey)
266 if (hiddenGroups.contains(groupKey))
269 tabs[groupKey] = widget;
271 QString tabName = groupKey.isEmpty() ? i18n(
DEFAULT_GROUP_NAME) : findTranslatedGroupName(groupKey);
272 tabWidget->addTab(widget, tabName);
274 QGridLayout* layout =
new QGridLayout(widget);
276 layout->setMargin(marginHint()+20);
277 layout->setSpacing(spacingHint());
278 layout->addItem(
new QSpacerItem(0, 15), 4, 0);
280 commentLabel =
new QLabel(tabWidget);
281 commentLabel->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
283 QFont bold = q->font();
287 layout->addItem(
new QSpacerItem(50, 0), 0, 0);
288 label =
new QLabel(i18n(
"Rank"), widget);
289 layout->addWidget(label, 3, 0);
290 label->setFont(bold);
292 for(
int field = 1; field < fields; field = field * 2)
294 if ( (fields & field) && !(hiddenFields & field ) )
296 layout->addItem(
new QSpacerItem( 50, 0 ), 0, col[field] );
297 label =
new QLabel(header[field], widget);
298 layout->addWidget(label, 3, col[field], field <= Name ? Qt::AlignLeft : Qt::AlignRight);
299 label->setFont(bold);
303 KSeparator *sep =
new KSeparator(Qt::Horizontal, tabWidget->widget(tabWidget->currentIndex()));
304 layout->addWidget(sep, 4, 0, 1, nrCols);
307 for (
int i = 1; i <= 10; ++i)
311 label =
new QLabel(i18nc(
"Enumeration (#1, #2 ...) of the highscore entries",
"#%1", num), widget);
312 labels[groupKey].insert((i-1)*nrCols + 0, label);
313 layout->addWidget(label, i+4, 0);
316 QStackedWidget *localStack =
new QStackedWidget(widget);
317 stack[groupKey].insert(i-1, localStack);
318 layout->addWidget(localStack, i+4, col[Name]);
319 label =
new QLabel(localStack);
320 labels[groupKey].insert((i-1)*nrCols + col[Name], label);
321 localStack->addWidget(label);
322 localStack->setCurrentWidget(label);
324 for(
int field = Name * 2; field < fields; field = field * 2)
326 if ( (fields & field) && !(hiddenFields & field ) )
328 label =
new QLabel(widget);
329 labels[groupKey].insert((i-1)*nrCols + col[field], label);
330 layout->addWidget(label, i+4, col[field], Qt::AlignRight);
340 void KScoreDialog::KScoreDialogPrivate::aboutToShow()
350 QMap<QByteArray, GroupScores>::const_iterator it = scores.constBegin();
351 for (; it != scores.constEnd(); ++it)
353 const QByteArray &groupKey = it.key();
354 if (hiddenGroups.contains(groupKey))
356 kDebug() << latest.first << tabWidget->tabText(tabIndex);
359 if(latest.first == groupKey || ( latest.first.isEmpty() && groupKey ==
DEFAULT_GROUP_NAME ) )
361 QWidget* widget = tabs.value(groupKey);
362 QGridLayout* layout = qobject_cast<QGridLayout*>(widget->layout());
364 commentLabel->setText(comment);
365 if (comment.isEmpty())
367 commentLabel->setMinimumSize(QSize(1,1));
368 commentLabel->hide();
369 layout->addItem(
new QSpacerItem( 0, -15 ), 0, 0 );
370 layout->addItem(
new QSpacerItem( 0, -15 ), 2, 0 );
374 layout->addWidget(commentLabel, 1, 0, 1, nrCols);
375 commentLabel->setMinimumSize(commentLabel->sizeHint());
376 commentLabel->show();
377 layout->addItem(
new QSpacerItem( 0, -10 ), 0, 0 );
378 layout->addItem(
new QSpacerItem( 0, 10 ), 2, 0 );
382 tabWidget->setCurrentWidget(widget);
385 QFont normal = q->font();
390 for (
int i = 1; i <= 10; ++i)
397 FieldInfo score = scores[groupKey].at(i-1);
398 label = labels[groupKey].at((i-1)*nrCols + 0);
399 if ( (i == latest.second) && (groupKey == latest.first) )
400 label->setFont(bold);
402 label->setFont(normal);
406 if ( (newName.second == i) && (groupKey == newName.first) )
408 QStackedWidget *localStack = stack[groupKey].at(i-1);
409 edit =
new KLineEdit(player, localStack);
410 edit->setMinimumWidth(40);
411 localStack->addWidget(edit);
412 localStack->setCurrentWidget(edit);
414 connect(edit, SIGNAL(returnPressed()), q, SLOT(slotGotReturn()));
418 label = labels[groupKey].at((i-1)*nrCols + col[Name]);
419 if ( (i == latest.second) && (groupKey == latest.first) )
420 label->setFont(bold);
422 label->setFont(normal);
423 label->setText(score[Name]);
427 for(
int field = Name * 2; field < fields; field = field * 2)
429 if ( (fields & field) && !(hiddenFields & field ) )
431 label = labels[groupKey].at((i-1)*nrCols + col[field]);
432 if ( (i == latest.second) && (groupKey == latest.first) )
433 label->setFont(bold);
435 label->setFont(normal);
436 label->setText(score[field]);
442 latest = QPair<QByteArray,int>(QByteArray(),-1);
443 q->setFixedSize(q->minimumSizeHint());
446 void KScoreDialog::KScoreDialogPrivate::loadScores()
450 QList<QByteArray> groupKeyList;
451 foreach(
const QString & groupString, highscoreObject->groupList())
453 groupKeyList << groupString.toUtf8();
456 QByteArray tempCurrentGroup = configGroup;
458 if (!groupKeyList.contains( configGroup) )
460 kDebug(11002) <<
"The current high score group " << configGroup <<
" isn't in the list, adding it";
461 groupKeyList << configGroup;
462 setupGroup(configGroup);
465 foreach(
const QByteArray &groupKey, groupKeyList)
467 highscoreObject->setHighscoreGroup(QLatin1String( groupKey ));
468 player = highscoreObject->readEntry(0, QLatin1String(
"LastPlayer" ));
470 for (
int i = 1; i <= 10; ++i)
473 for(
int field = 1; field < fields; field = field * 2)
477 score[field] = highscoreObject->readEntry(i, key[field], QLatin1String(
"-"));
480 scores[groupKey].append(score);
483 highscoreObject->setHighscoreGroup(QLatin1String( tempCurrentGroup ));
484 foreach(
const QByteArray &groupKey, scores.keys())
486 if( (scores[groupKey][0].value(Score)==QLatin1String(
"-" )) && (scores.size() > 1) && (latest.first != groupKey) )
488 kDebug(11002) <<
"Removing group " << groupKey <<
" since it's unused.";
489 scores.remove(groupKey);
495 void KScoreDialog::KScoreDialogPrivate::saveScores()
497 highscoreObject->setHighscoreGroup(QLatin1String( configGroup ));
499 highscoreObject->writeEntry(0,QLatin1String(
"LastPlayer" ), player);
501 for (
int i = 1; i <= 10; ++i)
503 FieldInfo score = scores[configGroup].at(i-1);
504 for(
int field = 1; field < fields; field = field * 2)
508 highscoreObject->writeEntry(i, key[field], score[field]);
512 highscoreObject->writeAndUnlock();
517 kDebug() <<
"adding new score";
519 bool askName=
false, lessIsMore=
false;
525 d->latest.first = d->configGroup;
528 d->latest.first =
"Null";
530 for(
int i=0; i<d->scores[d->configGroup].size(); i++)
532 FieldInfo score = d->scores[d->configGroup].at(i);
534 int num_score = score[
Score].toLong(&ok);
537 int newScore = score[
Score].toInt();
539 kDebug() <<
"num_score =" << num_score <<
" - newScore =" << newScore;
541 if (((newScore > num_score) && !lessIsMore) ||
542 ((newScore < num_score) && lessIsMore) || !ok)
544 d->latest = QPair<QByteArray,int>(d->configGroup,i+1);
545 d->scores[d->configGroup].insert(i, score);
547 d->lastHighPosition = i;
549 if(score[Name].isEmpty())
551 if(!d->player.isEmpty())
553 score[
Name] = d->player;
558 score[
Name] = user.property(KUser::FullName).toString();
559 if (score[Name].isEmpty())
561 score[
Name] = user.loginName();
569 d->player=score[
Name];
570 d->newName = QPair<QByteArray,int>(d->configGroup,i+1);
572 setButtons(Ok|Cancel);
573 setButtonText(Ok, i18n(
"&Remember"));
574 setButtonText(Cancel, i18n(
"&Forget"));
575 setButtonToolTip(Ok, i18n(
"Remember this high score"));
576 setButtonToolTip(Cancel, i18n(
"Forget this high score"));
577 connect(
this, SIGNAL(okClicked()), SLOT(slotGotName()));
578 connect(
this, SIGNAL(cancelClicked()), SLOT(slotForgetScore()));
584 d->comment = i18n(
"Excellent!\nYou have a new high score!");
586 d->comment = i18n(
"Well done!\nYou made it to the high score list!");
590 d->latest = qMakePair(d->configGroup, 0);
597 scoreInfo[
Score]=QString::number(newScore);
613 void KScoreDialog::slotGotReturn()
615 QTimer::singleShot(0,
this, SLOT(slotGotName()));
619 void KScoreDialog::slotGotName()
621 if (d->newName.second == -1)
return;
623 d->player = d->edit->text();
625 d->scores[d->newName.first][d->newName.second-1][
Name] = d->player;
631 QLabel *label = d->labels[d->newName.first].at((d->newName.second-1)*d->nrCols + d->col[Name]);
632 label->setFont(bold);
633 label->setText(d->player);
634 d->stack[d->newName.first].at((d->newName.second-1))->setCurrentWidget(label);
635 d->stack[d->newName.first].at((d->newName.second-1))->removeWidget(d->edit);
638 d->newName = QPair<QByteArray,int>(QByteArray(),-1);
639 d->scores[d->configGroup].removeAt(10);
641 d->commentLabel->hide();
645 void KScoreDialog::slotForgetScore()
647 if (d->newName.second == -1)
return;
649 d->stack[d->newName.first].at((d->newName.second-1))->removeWidget(d->edit);
654 d->newName = QPair<QByteArray,int>(QByteArray(),-1);
656 d->scores[d->configGroup].removeAt(d->lastHighPosition);
658 d->commentLabel->hide();
668 if (!d->scores[d->configGroup].isEmpty())
669 return d->scores[d->configGroup].first()[
Score].toInt();
674 void KScoreDialog::keyPressEvent(QKeyEvent *ev)
676 if ((d->newName.second != -1) && (ev->key() == Qt::Key_Return))
681 KDialog::keyPressEvent(ev);
684 #include "kscoredialog.moc"
Class for managing highscore tables.
void KDE_DEPRECATED setConfigGroup(const QString &group=QString())
The group name must be passed though I18N_NOOP() in order for the group name to be translated...
void setComment(const QString &comment)
void addLocalizedConfigGroupNames(const QMap< QByteArray, QString > &groups)
You must add the translations of all group names to the dialog.
void show(QWidget *parent, int rank)
A simple high score implementation.
void setConfigGroupWeights(const QMap< int, QByteArray > &weights)
It is a good idea giving config group weigths, otherwise tabs get ordered by their tab name that is n...
int addScore(const FieldInfo &newInfo=FieldInfo(), const AddScoreFlags &flags=0)
Adds a new score to the list.
Promt the player for their name.
virtual void show()
Display the dialog as non-modal.
void addLocalizedConfigGroupName(const QPair< QByteArray, QString > &group)
You must add the translations of all group names to the dialog.
void initFromDifficulty(const KgDifficulty *difficulty, bool setConfigGroup=true)
Assume that config groups (incl.
KScoreDialog(int fields=Name, QWidget *parent=0)
void hideField(int field)
Hide a field so that it is not shown on the table (but is still stored in the configuration file)...
QMap< int, QString > FieldInfo
void addField(int field, const QString &header, const QString &key)
Define an extra FieldInfo entry.
virtual void exec()
Display the dialog as modal.
#define DEFAULT_GROUP_NAME
QList< KScoreDialog::FieldInfo > GroupScores
The list of scores in a group.
A lower numerical score means higher placing on the table.
void setHiddenConfigGroups(const QList< QByteArray > &hiddenGroups)
Hide some config groups so that they are not shown on the dialog (but are still stored in the configu...