bump product version to 4.1.6.2
[LibreOffice.git] / sfx2 / source / appl / shutdownicon.cxx
blob2fa5ba902b547e3c6d3bc9487fdb493a94c83ca3
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 <shutdownicon.hxx>
21 #include <app.hrc>
22 #include <sfx2/app.hxx>
23 #include <osl/mutex.hxx>
24 #include <svtools/imagemgr.hxx>
25 #include <svtools/miscopt.hxx>
26 #include <com/sun/star/task/InteractionHandler.hpp>
27 #include <com/sun/star/frame/Desktop.hpp>
28 #include <com/sun/star/frame/XDispatchResultListener.hpp>
29 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
30 #include <com/sun/star/frame/XFramesSupplier.hpp>
31 #include <com/sun/star/frame/XComponentLoader.hpp>
32 #include <com/sun/star/frame/XFrame.hpp>
33 #include <com/sun/star/util/URLTransformer.hpp>
34 #include <com/sun/star/util/XURLTransformer.hpp>
35 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
36 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
37 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
38 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
39 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
40 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
41 #include <com/sun/star/document/MacroExecMode.hpp>
42 #include <com/sun/star/document/UpdateDocMode.hpp>
43 #include <sfx2/filedlghelper.hxx>
44 #include <sfx2/fcontnr.hxx>
45 #include <comphelper/processfactory.hxx>
46 #include <cppuhelper/compbase1.hxx>
47 #include <sfx2/dispatch.hxx>
48 #include <comphelper/extract.hxx>
49 #include <tools/urlobj.hxx>
50 #include <osl/security.hxx>
51 #include <osl/file.hxx>
52 #include <rtl/bootstrap.hxx>
53 #include <rtl/ustrbuf.hxx>
54 #ifdef UNX // need symlink
55 #include <unistd.h>
56 #include <errno.h>
57 #endif
58 #include <vcl/timer.hxx>
60 #include "sfx2/sfxresid.hxx"
62 using namespace ::com::sun::star;
63 using namespace ::com::sun::star::uno;
64 using namespace ::com::sun::star::frame;
65 using namespace ::com::sun::star::container;
66 using namespace ::com::sun::star::io;
67 using namespace ::com::sun::star::lang;
68 using namespace ::com::sun::star::beans;
69 using namespace ::com::sun::star::util;
70 using namespace ::com::sun::star::ui::dialogs;
71 #ifdef WNT
72 #else
73 using namespace ::rtl;
74 #endif
75 using namespace ::sfx2;
77 #ifdef ENABLE_QUICKSTART_APPLET
78 # if !defined(WIN32) && !defined(MACOSX)
79 extern "C" { static void SAL_CALL thisModule() {} }
80 # endif
81 #endif
83 #if defined(UNX) && defined(ENABLE_SYSTRAY_GTK) && !defined(PLUGIN_NAME)
84 #define PLUGIN_NAME "libqstart_gtklo.so"
85 #endif
87 class SfxNotificationListener_Impl : public cppu::WeakImplHelper1< XDispatchResultListener >
89 public:
90 virtual void SAL_CALL dispatchFinished( const DispatchResultEvent& aEvent ) throw( RuntimeException );
91 virtual void SAL_CALL disposing( const EventObject& aEvent ) throw( RuntimeException );
94 void SAL_CALL SfxNotificationListener_Impl::dispatchFinished( const DispatchResultEvent& ) throw( RuntimeException )
96 ShutdownIcon::LeaveModalMode();
99 void SAL_CALL SfxNotificationListener_Impl::disposing( const EventObject& ) throw( RuntimeException )
103 SFX_IMPL_XSERVICEINFO_CTX( ShutdownIcon, "com.sun.star.office.Quickstart", "com.sun.star.comp.desktop.QuickstartWrapper" ) \
104 SFX_IMPL_ONEINSTANCEFACTORY( ShutdownIcon );
106 bool ShutdownIcon::bModalMode = false;
107 ShutdownIcon* ShutdownIcon::pShutdownIcon = NULL;
109 #if !defined( ENABLE_QUICKSTART_APPLET ) || defined( UNX )
110 // To remove conditionals
111 extern "C" {
112 static void disabled_initSystray() { }
113 static void disabled_deInitSystray() { }
115 #endif
117 bool ShutdownIcon::LoadModule( osl::Module **pModule,
118 oslGenericFunction *pInit,
119 oslGenericFunction *pDeInit )
121 if ( pModule )
123 OSL_ASSERT ( pInit && pDeInit );
124 *pInit = *pDeInit = NULL;
125 *pModule = NULL;
128 #ifdef ENABLE_QUICKSTART_APPLET
129 # ifdef WIN32
130 if ( pModule )
132 *pInit = win32_init_sys_tray;
133 *pDeInit = win32_shutdown_sys_tray;
135 return true;
136 # elif defined MACOSX
137 *pInit = aqua_init_systray;
138 *pDeInit = aqua_shutdown_systray;
139 return true;
140 # else // UNX
141 osl::Module *pPlugin;
142 pPlugin = new osl::Module();
144 oslGenericFunction pTmpInit = NULL;
145 oslGenericFunction pTmpDeInit = NULL;
147 #define DOSTRING( x ) #x
148 #define STRING( x ) DOSTRING( x )
150 if ( pPlugin->loadRelative( &thisModule, OUString (STRING( PLUGIN_NAME ) ) ) )
152 pTmpInit = pPlugin->getFunctionSymbol(
153 OUString( "plugin_init_sys_tray" ) );
154 pTmpDeInit = pPlugin->getFunctionSymbol(
155 OUString( "plugin_shutdown_sys_tray" ) );
157 if ( !pTmpInit || !pTmpDeInit )
159 delete pPlugin;
160 pPlugin = NULL;
162 if ( pModule )
164 *pModule = pPlugin;
165 *pInit = pTmpInit;
166 *pDeInit = pTmpDeInit;
168 else
170 bool bRet = pPlugin != NULL;
171 delete pPlugin;
172 return bRet;
174 # endif // UNX
175 #endif // ENABLE_QUICKSTART_APPLET
177 #if !defined( ENABLE_QUICKSTART_APPLET ) || defined( UNX )
178 // Avoid unreachable code. In the ENABLE_QUICKSTART_APPLET && !UNX
179 // case, we have already returned.
180 if ( pModule )
182 if ( !*pInit )
183 *pInit = disabled_initSystray;
184 if ( !*pDeInit )
185 *pDeInit = disabled_deInitSystray;
188 return true;
189 #endif // !ENABLE_QUICKSTART_APPLET || UNX
192 // These two timeouts are necessary to avoid there being
193 // plugin frames still on the stack, after unloading that
194 // code, causing a crash during disabling / termination.
195 class IdleUnloader : Timer
197 ::osl::Module *m_pModule;
198 public:
199 IdleUnloader (::osl::Module **pModule) :
200 m_pModule (*pModule)
202 *pModule = NULL;
203 Start();
205 virtual void Timeout()
207 delete m_pModule;
208 delete this;
212 class IdleTerminate : Timer
214 Reference< XDesktop2 > m_xDesktop;
215 public:
216 IdleTerminate (Reference< XDesktop2 > xDesktop)
218 m_xDesktop = xDesktop;
219 Start();
221 virtual void Timeout()
223 m_xDesktop->terminate();
224 delete this;
228 void ShutdownIcon::initSystray()
230 if (m_bInitialized)
231 return;
232 m_bInitialized = true;
234 (void) LoadModule( &m_pPlugin, &m_pInitSystray, &m_pDeInitSystray );
235 m_bVeto = true;
236 m_pInitSystray();
239 void ShutdownIcon::deInitSystray()
241 if (!m_bInitialized)
242 return;
244 if (m_pDeInitSystray)
245 m_pDeInitSystray();
247 m_bVeto = false;
248 m_pInitSystray = 0;
249 m_pDeInitSystray = 0;
250 new IdleUnloader (&m_pPlugin);
252 delete m_pFileDlg;
253 m_pFileDlg = NULL;
254 m_bInitialized = false;
258 ShutdownIcon::ShutdownIcon( const Reference< XComponentContext > & rxContext ) :
259 ShutdownIconServiceBase( m_aMutex ),
260 m_bVeto ( false ),
261 m_bListenForTermination ( false ),
262 m_bSystemDialogs( false ),
263 m_pResMgr( NULL ),
264 m_pFileDlg( NULL ),
265 m_xContext( rxContext ),
266 m_pInitSystray( 0 ),
267 m_pDeInitSystray( 0 ),
268 m_pPlugin( 0 ),
269 m_bInitialized( false )
271 m_bSystemDialogs = SvtMiscOptions().UseSystemFileDialog();
274 ShutdownIcon::~ShutdownIcon()
276 deInitSystray();
277 new IdleUnloader (&m_pPlugin);
280 // ---------------------------------------------------------------------------
282 void ShutdownIcon::OpenURL( const OUString& aURL, const OUString& rTarget, const Sequence< PropertyValue >& aArgs )
284 if ( getInstance() && getInstance()->m_xDesktop.is() )
286 Reference < XDispatchProvider > xDispatchProvider( getInstance()->m_xDesktop, UNO_QUERY );
287 if ( xDispatchProvider.is() )
289 com::sun::star::util::URL aDispatchURL;
290 aDispatchURL.Complete = aURL;
292 Reference< util::XURLTransformer > xURLTransformer( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
295 Reference< com::sun::star::frame::XDispatch > xDispatch;
297 xURLTransformer->parseStrict( aDispatchURL );
298 xDispatch = xDispatchProvider->queryDispatch( aDispatchURL, rTarget, 0 );
299 if ( xDispatch.is() )
300 xDispatch->dispatch( aDispatchURL, aArgs );
302 catch ( com::sun::star::uno::RuntimeException& )
304 throw;
306 catch ( com::sun::star::uno::Exception& )
313 // ---------------------------------------------------------------------------
315 void ShutdownIcon::FileOpen()
317 if ( getInstance() && getInstance()->m_xDesktop.is() )
319 ::SolarMutexGuard aGuard;
320 EnterModalMode();
321 getInstance()->StartFileDialog();
325 // ---------------------------------------------------------------------------
327 void ShutdownIcon::FromTemplate()
329 if ( getInstance() && getInstance()->m_xDesktop.is() )
331 Reference < ::com::sun::star::frame::XFramesSupplier > xDesktop ( getInstance()->m_xDesktop, UNO_QUERY);
332 Reference < ::com::sun::star::frame::XFrame > xFrame( xDesktop->getActiveFrame() );
333 if ( !xFrame.is() )
334 xFrame = Reference < ::com::sun::star::frame::XFrame >( xDesktop, UNO_QUERY );
336 URL aTargetURL;
337 aTargetURL.Complete = OUString( "slot:5500" );
338 Reference< util::XURLTransformer > xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
339 xTrans->parseStrict( aTargetURL );
341 Reference < ::com::sun::star::frame::XDispatchProvider > xProv( xFrame, UNO_QUERY );
342 Reference < ::com::sun::star::frame::XDispatch > xDisp;
343 if ( xProv.is() )
345 if ( aTargetURL.Protocol.compareToAscii("slot:") == COMPARE_EQUAL )
346 xDisp = xProv->queryDispatch( aTargetURL, OUString(), 0 );
347 else
348 xDisp = xProv->queryDispatch( aTargetURL, OUString("_blank"), 0 );
350 if ( xDisp.is() )
352 Sequence<PropertyValue> aArgs(1);
353 PropertyValue* pArg = aArgs.getArray();
354 pArg[0].Name = OUString("Referer");
355 pArg[0].Value <<= OUString("private:user");
356 Reference< ::com::sun::star::frame::XNotifyingDispatch > xNotifyer( xDisp, UNO_QUERY );
357 if ( xNotifyer.is() )
359 EnterModalMode();
360 xNotifyer->dispatchWithNotification( aTargetURL, aArgs, new SfxNotificationListener_Impl() );
362 else
363 xDisp->dispatch( aTargetURL, aArgs );
368 // ---------------------------------------------------------------------------
369 #include <tools/rcid.h>
370 OUString ShutdownIcon::GetResString( int id )
372 ::SolarMutexGuard aGuard;
374 if( ! m_pResMgr )
375 m_pResMgr = SfxResId::GetResMgr();
376 ResId aResId( id, *m_pResMgr );
377 aResId.SetRT( RSC_STRING );
378 if( !m_pResMgr || !m_pResMgr->IsAvailable( aResId ) )
379 return OUString();
381 return ResId(id, *m_pResMgr).toString();
384 // ---------------------------------------------------------------------------
386 OUString ShutdownIcon::GetUrlDescription( const OUString& aUrl )
388 ::SolarMutexGuard aGuard;
390 return OUString( SvFileInformationManager::GetDescription( INetURLObject( aUrl ) ) );
393 // ---------------------------------------------------------------------------
395 void ShutdownIcon::StartFileDialog()
397 ::SolarMutexGuard aGuard;
399 bool bDirty = ( m_bSystemDialogs != static_cast<bool>(SvtMiscOptions().UseSystemFileDialog()) );
401 if ( m_pFileDlg && bDirty )
403 // Destroy instance as changing the system file dialog setting
404 // forces us to create a new FileDialogHelper instance!
405 delete m_pFileDlg;
406 m_pFileDlg = NULL;
409 if ( !m_pFileDlg )
410 m_pFileDlg = new FileDialogHelper(
411 ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION,
412 SFXWB_MULTISELECTION, String() );
413 m_pFileDlg->StartExecuteModal( STATIC_LINK( this, ShutdownIcon, DialogClosedHdl_Impl ) );
416 // ---------------------------------------------------------------------------
418 IMPL_STATIC_LINK( ShutdownIcon, DialogClosedHdl_Impl, FileDialogHelper*, EMPTYARG )
420 DBG_ASSERT( pThis->m_pFileDlg, "ShutdownIcon, DialogClosedHdl_Impl(): no file dialog" );
422 // use constructor for filling up filters automatically!
423 if ( ERRCODE_NONE == pThis->m_pFileDlg->GetError() )
425 Reference< XFilePicker > xPicker = pThis->m_pFileDlg->GetFilePicker();
430 if ( xPicker.is() )
433 Reference < XFilePickerControlAccess > xPickerControls ( xPicker, UNO_QUERY );
434 Reference < XFilterManager > xFilterManager ( xPicker, UNO_QUERY );
436 Sequence< OUString > sFiles = xPicker->getFiles();
437 int nFiles = sFiles.getLength();
439 int nArgs=3;
440 Sequence< PropertyValue > aArgs(3);
442 Reference < com::sun::star::task::XInteractionHandler2 > xInteraction(
443 task::InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(), 0) );
445 aArgs[0].Name = OUString("InteractionHandler");
446 aArgs[0].Value <<= xInteraction;
448 sal_Int16 nMacroExecMode = ::com::sun::star::document::MacroExecMode::USE_CONFIG;
449 aArgs[1].Name = OUString("MacroExecutionMode");
450 aArgs[1].Value <<= nMacroExecMode;
452 sal_Int16 nUpdateDoc = ::com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG;
453 aArgs[2].Name = OUString("UpdateDocMode");
454 aArgs[2].Value <<= nUpdateDoc;
456 // use the filedlghelper to get the current filter name,
457 // because it removes the extensions before you get the filter name.
458 OUString aFilterName( pThis->m_pFileDlg->GetCurrentFilter() );
460 if ( xPickerControls.is() )
463 // Set readonly flag
465 sal_Bool bReadOnly = sal_False;
468 xPickerControls->getValue( ExtendedFilePickerElementIds::CHECKBOX_READONLY, 0 ) >>= bReadOnly;
470 // Only set porperty if readonly is set to TRUE
472 if ( bReadOnly )
474 aArgs.realloc( ++nArgs );
475 aArgs[nArgs-1].Name = OUString("ReadOnly");
476 aArgs[nArgs-1].Value <<= bReadOnly;
479 // Get version string
481 sal_Int32 iVersion = -1;
483 xPickerControls->getValue( ExtendedFilePickerElementIds::LISTBOX_VERSION, ControlActions::GET_SELECTED_ITEM_INDEX ) >>= iVersion;
485 if ( iVersion >= 0 )
487 sal_Int16 uVersion = (sal_Int16)iVersion;
489 aArgs.realloc( ++nArgs );
490 aArgs[nArgs-1].Name = OUString("Version");
491 aArgs[nArgs-1].Value <<= uVersion;
494 // Retrieve the current filter
496 if ( aFilterName.isEmpty() )
497 xPickerControls->getValue( CommonFilePickerElementIds::LISTBOX_FILTER, ControlActions::GET_SELECTED_ITEM ) >>= aFilterName;
502 // Convert UI filter name to internal filter name
504 if ( !aFilterName.isEmpty() )
506 const SfxFilter* pFilter = SFX_APP()->GetFilterMatcher().GetFilter4UIName( aFilterName, 0, SFX_FILTER_NOTINFILEDLG );
508 if ( pFilter )
510 aFilterName = pFilter->GetFilterName();
512 if ( !aFilterName.isEmpty() )
514 aArgs.realloc( ++nArgs );
515 aArgs[nArgs-1].Name = OUString("FilterName");
516 aArgs[nArgs-1].Value <<= aFilterName;
521 if ( 1 == nFiles )
522 OpenURL( sFiles[0], OUString( "_default" ), aArgs );
523 else
525 OUString aBaseDirURL = sFiles[0];
526 if ( !aBaseDirURL.isEmpty() && aBaseDirURL[aBaseDirURL.getLength()-1] != '/' )
527 aBaseDirURL += "/";
529 int iFiles;
530 for ( iFiles = 1; iFiles < nFiles; iFiles++ )
532 OUString aURL = aBaseDirURL;
533 aURL += sFiles[iFiles];
534 OpenURL( aURL, OUString( "_default" ), aArgs );
539 catch ( ... )
544 #ifdef WNT
545 // Destroy dialog to prevent problems with custom controls
546 // This fix is dependent on the dialog settings. Destroying the dialog here will
547 // crash the non-native dialog implementation! Therefore make this dependent on
548 // the settings.
549 if ( SvtMiscOptions().UseSystemFileDialog() )
551 delete pThis->m_pFileDlg;
552 pThis->m_pFileDlg = NULL;
554 #endif
556 LeaveModalMode();
557 return 0;
560 // ---------------------------------------------------------------------------
562 void ShutdownIcon::addTerminateListener()
564 ShutdownIcon* pInst = getInstance();
565 if ( ! pInst)
566 return;
568 if (pInst->m_bListenForTermination)
569 return;
571 Reference< XDesktop2 > xDesktop = pInst->m_xDesktop;
572 if ( ! xDesktop.is())
573 return;
575 xDesktop->addTerminateListener( pInst );
576 pInst->m_bListenForTermination = true;
579 // ---------------------------------------------------------------------------
581 void ShutdownIcon::terminateDesktop()
583 ShutdownIcon* pInst = getInstance();
584 if ( ! pInst)
585 return;
587 Reference< XDesktop2 > xDesktop = pInst->m_xDesktop;
588 if ( ! xDesktop.is())
589 return;
591 // always remove ourselves as listener
592 pInst->m_bListenForTermination = true;
593 xDesktop->removeTerminateListener( pInst );
595 // terminate desktop only if no tasks exist
596 Reference< XIndexAccess > xTasks ( xDesktop->getFrames(), UNO_QUERY );
597 if( xTasks.is() && xTasks->getCount() < 1 )
598 new IdleTerminate( xDesktop );
600 // remove the instance pointer
601 ShutdownIcon::pShutdownIcon = 0;
604 // ---------------------------------------------------------------------------
606 ShutdownIcon* ShutdownIcon::getInstance()
608 OSL_ASSERT( pShutdownIcon );
609 return pShutdownIcon;
612 // ---------------------------------------------------------------------------
614 ShutdownIcon* ShutdownIcon::createInstance()
616 if (pShutdownIcon)
617 return pShutdownIcon;
619 ShutdownIcon *pIcon = NULL;
620 try {
621 pIcon = new ShutdownIcon( comphelper::getProcessComponentContext() );
622 pIcon->init ();
623 pShutdownIcon = pIcon;
624 } catch (...) {
625 delete pIcon;
628 return pShutdownIcon;
631 void ShutdownIcon::init() throw( ::com::sun::star::uno::Exception )
633 // access resource system and sfx only protected by solarmutex
634 ::SolarMutexGuard aSolarGuard;
635 ResMgr *pResMgr = SfxResId::GetResMgr();
637 ::osl::ResettableMutexGuard aGuard( m_aMutex );
638 m_pResMgr = pResMgr;
639 aGuard.clear();
640 Reference < XDesktop2 > xDesktop = Desktop::create( m_xContext );
641 aGuard.reset();
642 m_xDesktop = xDesktop;
645 // ---------------------------------------------------------------------------
647 void SAL_CALL ShutdownIcon::disposing()
649 m_xContext.clear();
650 m_xDesktop.clear();
653 // ---------------------------------------------------------------------------
655 // XEventListener
656 void SAL_CALL ShutdownIcon::disposing( const ::com::sun::star::lang::EventObject& )
657 throw(::com::sun::star::uno::RuntimeException)
661 // ---------------------------------------------------------------------------
663 // XTerminateListener
664 void SAL_CALL ShutdownIcon::queryTermination( const ::com::sun::star::lang::EventObject& )
665 throw(::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException)
667 SAL_INFO("sfx2.appl", "ShutdownIcon::queryTermination: veto is " << m_bVeto);
668 ::osl::ClearableMutexGuard aGuard( m_aMutex );
670 if ( m_bVeto )
671 throw ::com::sun::star::frame::TerminationVetoException();
675 // ---------------------------------------------------------------------------
677 void SAL_CALL ShutdownIcon::notifyTermination( const ::com::sun::star::lang::EventObject& )
678 throw(::com::sun::star::uno::RuntimeException)
683 // ---------------------------------------------------------------------------
685 void SAL_CALL ShutdownIcon::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments )
686 throw( ::com::sun::star::uno::Exception )
688 ::osl::ResettableMutexGuard aGuard( m_aMutex );
690 // third argument only sets veto, everything else will be ignored!
691 if (aArguments.getLength() > 2)
693 sal_Bool bVeto = sal_True;
694 bVeto = ::cppu::any2bool(aArguments[2]);
695 m_bVeto = bVeto;
696 return;
699 if ( aArguments.getLength() > 0 )
701 if ( !ShutdownIcon::pShutdownIcon )
705 sal_Bool bQuickstart = sal_False;
706 bQuickstart = ::cppu::any2bool( aArguments[0] );
707 if( !bQuickstart && !GetAutostart() )
708 return;
709 aGuard.clear();
710 init ();
711 aGuard.reset();
712 if ( !m_xDesktop.is() )
713 return;
715 /* Create a sub-classed instance - foo */
716 ShutdownIcon::pShutdownIcon = this;
717 initSystray();
719 catch(const ::com::sun::star::lang::IllegalArgumentException&)
724 if ( aArguments.getLength() > 1 )
726 sal_Bool bAutostart = sal_False;
727 bAutostart = ::cppu::any2bool( aArguments[1] );
728 if (bAutostart && !GetAutostart())
729 SetAutostart( sal_True );
730 if (!bAutostart && GetAutostart())
731 SetAutostart( sal_False );
736 // -------------------------------
738 void ShutdownIcon::EnterModalMode()
740 bModalMode = sal_True;
743 // -------------------------------
745 void ShutdownIcon::LeaveModalMode()
747 bModalMode = sal_False;
750 #ifdef WNT
751 // defined in shutdowniconw32.cxx
752 #elif defined MACOSX
753 // defined in shutdowniconaqua.cxx
754 #else
755 bool ShutdownIcon::IsQuickstarterInstalled()
757 #ifndef ENABLE_QUICKSTART_APPLET
758 return false;
759 #else // !ENABLE_QUICKSTART_APPLET
760 #ifdef UNX
761 return LoadModule( NULL, NULL, NULL);
762 #endif // UNX
763 #endif // !ENABLE_QUICKSTART_APPLET
765 #endif // !WNT
767 // ---------------------------------------------------------------------------
769 #if defined (ENABLE_QUICKSTART_APPLET) && defined (UNX)
771 * Return the XDG autostart directory.
772 * http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
773 * Available in Unix and with Quickstart enabled.
774 * @param bCreate Create the directory if it does not exist yet.
775 * @return OUString containing the autostart directory path.
777 static OUString getAutostartDir( bool bCreate = false )
779 OUString aShortcut;
780 const char *pConfigHome;
781 if( (pConfigHome = getenv("XDG_CONFIG_HOME") ) )
782 aShortcut = OStringToOUString( OString( pConfigHome ),
783 RTL_TEXTENCODING_UTF8 );
784 else
786 OUString aHomeURL;
787 osl::Security().getHomeDir( aHomeURL );
788 ::osl::File::getSystemPathFromFileURL( aHomeURL, aShortcut );
789 aShortcut += "/.config";
791 aShortcut += "/autostart";
792 if (bCreate)
794 OUString aShortcutUrl;
795 osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
796 osl::Directory::createPath( aShortcutUrl );
798 return aShortcut;
800 #endif
802 OUString ShutdownIcon::getShortcutName()
804 #ifndef ENABLE_QUICKSTART_APPLET
805 return OUString();
806 #else
808 OUString aShortcutName( "StarOffice 6.0" );
809 ResMgr* pMgr = SfxResId::GetResMgr();
810 if( pMgr )
812 ::SolarMutexGuard aGuard;
813 aShortcutName = SFX2_RESSTR(STR_QUICKSTART_LNKNAME);
815 #ifdef WNT
816 aShortcutName += ".lnk";
818 OUString aShortcut(GetAutostartFolderNameW32());
819 aShortcut += "\\";
820 aShortcut += aShortcutName;
821 #else // UNX
822 OUString aShortcut = getAutostartDir();
823 aShortcut += "/qstart.desktop";
824 #endif // UNX
825 return aShortcut;
826 #endif // ENABLE_QUICKSTART_APPLET
829 bool ShutdownIcon::GetAutostart( )
831 #if defined MACOSX
832 return true;
833 #else
834 bool bRet = false;
835 #ifdef ENABLE_QUICKSTART_APPLET
836 OUString aShortcut( getShortcutName() );
837 OUString aShortcutUrl;
838 osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
839 osl::File f( aShortcutUrl );
840 osl::File::RC error = f.open( osl_File_OpenFlag_Read );
841 if( error == osl::File::E_None )
843 f.close();
844 bRet = true;
846 #endif // ENABLE_QUICKSTART_APPLET
847 return bRet;
848 #endif
851 void ShutdownIcon::SetAutostart( bool bActivate )
853 #ifdef ENABLE_QUICKSTART_APPLET
854 OUString aShortcut( getShortcutName() );
856 if( bActivate && IsQuickstarterInstalled() )
858 #ifdef WNT
859 EnableAutostartW32( aShortcut );
860 #else // UNX
861 getAutostartDir( true );
863 OUString aPath( "${BRAND_BASE_DIR}/share/xdg/qstart.desktop" );
864 Bootstrap::expandMacros( aPath );
866 OUString aDesktopFile;
867 ::osl::File::getSystemPathFromFileURL( aPath, aDesktopFile );
869 OString aDesktopFileUnx = OUStringToOString( aDesktopFile,
870 osl_getThreadTextEncoding() );
871 OString aShortcutUnx = OUStringToOString( aShortcut,
872 osl_getThreadTextEncoding() );
873 if ((0 != symlink(aDesktopFileUnx.getStr(), aShortcutUnx.getStr())) && (errno == EEXIST))
875 unlink(aShortcutUnx.getStr());
876 int ret = symlink(aDesktopFileUnx.getStr(), aShortcutUnx.getStr());
877 (void)ret; //deliberately ignore return value, it's non-critical if it fails
880 ShutdownIcon *pIcon = ShutdownIcon::createInstance();
881 if( pIcon )
882 pIcon->initSystray();
883 #endif // UNX
885 else
887 OUString aShortcutUrl;
888 ::osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
889 ::osl::File::remove( aShortcutUrl );
890 #ifdef UNX
891 if (pShutdownIcon)
893 ShutdownIcon *pIcon = getInstance();
894 pIcon->deInitSystray();
896 #endif
898 #else
899 (void)bActivate; // unused variable
900 #endif // ENABLE_QUICKSTART_APPLET
903 static const ::sal_Int32 PROPHANDLE_TERMINATEVETOSTATE = 0;
905 // XFastPropertySet
906 void SAL_CALL ShutdownIcon::setFastPropertyValue( ::sal_Int32 nHandle,
907 const ::com::sun::star::uno::Any& aValue )
908 throw (::com::sun::star::beans::UnknownPropertyException,
909 ::com::sun::star::beans::PropertyVetoException,
910 ::com::sun::star::lang::IllegalArgumentException,
911 ::com::sun::star::lang::WrappedTargetException,
912 ::com::sun::star::uno::RuntimeException)
914 switch(nHandle)
916 case PROPHANDLE_TERMINATEVETOSTATE :
918 // use new value in case it's a valid information only
919 ::sal_Bool bState( sal_False );
920 if (! (aValue >>= bState))
921 return;
923 m_bVeto = bState;
924 if (m_bVeto && ! m_bListenForTermination)
925 addTerminateListener();
927 break;
929 default :
930 throw ::com::sun::star::beans::UnknownPropertyException();
934 // XFastPropertySet
935 ::com::sun::star::uno::Any SAL_CALL ShutdownIcon::getFastPropertyValue( ::sal_Int32 nHandle )
936 throw (::com::sun::star::beans::UnknownPropertyException,
937 ::com::sun::star::lang::WrappedTargetException,
938 ::com::sun::star::uno::RuntimeException)
940 ::com::sun::star::uno::Any aValue;
941 switch(nHandle)
943 case PROPHANDLE_TERMINATEVETOSTATE :
945 bool bState = (m_bListenForTermination && m_bVeto);
946 aValue <<= bState;
948 break;
950 default :
951 throw ::com::sun::star::beans::UnknownPropertyException();
954 return aValue;
957 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */