/src/libreoffice/sfx2/source/appl/shutdownicon.cxx
Line | Count | Source |
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 | | #include <sal/config.h> |
21 | | #include <sal/log.hxx> |
22 | | |
23 | | #include <shutdownicon.hxx> |
24 | | #include <sfx2/strings.hrc> |
25 | | #include <sfx2/app.hxx> |
26 | | #include <svtools/imagemgr.hxx> |
27 | | #include <com/sun/star/task/InteractionHandler.hpp> |
28 | | #include <com/sun/star/frame/Desktop.hpp> |
29 | | #include <com/sun/star/frame/TerminationVetoException.hpp> |
30 | | #include <com/sun/star/frame/XDispatchResultListener.hpp> |
31 | | #include <com/sun/star/frame/XNotifyingDispatch.hpp> |
32 | | #include <com/sun/star/frame/XFramesSupplier.hpp> |
33 | | #include <com/sun/star/frame/XFrame.hpp> |
34 | | #include <com/sun/star/util/URLTransformer.hpp> |
35 | | #include <com/sun/star/util/XURLTransformer.hpp> |
36 | | #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> |
37 | | #include <com/sun/star/ui/dialogs/XFilePicker3.hpp> |
38 | | #include <com/sun/star/ui/dialogs/TemplateDescription.hpp> |
39 | | #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> |
40 | | #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> |
41 | | #include <com/sun/star/ui/dialogs/ControlActions.hpp> |
42 | | #include <com/sun/star/document/MacroExecMode.hpp> |
43 | | #include <com/sun/star/document/UpdateDocMode.hpp> |
44 | | #include <sfx2/filedlghelper.hxx> |
45 | | #include <sfx2/docfilt.hxx> |
46 | | #include <sfx2/fcontnr.hxx> |
47 | | #include <comphelper/processfactory.hxx> |
48 | | #include <comphelper/propertyvalue.hxx> |
49 | | #include <cppuhelper/implbase.hxx> |
50 | | #include <cppuhelper/supportsservice.hxx> |
51 | | #include <comphelper/extract.hxx> |
52 | | #include <officecfg/Office/Common.hxx> |
53 | | #include <tools/urlobj.hxx> |
54 | | #include <tools/debug.hxx> |
55 | | #include <osl/diagnose.h> |
56 | | #include <osl/file.hxx> |
57 | | #include <osl/module.hxx> |
58 | | #include <rtl/ref.hxx> |
59 | | #include <utility> |
60 | | #include <vcl/svapp.hxx> |
61 | | |
62 | | #include <sfx2/sfxresid.hxx> |
63 | | |
64 | | using namespace ::com::sun::star; |
65 | | using namespace ::com::sun::star::uno; |
66 | | using namespace ::com::sun::star::frame; |
67 | | using namespace ::com::sun::star::container; |
68 | | using namespace ::com::sun::star::lang; |
69 | | using namespace ::com::sun::star::beans; |
70 | | using namespace ::com::sun::star::util; |
71 | | using namespace ::com::sun::star::ui::dialogs; |
72 | | using namespace ::sfx2; |
73 | | |
74 | | class SfxNotificationListener_Impl : public cppu::WeakImplHelper< XDispatchResultListener > |
75 | | { |
76 | | public: |
77 | | virtual void SAL_CALL dispatchFinished( const DispatchResultEvent& aEvent ) override; |
78 | | virtual void SAL_CALL disposing( const EventObject& aEvent ) override; |
79 | | }; |
80 | | |
81 | | void SAL_CALL SfxNotificationListener_Impl::dispatchFinished( const DispatchResultEvent& ) |
82 | 0 | { |
83 | 0 | ShutdownIcon::LeaveModalMode(); |
84 | 0 | } |
85 | | |
86 | | void SAL_CALL SfxNotificationListener_Impl::disposing( const EventObject& ) |
87 | 0 | { |
88 | 0 | } |
89 | | |
90 | | OUString SAL_CALL ShutdownIcon::getImplementationName() |
91 | 0 | { |
92 | 0 | return u"com.sun.star.comp.desktop.QuickstartWrapper"_ustr; |
93 | 0 | } |
94 | | |
95 | | sal_Bool SAL_CALL ShutdownIcon::supportsService(OUString const & ServiceName) |
96 | 0 | { |
97 | 0 | return cppu::supportsService(this, ServiceName); |
98 | 0 | } |
99 | | |
100 | | css::uno::Sequence<OUString> SAL_CALL ShutdownIcon::getSupportedServiceNames() |
101 | 0 | { |
102 | 0 | return { u"com.sun.star.office.Quickstart"_ustr }; |
103 | 0 | } |
104 | | |
105 | | bool ShutdownIcon::bModalMode = false; |
106 | | rtl::Reference<ShutdownIcon> ShutdownIcon::pShutdownIcon; |
107 | | |
108 | | void ShutdownIcon::initSystray() |
109 | 0 | { |
110 | 0 | if (m_bInitialized) |
111 | 0 | return; |
112 | 0 | m_bInitialized = true; |
113 | |
|
114 | | #ifdef ENABLE_QUICKSTART_APPLET |
115 | | # ifdef _WIN32 |
116 | | win32_init_sys_tray(); |
117 | | # elif defined MACOSX |
118 | | aqua_init_systray(); |
119 | | # endif // MACOSX |
120 | | #endif // ENABLE_QUICKSTART_APPLET |
121 | 0 | } |
122 | | |
123 | | void ShutdownIcon::deInitSystray() |
124 | 0 | { |
125 | 0 | if (!m_bInitialized) |
126 | 0 | return; |
127 | | |
128 | | #ifdef ENABLE_QUICKSTART_APPLET |
129 | | # ifdef _WIN32 |
130 | | win32_shutdown_sys_tray(); |
131 | | # elif defined MACOSX |
132 | | aqua_shutdown_systray(); |
133 | | # endif // MACOSX |
134 | | #endif // ENABLE_QUICKSTART_APPLET |
135 | | |
136 | 0 | m_bVeto = false; |
137 | |
|
138 | 0 | m_pFileDlg.reset(); |
139 | 0 | m_bInitialized = false; |
140 | 0 | } |
141 | | |
142 | | static bool UseSystemFileDialog() |
143 | 0 | { |
144 | 0 | return !Application::IsHeadlessModeEnabled() && officecfg::Office::Common::Misc::UseSystemFileDialog::get(); |
145 | 0 | } |
146 | | |
147 | | ShutdownIcon::ShutdownIcon( css::uno::Reference< XComponentContext > xContext ) : |
148 | 0 | m_bVeto ( false ), |
149 | 0 | m_bListenForTermination ( false ), |
150 | 0 | m_bSystemDialogs(UseSystemFileDialog()), |
151 | 0 | m_xContext(std::move( xContext )), |
152 | 0 | m_bInitialized( false ) |
153 | 0 | { |
154 | 0 | } Unexecuted instantiation: ShutdownIcon::ShutdownIcon(com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext>) Unexecuted instantiation: ShutdownIcon::ShutdownIcon(com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext>) |
155 | | |
156 | | ShutdownIcon::~ShutdownIcon() |
157 | 0 | { |
158 | 0 | deInitSystray(); |
159 | 0 | } |
160 | | |
161 | | |
162 | | void ShutdownIcon::OpenURL( const OUString& aURL, const OUString& rTarget, const Sequence< PropertyValue >& aArgs ) |
163 | 0 | { |
164 | 0 | if ( !getInstance() || !getInstance()->m_xDesktop.is() ) |
165 | 0 | return; |
166 | | |
167 | 0 | css::uno::Reference < XDispatchProvider > xDispatchProvider = getInstance()->m_xDesktop; |
168 | 0 | if ( !xDispatchProvider.is() ) |
169 | 0 | return; |
170 | | |
171 | 0 | css::util::URL aDispatchURL; |
172 | 0 | aDispatchURL.Complete = aURL; |
173 | |
|
174 | 0 | css::uno::Reference< util::XURLTransformer > xURLTransformer( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) ); |
175 | 0 | try |
176 | 0 | { |
177 | 0 | css::uno::Reference< css::frame::XDispatch > xDispatch; |
178 | |
|
179 | 0 | xURLTransformer->parseStrict( aDispatchURL ); |
180 | 0 | xDispatch = xDispatchProvider->queryDispatch( aDispatchURL, rTarget, 0 ); |
181 | 0 | if ( xDispatch.is() ) |
182 | 0 | xDispatch->dispatch( aDispatchURL, aArgs ); |
183 | 0 | } |
184 | 0 | catch ( css::uno::RuntimeException& ) |
185 | 0 | { |
186 | 0 | throw; |
187 | 0 | } |
188 | 0 | catch ( css::uno::Exception& ) |
189 | 0 | { |
190 | 0 | } |
191 | 0 | } |
192 | | |
193 | | |
194 | | void ShutdownIcon::FileOpen() |
195 | 0 | { |
196 | 0 | if ( getInstance() && getInstance()->m_xDesktop.is() ) |
197 | 0 | { |
198 | 0 | ::SolarMutexGuard aGuard; |
199 | 0 | EnterModalMode(); |
200 | 0 | getInstance()->StartFileDialog(); |
201 | 0 | } |
202 | 0 | } |
203 | | |
204 | | |
205 | | void ShutdownIcon::FromTemplate() |
206 | 0 | { |
207 | 0 | ShutdownIcon::FromCommand( ".uno:NewDoc" ); |
208 | 0 | } |
209 | | |
210 | | void ShutdownIcon::FromCommand( const OUString& rCommand ) |
211 | 0 | { |
212 | 0 | if ( !getInstance() || !getInstance()->m_xDesktop.is() ) |
213 | 0 | return; |
214 | | |
215 | 0 | css::uno::Reference < css::frame::XFramesSupplier > xDesktop = getInstance()->m_xDesktop; |
216 | 0 | css::uno::Reference < css::frame::XFrame > xFrame( xDesktop->getActiveFrame() ); |
217 | 0 | if ( !xFrame.is() ) |
218 | 0 | xFrame = xDesktop; |
219 | |
|
220 | 0 | URL aTargetURL; |
221 | 0 | aTargetURL.Complete = rCommand; |
222 | 0 | css::uno::Reference< util::XURLTransformer > xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) ); |
223 | 0 | xTrans->parseStrict( aTargetURL ); |
224 | |
|
225 | 0 | css::uno::Reference < css::frame::XDispatchProvider > xProv( xFrame, UNO_QUERY ); |
226 | 0 | css::uno::Reference < css::frame::XDispatch > xDisp; |
227 | 0 | if ( xProv.is() ) |
228 | 0 | { |
229 | 0 | xDisp = xProv->queryDispatch( aTargetURL, u"_self"_ustr, 0 ); |
230 | 0 | } |
231 | 0 | if ( !xDisp.is() ) |
232 | 0 | return; |
233 | | |
234 | 0 | Sequence<PropertyValue> aArgs { comphelper::makePropertyValue(u"Referer"_ustr, u"private:user"_ustr) }; |
235 | 0 | css::uno::Reference< css::frame::XNotifyingDispatch > xNotifier(xDisp, UNO_QUERY); |
236 | 0 | if (xNotifier.is()) |
237 | 0 | { |
238 | 0 | EnterModalMode(); |
239 | 0 | xNotifier->dispatchWithNotification(aTargetURL, aArgs, new SfxNotificationListener_Impl); |
240 | 0 | } |
241 | 0 | else |
242 | 0 | xDisp->dispatch( aTargetURL, aArgs ); |
243 | 0 | } |
244 | | |
245 | | OUString ShutdownIcon::GetUrlDescription( std::u16string_view aUrl ) |
246 | 0 | { |
247 | 0 | return SvFileInformationManager::GetDescription( INetURLObject( aUrl ) ); |
248 | 0 | } |
249 | | |
250 | | void ShutdownIcon::StartFileDialog() |
251 | 0 | { |
252 | 0 | ::SolarMutexGuard aGuard; |
253 | |
|
254 | 0 | bool bDirty = m_bSystemDialogs != UseSystemFileDialog(); |
255 | |
|
256 | 0 | if ( m_pFileDlg && bDirty ) |
257 | 0 | { |
258 | | // Destroy instance as changing the system file dialog setting |
259 | | // forces us to create a new FileDialogHelper instance! |
260 | 0 | m_pFileDlg.reset(); |
261 | 0 | } |
262 | |
|
263 | 0 | if ( !m_pFileDlg ) |
264 | 0 | m_pFileDlg.reset( new FileDialogHelper( |
265 | 0 | ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION, |
266 | 0 | FileDialogFlags::MultiSelection, OUString(), SfxFilterFlags::NONE, SfxFilterFlags::NONE, nullptr ) ); |
267 | 0 | m_pFileDlg->StartExecuteModal( LINK( this, ShutdownIcon, DialogClosedHdl_Impl ) ); |
268 | 0 | } |
269 | | |
270 | | IMPL_LINK( ShutdownIcon, DialogClosedHdl_Impl, FileDialogHelper*, /*unused*/, void ) |
271 | 0 | { |
272 | 0 | DBG_ASSERT( m_pFileDlg, "ShutdownIcon, DialogClosedHdl_Impl(): no file dialog" ); |
273 | | |
274 | | // use constructor for filling up filters automatically! |
275 | 0 | if ( ERRCODE_NONE == m_pFileDlg->GetError() ) |
276 | 0 | { |
277 | 0 | css::uno::Reference< XFilePicker3 > xPicker = m_pFileDlg->GetFilePicker(); |
278 | |
|
279 | 0 | try |
280 | 0 | { |
281 | |
|
282 | 0 | if ( xPicker.is() ) |
283 | 0 | { |
284 | |
|
285 | 0 | css::uno::Reference < XFilePickerControlAccess > xPickerControls ( xPicker, UNO_QUERY ); |
286 | |
|
287 | 0 | Sequence< OUString > sFiles = xPicker->getSelectedFiles(); |
288 | 0 | int nFiles = sFiles.getLength(); |
289 | |
|
290 | 0 | css::uno::Reference < css::task::XInteractionHandler2 > xInteraction( |
291 | 0 | task::InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(), nullptr) ); |
292 | |
|
293 | 0 | int nArgs=3; |
294 | 0 | Sequence< PropertyValue > aArgs{ |
295 | 0 | comphelper::makePropertyValue(u"InteractionHandler"_ustr, xInteraction), |
296 | 0 | comphelper::makePropertyValue(u"MacroExecutionMode"_ustr, sal_Int16(css::document::MacroExecMode::USE_CONFIG)), |
297 | 0 | comphelper::makePropertyValue(u"UpdateDocMode"_ustr, sal_Int16(css::document::UpdateDocMode::ACCORDING_TO_CONFIG)) |
298 | 0 | }; |
299 | | |
300 | | // use the filedlghelper to get the current filter name, |
301 | | // because it removes the extensions before you get the filter name. |
302 | 0 | OUString aFilterName( m_pFileDlg->GetCurrentFilter() ); |
303 | |
|
304 | 0 | if ( xPickerControls.is() ) |
305 | 0 | { |
306 | | |
307 | | // Set readonly flag |
308 | |
|
309 | 0 | bool bReadOnly = false; |
310 | | |
311 | |
|
312 | 0 | xPickerControls->getValue( ExtendedFilePickerElementIds::CHECKBOX_READONLY, 0 ) >>= bReadOnly; |
313 | | |
314 | | // Only set property if readonly is set to TRUE |
315 | |
|
316 | 0 | if ( bReadOnly ) |
317 | 0 | { |
318 | 0 | aArgs.realloc( ++nArgs ); |
319 | 0 | auto pArgs = aArgs.getArray(); |
320 | 0 | pArgs[nArgs-1].Name = "ReadOnly"; |
321 | 0 | pArgs[nArgs-1].Value <<= bReadOnly; |
322 | 0 | } |
323 | | |
324 | | // Get version string |
325 | |
|
326 | 0 | sal_Int32 iVersion = -1; |
327 | |
|
328 | 0 | xPickerControls->getValue( ExtendedFilePickerElementIds::LISTBOX_VERSION, ControlActions::GET_SELECTED_ITEM_INDEX ) >>= iVersion; |
329 | |
|
330 | 0 | if ( iVersion >= 0 ) |
331 | 0 | { |
332 | 0 | sal_Int16 uVersion = static_cast<sal_Int16>(iVersion); |
333 | |
|
334 | 0 | aArgs.realloc( ++nArgs ); |
335 | 0 | auto pArgs = aArgs.getArray(); |
336 | 0 | pArgs[nArgs-1].Name = "Version"; |
337 | 0 | pArgs[nArgs-1].Value <<= uVersion; |
338 | 0 | } |
339 | | |
340 | | // Retrieve the current filter |
341 | |
|
342 | 0 | if ( aFilterName.isEmpty() ) |
343 | 0 | xPickerControls->getValue( CommonFilePickerElementIds::LISTBOX_FILTER, ControlActions::GET_SELECTED_ITEM ) >>= aFilterName; |
344 | |
|
345 | 0 | } |
346 | | |
347 | | |
348 | | // Convert UI filter name to internal filter name |
349 | |
|
350 | 0 | if ( !aFilterName.isEmpty() ) |
351 | 0 | { |
352 | 0 | std::shared_ptr<const SfxFilter> pFilter = SfxGetpApp()->GetFilterMatcher().GetFilter4UIName( aFilterName, SfxFilterFlags::NONE, SfxFilterFlags::NOTINFILEDLG ); |
353 | |
|
354 | 0 | if ( pFilter ) |
355 | 0 | { |
356 | 0 | aFilterName = pFilter->GetFilterName(); |
357 | |
|
358 | 0 | if ( !aFilterName.isEmpty() ) |
359 | 0 | { |
360 | 0 | aArgs.realloc( ++nArgs ); |
361 | 0 | auto pArgs = aArgs.getArray(); |
362 | 0 | pArgs[nArgs-1].Name = "FilterName"; |
363 | 0 | pArgs[nArgs-1].Value <<= aFilterName; |
364 | 0 | } |
365 | 0 | } |
366 | 0 | } |
367 | |
|
368 | 0 | if ( 1 == nFiles ) |
369 | 0 | OpenURL( sFiles[0], u"_default"_ustr, aArgs ); |
370 | 0 | else |
371 | 0 | { |
372 | 0 | OUString aBaseDirURL = sFiles[0]; |
373 | 0 | if ( !aBaseDirURL.isEmpty() && !aBaseDirURL.endsWith("/") ) |
374 | 0 | aBaseDirURL += "/"; |
375 | |
|
376 | 0 | int iFiles; |
377 | 0 | for ( iFiles = 1; iFiles < nFiles; iFiles++ ) |
378 | 0 | { |
379 | 0 | OUString aURL = aBaseDirURL + sFiles[iFiles]; |
380 | 0 | OpenURL( aURL, u"_default"_ustr, aArgs ); |
381 | 0 | } |
382 | 0 | } |
383 | 0 | } |
384 | 0 | } |
385 | 0 | catch ( ... ) |
386 | 0 | { |
387 | 0 | } |
388 | 0 | } |
389 | |
|
390 | | #ifdef _WIN32 |
391 | | // Destroy dialog to prevent problems with custom controls |
392 | | // This fix is dependent on the dialog settings. Destroying the dialog here will |
393 | | // crash the non-native dialog implementation! Therefore make this dependent on |
394 | | // the settings. |
395 | | if (UseSystemFileDialog()) |
396 | | { |
397 | | m_pFileDlg.reset(); |
398 | | } |
399 | | #endif |
400 | |
|
401 | 0 | LeaveModalMode(); |
402 | 0 | } |
403 | | |
404 | | |
405 | | void ShutdownIcon::addTerminateListener() |
406 | 0 | { |
407 | 0 | ShutdownIcon* pInst = getInstance(); |
408 | 0 | if ( ! pInst) |
409 | 0 | return; |
410 | | |
411 | 0 | if (pInst->m_bListenForTermination) |
412 | 0 | return; |
413 | | |
414 | 0 | css::uno::Reference< XDesktop2 > xDesktop = pInst->m_xDesktop; |
415 | 0 | if ( ! xDesktop.is()) |
416 | 0 | return; |
417 | | |
418 | 0 | xDesktop->addTerminateListener( pInst ); |
419 | 0 | pInst->m_bListenForTermination = true; |
420 | 0 | } |
421 | | |
422 | | |
423 | | void ShutdownIcon::terminateDesktop() |
424 | 0 | { |
425 | 0 | ShutdownIcon* pInst = getInstance(); |
426 | 0 | if ( ! pInst) |
427 | 0 | return; |
428 | | |
429 | 0 | css::uno::Reference< XDesktop2 > xDesktop = pInst->m_xDesktop; |
430 | 0 | if ( ! xDesktop.is()) |
431 | 0 | return; |
432 | | |
433 | | // always remove ourselves as listener |
434 | 0 | pInst->m_bListenForTermination = true; |
435 | 0 | xDesktop->removeTerminateListener( pInst ); |
436 | | |
437 | | // terminate desktop only if no tasks exist |
438 | 0 | css::uno::Reference< XIndexAccess > xTasks = xDesktop->getFrames(); |
439 | 0 | if( xTasks.is() && xTasks->getCount() < 1 ) |
440 | 0 | Application::Quit(); |
441 | | |
442 | | // remove the instance pointer |
443 | 0 | ShutdownIcon::pShutdownIcon = nullptr; |
444 | 0 | } |
445 | | |
446 | | |
447 | | ShutdownIcon* ShutdownIcon::getInstance() |
448 | 0 | { |
449 | 0 | OSL_ASSERT( pShutdownIcon ); |
450 | 0 | return pShutdownIcon.get(); |
451 | 0 | } |
452 | | |
453 | | |
454 | | ShutdownIcon* ShutdownIcon::createInstance() |
455 | 0 | { |
456 | 0 | if (pShutdownIcon) |
457 | 0 | return pShutdownIcon.get(); |
458 | | |
459 | 0 | try { |
460 | 0 | rtl::Reference<ShutdownIcon> pIcon(new ShutdownIcon( comphelper::getProcessComponentContext() )); |
461 | 0 | pIcon->init (); |
462 | 0 | pShutdownIcon = std::move(pIcon); |
463 | 0 | } catch (...) { |
464 | 0 | } |
465 | |
|
466 | 0 | return pShutdownIcon.get(); |
467 | 0 | } |
468 | | |
469 | | void ShutdownIcon::init() |
470 | 0 | { |
471 | 0 | css::uno::Reference < XDesktop2 > xDesktop = Desktop::create( m_xContext ); |
472 | 0 | std::unique_lock aGuard(m_aMutex); |
473 | 0 | m_xDesktop = std::move(xDesktop); |
474 | 0 | } |
475 | | |
476 | | void ShutdownIcon::disposing(std::unique_lock<std::mutex>&) |
477 | 0 | { |
478 | 0 | m_xContext.clear(); |
479 | 0 | m_xDesktop.clear(); |
480 | |
|
481 | 0 | deInitSystray(); |
482 | 0 | } |
483 | | |
484 | | // XEventListener |
485 | | void SAL_CALL ShutdownIcon::disposing( const css::lang::EventObject& ) |
486 | 0 | { |
487 | 0 | } |
488 | | |
489 | | // XTerminateListener |
490 | | void SAL_CALL ShutdownIcon::queryTermination( const css::lang::EventObject& ) |
491 | 0 | { |
492 | 0 | SAL_INFO("sfx.appl", "ShutdownIcon::queryTermination: veto is " << m_bVeto); |
493 | 0 | std::unique_lock aGuard( m_aMutex ); |
494 | |
|
495 | 0 | if ( m_bVeto ) |
496 | 0 | throw css::frame::TerminationVetoException(); |
497 | 0 | } |
498 | | |
499 | | |
500 | | void SAL_CALL ShutdownIcon::notifyTermination( const css::lang::EventObject& ) |
501 | 0 | { |
502 | 0 | } |
503 | | |
504 | | |
505 | | void SAL_CALL ShutdownIcon::initialize( const css::uno::Sequence< css::uno::Any>& aArguments ) |
506 | 0 | { |
507 | 0 | std::unique_lock aGuard( m_aMutex ); |
508 | | |
509 | | // third argument only sets veto, everything else will be ignored! |
510 | 0 | if (aArguments.getLength() > 2) |
511 | 0 | { |
512 | 0 | bool bVeto = ::cppu::any2bool(aArguments[2]); |
513 | 0 | m_bVeto = bVeto; |
514 | 0 | return; |
515 | 0 | } |
516 | | |
517 | 0 | if ( aArguments.getLength() > 0 ) |
518 | 0 | { |
519 | 0 | if ( !ShutdownIcon::pShutdownIcon ) |
520 | 0 | { |
521 | 0 | try |
522 | 0 | { |
523 | 0 | bool bQuickstart = ::cppu::any2bool( aArguments[0] ); |
524 | 0 | if( !bQuickstart && !GetAutostart() ) |
525 | 0 | return; |
526 | 0 | aGuard.unlock(); |
527 | 0 | init (); |
528 | 0 | aGuard.lock(); |
529 | 0 | if ( !m_xDesktop.is() ) |
530 | 0 | return; |
531 | | |
532 | | /* Create a sub-classed instance - foo */ |
533 | 0 | ShutdownIcon::pShutdownIcon = this; |
534 | 0 | initSystray(); |
535 | 0 | } |
536 | 0 | catch(const css::lang::IllegalArgumentException&) |
537 | 0 | { |
538 | 0 | } |
539 | 0 | } |
540 | 0 | } |
541 | 0 | if ( aArguments.getLength() > 1 ) |
542 | 0 | { |
543 | 0 | bool bAutostart = ::cppu::any2bool( aArguments[1] ); |
544 | 0 | if (bAutostart && !GetAutostart()) |
545 | 0 | SetAutostart( true ); |
546 | 0 | if (!bAutostart && GetAutostart()) |
547 | 0 | SetAutostart( false ); |
548 | 0 | } |
549 | |
|
550 | 0 | } |
551 | | |
552 | | |
553 | | void ShutdownIcon::EnterModalMode() |
554 | 0 | { |
555 | 0 | bModalMode = true; |
556 | 0 | } |
557 | | |
558 | | |
559 | | void ShutdownIcon::LeaveModalMode() |
560 | 0 | { |
561 | 0 | bModalMode = false; |
562 | 0 | } |
563 | | |
564 | | #ifdef _WIN32 |
565 | | // defined in shutdowniconw32.cxx |
566 | | #elif defined MACOSX |
567 | | // defined in shutdowniconaqua.cxx |
568 | | #else |
569 | | bool ShutdownIcon::IsQuickstarterInstalled() |
570 | 0 | { |
571 | 0 | return false; |
572 | 0 | } |
573 | | #endif |
574 | | |
575 | | |
576 | | #ifdef ENABLE_QUICKSTART_APPLET |
577 | | #ifdef _WIN32 |
578 | | OUString ShutdownIcon::getShortcutName() |
579 | | { |
580 | | return GetAutostartFolderNameW32() + "\\" + SfxResId(STR_QUICKSTART_LNKNAME) + ".lnk"; |
581 | | } |
582 | | #endif // _WIN32 |
583 | | #endif |
584 | | |
585 | | bool ShutdownIcon::GetAutostart( ) |
586 | 0 | { |
587 | | #if defined MACOSX |
588 | | return true; |
589 | | #elif defined ENABLE_QUICKSTART_APPLET |
590 | | bool bRet = false; |
591 | | OUString aShortcut( getShortcutName() ); |
592 | | OUString aShortcutUrl; |
593 | | osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl ); |
594 | | osl::File f( aShortcutUrl ); |
595 | | osl::File::RC error = f.open( osl_File_OpenFlag_Read ); |
596 | | if( error == osl::File::E_None ) |
597 | | { |
598 | | f.close(); |
599 | | bRet = true; |
600 | | } |
601 | | return bRet; |
602 | | #else // ENABLE_QUICKSTART_APPLET |
603 | 0 | return false; |
604 | 0 | #endif |
605 | 0 | } |
606 | | |
607 | | void ShutdownIcon::SetAutostart( bool bActivate ) |
608 | 0 | { |
609 | | #ifdef ENABLE_QUICKSTART_APPLET |
610 | | #ifndef MACOSX |
611 | | OUString aShortcut( getShortcutName() ); |
612 | | #endif |
613 | | |
614 | | if( bActivate && IsQuickstarterInstalled() ) |
615 | | { |
616 | | #ifdef _WIN32 |
617 | | EnableAutostartW32( aShortcut ); |
618 | | #endif |
619 | | } |
620 | | else |
621 | | { |
622 | | #ifndef MACOSX |
623 | | OUString aShortcutUrl; |
624 | | ::osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl ); |
625 | | ::osl::File::remove( aShortcutUrl ); |
626 | | #endif |
627 | | } |
628 | | #else |
629 | 0 | (void)bActivate; // unused variable |
630 | 0 | #endif // ENABLE_QUICKSTART_APPLET |
631 | 0 | } |
632 | | |
633 | | const ::sal_Int32 PROPHANDLE_TERMINATEVETOSTATE = 0; |
634 | | |
635 | | // XFastPropertySet |
636 | | void SAL_CALL ShutdownIcon::setFastPropertyValue( ::sal_Int32 nHandle, |
637 | | const css::uno::Any& aValue ) |
638 | 0 | { |
639 | 0 | switch(nHandle) |
640 | 0 | { |
641 | 0 | case PROPHANDLE_TERMINATEVETOSTATE : |
642 | 0 | { |
643 | | // use new value in case it's a valid information only |
644 | 0 | bool bState( false ); |
645 | 0 | if (! (aValue >>= bState)) |
646 | 0 | return; |
647 | | |
648 | 0 | m_bVeto = bState; |
649 | 0 | if (m_bVeto && ! m_bListenForTermination) |
650 | 0 | addTerminateListener(); |
651 | 0 | } |
652 | 0 | break; |
653 | | |
654 | 0 | default : |
655 | 0 | throw css::beans::UnknownPropertyException(OUString::number(nHandle)); |
656 | 0 | } |
657 | 0 | } |
658 | | |
659 | | // XFastPropertySet |
660 | | css::uno::Any SAL_CALL ShutdownIcon::getFastPropertyValue( ::sal_Int32 nHandle ) |
661 | 0 | { |
662 | 0 | css::uno::Any aValue; |
663 | 0 | switch(nHandle) |
664 | 0 | { |
665 | 0 | case PROPHANDLE_TERMINATEVETOSTATE : |
666 | 0 | { |
667 | 0 | bool bState = (m_bListenForTermination && m_bVeto); |
668 | 0 | aValue <<= bState; |
669 | 0 | } |
670 | 0 | break; |
671 | | |
672 | 0 | default : |
673 | 0 | throw css::beans::UnknownPropertyException(OUString::number(nHandle)); |
674 | 0 | } |
675 | | |
676 | 0 | return aValue; |
677 | 0 | } |
678 | | |
679 | | extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * |
680 | | com_sun_star_comp_desktop_QuickstartWrapper_get_implementation( |
681 | | css::uno::XComponentContext *context, |
682 | | css::uno::Sequence<css::uno::Any> const &) |
683 | 0 | { |
684 | 0 | return cppu::acquire(new ShutdownIcon(context)); |
685 | 0 | } |
686 | | |
687 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |