Skip to content

Commit

Permalink
ENH: Improve appearance of node information section in Data module
Browse files Browse the repository at this point in the history
In Data module, "MRML node information" section had a "Node information" section and an untitled node attributes section. The node attributes section displayed messages (e.g., attribute name already exists) above the table. This all looked quite confusing.

Updated the GUI to have a "Properties" and "Attributes" section under "MRML node information". Also replaced the label above the table by a tooltip for showing "attribute name already exists" message.

Co-authored-by: Jean-Christophe Fillion-Robin <jchris.fillionr@kitware.com>
  • Loading branch information
lassoan and jcfr committed Feb 13, 2024
1 parent 5207638 commit 55d3feb
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 116 deletions.
36 changes: 10 additions & 26 deletions Libs/MRML/Widgets/Resources/UI/qMRMLNodeAttributeTableView.ui
Original file line number Diff line number Diff line change
Expand Up @@ -26,35 +26,19 @@
<string>qMRMLNodeAttributeTableView</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="AttributeTableMessageLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>13</height>
</size>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>No node selected</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QTableWidget" name="NodeAttributesTable">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
Expand Down
172 changes: 107 additions & 65 deletions Libs/MRML/Widgets/Resources/UI/qMRMLNodeAttributeTableWidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -14,75 +14,108 @@
<string>qMRMLNodeAttributeTableWidget</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>4</number>
</property>
<item row="2" column="0">
<widget class="qMRMLNodeAttributeTableView" name="MRMLNodeAttributeTableView">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
<widget class="ctkCollapsibleGroupBox" name="NodeAttributesGroupBox">
<property name="title">
<string>Attributes</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<widget class="qMRMLNodeAttributeTableView" name="MRMLNodeAttributeTableView">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="AddAttributeButton">
<property name="minimumSize">
<size>
<width>72</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Add blank row to the table. The attribute is added to the MRML node when the name and value is set</string>
</property>
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="RemoveAttributeButton">
<property name="minimumSize">
<size>
<width>72</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Remove selected attribute(s)</string>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="AddAttributeButton">
<property name="minimumSize">
<size>
<width>72</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Add blank row to the table. The attribute is added to the MRML node when the name and value is set</string>
</property>
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="RemoveAttributeButton">
<property name="minimumSize">
<size>
<width>72</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Remove selected attribute(s)</string>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="ctkCollapsibleGroupBox" name="NodeInformationGroupBox">
<widget class="ctkCollapsibleGroupBox" name="NodePropertiesGroupBox">
<property name="title">
<string>Node information</string>
<string>Properties</string>
</property>
<property name="collapsed">
<bool>true</bool>
Expand All @@ -91,13 +124,22 @@
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<widget class="QLabel" name="MRMLNodeInfoLabel">
<property name="text">
<string>No node information is available.</string>
<string/>
</property>
<property name="wordWrap">
<bool>true</bool>
Expand All @@ -113,17 +155,17 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>qMRMLNodeAttributeTableView</class>
<extends>QWidget</extends>
<header>qMRMLNodeAttributeTableView.h</header>
</customwidget>
<customwidget>
<class>ctkCollapsibleGroupBox</class>
<extends>QGroupBox</extends>
<header>ctkCollapsibleGroupBox.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>qMRMLNodeAttributeTableView</class>
<extends>QWidget</extends>
<header>qMRMLNodeAttributeTableView.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
Expand Down
47 changes: 24 additions & 23 deletions Libs/MRML/Widgets/qMRMLNodeAttributeTableView.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
// Qt includes
#include <QStringList>
#include <QItemSelectionModel>
#include <QTimer>
#include <QToolTip>

// qMRML includes
#include "qMRMLNodeAttributeTableView.h"
Expand All @@ -43,16 +45,12 @@ class qMRMLNodeAttributeTableViewPrivate: public Ui_qMRMLNodeAttributeTableView
qMRMLNodeAttributeTableViewPrivate(qMRMLNodeAttributeTableView& object);
void init();

/// Sets table message and takes care of the visibility of the label
void setMessage(const QString& message)
{
this->AttributeTableMessageLabel->setVisible(!message.isEmpty());
this->AttributeTableMessageLabel->setText(message);
};

public:
/// MRML node to inspect
vtkMRMLNode* InspectedNode;
QPoint MessagePosition;
QString MessageText;
QTimer MessageDisplayTimer;
};

// --------------------------------------------------------------------------
Expand All @@ -68,10 +66,12 @@ void qMRMLNodeAttributeTableViewPrivate::init()
Q_Q(qMRMLNodeAttributeTableView);
this->setupUi(q);

