bump product version to 4.2.0.1
[LibreOffice.git] / sfx2 / source / appl / shutdownicon.cxx
blobea865f481322d40330b32eb390e5c898d6a29e53
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 <config_folders.h>
22 #include <shutdownicon.hxx>
23 #include <app.hrc>
24 #include <sfx2/app.hxx>
25 #include <osl/mutex.hxx>
26 #include <svtools/imagemgr.hxx>
27 #include <svtools/miscopt.hxx>
28 #include <com/sun/star/task/InteractionHandler.hpp>
29 #include <com/sun/star/frame/Desktop.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/XComponentLoader.hpp>
34 #include <com/sun/star/frame/XFrame.hpp>
35 #include <com/sun/star/util/URLTransformer.hpp>
36 #include <com/sun/star/util/XURLTransformer.hpp>
37 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
38 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
39 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
40 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
41 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
42 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
43 #include <com/sun/star/document/MacroExecMode.hpp>
44 #include <com/sun/star/document/UpdateDocMode.hpp>
45 #include <sfx2/filedlghelper.hxx>
46 #include <sfx2/fcontnr.hxx>
47 #include <comphelper/processfactory.hxx>
48 #include <cppuhelper/compbase1.hxx>
49 #include <sfx2/dispatch.hxx>
50 #include <comphelper/extract.hxx>
51 #include <tools/urlobj.hxx>
52 #include <osl/security.hxx>
53 #include <osl/file.hxx>
54 #include <rtl/bootstrap.hxx>
55 #include <rtl/ustrbuf.hxx>
56 #ifdef UNX // need symlink
57 #include <unistd.h>
58 #include <errno.h>
59 #endif
60 #include <vcl/timer.hxx>
62 #include <sfx2/sfxresid.hxx>
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::io;
69 using namespace ::com::sun::star::lang;
70 using namespace ::com::sun::star::beans;
71 using namespace ::com::sun::star::util;
72 using namespace ::com::sun::star::ui::dialogs;
73 #ifdef WNT
74 #else
75 using namespace ::rtl;
76 #endif
77 using namespace ::sfx2;
79 #ifdef ENABLE_QUICKSTART_APPLET
80 # if !defined(WIN32) && !defined(MACOSX)
81 extern "C" { static void SAL_CALL thisModule() {} }
82 # endif
83 #endif
85 #if defined(UNX) && defined(ENABLE_SYSTRAY_GTK) && !defined(PLUGIN_NAME)
86 #define PLUGIN_NAME "libqstart_gtklo.so"
87 #endif
89 class SfxNotificationListener_Impl : public cppu::WeakImplHelper1< XDispatchResultListener >
91 public:
92 virtual void SAL_CALL dispatchFinished( const DispatchResultEvent& aEvent ) throw( RuntimeException );
93 virtual void SAL_CALL disposing( const EventObject& aEvent ) throw( RuntimeException );
96 void SAL_CALL SfxNotificationListener_Impl::dispatchFinished( const DispatchResultEvent& ) throw( RuntimeException )
98 ShutdownIcon::LeaveModalMode();
101 void SAL_CALL SfxNotificationListener_Impl::disposing( const EventObject& ) throw( RuntimeException )
105 SFX_IMPL_XSERVICEINFO_CTX( ShutdownIcon, "com.sun.star.office.Quickstart", "com.sun.star.comp.desktop.QuickstartWrapper" ) \
106 SFX_IMPL_ONEINSTANCEFACTORY( ShutdownIcon );
108 bool ShutdownIcon::bModalMode = false;
109 ShutdownIcon* ShutdownIcon::pShutdownIcon = NULL;
111 #if !defined( ENABLE_QUICKSTART_APPLET ) || defined( UNX )
112 // To remove conditionals
113 extern "C" {
114 static void disabled_initSystray() { }
115 static void disabled_deInitSystray() { }
117 #endif
119 bool ShutdownIcon::LoadModule( osl::Module **pModule,
120 oslGenericFunction *pInit,
121 oslGenericFunction *pDeInit )
123 if ( pModule )
125 OSL_ASSERT ( pInit && pDeInit );
126 *pInit = *pDeInit = NULL;
127 *pModule = NULL;
130 #ifdef ENABLE_QUICKSTART_APPLET
131 # ifdef WIN32
132 if ( pModule )
134 *pInit = win32_init_sys_tray;
135 *pDeInit = win32_shutdown_sys_tray;
137 return true;
138 # elif defined MACOSX
139 *pInit = aqua_init_systray;
140 *pDeInit = aqua_shutdown_systray;
141 return true;
142 # else // UNX
143 osl::Module *pPlugin;
144 pPlugin = new osl::Module();
146 oslGenericFunction pTmpInit = NULL;
147 oslGenericFunction pTmpDeInit = NULL;
149 #define DOSTRING( x ) #x
150 #define STRING( x ) DOSTRING( x )
152 if ( pPlugin->loadRelative( &thisModule, OUString (STRING( PLUGIN_NAME ) ) ) )
154 pTmpInit = pPlugin->getFunctionSymbol(
155 OUString( "plugin_init_sys_tray" ) );
156 pTmpDeInit = pPlugin->getFunctionSymbol(
157 OUString( "plugin_shutdown_sys_tray" ) );
159 if ( !pTmpInit || !pTmpDeInit )
161 delete pPlugin;
162 pPlugin = NULL;
164 if ( pModule )
166 *pModule = pPlugin;
167 *pInit = pTmpInit;
168 *pDeInit = pTmpDeInit;
170 else
172 bool bRet = pPlugin != NULL;
173 delete pPlugin;
174 return bRet;
176 # endif // UNX
177 #endif // ENABLE_QUICKSTART_APPLET
179 #if !defined( ENABLE_QUICKSTART_APPLET ) || defined( UNX )
180 // Avoid unreachable code. In the ENABLE_QUICKSTART_APPLET && !UNX
181 // case, we have already returned.
182 if ( pModule )
184 if ( !*pInit )
185 *pInit = disabled_initSystray;
186 if ( !*pDeInit )
187 *pDeInit = disabled_deInitSystray;
190 return true;
191 #endif // !ENABLE_QUICKSTART_APPLET || UNX
194 // These two timeouts are necessary to avoid there being
195 // plugin frames still on the stack, after unloading that
196 // code, causing a crash during disabling / termination.
197 class IdleUnloader : Timer
199 ::osl::Module *m_pModule;
200 public:
201 IdleUnloader (::osl::Module **pModule) :
202 m_pModule (*pModule)
204 *pModule = NULL;
205 Start();
207 virtual void Timeout()
209 delete m_pModule;
210 delete this;
214 class IdleTerminate : Timer
216 Reference< XDesktop2 > m_xDesktop;
217 public:
218 IdleTerminate (Reference< XDesktop2 > xDesktop)
220 m_xDesktop = xDesktop;
221 Start();
223 virtual void Timeout()
225 m_xDesktop->terminate();
226 delete this;
230 void ShutdownIcon::initSystray()
232 if (m_bInitialized)
233 return;
234 m_bInitialized = true;
236 (void) LoadModule( &m_pPlugin, &m_pInitSystray, &m_pDeInitSystray );
237 m_bVeto = true;
238 m_pInitSystray();
241 void ShutdownIcon::deInitSystray()
243 if (!m_bInitialized)
244 return;
246 if (m_pDeInitSystray)
247 m_pDeInitSystray();
249 m_bVeto = false;
250 m_pInitSystray = 0;
251 m_pDeInitSystray = 0;
252 new IdleUnloader (&m_pPlugin);
254 delete m_pFileDlg;
255 m_pFileDlg = NULL;
256 m_bInitialized = false;
260 ShutdownIcon::ShutdownIcon( const Reference< XComponentContext > & rxContext ) :
261 ShutdownIconServiceBase( m_aMutex ),
262 m_bVeto ( false ),
263 m_bListenForTermination ( false ),
264 m_bSystemDialogs( false ),
265 m_pResMgr( NULL ),
266 m_pFileDlg( NULL ),
267 m_xContext( rxContext ),
268 m_pInitSystray( 0 ),
269 m_pDeInitSystray( 0 ),
270 m_pPlugin( 0 ),
271 m_bInitialized( false )
273 m_bSystemDialogs = SvtMiscOptions().UseSystemFileDialog();
276 ShutdownIcon::~ShutdownIcon()
278 deInitSystray();
279 new IdleUnloader (&m_pPlugin);
282 // ---------------------------------------------------------------------------
284 void ShutdownIcon::OpenURL( const OUString& aURL, const OUString& rTarget, const Sequence< PropertyValue >& aArgs )
286 if ( getInstance() && getInstance()->m_xDesktop.is() )
288 Reference < XDispatchProvider > xDispatchProvider( getInstance()->m_xDesktop, UNO_QUERY );
289 if ( xDispatchProvider.is() )
291 com::sun::star::util::URL aDispatchURL;
292 aDispatchURL.Complete = aURL;
294 Reference< util::XURLTransformer > xURLTransformer( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
297 Reference< com::sun::star::frame::XDispatch > xDispatch;
299 xURLTransformer->parseStrict( aDispatchURL );
300 xDispatch = xDispatchProvider->queryDispatch( aDispatchURL, rTarget, 0 );
301 if ( xDispatch.is() )
302 xDispatch->dispatch( aDispatchURL, aArgs );
304 catch ( com::sun::star::uno::RuntimeException& )
306 throw;
308 catch ( com::sun::star::uno::Exception& )
315 // ---------------------------------------------------------------------------
317 void ShutdownIcon::FileOpen()
319 if ( getInstance() && getInstance()->m_xDesktop.is() )
321 ::SolarMutexGuard aGuard;
322 EnterModalMode();
323 getInstance()->StartFileDialog();
327 // ---------------------------------------------------------------------------
329 void ShutdownIcon::FromTemplate()
331 if ( getInstance() && getInstance()->m_xDesktop.is() )
333 Reference < ::com::sun::star::frame::XFramesSupplier > xDesktop ( getInstance()->m_xDesktop, UNO_QUERY);
334 Reference < ::com::sun::star::frame::XFrame > xFrame( xDesktop->getActiveFrame() );
335 if ( !xFrame.is() )
336 xFrame = Reference < ::com::sun::star::frame::XFrame >( xDesktop, UNO_QUERY );
338 URL aTargetURL;
339 aTargetURL.Complete = "slot:5500";
340 Reference< util::XURLTransformer > xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
341 xTrans->parseStrict( aTargetURL );
343 Reference < ::com::sun::star::frame::XDispatchProvider > xProv( xFrame, UNO_QUERY );
344 Reference < ::com::sun::star::frame::XDispatch > xDisp;
345 if ( xProv.is() )
347 if (aTargetURL.Protocol == "slot:")
348 xDisp = xProv->queryDispatch( aTargetURL, OUString(), 0 );
349 else
350 xDisp = xProv->queryDispatch( aTargetURL, OUString("_blank"), 0 );
352 if ( xDisp.is() )
354 Sequence<PropertyValue> aArgs(1);
355 PropertyValue* pArg = aArgs.getArray();
356 pArg[0].Name = "Referer";
357 pArg[0].Value <<= OUString("private:user");
358 Reference< ::com::sun::star::frame::XNotifyingDispatch > xNotifyer( xDisp, UNO_QUERY );
359 if ( xNotifyer.is() )
361 EnterModalMode();
362 xNotifyer->dispatchWithNotification( aTargetURL, aArgs, new SfxNotificationListener_Impl() );
364 else
365 xDisp->dispatch( aTargetURL, aArgs );
370 // ---------------------------------------------------------------------------
371 #include <tools/rcid.h>
372 OUString ShutdownIcon::GetResString( int id )
374 ::SolarMutexGuard aGuard;
376 if( ! m_pResMgr )
377 m_pResMgr = SfxResId::GetResMgr();
378 ResId aResId( id, *m_pResMgr );
379 aResId.SetRT( RSC_STRING );
380 if( !m_pResMgr || !m_pResMgr->IsAvailable( aResId ) )
381 return OUString();
383 return ResId(id, *m_pResMgr).toString();
386 // ---------------------------------------------------------------------------
388 OUString ShutdownIcon::GetUrlDescription( const OUString& aUrl )
390 ::SolarMutexGuard aGuard;
392 return OUString( SvFileInformationManager::GetDescription( INetURLObject( aUrl ) ) );
395 // ---------------------------------------------------------------------------
397 void ShutdownIcon::StartFileDialog()
399 ::SolarMutexGuard aGuard;
401 bool bDirty = ( m_bSystemDialogs != static_cast<bool>(SvtMiscOptions().UseSystemFileDialog()) );
403 if ( m_pFileDlg && bDirty )
405 // Destroy instance as changing the system file dialog setting
406 // forces us to create a new FileDialogHelper instance!
407 delete m_pFileDlg;
408 m_pFileDlg = NULL;
411 if ( !m_pFileDlg )
412 m_pFileDlg = new FileDialogHelper(
413 ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION,
414 SFXWB_MULTISELECTION, OUString() );
415 m_pFileDlg->StartExecuteModal( STATIC_LINK( this, ShutdownIcon, DialogClosedHdl_Impl ) );
418 // ---------------------------------------------------------------------------
420 IMPL_STATIC_LINK( ShutdownIcon, DialogClosedHdl_Impl, FileDialogHelper*, EMPTYARG )
422 DBG_ASSERT( pThis->m_pFileDlg, "ShutdownIcon, DialogClosedHdl_Impl(): no file dialog" );
424 // use constructor for filling up filters automatically!
425 if ( ERRCODE_NONE == pThis->m_pFileDlg->GetError() )
427 Reference< XFilePicker > xPicker = pThis->m_pFileDlg->GetFilePicker();
432 if ( xPicker.is() )
435 Reference < XFilePickerControlAccess > xPickerControls ( xPicker, UNO_QUERY );
436 Reference < XFilterManager > xFilterManager ( xPicker, UNO_QUERY );
438 Sequence< OUString > sFiles = xPicker->getFiles();
439 int nFiles = sFiles.getLength();
441 int nArgs=3;
442 Sequence< PropertyValue > aArgs(3);
444 Reference < com::sun::star::task::XInteractionHandler2 > xInteraction(
445 task::InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(), 0) );
447 aArgs[0].Name = "InteractionHandler";
448 aArgs[0].Value <<= xInteraction;
450 sal_Int16 nMacroExecMode = ::com::sun::star::document::MacroExecMode::USE_CONFIG;
451 aArgs[1].Name = "MacroExecutionMode";
452 aArgs[1].Value <<= nMacroExecMode;
454 sal_Int16 nUpdateDoc = ::com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG;
455 aArgs[2].Name = "UpdateDocMode";
456 aArgs[2].Value <<= nUpdateDoc;
458 // use the filedlghelper to get the current filter name,
459 // because it removes the extensions before you get the filter name.
460 OUString aFilterName( pThis->m_pFileDlg->GetCurrentFilter() );
462 if ( xPickerControls.is() )
465 // Set readonly flag
467 sal_Bool bReadOnly = sal_False;
470 xPickerControls->getValue( ExtendedFilePickerElementIds::CHECKBOX_READONLY, 0 ) >>= bReadOnly;
472 // Only set porperty if readonly is set to TRUE
474 if ( bReadOnly )
476 aArgs.realloc( ++nArgs );
477 aArgs[nArgs-1].Name = "ReadOnly";
478 aArgs[nArgs-1].Value <<= bReadOnly;
481 // Get version string
483 sal_Int32 iVersion = -1;
485 xPickerControls->getValue( ExtendedFilePickerElementIds::LISTBOX_VERSION, ControlActions::GET_SELECTED_ITEM_INDEX ) >>= iVersion;
487 if ( iVersion >= 0 )
489 sal_Int16 uVersion = (sal_Int16)iVersion;
491 aArgs.realloc( ++nArgs );
492 aArgs[nArgs-1].Name = "Version";
493 aArgs[nArgs-1].Value <<= uVersion;
496 // Retrieve the current filter
498 if ( aFilterName.isEmpty() )
499 xPickerControls->getValue( CommonFilePickerElementIds::LISTBOX_FILTER, ControlActions::GET_SELECTED_ITEM ) >>= aFilterName;
504 // Convert UI filter name to internal filter name
506 if ( !aFilterName.isEmpty() )
508 const SfxFilter* pFilter = SFX_APP()->GetFilterMatcher().GetFilter4UIName( aFilterName, 0, SFX_FILTER_NOTINFILEDLG );
510 if ( pFilter )
512 aFilterName = pFilter->GetFilterName();
514 if ( !aFilterName.isEmpty() )
516 aArgs.realloc( ++nArgs );
517 aArgs[nArgs-1].Name = "FilterName";
518 aArgs[nArgs-1].Value <<= aFilterName;
523 if ( 1 == nFiles )
524 OpenURL( sFiles[0], OUString( "_default" ), aArgs );
525 else
527 OUString aBaseDirURL = sFiles[0];
528 if ( !aBaseDirURL.isEmpty() && !aBaseDirURL.endsWith("/") )
529 aBaseDirURL += "/";
531 int iFiles;
532 for ( iFiles = 1; iFiles < nFiles; iFiles++ )
534 OUString aURL = aBaseDirURL;
535 aURL += sFiles[iFiles];
536 OpenURL( aURL, OUString( "_default" ), aArgs );
541 catch ( ... )
546 #ifdef WNT
547 // Destroy dialog to prevent problems with custom controls
548 // This fix is dependent on the dialog settings. Destroying the dialog here will
549 // crash the non-native dialog implementation! Therefore make this dependent on
550 // the settings.
551 if ( SvtMiscOptions().UseSystemFileDialog() )
553 delete pThis->m_pFileDlg;
554 pThis->m_pFileDlg = NULL;
556 #endif
558 LeaveModalMode();
559 return 0;
562 // ---------------------------------------------------------------------------
564 void ShutdownIcon::addTerminateListener()
566 ShutdownIcon* pInst = getInstance();
567 if ( ! pInst)
568 return;
570 if (pInst->m_bListenForTermination)
571 return;
573 Reference< XDesktop2 > xDesktop = pInst->m_xDesktop;
574 if ( ! xDesktop.is())
575 return;
577 xDesktop->addTerminateListener( pInst );
578 pInst->m_bListenForTermination = true;
581 // ---------------------------------------------------------------------------
583 void ShutdownIcon::terminateDesktop()
585 ShutdownIcon* pInst = getInstance();
586 if ( ! pInst)
587 return;
589 Reference< XDesktop2 > xDesktop = pInst->m_xDesktop;
590 if ( ! xDesktop.is())
591 return;
593 // always remove ourselves as listener
594 pInst->m_bListenForTermination = true;
595 xDesktop->removeTerminateListener( pInst );
597 // terminate desktop only if no tasks exist
598 Reference< XIndexAccess > xTasks ( xDesktop->getFrames(), UNO_QUERY );
599 if( xTasks.is() && xTasks->getCount() < 1 )
600 new IdleTerminate( xDesktop );
602 // remove the instance pointer
603 ShutdownIcon::pShutdownIcon = 0;
606 // ---------------------------------------------------------------------------
608 ShutdownIcon* ShutdownIcon::getInstance()
610 OSL_ASSERT( pShutdownIcon );
611 return pShutdownIcon;
614 // ---------------------------------------------------------------------------
616 ShutdownIcon* ShutdownIcon::createInstance()
618 if (pShutdownIcon)
619 return pShutdownIcon;
621 ShutdownIcon *pIcon = NULL;
622 try {
623 pIcon = new ShutdownIcon( comphelper::getProcessComponentContext() );
624 pIcon->init ();
625 pShutdownIcon = pIcon;
626 } catch (...) {
627 delete pIcon;
630 return pShutdownIcon;
633 void ShutdownIcon::init() throw( ::com::sun::star::uno::Exception )
635 // access resource system and sfx only protected by solarmutex
636 ::SolarMutexGuard aSolarGuard;
637 ResMgr *pResMgr = SfxResId::GetResMgr();
639 ::osl::ResettableMutexGuard aGuard( m_aMutex );
640 m_pResMgr = pResMgr;
641 aGuard.clear();
642 Reference < XDesktop2 > xDesktop = Desktop::create( m_xContext );
643 aGuard.reset();
644 m_xDesktop = xDesktop;
647 // ---------------------------------------------------------------------------
649 void SAL_CALL ShutdownIcon::disposing()
651 m_xContext.clear();
652 m_xDesktop.clear();
655 // ---------------------------------------------------------------------------
657 // XEventListener
658 void SAL_CALL ShutdownIcon::disposing( const ::com::sun::star::lang::EventObject& )
659 throw(::com::sun::star::uno::RuntimeException)
663 // ---------------------------------------------------------------------------
665 // XTerminateListener
666 void SAL_CALL ShutdownIcon::queryTermination( const ::com::sun::star::lang::EventObject& )
667 throw(::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException)
669 SAL_INFO("sfx.appl", "ShutdownIcon::queryTermination: veto is " << m_bVeto);
670 ::osl::ClearableMutexGuard aGuard( m_aMutex );
672 if ( m_bVeto )
673 throw ::com::sun::star::frame::TerminationVetoException();
677 // ---------------------------------------------------------------------------
679 void SAL_CALL ShutdownIcon::notifyTermination( const ::com::sun::star::lang::EventObject& )
680 throw(::com::sun::star::uno::RuntimeException)
685 // ---------------------------------------------------------------------------
687 void SAL_CALL ShutdownIcon::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments )
688 throw( ::com::sun::star::uno::Exception )
690 ::osl::ResettableMutexGuard aGuard( m_aMutex );
692 // third argument only sets veto, everything else will be ignored!
693 if (aArguments.getLength() > 2)
695 sal_Bool bVeto = sal_True;
696 bVeto = ::cppu::any2bool(aArguments[2]);
697 m_bVeto = bVeto;
698 return;
701 if ( aArguments.getLength() > 0 )
703 if ( !ShutdownIcon::pShutdownIcon )
707 sal_Bool bQuickstart = sal_False;
708 bQuickstart = ::cppu::any2bool( aArguments[0] );
709 if( !bQuickstart && !GetAutostart() )
710 return;
711 aGuard.clear();
712 init ();
713 aGuard.reset();
714 if ( !m_xDesktop.is() )
715 return;
717 /* Create a sub-classed instance - foo */
718 ShutdownIcon::pShutdownIcon = this;
719 initSystray();
721 catch(const ::com::sun::star::lang::IllegalArgumentException&)
726 if ( aArguments.getLength() > 1 )
728 sal_Bool bAutostart = sal_False;
729 bAutostart = ::cppu::any2bool( aArguments[1] );
730 if (bAutostart && !GetAutostart())
731 SetAutostart( sal_True );
732 if (!bAutostart && GetAutostart())
733 SetAutostart( sal_False );
738 // -------------------------------
740 void ShutdownIcon::EnterModalMode()
742 bModalMode = sal_True;
745 // -------------------------------
747 void ShutdownIcon::LeaveModalMode()
749 bModalMode = sal_False;
752 #ifdef WNT
753 // defined in shutdowniconw32.cxx
754 #elif defined MACOSX
755 // defined in shutdowniconaqua.cxx
756 #else
757 bool ShutdownIcon::IsQuickstarterInstalled()
759 #ifndef ENABLE_QUICKSTART_APPLET
760 return false;
761 #else // !ENABLE_QUICKSTART_APPLET
762 #ifdef UNX
763 return LoadModule( NULL, NULL, NULL);
764 #endif // UNX
765 #endif // !ENABLE_QUICKSTART_APPLET
767 #endif // !WNT
769 // ---------------------------------------------------------------------------
771 #if defined (ENABLE_QUICKSTART_APPLET) && defined (UNX)
773 * Return the XDG autostart directory.
774 * http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
775 * Available in Unix and with Quickstart enabled.
776 * @param bCreate Create the directory if it does not exist yet.
777 * @return OUString containing the autostart directory path.
779 static OUString getAutostartDir( bool bCreate = false )
781 OUString aShortcut;
782 const char *pConfigHome;
783 if( (pConfigHome = getenv("XDG_CONFIG_HOME") ) )
784 aShortcut = OStringToOUString( OString( pConfigHome ),
785 RTL_TEXTENCODING_UTF8 );
786 else
788 OUString aHomeURL;
789 osl::Security().getHomeDir( aHomeURL );
790 ::osl::File::getSystemPathFromFileURL( aHomeURL, aShortcut );
791 aShortcut += "/.config";
793 aShortcut += "/autostart";
794 if (bCreate)
796 OUString aShortcutUrl;
797 osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
798 osl::Directory::createPath( aShortcutUrl );
800 return aShortcut;
802 #endif
804 OUString ShutdownIcon::getShortcutName()
806 #ifndef ENABLE_QUICKSTART_APPLET
807 return OUString();
808 #else
810 OUString aShortcutName( "StarOffice 6.0" );
811 ResMgr* pMgr = SfxResId::GetResMgr();
812 if( pMgr )
814 ::SolarMutexGuard aGuard;
815 aShortcutName = SFX2_RESSTR(STR_QUICKSTART_LNKNAME);
817 #ifdef WNT
818 aShortcutName += ".lnk";
820 OUString aShortcut(GetAutostartFolderNameW32());
821 aShortcut += "\\";
822 aShortcut += aShortcutName;
823 #else // UNX
824 OUString aShortcut = getAutostartDir();
825 aShortcut += "/qstart.desktop";
826 #endif // UNX
827 return aShortcut;
828 #endif // ENABLE_QUICKSTART_APPLET
831 bool ShutdownIcon::GetAutostart( )
833 #if defined MACOSX
834 return true;
835 #else
836 bool bRet = false;
837 #ifdef ENABLE_QUICKSTART_APPLET
838 OUString aShortcut( getShortcutName() );
839 OUString aShortcutUrl;
840 osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
841 osl::File f( aShortcutUrl );
842 osl::File::RC error = f.open( osl_File_OpenFlag_Read );
843 if( error == osl::File::E_None )
845 f.close();
846 bRet = true;
848 #endif // ENABLE_QUICKSTART_APPLET
849 return bRet;
850 #endif
853 void ShutdownIcon::SetAutostart( bool bActivate )
855 #ifdef ENABLE_QUICKSTART_APPLET
856 OUString aShortcut( getShortcutName() );
858 if( bActivate && IsQuickstarterInstalled() )
860 #ifdef WNT
861 EnableAutostartW32( aShortcut );
862 #else // UNX
863 getAutostartDir( true );
865 OUString aPath( "${BRAND_BASE_DIR}/" LIBO_SHARE_FOLDER "/xdg/qstart.desktop" );
866 Bootstrap::expandMacros( aPath );
868 OUString aDesktopFile;
869 ::osl::File::getSystemPathFromFileURL( aPath, aDesktopFile );
871 OString aDesktopFileUnx = OUStringToOString( aDesktopFile,
872 osl_getThreadTextEncoding() );
873 OString aShortcutUnx = OUStringToOString( aShortcut,
874 osl_getThreadTextEncoding() );
875 if ((0 != symlink(aDesktopFileUnx.getStr(), aShortcutUnx.getStr())) && (errno == EEXIST))
877 unlink(aShortcutUnx.getStr());
878 int ret = symlink(aDesktopFileUnx.getStr(), aShortcutUnx.getStr());
879 (void)ret; //deliberately ignore return value, it's non-critical if it fails
882 ShutdownIcon *pIcon = ShutdownIcon::createInstance();
883 if( pIcon )
884 pIcon->initSystray();
885 #endif // UNX
887 else
889 OUString aShortcutUrl;
890 ::osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
891 ::osl::File::remove( aShortcutUrl );
892 #ifdef UNX
893 if (pShutdownIcon)
895 ShutdownIcon *pIcon = getInstance();
896 pIcon->deInitSystray();
898 #endif
900 #else
901 (void)bActivate; // unused variable
902 #endif // ENABLE_QUICKSTART_APPLET
905 static const ::sal_Int32 PROPHANDLE_TERMINATEVETOSTATE = 0;
907 // XFastPropertySet
908 void SAL_CALL ShutdownIcon::setFastPropertyValue( ::sal_Int32 nHandle,
909 const ::com::sun::star::uno::Any& aValue )
910 throw (::com::sun::star::beans::UnknownPropertyException,
911 ::com::sun::star::beans::PropertyVetoException,
912 ::com::sun::star::lang::IllegalArgumentException,
913 ::com::sun::star::lang::WrappedTargetException,
914 ::com::sun::star::uno::RuntimeException)
916 switch(nHandle)
918 case PROPHANDLE_TERMINATEVETOSTATE :
920 // use new value in case it's a valid information only
921 ::sal_Bool bState( sal_False );
922 if (! (aValue >>= bState))
923 return;
925 m_bVeto = bState;
926 if (m_bVeto && ! m_bListenForTermination)
927 addTerminateListener();
929 break;
931 default :
932 throw ::com::sun::star::beans::UnknownPropertyException();
936 // XFastPropertySet
937 ::com::sun::star::uno::Any SAL_CALL ShutdownIcon::getFastPropertyValue( ::sal_Int32 nHandle )
938 throw (::com::sun::star::beans::UnknownPropertyException,
939 ::com::sun::star::lang::WrappedTargetException,
940 ::com::sun::star::uno::RuntimeException)
942 ::com::sun::star::uno::Any aValue;
943 switch(nHandle)
945 case PROPHANDLE_TERMINATEVETOSTATE :
947 bool bState = (m_bListenForTermination && m_bVeto);
948 aValue <<= bState;
950 break;
952 default :
953 throw ::com::sun::star::beans::UnknownPropertyException();
956 return aValue;
959 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */