libkcal

resourcelocaldir.cpp
00001 /*
00002     This file is part of libkcal.
00003 
00004     Copyright (c) 2003 Cornelius Schumacher <schumacher@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 as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public License
00017     along with this library; see the file COPYING.LIB.  If not, write to
00018     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019     Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include <typeinfo>
00023 #include <stdlib.h>
00024 
00025 #include <tqdatetime.h>
00026 #include <tqfileinfo.h>
00027 #include <tqstring.h>
00028 #include <tqptrlist.h>
00029 
00030 #include <kdebug.h>
00031 #include <klocale.h>
00032 #include <kurl.h>
00033 #include <kconfig.h>
00034 #include <kstandarddirs.h>
00035 
00036 #include "vcaldrag.h"
00037 #include "vcalformat.h"
00038 #include "icalformat.h"
00039 #include "exceptions.h"
00040 #include "calendarlocal.h"
00041 #include "incidence.h"
00042 #include "event.h"
00043 #include "todo.h"
00044 #include "journal.h"
00045 #include "filestorage.h"
00046 
00047 #include <kresources/configwidget.h>
00048 
00049 #include "resourcelocaldirconfig.h"
00050 
00051 #include "resourcelocaldir.h"
00052 
00053 using namespace KCal;
00054 
00055 ResourceLocalDir::ResourceLocalDir( const KConfig* config )
00056   : ResourceCached( config ), mLock( 0 )
00057 {
00058   if ( config ) {
00059     readConfig( config );
00060   }
00061 
00062   init();
00063 }
00064 
00065 ResourceLocalDir::ResourceLocalDir( const TQString& dirName )
00066   : ResourceCached( 0 )
00067 {
00068   mURL = KURL( dirName );
00069 
00070   init();
00071 }
00072 
00073 
00074 void ResourceLocalDir::readConfig( const KConfig *config )
00075 {
00076   TQString url = config->readPathEntry( "CalendarURL" );
00077   mURL = KURL( url );
00078 }
00079 
00080 void ResourceLocalDir::writeConfig( KConfig *config )
00081 {
00082   kdDebug(5800) << "ResourceLocalDir::writeConfig()" << endl;
00083 
00084   ResourceCalendar::writeConfig( config );
00085 
00086   config->writePathEntry( "CalendarURL", mURL.prettyURL() );
00087 }
00088 
00089 void ResourceLocalDir::init()
00090 {
00091   setType( "dir" );
00092 
00093   setSavePolicy( SaveDelayed );
00094 
00095   connect( &mDirWatch, TQT_SIGNAL( dirty( const TQString & ) ),
00096            TQT_SLOT( reload( const TQString & ) ) );
00097   connect( &mDirWatch, TQT_SIGNAL( created( const TQString & ) ),
00098            TQT_SLOT( reload( const TQString & ) ) );
00099   connect( &mDirWatch, TQT_SIGNAL( deleted( const TQString & ) ),
00100            TQT_SLOT( reload( const TQString & ) ) );
00101 
00102   mLock = new KABC::Lock( mURL.path() );
00103 
00104   mDirWatch.addDir( mURL.path(), true );
00105   mDirWatch.startScan();
00106 }
00107 
00108 
00109 ResourceLocalDir::~ResourceLocalDir()
00110 {
00111   close();
00112 
00113   delete mLock;
00114 }
00115 
00116 bool ResourceLocalDir::doOpen()
00117 {
00118   TQFileInfo dirInfo( mURL.path() );
00119   return dirInfo.isDir() && dirInfo.isReadable() &&
00120          ( dirInfo.isWritable() || readOnly() );
00121 }
00122 
00123 bool ResourceLocalDir::doLoad()
00124 {
00125   kdDebug(5800) << "ResourceLocalDir::load()" << endl;
00126 
00127   mCalendar.close();
00128   TQString dirName = mURL.path();
00129 
00130   if ( !( KStandardDirs::exists( dirName ) || KStandardDirs::exists( dirName + "/") ) ) {
00131     kdDebug(5800) << "ResourceLocalDir::load(): Directory '" << dirName
00132                   << "' doesn't exist yet. Creating it..." << endl;
00133     // Create the directory. Use 0775 to allow group-writable if the umask
00134     // allows it (permissions will be 0775 & ~umask). This is desired e.g. for
00135     // group-shared directories!
00136     return KStandardDirs::makeDir( dirName, 0775 );
00137   }
00138 
00139   // The directory exists. Now try to open (the files in) it.
00140   kdDebug(5800) << "ResourceLocalDir::load(): '" << dirName << "'" << endl;
00141   TQFileInfo dirInfo( dirName );
00142   if ( !( dirInfo.isDir() && dirInfo.isReadable() &&
00143           ( dirInfo.isWritable() || readOnly() ) ) )
00144     return false;
00145 
00146   TQDir dir( dirName );
00147   TQStringList entries = dir.entryList( TQDir::Files | TQDir::Readable );
00148 
00149   bool success = true;
00150   TQStringList::ConstIterator it;
00151   for( it = entries.constBegin(); it != entries.constEnd(); ++it ) {
00152     if ( (*it).endsWith( "~" ) ) // is backup file, ignore it
00153       continue;
00154 
00155     TQString fileName = dirName + "/" + *it;
00156     kdDebug(5800) << " read '" << fileName << "'" << endl;
00157     CalendarLocal cal( mCalendar.timeZoneId() );
00158     if ( !doFileLoad( cal, fileName ) ) {
00159       success = false;
00160     }
00161   }
00162 
00163   return success;
00164 }
00165 
00166 bool ResourceLocalDir::doFileLoad( CalendarLocal &cal, const TQString &fileName )
00167 {
00168   if ( !cal.load( fileName ) )
00169     return false;
00170   Incidence::List incidences = cal.rawIncidences();
00171   Incidence::List::ConstIterator it;
00172   for ( it = incidences.constBegin(); it != incidences.constEnd(); ++it ) {
00173     Incidence *i = *it;
00174     if ( i ) mCalendar.addIncidence( i->clone() );
00175   }
00176   return true;
00177 }
00178 
00179 bool ResourceLocalDir::doSave()
00180 {
00181   Incidence::List list;
00182   bool success = true;
00183 
00184   list = addedIncidences();
00185   list += changedIncidences();
00186 
00187   for ( Incidence::List::iterator it = list.begin(); it != list.end(); ++it )
00188     if ( !doSave( *it ) )
00189       success = false;
00190 
00191   return success;
00192 }
00193 
00194 bool ResourceLocalDir::doSave( Incidence *incidence )
00195 {
00196   if ( mDeletedIncidences.contains( incidence ) ) {
00197     mDeletedIncidences.remove( incidence );
00198     return true;
00199   }
00200 
00201   mDirWatch.stopScan();  // do prohibit the dirty() signal and a following reload()
00202 
00203   TQString fileName = mURL.path() + "/" + incidence->uid();
00204   kdDebug(5800) << "writing '" << fileName << "'" << endl;
00205 
00206   CalendarLocal cal( mCalendar.timeZoneId() );
00207   cal.addIncidence( incidence->clone() );
00208   const bool ret = cal.save( fileName );
00209 
00210   mDirWatch.startScan();
00211 
00212   return ret;
00213 }
00214 
00215 KABC::Lock *ResourceLocalDir::lock()
00216 {
00217   return mLock;
00218 }
00219 
00220 void ResourceLocalDir::reload( const TQString &file )
00221 {
00222   kdDebug(5800) << "ResourceLocalDir::reload()" << endl;
00223 
00224   if ( !isOpen() )
00225     return;
00226 
00227   kdDebug(5800) << "  File: '" << file << "'" << endl;
00228 
00229   mCalendar.close();
00230   load();
00231 
00232   emit resourceChanged( this );
00233 }
00234 
00235 
00236 bool ResourceLocalDir::deleteEvent(Event *event)
00237 {
00238   kdDebug(5800) << "ResourceLocalDir::deleteEvent" << endl;
00239   if ( deleteIncidenceFile(event) ) {
00240     if ( mCalendar.deleteEvent( event ) ) {
00241       mDeletedIncidences.append( event );
00242       return true;
00243     } else {
00244       return false;
00245     }
00246   } else {
00247     return false;
00248   }
00249 }
00250 
00251 
00252 bool ResourceLocalDir::deleteTodo(Todo *todo)
00253 {
00254   if ( deleteIncidenceFile(todo) ) {
00255     if ( mCalendar.deleteTodo( todo ) ) {
00256       mDeletedIncidences.append( todo );
00257       return true;
00258     } else {
00259       return false;
00260     }
00261   } else {
00262     return false;
00263   }
00264 }
00265 
00266 
00267 bool ResourceLocalDir::deleteJournal( Journal *journal )
00268 {
00269   if ( deleteIncidenceFile( journal ) ) {
00270     if ( mCalendar.deleteJournal( journal ) ) {
00271       mDeletedIncidences.append( journal );
00272       return true;
00273     } else {
00274       return false;
00275     }
00276   } else {
00277     return false;
00278   }
00279 }
00280 
00281 
00282 void ResourceLocalDir::dump() const
00283 {
00284   ResourceCalendar::dump();
00285   kdDebug(5800) << "  Url: " << mURL.url() << endl;
00286 }
00287 
00288 bool ResourceLocalDir::deleteIncidenceFile(Incidence *incidence)
00289 {
00290   TQFile file( mURL.path() + "/" + incidence->uid() );
00291   if ( !file.exists() )
00292     return true;
00293 
00294   mDirWatch.stopScan();
00295   bool removed = file.remove();
00296   mDirWatch.startScan();
00297   return removed;
00298 }
00299 
00300 #include "resourcelocaldir.moc"