LibreOffice Module fpicker (master) 1
commonpicker.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20
21#include "commonpicker.hxx"
22#include "fpdialogbase.hxx"
24#include <com/sun/star/beans/PropertyAttribute.hpp>
25#include <com/sun/star/beans/PropertyValue.hpp>
26#include <com/sun/star/beans/NamedValue.hpp>
27#include <vcl/svapp.hxx>
28#include <vcl/window.hxx>
29#include <osl/mutex.hxx>
30#include <sal/log.hxx>
31#include <tools/debug.hxx>
34#include <comphelper/types.hxx>
35
36
37namespace svt
38{
39
40
41#define PROPERTY_ID_HELPURL 1
42#define PROPERTY_ID_WINDOW 2
43
44 // using --------------------------------------------------------------
45
46 using namespace ::com::sun::star::lang;
47 using namespace ::com::sun::star::ui::dialogs;
48 using namespace ::com::sun::star::uno;
49 using namespace ::com::sun::star::beans;
50 using namespace ::comphelper;
51
52
55 ,OPropertyContainer( GetBroadcastHelper() )
56 ,m_nCancelEvent( nullptr )
57 ,m_bExecuting( false )
58 {
59 // the two properties we have
61 "HelpURL", PROPERTY_ID_HELPURL,
62 PropertyAttribute::TRANSIENT,
63 &m_sHelpURL, cppu::UnoType<decltype(m_sHelpURL)>::get()
64 );
65
67 "Window", PROPERTY_ID_WINDOW,
68 PropertyAttribute::TRANSIENT | PropertyAttribute::READONLY,
69 &m_xWindow, cppu::UnoType<decltype(m_xWindow)>::get()
70 );
71 }
72
73
75 {
76 if ( !GetBroadcastHelper().bDisposed )
77 {
78 acquire();
79 dispose();
80 }
81 }
82
83
84 // disambiguate XInterface
85
87
88
89 // disambiguate XTypeProvider
90
92
93
94 // XComponent related methods
95
96 void OCommonPicker::checkAlive() const
97 {
98 if ( GetBroadcastHelper().bInDispose || GetBroadcastHelper().bDisposed )
99 throw DisposedException();
100 }
101
103 {
104 if(createPicker())
105 {
106 // set the title
107 if ( !m_aTitle.isEmpty() )
108 m_xDlg->set_title(m_aTitle);
109 }
110 }
111
112
114 {
115 SolarMutexGuard aGuard;
116
118
119 if ( m_nCancelEvent )
121
122 {
123 ::osl::MutexGuard aOwnGuard( m_aMutex );
124 if ( m_bExecuting && m_xDlg )
125 m_xDlg->response(RET_CANCEL);
126 }
127
128 m_xDlg.reset();
129 m_xWindow = nullptr;
130 m_xDialogParent = nullptr;
131 }
132
133
135 {
138 }
139
140 // XEventListener
141 void SAL_CALL OCommonPicker::disposing( const EventObject& _rSource )
142 {
143 SolarMutexGuard aGuard;
144 bool bDialogDying = _rSource.Source == m_xWindow;
145 bool bParentDying = _rSource.Source == m_xDialogParent;
146
147 if ( bDialogDying || bParentDying )
148 {
150
151 SAL_WARN_IF(bDialogDying && m_bExecuting, "fpicker.office", "unexpected disposing before response" );
152
153 // it's the parent which is dying -> delete the dialog
154 {
155 ::osl::MutexGuard aOwnGuard(m_aMutex);
156 if (m_bExecuting && m_xDlg)
157 m_xDlg->response(RET_CANCEL);
158 }
159
160 m_xDlg.reset();
161 m_xWindow = nullptr;
162 m_xDialogParent = nullptr;
163 }
164 else
165 {
166 OSL_FAIL( "OCommonPicker::disposing: where did this come from?" );
167 }
168 }
169
170 // property set related methods
172 {
173 Sequence< Property > aProps;
174 describeProperties( aProps );
175 return new cppu::OPropertyArrayHelper( aProps );
176 }
177
179 {
180 return *getArrayHelper();
181 }
182
183 Reference< XPropertySetInfo > SAL_CALL OCommonPicker::getPropertySetInfo( )
184 {
185 return ::cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() );
186 }
187
188 void SAL_CALL OCommonPicker::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue)
189 {
190 OPropertyContainer::setFastPropertyValue_NoBroadcast(nHandle, rValue);
191
192 // if the HelpURL changed, forward this to the dialog
194 {
195 ::svt::OControlAccess aAccess(m_xDlg.get(), m_xDlg->GetView());
196 aAccess.setHelpURL(m_xDlg->getDialog(), m_sHelpURL);
197 }
198 }
199
201 {
202 if ( !m_xDlg )
203 {
205 SAL_WARN_IF( !m_xDlg, "fpicker.office", "OCommonPicker::createPicker: invalid dialog returned!" );
206
207 if ( m_xDlg )
208 {
209 weld::Dialog* pDlg = m_xDlg->getDialog();
210
211 ::svt::OControlAccess aAccess(m_xDlg.get(), m_xDlg->GetView());
212 // synchronize the help id of the dialog without help URL property
213 if ( !m_sHelpURL.isEmpty() )
214 { // somebody already set the help URL while we had no dialog yet
215 aAccess.setHelpURL(pDlg, m_sHelpURL);
216 }
217 else
218 {
219 m_sHelpURL = aAccess.getHelpURL(pDlg);
220 }
221
222 m_xWindow = pDlg->GetXWindow();
223
224 // add as event listener to the window
225 OSL_ENSURE( m_xWindow.is(), "OCommonPicker::createFileDialog: invalid window component!" );
226 if ( m_xWindow.is() )
227 {
228 m_xWindowListenerAdapter = new OWeakEventListenerAdapter( this, m_xWindow );
229 // the adapter will add itself as listener, and forward notifications
230 }
231
233 if (xVclDialog) // this block is quite possibly unnecessary by now
234 {
235 // _and_ add as event listener to the parent - in case the parent is destroyed
236 // before we are disposed, our disposal would access dead VCL windows then...
237 m_xDialogParent = VCLUnoHelper::GetInterface(xVclDialog->GetParent());
238 OSL_ENSURE(m_xDialogParent.is() || !xVclDialog->GetParent(), "OCommonPicker::createFileDialog: invalid window component (the parent this time)!");
239 }
240 if ( m_xDialogParent.is() )
241 {
242 m_xParentListenerAdapter = new OWeakEventListenerAdapter( this, m_xDialogParent );
243 // the adapter will add itself as listener, and forward notifications
244 }
245 }
246 }
247
248 return nullptr != m_xDlg;
249 }
250
251 // XControlAccess functions
252 void SAL_CALL OCommonPicker::setControlProperty( const OUString& aControlName, const OUString& aControlProperty, const Any& aValue )
253 {
254 checkAlive();
255
256 SolarMutexGuard aGuard;
257 if ( createPicker() )
258 {
259 ::svt::OControlAccess aAccess( m_xDlg.get(), m_xDlg->GetView() );
260 aAccess.setControlProperty( aControlName, aControlProperty, aValue );
261 }
262 }
263
264 Any SAL_CALL OCommonPicker::getControlProperty( const OUString& aControlName, const OUString& aControlProperty )
265 {
266 checkAlive();
267
268 SolarMutexGuard aGuard;
269 if ( createPicker() )
270 {
271 ::svt::OControlAccess aAccess( m_xDlg.get(), m_xDlg->GetView() );
272 return aAccess.getControlProperty( aControlName, aControlProperty );
273 }
274
275 return Any();
276 }
277
278 // XControlInformation functions
279 Sequence< OUString > SAL_CALL OCommonPicker::getSupportedControls( )
280 {
281 checkAlive();
282
283 SolarMutexGuard aGuard;
284 if ( createPicker() )
285 {
286 ::svt::OControlAccess aAccess( m_xDlg.get(), m_xDlg->GetView() );
287 return aAccess.getSupportedControls( );
288 }
289
290 return Sequence< OUString >();
291 }
292
293 sal_Bool SAL_CALL OCommonPicker::isControlSupported( const OUString& aControlName )
294 {
295 checkAlive();
296
297 SolarMutexGuard aGuard;
298 if ( createPicker() )
299 {
300 return svt::OControlAccess::isControlSupported( aControlName );
301 }
302
303 return false;
304 }
305
306 Sequence< OUString > SAL_CALL OCommonPicker::getSupportedControlProperties( const OUString& aControlName )
307 {
308 checkAlive();
309
310 SolarMutexGuard aGuard;
311 if ( createPicker() )
312 {
313 ::svt::OControlAccess aAccess( m_xDlg.get(), m_xDlg->GetView() );
314 return aAccess.getSupportedControlProperties( aControlName );
315 }
316
317 return Sequence< OUString >();
318 }
319
320 sal_Bool SAL_CALL OCommonPicker::isControlPropertySupported( const OUString& aControlName, const OUString& aControlProperty )
321 {
322 checkAlive();
323
324 SolarMutexGuard aGuard;
325 if ( createPicker() )
326 {
327 ::svt::OControlAccess aAccess( m_xDlg.get(), m_xDlg->GetView() );
328 return aAccess.isControlPropertySupported( aControlName, aControlProperty );
329 }
330
331 return false;
332 }
333
334
335 // XExecutableDialog functions
336
337 void OCommonPicker::setTitle( const OUString& _rTitle )
338 {
339 SolarMutexGuard aGuard;
340 m_aTitle = _rTitle;
341 }
342
343
345 {
346 SolarMutexGuard aGuard;
347
349
350 {
351 ::osl::MutexGuard aOwnGuard( m_aMutex );
352 m_bExecuting = true;
353 }
354 sal_Int16 nResult = implExecutePicker();
355 {
356 ::osl::MutexGuard aOwnGuard( m_aMutex );
357 m_bExecuting = false;
358 }
359
360 return nResult;
361 }
362
363
364 // XCancellable functions
365
366 void SAL_CALL OCommonPicker::cancel( )
367 {
368 {
369 ::osl::MutexGuard aGuard( m_aMutex );
370 if ( m_nCancelEvent )
371 // nothing to do - the event for cancelling the dialog is already on the way
372 return;
373 }
374
375 // The thread which executes our dialog has locked the solar mutex for
376 // sure. Cancelling the dialog should be done with a locked solar mutex, too.
377 // Thus we post ourself a message for cancelling the dialog. This way, the message
378 // is either handled in the thread which opened the dialog (which may even be
379 // this thread here), or, if no dialog is open, in the thread doing scheduling
380 // currently. Both is okay for us...
381
382 // Note that we could do check if we are really executing the dialog currently.
383 // but the information would be potentially obsolete at the moment our event
384 // arrives, so we need to check it there, anyway...
385 m_nCancelEvent = Application::PostUserEvent( LINK( this, OCommonPicker, OnCancelPicker ) );
386 }
387
388 IMPL_LINK_NOARG(OCommonPicker, OnCancelPicker, void*, void)
389 {
390 // By definition, the solar mutex is locked when we arrive here. Note that this
391 // is important, as for instance the consistency of m_xDlg depends on this mutex.
392 ::osl::MutexGuard aGuard( m_aMutex );
393 m_nCancelEvent = nullptr;
394
395 if ( !m_bExecuting )
396 // nothing to do. This may be because the dialog was canceled after our cancel method
397 // posted this async event, or because somebody called cancel without the dialog
398 // being executed at this time.
399 return;
400
401 OSL_ENSURE( m_xDlg, "OCommonPicker::OnCancelPicker: executing, but no dialog!" );
402 if (m_xDlg)
403 m_xDlg->response(RET_CANCEL);
404 }
405
406 // XInitialization functions
407 void SAL_CALL OCommonPicker::initialize( const Sequence< Any >& _rArguments )
408 {
409 checkAlive();
410
411 OUString sSettingName;
412 Any aSettingValue;
413
414 PropertyValue aPropArg;
415 NamedValue aPairArg;
416
417
418 const Any* pArguments = _rArguments.getConstArray();
419 const Any* pArgumentsEnd = _rArguments.getConstArray() + _rArguments.getLength();
420 for ( const Any* pArgument = pArguments;
421 pArgument != pArgumentsEnd;
422 ++pArgument
423 )
424 {
425 if ( *pArgument >>= aPropArg )
426 {
427 if ( aPropArg.Name.isEmpty())
428 continue;
429
430 sSettingName = aPropArg.Name;
431 aSettingValue = aPropArg.Value;
432 }
433 else if ( *pArgument >>= aPairArg )
434 {
435 if ( aPairArg.Name.isEmpty())
436 continue;
437
438 sSettingName = aPairArg.Name;
439 aSettingValue = aPairArg.Value;
440
441
442 }
443 else
444 {
445 SAL_WARN( "fpicker", "OCommonPicker::initialize: unknown argument type at position "
446 << (pArguments - _rArguments.getConstArray()));
447 continue;
448 }
449
450 bool bKnownSetting =
451 implHandleInitializationArgument( sSettingName, aSettingValue );
452 DBG_ASSERT( bKnownSetting,
453 OString(
454 "OCommonPicker::initialize: unknown argument \""
455 + OUStringToOString(sSettingName, osl_getThreadTextEncoding())
456 + "\"!").getStr() );
457 }
458 }
459
460 bool OCommonPicker::implHandleInitializationArgument( const OUString& _rName, const Any& _rValue )
461 {
462 bool bKnown = true;
463 if ( _rName == "ParentWindow" )
464 {
465 m_xDialogParent.clear();
466 OSL_VERIFY( _rValue >>= m_xDialogParent );
467 OSL_ENSURE( m_xDialogParent.is(), "OCommonPicker::implHandleInitializationArgument: invalid parent window given!" );
468 }
469 else
470 bKnown = false;
471 return bKnown;
472 }
473
474} // namespace svt
475
476/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static weld::Window * GetFrameWeld(const css::uno::Reference< css::awt::XWindow > &rWindow)
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
static void RemoveUserEvent(ImplSVEvent *nUserEvent)
static css::uno::Reference< css::awt::XWindow > GetInterface(vcl::Window *pWindow)
static vcl::Window * GetWindow(const css::uno::Reference< css::awt::XWindow > &rxWindow)
::cppu::IPropertyArrayHelper * getArrayHelper()
void describeProperties(css::uno::Sequence< css::beans::Property > &_rProps) const
void registerProperty(const OUString &_rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, void *_pPointerToMember, const css::uno::Type &_rMemberType)
mutable::osl::Mutex m_aMutex
implements common functionality for the 2 UNO picker components
virtual void SAL_CALL setTitle(const OUString &_rTitle)
const ::cppu::OBroadcastHelper & GetBroadcastHelper() const
css::uno::Reference< css::lang::XComponent > m_xParentListenerAdapter
std::shared_ptr< SvtFileDialog_Base > m_xDlg
virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > &aArguments) override
virtual std::shared_ptr< SvtFileDialog_Base > implCreateDialog(weld::Window *pParent)=0
void checkAlive() const
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedControlProperties(const OUString &aControlName) override
virtual css::uno::Any SAL_CALL getControlProperty(const OUString &aControlName, const OUString &aControlProperty) override
virtual sal_Bool SAL_CALL isControlPropertySupported(const OUString &aControlName, const OUString &aControlProperty) override
css::uno::Reference< css::awt::XWindow > m_xDialogParent
css::uno::Reference< css::lang::XComponent > m_xWindowListenerAdapter
virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const css::uno::Any &_rValue) override
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override
virtual void SAL_CALL disposing() override
virtual ::cppu::IPropertyArrayHelper * createArrayHelper() const override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedControls() override
virtual sal_Bool SAL_CALL isControlSupported(const OUString &aControlName) override
virtual ::cppu::IPropertyArrayHelper &SAL_CALL getInfoHelper() override
virtual void SAL_CALL setControlProperty(const OUString &aControlName, const OUString &aControlProperty, const css::uno::Any &aValue) override
css::uno::Reference< css::awt::XWindow > m_xWindow
virtual sal_Int16 SAL_CALL execute()
virtual void SAL_CALL cancel() override
virtual ~OCommonPicker() override
virtual sal_Int16 implExecutePicker()=0
virtual bool implHandleInitializationArgument(const OUString &_rName, const css::uno::Any &_rValue)
handle a single argument from the XInitialization::initialize method
ImplSVEvent * m_nCancelEvent
implements the XControlAccess, XControlInformation and XFilePickerControlAccess for the file picker
css::uno::Sequence< OUString > getSupportedControlProperties(std::u16string_view rControlName)
static bool isControlSupported(std::u16string_view rControlName)
void setHelpURL(weld::Widget *pControl, const OUString &rURL)
css::uno::Sequence< OUString > getSupportedControls() const
OUString getHelpURL(weld::Widget const *pControl) const
css::uno::Any getControlProperty(std::u16string_view rControlName, const OUString &rControlProperty)
void setControlProperty(std::u16string_view rControlName, const OUString &rControlProperty, const css::uno::Any &rValue)
bool isControlPropertySupported(std::u16string_view rControlName, const OUString &rControlProperty)
virtual css::uno::Reference< css::awt::XWindow > GetXWindow()=0
#define PROPERTY_ID_WINDOW
#define PROPERTY_ID_HELPURL
#define DBG_ASSERT(sCon, aError)
std::mutex m_aMutex
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
void disposeComponent(css::uno::Reference< TYPE > &_rxComp)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
IMPLEMENT_FORWARD_XTYPEPROVIDER2(ChildWindowPane, ChildWindowPaneInterfaceBase, Pane)
IMPLEMENT_FORWARD_XINTERFACE2(ChildWindowPane, ChildWindowPaneInterfaceBase, Pane)
IMPL_LINK_NOARG(ComboBoxControl, SelectHdl, weld::ComboBox &, void)
::cppu::WeakComponentImplHelper< css::ui::dialogs::XControlAccess, css::ui::dialogs::XControlInformation, css::lang::XEventListener, css::util::XCancellable, css::lang::XInitialization > OCommonPicker_Base
void dispose()
sal_Int32 nHandle
unsigned char sal_Bool
RET_CANCEL