summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamás Zolnai <tamas.zolnai@collabora.com>2019-02-21 13:38:33 +0100
committerTamás Zolnai <tamas.zolnai@collabora.com>2019-03-09 12:58:31 +0100
commit55d6be75732d1bb0067bba9496c74ef30be9a3ec (patch)
tree281c43cc47c77f1c202708fcf89b66a4798d7946
parent021332144074a9d20a3eab9ada117acfa7cdbfe0 (diff)
MSForms: Implement undo / redo for insertion of legacy form fields
Need to handle undo / redo explicitely for form fields, because there is no a general working undo / redo mechanism for fieldmarks. During the insertion of the fieldmark, text insertion also happens which generates an interfering undo action, so we need to disable undoing temporary. Also need to invalidta SID_UNDO slot to make the undo toolbar item updated after we insert a form field. Change-Id: I358c2704cb30212a38f8a998888a36f72fa404e5 Reviewed-on: https://gerrit.libreoffice.org/68956 Tested-by: Jenkins Reviewed-by: Tamás Zolnai <tamas.zolnai@collabora.com>
-rw-r--r--sw/inc/IDocumentMarkAccess.hxx2
-rw-r--r--sw/inc/strings.hrc1
-rw-r--r--sw/inc/swundo.hxx4
-rw-r--r--sw/source/core/doc/docbm.cxx32
-rw-r--r--sw/source/core/inc/MarkManager.hxx2
-rw-r--r--sw/source/core/inc/UndoBookmark.hxx27
-rw-r--r--sw/source/core/inc/rolbck.hxx29
-rw-r--r--sw/source/core/undo/rolbck.cxx90
-rw-r--r--sw/source/core/undo/unbkmk.cxx32
-rw-r--r--sw/source/core/undo/undobj.cxx3
-rw-r--r--sw/source/uibase/shells/textfld.cxx16
11 files changed, 237 insertions, 1 deletions
diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx
index 3fb7090e5067..823326e2b8ac 100644
--- a/sw/inc/IDocumentMarkAccess.hxx
+++ b/sw/inc/IDocumentMarkAccess.hxx
@@ -254,6 +254,8 @@ class IDocumentMarkAccess
virtual ::sw::mark::IFieldmark* getDropDownFor(const SwPosition& pos) const=0;
virtual std::vector< ::sw::mark::IFieldmark* > getDropDownsFor(const SwPaM &rPaM) const=0;
+ virtual void deleteFieldmarkAt(const SwPosition& rPos) = 0;
+
// Annotation Marks
virtual const_iterator_t getAnnotationMarksBegin() const = 0;
virtual const_iterator_t getAnnotationMarksEnd() const = 0;
diff --git a/sw/inc/strings.hrc b/sw/inc/strings.hrc
index 85ec816ad3d8..c8671f015e91 100644
--- a/sw/inc/strings.hrc
+++ b/sw/inc/strings.hrc
@@ -541,6 +541,7 @@
#define STR_UNDO_TBLSTYLE_DELETE NC_("STR_UNDO_TBLSTYLE_DELETE", "Delete table style: $1")
#define STR_UNDO_TBLSTYLE_UPDATE NC_("STR_UNDO_TBLSTYLE_UPDATE", "Update table style: $1")
#define STR_UNDO_TABLE_DELETE NC_("STR_UNDO_TABLE_DELETE", "Delete table")
+#define STR_UNDO_INSERT_FORM_FIELD NC_("STR_UNDO_INSERT_FORM_FIELD", "Insert form field")
#define STR_ACCESS_DOC_NAME NC_("STR_ACCESS_DOC_NAME", "Document view")
#define STR_ACCESS_DOC_DESC NC_("STR_ACCESS_DOC_DESC", "Document view")
diff --git a/sw/inc/swundo.hxx b/sw/inc/swundo.hxx
index c393554f0614..90fa6c51d055 100644
--- a/sw/inc/swundo.hxx
+++ b/sw/inc/swundo.hxx
@@ -162,7 +162,9 @@ enum class SwUndoId
UI_DELETE_PAGE_BREAK, // 131
UI_TEXT_CORRECTION, // 132
UI_TABLE_DELETE, // 133
- CONFLICT // 134
+ CONFLICT, // 134
+
+ INSERT_FORM_FIELD // 135
};
OUString GetUndoComment(SwUndoId eId);
diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
index bc429b9486d3..e06908f3438a 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -490,6 +490,10 @@ namespace sw { namespace mark
const OUString& rName,
const OUString& rType )
{
+ // Disable undo, because we handle it using SwUndoInsTextFieldmark
+ bool bUndoIsEnabled = m_pDoc->GetIDocumentUndoRedo().DoesUndo();
+ m_pDoc->GetIDocumentUndoRedo().DoUndo(false);
+
sw::mark::IMark* pMark = makeMark( rPaM, rName,
IDocumentMarkAccess::MarkType::TEXT_FIELDMARK,
sw::mark::InsertMode::New);
@@ -497,6 +501,12 @@ namespace sw { namespace mark
if (pFieldMark)
pFieldMark->SetFieldname( rType );
+ if (bUndoIsEnabled)
+ {
+ m_pDoc->GetIDocumentUndoRedo().DoUndo(bUndoIsEnabled);
+ m_pDoc->GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoInsTextFieldmark>(*pFieldMark));
+ }
+
return pFieldMark;
}
@@ -505,6 +515,10 @@ namespace sw { namespace mark
const OUString& rName,
const OUString& rType)
{
+ // Disable undo, because we handle it using SwUndoInsNoTextFieldmark
+ bool bUndoIsEnabled = m_pDoc->GetIDocumentUndoRedo().DoesUndo();
+ m_pDoc->GetIDocumentUndoRedo().DoUndo(false);
+
bool bEnableSetModified = m_pDoc->getIDocumentState().IsEnableSetModified();
m_pDoc->getIDocumentState().SetEnableSetModified(false);
@@ -515,6 +529,12 @@ namespace sw { namespace mark
if (pFieldMark)
pFieldMark->SetFieldname( rType );
+ if (bUndoIsEnabled)
+ {
+ m_pDoc->GetIDocumentUndoRedo().DoUndo(bUndoIsEnabled);
+ m_pDoc->GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoInsNoTextFieldmark>(*pFieldMark));
+ }
+
m_pDoc->getIDocumentState().SetEnableSetModified(bEnableSetModified);
m_pDoc->getIDocumentState().SetModified();
@@ -1046,6 +1066,18 @@ namespace sw { namespace mark
return dynamic_cast<IFieldmark*>(pFieldmark->get());
}
+ void MarkManager::deleteFieldmarkAt(const SwPosition& rPos)
+ {
+ const_iterator_t pFieldmark = find_if(
+ m_vFieldmarks.begin(),
+ m_vFieldmarks.end(),
+ [&rPos] (pMark_t const& rpMark) { return rpMark->IsCoveringPosition(rPos); } );
+ if(pFieldmark == m_vFieldmarks.end()) return;
+
+ deleteMark(lcl_FindMark(m_vAllMarks, *pFieldmark));
+ }
+
+
IFieldmark* MarkManager::getDropDownFor(const SwPosition& rPos) const
{
IFieldmark *pMark = getFieldmarkFor(rPos);
diff --git a/sw/source/core/inc/MarkManager.hxx b/sw/source/core/inc/MarkManager.hxx
index d47e4a615d92..cbae235520e8 100644
--- a/sw/source/core/inc/MarkManager.hxx
+++ b/sw/source/core/inc/MarkManager.hxx
@@ -85,6 +85,8 @@ namespace sw {
virtual ::sw::mark::IFieldmark* getDropDownFor(const SwPosition &rPos) const override;
virtual std::vector< ::sw::mark::IFieldmark* > getDropDownsFor(const SwPaM &rPaM) const override;
+ virtual void deleteFieldmarkAt(const SwPosition& rPos) override;
+
void dumpAsXml(xmlTextWriterPtr pWriter) const;
// Annotation Marks
diff --git a/sw/source/core/inc/UndoBookmark.hxx b/sw/source/core/inc/UndoBookmark.hxx
index eb32662c92d8..7b9dd4fc68e5 100644
--- a/sw/source/core/inc/UndoBookmark.hxx
+++ b/sw/source/core/inc/UndoBookmark.hxx
@@ -24,10 +24,13 @@
#include <undobj.hxx>
class SwHistoryBookmark;
+class SwHistoryNoTextFieldmark;
+class SwHistoryTextFieldmark;
namespace sw {
namespace mark {
class IMark;
+ class IFieldmark;
}
}
@@ -95,6 +98,30 @@ private:
virtual void RedoImpl( ::sw::UndoRedoContext & ) override;
};
+class SwUndoInsNoTextFieldmark : public SwUndo
+{
+private:
+ const std::unique_ptr<SwHistoryNoTextFieldmark> m_pHistoryNoTextFieldmark;
+
+public:
+ SwUndoInsNoTextFieldmark(const ::sw::mark::IFieldmark& rFieldmark);
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & ) override;
+ virtual void RedoImpl( ::sw::UndoRedoContext & ) override;
+};
+
+class SwUndoInsTextFieldmark : public SwUndo
+{
+private:
+ const std::unique_ptr<SwHistoryTextFieldmark> m_pHistoryTextFieldmark;
+
+public:
+ SwUndoInsTextFieldmark(const ::sw::mark::IFieldmark& rFieldmark);
+
+ virtual void UndoImpl( ::sw::UndoRedoContext & ) override;
+ virtual void RedoImpl( ::sw::UndoRedoContext & ) override;
+};
+
#endif // INCLUDED_SW_SOURCE_CORE_INC_UNDOBOOKMARK_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/rolbck.hxx b/sw/source/core/inc/rolbck.hxx
index 945ed1948388..3fde226b7acf 100644
--- a/sw/source/core/inc/rolbck.hxx
+++ b/sw/source/core/inc/rolbck.hxx
@@ -72,6 +72,8 @@ enum HISTORY_HINT {
HSTRY_CHGFLYANCHOR,
HSTRY_CHGFLYCHAIN,
HSTRY_CHGCHARFMT,
+ HSTRY_NOTEXTFIELDMARK,
+ HSTRY_TEXTFIELDMARK,
};
class SwHistoryHint
@@ -260,6 +262,33 @@ class SwHistoryBookmark : public SwHistoryHint
std::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndo;
};
+class SwHistoryNoTextFieldmark : public SwHistoryHint
+{
+ public:
+ SwHistoryNoTextFieldmark(const ::sw::mark::IFieldmark& rFieldMark);
+ virtual void SetInDoc(SwDoc* pDoc, bool) override;
+ void ResetInDoc(SwDoc* pDoc);
+
+ private:
+ const OUString m_sType;
+ const sal_uLong m_nNode;
+ const sal_Int32 m_nContent;
+};
+
+class SwHistoryTextFieldmark : public SwHistoryHint
+{
+ public:
+ SwHistoryTextFieldmark(const ::sw::mark::IFieldmark& rFieldMark);
+ virtual void SetInDoc(SwDoc* pDoc, bool) override;
+ void ResetInDoc(SwDoc* pDoc);
+
+ private:
+ const OUString m_sName;
+ const OUString m_sType;
+ const sal_uLong m_nNode;
+ const sal_Int32 m_nContent;
+};
+
class SwHistorySetAttrSet : public SwHistoryHint
{
SfxItemSet m_OldSet;
diff --git a/sw/source/core/undo/rolbck.cxx b/sw/source/core/undo/rolbck.cxx
index 51a4bcdd813f..8a24eb941527 100644
--- a/sw/source/core/undo/rolbck.cxx
+++ b/sw/source/core/undo/rolbck.cxx
@@ -677,6 +677,96 @@ bool SwHistoryBookmark::IsEqualBookmark(const ::sw::mark::IMark& rBkmk)
|| dynamic_cast<sw::mark::CrossRefHeadingBookmark const*>(&rBkmk));
}
+SwHistoryNoTextFieldmark::SwHistoryNoTextFieldmark(const ::sw::mark::IFieldmark& rFieldMark)
+ : SwHistoryHint(HSTRY_NOTEXTFIELDMARK)
+ , m_sType(rFieldMark.GetFieldname())
+ , m_nNode(rFieldMark.GetMarkPos().nNode.GetIndex())
+ , m_nContent(rFieldMark.GetMarkPos().nContent.GetIndex())
+{
+}
+
+void SwHistoryNoTextFieldmark::SetInDoc(SwDoc* pDoc, bool)
+{
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ SwNodes& rNds = pDoc->GetNodes();
+ std::unique_ptr<SwPaM> pPam;
+
+ const SwContentNode* pContentNd = rNds[m_nNode]->GetContentNode();
+ if(pContentNd)
+ pPam.reset(new SwPaM(*pContentNd, m_nContent));
+
+ if (pPam)
+ {
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+ pMarkAccess->makeNoTextFieldBookmark(*pPam, OUString(), m_sType);
+ }
+}
+
+void SwHistoryNoTextFieldmark::ResetInDoc(SwDoc* pDoc)
+{
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ SwNodes& rNds = pDoc->GetNodes();
+ std::unique_ptr<SwPaM> pPam;
+
+ const SwContentNode* pContentNd = rNds[m_nNode]->GetContentNode();
+ if(pContentNd)
+ pPam.reset(new SwPaM(*pContentNd, m_nContent-1));
+
+ if (pPam)
+ {
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+ pMarkAccess->deleteFieldmarkAt(*pPam->GetPoint());
+ }
+}
+
+SwHistoryTextFieldmark::SwHistoryTextFieldmark(const ::sw::mark::IFieldmark& rFieldMark)
+ : SwHistoryHint(HSTRY_TEXTFIELDMARK)
+ , m_sName(rFieldMark.GetName())
+ , m_sType(rFieldMark.GetFieldname())
+ , m_nNode(rFieldMark.GetMarkPos().nNode.GetIndex())
+ , m_nContent(rFieldMark.GetMarkPos().nContent.GetIndex())
+{
+}
+
+void SwHistoryTextFieldmark::SetInDoc(SwDoc* pDoc, bool)
+{
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ SwNodes& rNds = pDoc->GetNodes();
+ std::unique_ptr<SwPaM> pPam;
+
+ const SwContentNode* pContentNd = rNds[m_nNode]->GetContentNode();
+ if(pContentNd)
+ pPam.reset(new SwPaM(*pContentNd, m_nContent));
+
+ if (pPam)
+ {
+ IDocumentMarkAccess* pMarksAccess = pDoc->getIDocumentMarkAccess();
+ SwPaM aFieldPam(pPam->GetPoint()->nNode, pPam->GetPoint()->nContent.GetIndex(),
+ pPam->GetPoint()->nNode, pPam->GetPoint()->nContent.GetIndex() + 5);
+ pMarksAccess->makeFieldBookmark(aFieldPam, m_sName, m_sType);
+ }
+}
+
+void SwHistoryTextFieldmark::ResetInDoc(SwDoc* pDoc)
+{
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ SwNodes& rNds = pDoc->GetNodes();
+ std::unique_ptr<SwPaM> pPam;
+
+ const SwContentNode* pContentNd = rNds[m_nNode]->GetContentNode();
+ if(pContentNd)
+ pPam.reset(new SwPaM(*pContentNd, m_nContent));
+
+ if (pPam)
+ {
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+ pMarkAccess->deleteFieldmarkAt(*pPam->GetPoint());
+ }
+}
SwHistorySetAttrSet::SwHistorySetAttrSet( const SfxItemSet& rSet,
sal_uLong nNodePos, const std::set<sal_uInt16> &rSetArr )
diff --git a/sw/source/core/undo/unbkmk.cxx b/sw/source/core/undo/unbkmk.cxx
index fc465aad21b2..c4d77b6e2f71 100644
--- a/sw/source/core/undo/unbkmk.cxx
+++ b/sw/source/core/undo/unbkmk.cxx
@@ -148,4 +148,36 @@ void SwUndoRenameBookmark::RedoImpl(::sw::UndoRedoContext & rContext)
Rename(rContext, m_sOldName, m_sNewName);
}
+SwUndoInsNoTextFieldmark::SwUndoInsNoTextFieldmark(const ::sw::mark::IFieldmark& rFieldmark)
+ : SwUndo(SwUndoId::INSERT, rFieldmark.GetMarkPos().GetDoc())
+ , m_pHistoryNoTextFieldmark(new SwHistoryNoTextFieldmark(rFieldmark))
+{
+}
+
+void SwUndoInsNoTextFieldmark::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ m_pHistoryNoTextFieldmark->ResetInDoc(&rContext.GetDoc());
+}
+
+void SwUndoInsNoTextFieldmark::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ m_pHistoryNoTextFieldmark->SetInDoc(&rContext.GetDoc(), false);
+}
+
+SwUndoInsTextFieldmark::SwUndoInsTextFieldmark(const ::sw::mark::IFieldmark& rFieldmark)
+ : SwUndo(SwUndoId::INSERT, rFieldmark.GetMarkPos().GetDoc())
+ , m_pHistoryTextFieldmark(new SwHistoryTextFieldmark(rFieldmark))
+{
+}
+
+void SwUndoInsTextFieldmark::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ m_pHistoryTextFieldmark->ResetInDoc(&rContext.GetDoc());
+}
+
+void SwUndoInsTextFieldmark::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ m_pHistoryTextFieldmark->SetInDoc(&rContext.GetDoc(), false);
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/undobj.cxx b/sw/source/core/undo/undobj.cxx
index 5f5adbb1bfd7..eb909378556b 100644
--- a/sw/source/core/undo/undobj.cxx
+++ b/sw/source/core/undo/undobj.cxx
@@ -641,6 +641,9 @@ OUString GetUndoComment(SwUndoId eId)
case SwUndoId::PARA_SIGN_ADD:
pId = STR_PARAGRAPH_SIGN_UNDO;
break;
+ case SwUndoId::INSERT_FORM_FIELD:
+ pId = STR_UNDO_INSERT_FORM_FIELD;
+ break;
};
assert(pId);
diff --git a/sw/source/uibase/shells/textfld.cxx b/sw/source/uibase/shells/textfld.cxx
index dd34a47e16bd..ccf3952aaa97 100644
--- a/sw/source/uibase/shells/textfld.cxx
+++ b/sw/source/uibase/shells/textfld.cxx
@@ -74,6 +74,7 @@
#include <MarkManager.hxx>
#include <xmloff/odffields.hxx>
#include <IDocumentContentOperations.hxx>
+#include <IDocumentUndoRedo.hxx>
using namespace nsSwDocInfoSubType;
@@ -721,6 +722,8 @@ FIELD_INSERT:
case FN_INSERT_TEXT_FORMFIELD:
{
+ rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
+
SwPaM* pCursorPos = rSh.GetCursor();
if(pCursorPos)
{
@@ -735,26 +738,39 @@ FIELD_INSERT:
pMarksAccess->makeFieldBookmark(aFieldPam, OUString(), ODF_FORMTEXT);
}
}
+
+ rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
+ rSh.GetView().GetViewFrame()->GetBindings().Invalidate( SID_UNDO );
}
break;
case FN_INSERT_CHECKBOX_FORMFIELD:
{
+ rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
+
SwPaM* pCursorPos = rSh.GetCursor();
if(pCursorPos)
{
IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess();
pMarksAccess->makeNoTextFieldBookmark(*pCursorPos, OUString(), ODF_FORMCHECKBOX);
}
+
+ rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
+ rSh.GetView().GetViewFrame()->GetBindings().Invalidate( SID_UNDO );
}
break;
case FN_INSERT_DROPDOWN_FORMFIELD:
{
+ rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
+
SwPaM* pCursorPos = rSh.GetCursor();
if(pCursorPos)
{
IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess();
pMarksAccess->makeNoTextFieldBookmark(*pCursorPos, OUString(), ODF_FORMDROPDOWN);
}
+
+ rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
+ rSh.GetView().GetViewFrame()->GetBindings().Invalidate( SID_UNDO );
}
break;
default: