[Libreoffice-commits] core.git: sw/inc sw/source

Miklos Vajna vmiklos at collabora.co.uk
Wed Jun 10 10:05:36 PDT 2015


 sw/inc/dbmgr.hxx                |   10 +++-
 sw/source/core/doc/docnew.cxx   |    6 ++
 sw/source/uibase/app/applab.cxx |    2 
 sw/source/uibase/dbui/dbmgr.cxx |  100 +++++++++++++++++++++++++++++++++++++++-
 4 files changed, 114 insertions(+), 4 deletions(-)

New commits:
commit b8b4ac9e6e8f03fb84bddb714d3c5908a45153b1
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Wed Jun 10 19:04:04 2015 +0200

    sw: remove embedded data source on location deregistration
    
    Change-Id: I5b2a24fee50a25a41ba26787f7e30409348d7808

diff --git a/sw/inc/dbmgr.hxx b/sw/inc/dbmgr.hxx
index 5bf1542..0b809f9 100644
--- a/sw/inc/dbmgr.hxx
+++ b/sw/inc/dbmgr.hxx
@@ -184,6 +184,7 @@ struct SwMergeDescriptor
 struct SwDBManager_Impl;
 class SwConnectionDisposedListener_Impl;
 class AbstractMailMergeDlg;
+class SwDoc;
 
 class SW_DLLPUBLIC SwDBManager
 {
@@ -205,6 +206,9 @@ friend class SwConnectionDisposedListener_Impl;
     /// Name of the embedded database that's included in the current document.
     OUString     m_sEmbeddedName;
 
+    /// The document that owns this manager.
+    SwDoc* m_pDoc;
+
     SAL_DLLPRIVATE SwDSParam*          FindDSData(const SwDBData& rData, bool bCreate);
     SAL_DLLPRIVATE SwDSParam*          FindDSConnection(const OUString& rSource, bool bCreate);
 
@@ -222,7 +226,7 @@ friend class SwConnectionDisposedListener_Impl;
     SAL_DLLPRIVATE bool          ToNextRecord(SwDSParam* pParam);
 
 public:
-    SwDBManager();
+    SwDBManager(SwDoc* pDoc);
     ~SwDBManager();
 
     enum DBConnURITypes {
@@ -421,6 +425,10 @@ public:
                                         const css::uno::Reference<css::embed::XStorage>& xStorage,
                                         const OUString& rStreamRelPath,
                                         const OUString& rOwnURL);
+
+    SwDoc* getDoc() const;
+    /// Stop reacting to removed database registrations.
+    void releaseRevokeListener();
 };
 
 #endif
diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index ef6b904..939f270 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -343,7 +343,7 @@ SwDoc::SwDoc()
 
 #if HAVE_FEATURE_DBCONNECTIVITY
     // Create DBManager
-    mpDBManager = new SwDBManager;
+    mpDBManager = new SwDBManager(this);
 #endif
 
     // create TOXTypes
@@ -543,7 +543,11 @@ SwDoc::~SwDoc()
     // On load, SwDBManager::setEmbeddedName() may register a data source.
     // If we have an embedded one, then sDataSoure points to the registered name, so revoke it here.
     if (!mpDBManager->getEmbeddedName().isEmpty() && !maDBData.sDataSource.isEmpty())
+    {
+        // Remove the revoke listener here first, so that we don't remove the data source from the document.
+        mpDBManager->releaseRevokeListener();
         SwDBManager::RevokeDataSource(maDBData.sDataSource);
+    }
 
     DELETEZ( mpDBManager );
 #endif
diff --git a/sw/source/uibase/app/applab.cxx b/sw/source/uibase/app/applab.cxx
index 2521c99..4858f89 100644
--- a/sw/source/uibase/app/applab.cxx
+++ b/sw/source/uibase/app/applab.cxx
@@ -159,7 +159,7 @@ void SwModule::InsertLab(SfxRequest& rReq, bool bLabel)
 
 #if HAVE_FEATURE_DBCONNECTIVITY
     // Create DB-Manager
-    boost::scoped_ptr<SwDBManager> pDBManager(new SwDBManager);
+    boost::scoped_ptr<SwDBManager> pDBManager(new SwDBManager(0));
 #endif
 
     // Read SwLabItem from Config
diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx
index 6dc0bb4..48077f6 100644
--- a/sw/source/uibase/dbui/dbmgr.cxx
+++ b/sw/source/uibase/dbui/dbmgr.cxx
@@ -204,11 +204,90 @@ public:
 
 };
 
