1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <sfx2/viewfrm.hxx>
21 #include <svx/dataaccessdescriptor.hxx>
22 #include <svl/hint.hxx>
23 #include <vcl/svapp.hxx>
25 #include <com/sun/star/frame/XDispatchProviderInterception.hpp>
26 #include <com/sun/star/view/XSelectionSupplier.hpp>
27 #include <com/sun/star/sdb/CommandType.hpp>
29 #include <dispuno.hxx>
30 #include <tabvwsh.hxx>
31 #include <dbdocfun.hxx>
34 using namespace com::sun::star
;
36 const char cURLInsertColumns
[] = ".uno:DataSourceBrowser/InsertColumns"; //data into text
37 constexpr OUString cURLDocDataSource
= u
".uno:DataSourceBrowser/DocumentDataSource"_ustr
;
39 static uno::Reference
<view::XSelectionSupplier
> lcl_GetSelectionSupplier( const SfxViewShell
* pViewShell
)
43 SfxViewFrame
& rViewFrame
= pViewShell
->GetViewFrame();
44 return uno::Reference
<view::XSelectionSupplier
>( rViewFrame
.GetFrame().GetController(), uno::UNO_QUERY
);
46 return uno::Reference
<view::XSelectionSupplier
>();
49 ScDispatchProviderInterceptor::ScDispatchProviderInterceptor(ScTabViewShell
* pViewSh
) :
55 m_xIntercepted
.set(uno::Reference
<frame::XDispatchProviderInterception
>(pViewShell
->GetViewFrame().GetFrame().GetFrameInterface(), uno::UNO_QUERY
));
56 if (m_xIntercepted
.is())
58 osl_atomic_increment( &m_refCount
);
60 m_xIntercepted
->registerDispatchProviderInterceptor(
61 static_cast<frame::XDispatchProviderInterceptor
*>(this));
62 // this should make us the top-level dispatch-provider for the component, via a call to our
63 // setDispatchProvider we should have got a fallback for requests we (i.e. our master) cannot fulfill
64 uno::Reference
<lang::XComponent
> xInterceptedComponent(m_xIntercepted
, uno::UNO_QUERY
);
65 if (xInterceptedComponent
.is())
66 xInterceptedComponent
->addEventListener(static_cast<lang::XEventListener
*>(this));
68 osl_atomic_decrement( &m_refCount
);
71 StartListening(*pViewShell
);
74 ScDispatchProviderInterceptor::~ScDispatchProviderInterceptor()
77 EndListening(*pViewShell
);
80 void ScDispatchProviderInterceptor::Notify( SfxBroadcaster
&, const SfxHint
& rHint
)
82 if ( rHint
.GetId() == SfxHintId::Dying
)
88 uno::Reference
<frame::XDispatch
> SAL_CALL
ScDispatchProviderInterceptor::queryDispatch(
89 const util::URL
& aURL
, const OUString
& aTargetFrameName
,
90 sal_Int32 nSearchFlags
)
92 SolarMutexGuard aGuard
;
94 uno::Reference
<frame::XDispatch
> xResult
;
95 // create some dispatch ...
97 aURL
.Complete
== cURLInsertColumns
||
98 aURL
.Complete
== cURLDocDataSource
) )
100 if (!m_xMyDispatch
.is())
101 m_xMyDispatch
= new ScDispatch( pViewShell
);
102 xResult
= m_xMyDispatch
;
105 // ask our slave provider
106 if (!xResult
.is() && m_xSlaveDispatcher
.is())
107 xResult
= m_xSlaveDispatcher
->queryDispatch(aURL
, aTargetFrameName
, nSearchFlags
);
112 uno::Sequence
< uno::Reference
<frame::XDispatch
> > SAL_CALL
113 ScDispatchProviderInterceptor::queryDispatches(
114 const uno::Sequence
<frame::DispatchDescriptor
>& aDescripts
)
116 SolarMutexGuard aGuard
;
118 uno::Sequence
< uno::Reference
< frame::XDispatch
> > aReturn(aDescripts
.getLength());
119 std::transform(aDescripts
.begin(), aDescripts
.end(), aReturn
.getArray(),
120 [this](const frame::DispatchDescriptor
& rDescr
) -> uno::Reference
<frame::XDispatch
> {
121 return queryDispatch(rDescr
.FeatureURL
, rDescr
.FrameName
, rDescr
.SearchFlags
); });
125 // XDispatchProviderInterceptor
127 uno::Reference
<frame::XDispatchProvider
> SAL_CALL
128 ScDispatchProviderInterceptor::getSlaveDispatchProvider()
130 SolarMutexGuard aGuard
;
131 return m_xSlaveDispatcher
;
134 void SAL_CALL
ScDispatchProviderInterceptor::setSlaveDispatchProvider(
135 const uno::Reference
<frame::XDispatchProvider
>& xNewDispatchProvider
)
137 SolarMutexGuard aGuard
;
138 m_xSlaveDispatcher
.set(xNewDispatchProvider
);
141 uno::Reference
<frame::XDispatchProvider
> SAL_CALL
142 ScDispatchProviderInterceptor::getMasterDispatchProvider()
144 SolarMutexGuard aGuard
;
145 return m_xMasterDispatcher
;
148 void SAL_CALL
ScDispatchProviderInterceptor::setMasterDispatchProvider(
149 const uno::Reference
<frame::XDispatchProvider
>& xNewSupplier
)
151 SolarMutexGuard aGuard
;
152 m_xMasterDispatcher
.set(xNewSupplier
);
157 void SAL_CALL
ScDispatchProviderInterceptor::disposing( const lang::EventObject
& /* Source */ )
159 SolarMutexGuard aGuard
;
161 if (m_xIntercepted
.is())
163 m_xIntercepted
->releaseDispatchProviderInterceptor(
164 static_cast<frame::XDispatchProviderInterceptor
*>(this));
165 uno::Reference
<lang::XComponent
> xInterceptedComponent(m_xIntercepted
, uno::UNO_QUERY
);
166 if (xInterceptedComponent
.is())
167 xInterceptedComponent
->removeEventListener(static_cast<lang::XEventListener
*>(this));
169 m_xMyDispatch
= nullptr;
171 m_xIntercepted
= nullptr;
174 ScDispatch::ScDispatch(ScTabViewShell
* pViewSh
) :
175 pViewShell( pViewSh
),
176 bListeningToView( false )
179 StartListening(*pViewShell
);
182 ScDispatch::~ScDispatch()
185 EndListening(*pViewShell
);
187 if (bListeningToView
&& pViewShell
)
189 uno::Reference
<view::XSelectionSupplier
> xSupplier(lcl_GetSelectionSupplier( pViewShell
));
190 if ( xSupplier
.is() )
191 xSupplier
->removeSelectionChangeListener(this);
195 void ScDispatch::Notify( SfxBroadcaster
&, const SfxHint
& rHint
)
197 if ( rHint
.GetId() == SfxHintId::Dying
)
198 pViewShell
= nullptr;
203 void SAL_CALL
ScDispatch::dispatch( const util::URL
& aURL
,
204 const uno::Sequence
<beans::PropertyValue
>& aArgs
)
206 SolarMutexGuard aGuard
;
209 if ( pViewShell
&& aURL
.Complete
== cURLInsertColumns
)
211 ScViewData
& rViewData
= pViewShell
->GetViewData();
212 ScAddress
aPos( rViewData
.GetCurX(), rViewData
.GetCurY(), rViewData
.GetTabNo() );
214 ScDBDocFunc
aFunc( *rViewData
.GetDocShell() );
215 aFunc
.DoImportUno( aPos
, aArgs
);
218 // cURLDocDataSource is never dispatched
221 throw uno::RuntimeException();
224 static void lcl_FillDataSource( frame::FeatureStateEvent
& rEvent
, const ScImportParam
& rParam
)
226 rEvent
.IsEnabled
= rParam
.bImport
;
228 svx::ODataAccessDescriptor aDescriptor
;
229 if ( rParam
.bImport
)
231 sal_Int32 nType
= rParam
.bSql
? sdb::CommandType::COMMAND
:
232 ( (rParam
.nType
== ScDbQuery
) ? sdb::CommandType::QUERY
:
233 sdb::CommandType::TABLE
);
235 aDescriptor
.setDataSource(rParam
.aDBName
);
236 aDescriptor
[svx::DataAccessDescriptorProperty::Command
] <<= rParam
.aStatement
;
237 aDescriptor
[svx::DataAccessDescriptorProperty::CommandType
] <<= nType
;
241 // descriptor has to be complete anyway
243 aDescriptor
[svx::DataAccessDescriptorProperty::DataSource
] <<= OUString();
244 aDescriptor
[svx::DataAccessDescriptorProperty::Command
] <<= OUString();
245 aDescriptor
[svx::DataAccessDescriptorProperty::CommandType
] <<= sal_Int32(sdb::CommandType::TABLE
);
247 rEvent
.State
<<= aDescriptor
.createPropertyValueSequence();
250 void SAL_CALL
ScDispatch::addStatusListener(
251 const uno::Reference
<frame::XStatusListener
>& xListener
,
252 const util::URL
& aURL
)
254 SolarMutexGuard aGuard
;
257 throw uno::RuntimeException();
260 frame::FeatureStateEvent aEvent
;
261 aEvent
.IsEnabled
= true;
262 aEvent
.Source
= getXWeak();
263 aEvent
.FeatureURL
= aURL
;
265 if ( aURL
.Complete
== cURLDocDataSource
)
267 aDataSourceListeners
.emplace_back( xListener
);
269 if (!bListeningToView
)
271 uno::Reference
<view::XSelectionSupplier
> xSupplier(lcl_GetSelectionSupplier( pViewShell
));
272 if ( xSupplier
.is() )
273 xSupplier
->addSelectionChangeListener(this);
274 bListeningToView
= true;
277 ScDBData
* pDBData
= pViewShell
->GetDBData(false,SC_DB_OLD
);
279 pDBData
->GetImportParam( aLastImport
);
280 lcl_FillDataSource( aEvent
, aLastImport
); // modifies State, IsEnabled
282 //! else add to listener for "enabled" changes?
284 xListener
->statusChanged( aEvent
);
287 void SAL_CALL
ScDispatch::removeStatusListener(
288 const uno::Reference
<frame::XStatusListener
>& xListener
,
289 const util::URL
& aURL
)
291 SolarMutexGuard aGuard
;
293 if ( aURL
.Complete
!= cURLDocDataSource
)
296 sal_uInt16 nCount
= aDataSourceListeners
.size();
297 for ( sal_uInt16 n
=nCount
; n
--; )
299 uno::Reference
<frame::XStatusListener
>& rObj
= aDataSourceListeners
[n
];
300 if ( rObj
== xListener
)
302 aDataSourceListeners
.erase( aDataSourceListeners
.begin() + n
);
307 if ( aDataSourceListeners
.empty() && pViewShell
)
309 uno::Reference
<view::XSelectionSupplier
> xSupplier(lcl_GetSelectionSupplier( pViewShell
));
310 if ( xSupplier
.is() )
311 xSupplier
->removeSelectionChangeListener(this);
312 bListeningToView
= false;
316 // XSelectionChangeListener
318 void SAL_CALL
ScDispatch::selectionChanged( const css::lang::EventObject
& /* aEvent */ )
320 // currently only called for URL cURLDocDataSource
325 ScImportParam aNewImport
;
326 ScDBData
* pDBData
= pViewShell
->GetDBData(false,SC_DB_OLD
);
328 pDBData
->GetImportParam( aNewImport
);
330 // notify listeners only if data source has changed
331 if ( !(aNewImport
.bImport
!= aLastImport
.bImport
||
332 aNewImport
.aDBName
!= aLastImport
.aDBName
||
333 aNewImport
.aStatement
!= aLastImport
.aStatement
||
334 aNewImport
.bSql
!= aLastImport
.bSql
||
335 aNewImport
.nType
!= aLastImport
.nType
) )
338 frame::FeatureStateEvent aEvent
;
339 aEvent
.Source
= getXWeak();
340 aEvent
.FeatureURL
.Complete
= cURLDocDataSource
;
342 lcl_FillDataSource( aEvent
, aNewImport
); // modifies State, IsEnabled
344 for (uno::Reference
<frame::XStatusListener
> & xDataSourceListener
: aDataSourceListeners
)
345 xDataSourceListener
->statusChanged( aEvent
);
347 aLastImport
= aNewImport
;
352 void SAL_CALL
ScDispatch::disposing( const css::lang::EventObject
& rSource
)
354 uno::Reference
<view::XSelectionSupplier
> xSupplier(rSource
.Source
, uno::UNO_QUERY
);
355 xSupplier
->removeSelectionChangeListener(this);
356 bListeningToView
= false;
358 lang::EventObject aEvent
;
359 aEvent
.Source
= getXWeak();
360 for (uno::Reference
<frame::XStatusListener
> & xDataSourceListener
: aDataSourceListeners
)
361 xDataSourceListener
->disposing( aEvent
);
363 pViewShell
= nullptr;
366 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */