Merge pull request #12298 from NomAnor/visibility-icon

Add an icon to toggle the visibility of items in the tree view
This commit is contained in:
Chris Hennes
2024-02-26 10:45:07 -06:00
committed by GitHub
11 changed files with 1635 additions and 279 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 21 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -133,6 +133,8 @@
<file>Tree_Annotation.svg</file>
<file>Tree_Dimension.svg</file>
<file>Tree_Python.svg</file>
<file>TreeItemVisible.svg</file>
<file>TreeItemInvisible.svg</file>
<file>dagViewVisible.svg</file>
<file>dagViewPass.svg</file>
<file>dagViewFail.svg</file>

View File

@@ -92,50 +92,57 @@ DlgSettingsUI::DlgSettingsUI(QWidget* parent)
ResizableColumn->setEntryName("ResizableColumn");
ResizableColumn->setParamGrpPath("TreeView");
// Auto generated code (Tools/params_utils.py:433)
VisibilityIcon = new Gui::PrefCheckBox(this);
layoutTreeview->addWidget(VisibilityIcon, 3, 0);
VisibilityIcon->setChecked(Gui::TreeParams::defaultVisibilityIcon());
VisibilityIcon->setEntryName("VisibilityIcon");
VisibilityIcon->setParamGrpPath("TreeView");
// Auto generated code (Tools/params_utils.py:433)
HideColumn = new Gui::PrefCheckBox(this);
layoutTreeview->addWidget(HideColumn, 3, 0);
layoutTreeview->addWidget(HideColumn, 4, 0);
HideColumn->setChecked(Gui::TreeParams::defaultHideColumn());
HideColumn->setEntryName("HideColumn");
HideColumn->setParamGrpPath("TreeView");
// Auto generated code (Tools/params_utils.py:433)
HideScrollBar = new Gui::PrefCheckBox(this);
layoutTreeview->addWidget(HideScrollBar, 4, 0);
layoutTreeview->addWidget(HideScrollBar, 5, 0);
HideScrollBar->setChecked(Gui::TreeParams::defaultHideScrollBar());
HideScrollBar->setEntryName("HideScrollBar");
HideScrollBar->setParamGrpPath("TreeView");
// Auto generated code (Tools/params_utils.py:433)
HideHeaderView = new Gui::PrefCheckBox(this);
layoutTreeview->addWidget(HideHeaderView, 5, 0);
layoutTreeview->addWidget(HideHeaderView, 6, 0);
HideHeaderView->setChecked(Gui::TreeParams::defaultHideHeaderView());
HideHeaderView->setEntryName("HideHeaderView");
HideHeaderView->setParamGrpPath("TreeView");
// Auto generated code (Tools/params_utils.py:433)
labelIconSize = new QLabel(this);
layoutTreeview->addWidget(labelIconSize, 6, 0);
layoutTreeview->addWidget(labelIconSize, 7, 0);
IconSize = new Gui::PrefSpinBox(this);
layoutTreeview->addWidget(IconSize, 6, 1);
layoutTreeview->addWidget(IconSize, 7, 1);
IconSize->setValue(Gui::TreeParams::defaultIconSize());
IconSize->setEntryName("IconSize");
IconSize->setParamGrpPath("TreeView");
// Auto generated code (Tools/params_utils.py:433)
labelFontSize = new QLabel(this);
layoutTreeview->addWidget(labelFontSize, 7, 0);
layoutTreeview->addWidget(labelFontSize, 8, 0);
FontSize = new Gui::PrefSpinBox(this);
layoutTreeview->addWidget(FontSize, 7, 1);
layoutTreeview->addWidget(FontSize, 8, 1);
FontSize->setValue(Gui::TreeParams::defaultFontSize());
FontSize->setEntryName("FontSize");
FontSize->setParamGrpPath("TreeView");
// Auto generated code (Tools/params_utils.py:433)
labelItemSpacing = new QLabel(this);
layoutTreeview->addWidget(labelItemSpacing, 8, 0);
layoutTreeview->addWidget(labelItemSpacing, 9, 0);
ItemSpacing = new Gui::PrefSpinBox(this);
layoutTreeview->addWidget(ItemSpacing, 8, 1);
layoutTreeview->addWidget(ItemSpacing, 9, 1);
ItemSpacing->setValue(Gui::TreeParams::defaultItemSpacing());
ItemSpacing->setEntryName("ItemSpacing");
ItemSpacing->setParamGrpPath("TreeView");
@@ -442,6 +449,7 @@ void DlgSettingsUI::saveSettings()
ItemBackground->onSave();
ItemBackgroundPadding->onSave();
ResizableColumn->onSave();
VisibilityIcon->onSave();
HideColumn->onSave();
HideScrollBar->onSave();
HideHeaderView->onSave();
@@ -482,6 +490,7 @@ void DlgSettingsUI::loadSettings()
ItemBackground->onRestore();
ItemBackgroundPadding->onRestore();
ResizableColumn->onRestore();
VisibilityIcon->onRestore();
HideColumn->onRestore();
HideScrollBar->onRestore();
HideHeaderView->onRestore();
@@ -528,6 +537,8 @@ void DlgSettingsUI::retranslateUi()
labelItemBackgroundPadding->setToolTip(ItemBackgroundPadding->toolTip());
ResizableColumn->setToolTip(QApplication::translate("TreeParams", Gui::TreeParams::docResizableColumn()));
ResizableColumn->setText(QObject::tr("Resizable columns"));
VisibilityIcon->setToolTip(QApplication::translate("TreeParams", Gui::TreeParams::docVisibilityIcon()));
VisibilityIcon->setText(QObject::tr("Show visibility icon"));
HideColumn->setToolTip(QApplication::translate("TreeParams", Gui::TreeParams::docHideColumn()));
HideColumn->setText(QObject::tr("Hide extra column"));
HideScrollBar->setToolTip(QApplication::translate("TreeParams", Gui::TreeParams::docHideScrollBar()));