+/// Listens to removed data sources, and if it's one that's embedded into this document, triggers embedding removal.
+class SwDataSourceRemovedListener : public cppu::WeakImplHelper<sdb::XDatabaseRegistrationsListener>
+{
+    uno::Reference<sdb::XDatabaseContext> m_xDatabaseContext;
+    SwDBManager* m_pDBManager;
+
+public:
+    SwDataSourceRemovedListener(SwDBManager& rDBManager);
+    virtual ~SwDataSourceRemovedListener();
+    virtual void SAL_CALL registeredDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
+    virtual void SAL_CALL revokedDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
+    virtual void SAL_CALL changedDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
+    virtual void SAL_CALL disposing(const lang::EventObject& rObject) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
+    void Dispose();
+};
+
+SwDataSourceRemovedListener::SwDataSourceRemovedListener(SwDBManager& rDBManager)
+    : m_pDBManager(&rDBManager)
+{
+    uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
+    m_xDatabaseContext = sdb::DatabaseContext::create(xComponentContext);
+    m_xDatabaseContext->addDatabaseRegistrationsListener(this);
+}
+
+SwDataSourceRemovedListener::~SwDataSourceRemovedListener()
+{
+    if (m_xDatabaseContext.is())
+        m_xDatabaseContext->removeDatabaseRegistrationsListener(this);
+}
+
+void SAL_CALL SwDataSourceRemovedListener::registeredDatabaseLocation(const sdb::DatabaseRegistrationEvent& /*rEvent*/) throw (uno::RuntimeException, std::exception)
+{
+}
+
+void SAL_CALL SwDataSourceRemovedListener::revokedDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) throw (uno::RuntimeException, std::exception)
+{
+    if (!m_pDBManager || m_pDBManager->getEmbeddedName().isEmpty())
+        return;
+
+    SwDoc* pDoc = m_pDBManager->getDoc();
+    if (!pDoc)
+        return;
+
+    SwDocShell* pDocShell = pDoc->GetDocShell();
+    if (!pDocShell)
+        return;
+
+    OUString aOwnURL = pDocShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_WITH_CHARSET);
+    OUString sTmpName = "vnd.sun.star.pkg://";
+    sTmpName += INetURLObject::encode(aOwnURL, INetURLObject::PART_AUTHORITY, INetURLObject::ENCODE_ALL);
+    sTmpName += "/" + m_pDBManager->getEmbeddedName();
+
+    if (sTmpName != rEvent.OldLocation)
+        return;
+
+    // The revoked database location is inside this document, then remove the
+    // embedding, as otherwise it would be back on the next reload of the
+    // document.
+    pDocShell->GetStorage()->removeElement(m_pDBManager->getEmbeddedName());
+    m_pDBManager->setEmbeddedName(OUString(), *pDocShell);
+}
+
+void SAL_CALL SwDataSourceRemovedListener::changedDatabaseLocation(const sdb::DatabaseRegistrationEvent& rEvent) throw (uno::RuntimeException, std::exception)
+{
+    if (rEvent.OldLocation != rEvent.NewLocation)
+        revokedDatabaseLocation(rEvent);
+}
+
+void SwDataSourceRemovedListener::disposing(const lang::EventObject& /*rObject*/) throw (uno::RuntimeException, std::exception)
+{
+    m_xDatabaseContext.clear();
+}
+
+void SwDataSourceRemovedListener::Dispose()
+{
+    m_pDBManager = 0;
+}
+
 struct SwDBManager_Impl
 {
     SwDSParam*          pMergeData;
     AbstractMailMergeDlg*     pMergeDialog;
     ::rtl::Reference<SwConnectionDisposedListener_Impl> m_xDisposeListener;
+    rtl::Reference<SwDataSourceRemovedListener> m_xDataSourceRemovedListener;
 
     explicit SwDBManager_Impl(SwDBManager& rDBManager)
        :pMergeData(0)
@@ -219,6 +298,8 @@ struct SwDBManager_Impl
     ~SwDBManager_Impl()
     {
         m_xDisposeListener->Dispose();
+        if (m_xDataSourceRemovedListener.is())
+            m_xDataSourceRemovedListener->Dispose();
     }
 };
 
@@ -693,7 +774,7 @@ void SwDBManager::GetColumnNames(ListBox* pListBox,
     }
 }
 
-SwDBManager::SwDBManager()
+SwDBManager::SwDBManager(SwDoc* pDoc)
     : bCancel(false)
     , bInitDBFields(false)
     , bSingleJobs(false)
@@ -702,6 +783,7 @@ SwDBManager::SwDBManager()
     , bMergeLock(false)
     , pImpl(new SwDBManager_Impl(*this))
     , pMergeEvtSrc(NULL)
+    , m_pDoc(pDoc)
 {
 }
 
@@ -2973,6 +3055,7 @@ uno::Reference<sdbc::XResultSet> SwDBManager::createCursor(const OUString& _sDat
 void SwDBManager::setEmbeddedName(const OUString& rEmbeddedName, SwDocShell& rDocShell)
 {
     bool bLoad = m_sEmbeddedName != rEmbeddedName && !rEmbeddedName.isEmpty();
+    bool bRegisterListener = m_sEmbeddedName.isEmpty() && !rEmbeddedName.isEmpty();
 
     m_sEmbeddedName = rEmbeddedName;
 
@@ -2984,6 +3067,10 @@ void SwDBManager::setEmbeddedName(const OUString& rEmbeddedName, SwDocShell& rDo
         if (xStorage->hasByName(rEmbeddedName))
             LoadAndRegisterEmbeddedDataSource(rDocShell.GetDoc()->GetDBData(), rDocShell);
     }
+
+    if (bRegisterListener)
+        // Register a remove listener, so we know when the embedded data source is removed.
+        pImpl->m_xDataSourceRemovedListener = new SwDataSourceRemovedListener(*this);
 }
 
 OUString SwDBManager::getEmbeddedName() const
@@ -2991,6 +3078,17 @@ OUString SwDBManager::getEmbeddedName() const
     return m_sEmbeddedName;
 }
 
+SwDoc* SwDBManager::getDoc() const
+{
+    return m_pDoc;
+}
+
+void SwDBManager::releaseRevokeListener()
+{
+    pImpl->m_xDataSourceRemovedListener->Dispose();
+    pImpl->m_xDataSourceRemovedListener.clear();
+}
+
 SwConnectionDisposedListener_Impl::SwConnectionDisposedListener_Impl(SwDBManager& rManager)
     : m_pDBManager(&rManager)
 {


More information about the Libreoffice-commits mailing list