libkcal

resourcelocaldir.cpp

Go to the documentation of this file.
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 <qdatetime.h>
00026 #include <qfileinfo.h>
00027 #include <qstring.h>
00028 #include <qptrlist.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 QString& dirName )
00066   : ResourceCached( 0 )
00067 {
00068   mURL = KURL( dirName );
00069 
00070   init();
00071 }
00072 
00073 
00074 void ResourceLocalDir::readConfig( const KConfig *config )
00075 {
00076   QString 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, SIGNAL( dirty( const QString & ) ),
00096            SLOT( reload( const QString & ) ) );
00097   connect( &mDirWatch, SIGNAL( created( const QString & ) ),
00098            SLOT( reload( const QString & ) ) );
00099   connect( &mDirWatch, SIGNAL( deleted( const QString & ) ),
00100            SLOT( reload( const QString & ) ) );
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   QFileInfo 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   QString 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   QFileInfo dirInfo( dirName );
00142   if ( !( dirInfo.isDir() && dirInfo.isReadable() && 
00143           ( dirInfo.isWritable() || readOnly() ) ) )
00144     return false;
00145 
00146   QDir dir( dirName );
00147   QStringList entries = dir.entryList( QDir::Files | QDir::Readable );
00148 
00149   bool success = true;
00150   QStringList::ConstIterator it;
00151   for( it = entries.constBegin(); it != entries.constEnd(); ++it ) {
00152     if ( (*it).endsWith( "~" ) ) // is backup file, ignore it
00153       continue;
00154 
00155     QString 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 QString &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   mDirWatch.stopScan();  // do prohibit the dirty() signal and a following reload()
00197 
00198   QString fileName = mURL.path() + "/" + incidence->uid();
00199   kdDebug(5800) << "writing '" << fileName << "'" << endl;
00200 
00201   CalendarLocal cal( mCalendar.timeZoneId() );
00202   cal.addIncidence( incidence->clone() );
00203   const bool ret = cal.save( fileName );
00204 
00205   mDirWatch.startScan();
00206 
00207   return ret;
00208 }
00209 
00210 KABC::Lock *ResourceLocalDir::lock()
00211 {
00212   return mLock;
00213 }
00214 
00215 void ResourceLocalDir::reload( const QString &file )
00216 {
00217   kdDebug(5800) << "ResourceLocalDir::reload()" << endl;
00218 
00219   if ( !isOpen() )
00220     return;
00221 
00222   kdDebug(5800) << "  File: '" << file << "'" << endl;
00223 
00224   mCalendar.close();
00225   load();
00226 
00227   emit resourceChanged( this );
00228 }
00229 
00230 
00231 bool ResourceLocalDir::deleteEvent(Event *event)
00232 {
00233   kdDebug(5800) << "ResourceLocalDir::deleteEvent" << endl;
00234   if ( deleteIncidenceFile(event) )
00235     return( mCalendar.deleteEvent( event ) );
00236   else
00237     return( false );
00238 }
00239 
00240 
00241 bool ResourceLocalDir::deleteTodo(Todo *todo)
00242 {
00243   if ( deleteIncidenceFile(todo) )
00244     return( mCalendar.deleteTodo( todo ) );
00245   else
00246     return( false );
00247 }
00248 
00249 
00250 bool ResourceLocalDir::deleteJournal( Journal *journal )
00251 {
00252   if ( deleteIncidenceFile( journal ) )
00253     return( mCalendar.deleteJournal( journal ) );
00254   else
00255     return( false );
00256 }
00257 
00258 
00259 void ResourceLocalDir::dump() const
00260 {
00261   ResourceCalendar::dump();
00262   kdDebug(5800) << "  Url: " << mURL.url() << endl;
00263 }
00264 
00265 bool ResourceLocalDir::deleteIncidenceFile(Incidence *incidence)
00266 {
00267   QFile file( mURL.path() + "/" + incidence->uid() );
00268   if ( !file.exists() )
00269     return true;
00270 
00271   mDirWatch.stopScan();
00272   bool removed = file.remove();
00273   mDirWatch.startScan();
00274   return removed;
00275 }
00276 
00277 #include "resourcelocaldir.moc"