mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-04 18:04:14 +02:00
Add View > Show to hide texts, shapes, pictures by kind (bugtracker #301)
A submenu under View (Affichage > Afficher) with one tick per kind: symbol texts, wire texts, free texts, shapes, pictures, tables and cross-references. Unticking one hides it on every folio of every open project; the status bar says how many kinds are hidden. Session only, not saved in the project. Each item is tagged with its kind by its constructor (ShownKinds::tag), so an item created while its kind is hidden starts hidden whatever created it. A tag rather than type(): the cross-reference under a contact's label is a plain QGraphicsTextItem. Items that already hide themselves (wire text switched off, one text per potential, a cross-reference snapped elsewhere) now go through ShownKinds::setVisible(): the kind state can only veto a show, and apply() re-shows only what it hid itself (hidden_key), never what an item hid. Conductor::updateTextVisibility() replaces the same visibility rule pasted in diagrampropertiesdialog.cpp and qetscriptapi.cpp. Hidden items are not selectable (Qt), so Select All, copy and delete skip them. Print, PDF and image export render the scene and leave them out; the DXF export walks items itself and skips them through ShownKinds::isHidden(). CrossRefItem::linkedChanged() keeps following its slaves while hidden only by kind, so its label is right when shown. Known limitation: QGraphicsScene::itemsBoundingRect() still counts hidden items, so Zoom to fit and borderless image export keep their space. Verified: tst_shownkinds (12 cases, two mutation checks) and ctest 55/55; GUI hide/show of symbol texts, wire texts (incl. one text per potential), free texts, shapes and cross-references returns pixel-identical folios; with nothing hidden, --export-dxf of the 24 examples is byte-identical to master (133 files) and --export-pdf renders identically (133 pages). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015FPuYPS4T7QuEwjNu22rXD
This commit is contained in:
@@ -242,6 +242,8 @@ set(QET_SRC_FILES
|
||||
${QET_DIR}/sources/genericpanel.h
|
||||
${QET_DIR}/sources/itemgroups.cpp
|
||||
${QET_DIR}/sources/itemgroups.h
|
||||
${QET_DIR}/sources/shownkinds.cpp
|
||||
${QET_DIR}/sources/shownkinds.h
|
||||
${QET_DIR}/sources/lastusedstyle.cpp
|
||||
${QET_DIR}/sources/lastusedstyle.h
|
||||
${QET_DIR}/sources/machine_info.cpp
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "dxfexport.h"
|
||||
#include "shownkinds.h"
|
||||
|
||||
#include "conductorsegment.h"
|
||||
#include "createdxf.h"
|
||||
@@ -135,6 +136,10 @@ void DxfExport::write(Diagram *diagram, int width, int height,
|
||||
}
|
||||
}
|
||||
for (QGraphicsItem *qgi : std::as_const(stacked_items)) {
|
||||
//Left out like on screen and in print (View > Show, #301)
|
||||
if (ShownKinds::isHidden(qgi)) {
|
||||
continue;
|
||||
}
|
||||
if (Element *elmt = qgraphicsitem_cast<Element *>(qgi)) {
|
||||
list_elements << elmt;
|
||||
} else if (Conductor *f = qgraphicsitem_cast<Conductor *>(qgi)) {
|
||||
@@ -147,7 +152,8 @@ void DxfExport::write(Diagram *diagram, int width, int height,
|
||||
list_shapes << dii;
|
||||
} else if (DynamicElementTextItem *deti = qgraphicsitem_cast<DynamicElementTextItem *>(qgi)) {
|
||||
list_texts << deti;
|
||||
if (QGraphicsTextItem *xref = deti->slaveXrefItem()) {
|
||||
QGraphicsTextItem *xref = deti->slaveXrefItem();
|
||||
if (xref && !ShownKinds::isHidden(xref)) {
|
||||
list_xref_texts << xref;
|
||||
}
|
||||
} else if (QetGraphicsTableItem *gti = qgraphicsitem_cast<QetGraphicsTableItem *>(qgi)) {
|
||||
@@ -290,7 +296,7 @@ void DxfExport::write(Diagram *diagram, int width, int height,
|
||||
Createdxf::layer = Layer::WireNumbers;
|
||||
ConductorTextItem *textItem = cond -> textItem();
|
||||
|
||||
if (textItem) {
|
||||
if (textItem && !ShownKinds::isHidden(textItem)) {
|
||||
qreal fontSize = textItem -> font().pointSizeF();
|
||||
if (fontSize < 0)
|
||||
fontSize = textItem -> font().pixelSize();
|
||||
|
||||
@@ -264,6 +264,8 @@ class QETApp : public QObject
|
||||
signals:
|
||||
/// The text grid setting changed, see TextGrid.
|
||||
void textGridChanged();
|
||||
/// A kind of item was shown or hidden, see ShownKinds.
|
||||
void shownKindsChanged();
|
||||
|
||||
public slots:
|
||||
void systray(QSystemTrayIcon::ActivationReason);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "qetdiagrameditor.h"
|
||||
#include "shownkinds.h"
|
||||
#ifdef QET_HAS_SCRIPTING
|
||||
#include "scripting/qetscripting.h"
|
||||
#include "scripting/scriptlibrary.h"
|
||||
@@ -607,6 +608,36 @@ void QETDiagramEditor::setUpActions()
|
||||
dv->setCellLinesShown(checked);
|
||||
});
|
||||
|
||||
//Show or hide whole kinds of items on every folio (bugtracker #301)
|
||||
m_shown_kinds_menu = new QMenu(tr("Afficher"), this);
|
||||
const QList<QPair<ShownKinds::Kind, QString>> kinds {
|
||||
{ShownKinds::SymbolTexts, tr("Textes des éléments")},
|
||||
{ShownKinds::WireNumbers, tr("Textes des conducteurs")},
|
||||
{ShownKinds::FreeTexts, tr("Champs de texte")},
|
||||
{ShownKinds::Shapes, tr("Formes")},
|
||||
{ShownKinds::Pictures, tr("Images")},
|
||||
{ShownKinds::Tables, tr("Tableaux")},
|
||||
{ShownKinds::CrossReferences, tr("Références croisées")}};
|
||||
for (const auto &kind : kinds)
|
||||
{
|
||||
QAction *action = m_shown_kinds_menu->addAction(kind.second);
|
||||
action->setCheckable(true);
|
||||
action->setData(int(kind.first));
|
||||
connect(action, &QAction::triggered, this, [kind](bool checked) {
|
||||
ShownKinds::setShown(kind.first, checked);
|
||||
for (QETProject *project : QETApp::registeredProjects())
|
||||
for (Diagram *diagram : project->diagrams())
|
||||
ShownKinds::apply(diagram, kind.first);
|
||||
emit QETApp::instance()->shownKindsChanged();
|
||||
});
|
||||
}
|
||||
m_hidden_kinds_label = new QLabel(this);
|
||||
m_hidden_kinds_label->setToolTip(tr("Voir Affichage > Afficher"));
|
||||
statusBar()->addPermanentWidget(m_hidden_kinds_label);
|
||||
connect(QETApp::instance(), &QETApp::shownKindsChanged,
|
||||
this, &QETDiagramEditor::updateShownKinds);
|
||||
updateShownKinds();
|
||||
|
||||
//Edit current diagram properties
|
||||
m_edit_diagram_properties = new QAction(QET::Icons::DialogInformation, tr("Propriétés du folio"), this);
|
||||
ShortcutManager::instance().registerAction(m_edit_diagram_properties, "diagrameditor.edit_diagram_properties", tr("Éditeur de schémas"), Qt::CTRL | Qt::Key_L);
|
||||
@@ -1458,6 +1489,7 @@ void QETDiagramEditor::setUpMenu()
|
||||
menu_affichage -> addAction(m_draw_guides);
|
||||
menu_affichage -> addAction(m_cell_rulers);
|
||||
menu_affichage -> addAction(m_cell_lines);
|
||||
menu_affichage -> addMenu(m_shown_kinds_menu);
|
||||
menu_affichage -> addMenu(m_background_color_button->menu());
|
||||
menu_affichage -> addSeparator();
|
||||
menu_affichage -> addActions(m_zoom_actions_group.actions());
|
||||
@@ -4140,6 +4172,21 @@ void QETDiagramEditor::updateScriptActions()
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
@brief QETDiagramEditor::updateShownKinds
|
||||
Tick the kinds shown in View > Show, and say in the status bar how many
|
||||
are hidden, so that a hidden kind is never forgotten.
|
||||
*/
|
||||
void QETDiagramEditor::updateShownKinds()
|
||||
{
|
||||
for (QAction *action : m_shown_kinds_menu->actions())
|
||||
action->setChecked(ShownKinds::isShown(ShownKinds::Kind(action->data().toInt())));
|
||||
|
||||
const int hidden = ShownKinds::hiddenCount();
|
||||
m_hidden_kinds_label->setText(tr("%n type(s) d'objets masqué(s)", "", hidden));
|
||||
m_hidden_kinds_label->setVisible(hidden > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief QETDiagramEditor::updateTextGridButton
|
||||
Show the current text grid on its toolbar button and check it in its menu.
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <QUndoGroup>
|
||||
|
||||
class QToolButton;
|
||||
class QLabel;
|
||||
|
||||
class QMdiSubWindow;
|
||||
class QETProject;
|
||||
@@ -187,6 +188,7 @@ class QETDiagramEditor : public QETMainWindow
|
||||
|
||||
private slots:
|
||||
void updateTextGridButton();
|
||||
void updateShownKinds();
|
||||
void selectionChanged();
|
||||
|
||||
public:
|
||||
@@ -284,6 +286,8 @@ class QETDiagramEditor : public QETMainWindow
|
||||
DiagramBgColorToolButton *m_background_color_button = nullptr;
|
||||
QMenu *m_text_grid_menu = nullptr; ///< Snap step used when dragging texts
|
||||
QToolButton *m_text_grid_button = nullptr;
|
||||
QMenu *m_shown_kinds_menu = nullptr; ///< View > Show, kinds of items (#301)
|
||||
QLabel *m_hidden_kinds_label = nullptr; ///< Status bar: how many kinds are hidden
|
||||
|
||||
QList <QAction *> m_zoom_action_toolBar; ///Only zoom action must displayed in the toolbar
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "qetgraphicstableitem.h"
|
||||
#include "../../shownkinds.h"
|
||||
#include "../../qetproject.h"
|
||||
#include "../../QPropertyUndoCommand/qpropertyundocommand.h"
|
||||
#include "../../createdxf.h"
|
||||
@@ -133,6 +134,7 @@ void QetGraphicsTableItem::checkInsufficientRowsCount(
|
||||
QetGraphicsTableItem::QetGraphicsTableItem(QGraphicsItem *parent) :
|
||||
QetGraphicsItem(parent)
|
||||
{
|
||||
ShownKinds::tag(this, ShownKinds::Tables);
|
||||
setFlag(QGraphicsItem::ItemIsMovable, true);
|
||||
setFlag(QGraphicsItem::ItemIsSelectable, true);
|
||||
setAcceptHoverEvents(true);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "../qetgraphicsitem/conductor.h"
|
||||
#include "../shownkinds.h"
|
||||
#include "../lastusedstyle.h"
|
||||
#include "../qetproject.h"
|
||||
#include "../QPropertyUndoCommand/qpropertyundocommand.h"
|
||||
@@ -1521,6 +1522,20 @@ QPointF Conductor::posForText(Qt::Orientations &flag)
|
||||
return p1;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Conductor::updateTextVisibility
|
||||
Show the text of this conductor if its properties ask for it and wire
|
||||
numbers are not hidden (View > Show). With "one text per potential",
|
||||
call calculateTextItemPosition() afterwards: it hides all texts of the
|
||||
potential but the longest conductor's.
|
||||
*/
|
||||
void Conductor::updateTextVisibility()
|
||||
{
|
||||
ShownKinds::setVisible(m_text_item,
|
||||
m_properties.type == ConductorProperties::Multi
|
||||
&& m_properties.m_show_text);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Conductor::calculateTextItemPosition
|
||||
Move the text at middle of conductor (if is vertical or horizontal)
|
||||
@@ -1548,10 +1563,11 @@ void Conductor::calculateTextItemPosition()
|
||||
|
||||
//At this point this conductor is the longest conductor we hide all text of conductor_list
|
||||
foreach (Conductor *c, relatedPotentialConductors(false)) {
|
||||
c -> textItem() -> setVisible(false);
|
||||
ShownKinds::setVisible(c -> textItem(), false);
|
||||
}
|
||||
//Make sure text item is visible
|
||||
m_text_item -> setVisible(true);
|
||||
//Make sure text item is visible, unless wire numbers are hidden
|
||||
//(View > Show)
|
||||
ShownKinds::setVisible(m_text_item, true);
|
||||
}
|
||||
|
||||
//position
|
||||
@@ -1806,11 +1822,7 @@ void Conductor::setProperties(const ConductorProperties &property)
|
||||
m_text_item->setFont(font);
|
||||
m_text_item->setColor(m_properties.text_color);
|
||||
|
||||
if (m_properties.type != ConductorProperties::Multi)
|
||||
m_text_item->setVisible(false);
|
||||
else
|
||||
m_text_item->setVisible(m_properties.m_show_text);
|
||||
|
||||
updateTextVisibility();
|
||||
calculateTextItemPosition();
|
||||
update();
|
||||
|
||||
|
||||
@@ -129,6 +129,7 @@ class Conductor : public QGraphicsObject
|
||||
void setProfiles(const ConductorProfilesGroup &);
|
||||
ConductorProfilesGroup profiles() const;
|
||||
void calculateTextItemPosition();
|
||||
void updateTextVisibility();
|
||||
virtual Highlight highlight() const;
|
||||
virtual void setHighlighted(Highlight);
|
||||
QSet<Conductor *> relatedPotentialConductors(
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "conductortextitem.h"
|
||||
#include "../shownkinds.h"
|
||||
|
||||
#include "../diagram.h"
|
||||
#include "../diagramcommands.h"
|
||||
@@ -31,6 +32,7 @@ ConductorTextItem::ConductorTextItem(Conductor *parent_conductor) :
|
||||
moved_by_user_(false),
|
||||
rotate_by_user_(false)
|
||||
{
|
||||
ShownKinds::tag(this, ShownKinds::WireNumbers);
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
|
||||
@@ -45,7 +47,9 @@ ConductorTextItem::ConductorTextItem(
|
||||
parent_conductor_(parent_conductor),
|
||||
moved_by_user_(false),
|
||||
rotate_by_user_(false)
|
||||
{}
|
||||
{
|
||||
ShownKinds::tag(this, ShownKinds::WireNumbers);
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "crossrefitem.h"
|
||||
#include "../shownkinds.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include "../qetproject.h"
|
||||
@@ -81,6 +82,7 @@ CrossRefItem::~CrossRefItem()
|
||||
*/
|
||||
void CrossRefItem::init()
|
||||
{
|
||||
ShownKinds::tag(this, ShownKinds::CrossReferences);
|
||||
if(!m_element->diagram())
|
||||
{
|
||||
qDebug() << "CrossRefItem constructor" << "element is not in a diagram";
|
||||
@@ -238,11 +240,13 @@ void CrossRefItem::updateProperties()
|
||||
if (m_properties != xrp)
|
||||
{
|
||||
m_properties = xrp;
|
||||
hide();
|
||||
//Through ShownKinds: stays hidden while View > Show hides
|
||||
//cross-references
|
||||
ShownKinds::setVisible(this, false);
|
||||
if(m_properties.snapTo() == XRefProperties::Label && (m_text || m_group)) //Snap to label and parent is text or group
|
||||
show();
|
||||
ShownKinds::setVisible(this, true);
|
||||
else if((m_properties.snapTo() == XRefProperties::Bottom && !m_text && !m_group)) //Snap to bottom of element is the parent
|
||||
show();
|
||||
ShownKinds::setVisible(this, true);
|
||||
|
||||
setUpConnection();
|
||||
updateLabel();
|
||||
@@ -528,7 +532,9 @@ void CrossRefItem::linkedChanged()
|
||||
|
||||
m_slave_connection.clear();
|
||||
|
||||
if(!isVisible())
|
||||
//Hidden only by View > Show: keep following the slaves, so the
|
||||
//label is right when it is shown again
|
||||
if(!isVisible() && !ShownKinds::isHidden(this))
|
||||
return;
|
||||
|
||||
for(Element *elmt : m_element->linkedElements())
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "diagramimageitem.h"
|
||||
#include "../shownkinds.h"
|
||||
|
||||
#include "../PropertiesEditor/propertieseditordialog.h"
|
||||
#include "../QPropertyUndoCommand/qpropertyundocommand.h"
|
||||
@@ -50,6 +51,7 @@
|
||||
DiagramImageItem::DiagramImageItem(QetGraphicsItem *parent_item):
|
||||
QetGraphicsItem(parent_item)
|
||||
{
|
||||
ShownKinds::tag(this, ShownKinds::Pictures);
|
||||
setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemSendsGeometryChanges);
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
@@ -66,6 +68,7 @@ DiagramImageItem::DiagramImageItem(const QPixmap &pixmap, QetGraphicsItem *paren
|
||||
m_base_pixmap(pixmap),
|
||||
m_crop_rect(pixmap.rect())
|
||||
{
|
||||
ShownKinds::tag(this, ShownKinds::Pictures);
|
||||
// m_transform.toMatrix(), not QGraphicsItem::setRotation()/setScale():
|
||||
// those are a single uniform scale() float, which is exactly why an
|
||||
// image could never break its own aspect ratio before this class
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "dynamicelementtextitem.h"
|
||||
#include "../shownkinds.h"
|
||||
#include "../qetproject.h"
|
||||
#include "../QPropertyUndoCommand/qpropertyundocommand.h"
|
||||
#include "../diagram.h"
|
||||
@@ -44,6 +45,7 @@ DynamicElementTextItem::DynamicElementTextItem(Element *parent_element) :
|
||||
m_parent_element(parent_element),
|
||||
m_uuid(QUuid::createUuid())
|
||||
{
|
||||
ShownKinds::tag(this, ShownKinds::SymbolTexts);
|
||||
setFont(QETApp::dynamicTextsItemFont());
|
||||
setText(tr("Texte"));
|
||||
setParentItem(parent_element);
|
||||
@@ -1662,6 +1664,7 @@ void DynamicElementTextItem::updateXref()
|
||||
if(!m_slave_Xref_item)
|
||||
{
|
||||
m_slave_Xref_item = new QGraphicsTextItem(xref_label, this);
|
||||
ShownKinds::tag(m_slave_Xref_item, ShownKinds::CrossReferences);
|
||||
m_slave_Xref_item->setFont(QETApp::diagramTextsFont(5));
|
||||
// Match the parent text's user-configurable color instead of
|
||||
// hardcoding black, which renders invisible under dark themes
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "elementtextitemgroup.h"
|
||||
#include "../shownkinds.h"
|
||||
#include "../qetproject.h"
|
||||
#include "../QPropertyUndoCommand/qpropertyundocommand.h"
|
||||
#include "../diagram.h"
|
||||
@@ -53,6 +54,7 @@ ElementTextItemGroup::ElementTextItemGroup(const QString &name,
|
||||
m_name(name),
|
||||
m_parent_element(parent)
|
||||
{
|
||||
ShownKinds::tag(this, ShownKinds::SymbolTexts);
|
||||
setFlags(QGraphicsItem::ItemIsSelectable
|
||||
| QGraphicsItem::ItemIsMovable);
|
||||
connect(parent,
|
||||
@@ -882,6 +884,7 @@ void ElementTextItemGroup::updateXref()
|
||||
if(!m_slave_Xref_item)
|
||||
{
|
||||
m_slave_Xref_item = new QGraphicsTextItem(xref_label, this);
|
||||
ShownKinds::tag(m_slave_Xref_item, ShownKinds::CrossReferences);
|
||||
m_slave_Xref_item->setFont(QETApp::diagramTextsFont(5));
|
||||
|
||||
m_update_slave_Xref_connection << connect(master_elmt, &Element::xChanged, this, &ElementTextItemGroup::updateXref);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "independenttextitem.h"
|
||||
#include "../shownkinds.h"
|
||||
|
||||
#include "../diagram.h"
|
||||
#include "../diagramcommands.h"
|
||||
@@ -34,6 +35,7 @@
|
||||
IndependentTextItem::IndependentTextItem() :
|
||||
DiagramTextItem(nullptr)
|
||||
{
|
||||
ShownKinds::tag(this, ShownKinds::FreeTexts);
|
||||
//Start from the font last applied to a text item this session,
|
||||
//falling back to the app-wide Preferences default otherwise.
|
||||
setFont(LastUsedStyle::hasTextFont() ? LastUsedStyle::textFont()
|
||||
@@ -49,7 +51,9 @@ IndependentTextItem::IndependentTextItem() :
|
||||
*/
|
||||
IndependentTextItem::IndependentTextItem(const QString &text) :
|
||||
DiagramTextItem(text, nullptr)
|
||||
{}
|
||||
{
|
||||
ShownKinds::tag(this, ShownKinds::FreeTexts);
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
IndependentTextItem::~IndependentTextItem()
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "qetshapeitem.h"
|
||||
#include "../shownkinds.h"
|
||||
|
||||
#include "../PropertiesEditor/propertieseditordialog.h"
|
||||
#include "../QPropertyUndoCommand/qpropertyundocommand.h"
|
||||
@@ -57,6 +58,7 @@ QetShapeItem::QetShapeItem(QPointF p1, QPointF p2, ShapeType type, QGraphicsItem
|
||||
m_P2 (p2),
|
||||
m_hovered(false)
|
||||
{
|
||||
ShownKinds::tag(this, ShownKinds::Shapes);
|
||||
if (type == Polygon) m_polygon << m_P1 << m_P2;
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);
|
||||
setAcceptHoverEvents(true);
|
||||
|
||||
@@ -4098,10 +4098,7 @@ bool QetScriptApi::setConductorDefault(int folioIndex, const QString &property,
|
||||
{
|
||||
const QList<Conductor *> conductor_list = diagram->conductors();
|
||||
for (Conductor *c : conductor_list)
|
||||
{
|
||||
const ConductorProperties cp = c->properties();
|
||||
c->textItem()->setVisible(cp.type == ConductorProperties::Multi && cp.m_show_text);
|
||||
}
|
||||
c->updateTextVisibility();
|
||||
for (Conductor *c : conductor_list)
|
||||
c->calculateTextItemPosition();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
Copyright 2006-2026 The QElectroTech Team
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
QElectroTech is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "shownkinds.h"
|
||||
|
||||
#include <QGraphicsItem>
|
||||
#include <QGraphicsScene>
|
||||
|
||||
namespace
|
||||
{
|
||||
bool hidden[ShownKinds::KindCount] = {};
|
||||
}
|
||||
|
||||
/**
|
||||
@return true unless @a kind was hidden with setShown().
|
||||
*/
|
||||
bool ShownKinds::isShown(Kind kind)
|
||||
{
|
||||
return kind < 0 || kind >= KindCount || !hidden[kind];
|
||||
}
|
||||
|
||||
/**
|
||||
Show or hide @a kind for the items created from now on. Items already
|
||||
on a scene change when apply() is called on it.
|
||||
*/
|
||||
void ShownKinds::setShown(Kind kind, bool shown)
|
||||
{
|
||||
if (kind >= 0 && kind < KindCount) {
|
||||
hidden[kind] = !shown;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@return how many kinds are hidden, for the status bar.
|
||||
*/
|
||||
int ShownKinds::hiddenCount()
|
||||
{
|
||||
int count = 0;
|
||||
for (bool h : hidden) {
|
||||
count += h ? 1 : 0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
Mark @a item as being of @a kind, and hide it now if that kind is
|
||||
hidden. Called by the item's constructor, while the item still wants to
|
||||
be visible.
|
||||
*/
|
||||
void ShownKinds::tag(QGraphicsItem *item, Kind kind)
|
||||
{
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
item->setData(data_key, int(kind));
|
||||
if (!isShown(kind)) {
|
||||
item->setVisible(false);
|
||||
item->setData(hidden_key, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Show or hide @a item as its own code wants, unless its kind is hidden:
|
||||
then it stays hidden, and comes back when the kind is shown again.
|
||||
Use this instead of QGraphicsItem::setVisible() in a tagged item.
|
||||
*/
|
||||
void ShownKinds::setVisible(QGraphicsItem *item, bool visible)
|
||||
{
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
const QVariant kind = item->data(data_key);
|
||||
const bool vetoed = visible && kind.isValid() && !isShown(Kind(kind.toInt()));
|
||||
item->setVisible(visible && !vetoed);
|
||||
item->setData(hidden_key, vetoed ? QVariant(true) : QVariant());
|
||||
}
|
||||
|
||||
/**
|
||||
@return true if @a item, or an item it hangs from, is of a hidden kind.
|
||||
For code that walks the items itself (DXF export) and must leave out
|
||||
what View > Show hides.
|
||||
*/
|
||||
bool ShownKinds::isHidden(const QGraphicsItem *item)
|
||||
{
|
||||
for (; item; item = item->parentItem())
|
||||
{
|
||||
const QVariant value = item->data(data_key);
|
||||
if (value.isValid() && !isShown(Kind(value.toInt()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
Bring the items of @a kind on @a scene in line with the current state:
|
||||
hide the ones that are visible, or show again the ones hidden for it.
|
||||
*/
|
||||
void ShownKinds::apply(QGraphicsScene *scene, Kind kind)
|
||||
{
|
||||
if (!scene) {
|
||||
return;
|
||||
}
|
||||
const bool shown = isShown(kind);
|
||||
//items() with no argument also returns the hidden items
|
||||
const QList<QGraphicsItem *> items = scene->items();
|
||||
for (QGraphicsItem *item : items)
|
||||
{
|
||||
const QVariant value = item->data(data_key);
|
||||
if (!value.isValid() || value.toInt() != kind) {
|
||||
continue;
|
||||
}
|
||||
if (!shown) {
|
||||
//Its own flag, not isVisible(): a symbol text under a
|
||||
//hidden group still wants to be visible
|
||||
if (item->isVisibleTo(item->parentItem())) {
|
||||
item->setVisible(false);
|
||||
item->setData(hidden_key, true);
|
||||
}
|
||||
} else if (item->data(hidden_key).toBool()) {
|
||||
item->setVisible(true);
|
||||
item->setData(hidden_key, QVariant());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
Copyright 2006-2026 The QElectroTech Team
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
QElectroTech is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef SHOWNKINDS_H
|
||||
#define SHOWNKINDS_H
|
||||
|
||||
class QGraphicsItem;
|
||||
class QGraphicsScene;
|
||||
|
||||
/**
|
||||
Show or hide whole kinds of folio items, View > Show (bugtracker #301):
|
||||
symbol texts, wire numbers, free texts and so on.
|
||||
|
||||
Each item says which kind it is with a tag set by its constructor, so an
|
||||
item created while its kind is hidden starts hidden, whichever way it was
|
||||
created (load, paste, a text added to a symbol, a new cross-reference).
|
||||
A tag and not type(): the cross-reference under a contact's label is a
|
||||
plain QGraphicsTextItem.
|
||||
|
||||
Some items also hide themselves (a wire number switched off, one text
|
||||
per potential, a cross-reference snapped elsewhere). They call
|
||||
setVisible() here instead of QGraphicsItem::setVisible(), and the kind
|
||||
state can only veto what they ask for: showing a kind again brings back
|
||||
only what was hidden for it, never what an item hid itself.
|
||||
|
||||
The state is for the whole application and is not saved: it is a way of
|
||||
looking at the folios, like the grid. Hidden items are left out of
|
||||
printing and exports, and Qt does not select them, so nothing hidden is
|
||||
copied, moved or deleted by accident.
|
||||
|
||||
This part knows nothing of Diagram, so it can be tested on a plain scene.
|
||||
*/
|
||||
namespace ShownKinds
|
||||
{
|
||||
enum Kind {
|
||||
SymbolTexts,
|
||||
WireNumbers,
|
||||
FreeTexts,
|
||||
Shapes,
|
||||
Pictures,
|
||||
Tables,
|
||||
CrossReferences,
|
||||
KindCount
|
||||
};
|
||||
|
||||
/// QGraphicsItem::data() key holding an item's kind.
|
||||
inline constexpr int data_key = 0x4b4e44; // "KND"
|
||||
/// QGraphicsItem::data() key set while an item that wants to be
|
||||
/// visible is hidden only because its kind is hidden.
|
||||
inline constexpr int hidden_key = 0x4b4e48; // "KNH"
|
||||
|
||||
bool isShown(Kind kind);
|
||||
void setShown(Kind kind, bool shown);
|
||||
int hiddenCount();
|
||||
|
||||
void tag(QGraphicsItem *item, Kind kind);
|
||||
void setVisible(QGraphicsItem *item, bool visible);
|
||||
bool isHidden(const QGraphicsItem *item);
|
||||
void apply(QGraphicsScene *scene, Kind kind);
|
||||
}
|
||||
|
||||
#endif // SHOWNKINDS_H
|
||||
@@ -124,10 +124,7 @@ DiagramPropertiesDialog::DiagramPropertiesDialog(Diagram *diagram, QWidget *pare
|
||||
{
|
||||
const QList<Conductor *> conductor_list = diagram -> conductors();
|
||||
for (Conductor *c : conductor_list)
|
||||
{
|
||||
const ConductorProperties cp = c -> properties();
|
||||
c -> textItem() -> setVisible(cp.type == ConductorProperties::Multi && cp.m_show_text);
|
||||
}
|
||||
c -> updateTextVisibility();
|
||||
for (Conductor *c : conductor_list)
|
||||
c -> calculateTextItemPosition();
|
||||
}
|
||||
|
||||
@@ -139,6 +139,14 @@ add_test(NAME tst_itemgroups COMMAND tst_itemgroups)
|
||||
target_include_directories(tst_itemgroups PRIVATE ${QET_DIR}/sources)
|
||||
target_link_libraries(tst_itemgroups PRIVATE Qt::Test Qt::Widgets Qt::Xml)
|
||||
|
||||
# shownkinds.cpp keeps View > Show (bugtracker #301) apart from the item
|
||||
# classes, so it is tested here on a plain scene of rectangles.
|
||||
add_executable(tst_shownkinds tst_shownkinds.cpp ${QET_DIR}/sources/shownkinds.cpp)
|
||||
add_test(NAME tst_shownkinds COMMAND tst_shownkinds)
|
||||
set_tests_properties(tst_shownkinds PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=offscreen")
|
||||
target_include_directories(tst_shownkinds PRIVATE ${QET_DIR}/sources)
|
||||
target_link_libraries(tst_shownkinds PRIVATE Qt::Test Qt::Widgets)
|
||||
|
||||
# textanchor.h is header-only: the point of a text chosen by its alignment,
|
||||
# shown as Position X/Y in the text properties (#1155).
|
||||
add_executable(tst_textanchor tst_textanchor.cpp)
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
#include <QtTest>
|
||||
#include <QGraphicsRectItem>
|
||||
#include <QGraphicsScene>
|
||||
|
||||
#include "shownkinds.h"
|
||||
|
||||
class tst_shownkinds : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QGraphicsScene *scene = nullptr;
|
||||
|
||||
QGraphicsRectItem *add(QGraphicsItem *parent = nullptr)
|
||||
{
|
||||
auto item = new QGraphicsRectItem(0, 0, 10, 10, parent);
|
||||
item->setFlag(QGraphicsItem::ItemIsSelectable);
|
||||
if (!parent) {
|
||||
scene->addItem(item);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void init()
|
||||
{
|
||||
scene = new QGraphicsScene;
|
||||
for (int k = 0; k < ShownKinds::KindCount; ++k) {
|
||||
ShownKinds::setShown(ShownKinds::Kind(k), true);
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
delete scene;
|
||||
scene = nullptr;
|
||||
}
|
||||
|
||||
void hideAndShowAgain()
|
||||
{
|
||||
auto shape = add();
|
||||
auto text = add();
|
||||
ShownKinds::tag(shape, ShownKinds::Shapes);
|
||||
ShownKinds::tag(text, ShownKinds::FreeTexts);
|
||||
|
||||
ShownKinds::setShown(ShownKinds::Shapes, false);
|
||||
ShownKinds::apply(scene, ShownKinds::Shapes);
|
||||
QVERIFY(!shape->isVisible());
|
||||
QVERIFY(text->isVisible());
|
||||
QCOMPARE(ShownKinds::hiddenCount(), 1);
|
||||
|
||||
ShownKinds::setShown(ShownKinds::Shapes, true);
|
||||
ShownKinds::apply(scene, ShownKinds::Shapes);
|
||||
QVERIFY(shape->isVisible());
|
||||
QCOMPARE(ShownKinds::hiddenCount(), 0);
|
||||
}
|
||||
|
||||
// Created while its kind is hidden: starts hidden, whatever created it.
|
||||
void createdWhileHidden()
|
||||
{
|
||||
ShownKinds::setShown(ShownKinds::Pictures, false);
|
||||
auto picture = add();
|
||||
ShownKinds::tag(picture, ShownKinds::Pictures);
|
||||
QVERIFY(!picture->isVisible());
|
||||
}
|
||||
|
||||
// Untagged items (symbols, wires) are never touched.
|
||||
void untaggedUntouched()
|
||||
{
|
||||
auto symbol = add();
|
||||
auto hidden_symbol = add();
|
||||
hidden_symbol->setVisible(false);
|
||||
for (int k = 0; k < ShownKinds::KindCount; ++k) {
|
||||
ShownKinds::setShown(ShownKinds::Kind(k), false);
|
||||
ShownKinds::apply(scene, ShownKinds::Kind(k));
|
||||
}
|
||||
QVERIFY(symbol->isVisible());
|
||||
for (int k = 0; k < ShownKinds::KindCount; ++k) {
|
||||
ShownKinds::setShown(ShownKinds::Kind(k), true);
|
||||
ShownKinds::apply(scene, ShownKinds::Kind(k));
|
||||
}
|
||||
QVERIFY(!hidden_symbol->isVisible());
|
||||
}
|
||||
|
||||
// apply() touches only the kind it is given.
|
||||
void applyOnlyThatKind()
|
||||
{
|
||||
auto shape = add();
|
||||
ShownKinds::tag(shape, ShownKinds::Shapes);
|
||||
ShownKinds::setShown(ShownKinds::Shapes, false);
|
||||
ShownKinds::apply(scene, ShownKinds::Tables);
|
||||
QVERIFY(shape->isVisible());
|
||||
}
|
||||
|
||||
// An item that hid itself (a wire number switched off) stays hidden
|
||||
// when its kind is hidden and shown again.
|
||||
void ownHiddenStaysHidden()
|
||||
{
|
||||
auto number = add();
|
||||
ShownKinds::tag(number, ShownKinds::WireNumbers);
|
||||
ShownKinds::setVisible(number, false);
|
||||
ShownKinds::setShown(ShownKinds::WireNumbers, false);
|
||||
ShownKinds::apply(scene, ShownKinds::WireNumbers);
|
||||
ShownKinds::setShown(ShownKinds::WireNumbers, true);
|
||||
ShownKinds::apply(scene, ShownKinds::WireNumbers);
|
||||
QVERIFY(!number->isVisible());
|
||||
}
|
||||
|
||||
// An item asking to be shown while its kind is hidden stays hidden,
|
||||
// and appears when the kind is shown (one text per potential moving
|
||||
// to another wire, a cross-reference changing its snap).
|
||||
void showVetoedThenRestored()
|
||||
{
|
||||
auto number = add();
|
||||
ShownKinds::tag(number, ShownKinds::WireNumbers);
|
||||
ShownKinds::setShown(ShownKinds::WireNumbers, false);
|
||||
ShownKinds::apply(scene, ShownKinds::WireNumbers);
|
||||
ShownKinds::setVisible(number, true);
|
||||
QVERIFY(!number->isVisible());
|
||||
ShownKinds::setShown(ShownKinds::WireNumbers, true);
|
||||
ShownKinds::apply(scene, ShownKinds::WireNumbers);
|
||||
QVERIFY(number->isVisible());
|
||||
}
|
||||
|
||||
// Hidden while its kind is hidden: not shown again with the kind.
|
||||
void hiddenWhileKindHidden()
|
||||
{
|
||||
auto number = add();
|
||||
ShownKinds::tag(number, ShownKinds::WireNumbers);
|
||||
ShownKinds::setShown(ShownKinds::WireNumbers, false);
|
||||
ShownKinds::apply(scene, ShownKinds::WireNumbers);
|
||||
ShownKinds::setVisible(number, false);
|
||||
ShownKinds::setShown(ShownKinds::WireNumbers, true);
|
||||
ShownKinds::apply(scene, ShownKinds::WireNumbers);
|
||||
QVERIFY(!number->isVisible());
|
||||
}
|
||||
|
||||
// A text under a hidden parent still counts as wanting to be visible.
|
||||
void childOfHiddenParent()
|
||||
{
|
||||
auto group = add();
|
||||
auto text = add(group);
|
||||
ShownKinds::tag(group, ShownKinds::SymbolTexts);
|
||||
ShownKinds::tag(text, ShownKinds::CrossReferences);
|
||||
ShownKinds::setShown(ShownKinds::SymbolTexts, false);
|
||||
ShownKinds::apply(scene, ShownKinds::SymbolTexts);
|
||||
ShownKinds::setShown(ShownKinds::CrossReferences, false);
|
||||
ShownKinds::apply(scene, ShownKinds::CrossReferences);
|
||||
ShownKinds::setShown(ShownKinds::SymbolTexts, true);
|
||||
ShownKinds::apply(scene, ShownKinds::SymbolTexts);
|
||||
QVERIFY(!text->isVisible());
|
||||
ShownKinds::setShown(ShownKinds::CrossReferences, true);
|
||||
ShownKinds::apply(scene, ShownKinds::CrossReferences);
|
||||
QVERIFY(text->isVisible());
|
||||
}
|
||||
|
||||
// isHidden() follows the parents: a cross-reference under a symbol text.
|
||||
void hiddenThroughParent()
|
||||
{
|
||||
auto symbol = add();
|
||||
auto label = add(symbol);
|
||||
auto xref = add(label);
|
||||
ShownKinds::tag(label, ShownKinds::SymbolTexts);
|
||||
ShownKinds::tag(xref, ShownKinds::CrossReferences);
|
||||
QVERIFY(!ShownKinds::isHidden(xref));
|
||||
|
||||
ShownKinds::setShown(ShownKinds::SymbolTexts, false);
|
||||
QVERIFY(ShownKinds::isHidden(xref));
|
||||
QVERIFY(!ShownKinds::isHidden(symbol));
|
||||
}
|
||||
|
||||
// Hidden means safe from Select All, copy and delete: Qt will not
|
||||
// select it, and drops a selection it had.
|
||||
void hiddenIsNotSelectable()
|
||||
{
|
||||
auto text = add();
|
||||
ShownKinds::tag(text, ShownKinds::FreeTexts);
|
||||
text->setSelected(true);
|
||||
ShownKinds::setShown(ShownKinds::FreeTexts, false);
|
||||
ShownKinds::apply(scene, ShownKinds::FreeTexts);
|
||||
QVERIFY(!text->isSelected());
|
||||
text->setSelected(true);
|
||||
QVERIFY(scene->selectedItems().isEmpty());
|
||||
QVERIFY(scene->items(QRectF(-5, -5, 20, 20)).isEmpty());
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_MAIN(tst_shownkinds)
|
||||
#include "tst_shownkinds.moc"
|
||||
Reference in New Issue
Block a user