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