@@ -0,0 +1,23 | |||
|
1 | #ifndef SCIQLOP_DATASOURCETREEWIDGETHELPER_H | |
|
2 | #define SCIQLOP_DATASOURCETREEWIDGETHELPER_H | |
|
3 | ||
|
4 | #include <functional> | |
|
5 | ||
|
6 | class DataSourceTreeWidgetItem; | |
|
7 | class QTreeWidget; | |
|
8 | ||
|
9 | class DataSourceTreeWidgetHelper { | |
|
10 | public: | |
|
11 | /// Signature of the function associated to the filtering action | |
|
12 | using FilterFunction = std::function<bool(const DataSourceTreeWidgetItem &dataSourceItem)>; | |
|
13 | ||
|
14 | /** | |
|
15 | * Filters a tree widget according to a function. If an item is valid according to this | |
|
16 | * function, all of its ancestors and children are shown | |
|
17 | * @param treeWidget the widget to filter | |
|
18 | * @param fun the filter function | |
|
19 | */ | |
|
20 | static void filter(QTreeWidget &treeWidget, FilterFunction fun) noexcept; | |
|
21 | }; | |
|
22 | ||
|
23 | #endif // SCIQLOP_DATASOURCETREEWIDGETHELPER_H |
@@ -0,0 +1,36 | |||
|
1 | #include "DataSource/DataSourceTreeWidgetHelper.h" | |
|
2 | #include "DataSource/DataSourceTreeWidgetItem.h" | |
|
3 | ||
|
4 | namespace { | |
|
5 | ||
|
6 | bool filterTreeItem(DataSourceTreeWidgetItem &treeItem, | |
|
7 | DataSourceTreeWidgetHelper::FilterFunction fun, bool parentValid = false) | |
|
8 | { | |
|
9 | auto selfValid = parentValid || fun(treeItem); | |
|
10 | ||
|
11 | auto childValid = false; | |
|
12 | auto childCount = treeItem.childCount(); | |
|
13 | for (auto i = 0; i < childCount; ++i) { | |
|
14 | if (auto childItem = dynamic_cast<DataSourceTreeWidgetItem *>(treeItem.child(i))) { | |
|
15 | childValid |= filterTreeItem(*childItem, fun, selfValid); | |
|
16 | } | |
|
17 | } | |
|
18 | ||
|
19 | auto valid = selfValid || childValid; | |
|
20 | ||
|
21 | treeItem.setHidden(!valid); | |
|
22 | ||
|
23 | return valid; | |
|
24 | } | |
|
25 | ||
|
26 | } // namespace | |
|
27 | ||
|
28 | void DataSourceTreeWidgetHelper::filter(QTreeWidget &treeWidget, FilterFunction fun) noexcept | |
|
29 | { | |
|
30 | auto itemCount = treeWidget.topLevelItemCount(); | |
|
31 | for (auto i = 0; i < itemCount; ++i) { | |
|
32 | if (auto item = dynamic_cast<DataSourceTreeWidgetItem *>(treeWidget.topLevelItem(i))) { | |
|
33 | filterTreeItem(*item, fun); | |
|
34 | } | |
|
35 | } | |
|
36 | } |
@@ -21,6 +21,8 public: | |||
|
21 | 21 | explicit DataSourceTreeWidgetItem(QTreeWidget *parent, const DataSourceItem *data, |
|
22 | 22 | int type = Type); |
|
23 | 23 | |
|
24 | const DataSourceItem *data() const; | |
|
25 | ||
|
24 | 26 | virtual QVariant data(int column, int role) const override; |
|
25 | 27 | virtual void setData(int column, int role, const QVariant &value) override; |
|
26 | 28 |
@@ -32,6 +32,9 private: | |||
|
32 | 32 | Ui::DataSourceWidget *ui; |
|
33 | 33 | |
|
34 | 34 | private slots: |
|
35 | /// Slot called when the filtering text has changed | |
|
36 | void filterChanged(const QString &text) noexcept; | |
|
37 | ||
|
35 | 38 | /// Slot called when right clicking on an item in the tree (displays a menu) |
|
36 | 39 | void onTreeMenuRequested(const QPoint &pos) noexcept; |
|
37 | 40 | }; |
@@ -131,6 +131,11 DataSourceTreeWidgetItem::DataSourceTreeWidgetItem(QTreeWidget *parent, const Da | |||
|
131 | 131 | std::back_inserter(impl->m_Actions), createTreeAction); |
|
132 | 132 | } |
|
133 | 133 | |
|
134 | const DataSourceItem *DataSourceTreeWidgetItem::data() const | |
|
135 | { | |
|
136 | return impl->m_Data; | |
|
137 | } | |
|
138 | ||
|
134 | 139 | QVariant DataSourceTreeWidgetItem::data(int column, int role) const |
|
135 | 140 | { |
|
136 | 141 | if (role == Qt::DisplayRole) { |
@@ -3,6 +3,7 | |||
|
3 | 3 | #include <ui_DataSourceWidget.h> |
|
4 | 4 | |
|
5 | 5 | #include <DataSource/DataSourceItem.h> |
|
6 | #include <DataSource/DataSourceTreeWidgetHelper.h> | |
|
6 | 7 | #include <DataSource/DataSourceTreeWidgetItem.h> |
|
7 | 8 | |
|
8 | 9 | #include <QMenu> |
@@ -47,6 +48,9 DataSourceWidget::DataSourceWidget(QWidget *parent) : QWidget{parent}, ui{new Ui | |||
|
47 | 48 | // Connection to show a menu when right clicking on the tree |
|
48 | 49 | connect(ui->treeWidget, &QTreeWidget::customContextMenuRequested, this, |
|
49 | 50 | &DataSourceWidget::onTreeMenuRequested); |
|
51 | ||
|
52 | // Connection to filter tree | |
|
53 | connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &DataSourceWidget::filterChanged); | |
|
50 | 54 | } |
|
51 | 55 | |
|
52 | 56 | DataSourceWidget::~DataSourceWidget() noexcept |
@@ -63,6 +67,25 void DataSourceWidget::addDataSource(DataSourceItem *dataSource) noexcept | |||
|
63 | 67 | } |
|
64 | 68 | } |
|
65 | 69 | |
|
70 | void DataSourceWidget::filterChanged(const QString &text) noexcept | |
|
71 | { | |
|
72 | auto validateItem = [&text](const DataSourceTreeWidgetItem &item) { | |
|
73 | auto regExp = QRegExp{text, Qt::CaseInsensitive, QRegExp::Wildcard}; | |
|
74 | ||
|
75 | // An item is valid if any of its metadata validates the text filter | |
|
76 | auto itemMetadata = item.data()->data(); | |
|
77 | auto itemMetadataEnd = itemMetadata.cend(); | |
|
78 | auto acceptFilter | |
|
79 | = [®Exp](const auto &variant) { return variant.toString().contains(regExp); }; | |
|
80 | ||
|
81 | return std::find_if(itemMetadata.cbegin(), itemMetadataEnd, acceptFilter) | |
|
82 | != itemMetadataEnd; | |
|
83 | }; | |
|
84 | ||
|
85 | // Applies filter on tree widget | |
|
86 | DataSourceTreeWidgetHelper::filter(*ui->treeWidget, validateItem); | |
|
87 | } | |
|
88 | ||
|
66 | 89 | void DataSourceWidget::onTreeMenuRequested(const QPoint &pos) noexcept |
|
67 | 90 | { |
|
68 | 91 | // Retrieves the selected item in the tree, and build the menu from its actions |
@@ -14,19 +14,10 | |||
|
14 | 14 | <string>Data sources</string> |
|
15 | 15 | </property> |
|
16 | 16 | <layout class="QGridLayout" name="gridLayout"> |
|
17 | <property name="topMargin"> | |
|
18 | <number>0</number> | |
|
19 | </property> | |
|
20 | <property name="rightMargin"> | |
|
21 | <number>0</number> | |
|
22 | </property> | |
|
23 | <property name="bottomMargin"> | |
|
24 | <number>0</number> | |
|
25 | </property> | |
|
26 | <property name="spacing"> | |
|
27 | <number>0</number> | |
|
28 | </property> | |
|
29 | 17 | <item row="0" column="0"> |
|
18 | <widget class="QLineEdit" name="filterLineEdit"/> | |
|
19 | </item> | |
|
20 | <item row="1" column="0"> | |
|
30 | 21 | <widget class="QTreeWidget" name="treeWidget"> |
|
31 | 22 | <column> |
|
32 | 23 | <property name="text"> |
General Comments 0
You need to be logged in to leave comments.
Login now