KD Chart 2 [rev.2.4]
|
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 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