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