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