Branch libreoffice-5-0-4
[LibreOffice.git] / sfx2 / source / appl / shutdownicon.cxx
bloba8b8a13606906f8ceee184ec41835367cb30a4ec
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 <sal/config.h>
22 #include <cassert>
24 #include <boost/logic/tribool.hpp>
25 #include <config_folders.h>
26 #include <shutdownicon.hxx>
27 #include <app.hrc>
28 #include <sfx2/app.hxx>
29 #include <osl/mutex.hxx>
30 #include <svtools/imagemgr.hxx>
31 #include <svtools/miscopt.hxx>
32 #include <com/sun/star/task/InteractionHandler.hpp>
33 #include <com/sun/star/frame/Desktop.hpp>
34 #include <com/sun/star/frame/XDispatchResultListener.hpp>
35 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
36 #include <com/sun/star/frame/XFramesSupplier.hpp>
37 #include <com/sun/star/frame/XComponentLoader.hpp>
38 #include <com/sun/star/frame/XFrame.hpp>
39 #include <com/sun/star/util/URLTransformer.hpp>
40 #include <com/sun/star/util/XURLTransformer.hpp>
41 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
42 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
43 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
44 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
45 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
46 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
47 #include <com/sun/star/document/MacroExecMode.hpp>
48 #include <com/sun/star/document/UpdateDocMode.hpp>
49 #include <sfx2/filedlghelper.hxx>
50 #include <sfx2/fcontnr.hxx>
51 #include <comphelper/processfactory.hxx>
52 #include <cppuhelper/compbase1.hxx>
53 #include <cppuhelper/supportsservice.hxx>
54 #include <sfx2/dispatch.hxx>
55 #include <comphelper/extract.hxx>
56 #include <tools/urlobj.hxx>
57 #include <osl/security.hxx>
58 #include <osl/file.hxx>
59 #include <rtl/bootstrap.hxx>
60 #include <rtl/ref.hxx>
61 #include <rtl/ustrbuf.hxx>
62 #ifdef UNX // need symlink
63 #include <unistd.h>
64 #include <errno.h>
65 #endif
67 #include <sfx2/sfxresid.hxx>
69 using namespace ::com::sun::star;
70 using namespace ::com::sun::star::uno;
71 using namespace ::com::sun::star::frame;
72 using namespace ::com::sun::star::container;
73 using namespace ::com::sun::star::io;
74 using namespace ::com::sun::star::lang;
75 using namespace ::com::sun::star::beans;
76 using namespace ::com::sun::star::util;
77 using namespace ::com::sun::star::ui::dialogs;
78 using namespace ::sfx2;
80 #ifdef ENABLE_QUICKSTART_APPLET
81 # if !defined(WIN32) && !defined(MACOSX)
82 extern "C" { static void SAL_CALL thisModule() {} }
83 # endif
84 #endif
86 class SfxNotificationListener_Impl : public cppu::WeakImplHelper1< XDispatchResultListener >
88 public:
89 virtual void SAL_CALL dispatchFinished( const DispatchResultEvent& aEvent ) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
90 virtual void SAL_CALL disposing( const EventObject& aEvent ) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
93 void SAL_CALL SfxNotificationListener_Impl::dispatchFinished( const DispatchResultEvent& ) throw( RuntimeException, std::exception )
95 ShutdownIcon::LeaveModalMode();
98 void SAL_CALL SfxNotificationListener_Impl::disposing( const EventObject& ) throw( RuntimeException, std::exception )
102 OUString SAL_CALL ShutdownIcon::getImplementationName()
103 throw (css::uno::RuntimeException, std::exception)
105 return OUString("com.sun.star.comp.desktop.QuickstartWrapper");
108 sal_Bool SAL_CALL ShutdownIcon::supportsService(OUString const & ServiceName)
109 throw (css::uno::RuntimeException, std::exception)
111 return cppu::supportsService(this, ServiceName);
114 css::uno::Sequence<OUString> SAL_CALL ShutdownIcon::getSupportedServiceNames()
115 throw (css::uno::RuntimeException, std::exception)
117 css::uno::Sequence< OUString > aSeq(1);
118 aSeq[0] = "com.sun.star.office.Quickstart";
119 return aSeq;
122 bool ShutdownIcon::bModalMode = false;
123 ShutdownIcon* ShutdownIcon::pShutdownIcon = NULL;
125 #if !defined( ENABLE_QUICKSTART_APPLET )
126 // To remove conditionals
127 extern "C" {
128 static void disabled_initSystray() { }
129 static void disabled_deInitSystray() { }
131 #endif
133 namespace {
135 boost::logic::tribool loaded(boost::logic::indeterminate);
136 oslGenericFunction pInitSystray(nullptr);
137 oslGenericFunction pDeInitSystray(nullptr);
139 bool LoadModule()
141 if (boost::logic::indeterminate(loaded))
143 #ifdef ENABLE_QUICKSTART_APPLET
144 # ifdef WIN32
145 pInitSystray = win32_init_sys_tray;
146 pDeInitSystray = win32_shutdown_sys_tray;
147 loaded = true;
148 # elif defined MACOSX
149 pInitSystray = aqua_init_systray;
150 pDeInitSystray = aqua_shutdown_systray;
151 loaded = true;
152 # else // UNX
153 osl::Module plugin;
154 oslGenericFunction pTmpInit = NULL;
155 oslGenericFunction pTmpDeInit = NULL;
156 if ( plugin.loadRelative( &thisModule, "libqstart_gtklo.so" ) )
158 pTmpInit = plugin.getFunctionSymbol( "plugin_init_sys_tray" );
159 pTmpDeInit = plugin.getFunctionSymbol( "plugin_shutdown_sys_tray" );
161 if ( !pTmpInit || !pTmpDeInit )
163 loaded = false;
165 else
167 plugin.release();
168 pInitSystray = pTmpInit;
169 pDeInitSystray = pTmpDeInit;
170 loaded = true;
172 # endif // UNX
173 #else
174 pInitSystray = disabled_initSystray;
175 pDeInitSystray = disabled_deInitSystray;
176 loaded = false;
177 #endif // ENABLE_QUICKSTART_APPLET
179 assert(!boost::logic::indeterminate(loaded));
180 return loaded;
185 void ShutdownIcon::initSystray()
187 if (m_bInitialized)
188 return;
189 m_bInitialized = true;
191 (void) LoadModule();
192 m_bVeto = true;
193 pInitSystray();
196 void ShutdownIcon::deInitSystray()
198 if (!m_bInitialized)
199 return;
201 if (pDeInitSystray)
202 pDeInitSystray();
204 m_bVeto = false;
205 pInitSystray = 0;
206 pDeInitSystray = 0;
208 delete m_pFileDlg;
209 m_pFileDlg = NULL;
210 m_bInitialized = false;
214 ShutdownIcon::ShutdownIcon( const ::com::sun::star::uno::Reference< XComponentContext > & rxContext ) :
215 ShutdownIconServiceBase( m_aMutex ),
216 m_bVeto ( false ),
217 m_bListenForTermination ( false ),
218 m_bSystemDialogs( false ),
219 m_pResMgr( NULL ),
220 m_pFileDlg( NULL ),
221 m_xContext( rxContext ),
222 m_bInitialized( false )
224 m_bSystemDialogs = SvtMiscOptions().UseSystemFileDialog();
227 ShutdownIcon::~ShutdownIcon()
229 deInitSystray();
234 void ShutdownIcon::OpenURL( const OUString& aURL, const OUString& rTarget, const Sequence< PropertyValue >& aArgs )
236 if ( getInstance() && getInstance()->m_xDesktop.is() )
238 ::com::sun::star::uno::Reference < XDispatchProvider > xDispatchProvider( getInstance()->m_xDesktop, UNO_QUERY );
239 if ( xDispatchProvider.is() )
241 com::sun::star::util::URL aDispatchURL;
242 aDispatchURL.Complete = aURL;
244 ::com::sun::star::uno::Reference< util::XURLTransformer > xURLTransformer( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
247 ::com::sun::star::uno::Reference< com::sun::star::frame::XDispatch > xDispatch;
249 xURLTransformer->parseStrict( aDispatchURL );
250 xDispatch = xDispatchProvider->queryDispatch( aDispatchURL, rTarget, 0 );
251 if ( xDispatch.is() )
252 xDispatch->dispatch( aDispatchURL, aArgs );
254 catch ( com::sun::star::uno::RuntimeException& )
256 throw;
258 catch ( com::sun::star::uno::Exception& )
267 void ShutdownIcon::FileOpen()
269 if ( getInstance() && getInstance()->m_xDesktop.is() )
271 ::SolarMutexGuard aGuard;
272 EnterModalMode();
273 getInstance()->StartFileDialog();
279 void ShutdownIcon::FromTemplate()
281 if ( getInstance() && getInstance()->m_xDesktop.is() )
283 ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFramesSupplier > xDesktop ( getInstance()->m_xDesktop, UNO_QUERY);
284 ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame( xDesktop->getActiveFrame() );
285 if ( !xFrame.is() )
286 xFrame = ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame >( xDesktop, UNO_QUERY );
288 URL aTargetURL;
289 aTargetURL.Complete = ".uno:NewDoc";
290 ::com::sun::star::uno::Reference< util::XURLTransformer > xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
291 xTrans->parseStrict( aTargetURL );
293 ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatchProvider > xProv( xFrame, UNO_QUERY );
294 ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatch > xDisp;
295 if ( xProv.is() )
297 xDisp = xProv->queryDispatch( aTargetURL, OUString("_self"), 0 );
299 if ( xDisp.is() )
301 Sequence<PropertyValue> aArgs(1);
302 PropertyValue* pArg = aArgs.getArray();
303 pArg[0].Name = "Referer";
304 pArg[0].Value <<= OUString("private:user");
305 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XNotifyingDispatch > xNotifyer( xDisp, UNO_QUERY );
306 if ( xNotifyer.is() )
308 EnterModalMode();
309 xNotifyer->dispatchWithNotification( aTargetURL, aArgs, new SfxNotificationListener_Impl() );
311 else
312 xDisp->dispatch( aTargetURL, aArgs );
318 #include <tools/rcid.h>
319 OUString ShutdownIcon::GetResString( int id )
321 ::SolarMutexGuard aGuard;
323 if( ! m_pResMgr )
324 m_pResMgr = SfxResId::GetResMgr();
325 ResId aResId( id, *m_pResMgr );
326 aResId.SetRT( RSC_STRING );
327 if (!m_pResMgr->IsAvailable(aResId))
328 return OUString();
330 return ResId(id, *m_pResMgr).toString();
335 OUString ShutdownIcon::GetUrlDescription( const OUString& aUrl )
337 ::SolarMutexGuard aGuard;
339 return OUString( SvFileInformationManager::GetDescription( INetURLObject( aUrl ) ) );
344 void ShutdownIcon::StartFileDialog()
346 ::SolarMutexGuard aGuard;
348 bool bDirty = ( m_bSystemDialogs != static_cast<bool>(SvtMiscOptions().UseSystemFileDialog()) );
350 if ( m_pFileDlg && bDirty )
352 // Destroy instance as changing the system file dialog setting
353 // forces us to create a new FileDialogHelper instance!
354 delete m_pFileDlg;
355 m_pFileDlg = NULL;
358 if ( !m_pFileDlg )
359 m_pFileDlg = new FileDialogHelper(
360 ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION,
361 SFXWB_MULTISELECTION, OUString() );
362 m_pFileDlg->StartExecuteModal( LINK( this, ShutdownIcon, DialogClosedHdl_Impl ) );
367 IMPL_LINK( ShutdownIcon, DialogClosedHdl_Impl, FileDialogHelper*, )
369 DBG_ASSERT( m_pFileDlg, "ShutdownIcon, DialogClosedHdl_Impl(): no file dialog" );
371 // use constructor for filling up filters automatically!
372 if ( ERRCODE_NONE == m_pFileDlg->GetError() )
374 ::com::sun::star::uno::Reference< XFilePicker > xPicker = m_pFileDlg->GetFilePicker();
379 if ( xPicker.is() )
382 ::com::sun::star::uno::Reference < XFilePickerControlAccess > xPickerControls ( xPicker, UNO_QUERY );
383 ::com::sun::star::uno::Reference < XFilterManager > xFilterManager ( xPicker, UNO_QUERY );
385 Sequence< OUString > sFiles = xPicker->getFiles();
386 int nFiles = sFiles.getLength();
388 int nArgs=3;
389 Sequence< PropertyValue > aArgs(3);
391 ::com::sun::star::uno::Reference < com::sun::star::task::XInteractionHandler2 > xInteraction(
392 task::InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(), 0) );
394 aArgs[0].Name = "InteractionHandler";
395 aArgs[0].Value <<= xInteraction;
397 sal_Int16 nMacroExecMode = ::com::sun::star::document::MacroExecMode::USE_CONFIG;
398 aArgs[1].Name = "MacroExecutionMode";
399 aArgs[1].Value <<= nMacroExecMode;
401 sal_Int16 nUpdateDoc = ::com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG;
402 aArgs[2].Name = "UpdateDocMode";
403 aArgs[2].Value <<= nUpdateDoc;
405 // use the filedlghelper to get the current filter name,
406 // because it removes the extensions before you get the filter name.
407 OUString aFilterName( m_pFileDlg->GetCurrentFilter() );
409 if ( xPickerControls.is() )
412 // Set readonly flag
414 bool bReadOnly = false;
417 xPickerControls->getValue( ExtendedFilePickerElementIds::CHECKBOX_READONLY, 0 ) >>= bReadOnly;
419 // Only set porperty if readonly is set to TRUE
421 if ( bReadOnly )
423 aArgs.realloc( ++nArgs );
424 aArgs[nArgs-1].Name = "ReadOnly";
425 aArgs[nArgs-1].Value <<= bReadOnly;
428 // Get version string
430 sal_Int32 iVersion = -1;
432 xPickerControls->getValue( ExtendedFilePickerElementIds::LISTBOX_VERSION, ControlActions::GET_SELECTED_ITEM_INDEX ) >>= iVersion;
434 if ( iVersion >= 0 )
436 sal_Int16 uVersion = (sal_Int16)iVersion;
438 aArgs.realloc( ++nArgs );
439 aArgs[nArgs-1].Name = "Version";
440 aArgs[nArgs-1].Value <<= uVersion;
443 // Retrieve the current filter
445 if ( aFilterName.isEmpty() )
446 xPickerControls->getValue( CommonFilePickerElementIds::LISTBOX_FILTER, ControlActions::GET_SELECTED_ITEM ) >>= aFilterName;
451 // Convert UI filter name to internal filter name
453 if ( !aFilterName.isEmpty() )
455 const SfxFilter* pFilter = SfxGetpApp()->GetFilterMatcher().GetFilter4UIName( aFilterName, SfxFilterFlags::NONE, SfxFilterFlags::NOTINFILEDLG );
457 if ( pFilter )
459 aFilterName = pFilter->GetFilterName();
461 if ( !aFilterName.isEmpty() )
463 aArgs.realloc( ++nArgs );
464 aArgs[nArgs-1].Name = "FilterName";
465 aArgs[nArgs-1].Value <<= aFilterName;
470 if ( 1 == nFiles )
471 OpenURL( sFiles[0], OUString( "_default" ), aArgs );
472 else
474 OUString aBaseDirURL = sFiles[0];
475 if ( !aBaseDirURL.isEmpty() && !aBaseDirURL.endsWith("/") )
476 aBaseDirURL += "/";
478 int iFiles;
479 for ( iFiles = 1; iFiles < nFiles; iFiles++ )
481 OUString aURL = aBaseDirURL;
482 aURL += sFiles[iFiles];
483 OpenURL( aURL, OUString( "_default" ), aArgs );
488 catch ( ... )
493 #ifdef WNT
494 // Destroy dialog to prevent problems with custom controls
495 // This fix is dependent on the dialog settings. Destroying the dialog here will
496 // crash the non-native dialog implementation! Therefore make this dependent on
497 // the settings.
498 if ( SvtMiscOptions().UseSystemFileDialog() )
500 delete m_pFileDlg;
501 m_pFileDlg = NULL;
503 #endif
505 LeaveModalMode();
506 return 0;
511 void ShutdownIcon::addTerminateListener()
513 ShutdownIcon* pInst = getInstance();
514 if ( ! pInst)
515 return;
517 if (pInst->m_bListenForTermination)
518 return;
520 ::com::sun::star::uno::Reference< XDesktop2 > xDesktop = pInst->m_xDesktop;
521 if ( ! xDesktop.is())
522 return;
524 xDesktop->addTerminateListener( pInst );
525 pInst->m_bListenForTermination = true;
530 void ShutdownIcon::terminateDesktop()
532 ShutdownIcon* pInst = getInstance();
533 if ( ! pInst)
534 return;
536 ::com::sun::star::uno::Reference< XDesktop2 > xDesktop = pInst->m_xDesktop;
537 if ( ! xDesktop.is())
538 return;
540 // always remove ourselves as listener
541 pInst->m_bListenForTermination = true;
542 xDesktop->removeTerminateListener( pInst );
544 // terminate desktop only if no tasks exist
545 ::com::sun::star::uno::Reference< XIndexAccess > xTasks ( xDesktop->getFrames(), UNO_QUERY );
546 if( xTasks.is() && xTasks->getCount() < 1 )
547 Application::Quit();
549 // remove the instance pointer
550 ShutdownIcon::pShutdownIcon = 0;
555 ShutdownIcon* ShutdownIcon::getInstance()
557 OSL_ASSERT( pShutdownIcon );
558 return pShutdownIcon;
563 ShutdownIcon* ShutdownIcon::createInstance()
565 if (pShutdownIcon)
566 return pShutdownIcon;
568 ShutdownIcon *pIcon = NULL;
569 try {
570 pIcon = new ShutdownIcon( comphelper::getProcessComponentContext() );
571 pIcon->init ();
572 pShutdownIcon = pIcon;
573 } catch (...) {
574 delete pIcon;
577 return pShutdownIcon;
580 void ShutdownIcon::init() throw( ::com::sun::star::uno::Exception )
582 // access resource system and sfx only protected by solarmutex
583 ::SolarMutexGuard aSolarGuard;
584 ResMgr *pResMgr = SfxResId::GetResMgr();
586 ::osl::ResettableMutexGuard aGuard( m_aMutex );
587 m_pResMgr = pResMgr;
588 aGuard.clear();
589 ::com::sun::star::uno::Reference < XDesktop2 > xDesktop = Desktop::create( m_xContext );
590 aGuard.reset();
591 m_xDesktop = xDesktop;
596 void SAL_CALL ShutdownIcon::disposing()
598 m_xContext.clear();
599 m_xDesktop.clear();
601 deInitSystray();
606 // XEventListener
607 void SAL_CALL ShutdownIcon::disposing( const ::com::sun::star::lang::EventObject& )
608 throw(::com::sun::star::uno::RuntimeException, std::exception)
614 // XTerminateListener
615 void SAL_CALL ShutdownIcon::queryTermination( const ::com::sun::star::lang::EventObject& )
616 throw(::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException, std::exception)
618 SAL_INFO("sfx.appl", "ShutdownIcon::queryTermination: veto is " << m_bVeto);
619 ::osl::ClearableMutexGuard aGuard( m_aMutex );
621 if ( m_bVeto )
622 throw ::com::sun::star::frame::TerminationVetoException();
628 void SAL_CALL ShutdownIcon::notifyTermination( const ::com::sun::star::lang::EventObject& )
629 throw(::com::sun::star::uno::RuntimeException, std::exception)
636 void SAL_CALL ShutdownIcon::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments )
637 throw( ::com::sun::star::uno::Exception, std::exception )
639 ::osl::ResettableMutexGuard aGuard( m_aMutex );
641 // third argument only sets veto, everything else will be ignored!
642 if (aArguments.getLength() > 2)
644 bool bVeto = ::cppu::any2bool(aArguments[2]);
645 m_bVeto = bVeto;
646 return;
649 if ( aArguments.getLength() > 0 )
651 if ( !ShutdownIcon::pShutdownIcon )
655 bool bQuickstart = ::cppu::any2bool( aArguments[0] );
656 if( !bQuickstart && !GetAutostart() )
657 return;
658 aGuard.clear();
659 init ();
660 aGuard.reset();
661 if ( !m_xDesktop.is() )
662 return;
664 /* Create a sub-classed instance - foo */
665 ShutdownIcon::pShutdownIcon = this;
666 initSystray();
668 catch(const ::com::sun::star::lang::IllegalArgumentException&)
673 if ( aArguments.getLength() > 1 )
675 bool bAutostart = ::cppu::any2bool( aArguments[1] );
676 if (bAutostart && !GetAutostart())
677 SetAutostart( true );
678 if (!bAutostart && GetAutostart())
679 SetAutostart( false );
686 void ShutdownIcon::EnterModalMode()
688 bModalMode = true;
693 void ShutdownIcon::LeaveModalMode()
695 bModalMode = false;
698 #ifdef WNT
699 // defined in shutdowniconw32.cxx
700 #elif defined MACOSX
701 // defined in shutdowniconaqua.cxx
702 #else
703 bool ShutdownIcon::IsQuickstarterInstalled()
705 #ifndef ENABLE_QUICKSTART_APPLET
706 return false;
707 #else // !ENABLE_QUICKSTART_APPLET
708 #ifdef UNX
709 return LoadModule();
710 #endif // UNX
711 #endif // !ENABLE_QUICKSTART_APPLET
713 #endif // !WNT
717 #if defined (ENABLE_QUICKSTART_APPLET) && defined (UNX)
719 * Return the XDG autostart directory.
720 * http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
721 * Available in Unix and with Quickstart enabled.
722 * @param bCreate Create the directory if it does not exist yet.
723 * @return OUString containing the autostart directory path.
725 static OUString getAutostartDir( bool bCreate = false )
727 OUString aShortcut;
728 const char *pConfigHome;
729 if( (pConfigHome = getenv("XDG_CONFIG_HOME") ) )
730 aShortcut = OStringToOUString( OString( pConfigHome ),
731 RTL_TEXTENCODING_UTF8 );
732 else
734 OUString aHomeURL;
735 osl::Security().getHomeDir( aHomeURL );
736 ::osl::File::getSystemPathFromFileURL( aHomeURL, aShortcut );
737 aShortcut += "/.config";
739 aShortcut += "/autostart";
740 if (bCreate)
742 OUString aShortcutUrl;
743 osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
744 osl::Directory::createPath( aShortcutUrl );
746 return aShortcut;
748 #endif
750 OUString ShutdownIcon::getShortcutName()
752 #ifndef ENABLE_QUICKSTART_APPLET
753 return OUString();
754 #else
756 OUString aShortcutName( "StarOffice 6.0" );
757 ResMgr* pMgr = SfxResId::GetResMgr();
758 if( pMgr )
760 ::SolarMutexGuard aGuard;
761 aShortcutName = SFX2_RESSTR(STR_QUICKSTART_LNKNAME);
763 #ifdef WNT
764 aShortcutName += ".lnk";
766 OUString aShortcut(GetAutostartFolderNameW32());
767 aShortcut += "\\";
768 aShortcut += aShortcutName;
769 #else // UNX
770 OUString aShortcut = getAutostartDir();
771 aShortcut += "/qstart.desktop";
772 #endif // UNX
773 return aShortcut;
774 #endif // ENABLE_QUICKSTART_APPLET
777 bool ShutdownIcon::GetAutostart( )
779 #if defined MACOSX
780 return true;
781 #else
782 bool bRet = false;
783 #ifdef ENABLE_QUICKSTART_APPLET
784 OUString aShortcut( getShortcutName() );
785 OUString aShortcutUrl;
786 osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
787 osl::File f( aShortcutUrl );
788 osl::File::RC error = f.open( osl_File_OpenFlag_Read );
789 if( error == osl::File::E_None )
791 f.close();
792 bRet = true;
794 #endif // ENABLE_QUICKSTART_APPLET
795 return bRet;
796 #endif
799 void ShutdownIcon::SetAutostart( bool bActivate )
801 #ifdef ENABLE_QUICKSTART_APPLET
802 OUString aShortcut( getShortcutName() );
804 if( bActivate && IsQuickstarterInstalled() )
806 #ifdef WNT
807 EnableAutostartW32( aShortcut );
808 #else // UNX
809 getAutostartDir( true );
811 OUString aPath( "${BRAND_BASE_DIR}/" LIBO_SHARE_FOLDER "/xdg/qstart.desktop" );
812 rtl::Bootstrap::expandMacros( aPath );
814 OUString aDesktopFile;
815 ::osl::File::getSystemPathFromFileURL( aPath, aDesktopFile );
817 OString aDesktopFileUnx = OUStringToOString( aDesktopFile,
818 osl_getThreadTextEncoding() );
819 OString aShortcutUnx = OUStringToOString( aShortcut,
820 osl_getThreadTextEncoding() );
821 if ((0 != symlink(aDesktopFileUnx.getStr(), aShortcutUnx.getStr())) && (errno == EEXIST))
823 unlink(aShortcutUnx.getStr());
824 int ret = symlink(aDesktopFileUnx.getStr(), aShortcutUnx.getStr());
825 (void)ret; //deliberately ignore return value, it's non-critical if it fails
828 ShutdownIcon *pIcon = ShutdownIcon::createInstance();
829 if( pIcon )
830 pIcon->initSystray();
831 #endif // UNX
833 else
835 OUString aShortcutUrl;
836 ::osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
837 ::osl::File::remove( aShortcutUrl );
838 #ifdef UNX
839 if (pShutdownIcon)
841 ShutdownIcon *pIcon = getInstance();
842 pIcon->deInitSystray();
844 #endif
846 #else
847 (void)bActivate; // unused variable
848 #endif // ENABLE_QUICKSTART_APPLET
851 static const ::sal_Int32 PROPHANDLE_TERMINATEVETOSTATE = 0;
853 // XFastPropertySet
854 void SAL_CALL ShutdownIcon::setFastPropertyValue( ::sal_Int32 nHandle,
855 const ::com::sun::star::uno::Any& aValue )
856 throw (::com::sun::star::beans::UnknownPropertyException,
857 ::com::sun::star::beans::PropertyVetoException,
858 ::com::sun::star::lang::IllegalArgumentException,
859 ::com::sun::star::lang::WrappedTargetException,
860 ::com::sun::star::uno::RuntimeException, std::exception)
862 switch(nHandle)
864 case PROPHANDLE_TERMINATEVETOSTATE :
866 // use new value in case it's a valid information only
867 bool bState( false );
868 if (! (aValue >>= bState))
869 return;
871 m_bVeto = bState;
872 if (m_bVeto && ! m_bListenForTermination)
873 addTerminateListener();
875 break;
877 default :
878 throw ::com::sun::star::beans::UnknownPropertyException();
882 // XFastPropertySet
883 ::com::sun::star::uno::Any SAL_CALL ShutdownIcon::getFastPropertyValue( ::sal_Int32 nHandle )
884 throw (::com::sun::star::beans::UnknownPropertyException,
885 ::com::sun::star::lang::WrappedTargetException,
886 ::com::sun::star::uno::RuntimeException, std::exception)
888 ::com::sun::star::uno::Any aValue;
889 switch(nHandle)
891 case PROPHANDLE_TERMINATEVETOSTATE :
893 bool bState = (m_bListenForTermination && m_bVeto);
894 aValue <<= bState;
896 break;
898 default :
899 throw ::com::sun::star::beans::UnknownPropertyException();
902 return aValue;
905 namespace {
907 struct Instance {
908 explicit Instance(
909 css::uno::Reference<css::uno::XComponentContext> const & context):
910 instance(static_cast<cppu::OWeakObject *>(new ShutdownIcon(context)))
913 rtl::Reference<css::uno::XInterface> instance;
916 struct Singleton:
917 public rtl::StaticWithArg<
918 Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton>
923 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
924 com_sun_star_comp_desktop_QuickstartWrapper_get_implementation(
925 css::uno::XComponentContext *context,
926 css::uno::Sequence<css::uno::Any> const &)
928 return cppu::acquire(static_cast<cppu::OWeakObject *>(
929 Singleton::get(context).instance.get()));
932 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */