• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.10.5 API Reference
  • KDE Home
  • Contact Us
 

KCal Library

  • kcal
resourcelocaldir.cpp
1 /*
2  This file is part of the kcal library.
3 
4  Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
5  Copyright (c) 2009 Sergio Martins <iamsergio@gmail.com>
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License as published by the Free Software Foundation; either
10  version 2 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Library General Public License for more details.
16 
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB. If not, write to
19  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  Boston, MA 02110-1301, USA.
21 */
22 
23 #include "resourcelocaldir.h"
24 #include "resourcelocaldir_p.h"
25 #include "calendarlocal.h"
26 #include "incidence.h"
27 #include "event.h"
28 #include "todo.h"
29 #include "journal.h"
30 
31 #include "kresources/configwidget.h"
32 
33 #include <kcal/assignmentvisitor.h>
34 #include <kcal/comparisonvisitor.h>
35 #include <kdebug.h>
36 #include <klocale.h>
37 #include <kconfig.h>
38 #include <kstandarddirs.h>
39 #include <kconfiggroup.h>
40 
41 #include <QtCore/QString>
42 #include <QtCore/QDir>
43 #include <QtCore/QFileInfo>
44 
45 #include <typeinfo>
46 #include <stdlib.h>
47 
48 #include "moc_resourcelocaldir.cpp"
49 #include "moc_resourcelocaldir_p.cpp"
50 
51 using namespace KCal;
52 
53 ResourceLocalDir::ResourceLocalDir()
54  : ResourceCached(), d( new KCal::ResourceLocalDir::Private( this ) )
55 {
56  d->init();
57 }
58 
59 ResourceLocalDir::ResourceLocalDir( const KConfigGroup &group )
60  : ResourceCached( group ), d( new KCal::ResourceLocalDir::Private( this ) )
61 {
62  readConfig( group );
63  d->init();
64 }
65 
66 ResourceLocalDir::ResourceLocalDir( const QString &dirName )
67  : ResourceCached(), d( new KCal::ResourceLocalDir::Private( dirName, this ) )
68 {
69  d->init();
70 }
71 
72 void ResourceLocalDir::readConfig( const KConfigGroup &group )
73 {
74  QString url = group.readPathEntry( "CalendarURL", QString() );
75  d->mURL = KUrl( url );
76 }
77 
78 void ResourceLocalDir::writeConfig( KConfigGroup &group )
79 {
80  kDebug();
81 
82  ResourceCalendar::writeConfig( group );
83 
84  group.writePathEntry( "CalendarURL", d->mURL.prettyUrl() );
85 }
86 
87 //@cond PRIVATE
88 void ResourceLocalDir::Private::init()
89 {
90  mResource->setType( "dir" );
91 
92  mResource->setSavePolicy( SaveDelayed );
93 
94  connect( &mDirWatch, SIGNAL(dirty(QString)),
95  this, SLOT(updateIncidenceInCalendar(QString)) );
96  connect( &mDirWatch, SIGNAL(created(QString)),
97  this, SLOT(addIncidenceToCalendar(QString)) );
98  connect( &mDirWatch, SIGNAL(deleted(QString)),
99  this, SLOT(deleteIncidenceFromCalendar(QString)) );
100 
101  connect ( this, SIGNAL(resourceChanged(ResourceCalendar*)),
102  mResource, SIGNAL(resourceChanged(ResourceCalendar*)) );
103 
104  mLock = new KABC::Lock( mURL.path() );
105 
106  mDirWatch.addDir( mURL.path(), KDirWatch::WatchFiles );
107  mDirWatch.startScan();
108 }
109 //@endcond
110 
111 ResourceLocalDir::~ResourceLocalDir()
112 {
113  close();
114 
115  delete d->mLock;
116  delete d;
117 }
118 
119 bool ResourceLocalDir::doOpen()
120 {
121  QFileInfo dirInfo( d->mURL.path() );
122  return dirInfo.isDir() && dirInfo.isReadable() &&
123  ( dirInfo.isWritable() || readOnly() );
124 }
125 
126 bool ResourceLocalDir::doLoad( bool )
127 {
128  kDebug();
129 
130  calendar()->close();
131  QString dirName = d->mURL.path();
132 
133  if ( !( KStandardDirs::exists( dirName ) || KStandardDirs::exists( dirName + '/' ) ) ) {
134  kDebug() << "Directory '" << dirName << "' doesn't exist yet. Creating it.";
135 
136  // Create the directory. Use 0775 to allow group-writable if the umask
137  // allows it (permissions will be 0775 & ~umask). This is desired e.g. for
138  // group-shared directories!
139  return KStandardDirs::makeDir( dirName, 0775 );
140  }
141 
142  // The directory exists. Now try to open (the files in) it.
143  kDebug() << dirName;
144  QFileInfo dirInfo( dirName );
145  if ( !( dirInfo.isDir() && dirInfo.isReadable() &&
146  ( dirInfo.isWritable() || readOnly() ) ) ) {
147  return false;
148  }
149 
150  QDir dir( dirName );
151  const QStringList entries = dir.entryList( QDir::Files | QDir::Readable );
152 
153  bool success = true;
154 
155  foreach ( const QString &entry, entries ) {
156  if ( d->isTempFile( entry ) ) {
157  continue; // backup or temporary file, ignore it
158  }
159 
160  const QString fileName = dirName + '/' + entry;
161  kDebug() << " read '" << fileName << "'";
162  CalendarLocal cal( calendar()->timeSpec() );
163  if ( !doFileLoad( cal, fileName ) ) {
164  success = false;
165  }
166  }
167 
168  return success;
169 }
170 
171 bool ResourceLocalDir::doFileLoad( CalendarLocal &cal, const QString &fileName )
172 {
173  return d->doFileLoad( cal, fileName, false );
174 }
175 
176 bool ResourceLocalDir::doSave( bool syncCache )
177 {
178  Q_UNUSED( syncCache );
179  Incidence::List list;
180  bool success = true;
181 
182  list = addedIncidences();
183  list += changedIncidences();
184 
185  for ( Incidence::List::iterator it = list.begin(); it != list.end(); ++it ) {
186  if ( !doSave( *it ) ) {
187  success = false;
188  }
189  }
190 
191  return success;
192 }
193 
194 bool ResourceLocalDir::doSave( bool, Incidence *incidence )
195 {
196  if ( d->mDeletedIncidences.contains( incidence ) ) {
197  d->mDeletedIncidences.removeAll( incidence );
198  return true;
199  }
200 
201  d->mDirWatch.stopScan(); // do prohibit the dirty() signal and a following reload()
202 
203  QString fileName = d->mURL.path() + '/' + incidence->uid();
204  kDebug() << "writing '" << fileName << "'";
205 
206  CalendarLocal cal( calendar()->timeSpec() );
207  cal.addIncidence( incidence->clone() );
208  const bool ret = cal.save( fileName );
209 
210  d->mDirWatch.startScan();
211 
212  return ret;
213 }
214 
215 KABC::Lock *ResourceLocalDir::lock()
216 {
217  return d->mLock;
218 }
219 
220 void ResourceLocalDir::reload( const QString &file )
221 {
222  Q_UNUSED( file );
223 }
224 
225 bool ResourceLocalDir::deleteEvent( Event *event )
226 {
227  kDebug();
228  if ( d->deleteIncidenceFile( event ) ) {
229  if ( calendar()->deleteEvent( event ) ) {
230  d->mDeletedIncidences.append( event );
231  return true;
232  } else {
233  return false;
234  }
235  } else {
236  return false;
237  }
238 }
239 
240 void ResourceLocalDir::deleteAllEvents()
241 {
242  calendar()->deleteAllEvents();
243 }
244 
245 bool ResourceLocalDir::deleteTodo( Todo *todo )
246 {
247  if ( d->deleteIncidenceFile( todo ) ) {
248  if ( calendar()->deleteTodo( todo ) ) {
249  d->mDeletedIncidences.append( todo );
250  return true;
251  } else {
252  return false;
253  }
254  } else {
255  return false;
256  }
257 }
258 
259 void ResourceLocalDir::deleteAllTodos()
260 {
261  calendar()->deleteAllTodos();
262 }
263 
264 bool ResourceLocalDir::deleteJournal( Journal *journal )
265 {
266  if ( d->deleteIncidenceFile( journal ) ) {
267  if ( calendar()->deleteJournal( journal ) ) {
268  d->mDeletedIncidences.append( journal );
269  return true;
270  } else {
271  return false;
272  }
273  } else {
274  return false;
275  }
276 }
277 
278 void ResourceLocalDir::deleteAllJournals()
279 {
280  calendar()->deleteAllJournals();
281 }
282 
283 void ResourceLocalDir::dump() const
284 {
285  ResourceCalendar::dump();
286  kDebug() << " Url:" << d->mURL.url();
287 }
288 
289 //@cond PRIVATE
290 bool ResourceLocalDir::Private::deleteIncidenceFile( Incidence *incidence )
291 {
292  QFile file( mURL.path() + '/' + incidence->uid() );
293  if ( !file.exists() ) {
294  return true;
295  }
296 
297  mDirWatch.stopScan();
298  bool removed = file.remove();
299  mDirWatch.startScan();
300  return removed;
301 }
302 
303 bool ResourceLocalDir::Private::isTempFile( const QString &fileName ) const
304 {
305  return
306  fileName.contains( QRegExp( "(~|\\.new|\\.tmp)$" ) ) ||
307  QFileInfo( fileName ).fileName().startsWith( QLatin1String( "qt_temp." ) ) ||
308  fileName == mURL.path();
309 }
310 
311 void ResourceLocalDir::Private::addIncidenceToCalendar( const QString &file )
312 {
313 
314  if ( mResource->isOpen() &&
315  !isTempFile( file ) &&
316  !mResource->calendar()->incidence( getUidFromFileName( file ) ) ) {
317 
318  CalendarLocal cal( mResource->calendar()->timeSpec() );
319  if ( doFileLoad( cal, file, true ) ) {
320  emit resourceChanged( mResource );
321  }
322  }
323 }
324 
325 void ResourceLocalDir::Private::updateIncidenceInCalendar( const QString &file )
326 {
327  if ( mResource->isOpen() && !isTempFile( file ) ) {
328  CalendarLocal cal( mResource->calendar()->timeSpec() );
329  if ( doFileLoad( cal, file, true ) ) {
330  emit resourceChanged( mResource );
331  }
332  }
333 }
334 
335 QString ResourceLocalDir::Private::getUidFromFileName( const QString &fileName )
336 {
337  return QFileInfo( fileName ).fileName();
338 }
339 
340 void ResourceLocalDir::Private::deleteIncidenceFromCalendar( const QString &file )
341 {
342 
343  if ( mResource->isOpen() && !isTempFile( file ) ) {
344  Incidence *inc = mResource->calendar()->incidence( getUidFromFileName( file ) );
345 
346  if ( inc ) {
347  mResource->calendar()->deleteIncidence( inc );
348  emit resourceChanged( mResource );
349  }
350  }
351 }
352 
353 bool ResourceLocalDir::Private::doFileLoad( CalendarLocal &cal,
354  const QString &fileName,
355  const bool replace )
356 {
357  if ( !cal.load( fileName ) ) {
358  return false;
359  }
360  Incidence::List incidences = cal.rawIncidences();
361  Incidence::List::ConstIterator it;
362  Incidence *inc;
363  ComparisonVisitor compVisitor;
364  AssignmentVisitor assVisitor;
365  for ( it = incidences.constBegin(); it != incidences.constEnd(); ++it ) {
366  Incidence *i = *it;
367  if ( i ) {
368  // should we replace, and does the incidence exist in calendar?
369  if ( replace && ( inc = mResource->calendar()->incidence( i->uid() ) ) ) {
370  if ( compVisitor.compare( i, inc ) ) {
371  // no need to do anything
372  return false;
373  } else {
374  inc->startUpdates();
375 
376  bool assignResult = assVisitor.assign( inc, i );
377 
378  if ( assignResult ) {
379  if ( !inc->relatedToUid().isEmpty() ) {
380  QString uid = inc->relatedToUid();
381  inc->setRelatedTo( mResource->calendar()->incidence( uid ) );
382  }
383  inc->updated();
384  inc->endUpdates();
385  } else {
386  inc->endUpdates();
387  kWarning() << "Incidence (uid=" << inc->uid()
388  << ", summary=" << inc->summary()
389  << ") changed type. Replacing it.";
390 
391  mResource->calendar()->deleteIncidence( inc );
392  delete inc;
393  mResource->calendar()->addIncidence( i->clone() );
394  }
395  }
396  } else {
397  mResource->calendar()->addIncidence( i->clone() );
398  }
399  }
400  }
401  return true;
402 }
403 //@endcond
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Sat Jul 13 2013 01:29:16 by doxygen 1.8.3.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KCal Library

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

kdepimlibs-4.10.5 API Reference

Skip menu "kdepimlibs-4.10.5 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal