KD Chart API Documentation 3.0
Loading...
Searching...
No Matches
kdganttview.cpp
Go to the documentation of this file.
1/****************************************************************************
2**
3** This file is part of the KD Chart library.
4**
5** SPDX-FileCopyrightText: 2001 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6**
7** SPDX-License-Identifier: MIT
8**
9****************************************************************************/
10
11#include "kdganttview.h"
12#include "kdganttview_p.h"
13
14#include "kdganttgraphicsitem.h"
15#include "kdganttitemdelegate.h"
17
18#include <QAbstractItemModel>
19#include <QGraphicsItem>
20#include <QGraphicsRectItem>
21#include <QHeaderView>
22#include <QPaintEvent>
23#include <QScrollBar>
24#include <QVBoxLayout>
25
26#include <QDebug>
27
28#include <cassert>
29
30#if defined KDAB_EVAL
31#include "../evaldialog/evaldialog.h"
32#endif
33
34using namespace KDGantt;
35
36namespace {
37class HeaderView : public QHeaderView
38{
39public:
40 explicit HeaderView(QWidget *parent = nullptr)
41 : QHeaderView(Qt::Horizontal, parent)
42 {
43 }
44
45 QSize sizeHint() const override
46 {
48 s.rheight() *= 2;
49 return s;
50 }
51};
52}
53
54KDGanttTreeView::KDGanttTreeView(QAbstractProxyModel *proxy, QWidget *parent)
55 : QTreeView(parent)
56 , m_controller(this, proxy)
57{
58 setHeader(new HeaderView);
59}
60
61KDGanttTreeView::~KDGanttTreeView()
62{
63}
64
65void KDGanttTreeView::expandAll(QModelIndex index)
66{
67 for (int i = 0; i < model()->rowCount(index); i++) {
68 QModelIndex indexAt = model()->index(i, 0, index);
69 if (model()->hasChildren(indexAt))
70 expandAll(indexAt);
71 if (isExpanded(indexAt))
72 continue;
73 expand(indexAt);
74 }
75}
76
77void KDGanttTreeView::collapseAll(QModelIndex index)
78{
79 for (int i = 0; i < model()->rowCount(index); i++) {
80 QModelIndex indexAt = model()->index(i, 0, index);
81 if (model()->hasChildren(indexAt))
82 collapseAll(indexAt);
83 if (!isExpanded(indexAt))
84 continue;
85 collapse(indexAt);
86 }
87}
88
89View::Private::Private(View *v)
90 : q(v)
91 , splitter(v)
92 , rowController(nullptr)
93 , gfxview(new GraphicsView(&splitter))
94 , model(nullptr)
95{
96 // init();
97}
98
99View::Private::~Private()
100{
101 delete gfxview;
102}
103
104void View::Private::init()
105{
106 auto *tw = new KDGanttTreeView(&ganttProxyModel, &splitter);
107 tw->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
108 tw->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
109
110 q->setLeftView(tw);
111 q->setRowController(tw->rowController());
112
113 // gfxview.setRenderHints( QPainter::Antialiasing );
114
115 tw->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
116
117 auto *layout = new QVBoxLayout(q);
118 layout->setContentsMargins(0, 0, 0, 0);
119 layout->addWidget(&splitter);
120 q->setLayout(layout);
121
122 constraintProxy.setProxyModel(&ganttProxyModel);
123 constraintProxy.setDestinationModel(&mappedConstraintModel);
124 setupGraphicsView();
125}
126
127void View::Private::setupGraphicsView()
128{
129 gfxview->setParent(&splitter);
130 gfxview->setAlignment(Qt::AlignTop | Qt::AlignLeft);
131 gfxview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
132 gfxview->setSelectionModel(leftWidget->selectionModel());
133 gfxview->setConstraintModel(&mappedConstraintModel);
134 q->setLeftView(leftWidget);
135 q->setRowController(rowController);
136 updateScene();
137}
138
139void View::Private::updateScene()
140{
141 gfxview->clearItems();
142 if (!model)
143 return;
144
145 if (auto *tw = qobject_cast<QTreeView *>(leftWidget)) {
146 QModelIndex idx = ganttProxyModel.mapFromSource(model->index(0, 0, leftWidget->rootIndex()));
147 do {
148 gfxview->updateRow(idx);
149 } while ((idx = tw->indexBelow(idx)) != QModelIndex() && gfxview->rowController()->isRowVisible(idx));
150 gfxview->updateSceneRect();
151 } else {
152 const QModelIndex rootidx = ganttProxyModel.mapFromSource(leftWidget->rootIndex());
153 for (int r = 0; r < ganttProxyModel.rowCount(rootidx); ++r) {
154 gfxview->updateRow(ganttProxyModel.index(r, 0, rootidx));
155 }
156 }
157}
158
159void View::Private::slotCollapsed(const QModelIndex &_idx)
160{
161 auto *tw = qobject_cast<QTreeView *>(leftWidget);
162 if (!tw)
163 return;
164
165 bool blocked = gfxview->blockSignals(true);
166
167 QModelIndex idx(_idx);
168 const QAbstractItemModel *model = leftWidget->model();
169 const QModelIndex pidx = ganttProxyModel.mapFromSource(idx);
170 bool isMulti = false;
171 for (QModelIndex treewalkidx = pidx; treewalkidx.isValid(); treewalkidx = treewalkidx.parent()) {
172 if (treewalkidx.data(ItemTypeRole).toInt() == TypeMulti
173 && !gfxview->rowController()->isRowExpanded(treewalkidx)) {
174 isMulti = true;
175 break;
176 }
177 }
178
179 if (!isMulti) {
180 for (int i = 0; i < model->rowCount(idx); ++i) {
181 gfxview->deleteSubtree(ganttProxyModel.index(i, 0, pidx));
182 }
183 } else {
184 gfxview->updateRow(pidx);
185 }
186 // qDebug() << "Looking to update from " << idx;
187 while ((idx = tw->indexBelow(idx)) != QModelIndex() && gfxview->rowController()->isRowVisible(ganttProxyModel.mapFromSource(idx))) {
188 const QModelIndex proxyidx(ganttProxyModel.mapFromSource(idx));
189 gfxview->updateRow(proxyidx);
190 }
191 gfxview->blockSignals(blocked);
192 gfxview->updateSceneRect();
193}
194
195void View::Private::slotExpanded(const QModelIndex &_idx)
196{
197 QModelIndex idx(ganttProxyModel.mapFromSource(_idx));
198 do {
199 // qDebug() << "Updating row" << idx << idx.data( Qt::DisplayRole ).toString();
200 gfxview->updateRow(idx);
201 } while ((idx = gfxview->rowController()->indexBelow(idx)) != QModelIndex()
202 && gfxview->rowController()->isRowVisible(idx));
203 gfxview->updateSceneRect();
204}
205
206void View::Private::slotVerticalScrollValueChanged(int val)
207{
208#if 0
209 qDebug() << "View::Private::slotVerticalScrollValueChanged("<<val<<")="
210 << val/gfxview->verticalScrollBar()->singleStep();
211#endif
212 leftWidget->verticalScrollBar()->setValue(val / gfxview->verticalScrollBar()->singleStep());
213}
214
215void View::Private::slotLeftWidgetVerticalRangeChanged(int min, int max)
216{
217 // qDebug() << "View::Private::slotLeftWidgetVerticalRangeChanged("<<min<<max<<")";
218 gfxview->verticalScrollBar()->setRange(min, max);
219 gfxview->updateSceneRect();
220}
221
222void View::Private::slotGfxViewVerticalRangeChanged(int min, int max)
223{
224 // qDebug() << "View::Private::slotGfxViewVerticalRangeChanged("<<min<<max<<")";
225 if (!leftWidget.isNull() && !gfxview.isNull()) {
226 int leftMin = leftWidget->verticalScrollBar()->minimum();
227 int leftMax = leftWidget->verticalScrollBar()->maximum();
228 bool blocked = gfxview->verticalScrollBar()->blockSignals(true);
229 gfxview->verticalScrollBar()->setRange(qMax(min, leftMin), qMax(max, leftMax));
230 gfxview->verticalScrollBar()->blockSignals(blocked);
231 }
232}
233
248 : QWidget(parent)
249 , _d(new Private(this))
250{
251#if defined KDAB_EVAL
252 EvalDialog::checkEvalLicense("KD Gantt");
253#endif
254 _d->init();
255}
256
258{
259 delete _d;
260}
261
262#define d d_func()
263
270{
271 assert(aiv);
272 if (aiv == d->leftWidget)
273 return;
274 if (!d->leftWidget.isNull()) {
275 d->leftWidget->disconnect(this);
276 d->leftWidget->hide();
277 d->leftWidget->verticalScrollBar()->disconnect(d->gfxview->verticalScrollBar());
278 d->gfxview->verticalScrollBar()->disconnect(d->leftWidget->verticalScrollBar());
279 }
280
281 d->leftWidget = aiv;
282 d->splitter.insertWidget(0, d->leftWidget);
283
284 if (qobject_cast<QTreeView *>(d->leftWidget)) {
285 connect(d->leftWidget, SIGNAL(collapsed(const QModelIndex &)),
286 this, SLOT(slotCollapsed(const QModelIndex &)));
287 connect(d->leftWidget, SIGNAL(expanded(const QModelIndex &)),
288 this, SLOT(slotExpanded(const QModelIndex &)));
289 }
290
291 connect(d->gfxview->verticalScrollBar(), SIGNAL(valueChanged(int)),
292 d->leftWidget->verticalScrollBar(), SLOT(setValue(int)));
293 connect(d->leftWidget->verticalScrollBar(), SIGNAL(valueChanged(int)),
294 d->gfxview->verticalScrollBar(), SLOT(setValue(int)));
295 connect(d->leftWidget->verticalScrollBar(), SIGNAL(rangeChanged(int, int)),
297 connect(d->gfxview->verticalScrollBar(), SIGNAL(rangeChanged(int, int)),
298 this, SLOT(slotGfxViewVerticalRangeChanged(int, int)));
299}
300
307{
308 if (ctrl == d->rowController && d->gfxview->rowController() == ctrl)
309 return;
310 d->rowController = ctrl;
311 d->gfxview->setRowController(d->rowController);
312}
313
318{
319 return d->rowController;
320}
321
325{
326 return d->rowController;
327}
328
334{
335 return d->leftWidget;
336}
337
342{
343 return d->leftWidget;
344}
345
353{
354 if (gv != d->gfxview) {
355 GraphicsView *old = d->gfxview;
356 d->gfxview = gv;
357 d->setupGraphicsView();
358 d->gfxview->setGrid(old->grid());
359 delete old;
360 }
361}
362
367{
368 return d->gfxview;
369}
370
375{
376 return d->gfxview;
377}
378
383{
384 return &d->splitter;
385}
386
391{
392 return &d->splitter;
393}
394
398{
399 return leftView()->model();
400}
401
408{
410 d->ganttProxyModel.setSourceModel(model);
411 d->gfxview->setModel(&d->ganttProxyModel);
412}
413
420
425{
427 d->gfxview->setSelectionModel(new QItemSelectionModel(&(d->ganttProxyModel), this));
428}
429
436{
437 d->gfxview->setGrid(grid);
438}
439
441{
443 tw->expandAll(index);
444}
445
447{
449 tw->collapseAll(index);
450}
451
455{
456 return d->gfxview->grid();
457}
458
462{
463 return leftView()->rootIndex();
464}
465
470{
472 d->gfxview->setRootIndex(idx);
473}
474
478{
479 return d->gfxview->itemDelegate();
480}
481
486{
488 d->gfxview->setItemDelegate(delegate);
489}
490
495{
496 d->constraintProxy.setSourceModel(cm);
497 d->gfxview->setConstraintModel(&d->mappedConstraintModel);
498}
499
503{
504 return d->constraintProxy.sourceModel();
505}
506
508{
509 return &(d->ganttProxyModel);
510}
511
513{
514 return &(d->ganttProxyModel);
515}
516
518{
519 QGraphicsView *view = graphicsView();
520 auto *scene = static_cast<KDGantt::GraphicsScene *>(view->scene());
521 if (!scene)
522 return;
523
524 auto *model = static_cast<KDGantt::SummaryHandlingProxyModel *>(scene->summaryHandlingModel());
525
526 const QModelIndex pidx = d->ganttProxyModel.mapFromSource(index);
527 const QModelIndex idx = model->mapFromSource(pidx);
528 QGraphicsItem *item = scene->findItem(idx);
529 view->ensureVisible(item);
530}
531
536
544{
545 return d->gfxview->indexAt(pos);
546}
547
556void View::print(QPrinter *printer, bool drawRowLabels, bool drawColumnLabels)
557{
559}
560
573void View::print(QPrinter *printer, qreal start, qreal end, bool drawRowLabels, bool drawColumnLabels)
574{
575 graphicsView()->print(printer, start, end, drawRowLabels, drawColumnLabels);
576}
577
584void View::print(QPainter *painter, const QRectF &target, bool drawRowLabels, bool drawColumnLabels)
585{
586 d->gfxview->print(painter,
587 target,
590}
591
602void View::print(QPainter *painter, qreal start, qreal end, const QRectF &target, bool drawRowLabels, bool drawColumnLabels)
603{
604 d->gfxview->print(painter,
605 start, end,
606 target,
609}
610
611#include "moc_kdganttview.cpp"
612
613#undef d
614
615#ifndef KDAB_NO_UNIT_TESTS
616#include "unittest/test.h"
617
619#include <QApplication>
620#include <QListView>
621#include <QPixmap>
622#include <QTimer>
623
625{
626 View view(nullptr);
627#if 0 // GUI tests do not work well on the server
628 QTimer::singleShot( 1000, qApp, SLOT( quit() ) );
629 view.show();
630
631 qApp->exec();
632 QPixmap screenshot1 = QPixmap::grabWidget( &view );
633
634 QTreeView* tv = new QTreeView;
635 view.setLeftView( tv );
637
638 QTimer::singleShot( 1000, qApp, SLOT( quit() ) );
639
640 qApp->exec();
641 QPixmap screenshot2 = QPixmap::grabWidget( &view );
642
643 assertEqual( screenshot1.toImage(), screenshot2.toImage() );
644
645 QListView* lv = new QListView;
646 view.setLeftView(lv);
648 view.show();
649 QTimer::singleShot( 1000, qApp, SLOT( quit() ) );
650 qApp->exec();
651#endif
652}
653#endif /* KDAB_NO_UNIT_TESTS */
Abstract baseclass for grids.
Abstract baseclass for row controllers.
The ConstraintModel keeps track of the interdependencies between gantt items in a View.
The GraphicsView class provides a model/view implementation of a gantt chart.
void print(QPrinter *printer, bool drawRowLabels=true, bool drawColumnLabels=true)
Print the Gantt chart using printer.
void setGrid(AbstractGrid *)
Sets the AbstractGrid for this view.
Class used to render gantt items in a KDGantt::GraphicsView.
Proxy model that supports summary gantt items.
This widget that consists of a QTreeView and a GraphicsView.
Definition kdganttview.h:36
~View() override
void ensureVisible(const QModelIndex &index)
void expandAll(QModelIndex index=QModelIndex())
QModelIndex indexAt(const QPoint &pos) const
View(QWidget *parent=nullptr)
Constructor.
void setLeftView(QAbstractItemView *)
Replaces the left widget with a custom QAbstractItemView.
void setConstraintModel(ConstraintModel *)
Sets the constraintmodel displayed by this view.
void setGrid(AbstractGrid *)
Sets the AbstractGrid for this view.
void setRootIndex(const QModelIndex &idx)
Sets the root index of the model displayed by this view.
void setItemDelegate(ItemDelegate *)
Sets the KDGantt::ItemDelegate used for rendering items on this view.
void setRowController(AbstractRowController *)
Sets ctrl to be the rowcontroller used by this View.
void setSelectionModel(QItemSelectionModel *smodel)
Sets the QItemSelectionModel used by this view to manage selections.
void setGraphicsView(GraphicsView *)
Set the GraphicsView to be used for this View.
const QSplitter * splitter() const
void setModel(QAbstractItemModel *model)
Sets the QAbstractItemModel to be displayed in this view to model.
QItemSelectionModel * selectionModel() const
const QAbstractProxyModel * ganttProxyModel() const
const QAbstractItemView * leftView() const
ItemDelegate * itemDelegate() const
ConstraintModel * constraintModel() const
const GraphicsView * graphicsView() const
AbstractRowController * rowController()
void resizeEvent(QResizeEvent *) override
void print(QPrinter *printer, bool drawRowLabels=true, bool drawColumnLabels=true)
Print the Gantt chart using printer.
AbstractGrid * grid() const
QAbstractItemModel * model() const
QModelIndex rootIndex() const
void collapseAll(QModelIndex index=QModelIndex())
KDAB_SCOPED_UNITTEST_SIMPLE(KDGantt, Constraint, "test")
virtual int rowCount(const QModelIndex &parent) const const=0
QAbstractItemModel * model() const const
QModelIndex rootIndex() const const
QItemSelectionModel * selectionModel() const const
void setItemDelegate(QAbstractItemDelegate *delegate)
virtual void setModel(QAbstractItemModel *model)
virtual void setRootIndex(const QModelIndex &index)
virtual void setSelectionModel(QItemSelectionModel *selectionModel)
void ensureVisible(const QRectF &rect, int xmargin, int ymargin)
QGraphicsScene * scene() const const
virtual QSize sizeHint() const const override
bool isValid() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
T qobject_cast(QObject *object)
QPixmap grabWidget(QObject *widget, const QRect &rectangle)
QImage toImage() const const
int & rheight()
AlignTop
Horizontal
ScrollBarAlwaysOff
virtual void resizeEvent(QResizeEvent *event)
void show()

© 2001 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/
Generated on Sat Mar 23 2024 00:06:52 for KD Chart API Documentation by doxygen 1.9.8