khighscore.cpp
00001 /* 00002 This file is part of the TDE 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$ 00022 */ 00023 00024 #include <config.h> 00025 #include <fcntl.h> 00026 #include <unistd.h> 00027 #include <sys/file.h> 00028 00029 #include <tdeapplication.h> 00030 #include <ksimpleconfig.h> 00031 #include <tdeglobal.h> 00032 #include <kstdguiitem.h> 00033 #include <tdelocale.h> 00034 #include <tdemessagebox.h> 00035 #include <kdebug.h> 00036 #include <kstaticdeleter.h> 00037 00038 #include "khighscore.h" 00039 #include "tdeconfigrawbackend.h" 00040 #include "tdefilelock.h" 00041 00042 #define GROUP "KHighscore" 00043 00044 class KHighscorePrivate 00045 { 00046 public: 00047 KHighscorePrivate() {} 00048 00049 TQString 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(TQObject* parent) 00060 : TQObject(parent) 00061 { 00062 init(true); 00063 } 00064 00065 KHighscore::KHighscore(bool forceLocal, TQObject* parent) 00066 : TQObject(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 TQString filename = TQString::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(TQWidget *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."), TQString(), 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 TDEConfig* KHighscore::config() const 00164 { 00165 return (d->global ? _config : kapp->config()); 00166 } 00167 00168 void KHighscore::writeEntry(int entry, const TQString& key, const TQVariant& value) 00169 { 00170 Q_ASSERT( isLocked() ); 00171 TDEConfigGroupSaver cg(config(), group()); 00172 TQString confKey = TQString("%1_%2").arg(entry).arg(key); 00173 cg.config()->writeEntry(confKey, value); 00174 } 00175 00176 void KHighscore::writeEntry(int entry, const TQString& key, int value) 00177 { 00178 Q_ASSERT( isLocked() ); 00179 TDEConfigGroupSaver cg(config(), group()); 00180 TQString confKey = TQString("%1_%2").arg(entry).arg(key); 00181 cg.config()->writeEntry(confKey, value); 00182 } 00183 00184 void KHighscore::writeEntry(int entry, const TQString& key, const TQString &value) 00185 { 00186 Q_ASSERT (isLocked() ); 00187 TDEConfigGroupSaver cg(config(), group()); 00188 TQString confKey = TQString("%1_%2").arg(entry).arg(key); 00189 cg.config()->writeEntry(confKey, value); 00190 } 00191 00192 TQVariant KHighscore::readPropertyEntry(int entry, const TQString& key, const TQVariant& pDefault) const 00193 { 00194 TDEConfigGroupSaver cg(config(), group()); 00195 TQString confKey = TQString("%1_%2").arg(entry).arg(key); 00196 return cg.config()->readPropertyEntry(confKey, pDefault); 00197 } 00198 00199 TQString KHighscore::readEntry(int entry, const TQString& key, const TQString& pDefault) const 00200 { 00201 TDEConfigGroupSaver cg(config(), group()); 00202 TQString confKey = TQString("%1_%2").arg(entry).arg(key); 00203 return cg.config()->readEntry(confKey, pDefault); 00204 } 00205 00206 int KHighscore::readNumEntry(int entry, const TQString& key, int pDefault) const 00207 { 00208 TDEConfigGroupSaver cg(config(), group()); 00209 TQString confKey = TQString("%1_%2").arg(entry).arg(key); 00210 return cg.config()->readNumEntry(confKey, pDefault); 00211 } 00212 00213 bool KHighscore::hasEntry(int entry, const TQString& key) const 00214 { 00215 TDEConfigGroupSaver cg(config(), group()); 00216 TQString confKey = TQString("%1_%2").arg(entry).arg(key); 00217 return cg.config()->hasKey(confKey); 00218 } 00219 00220 TQStringList KHighscore::readList(const TQString& key, int lastEntry) const 00221 { 00222 TQStringList 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 TQString& key, const TQStringList& 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 TQString& group) 00237 { 00238 d->group = group; 00239 } 00240 00241 const TQString& KHighscore::highscoreGroup() const 00242 { 00243 return d->group; 00244 } 00245 00246 TQString KHighscore::group() const 00247 { 00248 if ( highscoreGroup().isNull() ) 00249 return (d->global ? TQString() : GROUP); 00250 return (d->global ? highscoreGroup() 00251 : TQString("%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"