summaryrefslogtreecommitdiffabout
authorzautrix <zautrix>2004-07-10 17:03:16 (UTC)
committer zautrix <zautrix>2004-07-10 17:03:16 (UTC)
commitcf2f3f98a4811668f9e9d0d5f44ea5b51d268cef (patch) (unidiff)
tree963322cd4c539c084feb43dfde5eabe52ae4385f
parent8cc6d456812b5a9a386e81c9e46baccd56029537 (diff)
downloadkdepimpi-cf2f3f98a4811668f9e9d0d5f44ea5b51d268cef.zip
kdepimpi-cf2f3f98a4811668f9e9d0d5f44ea5b51d268cef.tar.gz
kdepimpi-cf2f3f98a4811668f9e9d0d5f44ea5b51d268cef.tar.bz2
Fixed some problems with the recurrence
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--korganizer/koeditorrecurrence.cpp125
-rw-r--r--korganizer/koeditorrecurrence.h9
-rw-r--r--libkcal/icalformatimpl.cpp20
-rw-r--r--libkcal/recurrence.cpp17
-rw-r--r--libkcal/recurrence.h6
5 files changed, 110 insertions, 67 deletions
diff --git a/korganizer/koeditorrecurrence.cpp b/korganizer/koeditorrecurrence.cpp
index 98356fe..ffc0fac 100644
--- a/korganizer/koeditorrecurrence.cpp
+++ b/korganizer/koeditorrecurrence.cpp
@@ -1,1116 +1,1139 @@
1/* 1/*
2 This file is part of KOrganizer. 2 This file is part of KOrganizer.
3 Copyright (c) 2000-2003 Cornelius Schumacher <schumacher@kde.org> 3 Copyright (c) 2000-2003 Cornelius Schumacher <schumacher@kde.org>
4 4
5 This program is free software; you can redistribute it and/or modify 5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by 6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or 7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version. 8 (at your option) any later version.
9 9
10 This program is distributed in the hope that it will be useful, 10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details. 13 GNU General Public License for more details.
14 14
15 You should have received a copy of the GNU General Public License 15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software 16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 18
19 As a special exception, permission is given to link this program 19 As a special exception, permission is given to link this program
20 with any edition of Qt, and distribute the resulting executable, 20 with any edition of Qt, and distribute the resulting executable,
21 without including the source code for Qt in the source distribution. 21 without including the source code for Qt in the source distribution.
22*/ 22*/
23 23
24#include <qtooltip.h> 24#include <qtooltip.h>
25#include <qfiledialog.h> 25#include <qfiledialog.h>
26#include <qlayout.h> 26#include <qlayout.h>
27#include <qvbox.h> 27#include <qvbox.h>
28#include <qbuttongroup.h> 28#include <qbuttongroup.h>
29#include <qvgroupbox.h> 29#include <qvgroupbox.h>
30#include <qwidgetstack.h> 30#include <qwidgetstack.h>
31#include <qdatetime.h> 31#include <qdatetime.h>
32#include <qlistbox.h> 32#include <qlistbox.h>
33#include <qspinbox.h> 33#include <qspinbox.h>
34#include <qcheckbox.h> 34#include <qcheckbox.h>
35#include <qapplication.h> 35#include <qapplication.h>
36 36
37#include <kdialog.h> 37#include <kdialog.h>
38#include <kglobal.h> 38#include <kglobal.h>
39#include <klocale.h> 39#include <klocale.h>
40#include <kiconloader.h> 40#include <kiconloader.h>
41#include <kdebug.h> 41#include <kdebug.h>
42#include <knumvalidator.h> 42#include <knumvalidator.h>
43 43
44#include <libkcal/event.h> 44#include <libkcal/event.h>
45 45
46#include <libkdepim/kdateedit.h> 46#include <libkdepim/kdateedit.h>
47 47
48#include "koprefs.h" 48#include "koprefs.h"
49 49
50#include "koeditorrecurrence.h" 50#include "koeditorrecurrence.h"
51 51
52/////////////////////////// RecurBase /////////////////////////////// 52/////////////////////////// RecurBase ///////////////////////////////
53 53
54RecurBase::RecurBase( QWidget *parent, const char *name ) : 54RecurBase::RecurBase( QWidget *parent, const char *name ) :
55 QWidget( parent, name ) 55 QWidget( parent, name )
56{ 56{
57 mFrequencyEdit = new QSpinBox( 1, 9999, 1, this ); 57 mFrequencyEdit = new QSpinBox( 1, 9999, 1, this );
58 mFrequencyEdit->setValue( 1 ); 58 mFrequencyEdit->setValue( 1 );
59} 59}
60 60
61QWidget *RecurBase::frequencyEdit() 61QWidget *RecurBase::frequencyEdit()
62{ 62{
63 return mFrequencyEdit; 63 return mFrequencyEdit;
64} 64}
65 65
66void RecurBase::setFrequency( int f ) 66void RecurBase::setFrequency( int f )
67{ 67{
68 if ( f < 1 ) f = 1; 68 if ( f < 1 ) f = 1;
69 69
70 mFrequencyEdit->setValue( f ); 70 mFrequencyEdit->setValue( f );
71} 71}
72 72
73int RecurBase::frequency() 73int RecurBase::frequency()
74{ 74{
75 return mFrequencyEdit->value(); 75 return mFrequencyEdit->value();
76} 76}
77 77
78/////////////////////////// RecurDaily /////////////////////////////// 78/////////////////////////// RecurDaily ///////////////////////////////
79 79
80RecurDaily::RecurDaily( QWidget *parent, const char *name ) : 80RecurDaily::RecurDaily( QWidget *parent, const char *name ) :
81 RecurBase( parent, name ) 81 RecurBase( parent, name )
82{ 82{
83 QBoxLayout *topLayout = new QHBoxLayout( this ); 83 QBoxLayout *topLayout = new QHBoxLayout( this );
84 topLayout->setSpacing( KDialog::spacingHint() ); 84 topLayout->setSpacing( KDialog::spacingHint() );
85 85
86 QLabel *preLabel = new QLabel( i18n("Recur every"), this ); 86 QLabel *preLabel = new QLabel( i18n("Recur every"), this );
87 topLayout->addWidget( preLabel ); 87 topLayout->addWidget( preLabel );
88 88
89 topLayout->addWidget( frequencyEdit() ); 89 topLayout->addWidget( frequencyEdit() );
90 90
91 QLabel *postLabel = new QLabel( i18n("day(s)"), this ); 91 QLabel *postLabel = new QLabel( i18n("day(s)"), this );
92 topLayout->addWidget( postLabel ); 92 topLayout->addWidget( postLabel );
93} 93}
94 94
95 95
96/////////////////////////// RecurWeekly /////////////////////////////// 96/////////////////////////// RecurWeekly ///////////////////////////////
97 97
98RecurWeekly::RecurWeekly( QWidget *parent, const char *name ) : 98RecurWeekly::RecurWeekly( QWidget *parent, const char *name ) :
99 RecurBase( parent, name ) 99 RecurBase( parent, name )
100{ 100{
101 QBoxLayout *topLayout = new QVBoxLayout( this ); 101 QBoxLayout *topLayout = new QVBoxLayout( this );
102 topLayout->setSpacing( KDialog::spacingHint() ); 102 topLayout->setSpacing( KDialog::spacingHint() );
103 103
104 topLayout->addStretch( 1 ); 104 topLayout->addStretch( 1 );
105 105
106 QBoxLayout *weeksLayout = new QHBoxLayout( topLayout ); 106 QBoxLayout *weeksLayout = new QHBoxLayout( topLayout );
107 107
108 QLabel *preLabel = new QLabel( i18n("Recur every"), this ); 108 QLabel *preLabel = new QLabel( i18n("Recur every"), this );
109 weeksLayout->addWidget( preLabel ); 109 weeksLayout->addWidget( preLabel );
110 110
111 weeksLayout->addWidget( frequencyEdit() ); 111 weeksLayout->addWidget( frequencyEdit() );
112 112
113 QLabel *postLabel = new QLabel( i18n("week(s) on:"), this ); 113 QLabel *postLabel = new QLabel( i18n("week(s) on:"), this );
114 weeksLayout->addWidget( postLabel ); 114 weeksLayout->addWidget( postLabel );
115 115
116 QHBox *dayBox = new QHBox( this ); 116 QHBox *dayBox = new QHBox( this );
117 topLayout->addWidget( dayBox, 1, AlignVCenter ); 117 topLayout->addWidget( dayBox, 1, AlignVCenter );
118 // TODO: Respect start of week setting 118 // TODO: Respect start of week setting
119 for ( int i = 0; i < 7; ++i ) { 119 for ( int i = 0; i < 7; ++i ) {
120 QString weekDayName = KGlobal::locale()->weekDayName( i + 1, true ); 120 QString weekDayName = KGlobal::locale()->weekDayName( i + 1, true );
121 if ( KOPrefs::instance()->mCompactDialogs ) { 121 if ( KOPrefs::instance()->mCompactDialogs ) {
122 weekDayName = weekDayName.left( 1 ); 122 weekDayName = weekDayName.left( 1 );
123 } 123 }
124 mDayBoxes[ i ] = new QCheckBox( weekDayName, dayBox ); 124 mDayBoxes[ i ] = new QCheckBox( weekDayName, dayBox );
125 } 125 }
126 126
127 topLayout->addStretch( 1 ); 127 topLayout->addStretch( 1 );
128} 128}
129 129
130void RecurWeekly::setDays( const QBitArray &days ) 130void RecurWeekly::setDays( const QBitArray &days )
131{ 131{
132 for ( int i = 0; i < 7; ++i ) { 132 for ( int i = 0; i < 7; ++i ) {
133 mDayBoxes[ i ]->setChecked( days.testBit( i ) ); 133 mDayBoxes[ i ]->setChecked( days.testBit( i ) );
134 } 134 }
135} 135}
136 136
137QBitArray RecurWeekly::days() 137QBitArray RecurWeekly::days()
138{ 138{
139 QBitArray days( 7 ); 139 QBitArray days( 7 );
140 140
141 for ( int i = 0; i < 7; ++i ) { 141 for ( int i = 0; i < 7; ++i ) {
142 days.setBit( i, mDayBoxes[ i ]->isChecked() ); 142 days.setBit( i, mDayBoxes[ i ]->isChecked() );
143 } 143 }
144 144
145 return days; 145 return days;
146} 146}
147 147
148/////////////////////////// RecurMonthly /////////////////////////////// 148/////////////////////////// RecurMonthly ///////////////////////////////
149 149
150RecurMonthly::RecurMonthly( QWidget *parent, const char *name ) : 150RecurMonthly::RecurMonthly( QWidget *parent, const char *name ) :
151 RecurBase( parent, name ) 151 RecurBase( parent, name )
152{ 152{
153 QBoxLayout *topLayout = new QVBoxLayout( this ); 153 QBoxLayout *topLayout = new QVBoxLayout( this );
154 topLayout->setSpacing( KDialog::spacingHint() ); 154 topLayout->setSpacing( KDialog::spacingHint() );
155 155
156 156
157 QBoxLayout *freqLayout = new QHBoxLayout( topLayout ); 157 QBoxLayout *freqLayout = new QHBoxLayout( topLayout );
158 158
159 QLabel *preLabel = new QLabel( i18n("every"), this ); 159 QLabel *preLabel = new QLabel( i18n("every"), this );
160 freqLayout->addWidget( preLabel ); 160 freqLayout->addWidget( preLabel );
161 161
162 freqLayout->addWidget( frequencyEdit() ); 162 freqLayout->addWidget( frequencyEdit() );
163 163
164 QLabel *postLabel = new QLabel( i18n("month(s)"), this ); 164 QLabel *postLabel = new QLabel( i18n("month(s)"), this );
165 freqLayout->addWidget( postLabel ); 165 freqLayout->addWidget( postLabel );
166 166
167 167
168 QButtonGroup *buttonGroup = new QButtonGroup( this ); 168 QButtonGroup *buttonGroup = new QButtonGroup( this );
169 buttonGroup->setFrameStyle( QFrame::NoFrame ); 169 buttonGroup->setFrameStyle( QFrame::NoFrame );
170 topLayout->addWidget( buttonGroup, 1, AlignVCenter ); 170 topLayout->addWidget( buttonGroup, 1, AlignVCenter );
171 171
172 QGridLayout *buttonLayout = new QGridLayout( buttonGroup, 3, 2 ); 172 QGridLayout *buttonLayout = new QGridLayout( buttonGroup, 3, 2 );
173 buttonLayout->setSpacing( KDialog::spacingHint() ); 173 buttonLayout->setSpacing( KDialog::spacingHint() );
174 174
175 175
176 QString recurOnText; 176 QString recurOnText;
177 if ( !KOPrefs::instance()->mCompactDialogs ) { 177 if ( !KOPrefs::instance()->mCompactDialogs ) {
178 recurOnText = i18n("Recur on the"); 178 recurOnText = i18n("Recur on the");
179 } 179 }
180 180
181 mByDayRadio = new QRadioButton( recurOnText, buttonGroup ); 181 mByDayRadio = new QRadioButton( recurOnText, buttonGroup );
182 buttonLayout->addWidget( mByDayRadio, 0, 0 ); 182 buttonLayout->addWidget( mByDayRadio, 0, 0 );
183 183
184 mByDayCombo = new QComboBox( buttonGroup ); 184 mByDayCombo = new QComboBox( buttonGroup );
185 mByDayCombo->setSizeLimit( 7 ); 185 mByDayCombo->setSizeLimit( 7 );
186 mByDayCombo->insertItem( i18n("1st") ); 186 mByDayCombo->insertItem( i18n("1st") );
187 mByDayCombo->insertItem( i18n("2nd") ); 187 mByDayCombo->insertItem( i18n("2nd") );
188 mByDayCombo->insertItem( i18n("3rd") ); 188 mByDayCombo->insertItem( i18n("3rd") );
189 mByDayCombo->insertItem( i18n("4th") ); 189 mByDayCombo->insertItem( i18n("4th") );
190 mByDayCombo->insertItem( i18n("5th") ); 190 mByDayCombo->insertItem( i18n("5th") );
191 mByDayCombo->insertItem( i18n("6th") ); 191 mByDayCombo->insertItem( i18n("6th") );
192 mByDayCombo->insertItem( i18n("7th") ); 192 mByDayCombo->insertItem( i18n("7th") );
193 mByDayCombo->insertItem( i18n("8th") ); 193 mByDayCombo->insertItem( i18n("8th") );
194 mByDayCombo->insertItem( i18n("9th") ); 194 mByDayCombo->insertItem( i18n("9th") );
195 mByDayCombo->insertItem( i18n("10th") ); 195 mByDayCombo->insertItem( i18n("10th") );
196 mByDayCombo->insertItem( i18n("11th") ); 196 mByDayCombo->insertItem( i18n("11th") );
197 mByDayCombo->insertItem( i18n("12th") ); 197 mByDayCombo->insertItem( i18n("12th") );
198 mByDayCombo->insertItem( i18n("13th") ); 198 mByDayCombo->insertItem( i18n("13th") );
199 mByDayCombo->insertItem( i18n("14th") ); 199 mByDayCombo->insertItem( i18n("14th") );
200 mByDayCombo->insertItem( i18n("15th") ); 200 mByDayCombo->insertItem( i18n("15th") );
201 mByDayCombo->insertItem( i18n("16th") ); 201 mByDayCombo->insertItem( i18n("16th") );
202 mByDayCombo->insertItem( i18n("17th") ); 202 mByDayCombo->insertItem( i18n("17th") );
203 mByDayCombo->insertItem( i18n("18th") ); 203 mByDayCombo->insertItem( i18n("18th") );
204 mByDayCombo->insertItem( i18n("19th") ); 204 mByDayCombo->insertItem( i18n("19th") );
205 mByDayCombo->insertItem( i18n("20th") ); 205 mByDayCombo->insertItem( i18n("20th") );
206 mByDayCombo->insertItem( i18n("21st") ); 206 mByDayCombo->insertItem( i18n("21st") );
207 mByDayCombo->insertItem( i18n("22nd") ); 207 mByDayCombo->insertItem( i18n("22nd") );
208 mByDayCombo->insertItem( i18n("23rd") ); 208 mByDayCombo->insertItem( i18n("23rd") );
209 mByDayCombo->insertItem( i18n("24th") ); 209 mByDayCombo->insertItem( i18n("24th") );
210 mByDayCombo->insertItem( i18n("25th") ); 210 mByDayCombo->insertItem( i18n("25th") );
211 mByDayCombo->insertItem( i18n("26th") ); 211 mByDayCombo->insertItem( i18n("26th") );
212 mByDayCombo->insertItem( i18n("27th") ); 212 mByDayCombo->insertItem( i18n("27th") );
213 mByDayCombo->insertItem( i18n("28th") ); 213 mByDayCombo->insertItem( i18n("28th") );
214 mByDayCombo->insertItem( i18n("29th") ); 214 mByDayCombo->insertItem( i18n("29th") );
215 mByDayCombo->insertItem( i18n("30th") ); 215 mByDayCombo->insertItem( i18n("30th") );
216 mByDayCombo->insertItem( i18n("31st") ); 216 mByDayCombo->insertItem( i18n("31st") );
217 buttonLayout->addWidget( mByDayCombo, 0, 1 ); 217 buttonLayout->addWidget( mByDayCombo, 0, 1 );
218 218
219 QLabel *byDayLabel = new QLabel( i18n("day"), buttonGroup ); 219 QLabel *byDayLabel = new QLabel( i18n("day"), buttonGroup );
220 buttonLayout->addWidget( byDayLabel, 0, 2 ); 220 buttonLayout->addWidget( byDayLabel, 0, 2 );
221 221
222 222
223 mByPosRadio = new QRadioButton( recurOnText, buttonGroup); 223 mByPosRadio = new QRadioButton( recurOnText, buttonGroup);
224 buttonLayout->addWidget( mByPosRadio, 1, 0 ); 224 buttonLayout->addWidget( mByPosRadio, 1, 0 );
225 225
226 mByPosCountCombo = new QComboBox( buttonGroup ); 226 mByPosCountCombo = new QComboBox( buttonGroup );
227 mByPosCountCombo->insertItem( i18n("1st") ); 227 mByPosCountCombo->insertItem( i18n("1st") );
228 mByPosCountCombo->insertItem( i18n("2nd") ); 228 mByPosCountCombo->insertItem( i18n("2nd") );
229 mByPosCountCombo->insertItem( i18n("3rd") ); 229 mByPosCountCombo->insertItem( i18n("3rd") );
230 mByPosCountCombo->insertItem( i18n("4th") ); 230 mByPosCountCombo->insertItem( i18n("4th") );
231 mByPosCountCombo->insertItem( i18n("5th") ); 231 mByPosCountCombo->insertItem( i18n("5th") );
232 buttonLayout->addWidget( mByPosCountCombo, 1, 1 ); 232 buttonLayout->addWidget( mByPosCountCombo, 1, 1 );
233 233
234 mByPosWeekdayCombo = new QComboBox( buttonGroup ); 234 mByPosWeekdayCombo = new QComboBox( buttonGroup );
235 mByPosWeekdayCombo->insertItem( i18n("Monday") ); 235 mByPosWeekdayCombo->insertItem( i18n("Monday") );
236 mByPosWeekdayCombo->insertItem( i18n("Tuesday") ); 236 mByPosWeekdayCombo->insertItem( i18n("Tuesday") );
237 mByPosWeekdayCombo->insertItem( i18n("Wednesday") ); 237 mByPosWeekdayCombo->insertItem( i18n("Wednesday") );
238 mByPosWeekdayCombo->insertItem( i18n("Thursday") ); 238 mByPosWeekdayCombo->insertItem( i18n("Thursday") );
239 mByPosWeekdayCombo->insertItem( i18n("Friday") ); 239 mByPosWeekdayCombo->insertItem( i18n("Friday") );
240 mByPosWeekdayCombo->insertItem( i18n("Saturday") ); 240 mByPosWeekdayCombo->insertItem( i18n("Saturday") );
241 mByPosWeekdayCombo->insertItem( i18n("Sunday") ); 241 mByPosWeekdayCombo->insertItem( i18n("Sunday") );
242 buttonLayout->addWidget( mByPosWeekdayCombo, 1, 2 ); 242 buttonLayout->addWidget( mByPosWeekdayCombo, 1, 2 );
243} 243}
244 244
245void RecurMonthly::setByDay( int day ) 245void RecurMonthly::setByDay( int day )
246{ 246{
247 mByDayRadio->setChecked( true ); 247 mByDayRadio->setChecked( true );
248 mByDayCombo->setCurrentItem( day ); 248 mByDayCombo->setCurrentItem( day );
249} 249}
250 250
251void RecurMonthly::setByPos( int count, int weekday ) 251void RecurMonthly::setByPos( int count, int weekday )
252{ 252{
253 mByPosRadio->setChecked( true ); 253 mByPosRadio->setChecked( true );
254 mByPosCountCombo->setCurrentItem( count ); 254 mByPosCountCombo->setCurrentItem( count );
255 mByPosWeekdayCombo->setCurrentItem( weekday ); 255 mByPosWeekdayCombo->setCurrentItem( weekday );
256} 256}
257 257
258bool RecurMonthly::byDay() 258bool RecurMonthly::byDay()
259{ 259{
260 return mByDayRadio->isChecked(); 260 return mByDayRadio->isChecked();
261} 261}
262 262
263bool RecurMonthly::byPos() 263bool RecurMonthly::byPos()
264{ 264{
265 return mByPosRadio->isChecked(); 265 return mByPosRadio->isChecked();
266} 266}
267 267
268int RecurMonthly::day() 268int RecurMonthly::day()
269{ 269{
270 return mByDayCombo->currentItem() + 1; 270 return mByDayCombo->currentItem() + 1;
271} 271}
272 272
273int RecurMonthly::count() 273int RecurMonthly::count()
274{ 274{
275 return mByPosCountCombo->currentItem() + 1; 275 return mByPosCountCombo->currentItem() + 1;
276} 276}
277 277
278int RecurMonthly::weekday() 278int RecurMonthly::weekday()
279{ 279{
280 return mByPosWeekdayCombo->currentItem(); 280 return mByPosWeekdayCombo->currentItem();
281} 281}
282 282
283/////////////////////////// RecurYearly /////////////////////////////// 283/////////////////////////// RecurYearly ///////////////////////////////
284 284
285RecurYearly::RecurYearly( QWidget *parent, const char *name ) : 285RecurYearly::RecurYearly( QWidget *parent, const char *name ) :
286 RecurBase( parent, name ) 286 RecurBase( parent, name )
287{ 287{
288 QBoxLayout *topLayout = new QVBoxLayout( this ); 288 QBoxLayout *topLayout = new QVBoxLayout( this );
289 topLayout->setSpacing( KDialog::spacingHint() ); 289 topLayout->setSpacing( KDialog::spacingHint() );
290 290
291 291
292 QBoxLayout *freqLayout = new QHBoxLayout( topLayout ); 292 QBoxLayout *freqLayout = new QHBoxLayout( topLayout );
293 293
294 QLabel *preLabel = new QLabel( i18n("every"), this ); 294 QLabel *preLabel = new QLabel( i18n("every"), this );
295 freqLayout->addWidget( preLabel ); 295 freqLayout->addWidget( preLabel );
296 296
297 freqLayout->addWidget( frequencyEdit() ); 297 freqLayout->addWidget( frequencyEdit() );
298 298
299 QLabel *postLabel = new QLabel( i18n("year(s)"), this ); 299 QLabel *postLabel = new QLabel( i18n("year(s)"), this );
300 freqLayout->addWidget( postLabel ); 300 freqLayout->addWidget( postLabel );
301 301
302 302
303 QButtonGroup *buttonGroup = new QButtonGroup( this ); 303 QButtonGroup *buttonGroup = new QButtonGroup( this );
304 buttonGroup->setFrameStyle( QFrame::NoFrame ); 304 buttonGroup->setFrameStyle( QFrame::NoFrame );
305 topLayout->addWidget( buttonGroup, 1, AlignVCenter ); 305 topLayout->addWidget( buttonGroup, 1, AlignVCenter );
306 306
307 QGridLayout *buttonLayout = new QGridLayout( buttonGroup, 3, 2 ); 307 QGridLayout *buttonLayout = new QGridLayout( buttonGroup, 2, 3 );
308
309 QString recurInMonthText;
310 if ( !KOPrefs::instance()->mCompactDialogs ) {
311 recurInMonthText = i18n("Recur in the month of");
312 }
313
314 mByMonthRadio = new QRadioButton( recurInMonthText, buttonGroup);
315 buttonLayout->addWidget( mByMonthRadio, 0, 0 );
316 308
309 mByMonthRadio = new QRadioButton( i18n("On day "), buttonGroup);
310 buttonLayout->addWidget( mByMonthRadio, 0, 0 , Qt::AlignRight);
311 mByDayLabel = new QLabel( i18n(" 1 of "), buttonGroup );
312
313 buttonLayout->addWidget( mByDayLabel, 0, 1 );
317 mByMonthCombo = new QComboBox( buttonGroup ); 314 mByMonthCombo = new QComboBox( buttonGroup );
318 mByMonthCombo->insertItem( i18n("January") ); 315 mByMonthCombo->insertItem( i18n("January") );
319 mByMonthCombo->insertItem( i18n("February") ); 316 mByMonthCombo->insertItem( i18n("February") );
320 mByMonthCombo->insertItem( i18n("March") ); 317 mByMonthCombo->insertItem( i18n("March") );
321 mByMonthCombo->insertItem( i18n("April") ); 318 mByMonthCombo->insertItem( i18n("April") );
322 mByMonthCombo->insertItem( i18n("May") ); 319 mByMonthCombo->insertItem( i18n("May") );
323 mByMonthCombo->insertItem( i18n("June") ); 320 mByMonthCombo->insertItem( i18n("June") );
324 mByMonthCombo->insertItem( i18n("July") ); 321 mByMonthCombo->insertItem( i18n("July") );
325 mByMonthCombo->insertItem( i18n("August") ); 322 mByMonthCombo->insertItem( i18n("August") );
326 mByMonthCombo->insertItem( i18n("September") ); 323 mByMonthCombo->insertItem( i18n("September") );
327 mByMonthCombo->insertItem( i18n("October") ); 324 mByMonthCombo->insertItem( i18n("October") );
328 mByMonthCombo->insertItem( i18n("November") ); 325 mByMonthCombo->insertItem( i18n("November") );
329 mByMonthCombo->insertItem( i18n("December") ); 326 mByMonthCombo->insertItem( i18n("December") );
330 buttonLayout->addWidget( mByMonthCombo, 0, 1 ); 327 buttonLayout->addWidget( mByMonthCombo, 0, 2,Qt::AlignLeft );
331 328 if ( QApplication::desktop()->width() <= 640 ) {
332 mByMonthCombo->setSizeLimit( 6 ); 329 mByMonthCombo->setSizeLimit( 6 );
333 330 }
334 buttonLayout->setRowStretch( 1, 1 ); 331
335 332 mByDayRadio = new QRadioButton( i18n("On day "), buttonGroup);
336 QString recurOnDayText; 333 buttonLayout->addWidget( mByDayRadio, 1, 0 , Qt::AlignRight);
337 if ( KOPrefs::instance()->mCompactDialogs ) { 334 mDayOfLabel = new QLabel( i18n("1 of the year"), buttonGroup );
338 recurOnDayText = i18n("This day"); 335 buttonLayout->addMultiCellWidget( mDayOfLabel, 1, 1, 1,3 );
339 } else { 336
340 recurOnDayText = i18n("Recur on this day");
341 }
342
343 mByDayRadio = new QRadioButton( recurOnDayText, buttonGroup);
344 buttonLayout->addMultiCellWidget( mByDayRadio, 2, 2, 0, 1 );
345} 337}
346 338
347void RecurYearly::setByDay() 339void RecurYearly::setByDay( int doy )
348{ 340{
349 mByDayRadio->setChecked( true ); 341 mByDayRadio->setChecked( true );
342 mDayOfLabel->setText(i18n("%1 of the year").arg( doy ) );
350} 343}
351 344
352void RecurYearly::setByMonth( int month ) 345void RecurYearly::setByMonth( int month, int day )
353{ 346{
354 mByMonthRadio->setChecked( true ); 347 mByMonthRadio->setChecked( true );
355 mByMonthCombo->setCurrentItem( month - 1 ); 348 mByMonthCombo->setCurrentItem( month - 1 );
349 mByDayLabel->setText(i18n("%1 of ").arg( day ) );
350 mDay = day;
356} 351}
357 352
358bool RecurYearly::byMonth() 353bool RecurYearly::byMonth()
359{ 354{
360 return mByMonthRadio->isChecked(); 355 return mByMonthRadio->isChecked();
361} 356}
362 357
363bool RecurYearly::byDay() 358bool RecurYearly::byDay()
364{ 359{
365 return mByDayRadio->isChecked(); 360 return mByDayRadio->isChecked();
366} 361}
367 362
368int RecurYearly::month() 363int RecurYearly::month()
369{ 364{
370 return mByMonthCombo->currentItem() + 1; 365 return mByMonthCombo->currentItem() + 1;
371} 366}
367int RecurYearly::day()
368{
369 return mDay;//mByDayCombo->currentItem() + 1;
370}
372 371
373//////////////////////////// ExceptionsWidget ////////////////////////// 372//////////////////////////// ExceptionsWidget //////////////////////////
374 373
375ExceptionsWidget::ExceptionsWidget( QWidget *parent, const char *name ) : 374ExceptionsWidget::ExceptionsWidget( QWidget *parent, const char *name ) :
376 QWidget( parent, name ) 375 QWidget( parent, name )
377{ 376{
378 QBoxLayout *topLayout = new QVBoxLayout( this ); 377 QBoxLayout *topLayout = new QVBoxLayout( this );
379 378
380 QGroupBox *groupBox = new QGroupBox( 1, Horizontal, i18n("Exceptions"), 379 QGroupBox *groupBox = new QGroupBox( 1, Horizontal, i18n("Exceptions"),
381 this ); 380 this );
382 topLayout->addWidget( groupBox ); 381 topLayout->addWidget( groupBox );
383 382
384 QWidget *box = new QWidget( groupBox ); 383 QWidget *box = new QWidget( groupBox );
385 384
386 QGridLayout *boxLayout = new QGridLayout( box ); 385 QGridLayout *boxLayout = new QGridLayout( box );
387 386
388 mExceptionDateEdit = new KDateEdit( box ); 387 mExceptionDateEdit = new KDateEdit( box );
389 boxLayout->addWidget( mExceptionDateEdit, 0, 0 ); 388 boxLayout->addWidget( mExceptionDateEdit, 0, 0 );
390 389
391 QPushButton *addExceptionButton = new QPushButton( i18n("Add"), box ); 390 QPushButton *addExceptionButton = new QPushButton( i18n("Add"), box );
392 boxLayout->addWidget( addExceptionButton, 1, 0 ); 391 boxLayout->addWidget( addExceptionButton, 1, 0 );
393 QPushButton *changeExceptionButton = new QPushButton( i18n("Change"), box ); 392 QPushButton *changeExceptionButton = new QPushButton( i18n("Change"), box );
394 boxLayout->addWidget( changeExceptionButton, 2, 0 ); 393 boxLayout->addWidget( changeExceptionButton, 2, 0 );
395 QPushButton *deleteExceptionButton = new QPushButton( i18n("Delete"), box ); 394 QPushButton *deleteExceptionButton = new QPushButton( i18n("Delete"), box );
396 boxLayout->addWidget( deleteExceptionButton, 3, 0 ); 395 boxLayout->addWidget( deleteExceptionButton, 3, 0 );
397 396
398 mExceptionList = new QListBox( box ); 397 mExceptionList = new QListBox( box );
399 boxLayout->addMultiCellWidget( mExceptionList, 0, 3, 1, 1 ); 398 boxLayout->addMultiCellWidget( mExceptionList, 0, 3, 1, 1 );
400 399
401 boxLayout->setRowStretch( 4, 1 ); 400 boxLayout->setRowStretch( 4, 1 );
402 boxLayout->setColStretch( 1, 3 ); 401 boxLayout->setColStretch( 1, 3 );
403 402
404 connect( addExceptionButton, SIGNAL( clicked() ), 403 connect( addExceptionButton, SIGNAL( clicked() ),
405 SLOT( addException() ) ); 404 SLOT( addException() ) );
406 connect( changeExceptionButton, SIGNAL( clicked() ), 405 connect( changeExceptionButton, SIGNAL( clicked() ),
407 SLOT( changeException() ) ); 406 SLOT( changeException() ) );
408 connect( deleteExceptionButton, SIGNAL( clicked() ), 407 connect( deleteExceptionButton, SIGNAL( clicked() ),
409 SLOT( deleteException() ) ); 408 SLOT( deleteException() ) );
410 if ( QApplication::desktop()->width() < 480 ) { 409 if ( QApplication::desktop()->width() < 480 ) {
411 setMinimumWidth( 220 ); 410 setMinimumWidth( 220 );
412 } else { 411 } else {
413 setMinimumWidth( 440 ); 412 setMinimumWidth( 440 );
414 mExceptionDateEdit->setMinimumWidth( 200 ); 413 mExceptionDateEdit->setMinimumWidth( 200 );
415 } 414 }
416} 415}
417 416
418void ExceptionsWidget::setDefaults( const QDateTime &from ) 417void ExceptionsWidget::setDefaults( const QDateTime &from )
419{ 418{
420 mExceptionDateEdit->setDate( from.date() ); 419 mExceptionDateEdit->setDate( from.date() );
421} 420}
422 421
423void ExceptionsWidget::addException() 422void ExceptionsWidget::addException()
424{ 423{
425 QDate date = mExceptionDateEdit->date(); 424 QDate date = mExceptionDateEdit->date();
426 QString dateStr = KGlobal::locale()->formatDate( date ); 425 QString dateStr = KGlobal::locale()->formatDate( date );
427 if( !mExceptionList->findItem( dateStr ) ) { 426 if( !mExceptionList->findItem( dateStr ) ) {
428 mExceptionDates.append( date ); 427 mExceptionDates.append( date );
429 mExceptionList->insertItem( dateStr ); 428 mExceptionList->insertItem( dateStr );
430 } 429 }
431} 430}
432 431
433void ExceptionsWidget::changeException() 432void ExceptionsWidget::changeException()
434{ 433{
435 int pos = mExceptionList->currentItem(); 434 int pos = mExceptionList->currentItem();
436 if ( pos < 0 ) return; 435 if ( pos < 0 ) return;
437 436
438 QDate date = mExceptionDateEdit->date(); 437 QDate date = mExceptionDateEdit->date();
439 mExceptionDates[ pos ] = date; 438 mExceptionDates[ pos ] = date;
440 mExceptionList->changeItem( KGlobal::locale()->formatDate( date ), pos ); 439 mExceptionList->changeItem( KGlobal::locale()->formatDate( date ), pos );
441} 440}
442 441
443void ExceptionsWidget::deleteException() 442void ExceptionsWidget::deleteException()
444{ 443{
445 int pos = mExceptionList->currentItem(); 444 int pos = mExceptionList->currentItem();
446 if ( pos < 0 ) return; 445 if ( pos < 0 ) return;
447 446
448 mExceptionDates.remove( mExceptionDates.at( pos ) ); 447 mExceptionDates.remove( mExceptionDates.at( pos ) );
449 mExceptionList->removeItem( pos ); 448 mExceptionList->removeItem( pos );
450} 449}
451 450
452void ExceptionsWidget::setDates( const DateList &dates ) 451void ExceptionsWidget::setDates( const DateList &dates )
453{ 452{
454 mExceptionList->clear(); 453 mExceptionList->clear();
455 mExceptionDates.clear(); 454 mExceptionDates.clear();
456 DateList::ConstIterator dit; 455 DateList::ConstIterator dit;
457 for ( dit = dates.begin(); dit != dates.end(); ++dit ) { 456 for ( dit = dates.begin(); dit != dates.end(); ++dit ) {
458 mExceptionList->insertItem( KGlobal::locale()->formatDate(* dit ) ); 457 mExceptionList->insertItem( KGlobal::locale()->formatDate(* dit ) );
459 mExceptionDates.append( *dit ); 458 mExceptionDates.append( *dit );
460 } 459 }
461} 460}
462 461
463DateList ExceptionsWidget::dates() 462DateList ExceptionsWidget::dates()
464{ 463{
465 return mExceptionDates; 464 return mExceptionDates;
466} 465}
467 466
468///////////////////////// ExceptionsDialog /////////////////////////// 467///////////////////////// ExceptionsDialog ///////////////////////////
469 468
470ExceptionsDialog::ExceptionsDialog( QWidget *parent, const char *name ) : 469ExceptionsDialog::ExceptionsDialog( QWidget *parent, const char *name ) :
471 KDialogBase( parent, name, true, i18n("Edit exceptions"), Ok|Cancel ) 470 KDialogBase( parent, name, true, i18n("Edit exceptions"), Ok|Cancel )
472{ 471{
473 mExceptions = new ExceptionsWidget( this ); 472 mExceptions = new ExceptionsWidget( this );
474 setMainWidget( mExceptions ); 473 setMainWidget( mExceptions );
475 resize(220,10); 474 resize(220,10);
476} 475}
477 476
478void ExceptionsDialog::setDefaults( const QDateTime &from ) 477void ExceptionsDialog::setDefaults( const QDateTime &from )
479{ 478{
480 mExceptions->setDefaults( from ); 479 mExceptions->setDefaults( from );
481} 480}
482 481
483void ExceptionsDialog::setDates( const DateList &dates ) 482void ExceptionsDialog::setDates( const DateList &dates )
484{ 483{
485 mExceptions->setDates( dates ); 484 mExceptions->setDates( dates );
486} 485}
487 486
488DateList ExceptionsDialog::dates() 487DateList ExceptionsDialog::dates()
489{ 488{
490 return mExceptions->dates(); 489 return mExceptions->dates();
491} 490}
492 491
493///////////////////////// RecurrenceRangeWidget /////////////////////////// 492///////////////////////// RecurrenceRangeWidget ///////////////////////////
494 493
495RecurrenceRangeWidget::RecurrenceRangeWidget( QWidget *parent, 494RecurrenceRangeWidget::RecurrenceRangeWidget( QWidget *parent,
496 const char *name ) 495 const char *name )
497 : QWidget( parent, name ) 496 : QWidget( parent, name )
498{ 497{
499 QBoxLayout *topLayout = new QVBoxLayout( this ); 498 QBoxLayout *topLayout = new QVBoxLayout( this );
500 499
501 mRangeGroupBox = new QGroupBox( 1, Horizontal, i18n("Recurrence Range"), 500 mRangeGroupBox = new QGroupBox( 1, Horizontal, i18n("Recurrence Range"),
502 this ); 501 this );
503 topLayout->addWidget( mRangeGroupBox ); 502 topLayout->addWidget( mRangeGroupBox );
504 503
505 QWidget *rangeBox = new QWidget( mRangeGroupBox ); 504 QWidget *rangeBox = new QWidget( mRangeGroupBox );
506 QVBoxLayout *rangeLayout = new QVBoxLayout( rangeBox ); 505 QVBoxLayout *rangeLayout = new QVBoxLayout( rangeBox );
507 rangeLayout->setSpacing( KDialog::spacingHint() ); 506 rangeLayout->setSpacing( KDialog::spacingHint() );
508 507
509 mStartDateLabel = new QLabel( i18n("Begin on:"), rangeBox ); 508 mStartDateLabel = new QLabel( i18n("Begin on:"), rangeBox );
510 rangeLayout->addWidget( mStartDateLabel ); 509 rangeLayout->addWidget( mStartDateLabel );
511 510
512 QButtonGroup *rangeButtonGroup = new QButtonGroup; 511 QButtonGroup *rangeButtonGroup = new QButtonGroup;
513 512
514 mNoEndDateButton = new QRadioButton( i18n("No ending date"), rangeBox ); 513 mNoEndDateButton = new QRadioButton( i18n("No ending date"), rangeBox );
515 rangeButtonGroup->insert( mNoEndDateButton ); 514 rangeButtonGroup->insert( mNoEndDateButton );
516 rangeLayout->addWidget( mNoEndDateButton ); 515 rangeLayout->addWidget( mNoEndDateButton );
517 516
518 QBoxLayout *durationLayout = new QHBoxLayout( rangeLayout ); 517 QBoxLayout *durationLayout = new QHBoxLayout( rangeLayout );
519 durationLayout->setSpacing( KDialog::spacingHint() ); 518 durationLayout->setSpacing( KDialog::spacingHint() );
520 519
521 mEndDurationButton = new QRadioButton( i18n("End after"), rangeBox ); 520 mEndDurationButton = new QRadioButton( i18n("End after"), rangeBox );
522 rangeButtonGroup->insert( mEndDurationButton ); 521 rangeButtonGroup->insert( mEndDurationButton );
523 durationLayout->addWidget( mEndDurationButton ); 522 durationLayout->addWidget( mEndDurationButton );
524 523
525 mEndDurationEdit = new QSpinBox( 1, 9999, 1, rangeBox ); 524 mEndDurationEdit = new QSpinBox( 1, 9999, 1, rangeBox );
526 durationLayout->addWidget( mEndDurationEdit ); 525 durationLayout->addWidget( mEndDurationEdit );
527 526
528 QLabel *endDurationLabel = new QLabel( i18n("occurrence(s)"), rangeBox ); 527 QLabel *endDurationLabel = new QLabel( i18n("occurrence(s)"), rangeBox );
529 durationLayout ->addWidget( endDurationLabel ); 528 durationLayout ->addWidget( endDurationLabel );
530 529
531 QBoxLayout *endDateLayout = new QHBoxLayout( rangeLayout ); 530 QBoxLayout *endDateLayout = new QHBoxLayout( rangeLayout );
532 endDateLayout->setSpacing( KDialog::spacingHint() ); 531 endDateLayout->setSpacing( KDialog::spacingHint() );
533 532
534 mEndDateButton = new QRadioButton( i18n("End by:"), rangeBox ); 533 mEndDateButton = new QRadioButton( i18n("End by:"), rangeBox );
535 rangeButtonGroup->insert( mEndDateButton ); 534 rangeButtonGroup->insert( mEndDateButton );
536 endDateLayout->addWidget( mEndDateButton ); 535 endDateLayout->addWidget( mEndDateButton );
537 536
538 mEndDateEdit = new KDateEdit( rangeBox ); 537 mEndDateEdit = new KDateEdit( rangeBox );
539 endDateLayout->addWidget( mEndDateEdit ); 538 endDateLayout->addWidget( mEndDateEdit );
540 539
541 endDateLayout->addStretch( 1 ); 540 endDateLayout->addStretch( 1 );
542 541
543 connect( mNoEndDateButton, SIGNAL( toggled( bool ) ), 542 connect( mNoEndDateButton, SIGNAL( toggled( bool ) ),
544 SLOT( showCurrentRange() ) ); 543 SLOT( showCurrentRange() ) );
545 connect( mEndDurationButton, SIGNAL( toggled( bool ) ), 544 connect( mEndDurationButton, SIGNAL( toggled( bool ) ),
546 SLOT( showCurrentRange() ) ); 545 SLOT( showCurrentRange() ) );
547 connect( mEndDateButton, SIGNAL( toggled( bool ) ), 546 connect( mEndDateButton, SIGNAL( toggled( bool ) ),
548 SLOT( showCurrentRange() ) ); 547 SLOT( showCurrentRange() ) );
549} 548}
550 549
551void RecurrenceRangeWidget::setDefaults( const QDateTime &from ) 550void RecurrenceRangeWidget::setDefaults( const QDateTime &from )
552{ 551{
553 mNoEndDateButton->setChecked( true ); 552 mNoEndDateButton->setChecked( true );
554 553
555 setDateTimes( from ); 554 setDateTimes( from );
556 mEndDateEdit->setDate( from.date() ); 555 mEndDateEdit->setDate( from.date() );
557} 556}
558 557
559void RecurrenceRangeWidget::setDuration( int duration ) 558void RecurrenceRangeWidget::setDuration( int duration )
560{ 559{
561 if ( duration == -1 ) { 560 if ( duration == -1 ) {
562 mNoEndDateButton->setChecked( true ); 561 mNoEndDateButton->setChecked( true );
563 } else if ( duration == 0 ) { 562 } else if ( duration == 0 ) {
564 mEndDateButton->setChecked( true ); 563 mEndDateButton->setChecked( true );
565 } else { 564 } else {
566 mEndDurationButton->setChecked( true ); 565 mEndDurationButton->setChecked( true );
567 mEndDurationEdit->setValue( duration ); 566 mEndDurationEdit->setValue( duration );
568 } 567 }
569} 568}
570 569
571int RecurrenceRangeWidget::duration() 570int RecurrenceRangeWidget::duration()
572{ 571{
573 if ( mNoEndDateButton->isChecked() ) { 572 if ( mNoEndDateButton->isChecked() ) {
574 return -1; 573 return -1;
575 } else if ( mEndDurationButton->isChecked() ) { 574 } else if ( mEndDurationButton->isChecked() ) {
576 return mEndDurationEdit->value(); 575 return mEndDurationEdit->value();
577 } else { 576 } else {
578 return 0; 577 return 0;
579 } 578 }
580} 579}
581 580
582void RecurrenceRangeWidget::setEndDate( const QDate &date ) 581void RecurrenceRangeWidget::setEndDate( const QDate &date )
583{ 582{
584 mEndDateEdit->setDate( date ); 583 mEndDateEdit->setDate( date );
585} 584}
586 585
587QDate RecurrenceRangeWidget::endDate() 586QDate RecurrenceRangeWidget::endDate()
588{ 587{
589 return mEndDateEdit->date(); 588 return mEndDateEdit->date();
590} 589}
591 590
592void RecurrenceRangeWidget::showCurrentRange() 591void RecurrenceRangeWidget::showCurrentRange()
593{ 592{
594 mEndDurationEdit->setEnabled( mEndDurationButton->isChecked() ); 593 mEndDurationEdit->setEnabled( mEndDurationButton->isChecked() );
595 mEndDateEdit->setEnabled( mEndDateButton->isChecked() ); 594 mEndDateEdit->setEnabled( mEndDateButton->isChecked() );
596} 595}
597 596
598void RecurrenceRangeWidget::setDateTimes( const QDateTime &start, 597void RecurrenceRangeWidget::setDateTimes( const QDateTime &start,
599 const QDateTime & ) 598 const QDateTime & )
600{ 599{
601 mStartDateLabel->setText( i18n("Start date: %1") 600 mStartDateLabel->setText( i18n("Start date: %1")
602 .arg( KGlobal::locale()->formatDate( start.date() ) ) ); 601 .arg( KGlobal::locale()->formatDate( start.date() ) ) );
603 602
604 if(!mEndDateButton->isChecked()) 603 if(!mEndDateButton->isChecked())
605 mEndDateEdit->setDate( start.date() ); 604 mEndDateEdit->setDate( start.date() );
606} 605}
607 606
608///////////////////////// RecurrenceRangeDialog /////////////////////////// 607///////////////////////// RecurrenceRangeDialog ///////////////////////////
609 608
610RecurrenceRangeDialog::RecurrenceRangeDialog( QWidget *parent, 609RecurrenceRangeDialog::RecurrenceRangeDialog( QWidget *parent,
611 const char *name ) : 610 const char *name ) :
612 KDialogBase( parent, name, true, i18n("Edit Recurrence Range"), Ok|Cancel ) 611 KDialogBase( parent, name, true, i18n("Edit Recurrence Range"), Ok|Cancel )
613{ 612{
614 mRecurrenceRangeWidget = new RecurrenceRangeWidget( this ); 613 mRecurrenceRangeWidget = new RecurrenceRangeWidget( this );
615 setMainWidget( mRecurrenceRangeWidget ); 614 setMainWidget( mRecurrenceRangeWidget );
616} 615}
617 616
618void RecurrenceRangeDialog::setDefaults( const QDateTime &from ) 617void RecurrenceRangeDialog::setDefaults( const QDateTime &from )
619{ 618{
620 mRecurrenceRangeWidget->setDefaults( from ); 619 mRecurrenceRangeWidget->setDefaults( from );
621} 620}
622 621
623void RecurrenceRangeDialog::setDuration( int duration ) 622void RecurrenceRangeDialog::setDuration( int duration )
624{ 623{
625 mRecurrenceRangeWidget->setDuration( duration ); 624 mRecurrenceRangeWidget->setDuration( duration );
626} 625}
627 626
628int RecurrenceRangeDialog::duration() 627int RecurrenceRangeDialog::duration()
629{ 628{
630 return mRecurrenceRangeWidget->duration(); 629 return mRecurrenceRangeWidget->duration();
631} 630}
632 631
633void RecurrenceRangeDialog::setEndDate( const QDate &date ) 632void RecurrenceRangeDialog::setEndDate( const QDate &date )
634{ 633{
635 mRecurrenceRangeWidget->setEndDate( date ); 634 mRecurrenceRangeWidget->setEndDate( date );
636} 635}
637 636
638QDate RecurrenceRangeDialog::endDate() 637QDate RecurrenceRangeDialog::endDate()
639{ 638{
640 return mRecurrenceRangeWidget->endDate(); 639 return mRecurrenceRangeWidget->endDate();
641} 640}
642 641
643void RecurrenceRangeDialog::setDateTimes( const QDateTime &start, 642void RecurrenceRangeDialog::setDateTimes( const QDateTime &start,
644 const QDateTime &end ) 643 const QDateTime &end )
645{ 644{
646 mRecurrenceRangeWidget->setDateTimes( start, end ); 645 mRecurrenceRangeWidget->setDateTimes( start, end );
647} 646}
648 647
649//////////////////////////// RecurrenceChooser //////////////////////// 648//////////////////////////// RecurrenceChooser ////////////////////////
650 649
651RecurrenceChooser::RecurrenceChooser( QWidget *parent, const char *name ) : 650RecurrenceChooser::RecurrenceChooser( QWidget *parent, const char *name ) :
652 QWidget( parent, name ) 651 QWidget( parent, name )
653{ 652{
654 QBoxLayout *topLayout = new QVBoxLayout( this ); 653 QBoxLayout *topLayout = new QVBoxLayout( this );
655 654
656 if ( KOPrefs::instance()->mCompactDialogs ) { 655 if ( KOPrefs::instance()->mCompactDialogs ) {
657 mTypeCombo = new QComboBox( this ); 656 mTypeCombo = new QComboBox( this );
658 mTypeCombo->insertItem( i18n("Daily") ); 657 mTypeCombo->insertItem( i18n("Daily") );
659 mTypeCombo->insertItem( i18n("Weekly") ); 658 mTypeCombo->insertItem( i18n("Weekly") );
660 mTypeCombo->insertItem( i18n("Monthly") ); 659 mTypeCombo->insertItem( i18n("Monthly") );
661 mTypeCombo->insertItem( i18n("Yearly") ); 660 mTypeCombo->insertItem( i18n("Yearly") );
662 661
663 topLayout->addWidget( mTypeCombo ); 662 topLayout->addWidget( mTypeCombo );
664 663
665 connect( mTypeCombo, SIGNAL( activated( int ) ), SLOT( emitChoice() ) ); 664 connect( mTypeCombo, SIGNAL( activated( int ) ), SLOT( emitChoice() ) );
666 } else { 665 } else {
667 mTypeCombo = 0; 666 mTypeCombo = 0;
668 667
669 QButtonGroup *ruleButtonGroup = new QButtonGroup( 1, Horizontal, this ); 668 QButtonGroup *ruleButtonGroup = new QButtonGroup( 1, Horizontal, this );
670 ruleButtonGroup->setFrameStyle( QFrame::NoFrame ); 669 ruleButtonGroup->setFrameStyle( QFrame::NoFrame );
671 topLayout->addWidget( ruleButtonGroup ); 670 topLayout->addWidget( ruleButtonGroup );
672 671
673 mDailyButton = new QRadioButton( i18n("Daily"), ruleButtonGroup ); 672 mDailyButton = new QRadioButton( i18n("Daily"), ruleButtonGroup );
674 mWeeklyButton = new QRadioButton( i18n("Weekly"), ruleButtonGroup ); 673 mWeeklyButton = new QRadioButton( i18n("Weekly"), ruleButtonGroup );
675 mMonthlyButton = new QRadioButton( i18n("Monthly"), ruleButtonGroup ); 674 mMonthlyButton = new QRadioButton( i18n("Monthly"), ruleButtonGroup );
676 mYearlyButton = new QRadioButton( i18n("Yearly"), ruleButtonGroup ); 675 mYearlyButton = new QRadioButton( i18n("Yearly"), ruleButtonGroup );
677 676
678 connect( mDailyButton, SIGNAL( toggled( bool ) ), 677 connect( mDailyButton, SIGNAL( toggled( bool ) ),
679 SLOT( emitChoice() ) ); 678 SLOT( emitChoice() ) );
680 connect( mWeeklyButton, SIGNAL( toggled( bool ) ), 679 connect( mWeeklyButton, SIGNAL( toggled( bool ) ),
681 SLOT( emitChoice() ) ); 680 SLOT( emitChoice() ) );
682 connect( mMonthlyButton, SIGNAL( toggled( bool ) ), 681 connect( mMonthlyButton, SIGNAL( toggled( bool ) ),
683 SLOT( emitChoice() ) ); 682 SLOT( emitChoice() ) );
684 connect( mYearlyButton, SIGNAL( toggled( bool ) ), 683 connect( mYearlyButton, SIGNAL( toggled( bool ) ),
685 SLOT( emitChoice() ) ); 684 SLOT( emitChoice() ) );
686 } 685 }
687} 686}
688 687
689int RecurrenceChooser::type() 688int RecurrenceChooser::type()
690{ 689{
691 if ( mTypeCombo ) { 690 if ( mTypeCombo ) {
692 return mTypeCombo->currentItem(); 691 return mTypeCombo->currentItem();
693 } else { 692 } else {
694 if ( mDailyButton->isChecked() ) return Daily; 693 if ( mDailyButton->isChecked() ) return Daily;
695 else if ( mWeeklyButton->isChecked() ) return Weekly; 694 else if ( mWeeklyButton->isChecked() ) return Weekly;
696 else if ( mMonthlyButton->isChecked() ) return Monthly; 695 else if ( mMonthlyButton->isChecked() ) return Monthly;
697 else return Yearly; 696 else return Yearly;
698 } 697 }
699} 698}
700 699
701void RecurrenceChooser::setType( int type ) 700void RecurrenceChooser::setType( int type )
702{ 701{
703 if ( mTypeCombo ) { 702 if ( mTypeCombo ) {
704 mTypeCombo->setCurrentItem( type ); 703 mTypeCombo->setCurrentItem( type );
705 } else { 704 } else {
706 switch ( type ) { 705 switch ( type ) {
707 case Daily: 706 case Daily:
708 mDailyButton->setChecked( true ); 707 mDailyButton->setChecked( true );
709 break; 708 break;
710 case Weekly: 709 case Weekly:
711 mWeeklyButton->setChecked( true ); 710 mWeeklyButton->setChecked( true );
712 break; 711 break;
713 case Monthly: 712 case Monthly:
714 mMonthlyButton->setChecked( true ); 713 mMonthlyButton->setChecked( true );
715 break; 714 break;
716 case Yearly: 715 case Yearly:
717 default: 716 default:
718 mYearlyButton->setChecked( true ); 717 mYearlyButton->setChecked( true );
719 break; 718 break;
720 } 719 }
721 } 720 }
722} 721}
723 722
724void RecurrenceChooser::emitChoice() 723void RecurrenceChooser::emitChoice()
725{ 724{
726 emit chosen ( type() ); 725 emit chosen ( type() );
727} 726}
728 727
729/////////////////////////////// Main Widget ///////////////////////////// 728/////////////////////////////// Main Widget /////////////////////////////
730 729
731KOEditorRecurrence::KOEditorRecurrence( QWidget* parent, const char *name ) : 730KOEditorRecurrence::KOEditorRecurrence( QWidget* parent, const char *name ) :
732 QWidget( parent, name ) 731 QWidget( parent, name )
733{ 732{
734 QGridLayout *topLayout = new QGridLayout( this, 2,2 ); 733 QGridLayout *topLayout = new QGridLayout( this, 2,2 );
735 topLayout->setSpacing( KDialog::spacingHint() ); 734 topLayout->setSpacing( KDialog::spacingHint() );
736 735
737 mEnabledCheck = new QCheckBox( i18n("Enable Recurrence"), this ); 736 mEnabledCheck = new QCheckBox( i18n("Enable Recurrence"), this );
738 connect( mEnabledCheck, SIGNAL( toggled( bool ) ), 737 connect( mEnabledCheck, SIGNAL( toggled( bool ) ),
739 SLOT( setEnabled( bool ) ) ); 738 SLOT( setEnabled( bool ) ) );
740 topLayout->addMultiCellWidget( mEnabledCheck, 0, 0, 0, 1 ); 739 topLayout->addMultiCellWidget( mEnabledCheck, 0, 0, 0, 1 );
741 740
742 741
743 mTimeGroupBox = new QGroupBox( 1, Horizontal, i18n("Appointment Time "), 742 mTimeGroupBox = new QGroupBox( 1, Horizontal, i18n("Appointment Time "),
744 this ); 743 this );
745 topLayout->addMultiCellWidget( mTimeGroupBox, 1, 1 , 0 , 1 ); 744 topLayout->addMultiCellWidget( mTimeGroupBox, 1, 1 , 0 , 1 );
746 745
747 if ( KOPrefs::instance()->mCompactDialogs ) { 746 if ( KOPrefs::instance()->mCompactDialogs ) {
748 mTimeGroupBox->hide(); 747 mTimeGroupBox->hide();
749 } 748 }
750 749
751// QFrame *timeFrame = new QFrame( mTimeGroupBox ); 750// QFrame *timeFrame = new QFrame( mTimeGroupBox );
752// QBoxLayout *layoutTimeFrame = new QHBoxLayout( timeFrame ); 751// QBoxLayout *layoutTimeFrame = new QHBoxLayout( timeFrame );
753// layoutTimeFrame->setSpacing( KDialog::spacingHint() ); 752// layoutTimeFrame->setSpacing( KDialog::spacingHint() );
754 753
755 mDateTimeLabel = new QLabel( mTimeGroupBox ); 754 mDateTimeLabel = new QLabel( mTimeGroupBox );
756// mDateTimeLabel = new QLabel( timeFrame ); 755// mDateTimeLabel = new QLabel( timeFrame );
757// layoutTimeFrame->addWidget( mDateTimeLabel ); 756// layoutTimeFrame->addWidget( mDateTimeLabel );
758 757
759 Qt::Orientation orientation; 758 Qt::Orientation orientation;
760 if ( KOPrefs::instance()->mCompactDialogs ) orientation = Horizontal; 759 if ( KOPrefs::instance()->mCompactDialogs ) orientation = Horizontal;
761 else orientation = Vertical; 760 else orientation = Vertical;
762 761
763 mRuleBox = new QGroupBox( 1, orientation, i18n("Recurrence Rule"), this ); 762 mRuleBox = new QGroupBox( 1, orientation, i18n("Recurrence Rule"), this );
764 if ( KOPrefs::instance()->mCompactDialogs ) { 763 if ( KOPrefs::instance()->mCompactDialogs ) {
765 topLayout->addMultiCellWidget( mRuleBox, 2, 2, 0, 1 ); 764 topLayout->addMultiCellWidget( mRuleBox, 2, 2, 0, 1 );
766 } else { 765 } else {
767 topLayout->addMultiCellWidget( mRuleBox, 2, 2, 0, 1 ); 766 topLayout->addMultiCellWidget( mRuleBox, 2, 2, 0, 1 );
768 } 767 }
769 768
770 mRecurrenceChooser = new RecurrenceChooser( mRuleBox ); 769 mRecurrenceChooser = new RecurrenceChooser( mRuleBox );
771 connect( mRecurrenceChooser, SIGNAL( chosen( int ) ), 770 connect( mRecurrenceChooser, SIGNAL( chosen( int ) ),
772 SLOT( showCurrentRule( int ) ) ); 771 SLOT( showCurrentRule( int ) ) );
773 772
774 if ( !KOPrefs::instance()->mCompactDialogs ) { 773 if ( !KOPrefs::instance()->mCompactDialogs ) {
775 QFrame *ruleSepFrame = new QFrame( mRuleBox ); 774 QFrame *ruleSepFrame = new QFrame( mRuleBox );
776 ruleSepFrame->setFrameStyle( QFrame::VLine | QFrame::Sunken ); 775 ruleSepFrame->setFrameStyle( QFrame::VLine | QFrame::Sunken );
777 } 776 }
778 777
779 mRuleStack = new QWidgetStack( mRuleBox ); 778 mRuleStack = new QWidgetStack( mRuleBox );
780 779
781 mDaily = new RecurDaily( mRuleStack ); 780 mDaily = new RecurDaily( mRuleStack );
782 mRuleStack->addWidget( mDaily, 0 ); 781 mRuleStack->addWidget( mDaily, 0 );
783 782
784 mWeekly = new RecurWeekly( mRuleStack ); 783 mWeekly = new RecurWeekly( mRuleStack );
785 mRuleStack->addWidget( mWeekly, 0 ); 784 mRuleStack->addWidget( mWeekly, 0 );
786 785
787 mMonthly = new RecurMonthly( mRuleStack ); 786 mMonthly = new RecurMonthly( mRuleStack );
788 mRuleStack->addWidget( mMonthly, 0 ); 787 mRuleStack->addWidget( mMonthly, 0 );
789 788
790 mYearly = new RecurYearly( mRuleStack ); 789 mYearly = new RecurYearly( mRuleStack );
791 mRuleStack->addWidget( mYearly, 0 ); 790 mRuleStack->addWidget( mYearly, 0 );
792 791
793 showCurrentRule( mRecurrenceChooser->type() ); 792 showCurrentRule( mRecurrenceChooser->type() );
794 793
795 if ( KOPrefs::instance()->mCompactDialogs ) { 794 if ( KOPrefs::instance()->mCompactDialogs ) {
796 mRecurrenceRangeWidget = 0; 795 mRecurrenceRangeWidget = 0;
797 mRecurrenceRangeDialog = new RecurrenceRangeDialog( this ); 796 mRecurrenceRangeDialog = new RecurrenceRangeDialog( this );
798 mRecurrenceRange = mRecurrenceRangeDialog; 797 mRecurrenceRange = mRecurrenceRangeDialog;
799 mRecurrenceRangeButton = new QPushButton( i18n("Recurrence Range..."), 798 mRecurrenceRangeButton = new QPushButton( i18n("Recurrence Range..."),
800 this ); 799 this );
801 800
802 connect( mRecurrenceRangeButton, SIGNAL( clicked() ), 801 connect( mRecurrenceRangeButton, SIGNAL( clicked() ),
803 SLOT( showRecurrenceRangeDialog() ) ); 802 SLOT( showRecurrenceRangeDialog() ) );
804 803
805 mExceptionsWidget = 0; 804 mExceptionsWidget = 0;
806 mExceptionsDialog = new ExceptionsDialog( this ); 805 mExceptionsDialog = new ExceptionsDialog( this );
807 mExceptions = mExceptionsDialog; 806 mExceptions = mExceptionsDialog;
808 mExceptionsButton = new QPushButton( i18n("Exceptions..."), this ); 807 mExceptionsButton = new QPushButton( i18n("Exceptions..."), this );
809 if ( QApplication::desktop()->width() < 320 ) { 808 if ( QApplication::desktop()->width() < 320 ) {
810 topLayout->addMultiCellWidget( mRecurrenceRangeButton, 3, 3, 0, 1 ); 809 topLayout->addMultiCellWidget( mRecurrenceRangeButton, 3, 3, 0, 1 );
811 topLayout->addMultiCellWidget( mExceptionsButton, 4, 4, 0, 1 ); 810 topLayout->addMultiCellWidget( mExceptionsButton, 4, 4, 0, 1 );
812 } else { 811 } else {
813 topLayout->addWidget( mRecurrenceRangeButton, 3, 0 ); 812 topLayout->addWidget( mRecurrenceRangeButton, 3, 0 );
814 topLayout->addWidget( mExceptionsButton, 3, 1 ); 813 topLayout->addWidget( mExceptionsButton, 3, 1 );
815 } 814 }
816 connect( mExceptionsButton, SIGNAL( clicked() ), 815 connect( mExceptionsButton, SIGNAL( clicked() ),
817 SLOT( showExceptionsDialog() ) ); 816 SLOT( showExceptionsDialog() ) );
818 817
819 } else { 818 } else {
820 mRecurrenceRangeWidget = new RecurrenceRangeWidget( this ); 819 mRecurrenceRangeWidget = new RecurrenceRangeWidget( this );
821 mRecurrenceRangeDialog = 0; 820 mRecurrenceRangeDialog = 0;
822 mRecurrenceRange = mRecurrenceRangeWidget; 821 mRecurrenceRange = mRecurrenceRangeWidget;
823 mRecurrenceRangeButton = 0; 822 mRecurrenceRangeButton = 0;
824 topLayout->addWidget( mRecurrenceRangeWidget, 3, 0 ); 823 topLayout->addWidget( mRecurrenceRangeWidget, 3, 0 );
825 824
826 mExceptionsWidget = new ExceptionsWidget( this ); 825 mExceptionsWidget = new ExceptionsWidget( this );
827 mExceptionsDialog = 0; 826 mExceptionsDialog = 0;
828 mExceptions = mExceptionsWidget; 827 mExceptions = mExceptionsWidget;
829 mExceptionsButton = 0; 828 mExceptionsButton = 0;
830 topLayout->addWidget( mExceptionsWidget, 3, 1 ); 829 topLayout->addWidget( mExceptionsWidget, 3, 1 );
831 } 830 }
832} 831}
833 832
834KOEditorRecurrence::~KOEditorRecurrence() 833KOEditorRecurrence::~KOEditorRecurrence()
835{ 834{
836} 835}
837 836
838void KOEditorRecurrence::setEnabled( bool enabled ) 837void KOEditorRecurrence::setEnabled( bool enabled )
839{ 838{
840// kdDebug() << "KOEditorRecurrence::setEnabled(): " << (enabled ? "on" : "off") << endl; 839// kdDebug() << "KOEditorRecurrence::setEnabled(): " << (enabled ? "on" : "off") << endl;
841 840
842 mTimeGroupBox->setEnabled( enabled ); 841 mTimeGroupBox->setEnabled( enabled );
843 if ( mRecurrenceRangeWidget ) mRecurrenceRangeWidget->setEnabled( enabled ); 842 if ( mRecurrenceRangeWidget ) mRecurrenceRangeWidget->setEnabled( enabled );
844 if ( mRecurrenceRangeButton ) mRecurrenceRangeButton->setEnabled( enabled ); 843 if ( mRecurrenceRangeButton ) mRecurrenceRangeButton->setEnabled( enabled );
845 if ( mExceptionsWidget ) mExceptionsWidget->setEnabled( enabled ); 844 if ( mExceptionsWidget ) mExceptionsWidget->setEnabled( enabled );
846 if ( mExceptionsButton ) mExceptionsButton->setEnabled( enabled ); 845 if ( mExceptionsButton ) mExceptionsButton->setEnabled( enabled );
846 mRuleBox->setEnabled( enabled );
847} 847}
848 848
849void KOEditorRecurrence::showCurrentRule( int current ) 849void KOEditorRecurrence::showCurrentRule( int current )
850{ 850{
851 switch ( current ) { 851 switch ( current ) {
852 case Daily: 852 case Daily:
853 mRuleStack->raiseWidget( mDaily ); 853 mRuleStack->raiseWidget( mDaily );
854 break; 854 break;
855 case Weekly: 855 case Weekly:
856 mRuleStack->raiseWidget( mWeekly ); 856 mRuleStack->raiseWidget( mWeekly );
857 break; 857 break;
858 case Monthly: 858 case Monthly:
859 mRuleStack->raiseWidget( mMonthly ); 859 mRuleStack->raiseWidget( mMonthly );
860 break; 860 break;
861 default: 861 default:
862 case Yearly: 862 case Yearly:
863 mRuleStack->raiseWidget( mYearly ); 863 mRuleStack->raiseWidget( mYearly );
864 break; 864 break;
865 } 865 }
866} 866}
867 867
868void KOEditorRecurrence::setDateTimes( QDateTime start, QDateTime end ) 868void KOEditorRecurrence::setDateTimes( QDateTime start, QDateTime end )
869{ 869{
870// kdDebug() << "KOEditorRecurrence::setDateTimes" << endl; 870// kdDebug() << "KOEditorRecurrence::setDateTimes" << endl;
871 871
872 mRecurrenceRange->setDateTimes( start, end ); 872 mRecurrenceRange->setDateTimes( start, end );
873 mExceptions->setDefaults( end ); 873 mExceptions->setDefaults( end );
874 874
875} 875}
876 876
877void KOEditorRecurrence::setDefaults( QDateTime from, QDateTime to, bool ) 877void KOEditorRecurrence::setDefaults( QDateTime from, QDateTime to, bool )
878{ 878{
879 879
880 // qDebug("KOEditorRecurrence::setDefaults %s %s ",from.toString().latin1(),to.toString().latin1() ); 880 // qDebug("KOEditorRecurrence::setDefaults %s %s ",from.toString().latin1(),to.toString().latin1() );
881 setDateTimes( from, to ); 881 setDateTimes( from, to );
882 882
883 bool enabled = false; 883 bool enabled = false;
884 mEnabledCheck->setChecked( enabled ); 884 mEnabledCheck->setChecked( enabled );
885 setEnabled( enabled ); 885 setEnabled( enabled );
886 886
887 mExceptions->setDefaults( to ); 887 mExceptions->setDefaults( to );
888 mRecurrenceRange->setDefaults( to ); 888 mRecurrenceRange->setDefaults( to );
889 889
890 mRecurrenceChooser->setType( RecurrenceChooser::Weekly ); 890 mRecurrenceChooser->setType( RecurrenceChooser::Weekly );
891 showCurrentRule( mRecurrenceChooser->type() ); 891 showCurrentRule( mRecurrenceChooser->type() );
892 892
893 mDaily->setFrequency( 1 ); 893 mDaily->setFrequency( 1 );
894 894
895 mWeekly->setFrequency( 1 ); 895 mWeekly->setFrequency( 1 );
896 QBitArray days( 7 ); 896 QBitArray days( 7 );
897 days.fill( 0 ); 897 days.fill( 0 );
898 days.setBit( from.date().dayOfWeek()- 1);
898 mWeekly->setDays( days ); 899 mWeekly->setDays( days );
899
900 mMonthly->setFrequency( 1 ); 900 mMonthly->setFrequency( 1 );
901 mMonthly->setByPos((from.date().day()/7), from.date().dayOfWeek()-1 );
901 mMonthly->setByDay( from.date().day()-1 ); 902 mMonthly->setByDay( from.date().day()-1 );
902
903 mYearly->setFrequency( 1 ); 903 mYearly->setFrequency( 1 );
904 mYearly->setByDay(); 904 mYearly->setByDay( from.date().dayOfYear() );
905 mYearly->setByMonth( from.date().month(), from.date().day() );
905} 906}
906 907
907void KOEditorRecurrence::readEvent(Event *event) 908void KOEditorRecurrence::readEvent(Event *event)
908{ 909{
910 setDefaults( event->dtStart(), event->dtEnd(), true );
909 QBitArray rDays( 7 ); 911 QBitArray rDays( 7 );
910 QPtrList<Recurrence::rMonthPos> rmp; 912 QPtrList<Recurrence::rMonthPos> rmp;
911 QPtrList<int> rmd; 913 QPtrList<int> rmd;
912 int day = 0; 914 int day = 0;
913 int count = 0; 915 int count = 0;
914 int month = 0; 916 int month = 0;
915 setDateTimes( event->dtStart(), event->dtEnd() ); 917 setDateTimes( event->dtStart(), event->dtEnd() );
916 918
917 Recurrence *r = event->recurrence(); 919 Recurrence *r = event->recurrence();
918 int f = r->frequency(); 920 int f = r->frequency();
919 921
920 int recurs = r->doesRecur(); 922 int recurs = r->doesRecur();
921 923
922 mEnabledCheck->setChecked( recurs ); 924 mEnabledCheck->setChecked( recurs );
923 setEnabled( recurs ); 925 setEnabled( recurs );
924 926
925 int recurrenceType = RecurrenceChooser::Weekly; 927 int recurrenceType = RecurrenceChooser::Weekly;
926 928
927 switch ( recurs ) { 929 switch ( recurs ) {
928 case Recurrence::rNone: 930 case Recurrence::rNone:
929 setDefaults( event->dtStart(), event->dtEnd(), true ); 931 setDefaults( event->dtStart(), event->dtEnd(), true );
930 break; 932 break;
931 case Recurrence::rDaily: 933 case Recurrence::rDaily:
932 recurrenceType = RecurrenceChooser::Daily; 934 recurrenceType = RecurrenceChooser::Daily;
933 mDaily->setFrequency( f ); 935 mDaily->setFrequency( f );
934 break; 936 break;
935 case Recurrence::rWeekly: 937 case Recurrence::rWeekly:
936 recurrenceType = RecurrenceChooser::Weekly; 938 recurrenceType = RecurrenceChooser::Weekly;
937 mWeekly->setFrequency( f ); 939 mWeekly->setFrequency( f );
938 mWeekly->setDays( r->days() ); 940 mWeekly->setDays( r->days() );
939 break; 941 break;
940 case Recurrence::rMonthlyPos: 942 case Recurrence::rMonthlyPos:
941 // we only handle one possibility in the list right now, 943 // we only handle one possibility in the list right now,
942 // so I have hardcoded calls with first(). If we make the GUI 944 // so I have hardcoded calls with first(). If we make the GUI
943 // more extended, this can be changed. 945 // more extended, this can be changed.
944 recurrenceType = RecurrenceChooser::Monthly; 946 recurrenceType = RecurrenceChooser::Monthly;
945 947
946 rmp = r->monthPositions(); 948 rmp = r->monthPositions();
947 if ( rmp.first()->negative ) 949 if ( rmp.first()->negative )
948 count = 5 - rmp.first()->rPos - 1; 950 count = 5 - rmp.first()->rPos - 1;
949 else 951 else
950 count = rmp.first()->rPos - 1; 952 count = rmp.first()->rPos - 1;
951 day = 0; 953 day = 0;
952 while ( !rmp.first()->rDays.testBit( day ) ) ++day; 954 while ( !rmp.first()->rDays.testBit( day ) ) ++day;
953 mMonthly->setByPos( count, day ); 955 mMonthly->setByPos( count, day );
954 956
955 mMonthly->setFrequency( f ); 957 mMonthly->setFrequency( f );
956 958
957 break; 959 break;
958 case Recurrence::rMonthlyDay: 960 case Recurrence::rMonthlyDay:
959 recurrenceType = RecurrenceChooser::Monthly; 961 recurrenceType = RecurrenceChooser::Monthly;
960 962
961 rmd = r->monthDays(); 963 rmd = r->monthDays();
962 day = *rmd.first() - 1; 964 day = *rmd.first() - 1;
963 mMonthly->setByDay( day ); 965 mMonthly->setByDay( day );
964 966
965 mMonthly->setFrequency( f ); 967 mMonthly->setFrequency( f );
966 968
967 break; 969 break;
968 case Recurrence::rYearlyMonth: 970 case Recurrence::rYearlyMonth:
969 case Recurrence::rYearlyDay: 971 {
970 recurrenceType = RecurrenceChooser::Yearly; 972 recurrenceType = RecurrenceChooser::Yearly;
971 973 qDebug("Recurrence::rYearlyMonth: ");
972 rmd = r->yearNums(); 974 day = event->dtStart().date().day();
973 month = *rmd.first(); 975 rmd = r->yearNums();
974 if ( month == event->dtStart().date().month() ) { 976 if ( rmd.count() > 0 )
975 mYearly->setByDay(); 977 month = *rmd.first();
976 } else { 978 else
977 mYearly->setByMonth( month ); 979 month = event->dtStart().date().month() ;
978 } 980 mYearly->setByMonth( month, day );
981#if 0
982 qDebug("2day = %d ",day );
983 QPtrList<Recurrence::rMonthPos> monthlist = r->yearMonthPositions();
984 int month;
985 if ( !monthlist.isEmpty() ) {
986 month = monthlist.first()->rPos ;
987 } else {
988 month = event->dtStart().date().month() ;
989 }
990 mYearly->setByMonth( day, month );
991#endif
992 mYearly->setFrequency( f );
993 }
979 994
980 mYearly->setFrequency( f );
981 break; 995 break;
996 case Recurrence::rYearlyDay:
997 qDebug("Recurrence::rYearlyDay: ");
998 recurrenceType = RecurrenceChooser::Yearly;
999 mYearly->setByDay( event->dtStart().date().dayOfYear() );
1000 mYearly->setFrequency( f );
1001 break;
982 default: 1002 default:
983 setDefaults( event->dtStart(), event->dtEnd(), true ); 1003 setDefaults( event->dtStart(), event->dtEnd(), true );
984 break; 1004 break;
985 } 1005 }
986 1006
987 mRecurrenceChooser->setType( recurrenceType ); 1007 mRecurrenceChooser->setType( recurrenceType );
988 showCurrentRule( recurrenceType ); 1008 showCurrentRule( recurrenceType );
989 1009
990 mRecurrenceRange->setDateTimes( event->dtStart() ); 1010 mRecurrenceRange->setDateTimes( event->dtStart() );
991 1011
992 if ( r->doesRecur() ) { 1012 if ( r->doesRecur() ) {
993 mRecurrenceRange->setDuration( r->duration() ); 1013 mRecurrenceRange->setDuration( r->duration() );
994 if ( r->duration() == 0 ) 1014 if ( r->duration() == 0 )
995 { 1015 {
996 if ( r->endDate() < event->dtStart().date() ) 1016 if ( r->endDate() < event->dtStart().date() )
997 mRecurrenceRange->setEndDate( event->dtStart().date() ); 1017 mRecurrenceRange->setEndDate( event->dtStart().date() );
998 else 1018 else
999 mRecurrenceRange->setEndDate( r->endDate() ); 1019 mRecurrenceRange->setEndDate( r->endDate() );
1000 } else 1020 } else
1001 mRecurrenceRange->setEndDate( event->dtStart().date() ); 1021 mRecurrenceRange->setEndDate( event->dtStart().date() );
1002 } 1022 }
1003 1023
1004 mExceptions->setDates( event->exDates() ); 1024 mExceptions->setDates( event->exDates() );
1005} 1025}
1006 1026
1007void KOEditorRecurrence::writeEvent( Event *event ) 1027void KOEditorRecurrence::writeEvent( Event *event )
1008{ 1028{
1009 Recurrence *r = event->recurrence(); 1029 Recurrence *r = event->recurrence();
1010 1030
1011 // clear out any old settings; 1031 // clear out any old settings;
1012 r->unsetRecurs(); 1032 r->unsetRecurs();
1013 1033
1014 if ( mEnabledCheck->isChecked() ) { 1034 if ( mEnabledCheck->isChecked() ) {
1015 int duration = mRecurrenceRange->duration(); 1035 int duration = mRecurrenceRange->duration();
1016 QDate endDate; 1036 QDate endDate;
1017 if ( duration == 0 ) endDate = mRecurrenceRange->endDate(); 1037 if ( duration == 0 ) endDate = mRecurrenceRange->endDate();
1018 1038
1019 int recurrenceType = mRecurrenceChooser->type(); 1039 int recurrenceType = mRecurrenceChooser->type();
1020 1040
1021 if ( recurrenceType == RecurrenceChooser::Daily ) { 1041 if ( recurrenceType == RecurrenceChooser::Daily ) {
1022 int freq = mDaily->frequency(); 1042 int freq = mDaily->frequency();
1023 if ( duration != 0 ) r->setDaily( freq, duration ); 1043 if ( duration != 0 ) r->setDaily( freq, duration );
1024 else r->setDaily( freq, endDate ); 1044 else r->setDaily( freq, endDate );
1025 } else if ( recurrenceType == RecurrenceChooser::Weekly ) { 1045 } else if ( recurrenceType == RecurrenceChooser::Weekly ) {
1026 int freq = mWeekly->frequency(); 1046 int freq = mWeekly->frequency();
1027 QBitArray days = mWeekly->days(); 1047 QBitArray days = mWeekly->days();
1028 int j; 1048 int j;
1029 bool found = false; 1049 bool found = false;
1030 for (j = 0; j < 7 ; ++j ) { 1050 for (j = 0; j < 7 ; ++j ) {
1031 found |=days.at(j); 1051 found |=days.at(j);
1032 } 1052 }
1033 if ( !found ) { 1053 if ( !found ) {
1034 days.setBit( event->dtStart().date().dayOfWeek()-1); 1054 days.setBit( event->dtStart().date().dayOfWeek()-1);
1035 qDebug("bit set %d "); 1055 qDebug("bit set %d ");
1036 } 1056 }
1037 if ( duration != 0 ) r->setWeekly( freq, days, duration ); 1057 if ( duration != 0 ) r->setWeekly( freq, days, duration );
1038 else r->setWeekly( freq, days, endDate ); 1058 else r->setWeekly( freq, days, endDate );
1039 } else if ( recurrenceType == RecurrenceChooser::Monthly ) { 1059 } else if ( recurrenceType == RecurrenceChooser::Monthly ) {
1040 int freq = mMonthly->frequency(); 1060 int freq = mMonthly->frequency();
1041 if ( mMonthly->byPos() ) { 1061 if ( mMonthly->byPos() ) {
1042 int pos = mMonthly->count(); 1062 int pos = mMonthly->count();
1043 1063
1044 QBitArray days( 7 ); 1064 QBitArray days( 7 );
1045 days.fill( false ); 1065 days.fill( false );
1046 1066
1047 days.setBit( mMonthly->weekday() ); 1067 days.setBit( mMonthly->weekday() );
1048 if ( duration != 0 ) 1068 if ( duration != 0 )
1049 r->setMonthly( Recurrence::rMonthlyPos, freq, duration ); 1069 r->setMonthly( Recurrence::rMonthlyPos, freq, duration );
1050 else 1070 else
1051 r->setMonthly( Recurrence::rMonthlyPos, freq, endDate ); 1071 r->setMonthly( Recurrence::rMonthlyPos, freq, endDate );
1052 r->addMonthlyPos( pos, days ); 1072 r->addMonthlyPos( pos, days );
1053 } else { 1073 } else {
1054 // it's by day 1074 // it's by day
1055 int day = mMonthly->day(); 1075 int day = mMonthly->day();
1056 1076
1057 if ( duration != 0 ) { 1077 if ( duration != 0 ) {
1058 r->setMonthly( Recurrence::rMonthlyDay, freq, duration ); 1078 r->setMonthly( Recurrence::rMonthlyDay, freq, duration );
1059 } else { 1079 } else {
1060 r->setMonthly( Recurrence::rMonthlyDay, freq, endDate ); 1080 r->setMonthly( Recurrence::rMonthlyDay, freq, endDate );
1061 } 1081 }
1062 r->addMonthlyDay( day ); 1082 r->addMonthlyDay( day );
1063 } 1083 }
1064 } else if ( recurrenceType == RecurrenceChooser::Yearly ) { 1084 } else if ( recurrenceType == RecurrenceChooser::Yearly ) {
1085 qDebug("RecurrenceChooser::Yearly ");
1065 int freq = mYearly->frequency(); 1086 int freq = mYearly->frequency();
1066 1087 if ( mYearly->byDay() ) {
1067 int month; 1088 if ( duration != 0 ) {
1068 if ( mYearly->byMonth() ) { 1089 r->setYearly( Recurrence::rYearlyDay, freq, duration );
1069 month = mYearly->month(); 1090 } else {
1070 } else { 1091 r->setYearly( Recurrence::rYearlyDay, freq, endDate );
1071 month = event->dtStart().date().month(); 1092 }
1072 } 1093 r->addYearlyNum( event->dtStart().date().dayOfYear() );
1073 if ( duration != 0 ) {
1074 r->setYearly( Recurrence::rYearlyMonth, freq, duration );
1075 } else { 1094 } else {
1076 r->setYearly( Recurrence::rYearlyMonth, freq, endDate ); 1095 if ( duration != 0 ) {
1096 r->setYearly( Recurrence::rYearlyMonth, freq, duration );
1097 } else {
1098 r->setYearly( Recurrence::rYearlyMonth, freq, endDate );
1099 }
1100 r->addYearlyNum( mYearly->month() );
1077 } 1101 }
1078 1102
1079 r->addYearlyNum( month );
1080 } 1103 }
1081 1104
1082 event->setExDates( mExceptions->dates() ); 1105 event->setExDates( mExceptions->dates() );
1083 } 1106 }
1084} 1107}
1085 1108
1086void KOEditorRecurrence::setDateTimeStr( const QString &str ) 1109void KOEditorRecurrence::setDateTimeStr( const QString &str )
1087{ 1110{
1088 mDateTimeLabel->setText( str ); 1111 mDateTimeLabel->setText( str );
1089} 1112}
1090 1113
1091bool KOEditorRecurrence::validateInput() 1114bool KOEditorRecurrence::validateInput()
1092{ 1115{
1093 // Check input here 1116 // Check input here
1094 1117
1095 return true; 1118 return true;
1096} 1119}
1097 1120
1098void KOEditorRecurrence::showExceptionsDialog() 1121void KOEditorRecurrence::showExceptionsDialog()
1099{ 1122{
1100 DateList dates = mExceptions->dates(); 1123 DateList dates = mExceptions->dates();
1101 int result = mExceptionsDialog->exec(); 1124 int result = mExceptionsDialog->exec();
1102 if ( result == QDialog::Rejected ) mExceptions->setDates( dates ); 1125 if ( result == QDialog::Rejected ) mExceptions->setDates( dates );
1103} 1126}
1104 1127
1105void KOEditorRecurrence::showRecurrenceRangeDialog() 1128void KOEditorRecurrence::showRecurrenceRangeDialog()
1106{ 1129{
1107 int duration = mRecurrenceRange->duration(); 1130 int duration = mRecurrenceRange->duration();
1108 QDate endDate = mRecurrenceRange->endDate(); 1131 QDate endDate = mRecurrenceRange->endDate();
1109 1132
1110 int result = mRecurrenceRangeDialog->exec(); 1133 int result = mRecurrenceRangeDialog->exec();
1111 if ( result == QDialog::Rejected ) { 1134 if ( result == QDialog::Rejected ) {
1112 mRecurrenceRange->setDuration( duration ); 1135 mRecurrenceRange->setDuration( duration );
1113 mRecurrenceRange->setEndDate( endDate ); 1136 mRecurrenceRange->setEndDate( endDate );
1114 } 1137 }
1115 1138
1116} 1139}
diff --git a/korganizer/koeditorrecurrence.h b/korganizer/koeditorrecurrence.h
index 4f0f0b2..2b59085 100644
--- a/korganizer/koeditorrecurrence.h
+++ b/korganizer/koeditorrecurrence.h
@@ -1,321 +1,324 @@
1/* 1/*
2 This file is part of KOrganizer. 2 This file is part of KOrganizer.
3 Copyright (c) 2000-2003 Cornelius Schumacher <schumacher@kde.org> 3 Copyright (c) 2000-2003 Cornelius Schumacher <schumacher@kde.org>
4 4
5 This program is free software; you can redistribute it and/or modify 5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by 6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or 7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version. 8 (at your option) any later version.
9 9
10 This program is distributed in the hope that it will be useful, 10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details. 13 GNU General Public License for more details.
14 14
15 You should have received a copy of the GNU General Public License 15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software 16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 18
19 As a special exception, permission is given to link this program 19 As a special exception, permission is given to link this program
20 with any edition of Qt, and distribute the resulting executable, 20 with any edition of Qt, and distribute the resulting executable,
21 without including the source code for Qt in the source distribution. 21 without including the source code for Qt in the source distribution.
22*/ 22*/
23#ifndef _KOEDITORRECURRENCE_H 23#ifndef _KOEDITORRECURRENCE_H
24#define _KOEDITORRECURRENCE_H 24#define _KOEDITORRECURRENCE_H
25 25
26#include <qframe.h> 26#include <qframe.h>
27#include <qlabel.h> 27#include <qlabel.h>
28#include <qcheckbox.h> 28#include <qcheckbox.h>
29#include <qpushbutton.h> 29#include <qpushbutton.h>
30#include <qgroupbox.h> 30#include <qgroupbox.h>
31#include <qlineedit.h> 31#include <qlineedit.h>
32#include <qcombobox.h> 32#include <qcombobox.h>
33#include <qmultilineedit.h> 33#include <qmultilineedit.h>
34#include <qlistview.h> 34#include <qlistview.h>
35#include <qradiobutton.h> 35#include <qradiobutton.h>
36 36
37#include <kdialogbase.h> 37#include <kdialogbase.h>
38 38
39#include <libkcal/event.h> 39#include <libkcal/event.h>
40 40
41#include "ktimeedit.h" 41#include "ktimeedit.h"
42 42
43class QWidgetStack; 43class QWidgetStack;
44class QSpinBox; 44class QSpinBox;
45 45
46class KDateEdit; 46class KDateEdit;
47 47
48using namespace KCal; 48using namespace KCal;
49 49
50class RecurBase : public QWidget 50class RecurBase : public QWidget
51{ 51{
52 public: 52 public:
53 RecurBase( QWidget *parent = 0, const char *name = 0 ); 53 RecurBase( QWidget *parent = 0, const char *name = 0 );
54 54
55 void setFrequency( int ); 55 void setFrequency( int );
56 int frequency(); 56 int frequency();
57 57
58 QWidget *frequencyEdit(); 58 QWidget *frequencyEdit();
59 59
60 private: 60 private:
61 QSpinBox *mFrequencyEdit; 61 QSpinBox *mFrequencyEdit;
62}; 62};
63 63
64class RecurDaily : public RecurBase 64class RecurDaily : public RecurBase
65{ 65{
66 public: 66 public:
67 RecurDaily( QWidget *parent = 0, const char *name = 0 ); 67 RecurDaily( QWidget *parent = 0, const char *name = 0 );
68}; 68};
69 69
70class RecurWeekly : public RecurBase 70class RecurWeekly : public RecurBase
71{ 71{
72 public: 72 public:
73 RecurWeekly( QWidget *parent = 0, const char *name = 0 ); 73 RecurWeekly( QWidget *parent = 0, const char *name = 0 );
74 74
75 void setDays( const QBitArray & ); 75 void setDays( const QBitArray & );
76 QBitArray days(); 76 QBitArray days();
77 77
78 private: 78 private:
79 QCheckBox *mDayBoxes[7]; 79 QCheckBox *mDayBoxes[7];
80}; 80};
81 81
82class RecurMonthly : public RecurBase 82class RecurMonthly : public RecurBase
83{ 83{
84 public: 84 public:
85 RecurMonthly( QWidget *parent = 0, const char *name = 0 ); 85 RecurMonthly( QWidget *parent = 0, const char *name = 0 );
86 86
87 void setByDay( int day ); 87 void setByDay( int day );
88 void setByPos( int count, int weekday ); 88 void setByPos( int count, int weekday );
89 89
90 bool byDay(); 90 bool byDay();
91 bool byPos(); 91 bool byPos();
92 92
93 int day(); 93 int day();
94 94
95 int count(); 95 int count();
96 int weekday(); 96 int weekday();
97 97
98 private: 98 private:
99 QRadioButton *mByDayRadio; 99 QRadioButton *mByDayRadio;
100 QComboBox *mByDayCombo; 100 QComboBox *mByDayCombo;
101 101
102 QRadioButton *mByPosRadio; 102 QRadioButton *mByPosRadio;
103 QComboBox *mByPosCountCombo; 103 QComboBox *mByPosCountCombo;
104 QComboBox *mByPosWeekdayCombo; 104 QComboBox *mByPosWeekdayCombo;
105}; 105};
106 106
107class RecurYearly : public RecurBase 107class RecurYearly : public RecurBase
108{ 108{
109 public: 109 public:
110 RecurYearly( QWidget *parent = 0, const char *name = 0 ); 110 RecurYearly( QWidget *parent = 0, const char *name = 0 );
111 111
112 void setByDay(); 112 void setByDay( int doy );
113 void setByMonth( int month ); 113 void setByMonth( int month, int day );
114 114
115 bool byMonth(); 115 bool byMonth();
116 bool byDay(); 116 bool byDay();
117 117
118 int month(); 118 int month();
119 int day();
119 120
120 private: 121 private:
122 int mDay;
121 QRadioButton *mByMonthRadio; 123 QRadioButton *mByMonthRadio;
122 QComboBox *mByMonthCombo; 124 QComboBox *mByMonthCombo;
123 125 QLabel* mByDayLabel;
126 QLabel* mDayOfLabel;
124 QRadioButton *mByDayRadio; 127 QRadioButton *mByDayRadio;
125}; 128};
126 129
127class RecurrenceChooser : public QWidget 130class RecurrenceChooser : public QWidget
128{ 131{
129 Q_OBJECT 132 Q_OBJECT
130 public: 133 public:
131 RecurrenceChooser( QWidget *parent = 0, const char *name = 0 ); 134 RecurrenceChooser( QWidget *parent = 0, const char *name = 0 );
132 135
133 enum { Daily, Weekly, Monthly, Yearly }; 136 enum { Daily, Weekly, Monthly, Yearly };
134 137
135 void setType( int ); 138 void setType( int );
136 int type(); 139 int type();
137 140
138 signals: 141 signals:
139 void chosen( int ); 142 void chosen( int );
140 143
141 protected slots: 144 protected slots:
142 void emitChoice(); 145 void emitChoice();
143 146
144 private: 147 private:
145 QComboBox *mTypeCombo; 148 QComboBox *mTypeCombo;
146 149
147 QRadioButton *mDailyButton; 150 QRadioButton *mDailyButton;
148 QRadioButton *mWeeklyButton; 151 QRadioButton *mWeeklyButton;
149 QRadioButton *mMonthlyButton; 152 QRadioButton *mMonthlyButton;
150 QRadioButton *mYearlyButton; 153 QRadioButton *mYearlyButton;
151}; 154};
152 155
153class ExceptionsBase 156class ExceptionsBase
154{ 157{
155 public: 158 public:
156 virtual void setDefaults( const QDateTime &from ) = 0; 159 virtual void setDefaults( const QDateTime &from ) = 0;
157 virtual void setDates( const DateList & ) = 0; 160 virtual void setDates( const DateList & ) = 0;
158 virtual DateList dates() = 0; 161 virtual DateList dates() = 0;
159}; 162};
160 163
161class ExceptionsWidget : public QWidget, public ExceptionsBase 164class ExceptionsWidget : public QWidget, public ExceptionsBase
162{ 165{
163 Q_OBJECT 166 Q_OBJECT
164 public: 167 public:
165 ExceptionsWidget( QWidget *parent = 0, const char *name = 0 ); 168 ExceptionsWidget( QWidget *parent = 0, const char *name = 0 );
166 169
167 void setDefaults( const QDateTime &from ); 170 void setDefaults( const QDateTime &from );
168 171
169 void setDates( const DateList & ); 172 void setDates( const DateList & );
170 DateList dates(); 173 DateList dates();
171 174
172 protected slots: 175 protected slots:
173 void addException(); 176 void addException();
174 void changeException(); 177 void changeException();
175 void deleteException(); 178 void deleteException();
176 179
177 private: 180 private:
178 KDateEdit *mExceptionDateEdit; 181 KDateEdit *mExceptionDateEdit;
179 QListBox *mExceptionList; 182 QListBox *mExceptionList;
180 DateList mExceptionDates; 183 DateList mExceptionDates;
181}; 184};
182 185
183class ExceptionsDialog : public KDialogBase, public ExceptionsBase 186class ExceptionsDialog : public KDialogBase, public ExceptionsBase
184{ 187{
185 public: 188 public:
186 ExceptionsDialog( QWidget *parent, const char *name = 0 ); 189 ExceptionsDialog( QWidget *parent, const char *name = 0 );
187 190
188 void setDefaults( const QDateTime &from ); 191 void setDefaults( const QDateTime &from );
189 192
190 void setDates( const DateList & ); 193 void setDates( const DateList & );
191 DateList dates(); 194 DateList dates();
192 195
193 private: 196 private:
194 ExceptionsWidget *mExceptions; 197 ExceptionsWidget *mExceptions;
195}; 198};
196 199
197class RecurrenceRangeBase 200class RecurrenceRangeBase
198{ 201{
199 public: 202 public:
200 virtual void setDefaults( const QDateTime &from ) = 0; 203 virtual void setDefaults( const QDateTime &from ) = 0;
201 204
202 virtual void setDuration( int ) = 0; 205 virtual void setDuration( int ) = 0;
203 virtual int duration() = 0; 206 virtual int duration() = 0;
204 207
205 virtual void setEndDate( const QDate & ) = 0; 208 virtual void setEndDate( const QDate & ) = 0;
206 virtual QDate endDate() = 0; 209 virtual QDate endDate() = 0;
207 210
208 virtual void setDateTimes( const QDateTime &start, 211 virtual void setDateTimes( const QDateTime &start,
209 const QDateTime &end = QDateTime() ) = 0; 212 const QDateTime &end = QDateTime() ) = 0;
210}; 213};
211 214
212class RecurrenceRangeWidget : public QWidget, public RecurrenceRangeBase 215class RecurrenceRangeWidget : public QWidget, public RecurrenceRangeBase
213{ 216{
214 Q_OBJECT 217 Q_OBJECT
215 public: 218 public:
216 RecurrenceRangeWidget( QWidget *parent = 0, const char *name = 0 ); 219 RecurrenceRangeWidget( QWidget *parent = 0, const char *name = 0 );
217 220
218 void setDefaults( const QDateTime &from ); 221 void setDefaults( const QDateTime &from );
219 222
220 void setDuration( int ); 223 void setDuration( int );
221 int duration(); 224 int duration();
222 225
223 void setEndDate( const QDate & ); 226 void setEndDate( const QDate & );
224 QDate endDate(); 227 QDate endDate();
225 228
226 void setDateTimes( const QDateTime &start, 229 void setDateTimes( const QDateTime &start,
227 const QDateTime &end = QDateTime() ); 230 const QDateTime &end = QDateTime() );
228 231
229 protected slots: 232 protected slots:
230 void showCurrentRange(); 233 void showCurrentRange();
231 234
232 private: 235 private:
233 QGroupBox *mRangeGroupBox; 236 QGroupBox *mRangeGroupBox;
234 QLabel *mStartDateLabel; 237 QLabel *mStartDateLabel;
235 QRadioButton *mNoEndDateButton; 238 QRadioButton *mNoEndDateButton;
236 QRadioButton *mEndDurationButton; 239 QRadioButton *mEndDurationButton;
237 QSpinBox *mEndDurationEdit; 240 QSpinBox *mEndDurationEdit;
238 QRadioButton *mEndDateButton; 241 QRadioButton *mEndDateButton;
239 KDateEdit *mEndDateEdit; 242 KDateEdit *mEndDateEdit;
240}; 243};
241 244
242class RecurrenceRangeDialog : public KDialogBase, public RecurrenceRangeBase 245class RecurrenceRangeDialog : public KDialogBase, public RecurrenceRangeBase
243{ 246{
244 public: 247 public:
245 RecurrenceRangeDialog( QWidget *parent = 0, const char *name = 0 ); 248 RecurrenceRangeDialog( QWidget *parent = 0, const char *name = 0 );
246 249
247 void setDefaults( const QDateTime &from ); 250 void setDefaults( const QDateTime &from );
248 251
249 void setDuration( int ); 252 void setDuration( int );
250 int duration(); 253 int duration();
251 254
252 void setEndDate( const QDate & ); 255 void setEndDate( const QDate & );
253 QDate endDate(); 256 QDate endDate();
254 257
255 void setDateTimes( const QDateTime &start, 258 void setDateTimes( const QDateTime &start,
256 const QDateTime &end = QDateTime() ); 259 const QDateTime &end = QDateTime() );
257 260
258 private: 261 private:
259 RecurrenceRangeWidget *mRecurrenceRangeWidget; 262 RecurrenceRangeWidget *mRecurrenceRangeWidget;
260}; 263};
261 264
262class KOEditorRecurrence : public QWidget 265class KOEditorRecurrence : public QWidget
263{ 266{
264 Q_OBJECT 267 Q_OBJECT
265 public: 268 public:
266 KOEditorRecurrence ( QWidget *parent = 0, const char *name = 0 ); 269 KOEditorRecurrence ( QWidget *parent = 0, const char *name = 0 );
267 virtual ~KOEditorRecurrence(); 270 virtual ~KOEditorRecurrence();
268 271
269 enum { Daily, Weekly, Monthly, Yearly }; 272 enum { Daily, Weekly, Monthly, Yearly };
270 273
271 /** Set widgets to default values */ 274 /** Set widgets to default values */
272 void setDefaults( QDateTime from, QDateTime to, bool allday ); 275 void setDefaults( QDateTime from, QDateTime to, bool allday );
273 /** Read event object and setup widgets accordingly */ 276 /** Read event object and setup widgets accordingly */
274 void readEvent( Event * ); 277 void readEvent( Event * );
275 /** Write event settings to event object */ 278 /** Write event settings to event object */
276 void writeEvent( Event * ); 279 void writeEvent( Event * );
277 280
278 /** Check if the input is valid. */ 281 /** Check if the input is valid. */
279 bool validateInput(); 282 bool validateInput();
280 283
281 public slots: 284 public slots:
282 void setEnabled( bool ); 285 void setEnabled( bool );
283 void setDateTimes( QDateTime start, QDateTime end ); 286 void setDateTimes( QDateTime start, QDateTime end );
284 void setDateTimeStr( const QString & ); 287 void setDateTimeStr( const QString & );
285 288
286 signals: 289 signals:
287 void dateTimesChanged( QDateTime start, QDateTime end ); 290 void dateTimesChanged( QDateTime start, QDateTime end );
288 291
289 protected slots: 292 protected slots:
290 void showCurrentRule( int ); 293 void showCurrentRule( int );
291 void showExceptionsDialog(); 294 void showExceptionsDialog();
292 void showRecurrenceRangeDialog(); 295 void showRecurrenceRangeDialog();
293 296
294 private: 297 private:
295 QCheckBox *mEnabledCheck; 298 QCheckBox *mEnabledCheck;
296 299
297 QGroupBox *mTimeGroupBox; 300 QGroupBox *mTimeGroupBox;
298 QLabel *mDateTimeLabel; 301 QLabel *mDateTimeLabel;
299 302
300 QGroupBox *mRuleBox; 303 QGroupBox *mRuleBox;
301 QWidgetStack *mRuleStack; 304 QWidgetStack *mRuleStack;
302 RecurrenceChooser *mRecurrenceChooser; 305 RecurrenceChooser *mRecurrenceChooser;
303 306
304 RecurDaily *mDaily; 307 RecurDaily *mDaily;
305 RecurWeekly *mWeekly; 308 RecurWeekly *mWeekly;
306 RecurMonthly *mMonthly; 309 RecurMonthly *mMonthly;
307 RecurYearly *mYearly; 310 RecurYearly *mYearly;
308 311
309 RecurrenceRangeBase *mRecurrenceRange; 312 RecurrenceRangeBase *mRecurrenceRange;
310 RecurrenceRangeWidget *mRecurrenceRangeWidget; 313 RecurrenceRangeWidget *mRecurrenceRangeWidget;
311 RecurrenceRangeDialog *mRecurrenceRangeDialog; 314 RecurrenceRangeDialog *mRecurrenceRangeDialog;
312 QPushButton *mRecurrenceRangeButton; 315 QPushButton *mRecurrenceRangeButton;
313 316
314 ExceptionsBase *mExceptions; 317 ExceptionsBase *mExceptions;
315 ExceptionsDialog *mExceptionsDialog; 318 ExceptionsDialog *mExceptionsDialog;
316 ExceptionsWidget *mExceptionsWidget; 319 ExceptionsWidget *mExceptionsWidget;
317 QPushButton *mExceptionsButton; 320 QPushButton *mExceptionsButton;
318 321
319}; 322};
320 323
321#endif 324#endif
diff --git a/libkcal/icalformatimpl.cpp b/libkcal/icalformatimpl.cpp
index 32a1337..964ffe3 100644
--- a/libkcal/icalformatimpl.cpp
+++ b/libkcal/icalformatimpl.cpp
@@ -1,2170 +1,2174 @@
1/* 1/*
2 This file is part of libkcal. 2 This file is part of libkcal.
3 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> 3 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
4 4
5 This library is free software; you can redistribute it and/or 5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public 6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either 7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version. 8 version 2 of the License, or (at your option) any later version.
9 9
10 This library is distributed in the hope that it will be useful, 10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details. 13 Library General Public License for more details.
14 14
15 You should have received a copy of the GNU Library General Public License 15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to 16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. 18 Boston, MA 02111-1307, USA.
19*/ 19*/
20 20
21#include <qdatetime.h> 21#include <qdatetime.h>
22#include <qstring.h> 22#include <qstring.h>
23#include <qptrlist.h> 23#include <qptrlist.h>
24#include <qfile.h> 24#include <qfile.h>
25 25
26#include <kdebug.h> 26#include <kdebug.h>
27#include <klocale.h> 27#include <klocale.h>
28#include <kglobal.h> 28#include <kglobal.h>
29 29
30extern "C" { 30extern "C" {
31 #include <ical.h> 31 #include <ical.h>
32 #include <icalss.h> 32 #include <icalss.h>
33 #include <icalparser.h> 33 #include <icalparser.h>
34 #include <icalrestriction.h> 34 #include <icalrestriction.h>
35} 35}
36 36
37#include "calendar.h" 37#include "calendar.h"
38#include "journal.h" 38#include "journal.h"
39#include "icalformat.h" 39#include "icalformat.h"
40#include "icalformatimpl.h" 40#include "icalformatimpl.h"
41#include "compat.h" 41#include "compat.h"
42 42
43#define _ICAL_VERSION "2.0" 43#define _ICAL_VERSION "2.0"
44 44
45using namespace KCal; 45using namespace KCal;
46 46
47const int gSecondsPerMinute = 60; 47const int gSecondsPerMinute = 60;
48const int gSecondsPerHour = gSecondsPerMinute * 60; 48const int gSecondsPerHour = gSecondsPerMinute * 60;
49const int gSecondsPerDay = gSecondsPerHour * 24; 49const int gSecondsPerDay = gSecondsPerHour * 24;
50const int gSecondsPerWeek = gSecondsPerDay * 7; 50const int gSecondsPerWeek = gSecondsPerDay * 7;
51 51
52ICalFormatImpl::ICalFormatImpl( ICalFormat *parent ) : 52ICalFormatImpl::ICalFormatImpl( ICalFormat *parent ) :
53 mParent( parent ), mCalendarVersion( 0 ) 53 mParent( parent ), mCalendarVersion( 0 )
54{ 54{
55 mCompat = new Compat; 55 mCompat = new Compat;
56} 56}
57 57
58ICalFormatImpl::~ICalFormatImpl() 58ICalFormatImpl::~ICalFormatImpl()
59{ 59{
60 delete mCompat; 60 delete mCompat;
61} 61}
62 62
63class ToStringVisitor : public Incidence::Visitor 63class ToStringVisitor : public Incidence::Visitor
64{ 64{
65 public: 65 public:
66 ToStringVisitor( ICalFormatImpl *impl ) : mImpl( impl ), mComponent( 0 ) {} 66 ToStringVisitor( ICalFormatImpl *impl ) : mImpl( impl ), mComponent( 0 ) {}
67 67
68 bool visit( Event *e ) { mComponent = mImpl->writeEvent( e ); return true; } 68 bool visit( Event *e ) { mComponent = mImpl->writeEvent( e ); return true; }
69 bool visit( Todo *e ) { mComponent = mImpl->writeTodo( e ); return true; } 69 bool visit( Todo *e ) { mComponent = mImpl->writeTodo( e ); return true; }
70 bool visit( Journal *e ) { mComponent = mImpl->writeJournal( e ); return true; } 70 bool visit( Journal *e ) { mComponent = mImpl->writeJournal( e ); return true; }
71 71
72 icalcomponent *component() { return mComponent; } 72 icalcomponent *component() { return mComponent; }
73 73
74 private: 74 private:
75 ICalFormatImpl *mImpl; 75 ICalFormatImpl *mImpl;
76 icalcomponent *mComponent; 76 icalcomponent *mComponent;
77}; 77};
78 78
79icalcomponent *ICalFormatImpl::writeIncidence(Incidence *incidence) 79icalcomponent *ICalFormatImpl::writeIncidence(Incidence *incidence)
80{ 80{
81 ToStringVisitor v( this ); 81 ToStringVisitor v( this );
82 incidence->accept(v); 82 incidence->accept(v);
83 return v.component(); 83 return v.component();
84} 84}
85 85
86icalcomponent *ICalFormatImpl::writeTodo(Todo *todo) 86icalcomponent *ICalFormatImpl::writeTodo(Todo *todo)
87{ 87{
88 QString tmpStr; 88 QString tmpStr;
89 QStringList tmpStrList; 89 QStringList tmpStrList;
90 90
91 icalcomponent *vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT); 91 icalcomponent *vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
92 92
93 writeIncidence(vtodo,todo); 93 writeIncidence(vtodo,todo);
94 94
95 // due date 95 // due date
96 if (todo->hasDueDate()) { 96 if (todo->hasDueDate()) {
97 icaltimetype due; 97 icaltimetype due;
98 if (todo->doesFloat()) { 98 if (todo->doesFloat()) {
99 due = writeICalDate(todo->dtDue().date()); 99 due = writeICalDate(todo->dtDue().date());
100 } else { 100 } else {
101 due = writeICalDateTime(todo->dtDue()); 101 due = writeICalDateTime(todo->dtDue());
102 } 102 }
103 icalcomponent_add_property(vtodo,icalproperty_new_due(due)); 103 icalcomponent_add_property(vtodo,icalproperty_new_due(due));
104 } 104 }
105 105
106 // start time 106 // start time
107 if (todo->hasStartDate()) { 107 if (todo->hasStartDate()) {
108 icaltimetype start; 108 icaltimetype start;
109 if (todo->doesFloat()) { 109 if (todo->doesFloat()) {
110// kdDebug(5800) << "§§ Incidence " << todo->summary() << " floats." << endl; 110// kdDebug(5800) << "§§ Incidence " << todo->summary() << " floats." << endl;
111 start = writeICalDate(todo->dtStart().date()); 111 start = writeICalDate(todo->dtStart().date());
112 } else { 112 } else {
113// kdDebug(5800) << "§§ incidence " << todo->summary() << " has time." << endl; 113// kdDebug(5800) << "§§ incidence " << todo->summary() << " has time." << endl;
114 start = writeICalDateTime(todo->dtStart()); 114 start = writeICalDateTime(todo->dtStart());
115 } 115 }
116 icalcomponent_add_property(vtodo,icalproperty_new_dtstart(start)); 116 icalcomponent_add_property(vtodo,icalproperty_new_dtstart(start));
117 } 117 }
118 118
119 // completion date 119 // completion date
120 if (todo->isCompleted()) { 120 if (todo->isCompleted()) {
121 if (!todo->hasCompletedDate()) { 121 if (!todo->hasCompletedDate()) {
122 // If todo was created by KOrganizer <2.2 it has no correct completion 122 // If todo was created by KOrganizer <2.2 it has no correct completion
123 // date. Set it to now. 123 // date. Set it to now.
124 todo->setCompleted(QDateTime::currentDateTime()); 124 todo->setCompleted(QDateTime::currentDateTime());
125 } 125 }
126 icaltimetype completed = writeICalDateTime(todo->completed()); 126 icaltimetype completed = writeICalDateTime(todo->completed());
127 icalcomponent_add_property(vtodo,icalproperty_new_completed(completed)); 127 icalcomponent_add_property(vtodo,icalproperty_new_completed(completed));
128 } 128 }
129 129
130 icalcomponent_add_property(vtodo, 130 icalcomponent_add_property(vtodo,
131 icalproperty_new_percentcomplete(todo->percentComplete())); 131 icalproperty_new_percentcomplete(todo->percentComplete()));
132 132
133 return vtodo; 133 return vtodo;
134} 134}
135 135
136icalcomponent *ICalFormatImpl::writeEvent(Event *event) 136icalcomponent *ICalFormatImpl::writeEvent(Event *event)
137{ 137{
138 kdDebug(5800) << "Write Event '" << event->summary() << "' (" << event->uid() 138 kdDebug(5800) << "Write Event '" << event->summary() << "' (" << event->uid()
139 << ")" << endl; 139 << ")" << endl;
140 140
141 QString tmpStr; 141 QString tmpStr;
142 QStringList tmpStrList; 142 QStringList tmpStrList;
143 143
144 icalcomponent *vevent = icalcomponent_new(ICAL_VEVENT_COMPONENT); 144 icalcomponent *vevent = icalcomponent_new(ICAL_VEVENT_COMPONENT);
145 145
146 writeIncidence(vevent,event); 146 writeIncidence(vevent,event);
147 147
148 // start time 148 // start time
149 icaltimetype start; 149 icaltimetype start;
150 if (event->doesFloat()) { 150 if (event->doesFloat()) {
151// kdDebug(5800) << "§§ Incidence " << event->summary() << " floats." << endl; 151// kdDebug(5800) << "§§ Incidence " << event->summary() << " floats." << endl;
152 start = writeICalDate(event->dtStart().date()); 152 start = writeICalDate(event->dtStart().date());
153 } else { 153 } else {
154// kdDebug(5800) << "§§ incidence " << event->summary() << " has time." << endl; 154// kdDebug(5800) << "§§ incidence " << event->summary() << " has time." << endl;
155 start = writeICalDateTime(event->dtStart()); 155 start = writeICalDateTime(event->dtStart());
156 } 156 }
157 icalcomponent_add_property(vevent,icalproperty_new_dtstart(start)); 157 icalcomponent_add_property(vevent,icalproperty_new_dtstart(start));
158 158
159 if (event->hasEndDate()) { 159 if (event->hasEndDate()) {
160 // end time 160 // end time
161 icaltimetype end; 161 icaltimetype end;
162 if (event->doesFloat()) { 162 if (event->doesFloat()) {
163// kdDebug(5800) << "§§ Event " << event->summary() << " floats." << endl; 163// kdDebug(5800) << "§§ Event " << event->summary() << " floats." << endl;
164 // +1 day because end date is non-inclusive. 164 // +1 day because end date is non-inclusive.
165 end = writeICalDate( event->dtEnd().date().addDays( 1 ) ); 165 end = writeICalDate( event->dtEnd().date().addDays( 1 ) );
166 } else { 166 } else {
167// kdDebug(5800) << "§§ Event " << event->summary() << " has time." << endl; 167// kdDebug(5800) << "§§ Event " << event->summary() << " has time." << endl;
168 end = writeICalDateTime(event->dtEnd()); 168 end = writeICalDateTime(event->dtEnd());
169 } 169 }
170 icalcomponent_add_property(vevent,icalproperty_new_dtend(end)); 170 icalcomponent_add_property(vevent,icalproperty_new_dtend(end));
171 } 171 }
172 172
173// TODO: attachments, resources 173// TODO: attachments, resources
174#if 0 174#if 0
175 // attachments 175 // attachments
176 tmpStrList = anEvent->attachments(); 176 tmpStrList = anEvent->attachments();
177 for ( QStringList::Iterator it = tmpStrList.begin(); 177 for ( QStringList::Iterator it = tmpStrList.begin();
178 it != tmpStrList.end(); 178 it != tmpStrList.end();
179 ++it ) 179 ++it )
180 addPropValue(vevent, VCAttachProp, (*it).utf8()); 180 addPropValue(vevent, VCAttachProp, (*it).utf8());
181 181
182 // resources 182 // resources
183 tmpStrList = anEvent->resources(); 183 tmpStrList = anEvent->resources();
184 tmpStr = tmpStrList.join(";"); 184 tmpStr = tmpStrList.join(";");
185 if (!tmpStr.isEmpty()) 185 if (!tmpStr.isEmpty())
186 addPropValue(vevent, VCResourcesProp, tmpStr.utf8()); 186 addPropValue(vevent, VCResourcesProp, tmpStr.utf8());
187 187
188#endif 188#endif
189 189
190 // Transparency 190 // Transparency
191 switch( event->transparency() ) { 191 switch( event->transparency() ) {
192 case Event::Transparent: 192 case Event::Transparent:
193 icalcomponent_add_property(vevent, icalproperty_new_transp(ICAL_TRANSP_TRANSPARENT)); 193 icalcomponent_add_property(vevent, icalproperty_new_transp(ICAL_TRANSP_TRANSPARENT));
194 break; 194 break;
195 case Event::Opaque: 195 case Event::Opaque:
196 icalcomponent_add_property(vevent, icalproperty_new_transp(ICAL_TRANSP_OPAQUE)); 196 icalcomponent_add_property(vevent, icalproperty_new_transp(ICAL_TRANSP_OPAQUE));
197 break; 197 break;
198 } 198 }
199 199
200 return vevent; 200 return vevent;
201} 201}
202 202
203icalcomponent *ICalFormatImpl::writeFreeBusy(FreeBusy *freebusy, 203icalcomponent *ICalFormatImpl::writeFreeBusy(FreeBusy *freebusy,
204 Scheduler::Method method) 204 Scheduler::Method method)
205{ 205{
206#if QT_VERSION >= 300 206#if QT_VERSION >= 300
207 kdDebug(5800) << "icalformatimpl: writeFreeBusy: startDate: " 207 kdDebug(5800) << "icalformatimpl: writeFreeBusy: startDate: "
208 << freebusy->dtStart().toString("ddd MMMM d yyyy: h:m:s ap") << " End Date: " 208 << freebusy->dtStart().toString("ddd MMMM d yyyy: h:m:s ap") << " End Date: "
209 << freebusy->dtEnd().toString("ddd MMMM d yyyy: h:m:s ap") << endl; 209 << freebusy->dtEnd().toString("ddd MMMM d yyyy: h:m:s ap") << endl;
210#endif 210#endif
211 211
212 icalcomponent *vfreebusy = icalcomponent_new(ICAL_VFREEBUSY_COMPONENT); 212 icalcomponent *vfreebusy = icalcomponent_new(ICAL_VFREEBUSY_COMPONENT);
213 213
214 writeIncidenceBase(vfreebusy,freebusy); 214 writeIncidenceBase(vfreebusy,freebusy);
215 215
216 icalcomponent_add_property(vfreebusy, icalproperty_new_dtstart( 216 icalcomponent_add_property(vfreebusy, icalproperty_new_dtstart(
217 writeICalDateTime(freebusy->dtStart()))); 217 writeICalDateTime(freebusy->dtStart())));
218 218
219 icalcomponent_add_property(vfreebusy, icalproperty_new_dtend( 219 icalcomponent_add_property(vfreebusy, icalproperty_new_dtend(
220 writeICalDateTime(freebusy->dtEnd()))); 220 writeICalDateTime(freebusy->dtEnd())));
221 221
222 if (method == Scheduler::Request) { 222 if (method == Scheduler::Request) {
223 icalcomponent_add_property(vfreebusy,icalproperty_new_uid( 223 icalcomponent_add_property(vfreebusy,icalproperty_new_uid(
224 freebusy->uid().utf8())); 224 freebusy->uid().utf8()));
225 } 225 }
226 226
227 //Loops through all the periods in the freebusy object 227 //Loops through all the periods in the freebusy object
228 QValueList<Period> list = freebusy->busyPeriods(); 228 QValueList<Period> list = freebusy->busyPeriods();
229 QValueList<Period>::Iterator it; 229 QValueList<Period>::Iterator it;
230 icalperiodtype period; 230 icalperiodtype period;
231 for (it = list.begin(); it!= list.end(); ++it) { 231 for (it = list.begin(); it!= list.end(); ++it) {
232 period.start = writeICalDateTime((*it).start()); 232 period.start = writeICalDateTime((*it).start());
233 period.end = writeICalDateTime((*it).end()); 233 period.end = writeICalDateTime((*it).end());
234 icalcomponent_add_property(vfreebusy, icalproperty_new_freebusy(period) ); 234 icalcomponent_add_property(vfreebusy, icalproperty_new_freebusy(period) );
235 } 235 }
236 236
237 return vfreebusy; 237 return vfreebusy;
238} 238}
239 239
240icalcomponent *ICalFormatImpl::writeJournal(Journal *journal) 240icalcomponent *ICalFormatImpl::writeJournal(Journal *journal)
241{ 241{
242 icalcomponent *vjournal = icalcomponent_new(ICAL_VJOURNAL_COMPONENT); 242 icalcomponent *vjournal = icalcomponent_new(ICAL_VJOURNAL_COMPONENT);
243 243
244 writeIncidence(vjournal,journal); 244 writeIncidence(vjournal,journal);
245 245
246 // start time 246 // start time
247 if (journal->dtStart().isValid()) { 247 if (journal->dtStart().isValid()) {
248 icaltimetype start; 248 icaltimetype start;
249 if (journal->doesFloat()) { 249 if (journal->doesFloat()) {
250// kdDebug(5800) << "§§ Incidence " << event->summary() << " floats." << endl; 250// kdDebug(5800) << "§§ Incidence " << event->summary() << " floats." << endl;
251 start = writeICalDate(journal->dtStart().date()); 251 start = writeICalDate(journal->dtStart().date());
252 } else { 252 } else {
253// kdDebug(5800) << "§§ incidence " << event->summary() << " has time." << endl; 253// kdDebug(5800) << "§§ incidence " << event->summary() << " has time." << endl;
254 start = writeICalDateTime(journal->dtStart()); 254 start = writeICalDateTime(journal->dtStart());
255 } 255 }
256 icalcomponent_add_property(vjournal,icalproperty_new_dtstart(start)); 256 icalcomponent_add_property(vjournal,icalproperty_new_dtstart(start));
257 } 257 }
258 258
259 return vjournal; 259 return vjournal;
260} 260}
261 261
262void ICalFormatImpl::writeIncidence(icalcomponent *parent,Incidence *incidence) 262void ICalFormatImpl::writeIncidence(icalcomponent *parent,Incidence *incidence)
263{ 263{
264 // pilot sync stuff 264 // pilot sync stuff
265// TODO: move this application-specific code to kpilot 265// TODO: move this application-specific code to kpilot
266 if (incidence->pilotId()) { 266 if (incidence->pilotId()) {
267 incidence->setNonKDECustomProperty("X-PILOTID", QString::number(incidence->pilotId())); 267 incidence->setNonKDECustomProperty("X-PILOTID", QString::number(incidence->pilotId()));
268 incidence->setNonKDECustomProperty("X-PILOTSTAT", QString::number(incidence->syncStatus())); 268 incidence->setNonKDECustomProperty("X-PILOTSTAT", QString::number(incidence->syncStatus()));
269 } 269 }
270 if (incidence->zaurusId() >= 0) { 270 if (incidence->zaurusId() >= 0) {
271 incidence->setNonKDECustomProperty("X-ZAURUSID", QString::number(incidence->zaurusId())); 271 incidence->setNonKDECustomProperty("X-ZAURUSID", QString::number(incidence->zaurusId()));
272 } 272 }
273 273
274 if (incidence->zaurusUid() > 0) { 274 if (incidence->zaurusUid() > 0) {
275 incidence->setNonKDECustomProperty("X-ZAURUSUID", QString::number(incidence->zaurusUid())); 275 incidence->setNonKDECustomProperty("X-ZAURUSUID", QString::number(incidence->zaurusUid()));
276 } 276 }
277 if (incidence->zaurusStat() > 0) { 277 if (incidence->zaurusStat() > 0) {
278 incidence->setNonKDECustomProperty("X-ZAURUSSTAT", QString::number(incidence->zaurusStat())); 278 incidence->setNonKDECustomProperty("X-ZAURUSSTAT", QString::number(incidence->zaurusStat()));
279 } 279 }
280 280
281 writeIncidenceBase(parent,incidence); 281 writeIncidenceBase(parent,incidence);
282 if (incidence->cancelled()) { 282 if (incidence->cancelled()) {
283 icalcomponent_add_property(parent,icalproperty_new_status(ICAL_STATUS_CANCELLED)); 283 icalcomponent_add_property(parent,icalproperty_new_status(ICAL_STATUS_CANCELLED));
284 } 284 }
285 285
286 // creation date 286 // creation date
287 icalcomponent_add_property(parent,icalproperty_new_created( 287 icalcomponent_add_property(parent,icalproperty_new_created(
288 writeICalDateTime(incidence->created()))); 288 writeICalDateTime(incidence->created())));
289 289
290 // unique id 290 // unique id
291 icalcomponent_add_property(parent,icalproperty_new_uid( 291 icalcomponent_add_property(parent,icalproperty_new_uid(
292 incidence->uid().utf8())); 292 incidence->uid().utf8()));
293 293
294 // revision 294 // revision
295 icalcomponent_add_property(parent,icalproperty_new_sequence( 295 icalcomponent_add_property(parent,icalproperty_new_sequence(
296 incidence->revision())); 296 incidence->revision()));
297 297
298 // last modification date 298 // last modification date
299 icalcomponent_add_property(parent,icalproperty_new_lastmodified( 299 icalcomponent_add_property(parent,icalproperty_new_lastmodified(
300 writeICalDateTime(incidence->lastModified()))); 300 writeICalDateTime(incidence->lastModified())));
301 301
302 // description 302 // description
303 if (!incidence->description().isEmpty()) { 303 if (!incidence->description().isEmpty()) {
304 icalcomponent_add_property(parent,icalproperty_new_description( 304 icalcomponent_add_property(parent,icalproperty_new_description(
305 incidence->description().utf8())); 305 incidence->description().utf8()));
306 } 306 }
307 307
308 // summary 308 // summary
309 if (!incidence->summary().isEmpty()) { 309 if (!incidence->summary().isEmpty()) {
310 icalcomponent_add_property(parent,icalproperty_new_summary( 310 icalcomponent_add_property(parent,icalproperty_new_summary(
311 incidence->summary().utf8())); 311 incidence->summary().utf8()));
312 } 312 }
313 313
314 // location 314 // location
315 if (!incidence->location().isEmpty()) { 315 if (!incidence->location().isEmpty()) {
316 icalcomponent_add_property(parent,icalproperty_new_location( 316 icalcomponent_add_property(parent,icalproperty_new_location(
317 incidence->location().utf8())); 317 incidence->location().utf8()));
318 } 318 }
319 319
320// TODO: 320// TODO:
321 // status 321 // status
322// addPropValue(parent, VCStatusProp, incidence->getStatusStr().utf8()); 322// addPropValue(parent, VCStatusProp, incidence->getStatusStr().utf8());
323 323
324 // secrecy 324 // secrecy
325 enum icalproperty_class classInt; 325 enum icalproperty_class classInt;
326 switch (incidence->secrecy()) { 326 switch (incidence->secrecy()) {
327 case Incidence::SecrecyPublic: 327 case Incidence::SecrecyPublic:
328 classInt = ICAL_CLASS_PUBLIC; 328 classInt = ICAL_CLASS_PUBLIC;
329 break; 329 break;
330 case Incidence::SecrecyConfidential: 330 case Incidence::SecrecyConfidential:
331 classInt = ICAL_CLASS_CONFIDENTIAL; 331 classInt = ICAL_CLASS_CONFIDENTIAL;
332 break; 332 break;
333 case Incidence::SecrecyPrivate: 333 case Incidence::SecrecyPrivate:
334 classInt =ICAL_CLASS_PRIVATE ; 334 classInt =ICAL_CLASS_PRIVATE ;
335 default: 335 default:
336 classInt =ICAL_CLASS_PRIVATE ; 336 classInt =ICAL_CLASS_PRIVATE ;
337 break; 337 break;
338 } 338 }
339 icalcomponent_add_property(parent,icalproperty_new_class(classInt)); 339 icalcomponent_add_property(parent,icalproperty_new_class(classInt));
340 340
341 // priority 341 // priority
342 icalcomponent_add_property(parent,icalproperty_new_priority( 342 icalcomponent_add_property(parent,icalproperty_new_priority(
343 incidence->priority())); 343 incidence->priority()));
344 344
345 // categories 345 // categories
346 QStringList categories = incidence->categories(); 346 QStringList categories = incidence->categories();
347 QStringList::Iterator it; 347 QStringList::Iterator it;
348 for(it = categories.begin(); it != categories.end(); ++it ) { 348 for(it = categories.begin(); it != categories.end(); ++it ) {
349 icalcomponent_add_property(parent,icalproperty_new_categories((*it).utf8())); 349 icalcomponent_add_property(parent,icalproperty_new_categories((*it).utf8()));
350 } 350 }
351// TODO: Ensure correct concatenation of categories properties. 351// TODO: Ensure correct concatenation of categories properties.
352 352
353/* 353/*
354 // categories 354 // categories
355 tmpStrList = incidence->getCategories(); 355 tmpStrList = incidence->getCategories();
356 tmpStr = ""; 356 tmpStr = "";
357 QString catStr; 357 QString catStr;
358 for ( QStringList::Iterator it = tmpStrList.begin(); 358 for ( QStringList::Iterator it = tmpStrList.begin();
359 it != tmpStrList.end(); 359 it != tmpStrList.end();
360 ++it ) { 360 ++it ) {
361 catStr = *it; 361 catStr = *it;
362 if (catStr[0] == ' ') 362 if (catStr[0] == ' ')
363 tmpStr += catStr.mid(1); 363 tmpStr += catStr.mid(1);
364 else 364 else
365 tmpStr += catStr; 365 tmpStr += catStr;
366 // this must be a ';' character as the vCalendar specification requires! 366 // this must be a ';' character as the vCalendar specification requires!
367 // vcc.y has been hacked to translate the ';' to a ',' when the vcal is 367 // vcc.y has been hacked to translate the ';' to a ',' when the vcal is
368 // read in. 368 // read in.
369 tmpStr += ";"; 369 tmpStr += ";";
370 } 370 }
371 if (!tmpStr.isEmpty()) { 371 if (!tmpStr.isEmpty()) {
372 tmpStr.truncate(tmpStr.length()-1); 372 tmpStr.truncate(tmpStr.length()-1);
373 icalcomponent_add_property(parent,icalproperty_new_categories( 373 icalcomponent_add_property(parent,icalproperty_new_categories(
374 writeText(incidence->getCategories().join(";")))); 374 writeText(incidence->getCategories().join(";"))));
375 } 375 }
376*/ 376*/
377 377
378 // related event 378 // related event
379 if (incidence->relatedTo()) { 379 if (incidence->relatedTo()) {
380 icalcomponent_add_property(parent,icalproperty_new_relatedto( 380 icalcomponent_add_property(parent,icalproperty_new_relatedto(
381 incidence->relatedTo()->uid().utf8())); 381 incidence->relatedTo()->uid().utf8()));
382 } 382 }
383 383
384 // recurrence rule stuff 384 // recurrence rule stuff
385 Recurrence *recur = incidence->recurrence(); 385 Recurrence *recur = incidence->recurrence();
386 if (recur->doesRecur()) { 386 if (recur->doesRecur()) {
387 387
388 icalcomponent_add_property(parent,writeRecurrenceRule(recur)); 388 icalcomponent_add_property(parent,writeRecurrenceRule(recur));
389 } 389 }
390 390
391 // recurrence excpetion dates 391 // recurrence excpetion dates
392 DateList dateList = incidence->exDates(); 392 DateList dateList = incidence->exDates();
393 DateList::ConstIterator exIt; 393 DateList::ConstIterator exIt;
394 for(exIt = dateList.begin(); exIt != dateList.end(); ++exIt) { 394 for(exIt = dateList.begin(); exIt != dateList.end(); ++exIt) {
395 icalcomponent_add_property(parent,icalproperty_new_exdate( 395 icalcomponent_add_property(parent,icalproperty_new_exdate(
396 writeICalDate(*exIt))); 396 writeICalDate(*exIt)));
397 } 397 }
398 398
399 // attachments 399 // attachments
400 QPtrList<Attachment> attachments = incidence->attachments(); 400 QPtrList<Attachment> attachments = incidence->attachments();
401 for (Attachment *at = attachments.first(); at; at = attachments.next()) 401 for (Attachment *at = attachments.first(); at; at = attachments.next())
402 icalcomponent_add_property(parent,writeAttachment(at)); 402 icalcomponent_add_property(parent,writeAttachment(at));
403 403
404 // alarms 404 // alarms
405 QPtrList<Alarm> alarms = incidence->alarms(); 405 QPtrList<Alarm> alarms = incidence->alarms();
406 Alarm* alarm; 406 Alarm* alarm;
407 for (alarm = alarms.first(); alarm; alarm = alarms.next()) { 407 for (alarm = alarms.first(); alarm; alarm = alarms.next()) {
408 if (alarm->enabled()) { 408 if (alarm->enabled()) {
409 kdDebug(5800) << "Write alarm for " << incidence->summary() << endl; 409 kdDebug(5800) << "Write alarm for " << incidence->summary() << endl;
410 icalcomponent_add_component(parent,writeAlarm(alarm)); 410 icalcomponent_add_component(parent,writeAlarm(alarm));
411 } 411 }
412 } 412 }
413 413
414 // duration 414 // duration
415 415
416// turned off as it always is set to PTS0 (and must not occur together with DTEND 416// turned off as it always is set to PTS0 (and must not occur together with DTEND
417 417
418// if (incidence->hasDuration()) { 418// if (incidence->hasDuration()) {
419// icaldurationtype duration; 419// icaldurationtype duration;
420// duration = writeICalDuration(incidence->duration()); 420// duration = writeICalDuration(incidence->duration());
421// icalcomponent_add_property(parent,icalproperty_new_duration(duration)); 421// icalcomponent_add_property(parent,icalproperty_new_duration(duration));
422// } 422// }
423} 423}
424 424
425void ICalFormatImpl::writeIncidenceBase(icalcomponent *parent,IncidenceBase *incidenceBase) 425void ICalFormatImpl::writeIncidenceBase(icalcomponent *parent,IncidenceBase *incidenceBase)
426{ 426{
427 icalcomponent_add_property(parent,icalproperty_new_dtstamp( 427 icalcomponent_add_property(parent,icalproperty_new_dtstamp(
428 writeICalDateTime(QDateTime::currentDateTime()))); 428 writeICalDateTime(QDateTime::currentDateTime())));
429 429
430 // organizer stuff 430 // organizer stuff
431 icalcomponent_add_property(parent,icalproperty_new_organizer( 431 icalcomponent_add_property(parent,icalproperty_new_organizer(
432 ("MAILTO:" + incidenceBase->organizer()).utf8())); 432 ("MAILTO:" + incidenceBase->organizer()).utf8()));
433 433
434 // attendees 434 // attendees
435 if (incidenceBase->attendeeCount() != 0) { 435 if (incidenceBase->attendeeCount() != 0) {
436 QPtrList<Attendee> al = incidenceBase->attendees(); 436 QPtrList<Attendee> al = incidenceBase->attendees();
437 QPtrListIterator<Attendee> ai(al); 437 QPtrListIterator<Attendee> ai(al);
438 for (; ai.current(); ++ai) { 438 for (; ai.current(); ++ai) {
439 icalcomponent_add_property(parent,writeAttendee(ai.current())); 439 icalcomponent_add_property(parent,writeAttendee(ai.current()));
440 } 440 }
441 } 441 }
442 442
443 // custom properties 443 // custom properties
444 writeCustomProperties(parent, incidenceBase); 444 writeCustomProperties(parent, incidenceBase);
445} 445}
446 446
447void ICalFormatImpl::writeCustomProperties(icalcomponent *parent,CustomProperties *properties) 447void ICalFormatImpl::writeCustomProperties(icalcomponent *parent,CustomProperties *properties)
448{ 448{
449 QMap<QCString, QString> custom = properties->customProperties(); 449 QMap<QCString, QString> custom = properties->customProperties();
450 for (QMap<QCString, QString>::Iterator c = custom.begin(); c != custom.end(); ++c) { 450 for (QMap<QCString, QString>::Iterator c = custom.begin(); c != custom.end(); ++c) {
451 icalproperty *p = icalproperty_new_x(c.data().utf8()); 451 icalproperty *p = icalproperty_new_x(c.data().utf8());
452 icalproperty_set_x_name(p,c.key()); 452 icalproperty_set_x_name(p,c.key());
453 icalcomponent_add_property(parent,p); 453 icalcomponent_add_property(parent,p);
454 } 454 }
455} 455}
456 456
457icalproperty *ICalFormatImpl::writeAttendee(Attendee *attendee) 457icalproperty *ICalFormatImpl::writeAttendee(Attendee *attendee)
458{ 458{
459 icalproperty *p = icalproperty_new_attendee("mailto:" + attendee->email().utf8()); 459 icalproperty *p = icalproperty_new_attendee("mailto:" + attendee->email().utf8());
460 460
461 if (!attendee->name().isEmpty()) { 461 if (!attendee->name().isEmpty()) {
462 icalproperty_add_parameter(p,icalparameter_new_cn(attendee->name().utf8())); 462 icalproperty_add_parameter(p,icalparameter_new_cn(attendee->name().utf8()));
463 } 463 }
464 464
465 465
466 icalproperty_add_parameter(p,icalparameter_new_rsvp( 466 icalproperty_add_parameter(p,icalparameter_new_rsvp(
467 attendee->RSVP() ? ICAL_RSVP_TRUE : ICAL_RSVP_FALSE )); 467 attendee->RSVP() ? ICAL_RSVP_TRUE : ICAL_RSVP_FALSE ));
468 468
469 icalparameter_partstat status = ICAL_PARTSTAT_NEEDSACTION; 469 icalparameter_partstat status = ICAL_PARTSTAT_NEEDSACTION;
470 switch (attendee->status()) { 470 switch (attendee->status()) {
471 default: 471 default:
472 case Attendee::NeedsAction: 472 case Attendee::NeedsAction:
473 status = ICAL_PARTSTAT_NEEDSACTION; 473 status = ICAL_PARTSTAT_NEEDSACTION;
474 break; 474 break;
475 case Attendee::Accepted: 475 case Attendee::Accepted:
476 status = ICAL_PARTSTAT_ACCEPTED; 476 status = ICAL_PARTSTAT_ACCEPTED;
477 break; 477 break;
478 case Attendee::Declined: 478 case Attendee::Declined:
479 status = ICAL_PARTSTAT_DECLINED; 479 status = ICAL_PARTSTAT_DECLINED;
480 break; 480 break;
481 case Attendee::Tentative: 481 case Attendee::Tentative:
482 status = ICAL_PARTSTAT_TENTATIVE; 482 status = ICAL_PARTSTAT_TENTATIVE;
483 break; 483 break;
484 case Attendee::Delegated: 484 case Attendee::Delegated:
485 status = ICAL_PARTSTAT_DELEGATED; 485 status = ICAL_PARTSTAT_DELEGATED;
486 break; 486 break;
487 case Attendee::Completed: 487 case Attendee::Completed:
488 status = ICAL_PARTSTAT_COMPLETED; 488 status = ICAL_PARTSTAT_COMPLETED;
489 break; 489 break;
490 case Attendee::InProcess: 490 case Attendee::InProcess:
491 status = ICAL_PARTSTAT_INPROCESS; 491 status = ICAL_PARTSTAT_INPROCESS;
492 break; 492 break;
493 } 493 }
494 icalproperty_add_parameter(p,icalparameter_new_partstat(status)); 494 icalproperty_add_parameter(p,icalparameter_new_partstat(status));
495 495
496 icalparameter_role role = ICAL_ROLE_REQPARTICIPANT; 496 icalparameter_role role = ICAL_ROLE_REQPARTICIPANT;
497 switch (attendee->role()) { 497 switch (attendee->role()) {
498 case Attendee::Chair: 498 case Attendee::Chair:
499 role = ICAL_ROLE_CHAIR; 499 role = ICAL_ROLE_CHAIR;
500 break; 500 break;
501 default: 501 default:
502 case Attendee::ReqParticipant: 502 case Attendee::ReqParticipant:
503 role = ICAL_ROLE_REQPARTICIPANT; 503 role = ICAL_ROLE_REQPARTICIPANT;
504 break; 504 break;
505 case Attendee::OptParticipant: 505 case Attendee::OptParticipant:
506 role = ICAL_ROLE_OPTPARTICIPANT; 506 role = ICAL_ROLE_OPTPARTICIPANT;
507 break; 507 break;
508 case Attendee::NonParticipant: 508 case Attendee::NonParticipant:
509 role = ICAL_ROLE_NONPARTICIPANT; 509 role = ICAL_ROLE_NONPARTICIPANT;
510 break; 510 break;
511 } 511 }
512 icalproperty_add_parameter(p,icalparameter_new_role(role)); 512 icalproperty_add_parameter(p,icalparameter_new_role(role));
513 513
514 if (!attendee->uid().isEmpty()) { 514 if (!attendee->uid().isEmpty()) {
515 icalparameter* icalparameter_uid = icalparameter_new_x(attendee->uid().utf8()); 515 icalparameter* icalparameter_uid = icalparameter_new_x(attendee->uid().utf8());
516 icalparameter_set_xname(icalparameter_uid,"X-UID"); 516 icalparameter_set_xname(icalparameter_uid,"X-UID");
517 icalproperty_add_parameter(p,icalparameter_uid); 517 icalproperty_add_parameter(p,icalparameter_uid);
518 } 518 }
519 519
520 return p; 520 return p;
521} 521}
522 522
523icalproperty *ICalFormatImpl::writeAttachment(Attachment *att) 523icalproperty *ICalFormatImpl::writeAttachment(Attachment *att)
524{ 524{
525#if 0 525#if 0
526 icalattachtype* attach = icalattachtype_new(); 526 icalattachtype* attach = icalattachtype_new();
527 if (att->isURI()) 527 if (att->isURI())
528 icalattachtype_set_url(attach, att->uri().utf8().data()); 528 icalattachtype_set_url(attach, att->uri().utf8().data());
529 else 529 else
530 icalattachtype_set_base64(attach, att->data(), 0); 530 icalattachtype_set_base64(attach, att->data(), 0);
531#endif 531#endif
532 icalattach *attach; 532 icalattach *attach;
533 if (att->isURI()) 533 if (att->isURI())
534 attach = icalattach_new_from_url( att->uri().utf8().data()); 534 attach = icalattach_new_from_url( att->uri().utf8().data());
535 else 535 else
536 attach = icalattach_new_from_data ( (unsigned char *)att->data(), 0, 0); 536 attach = icalattach_new_from_data ( (unsigned char *)att->data(), 0, 0);
537 icalproperty *p = icalproperty_new_attach(attach); 537 icalproperty *p = icalproperty_new_attach(attach);
538 if (!att->mimeType().isEmpty()) 538 if (!att->mimeType().isEmpty())
539 icalproperty_add_parameter(p,icalparameter_new_fmttype(att->mimeType().utf8().data())); 539 icalproperty_add_parameter(p,icalparameter_new_fmttype(att->mimeType().utf8().data()));
540 540
541 if (att->isBinary()) { 541 if (att->isBinary()) {
542 icalproperty_add_parameter(p,icalparameter_new_value(ICAL_VALUE_BINARY)); 542 icalproperty_add_parameter(p,icalparameter_new_value(ICAL_VALUE_BINARY));
543 icalproperty_add_parameter(p,icalparameter_new_encoding(ICAL_ENCODING_BASE64)); 543 icalproperty_add_parameter(p,icalparameter_new_encoding(ICAL_ENCODING_BASE64));
544 } 544 }
545 return p; 545 return p;
546} 546}
547 547
548icalproperty *ICalFormatImpl::writeRecurrenceRule(Recurrence *recur) 548icalproperty *ICalFormatImpl::writeRecurrenceRule(Recurrence *recur)
549{ 549{
550// kdDebug(5800) << "ICalFormatImpl::writeRecurrenceRule()" << endl; 550// kdDebug(5800) << "ICalFormatImpl::writeRecurrenceRule()" << endl;
551 551
552 icalrecurrencetype r; 552 icalrecurrencetype r;
553 553
554 icalrecurrencetype_clear(&r); 554 icalrecurrencetype_clear(&r);
555 555
556 int index = 0; 556 int index = 0;
557 int index2 = 0; 557 int index2 = 0;
558 558
559 QPtrList<Recurrence::rMonthPos> tmpPositions; 559 QPtrList<Recurrence::rMonthPos> tmpPositions;
560 QPtrList<int> tmpDays; 560 QPtrList<int> tmpDays;
561 int *tmpDay; 561 int *tmpDay;
562 Recurrence::rMonthPos *tmpPos; 562 Recurrence::rMonthPos *tmpPos;
563 bool datetime = false; 563 bool datetime = false;
564 int day; 564 int day;
565 int i; 565 int i;
566 566
567 switch(recur->doesRecur()) { 567 switch(recur->doesRecur()) {
568 case Recurrence::rMinutely: 568 case Recurrence::rMinutely:
569 r.freq = ICAL_MINUTELY_RECURRENCE; 569 r.freq = ICAL_MINUTELY_RECURRENCE;
570 datetime = true; 570 datetime = true;
571 break; 571 break;
572 case Recurrence::rHourly: 572 case Recurrence::rHourly:
573 r.freq = ICAL_HOURLY_RECURRENCE; 573 r.freq = ICAL_HOURLY_RECURRENCE;
574 datetime = true; 574 datetime = true;
575 break; 575 break;
576 case Recurrence::rDaily: 576 case Recurrence::rDaily:
577 r.freq = ICAL_DAILY_RECURRENCE; 577 r.freq = ICAL_DAILY_RECURRENCE;
578 break; 578 break;
579 case Recurrence::rWeekly: 579 case Recurrence::rWeekly:
580 r.freq = ICAL_WEEKLY_RECURRENCE; 580 r.freq = ICAL_WEEKLY_RECURRENCE;
581 r.week_start = static_cast<icalrecurrencetype_weekday>(recur->weekStart()%7 + 1); 581 r.week_start = static_cast<icalrecurrencetype_weekday>(recur->weekStart()%7 + 1);
582 for (i = 0; i < 7; i++) { 582 for (i = 0; i < 7; i++) {
583 if (recur->days().testBit(i)) { 583 if (recur->days().testBit(i)) {
584 day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1 584 day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1
585 r.by_day[index++] = icalrecurrencetype_day_day_of_week(day); 585 r.by_day[index++] = icalrecurrencetype_day_day_of_week(day);
586 } 586 }
587 } 587 }
588// r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX; 588// r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX;
589 break; 589 break;
590 case Recurrence::rMonthlyPos: 590 case Recurrence::rMonthlyPos:
591 r.freq = ICAL_MONTHLY_RECURRENCE; 591 r.freq = ICAL_MONTHLY_RECURRENCE;
592 592
593 tmpPositions = recur->monthPositions(); 593 tmpPositions = recur->monthPositions();
594 for (tmpPos = tmpPositions.first(); 594 for (tmpPos = tmpPositions.first();
595 tmpPos; 595 tmpPos;
596 tmpPos = tmpPositions.next()) { 596 tmpPos = tmpPositions.next()) {
597 for (i = 0; i < 7; i++) { 597 for (i = 0; i < 7; i++) {
598 if (tmpPos->rDays.testBit(i)) { 598 if (tmpPos->rDays.testBit(i)) {
599 day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1 599 day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1
600 day += tmpPos->rPos*8; 600 day += tmpPos->rPos*8;
601 if (tmpPos->negative) day = -day; 601 if (tmpPos->negative) day = -day;
602 r.by_day[index++] = day; 602 r.by_day[index++] = day;
603 } 603 }
604 } 604 }
605 } 605 }
606// r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX; 606// r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX;
607 break; 607 break;
608 case Recurrence::rMonthlyDay: 608 case Recurrence::rMonthlyDay:
609 r.freq = ICAL_MONTHLY_RECURRENCE; 609 r.freq = ICAL_MONTHLY_RECURRENCE;
610 610
611 tmpDays = recur->monthDays(); 611 tmpDays = recur->monthDays();
612 for (tmpDay = tmpDays.first(); 612 for (tmpDay = tmpDays.first();
613 tmpDay; 613 tmpDay;
614 tmpDay = tmpDays.next()) { 614 tmpDay = tmpDays.next()) {
615 r.by_month_day[index++] = icalrecurrencetype_day_position(*tmpDay*8);//*tmpDay); 615 r.by_month_day[index++] = icalrecurrencetype_day_position(*tmpDay*8);//*tmpDay);
616 } 616 }
617// r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX; 617// r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX;
618 break; 618 break;
619 case Recurrence::rYearlyMonth: 619 case Recurrence::rYearlyMonth:
620 case Recurrence::rYearlyPos: 620 case Recurrence::rYearlyPos:
621 r.freq = ICAL_YEARLY_RECURRENCE; 621 r.freq = ICAL_YEARLY_RECURRENCE;
622 622
623 tmpDays = recur->yearNums(); 623 tmpDays = recur->yearNums();
624 for (tmpDay = tmpDays.first(); 624 for (tmpDay = tmpDays.first();
625 tmpDay; 625 tmpDay;
626 tmpDay = tmpDays.next()) { 626 tmpDay = tmpDays.next()) {
627 r.by_month[index++] = *tmpDay; 627 r.by_month[index++] = *tmpDay;
628 } 628 }
629// r.by_set_pos[index] = ICAL_RECURRENCE_ARRAY_MAX; 629// r.by_set_pos[index] = ICAL_RECURRENCE_ARRAY_MAX;
630 if (recur->doesRecur() == Recurrence::rYearlyPos) { 630 if (recur->doesRecur() == Recurrence::rYearlyPos) {
631 tmpPositions = recur->monthPositions(); 631 tmpPositions = recur->monthPositions();
632 for (tmpPos = tmpPositions.first(); 632 for (tmpPos = tmpPositions.first();
633 tmpPos; 633 tmpPos;
634 tmpPos = tmpPositions.next()) { 634 tmpPos = tmpPositions.next()) {
635 for (i = 0; i < 7; i++) { 635 for (i = 0; i < 7; i++) {
636 if (tmpPos->rDays.testBit(i)) { 636 if (tmpPos->rDays.testBit(i)) {
637 day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1 637 day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1
638 day += tmpPos->rPos*8; 638 day += tmpPos->rPos*8;
639 if (tmpPos->negative) day = -day; 639 if (tmpPos->negative) day = -day;
640 r.by_day[index2++] = day; 640 r.by_day[index2++] = day;
641 } 641 }
642 } 642 }
643 } 643 }
644// r.by_day[index2] = ICAL_RECURRENCE_ARRAY_MAX; 644// r.by_day[index2] = ICAL_RECURRENCE_ARRAY_MAX;
645 } 645 }
646 break; 646 break;
647 case Recurrence::rYearlyDay: 647 case Recurrence::rYearlyDay:
648 r.freq = ICAL_YEARLY_RECURRENCE; 648 r.freq = ICAL_YEARLY_RECURRENCE;
649 649
650 tmpDays = recur->yearNums(); 650 tmpDays = recur->yearNums();
651 for (tmpDay = tmpDays.first(); 651 for (tmpDay = tmpDays.first();
652 tmpDay; 652 tmpDay;
653 tmpDay = tmpDays.next()) { 653 tmpDay = tmpDays.next()) {
654 r.by_year_day[index++] = *tmpDay; 654 r.by_year_day[index++] = *tmpDay;
655 } 655 }
656// r.by_year_day[index] = ICAL_RECURRENCE_ARRAY_MAX; 656// r.by_year_day[index] = ICAL_RECURRENCE_ARRAY_MAX;
657 break; 657 break;
658 default: 658 default:
659 r.freq = ICAL_NO_RECURRENCE; 659 r.freq = ICAL_NO_RECURRENCE;
660 kdDebug(5800) << "ICalFormatImpl::writeRecurrence(): no recurrence" << endl; 660 kdDebug(5800) << "ICalFormatImpl::writeRecurrence(): no recurrence" << endl;
661 break; 661 break;
662 } 662 }
663 663
664 r.interval = recur->frequency(); 664 r.interval = recur->frequency();
665 665
666 if (recur->duration() > 0) { 666 if (recur->duration() > 0) {
667 r.count = recur->duration(); 667 r.count = recur->duration();
668 } else if (recur->duration() == -1) { 668 } else if (recur->duration() == -1) {
669 r.count = 0; 669 r.count = 0;
670 } else { 670 } else {
671 if (datetime) 671 if (datetime)
672 r.until = writeICalDateTime(recur->endDateTime()); 672 r.until = writeICalDateTime(recur->endDateTime());
673 else 673 else
674 r.until = writeICalDate(recur->endDate()); 674 r.until = writeICalDate(recur->endDate());
675 } 675 }
676 676
677// Debug output 677// Debug output
678#if 0 678#if 0
679 const char *str = icalrecurrencetype_as_string(&r); 679 const char *str = icalrecurrencetype_as_string(&r);
680 if (str) { 680 if (str) {
681 kdDebug(5800) << " String: " << str << endl; 681 kdDebug(5800) << " String: " << str << endl;
682 } else { 682 } else {
683 kdDebug(5800) << " No String" << endl; 683 kdDebug(5800) << " No String" << endl;
684 } 684 }
685#endif 685#endif
686 686
687 return icalproperty_new_rrule(r); 687 return icalproperty_new_rrule(r);
688} 688}
689 689
690icalcomponent *ICalFormatImpl::writeAlarm(Alarm *alarm) 690icalcomponent *ICalFormatImpl::writeAlarm(Alarm *alarm)
691{ 691{
692 icalcomponent *a = icalcomponent_new(ICAL_VALARM_COMPONENT); 692 icalcomponent *a = icalcomponent_new(ICAL_VALARM_COMPONENT);
693 693
694 icalproperty_action action; 694 icalproperty_action action;
695 icalattach *attach = 0; 695 icalattach *attach = 0;
696 696
697 switch (alarm->type()) { 697 switch (alarm->type()) {
698 case Alarm::Procedure: 698 case Alarm::Procedure:
699 action = ICAL_ACTION_PROCEDURE; 699 action = ICAL_ACTION_PROCEDURE;
700 attach = icalattach_new_from_url( QFile::encodeName(alarm->programFile()).data() ); 700 attach = icalattach_new_from_url( QFile::encodeName(alarm->programFile()).data() );
701 icalcomponent_add_property(a,icalproperty_new_attach(attach)); 701 icalcomponent_add_property(a,icalproperty_new_attach(attach));
702 if (!alarm->programArguments().isEmpty()) { 702 if (!alarm->programArguments().isEmpty()) {
703 icalcomponent_add_property(a,icalproperty_new_description(alarm->programArguments().utf8())); 703 icalcomponent_add_property(a,icalproperty_new_description(alarm->programArguments().utf8()));
704 } 704 }
705 break; 705 break;
706 case Alarm::Audio: 706 case Alarm::Audio:
707 action = ICAL_ACTION_AUDIO; 707 action = ICAL_ACTION_AUDIO;
708 if (!alarm->audioFile().isEmpty()) { 708 if (!alarm->audioFile().isEmpty()) {
709 attach = icalattach_new_from_url(QFile::encodeName( alarm->audioFile() ).data()); 709 attach = icalattach_new_from_url(QFile::encodeName( alarm->audioFile() ).data());
710 icalcomponent_add_property(a,icalproperty_new_attach(attach)); 710 icalcomponent_add_property(a,icalproperty_new_attach(attach));
711 } 711 }
712 break; 712 break;
713 case Alarm::Email: { 713 case Alarm::Email: {
714 action = ICAL_ACTION_EMAIL; 714 action = ICAL_ACTION_EMAIL;
715 QValueList<Person> addresses = alarm->mailAddresses(); 715 QValueList<Person> addresses = alarm->mailAddresses();
716 for (QValueList<Person>::Iterator ad = addresses.begin(); ad != addresses.end(); ++ad) { 716 for (QValueList<Person>::Iterator ad = addresses.begin(); ad != addresses.end(); ++ad) {
717 icalproperty *p = icalproperty_new_attendee("MAILTO:" + (*ad).email().utf8()); 717 icalproperty *p = icalproperty_new_attendee("MAILTO:" + (*ad).email().utf8());
718 if (!(*ad).name().isEmpty()) { 718 if (!(*ad).name().isEmpty()) {
719 icalproperty_add_parameter(p,icalparameter_new_cn((*ad).name().utf8())); 719 icalproperty_add_parameter(p,icalparameter_new_cn((*ad).name().utf8()));
720 } 720 }
721 icalcomponent_add_property(a,p); 721 icalcomponent_add_property(a,p);
722 } 722 }
723 icalcomponent_add_property(a,icalproperty_new_summary(alarm->mailSubject().utf8())); 723 icalcomponent_add_property(a,icalproperty_new_summary(alarm->mailSubject().utf8()));
724 icalcomponent_add_property(a,icalproperty_new_description(alarm->text().utf8())); 724 icalcomponent_add_property(a,icalproperty_new_description(alarm->text().utf8()));
725 QStringList attachments = alarm->mailAttachments(); 725 QStringList attachments = alarm->mailAttachments();
726 if (attachments.count() > 0) { 726 if (attachments.count() > 0) {
727 for (QStringList::Iterator at = attachments.begin(); at != attachments.end(); ++at) { 727 for (QStringList::Iterator at = attachments.begin(); at != attachments.end(); ++at) {
728 attach = icalattach_new_from_url(QFile::encodeName( *at ).data()); 728 attach = icalattach_new_from_url(QFile::encodeName( *at ).data());
729 icalcomponent_add_property(a,icalproperty_new_attach(attach)); 729 icalcomponent_add_property(a,icalproperty_new_attach(attach));
730 } 730 }
731 } 731 }
732 break; 732 break;
733 } 733 }
734 case Alarm::Display: 734 case Alarm::Display:
735 action = ICAL_ACTION_DISPLAY; 735 action = ICAL_ACTION_DISPLAY;
736 icalcomponent_add_property(a,icalproperty_new_description(alarm->text().utf8())); 736 icalcomponent_add_property(a,icalproperty_new_description(alarm->text().utf8()));
737 break; 737 break;
738 case Alarm::Invalid: 738 case Alarm::Invalid:
739 default: 739 default:
740 kdDebug(5800) << "Unknown type of alarm" << endl; 740 kdDebug(5800) << "Unknown type of alarm" << endl;
741 action = ICAL_ACTION_NONE; 741 action = ICAL_ACTION_NONE;
742 break; 742 break;
743 } 743 }
744 icalcomponent_add_property(a,icalproperty_new_action(action)); 744 icalcomponent_add_property(a,icalproperty_new_action(action));
745 745
746 // Trigger time 746 // Trigger time
747 icaltriggertype trigger; 747 icaltriggertype trigger;
748 if ( alarm->hasTime() ) { 748 if ( alarm->hasTime() ) {
749 trigger.time = writeICalDateTime(alarm->time()); 749 trigger.time = writeICalDateTime(alarm->time());
750 trigger.duration = icaldurationtype_null_duration(); 750 trigger.duration = icaldurationtype_null_duration();
751 } else { 751 } else {
752 trigger.time = icaltime_null_time(); 752 trigger.time = icaltime_null_time();
753 Duration offset; 753 Duration offset;
754 if ( alarm->hasStartOffset() ) 754 if ( alarm->hasStartOffset() )
755 offset = alarm->startOffset(); 755 offset = alarm->startOffset();
756 else 756 else
757 offset = alarm->endOffset(); 757 offset = alarm->endOffset();
758 trigger.duration = icaldurationtype_from_int( offset.asSeconds() ); 758 trigger.duration = icaldurationtype_from_int( offset.asSeconds() );
759 } 759 }
760 icalproperty *p = icalproperty_new_trigger(trigger); 760 icalproperty *p = icalproperty_new_trigger(trigger);
761 if ( alarm->hasEndOffset() ) 761 if ( alarm->hasEndOffset() )
762 icalproperty_add_parameter(p,icalparameter_new_related(ICAL_RELATED_END)); 762 icalproperty_add_parameter(p,icalparameter_new_related(ICAL_RELATED_END));
763 icalcomponent_add_property(a,p); 763 icalcomponent_add_property(a,p);
764 764
765 // Repeat count and duration 765 // Repeat count and duration
766 if (alarm->repeatCount()) { 766 if (alarm->repeatCount()) {
767 icalcomponent_add_property(a,icalproperty_new_repeat(alarm->repeatCount())); 767 icalcomponent_add_property(a,icalproperty_new_repeat(alarm->repeatCount()));
768 icalcomponent_add_property(a,icalproperty_new_duration( 768 icalcomponent_add_property(a,icalproperty_new_duration(
769 icaldurationtype_from_int(alarm->snoozeTime()*60))); 769 icaldurationtype_from_int(alarm->snoozeTime()*60)));
770 } 770 }
771 771
772 // Custom properties 772 // Custom properties
773 QMap<QCString, QString> custom = alarm->customProperties(); 773 QMap<QCString, QString> custom = alarm->customProperties();
774 for (QMap<QCString, QString>::Iterator c = custom.begin(); c != custom.end(); ++c) { 774 for (QMap<QCString, QString>::Iterator c = custom.begin(); c != custom.end(); ++c) {
775 icalproperty *p = icalproperty_new_x(c.data().utf8()); 775 icalproperty *p = icalproperty_new_x(c.data().utf8());
776 icalproperty_set_x_name(p,c.key()); 776 icalproperty_set_x_name(p,c.key());
777 icalcomponent_add_property(a,p); 777 icalcomponent_add_property(a,p);
778 } 778 }
779 779
780 return a; 780 return a;
781} 781}
782 782
783Todo *ICalFormatImpl::readTodo(icalcomponent *vtodo) 783Todo *ICalFormatImpl::readTodo(icalcomponent *vtodo)
784{ 784{
785 Todo *todo = new Todo; 785 Todo *todo = new Todo;
786 786
787 readIncidence(vtodo,todo); 787 readIncidence(vtodo,todo);
788 788
789 icalproperty *p = icalcomponent_get_first_property(vtodo,ICAL_ANY_PROPERTY); 789 icalproperty *p = icalcomponent_get_first_property(vtodo,ICAL_ANY_PROPERTY);
790 790
791// int intvalue; 791// int intvalue;
792 icaltimetype icaltime; 792 icaltimetype icaltime;
793 793
794 QStringList categories; 794 QStringList categories;
795 795
796 while (p) { 796 while (p) {
797 icalproperty_kind kind = icalproperty_isa(p); 797 icalproperty_kind kind = icalproperty_isa(p);
798 switch (kind) { 798 switch (kind) {
799 799
800 case ICAL_DUE_PROPERTY: // due date 800 case ICAL_DUE_PROPERTY: // due date
801 icaltime = icalproperty_get_due(p); 801 icaltime = icalproperty_get_due(p);
802 if (icaltime.is_date) { 802 if (icaltime.is_date) {
803 todo->setDtDue(QDateTime(readICalDate(icaltime),QTime(0,0,0))); 803 todo->setDtDue(QDateTime(readICalDate(icaltime),QTime(0,0,0)));
804 todo->setFloats(true); 804 todo->setFloats(true);
805 805
806 } else { 806 } else {
807 todo->setDtDue(readICalDateTime(icaltime)); 807 todo->setDtDue(readICalDateTime(icaltime));
808 todo->setFloats(false); 808 todo->setFloats(false);
809 } 809 }
810 todo->setHasDueDate(true); 810 todo->setHasDueDate(true);
811 break; 811 break;
812 812
813 case ICAL_COMPLETED_PROPERTY: // completion date 813 case ICAL_COMPLETED_PROPERTY: // completion date
814 icaltime = icalproperty_get_completed(p); 814 icaltime = icalproperty_get_completed(p);
815 todo->setCompleted(readICalDateTime(icaltime)); 815 todo->setCompleted(readICalDateTime(icaltime));
816 break; 816 break;
817 817
818 case ICAL_PERCENTCOMPLETE_PROPERTY: // Percent completed 818 case ICAL_PERCENTCOMPLETE_PROPERTY: // Percent completed
819 todo->setPercentComplete(icalproperty_get_percentcomplete(p)); 819 todo->setPercentComplete(icalproperty_get_percentcomplete(p));
820 break; 820 break;
821 821
822 case ICAL_RELATEDTO_PROPERTY: // related todo (parent) 822 case ICAL_RELATEDTO_PROPERTY: // related todo (parent)
823 todo->setRelatedToUid(QString::fromUtf8(icalproperty_get_relatedto(p))); 823 todo->setRelatedToUid(QString::fromUtf8(icalproperty_get_relatedto(p)));
824 mTodosRelate.append(todo); 824 mTodosRelate.append(todo);
825 break; 825 break;
826 826
827 case ICAL_DTSTART_PROPERTY: 827 case ICAL_DTSTART_PROPERTY:
828 // Flag that todo has start date. Value is read in by readIncidence(). 828 // Flag that todo has start date. Value is read in by readIncidence().
829 todo->setHasStartDate(true); 829 todo->setHasStartDate(true);
830 break; 830 break;
831 831
832 default: 832 default:
833// kdDebug(5800) << "ICALFormat::readTodo(): Unknown property: " << kind 833// kdDebug(5800) << "ICALFormat::readTodo(): Unknown property: " << kind
834// << endl; 834// << endl;
835 break; 835 break;
836 } 836 }
837 837
838 p = icalcomponent_get_next_property(vtodo,ICAL_ANY_PROPERTY); 838 p = icalcomponent_get_next_property(vtodo,ICAL_ANY_PROPERTY);
839 } 839 }
840 840
841 return todo; 841 return todo;
842} 842}
843 843
844Event *ICalFormatImpl::readEvent(icalcomponent *vevent) 844Event *ICalFormatImpl::readEvent(icalcomponent *vevent)
845{ 845{
846 Event *event = new Event; 846 Event *event = new Event;
847 event->setFloats(false); 847 event->setFloats(false);
848 848
849 readIncidence(vevent,event); 849 readIncidence(vevent,event);
850 850
851 icalproperty *p = icalcomponent_get_first_property(vevent,ICAL_ANY_PROPERTY); 851 icalproperty *p = icalcomponent_get_first_property(vevent,ICAL_ANY_PROPERTY);
852 852
853// int intvalue; 853// int intvalue;
854 icaltimetype icaltime; 854 icaltimetype icaltime;
855 855
856 QStringList categories; 856 QStringList categories;
857 QString transparency; 857 QString transparency;
858 858
859 while (p) { 859 while (p) {
860 icalproperty_kind kind = icalproperty_isa(p); 860 icalproperty_kind kind = icalproperty_isa(p);
861 switch (kind) { 861 switch (kind) {
862 862
863 case ICAL_DTEND_PROPERTY: // start date and time 863 case ICAL_DTEND_PROPERTY: // start date and time
864 icaltime = icalproperty_get_dtend(p); 864 icaltime = icalproperty_get_dtend(p);
865 if (icaltime.is_date) { 865 if (icaltime.is_date) {
866 event->setFloats( true ); 866 event->setFloats( true );
867 // End date is non-inclusive 867 // End date is non-inclusive
868 QDate endDate = readICalDate( icaltime ).addDays( -1 ); 868 QDate endDate = readICalDate( icaltime ).addDays( -1 );
869 mCompat->fixFloatingEnd( endDate ); 869 mCompat->fixFloatingEnd( endDate );
870 if ( endDate < event->dtStart().date() ) { 870 if ( endDate < event->dtStart().date() ) {
871 endDate = event->dtStart().date(); 871 endDate = event->dtStart().date();
872 } 872 }
873 event->setDtEnd( QDateTime( endDate, QTime( 0, 0, 0 ) ) ); 873 event->setDtEnd( QDateTime( endDate, QTime( 0, 0, 0 ) ) );
874 } else { 874 } else {
875 event->setDtEnd(readICalDateTime(icaltime)); 875 event->setDtEnd(readICalDateTime(icaltime));
876 } 876 }
877 break; 877 break;
878 878
879// TODO: 879// TODO:
880 // at this point, there should be at least a start or end time. 880 // at this point, there should be at least a start or end time.
881 // fix up for events that take up no time but have a time associated 881 // fix up for events that take up no time but have a time associated
882#if 0 882#if 0
883 if (!(vo = isAPropertyOf(vevent, VCDTstartProp))) 883 if (!(vo = isAPropertyOf(vevent, VCDTstartProp)))
884 anEvent->setDtStart(anEvent->dtEnd()); 884 anEvent->setDtStart(anEvent->dtEnd());
885 if (!(vo = isAPropertyOf(vevent, VCDTendProp))) 885 if (!(vo = isAPropertyOf(vevent, VCDTendProp)))
886 anEvent->setDtEnd(anEvent->dtStart()); 886 anEvent->setDtEnd(anEvent->dtStart());
887#endif 887#endif
888 888
889// TODO: exdates 889// TODO: exdates
890#if 0 890#if 0
891 // recurrence exceptions 891 // recurrence exceptions
892 if ((vo = isAPropertyOf(vevent, VCExDateProp)) != 0) { 892 if ((vo = isAPropertyOf(vevent, VCExDateProp)) != 0) {
893 anEvent->setExDates(s = fakeCString(vObjectUStringZValue(vo))); 893 anEvent->setExDates(s = fakeCString(vObjectUStringZValue(vo)));
894 deleteStr(s); 894 deleteStr(s);
895 } 895 }
896#endif 896#endif
897 897
898#if 0 898#if 0
899 // secrecy 899 // secrecy
900 if ((vo = isAPropertyOf(vevent, VCClassProp)) != 0) { 900 if ((vo = isAPropertyOf(vevent, VCClassProp)) != 0) {
901 anEvent->setSecrecy(s = fakeCString(vObjectUStringZValue(vo))); 901 anEvent->setSecrecy(s = fakeCString(vObjectUStringZValue(vo)));
902 deleteStr(s); 902 deleteStr(s);
903 } 903 }
904 else 904 else
905 anEvent->setSecrecy("PUBLIC"); 905 anEvent->setSecrecy("PUBLIC");
906 906
907 // attachments 907 // attachments
908 tmpStrList.clear(); 908 tmpStrList.clear();
909 initPropIterator(&voi, vevent); 909 initPropIterator(&voi, vevent);
910 while (moreIteration(&voi)) { 910 while (moreIteration(&voi)) {
911 vo = nextVObject(&voi); 911 vo = nextVObject(&voi);
912 if (strcmp(vObjectName(vo), VCAttachProp) == 0) { 912 if (strcmp(vObjectName(vo), VCAttachProp) == 0) {
913 tmpStrList.append(s = fakeCString(vObjectUStringZValue(vo))); 913 tmpStrList.append(s = fakeCString(vObjectUStringZValue(vo)));
914 deleteStr(s); 914 deleteStr(s);
915 } 915 }
916 } 916 }
917 anEvent->setAttachments(tmpStrList); 917 anEvent->setAttachments(tmpStrList);
918 918
919 // resources 919 // resources
920 if ((vo = isAPropertyOf(vevent, VCResourcesProp)) != 0) { 920 if ((vo = isAPropertyOf(vevent, VCResourcesProp)) != 0) {
921 QString resources = (s = fakeCString(vObjectUStringZValue(vo))); 921 QString resources = (s = fakeCString(vObjectUStringZValue(vo)));
922 deleteStr(s); 922 deleteStr(s);
923 tmpStrList.clear(); 923 tmpStrList.clear();
924 index1 = 0; 924 index1 = 0;
925 index2 = 0; 925 index2 = 0;
926 QString resource; 926 QString resource;
927 while ((index2 = resources.find(';', index1)) != -1) { 927 while ((index2 = resources.find(';', index1)) != -1) {
928 resource = resources.mid(index1, (index2 - index1)); 928 resource = resources.mid(index1, (index2 - index1));
929 tmpStrList.append(resource); 929 tmpStrList.append(resource);
930 index1 = index2; 930 index1 = index2;
931 } 931 }
932 anEvent->setResources(tmpStrList); 932 anEvent->setResources(tmpStrList);
933 } 933 }
934#endif 934#endif
935 935
936 case ICAL_RELATEDTO_PROPERTY: // releated event (parent) 936 case ICAL_RELATEDTO_PROPERTY: // releated event (parent)
937 event->setRelatedToUid(QString::fromUtf8(icalproperty_get_relatedto(p))); 937 event->setRelatedToUid(QString::fromUtf8(icalproperty_get_relatedto(p)));
938 mEventsRelate.append(event); 938 mEventsRelate.append(event);
939 break; 939 break;
940 940
941 case ICAL_TRANSP_PROPERTY: // Transparency 941 case ICAL_TRANSP_PROPERTY: // Transparency
942 if(icalproperty_get_transp(p) == ICAL_TRANSP_TRANSPARENT ) 942 if(icalproperty_get_transp(p) == ICAL_TRANSP_TRANSPARENT )
943 event->setTransparency( Event::Transparent ); 943 event->setTransparency( Event::Transparent );
944 else 944 else
945 event->setTransparency( Event::Opaque ); 945 event->setTransparency( Event::Opaque );
946 break; 946 break;
947 947
948 default: 948 default:
949// kdDebug(5800) << "ICALFormat::readEvent(): Unknown property: " << kind 949// kdDebug(5800) << "ICALFormat::readEvent(): Unknown property: " << kind
950// << endl; 950// << endl;
951 break; 951 break;
952 } 952 }
953 953
954 p = icalcomponent_get_next_property(vevent,ICAL_ANY_PROPERTY); 954 p = icalcomponent_get_next_property(vevent,ICAL_ANY_PROPERTY);
955 } 955 }
956 956
957 QString msade = event->nonKDECustomProperty("X-MICROSOFT-CDO-ALLDAYEVENT"); 957 QString msade = event->nonKDECustomProperty("X-MICROSOFT-CDO-ALLDAYEVENT");
958 if (!msade.isNull()) { 958 if (!msade.isNull()) {
959 bool floats = (msade == QString::fromLatin1("TRUE")); 959 bool floats = (msade == QString::fromLatin1("TRUE"));
960 kdDebug(5800) << "ICALFormat::readEvent(): all day event: " << floats << endl; 960 kdDebug(5800) << "ICALFormat::readEvent(): all day event: " << floats << endl;
961 event->setFloats(floats); 961 event->setFloats(floats);
962 if (floats) { 962 if (floats) {
963 QDateTime endDate = event->dtEnd(); 963 QDateTime endDate = event->dtEnd();
964 event->setDtEnd(endDate.addDays(-1)); 964 event->setDtEnd(endDate.addDays(-1));
965 } 965 }
966 } 966 }
967 967
968 // some stupid vCal exporters ignore the standard and use Description 968 // some stupid vCal exporters ignore the standard and use Description
969 // instead of Summary for the default field. Correct for this. 969 // instead of Summary for the default field. Correct for this.
970 if (event->summary().isEmpty() && 970 if (event->summary().isEmpty() &&
971 !(event->description().isEmpty())) { 971 !(event->description().isEmpty())) {
972 QString tmpStr = event->description().simplifyWhiteSpace(); 972 QString tmpStr = event->description().simplifyWhiteSpace();
973 event->setDescription(""); 973 event->setDescription("");
974 event->setSummary(tmpStr); 974 event->setSummary(tmpStr);
975 } 975 }
976 976
977 return event; 977 return event;
978} 978}
979 979
980FreeBusy *ICalFormatImpl::readFreeBusy(icalcomponent *vfreebusy) 980FreeBusy *ICalFormatImpl::readFreeBusy(icalcomponent *vfreebusy)
981{ 981{
982 FreeBusy *freebusy = new FreeBusy; 982 FreeBusy *freebusy = new FreeBusy;
983 983
984 readIncidenceBase(vfreebusy,freebusy); 984 readIncidenceBase(vfreebusy,freebusy);
985 985
986 icalproperty *p = icalcomponent_get_first_property(vfreebusy,ICAL_ANY_PROPERTY); 986 icalproperty *p = icalcomponent_get_first_property(vfreebusy,ICAL_ANY_PROPERTY);
987 987
988 icaltimetype icaltime; 988 icaltimetype icaltime;
989 icalperiodtype icalperiod; 989 icalperiodtype icalperiod;
990 QDateTime period_start, period_end; 990 QDateTime period_start, period_end;
991 991
992 while (p) { 992 while (p) {
993 icalproperty_kind kind = icalproperty_isa(p); 993 icalproperty_kind kind = icalproperty_isa(p);
994 switch (kind) { 994 switch (kind) {
995 995
996 case ICAL_DTSTART_PROPERTY: // start date and time 996 case ICAL_DTSTART_PROPERTY: // start date and time
997 icaltime = icalproperty_get_dtstart(p); 997 icaltime = icalproperty_get_dtstart(p);
998 freebusy->setDtStart(readICalDateTime(icaltime)); 998 freebusy->setDtStart(readICalDateTime(icaltime));
999 break; 999 break;
1000 1000
1001 case ICAL_DTEND_PROPERTY: // start End Date and Time 1001 case ICAL_DTEND_PROPERTY: // start End Date and Time
1002 icaltime = icalproperty_get_dtend(p); 1002 icaltime = icalproperty_get_dtend(p);
1003 freebusy->setDtEnd(readICalDateTime(icaltime)); 1003 freebusy->setDtEnd(readICalDateTime(icaltime));
1004 break; 1004 break;
1005 1005
1006 case ICAL_FREEBUSY_PROPERTY: //Any FreeBusy Times 1006 case ICAL_FREEBUSY_PROPERTY: //Any FreeBusy Times
1007 icalperiod = icalproperty_get_freebusy(p); 1007 icalperiod = icalproperty_get_freebusy(p);
1008 period_start = readICalDateTime(icalperiod.start); 1008 period_start = readICalDateTime(icalperiod.start);
1009 period_end = readICalDateTime(icalperiod.end); 1009 period_end = readICalDateTime(icalperiod.end);
1010 freebusy->addPeriod(period_start, period_end); 1010 freebusy->addPeriod(period_start, period_end);
1011 break; 1011 break;
1012 1012
1013 default: 1013 default:
1014 kdDebug(5800) << "ICALFormat::readIncidence(): Unknown property: " << kind 1014 kdDebug(5800) << "ICALFormat::readIncidence(): Unknown property: " << kind
1015 << endl; 1015 << endl;
1016 break; 1016 break;
1017 } 1017 }
1018 p = icalcomponent_get_next_property(vfreebusy,ICAL_ANY_PROPERTY); 1018 p = icalcomponent_get_next_property(vfreebusy,ICAL_ANY_PROPERTY);
1019 } 1019 }
1020 1020
1021 return freebusy; 1021 return freebusy;
1022} 1022}
1023 1023
1024Journal *ICalFormatImpl::readJournal(icalcomponent *vjournal) 1024Journal *ICalFormatImpl::readJournal(icalcomponent *vjournal)
1025{ 1025{
1026 Journal *journal = new Journal; 1026 Journal *journal = new Journal;
1027 1027
1028 readIncidence(vjournal,journal); 1028 readIncidence(vjournal,journal);
1029 1029
1030 return journal; 1030 return journal;
1031} 1031}
1032 1032
1033Attendee *ICalFormatImpl::readAttendee(icalproperty *attendee) 1033Attendee *ICalFormatImpl::readAttendee(icalproperty *attendee)
1034{ 1034{
1035 icalparameter *p = 0; 1035 icalparameter *p = 0;
1036 1036
1037 QString email = QString::fromUtf8(icalproperty_get_attendee(attendee)); 1037 QString email = QString::fromUtf8(icalproperty_get_attendee(attendee));
1038 1038
1039 QString name; 1039 QString name;
1040 QString uid = QString::null; 1040 QString uid = QString::null;
1041 p = icalproperty_get_first_parameter(attendee,ICAL_CN_PARAMETER); 1041 p = icalproperty_get_first_parameter(attendee,ICAL_CN_PARAMETER);
1042 if (p) { 1042 if (p) {
1043 name = QString::fromUtf8(icalparameter_get_cn(p)); 1043 name = QString::fromUtf8(icalparameter_get_cn(p));
1044 } else { 1044 } else {
1045 } 1045 }
1046 1046
1047 bool rsvp=false; 1047 bool rsvp=false;
1048 p = icalproperty_get_first_parameter(attendee,ICAL_RSVP_PARAMETER); 1048 p = icalproperty_get_first_parameter(attendee,ICAL_RSVP_PARAMETER);
1049 if (p) { 1049 if (p) {
1050 icalparameter_rsvp rsvpParameter = icalparameter_get_rsvp(p); 1050 icalparameter_rsvp rsvpParameter = icalparameter_get_rsvp(p);
1051 if (rsvpParameter == ICAL_RSVP_TRUE) rsvp = true; 1051 if (rsvpParameter == ICAL_RSVP_TRUE) rsvp = true;
1052 } 1052 }
1053 1053
1054 Attendee::PartStat status = Attendee::NeedsAction; 1054 Attendee::PartStat status = Attendee::NeedsAction;
1055 p = icalproperty_get_first_parameter(attendee,ICAL_PARTSTAT_PARAMETER); 1055 p = icalproperty_get_first_parameter(attendee,ICAL_PARTSTAT_PARAMETER);
1056 if (p) { 1056 if (p) {
1057 icalparameter_partstat partStatParameter = icalparameter_get_partstat(p); 1057 icalparameter_partstat partStatParameter = icalparameter_get_partstat(p);
1058 switch(partStatParameter) { 1058 switch(partStatParameter) {
1059 default: 1059 default:
1060 case ICAL_PARTSTAT_NEEDSACTION: 1060 case ICAL_PARTSTAT_NEEDSACTION:
1061 status = Attendee::NeedsAction; 1061 status = Attendee::NeedsAction;
1062 break; 1062 break;
1063 case ICAL_PARTSTAT_ACCEPTED: 1063 case ICAL_PARTSTAT_ACCEPTED:
1064 status = Attendee::Accepted; 1064 status = Attendee::Accepted;
1065 break; 1065 break;
1066 case ICAL_PARTSTAT_DECLINED: 1066 case ICAL_PARTSTAT_DECLINED:
1067 status = Attendee::Declined; 1067 status = Attendee::Declined;
1068 break; 1068 break;
1069 case ICAL_PARTSTAT_TENTATIVE: 1069 case ICAL_PARTSTAT_TENTATIVE:
1070 status = Attendee::Tentative; 1070 status = Attendee::Tentative;
1071 break; 1071 break;
1072 case ICAL_PARTSTAT_DELEGATED: 1072 case ICAL_PARTSTAT_DELEGATED:
1073 status = Attendee::Delegated; 1073 status = Attendee::Delegated;
1074 break; 1074 break;
1075 case ICAL_PARTSTAT_COMPLETED: 1075 case ICAL_PARTSTAT_COMPLETED:
1076 status = Attendee::Completed; 1076 status = Attendee::Completed;
1077 break; 1077 break;
1078 case ICAL_PARTSTAT_INPROCESS: 1078 case ICAL_PARTSTAT_INPROCESS:
1079 status = Attendee::InProcess; 1079 status = Attendee::InProcess;
1080 break; 1080 break;
1081 } 1081 }
1082 } 1082 }
1083 1083
1084 Attendee::Role role = Attendee::ReqParticipant; 1084 Attendee::Role role = Attendee::ReqParticipant;
1085 p = icalproperty_get_first_parameter(attendee,ICAL_ROLE_PARAMETER); 1085 p = icalproperty_get_first_parameter(attendee,ICAL_ROLE_PARAMETER);
1086 if (p) { 1086 if (p) {
1087 icalparameter_role roleParameter = icalparameter_get_role(p); 1087 icalparameter_role roleParameter = icalparameter_get_role(p);
1088 switch(roleParameter) { 1088 switch(roleParameter) {
1089 case ICAL_ROLE_CHAIR: 1089 case ICAL_ROLE_CHAIR:
1090 role = Attendee::Chair; 1090 role = Attendee::Chair;
1091 break; 1091 break;
1092 default: 1092 default:
1093 case ICAL_ROLE_REQPARTICIPANT: 1093 case ICAL_ROLE_REQPARTICIPANT:
1094 role = Attendee::ReqParticipant; 1094 role = Attendee::ReqParticipant;
1095 break; 1095 break;
1096 case ICAL_ROLE_OPTPARTICIPANT: 1096 case ICAL_ROLE_OPTPARTICIPANT:
1097 role = Attendee::OptParticipant; 1097 role = Attendee::OptParticipant;
1098 break; 1098 break;
1099 case ICAL_ROLE_NONPARTICIPANT: 1099 case ICAL_ROLE_NONPARTICIPANT:
1100 role = Attendee::NonParticipant; 1100 role = Attendee::NonParticipant;
1101 break; 1101 break;
1102 } 1102 }
1103 } 1103 }
1104 1104
1105 p = icalproperty_get_first_parameter(attendee,ICAL_X_PARAMETER); 1105 p = icalproperty_get_first_parameter(attendee,ICAL_X_PARAMETER);
1106 uid = icalparameter_get_xvalue(p); 1106 uid = icalparameter_get_xvalue(p);
1107 // This should be added, but there seems to be a libical bug here. 1107 // This should be added, but there seems to be a libical bug here.
1108 /*while (p) { 1108 /*while (p) {
1109 // if (icalparameter_get_xname(p) == "X-UID") { 1109 // if (icalparameter_get_xname(p) == "X-UID") {
1110 uid = icalparameter_get_xvalue(p); 1110 uid = icalparameter_get_xvalue(p);
1111 p = icalproperty_get_next_parameter(attendee,ICAL_X_PARAMETER); 1111 p = icalproperty_get_next_parameter(attendee,ICAL_X_PARAMETER);
1112 } */ 1112 } */
1113 1113
1114 return new Attendee( name, email, rsvp, status, role, uid ); 1114 return new Attendee( name, email, rsvp, status, role, uid );
1115} 1115}
1116 1116
1117Attachment *ICalFormatImpl::readAttachment(icalproperty *attach) 1117Attachment *ICalFormatImpl::readAttachment(icalproperty *attach)
1118{ 1118{
1119 icalattach *a = icalproperty_get_attach(attach); 1119 icalattach *a = icalproperty_get_attach(attach);
1120 icalparameter_value v = ICAL_VALUE_NONE; 1120 icalparameter_value v = ICAL_VALUE_NONE;
1121 icalparameter_encoding e = ICAL_ENCODING_NONE; 1121 icalparameter_encoding e = ICAL_ENCODING_NONE;
1122 1122
1123 Attachment *attachment = 0; 1123 Attachment *attachment = 0;
1124 /* 1124 /*
1125 icalparameter *vp = icalproperty_get_first_parameter(attach, ICAL_VALUE_PARAMETER); 1125 icalparameter *vp = icalproperty_get_first_parameter(attach, ICAL_VALUE_PARAMETER);
1126 if (vp) 1126 if (vp)
1127 v = icalparameter_get_value(vp); 1127 v = icalparameter_get_value(vp);
1128 1128
1129 icalparameter *ep = icalproperty_get_first_parameter(attach, ICAL_ENCODING_PARAMETER); 1129 icalparameter *ep = icalproperty_get_first_parameter(attach, ICAL_ENCODING_PARAMETER);
1130 if (ep) 1130 if (ep)
1131 e = icalparameter_get_encoding(ep); 1131 e = icalparameter_get_encoding(ep);
1132 */ 1132 */
1133 int isurl = icalattach_get_is_url (a); 1133 int isurl = icalattach_get_is_url (a);
1134 if (isurl == 0) 1134 if (isurl == 0)
1135 attachment = new Attachment((const char*)icalattach_get_data(a)); 1135 attachment = new Attachment((const char*)icalattach_get_data(a));
1136 else { 1136 else {
1137 attachment = new Attachment(QString(icalattach_get_url(a))); 1137 attachment = new Attachment(QString(icalattach_get_url(a)));
1138 } 1138 }
1139 1139
1140 icalparameter *p = icalproperty_get_first_parameter(attach, ICAL_FMTTYPE_PARAMETER); 1140 icalparameter *p = icalproperty_get_first_parameter(attach, ICAL_FMTTYPE_PARAMETER);
1141 if (p) 1141 if (p)
1142 attachment->setMimeType(QString(icalparameter_get_fmttype(p))); 1142 attachment->setMimeType(QString(icalparameter_get_fmttype(p)));
1143 1143
1144 return attachment; 1144 return attachment;
1145} 1145}
1146#include <qtextcodec.h> 1146#include <qtextcodec.h>
1147void ICalFormatImpl::readIncidence(icalcomponent *parent,Incidence *incidence) 1147void ICalFormatImpl::readIncidence(icalcomponent *parent,Incidence *incidence)
1148{ 1148{
1149 readIncidenceBase(parent,incidence); 1149 readIncidenceBase(parent,incidence);
1150 1150
1151 icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY); 1151 icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY);
1152 bool readrec = false; 1152 bool readrec = false;
1153 const char *text; 1153 const char *text;
1154 int intvalue; 1154 int intvalue;
1155 icaltimetype icaltime; 1155 icaltimetype icaltime;
1156 icaldurationtype icalduration; 1156 icaldurationtype icalduration;
1157 struct icalrecurrencetype rectype; 1157 struct icalrecurrencetype rectype;
1158 QStringList categories; 1158 QStringList categories;
1159 1159
1160 while (p) { 1160 while (p) {
1161 icalproperty_kind kind = icalproperty_isa(p); 1161 icalproperty_kind kind = icalproperty_isa(p);
1162 switch (kind) { 1162 switch (kind) {
1163 1163
1164 case ICAL_CREATED_PROPERTY: 1164 case ICAL_CREATED_PROPERTY:
1165 icaltime = icalproperty_get_created(p); 1165 icaltime = icalproperty_get_created(p);
1166 incidence->setCreated(readICalDateTime(icaltime)); 1166 incidence->setCreated(readICalDateTime(icaltime));
1167 break; 1167 break;
1168 1168
1169 case ICAL_SEQUENCE_PROPERTY: // sequence 1169 case ICAL_SEQUENCE_PROPERTY: // sequence
1170 intvalue = icalproperty_get_sequence(p); 1170 intvalue = icalproperty_get_sequence(p);
1171 incidence->setRevision(intvalue); 1171 incidence->setRevision(intvalue);
1172 break; 1172 break;
1173 1173
1174 case ICAL_LASTMODIFIED_PROPERTY: // last modification date 1174 case ICAL_LASTMODIFIED_PROPERTY: // last modification date
1175 icaltime = icalproperty_get_lastmodified(p); 1175 icaltime = icalproperty_get_lastmodified(p);
1176 incidence->setLastModified(readICalDateTime(icaltime)); 1176 incidence->setLastModified(readICalDateTime(icaltime));
1177 break; 1177 break;
1178 1178
1179 case ICAL_DTSTART_PROPERTY: // start date and time 1179 case ICAL_DTSTART_PROPERTY: // start date and time
1180 icaltime = icalproperty_get_dtstart(p); 1180 icaltime = icalproperty_get_dtstart(p);
1181 if (icaltime.is_date) { 1181 if (icaltime.is_date) {
1182 incidence->setDtStart(QDateTime(readICalDate(icaltime),QTime(0,0,0))); 1182 incidence->setDtStart(QDateTime(readICalDate(icaltime),QTime(0,0,0)));
1183 incidence->setFloats(true); 1183 incidence->setFloats(true);
1184 } else { 1184 } else {
1185 incidence->setDtStart(readICalDateTime(icaltime)); 1185 incidence->setDtStart(readICalDateTime(icaltime));
1186 } 1186 }
1187 break; 1187 break;
1188 1188
1189 case ICAL_DURATION_PROPERTY: // start date and time 1189 case ICAL_DURATION_PROPERTY: // start date and time
1190 icalduration = icalproperty_get_duration(p); 1190 icalduration = icalproperty_get_duration(p);
1191 incidence->setDuration(readICalDuration(icalduration)); 1191 incidence->setDuration(readICalDuration(icalduration));
1192 break; 1192 break;
1193 1193
1194 case ICAL_DESCRIPTION_PROPERTY: // description 1194 case ICAL_DESCRIPTION_PROPERTY: // description
1195 text = icalproperty_get_description(p); 1195 text = icalproperty_get_description(p);
1196 incidence->setDescription(QString::fromUtf8(text)); 1196 incidence->setDescription(QString::fromUtf8(text));
1197 break; 1197 break;
1198 1198
1199 case ICAL_SUMMARY_PROPERTY: // summary 1199 case ICAL_SUMMARY_PROPERTY: // summary
1200 { 1200 {
1201 text = icalproperty_get_summary(p); 1201 text = icalproperty_get_summary(p);
1202 incidence->setSummary(QString::fromUtf8(text)); 1202 incidence->setSummary(QString::fromUtf8(text));
1203 } 1203 }
1204 break; 1204 break;
1205 case ICAL_STATUS_PROPERTY: // summary 1205 case ICAL_STATUS_PROPERTY: // summary
1206 { 1206 {
1207 if ( ICAL_STATUS_CANCELLED == icalproperty_get_status(p) ) 1207 if ( ICAL_STATUS_CANCELLED == icalproperty_get_status(p) )
1208 incidence->setCancelled( true ); 1208 incidence->setCancelled( true );
1209 } 1209 }
1210 break; 1210 break;
1211 1211
1212 case ICAL_LOCATION_PROPERTY: // location 1212 case ICAL_LOCATION_PROPERTY: // location
1213 text = icalproperty_get_location(p); 1213 text = icalproperty_get_location(p);
1214 incidence->setLocation(QString::fromUtf8(text)); 1214 incidence->setLocation(QString::fromUtf8(text));
1215 break; 1215 break;
1216 1216
1217#if 0 1217#if 0
1218 // status 1218 // status
1219 if ((vo = isAPropertyOf(vincidence, VCStatusProp)) != 0) { 1219 if ((vo = isAPropertyOf(vincidence, VCStatusProp)) != 0) {
1220 incidence->setStatus(s = fakeCString(vObjectUStringZValue(vo))); 1220 incidence->setStatus(s = fakeCString(vObjectUStringZValue(vo)));
1221 deleteStr(s); 1221 deleteStr(s);
1222 } 1222 }
1223 else 1223 else
1224 incidence->setStatus("NEEDS ACTION"); 1224 incidence->setStatus("NEEDS ACTION");
1225#endif 1225#endif
1226 1226
1227 case ICAL_PRIORITY_PROPERTY: // priority 1227 case ICAL_PRIORITY_PROPERTY: // priority
1228 intvalue = icalproperty_get_priority(p); 1228 intvalue = icalproperty_get_priority(p);
1229 incidence->setPriority(intvalue); 1229 incidence->setPriority(intvalue);
1230 break; 1230 break;
1231 1231
1232 case ICAL_CATEGORIES_PROPERTY: // categories 1232 case ICAL_CATEGORIES_PROPERTY: // categories
1233 text = icalproperty_get_categories(p); 1233 text = icalproperty_get_categories(p);
1234 categories.append(QString::fromUtf8(text)); 1234 categories.append(QString::fromUtf8(text));
1235 break; 1235 break;
1236 //******************************************* 1236 //*******************************************
1237 case ICAL_RRULE_PROPERTY: 1237 case ICAL_RRULE_PROPERTY:
1238 // we do need (maybe )start datetime of incidence for recurrence 1238 // we do need (maybe )start datetime of incidence for recurrence
1239 // such that we can read recurrence only after we read incidence completely 1239 // such that we can read recurrence only after we read incidence completely
1240 readrec = true; 1240 readrec = true;
1241 rectype = icalproperty_get_rrule(p); 1241 rectype = icalproperty_get_rrule(p);
1242 break; 1242 break;
1243 1243
1244 case ICAL_EXDATE_PROPERTY: 1244 case ICAL_EXDATE_PROPERTY:
1245 icaltime = icalproperty_get_exdate(p); 1245 icaltime = icalproperty_get_exdate(p);
1246 incidence->addExDate(readICalDate(icaltime)); 1246 incidence->addExDate(readICalDate(icaltime));
1247 break; 1247 break;
1248 1248
1249 case ICAL_CLASS_PROPERTY: { 1249 case ICAL_CLASS_PROPERTY: {
1250 int inttext = icalproperty_get_class(p); 1250 int inttext = icalproperty_get_class(p);
1251 if (inttext == ICAL_CLASS_PUBLIC ) { 1251 if (inttext == ICAL_CLASS_PUBLIC ) {
1252 incidence->setSecrecy(Incidence::SecrecyPublic); 1252 incidence->setSecrecy(Incidence::SecrecyPublic);
1253 } else if (inttext == ICAL_CLASS_CONFIDENTIAL ) { 1253 } else if (inttext == ICAL_CLASS_CONFIDENTIAL ) {
1254 incidence->setSecrecy(Incidence::SecrecyConfidential); 1254 incidence->setSecrecy(Incidence::SecrecyConfidential);
1255 } else { 1255 } else {
1256 incidence->setSecrecy(Incidence::SecrecyPrivate); 1256 incidence->setSecrecy(Incidence::SecrecyPrivate);
1257 } 1257 }
1258 } 1258 }
1259 break; 1259 break;
1260 1260
1261 case ICAL_ATTACH_PROPERTY: // attachments 1261 case ICAL_ATTACH_PROPERTY: // attachments
1262 incidence->addAttachment(readAttachment(p)); 1262 incidence->addAttachment(readAttachment(p));
1263 break; 1263 break;
1264 1264
1265 default: 1265 default:
1266// kdDebug(5800) << "ICALFormat::readIncidence(): Unknown property: " << kind 1266// kdDebug(5800) << "ICALFormat::readIncidence(): Unknown property: " << kind
1267// << endl; 1267// << endl;
1268 break; 1268 break;
1269 } 1269 }
1270 1270
1271 p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY); 1271 p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY);
1272 } 1272 }
1273 if ( readrec ) { 1273 if ( readrec ) {
1274 readRecurrenceRule(rectype,incidence); 1274 readRecurrenceRule(rectype,incidence);
1275 } 1275 }
1276 // kpilot stuff 1276 // kpilot stuff
1277// TODO: move this application-specific code to kpilot 1277// TODO: move this application-specific code to kpilot
1278 QString kp = incidence->nonKDECustomProperty("X-PILOTID"); 1278 QString kp = incidence->nonKDECustomProperty("X-PILOTID");
1279 if (!kp.isNull()) { 1279 if (!kp.isNull()) {
1280 incidence->setPilotId(kp.toInt()); 1280 incidence->setPilotId(kp.toInt());
1281 } 1281 }
1282 kp = incidence->nonKDECustomProperty("X-PILOTSTAT"); 1282 kp = incidence->nonKDECustomProperty("X-PILOTSTAT");
1283 if (!kp.isNull()) { 1283 if (!kp.isNull()) {
1284 incidence->setSyncStatus(kp.toInt()); 1284 incidence->setSyncStatus(kp.toInt());
1285 } 1285 }
1286 kp = incidence->nonKDECustomProperty("X-ZAURUSID"); 1286 kp = incidence->nonKDECustomProperty("X-ZAURUSID");
1287 if (!kp.isNull()) { 1287 if (!kp.isNull()) {
1288 incidence->setZaurusId(kp.toInt()); 1288 incidence->setZaurusId(kp.toInt());
1289 } 1289 }
1290 1290
1291 kp = incidence->nonKDECustomProperty("X-ZAURUSUID"); 1291 kp = incidence->nonKDECustomProperty("X-ZAURUSUID");
1292 if (!kp.isNull()) { 1292 if (!kp.isNull()) {
1293 incidence->setZaurusUid(kp.toInt()); 1293 incidence->setZaurusUid(kp.toInt());
1294 } 1294 }
1295 1295
1296 kp = incidence->nonKDECustomProperty("X-ZAURUSSTAT"); 1296 kp = incidence->nonKDECustomProperty("X-ZAURUSSTAT");
1297 if (!kp.isNull()) { 1297 if (!kp.isNull()) {
1298 incidence->setZaurusStat(kp.toInt()); 1298 incidence->setZaurusStat(kp.toInt());
1299 } 1299 }
1300 1300
1301 // Cancel backwards compatibility mode for subsequent changes by the application 1301 // Cancel backwards compatibility mode for subsequent changes by the application
1302 incidence->recurrence()->setCompatVersion(); 1302 incidence->recurrence()->setCompatVersion();
1303 1303
1304 // add categories 1304 // add categories
1305 incidence->setCategories(categories); 1305 incidence->setCategories(categories);
1306 1306
1307 // iterate through all alarms 1307 // iterate through all alarms
1308 for (icalcomponent *alarm = icalcomponent_get_first_component(parent,ICAL_VALARM_COMPONENT); 1308 for (icalcomponent *alarm = icalcomponent_get_first_component(parent,ICAL_VALARM_COMPONENT);
1309 alarm; 1309 alarm;
1310 alarm = icalcomponent_get_next_component(parent,ICAL_VALARM_COMPONENT)) { 1310 alarm = icalcomponent_get_next_component(parent,ICAL_VALARM_COMPONENT)) {
1311 readAlarm(alarm,incidence); 1311 readAlarm(alarm,incidence);
1312 } 1312 }
1313} 1313}
1314 1314
1315void ICalFormatImpl::readIncidenceBase(icalcomponent *parent,IncidenceBase *incidenceBase) 1315void ICalFormatImpl::readIncidenceBase(icalcomponent *parent,IncidenceBase *incidenceBase)
1316{ 1316{
1317 icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY); 1317 icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY);
1318 1318
1319 while (p) { 1319 while (p) {
1320 icalproperty_kind kind = icalproperty_isa(p); 1320 icalproperty_kind kind = icalproperty_isa(p);
1321 switch (kind) { 1321 switch (kind) {
1322 1322
1323 case ICAL_UID_PROPERTY: // unique id 1323 case ICAL_UID_PROPERTY: // unique id
1324 incidenceBase->setUid(QString::fromUtf8(icalproperty_get_uid(p))); 1324 incidenceBase->setUid(QString::fromUtf8(icalproperty_get_uid(p)));
1325 break; 1325 break;
1326 1326
1327 case ICAL_ORGANIZER_PROPERTY: // organizer 1327 case ICAL_ORGANIZER_PROPERTY: // organizer
1328 incidenceBase->setOrganizer(QString::fromUtf8(icalproperty_get_organizer(p))); 1328 incidenceBase->setOrganizer(QString::fromUtf8(icalproperty_get_organizer(p)));
1329 break; 1329 break;
1330 1330
1331 case ICAL_ATTENDEE_PROPERTY: // attendee 1331 case ICAL_ATTENDEE_PROPERTY: // attendee
1332 incidenceBase->addAttendee(readAttendee(p)); 1332 incidenceBase->addAttendee(readAttendee(p));
1333 break; 1333 break;
1334 1334
1335 default: 1335 default:
1336 break; 1336 break;
1337 } 1337 }
1338 1338
1339 p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY); 1339 p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY);
1340 } 1340 }
1341 1341
1342 // custom properties 1342 // custom properties
1343 readCustomProperties(parent, incidenceBase); 1343 readCustomProperties(parent, incidenceBase);
1344} 1344}
1345 1345
1346void ICalFormatImpl::readCustomProperties(icalcomponent *parent,CustomProperties *properties) 1346void ICalFormatImpl::readCustomProperties(icalcomponent *parent,CustomProperties *properties)
1347{ 1347{
1348 QMap<QCString, QString> customProperties; 1348 QMap<QCString, QString> customProperties;
1349 1349
1350 icalproperty *p = icalcomponent_get_first_property(parent,ICAL_X_PROPERTY); 1350 icalproperty *p = icalcomponent_get_first_property(parent,ICAL_X_PROPERTY);
1351 1351
1352 while (p) { 1352 while (p) {
1353 QString value = QString::fromUtf8(icalproperty_get_x(p)); 1353 QString value = QString::fromUtf8(icalproperty_get_x(p));
1354 customProperties[icalproperty_get_x_name(p)] = value; 1354 customProperties[icalproperty_get_x_name(p)] = value;
1355 //qDebug("ICalFormatImpl::readCustomProperties %s %s",value.latin1(), icalproperty_get_x_name(p) ); 1355 //qDebug("ICalFormatImpl::readCustomProperties %s %s",value.latin1(), icalproperty_get_x_name(p) );
1356 1356
1357 p = icalcomponent_get_next_property(parent,ICAL_X_PROPERTY); 1357 p = icalcomponent_get_next_property(parent,ICAL_X_PROPERTY);
1358 } 1358 }
1359 1359
1360 properties->setCustomProperties(customProperties); 1360 properties->setCustomProperties(customProperties);
1361} 1361}
1362 1362
1363void ICalFormatImpl::readRecurrenceRule(struct icalrecurrencetype rrule,Incidence *incidence) 1363void ICalFormatImpl::readRecurrenceRule(struct icalrecurrencetype rrule,Incidence *incidence)
1364{ 1364{
1365// kdDebug(5800) << "Read recurrence for " << incidence->summary() << endl; 1365// kdDebug(5800) << "Read recurrence for " << incidence->summary() << endl;
1366 1366
1367 Recurrence *recur = incidence->recurrence(); 1367 Recurrence *recur = incidence->recurrence();
1368 recur->setCompatVersion(mCalendarVersion); 1368 recur->setCompatVersion(mCalendarVersion);
1369 recur->unsetRecurs(); 1369 recur->unsetRecurs();
1370 1370
1371 struct icalrecurrencetype r = rrule; 1371 struct icalrecurrencetype r = rrule;
1372 1372
1373 dumpIcalRecurrence(r); 1373 dumpIcalRecurrence(r);
1374 readRecurrence( r, recur, incidence); 1374 readRecurrence( r, recur, incidence);
1375} 1375}
1376 1376
1377void ICalFormatImpl::readRecurrence( const struct icalrecurrencetype &r, Recurrence* recur, Incidence *incidence) 1377void ICalFormatImpl::readRecurrence( const struct icalrecurrencetype &r, Recurrence* recur, Incidence *incidence)
1378{ 1378{
1379 int wkst; 1379 int wkst;
1380 int index = 0; 1380 int index = 0;
1381 short day = 0; 1381 short day = 0;
1382 QBitArray qba(7); 1382 QBitArray qba(7);
1383 int frequ = r.freq; 1383 int frequ = r.freq;
1384 int interv = r.interval; 1384 int interv = r.interval;
1385 // preprocessing for odd recurrence definitions 1385 // preprocessing for odd recurrence definitions
1386 1386
1387 if ( r.freq == ICAL_MONTHLY_RECURRENCE ) { 1387 if ( r.freq == ICAL_MONTHLY_RECURRENCE ) {
1388 if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) { 1388 if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) {
1389 interv = 12; 1389 interv = 12;
1390 } 1390 }
1391 } 1391 }
1392 if ( r.freq == ICAL_YEARLY_RECURRENCE ) { 1392 if ( r.freq == ICAL_YEARLY_RECURRENCE ) {
1393 if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX && r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX ) { 1393 if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX && r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX ) {
1394 frequ = ICAL_MONTHLY_RECURRENCE; 1394 frequ = ICAL_MONTHLY_RECURRENCE;
1395 interv = 12; 1395 interv = 12* r.interval;
1396 } 1396 }
1397 } 1397 }
1398 1398
1399 switch (frequ) { 1399 switch (frequ) {
1400 case ICAL_MINUTELY_RECURRENCE: 1400 case ICAL_MINUTELY_RECURRENCE:
1401 if (!icaltime_is_null_time(r.until)) { 1401 if (!icaltime_is_null_time(r.until)) {
1402 recur->setMinutely(interv,readICalDateTime(r.until)); 1402 recur->setMinutely(interv,readICalDateTime(r.until));
1403 } else { 1403 } else {
1404 if (r.count == 0) 1404 if (r.count == 0)
1405 recur->setMinutely(interv,-1); 1405 recur->setMinutely(interv,-1);
1406 else 1406 else
1407 recur->setMinutely(interv,r.count); 1407 recur->setMinutely(interv,r.count);
1408 } 1408 }
1409 break; 1409 break;
1410 case ICAL_HOURLY_RECURRENCE: 1410 case ICAL_HOURLY_RECURRENCE:
1411 if (!icaltime_is_null_time(r.until)) { 1411 if (!icaltime_is_null_time(r.until)) {
1412 recur->setHourly(interv,readICalDateTime(r.until)); 1412 recur->setHourly(interv,readICalDateTime(r.until));
1413 } else { 1413 } else {
1414 if (r.count == 0) 1414 if (r.count == 0)
1415 recur->setHourly(interv,-1); 1415 recur->setHourly(interv,-1);
1416 else 1416 else
1417 recur->setHourly(interv,r.count); 1417 recur->setHourly(interv,r.count);
1418 } 1418 }
1419 break; 1419 break;
1420 case ICAL_DAILY_RECURRENCE: 1420 case ICAL_DAILY_RECURRENCE:
1421 if (!icaltime_is_null_time(r.until)) { 1421 if (!icaltime_is_null_time(r.until)) {
1422 recur->setDaily(interv,readICalDate(r.until)); 1422 recur->setDaily(interv,readICalDate(r.until));
1423 } else { 1423 } else {
1424 if (r.count == 0) 1424 if (r.count == 0)
1425 recur->setDaily(interv,-1); 1425 recur->setDaily(interv,-1);
1426 else 1426 else
1427 recur->setDaily(interv,r.count); 1427 recur->setDaily(interv,r.count);
1428 } 1428 }
1429 break; 1429 break;
1430 case ICAL_WEEKLY_RECURRENCE: 1430 case ICAL_WEEKLY_RECURRENCE:
1431 // kdDebug(5800) << "WEEKLY_RECURRENCE" << endl; 1431 // kdDebug(5800) << "WEEKLY_RECURRENCE" << endl;
1432 wkst = (r.week_start + 5)%7 + 1; 1432 wkst = (r.week_start + 5)%7 + 1;
1433 if (!icaltime_is_null_time(r.until)) { 1433 if (!icaltime_is_null_time(r.until)) {
1434 recur->setWeekly(interv,qba,readICalDate(r.until),wkst); 1434 recur->setWeekly(interv,qba,readICalDate(r.until),wkst);
1435 } else { 1435 } else {
1436 if (r.count == 0) 1436 if (r.count == 0)
1437 recur->setWeekly(interv,qba,-1,wkst); 1437 recur->setWeekly(interv,qba,-1,wkst);
1438 else 1438 else
1439 recur->setWeekly(interv,qba,r.count,wkst); 1439 recur->setWeekly(interv,qba,r.count,wkst);
1440 } 1440 }
1441 if ( r.by_day[0] == ICAL_RECURRENCE_ARRAY_MAX) { 1441 if ( r.by_day[0] == ICAL_RECURRENCE_ARRAY_MAX) {
1442 int wday = incidence->dtStart().date().dayOfWeek ()-1; 1442 int wday = incidence->dtStart().date().dayOfWeek ()-1;
1443 //qDebug("weekly error found "); 1443 //qDebug("weekly error found ");
1444 qba.setBit(wday); 1444 qba.setBit(wday);
1445 } else { 1445 } else {
1446 while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 1446 while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
1447 // kdDebug(5800) << " " << day << endl; 1447 // kdDebug(5800) << " " << day << endl;
1448 qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 1448 qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
1449 } 1449 }
1450 } 1450 }
1451 break; 1451 break;
1452 case ICAL_MONTHLY_RECURRENCE: 1452 case ICAL_MONTHLY_RECURRENCE:
1453 1453
1454 if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { 1454 if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
1455 if (!icaltime_is_null_time(r.until)) { 1455 if (!icaltime_is_null_time(r.until)) {
1456 recur->setMonthly(Recurrence::rMonthlyPos,interv, 1456 recur->setMonthly(Recurrence::rMonthlyPos,interv,
1457 readICalDate(r.until)); 1457 readICalDate(r.until));
1458 } else { 1458 } else {
1459 if (r.count == 0) 1459 if (r.count == 0)
1460 recur->setMonthly(Recurrence::rMonthlyPos,interv,-1); 1460 recur->setMonthly(Recurrence::rMonthlyPos,interv,-1);
1461 else 1461 else
1462 recur->setMonthly(Recurrence::rMonthlyPos,interv,r.count); 1462 recur->setMonthly(Recurrence::rMonthlyPos,interv,r.count);
1463 } 1463 }
1464 bool useSetPos = false; 1464 bool useSetPos = false;
1465 short pos = 0; 1465 short pos = 0;
1466 while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 1466 while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
1467 // kdDebug(5800) << "----a " << index << ": " << day << endl; 1467 // kdDebug(5800) << "----a " << index << ": " << day << endl;
1468 pos = icalrecurrencetype_day_position(day); 1468 pos = icalrecurrencetype_day_position(day);
1469 if (pos) { 1469 if (pos) {
1470 day = icalrecurrencetype_day_day_of_week(day); 1470 day = icalrecurrencetype_day_day_of_week(day);
1471 QBitArray ba(7); // don't wipe qba 1471 QBitArray ba(7); // don't wipe qba
1472 ba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 1472 ba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
1473 recur->addMonthlyPos(pos,ba); 1473 recur->addMonthlyPos(pos,ba);
1474 } else { 1474 } else {
1475 qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 1475 qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
1476 useSetPos = true; 1476 useSetPos = true;
1477 } 1477 }
1478 } 1478 }
1479 if (useSetPos) { 1479 if (useSetPos) {
1480 if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) { 1480 if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) {
1481 recur->addMonthlyPos(r.by_set_pos[0],qba); 1481 recur->addMonthlyPos(r.by_set_pos[0],qba);
1482 } 1482 }
1483 } 1483 }
1484 } else if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { 1484 } else if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
1485 if (!icaltime_is_null_time(r.until)) { 1485 if (!icaltime_is_null_time(r.until)) {
1486 recur->setMonthly(Recurrence::rMonthlyDay,interv, 1486 recur->setMonthly(Recurrence::rMonthlyDay,interv,
1487 readICalDate(r.until)); 1487 readICalDate(r.until));
1488 } else { 1488 } else {
1489 if (r.count == 0) 1489 if (r.count == 0)
1490 recur->setMonthly(Recurrence::rMonthlyDay,interv,-1); 1490 recur->setMonthly(Recurrence::rMonthlyDay,interv,-1);
1491 else 1491 else
1492 recur->setMonthly(Recurrence::rMonthlyDay,interv,r.count); 1492 recur->setMonthly(Recurrence::rMonthlyDay,interv,r.count);
1493 } 1493 }
1494 while((day = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 1494 while((day = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
1495 // kdDebug(5800) << "----b " << day << endl; 1495 // kdDebug(5800) << "----b " << day << endl;
1496 recur->addMonthlyDay(day); 1496 recur->addMonthlyDay(day);
1497 } 1497 }
1498 } 1498 }
1499 break; 1499 break;
1500 case ICAL_YEARLY_RECURRENCE: 1500 case ICAL_YEARLY_RECURRENCE:
1501 if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { 1501 if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
1502 qDebug(" YEARLY DAY OF YEAR");
1502 if (!icaltime_is_null_time(r.until)) { 1503 if (!icaltime_is_null_time(r.until)) {
1503 recur->setYearly(Recurrence::rYearlyDay,interv, 1504 recur->setYearly(Recurrence::rYearlyDay,interv,
1504 readICalDate(r.until)); 1505 readICalDate(r.until));
1505 } else { 1506 } else {
1506 if (r.count == 0) 1507 if (r.count == 0)
1507 recur->setYearly(Recurrence::rYearlyDay,interv,-1); 1508 recur->setYearly(Recurrence::rYearlyDay,interv,-1);
1508 else 1509 else
1509 recur->setYearly(Recurrence::rYearlyDay,interv,r.count); 1510 recur->setYearly(Recurrence::rYearlyDay,interv,r.count);
1510 } 1511 }
1511 while((day = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 1512 while((day = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
1512 recur->addYearlyNum(day); 1513 recur->addYearlyNum(day);
1513 } 1514 }
1514 } else if ( true /*r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX*/) { 1515 } else if ( true /*r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX*/) {
1515 if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { 1516 if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
1517 qDebug("YEARLY POS NOT SUPPORTED BY GUI");
1516 if (!icaltime_is_null_time(r.until)) { 1518 if (!icaltime_is_null_time(r.until)) {
1517 recur->setYearly(Recurrence::rYearlyPos,interv, 1519 recur->setYearly(Recurrence::rYearlyPos,interv,
1518 readICalDate(r.until)); 1520 readICalDate(r.until));
1519 } else { 1521 } else {
1520 if (r.count == 0) 1522 if (r.count == 0)
1521 recur->setYearly(Recurrence::rYearlyPos,interv,-1); 1523 recur->setYearly(Recurrence::rYearlyPos,interv,-1);
1522 else 1524 else
1523 recur->setYearly(Recurrence::rYearlyPos,interv,r.count); 1525 recur->setYearly(Recurrence::rYearlyPos,interv,r.count);
1524 } 1526 }
1525 bool useSetPos = false; 1527 bool useSetPos = false;
1526 short pos = 0; 1528 short pos = 0;
1527 while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 1529 while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
1528 // kdDebug(5800) << "----a " << index << ": " << day << endl; 1530 // kdDebug(5800) << "----a " << index << ": " << day << endl;
1529 pos = icalrecurrencetype_day_position(day); 1531 pos = icalrecurrencetype_day_position(day);
1530 if (pos) { 1532 if (pos) {
1531 day = icalrecurrencetype_day_day_of_week(day); 1533 day = icalrecurrencetype_day_day_of_week(day);
1532 QBitArray ba(7); // don't wipe qba 1534 QBitArray ba(7); // don't wipe qba
1533 ba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 1535 ba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
1534 recur->addYearlyMonthPos(pos,ba); 1536 recur->addYearlyMonthPos(pos,ba);
1535 } else { 1537 } else {
1536 qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 1538 qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0
1537 useSetPos = true; 1539 useSetPos = true;
1538 } 1540 }
1539 } 1541 }
1540 if (useSetPos) { 1542 if (useSetPos) {
1541 if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) { 1543 if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) {
1542 recur->addYearlyMonthPos(r.by_set_pos[0],qba); 1544 recur->addYearlyMonthPos(r.by_set_pos[0],qba);
1543 } 1545 }
1544 } 1546 }
1545 } else { 1547 } else {
1548 qDebug("YEARLY MONTH ");
1546 if (!icaltime_is_null_time(r.until)) { 1549 if (!icaltime_is_null_time(r.until)) {
1547 recur->setYearly(Recurrence::rYearlyMonth,interv, 1550 recur->setYearly(Recurrence::rYearlyMonth,interv,
1548 readICalDate(r.until)); 1551 readICalDate(r.until));
1549 } else { 1552 } else {
1550 if (r.count == 0) 1553 if (r.count == 0)
1551 recur->setYearly(Recurrence::rYearlyMonth,interv,-1); 1554 recur->setYearly(Recurrence::rYearlyMonth,interv,-1);
1552 else 1555 else
1553 recur->setYearly(Recurrence::rYearlyMonth,interv,r.count); 1556 recur->setYearly(Recurrence::rYearlyMonth,interv,r.count);
1554 } 1557 }
1555 } 1558 if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX ) {
1556 if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX ) { 1559 index = 0;
1557 index = 0; 1560 while((day = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
1558 while((day = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 1561 recur->addYearlyNum(day);
1559 recur->addYearlyNum(day); 1562 }
1563 } else {
1564 recur->addYearlyNum(incidence->dtStart().date().month());
1560 } 1565 }
1561 } else {
1562 recur->addYearlyNum(incidence->dtStart().date().month());
1563 } 1566 }
1567
1564 } 1568 }
1565 break; 1569 break;
1566 default: 1570 default:
1567 ; 1571 ;
1568 break; 1572 break;
1569 } 1573 }
1570} 1574}
1571 1575
1572void ICalFormatImpl::readAlarm(icalcomponent *alarm,Incidence *incidence) 1576void ICalFormatImpl::readAlarm(icalcomponent *alarm,Incidence *incidence)
1573{ 1577{
1574 //kdDebug(5800) << "Read alarm for " << incidence->summary() << endl; 1578 //kdDebug(5800) << "Read alarm for " << incidence->summary() << endl;
1575 1579
1576 Alarm* ialarm = incidence->newAlarm(); 1580 Alarm* ialarm = incidence->newAlarm();
1577 ialarm->setRepeatCount(0); 1581 ialarm->setRepeatCount(0);
1578 ialarm->setEnabled(true); 1582 ialarm->setEnabled(true);
1579 1583
1580 // Determine the alarm's action type 1584 // Determine the alarm's action type
1581 icalproperty *p = icalcomponent_get_first_property(alarm,ICAL_ACTION_PROPERTY); 1585 icalproperty *p = icalcomponent_get_first_property(alarm,ICAL_ACTION_PROPERTY);
1582 if ( !p ) { 1586 if ( !p ) {
1583 return; 1587 return;
1584 } 1588 }
1585 1589
1586 icalproperty_action action = icalproperty_get_action(p); 1590 icalproperty_action action = icalproperty_get_action(p);
1587 Alarm::Type type = Alarm::Display; 1591 Alarm::Type type = Alarm::Display;
1588 switch ( action ) { 1592 switch ( action ) {
1589 case ICAL_ACTION_DISPLAY: type = Alarm::Display; break; 1593 case ICAL_ACTION_DISPLAY: type = Alarm::Display; break;
1590 case ICAL_ACTION_AUDIO: type = Alarm::Audio; break; 1594 case ICAL_ACTION_AUDIO: type = Alarm::Audio; break;
1591 case ICAL_ACTION_PROCEDURE: type = Alarm::Procedure; break; 1595 case ICAL_ACTION_PROCEDURE: type = Alarm::Procedure; break;
1592 case ICAL_ACTION_EMAIL: type = Alarm::Email; break; 1596 case ICAL_ACTION_EMAIL: type = Alarm::Email; break;
1593 default: 1597 default:
1594 ; 1598 ;
1595 return; 1599 return;
1596 } 1600 }
1597 ialarm->setType(type); 1601 ialarm->setType(type);
1598 1602
1599 p = icalcomponent_get_first_property(alarm,ICAL_ANY_PROPERTY); 1603 p = icalcomponent_get_first_property(alarm,ICAL_ANY_PROPERTY);
1600 while (p) { 1604 while (p) {
1601 icalproperty_kind kind = icalproperty_isa(p); 1605 icalproperty_kind kind = icalproperty_isa(p);
1602 1606
1603 switch (kind) { 1607 switch (kind) {
1604 case ICAL_TRIGGER_PROPERTY: { 1608 case ICAL_TRIGGER_PROPERTY: {
1605 icaltriggertype trigger = icalproperty_get_trigger(p); 1609 icaltriggertype trigger = icalproperty_get_trigger(p);
1606 if (icaltime_is_null_time(trigger.time)) { 1610 if (icaltime_is_null_time(trigger.time)) {
1607 if (icaldurationtype_is_null_duration(trigger.duration)) { 1611 if (icaldurationtype_is_null_duration(trigger.duration)) {
1608 kdDebug(5800) << "ICalFormatImpl::readAlarm(): Trigger has no time and no duration." << endl; 1612 kdDebug(5800) << "ICalFormatImpl::readAlarm(): Trigger has no time and no duration." << endl;
1609 } else { 1613 } else {
1610 Duration duration = icaldurationtype_as_int( trigger.duration ); 1614 Duration duration = icaldurationtype_as_int( trigger.duration );
1611 icalparameter *param = icalproperty_get_first_parameter(p,ICAL_RELATED_PARAMETER); 1615 icalparameter *param = icalproperty_get_first_parameter(p,ICAL_RELATED_PARAMETER);
1612 if (param && icalparameter_get_related(param) == ICAL_RELATED_END) 1616 if (param && icalparameter_get_related(param) == ICAL_RELATED_END)
1613 ialarm->setEndOffset(duration); 1617 ialarm->setEndOffset(duration);
1614 else 1618 else
1615 ialarm->setStartOffset(duration); 1619 ialarm->setStartOffset(duration);
1616 } 1620 }
1617 } else { 1621 } else {
1618 ialarm->setTime(readICalDateTime(trigger.time)); 1622 ialarm->setTime(readICalDateTime(trigger.time));
1619 } 1623 }
1620 break; 1624 break;
1621 } 1625 }
1622 case ICAL_DURATION_PROPERTY: { 1626 case ICAL_DURATION_PROPERTY: {
1623 icaldurationtype duration = icalproperty_get_duration(p); 1627 icaldurationtype duration = icalproperty_get_duration(p);
1624 ialarm->setSnoozeTime(icaldurationtype_as_int(duration)/60); 1628 ialarm->setSnoozeTime(icaldurationtype_as_int(duration)/60);
1625 break; 1629 break;
1626 } 1630 }
1627 case ICAL_REPEAT_PROPERTY: 1631 case ICAL_REPEAT_PROPERTY:
1628 ialarm->setRepeatCount(icalproperty_get_repeat(p)); 1632 ialarm->setRepeatCount(icalproperty_get_repeat(p));
1629 break; 1633 break;
1630 1634
1631 // Only in DISPLAY and EMAIL and PROCEDURE alarms 1635 // Only in DISPLAY and EMAIL and PROCEDURE alarms
1632 case ICAL_DESCRIPTION_PROPERTY: { 1636 case ICAL_DESCRIPTION_PROPERTY: {
1633 QString description = QString::fromUtf8(icalproperty_get_description(p)); 1637 QString description = QString::fromUtf8(icalproperty_get_description(p));
1634 switch ( action ) { 1638 switch ( action ) {
1635 case ICAL_ACTION_DISPLAY: 1639 case ICAL_ACTION_DISPLAY:
1636 ialarm->setText( description ); 1640 ialarm->setText( description );
1637 break; 1641 break;
1638 case ICAL_ACTION_PROCEDURE: 1642 case ICAL_ACTION_PROCEDURE:
1639 ialarm->setProgramArguments( description ); 1643 ialarm->setProgramArguments( description );
1640 break; 1644 break;
1641 case ICAL_ACTION_EMAIL: 1645 case ICAL_ACTION_EMAIL:
1642 ialarm->setMailText( description ); 1646 ialarm->setMailText( description );
1643 break; 1647 break;
1644 default: 1648 default:
1645 break; 1649 break;
1646 } 1650 }
1647 break; 1651 break;
1648 } 1652 }
1649 // Only in EMAIL alarm 1653 // Only in EMAIL alarm
1650 case ICAL_SUMMARY_PROPERTY: 1654 case ICAL_SUMMARY_PROPERTY:
1651 ialarm->setMailSubject(QString::fromUtf8(icalproperty_get_summary(p))); 1655 ialarm->setMailSubject(QString::fromUtf8(icalproperty_get_summary(p)));
1652 break; 1656 break;
1653 1657
1654 // Only in EMAIL alarm 1658 // Only in EMAIL alarm
1655 case ICAL_ATTENDEE_PROPERTY: { 1659 case ICAL_ATTENDEE_PROPERTY: {
1656 QString email = QString::fromUtf8(icalproperty_get_attendee(p)); 1660 QString email = QString::fromUtf8(icalproperty_get_attendee(p));
1657 QString name; 1661 QString name;
1658 icalparameter *param = icalproperty_get_first_parameter(p,ICAL_CN_PARAMETER); 1662 icalparameter *param = icalproperty_get_first_parameter(p,ICAL_CN_PARAMETER);
1659 if (param) { 1663 if (param) {
1660 name = QString::fromUtf8(icalparameter_get_cn(param)); 1664 name = QString::fromUtf8(icalparameter_get_cn(param));
1661 } 1665 }
1662 ialarm->addMailAddress(Person(name, email)); 1666 ialarm->addMailAddress(Person(name, email));
1663 break; 1667 break;
1664 } 1668 }
1665 // Only in AUDIO and EMAIL and PROCEDURE alarms 1669 // Only in AUDIO and EMAIL and PROCEDURE alarms
1666 case ICAL_ATTACH_PROPERTY: { 1670 case ICAL_ATTACH_PROPERTY: {
1667 icalattach *attach = icalproperty_get_attach(p); 1671 icalattach *attach = icalproperty_get_attach(p);
1668 QString url = QFile::decodeName(icalattach_get_url(attach)); 1672 QString url = QFile::decodeName(icalattach_get_url(attach));
1669 switch ( action ) { 1673 switch ( action ) {
1670 case ICAL_ACTION_AUDIO: 1674 case ICAL_ACTION_AUDIO:
1671 ialarm->setAudioFile( url ); 1675 ialarm->setAudioFile( url );
1672 break; 1676 break;
1673 case ICAL_ACTION_PROCEDURE: 1677 case ICAL_ACTION_PROCEDURE:
1674 ialarm->setProgramFile( url ); 1678 ialarm->setProgramFile( url );
1675 break; 1679 break;
1676 case ICAL_ACTION_EMAIL: 1680 case ICAL_ACTION_EMAIL:
1677 ialarm->addMailAttachment( url ); 1681 ialarm->addMailAttachment( url );
1678 break; 1682 break;
1679 default: 1683 default:
1680 break; 1684 break;
1681 } 1685 }
1682 break; 1686 break;
1683 } 1687 }
1684 default: 1688 default:
1685 break; 1689 break;
1686 } 1690 }
1687 1691
1688 p = icalcomponent_get_next_property(alarm,ICAL_ANY_PROPERTY); 1692 p = icalcomponent_get_next_property(alarm,ICAL_ANY_PROPERTY);
1689 } 1693 }
1690 1694
1691 // custom properties 1695 // custom properties
1692 readCustomProperties(alarm, ialarm); 1696 readCustomProperties(alarm, ialarm);
1693 1697
1694 // TODO: check for consistency of alarm properties 1698 // TODO: check for consistency of alarm properties
1695} 1699}
1696 1700
1697icaltimetype ICalFormatImpl::writeICalDate(const QDate &date) 1701icaltimetype ICalFormatImpl::writeICalDate(const QDate &date)
1698{ 1702{
1699 icaltimetype t; 1703 icaltimetype t;
1700 1704
1701 t.year = date.year(); 1705 t.year = date.year();
1702 t.month = date.month(); 1706 t.month = date.month();
1703 t.day = date.day(); 1707 t.day = date.day();
1704 1708
1705 t.hour = 0; 1709 t.hour = 0;
1706 t.minute = 0; 1710 t.minute = 0;
1707 t.second = 0; 1711 t.second = 0;
1708 1712
1709 t.is_date = 1; 1713 t.is_date = 1;
1710 1714
1711 t.is_utc = 0; 1715 t.is_utc = 0;
1712 1716
1713 t.zone = 0; 1717 t.zone = 0;
1714 1718
1715 return t; 1719 return t;
1716} 1720}
1717 1721
1718icaltimetype ICalFormatImpl::writeICalDateTime(const QDateTime &dt ) 1722icaltimetype ICalFormatImpl::writeICalDateTime(const QDateTime &dt )
1719{ 1723{
1720 icaltimetype t; 1724 icaltimetype t;
1721 t.is_date = 0; 1725 t.is_date = 0;
1722 t.zone = 0; 1726 t.zone = 0;
1723 QDateTime datetime; 1727 QDateTime datetime;
1724 if ( mParent->utc() ) { 1728 if ( mParent->utc() ) {
1725 int offset = KGlobal::locale()->localTimeOffset( dt ); 1729 int offset = KGlobal::locale()->localTimeOffset( dt );
1726 datetime = dt.addSecs ( -offset*60); 1730 datetime = dt.addSecs ( -offset*60);
1727 t.is_utc = 1; 1731 t.is_utc = 1;
1728 } 1732 }
1729 else { 1733 else {
1730 datetime = dt; 1734 datetime = dt;
1731 t.is_utc = 0; 1735 t.is_utc = 0;
1732 1736
1733 } 1737 }
1734 t.year = datetime.date().year(); 1738 t.year = datetime.date().year();
1735 t.month = datetime.date().month(); 1739 t.month = datetime.date().month();
1736 t.day = datetime.date().day(); 1740 t.day = datetime.date().day();
1737 1741
1738 t.hour = datetime.time().hour(); 1742 t.hour = datetime.time().hour();
1739 t.minute = datetime.time().minute(); 1743 t.minute = datetime.time().minute();
1740 t.second = datetime.time().second(); 1744 t.second = datetime.time().second();
1741 1745
1742 //qDebug("*** time %s localtime %s ",dt .toString().latin1() ,datetime .toString().latin1() ); 1746 //qDebug("*** time %s localtime %s ",dt .toString().latin1() ,datetime .toString().latin1() );
1743 1747
1744// if ( mParent->utc() ) { 1748// if ( mParent->utc() ) {
1745// datetime = KGlobal::locale()->localTime( dt ); 1749// datetime = KGlobal::locale()->localTime( dt );
1746// qDebug("*** time %s localtime %s ",dt .toString().latin1() ,datetime .toString().latin1() ); 1750// qDebug("*** time %s localtime %s ",dt .toString().latin1() ,datetime .toString().latin1() );
1747// if (mParent->timeZoneId().isEmpty()) 1751// if (mParent->timeZoneId().isEmpty())
1748// t = icaltime_as_utc(t, 0); 1752// t = icaltime_as_utc(t, 0);
1749// else 1753// else
1750// t = icaltime_as_utc(t,mParent->timeZoneId().local8Bit()); 1754// t = icaltime_as_utc(t,mParent->timeZoneId().local8Bit());
1751// } 1755// }
1752 1756
1753 return t; 1757 return t;
1754} 1758}
1755 1759
1756QDateTime ICalFormatImpl::readICalDateTime(icaltimetype t) 1760QDateTime ICalFormatImpl::readICalDateTime(icaltimetype t)
1757{ 1761{
1758 QDateTime dt (QDate(t.year,t.month,t.day), 1762 QDateTime dt (QDate(t.year,t.month,t.day),
1759 QTime(t.hour,t.minute,t.second) ); 1763 QTime(t.hour,t.minute,t.second) );
1760 1764
1761 if (t.is_utc) { 1765 if (t.is_utc) {
1762 int offset = KGlobal::locale()->localTimeOffset( dt ); 1766 int offset = KGlobal::locale()->localTimeOffset( dt );
1763 dt = dt.addSecs ( offset*60); 1767 dt = dt.addSecs ( offset*60);
1764 } 1768 }
1765 1769
1766 return dt; 1770 return dt;
1767} 1771}
1768 1772
1769QDate ICalFormatImpl::readICalDate(icaltimetype t) 1773QDate ICalFormatImpl::readICalDate(icaltimetype t)
1770{ 1774{
1771 return QDate(t.year,t.month,t.day); 1775 return QDate(t.year,t.month,t.day);
1772} 1776}
1773 1777
1774icaldurationtype ICalFormatImpl::writeICalDuration(int seconds) 1778icaldurationtype ICalFormatImpl::writeICalDuration(int seconds)
1775{ 1779{
1776 icaldurationtype d; 1780 icaldurationtype d;
1777 1781
1778 d.weeks = seconds % gSecondsPerWeek; 1782 d.weeks = seconds % gSecondsPerWeek;
1779 seconds -= d.weeks * gSecondsPerWeek; 1783 seconds -= d.weeks * gSecondsPerWeek;
1780 d.days = seconds % gSecondsPerDay; 1784 d.days = seconds % gSecondsPerDay;
1781 seconds -= d.days * gSecondsPerDay; 1785 seconds -= d.days * gSecondsPerDay;
1782 d.hours = seconds % gSecondsPerHour; 1786 d.hours = seconds % gSecondsPerHour;
1783 seconds -= d.hours * gSecondsPerHour; 1787 seconds -= d.hours * gSecondsPerHour;
1784 d.minutes = seconds % gSecondsPerMinute; 1788 d.minutes = seconds % gSecondsPerMinute;
1785 seconds -= d.minutes * gSecondsPerMinute; 1789 seconds -= d.minutes * gSecondsPerMinute;
1786 d.seconds = seconds; 1790 d.seconds = seconds;
1787 d.is_neg = 0; 1791 d.is_neg = 0;
1788 1792
1789 return d; 1793 return d;
1790} 1794}
1791 1795
1792int ICalFormatImpl::readICalDuration(icaldurationtype d) 1796int ICalFormatImpl::readICalDuration(icaldurationtype d)
1793{ 1797{
1794 int result = 0; 1798 int result = 0;
1795 1799
1796 result += d.weeks * gSecondsPerWeek; 1800 result += d.weeks * gSecondsPerWeek;
1797 result += d.days * gSecondsPerDay; 1801 result += d.days * gSecondsPerDay;
1798 result += d.hours * gSecondsPerHour; 1802 result += d.hours * gSecondsPerHour;
1799 result += d.minutes * gSecondsPerMinute; 1803 result += d.minutes * gSecondsPerMinute;
1800 result += d.seconds; 1804 result += d.seconds;
1801 1805
1802 if (d.is_neg) result *= -1; 1806 if (d.is_neg) result *= -1;
1803 1807
1804 return result; 1808 return result;
1805} 1809}
1806 1810
1807icalcomponent *ICalFormatImpl::createCalendarComponent(Calendar *cal) 1811icalcomponent *ICalFormatImpl::createCalendarComponent(Calendar *cal)
1808{ 1812{
1809 icalcomponent *calendar; 1813 icalcomponent *calendar;
1810 1814
1811 // Root component 1815 // Root component
1812 calendar = icalcomponent_new(ICAL_VCALENDAR_COMPONENT); 1816 calendar = icalcomponent_new(ICAL_VCALENDAR_COMPONENT);
1813 1817
1814 icalproperty *p; 1818 icalproperty *p;
1815 1819
1816 // Product Identifier 1820 // Product Identifier
1817 p = icalproperty_new_prodid(CalFormat::productId().utf8()); 1821 p = icalproperty_new_prodid(CalFormat::productId().utf8());
1818 icalcomponent_add_property(calendar,p); 1822 icalcomponent_add_property(calendar,p);
1819 1823
1820 // TODO: Add time zone 1824 // TODO: Add time zone
1821 1825
1822 // iCalendar version (2.0) 1826 // iCalendar version (2.0)
1823 p = icalproperty_new_version(const_cast<char *>(_ICAL_VERSION)); 1827 p = icalproperty_new_version(const_cast<char *>(_ICAL_VERSION));
1824 icalcomponent_add_property(calendar,p); 1828 icalcomponent_add_property(calendar,p);
1825 1829
1826 // Custom properties 1830 // Custom properties
1827 if( cal != 0 ) 1831 if( cal != 0 )
1828 writeCustomProperties(calendar, cal); 1832 writeCustomProperties(calendar, cal);
1829 1833
1830 return calendar; 1834 return calendar;
1831} 1835}
1832 1836
1833 1837
1834 1838
1835// take a raw vcalendar (i.e. from a file on disk, clipboard, etc. etc. 1839// take a raw vcalendar (i.e. from a file on disk, clipboard, etc. etc.
1836// and break it down from its tree-like format into the dictionary format 1840// and break it down from its tree-like format into the dictionary format
1837// that is used internally in the ICalFormatImpl. 1841// that is used internally in the ICalFormatImpl.
1838bool ICalFormatImpl::populate( Calendar *cal, icalcomponent *calendar) 1842bool ICalFormatImpl::populate( Calendar *cal, icalcomponent *calendar)
1839{ 1843{
1840 // this function will populate the caldict dictionary and other event 1844 // this function will populate the caldict dictionary and other event
1841 // lists. It turns vevents into Events and then inserts them. 1845 // lists. It turns vevents into Events and then inserts them.
1842 1846
1843 if (!calendar) return false; 1847 if (!calendar) return false;
1844 1848
1845// TODO: check for METHOD 1849// TODO: check for METHOD
1846#if 0 1850#if 0
1847 if ((curVO = isAPropertyOf(vcal, ICMethodProp)) != 0) { 1851 if ((curVO = isAPropertyOf(vcal, ICMethodProp)) != 0) {
1848 char *methodType = 0; 1852 char *methodType = 0;
1849 methodType = fakeCString(vObjectUStringZValue(curVO)); 1853 methodType = fakeCString(vObjectUStringZValue(curVO));
1850 if (mEnableDialogs) 1854 if (mEnableDialogs)
1851 KMessageBox::information(mTopWidget, 1855 KMessageBox::information(mTopWidget,
1852 i18n("This calendar is an iTIP transaction of type \"%1\".") 1856 i18n("This calendar is an iTIP transaction of type \"%1\".")
1853 .arg(methodType), 1857 .arg(methodType),
1854 i18n("%1: iTIP Transaction").arg(CalFormat::application())); 1858 i18n("%1: iTIP Transaction").arg(CalFormat::application()));
1855 delete methodType; 1859 delete methodType;
1856 } 1860 }
1857#endif 1861#endif
1858 1862
1859 icalproperty *p; 1863 icalproperty *p;
1860 1864
1861 p = icalcomponent_get_first_property(calendar,ICAL_PRODID_PROPERTY); 1865 p = icalcomponent_get_first_property(calendar,ICAL_PRODID_PROPERTY);
1862 if (!p) { 1866 if (!p) {
1863// TODO: does no PRODID really matter? 1867// TODO: does no PRODID really matter?
1864// mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown)); 1868// mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
1865// return false; 1869// return false;
1866 mLoadedProductId = ""; 1870 mLoadedProductId = "";
1867 mCalendarVersion = 0; 1871 mCalendarVersion = 0;
1868 } else { 1872 } else {
1869 mLoadedProductId = QString::fromUtf8(icalproperty_get_prodid(p)); 1873 mLoadedProductId = QString::fromUtf8(icalproperty_get_prodid(p));
1870 mCalendarVersion = CalFormat::calendarVersion(mLoadedProductId); 1874 mCalendarVersion = CalFormat::calendarVersion(mLoadedProductId);
1871 1875
1872 delete mCompat; 1876 delete mCompat;
1873 mCompat = CompatFactory::createCompat( mLoadedProductId ); 1877 mCompat = CompatFactory::createCompat( mLoadedProductId );
1874 } 1878 }
1875 1879
1876// TODO: check for unknown PRODID 1880// TODO: check for unknown PRODID
1877#if 0 1881#if 0
1878 if (!mCalendarVersion 1882 if (!mCalendarVersion
1879 && CalFormat::productId() != mLoadedProductId) { 1883 && CalFormat::productId() != mLoadedProductId) {
1880 // warn the user that we might have trouble reading non-known calendar. 1884 // warn the user that we might have trouble reading non-known calendar.
1881 if (mEnableDialogs) 1885 if (mEnableDialogs)
1882 KMessageBox::information(mTopWidget, 1886 KMessageBox::information(mTopWidget,
1883 i18n("This vCalendar file was not created by KOrganizer " 1887 i18n("This vCalendar file was not created by KOrganizer "
1884 "or any other product we support. Loading anyway..."), 1888 "or any other product we support. Loading anyway..."),
1885 i18n("%1: Unknown vCalendar Vendor").arg(CalFormat::application())); 1889 i18n("%1: Unknown vCalendar Vendor").arg(CalFormat::application()));
1886 } 1890 }
1887#endif 1891#endif
1888 1892
1889 p = icalcomponent_get_first_property(calendar,ICAL_VERSION_PROPERTY); 1893 p = icalcomponent_get_first_property(calendar,ICAL_VERSION_PROPERTY);
1890 if (!p) { 1894 if (!p) {
1891 mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown)); 1895 mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
1892 return false; 1896 return false;
1893 } else { 1897 } else {
1894 const char *version = icalproperty_get_version(p); 1898 const char *version = icalproperty_get_version(p);
1895 1899
1896 if (strcmp(version,"1.0") == 0) { 1900 if (strcmp(version,"1.0") == 0) {
1897 mParent->setException(new ErrorFormat(ErrorFormat::CalVersion1, 1901 mParent->setException(new ErrorFormat(ErrorFormat::CalVersion1,
1898 i18n("Expected iCalendar format"))); 1902 i18n("Expected iCalendar format")));
1899 return false; 1903 return false;
1900 } else if (strcmp(version,"2.0") != 0) { 1904 } else if (strcmp(version,"2.0") != 0) {
1901 mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown)); 1905 mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
1902 return false; 1906 return false;
1903 } 1907 }
1904 } 1908 }
1905 1909
1906 1910
1907// TODO: check for calendar format version 1911// TODO: check for calendar format version
1908#if 0 1912#if 0
1909 // warn the user we might have trouble reading this unknown version. 1913 // warn the user we might have trouble reading this unknown version.
1910 if ((curVO = isAPropertyOf(vcal, VCVersionProp)) != 0) { 1914 if ((curVO = isAPropertyOf(vcal, VCVersionProp)) != 0) {
1911 char *s = fakeCString(vObjectUStringZValue(curVO)); 1915 char *s = fakeCString(vObjectUStringZValue(curVO));
1912 if (strcmp(_VCAL_VERSION, s) != 0) 1916 if (strcmp(_VCAL_VERSION, s) != 0)
1913 if (mEnableDialogs) 1917 if (mEnableDialogs)
1914 KMessageBox::sorry(mTopWidget, 1918 KMessageBox::sorry(mTopWidget,
1915 i18n("This vCalendar file has version %1.\n" 1919 i18n("This vCalendar file has version %1.\n"
1916 "We only support %2.") 1920 "We only support %2.")
1917 .arg(s).arg(_VCAL_VERSION), 1921 .arg(s).arg(_VCAL_VERSION),
1918 i18n("%1: Unknown vCalendar Version").arg(CalFormat::application())); 1922 i18n("%1: Unknown vCalendar Version").arg(CalFormat::application()));
1919 deleteStr(s); 1923 deleteStr(s);
1920 } 1924 }
1921#endif 1925#endif
1922 1926
1923 // custom properties 1927 // custom properties
1924 readCustomProperties(calendar, cal); 1928 readCustomProperties(calendar, cal);
1925 1929
1926// TODO: set time zone 1930// TODO: set time zone
1927#if 0 1931#if 0
1928 // set the time zone 1932 // set the time zone
1929 if ((curVO = isAPropertyOf(vcal, VCTimeZoneProp)) != 0) { 1933 if ((curVO = isAPropertyOf(vcal, VCTimeZoneProp)) != 0) {
1930 char *s = fakeCString(vObjectUStringZValue(curVO)); 1934 char *s = fakeCString(vObjectUStringZValue(curVO));
1931 cal->setTimeZone(s); 1935 cal->setTimeZone(s);
1932 deleteStr(s); 1936 deleteStr(s);
1933 } 1937 }
1934#endif 1938#endif
1935 1939
1936 // Store all events with a relatedTo property in a list for post-processing 1940 // Store all events with a relatedTo property in a list for post-processing
1937 mEventsRelate.clear(); 1941 mEventsRelate.clear();
1938 mTodosRelate.clear(); 1942 mTodosRelate.clear();
1939 // TODO: make sure that only actually added ecvens go to this lists. 1943 // TODO: make sure that only actually added ecvens go to this lists.
1940 1944
1941 icalcomponent *c; 1945 icalcomponent *c;
1942 1946
1943 // Iterate through all todos 1947 // Iterate through all todos
1944 c = icalcomponent_get_first_component(calendar,ICAL_VTODO_COMPONENT); 1948 c = icalcomponent_get_first_component(calendar,ICAL_VTODO_COMPONENT);
1945 while (c) { 1949 while (c) {
1946// kdDebug(5800) << "----Todo found" << endl; 1950// kdDebug(5800) << "----Todo found" << endl;
1947 Todo *todo = readTodo(c); 1951 Todo *todo = readTodo(c);
1948 if (!cal->todo(todo->uid())) cal->addTodo(todo); 1952 if (!cal->todo(todo->uid())) cal->addTodo(todo);
1949 c = icalcomponent_get_next_component(calendar,ICAL_VTODO_COMPONENT); 1953 c = icalcomponent_get_next_component(calendar,ICAL_VTODO_COMPONENT);
1950 } 1954 }
1951 1955
1952 // Iterate through all events 1956 // Iterate through all events
1953 c = icalcomponent_get_first_component(calendar,ICAL_VEVENT_COMPONENT); 1957 c = icalcomponent_get_first_component(calendar,ICAL_VEVENT_COMPONENT);
1954 while (c) { 1958 while (c) {
1955// kdDebug(5800) << "----Event found" << endl; 1959// kdDebug(5800) << "----Event found" << endl;
1956 Event *event = readEvent(c); 1960 Event *event = readEvent(c);
1957 if (!cal->event(event->uid())) cal->addEvent(event); 1961 if (!cal->event(event->uid())) cal->addEvent(event);
1958 c = icalcomponent_get_next_component(calendar,ICAL_VEVENT_COMPONENT); 1962 c = icalcomponent_get_next_component(calendar,ICAL_VEVENT_COMPONENT);
1959 } 1963 }
1960 1964
1961 // Iterate through all journals 1965 // Iterate through all journals
1962 c = icalcomponent_get_first_component(calendar,ICAL_VJOURNAL_COMPONENT); 1966 c = icalcomponent_get_first_component(calendar,ICAL_VJOURNAL_COMPONENT);
1963 while (c) { 1967 while (c) {
1964// kdDebug(5800) << "----Journal found" << endl; 1968// kdDebug(5800) << "----Journal found" << endl;
1965 Journal *journal = readJournal(c); 1969 Journal *journal = readJournal(c);
1966 if (!cal->journal(journal->uid())) cal->addJournal(journal); 1970 if (!cal->journal(journal->uid())) cal->addJournal(journal);
1967 c = icalcomponent_get_next_component(calendar,ICAL_VJOURNAL_COMPONENT); 1971 c = icalcomponent_get_next_component(calendar,ICAL_VJOURNAL_COMPONENT);
1968 } 1972 }
1969 1973
1970#if 0 1974#if 0
1971 initPropIterator(&i, vcal); 1975 initPropIterator(&i, vcal);
1972 1976
1973 // go through all the vobjects in the vcal 1977 // go through all the vobjects in the vcal
1974 while (moreIteration(&i)) { 1978 while (moreIteration(&i)) {
1975 curVO = nextVObject(&i); 1979 curVO = nextVObject(&i);
1976 1980
1977 /************************************************************************/ 1981 /************************************************************************/
1978 1982
1979 // now, check to see that the object is an event or todo. 1983 // now, check to see that the object is an event or todo.
1980 if (strcmp(vObjectName(curVO), VCEventProp) == 0) { 1984 if (strcmp(vObjectName(curVO), VCEventProp) == 0) {
1981 1985
1982 if ((curVOProp = isAPropertyOf(curVO, KPilotStatusProp)) != 0) { 1986 if ((curVOProp = isAPropertyOf(curVO, KPilotStatusProp)) != 0) {
1983 char *s; 1987 char *s;
1984 s = fakeCString(vObjectUStringZValue(curVOProp)); 1988 s = fakeCString(vObjectUStringZValue(curVOProp));
1985 // check to see if event was deleted by the kpilot conduit 1989 // check to see if event was deleted by the kpilot conduit
1986 if (atoi(s) == Event::SYNCDEL) { 1990 if (atoi(s) == Event::SYNCDEL) {
1987 deleteStr(s); 1991 deleteStr(s);
1988 goto SKIP; 1992 goto SKIP;
1989 } 1993 }
1990 deleteStr(s); 1994 deleteStr(s);
1991 } 1995 }
1992 1996
1993 // this code checks to see if we are trying to read in an event 1997 // this code checks to see if we are trying to read in an event
1994 // that we already find to be in the calendar. If we find this 1998 // that we already find to be in the calendar. If we find this
1995 // to be the case, we skip the event. 1999 // to be the case, we skip the event.
1996 if ((curVOProp = isAPropertyOf(curVO, VCUniqueStringProp)) != 0) { 2000 if ((curVOProp = isAPropertyOf(curVO, VCUniqueStringProp)) != 0) {
1997 char *s = fakeCString(vObjectUStringZValue(curVOProp)); 2001 char *s = fakeCString(vObjectUStringZValue(curVOProp));
1998 QString tmpStr(s); 2002 QString tmpStr(s);
1999 deleteStr(s); 2003 deleteStr(s);
2000 2004
2001 if (cal->event(tmpStr)) { 2005 if (cal->event(tmpStr)) {
2002 goto SKIP; 2006 goto SKIP;
2003 } 2007 }
2004 if (cal->todo(tmpStr)) { 2008 if (cal->todo(tmpStr)) {
2005 goto SKIP; 2009 goto SKIP;
2006 } 2010 }
2007 } 2011 }
2008 2012
2009 if ((!(curVOProp = isAPropertyOf(curVO, VCDTstartProp))) && 2013 if ((!(curVOProp = isAPropertyOf(curVO, VCDTstartProp))) &&
2010 (!(curVOProp = isAPropertyOf(curVO, VCDTendProp)))) { 2014 (!(curVOProp = isAPropertyOf(curVO, VCDTendProp)))) {
2011 kdDebug(5800) << "found a VEvent with no DTSTART and no DTEND! Skipping..." << endl; 2015 kdDebug(5800) << "found a VEvent with no DTSTART and no DTEND! Skipping..." << endl;
2012 goto SKIP; 2016 goto SKIP;
2013 } 2017 }
2014 2018
2015 anEvent = VEventToEvent(curVO); 2019 anEvent = VEventToEvent(curVO);
2016 // we now use addEvent instead of insertEvent so that the 2020 // we now use addEvent instead of insertEvent so that the
2017 // signal/slot get connected. 2021 // signal/slot get connected.
2018 if (anEvent) 2022 if (anEvent)
2019 cal->addEvent(anEvent); 2023 cal->addEvent(anEvent);
2020 else { 2024 else {
2021 // some sort of error must have occurred while in translation. 2025 // some sort of error must have occurred while in translation.
2022 goto SKIP; 2026 goto SKIP;
2023 } 2027 }
2024 } else if (strcmp(vObjectName(curVO), VCTodoProp) == 0) { 2028 } else if (strcmp(vObjectName(curVO), VCTodoProp) == 0) {
2025 anEvent = VTodoToEvent(curVO); 2029 anEvent = VTodoToEvent(curVO);
2026 cal->addTodo(anEvent); 2030 cal->addTodo(anEvent);
2027 } else if ((strcmp(vObjectName(curVO), VCVersionProp) == 0) || 2031 } else if ((strcmp(vObjectName(curVO), VCVersionProp) == 0) ||
2028 (strcmp(vObjectName(curVO), VCProdIdProp) == 0) || 2032 (strcmp(vObjectName(curVO), VCProdIdProp) == 0) ||
2029 (strcmp(vObjectName(curVO), VCTimeZoneProp) == 0)) { 2033 (strcmp(vObjectName(curVO), VCTimeZoneProp) == 0)) {
2030 // do nothing, we know these properties and we want to skip them. 2034 // do nothing, we know these properties and we want to skip them.
2031 // we have either already processed them or are ignoring them. 2035 // we have either already processed them or are ignoring them.
2032 ; 2036 ;
2033 } else { 2037 } else {
2034 ; 2038 ;
2035 } 2039 }
2036 SKIP: 2040 SKIP:
2037 ; 2041 ;
2038 } // while 2042 } // while
2039#endif 2043#endif
2040 2044
2041 // Post-Process list of events with relations, put Event objects in relation 2045 // Post-Process list of events with relations, put Event objects in relation
2042 Event *ev; 2046 Event *ev;
2043 for ( ev=mEventsRelate.first(); ev != 0; ev=mEventsRelate.next() ) { 2047 for ( ev=mEventsRelate.first(); ev != 0; ev=mEventsRelate.next() ) {
2044 ev->setRelatedTo(cal->event(ev->relatedToUid())); 2048 ev->setRelatedTo(cal->event(ev->relatedToUid()));
2045 } 2049 }
2046 Todo *todo; 2050 Todo *todo;
2047 for ( todo=mTodosRelate.first(); todo != 0; todo=mTodosRelate.next() ) { 2051 for ( todo=mTodosRelate.first(); todo != 0; todo=mTodosRelate.next() ) {
2048 todo->setRelatedTo(cal->todo(todo->relatedToUid())); 2052 todo->setRelatedTo(cal->todo(todo->relatedToUid()));
2049 } 2053 }
2050 2054
2051 return true; 2055 return true;
2052} 2056}
2053 2057
2054QString ICalFormatImpl::extractErrorProperty(icalcomponent *c) 2058QString ICalFormatImpl::extractErrorProperty(icalcomponent *c)
2055{ 2059{
2056// kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: " 2060// kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: "
2057// << icalcomponent_as_ical_string(c) << endl; 2061// << icalcomponent_as_ical_string(c) << endl;
2058 2062
2059 QString errorMessage; 2063 QString errorMessage;
2060 2064
2061 icalproperty *error; 2065 icalproperty *error;
2062 error = icalcomponent_get_first_property(c,ICAL_XLICERROR_PROPERTY); 2066 error = icalcomponent_get_first_property(c,ICAL_XLICERROR_PROPERTY);
2063 while(error) { 2067 while(error) {
2064 errorMessage += icalproperty_get_xlicerror(error); 2068 errorMessage += icalproperty_get_xlicerror(error);
2065 errorMessage += "\n"; 2069 errorMessage += "\n";
2066 error = icalcomponent_get_next_property(c,ICAL_XLICERROR_PROPERTY); 2070 error = icalcomponent_get_next_property(c,ICAL_XLICERROR_PROPERTY);
2067 } 2071 }
2068 2072
2069// kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: " << errorMessage << endl; 2073// kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: " << errorMessage << endl;
2070 2074
2071 return errorMessage; 2075 return errorMessage;
2072} 2076}
2073 2077
2074void ICalFormatImpl::dumpIcalRecurrence(icalrecurrencetype r) 2078void ICalFormatImpl::dumpIcalRecurrence(icalrecurrencetype r)
2075{ 2079{
2076 int i; 2080 int i;
2077 2081
2078 2082
2079 if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { 2083 if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
2080 int index = 0; 2084 int index = 0;
2081 QString out = " By Day: "; 2085 QString out = " By Day: ";
2082 while((i = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 2086 while((i = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
2083 out.append(QString::number(i) + " "); 2087 out.append(QString::number(i) + " ");
2084 } 2088 }
2085 } 2089 }
2086 if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { 2090 if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
2087 int index = 0; 2091 int index = 0;
2088 QString out = " By Month Day: "; 2092 QString out = " By Month Day: ";
2089 while((i = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 2093 while((i = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
2090 out.append(QString::number(i) + " "); 2094 out.append(QString::number(i) + " ");
2091 } 2095 }
2092 } 2096 }
2093 if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { 2097 if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) {
2094 int index = 0; 2098 int index = 0;
2095 QString out = " By Year Day: "; 2099 QString out = " By Year Day: ";
2096 while((i = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 2100 while((i = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
2097 out.append(QString::number(i) + " "); 2101 out.append(QString::number(i) + " ");
2098 } 2102 }
2099 } 2103 }
2100 if (r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) { 2104 if (r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) {
2101 int index = 0; 2105 int index = 0;
2102 QString out = " By Month: "; 2106 QString out = " By Month: ";
2103 while((i = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 2107 while((i = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
2104 out.append(QString::number(i) + " "); 2108 out.append(QString::number(i) + " ");
2105 } 2109 }
2106 } 2110 }
2107 if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) { 2111 if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) {
2108 int index = 0; 2112 int index = 0;
2109 QString out = " By Set Pos: "; 2113 QString out = " By Set Pos: ";
2110 while((i = r.by_set_pos[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { 2114 while((i = r.by_set_pos[index++]) != ICAL_RECURRENCE_ARRAY_MAX) {
2111 out.append(QString::number(i) + " "); 2115 out.append(QString::number(i) + " ");
2112 } 2116 }
2113 } 2117 }
2114} 2118}
2115 2119
2116icalcomponent *ICalFormatImpl::createScheduleComponent(IncidenceBase *incidence, 2120icalcomponent *ICalFormatImpl::createScheduleComponent(IncidenceBase *incidence,
2117 Scheduler::Method method) 2121 Scheduler::Method method)
2118{ 2122{
2119 icalcomponent *message = createCalendarComponent(); 2123 icalcomponent *message = createCalendarComponent();
2120 2124
2121 icalproperty_method icalmethod = ICAL_METHOD_NONE; 2125 icalproperty_method icalmethod = ICAL_METHOD_NONE;
2122 2126
2123 switch (method) { 2127 switch (method) {
2124 case Scheduler::Publish: 2128 case Scheduler::Publish:
2125 icalmethod = ICAL_METHOD_PUBLISH; 2129 icalmethod = ICAL_METHOD_PUBLISH;
2126 break; 2130 break;
2127 case Scheduler::Request: 2131 case Scheduler::Request:
2128 icalmethod = ICAL_METHOD_REQUEST; 2132 icalmethod = ICAL_METHOD_REQUEST;
2129 break; 2133 break;
2130 case Scheduler::Refresh: 2134 case Scheduler::Refresh:
2131 icalmethod = ICAL_METHOD_REFRESH; 2135 icalmethod = ICAL_METHOD_REFRESH;
2132 break; 2136 break;
2133 case Scheduler::Cancel: 2137 case Scheduler::Cancel:
2134 icalmethod = ICAL_METHOD_CANCEL; 2138 icalmethod = ICAL_METHOD_CANCEL;
2135 break; 2139 break;
2136 case Scheduler::Add: 2140 case Scheduler::Add:
2137 icalmethod = ICAL_METHOD_ADD; 2141 icalmethod = ICAL_METHOD_ADD;
2138 break; 2142 break;
2139 case Scheduler::Reply: 2143 case Scheduler::Reply:
2140 icalmethod = ICAL_METHOD_REPLY; 2144 icalmethod = ICAL_METHOD_REPLY;
2141 break; 2145 break;
2142 case Scheduler::Counter: 2146 case Scheduler::Counter:
2143 icalmethod = ICAL_METHOD_COUNTER; 2147 icalmethod = ICAL_METHOD_COUNTER;
2144 break; 2148 break;
2145 case Scheduler::Declinecounter: 2149 case Scheduler::Declinecounter:
2146 icalmethod = ICAL_METHOD_DECLINECOUNTER; 2150 icalmethod = ICAL_METHOD_DECLINECOUNTER;
2147 break; 2151 break;
2148 default: 2152 default:
2149 2153
2150 return message; 2154 return message;
2151 } 2155 }
2152 2156
2153 icalcomponent_add_property(message,icalproperty_new_method(icalmethod)); 2157 icalcomponent_add_property(message,icalproperty_new_method(icalmethod));
2154 2158
2155 // TODO: check, if dynamic cast is required 2159 // TODO: check, if dynamic cast is required
2156 if(incidence->type() == "Todo") { 2160 if(incidence->type() == "Todo") {
2157 Todo *todo = static_cast<Todo *>(incidence); 2161 Todo *todo = static_cast<Todo *>(incidence);
2158 icalcomponent_add_component(message,writeTodo(todo)); 2162 icalcomponent_add_component(message,writeTodo(todo));
2159 } 2163 }
2160 if(incidence->type() == "Event") { 2164 if(incidence->type() == "Event") {
2161 Event *event = static_cast<Event *>(incidence); 2165 Event *event = static_cast<Event *>(incidence);
2162 icalcomponent_add_component(message,writeEvent(event)); 2166 icalcomponent_add_component(message,writeEvent(event));
2163 } 2167 }
2164 if(incidence->type() == "FreeBusy") { 2168 if(incidence->type() == "FreeBusy") {
2165 FreeBusy *freebusy = static_cast<FreeBusy *>(incidence); 2169 FreeBusy *freebusy = static_cast<FreeBusy *>(incidence);
2166 icalcomponent_add_component(message,writeFreeBusy(freebusy, method)); 2170 icalcomponent_add_component(message,writeFreeBusy(freebusy, method));
2167 } 2171 }
2168 2172
2169 return message; 2173 return message;
2170} 2174}
diff --git a/libkcal/recurrence.cpp b/libkcal/recurrence.cpp
index 5fc5d1f..dd74e10 100644
--- a/libkcal/recurrence.cpp
+++ b/libkcal/recurrence.cpp
@@ -1,2776 +1,2789 @@
1/* 1/*
2 This file is part of libkcal. 2 This file is part of libkcal.
3 Copyright (c) 1998 Preston Brown 3 Copyright (c) 1998 Preston Brown
4 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> 4 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
5 Copyright (c) 2002 David Jarvie <software@astrojar.org.uk> 5 Copyright (c) 2002 David Jarvie <software@astrojar.org.uk>
6 6
7 This library is free software; you can redistribute it and/or 7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public 8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either 9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version. 10 version 2 of the License, or (at your option) any later version.
11 11
12 This library is distributed in the hope that it will be useful, 12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details. 15 Library General Public License for more details.
16 16
17 You should have received a copy of the GNU Library General Public License 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 18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. 20 Boston, MA 02111-1307, USA.
21*/ 21*/
22 22
23#include <limits.h> 23#include <limits.h>
24 24
25#include <kdebug.h> 25#include <kdebug.h>
26#include <kglobal.h> 26#include <kglobal.h>
27#include <klocale.h> 27#include <klocale.h>
28 28
29#include "incidence.h" 29#include "incidence.h"
30 30
31#include "recurrence.h" 31#include "recurrence.h"
32 32
33using namespace KCal; 33using namespace KCal;
34 34
35Recurrence::Feb29Type Recurrence::mFeb29YearlyDefaultType = Recurrence::rMar1; 35Recurrence::Feb29Type Recurrence::mFeb29YearlyDefaultType = Recurrence::rMar1;
36 36
37 37
38Recurrence::Recurrence(Incidence *parent, int compatVersion) 38Recurrence::Recurrence(Incidence *parent, int compatVersion)
39: recurs(rNone), // by default, it's not a recurring event 39: recurs(rNone), // by default, it's not a recurring event
40 rWeekStart(1), // default is Monday 40 rWeekStart(1), // default is Monday
41 rDays(7), 41 rDays(7),
42 mFloats(parent ? parent->doesFloat() : false), 42 mFloats(parent ? parent->doesFloat() : false),
43 mRecurReadOnly(false), 43 mRecurReadOnly(false),
44 mRecurExDatesCount(0), 44 mRecurExDatesCount(0),
45 mFeb29YearlyType(mFeb29YearlyDefaultType), 45 mFeb29YearlyType(mFeb29YearlyDefaultType),
46 mCompatVersion(compatVersion ? compatVersion : INT_MAX), 46 mCompatVersion(compatVersion ? compatVersion : INT_MAX),
47 mCompatRecurs(rNone), 47 mCompatRecurs(rNone),
48 mCompatDuration(0), 48 mCompatDuration(0),
49 mParent(parent) 49 mParent(parent)
50{ 50{
51 rMonthDays.setAutoDelete( true ); 51 rMonthDays.setAutoDelete( true );
52 rMonthPositions.setAutoDelete( true ); 52 rMonthPositions.setAutoDelete( true );
53 rYearNums.setAutoDelete( true ); 53 rYearNums.setAutoDelete( true );
54} 54}
55 55
56Recurrence::Recurrence(const Recurrence &r, Incidence *parent) 56Recurrence::Recurrence(const Recurrence &r, Incidence *parent)
57: recurs(r.recurs), 57: recurs(r.recurs),
58 rWeekStart(r.rWeekStart), 58 rWeekStart(r.rWeekStart),
59 rDays(r.rDays.copy()), 59 rDays(r.rDays.copy()),
60 rFreq(r.rFreq), 60 rFreq(r.rFreq),
61 rDuration(r.rDuration), 61 rDuration(r.rDuration),
62 rEndDateTime(r.rEndDateTime), 62 rEndDateTime(r.rEndDateTime),
63 mRecurStart(r.mRecurStart), 63 mRecurStart(r.mRecurStart),
64 mFloats(r.mFloats), 64 mFloats(r.mFloats),
65 mRecurReadOnly(r.mRecurReadOnly), 65 mRecurReadOnly(r.mRecurReadOnly),
66 mRecurExDatesCount(r.mRecurExDatesCount), 66 mRecurExDatesCount(r.mRecurExDatesCount),
67 mFeb29YearlyType(r.mFeb29YearlyType), 67 mFeb29YearlyType(r.mFeb29YearlyType),
68 mCompatVersion(r.mCompatVersion), 68 mCompatVersion(r.mCompatVersion),
69 mCompatRecurs(r.mCompatRecurs), 69 mCompatRecurs(r.mCompatRecurs),
70 mCompatDuration(r.mCompatDuration), 70 mCompatDuration(r.mCompatDuration),
71 mParent(parent) 71 mParent(parent)
72{ 72{
73 for (QPtrListIterator<rMonthPos> mp(r.rMonthPositions); mp.current(); ++mp) { 73 for (QPtrListIterator<rMonthPos> mp(r.rMonthPositions); mp.current(); ++mp) {
74 rMonthPos *tmp = new rMonthPos; 74 rMonthPos *tmp = new rMonthPos;
75 tmp->rPos = mp.current()->rPos; 75 tmp->rPos = mp.current()->rPos;
76 tmp->negative = mp.current()->negative; 76 tmp->negative = mp.current()->negative;
77 tmp->rDays = mp.current()->rDays.copy(); 77 tmp->rDays = mp.current()->rDays.copy();
78 rMonthPositions.append(tmp); 78 rMonthPositions.append(tmp);
79 } 79 }
80 for (QPtrListIterator<int> md(r.rMonthDays); md.current(); ++md) { 80 for (QPtrListIterator<int> md(r.rMonthDays); md.current(); ++md) {
81 int *tmp = new int; 81 int *tmp = new int;
82 *tmp = *md.current(); 82 *tmp = *md.current();
83 rMonthDays.append(tmp); 83 rMonthDays.append(tmp);
84 } 84 }
85 for (QPtrListIterator<int> yn(r.rYearNums); yn.current(); ++yn) { 85 for (QPtrListIterator<int> yn(r.rYearNums); yn.current(); ++yn) {
86 int *tmp = new int; 86 int *tmp = new int;
87 *tmp = *yn.current(); 87 *tmp = *yn.current();
88 rYearNums.append(tmp); 88 rYearNums.append(tmp);
89 } 89 }
90 rMonthDays.setAutoDelete( true ); 90 rMonthDays.setAutoDelete( true );
91 rMonthPositions.setAutoDelete( true ); 91 rMonthPositions.setAutoDelete( true );
92 rYearNums.setAutoDelete( true ); 92 rYearNums.setAutoDelete( true );
93} 93}
94 94
95Recurrence::~Recurrence() 95Recurrence::~Recurrence()
96{ 96{
97} 97}
98 98
99 99
100bool Recurrence::operator==( const Recurrence& r2 ) const 100bool Recurrence::operator==( const Recurrence& r2 ) const
101{ 101{
102 102
103 // the following line is obvious 103 // the following line is obvious
104 if ( recurs == rNone && r2.recurs == rNone ) 104 if ( recurs == rNone && r2.recurs == rNone )
105 return true; 105 return true;
106 // we need the above line, because two non recurring events may 106 // we need the above line, because two non recurring events may
107 // differ in the other settings, because one (or both) 107 // differ in the other settings, because one (or both)
108 // may be not initialized properly 108 // may be not initialized properly
109 if ( recurs != r2.recurs 109 if ( recurs != r2.recurs
110 || rFreq != r2.rFreq 110 || rFreq != r2.rFreq
111 || rDuration != r2.rDuration 111 || rDuration != r2.rDuration
112 || !rDuration && rEndDateTime != r2.rEndDateTime 112 || !rDuration && rEndDateTime != r2.rEndDateTime
113 || mRecurStart != r2.mRecurStart 113 || mRecurStart != r2.mRecurStart
114 || mFloats != r2.mFloats 114 || mFloats != r2.mFloats
115 || mRecurReadOnly != r2.mRecurReadOnly 115 || mRecurReadOnly != r2.mRecurReadOnly
116 || mRecurExDatesCount != r2.mRecurExDatesCount ) 116 || mRecurExDatesCount != r2.mRecurExDatesCount )
117 return false; 117 return false;
118 // no need to compare mCompat* and mParent 118 // no need to compare mCompat* and mParent
119 // OK to compare the pointers 119 // OK to compare the pointers
120 switch ( recurs ) 120 switch ( recurs )
121 { 121 {
122 case rWeekly: 122 case rWeekly:
123 return rDays == r2.rDays 123 return rDays == r2.rDays
124 && rWeekStart == r2.rWeekStart; 124 && rWeekStart == r2.rWeekStart;
125 case rMonthlyPos: 125 case rMonthlyPos:
126 return rMonthPositions.count() == r2.rMonthPositions.count(); 126 return rMonthPositions.count() == r2.rMonthPositions.count();
127 case rMonthlyDay: 127 case rMonthlyDay:
128 return rMonthDays.count() == r2.rMonthDays.count(); 128 return rMonthDays.count() == r2.rMonthDays.count();
129 case rYearlyPos: 129 case rYearlyPos:
130 return rYearNums.count() == r2.rYearNums.count() 130 return rYearNums.count() == r2.rYearNums.count()
131 && rMonthPositions.count() == r2.rMonthPositions.count(); 131 && rMonthPositions.count() == r2.rMonthPositions.count();
132 case rYearlyMonth: 132 case rYearlyMonth:
133 return rYearNums.count() == r2.rYearNums.count() 133 return rYearNums.count() == r2.rYearNums.count()
134 && mFeb29YearlyType == r2.mFeb29YearlyType; 134 && mFeb29YearlyType == r2.mFeb29YearlyType;
135 case rYearlyDay: 135 case rYearlyDay:
136 return rYearNums == r2.rYearNums; 136 return rYearNums == r2.rYearNums;
137 case rNone: 137 case rNone:
138 case rMinutely: 138 case rMinutely:
139 case rHourly: 139 case rHourly:
140 case rDaily: 140 case rDaily:
141 default: 141 default:
142 return true; 142 return true;
143 } 143 }
144} 144}
145/* 145/*
146bool Recurrence::compareLists( const QPtrList<int> &l1 ,const QPtrList<int> &l2) 146bool Recurrence::compareLists( const QPtrList<int> &l1 ,const QPtrList<int> &l2)
147{ 147{
148 if ( l1.count() != l2.count() ) 148 if ( l1.count() != l2.count() )
149 return false; 149 return false;
150 int count = l1.count(); 150 int count = l1.count();
151 int i; 151 int i;
152 for ( i = 0; i < count ; ++i ) { 152 for ( i = 0; i < count ; ++i ) {
153 // if ( l1.at(i) != l2.at(i) ) 153 // if ( l1.at(i) != l2.at(i) )
154 return false; 154 return false;
155 qDebug("compüare "); 155 qDebug("compüare ");
156 } 156 }
157 return true; 157 return true;
158} 158}
159*/ 159*/
160QString Recurrence::recurrenceText() const 160QString Recurrence::recurrenceText() const
161{ 161{
162 QString recurText = i18n("No"); 162 QString recurText = i18n("No");
163 if ( recurs == Recurrence::rMinutely ) 163 if ( recurs == Recurrence::rMinutely )
164 recurText = i18n("minutely"); 164 recurText = i18n("minutely");
165 else if ( recurs == Recurrence::rHourly ) 165 else if ( recurs == Recurrence::rHourly )
166 recurText = i18n("hourly"); 166 recurText = i18n("hourly");
167 else if ( recurs == Recurrence::rDaily ) 167 else if ( recurs == Recurrence::rDaily )
168 recurText = i18n("daily"); 168 recurText = i18n("daily");
169 else if ( recurs == Recurrence::rWeekly ) 169 else if ( recurs == Recurrence::rWeekly )
170 recurText = i18n("weekly"); 170 recurText = i18n("weekly");
171 else if ( recurs == Recurrence::rMonthlyPos ) 171 else if ( recurs == Recurrence::rMonthlyPos )
172 recurText = i18n("monthly"); 172 recurText = i18n("monthly");
173 else if ( recurs == Recurrence::rMonthlyDay ) 173 else if ( recurs == Recurrence::rMonthlyDay )
174 recurText = i18n("day-monthly"); 174 recurText = i18n("day-monthly");
175 else if ( recurs == Recurrence::rYearlyMonth ) 175 else if ( recurs == Recurrence::rYearlyMonth )
176 recurText = i18n("month-yearly"); 176 recurText = i18n("month-yearly");
177 else if ( recurs == Recurrence::rYearlyDay ) 177 else if ( recurs == Recurrence::rYearlyDay )
178 recurText = i18n("day-yearly"); 178 recurText = i18n("day-yearly");
179 else if ( recurs == Recurrence::rYearlyPos ) 179 else if ( recurs == Recurrence::rYearlyPos )
180 recurText = i18n("position-yearly"); 180 recurText = i18n("position-yearly");
181 return recurText; 181 return recurText;
182} 182}
183 183
184void Recurrence::setCompatVersion(int version) 184void Recurrence::setCompatVersion(int version)
185{ 185{
186 mCompatVersion = version ? version : INT_MAX; 186 mCompatVersion = version ? version : INT_MAX;
187} 187}
188 188
189ushort Recurrence::doesRecur() const 189ushort Recurrence::doesRecur() const
190{ 190{
191 return recurs; 191 return recurs;
192} 192}
193 193
194bool Recurrence::recursOnPure(const QDate &qd) const 194bool Recurrence::recursOnPure(const QDate &qd) const
195{ 195{
196 switch(recurs) { 196 switch(recurs) {
197 case rMinutely: 197 case rMinutely:
198 return recursSecondly(qd, rFreq*60); 198 return recursSecondly(qd, rFreq*60);
199 case rHourly: 199 case rHourly:
200 return recursSecondly(qd, rFreq*3600); 200 return recursSecondly(qd, rFreq*3600);
201 case rDaily: 201 case rDaily:
202 return recursDaily(qd); 202 return recursDaily(qd);
203 case rWeekly: 203 case rWeekly:
204 return recursWeekly(qd); 204 return recursWeekly(qd);
205 case rMonthlyPos: 205 case rMonthlyPos:
206 case rMonthlyDay: 206 case rMonthlyDay:
207 return recursMonthly(qd); 207 return recursMonthly(qd);
208 case rYearlyMonth: 208 case rYearlyMonth:
209 return recursYearlyByMonth(qd); 209 return recursYearlyByMonth(qd);
210 case rYearlyDay: 210 case rYearlyDay:
211 return recursYearlyByDay(qd); 211 return recursYearlyByDay(qd);
212 case rYearlyPos: 212 case rYearlyPos:
213 return recursYearlyByPos(qd); 213 return recursYearlyByPos(qd);
214 default: 214 default:
215 return false; 215 return false;
216 case rNone: 216 case rNone:
217 return false; 217 return false;
218 } // case 218 } // case
219 return false; 219 return false;
220} 220}
221 221
222bool Recurrence::recursAtPure(const QDateTime &dt) const 222bool Recurrence::recursAtPure(const QDateTime &dt) const
223{ 223{
224 switch(recurs) { 224 switch(recurs) {
225 case rMinutely: 225 case rMinutely:
226 return recursMinutelyAt(dt, rFreq); 226 return recursMinutelyAt(dt, rFreq);
227 case rHourly: 227 case rHourly:
228 return recursMinutelyAt(dt, rFreq*60); 228 return recursMinutelyAt(dt, rFreq*60);
229 default: 229 default:
230 if (dt.time() != mRecurStart.time()) 230 if (dt.time() != mRecurStart.time())
231 return false; 231 return false;
232 switch(recurs) { 232 switch(recurs) {
233 case rDaily: 233 case rDaily:
234 return recursDaily(dt.date()); 234 return recursDaily(dt.date());
235 case rWeekly: 235 case rWeekly:
236 return recursWeekly(dt.date()); 236 return recursWeekly(dt.date());
237 case rMonthlyPos: 237 case rMonthlyPos:
238 case rMonthlyDay: 238 case rMonthlyDay:
239 return recursMonthly(dt.date()); 239 return recursMonthly(dt.date());
240 case rYearlyMonth: 240 case rYearlyMonth:
241 return recursYearlyByMonth(dt.date()); 241 return recursYearlyByMonth(dt.date());
242 case rYearlyDay: 242 case rYearlyDay:
243 return recursYearlyByDay(dt.date()); 243 return recursYearlyByDay(dt.date());
244 case rYearlyPos: 244 case rYearlyPos:
245 return recursYearlyByPos(dt.date()); 245 return recursYearlyByPos(dt.date());
246 default: 246 default:
247 return false; 247 return false;
248 case rNone: 248 case rNone:
249 return false; 249 return false;
250 } 250 }
251 } // case 251 } // case
252 return false; 252 return false;
253} 253}
254 254
255QDate Recurrence::endDate() const 255QDate Recurrence::endDate() const
256{ 256{
257 int count = 0; 257 int count = 0;
258 QDate end; 258 QDate end;
259 if (recurs != rNone) { 259 if (recurs != rNone) {
260 if (rDuration < 0) 260 if (rDuration < 0)
261 return QDate(); // infinite recurrence 261 return QDate(); // infinite recurrence
262 if (rDuration == 0) 262 if (rDuration == 0)
263 return rEndDateTime.date(); 263 return rEndDateTime.date();
264 264
265 // The end date is determined by the recurrence count 265 // The end date is determined by the recurrence count
266 QDate dStart = mRecurStart.date(); 266 QDate dStart = mRecurStart.date();
267 switch (recurs) 267 switch (recurs)
268 { 268 {
269 case rMinutely: 269 case rMinutely:
270 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*60).date(); 270 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*60).date();
271 case rHourly: 271 case rHourly:
272 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*3600).date(); 272 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*3600).date();
273 case rDaily: 273 case rDaily:
274 return dStart.addDays((rDuration-1+mRecurExDatesCount)*rFreq); 274 return dStart.addDays((rDuration-1+mRecurExDatesCount)*rFreq);
275 275
276 case rWeekly: 276 case rWeekly:
277 count = weeklyCalc(END_DATE_AND_COUNT, end); 277 count = weeklyCalc(END_DATE_AND_COUNT, end);
278 break; 278 break;
279 case rMonthlyPos: 279 case rMonthlyPos:
280 case rMonthlyDay: 280 case rMonthlyDay:
281 count = monthlyCalc(END_DATE_AND_COUNT, end); 281 count = monthlyCalc(END_DATE_AND_COUNT, end);
282 break; 282 break;
283 case rYearlyMonth: 283 case rYearlyMonth:
284 count = yearlyMonthCalc(END_DATE_AND_COUNT, end); 284 count = yearlyMonthCalc(END_DATE_AND_COUNT, end);
285 break; 285 break;
286 case rYearlyDay: 286 case rYearlyDay:
287 count = yearlyDayCalc(END_DATE_AND_COUNT, end); 287 count = yearlyDayCalc(END_DATE_AND_COUNT, end);
288 break; 288 break;
289 case rYearlyPos: 289 case rYearlyPos:
290 count = yearlyPosCalc(END_DATE_AND_COUNT, end); 290 count = yearlyPosCalc(END_DATE_AND_COUNT, end);
291 break; 291 break;
292 default: 292 default:
293 // catch-all. Should never get here. 293 // catch-all. Should never get here.
294 kdDebug(5800) << "Control should never reach here in endDate()!" << endl; 294 kdDebug(5800) << "Control should never reach here in endDate()!" << endl;
295 break; 295 break;
296 } 296 }
297 } 297 }
298 if (!count) 298 if (!count)
299 return QDate(); // error - there is no recurrence 299 return QDate(); // error - there is no recurrence
300 return end; 300 return end;
301} 301}
302 302
303QDateTime Recurrence::endDateTime() const 303QDateTime Recurrence::endDateTime() const
304{ 304{
305 int count = 0; 305 int count = 0;
306 QDate end; 306 QDate end;
307 if (recurs != rNone) { 307 if (recurs != rNone) {
308 if (rDuration < 0) 308 if (rDuration < 0)
309 return QDateTime(); // infinite recurrence 309 return QDateTime(); // infinite recurrence
310 if (rDuration == 0) 310 if (rDuration == 0)
311 return rEndDateTime; 311 return rEndDateTime;
312 312
313 // The end date is determined by the recurrence count 313 // The end date is determined by the recurrence count
314 QDate dStart = mRecurStart.date(); 314 QDate dStart = mRecurStart.date();
315 switch (recurs) 315 switch (recurs)
316 { 316 {
317 case rMinutely: 317 case rMinutely:
318 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*60); 318 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*60);
319 case rHourly: 319 case rHourly:
320 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*3600); 320 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*3600);
321 case rDaily: 321 case rDaily:
322 return dStart.addDays((rDuration-1+mRecurExDatesCount)*rFreq); 322 return dStart.addDays((rDuration-1+mRecurExDatesCount)*rFreq);
323 323
324 case rWeekly: 324 case rWeekly:
325 count = weeklyCalc(END_DATE_AND_COUNT, end); 325 count = weeklyCalc(END_DATE_AND_COUNT, end);
326 break; 326 break;
327 case rMonthlyPos: 327 case rMonthlyPos:
328 case rMonthlyDay: 328 case rMonthlyDay:
329 count = monthlyCalc(END_DATE_AND_COUNT, end); 329 count = monthlyCalc(END_DATE_AND_COUNT, end);
330 break; 330 break;
331 case rYearlyMonth: 331 case rYearlyMonth:
332 count = yearlyMonthCalc(END_DATE_AND_COUNT, end); 332 count = yearlyMonthCalc(END_DATE_AND_COUNT, end);
333 break; 333 break;
334 case rYearlyDay: 334 case rYearlyDay:
335 count = yearlyDayCalc(END_DATE_AND_COUNT, end); 335 count = yearlyDayCalc(END_DATE_AND_COUNT, end);
336 break; 336 break;
337 case rYearlyPos: 337 case rYearlyPos:
338 count = yearlyPosCalc(END_DATE_AND_COUNT, end); 338 count = yearlyPosCalc(END_DATE_AND_COUNT, end);
339 break; 339 break;
340 default: 340 default:
341 // catch-all. Should never get here. 341 // catch-all. Should never get here.
342 kdDebug(5800) << "Control should never reach here in endDate()!" << endl; 342 kdDebug(5800) << "Control should never reach here in endDate()!" << endl;
343 break; 343 break;
344 } 344 }
345 } 345 }
346 if (!count) 346 if (!count)
347 return QDateTime(); // error - there is no recurrence 347 return QDateTime(); // error - there is no recurrence
348 return QDateTime(end, mRecurStart.time()); 348 return QDateTime(end, mRecurStart.time());
349} 349}
350 350
351int Recurrence::durationTo(const QDate &date) const 351int Recurrence::durationTo(const QDate &date) const
352{ 352{
353 QDate d = date; 353 QDate d = date;
354 return recurCalc(COUNT_TO_DATE, d); 354 return recurCalc(COUNT_TO_DATE, d);
355} 355}
356 356
357int Recurrence::durationTo(const QDateTime &datetime) const 357int Recurrence::durationTo(const QDateTime &datetime) const
358{ 358{
359 QDateTime dt = datetime; 359 QDateTime dt = datetime;
360 return recurCalc(COUNT_TO_DATE, dt); 360 return recurCalc(COUNT_TO_DATE, dt);
361} 361}
362 362
363void Recurrence::unsetRecurs() 363void Recurrence::unsetRecurs()
364{ 364{
365 if (mRecurReadOnly) return; 365 if (mRecurReadOnly) return;
366 recurs = rNone; 366 recurs = rNone;
367 rMonthPositions.clear(); 367 rMonthPositions.clear();
368 rMonthDays.clear(); 368 rMonthDays.clear();
369 rYearNums.clear(); 369 rYearNums.clear();
370} 370}
371 371
372void Recurrence::setRecurStart(const QDateTime &start) 372void Recurrence::setRecurStart(const QDateTime &start)
373{ 373{
374 mRecurStart = start; 374 mRecurStart = start;
375 mFloats = false; 375 mFloats = false;
376 switch (recurs) 376 switch (recurs)
377 { 377 {
378 case rMinutely: 378 case rMinutely:
379 case rHourly: 379 case rHourly:
380 break; 380 break;
381 case rDaily: 381 case rDaily:
382 case rWeekly: 382 case rWeekly:
383 case rMonthlyPos: 383 case rMonthlyPos:
384 case rMonthlyDay: 384 case rMonthlyDay:
385 case rYearlyMonth: 385 case rYearlyMonth:
386 case rYearlyDay: 386 case rYearlyDay:
387 case rYearlyPos: 387 case rYearlyPos:
388 default: 388 default:
389 rEndDateTime.setTime(start.time()); 389 rEndDateTime.setTime(start.time());
390 break; 390 break;
391 } 391 }
392} 392}
393 393
394void Recurrence::setRecurStart(const QDate &start) 394void Recurrence::setRecurStart(const QDate &start)
395{ 395{
396 mRecurStart.setDate(start); 396 mRecurStart.setDate(start);
397 mRecurStart.setTime(QTime(0,0,0)); 397 mRecurStart.setTime(QTime(0,0,0));
398 switch (recurs) 398 switch (recurs)
399 { 399 {
400 case rMinutely: 400 case rMinutely:
401 case rHourly: 401 case rHourly:
402 break; 402 break;
403 case rDaily: 403 case rDaily:
404 case rWeekly: 404 case rWeekly:
405 case rMonthlyPos: 405 case rMonthlyPos:
406 case rMonthlyDay: 406 case rMonthlyDay:
407 case rYearlyMonth: 407 case rYearlyMonth:
408 case rYearlyDay: 408 case rYearlyDay:
409 case rYearlyPos: 409 case rYearlyPos:
410 default: 410 default:
411 mFloats = true; 411 mFloats = true;
412 break; 412 break;
413 } 413 }
414} 414}
415 415
416void Recurrence::setFloats(bool f) 416void Recurrence::setFloats(bool f)
417{ 417{
418 switch (recurs) 418 switch (recurs)
419 { 419 {
420 case rDaily: 420 case rDaily:
421 case rWeekly: 421 case rWeekly:
422 case rMonthlyPos: 422 case rMonthlyPos:
423 case rMonthlyDay: 423 case rMonthlyDay:
424 case rYearlyMonth: 424 case rYearlyMonth:
425 case rYearlyDay: 425 case rYearlyDay:
426 case rYearlyPos: 426 case rYearlyPos:
427 break; 427 break;
428 case rMinutely: 428 case rMinutely:
429 case rHourly: 429 case rHourly:
430 default: 430 default:
431 return; // can't set sub-daily to floating 431 return; // can't set sub-daily to floating
432 } 432 }
433 mFloats = f; 433 mFloats = f;
434 if (f) { 434 if (f) {
435 mRecurStart.setTime(QTime(0,0,0)); 435 mRecurStart.setTime(QTime(0,0,0));
436 rEndDateTime.setTime(QTime(0,0,0)); 436 rEndDateTime.setTime(QTime(0,0,0));
437 } 437 }
438} 438}
439 439
440int Recurrence::frequency() const 440int Recurrence::frequency() const
441{ 441{
442 return rFreq; 442 return rFreq;
443} 443}
444 444
445int Recurrence::duration() const 445int Recurrence::duration() const
446{ 446{
447 return rDuration; 447 return rDuration;
448} 448}
449 449
450void Recurrence::setDuration(int _rDuration) 450void Recurrence::setDuration(int _rDuration)
451{ 451{
452 if (mRecurReadOnly) return; 452 if (mRecurReadOnly) return;
453 if (_rDuration > 0) { 453 if (_rDuration > 0) {
454 rDuration = _rDuration; 454 rDuration = _rDuration;
455 // Compatibility mode is only needed when reading the calendar in ICalFormatImpl, 455 // Compatibility mode is only needed when reading the calendar in ICalFormatImpl,
456 // so explicitly setting the duration means no backwards compatibility is needed. 456 // so explicitly setting the duration means no backwards compatibility is needed.
457 mCompatDuration = 0; 457 mCompatDuration = 0;
458 } 458 }
459} 459}
460 460
461QString Recurrence::endDateStr(bool shortfmt) const 461QString Recurrence::endDateStr(bool shortfmt) const
462{ 462{
463 return KGlobal::locale()->formatDate(rEndDateTime.date(),shortfmt); 463 return KGlobal::locale()->formatDate(rEndDateTime.date(),shortfmt);
464} 464}
465 465
466const QBitArray &Recurrence::days() const 466const QBitArray &Recurrence::days() const
467{ 467{
468 return rDays; 468 return rDays;
469} 469}
470 470
471const QPtrList<Recurrence::rMonthPos> &Recurrence::monthPositions() const 471const QPtrList<Recurrence::rMonthPos> &Recurrence::monthPositions() const
472{ 472{
473 return rMonthPositions; 473 return rMonthPositions;
474} 474}
475 475
476const QPtrList<Recurrence::rMonthPos> &Recurrence::yearMonthPositions() const 476const QPtrList<Recurrence::rMonthPos> &Recurrence::yearMonthPositions() const
477{ 477{
478 return rMonthPositions; 478 return rMonthPositions;
479} 479}
480 480
481const QPtrList<int> &Recurrence::monthDays() const 481const QPtrList<int> &Recurrence::monthDays() const
482{ 482{
483 return rMonthDays; 483 return rMonthDays;
484} 484}
485 485
486void Recurrence::setMinutely(int _rFreq, int _rDuration) 486void Recurrence::setMinutely(int _rFreq, int _rDuration)
487{ 487{
488 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 488 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
489 return; 489 return;
490 setDailySub(rMinutely, _rFreq, _rDuration); 490 setDailySub(rMinutely, _rFreq, _rDuration);
491} 491}
492 492
493void Recurrence::setMinutely(int _rFreq, const QDateTime &_rEndDateTime) 493void Recurrence::setMinutely(int _rFreq, const QDateTime &_rEndDateTime)
494{ 494{
495 if (mRecurReadOnly) return; 495 if (mRecurReadOnly) return;
496 rEndDateTime = _rEndDateTime; 496 rEndDateTime = _rEndDateTime;
497 setDailySub(rMinutely, _rFreq, 0); 497 setDailySub(rMinutely, _rFreq, 0);
498} 498}
499 499
500void Recurrence::setHourly(int _rFreq, int _rDuration) 500void Recurrence::setHourly(int _rFreq, int _rDuration)
501{ 501{
502 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 502 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
503 return; 503 return;
504 setDailySub(rHourly, _rFreq, _rDuration); 504 setDailySub(rHourly, _rFreq, _rDuration);
505} 505}
506 506
507void Recurrence::setHourly(int _rFreq, const QDateTime &_rEndDateTime) 507void Recurrence::setHourly(int _rFreq, const QDateTime &_rEndDateTime)
508{ 508{
509 if (mRecurReadOnly) return; 509 if (mRecurReadOnly) return;
510 rEndDateTime = _rEndDateTime; 510 rEndDateTime = _rEndDateTime;
511 setDailySub(rHourly, _rFreq, 0); 511 setDailySub(rHourly, _rFreq, 0);
512} 512}
513 513
514void Recurrence::setDaily(int _rFreq, int _rDuration) 514void Recurrence::setDaily(int _rFreq, int _rDuration)
515{ 515{
516 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 516 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
517 return; 517 return;
518 setDailySub(rDaily, _rFreq, _rDuration); 518 setDailySub(rDaily, _rFreq, _rDuration);
519} 519}
520 520
521void Recurrence::setDaily(int _rFreq, const QDate &_rEndDate) 521void Recurrence::setDaily(int _rFreq, const QDate &_rEndDate)
522{ 522{
523 if (mRecurReadOnly) return; 523 if (mRecurReadOnly) return;
524 rEndDateTime.setDate(_rEndDate); 524 rEndDateTime.setDate(_rEndDate);
525 rEndDateTime.setTime(mRecurStart.time()); 525 rEndDateTime.setTime(mRecurStart.time());
526 setDailySub(rDaily, _rFreq, 0); 526 setDailySub(rDaily, _rFreq, 0);
527} 527}
528 528
529void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays, 529void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays,
530 int _rDuration, int _rWeekStart) 530 int _rDuration, int _rWeekStart)
531{ 531{
532 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 532 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
533 return; 533 return;
534 recurs = rWeekly; 534 recurs = rWeekly;
535 535
536 rFreq = _rFreq; 536 rFreq = _rFreq;
537 rDays = _rDays; 537 rDays = _rDays;
538 rWeekStart = _rWeekStart; 538 rWeekStart = _rWeekStart;
539 rDuration = _rDuration; 539 rDuration = _rDuration;
540 if (mCompatVersion < 310 && _rDuration > 0) { 540 if (mCompatVersion < 310 && _rDuration > 0) {
541 // Backwards compatibility for KDE < 3.1. 541 // Backwards compatibility for KDE < 3.1.
542 // rDuration was set to the number of time periods to recur, 542 // rDuration was set to the number of time periods to recur,
543 // with week start always on a Monday. 543 // with week start always on a Monday.
544 // Convert this to the number of occurrences. 544 // Convert this to the number of occurrences.
545 mCompatDuration = _rDuration; 545 mCompatDuration = _rDuration;
546 int weeks = ((mCompatDuration-1+mRecurExDatesCount)*7) + (7 - mRecurStart.date().dayOfWeek()); 546 int weeks = ((mCompatDuration-1+mRecurExDatesCount)*7) + (7 - mRecurStart.date().dayOfWeek());
547 QDate end(mRecurStart.date().addDays(weeks * rFreq)); 547 QDate end(mRecurStart.date().addDays(weeks * rFreq));
548 rDuration = INT_MAX; // ensure that weeklyCalc() does its job correctly 548 rDuration = INT_MAX; // ensure that weeklyCalc() does its job correctly
549 rDuration = weeklyCalc(COUNT_TO_DATE, end); 549 rDuration = weeklyCalc(COUNT_TO_DATE, end);
550 } else { 550 } else {
551 mCompatDuration = 0; 551 mCompatDuration = 0;
552 } 552 }
553 rMonthPositions.clear(); 553 rMonthPositions.clear();
554 rMonthDays.clear(); 554 rMonthDays.clear();
555 if (mParent) mParent->updated(); 555 if (mParent) mParent->updated();
556} 556}
557 557
558void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays, 558void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays,
559 const QDate &_rEndDate, int _rWeekStart) 559 const QDate &_rEndDate, int _rWeekStart)
560{ 560{
561 if (mRecurReadOnly) return; 561 if (mRecurReadOnly) return;
562 recurs = rWeekly; 562 recurs = rWeekly;
563 563
564 rFreq = _rFreq; 564 rFreq = _rFreq;
565 rDays = _rDays; 565 rDays = _rDays;
566 rWeekStart = _rWeekStart; 566 rWeekStart = _rWeekStart;
567 rEndDateTime.setDate(_rEndDate); 567 rEndDateTime.setDate(_rEndDate);
568 rEndDateTime.setTime(mRecurStart.time()); 568 rEndDateTime.setTime(mRecurStart.time());
569 rDuration = 0; // set to 0 because there is an end date 569 rDuration = 0; // set to 0 because there is an end date
570 mCompatDuration = 0; 570 mCompatDuration = 0;
571 rMonthPositions.clear(); 571 rMonthPositions.clear();
572 rMonthDays.clear(); 572 rMonthDays.clear();
573 rYearNums.clear(); 573 rYearNums.clear();
574 if (mParent) mParent->updated(); 574 if (mParent) mParent->updated();
575} 575}
576 576
577void Recurrence::setMonthly(short type, int _rFreq, int _rDuration) 577void Recurrence::setMonthly(short type, int _rFreq, int _rDuration)
578{ 578{
579 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 579 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
580 return; 580 return;
581 recurs = type; 581 recurs = type;
582 582
583 rFreq = _rFreq; 583 rFreq = _rFreq;
584 rDuration = _rDuration; 584 rDuration = _rDuration;
585 if (mCompatVersion < 310) 585 if (mCompatVersion < 310)
586 mCompatDuration = (_rDuration > 0) ? _rDuration : 0; 586 mCompatDuration = (_rDuration > 0) ? _rDuration : 0;
587 rYearNums.clear(); 587 rYearNums.clear();
588 if (mParent) mParent->updated(); 588 if (mParent) mParent->updated();
589} 589}
590 590
591void Recurrence::setMonthly(short type, int _rFreq, 591void Recurrence::setMonthly(short type, int _rFreq,
592 const QDate &_rEndDate) 592 const QDate &_rEndDate)
593{ 593{
594 if (mRecurReadOnly) return; 594 if (mRecurReadOnly) return;
595 recurs = type; 595 recurs = type;
596 596
597 rFreq = _rFreq; 597 rFreq = _rFreq;
598 rEndDateTime.setDate(_rEndDate); 598 rEndDateTime.setDate(_rEndDate);
599 rEndDateTime.setTime(mRecurStart.time()); 599 rEndDateTime.setTime(mRecurStart.time());
600 rDuration = 0; // set to 0 because there is an end date 600 rDuration = 0; // set to 0 because there is an end date
601 mCompatDuration = 0; 601 mCompatDuration = 0;
602 rYearNums.clear(); 602 rYearNums.clear();
603 if (mParent) mParent->updated(); 603 if (mParent) mParent->updated();
604} 604}
605 605
606void Recurrence::addMonthlyPos(short _rPos, const QBitArray &_rDays) 606void Recurrence::addMonthlyPos(short _rPos, const QBitArray &_rDays)
607{ 607{
608 if (recurs == rMonthlyPos) 608 if (recurs == rMonthlyPos)
609 addMonthlyPos_(_rPos, _rDays); 609 addMonthlyPos_(_rPos, _rDays);
610} 610}
611 611
612void Recurrence::addMonthlyPos_(short _rPos, const QBitArray &_rDays) 612void Recurrence::addMonthlyPos_(short _rPos, const QBitArray &_rDays)
613{ 613{
614 if (mRecurReadOnly 614 if (mRecurReadOnly
615 || _rPos == 0 || _rPos > 5 || _rPos < -5) // invalid week number 615 || _rPos == 0 || _rPos > 5 || _rPos < -5) // invalid week number
616 return; 616 return;
617 617
618 for (rMonthPos* it = rMonthPositions.first(); it; it = rMonthPositions.next()) { 618 for (rMonthPos* it = rMonthPositions.first(); it; it = rMonthPositions.next()) {
619 int itPos = it->negative ? -it->rPos : it->rPos; 619 int itPos = it->negative ? -it->rPos : it->rPos;
620 if (_rPos == itPos) { 620 if (_rPos == itPos) {
621 // This week is already in the list. 621 // This week is already in the list.
622 // Combine the specified days with those in the list. 622 // Combine the specified days with those in the list.
623 it->rDays |= _rDays; 623 it->rDays |= _rDays;
624 if (mParent) mParent->updated(); 624 if (mParent) mParent->updated();
625 return; 625 return;
626 } 626 }
627 } 627 }
628 // Add the new position to the list 628 // Add the new position to the list
629 rMonthPos *tmpPos = new rMonthPos; 629 rMonthPos *tmpPos = new rMonthPos;
630 if (_rPos > 0) { 630 if (_rPos > 0) {
631 tmpPos->rPos = _rPos; 631 tmpPos->rPos = _rPos;
632 tmpPos->negative = false; 632 tmpPos->negative = false;
633 } else { 633 } else {
634 tmpPos->rPos = -_rPos; // take abs() 634 tmpPos->rPos = -_rPos; // take abs()
635 tmpPos->negative = true; 635 tmpPos->negative = true;
636 } 636 }
637 tmpPos->rDays = _rDays; 637 tmpPos->rDays = _rDays;
638 tmpPos->rDays.detach(); 638 tmpPos->rDays.detach();
639 rMonthPositions.append(tmpPos); 639 rMonthPositions.append(tmpPos);
640 640
641 if (mCompatVersion < 310 && mCompatDuration > 0) { 641 if (mCompatVersion < 310 && mCompatDuration > 0) {
642 // Backwards compatibility for KDE < 3.1. 642 // Backwards compatibility for KDE < 3.1.
643 // rDuration was set to the number of time periods to recur. 643 // rDuration was set to the number of time periods to recur.
644 // Convert this to the number of occurrences. 644 // Convert this to the number of occurrences.
645 int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq; 645 int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq;
646 int month = mRecurStart.date().month() - 1 + monthsAhead; 646 int month = mRecurStart.date().month() - 1 + monthsAhead;
647 QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31); 647 QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31);
648 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly 648 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly
649 rDuration = recurCalc(COUNT_TO_DATE, end); 649 rDuration = recurCalc(COUNT_TO_DATE, end);
650 } 650 }
651 651
652 if (mParent) mParent->updated(); 652 if (mParent) mParent->updated();
653} 653}
654 654
655void Recurrence::addMonthlyDay(short _rDay) 655void Recurrence::addMonthlyDay(short _rDay)
656{ 656{
657 if (mRecurReadOnly || recurs != rMonthlyDay 657 if (mRecurReadOnly || (recurs != rMonthlyDay && recurs != rYearlyMonth)
658 || _rDay == 0 || _rDay > 31 || _rDay < -31) // invalid day number 658 || _rDay == 0 || _rDay > 31 || _rDay < -31) // invalid day number
659 return; 659 return;
660 for (int* it = rMonthDays.first(); it; it = rMonthDays.next()) { 660 for (int* it = rMonthDays.first(); it; it = rMonthDays.next()) {
661 if (_rDay == *it) 661 if (_rDay == *it)
662 return; // this day is already in the list - avoid duplication 662 return; // this day is already in the list - avoid duplication
663 } 663 }
664 int *tmpDay = new int; 664 int *tmpDay = new int;
665 *tmpDay = _rDay; 665 *tmpDay = _rDay;
666 rMonthDays.append(tmpDay); 666 rMonthDays.append(tmpDay);
667 667
668 if (mCompatVersion < 310 && mCompatDuration > 0) { 668 if (mCompatVersion < 310 && mCompatDuration > 0) {
669 // Backwards compatibility for KDE < 3.1. 669 // Backwards compatibility for KDE < 3.1.
670 // rDuration was set to the number of time periods to recur. 670 // rDuration was set to the number of time periods to recur.
671 // Convert this to the number of occurrences. 671 // Convert this to the number of occurrences.
672 int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq; 672 int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq;
673 int month = mRecurStart.date().month() - 1 + monthsAhead; 673 int month = mRecurStart.date().month() - 1 + monthsAhead;
674 QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31); 674 QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31);
675 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly 675 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly
676 rDuration = recurCalc(COUNT_TO_DATE, end); 676 rDuration = recurCalc(COUNT_TO_DATE, end);
677 } 677 }
678 678
679 if (mParent) mParent->updated(); 679 if (mParent) mParent->updated();
680} 680}
681 681
682void Recurrence::setYearly(int type, int _rFreq, int _rDuration) 682void Recurrence::setYearly(int type, int _rFreq, int _rDuration)
683{ 683{
684 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 684 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
685 return; 685 return;
686 if (mCompatVersion < 310) 686 if (mCompatVersion < 310)
687 mCompatDuration = (_rDuration > 0) ? _rDuration : 0; 687 mCompatDuration = (_rDuration > 0) ? _rDuration : 0;
688 setYearly_(type, mFeb29YearlyDefaultType, _rFreq, _rDuration); 688 setYearly_(type, mFeb29YearlyDefaultType, _rFreq, _rDuration);
689} 689}
690 690
691void Recurrence::setYearly(int type, int _rFreq, const QDate &_rEndDate) 691void Recurrence::setYearly(int type, int _rFreq, const QDate &_rEndDate)
692{ 692{
693 if (mRecurReadOnly) return; 693 if (mRecurReadOnly) return;
694 rEndDateTime.setDate(_rEndDate); 694 rEndDateTime.setDate(_rEndDate);
695 rEndDateTime.setTime(mRecurStart.time()); 695 rEndDateTime.setTime(mRecurStart.time());
696 mCompatDuration = 0; 696 mCompatDuration = 0;
697 setYearly_(type, mFeb29YearlyDefaultType, _rFreq, 0); 697 setYearly_(type, mFeb29YearlyDefaultType, _rFreq, 0);
698} 698}
699 699
700void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, int _rDuration) 700void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, int _rDuration)
701{ 701{
702 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 702 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
703 return; 703 return;
704 if (mCompatVersion < 310) 704 if (mCompatVersion < 310)
705 mCompatDuration = (_rDuration > 0) ? _rDuration : 0; 705 mCompatDuration = (_rDuration > 0) ? _rDuration : 0;
706 setYearly_(rYearlyMonth, type, _rFreq, _rDuration); 706 setYearly_(rYearlyMonth, type, _rFreq, _rDuration);
707} 707}
708 708
709void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, const QDate &_rEndDate) 709void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, const QDate &_rEndDate)
710{ 710{
711 if (mRecurReadOnly) return; 711 if (mRecurReadOnly) return;
712 rEndDateTime.setDate(_rEndDate); 712 rEndDateTime.setDate(_rEndDate);
713 rEndDateTime.setTime(mRecurStart.time()); 713 rEndDateTime.setTime(mRecurStart.time());
714 mCompatDuration = 0; 714 mCompatDuration = 0;
715 setYearly_(rYearlyMonth, type, _rFreq, 0); 715 setYearly_(rYearlyMonth, type, _rFreq, 0);
716} 716}
717 717
718void Recurrence::addYearlyMonthPos(short _rPos, const QBitArray &_rDays) 718void Recurrence::addYearlyMonthPos(short _rPos, const QBitArray &_rDays)
719{ 719{
720 if (recurs == rYearlyPos) 720 if (recurs == rYearlyPos)
721 addMonthlyPos_(_rPos, _rDays); 721 addMonthlyPos_(_rPos, _rDays);
722} 722}
723 723
724const QPtrList<int> &Recurrence::yearNums() const 724const QPtrList<int> &Recurrence::yearNums() const
725{ 725{
726 return rYearNums; 726 return rYearNums;
727} 727}
728 728void Recurrence::addYearlyMonth(short _rPos )
729{
730 if (mRecurReadOnly || recurs != rYearlyMonth) // invalid day/month number
731 return;
732 rMonthPos *tmpPos = new rMonthPos;
733 if ( _rPos > 0) {
734 tmpPos->rPos = _rPos;
735 tmpPos->negative = false;
736 } else {
737 tmpPos->rPos = -_rPos; // take abs()
738 tmpPos->negative = true;
739 }
740 rMonthPositions.append(tmpPos);
741}
729void Recurrence::addYearlyNum(short _rNum) 742void Recurrence::addYearlyNum(short _rNum)
730{ 743{
731 if (mRecurReadOnly 744 if (mRecurReadOnly
732 || (recurs != rYearlyMonth && recurs != rYearlyDay && recurs != rYearlyPos) 745 || (recurs != rYearlyMonth && recurs != rYearlyDay && recurs != rYearlyPos)
733 || _rNum <= 0) // invalid day/month number 746 || _rNum <= 0) // invalid day/month number
734 return; 747 return;
735 748
736 if (mCompatVersion < 310 && mCompatRecurs == rYearlyDay) { 749 if (mCompatVersion < 310 && mCompatRecurs == rYearlyDay) {
737 // Backwards compatibility for KDE < 3.1. 750 // Backwards compatibility for KDE < 3.1.
738 // Dates were stored as day numbers, with a fiddle to take account of leap years. 751 // Dates were stored as day numbers, with a fiddle to take account of leap years.
739 // Convert the day number to a month. 752 // Convert the day number to a month.
740 if (_rNum <= 0 || _rNum > 366 || (_rNum == 366 && mRecurStart.date().daysInYear() < 366)) 753 if (_rNum <= 0 || _rNum > 366 || (_rNum == 366 && mRecurStart.date().daysInYear() < 366))
741 return; // invalid day number 754 return; // invalid day number
742 _rNum = QDate(mRecurStart.date().year(), 1, 1).addDays(_rNum - 1).month(); 755 _rNum = QDate(mRecurStart.date().year(), 1, 1).addDays(_rNum - 1).month();
743 } else 756 } else
744 if ((recurs == rYearlyMonth || recurs == rYearlyPos) && _rNum > 12 757 if ((recurs == rYearlyMonth || recurs == rYearlyPos) && _rNum > 12
745 || recurs == rYearlyDay && _rNum > 366) 758 || recurs == rYearlyDay && _rNum > 366)
746 return; // invalid day number 759 return; // invalid day number
747 760
748 uint i = 0; 761 uint i = 0;
749 for (int* it = rYearNums.first(); it && _rNum >= *it; it = rYearNums.next()) { 762 for (int* it = rYearNums.first(); it && _rNum >= *it; it = rYearNums.next()) {
750 if (_rNum == *it) 763 if (_rNum == *it)
751 return; // this day/month is already in the list - avoid duplication 764 return; // this day/month is already in the list - avoid duplication
752 ++i; 765 ++i;
753 } 766 }
754 767
755 int *tmpNum = new int; 768 int *tmpNum = new int;
756 *tmpNum = _rNum; 769 *tmpNum = _rNum;
757 rYearNums.insert(i, tmpNum); // insert the day/month in a sorted position 770 rYearNums.insert(i, tmpNum); // insert the day/month in a sorted position
758 771
759 if (mCompatVersion < 310 && mCompatDuration > 0) { 772 if (mCompatVersion < 310 && mCompatDuration > 0) {
760 // Backwards compatibility for KDE < 3.1. 773 // Backwards compatibility for KDE < 3.1.
761 // rDuration was set to the number of time periods to recur. 774 // rDuration was set to the number of time periods to recur.
762 // Convert this to the number of occurrences. 775 // Convert this to the number of occurrences.
763 QDate end(mRecurStart.date().year() + (mCompatDuration-1+mRecurExDatesCount)*rFreq, 12, 31); 776 QDate end(mRecurStart.date().year() + (mCompatDuration-1+mRecurExDatesCount)*rFreq, 12, 31);
764 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly 777 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly
765 rDuration = recurCalc(COUNT_TO_DATE, end); 778 rDuration = recurCalc(COUNT_TO_DATE, end);
766 } 779 }
767 780
768 if (mParent) mParent->updated(); 781 if (mParent) mParent->updated();
769} 782}
770 783
771 784
772QDateTime Recurrence::getNextDateTime(const QDateTime &preDateTime, bool *last) const 785QDateTime Recurrence::getNextDateTime(const QDateTime &preDateTime, bool *last) const
773{ 786{
774 if (last) 787 if (last)
775 *last = false; 788 *last = false;
776 int freq; 789 int freq;
777 switch (recurs) 790 switch (recurs)
778 { 791 {
779 case rMinutely: 792 case rMinutely:
780 freq = rFreq * 60; 793 freq = rFreq * 60;
781 break; 794 break;
782 case rHourly: 795 case rHourly:
783 freq = rFreq * 3600; 796 freq = rFreq * 3600;
784 break; 797 break;
785 case rDaily: 798 case rDaily:
786 case rWeekly: 799 case rWeekly:
787 case rMonthlyPos: 800 case rMonthlyPos:
788 case rMonthlyDay: 801 case rMonthlyDay:
789 case rYearlyMonth: 802 case rYearlyMonth:
790 case rYearlyDay: 803 case rYearlyDay:
791 case rYearlyPos: { 804 case rYearlyPos: {
792 QDate preDate = preDateTime.date(); 805 QDate preDate = preDateTime.date();
793 if (!mFloats && mRecurStart.time() > preDateTime.time()) 806 if (!mFloats && mRecurStart.time() > preDateTime.time())
794 preDate = preDate.addDays(-1); 807 preDate = preDate.addDays(-1);
795 return QDateTime(getNextDateNoTime(preDate, last), mRecurStart.time()); 808 return QDateTime(getNextDateNoTime(preDate, last), mRecurStart.time());
796 } 809 }
797 default: 810 default:
798 return QDateTime(); 811 return QDateTime();
799 } 812 }
800 813
801 // It's a sub-daily recurrence 814 // It's a sub-daily recurrence
802 if (preDateTime < mRecurStart) 815 if (preDateTime < mRecurStart)
803 return mRecurStart; 816 return mRecurStart;
804 int count = mRecurStart.secsTo(preDateTime) / freq + 2; 817 int count = mRecurStart.secsTo(preDateTime) / freq + 2;
805 if (rDuration > 0) { 818 if (rDuration > 0) {
806 if (count > rDuration) 819 if (count > rDuration)
807 return QDateTime(); 820 return QDateTime();
808 if (last && count == rDuration) 821 if (last && count == rDuration)
809 *last = true; 822 *last = true;
810 } 823 }
811 QDateTime endtime = mRecurStart.addSecs((count - 1)*freq); 824 QDateTime endtime = mRecurStart.addSecs((count - 1)*freq);
812 if (rDuration == 0) { 825 if (rDuration == 0) {
813 if (endtime > rEndDateTime) 826 if (endtime > rEndDateTime)
814 return QDateTime(); 827 return QDateTime();
815 if (last && endtime == rEndDateTime) 828 if (last && endtime == rEndDateTime)
816 *last = true; 829 *last = true;
817 } 830 }
818 return endtime; 831 return endtime;
819} 832}
820 833
821QDate Recurrence::getNextDate(const QDate &preDate, bool *last) const 834QDate Recurrence::getNextDate(const QDate &preDate, bool *last) const
822{ 835{
823 if (last) 836 if (last)
824 *last = false; 837 *last = false;
825 switch (recurs) 838 switch (recurs)
826 { 839 {
827 case rMinutely: 840 case rMinutely:
828 case rHourly: 841 case rHourly:
829 return getNextDateTime(QDateTime(preDate, QTime(23,59,59)), last).date(); 842 return getNextDateTime(QDateTime(preDate, QTime(23,59,59)), last).date();
830 case rDaily: 843 case rDaily:
831 case rWeekly: 844 case rWeekly:
832 case rMonthlyPos: 845 case rMonthlyPos:
833 case rMonthlyDay: 846 case rMonthlyDay:
834 case rYearlyMonth: 847 case rYearlyMonth:
835 case rYearlyDay: 848 case rYearlyDay:
836 case rYearlyPos: 849 case rYearlyPos:
837 return getNextDateNoTime(preDate, last); 850 return getNextDateNoTime(preDate, last);
838 default: 851 default:
839 return QDate(); 852 return QDate();
840 } 853 }
841} 854}
842 855
843 856
844QDateTime Recurrence::getPreviousDateTime(const QDateTime &afterDateTime, bool *last) const 857QDateTime Recurrence::getPreviousDateTime(const QDateTime &afterDateTime, bool *last) const
845{ 858{
846 if (last) 859 if (last)
847 *last = false; 860 *last = false;
848 int freq; 861 int freq;
849 switch (recurs) 862 switch (recurs)
850 { 863 {
851 case rMinutely: 864 case rMinutely:
852 freq = rFreq * 60; 865 freq = rFreq * 60;
853 break; 866 break;
854 case rHourly: 867 case rHourly:
855 freq = rFreq * 3600; 868 freq = rFreq * 3600;
856 break; 869 break;
857 case rDaily: 870 case rDaily:
858 case rWeekly: 871 case rWeekly:
859 case rMonthlyPos: 872 case rMonthlyPos:
860 case rMonthlyDay: 873 case rMonthlyDay:
861 case rYearlyMonth: 874 case rYearlyMonth:
862 case rYearlyDay: 875 case rYearlyDay:
863 case rYearlyPos: { 876 case rYearlyPos: {
864 QDate afterDate = afterDateTime.date(); 877 QDate afterDate = afterDateTime.date();
865 if (!mFloats && mRecurStart.time() < afterDateTime.time()) 878 if (!mFloats && mRecurStart.time() < afterDateTime.time())
866 afterDate = afterDate.addDays(1); 879 afterDate = afterDate.addDays(1);
867 return QDateTime(getPreviousDateNoTime(afterDate, last), mRecurStart.time()); 880 return QDateTime(getPreviousDateNoTime(afterDate, last), mRecurStart.time());
868 } 881 }
869 default: 882 default:
870 return QDateTime(); 883 return QDateTime();
871 } 884 }
872 885
873 // It's a sub-daily recurrence 886 // It's a sub-daily recurrence
874 if (afterDateTime <= mRecurStart) 887 if (afterDateTime <= mRecurStart)
875 return QDateTime(); 888 return QDateTime();
876 int count = (mRecurStart.secsTo(afterDateTime) - 1) / freq + 1; 889 int count = (mRecurStart.secsTo(afterDateTime) - 1) / freq + 1;
877 if (rDuration > 0) { 890 if (rDuration > 0) {
878 if (count > rDuration) 891 if (count > rDuration)
879 count = rDuration; 892 count = rDuration;
880 if (last && count == rDuration) 893 if (last && count == rDuration)
881 *last = true; 894 *last = true;
882 } 895 }
883 QDateTime endtime = mRecurStart.addSecs((count - 1)*freq); 896 QDateTime endtime = mRecurStart.addSecs((count - 1)*freq);
884 if (rDuration == 0) { 897 if (rDuration == 0) {
885 if (endtime > rEndDateTime) 898 if (endtime > rEndDateTime)
886 endtime = rEndDateTime; 899 endtime = rEndDateTime;
887 if (last && endtime == rEndDateTime) 900 if (last && endtime == rEndDateTime)
888 *last = true; 901 *last = true;
889 } 902 }
890 return endtime; 903 return endtime;
891} 904}
892 905
893QDate Recurrence::getPreviousDate(const QDate &afterDate, bool *last) const 906QDate Recurrence::getPreviousDate(const QDate &afterDate, bool *last) const
894{ 907{
895 if (last) 908 if (last)
896 *last = false; 909 *last = false;
897 switch (recurs) 910 switch (recurs)
898 { 911 {
899 case rMinutely: 912 case rMinutely:
900 case rHourly: 913 case rHourly:
901 return getPreviousDateTime(QDateTime(afterDate, QTime(0,0,0)), last).date(); 914 return getPreviousDateTime(QDateTime(afterDate, QTime(0,0,0)), last).date();
902 case rDaily: 915 case rDaily:
903 case rWeekly: 916 case rWeekly:
904 case rMonthlyPos: 917 case rMonthlyPos:
905 case rMonthlyDay: 918 case rMonthlyDay:
906 case rYearlyMonth: 919 case rYearlyMonth:
907 case rYearlyDay: 920 case rYearlyDay:
908 case rYearlyPos: 921 case rYearlyPos:
909 return getPreviousDateNoTime(afterDate, last); 922 return getPreviousDateNoTime(afterDate, last);
910 default: 923 default:
911 return QDate(); 924 return QDate();
912 } 925 }
913} 926}
914 927
915 928
916/***************************** PROTECTED FUNCTIONS ***************************/ 929/***************************** PROTECTED FUNCTIONS ***************************/
917 930
918bool Recurrence::recursSecondly(const QDate &qd, int secondFreq) const 931bool Recurrence::recursSecondly(const QDate &qd, int secondFreq) const
919{ 932{
920 if ((qd >= mRecurStart.date()) && 933 if ((qd >= mRecurStart.date()) &&
921 ((rDuration > 0) && (qd <= endDate()) || 934 ((rDuration > 0) && (qd <= endDate()) ||
922 ((rDuration == 0) && (qd <= rEndDateTime.date())) || 935 ((rDuration == 0) && (qd <= rEndDateTime.date())) ||
923 (rDuration == -1))) { 936 (rDuration == -1))) {
924 // The date queried falls within the range of the event. 937 // The date queried falls within the range of the event.
925 if (secondFreq < 24*3600) 938 if (secondFreq < 24*3600)
926 return true; // the event recurs at least once each day 939 return true; // the event recurs at least once each day
927 int after = mRecurStart.secsTo(QDateTime(qd)); 940 int after = mRecurStart.secsTo(QDateTime(qd));
928 if (after / secondFreq != (after + 24*3600) / secondFreq) 941 if (after / secondFreq != (after + 24*3600) / secondFreq)
929 return true; 942 return true;
930 } 943 }
931 return false; 944 return false;
932} 945}
933 946
934bool Recurrence::recursMinutelyAt(const QDateTime &dt, int minuteFreq) const 947bool Recurrence::recursMinutelyAt(const QDateTime &dt, int minuteFreq) const
935{ 948{
936 if ((dt >= mRecurStart) && 949 if ((dt >= mRecurStart) &&
937 ((rDuration > 0) && (dt <= endDateTime()) || 950 ((rDuration > 0) && (dt <= endDateTime()) ||
938 ((rDuration == 0) && (dt <= rEndDateTime)) || 951 ((rDuration == 0) && (dt <= rEndDateTime)) ||
939 (rDuration == -1))) { 952 (rDuration == -1))) {
940 // The time queried falls within the range of the event. 953 // The time queried falls within the range of the event.
941 if (((mRecurStart.secsTo(dt) / 60) % minuteFreq) == 0) 954 if (((mRecurStart.secsTo(dt) / 60) % minuteFreq) == 0)
942 return true; 955 return true;
943 } 956 }
944 return false; 957 return false;
945} 958}
946 959
947bool Recurrence::recursDaily(const QDate &qd) const 960bool Recurrence::recursDaily(const QDate &qd) const
948{ 961{
949 QDate dStart = mRecurStart.date(); 962 QDate dStart = mRecurStart.date();
950 if ((dStart.daysTo(qd) % rFreq) == 0) { 963 if ((dStart.daysTo(qd) % rFreq) == 0) {
951 // The date is a day which recurs 964 // The date is a day which recurs
952 if (qd >= dStart 965 if (qd >= dStart
953 && ((rDuration > 0 && qd <= endDate()) || 966 && ((rDuration > 0 && qd <= endDate()) ||
954 (rDuration == 0 && qd <= rEndDateTime.date()) || 967 (rDuration == 0 && qd <= rEndDateTime.date()) ||
955 rDuration == -1)) { 968 rDuration == -1)) {
956 // The date queried falls within the range of the event. 969 // The date queried falls within the range of the event.
957 return true; 970 return true;
958 } 971 }
959 } 972 }
960 return false; 973 return false;
961} 974}
962 975
963bool Recurrence::recursWeekly(const QDate &qd) const 976bool Recurrence::recursWeekly(const QDate &qd) const
964{ 977{
965 QDate dStart = mRecurStart.date(); 978 QDate dStart = mRecurStart.date();
966 if ((dStart.daysTo(qd)/7) % rFreq == 0) { 979 if ((dStart.daysTo(qd)/7) % rFreq == 0) {
967 // The date is in a week which recurs 980 // The date is in a week which recurs
968 if (qd >= dStart 981 if (qd >= dStart
969 && ((rDuration > 0 && qd <= endDate()) || 982 && ((rDuration > 0 && qd <= endDate()) ||
970 (rDuration == 0 && qd <= rEndDateTime.date()) || 983 (rDuration == 0 && qd <= rEndDateTime.date()) ||
971 rDuration == -1)) { 984 rDuration == -1)) {
972 // The date queried falls within the range of the event. 985 // The date queried falls within the range of the event.
973 // check if the bits set match today. 986 // check if the bits set match today.
974 int i = qd.dayOfWeek()-1; 987 int i = qd.dayOfWeek()-1;
975 if (rDays.testBit((uint) i)) 988 if (rDays.testBit((uint) i))
976 return true; 989 return true;
977 } 990 }
978 } 991 }
979 return false; 992 return false;
980} 993}
981 994
982bool Recurrence::recursMonthly(const QDate &qd) const 995bool Recurrence::recursMonthly(const QDate &qd) const
983{ 996{
984 QDate dStart = mRecurStart.date(); 997 QDate dStart = mRecurStart.date();
985 int year = qd.year(); 998 int year = qd.year();
986 int month = qd.month(); 999 int month = qd.month();
987 int day = qd.day(); 1000 int day = qd.day();
988 // calculate how many months ahead this date is from the original 1001 // calculate how many months ahead this date is from the original
989 // event's date 1002 // event's date
990 int monthsAhead = (year - dStart.year()) * 12 + (month - dStart.month()); 1003 int monthsAhead = (year - dStart.year()) * 12 + (month - dStart.month());
991 if ((monthsAhead % rFreq) == 0) { 1004 if ((monthsAhead % rFreq) == 0) {
992 // The date is in a month which recurs 1005 // The date is in a month which recurs
993 if (qd >= dStart 1006 if (qd >= dStart
994 && ((rDuration > 0 && qd <= endDate()) || 1007 && ((rDuration > 0 && qd <= endDate()) ||
995 (rDuration == 0 && qd <= rEndDateTime.date()) || 1008 (rDuration == 0 && qd <= rEndDateTime.date()) ||
996 rDuration == -1)) { 1009 rDuration == -1)) {
997 // The date queried falls within the range of the event. 1010 // The date queried falls within the range of the event.
998 QValueList<int> days; 1011 QValueList<int> days;
999 int daysInMonth = qd.daysInMonth(); 1012 int daysInMonth = qd.daysInMonth();
1000 if (recurs == rMonthlyDay) 1013 if (recurs == rMonthlyDay)
1001 getMonthlyDayDays(days, daysInMonth); 1014 getMonthlyDayDays(days, daysInMonth);
1002 else if (recurs == rMonthlyPos) 1015 else if (recurs == rMonthlyPos)
1003 getMonthlyPosDays(days, daysInMonth, QDate(year, month, 1).dayOfWeek()); 1016 getMonthlyPosDays(days, daysInMonth, QDate(year, month, 1).dayOfWeek());
1004 for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) { 1017 for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) {
1005 if (*it == day) 1018 if (*it == day)
1006 return true; 1019 return true;
1007 } 1020 }
1008 // no dates matched 1021 // no dates matched
1009 } 1022 }
1010 } 1023 }
1011 return false; 1024 return false;
1012} 1025}
1013 1026
1014bool Recurrence::recursYearlyByMonth(const QDate &qd) const 1027bool Recurrence::recursYearlyByMonth(const QDate &qd) const
1015{ 1028{
1016 QDate dStart = mRecurStart.date(); 1029 QDate dStart = mRecurStart.date();
1017 int startDay = dStart.day(); 1030 int startDay = dStart.day();
1018 int qday = qd.day(); 1031 int qday = qd.day();
1019 int qmonth = qd.month(); 1032 int qmonth = qd.month();
1020 int qyear = qd.year(); 1033 int qyear = qd.year();
1021 bool match = (qday == startDay); 1034 bool match = (qday == startDay);
1022 if (!match && startDay == 29 && dStart.month() == 2) { 1035 if (!match && startDay == 29 && dStart.month() == 2) {
1023 // It's a recurrence on February 29th 1036 // It's a recurrence on February 29th
1024 switch (mFeb29YearlyType) { 1037 switch (mFeb29YearlyType) {
1025 case rFeb28: 1038 case rFeb28:
1026 if (qday == 28 && qmonth == 2 && !QDate::leapYear(qyear)) 1039 if (qday == 28 && qmonth == 2 && !QDate::leapYear(qyear))
1027 match = true; 1040 match = true;
1028 break; 1041 break;
1029 case rMar1: 1042 case rMar1:
1030 if (qday == 1 && qmonth == 3 && !QDate::leapYear(qyear)) { 1043 if (qday == 1 && qmonth == 3 && !QDate::leapYear(qyear)) {
1031 qmonth = 2; 1044 qmonth = 2;
1032 match = true; 1045 match = true;
1033 } 1046 }
1034 break; 1047 break;
1035 case rFeb29: 1048 case rFeb29:
1036 break; 1049 break;
1037 } 1050 }
1038 } 1051 }
1039 1052
1040 if (match) { 1053 if (match) {
1041 // The day of the month matches. Calculate how many years ahead 1054 // The day of the month matches. Calculate how many years ahead
1042 // this date is from the original event's date. 1055 // this date is from the original event's date.
1043 int yearsAhead = (qyear - dStart.year()); 1056 int yearsAhead = (qyear - dStart.year());
1044 if (yearsAhead % rFreq == 0) { 1057 if (yearsAhead % rFreq == 0) {
1045 // The date is in a year which recurs 1058 // The date is in a year which recurs
1046 if (qd >= dStart 1059 if (qd >= dStart
1047 && ((rDuration > 0 && qd <= endDate()) || 1060 && ((rDuration > 0 && qd <= endDate()) ||
1048 (rDuration == 0 && qd <= rEndDateTime.date()) || 1061 (rDuration == 0 && qd <= rEndDateTime.date()) ||
1049 rDuration == -1)) { 1062 rDuration == -1)) {
1050 // The date queried falls within the range of the event. 1063 // The date queried falls within the range of the event.
1051 int i = qmonth; 1064 int i = qmonth;
1052 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) { 1065 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) {
1053 if (i == *qlin.current()) 1066 if (i == *qlin.current())
1054 return true; 1067 return true;
1055 } 1068 }
1056 } 1069 }
1057 } 1070 }
1058 } 1071 }
1059 return false; 1072 return false;
1060} 1073}
1061 1074
1062bool Recurrence::recursYearlyByPos(const QDate &qd) const 1075bool Recurrence::recursYearlyByPos(const QDate &qd) const
1063{ 1076{
1064 QDate dStart = mRecurStart.date(); 1077 QDate dStart = mRecurStart.date();
1065 int year = qd.year(); 1078 int year = qd.year();
1066 int month = qd.month(); 1079 int month = qd.month();
1067 int day = qd.day(); 1080 int day = qd.day();
1068 // calculate how many years ahead this date is from the original 1081 // calculate how many years ahead this date is from the original
1069 // event's date 1082 // event's date
1070 int yearsAhead = (year - dStart.year()); 1083 int yearsAhead = (year - dStart.year());
1071 if (yearsAhead % rFreq == 0) { 1084 if (yearsAhead % rFreq == 0) {
1072 // The date is in a year which recurs 1085 // The date is in a year which recurs
1073 if (qd >= dStart 1086 if (qd >= dStart
1074 && ((rDuration > 0 && qd <= endDate()) || 1087 && ((rDuration > 0 && qd <= endDate()) ||
1075 (rDuration == 0 && qd <= rEndDateTime.date()) || 1088 (rDuration == 0 && qd <= rEndDateTime.date()) ||
1076 rDuration == -1)) { 1089 rDuration == -1)) {
1077 // The date queried falls within the range of the event. 1090 // The date queried falls within the range of the event.
1078 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) { 1091 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) {
1079 if (month == *qlin.current()) { 1092 if (month == *qlin.current()) {
1080 // The month recurs 1093 // The month recurs
1081 QValueList<int> days; 1094 QValueList<int> days;
1082 getMonthlyPosDays(days, qd.daysInMonth(), QDate(year, month, 1).dayOfWeek()); 1095 getMonthlyPosDays(days, qd.daysInMonth(), QDate(year, month, 1).dayOfWeek());
1083 for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) { 1096 for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) {
1084 if (*it == day) 1097 if (*it == day)
1085 return true; 1098 return true;
1086 } 1099 }
1087 } 1100 }
1088 } 1101 }
1089 } 1102 }
1090 } 1103 }
1091 return false; 1104 return false;
1092} 1105}
1093 1106
1094bool Recurrence::recursYearlyByDay(const QDate &qd) const 1107bool Recurrence::recursYearlyByDay(const QDate &qd) const
1095{ 1108{
1096 QDate dStart = mRecurStart.date(); 1109 QDate dStart = mRecurStart.date();
1097 // calculate how many years ahead this date is from the original 1110 // calculate how many years ahead this date is from the original
1098 // event's date 1111 // event's date
1099 int yearsAhead = (qd.year() - dStart.year()); 1112 int yearsAhead = (qd.year() - dStart.year());
1100 if (yearsAhead % rFreq == 0) { 1113 if (yearsAhead % rFreq == 0) {
1101 // The date is in a year which recurs 1114 // The date is in a year which recurs
1102 if (qd >= dStart 1115 if (qd >= dStart
1103 && ((rDuration > 0 && qd <= endDate()) || 1116 && ((rDuration > 0 && qd <= endDate()) ||
1104 (rDuration == 0 && qd <= rEndDateTime.date()) || 1117 (rDuration == 0 && qd <= rEndDateTime.date()) ||
1105 rDuration == -1)) { 1118 rDuration == -1)) {
1106 // The date queried falls within the range of the event. 1119 // The date queried falls within the range of the event.
1107 int i = qd.dayOfYear(); 1120 int i = qd.dayOfYear();
1108 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) { 1121 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) {
1109 if (i == *qlin.current()) 1122 if (i == *qlin.current())
1110 return true; 1123 return true;
1111 } 1124 }
1112 } 1125 }
1113 } 1126 }
1114 return false; 1127 return false;
1115} 1128}
1116 1129
1117/* Get the date of the next recurrence, after the specified date. 1130/* Get the date of the next recurrence, after the specified date.
1118 * If 'last' is non-null, '*last' is set to true if the next recurrence is the 1131 * If 'last' is non-null, '*last' is set to true if the next recurrence is the
1119 * last recurrence, else false. 1132 * last recurrence, else false.
1120 * Reply = date of next recurrence, or invalid date if none. 1133 * Reply = date of next recurrence, or invalid date if none.
1121 */ 1134 */
1122QDate Recurrence::getNextDateNoTime(const QDate &preDate, bool *last) const 1135QDate Recurrence::getNextDateNoTime(const QDate &preDate, bool *last) const
1123{ 1136{
1124 if (last) 1137 if (last)
1125 *last = false; 1138 *last = false;
1126 QDate dStart = mRecurStart.date(); 1139 QDate dStart = mRecurStart.date();
1127 if (preDate < dStart) 1140 if (preDate < dStart)
1128 return dStart; 1141 return dStart;
1129 QDate earliestDate = preDate.addDays(1); 1142 QDate earliestDate = preDate.addDays(1);
1130 QDate nextDate; 1143 QDate nextDate;
1131 1144
1132 switch (recurs) { 1145 switch (recurs) {
1133 case rDaily: 1146 case rDaily:
1134 nextDate = dStart.addDays((dStart.daysTo(preDate)/rFreq + 1) * rFreq); 1147 nextDate = dStart.addDays((dStart.daysTo(preDate)/rFreq + 1) * rFreq);
1135 break; 1148 break;
1136 1149
1137 case rWeekly: { 1150 case rWeekly: {
1138 QDate start = dStart.addDays(1 - dStart.dayOfWeek()); // start of week for dStart 1151 QDate start = dStart.addDays(1 - dStart.dayOfWeek()); // start of week for dStart
1139 int earliestDayOfWeek = earliestDate.dayOfWeek(); 1152 int earliestDayOfWeek = earliestDate.dayOfWeek();
1140 int weeksAhead = start.daysTo(earliestDate) / 7; 1153 int weeksAhead = start.daysTo(earliestDate) / 7;
1141 int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week 1154 int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week
1142 weeksAhead -= notThisWeek; // latest week which recurred 1155 weeksAhead -= notThisWeek; // latest week which recurred
1143 int weekday = 0; 1156 int weekday = 0;
1144 // First check for any remaining day this week, if this week is a recurring week 1157 // First check for any remaining day this week, if this week is a recurring week
1145 if (!notThisWeek) 1158 if (!notThisWeek)
1146 weekday = getFirstDayInWeek(earliestDayOfWeek); 1159 weekday = getFirstDayInWeek(earliestDayOfWeek);
1147 // Check for a day in the next scheduled week 1160 // Check for a day in the next scheduled week
1148 if (!weekday && earliestDayOfWeek > 1) 1161 if (!weekday && earliestDayOfWeek > 1)
1149 weekday = getFirstDayInWeek(rWeekStart) + rFreq*7; 1162 weekday = getFirstDayInWeek(rWeekStart) + rFreq*7;
1150 if (weekday) 1163 if (weekday)
1151 nextDate = start.addDays(weeksAhead*7 + weekday - 1); 1164 nextDate = start.addDays(weeksAhead*7 + weekday - 1);
1152 break; 1165 break;
1153 } 1166 }
1154 case rMonthlyDay: 1167 case rMonthlyDay:
1155 case rMonthlyPos: { 1168 case rMonthlyPos: {
1156 int startYear = dStart.year(); 1169 int startYear = dStart.year();
1157 int startMonth = dStart.month(); // 1..12 1170 int startMonth = dStart.month(); // 1..12
1158 int earliestYear = earliestDate.year(); 1171 int earliestYear = earliestDate.year();
1159 int monthsAhead = (earliestYear - startYear)*12 + earliestDate.month() - startMonth; 1172 int monthsAhead = (earliestYear - startYear)*12 + earliestDate.month() - startMonth;
1160 int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month 1173 int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month
1161 monthsAhead -= notThisMonth; // latest month which recurred 1174 monthsAhead -= notThisMonth; // latest month which recurred
1162 // Check for the first later day in the current month 1175 // Check for the first later day in the current month
1163 if (!notThisMonth) 1176 if (!notThisMonth)
1164 nextDate = getFirstDateInMonth(earliestDate); 1177 nextDate = getFirstDateInMonth(earliestDate);
1165 if (!nextDate.isValid() && earliestDate.day() > 1) { 1178 if (!nextDate.isValid() && earliestDate.day() > 1) {
1166 // Check for a day in the next scheduled month 1179 // Check for a day in the next scheduled month
1167 int months = startMonth - 1 + monthsAhead + rFreq; 1180 int months = startMonth - 1 + monthsAhead + rFreq;
1168 nextDate = getFirstDateInMonth(QDate(startYear + months/12, months%12 + 1, 1)); 1181 nextDate = getFirstDateInMonth(QDate(startYear + months/12, months%12 + 1, 1));
1169 } 1182 }
1170 break; 1183 break;
1171 } 1184 }
1172 case rYearlyMonth: 1185 case rYearlyMonth:
1173 case rYearlyPos: 1186 case rYearlyPos:
1174 case rYearlyDay: { 1187 case rYearlyDay: {
1175 int startYear = dStart.year(); 1188 int startYear = dStart.year();
1176 int yearsAhead = earliestDate.year() - startYear; 1189 int yearsAhead = earliestDate.year() - startYear;
1177 int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year 1190 int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year
1178 yearsAhead -= notThisYear; // latest year which recurred 1191 yearsAhead -= notThisYear; // latest year which recurred
1179 // Check for the first later date in the current year 1192 // Check for the first later date in the current year
1180 if (!notThisYear) 1193 if (!notThisYear)
1181 nextDate = getFirstDateInYear(earliestDate); 1194 nextDate = getFirstDateInYear(earliestDate);
1182 // Check for a date in the next scheduled year 1195 // Check for a date in the next scheduled year
1183 if (!nextDate.isValid() && earliestDate.dayOfYear() > 1) 1196 if (!nextDate.isValid() && earliestDate.dayOfYear() > 1)
1184 nextDate = getFirstDateInYear(QDate(startYear + yearsAhead + rFreq, 1, 1)); 1197 nextDate = getFirstDateInYear(QDate(startYear + yearsAhead + rFreq, 1, 1));
1185 break; 1198 break;
1186 } 1199 }
1187 case rNone: 1200 case rNone:
1188 default: 1201 default:
1189 return QDate(); 1202 return QDate();
1190 } 1203 }
1191 1204
1192 if (rDuration >= 0 && nextDate.isValid()) { 1205 if (rDuration >= 0 && nextDate.isValid()) {
1193 // Check that the date found is within the range of the recurrence 1206 // Check that the date found is within the range of the recurrence
1194 QDate end = endDate(); 1207 QDate end = endDate();
1195 if (nextDate > end) 1208 if (nextDate > end)
1196 return QDate(); 1209 return QDate();
1197 if (last && nextDate == end) 1210 if (last && nextDate == end)
1198 *last = true; 1211 *last = true;
1199 } 1212 }
1200 return nextDate; 1213 return nextDate;
1201} 1214}
1202 1215
1203/* Get the date of the last previous recurrence, before the specified date. 1216/* Get the date of the last previous recurrence, before the specified date.
1204 * Reply = date of previous recurrence, or invalid date if none. 1217 * Reply = date of previous recurrence, or invalid date if none.
1205 */ 1218 */
1206QDate Recurrence::getPreviousDateNoTime(const QDate &afterDate, bool *last) const 1219QDate Recurrence::getPreviousDateNoTime(const QDate &afterDate, bool *last) const
1207{ 1220{
1208 if (last) 1221 if (last)
1209 *last = false; 1222 *last = false;
1210 QDate dStart = mRecurStart.date(); 1223 QDate dStart = mRecurStart.date();
1211 QDate latestDate = afterDate.addDays(-1); 1224 QDate latestDate = afterDate.addDays(-1);
1212 if (latestDate < dStart) 1225 if (latestDate < dStart)
1213 return QDate(); 1226 return QDate();
1214 QDate prevDate; 1227 QDate prevDate;
1215 1228
1216 switch (recurs) { 1229 switch (recurs) {
1217 case rDaily: 1230 case rDaily:
1218 prevDate = dStart.addDays((dStart.daysTo(latestDate) / rFreq) * rFreq); 1231 prevDate = dStart.addDays((dStart.daysTo(latestDate) / rFreq) * rFreq);
1219 break; 1232 break;
1220 1233
1221 case rWeekly: { 1234 case rWeekly: {
1222 QDate start = dStart.addDays(1 - dStart.dayOfWeek()); // start of week for dStart 1235 QDate start = dStart.addDays(1 - dStart.dayOfWeek()); // start of week for dStart
1223 int latestDayOfWeek = latestDate.dayOfWeek(); 1236 int latestDayOfWeek = latestDate.dayOfWeek();
1224 int weeksAhead = start.daysTo(latestDate) / 7; 1237 int weeksAhead = start.daysTo(latestDate) / 7;
1225 int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week 1238 int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week
1226 weeksAhead -= notThisWeek; // latest week which recurred 1239 weeksAhead -= notThisWeek; // latest week which recurred
1227 int weekday = 0; 1240 int weekday = 0;
1228 // First check for any previous day this week, if this week is a recurring week 1241 // First check for any previous day this week, if this week is a recurring week
1229 if (!notThisWeek) 1242 if (!notThisWeek)
1230 weekday = getLastDayInWeek(latestDayOfWeek); 1243 weekday = getLastDayInWeek(latestDayOfWeek);
1231 // Check for a day in the previous scheduled week 1244 // Check for a day in the previous scheduled week
1232 if (!weekday) { 1245 if (!weekday) {
1233 int weekEnd = (rWeekStart + 5)%7 + 1; 1246 int weekEnd = (rWeekStart + 5)%7 + 1;
1234 if (latestDayOfWeek < weekEnd) { 1247 if (latestDayOfWeek < weekEnd) {
1235 if (!notThisWeek) 1248 if (!notThisWeek)
1236 weeksAhead -= rFreq; 1249 weeksAhead -= rFreq;
1237 weekday = getLastDayInWeek(weekEnd); 1250 weekday = getLastDayInWeek(weekEnd);
1238 } 1251 }
1239 } 1252 }
1240 if (weekday) 1253 if (weekday)
1241 prevDate = start.addDays(weeksAhead*7 + weekday - 1); 1254 prevDate = start.addDays(weeksAhead*7 + weekday - 1);
1242 break; 1255 break;
1243 } 1256 }
1244 case rMonthlyDay: 1257 case rMonthlyDay:
1245 case rMonthlyPos: { 1258 case rMonthlyPos: {
1246 int startYear = dStart.year(); 1259 int startYear = dStart.year();
1247 int startMonth = dStart.month(); // 1..12 1260 int startMonth = dStart.month(); // 1..12
1248 int latestYear = latestDate.year(); 1261 int latestYear = latestDate.year();
1249 int monthsAhead = (latestYear - startYear)*12 + latestDate.month() - startMonth; 1262 int monthsAhead = (latestYear - startYear)*12 + latestDate.month() - startMonth;
1250 int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month 1263 int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month
1251 monthsAhead -= notThisMonth; // latest month which recurred 1264 monthsAhead -= notThisMonth; // latest month which recurred
1252 // Check for the last earlier day in the current month 1265 // Check for the last earlier day in the current month
1253 if (!notThisMonth) 1266 if (!notThisMonth)
1254 prevDate = getLastDateInMonth(latestDate); 1267 prevDate = getLastDateInMonth(latestDate);
1255 if (!prevDate.isValid() && latestDate.day() < latestDate.daysInMonth()) { 1268 if (!prevDate.isValid() && latestDate.day() < latestDate.daysInMonth()) {
1256 // Check for a day in the previous scheduled month 1269 // Check for a day in the previous scheduled month
1257 if (!notThisMonth) 1270 if (!notThisMonth)
1258 monthsAhead -= rFreq; 1271 monthsAhead -= rFreq;
1259 int months = startMonth + monthsAhead; // get the month after the one that recurs 1272 int months = startMonth + monthsAhead; // get the month after the one that recurs
1260 prevDate = getLastDateInMonth(QDate(startYear + months/12, months%12 + 1, 1).addDays(-1)); 1273 prevDate = getLastDateInMonth(QDate(startYear + months/12, months%12 + 1, 1).addDays(-1));
1261 } 1274 }
1262 break; 1275 break;
1263 } 1276 }
1264 case rYearlyMonth: 1277 case rYearlyMonth:
1265 case rYearlyPos: 1278 case rYearlyPos:
1266 case rYearlyDay: { 1279 case rYearlyDay: {
1267 int startYear = dStart.year(); 1280 int startYear = dStart.year();
1268 int yearsAhead = latestDate.year() - startYear; 1281 int yearsAhead = latestDate.year() - startYear;
1269 int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year 1282 int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year
1270 yearsAhead -= notThisYear; // latest year which recurred 1283 yearsAhead -= notThisYear; // latest year which recurred
1271 // Check for the first later date in the current year 1284 // Check for the first later date in the current year
1272 if (!notThisYear) 1285 if (!notThisYear)
1273 prevDate = getLastDateInYear(latestDate); 1286 prevDate = getLastDateInYear(latestDate);
1274 if (!prevDate.isValid() && latestDate.dayOfYear() < latestDate.daysInYear()) { 1287 if (!prevDate.isValid() && latestDate.dayOfYear() < latestDate.daysInYear()) {
1275 // Check for a date in the next scheduled year 1288 // Check for a date in the next scheduled year
1276 if (!notThisYear) 1289 if (!notThisYear)
1277 yearsAhead -= rFreq; 1290 yearsAhead -= rFreq;
1278 prevDate = getLastDateInYear(QDate(startYear + yearsAhead, 12, 31)); 1291 prevDate = getLastDateInYear(QDate(startYear + yearsAhead, 12, 31));
1279 } 1292 }
1280 break; 1293 break;
1281 } 1294 }
1282 case rNone: 1295 case rNone:
1283 default: 1296 default:
1284 return QDate(); 1297 return QDate();
1285 } 1298 }
1286 1299
1287 if (prevDate.isValid()) { 1300 if (prevDate.isValid()) {
1288 // Check that the date found is within the range of the recurrence 1301 // Check that the date found is within the range of the recurrence
1289 if (prevDate < dStart) 1302 if (prevDate < dStart)
1290 return QDate(); 1303 return QDate();
1291 if (rDuration >= 0) { 1304 if (rDuration >= 0) {
1292 QDate end = endDate(); 1305 QDate end = endDate();
1293 if (prevDate >= end) { 1306 if (prevDate >= end) {
1294 if (last) 1307 if (last)
1295 *last = true; 1308 *last = true;
1296 return end; 1309 return end;
1297 } 1310 }
1298 } 1311 }
1299 } 1312 }
1300 return prevDate; 1313 return prevDate;
1301} 1314}
1302 1315
1303void Recurrence::setDailySub(short type, int freq, int duration) 1316void Recurrence::setDailySub(short type, int freq, int duration)
1304{ 1317{
1305 recurs = type; 1318 recurs = type;
1306 rFreq = freq; 1319 rFreq = freq;
1307 rDuration = duration; 1320 rDuration = duration;
1308 rMonthPositions.clear(); 1321 rMonthPositions.clear();
1309 rMonthDays.clear(); 1322 rMonthDays.clear();
1310 rYearNums.clear(); 1323 rYearNums.clear();
1311 if (type != rDaily) 1324 if (type != rDaily)
1312 mFloats = false; // sub-daily types can't be floating 1325 mFloats = false; // sub-daily types can't be floating
1313 1326
1314 if (mParent) mParent->updated(); 1327 if (mParent) mParent->updated();
1315} 1328}
1316 1329
1317void Recurrence::setYearly_(short type, Feb29Type feb29type, int freq, int duration) 1330void Recurrence::setYearly_(short type, Feb29Type feb29type, int freq, int duration)
1318{ 1331{
1319 recurs = type; 1332 recurs = type;
1320 if (mCompatVersion < 310 && type == rYearlyDay) { 1333 if (mCompatVersion < 310 && type == rYearlyDay) {
1321 mCompatRecurs = rYearlyDay; 1334 mCompatRecurs = rYearlyDay;
1322 recurs = rYearlyMonth; // convert old yearly-by-day to yearly-by-month 1335 recurs = rYearlyMonth; // convert old yearly-by-day to yearly-by-month
1323 feb29type = rMar1; // retain the same day number in the year 1336 feb29type = rMar1; // retain the same day number in the year
1324 } 1337 }
1325 1338
1326 mFeb29YearlyType = feb29type; 1339 mFeb29YearlyType = feb29type;
1327 rFreq = freq; 1340 rFreq = freq;
1328 rDuration = duration; 1341 rDuration = duration;
1329 if (type != rYearlyPos) 1342 if (type != rYearlyPos)
1330 rMonthPositions.clear(); 1343 rMonthPositions.clear();
1331 rMonthDays.clear(); 1344 rMonthDays.clear();
1332 if (mParent) mParent->updated(); 1345 if (mParent) mParent->updated();
1333} 1346}
1334 1347
1335int Recurrence::recurCalc(PeriodFunc func, QDateTime &endtime) const 1348int Recurrence::recurCalc(PeriodFunc func, QDateTime &endtime) const
1336{ 1349{
1337 QDate enddate = endtime.date(); 1350 QDate enddate = endtime.date();
1338 switch (func) { 1351 switch (func) {
1339 case END_DATE_AND_COUNT: 1352 case END_DATE_AND_COUNT:
1340 if (rDuration < 0) { 1353 if (rDuration < 0) {
1341 endtime = QDateTime(); 1354 endtime = QDateTime();
1342 return 0; // infinite recurrence 1355 return 0; // infinite recurrence
1343 } 1356 }
1344 if (rDuration == 0) { 1357 if (rDuration == 0) {
1345 endtime = rEndDateTime; 1358 endtime = rEndDateTime;
1346 func = COUNT_TO_DATE; 1359 func = COUNT_TO_DATE;
1347 } 1360 }
1348 break; 1361 break;
1349 case COUNT_TO_DATE: 1362 case COUNT_TO_DATE:
1350 // Count recurrences up to and including the specified date/time. 1363 // Count recurrences up to and including the specified date/time.
1351 if (endtime < mRecurStart) 1364 if (endtime < mRecurStart)
1352 return 0; 1365 return 0;
1353 if (rDuration == 0 && endtime > rEndDateTime) 1366 if (rDuration == 0 && endtime > rEndDateTime)
1354 enddate = rEndDateTime.date(); 1367 enddate = rEndDateTime.date();
1355 else if (!mFloats && mRecurStart.time() > endtime.time()) 1368 else if (!mFloats && mRecurStart.time() > endtime.time())
1356 enddate = enddate.addDays(-1); 1369 enddate = enddate.addDays(-1);
1357 break; 1370 break;
1358 case NEXT_AFTER_DATE: 1371 case NEXT_AFTER_DATE:
1359 // Find next recurrence AFTER endtime 1372 // Find next recurrence AFTER endtime
1360 if (endtime < mRecurStart) { 1373 if (endtime < mRecurStart) {
1361 endtime = mRecurStart; 1374 endtime = mRecurStart;
1362 return 1; 1375 return 1;
1363 } 1376 }
1364 if (rDuration == 0 && endtime >= rEndDateTime) { 1377 if (rDuration == 0 && endtime >= rEndDateTime) {
1365 endtime = QDateTime(); 1378 endtime = QDateTime();
1366 return 0; 1379 return 0;
1367 } 1380 }
1368 if (!mFloats && mRecurStart.time() > endtime.time()) 1381 if (!mFloats && mRecurStart.time() > endtime.time())
1369 enddate = enddate.addDays(-1); 1382 enddate = enddate.addDays(-1);
1370 break; 1383 break;
1371 default: 1384 default:
1372 endtime = QDateTime(); 1385 endtime = QDateTime();
1373 return 0; 1386 return 0;
1374 } 1387 }
1375 1388
1376 int count = 0; // default = error 1389 int count = 0; // default = error
1377 bool timed = false; 1390 bool timed = false;
1378 switch (recurs) { 1391 switch (recurs) {
1379 case rMinutely: 1392 case rMinutely:
1380 timed = true; 1393 timed = true;
1381 count = secondlyCalc(func, endtime, rFreq*60); 1394 count = secondlyCalc(func, endtime, rFreq*60);
1382 break; 1395 break;
1383 case rHourly: 1396 case rHourly:
1384 timed = true; 1397 timed = true;
1385 count = secondlyCalc(func, endtime, rFreq*3600); 1398 count = secondlyCalc(func, endtime, rFreq*3600);
1386 break; 1399 break;
1387 case rDaily: 1400 case rDaily:
1388 count = dailyCalc(func, enddate); 1401 count = dailyCalc(func, enddate);
1389 break; 1402 break;
1390 case rWeekly: 1403 case rWeekly:
1391 count = weeklyCalc(func, enddate); 1404 count = weeklyCalc(func, enddate);
1392 break; 1405 break;
1393 case rMonthlyPos: 1406 case rMonthlyPos:
1394 case rMonthlyDay: 1407 case rMonthlyDay:
1395 count = monthlyCalc(func, enddate); 1408 count = monthlyCalc(func, enddate);
1396 break; 1409 break;
1397 case rYearlyMonth: 1410 case rYearlyMonth:
1398 count = yearlyMonthCalc(func, enddate); 1411 count = yearlyMonthCalc(func, enddate);
1399 break; 1412 break;
1400 case rYearlyPos: 1413 case rYearlyPos:
1401 count = yearlyPosCalc(func, enddate); 1414 count = yearlyPosCalc(func, enddate);
1402 break; 1415 break;
1403 case rYearlyDay: 1416 case rYearlyDay:
1404 count = yearlyDayCalc(func, enddate); 1417 count = yearlyDayCalc(func, enddate);
1405 break; 1418 break;
1406 default: 1419 default:
1407 break; 1420 break;
1408 } 1421 }
1409 1422
1410 switch (func) { 1423 switch (func) {
1411 case END_DATE_AND_COUNT: 1424 case END_DATE_AND_COUNT:
1412 case NEXT_AFTER_DATE: 1425 case NEXT_AFTER_DATE:
1413 if (count == 0) 1426 if (count == 0)
1414 endtime = QDateTime(); 1427 endtime = QDateTime();
1415 else if (!timed) { 1428 else if (!timed) {
1416 endtime.setDate(enddate); 1429 endtime.setDate(enddate);
1417 endtime.setTime(mRecurStart.time()); 1430 endtime.setTime(mRecurStart.time());
1418 } 1431 }
1419 break; 1432 break;
1420 case COUNT_TO_DATE: 1433 case COUNT_TO_DATE:
1421 break; 1434 break;
1422 } 1435 }
1423 return count; 1436 return count;
1424} 1437}
1425 1438
1426int Recurrence::recurCalc(PeriodFunc func, QDate &enddate) const 1439int Recurrence::recurCalc(PeriodFunc func, QDate &enddate) const
1427{ 1440{
1428 QDateTime endtime(enddate, QTime(23,59,59)); 1441 QDateTime endtime(enddate, QTime(23,59,59));
1429 switch (func) { 1442 switch (func) {
1430 case END_DATE_AND_COUNT: 1443 case END_DATE_AND_COUNT:
1431 if (rDuration < 0) { 1444 if (rDuration < 0) {
1432 enddate = QDate(); 1445 enddate = QDate();
1433 return 0; // infinite recurrence 1446 return 0; // infinite recurrence
1434 } 1447 }
1435 if (rDuration == 0) { 1448 if (rDuration == 0) {
1436 enddate = rEndDateTime.date(); 1449 enddate = rEndDateTime.date();
1437 func = COUNT_TO_DATE; 1450 func = COUNT_TO_DATE;
1438 } 1451 }
1439 break; 1452 break;
1440 case COUNT_TO_DATE: 1453 case COUNT_TO_DATE:
1441 // Count recurrences up to and including the specified date. 1454 // Count recurrences up to and including the specified date.
1442 if (enddate < mRecurStart.date()) 1455 if (enddate < mRecurStart.date())
1443 return 0; 1456 return 0;
1444 if (rDuration == 0 && enddate > rEndDateTime.date()) { 1457 if (rDuration == 0 && enddate > rEndDateTime.date()) {
1445 enddate = rEndDateTime.date(); 1458 enddate = rEndDateTime.date();
1446 endtime.setDate(enddate); 1459 endtime.setDate(enddate);
1447 } 1460 }
1448 break; 1461 break;
1449 case NEXT_AFTER_DATE: 1462 case NEXT_AFTER_DATE:
1450 if (enddate < mRecurStart.date()) { 1463 if (enddate < mRecurStart.date()) {
1451 enddate = mRecurStart.date(); 1464 enddate = mRecurStart.date();
1452 return 1; 1465 return 1;
1453 } 1466 }
1454 if (rDuration == 0 && enddate >= rEndDateTime.date()) { 1467 if (rDuration == 0 && enddate >= rEndDateTime.date()) {
1455 enddate = QDate(); 1468 enddate = QDate();
1456 return 0; 1469 return 0;
1457 } 1470 }
1458 break; 1471 break;
1459 default: 1472 default:
1460 enddate = QDate(); 1473 enddate = QDate();
1461 return 0; 1474 return 0;
1462 } 1475 }
1463 1476
1464 int count = 0; // default = error 1477 int count = 0; // default = error
1465 bool timed = false; 1478 bool timed = false;
1466 switch (recurs) { 1479 switch (recurs) {
1467 case rMinutely: 1480 case rMinutely:
1468 timed = true; 1481 timed = true;
1469 count = secondlyCalc(func, endtime, rFreq*60); 1482 count = secondlyCalc(func, endtime, rFreq*60);
1470 break; 1483 break;
1471 case rHourly: 1484 case rHourly:
1472 timed = true; 1485 timed = true;
1473 count = secondlyCalc(func, endtime, rFreq*3600); 1486 count = secondlyCalc(func, endtime, rFreq*3600);
1474 break; 1487 break;
1475 case rDaily: 1488 case rDaily:
1476 count = dailyCalc(func, enddate); 1489 count = dailyCalc(func, enddate);
1477 break; 1490 break;
1478 case rWeekly: 1491 case rWeekly:
1479 count = weeklyCalc(func, enddate); 1492 count = weeklyCalc(func, enddate);
1480 break; 1493 break;
1481 case rMonthlyPos: 1494 case rMonthlyPos:
1482 case rMonthlyDay: 1495 case rMonthlyDay:
1483 count = monthlyCalc(func, enddate); 1496 count = monthlyCalc(func, enddate);
1484 break; 1497 break;
1485 case rYearlyMonth: 1498 case rYearlyMonth:
1486 count = yearlyMonthCalc(func, enddate); 1499 count = yearlyMonthCalc(func, enddate);
1487 break; 1500 break;
1488 case rYearlyPos: 1501 case rYearlyPos:
1489 count = yearlyPosCalc(func, enddate); 1502 count = yearlyPosCalc(func, enddate);
1490 break; 1503 break;
1491 case rYearlyDay: 1504 case rYearlyDay:
1492 count = yearlyDayCalc(func, enddate); 1505 count = yearlyDayCalc(func, enddate);
1493 break; 1506 break;
1494 default: 1507 default:
1495 break; 1508 break;
1496 } 1509 }
1497 1510
1498 switch (func) { 1511 switch (func) {
1499 case END_DATE_AND_COUNT: 1512 case END_DATE_AND_COUNT:
1500 case NEXT_AFTER_DATE: 1513 case NEXT_AFTER_DATE:
1501 if (count == 0) 1514 if (count == 0)
1502 endtime = QDate(); 1515 endtime = QDate();
1503 else if (timed) 1516 else if (timed)
1504 enddate = endtime.date(); 1517 enddate = endtime.date();
1505 break; 1518 break;
1506 case COUNT_TO_DATE: 1519 case COUNT_TO_DATE:
1507 break; 1520 break;
1508 } 1521 }
1509 return count; 1522 return count;
1510} 1523}
1511 1524
1512/* Find count and, depending on 'func', the end date/time of a secondly recurrence. 1525/* Find count and, depending on 'func', the end date/time of a secondly recurrence.
1513 * Reply = total number of occurrences up to 'endtime', or 0 if error. 1526 * Reply = total number of occurrences up to 'endtime', or 0 if error.
1514 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'endtime' is updated to the 1527 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'endtime' is updated to the
1515 * recurrence end date/time. 1528 * recurrence end date/time.
1516 */ 1529 */
1517int Recurrence::secondlyCalc(PeriodFunc func, QDateTime &endtime, int freq) const 1530int Recurrence::secondlyCalc(PeriodFunc func, QDateTime &endtime, int freq) const
1518{ 1531{
1519 switch (func) { 1532 switch (func) {
1520 case END_DATE_AND_COUNT: 1533 case END_DATE_AND_COUNT:
1521 endtime = mRecurStart.addSecs((rDuration + mRecurExDatesCount - 1) * freq); 1534 endtime = mRecurStart.addSecs((rDuration + mRecurExDatesCount - 1) * freq);
1522 return rDuration + mRecurExDatesCount; 1535 return rDuration + mRecurExDatesCount;
1523 case COUNT_TO_DATE: { 1536 case COUNT_TO_DATE: {
1524 int n = mRecurStart.secsTo(endtime)/freq + 1; 1537 int n = mRecurStart.secsTo(endtime)/freq + 1;
1525 if (rDuration > 0 && n > rDuration + mRecurExDatesCount) 1538 if (rDuration > 0 && n > rDuration + mRecurExDatesCount)
1526 return rDuration + mRecurExDatesCount; 1539 return rDuration + mRecurExDatesCount;
1527 return n; 1540 return n;
1528 } 1541 }
1529 case NEXT_AFTER_DATE: { 1542 case NEXT_AFTER_DATE: {
1530 int count = mRecurStart.secsTo(endtime) / freq + 2; 1543 int count = mRecurStart.secsTo(endtime) / freq + 2;
1531 if (rDuration > 0 && count > rDuration) 1544 if (rDuration > 0 && count > rDuration)
1532 return 0; 1545 return 0;
1533 endtime = mRecurStart.addSecs((count - 1)*freq); 1546 endtime = mRecurStart.addSecs((count - 1)*freq);
1534 return count; 1547 return count;
1535 } 1548 }
1536 } 1549 }
1537 return 0; 1550 return 0;
1538} 1551}
1539 1552
1540/* Find count and, depending on 'func', the end date of a daily recurrence. 1553/* Find count and, depending on 'func', the end date of a daily recurrence.
1541 * Reply = total number of occurrences up to 'enddate', or 0 if error. 1554 * Reply = total number of occurrences up to 'enddate', or 0 if error.
1542 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the 1555 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the
1543 * recurrence end date. 1556 * recurrence end date.
1544 */ 1557 */
1545int Recurrence::dailyCalc(PeriodFunc func, QDate &enddate) const 1558int Recurrence::dailyCalc(PeriodFunc func, QDate &enddate) const
1546{ 1559{
1547 QDate dStart = mRecurStart.date(); 1560 QDate dStart = mRecurStart.date();
1548 switch (func) { 1561 switch (func) {
1549 case END_DATE_AND_COUNT: 1562 case END_DATE_AND_COUNT:
1550 enddate = dStart.addDays((rDuration + mRecurExDatesCount - 1) * rFreq); 1563 enddate = dStart.addDays((rDuration + mRecurExDatesCount - 1) * rFreq);
1551 return rDuration + mRecurExDatesCount; 1564 return rDuration + mRecurExDatesCount;
1552 case COUNT_TO_DATE: { 1565 case COUNT_TO_DATE: {
1553 int n = dStart.daysTo(enddate)/rFreq + 1; 1566 int n = dStart.daysTo(enddate)/rFreq + 1;
1554 if (rDuration > 0 && n > rDuration + mRecurExDatesCount) 1567 if (rDuration > 0 && n > rDuration + mRecurExDatesCount)
1555 return rDuration + mRecurExDatesCount; 1568 return rDuration + mRecurExDatesCount;
1556 return n; 1569 return n;
1557 } 1570 }
1558 case NEXT_AFTER_DATE: { 1571 case NEXT_AFTER_DATE: {
1559 int count = dStart.daysTo(enddate) / rFreq + 2; 1572 int count = dStart.daysTo(enddate) / rFreq + 2;
1560 if (rDuration > 0 && count > rDuration) 1573 if (rDuration > 0 && count > rDuration)
1561 return 0; 1574 return 0;
1562 enddate = dStart.addDays((count - 1)*rFreq); 1575 enddate = dStart.addDays((count - 1)*rFreq);
1563 return count; 1576 return count;
1564 } 1577 }
1565 } 1578 }
1566 return 0; 1579 return 0;
1567} 1580}
1568 1581
1569/* Find count and, depending on 'func', the end date of a weekly recurrence. 1582/* Find count and, depending on 'func', the end date of a weekly recurrence.
1570 * Reply = total number of occurrences up to 'enddate', or 0 if error. 1583 * Reply = total number of occurrences up to 'enddate', or 0 if error.
1571 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the 1584 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the
1572 * recurrence end date. 1585 * recurrence end date.
1573 */ 1586 */
1574int Recurrence::weeklyCalc(PeriodFunc func, QDate &enddate) const 1587int Recurrence::weeklyCalc(PeriodFunc func, QDate &enddate) const
1575{ 1588{
1576 int daysPerWeek = 0; 1589 int daysPerWeek = 0;
1577 for (int i = 0; i < 7; ++i) { 1590 for (int i = 0; i < 7; ++i) {
1578 if (rDays.testBit((uint)i)) 1591 if (rDays.testBit((uint)i))
1579 ++daysPerWeek; 1592 ++daysPerWeek;
1580 } 1593 }
1581 if (!daysPerWeek) 1594 if (!daysPerWeek)
1582 return 0; // there are no days to recur on 1595 return 0; // there are no days to recur on
1583 1596
1584 switch (func) { 1597 switch (func) {
1585 case END_DATE_AND_COUNT: 1598 case END_DATE_AND_COUNT:
1586 return weeklyCalcEndDate(enddate, daysPerWeek); 1599 return weeklyCalcEndDate(enddate, daysPerWeek);
1587 case COUNT_TO_DATE: 1600 case COUNT_TO_DATE:
1588 return weeklyCalcToDate(enddate, daysPerWeek); 1601 return weeklyCalcToDate(enddate, daysPerWeek);
1589 case NEXT_AFTER_DATE: 1602 case NEXT_AFTER_DATE:
1590 return weeklyCalcNextAfter(enddate, daysPerWeek); 1603 return weeklyCalcNextAfter(enddate, daysPerWeek);
1591 } 1604 }
1592 return 0; 1605 return 0;
1593} 1606}
1594 1607
1595int Recurrence::weeklyCalcEndDate(QDate &enddate, int daysPerWeek) const 1608int Recurrence::weeklyCalcEndDate(QDate &enddate, int daysPerWeek) const
1596{ 1609{
1597 int startDayOfWeek = mRecurStart.date().dayOfWeek(); // 1..7 1610 int startDayOfWeek = mRecurStart.date().dayOfWeek(); // 1..7
1598 int countGone = 0; 1611 int countGone = 0;
1599 int daysGone = 0; 1612 int daysGone = 0;
1600 uint countTogo = rDuration + mRecurExDatesCount; 1613 uint countTogo = rDuration + mRecurExDatesCount;
1601 if (startDayOfWeek != rWeekStart) { 1614 if (startDayOfWeek != rWeekStart) {
1602 // Check what remains of the start week 1615 // Check what remains of the start week
1603 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) { 1616 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) {
1604 ++daysGone; 1617 ++daysGone;
1605 if (rDays.testBit((uint)i)) { 1618 if (rDays.testBit((uint)i)) {
1606 ++countGone; 1619 ++countGone;
1607 if (--countTogo == 0) 1620 if (--countTogo == 0)
1608 break; 1621 break;
1609 } 1622 }
1610 } 1623 }
1611 daysGone += 7 * (rFreq - 1); 1624 daysGone += 7 * (rFreq - 1);
1612 } 1625 }
1613 if (countTogo) { 1626 if (countTogo) {
1614 // Skip the remaining whole weeks 1627 // Skip the remaining whole weeks
1615 // Leave at least 1 recurrence remaining, in order to get its date 1628 // Leave at least 1 recurrence remaining, in order to get its date
1616 int wholeWeeks = (countTogo - 1) / daysPerWeek; 1629 int wholeWeeks = (countTogo - 1) / daysPerWeek;
1617 daysGone += wholeWeeks * 7 * rFreq; 1630 daysGone += wholeWeeks * 7 * rFreq;
1618 countGone += wholeWeeks * daysPerWeek; 1631 countGone += wholeWeeks * daysPerWeek;
1619 countTogo -= wholeWeeks * daysPerWeek; 1632 countTogo -= wholeWeeks * daysPerWeek;
1620 // Check the last week in the recurrence 1633 // Check the last week in the recurrence
1621 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) { 1634 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) {
1622 ++daysGone; 1635 ++daysGone;
1623 if (rDays.testBit((uint)i)) { 1636 if (rDays.testBit((uint)i)) {
1624 ++countGone; 1637 ++countGone;
1625 if (--countTogo == 0) 1638 if (--countTogo == 0)
1626 break; 1639 break;
1627 } 1640 }
1628 } 1641 }
1629 } 1642 }
1630 enddate = mRecurStart.date().addDays(daysGone); 1643 enddate = mRecurStart.date().addDays(daysGone);
1631 return countGone; 1644 return countGone;
1632} 1645}
1633 1646
1634int Recurrence::weeklyCalcToDate(const QDate &enddate, int daysPerWeek) const 1647int Recurrence::weeklyCalcToDate(const QDate &enddate, int daysPerWeek) const
1635{ 1648{
1636 QDate dStart = mRecurStart.date(); 1649 QDate dStart = mRecurStart.date();
1637 int startDayOfWeek = dStart.dayOfWeek(); // 1..7 1650 int startDayOfWeek = dStart.dayOfWeek(); // 1..7
1638 int countGone = 0; 1651 int countGone = 0;
1639 int daysGone = 0; 1652 int daysGone = 0;
1640 int totalDays = dStart.daysTo(enddate) + 1; 1653 int totalDays = dStart.daysTo(enddate) + 1;
1641 int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX; 1654 int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX;
1642 1655
1643 if (startDayOfWeek != rWeekStart) { 1656 if (startDayOfWeek != rWeekStart) {
1644 // Check what remains of the start week 1657 // Check what remains of the start week
1645 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) { 1658 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) {
1646 if (rDays.testBit((uint)i)) { 1659 if (rDays.testBit((uint)i)) {
1647 if (++countGone >= countMax) 1660 if (++countGone >= countMax)
1648 return countMax; 1661 return countMax;
1649 } 1662 }
1650 if (++daysGone == totalDays) 1663 if (++daysGone == totalDays)
1651 return countGone; 1664 return countGone;
1652 } 1665 }
1653 daysGone += 7 * (rFreq - 1); 1666 daysGone += 7 * (rFreq - 1);
1654 if (daysGone >= totalDays) 1667 if (daysGone >= totalDays)
1655 return countGone; 1668 return countGone;
1656 } 1669 }
1657 // Skip the remaining whole weeks 1670 // Skip the remaining whole weeks
1658 int wholeWeeks = (totalDays - daysGone) / 7; 1671 int wholeWeeks = (totalDays - daysGone) / 7;
1659 countGone += (wholeWeeks / rFreq) * daysPerWeek; 1672 countGone += (wholeWeeks / rFreq) * daysPerWeek;
1660 if (countGone >= countMax) 1673 if (countGone >= countMax)
1661 return countMax; 1674 return countMax;
1662 daysGone += wholeWeeks * 7; 1675 daysGone += wholeWeeks * 7;
1663 if (daysGone >= totalDays // have we reached the end date? 1676 if (daysGone >= totalDays // have we reached the end date?
1664 || wholeWeeks % rFreq) // is end week a recurrence week? 1677 || wholeWeeks % rFreq) // is end week a recurrence week?
1665 return countGone; 1678 return countGone;
1666 1679
1667 // Check the last week in the recurrence 1680 // Check the last week in the recurrence
1668 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) { 1681 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) {
1669 if (rDays.testBit((uint)i)) { 1682 if (rDays.testBit((uint)i)) {
1670 if (++countGone >= countMax) 1683 if (++countGone >= countMax)
1671 return countMax; 1684 return countMax;
1672 } 1685 }
1673 if (++daysGone == totalDays) 1686 if (++daysGone == totalDays)
1674 return countGone; 1687 return countGone;
1675 } 1688 }
1676 return countGone; 1689 return countGone;
1677} 1690}
1678 1691
1679int Recurrence::weeklyCalcNextAfter(QDate &enddate, int daysPerWeek) const 1692int Recurrence::weeklyCalcNextAfter(QDate &enddate, int daysPerWeek) const
1680{ 1693{
1681 QDate dStart = mRecurStart.date(); 1694 QDate dStart = mRecurStart.date();
1682 int startDayOfWeek = dStart.dayOfWeek(); // 1..7 1695 int startDayOfWeek = dStart.dayOfWeek(); // 1..7
1683 int totalDays = dStart.daysTo(enddate) + 1; 1696 int totalDays = dStart.daysTo(enddate) + 1;
1684 uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX; 1697 uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX;
1685 int countGone = 0; 1698 int countGone = 0;
1686 int daysGone = 0; 1699 int daysGone = 0;
1687 int recurWeeks; 1700 int recurWeeks;
1688 1701
1689 if (startDayOfWeek != rWeekStart) { 1702 if (startDayOfWeek != rWeekStart) {
1690 // Check what remains of the start week 1703 // Check what remains of the start week
1691 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) { 1704 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) {
1692 ++daysGone; 1705 ++daysGone;
1693 if (rDays.testBit((uint)i)) { 1706 if (rDays.testBit((uint)i)) {
1694 ++countGone; 1707 ++countGone;
1695 if (daysGone > totalDays) 1708 if (daysGone > totalDays)
1696 goto ex; 1709 goto ex;
1697 if (--countTogo == 0) 1710 if (--countTogo == 0)
1698 return 0; 1711 return 0;
1699 } 1712 }
1700 } 1713 }
1701 daysGone += 7 * (rFreq - 1); 1714 daysGone += 7 * (rFreq - 1);
1702 } 1715 }
1703 1716
1704 // Skip the remaining whole weeks 1717 // Skip the remaining whole weeks
1705 recurWeeks = (totalDays - daysGone) / (7 * rFreq); 1718 recurWeeks = (totalDays - daysGone) / (7 * rFreq);
1706 if (recurWeeks) { 1719 if (recurWeeks) {
1707 int n = recurWeeks * daysPerWeek; 1720 int n = recurWeeks * daysPerWeek;
1708 if (static_cast<uint>(n) > countTogo) 1721 if (static_cast<uint>(n) > countTogo)
1709 return 0; // reached end of recurrence 1722 return 0; // reached end of recurrence
1710 countGone += n; 1723 countGone += n;
1711 countTogo -= n; 1724 countTogo -= n;
1712 daysGone += recurWeeks * 7 * rFreq; 1725 daysGone += recurWeeks * 7 * rFreq;
1713 } 1726 }
1714 1727
1715 // Check the last week or two in the recurrence 1728 // Check the last week or two in the recurrence
1716 for ( ; ; ) { 1729 for ( ; ; ) {
1717 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) { 1730 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) {
1718 ++daysGone; 1731 ++daysGone;
1719 if (rDays.testBit((uint)i)) { 1732 if (rDays.testBit((uint)i)) {
1720 ++countGone; 1733 ++countGone;
1721 if (daysGone > totalDays) 1734 if (daysGone > totalDays)
1722 goto ex; 1735 goto ex;
1723 if (--countTogo == 0) 1736 if (--countTogo == 0)
1724 return 0; 1737 return 0;
1725 } 1738 }
1726 } 1739 }
1727 daysGone += 7 * (rFreq - 1); 1740 daysGone += 7 * (rFreq - 1);
1728 } 1741 }
1729ex: 1742ex:
1730 enddate = dStart.addDays(daysGone); 1743 enddate = dStart.addDays(daysGone);
1731 return countGone; 1744 return countGone;
1732} 1745}
1733 1746
1734/* Find count and, depending on 'func', the end date of a monthly recurrence. 1747/* Find count and, depending on 'func', the end date of a monthly recurrence.
1735 * Reply = total number of occurrences up to 'enddate', or 0 if error. 1748 * Reply = total number of occurrences up to 'enddate', or 0 if error.
1736 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the 1749 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the
1737 * recurrence end date. 1750 * recurrence end date.
1738 */ 1751 */
1739struct Recurrence::MonthlyData { 1752struct Recurrence::MonthlyData {
1740 const Recurrence *recurrence; 1753 const Recurrence *recurrence;
1741 int year; // current year 1754 int year; // current year
1742 int month; // current month 0..11 1755 int month; // current month 0..11
1743 int day; // current day of month 1..31 1756 int day; // current day of month 1..31
1744 bool varies; // true if recurring days vary between different months 1757 bool varies; // true if recurring days vary between different months
1745 private: 1758 private:
1746 QValueList<int> days28, days29, days30, days31; // recurring days in months of each length 1759 QValueList<int> days28, days29, days30, days31; // recurring days in months of each length
1747 QValueList<int> *recurDays[4]; 1760 QValueList<int> *recurDays[4];
1748 public: 1761 public:
1749 MonthlyData(const Recurrence* r, const QDate &date) 1762 MonthlyData(const Recurrence* r, const QDate &date)
1750 : recurrence(r), year(date.year()), month(date.month()-1), day(date.day()) 1763 : recurrence(r), year(date.year()), month(date.month()-1), day(date.day())
1751 { recurDays[0] = &days28; 1764 { recurDays[0] = &days28;
1752 recurDays[1] = &days29; 1765 recurDays[1] = &days29;
1753 recurDays[2] = &days30; 1766 recurDays[2] = &days30;
1754 recurDays[3] = &days31; 1767 recurDays[3] = &days31;
1755 varies = (recurrence->recurs == rMonthlyPos) 1768 varies = (recurrence->recurs == rMonthlyPos)
1756 ? true : recurrence->getMonthlyDayDays(days31, 31); 1769 ? true : recurrence->getMonthlyDayDays(days31, 31);
1757 } 1770 }
1758 const QValueList<int>* dayList() const { 1771 const QValueList<int>* dayList() const {
1759 if (!varies) 1772 if (!varies)
1760 return &days31; 1773 return &days31;
1761 QDate startOfMonth(year, month + 1, 1); 1774 QDate startOfMonth(year, month + 1, 1);
1762 int daysInMonth = startOfMonth.daysInMonth(); 1775 int daysInMonth = startOfMonth.daysInMonth();
1763 QValueList<int>* days = recurDays[daysInMonth - 28]; 1776 QValueList<int>* days = recurDays[daysInMonth - 28];
1764 if (recurrence->recurs == rMonthlyPos) 1777 if (recurrence->recurs == rMonthlyPos)
1765 recurrence->getMonthlyPosDays(*days, daysInMonth, startOfMonth.dayOfWeek()); 1778 recurrence->getMonthlyPosDays(*days, daysInMonth, startOfMonth.dayOfWeek());
1766 else if (days->isEmpty()) 1779 else if (days->isEmpty())
1767 recurrence->getMonthlyDayDays(*days, daysInMonth); 1780 recurrence->getMonthlyDayDays(*days, daysInMonth);
1768 return days; 1781 return days;
1769 } 1782 }
1770 int yearMonth() const { return year*12 + month; } 1783 int yearMonth() const { return year*12 + month; }
1771 void addMonths(int diff) { month += diff; year += month / 12; month %= 12; } 1784 void addMonths(int diff) { month += diff; year += month / 12; month %= 12; }
1772 QDate date() const { return QDate(year, month + 1, day); } 1785 QDate date() const { return QDate(year, month + 1, day); }
1773}; 1786};
1774 1787
1775int Recurrence::monthlyCalc(PeriodFunc func, QDate &enddate) const 1788int Recurrence::monthlyCalc(PeriodFunc func, QDate &enddate) const
1776{ 1789{
1777 if (recurs == rMonthlyPos && rMonthPositions.isEmpty() 1790 if (recurs == rMonthlyPos && rMonthPositions.isEmpty()
1778 || recurs == rMonthlyDay && rMonthDays.isEmpty()) 1791 || recurs == rMonthlyDay && rMonthDays.isEmpty())
1779 return 0; 1792 return 0;
1780 1793
1781 MonthlyData data(this, mRecurStart.date()); 1794 MonthlyData data(this, mRecurStart.date());
1782 switch (func) { 1795 switch (func) {
1783 case END_DATE_AND_COUNT: 1796 case END_DATE_AND_COUNT:
1784 return monthlyCalcEndDate(enddate, data); 1797 return monthlyCalcEndDate(enddate, data);
1785 case COUNT_TO_DATE: 1798 case COUNT_TO_DATE:
1786 return monthlyCalcToDate(enddate, data); 1799 return monthlyCalcToDate(enddate, data);
1787 case NEXT_AFTER_DATE: 1800 case NEXT_AFTER_DATE:
1788 return monthlyCalcNextAfter(enddate, data); 1801 return monthlyCalcNextAfter(enddate, data);
1789 } 1802 }
1790 return 0; 1803 return 0;
1791} 1804}
1792 1805
1793int Recurrence::monthlyCalcEndDate(QDate &enddate, MonthlyData &data) const 1806int Recurrence::monthlyCalcEndDate(QDate &enddate, MonthlyData &data) const
1794{ 1807{
1795 uint countTogo = rDuration + mRecurExDatesCount; 1808 uint countTogo = rDuration + mRecurExDatesCount;
1796 int countGone = 0; 1809 int countGone = 0;
1797 QValueList<int>::ConstIterator it; 1810 QValueList<int>::ConstIterator it;
1798 const QValueList<int>* days = data.dayList(); 1811 const QValueList<int>* days = data.dayList();
1799 1812
1800 if (data.day > 1) { 1813 if (data.day > 1) {
1801 // Check what remains of the start month 1814 // Check what remains of the start month
1802 for (it = days->begin(); it != days->end(); ++it) { 1815 for (it = days->begin(); it != days->end(); ++it) {
1803 if (*it >= data.day) { 1816 if (*it >= data.day) {
1804 ++countGone; 1817 ++countGone;
1805 if (--countTogo == 0) { 1818 if (--countTogo == 0) {
1806 data.day = *it; 1819 data.day = *it;
1807 break; 1820 break;
1808 } 1821 }
1809 } 1822 }
1810 } 1823 }
1811 if (countTogo) { 1824 if (countTogo) {
1812 data.day = 1; 1825 data.day = 1;
1813 data.addMonths(rFreq); 1826 data.addMonths(rFreq);
1814 } 1827 }
1815 } 1828 }
1816 if (countTogo) { 1829 if (countTogo) {
1817 if (data.varies) { 1830 if (data.varies) {
1818 // The number of recurrence days varies from month to month, 1831 // The number of recurrence days varies from month to month,
1819 // so we need to check month by month. 1832 // so we need to check month by month.
1820 for ( ; ; ) { 1833 for ( ; ; ) {
1821 days = data.dayList(); 1834 days = data.dayList();
1822 uint n = days->count(); // number of recurrence days in this month 1835 uint n = days->count(); // number of recurrence days in this month
1823 if (n >= countTogo) 1836 if (n >= countTogo)
1824 break; 1837 break;
1825 countTogo -= n; 1838 countTogo -= n;
1826 countGone += n; 1839 countGone += n;
1827 data.addMonths(rFreq); 1840 data.addMonths(rFreq);
1828 } 1841 }
1829 } else { 1842 } else {
1830 // The number of recurrences is the same every month, 1843 // The number of recurrences is the same every month,
1831 // so skip the month-by-month check. 1844 // so skip the month-by-month check.
1832 // Skip the remaining whole months, but leave at least 1845 // Skip the remaining whole months, but leave at least
1833 // 1 recurrence remaining, in order to get its date. 1846 // 1 recurrence remaining, in order to get its date.
1834 int daysPerMonth = days->count(); 1847 int daysPerMonth = days->count();
1835 int wholeMonths = (countTogo - 1) / daysPerMonth; 1848 int wholeMonths = (countTogo - 1) / daysPerMonth;
1836 data.addMonths(wholeMonths * rFreq); 1849 data.addMonths(wholeMonths * rFreq);
1837 countGone += wholeMonths * daysPerMonth; 1850 countGone += wholeMonths * daysPerMonth;
1838 countTogo -= wholeMonths * daysPerMonth; 1851 countTogo -= wholeMonths * daysPerMonth;
1839 } 1852 }
1840 if (countTogo) { 1853 if (countTogo) {
1841 // Check the last month in the recurrence 1854 // Check the last month in the recurrence
1842 for (it = days->begin(); it != days->end(); ++it) { 1855 for (it = days->begin(); it != days->end(); ++it) {
1843 ++countGone; 1856 ++countGone;
1844 if (--countTogo == 0) { 1857 if (--countTogo == 0) {
1845 data.day = *it; 1858 data.day = *it;
1846 break; 1859 break;
1847 } 1860 }
1848 } 1861 }
1849 } 1862 }
1850 } 1863 }
1851 enddate = data.date(); 1864 enddate = data.date();
1852 return countGone; 1865 return countGone;
1853} 1866}
1854 1867
1855int Recurrence::monthlyCalcToDate(const QDate &enddate, MonthlyData &data) const 1868int Recurrence::monthlyCalcToDate(const QDate &enddate, MonthlyData &data) const
1856{ 1869{
1857 int countGone = 0; 1870 int countGone = 0;
1858 int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX; 1871 int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX;
1859 int endYear = enddate.year(); 1872 int endYear = enddate.year();
1860 int endMonth = enddate.month() - 1; // zero-based 1873 int endMonth = enddate.month() - 1; // zero-based
1861 int endDay = enddate.day(); 1874 int endDay = enddate.day();
1862 int endYearMonth = endYear*12 + endMonth; 1875 int endYearMonth = endYear*12 + endMonth;
1863 QValueList<int>::ConstIterator it; 1876 QValueList<int>::ConstIterator it;
1864 const QValueList<int>* days = data.dayList(); 1877 const QValueList<int>* days = data.dayList();
1865 1878
1866 if (data.day > 1) { 1879 if (data.day > 1) {
1867 // Check what remains of the start month 1880 // Check what remains of the start month
1868 for (it = days->begin(); it != days->end(); ++it) { 1881 for (it = days->begin(); it != days->end(); ++it) {
1869 if (*it >= data.day) { 1882 if (*it >= data.day) {
1870 if (data.yearMonth() == endYearMonth && *it > endDay) 1883 if (data.yearMonth() == endYearMonth && *it > endDay)
1871 return countGone; 1884 return countGone;
1872 if (++countGone >= countMax) 1885 if (++countGone >= countMax)
1873 return countMax; 1886 return countMax;
1874 } 1887 }
1875 } 1888 }
1876 data.day = 1; 1889 data.day = 1;
1877 data.addMonths(rFreq); 1890 data.addMonths(rFreq);
1878 } 1891 }
1879 1892
1880 if (data.varies) { 1893 if (data.varies) {
1881 // The number of recurrence days varies from month to month, 1894 // The number of recurrence days varies from month to month,
1882 // so we need to check month by month. 1895 // so we need to check month by month.
1883 while (data.yearMonth() < endYearMonth) { 1896 while (data.yearMonth() < endYearMonth) {
1884 countGone += data.dayList()->count(); 1897 countGone += data.dayList()->count();
1885 if (countGone >= countMax) 1898 if (countGone >= countMax)
1886 return countMax; 1899 return countMax;
1887 data.addMonths(rFreq); 1900 data.addMonths(rFreq);
1888 } 1901 }
1889 days = data.dayList(); 1902 days = data.dayList();
1890 } else { 1903 } else {
1891 // The number of recurrences is the same every month, 1904 // The number of recurrences is the same every month,
1892 // so skip the month-by-month check. 1905 // so skip the month-by-month check.
1893 // Skip the remaining whole months. 1906 // Skip the remaining whole months.
1894 int daysPerMonth = days->count(); 1907 int daysPerMonth = days->count();
1895 int wholeMonths = endYearMonth - data.yearMonth(); 1908 int wholeMonths = endYearMonth - data.yearMonth();
1896 countGone += (wholeMonths / rFreq) * daysPerMonth; 1909 countGone += (wholeMonths / rFreq) * daysPerMonth;
1897 if (countGone >= countMax) 1910 if (countGone >= countMax)
1898 return countMax; 1911 return countMax;
1899 if (wholeMonths % rFreq) 1912 if (wholeMonths % rFreq)
1900 return countGone; // end year isn't a recurrence year 1913 return countGone; // end year isn't a recurrence year
1901 data.year = endYear; 1914 data.year = endYear;
1902 data.month = endMonth; 1915 data.month = endMonth;
1903 } 1916 }
1904 1917
1905 // Check the last month in the recurrence 1918 // Check the last month in the recurrence
1906 for (it = days->begin(); it != days->end(); ++it) { 1919 for (it = days->begin(); it != days->end(); ++it) {
1907 if (*it > endDay) 1920 if (*it > endDay)
1908 return countGone; 1921 return countGone;
1909 if (++countGone >= countMax) 1922 if (++countGone >= countMax)
1910 return countMax; 1923 return countMax;
1911 } 1924 }
1912 return countGone; 1925 return countGone;
1913} 1926}
1914 1927
1915int Recurrence::monthlyCalcNextAfter(QDate &enddate, MonthlyData &data) const 1928int Recurrence::monthlyCalcNextAfter(QDate &enddate, MonthlyData &data) const
1916{ 1929{
1917 uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX; 1930 uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX;
1918 int countGone = 0; 1931 int countGone = 0;
1919 int endYear = enddate.year(); 1932 int endYear = enddate.year();
1920 int endDay = enddate.day(); 1933 int endDay = enddate.day();
1921 int endYearMonth = endYear*12 + enddate.month() - 1; 1934 int endYearMonth = endYear*12 + enddate.month() - 1;
1922 QValueList<int>::ConstIterator it; 1935 QValueList<int>::ConstIterator it;
1923 const QValueList<int>* days = data.dayList(); 1936 const QValueList<int>* days = data.dayList();
1924 1937
1925 if (data.day > 1) { 1938 if (data.day > 1) {
1926 // Check what remains of the start month 1939 // Check what remains of the start month
1927 for (it = days->begin(); it != days->end(); ++it) { 1940 for (it = days->begin(); it != days->end(); ++it) {
1928 if (*it >= data.day) { 1941 if (*it >= data.day) {
1929 ++countGone; 1942 ++countGone;
1930 if (data.yearMonth() == endYearMonth && *it > endDay) { 1943 if (data.yearMonth() == endYearMonth && *it > endDay) {
1931 data.day = *it; 1944 data.day = *it;
1932 goto ex; 1945 goto ex;
1933 } 1946 }
1934 if (--countTogo == 0) 1947 if (--countTogo == 0)
1935 return 0; 1948 return 0;
1936 } 1949 }
1937 } 1950 }
1938 data.day = 1; 1951 data.day = 1;
1939 data.addMonths(rFreq); 1952 data.addMonths(rFreq);
1940 } 1953 }
1941 1954
1942 if (data.varies) { 1955 if (data.varies) {
1943 // The number of recurrence days varies from month to month, 1956 // The number of recurrence days varies from month to month,
1944 // so we need to check month by month. 1957 // so we need to check month by month.
1945 while (data.yearMonth() <= endYearMonth) { 1958 while (data.yearMonth() <= endYearMonth) {
1946 days = data.dayList(); 1959 days = data.dayList();
1947 uint n = days->count(); // number of recurrence days in this month 1960 uint n = days->count(); // number of recurrence days in this month
1948 if (data.yearMonth() == endYearMonth && days->last() > endDay) 1961 if (data.yearMonth() == endYearMonth && days->last() > endDay)
1949 break; 1962 break;
1950 if (n >= countTogo) 1963 if (n >= countTogo)
1951 return 0; 1964 return 0;
1952 countGone += n; 1965 countGone += n;
1953 countTogo -= n; 1966 countTogo -= n;
1954 data.addMonths(rFreq); 1967 data.addMonths(rFreq);
1955 } 1968 }
1956 days = data.dayList(); 1969 days = data.dayList();
1957 } else { 1970 } else {
1958 // The number of recurrences is the same every month, 1971 // The number of recurrences is the same every month,
1959 // so skip the month-by-month check. 1972 // so skip the month-by-month check.
1960 // Skip the remaining whole months to at least end year/month. 1973 // Skip the remaining whole months to at least end year/month.
1961 int daysPerMonth = days->count(); 1974 int daysPerMonth = days->count();
1962 int elapsed = endYearMonth - data.yearMonth(); 1975 int elapsed = endYearMonth - data.yearMonth();
1963 int recurMonths = (elapsed + rFreq - 1) / rFreq; 1976 int recurMonths = (elapsed + rFreq - 1) / rFreq;
1964 if (elapsed % rFreq == 0 && days->last() <= endDay) 1977 if (elapsed % rFreq == 0 && days->last() <= endDay)
1965 ++recurMonths; // required month is after endYearMonth 1978 ++recurMonths; // required month is after endYearMonth
1966 if (recurMonths) { 1979 if (recurMonths) {
1967 int n = recurMonths * daysPerMonth; 1980 int n = recurMonths * daysPerMonth;
1968 if (static_cast<uint>(n) > countTogo) 1981 if (static_cast<uint>(n) > countTogo)
1969 return 0; // reached end of recurrence 1982 return 0; // reached end of recurrence
1970 countTogo -= n; 1983 countTogo -= n;
1971 countGone += n; 1984 countGone += n;
1972 data.addMonths(recurMonths * rFreq); 1985 data.addMonths(recurMonths * rFreq);
1973 } 1986 }
1974 } 1987 }
1975 1988
1976 // Check the last month in the recurrence 1989 // Check the last month in the recurrence
1977 for (it = days->begin(); it != days->end(); ++it) { 1990 for (it = days->begin(); it != days->end(); ++it) {
1978 ++countGone; 1991 ++countGone;
1979 if (data.yearMonth() > endYearMonth || *it > endDay) { 1992 if (data.yearMonth() > endYearMonth || *it > endDay) {
1980 data.day = *it; 1993 data.day = *it;
1981 break; 1994 break;
1982 } 1995 }
1983 if (--countTogo == 0) 1996 if (--countTogo == 0)
1984 return 0; 1997 return 0;
1985 } 1998 }
1986ex: 1999ex:
1987 enddate = data.date(); 2000 enddate = data.date();
1988 return countGone; 2001 return countGone;
1989} 2002}
1990 2003
1991 2004
1992/* Find count and, depending on 'func', the end date of an annual recurrence by date. 2005/* Find count and, depending on 'func', the end date of an annual recurrence by date.
1993 * Reply = total number of occurrences up to 'enddate', or 0 if error. 2006 * Reply = total number of occurrences up to 'enddate', or 0 if error.
1994 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the 2007 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the
1995 * recurrence end date. 2008 * recurrence end date.
1996 */ 2009 */
1997struct Recurrence::YearlyMonthData { 2010struct Recurrence::YearlyMonthData {
1998 const Recurrence *recurrence; 2011 const Recurrence *recurrence;
1999 int year; // current year 2012 int year; // current year
2000 int month; // current month 1..12 2013 int month; // current month 1..12
2001 int day; // current day of month 1..31 2014 int day; // current day of month 1..31
2002 bool leapyear; // true if February 29th recurs and current year is a leap year 2015 bool leapyear; // true if February 29th recurs and current year is a leap year
2003 bool feb29; // true if February 29th recurs 2016 bool feb29; // true if February 29th recurs
2004 private: 2017 private:
2005 QValueList<int> months; // recurring months in non-leap years 1..12 2018 QValueList<int> months; // recurring months in non-leap years 1..12
2006 QValueList<int> leapMonths; // recurring months in leap years 1..12 2019 QValueList<int> leapMonths; // recurring months in leap years 1..12
2007 public: 2020 public:
2008 YearlyMonthData(const Recurrence* r, const QDate &date) 2021 YearlyMonthData(const Recurrence* r, const QDate &date)
2009 : recurrence(r), year(date.year()), month(date.month()), day(date.day()) 2022 : recurrence(r), year(date.year()), month(date.month()), day(date.day())
2010 { feb29 = recurrence->getYearlyMonthMonths(day, months, leapMonths); 2023 { feb29 = recurrence->getYearlyMonthMonths(day, months, leapMonths);
2011 leapyear = feb29 && QDate::leapYear(year); 2024 leapyear = feb29 && QDate::leapYear(year);
2012 } 2025 }
2013 const QValueList<int>* monthList() const 2026 const QValueList<int>* monthList() const
2014 { return leapyear ? &leapMonths : &months; } 2027 { return leapyear ? &leapMonths : &months; }
2015 const QValueList<int>* leapMonthList() const { return &leapMonths; } 2028 const QValueList<int>* leapMonthList() const { return &leapMonths; }
2016 QDate date() const { return QDate(year, month, day); } 2029 QDate date() const { return QDate(year, month, day); }
2017}; 2030};
2018 2031
2019int Recurrence::yearlyMonthCalc(PeriodFunc func, QDate &enddate) const 2032int Recurrence::yearlyMonthCalc(PeriodFunc func, QDate &enddate) const
2020{ 2033{
2021 if (rYearNums.isEmpty()) 2034 if (rYearNums.isEmpty())
2022 return 0; 2035 return 0;
2023 YearlyMonthData data(this, mRecurStart.date()); 2036 YearlyMonthData data(this, mRecurStart.date());
2024 switch (func) { 2037 switch (func) {
2025 case END_DATE_AND_COUNT: 2038 case END_DATE_AND_COUNT:
2026 return yearlyMonthCalcEndDate(enddate, data); 2039 return yearlyMonthCalcEndDate(enddate, data);
2027 case COUNT_TO_DATE: 2040 case COUNT_TO_DATE:
2028 return yearlyMonthCalcToDate(enddate, data); 2041 return yearlyMonthCalcToDate(enddate, data);
2029 case NEXT_AFTER_DATE: 2042 case NEXT_AFTER_DATE:
2030 return yearlyMonthCalcNextAfter(enddate, data); 2043 return yearlyMonthCalcNextAfter(enddate, data);
2031 } 2044 }
2032 return 0; 2045 return 0;
2033} 2046}
2034 2047
2035// Find total count and end date of an annual recurrence by date. 2048// Find total count and end date of an annual recurrence by date.
2036// Reply = total number of occurrences. 2049// Reply = total number of occurrences.
2037int Recurrence::yearlyMonthCalcEndDate(QDate &enddate, YearlyMonthData &data) const 2050int Recurrence::yearlyMonthCalcEndDate(QDate &enddate, YearlyMonthData &data) const
2038{ 2051{
2039 uint countTogo = rDuration + mRecurExDatesCount; 2052 uint countTogo = rDuration + mRecurExDatesCount;
2040 int countGone = 0; 2053 int countGone = 0;
2041 QValueList<int>::ConstIterator it; 2054 QValueList<int>::ConstIterator it;
2042 const QValueList<int>* mons = data.monthList(); // get recurring months for this year 2055 const QValueList<int>* mons = data.monthList(); // get recurring months for this year
2043 2056
2044 if (data.month > 1) { 2057 if (data.month > 1) {
2045 // Check what remains of the start year 2058 // Check what remains of the start year
2046 for (it = mons->begin(); it != mons->end(); ++it) { 2059 for (it = mons->begin(); it != mons->end(); ++it) {
2047 if (*it >= data.month) { 2060 if (*it >= data.month) {
2048 ++countGone; 2061 ++countGone;
2049 if (--countTogo == 0) { 2062 if (--countTogo == 0) {
2050 data.month = *it; 2063 data.month = *it;
2051 if (data.month == 2 && data.feb29 && !data.leapyear) { 2064 if (data.month == 2 && data.feb29 && !data.leapyear) {
2052 // The recurrence should end on February 29th, but it's a non-leap year 2065 // The recurrence should end on February 29th, but it's a non-leap year
2053 switch (mFeb29YearlyType) { 2066 switch (mFeb29YearlyType) {
2054 case rFeb28: 2067 case rFeb28:
2055 data.day = 28; 2068 data.day = 28;
2056 break; 2069 break;
2057 case rMar1: 2070 case rMar1:
2058 data.month = 3; 2071 data.month = 3;
2059 data.day = 1; 2072 data.day = 1;
2060 break; 2073 break;
2061 case rFeb29: 2074 case rFeb29:
2062 break; 2075 break;
2063 } 2076 }
2064 } 2077 }
2065 break; 2078 break;
2066 } 2079 }
2067 } 2080 }
2068 } 2081 }
2069 if (countTogo) { 2082 if (countTogo) {
2070 data.month = 1; 2083 data.month = 1;
2071 data.year += rFreq; 2084 data.year += rFreq;
2072 } 2085 }
2073 } 2086 }
2074 if (countTogo) { 2087 if (countTogo) {
2075 if (data.feb29 && mFeb29YearlyType == rFeb29) { 2088 if (data.feb29 && mFeb29YearlyType == rFeb29) {
2076 // The number of recurrences is different on leap years, 2089 // The number of recurrences is different on leap years,
2077 // so check year-by-year. 2090 // so check year-by-year.
2078 for ( ; ; ) { 2091 for ( ; ; ) {
2079 mons = data.monthList(); 2092 mons = data.monthList();
2080 uint n = mons->count(); 2093 uint n = mons->count();
2081 if (n >= countTogo) 2094 if (n >= countTogo)
2082 break; 2095 break;
2083 countTogo -= n; 2096 countTogo -= n;
2084 countGone += n; 2097 countGone += n;
2085 data.year += rFreq; 2098 data.year += rFreq;
2086 } 2099 }
2087 } else { 2100 } else {
2088 // The number of recurrences is the same every year, 2101 // The number of recurrences is the same every year,
2089 // so skip the year-by-year check. 2102 // so skip the year-by-year check.
2090 // Skip the remaining whole years, but leave at least 2103 // Skip the remaining whole years, but leave at least
2091 // 1 recurrence remaining, in order to get its date. 2104 // 1 recurrence remaining, in order to get its date.
2092 int monthsPerYear = mons->count(); 2105 int monthsPerYear = mons->count();
2093 int wholeYears = (countTogo - 1) / monthsPerYear; 2106 int wholeYears = (countTogo - 1) / monthsPerYear;
2094 data.year += wholeYears * rFreq; 2107 data.year += wholeYears * rFreq;
2095 countGone += wholeYears * monthsPerYear; 2108 countGone += wholeYears * monthsPerYear;
2096 countTogo -= wholeYears * monthsPerYear; 2109 countTogo -= wholeYears * monthsPerYear;
2097 } 2110 }
2098 if (countTogo) { 2111 if (countTogo) {
2099 // Check the last year in the recurrence 2112 // Check the last year in the recurrence
2100 for (it = mons->begin(); it != mons->end(); ++it) { 2113 for (it = mons->begin(); it != mons->end(); ++it) {
2101 ++countGone; 2114 ++countGone;
2102 if (--countTogo == 0) { 2115 if (--countTogo == 0) {
2103 data.month = *it; 2116 data.month = *it;
2104 if (data.month == 2 && data.feb29 && !QDate::leapYear(data.year)) { 2117 if (data.month == 2 && data.feb29 && !QDate::leapYear(data.year)) {
2105 // The recurrence should end on February 29th, but it's a non-leap year 2118 // The recurrence should end on February 29th, but it's a non-leap year
2106 switch (mFeb29YearlyType) { 2119 switch (mFeb29YearlyType) {
2107 case rFeb28: 2120 case rFeb28:
2108 data.day = 28; 2121 data.day = 28;
2109 break; 2122 break;
2110 case rMar1: 2123 case rMar1:
2111 data.month = 3; 2124 data.month = 3;
2112 data.day = 1; 2125 data.day = 1;
2113 break; 2126 break;
2114 case rFeb29: 2127 case rFeb29:
2115 break; 2128 break;
2116 } 2129 }
2117 } 2130 }
2118 break; 2131 break;
2119 } 2132 }
2120 } 2133 }
2121 } 2134 }
2122 } 2135 }
2123 enddate = data.date(); 2136 enddate = data.date();
2124 return countGone; 2137 return countGone;
2125} 2138}
2126 2139
2127// Find count of an annual recurrence by date. 2140// Find count of an annual recurrence by date.
2128// Reply = total number of occurrences up to 'enddate'. 2141// Reply = total number of occurrences up to 'enddate'.
2129int Recurrence::yearlyMonthCalcToDate(const QDate &enddate, YearlyMonthData &data) const 2142int Recurrence::yearlyMonthCalcToDate(const QDate &enddate, YearlyMonthData &data) const
2130{ 2143{
2131 int countGone = 0; 2144 int countGone = 0;
2132 int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX; 2145 int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX;
2133 int endYear = enddate.year(); 2146 int endYear = enddate.year();
2134 int endMonth = enddate.month(); 2147 int endMonth = enddate.month();
2135 int endDay = enddate.day(); 2148 int endDay = enddate.day();
2136 if (endDay < data.day) { 2149 if (endDay < data.day) {
2137 /* The end day of the month is earlier than the recurrence day of the month. 2150 /* The end day of the month is earlier than the recurrence day of the month.
2138 * If Feb 29th recurs and: 2151 * If Feb 29th recurs and:
2139 * 1) it recurs on Feb 28th in non-leap years, don't adjust the end month 2152 * 1) it recurs on Feb 28th in non-leap years, don't adjust the end month
2140 * if enddate is Feb 28th on a non-leap year. 2153 * if enddate is Feb 28th on a non-leap year.
2141 * 2) it recurs on Mar 1st in non-leap years, allow the end month to be 2154 * 2) it recurs on Mar 1st in non-leap years, allow the end month to be
2142 * adjusted to February, to simplify calculations. 2155 * adjusted to February, to simplify calculations.
2143 */ 2156 */
2144 if (data.feb29 && !QDate::leapYear(endYear) 2157 if (data.feb29 && !QDate::leapYear(endYear)
2145 && mFeb29YearlyType == rFeb28 && endDay == 28 && endMonth == 2) { 2158 && mFeb29YearlyType == rFeb28 && endDay == 28 && endMonth == 2) {
2146 } 2159 }
2147 else if (--endMonth == 0) { 2160 else if (--endMonth == 0) {
2148 endMonth = 12; 2161 endMonth = 12;
2149 --endYear; 2162 --endYear;
2150 } 2163 }
2151 } 2164 }
2152 QValueList<int>::ConstIterator it; 2165 QValueList<int>::ConstIterator it;
2153 const QValueList<int>* mons = data.monthList(); 2166 const QValueList<int>* mons = data.monthList();
2154 2167
2155 if (data.month > 1) { 2168 if (data.month > 1) {
2156 // Check what remains of the start year 2169 // Check what remains of the start year
2157 for (it = mons->begin(); it != mons->end(); ++it) { 2170 for (it = mons->begin(); it != mons->end(); ++it) {
2158 if (*it >= data.month) { 2171 if (*it >= data.month) {
2159 if (data.year == endYear && *it > endMonth) 2172 if (data.year == endYear && *it > endMonth)
2160 return countGone; 2173 return countGone;
2161 if (++countGone >= countMax) 2174 if (++countGone >= countMax)
2162 return countMax; 2175 return countMax;
2163 } 2176 }
2164 } 2177 }
2165 data.month = 1; 2178 data.month = 1;
2166 data.year += rFreq; 2179 data.year += rFreq;
2167 } 2180 }
2168 if (data.feb29 && mFeb29YearlyType == rFeb29) { 2181 if (data.feb29 && mFeb29YearlyType == rFeb29) {
2169 // The number of recurrences is different on leap years, 2182 // The number of recurrences is different on leap years,
2170 // so check year-by-year. 2183 // so check year-by-year.
2171 while (data.year < endYear) { 2184 while (data.year < endYear) {
2172 countGone += data.monthList()->count(); 2185 countGone += data.monthList()->count();
2173 if (countGone >= countMax) 2186 if (countGone >= countMax)
2174 return countMax; 2187 return countMax;
2175 data.year += rFreq; 2188 data.year += rFreq;
2176 } 2189 }
2177 mons = data.monthList(); 2190 mons = data.monthList();
2178 } else { 2191 } else {
2179 // The number of recurrences is the same every year, 2192 // The number of recurrences is the same every year,
2180 // so skip the year-by-year check. 2193 // so skip the year-by-year check.
2181 // Skip the remaining whole years. 2194 // Skip the remaining whole years.
2182 int monthsPerYear = mons->count(); 2195 int monthsPerYear = mons->count();
2183 int wholeYears = endYear - data.year; 2196 int wholeYears = endYear - data.year;
2184 countGone += (wholeYears / rFreq) * monthsPerYear; 2197 countGone += (wholeYears / rFreq) * monthsPerYear;
2185 if (countGone >= countMax) 2198 if (countGone >= countMax)
2186 return countMax; 2199 return countMax;
2187 if (wholeYears % rFreq) 2200 if (wholeYears % rFreq)
2188 return countGone; // end year isn't a recurrence year 2201 return countGone; // end year isn't a recurrence year
2189 data.year = endYear; 2202 data.year = endYear;
2190 } 2203 }
2191 2204
2192 // Check the last year in the recurrence 2205 // Check the last year in the recurrence
2193 for (it = mons->begin(); it != mons->end(); ++it) { 2206 for (it = mons->begin(); it != mons->end(); ++it) {
2194 if (*it > endMonth) 2207 if (*it > endMonth)
2195 return countGone; 2208 return countGone;
2196 if (++countGone >= countMax) 2209 if (++countGone >= countMax)
2197 return countMax; 2210 return countMax;
2198 } 2211 }
2199 return countGone; 2212 return countGone;
2200} 2213}
2201 2214
2202// Find count and date of first recurrence after 'enddate' of an annual recurrence by date. 2215// Find count and date of first recurrence after 'enddate' of an annual recurrence by date.
2203// Reply = total number of occurrences up to 'enddate'. 2216// Reply = total number of occurrences up to 'enddate'.
2204int Recurrence::yearlyMonthCalcNextAfter(QDate &enddate, YearlyMonthData &data) const 2217int Recurrence::yearlyMonthCalcNextAfter(QDate &enddate, YearlyMonthData &data) const
2205{ 2218{
2206 uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX; 2219 uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX;
2207 int countGone = 0; 2220 int countGone = 0;
2208 int endYear = enddate.year(); 2221 int endYear = enddate.year();
2209 int endMonth = enddate.month(); 2222 int endMonth = enddate.month();
2210 int endDay = enddate.day(); 2223 int endDay = enddate.day();
2211 bool mar1TooEarly = false; 2224 bool mar1TooEarly = false;
2212 bool feb28ok = false; 2225 bool feb28ok = false;
2213 if (endDay < data.day) { 2226 if (endDay < data.day) {
2214 if (data.feb29 && mFeb29YearlyType == rMar1 && endMonth == 3) 2227 if (data.feb29 && mFeb29YearlyType == rMar1 && endMonth == 3)
2215 mar1TooEarly = true; 2228 mar1TooEarly = true;
2216 if (data.feb29 && mFeb29YearlyType == rFeb28 && endMonth == 2 && endDay == 28) 2229 if (data.feb29 && mFeb29YearlyType == rFeb28 && endMonth == 2 && endDay == 28)
2217 feb28ok = true; 2230 feb28ok = true;
2218 else if (--endMonth == 0) { 2231 else if (--endMonth == 0) {
2219 endMonth = 12; 2232 endMonth = 12;
2220 --endYear; 2233 --endYear;
2221 } 2234 }
2222 } 2235 }
2223 QValueList<int>::ConstIterator it; 2236 QValueList<int>::ConstIterator it;
2224 const QValueList<int>* mons = data.monthList(); 2237 const QValueList<int>* mons = data.monthList();
2225 2238
2226 if (data.month > 1) { 2239 if (data.month > 1) {
2227 // Check what remains of the start year 2240 // Check what remains of the start year
2228 for (it = mons->begin(); it != mons->end(); ++it) { 2241 for (it = mons->begin(); it != mons->end(); ++it) {
2229 if (*it >= data.month) { 2242 if (*it >= data.month) {
2230 ++countGone; 2243 ++countGone;
2231 if (data.year == endYear 2244 if (data.year == endYear
2232 && ( *it > endMonth && (*it > 3 || !mar1TooEarly) 2245 && ( *it > endMonth && (*it > 3 || !mar1TooEarly)
2233 || *it == 2 && feb28ok && data.leapyear)) { 2246 || *it == 2 && feb28ok && data.leapyear)) {
2234 if (*it == 2 && data.feb29 && !data.leapyear) { 2247 if (*it == 2 && data.feb29 && !data.leapyear) {
2235 // The next recurrence should be on February 29th, but it's a non-leap year 2248 // The next recurrence should be on February 29th, but it's a non-leap year
2236 switch (mFeb29YearlyType) { 2249 switch (mFeb29YearlyType) {
2237 case rFeb28: 2250 case rFeb28:
2238 data.month = 2; 2251 data.month = 2;
2239 data.day = 28; 2252 data.day = 28;
2240 break; 2253 break;
2241 case rMar1: 2254 case rMar1:
2242 data.month = 3; 2255 data.month = 3;
2243 data.day = 1; 2256 data.day = 1;
2244 break; 2257 break;
2245 case rFeb29: // impossible in this context! 2258 case rFeb29: // impossible in this context!
2246 break; 2259 break;
2247 } 2260 }
2248 } 2261 }
2249 else 2262 else
2250 data.month = *it; 2263 data.month = *it;
2251 goto ex; 2264 goto ex;
2252 } 2265 }
2253 if (--countTogo == 0) 2266 if (--countTogo == 0)
2254 return 0; 2267 return 0;
2255 } 2268 }
2256 } 2269 }
2257 data.month = 1; 2270 data.month = 1;
2258 data.year += rFreq; 2271 data.year += rFreq;
2259 } 2272 }
2260 2273
2261 if (data.feb29 && mFeb29YearlyType == rFeb29) { 2274 if (data.feb29 && mFeb29YearlyType == rFeb29) {
2262 // The number of recurrences is different on leap years, 2275 // The number of recurrences is different on leap years,
2263 // so check year-by-year. 2276 // so check year-by-year.
2264 while (data.year <= endYear) { 2277 while (data.year <= endYear) {
2265 mons = data.monthList(); 2278 mons = data.monthList();
2266 if (data.year == endYear && mons->last() > endMonth) 2279 if (data.year == endYear && mons->last() > endMonth)
2267 break; 2280 break;
2268 uint n = mons->count(); 2281 uint n = mons->count();
2269 if (n >= countTogo) 2282 if (n >= countTogo)
2270 break; 2283 break;
2271 countTogo -= n; 2284 countTogo -= n;
2272 countGone += n; 2285 countGone += n;
2273 data.year += rFreq; 2286 data.year += rFreq;
2274 } 2287 }
2275 mons = data.monthList(); 2288 mons = data.monthList();
2276 } else { 2289 } else {
2277 // The number of recurrences is the same every year, 2290 // The number of recurrences is the same every year,
2278 // so skip the year-by-year check. 2291 // so skip the year-by-year check.
2279 // Skip the remaining whole years to at least endYear. 2292 // Skip the remaining whole years to at least endYear.
2280 int monthsPerYear = mons->count(); 2293 int monthsPerYear = mons->count();
2281 int recurYears = (endYear - data.year + rFreq - 1) / rFreq; 2294 int recurYears = (endYear - data.year + rFreq - 1) / rFreq;
2282 if ((endYear - data.year)%rFreq == 0 2295 if ((endYear - data.year)%rFreq == 0
2283 && mons->last() <= endMonth) 2296 && mons->last() <= endMonth)
2284 ++recurYears; // required year is after endYear 2297 ++recurYears; // required year is after endYear
2285 if (recurYears) { 2298 if (recurYears) {
2286 int n = recurYears * monthsPerYear; 2299 int n = recurYears * monthsPerYear;
2287 if (static_cast<uint>(n) > countTogo) 2300 if (static_cast<uint>(n) > countTogo)
2288 return 0; // reached end of recurrence 2301 return 0; // reached end of recurrence
2289 countTogo -= n; 2302 countTogo -= n;
2290 countGone += n; 2303 countGone += n;
2291 data.year += recurYears * rFreq; 2304 data.year += recurYears * rFreq;
2292 } 2305 }
2293 } 2306 }
2294 2307
2295 // Check the last year in the recurrence 2308 // Check the last year in the recurrence
2296 for (it = mons->begin(); it != mons->end(); ++it) { 2309 for (it = mons->begin(); it != mons->end(); ++it) {
2297 ++countGone; 2310 ++countGone;
2298 if (data.year > endYear 2311 if (data.year > endYear
2299 || ( *it > endMonth && (*it > 3 || !mar1TooEarly) 2312 || ( *it > endMonth && (*it > 3 || !mar1TooEarly)
2300 || *it == 2 && feb28ok && QDate::leapYear(data.year))) { 2313 || *it == 2 && feb28ok && QDate::leapYear(data.year))) {
2301 if (*it == 2 && data.feb29 && !QDate::leapYear(data.year)) { 2314 if (*it == 2 && data.feb29 && !QDate::leapYear(data.year)) {
2302 // The next recurrence should be on February 29th, but it's a non-leap year 2315 // The next recurrence should be on February 29th, but it's a non-leap year
2303 switch (mFeb29YearlyType) { 2316 switch (mFeb29YearlyType) {
2304 case rFeb28: 2317 case rFeb28:
2305 data.month = 2; 2318 data.month = 2;
2306 data.day = 28; 2319 data.day = 28;
2307 break; 2320 break;
2308 case rMar1: 2321 case rMar1:
2309 data.month = 3; 2322 data.month = 3;
2310 data.day = 1; 2323 data.day = 1;
2311 break; 2324 break;
2312 case rFeb29: // impossible in this context! 2325 case rFeb29: // impossible in this context!
2313 break; 2326 break;
2314 } 2327 }
2315 } 2328 }
2316 else 2329 else
2317 data.month = *it; 2330 data.month = *it;
2318 break; 2331 break;
2319 } 2332 }
2320 if (--countTogo == 0) 2333 if (--countTogo == 0)
2321 return 0; 2334 return 0;
2322 } 2335 }
2323ex: 2336ex:
2324 enddate = data.date(); 2337 enddate = data.date();
2325 return countGone; 2338 return countGone;
2326} 2339}
2327 2340
2328 2341
2329/* Find count and, depending on 'func', the end date of an annual recurrence by date. 2342/* Find count and, depending on 'func', the end date of an annual recurrence by date.
2330 * Reply = total number of occurrences up to 'enddate', or 0 if error. 2343 * Reply = total number of occurrences up to 'enddate', or 0 if error.
2331 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the 2344 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the
2332 * recurrence end date. 2345 * recurrence end date.
2333 */ 2346 */
2334struct Recurrence::YearlyPosData { 2347struct Recurrence::YearlyPosData {
2335 const Recurrence *recurrence; 2348 const Recurrence *recurrence;
2336 int year; // current year 2349 int year; // current year
2337 int month; // current month 1..12 2350 int month; // current month 1..12
2338 int day; // current day of month 1..31 2351 int day; // current day of month 1..31
2339 int daysPerMonth; // number of days which recur each month, or -1 if variable 2352 int daysPerMonth; // number of days which recur each month, or -1 if variable
2340 int count; // number of days which recur each year, or -1 if variable 2353 int count; // number of days which recur each year, or -1 if variable
2341 bool varies; // true if number of days varies from year to year 2354 bool varies; // true if number of days varies from year to year
2342 private: 2355 private:
2343 mutable QValueList<int> days; 2356 mutable QValueList<int> days;
2344 public: 2357 public:
2345 YearlyPosData(const Recurrence* r, const QDate &date) 2358 YearlyPosData(const Recurrence* r, const QDate &date)
2346 : recurrence(r), year(date.year()), month(date.month()), day(date.day()), count(-1) 2359 : recurrence(r), year(date.year()), month(date.month()), day(date.day()), count(-1)
2347 { if ((daysPerMonth = r->countMonthlyPosDays()) > 0) 2360 { if ((daysPerMonth = r->countMonthlyPosDays()) > 0)
2348 count = daysPerMonth * r->rYearNums.count(); 2361 count = daysPerMonth * r->rYearNums.count();
2349 varies = (daysPerMonth < 0); 2362 varies = (daysPerMonth < 0);
2350 } 2363 }
2351 const QValueList<int>* dayList() const { 2364 const QValueList<int>* dayList() const {
2352 QDate startOfMonth(year, month, 1); 2365 QDate startOfMonth(year, month, 1);
2353 recurrence->getMonthlyPosDays(days, startOfMonth.daysInMonth(), startOfMonth.dayOfWeek()); 2366 recurrence->getMonthlyPosDays(days, startOfMonth.daysInMonth(), startOfMonth.dayOfWeek());
2354 return &days; 2367 return &days;
2355 } 2368 }
2356 int yearMonth() const { return year*12 + month - 1; } 2369 int yearMonth() const { return year*12 + month - 1; }
2357 void addMonths(int diff) { month += diff - 1; year += month / 12; month = month % 12 + 1; } 2370 void addMonths(int diff) { month += diff - 1; year += month / 12; month = month % 12 + 1; }
2358 QDate date() const { return QDate(year, month, day); } 2371 QDate date() const { return QDate(year, month, day); }
2359}; 2372};
2360 2373
2361int Recurrence::yearlyPosCalc(PeriodFunc func, QDate &enddate) const 2374int Recurrence::yearlyPosCalc(PeriodFunc func, QDate &enddate) const
2362{ 2375{
2363 if (rYearNums.isEmpty() || rMonthPositions.isEmpty()) 2376 if (rYearNums.isEmpty() || rMonthPositions.isEmpty())
2364 return 0; 2377 return 0;
2365 YearlyPosData data(this, mRecurStart.date()); 2378 YearlyPosData data(this, mRecurStart.date());
2366 switch (func) { 2379 switch (func) {
2367 case END_DATE_AND_COUNT: 2380 case END_DATE_AND_COUNT:
2368 return yearlyPosCalcEndDate(enddate, data); 2381 return yearlyPosCalcEndDate(enddate, data);
2369 case COUNT_TO_DATE: 2382 case COUNT_TO_DATE:
2370 return yearlyPosCalcToDate(enddate, data); 2383 return yearlyPosCalcToDate(enddate, data);
2371 case NEXT_AFTER_DATE: 2384 case NEXT_AFTER_DATE:
2372 return yearlyPosCalcNextAfter(enddate, data); 2385 return yearlyPosCalcNextAfter(enddate, data);
2373 } 2386 }
2374 return 0; 2387 return 0;
2375} 2388}
2376 2389
2377int Recurrence::yearlyPosCalcEndDate(QDate &enddate, YearlyPosData &data) const 2390int Recurrence::yearlyPosCalcEndDate(QDate &enddate, YearlyPosData &data) const
2378{ 2391{
2379 uint countTogo = rDuration + mRecurExDatesCount; 2392 uint countTogo = rDuration + mRecurExDatesCount;
2380 int countGone = 0; 2393 int countGone = 0;
2381 QValueList<int>::ConstIterator id; 2394 QValueList<int>::ConstIterator id;
2382 const QValueList<int>* days; 2395 const QValueList<int>* days;
2383 2396
2384 if (data.month > 1 || data.day > 1) { 2397 if (data.month > 1 || data.day > 1) {
2385 // Check what remains of the start year 2398 // Check what remains of the start year
2386 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { 2399 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) {
2387 if (*im.current() >= data.month) { 2400 if (*im.current() >= data.month) {
2388 // Check what remains of the start month 2401 // Check what remains of the start month
2389 if (data.day > 1 || data.varies 2402 if (data.day > 1 || data.varies
2390 || static_cast<uint>(data.daysPerMonth) >= countTogo) { 2403 || static_cast<uint>(data.daysPerMonth) >= countTogo) {
2391 data.month = *im.current(); 2404 data.month = *im.current();
2392 days = data.dayList(); 2405 days = data.dayList();
2393 for (id = days->begin(); id != days->end(); ++id) { 2406 for (id = days->begin(); id != days->end(); ++id) {
2394 if (*id >= data.day) { 2407 if (*id >= data.day) {
2395 ++countGone; 2408 ++countGone;
2396 if (--countTogo == 0) { 2409 if (--countTogo == 0) {
2397 data.month = *im.current(); 2410 data.month = *im.current();
2398 data.day = *id; 2411 data.day = *id;
2399 goto ex; 2412 goto ex;
2400 } 2413 }
2401 } 2414 }
2402 } 2415 }
2403 data.day = 1; 2416 data.day = 1;
2404 } else { 2417 } else {
2405 // The number of days per month is constant, so skip 2418 // The number of days per month is constant, so skip
2406 // the whole month. 2419 // the whole month.
2407 countTogo -= data.daysPerMonth; 2420 countTogo -= data.daysPerMonth;
2408 countGone += data.daysPerMonth; 2421 countGone += data.daysPerMonth;
2409 } 2422 }
2410 } 2423 }
2411 } 2424 }
2412 data.month = 1; 2425 data.month = 1;
2413 data.year += rFreq; 2426 data.year += rFreq;
2414 } 2427 }
2415 2428
2416 if (data.varies) { 2429 if (data.varies) {
2417 // The number of recurrences varies from year to year. 2430 // The number of recurrences varies from year to year.
2418 for ( ; ; ) { 2431 for ( ; ; ) {
2419 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { 2432 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) {
2420 data.month = *im.current(); 2433 data.month = *im.current();
2421 days = data.dayList(); 2434 days = data.dayList();
2422 int n = days->count(); 2435 int n = days->count();
2423 if (static_cast<uint>(n) >= countTogo) { 2436 if (static_cast<uint>(n) >= countTogo) {
2424 // Check the last month in the recurrence 2437 // Check the last month in the recurrence
2425 for (id = days->begin(); id != days->end(); ++id) { 2438 for (id = days->begin(); id != days->end(); ++id) {
2426 ++countGone; 2439 ++countGone;
2427 if (--countTogo == 0) { 2440 if (--countTogo == 0) {
2428 data.day = *id; 2441 data.day = *id;
2429 goto ex; 2442 goto ex;
2430 } 2443 }
2431 } 2444 }
2432 } 2445 }
2433 countTogo -= n; 2446 countTogo -= n;
2434 countGone += n; 2447 countGone += n;
2435 } 2448 }
2436 data.year += rFreq; 2449 data.year += rFreq;
2437 } 2450 }
2438 } else { 2451 } else {
2439 // The number of recurrences is the same every year, 2452 // The number of recurrences is the same every year,
2440 // so skip the year-by-year check. 2453 // so skip the year-by-year check.
2441 // Skip the remaining whole years, but leave at least 2454 // Skip the remaining whole years, but leave at least
2442 // 1 recurrence remaining, in order to get its date. 2455 // 1 recurrence remaining, in order to get its date.
2443 int wholeYears = (countTogo - 1) / data.count; 2456 int wholeYears = (countTogo - 1) / data.count;
2444 data.year += wholeYears * rFreq; 2457 data.year += wholeYears * rFreq;
2445 countGone += wholeYears * data.count; 2458 countGone += wholeYears * data.count;
2446 countTogo -= wholeYears * data.count; 2459 countTogo -= wholeYears * data.count;
2447 2460
2448 // Check the last year in the recurrence. 2461 // Check the last year in the recurrence.
2449 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { 2462 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) {
2450 if (static_cast<uint>(data.daysPerMonth) >= countTogo) { 2463 if (static_cast<uint>(data.daysPerMonth) >= countTogo) {
2451 // Check the last month in the recurrence 2464 // Check the last month in the recurrence
2452 data.month = *im.current(); 2465 data.month = *im.current();
2453 days = data.dayList(); 2466 days = data.dayList();
2454 for (id = days->begin(); id != days->end(); ++id) { 2467 for (id = days->begin(); id != days->end(); ++id) {
2455 ++countGone; 2468 ++countGone;
2456 if (--countTogo == 0) { 2469 if (--countTogo == 0) {
2457 data.day = *id; 2470 data.day = *id;
2458 goto ex; 2471 goto ex;
2459 } 2472 }
2460 } 2473 }
2461 } 2474 }
2462 countTogo -= data.daysPerMonth; 2475 countTogo -= data.daysPerMonth;
2463 countGone += data.daysPerMonth; 2476 countGone += data.daysPerMonth;
2464 } 2477 }
2465 data.year += rFreq; 2478 data.year += rFreq;
2466 } 2479 }
2467ex: 2480ex:
2468 enddate = data.date(); 2481 enddate = data.date();
2469 return countGone; 2482 return countGone;
2470} 2483}
2471 2484
2472int Recurrence::yearlyPosCalcToDate(const QDate &enddate, YearlyPosData &data) const 2485int Recurrence::yearlyPosCalcToDate(const QDate &enddate, YearlyPosData &data) const
2473{ 2486{
2474 int countGone = 0; 2487 int countGone = 0;
2475 int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX; 2488 int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX;
2476 int endYear = enddate.year(); 2489 int endYear = enddate.year();
2477 int endMonth = enddate.month(); 2490 int endMonth = enddate.month();
2478 int endDay = enddate.day(); 2491 int endDay = enddate.day();
2479 if (endDay < data.day && --endMonth == 0) { 2492 if (endDay < data.day && --endMonth == 0) {
2480 endMonth = 12; 2493 endMonth = 12;
2481 --endYear; 2494 --endYear;
2482 } 2495 }
2483 int endYearMonth = endYear*12 + endMonth; 2496 int endYearMonth = endYear*12 + endMonth;
2484 QValueList<int>::ConstIterator id; 2497 QValueList<int>::ConstIterator id;
2485 const QValueList<int>* days; 2498 const QValueList<int>* days;
2486 2499
2487 if (data.month > 1 || data.day > 1) { 2500 if (data.month > 1 || data.day > 1) {
2488 // Check what remains of the start year 2501 // Check what remains of the start year
2489 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { 2502 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) {
2490 if (*im.current() >= data.month) { 2503 if (*im.current() >= data.month) {
2491 data.month = *im.current(); 2504 data.month = *im.current();
2492 if (data.yearMonth() > endYearMonth) 2505 if (data.yearMonth() > endYearMonth)
2493 return countGone; 2506 return countGone;
2494 // Check what remains of the start month 2507 // Check what remains of the start month
2495 bool lastMonth = (data.yearMonth() == endYearMonth); 2508 bool lastMonth = (data.yearMonth() == endYearMonth);
2496 if (lastMonth || data.day > 1 || data.varies) { 2509 if (lastMonth || data.day > 1 || data.varies) {
2497 days = data.dayList(); 2510 days = data.dayList();
2498 if (lastMonth || data.day > 1) { 2511 if (lastMonth || data.day > 1) {
2499 for (id = days->begin(); id != days->end(); ++id) { 2512 for (id = days->begin(); id != days->end(); ++id) {
2500 if (*id >= data.day) { 2513 if (*id >= data.day) {
2501 if (lastMonth && *id > endDay) 2514 if (lastMonth && *id > endDay)
2502 return countGone; 2515 return countGone;
2503 if (++countGone >= countMax) 2516 if (++countGone >= countMax)
2504 return countMax; 2517 return countMax;
2505 } 2518 }
2506 } 2519 }
2507 } else { 2520 } else {
2508 countGone += days->count(); 2521 countGone += days->count();
2509 if (countGone >= countMax) 2522 if (countGone >= countMax)
2510 return countMax; 2523 return countMax;
2511 } 2524 }
2512 data.day = 1; 2525 data.day = 1;
2513 } else { 2526 } else {
2514 // The number of days per month is constant, so skip 2527 // The number of days per month is constant, so skip
2515 // the whole month. 2528 // the whole month.
2516 countGone += data.daysPerMonth; 2529 countGone += data.daysPerMonth;
2517 if (countGone >= countMax) 2530 if (countGone >= countMax)
2518 return countMax; 2531 return countMax;
2519 } 2532 }
2520 } 2533 }
2521 } 2534 }
2522 data.month = 1; 2535 data.month = 1;
2523 data.year += rFreq; 2536 data.year += rFreq;
2524 } 2537 }
2525 2538
2526 if (data.varies) { 2539 if (data.varies) {
2527 // The number of recurrences varies from year to year. 2540 // The number of recurrences varies from year to year.
2528 for ( ; ; ) { 2541 for ( ; ; ) {
2529 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { 2542 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) {
2530 data.month = *im.current(); 2543 data.month = *im.current();
2531 days = data.dayList(); 2544 days = data.dayList();
2532 if (data.yearMonth() >= endYearMonth) { 2545 if (data.yearMonth() >= endYearMonth) {
2533 if (data.yearMonth() > endYearMonth) 2546 if (data.yearMonth() > endYearMonth)
2534 return countGone; 2547 return countGone;
2535 // Check the last month in the recurrence 2548 // Check the last month in the recurrence
2536 for (id = days->begin(); id != days->end(); ++id) { 2549 for (id = days->begin(); id != days->end(); ++id) {
2537 if (*id > endDay) 2550 if (*id > endDay)
2538 return countGone; 2551 return countGone;
2539 if (++countGone >= countMax) 2552 if (++countGone >= countMax)
2540 return countMax; 2553 return countMax;
2541 } 2554 }
2542 } else { 2555 } else {
2543 countGone += days->count(); 2556 countGone += days->count();
2544 if (countGone >= countMax) 2557 if (countGone >= countMax)
2545 return countMax; 2558 return countMax;
2546 } 2559 }
2547 } 2560 }
2548 data.year += rFreq; 2561 data.year += rFreq;
2549 } 2562 }
2550 } else { 2563 } else {
2551 // The number of recurrences is the same every year, 2564 // The number of recurrences is the same every year,
2552 // so skip the year-by-year check. 2565 // so skip the year-by-year check.
2553 // Skip the remaining whole years, but leave at least 2566 // Skip the remaining whole years, but leave at least
2554 // 1 recurrence remaining, in order to get its date. 2567 // 1 recurrence remaining, in order to get its date.
2555 int wholeYears = endYear - data.year; 2568 int wholeYears = endYear - data.year;
2556 countGone += (wholeYears / rFreq) * data.count; 2569 countGone += (wholeYears / rFreq) * data.count;
2557 if (countGone >= countMax) 2570 if (countGone >= countMax)
2558 return countMax; 2571 return countMax;
2559 if (wholeYears % rFreq) 2572 if (wholeYears % rFreq)
2560 return countGone; // end year isn't a recurrence year 2573 return countGone; // end year isn't a recurrence year
2561 data.year = endYear; 2574 data.year = endYear;
2562 2575
2563 // Check the last year in the recurrence. 2576 // Check the last year in the recurrence.
2564 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { 2577 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) {
2565 data.month = *im.current(); 2578 data.month = *im.current();
2566 if (data.month >= endMonth) { 2579 if (data.month >= endMonth) {
2567 if (data.month > endMonth) 2580 if (data.month > endMonth)
2568 return countGone; 2581 return countGone;
2569 // Check the last month in the recurrence 2582 // Check the last month in the recurrence
2570 days = data.dayList(); 2583 days = data.dayList();
2571 for (id = days->begin(); id != days->end(); ++id) { 2584 for (id = days->begin(); id != days->end(); ++id) {
2572 if (*id > endDay) 2585 if (*id > endDay)
2573 return countGone; 2586 return countGone;
2574 if (++countGone >= countMax) 2587 if (++countGone >= countMax)
2575 return countMax; 2588 return countMax;
2576 } 2589 }
2577 } else { 2590 } else {
2578 countGone += data.daysPerMonth; 2591 countGone += data.daysPerMonth;
2579 if (countGone >= countMax) 2592 if (countGone >= countMax)
2580 return countMax; 2593 return countMax;
2581 } 2594 }
2582 } 2595 }
2583 } 2596 }
2584 return countGone; 2597 return countGone;
2585} 2598}
2586 2599
2587int Recurrence::yearlyPosCalcNextAfter(QDate &enddate, YearlyPosData &data) const 2600int Recurrence::yearlyPosCalcNextAfter(QDate &enddate, YearlyPosData &data) const
2588{ 2601{
2589 uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX; 2602 uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX;
2590 int countGone = 0; 2603 int countGone = 0;
2591 int endYear = enddate.year(); 2604 int endYear = enddate.year();
2592 int endMonth = enddate.month(); 2605 int endMonth = enddate.month();
2593 int endDay = enddate.day(); 2606 int endDay = enddate.day();
2594 if (endDay < data.day && --endMonth == 0) { 2607 if (endDay < data.day && --endMonth == 0) {
2595 endMonth = 12; 2608 endMonth = 12;
2596 --endYear; 2609 --endYear;
2597 } 2610 }
2598 int endYearMonth = endYear*12 + endMonth; 2611 int endYearMonth = endYear*12 + endMonth;
2599 QValueList<int>::ConstIterator id; 2612 QValueList<int>::ConstIterator id;
2600 const QValueList<int>* days; 2613 const QValueList<int>* days;
2601 2614
2602 if (data.varies) { 2615 if (data.varies) {
2603 // The number of recurrences varies from year to year. 2616 // The number of recurrences varies from year to year.
2604 for ( ; ; ) { 2617 for ( ; ; ) {
2605 // Check the next year 2618 // Check the next year
2606 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { 2619 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) {
2607 if (*im.current() >= data.month) { 2620 if (*im.current() >= data.month) {
2608 // Check the next month 2621 // Check the next month
2609 data.month = *im.current(); 2622 data.month = *im.current();
2610 int ended = data.yearMonth() - endYearMonth; 2623 int ended = data.yearMonth() - endYearMonth;
2611 days = data.dayList(); 2624 days = data.dayList();
2612 if (ended >= 0 || data.day > 1) { 2625 if (ended >= 0 || data.day > 1) {
2613 // This is the start or end month, so check each day 2626 // This is the start or end month, so check each day
2614 for (id = days->begin(); id != days->end(); ++id) { 2627 for (id = days->begin(); id != days->end(); ++id) {
2615 if (*id >= data.day) { 2628 if (*id >= data.day) {
2616 ++countGone; 2629 ++countGone;
2617 if (ended > 0 || (ended == 0 && *id > endDay)) { 2630 if (ended > 0 || (ended == 0 && *id > endDay)) {
2618 data.day = *id; 2631 data.day = *id;
2619 goto ex; 2632 goto ex;
2620 } 2633 }
2621 if (--countTogo == 0) 2634 if (--countTogo == 0)
2622 return 0; 2635 return 0;
2623 } 2636 }
2624 } 2637 }
2625 } else { 2638 } else {
2626 // Skip the whole month 2639 // Skip the whole month
2627 uint n = days->count(); 2640 uint n = days->count();
2628 if (n >= countTogo) 2641 if (n >= countTogo)
2629 return 0; 2642 return 0;
2630 countGone += n; 2643 countGone += n;
2631 } 2644 }
2632 data.day = 1; // we've checked the start month now 2645 data.day = 1; // we've checked the start month now
2633 } 2646 }
2634 } 2647 }
2635 data.month = 1; // we've checked the start year now 2648 data.month = 1; // we've checked the start year now
2636 data.year += rFreq; 2649 data.year += rFreq;
2637 } 2650 }
2638 } else { 2651 } else {
2639 // The number of recurrences is the same every year. 2652 // The number of recurrences is the same every year.
2640 if (data.month > 1 || data.day > 1) { 2653 if (data.month > 1 || data.day > 1) {
2641 // Check what remains of the start year 2654 // Check what remains of the start year
2642 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { 2655 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) {
2643 if (*im.current() >= data.month) { 2656 if (*im.current() >= data.month) {
2644 // Check what remains of the start month 2657 // Check what remains of the start month
2645 data.month = *im.current(); 2658 data.month = *im.current();
2646 int ended = data.yearMonth() - endYearMonth; 2659 int ended = data.yearMonth() - endYearMonth;
2647 if (ended >= 0 || data.day > 1) { 2660 if (ended >= 0 || data.day > 1) {
2648 // This is the start or end month, so check each day 2661 // This is the start or end month, so check each day
2649 days = data.dayList(); 2662 days = data.dayList();
2650 for (id = days->begin(); id != days->end(); ++id) { 2663 for (id = days->begin(); id != days->end(); ++id) {
2651 if (*id >= data.day) { 2664 if (*id >= data.day) {
2652 ++countGone; 2665 ++countGone;
2653 if (ended > 0 || (ended == 0 && *id > endDay)) { 2666 if (ended > 0 || (ended == 0 && *id > endDay)) {
2654 data.day = *id; 2667 data.day = *id;
2655 goto ex; 2668 goto ex;
2656 } 2669 }
2657 if (--countTogo == 0) 2670 if (--countTogo == 0)
2658 return 0; 2671 return 0;
2659 } 2672 }
2660 } 2673 }
2661 data.day = 1; // we've checked the start month now 2674 data.day = 1; // we've checked the start month now
2662 } else { 2675 } else {
2663 // Skip the whole month. 2676 // Skip the whole month.
2664 if (static_cast<uint>(data.daysPerMonth) >= countTogo) 2677 if (static_cast<uint>(data.daysPerMonth) >= countTogo)
2665 return 0; 2678 return 0;
2666 countGone += data.daysPerMonth; 2679 countGone += data.daysPerMonth;
2667 } 2680 }
2668 } 2681 }
2669 } 2682 }
2670 data.year += rFreq; 2683 data.year += rFreq;
2671 } 2684 }
2672 // Skip the remaining whole years to at least endYear. 2685 // Skip the remaining whole years to at least endYear.
2673 int recurYears = (endYear - data.year + rFreq - 1) / rFreq; 2686 int recurYears = (endYear - data.year + rFreq - 1) / rFreq;
2674 if ((endYear - data.year)%rFreq == 0 2687 if ((endYear - data.year)%rFreq == 0
2675 && *rYearNums.getLast() <= endMonth) 2688 && *rYearNums.getLast() <= endMonth)
2676 ++recurYears; // required year is after endYear 2689 ++recurYears; // required year is after endYear
2677 if (recurYears) { 2690 if (recurYears) {
2678 int n = recurYears * data.count; 2691 int n = recurYears * data.count;
2679 if (static_cast<uint>(n) > countTogo) 2692 if (static_cast<uint>(n) > countTogo)
2680 return 0; // reached end of recurrence 2693 return 0; // reached end of recurrence
2681 countTogo -= n; 2694 countTogo -= n;
2682 countGone += n; 2695 countGone += n;
2683 data.year += recurYears * rFreq; 2696 data.year += recurYears * rFreq;
2684 } 2697 }
2685 2698
2686 // Check the last year in the recurrence 2699 // Check the last year in the recurrence
2687 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) { 2700 for (QPtrListIterator<int> im(rYearNums); im.current(); ++im) {
2688 data.month = *im.current(); 2701 data.month = *im.current();
2689 int ended = data.yearMonth() - endYearMonth; 2702 int ended = data.yearMonth() - endYearMonth;
2690 if (ended >= 0) { 2703 if (ended >= 0) {
2691 // This is the end month, so check each day 2704 // This is the end month, so check each day
2692 days = data.dayList(); 2705 days = data.dayList();
2693 for (id = days->begin(); id != days->end(); ++id) { 2706 for (id = days->begin(); id != days->end(); ++id) {
2694 ++countGone; 2707 ++countGone;
2695 if (ended > 0 || (ended == 0 && *id > endDay)) { 2708 if (ended > 0 || (ended == 0 && *id > endDay)) {
2696 data.day = *id; 2709 data.day = *id;
2697 goto ex; 2710 goto ex;
2698 } 2711 }
2699 if (--countTogo == 0) 2712 if (--countTogo == 0)
2700 return 0; 2713 return 0;
2701 } 2714 }
2702 } else { 2715 } else {
2703 // Skip the whole month. 2716 // Skip the whole month.
2704 if (static_cast<uint>(data.daysPerMonth) >= countTogo) 2717 if (static_cast<uint>(data.daysPerMonth) >= countTogo)
2705 return 0; 2718 return 0;
2706 countGone += data.daysPerMonth; 2719 countGone += data.daysPerMonth;
2707 } 2720 }
2708 } 2721 }
2709 } 2722 }
2710ex: 2723ex:
2711 enddate = data.date(); 2724 enddate = data.date();
2712 return countGone; 2725 return countGone;
2713} 2726}
2714 2727
2715 2728
2716/* Find count and, depending on 'func', the end date of an annual recurrence by day. 2729/* Find count and, depending on 'func', the end date of an annual recurrence by day.
2717 * Reply = total number of occurrences up to 'enddate', or 0 if error. 2730 * Reply = total number of occurrences up to 'enddate', or 0 if error.
2718 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the 2731 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the
2719 * recurrence end date. 2732 * recurrence end date.
2720 */ 2733 */
2721struct Recurrence::YearlyDayData { 2734struct Recurrence::YearlyDayData {
2722 int year; // current year 2735 int year; // current year
2723 int day; // current day of year 1..366 2736 int day; // current day of year 1..366
2724 bool varies; // true if day 366 recurs 2737 bool varies; // true if day 366 recurs
2725 private: 2738 private:
2726 int daycount; 2739 int daycount;
2727 public: 2740 public:
2728 YearlyDayData(const Recurrence* r, const QDate &date) 2741 YearlyDayData(const Recurrence* r, const QDate &date)
2729 : year(date.year()), day(date.dayOfYear()), varies(*r->rYearNums.getLast() == 366), 2742 : year(date.year()), day(date.dayOfYear()), varies(*r->rYearNums.getLast() == 366),
2730 daycount(r->rYearNums.count()) { } 2743 daycount(r->rYearNums.count()) { }
2731 bool leapYear() const { return QDate::leapYear(year); } 2744 bool leapYear() const { return QDate::leapYear(year); }
2732 int dayCount() const { return daycount - (varies && !QDate::leapYear(year) ? 1 : 0); } 2745 int dayCount() const { return daycount - (varies && !QDate::leapYear(year) ? 1 : 0); }
2733 bool isMaxDayCount() const { return !varies || QDate::leapYear(year); } 2746 bool isMaxDayCount() const { return !varies || QDate::leapYear(year); }
2734 QDate date() const { return QDate(year, 1, 1).addDays(day - 1); } 2747 QDate date() const { return QDate(year, 1, 1).addDays(day - 1); }
2735}; 2748};
2736 2749
2737int Recurrence::yearlyDayCalc(PeriodFunc func, QDate &enddate) const 2750int Recurrence::yearlyDayCalc(PeriodFunc func, QDate &enddate) const
2738{ 2751{
2739 if (rYearNums.isEmpty()) 2752 if (rYearNums.isEmpty())
2740 return 0; 2753 return 0;
2741 YearlyDayData data(this, mRecurStart.date()); 2754 YearlyDayData data(this, mRecurStart.date());
2742 switch (func) { 2755 switch (func) {
2743 case END_DATE_AND_COUNT: 2756 case END_DATE_AND_COUNT:
2744 return yearlyDayCalcEndDate(enddate, data); 2757 return yearlyDayCalcEndDate(enddate, data);
2745 case COUNT_TO_DATE: 2758 case COUNT_TO_DATE:
2746 return yearlyDayCalcToDate(enddate, data); 2759 return yearlyDayCalcToDate(enddate, data);
2747 case NEXT_AFTER_DATE: 2760 case NEXT_AFTER_DATE:
2748 return yearlyDayCalcNextAfter(enddate, data); 2761 return yearlyDayCalcNextAfter(enddate, data);
2749 } 2762 }
2750 return 0; 2763 return 0;
2751} 2764}
2752 2765
2753int Recurrence::yearlyDayCalcEndDate(QDate &enddate, YearlyDayData &data) const 2766int Recurrence::yearlyDayCalcEndDate(QDate &enddate, YearlyDayData &data) const
2754{ 2767{
2755 uint countTogo = rDuration + mRecurExDatesCount; 2768 uint countTogo = rDuration + mRecurExDatesCount;
2756 int countGone = 0; 2769 int countGone = 0;
2757 2770
2758 if (data.day > 1) { 2771 if (data.day > 1) {
2759 // Check what remains of the start year 2772 // Check what remains of the start year
2760 bool leapOK = data.isMaxDayCount(); 2773 bool leapOK = data.isMaxDayCount();
2761 for (QPtrListIterator<int> it(rYearNums); it.current(); ++it) { 2774 for (QPtrListIterator<int> it(rYearNums); it.current(); ++it) {
2762 int d = *it.current(); 2775 int d = *it.current();
2763 if (d >= data.day && (leapOK || d < 366)) { 2776 if (d >= data.day && (leapOK || d < 366)) {
2764 ++countGone; 2777 ++countGone;
2765 if (--countTogo == 0) { 2778 if (--countTogo == 0) {
2766 data.day = d; 2779 data.day = d;
2767 goto ex; 2780 goto ex;
2768 } 2781 }
2769 } 2782 }
2770 } 2783 }
2771 data.day = 1; 2784 data.day = 1;
2772 data.year += rFreq; 2785 data.year += rFreq;
2773 } 2786 }
2774 2787
2775 if (data.varies) { 2788 if (data.varies) {
2776 // The number of recurrences is different in leap years, 2789 // The number of recurrences is different in leap years,
diff --git a/libkcal/recurrence.h b/libkcal/recurrence.h
index a0f6d84..b13d14f 100644
--- a/libkcal/recurrence.h
+++ b/libkcal/recurrence.h
@@ -1,401 +1,401 @@
1/* 1/*
2 This file is part of libkcal. 2 This file is part of libkcal.
3 Copyright (c) 1998 Preston Brown 3 Copyright (c) 1998 Preston Brown
4 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> 4 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
5 Copyright (c) 2002 David Jarvie <software@astrojar.org.uk> 5 Copyright (c) 2002 David Jarvie <software@astrojar.org.uk>
6 6
7 This library is free software; you can redistribute it and/or 7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public 8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either 9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version. 10 version 2 of the License, or (at your option) any later version.
11 11
12 This library is distributed in the hope that it will be useful, 12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details. 15 Library General Public License for more details.
16 16
17 You should have received a copy of the GNU Library General Public License 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 18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. 20 Boston, MA 02111-1307, USA.
21*/ 21*/
22#ifndef KCAL_RECURRENCE_H 22#ifndef KCAL_RECURRENCE_H
23#define KCAL_RECURRENCE_H 23#define KCAL_RECURRENCE_H
24 24
25#include <qstring.h> 25#include <qstring.h>
26#include <qbitarray.h> 26#include <qbitarray.h>
27#include <qptrlist.h> 27#include <qptrlist.h>
28 28
29namespace KCal { 29namespace KCal {
30 30
31class Incidence; 31class Incidence;
32 32
33/** 33/**
34 This class represents a recurrence rule for a calendar incidence. 34 This class represents a recurrence rule for a calendar incidence.
35*/ 35*/
36class Recurrence 36class Recurrence
37{ 37{
38 public: 38 public:
39 /** enumeration for describing how an event recurs, if at all. */ 39 /** enumeration for describing how an event recurs, if at all. */
40 enum { rNone = 0, rMinutely = 0x001, rHourly = 0x0002, rDaily = 0x0003, 40 enum { rNone = 0, rMinutely = 0x001, rHourly = 0x0002, rDaily = 0x0003,
41 rWeekly = 0x0004, rMonthlyPos = 0x0005, rMonthlyDay = 0x0006, 41 rWeekly = 0x0004, rMonthlyPos = 0x0005, rMonthlyDay = 0x0006,
42 rYearlyMonth = 0x0007, rYearlyDay = 0x0008, rYearlyPos = 0x0009 }; 42 rYearlyMonth = 0x0007, rYearlyDay = 0x0008, rYearlyPos = 0x0009 };
43 43
44 /** Enumeration for specifying what date yearly recurrences of February 29th occur 44 /** Enumeration for specifying what date yearly recurrences of February 29th occur
45 * in non-leap years. */ 45 * in non-leap years. */
46 enum Feb29Type { 46 enum Feb29Type {
47 rMar1, // recur on March 1st (default) 47 rMar1, // recur on March 1st (default)
48 rFeb28, // recur on February 28th 48 rFeb28, // recur on February 28th
49 rFeb29 // only recur on February 29th, i.e. don't recur in non-leap years 49 rFeb29 // only recur on February 29th, i.e. don't recur in non-leap years
50 }; 50 };
51 51
52 /** structure for Recurs rMonthlyPos */ 52 /** structure for Recurs rMonthlyPos */
53 struct rMonthPos { 53 struct rMonthPos {
54 QBitArray rDays; 54 QBitArray rDays;
55 short rPos; 55 short rPos;
56 bool negative; 56 bool negative;
57 }; 57 };
58 58
59 Recurrence(Incidence *parent, int compatVersion = 0); 59 Recurrence(Incidence *parent, int compatVersion = 0);
60 Recurrence(const Recurrence&, Incidence *parent); 60 Recurrence(const Recurrence&, Incidence *parent);
61 ~Recurrence(); 61 ~Recurrence();
62 62
63 bool operator==( const Recurrence& ) const; 63 bool operator==( const Recurrence& ) const;
64 bool operator!=( const Recurrence& r ) const { return !operator==(r); } 64 bool operator!=( const Recurrence& r ) const { return !operator==(r); }
65 65
66 Incidence *parent() { return mParent; } 66 Incidence *parent() { return mParent; }
67 67
68 /** Return the start of the recurrence */ 68 /** Return the start of the recurrence */
69 QDateTime recurStart() const { return mRecurStart; } 69 QDateTime recurStart() const { return mRecurStart; }
70 /** Returns the number of exception dates for the recurrence */ 70 /** Returns the number of exception dates for the recurrence */
71 int recurExDatesCount() const { return mRecurExDatesCount; } 71 int recurExDatesCount() const { return mRecurExDatesCount; }
72 /** Set start of recurrence, as a date and time. */ 72 /** Set start of recurrence, as a date and time. */
73 void setRecurStart(const QDateTime &start); 73 void setRecurStart(const QDateTime &start);
74 /** Set start of recurrence, as a date with no time. 74 /** Set start of recurrence, as a date with no time.
75 * Recurrence types which are sub-daily (e.g. rHourly) always have a time; 75 * Recurrence types which are sub-daily (e.g. rHourly) always have a time;
76 * the time is set to 00:00:00 in these cases. */ 76 * the time is set to 00:00:00 in these cases. */
77 void setRecurStart(const QDate &start); 77 void setRecurStart(const QDate &start);
78 /** Set whether the recurrence has no time, just a date. 78 /** Set whether the recurrence has no time, just a date.
79 * Recurrence types which are sub-daily (e.g. rHourly) always have a time 79 * Recurrence types which are sub-daily (e.g. rHourly) always have a time
80 * and cannot be set to float. 80 * and cannot be set to float.
81 * N.B. This property is derived by default from the parent incidence, 81 * N.B. This property is derived by default from the parent incidence,
82 * or according to whether a time is specified in setRecurStart(). */ 82 * or according to whether a time is specified in setRecurStart(). */
83 void setFloats(bool f); 83 void setFloats(bool f);
84 /** 84 /**
85 Returns whether the recurrence has no time, just a date. 85 Returns whether the recurrence has no time, just a date.
86 */ 86 */
87 bool doesFloat() const { 87 bool doesFloat() const {
88 return mFloats; 88 return mFloats;
89 } 89 }
90 90
91 /** Set if recurrence is read-only or can be changed. */ 91 /** Set if recurrence is read-only or can be changed. */
92 void setRecurReadOnly(bool readOnly) { mRecurReadOnly = readOnly; } 92 void setRecurReadOnly(bool readOnly) { mRecurReadOnly = readOnly; }
93 bool recurReadOnly() const 93 bool recurReadOnly() const
94 { 94 {
95 return mRecurReadOnly; 95 return mRecurReadOnly;
96 } 96 }
97 97
98 98
99 /** Set number of exception dates. */ 99 /** Set number of exception dates. */
100 void setRecurExDatesCount(int count) { if (count >= 0) mRecurExDatesCount = count; } 100 void setRecurExDatesCount(int count) { if (count >= 0) mRecurExDatesCount = count; }
101 /** Set the calendar file version for backwards compatibility. 101 /** Set the calendar file version for backwards compatibility.
102 * @var version is the KOrganizer/libkcal version, e.g. 220 for KDE 2.2.0. 102 * @var version is the KOrganizer/libkcal version, e.g. 220 for KDE 2.2.0.
103 * Specify version = 0 to cancel compatibility mode. 103 * Specify version = 0 to cancel compatibility mode.
104 */ 104 */
105 void setCompatVersion(int version = 0); 105 void setCompatVersion(int version = 0);
106 106
107 /** Returns the event's recurrence status. See the enumeration at the top 107 /** Returns the event's recurrence status. See the enumeration at the top
108 * of this file for possible values. */ 108 * of this file for possible values. */
109 ushort doesRecur() const; 109 ushort doesRecur() const;
110 /** Returns true if the date specified is one on which the event will 110 /** Returns true if the date specified is one on which the event will
111 * recur. */ 111 * recur. */
112 bool recursOnPure(const QDate &qd) const; 112 bool recursOnPure(const QDate &qd) const;
113 /** Returns true if the date/time specified is one at which the event will 113 /** Returns true if the date/time specified is one at which the event will
114 * recur. Times are rounded down to the nearest minute to determine the result. */ 114 * recur. Times are rounded down to the nearest minute to determine the result. */
115 bool recursAtPure(const QDateTime &) const; 115 bool recursAtPure(const QDateTime &) const;
116 /** Turns off recurrence for the event. */ 116 /** Turns off recurrence for the event. */
117 void unsetRecurs(); 117 void unsetRecurs();
118 118
119 /** Returns the date of the next recurrence, after the specified date. 119 /** Returns the date of the next recurrence, after the specified date.
120 * @var preDate the date after which to find the recurrence. 120 * @var preDate the date after which to find the recurrence.
121 * @var last if non-null, *last is set to true if the next recurrence is the 121 * @var last if non-null, *last is set to true if the next recurrence is the
122 * last recurrence, else false. 122 * last recurrence, else false.
123 * Reply = date of next recurrence, or invalid date if none. 123 * Reply = date of next recurrence, or invalid date if none.
124 */ 124 */
125 QDate getNextDate(const QDate& preDate, bool* last = 0) const; 125 QDate getNextDate(const QDate& preDate, bool* last = 0) const;
126 /** Returns the date and time of the next recurrence, after the specified date/time. 126 /** Returns the date and time of the next recurrence, after the specified date/time.
127 * If the recurrence has no time, the next date after the specified date is returned. 127 * If the recurrence has no time, the next date after the specified date is returned.
128 * @var preDate the date/time after which to find the recurrence. 128 * @var preDate the date/time after which to find the recurrence.
129 * @var last if non-null, *last is set to true if the next recurrence is the 129 * @var last if non-null, *last is set to true if the next recurrence is the
130 * last recurrence, else false. 130 * last recurrence, else false.
131 * Reply = date/time of next recurrence, or invalid date if none. 131 * Reply = date/time of next recurrence, or invalid date if none.
132 */ 132 */
133 QDateTime getNextDateTime(const QDateTime& preDateTime, bool* last = 0) const; 133 QDateTime getNextDateTime(const QDateTime& preDateTime, bool* last = 0) const;
134 /** Returns the date of the last previous recurrence, before the specified date. 134 /** Returns the date of the last previous recurrence, before the specified date.
135 * @var afterDate the date before which to find the recurrence. 135 * @var afterDate the date before which to find the recurrence.
136 * @var last if non-null, *last is set to true if the previous recurrence is the 136 * @var last if non-null, *last is set to true if the previous recurrence is the
137 * last recurrence, else false. 137 * last recurrence, else false.
138 * Reply = date of previous recurrence, or invalid date if none. 138 * Reply = date of previous recurrence, or invalid date if none.
139 */ 139 */
140 QDate getPreviousDate(const QDate& afterDate, bool* last = 0) const; 140 QDate getPreviousDate(const QDate& afterDate, bool* last = 0) const;
141 /** Returns the date and time of the last previous recurrence, before the specified date/time. 141 /** Returns the date and time of the last previous recurrence, before the specified date/time.
142 * If a time later than 00:00:00 is specified and the recurrence has no time, 00:00:00 on 142 * If a time later than 00:00:00 is specified and the recurrence has no time, 00:00:00 on
143 * the specified date is returned if that date recurs. 143 * the specified date is returned if that date recurs.
144 * @var afterDate the date/time before which to find the recurrence. 144 * @var afterDate the date/time before which to find the recurrence.
145 * @var last if non-null, *last is set to true if the previous recurrence is the 145 * @var last if non-null, *last is set to true if the previous recurrence is the
146 * last recurrence, else false. 146 * last recurrence, else false.
147 * Reply = date/time of previous recurrence, or invalid date if none. 147 * Reply = date/time of previous recurrence, or invalid date if none.
148 */ 148 */
149 QDateTime getPreviousDateTime(const QDateTime& afterDateTime, bool* last = 0) const; 149 QDateTime getPreviousDateTime(const QDateTime& afterDateTime, bool* last = 0) const;
150 150
151 /** Returns frequency of recurrence, in terms of the recurrence time period type. */ 151 /** Returns frequency of recurrence, in terms of the recurrence time period type. */
152 int frequency() const; 152 int frequency() const;
153 /** Returns the total number of recurrences, including the initial occurrence. */ 153 /** Returns the total number of recurrences, including the initial occurrence. */
154 int duration() const; 154 int duration() const;
155 /** Sets the total number of times the event is to occur, including both the 155 /** Sets the total number of times the event is to occur, including both the
156 * first and last. */ 156 * first and last. */
157 void setDuration(int duration); 157 void setDuration(int duration);
158 /** Returns the number of recurrences up to and including the date specified. */ 158 /** Returns the number of recurrences up to and including the date specified. */
159 int durationTo(const QDate &) const; 159 int durationTo(const QDate &) const;
160 /** Returns the number of recurrences up to and including the date/time specified. */ 160 /** Returns the number of recurrences up to and including the date/time specified. */
161 int durationTo(const QDateTime &) const; 161 int durationTo(const QDateTime &) const;
162 162
163 /** Returns the date of the last recurrence. 163 /** Returns the date of the last recurrence.
164 * An invalid date is returned if the recurrence has no end. 164 * An invalid date is returned if the recurrence has no end.
165 * Note: for some recurrence types, endDate() can involve significant calculation. 165 * Note: for some recurrence types, endDate() can involve significant calculation.
166 */ 166 */
167 QDate endDate() const; 167 QDate endDate() const;
168 /** Returns the date and time of the last recurrence. 168 /** Returns the date and time of the last recurrence.
169 * An invalid date is returned if the recurrence has no end. 169 * An invalid date is returned if the recurrence has no end.
170 * Note: for some recurrence types, endDateTime() can involve significant calculation. 170 * Note: for some recurrence types, endDateTime() can involve significant calculation.
171 */ 171 */
172 QDateTime endDateTime() const; 172 QDateTime endDateTime() const;
173 /** Returns a string representing the recurrence end date in the format 173 /** Returns a string representing the recurrence end date in the format
174 according to the user's locale settings. */ 174 according to the user's locale settings. */
175 QString endDateStr(bool shortfmt=true) const; 175 QString endDateStr(bool shortfmt=true) const;
176 176
177 /** Sets an event to recur minutely. 177 /** Sets an event to recur minutely.
178 * @var _rFreq the frequency to recur, e.g. 2 is every other minute 178 * @var _rFreq the frequency to recur, e.g. 2 is every other minute
179 * @var duration the number of times the event is to occur, or -1 to recur indefinitely. 179 * @var duration the number of times the event is to occur, or -1 to recur indefinitely.
180 */ 180 */
181 void setMinutely(int _rFreq, int duration); 181 void setMinutely(int _rFreq, int duration);
182 /** Sets an event to recur minutely. 182 /** Sets an event to recur minutely.
183 * @var _rFreq the frequency to recur, e.g. 2 is every other minute 183 * @var _rFreq the frequency to recur, e.g. 2 is every other minute
184 * @var endDateTime the ending date/time after which to stop recurring 184 * @var endDateTime the ending date/time after which to stop recurring
185 */ 185 */
186 void setMinutely(int _rFreq, const QDateTime &endDateTime); 186 void setMinutely(int _rFreq, const QDateTime &endDateTime);
187 187
188 /** Sets an event to recur hourly. 188 /** Sets an event to recur hourly.
189 * @var _rFreq the frequency to recur, e.g. 2 is every other hour 189 * @var _rFreq the frequency to recur, e.g. 2 is every other hour
190 * @var duration the number of times the event is to occur, or -1 to recur indefinitely. 190 * @var duration the number of times the event is to occur, or -1 to recur indefinitely.
191 */ 191 */
192 void setHourly(int _rFreq, int duration); 192 void setHourly(int _rFreq, int duration);
193 /** Sets an event to recur hourly. 193 /** Sets an event to recur hourly.
194 * @var _rFreq the frequency to recur, e.g. 2 is every other hour 194 * @var _rFreq the frequency to recur, e.g. 2 is every other hour
195 * @var endDateTime the ending date/time after which to stop recurring 195 * @var endDateTime the ending date/time after which to stop recurring
196 */ 196 */
197 void setHourly(int _rFreq, const QDateTime &endDateTime); 197 void setHourly(int _rFreq, const QDateTime &endDateTime);
198 198
199 /** Sets an event to recur daily. 199 /** Sets an event to recur daily.
200 * @var _rFreq the frequency to recur, e.g. 2 is every other day 200 * @var _rFreq the frequency to recur, e.g. 2 is every other day
201 * @var duration the number of times the event is to occur, or -1 to recur indefinitely. 201 * @var duration the number of times the event is to occur, or -1 to recur indefinitely.
202 */ 202 */
203 void setDaily(int _rFreq, int duration); 203 void setDaily(int _rFreq, int duration);
204 /** Sets an event to recur daily. 204 /** Sets an event to recur daily.
205 * @var _rFreq the frequency to recur, e.g. 2 is every other day 205 * @var _rFreq the frequency to recur, e.g. 2 is every other day
206 * @var endDate the ending date after which to stop recurring 206 * @var endDate the ending date after which to stop recurring
207 */ 207 */
208 void setDaily(int _rFreq, const QDate &endDate); 208 void setDaily(int _rFreq, const QDate &endDate);
209 209
210 /** Sets an event to recur weekly. 210 /** Sets an event to recur weekly.
211 * @var _rFreq the frequency to recur, e.g. every other week etc. 211 * @var _rFreq the frequency to recur, e.g. every other week etc.
212 * @var _rDays a 7 bit array indicating which days on which to recur (bit 0 = Monday). 212 * @var _rDays a 7 bit array indicating which days on which to recur (bit 0 = Monday).
213 * @var duration the number of times the event is to occur, or -1 to recur indefinitely. 213 * @var duration the number of times the event is to occur, or -1 to recur indefinitely.
214 * @var weekStart the first day of the week (Monday=1 .. Sunday=7, default is Monday). 214 * @var weekStart the first day of the week (Monday=1 .. Sunday=7, default is Monday).
215 */ 215 */
216 void setWeekly(int _rFreq, const QBitArray &_rDays, int duration, int weekStart = 1); 216 void setWeekly(int _rFreq, const QBitArray &_rDays, int duration, int weekStart = 1);
217 /** Sets an event to recur weekly. 217 /** Sets an event to recur weekly.
218 * @var _rFreq the frequency to recur, e.g. every other week etc. 218 * @var _rFreq the frequency to recur, e.g. every other week etc.
219 * @var _rDays a 7 bit array indicating which days on which to recur (bit 0 = Monday). 219 * @var _rDays a 7 bit array indicating which days on which to recur (bit 0 = Monday).
220 * @var endDate the date on which to stop recurring. 220 * @var endDate the date on which to stop recurring.
221 * @var weekStart the first day of the week (Monday=1 .. Sunday=7, default is Monday). 221 * @var weekStart the first day of the week (Monday=1 .. Sunday=7, default is Monday).
222 */ 222 */
223 void setWeekly(int _rFreq, const QBitArray &_rDays, const QDate &endDate, int weekStart = 1); 223 void setWeekly(int _rFreq, const QBitArray &_rDays, const QDate &endDate, int weekStart = 1);
224 /** Returns the first day of the week. Monday=1 .. Sunday=7. */ 224 /** Returns the first day of the week. Monday=1 .. Sunday=7. */
225 int weekStart() const { return rWeekStart; } 225 int weekStart() const { return rWeekStart; }
226 /** Returns week day mask (bit 0 = Monday). */ 226 /** Returns week day mask (bit 0 = Monday). */
227 const QBitArray &days() const; 227 const QBitArray &days() const;
228 228
229 /** Sets an event to recur monthly. 229 /** Sets an event to recur monthly.
230 * @var type rMonthlyPos or rMonthlyDay 230 * @var type rMonthlyPos or rMonthlyDay
231 * @var _rFreq the frequency to recur, e.g. 3 for every third month. 231 * @var _rFreq the frequency to recur, e.g. 3 for every third month.
232 * @var duration the number of times the event is to occur, or -1 to recur indefinitely. 232 * @var duration the number of times the event is to occur, or -1 to recur indefinitely.
233 */ 233 */
234 void setMonthly(short type, int _rFreq, int duration); 234 void setMonthly(short type, int _rFreq, int duration);
235 /** same as above, but with ending date not number of recurrences */ 235 /** same as above, but with ending date not number of recurrences */
236 void setMonthly(short type, int _rFreq, const QDate &endDate); 236 void setMonthly(short type, int _rFreq, const QDate &endDate);
237 /** Adds a position to the recursMonthlyPos recurrence rule, if it is 237 /** Adds a position to the recursMonthlyPos recurrence rule, if it is
238 * set. 238 * set.
239 * @var _rPos the position in the month for the recurrence, with valid 239 * @var _rPos the position in the month for the recurrence, with valid
240 * values being 1-5 (5 weeks max in a month). 240 * values being 1-5 (5 weeks max in a month).
241 * @var _rDays the days for the position to recur on (bit 0 = Monday). 241 * @var _rDays the days for the position to recur on (bit 0 = Monday).
242 * Example: _rPos = 2, and bits 0 and 2 are set in _rDays: 242 * Example: _rPos = 2, and bits 0 and 2 are set in _rDays:
243 * the rule is to repeat every 2nd Monday and Wednesday in the month. 243 * the rule is to repeat every 2nd Monday and Wednesday in the month.
244 */ 244 */
245 void addMonthlyPos(short _rPos, const QBitArray &_rDays); 245 void addMonthlyPos(short _rPos, const QBitArray &_rDays);
246 /** Adds a position the the recursMonthlyDay list. 246 /** Adds a position the the recursMonthlyDay list.
247 * @var _rDay the date in the month to recur. 247 * @var _rDay the date in the month to recur.
248 */ 248 */
249 void addMonthlyDay(short _rDay); 249 void addMonthlyDay(short _rDay);
250 /** Returns list of day positions in months. */ 250 /** Returns list of day positions in months. */
251 const QPtrList<rMonthPos> &monthPositions() const; 251 const QPtrList<rMonthPos> &monthPositions() const;
252 /** Returns list of day numbers of a month. */ 252 /** Returns list of day numbers of a month. */
253 const QPtrList<int> &monthDays() const; 253 const QPtrList<int> &monthDays() const;
254 254
255 /** Sets an event to recur yearly. 255 /** Sets an event to recur yearly.
256 * @var type rYearlyMonth, rYearlyPos or rYearlyDay 256 * @var type rYearlyMonth, rYearlyPos or rYearlyDay
257 * @var freq the frequency to recur, e.g. 3 for every third year. 257 * @var freq the frequency to recur, e.g. 3 for every third year.
258 * @var duration the number of times the event is to occur, or -1 to recur indefinitely. 258 * @var duration the number of times the event is to occur, or -1 to recur indefinitely.
259 */ 259 */
260 void setYearly(int type, int freq, int duration); 260 void setYearly(int type, int freq, int duration);
261 /** Sets an event to recur yearly ending at \a endDate. */ 261 /** Sets an event to recur yearly ending at \a endDate. */
262 void setYearly(int type, int freq, const QDate &endDate); 262 void setYearly(int type, int freq, const QDate &endDate);
263 /** Sets an event to recur yearly on specified dates. 263 /** Sets an event to recur yearly on specified dates.
264 * The dates must be specified by calling addYearlyNum(). 264 * The dates must be specified by calling addYearlyNum().
265 * @var type the way recurrences of February 29th are to be handled in non-leap years. 265 * @var type the way recurrences of February 29th are to be handled in non-leap years.
266 * @var freq the frequency to recur, e.g. 3 for every third year. 266 * @var freq the frequency to recur, e.g. 3 for every third year.
267 * @var duration the number of times the event is to occur, or -1 to recur indefinitely. 267 * @var duration the number of times the event is to occur, or -1 to recur indefinitely.
268 */ 268 */
269 void setYearlyByDate(Feb29Type type, int freq, int duration); 269 void setYearlyByDate(Feb29Type type, int freq, int duration);
270 /** Sets an event to recur yearly ending at \a endDate. */ 270 /** Sets an event to recur yearly ending at \a endDate. */
271 void setYearlyByDate(Feb29Type type, int freq, const QDate &endDate); 271 void setYearlyByDate(Feb29Type type, int freq, const QDate &endDate);
272 /** Adds position of day or month in year. 272 /** Adds position of day or month in year.
273 * N.B. for recursYearlyPos, addYearlyMonthPos() must also be called 273 * N.B. for recursYearlyPos, addYearlyMonthPos() must also be called
274 * to add positions within the month. */ 274 * to add positions within the month. */
275 void addYearlyNum(short _rNum); 275 void addYearlyNum(short _rNum);
276 /** Adds a position to the recursYearlyPos recurrence rule, if it is set. 276 /** Adds a position to the recursYearlyPos recurrence rule, if it is set.
277 * N.B. addYearlyNum() must also be called to add recurrence months. 277 * N.B. addYearlyNum() must also be called to add recurrence months.
278 * Parameters are the same as for addMonthlyPos(). 278 * Parameters are the same as for addMonthlyPos().
279 */ 279 */
280 void addYearlyMonthPos(short _rPos, const QBitArray &_rDays); 280 void addYearlyMonthPos(short _rPos, const QBitArray &_rDays);
281 /** Returns positions of days or months in year. */ 281 /** Returns positions of days or months in year. */
282 const QPtrList<int> &yearNums() const; 282 const QPtrList<int> &yearNums() const;
283 /** Returns list of day positions in months, for a recursYearlyPos recurrence rule. */ 283 /** Returns list of day positions in months, for a recursYearlyPos recurrence rule. */
284 const QPtrList<rMonthPos> &yearMonthPositions() const; 284 const QPtrList<rMonthPos> &yearMonthPositions() const;
285 /** Returns how yearly recurrences of February 29th are handled. */ 285 /** Returns how yearly recurrences of February 29th are handled. */
286 Feb29Type feb29YearlyType() const { return mFeb29YearlyType; } 286 Feb29Type feb29YearlyType() const { return mFeb29YearlyType; }
287 /** Sets the default method for handling yearly recurrences of February 29th. */ 287 /** Sets the default method for handling yearly recurrences of February 29th. */
288 static void setFeb29YearlyTypeDefault(Feb29Type t) { mFeb29YearlyDefaultType = t; } 288 static void setFeb29YearlyTypeDefault(Feb29Type t) { mFeb29YearlyDefaultType = t; }
289 /** Returns the default method for handling yearly recurrences of February 29th. */ 289 /** Returns the default method for handling yearly recurrences of February 29th. */
290 static Feb29Type setFeb29YearlyTypeDefault() { return mFeb29YearlyDefaultType; } 290 static Feb29Type setFeb29YearlyTypeDefault() { return mFeb29YearlyDefaultType; }
291 291 void addYearlyMonth(short _rPos ); // added LR
292 /** 292 /**
293 Debug output. 293 Debug output.
294 */ 294 */
295 void dump() const; 295 void dump() const;
296 QString recurrenceText() const; 296 QString recurrenceText() const;
297 bool getYearlyMonthMonths(int day, QValueList<int>&,
298 QValueList<int> &leaplist) const;
297 299
298 protected: 300 protected:
299 enum PeriodFunc { END_DATE_AND_COUNT, COUNT_TO_DATE, NEXT_AFTER_DATE }; 301 enum PeriodFunc { END_DATE_AND_COUNT, COUNT_TO_DATE, NEXT_AFTER_DATE };
300 struct MonthlyData; friend struct MonthlyData; 302 struct MonthlyData; friend struct MonthlyData;
301 struct YearlyMonthData; friend struct YearlyMonthData; 303 struct YearlyMonthData; friend struct YearlyMonthData;
302 struct YearlyPosData; friend struct YearlyPosData; 304 struct YearlyPosData; friend struct YearlyPosData;
303 struct YearlyDayData; friend struct YearlyDayData; 305 struct YearlyDayData; friend struct YearlyDayData;
304 306
305 bool recursSecondly(const QDate &, int secondFreq) const; 307 bool recursSecondly(const QDate &, int secondFreq) const;
306 bool recursMinutelyAt(const QDateTime &dt, int minuteFreq) const; 308 bool recursMinutelyAt(const QDateTime &dt, int minuteFreq) const;
307 bool recursDaily(const QDate &) const; 309 bool recursDaily(const QDate &) const;
308 bool recursWeekly(const QDate &) const; 310 bool recursWeekly(const QDate &) const;
309 bool recursMonthly(const QDate &) const; 311 bool recursMonthly(const QDate &) const;
310 bool recursYearlyByMonth(const QDate &) const; 312 bool recursYearlyByMonth(const QDate &) const;
311 bool recursYearlyByPos(const QDate &) const; 313 bool recursYearlyByPos(const QDate &) const;
312 bool recursYearlyByDay(const QDate &) const; 314 bool recursYearlyByDay(const QDate &) const;
313 315
314 QDate getNextDateNoTime(const QDate& preDate, bool* last) const; 316 QDate getNextDateNoTime(const QDate& preDate, bool* last) const;
315 QDate getPreviousDateNoTime(const QDate& afterDate, bool* last) const; 317 QDate getPreviousDateNoTime(const QDate& afterDate, bool* last) const;
316 318
317 void addMonthlyPos_(short _rPos, const QBitArray &_rDays); 319 void addMonthlyPos_(short _rPos, const QBitArray &_rDays);
318 void setDailySub(short type, int freq, int duration); 320 void setDailySub(short type, int freq, int duration);
319 void setYearly_(short type, Feb29Type, int freq, int duration); 321 void setYearly_(short type, Feb29Type, int freq, int duration);
320 int recurCalc(PeriodFunc, QDate &enddate) const; 322 int recurCalc(PeriodFunc, QDate &enddate) const;
321 int recurCalc(PeriodFunc, QDateTime &endtime) const; 323 int recurCalc(PeriodFunc, QDateTime &endtime) const;
322 int secondlyCalc(PeriodFunc, QDateTime& endtime, int freq) const; 324 int secondlyCalc(PeriodFunc, QDateTime& endtime, int freq) const;
323 int dailyCalc(PeriodFunc, QDate &enddate) const; 325 int dailyCalc(PeriodFunc, QDate &enddate) const;
324 int weeklyCalc(PeriodFunc, QDate &enddate) const; 326 int weeklyCalc(PeriodFunc, QDate &enddate) const;
325 int weeklyCalcEndDate(QDate& enddate, int daysPerWeek) const; 327 int weeklyCalcEndDate(QDate& enddate, int daysPerWeek) const;
326 int weeklyCalcToDate(const QDate& enddate, int daysPerWeek) const; 328 int weeklyCalcToDate(const QDate& enddate, int daysPerWeek) const;
327 int weeklyCalcNextAfter(QDate& enddate, int daysPerWeek) const; 329 int weeklyCalcNextAfter(QDate& enddate, int daysPerWeek) const;
328 int monthlyCalc(PeriodFunc, QDate &enddate) const; 330 int monthlyCalc(PeriodFunc, QDate &enddate) const;
329 int monthlyCalcEndDate(QDate& enddate, MonthlyData&) const; 331 int monthlyCalcEndDate(QDate& enddate, MonthlyData&) const;
330 int monthlyCalcToDate(const QDate& enddate, MonthlyData&) const; 332 int monthlyCalcToDate(const QDate& enddate, MonthlyData&) const;
331 int monthlyCalcNextAfter(QDate& enddate, MonthlyData&) const; 333 int monthlyCalcNextAfter(QDate& enddate, MonthlyData&) const;
332 int yearlyMonthCalc(PeriodFunc, QDate &enddate) const; 334 int yearlyMonthCalc(PeriodFunc, QDate &enddate) const;
333 int yearlyMonthCalcEndDate(QDate& enddate, YearlyMonthData&) const; 335 int yearlyMonthCalcEndDate(QDate& enddate, YearlyMonthData&) const;
334 int yearlyMonthCalcToDate(const QDate& enddate, YearlyMonthData&) const; 336 int yearlyMonthCalcToDate(const QDate& enddate, YearlyMonthData&) const;
335 int yearlyMonthCalcNextAfter(QDate& enddate, YearlyMonthData&) const; 337 int yearlyMonthCalcNextAfter(QDate& enddate, YearlyMonthData&) const;
336 int yearlyPosCalc(PeriodFunc, QDate &enddate) const; 338 int yearlyPosCalc(PeriodFunc, QDate &enddate) const;
337 int yearlyPosCalcEndDate(QDate& enddate, YearlyPosData&) const; 339 int yearlyPosCalcEndDate(QDate& enddate, YearlyPosData&) const;
338 int yearlyPosCalcToDate(const QDate& enddate, YearlyPosData&) const; 340 int yearlyPosCalcToDate(const QDate& enddate, YearlyPosData&) const;
339 int yearlyPosCalcNextAfter(QDate& enddate, YearlyPosData&) const; 341 int yearlyPosCalcNextAfter(QDate& enddate, YearlyPosData&) const;
340 int yearlyDayCalc(PeriodFunc, QDate &enddate) const; 342 int yearlyDayCalc(PeriodFunc, QDate &enddate) const;
341 int yearlyDayCalcEndDate(QDate& enddate, YearlyDayData&) const; 343 int yearlyDayCalcEndDate(QDate& enddate, YearlyDayData&) const;
342 int yearlyDayCalcToDate(const QDate& enddate, YearlyDayData&) const; 344 int yearlyDayCalcToDate(const QDate& enddate, YearlyDayData&) const;
343 int yearlyDayCalcNextAfter(QDate& enddate, YearlyDayData&) const; 345 int yearlyDayCalcNextAfter(QDate& enddate, YearlyDayData&) const;
344 346
345 int countMonthlyPosDays() const; 347 int countMonthlyPosDays() const;
346 void getMonthlyPosDays(QValueList<int>&, int daysInMonth, 348 void getMonthlyPosDays(QValueList<int>&, int daysInMonth,
347 int startDayOfWeek) const; 349 int startDayOfWeek) const;
348 bool getMonthlyDayDays(QValueList<int>&, int daysInMonth) const; 350 bool getMonthlyDayDays(QValueList<int>&, int daysInMonth) const;
349 bool getYearlyMonthMonths(int day, QValueList<int>&,
350 QValueList<int> &leaplist) const;
351 351
352 int getFirstDayInWeek(int startDay, bool useWeekStart = true) const; 352 int getFirstDayInWeek(int startDay, bool useWeekStart = true) const;
353 int getLastDayInWeek(int endDay, bool useWeekStart = true) const; 353 int getLastDayInWeek(int endDay, bool useWeekStart = true) const;
354 QDate getFirstDateInMonth(const QDate& earliestDate) const; 354 QDate getFirstDateInMonth(const QDate& earliestDate) const;
355 QDate getLastDateInMonth(const QDate& latestDate) const; 355 QDate getLastDateInMonth(const QDate& latestDate) const;
356 QDate getFirstDateInYear(const QDate& earliestDate) const; 356 QDate getFirstDateInYear(const QDate& earliestDate) const;
357 QDate getLastDateInYear(const QDate& latestDate) const; 357 QDate getLastDateInYear(const QDate& latestDate) const;
358 358
359 private: 359 private:
360 // Prohibit copying 360 // Prohibit copying
361 Recurrence(const Recurrence&); 361 Recurrence(const Recurrence&);
362 Recurrence &operator=(const Recurrence&); 362 Recurrence &operator=(const Recurrence&);
363 363
364 short recurs; // should be one of the enums. 364 short recurs; // should be one of the enums.
365 365
366 int rWeekStart; // day which starts the week, Monday=1 .. Sunday=7 366 int rWeekStart; // day which starts the week, Monday=1 .. Sunday=7
367 QBitArray rDays; // array of days during week it recurs 367 QBitArray rDays; // array of days during week it recurs
368 368
369 QPtrList<rMonthPos> rMonthPositions; // list of positions during a month 369 QPtrList<rMonthPos> rMonthPositions; // list of positions during a month
370 // on which an event recurs 370 // on which an event recurs
371 371
372 QPtrList<int> rMonthDays; // list of days during a month on 372 QPtrList<int> rMonthDays; // list of days during a month on
373 // which the event recurs 373 // which the event recurs
374 374
375 QPtrList<int> rYearNums; // either months/days to recur on for rYearly, 375 QPtrList<int> rYearNums; // either months/days to recur on for rYearly,
376 // sorted in numerical order 376 // sorted in numerical order
377 377
378 int rFreq; // frequency of period 378 int rFreq; // frequency of period
379 379
380 // one of the following must be specified 380 // one of the following must be specified
381 int rDuration; // num times to recur (inc. first occurrence), -1 = infinite 381 int rDuration; // num times to recur (inc. first occurrence), -1 = infinite
382 QDateTime rEndDateTime; // date/time at which to end recurrence 382 QDateTime rEndDateTime; // date/time at which to end recurrence
383 383
384 QDateTime mRecurStart; // date/time of first recurrence 384 QDateTime mRecurStart; // date/time of first recurrence
385 bool mFloats; // the recurrence has no time, just a date 385 bool mFloats; // the recurrence has no time, just a date
386 bool mRecurReadOnly; 386 bool mRecurReadOnly;
387 int mRecurExDatesCount; // number of recurrences (in addition to rDuration) which are excluded 387 int mRecurExDatesCount; // number of recurrences (in addition to rDuration) which are excluded
388 Feb29Type mFeb29YearlyType; // how to handle yearly recurrences of February 29th 388 Feb29Type mFeb29YearlyType; // how to handle yearly recurrences of February 29th
389 static Feb29Type mFeb29YearlyDefaultType; // default value for mFeb29YearlyType 389 static Feb29Type mFeb29YearlyDefaultType; // default value for mFeb29YearlyType
390 390
391 // Backwards compatibility for KDE < 3.1. 391 // Backwards compatibility for KDE < 3.1.
392 int mCompatVersion; // calendar file version for backwards compatibility 392 int mCompatVersion; // calendar file version for backwards compatibility
393 short mCompatRecurs; // original 'recurs' in old calendar format, or rNone 393 short mCompatRecurs; // original 'recurs' in old calendar format, or rNone
394 int mCompatDuration; // original 'rDuration' in old calendar format, or 0 394 int mCompatDuration; // original 'rDuration' in old calendar format, or 0
395 395
396 Incidence *mParent; 396 Incidence *mParent;
397}; 397};
398 398
399} 399}
400 400
401#endif 401#endif