From 4db17e028382ec409e822d3504c6e5b06d1a5d5f Mon Sep 17 00:00:00 2001 From: Haocheng Liu Date: Wed, 5 Apr 2017 14:50:37 -0400 Subject: [PATCH 1/2] Add assign color to ENTITY_LIST feature Now user can assign color to ENTITY_LIST by just clicking the icon. For this ENTITY_LIST, it's parent entity must be a model and the color info is stored as a FloatProperty on the associated model as "$Entity:: flagSummary(bitflags) + color."(Ex. "face color"). This MR also fix a logic error in qtItemDelegate when deciding color is mutable or not. --- smtk/extension/qt/qtEntityItemDelegate.cxx | 14 ++- smtk/extension/qt/qtEntityItemDelegate.h | 4 +- smtk/extension/qt/qtEntityItemModel.cxx | 3 +- smtk/extension/qt/qtModelView.cxx | 131 ++++++++++++++++----- smtk/model/EntityListPhrase.cxx | 42 +++++++ smtk/model/EntityListPhrase.h | 2 + smtk/model/EntityPhrase.cxx | 26 +++- smtk/model/EntityRef.cxx | 2 +- 8 files changed, 181 insertions(+), 43 deletions(-) diff --git a/smtk/extension/qt/qtEntityItemDelegate.cxx b/smtk/extension/qt/qtEntityItemDelegate.cxx index 6f236e4f48..19b574f58a 100644 --- a/smtk/extension/qt/qtEntityItemDelegate.cxx +++ b/smtk/extension/qt/qtEntityItemDelegate.cxx @@ -135,7 +135,6 @@ void QEntityItemDelegate::paint( QIcon icon = qvariant_cast(idx.data(QEntityItemModel::EntityIconRole)); QSize iconsize = icon.actualSize(option.decorationSize); - QColor swatchColor = qvariant_cast(idx.data(QEntityItemModel::EntityColorRole)); QFont titleFont = QApplication::font(); QFont subtitleFont = QApplication::font(); titleFont.setPixelSize(this->m_titleFontSize); @@ -149,6 +148,7 @@ void QEntityItemDelegate::paint( QString titleText = qvariant_cast(idx.data(QEntityItemModel::TitleTextRole)); QString subtitleText = qvariant_cast(idx.data(QEntityItemModel::SubtitleTextRole)); //std::cout << "Paint " << idx.internalPointer() << " " << idx.row() << " " << titleText.toStdString().c_str() << "\n"; + QColor swatchColor = qvariant_cast(idx.data(QEntityItemModel::EntityColorRole)); QRect titleRect = option.rect; QRect subtitleRect = option.rect; @@ -269,7 +269,8 @@ bool QEntityItemDelegate::eventFilter(QObject* editor, QEvent* evt) std::string QEntityItemDelegate::determineAction ( const QPoint& pPos, const QModelIndex& idx, - const QStyleOptionViewItem & option) const + const QStyleOptionViewItem & option, + const smtk::extension::QEntityItemModel* entityMod) const { std::string res; // with the help of styles, return where the pPos is on: @@ -278,7 +279,6 @@ std::string QEntityItemDelegate::determineAction ( QIcon visicon = qvariant_cast( idx.data(QEntityItemModel::EntityVisibilityRole)); QSize visiconsize = visicon.actualSize(option.decorationSize); - QColor swatchColor = qvariant_cast(idx.data(QEntityItemModel::EntityColorRole)); int px = pPos.x(); int py = pPos.y(); bool bvis = false, bcolor = false; @@ -289,7 +289,7 @@ std::string QEntityItemDelegate::determineAction ( && py > option.rect.top() && py < (option.rect.top() + option.rect.height()); } - if(!bvis && swatchColor.isValid()) + if(!bvis && entityMod && entityMod->getItem(idx)->isRelatedColorMutable()) { bcolor = px > (option.rect.left() + visiconsize.width() + 2) && px < (option.rect.left() + visiconsize.width() + 2 + this->m_swatchSize) @@ -325,7 +325,11 @@ bool QEntityItemDelegate::editorEvent ( return res; } - std::string whichIcon = this->determineAction(e->pos(), idx, option); + // pass in qEntityItemModel for mutability check + smtk::extension::QEntityItemModel* entityMod = dynamic_cast< + smtk::extension::QEntityItemModel*>(mod); + std::string whichIcon = this->determineAction(e->pos(), idx, option, + entityMod); if(whichIcon == "visible") { diff --git a/smtk/extension/qt/qtEntityItemDelegate.h b/smtk/extension/qt/qtEntityItemDelegate.h index bba4f41fe3..f7810e4f6c 100644 --- a/smtk/extension/qt/qtEntityItemDelegate.h +++ b/smtk/extension/qt/qtEntityItemDelegate.h @@ -18,6 +18,7 @@ namespace smtk { namespace extension { + class QEntityItemModel; /**\brief Present the contents of an smtk::model::Manager instance via QEntityItemModel. * */ @@ -80,7 +81,8 @@ public: // return which icon the Point position is on // 'visible', 'color', or empty string; std::string determineAction(const QPoint& pPos, const QModelIndex& idx, - const QStyleOptionViewItem & option) const; + const QStyleOptionViewItem & option, + const smtk::extension::QEntityItemModel* entityMod = nullptr) const; protected slots: virtual void commitAndCloseEditor(); diff --git a/smtk/extension/qt/qtEntityItemModel.cxx b/smtk/extension/qt/qtEntityItemModel.cxx index e402e96c03..ff4996ca51 100644 --- a/smtk/extension/qt/qtEntityItemModel.cxx +++ b/smtk/extension/qt/qtEntityItemModel.cxx @@ -355,7 +355,8 @@ QVariant QEntityItemModel::data(const QModelIndex& idx, int role) const return QVariant(QIcon(":/icons/display/eyeballx_16.png")); } else if (role == EntityColorRole && - (item->phraseType() == MESH_SUMMARY || item->relatedEntity().isValid())) + (item->phraseType() == MESH_SUMMARY || item->relatedEntity().isValid() + || item->phraseType() == ENTITY_LIST )) // if needed, disable assign model color here { QColor color; FloatList rgba = item->relatedColor(); diff --git a/smtk/extension/qt/qtModelView.cxx b/smtk/extension/qt/qtModelView.cxx index fbce52330f..5e9de38792 100644 --- a/smtk/extension/qt/qtModelView.cxx +++ b/smtk/extension/qt/qtModelView.cxx @@ -1260,49 +1260,116 @@ void qtModelView::changeEntityColor( const QModelIndex& idx) smtk::model::EntityRefs selentityrefs; smtk::mesh::MeshSets selmeshes; QColor currentColor = Qt::white; - if(dp->phraseType() == MESH_SUMMARY) - { - MeshPhrasePtr mphrase = smtk::dynamic_pointer_cast(dp); - smtk::mesh::CollectionPtr c; - smtk::mesh::MeshSet meshkey; - if(!mphrase->relatedMesh().is_empty()) + if (dp->phraseType() == ENTITY_LIST) + { + EntityListPhrasePtr elp = smtk::dynamic_pointer_cast + (dp); + std::string colorName; + // Currently only handle model's entity list + if (elp && elp->parent()->relatedEntity().isModel()) + { + colorName = Entity::flagSummary(elp->relatedBitFlags()); + colorName += " color"; + // get the color for the list + QColor newColor = QColorDialog::getColor(currentColor, this, + "Choose Entity Color", + QColorDialog::DontUseNativeDialog | QColorDialog::ShowAlphaChannel); + + // store color property on the model + // use set property operator to store color + smtk::model::EntityRef model = elp->parent()->relatedEntity(); + smtk::attribute::AttributePtr attrib = brOp->specification(); + smtk::attribute::StringItemPtr nameItem = + attrib->findString("name"); + smtk::attribute::DoubleItemPtr colorItem = + attrib->findDouble("float value"); + if(!nameItem || !colorItem) + { + std::cerr + << "The set-property op is missing item(s): name or double value\n"; + } + nameItem->setValue(colorName); + if(newColor.isValid()) + { + colorItem->setNumberOfValues(4); + colorItem->setValue(0, newColor.redF()); + colorItem->setValue(1, newColor.greenF()); + colorItem->setValue(2, newColor.blueF()); + colorItem->setValue(3, newColor.alphaF()); + } + else + { + colorItem->setNumberOfValues(4); + std::vector nullColor(4, -1.); + colorItem->setValues(nullColor.begin(), nullColor.end()); + } + attrib->associateEntity(model); + + emit this->operationRequested(brOp); + + // invalid color of elp's children entities to be (0, 0, 0, -1) + OperatorPtr acOp = this->getOp(idx, "assign colors"); + EntityRefArray relatedEntities = elp->relatedEntities(); + for (auto & relatedEntity : relatedEntities) { - meshkey = mphrase->relatedMesh(); - c = meshkey.collection(); + acOp->associateEntity(relatedEntity); } - else + + emit this->operationRequested(acOp); + + if (newColor.isValid()) { - c = mphrase->relatedMeshCollection(); - meshkey = c->meshes(); + this->dataChanged(idx, idx); } - if(c && !meshkey.is_empty()) + } + } + else + { + if(dp->phraseType() == MESH_SUMMARY) { - const FloatList& rgba(c->floatProperty(meshkey, "color")); - currentColor = internal_convertColor(rgba); - selmeshes.insert(meshkey); + MeshPhrasePtr mphrase = smtk::dynamic_pointer_cast(dp); + smtk::mesh::CollectionPtr c; + smtk::mesh::MeshSet meshkey; + if(!mphrase->relatedMesh().is_empty()) + { + meshkey = mphrase->relatedMesh(); + c = meshkey.collection(); + } + else + { + c = mphrase->relatedMeshCollection(); + meshkey = c->meshes(); + } + + if(c && !meshkey.is_empty()) + { + const FloatList& rgba(c->floatProperty(meshkey, "color")); + currentColor = internal_convertColor(rgba); + selmeshes.insert(meshkey); + } } - } - else if(!dp->isPropertyValueType() && dp->relatedEntity().isValid()) - { - selentityrefs.insert(dp->relatedEntity()); + else if(!dp->isPropertyValueType() && dp->relatedEntity().isValid()) + { + selentityrefs.insert(dp->relatedEntity()); - smtk::model::FloatList rgba(4); - rgba = dp->relatedEntity().color(); - currentColor = internal_convertColor(rgba); - } + smtk::model::FloatList rgba(4); + rgba = dp->relatedEntity().color(); + currentColor = internal_convertColor(rgba); + } - if(selentityrefs.size() > 0 || selmeshes.size() > 0) - { - QColor newColor = QColorDialog::getColor(currentColor, this, - "Choose Entity Color", - QColorDialog::DontUseNativeDialog | QColorDialog::ShowAlphaChannel); - if(newColor.isValid() && newColor != currentColor) + if(selentityrefs.size() > 0 || selmeshes.size() > 0) { - if(this->setEntityColor(selentityrefs, selmeshes, newColor, brOp)) - this->dataChanged(idx, idx); + QColor newColor = QColorDialog::getColor(currentColor, this, + "Choose Entity Color", + QColorDialog::DontUseNativeDialog | QColorDialog::ShowAlphaChannel); + if(newColor.isValid() && newColor != currentColor) + { + if(this->setEntityColor(selentityrefs, selmeshes, newColor, brOp)) + this->dataChanged(idx, idx); + } } - } + } } bool qtModelView::setEntityColor( diff --git a/smtk/model/EntityListPhrase.cxx b/smtk/model/EntityListPhrase.cxx index aadb918adb..86064b49c2 100644 --- a/smtk/model/EntityListPhrase.cxx +++ b/smtk/model/EntityListPhrase.cxx @@ -11,6 +11,8 @@ #include "smtk/model/EntityPhrase.h" #include "smtk/model/PropertyListPhrase.h" +#include "smtk/model/EntityTypeBits.h" +#include "smtk/model/Entity.h" namespace smtk { namespace model { @@ -18,6 +20,7 @@ namespace smtk { EntityListPhrase::EntityListPhrase() : m_commonFlags(INVALID), m_unionFlags(0) { + // only color is mutable } /// Show the entity name (or a default name) in the title @@ -115,5 +118,44 @@ void EntityListPhrase::setFlags(BitFlags commonFlags, BitFlags unionFlags) this->m_unionFlags = unionFlags; } +/**\brief return whether the related color is mutable or not + * Only when parent is model, related entities are of the same type + * and entity is cell then user could change related color + */ +bool EntityListPhrase::isRelatedColorMutable() const +{ + if (this->parent() && this->parent()->relatedEntity().isModel() + && this->m_commonFlags == this->m_unionFlags + && (this->m_commonFlags | smtk::model::CELL_ENTITY)) + { + return true; + } + return false; + +} + +/** \brief return the color of the entityListPhrase which is stored + * in the model + */ +FloatList EntityListPhrase::relatedColor() const +{ + std::string colorName; + if (this->parent() && this->parent()->relatedEntity().isModel()) + { // return parent model's default color for the cell type specified by + // commonflag + colorName = Entity::flagSummary(this->m_commonFlags); + colorName += " color"; + smtk::model::Model model = this->parent()->relatedEntity(). + as(); + if (model.hasFloatProperty(colorName)) + { + return model.floatProperty(colorName); + } + } + return FloatList(4,-1.); +} + + + } // model namespace } // smtk namespace diff --git a/smtk/model/EntityListPhrase.h b/smtk/model/EntityListPhrase.h index a093a032b9..ab59ee0304 100644 --- a/smtk/model/EntityListPhrase.h +++ b/smtk/model/EntityListPhrase.h @@ -35,6 +35,8 @@ public: EntityRefArray& relatedEntities(); virtual void setFlags(BitFlags commonFlags, BitFlags unionFlags); + virtual bool isRelatedColorMutable() const; + virtual FloatList relatedColor() const; protected: EntityListPhrase(); diff --git a/smtk/model/EntityPhrase.cxx b/smtk/model/EntityPhrase.cxx index 2cf56c82f1..8995024e1b 100644 --- a/smtk/model/EntityPhrase.cxx +++ b/smtk/model/EntityPhrase.cxx @@ -24,7 +24,7 @@ namespace smtk { EntityPhrase::EntityPhrase() { - this->m_mutability = 3; // both color and title are mutable. + this->m_mutability = 5; // both color(4) and title(1) are mutable. } /**\brief Prepare an EntityPhrase for display. @@ -33,7 +33,7 @@ EntityPhrase::Ptr EntityPhrase::setup(const EntityRef& entity, DescriptivePhrase { this->DescriptivePhrase::setup(ENTITY_SUMMARY, parnt); this->m_entity = entity; - this->m_mutability = 3; // both color and title are mutable by default. + this->m_mutability = 5; // both color and title are mutable by default. return this->shared_from_this(); } @@ -83,7 +83,27 @@ EntityRef EntityPhrase::relatedEntity() const /// Return a color associated with the related entity. FloatList EntityPhrase::relatedColor() const { - return this->m_entity.color(); + // return its own color or the color stored on model(set by ENTITY_LIST) + // if in the future user wants to differentiate the color set by entity or + // ENTITY_LIST, change the logic here + smtk::model::FloatList rgba = this->m_entity.color(); + if ((rgba.size() == 4) && (rgba[3] < 0 || rgba[3] > 1)) + { + // invalid color. Maybe the color is assigned by ENTITY_LIST, check model + if (this->m_entity.owningModel().isValid()) + { + // if color is assigned by ENTITIY_LIST, check model + smtk::model::Model model = this->m_entity.owningModel(); + std::string colorName; + colorName = smtk::model::Entity::flagSummary(this->m_entity.entityFlags()); + colorName += " color"; + if (model.hasFloatProperty(colorName)) + { + rgba = model.floatProperty(colorName); + } + } + } + return rgba; } /// True when the entity is valid and marked as mutable (the default, setMutability(0x4)). diff --git a/smtk/model/EntityRef.cxx b/smtk/model/EntityRef.cxx index 342e5f0cf1..9b6248bb30 100644 --- a/smtk/model/EntityRef.cxx +++ b/smtk/model/EntityRef.cxx @@ -313,7 +313,7 @@ void EntityRef::setVisible(bool vis) /** Return a user-assigned color for the entity. * - * If no color was assigned, (0,0,0,0) will be returned. + * If no color was assigned, (0,0,0,-1) will be returned. */ FloatList EntityRef::color() const { -- GitLab From 60075af9e2b40f68e31b34d9ad3a579cca2cd5a2 Mon Sep 17 00:00:00 2001 From: Haocheng Liu Date: Fri, 7 Apr 2017 18:57:52 -0400 Subject: [PATCH 2/2] Fix assigning wrong name for cell color array --- smtk/extension/vtk/source/vtkModelMultiBlockSource.cxx | 4 ++-- smtk/model/testing/python/modelPhrase.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/smtk/extension/vtk/source/vtkModelMultiBlockSource.cxx b/smtk/extension/vtk/source/vtkModelMultiBlockSource.cxx index 05c73e0f58..fd8d2217a5 100644 --- a/smtk/extension/vtk/source/vtkModelMultiBlockSource.cxx +++ b/smtk/extension/vtk/source/vtkModelMultiBlockSource.cxx @@ -423,7 +423,7 @@ vtkSmartPointer vtkModelMultiBlockSource::GenerateRepresentationFro vtkNew cellColor; cellColor->SetNumberOfComponents(4); cellColor->SetNumberOfTuples(pd->GetNumberOfCells()); - cellColor->SetName("Entity Color"); + cellColor->SetName("Entity"); for (int i = 0; i < 4; ++i) { cellColor->FillComponent(i, @@ -542,7 +542,7 @@ void vtkModelMultiBlockSource::GenerateRepresentationFromModel( vtkNew cellColor; cellColor->SetNumberOfComponents(4); cellColor->SetNumberOfTuples(pd->GetNumberOfCells()); - cellColor->SetName("Entity Color"); + cellColor->SetName("Entity"); for (int i = 0; i < 4; ++i) { cellColor->FillComponent(i, diff --git a/smtk/model/testing/python/modelPhrase.py b/smtk/model/testing/python/modelPhrase.py index 7be97a455d..5733fc4916 100644 --- a/smtk/model/testing/python/modelPhrase.py +++ b/smtk/model/testing/python/modelPhrase.py @@ -76,7 +76,7 @@ class TestModelPhrases(unittest.TestCase): 'Expected model name to be mutable.') self.assertEqual(s1[0].isSubtitleMutable(), False, 'Expected model subtitle to be immutable.') - self.assertEqual(s1[0].isRelatedColorMutable(), False, + self.assertEqual(s1[0].isRelatedColorMutable(), True, 'Expected model color to be immutable.') self.assertEqual(s1[0].relatedPropertyName(), '', 'Unexpected related property name "{p}".'.format(p=s1[0].relatedPropertyName())) -- GitLab