View File

@@ -78,6 +78,7 @@ private:
QLabel *labelItemBackgroundPadding = nullptr;
Gui::PrefSpinBox *ItemBackgroundPadding = nullptr;
Gui::PrefCheckBox *ResizableColumn = nullptr;
Gui::PrefCheckBox *VisibilityIcon = nullptr;
Gui::PrefCheckBox *HideColumn = nullptr;
Gui::PrefCheckBox *HideScrollBar = nullptr;
Gui::PrefCheckBox *HideHeaderView = nullptr;

View File

@@ -48,6 +48,7 @@ ParamGroup = (
'ItemBackground',
'ItemBackgroundPadding',
'ResizableColumn',
'VisibilityIcon',
'HideColumn',
'HideScrollBar',
'HideHeaderView',

View File

@@ -93,6 +93,14 @@ const int TreeWidget::ObjectType = 1001;
static bool _DraggingActive;
static bool _DragEventFilter;
static bool isVisibilityIconEnabled() {
return TreeParams::getVisibilityIcon();
}
static bool isSelectionCheckBoxesEnabled() {
return TreeParams::getCheckBoxesSelection();
}
void TreeParams::onItemBackgroundChanged()
{
if (getItemBackground()) {
@@ -1552,6 +1560,50 @@ void TreeWidget::keyPressEvent(QKeyEvent* event)
QTreeWidget::keyPressEvent(event);
}
void TreeWidget::mousePressEvent(QMouseEvent* event)
{
QTreeWidget::mousePressEvent(event);
// Handle the visibility icon after the normal event processing to not interfer with
// the selection logic.
if (isVisibilityIconEnabled()) {
QTreeWidgetItem* item = itemAt(event->pos());
if (item && item->type() == TreeWidget::ObjectType && event->button() == Qt::LeftButton) {
auto objitem = static_cast<DocumentObjectItem*>(item);
// Mouse position relative to viewport
auto mousePos = event->pos();
// Rect occupied by the item relative to viewport
auto iconRect = visualItemRect(objitem);
// If the checkboxes are visible, these are displayed before the icon
// and we have to compensate for its width.
if (isSelectionCheckBoxesEnabled()) {
auto style = this->style();
int checkboxWidth = style->pixelMetric(QStyle::PM_IndicatorWidth)
+ style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
iconRect.adjust(checkboxWidth, 0, 0, 0);
}
// We are interested in the first icon (visibility icon)
iconRect.setWidth(iconSize());
// If the visibility icon was clicked, toggle the DocumentObject visibility
if (iconRect.contains(mousePos)) {
auto vp = objitem->object();
if (vp->isShow()) {
vp->hide();
} else {
vp->show();
}
event->setAccepted(true);
return;
}
}
}
}
void TreeWidget::mouseDoubleClickEvent(QMouseEvent* event)
{
QTreeWidgetItem* item = itemAt(event->pos());
@@ -3282,10 +3334,6 @@ void TreeWidget::onItemSelectionChanged()
this->blockSelection(lock);
}
static bool isSelectionCheckBoxesEnabled() {
return TreeParams::getCheckBoxesSelection();
}
void TreeWidget::synchronizeSelectionCheckBoxes() {
const bool useCheckBoxes = isSelectionCheckBoxesEnabled();
for (auto tree : TreeWidget::Instances) {
@@ -3303,6 +3351,20 @@ void TreeWidget::synchronizeSelectionCheckBoxes() {
}
}
void TreeWidget::updateVisibilityIcons() {
for (auto tree : TreeWidget::Instances) {
QSignalBlocker blocker(tree);
for (QTreeWidgetItemIterator it(tree); *it; ++it) {
auto item = *it;
if (item->type() == ObjectType) {
auto objitem = static_cast<DocumentObjectItem*>(item);
objitem->testStatus(true);
}
}
tree->resizeColumnToContents(0);
}
}
QList<QTreeWidgetItem*> TreeWidget::childrenOfItem(const QTreeWidgetItem& item) const {
QList children = QList<QTreeWidgetItem*>();
@@ -5117,7 +5179,7 @@ void DocumentObjectItem::testStatus(bool resetStatus, QIcon& icon1, QIcon& icon2
previousStatus = currentStatus;
QIcon::Mode mode = QIcon::Normal;
if (currentStatus & 1) { // visible
if (isVisibilityIconEnabled() || (currentStatus & 1)) { // visible
// Note: By default the foreground, i.e. text color is invalid
// to make use of the default color of the tree widget's palette.
// If we temporarily set this color to dark and reset to an invalid
@@ -5262,6 +5324,35 @@ void DocumentObjectItem::testStatus(bool resetStatus, QIcon& icon1, QIcon& icon2
icon = object()->mergeColorfulOverlayIcons(icon);
}
if (isVisibilityIconEnabled()) {
static QPixmap pxVisible, pxInvisible;
if (pxVisible.isNull()) {
pxVisible = BitmapFactory().pixmap("TreeItemVisible");
}
if (pxInvisible.isNull()) {
pxInvisible = BitmapFactory().pixmap("TreeItemInvisible");
}
// Prepend the visibility pixmap to the final icon pixmaps and use these as the icon.
QIcon new_icon;
for (auto state: {QIcon::On, QIcon::Off}) {
QPixmap px_org = icon.pixmap(0xFFFF, 0xFFFF, QIcon::Normal, state);
QPixmap px(2*px_org.width(), px_org.height());
px.fill(Qt::transparent);
QPainter pt;
pt.begin(&px);
pt.setPen(Qt::NoPen);
pt.drawPixmap(0, 0, px_org.width(), px_org.height(), (currentStatus & 1) ? pxVisible : pxInvisible);
pt.drawPixmap(px_org.width(), 0, px_org.width(), px_org.height(), px_org);
pt.end();
new_icon.addPixmap(px, QIcon::Normal, state);
}
icon = new_icon;
}
_Timing(2, setIcon);
this->setIcon(0, icon);

View File

@@ -122,6 +122,7 @@ public:
void itemSearch(const QString &text, bool select);
static void synchronizeSelectionCheckBoxes();
static void updateVisibilityIcons();
QList<QTreeWidgetItem *> childrenOfItem(const QTreeWidgetItem &item) const;
@@ -155,6 +156,7 @@ protected:
//@}
bool event(QEvent *e) override;
void keyPressEvent(QKeyEvent *event) override;
void mousePressEvent(QMouseEvent * event) override;
void mouseDoubleClickEvent(QMouseEvent * event) override;
protected:

File diff suppressed because it is too large Load Diff

View File

@@ -28,11 +28,11 @@ import TreeParams
TreeParams.declare_begin()
]]]*/
// Auto generated code (Tools/params_utils.py:72)
// Auto generated code (Tools/params_utils.py:82)
#include <Base/Parameter.h>
// Auto generated code (Tools/params_utils.py:78)
// Auto generated code (Tools/params_utils.py:90)
namespace Gui {
/** Convenient class to obtain tree view related parameters
@@ -68,7 +68,7 @@ class GuiExport TreeParams {
public:
static ParameterGrp::handle getHandle();
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter SyncSelection
static const bool & getSyncSelection();
@@ -79,7 +79,7 @@ public:
static void onSyncSelectionChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter CheckBoxesSelection
static const bool & getCheckBoxesSelection();
@@ -90,7 +90,7 @@ public:
static void onCheckBoxesSelectionChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter SyncView
static const bool & getSyncView();
@@ -100,7 +100,7 @@ public:
static const char *docSyncView();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter PreSelection
static const bool & getPreSelection();
@@ -110,7 +110,7 @@ public:
static const char *docPreSelection();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter SyncPlacement
static const bool & getSyncPlacement();
@@ -120,7 +120,7 @@ public:
static const char *docSyncPlacement();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter RecordSelection
static const bool & getRecordSelection();
@@ -130,7 +130,7 @@ public:
static const char *docRecordSelection();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter DocumentMode
static const long & getDocumentMode();
@@ -141,7 +141,7 @@ public:
static void onDocumentModeChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter StatusTimeout
static const long & getStatusTimeout();
@@ -151,7 +151,7 @@ public:
static const char *docStatusTimeout();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter SelectionTimeout
static const long & getSelectionTimeout();
@@ -161,7 +161,7 @@ public:
static const char *docSelectionTimeout();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter PreSelectionTimeout
static const long & getPreSelectionTimeout();
@@ -171,7 +171,7 @@ public:
static const char *docPreSelectionTimeout();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter PreSelectionDelay
static const long & getPreSelectionDelay();
@@ -181,7 +181,7 @@ public:
static const char *docPreSelectionDelay();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter PreSelectionMinDelay
static const long & getPreSelectionMinDelay();
@@ -191,7 +191,7 @@ public:
static const char *docPreSelectionMinDelay();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter RecomputeOnDrop
static const bool & getRecomputeOnDrop();
@@ -201,7 +201,7 @@ public:
static const char *docRecomputeOnDrop();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter KeepRootOrder
static const bool & getKeepRootOrder();
@@ -211,7 +211,7 @@ public:
static const char *docKeepRootOrder();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter TreeActiveAutoExpand
static const bool & getTreeActiveAutoExpand();
@@ -221,7 +221,7 @@ public:
static const char *docTreeActiveAutoExpand();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter TreeActiveColor
static const unsigned long & getTreeActiveColor();
@@ -232,7 +232,7 @@ public:
static void onTreeActiveColorChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter TreeEditColor
static const unsigned long & getTreeEditColor();
@@ -243,7 +243,7 @@ public:
static void onTreeEditColorChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter SelectingGroupColor
static const unsigned long & getSelectingGroupColor();
@@ -254,7 +254,7 @@ public:
static void onSelectingGroupColorChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter TreeActiveBold
static const bool & getTreeActiveBold();
@@ -265,7 +265,7 @@ public:
static void onTreeActiveBoldChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter TreeActiveItalic
static const bool & getTreeActiveItalic();
@@ -276,7 +276,7 @@ public:
static void onTreeActiveItalicChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter TreeActiveUnderlined
static const bool & getTreeActiveUnderlined();
@@ -287,7 +287,7 @@ public:
static void onTreeActiveUnderlinedChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter TreeActiveOverlined
static const bool & getTreeActiveOverlined();
@@ -298,7 +298,7 @@ public:
static void onTreeActiveOverlinedChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter Indentation
static const long & getIndentation();
@@ -309,7 +309,7 @@ public:
static void onIndentationChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter LabelExpression
static const bool & getLabelExpression();
@@ -319,7 +319,7 @@ public:
static const char *docLabelExpression();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter IconSize
static const long & getIconSize();
@@ -330,7 +330,7 @@ public:
static void onIconSizeChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter FontSize
static const long & getFontSize();
@@ -341,7 +341,7 @@ public:
static void onFontSizeChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter ItemSpacing
static const long & getItemSpacing();
@@ -352,7 +352,7 @@ public:
static void onItemSpacingChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter ItemBackground
///
@@ -365,7 +365,7 @@ public:
static void onItemBackgroundChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter ItemBackgroundPadding
///
@@ -378,7 +378,7 @@ public:
static void onItemBackgroundPaddingChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter HideColumn
///
@@ -391,7 +391,7 @@ public:
static void onHideColumnChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter HideScrollBar
///
@@ -403,7 +403,7 @@ public:
static const char *docHideScrollBar();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter HideHeaderView
///
@@ -415,7 +415,7 @@ public:
static const char *docHideHeaderView();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter ResizableColumn
///
@@ -428,7 +428,7 @@ public:
static void onResizableColumnChanged();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter ColumnSize1
static const long & getColumnSize1();
@@ -438,7 +438,7 @@ public:
static const char *docColumnSize1();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter ColumnSize2
static const long & getColumnSize2();
@@ -448,7 +448,7 @@ public:
static const char *docColumnSize2();
//@}
// Auto generated code (Tools/params_utils.py:122)
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter TreeToolTipIcon
static const bool & getTreeToolTipIcon();
@@ -457,6 +457,19 @@ public:
static void setTreeToolTipIcon(const bool &v);
static const char *docTreeToolTipIcon();
//@}
// Auto generated code (Tools/params_utils.py:138)
//@{
/// Accessor for parameter VisibilityIcon
///
/// If enabled, show an eye icon before the tree view items, showing the items visibility status. When clicked the visibility is toggled
static const bool & getVisibilityIcon();
static const bool & defaultVisibilityIcon();
static void removeVisibilityIcon();
static void setVisibilityIcon(const bool &v);
static const char *docVisibilityIcon();
static void onVisibilityIconChanged();
//@}
//[[[end]]]
static void refreshTreeViews();
@@ -465,7 +478,7 @@ public:
TreeParams.declare_end()
]]]*/
// Auto generated code (Tools/params_utils.py:150)
// Auto generated code (Tools/params_utils.py:178)
}; // class TreeParams
} // namespace Gui
//[[[end]]]

View File

@@ -80,6 +80,8 @@ Params = [
ParamInt('ColumnSize1', 0),
ParamInt('ColumnSize2', 0),
ParamBool('TreeToolTipIcon', False, title='Show icon in tool tip'),
ParamBool('VisibilityIcon', False, on_change=True, title='Show visibility icon',
doc = "If enabled, show an eye icon before the tree view items, showing the items visibility status. When clicked the visibility is toggled"),
]
def declare_begin():