• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

KCal Library

resourcelocaldir.cpp

00001 /*
00002   This file is part of the kcal library.
00003 
00004   Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
00005   Copyright (c) 2009 Sergio Martins <iamsergio@gmail.com>
00006 
00007   This library is free software; you can redistribute it and/or
00008   modify it under the terms of the GNU Library General Public
00009   License as published by the Free Software Foundation; either
00010   version 2 of the License, or (at your option) any later version.
00011 
00012   This library is distributed in the hope that it will be useful,
00013   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015   Library General Public License for more details.
00016 
00017   You should have received a copy of the GNU Library General Public License
00018   along with this library; see the file COPYING.LIB.  If not, write to
00019   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020   Boston, MA 02110-1301, USA.
00021 */
00022 
00023 #include "resourcelocaldir.h"
00024 #include "resourcelocaldir_p.h"
00025 #include "calendarlocal.h"
00026 #include "incidence.h"
00027 #include "event.h"
00028 #include "todo.h"
00029 #include "journal.h"
00030 
00031 #include "kresources/configwidget.h"
00032 
00033 #include <kcal/assignmentvisitor.h>
00034 #include <kcal/comparisonvisitor.h>
00035 #include <kdebug.h>
00036 #include <klocale.h>
00037 #include <kconfig.h>
00038 #include <kstandarddirs.h>
00039 #include <kconfiggroup.h>
00040 
00041 #include <QtCore/QString>
00042 #include <QtCore/QDir>
00043 #include <QtCore/QFileInfo>
00044 
00045 #include <typeinfo>
00046 #include <stdlib.h>
00047 
00048 #include "resourcelocaldir.moc"
00049 #include "resourcelocaldir_p.moc"
00050 
00051 using namespace KCal;
00052 
00053 ResourceLocalDir::ResourceLocalDir()
00054   : ResourceCached(), d( new KCal::ResourceLocalDir::Private( this ) )
00055 {
00056   d->init();
00057 }
00058 
00059 ResourceLocalDir::ResourceLocalDir( const KConfigGroup &group )
00060   : ResourceCached( group ), d( new KCal::ResourceLocalDir::Private( this ) )
00061 {
00062   readConfig( group );
00063   d->init();
00064 }
00065 
00066 ResourceLocalDir::ResourceLocalDir( const QString &dirName )
00067   : ResourceCached(), d( new KCal::ResourceLocalDir::Private( dirName, this ) )
00068 {
00069   d->init();
00070 }
00071 
00072 void ResourceLocalDir::readConfig( const KConfigGroup &group )
00073 {
00074   QString url = group.readPathEntry( "CalendarURL", QString() );
00075   d->mURL = KUrl( url );
00076 }
00077 
00078 void ResourceLocalDir::writeConfig( KConfigGroup &group )
00079 {
00080   kDebug();
00081 
00082   ResourceCalendar::writeConfig( group );
00083 
00084   group.writePathEntry( "CalendarURL", d->mURL.prettyUrl() );
00085 }
00086 
00087 //@cond PRIVATE
00088 void ResourceLocalDir::Private::init()
00089 {
00090   mResource->setType( "dir" );
00091 
00092   mResource->setSavePolicy( SaveDelayed );
00093 
00094   connect( &mDirWatch, SIGNAL( dirty( const QString & ) ),
00095            this, SLOT( updateIncidenceInCalendar( const QString & ) ) );
00096   connect( &mDirWatch, SIGNAL( created( const QString & ) ),
00097            this, SLOT( addIncidenceToCalendar( const QString & ) ) );
00098   connect( &mDirWatch, SIGNAL( deleted( const QString & ) ),
00099            this, SLOT( deleteIncidenceFromCalendar( const QString & ) ) );
00100 
00101   connect ( this, SIGNAL(resourceChanged( ResourceCalendar *)),
00102             mResource, SIGNAL(resourceChanged( ResourceCalendar *)) );
00103 
00104   mLock = new KABC::Lock( mURL.path() );
00105 
00106   mDirWatch.addDir( mURL.path(), KDirWatch::WatchFiles );
00107   mDirWatch.startScan();
00108 }
00109 //@endcond
00110 
00111 ResourceLocalDir::~ResourceLocalDir()
00112 {
00113   close();
00114 
00115   delete d->mLock;
00116   delete d;
00117 }
00118 
00119 bool ResourceLocalDir::doOpen()
00120 {
00121   QFileInfo dirInfo( d->mURL.path() );
00122   return dirInfo.isDir() && dirInfo.isReadable() &&
00123     ( dirInfo.isWritable() || readOnly() );
00124 }
00125 
00126 bool ResourceLocalDir::doLoad( bool )
00127 {
00128   kDebug();
00129 
00130   calendar()->close();
00131   QString dirName = d->mURL.path();
00132 
00133   if ( !( KStandardDirs::exists( dirName ) || KStandardDirs::exists( dirName + '/' ) ) ) {
00134     kDebug() << "Directory '" << dirName << "' doesn't exist yet. Creating it.";
00135 
00136     // Create the directory. Use 0775 to allow group-writable if the umask
00137     // allows it (permissions will be 0775 & ~umask). This is desired e.g. for
00138     // group-shared directories!
00139     return KStandardDirs::makeDir( dirName, 0775 );
00140   }
00141 
00142   // The directory exists. Now try to open (the files in) it.
00143   kDebug() << dirName;
00144   QFileInfo dirInfo( dirName );
00145   if ( !( dirInfo.isDir() && dirInfo.isReadable() &&
00146           ( dirInfo.isWritable() || readOnly() ) ) ) {
00147     return false;
00148   }
00149 
00150   QDir dir( dirName );
00151   const QStringList entries = dir.entryList( QDir::Files | QDir::Readable );
00152 
00153   bool success = true;
00154 
00155   foreach ( const QString &entry, entries ) {
00156     if ( d->isTempFile( entry ) ) {
00157       continue;  // backup or temporary file, ignore it
00158     }
00159 
00160     const QString fileName = dirName + '/' + entry;
00161     kDebug() << " read '" << fileName << "'";
00162     CalendarLocal cal( calendar()->timeSpec() );
00163     if ( !doFileLoad( cal, fileName ) ) {
00164       success = false;
00165     }
00166   }
00167 
00168   return success;
00169 }
00170 
00171 bool ResourceLocalDir::doFileLoad( CalendarLocal &cal, const QString &fileName )
00172 {
00173   return d->doFileLoad( cal, fileName, false );
00174 }
00175 
00176 bool ResourceLocalDir::doSave( bool syncCache )
00177 {
00178   Q_UNUSED( syncCache );
00179   Incidence::List list;
00180   bool success = true;
00181 
00182   list = addedIncidences();
00183   list += changedIncidences();
00184 
00185   for ( Incidence::List::iterator it = list.begin(); it != list.end(); ++it ) {
00186     if ( !doSave( *it ) ) {
00187       success = false;
00188     }
00189   }
00190 
00191   return success;
00192 }
00193 
00194 bool ResourceLocalDir::doSave( bool, Incidence *incidence )
00195 {
00196   if ( d->mDeletedIncidences.contains( incidence ) ) {
00197     d->mDeletedIncidences.removeAll( incidence );
00198     return true;
00199   }
00200 
00201   d->mDirWatch.stopScan();  // do prohibit the dirty() signal and a following reload()
00202 
00203   QString fileName = d->mURL.path() + '/' + incidence->uid();
00204   kDebug() << "writing '" << fileName << "'";
00205 
00206   CalendarLocal cal( calendar()->timeSpec() );
00207   cal.addIncidence( incidence->clone() );
00208   const bool ret = cal.save( fileName );
00209 
00210   d->mDirWatch.startScan();
00211 
00212   return ret;
00213 }
00214 
00215 KABC::Lock *ResourceLocalDir::lock()
00216 {
00217   return d->mLock;
00218 }
00219 
00220 void ResourceLocalDir::reload( const QString &file )
00221 {
00222   Q_UNUSED( file );
00223 }
00224 
00225 bool ResourceLocalDir::deleteEvent( Event *event )
00226 {
00227   kDebug();
00228   if ( d->deleteIncidenceFile( event ) ) {
00229     if ( calendar()->deleteEvent( event ) ) {
00230       d->mDeletedIncidences.append( event );
00231       return true;
00232     } else {
00233       return false;
00234     }
00235   } else {
00236     return false;
00237   }
00238 }
00239 
00240 void ResourceLocalDir::deleteAllEvents()
00241 {
00242   calendar()->deleteAllEvents();
00243 }
00244 
00245 bool ResourceLocalDir::deleteTodo( Todo *todo )
00246 {
00247   if ( d->deleteIncidenceFile( todo ) ) {
00248     if ( calendar()->deleteTodo( todo ) ) {
00249       d->mDeletedIncidences.append( todo );
00250       return true;
00251     } else {
00252       return false;
00253     }
00254   } else {
00255     return false;
00256   }
00257 }
00258 
00259 void ResourceLocalDir::deleteAllTodos()
00260 {
00261   calendar()->deleteAllTodos();
00262 }
00263 
00264 bool ResourceLocalDir::deleteJournal( Journal *journal )
00265 {
00266   if ( d->deleteIncidenceFile( journal ) ) {
00267     if ( calendar()->deleteJournal( journal ) ) {
00268       d->mDeletedIncidences.append( journal );
00269       return true;
00270     } else {
00271       return false;
00272     }
00273   } else {
00274     return false;
00275   }
00276 }
00277 
00278 void ResourceLocalDir::deleteAllJournals()
00279 {
00280   calendar()->deleteAllJournals();
00281 }
00282 
00283 void ResourceLocalDir::dump() const
00284 {
00285   ResourceCalendar::dump();
00286   kDebug() << "  Url:" << d->mURL.url();
00287 }
00288 
00289 //@cond PRIVATE
00290 bool ResourceLocalDir::Private::deleteIncidenceFile( Incidence *incidence )
00291 {
00292   QFile file( mURL.path() + '/' + incidence->uid() );
00293   if ( !file.exists() ) {
00294     return true;
00295   }
00296 
00297   mDirWatch.stopScan();
00298   bool removed = file.remove();
00299   mDirWatch.startScan();
00300   return removed;
00301 }
00302 
00303 bool ResourceLocalDir::Private::isTempFile( const QString &fileName ) const
00304 {
00305   return
00306     fileName.contains( QRegExp( "(~|\\.new|\\.tmp)$" ) ) ||
00307     QFileInfo( fileName ).fileName().startsWith( QLatin1String( "qt_temp." ) ) ||
00308     fileName == mURL.path();
00309 }
00310 
00311 void ResourceLocalDir::Private::addIncidenceToCalendar( const QString &file )
00312 {
00313 
00314   if ( mResource->isOpen() &&
00315        !isTempFile( file ) &&
00316        !mResource->calendar()->incidence( getUidFromFileName( file ) ) ) {
00317 
00318     CalendarLocal cal( mResource->calendar()->timeSpec() );
00319     if ( doFileLoad( cal, file, true ) ) {
00320       emit resourceChanged( mResource );
00321     }
00322   }
00323 }
00324 
00325 void ResourceLocalDir::Private::updateIncidenceInCalendar( const QString &file )
00326 {
00327   if ( mResource->isOpen() && !isTempFile( file ) ) {
00328     CalendarLocal cal( mResource->calendar()->timeSpec() );
00329     if ( doFileLoad( cal, file, true ) ) {
00330       emit resourceChanged( mResource );
00331     }
00332   }
00333 }
00334 
00335 QString ResourceLocalDir::Private::getUidFromFileName( const QString &fileName )
00336 {
00337   return QFileInfo( fileName ).fileName();
00338 }
00339 
00340 void ResourceLocalDir::Private::deleteIncidenceFromCalendar( const QString &file )
00341 {
00342 
00343   if ( mResource->isOpen() && !isTempFile( file ) ) {
00344     Incidence *inc = mResource->calendar()->incidence( getUidFromFileName( file ) );
00345 
00346     if ( inc ) {
00347       mResource->calendar()->deleteIncidence( inc );
00348       emit resourceChanged( mResource );
00349     }
00350   }
00351 }
00352 
00353 bool ResourceLocalDir::Private::doFileLoad( CalendarLocal &cal,
00354                                             const QString &fileName,
00355                                             const bool replace )
00356 {
00357   if ( !cal.load( fileName ) ) {
00358     return false;
00359   }
00360   Incidence::List incidences = cal.rawIncidences();
00361   Incidence::List::ConstIterator it;
00362   Incidence *inc;
00363   ComparisonVisitor compVisitor;
00364   AssignmentVisitor assVisitor;
00365   for ( it = incidences.constBegin(); it != incidences.constEnd(); ++it ) {
00366     Incidence *i = *it;
00367     if ( i ) {
00368       // should we replace, and does the incidence exist in calendar?
00369       if ( replace && ( inc = mResource->calendar()->incidence( i->uid() ) ) ) {
00370         if ( compVisitor.compare( i, inc ) ) {
00371           // no need to do anything
00372           return false;
00373         } else {
00374           inc->startUpdates();
00375 
00376           bool assignResult = assVisitor.assign( inc, i );
00377 
00378           if ( assignResult ) {
00379             if ( !inc->relatedToUid().isEmpty() ) {
00380               QString uid = inc->relatedToUid();
00381               inc->setRelatedTo( mResource->calendar()->incidence( uid ) );
00382             }
00383             inc->updated();
00384             inc->endUpdates();
00385           } else {
00386             inc->endUpdates();
00387             kWarning() << "Incidence (uid=" << inc->uid()
00388                        << ", summary=" << inc->summary()
00389                        << ") changed type. Replacing it.";
00390 
00391             mResource->calendar()->deleteIncidence( inc );
00392             delete inc;
00393             mResource->calendar()->addIncidence( i->clone() );
00394           }
00395         }
00396       } else {
00397         mResource->calendar()->addIncidence( i->clone() );
00398       }
00399     }
00400   }
00401   return true;
00402 }
00403 //@endcond

KCal Library

Skip menu "KCal Library"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  • kabc
  • kblog
  • kcal
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  • kldap
  • kmime
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal