Commit eb611609 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Fix a crash when creating a text shape

Every KoShapeController used to reset the global "shape document" in its
KoDocumentResourceManager. The problem is that in Krita we have multiple
KoShapeController-s, but the resource manager is the only one. It means
that every shape selection or shape layer used to reset the pointer to
the global "shape document" to its own one. The only reason why we didn't
have too many crashes is that almost noone uses this "shape document".

Ideally we should:
1) Remove KoDocumentResourceManager::GlobalShapeController resource. This
   resource is not global to the document, but is created per-layer. The only
   user of it atm is the legacy text tool, which should be deprecated.

2) Remove KoDocumentResourceManager at all. There is no much use of it
   anymore. Its main user is legacy text tool.

BUG:407554
parent 3dfad538
......@@ -186,16 +186,29 @@ void KoDocumentResourceManager::setOdfDocument(KoDocumentBase *currentDocument)
setResource(OdfDocument, variant);
}
KoShapeController *KoDocumentResourceManager::shapeController() const
qreal KoDocumentResourceManager::documentResolution() const
{
if (!hasResource(ShapeController))
KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(hasResource(DocumentResolution), 72.0);
return resource(DocumentResolution).toReal();
}
QRectF KoDocumentResourceManager::documentRectInPixels() const
{
KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(hasResource(DocumentRectInPixels), QRectF(0,0, 777, 666));
return resource(DocumentRectInPixels).toRectF();
}
KoShapeController *KoDocumentResourceManager::globalShapeController() const
{
if (!hasResource(GlobalShapeController))
return 0;
return resource(ShapeController).value<KoShapeController *>();
return resource(GlobalShapeController).value<KoShapeController *>();
}
void KoDocumentResourceManager::setShapeController(KoShapeController *shapeController)
void KoDocumentResourceManager::setGlobalShapeController(KoShapeController *shapeController)
{
QVariant variant;
variant.setValue<KoShapeController *>(shapeController);
setResource(ShapeController, variant);
setResource(GlobalShapeController, variant);
}
......@@ -76,7 +76,9 @@ enum DocumentResource {
HandleRadius, ///< The handle radius used for drawing handles of any kind
GrabSensitivity, ///< The grab sensitivity used for grabbing handles of any kind
MarkerCollection, ///< The collection holding all markers
ShapeController, ///< The KoShapeController for the document
GlobalShapeController, ///< The KoShapeController for the document
DocumentResolution, ///< Pixels-per-inch resoluton of the document
DocumentRectInPixels, ///< Bounds of the document in pixels
KarbonStart = 1000, ///< Base number for Karbon specific values.
KexiStart = 2000, ///< Base number for Kexi specific values.
......@@ -229,8 +231,16 @@ enum DocumentResource {
KoDocumentBase *odfDocument() const;
void setOdfDocument(KoDocumentBase *currentDocument);
KoShapeController *shapeController() const;
void setShapeController(KoShapeController *shapeController);
qreal documentResolution() const;
QRectF documentRectInPixels() const;
/**
* TODO: remove these methods after legacy ODF text shape is removed.
* New code must use documentResolution() and documentRectInPixels()
* instead.
*/
Q_DECL_DEPRECATED KoShapeController *globalShapeController() const;
Q_DECL_DEPRECATED void setGlobalShapeController(KoShapeController *globalShapeController);
Q_SIGNALS:
/**
......
......@@ -128,9 +128,6 @@ KoShapeController::KoShapeController(KoCanvasBase *canvas, KoShapeControllerBase
{
d->canvas = canvas;
d->shapeController = shapeController;
if (shapeController) {
shapeController->resourceManager()->setShapeController(this);
}
}
KoShapeController::~KoShapeController()
......
......@@ -401,7 +401,7 @@ KoShape * KoShapeRegistry::createShapeFromOdf(const KoXmlElement & e, KoShapeLoa
const bool parsed = xmlDoc.setContent(file->contents, &errormessage, &line, &col);
if (!parsed) continue;
const QRectF bounds = context.documentResourceManager()->shapeController()->documentRectInPixels();
const QRectF bounds = context.documentResourceManager()->documentRectInPixels();
// WARNING: Krita 3.x expects all the embedded objects to
// be loaded in default resolution of 72.0 ppi.
......
......@@ -194,7 +194,7 @@ void TestKoShapeRegistry::testFramedSvgShapes()
QScopedPointer<MockCanvas> canvas(new MockCanvas(document.data()));
QScopedPointer<KoShapeController> shapeController(new KoShapeController(canvas.data(), document.data()));
resourceManager->setShapeController(shapeController.data());
resourceManager->setGlobalShapeController(shapeController.data());
KoOdfLoadingContext odfContext(stylesReader, store.data());
......
......@@ -596,7 +596,7 @@ KoShape *KoSvgTextShapeFactory::createDefaultShape(KoDocumentResourceManager *do
converter.convertFromSvg("<text>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</text>",
"<defs/>",
QRectF(0, 0, 200, 60),
documentResources->shapeController()->pixelsPerInch());
documentResources->documentResolution());
debugFlake << converter.errors() << converter.warnings();
......@@ -617,13 +617,11 @@ KoShape *KoSvgTextShapeFactory::createShape(const KoProperties *params, KoDocume
shapeRect = rect.toRectF();
}
KoShapeController *controller = documentResources->shapeController();
KoSvgTextShapeMarkupConverter converter(shape);
converter.convertFromSvg(svgText,
defs,
shapeRect,
controller ? controller->pixelsPerInch() : 72);
documentResources->documentResolution());
shape->setPosition(shapeRect.topLeft());
......
......@@ -47,6 +47,7 @@
#include <KoStoreDevice.h>
#include <KoDialog.h>
#include <KisImportExportErrorCode.h>
#include <KoDocumentResourceManager.h>
#include <KisUsageLogger.h>
#include <klocalizedstring.h>
......@@ -427,10 +428,11 @@ KisDocument::KisDocument()
// preload the krita resources
KisResourceServerProvider::instance();
d->shapeController = new KisShapeController(this, d->nserver),
d->koShapeController = new KoShapeController(0, d->shapeController),
d->shapeController = new KisShapeController(this, d->nserver);
d->koShapeController = new KoShapeController(0, d->shapeController);
d->shapeController->resourceManager()->setGlobalShapeController(d->koShapeController);
slotConfigChanged();
slotConfigChanged();
}
KisDocument::KisDocument(const KisDocument &rhs)
......@@ -442,10 +444,11 @@ KisDocument::KisDocument(const KisDocument &rhs)
connect(d->autoSaveTimer, SIGNAL(timeout()), this, SLOT(slotAutoSave()));
setObjectName(rhs.objectName());
d->shapeController = new KisShapeController(this, d->nserver),
d->koShapeController = new KoShapeController(0, d->shapeController),
d->shapeController = new KisShapeController(this, d->nserver);
d->koShapeController = new KoShapeController(0, d->shapeController);
d->shapeController->resourceManager()->setGlobalShapeController(d->koShapeController);
slotConfigChanged();
slotConfigChanged();
// clone the image with keeping the GUIDs of the layers intact
// NOTE: we expect the image to be locked!
......
......@@ -42,7 +42,7 @@ public:
KisDummiesFacadeBase(QObject *parent = 0);
~KisDummiesFacadeBase() override;
void setImage(KisImageWSP image);
virtual void setImage(KisImageWSP image);
virtual bool hasDummyForNode(KisNodeSP node) const = 0;
virtual KisNodeDummy* dummyForNode(KisNodeSP node) const = 0;
......
......@@ -56,6 +56,7 @@
#include <commands/kis_image_layer_add_command.h>
#include <kis_undo_adapter.h>
#include "KoSelectedShapesProxy.h"
#include "kis_signal_auto_connection.h"
struct KisShapeController::Private
......@@ -63,6 +64,7 @@ struct KisShapeController::Private
public:
KisDocument *doc;
KisNameServer *nameServer;
KisSignalAutoConnectionsStore imageConnections;
KisNodeShapesGraph shapesGraph;
};
......@@ -87,6 +89,17 @@ KisShapeController::~KisShapeController()
delete m_d;
}
void KisShapeController::slotUpdateDocumentResolution()
{
const qreal pixelsPerInch = m_d->doc->image()->xRes() * 72.0;
resourceManager()->setResource(KoDocumentResourceManager::DocumentResolution, pixelsPerInch);
}
void KisShapeController::slotUpdateDocumentSize()
{
resourceManager()->setResource(KoDocumentResourceManager::DocumentRectInPixels, m_d->doc->image()->bounds());
}
void KisShapeController::addNodeImpl(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis)
{
KisNodeShape *newShape =
......@@ -251,6 +264,19 @@ void KisShapeController::setInitialShapeForCanvas(KisCanvas2 *canvas)
}
}
void KisShapeController::setImage(KisImageWSP image)
{
m_d->imageConnections.clear();
m_d->imageConnections.addConnection(m_d->doc->image(), SIGNAL(sigResolutionChanged(double, double)), this, SLOT(slotUpdateDocumentResolution()));
m_d->imageConnections.addConnection(m_d->doc->image(), SIGNAL(sigSizeChanged(QPointF, QPointF)), this, SLOT(slotUpdateDocumentSize()));
slotUpdateDocumentResolution();
slotUpdateDocumentSize();
KisDummiesFacadeBase::setImage(image);
}
KoShapeLayer* KisShapeController::shapeForNode(KisNodeSP node) const
{
if (node) {
......
......@@ -54,11 +54,17 @@ public:
KoShapeLayer* shapeForNode(KisNodeSP layer) const;
void setInitialShapeForCanvas(KisCanvas2 *canvas);
void setImage(KisImageWSP image) override;
private:
void addNodeImpl(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis) override;
void removeNodeImpl(KisNodeSP node) override;
private Q_SLOTS:
void slotUpdateDocumentResolution();
void slotUpdateDocumentSize();
Q_SIGNALS:
/**
* These three signals are forwarded from the local shape manager of
......
......@@ -105,7 +105,7 @@ KoShape *TextShapeFactory::createDefaultShape(KoDocumentResourceManager *documen
document.setChangeTracker(changeTracker);
}
document.setShapeController(documentResources->shapeController());
document.setShapeController(documentResources->globalShapeController());
//update the resources of the document
text->updateDocumentData();
......
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