khighscore.cpp

00001 /*
00002     This file is part of the KDE games library
00003     Copyright (C) 2001 Andreas Beckermann (b_mann@gmx.de)
00004     Copyright (C) 2003 Nicolas Hadacek <hadacek@kde.org>
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License version 2 as published by the Free Software Foundation.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018     Boston, MA 02110-1301, USA.
00019 */
00020 /*
00021     $Id: khighscore.cpp 465369 2005-09-29 14:33:08Z mueller $
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)); // read-only
00105 
00106     // drop the effective gid
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         // lock the highscore file (it should exist)
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(); // write config
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"
KDE Home | KDE Accessibility Home | Description of Access Keys