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 
63 RecurBase::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 
70 TQWidget *RecurBase::frequencyEdit()
71 {
72  return mFrequencyEdit;
73 }
74 
75 void RecurBase::setFrequency( int f )
76 {
77  if ( f < 1 ) f = 1;
78 
79  mFrequencyEdit->setValue( f );
80 }
81 
82 int RecurBase::frequency()
83 {
84  return mFrequencyEdit->value();
85 }
86 
87 TQComboBox *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 
108 TQComboBox *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 
122 TQComboBox *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 
138 TQBoxLayout *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 
161 RecurDaily::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 
173 RecurWeekly::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 
206 void RecurWeekly::setDays( const TQBitArray &days )
207 {
208  for ( int i = 0; i < 7; ++i ) {
209  mDayBoxes[ i ]->setChecked( days.testBit( i ) );
210  }
211 }
212 
213 TQBitArray 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 
226 RecurMonthly::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 
343 void 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 
354 void 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 
365 bool RecurMonthly::byDay()
366 {
367  return mByDayRadio->isChecked();
368 }
369 
370 bool RecurMonthly::byPos()
371 {
372  return mByPosRadio->isChecked();
373 }
374 
375 int RecurMonthly::day()
376 {
377  int day = mByDayCombo->currentItem();
378  if ( day >= 31 ) day = 31-day-1;
379  else ++day;
380  return day;
381 }
382 
383 int 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 
392 int RecurMonthly::weekday()
393 {
394  return mByPosWeekdayCombo->currentItem() + 1;
395 }
396 
398 
399 RecurYearly::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 
508 void RecurYearly::setByDay( int day )
509 {
510  mByDayRadio->setChecked( true );
511  mByDaySpin->setValue( day );
512 }
513 
514 void 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 
525 void RecurYearly::setByMonth( int day, int month )
526 {
527  mByMonthRadio->setChecked( true );
528  mByMonthSpin->setValue( day );
529  mByMonthCombo->setCurrentItem( month - 1 );
530 }
531 
532 RecurYearly::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 
540 int RecurYearly::monthDay()
541 {
542  return mByMonthSpin->value();
543 }
544 
545 int RecurYearly::month()
546 {
547  return mByMonthCombo->currentItem() + 1;
548 }
549 
550 int 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 
559 int RecurYearly::posWeekday()
560 {
561  return mByPosWeekdayCombo->currentItem() + 1;
562 }
563 
564 int RecurYearly::posMonth()
565 {
566  return mByPosMonthCombo->currentItem() + 1;
567 }
568 
569 int RecurYearly::day()
570 {
571  return mByDaySpin->value();
572 }
573 
575 
576 ExceptionsWidget::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 
631 void 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 
641 void 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 
651 void 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 
660 void 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 
671 DateList ExceptionsWidget::dates()
672 {
673  return mExceptionDates;
674 }
675 
677 
678 ExceptionsDialog::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 
685 void ExceptionsDialog::setDates( const DateList &dates )
686 {
687  mExceptions->setDates( dates );
688 }
689 
690 DateList ExceptionsDialog::dates()
691 {
692  return mExceptions->dates();
693 }
694 
696 
697 RecurrenceRangeWidget::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 
776 void RecurrenceRangeWidget::setDefaults( const TQDateTime &from )
777 {
778  mNoEndDateButton->setChecked( true );
779 
780  setDateTimes( from );
781  setEndDate( from.date() );
782 }
783 
784 void 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 
796 int 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 
807 void RecurrenceRangeWidget::setEndDate( const TQDate &date )
808 {
809  mEndDateEdit->setDate( date );
810 }
811 
812 TQDate RecurrenceRangeWidget::endDate()
813 {
814  return mEndDateEdit->date();
815 }
816 
817 void RecurrenceRangeWidget::showCurrentRange()
818 {
819  mEndDurationEdit->setEnabled( mEndDurationButton->isChecked() );
820  mEndDateEdit->setEnabled( mEndDateButton->isChecked() );
821 }
822 
823 void 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 
832 RecurrenceRangeDialog::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 
840 void RecurrenceRangeDialog::setDefaults( const TQDateTime &from )
841 {
842  mRecurrenceRangeWidget->setDefaults( from );
843 }
844 
845 void RecurrenceRangeDialog::setDuration( int duration )
846 {
847  mRecurrenceRangeWidget->setDuration( duration );
848 }
849 
850 int RecurrenceRangeDialog::duration()
851 {
852  return mRecurrenceRangeWidget->duration();
853 }
854 
855 void RecurrenceRangeDialog::setEndDate( const TQDate &date )
856 {
857  mRecurrenceRangeWidget->setEndDate( date );
858 }
859 
860 TQDate RecurrenceRangeDialog::endDate()
861 {
862  return mRecurrenceRangeWidget->endDate();
863 }
864 
865 void RecurrenceRangeDialog::setDateTimes( const TQDateTime &start,
866  const TQDateTime &end )
867 {
868  mRecurrenceRangeWidget->setDateTimes( start, end );
869 }
870 
872 
873 RecurrenceChooser::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 
926 int 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 
938 void 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 
961 void RecurrenceChooser::emitChoice()
962 {
963  emit chosen ( type() );
964 }
965 
967 
968 KOEditorRecurrence::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 
1082 KOEditorRecurrence::~KOEditorRecurrence()
1083 {
1084 }
1085 
1086 void 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 
1099 void 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 
1118 void 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 
1151 void 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 
1181 void 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 
1319 void 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 
1384 void KOEditorRecurrence::setDateTimeStr( const TQString &str )
1385 {
1386  mDateTimeLabel->setText( str );
1387 }
1388 
1389 bool 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 
1418 void KOEditorRecurrence::showExceptionsDialog()
1419 {
1420  DateList dates = mExceptions->dates();
1421  int result = mExceptionsDialog->exec();
1422  if ( result == TQDialog::Rejected ) mExceptions->setDates( dates );
1423 }
1424 
1425 void 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 
1437 bool KOEditorRecurrence::doesRecur()
1438 {
1439  return mEnabledCheck->isChecked();
1440 }
1441 
1442 void 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 
1503 void 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 
1636 KOEditorRecurrenceDialog::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 
1643 void 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 
1651 void 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