File indexing completed on 2024-05-19 05:42:28

0001 // ct_lvtqtw_treeview.cpp                                            -*-C++-*-
0002 
0003 /*
0004 // Copyright 2023 Codethink Ltd <codethink@codethink.co.uk>
0005 // SPDX-License-Identifier: Apache-2.0
0006 //
0007 // Licensed under the Apache License, Version 2.0 (the "License");
0008 // you may not use this file except in compliance with the License.
0009 // You may obtain a copy of the License at
0010 //
0011 //     http://www.apache.org/licenses/LICENSE-2.0
0012 //
0013 // Unless required by applicable law or agreed to in writing, software
0014 // distributed under the License is distributed on an "AS IS" BASIS,
0015 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0016 // See the License for the specific language governing permissions and
0017 // limitations under the License.
0018 */
0019 
0020 #include <ct_lvtqtw_treeview.h>
0021 
0022 #include <ct_lvtmdl_basetreemodel.h>
0023 #include <ct_lvtmdl_modelhelpers.h>
0024 #include <ct_lvtmdl_treefiltermodel.h>
0025 
0026 #include <QDebug>
0027 #include <QMouseEvent>
0028 #include <QSortFilterProxyModel>
0029 
0030 #include <QDrag>
0031 #include <QMimeData>
0032 #include <qnamespace.h>
0033 
0034 namespace Codethink::lvtqtw {
0035 
0036 struct TreeView::TreeViewPrivate {
0037     Codethink::lvtmdl::BaseTreeModel *model = nullptr;
0038     Codethink::lvtmdl::TreeFilterModel *filterModel = nullptr;
0039     QPoint mousePressPos;
0040 };
0041 
0042 // --------------------------------------------
0043 // class TreeView
0044 // --------------------------------------------
0045 
0046 TreeView::TreeView(QWidget *parent): QTreeView(parent), d(std::make_unique<TreeView::TreeViewPrivate>())
0047 {
0048     // Sorting the table loads the data, but also messes up the positions.
0049     // not sorting the table does not load the data.
0050     setSortingEnabled(false);
0051     setDragEnabled(true);
0052     setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection);
0053 
0054     connect(this, &QTreeView::clicked, this, [this](const QModelIndex& idx) {
0055         auto isBranch = idx.data(lvtmdl::ModelRoles::e_IsBranch).value<bool>();
0056 
0057         if (isBranch) {
0058             Q_EMIT branchSelected(idx);
0059         } else {
0060             Q_EMIT leafSelected(idx);
0061         }
0062     });
0063 
0064     d->filterModel = new lvtmdl::TreeFilterModel();
0065 }
0066 
0067 TreeView::~TreeView() noexcept = default;
0068 
0069 void TreeView::setModel(QAbstractItemModel *model)
0070 {
0071     auto *base_model = qobject_cast<lvtmdl::BaseTreeModel *>(model);
0072     assert(base_model);
0073 
0074     d->model = base_model;
0075     d->filterModel->setSourceModel(d->model);
0076 
0077     connect(this, &QTreeView::expanded, model, &QAbstractItemModel::fetchMore);
0078 
0079     QTreeView::setModel(d->filterModel);
0080 }
0081 
0082 void TreeView::mousePressEvent(QMouseEvent *ev)
0083 {
0084     if (ev->buttons() & Qt::MouseButton::MiddleButton) {
0085         const QModelIndex& idx = indexAt(ev->pos());
0086         if (!idx.isValid()) {
0087             return;
0088         }
0089         auto isBranch = idx.data(lvtmdl::ModelRoles::e_IsBranch).value<bool>();
0090         if (isBranch) {
0091             Q_EMIT branchMiddleClicked(idx);
0092         } else {
0093             Q_EMIT leafMiddleClicked(idx);
0094         }
0095     } else if (ev->buttons() & Qt::MouseButton::RightButton) {
0096         const QModelIndex& idx = indexAt(ev->pos());
0097         if (!idx.isValid()) {
0098             return;
0099         }
0100 
0101         auto isBranch = idx.data(lvtmdl::ModelRoles::e_IsBranch).value<bool>();
0102         if (isBranch) {
0103             Q_EMIT branchRightClicked(selectedIndexes(), idx, ev->globalPos());
0104         } else {
0105             Q_EMIT leafRightClicked(selectedIndexes(), idx, ev->globalPos());
0106         }
0107     }
0108     d->mousePressPos = ev->pos();
0109 
0110     QTreeView::mousePressEvent(ev);
0111 }
0112 
0113 void TreeView::setFilterText(const QString& txt)
0114 {
0115     d->filterModel->setFilter(txt);
0116 }
0117 
0118 void TreeView::mouseReleaseEvent(QMouseEvent *ev)
0119 {
0120     QTreeView::mouseReleaseEvent(ev);
0121     d->mousePressPos = QPoint{};
0122 }
0123 
0124 void TreeView::keyPressEvent(QKeyEvent *e)
0125 {
0126     QTreeView::keyPressEvent(e);
0127     if (e->key() == Qt::Key_Escape) {
0128         clearSelection();
0129     }
0130 }
0131 
0132 } // namespace Codethink::lvtqtw