Commit ef965d1e authored by David Thompson's avatar David Thompson

Various improvements and fixes to the GUI.

+ Refactor the resource-panel decorator into a method.
+ Properly update the attribute when the sphere widget changes.
  ParaView now emits a signal when properties are changed via Qt.
  Use it to update the SMTK attribute's item(s).
  Do not print errors when none may have occurred.
+ Fix how auxiliary geometry is handled.
  Without this, the RGG extension would be used to load OBJ
  files (rather than the VTK extension) just because it was
  first in the list.
+ Remove redundant created/modified entries in AddAuxiliaryGeometry.
  This appears to be cruft accumulated during the
  migration from ModelEntityItem to ReferenceItem/ComponentItem.
+ Prevent a crash during first-time initialization in qtReferenceItem.
+ Eliminate unneeded code from qtResourceItem.
  The base class now handles this.
+ Override `smtk::resource::Resource::name()`.
  Make the name the stem of the location URL.
  Showing a UUID here is really bad for users,
  so pretty much anything is better.
+ Fix attribute association op's specification.
+ Fix qtResourceItem membership checkboxes.
+ Make qtReferenceItem return the proper "acceptable types" enum,
  which fixes an issue where associations which are supposed to be
  resources instead list components.
+ Add a phrase model that shows the current selection.
+ Allow phrase model sources to include a selection.
parent f3a27a80
......@@ -14,13 +14,13 @@
<p>The visualized lists of attribute component items are
populated from associated resources.
</DetailedDescription>
<AssociationsDef>
<AssociationsDef Name="attribute">
<Accepts><Resource Name="smtk::attribute::Resource"/></Accepts>
</AssociationsDef>
<ItemDefinitions>
<Resource Name = "associate to" Label = "Associated Resource"
NumberOfRequiredValues="1" Extensible="true">
<Resource Name="associate to" Label="associated resource(s)"
NumberOfRequiredValues="1" Extensible="true">
<Accepts>
<Resource Name="smtk::resource::Resource"/>
</Accepts>
......
......@@ -60,7 +60,7 @@ public:
: m_selnSource("resource panel")
, m_selnLabel("selected")
, m_hoverLabel("hovered")
, m_resourceTreeStyle(vtkSMTKSettings::HierarchicalStyle)
, m_resourceTreeStyle(-1)
, m_updatingPanelSelectionFromSMTK(false)
{
}
......@@ -79,93 +79,11 @@ public:
parent->setWidget(ww);
m_phraseModel = smtk::view::ResourcePhraseModel::create();
m_phraseModel->setDecorator([this](smtk::view::DescriptivePhrasePtr phr) {
smtk::view::VisibilityContent::decoratePhrase(phr, [this](
smtk::view::VisibilityContent::Query qq,
int val,
smtk::view::ConstPhraseContentPtr data) {
auto comp = data->relatedComponent();
auto rsrc = data->relatedResource();
smtk::model::EntityPtr ent =
data ? std::dynamic_pointer_cast<smtk::model::Entity>(comp) : nullptr;
smtk::model::ResourcePtr modelRsrc = ent
? ent->modelResource()
: (data ? std::dynamic_pointer_cast<smtk::model::Resource>(rsrc) : nullptr);
smtk::mesh::ComponentPtr msh =
data ? std::dynamic_pointer_cast<smtk::mesh::Component>(comp) : nullptr;
smtk::mesh::ResourcePtr meshRsrc = msh
? std::dynamic_pointer_cast<smtk::mesh::Resource>(msh->resource())
: (data ? std::dynamic_pointer_cast<smtk::mesh::Resource>(rsrc) : nullptr);
auto smtkBehavior = pqSMTKBehavior::instance();
// TODO: We could check more than just that the view is non-null.
// For instance, does the resource have a representation in the active view?
// However, that gets expensive.
bool validView = pqActiveObjects::instance().activeView() ? true : false;
switch (qq)
{
case smtk::view::VisibilityContent::DISPLAYABLE:
return validView && (ent || (!ent && modelRsrc) || (msh || (!ent && meshRsrc))) ? 1 : 0;
case smtk::view::VisibilityContent::EDITABLE:
return validView && (ent || (!ent && modelRsrc) || (msh || (!ent && meshRsrc))) ? 1 : 0;
case smtk::view::VisibilityContent::GET_VALUE:
if (ent || msh)
{
auto valIt = m_visibleThings.find(comp->id());
if (valIt != m_visibleThings.end())
{
return valIt->second;
}
return 1; // visibility is assumed if there is no entry.
}
else if (modelRsrc || meshRsrc)
{
auto view = pqActiveObjects::instance().activeView();
auto pvrc = smtkBehavior->getPVResource(rsrc);
// If we are trying to get the value of a resource that has no
// pipeline source, we create one.
if (pvrc == nullptr)
{
pvrc = pqSMTKRenderResourceBehavior::instance()->createPipelineSource(rsrc);
}
auto mapr = pvrc ? pvrc->getRepresentation(view) : nullptr;
return mapr ? mapr->isVisible() : 0;
}
return 0; // visibility is false if the component is not a model entity or NULL.
case smtk::view::VisibilityContent::SET_VALUE:
if (ent || msh)
{ // Find the mapper in the active view for the related resource, then set the visibility.
auto view = pqActiveObjects::instance().activeView();
auto pvrc = smtkBehavior->getPVResource(data->relatedResource());
auto mapr = pvrc ? pvrc->getRepresentation(view) : nullptr;
auto smap = dynamic_cast<pqSMTKModelRepresentation*>(mapr);
if (smap)
{
int rval = smap->setVisibility(comp, val ? true : false) ? 1 : 0;
smap->renderViewEventually();
return rval;
}
}
else if (modelRsrc || meshRsrc)
{ // A resource, not a component, is being modified. Change the pipeline object's visibility.
auto view = pqActiveObjects::instance().activeView();
auto pvrc = smtkBehavior->getPVResource(rsrc);
auto mapr = pvrc ? pvrc->getRepresentation(view) : nullptr;
if (mapr)
{
mapr->setVisible(!mapr->isVisible());
pqActiveObjects::instance().setActiveSource(pvrc);
mapr->renderViewEventually();
return 1;
}
}
return 0;
}
return 0;
});
smtk::view::VisibilityContent::decoratePhrase(
phr, [this](smtk::view::VisibilityContent::Query qq, int val,
smtk::view::ConstPhraseContentPtr data) {
return this->panelPhraseDecorator(qq, val, data);
});
});
m_model = new smtk::extension::qtDescriptivePhraseModel;
m_model->setPhraseModel(m_phraseModel);
......@@ -196,6 +114,93 @@ public:
parent->updateSettings();
}
int panelPhraseDecorator(
smtk::view::VisibilityContent::Query qq, int val, smtk::view::ConstPhraseContentPtr data)
{
auto comp = data->relatedComponent();
auto rsrc = data->relatedResource();
smtk::model::EntityPtr ent =
data ? std::dynamic_pointer_cast<smtk::model::Entity>(comp) : nullptr;
smtk::model::ResourcePtr modelRsrc = ent
? ent->modelResource()
: (data ? std::dynamic_pointer_cast<smtk::model::Resource>(rsrc) : nullptr);
smtk::mesh::ComponentPtr msh =
data ? std::dynamic_pointer_cast<smtk::mesh::Component>(comp) : nullptr;
smtk::mesh::ResourcePtr meshRsrc = msh
? std::dynamic_pointer_cast<smtk::mesh::Resource>(msh->resource())
: (data ? std::dynamic_pointer_cast<smtk::mesh::Resource>(rsrc) : nullptr);
auto smtkBehavior = pqSMTKBehavior::instance();
// TODO: We could check more than just that the view is non-null.
// For instance, does the resource have a representation in the active view?
// However, that gets expensive.
bool validView = pqActiveObjects::instance().activeView() ? true : false;
switch (qq)
{
case smtk::view::VisibilityContent::DISPLAYABLE:
return validView && (ent || (!ent && modelRsrc) || (msh || (!ent && meshRsrc))) ? 1 : 0;
case smtk::view::VisibilityContent::EDITABLE:
return validView && (ent || (!ent && modelRsrc) || (msh || (!ent && meshRsrc))) ? 1 : 0;
case smtk::view::VisibilityContent::GET_VALUE:
if (ent || msh)
{
auto valIt = m_visibleThings.find(comp->id());
if (valIt != m_visibleThings.end())
{
return valIt->second;
}
return 1; // visibility is assumed if there is no entry.
}
else if (modelRsrc || meshRsrc)
{
auto view = pqActiveObjects::instance().activeView();
auto pvrc = smtkBehavior->getPVResource(rsrc);
// If we are trying to get the value of a resource that has no
// pipeline source, we create one.
if (pvrc == nullptr)
{
pvrc = pqSMTKRenderResourceBehavior::instance()->createPipelineSource(rsrc);
}
auto mapr = pvrc ? pvrc->getRepresentation(view) : nullptr;
return mapr ? mapr->isVisible() : 0;
}
return 0; // visibility is false if the component is not a model entity or NULL.
case smtk::view::VisibilityContent::SET_VALUE:
if (ent || msh)
{ // Find the mapper in the active view for the related resource, then set the visibility.
auto view = pqActiveObjects::instance().activeView();
auto pvrc = smtkBehavior->getPVResource(data->relatedResource());
auto mapr = pvrc ? pvrc->getRepresentation(view) : nullptr;
auto smap = dynamic_cast<pqSMTKModelRepresentation*>(mapr);
if (smap)
{
int rval = smap->setVisibility(comp, val ? true : false) ? 1 : 0;
smap->renderViewEventually();
return rval;
}
}
else if (modelRsrc || meshRsrc)
{ // A resource, not a component, is being modified. Change the pipeline object's visibility.
auto view = pqActiveObjects::instance().activeView();
auto pvrc = smtkBehavior->getPVResource(rsrc);
auto mapr = pvrc ? pvrc->getRepresentation(view) : nullptr;
if (mapr)
{
mapr->setVisible(!mapr->isVisible());
pqActiveObjects::instance().setActiveSource(pvrc);
mapr->renderViewEventually();
return 1;
}
}
return 0;
}
return 0;
}
QPointer<smtk::extension::qtDescriptivePhraseModel> m_model;
QPointer<smtk::extension::qtDescriptivePhraseDelegate> m_delegate;
std::map<smtk::resource::ManagerPtr, int> m_observers;
......@@ -392,7 +397,8 @@ void pqSMTKResourcePanel::resourceManagerAdded(pqSMTKWrapper* wrapper, pqServer*
}
});
}
m_p->m_phraseModel->addSource(wrapper->smtkResourceManager(), wrapper->smtkOperationManager());
m_p->m_phraseModel->addSource(
wrapper->smtkResourceManager(), wrapper->smtkOperationManager(), wrapper->smtkSelection());
}
void pqSMTKResourcePanel::resourceManagerRemoved(pqSMTKWrapper* mgr, pqServer* server)
......@@ -414,7 +420,8 @@ void pqSMTKResourcePanel::resourceManagerRemoved(pqSMTKWrapper* mgr, pqServer* s
}
m_p->m_seln = nullptr;
m_p->m_phraseModel->removeSource(mgr->smtkResourceManager(), mgr->smtkOperationManager());
m_p->m_phraseModel->removeSource(
mgr->smtkResourceManager(), mgr->smtkOperationManager(), mgr->smtkSelection());
}
void pqSMTKResourcePanel::activeViewChanged(pqView* view)
......
......@@ -40,6 +40,33 @@ public:
static qtItem* createBoxItemWidget(const AttributeItemInfo& info);
bool createProxyAndWidget(vtkSMProxy*& proxy, pqInteractivePropertyWidget*& widget) override;
void updateItemFromWidget() override;
protected:
enum class ItemBindings
{
AxisAlignedBounds, //!< 1 item with 6 values (xmin, xmax, ymin, ymax, zmin, zmax)
AxisAlignedMinMax, //!< 2 items with 3 values each (xlo, ylo, zlo), (xhi, yhi, zhi)
AxisAlignedCenterDeltas, //!< 2 items with 3 values each (xc, yc, zc), (dx, dy, dz)
EulerAngleMinMax, //!< 3 items with 3 values each (xlo, ylo, zlo), (xhi, yhi, zhi), (roll, pitch, yaw)
EulerAngleCenterDeltas //!< 3 items with 3 values each (xc, yc, zc), (dx, dy, dz), (roll, pitch, yaw)
};
/**\brief Starting with the widget's assigned item (which may
* be a GroupItem or a DoubleItem), determine and return bound items.
*
* If errors are encountered, this method returns false.
* If the name of a DoubleItem is provided, then the AxisAlignedBounds binding
* is assumed and that item is returned as the sole entry of \items.
* Otherwise, the named item must be a Group holding items called out as one
* of the following:
* + AxisAlignedMinMax: "Min", "Max" with numberOfValues == 3
* + AxisAlignedCenterDeltas: "Center", "Deltas", with numberOfValues == 3
* + EulerAngleMinMax: "Angles", "Min", "Max" with numberOfValues == 3
* + EulerAngleCenterDeltas: "Angles, "Center", "Deltas" with numberOfValues == 3
*
* Euler angles must be provided in degrees and are roll, pitch, and yaw
* (i.e., rotation about the x, y, and z axes, respectively).
*/
bool fetchBoxItems(ItemBindings& binding, std::vector<smtk::attribute::DoubleItemPtr>& items);
};
#endif // smtk_extension_paraview_widgets_pqSMTKBoxItemWidget_h
......@@ -91,6 +91,8 @@ bool pqSMTKSphereItemWidget::createProxyAndWidget(
proxy->GetProperty("Center"), vtkCommand::ModifiedEvent, this, SLOT(updateItemFromWidget()));
m_p->m_connector->Connect(
proxy->GetProperty("Radius"), vtkCommand::ModifiedEvent, this, SLOT(updateItemFromWidget()));
// The above detect render-window interactions. The below detects Qt interactions:
QObject::connect(widget, SIGNAL(changeFinished()), this, SLOT(updateItemFromWidget()));
return widget != nullptr;
}
......@@ -108,6 +110,11 @@ void pqSMTKSphereItemWidget::updateItemFromWidget()
// pqImplicitPlanePropertyWidget* pw = dynamic_cast<pqImplicitPlanePropertyWidget*>(m_p->m_pvwidget);
vtkSMPropertyHelper centerHelper(widget, "Center");
vtkSMPropertyHelper radiusHelper(widget, "Radius");
// NB: Because ParaView widgets may emit a "value possibly changed" signal when
// no value actually _has_ changed, we do not want to emit error messages
// that could frighten/confuse users just because the SMTK items were not
// updated. But this can be a silent failure point.
for (int i = 0; i < 3; ++i)
{
centerItem->setValue(i, centerHelper.GetAsDouble(i));
......
......@@ -79,7 +79,7 @@ int main(int argc, char* argv[])
ModelBrowser* qview = new ModelBrowser;
auto view = smtk::view::View::New("ModelBrowser", "SMTK Model");
auto phraseModel = smtk::view::ResourcePhraseModel::create(view);
phraseModel->addSource(resourceManager, operationManager);
phraseModel->addSource(resourceManager, operationManager, nullptr);
qmodel->setPhraseModel(phraseModel);
qview->setup(resourceManager, qmodel, qdelegate, nullptr);
......
......@@ -93,7 +93,7 @@ qtReferenceItem::~qtReferenceItem()
qtReferenceItem::AcceptsTypes qtReferenceItem::acceptableTypes() const
{
auto def = std::dynamic_pointer_cast<const smtk::attribute::ComponentItemDefinition>(
auto def = std::dynamic_pointer_cast<const smtk::attribute::ReferenceItemDefinition>(
m_itemInfo.item()->definition());
if (!def)
{
......@@ -334,7 +334,12 @@ void qtReferenceItem::createWidget()
void qtReferenceItem::clearWidgets()
{
m_itemInfo.parentWidget()->layout()->removeWidget(m_widget);
auto pwidget = m_itemInfo.parentWidget();
if (!pwidget)
{
return;
}
pwidget->layout()->removeWidget(m_widget);
delete m_widget;
m_widget = nullptr;
}
......@@ -350,7 +355,8 @@ void qtReferenceItem::updateUI()
// TODO: this need to connect to the right managers
auto rsrcMgr = m_itemInfo.uiManager()->resourceManager();
auto operMgr = smtk::operation::Manager::create();
auto operMgr = m_itemInfo.uiManager()->operationManager();
auto seln = m_itemInfo.uiManager()->selection();
auto phraseModel = this->createPhraseModel();
m_p->m_phraseModel = phraseModel;
......@@ -370,7 +376,7 @@ void qtReferenceItem::updateUI()
m_p->m_qtModel->setInvisibleIconURL(":/icons/display/unselected.png");
if (m_p->m_phraseModel)
{
m_p->m_phraseModel->addSource(rsrcMgr, operMgr);
m_p->m_phraseModel->addSource(rsrcMgr, operMgr, seln);
m_p->m_modelObserverId =
m_p->m_phraseModel->observe([this](smtk::view::DescriptivePhrasePtr phr,
smtk::view::PhraseModelEvent evt, const std::vector<int>& src, const std::vector<int>& dst,
......
......@@ -36,28 +36,25 @@ qtItem* qtResourceItem::createItemWidget(const AttributeItemInfo& info)
{
return nullptr;
}
return new qtResourceItem(info);
auto qi = new qtResourceItem(info);
// Unlike other classes, qtResourceItem does not call createWidget()
// in its constructor since the base class, qtReferenceItem, is
// concrete and cannot call virtual methods of subclases. So, for
// qtReferenceItem and its subclasses, we create the widget after
// constructing the item.
qi->createWidget();
return qi;
}
qtResourceItem::qtResourceItem(const AttributeItemInfo& info)
: qtReferenceItem(info)
{
this->createWidget();
}
qtResourceItem::~qtResourceItem()
{
}
void qtResourceItem::setLabelVisible(bool visible)
{
m_p->m_label->setVisible(visible);
}
void qtResourceItem::updateItemData()
{
}
smtk::view::PhraseModelPtr qtResourceItem::createPhraseModel() const
{
// Constructing the PhraseModel with a View properly initializes the SubphraseGenerator
......@@ -74,23 +71,6 @@ smtk::view::PhraseModelPtr qtResourceItem::createPhraseModel() const
return phraseModel;
}
void qtResourceItem::createWidget()
{
// Let our subclass do the UI work.
this->Superclass::createWidget();
// Now add in ResourceItem specifics.
smtk::attribute::ItemPtr dataObj = m_itemInfo.item();
if (!dataObj || !this->passAdvancedCheck() ||
(m_itemInfo.uiManager() &&
!m_itemInfo.uiManager()->passItemCategoryCheck(dataObj->definition())))
{
return;
}
this->updateItemData();
}
std::string qtResourceItem::synopsis(bool& ok) const
{
auto item = m_itemInfo.itemAs<smtk::attribute::ResourceItem>();
......@@ -177,134 +157,5 @@ std::string qtResourceItem::synopsis(bool& ok) const
ok &= (maxAllowed == 0 || numSel <= maxAllowed);
return label.str();
}
int qtResourceItem::decorateWithMembership(smtk::view::DescriptivePhrasePtr phr)
{
smtk::view::VisibilityContent::decoratePhrase(
phr, [this](smtk::view::VisibilityContent::Query qq, int val,
smtk::view::ConstPhraseContentPtr data) {
auto resource = data->relatedResource();
switch (qq)
{
case smtk::view::VisibilityContent::DISPLAYABLE:
return resource == nullptr ? 1 : 0;
case smtk::view::VisibilityContent::EDITABLE:
return resource == nullptr ? 1 : 0;
case smtk::view::VisibilityContent::GET_VALUE:
if (resource)
{
auto valIt = m_p->m_members.find(resource);
if (valIt != m_p->m_members.end())
{
return valIt->second;
}
return 0; // visibility is assumed if there is no entry.
}
return 0; // visibility is false if the resource is not a model entity or NULL.
case smtk::view::VisibilityContent::SET_VALUE:
if (resource)
{
if (val && !m_p->m_members.empty())
{
auto item = m_itemInfo.itemAs<attribute::ResourceItem>();
if (item->numberOfRequiredValues() <= 1 && item->maxNumberOfValues() == 1)
{ // Clear all other members since only 1 is allowed and the user just chose it.
m_p->m_members.clear();
m_p->m_phraseModel->triggerDataChanged();
}
}
m_p->m_members[resource] = val ? 1 : 0;
this->updateSynopsisLabels();
return 1;
}
}
return 0;
});
return 0;
}
void qtResourceItem::toggleCurrentItem()
{
auto cphr = m_p->m_qtModel->getItem(m_p->m_popupList->currentIndex());
if (cphr)
{
auto currentMembership = cphr->relatedVisibility();
// Selecting a new item when only 1 is allowed should reset all other membership.
if (!currentMembership && !m_p->m_members.empty())
{
auto item = m_itemInfo.itemAs<attribute::ResourceItem>();
if (item->numberOfRequiredValues() <= 1 && item->maxNumberOfValues() == 1)
{
m_p->m_members.clear();
m_p->m_phraseModel->triggerDataChanged();
}
}
cphr->setRelatedVisibility(!currentMembership);
this->updateSynopsisLabels();
}
}
bool qtResourceItem::synchronize(UpdateSource src)
{
auto item = m_itemInfo.itemAs<attribute::ResourceItem>();
if (!item)
{
return false;
}
std::size_t uiMembers = 0;
for (auto member : m_p->m_members)
{
if (member.second)
{
++uiMembers;
}
}
switch (src)
{
case UpdateSource::ITEM_FROM_GUI:
{
// Everything else in this case statement should really be
// a single, atomic operation executed on the attribute/item:
if (!item->setNumberOfValues(uiMembers))
{
return false;
}
int idx = 0;
for (auto member : m_p->m_members)
{
if (member.second)
{
if (!item->setValue(
idx, std::dynamic_pointer_cast<smtk::resource::Resource>(member.first)))
{
return false; // Huh!?!
}
++idx;
}
}
emit modified();
}
break;
case UpdateSource::GUI_FROM_ITEM:
m_p->m_members.clear();
m_p->m_phraseModel->triggerDataChanged();
for (auto vit = item->begin(); vit != item->end(); ++vit)
{
// Only allow non-null pointers into the set of selected items;
// null pointers indicate that the item's entry is invalid and
// the size of m_members is used to determine whether the
// association's rules are met, so an extra entry can prevent
// the association from being edited by the user.
if (*vit)
{
m_p->m_members[*vit] = 1; // FIXME: Use a bit specified by the application.
}
}
break;
}
return true;
}
}
}
......@@ -31,23 +31,10 @@ public:
qtResourceItem(const AttributeItemInfo& info);
virtual ~qtResourceItem();
void setLabelVisible(bool) override;
protected slots:
void updateItemData() override;
protected:
smtk::view::PhraseModelPtr createPhraseModel() const override;
void createWidget() override;
std::string synopsis(bool& membershipValid) const override;
int decorateWithMembership(smtk::view::DescriptivePhrasePtr phr) override;
void toggleCurrentItem() override;
bool synchronize(UpdateSource src) override;
};
}
}
......
......@@ -275,7 +275,7 @@ int unitQtComponentItem(int argc, char* argv[])
}
};
phraseModel->addSource(rsrcMgr, operMgr);
phraseModel->addSource(rsrcMgr, operMgr, nullptr);
phraseModel->setDecorator([&m_visibleThings](smtk::view::DescriptivePhrasePtr phr) {
smtk::view::VisibilityContent::decoratePhrase(
phr, [&m_visibleThings](smtk::view::VisibilityContent::Query qq, int val,
......
......@@ -136,8 +136,10 @@ AddAuxiliaryGeometry::Result AddAuxiliaryGeometry::operateInternal()
{
AuxiliaryGeometryExtension::Ptr ext;
smtk::common::Extension::visit<AuxiliaryGeometryExtension::Ptr>(
[&ext](const std::string&, AuxiliaryGeometryExtension::Ptr obj) {
if (obj)
[&ext, &auxGeom, &bbox](const std::string&, AuxiliaryGeometryExtension::Ptr obj) {
// Don't take the first AuxiliaryGeometryExtenion... look for one
// that can handle the URL.
if (obj && obj->canHandleAuxiliaryGeometry(auxGeom, bbox))
{
ext = obj;
return std::make_pair(true, true);
......@@ -146,7 +148,7 @@ AddAuxiliaryGeometry::Result AddAuxiliaryGeometry::operateInternal()
});
if (ext)
{
isURLValid = ext->canHandleAuxiliaryGeometry(auxGeom, bbox);
isURLValid = true;
haveBBox = true;
}
else
......@@ -173,17 +175,11 @@ AddAuxiliaryGeometry::Result AddAuxiliaryGeometry::operateInternal()
created->appendValue(auxGeom.component());
smtk::attribute::ComponentItem::Ptr modified = result->findComponent("modified");
modified->appendValue(parent.component());
smtk::attribute::ComponentItem::Ptr modifiedItem = result->findComponent("modified");
modifiedItem->appendValue(parent.component());
for (auto& m : reparented)
{
modifiedItem->appendValue(m.component());
modified->appendValue(m.component());
}
smtk::attribute::ComponentItem::Ptr createdItem = result->findComponent("created");
createdItem->appendValue(auxGeom.component());
if (auxGeom.hasURL())
{
auto tessItem = result->findComponent("tess_changed");
......
......@@ -13,6 +13,7 @@
#include "smtk/resource/Resource.h"
#include "smtk/common/Paths.h"
#include "smtk/common/UUIDGenerator.h"
#include "smtk/resource/Manager.h"
......@@ -149,5 +150,10 @@ bool Resource::setLocation(const std::string& myLocation)
return myLocation == m_location;
}
std::string Resource::name() const
{
return smtk::common::Paths::stem(m_location);
}
} // namespace resource
} // namespace smtk
......@@ -93,6 +93,9 @@ public:
bool setId(const smtk::common::UUID& myID) override;
bool setLocation(const std::string& location);
/// Make the name of a resource simply the stem of its filename.
std::string name() const override;
/// Indicate whether the resource is in sync with its location.
///
/// Resources that have a non-empty location and are identical to
......
......@@ -12,6 +12,7 @@ set(viewSrcs
ResourcePhraseContent.cxx
ResourcePhraseModel.cxx
Selection.cxx
SelectionPhraseModel.cxx
SubphraseGenerator.cxx
TwoLevelSubphraseGenerator.cxx
View.cxx
......@@ -34,6 +35,7 @@ set(viewHeaders
ResourcePhraseContent.h
ResourcePhraseModel.h
Selection.h
SelectionPhraseModel.h
SubphraseGenerator.h
SubphraseGenerator.txx
TwoLevelSubphraseGenerator.h
......
......@@ -110,11 +110,12 @@ PhraseModel::~PhraseModel()
this->resetSources();
}
bool PhraseModel::addSource(smtk::resource::ManagerPtr rsrcMgr, smtk::operation::ManagerPtr operMgr)
bool PhraseModel::addSource(smtk::resource::ManagerPtr rsrcMgr, smtk::operation::ManagerPtr operMgr,
smtk::view::SelectionPtr seln)
{
for (auto source : m_sources)
{
if (source.m_rsrcMgr == rsrcMgr && source.m_operMgr == operMgr)
if (source.m_rsrcMgr == rsrcMgr && source.m_operMgr == operMgr && source.m_seln == seln)
{
return false; // Do not add what we already have
}
......@@ -134,16 +135,21 @@ bool PhraseModel::addSource(smtk::resource::ManagerPtr rsrcMgr, smtk::operation:
return 0;
})
: -1;
m_sources.push_back(Source(rsrcMgr, operMgr, rsrcHandle, operHandle));
int selnHandle = seln
? seln->observe([this](const std::string& src,
smtk::view::SelectionPtr seln) { this->handleSelectionEvent(src, seln); },
/*observeImmediately*/ true)
: -1;
m_sources.push_back(Source(rsrcMgr, operMgr, seln, rsrcHandle, operHandle, selnHandle));
return true;
}
bool PhraseModel::removeSource(
smtk::resource::ManagerPtr rsrcMgr, smtk::operation::ManagerPtr operMgr)
bool PhraseModel::removeSource(smtk::resource::ManagerPtr rsrcMgr,
smtk::operation::ManagerPtr operMgr, smtk::view::SelectionPtr seln)