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