replace SPDX identifier GPL-2.0+ with GPL-2.0-or-later.
[metze/wireshark/wip.git] / ui / qt / models / astringlist_list_model.cpp
1 /* astringlist_list_model.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 <QSortFilterProxyModel>
11 #include <QStringList>
12 #include <QPalette>
13 #include <QApplication>
14 #include <QBrush>
15
16 #include <ui/qt/models/astringlist_list_model.h>
17
18 AStringListListModel::AStringListListModel(QObject * parent):
19 QAbstractTableModel(parent)
20 {}
21
22 AStringListListModel::~AStringListListModel() { display_data_.clear(); }
23
24 void AStringListListModel::appendRow(const QStringList & display_strings, const QString & row_tooltip, const QModelIndex &parent)
25 {
26     QStringList columns = headerColumns();
27     if ( display_strings.count() != columns.count() )
28         return;
29
30     emit beginInsertRows(parent, rowCount(), rowCount());
31     display_data_ << display_strings;
32     tooltip_data_ << row_tooltip;
33     emit endInsertRows();
34 }
35
36 int AStringListListModel::rowCount(const QModelIndex &parent) const
37 {
38     Q_UNUSED(parent);
39
40     return display_data_.count();
41 }
42
43 int AStringListListModel::columnCount(const QModelIndex &parent) const
44 {
45     if ( rowCount(parent) == 0 )
46         return 0;
47
48     return headerColumns().count();
49 }
50
51 QVariant AStringListListModel::headerData(int section, Qt::Orientation orientation, int role) const
52 {
53     if ( orientation == Qt::Vertical )
54         return QVariant();
55
56     QStringList columns = headerColumns();
57     if ( role == Qt::DisplayRole && section < columns.count() )
58         return QVariant::fromValue(columns[section]);
59
60     return QVariant();
61 }
62
63 QVariant AStringListListModel::data(const QModelIndex &index, int role) const
64 {
65     if ( ! index.isValid() || index.row() >= rowCount() )
66         return QVariant();
67
68     if ( role == Qt::DisplayRole )
69     {
70         QStringList data = display_data_.at(index.row());
71
72         if ( index.column() < columnCount() )
73             return QVariant::fromValue(data.at(index.column()));
74     }
75     else if ( role == Qt::ToolTipRole )
76     {
77         QString tooltip = tooltip_data_.at(index.row());
78         if (!tooltip.isEmpty()) {
79             return tooltip;
80         }
81     }
82
83     return QVariant();
84 }
85
86 AStringListListSortFilterProxyModel::AStringListListSortFilterProxyModel(QObject * parent)
87 : QSortFilterProxyModel(parent)
88 {
89     filter_ = QString();
90     type_ = FilterByContains;
91 }
92
93 bool AStringListListSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
94 {
95     QString leftData = sourceModel()->data(left).toStringList().join(",");
96     QString rightData = sourceModel()->data(right).toStringList().join(",");
97
98     return leftData.compare(rightData, sortCaseSensitivity()) < 0;
99 }
100
101 void AStringListListSortFilterProxyModel::setFilter(const QString & filter)
102 {
103     filter_ = filter;
104     invalidateFilter();
105 }
106
107 static bool AContainsB(const QString &a, const QString &b, Qt::CaseSensitivity cs)
108 {
109     return a.contains(b, cs);
110 }
111
112 static bool AStartsWithB(const QString &a, const QString &b, Qt::CaseSensitivity cs)
113 {
114     return a.startsWith(b, cs);
115 }
116
117 bool AStringListListSortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
118 {
119     if ( columnsToFilter_.count() == 0 )
120         return true;
121
122     foreach(int column, columnsToFilter_)
123     {
124         if ( column >= columnCount() )
125             continue;
126
127         QModelIndex chkIdx = sourceModel()->index(sourceRow, column, sourceParent);
128         QString dataString = sourceModel()->data(chkIdx).toString();
129
130         /* Default is filter by string a contains string b */
131         bool (*compareFunc)(const QString&, const QString&, Qt::CaseSensitivity) = AContainsB;
132         if ( type_ == FilterByStart )
133             compareFunc = AStartsWithB;
134
135         if ( compareFunc(dataString, filter_, filterCaseSensitivity()) )
136             return true;
137     }
138
139     return false;
140 }
141
142 void AStringListListSortFilterProxyModel::setFilterType(AStringListListFilterType type)
143 {
144     if ( type != type_ )
145     {
146         type_ = type;
147         invalidateFilter();
148     }
149 }
150
151 void AStringListListSortFilterProxyModel::setColumnToFilter(int column)
152 {
153     if ( column < columnCount() && ! columnsToFilter_.contains(column) )
154     {
155         columnsToFilter_.append(column);
156         invalidateFilter();
157     }
158 }
159
160 void AStringListListSortFilterProxyModel::clearColumnsToFilter()
161 {
162     columnsToFilter_.clear();
163     invalidateFilter();
164 }
165
166 AStringListListUrlProxyModel::AStringListListUrlProxyModel(QObject * parent):
167         QIdentityProxyModel(parent)
168 {}
169
170 void AStringListListUrlProxyModel::setUrlColumn(int column)
171 {
172     if ( column < columnCount() && ! urls_.contains(column) )
173         urls_ << column;
174 }
175
176 bool AStringListListUrlProxyModel::isUrlColumn(int column) const
177 {
178     return urls_.contains(column);
179 }
180
181 QVariant AStringListListUrlProxyModel::data(const QModelIndex &index, int role) const
182 {
183     QVariant result = QIdentityProxyModel::data(index, role);
184
185     if ( urls_.contains(index.column()) )
186     {
187         if ( role == Qt::ForegroundRole )
188         {
189             if ( result.canConvert(QVariant::Brush) )
190             {
191                 QBrush selected = result.value<QBrush>();
192                 selected.setColor(QApplication::palette().link().color());
193                 return selected;
194             }
195         } else if ( role == Qt::TextColorRole ) {
196             return QApplication::palette().link().color();
197         }
198     }
199
200     return result;
201 }
202
203 /*
204  * Editor modelines
205  *
206  * Local Variables:
207  * c-basic-offset: 4
208  * tab-width: 8
209  * indent-tabs-mode: nil
210  * End:
211  *
212  * ex: set shiftwidth=4 tabstop=8 expandtab:
213  * :indentSize=4:tabSize=8:noTabs=true:
214  */