Commit 3a99fd93 authored by Haocheng LIU's avatar Haocheng LIU Committed by Kitware Robot
Browse files

Merge topic 'Active-model-support'

bf7b6e10

 FEATURE: Add active model support
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Acked-by: David Thompson's avatarDavid Thompson <david.thompson@kitware.com>
Merge-request: !546
parents f741fa3b bf7b6e10
......@@ -179,13 +179,13 @@ bool ModelEntityItem::appendValue(const smtk::model::EntityRef& val)
for (std::size_t i = 0; i < n; ++i)
{
if (this->isSet(i) && (this->value(i).entity() == val.entity()))
{
return true;
}
{
return true;
}
if (!this->isSet(i))
{
foundEmpty = true;
emptyIndex = i;
foundEmpty = true;
emptyIndex = i;
}
}
// If not, was there a space available?
......
......@@ -4,6 +4,7 @@ smtk_find_package_qt(qt_targets REQUIRED
# set up sources to build
set(QAttrLibSrcs
qtActiveObjects.cxx
qtUIManager.cxx
qtSelectionManager.cxx
qtAttribute.cxx
......@@ -59,6 +60,7 @@ set(QAttrLibUIs
set(QAttrLibMocHeaders
qtActiveObjects.h
qtUIManager.h
qtSelectionManager.h
qtAttribute.h
......
//=========================================================================
// 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.
//=========================================================================
#include <smtk/extension/qt/qtActiveObjects.h>
qtActiveObjects::qtActiveObjects()
{
this->m_activeModel = smtk::model::Model();
}
qtActiveObjects::~qtActiveObjects()
{
}
qtActiveObjects& qtActiveObjects::instance()
{
static qtActiveObjects theInstance;
return theInstance;
}
void qtActiveObjects::setActiveModel(const smtk::model::Model& inputModel)
{
this->m_activeModel = inputModel;
emit this->activeModelChanged();
}
//=========================================================================
// 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.
//=========================================================================
#ifndef qtActiveObjects_h
#define qtActiveObjects_h
#include <QObject>
#include "smtk/PublicPointerDefs.h"
#include "smtk/model/Model.h" //for smtk::model::Model
namespace smtk {
namespace model {
class Model;
}
}
class pqView;
class vtkSMSessionProxyManager;
class vtkSMViewProxy;
/**
qtActiveObjects keeps track of active objects.
This is similar to pqActiveObjects in ParaView, however it tracks objects
relevant to SMTK and CMB.
*/
class qtActiveObjects : public QObject
{
Q_OBJECT
typedef QObject Superclass;
public:
/// Returns reference to the singleton instance.
static qtActiveObjects& instance();
/// Returns the active model.
smtk::model::Model activeModel() const {return this->m_activeModel;}
public slots:
/// Set the active module.
void setActiveModel(const smtk::model::Model& inputModel);
signals:
/// Fire when activeModel changes.
void activeModelChanged();
private slots:
protected:
qtActiveObjects();
virtual ~qtActiveObjects();
smtk::model::Model m_activeModel;
private:
Q_DISABLE_COPY(qtActiveObjects)
};
#endif
......@@ -8,6 +8,7 @@
// PURPOSE. See the above copyright notice for more information.
//=========================================================================
#include "smtk/extension/qt/qtActiveObjects.h"
#include "smtk/extension/qt/qtAssociationWidget.h"
#include "smtk/extension/qt/qtAttribute.h"
......@@ -344,14 +345,14 @@ void qtAssociationWidget::showEntityAssociation(
typedef smtk::model::EntityRefs::const_iterator cit;
for (cit i =modelEnts.begin(); i != modelEnts.end(); ++i)
{
this->addModelAssociationListItem(this->Internals->CurrentList, *i, false);
this->addModelAssociationListItem(this->Internals->CurrentList, *i, false, true);
}
this->Internals->CurrentList->sortItems();
// The returned usedModelEnts should include all of the input modelEnts AND, if attDef is unique,
// entities that have been associated with the attributes with same definition.
std::set<smtk::model::EntityRef> usedModelEnts = this->processAttUniqueness(attDef, modelEnts);
// Now that we have add all the used model entities, we need to move on to all model
// Now that we have added all the used model entities, we need to move on to all model
// entities that are not associated with the attribute, but could be associated.
// We use the "no-exact match required" flag to catch any entity that could possibly match
// the association mask. This gets pruned below.
......@@ -366,18 +367,23 @@ void qtAssociationWidget::showEntityAssociation(
usedModelEnts.begin(), usedModelEnts.end(),
std::inserter(avail, avail.end()));
// Add a subset of the remainder to the list of available entities.
// Add a subset of the remainder which also belongs to current active model
// to the list of available entities.
// We create a temporary group and use Group::meetsMembershipConstraints()
// to test whether the mask allows association.
smtk::model::Model activeModel = qtActiveObjects::instance().activeModel();
smtk::model::Manager::Ptr tmpMgr = smtk::model::Manager::create();
Group tmpGrp = tmpMgr->addGroup();
tmpGrp.setMembershipMask(attDef->associationMask());
for(EntityRefs::iterator i = avail.begin(); i != avail.end(); ++i)
{
if (tmpGrp.meetsMembershipConstraints(*i))
if (tmpGrp.meetsMembershipConstraints(*i) &&
i->owningModel().entity() == activeModel.entity())
{
this->addModelAssociationListItem(this->Internals->AvailableList, *i, false);
}
}
this->Internals->AvailableList->sortItems();
this->Internals->CurrentList->blockSignals(false);
this->Internals->AvailableList->blockSignals(false);
......@@ -550,10 +556,13 @@ void qtAssociationWidget::removeItem(QListWidget* theList,
}
QListWidgetItem* qtAssociationWidget::addModelAssociationListItem(
QListWidget* theList, smtk::model::EntityRef modelItem, bool sort)
QListWidget* theList, smtk::model::EntityRef modelItem, bool sort, bool
appendModelName)
{
std::string name = appendModelName ? (modelItem.name() +
" - " + modelItem.owningModel().name()) : modelItem.name();
QListWidgetItem* item = new QListWidgetItem(
QString::fromStdString(modelItem.name()),
QString::fromStdString(name),
theList,
smtk_USER_DATA_TYPE);
//save the entity as a uuid string
......@@ -648,8 +657,14 @@ void qtAssociationWidget::onRemoveAssigned()
{
this->Internals->CurrentAtt.lock()->disassociateEntity(currentItem);
this->removeItem(theList, item);
selItem = this->addModelAssociationListItem(
this->Internals->AvailableList, currentItem);
// only add entityRef back to availableList when it belongs to
// the current active model
if (currentItem.owningModel().entity() ==
qtActiveObjects::instance().activeModel().entity())
{
selItem = this->addModelAssociationListItem(
this->Internals->AvailableList, currentItem);
}
}
}
else if(!this->Internals->CurrentModelGroup.isNull())
......@@ -695,7 +710,7 @@ void qtAssociationWidget::onAddAvailable()
{
this->removeItem(theList, item);
selItem = this->addModelAssociationListItem(
this->Internals->CurrentList, currentItem);
this->Internals->CurrentList, currentItem, true, true);
}
else // faied to assoicate with new entity
{
......@@ -773,11 +788,16 @@ void qtAssociationWidget::onExchange()
{
this->removeItem(this->Internals->CurrentList, selCurrentItems[i]);
selCurrentItem = this->addModelAssociationListItem(
this->Internals->CurrentList, availableItem);
this->Internals->CurrentList, availableItem, true, true);
this->removeItem(this->Internals->AvailableList, selAvailItems[i]);
selAvailItem = this->addModelAssociationListItem(
this->Internals->AvailableList, currentItem);
// only add it back to available list when it's part of active model
if (currentItem.owningModel().entity() ==
qtActiveObjects::instance().activeModel().entity())
{
selAvailItem = this->addModelAssociationListItem(
this->Internals->AvailableList, currentItem);
}
}
else // faied to exchange, add back association
{
......
......@@ -74,8 +74,10 @@ namespace smtk
//returns the Item it has added to the widget
//ownership of the item is handled by the widget so no need to delete
//for now we append model name to currentList
virtual QListWidgetItem* addModelAssociationListItem(
QListWidget* theList, smtk::model::EntityRef modelItem, bool sort=true);
QListWidget* theList, smtk::model::EntityRef modelItem,
bool sort=true, bool appendModelName = false);
//returns the Item it has added to the widget
//ownership of the item is handled by the widget so no need to delete
......
......@@ -15,6 +15,7 @@
#include "smtk/attribute/ModelEntityItem.h"
#include "smtk/attribute/ModelEntityItemDefinition.h"
#include "smtk/attribute/System.h"
#include "smtk/extension/qt/qtActiveObjects.h"
#include "smtk/extension/qt/qtMeshItem.h"
#include "smtk/extension/qt/qtModelEntityItem.h"
#include "smtk/mesh/Collection.h"
......@@ -151,7 +152,10 @@ void qtModelEntityItemCombo::init()
// if the mask is only groups, get all groups from manager
((onlyGroups && entref.isGroup()) ||
// else, check the membership constraints
(!onlyGroups && tmpGrp.meetsMembershipConstraints(entref))))
(!onlyGroups && tmpGrp.meetsMembershipConstraints(entref))) &&
// only show entities in active model or its type is model
(entref.owningModel().entity() ==
qtActiveObjects::instance().activeModel().entity() || entref.isModel()))
{
QStandardItem* item = new QStandardItem;
std::string entName = entref.name();
......
......@@ -138,7 +138,13 @@ void QEntityItemDelegate::paint(
QFont titleFont = QApplication::font();
QFont subtitleFont = QApplication::font();
titleFont.setPixelSize(this->m_titleFontSize);
/// add a method to set/get title font
titleFont.setBold(this->titleFontWeight() > 1 ? true : false);
// bold the active model title
if (idx.data(Qt::FontRole).toBool())
{
titleFont.setBold(true);
}
subtitleFont.setPixelSize(this->m_subtitleFontSize);
subtitleFont.setBold(this->subtitleFontWeight() > 1 ? true : false);
......
......@@ -9,6 +9,7 @@
//=========================================================================
#include "smtk/extension/qt/qtEntityItemModel.h"
#include "smtk/extension/qt/qtActiveObjects.h"
#include "smtk/model/Entity.h"
#include "smtk/model/EntityPhrase.h"
#include "smtk/model/FloatData.h"
......@@ -356,7 +357,7 @@ QVariant QEntityItemModel::data(const QModelIndex& idx, int role) const
}
else if (role == EntityColorRole &&
(item->phraseType() == MESH_SUMMARY || item->relatedEntity().isValid()
|| item->phraseType() == ENTITY_LIST )) // if needed, disable assign model color here
|| item->phraseType() == ENTITY_LIST ))
{
QColor color;
FloatList rgba = item->relatedColor();
......@@ -390,6 +391,14 @@ QVariant QEntityItemModel::data(const QModelIndex& idx, int role) const
}
return color;
}
else if (role == Qt::FontRole)
{
// used to bold the active model's title
return (item->relatedEntity().entity() ==
qtActiveObjects::instance().activeModel().entity()) ? QVariant(true)
: QVariant(false);
}
}
}
return QVariant();
......@@ -1454,6 +1463,10 @@ void QEntityItemModel::newSessionOperatorResult(
smtk::model::DescriptivePhrases newSubs =
this->m_root->findDelegate()->subphrases(this->m_root);
// udpate active model in subphraseGenerator
this->m_root->findDelegate()->setActiveModel(qtActiveObjects::instance().activeModel());
std::vector< std::pair<DescriptivePhrasePtr, int> > newDphrs;
int newIdx = 0;
for (smtk::model::DescriptivePhrases::iterator it = newSubs.begin();
......
......@@ -9,6 +9,7 @@
//=========================================================================
#include "smtk/extension/qt/qtModelPanel.h"
#include "smtk/extension/qt/qtActiveObjects.h"
#include "smtk/extension/qt/qtEntityItemModel.h"
#include "smtk/extension/qt/qtModelView.h"
#include "smtk/model/Entity.h"
......@@ -112,6 +113,7 @@ void qtModelPanel::resetView(qtModelPanel::enumTreeView enType,
spg->setDirectLimit(-1);
spg->setSkipAttributes(true);
spg->setSkipProperties(true);
spg->setActiveModel(qtActiveObjects::instance().activeModel());
qtModelView* modelview = this->getModelView();
QPointer<smtk::extension::QEntityItemModel> qmodel = modelview->getModel();
......
......@@ -8,15 +8,19 @@
// PURPOSE. See the above copyright notice for more information.
//=========================================================================
#include "smtk/extension/qt/qtModelView.h"
#include "smtk/extension/qt/qtActiveObjects.h"
#include "smtk/model/DescriptivePhrase.h"
#include "smtk/model/Entity.h"
#include "smtk/model/EntityIterator.h"
#include "smtk/model/FloatData.h"
#include "smtk/model/Group.h"
#include "smtk/model/IntegerData.h"
#include "smtk/model/Manager.h"
#include "smtk/model/Model.h"
#include "smtk/model/StringData.h"
#include "smtk/model/SubphraseGenerator.h"
#include "smtk/model/SimpleModelSubphrases.h"
#include "smtk/extension/qt/qtEntityItemDelegate.h"
......@@ -38,6 +42,7 @@
#include "smtk/extension/qt/qtAttribute.h"
#include "smtk/extension/qt/qtModelEntityItem.h"
#include "smtk/extension/qt/qtModelPanel.h"
#include "smtk/extension/qt/qtModelOperationWidget.h"
#include "smtk/extension/qt/qtOperatorDockWidget.h"
#include "smtk/extension/qt/qtUIManager.h"
......@@ -385,7 +390,7 @@ void qtModelView::selectionChanged (
emit this->sendSelectionsFromModelViewToSelectionManager(selentityrefs,
selmeshes, selproperties,
smtk::extension::SelectionModifier::SELECTION_REPLACE_UNFILTERED,
smtk::model::StringList());
skipList);
}
// when the dataChanged is emitted from the model, we want to scroll to
......@@ -395,6 +400,119 @@ void qtModelView::newIndexAdded(const QModelIndex & newidx)
this->scrollTo(newidx);
}
void qtModelView::filterSelectionByEntity (const smtk::model::DescriptivePhrasePtr& dPhrase,
smtk::model::EntityRefs& selentityrefs,
smtk::mesh::MeshSets* selmeshes)
{
SubphraseGeneratorPtr gen = dPhrase->findDelegate();
SimpleModelSubphrasesPtr sGen = smtk::dynamic_pointer_cast<SimpleModelSubphrases>(gen);
qtModelPanel::enumTreeView enType = sGen ? qtModelPanel::VIEW_BY_TOPOLOGY
: qtModelPanel::VIEW_BY_ENTITY_LIST;
BitFlags defaultMask = CELL_ENTITY | GROUP_ENTITY | MODEL_ENTITY
| AUX_GEOM_ENTITY | INSTANCE_ENTITY | SESSION;
smtk::model::EntityRef relatedEnt = dPhrase->relatedEntity();
if(dPhrase)
{
if(dPhrase->phraseType() == MESH_SUMMARY ||
dPhrase->phraseType() == MESH_LIST)
{
this->selectMeshes(dPhrase, selmeshes);
}
else
{// single entity
BitFlags masked = dPhrase->relatedEntity().entityFlags() & defaultMask;
if (masked)
{
selentityrefs.insert(relatedEnt);
}
}
if (relatedEnt.entityFlags() == SESSION)
{// session condition
smtk::model::SessionRef sessionRef = relatedEnt.
as<smtk::model::SessionRef>();
// loop through each model, its entities and meshes
Models models = sessionRef.models<Models>();
for (const auto& model : models)
{
smtk::model::EntityIterator eit;
eit.traverse(model, smtk::model::ITERATE_MODELS);
for (eit.begin(); !eit.isAtEnd(); eit.advance())
{
// needed? @David
if (eit->isCellEntity() || eit->isAuxiliaryGeometry() || eit->isModel())
{
selentityrefs.insert(*eit);
}
}
smtk::mesh::ManagerPtr meshMgr = model.manager()->meshes();
std::vector<smtk::mesh::CollectionPtr> meshCols = meshMgr->
associatedCollections(model);
for (const auto & meshCol : meshCols)
{
selmeshes->insert(meshCol->meshes());
}
}
}
else if (relatedEnt.isModel())
{// non-active model and active model
smtk::model::EntityIterator eit;
eit.traverse(relatedEnt, smtk::model::ITERATE_CHILDREN);
for (eit.begin(); !eit.isAtEnd(); eit.advance())
{
if (eit->isCellEntity() || eit->isAuxiliaryGeometry() || eit->isModel())
{
selentityrefs.insert(*eit);
}
}
smtk::mesh::ManagerPtr meshMgr = relatedEnt.manager()->meshes();
std::vector<smtk::mesh::CollectionPtr> meshCols = meshMgr->
associatedCollections(relatedEnt);
for (const auto & meshCol : meshCols)
{
selmeshes->insert(meshCol->meshes());
}
}
else if (dPhrase->phraseType() == ENTITY_LIST)
{// handle items in ENTITY_LIST
if (enType == qtModelPanel::VIEW_BY_ENTITY_LIST)
{
if(EntityListPhrasePtr elist = smtk::dynamic_pointer_cast<EntityListPhrase>
(dPhrase))
{
smtk::model::EntityRefArray entities = elist->relatedEntities();
for (const auto& item: entities)
{
selentityrefs.insert(item);
}
}
}
}
else if (dPhrase->phraseType() == ENTITY_SUMMARY)
{
if (enType == qtModelPanel::VIEW_BY_TOPOLOGY)
{//VIEW_BY_TOPOLOGY
if(EntityPhrasePtr entity = smtk::dynamic_pointer_cast<EntityPhrase>
(dPhrase))
{
smtk::model::EntityRef ent = entity->relatedEntity();
EntityRefs lowerEnts = ent.lowerDimensionalBoundaries(-1);
for (const auto& lowerEnt: lowerEnts)
{
selentityrefs.insert(lowerEnt);
}
// EntityIterator would fail here to give wrong boundary entities
}
}
}
}
}
void qtModelView::recursiveSelect (const smtk::model::DescriptivePhrasePtr& dPhrase,
smtk::model::EntityRefs& selentityrefs, BitFlags entityFlags,
smtk::model::DescriptivePhrases& selproperties, bool exactMatch,
......@@ -507,6 +625,15 @@ void qtModelView::currentSelectionByMask (
}
}
void qtModelView::updateActiveModelByModelIndex()
{
// get the current model and compare with active model
smtk::model::Model currentModel = this->owningEntityAs<smtk::model::Model>(
this->m_contextMenuIndex);
qtActiveObjects::instance().setActiveModel(currentModel);
}
bool qtModelView::removeSession(const smtk::model::SessionRef& sref)
{
smtk::extension::QEntityItemModel* qmodel =
......@@ -773,6 +900,9 @@ void qtModelView::showContextMenu(const QModelIndex &idx, const QPoint& p)
smtk::model::SessionRef brSession =
this->owningEntityAs<smtk::model::SessionRef>(idx);
// get the current model and compare with active model
smtk::model::Model currentModel = this->owningEntityAs<smtk::model::Model>(idx);
if (!brSession.isValid())
{
// Nothing to do the session is not valid;
......@@ -796,14 +926,32 @@ void qtModelView::showContextMenu(const QModelIndex &idx, const QPoint& p)
std::pair<std::vector<std::string>, std::map<std::string, std::string> >(keyList, opLabelsMap);
}
auto sinfo = this->m_sessionInfo[sessionString];
for(StringList::const_iterator it = sinfo.first.begin();
it != sinfo.first.end(); ++it)
{
QAction* act = this->m_ContextMenu->addAction((*it).c_str());
// Compare the current model with active model. If true, show related
// operators. If not, only show `set as active model`.
smtk::model::Model currentActiveModel = qtActiveObjects::instance().activeModel();
if (currentModel.isValid() && (currentModel.entity() == currentActiveModel.entity()))
{
for(StringList::const_iterator it = sinfo.first.begin();
it != sinfo.first.end(); ++it)
{
QAction* act = this->m_ContextMenu->addAction((*it).c_str());
QVariant vdata( QString::fromStdString(sessionString) );
act->setData(vdata);
QObject::connect(act, SIGNAL(triggered()), this, SLOT(operatorInvoked()));
}
}
else if (currentModel.isValid()) // if invalid, then it's sessionRef
{ // set active model
std::string setAsActiveModel("set as active model");
QAction* act = this->m_ContextMenu->addAction(setAsActiveModel.c_str());
QVariant vdata( QString::fromStdString(sessionString) );
act->setData(vdata);
QObject::connect(act, SIGNAL(triggered()), this, SLOT(operatorInvoked()));
}
QObject::connect(act, SIGNAL(triggered()), this, SLOT(updateActiveModelByModelIndex()));
}
// store current contextMenuIndex to set active model
this->m_contextMenuIndex = idx;
QPoint popP = p;
if(popP.isNull())
{
......@@ -1125,11 +1273,8 @@ void qtModelView::toggleEntityVisibility( const QModelIndex& idx)
smtk::model::EntityRefs selentityrefs;
smtk::mesh::MeshSets selmeshes;
smtk::model::DescriptivePhrases selproperties;
this->recursiveSelect(dp, selentityrefs,
CELL_ENTITY | SHELL_ENTITY | GROUP_ENTITY |
MODEL_ENTITY | AUX_GEOM_ENTITY | INSTANCE_ENTITY | SESSION,
selproperties, false, &selmeshes);
// filter selection by entity instead of DesriptivePhrase
this->filterSelectionByEntity(dp, selentityrefs,&selmeshes);
bool visible = true;
if(dp->phraseType() == MESH_LIST || dp->phraseType() == MESH_SUMMARY)
{
......@@ -1590,6 +1735,10 @@ void qtModelView::updateWithOperatorResult(
{
smtk::extension::QEntityItemModel* qmodel =
dynamic_cast<smtk::extension::QEntityItemModel*>(this->model());
// udpate active model in subphraseGenerator. Get the m_root
qmodel->getItem(QModelIndex())->findDelegate()->
setActiveModel(qtActiveObjects::instance().activeModel());
QModelIndex top = this->rootIndex();
for (int row = 0; row < qmodel->rowCount(top); ++row)
{
......
......@@ -80,6 +80,7 @@ namespace smtk{
void expandAllModels();
public slots:
void updateActiveModelByModelIndex();
bool removeSession(const smtk::model::SessionRef& sref);