/*
This file is part of the TDE 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"