datenavigatorcontainer.cpp
00001 /* 00002 This file is part of KOrganizer. 00003 00004 Copyright (c) 2001,2002,2003 Cornelius Schumacher <schumacher@kde.org> 00005 Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com> 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 2 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program; if not, write to the Free Software 00019 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00020 00021 As a special exception, permission is given to link this program 00022 with any edition of TQt, and distribute the resulting executable, 00023 without including the source code for TQt in the source distribution. 00024 */ 00025 00026 #include <kdebug.h> 00027 #include <tdelocale.h> 00028 00029 #include "koglobals.h" 00030 #include "navigatorbar.h" 00031 #include "kdatenavigator.h" 00032 #include "kodaymatrix.h" 00033 00034 #include <kcalendarsystem.h> 00035 #include <kdialog.h> 00036 00037 #include "datenavigatorcontainer.h" 00038 00039 #include <tqwhatsthis.h> 00040 #include <tqtimer.h> 00041 00042 DateNavigatorContainer::DateNavigatorContainer( TQWidget *parent, 00043 const char *name ) 00044 : TQFrame( parent, name ), mCalendar( 0 ), 00045 mHorizontalCount( 1 ), mVerticalCount( 1 ) 00046 { 00047 mExtraViews.setAutoDelete( true ); 00048 setFrameStyle( TQFrame::Sunken | TQFrame::StyledPanel ); 00049 00050 mNavigatorView = new KDateNavigator( this, name ); 00051 TQWhatsThis::add( mNavigatorView, 00052 i18n( "<qt><p>Select the dates you want to " 00053 "display in KOrganizer's main view here. Hold down the " 00054 "mouse button to select more than one day.</p>" 00055 "<p>Press the top buttons to browse to the next " 00056 "/ previous months or years.</p>" 00057 "<p>Each line shows a week. The number in the left " 00058 "column is the number of the week in the year. " 00059 "Press it to select the whole week.</p>" 00060 "</qt>" ) ); 00061 00062 connectNavigatorView( mNavigatorView ); 00063 } 00064 00065 DateNavigatorContainer::~DateNavigatorContainer() 00066 { 00067 } 00068 00069 void DateNavigatorContainer::connectNavigatorView( KDateNavigator *v ) 00070 { 00071 connect( v, TQT_SIGNAL( datesSelected( const KCal::DateList & ) ), 00072 TQT_SIGNAL( datesSelected( const KCal::DateList & ) ) ); 00073 connect( v, TQT_SIGNAL( incidenceDropped( Incidence *, const TQDate & ) ), 00074 TQT_SIGNAL( incidenceDropped( Incidence *, const TQDate & ) ) ); 00075 connect( v, TQT_SIGNAL( incidenceDroppedMove( Incidence *, const TQDate & ) ), 00076 TQT_SIGNAL( incidenceDroppedMove( Incidence *, const TQDate & ) ) ); 00077 connect( v, TQT_SIGNAL( weekClicked( const TQDate & ) ), 00078 TQT_SIGNAL( weekClicked( const TQDate & ) ) ); 00079 00080 connect( v, TQT_SIGNAL( goPrevious() ), TQT_SIGNAL( goPrevious() ) ); 00081 connect( v, TQT_SIGNAL( goNext() ), TQT_SIGNAL( goNext() ) ); 00082 00083 connect( v, TQT_SIGNAL( nextYearClicked() ), TQT_SIGNAL( nextYearClicked() ) ); 00084 connect( v, TQT_SIGNAL( prevYearClicked() ), TQT_SIGNAL( prevYearClicked() ) ); 00085 00086 connect( v, TQT_SIGNAL( prevMonthClicked() ), this, TQT_SLOT( goPrevMonth() ) ); 00087 connect( v, TQT_SIGNAL( nextMonthClicked() ), this, TQT_SLOT( goNextMonth() ) ); 00088 00089 connect( v, TQT_SIGNAL( monthSelected( int ) ), TQT_SIGNAL( monthSelected( int ) ) ); 00090 connect( v, TQT_SIGNAL( yearSelected( int ) ), TQT_SIGNAL( yearSelected( int ) ) ); 00091 } 00092 00093 void DateNavigatorContainer::setCalendar( Calendar *cal ) 00094 { 00095 mCalendar = cal; 00096 mNavigatorView->setCalendar( cal ); 00097 KDateNavigator *n; 00098 for( n = mExtraViews.first(); n; n = mExtraViews.next() ) { 00099 n->setCalendar( cal ); 00100 } 00101 } 00102 00103 // TODO_Recurrence: let the navigators update just once, and tell them that 00104 // if data has changed or just the selection (because then the list of dayss 00105 // with events doesn't have to be updated if the month stayed the same 00106 void DateNavigatorContainer::updateDayMatrix() 00107 { 00108 mNavigatorView->updateDayMatrix(); 00109 KDateNavigator *n; 00110 for( n = mExtraViews.first(); n; n = mExtraViews.next() ) { 00111 n->updateDayMatrix(); 00112 } 00113 } 00114 00115 void DateNavigatorContainer::updateToday() 00116 { 00117 mNavigatorView->updateToday(); 00118 KDateNavigator *n; 00119 for( n = mExtraViews.first(); n; n = mExtraViews.next() ) { 00120 n->updateToday(); 00121 } 00122 } 00123 00124 void DateNavigatorContainer::setUpdateNeeded() 00125 { 00126 mNavigatorView->setUpdateNeeded(); 00127 KDateNavigator *n; 00128 for ( n = mExtraViews.first(); n; n = mExtraViews.next() ) { 00129 n->setUpdateNeeded(); 00130 } 00131 } 00132 00133 void DateNavigatorContainer::updateView() 00134 { 00135 mNavigatorView->updateView(); 00136 KDateNavigator *n; 00137 for ( n = mExtraViews.first(); n; n = mExtraViews.next() ) { 00138 n->setUpdateNeeded(); 00139 } 00140 } 00141 00142 void DateNavigatorContainer::updateConfig() 00143 { 00144 mNavigatorView->updateConfig(); 00145 KDateNavigator *n; 00146 for( n = mExtraViews.first(); n; n = mExtraViews.next() ) { 00147 n->updateConfig(); 00148 } 00149 } 00150 00151 void DateNavigatorContainer::selectDates( const DateList &dateList, const TQDate &preferredMonth ) 00152 { 00153 if ( !dateList.isEmpty() ) { 00154 TQDate start( dateList.first() ); 00155 TQDate end( dateList.last() ); 00156 TQDate navfirst( mNavigatorView->startDate() ); 00157 TQDate navsecond; // start of the second shown month if existant 00158 TQDate navlast; 00159 if ( !mExtraViews.isEmpty() ) { 00160 navlast = mExtraViews.last()->endDate(); 00161 navsecond = mExtraViews.first()->startDate(); 00162 } else { 00163 navlast = mNavigatorView->endDate(); 00164 navsecond = navfirst; 00165 } 00166 00167 const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); 00168 00169 // If the datelist crosses months we won't know which month to show 00170 // so we read what's in preferredMonth 00171 const bool changingMonth = ( preferredMonth.isValid() && 00172 calSys->month( mNavigatorView->month() ) != calSys->month( preferredMonth ) ); 00173 00174 if ( start < navfirst // <- start should always be visible 00175 // end is not visible and we have a spare month at the beginning: 00176 || ( end > navlast && start >= navsecond ) 00177 || changingMonth ) { 00178 00179 if ( preferredMonth.isValid() ) { 00180 setBaseDates( preferredMonth ); 00181 } else { 00182 setBaseDates( start ); 00183 } 00184 } 00185 00186 mNavigatorView->selectDates( dateList ); 00187 KDateNavigator *n = mExtraViews.first(); 00188 while ( n ) { 00189 n->selectDates( dateList ); 00190 n = mExtraViews.next(); 00191 } 00192 } 00193 } 00194 00195 void DateNavigatorContainer::setBaseDates( const TQDate &start ) 00196 { 00197 TQDate baseDate = start; 00198 mNavigatorView->setBaseDate( baseDate ); 00199 for( KDateNavigator *n = mExtraViews.first(); n; n = mExtraViews.next() ) { 00200 baseDate = KOGlobals::self()->calendarSystem()->addMonths( baseDate, 1 ); 00201 n->setBaseDate( baseDate ); 00202 } 00203 } 00204 00205 void DateNavigatorContainer::resizeEvent( TQResizeEvent * ) 00206 { 00207 #if 0 00208 kdDebug(5850) << "DateNavigatorContainer::resizeEvent()" << endl; 00209 kdDebug(5850) << " CURRENT SIZE: " << size() << endl; 00210 kdDebug(5850) << " MINIMUM SIZEHINT: " << minimumSizeHint() << endl; 00211 kdDebug(5850) << " SIZEHINT: " << sizeHint() << endl; 00212 kdDebug(5850) << " MINIMUM SIZE: " << minimumSize() << endl; 00213 #endif 00214 TQTimer::singleShot( 0, this, TQT_SLOT( resizeAllContents() ) ); 00215 } 00216 00217 void DateNavigatorContainer::resizeAllContents() 00218 { 00219 TQSize minSize = mNavigatorView->minimumSizeHint(); 00220 00221 // kdDebug(5850) << " NAVIGATORVIEW minimumSizeHint: " << minSize << endl; 00222 00223 int margin = KDialog::spacingHint(); 00224 int verticalCount = ( size().height() - margin*2 ) / minSize.height(); 00225 int horizontalCount = ( size().width() - margin*2 ) / minSize.width(); 00226 00227 if ( horizontalCount != mHorizontalCount || 00228 verticalCount != mVerticalCount ) { 00229 uint count = horizontalCount * verticalCount; 00230 if ( count == 0 ) { 00231 return; 00232 } 00233 00234 while ( count > ( mExtraViews.count() + 1 ) ) { 00235 KDateNavigator *n = new KDateNavigator( this ); 00236 mExtraViews.append( n ); 00237 n->setCalendar( mCalendar ); 00238 connectNavigatorView( n ); 00239 } 00240 00241 while ( count < ( mExtraViews.count() + 1 ) ) { 00242 mExtraViews.removeLast(); 00243 } 00244 00245 mHorizontalCount = horizontalCount; 00246 mVerticalCount = verticalCount; 00247 setBaseDates( mNavigatorView->selectedDates().first() ); 00248 selectDates( mNavigatorView->selectedDates() ); 00249 for( KDateNavigator *n = mExtraViews.first(); n; n = mExtraViews.next() ) { 00250 n->show(); 00251 } 00252 } 00253 00254 int height = (size().height() - margin*2) / verticalCount; 00255 int width = (size().width() - margin*2) / horizontalCount; 00256 00257 NavigatorBar *bar = mNavigatorView->navigatorBar(); 00258 if ( horizontalCount > 1 ) { 00259 bar->showButtons( true, false ); 00260 } else { 00261 bar->showButtons( true, true ); 00262 } 00263 00264 mNavigatorView->setGeometry( 00265 ( ( (KOGlobals::self()->reverseLayout())?(horizontalCount-1):0) * width ) + margin, 00266 margin, width, height ); 00267 00268 for( uint i = 0; i < mExtraViews.count(); ++i ) { 00269 int x = ( i + 1 ) % horizontalCount; 00270 int y = ( i + 1 ) / horizontalCount; 00271 00272 KDateNavigator *view = mExtraViews.at( i ); 00273 bar = view->navigatorBar(); 00274 if ( y > 0 ) { 00275 bar->showButtons( false, false ); 00276 } else { 00277 if ( x + 1 == horizontalCount ) { 00278 bar->showButtons( false, true ); 00279 } else { 00280 bar->showButtons( false, false ); 00281 } 00282 } 00283 view->setGeometry( 00284 ( ( (KOGlobals::self()->reverseLayout())?(horizontalCount-1-x):x) * width ) + margin, 00285 ( y * height ) + margin, width, height ); 00286 } 00287 } 00288 00289 TQSize DateNavigatorContainer::minimumSizeHint() const 00290 { 00291 int margin = KDialog::spacingHint() * 2; 00292 return mNavigatorView->minimumSizeHint() + TQSize( margin, margin ); 00293 } 00294 00295 TQSize DateNavigatorContainer::sizeHint() const 00296 { 00297 int margin = KDialog::spacingHint() * 2; 00298 return mNavigatorView->sizeHint() + TQSize( margin, margin ); 00299 } 00300 00301 void DateNavigatorContainer::goNextMonth() 00302 { 00303 const TQPair<TQDate,TQDate> p = dateLimits( 1 ); 00304 00305 emit nextMonthClicked( mNavigatorView->month(), 00306 p.first, 00307 p.second); 00308 } 00309 00310 void DateNavigatorContainer::goPrevMonth() 00311 { 00312 const TQPair<TQDate,TQDate> p = dateLimits( -1 ); 00313 00314 emit prevMonthClicked( mNavigatorView->month(), 00315 p.first, 00316 p.second ); 00317 } 00318 00319 TQPair<TQDate,TQDate> DateNavigatorContainer::dateLimits( int offset ) 00320 { 00321 const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem(); 00322 TQDate firstMonth, lastMonth; 00323 if ( mExtraViews.isEmpty() ) { 00324 lastMonth = mNavigatorView->month(); 00325 } else { 00326 lastMonth = mExtraViews.last()->month(); 00327 } 00328 00329 firstMonth = calSys->addMonths( mNavigatorView->month(), offset ); 00330 lastMonth = calSys->addMonths( lastMonth, offset ); 00331 00332 TQPair<TQDate,TQDate> firstMonthBoundary = KODayMatrix::matrixLimits( firstMonth ); 00333 TQPair<TQDate,TQDate> lastMonthBoundary = KODayMatrix::matrixLimits( lastMonth ); 00334 00335 return tqMakePair( firstMonthBoundary.first, lastMonthBoundary.second ); 00336 } 00337 00338 #include "datenavigatorcontainer.moc"