summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
Diffstat (limited to 'sw')
-rw-r--r--sw/CppunitTest_sw_apitests.mk1
-rw-r--r--sw/inc/fmtfld.hxx2
-rw-r--r--sw/qa/api/SwXTextField.cxx89
-rw-r--r--sw/qa/python/xtext.py8
-rw-r--r--sw/source/core/txtnode/atrfld.cxx4
-rw-r--r--sw/source/core/unocore/unofield.cxx174
6 files changed, 177 insertions, 101 deletions
diff --git a/sw/CppunitTest_sw_apitests.mk b/sw/CppunitTest_sw_apitests.mk
index ca2c919e0aa6..370ed779d8b9 100644
--- a/sw/CppunitTest_sw_apitests.mk
+++ b/sw/CppunitTest_sw_apitests.mk
@@ -16,6 +16,7 @@ $(eval $(call gb_CppunitTest_use_external,sw_apitests,boost_headers))
$(eval $(call gb_CppunitTest_add_exception_objects,sw_apitests, \
sw/qa/api/SwXDocumentIndex \
sw/qa/api/SwXDocumentSettings \
+ sw/qa/api/SwXTextField \
sw/qa/api/SwXTextTable \
))
diff --git a/sw/inc/fmtfld.hxx b/sw/inc/fmtfld.hxx
index b144243ec4c9..d9eafeea82a3 100644
--- a/sw/inc/fmtfld.hxx
+++ b/sw/inc/fmtfld.hxx
@@ -36,7 +36,7 @@ namespace com { namespace sun { namespace star { namespace text { class XTextFie
// ATT_FLD
class SW_DLLPUBLIC SwFormatField
: public SfxPoolItem
- , public SwModify
+ , public sw::BroadcastingModify
, public SfxBroadcaster
{
friend void InitCore();
diff --git a/sw/qa/api/SwXTextField.cxx b/sw/qa/api/SwXTextField.cxx
new file mode 100644
index 000000000000..1de775d1e3d7
--- /dev/null
+++ b/sw/qa/api/SwXTextField.cxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+#include <test/lang/xcomponent.hxx>
+#include <unotest/macros_test.hxx>
+
+#include <com/sun/star/frame/Desktop.hpp>
+
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/text/XTextContent.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/text/XTextField.hpp>
+#include <com/sun/star/text/XDependentTextField.hpp>
+#include <com/sun/star/text/XTextCursor.hpp>
+
+#include <comphelper/processfactory.hxx>
+
+using namespace css;
+using namespace css::uno;
+using namespace css::beans;
+
+namespace
+{
+/**
+ * Initial tests for SwXTextField.
+ */
+struct SwXTextField final : public test::BootstrapFixture,
+ public unotest::MacrosTest,
+ public apitest::XComponent
+{
+ virtual void setUp() override;
+
+ Reference<XInterface> init() override;
+ void triggerDesktopTerminate() override;
+
+ CPPUNIT_TEST_SUITE(SwXTextField);
+ CPPUNIT_TEST(testAddEventListener);
+ CPPUNIT_TEST(testRemoveEventListener);
+ //CPPUNIT_TEST(testDisposedByDesktopTerminate);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void SwXTextField::setUp()
+{
+ test::BootstrapFixture::setUp();
+ mxDesktop.set(
+ frame::Desktop::create(comphelper::getComponentContext(getMultiServiceFactory())));
+}
+
+void SwXTextField::triggerDesktopTerminate() { mxDesktop->terminate(); }
+
+Reference<XInterface> SwXTextField::init()
+{
+ auto xComponent = loadFromDesktop("private:factory/swriter", "com.sun.star.text.TextDocument");
+ CPPUNIT_ASSERT(xComponent.is());
+ Reference<text::XTextDocument> xTextDocument(xComponent, UNO_QUERY_THROW);
+ Reference<lang::XMultiServiceFactory> xMSF(xComponent, UNO_QUERY_THROW);
+
+ Reference<XPropertySet> xFieldMaster(
+ xMSF->createInstance("com.sun.star.text.FieldMaster.Database"), UNO_QUERY_THROW);
+ xFieldMaster->setPropertyValue("DataBaseName", makeAny(OUString("Address Book File")));
+ xFieldMaster->setPropertyValue("DataTableName", makeAny(OUString("address")));
+ xFieldMaster->setPropertyValue("DataColumnName", makeAny(OUString("FIRSTNAME")));
+
+ Reference<text::XDependentTextField> xField(
+ xMSF->createInstance("com.sun.star.text.TextField.Database"), UNO_QUERY_THROW);
+ xField->attachTextFieldMaster(xFieldMaster);
+ Reference<text::XText> xText = xTextDocument->getText();
+ Reference<text::XTextCursor> xCursor = xText->createTextCursor();
+ Reference<text::XTextContent> xFieldAsContent(xField, UNO_QUERY_THROW);
+ xText->insertTextContent(xCursor, xFieldAsContent, false);
+ return Reference<XInterface>(xField, UNO_QUERY_THROW);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SwXTextField);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/python/xtext.py b/sw/qa/python/xtext.py
index d137cb1f69ce..b8bc25d90e92 100644
--- a/sw/qa/python/xtext.py
+++ b/sw/qa/python/xtext.py
@@ -37,9 +37,11 @@ class TestXText(unittest.TestCase):
# And the same once again, actually not inserted
x_text.insertTextContent(x_cursor, x_annotation, False)
- # Exception if we try to replace object by itself
- with self.assertRaises(IllegalArgumentException):
- x_text.insertTextContent(x_cursor, x_annotation, True)
+ # no exception if we try to replace object by itself:
+ # this did throw in the past, but only because the inserted
+ # UNO annotation had a core object assigned, but no document
+ # which insertTextContent then didnt like on another call.
+ x_text.insertTextContent(x_cursor, x_annotation, True)
# We expect just one annotation actually
self.check_annotations(["John Doe"])
diff --git a/sw/source/core/txtnode/atrfld.cxx b/sw/source/core/txtnode/atrfld.cxx
index 3e7ffb0604fa..6f433b2056f5 100644
--- a/sw/source/core/txtnode/atrfld.cxx
+++ b/sw/source/core/txtnode/atrfld.cxx
@@ -47,7 +47,6 @@
// constructor for default item in attribute-pool
SwFormatField::SwFormatField( sal_uInt16 nWhich )
: SfxPoolItem( nWhich )
- , SwModify(nullptr)
, SfxBroadcaster()
, mpTextField( nullptr )
{
@@ -55,11 +54,11 @@ SwFormatField::SwFormatField( sal_uInt16 nWhich )
SwFormatField::SwFormatField( const SwField &rField )
: SfxPoolItem( RES_TXTATR_FIELD )
- , SwModify( rField.GetTyp() )
, SfxBroadcaster()
, mpField( rField.CopyField() )
, mpTextField( nullptr )
{
+ rField.GetTyp()->Add(this);
if ( mpField->GetTyp()->Which() == SwFieldIds::Input )
{
// input field in-place editing
@@ -93,7 +92,6 @@ SwFormatField::SwFormatField( const SwField &rField )
// corrected
SwFormatField::SwFormatField( const SwFormatField& rAttr )
: SfxPoolItem( rAttr )
- , SwModify(nullptr)
, SfxBroadcaster()
, mpTextField( nullptr )
{
diff --git a/sw/source/core/unocore/unofield.cxx b/sw/source/core/unocore/unofield.cxx
index 14f8f3ca0b98..63614495ab9c 100644
--- a/sw/source/core/unocore/unofield.cxx
+++ b/sw/source/core/unocore/unofield.cxx
@@ -1117,39 +1117,37 @@ struct SwFieldProperties_Impl
};
class SwXTextField::Impl
- : public SwClient, public SvtListener
+ : public SvtListener
{
private:
::osl::Mutex m_Mutex; // just for OInterfaceContainerHelper2
SwFieldType* m_pFieldType;
+ SwFormatField* m_pFormatField;
public:
uno::WeakReference<uno::XInterface> m_wThis;
::comphelper::OInterfaceContainerHelper2 m_EventListeners;
- SwFormatField const* m_pFormatField;
- SwDoc * m_pDoc;
+ SwDoc* m_pDoc;
rtl::Reference<SwTextAPIObject> m_xTextObject;
-
- bool m_bIsDescriptor;
- bool m_bCallUpdate;
- SwServiceType const m_nServiceId;
- OUString m_sTypeName;
+ bool m_bCallUpdate;
+ SwServiceType const m_nServiceId;
+ OUString m_sTypeName;
std::unique_ptr<SwFieldProperties_Impl> m_pProps;
- Impl(SwDoc *const pDoc, SwFormatField *const pFormat,
- SwServiceType nServiceId)
- : SwClient(pFormat)
+ Impl(SwDoc *const pDoc, SwFormatField *const pFormat, SwServiceType nServiceId)
+ : m_pFormatField(pFormat)
, m_EventListeners(m_Mutex)
- , m_pFormatField(pFormat)
, m_pDoc(pDoc)
- , m_bIsDescriptor(pFormat == nullptr)
, m_bCallUpdate(false)
, m_nServiceId(pFormat
? lcl_GetServiceForField(*pFormat->GetField())
: nServiceId)
, m_pProps(pFormat ? nullptr : new SwFieldProperties_Impl)
- { }
+ {
+ if(m_pFormatField)
+ StartListening(m_pFormatField->GetNotifier());
+ }
virtual ~Impl() override
{
@@ -1159,21 +1157,37 @@ public:
}
}
+ void SetFormatField(SwFormatField* pFormatField, SwDoc* pDoc)
+ {
+ m_pFormatField = pFormatField;
+ m_pDoc = pDoc;
+ if(m_pFormatField)
+ {
+ EndListeningAll();
+ StartListening(m_pFormatField->GetNotifier());
+ }
+ }
+ SwFormatField* GetFormatField()
+ {
+ return m_pFormatField;
+ }
+ bool IsDescriptor() const
+ {
+ return !m_pFormatField;
+ }
void Invalidate();
- const SwField* GetField() const;
+ const SwField* GetField() const;
- SwFieldType* GetFieldType()
+ SwFieldType* GetFieldType() const
{
- if (m_bIsDescriptor)
+ if (IsDescriptor())
return m_pFieldType;
- if (!GetRegisteredIn())
- throw uno::RuntimeException();
return m_pFormatField->GetField()->GetTyp();
}
void SetFieldType(SwFieldType& rType)
{
- SvtListener::EndListeningAll();
+ EndListeningAll();
m_pFieldType = &rType;
StartListening(m_pFieldType->GetNotifier());
}
@@ -1182,9 +1196,6 @@ public:
SvtListener::EndListeningAll();
m_pFieldType = nullptr;
}
-protected:
- // SwClient
- virtual void Modify(SfxPoolItem const* pOld, SfxPoolItem const* pNew) override;
virtual void Notify(const SfxHint&) override;
};
@@ -1292,12 +1303,8 @@ void SwXTextField::TransmuteLeadToInputField(SwSetExpField & rField)
uno::Reference<lang::XUnoTunnel>(xField, uno::UNO_QUERY_THROW)
->getSomething(getUnoTunnelId())))
: nullptr;
- if (xField.is())
- {
- assert(pXField->m_pImpl->m_pFormatField == rField.GetFormatField());
- rField.GetFormatField()->Remove(pXField->m_pImpl.get());
- pXField->m_pImpl->m_pFormatField = nullptr;
- }
+ if (pXField)
+ pXField->m_pImpl->SetFormatField(nullptr, nullptr);
SwTextField *const pOldAttr(rField.GetFormatField()->GetTextField());
SwSetExpField tempField(rField);
tempField.SetInputFlag(!rField.GetInputFlag());
@@ -1323,8 +1330,7 @@ void SwXTextField::TransmuteLeadToInputField(SwSetExpField & rField)
assert(static_cast<SwSetExpField const*>(rNewFormat.GetField())->GetInputFlag() == (dynamic_cast<SwTextInputField const*>(pNewAttr) != nullptr));
if (xField.is())
{
- pXField->m_pImpl->m_pFormatField = &rNewFormat;
- const_cast<SwFormatField&>(rNewFormat).Add(pXField->m_pImpl.get());
+ pXField->m_pImpl->SetFormatField(const_cast<SwFormatField*>(&rNewFormat), rNode.GetDoc());
const_cast<SwFormatField&>(rNewFormat).SetXTextField(xField);
}
}
@@ -1334,7 +1340,7 @@ void SAL_CALL SwXTextField::attachTextFieldMaster(
{
SolarMutexGuard aGuard;
- if (!m_pImpl->m_bIsDescriptor)
+ if (!m_pImpl->IsDescriptor())
throw uno::RuntimeException();
uno::Reference< lang::XUnoTunnel > xMasterTunnel(xFieldMaster, uno::UNO_QUERY);
if (!xMasterTunnel.is())
@@ -1378,7 +1384,7 @@ void SAL_CALL SwXTextField::attach(
const uno::Reference< text::XTextRange > & xTextRange)
{
SolarMutexGuard aGuard;
- if (m_pImpl->m_bIsDescriptor)
+ if (m_pImpl->IsDescriptor())
{
uno::Reference<lang::XUnoTunnel> xRangeTunnel( xTextRange, uno::UNO_QUERY);
SwXTextRange* pRange = nullptr;
@@ -2005,7 +2011,7 @@ void SAL_CALL SwXTextField::attach(
throw uno::RuntimeException("no SwTextAttr inserted?"); // could theoretically happen, if paragraph is full
const SwFormatField& rField = pTextAttr->GetFormatField();
- m_pImpl->m_pFormatField = &rField;
+ m_pImpl->SetFormatField(const_cast<SwFormatField*>(&rField), pDoc);
if ( pTextAttr->Which() == RES_TXTATR_ANNOTATION
&& *aPam.GetPoint() != *aPam.GetMark() )
@@ -2022,18 +2028,16 @@ void SAL_CALL SwXTextField::attach(
xField.reset();
- assert(m_pImpl->m_pFormatField);
+ assert(m_pImpl->GetFormatField());
m_pImpl->m_pDoc = pDoc;
- const_cast<SwFormatField *>(m_pImpl->m_pFormatField)->Add(m_pImpl.get());
- const_cast<SwFormatField *>(m_pImpl->m_pFormatField)->SetXTextField(this);
+ m_pImpl->GetFormatField()->SetXTextField(this);
m_pImpl->m_wThis = *this;
- m_pImpl->m_bIsDescriptor = false;
m_pImpl->ClearFieldType();
m_pImpl->m_pProps.reset();
if (m_pImpl->m_bCallUpdate)
update();
}
- else if ( m_pImpl->m_pFormatField != nullptr
+ else if ( !m_pImpl->IsDescriptor()
&& m_pImpl->m_pDoc != nullptr
&& m_pImpl->m_nServiceId == SwServiceType::FieldTypeAnnotation )
{
@@ -2047,14 +2051,14 @@ void SAL_CALL SwXTextField::attach(
{
UnoActionContext aCont( m_pImpl->m_pDoc );
// insert copy of annotation at new text range
- std::unique_ptr<SwPostItField> pPostItField(static_cast< SwPostItField* >(m_pImpl->m_pFormatField->GetField()->CopyField().release()));
+ std::unique_ptr<SwPostItField> pPostItField(static_cast< SwPostItField* >(m_pImpl->GetFormatField()->GetField()->CopyField().release()));
SwFormatField aFormatField( *pPostItField );
pPostItField.reset();
SwPaM aEnd( *aIntPam.End(), *aIntPam.End() );
m_pImpl->m_pDoc->getIDocumentContentOperations().InsertPoolItem( aEnd, aFormatField );
// delete former annotation
{
- const SwTextField* pTextField = m_pImpl->m_pFormatField->GetTextField();
+ const SwTextField* pTextField = m_pImpl->GetFormatField()->GetTextField();
SwTextNode& rTextNode = *pTextField->GetpTextNode();
SwPaM aPam( rTextNode, pTextField->GetStart() );
aPam.SetMark();
@@ -2066,7 +2070,7 @@ void SAL_CALL SwXTextField::attach(
SwTextField* pTextAttr = aEnd.GetNode().GetTextNode()->GetFieldTextAttrAt( aEnd.End()->nContent.GetIndex()-1, true );
if ( pTextAttr != nullptr )
{
- m_pImpl->m_pFormatField = &pTextAttr->GetFormatField();
+ m_pImpl->SetFormatField(const_cast<SwFormatField*>(&pTextAttr->GetFormatField()), m_pImpl->m_pDoc);
if ( *aIntPam.GetPoint() != *aIntPam.GetMark() )
{
@@ -2097,7 +2101,7 @@ SwXTextField::getAnchor()
if (!pField)
return nullptr;
- const SwTextField* pTextField = m_pImpl->m_pFormatField->GetTextField();
+ const SwTextField* pTextField = m_pImpl->GetFormatField()->GetTextField();
if (!pTextField)
throw uno::RuntimeException();
@@ -2130,12 +2134,11 @@ void SAL_CALL SwXTextField::dispose()
{
SolarMutexGuard aGuard;
SwField const*const pField = m_pImpl->GetField();
- if(pField)
+ if(pField && m_pImpl->m_pDoc)
{
UnoActionContext aContext(m_pImpl->m_pDoc);
-
- assert(m_pImpl->m_pFormatField->GetTextField() && "<SwXTextField::dispose()> - missing <SwTextField> --> crash");
- SwTextField::DeleteTextField(*(m_pImpl->m_pFormatField->GetTextField()));
+ assert(m_pImpl->GetFormatField()->GetTextField() && "<SwXTextField::dispose()> - missing <SwTextField> --> crash");
+ SwTextField::DeleteTextField(*(m_pImpl->GetFormatField()->GetTextField()));
}
if (m_pImpl->m_xTextObject.is())
@@ -2143,6 +2146,7 @@ void SAL_CALL SwXTextField::dispose()
m_pImpl->m_xTextObject->DisposeEditSource();
m_pImpl->m_xTextObject.clear();
}
+ m_pImpl->Invalidate();
}
void SAL_CALL SwXTextField::addEventListener(
@@ -2213,7 +2217,7 @@ SwXTextField::setPropertyValue(
{
SwDoc * pDoc = m_pImpl->m_pDoc;
assert(pDoc);
- const SwTextField* pTextField = m_pImpl->m_pFormatField->GetTextField();
+ const SwTextField* pTextField = m_pImpl->GetFormatField()->GetTextField();
if(!pTextField)
throw uno::RuntimeException();
SwPosition aPosition( pTextField->GetTextNode() );
@@ -2222,16 +2226,16 @@ SwXTextField::setPropertyValue(
}
//#i100374# notify SwPostIt about new field content
- if (SwFieldIds::Postit == nWhich && m_pImpl->m_pFormatField)
+ if (SwFieldIds::Postit == nWhich && !m_pImpl->IsDescriptor())
{
- const_cast<SwFormatField*>(m_pImpl->m_pFormatField)->Broadcast(
+ m_pImpl->GetFormatField()->Broadcast(
SwFormatFieldHint( nullptr, SwFormatFieldHintWhich::CHANGED ));
}
// fdo#42073 notify SwTextField about changes of the expanded string
- if (m_pImpl->m_pFormatField->GetTextField())
+ if (m_pImpl->GetFormatField()->GetTextField())
{
- m_pImpl->m_pFormatField->GetTextField()->ExpandTextField();
+ m_pImpl->GetFormatField()->GetTextField()->ExpandTextField();
}
//#i100374# changing a document field should set the modify flag
@@ -2396,9 +2400,9 @@ uno::Any SAL_CALL SwXTextField::getPropertyValue(const OUString& rPropertyName)
// get text node for the text field
const SwFormatField *pFieldFormat =
- (m_pImpl->GetField()) ? m_pImpl->m_pFormatField : nullptr;
+ (m_pImpl->GetField()) ? m_pImpl->GetFormatField() : nullptr;
const SwTextField* pTextField = pFieldFormat
- ? m_pImpl->m_pFormatField->GetTextField() : nullptr;
+ ? m_pImpl->GetFormatField()->GetTextField() : nullptr;
if(!pTextField)
throw uno::RuntimeException();
const SwTextNode& rTextNode = pTextField->GetTextNode();
@@ -2586,7 +2590,7 @@ void SAL_CALL SwXTextField::update()
default: break;
}
// Text formatting has to be triggered.
- const_cast<SwFormatField*>(m_pImpl->m_pFormatField)->ModifyNotification(nullptr, nullptr);
+ m_pImpl->GetFormatField()->ModifyNotification(nullptr, nullptr);
}
else
m_pImpl->m_bCallUpdate = true;
@@ -2637,56 +2641,38 @@ uno::Sequence< OUString > SAL_CALL SwXTextField::getSupportedServiceNames()
void SwXTextField::Impl::Invalidate()
{
- if (GetRegisteredIn())
- {
- SwClient::EndListeningAll();
- m_pFormatField = nullptr;
- m_pDoc = nullptr;
- uno::Reference<uno::XInterface> const xThis(m_wThis);
- if (!xThis.is())
- { // fdo#72695: if UNO object is already dead, don't revive it with event
- return;
- }
- lang::EventObject const ev(xThis);
- m_EventListeners.disposeAndClear(ev);
- }
-}
-
-void SwXTextField::Impl::Modify(
- SfxPoolItem const*const pOld, SfxPoolItem const*const pNew)
-{
- switch( pOld ? pOld->Which() : 0 )
- {
- case RES_REMOVE_UNO_OBJECT:
- case RES_OBJECTDYING:
- if( static_cast<void*>(GetRegisteredIn()) == static_cast<const SwPtrMsgPoolItem *>(pOld)->pObject )
- Invalidate();
- break;
-
- case RES_FMT_CHG:
- // Am I re-attached to a new one and will the old one be deleted?
- if( static_cast<const SwFormatChg*>(pNew)->pChangedFormat == GetRegisteredIn() &&
- static_cast<const SwFormatChg*>(pOld)->pChangedFormat->IsFormatInDTOR() )
- Invalidate();
- break;
+ EndListeningAll();
+ m_pFormatField = nullptr;
+ m_pDoc = nullptr;
+ uno::Reference<uno::XInterface> const xThis(m_wThis);
+ if (!xThis.is())
+ { // fdo#72695: if UNO object is already dead, don't revive it with event
+ return;
}
+ lang::EventObject const ev(xThis);
+ m_EventListeners.disposeAndClear(ev);
}
void SwXTextField::Impl::Notify(const SfxHint& rHint)
{
+
if(rHint.GetId() == SfxHintId::Dying)
+ Invalidate();
+ else if (auto pLegacyHint = dynamic_cast<const sw::LegacyModifyHint*>(&rHint))
{
- m_pFieldType = nullptr;
+ switch(pLegacyHint->m_pOld ? pLegacyHint->m_pOld->Which() : 0)
+ {
+ case RES_REMOVE_UNO_OBJECT:
+ case RES_OBJECTDYING:
+ Invalidate();
+ break;
+ }
}
}
-const SwField* SwXTextField::Impl::GetField() const
+const SwField* SwXTextField::Impl::GetField() const
{
- if (GetRegisteredIn() && m_pFormatField)
- {
- return m_pFormatField->GetField();
- }
- return nullptr;
+ return IsDescriptor() ? nullptr : m_pFormatField->GetField();
}
OUString SwXTextFieldMasters::getImplementationName()