File indexing completed on 2025-02-02 04:11:34
0001 /* 0002 * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best> 0003 * 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 */ 0006 0007 #include "timeline_treeview.hpp" 0008 0009 #include <QMouseEvent> 0010 #include <QPainter> 0011 0012 #include "item_models/property_model_full.hpp" 0013 #include "item_models/comp_filter_model.hpp" 0014 0015 class glaxnimate::gui::TimelineTreeview::Private 0016 { 0017 public: 0018 QModelIndex source_index(const QModelIndex& index) 0019 { 0020 return proxy_model()->mapToSource(index); 0021 } 0022 0023 item_models::CompFilterModel* proxy_model() 0024 { 0025 return static_cast<item_models::CompFilterModel*>(parent->model()); 0026 } 0027 0028 item_models::PropertyModelFull* source_model() 0029 { 0030 return static_cast<item_models::PropertyModelFull*>(proxy_model()->sourceModel()); 0031 } 0032 0033 model::Layer* layer(const QModelIndex& source_index) 0034 { 0035 return qobject_cast<model::Layer*>(source_model()->node(source_index)); 0036 } 0037 0038 void on_drag() 0039 { 0040 auto index = parent->indexAt(drag_to_local); 0041 auto source_index = this->source_index(index); 0042 0043 auto layer = this->layer(source_index); 0044 0045 if ( layer && drag_from_layer->is_valid_parent(layer) ) 0046 { 0047 drag_to_layer = layer; 0048 drag_to_index = index; 0049 } 0050 else 0051 { 0052 drag_to_layer = nullptr; 0053 drag_to_index = {}; 0054 } 0055 0056 parent->viewport()->update(); 0057 } 0058 0059 QPoint relpoint() 0060 { 0061 return parent->visualRect(parent->model()->index(0, 0)).topLeft(); 0062 } 0063 0064 TimelineTreeview* parent; 0065 QPoint drag_from; 0066 QPoint drag_to; 0067 QPoint drag_to_local; 0068 QModelIndex drag_from_index; 0069 QModelIndex drag_to_index; 0070 model::Layer* drag_from_layer = nullptr; 0071 model::Layer* drag_to_layer = nullptr; 0072 bool dragging = false; 0073 }; 0074 0075 glaxnimate::gui::TimelineTreeview::TimelineTreeview(QWidget* parent) 0076 : QTreeView(parent), d(std::make_unique<Private>()) 0077 { 0078 d->parent = this; 0079 } 0080 0081 glaxnimate::gui::TimelineTreeview::~TimelineTreeview() = default; 0082 0083 void glaxnimate::gui::TimelineTreeview::mousePressEvent(QMouseEvent* event) 0084 { 0085 if ( event->button() == Qt::LeftButton ) 0086 { 0087 auto index = indexAt(event->pos()); 0088 auto source_index = d->source_index(index); 0089 0090 if ( source_index.column() == item_models::PropertyModelFull::ColumnValue ) 0091 { 0092 auto layer = d->layer(source_index); 0093 if ( layer && !layer->docnode_locked_recursive() ) 0094 { 0095 d->drag_from_layer = layer; 0096 d->drag_from = d->drag_to = event->pos() - d->relpoint(); 0097 d->drag_to_local = event->pos(); 0098 d->drag_from_index = index; 0099 d->drag_to_layer = nullptr; 0100 d->drag_to_layer = nullptr; 0101 d->drag_to_index = {}; 0102 d->dragging = true; 0103 0104 event->accept(); 0105 viewport()->update(); 0106 return; 0107 } 0108 } 0109 } 0110 0111 QTreeView::mousePressEvent(event); 0112 } 0113 0114 void glaxnimate::gui::TimelineTreeview::mouseMoveEvent(QMouseEvent* event) 0115 { 0116 if ( d->dragging ) 0117 { 0118 d->drag_to = event->pos() - d->relpoint(); 0119 d->drag_to_local = event->pos(); 0120 d->on_drag(); 0121 } 0122 else 0123 { 0124 QTreeView::mouseMoveEvent(event); 0125 } 0126 } 0127 0128 void glaxnimate::gui::TimelineTreeview::mouseReleaseEvent(QMouseEvent* event) 0129 { 0130 if ( d->dragging && event->button() == Qt::LeftButton ) 0131 { 0132 d->dragging = false; 0133 0134 // if moved less than 3 pixels, treat as a click 0135 if ( math::length_squared<QPointF>(d->drag_to - d->drag_from) < 9 ) 0136 { 0137 QTreeView::mousePressEvent(event); 0138 QTreeView::mouseReleaseEvent(event); 0139 } 0140 else 0141 { 0142 d->drag_from_layer->parent.set_undoable(QVariant::fromValue(d->drag_to_layer)); 0143 } 0144 0145 d->drag_from_layer = d->drag_to_layer = nullptr; 0146 d->drag_from_index = d->drag_to_index = {}; 0147 viewport()->update(); 0148 } 0149 else 0150 { 0151 QTreeView::mouseReleaseEvent(event); 0152 } 0153 } 0154 0155 void glaxnimate::gui::TimelineTreeview::paintEvent(QPaintEvent* event) 0156 { 0157 QTreeView::paintEvent(event); 0158 0159 if ( d->dragging ) 0160 { 0161 QPainter painter(viewport()); 0162 painter.setRenderHint(QPainter::Antialiasing); 0163 0164 if ( d->drag_to_index.isValid() ) 0165 { 0166 painter.setPen(QPen(palette().text(), 2)); 0167 0168 auto rect = visualRect(d->drag_to_index); 0169 rect.setX(0); 0170 rect.setWidth(width()); 0171 painter.drawRect(rect); 0172 } 0173 0174 painter.setPen(QPen(palette().highlight(), 2)); 0175 QPoint off = d->relpoint(); 0176 painter.drawLine( 0177 d->drag_from + off, 0178 d->drag_to + off 0179 ); 0180 } 0181 } 0182 0183 void glaxnimate::gui::TimelineTreeview::scrollContentsBy(int dx, int dy) 0184 { 0185 QTreeView::scrollContentsBy(dx, dy); 0186 0187 if ( d->dragging ) 0188 { 0189 d->drag_to = d->drag_to_local - d->relpoint(); 0190 d->on_drag(); 0191 } 0192 }