15#include <kconfiggroup.h>
18#include <ksharedconfig.h>
23#include <QContextMenuEvent>
29#include <QPersistentModelIndex>
30#include <QApplication>
37#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
38#define QT6_SHIFT_SELECTION_WORKAROUND
42#define DRAG_WHILE_DRAG_WORKAROUND
45#ifdef DRAG_WHILE_DRAG_WORKAROUND
46#define DRAG_WHILE_DRAG_WORKAROUND_START() d->isDragging = true
47#define DRAG_WHILE_DRAG_WORKAROUND_STOP() d->isDragging = false
49#define DRAG_WHILE_DRAG_WORKAROUND_START()
50#define DRAG_WHILE_DRAG_WORKAROUND_STOP()
59#ifdef DRAG_WHILE_DRAG_WORKAROUND
63 , shiftClickFix(false)
71#ifdef DRAG_WHILE_DRAG_WORKAROUND
74#ifdef QT6_SHIFT_SELECTION_WORKAROUND
77 bool ignoreDataChanged =
false;
83 , m_draggingFlag(false)
86 setItemDelegate(&
d->delegate);
88 setMouseTracking(
true);
89 setSelectionBehavior(SelectRows);
90 setDefaultDropAction(Qt::MoveAction);
91 setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
92 setSelectionMode(QAbstractItemView::ExtendedSelection);
93 setRootIsDecorated(
false);
97 setDragDropMode(QAbstractItemView::DragDrop);
99 setDropIndicatorShown(
true);
104 connect(scroller, SIGNAL(stateChanged(QScroller::State)),
117 QTreeView::setModel(model);
119 if (!this->model()->inherits(
"KisNodeModel") && !this->model()->inherits(
"KisNodeFilterProxyModel")) {
120 qWarning() <<
"NodeView may not work with" << model->metaObject()->className();
122 if (this->model()->columnCount() != 3) {
123 qWarning() <<
"NodeView: expected 2 model columns, got " << this->model()->columnCount();
143 for (
int i = 0, n = list.count(); i < n; ++i) {
144 if (list.at(i).isMutable) {
146 connect(a, SIGNAL(toggled(
bool,QPersistentModelIndex,
int)),
159 d->delegate.toggleSolo(index);
165 if (!event && QApplication::keyboardModifiers() != Qt::NoModifier
170#ifdef QT6_SHIFT_SELECTION_WORKAROUND
171 d->shiftClickFix =
false;
173 return QItemSelectionModel::ClearAndSelect;
176#ifdef QT6_SHIFT_SELECTION_WORKAROUND
178 d->shiftClickFix =
false;
183 (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::KeyPress) &&
184 QApplication::keyboardModifiers() & Qt::ShiftModifier)
185 d->shiftClickFix =
true;
190 event->type() == QEvent::MouseButtonPress && (
static_cast<const QMouseEvent*
>(event)->modifiers() & Qt::ControlModifier))
191 return QItemSelectionModel::NoUpdate;
193 return QTreeView::selectionCommand(index, event);
200 QModelIndex index = QTreeView::indexAt(point);
201 if (!index.isValid()) {
204 index = QTreeView::indexAt(point - QPoint(point.x(), 0) + QPoint(width() / 2, 0));
214 case QEvent::MouseButtonPress: {
217 const QPoint pos =
static_cast<QMouseEvent*
>(e)->pos();
221 return QTreeView::viewportEvent(e);
223 QModelIndex index = model()->buddy(
indexAt(pos));
224 if (
d->delegate.editorEvent(e, model(),
optionForIndex(index), index)) {
228 case QEvent::MouseButtonRelease: {
229 const QPoint pos =
static_cast<QMouseEvent*
>(e)->pos();
230 QModelIndex index = model()->buddy(
indexAt(pos));
232 return QTreeView::viewportEvent(e);
234 if (
d->delegate.editorEvent(e, model(),
optionForIndex(index), index)) {
237 if (active_ind.has_value()) {
243 case QEvent::Leave: {
244 QEvent e(QEvent::Leave);
246 d->hovered = QModelIndex();
248 case QEvent::MouseMove: {
249#ifdef DRAG_WHILE_DRAG_WORKAROUND
255 const QPoint pos =
static_cast<QMouseEvent*
>(e)->pos();
258 if (
d->hovered.isValid()) {
259 QEvent e(QEvent::Leave);
263 QEvent e(QEvent::Enter);
270 Qt::MouseButtons
buttons =
static_cast<QMouseEvent*
>(e)->
buttons();
271 if ((Qt::LeftButton | Qt::MiddleButton) &
buttons) {
272 if ((pos -
d->lastPos).manhattanLength() > qApp->startDragDistance()) {
273 return QTreeView::viewportEvent(e);
278 case QEvent::ToolTip: {
279 const QPoint pos =
static_cast<QHelpEvent*
>(e)->pos();
281 return QTreeView::viewportEvent(e);
283 QModelIndex index = model()->buddy(
indexAt(pos));
284 return d->delegate.editorEvent(e, model(),
optionForIndex(index), index);
286 case QEvent::Resize: {
287 scheduleDelayedItemsLayout();
294 return QTreeView::viewportEvent(e);
299 QTreeView::contextMenuEvent(e);
300 QModelIndex i =
indexAt(e->pos());
302 i = model()->buddy(i);
313 QTreeView::currentChanged(current, previous);
314 if (current != previous) {
315 Q_ASSERT(!current.isValid() || current.model() == model());
323 QTreeView::dataChanged(topLeft, bottomRight);
325 if (
d->ignoreDataChanged){
326 d->ignoreDataChanged =
false;
330 for (
int x = topLeft.row(); x <= bottomRight.row(); ++x) {
331 for (
int y = topLeft.column(); y <= bottomRight.column(); ++y) {
332 QModelIndex index = topLeft.sibling(x, y);
334 if (currentIndex() != index) {
335 setCurrentIndex(index);
346 QTreeView::selectionChanged(selected, deselected);
354 list[num].state = on;
360#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
361 QStyleOptionViewItem option = viewOptions();
363 QStyleOptionViewItem option;
364 initViewItemOption(&option);
366 option.rect = visualRect(index);
367 if (index == currentIndex())
368 option.state |= QStyle::State_HasFocus;
375 QTreeView::startDrag(supportedActions);
380 const QModelIndexList selectedIndexes = selectionModel()->selectedIndexes();
381 Q_ASSERT(!selectedIndexes.isEmpty());
383 const int itemCount = selectedIndexes.count();
393 else if (itemCount > 4) {
397 else if (itemCount < xCount) {
401 int yCount = itemCount / xCount;
402 if (itemCount % xCount != 0) {
406 if (yCount > xCount) {
411 QPixmap dragPixmap(xCount * size + xCount - 1, yCount * size + yCount - 1);
412 dragPixmap.fill(Qt::transparent);
414 QPainter painter(&dragPixmap);
417 Q_FOREACH (
const QModelIndex &selectedIndex, selectedIndexes) {
419 painter.drawPixmap(x, y, QPixmap::fromImage(img.scaled(QSize(size, size), Qt::KeepAspectRatio, Qt::SmoothTransformation)));
422 if (x >= dragPixmap.width()) {
426 if (y >= dragPixmap.height()) {
437 header()->setStretchLastSection(
false);
442 if (
KisConfig(
false).useLayerSelectionCheckbox()) {
445 header()->resizeSection(
DEFAULT_COL, event->size().width() - otherColumnsWidth);
450 QTreeView::resizeEvent(event);
456 QTreeView::paintEvent(event);
460 const QModelIndex &index)
const
462#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
463 QStyleOptionViewItem option = viewOptions();
465 QStyleOptionViewItem option;
466 initViewItemOption(&option);
470 d->delegate.drawBranches(painter, option, index);
475 QTreeView::dropEvent(ev);
481 QSize size(visualRect(model()->index(0, 0, QModelIndex())).width(), visualRect(model()->index(0, 0, QModelIndex())).height());
482 int scrollBarValue = verticalScrollBar()->value();
484 QPoint cursorPosition = QWidget::mapFromGlobal(QCursor::pos());
486 int numberRow = (cursorPosition.y() + scrollBarValue) / size.height();
490 if (abs((cursorPosition.y() + scrollBarValue) - size.height()*numberRow) > (size.height()/2)) {
494 if (numberRow > model()->rowCount(QModelIndex())) {
495 numberRow = model()->rowCount(QModelIndex());
505 QVariant data = QVariant::fromValue(
506 static_cast<void*
>(
const_cast<QMimeData*
>(ev->mimeData())));
509 QTreeView::dragEnterEvent(ev);
515 QTreeView::dragMoveEvent(ev);
520 QTreeView::dragLeaveEvent(e);
525 if (!(e->modifiers() & Qt::ControlModifier)) {
526 QTreeView::mousePressEvent(e);
531 QTreeView::mousePressEvent(e);
533 if (ind.has_value()) {
550 d->delegate.slotUpdateIcon();
561 d->delegate.slotConfigChanged();
580 QAbstractItemModel* mdl = model();
582 int rows = mdl->rowCount();
583 int clmns = mdl->columnCount();
585 for (
int i = 0; i < rows; i++) {
586 for (
int j = 0; j < clmns; j++) {
587 auto index = mdl->index(i, j);
599 QAbstractItemModel* mdl = model();
601 int rows = mdl->rowCount();
602 int clmns = mdl->columnCount();
604 for (
int i = 0; i < rows; i++) {
605 for (
int j = 0; j < clmns; j++) {
606 QModelIndex ind = mdl->index(i, j);
609 d->ignoreDataChanged =
true;
614 d->ignoreDataChanged =
true;
617 selectionModel()->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
#define QT6_SHIFT_SELECTION_WORKAROUND
#define DRAG_WHILE_DRAG_WORKAROUND_START()
#define DRAG_WHILE_DRAG_WORKAROUND_STOP()
bool useLayerSelectionCheckbox(bool defaultValue=false) const
@ PropertiesRole
A list of properties the part has.
@ ActiveRole
Whether the section is the active one.
int selectedButtonColumnWidth() const
int visibilityColumnWidth() const
static KisNodeViewColorScheme * instance()
QItemSelectionModel::SelectionFlags selectionCommand(const QModelIndex &index, const QEvent *event) const override
void setDraggingFlag(bool flag=true)
virtual void showContextMenu(const QPoint &globalPos, const QModelIndex &index)
void contextMenuRequested(const QPoint &globalPos, const QModelIndex &index)
void setExclusiveActiveItem(QModelIndex index)
void paintEvent(QPaintEvent *event) override
void mousePressEvent(QMouseEvent *e) override
void selectionChanged(const QModelIndexList &)
void dragMoveEvent(QDragMoveEvent *ev) override
void updateNode(const QModelIndex &index)
void resizeEvent(QResizeEvent *event) override
bool viewportEvent(QEvent *event) override
int cursorPageIndex() const
void drawBranches(QPainter *painter, const QRect &rect, const QModelIndex &index) const override
NodeView(QWidget *parent=0)
void slotScrollerStateChanged(QScroller::State state)
void toggleSolo(const QModelIndex &index)
void slotConfigurationChanged()
void slotUpdateIcons()
called with a theme change to refresh icon colors
void dropEvent(QDropEvent *ev) override
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector< int > &roles=QVector< int >()) override
QStyleOptionViewItem optionForIndex(const QModelIndex &index) const
void slotActionToggled(bool on, const QPersistentModelIndex &index, int property)
QPixmap createDragPixmap() const
QPersistentModelIndex hovered
void dragEnterEvent(QDragEnterEvent *e) override
void addPropertyActions(QMenu *menu, const QModelIndex &index)
std::optional< QModelIndex > getActiveItem()
void startDrag(Qt::DropActions supportedActions) override
void setModel(QAbstractItemModel *model) override
void dragLeaveEvent(QDragLeaveEvent *e) override
void updateSelectedCheckboxColumn()
void contextMenuEvent(QContextMenuEvent *event) override
void currentChanged(const QModelIndex ¤t, const QModelIndex &previous) override
QModelIndex indexAt(const QPoint &point) const override
QString buttons(const T &ev)