korganizer

multiagendaview.cpp

00001 /*
00002     Copyright (c) 2007 Volker Krause <vkrause@kde.org>
00003 
00004     This program is free software; you can redistribute it and/or modify
00005     it under the terms of the GNU General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or
00007     (at your option) any later version.
00008 
00009     This program is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00012     GNU General Public License for more details.
00013 
00014     You should have received a copy of the GNU General Public License
00015     along with this program; if not, write to the Free Software
00016     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017 */
00018 
00019 #include "multiagendaview.h"
00020 
00021 #include "koagendaview.h"
00022 #include "koagenda.h"
00023 #include "koprefs.h"
00024 #include "timelabels.h"
00025 
00026 #include <libkcal/calendarresources.h>
00027 
00028 #include <kglobalsettings.h>
00029 
00030 #include <qlayout.h>
00031 #include <qvbox.h>
00032 #include <qobjectlist.h>
00033 #include <qheader.h>
00034 
00035 #define FOREACH_VIEW(av) \
00036 for(QValueList<KOAgendaView*>::ConstIterator it = mAgendaViews.constBegin(); \
00037   it != mAgendaViews.constEnd();) \
00038   for(KOAgendaView* av = (it != mAgendaViews.constEnd() ? (*it) : 0); \
00039       it != mAgendaViews.constEnd(); ++it, av = (*it)  )
00040 
00041 using namespace KOrg;
00042 
00043 MultiAgendaView::MultiAgendaView(Calendar * cal, QWidget * parent, const char *name ) :
00044     AgendaView( cal, parent, name ),
00045     mSelectedAgendaView( 0 ),
00046     mLastMovedSplitter( 0 ),
00047     mUpdateOnShow( false ),
00048     mPendingChanges( true )
00049 {
00050   QBoxLayout *topLevelLayout = new QHBoxLayout( this );
00051 
00052   QFontMetrics fm( font() );
00053   int topLabelHeight = 2 * fm.height() + fm.lineSpacing();
00054 
00055   QVBox *topSideBox = new QVBox( this );
00056   mLeftTopSpacer = new QWidget( topSideBox );
00057   mLeftTopSpacer->setFixedHeight( topLabelHeight );
00058   mLeftSplitter = new QSplitter( Qt::Vertical, topSideBox );
00059   mLeftSplitter->setOpaqueResize( KGlobalSettings::opaqueResize() );
00060   QLabel *label = new QLabel( i18n("All Day"), mLeftSplitter );
00061   label->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::WordBreak );
00062   QVBox *sideBox = new QVBox( mLeftSplitter );
00063   EventIndicator *eiSpacer = new EventIndicator( EventIndicator::Top, sideBox );
00064   eiSpacer->changeColumns( 0 );
00065   mTimeLabels = new TimeLabels( 24, sideBox );
00066   eiSpacer = new EventIndicator( EventIndicator::Bottom, sideBox );
00067   eiSpacer->changeColumns( 0 );
00068   mLeftBottomSpacer = new QWidget( topSideBox );
00069   topLevelLayout->addWidget( topSideBox );
00070 
00071   mScrollView = new QScrollView( this );
00072   mScrollView->setResizePolicy( QScrollView::Manual );
00073   mScrollView->setVScrollBarMode( QScrollView::AlwaysOff );
00074   mScrollView->setFrameShape( QFrame::NoFrame );
00075   topLevelLayout->addWidget( mScrollView, 100 );
00076   mTopBox = new QHBox( mScrollView->viewport() );
00077   mScrollView->addChild( mTopBox );
00078 
00079   topSideBox = new QVBox( this );
00080   mRightTopSpacer = new QWidget( topSideBox );
00081   mRightTopSpacer->setFixedHeight( topLabelHeight );
00082   mRightSplitter = new QSplitter( Qt::Vertical, topSideBox );
00083   mRightSplitter->setOpaqueResize( KGlobalSettings::opaqueResize() );
00084   new QWidget( mRightSplitter );
00085   sideBox = new QVBox( mRightSplitter );
00086   eiSpacer = new EventIndicator( EventIndicator::Top, sideBox );
00087   eiSpacer->setFixedHeight( eiSpacer->minimumHeight() );
00088   eiSpacer->changeColumns( 0 );
00089   mScrollBar = new QScrollBar( Qt::Vertical, sideBox );
00090   eiSpacer = new EventIndicator( EventIndicator::Bottom, sideBox );
00091   eiSpacer->setFixedHeight( eiSpacer->minimumHeight() );
00092   eiSpacer->changeColumns( 0 );
00093   mRightBottomSpacer = new QWidget( topSideBox );
00094   topLevelLayout->addWidget( topSideBox );
00095 
00096   recreateViews();
00097 }
00098 
00099 void MultiAgendaView::recreateViews()
00100 {
00101   if ( !mPendingChanges )
00102     return;
00103   mPendingChanges = false;
00104 
00105   deleteViews();
00106 
00107   CalendarResources *calres = dynamic_cast<CalendarResources*>( calendar() );
00108   if ( !calres ) {
00109     // fallback to single-agenda
00110     KOAgendaView* av = new KOAgendaView( calendar(), mTopBox );
00111     mAgendaViews.append( av );
00112     mAgendaWidgets.append( av );
00113     mSelectedAgendaView = av;
00114     av->show();
00115   } else {
00116     CalendarResourceManager *manager = calres->resourceManager();
00117     for ( CalendarResourceManager::ActiveIterator it = manager->activeBegin(); it != manager->activeEnd(); ++it ) {
00118       if ( (*it)->canHaveSubresources() ) {
00119         QStringList subResources = (*it)->subresources();
00120         for ( QStringList::ConstIterator subit = subResources.constBegin(); subit != subResources.constEnd(); ++subit ) {
00121           QString type = (*it)->subresourceType( *subit );
00122           if ( !(*it)->subresourceActive( *subit ) || (!type.isEmpty() && type != "event") )
00123             continue;
00124           addView( (*it)->labelForSubresource( *subit ), *it, *subit );
00125         }
00126       } else {
00127         addView( (*it)->resourceName(), *it );
00128       }
00129     }
00130   }
00131 
00132   // no resources activated, so stop here to avoid crashing somewhere down the line, TODO: show a nice message instead
00133   if ( mAgendaViews.isEmpty() )
00134     return;
00135 
00136   setupViews();
00137   QTimer::singleShot( 0, this, SLOT(slotResizeScrollView()) );
00138   mTimeLabels->updateConfig();
00139 
00140   QScrollBar *scrollBar = mAgendaViews.first()->agenda()->verticalScrollBar();
00141   mScrollBar->setMinValue( scrollBar->minValue() );
00142   mScrollBar->setMaxValue( scrollBar->maxValue() );
00143   mScrollBar->setLineStep( scrollBar->lineStep() );
00144   mScrollBar->setPageStep( scrollBar->pageStep() );
00145   mScrollBar->setValue( scrollBar->value() );
00146   connect( mTimeLabels->verticalScrollBar(), SIGNAL(valueChanged(int)),
00147            mScrollBar, SLOT(setValue(int)) );
00148   connect( mScrollBar, SIGNAL(valueChanged(int)),
00149            mTimeLabels, SLOT(positionChanged(int)) );
00150 
00151   installSplitterEventFilter( mLeftSplitter );
00152   installSplitterEventFilter( mRightSplitter );
00153 
00154   QValueList<int> sizes = KOGlobals::self()->config()->readIntListEntry("Separator AgendaView");
00155   if (sizes.count() != 2) {
00156     sizes = mLeftSplitter->sizes();
00157   }
00158   FOREACH_VIEW( agenda ) {
00159     agenda->splitter()->setSizes( sizes );
00160   }
00161   mLeftSplitter->setSizes( sizes );
00162   mRightSplitter->setSizes( sizes );
00163 
00164   mTimeLabels->positionChanged();
00165 }
00166 
00167 void MultiAgendaView::deleteViews()
00168 {
00169   for ( QValueList<QWidget*>::ConstIterator it = mAgendaWidgets.constBegin();
00170         it != mAgendaWidgets.constEnd(); ++it ) {
00171     delete *it;
00172   }
00173   mAgendaViews.clear();
00174   mAgendaWidgets.clear();
00175   mLastMovedSplitter = 0;
00176 }
00177 
00178 void MultiAgendaView::setupViews()
00179 {
00180   FOREACH_VIEW( agenda ) {
00181     if ( !agenda->readOnly() ) {
00182       connect( agenda,
00183                SIGNAL(newEventSignal(ResourceCalendar *,const QString &)),
00184                SIGNAL(newEventSignal(ResourceCalendar *,const QString &)) );
00185       connect( agenda,
00186                SIGNAL(newEventSignal(ResourceCalendar *,const QString &,const QDate &)),
00187                SIGNAL(newEventSignal(ResourceCalendar *,const QString &,const QDate &)) );
00188       connect( agenda,
00189                SIGNAL(newEventSignal(ResourceCalendar *,const QString &,const QDateTime &)),
00190                SIGNAL(newEventSignal(ResourceCalendar *,const QString &,const QDateTime &)) );
00191       connect( agenda,
00192                SIGNAL(newEventSignal(ResourceCalendar *,const QString &,const QDateTime &,const QDateTime &)),
00193                SIGNAL(newEventSignal(ResourceCalendar *,const QString &,const QDateTime &,const QDateTime&)) );
00194 
00195       connect( agenda,
00196                SIGNAL(newTodoSignal(ResourceCalendar *,const QString &,const QDate &)),
00197                SIGNAL(newTodoSignal(ResourceCalendar *,const QString &,const QDate &)) );
00198 
00199       connect( agenda,
00200                SIGNAL(editIncidenceSignal(Incidence *)),
00201                SIGNAL(editIncidenceSignal(Incidence *)) );
00202       connect( agenda,
00203                SIGNAL(deleteIncidenceSignal(Incidence *)),
00204                SIGNAL(deleteIncidenceSignal(Incidence *)) );
00205       connect( agenda,
00206                SIGNAL(startMultiModify(const QString &)),
00207                SIGNAL(startMultiModify(const QString &)) );
00208       connect( agenda,
00209                SIGNAL(endMultiModify()),
00210                SIGNAL(endMultiModify()) );
00211 
00212       connect( agenda,
00213                SIGNAL(cutIncidenceSignal(Incidence*)),
00214                SIGNAL(cutIncidenceSignal(Incidence*)) );
00215       connect( agenda,
00216                SIGNAL(pasteIncidenceSignal()),
00217                SIGNAL(pasteIncidenceSignal()) );
00218       connect( agenda,
00219                SIGNAL(toggleAlarmSignal(Incidence*)),
00220                SIGNAL(toggleAlarmSignal(Incidence*)) );
00221       connect( agenda,
00222                SIGNAL(dissociateOccurrenceSignal(Incidence*, const QDate&)),
00223                SIGNAL(dissociateOccurrenceSignal(Incidence*, const QDate&)) );
00224       connect( agenda,
00225                SIGNAL(dissociateFutureOccurrenceSignal(Incidence*, const QDate&)),
00226                SIGNAL(dissociateFutureOccurrenceSignal(Incidence*, const QDate&)) );
00227     }
00228 
00229     connect( agenda,
00230              SIGNAL(copyIncidenceSignal(Incidence*)),
00231              SIGNAL(copyIncidenceSignal(Incidence*)) );
00232     connect( agenda,
00233              SIGNAL(showIncidenceSignal(Incidence *)),
00234              SIGNAL(showIncidenceSignal(Incidence *)) );
00235     connect( agenda,
00236              SIGNAL(incidenceSelected(Incidence *,const QDate &)),
00237              SIGNAL(incidenceSelected(Incidence *,const QDate &)) );
00238     connect( agenda,
00239              SIGNAL(incidenceSelected(Incidence*,const QDate &)),
00240              SLOT(slotSelectionChanged()) );
00241 
00242     connect( agenda,
00243              SIGNAL(timeSpanSelectionChanged()),
00244              SLOT(slotClearTimeSpanSelection()) );
00245 
00246     disconnect( agenda->agenda(),
00247                 SIGNAL(zoomView(const int,const QPoint&,const Qt::Orientation)),
00248                 agenda, 0 );
00249     connect( agenda->agenda(),
00250              SIGNAL(zoomView(const int,const QPoint&,const Qt::Orientation)),
00251              SLOT(zoomView(const int,const QPoint&,const Qt::Orientation)) );
00252   }
00253 
00254   KOAgenda *anAgenda = mAgendaViews.first()->agenda();
00255   connect( anAgenda, SIGNAL(lowerYChanged(int) ), SLOT(resizeSpacers(int)) );
00256 
00257   FOREACH_VIEW( agenda ) {
00258     agenda->readSettings();
00259   }
00260 
00261   int minWidth = 0;
00262   for ( QValueList<QWidget*>::ConstIterator it = mAgendaWidgets.constBegin(); it != mAgendaWidgets.constEnd(); ++it )
00263     minWidth = QMAX( minWidth, (*it)->minimumSizeHint().width() );
00264   for ( QValueList<QWidget*>::ConstIterator it = mAgendaWidgets.constBegin(); it != mAgendaWidgets.constEnd(); ++it )
00265     (*it)->setMinimumWidth( minWidth );
00266 }
00267 
00268 MultiAgendaView::~ MultiAgendaView()
00269 {
00270 }
00271 
00272 Incidence::List MultiAgendaView::selectedIncidences()
00273 {
00274   Incidence::List list;
00275   FOREACH_VIEW(agendaView) {
00276     list += agendaView->selectedIncidences();
00277   }
00278   return list;
00279 }
00280 
00281 DateList MultiAgendaView::selectedDates()
00282 {
00283   DateList list;
00284   FOREACH_VIEW(agendaView) {
00285     list += agendaView->selectedDates();
00286   }
00287   return list;
00288 }
00289 
00290 int MultiAgendaView::currentDateCount()
00291 {
00292   FOREACH_VIEW( agendaView )
00293     return agendaView->currentDateCount();
00294   return 0;
00295 }
00296 
00297 void MultiAgendaView::showDates(const QDate & start, const QDate & end)
00298 {
00299   mStartDate = start;
00300   mEndDate = end;
00301   recreateViews();
00302   FOREACH_VIEW( agendaView )
00303     agendaView->showDates( start, end );
00304 }
00305 
00306 void MultiAgendaView::showIncidences(const Incidence::List & incidenceList, const QDate &date)
00307 {
00308   FOREACH_VIEW( agendaView )
00309     agendaView->showIncidences( incidenceList, date );
00310 }
00311 
00312 void MultiAgendaView::updateView()
00313 {
00314   recreateViews();
00315   FOREACH_VIEW( agendaView )
00316     agendaView->updateView();
00317 }
00318 
00319 void MultiAgendaView::changeIncidenceDisplay(Incidence * incidence, int mode)
00320 {
00321   FOREACH_VIEW( agendaView )
00322     agendaView->changeIncidenceDisplay( incidence, mode );
00323 }
00324 
00325 int MultiAgendaView::maxDatesHint()
00326 {
00327   FOREACH_VIEW( agendaView )
00328     return agendaView->maxDatesHint();
00329   return 0;
00330 }
00331 
00332 void MultiAgendaView::slotSelectionChanged()
00333 {
00334   FOREACH_VIEW( agenda ) {
00335     if ( agenda != sender() )
00336       agenda->clearSelection();
00337   }
00338 }
00339 
00340 bool MultiAgendaView::eventDurationHint(QDateTime & startDt, QDateTime & endDt, bool & allDay)
00341 {
00342   FOREACH_VIEW( agenda ) {
00343     bool valid = agenda->eventDurationHint( startDt, endDt, allDay );
00344     if ( valid )
00345       return true;
00346   }
00347   return false;
00348 }
00349 
00350 void MultiAgendaView::slotClearTimeSpanSelection()
00351 {
00352   FOREACH_VIEW( agenda ) {
00353     if ( agenda != sender() )
00354       agenda->clearTimeSpanSelection();
00355   }
00356 }
00357 
00358 void MultiAgendaView::setTypeAheadReceiver(QObject * o)
00359 {
00360   FOREACH_VIEW( agenda )
00361     agenda->setTypeAheadReceiver( o );
00362 }
00363 
00364 void MultiAgendaView::finishTypeAhead()
00365 {
00366   FOREACH_VIEW( agenda )
00367     agenda->finishTypeAhead();
00368 }
00369 
00370 void MultiAgendaView::addView( const QString &label, KCal::ResourceCalendar * res, const QString & subRes )
00371 {
00372   bool readOnlyView = false;
00373 
00374   QVBox *box = new QVBox( mTopBox );
00375 
00376   // First, the calendar folder title
00377   QHeader *title = new QHeader( 1, box );
00378   title->setClickEnabled( false );
00379   title->setStretchEnabled( true );
00380   if ( res->readOnly() || !res->subresourceWritable( subRes ) ) {
00381     readOnlyView = true;
00382     title->setLabel( 0, QIconSet( KOGlobals::self()->smallIcon( "readonlyevent" ) ), label );
00383   } else {
00384     QColor resColor;
00385     if ( subRes.isEmpty() ) {
00386       resColor = *KOPrefs::instance()->resourceColor( res->identifier() );
00387     } else {
00388       resColor = *KOPrefs::instance()->resourceColor( subRes );
00389     }
00390     QFontMetrics fm = fontMetrics();
00391     QPixmap px( fm.height(), fm.height() );
00392     px.fill( resColor );
00393     title->setLabel( 0, QIconSet( px, QIconSet::Small ), label );
00394   }
00395 
00396   // Now, the sub agenda view
00397   KOAgendaView* av = new KOAgendaView( calendar(), box, 0, true );
00398   mSelectedAgendaView = av;
00399   av->setReadOnly( readOnlyView );
00400   av->setResource( res, subRes );
00401   av->setIncidenceChanger( mChanger );
00402   av->agenda()->setVScrollBarMode( QScrollView::AlwaysOff );
00403   mAgendaViews.append( av );
00404   mAgendaWidgets.append( box );
00405   box->show();
00406   mTimeLabels->setAgenda( av->agenda() );
00407 
00408   connect( av->agenda()->verticalScrollBar(), SIGNAL(valueChanged(int)),
00409            mTimeLabels, SLOT(positionChanged(int)) );
00410   connect( mTimeLabels->verticalScrollBar(), SIGNAL(valueChanged(int)),
00411            av, SLOT(setContentsPos(int)) );
00412 
00413   av->installEventFilter( this );
00414   installSplitterEventFilter( av->splitter() );
00415 }
00416 
00417 void MultiAgendaView::resizeEvent(QResizeEvent * ev)
00418 {
00419   resizeScrollView( ev->size() );
00420   AgendaView::resizeEvent( ev );
00421 }
00422 
00423 void MultiAgendaView::resizeScrollView(const QSize & size)
00424 {
00425   const int widgetWidth = size.width() - mTimeLabels->width() - mScrollBar->width();
00426   int width = QMAX( mTopBox->sizeHint().width(), widgetWidth );
00427   int height = size.height();
00428   if ( width > widgetWidth ) {
00429     const int sbHeight = mScrollView->horizontalScrollBar()->height();
00430     height -= sbHeight;
00431     mLeftBottomSpacer->setFixedHeight( sbHeight );
00432     mRightBottomSpacer->setFixedHeight( sbHeight );
00433   } else {
00434     mLeftBottomSpacer->setFixedHeight( 0 );
00435     mRightBottomSpacer->setFixedHeight( 0 );
00436   }
00437   mScrollView->resizeContents( width, height );
00438   mTopBox->resize( width, height );
00439 }
00440 
00441 void MultiAgendaView::setIncidenceChanger(IncidenceChangerBase * changer)
00442 {
00443   AgendaView::setIncidenceChanger( changer );
00444   FOREACH_VIEW( agenda )
00445     agenda->setIncidenceChanger( changer );
00446 }
00447 
00448 void MultiAgendaView::updateConfig()
00449 {
00450   AgendaView::updateConfig();
00451   mTimeLabels->updateConfig();
00452   FOREACH_VIEW( agenda )
00453     agenda->updateConfig();
00454 }
00455 
00456 bool MultiAgendaView::eventFilter(QObject * obj, QEvent * event)
00457 {
00458   if ( obj->className() == QCString("QSplitterHandle") ) {
00459     // KDE4: not needed anymore, QSplitter has a moved signal there
00460     if ( (event->type() == QEvent::MouseMove && KGlobalSettings::opaqueResize())
00461            || event->type() == QEvent::MouseButtonRelease ) {
00462       FOREACH_VIEW( agenda ) {
00463         if ( agenda->splitter() == obj->parent() )
00464           mLastMovedSplitter = agenda->splitter();
00465       }
00466       if ( mLeftSplitter == obj->parent() )
00467         mLastMovedSplitter = mLeftSplitter;
00468       else if ( mRightSplitter == obj->parent() )
00469         mLastMovedSplitter = mRightSplitter;
00470       QTimer::singleShot( 0, this, SLOT(resizeSplitters()) );
00471     }
00472   }
00473 
00474   if ( obj->className() == QCString( "KOAgendaView" ) ) {
00475     if ( event->type() == QEvent::Enter ) {
00476       mSelectedAgendaView = (KOAgendaView *)obj;
00477     }
00478   }
00479 
00480   return AgendaView::eventFilter( obj, event );
00481 }
00482 
00483 void MultiAgendaView::resizeSplitters()
00484 {
00485   if ( !mLastMovedSplitter )
00486     mLastMovedSplitter = mAgendaViews.first()->splitter();
00487   FOREACH_VIEW( agenda ) {
00488     if ( agenda->splitter() == mLastMovedSplitter )
00489       continue;
00490     agenda->splitter()->setSizes( mLastMovedSplitter->sizes() );
00491   }
00492   if ( mLastMovedSplitter != mLeftSplitter )
00493     mLeftSplitter->setSizes( mLastMovedSplitter->sizes() );
00494   if ( mLastMovedSplitter != mRightSplitter )
00495     mRightSplitter->setSizes( mLastMovedSplitter->sizes() );
00496 }
00497 
00498 void MultiAgendaView::resizeSpacers( int newY )
00499 {
00500   // this slot is needed because the Agenda view's day labels frame height
00501   // can change depending if holidays are shown. When this happens, all
00502   // the widgets move down except the timelabels, so we need to change
00503   // the top spacer height accordingly to move the timelabels up/down.
00504   // kolab/issue2656
00505   Q_UNUSED( newY );
00506   QFontMetrics fm( font() );
00507   int topLabelHeight = mAgendaViews.first()->dayLabels()->height() +
00508                        fm.height() + mLeftSplitter->handleWidth();
00509   mLeftTopSpacer->setFixedHeight( topLabelHeight );
00510   mRightTopSpacer->setFixedHeight( topLabelHeight );
00511 }
00512 
00513 void MultiAgendaView::zoomView( const int delta, const QPoint & pos, const Qt::Orientation ori )
00514 {
00515   if ( ori == Qt::Vertical ) {
00516     if ( delta > 0 ) {
00517       if ( KOPrefs::instance()->mHourSize > 4 )
00518         KOPrefs::instance()->mHourSize--;
00519     } else {
00520       KOPrefs::instance()->mHourSize++;
00521     }
00522   }
00523 
00524   FOREACH_VIEW( agenda )
00525     agenda->zoomView( delta, pos, ori );
00526 
00527   mTimeLabels->updateConfig();
00528   mTimeLabels->positionChanged();
00529   mTimeLabels->repaint();
00530 }
00531 
00532 // KDE4: not needed, use existing QSplitter signals instead
00533 void MultiAgendaView::installSplitterEventFilter(QSplitter * splitter)
00534 {
00535   QObjectList *objlist = splitter->queryList( "QSplitterHandle" );
00536   // HACK: when not being visible, the splitter handle is sometimes not found
00537   // for unknown reasons, so trigger an update when we are shown again
00538   if ( objlist->count() == 0 && !isVisible() )
00539     mUpdateOnShow = true;
00540   QObjectListIt it( *objlist );
00541   QObject *obj;
00542   while ( (obj = it.current()) != 0 ) {
00543     obj->removeEventFilter( this );
00544     obj->installEventFilter( this );
00545     ++it;
00546   }
00547   delete objlist;
00548 }
00549 
00550 void MultiAgendaView::slotResizeScrollView()
00551 {
00552   resizeScrollView( size() );
00553 }
00554 
00555 void MultiAgendaView::show()
00556 {
00557   AgendaView::show();
00558   if ( mUpdateOnShow ) {
00559     mUpdateOnShow = false;
00560     mPendingChanges = true; // force a full view recreation
00561     showDates( mStartDate, mEndDate );
00562   }
00563 }
00564 
00565 void MultiAgendaView::resourcesChanged()
00566 {
00567   mPendingChanges = true;
00568   FOREACH_VIEW( agenda )
00569     agenda->resourcesChanged();
00570 }
00571 
00572 #include "multiagendaview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys