korganizer

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"