00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00137 _scoresList = new HighscoresList(_tw);
00138 _scoresList->addHeader(s);
00139 _tw->addTab(_scoresList, i18n("Best &Scores"));
00140
00141
00142 _playersList = new HighscoresList(_tw);
00143 _playersList->addHeader(p);
00144 _tw->addTab(_playersList, i18n("&Players"));
00145
00146
00147 if ( internal->showStatistics ) {
00148 _statsTab = new StatisticsTab(_tw);
00149 _tw->addTab(_statsTab, i18n("Statistics"));
00150 }
00151
00152
00153 if ( p.histogram().size()!=0 ) {
00154 _histoTab = new HistogramTab(_tw);
00155 _tw->addTab(_histoTab, i18n("Histogram"));
00156 }
00157
00158
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 (void)new KRun(KURL(url));
00185 }
00186
00187 void HighscoresWidget::load(int rank)
00188 {
00189 _scoresList->load(internal->scoreInfos(), rank);
00190 _playersList->load(internal->playerInfos(), internal->playerInfos().id());
00191 if (_scoresUrl)
00192 _scoresUrl->setURL(internal->queryURL(ManagerPrivate::Scores).url());
00193 if (_playersUrl)
00194 _playersUrl->setURL(internal->queryURL(ManagerPrivate::Players).url());
00195 if (_statsTab) _statsTab->load();
00196 if (_histoTab) _histoTab->load();
00197 }
00198
00199
00200 HighscoresDialog::HighscoresDialog(int rank, QWidget *parent)
00201 : KDialogBase(internal->nbGameTypes()>1 ? TreeList : Plain,
00202 i18n("Highscores"), Close|User1|User2, Close,
00203 parent, "show_highscores", true, true,
00204 KGuiItem(i18n("Configure..."), "configure"),
00205 KGuiItem(i18n("Export..."))), _rank(rank), _tab(0)
00206 {
00207 _widgets.resize(internal->nbGameTypes(), 0);
00208
00209 if ( internal->nbGameTypes()>1 ) {
00210 for (uint i=0; i<internal->nbGameTypes(); i++) {
00211 QString title = internal->manager.gameTypeLabel(i, Manager::I18N);
00212 QString icon = internal->manager.gameTypeLabel(i, Manager::Icon);
00213 QWidget *w = addVBoxPage(title, QString::null,
00214 BarIcon(icon, KIcon::SizeLarge));
00215 if ( i==internal->gameType() ) createPage(w);
00216 }
00217
00218 connect(this, SIGNAL(aboutToShowPage(QWidget *)),
00219 SLOT(createPage(QWidget *)));
00220 showPage(internal->gameType());
00221 } else {
00222 QVBoxLayout *vbox = new QVBoxLayout(plainPage());
00223 createPage(plainPage());
00224 vbox->addWidget(_widgets[0]);
00225 setMainWidget(_widgets[0]);
00226 }
00227 }
00228
00229 void HighscoresDialog::createPage(QWidget *page)
00230 {
00231 internal->hsConfig().readCurrentConfig();
00232 _current = page;
00233 bool several = ( internal->nbGameTypes()>1 );
00234 int i = (several ? pageIndex(page) : 0);
00235 if ( _widgets[i]==0 ) {
00236 _widgets[i] = new HighscoresWidget(page);
00237 connect(_widgets[i], SIGNAL(tabChanged(int)), SLOT(tabChanged(int)));
00238 }
00239 uint type = internal->gameType();
00240 if (several) internal->setGameType(i);
00241 _widgets[i]->load(uint(i)==type ? _rank : -1);
00242 if (several) setGameType(type);
00243 _widgets[i]->changeTab(_tab);
00244 }
00245
00246 void HighscoresDialog::slotUser1()
00247 {
00248 if ( KExtHighscore::configure(this) )
00249 createPage(_current);
00250 }
00251
00252 void HighscoresDialog::slotUser2()
00253 {
00254 KURL url = KFileDialog::getSaveURL(QString::null, QString::null, this);
00255 if ( url.isEmpty() ) return;
00256 if ( KIO::NetAccess::exists(url, true, this) ) {
00257 KGuiItem gi = KStdGuiItem::save();
00258 gi.setText(i18n("Overwrite"));
00259 int res = KMessageBox::warningContinueCancel(this,
00260 i18n("The file already exists. Overwrite?"),
00261 i18n("Export"), gi);
00262 if ( res==KMessageBox::Cancel ) return;
00263 }
00264 KTempFile tmp;
00265 internal->exportHighscores(*tmp.textStream());
00266 tmp.close();
00267 KIO::NetAccess::upload(tmp.name(), url, this);
00268 tmp.unlink();
00269 }
00270
00271
00272 LastMultipleScoresList::LastMultipleScoresList(
00273 const QValueVector<Score> &scores, QWidget *parent)
00274 : ScoresList(parent), _scores(scores)
00275 {
00276 const ScoreInfos &s = internal->scoreInfos();
00277 addHeader(s);
00278 for (uint i=0; i<scores.size(); i++) addLine(s, i, false);
00279 }
00280
00281 void LastMultipleScoresList::addLineItem(const ItemArray &si,
00282 uint index, QListViewItem *line)
00283 {
00284 uint k = 1;
00285 for (uint i=0; i<si.size()-2; i++) {
00286 if ( i==3 ) k = 5;
00287 const ItemContainer *container = si[k];
00288 k++;
00289 if (line) line->setText(i, itemText(*container, index));
00290 else {
00291 addColumn( container->item()->label() );
00292 setColumnAlignment(i, container->item()->alignment());
00293 }
00294 }
00295 }
00296
00297 QString LastMultipleScoresList::itemText(const ItemContainer &item,
00298 uint row) const
00299 {
00300 QString name = item.name();
00301 if ( name=="rank" )
00302 return (_scores[row].type()==Won ? i18n("Winner") : QString::null);
00303 QVariant v = _scores[row].data(name);
00304 if ( name=="name" ) return v.toString();
00305 return item.item()->pretty(row, v);
00306 }
00307
00308
00309 TotalMultipleScoresList::TotalMultipleScoresList(
00310 const QValueVector<Score> &scores, QWidget *parent)
00311 : ScoresList(parent), _scores(scores)
00312 {
00313 const ScoreInfos &s = internal->scoreInfos();
00314 addHeader(s);
00315 for (uint i=0; i<scores.size(); i++) addLine(s, i, false);
00316 }
00317
00318 void TotalMultipleScoresList::addLineItem(const ItemArray &si,
00319 uint index, QListViewItem *line)
00320 {
00321 const PlayerInfos &pi = internal->playerInfos();
00322 uint k = 1;
00323 for (uint i=0; i<4; i++) {
00324 const ItemContainer *container;
00325 if ( i==2 ) container = pi.item("nb games");
00326 else if ( i==3 ) container = pi.item("mean score");
00327 else {
00328 container = si[k];
00329 k++;
00330 }
00331 if (line) line->setText(i, itemText(*container, index));
00332 else {
00333 QString label =
00334 (i==2 ? i18n("Won Games") : container->item()->label());
00335 addColumn(label);
00336 setColumnAlignment(i, container->item()->alignment());
00337 }
00338 }
00339 }
00340
00341 QString TotalMultipleScoresList::itemText(const ItemContainer &item,
00342 uint row) const
00343 {
00344 QString name = item.name();
00345 if ( name=="rank" ) return QString::number(_scores.size()-row);
00346 if ( name=="nb games" )
00347 return QString::number( _scores[row].data("nb won games").toUInt() );
00348 QVariant v = _scores[row].data(name);
00349 if ( name=="name" ) return v.toString();
00350 return item.item()->pretty(row, v);
00351 }
00352
00353
00354
00355 ConfigDialog::ConfigDialog(QWidget *parent)
00356 : KDialogBase(Swallow, i18n("Configure Highscores"),
00357 Ok|Apply|Cancel, Cancel,
00358 parent, "configure_highscores", true, true),
00359 _saved(false), _WWHEnabled(0)
00360 {
00361 QWidget *page = 0;
00362 QTabWidget *tab = 0;
00363 if ( internal->isWWHSAvailable() ) {
00364 tab = new QTabWidget(this);
00365 setMainWidget(tab);
00366 page = new QWidget(tab);
00367 tab->addTab(page, i18n("Main"));
00368 } else {
00369 page = new QWidget(this);
00370 setMainWidget(page);
00371 }
00372
00373 QGridLayout *pageTop =
00374 new QGridLayout(page, 2, 2, spacingHint(), spacingHint());
00375
00376 QLabel *label = new QLabel(i18n("Nickname:"), page);
00377 pageTop->addWidget(label, 0, 0);
00378 _nickname = new QLineEdit(page);
00379 connect(_nickname, SIGNAL(textChanged(const QString &)),
00380 SLOT(modifiedSlot()));
00381 connect(_nickname, SIGNAL(textChanged(const QString &)),
00382 SLOT(nickNameChanged(const QString &)));
00383
00384 _nickname->setMaxLength(16);
00385 pageTop->addWidget(_nickname, 0, 1);
00386
00387 label = new QLabel(i18n("Comment:"), page);
00388 pageTop->addWidget(label, 1, 0);
00389 _comment = new QLineEdit(page);
00390 connect(_comment, SIGNAL(textChanged(const QString &)),
00391 SLOT(modifiedSlot()));
00392 _comment->setMaxLength(50);
00393 pageTop->addWidget(_comment, 1, 1);
00394
00395 if (tab) {
00396 _WWHEnabled
00397 = new QCheckBox(i18n("World-wide highscores enabled"), page);
00398 connect(_WWHEnabled, SIGNAL(toggled(bool)),
00399 SLOT(modifiedSlot()));
00400 pageTop->addMultiCellWidget(_WWHEnabled, 2, 2, 0, 1);
00401
00402
00403 QWidget *page = new QWidget(tab);
00404 tab->addTab(page, i18n("Advanced"));
00405 QVBoxLayout *pageTop =
00406 new QVBoxLayout(page, spacingHint(), spacingHint());
00407
00408 QVGroupBox *group = new QVGroupBox(i18n("Registration Data"), page);
00409 pageTop->addWidget(group);
00410 QGrid *grid = new QGrid(2, group);
00411 grid->setSpacing(spacingHint());
00412
00413 label = new QLabel(i18n("Nickname:"), grid);
00414 _registeredName = new KLineEdit(grid);
00415 _registeredName->setReadOnly(true);
00416
00417 label = new QLabel(i18n("Key:"), grid);
00418 _key = new KLineEdit(grid);
00419 _key->setReadOnly(true);
00420
00421 KGuiItem gi = KStdGuiItem::clear();
00422 gi.setText(i18n("Remove"));
00423 _removeButton = new KPushButton(gi, grid);
00424 connect(_removeButton, SIGNAL(clicked()), SLOT(removeSlot()));
00425 }
00426
00427 load();
00428 enableButtonOK( !_nickname->text().isEmpty() );
00429 enableButtonApply(false);
00430 }
00431
00432 void ConfigDialog::nickNameChanged(const QString &text)
00433 {
00434 enableButtonOK( !text.isEmpty() );
00435 }
00436
00437
00438 void ConfigDialog::modifiedSlot()
00439 {
00440 enableButtonApply(true && !_nickname->text().isEmpty() );
00441 }
00442
00443 void ConfigDialog::accept()
00444 {
00445 if ( save() ) {
00446 KDialogBase::accept();
00447 kapp->config()->sync();
00448 }
00449 }
00450
00451 void ConfigDialog::removeSlot()
00452 {
00453 KGuiItem gi = KStdGuiItem::clear();
00454 gi.setText(i18n("Remove"));
00455 int res = KMessageBox::warningContinueCancel(this,
00456 i18n("This will permanently remove your "
00457 "registration key. You will not be able to use "
00458 "the currently registered nickname anymore."),
00459 QString::null, gi);
00460 if ( res==KMessageBox::Continue ) {
00461 internal->playerInfos().removeKey();
00462 _registeredName->clear();
00463 _key->clear();
00464 _removeButton->setEnabled(false);
00465 _WWHEnabled->setChecked(false);
00466 modifiedSlot();
00467 }
00468 }
00469
00470 void ConfigDialog::load()
00471 {
00472 internal->hsConfig().readCurrentConfig();
00473 const PlayerInfos &infos = internal->playerInfos();
00474 _nickname->setText(infos.isAnonymous() ? QString::null : infos.name());
00475 _comment->setText(infos.comment());
00476 if (_WWHEnabled) {
00477 _WWHEnabled->setChecked(infos.isWWEnabled());
00478 if ( !infos.key().isEmpty() ) {
00479 _registeredName->setText(infos.registeredName());
00480 _registeredName->home(false);
00481 _key->setText(infos.key());
00482 _key->home(false);
00483 }
00484 _removeButton->setEnabled(!infos.key().isEmpty());
00485 }
00486 }
00487
00488 bool ConfigDialog::save()
00489 {
00490 bool enabled = (_WWHEnabled ? _WWHEnabled->isChecked() : false);
00491
00492
00493
00494 QString newName = _nickname->text();
00495 if ( newName.isEmpty() && !internal->playerInfos().isAnonymous()
00496 && !enabled ) return true;
00497
00498 if ( newName.isEmpty() ) {
00499 KMessageBox::sorry(this, i18n("Please choose a non empty nickname."));
00500 return false;
00501 }
00502 if ( internal->playerInfos().isNameUsed(newName) ) {
00503 KMessageBox::sorry(this, i18n("Nickname already in use. Please "
00504 "choose another one"));
00505 return false;
00506 }
00507
00508 int res =
00509 internal->modifySettings(newName, _comment->text(), enabled, this);
00510 if (res) {
00511 load();
00512 enableButtonApply(false);
00513 }
00514 _saved = true;
00515 return res;
00516 }
00517
00518
00519 AskNameDialog::AskNameDialog(QWidget *parent)
00520 : KDialogBase(Plain, i18n("Enter Your Nickname"), Ok | Cancel, Ok,
00521 parent, "ask_name_dialog")
00522 {
00523 internal->hsConfig().readCurrentConfig();
00524
00525 QVBoxLayout *top =
00526 new QVBoxLayout(plainPage(), marginHint(), spacingHint());
00527 QLabel *label =
00528 new QLabel(i18n("Congratulations, you have won!"), plainPage());
00529 top->addWidget(label);
00530
00531 QHBoxLayout *hbox = new QHBoxLayout(top);
00532 label = new QLabel(i18n("Enter your nickname:"), plainPage());
00533 hbox->addWidget(label);
00534 _edit = new QLineEdit(plainPage());
00535 _edit->setFocus();
00536 connect(_edit, SIGNAL(textChanged(const QString &)), SLOT(nameChanged()));
00537 hbox->addWidget(_edit);
00538
00539 top->addSpacing(spacingHint());
00540 _checkbox = new QCheckBox(i18n("Do not ask again."), plainPage());
00541 top->addWidget(_checkbox);
00542
00543 nameChanged();
00544 }
00545
00546 void AskNameDialog::nameChanged()
00547 {
00548 enableButtonOK( !name().isEmpty()
00549 && !internal->playerInfos().isNameUsed(name()) );
00550 }
00551
00552 }