diff --git a/Applications/ParaView/Testing/XML/SpreadSheet3.xml b/Applications/ParaView/Testing/XML/SpreadSheet3.xml index 75c49e54862333012213501ad360cbaeab217446..1b28fc0776fe8c6129d3f150ef61e4c5e84cd304 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/Core/vtkSMCompositeTreeDomain.cxx b/ParaViewCore/ServerManager/Core/vtkSMCompositeTreeDomain.cxx index 40d4b1044c442fad09f69e36a77c5ec2ad67061d..5fee068a3afdd613beb220f27bc5c19674233599 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 d8a427239bd5a20dfa0b15ffb4d7896404257649..f8344faaaf429c5687bc1c6144313daf16d2b06c 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 173af097839bdb0977c60dd776e2b58d758d7cca..c070c36e80eb34a8997b53e2bec7b037430fe9c3 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"> - - + diff --git a/Plugins/LagrangianParticleTracker/Testing/LagrangianSurfaceHelperNone.xml b/Plugins/LagrangianParticleTracker/Testing/LagrangianSurfaceHelperNone.xml index 6ca6e4375529299629e81efe8f88ea5429c18ec4..b977b68614ad799dc49b162ad4af85b80e7803ca 100644 --- a/Plugins/LagrangianParticleTracker/Testing/LagrangianSurfaceHelperNone.xml +++ b/Plugins/LagrangianParticleTracker/Testing/LagrangianSurfaceHelperNone.xml @@ -23,6 +23,7 @@ + diff --git a/Plugins/LagrangianParticleTracker/pqIntegrationModelSurfaceHelperWidget.cxx b/Plugins/LagrangianParticleTracker/pqIntegrationModelSurfaceHelperWidget.cxx index 9fb880279282a3ec4f9354d98bfebc344966c461..3d7b55fdbe1caf1aaab759fd389f37c80d7c513b 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); diff --git a/Qt/Components/CMakeLists.txt b/Qt/Components/CMakeLists.txt index 6a42c13f888db574faab8e18fbf94abf5f9ff9dc..f95c83185c439ea5e9dfc348eeee6e08aa262940 100644 --- a/Qt/Components/CMakeLists.txt +++ b/Qt/Components/CMakeLists.txt @@ -62,8 +62,8 @@ set (Module_SRCS pqColorChooserButtonWithPalettes.h pqComboBoxDomain.cxx pqComboBoxDomain.h - pqCommandPropertyWidget.h pqCommandPropertyWidget.cxx + pqCommandPropertyWidget.h pqComparativeCueWidget.cxx pqComparativeCueWidget.h pqComparativeVisPanel.cxx @@ -72,6 +72,10 @@ set (Module_SRCS pqComponentsInit.h pqComponentsTestUtility.cxx pqComponentsTestUtility.h + pqCompositeDataInformationTreeModel.cxx + pqCompositeDataInformationTreeModel.h + pqCompositeTreePropertyWidget.cxx + pqCompositeTreePropertyWidget.h pqCustomFilterDefinitionModel.cxx pqCustomFilterDefinitionModel.h pqCustomFilterDefinitionWizard.cxx @@ -253,8 +257,6 @@ set (Module_SRCS pqSetBreakpointDialog.h pqSettingsDialog.cxx pqSettingsDialog.h - pqSignalAdaptorCompositeTreeWidget.cxx - pqSignalAdaptorCompositeTreeWidget.h pqSignalAdaptorKeyFrameType.cxx pqSignalAdaptorKeyFrameType.h pqSignalAdaptorSelectionTreeWidget.cxx @@ -323,6 +325,8 @@ set (Module_MOC_HDRS pqComparativeCueWidget.h pqComparativeVisPanel.h pqComponentsTestUtility.h + pqCompositeDataInformationTreeModel.h + pqCompositeTreePropertyWidget.h pqCustomFilterDefinitionWizard.h pqCustomFilterManager.h pqCustomFilterManagerModel.h @@ -410,7 +414,6 @@ set (Module_MOC_HDRS pqServerLauncher.h pqSetBreakpointDialog.h pqSettingsDialog.h - pqSignalAdaptorCompositeTreeWidget.h pqSignalAdaptorKeyFrameType.h pqSignalAdaptorSelectionTreeWidget.h pqSignalAdaptorTreeWidget.h diff --git a/Qt/Components/Resources/UI/pqQueryCompositeTreeDialog.ui b/Qt/Components/Resources/UI/pqQueryCompositeTreeDialog.ui index a010b22cc491f1c1affae2d04454dfc11404d6bc..1a9088ef24de57192ebf92db2e9d7e18b791c833 100644 --- a/Qt/Components/Resources/UI/pqQueryCompositeTreeDialog.ui +++ b/Qt/Components/Resources/UI/pqQueryCompositeTreeDialog.ui @@ -15,15 +15,13 @@ - + 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 0000000000000000000000000000000000000000..a020e4fc6b317624b17e6f06699e993b25dcdc8e --- /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 0000000000000000000000000000000000000000..2b76a79558d41ff2387f41d1a7b6b1f8d7b07ac4 --- /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 0000000000000000000000000000000000000000..b006adc6e906f8fd75349d688b5cf2a93a2c97ad --- /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 0000000000000000000000000000000000000000..74401e41a3ea352a448791ece85cdcf5b31dd55d --- /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 039fbb465cfe7e21d9bc70dbf1090a547331711b..cc81c85e223722e70ab99b591345b0fd3a585e48 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 2f4b0ef478aa3a8bf373e40ee74f2a9318741ebc..ababd18b28d0f66632a348eb4d8e42a60fc3ebba 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 b7745fe4ded59fa06c41aeaafce07f83de435bde..30d33e9fa0ceca7978b4466d89debceee936ab74 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 5dafeccf1238f347b769b58e77f9667b700f285a..d681103b01b899ba5a658d1b9bdfd652a542beba 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" @@ -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()); @@ -513,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 8ac96722e2c5496adf9b2eefb324a00945be7701..0000000000000000000000000000000000000000 --- 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 cb0d1b5c633084689944c82b047e835ce643a0b5..0000000000000000000000000000000000000000 --- 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 diff --git a/Qt/Widgets/pqTreeView.cxx b/Qt/Widgets/pqTreeView.cxx index 5ae2c059dd14a53632838c09b2bb7ae6948ce7a6..ca67fc805c7bd3c802b27f14818bb37f24a416f8 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) @@ -52,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 @@ -121,13 +140,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; diff --git a/Testing/Data/Baseline/SpreadSheet3.png.md5 b/Testing/Data/Baseline/SpreadSheet3.png.md5 index c79763d491c54bdf73f7958162e5e083f26f46ee..4640b0a8c250e163e31c2533b813cc46ab164a64 100644 --- a/Testing/Data/Baseline/SpreadSheet3.png.md5 +++ b/Testing/Data/Baseline/SpreadSheet3.png.md5 @@ -1 +1 @@ -044dca08db93e83b1f09bf4c4a440b8d +305ae44caff67b97e798d1a71b3475ae