Commit c918a367 authored by Albert Astals Cid's avatar Albert Astals Cid
Browse files

Bring KExtHighscore classes from libkdegames

KExtHighscore is being removed from libkdegames since they are considered deprecated.

KReversi its the only user so we're bringing the code here. This is an unfinished port that lived in libkdegames (see there's a few TODO). Would probably need some clearing also like removing the world-wide highscore support that we don't use and adds a considerable amount of code (i have a patch for that too)

Compiles, haven't done much more since it's the frameworks branch and thus work in progress/unreleased

REVIEW: 124393
parent 842ef3ed
......@@ -24,6 +24,7 @@ find_package(KF5 REQUIRED COMPONENTS
XmlGui
KIO
NewStuff
KDELibs4Support
)
find_package(KF5KDEGames 4.9.0 REQUIRED)
......@@ -57,6 +58,11 @@ set(kreversi_SRCS
startgamedialog.cpp
Engine.cpp
highscores.cpp
kexthighscore.cpp
kexthighscore_gui.cpp
kexthighscore_internal.cpp
kexthighscore_item.cpp
kexthighscore_tab.cpp
mainwindow.cpp
main.cpp )
......@@ -66,7 +72,7 @@ kconfig_add_kcfg_files(kreversi_SRCS preferences.kcfgc)
add_executable(kreversi ${kreversi_SRCS})
target_link_libraries(kreversi Qt5::Svg KF5::Declarative KF5::XmlGui KF5::TextWidgets KF5KDEGames KF5::Completion KF5::DBusAddons)
target_link_libraries(kreversi Qt5::Svg KF5::Declarative KF5::XmlGui KF5::TextWidgets KF5KDEGames KF5::Completion KF5::DBusAddons KF5::KDELibs4Support)
install(TARGETS kreversi ${KDE_INSTALL_TARGETS_DEFAULT_ARGS} )
......
......@@ -19,7 +19,7 @@
#define HIGHSCORES_H
#include <QStringList>
#include <KExtHighscore>
#include "kexthighscore.h"
namespace KExtHighscore
{
......
/*
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.h"
#include <QLayout>
//Added by qt3to4:
#include <QVector>
#include <QUrlQuery>
#include "kexthighscore_internal.h"
#include "kexthighscore_gui.h"
Q_LOGGING_CATEGORY(GAMES_EXTHIGHSCORE, "games.exthighscore")
namespace KExtHighscore
{
//-----------------------------------------------------------------------------
ManagerPrivate *internal = 0;
uint gameType()
{
internal->checkFirst();
return internal->gameType();
}
void setGameType(uint type)
{
internal->setGameType(type);
}
bool configure(QWidget *parent)
{
internal->checkFirst();
ConfigDialog *cd = new ConfigDialog(parent);
cd->exec();
bool saved = cd->hasBeenSaved();
delete cd;
return saved;
}
void show(QWidget *parent, int rank)
{
HighscoresDialog *hd = new HighscoresDialog(rank, parent);
hd->exec();
delete hd;
}
void submitScore(const Score &score, QWidget *widget)
{
int rank = internal->submitScore(score, widget,
internal->showMode!=Manager::NeverShow);
switch (internal->showMode) {
case Manager::AlwaysShow:
show(widget, -1);
break;
case Manager::ShowForHigherScore:
if ( rank!=-1) show(widget, rank);
break;
case Manager::ShowForHighestScore:
if ( rank==0 ) show(widget, rank);
break;
case Manager::NeverShow:
break;
}
}
void show(QWidget *widget)
{
internal->checkFirst();
show(widget, -1);
}
Score lastScore()
{
internal->checkFirst();
internal->hsConfig().readCurrentConfig();
uint nb = internal->scoreInfos().maxNbEntries();
return internal->readScore(nb-1);
}
Score firstScore()
{
internal->checkFirst();
internal->hsConfig().readCurrentConfig();
return internal->readScore(0);
}
//-----------------------------------------------------------------------------
Manager::Manager(uint nbGameTypes, uint maxNbEntries)
{
QLoggingCategory::setFilterRules(QLatin1Literal("games.highscore.debug = true"));
Q_ASSERT(nbGameTypes);
Q_ASSERT(maxNbEntries);
if (internal)
{
qCWarning(GAMES_EXTHIGHSCORE) << "A highscore object already exists";
abort();
}
internal = new ManagerPrivate(nbGameTypes, *this);
internal->init(maxNbEntries);
}
Manager::~Manager()
{
delete internal;
internal = 0;
}
void Manager::setTrackLostGames(bool track)
{
internal->trackLostGames = track;
}
void Manager::setTrackDrawGames(bool track)
{
internal->trackDrawGames = track;
}
void Manager::setShowStatistics(bool show)
{
internal->showStatistics = show;
}
void Manager::setShowDrawGamesStatistic(bool show)
{
internal->showDrawGames = show;
}
void Manager::setWWHighscores(const QUrl &url, const QString &version)
{
Q_ASSERT( url.isValid() );
internal->serverURL = url;
const char *HS_WW_URL = "ww hs url";
ConfigGroup cg;
if ( cg.hasKey(HS_WW_URL) )
internal->serverURL = cg.readEntry(HS_WW_URL);
else cg.writeEntry(HS_WW_URL, url.url());
internal->version = version;
}
void Manager::setScoreHistogram(const QVector<uint> &scores,
ScoreTypeBound type)
{
Q_ASSERT( scores.size()>=2 );
for (int i=0; i<scores.size()-1; i++)
Q_ASSERT( scores[i]<scores[i+1] );
internal->playerInfos().createHistoItems(scores, type==ScoreBound);
}
void Manager::setShowMode(ShowMode mode)
{
internal->showMode = mode;
}
void Manager::setScoreType(ScoreType type)
{
switch (type) {
case Normal:
return;
case MinuteTime: {
Item *item = createItem(ScoreDefault);
item->setPrettyFormat(Item::MinuteTime);
setScoreItem(0, item);
item = createItem(MeanScoreDefault);
item->setPrettyFormat(Item::MinuteTime);
setPlayerItem(MeanScore, item);
item = createItem(BestScoreDefault);
item->setPrettyFormat(Item::MinuteTime);
setPlayerItem(BestScore, item);
return;
}
}
}
void Manager::submitLegacyScore(const Score &score) const
{
internal->submitLocal(score);
}
bool Manager::isStrictlyLess(const Score &s1, const Score &s2) const
{
return s1.score()<s2.score();
}
Item *Manager::createItem(ItemType type)
{
Item *item = 0;
switch (type) {
case ScoreDefault:
item = new Item((uint)0, i18n("Score"), Qt::AlignRight);
break;
case MeanScoreDefault:
item = new Item((double)0, i18n("Mean Score"), Qt::AlignRight);
item->setPrettyFormat(Item::OneDecimal);
item->setPrettySpecial(Item::DefaultNotDefined);
break;
case BestScoreDefault:
item = new Item((uint)0, i18n("Best Score"), Qt::AlignRight);
item->setPrettySpecial(Item::DefaultNotDefined);
break;
case ElapsedTime:
item = new Item((uint)0, i18n("Elapsed Time"), Qt::AlignRight);
item->setPrettyFormat(Item::MinuteTime);
item->setPrettySpecial(Item::ZeroNotDefined);
break;
}
return item;
}
void Manager::setScoreItem(uint worstScore, Item *item)
{
item->setDefaultValue(worstScore);
internal->scoreInfos().setItem(QLatin1String( "score" ), item);
internal->playerInfos().item(QLatin1String( "mean score" ))
->item()->setDefaultValue(double(worstScore));
internal->playerInfos().item(QLatin1String( "best score" ))
->item()->setDefaultValue(worstScore);
}
void Manager::addScoreItem(const QString &name, Item *item)
{
internal->scoreInfos().addItem(name, item, true);
}
void Manager::setPlayerItem(PlayerItemType type, Item *item)
{
const Item *scoreItem = internal->scoreInfos().item(QLatin1String( "score" ))->item();
uint def = scoreItem->defaultValue().toUInt();
QString name;
switch (type) {
case MeanScore:
name = QLatin1String( "mean score" );
item->setDefaultValue(double(def));
break;
case BestScore:
name = QLatin1String( "best score" );
item->setDefaultValue(def);
break;
}
internal->playerInfos().setItem(name, item);
}
QString Manager::gameTypeLabel(uint gameType, LabelType type) const
{
QLoggingCategory::setFilterRules(QLatin1Literal("games.highscore.debug = true"));
if ( gameType!=0 )
{
qCWarning(GAMES_EXTHIGHSCORE) << "You need to reimplement KExtHighscore::Manager for "
<< "multiple game types";
abort();
}
switch (type) {
case Icon:
case Standard:
case I18N: break;
case WW: return QLatin1String( "normal" );
}
return QString();
}
void Manager::addToQueryURL(QUrl &url, const QString &item,
const QString &content)
{
QUrlQuery urlquery(url);
Q_ASSERT( !item.isEmpty() && urlquery.queryItemValue(item).isEmpty() );
QString query = url.query();
if ( !query.isEmpty() ) query += QLatin1Char( '&' );
query += item + QLatin1Char( '=' ) + QLatin1String( QUrl::toPercentEncoding( content ) );
url.setQuery(query);
}
} // namescape
/*
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.
*/
#ifndef KEXTHIGHSCORE_H
#define KEXTHIGHSCORE_H
#include "kexthighscore_item.h"
#include <libkdegames_export.h>
#include <QtCore/QVector>
#include <QtCore/QUrl>
#include <QLoggingCategory>
namespace KExtHighscore
{
class Score;
class Item;
class ManagerPrivate;
extern ManagerPrivate *internal;
/**
* Get the current game type.
*/
KDEGAMES_EXPORT uint gameType();
/**
* Set the current game type.
*/
KDEGAMES_EXPORT void setGameType(uint gameType);
/**
* Configure the highscores.
* @return true if the configuration has been modified and saved
*/
KDEGAMES_EXPORT bool configure(QWidget *parent);
/**
* Show the highscores lists.
*/
KDEGAMES_EXPORT void show(QWidget *parent);
/**
* Submit a score. See @ref Manager for usage example.
*
* @param score the players score
* @param widget a widget used as parent for error message box.
*/
KDEGAMES_EXPORT void submitScore(const Score &score, QWidget *widget);
/**
* @return the last score in the local list of highscores. The worst possible
* score if there are less items than the maximum number.
*/
KDEGAMES_EXPORT Score lastScore();
/**
* @return the first score in the local list of highscores (the worst possible
* score if there is no entry).
*/
KDEGAMES_EXPORT Score firstScore();
/**
* This class manages highscores and players entries (several players can
* share the same highscores list if the libkdegame library is built to
* support a common highscores file; NOTE that to correctly implement such
* feature we probably need a locking mechanism in @ref KHighscore).
*
* You need one instance of this class during the application lifetime; in
* main() just insert
* \code
* KExtHighscore::Manager highscoresManager;
* \endcode
* with the needed arguments. Use the derived class if you need to
* reimplement some of the default methods.
*
* This class has three functions:
* <ul>
* <li> Update the highscores list when new entries are submitted </li>
* <li> Display the highscores list and the players list </li>
* <li> Send query to an optional web server to support world-wide
* highscores </li>
* </ul>
*
* The highscores and the players lists contain several items described by
* the @ref Item class.
*
* The highscores list contains by default:
* <ul>
* <li> the player name (automatically set from the config value)</li>
* <li> the score value </li>
* <li> the time and date of the highscore (automatically set) </li>
* </ul>
* You can replace the score item (for e.g. displaying it differently) with
* setScoreItem or add an item with addScoreItem.
*
* The players list contains:
* <ul>
* <li> the player name (as defined by the user in the configuration
* dialog) </li>
* <li> the number of games played </li>
* <li> the mean score </li>
* <li> the best score </li>
* <li> the best score time and date </li>
* <li> the player comment (as defined by the user in the
* configuration dialog) </li>
* </ul>
* You can replace the best score and the mean score items
* by calling setPlayerItem.
*
* To submit a new score at game end, just construct a Score, set the
* score data and then call submitScore().
* \code
* KExtHighscore::Score score(KExtHighscore::Won);
* score.setScore(myScore);
* KExtHighscore::submitScore(score, widget);
* \endcode
* You only need to set the score value with Score::setScore()
* and the value of the items that you have optionally added
* with Score::setData() player name and date are set automatically.
*/
class KDEGAMES_EXPORT Manager
{
public:
/**
* Constructor
*
* @param nbGameTypes the number of different game types (usually one).
* For example KMines has easy, normal and expert levels.
* @param maxNbEntries the maximum numbers of highscores entries (by game
* types)
*/
explicit Manager(uint nbGameTypes = 1, uint maxNbEntries = 10);
virtual ~Manager();
/**
* Set the world-wide highscores.
* By default there is no world-wide highscores.
*
* Note: should be called at construction time.
*
* @param url the web server url
* @param version the game version which is sent to the web server (it can
* be useful for backward compatibility on the server side).
*/
void setWWHighscores(const QUrl &url, const QString &version);
/**
* Set if the number of lost games should be track for the world-wide
* highscores statistics. By default, there is no tracking.
* False by default.
*
* Note: should be called at construction time.
*/
void setTrackLostGames(bool track);
/**
* Set if the number of "draw" games should be track for the world-wide
* highscores statistics. By default, there is no tracking.
* False by default.
*
* Note: should be called at construction time.
*/
void setTrackDrawGames(bool track);
/**
* Set if the statistics tab should be shown in the highscores dialog.
* You only want to show this tab if it makes sense to lose or to win the
* game (for e.g. it makes no sense for a tetris game but it does for a
* minesweeper game).
* False by default.
*
* Note: should be called at construction time.
*/
void setShowStatistics(bool show);
/**
* Set if draw games statistics should be shown (enable this if
* draws are possible in your game).
* False by default.
*/
void setShowDrawGamesStatistic(bool show);
enum ScoreTypeBound { ScoreNotBound, ScoreBound };
/**
* Set the ranges for the score histogram.
*
* Note: should be called at construction time.
*/
void setScoreHistogram(const QVector<uint> &scores, ScoreTypeBound type);
/**
* Enumerate different conditions under which to show the
* high score dialog.
*/
enum ShowMode { AlwaysShow, ///< Always show the dialog
NeverShow, ///< Never show the dialog
ShowForHigherScore, ///< Show if score has improved
ShowForHighestScore ///< Only for the top spot
};
/**
* Set how the highscores dialog is shown at game end.
* By default, the mode is ShowForHigherScore.
*
* Note: should be called at construction time.
*/
void setShowMode(ShowMode mode);
/**
* Score type (@see setScoreType).
* @p Normal default score (unsigned integer without upper bound)
* @p MinuteTime score by time bound at 3599 seconds (for e.g. kmines)
*/
enum ScoreType { Normal, MinuteTime };
/**
* Set score type. Helper method to quickly set the type of score.
* By default the type is Normal.
*
* Note: should be called at construction time.
*/
void setScoreType(ScoreType type);
/**
* Some predefined item types.
* @p ScoreDefault default item for the score in the highscores list.
* @p MeanScoreDefault default item for the mean score (only show one decimal and
* 0 is shown as "--".
* @p BestScoreDefault default item for the best score (0 is shown as "--").
* @p ElapsedTime optional item for elapsed time (maximum value is 3599 seconds).
*/
enum ItemType { ScoreDefault, MeanScoreDefault, BestScoreDefault,
ElapsedTime };
/**
* Create a predefined item.
*/
static Item *createItem(ItemType type);
/**
* Replace the default score item in the highscores list by the given one.
* @p worstScore is the worst possible score. By default it is 0.
*
* Note: This method should be called at construction time.
*/
void setScoreItem(uint worstScore, Item *item);
/**
* Add an item in the highscores list (it will add a column to this list).
*
* Note: This method should be called at construction time.
*/
void addScoreItem(const QString &name, Item *item);
enum PlayerItemType { MeanScore, BestScore };
/**
* Replace an item in the players list.
*
* Note: This method should be called at construction time.
*/
void setPlayerItem(PlayerItemType type, Item *item);
/**
* @return true if the first score is strictly worse than the second one.
* By default return <pre>s1.score()<s2.score()</pre>. You can reimplement
* this method if additional items added to @ref Score can further
* differentiate the scores (for e.g. the time spent).
*
* Note that you do not need to use directly this method, simply write
* <pre>s1<s2</pre> since the operator calls this method.
*/
virtual bool isStrictlyLess(const Score &s1, const Score &s2) const;
/**
* Possible type of label (@see gameTypeLabel).
* @p Standard label used in config file.
* @p I18N label used to display the game type.
* @p WW label used when contacting the world-wide highscores server.
* @p Icon label used to load the icon corresponding to the game type.
*/
enum LabelType { Standard, I18N, WW, Icon };
/**