kdganttgraphicsscene.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** Copyright (C) 2001-2011 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.txt 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     //q->insertConstraintItem( c, citem );
00096 }
00097 
00098 // Delete the constraint item, and clean up pointers in the start- and end item
00099 void GraphicsScene::Private::deleteConstraintItem( ConstraintGraphicsItem *citem )
00100 {
00101     //qDebug()<<"GraphicsScene::Private::deleteConstraintItem citem="<<citem;
00102     if ( citem == 0 ) {
00103         return;
00104     }
00105     Constraint c = citem->constraint();
00106     GraphicsItem* item = items.value( summaryHandlingModel->mapFromSource( c.startIndex() ), 0 );
00107     if ( item ) {
00108         item->removeStartConstraint( citem );
00109     }
00110     item = items.value( summaryHandlingModel->mapFromSource( c.endIndex() ), 0 );
00111     if ( item ) {
00112         item->removeEndConstraint( citem );
00113     }
00114     delete citem;
00115 }
00116 
00117 void GraphicsScene::Private::deleteConstraintItem( const Constraint& c )
00118 {
00119     deleteConstraintItem( findConstraintItem( c ) );
00120 }
00121 
00122 ConstraintGraphicsItem* GraphicsScene::Private::findConstraintItem( const Constraint& c ) const
00123 {
00124     GraphicsItem* item = items.value( summaryHandlingModel->mapFromSource( c.startIndex() ), 0 );
00125     if ( item ) {
00126         const QList<ConstraintGraphicsItem*> clst = item->startConstraints();
00127         QList<ConstraintGraphicsItem*>::const_iterator it = clst.begin();
00128         for( ; it != clst.end() ; ++it ) {
00129             if ( c.compareIndexes((*it)->constraint()) )
00130                 break;
00131         }
00132         if (  it != clst.end() ) {
00133             return *it;
00134         }
00135     }
00136     item = items.value( summaryHandlingModel->mapFromSource( c.endIndex() ), 0 );
00137     if ( item ) {
00138         const QList<ConstraintGraphicsItem*> clst = item->endConstraints();
00139         QList<ConstraintGraphicsItem*>::const_iterator it = clst.begin();
00140         for( ; it != clst.end() ; ++it ) {
00141             if ( c.compareIndexes( (*it)->constraint() ) )
00142                 break;
00143         }
00144         if (  it != clst.end() ) {
00145             return *it;
00146         }
00147     }
00148     return 0;
00149 }
00150 
00151 GraphicsScene::GraphicsScene( QObject* parent )
00152     : QGraphicsScene( parent ), _d( new Private( this ) )
00153 {
00154     init();
00155 }
00156 
00157 GraphicsScene::~GraphicsScene()
00158 {
00159     clearConstraintItems();
00160     clearItems();
00161 }
00162 
00163 #define d d_func()
00164 
00165 void GraphicsScene::init()
00166 {
00167     setItemIndexMethod( QGraphicsScene::NoIndex );
00168     setConstraintModel( new ConstraintModel( this ) );
00169     connect( d->grid, SIGNAL( gridChanged() ), this, SLOT( slotGridChanged() ) );
00170 }
00171 
00172 /* NOTE: The delegate should really be a property
00173  * of the view, but that doesn't really fit at
00174  * this time
00175  */
00176 void GraphicsScene::setItemDelegate( ItemDelegate* delegate )
00177 {
00178     if ( !d->itemDelegate.isNull() && d->itemDelegate->parent()==this ) delete d->itemDelegate;
00179     d->itemDelegate = delegate;
00180     update();
00181 }
00182 
00183 ItemDelegate* GraphicsScene::itemDelegate() const
00184 {
00185     return d->itemDelegate;
00186 }
00187 
00188 QAbstractItemModel* GraphicsScene::model() const
00189 {
00190     assert(!d->summaryHandlingModel.isNull());
00191     return d->summaryHandlingModel->sourceModel();
00192 }
00193 
00194 void GraphicsScene::setModel( QAbstractItemModel* model )
00195 {
00196     assert(!d->summaryHandlingModel.isNull());
00197     d->summaryHandlingModel->setSourceModel(model);
00198     d->grid->setModel( d->summaryHandlingModel );
00199     setSelectionModel( new QItemSelectionModel( model, this ) );
00200 }
00201 
00202 QAbstractProxyModel* GraphicsScene::summaryHandlingModel() const
00203 {
00204     return d->summaryHandlingModel;
00205 }
00206 
00207 void GraphicsScene::setSummaryHandlingModel( QAbstractProxyModel* proxyModel )
00208 {
00209     proxyModel->setSourceModel( model() );
00210     d->summaryHandlingModel = proxyModel;
00211 }
00212 
00213 void GraphicsScene::setRootIndex( const QModelIndex& idx )
00214 {
00215     d->grid->setRootIndex( idx );
00216 }
00217 
00218 QModelIndex GraphicsScene::rootIndex() const
00219 {
00220     return d->grid->rootIndex();
00221 }
00222 
00223 ConstraintModel* GraphicsScene::constraintModel() const
00224 {
00225     return d->constraintModel;
00226 }
00227 
00228 void GraphicsScene::setConstraintModel( ConstraintModel* cm )
00229 {
00230     if ( !d->constraintModel.isNull() ) {
00231         d->constraintModel->disconnect( this );
00232     }
00233     d->constraintModel = cm;
00234 
00235     connect( cm, SIGNAL( constraintAdded( const KDGantt::Constraint& ) ),
00236              this, SLOT( slotConstraintAdded( const KDGantt::Constraint& ) ) );
00237     connect( cm, SIGNAL( constraintRemoved( const KDGantt::Constraint& ) ),
00238              this, SLOT( slotConstraintRemoved( const KDGantt::Constraint& ) ) );
00239     d->resetConstraintItems();
00240 }
00241 
00242 void GraphicsScene::setSelectionModel( QItemSelectionModel* smodel )
00243 {
00244     d->selectionModel = smodel;
00245     // TODO: update selection from model and connect signals
00246 }
00247 
00248 QItemSelectionModel* GraphicsScene::selectionModel() const
00249 {
00250     return d->selectionModel;
00251 }
00252 
00253 void GraphicsScene::setRowController( AbstractRowController* rc )
00254 {
00255     d->rowController = rc;
00256 }
00257 
00258 AbstractRowController* GraphicsScene::rowController() const
00259 {
00260     return d->rowController;
00261 }
00262 
00263 void GraphicsScene::setGrid( AbstractGrid* grid )
00264 {
00265     QAbstractItemModel* model = d->grid->model();
00266     if ( grid == 0 ) grid = &d->default_grid;
00267     if ( d->grid ) d->grid->disconnect( this );
00268     d->grid = grid;
00269     connect( d->grid, SIGNAL( gridChanged() ), this, SLOT( slotGridChanged() ) );
00270     d->grid->setModel( model );
00271     slotGridChanged();
00272 }
00273 
00274 AbstractGrid* GraphicsScene::grid() const
00275 {
00276     return d->grid;
00277 }
00278 
00279 void GraphicsScene::setReadOnly( bool ro )
00280 {
00281     d->readOnly = ro;
00282 }
00283 
00284 bool GraphicsScene::isReadOnly() const
00285 {
00286     return d->readOnly;
00287 }
00288 
00289 /* Returns the index with column=0 fromt the
00290  * same row as idx and with the same parent.
00291  * This is used to traverse the tree-structure
00292  * of the model
00293  */
00294 QModelIndex GraphicsScene::mainIndex( const QModelIndex& idx )
00295 {
00296 #if 0
00297     if ( idx.isValid() ) {
00298         return idx.model()->index( idx.row(), 0,idx.parent() );
00299     } else {
00300         return QModelIndex();
00301     }
00302 #else
00303     return idx;
00304 #endif
00305 }
00306 
00311 QModelIndex GraphicsScene::dataIndex( const QModelIndex& idx )
00312 {
00313 #if 0
00314     if ( idx.isValid() ) {
00315         const QAbstractItemModel* model = idx.model();
00316         return model->index( idx.row(), model->columnCount( idx.parent() )-1,idx.parent() );
00317     } else {
00318         return QModelIndex();
00319     }
00320 #else
00321     return idx;
00322 #endif
00323 }
00324 
00329 GraphicsItem* GraphicsScene::createItem( ItemType type ) const
00330 {
00331 #if 0
00332     switch( type ) {
00333     case TypeEvent:   return 0;
00334     case TypeTask:    return new TaskItem;
00335     case TypeSummary: return new SummaryItem;
00336     default:          return 0;
00337     }
00338 #endif
00339     //qDebug() << "GraphicsScene::createItem("<<type<<")";
00340     Q_UNUSED( type );
00341     return new GraphicsItem;
00342 }
00343 
00344 void GraphicsScene::Private::recursiveUpdateMultiItem( const Span& span, const QModelIndex& idx )
00345 {
00346     //qDebug() << "recursiveUpdateMultiItem("<<span<<idx<<")";
00347     GraphicsItem* item = q->findItem( idx );
00348     const int itemtype = summaryHandlingModel->data( idx, ItemTypeRole ).toInt();
00349     if (!item) {
00350         item = q->createItem( static_cast<ItemType>( itemtype ) );
00351         item->setIndex( idx );
00352         q->insertItem( idx, item);
00353     }
00354     item->updateItem( span, idx );
00355     QModelIndex child;
00356     int cr = 0;
00357     while ( ( child = idx.child( cr, 0 ) ).isValid() ) {
00358         recursiveUpdateMultiItem( span, child );
00359         ++cr;
00360     }
00361 }
00362 
00363 void GraphicsScene::updateRow( const QModelIndex& rowidx )
00364 {
00365     //qDebug() << "GraphicsScene::updateRow("<<rowidx<<")" << rowidx.data( Qt::DisplayRole );
00366     if ( !rowidx.isValid() ) return;
00367     const QAbstractItemModel* model = rowidx.model(); // why const?
00368     assert( model );
00369     assert( rowController() );
00370     assert( model == summaryHandlingModel() );
00371 
00372     const QModelIndex sidx = summaryHandlingModel()->mapToSource( rowidx );
00373     Span rg = rowController()->rowGeometry( sidx );
00374     for ( QModelIndex treewalkidx = sidx; treewalkidx.isValid(); treewalkidx = treewalkidx.parent() ) {
00375         if ( treewalkidx.data( ItemTypeRole ).toInt() == TypeMulti
00376              && !rowController()->isRowExpanded( treewalkidx )) {
00377             rg = rowController()->rowGeometry( treewalkidx );
00378         }
00379     }
00380 
00381     bool blocked = blockSignals( true );
00382     for ( int col = 0; col < summaryHandlingModel()->columnCount( rowidx.parent() ); ++col ) {
00383         const QModelIndex idx = summaryHandlingModel()->index( rowidx.row(), col, rowidx.parent() );
00384         const QModelIndex sidx = summaryHandlingModel()->mapToSource( idx );
00385         const int itemtype = summaryHandlingModel()->data( idx, ItemTypeRole ).toInt();
00386         const bool isExpanded = rowController()->isRowExpanded( sidx );
00387         if ( itemtype == TypeNone ) {
00388             removeItem( idx );
00389             continue;
00390         }
00391         if ( itemtype == TypeMulti && !isExpanded ) {
00392             d->recursiveUpdateMultiItem( rg, idx );
00393         } else {
00394             if ( summaryHandlingModel()->data( rowidx.parent(), ItemTypeRole ).toInt() == TypeMulti && !isExpanded ) {
00395                 //continue;
00396             }
00397 
00398             GraphicsItem* item = findItem( idx );
00399             if (!item) {
00400                 item = createItem( static_cast<ItemType>( itemtype ) );
00401                 item->setIndex( idx );
00402                 insertItem(idx, item);
00403             }
00404             const Span span = rowController()->rowGeometry( sidx );
00405             item->updateItem( span, idx );
00406         }
00407     }
00408     blockSignals( blocked );
00409 }
00410 
00411 void GraphicsScene::insertItem( const QPersistentModelIndex& idx, GraphicsItem* item )
00412 {
00413     if ( !d->constraintModel.isNull() ) {
00414         // Create items for constraints
00415         const QModelIndex sidx = summaryHandlingModel()->mapToSource( idx );
00416         const QList<Constraint> clst = d->constraintModel->constraintsForIndex( sidx );
00417         Q_FOREACH( Constraint c,  clst ) {
00418             QModelIndex other_idx;
00419             if ( c.startIndex() == sidx ) {
00420                 other_idx = c.endIndex();
00421                 GraphicsItem* other_item = d->items.value(summaryHandlingModel()->mapFromSource( other_idx ),0);
00422                 if ( !other_item ) continue;
00423                 ConstraintGraphicsItem* citem = new ConstraintGraphicsItem( c );
00424                 item->addStartConstraint( citem );
00425                 other_item->addEndConstraint( citem );
00426                 addItem( citem );
00427             } else if ( c.endIndex() == sidx ) {
00428                 other_idx = c.startIndex();
00429                 GraphicsItem* other_item = d->items.value(summaryHandlingModel()->mapFromSource( other_idx ),0);
00430                 if ( !other_item ) continue;
00431                 ConstraintGraphicsItem* citem = new ConstraintGraphicsItem( c );
00432                 other_item->addStartConstraint( citem );
00433                 item->addEndConstraint( citem );
00434                 addItem( citem );
00435             } else {
00436                 assert( 0 ); // Impossible
00437             }
00438         }
00439     }
00440     d->items.insert( idx, item );
00441     addItem( item );
00442 }
00443 
00444 void GraphicsScene::removeItem( const QModelIndex& idx )
00445 {
00446     //qDebug() << "GraphicsScene::removeItem("<<idx<<")";
00447     QHash<QPersistentModelIndex,GraphicsItem*>::iterator it = d->items.find( idx );
00448     if ( it != d->items.end() ) {
00449         GraphicsItem* item = *it;
00450         assert( item );
00451         // We have to remove the item from the list first because
00452         // there is a good chance there will be reentrant calls
00453         d->items.erase( it );
00454         {
00455             // Remove any constraintitems attached
00456             const QSet<ConstraintGraphicsItem*> clst = QSet<ConstraintGraphicsItem*>::fromList( item->startConstraints() ) +
00457                                                        QSet<ConstraintGraphicsItem*>::fromList( item->endConstraints() );
00458             Q_FOREACH( ConstraintGraphicsItem* citem, clst ) {
00459                 d->deleteConstraintItem( citem );
00460             }
00461         }
00462         // Get rid of the item
00463         delete item;
00464     }
00465 }
00466 
00467 GraphicsItem* GraphicsScene::findItem( const QModelIndex& idx ) const
00468 {
00469     if ( !idx.isValid() ) return 0;
00470     assert( idx.model() == summaryHandlingModel() );
00471     QHash<QPersistentModelIndex,GraphicsItem*>::const_iterator it = d->items.find( idx );
00472     return ( it != d->items.end() )?*it:0;
00473 }
00474 
00475 GraphicsItem* GraphicsScene::findItem( const QPersistentModelIndex& idx ) const
00476 {
00477     if ( !idx.isValid() ) return 0;
00478     assert( idx.model() == summaryHandlingModel() );
00479     QHash<QPersistentModelIndex,GraphicsItem*>::const_iterator it = d->items.find( idx );
00480     return ( it != d->items.end() )?*it:0;
00481 }
00482 
00483 void GraphicsScene::clearItems()
00484 {
00485     // TODO constraints
00486     qDeleteAll( items() );
00487     d->items.clear();
00488 }
00489 
00490 void GraphicsScene::updateItems()
00491 {
00492     for ( QHash<QPersistentModelIndex,GraphicsItem*>::iterator it = d->items.begin();
00493           it != d->items.end(); ++it ) {
00494         GraphicsItem* const item = it.value();
00495         const QPersistentModelIndex& idx = it.key();
00496         item->updateItem( Span( item->pos().y(), item->rect().height() ), idx );
00497     }
00498     invalidate( QRectF(), QGraphicsScene::BackgroundLayer );
00499 }
00500 
00501 void GraphicsScene::deleteSubtree( const QModelIndex& _idx )
00502 {
00503     QModelIndex idx = dataIndex( _idx );
00504     if ( !idx.model() ) return;
00505     const QModelIndex parent( idx.parent() );
00506     const int colcount = idx.model()->columnCount( parent );
00507     {for ( int i = 0; i < colcount; ++i ) {
00508         removeItem( parent.child( idx.row(), i ) );
00509     }}
00510     const int rowcount = summaryHandlingModel()->rowCount( _idx );
00511     {for ( int i = 0; i < rowcount; ++i ) {
00512         deleteSubtree( summaryHandlingModel()->index( i, summaryHandlingModel()->columnCount(_idx)-1, _idx ) );
00513     }}
00514 }
00515 
00516 
00517 ConstraintGraphicsItem* GraphicsScene::findConstraintItem( const Constraint& c ) const
00518 {
00519     return d->findConstraintItem( c );
00520 }
00521 
00522 void GraphicsScene::clearConstraintItems()
00523 {
00524     // TODO
00525     // d->constraintItems.clearConstraintItems();
00526 }
00527 
00528 void GraphicsScene::slotConstraintAdded( const KDGantt::Constraint& c )
00529 {
00530     d->createConstraintItem( c );
00531 }
00532 
00533 void GraphicsScene::slotConstraintRemoved( const KDGantt::Constraint& c )
00534 {
00535     d->deleteConstraintItem( c );
00536 }
00537 
00538 void GraphicsScene::slotGridChanged()
00539 {
00540     updateItems();
00541     update();
00542     emit gridChanged();
00543 }
00544 
00545 void GraphicsScene::helpEvent( QGraphicsSceneHelpEvent *helpEvent )
00546 {
00547 #ifndef QT_NO_TOOLTIP
00548     QGraphicsItem *item = itemAt( helpEvent->scenePos() );
00549     if ( GraphicsItem* gitem = qgraphicsitem_cast<GraphicsItem*>( item ) ) {
00550         QToolTip::showText(helpEvent->screenPos(), gitem->ganttToolTip());
00551     } else if ( ConstraintGraphicsItem* citem = qgraphicsitem_cast<ConstraintGraphicsItem*>( item ) ) {
00552         QToolTip::showText(helpEvent->screenPos(), citem->ganttToolTip());
00553     } else {
00554         QGraphicsScene::helpEvent( helpEvent );
00555     }
00556 #endif /* QT_NO_TOOLTIP */
00557 }
00558 
00559 void GraphicsScene::drawBackground( QPainter* painter, const QRectF& _rect )
00560 {
00561     QRectF scn( sceneRect() );
00562     QRectF rect( _rect );
00563     if ( d->isPrinting ) {
00564         QRectF headerRect( scn.topLeft()+QPointF( d->labelsWidth, 0 ),
00565                            QSizeF( scn.width()-d->labelsWidth, d->rowController->headerHeight() ));
00566         d->grid->paintHeader( painter, headerRect, rect, 0, 0 );
00567 
00568         /* We have to blank out the part of the header that is invisible during
00569      * normal rendering when we are printing.
00570      */
00571         QRectF labelsTabRect( scn.topLeft(), QSizeF( d->labelsWidth, headerRect.height() ) );
00572 
00573         QStyleOptionHeader opt;
00574         opt.rect = labelsTabRect.toRect();
00575         opt.text = tr( "" );
00576         opt.textAlignment = Qt::AlignCenter;
00577 #if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)
00578         style()->drawControl(QStyle::CE_Header, &opt, painter, 0);
00579 #else
00580         QApplication::style()->drawControl(QStyle::CE_Header, &opt, painter, 0);
00581 #endif
00582         scn.setTop( headerRect.bottom() );
00583         scn.setLeft( headerRect.left() );
00584         rect = rect.intersected( scn );
00585     }
00586     d->grid->paintGrid( painter, scn, rect, d->rowController );
00587 
00588     d->grid->drawBackground(painter, rect);
00589 }
00590 
00591 void GraphicsScene::drawForeground( QPainter* painter, const QRectF& rect )
00592 {
00593     d->grid->drawForeground(painter, rect);
00594 }
00595 
00596 void GraphicsScene::itemEntered( const QModelIndex& idx )
00597 {
00598     emit entered( idx );
00599 }
00600 
00601 void GraphicsScene::itemPressed( const QModelIndex& idx )
00602 {
00603     emit pressed( idx );
00604 }
00605 
00606 void GraphicsScene::itemClicked( const QModelIndex& idx )
00607 {
00608     emit clicked( idx );
00609 }
00610 
00611 void GraphicsScene::itemDoubleClicked( const QModelIndex& idx )
00612 {
00613     emit doubleClicked( idx );
00614 }
00615 
00616 void GraphicsScene::setDragSource( GraphicsItem* item )
00617 {
00618     d->dragSource = item;
00619 }
00620 
00621 GraphicsItem* GraphicsScene::dragSource() const
00622 {
00623     return d->dragSource;
00624 }
00625 
00632 void GraphicsScene::print( QPrinter* printer, bool drawRowLabels )
00633 {
00634 #ifdef QT_NO_PRINTER
00635     Q_UNUSED( printer );
00636     Q_UNUSED( drawRowLabels );
00637 #else
00638     QPainter painter( printer );
00639     doPrint( &painter, printer->pageRect(), sceneRect().left(), sceneRect().right(), printer, drawRowLabels );
00640 #endif
00641 }
00642 
00653 void GraphicsScene::print( QPrinter* printer, qreal start, qreal end, bool drawRowLabels )
00654 {
00655 #ifdef QT_NO_PRINTER
00656     Q_UNUSED( printer );
00657     Q_UNUSED( start );
00658     Q_UNUSED( end );
00659     Q_UNUSED( drawRowLabels );
00660 #else
00661     QPainter painter( printer );
00662     doPrint( &painter, printer->pageRect(), start, end, printer, drawRowLabels );
00663 #endif
00664 }
00665 
00670 void GraphicsScene::print( QPainter* painter, const QRectF& _targetRect, bool drawRowLabels )
00671 {
00672     QRectF targetRect( _targetRect );
00673     if ( targetRect.isNull() ) {
00674         targetRect = sceneRect();
00675     }
00676 
00677     doPrint( painter, targetRect, sceneRect().left(), sceneRect().right(), 0, drawRowLabels );
00678 }
00679 
00688 void GraphicsScene::print( QPainter* painter, qreal start, qreal end,
00689                            const QRectF& _targetRect, bool drawRowLabels )
00690 {
00691     QRectF targetRect( _targetRect );
00692     if ( targetRect.isNull() ) {
00693         targetRect = sceneRect();
00694     }
00695 
00696     doPrint( painter, targetRect, start, end, 0, drawRowLabels );
00697 }
00698 
00701 void GraphicsScene::doPrint( QPainter* painter, const QRectF& targetRect,
00702                              qreal start, qreal end,
00703                              QPrinter* printer, bool drawRowLabels )
00704 {
00705     assert( painter );
00706     d->isPrinting = true;
00707 #if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)
00708     QFont sceneFont( font() );
00709 #ifndef QT_NO_PRINTER
00710     if ( printer ) {
00711         sceneFont = QFont( font(), printer );
00712         if ( font().pointSizeF() >= 0.0 )
00713             sceneFont.setPointSizeF( font().pointSizeF() );
00714         else if ( font().pointSize() >= 0 )
00715             sceneFont.setPointSize( font().pointSize() );
00716         else
00717             sceneFont.setPixelSize( font().pixelSize() );
00718     }
00719 #endif
00720 #else
00721     QFont sceneFont( painter->font() );
00722 #ifndef QT_NO_PRINTER
00723     if ( printer ) {
00724         sceneFont = QFont( painter->font(), printer );
00725         if ( painter->font().pointSizeF() >= 0.0 )
00726             sceneFont.setPointSizeF( painter->font().pointSizeF() );
00727         else if ( painter->font().pointSize() >= 0 )
00728             sceneFont.setPointSize( painter->font().pointSize() );
00729         else
00730             sceneFont.setPixelSize( painter->font().pixelSize() );
00731     }
00732 #endif
00733 #endif
00734 
00735     const QRectF oldScnRect( sceneRect() );
00736     QRectF scnRect( oldScnRect );
00737     scnRect.setLeft( start );
00738     scnRect.setRight( end );
00739     scnRect.setTop( -d->rowController->headerHeight() );
00740     bool b = blockSignals( true );
00741 
00742     /* row labels */
00743     QVector<QGraphicsTextItem*> textLabels;
00744     if ( drawRowLabels ) {
00745         qreal textWidth = 0.;
00746         QModelIndex sidx = summaryHandlingModel()->mapToSource( summaryHandlingModel()->index( 0, 0, rootIndex()) );
00747         do {
00748             QModelIndex idx = summaryHandlingModel()->mapFromSource( sidx );
00749             const Span rg=rowController()->rowGeometry( sidx );
00750             const QString txt = idx.data( Qt::DisplayRole ).toString();
00751             QGraphicsTextItem* item = new QGraphicsTextItem( txt );
00752             addItem( item );
00753             textLabels << item;
00754             item->adjustSize();
00755             textWidth = qMax( item->textWidth(), textWidth );
00756             item->setPos( 0, rg.start() );
00757         } while ( ( sidx = rowController()->indexBelow( sidx ) ).isValid() );
00758         // Add a little margin to textWidth
00759         textWidth += QFontMetricsF(sceneFont).width( QString::fromLatin1( "X" ) );
00760         Q_FOREACH( QGraphicsTextItem* item, textLabels ) {
00761             item->setPos( scnRect.left()-textWidth, item->y() );
00762             item->show();
00763         }
00764         scnRect.setLeft( scnRect.left()-textWidth );
00765         d->labelsWidth = textWidth;
00766     }
00767 
00768     setSceneRect( scnRect );
00769 
00770     painter->save();
00771     painter->setClipRect( targetRect );
00772 
00773     qreal yratio = targetRect.height()/scnRect.height();
00774     /* If we're not printing multiple pages,
00775      * check if the span fits and adjust:
00776      */
00777     if ( !printer && targetRect.width()/scnRect.width() < yratio ) {
00778         yratio = targetRect.width()/scnRect.width();
00779     }
00780 
00781     qreal offset = scnRect.left();
00782     int pagecount = 0;
00783     while ( offset < scnRect.right() ) {
00784         painter->setFont( sceneFont );
00785         render( painter, targetRect, QRectF( QPointF( offset, scnRect.top()),
00786                                              QSizeF( targetRect.width()/yratio, scnRect.height() ) ) );
00787         offset += targetRect.width()/yratio;
00788         ++pagecount;
00789         if ( printer && offset < scnRect.right() ) {
00790 #ifndef QT_NO_PRINTER
00791             printer->newPage();
00792 #endif
00793         } else {
00794             break;
00795         }
00796     }
00797 
00798     d->isPrinting = false;
00799     qDeleteAll( textLabels );
00800     blockSignals( b );
00801     setSceneRect( oldScnRect );
00802     painter->restore();
00803 }
00804 
00805 #include "moc_kdganttgraphicsscene.cpp"
00806 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines

Klarälvdalens Datakonsult AB (KDAB)
Qt-related services and products
http://www.kdab.com/
http://www.kdab.com/products/kd-chart/