24 #include "kdganttgraphicsscene_p.h"
30 #include "kdganttdatetimegrid.h"
33 #include <QApplication>
34 #include <QGraphicsSceneHelpEvent>
37 #include <QTextDocument>
67 grid( &default_grid ),
70 drawColumnLabels( true ),
75 default_grid.setStartDateTime( QDateTime::currentDateTime().addDays( -1 ) );
78 void GraphicsScene::Private::resetConstraintItems()
80 q->clearConstraintItems();
81 if ( constraintModel.isNull() )
return;
84 createConstraintItem( c );
89 void GraphicsScene::Private::createConstraintItem(
const Constraint& c )
94 if ( sitem && eitem ) {
116 item = items.value( summaryHandlingModel->mapFromSource( c.
endIndex() ), 0 );
123 void GraphicsScene::Private::deleteConstraintItem(
const Constraint& c )
125 deleteConstraintItem( findConstraintItem( c ) );
134 for ( ; it != clst.end() ; ++it ) {
138 if ( it != clst.end() ) {
142 item = items.value( summaryHandlingModel->mapFromSource( c.
endIndex() ), 0 );
146 for ( ; it != clst.end() ; ++it ) {
150 if ( it != clst.end() ) {
157 GraphicsScene::GraphicsScene(
QObject* parent )
166 qDeleteAll( items() );
172 void GraphicsScene::init()
174 setItemIndexMethod( QGraphicsScene::NoIndex );
176 connect(
d->grid, SIGNAL(
gridChanged() ),
this, SLOT( slotGridChanged() ) );
185 if ( !
d->itemDelegate.isNull() &&
d->itemDelegate->parent()==
this )
delete d->itemDelegate;
186 d->itemDelegate = delegate;
192 return d->itemDelegate;
197 assert(!
d->summaryHandlingModel.isNull());
198 return d->summaryHandlingModel->sourceModel();
203 assert(!
d->summaryHandlingModel.isNull());
204 d->summaryHandlingModel->setSourceModel(
model);
205 d->grid->setModel(
d->summaryHandlingModel );
211 return d->summaryHandlingModel;
216 proxyModel->setSourceModel(
model() );
217 d->summaryHandlingModel = proxyModel;
222 d->grid->setRootIndex( idx );
227 return d->grid->rootIndex();
232 return d->constraintModel;
237 if ( !
d->constraintModel.isNull() ) {
238 d->constraintModel->disconnect(
this );
240 d->constraintModel = cm;
246 d->resetConstraintItems();
251 d->selectionModel = smodel;
257 return d->selectionModel;
262 d->rowController = rc;
267 return d->rowController;
272 QAbstractItemModel*
model = 0;
273 if (
grid == 0 )
grid = &
d->default_grid;
275 d->grid->disconnect(
this );
279 connect(
d->grid, SIGNAL(
gridChanged() ),
this, SLOT( slotGridChanged() ) );
280 d->grid->setModel(
model );
307 if ( idx.isValid() ) {
308 return idx.model()->index( idx.row(), 0,idx.parent() );
310 return QModelIndex();
324 if ( idx.isValid() ) {
325 const QAbstractItemModel*
model = idx.model();
326 return model->index( idx.row(),
model->columnCount( idx.parent() )-1,idx.parent() );
328 return QModelIndex();
354 void GraphicsScene::Private::recursiveUpdateMultiItem(
const Span& span,
const QModelIndex& idx )
358 const int itemtype = summaryHandlingModel->data( idx,
ItemTypeRole ).toInt();
360 item = q->createItem(
static_cast<ItemType>( itemtype ) );
362 q->insertItem( idx, item);
367 while ( ( child = idx.child( cr, 0 ) ).isValid() ) {
368 recursiveUpdateMultiItem( span, child );
376 if ( !rowidx.isValid() )
return;
378 const QAbstractItemModel*
model = rowidx.model();
386 for ( QModelIndex treewalkidx = sidx; treewalkidx.isValid(); treewalkidx = treewalkidx.parent() ) {
393 bool blocked = blockSignals(
true );
403 if ( itemtype ==
TypeMulti && !isExpanded ) {
404 d->recursiveUpdateMultiItem( rg, idx );
420 blockSignals( blocked );
425 if ( !
d->constraintModel.isNull() ) {
430 QModelIndex other_idx;
434 if ( !other_item )
continue;
439 }
else if ( c.
endIndex() == sidx ) {
442 if ( !other_item )
continue;
452 d->items.insert( idx, item );
459 QHash<QPersistentModelIndex,GraphicsItem*>::iterator it =
d->items.find( idx );
460 if ( it !=
d->items.end() ) {
465 d->items.erase( it );
468 const QSet<ConstraintGraphicsItem*> clst = QSet<ConstraintGraphicsItem*>::fromList( item->
startConstraints() ) +
469 QSet<ConstraintGraphicsItem*>::fromList( item->
endConstraints() );
471 d->deleteConstraintItem( citem );
481 if ( !idx.isValid() )
return 0;
483 QHash<QPersistentModelIndex,GraphicsItem*>::const_iterator it =
d->items.find( idx );
484 return ( it !=
d->items.end() )?*it:0;
489 if ( !idx.isValid() )
return 0;
491 QHash<QPersistentModelIndex,GraphicsItem*>::const_iterator it =
d->items.find( idx );
492 return ( it !=
d->items.end() )?*it:0;
498 QHash<QPersistentModelIndex, GraphicsItem*>::const_iterator it =
d->items.constBegin();
499 for ( ; it !=
d->items.constEnd(); ++it ) {
507 for ( QHash<QPersistentModelIndex,GraphicsItem*>::iterator it =
d->items.begin();
508 it !=
d->items.end(); ++it ) {
510 const QPersistentModelIndex& idx = it.key();
513 invalidate( QRectF(), QGraphicsScene::BackgroundLayer );
519 if ( !idx.model() )
return;
520 const QModelIndex parent( idx.parent() );
521 const int colcount = idx.model()->columnCount( parent );
522 {
for (
int i = 0; i < colcount; ++i ) {
526 {
for (
int i = 0; i < rowcount; ++i ) {
534 return d->findConstraintItem( c );
545 d->createConstraintItem( c );
550 d->deleteConstraintItem( c );
553 void GraphicsScene::slotGridChanged()
562 #ifndef QT_NO_TOOLTIP
564 if (
GraphicsItem* gitem = qgraphicsitem_cast<GraphicsItem*>( item ) ) {
565 QToolTip::showText(
helpEvent->screenPos(), gitem->ganttToolTip());
576 QRectF scn( sceneRect() );
577 QRectF rect( _rect );
578 if (
d->isPrinting &&
d->drawColumnLabels ) {
579 QRectF headerRect( scn.topLeft()+QPointF(
d->labelsWidth, 0 ),
580 QSizeF( scn.width()-
d->labelsWidth,
d->rowController->headerHeight() ));
582 d->grid->paintHeader( painter, headerRect, rect, 0, 0 );
588 QRectF labelsTabRect( scn.topLeft(), QSizeF(
d->labelsWidth, headerRect.height() ) );
590 QStyleOptionHeader opt;
591 opt.rect = labelsTabRect.toRect();
592 opt.text = QLatin1String(
"");
593 opt.textAlignment = Qt::AlignCenter;
594 style()->drawControl(QStyle::CE_Header, &opt, painter, 0);
597 scn.setTop( headerRect.bottom() );
598 scn.setLeft( headerRect.left() );
599 rect = rect.intersected( scn );
601 d->grid->paintGrid( painter, scn, rect,
d->rowController );
603 d->grid->drawBackground(painter, rect);
608 d->grid->drawForeground(painter, rect);
633 d->dragSource = item;
638 return d->dragSource;
653 Q_UNUSED( drawRowLabels );
654 Q_UNUSED( drawColumnLabels );
656 QPainter painter( printer );
657 doPrint( &painter, printer->pageRect(), sceneRect().left(), sceneRect().right(), printer, drawRowLabels, drawColumnLabels );
673 void GraphicsScene::print( QPrinter* printer, qreal start, qreal end,
bool drawRowLabels,
bool drawColumnLabels )
679 Q_UNUSED( drawRowLabels );
680 Q_UNUSED( drawColumnLabels );
682 QPainter painter( printer );
683 doPrint( &painter, printer->pageRect(), start, end, printer, drawRowLabels, drawColumnLabels );
693 void GraphicsScene::print( QPainter* painter,
const QRectF& _targetRect,
bool drawRowLabels,
bool drawColumnLabels )
695 QRectF targetRect( _targetRect );
696 if ( targetRect.isNull() ) {
697 targetRect = sceneRect();
700 doPrint( painter, targetRect, sceneRect().left(), sceneRect().right(), 0, drawRowLabels, drawColumnLabels );
714 const QRectF& _targetRect,
bool drawRowLabels,
bool drawColumnLabels )
716 QRectF targetRect( _targetRect );
717 if ( targetRect.isNull() ) {
718 targetRect = sceneRect();
721 doPrint( painter, targetRect, start, end, 0, drawRowLabels, drawColumnLabels );
726 void GraphicsScene::doPrint( QPainter* painter,
const QRectF& targetRect,
727 qreal start, qreal end,
728 QPrinter* printer,
bool drawRowLabels,
bool drawColumnLabels )
731 d->isPrinting =
true;
732 d->drawColumnLabels = drawColumnLabels;
733 d->labelsWidth = 0.0;
734 QFont sceneFont( font() );
737 sceneFont = QFont( font(), printer );
738 if ( font().pointSizeF() >= 0.0 )
739 sceneFont.setPointSizeF( font().pointSizeF() );
740 else if ( font().pointSize() >= 0 )
741 sceneFont.setPointSize( font().pointSize() );
743 sceneFont.setPixelSize( font().pixelSize() );
747 QGraphicsTextItem dummyTextItem( QLatin1String(
"X") );
748 dummyTextItem.adjustSize();
749 QFontMetrics fm(dummyTextItem.font());
750 sceneFont.setPixelSize( fm.height() );
752 const QRectF oldScnRect( sceneRect() );
753 QRectF scnRect( oldScnRect );
754 scnRect.setLeft( start );
755 scnRect.setRight( end );
756 bool b = blockSignals(
true );
759 if (
d->drawColumnLabels ) {
760 QRectF headerRect( scnRect );
761 headerRect.setHeight( -
d->rowController->headerHeight() );
762 scnRect.setTop(scnRect.top() -
d->rowController->headerHeight());
767 if ( drawRowLabels ) {
768 qreal textWidth = 0.;
773 const QString txt = idx.data( Qt::DisplayRole ).toString();
774 QGraphicsTextItem* item =
new QGraphicsTextItem( txt );
778 textWidth = qMax( item->textWidth(), textWidth );
779 item->setPos( 0, rg.
start() );
780 }
while ( ( sidx =
rowController()->indexBelow( sidx ) ).isValid() );
782 textWidth += QFontMetricsF(sceneFont).width( QString::fromLatin1(
"X" ) );
783 Q_FOREACH( QGraphicsTextItem* item, textLabels ) {
784 item->setPos( scnRect.left()-textWidth, item->y() );
787 scnRect.setLeft( scnRect.left()-textWidth );
788 d->labelsWidth = textWidth;
791 setSceneRect( scnRect );
794 painter->setClipRect( targetRect );
796 qreal yratio = targetRect.height()/scnRect.height();
800 if ( !printer && targetRect.width()/scnRect.width() < yratio ) {
801 yratio = targetRect.width()/scnRect.width();
804 qreal offset = scnRect.left();
806 while ( offset < scnRect.right() ) {
807 painter->setFont( sceneFont );
808 render( painter, targetRect, QRectF( QPointF( offset, scnRect.top()),
809 QSizeF( targetRect.width()/yratio, scnRect.height() ) ) );
810 offset += targetRect.width()/yratio;
812 if ( printer && offset < scnRect.right() ) {
821 d->isPrinting =
false;
822 d->drawColumnLabels =
true;
823 d->labelsWidth = 0.0;
824 qDeleteAll( textLabels );
826 setSceneRect( oldScnRect );
830 #include "moc_kdganttgraphicsscene.cpp"
833 #ifndef KDAB_NO_UNIT_TESTS
836 #include <QGraphicsLineItem>
838 #include <QStandardItemModel>
844 static const int ROW_HEIGHT;
845 QPointer<QAbstractItemModel> m_model;
848 SceneTestRowController()
852 void setModel( QAbstractItemModel* model )
857 int headerHeight()
const override {
return 40; }
859 bool isRowVisible(
const QModelIndex& )
const override {
return true;}
860 bool isRowExpanded(
const QModelIndex& )
const override {
return false; }
861 KDGantt::Span rowGeometry(
const QModelIndex& idx )
const override
865 int maximumItemHeight()
const override {
868 int totalHeight()
const override {
869 return m_model->rowCount()* ROW_HEIGHT;
872 QModelIndex indexAt(
int height )
const override {
873 return m_model->index( height/ROW_HEIGHT, 0 );
876 QModelIndex indexBelow(
const QModelIndex& idx )
const override {
877 if ( !idx.isValid() )
return QModelIndex();
878 return idx.model()->index( idx.row()+1, idx.column(), idx.parent() );
880 QModelIndex indexAbove(
const QModelIndex& idx )
const override {
881 if ( !idx.isValid() )
return QModelIndex();
882 return idx.model()->index( idx.row()-1, idx.column(), idx.parent() );
887 class TestLineItem :
public QGraphicsLineItem
890 TestLineItem(
bool *destroyedFlag )
891 : QGraphicsLineItem( 0, 0, 10, 10 ),
892 m_destroyedFlag( destroyedFlag )
895 ~TestLineItem()
override
896 { *m_destroyedFlag =
true; }
899 bool *m_destroyedFlag;
902 const int SceneTestRowController::ROW_HEIGHT = 30;
905 QStandardItemModel model;
907 QStandardItem* item =
new QStandardItem();
909 item->setData( QString::fromLatin1(
"Decide on new product" ) );
913 QStandardItem* item2 =
new QStandardItem();
915 item2->setData( QString::fromLatin1(
"Educate personnel" ) );
919 model.appendRow( item );
920 model.appendRow( item2 );
922 SceneTestRowController rowController;
923 rowController.setModel( &model );
931 bool foreignItemDestroyed =
false;
932 TestLineItem *foreignItem =
new TestLineItem( &foreignItemDestroyed );
933 graphicsView.scene()->addItem( foreignItem );