1 /* profile_tree_view.cpp
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 1998 Gerald Combs
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  */
9 
10 #include <ui/qt/models/url_link_delegate.h>
11 #include <ui/qt/models/profile_model.h>
12 #include <ui/qt/widgets/profile_tree_view.h>
13 
14 #include <QDesktopServices>
15 #include <QDir>
16 #include <QItemDelegate>
17 #include <QLineEdit>
18 #include <QUrl>
19 
ProfileUrlLinkDelegate(QObject * parent)20 ProfileUrlLinkDelegate::ProfileUrlLinkDelegate(QObject *parent) : UrlLinkDelegate (parent) {}
21 
paint(QPainter * painter,const QStyleOptionViewItem & option,const QModelIndex & index) const22 void ProfileUrlLinkDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
23 {
24     /* Only paint links for valid paths */
25     if (index.data(ProfileModel::DATA_PATH_IS_NOT_DESCRIPTION).toBool())
26         UrlLinkDelegate::paint(painter, option, index);
27     else
28         QStyledItemDelegate::paint(painter, option, index);
29 
30 }
31 
ProfileTreeEditDelegate(QWidget * parent)32 ProfileTreeEditDelegate::ProfileTreeEditDelegate(QWidget *parent) : QItemDelegate(parent), editor_(Q_NULLPTR) {}
33 
setEditorData(QWidget * editor,const QModelIndex & index) const34 void ProfileTreeEditDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
35 {
36     if (qobject_cast<QLineEdit *>(editor))
37     {
38         QLineEdit * ql = qobject_cast<QLineEdit *>(editor);
39         ql->setText(index.data().toString());
40     }
41 }
42 
ProfileTreeView(QWidget * parent)43 ProfileTreeView::ProfileTreeView(QWidget *parent) :
44     QTreeView (parent)
45 {
46     delegate_ = new ProfileTreeEditDelegate();
47     setItemDelegateForColumn(ProfileModel::COL_NAME, delegate_);
48 
49     connect(this, &QAbstractItemView::clicked, this, &ProfileTreeView::clicked);
50     connect(delegate_, SIGNAL(commitData(QWidget *)), this, SIGNAL(itemUpdated()));
51 }
52 
~ProfileTreeView()53 ProfileTreeView::~ProfileTreeView()
54 {
55     delete delegate_;
56 }
57 
selectionChanged(const QItemSelection & selected,const QItemSelection & deselected)58 void ProfileTreeView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
59 {
60     QTreeView::selectionChanged(selected, deselected);
61 
62     if (model())
63     {
64         int offColumn = model()->columnCount();
65         int idxCount = selectedIndexes().count() / offColumn;
66         int dselCount = deselected.count() > 0 ? deselected.at(0).indexes().count() / offColumn : 0;
67 
68         /* Ensure, that the last selected row cannot be deselected */
69         if (idxCount == 0 && dselCount == 1)
70         {
71             QModelIndex idx = deselected.at(0).indexes().at(0);
72             /* If the last item is no longer valid or the row is out of bounds, select default */
73             if (! idx.isValid() || idx.row() >= model()->rowCount())
74                 idx = model()->index(0, ProfileModel::COL_NAME);
75             selectRow(idx.row());
76         }
77         else if (selectedIndexes().count() == 0)
78             selectRow(0);
79     }
80 }
81 
clicked(const QModelIndex & index)82 void ProfileTreeView::clicked(const QModelIndex &index)
83 {
84     if (!index.isValid())
85         return;
86 
87     /* Only paint links for valid paths */
88     if (index.data(ProfileModel::DATA_INDEX_VALUE_IS_URL).toBool())
89     {
90         QString path = QDir::toNativeSeparators(index.data().toString());
91         QDesktopServices::openUrl(QUrl::fromLocalFile(path));
92     }
93 }
94 
selectRow(int row)95 void ProfileTreeView::selectRow(int row)
96 {
97     if (row < 0)
98         return;
99 
100     setCurrentIndex(model()->index(row, 0));
101 
102     selectionModel()->select(
103                 QItemSelection(model()->index(row, 0), model()->index(row, model()->columnCount() -1)),
104                 QItemSelectionModel::ClearAndSelect);
105 
106 }
107 
mouseDoubleClickEvent(QMouseEvent * ev)108 void ProfileTreeView::mouseDoubleClickEvent(QMouseEvent *ev)
109 {
110     /* due to the fact, that we allow only row selection, selected rows are always added with all columns */
111     if (selectedIndexes().count() <= model()->columnCount())
112         QTreeView::mouseDoubleClickEvent(ev);
113 }
114 
activeEdit()115 bool ProfileTreeView::activeEdit()
116 {
117     return (state() == QAbstractItemView::EditingState);
118 }
119