diff --git a/kexthighscore_internal.cpp b/kexthighscore_internal.cpp index 1171518..c66a180 100644 --- a/kexthighscore_internal.cpp +++ b/kexthighscore_internal.cpp @@ -1,888 +1,887 @@ /* This file is part of the KDE games library Copyright (C) 2001-2004 Nicolas Hadacek (hadacek@kde.org) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kexthighscore_internal.h" #include -#include #include #include #include #include #include #include #include #include #include #include #include "kexthighscore.h" #include "kexthighscore_gui.h" #include "kemailsettings.h" // TODO Decide if want to support // a build time HIGHSCORE_DIRECTORY or not // #include namespace KExtHighscore { //----------------------------------------------------------------------------- const char ItemContainer::ANONYMOUS[] = "_"; const char ItemContainer::ANONYMOUS_LABEL[] = I18N_NOOP("anonymous"); ItemContainer::ItemContainer() : _item(0) {} ItemContainer::~ItemContainer() { delete _item; } void ItemContainer::setItem(Item *item) { delete _item; _item = item; } QString ItemContainer::entryName() const { if ( _subGroup.isEmpty() ) return _name; return _name + QLatin1Char( '_' ) + _subGroup; } QVariant ItemContainer::read(uint i) const { Q_ASSERT(_item); QVariant v = _item->defaultValue(); if ( isStored() ) { internal->hsConfig().setHighscoreGroup(_group); v = internal->hsConfig().readPropertyEntry(i+1, entryName(), v); } return _item->read(i, v); } QString ItemContainer::pretty(uint i) const { Q_ASSERT(_item); return _item->pretty(i, read(i)); } void ItemContainer::write(uint i, const QVariant &value) const { Q_ASSERT( isStored() ); Q_ASSERT( internal->hsConfig().isLocked() ); internal->hsConfig().setHighscoreGroup(_group); internal->hsConfig().writeEntry(i+1, entryName(), value); } uint ItemContainer::increment(uint i) const { uint v = read(i).toUInt() + 1; write(i, v); return v; } //----------------------------------------------------------------------------- ItemArray::ItemArray() : _group(QLatin1String( "" )), _subGroup(QLatin1String( "" )) // no null groups {} ItemArray::~ItemArray() { for (int i=0; iname()==name ) return i; return -1; } const ItemContainer *ItemArray::item(const QString &name) const { QLoggingCategory::setFilterRules(QStringLiteral("games.highscore.debug = true")); int i = findIndex(name); if ( i==-1 ) qCCritical(GAMES_EXTHIGHSCORE) << "no item named \"" << name << "\""; return at(i); } ItemContainer *ItemArray::item(const QString &name) { QLoggingCategory::setFilterRules(QStringLiteral("games.highscore.debug = true")); int i = findIndex(name); if ( i==-1 ) qCCritical(GAMES_EXTHIGHSCORE) << "no item named \"" << name << "\""; return at(i); } void ItemArray::setItem(const QString &name, Item *item) { QLoggingCategory::setFilterRules(QStringLiteral("games.highscore.debug = true")); int i = findIndex(name); if ( i==-1 ) qCCritical(GAMES_EXTHIGHSCORE) << "no item named \"" << name << "\""; bool stored = at(i)->isStored(); bool canHaveSubGroup = at(i)->canHaveSubGroup(); _setItem(i, name, item, stored, canHaveSubGroup); } void ItemArray::addItem(const QString &name, Item *item, bool stored, bool canHaveSubGroup) { QLoggingCategory::setFilterRules(QStringLiteral("games.highscore.debug = true")); if ( findIndex(name)!=-1 ) qCCritical(GAMES_EXTHIGHSCORE) << "item already exists \"" << name << "\""; append(new ItemContainer); //at(i) = new ItemContainer; _setItem(size()-1, name, item, stored, canHaveSubGroup); } void ItemArray::_setItem(uint i, const QString &name, Item *item, bool stored, bool canHaveSubGroup) { at(i)->setItem(item); at(i)->setName(name); at(i)->setGroup(stored ? _group : QString()); at(i)->setSubGroup(canHaveSubGroup ? _subGroup : QString()); } void ItemArray::setGroup(const QString &group) { Q_ASSERT( !group.isNull() ); _group = group; for (int i=0; iisStored() ) at(i)->setGroup(group); } void ItemArray::setSubGroup(const QString &subGroup) { Q_ASSERT( !subGroup.isNull() ); _subGroup = subGroup; for (int i=0; icanHaveSubGroup() ) at(i)->setSubGroup(subGroup); } void ItemArray::read(uint k, Score &data) const { for (int i=0; iisStored() ) continue; data.setData(at(i)->name(), at(i)->read(k)); } } void ItemArray::write(uint k, const Score &data, uint nb) const { for (int i=0; iisStored() ) continue; for (uint j=nb-1; j>k; j--) at(i)->write(j, at(i)->read(j-1)); at(i)->write(k, data.data(at(i)->name())); } } void ItemArray::exportToText(QTextStream &s) const { for (uint k=0; kitem(); if ( item->isVisible() ) { if ( i!=0 ) s << '\t'; if ( k==0 ) s << item->label(); else s << at(i)->pretty(k-1); } } s << endl; } } //----------------------------------------------------------------------------- class ScoreNameItem : public NameItem { public: ScoreNameItem(const ScoreInfos &score, const PlayerInfos &infos) : _score(score), _infos(infos) {} QString pretty(uint i, const QVariant &v) const override { uint id = _score.item(QStringLiteral( "id" ))->read(i).toUInt(); if ( id==0 ) return NameItem::pretty(i, v); return _infos.prettyName(id-1); } private: const ScoreInfos &_score; const PlayerInfos &_infos; }; //----------------------------------------------------------------------------- ScoreInfos::ScoreInfos(uint maxNbEntries, const PlayerInfos &infos) : _maxNbEntries(maxNbEntries) { addItem(QStringLiteral( "id" ), new Item((uint)0)); addItem(QStringLiteral( "rank" ), new RankItem, false); addItem(QStringLiteral( "name" ), new ScoreNameItem(*this, infos)); addItem(QStringLiteral( "score" ), Manager::createItem(Manager::ScoreDefault)); addItem(QStringLiteral( "date" ), new DateItem); } uint ScoreInfos::nbEntries() const { uint i = 0; for (; i<_maxNbEntries; i++) if ( item(QStringLiteral( "score" ))->read(i)==item(QStringLiteral( "score" ))->item()->defaultValue() ) break; return i; } //----------------------------------------------------------------------------- const char *HS_ID = "player id"; const char *HS_REGISTERED_NAME = "registered name"; const char *HS_KEY = "player key"; const char *HS_WW_ENABLED = "ww hs enabled"; PlayerInfos::PlayerInfos() { setGroup(QStringLiteral( "players" )); // standard items addItem(QStringLiteral( "name" ), new NameItem); Item *it = new Item((uint)0, i18n("Games Count"),Qt::AlignRight); addItem(QStringLiteral( "nb games" ), it, true, true); it = Manager::createItem(Manager::MeanScoreDefault); addItem(QStringLiteral( "mean score" ), it, true, true); it = Manager::createItem(Manager::BestScoreDefault); addItem(QStringLiteral( "best score" ), it, true, true); addItem(QStringLiteral( "date" ), new DateItem, true, true); it = new Item(QString(), i18n("Comment"), Qt::AlignLeft); addItem(QStringLiteral( "comment" ), it); // statistics items addItem(QStringLiteral( "nb black marks" ), new Item((uint)0), true, true); // legacy addItem(QStringLiteral( "nb lost games" ), new Item((uint)0), true, true); addItem(QStringLiteral( "nb draw games" ), new Item((uint)0), true, true); addItem(QStringLiteral( "current trend" ), new Item((int)0), true, true); addItem(QStringLiteral( "max lost trend" ), new Item((uint)0), true, true); addItem(QStringLiteral( "max won trend" ), new Item((uint)0), true, true); QString username = KUser().loginName(); #ifdef HIGHSCORE_DIRECTORY internal->hsConfig().setHighscoreGroup("players"); for (uint i=0; ;i++) { if ( !internal->hsConfig().hasEntry(i+1, "username") ) { _newPlayer = true; _id = i; break; } if ( internal->hsConfig().readEntry(i+1, "username")==username ) { _newPlayer = false; _id = i; return; } } #endif internal->hsConfig().lockForWriting(); KEMailSettings emailConfig; emailConfig.setProfile(emailConfig.defaultProfileName()); QString name = emailConfig.getSetting(KEMailSettings::RealName); if ( name.isEmpty() || isNameUsed(name) ) name = username; if ( isNameUsed(name) ) name= QLatin1String(ItemContainer::ANONYMOUS); #ifdef HIGHSCORE_DIRECTORY internal->hsConfig().writeEntry(_id+1, "username", username); item("name")->write(_id, name); #endif ConfigGroup cg; _oldLocalPlayer = cg.hasKey(HS_ID); _oldLocalId = cg.readEntry(HS_ID).toUInt(); #ifdef HIGHSCORE_DIRECTORY if (_oldLocalPlayer) { // player already exists in local config file // copy player data QString prefix = QString::fromLatin1( "%1_").arg(_oldLocalId+1); #ifdef __GNUC__ #warning "kde4 port g.config()->entryMap"; #endif #if 0 QMap entries = cg.config()->entryMap("KHighscore_players"); QMap::const_iterator it; for (it=entries.begin(); it!=entries.end(); ++it) { QString key = it.key(); if ( key.find(prefix)==0 ) { QString name = key.right(key.length()-prefix.length()); if ( name!="name" || !isNameUsed(it.data()) ) internal->hsConfig().writeEntry(_id+1, name, it.data()); } } #endif } #else _newPlayer = !_oldLocalPlayer; if (_oldLocalPlayer) _id = _oldLocalId; else { _id = nbEntries(); cg.writeEntry(HS_ID, _id); item(QStringLiteral( "name" ))->write(_id, name); } #endif _bound = true; internal->hsConfig().writeAndUnlock(); } void PlayerInfos::createHistoItems(const QVector &scores, bool bound) { Q_ASSERT( _histogram.size()==0 ); _bound = bound; _histogram = scores; for (int i=1; ihsConfig().setHighscoreGroup(QStringLiteral( "players" )); const QStringList list = internal->hsConfig().readList(QStringLiteral( "name" ), -1); return list.count(); } QString PlayerInfos::key() const { ConfigGroup cg; return cg.readEntry(HS_KEY, QString()); } bool PlayerInfos::isWWEnabled() const { ConfigGroup cg; return cg.readEntry(HS_WW_ENABLED, false); } QString PlayerInfos::histoName(int i) const { const QVector &sh = _histogram; Q_ASSERT( iincrement(_id); switch (score.type()) { case Lost: item(QStringLiteral( "nb lost games" ))->increment(_id); break; case Won: break; case Draw: item(QStringLiteral( "nb draw games" ))->increment(_id); break; }; // update mean if ( score.type()==Won ) { uint nbWonGames = nbGames - item(QStringLiteral( "nb lost games" ))->read(_id).toUInt() - item(QStringLiteral( "nb draw games" ))->read(_id).toUInt() - item(QStringLiteral( "nb black marks" ))->read(_id).toUInt(); // legacy double mean = (nbWonGames==1 ? 0.0 : item(QStringLiteral( "mean score" ))->read(_id).toDouble()); mean += (double(score.score()) - mean) / nbWonGames; item(QStringLiteral( "mean score" ))->write(_id, mean); } // update best score Score best = score; // copy optional fields (there are not taken into account here) best.setScore( item(QStringLiteral( "best score" ))->read(_id).toUInt() ); if ( bestwrite(_id, score.score()); item(QStringLiteral( "date" ))->write(_id, score.data(QStringLiteral( "date" )).toDateTime()); } // update trends int current = item(QStringLiteral( "current trend" ))->read(_id).toInt(); switch (score.type()) { case Won: { if ( current<0 ) current = 0; current++; uint won = item(QStringLiteral( "max won trend" ))->read(_id).toUInt(); if ( (uint)current>won ) item(QStringLiteral( "max won trend" ))->write(_id, current); break; } case Lost: { if ( current>0 ) current = 0; current--; uint lost = item(QStringLiteral( "max lost trend" ))->read(_id).toUInt(); uint clost = -current; if ( clost>lost ) item(QStringLiteral( "max lost trend" ))->write(_id, clost); break; } case Draw: current = 0; break; } item(QStringLiteral( "current trend" ))->write(_id, current); // update histogram if ( score.type()==Won ) { const QVector &sh = _histogram; for (int i=1; iincrement(_id); break; } } } bool PlayerInfos::isNameUsed(const QString &newName) const { if ( newName==name() ) return false; // own name... for (uint i=0; iread(i).toString().toLower() ) return true; if ( newName==i18n(ItemContainer::ANONYMOUS_LABEL) ) return true; return false; } void PlayerInfos::modifyName(const QString &newName) const { item(QStringLiteral( "name" ))->write(_id, newName); } void PlayerInfos::modifySettings(const QString &newName, const QString &comment, bool WWEnabled, const QString &newKey) const { modifyName(newName); item(QStringLiteral( "comment" ))->write(_id, comment); ConfigGroup cg; cg.writeEntry(HS_WW_ENABLED, WWEnabled); if ( !newKey.isEmpty() ) cg.writeEntry(HS_KEY, newKey); if (WWEnabled) cg.writeEntry(HS_REGISTERED_NAME, newName); } QString PlayerInfos::registeredName() const { ConfigGroup cg; return cg.readEntry(HS_REGISTERED_NAME, QString()); } void PlayerInfos::removeKey() { ConfigGroup cg; // save old key/nickname uint i = 0; QString str = QStringLiteral( "%1 old #%2" ); QString sk; do { i++; sk = str.arg(QLatin1String( HS_KEY )).arg(i); } while ( !cg.readEntry(sk, QString()).isEmpty() ); cg.writeEntry(sk, key()); cg.writeEntry(str.arg(QLatin1String( HS_REGISTERED_NAME )).arg(i), registeredName()); // clear current key/nickname cg.deleteEntry(HS_KEY); cg.deleteEntry(HS_REGISTERED_NAME); cg.writeEntry(HS_WW_ENABLED, false); } //----------------------------------------------------------------------------- ManagerPrivate::ManagerPrivate(uint nbGameTypes, Manager &m) : manager(m), showStatistics(false), showDrawGames(false), trackLostGames(false), trackDrawGames(false), showMode(Manager::ShowForHigherScore), _first(true), _nbGameTypes(nbGameTypes), _gameType(0) {} void ManagerPrivate::init(uint maxNbEntries) { _hsConfig = new KHighscore(false, 0); _playerInfos = new PlayerInfos; _scoreInfos = new ScoreInfos(maxNbEntries, *_playerInfos); } ManagerPrivate::~ManagerPrivate() { delete _scoreInfos; delete _playerInfos; delete _hsConfig; } QUrl ManagerPrivate::queryUrl(QueryType type, const QString &newName) const { QUrl url = serverURL; QString nameItem = QStringLiteral( "nickname" ); QString name = _playerInfos->registeredName(); bool withVersion = true; bool key = false; bool level = false; switch (type) { case Submit: url = url.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + QLatin1Char('/') + QStringLiteral( "submit.php" )); level = true; key = true; break; case Register: url = url.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + QLatin1Char('/') + QStringLiteral( "register.php" )); name = newName; break; case Change: url = url.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + QLatin1Char('/') + QStringLiteral( "change.php" )); key = true; if ( newName!=name ) Manager::addToQueryURL(url, QStringLiteral( "new_nickname" ), newName); break; case Players: url = url.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + QLatin1Char('/') + QStringLiteral( "players.php" )); nameItem = QStringLiteral( "highlight" ); withVersion = false; break; case Scores: url = url.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + QLatin1Char('/') + QStringLiteral( "highscores.php" )); withVersion = false; if ( _nbGameTypes>1 ) level = true; break; } if (withVersion) Manager::addToQueryURL(url, QStringLiteral( "version" ), version); if ( !name.isEmpty() ) Manager::addToQueryURL(url, nameItem, name); if (key) Manager::addToQueryURL(url, QStringLiteral( "key" ), _playerInfos->key()); if (level) { QString label = manager.gameTypeLabel(_gameType, Manager::WW); if ( !label.isEmpty() ) Manager::addToQueryURL(url, QStringLiteral( "level" ), label); } return url; } // strings that needs to be translated (coming from the highscores server) const char *DUMMY_STRINGS[] = { I18N_NOOP("Undefined error."), I18N_NOOP("Missing argument(s)."), I18N_NOOP("Invalid argument(s)."), I18N_NOOP("Unable to connect to MySQL server."), I18N_NOOP("Unable to select database."), I18N_NOOP("Error on database query."), I18N_NOOP("Error on database insert."), I18N_NOOP("Nickname already registered."), I18N_NOOP("Nickname not registered."), I18N_NOOP("Invalid key."), I18N_NOOP("Invalid submit key."), I18N_NOOP("Invalid level."), I18N_NOOP("Invalid score.") }; const char *UNABLE_TO_CONTACT = I18N_NOOP("Unable to contact world-wide highscore server"); bool ManagerPrivate::doQuery(const QUrl &url, QWidget *parent, QDomNamedNodeMap *map) { KIO::http_update_cache(url, true, QDateTime::fromSecsSinceEpoch(0)); // remove cache ! QTemporaryFile tmpFile; if ( !tmpFile.open() ) { QString details = i18n("Unable to open temporary file."); KMessageBox::detailedSorry(parent, i18n(UNABLE_TO_CONTACT), details); return false; } auto copyJob = KIO::file_copy(url, QUrl::fromLocalFile(tmpFile.fileName())); KJobWidgets::setWindow(copyJob, parent); copyJob->exec(); if( copyJob->error() ) { QString details = i18n("Server URL: %1", url.host()); KMessageBox::detailedSorry(parent, i18n(UNABLE_TO_CONTACT), details); return false; } QTextStream t(&tmpFile); QString content = t.readAll().trimmed(); tmpFile.close(); QDomDocument doc; if ( doc.setContent(content) ) { QDomElement root = doc.documentElement(); QDomElement element = root.firstChild().toElement(); if ( element.tagName()==QLatin1String( "success" ) ) { if (map) *map = element.attributes(); return true; } if ( element.tagName()==QLatin1String( "error" ) ) { QDomAttr attr = element.attributes().namedItem(QStringLiteral( "label" )).toAttr(); if ( !attr.isNull() ) { QString msg = i18n(attr.value().toLatin1()); QString caption = i18n("Message from world-wide highscores " "server"); KMessageBox::sorry(parent, msg, caption); return false; } } } QString msg = i18n("Invalid answer from world-wide highscores server."); QString details = i18n("Raw message: %1", content); KMessageBox::detailedSorry(parent, msg, details); return false; } bool ManagerPrivate::getFromQuery(const QDomNamedNodeMap &map, const QString &name, QString &value, QWidget *parent) { QDomAttr attr = map.namedItem(name).toAttr(); if ( attr.isNull() ) { KMessageBox::sorry(parent, i18n("Invalid answer from world-wide " "highscores server (missing item: %1).", name)); return false; } value = attr.value(); return true; } Score ManagerPrivate::readScore(uint i) const { Score score(Won); _scoreInfos->read(i, score); return score; } int ManagerPrivate::rank(const Score &score) const { uint nb = _scoreInfos->nbEntries(); uint i = 0; for (; imaxNbEntries() ? (int)i : -1); } bool ManagerPrivate::modifySettings(const QString &newName, const QString &comment, bool WWEnabled, QWidget *widget) { QString newKey; bool newPlayer = false; if (WWEnabled) { newPlayer = _playerInfos->key().isEmpty() || _playerInfos->registeredName().isEmpty(); QUrl url = queryUrl((newPlayer ? Register : Change), newName); Manager::addToQueryURL(url, QStringLiteral( "comment" ), comment); QDomNamedNodeMap map; bool ok = doQuery(url, widget, &map); if ( !ok || (newPlayer && !getFromQuery(map, QStringLiteral( "key" ), newKey, widget)) ) return false; } bool ok = _hsConfig->lockForWriting(widget); // no GUI when locking if (ok) { // check again name in case the config file has been changed... // if it has, it is unfortunate because the WWW name is already // committed but should be very rare and not really problematic ok = ( !_playerInfos->isNameUsed(newName) ); if (ok) _playerInfos->modifySettings(newName, comment, WWEnabled, newKey); _hsConfig->writeAndUnlock(); } return ok; } void ManagerPrivate::convertToGlobal() { // read old highscores KHighscore *tmp = _hsConfig; _hsConfig = new KHighscore(true, 0); QVector scores(_scoreInfos->nbEntries()); for (int i=0; ilockForWriting(); for (int i=0; ioldLocalId()+1 ) submitLocal(scores[i]); _hsConfig->writeAndUnlock(); } void ManagerPrivate::setGameType(uint type) { if (_first) { _first = false; if ( _playerInfos->isNewPlayer() ) { // convert legacy highscores for (uint i=0; i<_nbGameTypes; i++) { setGameType(i); manager.convertLegacy(i); } #ifdef HIGHSCORE_DIRECTORY if ( _playerInfos->isOldLocalPlayer() ) { // convert local to global highscores for (uint i=0; i<_nbGameTypes; i++) { setGameType(i); convertToGlobal(); } } #endif } } Q_ASSERT( type<_nbGameTypes ); _gameType = qMin(type, _nbGameTypes-1); QString str = QStringLiteral( "scores" ); QString lab = manager.gameTypeLabel(_gameType, Manager::Standard); if ( !lab.isEmpty() ) { _playerInfos->setSubGroup(lab); str += QLatin1Char( '_' ) + lab; } _scoreInfos->setGroup(str); } void ManagerPrivate::checkFirst() { if (_first) setGameType(0); } int ManagerPrivate::submitScore(const Score &ascore, QWidget *widget, bool askIfAnonymous) { checkFirst(); Score score = ascore; score.setData(QStringLiteral( "id" ), _playerInfos->id() + 1); score.setData(QStringLiteral( "date" ), QDateTime::currentDateTime()); // ask new name if anonymous and winner const QLatin1String dontAskAgainName = QLatin1String( "highscore_ask_name_dialog" ); QString newName; KMessageBox::ButtonCode dummy; if ( score.type()==Won && askIfAnonymous && _playerInfos->isAnonymous() && KMessageBox::shouldBeShownYesNo(dontAskAgainName, dummy) ) { AskNameDialog d(widget); if ( d.exec()==QDialog::Accepted ) newName = d.name(); if ( d.dontAskAgain() ) KMessageBox::saveDontShowAgainYesNo(dontAskAgainName, KMessageBox::No); } int rank = -1; if ( _hsConfig->lockForWriting(widget) ) { // no GUI when locking // check again new name in case the config file has been changed... if ( !newName.isEmpty() && !_playerInfos->isNameUsed(newName) ) _playerInfos->modifyName(newName); // commit locally _playerInfos->submitScore(score); if ( score.type()==Won ) rank = submitLocal(score); _hsConfig->writeAndUnlock(); } if ( _playerInfos->isWWEnabled() ) submitWorldWide(score, widget); return rank; } int ManagerPrivate::submitLocal(const Score &score) { int r = rank(score); if ( r!=-1 ) { uint nb = _scoreInfos->nbEntries(); if ( nb<_scoreInfos->maxNbEntries() ) nb++; _scoreInfos->write(r, score, nb); } return r; } bool ManagerPrivate::submitWorldWide(const Score &score, QWidget *widget) const { if ( score.type()==Lost && !trackLostGames ) return true; if ( score.type()==Draw && !trackDrawGames ) return true; QUrl url = queryUrl(Submit); manager.additionalQueryItems(url, score); int s = (score.type()==Won ? score.score() : (int)score.type()); QString str = QString::number(s); Manager::addToQueryURL(url, QStringLiteral( "score" ), str); QCryptographicHash context(QCryptographicHash::Md5); context.addData(QString(_playerInfos->registeredName() + str).toLatin1()); Manager::addToQueryURL(url, QStringLiteral( "check" ), QLatin1String( context.result().toHex() )); return doQuery(url, widget); } void ManagerPrivate::exportHighscores(QTextStream &s) { uint tmp = _gameType; for (uint i=0; i<_nbGameTypes; i++) { setGameType(i); if ( _nbGameTypes>1 ) { if ( i!=0 ) s << endl; s << "--------------------------------" << endl; s << "Game type: " << manager.gameTypeLabel(_gameType, Manager::I18N) << endl; s << endl; } s << "Players list:" << endl; _playerInfos->exportToText(s); s << endl; s << "Highscores list:" << endl; _scoreInfos->exportToText(s); } setGameType(tmp); } } // namespace