From 068002d966878c1c22c2e8300d7b9037de3d5608 Mon Sep 17 00:00:00 2001 From: Utkarsh Ayachit Date: Mon, 13 Feb 2017 16:11:16 -0500 Subject: [PATCH 1/6] Show all blocks in a MB in Spreadsheet view. Updated Spreadsheet3 test (which tested multiblock). Addresses #17162. --- .../ParaView/Testing/XML/SpreadSheet3.xml | 18 ++++++++---------- .../Resources/views_and_representations.xml | 4 +++- .../Testing/LagrangianSurfaceHelperNone.xml | 1 + Testing/Data/Baseline/SpreadSheet3.png.md5 | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Applications/ParaView/Testing/XML/SpreadSheet3.xml b/Applications/ParaView/Testing/XML/SpreadSheet3.xml index 75c49e5486..1b28fc0776 100644 --- a/Applications/ParaView/Testing/XML/SpreadSheet3.xml +++ b/Applications/ParaView/Testing/XML/SpreadSheet3.xml @@ -47,16 +47,13 @@ - - - - - - - - - - + + + + + + + @@ -68,4 +65,5 @@ + diff --git a/ParaViewCore/ServerManager/SMApplication/Resources/views_and_representations.xml b/ParaViewCore/ServerManager/SMApplication/Resources/views_and_representations.xml index 12fb9b00fe..985d675195 100644 --- a/ParaViewCore/ServerManager/SMApplication/Resources/views_and_representations.xml +++ b/ParaViewCore/ServerManager/SMApplication/Resources/views_and_representations.xml @@ -7365,9 +7365,11 @@ command="AddCompositeDataSetIndex" name="CompositeDataSetIndex" number_of_elements_per_command="1" + number_of_elements="1" + default_values="0" panel_visibility="default" repeat_command="1"> - + diff --git a/Plugins/LagrangianParticleTracker/Testing/LagrangianSurfaceHelperNone.xml b/Plugins/LagrangianParticleTracker/Testing/LagrangianSurfaceHelperNone.xml index 6ca6e43755..b977b68614 100644 --- a/Plugins/LagrangianParticleTracker/Testing/LagrangianSurfaceHelperNone.xml +++ b/Plugins/LagrangianParticleTracker/Testing/LagrangianSurfaceHelperNone.xml @@ -23,6 +23,7 @@ + diff --git a/Testing/Data/Baseline/SpreadSheet3.png.md5 b/Testing/Data/Baseline/SpreadSheet3.png.md5 index c79763d491..4640b0a8c2 100644 --- a/Testing/Data/Baseline/SpreadSheet3.png.md5 +++ b/Testing/Data/Baseline/SpreadSheet3.png.md5 @@ -1 +1 @@ -044dca08db93e83b1f09bf4c4a440b8d +305ae44caff67b97e798d1a71b3475ae -- GitLab From 5eac992d73d633cd9fc44121ab59cc165c80bba7 Mon Sep 17 00:00:00 2001 From: Utkarsh Ayachit Date: Fri, 7 Apr 2017 11:37:20 -0400 Subject: [PATCH 2/6] Fix `delete/delete[]` mismatch. --- .../pqIntegrationModelSurfaceHelperWidget.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/LagrangianParticleTracker/pqIntegrationModelSurfaceHelperWidget.cxx b/Plugins/LagrangianParticleTracker/pqIntegrationModelSurfaceHelperWidget.cxx index 9fb8802792..3d7b55fdbe 100644 --- a/Plugins/LagrangianParticleTracker/pqIntegrationModelSurfaceHelperWidget.cxx +++ b/Plugins/LagrangianParticleTracker/pqIntegrationModelSurfaceHelperWidget.cxx @@ -158,7 +158,7 @@ void pqIntegrationModelSurfaceHelperWidget::resetSurfaceWidget(bool force) gb->setProperty("name", arrayName); gb->setProperty("type", type); QObject::connect(gb, SIGNAL(toggled(bool)), this, SIGNAL(arrayToGenerateChanged())); - delete labelName; + delete[] labelName; // And associated layout QGridLayout* gbLayout = new QGridLayout(gb); -- GitLab From 8e69415dc1ea2d6790b956ea9bb8d14d7f5b22fb Mon Sep 17 00:00:00 2001 From: Utkarsh Ayachit Date: Mon, 17 Apr 2017 23:27:57 -0400 Subject: [PATCH 3/6] Fix sizing logic in pqTreeView. Making pqTreeView consider the full tree hierarchy rather than just the top-level items to determine widget size. --- Qt/Widgets/pqTreeView.cxx | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/Qt/Widgets/pqTreeView.cxx b/Qt/Widgets/pqTreeView.cxx index 5ae2c059dd..b13079388e 100644 --- a/Qt/Widgets/pqTreeView.cxx +++ b/Qt/Widgets/pqTreeView.cxx @@ -43,6 +43,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +namespace +{ +int pqCountItems(QAbstractItemModel* model, const QModelIndex& idx, int max) +{ + int numItems = model->rowCount(idx); + int count = numItems; + for (int cc = 0; cc < numItems; ++cc) + { + if (count >= max) + { + return count; + } + count += pqCountItems(model, model->index(cc, 0, idx), max - numItems); + } + return count; +} +} + pqTreeView::pqTreeView(QWidget* widgetParent) : QTreeView(widgetParent) , ScrollPadding(0) @@ -121,13 +139,9 @@ QSize pqTreeView::sizeHint() const // add padding for the scrollbar int extra = this->ScrollPadding; - int num = 0; - QAbstractItemModel* current = this->model(); - if (current) - { - num = current->rowCount(this->rootIndex()); - } - + QAbstractItemModel* dmodel = this->model(); + QModelIndex idx = this->rootIndex(); + int num = pqCountItems(dmodel, idx, maxItemHint); if (num >= maxItemHint) { extra = 0; -- GitLab From 0aa1015f35c713868e85f0f09fdcb105227b6a4d Mon Sep 17 00:00:00 2001 From: Utkarsh Ayachit Date: Wed, 19 Apr 2017 11:21:45 -0400 Subject: [PATCH 4/6] Preserve header state in pqTreeView. --- Qt/Widgets/pqTreeView.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Qt/Widgets/pqTreeView.cxx b/Qt/Widgets/pqTreeView.cxx index b13079388e..ca67fc805c 100644 --- a/Qt/Widgets/pqTreeView.cxx +++ b/Qt/Widgets/pqTreeView.cxx @@ -70,6 +70,7 @@ pqTreeView::pqTreeView(QWidget* widgetParent) // Change the default header view to a checkable one. pqCheckableHeaderView* checkable = new pqCheckableHeaderView(Qt::Horizontal, this); + checkable->setStretchLastSection(this->header()->stretchLastSection()); this->setHeader(checkable); this->installEventFilter(checkable); #if QT_VERSION >= 0x050000 -- GitLab From e50c56efd387b6a3cd0050959cd49667daa575fb Mon Sep 17 00:00:00 2001 From: Utkarsh Ayachit Date: Wed, 19 Apr 2017 11:40:51 -0400 Subject: [PATCH 5/6] Fix AMR dataset detecion in pqQueryClauseWidget. pqQueryClauseWidget was not detecting newer AMR types as AMR. Cleanup that code. --- Qt/Components/pqQueryClauseWidget.cxx | 33 +++++++++++++++++++-------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/Qt/Components/pqQueryClauseWidget.cxx b/Qt/Components/pqQueryClauseWidget.cxx index 5dafeccf12..7ba776bb9b 100644 --- a/Qt/Components/pqQueryClauseWidget.cxx +++ b/Qt/Components/pqQueryClauseWidget.cxx @@ -79,6 +79,25 @@ public: } } }; + +bool isAMR(vtkPVDataInformation* dinfo) +{ + switch (dinfo->GetCompositeDataSetType()) + { + case VTK_HIERARCHICAL_BOX_DATA_SET: + case VTK_HIERARCHICAL_DATA_SET: + case VTK_UNIFORM_GRID_AMR: + case VTK_NON_OVERLAPPING_AMR: + case VTK_OVERLAPPING_AMR: + return true; + } + return false; +} + +bool isMultiBlock(vtkPVDataInformation* dinfo) +{ + return dinfo->GetCompositeDataSetType() == VTK_MULTIBLOCK_DATA_SET; +} } // BUG #13806, remove collective operations temporarily since they don't work @@ -258,14 +277,14 @@ void pqQueryClauseWidget::populateSelectionCriteria(pqQueryClauseWidget::Criteri this->Internals->criteria->addItem("Query", QUERY); } - if (dataInfo->GetCompositeDataSetType() == VTK_MULTIBLOCK_DATA_SET) + if (isMultiBlock(dataInfo)) { if (type_flags & BLOCK) { this->Internals->criteria->addItem("Block ID", BLOCK); } } - else if (dataInfo->GetCompositeDataSetType() == VTK_HIERARCHICAL_BOX_DATA_SET) + else if (isAMR(dataInfo)) { if (type_flags & AMR_LEVEL) { @@ -415,14 +434,8 @@ void pqQueryClauseWidget::updateDependentClauseWidgets() #endif vtkPVDataInformation* dataInfo = this->producer()->getDataInformation(); - if (dataInfo->GetCompositeDataSetType() == VTK_MULTIBLOCK_DATA_SET) - { - multi_block = true; - } - else if (dataInfo->GetCompositeDataSetType() == VTK_HIERARCHICAL_BOX_DATA_SET) - { - amr = true; - } + multi_block = isMultiBlock(dataInfo); + amr = isAMR(dataInfo); QVBoxLayout* vbox = qobject_cast(this->layout()); -- GitLab From 3186c7c8d830bf8126ca681b27c4067bbeff7436 Mon Sep 17 00:00:00 2001 From: Utkarsh Ayachit Date: Fri, 7 Apr 2017 16:56:01 -0400 Subject: [PATCH 6/6] Cleanup widget for vtkSMCompositeTreeDomain. Cleaning up code used to create the default widget on the Properites panel. Added a new pqCompositeDataInformationTreeModel model that works with vtkPVDataInformation to show the composite tree. The new pqCompositeTreePropertyWidget uses this model rather than pqSignalAdaptorCompositeTreeWidget. pqSignalAdaptorCompositeTreeWidget is now removed since it was convoluted and tried to do too many things and hence caused issues. Signal adaptors will be removed as we continue such cleanups and remove old property panel widgets. vtkSMCompositeTreeDomain has been extended to better indicate the type of ids expected on the property i.e. whether a flat index, or AMR level or AMR level/block index is expected. Addresses #17382, #17175. --- .../Core/vtkSMCompositeTreeDomain.cxx | 28 +- .../Core/vtkSMCompositeTreeDomain.h | 52 +- .../SMApplication/Resources/filters.xml | 12 +- Qt/Components/CMakeLists.txt | 11 +- .../UI/pqQueryCompositeTreeDialog.ui | 16 +- .../pqCompositeDataInformationTreeModel.cxx | 661 +++++++++++++ .../pqCompositeDataInformationTreeModel.h | 178 ++++ .../pqCompositeTreePropertyWidget.cxx | 236 +++++ Qt/Components/pqCompositeTreePropertyWidget.h | 96 ++ Qt/Components/pqIntVectorPropertyWidget.cxx | 46 +- Qt/Components/pqIntVectorPropertyWidget.h | 12 +- Qt/Components/pqProxyWidget.cxx | 2 +- Qt/Components/pqQueryClauseWidget.cxx | 97 +- .../pqSignalAdaptorCompositeTreeWidget.cxx | 874 ------------------ .../pqSignalAdaptorCompositeTreeWidget.h | 262 ------ 15 files changed, 1342 insertions(+), 1241 deletions(-) create mode 100644 Qt/Components/pqCompositeDataInformationTreeModel.cxx create mode 100644 Qt/Components/pqCompositeDataInformationTreeModel.h create mode 100644 Qt/Components/pqCompositeTreePropertyWidget.cxx create mode 100644 Qt/Components/pqCompositeTreePropertyWidget.h delete mode 100644 Qt/Components/pqSignalAdaptorCompositeTreeWidget.cxx delete mode 100644 Qt/Components/pqSignalAdaptorCompositeTreeWidget.h diff --git a/ParaViewCore/ServerManager/Core/vtkSMCompositeTreeDomain.cxx b/ParaViewCore/ServerManager/Core/vtkSMCompositeTreeDomain.cxx index 40d4b1044c..5fee068a3a 100644 --- a/ParaViewCore/ServerManager/Core/vtkSMCompositeTreeDomain.cxx +++ b/ParaViewCore/ServerManager/Core/vtkSMCompositeTreeDomain.cxx @@ -141,13 +141,20 @@ int vtkSMCompositeTreeDomain::ReadXMLAttributes(vtkSMProperty* prop, vtkPVXMLEle { this->Mode = LEAVES; } + else if (strcmp(mode, "amr") == 0) + { + this->Mode = AMR; + } else if (strcmp(mode, "non-leaves") == 0) { - this->Mode = NON_LEAVES; + vtkWarningMacro("Obsolete 'non-leaves' mode detected. Using 'all' instead."); + this->Mode = ALL; } else if (strcmp(mode, "none") == 0) { - this->Mode = NONE; + // not sure why this mode was ever added or what it stood for <|:0). + vtkWarningMacro("Obsolete 'none' mode detected. Using 'all' instead."); + this->Mode = ALL; } else { @@ -155,6 +162,7 @@ int vtkSMCompositeTreeDomain::ReadXMLAttributes(vtkSMProperty* prop, vtkPVXMLEle return 0; } } + if (const char* default_mode = element->GetAttribute("default_mode")) { if (strcmp(default_mode, "nonempty-leaf") == 0) @@ -167,6 +175,18 @@ int vtkSMCompositeTreeDomain::ReadXMLAttributes(vtkSMProperty* prop, vtkPVXMLEle return 0; } } + + if (vtkPVXMLElement* hints = prop->GetHints()) + { + vtkPVXMLElement* useFlatIndex = hints->FindNestedElementByName("UseFlatIndex"); + if (useFlatIndex && useFlatIndex->GetAttribute("value") && + strcmp(useFlatIndex->GetAttribute("value"), "0") == 0) + { + this->Mode = AMR; + vtkWarningMacro("'UseFlatIndex' index hint is deprecated. You may simply want " + "to set the 'mode' for the domain to 'amr' in the XML configuration."); + } + } return 1; } @@ -231,8 +251,8 @@ void vtkSMCompositeTreeDomain::PrintSelf(ostream& os, vtkIndent indent) case NON_LEAVES: os << "NON_LEAVES"; break; - case NONE: - os << "NONE"; + case AMR: + os << "AMR"; default: os << "UNKNOWN"; } diff --git a/ParaViewCore/ServerManager/Core/vtkSMCompositeTreeDomain.h b/ParaViewCore/ServerManager/Core/vtkSMCompositeTreeDomain.h index d8a427239b..f8344faaaf 100644 --- a/ParaViewCore/ServerManager/Core/vtkSMCompositeTreeDomain.h +++ b/ParaViewCore/ServerManager/Core/vtkSMCompositeTreeDomain.h @@ -21,20 +21,42 @@ * vtkSMCompositeTreeDomain can be added to a vtkSMIntVectorProperty. This * domain requires a vtkSMInputProperty which is used to provide the input to * the filter. This domain obtains data information from the input selected on - * the required input property and then decides the range for the flat-index. A - * flat index for a tree is obtained by performing a pre-order traversal of the - * tree eg. A ( B ( D, E), C (F, G)) becomes: [A,B,D,E,C,F,G], so flat-index of A is - * 0, while flat-index of C is 4. + * the required input property and then decides the range for values the + * property can have. * - * vtkSMCompositeTreeDomain can be used in multiple modes. - * \li ALL : This mode is used if the property can accept any type of node index. - * To select this mode in XML, use the `mode="all"`. - * \li LEAVES: This mode is used if the property can only accept leaf nodes i.e. - * indices for non-composite datasets. This is specified in XML - * using `mode="leaves"`. - * \li NON_LEAVES: This mode is used if the property can only accept non-leaf - * node indices, specified using `mode="non-leaves"` in XML - * configuration. + * Broadly speaking, there are two ways of identifying unique node in a + * composite dataset: `flat-index` (also called `composite-index`) and + * `level-block-index`. `flat-index` applies to all types of composite + * datasets while `level-block-index` (or just `level-index`) applies only to AMR + * datasets. `flat-index` for any node in an arbitrary composite-dataset + * is simply the index of that node in a pre-order traversal of the tree with + * the root composite-dataset getting the index 0. `level-index` for an AMR + * dataset is the AMR level number while `level-block-index` is a pair of + * the AMR level number and block number for the node in that level. + * + * The type of index the property expects, is defined by the domain's mode. + * Supported modes are: + * -# vtkSMCompositeTreeDomain::ALL: (default) \n + * The property uses `flat-index` and can accept index for any node (leaf or non-leaf). + * This can be specified in XML using the `mode="all"`. + * + * -# vtkSMCompositeTreeDomain::LEAVES:\n + * The property uses `flat-index` however can only accept flat-indices for + * leaf-nodes. + * This can be specified in XML using the `mode="leaves"`. + * + * -# vtkSMCompositeTreeDomain::AMR: \n + * The property uses `level-index` i.e. AMR level number or + * `level-block-index`. If the property has 2 elements (or for repeatable + * properties, if number of elements per command is 2) then + * `level-block-index` is used, otherwise simply the `level-index` is used. + * This only makes sense for filters dealing with AMR datasets. + * This can be specified in XML using the `mode="amr"`. + * + * -# vtkSMCompositeTreeDomain::NON_LEAVES: (deprecated)\n + * No longer supported (as of ParaView 5.4) and simply interpreted as + * vtkSMCompositeTreeDomain::ALL. + * This used to be specified in XML using the `mode="non-leaves"`. * * vtkSMCompositeTreeDomain also provides ability to set default value on the * property. If mode is LEAVES, then the default value selected is the first @@ -61,7 +83,6 @@ class vtkPVDataInformation; class vtkSMInputProperty; class vtkSMSourceProxy; -// TODO: CHANGE NAME OF THIS CLASS class VTKPVSERVERMANAGERCORE_EXPORT vtkSMCompositeTreeDomain : public vtkSMDomain { public: @@ -119,7 +140,8 @@ public: ALL = 0, LEAVES = 1, NON_LEAVES = 2, - NONE = 3 + NONE = 3, + AMR = 4, }; enum DefaultModes diff --git a/ParaViewCore/ServerManager/SMApplication/Resources/filters.xml b/ParaViewCore/ServerManager/SMApplication/Resources/filters.xml index 173af09783..c070c36e80 100644 --- a/ParaViewCore/ServerManager/SMApplication/Resources/filters.xml +++ b/ParaViewCore/ServerManager/SMApplication/Resources/filters.xml @@ -11146,16 +11146,8 @@ source. number_of_elements_per_command="1" panel_visibility="default" repeat_command="1"> - - - - - - @@ -11317,7 +11309,7 @@ source. name="SelectedDataSets" number_of_elements_per_command="2" repeat_command="1"> - - + false - - - Structure (Flat Index) - - + + true + @@ -40,9 +38,9 @@ - pqTreeWidget - QTreeWidget -
pqTreeWidget.h
+ pqTreeView + QTreeView +
pqTreeView.h
diff --git a/Qt/Components/pqCompositeDataInformationTreeModel.cxx b/Qt/Components/pqCompositeDataInformationTreeModel.cxx new file mode 100644 index 0000000000..a020e4fc6b --- /dev/null +++ b/Qt/Components/pqCompositeDataInformationTreeModel.cxx @@ -0,0 +1,661 @@ +/*========================================================================= + + Program: ParaView + Module: pqCompositeDataInformationTreeModel.cxx + + Copyright (c) 2005,2006 Sandia Corporation, Kitware Inc. + All rights reserved. + + ParaView is a free software; you can redistribute it and/or modify it + under the terms of the ParaView license version 1.2. + + See License_v1.2.txt for the full ParaView license. + A copy of this license can be obtained by contacting + Kitware Inc. + 28 Corporate Drive + Clifton Park, NY 12065 + USA + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +========================================================================*/ +#include "pqCompositeDataInformationTreeModel.h" + +#include "vtkDataObjectTypes.h" +#include "vtkPVCompositeDataInformation.h" +#include "vtkPVDataInformation.h" + +#include +#include + +#include + +namespace +{ +inline bool isroot(const QModelIndex& idx) +{ + return (idx.isValid() && idx.internalId() == 0); +} +} + +class pqCompositeDataInformationTreeModel::pqInternals +{ +public: + class CNode + { + typedef pqCompositeDataInformationTreeModel::pqInternals PType; + friend PType; + + QString Name; + unsigned int Index; + int DataType; + int NumberOfPieces; + CNode* Parent; + std::vector Children; + bool Checked; + Qt::CheckState CheckState; + + QModelIndex createIndex(pqCompositeDataInformationTreeModel* dmodel) + { + if (this->Parent) + { + return dmodel->createIndex( + this->Parent->childIndex(*this), 0, static_cast(this->flatIndex())); + } + else + { + return dmodel->createIndex(0, 0, static_cast(0)); + } + } + + void setChildrenCheckState(Qt::CheckState state, pqCompositeDataInformationTreeModel* dmodel) + { + for (auto iter = this->Children.begin(); iter != this->Children.end(); ++iter) + { + iter->CheckState = state; + iter->setChildrenCheckState(state, dmodel); + } + if (this->Children.size() > 0) + { + dmodel->dataChanged( + this->Children.front().createIndex(dmodel), this->Children.back().createIndex(dmodel)); + } + } + + void updateCheckState(pqCompositeDataInformationTreeModel* dmodel) + { + int state = 0; + for (auto iter = this->Children.begin(); iter != this->Children.end(); ++iter) + { + switch (iter->CheckState) + { + case Qt::Unchecked: + state |= 0x01; + break; + + case Qt::PartiallyChecked: + state |= 0x02; + break; + + case Qt::Checked: + state |= 0x04; + break; + } + } + Qt::CheckState target; + switch (state) + { + case 0x01: + case 0: + target = Qt::Unchecked; + break; + case 0x04: + target = Qt::Checked; + break; + + case 0x02: + default: + target = Qt::PartiallyChecked; + } + if (this->CheckState != target) + { + this->CheckState = target; + if (this->Parent) + { + this->Parent->updateCheckState(dmodel); + } + QModelIndex idx = this->createIndex(dmodel); + dmodel->dataChanged(idx, idx); + } + } + + CNode& find(unsigned int findex) + { + if (this->Index == findex) + { + return (*this); + } + for (auto iter = this->Children.begin(); iter != this->Children.end(); ++iter) + { + CNode& found = iter->find(findex); + if (found != PType::nullNode()) + { + return found; + } + } + return PType::nullNode(); + } + + public: + CNode() + : Index(VTK_UNSIGNED_INT_MAX) + , DataType(0) + , NumberOfPieces(-1) + , Parent(nullptr) + , Checked(false) + , CheckState(Qt::Unchecked) + { + } + ~CNode() {} + + bool operator==(const CNode& other) const + { + return this->Name == other.Name && this->Index == other.Index && + this->DataType == other.DataType && this->NumberOfPieces == other.NumberOfPieces && + this->Parent == other.Parent && this->Children == other.Children; + } + bool operator!=(const CNode& other) const { return !(*this == other); } + + void reset() { (*this) = PType::nullNode(); } + + int childrenCount() const + { + return this->NumberOfPieces >= 0 ? this->NumberOfPieces + : static_cast(this->Children.size()); + } + + unsigned int flatIndex() const { return this->Index; } + const QString& name() const { return this->Name; } + QString dataTypeAsString() const + { + return this->DataType == -1 ? "Unknown" + : vtkDataObjectTypes::GetClassNameFromTypeId(this->DataType); + } + + CNode& child(int idx) + { + return idx < static_cast(this->Children.size()) ? this->Children[idx] + : PType::nullNode(); + } + const CNode& child(int idx) const + { + return idx < static_cast(this->Children.size()) ? this->Children[idx] + : PType::nullNode(); + } + + int childIndex(const CNode& achild) const + { + for (size_t cc = 0, max = this->Children.size(); cc < max; ++cc) + { + if (this->Children[cc] == achild) + { + return cc; + } + } + } + const CNode& parent() const { return this->Parent ? *this->Parent : PType::nullNode(); } + + Qt::CheckState checkState() const { return this->CheckState; } + + bool setChecked(bool val, pqCompositeDataInformationTreeModel* dmodel) + { + if ((val == true && this->CheckState != Qt::Checked) || + (val == false && this->CheckState != Qt::Unchecked)) + { + this->CheckState = val ? Qt::Checked : Qt::Unchecked; + this->setChildrenCheckState(this->CheckState, dmodel); + if (this->Parent) + { + this->Parent->updateCheckState(dmodel); + } + + QModelIndex idx = this->createIndex(dmodel); + dmodel->dataChanged(idx, idx); + return true; + } + return false; + } + + void checkedNodes(QSet& set, bool leaves_only) const + { + if (this->checkState() == Qt::Unchecked) + { + // do nothing. + } + else if (this->checkState() == Qt::Checked && leaves_only == false) + { + set.insert(this->flatIndex()); + } + else + { + // partially checked or leaves_only. + for (auto iter = this->Children.begin(); iter != this->Children.end(); ++iter) + { + iter->checkedNodes(set, leaves_only); + } + } + } + }; + + pqInternals() {} + + ~pqInternals() {} + + static CNode& nullNode() { return NullNode; } + + CNode& find(const QModelIndex& idx) + { + if (!idx.isValid()) + { + return nullNode(); + } + + vtkIdType findex = static_cast(idx.internalId()); + return this->find(findex); + } + + CNode& find(unsigned int findex) + { + if (findex == VTK_UNSIGNED_INT_MAX) + { + return nullNode(); + } + + if (findex == 0) + { + return this->Root; + } + + return this->Root.find(findex); + } + + /** + * Builds the data-structure using vtkPVDataInformation (may be null). + * @returns true if the info refers to a composite dataset otherwise returns + * false. + */ + bool build(vtkPVDataInformation* info, bool expand_multi_piece = false) + { + unsigned int index = 0; + return this->build(info, expand_multi_piece, this->Root, index); + } + + CNode& rootNode() { return this->Root; } + +private: + bool build(vtkPVDataInformation* info, bool expand_multi_piece, CNode& node, unsigned int& index) + { + node.reset(); + node.Index = index++; + if (info == nullptr || info->GetCompositeDataClassName() == 0) + { + node.Name = info != nullptr ? info->GetPrettyDataTypeString() : ""; + node.DataType = info != nullptr ? info->GetDataSetType() : -1; + return false; + } + + node.Name = info->GetPrettyDataTypeString(); + node.DataType = info->GetCompositeDataSetType(); + + vtkPVCompositeDataInformation* cinfo = info->GetCompositeDataInformation(); + + bool is_amr = (node.DataType == VTK_HIERARCHICAL_DATA_SET || + node.DataType == VTK_HIERARCHICAL_BOX_DATA_SET || node.DataType == VTK_UNIFORM_GRID_AMR || + node.DataType == VTK_NON_OVERLAPPING_AMR || node.DataType == VTK_OVERLAPPING_AMR); + bool is_multipiece = cinfo->GetDataIsMultiPiece() != 0; + if (!is_multipiece || expand_multi_piece) + { + node.Children.resize(cinfo->GetNumberOfChildren()); + for (unsigned int cc = 0, max = cinfo->GetNumberOfChildren(); cc < max; ++cc) + { + CNode& childNode = node.Children[cc]; + this->build(cinfo->GetDataInformation(cc), expand_multi_piece, childNode, index); + // note: build() will reset childNode, so don't set any ivars before calling it. + childNode.Parent = &node; + // if Name for block was provided, use that instead of the data type. + const char* name = cinfo->GetName(cc); + if (name && name[0]) + { + childNode.Name = name; + } + else if (is_multipiece) + { + childNode.Name = QString("Dataset %1").arg(cc); + } + else if (is_amr) + { + childNode.Name = QString("Level %1").arg(cc); + } + } + } + return true; + } + +private: + CNode Root; + static CNode NullNode; +}; + +pqCompositeDataInformationTreeModel::pqInternals::CNode + pqCompositeDataInformationTreeModel::pqInternals::NullNode; + +//----------------------------------------------------------------------------- +pqCompositeDataInformationTreeModel::pqCompositeDataInformationTreeModel(QObject* parentObject) + : Superclass(parentObject) + , Internals(new pqCompositeDataInformationTreeModel::pqInternals()) + , UserCheckable(false) + , ExpandMultiPiece(false) + , Exclusivity(false) +{ +} + +//----------------------------------------------------------------------------- +pqCompositeDataInformationTreeModel::~pqCompositeDataInformationTreeModel() +{ +} + +//----------------------------------------------------------------------------- +int pqCompositeDataInformationTreeModel::columnCount(const QModelIndex&) const +{ + return 1; +} + +//----------------------------------------------------------------------------- +int pqCompositeDataInformationTreeModel::rowCount(const QModelIndex& parentIdx) const +{ + if (!parentIdx.isValid()) + { + // return number of top-level items. + return 1; + } + pqInternals& internals = (*this->Internals); + const pqInternals::CNode& node = internals.find(parentIdx); + assert(node.childrenCount() >= 0); + return node.childrenCount(); +} + +//----------------------------------------------------------------------------- +QModelIndex pqCompositeDataInformationTreeModel::index( + int row, int column, const QModelIndex& parentIdx) const +{ + if (!parentIdx.isValid() && row == 0 && column == 0) + { + return this->createIndex(0, 0, static_cast(0)); + } + + if (row < 0 || column < 0 || column >= this->columnCount()) + { + return QModelIndex(); + } + + pqInternals& internals = (*this->Internals); + const pqInternals::CNode& node = internals.find(parentIdx); + const pqInternals::CNode& child = node.child(row); + return this->createIndex(row, column, static_cast(child.flatIndex())); +} + +//----------------------------------------------------------------------------- +QModelIndex pqCompositeDataInformationTreeModel::parent(const QModelIndex& idx) const +{ + if (!idx.isValid() || isroot(idx)) + { + return QModelIndex(); + } + + pqInternals& internals = (*this->Internals); + const pqInternals::CNode& node = internals.find(idx); + const pqInternals::CNode& parentNode = node.parent(); + if (parentNode == internals.nullNode()) + { + return QModelIndex(); + } + + if (parentNode == internals.rootNode()) + { + return this->createIndex(0, 0, static_cast(0)); + } + + const pqInternals::CNode& parentsParentNode = parentNode.parent(); + return this->createIndex(parentsParentNode.childIndex(parentNode), idx.column(), + static_cast(parentNode.flatIndex())); +} + +//----------------------------------------------------------------------------- +QVariant pqCompositeDataInformationTreeModel::data(const QModelIndex& idx, int role) const +{ + if (!idx.isValid()) + { + return QVariant(); + } + + pqInternals& internals = (*this->Internals); + const pqInternals::CNode& node = internals.find(idx); + if (node == internals.nullNode()) + { + return QVariant(); + } + + switch (role) + { + case Qt::DisplayRole: + return node.name(); + + case Qt::ToolTipRole: + return QString("Name: %1
Type: %2") + .arg(node.name()) + .arg(node.dataTypeAsString()); + + case Qt::CheckStateRole: + return this->UserCheckable ? QVariant(node.checkState()) : QVariant(); + } + + return QVariant(); +} + +//----------------------------------------------------------------------------- +Qt::ItemFlags pqCompositeDataInformationTreeModel::flags(const QModelIndex& idx) const +{ + Qt::ItemFlags pflags = this->Superclass::flags(idx); + if (this->UserCheckable) + { + pflags |= Qt::ItemIsUserCheckable | Qt::ItemIsTristate; + } + + // can't use Qt::ItemIsAutoTristate till we drop support for Qt 4 :(. + return pflags; +} + +//----------------------------------------------------------------------------- +bool pqCompositeDataInformationTreeModel::setData( + const QModelIndex& idx, const QVariant& value, int role) +{ + if (!idx.isValid()) + { + return false; + } + + if (role != Qt::CheckStateRole) + { + return false; + } + + pqInternals& internals = (*this->Internals); + pqInternals::CNode& node = internals.find(idx); + if (node == internals.nullNode()) + { + return false; + } + + Qt::CheckState checkState = value.value(); + if (checkState == Qt::Checked && this->exclusivity()) + { + internals.rootNode().setChecked(false, this); + } + node.setChecked(checkState == Qt::Checked, this); + return true; +} + +//----------------------------------------------------------------------------- +QVariant pqCompositeDataInformationTreeModel::headerData( + int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && section == 0 && role == Qt::DisplayRole) + { + return this->HeaderLabel; + } + return this->Superclass::headerData(section, orientation, role); +} + +//----------------------------------------------------------------------------- +bool pqCompositeDataInformationTreeModel::setHeaderData( + int section, Qt::Orientation orientation, const QVariant& value, int role) +{ + if (orientation == Qt::Horizontal && section == 0 && role == Qt::DisplayRole) + { + this->HeaderLabel = value.toString(); + emit this->headerDataChanged(orientation, section, section); + return true; + } + return this->Superclass::setHeaderData(section, orientation, value, role); +} + +//----------------------------------------------------------------------------- +bool pqCompositeDataInformationTreeModel::reset(vtkPVDataInformation* info) +{ + pqInternals& internals = (*this->Internals); + + this->beginResetModel(); + bool retVal = internals.build(info, this->ExpandMultiPiece); + this->endResetModel(); + return retVal; +} + +//----------------------------------------------------------------------------- +void pqCompositeDataInformationTreeModel::setChecked(const QList& indices) +{ + pqInternals& internals = (*this->Internals); + pqInternals::CNode& root = internals.rootNode(); + root.setChecked(false, this); + + foreach (unsigned int findex, indices) + { + pqInternals::CNode& node = internals.find(findex); + node.setChecked(true, this); + } +} + +//----------------------------------------------------------------------------- +QList pqCompositeDataInformationTreeModel::checkedNodes() const +{ + QSet indices; + pqInternals& internals = (*this->Internals); + internals.rootNode().checkedNodes(indices, false); + return indices.toList(); +} + +//----------------------------------------------------------------------------- +QList pqCompositeDataInformationTreeModel::checkedLeaves() const +{ + QSet indices; + pqInternals& internals = (*this->Internals); + internals.rootNode().checkedNodes(indices, true); + return indices.toList(); +} + +//----------------------------------------------------------------------------- +QList pqCompositeDataInformationTreeModel::checkedLevels() const +{ + QList indices; + pqInternals& internals = (*this->Internals); + pqInternals::CNode& root = internals.rootNode(); + for (int cc = 0; cc < root.childrenCount(); cc++) + { + if (root.child(cc).checkState() == Qt::Checked) + { + indices.push_back(static_cast(cc)); + } + } + return indices; +} + +//----------------------------------------------------------------------------- +void pqCompositeDataInformationTreeModel::setCheckedLevels(const QList& indices) +{ + pqInternals& internals = (*this->Internals); + pqInternals::CNode& root = internals.rootNode(); + root.setChecked(false, this); + + int childrenCount = root.childrenCount(); + foreach (unsigned int idx, indices) + { + if (idx < childrenCount) + { + root.child(idx).setChecked(true, this); + } + } +} + +//----------------------------------------------------------------------------- +QList > +pqCompositeDataInformationTreeModel::checkedLevelDatasets() const +{ + QList > indices; + pqInternals& internals = (*this->Internals); + pqInternals::CNode& root = internals.rootNode(); + for (int level = 0; level < root.childrenCount(); ++level) + { + pqInternals::CNode& levelNode = root.child(level); + for (int ds = 0; ds < levelNode.childrenCount(); ++ds) + { + if (levelNode.child(ds).checkState() == Qt::Checked) + { + indices.push_back(QPair(level, ds)); + } + } + } + return indices; +} + +//----------------------------------------------------------------------------- +void pqCompositeDataInformationTreeModel::setCheckedLevelDatasets( + const QList >& indices) +{ + pqInternals& internals = (*this->Internals); + pqInternals::CNode& root = internals.rootNode(); + root.setChecked(false, this); + + int numLevels = root.childrenCount(); + + typedef QPair IdxPair; + foreach (const IdxPair& idx, indices) + { + if (idx.first < numLevels) + { + pqInternals::CNode& level = root.child(idx.first); + if (idx.second < level.childrenCount()) + { + level.child(idx.second).setChecked(true, this); + } + } + } +} diff --git a/Qt/Components/pqCompositeDataInformationTreeModel.h b/Qt/Components/pqCompositeDataInformationTreeModel.h new file mode 100644 index 0000000000..2b76a79558 --- /dev/null +++ b/Qt/Components/pqCompositeDataInformationTreeModel.h @@ -0,0 +1,178 @@ +/*========================================================================= + + Program: ParaView + Module: pqCompositeDataInformationTreeModel.h + + Copyright (c) 2005,2006 Sandia Corporation, Kitware Inc. + All rights reserved. + + ParaView is a free software; you can redistribute it and/or modify it + under the terms of the ParaView license version 1.2. + + See License_v1.2.txt for the full ParaView license. + A copy of this license can be obtained by contacting + Kitware Inc. + 28 Corporate Drive + Clifton Park, NY 12065 + USA + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +========================================================================*/ +#ifndef pqCompositeDataInformationTreeModel_h +#define pqCompositeDataInformationTreeModel_h + +#include "pqComponentsModule.h" // for exports. +#include +#include // for QPair. +#include // for ivar. + +class vtkPVDataInformation; + +/** + * @class pqCompositeDataInformationTreeModel + * @brief Tree model that use vtkPVDataInformation to model composite data tree. + * + * pqCompositeDataInformationTreeModel is designed to map a data set hierarchy + * represented by vtkCompositeDataSet (and subclasses) to a Qt tree model. + * + * To use this model, one calls `pqCompositeDataInformationTreeModel::reset()` with + * the data information object to use to build the structure from. + * + * There are few properties on this model that should be set prior to calling + * reset that determine how the model behaves. To allow the user to check/uncheck nodes + * on the tree, set **userCheckable** to true (default: false). To expand datasets in a + * multipiece, set **expandMultiPiece** to true (default: false). Finally, if + * **userCheckable** is true, and you want to only allow the user to select one sub-tree + * at a time, set **exclusivity** to true (default: false). + */ +class PQCOMPONENTS_EXPORT pqCompositeDataInformationTreeModel : public QAbstractItemModel +{ + Q_OBJECT + Q_PROPERTY(bool userCheckable READ userCheckable WRITE setUserCheckable); + Q_PROPERTY(bool expandMultiPiece READ expandMultiPiece WRITE setExpandMultiPiece); + Q_PROPERTY(bool exclusivity READ exclusivity WRITE setExclusivity); + + typedef QAbstractItemModel Superclass; + +public: + pqCompositeDataInformationTreeModel(QObject* parent = 0); + virtual ~pqCompositeDataInformationTreeModel(); + + //@{ + /** + * QAbstractItemModel interface implementation. + */ + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex& index = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role) const override; + Qt::ItemFlags flags(const QModelIndex& index) const override; + bool setData(const QModelIndex& index, const QVariant& value, int role) override; + QVariant headerData( + int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + bool setHeaderData(int section, Qt::Orientation orientation, const QVariant& value, + int role = Qt::DisplayRole) override; + //@} + + //@{ + /** + * Toggle whether the model allows user to change check state. + * Note: please call reset() after changing this. + */ + void setUserCheckable(bool val) { this->UserCheckable = val; } + bool userCheckable() const { return this->UserCheckable; } + //@} + + //@{ + /** + * Toggle whether multipiece datasets are expanded (default false). + * Note: please call reset() after changing this. + */ + void setExpandMultiPiece(bool val) { this->ExpandMultiPiece = val; } + bool expandMultiPiece() const { return this->ExpandMultiPiece; } + //@} + + //@{ + /** + * When set to true for a userCheckable model, if the user checks a node, + * the all other nodes that are not children of the checked node are unchecked. + */ + void setExclusivity(bool val) { this->Exclusivity = val; } + bool exclusivity() const { return this->Exclusivity; } + //@} + + /** + * API to get flat-indices for checked nodes. `checkedNodes` may return a + * combination of leaf and non-leaf nodes i.e. if all child nodes of a node + * are checked, then it will prefer the parent node's index rather than indices of + * each of the children. + */ + QList checkedNodes() const; + + /** + * API to get flat-indices for checked nodes. `checkedLeaves` returns indices for + * the leaf nodes. The flat-index for a non-leaf node is never returned by this method. + */ + QList checkedLeaves() const; + + /** + * API to set the flat-indices for checked nodes. This methods accepts indices for + * both non-leaf and leaf nodes. Note that if a non-leaf node is checked, + * then all its children are also considered as checked. + */ + void setChecked(const QList& indices); + + //@{ + /** + * This is useful when dealing with AMR datasets. It sets/returns the level numbers for selected + * levels + * in the AMR dataset. + */ + QList checkedLevels() const; + void setCheckedLevels(const QList& indices); + //@} + + //@{ + /** + * This is useful when dealing with AMR datasets. It sets/returns the level and dataset indices + * for AMR datasets. + */ + QList > checkedLevelDatasets() const; + void setCheckedLevelDatasets(const QList >& indices); + //@} + +public slots: + /** + * Reset and rebuild the model using the data information object provided. + * The model does not maintain a reference to the vtkPVDataInformation + * instance. Hence it will not automatically update when \c info changes. + * + * @returns true is the data information refers to a composite dataset. + * Otherwise, returns false. + */ + bool reset(vtkPVDataInformation* info = nullptr); + +private: + Q_DISABLE_COPY(pqCompositeDataInformationTreeModel); + + class pqInternals; + QScopedPointer Internals; + QString HeaderLabel; + bool UserCheckable; + bool ExpandMultiPiece; + bool Exclusivity; +}; + +#endif diff --git a/Qt/Components/pqCompositeTreePropertyWidget.cxx b/Qt/Components/pqCompositeTreePropertyWidget.cxx new file mode 100644 index 0000000000..b006adc6e9 --- /dev/null +++ b/Qt/Components/pqCompositeTreePropertyWidget.cxx @@ -0,0 +1,236 @@ +/*========================================================================= + + Program: ParaView + Module: pqCompositeTreePropertyWidget.cxx + + Copyright (c) 2005,2006 Sandia Corporation, Kitware Inc. + All rights reserved. + + ParaView is a free software; you can redistribute it and/or modify it + under the terms of the ParaView license version 1.2. + + See License_v1.2.txt for the full ParaView license. + A copy of this license can be obtained by contacting + Kitware Inc. + 28 Corporate Drive + Clifton Park, NY 12065 + USA + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +========================================================================*/ +#include "pqCompositeTreePropertyWidget.h" + +#include "pqCompositeDataInformationTreeModel.h" +#include "pqTreeView.h" +#include "pqTreeViewSelectionHelper.h" +#include "vtkEventQtSlotConnect.h" +#include "vtkPVXMLElement.h" +#include "vtkSMCompositeTreeDomain.h" +#include "vtkSMIntVectorProperty.h" + +#include +#include + +namespace +{ +template +void push_back(L& list, const T& item) +{ + list.push_back(item); +} + +template +void push_back(L& list, const QPair& item) +{ + list.push_back(item.first); + list.push_back(item.second); +} + +template +QList convertToVariantList(const QList& val) +{ + QList ret; + foreach (const T& avalue, val) + { + push_back(ret, avalue); + } + return ret; +} + +QList convertToUIntList(const QList& val) +{ + QList ret; + foreach (const QVariant& avalue, val) + { + ret.push_back(avalue.value()); + } + return ret; +} + +QList > convertToUIntPairList(const QList& val) +{ + QList > ret; + for (int cc = 0, max = val.size(); cc + 1 < max; cc += 2) + { + ret.push_back(QPair( + val[cc].value(), val[cc + 1].value())); + } + return ret; +} +} + +//----------------------------------------------------------------------------- +pqCompositeTreePropertyWidget::pqCompositeTreePropertyWidget( + vtkSMIntVectorProperty* smproperty, vtkSMProxy* smproxy, QWidget* parentObject) + : Superclass(smproxy, parentObject) + , Property(smproperty) +{ + this->setShowLabel(false); + this->setChangeAvailableAsChangeFinished(true); + + vtkSMCompositeTreeDomain* ctd = + vtkSMCompositeTreeDomain::SafeDownCast(smproperty->FindDomain("vtkSMCompositeTreeDomain")); + Q_ASSERT(ctd); + this->Domain = ctd; + + this->VTKConnect->Connect(ctd, vtkCommand::DomainModifiedEvent, &this->Timer, SLOT(start())); + this->connect(&this->Timer, SIGNAL(timeout()), SLOT(domainModified())); + this->Timer.setSingleShot(true); + this->Timer.setInterval(0); + + pqTreeView* treeView = new pqTreeView(this); + this->TreeView = treeView; + treeView->setObjectName("TreeWidget"); + + QHBoxLayout* hbox = new QHBoxLayout(this); + hbox->setMargin(0); + + pqCompositeDataInformationTreeModel* dmodel = new pqCompositeDataInformationTreeModel(this); + dmodel->setUserCheckable(true); + dmodel->setHeaderData(0, Qt::Horizontal, smproperty->GetXMLLabel()); + + // If property takes multiple values, then user can select multiple items at a + // time. If not, then tell the model that it should uncheck other subtrees + // when a user clicks on an item. + dmodel->setExclusivity(smproperty->GetRepeatCommand() == 0); + + if (ctd->GetMode() == vtkSMCompositeTreeDomain::AMR && + ((smproperty->GetRepeatCommand() == 1 && smproperty->GetNumberOfElementsPerCommand() == 2) || + (smproperty->GetRepeatCommand() == 0 && smproperty->GetNumberOfElements() == 2))) + { + dmodel->setExpandMultiPiece(true); + } + this->Model = dmodel; + this->domainModified(); + + treeView->setUniformRowHeights(true); + treeView->header()->setStretchLastSection(true); + treeView->setRootIsDecorated(true); + treeView->setModel(dmodel); + treeView->expandToDepth(2); + + if (vtkPVXMLElement* hints = smproperty->GetHints()) + { + if (vtkPVXMLElement* elem = hints->FindNestedElementByName("WidgetHeight")) + { + int row_count = 0; + if (elem->GetScalarAttribute("number_of_rows", &row_count)) + { + treeView->setMaximumRowCountBeforeScrolling(row_count); + } + } + } + + pqTreeViewSelectionHelper* helper = new pqTreeViewSelectionHelper(treeView); + helper->setObjectName("CompositeTreeSelectionHelper"); + hbox->addWidget(treeView); + + this->addPropertyLink(this, "values", SIGNAL(valuesChanged()), smproperty); + this->connect( + dmodel, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), SIGNAL(valuesChanged())); + + PV_DEBUG_PANELS() << "pqCompositeTreePropertyWidget for an IntVectorPropertyWidget with a " + << "CompositeTreeDomain"; +} + +//----------------------------------------------------------------------------- +pqCompositeTreePropertyWidget::~pqCompositeTreePropertyWidget() +{ +} + +//----------------------------------------------------------------------------- +void pqCompositeTreePropertyWidget::domainModified() +{ + if (this->Model && this->Domain) + { + // this ensures that the widget is hidden if the data is not a composite + // dataset. + this->TreeView->setVisible(this->Model->reset(this->Domain->GetInformation())); + } +} + +//----------------------------------------------------------------------------- +QList pqCompositeTreePropertyWidget::values() const +{ + Q_ASSERT(this->Model && this->Property && this->Domain); + switch (this->Domain->GetMode()) + { + case vtkSMCompositeTreeDomain::ALL: + case vtkSMCompositeTreeDomain::NON_LEAVES: + return convertToVariantList(this->Model->checkedNodes()); + + case vtkSMCompositeTreeDomain::LEAVES: + return convertToVariantList(this->Model->checkedLeaves()); + + case vtkSMCompositeTreeDomain::AMR: + if ((this->Property->GetRepeatCommand() == 1 && + this->Property->GetNumberOfElementsPerCommand() == 2) || + (this->Property->GetRepeatCommand() == 0 && this->Property->GetNumberOfElements() == 2)) + { + return convertToVariantList(this->Model->checkedLevelDatasets()); + } + else + { + return convertToVariantList(this->Model->checkedLevels()); + } + } + return QList(); +} + +//----------------------------------------------------------------------------- +void pqCompositeTreePropertyWidget::setValues(const QList& values) +{ + Q_ASSERT(this->Model && this->Property && this->Domain); + switch (this->Domain->GetMode()) + { + case vtkSMCompositeTreeDomain::ALL: + case vtkSMCompositeTreeDomain::NON_LEAVES: + case vtkSMCompositeTreeDomain::LEAVES: + this->Model->setChecked(convertToUIntList(values)); + break; + + case vtkSMCompositeTreeDomain::AMR: + if ((this->Property->GetRepeatCommand() && + this->Property->GetNumberOfElementsPerCommand() == 2) || + this->Property->GetNumberOfElements() == 2) + { + this->Model->setCheckedLevelDatasets(convertToUIntPairList(values)); + } + else + { + this->Model->setCheckedLevels(convertToUIntList(values)); + } + break; + } +} diff --git a/Qt/Components/pqCompositeTreePropertyWidget.h b/Qt/Components/pqCompositeTreePropertyWidget.h new file mode 100644 index 0000000000..74401e41a3 --- /dev/null +++ b/Qt/Components/pqCompositeTreePropertyWidget.h @@ -0,0 +1,96 @@ +/*========================================================================= + + Program: ParaView + Module: pqCompositeTreePropertyWidget.h + + Copyright (c) 2005,2006 Sandia Corporation, Kitware Inc. + All rights reserved. + + ParaView is a free software; you can redistribute it and/or modify it + under the terms of the ParaView license version 1.2. + + See License_v1.2.txt for the full ParaView license. + A copy of this license can be obtained by contacting + Kitware Inc. + 28 Corporate Drive + Clifton Park, NY 12065 + USA + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +========================================================================*/ +#ifndef pqCompositeTreePropertyWidget_h +#define pqCompositeTreePropertyWidget_h + +#include "pqPropertyWidget.h" +#include "pqTimer.h" // needed for pqTimer. +#include "vtkNew.h" // needed for vtkNew. +#include "vtkWeakPointer.h" // needed for vtkWeakPointer. + +class vtkSMIntVectorProperty; +class vtkEventQtSlotConnect; +class vtkSMCompositeTreeDomain; +class pqCompositeDataInformationTreeModel; +class pqTreeView; + +/** + * @class pqCompositeDataInformationTreeModel + * @brief property widget for a vtkSMIntVectorProperty with vtkSMCompositeTreeDomain. + * + * pqCompositeDataInformationTreeModel is a subclass of pqPropertyWidget that is + * created by default for any vtkSMIntVectorProperty having a + * vtkSMCompositeTreeDomain. This widgets creates a tree view which shows the + * composite-dataset hierarchy. It supports both multiblock and AMR datasets + * with ability to select blocks either using flat or composite index or + * AMR-specific, level number or level number and block number. + * + * Internally, it uses pqCompositeDataInformationTreeModel and keeps it updated + * as the vtkSMCompositeTreeDomain changes. + */ +class PQCOMPONENTS_EXPORT pqCompositeTreePropertyWidget : public pqPropertyWidget +{ + Q_OBJECT + typedef pqPropertyWidget Superclass; + Q_PROPERTY(QList values READ values WRITE setValues NOTIFY valuesChanged); + +public: + pqCompositeTreePropertyWidget( + vtkSMIntVectorProperty* smproperty, vtkSMProxy* smproxy, QWidget* parent = nullptr); + virtual ~pqCompositeTreePropertyWidget(); + + /** + * API to get/set the selected values. What there values represents depends on + * the domain and the property e.g. it can represent flat indices or amr-level + * number or (amr-level, amr-block) pairs. + */ + QList values() const; + void setValues(const QList& values); + +signals: + void valuesChanged(); + +private slots: + void domainModified(); + +private: + Q_DISABLE_COPY(pqCompositeTreePropertyWidget); + + pqTimer Timer; + vtkNew VTKConnect; + vtkWeakPointer Domain; + vtkWeakPointer Property; + QPointer Model; + QPointer TreeView; +}; + +#endif diff --git a/Qt/Components/pqIntVectorPropertyWidget.cxx b/Qt/Components/pqIntVectorPropertyWidget.cxx index 039fbb465c..cc81c85e22 100644 --- a/Qt/Components/pqIntVectorPropertyWidget.cxx +++ b/Qt/Components/pqIntVectorPropertyWidget.cxx @@ -45,14 +45,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "vtkSmartPointer.h" #include "pqComboBoxDomain.h" +#include "pqCompositeTreePropertyWidget.h" #include "pqIntRangeWidget.h" #include "pqLabel.h" #include "pqLineEdit.h" #include "pqProxyWidget.h" #include "pqScalarValueListPropertyWidget.h" -#include "pqSignalAdaptorCompositeTreeWidget.h" #include "pqSignalAdaptorSelectionTreeWidget.h" #include "pqSignalAdaptors.h" +#include "pqTreeView.h" #include "pqTreeWidget.h" #include "pqTreeWidgetSelectionHelper.h" @@ -61,6 +62,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +//----------------------------------------------------------------------------- pqIntVectorPropertyWidget::pqIntVectorPropertyWidget( vtkSMProperty* smproperty, vtkSMProxy* smProxy, QWidget* parentObject) : pqPropertyWidget(smProxy, parentObject) @@ -178,29 +180,10 @@ pqIntVectorPropertyWidget::pqIntVectorPropertyWidget( << "(with non-repeatable command)"; } } - else if (vtkSMCompositeTreeDomain::SafeDownCast(domain)) + else if (vtkSMCompositeTreeDomain* ctd = vtkSMCompositeTreeDomain::SafeDownCast(domain)) { - pqTreeWidget* treeWidget = new pqTreeWidget(this); - treeWidget->setObjectName("TreeWidget"); - treeWidget->setHeaderLabel(smproperty->GetXMLLabel()); - treeWidget->setMaximumRowCountBeforeScrolling(smproperty); - - pqSignalAdaptorCompositeTreeWidget* adaptor = - new pqSignalAdaptorCompositeTreeWidget(treeWidget, ivp, - /*autoUpdateVisibility=*/true); - adaptor->setObjectName("CompositeTreeAdaptor"); - - pqTreeWidgetSelectionHelper* helper = new pqTreeWidgetSelectionHelper(treeWidget); - helper->setObjectName("CompositeTreeSelectionHelper"); - - this->addPropertyLink(adaptor, "values", SIGNAL(valuesChanged()), ivp); - this->setChangeAvailableAsChangeFinished(true); - - layoutLocal->addWidget(treeWidget); - this->setShowLabel(false); - - PV_DEBUG_PANELS() << "pqTreeWidget for an IntVectorPropertyWidget with a " - << "CompositeTreeDomain"; + // Should have been handled by pqCompositeTreePropertyWidget. + abort(); } else if (vtkSMIntRangeDomain* range = vtkSMIntRangeDomain::SafeDownCast(domain)) { @@ -301,3 +284,20 @@ pqIntVectorPropertyWidget::pqIntVectorPropertyWidget( this->setLayout(layoutLocal); } + +//----------------------------------------------------------------------------- +pqIntVectorPropertyWidget::~pqIntVectorPropertyWidget() +{ +} + +//----------------------------------------------------------------------------- +pqPropertyWidget* pqIntVectorPropertyWidget::createWidget( + vtkSMIntVectorProperty* smproperty, vtkSMProxy* smproxy, QWidget* parent) +{ + if (smproperty != nullptr && smproperty->FindDomain("vtkSMCompositeTreeDomain") != nullptr) + { + return new pqCompositeTreePropertyWidget(smproperty, smproxy, parent); + } + + return new pqIntVectorPropertyWidget(smproperty, smproxy, parent); +} diff --git a/Qt/Components/pqIntVectorPropertyWidget.h b/Qt/Components/pqIntVectorPropertyWidget.h index 2f4b0ef478..ababd18b28 100644 --- a/Qt/Components/pqIntVectorPropertyWidget.h +++ b/Qt/Components/pqIntVectorPropertyWidget.h @@ -35,7 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "pqPropertyWidget.h" -#include "pqPropertyLinks.h" +class vtkSMIntVectorProperty; class PQCOMPONENTS_EXPORT pqIntVectorPropertyWidget : public pqPropertyWidget { @@ -43,6 +43,16 @@ class PQCOMPONENTS_EXPORT pqIntVectorPropertyWidget : public pqPropertyWidget public: pqIntVectorPropertyWidget(vtkSMProperty* property, vtkSMProxy* proxy, QWidget* parent = 0); + virtual ~pqIntVectorPropertyWidget(); + + /** + * Creates known pqPropertyWidget subclasses for vtkSMIntVectorProperty property. + */ + static pqPropertyWidget* createWidget( + vtkSMIntVectorProperty* smproperty, vtkSMProxy* smproxy, QWidget* parent); + +private: + Q_DISABLE_COPY(pqIntVectorPropertyWidget); }; #endif // _pqIntVectorPropertyWidget_h diff --git a/Qt/Components/pqProxyWidget.cxx b/Qt/Components/pqProxyWidget.cxx index b7745fe4de..30d33e9fa0 100644 --- a/Qt/Components/pqProxyWidget.cxx +++ b/Qt/Components/pqProxyWidget.cxx @@ -1047,7 +1047,7 @@ pqPropertyWidget* pqProxyWidget::createWidgetForProperty( } else if (vtkSMIntVectorProperty* ivp = vtkSMIntVectorProperty::SafeDownCast(smproperty)) { - widget = new pqIntVectorPropertyWidget(ivp, smproxy, parentObj); + widget = pqIntVectorPropertyWidget::createWidget(ivp, smproxy, parentObj); } else if (vtkSMStringVectorProperty* svp = vtkSMStringVectorProperty::SafeDownCast(smproperty)) { diff --git a/Qt/Components/pqQueryClauseWidget.cxx b/Qt/Components/pqQueryClauseWidget.cxx index 7ba776bb9b..d681103b01 100644 --- a/Qt/Components/pqQueryClauseWidget.cxx +++ b/Qt/Components/pqQueryClauseWidget.cxx @@ -33,11 +33,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ui_pqQueryClauseWidget.h" #include "ui_pqQueryCompositeTreeDialog.h" +#include "pqCompositeDataInformationTreeModel.h" #include "pqHelpWindow.h" #include "pqOutputPort.h" #include "pqPipelineSource.h" #include "pqServer.h" -#include "pqSignalAdaptorCompositeTreeWidget.h" #include "vtkDataObject.h" #include "vtkPVArrayInformation.h" #include "vtkPVDataInformation.h" @@ -526,53 +526,74 @@ void pqQueryClauseWidget::showCompositeTree() ui.Blocks->setSelectionMode(QAbstractItemView::ExtendedSelection); } - pqSignalAdaptorCompositeTreeWidget adaptor( - ui.Blocks, this->producer()->getOutputPortProxy(), vtkSMCompositeTreeDomain::NONE); + pqCompositeDataInformationTreeModel dmodel; + if (criteria_type == AMR_BLOCK) + { + // if selecting AMR_BLOCK, we need to expand multipiece nodes. + dmodel.setExpandMultiPiece(true); + } + + ui.Blocks->setModel(&dmodel); + dmodel.reset(this->producer()->getDataInformation()); + ui.Blocks->expandAll(); if (dialog.exec() != QDialog::Accepted) { return; } - QStringList values; - QList selItems = ui.Blocks->selectedItems(); - foreach (QTreeWidgetItem* item, selItems) + // to convert selected indexes to flat or amr ids, we use a trick. We make the + // model check the selected indexes and then use existing API on the model to + // access the indexes for the checked nodes. + QModelIndexList selIndexes = ui.Blocks->selectionModel()->selectedIndexes(); + foreach (const QModelIndex& idx, selIndexes) { - int current_flat_index = adaptor.flatIndex(item); - switch (criteria_type) + if (idx.isValid()) { - case BLOCK: - if (this->Internals->criteria->currentText() == "Block ID") - { - values << QString("%1").arg(current_flat_index); - } - else - { - // name. - QString blockName = adaptor.blockName(item); - if (blockName.isEmpty()) - { - qWarning("Data block doesn't have a name assigned to it. Query may" - " not work. Use 'Block ID' based criteria instead."); - } - else - { - values << blockName; - } - } - break; - - case AMR_LEVEL: - values << QString("%1").arg(adaptor.hierarchicalLevel(item)); - break; - - case AMR_BLOCK: - values << QString("%1").arg(adaptor.hierarchicalBlockIndex(item)); - break; + dmodel.setData(idx, Qt::Checked, Qt::CheckStateRole); + } + } - default: - qCritical("Invalid criteria_type."); + QStringList values; + switch (criteria_type) + { + case BLOCK: + { + const QList findexes = dmodel.checkedNodes(); + foreach (unsigned int idx, findexes) + { + values << QString::number(idx); + } + } + break; + case AMR_LEVEL: + { + const QList levels = dmodel.checkedLevels(); + foreach (unsigned int idx, levels) + { + values << QString::number(idx); + } } + break; + case AMR_BLOCK: + { + typedef QPair UIPair; + const QList amrIndexes = dmodel.checkedLevelDatasets(); + QSet uniq; + foreach (const UIPair& idx, amrIndexes) + { + uniq.insert(idx.second); + } + foreach (unsigned int idx, uniq) + { + values << QString::number(idx); + } + } + break; + + default: + qCritical("Invalid criteria_type."); } + this->Internals->value_block->setText(values.join(",")); } diff --git a/Qt/Components/pqSignalAdaptorCompositeTreeWidget.cxx b/Qt/Components/pqSignalAdaptorCompositeTreeWidget.cxx deleted file mode 100644 index 8ac96722e2..0000000000 --- a/Qt/Components/pqSignalAdaptorCompositeTreeWidget.cxx +++ /dev/null @@ -1,874 +0,0 @@ -/*========================================================================= - - Program: ParaView - Module: pqSignalAdaptorCompositeTreeWidget.cxx - - Copyright (c) 2005-2008 Sandia Corporation, Kitware Inc. - All rights reserved. - - ParaView is a free software; you can redistribute it and/or modify it - under the terms of the ParaView license version 1.2. - - See License_v1.2.txt for the full ParaView license. - A copy of this license can be obtained by contacting - Kitware Inc. - 28 Corporate Drive - Clifton Park, NY 12065 - USA - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -========================================================================*/ -#include "pqSignalAdaptorCompositeTreeWidget.h" - -// Server Manager Includes. -#include "vtkEventQtSlotConnect.h" -#include "vtkPVCompositeDataInformation.h" -#include "vtkPVDataInformation.h" -#include "vtkPVXMLElement.h" -#include "vtkSMCompositeTreeDomain.h" -#include "vtkSMDomainIterator.h" -#include "vtkSMIntVectorProperty.h" -#include "vtkSMOutputPort.h" -#include "vtkSMSourceProxy.h" -#include "vtkSmartPointer.h" - -// Qt Includes. -#include -#include -#include - -// ParaView Includes. -#include "pqSMAdaptor.h" -#include "pqTreeWidgetItem.h" - -//----------------------------------------------------------------------------- -class pqSignalAdaptorCompositeTreeWidget::pqInternal -{ -public: - QPointer TreeWidget; - vtkSmartPointer Property; - vtkSmartPointer OutputPort; - vtkSmartPointer Domain; - vtkSmartPointer VTKConnect; - vtkSmartPointer VTKConnectSelection; - - QList Items; - int DomainMode; -}; - -//----------------------------------------------------------------------------- -class pqSignalAdaptorCompositeTreeWidget::pqCallbackAdaptor - : public pqTreeWidgetItem::pqCallbackHandler -{ - int ChangeDepth; // used to avoid repeated valuesChanged() signal firing when - // check states are being changed as a consequence of toggle - // the check state for a non-leaf node. - bool BlockCallbacks; - bool PrevBlockSignals; - pqSignalAdaptorCompositeTreeWidget* Adaptor; - -public: - pqCallbackAdaptor(pqSignalAdaptorCompositeTreeWidget* adaptor) - { - this->Adaptor = adaptor; - this->BlockCallbacks = false; - this->ChangeDepth = 0; - } - bool blockCallbacks(bool val) - { - bool old = this->BlockCallbacks; - this->BlockCallbacks = val; - return old; - } - virtual void checkStateChanged(pqTreeWidgetItem* item, int column) - { - // When a non-leaf node is toggled, Qt changes the check state of all child - // nodes. When that's happening we don't want to repeatedly fire - // valuesChanged() signal. Hence we use this ChangeDepth magic. - this->ChangeDepth--; - if (this->ChangeDepth == 0) - { - this->Adaptor->blockSignals(this->PrevBlockSignals); - } - if (this->BlockCallbacks == false) - { - this->Adaptor->updateCheckState(item, column); - } - } - - virtual void checkStateAboutToChange(pqTreeWidgetItem* /*item*/, int /*column*/) - { - // When a non-leaf node is toggled, Qt changes the check state of all child - // nodes. When that's happening we don't want to repeatedly fire - // valuesChanged() signal. Hence we use this ChangeDepth magic. - this->ChangeDepth++; - if (this->ChangeDepth == 1) - { - this->PrevBlockSignals = this->Adaptor->blockSignals(true); - } - } - - virtual bool acceptChange(pqTreeWidgetItem* item, const QVariant& curValue, - const QVariant& newValue, int column, int role) - { - if (this->BlockCallbacks == false) - { - // * In SINGLE_ITEM, it's an error to not have any item checked. Hence if - // the user is un-checking an item, we ensure that atleast one other item - // is checked. - if (this->Adaptor->CheckMode == pqSignalAdaptorCompositeTreeWidget::SINGLE_ITEM && - role == Qt::CheckStateRole && curValue.toInt() == Qt::Checked && - newValue.toInt() == Qt::Unchecked && (item->flags() & Qt::ItemIsTristate) == 0) - { - // ensure that at least one item is always checked. - foreach (pqTreeWidgetItem* curitem, this->Adaptor->Internal->Items) - { - if (item != curitem && curitem->checkState(column) == Qt::Checked) - { - return true; - } - } - return false; - } - } - return true; - } -}; - -// This TreeItem specialization needs some explanation. -// Default Qt behavior for tristate items: -// - If all immediate children are checked or partially checked -// then the item becomes fully checked. -// This is not appropriate for this widget. A parent item should never be fully -// checked unless the user explicitly checked it, since otherwise, the behavior -// of the filter is to pass the entire subtree through. -// This class fixes that issue. -class pqCompositeTreeWidgetItem : public pqTreeWidgetItem -{ - typedef pqTreeWidgetItem Superclass; - int triStateCheckState; - bool inSetData; - -public: - pqCompositeTreeWidgetItem(QTreeWidget* tree, QStringList _values) - : Superclass(tree, _values) - , triStateCheckState(-1) - , inSetData(false) - - { - } - - pqCompositeTreeWidgetItem(QTreeWidgetItem* item, QStringList _values) - : Superclass(item, _values) - , triStateCheckState(-1) - , inSetData(false) - { - } - - virtual QVariant data(int column, int role) const - { - if (role == Qt::CheckStateRole && this->triStateCheckState != -1 && this->childCount() > 0 && - (this->flags() & Qt::ItemIsTristate)) - { - // superclass implementation of this method only checks the immediate - // children. - QVariant vSuggestedValue = this->Superclass::data(column, role); - int suggestedValue = vSuggestedValue.toInt(); - if (this->triStateCheckState == Qt::PartiallyChecked) - { - if (suggestedValue == Qt::Checked || suggestedValue == Qt::PartiallyChecked) - { - return Qt::PartiallyChecked; - } - // suggestedValue == Qt:Unchecked - return Qt::Unchecked; - } - return this->triStateCheckState; - } - - return this->Superclass::data(column, role); - } - - virtual void setData(int column, int role, const QVariant& in_value) - { - this->inSetData = true; - this->triStateCheckState = -1; - - // Superclass will also mark all children checked or unchecked. - this->Superclass::setData(column, role, in_value); - - if (role == Qt::CheckStateRole && column == 0) - { - QVariant value = this->data(column, role); - - if (this->flags() & Qt::ItemIsTristate) - { - this->triStateCheckState = value.toInt(); - } - - // tell my parent it is partially checked (at best). - pqCompositeTreeWidgetItem* itemParent = - dynamic_cast(static_cast(this)->parent()); - while (itemParent && !itemParent->inSetData) - { - itemParent->triStateCheckState = Qt::PartiallyChecked; - itemParent = static_cast( - static_cast(itemParent)->parent()); - } - } - this->inSetData = false; - } -}; - -//----------------------------------------------------------------------------- -void pqSignalAdaptorCompositeTreeWidget::constructor(QTreeWidget* tree, bool autoUpdateVisibility) -{ - this->Internal = new pqInternal(); - this->Internal->TreeWidget = tree; - this->Internal->VTKConnect = vtkSmartPointer::New(); - this->Internal->VTKConnectSelection = vtkSmartPointer::New(); - this->AutoUpdateWidgetVisibility = autoUpdateVisibility; - - this->Internal->DomainMode = vtkSMCompositeTreeDomain::ALL; - this->CheckMode = SINGLE_ITEM; - this->IndexMode = INDEX_MODE_FLAT; - - this->ShowFlatIndex = false; - this->ShowDatasetsInMultiPiece = false; - this->ShowSelectedElementCounts = false; - - this->CallbackAdaptor = new pqCallbackAdaptor(this); -} - -//----------------------------------------------------------------------------- -pqSignalAdaptorCompositeTreeWidget::pqSignalAdaptorCompositeTreeWidget(QTreeWidget* tree, - vtkSMIntVectorProperty* smproperty, bool autoUpdateVisibility /*=false*/, - bool showSelectedElementCounts /*false*/) - : Superclass(tree) -{ - this->constructor(tree, autoUpdateVisibility); - this->ShowSelectedElementCounts = showSelectedElementCounts; - this->Internal->Property = smproperty; - if (!smproperty) - { - qCritical() << "Property cannot be NULL."; - return; - } - - // * Determine CheckMode. - this->CheckMode = smproperty->GetRepeatCommand() ? MULTIPLE_ITEMS : SINGLE_ITEM; - - // * Determine IndexMode. - this->IndexMode = INDEX_MODE_FLAT; - if (smproperty->GetNumberOfElementsPerCommand() == 2) - { - this->IndexMode = INDEX_MODE_LEVEL_INDEX; // (level, index) pairs. - } - - // IndexMode defaults may be overridden by some hints. - // If hints are provided, we use those to determine the IndexMode for this - // property. - vtkPVXMLElement* hints = smproperty->GetHints(); - if (hints) - { - vtkPVXMLElement* useFlatIndex = hints->FindNestedElementByName("UseFlatIndex"); - if (useFlatIndex && useFlatIndex->GetAttribute("value") && - strcmp(useFlatIndex->GetAttribute("value"), "0") == 0 && this->IndexMode == INDEX_MODE_FLAT) - { - this->IndexMode = INDEX_MODE_LEVEL; - } - } - - /// * Locate the Domain. - vtkSMDomainIterator* iter = smproperty->NewDomainIterator(); - iter->Begin(); - while (!iter->IsAtEnd() && !this->Internal->Domain) - { - vtkSMDomain* domain = iter->GetDomain(); - this->Internal->Domain = vtkSMCompositeTreeDomain::SafeDownCast(domain); - iter->Next(); - } - iter->Delete(); - - if (this->Internal->Domain) - { - this->Internal->VTKConnect->Connect( - this->Internal->Domain, vtkCommand::DomainModifiedEvent, this, SLOT(domainChanged())); - this->domainChanged(); - } - - // * Initialize the widget using the current value. - bool prev = this->blockSignals(true); - QList curValues = pqSMAdaptor::getMultipleElementProperty(smproperty); - this->setValues(curValues); - this->blockSignals(prev); -} - -//----------------------------------------------------------------------------- -pqSignalAdaptorCompositeTreeWidget::pqSignalAdaptorCompositeTreeWidget(QTreeWidget* tree, - vtkSMOutputPort* port, int domainMode, IndexModes indexMode, bool selectMultiple, - bool autoUpdateVisibility, bool showSelectedElementCounts) - : Superclass(tree) -{ - this->constructor(tree, autoUpdateVisibility); - - if (!port) - { - qCritical() << "Output port cannot be NULL."; - return; - } - - this->ShowFlatIndex = true; - this->ShowDatasetsInMultiPiece = true; - this->ShowSelectedElementCounts = showSelectedElementCounts; - this->CheckMode = selectMultiple ? MULTIPLE_ITEMS : SINGLE_ITEM; - this->IndexMode = indexMode; - this->Internal->DomainMode = domainMode; - this->Internal->OutputPort = port; - this->Internal->VTKConnect->Connect( - port, vtkCommand::UpdateDataEvent, this, SLOT(portInformationChanged())); - this->portInformationChanged(); -} - -//----------------------------------------------------------------------------- -pqSignalAdaptorCompositeTreeWidget::~pqSignalAdaptorCompositeTreeWidget() -{ - delete this->Internal; - delete this->CallbackAdaptor; - this->CallbackAdaptor = 0; -} - -//----------------------------------------------------------------------------- -void pqSignalAdaptorCompositeTreeWidget::select(unsigned int flat_index) -{ - QList selItems = this->Internal->TreeWidget->selectedItems(); - foreach (QTreeWidgetItem* item, selItems) - { - item->setSelected(false); - } - QList treeitems = this->Internal->Items; - foreach (pqTreeWidgetItem* item, treeitems) - { - QVariant metadata = item->data(0, FLAT_INDEX); - if (metadata.isValid() && metadata.toUInt() == flat_index) - { - item->setSelected(true); - break; - } - } -} - -//----------------------------------------------------------------------------- -unsigned int pqSignalAdaptorCompositeTreeWidget::getCurrentFlatIndex(bool* valid) -{ - if (valid) - { - *valid = false; - } - - QList selItems = this->Internal->TreeWidget->selectedItems(); - if (selItems.size() > 0) - { - if (valid) - { - *valid = true; - } - return this->flatIndex(selItems[0]); - } - return 0; -} - -//----------------------------------------------------------------------------- -unsigned int pqSignalAdaptorCompositeTreeWidget::flatIndex(const QTreeWidgetItem* item) const -{ - return item->data(0, FLAT_INDEX).toUInt(); -} - -//----------------------------------------------------------------------------- -unsigned int pqSignalAdaptorCompositeTreeWidget::hierarchicalLevel( - const QTreeWidgetItem* item) const -{ - QVariant val = item->data(0, AMR_LEVEL_NUMBER).toUInt(); - return val.toUInt(); -} - -//----------------------------------------------------------------------------- -unsigned int pqSignalAdaptorCompositeTreeWidget::hierarchicalBlockIndex( - const QTreeWidgetItem* item) const -{ - QVariant val = item->data(0, AMR_BLOCK_INDEX).toUInt(); - return val.toUInt(); -} - -//----------------------------------------------------------------------------- -QString pqSignalAdaptorCompositeTreeWidget::blockName(const QTreeWidgetItem* item) const -{ - QString block_name = item->data(0, BLOCK_NAME).toString(); - return block_name; -} - -//----------------------------------------------------------------------------- -QList pqSignalAdaptorCompositeTreeWidget::values() const -{ - QList reply; - - QList treeitems = this->Internal->Items; - foreach (pqTreeWidgetItem* item, treeitems) - { - QVariant nodeType = item->data(0, NODE_TYPE); - if (!nodeType.isValid()) - { - continue; - } - - if ((this->Internal->DomainMode == vtkSMCompositeTreeDomain::LEAVES && - nodeType.toInt() != LEAF) || - (this->Internal->DomainMode == vtkSMCompositeTreeDomain::NON_LEAVES && - nodeType.toInt() != NON_LEAF)) - { - // Skip nodes the filter is not interested in. - continue; - } - - if (this->IndexMode == INDEX_MODE_FLAT) - { - QVariant metadata = item->data(0, FLAT_INDEX); - // cout << metadata.toInt() << ": " << item->checkState(0) << endl; - if (metadata.isValid() && item->checkState(0) == Qt::Checked) - { - // metadata has the flat index for the node. - reply.push_back(metadata); - // cout << metadata.toInt() << endl; - } - } - else if (this->IndexMode == INDEX_MODE_LEVEL_INDEX) - { - QVariant metadata0 = item->data(0, AMR_LEVEL_NUMBER); - QVariant metadata1 = item->data(0, AMR_BLOCK_INDEX); - if (metadata0.isValid() && metadata1.isValid() && item->checkState(0) == Qt::Checked) - { - reply.push_back(metadata0); - reply.push_back(metadata1); - // cout << metadata0.toInt() << ", " << metadata1.toInt() << endl; - } - } - else if (this->IndexMode == INDEX_MODE_LEVEL) - { - QVariant metadata0 = item->data(0, AMR_LEVEL_NUMBER); - if (metadata0.isValid() && item->checkState(0) == Qt::Checked) - { - reply.push_back(metadata0); - // cout << metadata0.toInt() << endl; - } - } - } - - return reply; -} - -//----------------------------------------------------------------------------- -inline bool pqItemIsCheckable(QTreeWidgetItem* item) -{ - return ((item->flags() & Qt::ItemIsUserCheckable) == Qt::ItemIsUserCheckable); -} - -//----------------------------------------------------------------------------- -void pqSignalAdaptorCompositeTreeWidget::setValues(const QList& new_values) -{ - bool prev = this->blockSignals(true); - QList treeitems = this->Internal->Items; - bool changed = false; - - if (this->IndexMode == INDEX_MODE_FLAT) - { - foreach (pqTreeWidgetItem* item, treeitems) - { - QVariant metadata = item->data(0, FLAT_INDEX); - Qt::CheckState cstate = - (metadata.isValid() && new_values.contains(metadata)) ? Qt::Checked : Qt::Unchecked; - if (::pqItemIsCheckable(item) && item->checkState(0) != cstate) - { - item->setCheckState(0, cstate); - changed = true; - } - } - } - else if (this->IndexMode == INDEX_MODE_LEVEL) - { - foreach (pqTreeWidgetItem* item, treeitems) - { - QVariant metadata = item->data(0, AMR_LEVEL_NUMBER); - Qt::CheckState cstate = - (metadata.isValid() && new_values.contains(metadata)) ? Qt::Checked : Qt::Unchecked; - if (pqItemIsCheckable(item) && item->checkState(0) != cstate) - { - item->setCheckState(0, cstate); - changed = true; - } - } - } - else if (this->IndexMode == INDEX_MODE_LEVEL_INDEX) - { - QSet > pairs; - for (int cc = 0; (cc + 1) < new_values.size(); cc += 2) - { - unsigned int level = new_values[cc].toUInt(); - unsigned int index = new_values[cc + 1].toUInt(); - pairs.insert(QPair(level, index)); - } - - foreach (pqTreeWidgetItem* item, treeitems) - { - QVariant metadata0 = item->data(0, AMR_LEVEL_NUMBER); - QVariant metadata1 = item->data(0, AMR_BLOCK_INDEX); - Qt::CheckState cstate = - (metadata0.isValid() && metadata1.isValid() && - pairs.contains(QPair(metadata0.toUInt(), metadata1.toUInt()))) - ? Qt::Checked - : Qt::Unchecked; - if (pqItemIsCheckable(item) && item->checkState(0) != cstate) - { - item->setCheckState(0, cstate); - changed = true; - } - } - } - this->blockSignals(prev); - if (changed) - { - emit this->valuesChanged(); - } -} - -//----------------------------------------------------------------------------- -void pqSignalAdaptorCompositeTreeWidget::domainChanged() -{ - bool prev = this->blockSignals(true); - QList widgetvalues = this->values(); - this->Internal->Items.clear(); - this->Internal->TreeWidget->clear(); - - this->Internal->DomainMode = this->Internal->Domain->GetMode(); - vtkPVDataInformation* dInfo = this->Internal->Domain->GetInformation(); - - this->FlatIndex = 0; - this->LevelNo = 0; - - pqTreeWidgetItem* root = - new pqCompositeTreeWidgetItem(this->Internal->TreeWidget, QStringList("Root")); - root->setCallbackHandler(this->CallbackAdaptor); - root->setData(0, ORIGINAL_LABEL, "Root"); - root->setData(0, BLOCK_NAME, QString()); - root->setToolTip(0, root->text(0)); - this->buildTree(root, dInfo); - this->updateItemFlags(); - this->updateSelectionCounts(); - - // now update check state. - this->setValues(widgetvalues); - this->blockSignals(prev); - - if (this->AutoUpdateWidgetVisibility) - { - this->Internal->TreeWidget->setVisible( - dInfo ? dInfo->GetCompositeDataInformation()->GetDataIsComposite() == 1 : 0); - } - - if (this->ShowSelectedElementCounts) - { - this->setupSelectionUpdatedCallback( - this->Internal->Domain->GetSource(), this->Internal->Domain->GetSourcePort()); - } - else - { - this->setupSelectionUpdatedCallback(NULL, 0); - } -} - -//----------------------------------------------------------------------------- -void pqSignalAdaptorCompositeTreeWidget::portInformationChanged() -{ - bool prev = this->blockSignals(true); - QList widgetvalues = this->values(); - this->Internal->Items.clear(); - this->Internal->TreeWidget->clear(); - - vtkPVDataInformation* dInfo = this->Internal->OutputPort->GetDataInformation(); - - this->FlatIndex = 0; - this->LevelNo = 0; - - pqTreeWidgetItem* root = - new pqCompositeTreeWidgetItem(this->Internal->TreeWidget, QStringList("Root")); - root->setCallbackHandler(this->CallbackAdaptor); - root->setData(0, ORIGINAL_LABEL, "Root"); - root->setData(0, BLOCK_NAME, QString()); - root->setToolTip(0, root->text(0)); - this->buildTree(root, dInfo); - this->updateItemFlags(); - this->updateSelectionCounts(); - - // now update check state. - this->setValues(widgetvalues); - this->blockSignals(prev); - - if (this->AutoUpdateWidgetVisibility) - { - this->Internal->TreeWidget->setVisible( - dInfo->GetCompositeDataInformation()->GetDataIsComposite() == 1); - } - - this->setupSelectionUpdatedCallback(NULL, 0); -} - -//----------------------------------------------------------------------------- -// For all elements in the tree, this method determines if the item is checkable -// (given the current mode). -void pqSignalAdaptorCompositeTreeWidget::updateItemFlags() -{ - if (this->Internal->DomainMode == vtkSMCompositeTreeDomain::NONE) - { - // no item is checkable. - return; - } - - foreach (pqTreeWidgetItem* item, this->Internal->Items) - { - QVariant vNodeType = item->data(0, NODE_TYPE); - if (!vNodeType.isValid() || !vNodeType.canConvert()) - { - continue; - } - - int nodeType = vNodeType.toInt(); - if (nodeType == LEAF) - { - // leaves are always checkable. - item->setFlags(item->flags() | Qt::ItemIsUserCheckable); - item->setCheckState(0, Qt::Unchecked); - } - else if (nodeType == NON_LEAF) - { - // If domainMode == LEAVES and CheckMode == SINGLE_ITEM, then non-leaf are - // not checkable. - if (this->Internal->DomainMode != vtkSMCompositeTreeDomain::LEAVES || - this->CheckMode != SINGLE_ITEM) - { - item->setFlags(item->flags() | Qt::ItemIsUserCheckable | Qt::ItemIsTristate); - item->setCheckState(0, Qt::Unchecked); - } - } - } -} - -//----------------------------------------------------------------------------- -/// Called when an item check state is toggled. This is used only when -/// this->CheckMode == SINGLE_ITEM. We uncheck all other items. -void pqSignalAdaptorCompositeTreeWidget::updateCheckState(pqTreeWidgetItem* item, int column) -{ - this->CallbackAdaptor->blockCallbacks(true); - bool checked = item->checkState(column) == Qt::Checked; - if (item && checked && this->CheckMode == SINGLE_ITEM) - { - foreach (pqTreeWidgetItem* curitem, this->Internal->Items) - { - if (curitem != item && (curitem->flags() & Qt::ItemIsUserCheckable) && - (curitem->checkState(0) != Qt::Unchecked) && (curitem->flags() & Qt::ItemIsTristate) == 0) - { - curitem->setCheckState(0, Qt::Unchecked); - } - } - } - this->CallbackAdaptor->blockCallbacks(false); - emit this->valuesChanged(); -} - -//----------------------------------------------------------------------------- -void pqSignalAdaptorCompositeTreeWidget::buildTree( - pqTreeWidgetItem* item, vtkPVDataInformation* info) -{ - this->Internal->Items.push_back(item); - item->setData(0, FLAT_INDEX, this->FlatIndex); - item->setData(0, NODE_TYPE, LEAF); - this->FlatIndex++; - if (!info) - { - return; - } - - vtkPVCompositeDataInformation* cinfo = info->GetCompositeDataInformation(); - if (!cinfo->GetDataIsComposite()) - { - return; - } - - if (cinfo->GetDataIsMultiPiece()) - { - if (this->ShowDatasetsInMultiPiece || - (this->IndexMode == INDEX_MODE_LEVEL_INDEX && - this->Internal->DomainMode != vtkSMCompositeTreeDomain::NON_LEAVES)) - { - // multi-piece is treated as a leaf node, unless the IndexMode is - // INDEX_MODE_LEVEL_INDEX, in which case the pieces in the multi-piece are - // further expanded. - item->setData(0, NODE_TYPE, NON_LEAF); - // user should be able to select individual pieces. - for (unsigned int cc = 0; cc < cinfo->GetNumberOfChildren(); cc++) - { - // We don't fetch the names for each piece in a vtkMultiPieceDataSet - // hence we just make up a name, - QString childLabel = QString("DataSet %1").arg(cc); - if (this->ShowFlatIndex) - { - childLabel = QString("DataSet (%1)").arg(this->FlatIndex); - } - - pqTreeWidgetItem* child = new pqCompositeTreeWidgetItem(item, QStringList(childLabel)); - child->setCallbackHandler(this->CallbackAdaptor); - child->setToolTip(0, child->text(0)); - child->setData(0, ORIGINAL_LABEL, childLabel); - child->setData(0, BLOCK_NAME, QString()); - this->buildTree(child, NULL); - child->setData(0, AMR_BLOCK_INDEX, cc); - child->setData(0, AMR_LEVEL_NUMBER, this->LevelNo); - } - } - else - { - this->FlatIndex += cinfo->GetNumberOfChildren(); - } - item->setExpanded(false); // multipieces are not expanded by default. - return; - } - - // A composite dataset (non-multipiece) is always a non-leaf node. - item->setExpanded(true); - item->setData(0, NODE_TYPE, NON_LEAF); - - this->LevelNo = 0; - bool is_hierarchical = - (strcmp(info->GetCompositeDataClassName(), "vtkHierarchicalBoxDataSet") == 0); - - for (unsigned int cc = 0; cc < cinfo->GetNumberOfChildren(); cc++) - { - vtkPVDataInformation* childInfo = cinfo->GetDataInformation(cc); - QString childLabel = QString("DataSet %1").arg(cc); - QString block_name; - - bool is_leaf = true; - if (childInfo && childInfo->GetCompositeDataInformation()->GetDataIsComposite()) - { - childLabel = is_hierarchical ? QString("Level %1").arg(cc) : QString("Block %1").arg(cc); - is_leaf = false; - } - if (const char* cname = cinfo->GetName(cc)) - { - if (cname[0]) - { - childLabel = cname; - block_name = cname; - } - } - - if (this->ShowFlatIndex) - { - childLabel = QString("%1 (%2)").arg(childLabel).arg(this->FlatIndex); - } - - if (this->Internal->DomainMode != vtkSMCompositeTreeDomain::NON_LEAVES || !is_leaf) - { - pqTreeWidgetItem* child = new pqCompositeTreeWidgetItem(item, QStringList(childLabel)); - child->setCallbackHandler(this->CallbackAdaptor); - child->setData(0, ORIGINAL_LABEL, childLabel); - child->setData(0, BLOCK_NAME, block_name); - child->setToolTip(0, child->text(0)); - this->buildTree(child, cinfo->GetDataInformation(cc)); - child->setData(0, AMR_LEVEL_NUMBER, this->LevelNo); - this->LevelNo++; - } - else - { - // don't add leaf nodes, when non-leaves alone are selectable. - this->FlatIndex++; - } - } -} - -//----------------------------------------------------------------------------- -void pqSignalAdaptorCompositeTreeWidget::updateSelectionCounts() -{ - if (!this->ShowSelectedElementCounts) - { - // Nothing to do. - return; - } - - if (!this->Internal->Domain) - { - return; - } - - // Iterate over the selection data information and then update the labels. - vtkSMSourceProxy* sourceProxy = this->Internal->Domain->GetSource(); - if (!sourceProxy || !sourceProxy->GetSelectionOutput(this->Internal->Domain->GetSourcePort())) - { - return; - } - - vtkPVDataInformation* info = - sourceProxy->GetSelectionOutput(this->Internal->Domain->GetSourcePort())->GetDataInformation(); - - foreach (pqTreeWidgetItem* item, this->Internal->Items) - { - if (item->data(0, NODE_TYPE).toInt() != LEAF) - { - continue; - } - - unsigned int flat_index = item->data(0, FLAT_INDEX).toUInt(); - vtkPVDataInformation* subInfo = - info->GetDataInformationForCompositeIndex(static_cast(flat_index)); - if (subInfo) - { - item->setText(0, QString("%1 (%2, %3)") - .arg(item->data(0, ORIGINAL_LABEL).toString()) - .arg(subInfo->GetNumberOfPoints()) - .arg(subInfo->GetNumberOfCells())); - item->setToolTip(0, item->text(0)); - } - else - { - item->setText(0, QString("%1").arg(item->data(0, ORIGINAL_LABEL).toString())); - item->setToolTip(0, item->text(0)); - } - } -} - -//----------------------------------------------------------------------------- -/// Set up the callback to know when the selection changes, so that we can -/// update the selected cells/points counts. -void pqSignalAdaptorCompositeTreeWidget::setupSelectionUpdatedCallback( - vtkSMSourceProxy* source, unsigned int port) -{ - this->Internal->VTKConnectSelection->Disconnect(); - if (source) - { - vtkSMSourceProxy* selProxy = source->GetSelectionOutput(port); - if (selProxy) - { - this->Internal->VTKConnectSelection->Connect( - selProxy, vtkCommand::UpdateDataEvent, this, SLOT(updateSelectionCounts())); - } - } -} diff --git a/Qt/Components/pqSignalAdaptorCompositeTreeWidget.h b/Qt/Components/pqSignalAdaptorCompositeTreeWidget.h deleted file mode 100644 index cb0d1b5c63..0000000000 --- a/Qt/Components/pqSignalAdaptorCompositeTreeWidget.h +++ /dev/null @@ -1,262 +0,0 @@ -/*========================================================================= - - Program: ParaView - Module: pqSignalAdaptorCompositeTreeWidget.h - - Copyright (c) 2005-2008 Sandia Corporation, Kitware Inc. - All rights reserved. - - ParaView is a free software; you can redistribute it and/or modify it - under the terms of the ParaView license version 1.2. - - See License_v1.2.txt for the full ParaView license. - A copy of this license can be obtained by contacting - Kitware Inc. - 28 Corporate Drive - Clifton Park, NY 12065 - USA - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -========================================================================*/ -#ifndef pqSignalAdaptorCompositeTreeWidget_h -#define pqSignalAdaptorCompositeTreeWidget_h - -#include "pqComponentsModule.h" -#include -#include - -class pqTreeWidgetItem; -class QTreeWidget; -class QTreeWidgetItem; -class vtkPVDataInformation; -class vtkSMIntVectorProperty; -class vtkSMOutputPort; -class vtkSMSourceProxy; - -/** -* pqSignalAdaptorCompositeTreeWidget is used to connect a property with -* vtkSMCompositeTreeDomain as its domain to a Tree widget. It updates the tree -* to show composite data tree. -* Caveats: This widget does not handle SINGLE_ITEM selection where non-leaves -* are acceptable. -*/ -class PQCOMPONENTS_EXPORT pqSignalAdaptorCompositeTreeWidget : public QObject -{ - Q_OBJECT - typedef QObject Superclass; - - Q_PROPERTY(QList values READ values WRITE setValues) -public: - enum IndexModes - { - INDEX_MODE_FLAT, - INDEX_MODE_LEVEL_INDEX, // this mode works only for 1 level deep trees. - INDEX_MODE_LEVEL, // this mode works only for 1 level deep trees. - }; - - /** - * Constructor. \c domain is used to build the tree layout to show in the - * widget. - * \c autoUpdateWidgetVisibility - is true, the tree widget is hidden if the - * data information says that the data is - * not composite. - * \c showSelectedElementCounts - when true, next to each leaf node, an entry - * will be added showing the number of - * selected elements (cells|points). - */ - pqSignalAdaptorCompositeTreeWidget(QTreeWidget*, vtkSMIntVectorProperty* smproperty, - bool autoUpdateWidgetVisibility = false, bool showSelectedElementCounts = false); - - /** - * Alternate constructor. - * \c outputport - the output port producing the composite dataset to show. - * \c domainMode - vtkSMCompositeTreeDomain::ALL|LEAVES|NON_LEAVES|NONE. - * Indicates what types of nodes in the composite tree - * are selectable. - * \c indexMode - indicates how the values are set/get (using - * composite-flat-index, using level-dataset-index or using - * only the level number. - * \c selectMultiple - true if possible to select multiple nodes. - * \c autoUpdateWidgetVisibility - is true, the tree widget is hidden if the - * data information says that the data is - * not composite. - * \c showSelectedElementCounts - when true, next to each leaf node, an entry - * will be added showing the number of - * selected elements (cells|points). - */ - pqSignalAdaptorCompositeTreeWidget(QTreeWidget*, vtkSMOutputPort* outputport, int domainMode, - IndexModes indexMode = INDEX_MODE_FLAT, bool selectMultiple = false, - bool autoUpdateWidgetVisibility = false, bool showSelectedElementCounts = false); - - /** - * Destructor - */ - virtual ~pqSignalAdaptorCompositeTreeWidget(); - - /** - * Returns the current value. - * This is a QList of unsigned ints. - */ - QList values() const; - - /** - * When set, the adaptor will update the visibility of the widget depending - * on whether the data is composite or not. - */ - void setAutoUpdateWidgetVisibility(bool val) { this->AutoUpdateWidgetVisibility = val; } - bool autoUpdateWidgetVisibility() const { return this->AutoUpdateWidgetVisibility; } - - /** - * Select the item with the given flat index. - */ - void select(unsigned int flatIndex); - - /** - * API to get information about the currently selected item. - * Returns the flat index for the current item. - */ - unsigned int getCurrentFlatIndex(bool* valid = NULL); - - /** - * API to get information about an item. - * Returns the block name for the item. - */ - QString blockName(const QTreeWidgetItem* item) const; - - /** - * API to get information about an item. - * Returns the AMR level for the item if valid. - */ - unsigned int hierarchicalLevel(const QTreeWidgetItem* item) const; - - /** - * API to get information about an item. - * Returns the AMR block number for the item if valid. - */ - unsigned int hierarchicalBlockIndex(const QTreeWidgetItem* item) const; - - /** - * API to get information about an item. - * Returns the flat index for the item. - */ - unsigned int flatIndex(const QTreeWidgetItem* item) const; - -public slots: - /** - * Set the values. - */ - void setValues(const QList& values); - - /** - * Called when domain changes. - */ - void domainChanged(); - - /** - * Called when the output port says that the data information has been - * updated. - */ - void portInformationChanged(); - -signals: - /** - * Fired when the widget value changes. - */ - void valuesChanged(); - -private slots: - - /** - * Called to update the labels to show the current selected elements - * information. - */ - void updateSelectionCounts(); - -private: - Q_DISABLE_COPY(pqSignalAdaptorCompositeTreeWidget) - - /** - * Set up the callback to know when the selection changes, so that we can - * update the selected cells/points counts. - */ - void setupSelectionUpdatedCallback(vtkSMSourceProxy* source, unsigned int port); - - void buildTree(pqTreeWidgetItem* item, vtkPVDataInformation* info); - - /** - * updates the check flags for all the items. - */ - void updateItemFlags(); - - class pqInternal; - pqInternal* Internal; - - enum MetaData - { - FLAT_INDEX = Qt::UserRole, - AMR_LEVEL_NUMBER = Qt::UserRole + 1, - AMR_BLOCK_INDEX = Qt::UserRole + 2, - NODE_TYPE = Qt::UserRole + 3, - ORIGINAL_LABEL = Qt::UserRole + 4, - BLOCK_NAME = Qt::UserRole + 5 - }; - - enum NodeTypes - { - LEAF = 21, - NON_LEAF = 22, - }; - - enum CheckModes - { - SINGLE_ITEM, - MULTIPLE_ITEMS - }; - - IndexModes IndexMode; - - // Determines if the widget should allow checking only 1 item at a time or - // multiple items should be check-able. - CheckModes CheckMode; - - // These are used by buildTree() to determin indices for the nodes. - unsigned int FlatIndex; - unsigned int LevelNo; - - bool AutoUpdateWidgetVisibility; - - bool ShowFlatIndex; - - bool ShowSelectedElementCounts; - - // When set to true, all pieces within a multipiece are shown. - bool ShowDatasetsInMultiPiece; - - /** - * Code common to both variants of the constructor. - */ - void constructor(QTreeWidget* tree, bool autoUpdateVisibility); - - /** - * Called when an item check state is toggled. This is used only when - * this->CheckMode == SINGLE_ITEM. We uncheck all other items. - */ - void updateCheckState(pqTreeWidgetItem* item, int column); - - friend class pqCallbackAdaptor; - class pqCallbackAdaptor; - pqCallbackAdaptor* CallbackAdaptor; -}; - -#endif -- GitLab