KD Chart 2  [rev.2.7]
kdganttgraphicsview.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 ** Copyright (C) 2001-2020 Klaralvdalens Datakonsult AB. All rights reserved.
3 **
4 ** This file is part of the KD Chart library.
5 **
6 ** Licensees holding valid commercial KD Chart licenses may use this file in
7 ** accordance with the KD Chart Commercial License Agreement provided with
8 ** the Software.
9 **
10 **
11 ** This file may be distributed and/or modified under the terms of the
12 ** GNU General Public License version 2 and version 3 as published by the
13 ** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
14 **
15 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 **
18 ** Contact info@kdab.com if any conditions of this licensing are not
19 ** clear to you.
20 **
21 **********************************************************************/
22 
23 #include "kdganttgraphicsview.h"
24 #include "kdganttgraphicsview_p.h"
26 #include "kdganttgraphicsitem.h"
27 #include "kdganttconstraintmodel.h"
28 
29 #include <QMenu>
30 #include <QPainter>
31 #include <QPaintEvent>
32 #include <QResizeEvent>
33 #include <QScrollBar>
34 #include <QAbstractProxyModel>
35 #include <QPrinter>
36 
37 #include <cassert>
38 
39 #if defined KDAB_EVAL
40 #include "../evaldialog/evaldialog.h"
41 #endif
42 
47 using namespace KDGantt;
48 
49 HeaderWidget::HeaderWidget( GraphicsView* parent )
50  : QWidget( parent ), m_offset( 0. )
51 {
52  assert( parent ); // Parent must be set
53 }
54 
55 HeaderWidget::~HeaderWidget()
56 {
57 }
58 
59 void HeaderWidget::scrollTo( int v )
60 {
61  m_offset = v;
62  // QWidget::scroll() wont work properly for me on Mac
63  //scroll( static_cast<int>( old-v ), 0 );
64  update();
65 }
66 
67 void HeaderWidget::paintEvent( QPaintEvent* ev )
68 {
69  QPainter p( this );
70  view()->grid()->paintHeader( &p, rect(), ev->rect(), m_offset, this );
71 }
72 
73 bool HeaderWidget::event( QEvent* event )
74 {
75  if ( event->type() == QEvent::ToolTip ) {
76  DateTimeGrid* const grid = qobject_cast< DateTimeGrid* >( view()->grid() );
77  if ( grid ) {
78  QHelpEvent *e = static_cast<QHelpEvent*>( event );
79  QDateTime dt = grid->mapFromChart( view()->mapToScene( e->x(), 0 ).x() ).toDateTime();
80  setToolTip( dt.toString() );
81  }
82  }
83  return QWidget::event( event );
84 }
85 
86 void HeaderWidget::contextMenuEvent( QContextMenuEvent* event )
87 {
88  QMenu contextMenu;
89 
90  DateTimeGrid* const grid = qobject_cast< DateTimeGrid* >( view()->grid() );
91  QAction* actionScaleAuto = 0;
92  QAction* actionScaleMonth = 0;
93  QAction* actionScaleWeek = 0;
94  QAction* actionScaleDay = 0;
95  QAction* actionScaleHour = 0;
96  QAction* actionZoomIn = 0;
97  QAction* actionZoomOut = 0;
98  if ( grid != 0 )
99  {
100  QMenu* menuScale = new QMenu( tr( "Scale" ), &contextMenu );
101  QActionGroup* scaleGroup = new QActionGroup( &contextMenu );
102  scaleGroup->setExclusive( true );
103 
104  actionScaleAuto = new QAction( tr( "Auto" ), menuScale );
105  actionScaleAuto->setCheckable( true );
106  actionScaleAuto->setChecked( grid->scale() == DateTimeGrid::ScaleAuto );
107  actionScaleMonth = new QAction( tr( "Month" ), menuScale );
108  actionScaleMonth->setCheckable( true );
109  actionScaleMonth->setChecked( grid->scale() == DateTimeGrid::ScaleMonth );
110  actionScaleWeek = new QAction( tr( "Week" ), menuScale );
111  actionScaleWeek->setCheckable( true );
112  actionScaleWeek->setChecked( grid->scale() == DateTimeGrid::ScaleWeek );
113  actionScaleDay = new QAction( tr( "Day" ), menuScale );
114  actionScaleDay->setCheckable( true );
115  actionScaleDay->setChecked( grid->scale() == DateTimeGrid::ScaleDay );
116  actionScaleHour = new QAction( tr( "Hour" ), menuScale );
117  actionScaleHour->setCheckable( true );
118  actionScaleHour->setChecked( grid->scale() == DateTimeGrid::ScaleHour );
119 
120  scaleGroup->addAction( actionScaleAuto );
121  menuScale->addAction( actionScaleAuto );
122 
123  scaleGroup->addAction( actionScaleMonth );
124  menuScale->addAction( actionScaleMonth );
125 
126  scaleGroup->addAction( actionScaleWeek );
127  menuScale->addAction( actionScaleWeek );
128 
129  scaleGroup->addAction( actionScaleDay );
130  menuScale->addAction( actionScaleDay );
131 
132  scaleGroup->addAction( actionScaleHour );
133  menuScale->addAction( actionScaleHour );
134 
135  contextMenu.addMenu( menuScale );
136 
137  contextMenu.addSeparator();
138 
139  actionZoomIn = new QAction( tr( "Zoom In" ), &contextMenu );
140  contextMenu.addAction( actionZoomIn );
141  actionZoomOut = new QAction( tr( "Zoom Out" ), &contextMenu );
142  contextMenu.addAction( actionZoomOut );
143  }
144 
145  if ( contextMenu.isEmpty() )
146  {
147  event->ignore();
148  return;
149  }
150 
151  const QAction* const action = contextMenu.exec( event->globalPos() );
152  if ( action == 0 ) {}
153  else if ( action == actionScaleAuto )
154  {
155  assert( grid != 0 );
157  }
158  else if ( action == actionScaleMonth )
159  {
160  assert( grid != 0 );
162  }
163  else if ( action == actionScaleWeek )
164  {
165  assert( grid != 0 );
167  }
168  else if ( action == actionScaleDay )
169  {
170  assert( grid != 0 );
172  }
173  else if ( action == actionScaleHour )
174  {
175  assert( grid != 0 );
177  }
178  else if ( action == actionZoomIn )
179  {
180  assert( grid != 0 );
181  grid->setDayWidth( qMax(0.1, grid->dayWidth() + grid->dayWidth() * 0.2) );
182  }
183  else if ( action == actionZoomOut )
184  {
185  assert( grid != 0 );
186  grid->setDayWidth( qMax(0.1, grid->dayWidth() - grid->dayWidth() * 0.2) );
187  }
188 
189  event->accept();
190 }
191 
192 GraphicsView::Private::Private( GraphicsView* _q )
193  : q( _q ), rowcontroller(0), headerwidget( _q )
194 {
195 }
196 
197 void GraphicsView::Private::updateHeaderGeometry()
198 {
199  q->setViewportMargins(0,rowcontroller->headerHeight(),0,0);
200  headerwidget.setGeometry( q->viewport()->x(),
201  q->viewport()->y() - rowcontroller->headerHeight(),
202  q->viewport()->width(),
203  rowcontroller->headerHeight() );
204 }
205 
206 void GraphicsView::Private::slotGridChanged()
207 {
208  updateHeaderGeometry();
209  headerwidget.update();
210  q->updateSceneRect();
211  q->update();
212 }
213 
214 void GraphicsView::Private::slotHorizontalScrollValueChanged( int val )
215 {
216 #if QT_VERSION >= 0x040300
217  const QRectF viewRect = q->transform().mapRect( q->sceneRect() );
218 #else
219  const QRectF viewRect = q->sceneRect();
220 #endif
221  headerwidget.scrollTo( val-q->horizontalScrollBar()->minimum()+static_cast<int>( viewRect.left() ) );
222 }
223 
224 void GraphicsView::Private::slotColumnsInserted( const QModelIndex& parent, int start, int end )
225 {
226  Q_UNUSED( start );
227  Q_UNUSED( end );
228  QModelIndex idx = scene.model()->index( 0, 0, scene.summaryHandlingModel()->mapToSource( parent ) );
229  do {
230  scene.updateRow( scene.summaryHandlingModel()->mapFromSource( idx ) );
231  } while ( ( idx = rowcontroller->indexBelow( idx ) ) != QModelIndex() && rowcontroller->isRowVisible( idx ) );
232  //} while ( ( idx = d->treeview.indexBelow( idx ) ) != QModelIndex() && d->treeview.visualRect(idx).isValid() );
233  q->updateSceneRect();
234 }
235 
236 void GraphicsView::Private::slotColumnsRemoved( const QModelIndex& parent, int start, int end )
237 {
238  // TODO
239  Q_UNUSED( start );
240  Q_UNUSED( end );
241  Q_UNUSED( parent );
242  q->updateScene();
243 }
244 
245 void GraphicsView::Private::slotDataChanged( const QModelIndex& topLeft, const QModelIndex& bottomRight )
246 {
247  //qDebug() << "GraphicsView::slotDataChanged("<<topLeft<<bottomRight<<")";
248  const QModelIndex parent = topLeft.parent();
249  for ( int row = topLeft.row(); row <= bottomRight.row(); ++row ) {
250  scene.updateRow( scene.summaryHandlingModel()->index( row, 0, parent ) );
251  }
252 }
253 
254 void GraphicsView::Private::slotLayoutChanged()
255 {
256  //qDebug() << "slotLayoutChanged()";
257  q->updateScene();
258 }
259 
260 void GraphicsView::Private::slotModelReset()
261 {
262  //qDebug() << "slotModelReset()";
263  q->updateScene();
264 }
265 
266 void GraphicsView::Private::slotRowsInserted( const QModelIndex& parent, int start, int end )
267 {
268  Q_UNUSED( parent );
269  Q_UNUSED( start );
270  Q_UNUSED( end );
271  q->updateScene(); // TODO: This might be optimised
272 }
273 
274 void GraphicsView::Private::slotRowsAboutToBeRemoved( const QModelIndex& parent, int start, int end )
275 {
276  //qDebug() << "GraphicsView::Private::slotRowsAboutToBeRemoved("<<parent<<start<<end<<")";
277  for ( int row = start; row <= end; ++row ) {
278  for ( int col = 0; col < scene.summaryHandlingModel()->columnCount( parent ); ++col ) {
279  //qDebug() << "removing "<<scene.summaryHandlingModel()->index( row, col, parent );
280  scene.removeItem( scene.summaryHandlingModel()->index( row, col, parent ) );
281  }
282  }
283 }
284 
285 void GraphicsView::Private::slotRowsRemoved( const QModelIndex& parent, int start, int end )
286 {
287  //qDebug() << "GraphicsView::Private::slotRowsRemoved("<<parent<<start<<end<<")";
288  // TODO
289  Q_UNUSED( parent );
290  Q_UNUSED( start );
291  Q_UNUSED( end );
292 
293  q->updateScene();
294 }
295 
296 void GraphicsView::Private::slotItemClicked( const QModelIndex& idx )
297 {
298  QModelIndex sidx = idx;//scene.summaryHandlingModel()->mapToSource( idx );
299  emit q->clicked( sidx );
300  if (q->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, 0, q))
301  emit q->activated( sidx );
302 }
303 
304 void GraphicsView::Private::slotItemDoubleClicked( const QModelIndex& idx )
305 {
306  QModelIndex sidx = idx;//scene.summaryHandlingModel()->mapToSource( idx );
307  emit q->qrealClicked( sidx );
308  if (!q->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, 0, q))
309  emit q->activated( sidx );
310 }
311 
312 void GraphicsView::Private::slotHeaderContextMenuRequested( const QPoint& pt )
313 {
314  emit q->headerContextMenuRequested( headerwidget.mapToGlobal( pt ) );
315 }
316 
339  : QGraphicsView( parent ), _d( new Private( this ) )
340 {
341 
342 #if defined KDAB_EVAL
343  EvalDialog::checkEvalLicense( "KD Gantt" );
344 #endif
345  connect( horizontalScrollBar(), SIGNAL( valueChanged( int ) ),
346  this, SLOT( slotHorizontalScrollValueChanged( int ) ) );
347  connect( &_d->scene, SIGNAL( gridChanged() ),
348  this, SLOT( slotGridChanged() ) );
349  connect( &_d->scene, SIGNAL( entered( const QModelIndex& ) ),
350  this, SIGNAL( entered( const QModelIndex& ) ) );
351  connect( &_d->scene, SIGNAL( pressed( const QModelIndex& ) ),
352  this, SIGNAL( pressed( const QModelIndex& ) ) );
353  connect( &_d->scene, SIGNAL( clicked( const QModelIndex& ) ),
354  this, SLOT( slotItemClicked( const QModelIndex& ) ) );
355  connect( &_d->scene, SIGNAL( qrealClicked( const QModelIndex& ) ),
356  this, SLOT( slotItemDoubleClicked( const QModelIndex& ) ) );
357  connect( &_d->scene, SIGNAL( sceneRectChanged( const QRectF& ) ),
358  this, SLOT( updateSceneRect() ) );
359  connect( &_d->headerwidget, SIGNAL( customContextMenuRequested( const QPoint& ) ),
360  this, SLOT( slotHeaderContextMenuRequested( const QPoint& ) ) );
361  setScene( &_d->scene );
362 
363  // HACK!
364  setSummaryHandlingModel( _d->scene.summaryHandlingModel() );
365 
366  // So that AbstractGrid::drawBackground() and AbstractGrid::drawForeground()
367  // works properly
368  setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
369 
370  //setCacheMode( CacheBackground );
371 }
372 
375 {
376  delete _d;
377 }
378 
379 #define d d_func()
380 
394 void GraphicsView::setModel( QAbstractItemModel* model )
395 {
396  if ( d->scene.model() ) {
397  disconnect( d->scene.model() );
398  }
399 
400  d->scene.setModel( model );
401  connect( model, SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ),
402  this, SLOT( updateSceneRect() ) );
403  updateScene();
404 }
405 
408 QAbstractItemModel* GraphicsView::model() const
409 {
410  return d->scene.model();
411 }
412 
414 {
415  disconnect( d->scene.summaryHandlingModel() );
416  d->scene.setSummaryHandlingModel( proxyModel );
417 
418  /* Connections. We have to rely on the treeview
419  * to receive the signals before we do(!)
420  */
421  connect( proxyModel, SIGNAL( columnsInserted( const QModelIndex&, int, int ) ),
422  this, SLOT( slotColumnsInserted( const QModelIndex&, int, int ) ) );
423  connect( proxyModel, SIGNAL( columnsRemoved( const QModelIndex&, int, int ) ),
424  this, SLOT( slotColumnsRemoved( const QModelIndex&, int, int ) ) );
425  connect( proxyModel, SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ),
426  this, SLOT( slotDataChanged( const QModelIndex&, const QModelIndex& ) ) );
427  connect( proxyModel, SIGNAL( layoutChanged() ),
428  this, SLOT( slotLayoutChanged() ) );
429  connect( proxyModel, SIGNAL( modelReset() ),
430  this, SLOT( slotModelReset() ) );
431  connect( proxyModel, SIGNAL( rowsInserted( const QModelIndex&, int, int ) ),
432  this, SLOT( slotRowsInserted( const QModelIndex&, int, int ) ) );
433  connect( proxyModel, SIGNAL( rowsAboutToBeRemoved( const QModelIndex&, int, int ) ),
434  this, SLOT( slotRowsAboutToBeRemoved( const QModelIndex&, int, int ) ) );
435  connect( proxyModel, SIGNAL( rowsRemoved( const QModelIndex&, int, int ) ),
436  this, SLOT( slotRowsRemoved( const QModelIndex&, int, int ) ) );
437 
438  updateScene();
439 }
440 
445 {
446  d->scene.setConstraintModel( cmodel );
447 }
448 
452 {
453  return d->scene.constraintModel();
454 }
455 
459 {
460  return d->scene.summaryHandlingModel();
461 }
462 
466 void GraphicsView::setRootIndex( const QModelIndex& idx )
467 {
468  d->scene.setRootIndex( idx );
469 }
470 
473 QModelIndex GraphicsView::rootIndex() const
474 {
475  return d->scene.rootIndex();
476 }
477 
481 void GraphicsView::setSelectionModel( QItemSelectionModel* model )
482 {
483  d->scene.setSelectionModel( model );
484 }
485 
488 QItemSelectionModel* GraphicsView::selectionModel() const
489 {
490  return d->scene.selectionModel();
491 }
492 
497 {
498  d->scene.setItemDelegate( delegate );
499 }
500 
504 {
505  return d->scene.itemDelegate();
506 }
507 
514 {
515  d->rowcontroller = rowcontroller;
516  d->scene.setRowController( rowcontroller );
517  updateScene();
518 }
519 
524 {
525  return d->rowcontroller;
526 }
527 
534 {
535  d->scene.setGrid( grid );
536  d->slotGridChanged();
537 }
538 
542 {
543  return d->scene.grid();
544 }
545 
550 {
551  d->scene.setReadOnly( ro );
552 }
553 
557 {
558  return d->scene.isReadOnly();
559 }
560 
570 void GraphicsView::setHeaderContextMenuPolicy( Qt::ContextMenuPolicy p )
571 {
572  d->headerwidget.setContextMenuPolicy( p );
573 }
574 
577 Qt::ContextMenuPolicy GraphicsView::headerContextMenuPolicy() const
578 {
579  return d->headerwidget.contextMenuPolicy();
580 }
581 
590 void GraphicsView::addConstraint( const QModelIndex& from,
591  const QModelIndex& to,
592  Qt::KeyboardModifiers modifiers )
593 {
594  if ( isReadOnly() ) return;
595  ConstraintModel* cmodel = constraintModel();
596  assert( cmodel );
597  Constraint c( from, to, ( modifiers&Qt::ShiftModifier )?Constraint::TypeHard:Constraint::TypeSoft );
598  if ( cmodel->hasConstraint( c ) ) cmodel->removeConstraint( c );
599  else cmodel->addConstraint( c );
600 }
601 
602 void GraphicsView::resizeEvent( QResizeEvent* ev )
603 {
604  d->updateHeaderGeometry();
605  QRectF r = scene()->itemsBoundingRect();
606  // To scroll more to the left than the actual item start, bug #4516
607  r.setLeft( qMin<qreal>( 0.0, r.left() ) );
608  // TODO: take scrollbars into account (if not always on)
609  // The scene should be at least the size of the viewport
610  QSizeF size = viewport()->size();
611  //TODO: why -2 below? size should be ex. frames etc?
612  if ( size.width() > r.width() ) {
613  r.setWidth( size.width() - 2 );
614  }
615  if ( size.height() > r.height() ) {
616  r.setHeight( size.height() - 2 );
617  }
618  const int totalh = rowController()->totalHeight();
619  if ( r.height() < totalh ) {
620  r.setHeight( totalh );
621  }
622 
623  scene()->setSceneRect( r );
624 
625  QGraphicsView::resizeEvent( ev );
626 }
627 
634 QModelIndex GraphicsView::indexAt( const QPoint& pos ) const
635 {
636  QGraphicsItem* item = itemAt( pos );
637  if ( GraphicsItem* gitem = qgraphicsitem_cast<GraphicsItem*>( item ) ) {
638  return d->scene.summaryHandlingModel()->mapToSource( gitem->index() );
639  } else {
640  return QModelIndex();
641  }
642 }
643 
646 {
647  d->scene.clearItems();
648 }
649 
651 void GraphicsView::updateRow( const QModelIndex& idx )
652 {
653  d->scene.updateRow( d->scene.summaryHandlingModel()->mapFromSource( idx ) );
654 }
655 
660 {
661  /* What to do with this? We need to shrink the view to
662  * make collapsing items work
663  */
664  qreal range = horizontalScrollBar()->maximum()-horizontalScrollBar()->minimum();
665  const qreal hscroll = horizontalScrollBar()->value()/( range>0?range:1 );
666  QRectF r = d->scene.itemsBoundingRect();
667  // To scroll more to the left than the actual item start, bug #4516
668  r.setTop( 0. );
669  r.setLeft( qMin<qreal>( 0.0, r.left() ) );
670  r.setSize( r.size().expandedTo( viewport()->size() ) );
671  const int totalh = rowController()->totalHeight();
672  if ( r.height() < totalh ) r.setHeight( totalh );
673  d->scene.setSceneRect( r );
674 
675  /* set scrollbar to keep the same time in view */
676  range = horizontalScrollBar()->maximum()-horizontalScrollBar()->minimum();
677  if ( range>0 ) horizontalScrollBar()->setValue( qRound( hscroll*range ) );
678 
679  /* We have to update here to adjust for any rows with no
680  * information because they are painted with a different
681  * background brush
682  */
683  d->scene.invalidate( QRectF(), QGraphicsScene::BackgroundLayer );
684 }
685 
690 {
691  clearItems();
692  if ( !model()) return;
693  if ( !rowController()) return;
694  QModelIndex idx = model()->index( 0, 0, rootIndex() );
695  do {
696  updateRow( idx );
697  } while ( ( idx = rowController()->indexBelow( idx ) ) != QModelIndex() && rowController()->isRowVisible(idx) );
698  //constraintModel()->cleanup();
699  //qDebug() << constraintModel();
700  updateSceneRect();
701  if ( scene() ) scene()->invalidate( QRectF(), QGraphicsScene::BackgroundLayer );
702 }
703 
705 GraphicsItem* GraphicsView::createItem( ItemType type ) const
706 {
707  return d->scene.createItem( type );
708 }
709 
711 void GraphicsView::deleteSubtree( const QModelIndex& idx )
712 {
713  d->scene.deleteSubtree( d->scene.summaryHandlingModel()->mapFromSource( idx ) );
714 }
715 
724 void GraphicsView::print( QPrinter* printer, bool drawRowLabels, bool drawColumnLabels )
725 {
726  d->scene.print( printer, drawRowLabels, drawColumnLabels );
727 }
728 
741 void GraphicsView::print( QPrinter* printer, qreal start, qreal end, bool drawRowLabels, bool drawColumnLabels )
742 {
743  d->scene.print( printer, start, end, drawRowLabels, drawColumnLabels );
744 }
745 
752 void GraphicsView::print( QPainter* painter, const QRectF& targetRect, bool drawRowLabels, bool drawColumnLabels )
753 {
754  d->scene.print(painter, targetRect, drawRowLabels, drawColumnLabels);
755 }
756 
767 void GraphicsView::print( QPainter* painter, qreal start, qreal end,
768  const QRectF& targetRect, bool drawRowLabels, bool drawColumnLabels )
769 {
770  d->scene.print(painter, start, end, targetRect, drawRowLabels, drawColumnLabels);
771 }
772 
773 
774 #include "moc_kdganttgraphicsview.cpp"
QAbstractProxyModel * summaryHandlingModel() const
void setConstraintModel(ConstraintModel *)
QModelIndex rootIndex() const
virtual void addConstraint(const QModelIndex &from, const QModelIndex &to, Qt::KeyboardModifiers modifiers)
bool hasConstraint(const Constraint &c) const
virtual int totalHeight() const =0
Abstract baseclass for grids. A grid is used to convert between QModelIndex&#39;es and gantt chart values...
void setItemDelegate(ItemDelegate *delegate)
GraphicsView(QWidget *parent=0)
AbstractRowController * rowController() const
void deleteSubtree(const QModelIndex &)
void setModel(QAbstractItemModel *)
void print(QPrinter *printer, bool drawRowLabels=true, bool drawColumnLabels=true)
A class used to represent a dependency.
void qrealClicked(const QModelIndex &index)
Class used to render gantt items in a KDGantt::GraphicsView.
virtual bool removeConstraint(const Constraint &c)
virtual void addConstraint(const Constraint &c)
Subclassing ConstraintModel and overriding addConstraint() and removeConstraint() can provide re-entr...
void setGrid(AbstractGrid *)
bool mapFromChart(const Span &span, const QModelIndex &idx, const QList< Constraint > &constraints=QList< Constraint >()) const override
void setRowController(AbstractRowController *)
ItemDelegate * itemDelegate() const
Class only listed here to document inheritance of some KDChart classes.
Qt::ContextMenuPolicy headerContextMenuPolicy() const
The GraphicsView class provides a model/view implementation of a gantt chart.
void setRootIndex(const QModelIndex &)
AbstractGrid * grid() const
void updateRow(const QModelIndex &)
void entered(const QModelIndex &index)
QItemSelectionModel * selectionModel() const
void setHeaderContextMenuPolicy(Qt::ContextMenuPolicy)
void clicked(const QModelIndex &index)
void setSummaryHandlingModel(QAbstractProxyModel *model)
void setSelectionModel(QItemSelectionModel *)
QAbstractItemModel * model() const
ConstraintModel * constraintModel() const
AbstractGrid * grid() const
#define d
QModelIndex indexAt(const QPoint &pos) const
Class only listed here to document inheritance of some KDChart classes.
void resizeEvent(QResizeEvent *) override
Abstract baseclass for row controllers. A row controller is used by the GraphicsView to nagivate the ...
void pressed(const QModelIndex &index)

Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/

https://www.kdab.com/development-resources/qt-tools/kd-chart/