Commit 536e52fe authored by Ralf Habacker's avatar Ralf Habacker

Fix 'Crash when removing pin widgets after owning component has been removed before'.

The fix from clushkou@gmx.net is designed to remove PinPortBase objects when owner is remove.

BUG:371990
FIXED-IN:2.20.3 (KDE Applications 16.08.3)
parent d4dfde3d
......@@ -1180,6 +1180,8 @@ void UMLScene::removeWidgetCmd(UMLWidget * o)
removeAssociations(o);
removeOwnedWidgets(o);
WidgetBase::WidgetType t = o->baseType();
if (type() == DiagramType::Sequence && t == WidgetBase::wt_Object) {
checkMessages(static_cast<ObjectWidget*>(o));
......@@ -1199,6 +1201,25 @@ void UMLScene::removeWidgetCmd(UMLWidget * o)
m_doc->setModified(true);
}
/**
* Remove all widgets that have given widget as owner.
*
* @param o The owner widget that will be removed.
*/
void UMLScene::removeOwnedWidgets(UMLWidget* o)
{
foreach (UMLWidget* wid, m_WidgetList) {
if (wid->isPinWidget() ||
wid->isPortWidget()) {
PinPortBase* pw = wid->asPinPortBase();
if (pw->hasOwner(o)) {
pw->detachFromOwner();
removeWidgetCmd(pw);
}
}
}
}
/**
* Returns background color
*/
......@@ -1376,6 +1397,24 @@ void UMLScene::selectionSetVisualProperty(ClassifierWidget::VisualProperty prope
UMLApp::app()->endMacro();
}
/**
* Unselect child widgets when their owner is already selected.
*/
void UMLScene::unselectChildrenOfSelectedWidgets()
{
foreach(UMLWidget* widget, selectedWidgets()) {
if (widget->isPinWidget() ||
widget->isPortWidget()) {
PinPortBase* pw = widget->asPinPortBase();
foreach(UMLWidget* potentialParentWidget, selectedWidgets()) {
if (pw->hasOwner(potentialParentWidget)) {
pw->setSelectedFlag(false);
}
}
}
}
}
/**
* Delete the selected widgets list and the widgets in it.
*/
......@@ -1389,6 +1428,8 @@ void UMLScene::deleteSelection()
UMLApp::app()->beginMacro(i18n("Delete widgets"));
}
unselectChildrenOfSelectedWidgets();
foreach(UMLWidget* widget, selectedWidgets()) {
// Don't delete text widget that are connect to associations as these will
// be cleaned up by the associations.
......
......@@ -175,6 +175,9 @@ public:
void removeWidget(UMLWidget *o);
void removeWidgetCmd(UMLWidget *o);
private:
void removeOwnedWidgets(UMLWidget* o);
public:
UMLWidgetList selectedWidgets() const;
void clearSelected();
......@@ -190,6 +193,9 @@ public:
void selectionSetFillColor(const QColor &color);
void selectionSetVisualProperty(ClassifierWidget::VisualProperty property, bool value);
private:
void unselectChildrenOfSelectedWidgets();
public:
void deleteSelection();
void resizeSelection();
......
......@@ -69,6 +69,26 @@ UMLWidget* PinPortBase::ownerWidget()
return m_pOw;
}
/**
* Returns whether this widget is owned by given widget.
*
* @param o Owning widget
*/
bool PinPortBase::hasOwner(const UMLWidget* const o) const
{
return m_pOw == o;
}
/**
* Set owner widget.
*
* @param ownerWidget Owning widget
*/
void PinPortBase::setOwnerWidget(UMLWidget* const ownerWidget)
{
m_pOw = ownerWidget;
}
/**
* Overrides method from UMLWidget in order to set a tooltip.
* The tooltip is set to the name().
......@@ -193,6 +213,17 @@ void PinPortBase::attachToOwner() {
}
}
/**
* Remove link to owning widget.
*/
void PinPortBase::detachFromOwner()
{
if (ownerWidget() != 0)
{
setOwnerWidget(0);
}
}
/**
* Overrides standard method.
*/
......@@ -320,7 +351,7 @@ void PinPortBase::saveToXMI(QDomDocument& qDoc, QDomElement& qElement)
{
QDomElement element = qDoc.createElement(baseType() == wt_Pin ? QLatin1String("pinwidget")
: QLatin1String("portwidget"));
Q_ASSERT(ownerWidget() != NULL);
Q_ASSERT(ownerWidget() != 0);
element.setAttribute(QLatin1String("widgetaid"), Uml::ID::toString(ownerWidget()->id()));
UMLWidget::saveToXMI(qDoc, element);
if (m_pName && !m_pName->text().isEmpty()) {
......
......@@ -33,11 +33,14 @@ public:
virtual UMLWidget* ownerWidget();
virtual void connectOwnerMotion() = 0;
bool hasOwner(const UMLWidget* const o) const;
void setOwnerWidget(UMLWidget* const ownerWidget);
void setName(const QString &strName);
void updateWidget();
void moveWidgetBy(qreal diffX, qreal diffY);
void attachToOwner();
void detachFromOwner();
UMLWidget* onWidget(const QPointF& p);
UMLWidget* widgetWithID(Uml::ID::Type id);
......@@ -55,9 +58,11 @@ public slots:
protected:
void init(UMLWidget *owner = 0);
UMLWidget* m_pOw;
FloatingTextWidget *m_pName;
bool m_motionConnected;
private:
UMLWidget* m_pOw;
};
#endif
......@@ -57,11 +57,11 @@ PortWidget::~PortWidget()
*/
UMLWidget* PortWidget::ownerWidget()
{
if (m_pOw == NULL) {
const Uml::ID::Type compWidgetId = m_umlObject->umlPackage()->id();
m_pOw = m_scene->widgetOnDiagram(compWidgetId);
if (PinPortBase::ownerWidget() == 0) {
const Uml::ID::Type compWidgetId = umlObject()->umlPackage()->id();
setOwnerWidget(m_scene->widgetOnDiagram(compWidgetId));
}
return m_pOw;
return PinPortBase::ownerWidget();
}
/**
......
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