Commit a9e4e22c authored by David Thompson's avatar David Thompson

Move most of qtComponentItem into qtReferenceItem.

parent 32d13a08
......@@ -46,243 +46,5 @@ qtComponentItem::qtComponentItem(const AttributeItemInfo& info)
qtComponentItem::~qtComponentItem()
{
}
void qtComponentItem::setLabelVisible(bool visible)
{
m_p->m_label->setVisible(visible);
}
void qtComponentItem::updateItemData()
{
}
smtk::view::PhraseModelPtr qtComponentItem::createPhraseModel() const
{
// Constructing the PhraseModel with a View properly initializes the SubphraseGenerator
// to point back to the model (thus ensuring subphrases are decorated). This is required
// since we need to decorate phrases to show+edit "visibility" as set membership:
auto phraseModel = smtk::view::ComponentPhraseModel::create(m_itemInfo.component());
phraseModel->root()->findDelegate()->setModel(phraseModel);
auto def = std::dynamic_pointer_cast<const smtk::attribute::ComponentItemDefinition>(
m_itemInfo.item()->definition());
std::static_pointer_cast<smtk::view::ComponentPhraseModel>(phraseModel)
->setComponentFilters(def->acceptableEntries());
return phraseModel;
}
void qtComponentItem::createWidget()
{
// Let our subclass do the UI work.
this->Superclass::createWidget();
// Now add in ComponentItem 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 qtComponentItem::synopsis(bool& ok) const
{
auto item = m_itemInfo.itemAs<smtk::attribute::ComponentItem>();
if (!item)
{
ok = false;
return "uninitialized item";
}
std::size_t numRequired = item->numberOfRequiredValues();
std::size_t maxAllowed = (item->isExtensible() ? item->maxNumberOfValues() : numRequired);
std::ostringstream label;
std::size_t numSel = 0;
for (auto entry : m_p->m_members)
{
if (entry.second > 0)
{
++numSel;
}
}
ok = true;
if (numRequired < 2 && maxAllowed == 1)
{
auto ment = (m_p->m_members.empty() ? smtk::resource::PersistentObjectPtr()
: m_p->m_members.begin()->first);
label << (numSel == 1 ? (ment ? ment->name() : "NULL!!")
: (numSel > 0 ? "too many" : "(none)"));
ok = numSel >= numRequired && numSel <= maxAllowed;
}
else
{
label << numSel;
if (numRequired > 0)
{
label << " of ";
if (numRequired == maxAllowed)
{ // Exactly N values are allowed and required.
label << numRequired;
}
else if (maxAllowed > 0)
{ // There is a minimum required, but a limited additional number are acceptable
label << numRequired << "—" << maxAllowed;
}
else
{ // Any number are allowed, but there is a minimum.
label << numRequired << "+";
}
ok &= (numSel >= numRequired);
}
else
{ // no values are required, but there may be a cap on the maximum number.
if (maxAllowed > 0)
{
label << " of 0–" << maxAllowed;
}
else
{
label << " chosen";
}
}
}
ok &= (maxAllowed == 0 || numSel <= maxAllowed);
return label.str();
}
int qtComponentItem::decorateWithMembership(smtk::view::DescriptivePhrasePtr phr)
{
smtk::view::VisibilityContent::decoratePhrase(
phr, [this](smtk::view::VisibilityContent::Query qq, int val,
smtk::view::ConstPhraseContentPtr data) {
auto comp = data ? data->relatedComponent() : nullptr;
auto rsrc = comp ? comp->resource() : (data ? data->relatedResource() : nullptr);
switch (qq)
{
case smtk::view::VisibilityContent::DISPLAYABLE:
return (comp || (!comp && rsrc)) ? 1 : 0;
case smtk::view::VisibilityContent::EDITABLE:
return (comp || (!comp && rsrc)) ? 1 : 0;
case smtk::view::VisibilityContent::GET_VALUE:
if (comp)
{
auto valIt = m_p->m_members.find(comp);
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 component is not a model entity or NULL.
case smtk::view::VisibilityContent::SET_VALUE:
if (comp)
{
if (val && !m_p->m_members.empty())
{
auto item = m_itemInfo.itemAs<attribute::ComponentItem>();
if (item->numberOfRequiredValues() <= 1 &&
(!item->isExtensible() || 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[comp] = val ? 1 : 0; // FIXME: Use a bit specified by the application.
this->updateSynopsisLabels();
return 1;
}
}
return 0;
});
return 0;
}
void qtComponentItem::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::ComponentItem>();
if (item->numberOfRequiredValues() <= 1 && item->maxNumberOfValues() == 1)
{
m_p->m_members.clear();
m_p->m_phraseModel->triggerDataChanged();
}
}
cphr->setRelatedVisibility(!currentMembership);
this->updateSynopsisLabels();
}
}
bool qtComponentItem::synchronize(UpdateSource src)
{
auto item = m_itemInfo.itemAs<attribute::ComponentItem>();
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::Component>(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;
}
}
}
......@@ -30,24 +30,6 @@ public:
static qtItem* createItemWidget(const AttributeItemInfo& info);
qtComponentItem(const AttributeItemInfo& info);
virtual ~qtComponentItem();
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;
};
}
}
......
This diff is collapsed.
......@@ -35,8 +35,23 @@ class SMTKQTEXT_EXPORT qtReferenceItem : public qtItem
public:
qtReferenceItem(const AttributeItemInfo& info);
virtual ~qtReferenceItem();
static qtItem* createItemWidget(const AttributeItemInfo& info);
enum AcceptsTypes
{
NONE,
RESOURCES,
COMPONENTS,
BOTH
};
AcceptsTypes acceptableTypes() const;
void setLabelVisible(bool) override;
protected slots:
void updateItemData() override;
virtual void selectionLinkToggled(bool linked);
virtual void setOutputOptional(int state);
......@@ -69,28 +84,28 @@ protected:
* The model should be configured using information the item (this->getObject())
* and be ready for use.
*/
virtual smtk::view::PhraseModelPtr createPhraseModel() const = 0;
virtual smtk::view::PhraseModelPtr createPhraseModel() const;
virtual void createWidget() override;
virtual void clearWidgets();
virtual void updateUI();
virtual std::string synopsis(bool& membershipValid) const = 0;
virtual std::string synopsis(bool& membershipValid) const;
virtual void updateSynopsisLabels() const;
bool eventFilter(QObject* src, QEvent* event) override;
/// Called by eventFilter() when user hits space/enter in popup.
virtual void toggleCurrentItem() = 0;
virtual void toggleCurrentItem();
/**\brief This method is called by the m_p->m_phraseModel to decorate each phrase.
*
* This method ensures that each phrase's visibility corresponds to whether
* or not it is a member of the underlying attribute-system's reference item.
*/
virtual int decorateWithMembership(smtk::view::DescriptivePhrasePtr phr) = 0;
virtual int decorateWithMembership(smtk::view::DescriptivePhrasePtr phr);
/// Indicate whether the GUI should be updated from the item it presents or vice versa.
enum class UpdateSource
......@@ -100,7 +115,7 @@ protected:
};
/// Children must implement this.
virtual bool synchronize(UpdateSource src) = 0;
virtual bool synchronize(UpdateSource src);
void checkRemovedComponents(smtk::view::DescriptivePhrasePtr, smtk::view::PhraseModelEvent,
const std::vector<int>&, const std::vector<int>&, const std::vector<int>&);
......
......@@ -162,6 +162,7 @@ void qtUIManager::commonConstructor()
this->registerItemConstructor("qtFileItem", qtFileItem::createItemWidget);
this->registerItemConstructor("qtGroupItem", qtGroupItem::createItemWidget);
this->registerItemConstructor("qtIntItem", qtIntItem::createItemWidget);
this->registerItemConstructor("qtReferenceItem", qtReferenceItem::createItemWidget);
this->registerItemConstructor("qtResourceItem", qtResourceItem::createItemWidget);
this->registerItemConstructor("qtStringItem", qtStringItem::createItemWidget);
this->registerItemConstructor("qtVoidItem", qtVoidItem::createItemWidget);
......@@ -942,16 +943,14 @@ qtItem* qtUIManager::defaultItemConstructor(const AttributeItemInfo& info)
return qtGroupItem::createItemWidget(info);
case smtk::attribute::Item::IntType:
return qtIntItem::createItemWidget(info);
case smtk::attribute::Item::ReferenceType:
return qtReferenceItem::createItemWidget(info);
case smtk::attribute::Item::ResourceType:
return qtResourceItem::createItemWidget(info);
case smtk::attribute::Item::StringType:
return qtStringItem::createItemWidget(info);
case smtk::attribute::Item::VoidType:
return qtVoidItem::createItemWidget(info);
case smtk::attribute::Item::ReferenceType:
// ReferenceItems are currently only used for associations. We can safely
// ignore them here without signaling an error.
return nullptr;
default:
smtkErrorMacro(smtk::io::Logger::instance(),
"Error: Unsupported Item Type: " << smtk::attribute::Item::type2String(item->type()));
......
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