diff --git a/src/Gui/CombiView.cpp b/src/Gui/CombiView.cpp index 38e6c62160..b6a887f6ce 100644 --- a/src/Gui/CombiView.cpp +++ b/src/Gui/CombiView.cpp @@ -64,10 +64,7 @@ CombiView::CombiView(Gui::Document* pcDocument, QWidget *parent) splitter->setOrientation(Qt::Vertical); // tree widget - tree = new TreeWidget(this); - //tree->setRootIsDecorated(false); - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/TreeView"); - tree->setIndentation(hGrp->GetInt("Indentation", tree->indentation())); + tree = new TreePanel(this); splitter->addWidget(tree); // property view diff --git a/src/Gui/CombiView.h b/src/Gui/CombiView.h index 1e4faa197b..4dc1cd70e1 100644 --- a/src/Gui/CombiView.h +++ b/src/Gui/CombiView.h @@ -39,6 +39,7 @@ namespace Gui { class TreeWidget; class PropertyView; class ProjectWidget; + class TreePanel; namespace PropertyEditor { class EditableListView; class EditableItem; @@ -97,7 +98,7 @@ protected: private: QTabWidget * tabs; Gui::PropertyView * prop; - QTreeView * tree; + Gui::TreePanel * tree; Gui::TaskView::TaskView * taskPanel; //Gui::ProjectWidget * projectView; }; diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index 2d197943fc..4fbea298a8 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -29,6 +29,7 @@ # include # include # include +# include # include # include # include @@ -55,6 +56,7 @@ #include "MainWindow.h" #include "View3DInventor.h" #include "View3DInventorViewer.h" +#include "Widgets.h" using namespace Gui; @@ -106,6 +108,12 @@ TreeWidget::TreeWidget(QWidget* parent) connect(this->markRecomputeAction, SIGNAL(triggered()), this, SLOT(onMarkRecompute())); + this->searchObjectsAction = new QAction(this); + this->searchObjectsAction->setText(tr("Search...")); + this->searchObjectsAction->setStatusTip(tr("Search for objects")); + connect(this->searchObjectsAction, SIGNAL(triggered()), + this, SLOT(onSearchObjects())); + // Setup connections Application::Instance->signalNewDocument.connect(boost::bind(&TreeWidget::slotNewDocument, this, _1)); Application::Instance->signalDeleteDocument.connect(boost::bind(&TreeWidget::slotDeleteDocument, this, _1)); @@ -183,6 +191,7 @@ void TreeWidget::contextMenuEvent (QContextMenuEvent * e) contextMenu.addAction(this->skipRecomputeAction); contextMenu.addAction(this->markRecomputeAction); contextMenu.addAction(this->createGroupAction); + contextMenu.addAction(this->searchObjectsAction); } else if (this->contextItem && this->contextItem->type() == ObjectType) { DocumentObjectItem* objitem = static_cast @@ -362,6 +371,11 @@ void TreeWidget::onMarkRecompute() } } +void TreeWidget::onSearchObjects() +{ + emitSearchObjects(); +} + void TreeWidget::onActivateDocument(QAction* active) { // activate the specified document @@ -912,7 +926,145 @@ void TreeWidget::setItemsSelected (const QList items, bool se // ---------------------------------------------------------------------------- +/* TRANSLATOR Gui::TreePanel */ + +TreePanel::TreePanel(QWidget* parent) + : QWidget(parent) +{ + this->treeWidget = new TreeWidget(this); + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/TreeView"); + this->treeWidget->setIndentation(hGrp->GetInt("Indentation", this->treeWidget->indentation())); + + QVBoxLayout* pLayout = new QVBoxLayout(this); + pLayout->setSpacing(0); + pLayout->setMargin (0); + pLayout->addWidget(this->treeWidget); + connect(this->treeWidget, SIGNAL(emitSearchObjects()), + this, SLOT(showEditor())); + + this->searchBox = new Gui::ClearLineEdit(this); + pLayout->addWidget(this->searchBox); + this->searchBox->hide(); + this->searchBox->installEventFilter(this); +#if QT_VERSION >= 0x040700 + this->searchBox->setPlaceholderText(tr("Search")); +#endif + connect(this->searchBox, SIGNAL(returnPressed()), + this, SLOT(accept())); + connect(this->searchBox, SIGNAL(textEdited(QString)), + this, SLOT(findMatchingItems(QString))); +} + +TreePanel::~TreePanel() +{ +} + +void TreePanel::accept() +{ + QString text = this->searchBox->text(); + if (!text.isEmpty()) { + for (int i=0; itopLevelItemCount(); i++) { + selectTreeItem(treeWidget->topLevelItem(i), text); + } + } + hideEditor(); +} + +bool TreePanel::eventFilter(QObject *obj, QEvent *ev) +{ + if (obj != this->searchBox) + return false; + + if (ev->type() == QEvent::KeyPress) { + bool consumed = false; + int key = static_cast(ev)->key(); + switch (key) { + case Qt::Key_Escape: + hideEditor(); + consumed = true; + break; + + default: + break; + } + + return consumed; + } + + return false; +} + +void TreePanel::showEditor() +{ + this->searchBox->show(); + this->searchBox->setFocus(); +} + +void TreePanel::hideEditor() +{ + this->searchBox->clear(); + this->searchBox->hide(); + for (int i=0; itopLevelItemCount(); i++) { + resetBackground(treeWidget->topLevelItem(i)); + } +} + +void TreePanel::findMatchingItems(const QString& text) +{ + if (text.isEmpty()) { + for (int i=0; itopLevelItemCount(); i++) { + resetBackground(treeWidget->topLevelItem(i)); + } + } + else { + for (int i=0; itopLevelItemCount(); i++) { + searchTreeItem(treeWidget->topLevelItem(i), text); + } + } +} + +void TreePanel::searchTreeItem(QTreeWidgetItem* item, const QString& text) +{ + for (int i=0; ichildCount(); i++) { + QTreeWidgetItem* child = item->child(i); + child->setBackground(0, QBrush()); + child->setExpanded(false); + if (child->text(0).indexOf(text, 0, Qt::CaseInsensitive) >= 0) { + child->setBackground(0, QColor(255, 255, 0, 100)); + QTreeWidgetItem* parent = child->parent(); + while (parent) { + parent->setExpanded(true); + parent = parent->parent(); + } + } + searchTreeItem(child, text); + } +} + +void TreePanel::selectTreeItem(QTreeWidgetItem* item, const QString& text) +{ + for (int i=0; ichildCount(); i++) { + QTreeWidgetItem* child = item->child(i); + if (child->text(0).indexOf(text, 0, Qt::CaseInsensitive) >= 0) { + child->setSelected(true); + } + selectTreeItem(child, text); + } +} + +void TreePanel::resetBackground(QTreeWidgetItem* item) +{ + for (int i=0; ichildCount(); i++) { + QTreeWidgetItem* child = item->child(i); + child->setBackground(0, QBrush()); + resetBackground(child); + } +} + +// ---------------------------------------------------------------------------- + /* TRANSLATOR Gui::TreeDockWidget */ + TreeDockWidget::TreeDockWidget(Gui::Document* pcDocument,QWidget *parent) : DockWindow(pcDocument,parent) { diff --git a/src/Gui/Tree.h b/src/Gui/Tree.h index cc45a2c4e3..e3c20c8a9b 100644 --- a/src/Gui/Tree.h +++ b/src/Gui/Tree.h @@ -32,6 +32,7 @@ #include #include +class QLineEdit; namespace Gui { @@ -106,6 +107,7 @@ protected Q_SLOTS: void onFinishEditing(); void onSkipRecompute(bool on); void onMarkRecompute(); + void onSearchObjects(); private Q_SLOTS: void onItemSelectionChanged(void); @@ -114,6 +116,9 @@ private Q_SLOTS: void onItemExpanded(QTreeWidgetItem * item); void onTestStatus(void); +Q_SIGNALS: + void emitSearchObjects(); + private: void slotNewDocument(const Gui::Document&); void slotDeleteDocument(const Gui::Document&); @@ -129,6 +134,7 @@ private: QAction* finishEditingAction; QAction* skipRecomputeAction; QAction* markRecomputeAction; + QAction* searchObjectsAction; QTreeWidgetItem* contextItem; QTreeWidgetItem* rootItem; @@ -237,6 +243,32 @@ private: friend class DocumentItem; }; +class TreePanel : public QWidget +{ + Q_OBJECT + +public: + TreePanel(QWidget* parent=nullptr); + virtual ~TreePanel(); + + bool eventFilter(QObject *obj, QEvent *ev); + +private Q_SLOTS: + void accept(); + void showEditor(); + void hideEditor(); + void findMatchingItems(const QString&); + +private: + void searchTreeItem(QTreeWidgetItem* item, const QString& text); + void selectTreeItem(QTreeWidgetItem* item, const QString& text); + void resetBackground(QTreeWidgetItem* item); + +private: + QLineEdit* searchBox; + QTreeWidget* treeWidget; +}; + /** * The dock window containing the tree view. * @author Werner Mayer