File indexing completed on 2024-05-12 04:06:05
0001 /* 0002 This file is part of the KDE games library 0003 SPDX-FileCopyrightText: 2001 Andreas Beckermann <b_mann@gmx.de> 0004 SPDX-FileCopyrightText: 2003 Nicolas Hadacek <hadacek@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-only 0007 */ 0008 0009 #ifndef KGAMEHIGHSCORE_H 0010 #define KGAMEHIGHSCORE_H 0011 0012 // own 0013 #include <kdegames_export.h> 0014 // Qt 0015 #include <QObject> 0016 // Std 0017 #include <memory> 0018 0019 class KConfig; 0020 0021 /** 0022 * \class KGameHighscore kgamehighscore.h <KGameHighscore> 0023 * 0024 * @short Class for managing highscore tables 0025 * 0026 * This is the KDE class for saving and reading highscore tables. It offers the 0027 * possibility for system-wide highscore tables (cmake with e.g. 0028 * -DHIGHSCORE_DIRECTORY=/var/games) and a theoretically unlimited number of 0029 * entries. 0030 * 0031 * You can specify different "keys" for an entry - just like the KConfig 0032 * keys. But it will be prefixed with the number of the entry. For example you 0033 * will probably use something like this to save the name of the player on the 0034 * top of the list (ie the winner): 0035 * \code 0036 * highscore->writeEntry(1, "name", myPlayer->name()); 0037 * \endcode 0038 * Note that it does not really matter if you use "0" or "1" as the first entry 0039 * of the list as long as your program always uses the same for the first 0040 * entry. I recommend to use "1", as several convenience methods use this. 0041 * 0042 * You can also specify different groups using setHighscoreGroup. Just 0043 * like the keys mentioned above the groups behave like groups in KConfig 0044 * but are prefixed with "KHighscore_". The default group is just "KHighscore". 0045 * You might use this e.g. to create different highscore tables like 0046 * \code 0047 * table->setHighscoreGroup("Easy"); 0048 * // write the highscores for level "easy" to the table 0049 * writeEasyHighscores(table); 0050 * 0051 * table->setHighscore("Player_1"); 0052 * // write player specific highscores to the table 0053 * writePlayerHighscores(table); 0054 * \endcode 0055 * As you can see above you can also use this to write the highscores of a 0056 * single player, so the "best times" of a player. To write highscores for a 0057 * specific player in a specific level you will have to use a more complex way: 0058 * \code 0059 * QString group = QStringLiteral("%1_%2").arg(player).arg(level); 0060 * table->setGroup(group); 0061 * writeHighscore(table, player, level); 0062 * \endcode 0063 * 0064 * Also note that you MUST NOT mark the key or the group for translation! I.e. 0065 * don't use i18n() for the keys or groups! Here is the code to read the above 0066 * written entry: 0067 * \code 0068 * QString firstName = highscore->readEntry(0, "name"); 0069 * \endcode 0070 * Easy, what? 0071 * @author Andreas Beckermann <b_mann@gmx.de> 0072 */ 0073 class KDEGAMES_EXPORT KGameHighscore : public QObject 0074 { 0075 Q_OBJECT 0076 0077 public: 0078 /** 0079 * Constructor. 0080 * 0081 * @param forceLocal if true, the local highscore file is used even 0082 * when the configuration has been set to use a system-wide file. This 0083 * is convenient for converting highscores from legacy applications. 0084 * @param parent parent widget for this widget 0085 */ 0086 explicit KGameHighscore(bool forceLocal = true, QObject *parent = nullptr); 0087 0088 /** 0089 * Read the current state of the highscore file. Remember that when 0090 * it's not locked for writing, this file can change at any time. 0091 * (This method is only useful for a system-wide highscore file). 0092 */ 0093 void readCurrentConfig(); 0094 0095 /** 0096 * This method open the system-wide highscore file using the effective 0097 * group id of the game executable (which should be "games"). The 0098 * effective group id is completely dropped afterwards. 0099 * 0100 * Note: this method should be called in main() before creating a 0101 * KApplication and doing anything else (KApplication checks that the 0102 * program is not suid/sgid and will exit the program for security 0103 * reason if it is the case). 0104 */ 0105 static void init(const char *appname); 0106 0107 /** 0108 * Lock the system-wide highscore file for writing (does nothing and 0109 * return true if the local file is used). 0110 * You should perform writing without GUI interaction to avoid 0111 * blocking and don't forget to unlock the file as soon as possible 0112 * with writeAndUnlock(). 0113 * 0114 * If the config file cannot be locked, 0115 * the method waits for 1 second and, if it failed again, displays 0116 * a message box asking for retry or cancel. 0117 * @param widget used as the parent of the message box. 0118 * 0119 * @return false on error or if the config file is locked by another 0120 * process. In such case, the config stays read-only. 0121 */ 0122 bool lockForWriting(QWidget *widget = nullptr); 0123 0124 /** 0125 * Effectively write and unlock the system-wide highscore file 0126 * (@see lockForWriting). 0127 * If using a local highscore file, it will sync the config. 0128 */ 0129 void writeAndUnlock(); 0130 0131 /** 0132 * @return true if the highscore file is locked or if a local 0133 * file is used. 0134 */ 0135 bool isLocked() const; 0136 0137 /** 0138 * Destructor. 0139 * If necessary, write and unlock the highscore file. 0140 */ 0141 ~KGameHighscore() override; 0142 0143 /** 0144 * @param entry The number of the entry / the placing of the player 0145 * @param key A key for this entry. E.g. "name" for the name of the 0146 * player. Nearly the same as the usual keys in KConfig - but they 0147 * are prefixed with the entry number 0148 * @param value The value of this entry 0149 */ 0150 void writeEntry(int entry, const QString &key, const QString &value); 0151 0152 /** 0153 * This is an overloaded member function, provided for convenience. 0154 * It differs from the above function only in what argument(s) it accepts. 0155 */ 0156 void writeEntry(int entry, const QString &key, int value); 0157 0158 /** 0159 * This is an overloaded member function, provided for convenience. 0160 * It differs from the above function only in what argument(s) it accepts. 0161 * See KConfigBase documentation for allowed QVariant::Type. 0162 */ 0163 void writeEntry(int entry, const QString &key, const QVariant &value); 0164 0165 /** 0166 * Reads an entry from the highscore table. 0167 * @param entry The number of the entry / the placing to be read 0168 * @param key The key of the entry. E.g. "name" for the name of the 0169 * player. Nearly the same as the usual keys in KConfig - but they 0170 * are prefixed with the entry number 0171 * @param pDefault This will be used as default value if the key+pair 0172 * entry can't be found. 0173 * @return The value of this entry+key pair or pDefault if the entry+key 0174 * pair doesn't exist 0175 */ 0176 QString readEntry(int entry, const QString &key, const QString &pDefault = QString()) const; 0177 0178 /** 0179 * Read a numeric value. 0180 * @param entry The number of the entry / the placing to be read 0181 * @param key The key of the entry. E.g. "name" for the name of the 0182 * player. Nearly the same as the usual keys in KConfig - but they 0183 * are prefixed with the entry number 0184 * @param pDefault This will be used as default value if the key+pair 0185 * entry can't be found. 0186 * @return The value of this entry+key pair or pDefault if the entry+key 0187 * pair doesn't exist 0188 */ 0189 int readNumEntry(int entry, const QString &key, int pDefault = -1) const; 0190 0191 /** 0192 * Read a QVariant entry. 0193 * See KConfigBase documentation for allowed QVariant::Type. 0194 * 0195 * @return the value of this entry+key pair or pDefault if the entry+key 0196 * pair doesn't exist or 0197 */ 0198 QVariant readPropertyEntry(int entry, const QString &key, const QVariant &pDefault) const; 0199 0200 /** 0201 * @return True if the highscore table contains the entry/key pair, 0202 * otherwise false 0203 */ 0204 bool hasEntry(int entry, const QString &key) const; 0205 0206 /** 0207 * Reads a list of entries from the highscore table starting at 1 until 0208 * lastEntry. If an entry between those numbers doesn't exist the 0209 * function aborts reading even if after the missing entry is an 0210 * existing one. The first entry of the list is the first placing, the 0211 * last on is the last placing. 0212 * @return A list of the entries of this key. You could also call 0213 * readEntry(i, key) where i is from 1 to 20. Note that this function 0214 * depends on "1" as the first entry! 0215 * @param key The key of the entry. E.g. "name" for the name of the 0216 * player. Nearly the same as the usual keys in KConfig - but they 0217 * are prefixed with the entry number 0218 * @param lastEntry the last entry which will be includes into the list. 0219 * 1 will include a list with maximal 1 entry - 20 a list with maximal 0220 * 20 entries. If lastEntry is <= 0 then rading is only stopped when 0221 * when an entry does not exist. 0222 */ 0223 QStringList readList(const QString &key, int lastEntry = 20) const; 0224 0225 /** 0226 * Writes a list of entries to the highscore table. 0227 * 0228 * The first entry is prefixed with "1". Using this method is a short 0229 * way of calling writeEntry(i, key, list[i]) from i = 1 to 0230 * list.count() 0231 * @param key A key for the entry. E.g. "name" for the name of the 0232 * player. Nearly the same as the usual keys in KConfig - but they 0233 * are prefixed with the entry number 0234 * @param list The list of values 0235 */ 0236 void writeList(const QString &key, const QStringList &list); 0237 0238 /** 0239 * You can use this function to indicate whether KGameHighscore created a 0240 * highscore table before and - if not - read your old (non-KGameHighscore) 0241 * table instead. 0242 * This way you can safely read an old table and save it using 0243 * KGameHighscore without losing any data 0244 * @return Whether a highscore table exists. 0245 */ 0246 bool hasTable() const; 0247 0248 /** 0249 * Set the new highscore group. The group is being prefixed with 0250 * "KHighscore_" in the table. 0251 * @param groupname The new groupname. E.g. use "easy" for the easy 0252 * level of your game. If you use QString() (the default) the 0253 * default group is used. 0254 */ 0255 void setHighscoreGroup(const QString &groupname = QString()); 0256 0257 /** 0258 * Returns a list of group names without the KHighscore_ prexix. 0259 * E.g, "KHighscore", "KHighscore_Easy", "KHighscore_Medium" 0260 * will return "", "Easy", "Medium" 0261 * 0262 * @return A list of highscore groups. 0263 */ 0264 QStringList groupList() const; 0265 0266 /** 0267 * @return The currently used group. This doesn't contain the prefix 0268 * ("KHighscore_") but the same as setHighscoreGroup uses. The 0269 * default is QString() 0270 */ 0271 QString highscoreGroup() const; 0272 0273 protected: 0274 /** 0275 * @return A groupname to be used in KConfig. Used internally to 0276 * prefix the value from highscoreGroup() with "KHighscore_" 0277 */ 0278 QString group() const; 0279 0280 /** 0281 * @return A pointer to the KConfig object to be used. This is 0282 * either KGlobal::config() (default) or a KSimpleConfig object for 0283 * a system-wide highscore file. 0284 */ 0285 KConfig *config() const; 0286 0287 void init(bool forceLocal); 0288 0289 private: 0290 std::unique_ptr<class KGameHighscorePrivate> const d_ptr; 0291 Q_DECLARE_PRIVATE(KGameHighscore) 0292 }; 0293 0294 #endif