kdganttgraphicsscene.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB.  All rights reserved.
00003 **
00004 ** This file is part of the KD Chart library.
00005 **
00006 ** Licensees holding valid commercial KD Chart licenses may use this file in
00007 ** accordance with the KD Chart Commercial License Agreement provided with
00008 ** the Software.
00009 **
00010 **
00011 ** This file may be distributed and/or modified under the terms of the
00012 ** GNU General Public License version 2 and version 3 as published by the
00013 ** Free Software Foundation and appearing in the file LICENSE.GPL included.
00014 **
00015 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00016 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017 **
00018 ** Contact info@kdab.com if any conditions of this licensing are not
00019 ** clear to you.
00020 **
00021 **********************************************************************/
00022 
00023 #include "kdganttgraphicsscene.h"
00024 #include "kdganttgraphicsscene_p.h"
00025 #include "kdganttgraphicsitem.h"
00026 #include "kdganttconstraint.h"
00027 #include "kdganttconstraintgraphicsitem.h"
00028 #include "kdganttitemdelegate.h"
00029 #include "kdganttabstractrowcontroller.h"
00030 #include "kdganttdatetimegrid.h"
00031 #include "kdganttsummaryhandlingproxymodel.h"
00032 
00033 #include <QApplication>
00034 #include <QGraphicsSceneHelpEvent>
00035 #include <QPainter>
00036 #include <QPrinter>
00037 #include <QTextDocument>
00038 #include <QToolTip>
00039 #include <QSet>
00040 
00041 #include <QDebug>
00042 
00043 #include <functional>
00044 #include <algorithm>
00045 #include <cassert>
00046 
00047 /* Older Qt dont have this macro, so define it... */
00048 #ifndef QT_VERSION_CHECK
00049 #  define QT_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch))
00050 #endif
00051 
00056 using namespace KDGantt;
00057 
00058 GraphicsScene::Private::Private( GraphicsScene* _q )
00059     : q( _q ),
00060       dragSource( 0 ),
00061       itemDelegate( new ItemDelegate( _q ) ),
00062       rowController( 0 ),
00063       grid( &default_grid ),
00064       readOnly( false ),
00065       isPrinting( false ),
00066       summaryHandlingModel( new SummaryHandlingProxyModel( _q ) ),
00067       selectionModel( 0 )
00068 {
00069     default_grid.setStartDateTime( QDateTime::currentDateTime().addDays( -1 ) );
00070 }
00071 
00072 void GraphicsScene::Private::resetConstraintItems()
00073 {
00074     q->clearConstraintItems();
00075     if ( constraintModel.isNull() ) return;
00076     QList<Constraint> clst = constraintModel->constraints();
00077     Q_FOREACH( Constraint c, clst ) {
00078         createConstraintItem( c );
00079     }
00080     q->updateItems();
00081 }
00082 
00083 void GraphicsScene::Private::createConstraintItem( const Constraint& c )
00084 {
00085     GraphicsItem* sitem = q->findItem( summaryHandlingModel->mapFromSource( c.startIndex() ) );
00086     GraphicsItem* eitem = q->findItem( summaryHandlingModel->mapFromSource( c.endIndex() ) );
00087 
00088     if ( sitem && eitem ) {
00089         ConstraintGraphicsItem* citem = new ConstraintGraphicsItem( c );
00090         sitem->addStartConstraint( citem );
00091         eitem->addEndConstraint( citem );
00092         q->addItem( citem );
00093     }
00094 
00095 
00096 
00097     //q->insertConstraintItem( c, citem );
00098 }
00099 
00100 // Delete the constraint item, and clean up pointers in the start- and end item
00101 void GraphicsScene::Private::deleteConstraintItem( ConstraintGraphicsItem *citem )
00102 {
00103     //qDebug()<<"GraphicsScene::Private::deleteConstraintItem citem="<<(void*)citem;
00104     if ( citem == 0 ) {
00105         return;
00106     }
00107     Constraint c = citem->constraint();
00108     GraphicsItem* item = items.value( summaryHandlingModel->mapFromSource( c.startIndex() ), 0 );
00109     if ( item ) {
00110         //qDebug()<<"GraphicsScene::Private::deleteConstraintItem startConstraints"<<item<<(void*)citem;
00111         item->removeStartConstraint( citem );
00112     } //else qDebug()<<"GraphicsScene::Private::deleteConstraintItem"<<c.startIndex()<<"start item not found";
00113     item = items.value( summaryHandlingModel->mapFromSource( c.endIndex() ), 0 );
00114     if ( item ) {
00115         //qDebug()<<"GraphicsScene::Private::deleteConstraintItem endConstraints"<<item<<(void*)citem;
00116         item->removeEndConstraint( citem );
00117     } //else qDebug()<<"GraphicsScene::Private::deleteConstraintItem"<<c.endIndex()<<"end item not found";
00118     //qDebug()<<"GraphicsScene::Private::deleteConstraintItem"<<citem<<"deleted";
00119     delete citem;
00120 }
00121 
00122 void GraphicsScene::Private::deleteConstraintItem( const Constraint& c )
00123 {
00124     //qDebug()<<"GraphicsScene::Private::deleteConstraintItem c="<<c;
00125     deleteConstraintItem( findConstraintItem( c ) );
00126 }
00127 
00128 ConstraintGraphicsItem* GraphicsScene::Private::findConstraintItem( const Constraint& c ) const
00129 {
00130     GraphicsItem* item = items.value( summaryHandlingModel->mapFromSource( c.startIndex() ), 0 );
00131     if ( item ) {
00132         QList<ConstraintGraphicsItem*> clst = item->startConstraints();
00133         QList<ConstraintGraphicsItem*>::iterator it = clst.begin();
00134         //qDebug()<<"GraphicsScene::Private::findConstraintItem start:"<<c<<item<<clst;
00135         for( ; it != clst.end() ; ++it )
00136             if ((*it)->constraint() == c )
00137                 break;
00138         if (  it != clst.end() ) {
00139             return *it;
00140         }
00141     }
00142     item = items.value( summaryHandlingModel->mapFromSource( c.endIndex() ), 0 );
00143     if ( item ) {
00144         QList<ConstraintGraphicsItem*> clst = item->endConstraints();
00145         QList<ConstraintGraphicsItem*>::iterator it = clst.begin();
00146         //qDebug()<<"GraphicsScene::Private::findConstraintItem end:"<<c<<item<<clst;
00147         for( ; it != clst.end() ; ++it )
00148             if ((*it)->constraint() == c )
00149                 break;
00150         if (  it != clst.end() ) {
00151             return *it;
00152         }
00153     }
00154     //qDebug()<<"GraphicsScene::Private::findConstraintItem No item or constraintitem"<<c;
00155     return 0;
00156 }
00157 
00158 GraphicsScene::GraphicsScene( QObject* parent )
00159     : QGraphicsScene( parent ), _d( new Private( this ) )
00160 {
00161     init();
00162 }
00163 
00164 GraphicsScene::~GraphicsScene()
00165 {
00166     clearConstraintItems();
00167     clearItems();
00168 }
00169 
00170 #define d d_func()
00171 
00172 void GraphicsScene::init()
00173 {
00174     setItemIndexMethod( QGraphicsScene::NoIndex );
00175     setConstraintModel( new ConstraintModel( this ) );
00176     connect( d->grid, SIGNAL( gridChanged() ), this, SLOT( slotGridChanged() ) );
00177 }
00178 
00179 /* NOTE: The delegate should really be a property
00180  * of the view, but that doesn't really fit at
00181  * this time
00182  */
00183 void GraphicsScene::setItemDelegate( ItemDelegate* delegate )
00184 {
00185     if ( !d->itemDelegate.isNull() && d->itemDelegate->parent()==this ) delete d->itemDelegate;
00186     d->itemDelegate = delegate;
00187     update();
00188 }
00189 
00190 ItemDelegate* GraphicsScene::itemDelegate() const
00191 {
00192     return d->itemDelegate;
00193 }
00194 
00195 QAbstractItemModel* GraphicsScene::model() const
00196 {
00197     assert(!d->summaryHandlingModel.isNull());
00198     return d->summaryHandlingModel->sourceModel();
00199 }
00200 
00201 void GraphicsScene::setModel( QAbstractItemModel* model )
00202 {
00203     assert(!d->summaryHandlingModel.isNull());
00204     d->summaryHandlingModel->setSourceModel(model);
00205     d->grid->setModel( d->summaryHandlingModel );
00206     setSelectionModel( new QItemSelectionModel( model, this ) );
00207 }
00208 
00209 QAbstractProxyModel* GraphicsScene::summaryHandlingModel() const
00210 {
00211     return d->summaryHandlingModel;
00212 }
00213 
00214 void GraphicsScene::setSummaryHandlingModel( QAbstractProxyModel* proxyModel )
00215 {
00216     proxyModel->setSourceModel( model() );
00217     d->summaryHandlingModel = proxyModel;
00218 }
00219 
00220 void GraphicsScene::setRootIndex( const QModelIndex& idx )
00221 {
00222     d->grid->setRootIndex( idx );
00223 }
00224 
00225 QModelIndex GraphicsScene::rootIndex() const
00226 {
00227     return d->grid->rootIndex();
00228 }
00229 
00230 ConstraintModel* GraphicsScene::constraintModel() const
00231 {
00232     return d->constraintModel;
00233 }
00234 
00235 void GraphicsScene::setConstraintModel( ConstraintModel* cm )
00236 {
00237     if ( !d->constraintModel.isNull() ) {
00238         disconnect( d->constraintModel );
00239     }
00240     d->constraintModel = cm;
00241 
00242     connect( cm, SIGNAL( constraintAdded( const KDGantt::Constraint& ) ), this, SLOT( slotConstraintAdded( const KDGantt::Constraint& ) ) );
00243     connect( cm, SIGNAL( constraintRemoved( const KDGantt::Constraint& ) ), this, SLOT( slotConstraintRemoved( const KDGantt::Constraint& ) ) );
00244     d->resetConstraintItems();
00245 }
00246 
00247 void GraphicsScene::setSelectionModel( QItemSelectionModel* smodel )
00248 {
00249     d->selectionModel = smodel;
00250     // TODO: update selection from model and connect signals
00251 }
00252 
00253 QItemSelectionModel* GraphicsScene::selectionModel() const
00254 {
00255     return d->selectionModel;
00256 }
00257 
00258 void GraphicsScene::setRowController( AbstractRowController* rc )
00259 {
00260     d->rowController = rc;
00261 }
00262 
00263 AbstractRowController* GraphicsScene::rowController() const
00264 {
00265     return d->rowController;
00266 }
00267 
00268 void GraphicsScene::setGrid( AbstractGrid* grid )
00269 {
00270     QAbstractItemModel* model = d->grid->model();
00271     if ( grid == 0 ) grid = &d->default_grid;
00272     if ( d->grid ) disconnect( d->grid );
00273     d->grid = grid;
00274     connect( d->grid, SIGNAL( gridChanged() ), this, SLOT( slotGridChanged() ) );
00275     d->grid->setModel( model );
00276     slotGridChanged();
00277 }
00278 
00279 AbstractGrid* GraphicsScene::grid() const
00280 {
00281     return d->grid;
00282 }
00283 
00284 void GraphicsScene::setReadOnly( bool ro )
00285 {
00286     d->readOnly = ro;
00287 }
00288 
00289 bool GraphicsScene::isReadOnly() const
00290 {
00291     return d->readOnly;
00292 }
00293 
00294 /* Returns the index with column=0 fromt the
00295  * same row as idx and with the same parent.
00296  * This is used to traverse the tree-structure
00297  * of the model
00298  */
00299 QModelIndex GraphicsScene::mainIndex( const QModelIndex& idx )
00300 {
00301 #if 0
00302     if ( idx.isValid() ) {
00303         return idx.model()->index( idx.row(), 0,idx.parent() );
00304     } else {
00305         return QModelIndex();
00306     }
00307 #else
00308     return idx;
00309 #endif
00310 }
00311 
00316 QModelIndex GraphicsScene::dataIndex( const QModelIndex& idx )
00317 {
00318 #if 0
00319     if ( idx.isValid() ) {
00320         const QAbstractItemModel* model = idx.model();
00321         return model->index( idx.row(), model->columnCount( idx.parent() )-1,idx.parent() );
00322     } else {
00323         return QModelIndex();
00324     }
00325 #else
00326     return idx;
00327 #endif
00328 }
00329 
00334 GraphicsItem* GraphicsScene::createItem( ItemType type ) const
00335 {
00336 #if 0
00337     switch( type ) {
00338     case TypeEvent:   return 0;
00339     case TypeTask:    return new TaskItem;
00340     case TypeSummary: return new SummaryItem;
00341     default:          return 0;
00342     }
00343 #endif
00344     //qDebug() << "GraphicsScene::createItem("<<type<<")";
00345     Q_UNUSED( type );
00346     return new GraphicsItem;
00347 }
00348 
00349 void GraphicsScene::Private::recursiveUpdateMultiItem( const Span& span, const QModelIndex& idx )
00350 {
00351     //qDebug() << "recursiveUpdateMultiItem("<<span<<idx<<")";
00352     GraphicsItem* item = q->findItem( idx );
00353     const int itemtype = summaryHandlingModel->data( idx, ItemTypeRole ).toInt();
00354     if (!item) {
00355         item = q->createItem( static_cast<ItemType>( itemtype ) );
00356         item->setIndex( idx );
00357         q->insertItem( idx, item);
00358     }
00359     item->updateItem( span, idx );
00360     QModelIndex child;
00361     int cr = 0;
00362     while ( ( child = idx.child( cr, 0 ) ).isValid() ) {
00363         recursiveUpdateMultiItem( span, child );
00364         ++cr;
00365     }
00366 }
00367 
00368 void GraphicsScene::updateRow( const QModelIndex& rowidx )
00369 {
00370     //qDebug() << "GraphicsScene::updateRow("<<rowidx<<")" << rowidx.data( Qt::DisplayRole );
00371     if ( !rowidx.isValid() ) return;
00372     const QAbstractItemModel* model = rowidx.model(); // why const?
00373     assert( model );
00374     assert( rowController() );
00375     assert( model == summaryHandlingModel() );
00376 
00377     const QModelIndex sidx = summaryHandlingModel()->mapToSource( rowidx );
00378     Span rg = rowController()->rowGeometry( sidx );
00379     for ( QModelIndex treewalkidx = sidx; treewalkidx.isValid(); treewalkidx = treewalkidx.parent() ) {
00380         if ( treewalkidx.data( ItemTypeRole ).toInt() == TypeMulti
00381              && !rowController()->isRowExpanded( treewalkidx )) {
00382             rg = rowController()->rowGeometry( treewalkidx );
00383         }
00384     }
00385 
00386     bool blocked = blockSignals( true );
00387     for ( int col = 0; col < summaryHandlingModel()->columnCount( rowidx.parent() ); ++col ) {
00388         const QModelIndex idx = summaryHandlingModel()->index( rowidx.row(), col, rowidx.parent() );
00389         const QModelIndex sidx = summaryHandlingModel()->mapToSource( idx );
00390         const int itemtype = summaryHandlingModel()->data( idx, ItemTypeRole ).toInt();
00391         const bool isExpanded = rowController()->isRowExpanded( sidx );
00392         if ( itemtype == TypeNone ) {
00393             removeItem( idx );
00394             continue;
00395         }
00396         if ( itemtype == TypeMulti && !isExpanded ) {
00397             d->recursiveUpdateMultiItem( rg, idx );
00398         } else {
00399             if ( summaryHandlingModel()->data( rowidx.parent(), ItemTypeRole ).toInt() == TypeMulti && !isExpanded ) {
00400                 //continue;
00401             }
00402 
00403             GraphicsItem* item = findItem( idx );
00404             if (!item) {
00405                 item = createItem( static_cast<ItemType>( itemtype ) );
00406                 item->setIndex( idx );
00407                 insertItem(idx, item);
00408             }
00409             const Span span = rowController()->rowGeometry( sidx );
00410             item->updateItem( span, idx );
00411         }
00412     }
00413     blockSignals( blocked );
00414 }
00415 
00416 void GraphicsScene::insertItem( const QPersistentModelIndex& idx, GraphicsItem* item )
00417 {
00418     if ( !d->constraintModel.isNull() ) {
00419         // Create items for constraints
00420         const QModelIndex sidx = summaryHandlingModel()->mapToSource( idx );
00421         const QList<Constraint> clst = d->constraintModel->constraintsForIndex( sidx );
00422         Q_FOREACH( Constraint c,  clst ) {
00423             QModelIndex other_idx;
00424             if ( c.startIndex() == sidx ) {
00425                 other_idx = c.endIndex();
00426                 GraphicsItem* other_item = d->items.value(summaryHandlingModel()->mapFromSource( other_idx ),0);
00427                 if ( !other_item ) continue;
00428                 ConstraintGraphicsItem* citem = new ConstraintGraphicsItem( c );
00429                 item->addStartConstraint( citem );
00430                 other_item->addEndConstraint( citem );
00431                 addItem( citem );
00432             } else if ( c.endIndex() == sidx ) {
00433                 other_idx = c.startIndex();
00434                 GraphicsItem* other_item = d->items.value(summaryHandlingModel()->mapFromSource( other_idx ),0);
00435                 if ( !other_item ) continue;
00436                 ConstraintGraphicsItem* citem = new ConstraintGraphicsItem( c );
00437                 other_item->addStartConstraint( citem );
00438                 item->addEndConstraint( citem );
00439                 addItem( citem );
00440             } else {
00441                 assert( 0 ); // Impossible
00442             }
00443         }
00444     }
00445     d->items.insert( idx, item );
00446     addItem( item );
00447 }
00448 
00449 void GraphicsScene::removeItem( const QModelIndex& idx )
00450 {
00451     //qDebug() << "GraphicsScene::removeItem("<<idx<<")";
00452     QHash<QPersistentModelIndex,GraphicsItem*>::iterator it = d->items.find( idx );
00453     if ( it != d->items.end() ) {
00454         GraphicsItem* item = *it;
00455         assert( item );
00456         // We have to remove the item from the list first because
00457         // there is a good chance there will be reentrant calls
00458         d->items.erase( it );
00459         {
00460             // Remove any constraintitems attached
00461             const QSet<ConstraintGraphicsItem*> clst = QSet<ConstraintGraphicsItem*>::fromList( item->startConstraints() ) +
00462                                                        QSet<ConstraintGraphicsItem*>::fromList( item->endConstraints() );
00463             Q_FOREACH( ConstraintGraphicsItem* citem, clst ) {
00464                 d->deleteConstraintItem( citem );
00465             }
00466         }
00467         // Get rid of the item
00468         delete item;
00469     }
00470 }
00471 
00472 GraphicsItem* GraphicsScene::findItem( const QModelIndex& idx ) const
00473 {
00474     if ( !idx.isValid() ) return 0;
00475     assert( idx.model() == summaryHandlingModel() );
00476     QHash<QPersistentModelIndex,GraphicsItem*>::const_iterator it = d->items.find( idx );
00477     return ( it != d->items.end() )?*it:0;
00478 }
00479 
00480 GraphicsItem* GraphicsScene::findItem( const QPersistentModelIndex& idx ) const
00481 {
00482     if ( !idx.isValid() ) return 0;
00483     assert( idx.model() == summaryHandlingModel() );
00484     QHash<QPersistentModelIndex,GraphicsItem*>::const_iterator it = d->items.find( idx );
00485     return ( it != d->items.end() )?*it:0;
00486 }
00487 
00488 void GraphicsScene::clearItems()
00489 {
00490     // TODO constraints
00491     qDeleteAll( items() );
00492     d->items.clear();
00493 }
00494 
00495 void GraphicsScene::updateItems()
00496 {
00497     for ( QHash<QPersistentModelIndex,GraphicsItem*>::iterator it = d->items.begin();
00498           it != d->items.end(); ++it ) {
00499         GraphicsItem* const item = it.value();
00500         const QPersistentModelIndex& idx = it.key();
00501         item->updateItem( Span( item->pos().y(), item->rect().height() ), idx );
00502     }
00503     invalidate( QRectF(), QGraphicsScene::BackgroundLayer );
00504 }
00505 
00506 void GraphicsScene::deleteSubtree( const QModelIndex& _idx )
00507 {
00508     QModelIndex idx = dataIndex( _idx );
00509     if ( !idx.model() ) return;
00510     const QModelIndex parent( idx.parent() );
00511     const int colcount = idx.model()->columnCount( parent );
00512     {for ( int i = 0; i < colcount; ++i ) {
00513         removeItem( parent.child( idx.row(), i ) );
00514     }}
00515     const int rowcount = summaryHandlingModel()->rowCount( _idx );
00516     {for ( int i = 0; i < rowcount; ++i ) {
00517         deleteSubtree( summaryHandlingModel()->index( i, summaryHandlingModel()->columnCount(_idx)-1, _idx ) );
00518     }}
00519 }
00520 
00521 
00522 ConstraintGraphicsItem* GraphicsScene::findConstraintItem( const Constraint& c ) const
00523 {
00524     return d->findConstraintItem( c );
00525 }
00526 
00527 void GraphicsScene::clearConstraintItems()
00528 {
00529     // TODO
00530     // d->constraintItems.clearConstraintItems();
00531 }
00532 
00533 void GraphicsScene::slotConstraintAdded( const KDGantt::Constraint& c )
00534 {
00535     d->createConstraintItem( c );
00536 }
00537 
00538 void GraphicsScene::slotConstraintRemoved( const KDGantt::Constraint& c )
00539 {
00540     d->deleteConstraintItem( c );
00541 }
00542 
00543 void GraphicsScene::slotGridChanged()
00544 {
00545     updateItems();
00546     update();
00547     emit gridChanged();
00548 }
00549 
00550 void GraphicsScene::helpEvent( QGraphicsSceneHelpEvent *helpEvent )
00551 {
00552 #ifndef QT_NO_TOOLTIP
00553     QGraphicsItem *item = itemAt( helpEvent->scenePos() );
00554     if ( GraphicsItem* gitem = qgraphicsitem_cast<GraphicsItem*>( item ) ) {
00555         QToolTip::showText(helpEvent->screenPos(), gitem->ganttToolTip());
00556     } else if ( ConstraintGraphicsItem* citem = qgraphicsitem_cast<ConstraintGraphicsItem*>( item ) ) {
00557         QToolTip::showText(helpEvent->screenPos(), citem->ganttToolTip());
00558     } else {
00559         QGraphicsScene::helpEvent( helpEvent );
00560     }
00561 #endif /* QT_NO_TOOLTIP */
00562 }
00563 
00564 void GraphicsScene::drawBackground( QPainter* painter, const QRectF& _rect )
00565 {
00566     QRectF scn( sceneRect() );
00567     QRectF rect( _rect );
00568     if ( d->isPrinting ) {
00569         QRectF headerRect( scn.topLeft()+QPointF( d->labelsWidth, 0 ),
00570                            QSizeF( scn.width()-d->labelsWidth, d->rowController->headerHeight() ));
00571         d->grid->paintHeader( painter, headerRect, rect, 0, 0 );
00572 
00573         /* We have to blank out the part of the header that is invisible during
00574      * normal rendering when we are printing.
00575      */
00576         QRectF labelsTabRect( scn.topLeft(), QSizeF( d->labelsWidth, headerRect.height() ) );
00577 
00578         QStyleOptionHeader opt;
00579         opt.rect = labelsTabRect.toRect();
00580         opt.text = tr( "" );
00581         opt.textAlignment = Qt::AlignCenter;
00582 #if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)
00583         style()->drawControl(QStyle::CE_Header, &opt, painter, 0);
00584 #else
00585         QApplication::style()->drawControl(QStyle::CE_Header, &opt, painter, 0);
00586 #endif
00587         scn.setTop( headerRect.bottom() );
00588         scn.setLeft( headerRect.left() );
00589         rect = rect.intersected( scn );
00590     }
00591     d->grid->paintGrid( painter, scn, rect, d->rowController );
00592 
00593     d->grid->drawBackground(painter, rect);
00594 }
00595 
00596 void GraphicsScene::drawForeground( QPainter* painter, const QRectF& rect )
00597 {
00598     d->grid->drawForeground(painter, rect);
00599 }
00600 
00601 void GraphicsScene::itemEntered( const QModelIndex& idx )
00602 {
00603     emit entered( idx );
00604 }
00605 
00606 void GraphicsScene::itemPressed( const QModelIndex& idx )
00607 {
00608     emit pressed( idx );
00609 }
00610 
00611 void GraphicsScene::itemClicked( const QModelIndex& idx )
00612 {
00613     emit clicked( idx );
00614 }
00615 
00616 void GraphicsScene::itemDoubleClicked( const QModelIndex& idx )
00617 {
00618     emit doubleClicked( idx );
00619 }
00620 
00621 void GraphicsScene::setDragSource( GraphicsItem* item )
00622 {
00623     d->dragSource = item;
00624 }
00625 
00626 GraphicsItem* GraphicsScene::dragSource() const
00627 {
00628     return d->dragSource;
00629 }
00630 
00637 void GraphicsScene::print( QPrinter* printer, bool drawRowLabels )
00638 {
00639     QPainter painter( printer );
00640     doPrint( &painter, printer->pageRect(), sceneRect().left(), sceneRect().right(), printer, drawRowLabels );
00641 }
00642 
00653 void GraphicsScene::print( QPrinter* printer, qreal start, qreal end, bool drawRowLabels )
00654 {
00655     QPainter painter( printer );
00656     doPrint( &painter, printer->pageRect(), start, end, printer, drawRowLabels );
00657 }
00658 
00663 void GraphicsScene::print( QPainter* painter, const QRectF& _targetRect, bool drawRowLabels )
00664 {
00665     QRectF targetRect( _targetRect );
00666     if ( targetRect.isNull() ) {
00667         targetRect = sceneRect();
00668     }
00669 
00670     doPrint( painter, targetRect, sceneRect().left(), sceneRect().right(), 0, drawRowLabels );
00671 }
00672 
00681 void GraphicsScene::print( QPainter* painter, qreal start, qreal end,
00682                            const QRectF& _targetRect, bool drawRowLabels )
00683 {
00684     QRectF targetRect( _targetRect );
00685     if ( targetRect.isNull() ) {
00686         targetRect = sceneRect();
00687     }
00688 
00689     doPrint( painter, targetRect, start, end, 0, drawRowLabels );
00690 }
00691 
00694 void GraphicsScene::doPrint( QPainter* painter, const QRectF& targetRect,
00695                              qreal start, qreal end,
00696                              QPrinter* printer, bool drawRowLabels )
00697 {
00698     assert( painter );
00699     d->isPrinting = true;
00700 #if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)
00701     QFont sceneFont( font() );
00702     if ( printer ) {
00703         sceneFont = QFont( font(), printer );
00704         if ( font().pointSizeF() >= 0.0 )
00705             sceneFont.setPointSizeF( font().pointSizeF() );
00706         else if ( font().pointSize() >= 0 )
00707             sceneFont.setPointSize( font().pointSize() );
00708         else
00709             sceneFont.setPixelSize( font().pixelSize() );
00710     }
00711 #else
00712     QFont sceneFont( painter->font() );
00713     if ( printer ) {
00714         sceneFont = QFont( painter->font(), printer );
00715         if ( painter->font().pointSizeF() >= 0.0 )
00716             sceneFont.setPointSizeF( painter->font().pointSizeF() );
00717         else if ( painter->font().pointSize() >= 0 )
00718             sceneFont.setPointSize( painter->font().pointSize() );
00719         else
00720             sceneFont.setPixelSize( painter->font().pixelSize() );
00721     }
00722 #endif
00723 
00724     const QRectF oldScnRect( sceneRect() );
00725     QRectF scnRect( oldScnRect );
00726     scnRect.setLeft( start );
00727     scnRect.setRight( end );
00728     scnRect.setTop( -d->rowController->headerHeight() );
00729     bool b = blockSignals( true );
00730 
00731     /* row labels */
00732     QVector<QGraphicsTextItem*> textLabels;
00733     if ( drawRowLabels ) {
00734         qreal textWidth = 0.;
00735         QModelIndex sidx = summaryHandlingModel()->mapToSource( summaryHandlingModel()->index( 0, 0, rootIndex()) );
00736         do {
00737             QModelIndex idx = summaryHandlingModel()->mapFromSource( sidx );
00738             const Span rg=rowController()->rowGeometry( sidx );
00739             const QString txt = idx.data( Qt::DisplayRole ).toString();
00740             QGraphicsTextItem* item = new QGraphicsTextItem( txt );
00741             addItem( item );
00742             textLabels << item;
00743             item->adjustSize();
00744             textWidth = qMax( item->textWidth(), textWidth );
00745             item->setPos( 0, rg.start() );
00746         } while ( ( sidx = rowController()->indexBelow( sidx ) ).isValid() );
00747         // Add a little margin to textWidth
00748         textWidth += QFontMetricsF(sceneFont).width( QString::fromLatin1( "X" ) );
00749         Q_FOREACH( QGraphicsTextItem* item, textLabels ) {
00750             item->setPos( scnRect.left()-textWidth, item->y() );
00751             item->show();
00752         }
00753         scnRect.setLeft( scnRect.left()-textWidth );
00754         d->labelsWidth = textWidth;
00755     }
00756 
00757     setSceneRect( scnRect );
00758 
00759     painter->save();
00760     painter->setClipRect( targetRect );
00761 
00762     qreal yratio = targetRect.height()/scnRect.height();
00763     /* If we're not printing multiple pages,
00764      * check if the span fits and adjust:
00765      */
00766     if ( !printer && targetRect.width()/scnRect.width() < yratio ) {
00767         yratio = targetRect.width()/scnRect.width();
00768     }
00769 
00770     qreal offset = scnRect.left();
00771     int pagecount = 0;
00772     while ( offset < scnRect.right() ) {
00773         painter->setFont( sceneFont );
00774         render( painter, targetRect, QRectF( QPointF( offset, scnRect.top()),
00775                                              QSizeF( targetRect.width()/yratio, scnRect.height() ) ) );
00776         offset += targetRect.width()/yratio;
00777         ++pagecount;
00778         if ( printer && offset < scnRect.right() ) {
00779             printer->newPage();
00780         } else {
00781             break;
00782         }
00783     }
00784 
00785     d->isPrinting = false;
00786     qDeleteAll( textLabels );
00787     blockSignals( b );
00788     setSceneRect( oldScnRect );
00789     painter->restore();
00790 }
00791 
00792 #include "moc_kdganttgraphicsscene.cpp"
00793