Commit 4db17e02 authored by Haocheng LIU's avatar Haocheng LIU
Browse files

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.
parent d363a6ab
Pipeline #54397 passed with stage
......@@ -135,7 +135,6 @@ void QEntityItemDelegate::paint(
QIcon icon = qvariant_cast<QIcon>(idx.data(QEntityItemModel::EntityIconRole));
QSize iconsize = icon.actualSize(option.decorationSize);
QColor swatchColor = qvariant_cast<QColor>(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<QString>(idx.data(QEntityItemModel::TitleTextRole));
QString subtitleText = qvariant_cast<QString>(idx.data(QEntityItemModel::SubtitleTextRole));
//std::cout << "Paint " << idx.internalPointer() << " " << idx.row() << " " << titleText.toStdString().c_str() << "\n";
QColor swatchColor = qvariant_cast<QColor>(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<QIcon>(
idx.data(QEntityItemModel::EntityVisibilityRole));
QSize visiconsize = visicon.actualSize(option.decorationSize);
QColor swatchColor = qvariant_cast<QColor>(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")
{
......
......@@ -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();
......
......@@ -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();
......
......@@ -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<MeshPhrase>(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
<EntityListPhrase>(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<double> 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<MeshPhrase>(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(
......
......@@ -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<smtk::model::Model>();
if (model.hasFloatProperty(colorName))
{
return model.floatProperty(colorName);
}
}
return FloatList(4,-1.);
}
} // model namespace
} // smtk namespace
......@@ -35,6 +35,8 @@ public:
EntityRefArray& relatedEntities();
virtual void setFlags(BitFlags commonFlags, BitFlags unionFlags);
virtual bool isRelatedColorMutable() const;
virtual FloatList relatedColor() const;
protected:
EntityListPhrase();
......
......@@ -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)).
......
......@@ -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
{
......
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