resourcedir.cpp
00001 /* 00002 This file is part of libkabc. 00003 Copyright (c) 2002 - 2003 Tobias Koenig <tokoe@kde.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 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 #include <errno.h> 00022 #include <signal.h> 00023 #include <sys/types.h> 00024 #include <sys/stat.h> 00025 #include <unistd.h> 00026 00027 #include <tqregexp.h> 00028 #include <tqtimer.h> 00029 #include <tqwidget.h> 00030 00031 #include <kapplication.h> 00032 #include <kconfig.h> 00033 #include <kdebug.h> 00034 #include <kgenericfactory.h> 00035 #include <kglobal.h> 00036 #include <klocale.h> 00037 #include <kstandarddirs.h> 00038 #include <kurlrequester.h> 00039 00040 #include "addressbook.h" 00041 #include "formatfactory.h" 00042 #include "resourcedirconfig.h" 00043 #include "stdaddressbook.h" 00044 #include "lock.h" 00045 00046 #include "resourcedir.h" 00047 00048 using namespace KABC; 00049 00050 extern "C" 00051 { 00052 void *init_kabc_dir() 00053 { 00054 return new KRES::PluginFactory<ResourceDir,ResourceDirConfig>(); 00055 } 00056 } 00057 00058 00059 ResourceDir::ResourceDir( const KConfig *config ) 00060 : Resource( config ), mAsynchronous( false ) 00061 { 00062 if ( config ) { 00063 init( config->readPathEntry( "FilePath", StdAddressBook::directoryName() ), 00064 config->readEntry( "FileFormat", "vcard" ) ); 00065 } else { 00066 init( StdAddressBook::directoryName(), "vcard" ); 00067 } 00068 } 00069 00070 ResourceDir::ResourceDir( const TQString &path, const TQString &format ) 00071 : Resource( 0 ), mAsynchronous( false ) 00072 { 00073 init( path, format ); 00074 } 00075 00076 void ResourceDir::init( const TQString &path, const TQString &format ) 00077 { 00078 mFormatName = format; 00079 00080 FormatFactory *factory = FormatFactory::self(); 00081 mFormat = factory->format( mFormatName ); 00082 00083 if ( !mFormat ) { 00084 mFormatName = "vcard"; 00085 mFormat = factory->format( mFormatName ); 00086 } 00087 00088 mLock = 0; 00089 00090 connect( &mDirWatch, TQT_SIGNAL( dirty(const TQString&) ), TQT_SLOT( pathChanged() ) ); 00091 connect( &mDirWatch, TQT_SIGNAL( created(const TQString&) ), TQT_SLOT( pathChanged() ) ); 00092 connect( &mDirWatch, TQT_SIGNAL( deleted(const TQString&) ), TQT_SLOT( pathChanged() ) ); 00093 00094 setPath( path ); 00095 } 00096 00097 ResourceDir::~ResourceDir() 00098 { 00099 delete mFormat; 00100 mFormat = 0; 00101 } 00102 00103 void ResourceDir::writeConfig( KConfig *config ) 00104 { 00105 Resource::writeConfig( config ); 00106 00107 if ( mPath == StdAddressBook::directoryName() ) 00108 config->deleteEntry( "FilePath" ); 00109 else 00110 config->writePathEntry( "FilePath", mPath ); 00111 00112 config->writeEntry( "FileFormat", mFormatName ); 00113 } 00114 00115 Ticket *ResourceDir::requestSaveTicket() 00116 { 00117 kdDebug(5700) << "ResourceDir::requestSaveTicket()" << endl; 00118 00119 if ( !addressBook() ) return 0; 00120 00121 delete mLock; 00122 mLock = new Lock( mPath ); 00123 00124 if ( mLock->lock() ) { 00125 addressBook()->emitAddressBookLocked(); 00126 } else { 00127 addressBook()->error( mLock->error() ); 00128 kdDebug(5700) << "ResourceFile::requestSaveTicket(): Unable to lock path '" 00129 << mPath << "': " << mLock->error() << endl; 00130 return 0; 00131 } 00132 00133 return createTicket( this ); 00134 } 00135 00136 void ResourceDir::releaseSaveTicket( Ticket *ticket ) 00137 { 00138 delete ticket; 00139 00140 delete mLock; 00141 mLock = 0; 00142 } 00143 00144 bool ResourceDir::doOpen() 00145 { 00146 TQDir dir( mPath ); 00147 if ( !dir.exists() ) { // no directory available 00148 return dir.mkdir( dir.path() ); 00149 } else { 00150 TQString testName = dir.entryList( TQDir::Files )[0]; 00151 if ( testName.isNull() || testName.isEmpty() ) // no file in directory 00152 return true; 00153 00154 TQFile file( mPath + "/" + testName ); 00155 if ( file.open( IO_ReadOnly ) ) 00156 return true; 00157 00158 if ( file.size() == 0 ) 00159 return true; 00160 00161 bool ok = mFormat->checkFormat( &file ); 00162 file.close(); 00163 return ok; 00164 } 00165 } 00166 00167 void ResourceDir::doClose() 00168 { 00169 } 00170 00171 bool ResourceDir::load() 00172 { 00173 kdDebug(5700) << "ResourceDir::load(): '" << mPath << "'" << endl; 00174 00175 mAsynchronous = false; 00176 00177 TQDir dir( mPath ); 00178 TQStringList files = dir.entryList( TQDir::Files ); 00179 00180 TQStringList::Iterator it; 00181 bool ok = true; 00182 for ( it = files.begin(); it != files.end(); ++it ) { 00183 TQFile file( mPath + "/" + (*it) ); 00184 00185 if ( !file.open( IO_ReadOnly ) ) { 00186 addressBook()->error( i18n( "Unable to open file '%1' for reading" ).arg( file.name() ) ); 00187 ok = false; 00188 continue; 00189 } 00190 00191 if ( !mFormat->loadAll( addressBook(), this, &file ) ) 00192 ok = false; 00193 00194 file.close(); 00195 } 00196 00197 return ok; 00198 } 00199 00200 bool ResourceDir::asyncLoad() 00201 { 00202 mAsynchronous = true; 00203 00204 bool ok = load(); 00205 if ( !ok ) 00206 emit loadingError( this, i18n( "Loading resource '%1' failed!" ) 00207 .arg( resourceName() ) ); 00208 else 00209 emit loadingFinished( this ); 00210 00211 return ok; 00212 } 00213 00214 bool ResourceDir::save( Ticket * ) 00215 { 00216 kdDebug(5700) << "ResourceDir::save(): '" << mPath << "'" << endl; 00217 00218 Addressee::Map::Iterator it; 00219 bool ok = true; 00220 00221 mDirWatch.stopScan(); 00222 00223 for ( it = mAddrMap.begin(); it != mAddrMap.end(); ++it ) { 00224 if ( !it.data().changed() ) 00225 continue; 00226 00227 TQFile file( mPath + "/" + (*it).uid() ); 00228 if ( !file.open( IO_WriteOnly ) ) { 00229 addressBook()->error( i18n( "Unable to open file '%1' for writing" ).arg( file.name() ) ); 00230 continue; 00231 } 00232 00233 mFormat->save( *it, &file ); 00234 00235 // mark as unchanged 00236 (*it).setChanged( false ); 00237 00238 file.close(); 00239 } 00240 00241 mDirWatch.startScan(); 00242 00243 return ok; 00244 } 00245 00246 bool ResourceDir::asyncSave( Ticket *ticket ) 00247 { 00248 bool ok = save( ticket ); 00249 if ( !ok ) 00250 emit savingError( this, i18n( "Saving resource '%1' failed!" ) 00251 .arg( resourceName() ) ); 00252 else 00253 emit savingFinished( this ); 00254 00255 return ok; 00256 } 00257 00258 void ResourceDir::setPath( const TQString &path ) 00259 { 00260 mDirWatch.stopScan(); 00261 if ( mDirWatch.contains( mPath ) ) 00262 mDirWatch.removeDir( mPath ); 00263 00264 mPath = path; 00265 mDirWatch.addDir( mPath, true ); 00266 mDirWatch.startScan(); 00267 } 00268 00269 TQString ResourceDir::path() const 00270 { 00271 return mPath; 00272 } 00273 00274 void ResourceDir::setFormat( const TQString &format ) 00275 { 00276 mFormatName = format; 00277 00278 if ( mFormat ) 00279 delete mFormat; 00280 00281 FormatFactory *factory = FormatFactory::self(); 00282 mFormat = factory->format( mFormatName ); 00283 } 00284 00285 TQString ResourceDir::format() const 00286 { 00287 return mFormatName; 00288 } 00289 00290 void ResourceDir::pathChanged() 00291 { 00292 if ( !addressBook() ) 00293 return; 00294 00295 clear(); 00296 if ( mAsynchronous ) 00297 asyncLoad(); 00298 else { 00299 load(); 00300 addressBook()->emitAddressBookChanged(); 00301 } 00302 } 00303 00304 void ResourceDir::removeAddressee( const Addressee& addr ) 00305 { 00306 TQFile::remove( mPath + "/" + addr.uid() ); 00307 mAddrMap.erase( addr.uid() ); 00308 } 00309 00310 #include "resourcedir.moc"