• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

libkdegames/highscore

kscoredialog.cpp

Go to the documentation of this file.
00001 /****************************************************************
00002 Copyright (c) 1998 Sandro Sigala <ssigala@globalnet.it>.
00003 Copyright (c) 2001 Waldo Bastian <bastian@kde.org>
00004 Copyright (c) 2007 Matt Williams <matt@milliams.com>
00005 All rights reserved.
00006 
00007 Permission to use, copy, modify, and distribute this software
00008 and its documentation for any purpose and without fee is hereby
00009 granted, provided that the above copyright notice appear in all
00010 copies and that both that the copyright notice and this
00011 permission notice and warranty disclaimer appear in supporting
00012 documentation, and that the name of the author not be used in
00013 advertising or publicity pertaining to distribution of the
00014 software without specific, written prior permission.
00015 
00016 The author disclaim all warranties with regard to this
00017 software, including all implied warranties of merchantability
00018 and fitness.  In no event shall the author be liable for any
00019 special, indirect or consequential damages or any damages
00020 whatsoever resulting from loss of use, data or profits, whether
00021 in an action of contract, negligence or other tortious action,
00022 arising out of or in connection with the use or performance of
00023 this software.
00024 ****************************************************************/
00025 
00026 #include "kscoredialog.h"
00027 #include "khighscore.h"
00028 
00029 #include <KConfig>
00030 #include <KLocale>
00031 #include <KSeparator>
00032 #include <KGlobal>
00033 #include <KConfigGroup>
00034 #include <KTabWidget>
00035 #include <KDebug>
00036 
00037 #include <QtCore/QTimer>
00038 #include <QtCore/QList>
00039 #include <QtGui/QGridLayout>
00040 #include <QtGui/QKeyEvent>
00041 #include <QtGui/QLabel>
00042 #include <QtGui/QLayout>
00043 #include <QtGui/QLineEdit>
00044 #include <QtGui/QStackedWidget>
00045 
00046 #define DEFAULT_GROUP_NAME I18N_NOOP("High Scores")
00047 
00048 typedef QList<KScoreDialog::FieldInfo> GroupScores; 
00049 
00050 class KScoreDialog::KScoreDialogPrivate
00051 {
00052     public:
00053         //QList<FieldInfo*> scores;
00054         QMap<QString, GroupScores> scores; 
00055         KTabWidget *tabWidget;
00056         //QWidget *page;
00057         //QGridLayout *layout;
00058         QLineEdit *edit;    
00059         QMap<QString, QList<QStackedWidget*> > stack;
00060         QMap<QString, QList<QLabel*> > labels; 
00061         QLabel *commentLabel;
00062         QString comment;
00063         int fields;
00064         int hiddenFields;
00065         QPair<QString, int> newName; //index of the newname to add
00066         QPair<QString, int> latest; //index of the latest addition (groupName, position)
00067         int nrCols;
00068         int numberOfPages;
00069         bool loaded;
00070         QString configGroup;
00071         KHighscore* highscoreObject;
00072         
00073         QMap<int, int> col;
00074         QMap<int, QString> header; 
00075         QMap<int, QString> key; 
00076         QString player;
00077         
00078         //Q-Pointer
00079         KScoreDialogPrivate(KScoreDialog* parent):q(parent){}
00080         KScoreDialog* const q;
00081         
00082         //Functions
00083         void loadScores();
00084         void saveScores();
00085         
00086         void setupDialog();
00087         void setupGroup(QString& groupName);
00088         void aboutToShow();
00089 };
00090 
00091 
00092 KScoreDialog::KScoreDialog(int fields, QWidget *parent)
00093     : KDialog(parent), d(new KScoreDialogPrivate(this))
00094 {
00095     setCaption( i18n(DEFAULT_GROUP_NAME) );
00096     setModal( true );
00097     d->highscoreObject = new KHighscore();
00098     d->edit = 0;
00099     fields |= Score; //Make 'Score' field automatic (it can be hidden if necessary)
00100     d->fields = fields;
00101     d->hiddenFields = 0;
00102     d->newName = QPair<QString,int>(QString(),-1);
00103     d->latest = QPair<QString,int>("Null",-1);
00104     d->loaded = false;
00105     d->nrCols = 0;
00106     d->numberOfPages=0;
00107     d->configGroup=QString();
00108     
00109     //Set up the default table headers
00110     d->header[Name] = i18n("Name");
00111     d->key[Name] = "Name";
00112     d->header[Date] = i18n("Date");
00113     d->key[Date] = "Date";
00114     d->header[Level] = i18n("Level");
00115     d->key[Level] = "Level";
00116     d->header[Score] = i18n("Score");
00117     d->key[Score] = "Score";
00118     d->header[Time] = i18n("Time");
00119     d->key[Time] = "Time";
00120     
00121     //d->page = new QWidget(this);
00122     
00123     d->tabWidget = new KTabWidget(this);
00124     d->tabWidget->setTabPosition(QTabWidget::West);
00125     
00126     setMainWidget(d->tabWidget);
00127     if(d->newName.second == -1)
00128       setButtons(Close);
00129     else
00130     {
00131        setButtons(Ok|Cancel);
00132        connect(this, SIGNAL(okClicked()), SLOT(slotGotName()));
00133     }
00134 }
00135 
00136 KScoreDialog::~KScoreDialog()
00137 {
00138     delete d->highscoreObject;
00139 
00140     delete d;
00141 }
00142 
00143 void KScoreDialog::setConfigGroup(const QString &group)
00144 {
00145     d->configGroup = group;
00146     d->loaded = false;
00147 }
00148 
00149 void KScoreDialog::setComment(const QString &comment)
00150 {
00151     d->comment = comment;
00152 }
00153 
00154 void KScoreDialog::addField(int field, const QString &header, const QString &key)
00155 {
00156     d->fields |= field;
00157     d->header[field] = header;
00158     d->key[field] = key;
00159 }
00160 
00161 void KScoreDialog::hideField(int field)
00162 {
00163     d->hiddenFields |= field;
00164 }
00165 
00166 /*
00167 Create the widgets and layouts etc. for the dialog
00168 */
00169 
00170 void KScoreDialog::KScoreDialogPrivate::setupDialog()
00171 {
00172     nrCols = 1;
00173     for(int field = 1; field < fields; field = field * 2)
00174     {
00175         if ( (fields & field) && !(hiddenFields & field ) )
00176             col[field] = nrCols++;
00177     }
00178     
00179     tabWidget->clear();
00180     foreach(QString groupName, scores.keys())
00181         setupGroup(groupName);
00182 }
00183 
00184 void KScoreDialog::KScoreDialogPrivate::setupGroup(QString& groupName)
00185 {
00186         if(groupName.isEmpty()) //If the group doesn't have a name, use a default.
00187             tabWidget->addTab(new QWidget(q), i18n(DEFAULT_GROUP_NAME));
00188         else
00189             tabWidget->addTab(new QWidget(q), i18n(groupName.toUtf8()));
00190         tabWidget->setCurrentIndex(tabWidget->count()-1);
00191         
00192         QGridLayout* layout = new QGridLayout( tabWidget->widget( tabWidget->currentIndex() ) );
00193         //layout->setObjectName("ScoreTab-"+groupName);
00194         layout->setMargin(marginHint()+20);
00195         layout->setSpacing(spacingHint());
00196         layout->addItem(new QSpacerItem(0, 15), 4, 0);
00197         
00198         commentLabel = new QLabel(tabWidget);
00199         commentLabel->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
00200         
00201         QFont bold = q->font();
00202         bold.setBold(true);
00203         
00204         QLabel *label;
00205         layout->addItem(new QSpacerItem(50, 0), 0, 0);
00206         label = new QLabel(i18n("Rank"), tabWidget->widget(tabWidget->currentIndex()));
00207         layout->addWidget(label, 3, 0);
00208         label->setFont(bold);
00209         
00210         for(int field = 1; field < fields; field = field * 2)
00211         {
00212             if ( (fields & field) && !(hiddenFields & field ) ) //If it's used and not hidden
00213             {
00214                 layout->addItem( new QSpacerItem( 50, 0 ), 0, col[field] );
00215                 label = new QLabel(header[field], tabWidget->widget(tabWidget->currentIndex()));
00216                 layout->addWidget(label, 3, col[field], field <= Name ? Qt::AlignLeft : Qt::AlignRight);
00217                 label->setFont(bold);
00218             }
00219         }
00220         
00221         KSeparator *sep = new KSeparator(Qt::Horizontal, tabWidget->widget(tabWidget->currentIndex()));
00222         layout->addWidget(sep, 4, 0, 1, nrCols);
00223         
00224         QString num;
00225         for (int i = 1; i <= 10; ++i) 
00226         {
00227             QLabel *label;
00228             num.setNum(i);
00229             label = new QLabel(i18n("#%1", num), tabWidget->widget(tabWidget->currentIndex()));
00230             labels[groupName].insert((i-1)*nrCols + 0, label); //Fill up column zero
00231             layout->addWidget(label, i+4, 0);
00232             if (fields & Name) //If we have a Name field
00233             {
00234                 QStackedWidget *localStack = new QStackedWidget(tabWidget->widget(tabWidget->currentIndex()));
00235                 stack[groupName].insert(i-1, localStack);
00236                 layout->addWidget(localStack, i+4, col[Name]);
00237                 label = new QLabel(localStack);
00238                 labels[groupName].insert((i-1)*nrCols + col[Name], label);
00239                 localStack->addWidget(label);
00240                 localStack->setCurrentWidget(label);
00241             }
00242             for(int field = Name * 2; field < fields; field = field * 2)
00243             {
00244                 if ( (fields & field) && !(hiddenFields & field ) ) //Maybe disable for Name?
00245                 {
00246                     label = new QLabel(tabWidget->widget(tabWidget->currentIndex()));
00247                     labels[groupName].insert((i-1)*nrCols + col[field], label);
00248                     layout->addWidget(label, i+4, col[field], Qt::AlignRight);
00249                 }
00250             }
00251         }
00252 }
00253 
00254 /*
00255 Fill the dialog with the correct data
00256 */
00257 
00258 void KScoreDialog::KScoreDialogPrivate::aboutToShow()
00259 {
00260     if (!loaded)
00261         loadScores();
00262     
00263     if (!nrCols)
00264         setupDialog();
00265     
00266     int tabIndex=0; //Index of the current tab
00267     int newScoreTabIndex=0; //The index of the tab of the group with the new score
00268     foreach(QString groupName, scores.keys())
00269     {
00270         //Only display the comment on the page with the new score (or) this one if there's only one tab
00271         if((latest.first == tabWidget->tabText(tabIndex)) || ( latest.first.isEmpty() && tabWidget->tabText(tabIndex) == i18n(DEFAULT_GROUP_NAME) ))
00272         {
00273             newScoreTabIndex=tabIndex;
00274             commentLabel->setText(comment);
00275             if (comment.isEmpty())
00276             {
00277                 commentLabel->setMinimumSize(QSize(1,1));
00278                 commentLabel->hide();
00279                 QGridLayout* layout = qobject_cast<QGridLayout*>(tabWidget->widget(newScoreTabIndex)->layout());
00280                 layout->addItem( new QSpacerItem( 0, -15 ), 0, 0 );
00281                 layout->addItem( new QSpacerItem( 0, -15 ), 2, 0 );
00282             }
00283             else
00284             {
00285                 QGridLayout* layout = qobject_cast<QGridLayout*>(tabWidget->widget(newScoreTabIndex)->layout());
00286                 layout->addWidget(commentLabel, 1, 0, 1, nrCols);
00287                 commentLabel->setMinimumSize(commentLabel->sizeHint());
00288                 commentLabel->show();
00289                 layout->addItem( new QSpacerItem( 0, -10 ), 0, 0 );
00290                 layout->addItem( new QSpacerItem( 0, 10 ), 2, 0 );
00291             }
00292             comment.clear();
00293         }
00294         
00295         QFont normal = q->font();
00296         QFont bold = normal;
00297         bold.setBold(true);
00298         
00299         QString num;
00300         for (int i = 1; i <= 10; ++i)
00301         {
00302             QLabel *label;
00303             num.setNum(i);
00304             
00305             //kDebug() << "groupName:" << groupName << "id:" << i-1;
00306             
00307             FieldInfo score = scores[groupName].at(i-1);
00308             label = labels[groupName].at((i-1)*nrCols + 0); //crash! FIXME
00309             if ( (i == latest.second) && (groupName == latest.first) )
00310                 label->setFont(bold);
00311             else
00312                 label->setFont(normal);
00313     
00314             if (fields & Name)
00315             {
00316                 if ( (newName.second == i) && (groupName == newName.first) )
00317                 {
00318                     QStackedWidget *localStack = stack[groupName].at(i-1);
00319                     edit = new QLineEdit(player, localStack);
00320                     edit->setMinimumWidth(40);
00321                     localStack->addWidget(edit);
00322                     localStack->setCurrentWidget(edit);
00323                     edit->setFocus();
00324                     connect(edit, SIGNAL(returnPressed()), q, SLOT(slotGotReturn()));
00325                 }
00326                 else
00327                 {
00328                     label = labels[groupName].at((i-1)*nrCols + col[Name]);
00329                     if ( (i == latest.second) && (groupName == latest.first) )
00330                         label->setFont(bold);
00331                     else
00332                         label->setFont(normal);
00333                     label->setText(score[Name]);
00334                 }
00335         
00336             }
00337             for(int field = Name * 2; field < fields; field = field * 2)
00338             {
00339                 if ( (fields & field) && !(hiddenFields & field ) )
00340                 {
00341                     label = labels[groupName].at((i-1)*nrCols + col[field]);
00342                     if ( (i == latest.second) && (groupName == latest.first) )
00343                         label->setFont(bold);
00344                     else
00345                         label->setFont(normal);
00346                     label->setText(score[field]);
00347                 }
00348             }
00349         }
00350         tabIndex++;
00351     }
00352     latest = QPair<QString,int>(QString(),-1);
00353     q->setFixedSize(q->minimumSizeHint()); //NOTE Remove this line to make dialog resizable
00354     tabWidget->setCurrentIndex(newScoreTabIndex);
00355 }
00356 
00357 void KScoreDialog::KScoreDialogPrivate::loadScores()
00358 {
00359     scores.clear();
00360     
00361     QStringList groupList = highscoreObject->groupList(); //List of the group names
00362     numberOfPages = groupList.size();
00363     
00364     QString tempCurrentGroup = configGroup; //temp to store the user-set group name
00365     
00366     if (groupList.count(configGroup) == 0) //If the current group doesn't have any entries, add it to the list to process
00367     {
00368         kDebug(11002) << "The current high score group \"" << configGroup << "\" isn't in the list, adding it";
00369         groupList << configGroup;
00370         setupGroup(configGroup);
00371     }
00372     
00373     foreach(QString groupName, groupList)
00374     {
00375         highscoreObject->setHighscoreGroup(groupName);
00376         player = highscoreObject->readEntry(0, "LastPlayer");  //FIXME
00377         
00378         for (int i = 1; i <= 10; ++i)
00379         {
00380             FieldInfo score;
00381             for(int field = 1; field < fields; field = field * 2)
00382             {
00383                 if (fields & field)
00384                 {
00385                     score[field] = highscoreObject->readEntry(i, key[field], QString("-"));
00386                 }
00387             }
00388             scores[groupName].append(score);
00389         }
00390     }
00391     highscoreObject->setHighscoreGroup(tempCurrentGroup); //reset to the user-set group name
00392     foreach(QString groupName, scores.keys())
00393     {
00394         if( (scores[groupName][0].value(Score)=="-") && (scores.size() > 1) && (latest.first != groupName) )
00395         {
00396             kDebug(11002) << "Removing group \"" << groupName << "\" since it's unused.";
00397             scores.remove(groupName);
00398         }
00399     }
00400     loaded = true;
00401 }
00402 
00403 void KScoreDialog::KScoreDialogPrivate::saveScores()
00404 {
00405     highscoreObject->setHighscoreGroup(configGroup.toUtf8());
00406     
00407     highscoreObject->writeEntry(0,"LastPlayer", player);
00408     
00409     for (int i = 1; i <= 10; ++i)
00410     {
00411         FieldInfo score = scores[configGroup].at(i-1);
00412         for(int field = 1; field < fields; field = field * 2)
00413         {
00414             if (fields & field)
00415             {
00416                 highscoreObject->writeEntry(i, key[field], score[field]);
00417             }
00418         }
00419     }
00420     highscoreObject->writeAndUnlock();
00421 }
00422 
00423 int KScoreDialog::addScore(const FieldInfo& newInfo, const AddScoreFlags& flags)
00424 {
00425     bool askName=false, lessIsMore=false;
00426     if(flags.testFlag(KScoreDialog::AskName))
00427         askName = true;
00428     if(flags.testFlag(KScoreDialog::LessIsMore))
00429         lessIsMore = true;
00430     
00431     d->latest.first = d->configGroup; //Temporarily set this so loadScores() knows not to delete this group
00432     if (!d->loaded)
00433         d->loadScores();
00434     d->latest.first = "Null"; //and reset it.
00435     
00436     for(int i=0; i<d->scores[d->configGroup].size(); i++)
00437     {
00438         FieldInfo score = d->scores[d->configGroup].at(i); //First look at the score in the config file
00439         bool ok;
00440         int num_score = score[Score].toLong(&ok); //test if the stored score is a number
00441         if (lessIsMore && !ok)
00442             num_score = 1 << 30; //this is a very large number so the score won't be on the table
00443         
00444         score = FieldInfo(newInfo); //now look at the submitted score
00445         int newScore = score[Score].toInt();
00446         if (((newScore > num_score) && !lessIsMore) ||
00447               ((newScore < num_score) && lessIsMore))
00448         {
00449             
00450             d->latest = QPair<QString,int>(d->configGroup,i+1);
00451             d->scores[d->configGroup].insert(i, score);
00452             d->scores[d->configGroup].removeAt(10);
00453             
00454             if(score[Name].isEmpty()) //If we don't have a name, prompt the player.
00455                 askName = true;
00456             
00457             if (askName)
00458             {
00459                 d->player=score[Name];
00460                 d->newName = QPair<QString,int>(d->configGroup,i+1);
00461             }
00462             else
00463                 d->saveScores();
00464             
00465             if (i == 0)
00466                 d->comment = i18n("Excellent!\nYou have a new high score!");
00467             else
00468                 d->comment = i18n("Well done!\nYou made it to the high score list!");
00469             return i+1;
00470         }
00471     }
00472     return 0;
00473 }
00474 
00475 int KScoreDialog::addScore(int newScore, const AddScoreFlags& flags)
00476 {
00477     FieldInfo scoreInfo;
00478     scoreInfo[Score]=QString::number(newScore);
00479     return addScore(scoreInfo, AskName | flags);
00480 }
00481 
00482 void KScoreDialog::show()
00483 {
00484     d->aboutToShow();
00485     KDialog::show();
00486 }
00487 
00488 void KScoreDialog::exec()
00489 {
00490     d->aboutToShow();
00491     KDialog::exec();
00492 }
00493 
00494 void KScoreDialog::slotGotReturn()
00495 {
00496     QTimer::singleShot(0, this, SLOT(slotGotName()));
00497 }
00498 
00499 void KScoreDialog::slotGotName()
00500 {
00501     if (d->newName.second == -1) return;
00502 
00503     d->player = d->edit->text();
00504     
00505     d->scores[d->newName.first][d->newName.second-1][Name] = d->player;
00506     d->saveScores();
00507     
00508     QFont bold = font();
00509     bold.setBold(true);
00510     
00511     QLabel *label = d->labels[d->newName.first].at((d->newName.second-1)*d->nrCols + d->col[Name]);
00512     label->setFont(bold);
00513     label->setText(d->player);
00514     d->stack[d->newName.first].at((d->newName.second-1))->setCurrentWidget(label);
00515     delete d->edit;
00516     d->edit = 0;
00517     d->newName = QPair<QString,int>(QString(),-1);
00518 }
00519 
00520 int KScoreDialog::highScore()
00521 {
00522     if (!d->loaded)
00523         d->loadScores();
00524    
00525     if (!d->scores[d->configGroup].isEmpty())
00526         return d->scores[d->configGroup].first()[Score].toInt();
00527     else
00528         return 0;
00529 }
00530 
00531 void KScoreDialog::keyPressEvent(QKeyEvent *ev)
00532 {
00533     if ((d->newName.second != -1) && (ev->key() == Qt::Key_Return))
00534     {
00535         ev->ignore();
00536         return;
00537     }
00538     KDialog::keyPressEvent(ev);
00539 }
00540 
00541 #include "kscoredialog.moc"

libkdegames/highscore

Skip menu "libkdegames/highscore"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • kblackbox
  • kgoldrunner
  • kmahjongg
  • ksquares
  • libkdegames
  •   highscore
  •   kgame
  •   kggzgames
  •   kggzmod
  •   kggznet
  • libkmahjongg
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal