mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-05-27 00:49:58 +02:00
crossrefitem: fix SIGSEGV when dropping power NC contact on diagram
Three bugs were causing a crash (SIGSEGV in QRegion::begin) when a power NC slave element was placed on a folio, even before linking it to a master element. 1. m_drawing (QPicture) was never reset between updateLabel() calls. QPicture accumulates paint commands — calling qp.begin() on an existing QPicture appends to it rather than replacing its content. After several updates (load, move, hover...) the picture became corrupted and crashed on play(). Fix: reset m_drawing = QPicture() at the start of updateLabel(). 2. m_drawed_contacts was only initialized to 0 in drawAsContacts(), but not in drawAsCross(). When drawing in Cross mode, fillCrossRef() called drawContact() with an uninitialized m_drawed_contacts value, producing a garbage offset. The NC contact symbol uses drawPolyline() with a sub-pixel Y coordinate (offset+2.5); with a random offset Qt generated an invalid QRegion and crashed. This explains why NC contacts crashed but NO contacts did not: the NO symbol only uses drawLine() which is more tolerant of bad coords. Fix: add m_drawed_contacts = 0 at the start of drawAsCross(). 3. setUpCrossBoundingRect() used QRectF() (null rect) as the reference rect for painter.boundingRect(), which can return invalid dimensions. Additionally, height was accumulated incorrectly: united() + setHeight() doubled the height at each iteration, causing an exponentially growing bounding rect with multiple contacts. Fix: use QRectF(0, 0, 500, 20) as reference rect and accumulate height and width independently.
This commit is contained in:
@@ -222,6 +222,9 @@ void CrossRefItem::updateLabel()
|
|||||||
prepareGeometryChange();
|
prepareGeometryChange();
|
||||||
m_bounding_rect = QRectF();
|
m_bounding_rect = QRectF();
|
||||||
|
|
||||||
|
//Reset QPicture so it doesn't accumulate commands across updates
|
||||||
|
m_drawing = QPicture();
|
||||||
|
|
||||||
//init the painter
|
//init the painter
|
||||||
QPainter qp;
|
QPainter qp;
|
||||||
qp.begin(&m_drawing);
|
qp.begin(&m_drawing);
|
||||||
@@ -585,9 +588,10 @@ void CrossRefItem::setUpCrossBoundingRect(QPainter &painter)
|
|||||||
QRectF no_bounding;
|
QRectF no_bounding;
|
||||||
for (auto str : no_str)
|
for (auto str : no_str)
|
||||||
{
|
{
|
||||||
QRectF bounding = painter.boundingRect(QRectF (), Qt::AlignCenter, str);
|
QRectF bounding = painter.boundingRect(QRectF(0, 0, 500, 20), Qt::AlignLeft, str);
|
||||||
no_bounding = no_bounding.united(bounding);
|
|
||||||
no_bounding.setHeight(no_bounding.height() + bounding.height());
|
no_bounding.setHeight(no_bounding.height() + bounding.height());
|
||||||
|
if (bounding.width() > no_bounding.width())
|
||||||
|
no_bounding.setWidth(bounding.width());
|
||||||
}
|
}
|
||||||
//Adjust according to the NO
|
//Adjust according to the NO
|
||||||
if (no_bounding.height() > default_bounding.height() - header)
|
if (no_bounding.height() > default_bounding.height() - header)
|
||||||
@@ -599,9 +603,10 @@ void CrossRefItem::setUpCrossBoundingRect(QPainter &painter)
|
|||||||
QRectF nc_bounding;
|
QRectF nc_bounding;
|
||||||
for (auto str : nc_str)
|
for (auto str : nc_str)
|
||||||
{
|
{
|
||||||
QRectF bounding = painter.boundingRect(QRectF (), Qt::AlignCenter, str);
|
QRectF bounding = painter.boundingRect(QRectF(0, 0, 500, 20), Qt::AlignLeft, str);
|
||||||
nc_bounding = nc_bounding.united(bounding);
|
|
||||||
nc_bounding.setHeight(nc_bounding.height() + bounding.height());
|
nc_bounding.setHeight(nc_bounding.height() + bounding.height());
|
||||||
|
if (bounding.width() > nc_bounding.width())
|
||||||
|
nc_bounding.setWidth(bounding.width());
|
||||||
}
|
}
|
||||||
//Adjust according to the NC
|
//Adjust according to the NC
|
||||||
if (nc_bounding.height() > default_bounding.height() - header)
|
if (nc_bounding.height() > default_bounding.height() - header)
|
||||||
@@ -625,6 +630,7 @@ void CrossRefItem::drawAsCross(QPainter &painter)
|
|||||||
{
|
{
|
||||||
//calculate the size of the cross
|
//calculate the size of the cross
|
||||||
setUpCrossBoundingRect(painter);
|
setUpCrossBoundingRect(painter);
|
||||||
|
m_drawed_contacts = 0;
|
||||||
m_hovered_contacts_map.clear();
|
m_hovered_contacts_map.clear();
|
||||||
|
|
||||||
//Bounding rect is empty that mean there's no contact to draw
|
//Bounding rect is empty that mean there's no contact to draw
|
||||||
|
|||||||
Reference in New Issue
Block a user