summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Araminowicz <grzegorz.araminowicz@collabora.com>2019-09-20 12:53:45 +0200
committerGrzegorz Araminowicz <grzegorz.araminowicz@collabora.com>2019-09-25 09:31:08 +0200
commit711c0b6331958da4fd53eb6c4f9ecd5a422bb186 (patch)
treee17b463e3f813cc4a4d849d91397adc610f121db
parentb13421011d9377676e1adc282634991d5064a866 (diff)
SmartArt Edit UI: remove node
Removes data node from data model including associated presentation nodes, transition nodes and all connections between them (child-parent and presentation-of). It still doesn't update order of remaining connections after removal, so empty entries can happen. Additional step is needed or using better data structures. Change-Id: I96e0752b6ec5a19ae8e972dbd421314e6c442b53 Reviewed-on: https://gerrit.libreoffice.org/79279 Tested-by: Jenkins Reviewed-by: Grzegorz Araminowicz <grzegorz.araminowicz@collabora.com>
-rw-r--r--cui/source/dialogs/DiagramDialog.cxx19
-rw-r--r--cui/source/inc/DiagramDialog.hxx2
-rw-r--r--cui/uiconfig/ui/diagramdialog.ui14
-rw-r--r--include/svx/DiagramDataInterface.hxx6
-rw-r--r--oox/source/drawingml/diagram/datamodel.cxx68
-rw-r--r--oox/source/drawingml/diagram/datamodel.hxx3
6 files changed, 104 insertions, 8 deletions
diff --git a/cui/source/dialogs/DiagramDialog.cxx b/cui/source/dialogs/DiagramDialog.cxx
index 4891ef93daee..f3a4a069a19c 100644
--- a/cui/source/dialogs/DiagramDialog.cxx
+++ b/cui/source/dialogs/DiagramDialog.cxx
@@ -20,10 +20,12 @@ DiagramDialog::DiagramDialog(weld::Window* pWindow,
, mpBtnOk(m_xBuilder->weld_button("btnOk"))
, mpBtnCancel(m_xBuilder->weld_button("btnCancel"))
, mpBtnAdd(m_xBuilder->weld_button("btnAdd"))
+ , mpBtnRemove(m_xBuilder->weld_button("btnRemove"))
, mpTreeDiagram(m_xBuilder->weld_tree_view("treeDiagram"))
, mpTextAdd(m_xBuilder->weld_text_view("textAdd"))
{
mpBtnAdd->connect_clicked(LINK(this, DiagramDialog, OnAddClick));
+ mpBtnRemove->connect_clicked(LINK(this, DiagramDialog, OnRemoveClick));
populateTree(nullptr, OUString());
@@ -40,15 +42,28 @@ IMPL_LINK_NOARG(DiagramDialog, OnAddClick, weld::Button&, void)
OUString sText = mpTextAdd->get_text();
if (!sText.isEmpty())
{
+ OUString sNodeId = mpDiagramData->addNode(sText);
std::unique_ptr<weld::TreeIter> pEntry(mpTreeDiagram->make_iterator());
- mpTreeDiagram->insert(nullptr, -1, &sText, nullptr, nullptr, nullptr, nullptr, false,
+ mpTreeDiagram->insert(nullptr, -1, &sText, &sNodeId, nullptr, nullptr, nullptr, false,
pEntry.get());
mpTreeDiagram->select(*pEntry);
- mpDiagramData->addNode(sText);
comphelper::dispatchCommand(".uno:RegenerateDiagram", {});
}
}
+IMPL_LINK_NOARG(DiagramDialog, OnRemoveClick, weld::Button&, void)
+{
+ std::unique_ptr<weld::TreeIter> pEntry(mpTreeDiagram->make_iterator());
+ if (mpTreeDiagram->get_selected(pEntry.get()))
+ {
+ if (mpDiagramData->removeNode(mpTreeDiagram->get_id(*pEntry)))
+ {
+ mpTreeDiagram->remove(*pEntry);
+ comphelper::dispatchCommand(".uno:RegenerateDiagram", {});
+ }
+ }
+}
+
void DiagramDialog::populateTree(const weld::TreeIter* pParent, const OUString& rParentId)
{
auto aItems = mpDiagramData->getChildren(rParentId);
diff --git a/cui/source/inc/DiagramDialog.hxx b/cui/source/inc/DiagramDialog.hxx
index 461ffee9a7e6..e97144050a0e 100644
--- a/cui/source/inc/DiagramDialog.hxx
+++ b/cui/source/inc/DiagramDialog.hxx
@@ -27,10 +27,12 @@ private:
std::unique_ptr<weld::Button> mpBtnOk;
std::unique_ptr<weld::Button> mpBtnCancel;
std::unique_ptr<weld::Button> mpBtnAdd;
+ std::unique_ptr<weld::Button> mpBtnRemove;
std::unique_ptr<weld::TreeView> mpTreeDiagram;
std::unique_ptr<weld::TextView> mpTextAdd;
DECL_LINK(OnAddClick, weld::Button&, void);
+ DECL_LINK(OnRemoveClick, weld::Button&, void);
void populateTree(const weld::TreeIter* pParent, const OUString& rParentId);
};
diff --git a/cui/uiconfig/ui/diagramdialog.ui b/cui/uiconfig/ui/diagramdialog.ui
index 98a67717209a..c05031f19bc4 100644
--- a/cui/uiconfig/ui/diagramdialog.ui
+++ b/cui/uiconfig/ui/diagramdialog.ui
@@ -129,6 +129,20 @@
<property name="position">1</property>
</packing>
</child>
+ <child>
+ <object class="GtkButton" id="btnRemove">
+ <property name="label">gtk-remove</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">False</property>
diff --git a/include/svx/DiagramDataInterface.hxx b/include/svx/DiagramDataInterface.hxx
index aaa3a46968b3..f64dc3a09316 100644
--- a/include/svx/DiagramDataInterface.hxx
+++ b/include/svx/DiagramDataInterface.hxx
@@ -38,8 +38,10 @@ public:
virtual std::vector<std::pair<OUString, OUString>>
getChildren(const OUString& rParentId) const = 0;
- // add new top-level node to data model
- virtual void addNode(const OUString& rText) = 0;
+ // add new top-level node to data model, returns its id
+ virtual OUString addNode(const OUString& rText) = 0;
+
+ virtual bool removeNode(const OUString& rNodeId) = 0;
protected:
~DiagramDataInterface() throw() {}
diff --git a/oox/source/drawingml/diagram/datamodel.cxx b/oox/source/drawingml/diagram/datamodel.cxx
index 1f1794b31854..6b7d05ebe58d 100644
--- a/oox/source/drawingml/diagram/datamodel.cxx
+++ b/oox/source/drawingml/diagram/datamodel.cxx
@@ -29,6 +29,7 @@
#include <svx/DiagramDataInterface.hxx>
#include <comphelper/xmltools.hxx>
+#include <unordered_set>
#include <iostream>
#include <fstream>
@@ -137,6 +138,12 @@ std::vector<std::pair<OUString, OUString>> DiagramData::getChildren(const OUStri
pChild->second->msModelId,
pChild->second->mpShape->getTextBody()->getParagraphs().front()->getRuns().front()->getText());
}
+
+ // HACK: empty items shouldn't appear there
+ aChildren.erase(std::remove_if(aChildren.begin(), aChildren.end(),
+ [](const std::pair<OUString, OUString>& aItem) { return aItem.first.isEmpty(); }),
+ aChildren.end());
+
return aChildren;
}
@@ -154,7 +161,7 @@ void DiagramData::addConnection(sal_Int32 nType, const OUString& sSourceId, cons
rCxn.mnSourceOrder = nMaxOrd + 1;
}
-void DiagramData::addNode(const OUString& rText)
+OUString DiagramData::addNode(const OUString& rText)
{
const dgm::Point& rDataRoot = *getRootPoint();
OUString sPresRoot;
@@ -163,11 +170,13 @@ void DiagramData::addNode(const OUString& rText)
sPresRoot = aCxn.msDestId;
if (sPresRoot.isEmpty())
- return;
+ return OUString();
+
+ OUString sNewNodeId = OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_UTF8);
dgm::Point aDataPoint;
aDataPoint.mnType = XML_node;
- aDataPoint.msModelId = OStringToOUString(comphelper::xml::generateGUIDString(), RTL_TEXTENCODING_UTF8);
+ aDataPoint.msModelId = sNewNodeId;
aDataPoint.mpShape.reset(new Shape());
aDataPoint.mpShape->setTextBody(std::make_shared<TextBody>());
TextRunPtr pTextRun(new TextRun());
@@ -208,6 +217,59 @@ void DiagramData::addNode(const OUString& rText)
maPoints.push_back(aPresPoint);
build();
+ return sNewNodeId;
+}
+
+bool DiagramData::removeNode(const OUString& rNodeId)
+{
+ // check if it doesn't have children
+ for (const auto& aCxn : maConnections)
+ if (aCxn.mnType == XML_parOf && aCxn.msSourceId == rNodeId)
+ {
+ SAL_WARN("oox.drawingml", "Node has children - can't be removed");
+ return false;
+ }
+
+ dgm::Connection aParCxn;
+ for (const auto& aCxn : maConnections)
+ if (aCxn.mnType == XML_parOf && aCxn.msDestId == rNodeId)
+ aParCxn = aCxn;
+
+ std::unordered_set<OUString> aIdsToRemove;
+ aIdsToRemove.insert(rNodeId);
+ if (!aParCxn.msParTransId.isEmpty())
+ aIdsToRemove.insert(aParCxn.msParTransId);
+ if (!aParCxn.msSibTransId.isEmpty())
+ aIdsToRemove.insert(aParCxn.msSibTransId);
+
+ for (const dgm::Point& rPoint : maPoints)
+ if (aIdsToRemove.count(rPoint.msPresentationAssociationId))
+ aIdsToRemove.insert(rPoint.msModelId);
+
+ // instert also transition nodes
+ for (const auto& aCxn : maConnections)
+ if (aIdsToRemove.count(aCxn.msSourceId) || aIdsToRemove.count(aCxn.msDestId))
+ if (!aCxn.msPresId.isEmpty())
+ aIdsToRemove.insert(aCxn.msPresId);
+
+ // remove connections
+ maConnections.erase(std::remove_if(maConnections.begin(), maConnections.end(),
+ [aIdsToRemove](const dgm::Connection& rCxn) {
+ return aIdsToRemove.count(rCxn.msSourceId) || aIdsToRemove.count(rCxn.msDestId);
+ }),
+ maConnections.end());
+
+ // remove data and presentation nodes
+ maPoints.erase(std::remove_if(maPoints.begin(), maPoints.end(),
+ [aIdsToRemove](const dgm::Point& rPoint) {
+ return aIdsToRemove.count(rPoint.msModelId);
+ }),
+ maPoints.end());
+
+ // TODO: fix source/dest order
+
+ build();
+ return true;
}
#ifdef DEBUG_OOX_DIAGRAM
diff --git a/oox/source/drawingml/diagram/datamodel.hxx b/oox/source/drawingml/diagram/datamodel.hxx
index b4c7ce7f82f7..7f7f0f4910c5 100644
--- a/oox/source/drawingml/diagram/datamodel.hxx
+++ b/oox/source/drawingml/diagram/datamodel.hxx
@@ -182,7 +182,8 @@ public:
void dump() const;
OUString getString() const override;
std::vector<std::pair<OUString, OUString>> getChildren(const OUString& rParentId) const override;
- void addNode(const OUString& rText) override;
+ OUString addNode(const OUString& rText) override;
+ bool removeNode(const OUString& rNodeId) override;
private:
void getChildrenString(OUStringBuffer& rBuf, const dgm::Point* pPoint, sal_Int32 nLevel) const;