tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / dbaccess / source / core / dataaccess / documenteventnotifier.cxx
bloba5c678579253fad8959a6e94755c077768edbc36
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "documenteventnotifier.hxx"
22 #include <com/sun/star/frame/DoubleInitializationException.hpp>
24 #include <comphelper/asyncnotification.hxx>
25 #include <comphelper/interfacecontainer3.hxx>
26 #include <cppuhelper/weak.hxx>
27 #include <comphelper/diagnose_ex.hxx>
28 #include <vcl/svapp.hxx>
30 namespace dbaccess
33 using ::com::sun::star::uno::Reference;
34 using ::com::sun::star::uno::Exception;
35 using ::com::sun::star::uno::Any;
36 using ::com::sun::star::frame::DoubleInitializationException;
37 using ::com::sun::star::document::XDocumentEventListener;
38 using ::com::sun::star::document::DocumentEvent;
39 using ::com::sun::star::frame::XController2;
41 using namespace ::com::sun::star;
43 // DocumentEventNotifier_Impl
44 class DocumentEventNotifier_Impl : public ::comphelper::IEventProcessor
46 oslInterlockedCount m_refCount;
47 ::cppu::OWeakObject& m_rDocument;
48 ::osl::Mutex& m_rMutex;
49 bool m_bInitialized;
50 bool m_bDisposed;
51 std::shared_ptr<::comphelper::AsyncEventNotifierAutoJoin> m_pEventBroadcaster;
52 ::comphelper::OInterfaceContainerHelper3<css::document::XEventListener> m_aLegacyEventListeners;
53 ::comphelper::OInterfaceContainerHelper3<XDocumentEventListener> m_aDocumentEventListeners;
55 public:
56 DocumentEventNotifier_Impl( ::cppu::OWeakObject& _rBroadcasterDocument, ::osl::Mutex& _rMutex )
57 :m_refCount( 0 )
58 ,m_rDocument( _rBroadcasterDocument )
59 ,m_rMutex( _rMutex )
60 ,m_bInitialized( false )
61 ,m_bDisposed( false )
62 ,m_aLegacyEventListeners( _rMutex )
63 ,m_aDocumentEventListeners( _rMutex )
67 // IEventProcessor
68 virtual void SAL_CALL acquire() noexcept override;
69 virtual void SAL_CALL release() noexcept override;
71 void addLegacyEventListener( const Reference< document::XEventListener >& Listener )
73 m_aLegacyEventListeners.addInterface( Listener );
76 void removeLegacyEventListener( const Reference< document::XEventListener >& Listener )
78 m_aLegacyEventListeners.removeInterface( Listener );
81 void addDocumentEventListener( const Reference< XDocumentEventListener >& Listener )
83 m_aDocumentEventListeners.addInterface( Listener );
86 void removeDocumentEventListener( const Reference< XDocumentEventListener >& Listener )
88 m_aDocumentEventListeners.removeInterface( Listener );
91 void disposing();
93 void onDocumentInitialized();
95 void notifyDocumentEvent( const OUString& EventName, const Reference< XController2 >& ViewController,
96 const Any& Supplement )
98 impl_notifyEvent_nothrow( DocumentEvent(
99 m_rDocument, EventName, ViewController, Supplement ) );
102 void notifyDocumentEventAsync( const OUString& EventName, const Reference< XController2 >& ViewController,
103 const Any& Supplement )
105 impl_notifyEventAsync_nothrow( DocumentEvent(
106 m_rDocument, EventName, ViewController, Supplement ) );
109 protected:
110 virtual ~DocumentEventNotifier_Impl()
114 // IEventProcessor
115 virtual void processEvent( const ::comphelper::AnyEvent& _rEvent ) override;
117 private:
118 void impl_notifyEvent_nothrow( const DocumentEvent& _rEvent );
119 void impl_notifyEventAsync_nothrow( const DocumentEvent& _rEvent );
122 void SAL_CALL DocumentEventNotifier_Impl::acquire() noexcept
124 osl_atomic_increment( &m_refCount );
127 void SAL_CALL DocumentEventNotifier_Impl::release() noexcept
129 if ( 0 == osl_atomic_decrement( &m_refCount ) )
130 delete this;
133 void DocumentEventNotifier_Impl::disposing()
135 // SYNCHRONIZED ->
136 // cancel any pending asynchronous events
137 ::osl::ResettableMutexGuard aGuard( m_rMutex );
138 if (m_pEventBroadcaster)
140 m_pEventBroadcaster->removeEventsForProcessor( this );
141 m_pEventBroadcaster->terminate();
144 auto xEventBroadcaster = std::exchange(m_pEventBroadcaster, {});
146 lang::EventObject aEvent( m_rDocument );
147 aGuard.clear();
148 // <-- SYNCHRONIZED
150 if (xEventBroadcaster)
152 comphelper::SolarMutex& rSolarMutex = Application::GetSolarMutex();
153 // unblock threads blocked on that so we can join
154 sal_uInt32 nLockCount = (rSolarMutex.IsCurrentThread()) ? rSolarMutex.release(true) : 0;
155 xEventBroadcaster->join();
156 if (nLockCount)
157 rSolarMutex.acquire(nLockCount);
158 xEventBroadcaster.reset();
160 m_aLegacyEventListeners.disposeAndClear( aEvent );
161 m_aDocumentEventListeners.disposeAndClear( aEvent );
163 // SYNCHRONIZED ->
164 aGuard.reset();
165 m_bDisposed = true;
166 // <-- SYNCHRONIZED
169 void DocumentEventNotifier_Impl::onDocumentInitialized()
171 if ( m_bInitialized )
172 throw DoubleInitializationException();
174 m_bInitialized = true;
175 if (m_pEventBroadcaster)
177 // there are already pending asynchronous events
178 ::comphelper::AsyncEventNotifierAutoJoin::launch(m_pEventBroadcaster);
182 void DocumentEventNotifier_Impl::impl_notifyEvent_nothrow( const DocumentEvent& _rEvent )
184 OSL_PRECOND( m_bInitialized,
185 "DocumentEventNotifier_Impl::impl_notifyEvent_nothrow: only to be called when the document is already initialized!" );
188 document::EventObject aLegacyEvent( _rEvent.Source, _rEvent.EventName );
189 m_aLegacyEventListeners.notifyEach( &document::XEventListener::notifyEvent, aLegacyEvent );
191 catch(const Exception&)
193 DBG_UNHANDLED_EXCEPTION("dbaccess");
197 m_aDocumentEventListeners.notifyEach( &XDocumentEventListener::documentEventOccured, _rEvent );
199 catch( const Exception& )
201 DBG_UNHANDLED_EXCEPTION("dbaccess");
205 void DocumentEventNotifier_Impl::impl_notifyEventAsync_nothrow( const DocumentEvent& _rEvent )
207 if (!m_pEventBroadcaster)
209 m_pEventBroadcaster = ::comphelper::AsyncEventNotifierAutoJoin
210 ::newAsyncEventNotifierAutoJoin("DocumentEventNotifier");
211 if ( m_bInitialized )
213 // start processing the events if and only if we (our document, respectively) are
214 // already initialized
215 ::comphelper::AsyncEventNotifierAutoJoin::launch(m_pEventBroadcaster);
218 m_pEventBroadcaster->addEvent( new comphelper::DocumentEventHolder( _rEvent ), this );
221 void DocumentEventNotifier_Impl::processEvent( const ::comphelper::AnyEvent& _rEvent )
223 // beware, this is called from the notification thread
225 ::osl::MutexGuard aGuard( m_rMutex );
226 if ( m_bDisposed )
227 return;
229 const comphelper::DocumentEventHolder& rEventHolder = dynamic_cast< const comphelper::DocumentEventHolder& >( _rEvent );
230 impl_notifyEvent_nothrow( rEventHolder.getEventObject() );
233 // DocumentEventNotifier
234 DocumentEventNotifier::DocumentEventNotifier( ::cppu::OWeakObject& _rBroadcasterDocument, ::osl::Mutex& _rMutex )
235 :m_pImpl( new DocumentEventNotifier_Impl( _rBroadcasterDocument, _rMutex ) )
239 DocumentEventNotifier::~DocumentEventNotifier()
243 void DocumentEventNotifier::disposing()
245 m_pImpl->disposing();
248 void DocumentEventNotifier::onDocumentInitialized()
250 m_pImpl->onDocumentInitialized();
253 void DocumentEventNotifier::addLegacyEventListener( const Reference< document::XEventListener >& Listener )
255 m_pImpl->addLegacyEventListener( Listener );
258 void DocumentEventNotifier::removeLegacyEventListener( const Reference< document::XEventListener >& Listener )
260 m_pImpl->removeLegacyEventListener( Listener );
263 void DocumentEventNotifier::addDocumentEventListener( const Reference< XDocumentEventListener >& Listener )
265 m_pImpl->addDocumentEventListener( Listener );
268 void DocumentEventNotifier::removeDocumentEventListener( const Reference< XDocumentEventListener >& Listener )
270 m_pImpl->removeDocumentEventListener( Listener );
273 void DocumentEventNotifier::notifyDocumentEvent( const OUString& EventName,
274 const Reference< XController2 >& ViewController, const Any& Supplement )
276 m_pImpl->notifyDocumentEvent( EventName, ViewController, Supplement );
279 void DocumentEventNotifier::notifyDocumentEventAsync( const OUString& EventName,
280 const Reference< XController2 >& ViewController, const Any& Supplement )
282 m_pImpl->notifyDocumentEventAsync( EventName, ViewController, Supplement );
285 } // namespace dbaccess
287 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */