From 14a4a9cf453ec3be28b4951ec6355b84987ff479 2017-08-01 15:34:29 From: perrinel Date: 2017-08-01 15:34:29 Subject: [PATCH] Merge pull request #195 from SCIQLOP-Initialisation develop Develop --- diff --git a/gui/include/DataSource/DataSourceTreeWidgetHelper.h b/gui/include/DataSource/DataSourceTreeWidgetHelper.h new file mode 100644 index 0000000..9e1e849 --- /dev/null +++ b/gui/include/DataSource/DataSourceTreeWidgetHelper.h @@ -0,0 +1,23 @@ +#ifndef SCIQLOP_DATASOURCETREEWIDGETHELPER_H +#define SCIQLOP_DATASOURCETREEWIDGETHELPER_H + +#include + +class DataSourceTreeWidgetItem; +class QTreeWidget; + +class DataSourceTreeWidgetHelper { +public: + /// Signature of the function associated to the filtering action + using FilterFunction = std::function; + + /** + * Filters a tree widget according to a function. If an item is valid according to this + * function, all of its ancestors and children are shown + * @param treeWidget the widget to filter + * @param fun the filter function + */ + static void filter(QTreeWidget &treeWidget, FilterFunction fun) noexcept; +}; + +#endif // SCIQLOP_DATASOURCETREEWIDGETHELPER_H diff --git a/gui/include/DataSource/DataSourceTreeWidgetItem.h b/gui/include/DataSource/DataSourceTreeWidgetItem.h index 842e5ba..d58190f 100644 --- a/gui/include/DataSource/DataSourceTreeWidgetItem.h +++ b/gui/include/DataSource/DataSourceTreeWidgetItem.h @@ -21,6 +21,8 @@ public: explicit DataSourceTreeWidgetItem(QTreeWidget *parent, const DataSourceItem *data, int type = Type); + const DataSourceItem *data() const; + virtual QVariant data(int column, int role) const override; virtual void setData(int column, int role, const QVariant &value) override; diff --git a/gui/include/DataSource/DataSourceWidget.h b/gui/include/DataSource/DataSourceWidget.h index 84e09dd..615adfd 100644 --- a/gui/include/DataSource/DataSourceWidget.h +++ b/gui/include/DataSource/DataSourceWidget.h @@ -32,6 +32,9 @@ private: Ui::DataSourceWidget *ui; private slots: + /// Slot called when the filtering text has changed + void filterChanged(const QString &text) noexcept; + /// Slot called when right clicking on an item in the tree (displays a menu) void onTreeMenuRequested(const QPoint &pos) noexcept; }; diff --git a/gui/src/DataSource/DataSourceTreeWidgetHelper.cpp b/gui/src/DataSource/DataSourceTreeWidgetHelper.cpp new file mode 100644 index 0000000..b5b969b --- /dev/null +++ b/gui/src/DataSource/DataSourceTreeWidgetHelper.cpp @@ -0,0 +1,36 @@ +#include "DataSource/DataSourceTreeWidgetHelper.h" +#include "DataSource/DataSourceTreeWidgetItem.h" + +namespace { + +bool filterTreeItem(DataSourceTreeWidgetItem &treeItem, + DataSourceTreeWidgetHelper::FilterFunction fun, bool parentValid = false) +{ + auto selfValid = parentValid || fun(treeItem); + + auto childValid = false; + auto childCount = treeItem.childCount(); + for (auto i = 0; i < childCount; ++i) { + if (auto childItem = dynamic_cast(treeItem.child(i))) { + childValid |= filterTreeItem(*childItem, fun, selfValid); + } + } + + auto valid = selfValid || childValid; + + treeItem.setHidden(!valid); + + return valid; +} + +} // namespace + +void DataSourceTreeWidgetHelper::filter(QTreeWidget &treeWidget, FilterFunction fun) noexcept +{ + auto itemCount = treeWidget.topLevelItemCount(); + for (auto i = 0; i < itemCount; ++i) { + if (auto item = dynamic_cast(treeWidget.topLevelItem(i))) { + filterTreeItem(*item, fun); + } + } +} diff --git a/gui/src/DataSource/DataSourceTreeWidgetItem.cpp b/gui/src/DataSource/DataSourceTreeWidgetItem.cpp index 22a3cde..df831ad 100644 --- a/gui/src/DataSource/DataSourceTreeWidgetItem.cpp +++ b/gui/src/DataSource/DataSourceTreeWidgetItem.cpp @@ -131,6 +131,11 @@ DataSourceTreeWidgetItem::DataSourceTreeWidgetItem(QTreeWidget *parent, const Da std::back_inserter(impl->m_Actions), createTreeAction); } +const DataSourceItem *DataSourceTreeWidgetItem::data() const +{ + return impl->m_Data; +} + QVariant DataSourceTreeWidgetItem::data(int column, int role) const { if (role == Qt::DisplayRole) { diff --git a/gui/src/DataSource/DataSourceWidget.cpp b/gui/src/DataSource/DataSourceWidget.cpp index 67bcf4a..e1de06d 100644 --- a/gui/src/DataSource/DataSourceWidget.cpp +++ b/gui/src/DataSource/DataSourceWidget.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -47,6 +48,9 @@ DataSourceWidget::DataSourceWidget(QWidget *parent) : QWidget{parent}, ui{new Ui // Connection to show a menu when right clicking on the tree connect(ui->treeWidget, &QTreeWidget::customContextMenuRequested, this, &DataSourceWidget::onTreeMenuRequested); + + // Connection to filter tree + connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &DataSourceWidget::filterChanged); } DataSourceWidget::~DataSourceWidget() noexcept @@ -63,6 +67,25 @@ void DataSourceWidget::addDataSource(DataSourceItem *dataSource) noexcept } } +void DataSourceWidget::filterChanged(const QString &text) noexcept +{ + auto validateItem = [&text](const DataSourceTreeWidgetItem &item) { + auto regExp = QRegExp{text, Qt::CaseInsensitive, QRegExp::Wildcard}; + + // An item is valid if any of its metadata validates the text filter + auto itemMetadata = item.data()->data(); + auto itemMetadataEnd = itemMetadata.cend(); + auto acceptFilter + = [®Exp](const auto &variant) { return variant.toString().contains(regExp); }; + + return std::find_if(itemMetadata.cbegin(), itemMetadataEnd, acceptFilter) + != itemMetadataEnd; + }; + + // Applies filter on tree widget + DataSourceTreeWidgetHelper::filter(*ui->treeWidget, validateItem); +} + void DataSourceWidget::onTreeMenuRequested(const QPoint &pos) noexcept { // Retrieves the selected item in the tree, and build the menu from its actions diff --git a/gui/ui/DataSource/DataSourceWidget.ui b/gui/ui/DataSource/DataSourceWidget.ui index 473ed3b..e5d6f22 100644 --- a/gui/ui/DataSource/DataSourceWidget.ui +++ b/gui/ui/DataSource/DataSourceWidget.ui @@ -14,19 +14,10 @@ Data sources - - 0 - - - 0 - - - 0 - - - 0 - + + +