00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "khighscore.h"
00022 #include <config-highscore.h>
00023
00024 #include <KConfig>
00025 #include <KGlobal>
00026 #include <KStandardGuiItem>
00027 #include <KLocale>
00028 #include <KMessageBox>
00029 #include <KDebug>
00030 #include <KLockFile>
00031 #include <KConfigGroup>
00032
00033 #include <QtCore/QFile>
00034
00035 #include <unistd.h>
00036
00037 #define GROUP "KHighscore"
00038
00039 class KHighscore::KHighscorePrivate
00040 {
00041 public:
00042 KHighscorePrivate() {}
00043
00044 QString group;
00045 bool global;
00046 };
00047
00048 class KHighscoreLockedConfig
00049 {
00050 public:
00051 ~KHighscoreLockedConfig();
00052 KLockFile *lock;
00053 KConfig *config;
00054 };
00055
00056 KHighscoreLockedConfig::~KHighscoreLockedConfig()
00057 {
00058 delete lock;
00059 delete config;
00060 }
00061
00062 K_GLOBAL_STATIC(KHighscoreLockedConfig, lockedConfig)
00063
00064 KHighscore::KHighscore(bool forceLocal, QObject* parent)
00065 : QObject(parent), d(new KHighscorePrivate)
00066 {
00067 init(forceLocal);
00068 }
00069
00070 void KHighscore::init(bool forceLocal)
00071 {
00072 #ifdef HIGHSCORE_DIRECTORY
00073 d->global = !forceLocal;
00074 if ( d->global && lockedConfig->lock==0 )
00075 kFatal(11002) << "KHighscore::init should be called before!!";
00076 #else
00077 d->global = false;
00078 Q_UNUSED(forceLocal);
00079 #endif
00080 readCurrentConfig();
00081 }
00082
00083 bool KHighscore::isLocked() const
00084 {
00085 return (d->global ? lockedConfig->lock->isLocked() : true);
00086 }
00087
00088 void KHighscore::readCurrentConfig()
00089 {
00090 if ( d->global ) lockedConfig->config->reparseConfiguration();
00091 }
00092
00093 void KHighscore::init(const char *appname)
00094 {
00095 #ifdef HIGHSCORE_DIRECTORY
00096 const QString filename = QString::fromLocal8Bit("%1/%2.scores")
00097 .arg(HIGHSCORE_DIRECTORY).arg(appname);
00098
00099
00100
00101
00102
00103
00104 kDebug() << "Global highscore file \"" << filename << "\"";
00105 lockedConfig->lock = new KLockFile(filename);
00106 lockedConfig->config = new KConfig(filename, KConfig::NoGlobals);
00107
00108
00109 #ifdef __GNUC__
00110 #warning not portable yet. Unix only. Actually it does not even work there yet.
00111 #endif
00112 int gid = getgid();
00113 setregid(gid, gid);
00114 #else
00115 Q_UNUSED(appname);
00116 #endif
00117 }
00118
00119 bool KHighscore::lockForWriting(QWidget *widget)
00120 {
00121 if ( isLocked() ) return true;
00122
00123 bool first = true;
00124 for (;;) {
00125 kDebug(11002) << "try locking";
00126
00127 int result = lockedConfig->lock->lock();
00128 bool ok = ( result==0 );
00129 kDebug(11002) << "locking system-wide highscore file res="
00130 << result << " (ok=" << ok << ")";
00131 if (ok) {
00132 readCurrentConfig();
00133 return true;
00134 }
00135
00136 if ( !first ) {
00137 KGuiItem item = KStandardGuiItem::cont();
00138 item.setText(i18n("Retry"));
00139 int res = KMessageBox::warningContinueCancel(widget, i18n("Cannot access the highscore file. Another user is probably currently writing to it."), QString(), item, KStandardGuiItem::cancel(), "ask_lock_global_highscore_file");
00140 if ( res==KMessageBox::Cancel ) break;
00141 } else sleep(1);
00142 first = false;
00143 }
00144 return false;
00145 }
00146
00147 void KHighscore::writeAndUnlock()
00148 {
00149 if ( !d->global ) {
00150 KGlobal::config()->sync();
00151 return;
00152 }
00153 if ( !isLocked() ) return;
00154
00155 kDebug(11002) << "unlocking";
00156 lockedConfig->config->sync();
00157 lockedConfig->lock->unlock();
00158 }
00159
00160 KHighscore::~KHighscore()
00161 {
00162 writeAndUnlock();
00163 delete d;
00164 }
00165
00166 KConfig* KHighscore::config() const
00167 {
00168 return (d->global ? lockedConfig->config : static_cast<KConfig*>(KGlobal::config().data()));
00169 }
00170
00171 void KHighscore::writeEntry(int entry, const QString& key, const QVariant& value)
00172 {
00173 Q_ASSERT( isLocked() );
00174 KConfigGroup cg(config(), group());
00175 QString confKey = QString("%1_%2").arg(entry).arg(key);
00176 cg.writeEntry(confKey, value);
00177 }
00178
00179 void KHighscore::writeEntry(int entry, const QString& key, int value)
00180 {
00181 Q_ASSERT( isLocked() );
00182 KConfigGroup cg(config(), group());
00183 QString confKey = QString("%1_%2").arg(entry).arg(key);
00184 cg.writeEntry(confKey, value);
00185 }
00186
00187 void KHighscore::writeEntry(int entry, const QString& key, const QString &value)
00188 {
00189 Q_ASSERT (isLocked() );
00190 KConfigGroup cg(config(), group());
00191 QString confKey = QString("%1_%2").arg(entry).arg(key);
00192 cg.writeEntry(confKey, value);
00193 }
00194
00195 QVariant KHighscore::readPropertyEntry(int entry, const QString& key, const QVariant& pDefault) const
00196 {
00197 KConfigGroup cg(config(), group());
00198 QString confKey = QString("%1_%2").arg(entry).arg(key);
00199 return cg.readEntry(confKey, pDefault);
00200 }
00201
00202 QString KHighscore::readEntry(int entry, const QString& key, const QString& pDefault) const
00203 {
00204 KConfigGroup cg(config(), group());
00205 QString confKey = QString("%1_%2").arg(entry).arg(key);
00206 return cg.readEntry(confKey, pDefault);
00207 }
00208
00209 int KHighscore::readNumEntry(int entry, const QString& key, int pDefault) const
00210 {
00211 KConfigGroup cg(config(), group());
00212 QString confKey = QString("%1_%2").arg(entry).arg(key);
00213 return cg.readEntry(confKey, pDefault);
00214 }
00215
00216 bool KHighscore::hasEntry(int entry, const QString& key) const
00217 {
00218 KConfigGroup cg(config(), group());
00219 QString confKey = QString("%1_%2").arg(entry).arg(key);
00220 return cg.hasKey(confKey);
00221 }
00222
00223 QStringList KHighscore::readList(const QString& key, int lastEntry) const
00224 {
00225 QStringList list;
00226 for (int i = 1; hasEntry(i, key) && ((lastEntry > 0) ? (i <= lastEntry) : true); i++) {
00227 list.append(readEntry(i, key));
00228 }
00229 return list;
00230 }
00231
00232 void KHighscore::writeList(const QString& key, const QStringList& list)
00233 {
00234 for (int i = 1; i <= list.count(); i++) {
00235 writeEntry(i, key, list[i - 1]);
00236 }
00237 }
00238
00239 void KHighscore::setHighscoreGroup(const QString& group)
00240 {
00241 d->group = group;
00242 }
00243
00244 QString KHighscore::highscoreGroup() const
00245 {
00246 return d->group;
00247 }
00248
00249 QStringList KHighscore::groupList() const
00250 {
00251 QStringList groupList = config()->groupList();
00252 QStringList highscoreGroupList;
00253 foreach (QString group, groupList)
00254 {
00255 if(group.contains("KHighscore"))
00256 {
00257 if(group == "KHighscore")
00258 group.replace("KHighscore", QString());
00259 else
00260 group.replace("KHighscore_", QString());
00261 highscoreGroupList << group;
00262 }
00263 }
00264
00265 return highscoreGroupList;
00266 }
00267
00268 QString KHighscore::group() const
00269 {
00270 if (highscoreGroup().isEmpty())
00271 return (d->global ? QString() : QString::fromLatin1(GROUP));
00272 return (d->global ?
00273 highscoreGroup() :
00274 QString("%1_%2").arg(GROUP).arg(highscoreGroup()));
00275 }
00276
00277 bool KHighscore::hasTable() const
00278 {
00279 return config()->hasGroup(group());
00280 }
00281
00282 #include "khighscore.moc"