1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 #include <jobs/helponstartup.hxx>
25 #include <officecfg/Office/Common.hxx>
26 #include <officecfg/Setup.hxx>
29 #include <comphelper/sequenceashashmap.hxx>
30 #include <vcl/svapp.hxx>
31 #include <vcl/help.hxx>
34 #include <com/sun/star/frame/FrameSearchFlag.hpp>
35 #include <com/sun/star/frame/ModuleManager.hpp>
36 #include <com/sun/star/frame/XFramesSupplier.hpp>
37 #include <com/sun/star/frame/Desktop.hpp>
38 #include <cppuhelper/supportsservice.hxx>
42 // XInterface, XTypeProvider, XServiceInfo
44 OUString SAL_CALL
HelpOnStartup::getImplementationName()
46 return "com.sun.star.comp.framework.HelpOnStartup";
49 sal_Bool SAL_CALL
HelpOnStartup::supportsService( const OUString
& sServiceName
)
51 return cppu::supportsService(this, sServiceName
);
54 css::uno::Sequence
< OUString
> SAL_CALL
HelpOnStartup::getSupportedServiceNames()
56 return { SERVICENAME_JOB
};
59 HelpOnStartup::HelpOnStartup(const css::uno::Reference
< css::uno::XComponentContext
>& xContext
)
60 : m_xContext (xContext
)
62 // create some needed uno services and cache it
63 m_xModuleManager
= css::frame::ModuleManager::create( m_xContext
);
65 m_xDesktop
= css::frame::Desktop::create(m_xContext
);
67 // ask for office locale
68 m_sLocale
= officecfg::Setup::L10N::ooLocale::get(m_xContext
);
71 m_sSystem
= officecfg::Office::Common::Help::System::get(m_xContext
);
73 // Start listening for disposing events of these services,
74 // so we can react e.g. for an office shutdown
75 css::uno::Reference
< css::lang::XComponent
> xComponent
;
76 xComponent
.set(m_xModuleManager
, css::uno::UNO_QUERY
);
78 xComponent
->addEventListener(static_cast< css::lang::XEventListener
* >(this));
80 m_xDesktop
->addEventListener(static_cast< css::lang::XEventListener
* >(this));
81 xComponent
.set(m_xConfig
, css::uno::UNO_QUERY
);
83 xComponent
->addEventListener(static_cast< css::lang::XEventListener
* >(this));
86 HelpOnStartup::~HelpOnStartup()
91 css::uno::Any SAL_CALL
HelpOnStartup::execute(const css::uno::Sequence
< css::beans::NamedValue
>& lArguments
)
93 // Analyze the given arguments; try to locate a model there and
94 // classify it's used application module.
95 OUString sModule
= its_getModuleIdFromEnv(lArguments
);
97 // Attention: we are bound to events for opening any document inside the office.
98 // That includes e.g. the help module itself. But we have to do nothing then!
99 if (sModule
.isEmpty())
100 return css::uno::Any();
102 // check current state of the help module
103 // a) help isn't open => show default page for the detected module
104 // b) help shows any other default page(!) => show default page for the detected module
105 // c) help shows any other content => do nothing (user travelled to any other content and leaved the set of default pages)
106 OUString sCurrentHelpURL
= its_getCurrentHelpURL();
107 bool bCurrentHelpURLIsAnyDefaultURL
= its_isHelpUrlADefaultOne(sCurrentHelpURL
);
108 bool bShowIt
= false;
111 if (sCurrentHelpURL
.isEmpty())
114 else if (bCurrentHelpURLIsAnyDefaultURL
)
119 // retrieve the help URL for the detected application module
120 OUString sModuleDependentHelpURL
= its_checkIfHelpEnabledAndGetURL(sModule
);
121 if (!sModuleDependentHelpURL
.isEmpty())
123 // Show this help page.
124 // Note: The help window brings itself to front ...
125 Help
* pHelp
= Application::GetHelp();
127 pHelp
->Start(sModuleDependentHelpURL
, static_cast<vcl::Window
*>(nullptr));
131 return css::uno::Any();
134 void SAL_CALL
HelpOnStartup::disposing(const css::lang::EventObject
& aEvent
)
136 osl::MutexGuard
g(m_mutex
);
137 if (aEvent
.Source
== m_xModuleManager
)
138 m_xModuleManager
.clear();
139 else if (aEvent
.Source
== m_xDesktop
)
141 else if (aEvent
.Source
== m_xConfig
)
145 OUString
HelpOnStartup::its_getModuleIdFromEnv(const css::uno::Sequence
< css::beans::NamedValue
>& lArguments
)
147 ::comphelper::SequenceAsHashMap
lArgs (lArguments
);
148 ::comphelper::SequenceAsHashMap lEnvironment
= lArgs
.getUnpackedValueOrDefault("Environment", css::uno::Sequence
< css::beans::NamedValue
>());
150 // check for right environment.
151 // If it's not a DocumentEvent, which triggered this job,
152 // we can't work correctly! => return immediately and do nothing
153 OUString sEnvType
= lEnvironment
.getUnpackedValueOrDefault("EnvType", OUString());
154 if (sEnvType
!= "DOCUMENTEVENT")
157 css::uno::Reference
< css::frame::XModel
> xDoc
= lEnvironment
.getUnpackedValueOrDefault("Model", css::uno::Reference
< css::frame::XModel
>());
161 // be sure that we work on top level documents only, which are registered
162 // on the desktop instance. Ignore e.g. life previews, which are top frames too ...
163 // but not registered at this global desktop instance.
164 css::uno::Reference
< css::frame::XDesktop
> xDesktopCheck
;
165 css::uno::Reference
< css::frame::XFrame
> xFrame
;
166 css::uno::Reference
< css::frame::XController
> xController
= xDoc
->getCurrentController();
167 if (xController
.is())
168 xFrame
= xController
->getFrame();
169 if (xFrame
.is() && xFrame
->isTop())
170 xDesktopCheck
.set(xFrame
->getCreator(), css::uno::UNO_QUERY
);
171 if (!xDesktopCheck
.is())
174 // OK - now we are sure this document is a top level document.
177 osl::ClearableMutexGuard
aLock(m_mutex
);
178 css::uno::Reference
< css::frame::XModuleManager2
> xModuleManager
= m_xModuleManager
;
185 sModuleId
= xModuleManager
->identify(xDoc
);
187 catch(const css::uno::RuntimeException
&)
189 catch(const css::uno::Exception
&)
190 { sModuleId
.clear(); }
195 OUString
HelpOnStartup::its_getCurrentHelpURL()
198 osl::ClearableMutexGuard
aLock(m_mutex
);
199 css::uno::Reference
< css::frame::XDesktop2
> xDesktop
= m_xDesktop
;
206 css::uno::Reference
< css::frame::XFrame
> xHelp
= xDesktop
->findFrame(SPECIALTARGET_HELPTASK
, css::frame::FrameSearchFlag::CHILDREN
);
210 OUString sCurrentHelpURL
;
213 css::uno::Reference
< css::frame::XFramesSupplier
> xHelpRoot (xHelp
, css::uno::UNO_QUERY_THROW
);
214 css::uno::Reference
< css::container::XIndexAccess
> xHelpChildren(xHelpRoot
->getFrames(), css::uno::UNO_QUERY_THROW
);
216 css::uno::Reference
< css::frame::XFrame
> xHelpChild
;
217 css::uno::Reference
< css::frame::XController
> xHelpView
;
218 css::uno::Reference
< css::frame::XModel
> xHelpContent
;
220 xHelpChildren
->getByIndex(0) >>= xHelpChild
;
222 xHelpView
= xHelpChild
->getController();
224 xHelpContent
= xHelpView
->getModel();
225 if (xHelpContent
.is())
226 sCurrentHelpURL
= xHelpContent
->getURL();
228 catch(const css::uno::RuntimeException
&)
230 catch(const css::uno::Exception
&)
231 { sCurrentHelpURL
.clear(); }
233 return sCurrentHelpURL
;
236 bool HelpOnStartup::its_isHelpUrlADefaultOne(const OUString
& sHelpURL
)
238 if (sHelpURL
.isEmpty())
242 osl::ClearableMutexGuard
aLock(m_mutex
);
243 css::uno::Reference
< css::container::XNameAccess
> xConfig
= m_xConfig
;
244 OUString sLocale
= m_sLocale
;
245 OUString sSystem
= m_sSystem
;
252 // check given help url against all default ones
253 const css::uno::Sequence
< OUString
> lModules
= xConfig
->getElementNames();
254 const OUString
* pModules
= lModules
.getConstArray();
255 ::sal_Int32 c
= lModules
.getLength();
262 css::uno::Reference
< css::container::XNameAccess
> xModuleConfig
;
263 xConfig
->getByName(pModules
[i
]) >>= xModuleConfig
;
264 if (!xModuleConfig
.is())
267 OUString sHelpBaseURL
;
268 xModuleConfig
->getByName("ooSetupFactoryHelpBaseURL") >>= sHelpBaseURL
;
269 OUString sHelpURLForModule
= HelpOnStartup::ist_createHelpURL(sHelpBaseURL
, sLocale
, sSystem
);
270 if (sHelpURL
== sHelpURLForModule
)
273 catch(const css::uno::RuntimeException
&)
275 catch(const css::uno::Exception
&)
282 OUString
HelpOnStartup::its_checkIfHelpEnabledAndGetURL(const OUString
& sModule
)
285 osl::ClearableMutexGuard
aLock(m_mutex
);
286 css::uno::Reference
< css::container::XNameAccess
> xConfig
= m_xConfig
;
287 OUString sLocale
= m_sLocale
;
288 OUString sSystem
= m_sSystem
;
296 css::uno::Reference
< css::container::XNameAccess
> xModuleConfig
;
298 xConfig
->getByName(sModule
) >>= xModuleConfig
;
300 bool bHelpEnabled
= false;
301 if (xModuleConfig
.is())
302 xModuleConfig
->getByName("ooSetupFactoryHelpOnOpen") >>= bHelpEnabled
;
306 OUString sHelpBaseURL
;
307 xModuleConfig
->getByName("ooSetupFactoryHelpBaseURL") >>= sHelpBaseURL
;
308 sHelpURL
= HelpOnStartup::ist_createHelpURL(sHelpBaseURL
, sLocale
, sSystem
);
311 catch(const css::uno::RuntimeException
&)
313 catch(const css::uno::Exception
&)
314 { sHelpURL
.clear(); }
319 OUString
HelpOnStartup::ist_createHelpURL(const OUString
& sBaseURL
,
320 const OUString
& sLocale
,
321 const OUString
& sSystem
)
323 return sBaseURL
+ "?Language=" + sLocale
+ "&System=" + sSystem
;
326 } // namespace framework
328 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
329 framework_HelpOnStartup_get_implementation(
330 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const& )
332 return cppu::acquire(new framework::HelpOnStartup(context
));
335 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */