KDEGames

khighscore.cpp
1 /*
2  This file is part of the KDE games library
3  Copyright (C) 2001 Andreas Beckermann ([email protected])
4  Copyright (C) 2003 Nicolas Hadacek <[email protected]>
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Library General Public
8  License version 2 as published by the Free Software Foundation.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #include "khighscore.h"
22 #include <config-highscore.h>
23 
24 #include <KSharedConfig>
25 #include <KConfig>
26 #include <KStandardGuiItem>
27 #include <KMessageBox>
28 #include <KLocalizedString>
29 #include <KConfigGroup>
30 
31 #include <QFile>
32 #include <QLockFile>
33 #include <QGlobalStatic>
34 
35 #ifndef WIN32
36 #include <unistd.h> // sleep
37 #else
38 #include <qt_windows.h>
39 #endif
40 
41 #define GROUP "KHighscore"
42 
43 Q_LOGGING_CATEGORY(GAMES_HIGHSCORE, "org.kde.games.highscore", QtWarningMsg)
44 
45 class KHighscore::KHighscorePrivate
46 {
47 public:
48  KHighscorePrivate() {}
49 
50  QString group;
51  bool global;
52 };
53 
54 class KHighscoreLockedConfig
55 {
56 public:
57  ~KHighscoreLockedConfig();
58  QLockFile *lock;
59  KConfig *config;
60 };
61 
62 KHighscoreLockedConfig::~KHighscoreLockedConfig()
63 {
64  delete lock;
65  delete config;
66 }
67 
68 Q_GLOBAL_STATIC(KHighscoreLockedConfig, lockedConfig)
69 
70 KHighscore::KHighscore(bool forceLocal, QObject* parent)
71  : QObject(parent), d(new KHighscorePrivate)
72 {
73  init(forceLocal);
74 }
75 
76 void KHighscore::init(bool forceLocal)
77 {
78 #ifdef HIGHSCORE_DIRECTORY
79  d->global = !forceLocal;
80  if ( d->global && lockedConfig->lock==0 ) //If we're doing global highscores but not KFileLock has been set up yet
81  {
82  qCWarning(GAMES_HIGHSCORE) << "KHighscore::init should be called before!!";
83  abort();
84  }
85 #else
86  d->global = false;
87  Q_UNUSED(forceLocal);
88 #endif
89  readCurrentConfig();
90 }
91 
93 {
94  return (d->global ? lockedConfig->lock->isLocked() : true);
95 }
96 
98 {
99  if ( d->global ) lockedConfig->config->reparseConfiguration();
100 }
101 
102 void KHighscore::init(const char *appname)
103 {
104 #ifdef HIGHSCORE_DIRECTORY
105  const QString filename = QString::fromLocal8Bit("%1/%2.scores")
106  .arg(HIGHSCORE_DIRECTORY).arg(appname);
107 
108  //int fd = fopen(filename.toLocal8Bit(), O_RDWR);
109  /*QFile file(filename);
110  if ( !file.open(QIODevice::ReadWrite) )
111  {
112  qCWarning(GAMES_HIGHSCORE) << "cannot open global highscore file \""
113  << filename << "\"";
114  abort();
115  }*/
116 
117  /*if (!(QFile::permissions(filename) & QFile::WriteOwner))
118  {
119  qCWarning(GAMES_HIGHSCORE) << "cannot write to global highscore file \""
120  << filename << "\"";
121  abort();
122  }*/
123 
124  qCDebug(GAMES_HIGHSCORE) << "Global highscore file \"" << filename << "\"";
125  lockedConfig->lock = new QLockFile(filename);
126  lockedConfig->config = new KConfig(filename, KConfig::NoGlobals); // read-only (matt-?)
127 
128  // drop the effective gid
129 #ifdef __GNUC__
130  #warning not portable yet. Unix only. Actually it does not even work there yet.
131 #endif
132  int gid = getgid();
133  setregid(gid, gid);
134 #else
135  Q_UNUSED(appname);
136 #endif
137 }
138 
140 {
141  if ( isLocked() ) return true;
142 
143  bool first = true;
144  for (;;) {
145  qCDebug(GAMES_HIGHSCORE) << "try locking";
146  // lock the highscore file (it should exist)
147  int result = lockedConfig->lock->lock();
148  bool ok = ( result==0 );
149  qCDebug(GAMES_HIGHSCORE) << "locking system-wide highscore file res="
150  << result << " (ok=" << ok << ")";
151  if (ok) {
152  readCurrentConfig();
153  return true;
154  }
155 
156  if ( !first ) {
158  item.setText(i18n("Retry"));
159  int res = KMessageBox::warningContinueCancel(widget, i18n("Cannot access the highscore file. Another user is probably currently writing to it."), QString(), item, KStandardGuiItem::cancel(), QStringLiteral( "ask_lock_global_highscore_file" ));
160  if ( res==KMessageBox::Cancel ) break;
161  } else {
162 #ifdef WIN32
163  Sleep(1000);
164 #else
165  sleep(1);
166 #endif
167  }
168  first = false;
169  }
170  return false;
171 }
172 
174 {
175  if ( !d->global ) {
176  KSharedConfig::openConfig()->sync();
177  return;
178  }
179  if ( !isLocked() ) return;
180 
181  qCDebug(GAMES_HIGHSCORE) << "unlocking";
182  lockedConfig->config->sync(); // write config
183  lockedConfig->lock->unlock();
184 }
185 
187 {
188  writeAndUnlock();
189  delete d;
190 }
191 
193 {
194  return (d->global ? lockedConfig->config : static_cast<KConfig*>(KSharedConfig::openConfig().data()));
195 }
196 
197 void KHighscore::writeEntry(int entry, const QString& key, const QVariant& value)
198 {
199  Q_ASSERT( isLocked() );
200  KConfigGroup cg(config(), group());
201  QString confKey = QStringLiteral( "%1_%2").arg(entry).arg(key);
202  cg.writeEntry(confKey, value);
203 }
204 
205 void KHighscore::writeEntry(int entry, const QString& key, int value)
206 {
207  Q_ASSERT( isLocked() );
208  KConfigGroup cg(config(), group());
209  QString confKey = QStringLiteral( "%1_%2").arg(entry).arg(key);
210  cg.writeEntry(confKey, value);
211 }
212 
213 void KHighscore::writeEntry(int entry, const QString& key, const QString &value)
214 {
215  Q_ASSERT (isLocked() );
216  KConfigGroup cg(config(), group());
217  QString confKey = QStringLiteral( "%1_%2").arg(entry).arg(key);
218  cg.writeEntry(confKey, value);
219 }
220 
221 QVariant KHighscore::readPropertyEntry(int entry, const QString& key, const QVariant& pDefault) const
222 {
223  KConfigGroup cg(config(), group());
224  QString confKey = QStringLiteral( "%1_%2").arg(entry).arg(key);
225  return cg.readEntry(confKey, pDefault);
226 }
227 
228 QString KHighscore::readEntry(int entry, const QString& key, const QString& pDefault) const
229 {
230  KConfigGroup cg(config(), group());
231  QString confKey = QStringLiteral( "%1_%2").arg(entry).arg(key);
232  return cg.readEntry(confKey, pDefault);
233 }
234 
235 int KHighscore::readNumEntry(int entry, const QString& key, int pDefault) const
236 {
237  KConfigGroup cg(config(), group());
238  QString confKey = QStringLiteral( "%1_%2").arg(entry).arg(key);
239  return cg.readEntry(confKey, pDefault);
240 }
241 
242 bool KHighscore::hasEntry(int entry, const QString& key) const
243 {
244  KConfigGroup cg(config(), group());
245  QString confKey = QStringLiteral( "%1_%2").arg(entry).arg(key);
246  return cg.hasKey(confKey);
247 }
248 
249 QStringList KHighscore::readList(const QString& key, int lastEntry) const
250 {
251  QStringList list;
252  for (int i = 1; hasEntry(i, key) && ((lastEntry > 0) ? (i <= lastEntry) : true); i++) {
253  list.append(readEntry(i, key));
254  }
255  return list;
256 }
257 
258 void KHighscore::writeList(const QString& key, const QStringList& list)
259 {
260  for (int i = 1; i <= list.count(); i++) {
261  writeEntry(i, key, list[i - 1]);
262  }
263 }
264 
266 {
267  d->group = group;
268 }
269 
271 {
272  return d->group;
273 }
274 
276 {
277  const QStringList groupList = config()->groupList();
278  QStringList highscoreGroupList;
279  for (QString group : groupList) {
280  if(group.contains( QLatin1String( "KHighscore")) ) //If it's one of _our_ groups (KHighscore or KHighscore_xxx)
281  {
282  if(group == QLatin1String( "KHighscore" ))
283  group.remove( QStringLiteral( "KHighscore" )); //Set to blank
284  else
285  group.remove( QStringLiteral( "KHighscore_" )); //Remove the KHighscore_ prefix
286  highscoreGroupList << group;
287  }
288  }
289 
290  return highscoreGroupList;
291 }
292 
294 {
295  if (highscoreGroup().isEmpty())
296  return (d->global ? QString() : QStringLiteral(GROUP));
297  return (d->global ?
298  highscoreGroup() :
299  QStringLiteral( "%1_%2").arg( QStringLiteral( GROUP )).arg(highscoreGroup()));
300 }
301 
303 {
304  return config()->hasGroup(group());
305 }
306 
307 
Class for managing highscore tables.
Definition: khighscore.h:83
QStringList readList(const QString &key, int lastEntry=20) const
Reads a list of entries from the highscore table starting at 1 until lastEntry.
Definition: khighscore.cpp:249
~KHighscore()
Destructor.
Definition: khighscore.cpp:186
bool lockForWriting(QWidget *widget=nullptr)
Lock the system-wide highscore file for writing (does nothing and return true if the local file is us...
Definition: khighscore.cpp:139
void setHighscoreGroup(const QString &groupname=QLatin1String(""))
Set the new highscore group.
Definition: khighscore.cpp:265
bool isLocked() const
Definition: khighscore.cpp:92
void writeEntry(const QString &key, const QVariant &value, WriteConfigFlags pFlags=Normal)
KGuiItem cont()
KGuiItem cancel()
void setText(const QString &text)
int readNumEntry(int entry, const QString &key, int pDefault=-1) const
Read a numeric value.
Definition: khighscore.cpp:235
KSharedConfigPtr config()
QString group() const
Definition: khighscore.cpp:293
bool hasEntry(int entry, const QString &key) const
Definition: khighscore.cpp:242
int count(const T &value) const const
QString fromLocal8Bit(const char *str, int size)
void append(const T &value)
ButtonCode warningContinueCancel(QWidget *parent, const QString &text, const QString &caption=QString(), const KGuiItem &buttonContinue=KStandardGuiItem::cont(), const KGuiItem &buttonCancel=KStandardGuiItem::cancel(), const QString &dontAskAgainName=QString(), Options options=Notify)
static void init(const char *appname)
This method open the system-wide highscore file using the effective group id of the game executable (...
Definition: khighscore.cpp:102
QStringList groupList() const
Returns a list of group names without the KHighscore_ prexix.
Definition: khighscore.cpp:275
bool hasTable() const
You can use this function to indicate whether KHighscore created a highscore table before and - if no...
Definition: khighscore.cpp:302
void writeAndUnlock()
Effectively write and unlock the system-wide highscore file (.
Definition: khighscore.cpp:173
QVariant readPropertyEntry(int entry, const QString &key, const QVariant &pDefault) const
Read a QVariant entry.
Definition: khighscore.cpp:221
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
QCA_EXPORT void init()
bool hasKey(const QString &key) const
QString i18n(const char *text, const TYPE &arg...)
QString highscoreGroup() const
Definition: khighscore.cpp:270
QString readEntry(int entry, const QString &key, const QString &pDefault=QLatin1String("")) const
Reads an entry from the highscore table.
Definition: khighscore.cpp:228
void writeList(const QString &key, const QStringList &list)
Writes a list of entries to the highscore table.
Definition: khighscore.cpp:258
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
void readCurrentConfig()
Read the current state of the highscore file.
Definition: khighscore.cpp:97
KConfig * config() const
Definition: khighscore.cpp:192
T readEntry(const QString &key, const T &aDefault) const
void writeEntry(int entry, const QString &key, const QString &value)
Definition: khighscore.cpp:213
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Thu Nov 26 2020 22:36:18 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.