1/*
2 This file is part of the kcal library.
3
4 Copyright (c) 1998 Preston Brown <pbrown@kde.org>
5 Copyright (c) 2001,2003 Cornelius Schumacher <schumacher@kde.org>
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 @file
24 This file is part of the API for handling calendar data and
25 defines the ResourceLocal class.
26
27 @author Preston Brown <pbrown@kde.org>
28 @author Cornelius Schumacher <schumacher@kde.org>
29*/
30
31#include "resourcelocal.h"
32#include "resourcelocal_p.h"
33#include "resourcelocalconfig.h"
34#include "vcalformat.h"
35#include "icalformat.h"
36#include "calendarlocal.h"
37#include "exceptions.h"
38#include "incidence.h"
39#include "event.h"
40#include "todo.h"
41#include "journal.h"
42
43#include <kresources/configwidget.h>
44
45#include <typeinfo>
46#include <stdlib.h>
47
48#include <QtCore/QString>
49
50#include <kdebug.h>
51#include <klocalizedstring.h>
52#include <kurl.h>
53#include <kdirwatch.h>
54#include <kstandarddirs.h>
55#include <kconfiggroup.h>
56
57
58using namespace KCal;
59
60ResourceLocal::ResourceLocal()
61 : ResourceCached(), d( new ResourceLocal::Private() )
62{
63 d->mLock = 0;
64 d->mURL = KUrl();
65 d->mFormat = new ICalFormat();
66 init();
67}
68
69ResourceLocal::ResourceLocal( const KConfigGroup &group )
70 : ResourceCached( group ), d( new ResourceLocal::Private() )
71{
72 d->mLock = 0;
73 QString url = group.readPathEntry( "CalendarURL", QString() );
74 d->mURL = KUrl( url );
75
76 QString format = group.readEntry( "Format" );
77 if ( format == "ical" ) {
78 d->mFormat = new ICalFormat();
79 } else if ( format == "vcal" ) {
80 d->mFormat = new VCalFormat();
81 } else {
82 d->mFormat = new ICalFormat();
83 }
84 init();
85}
86
87ResourceLocal::ResourceLocal( const QString &fileName )
88 : ResourceCached(), d( new ResourceLocal::Private )
89{
90 d->mURL = KUrl::fromPath( fileName );
91 d->mFormat = new ICalFormat();
92 init();
93}
94
95void ResourceLocal::writeConfig( KConfigGroup &group )
96{
97 kDebug();
98
99 ResourceCalendar::writeConfig( group );
100 group.writePathEntry( "CalendarURL", d->mURL.prettyUrl() );
101
102 if ( typeid( *d->mFormat ) == typeid( ICalFormat ) ) {
103 group.writeEntry( "Format", "ical" );
104 } else if ( typeid( *d->mFormat ) == typeid( VCalFormat ) ) {
105 group.writeEntry( "Format", "vcal" );
106 } else {
107 kDebug() << "ERROR: Unknown format type";
108 }
109}
110
111void ResourceLocal::init()
112{
113
114 setType( "file" );
115
116 setSavePolicy( SaveDelayed );
117
118 connect( &d->mDirWatch, SIGNAL(dirty(QString)),
119 SLOT(reload()) );
120 connect( &d->mDirWatch, SIGNAL(created(QString)),
121 SLOT(reload()) );
122 connect( &d->mDirWatch, SIGNAL(deleted(QString)),
123 SLOT(reload()) );
124
125 d->mLock = new KABC::Lock( d->mURL.path() );
126
127 d->mDirWatch.addFile( d->mURL.path() );
128 d->mDirWatch.startScan();
129}
130
131ResourceLocal::~ResourceLocal()
132{
133 d->mDirWatch.stopScan();
134 close();
135
136 delete d->mLock;
137 delete d;
138}
139
140KDateTime ResourceLocal::readLastModified()
141{
142 QFileInfo fi( d->mURL.path() );
143 return KDateTime( fi.lastModified() ); // use local time zone
144}
145
146bool ResourceLocal::doLoad( bool syncCache )
147{
148 Q_UNUSED( syncCache );
149
150 bool success;
151 if ( !KStandardDirs::exists( d->mURL.path() ) ) {
152 kDebug() << "File doesn't exist yet.";
153 // Save the empty calendar, so the calendar file will be created.
154 success = doSave( true );
155 } else {
156 success = calendar()->load( d->mURL.path() );
157 if ( success ) {
158 d->mLastModified = readLastModified();
159 }
160 }
161
162 return success;
163}
164
165bool ResourceLocal::doSave( bool syncCache )
166{
167 Q_UNUSED( syncCache );
168 bool success = calendar()->save( d->mURL.path() );
169 kDebug() << "Save of " << d->mURL.path() << "was " << success;
170 d->mLastModified = readLastModified();
171
172 return success;
173}
174
175bool ResourceLocal::doSave( bool syncCache, Incidence *incidence )
176{
177 return ResourceCached::doSave( syncCache, incidence );
178}
179
180KABC::Lock *ResourceLocal::lock()
181{
182 return d->mLock;
183}
184
185bool ResourceLocal::doReload()
186{
187 kDebug();
188
189 if ( !isOpen() ) {
190 kDebug() << "trying to reload from a closed file";
191 return false;
192 }
193
194 if ( d->mLastModified == readLastModified() ) {
195 kDebug() << "file not modified since last read.";
196 return false;
197 }
198
199 calendar()->close();
200 calendar()->load( d->mURL.path() );
201 return true;
202}
203
204void ResourceLocal::reload()
205{
206 if ( doReload() ) {
207 emit resourceChanged( this );
208 }
209}
210
211void ResourceLocal::dump() const
212{
213 ResourceCalendar::dump();
214 kDebug() << " Url:" << d->mURL.url();
215}
216
217QString ResourceLocal::fileName() const
218{
219 return d->mURL.path();
220}
221
222bool ResourceLocal::setFileName( const QString &fileName )
223{
224 bool open = isOpen();
225 if ( open ) {
226 close();
227 }
228 delete d->mLock;
229 d->mDirWatch.stopScan();
230 d->mDirWatch.removeFile( d->mURL.path() );
231 d->mURL = KUrl::fromPath( fileName );
232 d->mLock = new KABC::Lock( d->mURL.path() );
233 d->mDirWatch.addFile( d->mURL.path() );
234 d->mDirWatch.startScan();
235 return true;
236}
237
238bool ResourceLocal::setValue( const QString &key, const QString &value )
239{
240 if ( key == "File" ) {
241 return setFileName( value );
242 } else {
243 return false;
244 }
245}
246
247bool ResourceLocal::operator==( const ResourceLocal &other )
248{
249 return
250 d->mURL == other.d->mURL &&
251 d->mLastModified == other.d->mLastModified;
252}
253
254ResourceLocal &ResourceLocal::operator=( const ResourceLocal &other )
255{
256 // check for self assignment
257 if ( &other == this ) {
258 return *this;
259 }
260
261 d->mURL = other.d->mURL;
262 d->mLastModified = other.d->mLastModified;
263 return *this;
264}
265