File indexing completed on 2025-02-02 04:11:26

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 "layer_view.hpp"
0008 
0009 #include <QHeaderView>
0010 
0011 #include <QtColorWidgets/ColorDelegate>
0012 
0013 #include "item_models/document_node_model.hpp"
0014 #include "item_models/comp_filter_model.hpp"
0015 
0016 
0017 using namespace glaxnimate::gui;
0018 
0019 
0020 class glaxnimate::gui::LayerView::Private
0021 {
0022 public:
0023     item_models::DocumentModelBase* base_model;
0024     item_models::CompFilterModel proxy_model;
0025 
0026     color_widgets::ColorDelegate color_delegate;
0027 };
0028 
0029 glaxnimate::gui::LayerView::LayerView(QWidget*parent)
0030     : CustomTreeView(parent), d(std::make_unique<Private>())
0031 {
0032     header()->setStretchLastSection(false);
0033     setHeaderHidden(true);
0034     setDragDropMode(InternalMove);
0035     setDragEnabled(true);
0036 }
0037 
0038 glaxnimate::gui::LayerView::~LayerView() = default;
0039 
0040 item_models::DocumentModelBase * glaxnimate::gui::LayerView::base_model() const
0041 {
0042     return d->base_model;
0043 }
0044 
0045 void glaxnimate::gui::LayerView::set_base_model(item_models::DocumentModelBase* base_model)
0046 {
0047     d->base_model = base_model;
0048     d->proxy_model.setSourceModel(base_model);
0049 
0050 
0051     setModel(&d->proxy_model);
0052 
0053     header()->setSectionResizeMode(item_models::DocumentNodeModel::ColumnName, QHeaderView::Stretch);
0054     header()->setSectionResizeMode(item_models::DocumentNodeModel::ColumnColor, QHeaderView::ResizeToContents);
0055     setItemDelegateForColumn(item_models::DocumentNodeModel::ColumnColor, &d->color_delegate);
0056     header()->hideSection(item_models::DocumentNodeModel::ColumnUsers);
0057 
0058 #ifdef Q_OS_ANDROID
0059     int icon_size = style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, nullptr);
0060     header()->setDefaultSectionSize(icon_size);
0061 #endif
0062 
0063     connect(selectionModel(), &QItemSelectionModel::currentChanged,
0064             this, &LayerView::on_current_node_changed);
0065     connect(selectionModel(), &QItemSelectionModel::selectionChanged,
0066             this, &LayerView::on_selection_changed);
0067 }
0068 
0069 
0070 
0071 void glaxnimate::gui::LayerView::on_current_node_changed(const QModelIndex& index)
0072 {
0073     Q_EMIT current_node_changed(d->base_model->visual_node(d->proxy_model.mapToSource(index)));
0074 }
0075 
0076 void glaxnimate::gui::LayerView::on_selection_changed(const QItemSelection& selected, const QItemSelection& deselected)
0077 {
0078     std::vector<model::VisualNode*> selected_nodes;
0079     std::vector<model::VisualNode*> deselected_nodes;
0080 
0081     for ( const auto& index : deselected.indexes() )
0082         if ( index.column() == 0 )
0083             if ( auto node = d->base_model->visual_node(d->proxy_model.mapToSource(index)) )
0084                 deselected_nodes.push_back(node);
0085 
0086     for ( const auto& index : selected.indexes() )
0087         if ( index.column() == 0 )
0088             if ( auto node = d->base_model->visual_node(d->proxy_model.mapToSource(index)) )
0089                 selected_nodes.push_back(node);
0090 
0091     Q_EMIT selection_changed(selected_nodes, deselected_nodes);
0092 }
0093 
0094 void glaxnimate::gui::LayerView::set_current_node(model::DocumentNode* node)
0095 {
0096     if ( !node )
0097     {
0098         setCurrentIndex({});
0099     }
0100     else
0101     {
0102         auto index = d->proxy_model.mapFromSource(d->base_model->node_index(node));
0103         setCurrentIndex(index);
0104     }
0105 }
0106 
0107 glaxnimate::model::VisualNode* glaxnimate::gui::LayerView::node(const QModelIndex& index) const
0108 {
0109     return d->base_model->visual_node(d->proxy_model.mapToSource(index));
0110 }
0111 
0112 void glaxnimate::gui::LayerView::set_composition(model::Composition* comp)
0113 {
0114     d->proxy_model.set_composition(comp);
0115 }
0116 
0117 glaxnimate::model::VisualNode * glaxnimate::gui::LayerView::current_node() const
0118 {
0119     return node(currentIndex());
0120 }
0121 
0122 void glaxnimate::gui::LayerView::replace_selection(model::VisualNode* node)
0123 {
0124     auto index = d->proxy_model.mapFromSource(d->base_model->node_index(node));
0125     selectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
0126 }
0127 
0128 
0129 void glaxnimate::gui::LayerView::update_selection(const std::vector<model::VisualNode *>& selected, const std::vector<model::VisualNode *>& deselected)
0130 {
0131     for ( model::VisualNode* node : deselected )
0132     {
0133         selectionModel()->select(
0134             d->proxy_model.mapFromSource(d->base_model->node_index(node)),
0135             QItemSelectionModel::Deselect|QItemSelectionModel::Rows
0136         );
0137     }
0138 
0139     for ( model::VisualNode* node : selected )
0140     {
0141         selectionModel()->select(
0142             d->proxy_model.mapFromSource(d->base_model->node_index(node)),
0143             QItemSelectionModel::Select|QItemSelectionModel::Rows
0144         );
0145     }
0146 }
0147 
0148 
0149 void glaxnimate::gui::LayerView::mouseReleaseEvent(QMouseEvent * event)
0150 {
0151     CustomTreeView::mouseReleaseEvent(event);
0152 
0153     if ( event->button() == Qt::LeftButton )
0154     {
0155         auto index = indexAt(event->pos());
0156         auto node = this->node(index);
0157         if ( !node )
0158             return;
0159 
0160         if ( index.column() == item_models::DocumentNodeModel::ColumnVisible )
0161             node->visible.set(!node->visible.get());
0162         else if ( index.column() == item_models::DocumentNodeModel::ColumnLocked )
0163             node->locked.set(!node->locked.get());
0164     }
0165 }