Commit 4acf76e7 authored by David Thompson's avatar David Thompson Committed by Kitware Robot

Merge topic 'attribute-query'

f60e6e18 Fix qtComponentItem to accept any components...
174b23aa Implement simple attribute query filtering.
d0d9d984 Wrap the `Resource::find()` query method.
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Acked-by: T.J. Corona's avatarT.J. Corona <tj.corona@kitware.com>
Merge-request: !1316
parents 9084d1ed f60e6e18
Pipeline #122674 failed with stage
in 0 seconds
......@@ -894,10 +894,33 @@ smtk::resource::ComponentPtr Resource::find(const smtk::common::UUID& attId) con
}
std::function<bool(const smtk::resource::ComponentPtr&)> Resource::queryOperation(
const std::string&) const
const std::string& filter) const
{
// TODO: fill me in!
return [](const smtk::resource::ComponentPtr&) { return true; };
if (filter.empty() || filter == "any" || filter == "*")
{
return [](const smtk::resource::ComponentPtr&) { return true; };
}
const std::string attributeFilter("attribute");
if (!filter.compare(0, attributeFilter.size(), attributeFilter))
{
std::string spec = filter.substr(attributeFilter.size());
const std::string definitionFilter("[type='");
auto sszm2 = spec.size() - 2;
auto dfsz = definitionFilter.size();
if (!spec.compare(0, dfsz, definitionFilter) && spec.substr(sszm2) == "']")
{
const std::string sdef = spec.substr(dfsz, sszm2 - dfsz);
smtk::attribute::DefinitionPtr defn = this->findDefinition(sdef);
if (defn)
{
return [defn](const smtk::resource::ComponentPtr& comp) {
auto attr = std::dynamic_pointer_cast<Attribute>(comp);
return (attr && attr->isA(defn));
};
}
}
}
return [](const smtk::resource::ComponentPtr&) { return false; };
}
// visit all components in the resource.
......
......@@ -39,6 +39,14 @@ namespace attribute
class Attribute;
class Definition;
/**\brief Store information about attribute definitions and instances.
*
* This subclass of smtk::resource::Resource holds attribute data.
* The file contains at least a schema (definitions and item-definitions)
* but may also contain attribute instances that conform to the schema
* as well as information about how to present the attribute system
* through a series of views.
*/
class SMTKCORE_EXPORT Resource
: public smtk::resource::DerivedFrom<Resource, smtk::resource::Resource>
{
......@@ -89,8 +97,19 @@ public:
// given a resource component's UUID, return the resource component.
smtk::resource::ComponentPtr find(const smtk::common::UUID& id) const override;
// given a std::string describing a query, return a functor for performing the
// query.
/**\brief Given a std::string describing a query, return a functor for performing the query.
*
* Currently, the query string must be either empty, `*`, `any`, or of the form
* `attribute[type='xxx']`, where `xxx` specifies the name of a definition that
* the resulting attributes instantiate.
* Note that if an attribute type `xxx` is provided, any attribute whose
* definition inherits from `xxx` as a base will be included, not just
* those whose immediate, concrete type is `xxx`.
*
* If the query string filters attributes by their definition types, note that
* the definition must exist at the time that queryOperation() is called.
* This requirement allows faster repeated evaluation of the query.
*/
std::function<bool(const smtk::resource::ComponentPtr&)> queryOperation(
const std::string&) const override;
......
......@@ -31,6 +31,7 @@ set(smtkAttributePythonDataTests
)
set(smtkAttributePythonNewDataTests
attributeItemByPath
attributeQuery
)
if (SMTK_DATA_DIR)
......
import sys
#=============================================================================
#
# Copyright (c) Kitware, Inc.
# All rights reserved.
# See LICENSE.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even
# the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the above copyright notice for more information.
#
#=============================================================================
import smtk
from smtk import attribute
from smtk import io
import smtk.testing
import os
class TestAttributeQuery(smtk.testing.TestCase):
def setUp(self):
if smtk.testing.DATA_DIR == '':
self.skipTest('SMTK test-data directory not provided')
self.resource = smtk.attribute.Resource.create()
logger = smtk.io.Logger()
reader = smtk.io.AttributeReader()
filenm = os.path.join(smtk.testing.DATA_DIR, 'attribute',
'attribute_collection', 'HydraTemplateV1.sbt')
status = reader.read(self.resource, filenm, logger)
print(
'\n'.join([logger.record(i).message for i in range(logger.numberOfRecords())]))
self.assertFalse(status, 'Could not read {fn}'.format(fn=filenm))
att = self.resource.createAttribute('hydrostat')
att = self.resource.createAttribute('BasicTurbulenceModel')
att = self.resource.createAttribute('InitialConditions')
att = self.resource.createAttribute('ppesolver')
def testQueryAny(self):
attrs = self.resource.find('any')
for aa in attrs:
print('Found %s of type %s' % (aa.name(), aa.type()))
self.assertEqual(
len(attrs), 4, 'Expected 4 attributes, got %d.' % len(attrs))
def testQueryByDefinition(self):
attrs = self.resource.find("attribute[type='hydrostat']")
self.assertEqual(
len(attrs), 1, 'Expected 1 attributes, got %d.' % len(attrs))
attr = attrs.pop()
self.assertEqual(attr.type(), 'hydrostat',
'Unexpected attribute type "%s"' % attr.type())
if __name__ == '__main__':
smtk.testing.process_arguments()
smtk.testing.main()
......@@ -158,23 +158,19 @@ int qtComponentItem::decorateWithMembership(smtk::view::DescriptivePhrasePtr phr
smtk::view::VisibilityContent::decoratePhrase(
phr, [this](smtk::view::VisibilityContent::Query qq, int val,
smtk::view::ConstPhraseContentPtr data) {
smtk::model::EntityPtr ent =
data ? std::dynamic_pointer_cast<smtk::model::Entity>(data->relatedComponent()) : nullptr;
smtk::model::ResourcePtr mResource = ent
? ent->modelResource()
: (data ? std::dynamic_pointer_cast<smtk::model::Resource>(data->relatedResource())
: nullptr);
auto comp = data ? data->relatedComponent() : nullptr;
auto rsrc = comp ? comp->resource() : (data ? data->relatedResource() : nullptr);
switch (qq)
{
case smtk::view::VisibilityContent::DISPLAYABLE:
return (ent || (!ent && mResource)) ? 1 : 0;
return (comp || (!comp && rsrc)) ? 1 : 0;
case smtk::view::VisibilityContent::EDITABLE:
return (ent || (!ent && mResource)) ? 1 : 0;
return (comp || (!comp && rsrc)) ? 1 : 0;
case smtk::view::VisibilityContent::GET_VALUE:
if (ent)
if (comp)
{
auto valIt = m_p->m_members.find(ent);
auto valIt = m_p->m_members.find(comp);
if (valIt != m_p->m_members.end())
{
return valIt->second;
......@@ -183,7 +179,7 @@ int qtComponentItem::decorateWithMembership(smtk::view::DescriptivePhrasePtr phr
}
return 0; // visibility is false if the component is not a model entity or NULL.
case smtk::view::VisibilityContent::SET_VALUE:
if (ent)
if (comp)
{
if (val && !m_p->m_members.empty())
{
......@@ -195,7 +191,7 @@ int qtComponentItem::decorateWithMembership(smtk::view::DescriptivePhrasePtr phr
m_p->m_phraseModel->triggerDataChanged();
}
}
m_p->m_members[ent] = val ? 1 : 0; // FIXME: Use a bit specified by the application.
m_p->m_members[comp] = val ? 1 : 0; // FIXME: Use a bit specified by the application.
this->updateSynopsisLabels();
return 1;
}
......
......@@ -27,6 +27,7 @@ PySharedPtrClass< smtk::resource::Resource, smtk::resource::PersistentObject > p
.def("location", &smtk::resource::Resource::location)
.def("setId", &smtk::resource::Resource::setId)
.def("setLocation", &smtk::resource::Resource::setLocation)
.def("find", (smtk::resource::ComponentSet (smtk::resource::Resource::*)(const std::string&) const) &smtk::resource::Resource::find)
;
return instance;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment