summaryrefslogtreecommitdiffabout
path: root/korganizer/koeditorrecurrence.cpp
Unidiff
Diffstat (limited to 'korganizer/koeditorrecurrence.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--korganizer/koeditorrecurrence.cpp1117
1 files changed, 1117 insertions, 0 deletions
diff --git a/korganizer/koeditorrecurrence.cpp b/korganizer/koeditorrecurrence.cpp
new file mode 100644
index 0000000..d82172f
--- a/dev/null
+++ b/korganizer/koeditorrecurrence.cpp
@@ -0,0 +1,1117 @@
1/*
2 This file is part of KOrganizer.
3 Copyright (c) 2000-2003 Cornelius Schumacher <schumacher@kde.org>
4
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
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
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
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 As a special exception, permission is given to link this program
20 with any edition of Qt, and distribute the resulting executable,
21 without including the source code for Qt in the source distribution.
22*/
23
24#include <qtooltip.h>
25#include <qfiledialog.h>
26#include <qlayout.h>
27#include <qvbox.h>
28#include <qbuttongroup.h>
29#include <qvgroupbox.h>
30#include <qwidgetstack.h>
31#include <qdatetime.h>
32#include <qlistbox.h>
33#include <qspinbox.h>
34#include <qcheckbox.h>
35#include <qapplication.h>
36
37#include <kdialog.h>
38#include <kglobal.h>
39#include <klocale.h>
40#include <kiconloader.h>
41#include <kdebug.h>
42#include <knumvalidator.h>
43
44#include <libkcal/event.h>
45
46#include <libkdepim/kdateedit.h>
47
48#include "koprefs.h"
49
50#include "koeditorrecurrence.h"
51#include "koeditorrecurrence.moc"
52
53/////////////////////////// RecurBase ///////////////////////////////
54
55RecurBase::RecurBase( QWidget *parent, const char *name ) :
56 QWidget( parent, name )
57{
58 mFrequencyEdit = new QSpinBox( 1, 9999, 1, this );
59 mFrequencyEdit->setValue( 1 );
60}
61
62QWidget *RecurBase::frequencyEdit()
63{
64 return mFrequencyEdit;
65}
66
67void RecurBase::setFrequency( int f )
68{
69 if ( f < 1 ) f = 1;
70
71 mFrequencyEdit->setValue( f );
72}
73
74int RecurBase::frequency()
75{
76 return mFrequencyEdit->value();
77}
78
79/////////////////////////// RecurDaily ///////////////////////////////
80
81RecurDaily::RecurDaily( QWidget *parent, const char *name ) :
82 RecurBase( parent, name )
83{
84 QBoxLayout *topLayout = new QHBoxLayout( this );
85 topLayout->setSpacing( KDialog::spacingHint() );
86
87 QLabel *preLabel = new QLabel( i18n("Recur every"), this );
88 topLayout->addWidget( preLabel );
89
90 topLayout->addWidget( frequencyEdit() );
91
92 QLabel *postLabel = new QLabel( i18n("day(s)"), this );
93 topLayout->addWidget( postLabel );
94}
95
96
97/////////////////////////// RecurWeekly ///////////////////////////////
98
99RecurWeekly::RecurWeekly( QWidget *parent, const char *name ) :
100 RecurBase( parent, name )
101{
102 QBoxLayout *topLayout = new QVBoxLayout( this );
103 topLayout->setSpacing( KDialog::spacingHint() );
104
105 topLayout->addStretch( 1 );
106
107 QBoxLayout *weeksLayout = new QHBoxLayout( topLayout );
108
109 QLabel *preLabel = new QLabel( i18n("Recur every"), this );
110 weeksLayout->addWidget( preLabel );
111
112 weeksLayout->addWidget( frequencyEdit() );
113
114 QLabel *postLabel = new QLabel( i18n("week(s) on:"), this );
115 weeksLayout->addWidget( postLabel );
116
117 QHBox *dayBox = new QHBox( this );
118 topLayout->addWidget( dayBox, 1, AlignVCenter );
119 // TODO: Respect start of week setting
120 for ( int i = 0; i < 7; ++i ) {
121 QString weekDayName = KGlobal::locale()->weekDayName( i + 1, true );
122 if ( KOPrefs::instance()->mCompactDialogs ) {
123 weekDayName = weekDayName.left( 1 );
124 }
125 mDayBoxes[ i ] = new QCheckBox( weekDayName, dayBox );
126 }
127
128 topLayout->addStretch( 1 );
129}
130
131void RecurWeekly::setDays( const QBitArray &days )
132{
133 for ( int i = 0; i < 7; ++i ) {
134 mDayBoxes[ i ]->setChecked( days.testBit( i ) );
135 }
136}
137
138QBitArray RecurWeekly::days()
139{
140 QBitArray days( 7 );
141
142 for ( int i = 0; i < 7; ++i ) {
143 days.setBit( i, mDayBoxes[ i ]->isChecked() );
144 }
145
146 return days;
147}
148
149/////////////////////////// RecurMonthly ///////////////////////////////
150
151RecurMonthly::RecurMonthly( QWidget *parent, const char *name ) :
152 RecurBase( parent, name )
153{
154 QBoxLayout *topLayout = new QVBoxLayout( this );
155 topLayout->setSpacing( KDialog::spacingHint() );
156
157
158 QBoxLayout *freqLayout = new QHBoxLayout( topLayout );
159
160 QLabel *preLabel = new QLabel( i18n("every"), this );
161 freqLayout->addWidget( preLabel );
162
163 freqLayout->addWidget( frequencyEdit() );
164
165 QLabel *postLabel = new QLabel( i18n("month(s)"), this );
166 freqLayout->addWidget( postLabel );
167
168
169 QButtonGroup *buttonGroup = new QButtonGroup( this );
170 buttonGroup->setFrameStyle( QFrame::NoFrame );
171 topLayout->addWidget( buttonGroup, 1, AlignVCenter );
172
173 QGridLayout *buttonLayout = new QGridLayout( buttonGroup, 3, 2 );
174 buttonLayout->setSpacing( KDialog::spacingHint() );
175
176
177 QString recurOnText;
178 if ( !KOPrefs::instance()->mCompactDialogs ) {
179 recurOnText = i18n("Recur on the");
180 }
181
182 mByDayRadio = new QRadioButton( recurOnText, buttonGroup );
183 buttonLayout->addWidget( mByDayRadio, 0, 0 );
184
185 mByDayCombo = new QComboBox( buttonGroup );
186 mByDayCombo->setSizeLimit( 7 );
187 mByDayCombo->insertItem( i18n("1st") );
188 mByDayCombo->insertItem( i18n("2nd") );
189 mByDayCombo->insertItem( i18n("3rd") );
190 mByDayCombo->insertItem( i18n("4th") );
191 mByDayCombo->insertItem( i18n("5th") );
192 mByDayCombo->insertItem( i18n("6th") );
193 mByDayCombo->insertItem( i18n("7th") );
194 mByDayCombo->insertItem( i18n("8th") );
195 mByDayCombo->insertItem( i18n("9th") );
196 mByDayCombo->insertItem( i18n("10th") );
197 mByDayCombo->insertItem( i18n("11th") );
198 mByDayCombo->insertItem( i18n("12th") );
199 mByDayCombo->insertItem( i18n("13th") );
200 mByDayCombo->insertItem( i18n("14th") );
201 mByDayCombo->insertItem( i18n("15th") );
202 mByDayCombo->insertItem( i18n("16th") );
203 mByDayCombo->insertItem( i18n("17th") );
204 mByDayCombo->insertItem( i18n("18th") );
205 mByDayCombo->insertItem( i18n("19th") );
206 mByDayCombo->insertItem( i18n("20th") );
207 mByDayCombo->insertItem( i18n("21st") );
208 mByDayCombo->insertItem( i18n("22nd") );
209 mByDayCombo->insertItem( i18n("23rd") );
210 mByDayCombo->insertItem( i18n("24th") );
211 mByDayCombo->insertItem( i18n("25th") );
212 mByDayCombo->insertItem( i18n("26th") );
213 mByDayCombo->insertItem( i18n("27th") );
214 mByDayCombo->insertItem( i18n("28th") );
215 mByDayCombo->insertItem( i18n("29th") );
216 mByDayCombo->insertItem( i18n("30th") );
217 mByDayCombo->insertItem( i18n("31st") );
218 buttonLayout->addWidget( mByDayCombo, 0, 1 );
219
220 QLabel *byDayLabel = new QLabel( i18n("day"), buttonGroup );
221 buttonLayout->addWidget( byDayLabel, 0, 2 );
222
223
224 mByPosRadio = new QRadioButton( recurOnText, buttonGroup);
225 buttonLayout->addWidget( mByPosRadio, 1, 0 );
226
227 mByPosCountCombo = new QComboBox( buttonGroup );
228 mByPosCountCombo->insertItem( i18n("1st") );
229 mByPosCountCombo->insertItem( i18n("2nd") );
230 mByPosCountCombo->insertItem( i18n("3rd") );
231 mByPosCountCombo->insertItem( i18n("4th") );
232 mByPosCountCombo->insertItem( i18n("5th") );
233 buttonLayout->addWidget( mByPosCountCombo, 1, 1 );
234
235 mByPosWeekdayCombo = new QComboBox( buttonGroup );
236 mByPosWeekdayCombo->insertItem( i18n("Monday") );
237 mByPosWeekdayCombo->insertItem( i18n("Tuesday") );
238 mByPosWeekdayCombo->insertItem( i18n("Wednesday") );
239 mByPosWeekdayCombo->insertItem( i18n("Thursday") );
240 mByPosWeekdayCombo->insertItem( i18n("Friday") );
241 mByPosWeekdayCombo->insertItem( i18n("Saturday") );
242 mByPosWeekdayCombo->insertItem( i18n("Sunday") );
243 buttonLayout->addWidget( mByPosWeekdayCombo, 1, 2 );
244}
245
246void RecurMonthly::setByDay( int day )
247{
248 mByDayRadio->setChecked( true );
249 mByDayCombo->setCurrentItem( day );
250}
251
252void RecurMonthly::setByPos( int count, int weekday )
253{
254 mByPosRadio->setChecked( true );
255 mByPosCountCombo->setCurrentItem( count );
256 mByPosWeekdayCombo->setCurrentItem( weekday );
257}
258
259bool RecurMonthly::byDay()
260{
261 return mByDayRadio->isChecked();
262}
263
264bool RecurMonthly::byPos()
265{
266 return mByPosRadio->isChecked();
267}
268
269int RecurMonthly::day()
270{
271 return mByDayCombo->currentItem() + 1;
272}
273
274int RecurMonthly::count()
275{
276 return mByPosCountCombo->currentItem() + 1;
277}
278
279int RecurMonthly::weekday()
280{
281 return mByPosWeekdayCombo->currentItem();
282}
283
284/////////////////////////// RecurYearly ///////////////////////////////
285
286RecurYearly::RecurYearly( QWidget *parent, const char *name ) :
287 RecurBase( parent, name )
288{
289 QBoxLayout *topLayout = new QVBoxLayout( this );
290 topLayout->setSpacing( KDialog::spacingHint() );
291
292
293 QBoxLayout *freqLayout = new QHBoxLayout( topLayout );
294
295 QLabel *preLabel = new QLabel( i18n("every"), this );
296 freqLayout->addWidget( preLabel );
297
298 freqLayout->addWidget( frequencyEdit() );
299
300 QLabel *postLabel = new QLabel( i18n("year(s)"), this );
301 freqLayout->addWidget( postLabel );
302
303
304 QButtonGroup *buttonGroup = new QButtonGroup( this );
305 buttonGroup->setFrameStyle( QFrame::NoFrame );
306 topLayout->addWidget( buttonGroup, 1, AlignVCenter );
307
308 QGridLayout *buttonLayout = new QGridLayout( buttonGroup, 3, 2 );
309
310 QString recurInMonthText;
311 if ( !KOPrefs::instance()->mCompactDialogs ) {
312 recurInMonthText = i18n("Recur in the month of");
313 }
314
315 mByMonthRadio = new QRadioButton( recurInMonthText, buttonGroup);
316 buttonLayout->addWidget( mByMonthRadio, 0, 0 );
317
318 mByMonthCombo = new QComboBox( buttonGroup );
319 mByMonthCombo->insertItem( i18n("January") );
320 mByMonthCombo->insertItem( i18n("February") );
321 mByMonthCombo->insertItem( i18n("March") );
322 mByMonthCombo->insertItem( i18n("April") );
323 mByMonthCombo->insertItem( i18n("May") );
324 mByMonthCombo->insertItem( i18n("June") );
325 mByMonthCombo->insertItem( i18n("July") );
326 mByMonthCombo->insertItem( i18n("August") );
327 mByMonthCombo->insertItem( i18n("September") );
328 mByMonthCombo->insertItem( i18n("October") );
329 mByMonthCombo->insertItem( i18n("November") );
330 mByMonthCombo->insertItem( i18n("December") );
331 buttonLayout->addWidget( mByMonthCombo, 0, 1 );
332
333 mByMonthCombo->setSizeLimit( 6 );
334
335 buttonLayout->setRowStretch( 1, 1 );
336
337 QString recurOnDayText;
338 if ( KOPrefs::instance()->mCompactDialogs ) {
339 recurOnDayText = i18n("This day");
340 } else {
341 recurOnDayText = i18n("Recur on this day");
342 }
343
344 mByDayRadio = new QRadioButton( recurOnDayText, buttonGroup);
345 buttonLayout->addMultiCellWidget( mByDayRadio, 2, 2, 0, 1 );
346}
347
348void RecurYearly::setByDay()
349{
350 mByDayRadio->setChecked( true );
351}
352
353void RecurYearly::setByMonth( int month )
354{
355 mByMonthRadio->setChecked( true );
356 mByMonthCombo->setCurrentItem( month - 1 );
357}
358
359bool RecurYearly::byMonth()
360{
361 return mByMonthRadio->isChecked();
362}
363
364bool RecurYearly::byDay()
365{
366 return mByDayRadio->isChecked();
367}
368
369int RecurYearly::month()
370{
371 return mByMonthCombo->currentItem() + 1;
372}
373
374//////////////////////////// ExceptionsWidget //////////////////////////
375
376ExceptionsWidget::ExceptionsWidget( QWidget *parent, const char *name ) :
377 QWidget( parent, name )
378{
379 QBoxLayout *topLayout = new QVBoxLayout( this );
380
381 QGroupBox *groupBox = new QGroupBox( 1, Horizontal, i18n("Exceptions"),
382 this );
383 topLayout->addWidget( groupBox );
384
385 QWidget *box = new QWidget( groupBox );
386
387 QGridLayout *boxLayout = new QGridLayout( box );
388
389 mExceptionDateEdit = new KDateEdit( box );
390 boxLayout->addWidget( mExceptionDateEdit, 0, 0 );
391
392 QPushButton *addExceptionButton = new QPushButton( i18n("Add"), box );
393 boxLayout->addWidget( addExceptionButton, 1, 0 );
394 QPushButton *changeExceptionButton = new QPushButton( i18n("Change"), box );
395 boxLayout->addWidget( changeExceptionButton, 2, 0 );
396 QPushButton *deleteExceptionButton = new QPushButton( i18n("Delete"), box );
397 boxLayout->addWidget( deleteExceptionButton, 3, 0 );
398
399 mExceptionList = new QListBox( box );
400 boxLayout->addMultiCellWidget( mExceptionList, 0, 3, 1, 1 );
401
402 boxLayout->setRowStretch( 4, 1 );
403 boxLayout->setColStretch( 1, 3 );
404
405 connect( addExceptionButton, SIGNAL( clicked() ),
406 SLOT( addException() ) );
407 connect( changeExceptionButton, SIGNAL( clicked() ),
408 SLOT( changeException() ) );
409 connect( deleteExceptionButton, SIGNAL( clicked() ),
410 SLOT( deleteException() ) );
411 if ( QApplication::desktop()->width() < 480 ) {
412 setMinimumWidth( 220 );
413 } else {
414 setMinimumWidth( 440 );
415 mExceptionDateEdit->setMinimumWidth( 200 );
416 }
417}
418
419void ExceptionsWidget::setDefaults( const QDateTime &from )
420{
421 mExceptionDateEdit->setDate( from.date() );
422}
423
424void ExceptionsWidget::addException()
425{
426 QDate date = mExceptionDateEdit->date();
427 QString dateStr = KGlobal::locale()->formatDate( date );
428 if( !mExceptionList->findItem( dateStr ) ) {
429 mExceptionDates.append( date );
430 mExceptionList->insertItem( dateStr );
431 }
432}
433
434void ExceptionsWidget::changeException()
435{
436 int pos = mExceptionList->currentItem();
437 if ( pos < 0 ) return;
438
439 QDate date = mExceptionDateEdit->date();
440 mExceptionDates[ pos ] = date;
441 mExceptionList->changeItem( KGlobal::locale()->formatDate( date ), pos );
442}
443
444void ExceptionsWidget::deleteException()
445{
446 int pos = mExceptionList->currentItem();
447 if ( pos < 0 ) return;
448
449 mExceptionDates.remove( mExceptionDates.at( pos ) );
450 mExceptionList->removeItem( pos );
451}
452
453void ExceptionsWidget::setDates( const DateList &dates )
454{
455 mExceptionList->clear();
456 mExceptionDates.clear();
457 DateList::ConstIterator dit;
458 for ( dit = dates.begin(); dit != dates.end(); ++dit ) {
459 mExceptionList->insertItem( KGlobal::locale()->formatDate(* dit ) );
460 mExceptionDates.append( *dit );
461 }
462}
463
464DateList ExceptionsWidget::dates()
465{
466 return mExceptionDates;
467}
468
469///////////////////////// ExceptionsDialog ///////////////////////////
470
471ExceptionsDialog::ExceptionsDialog( QWidget *parent, const char *name ) :
472 KDialogBase( parent, name, true, i18n("Edit exceptions"), Ok|Cancel )
473{
474 mExceptions = new ExceptionsWidget( this );
475 setMainWidget( mExceptions );
476 resize(220,10);
477}
478
479void ExceptionsDialog::setDefaults( const QDateTime &from )
480{
481 mExceptions->setDefaults( from );
482}
483
484void ExceptionsDialog::setDates( const DateList &dates )
485{
486 mExceptions->setDates( dates );
487}
488
489DateList ExceptionsDialog::dates()
490{
491 return mExceptions->dates();
492}
493
494///////////////////////// RecurrenceRangeWidget ///////////////////////////
495
496RecurrenceRangeWidget::RecurrenceRangeWidget( QWidget *parent,
497 const char *name )
498 : QWidget( parent, name )
499{
500 QBoxLayout *topLayout = new QVBoxLayout( this );
501
502 mRangeGroupBox = new QGroupBox( 1, Horizontal, i18n("Recurrence Range"),
503 this );
504 topLayout->addWidget( mRangeGroupBox );
505
506 QWidget *rangeBox = new QWidget( mRangeGroupBox );
507 QVBoxLayout *rangeLayout = new QVBoxLayout( rangeBox );
508 rangeLayout->setSpacing( KDialog::spacingHint() );
509
510 mStartDateLabel = new QLabel( i18n("Begin on:"), rangeBox );
511 rangeLayout->addWidget( mStartDateLabel );
512
513 QButtonGroup *rangeButtonGroup = new QButtonGroup;
514
515 mNoEndDateButton = new QRadioButton( i18n("No ending date"), rangeBox );
516 rangeButtonGroup->insert( mNoEndDateButton );
517 rangeLayout->addWidget( mNoEndDateButton );
518
519 QBoxLayout *durationLayout = new QHBoxLayout( rangeLayout );
520 durationLayout->setSpacing( KDialog::spacingHint() );
521
522 mEndDurationButton = new QRadioButton( i18n("End after"), rangeBox );
523 rangeButtonGroup->insert( mEndDurationButton );
524 durationLayout->addWidget( mEndDurationButton );
525
526 mEndDurationEdit = new QSpinBox( 1, 9999, 1, rangeBox );
527 durationLayout->addWidget( mEndDurationEdit );
528
529 QLabel *endDurationLabel = new QLabel( i18n("occurrence(s)"), rangeBox );
530 durationLayout ->addWidget( endDurationLabel );
531
532 QBoxLayout *endDateLayout = new QHBoxLayout( rangeLayout );
533 endDateLayout->setSpacing( KDialog::spacingHint() );
534
535 mEndDateButton = new QRadioButton( i18n("End by:"), rangeBox );
536 rangeButtonGroup->insert( mEndDateButton );
537 endDateLayout->addWidget( mEndDateButton );
538
539 mEndDateEdit = new KDateEdit( rangeBox );
540 endDateLayout->addWidget( mEndDateEdit );
541
542 endDateLayout->addStretch( 1 );
543
544 connect( mNoEndDateButton, SIGNAL( toggled( bool ) ),
545 SLOT( showCurrentRange() ) );
546 connect( mEndDurationButton, SIGNAL( toggled( bool ) ),
547 SLOT( showCurrentRange() ) );
548 connect( mEndDateButton, SIGNAL( toggled( bool ) ),
549 SLOT( showCurrentRange() ) );
550}
551
552void RecurrenceRangeWidget::setDefaults( const QDateTime &from )
553{
554 mNoEndDateButton->setChecked( true );
555
556 setDateTimes( from );
557 mEndDateEdit->setDate( from.date() );
558}
559
560void RecurrenceRangeWidget::setDuration( int duration )
561{
562 if ( duration == -1 ) {
563 mNoEndDateButton->setChecked( true );
564 } else if ( duration == 0 ) {
565 mEndDateButton->setChecked( true );
566 } else {
567 mEndDurationButton->setChecked( true );
568 mEndDurationEdit->setValue( duration );
569 }
570}
571
572int RecurrenceRangeWidget::duration()
573{
574 if ( mNoEndDateButton->isChecked() ) {
575 return -1;
576 } else if ( mEndDurationButton->isChecked() ) {
577 return mEndDurationEdit->value();
578 } else {
579 return 0;
580 }
581}
582
583void RecurrenceRangeWidget::setEndDate( const QDate &date )
584{
585 mEndDateEdit->setDate( date );
586}
587
588QDate RecurrenceRangeWidget::endDate()
589{
590 return mEndDateEdit->date();
591}
592
593void RecurrenceRangeWidget::showCurrentRange()
594{
595 mEndDurationEdit->setEnabled( mEndDurationButton->isChecked() );
596 mEndDateEdit->setEnabled( mEndDateButton->isChecked() );
597}
598
599void RecurrenceRangeWidget::setDateTimes( const QDateTime &start,
600 const QDateTime & )
601{
602 mStartDateLabel->setText( i18n("Start date: %1")
603 .arg( KGlobal::locale()->formatDate( start.date() ) ) );
604
605 if(!mEndDateButton->isChecked())
606 mEndDateEdit->setDate( start.date() );
607}
608
609///////////////////////// RecurrenceRangeDialog ///////////////////////////
610
611RecurrenceRangeDialog::RecurrenceRangeDialog( QWidget *parent,
612 const char *name ) :
613 KDialogBase( parent, name, true, i18n("Edit Recurrence Range"), Ok|Cancel )
614{
615 mRecurrenceRangeWidget = new RecurrenceRangeWidget( this );
616 setMainWidget( mRecurrenceRangeWidget );
617}
618
619void RecurrenceRangeDialog::setDefaults( const QDateTime &from )
620{
621 mRecurrenceRangeWidget->setDefaults( from );
622}
623
624void RecurrenceRangeDialog::setDuration( int duration )
625{
626 mRecurrenceRangeWidget->setDuration( duration );
627}
628
629int RecurrenceRangeDialog::duration()
630{
631 return mRecurrenceRangeWidget->duration();
632}
633
634void RecurrenceRangeDialog::setEndDate( const QDate &date )
635{
636 mRecurrenceRangeWidget->setEndDate( date );
637}
638
639QDate RecurrenceRangeDialog::endDate()
640{
641 return mRecurrenceRangeWidget->endDate();
642}
643
644void RecurrenceRangeDialog::setDateTimes( const QDateTime &start,
645 const QDateTime &end )
646{
647 mRecurrenceRangeWidget->setDateTimes( start, end );
648}
649
650//////////////////////////// RecurrenceChooser ////////////////////////
651
652RecurrenceChooser::RecurrenceChooser( QWidget *parent, const char *name ) :
653 QWidget( parent, name )
654{
655 QBoxLayout *topLayout = new QVBoxLayout( this );
656
657 if ( KOPrefs::instance()->mCompactDialogs ) {
658 mTypeCombo = new QComboBox( this );
659 mTypeCombo->insertItem( i18n("Daily") );
660 mTypeCombo->insertItem( i18n("Weekly") );
661 mTypeCombo->insertItem( i18n("Monthly") );
662 mTypeCombo->insertItem( i18n("Yearly") );
663
664 topLayout->addWidget( mTypeCombo );
665
666 connect( mTypeCombo, SIGNAL( activated( int ) ), SLOT( emitChoice() ) );
667 } else {
668 mTypeCombo = 0;
669
670 QButtonGroup *ruleButtonGroup = new QButtonGroup( 1, Horizontal, this );
671 ruleButtonGroup->setFrameStyle( QFrame::NoFrame );
672 topLayout->addWidget( ruleButtonGroup );
673
674 mDailyButton = new QRadioButton( i18n("Daily"), ruleButtonGroup );
675 mWeeklyButton = new QRadioButton( i18n("Weekly"), ruleButtonGroup );
676 mMonthlyButton = new QRadioButton( i18n("Monthly"), ruleButtonGroup );
677 mYearlyButton = new QRadioButton( i18n("Yearly"), ruleButtonGroup );
678
679 connect( mDailyButton, SIGNAL( toggled( bool ) ),
680 SLOT( emitChoice() ) );
681 connect( mWeeklyButton, SIGNAL( toggled( bool ) ),
682 SLOT( emitChoice() ) );
683 connect( mMonthlyButton, SIGNAL( toggled( bool ) ),
684 SLOT( emitChoice() ) );
685 connect( mYearlyButton, SIGNAL( toggled( bool ) ),
686 SLOT( emitChoice() ) );
687 }
688}
689
690int RecurrenceChooser::type()
691{
692 if ( mTypeCombo ) {
693 return mTypeCombo->currentItem();
694 } else {
695 if ( mDailyButton->isChecked() ) return Daily;
696 else if ( mWeeklyButton->isChecked() ) return Weekly;
697 else if ( mMonthlyButton->isChecked() ) return Monthly;
698 else return Yearly;
699 }
700}
701
702void RecurrenceChooser::setType( int type )
703{
704 if ( mTypeCombo ) {
705 mTypeCombo->setCurrentItem( type );
706 } else {
707 switch ( type ) {
708 case Daily:
709 mDailyButton->setChecked( true );
710 break;
711 case Weekly:
712 mWeeklyButton->setChecked( true );
713 break;
714 case Monthly:
715 mMonthlyButton->setChecked( true );
716 break;
717 case Yearly:
718 default:
719 mYearlyButton->setChecked( true );
720 break;
721 }
722 }
723}
724
725void RecurrenceChooser::emitChoice()
726{
727 emit chosen ( type() );
728}
729
730/////////////////////////////// Main Widget /////////////////////////////
731
732KOEditorRecurrence::KOEditorRecurrence( QWidget* parent, const char *name ) :
733 QWidget( parent, name )
734{
735 QGridLayout *topLayout = new QGridLayout( this, 2,2 );
736 topLayout->setSpacing( KDialog::spacingHint() );
737
738 mEnabledCheck = new QCheckBox( i18n("Enable Recurrence"), this );
739 connect( mEnabledCheck, SIGNAL( toggled( bool ) ),
740 SLOT( setEnabled( bool ) ) );
741 topLayout->addMultiCellWidget( mEnabledCheck, 0, 0, 0, 1 );
742
743
744 mTimeGroupBox = new QGroupBox( 1, Horizontal, i18n("Appointment Time "),
745 this );
746 topLayout->addMultiCellWidget( mTimeGroupBox, 1, 1 , 0 , 1 );
747
748 if ( KOPrefs::instance()->mCompactDialogs ) {
749 mTimeGroupBox->hide();
750 }
751
752// QFrame *timeFrame = new QFrame( mTimeGroupBox );
753// QBoxLayout *layoutTimeFrame = new QHBoxLayout( timeFrame );
754// layoutTimeFrame->setSpacing( KDialog::spacingHint() );
755
756 mDateTimeLabel = new QLabel( mTimeGroupBox );
757// mDateTimeLabel = new QLabel( timeFrame );
758// layoutTimeFrame->addWidget( mDateTimeLabel );
759
760 Qt::Orientation orientation;
761 if ( KOPrefs::instance()->mCompactDialogs ) orientation = Horizontal;
762 else orientation = Vertical;
763
764 mRuleBox = new QGroupBox( 1, orientation, i18n("Recurrence Rule"), this );
765 if ( KOPrefs::instance()->mCompactDialogs ) {
766 topLayout->addMultiCellWidget( mRuleBox, 2, 2, 0, 1 );
767 } else {
768 topLayout->addMultiCellWidget( mRuleBox, 2, 2, 0, 1 );
769 }
770
771 mRecurrenceChooser = new RecurrenceChooser( mRuleBox );
772 connect( mRecurrenceChooser, SIGNAL( chosen( int ) ),
773 SLOT( showCurrentRule( int ) ) );
774
775 if ( !KOPrefs::instance()->mCompactDialogs ) {
776 QFrame *ruleSepFrame = new QFrame( mRuleBox );
777 ruleSepFrame->setFrameStyle( QFrame::VLine | QFrame::Sunken );
778 }
779
780 mRuleStack = new QWidgetStack( mRuleBox );
781
782 mDaily = new RecurDaily( mRuleStack );
783 mRuleStack->addWidget( mDaily, 0 );
784
785 mWeekly = new RecurWeekly( mRuleStack );
786 mRuleStack->addWidget( mWeekly, 0 );
787
788 mMonthly = new RecurMonthly( mRuleStack );
789 mRuleStack->addWidget( mMonthly, 0 );
790
791 mYearly = new RecurYearly( mRuleStack );
792 mRuleStack->addWidget( mYearly, 0 );
793
794 showCurrentRule( mRecurrenceChooser->type() );
795
796 if ( KOPrefs::instance()->mCompactDialogs ) {
797 mRecurrenceRangeWidget = 0;
798 mRecurrenceRangeDialog = new RecurrenceRangeDialog( this );
799 mRecurrenceRange = mRecurrenceRangeDialog;
800 mRecurrenceRangeButton = new QPushButton( i18n("Recurrence Range..."),
801 this );
802
803 connect( mRecurrenceRangeButton, SIGNAL( clicked() ),
804 SLOT( showRecurrenceRangeDialog() ) );
805
806 mExceptionsWidget = 0;
807 mExceptionsDialog = new ExceptionsDialog( this );
808 mExceptions = mExceptionsDialog;
809 mExceptionsButton = new QPushButton( i18n("Exceptions..."), this );
810 if ( QApplication::desktop()->width() < 320 ) {
811 topLayout->addMultiCellWidget( mRecurrenceRangeButton, 3, 3, 0, 1 );
812 topLayout->addMultiCellWidget( mExceptionsButton, 4, 4, 0, 1 );
813 } else {
814 topLayout->addWidget( mRecurrenceRangeButton, 3, 0 );
815 topLayout->addWidget( mExceptionsButton, 3, 1 );
816 }
817 connect( mExceptionsButton, SIGNAL( clicked() ),
818 SLOT( showExceptionsDialog() ) );
819
820 } else {
821 mRecurrenceRangeWidget = new RecurrenceRangeWidget( this );
822 mRecurrenceRangeDialog = 0;
823 mRecurrenceRange = mRecurrenceRangeWidget;
824 mRecurrenceRangeButton = 0;
825 topLayout->addWidget( mRecurrenceRangeWidget, 3, 0 );
826
827 mExceptionsWidget = new ExceptionsWidget( this );
828 mExceptionsDialog = 0;
829 mExceptions = mExceptionsWidget;
830 mExceptionsButton = 0;
831 topLayout->addWidget( mExceptionsWidget, 3, 1 );
832 }
833}
834
835KOEditorRecurrence::~KOEditorRecurrence()
836{
837}
838
839void KOEditorRecurrence::setEnabled( bool enabled )
840{
841// kdDebug() << "KOEditorRecurrence::setEnabled(): " << (enabled ? "on" : "off") << endl;
842
843 mTimeGroupBox->setEnabled( enabled );
844 if ( mRecurrenceRangeWidget ) mRecurrenceRangeWidget->setEnabled( enabled );
845 if ( mRecurrenceRangeButton ) mRecurrenceRangeButton->setEnabled( enabled );
846 if ( mExceptionsWidget ) mExceptionsWidget->setEnabled( enabled );
847 if ( mExceptionsButton ) mExceptionsButton->setEnabled( enabled );
848}
849
850void KOEditorRecurrence::showCurrentRule( int current )
851{
852 switch ( current ) {
853 case Daily:
854 mRuleStack->raiseWidget( mDaily );
855 break;
856 case Weekly:
857 mRuleStack->raiseWidget( mWeekly );
858 break;
859 case Monthly:
860 mRuleStack->raiseWidget( mMonthly );
861 break;
862 default:
863 case Yearly:
864 mRuleStack->raiseWidget( mYearly );
865 break;
866 }
867}
868
869void KOEditorRecurrence::setDateTimes( QDateTime start, QDateTime end )
870{
871// kdDebug() << "KOEditorRecurrence::setDateTimes" << endl;
872
873 mRecurrenceRange->setDateTimes( start, end );
874 mExceptions->setDefaults( end );
875
876}
877
878void KOEditorRecurrence::setDefaults( QDateTime from, QDateTime to, bool )
879{
880
881 // qDebug("KOEditorRecurrence::setDefaults %s %s ",from.toString().latin1(),to.toString().latin1() );
882 setDateTimes( from, to );
883
884 bool enabled = false;
885 mEnabledCheck->setChecked( enabled );
886 setEnabled( enabled );
887
888 mExceptions->setDefaults( to );
889 mRecurrenceRange->setDefaults( to );
890
891 mRecurrenceChooser->setType( RecurrenceChooser::Weekly );
892 showCurrentRule( mRecurrenceChooser->type() );
893
894 mDaily->setFrequency( 1 );
895
896 mWeekly->setFrequency( 1 );
897 QBitArray days( 7 );
898 days.fill( 0 );
899 mWeekly->setDays( days );
900
901 mMonthly->setFrequency( 1 );
902 mMonthly->setByDay( from.date().day()-1 );
903
904 mYearly->setFrequency( 1 );
905 mYearly->setByDay();
906}
907
908void KOEditorRecurrence::readEvent(Event *event)
909{
910 QBitArray rDays( 7 );
911 QPtrList<Recurrence::rMonthPos> rmp;
912 QPtrList<int> rmd;
913 int day = 0;
914 int count = 0;
915 int month = 0;
916 setDateTimes( event->dtStart(), event->dtEnd() );
917
918 Recurrence *r = event->recurrence();
919 int f = r->frequency();
920
921 int recurs = r->doesRecur();
922
923 mEnabledCheck->setChecked( recurs );
924 setEnabled( recurs );
925
926 int recurrenceType = RecurrenceChooser::Weekly;
927
928 switch ( recurs ) {
929 case Recurrence::rNone:
930 setDefaults( event->dtStart(), event->dtEnd(), true );
931 break;
932 case Recurrence::rDaily:
933 recurrenceType = RecurrenceChooser::Daily;
934 mDaily->setFrequency( f );
935 break;
936 case Recurrence::rWeekly:
937 recurrenceType = RecurrenceChooser::Weekly;
938 mWeekly->setFrequency( f );
939 mWeekly->setDays( r->days() );
940 break;
941 case Recurrence::rMonthlyPos:
942 // we only handle one possibility in the list right now,
943 // so I have hardcoded calls with first(). If we make the GUI
944 // more extended, this can be changed.
945 recurrenceType = RecurrenceChooser::Monthly;
946
947 rmp = r->monthPositions();
948 if ( rmp.first()->negative )
949 count = 5 - rmp.first()->rPos - 1;
950 else
951 count = rmp.first()->rPos - 1;
952 day = 0;
953 while ( !rmp.first()->rDays.testBit( day ) ) ++day;
954 mMonthly->setByPos( count, day );
955
956 mMonthly->setFrequency( f );
957
958 break;
959 case Recurrence::rMonthlyDay:
960 recurrenceType = RecurrenceChooser::Monthly;
961
962 rmd = r->monthDays();
963 day = *rmd.first() - 1;
964 mMonthly->setByDay( day );
965
966 mMonthly->setFrequency( f );
967
968 break;
969 case Recurrence::rYearlyMonth:
970 case Recurrence::rYearlyDay:
971 recurrenceType = RecurrenceChooser::Yearly;
972
973 rmd = r->yearNums();
974 month = *rmd.first();
975 if ( month == event->dtStart().date().month() ) {
976 mYearly->setByDay();
977 } else {
978 mYearly->setByMonth( month );
979 }
980
981 mYearly->setFrequency( f );
982 break;
983 default:
984 setDefaults( event->dtStart(), event->dtEnd(), true );
985 break;
986 }
987
988 mRecurrenceChooser->setType( recurrenceType );
989 showCurrentRule( recurrenceType );
990
991 mRecurrenceRange->setDateTimes( event->dtStart() );
992
993 if ( r->doesRecur() ) {
994 mRecurrenceRange->setDuration( r->duration() );
995 if ( r->duration() == 0 )
996 {
997 if ( r->endDate() < event->dtStart().date() )
998 mRecurrenceRange->setEndDate( event->dtStart().date() );
999 else
1000 mRecurrenceRange->setEndDate( r->endDate() );
1001 } else
1002 mRecurrenceRange->setEndDate( event->dtStart().date() );
1003 }
1004
1005 mExceptions->setDates( event->exDates() );
1006}
1007
1008void KOEditorRecurrence::writeEvent( Event *event )
1009{
1010 Recurrence *r = event->recurrence();
1011
1012 // clear out any old settings;
1013 r->unsetRecurs();
1014
1015 if ( mEnabledCheck->isChecked() ) {
1016 int duration = mRecurrenceRange->duration();
1017 QDate endDate;
1018 if ( duration == 0 ) endDate = mRecurrenceRange->endDate();
1019
1020 int recurrenceType = mRecurrenceChooser->type();
1021
1022 if ( recurrenceType == RecurrenceChooser::Daily ) {
1023 int freq = mDaily->frequency();
1024 if ( duration != 0 ) r->setDaily( freq, duration );
1025 else r->setDaily( freq, endDate );
1026 } else if ( recurrenceType == RecurrenceChooser::Weekly ) {
1027 int freq = mWeekly->frequency();
1028 QBitArray days = mWeekly->days();
1029 int j;
1030 bool found = false;
1031 for (j = 0; j < 7 ; ++j ) {
1032 found |=days.at(j);
1033 }
1034 if ( !found ) {
1035 days.setBit( event->dtStart().date().dayOfWeek()-1);
1036 qDebug("bit set %d ");
1037 }
1038 if ( duration != 0 ) r->setWeekly( freq, days, duration );
1039 else r->setWeekly( freq, days, endDate );
1040 } else if ( recurrenceType == RecurrenceChooser::Monthly ) {
1041 int freq = mMonthly->frequency();
1042 if ( mMonthly->byPos() ) {
1043 int pos = mMonthly->count();
1044
1045 QBitArray days( 7 );
1046 days.fill( false );
1047
1048 days.setBit( mMonthly->weekday() );
1049 if ( duration != 0 )
1050 r->setMonthly( Recurrence::rMonthlyPos, freq, duration );
1051 else
1052 r->setMonthly( Recurrence::rMonthlyPos, freq, endDate );
1053 r->addMonthlyPos( pos, days );
1054 } else {
1055 // it's by day
1056 int day = mMonthly->day();
1057
1058 if ( duration != 0 ) {
1059 r->setMonthly( Recurrence::rMonthlyDay, freq, duration );
1060 } else {
1061 r->setMonthly( Recurrence::rMonthlyDay, freq, endDate );
1062 }
1063 r->addMonthlyDay( day );
1064 }
1065 } else if ( recurrenceType == RecurrenceChooser::Yearly ) {
1066 int freq = mYearly->frequency();
1067
1068 int month;
1069 if ( mYearly->byMonth() ) {
1070 month = mYearly->month();
1071 } else {
1072 month = event->dtStart().date().month();
1073 }
1074 if ( duration != 0 ) {
1075 r->setYearly( Recurrence::rYearlyMonth, freq, duration );
1076 } else {
1077 r->setYearly( Recurrence::rYearlyMonth, freq, endDate );
1078 }
1079
1080 r->addYearlyNum( month );
1081 }
1082
1083 event->setExDates( mExceptions->dates() );
1084 }
1085}
1086
1087void KOEditorRecurrence::setDateTimeStr( const QString &str )
1088{
1089 mDateTimeLabel->setText( str );
1090}
1091
1092bool KOEditorRecurrence::validateInput()
1093{
1094 // Check input here
1095
1096 return true;
1097}
1098
1099void KOEditorRecurrence::showExceptionsDialog()
1100{
1101 DateList dates = mExceptions->dates();
1102 int result = mExceptionsDialog->exec();
1103 if ( result == QDialog::Rejected ) mExceptions->setDates( dates );
1104}
1105
1106void KOEditorRecurrence::showRecurrenceRangeDialog()
1107{
1108 int duration = mRecurrenceRange->duration();
1109 QDate endDate = mRecurrenceRange->endDate();
1110
1111 int result = mRecurrenceRangeDialog->exec();
1112 if ( result == QDialog::Rejected ) {
1113 mRecurrenceRange->setDuration( duration );
1114 mRecurrenceRange->setEndDate( endDate );
1115 }
1116
1117}