Commit 8ab58be5 authored by Dmitry Kazakov's avatar Dmitry Kazakov
Browse files

Fix crash on moving shape layers

Now we use Qt::AutoConnection signal/slot connection to synchronize
UI and Image threads.

Above that, we do not move the paint device, because 1) we update the
shape anyway and 2) it causes concurrent access to the moving device
that causes a crash.

BUG:289746
parent e78752f3
......@@ -107,10 +107,14 @@ private:
struct KisShapeLayer::Private
{
public:
Private() : x(0), y(0) {}
KoViewConverter * converter;
KisPaintDeviceSP paintDevice;
KisShapeLayerCanvas * canvas;
KoShapeBasedDocumentBase* controller;
int x;
int y;
};
......@@ -177,6 +181,8 @@ void KisShapeLayer::initShapeLayer(KoShapeBasedDocumentBase* controller)
connect(m_d->canvas->shapeManager()->selection(), SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged()));
connect(m_d->canvas->shapeManager()->selection(), SIGNAL(currentLayerChanged(const KoShapeLayer*)), this, SIGNAL(currentLayerChanged(const KoShapeLayer*)));
connect(this, SIGNAL(sigMoveShapes(const QPointF&)), SLOT(slotMoveShapes(const QPointF&)));
}
bool KisShapeLayer::allowAsChild(KisNodeSP node) const
......@@ -201,32 +207,47 @@ KisPaintDeviceSP KisShapeLayer::paintDevice() const
qint32 KisShapeLayer::x() const
{
return m_d->paintDevice->x();
return m_d->x;
}
qint32 KisShapeLayer::y() const
{
return m_d->paintDevice->y();
return m_d->y;
}
void KisShapeLayer::setX(qint32 x)
{
qint32 delta = x - this->x();
m_d->paintDevice->setX(x);
foreach (KoShape* shape, shapeManager()->shapes()) {
QPointF pos = shape->position();
shape->setPosition(QPointF(pos.x() + m_d->converter->viewToDocumentX(delta), pos.y()));
}
QPointF diff = QPointF(m_d->converter->viewToDocumentX(delta), 0);
emit sigMoveShapes(diff);
// Save new value to satisfy LSP
m_d->x = x;
}
void KisShapeLayer::setY(qint32 y)
{
qint32 delta = y - this->y();
m_d->paintDevice->setY(y);
QPointF diff = QPointF(0, m_d->converter->viewToDocumentY(delta));
emit sigMoveShapes(diff);
// Save new value to satisfy LSP
m_d->y = y;
}
void KisShapeLayer::slotMoveShapes(const QPointF &diff)
{
QList<QPointF> prevPos;
QList<QPointF> newPos;
foreach (KoShape* shape, shapeManager()->shapes()) {
QPointF pos = shape->position();
shape->setPosition(QPointF(pos.x(), pos.y() + m_d->converter->viewToDocumentY(delta)));
prevPos << pos;
newPos << pos + diff;
}
KoShapeMoveCommand cmd(shapeManager()->shapes(), prevPos, newPos);
cmd.redo();
}
bool KisShapeLayer::accept(KisNodeVisitor& visitor)
......
......@@ -117,6 +117,17 @@ signals:
void selectionChanged();
void currentLayerChanged(const KoShapeLayer *layer);
signals:
/**
* A signal + slot to synchronize UI and image
* threads. Image thread emits the signal, UI
* thread performes the action
*/
void sigMoveShapes(const QPointF &diff);
private slots:
void slotMoveShapes(const QPointF &diff);
private:
struct Private;
Private * const m_d;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment