Commit 320c18b4 authored by Thomas Zander's avatar Thomas Zander

Introduce ref-counting to the borders.

This fixes the long open problem that we lost memory whenever we used borders. Especially since
it is possible to share a border with many shapes.
This fixes all those issues, while still allowing a border to be shared between multiple shapes.

svn path=/trunk/koffice/; revision=691271
parent 28423b6c
...@@ -14,6 +14,7 @@ set(flake_SRCS ...@@ -14,6 +14,7 @@ set(flake_SRCS
KoCanvasResourceProvider.cpp KoCanvasResourceProvider.cpp
KoInteractionStrategy.cpp KoInteractionStrategy.cpp
KoInteractionTool.cpp KoInteractionTool.cpp
KoShapeBorderModel.cpp
KoLineBorder.cpp KoLineBorder.cpp
KoPathShape.cpp KoPathShape.cpp
KoPathPoint.cpp KoPathPoint.cpp
......
...@@ -78,6 +78,11 @@ public: ...@@ -78,6 +78,11 @@ public:
manager->remove(me); manager->remove(me);
delete userData; delete userData;
delete appData; delete appData;
if(border) {
border->removeUser();
if(border->useCount() == 0)
delete border;
}
} }
void shapeChanged(ChangeType type) { void shapeChanged(ChangeType type) {
...@@ -566,7 +571,11 @@ KoShapeBorderModel *KoShape::border() const { ...@@ -566,7 +571,11 @@ KoShapeBorderModel *KoShape::border() const {
} }
void KoShape::setBorder(KoShapeBorderModel *border) { void KoShape::setBorder(KoShapeBorderModel *border) {
if(d->border)
d->border->removeUser();
d->border = border; d->border = border;
if(d->border)
d->border->addUser();
} }
const QMatrix& KoShape::matrix() const { const QMatrix& KoShape::matrix() const {
......
/* This file is part of the KDE project
* Copyright (C) 2007 Thomas Zander <zander@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "KoShapeBorderModel.h"
class KoShapeBorderModel::Private {
public:
Private() : refCount(0) { }
int refCount;
};
KoShapeBorderModel::KoShapeBorderModel()
: d(new Private())
{
}
KoShapeBorderModel::~KoShapeBorderModel()
{
delete d;
}
KoInsets KoShapeBorderModel::borderInsets(const KoShape *shape) {
KoInsets insets;
borderInsets(shape, insets);
return insets;
}
void KoShapeBorderModel::addUser() {
d->refCount++;
}
int KoShapeBorderModel::removeUser() {
return --d->refCount;
}
int KoShapeBorderModel::useCount() const {
return d->refCount;
}
...@@ -42,8 +42,8 @@ class KoViewConverter; ...@@ -42,8 +42,8 @@ class KoViewConverter;
*/ */
class FLAKE_EXPORT KoShapeBorderModel { class FLAKE_EXPORT KoShapeBorderModel {
public: public:
KoShapeBorderModel() {} KoShapeBorderModel();
virtual ~KoShapeBorderModel() {} virtual ~KoShapeBorderModel();
/** /**
* @brief Fill the style object * @brief Fill the style object
...@@ -59,11 +59,7 @@ public: ...@@ -59,11 +59,7 @@ public:
* @param shape the shape the insets will be calculated for * @param shape the shape the insets will be calculated for
* Note that the KoInsets is a new object that you are responsible to delete afterwards. * Note that the KoInsets is a new object that you are responsible to delete afterwards.
*/ */
KoInsets borderInsets(const KoShape *shape) { KoInsets borderInsets(const KoShape *shape);
KoInsets insets;
borderInsets(shape, insets);
return insets;
}
/** /**
* Return a borderInsets object filled with the size inside the shape that this border takes. * Return a borderInsets object filled with the size inside the shape that this border takes.
* @param shape the shape the insets will be calculated for * @param shape the shape the insets will be calculated for
...@@ -84,6 +80,17 @@ public: ...@@ -84,6 +80,17 @@ public:
* @param converter to convert between internal and view coordinates. * @param converter to convert between internal and view coordinates.
*/ */
virtual void paintBorder(KoShape *shape, QPainter &painter, const KoViewConverter &converter) = 0; virtual void paintBorder(KoShape *shape, QPainter &painter, const KoViewConverter &converter) = 0;
/// refcounting
void addUser();
/// refcounting
int removeUser();
/// refcounting
int useCount() const;
private:
class Private;
Private * const d;
}; };
#endif #endif
...@@ -27,10 +27,15 @@ ...@@ -27,10 +27,15 @@
class KoShapeBorderCommand::Private { class KoShapeBorderCommand::Private {
public: public:
Private() {} Private() {}
~Private() {
foreach(KoShapeBorderModel* border, oldBorders) {
if(border->useCount() <= 0)
delete border;
}
}
QList<KoShape*> shapes; ///< the shapes to set border for QList<KoShape*> shapes; ///< the shapes to set border for
QList<KoShapeBorderModel*> oldBorders; ///< the old borders, one for each shape QList<KoShapeBorderModel*> oldBorders; ///< the old borders, one for each shape
QList<KoShapeBorderModel*> newBorders; ///< the new borders to set QList<KoShapeBorderModel*> newBorders; ///< the new borders to set
}; };
KoShapeBorderCommand::KoShapeBorderCommand( const QList<KoShape*> &shapes, KoShapeBorderModel *border, KoShapeBorderCommand::KoShapeBorderCommand( const QList<KoShape*> &shapes, KoShapeBorderModel *border,
...@@ -47,10 +52,6 @@ KoShapeBorderCommand::KoShapeBorderCommand( const QList<KoShape*> &shapes, KoSha ...@@ -47,10 +52,6 @@ KoShapeBorderCommand::KoShapeBorderCommand( const QList<KoShape*> &shapes, KoSha
foreach( KoShape *shape, d->shapes ) foreach( KoShape *shape, d->shapes )
d->oldBorders.append( shape->border() ); d->oldBorders.append( shape->border() );
// XXX this command forgets to delete the old border on a shape and assumes someone else is still
// using it. For such cases we should probably create a new border for each shape in the redo method.
// and delete the old borders in the destructor
setText( i18n( "Set border" ) ); setText( i18n( "Set border" ) );
} }
...@@ -66,13 +67,9 @@ KoShapeBorderCommand::KoShapeBorderCommand( const QList<KoShape*> &shapes, ...@@ -66,13 +67,9 @@ KoShapeBorderCommand::KoShapeBorderCommand( const QList<KoShape*> &shapes,
d->newBorders = borders; d->newBorders = borders;
// save old borders // save old borders
foreach( KoShape *shape, d->shapes ) foreach( KoShape *shape, shapes )
d->oldBorders.append( shape->border() ); d->oldBorders.append( shape->border() );
// XXX this command forgets to delete the old border on a shape and assumes someone else is still
// using it. For such cases we should probably create a new border for each shape in the redo method.
// and delete the old borders in the destructor
setText( i18n( "Set border" ) ); setText( i18n( "Set border" ) );
} }
...@@ -84,9 +81,10 @@ void KoShapeBorderCommand::redo () { ...@@ -84,9 +81,10 @@ void KoShapeBorderCommand::redo () {
QUndoCommand::redo(); QUndoCommand::redo();
QList<KoShapeBorderModel*>::iterator borderIt = d->newBorders.begin(); QList<KoShapeBorderModel*>::iterator borderIt = d->newBorders.begin();
foreach( KoShape *shape, d->shapes ) { foreach( KoShape *shape, d->shapes ) {
shape->repaint();
shape->setBorder( *borderIt ); shape->setBorder( *borderIt );
shape->repaint(); shape->repaint();
borderIt++; ++borderIt;
} }
} }
...@@ -94,8 +92,9 @@ void KoShapeBorderCommand::undo () { ...@@ -94,8 +92,9 @@ void KoShapeBorderCommand::undo () {
QUndoCommand::undo(); QUndoCommand::undo();
QList<KoShapeBorderModel*>::iterator borderIt = d->oldBorders.begin(); QList<KoShapeBorderModel*>::iterator borderIt = d->oldBorders.begin();
foreach( KoShape *shape, d->shapes ) { foreach( KoShape *shape, d->shapes ) {
shape->repaint();
shape->setBorder( *borderIt ); shape->setBorder( *borderIt );
shape->repaint(); shape->repaint();
borderIt++; ++borderIt;
} }
} }
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