summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--korganizer/komonthview.cpp15
-rw-r--r--libkcal/recurrence.cpp34
2 files changed, 14 insertions, 35 deletions
diff --git a/korganizer/komonthview.cpp b/korganizer/komonthview.cpp
index cb69832..004ff50 100644
--- a/korganizer/komonthview.cpp
+++ b/korganizer/komonthview.cpp
@@ -751,957 +751,948 @@ Incidence *MonthViewCell::selectedIncidence()
751 751
752 MonthViewItem *item = 752 MonthViewItem *item =
753 static_cast<MonthViewItem *>( mItemList->item( index ) ); 753 static_cast<MonthViewItem *>( mItemList->item( index ) );
754 754
755 if ( !item ) return 0; 755 if ( !item ) return 0;
756 756
757 return item->incidence(); 757 return item->incidence();
758} 758}
759 759
760QDate MonthViewCell::selectedIncidenceDate() 760QDate MonthViewCell::selectedIncidenceDate()
761{ 761{
762 QDate qd; 762 QDate qd;
763 int index = mItemList->currentItem(); 763 int index = mItemList->currentItem();
764 if ( index < 0 ) return qd; 764 if ( index < 0 ) return qd;
765 765
766 MonthViewItem *item = 766 MonthViewItem *item =
767 static_cast<MonthViewItem *>( mItemList->item( index ) ); 767 static_cast<MonthViewItem *>( mItemList->item( index ) );
768 768
769 if ( !item ) return qd; 769 if ( !item ) return qd;
770 770
771 return item->incidenceDate(); 771 return item->incidenceDate();
772} 772}
773 773
774void MonthViewCell::deselect() 774void MonthViewCell::deselect()
775{ 775{
776 mItemList->clearSelection(); 776 mItemList->clearSelection();
777 enableScrollBars( false ); 777 enableScrollBars( false );
778 // updateCell(); 778 // updateCell();
779} 779}
780void MonthViewCell::select() 780void MonthViewCell::select()
781{ 781{
782 ;// updateCell(); 782 ;// updateCell();
783} 783}
784 784
785void MonthViewCell::resizeEvent ( QResizeEvent * ) 785void MonthViewCell::resizeEvent ( QResizeEvent * )
786{ 786{
787 if ( !mMonthView->isUpdatePossible() ) 787 if ( !mMonthView->isUpdatePossible() )
788 return; 788 return;
789 789
790 int size = height() - mLabel->height() - 2; 790 int size = height() - mLabel->height() - 2;
791 if ( size > 0 ) 791 if ( size > 0 )
792 mItemList->verticalScrollBar()->setMaximumHeight( size ); 792 mItemList->verticalScrollBar()->setMaximumHeight( size );
793 size = width() - mLabel->width() -2; 793 size = width() - mLabel->width() -2;
794 if ( size > 0 ) 794 if ( size > 0 )
795 mItemList->horizontalScrollBar()->setMaximumWidth( size ); 795 mItemList->horizontalScrollBar()->setMaximumWidth( size );
796 mLabel->move( width()-mItemList->lineWidth() - mLabel->width(), height()-mItemList->lineWidth() - mLabel->height() ); 796 mLabel->move( width()-mItemList->lineWidth() - mLabel->width(), height()-mItemList->lineWidth() - mLabel->height() );
797 //mLabel->setMaximumWidth( width() - mItemList->lineWidth()*2); 797 //mLabel->setMaximumWidth( width() - mItemList->lineWidth()*2);
798} 798}
799 799
800void MonthViewCell::defaultAction( QListBoxItem *item ) 800void MonthViewCell::defaultAction( QListBoxItem *item )
801{ 801{
802 if ( !item ) return; 802 if ( !item ) return;
803 803
804 MonthViewItem *eventItem = static_cast<MonthViewItem *>( item ); 804 MonthViewItem *eventItem = static_cast<MonthViewItem *>( item );
805 Incidence *incidence = eventItem->incidence(); 805 Incidence *incidence = eventItem->incidence();
806 if ( incidence ) mMonthView->defaultAction( incidence ); 806 if ( incidence ) mMonthView->defaultAction( incidence );
807} 807}
808void MonthViewCell::showDay() 808void MonthViewCell::showDay()
809{ 809{
810 emit showDaySignal( date() ); 810 emit showDaySignal( date() );
811} 811}
812void MonthViewCell::newEvent() 812void MonthViewCell::newEvent()
813{ 813{
814 QDateTime dt( date(), QTime( KOPrefs::instance()->mStartTime, 0 ) ); 814 QDateTime dt( date(), QTime( KOPrefs::instance()->mStartTime, 0 ) );
815 emit newEventSignal( dt ); 815 emit newEventSignal( dt );
816} 816}
817void MonthViewCell::cellClicked( QListBoxItem *item ) 817void MonthViewCell::cellClicked( QListBoxItem *item )
818{ 818{
819 static QListBoxItem * lastClicked = 0; 819 static QListBoxItem * lastClicked = 0;
820 if ( item == 0 ) { 820 if ( item == 0 ) {
821 QDateTime dt( date(), QTime( KOPrefs::instance()->mStartTime, 0 ) ); 821 QDateTime dt( date(), QTime( KOPrefs::instance()->mStartTime, 0 ) );
822 emit newEventSignal( dt ); 822 emit newEventSignal( dt );
823 return; 823 return;
824 } 824 }
825 /* 825 /*
826 if ( lastClicked ) 826 if ( lastClicked )
827 if ( ! item ) { 827 if ( ! item ) {
828 if ( lastClicked->listBox() != item->listBox() ) 828 if ( lastClicked->listBox() != item->listBox() )
829 lastClicked->listBox()->clearSelection(); 829 lastClicked->listBox()->clearSelection();
830 } 830 }
831 */ 831 */
832 832
833 mMonthView->setSelectedCell( this ); 833 mMonthView->setSelectedCell( this );
834 if( KOPrefs::instance()->mEnableMonthScroll || KOPrefs::instance()->mMonthViewWeek ) enableScrollBars( true ); 834 if( KOPrefs::instance()->mEnableMonthScroll || KOPrefs::instance()->mMonthViewWeek ) enableScrollBars( true );
835 select(); 835 select();
836} 836}
837 837
838void MonthViewCell::contextMenu( QListBoxItem *item ) 838void MonthViewCell::contextMenu( QListBoxItem *item )
839{ 839{
840 if ( !item ) return; 840 if ( !item ) return;
841 841
842 MonthViewItem *eventItem = static_cast<MonthViewItem *>( item ); 842 MonthViewItem *eventItem = static_cast<MonthViewItem *>( item );
843 Incidence *incidence = eventItem->incidence(); 843 Incidence *incidence = eventItem->incidence();
844 if ( incidence ) mMonthView->showContextMenu( incidence ); 844 if ( incidence ) mMonthView->showContextMenu( incidence );
845} 845}
846 846
847void MonthViewCell::selection( QListBoxItem *item ) 847void MonthViewCell::selection( QListBoxItem *item )
848{ 848{
849 if ( !item ) return; 849 if ( !item ) return;
850 850
851 mMonthView->setSelectedCell( this ); 851 mMonthView->setSelectedCell( this );
852} 852}
853 853
854 854
855// ******************************************************************************* 855// *******************************************************************************
856// ******************************************************************************* 856// *******************************************************************************
857// ******************************************************************************* 857// *******************************************************************************
858 858
859 859
860KOMonthView::KOMonthView(Calendar *calendar, QWidget *parent, const char *name) 860KOMonthView::KOMonthView(Calendar *calendar, QWidget *parent, const char *name)
861 : KOEventView( calendar, parent, name ), 861 : KOEventView( calendar, parent, name ),
862 mDaysPerWeek( 7 ), mNumWeeks( 6 ), mNumCells( mDaysPerWeek * mNumWeeks ), 862 mDaysPerWeek( 7 ), mNumWeeks( 6 ), mNumCells( mDaysPerWeek * mNumWeeks ),
863 mWidthLongDayLabel( 0 ), mSelectedCell( 0 ) 863 mWidthLongDayLabel( 0 ), mSelectedCell( 0 )
864{ 864{
865 mShortDayLabelsM = false; 865 mShortDayLabelsM = false;
866 mShortDayLabelsW = false; 866 mShortDayLabelsW = false;
867 skipResize = false; 867 skipResize = false;
868 clPending = true; 868 clPending = true;
869 mNavigatorBar = new NavigatorBar( QDate::currentDate(), this, "useBigPixmaps" ); 869 mNavigatorBar = new NavigatorBar( QDate::currentDate(), this, "useBigPixmaps" );
870 mWidStack = new QWidgetStack( this ); 870 mWidStack = new QWidgetStack( this );
871 QVBoxLayout* hb = new QVBoxLayout( this ); 871 QVBoxLayout* hb = new QVBoxLayout( this );
872 mMonthView = new QWidget( mWidStack ); 872 mMonthView = new QWidget( mWidStack );
873 mWeekView = new QWidget( mWidStack ); 873 mWeekView = new QWidget( mWidStack );
874#if QT_VERSION >= 0x030000 874#if QT_VERSION >= 0x030000
875 mWidStack->addWidget(mMonthView ); 875 mWidStack->addWidget(mMonthView );
876 mWidStack->addWidget(mWeekView ); 876 mWidStack->addWidget(mWeekView );
877#else 877#else
878 mWidStack->addWidget( mMonthView, 1 ); 878 mWidStack->addWidget( mMonthView, 1 );
879 mWidStack->addWidget( mWeekView , 1 ); 879 mWidStack->addWidget( mWeekView , 1 );
880#endif 880#endif
881 hb->addWidget( mNavigatorBar ); 881 hb->addWidget( mNavigatorBar );
882 hb->addWidget( mWidStack ); 882 hb->addWidget( mWidStack );
883 mWeekStartsMonday = KGlobal::locale()->weekStartsMonday(); 883 mWeekStartsMonday = KGlobal::locale()->weekStartsMonday();
884 mShowWeekView = KOPrefs::instance()->mMonthViewWeek; 884 mShowWeekView = KOPrefs::instance()->mMonthViewWeek;
885 if ( mShowWeekView ) 885 if ( mShowWeekView )
886 mWeekStartsMonday = true; 886 mWeekStartsMonday = true;
887 updatePossible = false; 887 updatePossible = false;
888 //updatePossible = true; 888 //updatePossible = true;
889 mCells.setAutoDelete( true ); 889 mCells.setAutoDelete( true );
890 mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ; 890 mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ;
891 mDayLabels.resize( mDaysPerWeek ); 891 mDayLabels.resize( mDaysPerWeek );
892 mDayLabelsW.resize( mDaysPerWeek ); 892 mDayLabelsW.resize( mDaysPerWeek );
893 QFont bfont = font(); 893 QFont bfont = font();
894 if ( QApplication::desktop()->width() < 650 ) { 894 if ( QApplication::desktop()->width() < 650 ) {
895 bfont.setPointSize( bfont.pointSize() - 2 ); 895 bfont.setPointSize( bfont.pointSize() - 2 );
896 } 896 }
897 bfont.setBold( true ); 897 bfont.setBold( true );
898 int i; 898 int i;
899 899
900 for( i = 0; i < mDaysPerWeek; i++ ) { 900 for( i = 0; i < mDaysPerWeek; i++ ) {
901 QLabel *label = new QLabel( mMonthView ); 901 QLabel *label = new QLabel( mMonthView );
902 label->setFont(bfont); 902 label->setFont(bfont);
903 label->setFrameStyle(QFrame::Panel|QFrame::Raised); 903 label->setFrameStyle(QFrame::Panel|QFrame::Raised);
904 label->setLineWidth(1); 904 label->setLineWidth(1);
905 label->setAlignment(AlignCenter); 905 label->setAlignment(AlignCenter);
906 mDayLabels.insert( i, label ); 906 mDayLabels.insert( i, label );
907 label = new QLabel( mWeekView ); 907 label = new QLabel( mWeekView );
908 label->setFont(bfont); 908 label->setFont(bfont);
909 label->setFrameStyle(QFrame::Panel|QFrame::Raised); 909 label->setFrameStyle(QFrame::Panel|QFrame::Raised);
910 label->setLineWidth(1); 910 label->setLineWidth(1);
911 label->setAlignment(AlignCenter); 911 label->setAlignment(AlignCenter);
912 mDayLabelsW.insert( i, label ); 912 mDayLabelsW.insert( i, label );
913 } 913 }
914 914
915 bfont.setBold( false ); 915 bfont.setBold( false );
916 mWeekLabels.resize( mNumWeeks+1 ); 916 mWeekLabels.resize( mNumWeeks+1 );
917 mWeekLabelsW.resize( 2 ); 917 mWeekLabelsW.resize( 2 );
918 for( i = 0; i < mNumWeeks+1; i++ ) { 918 for( i = 0; i < mNumWeeks+1; i++ ) {
919 KOWeekButton *label = new KOWeekButton( mMonthView ); 919 KOWeekButton *label = new KOWeekButton( mMonthView );
920 label->setFocusPolicy(NoFocus); 920 label->setFocusPolicy(NoFocus);
921 label->setFont(bfont); 921 label->setFont(bfont);
922 connect( label, SIGNAL( selectWeekNum ( int )),this, SLOT( selectInternalWeekNum ( int )) ); 922 connect( label, SIGNAL( selectWeekNum ( int )),this, SLOT( selectInternalWeekNum ( int )) );
923 label->setFlat(true); 923 label->setFlat(true);
924 QWhatsThis::add(label,i18n("Click on the week number to\nshow week zoomed")); 924 QWhatsThis::add(label,i18n("Click on the week number to\nshow week zoomed"));
925 //label->setFrameStyle(QFrame::Panel|QFrame::Raised); 925 //label->setFrameStyle(QFrame::Panel|QFrame::Raised);
926 //label->setLineWidth(1); 926 //label->setLineWidth(1);
927 //label->setAlignment(AlignCenter); 927 //label->setAlignment(AlignCenter);
928 mWeekLabels.insert( i, label ); 928 mWeekLabels.insert( i, label );
929 } 929 }
930 mWeekLabels[mNumWeeks]->setText( i18n("W")); 930 mWeekLabels[mNumWeeks]->setText( i18n("W"));
931 QWhatsThis::add(mWeekLabels[mNumWeeks],i18n("Click on this to\nselect week number")); 931 QWhatsThis::add(mWeekLabels[mNumWeeks],i18n("Click on this to\nselect week number"));
932 932
933 for( i = 0; i < 1+1; i++ ) { 933 for( i = 0; i < 1+1; i++ ) {
934 KOWeekButton *label = new KOWeekButton( mWeekView ); 934 KOWeekButton *label = new KOWeekButton( mWeekView );
935 label->setFocusPolicy(NoFocus); 935 label->setFocusPolicy(NoFocus);
936 label->setFont(bfont); 936 label->setFont(bfont);
937 connect( label, SIGNAL( selectWeekNum ( int )),this, SLOT( selectInternalWeekNum ( int )) ); 937 connect( label, SIGNAL( selectWeekNum ( int )),this, SLOT( selectInternalWeekNum ( int )) );
938 label->setFlat(true); 938 label->setFlat(true);
939 QWhatsThis::add(label,i18n("Click on the week number to\nshow week zoomed")); 939 QWhatsThis::add(label,i18n("Click on the week number to\nshow week zoomed"));
940 //label->setFrameStyle(QFrame::Panel|QFrame::Raised); 940 //label->setFrameStyle(QFrame::Panel|QFrame::Raised);
941 //label->setLineWidth(1); 941 //label->setLineWidth(1);
942 //label->setAlignment(AlignCenter); 942 //label->setAlignment(AlignCenter);
943 mWeekLabelsW.insert( i, label ); 943 mWeekLabelsW.insert( i, label );
944 } 944 }
945 mWeekLabelsW[1]->setText( i18n("W")); 945 mWeekLabelsW[1]->setText( i18n("W"));
946 946
947 947
948 int row, col; 948 int row, col;
949 mCells.resize( mNumCells ); 949 mCells.resize( mNumCells );
950 for( row = 0; row < mNumWeeks; ++row ) { 950 for( row = 0; row < mNumWeeks; ++row ) {
951 for( col = 0; col < mDaysPerWeek; ++col ) { 951 for( col = 0; col < mDaysPerWeek; ++col ) {
952 MonthViewCell *cell = new MonthViewCell( this, mMonthView ); 952 MonthViewCell *cell = new MonthViewCell( this, mMonthView );
953 mCells.insert( row * mDaysPerWeek + col, cell ); 953 mCells.insert( row * mDaysPerWeek + col, cell );
954 954
955 connect( cell, SIGNAL( defaultAction( Incidence * ) ), 955 connect( cell, SIGNAL( defaultAction( Incidence * ) ),
956 SLOT( defaultAction( Incidence * ) ) ); 956 SLOT( defaultAction( Incidence * ) ) );
957 connect( cell, SIGNAL( newEventSignal( QDateTime ) ), 957 connect( cell, SIGNAL( newEventSignal( QDateTime ) ),
958 SIGNAL( newEventSignal( QDateTime ) ) ); 958 SIGNAL( newEventSignal( QDateTime ) ) );
959 connect( cell, SIGNAL( showDaySignal( QDate ) ), 959 connect( cell, SIGNAL( showDaySignal( QDate ) ),
960 SIGNAL( showDaySignal( QDate ) ) ); 960 SIGNAL( showDaySignal( QDate ) ) );
961 } 961 }
962 } 962 }
963 mCellsW.resize( mDaysPerWeek ); 963 mCellsW.resize( mDaysPerWeek );
964 for( col = 0; col < mDaysPerWeek; ++col ) { 964 for( col = 0; col < mDaysPerWeek; ++col ) {
965 MonthViewCell *cell = new MonthViewCell( this, mWeekView ); 965 MonthViewCell *cell = new MonthViewCell( this, mWeekView );
966 mCellsW.insert( col, cell ); 966 mCellsW.insert( col, cell );
967 967
968 connect( cell, SIGNAL( defaultAction( Incidence * ) ), 968 connect( cell, SIGNAL( defaultAction( Incidence * ) ),
969 SLOT( defaultAction( Incidence * ) ) ); 969 SLOT( defaultAction( Incidence * ) ) );
970 connect( cell, SIGNAL( newEventSignal( QDateTime ) ), 970 connect( cell, SIGNAL( newEventSignal( QDateTime ) ),
971 SIGNAL( newEventSignal( QDateTime ) ) ); 971 SIGNAL( newEventSignal( QDateTime ) ) );
972 connect( cell, SIGNAL( showDaySignal( QDate ) ), 972 connect( cell, SIGNAL( showDaySignal( QDate ) ),
973 SIGNAL( showDaySignal( QDate ) ) ); 973 SIGNAL( showDaySignal( QDate ) ) );
974 cell->updateConfig(KOPrefs::instance()->mMonthViewUsesBigFont ); 974 cell->updateConfig(KOPrefs::instance()->mMonthViewUsesBigFont );
975 } 975 }
976 976
977 //connect( mWeekLabels[mNumWeeks], SIGNAL( clicked() ), SLOT( switchView() ) ); 977 //connect( mWeekLabels[mNumWeeks], SIGNAL( clicked() ), SLOT( switchView() ) );
978 mContextMenu = eventPopup(); 978 mContextMenu = eventPopup();
979 // updateConfig(); //useless here... 979 // updateConfig(); //useless here...
980 // ... but we need mWidthLongDayLabel computed 980 // ... but we need mWidthLongDayLabel computed
981 QFontMetrics fontmetric(mDayLabels[0]->font()); 981 QFontMetrics fontmetric(mDayLabels[0]->font());
982 mWidthLongDayLabel = 0; 982 mWidthLongDayLabel = 0;
983 for (int i = 0; i < 7; i++) { 983 for (int i = 0; i < 7; i++) {
984 int width = fontmetric.width(KOGlobals::self()->calendarSystem()->weekDayName(i+1)); 984 int width = fontmetric.width(KOGlobals::self()->calendarSystem()->weekDayName(i+1));
985 if ( width > mWidthLongDayLabel ) mWidthLongDayLabel = width; 985 if ( width > mWidthLongDayLabel ) mWidthLongDayLabel = width;
986 } 986 }
987 987
988 //mWeekLabels[mNumWeeks]->setText( i18n("W")); 988 //mWeekLabels[mNumWeeks]->setText( i18n("W"));
989 989
990#if 0 990#if 0
991 if ( mShowWeekView ) 991 if ( mShowWeekView )
992 mWidStack->raiseWidget( mWeekView ); 992 mWidStack->raiseWidget( mWeekView );
993 else 993 else
994 mWidStack->raiseWidget( mMonthView ); 994 mWidStack->raiseWidget( mMonthView );
995#endif 995#endif
996 996
997 emit incidenceSelected( 0 ); 997 emit incidenceSelected( 0 );
998#ifndef DESKTOP_VERSION 998#ifndef DESKTOP_VERSION
999 resize( QApplication::desktop()->size() ); 999 resize( QApplication::desktop()->size() );
1000#else 1000#else
1001 resize(640, 480 ); 1001 resize(640, 480 );
1002 updatePossible = true; 1002 updatePossible = true;
1003#endif 1003#endif
1004 computeLayout(); 1004 computeLayout();
1005 1005
1006 if ( mShowWeekView ) 1006 if ( mShowWeekView )
1007 mWidStack->raiseWidget( mWeekView ); 1007 mWidStack->raiseWidget( mWeekView );
1008 else 1008 else
1009 mWidStack->raiseWidget( mMonthView ); 1009 mWidStack->raiseWidget( mMonthView );
1010} 1010}
1011 1011
1012KOMonthView::~KOMonthView() 1012KOMonthView::~KOMonthView()
1013{ 1013{
1014 delete mContextMenu; 1014 delete mContextMenu;
1015} 1015}
1016 1016
1017void KOMonthView::selectInternalWeekNum ( int n ) 1017void KOMonthView::selectInternalWeekNum ( int n )
1018{ 1018{
1019 switchView(); 1019 switchView();
1020 if ( !KOPrefs::instance()->mMonthViewWeek ) 1020 if ( !KOPrefs::instance()->mMonthViewWeek )
1021 emit selectMonth (); 1021 emit selectMonth ();
1022 else 1022 else
1023 emit selectWeekNum ( n ); 1023 emit selectWeekNum ( n );
1024} 1024}
1025 1025
1026int KOMonthView::currentWeek() 1026int KOMonthView::currentWeek()
1027{ 1027{
1028 if ( mShowWeekView ) 1028 if ( mShowWeekView )
1029 return mWeekLabelsW[0]->getWeekNum(); 1029 return mWeekLabelsW[0]->getWeekNum();
1030 return mWeekLabels[0]->getWeekNum(); 1030 return mWeekLabels[0]->getWeekNum();
1031} 1031}
1032void KOMonthView::switchView() 1032void KOMonthView::switchView()
1033{ 1033{
1034 if ( selectedCell( ) ) 1034 if ( selectedCell( ) )
1035 selectedCell()->deselect(); 1035 selectedCell()->deselect();
1036 mShowWeekView = !mShowWeekView; 1036 mShowWeekView = !mShowWeekView;
1037 KOPrefs::instance()->mMonthViewWeek = mShowWeekView; 1037 KOPrefs::instance()->mMonthViewWeek = mShowWeekView;
1038 if ( clPending ) { 1038 if ( clPending ) {
1039 computeLayout(); 1039 computeLayout();
1040 updateConfig(); 1040 updateConfig();
1041 } 1041 }
1042 if ( mShowWeekView ) 1042 if ( mShowWeekView )
1043 mWidStack->raiseWidget( mWeekView ); 1043 mWidStack->raiseWidget( mWeekView );
1044 else 1044 else
1045 mWidStack->raiseWidget( mMonthView ); 1045 mWidStack->raiseWidget( mMonthView );
1046 clPending = false; 1046 clPending = false;
1047} 1047}
1048 1048
1049int KOMonthView::maxDatesHint() 1049int KOMonthView::maxDatesHint()
1050{ 1050{
1051 return mNumCells; 1051 return mNumCells;
1052} 1052}
1053 1053
1054int KOMonthView::currentDateCount() 1054int KOMonthView::currentDateCount()
1055{ 1055{
1056 return mNumCells; 1056 return mNumCells;
1057} 1057}
1058 1058
1059QPtrList<Incidence> KOMonthView::selectedIncidences() 1059QPtrList<Incidence> KOMonthView::selectedIncidences()
1060{ 1060{
1061 QPtrList<Incidence> selected; 1061 QPtrList<Incidence> selected;
1062 1062
1063 if ( mSelectedCell ) { 1063 if ( mSelectedCell ) {
1064 Incidence *incidence = mSelectedCell->selectedIncidence(); 1064 Incidence *incidence = mSelectedCell->selectedIncidence();
1065 if ( incidence ) selected.append( incidence ); 1065 if ( incidence ) selected.append( incidence );
1066 } 1066 }
1067 1067
1068 return selected; 1068 return selected;
1069} 1069}
1070 1070
1071DateList KOMonthView::selectedDates() 1071DateList KOMonthView::selectedDates()
1072{ 1072{
1073 DateList selected; 1073 DateList selected;
1074 1074
1075 if ( mSelectedCell ) { 1075 if ( mSelectedCell ) {
1076 QDate qd = mSelectedCell->selectedIncidenceDate(); 1076 QDate qd = mSelectedCell->selectedIncidenceDate();
1077 if ( qd.isValid() ) selected.append( qd ); 1077 if ( qd.isValid() ) selected.append( qd );
1078 } 1078 }
1079 1079
1080 return selected; 1080 return selected;
1081} 1081}
1082 1082
1083void KOMonthView::printPreview(CalPrinter *calPrinter, const QDate &fd, 1083void KOMonthView::printPreview(CalPrinter *calPrinter, const QDate &fd,
1084 const QDate &td) 1084 const QDate &td)
1085{ 1085{
1086#ifndef KORG_NOPRINTER 1086#ifndef KORG_NOPRINTER
1087 calPrinter->preview(CalPrinter::Month, fd, td); 1087 calPrinter->preview(CalPrinter::Month, fd, td);
1088#endif 1088#endif
1089} 1089}
1090 1090
1091void KOMonthView::updateConfig() 1091void KOMonthView::updateConfig()
1092{ 1092{
1093 1093
1094 mWeekStartsMonday = KGlobal::locale()->weekStartsMonday(); 1094 mWeekStartsMonday = KGlobal::locale()->weekStartsMonday();
1095 1095
1096 if ( mShowWeekView ) { 1096 if ( mShowWeekView ) {
1097 mWeekStartsMonday = true; 1097 mWeekStartsMonday = true;
1098 } 1098 }
1099 QFontMetrics fontmetric(mDayLabels[0]->font()); 1099 QFontMetrics fontmetric(mDayLabels[0]->font());
1100 mWidthLongDayLabel = 0; 1100 mWidthLongDayLabel = 0;
1101 1101
1102 for (int i = 0; i < 7; i++) { 1102 for (int i = 0; i < 7; i++) {
1103 int width = fontmetric.width(KOGlobals::self()->calendarSystem()->weekDayName(i+1)); 1103 int width = fontmetric.width(KOGlobals::self()->calendarSystem()->weekDayName(i+1));
1104 if ( width > mWidthLongDayLabel ) mWidthLongDayLabel = width; 1104 if ( width > mWidthLongDayLabel ) mWidthLongDayLabel = width;
1105 } 1105 }
1106 bool temp = mShowSatSunComp ; 1106 bool temp = mShowSatSunComp ;
1107 mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ; 1107 mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ;
1108 if ( ! mShowWeekView ) { 1108 if ( ! mShowWeekView ) {
1109 if ( temp != KOPrefs::instance()->mMonthViewSatSunTog ) 1109 if ( temp != KOPrefs::instance()->mMonthViewSatSunTog )
1110 computeLayout(); 1110 computeLayout();
1111 } 1111 }
1112 updateDayLabels(); 1112 updateDayLabels();
1113 //qDebug("KOMonthView::updateConfig() %d %d %d ",height(), mDayLabels[0]->sizeHint().height() ,mNumWeeks); 1113 //qDebug("KOMonthView::updateConfig() %d %d %d ",height(), mDayLabels[0]->sizeHint().height() ,mNumWeeks);
1114 //int cellHeight = (height() - mDayLabels[0]->sizeHint().height()) /mNumWeeks; 1114 //int cellHeight = (height() - mDayLabels[0]->sizeHint().height()) /mNumWeeks;
1115 //resizeEvent( 0 ); 1115 //resizeEvent( 0 );
1116 for (uint i = 0; i < mCells.count(); ++i) { 1116 for (uint i = 0; i < mCells.count(); ++i) {
1117 mCells[i]->updateConfig(); 1117 mCells[i]->updateConfig();
1118 } 1118 }
1119 1119
1120 for (uint i = 0; i < mCellsW.count(); ++i) { 1120 for (uint i = 0; i < mCellsW.count(); ++i) {
1121 mCellsW[i]->updateConfig(KOPrefs::instance()->mMonthViewUsesBigFont); 1121 mCellsW[i]->updateConfig(KOPrefs::instance()->mMonthViewUsesBigFont);
1122 } 1122 }
1123#ifdef DESKTOP_VERSION 1123#ifdef DESKTOP_VERSION
1124 MonthViewCell::toolTipGroup()->setEnabled(KOPrefs::instance()->mEnableToolTips); 1124 MonthViewCell::toolTipGroup()->setEnabled(KOPrefs::instance()->mEnableToolTips);
1125#endif 1125#endif
1126 updateView(); 1126 updateView();
1127} 1127}
1128 1128
1129void KOMonthView::updateDayLabels() 1129void KOMonthView::updateDayLabels()
1130{ 1130{
1131 1131
1132 QPtrVector<QLabel> *mDayLabelsT; 1132 QPtrVector<QLabel> *mDayLabelsT;
1133 1133
1134 mDayLabelsT = &mDayLabelsW; 1134 mDayLabelsT = &mDayLabelsW;
1135 for (int i = 0; i < 7; i++) { 1135 for (int i = 0; i < 7; i++) {
1136 if (mWeekStartsMonday) { 1136 if (mWeekStartsMonday) {
1137 bool show = mShortDayLabelsW; 1137 bool show = mShortDayLabelsW;
1138 if ( i > 4 && mShowSatSunComp && mWidthLongDayLabel > (*mDayLabelsT)[i]->width() ) 1138 if ( i > 4 && mShowSatSunComp && mWidthLongDayLabel > (*mDayLabelsT)[i]->width() )
1139 show = true; 1139 show = true;
1140 (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i+1,show)); 1140 (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i+1,show));
1141 } else { 1141 } else {
1142 if (i==0) (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(7,mShortDayLabelsW)); 1142 if (i==0) (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(7,mShortDayLabelsW));
1143 else (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i,mShortDayLabelsW)); 1143 else (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i,mShortDayLabelsW));
1144 1144
1145 } 1145 }
1146 } 1146 }
1147 mDayLabelsT = &mDayLabels; 1147 mDayLabelsT = &mDayLabels;
1148 for (int i = 0; i < 7; i++) { 1148 for (int i = 0; i < 7; i++) {
1149 if (mWeekStartsMonday) { 1149 if (mWeekStartsMonday) {
1150 bool show = mShortDayLabelsM; 1150 bool show = mShortDayLabelsM;
1151 if ( i > 4 && mShowSatSunComp && mWidthLongDayLabel > (*mDayLabelsT)[i]->width() ) 1151 if ( i > 4 && mShowSatSunComp && mWidthLongDayLabel > (*mDayLabelsT)[i]->width() )
1152 show = true; 1152 show = true;
1153 (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i+1,show)); 1153 (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i+1,show));
1154 } else { 1154 } else {
1155 if (i==0) (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(7,mShortDayLabelsM)); 1155 if (i==0) (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(7,mShortDayLabelsM));
1156 else (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i,mShortDayLabelsM)); 1156 else (*mDayLabelsT)[i]->setText(KOGlobals::self()->calendarSystem()->weekDayName(i,mShortDayLabelsM));
1157 1157
1158 } 1158 }
1159 } 1159 }
1160 1160
1161} 1161}
1162 1162
1163void KOMonthView::showDates(const QDate &start, const QDate &) 1163void KOMonthView::showDates(const QDate &start, const QDate &)
1164{ 1164{
1165 // kdDebug() << "KOMonthView::showDates(): " << start.toString() << endl; 1165 // kdDebug() << "KOMonthView::showDates(): " << start.toString() << endl;
1166 1166
1167 QPtrVector<MonthViewCell> *cells; 1167 QPtrVector<MonthViewCell> *cells;
1168 QPtrVector<QLabel> *dayLabels; 1168 QPtrVector<QLabel> *dayLabels;
1169 QPtrVector<KOWeekButton> *weekLabels; 1169 QPtrVector<KOWeekButton> *weekLabels;
1170 int weekNum = 6; 1170 int weekNum = 6;
1171 if ( mShowWeekView ) { 1171 if ( mShowWeekView ) {
1172 weekNum = 1; 1172 weekNum = 1;
1173 cells = &mCellsW; 1173 cells = &mCellsW;
1174 dayLabels = &mDayLabelsW; 1174 dayLabels = &mDayLabelsW;
1175 weekLabels = &mWeekLabelsW; 1175 weekLabels = &mWeekLabelsW;
1176 } else { 1176 } else {
1177 cells = &mCells; 1177 cells = &mCells;
1178 dayLabels = &mDayLabels; 1178 dayLabels = &mDayLabels;
1179 weekLabels = &mWeekLabels; 1179 weekLabels = &mWeekLabels;
1180 } 1180 }
1181 1181
1182 mStartDate = start; 1182 mStartDate = start;
1183 1183
1184 int startWeekDay = mWeekStartsMonday ? 1 : 7; 1184 int startWeekDay = mWeekStartsMonday ? 1 : 7;
1185 1185
1186 while( KOGlobals::self()->calendarSystem()->dayOfWeek(mStartDate) != startWeekDay ) { 1186 while( KOGlobals::self()->calendarSystem()->dayOfWeek(mStartDate) != startWeekDay ) {
1187 mStartDate = mStartDate.addDays( -1 ); 1187 mStartDate = mStartDate.addDays( -1 );
1188 } 1188 }
1189 1189
1190 bool primary = false; 1190 bool primary = false;
1191 uint i; 1191 uint i;
1192 for( i = 0; i < (*cells).size(); ++i ) { 1192 for( i = 0; i < (*cells).size(); ++i ) {
1193 QDate date = mStartDate.addDays( i ); 1193 QDate date = mStartDate.addDays( i );
1194 (*cells)[i]->setDate( date ); 1194 (*cells)[i]->setDate( date );
1195 1195
1196#ifndef KORG_NOPLUGINS 1196#ifndef KORG_NOPLUGINS
1197 // add holiday, if present 1197 // add holiday, if present
1198 QString hstring(KOCore::self()->holiday(date)); 1198 QString hstring(KOCore::self()->holiday(date));
1199 (*cells)[i]->setHoliday( hstring ); 1199 (*cells)[i]->setHoliday( hstring );
1200#endif 1200#endif
1201 1201
1202 } 1202 }
1203 QDate date = mStartDate.addDays( mWeekStartsMonday ? 3 : 4 ); 1203 QDate date = mStartDate.addDays( mWeekStartsMonday ? 3 : 4 );
1204 for( i = 0; i < weekNum; ++i ) { 1204 for( i = 0; i < weekNum; ++i ) {
1205 int wno; 1205 int wno;
1206 // remember, according to ISO 8601, the first week of the year is the 1206 // remember, according to ISO 8601, the first week of the year is the
1207 // first week that contains a thursday. Thus we must subtract off 4, 1207 // first week that contains a thursday. Thus we must subtract off 4,
1208 // not just 1. 1208 // not just 1.
1209 int dayOfYear = date.dayOfYear(); 1209 int dayOfYear = date.dayOfYear();
1210 if (dayOfYear % 7 != 0) 1210 if (dayOfYear % 7 != 0)
1211 wno = dayOfYear / 7 + 1; 1211 wno = dayOfYear / 7 + 1;
1212 else 1212 else
1213 wno =dayOfYear / 7; 1213 wno =dayOfYear / 7;
1214 (*weekLabels)[i]->setWeekNum( wno ); 1214 (*weekLabels)[i]->setWeekNum( wno );
1215 date = date.addDays( 7 ); 1215 date = date.addDays( 7 );
1216 } 1216 }
1217 updateView(); 1217 updateView();
1218} 1218}
1219 1219
1220void KOMonthView::showEvents(QPtrList<Event>) 1220void KOMonthView::showEvents(QPtrList<Event>)
1221{ 1221{
1222 qDebug("KOMonthView::selectEvents is not implemented yet. "); 1222 qDebug("KOMonthView::selectEvents is not implemented yet. ");
1223} 1223}
1224 1224
1225void KOMonthView::changeEventDisplay(Event *, int) 1225void KOMonthView::changeEventDisplay(Event *, int)
1226{ 1226{
1227 // this should be re-written to be much more efficient, but this 1227 // this should be re-written to be much more efficient, but this
1228 // quick-and-dirty-hack gets the job done for right now. 1228 // quick-and-dirty-hack gets the job done for right now.
1229 updateView(); 1229 updateView();
1230} 1230}
1231 1231
1232void KOMonthView::updateView() 1232void KOMonthView::updateView()
1233{ 1233{
1234 1234
1235 if ( !updatePossible ) 1235 if ( !updatePossible )
1236 return; 1236 return;
1237 //QTime ti; 1237 //QTime ti;
1238 //ti.start(); 1238 //ti.start();
1239 clearSelection(); 1239 clearSelection();
1240 QPtrVector<MonthViewCell> *cells; 1240 QPtrVector<MonthViewCell> *cells;
1241 if ( mShowWeekView ) { 1241 if ( mShowWeekView ) {
1242 cells = &mCellsW; 1242 cells = &mCellsW;
1243 } else { 1243 } else {
1244 cells = &mCells; 1244 cells = &mCells;
1245 } 1245 }
1246#if 1 1246#if 1
1247 int i; 1247 int i;
1248 int timeSpan = (*cells).size()-1; 1248 int timeSpan = (*cells).size()-1;
1249 if ( KOPrefs::instance()->mMonthViewWeek ) 1249 if ( KOPrefs::instance()->mMonthViewWeek )
1250 timeSpan = 6; 1250 timeSpan = 6;
1251 for( i = 0; i < timeSpan + 1; ++i ) { 1251 for( i = 0; i < timeSpan + 1; ++i ) {
1252 (*cells)[i]->startUpdateCell(); 1252 (*cells)[i]->startUpdateCell();
1253 } 1253 }
1254 1254
1255 QPtrList<Event> events = calendar()->events(); 1255 QPtrList<Event> events = calendar()->events();
1256 Event *event; 1256 Event *event;
1257 QDateTime dt; 1257 QDateTime dt;
1258 bool ok; 1258 bool ok;
1259 QDate endDate = mStartDate.addDays( timeSpan ); 1259 QDate endDate = mStartDate.addDays( timeSpan );
1260 for( event = events.first(); event; event = events.next() ) { // for event 1260 for( event = events.first(); event; event = events.next() ) { // for event
1261 if ( event->doesRecur() ) { 1261 if ( event->doesRecur() ) {
1262 bool last; 1262 bool last;
1263 qDebug("********************************************** ");
1264 qDebug("Event summary: %s ", event->summary().latin1());
1265 QDateTime incidenceStart = event->recurrence()->getPreviousDateTime( QDateTime( mStartDate ) , &last ); 1263 QDateTime incidenceStart = event->recurrence()->getPreviousDateTime( QDateTime( mStartDate ) , &last );
1266 QDateTime incidenceEnd; 1264 QDateTime incidenceEnd;
1267 int eventlen = event->dtStart().date().daysTo ( event->dtEnd().date() ); 1265 int eventlen = event->dtStart().date().daysTo ( event->dtEnd().date() );
1268 qDebug("eventlen %d ", eventlen);
1269 bool invalid = false; 1266 bool invalid = false;
1270 while( true ) { 1267 while( true ) {
1271 if ( incidenceStart.isValid() ) { 1268 if ( incidenceStart.isValid() ) {
1272 incidenceEnd = incidenceStart.addDays( eventlen ); 1269 incidenceEnd = incidenceStart.addDays( eventlen );
1273 int st = incidenceStart.date().daysTo( endDate ); 1270 int st = incidenceStart.date().daysTo( endDate );
1274 if ( st >= 0 ) { // start before timeend 1271 if ( st >= 0 ) { // start before timeend
1275 int end = mStartDate.daysTo( incidenceEnd.date() ); 1272 int end = mStartDate.daysTo( incidenceEnd.date() );
1276 if ( end >= 0 ) { // end after timestart --- got one! 1273 if ( end >= 0 ) { // end after timestart --- got one!
1277 //normalize 1274 //normalize
1278 st = timeSpan - st; 1275 st = timeSpan - st;
1279 if ( st < 0 ) st = 0; 1276 if ( st < 0 ) st = 0;
1280 if ( end > timeSpan ) end = timeSpan; 1277 if ( end > timeSpan ) end = timeSpan;
1281 int iii; 1278 int iii;
1282 //qDebug("found %s %d %d ",event->summary().latin1(), st, end ); 1279 //qDebug("found %s %d %d ",event->summary().latin1(), st, end );
1283 for ( iii = st;iii<= end;++iii) 1280 for ( iii = st;iii<= end;++iii)
1284 (*cells)[iii]->insertEvent( event ); 1281 (*cells)[iii]->insertEvent( event );
1285 } 1282 }
1286 } 1283 }
1287 } else { 1284 } else {
1288 if ( invalid ) 1285 if ( invalid )
1289 break; 1286 break;
1290 invalid = true; 1287 invalid = true;
1291 qDebug("invalid %s", event->summary().latin1()); 1288 //qDebug("invalid %s", event->summary().latin1());
1292 incidenceStart = QDateTime( mStartDate ).addSecs( -2 );; 1289 incidenceStart = QDateTime( mStartDate ).addSecs( -2 );;
1293 } 1290 }
1294 if ( last ) 1291 if ( last )
1295 break; 1292 break;
1296 bool ok; 1293 bool ok;
1297 qDebug("TRY next occurence %s ", incidenceStart.toString().latin1());
1298 incidenceStart = event->getNextOccurence( incidenceStart.addSecs( 1 ) ,&ok ); 1294 incidenceStart = event->getNextOccurence( incidenceStart.addSecs( 1 ) ,&ok );
1299 if ( ! ok ) { 1295 if ( ! ok )
1300 qDebug("NOT OK ");
1301 break; 1296 break;
1302 } 1297 if ( incidenceStart.date() > endDate )
1303 if ( incidenceStart.date() > endDate ) {
1304 qDebug("incidenceStart.date() > endDate ");
1305 break; 1298 break;
1306 }
1307 qDebug("next occurence %s ", incidenceStart.toString().latin1());
1308 } 1299 }
1309 } else { // no recur 1300 } else { // no recur
1310 int st = event->dtStart().date().daysTo( endDate ); 1301 int st = event->dtStart().date().daysTo( endDate );
1311 if ( st >= 0 ) { // start before timeend 1302 if ( st >= 0 ) { // start before timeend
1312 int end = mStartDate.daysTo( event->dtEnd().date() ); 1303 int end = mStartDate.daysTo( event->dtEnd().date() );
1313 if ( end >= 0 ) { // end after timestart --- got one! 1304 if ( end >= 0 ) { // end after timestart --- got one!
1314 //normalize 1305 //normalize
1315 st = timeSpan - st; 1306 st = timeSpan - st;
1316 if ( st < 0 ) st = 0; 1307 if ( st < 0 ) st = 0;
1317 if ( end > timeSpan ) end = timeSpan; 1308 if ( end > timeSpan ) end = timeSpan;
1318 int iii; 1309 int iii;
1319 for ( iii = st;iii<= end;++iii) 1310 for ( iii = st;iii<= end;++iii)
1320 (*cells)[iii]->insertEvent( event ); 1311 (*cells)[iii]->insertEvent( event );
1321 } 1312 }
1322 } 1313 }
1323 } 1314 }
1324 } 1315 }
1325 // insert due todos 1316 // insert due todos
1326 QPtrList<Todo> todos = calendar()->todos( ); 1317 QPtrList<Todo> todos = calendar()->todos( );
1327 Todo *todo; 1318 Todo *todo;
1328 for(todo = todos.first(); todo; todo = todos.next()) { 1319 for(todo = todos.first(); todo; todo = todos.next()) {
1329 //insertTodo( todo ); 1320 //insertTodo( todo );
1330 if ( todo->hasDueDate() ) { 1321 if ( todo->hasDueDate() ) {
1331 int day = mStartDate.daysTo( todo->dtDue().date() ); 1322 int day = mStartDate.daysTo( todo->dtDue().date() );
1332 if ( day >= 0 && day < timeSpan + 1) { 1323 if ( day >= 0 && day < timeSpan + 1) {
1333 (*cells)[day]->insertTodo( todo ); 1324 (*cells)[day]->insertTodo( todo );
1334 } 1325 }
1335 } 1326 }
1336 } 1327 }
1337 1328
1338 for( i = 0; i < timeSpan+1; ++i ) { 1329 for( i = 0; i < timeSpan+1; ++i ) {
1339 (*cells)[i]->finishUpdateCell(); 1330 (*cells)[i]->finishUpdateCell();
1340 } 1331 }
1341 processSelectionChange(); 1332 processSelectionChange();
1342 (*cells)[0]->setFocus(); 1333 (*cells)[0]->setFocus();
1343 1334
1344 1335
1345#else 1336#else
1346 // old code 1337 // old code
1347 //qDebug("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ "); 1338 //qDebug("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ");
1348 int i; 1339 int i;
1349 for( i = 0; i < (*cells).count(); ++i ) { 1340 for( i = 0; i < (*cells).count(); ++i ) {
1350 (*cells)[i]->updateCell(); 1341 (*cells)[i]->updateCell();
1351 } 1342 }
1352 1343
1353 //qDebug("KOMonthView::updateView() "); 1344 //qDebug("KOMonthView::updateView() ");
1354 processSelectionChange(); 1345 processSelectionChange();
1355 // qDebug("---------------------------------------------------------------------+ "); 1346 // qDebug("---------------------------------------------------------------------+ ");
1356 (*cells)[0]->setFocus(); 1347 (*cells)[0]->setFocus();
1357#endif 1348#endif
1358 1349
1359 //qDebug("update time %d ", ti.elapsed()); 1350 //qDebug("update time %d ", ti.elapsed());
1360} 1351}
1361 1352
1362void KOMonthView::resizeEvent(QResizeEvent * e) 1353void KOMonthView::resizeEvent(QResizeEvent * e)
1363{ 1354{
1364 //qDebug("KOMonthView::resizeEvent %d %d -- %d %d ", e->size().width(), e->size().height(), e->oldSize().width(), e->oldSize().height()); 1355 //qDebug("KOMonthView::resizeEvent %d %d -- %d %d ", e->size().width(), e->size().height(), e->oldSize().width(), e->oldSize().height());
1365 computeLayout(); 1356 computeLayout();
1366 clPending = true; 1357 clPending = true;
1367 if ( mShowWeekView ) 1358 if ( mShowWeekView )
1368 mCellsW[0]->setFocus(); 1359 mCellsW[0]->setFocus();
1369 else 1360 else
1370 mCells[0]->setFocus(); 1361 mCells[0]->setFocus();
1371} 1362}
1372void KOMonthView::computeLayoutWeek() 1363void KOMonthView::computeLayoutWeek()
1373{ 1364{
1374 static int lastWid = 0; 1365 static int lastWid = 0;
1375 static int lastHei = 0; 1366 static int lastHei = 0;
1376 int daysToShow; 1367 int daysToShow;
1377 bool combinedSatSun = false; 1368 bool combinedSatSun = false;
1378 if (mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ) { 1369 if (mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ) {
1379 daysToShow = 6; 1370 daysToShow = 6;
1380 combinedSatSun = true; 1371 combinedSatSun = true;
1381 } 1372 }
1382 int tWid = topLevelWidget()->size().width(); 1373 int tWid = topLevelWidget()->size().width();
1383 int tHei = topLevelWidget()->size().height(); 1374 int tHei = topLevelWidget()->size().height();
1384 1375
1385 int wid = width();//e 1376 int wid = width();//e
1386 int hei = height()-1-mNavigatorBar->height(); 1377 int hei = height()-1-mNavigatorBar->height();
1387 1378
1388 if ( ((wid *3)/2) < tWid && (( hei *3) /2) < tHei ) 1379 if ( ((wid *3)/2) < tWid && (( hei *3) /2) < tHei )
1389 return; 1380 return;
1390 1381
1391 if ( lastWid == width() && lastHei == height() ) 1382 if ( lastWid == width() && lastHei == height() )
1392 return; 1383 return;
1393 lastWid = width(); 1384 lastWid = width();
1394 lastHei = height(); 1385 lastHei = height();
1395 1386
1396 1387
1397 if ( wid < hei ) 1388 if ( wid < hei )
1398 daysToShow = 2; 1389 daysToShow = 2;
1399 else 1390 else
1400 daysToShow = 3; 1391 daysToShow = 3;
1401 mShowSatSunComp = true; 1392 mShowSatSunComp = true;
1402 combinedSatSun = true; 1393 combinedSatSun = true;
1403 1394
1404 //qDebug("KOMonthView::computeLayout() WWW ------------------------------------ "); 1395 //qDebug("KOMonthView::computeLayout() WWW ------------------------------------ ");
1405 QFontMetrics fm ( mWeekLabels[0]->font() ); 1396 QFontMetrics fm ( mWeekLabels[0]->font() );
1406 int weeklabelwid = fm.width( "888" ); 1397 int weeklabelwid = fm.width( "888" );
1407 wid -= weeklabelwid; 1398 wid -= weeklabelwid;
1408 1399
1409 int colWid = wid / daysToShow; 1400 int colWid = wid / daysToShow;
1410 int lastCol = wid - ( colWid*6 ); 1401 int lastCol = wid - ( colWid*6 );
1411 int dayLabelHei = mDayLabelsW[0]->sizeHint().height(); 1402 int dayLabelHei = mDayLabelsW[0]->sizeHint().height();
1412 int cellHei = (hei - (5- daysToShow )*dayLabelHei) /(5- daysToShow ); 1403 int cellHei = (hei - (5- daysToShow )*dayLabelHei) /(5- daysToShow );
1413 int colModulo = wid % daysToShow; 1404 int colModulo = wid % daysToShow;
1414 int rowModulo = (hei- (5- daysToShow )*dayLabelHei) % daysToShow-1; 1405 int rowModulo = (hei- (5- daysToShow )*dayLabelHei) % daysToShow-1;
1415 //qDebug("rowmod %d ", rowModulo); 1406 //qDebug("rowmod %d ", rowModulo);
1416 int i; 1407 int i;
1417 int x,y,w,h; 1408 int x,y,w,h;
1418 x= 0; 1409 x= 0;
1419 y= 0; 1410 y= 0;
1420 w = colWid; 1411 w = colWid;
1421 h = dayLabelHei ; 1412 h = dayLabelHei ;
1422 for ( i = 0; i < 7; i++) { 1413 for ( i = 0; i < 7; i++) {
1423 if ( i && !( i % daysToShow) && i < 6) { 1414 if ( i && !( i % daysToShow) && i < 6) {
1424 y += hei/(5-daysToShow); 1415 y += hei/(5-daysToShow);
1425 x = 0; 1416 x = 0;
1426 w = colWid; 1417 w = colWid;
1427 } 1418 }
1428 if ( ((i) % daysToShow) >= daysToShow-colModulo ) { 1419 if ( ((i) % daysToShow) >= daysToShow-colModulo ) {
1429 ++w; 1420 ++w;
1430 } 1421 }
1431 if ( i >= 5 ) { 1422 if ( i >= 5 ) {
1432 mDayLabelsW[i]->setGeometry( x+weeklabelwid,y,w/2+w%2,h); 1423 mDayLabelsW[i]->setGeometry( x+weeklabelwid,y,w/2+w%2,h);
1433 x -= (w/2 ); 1424 x -= (w/2 );
1434 } 1425 }
1435 else 1426 else
1436 mDayLabelsW[i]->setGeometry( x+weeklabelwid,y,w,h); 1427 mDayLabelsW[i]->setGeometry( x+weeklabelwid,y,w,h);
1437 x += w; 1428 x += w;
1438 } 1429 }
1439 x= 0; 1430 x= 0;
1440 y= dayLabelHei; 1431 y= dayLabelHei;
1441 w = colWid; 1432 w = colWid;
1442 h = cellHei; 1433 h = cellHei;
1443 for ( i = 0; i < mCellsW.count(); ++i) { 1434 for ( i = 0; i < mCellsW.count(); ++i) {
1444 if ( i > 6 ) { 1435 if ( i > 6 ) {
1445 mCellsW[i]->hide(); 1436 mCellsW[i]->hide();
1446 continue; 1437 continue;
1447 } 1438 }
1448 1439
1449 w = colWid; 1440 w = colWid;
1450 if ( ((i) % daysToShow) >= daysToShow-colModulo ) { 1441 if ( ((i) % daysToShow) >= daysToShow-colModulo ) {
1451 ++w; 1442 ++w;
1452 } 1443 }
1453 if ( i == (daysToShow-1-rowModulo)*7) 1444 if ( i == (daysToShow-1-rowModulo)*7)
1454 ++h; 1445 ++h;
1455 1446
1456 if ( i >= 5 ) { 1447 if ( i >= 5 ) {
1457 if ( i ==5 ) { 1448 if ( i ==5 ) {
1458 mCellsW[i]->setGeometry ( x+weeklabelwid,y,w,h/2 ); 1449 mCellsW[i]->setGeometry ( x+weeklabelwid,y,w,h/2 );
1459 x -= w ;y += h/2; 1450 x -= w ;y += h/2;
1460 } else { 1451 } else {
1461 if ( ((i-1) % daysToShow) >= daysToShow-colModulo ) { 1452 if ( ((i-1) % daysToShow) >= daysToShow-colModulo ) {
1462 ++w; 1453 ++w;
1463 } 1454 }
1464 mCellsW[i]->setGeometry ( x+weeklabelwid,y,w,h-h/2 ); 1455 mCellsW[i]->setGeometry ( x+weeklabelwid,y,w,h-h/2 );
1465 y -= h/2; 1456 y -= h/2;
1466 } 1457 }
1467 } else 1458 } else
1468 mCellsW[i]->setGeometry ( x+weeklabelwid,y,w,h ); 1459 mCellsW[i]->setGeometry ( x+weeklabelwid,y,w,h );
1469 1460
1470 1461
1471 x += w; 1462 x += w;
1472 if ( x + w/2 > wid ) { 1463 if ( x + w/2 > wid ) {
1473 x = 0; 1464 x = 0;
1474 y += h+dayLabelHei ; 1465 y += h+dayLabelHei ;
1475 } 1466 }
1476 } 1467 }
1477 y= dayLabelHei; 1468 y= dayLabelHei;
1478 h = cellHei ; 1469 h = cellHei ;
1479 mWeekLabelsW[0]->setGeometry( 0,y,weeklabelwid,hei-dayLabelHei); 1470 mWeekLabelsW[0]->setGeometry( 0,y,weeklabelwid,hei-dayLabelHei);
1480 mWeekLabelsW[1]->setGeometry( 0,0,weeklabelwid,dayLabelHei); 1471 mWeekLabelsW[1]->setGeometry( 0,0,weeklabelwid,dayLabelHei);
1481 // qDebug("RRRRRRRRRRRRR %d %d old %d %d", e->size().width(),e->size().height() , e->oldSize().width(),e->oldSize().height()); 1472 // qDebug("RRRRRRRRRRRRR %d %d old %d %d", e->size().width(),e->size().height() , e->oldSize().width(),e->oldSize().height());
1482 //qDebug("parent %d %d ", topLevelWidget()->size().width(), topLevelWidget()->size().height()); 1473 //qDebug("parent %d %d ", topLevelWidget()->size().width(), topLevelWidget()->size().height());
1483 mShortDayLabelsW = mDayLabelsW[0]->width()-2 < mWidthLongDayLabel ; 1474 mShortDayLabelsW = mDayLabelsW[0]->width()-2 < mWidthLongDayLabel ;
1484 updateDayLabels(); 1475 updateDayLabels();
1485 //bool forceUpdate = !updatePossible; 1476 //bool forceUpdate = !updatePossible;
1486 updatePossible = true; 1477 updatePossible = true;
1487 //mWeekLabels[mNumWeeks]->setText( i18n("M")); 1478 //mWeekLabels[mNumWeeks]->setText( i18n("M"));
1488 //if ( forceUpdate ) 1479 //if ( forceUpdate )
1489 // updateView(); 1480 // updateView();
1490} 1481}
1491void KOMonthView::computeLayout() 1482void KOMonthView::computeLayout()
1492{ 1483{
1493 1484
1494 1485
1495 static int lastWid = 0; 1486 static int lastWid = 0;
1496 static int lastHei = 0; 1487 static int lastHei = 0;
1497 1488
1498 if ( mShowWeekView ){ 1489 if ( mShowWeekView ){
1499 computeLayoutWeek(); 1490 computeLayoutWeek();
1500 return; 1491 return;
1501 } 1492 }
1502 int daysToShow = 7; 1493 int daysToShow = 7;
1503 bool combinedSatSun = false; 1494 bool combinedSatSun = false;
1504 if (mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ) { 1495 if (mShowSatSunComp = KOPrefs::instance()->mMonthViewSatSunTog ) {
1505 daysToShow = 6; 1496 daysToShow = 6;
1506 combinedSatSun = true; 1497 combinedSatSun = true;
1507 } 1498 }
1508 int tWid = topLevelWidget()->size().width(); 1499 int tWid = topLevelWidget()->size().width();
1509 int tHei = topLevelWidget()->size().height(); 1500 int tHei = topLevelWidget()->size().height();
1510 1501
1511 int wid = width();//e 1502 int wid = width();//e
1512 int hei = height()-1-mNavigatorBar->height(); 1503 int hei = height()-1-mNavigatorBar->height();
1513 1504
1514 if ( ((wid *3)/2) < tWid && (( hei *3) /2) < tHei ) { 1505 if ( ((wid *3)/2) < tWid && (( hei *3) /2) < tHei ) {
1515 return; 1506 return;
1516 } 1507 }
1517 if ( lastWid == width() && lastHei == height() ){ 1508 if ( lastWid == width() && lastHei == height() ){
1518 return; 1509 return;
1519 } 1510 }
1520 1511
1521 lastWid = width(); 1512 lastWid = width();
1522 lastHei = height(); 1513 lastHei = height();
1523 //qDebug("KOMonthView::computeLayout() MMM ------------------------------------ "); 1514 //qDebug("KOMonthView::computeLayout() MMM ------------------------------------ ");
1524 QFontMetrics fm ( mWeekLabels[0]->font() ); 1515 QFontMetrics fm ( mWeekLabels[0]->font() );
1525 int weeklabelwid = fm.width( "888" ); 1516 int weeklabelwid = fm.width( "888" );
1526 wid -= weeklabelwid; 1517 wid -= weeklabelwid;
1527 1518
1528 int colWid = wid / daysToShow; 1519 int colWid = wid / daysToShow;
1529 int lastCol = wid - ( colWid*6 ); 1520 int lastCol = wid - ( colWid*6 );
1530 int dayLabelHei = mDayLabels[0]->sizeHint().height(); 1521 int dayLabelHei = mDayLabels[0]->sizeHint().height();
1531 int cellHei = (hei - dayLabelHei) /6; 1522 int cellHei = (hei - dayLabelHei) /6;
1532 int colModulo = wid % daysToShow; 1523 int colModulo = wid % daysToShow;
1533 int rowModulo = (hei- dayLabelHei) % 6; 1524 int rowModulo = (hei- dayLabelHei) % 6;
1534 //qDebug("rowmod %d ", rowModulo); 1525 //qDebug("rowmod %d ", rowModulo);
1535 int i; 1526 int i;
1536 int x,y,w,h; 1527 int x,y,w,h;
1537 x= 0; 1528 x= 0;
1538 y= 0; 1529 y= 0;
1539 w = colWid; 1530 w = colWid;
1540 h = dayLabelHei ; 1531 h = dayLabelHei ;
1541 for ( i = 0; i < 7; i++) { 1532 for ( i = 0; i < 7; i++) {
1542 if ( i == daysToShow-colModulo ) 1533 if ( i == daysToShow-colModulo )
1543 ++w; 1534 ++w;
1544 if ( combinedSatSun ) { 1535 if ( combinedSatSun ) {
1545 if ( i >= daysToShow-1 ) { 1536 if ( i >= daysToShow-1 ) {
1546 mDayLabels[i]->setGeometry( x+weeklabelwid,y,w/2,h); 1537 mDayLabels[i]->setGeometry( x+weeklabelwid,y,w/2,h);
1547 x -= w/2 ; 1538 x -= w/2 ;
1548 } 1539 }
1549 else 1540 else
1550 mDayLabels[i]->setGeometry( x+weeklabelwid,y,w,h); 1541 mDayLabels[i]->setGeometry( x+weeklabelwid,y,w,h);
1551 } else 1542 } else
1552 mDayLabels[i]->setGeometry( x+weeklabelwid,y,w,h); 1543 mDayLabels[i]->setGeometry( x+weeklabelwid,y,w,h);
1553 x += w; 1544 x += w;
1554 } 1545 }
1555 x= 0; 1546 x= 0;
1556 y= dayLabelHei; 1547 y= dayLabelHei;
1557 w = colWid; 1548 w = colWid;
1558 h = cellHei ; 1549 h = cellHei ;
1559 for ( i = 0; i < mCells.count(); ++i) { 1550 for ( i = 0; i < mCells.count(); ++i) {
1560 //qDebug("iii %d ", i); 1551 //qDebug("iii %d ", i);
1561 w = colWid; 1552 w = colWid;
1562 if ( ((i) % 7) >= 7-colModulo ) { 1553 if ( ((i) % 7) >= 7-colModulo ) {
1563 ++w; 1554 ++w;
1564 } 1555 }
1565 if ( i == (6-rowModulo)*7) 1556 if ( i == (6-rowModulo)*7)
1566 ++h; 1557 ++h;
1567 if ( combinedSatSun ) { 1558 if ( combinedSatSun ) {
1568 if ( (i)%7 >= daysToShow-1 ) { 1559 if ( (i)%7 >= daysToShow-1 ) {
1569 if ( (i)%7 == daysToShow-1 ) { 1560 if ( (i)%7 == daysToShow-1 ) {
1570 mCells[i]->setGeometry ( x+weeklabelwid,y,w,h/2 ); 1561 mCells[i]->setGeometry ( x+weeklabelwid,y,w,h/2 );
1571 x -= w ;y += h/2; 1562 x -= w ;y += h/2;
1572 } else { 1563 } else {
1573 mCells[i]->setGeometry ( x+weeklabelwid,y,w,h-h/2 ); 1564 mCells[i]->setGeometry ( x+weeklabelwid,y,w,h-h/2 );
1574 y -= h/2; 1565 y -= h/2;
1575 } 1566 }
1576 } else 1567 } else
1577 mCells[i]->setGeometry ( x+weeklabelwid,y,w,h ); 1568 mCells[i]->setGeometry ( x+weeklabelwid,y,w,h );
1578 1569
1579 } 1570 }
1580 else 1571 else
1581 mCells[i]->setGeometry ( x+weeklabelwid,y,w,h ); 1572 mCells[i]->setGeometry ( x+weeklabelwid,y,w,h );
1582 x += w; 1573 x += w;
1583 if ( x + w/2 > wid ) { 1574 if ( x + w/2 > wid ) {
1584 x = 0; 1575 x = 0;
1585 y += h; 1576 y += h;
1586 } 1577 }
1587 } 1578 }
1588 y= dayLabelHei; 1579 y= dayLabelHei;
1589 h = cellHei ; 1580 h = cellHei ;
1590 for ( i = 0; i < 6; i++) { 1581 for ( i = 0; i < 6; i++) {
1591 if ( i == (6-rowModulo)) 1582 if ( i == (6-rowModulo))
1592 ++h; 1583 ++h;
1593 mWeekLabels[i]->setGeometry( 0,y,weeklabelwid,h); 1584 mWeekLabels[i]->setGeometry( 0,y,weeklabelwid,h);
1594 y += h; 1585 y += h;
1595 } 1586 }
1596 mWeekLabels[6]->setGeometry( 0,0,weeklabelwid,dayLabelHei); 1587 mWeekLabels[6]->setGeometry( 0,0,weeklabelwid,dayLabelHei);
1597 // qDebug("RRRRRRRRRRRRR %d %d old %d %d", e->size().width(),e->size().height() , e->oldSize().width(),e->oldSize().height()); 1588 // qDebug("RRRRRRRRRRRRR %d %d old %d %d", e->size().width(),e->size().height() , e->oldSize().width(),e->oldSize().height());
1598 //qDebug("parent %d %d ", topLevelWidget()->size().width(), topLevelWidget()->size().height()); 1589 //qDebug("parent %d %d ", topLevelWidget()->size().width(), topLevelWidget()->size().height());
1599 mShortDayLabelsM = mDayLabels[0]->width()-2 < mWidthLongDayLabel ; 1590 mShortDayLabelsM = mDayLabels[0]->width()-2 < mWidthLongDayLabel ;
1600 updateDayLabels(); 1591 updateDayLabels();
1601 //bool forceUpdate = !updatePossible; 1592 //bool forceUpdate = !updatePossible;
1602 updatePossible = true; 1593 updatePossible = true;
1603 //mWeekLabels[mNumWeeks]->setText( i18n("W")); 1594 //mWeekLabels[mNumWeeks]->setText( i18n("W"));
1604} 1595}
1605 1596
1606void KOMonthView::showContextMenu( Incidence *incidence ) 1597void KOMonthView::showContextMenu( Incidence *incidence )
1607{ 1598{
1608 mContextMenu->showIncidencePopup(incidence); 1599 mContextMenu->showIncidencePopup(incidence);
1609 /* 1600 /*
1610 if( incidence && incidence->type() == "Event" ) { 1601 if( incidence && incidence->type() == "Event" ) {
1611 Event *event = static_cast<Event *>(incidence); 1602 Event *event = static_cast<Event *>(incidence);
1612 mContextMenu->showEventPopup(event); 1603 mContextMenu->showEventPopup(event);
1613 } else { 1604 } else {
1614 kdDebug() << "MonthView::showContextMenu(): cast failed." << endl; 1605 kdDebug() << "MonthView::showContextMenu(): cast failed." << endl;
1615 } 1606 }
1616 */ 1607 */
1617} 1608}
1618MonthViewCell * KOMonthView::selectedCell( ) 1609MonthViewCell * KOMonthView::selectedCell( )
1619{ 1610{
1620 return mSelectedCell; 1611 return mSelectedCell;
1621} 1612}
1622void KOMonthView::setSelectedCell( MonthViewCell *cell ) 1613void KOMonthView::setSelectedCell( MonthViewCell *cell )
1623{ 1614{
1624 //qDebug("KOMonthView::setSelectedCell "); 1615 //qDebug("KOMonthView::setSelectedCell ");
1625 if ( mSelectedCell && mSelectedCell != cell ) { 1616 if ( mSelectedCell && mSelectedCell != cell ) {
1626 MonthViewCell * mvc = mSelectedCell; 1617 MonthViewCell * mvc = mSelectedCell;
1627 mSelectedCell = cell; 1618 mSelectedCell = cell;
1628 mvc->deselect(); 1619 mvc->deselect();
1629 } else 1620 } else
1630 mSelectedCell = cell; 1621 mSelectedCell = cell;
1631 // if ( mSelectedCell ) 1622 // if ( mSelectedCell )
1632 // mSelectedCell->select(); 1623 // mSelectedCell->select();
1633 if ( !mSelectedCell ) 1624 if ( !mSelectedCell )
1634 emit incidenceSelected( 0 ); 1625 emit incidenceSelected( 0 );
1635 else 1626 else
1636 emit incidenceSelected( mSelectedCell->selectedIncidence() ); 1627 emit incidenceSelected( mSelectedCell->selectedIncidence() );
1637} 1628}
1638 1629
1639void KOMonthView::processSelectionChange() 1630void KOMonthView::processSelectionChange()
1640{ 1631{
1641 QPtrList<Incidence> incidences = selectedIncidences(); 1632 QPtrList<Incidence> incidences = selectedIncidences();
1642 if (incidences.count() > 0) { 1633 if (incidences.count() > 0) {
1643 emit incidenceSelected( incidences.first() ); 1634 emit incidenceSelected( incidences.first() );
1644 } else { 1635 } else {
1645 emit incidenceSelected( 0 ); 1636 emit incidenceSelected( 0 );
1646 clearSelection(); 1637 clearSelection();
1647 } 1638 }
1648} 1639}
1649 1640
1650void KOMonthView::clearSelection() 1641void KOMonthView::clearSelection()
1651{ 1642{
1652 if ( mSelectedCell ) { 1643 if ( mSelectedCell ) {
1653 mSelectedCell->deselect(); 1644 mSelectedCell->deselect();
1654 mSelectedCell = 0; 1645 mSelectedCell = 0;
1655 } 1646 }
1656} 1647}
1657void KOMonthView::keyPressEvent ( QKeyEvent * e ) 1648void KOMonthView::keyPressEvent ( QKeyEvent * e )
1658{ 1649{
1659 //qDebug("KOMonthView::keyPressEvent "); 1650 //qDebug("KOMonthView::keyPressEvent ");
1660 switch(e->key()) { 1651 switch(e->key()) {
1661 case Key_Up: 1652 case Key_Up:
1662 { 1653 {
1663 if ( mShowWeekView ) { 1654 if ( mShowWeekView ) {
1664 mCellsW[0]->setFocus(); 1655 mCellsW[0]->setFocus();
1665 emit selectWeekNum ( currentWeek() - 1 ); 1656 emit selectWeekNum ( currentWeek() - 1 );
1666 } 1657 }
1667 else { 1658 else {
1668 mCells[0]->setFocus(); 1659 mCells[0]->setFocus();
1669 emit prevMonth(); 1660 emit prevMonth();
1670 } 1661 }
1671 } 1662 }
1672 e->accept(); 1663 e->accept();
1673 break; 1664 break;
1674 case Key_Down: 1665 case Key_Down:
1675 { 1666 {
1676 if ( mShowWeekView ) { 1667 if ( mShowWeekView ) {
1677 mCellsW[0]->setFocus(); 1668 mCellsW[0]->setFocus();
1678 emit selectWeekNum ( currentWeek() +1); 1669 emit selectWeekNum ( currentWeek() +1);
1679 } 1670 }
1680 else { 1671 else {
1681 mCells[0]->setFocus(); 1672 mCells[0]->setFocus();
1682 emit nextMonth(); 1673 emit nextMonth();
1683 } 1674 }
1684 1675
1685 } 1676 }
1686 e->accept(); 1677 e->accept();
1687 break; 1678 break;
1688 case Key_Return: 1679 case Key_Return:
1689 case Key_Enter: 1680 case Key_Enter:
1690 { 1681 {
1691 selectInternalWeekNum ( currentWeek() ); 1682 selectInternalWeekNum ( currentWeek() );
1692 } 1683 }
1693 e->accept(); 1684 e->accept();
1694 break; 1685 break;
1695 case Key_D: 1686 case Key_D:
1696 if ( mSelectedCell ) { 1687 if ( mSelectedCell ) {
1697 mSelectedCell->showDay(); 1688 mSelectedCell->showDay();
1698 e->accept(); 1689 e->accept();
1699 } else { 1690 } else {
1700 e->ignore(); 1691 e->ignore();
1701 } 1692 }
1702 break; 1693 break;
1703 default: 1694 default:
1704 e->ignore(); 1695 e->ignore();
1705 break; 1696 break;
1706 } 1697 }
1707} 1698}
diff --git a/libkcal/recurrence.cpp b/libkcal/recurrence.cpp
index 8a175c9..6ee5499 100644
--- a/libkcal/recurrence.cpp
+++ b/libkcal/recurrence.cpp
@@ -467,1337 +467,1334 @@ void Recurrence::setFloats(bool f)
467 case rHourly: 467 case rHourly:
468 default: 468 default:
469 return; // can't set sub-daily to floating 469 return; // can't set sub-daily to floating
470 } 470 }
471 mFloats = f; 471 mFloats = f;
472 if (f) { 472 if (f) {
473 mRecurStart.setTime(QTime(0,0,0)); 473 mRecurStart.setTime(QTime(0,0,0));
474 rEndDateTime.setTime(QTime(0,0,0)); 474 rEndDateTime.setTime(QTime(0,0,0));
475 } 475 }
476} 476}
477 477
478int Recurrence::frequency() const 478int Recurrence::frequency() const
479{ 479{
480 return rFreq; 480 return rFreq;
481} 481}
482 482
483int Recurrence::duration() const 483int Recurrence::duration() const
484{ 484{
485 return rDuration; 485 return rDuration;
486} 486}
487 487
488void Recurrence::setDuration(int _rDuration) 488void Recurrence::setDuration(int _rDuration)
489{ 489{
490 if (mRecurReadOnly) return; 490 if (mRecurReadOnly) return;
491 if (_rDuration > 0) { 491 if (_rDuration > 0) {
492 rDuration = _rDuration; 492 rDuration = _rDuration;
493 // Compatibility mode is only needed when reading the calendar in ICalFormatImpl, 493 // Compatibility mode is only needed when reading the calendar in ICalFormatImpl,
494 // so explicitly setting the duration means no backwards compatibility is needed. 494 // so explicitly setting the duration means no backwards compatibility is needed.
495 mCompatDuration = 0; 495 mCompatDuration = 0;
496 } 496 }
497} 497}
498 498
499QString Recurrence::endDateStr(bool shortfmt) const 499QString Recurrence::endDateStr(bool shortfmt) const
500{ 500{
501 return KGlobal::locale()->formatDate(rEndDateTime.date(),shortfmt); 501 return KGlobal::locale()->formatDate(rEndDateTime.date(),shortfmt);
502} 502}
503 503
504const QBitArray &Recurrence::days() const 504const QBitArray &Recurrence::days() const
505{ 505{
506 return rDays; 506 return rDays;
507} 507}
508 508
509const QPtrList<Recurrence::rMonthPos> &Recurrence::monthPositions() const 509const QPtrList<Recurrence::rMonthPos> &Recurrence::monthPositions() const
510{ 510{
511 return rMonthPositions; 511 return rMonthPositions;
512} 512}
513 513
514const QPtrList<Recurrence::rMonthPos> &Recurrence::yearMonthPositions() const 514const QPtrList<Recurrence::rMonthPos> &Recurrence::yearMonthPositions() const
515{ 515{
516 return rMonthPositions; 516 return rMonthPositions;
517} 517}
518 518
519const QPtrList<int> &Recurrence::monthDays() const 519const QPtrList<int> &Recurrence::monthDays() const
520{ 520{
521 return rMonthDays; 521 return rMonthDays;
522} 522}
523 523
524void Recurrence::setMinutely(int _rFreq, int _rDuration) 524void Recurrence::setMinutely(int _rFreq, int _rDuration)
525{ 525{
526 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 526 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
527 return; 527 return;
528 setDailySub(rMinutely, _rFreq, _rDuration); 528 setDailySub(rMinutely, _rFreq, _rDuration);
529} 529}
530 530
531void Recurrence::setMinutely(int _rFreq, const QDateTime &_rEndDateTime) 531void Recurrence::setMinutely(int _rFreq, const QDateTime &_rEndDateTime)
532{ 532{
533 if (mRecurReadOnly) return; 533 if (mRecurReadOnly) return;
534 rEndDateTime = _rEndDateTime; 534 rEndDateTime = _rEndDateTime;
535 setDailySub(rMinutely, _rFreq, 0); 535 setDailySub(rMinutely, _rFreq, 0);
536} 536}
537 537
538void Recurrence::setHourly(int _rFreq, int _rDuration) 538void Recurrence::setHourly(int _rFreq, int _rDuration)
539{ 539{
540 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 540 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
541 return; 541 return;
542 setDailySub(rHourly, _rFreq, _rDuration); 542 setDailySub(rHourly, _rFreq, _rDuration);
543} 543}
544 544
545void Recurrence::setHourly(int _rFreq, const QDateTime &_rEndDateTime) 545void Recurrence::setHourly(int _rFreq, const QDateTime &_rEndDateTime)
546{ 546{
547 if (mRecurReadOnly) return; 547 if (mRecurReadOnly) return;
548 rEndDateTime = _rEndDateTime; 548 rEndDateTime = _rEndDateTime;
549 setDailySub(rHourly, _rFreq, 0); 549 setDailySub(rHourly, _rFreq, 0);
550} 550}
551 551
552void Recurrence::setDaily(int _rFreq, int _rDuration) 552void Recurrence::setDaily(int _rFreq, int _rDuration)
553{ 553{
554 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 554 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
555 return; 555 return;
556 setDailySub(rDaily, _rFreq, _rDuration); 556 setDailySub(rDaily, _rFreq, _rDuration);
557} 557}
558 558
559void Recurrence::setDaily(int _rFreq, const QDate &_rEndDate) 559void Recurrence::setDaily(int _rFreq, const QDate &_rEndDate)
560{ 560{
561 if (mRecurReadOnly) return; 561 if (mRecurReadOnly) return;
562 rEndDateTime.setDate(_rEndDate); 562 rEndDateTime.setDate(_rEndDate);
563 rEndDateTime.setTime(mRecurStart.time()); 563 rEndDateTime.setTime(mRecurStart.time());
564 setDailySub(rDaily, _rFreq, 0); 564 setDailySub(rDaily, _rFreq, 0);
565} 565}
566 566
567void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays, 567void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays,
568 int _rDuration, int _rWeekStart) 568 int _rDuration, int _rWeekStart)
569{ 569{
570 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 570 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
571 return; 571 return;
572 recurs = rWeekly; 572 recurs = rWeekly;
573 573
574 rFreq = _rFreq; 574 rFreq = _rFreq;
575 rDays = _rDays; 575 rDays = _rDays;
576 rWeekStart = _rWeekStart; 576 rWeekStart = _rWeekStart;
577 rDuration = _rDuration; 577 rDuration = _rDuration;
578 if (mCompatVersion < 310 && _rDuration > 0) { 578 if (mCompatVersion < 310 && _rDuration > 0) {
579 // Backwards compatibility for KDE < 3.1. 579 // Backwards compatibility for KDE < 3.1.
580 // rDuration was set to the number of time periods to recur, 580 // rDuration was set to the number of time periods to recur,
581 // with week start always on a Monday. 581 // with week start always on a Monday.
582 // Convert this to the number of occurrences. 582 // Convert this to the number of occurrences.
583 mCompatDuration = _rDuration; 583 mCompatDuration = _rDuration;
584 int weeks = ((mCompatDuration-1+mRecurExDatesCount)*7) + (7 - mRecurStart.date().dayOfWeek()); 584 int weeks = ((mCompatDuration-1+mRecurExDatesCount)*7) + (7 - mRecurStart.date().dayOfWeek());
585 QDate end(mRecurStart.date().addDays(weeks * rFreq)); 585 QDate end(mRecurStart.date().addDays(weeks * rFreq));
586 rDuration = INT_MAX; // ensure that weeklyCalc() does its job correctly 586 rDuration = INT_MAX; // ensure that weeklyCalc() does its job correctly
587 rDuration = weeklyCalc(COUNT_TO_DATE, end); 587 rDuration = weeklyCalc(COUNT_TO_DATE, end);
588 } else { 588 } else {
589 mCompatDuration = 0; 589 mCompatDuration = 0;
590 } 590 }
591 rMonthPositions.clear(); 591 rMonthPositions.clear();
592 rMonthDays.clear(); 592 rMonthDays.clear();
593 if (mParent) mParent->updated(); 593 if (mParent) mParent->updated();
594} 594}
595 595
596void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays, 596void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays,
597 const QDate &_rEndDate, int _rWeekStart) 597 const QDate &_rEndDate, int _rWeekStart)
598{ 598{
599 if (mRecurReadOnly) return; 599 if (mRecurReadOnly) return;
600 recurs = rWeekly; 600 recurs = rWeekly;
601 601
602 rFreq = _rFreq; 602 rFreq = _rFreq;
603 rDays = _rDays; 603 rDays = _rDays;
604 rWeekStart = _rWeekStart; 604 rWeekStart = _rWeekStart;
605 rEndDateTime.setDate(_rEndDate); 605 rEndDateTime.setDate(_rEndDate);
606 rEndDateTime.setTime(mRecurStart.time()); 606 rEndDateTime.setTime(mRecurStart.time());
607 rDuration = 0; // set to 0 because there is an end date 607 rDuration = 0; // set to 0 because there is an end date
608 mCompatDuration = 0; 608 mCompatDuration = 0;
609 rMonthPositions.clear(); 609 rMonthPositions.clear();
610 rMonthDays.clear(); 610 rMonthDays.clear();
611 rYearNums.clear(); 611 rYearNums.clear();
612 if (mParent) mParent->updated(); 612 if (mParent) mParent->updated();
613} 613}
614 614
615void Recurrence::setMonthly(short type, int _rFreq, int _rDuration) 615void Recurrence::setMonthly(short type, int _rFreq, int _rDuration)
616{ 616{
617 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 617 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
618 return; 618 return;
619 recurs = type; 619 recurs = type;
620 620
621 rFreq = _rFreq; 621 rFreq = _rFreq;
622 rDuration = _rDuration; 622 rDuration = _rDuration;
623 if (mCompatVersion < 310) 623 if (mCompatVersion < 310)
624 mCompatDuration = (_rDuration > 0) ? _rDuration : 0; 624 mCompatDuration = (_rDuration > 0) ? _rDuration : 0;
625 rYearNums.clear(); 625 rYearNums.clear();
626 if (mParent) mParent->updated(); 626 if (mParent) mParent->updated();
627} 627}
628 628
629void Recurrence::setMonthly(short type, int _rFreq, 629void Recurrence::setMonthly(short type, int _rFreq,
630 const QDate &_rEndDate) 630 const QDate &_rEndDate)
631{ 631{
632 if (mRecurReadOnly) return; 632 if (mRecurReadOnly) return;
633 recurs = type; 633 recurs = type;
634 634
635 rFreq = _rFreq; 635 rFreq = _rFreq;
636 rEndDateTime.setDate(_rEndDate); 636 rEndDateTime.setDate(_rEndDate);
637 rEndDateTime.setTime(mRecurStart.time()); 637 rEndDateTime.setTime(mRecurStart.time());
638 rDuration = 0; // set to 0 because there is an end date 638 rDuration = 0; // set to 0 because there is an end date
639 mCompatDuration = 0; 639 mCompatDuration = 0;
640 rYearNums.clear(); 640 rYearNums.clear();
641 if (mParent) mParent->updated(); 641 if (mParent) mParent->updated();
642} 642}
643 643
644void Recurrence::addMonthlyPos(short _rPos, const QBitArray &_rDays) 644void Recurrence::addMonthlyPos(short _rPos, const QBitArray &_rDays)
645{ 645{
646 if (recurs == rMonthlyPos) 646 if (recurs == rMonthlyPos)
647 addMonthlyPos_(_rPos, _rDays); 647 addMonthlyPos_(_rPos, _rDays);
648} 648}
649 649
650void Recurrence::addMonthlyPos_(short _rPos, const QBitArray &_rDays) 650void Recurrence::addMonthlyPos_(short _rPos, const QBitArray &_rDays)
651{ 651{
652 if (mRecurReadOnly 652 if (mRecurReadOnly
653 || _rPos == 0 || _rPos > 5 || _rPos < -5) // invalid week number 653 || _rPos == 0 || _rPos > 5 || _rPos < -5) // invalid week number
654 return; 654 return;
655 655
656 for (rMonthPos* it = rMonthPositions.first(); it; it = rMonthPositions.next()) { 656 for (rMonthPos* it = rMonthPositions.first(); it; it = rMonthPositions.next()) {
657 int itPos = it->negative ? -it->rPos : it->rPos; 657 int itPos = it->negative ? -it->rPos : it->rPos;
658 if (_rPos == itPos) { 658 if (_rPos == itPos) {
659 // This week is already in the list. 659 // This week is already in the list.
660 // Combine the specified days with those in the list. 660 // Combine the specified days with those in the list.
661 it->rDays |= _rDays; 661 it->rDays |= _rDays;
662 if (mParent) mParent->updated(); 662 if (mParent) mParent->updated();
663 return; 663 return;
664 } 664 }
665 } 665 }
666 // Add the new position to the list 666 // Add the new position to the list
667 rMonthPos *tmpPos = new rMonthPos; 667 rMonthPos *tmpPos = new rMonthPos;
668 if (_rPos > 0) { 668 if (_rPos > 0) {
669 tmpPos->rPos = _rPos; 669 tmpPos->rPos = _rPos;
670 tmpPos->negative = false; 670 tmpPos->negative = false;
671 } else { 671 } else {
672 tmpPos->rPos = -_rPos; // take abs() 672 tmpPos->rPos = -_rPos; // take abs()
673 tmpPos->negative = true; 673 tmpPos->negative = true;
674 } 674 }
675 tmpPos->rDays = _rDays; 675 tmpPos->rDays = _rDays;
676 tmpPos->rDays.detach(); 676 tmpPos->rDays.detach();
677 rMonthPositions.append(tmpPos); 677 rMonthPositions.append(tmpPos);
678 678
679 if (mCompatVersion < 310 && mCompatDuration > 0) { 679 if (mCompatVersion < 310 && mCompatDuration > 0) {
680 // Backwards compatibility for KDE < 3.1. 680 // Backwards compatibility for KDE < 3.1.
681 // rDuration was set to the number of time periods to recur. 681 // rDuration was set to the number of time periods to recur.
682 // Convert this to the number of occurrences. 682 // Convert this to the number of occurrences.
683 int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq; 683 int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq;
684 int month = mRecurStart.date().month() - 1 + monthsAhead; 684 int month = mRecurStart.date().month() - 1 + monthsAhead;
685 QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31); 685 QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31);
686 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly 686 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly
687 rDuration = recurCalc(COUNT_TO_DATE, end); 687 rDuration = recurCalc(COUNT_TO_DATE, end);
688 } 688 }
689 689
690 if (mParent) mParent->updated(); 690 if (mParent) mParent->updated();
691} 691}
692 692
693void Recurrence::addMonthlyDay(short _rDay) 693void Recurrence::addMonthlyDay(short _rDay)
694{ 694{
695 if (mRecurReadOnly || (recurs != rMonthlyDay && recurs != rYearlyMonth) 695 if (mRecurReadOnly || (recurs != rMonthlyDay && recurs != rYearlyMonth)
696 || _rDay == 0 || _rDay > 31 || _rDay < -31) // invalid day number 696 || _rDay == 0 || _rDay > 31 || _rDay < -31) // invalid day number
697 return; 697 return;
698 for (int* it = rMonthDays.first(); it; it = rMonthDays.next()) { 698 for (int* it = rMonthDays.first(); it; it = rMonthDays.next()) {
699 if (_rDay == *it) 699 if (_rDay == *it)
700 return; // this day is already in the list - avoid duplication 700 return; // this day is already in the list - avoid duplication
701 } 701 }
702 int *tmpDay = new int; 702 int *tmpDay = new int;
703 *tmpDay = _rDay; 703 *tmpDay = _rDay;
704 rMonthDays.append(tmpDay); 704 rMonthDays.append(tmpDay);
705 705
706 if (mCompatVersion < 310 && mCompatDuration > 0) { 706 if (mCompatVersion < 310 && mCompatDuration > 0) {
707 // Backwards compatibility for KDE < 3.1. 707 // Backwards compatibility for KDE < 3.1.
708 // rDuration was set to the number of time periods to recur. 708 // rDuration was set to the number of time periods to recur.
709 // Convert this to the number of occurrences. 709 // Convert this to the number of occurrences.
710 int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq; 710 int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq;
711 int month = mRecurStart.date().month() - 1 + monthsAhead; 711 int month = mRecurStart.date().month() - 1 + monthsAhead;
712 QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31); 712 QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31);
713 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly 713 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly
714 rDuration = recurCalc(COUNT_TO_DATE, end); 714 rDuration = recurCalc(COUNT_TO_DATE, end);
715 } 715 }
716 716
717 if (mParent) mParent->updated(); 717 if (mParent) mParent->updated();
718} 718}
719 719
720void Recurrence::setYearly(int type, int _rFreq, int _rDuration) 720void Recurrence::setYearly(int type, int _rFreq, int _rDuration)
721{ 721{
722 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 722 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
723 return; 723 return;
724 if (mCompatVersion < 310) 724 if (mCompatVersion < 310)
725 mCompatDuration = (_rDuration > 0) ? _rDuration : 0; 725 mCompatDuration = (_rDuration > 0) ? _rDuration : 0;
726 setYearly_(type, mFeb29YearlyDefaultType, _rFreq, _rDuration); 726 setYearly_(type, mFeb29YearlyDefaultType, _rFreq, _rDuration);
727} 727}
728 728
729void Recurrence::setYearly(int type, int _rFreq, const QDate &_rEndDate) 729void Recurrence::setYearly(int type, int _rFreq, const QDate &_rEndDate)
730{ 730{
731 if (mRecurReadOnly) return; 731 if (mRecurReadOnly) return;
732 rEndDateTime.setDate(_rEndDate); 732 rEndDateTime.setDate(_rEndDate);
733 rEndDateTime.setTime(mRecurStart.time()); 733 rEndDateTime.setTime(mRecurStart.time());
734 mCompatDuration = 0; 734 mCompatDuration = 0;
735 setYearly_(type, mFeb29YearlyDefaultType, _rFreq, 0); 735 setYearly_(type, mFeb29YearlyDefaultType, _rFreq, 0);
736} 736}
737 737
738void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, int _rDuration) 738void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, int _rDuration)
739{ 739{
740 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 740 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
741 return; 741 return;
742 if (mCompatVersion < 310) 742 if (mCompatVersion < 310)
743 mCompatDuration = (_rDuration > 0) ? _rDuration : 0; 743 mCompatDuration = (_rDuration > 0) ? _rDuration : 0;
744 setYearly_(rYearlyMonth, type, _rFreq, _rDuration); 744 setYearly_(rYearlyMonth, type, _rFreq, _rDuration);
745} 745}
746 746
747void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, const QDate &_rEndDate) 747void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, const QDate &_rEndDate)
748{ 748{
749 if (mRecurReadOnly) return; 749 if (mRecurReadOnly) return;
750 rEndDateTime.setDate(_rEndDate); 750 rEndDateTime.setDate(_rEndDate);
751 rEndDateTime.setTime(mRecurStart.time()); 751 rEndDateTime.setTime(mRecurStart.time());
752 mCompatDuration = 0; 752 mCompatDuration = 0;
753 setYearly_(rYearlyMonth, type, _rFreq, 0); 753 setYearly_(rYearlyMonth, type, _rFreq, 0);
754} 754}
755 755
756void Recurrence::addYearlyMonthPos(short _rPos, const QBitArray &_rDays) 756void Recurrence::addYearlyMonthPos(short _rPos, const QBitArray &_rDays)
757{ 757{
758 if (recurs == rYearlyPos) 758 if (recurs == rYearlyPos)
759 addMonthlyPos_(_rPos, _rDays); 759 addMonthlyPos_(_rPos, _rDays);
760} 760}
761 761
762const QPtrList<int> &Recurrence::yearNums() const 762const QPtrList<int> &Recurrence::yearNums() const
763{ 763{
764 return rYearNums; 764 return rYearNums;
765} 765}
766void Recurrence::addYearlyMonth(short _rPos ) 766void Recurrence::addYearlyMonth(short _rPos )
767{ 767{
768 if (mRecurReadOnly || recurs != rYearlyMonth) // invalid day/month number 768 if (mRecurReadOnly || recurs != rYearlyMonth) // invalid day/month number
769 return; 769 return;
770 rMonthPos *tmpPos = new rMonthPos; 770 rMonthPos *tmpPos = new rMonthPos;
771 if ( _rPos > 0) { 771 if ( _rPos > 0) {
772 tmpPos->rPos = _rPos; 772 tmpPos->rPos = _rPos;
773 tmpPos->negative = false; 773 tmpPos->negative = false;
774 } else { 774 } else {
775 tmpPos->rPos = -_rPos; // take abs() 775 tmpPos->rPos = -_rPos; // take abs()
776 tmpPos->negative = true; 776 tmpPos->negative = true;
777 } 777 }
778 rMonthPositions.append(tmpPos); 778 rMonthPositions.append(tmpPos);
779} 779}
780void Recurrence::addYearlyNum(short _rNum) 780void Recurrence::addYearlyNum(short _rNum)
781{ 781{
782 if (mRecurReadOnly 782 if (mRecurReadOnly
783 || (recurs != rYearlyMonth && recurs != rYearlyDay && recurs != rYearlyPos) 783 || (recurs != rYearlyMonth && recurs != rYearlyDay && recurs != rYearlyPos)
784 || _rNum <= 0) // invalid day/month number 784 || _rNum <= 0) // invalid day/month number
785 return; 785 return;
786 786
787 if (mCompatVersion < 310 && mCompatRecurs == rYearlyDay) { 787 if (mCompatVersion < 310 && mCompatRecurs == rYearlyDay) {
788 // Backwards compatibility for KDE < 3.1. 788 // Backwards compatibility for KDE < 3.1.
789 // Dates were stored as day numbers, with a fiddle to take account of leap years. 789 // Dates were stored as day numbers, with a fiddle to take account of leap years.
790 // Convert the day number to a month. 790 // Convert the day number to a month.
791 if (_rNum <= 0 || _rNum > 366 || (_rNum == 366 && mRecurStart.date().daysInYear() < 366)) 791 if (_rNum <= 0 || _rNum > 366 || (_rNum == 366 && mRecurStart.date().daysInYear() < 366))
792 return; // invalid day number 792 return; // invalid day number
793 _rNum = QDate(mRecurStart.date().year(), 1, 1).addDays(_rNum - 1).month(); 793 _rNum = QDate(mRecurStart.date().year(), 1, 1).addDays(_rNum - 1).month();
794 } else 794 } else
795 if ((recurs == rYearlyMonth || recurs == rYearlyPos) && _rNum > 12 795 if ((recurs == rYearlyMonth || recurs == rYearlyPos) && _rNum > 12
796 || recurs == rYearlyDay && _rNum > 366) 796 || recurs == rYearlyDay && _rNum > 366)
797 return; // invalid day number 797 return; // invalid day number
798 798
799 uint i = 0; 799 uint i = 0;
800 for (int* it = rYearNums.first(); it && _rNum >= *it; it = rYearNums.next()) { 800 for (int* it = rYearNums.first(); it && _rNum >= *it; it = rYearNums.next()) {
801 if (_rNum == *it) 801 if (_rNum == *it)
802 return; // this day/month is already in the list - avoid duplication 802 return; // this day/month is already in the list - avoid duplication
803 ++i; 803 ++i;
804 } 804 }
805 805
806 int *tmpNum = new int; 806 int *tmpNum = new int;
807 *tmpNum = _rNum; 807 *tmpNum = _rNum;
808 rYearNums.insert(i, tmpNum); // insert the day/month in a sorted position 808 rYearNums.insert(i, tmpNum); // insert the day/month in a sorted position
809 809
810 if (mCompatVersion < 310 && mCompatDuration > 0) { 810 if (mCompatVersion < 310 && mCompatDuration > 0) {
811 // Backwards compatibility for KDE < 3.1. 811 // Backwards compatibility for KDE < 3.1.
812 // rDuration was set to the number of time periods to recur. 812 // rDuration was set to the number of time periods to recur.
813 // Convert this to the number of occurrences. 813 // Convert this to the number of occurrences.
814 QDate end(mRecurStart.date().year() + (mCompatDuration-1+mRecurExDatesCount)*rFreq, 12, 31); 814 QDate end(mRecurStart.date().year() + (mCompatDuration-1+mRecurExDatesCount)*rFreq, 12, 31);
815 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly 815 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly
816 rDuration = recurCalc(COUNT_TO_DATE, end); 816 rDuration = recurCalc(COUNT_TO_DATE, end);
817 } 817 }
818 818
819 if (mParent) mParent->updated(); 819 if (mParent) mParent->updated();
820} 820}
821 821
822 822
823QDateTime Recurrence::getNextDateTime(const QDateTime &preDateTime, bool *last) const 823QDateTime Recurrence::getNextDateTime(const QDateTime &preDateTime, bool *last) const
824{ 824{
825 if (last) 825 if (last)
826 *last = false; 826 *last = false;
827 int freq; 827 int freq;
828 switch (recurs) 828 switch (recurs)
829 { 829 {
830 case rMinutely: 830 case rMinutely:
831 freq = rFreq * 60; 831 freq = rFreq * 60;
832 break; 832 break;
833 case rHourly: 833 case rHourly:
834 freq = rFreq * 3600; 834 freq = rFreq * 3600;
835 break; 835 break;
836 case rDaily: 836 case rDaily:
837 case rWeekly: 837 case rWeekly:
838 case rMonthlyPos: 838 case rMonthlyPos:
839 case rMonthlyDay: 839 case rMonthlyDay:
840 case rYearlyMonth: 840 case rYearlyMonth:
841 case rYearlyDay: 841 case rYearlyDay:
842 case rYearlyPos: { 842 case rYearlyPos: {
843 QDate preDate = preDateTime.date(); 843 QDate preDate = preDateTime.date();
844 if (!mFloats && mRecurStart.time() > preDateTime.time()) 844 if (!mFloats && mRecurStart.time() > preDateTime.time())
845 preDate = preDate.addDays(-1); 845 preDate = preDate.addDays(-1);
846 return QDateTime(getNextDateNoTime(preDate, last), mRecurStart.time()); 846 return QDateTime(getNextDateNoTime(preDate, last), mRecurStart.time());
847 } 847 }
848 default: 848 default:
849 return QDateTime(); 849 return QDateTime();
850 } 850 }
851 851
852 // It's a sub-daily recurrence 852 // It's a sub-daily recurrence
853 if (preDateTime < mRecurStart) 853 if (preDateTime < mRecurStart)
854 return mRecurStart; 854 return mRecurStart;
855 int count = mRecurStart.secsTo(preDateTime) / freq + 2; 855 int count = mRecurStart.secsTo(preDateTime) / freq + 2;
856 if (rDuration > 0) { 856 if (rDuration > 0) {
857 if (count > rDuration) 857 if (count > rDuration)
858 return QDateTime(); 858 return QDateTime();
859 if (last && count == rDuration) 859 if (last && count == rDuration)
860 *last = true; 860 *last = true;
861 } 861 }
862 QDateTime endtime = mRecurStart.addSecs((count - 1)*freq); 862 QDateTime endtime = mRecurStart.addSecs((count - 1)*freq);
863 if (rDuration == 0) { 863 if (rDuration == 0) {
864 if (endtime > rEndDateTime) 864 if (endtime > rEndDateTime)
865 return QDateTime(); 865 return QDateTime();
866 if (last && endtime == rEndDateTime) 866 if (last && endtime == rEndDateTime)
867 *last = true; 867 *last = true;
868 } 868 }
869 return endtime; 869 return endtime;
870} 870}
871 871
872QDate Recurrence::getNextDate(const QDate &preDate, bool *last) const 872QDate Recurrence::getNextDate(const QDate &preDate, bool *last) const
873{ 873{
874 if (last) 874 if (last)
875 *last = false; 875 *last = false;
876 switch (recurs) 876 switch (recurs)
877 { 877 {
878 case rMinutely: 878 case rMinutely:
879 case rHourly: 879 case rHourly:
880 return getNextDateTime(QDateTime(preDate, QTime(23,59,59)), last).date(); 880 return getNextDateTime(QDateTime(preDate, QTime(23,59,59)), last).date();
881 case rDaily: 881 case rDaily:
882 case rWeekly: 882 case rWeekly:
883 case rMonthlyPos: 883 case rMonthlyPos:
884 case rMonthlyDay: 884 case rMonthlyDay:
885 case rYearlyMonth: 885 case rYearlyMonth:
886 case rYearlyDay: 886 case rYearlyDay:
887 case rYearlyPos: 887 case rYearlyPos:
888 qDebug("Recurrence::getNextDate: MAY BE BROKEN "); 888 qDebug("Recurrence::getNextDate: MAY BE BROKEN ");
889 return getNextDateNoTime(preDate, last); 889 return getNextDateNoTime(preDate, last);
890 default: 890 default:
891 return QDate(); 891 return QDate();
892 } 892 }
893} 893}
894 894
895 895
896QDateTime Recurrence::getPreviousDateTime(const QDateTime &afterDateTime, bool *last) const 896QDateTime Recurrence::getPreviousDateTime(const QDateTime &afterDateTime, bool *last) const
897{ 897{
898 if (last) 898 if (last)
899 *last = false; 899 *last = false;
900 int freq; 900 int freq;
901 switch (recurs) 901 switch (recurs)
902 { 902 {
903 case rMinutely: 903 case rMinutely:
904 freq = rFreq * 60; 904 freq = rFreq * 60;
905 break; 905 break;
906 case rHourly: 906 case rHourly:
907 freq = rFreq * 3600; 907 freq = rFreq * 3600;
908 break; 908 break;
909 case rDaily: 909 case rDaily:
910 case rWeekly: 910 case rWeekly:
911 case rMonthlyPos: 911 case rMonthlyPos:
912 case rMonthlyDay: 912 case rMonthlyDay:
913 case rYearlyMonth: 913 case rYearlyMonth:
914 case rYearlyDay: 914 case rYearlyDay:
915 case rYearlyPos: { 915 case rYearlyPos: {
916 QDate afterDate = afterDateTime.date(); 916 QDate afterDate = afterDateTime.date();
917 if (!mFloats && mRecurStart.time() < afterDateTime.time()) 917 if (!mFloats && mRecurStart.time() < afterDateTime.time())
918 afterDate = afterDate.addDays(1); 918 afterDate = afterDate.addDays(1);
919 return QDateTime(getPreviousDateNoTime(afterDate, last), mRecurStart.time()); 919 return QDateTime(getPreviousDateNoTime(afterDate, last), mRecurStart.time());
920 } 920 }
921 default: 921 default:
922 return QDateTime(); 922 return QDateTime();
923 } 923 }
924 924
925 // It's a sub-daily recurrence 925 // It's a sub-daily recurrence
926 if (afterDateTime <= mRecurStart) 926 if (afterDateTime <= mRecurStart)
927 return QDateTime(); 927 return QDateTime();
928 int count = (mRecurStart.secsTo(afterDateTime) - 1) / freq + 1; 928 int count = (mRecurStart.secsTo(afterDateTime) - 1) / freq + 1;
929 if (rDuration > 0) { 929 if (rDuration > 0) {
930 if (count > rDuration) 930 if (count > rDuration)
931 count = rDuration; 931 count = rDuration;
932 if (last && count == rDuration) 932 if (last && count == rDuration)
933 *last = true; 933 *last = true;
934 } 934 }
935 QDateTime endtime = mRecurStart.addSecs((count - 1)*freq); 935 QDateTime endtime = mRecurStart.addSecs((count - 1)*freq);
936 if (rDuration == 0) { 936 if (rDuration == 0) {
937 if (endtime > rEndDateTime) 937 if (endtime > rEndDateTime)
938 endtime = rEndDateTime; 938 endtime = rEndDateTime;
939 if (last && endtime == rEndDateTime) 939 if (last && endtime == rEndDateTime)
940 *last = true; 940 *last = true;
941 } 941 }
942 return endtime; 942 return endtime;
943} 943}
944 944
945QDate Recurrence::getPreviousDate(const QDate &afterDate, bool *last) const 945QDate Recurrence::getPreviousDate(const QDate &afterDate, bool *last) const
946{ 946{
947 if (last) 947 if (last)
948 *last = false; 948 *last = false;
949 switch (recurs) 949 switch (recurs)
950 { 950 {
951 case rMinutely: 951 case rMinutely:
952 case rHourly: 952 case rHourly:
953 return getPreviousDateTime(QDateTime(afterDate, QTime(0,0,0)), last).date(); 953 return getPreviousDateTime(QDateTime(afterDate, QTime(0,0,0)), last).date();
954 case rDaily: 954 case rDaily:
955 case rWeekly: 955 case rWeekly:
956 case rMonthlyPos: 956 case rMonthlyPos:
957 case rMonthlyDay: 957 case rMonthlyDay:
958 case rYearlyMonth: 958 case rYearlyMonth:
959 case rYearlyDay: 959 case rYearlyDay:
960 case rYearlyPos: 960 case rYearlyPos:
961 return getPreviousDateNoTime(afterDate, last); 961 return getPreviousDateNoTime(afterDate, last);
962 default: 962 default:
963 return QDate(); 963 return QDate();
964 } 964 }
965} 965}
966 966
967 967
968/***************************** PROTECTED FUNCTIONS ***************************/ 968/***************************** PROTECTED FUNCTIONS ***************************/
969 969
970bool Recurrence::recursSecondly(const QDate &qd, int secondFreq) const 970bool Recurrence::recursSecondly(const QDate &qd, int secondFreq) const
971{ 971{
972 if ((qd >= mRecurStart.date()) && 972 if ((qd >= mRecurStart.date()) &&
973 ((rDuration > 0) && (qd <= endDate()) || 973 ((rDuration > 0) && (qd <= endDate()) ||
974 ((rDuration == 0) && (qd <= rEndDateTime.date())) || 974 ((rDuration == 0) && (qd <= rEndDateTime.date())) ||
975 (rDuration == -1))) { 975 (rDuration == -1))) {
976 // The date queried falls within the range of the event. 976 // The date queried falls within the range of the event.
977 if (secondFreq < 24*3600) 977 if (secondFreq < 24*3600)
978 return true; // the event recurs at least once each day 978 return true; // the event recurs at least once each day
979 int after = mRecurStart.secsTo(QDateTime(qd)); 979 int after = mRecurStart.secsTo(QDateTime(qd)) - 1;
980 if (after / secondFreq != (after + 24*3600) / secondFreq) 980 if (after / secondFreq != (after + 24*3600) / secondFreq)
981 return true; 981 return true;
982 } 982 }
983 return false; 983 return false;
984} 984}
985 985
986bool Recurrence::recursMinutelyAt(const QDateTime &dt, int minuteFreq) const 986bool Recurrence::recursMinutelyAt(const QDateTime &dt, int minuteFreq) const
987{ 987{
988 if ((dt >= mRecurStart) && 988 if ((dt >= mRecurStart) &&
989 ((rDuration > 0) && (dt <= endDateTime()) || 989 ((rDuration > 0) && (dt <= endDateTime()) ||
990 ((rDuration == 0) && (dt <= rEndDateTime)) || 990 ((rDuration == 0) && (dt <= rEndDateTime)) ||
991 (rDuration == -1))) { 991 (rDuration == -1))) {
992 // The time queried falls within the range of the event. 992 // The time queried falls within the range of the event.
993 if (((mRecurStart.secsTo(dt) / 60) % minuteFreq) == 0) 993 if (((mRecurStart.secsTo(dt) / 60) % minuteFreq) == 0)
994 return true; 994 return true;
995 } 995 }
996 return false; 996 return false;
997} 997}
998 998
999bool Recurrence::recursDaily(const QDate &qd) const 999bool Recurrence::recursDaily(const QDate &qd) const
1000{ 1000{
1001 QDate dStart = mRecurStart.date(); 1001 QDate dStart = mRecurStart.date();
1002 if ((dStart.daysTo(qd) % rFreq) == 0) { 1002 if ((dStart.daysTo(qd) % rFreq) == 0) {
1003 // The date is a day which recurs 1003 // The date is a day which recurs
1004 if (qd >= dStart 1004 if (qd >= dStart
1005 && ((rDuration > 0 && qd <= endDate()) || 1005 && ((rDuration > 0 && qd <= endDate()) ||
1006 (rDuration == 0 && qd <= rEndDateTime.date()) || 1006 (rDuration == 0 && qd <= rEndDateTime.date()) ||
1007 rDuration == -1)) { 1007 rDuration == -1)) {
1008 // The date queried falls within the range of the event. 1008 // The date queried falls within the range of the event.
1009 return true; 1009 return true;
1010 } 1010 }
1011 } 1011 }
1012 return false; 1012 return false;
1013} 1013}
1014 1014
1015bool Recurrence::recursWeekly(const QDate &qd) const 1015bool Recurrence::recursWeekly(const QDate &qd) const
1016{ 1016{
1017 QDate dStart = mRecurStart.date(); 1017 QDate dStart = mRecurStart.date();
1018 if ((dStart.daysTo(qd)/7) % rFreq == 0) { 1018 if ((dStart.daysTo(qd)/7) % rFreq == 0) {
1019 // The date is in a week which recurs 1019 // The date is in a week which recurs
1020 if (qd >= dStart 1020 if (qd >= dStart
1021 && ((rDuration > 0 && qd <= endDate()) || 1021 && ((rDuration > 0 && qd <= endDate()) ||
1022 (rDuration == 0 && qd <= rEndDateTime.date()) || 1022 (rDuration == 0 && qd <= rEndDateTime.date()) ||
1023 rDuration == -1)) { 1023 rDuration == -1)) {
1024 // The date queried falls within the range of the event. 1024 // The date queried falls within the range of the event.
1025 // check if the bits set match today. 1025 // check if the bits set match today.
1026 int i = qd.dayOfWeek()-1; 1026 int i = qd.dayOfWeek()-1;
1027 if (rDays.testBit((uint) i)) 1027 if (rDays.testBit((uint) i))
1028 return true; 1028 return true;
1029 } 1029 }
1030 } 1030 }
1031 return false; 1031 return false;
1032} 1032}
1033 1033
1034bool Recurrence::recursMonthly(const QDate &qd) const 1034bool Recurrence::recursMonthly(const QDate &qd) const
1035{ 1035{
1036 QDate dStart = mRecurStart.date(); 1036 QDate dStart = mRecurStart.date();
1037 int year = qd.year(); 1037 int year = qd.year();
1038 int month = qd.month(); 1038 int month = qd.month();
1039 int day = qd.day(); 1039 int day = qd.day();
1040 // calculate how many months ahead this date is from the original 1040 // calculate how many months ahead this date is from the original
1041 // event's date 1041 // event's date
1042 int monthsAhead = (year - dStart.year()) * 12 + (month - dStart.month()); 1042 int monthsAhead = (year - dStart.year()) * 12 + (month - dStart.month());
1043 if ((monthsAhead % rFreq) == 0) { 1043 if ((monthsAhead % rFreq) == 0) {
1044 // The date is in a month which recurs 1044 // The date is in a month which recurs
1045 if (qd >= dStart 1045 if (qd >= dStart
1046 && ((rDuration > 0 && qd <= endDate()) || 1046 && ((rDuration > 0 && qd <= endDate()) ||
1047 (rDuration == 0 && qd <= rEndDateTime.date()) || 1047 (rDuration == 0 && qd <= rEndDateTime.date()) ||
1048 rDuration == -1)) { 1048 rDuration == -1)) {
1049 // The date queried falls within the range of the event. 1049 // The date queried falls within the range of the event.
1050 QValueList<int> days; 1050 QValueList<int> days;
1051 int daysInMonth = qd.daysInMonth(); 1051 int daysInMonth = qd.daysInMonth();
1052 if (recurs == rMonthlyDay) 1052 if (recurs == rMonthlyDay)
1053 getMonthlyDayDays(days, daysInMonth); 1053 getMonthlyDayDays(days, daysInMonth);
1054 else if (recurs == rMonthlyPos) 1054 else if (recurs == rMonthlyPos)
1055 getMonthlyPosDays(days, daysInMonth, QDate(year, month, 1).dayOfWeek()); 1055 getMonthlyPosDays(days, daysInMonth, QDate(year, month, 1).dayOfWeek());
1056 for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) { 1056 for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) {
1057 if (*it == day) 1057 if (*it == day)
1058 return true; 1058 return true;
1059 } 1059 }
1060 // no dates matched 1060 // no dates matched
1061 } 1061 }
1062 } 1062 }
1063 return false; 1063 return false;
1064} 1064}
1065 1065
1066bool Recurrence::recursYearlyByMonth(const QDate &qd) const 1066bool Recurrence::recursYearlyByMonth(const QDate &qd) const
1067{ 1067{
1068 QDate dStart = mRecurStart.date(); 1068 QDate dStart = mRecurStart.date();
1069 int startDay = dStart.day(); 1069 int startDay = dStart.day();
1070 int qday = qd.day(); 1070 int qday = qd.day();
1071 int qmonth = qd.month(); 1071 int qmonth = qd.month();
1072 int qyear = qd.year(); 1072 int qyear = qd.year();
1073 bool match = (qday == startDay); 1073 bool match = (qday == startDay);
1074 if (!match && startDay == 29 && dStart.month() == 2) { 1074 if (!match && startDay == 29 && dStart.month() == 2) {
1075 // It's a recurrence on February 29th 1075 // It's a recurrence on February 29th
1076 switch (mFeb29YearlyType) { 1076 switch (mFeb29YearlyType) {
1077 case rFeb28: 1077 case rFeb28:
1078 if (qday == 28 && qmonth == 2 && !QDate::leapYear(qyear)) 1078 if (qday == 28 && qmonth == 2 && !QDate::leapYear(qyear))
1079 match = true; 1079 match = true;
1080 break; 1080 break;
1081 case rMar1: 1081 case rMar1:
1082 if (qday == 1 && qmonth == 3 && !QDate::leapYear(qyear)) { 1082 if (qday == 1 && qmonth == 3 && !QDate::leapYear(qyear)) {
1083 qmonth = 2; 1083 qmonth = 2;
1084 match = true; 1084 match = true;
1085 } 1085 }
1086 break; 1086 break;
1087 case rFeb29: 1087 case rFeb29:
1088 break; 1088 break;
1089 } 1089 }
1090 } 1090 }
1091 1091
1092 if (match) { 1092 if (match) {
1093 // The day of the month matches. Calculate how many years ahead 1093 // The day of the month matches. Calculate how many years ahead
1094 // this date is from the original event's date. 1094 // this date is from the original event's date.
1095 int yearsAhead = (qyear - dStart.year()); 1095 int yearsAhead = (qyear - dStart.year());
1096 if (yearsAhead % rFreq == 0) { 1096 if (yearsAhead % rFreq == 0) {
1097 // The date is in a year which recurs 1097 // The date is in a year which recurs
1098 if (qd >= dStart 1098 if (qd >= dStart
1099 && ((rDuration > 0 && qd <= endDate()) || 1099 && ((rDuration > 0 && qd <= endDate()) ||
1100 (rDuration == 0 && qd <= rEndDateTime.date()) || 1100 (rDuration == 0 && qd <= rEndDateTime.date()) ||
1101 rDuration == -1)) { 1101 rDuration == -1)) {
1102 // The date queried falls within the range of the event. 1102 // The date queried falls within the range of the event.
1103 int i = qmonth; 1103 int i = qmonth;
1104 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) { 1104 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) {
1105 if (i == *qlin.current()) 1105 if (i == *qlin.current())
1106 return true; 1106 return true;
1107 } 1107 }
1108 } 1108 }
1109 } 1109 }
1110 } 1110 }
1111 return false; 1111 return false;
1112} 1112}
1113 1113
1114bool Recurrence::recursYearlyByPos(const QDate &qd) const 1114bool Recurrence::recursYearlyByPos(const QDate &qd) const
1115{ 1115{
1116 QDate dStart = mRecurStart.date(); 1116 QDate dStart = mRecurStart.date();
1117 int year = qd.year(); 1117 int year = qd.year();
1118 int month = qd.month(); 1118 int month = qd.month();
1119 int day = qd.day(); 1119 int day = qd.day();
1120 // calculate how many years ahead this date is from the original 1120 // calculate how many years ahead this date is from the original
1121 // event's date 1121 // event's date
1122 int yearsAhead = (year - dStart.year()); 1122 int yearsAhead = (year - dStart.year());
1123 if (yearsAhead % rFreq == 0) { 1123 if (yearsAhead % rFreq == 0) {
1124 // The date is in a year which recurs 1124 // The date is in a year which recurs
1125 if (qd >= dStart 1125 if (qd >= dStart
1126 && ((rDuration > 0 && qd <= endDate()) || 1126 && ((rDuration > 0 && qd <= endDate()) ||
1127 (rDuration == 0 && qd <= rEndDateTime.date()) || 1127 (rDuration == 0 && qd <= rEndDateTime.date()) ||
1128 rDuration == -1)) { 1128 rDuration == -1)) {
1129 // The date queried falls within the range of the event. 1129 // The date queried falls within the range of the event.
1130 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) { 1130 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) {
1131 if (month == *qlin.current()) { 1131 if (month == *qlin.current()) {
1132 // The month recurs 1132 // The month recurs
1133 QValueList<int> days; 1133 QValueList<int> days;
1134 getMonthlyPosDays(days, qd.daysInMonth(), QDate(year, month, 1).dayOfWeek()); 1134 getMonthlyPosDays(days, qd.daysInMonth(), QDate(year, month, 1).dayOfWeek());
1135 for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) { 1135 for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) {
1136 if (*it == day) 1136 if (*it == day)
1137 return true; 1137 return true;
1138 } 1138 }
1139 } 1139 }
1140 } 1140 }
1141 } 1141 }
1142 } 1142 }
1143 return false; 1143 return false;
1144} 1144}
1145 1145
1146bool Recurrence::recursYearlyByDay(const QDate &qd) const 1146bool Recurrence::recursYearlyByDay(const QDate &qd) const
1147{ 1147{
1148 QDate dStart = mRecurStart.date(); 1148 QDate dStart = mRecurStart.date();
1149 // calculate how many years ahead this date is from the original 1149 // calculate how many years ahead this date is from the original
1150 // event's date 1150 // event's date
1151 int yearsAhead = (qd.year() - dStart.year()); 1151 int yearsAhead = (qd.year() - dStart.year());
1152 if (yearsAhead % rFreq == 0) { 1152 if (yearsAhead % rFreq == 0) {
1153 // The date is in a year which recurs 1153 // The date is in a year which recurs
1154 if (qd >= dStart 1154 if (qd >= dStart
1155 && ((rDuration > 0 && qd <= endDate()) || 1155 && ((rDuration > 0 && qd <= endDate()) ||
1156 (rDuration == 0 && qd <= rEndDateTime.date()) || 1156 (rDuration == 0 && qd <= rEndDateTime.date()) ||
1157 rDuration == -1)) { 1157 rDuration == -1)) {
1158 // The date queried falls within the range of the event. 1158 // The date queried falls within the range of the event.
1159 int i = qd.dayOfYear(); 1159 int i = qd.dayOfYear();
1160 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) { 1160 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) {
1161 if (i == *qlin.current()) 1161 if (i == *qlin.current())
1162 return true; 1162 return true;
1163 } 1163 }
1164 } 1164 }
1165 } 1165 }
1166 return false; 1166 return false;
1167} 1167}
1168 1168
1169/* Get the date of the next recurrence, after the specified date. 1169/* Get the date of the next recurrence, after the specified date.
1170 * If 'last' is non-null, '*last' is set to true if the next recurrence is the 1170 * If 'last' is non-null, '*last' is set to true if the next recurrence is the
1171 * last recurrence, else false. 1171 * last recurrence, else false.
1172 * Reply = date of next recurrence, or invalid date if none. 1172 * Reply = date of next recurrence, or invalid date if none.
1173 */ 1173 */
1174QDate Recurrence::getNextDateNoTime(const QDate &preDate, bool *last) const 1174QDate Recurrence::getNextDateNoTime(const QDate &preDate, bool *last) const
1175{ 1175{
1176 1176
1177 if (last) 1177 if (last)
1178 *last = false; 1178 *last = false;
1179 QDate dStart = mRecurStart.date(); 1179 QDate dStart = mRecurStart.date();
1180 if (preDate < dStart) 1180 if (preDate < dStart)
1181 return dStart; 1181 return dStart;
1182 QDate earliestDate = preDate.addDays(1); 1182 QDate earliestDate = preDate.addDays(1);
1183 QDate nextDate; 1183 QDate nextDate;
1184 1184
1185 switch (recurs) { 1185 switch (recurs) {
1186 case rDaily: 1186 case rDaily:
1187 nextDate = dStart.addDays((dStart.daysTo(preDate)/rFreq + 1) * rFreq); 1187 nextDate = dStart.addDays((dStart.daysTo(preDate)/rFreq + 1) * rFreq);
1188 break; 1188 break;
1189 1189
1190 case rWeekly: { 1190 case rWeekly: {
1191 QDate start = dStart.addDays(1 - dStart.dayOfWeek()); // start of week for dStart 1191 QDate start = dStart.addDays(-((dStart.dayOfWeek() - rWeekStart + 7)%7)); // start of week for dStart
1192 int earliestDayOfWeek = earliestDate.dayOfWeek(); 1192 int earliestDayOfWeek = earliestDate.dayOfWeek();
1193 int weeksAhead = start.daysTo(earliestDate) / 7; 1193 int weeksAhead = start.daysTo(earliestDate) / 7;
1194 int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week 1194 int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week
1195 weeksAhead -= notThisWeek; // latest week which recurred 1195 weeksAhead -= notThisWeek; // latest week which recurred
1196 int weekday = 0; 1196 int weekday = 0;
1197 // First check for any remaining day this week, if this week is a recurring week 1197 // First check for any remaining day this week, if this week is a recurring week
1198 if (!notThisWeek) 1198 if (!notThisWeek)
1199 weekday = getFirstDayInWeek(earliestDayOfWeek); 1199 weekday = getFirstDayInWeek(earliestDayOfWeek);
1200 // Check for a day in the next scheduled week 1200 // Check for a day in the next scheduled week
1201 if (!weekday && earliestDayOfWeek > 1) 1201 if (!weekday )
1202 weekday = getFirstDayInWeek(rWeekStart) + rFreq*7; 1202 weekday = getFirstDayInWeek(rWeekStart) + rFreq*7;
1203 if (weekday) 1203 nextDate = start.addDays(weeksAhead*7 + weekday - 1);
1204 nextDate = start.addDays(weeksAhead*7 + weekday - 1);
1205 break; 1204 break;
1206 } 1205 }
1207 case rMonthlyDay: 1206 case rMonthlyDay:
1208 case rMonthlyPos: { 1207 case rMonthlyPos: {
1209 int startYear = dStart.year(); 1208 int startYear = dStart.year();
1210 int startMonth = dStart.month(); // 1..12 1209 int startMonth = dStart.month(); // 1..12
1211 int earliestYear = earliestDate.year(); 1210 int earliestYear = earliestDate.year();
1212 int monthsAhead = (earliestYear - startYear)*12 + earliestDate.month() - startMonth; 1211 int monthsAhead = (earliestYear - startYear)*12 + earliestDate.month() - startMonth;
1213 int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month 1212 int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month
1214 monthsAhead -= notThisMonth; // latest month which recurred 1213 monthsAhead -= notThisMonth; // latest month which recurred
1215 // Check for the first later day in the current month 1214 // Check for the first later day in the current month
1216 if (!notThisMonth) 1215 if (!notThisMonth)
1217 nextDate = getFirstDateInMonth(earliestDate); 1216 nextDate = getFirstDateInMonth(earliestDate);
1218 if (!nextDate.isValid() && earliestDate.day() > 1) { 1217 if (!nextDate.isValid() ) {
1219 // Check for a day in the next scheduled month 1218 // Check for a day in the next scheduled month
1220 int months = startMonth - 1 + monthsAhead + rFreq; 1219 int months = startMonth - 1 + monthsAhead + rFreq;
1221 nextDate = getFirstDateInMonth(QDate(startYear + months/12, months%12 + 1, 1)); 1220 nextDate = getFirstDateInMonth(QDate(startYear + months/12, months%12 + 1, 1));
1222 } 1221 }
1223 break; 1222 break;
1224 } 1223 }
1225 case rYearlyMonth: 1224 case rYearlyMonth:
1226 case rYearlyPos: 1225 case rYearlyPos:
1227 case rYearlyDay: { 1226 case rYearlyDay: {
1228 int startYear = dStart.year(); 1227 int startYear = dStart.year();
1229 int yearsAhead = earliestDate.year() - startYear; 1228 int yearsAhead = earliestDate.year() - startYear;
1230 int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year 1229 int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year
1231 yearsAhead -= notThisYear; // latest year which recurred 1230 yearsAhead -= notThisYear; // latest year which recurred
1232 // Check for the first later date in the current year 1231 // Check for the first later date in the current year
1233 if (!notThisYear) 1232 if (!notThisYear)
1234 nextDate = getFirstDateInYear(earliestDate); 1233 nextDate = getFirstDateInYear(earliestDate);
1235 // Check for a date in the next scheduled year 1234 // Check for a date in the next scheduled year
1236 if (!nextDate.isValid() && earliestDate.dayOfYear() > 1) 1235 if (!nextDate.isValid() && earliestDate.dayOfYear() > 1)
1237 nextDate = getFirstDateInYear(QDate(startYear + yearsAhead + rFreq, 1, 1)); 1236 nextDate = getFirstDateInYear(QDate(startYear + yearsAhead + rFreq, 1, 1));
1238 break; 1237 break;
1239 } 1238 }
1240 case rNone: 1239 case rNone:
1241 default: 1240 default:
1242 return QDate(); 1241 return QDate();
1243 } 1242 }
1244 1243
1245 if (rDuration >= 0 && nextDate.isValid()) { 1244 if (rDuration >= 0 && nextDate.isValid()) {
1246 // Check that the date found is within the range of the recurrence 1245 // Check that the date found is within the range of the recurrence
1247 QDate end = endDate(); 1246 QDate end = endDate();
1248 if (nextDate > end) 1247 if (nextDate > end)
1249 return QDate(); 1248 return QDate();
1250 if (last && nextDate == end) 1249 if (last && nextDate == end)
1251 *last = true; 1250 *last = true;
1252 } 1251 }
1253 return nextDate; 1252 return nextDate;
1254} 1253}
1255 1254
1256/* Get the date of the last previous recurrence, before the specified date. 1255/* Get the date of the last previous recurrence, before the specified date.
1257 * Reply = date of previous recurrence, or invalid date if none. 1256 * Reply = date of previous recurrence, or invalid date if none.
1258 */ 1257 */
1259QDate Recurrence::getPreviousDateNoTime(const QDate &afterDate, bool *last) const 1258QDate Recurrence::getPreviousDateNoTime(const QDate &afterDate, bool *last) const
1260{ 1259{
1261 if (last) 1260 if (last)
1262 *last = false; 1261 *last = false;
1263 QDate dStart = mRecurStart.date(); 1262 QDate dStart = mRecurStart.date();
1264 QDate latestDate = afterDate.addDays(-1); 1263 QDate latestDate = afterDate.addDays(-1);
1265 if (latestDate < dStart) 1264 if (latestDate < dStart)
1266 return QDate(); 1265 return QDate();
1267 QDate prevDate; 1266 QDate prevDate;
1268 1267
1269 switch (recurs) { 1268 switch (recurs) {
1270 case rDaily: 1269 case rDaily:
1271 prevDate = dStart.addDays((dStart.daysTo(latestDate) / rFreq) * rFreq); 1270 prevDate = dStart.addDays((dStart.daysTo(latestDate) / rFreq) * rFreq);
1272 break; 1271 break;
1273 1272
1274 case rWeekly: { 1273 case rWeekly: {
1275 QDate start = dStart.addDays(1 - dStart.dayOfWeek()); // start of week for dStart 1274 QDate start = dStart.addDays(-((dStart.dayOfWeek() - rWeekStart + 7)%7)); // start of week for dStart
1276 int latestDayOfWeek = latestDate.dayOfWeek(); 1275 int latestDayOfWeek = latestDate.dayOfWeek();
1277 int weeksAhead = start.daysTo(latestDate) / 7; 1276 int weeksAhead = start.daysTo(latestDate) / 7;
1278 int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week 1277 int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week
1279 weeksAhead -= notThisWeek; // latest week which recurred 1278 weeksAhead -= notThisWeek; // latest week which recurred
1280 int weekday = 0; 1279 int weekday = 0;
1281 // First check for any previous day this week, if this week is a recurring week 1280 // First check for any previous day this week, if this week is a recurring week
1282 if (!notThisWeek) 1281 if (!notThisWeek)
1283 weekday = getLastDayInWeek(latestDayOfWeek); 1282 weekday = getLastDayInWeek(latestDayOfWeek);
1284 // Check for a day in the previous scheduled week 1283 // Check for a day in the previous scheduled week
1285 if (!weekday) { 1284 if (!weekday) {
1285 if (!notThisWeek)
1286 weeksAhead -= rFreq;
1286 int weekEnd = (rWeekStart + 5)%7 + 1; 1287 int weekEnd = (rWeekStart + 5)%7 + 1;
1287 if (latestDayOfWeek < weekEnd) { 1288 weekday = getLastDayInWeek(weekEnd);
1288 if (!notThisWeek)
1289 weeksAhead -= rFreq;
1290 weekday = getLastDayInWeek(weekEnd);
1291 }
1292 } 1289 }
1293 if (weekday) 1290 if (weekday)
1294 prevDate = start.addDays(weeksAhead*7 + weekday - 1); 1291 prevDate = start.addDays(weeksAhead*7 + weekday - 1);
1295 break; 1292 break;
1296 } 1293 }
1297 case rMonthlyDay: 1294 case rMonthlyDay:
1298 case rMonthlyPos: { 1295 case rMonthlyPos: {
1299 int startYear = dStart.year(); 1296 int startYear = dStart.year();
1300 int startMonth = dStart.month(); // 1..12 1297 int startMonth = dStart.month(); // 1..12
1301 int latestYear = latestDate.year(); 1298 int latestYear = latestDate.year();
1302 int monthsAhead = (latestYear - startYear)*12 + latestDate.month() - startMonth; 1299 int monthsAhead = (latestYear - startYear)*12 + latestDate.month() - startMonth;
1303 int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month 1300 int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month
1304 monthsAhead -= notThisMonth; // latest month which recurred 1301 monthsAhead -= notThisMonth; // latest month which recurred
1305 // Check for the last earlier day in the current month 1302 // Check for the last earlier day in the current month
1306 if (!notThisMonth) 1303 if (!notThisMonth)
1307 prevDate = getLastDateInMonth(latestDate); 1304 prevDate = getLastDateInMonth(latestDate);
1308 if (!prevDate.isValid() && latestDate.day() < latestDate.daysInMonth()) { 1305 if (!prevDate.isValid() && latestDate.day() < latestDate.daysInMonth()) {
1309 // Check for a day in the previous scheduled month 1306 // Check for a day in the previous scheduled month
1310 if (!notThisMonth) 1307 if (!notThisMonth)
1311 monthsAhead -= rFreq; 1308 monthsAhead -= rFreq;
1312 int months = startMonth + monthsAhead; // get the month after the one that recurs 1309 int months = startMonth + monthsAhead; // get the month after the one that recurs
1313 prevDate = getLastDateInMonth(QDate(startYear + months/12, months%12 + 1, 1).addDays(-1)); 1310 prevDate = getLastDateInMonth(QDate(startYear + months/12, months%12 + 1, 1).addDays(-1));
1314 } 1311 }
1315 break; 1312 break;
1316 } 1313 }
1317 case rYearlyMonth: 1314 case rYearlyMonth:
1318 case rYearlyPos: 1315 case rYearlyPos:
1319 case rYearlyDay: { 1316 case rYearlyDay: {
1320 int startYear = dStart.year(); 1317 int startYear = dStart.year();
1321 int yearsAhead = latestDate.year() - startYear; 1318 int yearsAhead = latestDate.year() - startYear;
1322 int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year 1319 int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year
1323 yearsAhead -= notThisYear; // latest year which recurred 1320 yearsAhead -= notThisYear; // latest year which recurred
1324 // Check for the first later date in the current year 1321 // Check for the first later date in the current year
1325 if (!notThisYear) 1322 if (!notThisYear)
1326 prevDate = getLastDateInYear(latestDate); 1323 prevDate = getLastDateInYear(latestDate);
1327 if (!prevDate.isValid() && latestDate.dayOfYear() < latestDate.daysInYear()) { 1324 if (!prevDate.isValid() && latestDate.dayOfYear() < latestDate.daysInYear()) {
1328 // Check for a date in the next scheduled year 1325 // Check for a date in the next scheduled year
1329 if (!notThisYear) 1326 if (!notThisYear)
1330 yearsAhead -= rFreq; 1327 yearsAhead -= rFreq;
1331 prevDate = getLastDateInYear(QDate(startYear + yearsAhead, 12, 31)); 1328 prevDate = getLastDateInYear(QDate(startYear + yearsAhead, 12, 31));
1332 } 1329 }
1333 break; 1330 break;
1334 } 1331 }
1335 case rNone: 1332 case rNone:
1336 default: 1333 default:
1337 return QDate(); 1334 return QDate();
1338 } 1335 }
1339 1336
1340 if (prevDate.isValid()) { 1337 if (prevDate.isValid()) {
1341 // Check that the date found is within the range of the recurrence 1338 // Check that the date found is within the range of the recurrence
1342 if (prevDate < dStart) 1339 if (prevDate < dStart)
1343 return QDate(); 1340 return QDate();
1344 if (rDuration >= 0) { 1341 if (rDuration >= 0) {
1345 QDate end = endDate(); 1342 QDate end = endDate();
1346 if (prevDate >= end) { 1343 if (prevDate >= end) {
1347 if (last) 1344 if (last)
1348 *last = true; 1345 *last = true;
1349 return end; 1346 return end;
1350 } 1347 }
1351 } 1348 }
1352 } 1349 }
1353 return prevDate; 1350 return prevDate;
1354} 1351}
1355 1352
1356void Recurrence::setDailySub(short type, int freq, int duration) 1353void Recurrence::setDailySub(short type, int freq, int duration)
1357{ 1354{
1358 recurs = type; 1355 recurs = type;
1359 rFreq = freq; 1356 rFreq = freq;
1360 rDuration = duration; 1357 rDuration = duration;
1361 rMonthPositions.clear(); 1358 rMonthPositions.clear();
1362 rMonthDays.clear(); 1359 rMonthDays.clear();
1363 rYearNums.clear(); 1360 rYearNums.clear();
1364 if (type != rDaily) 1361 if (type != rDaily)
1365 mFloats = false; // sub-daily types can't be floating 1362 mFloats = false; // sub-daily types can't be floating
1366 1363
1367 if (mParent) mParent->updated(); 1364 if (mParent) mParent->updated();
1368} 1365}
1369 1366
1370void Recurrence::setYearly_(short type, Feb29Type feb29type, int freq, int duration) 1367void Recurrence::setYearly_(short type, Feb29Type feb29type, int freq, int duration)
1371{ 1368{
1372 recurs = type; 1369 recurs = type;
1373 if (mCompatVersion < 310 && type == rYearlyDay) { 1370 if (mCompatVersion < 310 && type == rYearlyDay) {
1374 mCompatRecurs = rYearlyDay; 1371 mCompatRecurs = rYearlyDay;
1375 recurs = rYearlyMonth; // convert old yearly-by-day to yearly-by-month 1372 recurs = rYearlyMonth; // convert old yearly-by-day to yearly-by-month
1376 feb29type = rMar1; // retain the same day number in the year 1373 feb29type = rMar1; // retain the same day number in the year
1377 } 1374 }
1378 1375
1379 mFeb29YearlyType = feb29type; 1376 mFeb29YearlyType = feb29type;
1380 rFreq = freq; 1377 rFreq = freq;
1381 rDuration = duration; 1378 rDuration = duration;
1382 if (type != rYearlyPos) 1379 if (type != rYearlyPos)
1383 rMonthPositions.clear(); 1380 rMonthPositions.clear();
1384 rMonthDays.clear(); 1381 rMonthDays.clear();
1385 if (mParent) mParent->updated(); 1382 if (mParent) mParent->updated();
1386} 1383}
1387 1384
1388int Recurrence::recurCalc(PeriodFunc func, QDateTime &endtime) const 1385int Recurrence::recurCalc(PeriodFunc func, QDateTime &endtime) const
1389{ 1386{
1390 QDate enddate = endtime.date(); 1387 QDate enddate = endtime.date();
1391 switch (func) { 1388 switch (func) {
1392 case END_DATE_AND_COUNT: 1389 case END_DATE_AND_COUNT:
1393 if (rDuration < 0) { 1390 if (rDuration < 0) {
1394 endtime = QDateTime(); 1391 endtime = QDateTime();
1395 return 0; // infinite recurrence 1392 return 0; // infinite recurrence
1396 } 1393 }
1397 if (rDuration == 0) { 1394 if (rDuration == 0) {
1398 endtime = rEndDateTime; 1395 endtime = rEndDateTime;
1399 func = COUNT_TO_DATE; 1396 func = COUNT_TO_DATE;
1400 } 1397 }
1401 break; 1398 break;
1402 case COUNT_TO_DATE: 1399 case COUNT_TO_DATE:
1403 // Count recurrences up to and including the specified date/time. 1400 // Count recurrences up to and including the specified date/time.
1404 if (endtime < mRecurStart) 1401 if (endtime < mRecurStart)
1405 return 0; 1402 return 0;
1406 if (rDuration == 0 && endtime > rEndDateTime) 1403 if (rDuration == 0 && endtime > rEndDateTime)
1407 enddate = rEndDateTime.date(); 1404 enddate = rEndDateTime.date();
1408 else if (!mFloats && mRecurStart.time() > endtime.time()) 1405 else if (!mFloats && mRecurStart.time() > endtime.time())
1409 enddate = enddate.addDays(-1); 1406 enddate = enddate.addDays(-1);
1410 break; 1407 break;
1411 case NEXT_AFTER_DATE: 1408 case NEXT_AFTER_DATE:
1412 // Find next recurrence AFTER endtime 1409 // Find next recurrence AFTER endtime
1413 if (endtime < mRecurStart) { 1410 if (endtime < mRecurStart) {
1414 endtime = mRecurStart; 1411 endtime = mRecurStart;
1415 return 1; 1412 return 1;
1416 } 1413 }
1417 if (rDuration == 0 && endtime >= rEndDateTime) { 1414 if (rDuration == 0 && endtime >= rEndDateTime) {
1418 endtime = QDateTime(); 1415 endtime = QDateTime();
1419 return 0; 1416 return 0;
1420 } 1417 }
1421 if (!mFloats && mRecurStart.time() > endtime.time()) 1418 if (!mFloats && mRecurStart.time() > endtime.time())
1422 enddate = enddate.addDays(-1); 1419 enddate = enddate.addDays(-1);
1423 break; 1420 break;
1424 default: 1421 default:
1425 endtime = QDateTime(); 1422 endtime = QDateTime();
1426 return 0; 1423 return 0;
1427 } 1424 }
1428 1425
1429 int count = 0; // default = error 1426 int count = 0; // default = error
1430 bool timed = false; 1427 bool timed = false;
1431 switch (recurs) { 1428 switch (recurs) {
1432 case rMinutely: 1429 case rMinutely:
1433 timed = true; 1430 timed = true;
1434 count = secondlyCalc(func, endtime, rFreq*60); 1431 count = secondlyCalc(func, endtime, rFreq*60);
1435 break; 1432 break;
1436 case rHourly: 1433 case rHourly:
1437 timed = true; 1434 timed = true;
1438 count = secondlyCalc(func, endtime, rFreq*3600); 1435 count = secondlyCalc(func, endtime, rFreq*3600);
1439 break; 1436 break;
1440 case rDaily: 1437 case rDaily:
1441 count = dailyCalc(func, enddate); 1438 count = dailyCalc(func, enddate);
1442 break; 1439 break;
1443 case rWeekly: 1440 case rWeekly:
1444 count = weeklyCalc(func, enddate); 1441 count = weeklyCalc(func, enddate);
1445 break; 1442 break;
1446 case rMonthlyPos: 1443 case rMonthlyPos:
1447 case rMonthlyDay: 1444 case rMonthlyDay:
1448 count = monthlyCalc(func, enddate); 1445 count = monthlyCalc(func, enddate);
1449 break; 1446 break;
1450 case rYearlyMonth: 1447 case rYearlyMonth:
1451 count = yearlyMonthCalc(func, enddate); 1448 count = yearlyMonthCalc(func, enddate);
1452 break; 1449 break;
1453 case rYearlyPos: 1450 case rYearlyPos:
1454 count = yearlyPosCalc(func, enddate); 1451 count = yearlyPosCalc(func, enddate);
1455 break; 1452 break;
1456 case rYearlyDay: 1453 case rYearlyDay:
1457 count = yearlyDayCalc(func, enddate); 1454 count = yearlyDayCalc(func, enddate);
1458 break; 1455 break;
1459 default: 1456 default:
1460 break; 1457 break;
1461 } 1458 }
1462 1459
1463 switch (func) { 1460 switch (func) {
1464 case END_DATE_AND_COUNT: 1461 case END_DATE_AND_COUNT:
1465 case NEXT_AFTER_DATE: 1462 case NEXT_AFTER_DATE:
1466 if (count == 0) 1463 if (count == 0)
1467 endtime = QDateTime(); 1464 endtime = QDateTime();
1468 else if (!timed) { 1465 else if (!timed) {
1469 endtime.setDate(enddate); 1466 endtime.setDate(enddate);
1470 endtime.setTime(mRecurStart.time()); 1467 endtime.setTime(mRecurStart.time());
1471 } 1468 }
1472 break; 1469 break;
1473 case COUNT_TO_DATE: 1470 case COUNT_TO_DATE:
1474 break; 1471 break;
1475 } 1472 }
1476 return count; 1473 return count;
1477} 1474}
1478 1475
1479int Recurrence::recurCalc(PeriodFunc func, QDate &enddate) const 1476int Recurrence::recurCalc(PeriodFunc func, QDate &enddate) const
1480{ 1477{
1481 QDateTime endtime(enddate, QTime(23,59,59)); 1478 QDateTime endtime(enddate, QTime(23,59,59));
1482 switch (func) { 1479 switch (func) {
1483 case END_DATE_AND_COUNT: 1480 case END_DATE_AND_COUNT:
1484 if (rDuration < 0) { 1481 if (rDuration < 0) {
1485 enddate = QDate(); 1482 enddate = QDate();
1486 return 0; // infinite recurrence 1483 return 0; // infinite recurrence
1487 } 1484 }
1488 if (rDuration == 0) { 1485 if (rDuration == 0) {
1489 enddate = rEndDateTime.date(); 1486 enddate = rEndDateTime.date();
1490 func = COUNT_TO_DATE; 1487 func = COUNT_TO_DATE;
1491 } 1488 }
1492 break; 1489 break;
1493 case COUNT_TO_DATE: 1490 case COUNT_TO_DATE:
1494 // Count recurrences up to and including the specified date. 1491 // Count recurrences up to and including the specified date.
1495 if (enddate < mRecurStart.date()) 1492 if (enddate < mRecurStart.date())
1496 return 0; 1493 return 0;
1497 if (rDuration == 0 && enddate > rEndDateTime.date()) { 1494 if (rDuration == 0 && enddate > rEndDateTime.date()) {
1498 enddate = rEndDateTime.date(); 1495 enddate = rEndDateTime.date();
1499 endtime.setDate(enddate); 1496 endtime.setDate(enddate);
1500 } 1497 }
1501 break; 1498 break;
1502 case NEXT_AFTER_DATE: 1499 case NEXT_AFTER_DATE:
1503 if (enddate < mRecurStart.date()) { 1500 if (enddate < mRecurStart.date()) {
1504 enddate = mRecurStart.date(); 1501 enddate = mRecurStart.date();
1505 return 1; 1502 return 1;
1506 } 1503 }
1507 if (rDuration == 0 && enddate >= rEndDateTime.date()) { 1504 if (rDuration == 0 && enddate >= rEndDateTime.date()) {
1508 enddate = QDate(); 1505 enddate = QDate();
1509 return 0; 1506 return 0;
1510 } 1507 }
1511 break; 1508 break;
1512 default: 1509 default:
1513 enddate = QDate(); 1510 enddate = QDate();
1514 return 0; 1511 return 0;
1515 } 1512 }
1516 1513
1517 int count = 0; // default = error 1514 int count = 0; // default = error
1518 bool timed = false; 1515 bool timed = false;
1519 switch (recurs) { 1516 switch (recurs) {
1520 case rMinutely: 1517 case rMinutely:
1521 timed = true; 1518 timed = true;
1522 count = secondlyCalc(func, endtime, rFreq*60); 1519 count = secondlyCalc(func, endtime, rFreq*60);
1523 break; 1520 break;
1524 case rHourly: 1521 case rHourly:
1525 timed = true; 1522 timed = true;
1526 count = secondlyCalc(func, endtime, rFreq*3600); 1523 count = secondlyCalc(func, endtime, rFreq*3600);
1527 break; 1524 break;
1528 case rDaily: 1525 case rDaily:
1529 count = dailyCalc(func, enddate); 1526 count = dailyCalc(func, enddate);
1530 break; 1527 break;
1531 case rWeekly: 1528 case rWeekly:
1532 count = weeklyCalc(func, enddate); 1529 count = weeklyCalc(func, enddate);
1533 break; 1530 break;
1534 case rMonthlyPos: 1531 case rMonthlyPos:
1535 case rMonthlyDay: 1532 case rMonthlyDay:
1536 count = monthlyCalc(func, enddate); 1533 count = monthlyCalc(func, enddate);
1537 break; 1534 break;
1538 case rYearlyMonth: 1535 case rYearlyMonth:
1539 count = yearlyMonthCalc(func, enddate); 1536 count = yearlyMonthCalc(func, enddate);
1540 break; 1537 break;
1541 case rYearlyPos: 1538 case rYearlyPos:
1542 count = yearlyPosCalc(func, enddate); 1539 count = yearlyPosCalc(func, enddate);
1543 break; 1540 break;
1544 case rYearlyDay: 1541 case rYearlyDay:
1545 count = yearlyDayCalc(func, enddate); 1542 count = yearlyDayCalc(func, enddate);
1546 break; 1543 break;
1547 default: 1544 default:
1548 break; 1545 break;
1549 } 1546 }
1550 1547
1551 switch (func) { 1548 switch (func) {
1552 case END_DATE_AND_COUNT: 1549 case END_DATE_AND_COUNT:
1553 case NEXT_AFTER_DATE: 1550 case NEXT_AFTER_DATE:
1554 if (count == 0) 1551 if (count == 0)
1555 endtime = QDate(); 1552 endtime = QDate();
1556 else if (timed) 1553 else if (timed)
1557 enddate = endtime.date(); 1554 enddate = endtime.date();
1558 break; 1555 break;
1559 case COUNT_TO_DATE: 1556 case COUNT_TO_DATE:
1560 break; 1557 break;
1561 } 1558 }
1562 return count; 1559 return count;
1563} 1560}
1564 1561
1565/* Find count and, depending on 'func', the end date/time of a secondly recurrence. 1562/* Find count and, depending on 'func', the end date/time of a secondly recurrence.
1566 * Reply = total number of occurrences up to 'endtime', or 0 if error. 1563 * Reply = total number of occurrences up to 'endtime', or 0 if error.
1567 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'endtime' is updated to the 1564 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'endtime' is updated to the
1568 * recurrence end date/time. 1565 * recurrence end date/time.
1569 */ 1566 */
1570int Recurrence::secondlyCalc(PeriodFunc func, QDateTime &endtime, int freq) const 1567int Recurrence::secondlyCalc(PeriodFunc func, QDateTime &endtime, int freq) const
1571{ 1568{
1572 switch (func) { 1569 switch (func) {
1573 case END_DATE_AND_COUNT: 1570 case END_DATE_AND_COUNT:
1574 endtime = mRecurStart.addSecs((rDuration + mRecurExDatesCount - 1) * freq); 1571 endtime = mRecurStart.addSecs((rDuration + mRecurExDatesCount - 1) * freq);
1575 return rDuration + mRecurExDatesCount; 1572 return rDuration + mRecurExDatesCount;
1576 case COUNT_TO_DATE: { 1573 case COUNT_TO_DATE: {
1577 int n = mRecurStart.secsTo(endtime)/freq + 1; 1574 int n = mRecurStart.secsTo(endtime)/freq + 1;
1578 if (rDuration > 0 && n > rDuration + mRecurExDatesCount) 1575 if (rDuration > 0 && n > rDuration + mRecurExDatesCount)
1579 return rDuration + mRecurExDatesCount; 1576 return rDuration + mRecurExDatesCount;
1580 return n; 1577 return n;
1581 } 1578 }
1582 case NEXT_AFTER_DATE: { 1579 case NEXT_AFTER_DATE: {
1583 int count = mRecurStart.secsTo(endtime) / freq + 2; 1580 int count = mRecurStart.secsTo(endtime) / freq + 2;
1584 if (rDuration > 0 && count > rDuration) 1581 if (rDuration > 0 && count > rDuration)
1585 return 0; 1582 return 0;
1586 endtime = mRecurStart.addSecs((count - 1)*freq); 1583 endtime = mRecurStart.addSecs((count - 1)*freq);
1587 return count; 1584 return count;
1588 } 1585 }
1589 } 1586 }
1590 return 0; 1587 return 0;
1591} 1588}
1592 1589
1593/* Find count and, depending on 'func', the end date of a daily recurrence. 1590/* Find count and, depending on 'func', the end date of a daily recurrence.
1594 * Reply = total number of occurrences up to 'enddate', or 0 if error. 1591 * Reply = total number of occurrences up to 'enddate', or 0 if error.
1595 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the 1592 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the
1596 * recurrence end date. 1593 * recurrence end date.
1597 */ 1594 */
1598int Recurrence::dailyCalc(PeriodFunc func, QDate &enddate) const 1595int Recurrence::dailyCalc(PeriodFunc func, QDate &enddate) const
1599{ 1596{
1600 QDate dStart = mRecurStart.date(); 1597 QDate dStart = mRecurStart.date();
1601 switch (func) { 1598 switch (func) {
1602 case END_DATE_AND_COUNT: 1599 case END_DATE_AND_COUNT:
1603 enddate = dStart.addDays((rDuration + mRecurExDatesCount - 1) * rFreq); 1600 enddate = dStart.addDays((rDuration + mRecurExDatesCount - 1) * rFreq);
1604 return rDuration + mRecurExDatesCount; 1601 return rDuration + mRecurExDatesCount;
1605 case COUNT_TO_DATE: { 1602 case COUNT_TO_DATE: {
1606 int n = dStart.daysTo(enddate)/rFreq + 1; 1603 int n = dStart.daysTo(enddate)/rFreq + 1;
1607 if (rDuration > 0 && n > rDuration + mRecurExDatesCount) 1604 if (rDuration > 0 && n > rDuration + mRecurExDatesCount)
1608 return rDuration + mRecurExDatesCount; 1605 return rDuration + mRecurExDatesCount;
1609 return n; 1606 return n;
1610 } 1607 }
1611 case NEXT_AFTER_DATE: { 1608 case NEXT_AFTER_DATE: {
1612 int count = dStart.daysTo(enddate) / rFreq + 2; 1609 int count = dStart.daysTo(enddate) / rFreq + 2;
1613 if (rDuration > 0 && count > rDuration) 1610 if (rDuration > 0 && count > rDuration)
1614 return 0; 1611 return 0;
1615 enddate = dStart.addDays((count - 1)*rFreq); 1612 enddate = dStart.addDays((count - 1)*rFreq);
1616 return count; 1613 return count;
1617 } 1614 }
1618 } 1615 }
1619 return 0; 1616 return 0;
1620} 1617}
1621 1618
1622/* Find count and, depending on 'func', the end date of a weekly recurrence. 1619/* Find count and, depending on 'func', the end date of a weekly recurrence.
1623 * Reply = total number of occurrences up to 'enddate', or 0 if error. 1620 * Reply = total number of occurrences up to 'enddate', or 0 if error.
1624 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the 1621 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the
1625 * recurrence end date. 1622 * recurrence end date.
1626 */ 1623 */
1627int Recurrence::weeklyCalc(PeriodFunc func, QDate &enddate) const 1624int Recurrence::weeklyCalc(PeriodFunc func, QDate &enddate) const
1628{ 1625{
1629 int daysPerWeek = 0; 1626 int daysPerWeek = 0;
1630 for (int i = 0; i < 7; ++i) { 1627 for (int i = 0; i < 7; ++i) {
1631 if (rDays.testBit((uint)i)) 1628 if (rDays.testBit((uint)i))
1632 ++daysPerWeek; 1629 ++daysPerWeek;
1633 } 1630 }
1634 if (!daysPerWeek) 1631 if (!daysPerWeek)
1635 return 0; // there are no days to recur on 1632 return 0; // there are no days to recur on
1636 1633
1637 switch (func) { 1634 switch (func) {
1638 case END_DATE_AND_COUNT: 1635 case END_DATE_AND_COUNT:
1639 return weeklyCalcEndDate(enddate, daysPerWeek); 1636 return weeklyCalcEndDate(enddate, daysPerWeek);
1640 case COUNT_TO_DATE: 1637 case COUNT_TO_DATE:
1641 return weeklyCalcToDate(enddate, daysPerWeek); 1638 return weeklyCalcToDate(enddate, daysPerWeek);
1642 case NEXT_AFTER_DATE: 1639 case NEXT_AFTER_DATE:
1643 return weeklyCalcNextAfter(enddate, daysPerWeek); 1640 return weeklyCalcNextAfter(enddate, daysPerWeek);
1644 } 1641 }
1645 return 0; 1642 return 0;
1646} 1643}
1647 1644
1648int Recurrence::weeklyCalcEndDate(QDate &enddate, int daysPerWeek) const 1645int Recurrence::weeklyCalcEndDate(QDate &enddate, int daysPerWeek) const
1649{ 1646{
1650 int startDayOfWeek = mRecurStart.date().dayOfWeek(); // 1..7 1647 int startDayOfWeek = mRecurStart.date().dayOfWeek(); // 1..7
1651 int countGone = 0; 1648 int countGone = 0;
1652 int daysGone = 0; 1649 int daysGone = 0;
1653 uint countTogo = rDuration + mRecurExDatesCount; 1650 uint countTogo = rDuration + mRecurExDatesCount;
1654 if (startDayOfWeek != rWeekStart) { 1651 if (startDayOfWeek != rWeekStart) {
1655 // Check what remains of the start week 1652 // Check what remains of the start week
1656 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) { 1653 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) {
1657 ++daysGone; 1654 ++daysGone;
1658 if (rDays.testBit((uint)i)) { 1655 if (rDays.testBit((uint)i)) {
1659 ++countGone; 1656 ++countGone;
1660 if (--countTogo == 0) 1657 if (--countTogo == 0)
1661 break; 1658 break;
1662 } 1659 }
1663 } 1660 }
1664 daysGone += 7 * (rFreq - 1); 1661 daysGone += 7 * (rFreq - 1);
1665 } 1662 }
1666 if (countTogo) { 1663 if (countTogo) {
1667 // Skip the remaining whole weeks 1664 // Skip the remaining whole weeks
1668 // Leave at least 1 recurrence remaining, in order to get its date 1665 // Leave at least 1 recurrence remaining, in order to get its date
1669 int wholeWeeks = (countTogo - 1) / daysPerWeek; 1666 int wholeWeeks = (countTogo - 1) / daysPerWeek;
1670 daysGone += wholeWeeks * 7 * rFreq; 1667 daysGone += wholeWeeks * 7 * rFreq;
1671 countGone += wholeWeeks * daysPerWeek; 1668 countGone += wholeWeeks * daysPerWeek;
1672 countTogo -= wholeWeeks * daysPerWeek; 1669 countTogo -= wholeWeeks * daysPerWeek;
1673 // Check the last week in the recurrence 1670 // Check the last week in the recurrence
1674 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) { 1671 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) {
1675 ++daysGone; 1672 ++daysGone;
1676 if (rDays.testBit((uint)i)) { 1673 if (rDays.testBit((uint)i)) {
1677 ++countGone; 1674 ++countGone;
1678 if (--countTogo == 0) 1675 if (--countTogo == 0)
1679 break; 1676 break;
1680 } 1677 }
1681 } 1678 }
1682 } 1679 }
1683 enddate = mRecurStart.date().addDays(daysGone); 1680 enddate = mRecurStart.date().addDays(daysGone);
1684 return countGone; 1681 return countGone;
1685} 1682}
1686 1683
1687int Recurrence::weeklyCalcToDate(const QDate &enddate, int daysPerWeek) const 1684int Recurrence::weeklyCalcToDate(const QDate &enddate, int daysPerWeek) const
1688{ 1685{
1689 QDate dStart = mRecurStart.date(); 1686 QDate dStart = mRecurStart.date();
1690 int startDayOfWeek = dStart.dayOfWeek(); // 1..7 1687 int startDayOfWeek = dStart.dayOfWeek(); // 1..7
1691 int countGone = 0; 1688 int countGone = 0;
1692 int daysGone = 0; 1689 int daysGone = 0;
1693 int totalDays = dStart.daysTo(enddate) + 1; 1690 int totalDays = dStart.daysTo(enddate) + 1;
1694 int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX; 1691 int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX;
1695 1692
1696 if (startDayOfWeek != rWeekStart) { 1693 if (startDayOfWeek != rWeekStart) {
1697 // Check what remains of the start week 1694 // Check what remains of the start week
1698 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) { 1695 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) {
1699 if (rDays.testBit((uint)i)) { 1696 if (rDays.testBit((uint)i)) {
1700 if (++countGone >= countMax) 1697 if (++countGone >= countMax)
1701 return countMax; 1698 return countMax;
1702 } 1699 }
1703 if (++daysGone == totalDays) 1700 if (++daysGone == totalDays)
1704 return countGone; 1701 return countGone;
1705 } 1702 }
1706 daysGone += 7 * (rFreq - 1); 1703 daysGone += 7 * (rFreq - 1);
1707 if (daysGone >= totalDays) 1704 if (daysGone >= totalDays)
1708 return countGone; 1705 return countGone;
1709 } 1706 }
1710 // Skip the remaining whole weeks 1707 // Skip the remaining whole weeks
1711 int wholeWeeks = (totalDays - daysGone) / 7; 1708 int wholeWeeks = (totalDays - daysGone) / 7;
1712 countGone += (wholeWeeks / rFreq) * daysPerWeek; 1709 countGone += (wholeWeeks / rFreq) * daysPerWeek;
1713 if (countGone >= countMax) 1710 if (countGone >= countMax)
1714 return countMax; 1711 return countMax;
1715 daysGone += wholeWeeks * 7; 1712 daysGone += wholeWeeks * 7;
1716 if (daysGone >= totalDays // have we reached the end date? 1713 if (daysGone >= totalDays // have we reached the end date?
1717 || wholeWeeks % rFreq) // is end week a recurrence week? 1714 || wholeWeeks % rFreq) // is end week a recurrence week?
1718 return countGone; 1715 return countGone;
1719 1716
1720 // Check the last week in the recurrence 1717 // Check the last week in the recurrence
1721 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) { 1718 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) {
1722 if (rDays.testBit((uint)i)) { 1719 if (rDays.testBit((uint)i)) {
1723 if (++countGone >= countMax) 1720 if (++countGone >= countMax)
1724 return countMax; 1721 return countMax;
1725 } 1722 }
1726 if (++daysGone == totalDays) 1723 if (++daysGone == totalDays)
1727 return countGone; 1724 return countGone;
1728 } 1725 }
1729 return countGone; 1726 return countGone;
1730} 1727}
1731 1728
1732int Recurrence::weeklyCalcNextAfter(QDate &enddate, int daysPerWeek) const 1729int Recurrence::weeklyCalcNextAfter(QDate &enddate, int daysPerWeek) const
1733{ 1730{
1734 QDate dStart = mRecurStart.date(); 1731 QDate dStart = mRecurStart.date();
1735 int startDayOfWeek = dStart.dayOfWeek(); // 1..7 1732 int startDayOfWeek = dStart.dayOfWeek(); // 1..7
1736 int totalDays = dStart.daysTo(enddate) + 1; 1733 int totalDays = dStart.daysTo(enddate) + 1;
1737 uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX; 1734 uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX;
1738 int countGone = 0; 1735 int countGone = 0;
1739 int daysGone = 0; 1736 int daysGone = 0;
1740 int recurWeeks; 1737 int recurWeeks;
1741 1738
1742 if (startDayOfWeek != rWeekStart) { 1739 if (startDayOfWeek != rWeekStart) {
1743 // Check what remains of the start week 1740 // Check what remains of the start week
1744 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) { 1741 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) {
1745 ++daysGone; 1742 ++daysGone;
1746 if (rDays.testBit((uint)i)) { 1743 if (rDays.testBit((uint)i)) {
1747 ++countGone; 1744 ++countGone;
1748 if (daysGone > totalDays) 1745 if (daysGone > totalDays)
1749 goto ex; 1746 goto ex;
1750 if (--countTogo == 0) 1747 if (--countTogo == 0)
1751 return 0; 1748 return 0;
1752 } 1749 }
1753 } 1750 }
1754 daysGone += 7 * (rFreq - 1); 1751 daysGone += 7 * (rFreq - 1);
1755 } 1752 }
1756 1753
1757 // Skip the remaining whole weeks 1754 // Skip the remaining whole weeks
1758 recurWeeks = (totalDays - daysGone) / (7 * rFreq); 1755 recurWeeks = (totalDays - daysGone) / (7 * rFreq);
1759 if (recurWeeks) { 1756 if (recurWeeks) {
1760 int n = recurWeeks * daysPerWeek; 1757 int n = recurWeeks * daysPerWeek;
1761 if (static_cast<uint>(n) > countTogo) 1758 if (static_cast<uint>(n) > countTogo)
1762 return 0; // reached end of recurrence 1759 return 0; // reached end of recurrence
1763 countGone += n; 1760 countGone += n;
1764 countTogo -= n; 1761 countTogo -= n;
1765 daysGone += recurWeeks * 7 * rFreq; 1762 daysGone += recurWeeks * 7 * rFreq;
1766 } 1763 }
1767 1764
1768 // Check the last week or two in the recurrence 1765 // Check the last week or two in the recurrence
1769 for ( ; ; ) { 1766 for ( ; ; ) {
1770 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) { 1767 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) {
1771 ++daysGone; 1768 ++daysGone;
1772 if (rDays.testBit((uint)i)) { 1769 if (rDays.testBit((uint)i)) {
1773 ++countGone; 1770 ++countGone;
1774 if (daysGone > totalDays) 1771 if (daysGone > totalDays)
1775 goto ex; 1772 goto ex;
1776 if (--countTogo == 0) 1773 if (--countTogo == 0)
1777 return 0; 1774 return 0;
1778 } 1775 }
1779 } 1776 }
1780 daysGone += 7 * (rFreq - 1); 1777 daysGone += 7 * (rFreq - 1);
1781 } 1778 }
1782ex: 1779ex:
1783 enddate = dStart.addDays(daysGone); 1780 enddate = dStart.addDays(daysGone);
1784 return countGone; 1781 return countGone;
1785} 1782}
1786 1783
1787/* Find count and, depending on 'func', the end date of a monthly recurrence. 1784/* Find count and, depending on 'func', the end date of a monthly recurrence.
1788 * Reply = total number of occurrences up to 'enddate', or 0 if error. 1785 * Reply = total number of occurrences up to 'enddate', or 0 if error.
1789 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the 1786 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the
1790 * recurrence end date. 1787 * recurrence end date.
1791 */ 1788 */
1792struct Recurrence::MonthlyData { 1789struct Recurrence::MonthlyData {
1793 const Recurrence *recurrence; 1790 const Recurrence *recurrence;
1794 int year; // current year 1791 int year; // current year
1795 int month; // current month 0..11 1792 int month; // current month 0..11
1796 int day; // current day of month 1..31 1793 int day; // current day of month 1..31
1797 bool varies; // true if recurring days vary between different months 1794 bool varies; // true if recurring days vary between different months
1798 private: 1795 private:
1799 QValueList<int> days28, days29, days30, days31; // recurring days in months of each length 1796 QValueList<int> days28, days29, days30, days31; // recurring days in months of each length
1800 QValueList<int> *recurDays[4]; 1797 QValueList<int> *recurDays[4];
1801 public: 1798 public:
1802 MonthlyData(const Recurrence* r, const QDate &date) 1799 MonthlyData(const Recurrence* r, const QDate &date)
1803 : recurrence(r), year(date.year()), month(date.month()-1), day(date.day()) 1800 : recurrence(r), year(date.year()), month(date.month()-1), day(date.day())
@@ -2891,523 +2888,514 @@ int Recurrence::yearlyDayCalcToDate(const QDate &enddate, YearlyDayData &data) c
2891 while (data.year < endYear) { 2888 while (data.year < endYear) {
2892 uint n = data.dayCount(); 2889 uint n = data.dayCount();
2893 countGone += n; 2890 countGone += n;
2894 if (countGone >= countMax) 2891 if (countGone >= countMax)
2895 return countMax; 2892 return countMax;
2896 data.year += rFreq; 2893 data.year += rFreq;
2897 } 2894 }
2898 if (data.year > endYear) 2895 if (data.year > endYear)
2899 return countGone; 2896 return countGone;
2900 } else { 2897 } else {
2901 // The number of recurrences is the same every year. 2898 // The number of recurrences is the same every year.
2902 // Skip the remaining whole years. 2899 // Skip the remaining whole years.
2903 int wholeYears = endYear - data.year; 2900 int wholeYears = endYear - data.year;
2904 countGone += (wholeYears / rFreq) * rYearNums.count(); 2901 countGone += (wholeYears / rFreq) * rYearNums.count();
2905 if (countGone >= countMax) 2902 if (countGone >= countMax)
2906 return countMax; 2903 return countMax;
2907 if (wholeYears % rFreq) 2904 if (wholeYears % rFreq)
2908 return countGone; // end year isn't a recurrence year 2905 return countGone; // end year isn't a recurrence year
2909 data.year = endYear; 2906 data.year = endYear;
2910 } 2907 }
2911 2908
2912 if (data.year <= endYear) { 2909 if (data.year <= endYear) {
2913 // Check the last year in the recurrence 2910 // Check the last year in the recurrence
2914 for (QPtrListIterator<int> it(rYearNums); it.current(); ++it) { 2911 for (QPtrListIterator<int> it(rYearNums); it.current(); ++it) {
2915 if (*it.current() > endDay) 2912 if (*it.current() > endDay)
2916 return countGone; 2913 return countGone;
2917 if (++countGone >= countMax) 2914 if (++countGone >= countMax)
2918 return countMax; 2915 return countMax;
2919 } 2916 }
2920 } 2917 }
2921 return countGone; 2918 return countGone;
2922} 2919}
2923 2920
2924int Recurrence::yearlyDayCalcNextAfter(QDate &enddate, YearlyDayData &data) const 2921int Recurrence::yearlyDayCalcNextAfter(QDate &enddate, YearlyDayData &data) const
2925{ 2922{
2926 uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX; 2923 uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX;
2927 int countGone = 0; 2924 int countGone = 0;
2928 int endYear = enddate.year(); 2925 int endYear = enddate.year();
2929 int endDay = enddate.dayOfYear(); 2926 int endDay = enddate.dayOfYear();
2930 2927
2931 if (data.day > 1) { 2928 if (data.day > 1) {
2932 // Check what remains of the start year 2929 // Check what remains of the start year
2933 bool leapOK = data.isMaxDayCount(); 2930 bool leapOK = data.isMaxDayCount();
2934 for (QPtrListIterator<int> it(rYearNums); it.current(); ++it) { 2931 for (QPtrListIterator<int> it(rYearNums); it.current(); ++it) {
2935 int d = *it.current(); 2932 int d = *it.current();
2936 if (d >= data.day && (leapOK || d < 366)) { 2933 if (d >= data.day && (leapOK || d < 366)) {
2937 ++countGone; 2934 ++countGone;
2938 if (data.year == endYear && d > endDay) { 2935 if (data.year == endYear && d > endDay) {
2939 data.day = d; 2936 data.day = d;
2940 goto ex; 2937 goto ex;
2941 } 2938 }
2942 if (--countTogo == 0) 2939 if (--countTogo == 0)
2943 return 0; 2940 return 0;
2944 } 2941 }
2945 } 2942 }
2946 data.day = 1; 2943 data.day = 1;
2947 data.year += rFreq; 2944 data.year += rFreq;
2948 } 2945 }
2949 2946
2950 if (data.varies) { 2947 if (data.varies) {
2951 // The number of recurrences is different in leap years, 2948 // The number of recurrences is different in leap years,
2952 // so check year-by-year. 2949 // so check year-by-year.
2953 while (data.year <= endYear) { 2950 while (data.year <= endYear) {
2954 uint n = data.dayCount(); 2951 uint n = data.dayCount();
2955 if (data.year == endYear && *rYearNums.getLast() > endDay) 2952 if (data.year == endYear && *rYearNums.getLast() > endDay)
2956 break; 2953 break;
2957 if (n >= countTogo) 2954 if (n >= countTogo)
2958 break; 2955 break;
2959 countTogo -= n; 2956 countTogo -= n;
2960 countGone += n; 2957 countGone += n;
2961 data.year += rFreq; 2958 data.year += rFreq;
2962 } 2959 }
2963 } else { 2960 } else {
2964 // The number of recurrences is the same every year, 2961 // The number of recurrences is the same every year,
2965 // so skip the year-by-year check. 2962 // so skip the year-by-year check.
2966 // Skip the remaining whole years to at least endYear. 2963 // Skip the remaining whole years to at least endYear.
2967 int daysPerYear = rYearNums.count(); 2964 int daysPerYear = rYearNums.count();
2968 int recurYears = (endYear - data.year + rFreq - 1) / rFreq; 2965 int recurYears = (endYear - data.year + rFreq - 1) / rFreq;
2969 if ((endYear - data.year)%rFreq == 0 2966 if ((endYear - data.year)%rFreq == 0
2970 && *rYearNums.getLast() <= endDay) 2967 && *rYearNums.getLast() <= endDay)
2971 ++recurYears; // required year is after endYear 2968 ++recurYears; // required year is after endYear
2972 if (recurYears) { 2969 if (recurYears) {
2973 int n = recurYears * daysPerYear; 2970 int n = recurYears * daysPerYear;
2974 if (static_cast<uint>(n) > countTogo) 2971 if (static_cast<uint>(n) > countTogo)
2975 return 0; // reached end of recurrence 2972 return 0; // reached end of recurrence
2976 countTogo -= n; 2973 countTogo -= n;
2977 countGone += n; 2974 countGone += n;
2978 data.year += recurYears * rFreq; 2975 data.year += recurYears * rFreq;
2979 } 2976 }
2980 } 2977 }
2981 2978
2982 // Check the last year in the recurrence 2979 // Check the last year in the recurrence
2983 for (QPtrListIterator<int> it(rYearNums); it.current(); ++it) { 2980 for (QPtrListIterator<int> it(rYearNums); it.current(); ++it) {
2984 ++countGone; 2981 ++countGone;
2985 int d = *it.current(); 2982 int d = *it.current();
2986 if (data.year > endYear || d > endDay) { 2983 if (data.year > endYear || d > endDay) {
2987 data.day = d; 2984 data.day = d;
2988 break; 2985 break;
2989 } 2986 }
2990 if (--countTogo == 0) 2987 if (--countTogo == 0)
2991 return 0; 2988 return 0;
2992 } 2989 }
2993ex: 2990ex:
2994 enddate = data.date(); 2991 enddate = data.date();
2995 return countGone; 2992 return countGone;
2996} 2993}
2997 2994
2998// Get the days in this month which recur, in numerical order. 2995// Get the days in this month which recur, in numerical order.
2999// Parameters: daysInMonth = number of days in this month 2996// Parameters: daysInMonth = number of days in this month
3000// startDayOfWeek = day of week for first day of month. 2997// startDayOfWeek = day of week for first day of month.
3001void Recurrence::getMonthlyPosDays(QValueList<int> &list, int daysInMonth, int startDayOfWeek) const 2998void Recurrence::getMonthlyPosDays(QValueList<int> &list, int daysInMonth, int startDayOfWeek) const
3002{ 2999{
3003 list.clear(); 3000 list.clear();
3004 int endDayOfWeek = (startDayOfWeek + daysInMonth - 2) % 7 + 1; 3001 int endDayOfWeek = (startDayOfWeek + daysInMonth - 2) % 7 + 1;
3005 // Go through the list, compiling a bit list of actual day numbers 3002 // Go through the list, compiling a bit list of actual day numbers
3006 Q_UINT32 days = 0; 3003 Q_UINT32 days = 0;
3007 for (QPtrListIterator<rMonthPos> pos(rMonthPositions); pos.current(); ++pos) { 3004 for (QPtrListIterator<rMonthPos> pos(rMonthPositions); pos.current(); ++pos) {
3008 int weeknum = pos.current()->rPos - 1; // get 0-based week number 3005 int weeknum = pos.current()->rPos - 1; // get 0-based week number
3009 QBitArray &rdays = pos.current()->rDays; 3006 QBitArray &rdays = pos.current()->rDays;
3010 if (pos.current()->negative) { 3007 if (pos.current()->negative) {
3011 // nth days before the end of the month 3008 // nth days before the end of the month
3012 for (uint i = 1; i <= 7; ++i) { 3009 for (uint i = 1; i <= 7; ++i) {
3013 if (rdays.testBit(i - 1)) { 3010 if (rdays.testBit(i - 1)) {
3014 int day = daysInMonth - weeknum*7 - (endDayOfWeek - i + 7) % 7; 3011 int day = daysInMonth - weeknum*7 - (endDayOfWeek - i + 7) % 7;
3015 if (day > 0) 3012 if (day > 0)
3016 days |= 1 << (day - 1); 3013 days |= 1 << (day - 1);
3017 } 3014 }
3018 } 3015 }
3019 } else { 3016 } else {
3020 // nth days after the start of the month 3017 // nth days after the start of the month
3021 for (uint i = 1; i <= 7; ++i) { 3018 for (uint i = 1; i <= 7; ++i) {
3022 if (rdays.testBit(i - 1)) { 3019 if (rdays.testBit(i - 1)) {
3023 int day = 1 + weeknum*7 + (i - startDayOfWeek + 7) % 7; 3020 int day = 1 + weeknum*7 + (i - startDayOfWeek + 7) % 7;
3024 if (day <= daysInMonth) 3021 if (day <= daysInMonth)
3025 days |= 1 << (day - 1); 3022 days |= 1 << (day - 1);
3026 } 3023 }
3027 } 3024 }
3028 } 3025 }
3029 } 3026 }
3030 // Compile the ordered list 3027 // Compile the ordered list
3031 Q_UINT32 mask = 1; 3028 Q_UINT32 mask = 1;
3032 for (int i = 0; i < daysInMonth; mask <<= 1, ++i) { 3029 for (int i = 0; i < daysInMonth; mask <<= 1, ++i) {
3033 if (days & mask) 3030 if (days & mask)
3034 list.append(i + 1); 3031 list.append(i + 1);
3035 } 3032 }
3036} 3033}
3037 3034
3038// Get the number of days in the month which recur. 3035// Get the number of days in the month which recur.
3039// Reply = -1 if the number varies from month to month. 3036// Reply = -1 if the number varies from month to month.
3040int Recurrence::countMonthlyPosDays() const 3037int Recurrence::countMonthlyPosDays() const
3041{ 3038{
3042 int count = 0; 3039 int count = 0;
3043 Q_UINT8 positive[5] = { 0, 0, 0, 0, 0 }; 3040 Q_UINT8 positive[5] = { 0, 0, 0, 0, 0 };
3044 Q_UINT8 negative[4] = { 0, 0, 0, 0 }; 3041 Q_UINT8 negative[4] = { 0, 0, 0, 0 };
3045 for (QPtrListIterator<rMonthPos> pos(rMonthPositions); pos.current(); ++pos) { 3042 for (QPtrListIterator<rMonthPos> pos(rMonthPositions); pos.current(); ++pos) {
3046 int weeknum = pos.current()->rPos; 3043 int weeknum = pos.current()->rPos;
3047 Q_UINT8* wk; 3044 Q_UINT8* wk;
3048 if (pos.current()->negative) { 3045 if (pos.current()->negative) {
3049 // nth days before the end of the month 3046 // nth days before the end of the month
3050 if (weeknum > 4) 3047 if (weeknum > 4)
3051 return -1; // days in 5th week are often missing 3048 return -1; // days in 5th week are often missing
3052 wk = &negative[4 - weeknum]; 3049 wk = &negative[4 - weeknum];
3053 } else { 3050 } else {
3054 // nth days after the start of the month 3051 // nth days after the start of the month
3055 if (weeknum > 4) 3052 if (weeknum > 4)
3056 return -1; // days in 5th week are often missing 3053 return -1; // days in 5th week are often missing
3057 wk = &positive[weeknum - 1]; 3054 wk = &positive[weeknum - 1];
3058 } 3055 }
3059 QBitArray &rdays = pos.current()->rDays; 3056 QBitArray &rdays = pos.current()->rDays;
3060 for (uint i = 0; i < 7; ++i) { 3057 for (uint i = 0; i < 7; ++i) {
3061 if (rdays.testBit(i)) { 3058 if (rdays.testBit(i)) {
3062 ++count; 3059 ++count;
3063 *wk |= (1 << i); 3060 *wk |= (1 << i);
3064 } 3061 }
3065 } 3062 }
3066 } 3063 }
3067 // Check for any possible days which could be duplicated by 3064 // Check for any possible days which could be duplicated by
3068 // a positive and a negative position. 3065 // a positive and a negative position.
3069 for (int i = 0; i < 4; ++i) { 3066 for (int i = 0; i < 4; ++i) {
3070 if (negative[i] & (positive[i] | positive[i+1])) 3067 if (negative[i] & (positive[i] | positive[i+1]))
3071 return -1; 3068 return -1;
3072 } 3069 }
3073 return count; 3070 return count;
3074} 3071}
3075 3072
3076// Get the days in this month which recur, in numerical order. 3073// Get the days in this month which recur, in numerical order.
3077// Reply = true if day numbers varies from month to month. 3074// Reply = true if day numbers varies from month to month.
3078bool Recurrence::getMonthlyDayDays(QValueList<int> &list, int daysInMonth) const 3075bool Recurrence::getMonthlyDayDays(QValueList<int> &list, int daysInMonth) const
3079{ 3076{
3080 list.clear(); 3077 list.clear();
3081 bool variable = false; 3078 bool variable = false;
3082 Q_UINT32 days = 0; 3079 Q_UINT32 days = 0;
3083 for (QPtrListIterator<int> it(rMonthDays); it.current(); ++it) { 3080 for (QPtrListIterator<int> it(rMonthDays); it.current(); ++it) {
3084 int day = *it.current(); 3081 int day = *it.current();
3085 if (day > 0) { 3082 if (day > 0) {
3086 // date in the month 3083 // date in the month
3087 if (day <= daysInMonth) 3084 if (day <= daysInMonth)
3088 days |= 1 << (day - 1); 3085 days |= 1 << (day - 1);
3089 if (day > 28 && day <= 31) 3086 if (day > 28 && day <= 31)
3090 variable = true; // this date does not appear in some months 3087 variable = true; // this date does not appear in some months
3091 } else if (day < 0) { 3088 } else if (day < 0) {
3092 // days before the end of the month 3089 // days before the end of the month
3093 variable = true; // this date varies depending on the month length 3090 variable = true; // this date varies depending on the month length
3094 day = daysInMonth + day; // zero-based day of month 3091 day = daysInMonth + day; // zero-based day of month
3095 if (day >= 0) 3092 if (day >= 0)
3096 days |= 1 << day; 3093 days |= 1 << day;
3097 } 3094 }
3098 } 3095 }
3099 // Compile the ordered list 3096 // Compile the ordered list
3100 Q_UINT32 mask = 1; 3097 Q_UINT32 mask = 1;
3101 for (int i = 0; i < daysInMonth; mask <<= 1, ++i) { 3098 for (int i = 0; i < daysInMonth; mask <<= 1, ++i) {
3102 if (days & mask) 3099 if (days & mask)
3103 list.append(i + 1); 3100 list.append(i + 1);
3104 } 3101 }
3105 return variable; 3102 return variable;
3106} 3103}
3107 3104
3108// Get the months which recur, in numerical order, for both leap years and non-leap years. 3105// Get the months which recur, in numerical order, for both leap years and non-leap years.
3109// N.B. If February 29th recurs on March 1st in non-leap years, February (not March) is 3106// N.B. If February 29th recurs on March 1st in non-leap years, February (not March) is
3110// included in the non-leap year month list. 3107// included in the non-leap year month list.
3111// Reply = true if February 29th also recurs. 3108// Reply = true if February 29th also recurs.
3112bool Recurrence::getYearlyMonthMonths(int day, QValueList<int> &list, QValueList<int> &leaplist) const 3109bool Recurrence::getYearlyMonthMonths(int day, QValueList<int> &list, QValueList<int> &leaplist) const
3113{ 3110{
3114 list.clear(); 3111 list.clear();
3115 leaplist.clear(); 3112 leaplist.clear();
3116 bool feb29 = false; 3113 bool feb29 = false;
3117 for (QPtrListIterator<int> it(rYearNums); it.current(); ++it) { 3114 for (QPtrListIterator<int> it(rYearNums); it.current(); ++it) {
3118 int month = *it.current(); 3115 int month = *it.current();
3119 if (month == 2) { 3116 if (month == 2) {
3120 if (day <= 28) { 3117 if (day <= 28) {
3121 list.append(month); // date appears in February 3118 list.append(month); // date appears in February
3122 leaplist.append(month); 3119 leaplist.append(month);
3123 } 3120 }
3124 else if (day == 29) { 3121 else if (day == 29) {
3125 // February 29th 3122 // February 29th
3126 leaplist.append(month); 3123 leaplist.append(month);
3127 switch (mFeb29YearlyType) { 3124 switch (mFeb29YearlyType) {
3128 case rFeb28: 3125 case rFeb28:
3129 case rMar1: 3126 case rMar1:
3130 list.append(2); 3127 list.append(2);
3131 break; 3128 break;
3132 case rFeb29: 3129 case rFeb29:
3133 break; 3130 break;
3134 } 3131 }
3135 feb29 = true; 3132 feb29 = true;
3136 } 3133 }
3137 } 3134 }
3138 else if (day <= 30 || QDate(2000, month, 1).daysInMonth() == 31) { 3135 else if (day <= 30 || QDate(2000, month, 1).daysInMonth() == 31) {
3139 list.append(month); // date appears in every month 3136 list.append(month); // date appears in every month
3140 leaplist.append(month); 3137 leaplist.append(month);
3141 } 3138 }
3142 } 3139 }
3143 return feb29; 3140 return feb29;
3144} 3141}
3145 3142
3146/* From the recurrence day of the week list, get the earliest day in the 3143/* From the recurrence day of the week list, get the earliest day in the
3147 * specified week which is >= the startDay. 3144 * specified week which is >= the startDay.
3148 * Parameters: startDay = 1..7 (Monday..Sunday) 3145 * Parameters: startDay = 1..7 (Monday..Sunday)
3149 * useWeekStart = true to end search at day before next rWeekStart 3146 * useWeekStart = true to end search at day before next rWeekStart
3150 * = false to search for a full 7 days 3147 * = false to search for a full 7 days
3151 * Reply = day of the week (1..7), or 0 if none found. 3148 * Reply = day of the week (1..7), or 0 if none found.
3152 */ 3149 */
3153int Recurrence::getFirstDayInWeek(int startDay, bool useWeekStart) const 3150int Recurrence::getFirstDayInWeek(int startDay, bool useWeekStart) const
3154{ 3151{
3155 int last = ((useWeekStart ? rWeekStart : startDay) + 5)%7; 3152 int last = ((useWeekStart ? rWeekStart : startDay) + 5)%7;
3156 for (int i = startDay - 1; ; i = (i + 1)%7) { 3153 for (int i = startDay - 1; ; i = (i + 1)%7) {
3157 if (rDays.testBit(i)) 3154 if (rDays.testBit(i))
3158 return i + 1; 3155 return i + 1;
3159 if (i == last) 3156 if (i == last)
3160 return 0; 3157 return 0;
3161 } 3158 }
3162} 3159}
3163 3160
3164/* From the recurrence day of the week list, get the latest day in the 3161/* From the recurrence day of the week list, get the latest day in the
3165 * specified week which is <= the endDay. 3162 * specified week which is <= the endDay.
3166 * Parameters: endDay = 1..7 (Monday..Sunday) 3163 * Parameters: endDay = 1..7 (Monday..Sunday)
3167 * useWeekStart = true to end search at rWeekStart 3164 * useWeekStart = true to end search at rWeekStart
3168 * = false to search for a full 7 days 3165 * = false to search for a full 7 days
3169 * Reply = day of the week (1..7), or 0 if none found. 3166 * Reply = day of the week (1..7), or 0 if none found.
3170 */ 3167 */
3171int Recurrence::getLastDayInWeek(int endDay, bool useWeekStart) const 3168int Recurrence::getLastDayInWeek(int endDay, bool useWeekStart) const
3172{ 3169{
3173 int last = useWeekStart ? rWeekStart - 1 : endDay%7; 3170 int last = useWeekStart ? rWeekStart - 1 : endDay%7;
3174 for (int i = endDay - 1; ; i = (i + 6)%7) { 3171 for (int i = endDay - 1; ; i = (i + 6)%7) {
3175 if (rDays.testBit(i)) 3172 if (rDays.testBit(i))
3176 return i + 1; 3173 return i + 1;
3177 if (i == last) 3174 if (i == last)
3178 return 0; 3175 return 0;
3179 } 3176 }
3180} 3177}
3181 3178
3182/* From the recurrence monthly day number list or monthly day of week/week of 3179/* From the recurrence monthly day number list or monthly day of week/week of
3183 * month list, get the earliest day in the specified month which is >= the 3180 * month list, get the earliest day in the specified month which is >= the
3184 * earliestDate. 3181 * earliestDate.
3185 */ 3182 */
3186QDate Recurrence::getFirstDateInMonth(const QDate &earliestDate) const 3183QDate Recurrence::getFirstDateInMonth(const QDate &earliestDate) const
3187{ 3184{
3188 int earliestDay = earliestDate.day(); 3185 int earliestDay = earliestDate.day();
3189 int daysInMonth = earliestDate.daysInMonth(); 3186 int daysInMonth = earliestDate.daysInMonth();
3190 switch (recurs) { 3187 switch (recurs) {
3191 case rMonthlyDay: { 3188 case rMonthlyDay: {
3192 int minday = daysInMonth + 1; 3189 int minday = daysInMonth + 1;
3193 for (QPtrListIterator<int> it(rMonthDays); it.current(); ++it) { 3190 for (QPtrListIterator<int> it(rMonthDays); it.current(); ++it) {
3194 int day = *it.current(); 3191 int day = *it.current();
3195 if (day < 0) 3192 if (day < 0)
3196 day = daysInMonth + day + 1; 3193 day = daysInMonth + day + 1;
3197 if (day >= earliestDay && day < minday) 3194 if (day >= earliestDay && day < minday)
3198 minday = day; 3195 minday = day;
3199 } 3196 }
3200 if (minday <= daysInMonth) 3197 if (minday <= daysInMonth)
3201 return earliestDate.addDays(minday - earliestDay); 3198 return earliestDate.addDays(minday - earliestDay);
3202 break; 3199 break;
3203 } 3200 }
3204 case rMonthlyPos: 3201 case rMonthlyPos:
3205 case rYearlyPos: { 3202 case rYearlyPos: {
3206 QDate monthBegin(earliestDate.addDays(1 - earliestDay)); 3203 QDate monthBegin(earliestDate.addDays(1 - earliestDay));
3207 QValueList<int> dayList; 3204 QValueList<int> dayList;
3208 getMonthlyPosDays(dayList, daysInMonth, monthBegin.dayOfWeek()); 3205 getMonthlyPosDays(dayList, daysInMonth, monthBegin.dayOfWeek());
3209 for (QValueList<int>::ConstIterator id = dayList.begin(); id != dayList.end(); ++id) { 3206 for (QValueList<int>::ConstIterator id = dayList.begin(); id != dayList.end(); ++id) {
3210 if (*id >= earliestDay) 3207 if (*id >= earliestDay)
3211 return monthBegin.addDays(*id - 1); 3208 return monthBegin.addDays(*id - 1);
3212 } 3209 }
3213 break; 3210 break;
3214 } 3211 }
3215 } 3212 }
3216 return QDate(); 3213 return QDate();
3217} 3214}
3218 3215
3219/* From the recurrence monthly day number list or monthly day of week/week of 3216/* From the recurrence monthly day number list or monthly day of week/week of
3220 * month list, get the latest day in the specified month which is <= the 3217 * month list, get the latest day in the specified month which is <= the
3221 * latestDate. 3218 * latestDate.
3222 */ 3219 */
3223QDate Recurrence::getLastDateInMonth(const QDate &latestDate) const 3220QDate Recurrence::getLastDateInMonth(const QDate &latestDate) const
3224{ 3221{
3225 int latestDay = latestDate.day(); 3222 int latestDay = latestDate.day();
3226 int daysInMonth = latestDate.daysInMonth(); 3223 int daysInMonth = latestDate.daysInMonth();
3227 switch (recurs) { 3224 switch (recurs) {
3228 case rMonthlyDay: { 3225 case rMonthlyDay: {
3229 int maxday = -1; 3226 int maxday = -1;
3230 for (QPtrListIterator<int> it(rMonthDays); it.current(); ++it) { 3227 for (QPtrListIterator<int> it(rMonthDays); it.current(); ++it) {
3231 int day = *it.current(); 3228 int day = *it.current();
3232 if (day < 0) 3229 if (day < 0)
3233 day = daysInMonth + day + 1; 3230 day = daysInMonth + day + 1;
3234 if (day <= latestDay && day > maxday) 3231 if (day <= latestDay && day > maxday)
3235 maxday = day; 3232 maxday = day;
3236 } 3233 }
3237 if (maxday > 0) 3234 if (maxday > 0)
3238 return QDate(latestDate.year(), latestDate.month(), maxday); 3235 return QDate(latestDate.year(), latestDate.month(), maxday);
3239 break; 3236 break;
3240 } 3237 }
3241 case rMonthlyPos: 3238 case rMonthlyPos:
3242 case rYearlyPos: { 3239 case rYearlyPos: {
3243 QDate monthBegin(latestDate.addDays(1 - latestDay)); 3240 QDate monthBegin(latestDate.addDays(1 - latestDay));
3244 QValueList<int> dayList; 3241 QValueList<int> dayList;
3245 getMonthlyPosDays(dayList, daysInMonth, monthBegin.dayOfWeek()); 3242 getMonthlyPosDays(dayList, daysInMonth, monthBegin.dayOfWeek());
3246 for (QValueList<int>::ConstIterator id = dayList.fromLast(); id != dayList.end(); --id) { 3243 for (QValueList<int>::ConstIterator id = dayList.fromLast(); id != dayList.end(); --id) {
3247 if (*id <= latestDay) 3244 if (*id <= latestDay)
3248 return monthBegin.addDays(*id - 1); 3245 return monthBegin.addDays(*id - 1);
3249 } 3246 }
3250 break; 3247 break;
3251 } 3248 }
3252 } 3249 }
3253 return QDate(); 3250 return QDate();
3254} 3251}
3255 3252
3256/* From the recurrence yearly month list or yearly day list, get the earliest 3253/* From the recurrence yearly month list or yearly day list, get the earliest
3257 * month or day in the specified year which is >= the earliestDate. 3254 * month or day in the specified year which is >= the earliestDate.
3258 * Note that rYearNums is sorted in numerical order. 3255 * Note that rYearNums is sorted in numerical order.
3259 */ 3256 */
3260QDate Recurrence::getFirstDateInYear(const QDate &earliestDate) const 3257QDate Recurrence::getFirstDateInYear(const QDate &earliestDate) const
3261{ 3258{
3262 QPtrListIterator<int> it(rYearNums); 3259 QPtrListIterator<int> it(rYearNums);
3263 switch (recurs) { 3260 switch (recurs) {
3264 case rYearlyMonth: { 3261 case rYearlyMonth: {
3265 int day = recurStart().date().day(); 3262 int day = recurStart().date().day();
3266 int earliestYear = earliestDate.year(); 3263 int earliestYear = earliestDate.year();
3267 int earliestMonth = earliestDate.month(); 3264 int earliestMonth = earliestDate.month();
3268 int earliestDay = earliestDate.day(); 3265 int earliestDay = earliestDate.day();
3269 if (earliestDay > day) { 3266 if (earliestDay > day) {
3270 // The earliest date is later in the month than the recurrence date, 3267 // The earliest date is later in the month than the recurrence date,
3271 // so skip to the next month before starting to check 3268 // so skip to the next month before starting to check
3272 if (++earliestMonth > 12) 3269 if (++earliestMonth > 12)
3273 return QDate(); 3270 return QDate();
3274 } 3271 }
3275 for ( ; it.current(); ++it) { 3272 for ( ; it.current(); ++it) {
3276 int month = *it.current(); 3273 int month = *it.current();
3277 if (month >= earliestMonth) { 3274 if (month >= earliestMonth) {
3278 if (day <= 28 || QDate::isValid(earliestYear, month, day)) 3275 if (day <= 28 || QDate::isValid(earliestYear, month, day))
3279 return QDate(earliestYear, month, day); 3276 return QDate(earliestYear, month, day);
3280 if (day == 29 && month == 2) { 3277 if (day == 29 && month == 2) {
3281 // It's a recurrence on February 29th, in a non-leap year 3278 // It's a recurrence on February 29th, in a non-leap year
3282 switch (mFeb29YearlyType) { 3279 switch (mFeb29YearlyType) {
3283 case rMar1: 3280 case rMar1:
3284 return QDate(earliestYear, 3, 1); 3281 return QDate(earliestYear, 3, 1);
3285 case rFeb28: 3282 case rFeb28:
3286 if (earliestDay <= 28) 3283 if (earliestDay <= 28)
3287 return QDate(earliestYear, 2, 28); 3284 return QDate(earliestYear, 2, 28);
3288 break; 3285 break;
3289 case rFeb29: 3286 case rFeb29:
3290 break; 3287 break;
3291 } 3288 }
3292 } 3289 }
3293 } 3290 }
3294 } 3291 }
3295 break; 3292 break;
3296 } 3293 }
3297 case rYearlyPos: { 3294 case rYearlyPos: {
3298 QValueList<int> dayList; 3295 QValueList<int> dayList;
3299 int earliestYear = earliestDate.year(); 3296 int earliestYear = earliestDate.year();
3300 int earliestMonth = earliestDate.month(); 3297 int earliestMonth = earliestDate.month();
3301 int earliestDay = earliestDate.day(); 3298 int earliestDay = earliestDate.day();
3302 for ( ; it.current(); ++it) { 3299 for ( ; it.current(); ++it) {
3303 int month = *it.current(); 3300 int month = *it.current();
3304 if (month >= earliestMonth) { 3301 if (month >= earliestMonth) {
3305 QDate monthBegin(earliestYear, month, 1); 3302 QDate monthBegin(earliestYear, month, 1);
3306 getMonthlyPosDays(dayList, monthBegin.daysInMonth(), monthBegin.dayOfWeek()); 3303 getMonthlyPosDays(dayList, monthBegin.daysInMonth(), monthBegin.dayOfWeek());
3307 for (QValueList<int>::ConstIterator id = dayList.begin(); id != dayList.end(); ++id) { 3304 for (QValueList<int>::ConstIterator id = dayList.begin(); id != dayList.end(); ++id) {
3308 if (*id >= earliestDay) 3305 if (*id >= earliestDay)
3309 return monthBegin.addDays(*id - 1); 3306 return monthBegin.addDays(*id - 1);
3310 } 3307 }
3311 earliestDay = 1; 3308 earliestDay = 1;
3312 } 3309 }
3313 } 3310 }
3314 break; 3311 break;
3315 } 3312 }
3316 case rYearlyDay: { 3313 case rYearlyDay: {
3317 int earliestDay = earliestDate.dayOfYear(); 3314 int earliestDay = earliestDate.dayOfYear();
3318 for ( ; it.current(); ++it) { 3315 for ( ; it.current(); ++it) {
3319 int day = *it.current(); 3316 int day = *it.current();
3320 if (day >= earliestDay && (day <= 365 || day <= earliestDate.daysInYear())) 3317 if (day >= earliestDay && (day <= 365 || day <= earliestDate.daysInYear()))
3321 return earliestDate.addDays(day - earliestDay); 3318 return earliestDate.addDays(day - earliestDay);
3322 } 3319 }
3323 break; 3320 break;
3324 } 3321 }
3325 } 3322 }
3326 return QDate(); 3323 return QDate();
3327} 3324}
3328 3325
3329/* From the recurrence yearly month list or yearly day list, get the latest 3326/* From the recurrence yearly month list or yearly day list, get the latest
3330 * month or day in the specified year which is <= the latestDate. 3327 * month or day in the specified year which is <= the latestDate.
3331 * Note that rYearNums is sorted in numerical order. 3328 * Note that rYearNums is sorted in numerical order.
3332 */ 3329 */
3333QDate Recurrence::getLastDateInYear(const QDate &latestDate) const 3330QDate Recurrence::getLastDateInYear(const QDate &latestDate) const
3334{ 3331{
3335 QPtrListIterator<int> it(rYearNums); 3332 QPtrListIterator<int> it(rYearNums);
3336 switch (recurs) { 3333 switch (recurs) {
3337 case rYearlyMonth: { 3334 case rYearlyMonth: {
3338 int day = recurStart().date().day(); 3335 int day = recurStart().date().day();
3339 int latestYear = latestDate.year(); 3336 int latestYear = latestDate.year();
3340 int latestMonth = latestDate.month(); 3337 int latestMonth = latestDate.month();
3341 if (latestDate.day() > day) { 3338 if (latestDate.day() > day) {
3342 // The latest date is earlier in the month than the recurrence date, 3339 // The latest date is earlier in the month than the recurrence date,
3343 // so skip to the previous month before starting to check 3340 // so skip to the previous month before starting to check
3344 if (--latestMonth <= 0) 3341 if (--latestMonth <= 0)
3345 return QDate(); 3342 return QDate();
3346 } 3343 }
3347 for (it.toLast(); it.current(); --it) { 3344 for (it.toLast(); it.current(); --it) {
3348 int month = *it.current(); 3345 int month = *it.current();
3349 if (month <= latestMonth) { 3346 if (month <= latestMonth) {
3350 if (day <= 28 || QDate::isValid(latestYear, month, day)) 3347 if (day <= 28 || QDate::isValid(latestYear, month, day))
3351 return QDate(latestYear, month, day); 3348 return QDate(latestYear, month, day);
3352 if (day == 29 && month == 2) { 3349 if (day == 29 && month == 2) {
3353 // It's a recurrence on February 29th, in a non-leap year 3350 // It's a recurrence on February 29th, in a non-leap year
3354 switch (mFeb29YearlyType) { 3351 switch (mFeb29YearlyType) {
3355 case rMar1: 3352 case rMar1:
3356 if (latestMonth >= 3) 3353 if (latestMonth >= 3)
3357 return QDate(latestYear, 3, 1); 3354 return QDate(latestYear, 3, 1);
3358 break; 3355 break;
3359 case rFeb28: 3356 case rFeb28:
3360 return QDate(latestYear, 2, 28); 3357 return QDate(latestYear, 2, 28);
3361 case rFeb29: 3358 case rFeb29:
3362 break; 3359 break;
3363 } 3360 }
3364 } 3361 }
3365 } 3362 }
3366 } 3363 }
3367 break; 3364 break;
3368 } 3365 }
3369 case rYearlyPos: { 3366 case rYearlyPos: {
3370 QValueList<int> dayList; 3367 QValueList<int> dayList;
3371 int latestYear = latestDate.year(); 3368 int latestYear = latestDate.year();
3372 int latestMonth = latestDate.month(); 3369 int latestMonth = latestDate.month();
3373 int latestDay = latestDate.day(); 3370 int latestDay = latestDate.day();
3374 for (it.toLast(); it.current(); --it) { 3371 for (it.toLast(); it.current(); --it) {
3375 int month = *it.current(); 3372 int month = *it.current();
3376 if (month <= latestMonth) { 3373 if (month <= latestMonth) {
3377 QDate monthBegin(latestYear, month, 1); 3374 QDate monthBegin(latestYear, month, 1);
3378 getMonthlyPosDays(dayList, monthBegin.daysInMonth(), monthBegin.dayOfWeek()); 3375 getMonthlyPosDays(dayList, monthBegin.daysInMonth(), monthBegin.dayOfWeek());
3379 for (QValueList<int>::ConstIterator id = dayList.fromLast(); id != dayList.end(); --id) { 3376 for (QValueList<int>::ConstIterator id = dayList.fromLast(); id != dayList.end(); --id) {
3380 if (*id <= latestDay) 3377 if (*id <= latestDay)
3381 return monthBegin.addDays(*id - 1); 3378 return monthBegin.addDays(*id - 1);
3382 } 3379 }
3383 latestDay = 31; 3380 latestDay = 31;
3384 } 3381 }
3385 } 3382 }
3386 break; 3383 break;
3387 } 3384 }
3388 case rYearlyDay: { 3385 case rYearlyDay: {
3389 int latestDay = latestDate.dayOfYear(); 3386 int latestDay = latestDate.dayOfYear();
3390 for (it.toLast(); it.current(); --it) { 3387 for (it.toLast(); it.current(); --it) {
3391 int day = *it.current(); 3388 int day = *it.current();
3392 if (day <= latestDay) 3389 if (day <= latestDay)
3393 return latestDate.addDays(day - latestDay); 3390 return latestDate.addDays(day - latestDay);
3394 } 3391 }
3395 break; 3392 break;
3396 } 3393 }
3397 } 3394 }
3398 return QDate(); 3395 return QDate();
3399} 3396}
3400 3397
3401void Recurrence::dump() const 3398void Recurrence::dump() const
3402{ 3399{
3403 kdDebug() << "Recurrence::dump():" << endl; 3400 ;
3404
3405 kdDebug() << " type: " << recurs << endl;
3406
3407 kdDebug() << " rDays: " << endl;
3408 int i;
3409 for( i = 0; i < 7; ++i ) {
3410 kdDebug() << " " << i << ": "
3411 << ( rDays.testBit( i ) ? "true" : "false" ) << endl;
3412 }
3413} 3401}