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