libkdegames Library API Documentation

kexthighscore_gui.cpp

00001 /*
00002     This file is part of the KDE games library
00003     Copyright (C) 2001-2003 Nicolas Hadacek (hadacek@kde.org)
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License version 2 as published by the Free Software Foundation.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Library General Public License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to
00016     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017     Boston, MA 02111-1307, USA.
00018 */
00019 
00020 #include "kexthighscore_gui.h"
00021 #include "kexthighscore_gui.moc"
00022 
00023 #include <qlayout.h>
00024 #include <qtextstream.h>
00025 #include <qheader.h>
00026 #include <qgrid.h>
00027 #include <qvgroupbox.h>
00028 
00029 #include <kapplication.h>
00030 #include <kmessagebox.h>
00031 #include <kurllabel.h>
00032 #include <kopenwith.h>
00033 #include <krun.h>
00034 #include <kfiledialog.h>
00035 #include <ktempfile.h>
00036 #include <kio/netaccess.h>
00037 #include <kiconloader.h>
00038 
00039 #include "kexthighscore_internal.h"
00040 #include "kexthighscore.h"
00041 #include "kexthighscore_tab.h"
00042 
00043 
00044 namespace KExtHighscore
00045 {
00046 
00047 //-----------------------------------------------------------------------------
00048 ShowItem::ShowItem(QListView *list, bool highlight)
00049     : KListViewItem(list), _highlight(highlight)
00050 {}
00051 
00052 void ShowItem::paintCell(QPainter *p, const QColorGroup &cg,
00053                          int column, int width, int align)
00054 {
00055     QColorGroup cgrp(cg);
00056     if (_highlight) cgrp.setColor(QColorGroup::Text, red);
00057     KListViewItem::paintCell(p, cgrp, column, width, align);
00058 }
00059 
00060 //-----------------------------------------------------------------------------
00061 ScoresList::ScoresList(QWidget *parent)
00062     : KListView(parent)
00063 {
00064     setSelectionMode(QListView::NoSelection);
00065     setItemMargin(3);
00066     setAllColumnsShowFocus(true);
00067     setSorting(-1);
00068     header()->setClickEnabled(false);
00069     header()->setMovingEnabled(false);
00070 }
00071 
00072 void ScoresList::addHeader(const ItemArray &items)
00073 {
00074     addLineItem(items, 0, 0);
00075 }
00076 
00077 QListViewItem *ScoresList::addLine(const ItemArray &items,
00078                                    uint index, bool highlight)
00079 {
00080     QListViewItem *item = new ShowItem(this, highlight);
00081     addLineItem(items, index, item);
00082     return item;
00083 }
00084 
00085 void ScoresList::addLineItem(const ItemArray &items,
00086                              uint index, QListViewItem *line)
00087 {
00088     uint k = 0;
00089     for (uint i=0; i<items.size(); i++) {
00090         const ItemContainer &container = *items[i];
00091         if ( !container.item()->isVisible() ) continue;
00092         if (line) line->setText(k, itemText(container, index));
00093         else {
00094             addColumn( container.item()->label() );
00095             setColumnAlignment(k, container.item()->alignment());
00096         }
00097         k++;
00098     }
00099 }
00100 
00101 //-----------------------------------------------------------------------------
00102 HighscoresList::HighscoresList(QWidget *parent)
00103     : ScoresList(parent)
00104 {}
00105 
00106 QString HighscoresList::itemText(const ItemContainer &item, uint row) const
00107 {
00108     return item.pretty(row);
00109 }
00110 
00111 void HighscoresList::load(const ItemArray &items, int highlight)
00112 {
00113     clear();
00114     QListViewItem *line = 0;
00115     for (int j=items.nbEntries()-1; j>=0; j--) {
00116         QListViewItem *item = addLine(items, j, j==highlight);
00117         if ( j==highlight ) line = item;
00118     }
00119     if (line) ensureItemVisible(line);
00120 }
00121 
00122 //-----------------------------------------------------------------------------
00123 HighscoresWidget::HighscoresWidget(QWidget *parent)
00124     : QWidget(parent, "show_highscores_widget"),
00125       _scoresUrl(0), _playersUrl(0), _statsTab(0), _histoTab(0)
00126 {
00127     const ScoreInfos &s = internal->scoreInfos();
00128     const PlayerInfos &p = internal->playerInfos();
00129 
00130     QVBoxLayout *vbox = new QVBoxLayout(this, KDialogBase::spacingHint());
00131 
00132     _tw = new QTabWidget(this);
00133     connect(_tw, SIGNAL(currentChanged(QWidget *)), SLOT(tabChanged()));
00134     vbox->addWidget(_tw);
00135 
00136     // scores tab
00137     _scoresList = new HighscoresList(_tw);
00138     _scoresList->addHeader(s);
00139     _tw->addTab(_scoresList, i18n("Best &Scores"));
00140 
00141     // players tab
00142     _playersList = new HighscoresList(_tw);
00143     _playersList->addHeader(p);
00144     _tw->addTab(_playersList, i18n("&Players"));
00145 
00146     // statistics tab
00147     if ( internal->showStatistics ) {
00148         _statsTab = new StatisticsTab(_tw);
00149         _tw->addTab(_statsTab, i18n("Statistics"));
00150     }
00151 
00152     // histogram tab
00153     if ( p.histogram().size()!=0 ) {
00154         _histoTab = new HistogramTab(_tw);
00155         _tw->addTab(_histoTab, i18n("Histogram"));
00156     }
00157 
00158     // url labels
00159     if ( internal->isWWHSAvailable() ) {
00160         KURL url = internal->queryURL(ManagerPrivate::Scores);
00161         _scoresUrl = new KURLLabel(url.url(),
00162                                    i18n("View world-wide highscores"), this);
00163         connect(_scoresUrl, SIGNAL(leftClickedURL(const QString &)),
00164                 SLOT(showURL(const QString &)));
00165         vbox->addWidget(_scoresUrl);
00166 
00167         url = internal->queryURL(ManagerPrivate::Players);
00168         _playersUrl = new KURLLabel(url.url(),
00169                                     i18n("View world-wide players"), this);
00170         connect(_playersUrl, SIGNAL(leftClickedURL(const QString &)),
00171                 SLOT(showURL(const QString &)));
00172         vbox->addWidget(_playersUrl);
00173     }
00174 }
00175 
00176 void HighscoresWidget::changeTab(int i)
00177 {
00178     if ( i!=_tw->currentPageIndex() )
00179         _tw->setCurrentPage(i);
00180 }
00181 
00182 void HighscoresWidget::showURL(const QString &url) const
00183 {
00184     KFileOpenWithHandler foo;
00185     (void)new KRun(KURL(url));
00186 }
00187 
00188 void HighscoresWidget::load(int rank)
00189 {
00190     _scoresList->load(internal->scoreInfos(), rank);
00191     _playersList->load(internal->playerInfos(), internal->playerInfos().id());
00192     if (_scoresUrl)
00193         _scoresUrl->setURL(internal->queryURL(ManagerPrivate::Scores).url());
00194     if (_playersUrl)
00195         _playersUrl->setURL(internal->queryURL(ManagerPrivate::Players).url());
00196     if (_statsTab) _statsTab->load();
00197     if (_histoTab) _histoTab->load();
00198 }
00199 
00200 //-----------------------------------------------------------------------------
00201 HighscoresDialog::HighscoresDialog(int rank, QWidget *parent)
00202     : KDialogBase(internal->nbGameTypes()>1 ? TreeList : Plain,
00203                   i18n("Highscores"), Close|User1|User2, Close,
00204                   parent, "show_highscores", true, true,
00205                   KGuiItem(i18n("Configure..."), "configure"),
00206                   KGuiItem(i18n("Export..."))), _rank(rank), _tab(0)
00207 {
00208     _widgets.resize(internal->nbGameTypes(), 0);
00209 
00210     if ( internal->nbGameTypes()>1 ) {
00211         for (uint i=0; i<internal->nbGameTypes(); i++) {
00212             QString title = internal->manager.gameTypeLabel(i, Manager::I18N);
00213             QString icon = internal->manager.gameTypeLabel(i, Manager::Icon);
00214             QWidget *w = addVBoxPage(title, QString::null,
00215                                      BarIcon(icon, KIcon::SizeLarge));
00216             if ( i==internal->gameType() ) createPage(w);
00217         }
00218 
00219         connect(this, SIGNAL(aboutToShowPage(QWidget *)),
00220                 SLOT(createPage(QWidget *)));
00221         showPage(internal->gameType());
00222     } else {
00223         QVBoxLayout *vbox = new QVBoxLayout(plainPage());
00224         createPage(plainPage());
00225         vbox->addWidget(_widgets[0]);
00226         setMainWidget(_widgets[0]);
00227     }
00228 }
00229 
00230 void HighscoresDialog::createPage(QWidget *page)
00231 {
00232     internal->hsConfig().readCurrentConfig();
00233     _current = page;
00234     bool several = ( internal->nbGameTypes()>1 );
00235     int i = (several ? pageIndex(page) : 0);
00236     if ( _widgets[i]==0 ) {
00237         _widgets[i] = new HighscoresWidget(page);
00238         connect(_widgets[i], SIGNAL(tabChanged(int)), SLOT(tabChanged(int)));
00239     }
00240     uint type = internal->gameType();
00241     if (several) internal->setGameType(i);
00242     _widgets[i]->load(uint(i)==type ? _rank : -1);
00243     if (several) setGameType(type);
00244     _widgets[i]->changeTab(_tab);
00245 }
00246 
00247 void HighscoresDialog::slotUser1()
00248 {
00249     if ( KExtHighscore::configure(this) )
00250         createPage(_current);
00251 }
00252 
00253 void HighscoresDialog::slotUser2()
00254 {
00255     KURL url = KFileDialog::getSaveURL(QString::null, QString::null, this);
00256     if ( url.isEmpty() ) return;
00257     if ( KIO::NetAccess::exists(url) ) {
00258         KGuiItem gi = KStdGuiItem::save();
00259         gi.setText(i18n("Overwrite"));
00260         int res = KMessageBox::warningYesNo(this,
00261                                  i18n("The file already exists. Overwrite?"),
00262                                  i18n("Export"), gi, KStdGuiItem::cancel());
00263         if ( res==KMessageBox::No ) return;
00264     }
00265     KTempFile tmp;
00266     internal->exportHighscores(*tmp.textStream());
00267     tmp.close();
00268     KIO::NetAccess::upload(tmp.name(), url);
00269     tmp.unlink();
00270 }
00271 
00272 //-----------------------------------------------------------------------------
00273 LastMultipleScoresList::LastMultipleScoresList(
00274                             const QValueVector<Score> &scores, QWidget *parent)
00275     : ScoresList(parent), _scores(scores)
00276 {
00277     const ScoreInfos &s = internal->scoreInfos();
00278     addHeader(s);
00279     for (uint i=0; i<scores.size(); i++) addLine(s, i, false);
00280 }
00281 
00282 void LastMultipleScoresList::addLineItem(const ItemArray &si,
00283                                          uint index, QListViewItem *line)
00284 {
00285     uint k = 1; // skip "id"
00286     for (uint i=0; i<si.size()-2; i++) {
00287         if ( i==3 ) k = 5; // skip "date"
00288         const ItemContainer *container = si[k];
00289         k++;
00290         if (line) line->setText(i, itemText(*container, index));
00291         else {
00292             addColumn(  container->item()->label() );
00293             setColumnAlignment(i, container->item()->alignment());
00294         }
00295     }
00296 }
00297 
00298 QString LastMultipleScoresList::itemText(const ItemContainer &item,
00299                                          uint row) const
00300 {
00301     QString name = item.name();
00302     if ( name=="rank" )
00303         return (_scores[row].type()==Won ? i18n("Winner") : QString::null);
00304     QVariant v = _scores[row].data(name);
00305     if ( name=="name" ) return v.toString();
00306     return item.item()->pretty(row, v);
00307 }
00308 
00309 //-----------------------------------------------------------------------------
00310 TotalMultipleScoresList::TotalMultipleScoresList(
00311                             const QValueVector<Score> &scores, QWidget *parent)
00312     : ScoresList(parent), _scores(scores)
00313 {
00314     const ScoreInfos &s = internal->scoreInfos();
00315     addHeader(s);
00316     for (uint i=0; i<scores.size(); i++) addLine(s, i, false);
00317 }
00318 
00319 void TotalMultipleScoresList::addLineItem(const ItemArray &si,
00320                                           uint index, QListViewItem *line)
00321 {
00322     const PlayerInfos &pi = internal->playerInfos();
00323     uint k = 1; // skip "id"
00324     for (uint i=0; i<4; i++) { // skip additional fields
00325         const ItemContainer *container;
00326         if ( i==2 ) container = pi.item("nb games");
00327         else if ( i==3 ) container = pi.item("mean score");
00328         else {
00329             container = si[k];
00330             k++;
00331         }
00332         if (line) line->setText(i, itemText(*container, index));
00333         else {
00334             QString label =
00335                 (i==2 ? i18n("Won Games") : container->item()->label());
00336             addColumn(label);
00337             setColumnAlignment(i, container->item()->alignment());
00338         }
00339     }
00340 }
00341 
00342 QString TotalMultipleScoresList::itemText(const ItemContainer &item,
00343                                           uint row) const
00344 {
00345     QString name = item.name();
00346     if ( name=="rank" ) return QString::number(_scores.size()-row);
00347     if ( name=="nb games" )
00348         return QString::number( _scores[row].data("nb won games").toUInt() );
00349     QVariant v = _scores[row].data(name);
00350     if ( name=="name" ) return v.toString();
00351     return item.item()->pretty(row, v);
00352 }
00353 
00354 
00355 //-----------------------------------------------------------------------------
00356 ConfigDialog::ConfigDialog(QWidget *parent)
00357     : KDialogBase(Swallow, i18n("Configure Highscores"),
00358                   Ok|Apply|Cancel, Cancel,
00359                   parent, "configure_highscores", true, true),
00360       _saved(false), _WWHEnabled(0)
00361 {
00362     QWidget *page = 0;
00363     QTabWidget *tab = 0;
00364     if ( internal->isWWHSAvailable() ) {
00365         tab = new QTabWidget(this);
00366         setMainWidget(tab);
00367         page = new QWidget(tab);
00368         tab->addTab(page, i18n("Main"));
00369     } else {
00370         page = new QWidget(this);
00371         setMainWidget(page);
00372     }
00373 
00374     QGridLayout *pageTop =
00375         new QGridLayout(page, 2, 2, spacingHint(), spacingHint());
00376 
00377     QLabel *label = new QLabel(i18n("Nickname:"), page);
00378     pageTop->addWidget(label, 0, 0);
00379     _nickname = new QLineEdit(page);
00380     connect(_nickname, SIGNAL(textChanged(const QString &)),
00381             SLOT(modifiedSlot()));
00382     connect(_nickname, SIGNAL(textChanged(const QString &)),
00383             SLOT(nickNameChanged(const QString &)));
00384 
00385     _nickname->setMaxLength(16);
00386     pageTop->addWidget(_nickname, 0, 1);
00387 
00388     label = new QLabel(i18n("Comment:"), page);
00389     pageTop->addWidget(label, 1, 0);
00390     _comment = new QLineEdit(page);
00391     connect(_comment, SIGNAL(textChanged(const QString &)),
00392             SLOT(modifiedSlot()));
00393     _comment->setMaxLength(50);
00394     pageTop->addWidget(_comment, 1, 1);
00395 
00396     if (tab) {
00397         _WWHEnabled
00398             = new QCheckBox(i18n("World-wide highscores enabled"), page);
00399         connect(_WWHEnabled, SIGNAL(toggled(bool)),
00400                 SLOT(modifiedSlot()));
00401         pageTop->addMultiCellWidget(_WWHEnabled, 2, 2, 0, 1);
00402 
00403         // advanced tab
00404         QWidget *page = new QWidget(tab);
00405         tab->addTab(page, i18n("Advanced"));
00406         QVBoxLayout *pageTop =
00407             new QVBoxLayout(page, spacingHint(), spacingHint());
00408 
00409         QVGroupBox *group = new QVGroupBox(i18n("Registration Data"), page);
00410         pageTop->addWidget(group);
00411         QGrid *grid = new QGrid(2, group);
00412         grid->setSpacing(spacingHint());
00413 
00414         label = new QLabel(i18n("Nickname:"), grid);
00415         _registeredName = new KLineEdit(grid);
00416         _registeredName->setReadOnly(true);
00417 
00418         label = new QLabel(i18n("Key:"), grid);
00419         _key = new KLineEdit(grid);
00420         _key->setReadOnly(true);
00421 
00422         KGuiItem gi = KStdGuiItem::clear();
00423         gi.setText(i18n("Remove"));
00424         _removeButton = new KPushButton(gi, grid);
00425         connect(_removeButton, SIGNAL(clicked()), SLOT(removeSlot()));
00426     }
00427 
00428     load();
00429     enableButtonOK( !_nickname->text().isEmpty() );
00430     enableButtonApply(false);
00431 }
00432 
00433 void ConfigDialog::nickNameChanged(const QString &text)
00434 {
00435     enableButtonOK( !text.isEmpty() );
00436 }
00437 
00438 
00439 void ConfigDialog::modifiedSlot()
00440 {
00441     enableButtonApply(true && !_nickname->text().isEmpty() );
00442 }
00443 
00444 void ConfigDialog::accept()
00445 {
00446     if ( save() ) {
00447         KDialogBase::accept();
00448         kapp->config()->sync(); // safer
00449     }
00450 }
00451 
00452 void ConfigDialog::removeSlot()
00453 {
00454     KGuiItem gi = KStdGuiItem::clear();
00455     gi.setText(i18n("Remove"));
00456     int res = KMessageBox::warningYesNo(this,
00457                                i18n("This will permanently remove your "
00458                                "registration key. You will not be able to use "
00459                                "the currently registered nickname anymore."),
00460                                QString::null, gi, KStdGuiItem::cancel());
00461     if ( res==KMessageBox::Yes ) {
00462         internal->playerInfos().removeKey();
00463         _registeredName->clear();
00464         _key->clear();
00465         _removeButton->setEnabled(false);
00466         _WWHEnabled->setChecked(false);
00467         modifiedSlot();
00468     }
00469 }
00470 
00471 void ConfigDialog::load()
00472 {
00473     internal->hsConfig().readCurrentConfig();
00474     const PlayerInfos &infos = internal->playerInfos();
00475     _nickname->setText(infos.isAnonymous() ? QString::null : infos.name());
00476     _comment->setText(infos.comment());
00477     if (_WWHEnabled) {
00478         _WWHEnabled->setChecked(infos.isWWEnabled());
00479         if ( !infos.key().isEmpty() ) {
00480             _registeredName->setText(infos.registeredName());
00481             _registeredName->home(false);
00482             _key->setText(infos.key());
00483             _key->home(false);
00484         }
00485         _removeButton->setEnabled(!infos.key().isEmpty());
00486     }
00487 }
00488 
00489 bool ConfigDialog::save()
00490 {
00491     bool enabled = (_WWHEnabled ? _WWHEnabled->isChecked() : false);
00492 
00493     // do not bother the user with "nickname empty" if he has not
00494     // messed with nickname settings ...
00495     QString newName = _nickname->text().lower();
00496     if ( newName.isEmpty() && !internal->playerInfos().isAnonymous()
00497          && !enabled ) return true;
00498 
00499     if ( newName.isEmpty() ) {
00500         KMessageBox::sorry(this, i18n("Please choose a non empty nickname."));
00501         return false;
00502     }
00503     if ( internal->playerInfos().isNameUsed(newName) ) {
00504         KMessageBox::sorry(this, i18n("Nickname already in use. Please "
00505                                       "choose another one"));
00506         return false;
00507     }
00508 
00509     int res =
00510         internal->modifySettings(newName, _comment->text(), enabled, this);
00511     if (res) {
00512         load(); // needed to update view when "apply" is clicked
00513         enableButtonApply(false);
00514     }
00515     _saved = true;
00516     return res;
00517 }
00518 
00519 //-----------------------------------------------------------------------------
00520 AskNameDialog::AskNameDialog(QWidget *parent)
00521     : KDialogBase(Plain, i18n("Enter Your Nickname"), Ok | Cancel, Cancel,
00522                   parent, "ask_name_dialog")
00523 {
00524     internal->hsConfig().readCurrentConfig();
00525 
00526     QVBoxLayout *top =
00527         new QVBoxLayout(plainPage(), marginHint(), spacingHint());
00528     QLabel *label =
00529         new QLabel(i18n("Congratulations, you have won!"), plainPage());
00530     top->addWidget(label);
00531 
00532     QHBoxLayout *hbox = new QHBoxLayout(top);
00533     label = new QLabel(i18n("Enter your nickname:"), plainPage());
00534     hbox->addWidget(label);
00535     _edit = new QLineEdit(plainPage());
00536     _edit->setFocus();
00537     connect(_edit, SIGNAL(textChanged(const QString &)), SLOT(nameChanged()));
00538     hbox->addWidget(_edit);
00539 
00540     top->addSpacing(spacingHint());
00541     _checkbox = new QCheckBox(i18n("Do not ask again."),  plainPage());
00542     top->addWidget(_checkbox);
00543 
00544     nameChanged();
00545 }
00546 
00547 void AskNameDialog::nameChanged()
00548 {
00549     enableButtonOK( !name().isEmpty()
00550                     && !internal->playerInfos().isNameUsed(name()) );
00551 }
00552 
00553 } // namespace
KDE Logo
This file is part of the documentation for libkdegames Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 10:06:36 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003