From 7d00b49f914b4d36331df163cd8e9fe1233c53cb Mon Sep 17 00:00:00 2001 From: Mirko Waechter <mirko.waechter@kit.edu> Date: Wed, 15 Jun 2016 17:54:35 +0200 Subject: [PATCH] refactored and improved treeview search --- .../StateTreeController.cpp | 78 +----------- .../StateTreeController.h | 16 +-- .../libraries/ArmarXGuiBase/CMakeLists.txt | 3 + .../widgets/InfixFilterModel.cpp | 117 ++++++++++++++++++ .../ArmarXGuiBase/widgets/InfixFilterModel.h | 60 +++++++++ 5 files changed, 188 insertions(+), 86 deletions(-) create mode 100644 source/ArmarXGui/libraries/ArmarXGuiBase/widgets/InfixFilterModel.cpp create mode 100644 source/ArmarXGui/libraries/ArmarXGuiBase/widgets/InfixFilterModel.h diff --git a/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StateTreeController.cpp b/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StateTreeController.cpp index 69ad4119..a3eb8fe6 100644 --- a/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StateTreeController.cpp +++ b/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StateTreeController.cpp @@ -71,7 +71,7 @@ StateTreeController::StateTreeController(Ice::CommunicatorPtr ic, VariantInfoPtr this->communicator = ic; - proxyModel = new StateFilterModel(this); + proxyModel = new InfixFilterModel(this); proxyModel->setSourceModel(this); proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); treeView->setModel(proxyModel); @@ -170,7 +170,7 @@ StateTreeController::StateTreeController(Ice::CommunicatorPtr ic, VariantInfoPtr connect(actionGroupProperties, SIGNAL(triggered()), this, SLOT(onGroupProperties())); connect(filterLineEdit, SIGNAL(textChanged(QString)), proxyModel, SLOT(setFilterFixedString(QString))); - connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(expandAll(QString))); + connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(expandFilterResults(QString))); } StateTreeController::~StateTreeController() @@ -1418,39 +1418,14 @@ void StateTreeController::stateAddedOrRemoved() treeView->repaint(); } -void StateTreeController::expandAll(const QString& filterString) +void StateTreeController::expandFilterResults(const QString& filterString) { if (filterString.length() == 0) { return; } - treeView->collapseAll(); - - QList<QModelIndex> indexList; - for (int i = 0; i < proxyModel->rowCount(); ++i) - { - indexList << proxyModel->index(i, 0); - } - while (indexList.size() > 0) - { - QModelIndex& index = indexList.front(); - if (proxyModel->data(index).toString().contains(proxyModel->filterRegExp())) - { - if (index.parent().isValid()) - { - treeView->expand(index.parent()); - } - } - int i = 0; - - while (index.child(i, 0).isValid()) - { - indexList << index.child(i, 0); - i++; - } - indexList.pop_front(); - } + InfixFilterModel::ExpandFilterResults(treeView); } @@ -1607,48 +1582,3 @@ bool StateTreeController::StateMimeData::isPublic() const return stateTreeModel->getNodeByState(this->state)->isPublic(); } - -bool StateFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const -{ - - QModelIndex index0 = sourceModel()->index(source_row, 0, source_parent); - QList<QModelIndex> indexList; - indexList << index0; - auto checkIndex = [this](QModelIndex index) - { - return sourceModel()->data(index).toString().contains(filterRegExp()); - }; - // if (checkIndex(index0)) - // { - // ARMARX_INFO_S << "Direct hit " << sourceModel()->data(index0).toString().toStdString() << LogSender::CreateBackTrace(); - // emit matchedItem(mapFromSource(index0)); // this is a direct match -> expand treeview to this - // } - - while (indexList.size() > 0) - { - QModelIndex& index = indexList.front(); - if (checkIndex(index)) - { - return true; - } - int i = 0; - - while (index.child(i, 0).isValid()) - { - indexList << index.child(i, 0); - i++; - } - indexList.pop_front(); - } - QModelIndex parent = source_parent; - while (parent.isValid()) - { - if (sourceModel()->data(parent).toString().contains(filterRegExp())) - { - return true; - } - parent = parent.parent(); - - } - return false; -} diff --git a/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StateTreeController.h b/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StateTreeController.h index 8547a6ac..028ed127 100644 --- a/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StateTreeController.h +++ b/source/ArmarXGui/gui-plugins/StatechartEditorPlugin/StateTreeController.h @@ -40,6 +40,7 @@ #include <ArmarXCore/statechart/xmlstates/profiles/StatechartProfiles.h> #include <ArmarXGui/gui-plugins/StatechartEditorPlugin/cloning/GroupCloner.h> #include <ArmarXGui/gui-plugins/StatechartEditorPlugin/renaming/GroupRenamer.h> +#include <ArmarXGui/libraries/ArmarXGuiBase/widgets/InfixFilterModel.h> class QProcess; @@ -50,16 +51,7 @@ namespace armarx typedef boost::shared_ptr<StatechartProfiles> StatechartProfilesPtr; - class StateFilterModel : - public QSortFilterProxyModel - { - Q_OBJECT - public: - StateFilterModel(QObject* parent = 0) : QSortFilterProxyModel(parent) {} - // QSortFilterProxyModel interface - protected: - bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const; - }; + class StateTreeController; @@ -151,7 +143,7 @@ namespace armarx void processOutputReady(); void processErrorsReady(); void stateAddedOrRemoved(); - void expandAll(const QString& filterString); + void expandFilterResults(const QString& filterString); private: QModelIndex getIndex(StateTreeNodePtr node); @@ -161,7 +153,7 @@ namespace armarx QList<QVariant> headerInfo; QTreeView* treeView; StateTreeModelPtr stateTreeModel; - StateFilterModel* proxyModel; + InfixFilterModel* proxyModel; GroupClonerPtr groupCloner; GroupRenamerPtr groupRenamer; StatechartGroupPtr activeGroup; diff --git a/source/ArmarXGui/libraries/ArmarXGuiBase/CMakeLists.txt b/source/ArmarXGui/libraries/ArmarXGuiBase/CMakeLists.txt index 2d87959e..84fbb67b 100644 --- a/source/ArmarXGui/libraries/ArmarXGuiBase/CMakeLists.txt +++ b/source/ArmarXGui/libraries/ArmarXGuiBase/CMakeLists.txt @@ -36,6 +36,7 @@ set(LIB_FILES ArmarXWidgetController.cpp widgets/cpp-markdown/markdown.cpp widgets/cpp-markdown/markdown-tokens.cpp widgets/TipDialog.cpp + widgets/InfixFilterModel.cpp ) set(LIB_HEADERS ArmarXGuiInterface.h @@ -52,6 +53,7 @@ set(LIB_HEADERS ArmarXGuiInterface.h widgets/cpp-markdown/markdown.h widgets/cpp-markdown/markdown-tokens.h widgets/TipDialog.h + widgets/InfixFilterModel.h ) set(GUI_UIS @@ -74,6 +76,7 @@ qt4_wrap_cpp(LIB_FILES widgets/JoystickControlWidget.h widgets/MarkdownEditor.h widgets/TipDialog.h + widgets/InfixFilterModel.h ) qt4_wrap_ui(UI_HEADER ${GUI_UIS}) diff --git a/source/ArmarXGui/libraries/ArmarXGuiBase/widgets/InfixFilterModel.cpp b/source/ArmarXGui/libraries/ArmarXGuiBase/widgets/InfixFilterModel.cpp new file mode 100644 index 00000000..380eef67 --- /dev/null +++ b/source/ArmarXGui/libraries/ArmarXGuiBase/widgets/InfixFilterModel.cpp @@ -0,0 +1,117 @@ +/* + * This file is part of ArmarX. + * + * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package ArmarX + * @author Mirko Waechter( mirko.waechter at kit dot edu) + * @date 2016 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ +#include "InfixFilterModel.h" +#include <ArmarXCore/core/logging/Logging.h> +#include <QTreeView> + +namespace armarx +{ + + + InfixFilterModel::InfixFilterModel(QObject* parent) : QSortFilterProxyModel(parent) + { + + } + + void InfixFilterModel::ExpandFilterResults(QTreeView* treeView) + { + if (!treeView) + { + return; + } + treeView->collapseAll(); + QSortFilterProxyModel* proxyModel = qobject_cast<QSortFilterProxyModel*>(treeView->model()); + if (!proxyModel) + { + ARMARX_WARNING_S << "Could not cast treeview model to proxymodel!"; + return; + } + QList<QModelIndex> indexList; + for (int i = 0; i < proxyModel->rowCount(); ++i) + { + indexList << proxyModel->index(i, 0); + } + while (indexList.size() > 0) + { + QModelIndex& index = indexList.front(); + if (proxyModel->data(index).toString().contains(proxyModel->filterRegExp())) + { + if (index.parent().isValid()) + { + treeView->expand(index.parent()); + } + } + int i = 0; + + while (index.child(i, 0).isValid()) + { + indexList << index.child(i, 0); + i++; + } + indexList.pop_front(); + } + } + + bool InfixFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const + { + + QModelIndex index0 = sourceModel()->index(source_row, 0, source_parent); + QList<QModelIndex> indexList; + indexList << index0; + auto checkIndex = [this](QModelIndex index) + { + return sourceModel()->data(index).toString().contains(filterRegExp()); + }; + + while (indexList.size() > 0) + { + QModelIndex& index = indexList.front(); + if (checkIndex(index)) + { + return true; + } + int i = 0; + + while (index.child(i, 0).isValid()) + { + indexList << index.child(i, 0); + i++; + } + indexList.pop_front(); + } + QModelIndex parent = source_parent; + while (parent.isValid()) + { + if (sourceModel()->data(parent).toString().contains(filterRegExp())) + { + return true; + } + parent = parent.parent(); + + } + return false; + } + + +} // namespace armarx diff --git a/source/ArmarXGui/libraries/ArmarXGuiBase/widgets/InfixFilterModel.h b/source/ArmarXGui/libraries/ArmarXGuiBase/widgets/InfixFilterModel.h new file mode 100644 index 00000000..9fae2ec7 --- /dev/null +++ b/source/ArmarXGui/libraries/ArmarXGuiBase/widgets/InfixFilterModel.h @@ -0,0 +1,60 @@ +/* + * This file is part of ArmarX. + * + * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package ArmarX + * @author Mirko Waechter( mirko.waechter at kit dot edu) + * @date 2016 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ +#ifndef H_ARMARX_INFIXFILTERMODEL_H +#define H_ARMARX_INFIXFILTERMODEL_H + +#include <QObject> +#include <QSortFilterProxyModel> + +class QTreeView; + +namespace armarx +{ + + /** + * @brief This proxy model reimplements the filterAcceptsRow function with a new behavior: + * All elements that fit the filter string are shown alongside with all their parents as well as all their children. + * This means the full sub-tree which contains matching elements is shown. + * + */ + class InfixFilterModel : + public QSortFilterProxyModel + { + Q_OBJECT + public: + InfixFilterModel(QObject* parent = 0); + // QSortFilterProxyModel interface + /** + * @brief Expands the treeview that all items that match the filterstring are expanded and directly visible. + * Anything else is collapsed. + * @param treeView + */ + static void ExpandFilterResults(QTreeView* treeView); + protected: + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const; + }; + +} + +#endif -- GitLab