12 #include "kdganttview_p.h"
18 #include <QAbstractItemModel>
19 #include <QGraphicsItem>
20 #include <QGraphicsRectItem>
21 #include <QHeaderView>
22 #include <QPaintEvent>
24 #include <QVBoxLayout>
31 #include "../evaldialog/evaldialog.h"
37 class HeaderView :
public QHeaderView
40 explicit HeaderView(QWidget *parent =
nullptr)
41 : QHeaderView(Qt::Horizontal, parent)
45 QSize sizeHint()
const override
47 QSize s = QHeaderView::sizeHint();
54 KDGanttTreeView::KDGanttTreeView(QAbstractProxyModel *proxy, QWidget *parent)
56 , m_controller(this, proxy)
58 setHeader(
new HeaderView);
61 KDGanttTreeView::~KDGanttTreeView()
65 void KDGanttTreeView::expandAll(QModelIndex index)
67 for (
int i = 0; i < model()->rowCount(index); i++) {
68 QModelIndex indexAt = model()->index(i, 0, index);
69 if (model()->hasChildren(indexAt))
71 if (isExpanded(indexAt))
77 void KDGanttTreeView::collapseAll(QModelIndex index)
79 for (
int i = 0; i < model()->rowCount(index); i++) {
80 QModelIndex indexAt = model()->index(i, 0, index);
81 if (model()->hasChildren(indexAt))
83 if (!isExpanded(indexAt))
89 View::Private::Private(
View *v)
92 , rowController(nullptr)
99 View::Private::~Private()
104 void View::Private::init()
106 auto *tw =
new KDGanttTreeView(&ganttProxyModel, &splitter);
107 tw->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
108 tw->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
111 q->setRowController(tw->rowController());
115 tw->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
117 auto *layout =
new QVBoxLayout(q);
118 layout->setContentsMargins(0, 0, 0, 0);
119 layout->addWidget(&splitter);
120 q->setLayout(layout);
122 constraintProxy.setProxyModel(&ganttProxyModel);
123 constraintProxy.setDestinationModel(&mappedConstraintModel);
127 void View::Private::setupGraphicsView()
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);
139 void View::Private::updateScene()
141 gfxview->clearItems();
145 if (
auto *tw = qobject_cast<QTreeView *>(leftWidget)) {
146 QModelIndex idx = ganttProxyModel.mapFromSource(model->index(0, 0, leftWidget->rootIndex()));
148 gfxview->updateRow(idx);
149 }
while ((idx = tw->indexBelow(idx)) != QModelIndex() && gfxview->rowController()->isRowVisible(idx));
150 gfxview->updateSceneRect();
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));
159 void View::Private::slotCollapsed(
const QModelIndex &_idx)
161 auto *tw = qobject_cast<QTreeView *>(leftWidget);
165 bool blocked = gfxview->blockSignals(
true);
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()) {
173 && !gfxview->rowController()->isRowExpanded(treewalkidx)) {
180 for (
int i = 0; i < model->rowCount(idx); ++i) {
181 gfxview->deleteSubtree(ganttProxyModel.index(i, 0, pidx));
184 gfxview->updateRow(pidx);
187 while ((idx = tw->indexBelow(idx)) != QModelIndex() && gfxview->rowController()->isRowVisible(ganttProxyModel.mapFromSource(idx))) {
188 const QModelIndex proxyidx(ganttProxyModel.mapFromSource(idx));
189 gfxview->updateRow(proxyidx);
191 gfxview->blockSignals(blocked);
192 gfxview->updateSceneRect();
195 void View::Private::slotExpanded(
const QModelIndex &_idx)
197 QModelIndex idx(ganttProxyModel.mapFromSource(_idx));
200 gfxview->updateRow(idx);
201 }
while ((idx = gfxview->rowController()->indexBelow(idx)) != QModelIndex()
202 && gfxview->rowController()->isRowVisible(idx));
203 gfxview->updateSceneRect();
206 void View::Private::slotVerticalScrollValueChanged(
int val)
209 qDebug() <<
"View::Private::slotVerticalScrollValueChanged("<<val<<
")="
210 << val/gfxview->verticalScrollBar()->singleStep();
212 leftWidget->verticalScrollBar()->setValue(val / gfxview->verticalScrollBar()->singleStep());
215 void View::Private::slotLeftWidgetVerticalRangeChanged(
int min,
int max)
218 gfxview->verticalScrollBar()->setRange(min, max);
219 gfxview->updateSceneRect();
222 void View::Private::slotGfxViewVerticalRangeChanged(
int min,
int 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);
247 View::View(QWidget *parent)
249 , _d(new Private(this))
251 #if defined KDAB_EVAL
252 EvalDialog::checkEvalLicense(
"KD Gantt");
272 if (aiv ==
d->leftWidget)
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());
282 d->splitter.insertWidget(0,
d->leftWidget);
284 auto leftWidgetTreeView = qobject_cast<QTreeView *>(
d->leftWidget);
285 if (leftWidgetTreeView) {
286 connect(leftWidgetTreeView, &QTreeView::collapsed,
287 this, [
this](
const QModelIndex &index) {
288 d->slotCollapsed(index);
290 connect(leftWidgetTreeView, &QTreeView::expanded,
291 this, [
this](
const QModelIndex &index) {
292 d->slotExpanded(index);
296 connect(
d->gfxview->verticalScrollBar(), &QScrollBar::valueChanged,
297 d->leftWidget->verticalScrollBar(), &QScrollBar::setValue);
298 connect(
d->leftWidget->verticalScrollBar(), &QScrollBar::valueChanged,
299 d->gfxview->verticalScrollBar(), &QScrollBar::setValue);
300 connect(
d->leftWidget->verticalScrollBar(), &QScrollBar::rangeChanged,
301 this, [
this](
int min,
int max) {
302 d->slotLeftWidgetVerticalRangeChanged(min, max);
304 connect(
d->gfxview->verticalScrollBar(), &QScrollBar::rangeChanged,
305 this, [
this](
int min,
int max) {
306 d->slotLeftWidgetVerticalRangeChanged(min, max);
317 if (ctrl ==
d->rowController &&
d->gfxview->rowController() == ctrl)
319 d->rowController = ctrl;
320 d->gfxview->setRowController(
d->rowController);
328 return d->rowController;
335 return d->rowController;
344 return d->leftWidget;
352 return d->leftWidget;
363 if (gv !=
d->gfxview) {
366 d->setupGraphicsView();
367 d->gfxview->setGrid(old->
grid());
419 d->ganttProxyModel.setSourceModel(
model);
420 d->gfxview->setModel(&
d->ganttProxyModel);
427 return leftView()->selectionModel();
435 leftView()->setSelectionModel(smodel);
436 d->gfxview->setSelectionModel(
new QItemSelectionModel(&(
d->ganttProxyModel),
this));
446 d->gfxview->setGrid(
grid);
451 auto *tw = qobject_cast<KDGanttTreeView *>(
leftView());
452 tw->expandAll(index);
457 auto *tw = qobject_cast<KDGanttTreeView *>(
leftView());
458 tw->collapseAll(index);
465 return d->gfxview->grid();
481 d->gfxview->setRootIndex(idx);
488 return d->gfxview->itemDelegate();
496 leftView()->setItemDelegate(delegate);
497 d->gfxview->setItemDelegate(delegate);
505 d->constraintProxy.setSourceModel(cm);
506 d->gfxview->setConstraintModel(&
d->mappedConstraintModel);
513 return d->constraintProxy.sourceModel();
518 return &(
d->ganttProxyModel);
523 return &(
d->ganttProxyModel);
535 const QModelIndex pidx =
d->ganttProxyModel.mapFromSource(index);
536 const QModelIndex idx =
model->mapFromSource(pidx);
537 QGraphicsItem *item = scene->findItem(idx);
538 view->ensureVisible(item);
543 QWidget::resizeEvent(ev);
554 return d->gfxview->indexAt(pos);
565 void View::print(QPrinter *printer,
bool drawRowLabels,
bool drawColumnLabels)
582 void View::print(QPrinter *printer, qreal start, qreal end,
bool drawRowLabels,
bool drawColumnLabels)
593 void View::print(QPainter *painter,
const QRectF &target,
bool drawRowLabels,
bool drawColumnLabels)
595 d->gfxview->print(painter,
611 void View::print(QPainter *painter, qreal start, qreal end,
const QRectF &target,
bool drawRowLabels,
bool drawColumnLabels)
613 d->gfxview->print(painter,
620 #include "moc_kdganttview.cpp"
624 #ifndef KDAB_NO_UNIT_TESTS
625 #include "unittest/test.h"
628 #include <QApplication>
637 QTimer::singleShot( 1000, qApp, &QCoreApplication::quit );
641 QPixmap screenshot1 = QPixmap::grabWidget( &view );
643 QTreeView* tv =
new QTreeView;
647 QTimer::singleShot( 1000, qApp, &QCoreApplication::quit );
650 QPixmap screenshot2 = QPixmap::grabWidget( &view );
652 assertEqual( screenshot1.toImage(), screenshot2.toImage() );
654 QListView* lv =
new QListView;
658 QTimer::singleShot( 1000, qApp, &QCoreApplication::quit );
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.
AbstractGrid * grid() const
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.
void ensureVisible(const QModelIndex &index)
void expandAll(QModelIndex index=QModelIndex())
QModelIndex indexAt(const QPoint &pos) const
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, View, "test")