• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdepim
  • Sitemap
  • Contact Us
 

korganizer

koeditorrecurrence.cpp

Go to the documentation of this file.
00001 /*
00002   This file is part of KOrganizer.
00003   Copyright (c) 2000-2003 Cornelius Schumacher <schumacher@kde.org>
00004   Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00005 
00006   This program is free software; you can redistribute it and/or modify
00007   it under the terms of the GNU General Public License as published by
00008   the Free Software Foundation; either version 2 of the License, or
00009   (at your option) any later version.
00010 
00011   This program is distributed in the hope that it will be useful,
00012   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014   GNU General Public License for more details.
00015 
00016   You should have received a copy of the GNU General Public License along
00017   with this program; if not, write to the Free Software Foundation, Inc.,
00018   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019 
00020   As a special exception, permission is given to link this program
00021   with any edition of Qt, and distribute the resulting executable,
00022   without including the source code for Qt in the source distribution.
00023 */
00024 
00025 #include "koeditorrecurrence.h"
00026 #include "koprefs.h"
00027 #include "koglobals.h"
00028 
00029 #include <libkdepim/kdateedit.h>
00030 
00031 #include <kcal/todo.h>
00032 
00033 #include <KComboBox>
00034 #include <kdialog.h>
00035 #include <kglobal.h>
00036 #include <klocale.h>
00037 #include <kiconloader.h>
00038 #include <knumvalidator.h>
00039 #include <kcalendarsystem.h>
00040 #include <kmessagebox.h>
00041 #include <kvbox.h>
00042 
00043 #include <QLayout>
00044 #include <QGroupBox>
00045 #include <QStackedWidget>
00046 #include <QDateTime>
00047 #include <QListWidget>
00048 #include <QSpinBox>
00049 #include <QCheckBox>
00050 #include <QRadioButton>
00051 #include <QLabel>
00052 #include <QPushButton>
00053 #include <QGridLayout>
00054 #include <QFrame>
00055 #include <QHBoxLayout>
00056 #include <QBoxLayout>
00057 #include <QVBoxLayout>
00058 #include <QButtonGroup>
00059 
00060 #include "koeditorrecurrence.moc"
00061 
00063 
00064 RecurBase::RecurBase( QWidget *parent ) : QWidget( parent )
00065 {
00066   mFrequencyEdit = new QSpinBox( this );
00067   mFrequencyEdit->setRange( 1, 9999 );
00068   mFrequencyEdit->setValue( 1 );
00069 }
00070 
00071 QWidget *RecurBase::frequencyEdit()
00072 {
00073   return mFrequencyEdit;
00074 }
00075 
00076 void RecurBase::setFrequency( int f )
00077 {
00078   if ( f < 1 ) {
00079     f = 1;
00080   }
00081 
00082   mFrequencyEdit->setValue( f );
00083 }
00084 
00085 int RecurBase::frequency()
00086 {
00087   return mFrequencyEdit->value();
00088 }
00089 
00090 KComboBox *RecurBase::createWeekCountCombo( QWidget *parent )
00091 {
00092   KComboBox *combo = new KComboBox( parent );
00093   if ( !combo ) {
00094     return 0;
00095   }
00096 
00097   combo->setWhatsThis( i18nc( "@info:whatsthis",
00098                               "The number of the week from the beginning "
00099                               "of the month on which this event or to-do "
00100                               "should recur." ) );
00101   combo->addItem( i18nc( "@item:inlistbox", "1st" ) );
00102   combo->addItem( i18nc( "@item:inlistbox", "2nd" ) );
00103   combo->addItem( i18nc( "@item:inlistbox", "3rd" ) );
00104   combo->addItem( i18nc( "@item:inlistbox", "4th" ) );
00105   combo->addItem( i18nc( "@item:inlistbox", "5th" ) );
00106   combo->addItem( i18nc( "@item:inlistbox last week of the month", "Last" ) );
00107   combo->addItem( i18nc( "@item:inlistbox", "2nd Last" ) );
00108   combo->addItem( i18nc( "@item:inlistbox", "3rd Last" ) );
00109   combo->addItem( i18nc( "@item:inlistbox", "4th Last" ) );
00110   combo->addItem( i18nc( "@item:inlistbox", "5th Last" ) );
00111   return combo;
00112 }
00113 
00114 KComboBox *RecurBase::createWeekdayCombo( QWidget *parent )
00115 {
00116   KComboBox *combo = new KComboBox( parent );
00117   if ( !combo ) {
00118     return 0;
00119   }
00120 
00121   combo->setWhatsThis( i18nc( "@info:whatsthis",
00122                               "The weekday on which this event or to-do "
00123                               "should recur." ) );
00124   const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
00125   for ( int i=1; i <= 7; ++i ) {
00126     combo->addItem( calSys->weekDayName( i ) );
00127   }
00128   return combo;
00129 }
00130 
00131 KComboBox *RecurBase::createMonthNameCombo( QWidget *parent )
00132 {
00133   KComboBox *combo = new KComboBox( parent );
00134   combo->setWhatsThis( i18nc( "@info:whatsthis",
00135                               "The month during which this event or to-do "
00136                               "should recur." ) );
00137   const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
00138   for ( int i=1; i <= 12; ++i ) {
00139     // use an arbitrary year, we just need the month name...
00140     QDate dt( 2005, i, 1 );
00141     combo->addItem( calSys->monthName( dt ) );
00142   }
00143   return combo;
00144 }
00145 
00146 QBoxLayout *RecurBase::createFrequencySpinBar( QWidget *parent, QLayout *layout,
00147                                                const QString &everyText,
00148                                                const QString &unitText )
00149 {
00150   QBoxLayout *freqLayout = new QHBoxLayout();
00151   freqLayout->setSpacing( layout->spacing() );
00152   layout->addItem( freqLayout );
00153 
00154   QString whatsThis = i18nc( "@info:whatsthis",
00155                              "Sets how often this event or to-do should recur." );
00156   QLabel *preLabel = new QLabel( everyText, parent );
00157   preLabel->setWhatsThis( whatsThis );
00158   freqLayout->addWidget( preLabel );
00159 
00160   freqLayout->addWidget( frequencyEdit() );
00161   preLabel->setBuddy( frequencyEdit() );
00162   preLabel->buddy()->setWhatsThis( whatsThis );
00163 
00164   QLabel *postLabel = new QLabel( unitText, parent );
00165   postLabel->setWhatsThis( whatsThis );
00166   freqLayout->addWidget( postLabel );
00167   freqLayout->addStretch();
00168   return freqLayout;
00169 }
00170 
00172 
00173 RecurDaily::RecurDaily( QWidget *parent ) : RecurBase( parent )
00174 {
00175   QBoxLayout *topLayout = new QVBoxLayout( this );
00176   topLayout->setSpacing( KDialog::spacingHint() );
00177 
00178   createFrequencySpinBar( this, topLayout,
00179                           i18nc( "@label", "&Recur every" ),
00180                           i18nc( "@label recurrence expressed in days", "day(s)" ) );
00181 }
00182 
00184 
00185 RecurWeekly::RecurWeekly( QWidget *parent ) : RecurBase( parent )
00186 {
00187   QBoxLayout *topLayout = new QVBoxLayout( this );
00188   topLayout->setSpacing( KDialog::spacingHint() );
00189 
00190 //  topLayout->addStretch( 1 );
00191 
00192   createFrequencySpinBar( this, topLayout,
00193                           i18nc( "@label", "&Recur every" ), i18nc( "@label", "week(s) on:" ) );
00194 
00195   KHBox *dayBox = new KHBox( this );
00196   topLayout->addWidget( dayBox, 1, Qt::AlignVCenter );
00197   // Respect start of week setting
00198   int weekStart=KGlobal::locale()->weekStartDay();
00199   for ( int i = 0; i < 7; ++i ) {
00200     // i is the nr of the combobox, not the day of week!
00201     // label=(i+weekStart+6)%7 + 1;
00202     // index in CheckBox array(=day): label-1
00203     const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
00204     QString weekDayName = calSys->weekDayName( ( i + weekStart + 6 ) % 7 + 1,
00205                                                KCalendarSystem::ShortDayName );
00206     QString longDayName = calSys->weekDayName( ( i + weekStart + 6 ) % 7 + 1,
00207                                                KCalendarSystem::LongDayName );
00208     if ( KOPrefs::instance()->mCompactDialogs ) {
00209       weekDayName = weekDayName.left( 1 );
00210     }
00211     mDayBoxes[ ( i + weekStart + 6 ) % 7 ] = new QCheckBox( weekDayName, dayBox );
00212     mDayBoxes[ ( i + weekStart + 6 ) % 7 ]->setWhatsThis(
00213       i18nc( "@info:whatsthis",
00214              "Set %1 as the day when this event or to-do should recur.", longDayName ) );
00215 
00216     mDayBoxes[ ( i + weekStart + 6 ) % 7 ]->setToolTip(
00217       i18nc( "@info:tooltip", "Recur on %1", longDayName ) );
00218   }
00219 
00220   topLayout->addStretch( 1 );
00221 }
00222 
00223 void RecurWeekly::setDays( const QBitArray &days )
00224 {
00225   for ( int i = 0; i < 7; ++i ) {
00226     mDayBoxes[ i ]->setChecked( days.testBit( i ) );
00227   }
00228 }
00229 
00230 QBitArray RecurWeekly::days()
00231 {
00232   QBitArray days( 7 );
00233 
00234   for ( int i = 0; i < 7; ++i ) {
00235     days.setBit( i, mDayBoxes[ i ]->isChecked() );
00236   }
00237 
00238   return days;
00239 }
00240 
00242 
00243 RecurMonthly::RecurMonthly( QWidget *parent ) : RecurBase( parent )
00244 {
00245   QBoxLayout *topLayout = new QVBoxLayout( this );
00246   topLayout->setSpacing( KDialog::spacingHint() );
00247 
00248   createFrequencySpinBar( this, topLayout,
00249                           i18nc( "@label", "&Recur every" ), i18nc( "@label", "month(s)" ) );
00250 
00251   QFrame *buttonGroup = new QFrame( this );
00252   topLayout->addWidget( buttonGroup, 1, Qt::AlignVCenter );
00253 
00254   QGridLayout *buttonLayout = new QGridLayout( buttonGroup );
00255   buttonLayout->setSpacing( KDialog::spacingHint() );
00256 
00257   QString recurOnText;
00258   if ( !KOPrefs::instance()->mCompactDialogs ) {
00259     recurOnText = i18nc( "@option:radio", "&Recur on the" );
00260   }
00261 
00262   mByDayRadio = new QRadioButton( recurOnText, buttonGroup );
00263   mByDayRadio->setWhatsThis( i18nc( "@info:whatsthis",
00264                                     "Sets a specific day of the month on which "
00265                                     "this event or to-do should recur." ) );
00266 
00267   buttonLayout->addWidget( mByDayRadio, 0, 0 );
00268 
00269   QString whatsThis = i18nc( "@info:whatsthis",
00270                              "The day of the month on which this event "
00271                              "or to-do should recur." );
00272   mByDayCombo = new KComboBox( buttonGroup );
00273   mByDayCombo->setWhatsThis( whatsThis );
00274   mByDayCombo->setMaxVisibleItems( 7 );
00275   mByDayCombo->addItem( i18nc( "@item:inlistbox", "1st" ) );
00276   mByDayCombo->addItem( i18nc( "@item:inlistbox", "2nd" ) );
00277   mByDayCombo->addItem( i18nc( "@item:inlistbox", "3rd" ) );
00278   mByDayCombo->addItem( i18nc( "@item:inlistbox", "4th" ) );
00279   mByDayCombo->addItem( i18nc( "@item:inlistbox", "5th" ) );
00280   mByDayCombo->addItem( i18nc( "@item:inlistbox", "6th" ) );
00281   mByDayCombo->addItem( i18nc( "@item:inlistbox", "7th" ) );
00282   mByDayCombo->addItem( i18nc( "@item:inlistbox", "8th" ) );
00283   mByDayCombo->addItem( i18nc( "@item:inlistbox", "9th" ) );
00284   mByDayCombo->addItem( i18nc( "@item:inlistbox", "10th" ) );
00285   mByDayCombo->addItem( i18nc( "@item:inlistbox", "11th" ) );
00286   mByDayCombo->addItem( i18nc( "@item:inlistbox", "12th" ) );
00287   mByDayCombo->addItem( i18nc( "@item:inlistbox", "13th" ) );
00288   mByDayCombo->addItem( i18nc( "@item:inlistbox", "14th" ) );
00289   mByDayCombo->addItem( i18nc( "@item:inlistbox", "15th" ) );
00290   mByDayCombo->addItem( i18nc( "@item:inlistbox", "16th" ) );
00291   mByDayCombo->addItem( i18nc( "@item:inlistbox", "17th" ) );
00292   mByDayCombo->addItem( i18nc( "@item:inlistbox", "18th" ) );
00293   mByDayCombo->addItem( i18nc( "@item:inlistbox", "19th" ) );
00294   mByDayCombo->addItem( i18nc( "@item:inlistbox", "20th" ) );
00295   mByDayCombo->addItem( i18nc( "@item:inlistbox", "21st" ) );
00296   mByDayCombo->addItem( i18nc( "@item:inlistbox", "22nd" ) );
00297   mByDayCombo->addItem( i18nc( "@item:inlistbox", "23rd" ) );
00298   mByDayCombo->addItem( i18nc( "@item:inlistbox", "24th" ) );
00299   mByDayCombo->addItem( i18nc( "@item:inlistbox", "25th" ) );
00300   mByDayCombo->addItem( i18nc( "@item:inlistbox", "26th" ) );
00301   mByDayCombo->addItem( i18nc( "@item:inlistbox", "27th" ) );
00302   mByDayCombo->addItem( i18nc( "@item:inlistbox", "28th" ) );
00303   mByDayCombo->addItem( i18nc( "@item:inlistbox", "29th" ) );
00304   mByDayCombo->addItem( i18nc( "@item:inlistbox", "30th" ) );
00305   mByDayCombo->addItem( i18nc( "@item:inlistbox", "31st" ) );
00306   mByDayCombo->addItem( i18nc( "@item:inlistbox last day of the month", "Last" ) );
00307   mByDayCombo->addItem( i18nc( "@item:inlistbox", "2nd Last" ) );
00308   mByDayCombo->addItem( i18nc( "@item:inlistbox", "3rd Last" ) );
00309   mByDayCombo->addItem( i18nc( "@item:inlistbox", "4th Last" ) );
00310   mByDayCombo->addItem( i18nc( "@item:inlistbox", "5th Last" ) );
00311   mByDayCombo->addItem( i18nc( "@item:inlistbox", "6th Last" ) );
00312   mByDayCombo->addItem( i18nc( "@item:inlistbox", "7th Last" ) );
00313   mByDayCombo->addItem( i18nc( "@item:inlistbox", "8th Last" ) );
00314   mByDayCombo->addItem( i18nc( "@item:inlistbox", "9th Last" ) );
00315   mByDayCombo->addItem( i18nc( "@item:inlistbox", "10th Last" ) );
00316   mByDayCombo->addItem( i18nc( "@item:inlistbox", "11th Last" ) );
00317   mByDayCombo->addItem( i18nc( "@item:inlistbox", "12th Last" ) );
00318   mByDayCombo->addItem( i18nc( "@item:inlistbox", "13th Last" ) );
00319   mByDayCombo->addItem( i18nc( "@item:inlistbox", "14th Last" ) );
00320   mByDayCombo->addItem( i18nc( "@item:inlistbox", "15th Last" ) );
00321   mByDayCombo->addItem( i18nc( "@item:inlistbox", "16th Last" ) );
00322   mByDayCombo->addItem( i18nc( "@item:inlistbox", "17th Last" ) );
00323   mByDayCombo->addItem( i18nc( "@item:inlistbox", "18th Last" ) );
00324   mByDayCombo->addItem( i18nc( "@item:inlistbox", "19th Last" ) );
00325   mByDayCombo->addItem( i18nc( "@item:inlistbox", "20th Last" ) );
00326   mByDayCombo->addItem( i18nc( "@item:inlistbox", "21st Last" ) );
00327   mByDayCombo->addItem( i18nc( "@item:inlistbox", "22nd Last" ) );
00328   mByDayCombo->addItem( i18nc( "@item:inlistbox", "23rd Last" ) );
00329   mByDayCombo->addItem( i18nc( "@item:inlistbox", "24th Last" ) );
00330   mByDayCombo->addItem( i18nc( "@item:inlistbox", "25th Last" ) );
00331   mByDayCombo->addItem( i18nc( "@item:inlistbox", "26th Last" ) );
00332   mByDayCombo->addItem( i18nc( "@item:inlistbox", "27th Last" ) );
00333   mByDayCombo->addItem( i18nc( "@item:inlistbox", "28th Last" ) );
00334   mByDayCombo->addItem( i18nc( "@item:inlistbox", "29th Last" ) );
00335   mByDayCombo->addItem( i18nc( "@item:inlistbox", "30th Last" ) );
00336   mByDayCombo->addItem( i18nc( "@item:inlistbox", "31st Last" ) );
00337   buttonLayout->addWidget( mByDayCombo, 0, 1 );
00338 
00339   QLabel *byDayLabel = new QLabel( i18nc( "@label", "day" ), buttonGroup );
00340   byDayLabel->setWhatsThis( whatsThis );
00341   buttonLayout->addWidget( byDayLabel, 0, 2 );
00342 
00343   mByPosRadio = new QRadioButton( recurOnText, buttonGroup );
00344   mByPosRadio->setWhatsThis( i18nc( "@info:whatsthis",
00345                                     "Sets a weekday and specific week in the month "
00346                                     "on which this event or to-do should recur" ) );
00347   buttonLayout->addWidget( mByPosRadio, 1, 0 );
00348 
00349   mByPosCountCombo = createWeekCountCombo( buttonGroup );
00350   buttonLayout->addWidget( mByPosCountCombo, 1, 1 );
00351 
00352   mByPosWeekdayCombo = createWeekdayCombo( buttonGroup );
00353   buttonLayout->addWidget( mByPosWeekdayCombo, 1, 2 );
00354 
00355   topLayout->addStretch( 1 );
00356 }
00357 
00358 void RecurMonthly::setByDay( int day )
00359 {
00360   mByDayRadio->setChecked( true );
00361   // Days from the end are after the ones from the begin, so correct for the
00362   // negative sign and add 30 (index starting at 0)
00363   if ( day > 0 && day <= 31 ) {
00364     mByDayCombo->setCurrentIndex( day - 1 );
00365   } else if ( day < 0 ) {
00366     mByDayCombo->setCurrentIndex( 31 - 1 - day );
00367   }
00368 }
00369 
00370 void RecurMonthly::setByPos( int count, int weekday )
00371 {
00372   mByPosRadio->setChecked( true );
00373   if ( count > 0 ) {
00374     mByPosCountCombo->setCurrentIndex( count - 1 );
00375   } else {
00376     // negative weeks means counted from the end of month
00377     mByPosCountCombo->setCurrentIndex( -count + 4 );
00378   }
00379   mByPosWeekdayCombo->setCurrentIndex( weekday - 1 );
00380 }
00381 
00382 bool RecurMonthly::byDay()
00383 {
00384   return mByDayRadio->isChecked();
00385 }
00386 
00387 bool RecurMonthly::byPos()
00388 {
00389   return mByPosRadio->isChecked();
00390 }
00391 
00392 int RecurMonthly::day()
00393 {
00394   int day = mByDayCombo->currentIndex();
00395   if ( day >= 31 ) {
00396     day = 31-day-1;
00397   } else {
00398     ++day;
00399   }
00400   return day;
00401 }
00402 
00403 int RecurMonthly::count()
00404 {
00405   int pos = mByPosCountCombo->currentIndex();
00406   if ( pos <= 4 ) { // positive count
00407     return pos + 1;
00408   } else {
00409     return -pos + 4;
00410   }
00411 }
00412 
00413 int RecurMonthly::weekday()
00414 {
00415   return mByPosWeekdayCombo->currentIndex() + 1;
00416 }
00417 
00419 
00420 RecurYearly::RecurYearly( QWidget *parent ) : RecurBase( parent )
00421 {
00422   QBoxLayout *topLayout = new QVBoxLayout( this );
00423   topLayout->setSpacing( KDialog::spacingHint() );
00424 
00425   createFrequencySpinBar( this, topLayout,
00426                           i18nc( "@label", "&Recur every" ), i18nc( "@label", "year(s)" ) );
00427 
00428   QFrame *buttonGroup = new QFrame( this );
00429   topLayout->addWidget( buttonGroup, 1, Qt::AlignVCenter );
00430 
00431   QBoxLayout *buttonLayout = new QVBoxLayout( buttonGroup );
00432 
00433   /* YearlyMonth (day n of Month Y) */
00434   QBoxLayout *monthLayout = new QHBoxLayout();
00435   buttonLayout->addItem( monthLayout );
00436   QString recurInMonthText(
00437     i18nc( "@option:radio part before XXX of 'Recur on day XXX of month YYY'", "&Recur on day " ) );
00438   if ( KOPrefs::instance()->mCompactDialogs ) {
00439     recurInMonthText = i18nc( "@option:radio", "&Day " );
00440   }
00441   mByMonthRadio = new QRadioButton( recurInMonthText, buttonGroup );
00442   mByMonthRadio->setWhatsThis(
00443     i18nc( "@info:whatsthis",
00444            "Sets a specific day in a specific month "
00445            "on which this event or to-do should recur." ) );
00446   monthLayout->addWidget( mByMonthRadio );
00447   mByMonthSpin = new QSpinBox( buttonGroup );
00448   mByMonthSpin->setRange( 1, 31 );
00449   mByMonthSpin->setWhatsThis(
00450     i18nc( "@info:whatsthis",
00451            "The day of the month on which this event "
00452            "or to-do should recur." ) );
00453   monthLayout->addWidget( mByMonthSpin );
00454   QLabel *ofLabel =
00455     new QLabel(
00456       i18nc( "@label part between XXX and YYY of 'Recur on day XXX of month YYY'", " &of " ),
00457       buttonGroup );
00458   //What do I do here? I'm not sure if this label should have What's This in it... - Antonio
00459   monthLayout->addWidget( ofLabel );
00460 
00461   mByMonthCombo = createMonthNameCombo( buttonGroup );
00462   monthLayout->addWidget( mByMonthCombo );
00463   ofLabel->setBuddy( mByMonthCombo );
00464 
00465   monthLayout->addStretch( 1 );
00466 
00467   /* YearlyPos (weekday X of week N of month Y) */
00468   QBoxLayout *posLayout = new QHBoxLayout();
00469   buttonLayout->addItem( posLayout );
00470   QString recurOnPosText(
00471     i18nc( "@option:radio Part before XXX in 'Recur on NNN. WEEKDAY of MONTH', short version",
00472            "&On" ) );
00473   if ( !KOPrefs::instance()->mCompactDialogs ) {
00474     recurOnPosText =
00475       i18nc( "@option:radio Part before XXX in 'Recur on NNN. WEEKDAY of MONTH'",
00476              "&On the" );
00477   }
00478   mByPosRadio = new QRadioButton( recurOnPosText, buttonGroup );
00479   mByPosRadio->setWhatsThis(
00480     i18nc( "@info:whatsthis",
00481            "Sets a specific day in a specific week "
00482            "of a specific month on which this event "
00483            "or to-do should recur." ) );
00484   posLayout->addWidget( mByPosRadio );
00485 
00486   mByPosDayCombo = createWeekCountCombo( buttonGroup );
00487   posLayout->addWidget( mByPosDayCombo );
00488 
00489   mByPosWeekdayCombo = createWeekdayCombo( buttonGroup );
00490   posLayout->addWidget( mByPosWeekdayCombo );
00491 
00492   ofLabel =
00493     new QLabel(
00494       i18nc( "@label part between WEEKDAY and MONTH in 'Recur on NNN. WEEKDAY of MONTH'", " o&f " ),
00495       buttonGroup );
00496   posLayout->addWidget( ofLabel );
00497 
00498   mByPosMonthCombo  = createMonthNameCombo( buttonGroup );
00499   posLayout->addWidget( mByPosMonthCombo );
00500   ofLabel->setBuddy( mByPosMonthCombo );
00501 
00502   posLayout->addStretch( 1 );
00503 
00504   /* YearlyDay (day N of the year) */
00505   QBoxLayout *dayLayout = new QHBoxLayout();
00506   buttonLayout->addItem( dayLayout );
00507   QString recurOnDayText;
00508   if ( KOPrefs::instance()->mCompactDialogs ) {
00509     recurOnDayText = i18nc( "@option:radio", "Day #" );
00510   } else {
00511     recurOnDayText = i18nc( "@option:radio", "Recur on &day #" );
00512   }
00513   QString whatsThis = i18nc( "@info:whatsthis",
00514                              "Sets a specific day within the year on which "
00515                              "this event or to-do should recur." );
00516   mByDayRadio = new QRadioButton( recurOnDayText, buttonGroup );
00517   mByDayRadio->setWhatsThis( whatsThis );
00518   dayLayout->addWidget( mByDayRadio );
00519 
00520   mByDaySpin = new QSpinBox( buttonGroup );
00521   mByDaySpin->setRange( 1, 366 );
00522   mByDaySpin->setWhatsThis( whatsThis );
00523 
00524   dayLayout->addWidget( mByDaySpin );
00525 
00526   QString ofTheYear(
00527     i18nc( "@label part after NNN of 'Recur on day #NNN of the year'",
00528            " of the &year" ) );
00529   if ( KOPrefs::instance()->mCompactDialogs ) {
00530     ofTheYear =
00531       i18nc( "@label part after NNN of 'Recur on day #NNN of the year', short version",
00532              " of the year" );
00533   }
00534   ofLabel = new QLabel( ofTheYear, buttonGroup );
00535   ofLabel->setWhatsThis( whatsThis );
00536   dayLayout->addWidget( ofLabel );
00537   ofLabel->setBuddy( mByDaySpin );
00538 
00539   dayLayout->addStretch( 1 );
00540   topLayout->addStretch( 1 );
00541 }
00542 
00543 void RecurYearly::setByDay( int day )
00544 {
00545   mByDayRadio->setChecked( true );
00546   mByDaySpin->setValue( day );
00547 }
00548 
00549 void RecurYearly::setByPos( int count, int weekday, int month )
00550 {
00551   mByPosRadio->setChecked( true );
00552   if ( count > 0 ) {
00553     mByPosDayCombo->setCurrentIndex( count - 1 );
00554   } else {
00555     mByPosDayCombo->setCurrentIndex( -count + 4 );
00556   }
00557   mByPosWeekdayCombo->setCurrentIndex( weekday - 1 );
00558   mByPosMonthCombo->setCurrentIndex( month-1 );
00559 }
00560 
00561 void RecurYearly::setByMonth( int day, int month )
00562 {
00563   mByMonthRadio->setChecked( true );
00564   mByMonthSpin->setValue( day );
00565   mByMonthCombo->setCurrentIndex( month - 1 );
00566 }
00567 
00568 RecurYearly::YearlyType RecurYearly::getType()
00569 {
00570   if ( mByMonthRadio->isChecked() ) {
00571     return byMonth;
00572   }
00573   if ( mByPosRadio->isChecked() ) {
00574     return byPos;
00575   }
00576   if ( mByDayRadio->isChecked() ) {
00577     return byDay;
00578   }
00579   return byMonth;
00580 }
00581 
00582 int RecurYearly::monthDay()
00583 {
00584   return mByMonthSpin->value();
00585 }
00586 
00587 int RecurYearly::month()
00588 {
00589   return mByMonthCombo->currentIndex() + 1;
00590 }
00591 
00592 int RecurYearly::posCount()
00593 {
00594   int pos = mByPosDayCombo->currentIndex();
00595   if ( pos <= 4 ) { // positive count
00596     return pos + 1;
00597   } else {
00598     return -pos + 4;
00599   }
00600 }
00601 
00602 int RecurYearly::posWeekday()
00603 {
00604   return mByPosWeekdayCombo->currentIndex() + 1;
00605 }
00606 
00607 int RecurYearly::posMonth()
00608 {
00609   return mByPosMonthCombo->currentIndex() + 1;
00610 }
00611 
00612 int RecurYearly::day()
00613 {
00614   return mByDaySpin->value();
00615 }
00616 
00618 
00619 ExceptionsWidget::ExceptionsWidget( QWidget *parent ) : QWidget( parent )
00620 {
00621   QBoxLayout *topLayout = new QVBoxLayout( this );
00622   topLayout->setSpacing( 0 );
00623   topLayout->setMargin( 0 );
00624 
00625   QGroupBox *groupBox = new QGroupBox( i18nc( "@title:group", "E&xceptions" ), this );
00626   topLayout->addWidget( groupBox );
00627 
00628   QGridLayout *boxLayout = new QGridLayout( groupBox );
00629 
00630   mExceptionDateEdit = new KPIM::KDateEdit( groupBox );
00631   mExceptionDateEdit->setWhatsThis(
00632     i18nc( "@info:whatsthis",
00633            "A date that should be considered an exception "
00634            "to the recurrence rules for this event or to-do." ) );
00635   mExceptionDateEdit->setDate( QDate::currentDate() );
00636   boxLayout->addWidget( mExceptionDateEdit, 0, 0 );
00637 
00638   QPushButton *addExceptionButton =
00639     new QPushButton( i18nc( "@action:button", "&Add" ), groupBox );
00640   addExceptionButton->setWhatsThis(
00641     i18nc( "@info:whatsthis",
00642            "Add this date as an exception "
00643            "to the recurrence rules for this event or to-do." ) );
00644   boxLayout->addWidget( addExceptionButton, 1, 0 );
00645 
00646   QPushButton *changeExceptionButton =
00647     new QPushButton( i18nc( "@action:button", "&Change" ), groupBox );
00648   changeExceptionButton->setWhatsThis(
00649     i18nc( "@info:whatsthis",
00650            "Replace the currently selected date with this date." ) );
00651   boxLayout->addWidget( changeExceptionButton, 2, 0 );
00652 
00653   QPushButton *deleteExceptionButton =
00654     new QPushButton( i18nc( "@action:button", "&Delete" ), groupBox );
00655   deleteExceptionButton->setWhatsThis(
00656     i18nc( "@info:whatsthis",
00657            "Delete the currently selected date from the list of dates "
00658            "that should be considered exceptions to the recurrence rules "
00659            "for this event or to-do." ) );
00660   boxLayout->addWidget( deleteExceptionButton, 3, 0 );
00661 
00662   mExceptionList = new QListWidget( groupBox );
00663   mExceptionList->setWhatsThis(
00664     i18nc( "@info:whatsthis",
00665            "Displays current dates that are being considered "
00666            "exceptions to the recurrence rules for this event "
00667            "or to-do." ) );
00668   boxLayout->addWidget( mExceptionList, 0, 1, 4, 1 );
00669 
00670   boxLayout->setRowStretch( 4, 1 );
00671   boxLayout->setColumnStretch( 1, 3 );
00672 
00673   connect( addExceptionButton, SIGNAL(clicked()), SLOT(addException()) );
00674   connect( changeExceptionButton, SIGNAL(clicked()), SLOT(changeException()) );
00675   connect( deleteExceptionButton, SIGNAL(clicked()), SLOT(deleteException()) );
00676 }
00677 
00678 void ExceptionsWidget::addException()
00679 {
00680   QDate date = mExceptionDateEdit->date();
00681   QString dateStr = KGlobal::locale()->formatDate( date );
00682   if( mExceptionList->findItems( dateStr, Qt::MatchExactly ).isEmpty() ) {
00683     mExceptionDates.append( date );
00684     mExceptionList->addItem( dateStr );
00685   }
00686 }
00687 
00688 void ExceptionsWidget::changeException()
00689 {
00690   int pos = mExceptionList->currentRow();
00691   if ( pos < 0 ) {
00692     return;
00693   }
00694 
00695   QDate date = mExceptionDateEdit->date();
00696   mExceptionDates[ pos ] = date;
00697   QListWidgetItem *item = mExceptionList->item( pos );
00698   item->setText( KGlobal::locale()->formatDate( date ) );
00699 }
00700 
00701 void ExceptionsWidget::deleteException()
00702 {
00703   int pos = mExceptionList->currentRow();
00704   if ( pos < 0 ) {
00705     return;
00706   }
00707 
00708   mExceptionDates.removeAt( pos );
00709   delete( mExceptionList->takeItem( pos ) );
00710 }
00711 
00712 void ExceptionsWidget::setDates( const DateList &dates )
00713 {
00714   mExceptionList->clear();
00715   mExceptionDates.clear();
00716   DateList::ConstIterator dit;
00717   for ( dit = dates.begin(); dit != dates.end(); ++dit ) {
00718     mExceptionList->addItem( KGlobal::locale()->formatDate(* dit ) );
00719     mExceptionDates.append( *dit );
00720   }
00721 }
00722 
00723 DateList ExceptionsWidget::dates()
00724 {
00725   return mExceptionDates;
00726 }
00727 
00729 
00730 ExceptionsDialog::ExceptionsDialog( QWidget *parent ) :
00731   KDialog( parent )
00732 {
00733   setCaption( i18nc( "@title:window", "Edit Exceptions" ) );
00734   setButtons( Ok | Cancel );
00735   mExceptions = new ExceptionsWidget( this );
00736   setMainWidget( mExceptions );
00737 }
00738 
00739 void ExceptionsDialog::setDates( const DateList &dates )
00740 {
00741   mExceptions->setDates( dates );
00742 }
00743 
00744 DateList ExceptionsDialog::dates()
00745 {
00746   return mExceptions->dates();
00747 }
00748 
00750 
00751 RecurrenceRangeWidget::RecurrenceRangeWidget( QWidget *parent ) : QWidget( parent )
00752 {
00753   QBoxLayout *topLayout = new QVBoxLayout( this );
00754   topLayout->setSpacing( 0 );
00755   topLayout->setMargin( 0 );
00756 
00757   mRangeGroupBox = new QGroupBox( i18nc( "@title:group", "Recurrence Range" ), this );
00758   mRangeGroupBox->setWhatsThis( i18nc( "@info:whatsthis",
00759                                        "Sets a range for which these recurrence "
00760                                        "rules will apply to this event or to-do." ) );
00761   topLayout->addWidget( mRangeGroupBox );
00762 
00763   QVBoxLayout *rangeLayout = new QVBoxLayout( mRangeGroupBox );
00764   rangeLayout->setSpacing( KDialog::spacingHint() );
00765 
00766   mStartDateLabel = new QLabel( i18nc( "@label", "Begin on:" ), mRangeGroupBox );
00767   mStartDateLabel->setWhatsThis( i18nc( "@info:whatsthis",
00768                                         "The date on which the recurrences "
00769                                         "for this event or to-do should begin." ) );
00770   rangeLayout->addWidget( mStartDateLabel );
00771 
00772   QButtonGroup *rangeButtonGroup = new QButtonGroup( mRangeGroupBox );
00773 
00774   mNoEndDateButton = new QRadioButton(
00775     i18nc( "@option radio", "&No ending date" ), mRangeGroupBox );
00776   mNoEndDateButton->setWhatsThis(
00777     i18nc( "@info:whatsthis", "Sets the event or to-do to recur forever." ) );
00778   rangeButtonGroup->addButton( mNoEndDateButton );
00779   rangeLayout->addWidget( mNoEndDateButton );
00780 
00781   // The "After N occurrences" is a widget with a horizontal layout
00782   QBoxLayout *durationLayout = new QHBoxLayout();
00783   rangeLayout->addItem( durationLayout );
00784   durationLayout->setSpacing( KDialog::spacingHint() );
00785 
00786   QString whatsthis = i18nc(
00787     "@info:whatsthis",
00788     "Sets the event or to-do to stop recurring after "
00789     "a certain number of occurrences." );
00790   mEndDurationButton = new QRadioButton( i18nc( "@option:radio", "End &after" ), mRangeGroupBox );
00791   mEndDurationButton->setWhatsThis( whatsthis );
00792   rangeButtonGroup->addButton( mEndDurationButton );
00793   durationLayout->addWidget( mEndDurationButton );
00794 
00795   mEndDurationEdit = new QSpinBox( mRangeGroupBox );
00796   mEndDurationEdit->setRange( 1, 9999 );
00797   durationLayout->addWidget( mEndDurationEdit );
00798 
00799   QLabel *endDurationLabel = new QLabel( i18nc( "@label", "&occurrence(s)" ), mRangeGroupBox );
00800   durationLayout ->addWidget( endDurationLabel );
00801   endDurationLabel->setBuddy( mEndDurationEdit );
00802   durationLayout->addStretch(1);
00803 
00804   // The "End on" is a widget with a horizontal layout
00805   QBoxLayout *endDateLayout = new QHBoxLayout();
00806   rangeLayout->addItem( endDateLayout );
00807   whatsthis = i18nc( "@info:whatsthis",
00808                      "Sets the event or to-do to stop recurring on a certain date." );
00809 
00810   mEndDateButton = new QRadioButton( i18nc( "@option:radio", "End &on:" ), mRangeGroupBox );
00811   rangeButtonGroup->addButton( mEndDateButton );
00812   endDateLayout->addWidget( mEndDateButton );
00813 
00814   mEndDateEdit = new KPIM::KDateEdit( mRangeGroupBox );
00815   mEndDateEdit->setWhatsThis(
00816     i18nc( "@info:whatsthis",
00817            "Date after which the event or to-do should stop recurring" ) );
00818   endDateLayout->addWidget( mEndDateEdit );
00819   endDateLayout->addStretch( 1 );
00820 
00821   rangeLayout->addStretch( 1 );
00822 
00823   connect( mNoEndDateButton, SIGNAL(toggled(bool)), SLOT(showCurrentRange()) );
00824   connect( mEndDurationButton, SIGNAL(toggled(bool)), SLOT(showCurrentRange()) );
00825   connect( mEndDateButton, SIGNAL(toggled(bool)), SLOT(showCurrentRange()) );
00826 }
00827 
00828 void RecurrenceRangeWidget::setDefaults( const QDateTime &from )
00829 {
00830   mNoEndDateButton->setChecked( true );
00831 
00832   setDateTimes( from );
00833   setEndDate( from.date() );
00834 }
00835 
00836 void RecurrenceRangeWidget::setDuration( int duration )
00837 {
00838   if ( duration == -1 ) {
00839     mNoEndDateButton->setChecked( true );
00840   } else if ( duration == 0 ) {
00841     mEndDateButton->setChecked( true );
00842   } else {
00843     mEndDurationButton->setChecked( true );
00844     mEndDurationEdit->setValue( duration );
00845   }
00846 }
00847 
00848 int RecurrenceRangeWidget::duration()
00849 {
00850   if ( mNoEndDateButton->isChecked() ) {
00851     return -1;
00852   } else if ( mEndDurationButton->isChecked() ) {
00853     return mEndDurationEdit->value();
00854   } else {
00855     return 0;
00856   }
00857 }
00858 
00859 void RecurrenceRangeWidget::setEndDate( const QDate &date )
00860 {
00861   mEndDateEdit->setDate( date );
00862 }
00863 
00864 QDate RecurrenceRangeWidget::endDate()
00865 {
00866   return mEndDateEdit->date();
00867 }
00868 
00869 void RecurrenceRangeWidget::showCurrentRange()
00870 {
00871   mEndDurationEdit->setEnabled( mEndDurationButton->isChecked() );
00872   mEndDateEdit->setEnabled( mEndDateButton->isChecked() );
00873 }
00874 
00875 void RecurrenceRangeWidget::setDateTimes( const QDateTime &start,
00876                                           const QDateTime & )
00877 {
00878   mStartDateLabel->setText(
00879     i18nc( "@label", "Begins on: %1", KGlobal::locale()->formatDate( start.date() ) ) );
00880 }
00881 
00883 
00884 RecurrenceRangeDialog::RecurrenceRangeDialog( QWidget *parent ) :
00885   KDialog( parent )
00886 {
00887   setCaption( i18nc( "@title:window", "Edit Recurrence Range" ) );
00888   setButtons( Ok | Cancel );
00889   mRecurrenceRangeWidget = new RecurrenceRangeWidget( this );
00890   setMainWidget( mRecurrenceRangeWidget );
00891 }
00892 
00893 void RecurrenceRangeDialog::setDefaults( const QDateTime &from )
00894 {
00895   mRecurrenceRangeWidget->setDefaults( from );
00896 }
00897 
00898 void RecurrenceRangeDialog::setDuration( int duration )
00899 {
00900   mRecurrenceRangeWidget->setDuration( duration );
00901 }
00902 
00903 int RecurrenceRangeDialog::duration()
00904 {
00905   return mRecurrenceRangeWidget->duration();
00906 }
00907 
00908 void RecurrenceRangeDialog::setEndDate( const QDate &date )
00909 {
00910   mRecurrenceRangeWidget->setEndDate( date );
00911 }
00912 
00913 QDate RecurrenceRangeDialog::endDate()
00914 {
00915   return mRecurrenceRangeWidget->endDate();
00916 }
00917 
00918 void RecurrenceRangeDialog::setDateTimes( const QDateTime &start,
00919                                           const QDateTime &end )
00920 {
00921   mRecurrenceRangeWidget->setDateTimes( start, end );
00922 }
00923 
00925 
00926 RecurrenceChooser::RecurrenceChooser( QWidget *parent ) : QWidget( parent )
00927 {
00928   QBoxLayout *topLayout = new QVBoxLayout( this );
00929 
00930   if ( KOPrefs::instance()->mCompactDialogs ) {
00931     mTypeCombo = new KComboBox( this );
00932     mTypeCombo->setWhatsThis( i18nc( "@info:whatsthis",
00933                                      "Sets the type of recurrence this event "
00934                                      "or to-do should have." ) );
00935     mTypeCombo->addItem( i18nc( "@item:inlistbox recur daily", "Daily" ) );
00936     mTypeCombo->addItem( i18nc( "@item:inlistbox recur weekly", "Weekly" ) );
00937     mTypeCombo->addItem( i18nc( "@item:inlistbox recur monthly", "Monthly" ) );
00938     mTypeCombo->addItem( i18nc( "@item:inlistbox recur yearly", "Yearly" ) );
00939 
00940     topLayout->addWidget( mTypeCombo );
00941 
00942     connect( mTypeCombo, SIGNAL(activated(int)), SLOT(emitChoice()) );
00943   } else {
00944     mTypeCombo = 0;
00945 
00946     QGroupBox *ruleButtonGroup = new QGroupBox( i18nc( "@title:group", "Recurrency Types" ), this );
00947     QBoxLayout *buttonLayout = new QVBoxLayout( ruleButtonGroup );
00948 
00949     ruleButtonGroup->setFlat( true );
00950     topLayout->addWidget( ruleButtonGroup );
00951 
00952     mDailyButton = new QRadioButton(
00953       i18nc( "@option:radio recur daily", "&Daily" ), ruleButtonGroup );
00954     mDailyButton->setWhatsThis(
00955       i18nc( "@info:whatsthis",
00956              "Sets the event or to-do to recur daily "
00957              "according to the specified rules." ) );
00958     buttonLayout->addWidget( mDailyButton );
00959     mWeeklyButton = new QRadioButton(
00960       i18nc( "@option:radio recur weekly", "&Weekly" ), ruleButtonGroup );
00961     mWeeklyButton->setWhatsThis(
00962       i18nc( "@info:whatsthis",
00963              "Sets the event or to-do to recur weekly "
00964              "according to the specified rules." ) );
00965     buttonLayout->addWidget( mWeeklyButton );
00966     mMonthlyButton = new QRadioButton(
00967       i18nc( "@option:radio recur monthly", "&Monthly" ), ruleButtonGroup );
00968     mMonthlyButton->setWhatsThis(
00969       i18nc( "@info:whatsthis",
00970              "Sets the event or to-do to recur monthly "
00971              "according to the specified rules." ) );
00972     buttonLayout->addWidget( mMonthlyButton );
00973     mYearlyButton = new QRadioButton(
00974       i18nc( "@option:radio recur yearly", "&Yearly" ), ruleButtonGroup );
00975     mYearlyButton->setWhatsThis(
00976       i18nc( "@info:whatsthis",
00977              "Sets the event or to-do to recur yearly "
00978              "according to the specified rules." ) );
00979     buttonLayout->addWidget( mYearlyButton );
00980 
00981     connect( mDailyButton, SIGNAL(toggled(bool)), SLOT(emitChoice()) );
00982     connect( mWeeklyButton, SIGNAL(toggled(bool)), SLOT(emitChoice()) );
00983     connect( mMonthlyButton, SIGNAL(toggled(bool)), SLOT(emitChoice()) );
00984     connect( mYearlyButton, SIGNAL(toggled(bool)), SLOT(emitChoice()) );
00985   }
00986 }
00987 
00988 int RecurrenceChooser::type()
00989 {
00990   if ( mTypeCombo ) {
00991     return mTypeCombo->currentIndex();
00992   } else {
00993     if ( mDailyButton->isChecked() ) {
00994       return Daily;
00995     }
00996     else if ( mWeeklyButton->isChecked() ) {
00997       return Weekly;
00998     }
00999     else if ( mMonthlyButton->isChecked() ) {
01000       return