00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kexthighscore_internal.h"
00021
00022 #include <pwd.h>
00023 #include <sys/types.h>
00024 #include <unistd.h>
00025
00026 #include <QFile>
00027 #include <QLayout>
00028 #include <qdom.h>
00029
00030 #include <QTextStream>
00031 #include <QVector>
00032 #include <kuser.h>
00033
00034 #include <kglobal.h>
00035 #include <kio/netaccess.h>
00036 #include <kio/job.h>
00037 #include <kmessagebox.h>
00038 #include <kcodecs.h>
00039 #include <kdebug.h>
00040
00041 #include "kexthighscore.h"
00042 #include "kexthighscore_gui.h"
00043 #include "kemailsettings.h"
00044
00045 #include <config-highscore.h>
00046
00047 namespace KExtHighscore
00048 {
00049
00050
00051 const char ItemContainer::ANONYMOUS[] = "_";
00052 const char ItemContainer::ANONYMOUS_LABEL[] = I18N_NOOP("anonymous");
00053
00054 ItemContainer::ItemContainer()
00055 : _item(0)
00056 {}
00057
00058 ItemContainer::~ItemContainer()
00059 {
00060 delete _item;
00061 }
00062
00063 void ItemContainer::setItem(Item *item)
00064 {
00065 delete _item;
00066 _item = item;
00067 }
00068
00069 QString ItemContainer::entryName() const
00070 {
00071 if ( _subGroup.isEmpty() ) return _name;
00072 return _name + '_' + _subGroup;
00073 }
00074
00075 QVariant ItemContainer::read(uint i) const
00076 {
00077 Q_ASSERT(_item);
00078
00079 QVariant v = _item->defaultValue();
00080 if ( isStored() ) {
00081 internal->hsConfig().setHighscoreGroup(_group);
00082 v = internal->hsConfig().readPropertyEntry(i+1, entryName(), v);
00083 }
00084 return _item->read(i, v);
00085 }
00086
00087 QString ItemContainer::pretty(uint i) const
00088 {
00089 Q_ASSERT(_item);
00090 return _item->pretty(i, read(i));
00091 }
00092
00093 void ItemContainer::write(uint i, const QVariant &value) const
00094 {
00095 Q_ASSERT( isStored() );
00096 Q_ASSERT( internal->hsConfig().isLocked() );
00097 internal->hsConfig().setHighscoreGroup(_group);
00098 internal->hsConfig().writeEntry(i+1, entryName(), value);
00099 }
00100
00101 uint ItemContainer::increment(uint i) const
00102 {
00103 uint v = read(i).toUInt() + 1;
00104 write(i, v);
00105 return v;
00106 }
00107
00108
00109 ItemArray::ItemArray()
00110 : _group(""), _subGroup("")
00111 {}
00112
00113 ItemArray::~ItemArray()
00114 {
00115 for (int i=0; i<size(); i++) delete at(i);
00116 }
00117
00118 int ItemArray::findIndex(const QString &name) const
00119 {
00120 for (int i=0; i<size(); i++)
00121 if ( at(i)->name()==name ) return i;
00122 return -1;
00123 }
00124
00125 const ItemContainer *ItemArray::item(const QString &name) const
00126 {
00127 int i = findIndex(name);
00128 if ( i==-1 ) kError(11002) << "no item named \"" << name
00129 << "\"";
00130 return at(i);
00131 }
00132
00133 ItemContainer *ItemArray::item(const QString &name)
00134 {
00135 int i = findIndex(name);
00136 if ( i==-1 ) kError(11002) << "no item named \"" << name
00137 << "\"";
00138 return at(i);
00139 }
00140
00141 void ItemArray::setItem(const QString &name, Item *item)
00142 {
00143 int i = findIndex(name);
00144 if ( i==-1 ) kError(11002) << "no item named \"" << name
00145 << "\"";
00146 bool stored = at(i)->isStored();
00147 bool canHaveSubGroup = at(i)->canHaveSubGroup();
00148 _setItem(i, name, item, stored, canHaveSubGroup);
00149 }
00150
00151 void ItemArray::addItem(const QString &name, Item *item,
00152 bool stored, bool canHaveSubGroup)
00153 {
00154 if ( findIndex(name)!=-1 )
00155 kError(11002) << "item already exists \"" << name << "\"";
00156
00157 append(new ItemContainer);
00158
00159 _setItem(size()-1, name, item, stored, canHaveSubGroup);
00160 }
00161
00162 void ItemArray::_setItem(uint i, const QString &name, Item *item,
00163 bool stored, bool canHaveSubGroup)
00164 {
00165 at(i)->setItem(item);
00166 at(i)->setName(name);
00167 at(i)->setGroup(stored ? _group : QString());
00168 at(i)->setSubGroup(canHaveSubGroup ? _subGroup : QString());
00169 }
00170
00171 void ItemArray::setGroup(const QString &group)
00172 {
00173 Q_ASSERT( !group.isNull() );
00174 _group = group;
00175 for (int i=0; i<size(); i++)
00176 if ( at(i)->isStored() ) at(i)->setGroup(group);
00177 }
00178
00179 void ItemArray::setSubGroup(const QString &subGroup)
00180 {
00181 Q_ASSERT( !subGroup.isNull() );
00182 _subGroup = subGroup;
00183 for (int i=0; i<size(); i++)
00184 if ( at(i)->canHaveSubGroup() ) at(i)->setSubGroup(subGroup);
00185 }
00186
00187 void ItemArray::read(uint k, Score &data) const
00188 {
00189 for (int i=0; i<size(); i++) {
00190 if ( !at(i)->isStored() ) continue;
00191 data.setData(at(i)->name(), at(i)->read(k));
00192 }
00193 }
00194
00195 void ItemArray::write(uint k, const Score &data, uint nb) const
00196 {
00197 for (int i=0; i<size(); i++) {
00198 if ( !at(i)->isStored() ) continue;
00199 for (uint j=nb-1; j>k; j--) at(i)->write(j, at(i)->read(j-1));
00200 at(i)->write(k, data.data(at(i)->name()));
00201 }
00202 }
00203
00204 void ItemArray::exportToText(QTextStream &s) const
00205 {
00206 for (uint k=0; k<nbEntries()+1; k++) {
00207 for (int i=0; i<size(); i++) {
00208 const Item *item = at(i)->item();
00209 if ( item->isVisible() ) {
00210 if ( i!=0 ) s << '\t';
00211 if ( k==0 ) s << item->label();
00212 else s << at(i)->pretty(k-1);
00213 }
00214 }
00215 s << endl;
00216 }
00217 }
00218
00219
00220 class ScoreNameItem : public NameItem
00221 {
00222 public:
00223 ScoreNameItem(const ScoreInfos &score, const PlayerInfos &infos)
00224 : _score(score), _infos(infos) {}
00225
00226 QString pretty(uint i, const QVariant &v) const {
00227 uint id = _score.item("id")->read(i).toUInt();
00228 if ( id==0 ) return NameItem::pretty(i, v);
00229 return _infos.prettyName(id-1);
00230 }
00231
00232 private:
00233 const ScoreInfos &_score;
00234 const PlayerInfos &_infos;
00235 };
00236
00237
00238 ScoreInfos::ScoreInfos(uint maxNbEntries, const PlayerInfos &infos)
00239 : _maxNbEntries(maxNbEntries)
00240 {
00241 addItem("id", new Item((uint)0));
00242 addItem("rank", new RankItem, false);
00243 addItem("name", new ScoreNameItem(*this, infos));
00244 addItem("score", Manager::createItem(Manager::ScoreDefault));
00245 addItem("date", new DateItem);
00246 }
00247
00248 uint ScoreInfos::nbEntries() const
00249 {
00250 uint i = 0;
00251 for (; i<_maxNbEntries; i++)
00252 if ( item("score")->read(i)==item("score")->item()->defaultValue() )
00253 break;
00254 return i;
00255 }
00256
00257
00258 const char *HS_ID = "player id";
00259 const char *HS_REGISTERED_NAME = "registered name";
00260 const char *HS_KEY = "player key";
00261 const char *HS_WW_ENABLED = "ww hs enabled";
00262
00263 PlayerInfos::PlayerInfos()
00264 {
00265 setGroup("players");
00266
00267
00268 addItem("name", new NameItem);
00269 Item *it = new Item((uint)0, i18n("Games Count"),Qt::AlignRight);
00270 addItem("nb games", it, true, true);
00271 it = Manager::createItem(Manager::MeanScoreDefault);
00272 addItem("mean score", it, true, true);
00273 it = Manager::createItem(Manager::BestScoreDefault);
00274 addItem("best score", it, true, true);
00275 addItem("date", new DateItem, true, true);
00276 it = new Item(QString(), i18n("Comment"), Qt::AlignLeft);
00277 addItem("comment", it);
00278
00279
00280 addItem("nb black marks", new Item((uint)0), true, true);
00281 addItem("nb lost games", new Item((uint)0), true, true);
00282 addItem("nb draw games", new Item((uint)0), true, true);
00283 addItem("current trend", new Item((int)0), true, true);
00284 addItem("max lost trend", new Item((uint)0), true, true);
00285 addItem("max won trend", new Item((uint)0), true, true);
00286
00287 QString username = KUser().loginName();
00288
00289 #ifdef HIGHSCORE_DIRECTORY
00290 internal->hsConfig().setHighscoreGroup("players");
00291 for (uint i=0; ;i++) {
00292 if ( !internal->hsConfig().hasEntry(i+1, "username") ) {
00293 _newPlayer = true;
00294 _id = i;
00295 break;
00296 }
00297 if ( internal->hsConfig().readEntry(i+1, "username")==username ) {
00298 _newPlayer = false;
00299 _id = i;
00300 return;
00301 }
00302 }
00303 #endif
00304 internal->hsConfig().lockForWriting();
00305 KEMailSettings emailConfig;
00306 emailConfig.setProfile(emailConfig.defaultProfileName());
00307 QString name = emailConfig.getSetting(KEMailSettings::RealName);
00308 if ( name.isEmpty() || isNameUsed(name) ) name = username;
00309 if ( isNameUsed(name) ) name= QString(ItemContainer::ANONYMOUS);
00310 #ifdef HIGHSCORE_DIRECTORY
00311 internal->hsConfig().writeEntry(_id+1, "username", username);
00312 item("name")->write(_id, name);
00313 #endif
00314
00315 ConfigGroup cg;
00316 _oldLocalPlayer = cg.hasKey(HS_ID);
00317 _oldLocalId = cg.readEntry(HS_ID).toUInt();
00318 #ifdef HIGHSCORE_DIRECTORY
00319 if (_oldLocalPlayer) {
00320
00321 QString prefix = QString("%1_").arg(_oldLocalId+1);
00322 #ifdef __GNUC__
00323 #warning "kde4 port g.config()->entryMap";
00324 #endif
00325 #if 0
00326 QMap<QString, QString> entries =
00327 cg.config()->entryMap("KHighscore_players");
00328 QMap<QString, QString>::const_iterator it;
00329 for (it=entries.begin(); it!=entries.end(); ++it) {
00330 QString key = it.key();
00331 if ( key.find(prefix)==0 ) {
00332 QString name = key.right(key.length()-prefix.length());
00333 if ( name!="name" || !isNameUsed(it.data()) )
00334 internal->hsConfig().writeEntry(_id+1, name, it.data());
00335 }
00336 }
00337 #endif
00338 }
00339 #else
00340 _newPlayer = !_oldLocalPlayer;
00341 if (_oldLocalPlayer) _id = _oldLocalId;
00342 else {
00343 _id = nbEntries();
00344 cg.writeEntry(HS_ID, _id);
00345 item("name")->write(_id, name);
00346 }
00347 #endif
00348 _bound = true;
00349 internal->hsConfig().writeAndUnlock();
00350 }
00351
00352 void PlayerInfos::createHistoItems(const QVector<uint> &scores, bool bound)
00353 {
00354 Q_ASSERT( _histogram.size()==0 );
00355 _bound = bound;
00356 _histogram = scores;
00357 for (int i=1; i<histoSize(); i++)
00358 addItem(histoName(i), new Item((uint)0), true, true);
00359 }
00360
00361 bool PlayerInfos::isAnonymous() const
00362 {
00363 return ( name()==ItemContainer::ANONYMOUS );
00364 }
00365
00366 uint PlayerInfos::nbEntries() const
00367 {
00368 internal->hsConfig().setHighscoreGroup("players");
00369 QStringList list = internal->hsConfig().readList("name", -1);
00370 return list.count();
00371 }
00372
00373 QString PlayerInfos::key() const
00374 {
00375 ConfigGroup cg;
00376 return cg.readEntry(HS_KEY, QString());
00377 }
00378
00379 bool PlayerInfos::isWWEnabled() const
00380 {
00381 ConfigGroup cg;
00382 return cg.readEntry(HS_WW_ENABLED, false);
00383 }
00384
00385 QString PlayerInfos::histoName(int i) const
00386 {
00387 const QVector<uint> &sh = _histogram;
00388 Q_ASSERT( i<sh.size() || (_bound || i==sh.size()) );
00389 if ( i==sh.size() )
00390 return QString("nb scores greater than %1").arg(sh[sh.size()-1]);
00391 return QString("nb scores less than %1").arg(sh[i]);
00392 }
00393
00394 int PlayerInfos::histoSize() const
00395 {
00396 return _histogram.size() + (_bound ? 0 : 1);
00397 }
00398
00399 void PlayerInfos::submitScore(const Score &score) const
00400 {
00401
00402 uint nbGames = item("nb games")->increment(_id);
00403 switch (score.type()) {
00404 case Lost:
00405 item("nb lost games")->increment(_id);
00406 break;
00407 case Won: break;
00408 case Draw:
00409 item("nb draw games")->increment(_id);
00410 break;
00411 };
00412
00413
00414 if ( score.type()==Won ) {
00415 uint nbWonGames = nbGames - item("nb lost games")->read(_id).toUInt()
00416 - item("nb draw games")->read(_id).toUInt()
00417 - item("nb black marks")->read(_id).toUInt();
00418 double mean = (nbWonGames==1 ? 0.0
00419 : item("mean score")->read(_id).toDouble());
00420 mean += (double(score.score()) - mean) / nbWonGames;
00421 item("mean score")->write(_id, mean);
00422 }
00423
00424
00425 Score best = score;
00426 best.setScore( item("best score")->read(_id).toUInt() );
00427 if ( best<score ) {
00428 item("best score")->write(_id, score.score());
00429 item("date")->write(_id, score.data("date").toDateTime());
00430 }
00431
00432
00433 int current = item("current trend")->read(_id).toInt();
00434 switch (score.type()) {
00435 case Won: {
00436 if ( current<0 ) current = 0;
00437 current++;
00438 uint won = item("max won trend")->read(_id).toUInt();
00439 if ( (uint)current>won ) item("max won trend")->write(_id, current);
00440 break;
00441 }
00442 case Lost: {
00443 if ( current>0 ) current = 0;
00444 current--;
00445 uint lost = item("max lost trend")->read(_id).toUInt();
00446 uint clost = -current;
00447 if ( clost>lost ) item("max lost trend")->write(_id, clost);
00448 break;
00449 }
00450 case Draw:
00451 current = 0;
00452 break;
00453 }
00454 item("current trend")->write(_id, current);
00455
00456
00457 if ( score.type()==Won ) {
00458 const QVector<uint> &sh = _histogram;
00459 for (int i=1; i<histoSize(); i++)
00460 if ( i==sh.size() || score.score()<sh[i] ) {
00461 item(histoName(i))->increment(_id);
00462 break;
00463 }
00464 }
00465 }
00466
00467 bool PlayerInfos::isNameUsed(const QString &newName) const
00468 {
00469 if ( newName==name() ) return false;
00470 for (uint i=0; i<nbEntries(); i++)
00471 if ( newName.toLower()==item("name")->read(i).toString().toLower() ) return true;
00472 if ( newName==i18n(ItemContainer::ANONYMOUS_LABEL) ) return true;
00473 return false;
00474 }
00475
00476 void PlayerInfos::modifyName(const QString &newName) const
00477 {
00478 item("name")->write(_id, newName);
00479 }
00480
00481 void PlayerInfos::modifySettings(const QString &newName,
00482 const QString &comment, bool WWEnabled,
00483 const QString &newKey) const
00484 {
00485 modifyName(newName);
00486 item("comment")->write(_id, comment);
00487 ConfigGroup cg;
00488 cg.writeEntry(HS_WW_ENABLED, WWEnabled);
00489 if ( !newKey.isEmpty() ) cg.writeEntry(HS_KEY, newKey);
00490 if (WWEnabled) cg.writeEntry(HS_REGISTERED_NAME, newName);
00491 }
00492
00493 QString PlayerInfos::registeredName() const
00494 {
00495 ConfigGroup cg;
00496 return cg.readEntry(HS_REGISTERED_NAME, QString());
00497 }
00498
00499 void PlayerInfos::removeKey()
00500 {
00501 ConfigGroup cg;
00502
00503
00504 uint i = 0;
00505 QString str = "%1 old #%2";
00506 QString sk;
00507 do {
00508 i++;
00509 sk = str.arg(HS_KEY).arg(i);
00510 } while ( !cg.readEntry(sk, QString()).isEmpty() );
00511 cg.writeEntry(sk, key());
00512 cg.writeEntry(str.arg(HS_REGISTERED_NAME).arg(i),
00513 registeredName());
00514
00515
00516 cg.deleteEntry(HS_KEY);
00517 cg.deleteEntry(HS_REGISTERED_NAME);
00518 cg.writeEntry(HS_WW_ENABLED, false);
00519 }
00520
00521
00522 ManagerPrivate::ManagerPrivate(uint nbGameTypes, Manager &m)
00523 : manager(m), showStatistics(false), showDrawGames(false),
00524 trackLostGames(false), trackDrawGames(false),
00525 showMode(Manager::ShowForHigherScore),
00526 _first(true), _nbGameTypes(nbGameTypes), _gameType(0)
00527 {}
00528
00529 void ManagerPrivate::init(uint maxNbEntries)
00530 {
00531 _hsConfig = new KHighscore(false, 0);
00532 _playerInfos = new PlayerInfos;
00533 _scoreInfos = new ScoreInfos(maxNbEntries, *_playerInfos);
00534 }
00535
00536 ManagerPrivate::~ManagerPrivate()
00537 {
00538 delete _scoreInfos;
00539 delete _playerInfos;
00540 delete _hsConfig;
00541 }
00542
00543 KUrl ManagerPrivate::queryUrl(QueryType type, const QString &newName) const
00544 {
00545 KUrl url = serverURL;
00546 QString nameItem = "nickname";
00547 QString name = _playerInfos->registeredName();
00548 bool withVersion = true;
00549 bool key = false;
00550 bool level = false;
00551
00552 switch (type) {
00553 case Submit:
00554 url.addPath("submit.php");
00555 level = true;
00556 key = true;
00557 break;
00558 case Register:
00559 url.addPath("register.php");
00560 name = newName;
00561 break;
00562 case Change:
00563 url.addPath("change.php");
00564 key = true;
00565 if ( newName!=name )
00566 Manager::addToQueryURL(url, "new_nickname", newName);
00567 break;
00568 case Players:
00569 url.addPath("players.php");
00570 nameItem = "highlight";
00571 withVersion = false;
00572 break;
00573 case Scores:
00574 url.addPath("highscores.php");
00575 withVersion = false;
00576 if ( _nbGameTypes>1 ) level = true;
00577 break;
00578 }
00579
00580 if (withVersion) Manager::addToQueryURL(url, "version", version);
00581 if ( !name.isEmpty() ) Manager::addToQueryURL(url, nameItem, name);
00582 if (key) Manager::addToQueryURL(url, "key", _playerInfos->key());
00583 if (level) {
00584 QString label = manager.gameTypeLabel(_gameType, Manager::WW);
00585 if ( !label.isEmpty() ) Manager::addToQueryURL(url, "level", label);
00586 }
00587
00588 return url;
00589 }
00590
00591
00592 const char *DUMMY_STRINGS[] = {
00593 I18N_NOOP("Undefined error."),
00594 I18N_NOOP("Missing argument(s)."),
00595 I18N_NOOP("Invalid argument(s)."),
00596
00597 I18N_NOOP("Unable to connect to MySQL server."),
00598 I18N_NOOP("Unable to select database."),
00599 I18N_NOOP("Error on database query."),
00600 I18N_NOOP("Error on database insert."),
00601
00602 I18N_NOOP("Nickname already registered."),
00603 I18N_NOOP("Nickname not registered."),
00604 I18N_NOOP("Invalid key."),
00605 I18N_NOOP("Invalid submit key."),
00606
00607 I18N_NOOP("Invalid level."),
00608 I18N_NOOP("Invalid score.")
00609 };
00610
00611 const char *UNABLE_TO_CONTACT =
00612 I18N_NOOP("Unable to contact world-wide highscore server");
00613
00614 bool ManagerPrivate::doQuery(const KUrl &url, QWidget *parent,
00615 QDomNamedNodeMap *map)
00616 {
00617 KIO::http_update_cache(url, true, 0);
00618
00619 QString tmpFile;
00620 if ( !KIO::NetAccess::download(url, tmpFile, parent) ) {
00621 QString details = i18n("Server URL: %1", url.host());
00622 KMessageBox::detailedSorry(parent, i18n(UNABLE_TO_CONTACT), details);
00623 return false;
00624 }
00625
00626 QFile file(tmpFile);
00627 if ( !file.open(QIODevice::ReadOnly) ) {
00628 KIO::NetAccess::removeTempFile(tmpFile);
00629 QString details = i18n("Unable to open temporary file.");
00630 KMessageBox::detailedSorry(parent, i18n(UNABLE_TO_CONTACT), details);
00631 return false;
00632 }
00633
00634 QTextStream t(&file);
00635 QString content = t.readAll().trimmed();
00636 file.close();
00637 KIO::NetAccess::removeTempFile(tmpFile);
00638
00639 QDomDocument doc;
00640 if ( doc.setContent(content) ) {
00641 QDomElement root = doc.documentElement();
00642 QDomElement element = root.firstChild().toElement();
00643 if ( element.tagName()=="success" ) {
00644 if (map) *map = element.attributes();
00645 return true;
00646 }
00647 if ( element.tagName()=="error" ) {
00648 QDomAttr attr = element.attributes().namedItem("label").toAttr();
00649 if ( !attr.isNull() ) {
00650 QString msg = i18n(attr.value().toLatin1());
00651 QString caption = i18n("Message from world-wide highscores "
00652 "server");
00653 KMessageBox::sorry(parent, msg, caption);
00654 return false;
00655 }
00656 }
00657 }
00658 QString msg = i18n("Invalid answer from world-wide highscores server.");
00659 QString details = i18n("Raw message: %1", content);
00660 KMessageBox::detailedSorry(parent, msg, details);
00661 return false;
00662 }
00663
00664 bool ManagerPrivate::getFromQuery(const QDomNamedNodeMap &map,
00665 const QString &name, QString &value,
00666 QWidget *parent)
00667 {
00668 QDomAttr attr = map.namedItem(name).toAttr();
00669 if ( attr.isNull() ) {
00670 KMessageBox::sorry(parent,
00671 i18n("Invalid answer from world-wide "
00672 "highscores server (missing item: %1).", name));
00673 return false;
00674 }
00675 value = attr.value();
00676 return true;
00677 }
00678
00679 Score ManagerPrivate::readScore(uint i) const
00680 {
00681 Score score(Won);
00682 _scoreInfos->read(i, score);
00683 return score;
00684 }
00685
00686 int ManagerPrivate::rank(const Score &score) const
00687 {
00688 uint nb = _scoreInfos->nbEntries();
00689 uint i = 0;
00690 for (; i<nb; i++)
00691 if ( readScore(i)<score ) break;
00692 return (i<_scoreInfos->maxNbEntries() ? (int)i : -1);
00693 }
00694
00695 bool ManagerPrivate::modifySettings(const QString &newName,
00696 const QString &comment, bool WWEnabled,
00697 QWidget *widget)
00698 {
00699 QString newKey;
00700 bool newPlayer = false;
00701
00702 if (WWEnabled) {
00703 newPlayer = _playerInfos->key().isEmpty()
00704 || _playerInfos->registeredName().isEmpty();
00705 KUrl url = queryUrl((newPlayer ? Register : Change), newName);
00706 Manager::addToQueryURL(url, "comment", comment);
00707
00708 QDomNamedNodeMap map;
00709 bool ok = doQuery(url, widget, &map);
00710 if ( !ok || (newPlayer && !getFromQuery(map, "key", newKey, widget)) )
00711 return false;
00712 }
00713
00714 bool ok = _hsConfig->lockForWriting(widget);
00715 if (ok) {
00716
00717
00718
00719 ok = ( !_playerInfos->isNameUsed(newName) );
00720 if (ok)
00721 _playerInfos->modifySettings(newName, comment, WWEnabled, newKey);
00722 _hsConfig->writeAndUnlock();
00723 }
00724 return ok;
00725 }
00726
00727 void ManagerPrivate::convertToGlobal()
00728 {
00729
00730 KHighscore *tmp = _hsConfig;
00731 _hsConfig = new KHighscore(true, 0);
00732 QVector<Score> scores(_scoreInfos->nbEntries());
00733 for (int i=0; i<scores.count(); i++)
00734 scores[i] = readScore(i);
00735
00736
00737 delete _hsConfig;
00738 _hsConfig = tmp;
00739 _hsConfig->lockForWriting();
00740 for (int i=0; i<scores.count(); i++)
00741 if ( scores[i].data("id").toUInt()==_playerInfos->oldLocalId()+1 )
00742 submitLocal(scores[i]);
00743 _hsConfig->writeAndUnlock();
00744 }
00745
00746 void ManagerPrivate::setGameType(uint type)
00747 {
00748 if (_first) {
00749 _first = false;
00750 if ( _playerInfos->isNewPlayer() ) {
00751
00752 for (uint i=0; i<_nbGameTypes; i++) {
00753 setGameType(i);
00754 manager.convertLegacy(i);
00755 }
00756
00757 #ifdef HIGHSCORE_DIRECTORY
00758 if ( _playerInfos->isOldLocalPlayer() ) {
00759
00760 for (uint i=0; i<_nbGameTypes; i++) {
00761 setGameType(i);
00762 convertToGlobal();
00763 }
00764 }
00765 #endif
00766 }
00767 }
00768
00769 Q_ASSERT( type<_nbGameTypes );
00770 _gameType = qMin(type, _nbGameTypes-1);
00771 QString str = "scores";
00772 QString lab = manager.gameTypeLabel(_gameType, Manager::Standard);
00773 if ( !lab.isEmpty() ) {
00774 _playerInfos->setSubGroup(lab);
00775 str += '_' + lab;
00776 }
00777 _scoreInfos->setGroup(str);
00778 }
00779
00780 void ManagerPrivate::checkFirst()
00781 {
00782 if (_first) setGameType(0);
00783 }
00784
00785 int ManagerPrivate::submitScore(const Score &ascore,
00786 QWidget *widget, bool askIfAnonymous)
00787 {
00788 checkFirst();
00789
00790 Score score = ascore;
00791 score.setData("id", _playerInfos->id() + 1);
00792 score.setData("date", QDateTime::currentDateTime());
00793
00794
00795 const char *dontAskAgainName = "highscore_ask_name_dialog";
00796 QString newName;
00797 KMessageBox::ButtonCode dummy;
00798 if ( score.type()==Won && askIfAnonymous && _playerInfos->isAnonymous()
00799 && KMessageBox::shouldBeShownYesNo(dontAskAgainName, dummy) ) {
00800 AskNameDialog d(widget);
00801 if ( d.exec()==QDialog::Accepted ) newName = d.name();
00802 if ( d.dontAskAgain() )
00803 KMessageBox::saveDontShowAgainYesNo(dontAskAgainName,
00804 KMessageBox::No);
00805 }
00806
00807 int rank = -1;
00808 if ( _hsConfig->lockForWriting(widget) ) {
00809
00810 if ( !newName.isEmpty() && !_playerInfos->isNameUsed(newName) )
00811 _playerInfos->modifyName(newName);
00812
00813
00814 _playerInfos->