Files
qelectrotech-source-mirror/sources/qetgraphicsitem/qetgraphicsitem.cpp
T
ispyisail 2dbaa69186 Fix a group splitting apart when one of its items is locked (#1146)
Grouping two symbols and then locking one of them (Lock position in its
properties) left the group in a broken state: dragging the unlocked symbol
pulled it away while the locked one stayed, and dragging the locked one
did nothing. The move simply dropped locked items, so the rest of the
group went without them.

A group with a locked member now does not move at all, whichever member
is dragged, and the status bar says why. This is the rule the item-groups
proposal (discussion #1070) set out for this case. The same rule applies
to the arrow keys and to the Align commands, which share
DiagramContent::removeNonMovableItems().

Also fixed on the way, for a plain selection with a locked symbol: a wire
between the locked symbol and one being dragged kept its user-placed text
moving with the dragged end. Such a wire is now redrawn only, as a wire to
an unselected symbol already is.

Checked in the GUI on two symbols joined by a wire (grafcet example),
master against this branch, positions read from the saved file:
- drag the unlocked member: master moves it 190 px, this branch moves
  nothing and shows the message
- arrow keys on the selected group (3 runs each): master moves the
  unlocked member, this branch nothing
- the same two symbols ungrouped: both move the unlocked one, as before
- user-placed wire text: master shifts it 190 px, this branch keeps it
ctest: 34/34.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:23:32 +13:00

209 lines
4.8 KiB
C++

/*
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 "qetgraphicsitem.h"
#include "../diagram.h"
/**
@brief QetGraphicsItem::QetGraphicsItem
Default constructor
@param parent : Parent Item
*/
void QetGraphicsItem::showItem(QetGraphicsItem *item)
{
if (item && item->diagram())
{
item->diagram()->showMe();
item->setSelected(true);
//Zoom to the item
for(QGraphicsView *view : item->scene()->views())
{
QRectF fit = item->sceneBoundingRect();
fit.adjust(-200, -200, 200, 200);
view->fitInView(fit, Qt::KeepAspectRatioByExpanding);
}
}
}
QetGraphicsItem::QetGraphicsItem(QGraphicsItem *parent):
QGraphicsObject(parent),
is_movable_(true),
m_first_move(true),
snap_to_grid_(true)
{
setAcceptHoverEvents(true);
}
QetGraphicsItem::~QetGraphicsItem()
{}
/**
@brief QetGraphicsItem::diagram
*return the diagram of this item
*/
Diagram* QetGraphicsItem::diagram() const{
return(qobject_cast<Diagram *>(scene()));
}
/**
@brief QetGraphicsItem::setPos
*set the position of the item to p
@param p the new position of item
*/
void QetGraphicsItem::setPos(const QPointF &p) {
QPointF pp = Diagram::snapToGrid(p);
if (pp == pos() || !is_movable_)
return;
QGraphicsItem::setPos(pp);
}
/**
@brief QetGraphicsItem::setPos
*set the position of the item
@param x new abscisse of item
@param y new ordonne of item
*/
void QetGraphicsItem::setPos(qreal x, qreal y) {
setPos(QPointF(x, y));
}
bool QetGraphicsItem::isHovered() const {
return m_hovered;
}
QPointF QetGraphicsItem::hoverMousePos() const
{
return m_mouse_hover_pos;
}
/**
@brief QetGraphicsItem::state
@return the current state of this item
*/
QET::GraphicsItemState QetGraphicsItem::state() const
{
return m_state;
}
/**
@brief QetGraphicsItem::mousePressEvent
*handle the mouse click
@param event
*/
void QetGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
m_first_move = true;
if (event->modifiers() & Qt::ControlModifier) {
setSelected(!isSelected());
}
}
QGraphicsItem::mousePressEvent(event);
}
/**
@brief QetGraphicsItem::mouseDoubleClickEvent
*handle the mouse double click
@param event
*/
void QetGraphicsItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
editProperty();
event->accept();
}
/**
@brief QetGraphicsItem::mouseMoveEvent
*handle mouse movement
@param event
*/
void QetGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (isSelected() && event->buttons() & Qt::LeftButton)
{
//Item is moving
if(diagram() && m_first_move) {
//It's the first movement, we signal it to parent diagram
diagram()->elementsMover().beginMovement(diagram(), this);
}
if (diagram() && diagram()->elementsMover().holds(this)) {
m_first_move = false;
event->accept();
return;
}
//we apply the mouse movement
QPointF old_pos = pos();
if (m_first_move) {
m_mouse_to_origin_movement = old_pos - event -> buttonDownScenePos(Qt::LeftButton);
}
QPointF expected_pos = event->scenePos() + m_mouse_to_origin_movement;
setPos(expected_pos); // setPos() will snap the expected position to the grid
//we calculate the real movement applied by setPos()
QPointF effective_movement = pos() - old_pos;
if (diagram()) {
//we signal the real movement apply to diagram,
//who he apply to other selected item
diagram()->elementsMover().continueMovement(effective_movement);
}
event->accept();
}
else {
event->ignore();
}
if (m_first_move) {
m_first_move = false;
}
}
/**
@brief QetGraphicsItem::mouseReleaseEvent
handle mouse release click
@param event
*/
void QetGraphicsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (diagram()) {
diagram()->elementsMover().endMovement();
event->accept();
}
}
void QetGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
m_hovered = true;
QGraphicsObject::hoverEnterEvent(event);
}
void QetGraphicsItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
QGraphicsObject::hoverMoveEvent(event);
m_mouse_hover_pos = event->pos();
}
void QetGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
m_hovered = false;
QGraphicsObject::hoverLeaveEvent(event);
}