KDEGames

khighscore.cpp
1 /*
2  This file is part of the KDE games library
3  SPDX-FileCopyrightText: 2001 Andreas Beckermann <[email protected]>
4  SPDX-FileCopyrightText: 2003 Nicolas Hadacek <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-only
7 */
8 
9 #include "khighscore.h"
10 
11 // own
12 #include <config-highscore.h>
13 // KF
14 #include <KSharedConfig>
15 #include <KConfig>
16 #include <KStandardGuiItem>
17 #include <KMessageBox>
18 #include <KLocalizedString>
19 #include <KConfigGroup>
20 // Qt
21 #include <QFile>
22 #include <QLockFile>
23 #include <QGlobalStatic>
24 
25 #ifndef WIN32
26 #include <unistd.h> // sleep
27 #else
28 #include <qt_windows.h>
29 #endif
30 
31 #define GROUP "KHighscore"
32 
33 Q_LOGGING_CATEGORY(GAMES_HIGHSCORE, "org.kde.games.highscore", QtWarningMsg)
34 
35 class KHighscorePrivate
36 {
37 public:
38  KHighscorePrivate() {}
39 
40  QString group;
41  bool global;
42 };
43 
44 class KHighscoreLockedConfig
45 {
46 public:
47  ~KHighscoreLockedConfig();
48  QLockFile *lock;
49  KConfig *config;
50 };
51 
52 KHighscoreLockedConfig::~KHighscoreLockedConfig()
53 {
54  delete lock;
55  delete config;
56 }
57 
58 Q_GLOBAL_STATIC(KHighscoreLockedConfig, lockedConfig)
59 
60 KHighscore::KHighscore(bool forceLocal, QObject* parent)
61  : QObject(parent), d(new KHighscorePrivate)
62 {
63  init(forceLocal);
64 }
65 
66 void KHighscore::init(bool forceLocal)
67 {
68 #ifdef HIGHSCORE_DIRECTORY
69  d->global = !forceLocal;
70  if ( d->global && lockedConfig->lock==0 ) //If we're doing global highscores but not KFileLock has been set up yet
71  {
72  qCWarning(GAMES_HIGHSCORE) << "KHighscore::init should be called before!!";
73  abort();
74  }
75 #else
76  d->global = false;
77  Q_UNUSED(forceLocal);
78 #endif
79  readCurrentConfig();
80 }
81 
83 {
84  return (d->global ? lockedConfig->lock->isLocked() : true);
85 }
86 
88 {
89  if ( d->global ) lockedConfig->config->reparseConfiguration();
90 }
91 
92 void KHighscore::init(const char *appname)
93 {
94 #ifdef HIGHSCORE_DIRECTORY
95  const QString filename = QString::fromLocal8Bit("%1/%2.scores")
96  .arg(HIGHSCORE_DIRECTORY).arg(appname);
97 
98  //int fd = fopen(filename.toLocal8Bit(), O_RDWR);
99  /*QFile file(filename);
100  if ( !file.open(QIODevice::ReadWrite) )
101  {
102  qCWarning(GAMES_HIGHSCORE) << "cannot open global highscore file \""
103  << filename << "\"";
104  abort();
105  }*/
106 
107  /*if (!(QFile::permissions(filename) & QFile::WriteOwner))
108  {
109  qCWarning(GAMES_HIGHSCORE) << "cannot write to global highscore file \""
110  << filename << "\"";
111  abort();
112  }*/
113 
114  qCDebug(GAMES_HIGHSCORE) << "Global highscore file \"" << filename << "\"";
115  lockedConfig->lock = new QLockFile(filename);
116  lockedConfig->config = new KConfig(filename, KConfig::NoGlobals); // read-only (matt-?)
117 
118  // drop the effective gid
119 #ifdef __GNUC__
120  #warning not portable yet. Unix only. Actually it does not even work there yet.
121 #endif
122  int gid = getgid();
123  setregid(gid, gid);
124 #else
125  Q_UNUSED(appname);
126 #endif
127 }
128 
130 {
131  if ( isLocked() ) return true;
132 
133  bool first = true;
134  for (;;) {
135  qCDebug(GAMES_HIGHSCORE) << "try locking";
136  // lock the highscore file (it should exist)
137  int result = lockedConfig->lock->lock();
138  bool ok = ( result==0 );
139  qCDebug(GAMES_HIGHSCORE) << "locking system-wide highscore file res="
140  << result << " (ok=" << ok << ")";
141  if (ok) {
142  readCurrentConfig();
143  return true;
144  }
145 
146  if ( !first ) {
148  item.setText(i18n("Retry"));
149  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" ));
150  if ( res==KMessageBox::Cancel ) break;
151  } else {
152 #ifdef WIN32
153  Sleep(1000);
154 #else
155  sleep(1);
156 #endif
157  }
158  first = false;
159  }
160  return false;
161 }
162 
164 {
165  if ( !d->global ) {
166  KSharedConfig::openConfig()->sync();
167  return;
168  }
169  if ( !isLocked() ) return;
170 
171  qCDebug(GAMES_HIGHSCORE) << "unlocking";
172  lockedConfig->config->sync(); // write config
173  lockedConfig->lock->unlock();
174 }
175 
177 {
178  writeAndUnlock();
179 }
180 
182 {
183  return (d->global ? lockedConfig->config : static_cast<KConfig*>(KSharedConfig::openConfig().data()));
184 }
185 
186 void KHighscore::writeEntry(int entry, const QString& key, const QVariant& value)
187 {
188  Q_ASSERT( isLocked() );
189  KConfigGroup cg(config(), group());
190  QString confKey = QStringLiteral( "%1_%2").arg(entry).arg(key);
191  cg.writeEntry(confKey, value);
192 }
193 
194 void KHighscore::writeEntry(int entry, const QString& key, int value)
195 {
196  Q_ASSERT( isLocked() );
197  KConfigGroup cg(config(), group());
198  QString confKey = QStringLiteral( "%1_%2").arg(entry).arg(key);
199  cg.writeEntry(confKey, value);
200 }
201 
202 void KHighscore::writeEntry(int entry, const QString& key, const QString &value)
203 {
204  Q_ASSERT (isLocked() );
205  KConfigGroup cg(config(), group());
206  QString confKey = QStringLiteral( "%1_%2").arg(entry).arg(key);
207  cg.writeEntry(confKey, value);
208 }
209 
210 QVariant KHighscore::readPropertyEntry(int entry, const QString& key, const QVariant& pDefault) const
211 {
212  KConfigGroup cg(config(), group());
213  QString confKey = QStringLiteral( "%1_%2").arg(entry).arg(key);
214  return cg.readEntry(confKey, pDefault);
215 }
216 
217 QString KHighscore::readEntry(int entry, const QString& key, const QString& pDefault) const
218 {
219  KConfigGroup cg(config(), group());
220  QString confKey = QStringLiteral( "%1_%2").arg(entry).arg(key);
221  return cg.readEntry(confKey, pDefault);
222 }
223 
224 int KHighscore::readNumEntry(int entry, const QString& key, int pDefault) const
225 {
226  KConfigGroup cg(config(), group());
227  QString confKey = QStringLiteral( "%1_%2").arg(entry).arg(key);
228  return cg.readEntry(confKey, pDefault);
229 }
230 
231 bool KHighscore::hasEntry(int entry, const QString& key) const
232 {
233  KConfigGroup cg(config(), group());
234  QString confKey = QStringLiteral( "%1_%2").arg(entry).arg(key);
235  return cg.hasKey(confKey);
236 }
237 
238 QStringList KHighscore::readList(const QString& key, int lastEntry) const
239 {
240  QStringList list;
241  for (int i = 1; hasEntry(i, key) && ((lastEntry > 0) ? (i <= lastEntry) : true); i++) {
242  list.append(readEntry(i, key));
243  }
244  return list;
245 }
246 
247 void KHighscore::writeList(const QString& key, const QStringList& list)
248 {
249  for (int i = 1; i <= list.count(); i++) {
250  writeEntry(i, key, list[i - 1]);
251  }
252 }
253 
255 {
256  d->group = group;
257 }
258 
260 {
261  return d->group;
262 }
263 
265 {
266  const QStringList groupList = config()->groupList();
267  QStringList highscoreGroupList;
268  for (QString group : groupList) {
269  if(group.contains( QLatin1String( "KHighscore")) ) //If it's one of _our_ groups (KHighscore or KHighscore_xxx)
270  {
271  if(group == QLatin1String( "KHighscore" ))
272  group.remove( QStringLiteral( "KHighscore" )); //Set to blank
273  else
274  group.remove( QStringLiteral( "KHighscore_" )); //Remove the KHighscore_ prefix
275  highscoreGroupList << group;
276  }
277  }
278 
279  return highscoreGroupList;
280 }
281 
283 {
284  if (highscoreGroup().isEmpty())
285  return (d->global ? QString() : QStringLiteral(GROUP));
286  return (d->global ?
287  highscoreGroup() :
288  QStringLiteral( "%1_%2").arg( QStringLiteral(GROUP), highscoreGroup()));
289 }
290 
292 {
293  return config()->hasGroup(group());
294 }
295 
296 
Class for managing highscore tables.
Definition: khighscore.h:74
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:238
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:129
void setHighscoreGroup(const QString &groupname=QLatin1String(""))
Set the new highscore group.
Definition: khighscore.cpp:254
bool isLocked() const
Definition: khighscore.cpp:82
void writeEntry(const QString &key, const QVariant &value, WriteConfigFlags pFlags=Normal)
Q_GLOBAL_STATIC(Internal::StaticControl, s_instance) class ControlPrivate
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:224
KSharedConfigPtr config()
QString group() const
Definition: khighscore.cpp:282
bool hasEntry(int entry, const QString &key) const
Definition: khighscore.cpp:231
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:92
QStringList groupList() const
Returns a list of group names without the KHighscore_ prexix.
Definition: khighscore.cpp:264
bool hasTable() const
You can use this function to indicate whether KHighscore created a highscore table before and - if no...
Definition: khighscore.cpp:291
void writeAndUnlock()
Effectively write and unlock the system-wide highscore file (.
Definition: khighscore.cpp:163
QVariant readPropertyEntry(int entry, const QString &key, const QVariant &pDefault) const
Read a QVariant entry.
Definition: khighscore.cpp:210
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:259
QString readEntry(int entry, const QString &key, const QString &pDefault=QLatin1String("")) const
Reads an entry from the highscore table.
Definition: khighscore.cpp:217
void writeList(const QString &key, const QStringList &list)
Writes a list of entries to the highscore table.
Definition: khighscore.cpp:247
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:87
KConfig * config() const
Definition: khighscore.cpp:181
~KHighscore() override
Destructor.
Definition: khighscore.cpp:176
T readEntry(const QString &key, const T &aDefault) const
void writeEntry(int entry, const QString &key, const QString &value)
Definition: khighscore.cpp:202
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Dec 7 2021 22:34:15 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.