00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00139 _scoresList = new HighscoresList(_tw);
00140 _scoresList->addHeader(s);
00141 _tw->addTab(_scoresList, i18n("Best &Scores"));
00142
00143
00144 _playersList = new HighscoresList(_tw);
00145 _playersList->addHeader(p);
00146 _tw->addTab(_playersList, i18n("&Players"));
00147
00148
00149 if ( internal->showStatistics ) {
00150 _statsTab = new StatisticsTab(_tw);
00151 _tw->addTab(_statsTab, i18n("Statistics"));
00152 }
00153
00154
00155 if ( p.histogram().size()!=0 ) {
00156 _histoTab = new HistogramTab(_tw);
00157 _tw->addTab(_histoTab, i18n("Histogram"));
00158 }
00159
00160
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;
00287 for (uint i=0; i<si.size()-2; i++) {
00288 if ( i==3 ) k = 5;
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;
00325 for (uint i=0; i<4; i++) {
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
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();
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
00495
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();
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 }