00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00034 #define FOREACH_VIEW(av) \
00035 for(QValueList<KOAgendaView*>::ConstIterator it = mAgendaViews.constBegin(); \
00036 it != mAgendaViews.constEnd();) \
00037 for(KOAgendaView* av = (it != mAgendaViews.constEnd() ? (*it) : 0); \
00038 it != mAgendaViews.constEnd(); ++it, av = (*it) )
00039
00040 using namespace KOrg;
00041
00042 MultiAgendaView::MultiAgendaView(Calendar * cal, QWidget * parent, const char *name ) :
00043 AgendaView( cal, parent, name ),
00044 mLastMovedSplitter( 0 ),
00045 mUpdateOnShow( false ),
00046 mPendingChanges( true )
00047 {
00048 QBoxLayout *topLevelLayout = new QHBoxLayout( this );
00049
00050 QFontMetrics fm( font() );
00051 int topLabelHeight = 2 * fm.height() + fm.lineSpacing();
00052
00053 QVBox *topSideBox = new QVBox( this );
00054 QWidget *topSideSpacer = new QWidget( topSideBox );
00055 topSideSpacer->setFixedHeight( topLabelHeight );
00056 mLeftSplitter = new QSplitter( Qt::Vertical, topSideBox );
00057 mLeftSplitter->setOpaqueResize( KGlobalSettings::opaqueResize() );
00058 QLabel *label = new QLabel( i18n("All Day"), mLeftSplitter );
00059 label->setAlignment( Qt::AlignRight | Qt::AlignVCenter | Qt::WordBreak );
00060 QVBox *sideBox = new QVBox( mLeftSplitter );
00061 EventIndicator *eiSpacer = new EventIndicator( EventIndicator::Top, sideBox );
00062 eiSpacer->changeColumns( 0 );
00063 mTimeLabels = new TimeLabels( 24, sideBox );
00064 eiSpacer = new EventIndicator( EventIndicator::Bottom, sideBox );
00065 eiSpacer->changeColumns( 0 );
00066 mLeftBottomSpacer = new QWidget( topSideBox );
00067 topLevelLayout->addWidget( topSideBox );
00068
00069 mScrollView = new QScrollView( this );
00070 mScrollView->setResizePolicy( QScrollView::Manual );
00071 mScrollView->setVScrollBarMode( QScrollView::AlwaysOff );
00072 mScrollView->setFrameShape( QFrame::NoFrame );
00073 topLevelLayout->addWidget( mScrollView, 100 );
00074 mTopBox = new QHBox( mScrollView->viewport() );
00075 mScrollView->addChild( mTopBox );
00076
00077 topSideBox = new QVBox( this );
00078 topSideSpacer = new QWidget( topSideBox );
00079 topSideSpacer->setFixedHeight( topLabelHeight );
00080 mRightSplitter = new QSplitter( Qt::Vertical, topSideBox );
00081 mRightSplitter->setOpaqueResize( KGlobalSettings::opaqueResize() );
00082 new QWidget( mRightSplitter );
00083 sideBox = new QVBox( mRightSplitter );
00084 eiSpacer = new EventIndicator( EventIndicator::Top, sideBox );
00085 eiSpacer->setFixedHeight( eiSpacer->minimumHeight() );
00086 eiSpacer->changeColumns( 0 );
00087 mScrollBar = new QScrollBar( Qt::Vertical, sideBox );
00088 eiSpacer = new EventIndicator( EventIndicator::Bottom, sideBox );
00089 eiSpacer->setFixedHeight( eiSpacer->minimumHeight() );
00090 eiSpacer->changeColumns( 0 );
00091 mRightBottomSpacer = new QWidget( topSideBox );
00092 topLevelLayout->addWidget( topSideBox );
00093
00094 recreateViews();
00095 }
00096
00097 void MultiAgendaView::recreateViews()
00098 {
00099 if ( !mPendingChanges )
00100 return;
00101 mPendingChanges = false;
00102
00103 deleteViews();
00104
00105 CalendarResources *calres = dynamic_cast<CalendarResources*>( calendar() );
00106 if ( !calres ) {
00107
00108 KOAgendaView* av = new KOAgendaView( calendar(), mTopBox );
00109 mAgendaViews.append( av );
00110 mAgendaWidgets.append( av );
00111 av->show();
00112 } else {
00113 CalendarResourceManager *manager = calres->resourceManager();
00114 for ( CalendarResourceManager::ActiveIterator it = manager->activeBegin(); it != manager->activeEnd(); ++it ) {
00115 if ( (*it)->canHaveSubresources() ) {
00116 QStringList subResources = (*it)->subresources();
00117 for ( QStringList::ConstIterator subit = subResources.constBegin(); subit != subResources.constEnd(); ++subit ) {
00118 QString type = (*it)->subresourceType( *subit );
00119 if ( !(*it)->subresourceActive( *subit ) || (!type.isEmpty() && type != "event") )
00120 continue;
00121 addView( (*it)->labelForSubresource( *subit ), *it, *subit );
00122 }
00123 } else {
00124 addView( (*it)->resourceName(), *it );
00125 }
00126 }
00127 }
00128
00129
00130 if ( mAgendaViews.isEmpty() )
00131 return;
00132
00133 setupViews();
00134 QTimer::singleShot( 0, this, SLOT(slotResizeScrollView()) );
00135 mTimeLabels->updateConfig();
00136
00137 QScrollBar *scrollBar = mAgendaViews.first()->agenda()->verticalScrollBar();
00138 mScrollBar->setMinValue( scrollBar->minValue() );
00139 mScrollBar->setMaxValue( scrollBar->maxValue() );
00140 mScrollBar->setLineStep( scrollBar->lineStep() );
00141 mScrollBar->setPageStep( scrollBar->pageStep() );
00142 mScrollBar->setValue( scrollBar->value() );
00143 connect( mTimeLabels->verticalScrollBar(), SIGNAL(valueChanged(int)),
00144 mScrollBar, SLOT(setValue(int)) );
00145 connect( mScrollBar, SIGNAL(valueChanged(int)),
00146 mTimeLabels, SLOT(positionChanged(int)) );
00147
00148 installSplitterEventFilter( mLeftSplitter );
00149 installSplitterEventFilter( mRightSplitter );
00150
00151 QValueList<int> sizes = KOGlobals::self()->config()->readIntListEntry("Separator AgendaView");
00152 if (sizes.count() != 2) {
00153 sizes = mLeftSplitter->sizes();
00154 }
00155 FOREACH_VIEW( agenda ) {
00156 agenda->splitter()->setSizes( sizes );
00157 }
00158 mLeftSplitter->setSizes( sizes );
00159 mRightSplitter->setSizes( sizes );
00160
00161 mTimeLabels->positionChanged();
00162 }
00163
00164 void MultiAgendaView::deleteViews()
00165 {
00166 for ( QValueList<QWidget*>::ConstIterator it = mAgendaWidgets.constBegin();
00167 it != mAgendaWidgets.constEnd(); ++it ) {
00168 delete *it;
00169 }
00170 mAgendaViews.clear();
00171 mAgendaWidgets.clear();
00172 mLastMovedSplitter = 0;
00173 }
00174
00175 void MultiAgendaView::setupViews()
00176 {
00177 FOREACH_VIEW( agenda ) {
00178 connect( agenda, SIGNAL( newEventSignal() ),
00179 SIGNAL( newEventSignal() ) );
00180 connect( agenda, SIGNAL( editIncidenceSignal( Incidence * ) ),
00181 SIGNAL( editIncidenceSignal( Incidence * ) ) );
00182 connect( agenda, SIGNAL( showIncidenceSignal( Incidence * ) ),
00183 SIGNAL( showIncidenceSignal( Incidence * ) ) );
00184 connect( agenda, SIGNAL( deleteIncidenceSignal( Incidence * ) ),
00185 SIGNAL( deleteIncidenceSignal( Incidence * ) ) );
00186 connect( agenda, SIGNAL( startMultiModify( const QString & ) ),
00187 SIGNAL( startMultiModify( const QString & ) ) );
00188 connect( agenda, SIGNAL( endMultiModify() ),
00189 SIGNAL( endMultiModify() ) );
00190
00191 connect( agenda, SIGNAL( incidenceSelected( Incidence *,const QDate & ) ),
00192 SIGNAL( incidenceSelected( Incidence *,const QDate & ) ) );
00193
00194 connect( agenda, SIGNAL(cutIncidenceSignal(Incidence*)),
00195 SIGNAL(cutIncidenceSignal(Incidence*)) );
00196 connect( agenda, SIGNAL(copyIncidenceSignal(Incidence*)),
00197 SIGNAL(copyIncidenceSignal(Incidence*)) );
00198 connect( agenda, SIGNAL(pasteIncidenceSignal()),
00199 SIGNAL(pasteIncidenceSignal()) );
00200 connect( agenda, SIGNAL(toggleAlarmSignal(Incidence*)),
00201 SIGNAL(toggleAlarmSignal(Incidence*)) );
00202 connect( agenda, SIGNAL(dissociateOccurrenceSignal(Incidence*, const QDate&)),
00203 SIGNAL(dissociateOccurrenceSignal(Incidence*, const QDate&)) );
00204 connect( agenda, SIGNAL(dissociateFutureOccurrenceSignal(Incidence*, const QDate&)),
00205 SIGNAL(dissociateFutureOccurrenceSignal(Incidence*, const QDate&)) );
00206
00207 connect( agenda, SIGNAL(newEventSignal(const QDate&)),
00208 SIGNAL(newEventSignal(const QDate&)) );
00209 connect( agenda, SIGNAL(newEventSignal(const QDateTime&)),
00210 SIGNAL(newEventSignal(const QDateTime&)) );
00211 connect( agenda, SIGNAL(newEventSignal(const QDateTime&, const QDateTime&)),
00212 SIGNAL(newEventSignal(const QDateTime&, const QDateTime&)) );
00213 connect( agenda, SIGNAL(newTodoSignal(const QDate&)),
00214 SIGNAL(newTodoSignal(const QDate&)) );
00215
00216 connect( agenda, SIGNAL(incidenceSelected(Incidence*, const QDate &)),
00217 SLOT(slotSelectionChanged()) );
00218
00219 connect( agenda, SIGNAL(timeSpanSelectionChanged()),
00220 SLOT(slotClearTimeSpanSelection()) );
00221
00222 disconnect( agenda->agenda(), SIGNAL(zoomView(const int,const QPoint&,const Qt::Orientation)), agenda, 0 );
00223 connect( agenda->agenda(), SIGNAL(zoomView(const int,const QPoint&,const Qt::Orientation)),
00224 SLOT(zoomView(const int,const QPoint&,const Qt::Orientation)) );
00225 }
00226
00227 FOREACH_VIEW( agenda ) {
00228 agenda->readSettings();
00229 }
00230
00231 int minWidth = 0;
00232 for ( QValueList<QWidget*>::ConstIterator it = mAgendaWidgets.constBegin(); it != mAgendaWidgets.constEnd(); ++it )
00233 minWidth = QMAX( minWidth, (*it)->minimumSizeHint().width() );
00234 for ( QValueList<QWidget*>::ConstIterator it = mAgendaWidgets.constBegin(); it != mAgendaWidgets.constEnd(); ++it )
00235 (*it)->setMinimumWidth( minWidth );
00236 }
00237
00238 MultiAgendaView::~ MultiAgendaView()
00239 {
00240 }
00241
00242 Incidence::List MultiAgendaView::selectedIncidences()
00243 {
00244 Incidence::List list;
00245 FOREACH_VIEW(agendaView) {
00246 list += agendaView->selectedIncidences();
00247 }
00248 return list;
00249 }
00250
00251 DateList MultiAgendaView::selectedDates()
00252 {
00253 DateList list;
00254 FOREACH_VIEW(agendaView) {
00255 list += agendaView->selectedDates();
00256 }
00257 return list;
00258 }
00259
00260 int MultiAgendaView::currentDateCount()
00261 {
00262 FOREACH_VIEW( agendaView )
00263 return agendaView->currentDateCount();
00264 return 0;
00265 }
00266
00267 void MultiAgendaView::showDates(const QDate & start, const QDate & end)
00268 {
00269 mStartDate = start;
00270 mEndDate = end;
00271 recreateViews();
00272 FOREACH_VIEW( agendaView )
00273 agendaView->showDates( start, end );
00274 }
00275
00276 void MultiAgendaView::showIncidences(const Incidence::List & incidenceList, const QDate &date)
00277 {
00278 FOREACH_VIEW( agendaView )
00279 agendaView->showIncidences( incidenceList, date );
00280 }
00281
00282 void MultiAgendaView::updateView()
00283 {
00284 recreateViews();
00285 FOREACH_VIEW( agendaView )
00286 agendaView->updateView();
00287 }
00288
00289 void MultiAgendaView::changeIncidenceDisplay(Incidence * incidence, int mode)
00290 {
00291 FOREACH_VIEW( agendaView )
00292 agendaView->changeIncidenceDisplay( incidence, mode );
00293 }
00294
00295 int MultiAgendaView::maxDatesHint()
00296 {
00297 FOREACH_VIEW( agendaView )
00298 return agendaView->maxDatesHint();
00299 return 0;
00300 }
00301
00302 void MultiAgendaView::slotSelectionChanged()
00303 {
00304 FOREACH_VIEW( agenda ) {
00305 if ( agenda != sender() )
00306 agenda->clearSelection();
00307 }
00308 }
00309
00310 bool MultiAgendaView::eventDurationHint(QDateTime & startDt, QDateTime & endDt, bool & allDay)
00311 {
00312 FOREACH_VIEW( agenda ) {
00313 bool valid = agenda->eventDurationHint( startDt, endDt, allDay );
00314 if ( valid )
00315 return true;
00316 }
00317 return false;
00318 }
00319
00320 void MultiAgendaView::slotClearTimeSpanSelection()
00321 {
00322 FOREACH_VIEW( agenda ) {
00323 if ( agenda != sender() )
00324 agenda->clearTimeSpanSelection();
00325 }
00326 }
00327
00328 void MultiAgendaView::setTypeAheadReceiver(QObject * o)
00329 {
00330 FOREACH_VIEW( agenda )
00331 agenda->setTypeAheadReceiver( o );
00332 }
00333
00334 void MultiAgendaView::finishTypeAhead()
00335 {
00336 FOREACH_VIEW( agenda )
00337 agenda->finishTypeAhead();
00338 }
00339
00340 void MultiAgendaView::addView( const QString &label, KCal::ResourceCalendar * res, const QString & subRes )
00341 {
00342 QVBox *box = new QVBox( mTopBox );
00343 QLabel *l = new QLabel( label, box );
00344 l->setAlignment( AlignVCenter | AlignHCenter );
00345 KOAgendaView* av = new KOAgendaView( calendar(), box, 0, true );
00346 av->setResource( res, subRes );
00347 av->setIncidenceChanger( mChanger );
00348 av->agenda()->setVScrollBarMode( QScrollView::AlwaysOff );
00349 mAgendaViews.append( av );
00350 mAgendaWidgets.append( box );
00351 box->show();
00352 mTimeLabels->setAgenda( av->agenda() );
00353
00354 connect( av->agenda()->verticalScrollBar(), SIGNAL(valueChanged(int)),
00355 mTimeLabels, SLOT(positionChanged(int)) );
00356 connect( mTimeLabels->verticalScrollBar(), SIGNAL(valueChanged(int)),
00357 av, SLOT(setContentsPos(int)) );
00358
00359 installSplitterEventFilter( av->splitter() );
00360 }
00361
00362 void MultiAgendaView::resizeEvent(QResizeEvent * ev)
00363 {
00364 resizeScrollView( ev->size() );
00365 AgendaView::resizeEvent( ev );
00366 }
00367
00368 void MultiAgendaView::resizeScrollView(const QSize & size)
00369 {
00370 const int widgetWidth = size.width() - mTimeLabels->width() - mScrollBar->width();
00371 int width = QMAX( mTopBox->sizeHint().width(), widgetWidth );
00372 int height = size.height();
00373 if ( width > widgetWidth ) {
00374 const int sbHeight = mScrollView->horizontalScrollBar()->height();
00375 height -= sbHeight;
00376 mLeftBottomSpacer->setFixedHeight( sbHeight );
00377 mRightBottomSpacer->setFixedHeight( sbHeight );
00378 } else {
00379 mLeftBottomSpacer->setFixedHeight( 0 );
00380 mRightBottomSpacer->setFixedHeight( 0 );
00381 }
00382 mScrollView->resizeContents( width, height );
00383 mTopBox->resize( width, height );
00384 }
00385
00386 void MultiAgendaView::setIncidenceChanger(IncidenceChangerBase * changer)
00387 {
00388 AgendaView::setIncidenceChanger( changer );
00389 FOREACH_VIEW( agenda )
00390 agenda->setIncidenceChanger( changer );
00391 }
00392
00393 void MultiAgendaView::updateConfig()
00394 {
00395 AgendaView::updateConfig();
00396 mTimeLabels->updateConfig();
00397 FOREACH_VIEW( agenda )
00398 agenda->updateConfig();
00399 }
00400
00401
00402 bool MultiAgendaView::eventFilter(QObject * obj, QEvent * event)
00403 {
00404 if ( obj->className() == QCString("QSplitterHandle") ) {
00405 if ( (event->type() == QEvent::MouseMove && KGlobalSettings::opaqueResize())
00406 || event->type() == QEvent::MouseButtonRelease ) {
00407 FOREACH_VIEW( agenda ) {
00408 if ( agenda->splitter() == obj->parent() )
00409 mLastMovedSplitter = agenda->splitter();
00410 }
00411 if ( mLeftSplitter == obj->parent() )
00412 mLastMovedSplitter = mLeftSplitter;
00413 else if ( mRightSplitter == obj->parent() )
00414 mLastMovedSplitter = mRightSplitter;
00415 QTimer::singleShot( 0, this, SLOT(resizeSplitters()) );
00416 }
00417 }
00418 return AgendaView::eventFilter( obj, event );
00419 }
00420
00421 void MultiAgendaView::resizeSplitters()
00422 {
00423 if ( !mLastMovedSplitter )
00424 mLastMovedSplitter = mAgendaViews.first()->splitter();
00425 FOREACH_VIEW( agenda ) {
00426 if ( agenda->splitter() == mLastMovedSplitter )
00427 continue;
00428 agenda->splitter()->setSizes( mLastMovedSplitter->sizes() );
00429 }
00430 if ( mLastMovedSplitter != mLeftSplitter )
00431 mLeftSplitter->setSizes( mLastMovedSplitter->sizes() );
00432 if ( mLastMovedSplitter != mRightSplitter )
00433 mRightSplitter->setSizes( mLastMovedSplitter->sizes() );
00434 }
00435
00436 void MultiAgendaView::zoomView( const int delta, const QPoint & pos, const Qt::Orientation ori )
00437 {
00438 if ( ori == Qt::Vertical ) {
00439 if ( delta > 0 ) {
00440 if ( KOPrefs::instance()->mHourSize > 4 )
00441 KOPrefs::instance()->mHourSize--;
00442 } else {
00443 KOPrefs::instance()->mHourSize++;
00444 }
00445 }
00446
00447 FOREACH_VIEW( agenda )
00448 agenda->zoomView( delta, pos, ori );
00449
00450 mTimeLabels->updateConfig();
00451 mTimeLabels->positionChanged();
00452 mTimeLabels->repaint();
00453 }
00454
00455
00456 void MultiAgendaView::installSplitterEventFilter(QSplitter * splitter)
00457 {
00458 QObjectList *objlist = splitter->queryList( "QSplitterHandle" );
00459
00460
00461 if ( objlist->count() == 0 && !isVisible() )
00462 mUpdateOnShow = true;
00463 QObjectListIt it( *objlist );
00464 QObject *obj;
00465 while ( (obj = it.current()) != 0 ) {
00466 obj->removeEventFilter( this );
00467 obj->installEventFilter( this );
00468 ++it;
00469 }
00470 delete objlist;
00471 }
00472
00473 void MultiAgendaView::slotResizeScrollView()
00474 {
00475 resizeScrollView( size() );
00476 }
00477
00478 void MultiAgendaView::show()
00479 {
00480 AgendaView::show();
00481 if ( mUpdateOnShow ) {
00482 mUpdateOnShow = false;
00483 mPendingChanges = true;
00484 showDates( mStartDate, mEndDate );
00485 }
00486 }
00487
00488 void MultiAgendaView::resourcesChanged()
00489 {
00490 mPendingChanges = true;
00491 FOREACH_VIEW( agenda )
00492 agenda->resourcesChanged();
00493 }
00494
00495 #include "multiagendaview.moc"