24 #include "kdganttgraphicsscene_p.h" 33 #include <QApplication> 34 #include <QGraphicsSceneHelpEvent> 37 #include <QTextDocument> 48 #ifndef QT_VERSION_CHECK 49 # define QT_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch)) 72 grid( &default_grid ),
75 drawColumnLabels( true ),
80 default_grid.setStartDateTime( QDateTime::currentDateTime().addDays( -1 ) );
83 void GraphicsScene::Private::resetConstraintItems()
85 q->clearConstraintItems();
86 if ( constraintModel.isNull() )
return;
89 createConstraintItem( c );
94 void GraphicsScene::Private::createConstraintItem(
const Constraint& c )
99 if ( sitem && eitem ) {
121 item = items.value( summaryHandlingModel->mapFromSource( c.
endIndex() ), 0 );
128 void GraphicsScene::Private::deleteConstraintItem(
const Constraint& c )
130 deleteConstraintItem( findConstraintItem( c ) );
139 for ( ; it != clst.end() ; ++it ) {
143 if ( it != clst.end() ) {
147 item = items.value( summaryHandlingModel->mapFromSource( c.
endIndex() ), 0 );
151 for ( ; it != clst.end() ; ++it ) {
155 if ( it != clst.end() ) {
162 GraphicsScene::GraphicsScene(
QObject* parent )
171 qDeleteAll( items() );
177 void GraphicsScene::init()
179 setItemIndexMethod( QGraphicsScene::NoIndex );
181 connect(
d->grid, SIGNAL(
gridChanged() ),
this, SLOT( slotGridChanged() ) );
190 if ( !
d->itemDelegate.isNull() &&
d->itemDelegate->parent()==this )
delete d->itemDelegate;
191 d->itemDelegate = delegate;
197 return d->itemDelegate;
202 assert(!
d->summaryHandlingModel.isNull());
203 return d->summaryHandlingModel->sourceModel();
208 assert(!
d->summaryHandlingModel.isNull());
209 d->summaryHandlingModel->setSourceModel(model);
210 d->grid->setModel(
d->summaryHandlingModel );
216 return d->summaryHandlingModel;
221 proxyModel->setSourceModel(
model() );
222 d->summaryHandlingModel = proxyModel;
227 d->grid->setRootIndex( idx );
232 return d->grid->rootIndex();
237 return d->constraintModel;
242 if ( !
d->constraintModel.isNull() ) {
243 d->constraintModel->disconnect(
this );
245 d->constraintModel = cm;
251 d->resetConstraintItems();
256 d->selectionModel = smodel;
262 return d->selectionModel;
267 d->rowController = rc;
272 return d->rowController;
277 QAbstractItemModel*
model = 0;
278 if ( grid == 0 ) grid = &
d->default_grid;
280 d->grid->disconnect(
this );
281 model =
d->grid->model();
284 connect(
d->grid, SIGNAL(
gridChanged() ),
this, SLOT( slotGridChanged() ) );
285 d->grid->setModel( model );
312 if ( idx.isValid() ) {
313 return idx.model()->index( idx.row(), 0,idx.parent() );
315 return QModelIndex();
329 if ( idx.isValid() ) {
330 const QAbstractItemModel*
model = idx.model();
331 return model->index( idx.row(), model->columnCount( idx.parent() )-1,idx.parent() );
333 return QModelIndex();
359 void GraphicsScene::Private::recursiveUpdateMultiItem(
const Span& span,
const QModelIndex& idx )
365 item = q->createItem( static_cast<ItemType>( itemtype ) );
367 q->insertItem( idx, item);
372 while ( ( child = idx.child( cr, 0 ) ).isValid() ) {
373 recursiveUpdateMultiItem( span, child );
381 if ( !rowidx.isValid() )
return;
383 const QAbstractItemModel*
model = rowidx.model();
391 for ( QModelIndex treewalkidx = sidx; treewalkidx.isValid(); treewalkidx = treewalkidx.parent() ) {
398 bool blocked = blockSignals(
true );
408 if ( itemtype ==
TypeMulti && !isExpanded ) {
409 d->recursiveUpdateMultiItem( rg, idx );
417 item =
createItem( static_cast<ItemType>( itemtype ) );
425 blockSignals( blocked );
430 if ( !
d->constraintModel.isNull() ) {
435 QModelIndex other_idx;
439 if ( !other_item )
continue;
444 }
else if ( c.
endIndex() == sidx ) {
447 if ( !other_item )
continue;
457 d->items.insert( idx, item );
464 QHash<QPersistentModelIndex,GraphicsItem*>::iterator it =
d->items.find( idx );
465 if ( it !=
d->items.end() ) {
470 d->items.erase( it );
473 const QSet<ConstraintGraphicsItem*> clst = QSet<ConstraintGraphicsItem*>::fromList( item->
startConstraints() ) +
474 QSet<ConstraintGraphicsItem*>::fromList( item->
endConstraints() );
476 d->deleteConstraintItem( citem );
486 if ( !idx.isValid() )
return 0;
488 QHash<QPersistentModelIndex,GraphicsItem*>::const_iterator it =
d->items.find( idx );
489 return ( it !=
d->items.end() )?*it:0;
494 if ( !idx.isValid() )
return 0;
496 QHash<QPersistentModelIndex,GraphicsItem*>::const_iterator it =
d->items.find( idx );
497 return ( it !=
d->items.end() )?*it:0;
503 QHash<QPersistentModelIndex, GraphicsItem*>::const_iterator it =
d->items.constBegin();
504 for ( ; it !=
d->items.constEnd(); ++it ) {
512 for ( QHash<QPersistentModelIndex,GraphicsItem*>::iterator it =
d->items.begin();
513 it !=
d->items.end(); ++it ) {
515 const QPersistentModelIndex& idx = it.key();
518 invalidate( QRectF(), QGraphicsScene::BackgroundLayer );
524 if ( !idx.model() )
return;
525 const QModelIndex parent( idx.parent() );
526 const int colcount = idx.model()->columnCount( parent );
527 {
for (
int i = 0; i < colcount; ++i ) {
531 {
for (
int i = 0; i < rowcount; ++i ) {
539 return d->findConstraintItem( c );
550 d->createConstraintItem( c );
555 d->deleteConstraintItem( c );
558 void GraphicsScene::slotGridChanged()
567 #ifndef QT_NO_TOOLTIP 568 QGraphicsItem *item = itemAt( helpEvent->scenePos(), QTransform() );
569 if (
GraphicsItem* gitem = qgraphicsitem_cast<GraphicsItem*>( item ) ) {
570 QToolTip::showText(helpEvent->screenPos(), gitem->ganttToolTip());
572 QToolTip::showText(helpEvent->screenPos(), citem->
ganttToolTip());
574 QGraphicsScene::helpEvent( helpEvent );
581 QRectF scn( sceneRect() );
582 QRectF rect( _rect );
583 if (
d->isPrinting &&
d->drawColumnLabels ) {
584 QRectF headerRect( scn.topLeft()+QPointF(
d->labelsWidth, 0 ),
585 QSizeF( scn.width()-
d->labelsWidth,
d->rowController->headerHeight() ));
587 d->grid->paintHeader( painter, headerRect, rect, 0, 0 );
593 QRectF labelsTabRect( scn.topLeft(), QSizeF(
d->labelsWidth, headerRect.height() ) );
595 QStyleOptionHeader opt;
596 opt.rect = labelsTabRect.toRect();
597 opt.text = QLatin1String(
"");
598 opt.textAlignment = Qt::AlignCenter;
599 #if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0) 600 style()->drawControl(QStyle::CE_Header, &opt, painter, 0);
602 QApplication::style()->drawControl(QStyle::CE_Header, &opt, painter, 0);
606 scn.setTop( headerRect.bottom() );
607 scn.setLeft( headerRect.left() );
608 rect = rect.intersected( scn );
610 d->grid->paintGrid( painter, scn, rect,
d->rowController );
612 d->grid->drawBackground(painter, rect);
617 d->grid->drawForeground(painter, rect);
642 d->dragSource = item;
647 return d->dragSource;
662 Q_UNUSED( drawRowLabels );
663 Q_UNUSED( drawColumnLabels );
665 QPainter painter( printer );
666 doPrint( &painter, printer->pageRect(), sceneRect().left(), sceneRect().right(), printer, drawRowLabels, drawColumnLabels );
682 void GraphicsScene::print( QPrinter* printer, qreal start, qreal end,
bool drawRowLabels,
bool drawColumnLabels )
688 Q_UNUSED( drawRowLabels );
689 Q_UNUSED( drawColumnLabels );
691 QPainter painter( printer );
692 doPrint( &painter, printer->pageRect(), start, end, printer, drawRowLabels, drawColumnLabels );
702 void GraphicsScene::print( QPainter* painter,
const QRectF& _targetRect,
bool drawRowLabels,
bool drawColumnLabels )
704 QRectF targetRect( _targetRect );
705 if ( targetRect.isNull() ) {
706 targetRect = sceneRect();
709 doPrint( painter, targetRect, sceneRect().left(), sceneRect().right(), 0, drawRowLabels, drawColumnLabels );
723 const QRectF& _targetRect,
bool drawRowLabels,
bool drawColumnLabels )
725 QRectF targetRect( _targetRect );
726 if ( targetRect.isNull() ) {
727 targetRect = sceneRect();
730 doPrint( painter, targetRect, start, end, 0, drawRowLabels, drawColumnLabels );
735 void GraphicsScene::doPrint( QPainter* painter,
const QRectF& targetRect,
736 qreal start, qreal end,
737 QPrinter* printer,
bool drawRowLabels,
bool drawColumnLabels )
740 d->isPrinting =
true;
741 d->drawColumnLabels = drawColumnLabels;
742 d->labelsWidth = 0.0;
743 #if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0) 744 QFont sceneFont( font() );
747 sceneFont = QFont( font(), printer );
748 if ( font().pointSizeF() >= 0.0 )
749 sceneFont.setPointSizeF( font().pointSizeF() );
750 else if ( font().pointSize() >= 0 )
751 sceneFont.setPointSize( font().pointSize() );
753 sceneFont.setPixelSize( font().pixelSize() );
757 QFont sceneFont( painter->font() );
760 sceneFont = QFont( painter->font(), printer );
761 if ( painter->font().pointSizeF() >= 0.0 )
762 sceneFont.setPointSizeF( painter->font().pointSizeF() );
763 else if ( painter->font().pointSize() >= 0 )
764 sceneFont.setPointSize( painter->font().pointSize() );
766 sceneFont.setPixelSize( painter->font().pixelSize() );
771 QGraphicsTextItem dummyTextItem( QLatin1String(
"X") );
772 dummyTextItem.adjustSize();
773 QFontMetrics fm(dummyTextItem.font());
774 sceneFont.setPixelSize( fm.height() );
776 const QRectF oldScnRect( sceneRect() );
777 QRectF scnRect( oldScnRect );
778 scnRect.setLeft( start );
779 scnRect.setRight( end );
780 bool b = blockSignals(
true );
783 if (
d->drawColumnLabels ) {
784 QRectF headerRect( scnRect );
785 headerRect.setHeight( -
d->rowController->headerHeight() );
786 scnRect.setTop(scnRect.top() -
d->rowController->headerHeight());
791 if ( drawRowLabels ) {
792 qreal textWidth = 0.;
797 const QString txt = idx.data( Qt::DisplayRole ).toString();
798 QGraphicsTextItem* item =
new QGraphicsTextItem( txt );
802 textWidth = qMax( item->textWidth(), textWidth );
803 item->setPos( 0, rg.
start() );
804 }
while ( ( sidx =
rowController()->indexBelow( sidx ) ).isValid() );
806 textWidth += QFontMetricsF(sceneFont).width( QString::fromLatin1(
"X" ) );
807 Q_FOREACH( QGraphicsTextItem* item, textLabels ) {
808 item->setPos( scnRect.left()-textWidth, item->y() );
811 scnRect.setLeft( scnRect.left()-textWidth );
812 d->labelsWidth = textWidth;
815 setSceneRect( scnRect );
818 painter->setClipRect( targetRect );
820 qreal yratio = targetRect.height()/scnRect.height();
824 if ( !printer && targetRect.width()/scnRect.width() < yratio ) {
825 yratio = targetRect.width()/scnRect.width();
828 qreal offset = scnRect.left();
830 while ( offset < scnRect.right() ) {
831 painter->setFont( sceneFont );
832 render( painter, targetRect, QRectF( QPointF( offset, scnRect.top()),
833 QSizeF( targetRect.width()/yratio, scnRect.height() ) ) );
834 offset += targetRect.width()/yratio;
836 if ( printer && offset < scnRect.right() ) {
845 d->isPrinting =
false;
846 d->drawColumnLabels =
true;
847 d->labelsWidth = 0.0;
848 qDeleteAll( textLabels );
850 setSceneRect( oldScnRect );
854 #include "moc_kdganttgraphicsscene.cpp" 857 #ifndef KDAB_NO_UNIT_TESTS 860 #include <QGraphicsLineItem> 862 #include <QStandardItemModel> 868 static const int ROW_HEIGHT;
869 QPointer<QAbstractItemModel> m_model;
872 SceneTestRowController()
881 int headerHeight()
const override {
return 40; }
883 bool isRowVisible(
const QModelIndex& )
const override {
return true;}
884 bool isRowExpanded(
const QModelIndex& )
const override {
return false; }
885 KDGantt::Span rowGeometry(
const QModelIndex& idx )
const override 889 int maximumItemHeight()
const override {
892 int totalHeight()
const override {
893 return m_model->rowCount()* ROW_HEIGHT;
896 QModelIndex indexAt(
int height )
const override {
897 return m_model->index( height/ROW_HEIGHT, 0 );
900 QModelIndex indexBelow(
const QModelIndex& idx )
const override {
901 if ( !idx.isValid() )
return QModelIndex();
902 return idx.model()->index( idx.row()+1, idx.column(), idx.parent() );
904 QModelIndex indexAbove(
const QModelIndex& idx )
const override {
905 if ( !idx.isValid() )
return QModelIndex();
906 return idx.model()->index( idx.row()-1, idx.column(), idx.parent() );
911 class TestLineItem :
public QGraphicsLineItem
914 TestLineItem(
bool *destroyedFlag )
915 : QGraphicsLineItem( 0, 0, 10, 10 ),
916 m_destroyedFlag( destroyedFlag )
919 ~TestLineItem()
override 920 { *m_destroyedFlag =
true; }
923 bool *m_destroyedFlag;
926 const int SceneTestRowController::ROW_HEIGHT = 30;
929 QStandardItemModel
model;
931 QStandardItem* item =
new QStandardItem();
933 item->setData( QString::fromLatin1(
"Decide on new product" ) );
937 QStandardItem* item2 =
new QStandardItem();
939 item2->setData( QString::fromLatin1(
"Educate personnel" ) );
943 model.appendRow( item );
944 model.appendRow( item2 );
947 rowController.setModel( &model );
955 bool foreignItemDestroyed =
false;
956 TestLineItem *foreignItem =
new TestLineItem( &foreignItemDestroyed );
957 graphicsView.scene()->addItem( foreignItem );
QAbstractProxyModel * summaryHandlingModel() const
void setGrid(AbstractGrid *grid)
KDAB_SCOPED_UNITTEST_SIMPLE(KDGantt, GraphicsView,"test")
Proxy model that supports summary gantt items.
GraphicsItem * dragSource() const
Abstract baseclass for grids. A grid is used to convert between QModelIndex'es and gantt chart values...
void clicked(const QModelIndex &index)
void itemClicked(const QModelIndex &)
void updateItem(const Span &rowgeometry, const QPersistentModelIndex &idx)
void setConstraintModel(ConstraintModel *)
void qrealClicked(const QModelIndex &index)
ConstraintModel * constraintModel() const
void setModel(QAbstractItemModel *)
A class used to represent a dependency.
Class used to render gantt items in a KDGantt::GraphicsView.
void addStartConstraint(ConstraintGraphicsItem *)
GraphicsItem * findItem(const QModelIndex &) const
virtual Span rowGeometry(const QModelIndex &idx) const =0
virtual bool isRowExpanded(const QModelIndex &idx) const =0
void drawBackground(QPainter *painter, const QRectF &rect) override
void print(QPrinter *printer, bool drawRowLabels=true, bool drawColumnLabels=true)
void pressed(const QModelIndex &index)
QModelIndex rootIndex() const
GraphicsItem * createItem(ItemType type) const
static QModelIndex mainIndex(const QModelIndex &idx)
~GraphicsScene() override
const Constraint & constraint() const
QAbstractItemModel * model() const
void setRowController(AbstractRowController *)
A class representing a start point and a length.
Class only listed here to document inheritance of some KDChart classes.
The GraphicsView class provides a model/view implementation of a gantt chart.
void entered(const QModelIndex &index)
void itemDoubleClicked(const QModelIndex &)
void drawForeground(QPainter *painter, const QRectF &rect) override
void setSelectionModel(QItemSelectionModel *selectionmodel)
void setRowController(AbstractRowController *rc)
void setItemDelegate(ItemDelegate *)
QString ganttToolTip() const
AbstractRowController * rowController() const
QItemSelectionModel * selectionModel() const
void itemEntered(const QModelIndex &)
void setModel(QAbstractItemModel *)
void removeStartConstraint(ConstraintGraphicsItem *)
void deleteSubtree(const QModelIndex &)
ConstraintGraphicsItem * findConstraintItem(const Constraint &) const
void setSummaryHandlingModel(QAbstractProxyModel *)
void insertItem(const QPersistentModelIndex &, GraphicsItem *)
void setRootIndex(const QModelIndex &idx)
QModelIndex endIndex() const
QList< ConstraintGraphicsItem * > endConstraints() const
void helpEvent(QGraphicsSceneHelpEvent *helpEvent) override
void addEndConstraint(ConstraintGraphicsItem *)
static QModelIndex dataIndex(const QModelIndex &idx)
void setIndex(const QPersistentModelIndex &idx)
void removeItem(const QModelIndex &)
void updateRow(const QModelIndex &idx)
void setDragSource(GraphicsItem *item)
Class only listed here to document inheritance of some KDChart classes.
ItemDelegate * itemDelegate() const
AbstractGrid * grid() const
void clearConstraintItems()
QList< ConstraintGraphicsItem * > startConstraints() const
Abstract baseclass for row controllers. A row controller is used by the GraphicsView to nagivate the ...
bool compareIndexes(const Constraint &other) const
QModelIndex startIndex() const
void removeEndConstraint(ConstraintGraphicsItem *)
void itemPressed(const QModelIndex &)