summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRalf Habacker <ralf.habacker@freenet.de>2016-11-08 07:39:19 (GMT)
committerRalf Habacker <ralf.habacker@freenet.de>2016-11-08 07:39:19 (GMT)
commit536e52fe6f71145cdcee16b5833f1c73b64e61fa (patch)
treeb8dd980f7f3fe28c82ed6fc81c58365981872324
parentd4dfde3d75047a8e3db1878200cf1ae8e35888b6 (diff)
Fix 'Crash when removing pin widgets after owning component has been removed before'.Applications/16.08
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)
-rw-r--r--umbrello/umlscene.cpp41
-rw-r--r--umbrello/umlscene.h6
-rw-r--r--umbrello/umlwidgets/pinportbase.cpp33
-rw-r--r--umbrello/umlwidgets/pinportbase.h7
-rw-r--r--umbrello/umlwidgets/portwidget.cpp8
5 files changed, 89 insertions, 6 deletions
diff --git a/umbrello/umlscene.cpp b/umbrello/umlscene.cpp
index b5acdc6..ac12e23 100644
--- a/umbrello/umlscene.cpp
+++ b/umbrello/umlscene.cpp
@@ -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));
@@ -1200,6 +1202,25 @@ void UMLScene::removeWidgetCmd(UMLWidget * o)
}
/**
+ * 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
*/
const QColor& UMLScene::backgroundColor() const
@@ -1377,6 +1398,24 @@ void UMLScene::selectionSetVisualProperty(ClassifierWidget::VisualProperty prope
}
/**
+ * 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.
*/
void UMLScene::deleteSelection()
@@ -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.
diff --git a/umbrello/umlscene.h b/umbrello/umlscene.h
index 895d212..1bd37f3 100644
--- a/umbrello/umlscene.h
+++ b/umbrello/umlscene.h
@@ -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();
diff --git a/umbrello/umlwidgets/pinportbase.cpp b/umbrello/umlwidgets/pinportbase.cpp
index 9e38235..62940ac 100644
--- a/umbrello/umlwidgets/pinportbase.cpp
+++ b/umbrello/umlwidgets/pinportbase.cpp
@@ -70,6 +70,26 @@ UMLWidget* PinPortBase::ownerWidget()
}
/**
+ * 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().
* The reason for using a tooltip for the name is that the size of this
@@ -194,6 +214,17 @@ void PinPortBase::attachToOwner() {
}
/**
+ * Remove link to owning widget.
+ */
+void PinPortBase::detachFromOwner()
+{
+ if (ownerWidget() != 0)
+ {
+ setOwnerWidget(0);
+ }
+}
+
+/**
* Overrides standard method.
*/
void PinPortBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
@@ -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()) {
diff --git a/umbrello/umlwidgets/pinportbase.h b/umbrello/umlwidgets/pinportbase.h
index ff9d397..3f77a96 100644
--- a/umbrello/umlwidgets/pinportbase.h
+++ b/umbrello/umlwidgets/pinportbase.h
@@ -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
diff --git a/umbrello/umlwidgets/portwidget.cpp b/umbrello/umlwidgets/portwidget.cpp
index b6884d9..6769ee3 100644
--- a/umbrello/umlwidgets/portwidget.cpp
+++ b/umbrello/umlwidgets/portwidget.cpp
@@ -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();
}
/**