this->MessageDisplayTimer.setSingleShot(true);

QObject::connect(this->NodeAttributesTable, SIGNAL(itemChanged(QTableWidgetItem*)),
q, SLOT(onAttributeChanged(QTableWidgetItem*)));

this->setMessage(QString());
QObject::connect(&this->MessageDisplayTimer, SIGNAL(timeout()), q, SLOT(showMessage()));
}

// --------------------------------------------------------------------------
Expand Down Expand Up @@ -115,8 +115,6 @@ void qMRMLNodeAttributeTableView::populateAttributeTable()
{
Q_D(qMRMLNodeAttributeTableView);

d->setMessage(QString());

// Block signals so that onAttributeChanged function is not called when populating
bool wasBlocked = d->NodeAttributesTable->blockSignals(true);

Expand All @@ -130,7 +128,6 @@ void qMRMLNodeAttributeTableView::populateAttributeTable()

if (!d->InspectedNode)
{
d->setMessage(tr("No node is selected"));
d->NodeAttributesTable->setRowCount(0);
d->NodeAttributesTable->blockSignals(wasBlocked);
return;
Expand All @@ -139,7 +136,6 @@ void qMRMLNodeAttributeTableView::populateAttributeTable()
std::vector< std::string > attributeNames = d->InspectedNode->GetAttributeNames();
if (attributeNames.size() == 0)
{
d->setMessage(tr("Selected node has no attributes"));
d->NodeAttributesTable->setRowCount(0);
}
else
Expand Down Expand Up @@ -173,8 +169,6 @@ void qMRMLNodeAttributeTableView::onAttributeChanged(QTableWidgetItem* changedIt
{
Q_D(qMRMLNodeAttributeTableView);

d->setMessage(QString());

if (!changedItem || !d->InspectedNode)
{
return;
Expand All @@ -193,12 +187,18 @@ void qMRMLNodeAttributeTableView::onAttributeChanged(QTableWidgetItem* changedIt
QString attributeNameBeforeEditing = changedItem->data(Qt::UserRole).toString();
if (d->InspectedNode->GetAttribute(changedItem->text().toUtf8().constData()))
{
// Don't set if there is another attribute with the same name (would overwrite it),
// revert to the original value.
d->setMessage(tr("There is already an attribute with the same name"));
bool wasBlocked = d->NodeAttributesTable->blockSignals(true);
changedItem->setText(attributeNameBeforeEditing);
d->NodeAttributesTable->blockSignals(wasBlocked);

// Ensure the attribute name is unique; if not, avoid overwriting it by reverting
// to the original value and notify the user.
d->MessageText = tr("There is already an attribute with the same name");
QRect rect = d->NodeAttributesTable->visualItemRect(changedItem);
d->MessagePosition = d->NodeAttributesTable->mapToGlobal(rect.bottomLeft());
// Due to limitations in displaying the tooltip immediately within this callback,
// a timer is used to delay its appearance until after the attribute change is fully processed.
d->MessageDisplayTimer.start(0);
}
else
{
Expand Down Expand Up @@ -251,12 +251,9 @@ void qMRMLNodeAttributeTableView::addAttribute()

if (!d->InspectedNode)
{
d->setMessage(tr("No node is selected"));
return;
}

d->setMessage(QString());

bool wasBlocked = d->NodeAttributesTable->blockSignals(true);
int rowCountBefore = d->NodeAttributesTable->rowCount();
d->NodeAttributesTable->insertRow( rowCountBefore );
Expand All @@ -280,12 +277,9 @@ void qMRMLNodeAttributeTableView::removeSelectedAttributes()

if (!d->InspectedNode)
{
d->setMessage(tr("No node is selected"));
return;
}

d->setMessage(QString());

// Extract selected row indices out of the selected table widget items list
// (there may be more items selected in a row)
QList<QTableWidgetItem*> selectedItems = d->NodeAttributesTable->selectedItems();
Expand Down Expand Up @@ -422,3 +416,10 @@ QItemSelectionModel* qMRMLNodeAttributeTableView::selectionModel()

return d->NodeAttributesTable->selectionModel();
}

//-----------------------------------------------------------------------------
void qMRMLNodeAttributeTableView::showMessage()
{
Q_D(qMRMLNodeAttributeTableView);
QToolTip::showText(d->MessagePosition, d->MessageText);
}

0 comments on commit 55d3feb

Please sign in to comment.