You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegames/libkdegames/highscore/khighscore.cpp

263 lines
6.9 KiB

/*
This file is part of the KDE games library
Copyright (C) 2001 Andreas Beckermann (b_mann@gmx.de)
Copyright (C) 2003 Nicolas Hadacek <hadacek@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
/*
$Id$
*/
#include <config.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/file.h>
#include <kapplication.h>
#include <ksimpleconfig.h>
#include <kglobal.h>
#include <kstdguiitem.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kdebug.h>
#include <kstaticdeleter.h>
#include "khighscore.h"
#include "kconfigrawbackend.h"
#include "kfilelock.h"
#define GROUP "KHighscore"
class KHighscorePrivate
{
public:
KHighscorePrivate() {}
TQString group;
bool global;
};
KFileLock *KHighscore::_lock = 0;
KRawConfig *KHighscore::_config = 0;
static KStaticDeleter<KFileLock> lockSD;
static KStaticDeleter<KRawConfig> configSD;
KHighscore::KHighscore(TQObject* parent)
: TQObject(parent)
{
init(true);
}
KHighscore::KHighscore(bool forceLocal, TQObject* parent)
: TQObject(parent)
{
init(forceLocal);
}
void KHighscore::init(bool forceLocal)
{
d = new KHighscorePrivate;
#ifdef HIGHSCORE_DIRECTORY
d->global = !forceLocal;
if ( d->global && _lock==0 )
kdFatal(11002) << "KHighscore::init should be called before!!" << endl;
#else
d->global = false;
Q_UNUSED(forceLocal);
#endif
readCurrentConfig();
}
bool KHighscore::isLocked() const
{
return (d->global ? _lock->isLocked() : true);
}
void KHighscore::readCurrentConfig()
{
if ( d->global ) _config->reparseConfiguration();
}
void KHighscore::init(const char *appname)
{
#ifdef HIGHSCORE_DIRECTORY
const TQString filename = TQString::fromLocal8Bit("%1/%2.scores")
.arg(HIGHSCORE_DIRECTORY).arg(appname);
int fd = open(filename.local8Bit(), O_RDWR);
if ( fd<0 ) kdFatal(11002) << "cannot open global highscore file \""
<< filename << "\"" << endl;
lockSD.setObject(_lock, new KFileLock(fd));
configSD.setObject(_config, new KRawConfig(fd, true)); // read-only
// drop the effective gid
int gid = getgid();
setregid(gid, gid);
#else
Q_UNUSED(appname);
#endif
}
bool KHighscore::lockForWriting(TQWidget *widget)
{
if ( isLocked() ) return true;
bool first = true;
for (;;) {
kdDebug(11002) << "try locking" << endl;
// lock the highscore file (it should exist)
int result = _lock->lock();
bool ok = ( result==0 );
kdDebug(11002) << "locking system-wide highscore file res="
<< result << " (ok=" << ok << ")" << endl;
if (ok) {
readCurrentConfig();
_config->setReadOnly(false);
return true;
}
if ( !first ) {
KGuiItem item = KStdGuiItem::cont();
item.setText(i18n("Retry"));
int res = KMessageBox::warningContinueCancel(widget, i18n("Cannot access the highscore file. Another user is probably currently writing to it."), TQString(), item, "ask_lock_global_highscore_file");
if ( res==KMessageBox::Cancel ) break;
} else sleep(1);
first = false;
}
return false;
}
void KHighscore::writeAndUnlock()
{
if ( !d->global ) {
kapp->config()->sync();
return;
}
if ( !isLocked() ) return;
kdDebug(11002) << "unlocking" << endl;
_config->sync(); // write config
_lock->unlock();
_config->setReadOnly(true);
}
KHighscore::~KHighscore()
{
writeAndUnlock();
delete d;
}
KConfig* KHighscore::config() const
{
return (d->global ? _config : kapp->config());
}
void KHighscore::writeEntry(int entry, const TQString& key, const TQVariant& value)
{
Q_ASSERT( isLocked() );
KConfigGroupSaver cg(config(), group());
TQString confKey = TQString("%1_%2").arg(entry).arg(key);
cg.config()->writeEntry(confKey, value);
}
void KHighscore::writeEntry(int entry, const TQString& key, int value)
{
Q_ASSERT( isLocked() );
KConfigGroupSaver cg(config(), group());
TQString confKey = TQString("%1_%2").arg(entry).arg(key);
cg.config()->writeEntry(confKey, value);
}
void KHighscore::writeEntry(int entry, const TQString& key, const TQString &value)
{
Q_ASSERT (isLocked() );
KConfigGroupSaver cg(config(), group());
TQString confKey = TQString("%1_%2").arg(entry).arg(key);
cg.config()->writeEntry(confKey, value);
}
TQVariant KHighscore::readPropertyEntry(int entry, const TQString& key, const TQVariant& pDefault) const
{
KConfigGroupSaver cg(config(), group());
TQString confKey = TQString("%1_%2").arg(entry).arg(key);
return cg.config()->readPropertyEntry(confKey, pDefault);
}
TQString KHighscore::readEntry(int entry, const TQString& key, const TQString& pDefault) const
{
KConfigGroupSaver cg(config(), group());
TQString confKey = TQString("%1_%2").arg(entry).arg(key);
return cg.config()->readEntry(confKey, pDefault);
}
int KHighscore::readNumEntry(int entry, const TQString& key, int pDefault) const
{
KConfigGroupSaver cg(config(), group());
TQString confKey = TQString("%1_%2").arg(entry).arg(key);
return cg.config()->readNumEntry(confKey, pDefault);
}
bool KHighscore::hasEntry(int entry, const TQString& key) const
{
KConfigGroupSaver cg(config(), group());
TQString confKey = TQString("%1_%2").arg(entry).arg(key);
return cg.config()->hasKey(confKey);
}
TQStringList KHighscore::readList(const TQString& key, int lastEntry) const
{
TQStringList list;
for (int i = 1; hasEntry(i, key) && ((lastEntry > 0) ? (i <= lastEntry) : true); i++) {
list.append(readEntry(i, key));
}
return list;
}
void KHighscore::writeList(const TQString& key, const TQStringList& list)
{
for (int unsigned i = 1; i <= list.count(); i++) {
writeEntry(i, key, list[i - 1]);
}
}
void KHighscore::setHighscoreGroup(const TQString& group)
{
d->group = group;
}
const TQString& KHighscore::highscoreGroup() const
{
return d->group;
}
TQString KHighscore::group() const
{
if ( highscoreGroup().isNull() )
return (d->global ? TQString() : GROUP);
return (d->global ? highscoreGroup()
: TQString("%1_%2").arg(GROUP).arg(highscoreGroup()));
}
bool KHighscore::hasTable() const
{ return config()->hasGroup(group()); }
void KHighscore::sync()
{
writeAndUnlock();
}
#include "khighscore.moc"