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 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;
00286
for (uint i=0; i<si.size()-2; i++) {
00287
if ( i==3 ) k = 5;
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;
00324
for (uint i=0; i<4; i++) {
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
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();
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
00494
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();
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, Ok,
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 }