15#include <kconfiggroup.h>
18#include <ksharedconfig.h>
22#include <QContextMenuEvent>
28#include <QPersistentModelIndex>
29#include <QApplication>
38#define DRAG_WHILE_DRAG_WORKAROUND
41#ifdef DRAG_WHILE_DRAG_WORKAROUND
42#define DRAG_WHILE_DRAG_WORKAROUND_START() d->isDragging = true
43#define DRAG_WHILE_DRAG_WORKAROUND_STOP() d->isDragging = false
45#define DRAG_WHILE_DRAG_WORKAROUND_START()
46#define DRAG_WHILE_DRAG_WORKAROUND_STOP()
55#ifdef DRAG_WHILE_DRAG_WORKAROUND
64#ifdef DRAG_WHILE_DRAG_WORKAROUND
72 , m_draggingFlag(false)
75 setItemDelegate(&
d->delegate);
77 setMouseTracking(
true);
78 setSelectionBehavior(SelectRows);
79 setDefaultDropAction(Qt::MoveAction);
80 setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
81 setSelectionMode(QAbstractItemView::ExtendedSelection);
82 setRootIsDecorated(
false);
86 setDragDropMode(QAbstractItemView::DragDrop);
88 setDropIndicatorShown(
true);
93 connect(scroller, SIGNAL(stateChanged(QScroller::State)),
106 QTreeView::setModel(model);
108 if (!this->model()->inherits(
"KisNodeModel") && !this->model()->inherits(
"KisNodeFilterProxyModel")) {
109 qWarning() <<
"NodeView may not work with" << model->metaObject()->className();
111 if (this->model()->columnCount() != 3) {
112 qWarning() <<
"NodeView: expected 2 model columns, got " << this->model()->columnCount();
132 for (
int i = 0, n = list.count(); i < n; ++i) {
133 if (list.at(i).isMutable) {
135 connect(a, SIGNAL(toggled(
bool,QPersistentModelIndex,
int)),
148 d->delegate.toggleSolo(index);
152 const QEvent *event)
const
165 (event->type() == QEvent::MouseButtonPress ||
166 event->type() == QEvent::MouseButtonRelease) &&
169 const QMouseEvent *mevent =
static_cast<const QMouseEvent*
>(event);
171 if (mevent->button() == Qt::RightButton &&
172 selectionModel()->selectedIndexes().contains(index)) {
175 return QItemSelectionModel::NoUpdate;
178 if (event->type() == QEvent::MouseButtonPress &&
179 (mevent->modifiers() & Qt::ControlModifier)) {
181 return QItemSelectionModel::NoUpdate;
184 if (event->type() == QEvent::MouseButtonRelease &&
185 (mevent->modifiers() & Qt::ControlModifier)) {
189 return QItemSelectionModel::Toggle | QItemSelectionModel::Rows;
198 Qt::KeyboardModifiers globalModifiers = QApplication::keyboardModifiers();
199 if (!event && globalModifiers != Qt::NoModifier) {
200 return QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows;
203 return QAbstractItemView::selectionCommand(index, event);
210 QModelIndex index = QTreeView::indexAt(point);
211 if (!index.isValid()) {
214 index = QTreeView::indexAt(point - QPoint(point.x(), 0) + QPoint(width() / 2, 0));
224 case QEvent::MouseButtonPress: {
227 const QPoint pos =
static_cast<QMouseEvent*
>(e)->pos();
231 return QTreeView::viewportEvent(e);
233 QModelIndex index = model()->buddy(
indexAt(pos));
234 if (
d->delegate.editorEvent(e, model(),
optionForIndex(index), index)) {
238 case QEvent::Leave: {
239 QEvent e(QEvent::Leave);
241 d->hovered = QModelIndex();
243 case QEvent::MouseMove: {
244#ifdef DRAG_WHILE_DRAG_WORKAROUND
250 const QPoint pos =
static_cast<QMouseEvent*
>(e)->pos();
253 if (
d->hovered.isValid()) {
254 QEvent e(QEvent::Leave);
258 QEvent e(QEvent::Enter);
265 Qt::MouseButtons
buttons =
static_cast<QMouseEvent*
>(e)->
buttons();
266 if ((Qt::LeftButton | Qt::MiddleButton) &
buttons) {
267 if ((pos -
d->lastPos).manhattanLength() > qApp->startDragDistance()) {
268 return QTreeView::viewportEvent(e);
273 case QEvent::ToolTip: {
274 const QPoint pos =
static_cast<QHelpEvent*
>(e)->pos();
276 return QTreeView::viewportEvent(e);
278 QModelIndex index = model()->buddy(
indexAt(pos));
279 return d->delegate.editorEvent(e, model(),
optionForIndex(index), index);
281 case QEvent::Resize: {
282 scheduleDelayedItemsLayout();
288 return QTreeView::viewportEvent(e);
293 QTreeView::contextMenuEvent(e);
294 QModelIndex i =
indexAt(e->pos());
296 i = model()->buddy(i);
307 QTreeView::currentChanged(current, previous);
308 if (current != previous) {
309 Q_ASSERT(!current.isValid() || current.model() == model());
317 QTreeView::dataChanged(topLeft, bottomRight);
319 for (
int x = topLeft.row(); x <= bottomRight.row(); ++x) {
320 for (
int y = topLeft.column(); y <= bottomRight.column(); ++y) {
321 QModelIndex index = topLeft.sibling(x, y);
323 if (currentIndex() != index) {
324 setCurrentIndex(index);
335 QTreeView::selectionChanged(selected, deselected);
343 list[num].state = on;
349#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
350 QStyleOptionViewItem option = viewOptions();
352 QStyleOptionViewItem option;
353 initViewItemOption(&option);
355 option.rect = visualRect(index);
356 if (index == currentIndex())
357 option.state |= QStyle::State_HasFocus;
364 QTreeView::startDrag(supportedActions);
369 const QModelIndexList selectedIndexes = selectionModel()->selectedIndexes();
370 Q_ASSERT(!selectedIndexes.isEmpty());
372 const int itemCount = selectedIndexes.count();
382 else if (itemCount > 4) {
386 else if (itemCount < xCount) {
390 int yCount = itemCount / xCount;
391 if (itemCount % xCount != 0) {
395 if (yCount > xCount) {
400 QPixmap dragPixmap(xCount * size + xCount - 1, yCount * size + yCount - 1);
401 dragPixmap.fill(Qt::transparent);
403 QPainter painter(&dragPixmap);
406 Q_FOREACH (
const QModelIndex &selectedIndex, selectedIndexes) {
408 painter.drawPixmap(x, y, QPixmap::fromImage(img.scaled(QSize(size, size), Qt::KeepAspectRatio, Qt::SmoothTransformation)));
411 if (x >= dragPixmap.width()) {
415 if (y >= dragPixmap.height()) {
426 header()->setStretchLastSection(
false);
431 if (
KisConfig(
false).useLayerSelectionCheckbox()) {
434 header()->resizeSection(
DEFAULT_COL, event->size().width() - otherColumnsWidth);
439 QTreeView::resizeEvent(event);
445 QTreeView::paintEvent(event);
449 const QModelIndex &index)
const
451#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
452 QStyleOptionViewItem option = viewOptions();
454 QStyleOptionViewItem option;
455 initViewItemOption(&option);
459 d->delegate.drawBranches(painter, option, index);
464 QTreeView::dropEvent(ev);
470 QSize size(visualRect(model()->index(0, 0, QModelIndex())).width(), visualRect(model()->index(0, 0, QModelIndex())).height());
471 int scrollBarValue = verticalScrollBar()->value();
473 QPoint cursorPosition = QWidget::mapFromGlobal(QCursor::pos());
475 int numberRow = (cursorPosition.y() + scrollBarValue) / size.height();
479 if (abs((cursorPosition.y() + scrollBarValue) - size.height()*numberRow) > (size.height()/2)) {
483 if (numberRow > model()->rowCount(QModelIndex())) {
484 numberRow = model()->rowCount(QModelIndex());
494 QVariant data = QVariant::fromValue(
495 static_cast<void*
>(
const_cast<QMimeData*
>(ev->mimeData())));
498 QTreeView::dragEnterEvent(ev);
504 QTreeView::dragMoveEvent(ev);
509 QTreeView::dragLeaveEvent(e);
525 d->delegate.slotUpdateIcon();
536 d->delegate.slotConfigChanged();
#define DRAG_WHILE_DRAG_WORKAROUND_START()
#define DRAG_WHILE_DRAG_WORKAROUND_STOP()
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
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 paintEvent(QPaintEvent *event) 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)
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)