korganizer

koeditorrecurrence.cpp
1/*
2 This file is part of KOrganizer.
3 Copyright (c) 2000-2003 Cornelius Schumacher <schumacher@kde.org>
4 Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
20 As a special exception, permission is given to link this program
21 with any edition of TQt, and distribute the resulting executable,
22 without including the source code for TQt in the source distribution.
23*/
24
25#include <tqtooltip.h>
26#include <tqfiledialog.h>
27#include <tqlayout.h>
28#include <tqvbox.h>
29#include <tqbuttongroup.h>
30#include <tqvgroupbox.h>
31#include <tqwidgetstack.h>
32#include <tqdatetime.h>
33#include <tqlistbox.h>
34#include <tqspinbox.h>
35#include <tqcheckbox.h>
36#include <tqgroupbox.h>
37#include <tqwidgetstack.h>
38#include <tqradiobutton.h>
39#include <tqlabel.h>
40#include <tqpushbutton.h>
41#include <tqwhatsthis.h>
42
43#include <kdialog.h>
44#include <tdeglobal.h>
45#include <tdelocale.h>
46#include <kiconloader.h>
47#include <kdebug.h>
48#include <knumvalidator.h>
49#include <kcalendarsystem.h>
50#include <tdemessagebox.h>
51
52#include <libtdepim/kdateedit.h>
53#include <libkcal/todo.h>
54
55#include "koprefs.h"
56#include "koglobals.h"
57
58#include "koeditorrecurrence.h"
59#include "koeditorrecurrence.moc"
60
62
63RecurBase::RecurBase( TQWidget *parent, const char *name ) :
64 TQWidget( parent, name )
65{
66 mFrequencyEdit = new TQSpinBox( 1, 9999, 1, this );
67 mFrequencyEdit->setValue( 1 );
68}
69
70TQWidget *RecurBase::frequencyEdit()
71{
72 return mFrequencyEdit;
73}
74
75void RecurBase::setFrequency( int f )
76{
77 if ( f < 1 ) f = 1;
78
79 mFrequencyEdit->setValue( f );
80}
81
82int RecurBase::frequency()
83{
84 return mFrequencyEdit->value();
85}
86
87TQComboBox *RecurBase::createWeekCountCombo( TQWidget *parent, const char *name )
88{
89 TQComboBox *combo = new TQComboBox( parent, name );
90 TQWhatsThis::add( combo,
91 i18n("The number of the week from the beginning "
92 "of the month on which this event or to-do "
93 "should recur.") );
94 if ( !combo ) return 0;
95 combo->insertItem( i18n("1st") );
96 combo->insertItem( i18n("2nd") );
97 combo->insertItem( i18n("3rd") );
98 combo->insertItem( i18n("4th") );
99 combo->insertItem( i18n("5th") );
100 combo->insertItem( i18n("Last") );
101 combo->insertItem( i18n("2nd Last") );
102 combo->insertItem( i18n("3rd Last") );
103 combo->insertItem( i18n("4th Last") );
104 combo->insertItem( i18n("5th Last") );
105 return combo;
106}
107
108TQComboBox *RecurBase::createWeekdayCombo( TQWidget *parent, const char *name )
109{
110 TQComboBox *combo = new TQComboBox( parent, name );
111 TQWhatsThis::add( combo,
112 i18n("The weekday on which this event or to-do "
113 "should recur.") );
114 if ( !combo ) return 0;
115 const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
116 for( int i = 1; i <= 7; ++i ) {
117 combo->insertItem( calSys->weekDayName( i ) );
118 }
119 return combo;
120}
121
122TQComboBox *RecurBase::createMonthNameCombo( TQWidget *parent, const char *name )
123{
124 TQComboBox *combo = new TQComboBox( parent, name );
125 TQWhatsThis::add( combo,
126 i18n("The month during which this event or to-do "
127 "should recur.") );
128 if ( !combo ) return 0;
129 const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
130 for( int i = 1; i <= 12; ++i ) {
131 // use an arbitrary year, we just need the month name...
132 TQDate dt( 2005, i, 1 );
133 combo->insertItem( calSys->monthName( dt ) );
134 }
135 return combo;
136}
137
138TQBoxLayout *RecurBase::createFrequencySpinBar( TQWidget *parent, TQLayout *layout,
139 TQString everyText, TQString unitText )
140{
141 TQBoxLayout *freqLayout = new TQHBoxLayout( layout );
142
143 TQString whatsThis = i18n("Sets how often this event or to-do should recur.");
144 TQLabel *preLabel = new TQLabel( everyText, parent );
145 TQWhatsThis::add( preLabel, whatsThis );
146 freqLayout->addWidget( preLabel );
147
148 freqLayout->addWidget( frequencyEdit() );
149 preLabel->setBuddy( frequencyEdit() );
150 TQWhatsThis::add( preLabel->buddy(), whatsThis );
151
152 TQLabel *postLabel = new TQLabel( unitText, parent );
153 TQWhatsThis::add( postLabel, whatsThis );
154 freqLayout->addWidget( postLabel );
155 freqLayout->addStretch();
156 return freqLayout;
157}
158
160
161RecurDaily::RecurDaily( TQWidget *parent, const char *name ) :
162 RecurBase( parent, name )
163{
164 TQBoxLayout *topLayout = new TQVBoxLayout( this );
165 topLayout->setSpacing( KDialog::spacingHint() );
166
167 createFrequencySpinBar( this, topLayout, i18n("&Recur every"), i18n("day(s)") );
168}
169
170
172
173RecurWeekly::RecurWeekly( TQWidget *parent, const char *name ) :
174 RecurBase( parent, name )
175{
176 TQBoxLayout *topLayout = new TQVBoxLayout( this );
177 topLayout->setSpacing( KDialog::spacingHint() );
178
179// topLayout->addStretch( 1 );
180
181 createFrequencySpinBar( this, topLayout, i18n("&Recur every"), i18n("week(s) on:") );
182
183 TQHBox *dayBox = new TQHBox( this );
184 topLayout->addWidget( dayBox, 1, AlignVCenter );
185 // Respect start of week setting
186 int weekStart=TDEGlobal::locale()->weekStartDay();
187 for ( int i = 0; i < 7; ++i ) {
188 // i is the nr of the combobox, not the day of week!
189 // label=(i+weekStart+6)%7 + 1;
190 // index in CheckBox array(=day): label-1
191 const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
192 TQString weekDayName = calSys->weekDayName(
193 (i + weekStart + 6)%7 + 1, true );
194 if ( KOPrefs::instance()->mCompactDialogs ) {
195 weekDayName = weekDayName.left( 1 );
196 }
197 mDayBoxes[ (i + weekStart + 6)%7 ] = new TQCheckBox( weekDayName, dayBox );
198 TQWhatsThis::add( mDayBoxes[ (i + weekStart + 6)%7 ],
199 i18n("Day of the week on which this event or to-do "
200 "should recur.") );
201 }
202
203 topLayout->addStretch( 1 );
204}
205
206void RecurWeekly::setDays( const TQBitArray &days )
207{
208 for ( int i = 0; i < 7; ++i ) {
209 mDayBoxes[ i ]->setChecked( days.testBit( i ) );
210 }
211}
212
213TQBitArray RecurWeekly::days()
214{
215 TQBitArray days( 7 );
216
217 for ( int i = 0; i < 7; ++i ) {
218 days.setBit( i, mDayBoxes[ i ]->isChecked() );
219 }
220
221 return days;
222}
223
225
226RecurMonthly::RecurMonthly( TQWidget *parent, const char *name ) :
227 RecurBase( parent, name )
228{
229 TQBoxLayout *topLayout = new TQVBoxLayout( this );
230 topLayout->setSpacing( KDialog::spacingHint() );
231
232 createFrequencySpinBar( this, topLayout, i18n("&Recur every"), i18n("month(s)") );
233
234 TQButtonGroup *buttonGroup = new TQButtonGroup( this );
235 buttonGroup->setFrameStyle( TQFrame::NoFrame );
236 topLayout->addWidget( buttonGroup, 1, AlignVCenter );
237
238 TQGridLayout *buttonLayout = new TQGridLayout( buttonGroup, 3, 2 );
239 buttonLayout->setSpacing( KDialog::spacingHint() );
240
241
242 TQString recurOnText;
243 if ( !KOPrefs::instance()->mCompactDialogs ) {
244 recurOnText = i18n("&Recur on the");
245 }
246
247 mByDayRadio = new TQRadioButton( recurOnText, buttonGroup );
248 TQWhatsThis::add( mByDayRadio,
249 i18n("Sets a specific day of the month on which "
250 "this event or to-do should recur.") );
251
252 buttonLayout->addWidget( mByDayRadio, 0, 0 );
253
254 TQString whatsThis = i18n("The day of the month on which this event or to-do "
255 "should recur.");
256 mByDayCombo = new TQComboBox( buttonGroup );
257 TQWhatsThis::add( mByDayCombo, whatsThis );
258 mByDayCombo->setSizeLimit( 7 );
259 mByDayCombo->insertItem( i18n("1st") );
260 mByDayCombo->insertItem( i18n("2nd") );
261 mByDayCombo->insertItem( i18n("3rd") );
262 mByDayCombo->insertItem( i18n("4th") );
263 mByDayCombo->insertItem( i18n("5th") );
264 mByDayCombo->insertItem( i18n("6th") );
265 mByDayCombo->insertItem( i18n("7th") );
266 mByDayCombo->insertItem( i18n("8th") );
267 mByDayCombo->insertItem( i18n("9th") );
268 mByDayCombo->insertItem( i18n("10th") );
269 mByDayCombo->insertItem( i18n("11th") );
270 mByDayCombo->insertItem( i18n("12th") );
271 mByDayCombo->insertItem( i18n("13th") );
272 mByDayCombo->insertItem( i18n("14th") );
273 mByDayCombo->insertItem( i18n("15th") );
274 mByDayCombo->insertItem( i18n("16th") );
275 mByDayCombo->insertItem( i18n("17th") );
276 mByDayCombo->insertItem( i18n("18th") );
277 mByDayCombo->insertItem( i18n("19th") );
278 mByDayCombo->insertItem( i18n("20th") );
279 mByDayCombo->insertItem( i18n("21st") );
280 mByDayCombo->insertItem( i18n("22nd") );
281 mByDayCombo->insertItem( i18n("23rd") );
282 mByDayCombo->insertItem( i18n("24th") );
283 mByDayCombo->insertItem( i18n("25th") );
284 mByDayCombo->insertItem( i18n("26th") );
285 mByDayCombo->insertItem( i18n("27th") );
286 mByDayCombo->insertItem( i18n("28th") );
287 mByDayCombo->insertItem( i18n("29th") );
288 mByDayCombo->insertItem( i18n("30th") );
289 mByDayCombo->insertItem( i18n("31st") );
290 mByDayCombo->insertItem( i18n("Last") );
291 mByDayCombo->insertItem( i18n("2nd Last") );
292 mByDayCombo->insertItem( i18n("3rd Last") );
293 mByDayCombo->insertItem( i18n("4th Last") );
294 mByDayCombo->insertItem( i18n("5th Last") );
295 // FIXME: After the string freeze is over, insert all possible values, not
296 // just the ones we already have translated:
297/* mByDayCombo->insertItem( i18n("6th Last") );
298 mByDayCombo->insertItem( i18n("7th Last") );
299 mByDayCombo->insertItem( i18n("8th Last") );
300 mByDayCombo->insertItem( i18n("9th Last") );
301 mByDayCombo->insertItem( i18n("10th Last") );
302 mByDayCombo->insertItem( i18n("11th Last") );
303 mByDayCombo->insertItem( i18n("12th Last") );
304 mByDayCombo->insertItem( i18n("13th Last") );
305 mByDayCombo->insertItem( i18n("14th Last") );
306 mByDayCombo->insertItem( i18n("15th Last") );
307 mByDayCombo->insertItem( i18n("16th Last") );
308 mByDayCombo->insertItem( i18n("17th Last") );
309 mByDayCombo->insertItem( i18n("18th Last") );
310 mByDayCombo->insertItem( i18n("19th Last") );
311 mByDayCombo->insertItem( i18n("20th Last") );
312 mByDayCombo->insertItem( i18n("21st Last") );
313 mByDayCombo->insertItem( i18n("22nd Last") );
314 mByDayCombo->insertItem( i18n("23rd Last") );
315 mByDayCombo->insertItem( i18n("24th Last") );
316 mByDayCombo->insertItem( i18n("25th Last") );
317 mByDayCombo->insertItem( i18n("26th Last") );
318 mByDayCombo->insertItem( i18n("27th Last") );
319 mByDayCombo->insertItem( i18n("28th Last") );
320 mByDayCombo->insertItem( i18n("29th Last") );
321 mByDayCombo->insertItem( i18n("30th Last") );
322 mByDayCombo->insertItem( i18n("31st Last") );*/
323 buttonLayout->addWidget( mByDayCombo, 0, 1 );
324
325 TQLabel *byDayLabel = new TQLabel( i18n("day"), buttonGroup );
326 TQWhatsThis::add( byDayLabel, whatsThis );
327 buttonLayout->addWidget( byDayLabel, 0, 2 );
328
329
330 mByPosRadio = new TQRadioButton( recurOnText, buttonGroup);
331 TQWhatsThis::add( mByPosRadio,
332 i18n("Sets a weekday and specific week in the month "
333 "on which this event or to-do should recur") );
334 buttonLayout->addWidget( mByPosRadio, 1, 0 );
335
336 mByPosCountCombo = createWeekCountCombo( buttonGroup );
337 buttonLayout->addWidget( mByPosCountCombo, 1, 1 );
338
339 mByPosWeekdayCombo = createWeekdayCombo( buttonGroup );
340 buttonLayout->addWidget( mByPosWeekdayCombo, 1, 2 );
341}
342
343void RecurMonthly::setByDay( int day )
344{
345 mByDayRadio->setChecked( true );
346 // Days from the end are after the ones from the begin, so correct for the
347 // negative sign and add 30 (index starting at 0)
348 if ( day > 0 && day <= 31 )
349 mByDayCombo->setCurrentItem( day-1 );
350 else if ( day < 0 )
351 mByDayCombo->setCurrentItem( 31 - 1 - day );
352}
353
354void RecurMonthly::setByPos( int count, int weekday )
355{
356 mByPosRadio->setChecked( true );
357 if (count>0)
358 mByPosCountCombo->setCurrentItem( count - 1 );
359 else
360 // negative weeks means counted from the end of month
361 mByPosCountCombo->setCurrentItem( -count + 4 );
362 mByPosWeekdayCombo->setCurrentItem( weekday - 1 );
363}
364
365bool RecurMonthly::byDay()
366{
367 return mByDayRadio->isChecked();
368}
369
370bool RecurMonthly::byPos()
371{
372 return mByPosRadio->isChecked();
373}
374
375int RecurMonthly::day()
376{
377 int day = mByDayCombo->currentItem();
378 if ( day >= 31 ) day = 31-day-1;
379 else ++day;
380 return day;
381}
382
383int RecurMonthly::count()
384{
385 int pos=mByPosCountCombo->currentItem();
386 if (pos<=4) // positive count
387 return pos+1;
388 else
389 return -pos+4;
390}
391
392int RecurMonthly::weekday()
393{
394 return mByPosWeekdayCombo->currentItem() + 1;
395}
396
398
399RecurYearly::RecurYearly( TQWidget *parent, const char *name ) :
400 RecurBase( parent, name )
401{
402 TQBoxLayout *topLayout = new TQVBoxLayout( this );
403 topLayout->setSpacing( KDialog::spacingHint() );
404
405 createFrequencySpinBar( this, topLayout, i18n("&Recur every"), i18n("year(s)") );
406
407
408 TQButtonGroup *buttonGroup = new TQButtonGroup( this );
409 buttonGroup->setFrameStyle( TQFrame::NoFrame );
410 topLayout->addWidget( buttonGroup, 1, AlignVCenter );
411
412 TQBoxLayout *buttonLayout = new TQVBoxLayout( buttonGroup );
413
414
415 /* YearlyMonth (day n of Month Y) */
416 TQBoxLayout *monthLayout = new TQHBoxLayout( buttonLayout );
417 TQString recurInMonthText(
418 i18n("part before XXX of 'Recur on day XXX of month YYY'",
419 "&Recur on day "));
420 if ( KOPrefs::instance()->mCompactDialogs ) {
421 recurInMonthText = i18n("&Day ");
422 }
423 mByMonthRadio = new TQRadioButton( recurInMonthText, buttonGroup );
424 TQWhatsThis::add( mByMonthRadio,
425 i18n("Sets a specific day in a specific month on which "
426 "this event or to-do should recur.") );
427 monthLayout->addWidget( mByMonthRadio );
428 mByMonthSpin = new TQSpinBox( 1, 31, 1, buttonGroup );
429 TQWhatsThis::add( mByMonthSpin,
430 i18n("The day of the month on which this event or to-do "
431 "should recur.") );
432 monthLayout->addWidget( mByMonthSpin );
433 TQLabel *ofLabel = new TQLabel(
434 i18n("part between XXX and YYY of 'Recur on day XXX of month YYY'", " &of "),
435 buttonGroup );
436 //What do I do here? I'm not sure if this label should have What's This in it... - Antonio
437 monthLayout->addWidget( ofLabel );
438
439 mByMonthCombo = createMonthNameCombo( buttonGroup );
440 monthLayout->addWidget( mByMonthCombo );
441 ofLabel->setBuddy( mByMonthCombo );
442
443 monthLayout->addStretch( 1 );
444
445
446 /* YearlyPos (weekday X of week N of month Y) */
447 TQBoxLayout *posLayout = new TQHBoxLayout( buttonLayout );
448 TQString recurOnPosText( i18n("Part before XXX in 'Recur on NNN. WEEKDAY of MONTH', short version", "&On" ) );
449 if ( !KOPrefs::instance()->mCompactDialogs ) {
450 recurOnPosText = i18n("Part before XXX in 'Recur on NNN. WEEKDAY of MONTH'", "&On the" );
451 }
452 mByPosRadio = new TQRadioButton( recurOnPosText, buttonGroup );
453 TQWhatsThis::add( mByPosRadio,
454 i18n("Sets a specific day in a specific week of a specific "
455 "month on which this event or to-do should recur.") );
456 posLayout->addWidget( mByPosRadio );
457
458 mByPosDayCombo = createWeekCountCombo( buttonGroup );
459 posLayout->addWidget( mByPosDayCombo );
460
461 mByPosWeekdayCombo = createWeekdayCombo( buttonGroup );
462 posLayout->addWidget( mByPosWeekdayCombo );
463
464 ofLabel = new TQLabel(
465 i18n("part between WEEKDAY and MONTH in 'Recur on NNN. WEEKDAY of MONTH'", " o&f "),
466 buttonGroup );
467 posLayout->addWidget( ofLabel );
468
469 mByPosMonthCombo = createMonthNameCombo( buttonGroup );
470 posLayout->addWidget( mByPosMonthCombo );
471 ofLabel->setBuddy( mByPosMonthCombo );
472
473 posLayout->addStretch( 1 );
474
475
476 /* YearlyDay (day N of the year) */
477 TQBoxLayout *dayLayout = new TQHBoxLayout( buttonLayout );
478 TQString recurOnDayText;
479 if ( KOPrefs::instance()->mCompactDialogs ) {
480 recurOnDayText = i18n("Day #");
481 } else {
482 recurOnDayText = i18n("Recur on &day #");
483 }
484 TQString whatsThis = i18n("Sets a specific day within the year on which this "
485 "event or to-do should recur.");
486 mByDayRadio = new TQRadioButton( recurOnDayText, buttonGroup );
487 TQWhatsThis::add( mByDayRadio, whatsThis );
488 dayLayout->addWidget( mByDayRadio );
489
490 mByDaySpin = new TQSpinBox( 1, 366, 1, buttonGroup );
491 TQWhatsThis::add( mByDaySpin, whatsThis );
492
493 dayLayout->addWidget( mByDaySpin );
494
495 TQString ofTheYear( i18n("part after NNN of 'Recur on day #NNN of the year'", " of the &year"));
496 if ( KOPrefs::instance()->mCompactDialogs ) {
497 ofTheYear = i18n("part after NNN of 'Recur on day #NNN of the year', short version",
498 " of the year");
499 }
500 ofLabel = new TQLabel( ofTheYear, buttonGroup );
501 TQWhatsThis::add( ofLabel, whatsThis );
502 dayLayout->addWidget( ofLabel );
503 ofLabel->setBuddy( mByDaySpin );
504
505 dayLayout->addStretch( 1 );
506}
507
508void RecurYearly::setByDay( int day )
509{
510 mByDayRadio->setChecked( true );
511 mByDaySpin->setValue( day );
512}
513
514void RecurYearly::setByPos( int count, int weekday, int month )
515{
516 mByPosRadio->setChecked( true );
517 if ( count > 0 )
518 mByPosDayCombo->setCurrentItem( count - 1 );
519 else
520 mByPosDayCombo->setCurrentItem( -count + 4 );
521 mByPosWeekdayCombo->setCurrentItem( weekday - 1 );
522 mByPosMonthCombo->setCurrentItem( month-1 );
523}
524
525void RecurYearly::setByMonth( int day, int month )
526{
527 mByMonthRadio->setChecked( true );
528 mByMonthSpin->setValue( day );
529 mByMonthCombo->setCurrentItem( month - 1 );
530}
531
532RecurYearly::YearlyType RecurYearly::getType()
533{
534 if ( mByMonthRadio->isChecked() ) return byMonth;
535 if ( mByPosRadio->isChecked() ) return byPos;
536 if ( mByDayRadio->isChecked() ) return byDay;
537 return byMonth;
538}
539
540int RecurYearly::monthDay()
541{
542 return mByMonthSpin->value();
543}
544
545int RecurYearly::month()
546{
547 return mByMonthCombo->currentItem() + 1;
548}
549
550int RecurYearly::posCount()
551{
552 int pos = mByPosDayCombo->currentItem();
553 if ( pos <= 4 ) // positive count
554 return pos + 1;
555 else
556 return -pos + 4;
557}
558
559int RecurYearly::posWeekday()
560{
561 return mByPosWeekdayCombo->currentItem() + 1;
562}
563
564int RecurYearly::posMonth()
565{
566 return mByPosMonthCombo->currentItem() + 1;
567}
568
569int RecurYearly::day()
570{
571 return mByDaySpin->value();
572}
573
575
576ExceptionsWidget::ExceptionsWidget( TQWidget *parent, const char *name ) :
577 TQWidget( parent, name )
578{
579 TQBoxLayout *topLayout = new TQVBoxLayout( this );
580
581 TQGroupBox *groupBox = new TQGroupBox( 1, TQt::Horizontal, i18n("E&xceptions"),
582 this );
583 topLayout->addWidget( groupBox );
584
585 TQWidget *box = new TQWidget( groupBox );
586
587 TQGridLayout *boxLayout = new TQGridLayout( box );
588
589 mExceptionDateEdit = new KDateEdit( box );
590 TQWhatsThis::add( mExceptionDateEdit,
591 i18n("A date that should be considered an exception "
592 "to the recurrence rules for this event or to-do.") );
593 mExceptionDateEdit->setDate( TQDate::currentDate() );
594 boxLayout->addWidget( mExceptionDateEdit, 0, 0 );
595
596 TQPushButton *addExceptionButton = new TQPushButton(
597 i18n( "Add a new recurrence to the recurrence list", "&Add" ), box );
598 TQWhatsThis::add( addExceptionButton,
599 i18n("Add this date as an exception "
600 "to the recurrence rules for this event or to-do.") );
601 boxLayout->addWidget( addExceptionButton, 1, 0 );
602 TQPushButton *changeExceptionButton = new TQPushButton( i18n("&Change"), box );
603 TQWhatsThis::add( changeExceptionButton,
604 i18n("Replace the currently selected date with this date.") );
605 boxLayout->addWidget( changeExceptionButton, 2, 0 );
606 TQPushButton *deleteExceptionButton = new TQPushButton( i18n("&Delete"), box );
607 TQWhatsThis::add( deleteExceptionButton,
608 i18n("Delete the currently selected date from the list of dates "
609 "that should be considered exceptions to the recurrence rules "
610 "for this event or to-do.") );
611 boxLayout->addWidget( deleteExceptionButton, 3, 0 );
612
613 mExceptionList = new TQListBox( box );
614 TQWhatsThis::add( mExceptionList,
615 i18n("Displays current dates that are being considered "
616 "exceptions to the recurrence rules for this event "
617 "or to-do.") );
618 boxLayout->addMultiCellWidget( mExceptionList, 0, 3, 1, 1 );
619
620 boxLayout->setRowStretch( 4, 1 );
621 boxLayout->setColStretch( 1, 3 );
622
623 connect( addExceptionButton, TQ_SIGNAL( clicked() ),
624 TQ_SLOT( addException() ) );
625 connect( changeExceptionButton, TQ_SIGNAL( clicked() ),
626 TQ_SLOT( changeException() ) );
627 connect( deleteExceptionButton, TQ_SIGNAL( clicked() ),
628 TQ_SLOT( deleteException() ) );
629}
630
631void ExceptionsWidget::addException()
632{
633 TQDate date = mExceptionDateEdit->date();
634 TQString dateStr = TDEGlobal::locale()->formatDate( date );
635 if( !mExceptionList->findItem( dateStr ) ) {
636 mExceptionDates.append( date );
637 mExceptionList->insertItem( dateStr );
638 }
639}
640
641void ExceptionsWidget::changeException()
642{
643 int pos = mExceptionList->currentItem();
644 if ( pos < 0 ) return;
645
646 TQDate date = mExceptionDateEdit->date();
647 mExceptionDates[ pos ] = date;
648 mExceptionList->changeItem( TDEGlobal::locale()->formatDate( date ), pos );
649}
650
651void ExceptionsWidget::deleteException()
652{
653 int pos = mExceptionList->currentItem();
654 if ( pos < 0 ) return;
655
656 mExceptionDates.remove( mExceptionDates.at( pos ) );
657 mExceptionList->removeItem( pos );
658}
659
660void ExceptionsWidget::setDates( const DateList &dates )
661{
662 mExceptionList->clear();
663 mExceptionDates.clear();
664 DateList::ConstIterator dit;
665 for ( dit = dates.begin(); dit != dates.end(); ++dit ) {
666 mExceptionList->insertItem( TDEGlobal::locale()->formatDate(* dit ) );
667 mExceptionDates.append( *dit );
668 }
669}
670
671DateList ExceptionsWidget::dates()
672{
673 return mExceptionDates;
674}
675
677
678ExceptionsDialog::ExceptionsDialog( TQWidget *parent, const char *name ) :
679 KDialogBase( parent, name, true, i18n("Edit Exceptions"), Ok|Cancel )
680{
681 mExceptions = new ExceptionsWidget( this );
682 setMainWidget( mExceptions );
683}
684
685void ExceptionsDialog::setDates( const DateList &dates )
686{
687 mExceptions->setDates( dates );
688}
689
690DateList ExceptionsDialog::dates()
691{
692 return mExceptions->dates();
693}
694
696
697RecurrenceRangeWidget::RecurrenceRangeWidget( TQWidget *parent,
698 const char *name )
699 : TQWidget( parent, name )
700{
701 TQBoxLayout *topLayout = new TQVBoxLayout( this );
702
703 mRangeGroupBox = new TQGroupBox( 1, TQt::Horizontal, i18n("Recurrence Range"),
704 this );
705 TQWhatsThis::add( mRangeGroupBox,
706 i18n("Sets a range for which these recurrence rules will "
707 "apply to this event or to-do.") );
708 topLayout->addWidget( mRangeGroupBox );
709
710 TQWidget *rangeBox = new TQWidget( mRangeGroupBox );
711 TQVBoxLayout *rangeLayout = new TQVBoxLayout( rangeBox );
712 rangeLayout->setSpacing( KDialog::spacingHint() );
713
714 mStartDateLabel = new TQLabel( i18n("Begin on:"), rangeBox );
715 TQWhatsThis::add( mStartDateLabel,
716 i18n("The date on which the recurrences for this event or to-do "
717 "should begin.") );
718 rangeLayout->addWidget( mStartDateLabel );
719
720 TQButtonGroup *rangeButtonGroup = new TQButtonGroup( this );
721 rangeButtonGroup->hide();
722
723 mNoEndDateButton = new TQRadioButton( i18n("&No ending date"), rangeBox );
724 TQWhatsThis::add( mNoEndDateButton,
725 i18n("Sets the event or to-do to recur forever.") );
726 rangeButtonGroup->insert( mNoEndDateButton );
727 rangeLayout->addWidget( mNoEndDateButton );
728
729 TQBoxLayout *durationLayout = new TQHBoxLayout( rangeLayout );
730 durationLayout->setSpacing( KDialog::spacingHint() );
731
732 mEndDurationButton = new TQRadioButton( i18n("End &after"), rangeBox );
733 TQWhatsThis::add( mEndDurationButton,
734 i18n("Sets the event or to-do to stop recurring after a "
735 "certain number of occurrences.") );
736 rangeButtonGroup->insert( mEndDurationButton );
737 durationLayout->addWidget( mEndDurationButton );
738
739 TQString whatsThis = i18n("Number of times the event or to-do should recur "
740 "before stopping.");
741 mEndDurationEdit = new TQSpinBox( 1, 9999, 1, rangeBox );
742 TQWhatsThis::add( mEndDurationEdit, whatsThis );
743 durationLayout->addWidget( mEndDurationEdit );
744
745 TQLabel *endDurationLabel = new TQLabel( i18n("&occurrence(s)"), rangeBox );
746 TQWhatsThis::add( endDurationLabel, whatsThis );
747 durationLayout ->addWidget( endDurationLabel );
748 endDurationLabel->setBuddy( mEndDurationEdit );
749
750 TQBoxLayout *endDateLayout = new TQHBoxLayout( rangeLayout );
751 endDateLayout->setSpacing( KDialog::spacingHint() );
752
753 mEndDateButton = new TQRadioButton( i18n("End &on:"), rangeBox );
754 TQWhatsThis::add( mEndDateButton,
755 i18n("Sets the event or to-do to stop recurring on "
756 "a certain date.") );
757 rangeButtonGroup->insert( mEndDateButton );
758 endDateLayout->addWidget( mEndDateButton );
759
760 mEndDateEdit = new KDateEdit( rangeBox );
761 TQWhatsThis::add( mEndDateEdit,
762 i18n("Date after which the event or to-do should stop "
763 "recurring") );
764 endDateLayout->addWidget( mEndDateEdit );
765
766 endDateLayout->addStretch( 1 );
767
768 connect( mNoEndDateButton, TQ_SIGNAL( toggled( bool ) ),
769 TQ_SLOT( showCurrentRange() ) );
770 connect( mEndDurationButton, TQ_SIGNAL( toggled( bool ) ),
771 TQ_SLOT( showCurrentRange() ) );
772 connect( mEndDateButton, TQ_SIGNAL( toggled( bool ) ),
773 TQ_SLOT( showCurrentRange() ) );
774}
775
776void RecurrenceRangeWidget::setDefaults( const TQDateTime &from )
777{
778 mNoEndDateButton->setChecked( true );
779
780 setDateTimes( from );
781 setEndDate( from.date() );
782}
783
784void RecurrenceRangeWidget::setDuration( int duration )
785{
786 if ( duration == -1 ) {
787 mNoEndDateButton->setChecked( true );
788 } else if ( duration == 0 ) {
789 mEndDateButton->setChecked( true );
790 } else {
791 mEndDurationButton->setChecked( true );
792 mEndDurationEdit->setValue( duration );
793 }
794}
795
796int RecurrenceRangeWidget::duration()
797{
798 if ( mNoEndDateButton->isChecked() ) {
799 return -1;
800 } else if ( mEndDurationButton->isChecked() ) {
801 return mEndDurationEdit->value();
802 } else {
803 return 0;
804 }
805}
806
807void RecurrenceRangeWidget::setEndDate( const TQDate &date )
808{
809 mEndDateEdit->setDate( date );
810}
811
812TQDate RecurrenceRangeWidget::endDate()
813{
814 return mEndDateEdit->date();
815}
816
817void RecurrenceRangeWidget::showCurrentRange()
818{
819 mEndDurationEdit->setEnabled( mEndDurationButton->isChecked() );
820 mEndDateEdit->setEnabled( mEndDateButton->isChecked() );
821}
822
823void RecurrenceRangeWidget::setDateTimes( const TQDateTime &start,
824 const TQDateTime & )
825{
826 mStartDateLabel->setText( i18n("Begins on: %1")
827 .arg( TDEGlobal::locale()->formatDate( start.date() ) ) );
828}
829
831
832RecurrenceRangeDialog::RecurrenceRangeDialog( TQWidget *parent,
833 const char *name ) :
834 KDialogBase( parent, name, true, i18n("Edit Recurrence Range"), Ok|Cancel )
835{
836 mRecurrenceRangeWidget = new RecurrenceRangeWidget( this );
837 setMainWidget( mRecurrenceRangeWidget );
838}
839
840void RecurrenceRangeDialog::setDefaults( const TQDateTime &from )
841{
842 mRecurrenceRangeWidget->setDefaults( from );
843}
844
845void RecurrenceRangeDialog::setDuration( int duration )
846{
847 mRecurrenceRangeWidget->setDuration( duration );
848}
849
850int RecurrenceRangeDialog::duration()
851{
852 return mRecurrenceRangeWidget->duration();
853}
854
855void RecurrenceRangeDialog::setEndDate( const TQDate &date )
856{
857 mRecurrenceRangeWidget->setEndDate( date );
858}
859
860TQDate RecurrenceRangeDialog::endDate()
861{
862 return mRecurrenceRangeWidget->endDate();
863}
864
865void RecurrenceRangeDialog::setDateTimes( const TQDateTime &start,
866 const TQDateTime &end )
867{
868 mRecurrenceRangeWidget->setDateTimes( start, end );
869}
870
872
873RecurrenceChooser::RecurrenceChooser( TQWidget *parent, const char *name ) :
874 TQWidget( parent, name )
875{
876 TQBoxLayout *topLayout = new TQVBoxLayout( this );
877
878 if ( KOPrefs::instance()->mCompactDialogs ) {
879 mTypeCombo = new TQComboBox( this );
880 TQWhatsThis::add( mTypeCombo,
881 i18n("Sets the type of recurrence this event or to-do "
882 "should have.") );
883 mTypeCombo->insertItem( i18n("Daily") );
884 mTypeCombo->insertItem( i18n("Weekly") );
885 mTypeCombo->insertItem( i18n("Monthly") );
886 mTypeCombo->insertItem( i18n("Yearly") );
887
888 topLayout->addWidget( mTypeCombo );
889
890 connect( mTypeCombo, TQ_SIGNAL( activated( int ) ), TQ_SLOT( emitChoice() ) );
891 } else {
892 mTypeCombo = 0;
893
894 TQButtonGroup *ruleButtonGroup = new TQButtonGroup( 1, TQt::Horizontal, this );
895 ruleButtonGroup->setFrameStyle( TQFrame::NoFrame );
896 topLayout->addWidget( ruleButtonGroup );
897
898 mDailyButton = new TQRadioButton( i18n("&Daily"), ruleButtonGroup );
899 TQWhatsThis::add( mDailyButton,
900 i18n("Sets the event or to-do to recur daily according "
901 "to the specified rules.") );
902 mWeeklyButton = new TQRadioButton( i18n("&Weekly"), ruleButtonGroup );
903 TQWhatsThis::add( mWeeklyButton,
904 i18n("Sets the event or to-do to recur weekly according "
905 "to the specified rules.") );
906 mMonthlyButton = new TQRadioButton( i18n("&Monthly"), ruleButtonGroup );
907 TQWhatsThis::add( mMonthlyButton,
908 i18n("Sets the event or to-do to recur monthly according "
909 "to the specified rules.") );
910 mYearlyButton = new TQRadioButton( i18n("&Yearly"), ruleButtonGroup );
911 TQWhatsThis::add( mYearlyButton,
912 i18n("Sets the event or to-do to recur yearly according "
913 "to the specified rules.") );
914
915 connect( mDailyButton, TQ_SIGNAL( toggled( bool ) ),
916 TQ_SLOT( emitChoice() ) );
917 connect( mWeeklyButton, TQ_SIGNAL( toggled( bool ) ),
918 TQ_SLOT( emitChoice() ) );
919 connect( mMonthlyButton, TQ_SIGNAL( toggled( bool ) ),
920 TQ_SLOT( emitChoice() ) );
921 connect( mYearlyButton, TQ_SIGNAL( toggled( bool ) ),
922 TQ_SLOT( emitChoice() ) );
923 }
924}
925
926int RecurrenceChooser::type()
927{
928 if ( mTypeCombo ) {
929 return mTypeCombo->currentItem();
930 } else {
931 if ( mDailyButton->isChecked() ) return Daily;
932 else if ( mWeeklyButton->isChecked() ) return Weekly;
933 else if ( mMonthlyButton->isChecked() ) return Monthly;
934 else return Yearly;
935 }
936}
937
938void RecurrenceChooser::setType( int type )
939{
940 if ( mTypeCombo ) {
941 mTypeCombo->setCurrentItem( type );
942 } else {
943 switch ( type ) {
944 case Daily:
945 mDailyButton->setChecked( true );
946 break;
947 case Weekly:
948 mWeeklyButton->setChecked( true );
949 break;
950 case Monthly:
951 mMonthlyButton->setChecked( true );
952 break;
953 case Yearly:
954 default:
955 mYearlyButton->setChecked( true );
956 break;
957 }
958 }
959}
960
961void RecurrenceChooser::emitChoice()
962{
963 emit chosen ( type() );
964}
965
967
968KOEditorRecurrence::KOEditorRecurrence( TQWidget* parent, const char *name ) :
969 TQWidget( parent, name )
970{
971 TQGridLayout *topLayout = new TQGridLayout( this );
972 topLayout->setSpacing( KDialog::spacingHint() );
973
974 mEnabledCheck = new TQCheckBox( i18n("&Enable recurrence"), this );
975 TQWhatsThis::add( mEnabledCheck,
976 i18n("Enables recurrence for this event or to-do according "
977 "to the specified rules.") );
978 connect( mEnabledCheck, TQ_SIGNAL( toggled( bool ) ),
979 TQ_SLOT( setRecurrenceEnabled( bool ) ) );
980 topLayout->addMultiCellWidget( mEnabledCheck, 0, 0, 0, 1 );
981
982
983 mTimeGroupBox = new TQGroupBox( 1, TQt::Horizontal, i18n("Appointment Time "),
984 this );
985 TQWhatsThis::add( mTimeGroupBox,
986 i18n("Displays appointment time information.") );
987 topLayout->addMultiCellWidget( mTimeGroupBox, 1, 1 , 0 , 1 );
988
989 if ( KOPrefs::instance()->mCompactDialogs ) {
990 mTimeGroupBox->hide();
991 }
992
993// TQFrame *timeFrame = new TQFrame( mTimeGroupBox );
994// TQBoxLayout *layoutTimeFrame = new TQHBoxLayout( timeFrame );
995// layoutTimeFrame->setSpacing( KDialog::spacingHint() );
996
997 mDateTimeLabel = new TQLabel( mTimeGroupBox );
998// mDateTimeLabel = new TQLabel( timeFrame );
999// layoutTimeFrame->addWidget( mDateTimeLabel );
1000
1001 TQt::Orientation orientation;
1002 if ( KOPrefs::instance()->mCompactDialogs ) orientation = TQt::Horizontal;
1003 else orientation = TQt::Vertical;
1004
1005 mRuleBox = new TQGroupBox( 1, orientation, i18n("Recurrence Rule"), this );
1006 TQWhatsThis::add( mRuleBox,
1007 i18n("Options concerning the type of recurrence this event "
1008 "or to-do should have.") );
1009 if ( KOPrefs::instance()->mCompactDialogs ) {
1010 topLayout->addWidget( mRuleBox, 2, 0 );
1011 } else {
1012 topLayout->addMultiCellWidget( mRuleBox, 2, 2, 0, 1 );
1013 }
1014
1015 mRecurrenceChooser = new RecurrenceChooser( mRuleBox );
1016 connect( mRecurrenceChooser, TQ_SIGNAL( chosen( int ) ),
1017 TQ_SLOT( showCurrentRule( int ) ) );
1018
1019 if ( !KOPrefs::instance()->mCompactDialogs ) {
1020 TQFrame *ruleSepFrame = new TQFrame( mRuleBox );
1021 ruleSepFrame->setFrameStyle( TQFrame::VLine | TQFrame::Sunken );
1022 }
1023
1024 mRuleStack = new TQWidgetStack( mRuleBox );
1025
1026 mDaily = new RecurDaily( mRuleStack );
1027 mRuleStack->addWidget( mDaily, 0 );
1028
1029 mWeekly = new RecurWeekly( mRuleStack );
1030 mRuleStack->addWidget( mWeekly, 0 );
1031
1032 mMonthly = new RecurMonthly( mRuleStack );
1033 mRuleStack->addWidget( mMonthly, 0 );
1034
1035 mYearly = new RecurYearly( mRuleStack );
1036 mRuleStack->addWidget( mYearly, 0 );
1037
1038 showCurrentRule( mRecurrenceChooser->type() );
1039
1040 if ( KOPrefs::instance()->mCompactDialogs ) {
1041 mRecurrenceRangeWidget = 0;
1042 mRecurrenceRangeDialog = new RecurrenceRangeDialog( this );
1043 mRecurrenceRange = mRecurrenceRangeDialog;
1044 mRecurrenceRangeButton = new TQPushButton( i18n("Recurrence Range..."),
1045 this );
1046 TQWhatsThis::add( mRecurrenceRangeButton,
1047 i18n("Options concerning the time range during which "
1048 "this event or to-do should recur.") );
1049 topLayout->addWidget( mRecurrenceRangeButton, 3, 0 );
1050 connect( mRecurrenceRangeButton, TQ_SIGNAL( clicked() ),
1051 TQ_SLOT( showRecurrenceRangeDialog() ) );
1052
1053 mExceptionsWidget = 0;
1054 mExceptionsDialog = new ExceptionsDialog( this );
1055 mExceptions = mExceptionsDialog;
1056 mExceptionsButton = new TQPushButton( i18n("Exceptions..."), this );
1057 topLayout->addWidget( mExceptionsButton, 4, 0 );
1058 connect( mExceptionsButton, TQ_SIGNAL( clicked() ),
1059 TQ_SLOT( showExceptionsDialog() ) );
1060
1061 } else {
1062 mRecurrenceRangeWidget = new RecurrenceRangeWidget( this );
1063 TQWhatsThis::add( mRecurrenceRangeWidget,
1064 i18n("Options concerning the time range during which "
1065 "this event or to-do should recur.") );
1066 mRecurrenceRangeDialog = 0;
1067 mRecurrenceRange = mRecurrenceRangeWidget;
1068 mRecurrenceRangeButton = 0;
1069 topLayout->addWidget( mRecurrenceRangeWidget, 3, 0 );
1070
1071 mExceptionsWidget = new ExceptionsWidget( this );
1072 mExceptionsDialog = 0;
1073 mExceptions = mExceptionsWidget;
1074 mExceptionsButton = 0;
1075 topLayout->addWidget( mExceptionsWidget, 3, 1 );
1076 }
1077
1078 // set some initial defaults for the saved recurrence
1079 mSaveRec.setDuration( -1 ); // never ending
1080}
1081
1082KOEditorRecurrence::~KOEditorRecurrence()
1083{
1084}
1085
1086void KOEditorRecurrence::setRecurrenceEnabled( bool enabled )
1087{
1088// kdDebug(5850) << "KOEditorRecurrence::setRecurrenceEnabled(): " << (enabled ? "on" : "off") << endl;
1089
1090 mEnabledCheck->setChecked( enabled );
1091 mTimeGroupBox->setEnabled( enabled );
1092 mRuleBox->setEnabled( enabled );
1093 if ( mRecurrenceRangeWidget ) mRecurrenceRangeWidget->setEnabled( enabled );
1094 if ( mRecurrenceRangeButton ) mRecurrenceRangeButton->setEnabled( enabled );
1095 if ( mExceptionsWidget ) mExceptionsWidget->setEnabled( enabled );
1096 if ( mExceptionsButton ) mExceptionsButton->setEnabled( enabled );
1097}
1098
1099void KOEditorRecurrence::showCurrentRule( int current )
1100{
1101 switch ( current ) {
1102 case Daily:
1103 mRuleStack->raiseWidget( mDaily );
1104 break;
1105 case Weekly:
1106 mRuleStack->raiseWidget( mWeekly );
1107 break;
1108 case Monthly:
1109 mRuleStack->raiseWidget( mMonthly );
1110 break;
1111 default:
1112 case Yearly:
1113 mRuleStack->raiseWidget( mYearly );
1114 break;
1115 }
1116}
1117
1118void KOEditorRecurrence::setDateTimes( const TQDateTime &start, const TQDateTime &end )
1119{
1120// kdDebug(5850) << "KOEditorRecurrence::setDateTimes" << endl;
1121
1122 mEventStartDt = start;
1123 mRecurrenceRange->setDateTimes( start, end );
1124 mDaily->setDateTimes( start, end );
1125 mWeekly->setDateTimes( start, end );
1126 mMonthly->setDateTimes( start, end );
1127 mYearly->setDateTimes( start, end );
1128
1129 // Now set the defaults for all unused types, use the start time for it
1130 bool enabled = mEnabledCheck->isChecked();
1131 int type = mRecurrenceChooser->type();
1132
1133 if ( !enabled || type != RecurrenceChooser::Weekly ) {
1134 TQBitArray days( 7 );
1135 days.fill( 0 );
1136 days.setBit( (start.date().dayOfWeek()+6) % 7 );
1137 mWeekly->setDays( days );
1138 }
1139 if ( !enabled || type != RecurrenceChooser::Monthly ) {
1140 mMonthly->setByPos( ( start.date().day() - 1 ) / 7 + 1, start.date().dayOfWeek() - 1 );
1141 mMonthly->setByDay( start.date().day() );
1142 }
1143 if ( !enabled || type != RecurrenceChooser::Yearly ) {
1144 mYearly->setByDay( start.date().dayOfYear() );
1145 mYearly->setByPos( ( start.date().day() - 1 ) / 7 + 1,
1146 start.date().dayOfWeek() - 1, start.date().month() );
1147 mYearly->setByMonth( start.date().day(), start.date().month() );
1148 }
1149}
1150
1151void KOEditorRecurrence::setDefaults( const TQDateTime &from, const TQDateTime &to, bool )
1152{
1153 setDateTimes( from, to );
1154
1155 setRecurrenceEnabled( false );
1156
1157 mRecurrenceRange->setDefaults( from );
1158
1159 mRecurrenceChooser->setType( RecurrenceChooser::Weekly );
1160 showCurrentRule( mRecurrenceChooser->type() );
1161
1162 mDaily->setFrequency( 1 );
1163
1164 mWeekly->setFrequency( 1 );
1165 TQBitArray days( 7 );
1166 days.fill( 0 );
1167 days.setBit( (from.date().dayOfWeek()+6) % 7 );
1168 mWeekly->setDays( days );
1169
1170 mMonthly->setFrequency( 1 );
1171 mMonthly->setByPos( ( from.date().day() - 1 ) / 7 + 1, from.date().dayOfWeek() );
1172 mMonthly->setByDay( from.date().day() );
1173
1174 mYearly->setFrequency( 1 );
1175 mYearly->setByDay( from.date().dayOfYear() );
1176 mYearly->setByPos( ( from.date().day() - 1 ) / 7 + 1,
1177 from.date().dayOfWeek(), from.date().month() );
1178 mYearly->setByMonth( from.date().day(), from.date().month() );
1179}
1180
1181void KOEditorRecurrence::readIncidence(Incidence *incidence)
1182{
1183 if (!incidence) return;
1184
1185 TQBitArray rDays( 7 );
1186 int day = 0;
1187 int count = 0;
1188 int month = 0;
1189
1190 if ( incidence->type() == "Todo" ) {
1191 Todo *todo = static_cast<Todo *>(incidence);
1192 setDefaults( todo->dtStart(true), todo->dtDue(), todo->doesFloat() );
1193 } else {
1194 setDefaults( incidence->dtStart(), incidence->dtEnd(), incidence->doesFloat() );
1195 }
1196
1197 uint recurs = incidence->recurrenceType();
1198 int f = 0;
1199 Recurrence *r = 0;
1200
1201 if ( recurs ) {
1202 r = incidence->recurrence();
1203 f = r->frequency();
1204 }
1205
1206 setRecurrenceEnabled( recurs );
1207
1208 int recurrenceType = RecurrenceChooser::Weekly;
1209
1210 switch ( recurs ) {
1211 case Recurrence::rNone:
1212 break;
1213 case Recurrence::rDaily:
1214 recurrenceType = RecurrenceChooser::Daily;
1215 mDaily->setFrequency( f );
1216 break;
1217 case Recurrence::rWeekly:
1218 recurrenceType = RecurrenceChooser::Weekly;
1219 mWeekly->setFrequency( f );
1220 mWeekly->setDays( r->days() );
1221 break;
1222 case Recurrence::rMonthlyPos: {
1223 // TODO: we only handle one possibility in the list right now,
1224 // so I have hardcoded calls with first(). If we make the GUI
1225 // more extended, this can be changed.
1226 recurrenceType = RecurrenceChooser::Monthly;
1227
1228 TQValueList<RecurrenceRule::WDayPos> rmp = r->monthPositions();
1229 if ( !rmp.isEmpty() ) {
1230 mMonthly->setByPos( rmp.first().pos(), rmp.first().day() );
1231 }
1232
1233 mMonthly->setFrequency( f );
1234
1235 break; }
1236 case Recurrence::rMonthlyDay: {
1237 recurrenceType = RecurrenceChooser::Monthly;
1238
1239 TQValueList<int> rmd = r->monthDays();
1240 // check if we have any setting for which day (vcs import is broken and
1241 // does not set any day, thus we need to check)
1242 if ( rmd.isEmpty() ) {
1243 day = incidence->dtStart().date().day();
1244 } else {
1245 day = rmd.first();
1246 }
1247 mMonthly->setByDay( day );
1248
1249 mMonthly->setFrequency( f );
1250
1251 break; }
1252 case Recurrence::rYearlyMonth: {
1253 recurrenceType = RecurrenceChooser::Yearly;
1254 TQValueList<int> rmd = r->yearDates();
1255 if ( rmd.isEmpty() ) {
1256 day = incidence->dtStart().date().day();
1257 } else {
1258 day = rmd.first();
1259 }
1260 int month = incidence->dtStart().date().month();
1261 rmd = r->yearMonths();
1262 if ( !rmd.isEmpty() )
1263 month = rmd.first();
1264 mYearly->setByMonth( day, month );
1265 mYearly->setFrequency( f );
1266 break; }
1267 case Recurrence::rYearlyPos: {
1268 recurrenceType = RecurrenceChooser::Yearly;
1269
1270 TQValueList<int> months = r->yearMonths();
1271 if ( months.isEmpty() ) {
1272 month = incidence->dtStart().date().month();
1273 } else {
1274 month = months.first();
1275 }
1276
1277 TQValueList<RecurrenceRule::WDayPos> pos = r->yearPositions();
1278
1279 if ( pos.isEmpty() ) {
1280 // Use dtStart if nothing is given (shouldn't happen!)
1281 count = ( incidence->dtStart().date().day() - 1 ) / 7;
1282 day = incidence->dtStart().date().dayOfWeek();
1283 } else {
1284 count = pos.first().pos();
1285 day = pos.first().day();
1286 }
1287 mYearly->setByPos( count, day, month );
1288 mYearly->setFrequency( f );
1289 break; }
1290 case Recurrence::rYearlyDay: {
1291 recurrenceType = RecurrenceChooser::Yearly;
1292 TQValueList<int> days = r->yearDays();
1293 if ( days.isEmpty() ) {
1294 day = incidence->dtStart().date().dayOfYear();
1295 } else {
1296 day = days.first();
1297 }
1298 mYearly->setByDay( day );
1299
1300 mYearly->setFrequency( f );
1301 break; }
1302 default:
1303 break;
1304 }
1305
1306 mRecurrenceChooser->setType( recurrenceType );
1307 showCurrentRule( recurrenceType );
1308
1309 mRecurrenceRange->setDateTimes( incidence->recurrence()->startDateTime() );
1310
1311 if ( incidence->doesRecur() ) {
1312 mRecurrenceRange->setDuration( r->duration() );
1313 if ( r->duration() == 0 ) mRecurrenceRange->setEndDate( r->endDate() );
1314 }
1315
1316 mExceptions->setDates( incidence->recurrence()->exDates() );
1317}
1318
1319void KOEditorRecurrence::writeIncidence( Incidence *incidence )
1320{
1321 if ( !mEnabledCheck->isChecked() || !isEnabled() )
1322 {
1323 if ( incidence->doesRecur() )
1324 incidence->recurrence()->unsetRecurs();
1325 return;
1326 }
1327
1328 Recurrence *r = incidence->recurrence();
1329
1330 // clear out any old settings;
1331 r->unsetRecurs();
1332
1333 int duration = mRecurrenceRange->duration();
1334 TQDate endDate;
1335 if ( duration == 0 ) endDate = mRecurrenceRange->endDate();
1336
1337 int recurrenceType = mRecurrenceChooser->type();
1338 if ( recurrenceType == RecurrenceChooser::Daily ) {
1339 r->setDaily( mDaily->frequency() );
1340 } else if ( recurrenceType == RecurrenceChooser::Weekly ) {
1341 r->setWeekly( mWeekly->frequency(), mWeekly->days() );
1342 } else if ( recurrenceType == RecurrenceChooser::Monthly ) {
1343 r->setMonthly( mMonthly->frequency() );
1344
1345 if ( mMonthly->byPos() ) {
1346 int pos = mMonthly->count();
1347
1348 TQBitArray days( 7 );
1349 days.fill( false );
1350 days.setBit( mMonthly->weekday() - 1 );
1351 r->addMonthlyPos( pos, days );
1352 } else {
1353 // it's by day
1354 r->addMonthlyDate( mMonthly->day() );
1355 }
1356 } else if ( recurrenceType == RecurrenceChooser::Yearly ) {
1357 r->setYearly( mYearly->frequency() );
1358
1359 switch ( mYearly->getType() ) {
1360 case RecurYearly::byMonth:
1361 r->addYearlyDate( mYearly->monthDay() );
1362 r->addYearlyMonth( mYearly->month() );
1363 break;
1364 case RecurYearly::byPos: {
1365 r->addYearlyMonth( mYearly->posMonth() );
1366 TQBitArray days( 7 );
1367 days.fill( false );
1368 days.setBit( mYearly->posWeekday() - 1 );
1369 r->addYearlyPos( mYearly->posCount(), days );
1370 break; }
1371 case RecurYearly::byDay:
1372 r->addYearlyDay( mYearly->day() );
1373 break;
1374 }
1375 } // end "Yearly"
1376
1377 if ( duration > 0 )
1378 r->setDuration( duration );
1379 else if ( duration == 0 )
1380 r->setEndDate( endDate );
1381 incidence->recurrence()->setExDates( mExceptions->dates() );
1382}
1383
1384void KOEditorRecurrence::setDateTimeStr( const TQString &str )
1385{
1386 mDateTimeLabel->setText( str );
1387}
1388
1389bool KOEditorRecurrence::validateInput()
1390{
1391 // Check input here.
1392 // Check if the recurrence (if set to end at a date) is scheduled to end before the event starts.
1393 if ( mEnabledCheck->isChecked() && (mRecurrenceRange->duration()==0) &&
1394 mEventStartDt.isValid() && ((mRecurrenceRange->endDate())<mEventStartDt.date()) ) {
1395 KMessageBox::sorry( 0,
1396 i18n("The end date '%1' of the recurrence must be after the start date '%2' of the event.")
1397 .arg( TDEGlobal::locale()->formatDate( mRecurrenceRange->endDate() ) )
1398 .arg( TDEGlobal::locale()->formatDate( mEventStartDt.date() ) ) );
1399 return false;
1400 }
1401 int recurrenceType = mRecurrenceChooser->type();
1402 // Check if a weekly recurrence has at least one day selected
1403 // TODO: Get rid of this, it's not really needed (by default the day should be taken from dtStart)
1404 if( mEnabledCheck->isChecked() && recurrenceType == RecurrenceChooser::Weekly ) {
1405 const TQBitArray &days = mWeekly->days();
1406 bool valid = false;
1407 for ( int i=0; i<7; ++i ) valid = valid || days.testBit( i );
1408 if ( !valid ) {
1409 KMessageBox::sorry( 0,
1410 i18n("A weekly recurring event or task has to have at least one weekday "
1411 "associated with it.") );
1412 return false;
1413 }
1414 }
1415 return true;
1416}
1417
1418void KOEditorRecurrence::showExceptionsDialog()
1419{
1420 DateList dates = mExceptions->dates();
1421 int result = mExceptionsDialog->exec();
1422 if ( result == TQDialog::Rejected ) mExceptions->setDates( dates );
1423}
1424
1425void KOEditorRecurrence::showRecurrenceRangeDialog()
1426{
1427 int duration = mRecurrenceRange->duration();
1428 TQDate endDate = mRecurrenceRange->endDate();
1429
1430 int result = mRecurrenceRangeDialog->exec();
1431 if ( result == TQDialog::Rejected ) {
1432 mRecurrenceRange->setDuration( duration );
1433 mRecurrenceRange->setEndDate( endDate );
1434 }
1435}
1436
1437bool KOEditorRecurrence::doesRecur()
1438{
1439 return mEnabledCheck->isChecked();
1440}
1441
1442void KOEditorRecurrence::saveValues()
1443{
1444 int duration = mRecurrenceRange->duration();
1445 TQDate endDate;
1446 if ( duration == 0 ) {
1447 endDate = mRecurrenceRange->endDate();
1448 }
1449
1450 int recurrenceType = mRecurrenceChooser->type();
1451 if ( recurrenceType == RecurrenceChooser::Daily ) {
1452 mSaveRec.setDaily( mDaily->frequency() );
1453 } else if ( recurrenceType == RecurrenceChooser::Weekly ) {
1454 mSaveRec.setWeekly( mWeekly->frequency(), mWeekly->days() );
1455 } else if ( recurrenceType == RecurrenceChooser::Monthly ) {
1456 mSaveRec.setMonthly( mMonthly->frequency() );
1457
1458 if ( mMonthly->byPos() ) {
1459 int pos = mMonthly->count();
1460
1461 TQBitArray days( 7 );
1462 days.fill( false );
1463 days.setBit( mMonthly->weekday() - 1 );
1464 mSaveRec.addMonthlyPos( pos, days );
1465 } else {
1466 // it's by day
1467 mSaveRec.addMonthlyDate( mMonthly->day() );
1468 }
1469 } else if ( recurrenceType == RecurrenceChooser::Yearly ) {
1470 mSaveRec.setYearly( mYearly->frequency() );
1471
1472 switch ( mYearly->getType() ) {
1473 case RecurYearly::byMonth:
1474 mSaveRec.addYearlyDate( mYearly->monthDay() );
1475 mSaveRec.addYearlyMonth( mYearly->month() );
1476 break;
1477
1478 case RecurYearly::byPos:
1479 {
1480 mSaveRec.addYearlyMonth( mYearly->posMonth() );
1481 TQBitArray days( 7 );
1482 days.fill( false );
1483 days.setBit( mYearly->posWeekday() - 1 );
1484 mSaveRec.addYearlyPos( mYearly->posCount(), days );
1485 break;
1486 }
1487
1488 case RecurYearly::byDay:
1489 mSaveRec.addYearlyDay( mYearly->day() );
1490 break;
1491 }
1492 }
1493
1494 if ( duration > 0 ) {
1495 mSaveRec.setDuration( duration );
1496 } else if ( duration == 0 ) {
1497 mSaveRec.setEndDate( endDate );
1498 }
1499
1500 mSaveRec.setExDates( mExceptions->dates() );
1501}
1502
1503void KOEditorRecurrence::restoreValues()
1504{
1505 TQBitArray rDays( 7 );
1506 int day = 0;
1507 int count = 0;
1508 int month = 0;
1509
1510 if ( mSaveRec.startDateTime().isValid() && mSaveRec.endDateTime().isValid() ) {
1511 setDefaults( mSaveRec.startDateTime(), mSaveRec.endDateTime(), mSaveRec.doesFloat() );
1512 }
1513
1514 int recurrenceType;
1515 switch ( mSaveRec.recurrenceType() ) {
1516 case Recurrence::rNone:
1517 recurrenceType = RecurrenceChooser::Weekly;
1518 break;
1519
1520 case Recurrence::rDaily:
1521 recurrenceType = RecurrenceChooser::Daily;
1522 mDaily->setFrequency( mSaveRec.frequency() );
1523 break;
1524
1525 case Recurrence::rWeekly:
1526 recurrenceType = RecurrenceChooser::Weekly;
1527
1528 mWeekly->setFrequency( mSaveRec.frequency() );
1529 mWeekly->setDays( mSaveRec.days() );
1530 break;
1531
1532 case Recurrence::rMonthlyPos:
1533 {
1534 // TODO: we only handle one possibility in the list right now,
1535 // so I have hardcoded calls with first(). If we make the GUI
1536 // more extended, this can be changed.
1537 recurrenceType = RecurrenceChooser::Monthly;
1538
1539 TQValueList<RecurrenceRule::WDayPos> rmp = mSaveRec.monthPositions();
1540 if ( !rmp.isEmpty() ) {
1541 mMonthly->setByPos( rmp.first().pos(), rmp.first().day() );
1542 }
1543 mMonthly->setFrequency( mSaveRec.frequency() );
1544 break;
1545 }
1546
1547 case Recurrence::rMonthlyDay:
1548 {
1549 recurrenceType = RecurrenceChooser::Monthly;
1550
1551 TQValueList<int> rmd = mSaveRec.monthDays();
1552 // check if we have any setting for which day (vcs import is broken and
1553 // does not set any day, thus we need to check)
1554 if ( !rmd.isEmpty() ) {
1555 day = rmd.first();
1556 }
1557 if ( day > 0 ) {
1558 mMonthly->setByDay( day );
1559 mMonthly->setFrequency( mSaveRec.frequency() );
1560 }
1561 break;
1562 }
1563
1564 case Recurrence::rYearlyMonth:
1565 {
1566 recurrenceType = RecurrenceChooser::Yearly;
1567
1568 TQValueList<int> rmd = mSaveRec.yearDates();
1569 if ( !rmd.isEmpty() ) {
1570 day = rmd.first();
1571 }
1572 rmd = mSaveRec.yearMonths();
1573 if ( !rmd.isEmpty() ) {
1574 month = rmd.first();
1575 }
1576 if ( day > 0 && month > 0 ) {
1577 mYearly->setByMonth( day, month );
1578 mYearly->setFrequency( mSaveRec.frequency() );
1579 }
1580 break;
1581 }
1582
1583 case Recurrence::rYearlyPos:
1584 {
1585 recurrenceType = RecurrenceChooser::Yearly;
1586
1587 TQValueList<int> months = mSaveRec.yearMonths();
1588 if ( !months.isEmpty() ) {
1589 month = months.first();
1590 }
1591 TQValueList<RecurrenceRule::WDayPos> pos = mSaveRec.yearPositions();
1592 if ( !pos.isEmpty() ) {
1593 count = pos.first().pos();
1594 day = pos.first().day();
1595 }
1596 if ( count > 0 && day > 0 && month > 0 ) {
1597 mYearly->setByPos( count, day, month );
1598 mYearly->setFrequency( mSaveRec.frequency() );
1599 }
1600 break;
1601 }
1602
1603 case Recurrence::rYearlyDay:
1604 {
1605 recurrenceType = RecurrenceChooser::Yearly;
1606
1607 TQValueList<int> days = mSaveRec.yearDays();
1608 if ( !days.isEmpty() ) {
1609 day = days.first();
1610 }
1611 if ( day > 0 ) {
1612 mYearly->setByDay( day );
1613 mYearly->setFrequency( mSaveRec.frequency() );
1614 }
1615 break;
1616 }
1617 default:
1618 break;
1619 }
1620
1621 mRecurrenceChooser->setType( recurrenceType );
1622 showCurrentRule( recurrenceType );
1623
1624 if ( mSaveRec.startDateTime().isValid() ) {
1625 mRecurrenceRange->setDateTimes( mSaveRec.startDateTime() );
1626 }
1627
1628 mRecurrenceRange->setDuration( mSaveRec.duration() );
1629 if ( mSaveRec.duration() == 0 && mSaveRec.endDate().isValid() ) {
1630 mRecurrenceRange->setEndDate( mSaveRec.endDate() );
1631 }
1632
1633 mExceptions->setDates( mSaveRec.exDates() );
1634}
1635
1636KOEditorRecurrenceDialog::KOEditorRecurrenceDialog(TQWidget * parent)
1637 : KDialogBase( parent, 0, false, i18n("Recurrence"), Ok|Cancel ), mRecurEnabled( false )
1638{
1639 mRecurrence = new KOEditorRecurrence( this );
1640 setMainWidget( mRecurrence );
1641}
1642
1643void KOEditorRecurrenceDialog::slotOk()
1644{
1645 mRecurEnabled = mRecurrence->doesRecur();
1646 mRecurrence->saveValues();
1647 emit okClicked(); // tell the incidence editor to update the recurrenceString
1648 accept();
1649}
1650
1651void KOEditorRecurrenceDialog::slotCancel()
1652{
1653 mRecurrence->setRecurrenceEnabled( mRecurEnabled );
1654 mRecurrence->restoreValues();
1655 reject();
1656}
bool doesFloat() const
virtual TQDateTime dtStart() const
virtual TQDateTime dtEnd() const
bool doesRecur() const
Recurrence * recurrence() const
void addYearlyPos(short pos, const TQBitArray &days)
int frequency() const
void addYearlyDay(int day)
void setYearly(int freq)
void setWeekly(int freq, int weekStart=1)
TQValueList< RecurrenceRule::WDayPos > yearPositions() const
TQBitArray days() const
void setMonthly(int freq)
TQValueList< int > monthDays() const
void addYearlyMonth(short _rNum)
void addMonthlyPos(short pos, const TQBitArray &days)
void addYearlyDate(int date)
TQDateTime startDateTime() const
void setDaily(int freq)
int duration() const
TQDate endDate() const
TQValueList< int > yearMonths() const
void addMonthlyDate(short day)
TQValueList< RecurrenceRule::WDayPos > monthPositions() const
void setEndDate(const TQDate &endDate)
TQValueList< int > yearDays() const
TQValueList< int > yearDates() const
void setDuration(int duration)
TQDateTime dtStart(bool first=false) const
TQDateTime dtDue(bool first=false) const