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 //_______________________________________________
23 #include <jobs/helponstartup.hxx>
24 #include <threadhelp/resetableguard.hxx>
25 #include <loadenv/targethelper.hxx>
28 //_______________________________________________
30 #include <comphelper/configurationhelper.hxx>
31 #include <comphelper/sequenceashashmap.hxx>
32 #include <unotools/configmgr.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vcl/help.hxx>
35 #include <rtl/ustrbuf.hxx>
37 //_______________________________________________
39 #include <com/sun/star/frame/FrameSearchFlag.hpp>
40 #include <com/sun/star/frame/ModuleManager.hpp>
41 #include <com/sun/star/frame/XFramesSupplier.hpp>
42 #include <com/sun/star/frame/Desktop.hpp>
48 // path to module config
49 static OUString
CFG_PACKAGE_MODULES ("/org.openoffice.Setup/Office/Factories");
50 static OUString
CFG_PACKAGE_SETUP ("/org.openoffice.Setup");
51 static OUString
CFG_PACKAGE_COMMON ("/org.openoffice.Office.Common");
52 static OUString
CFG_PATH_L10N ("L10N");
53 static OUString
CFG_PATH_HELP ("Help");
54 static OUString
CFG_KEY_LOCALE ("ooLocale");
55 static OUString
CFG_KEY_HELPSYSTEM ("System");
57 // props of job environment
58 static OUString
PROP_ENVIRONMENT ("Environment");
59 static OUString
PROP_JOBCONFIG ("JobConfig");
60 static OUString
PROP_ENVTYPE ("EnvType");
61 static OUString
PROP_MODEL ("Model");
63 // props of module config
64 static OUString
PROP_HELP_BASEURL ("ooSetupFactoryHelpBaseURL");
65 static OUString
PROP_AUTOMATIC_HELP ("ooSetupFactoryHelpOnOpen");
67 // special value of job environment
68 static OUString
ENVTYPE_DOCUMENTEVENT ("DOCUMENTEVENT");
70 //-----------------------------------------------
72 DEFINE_XSERVICEINFO_MULTISERVICE_2(HelpOnStartup
,
75 IMPLEMENTATIONNAME_HELPONSTARTUP
)
77 DEFINE_INIT_SERVICE(HelpOnStartup
,
80 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
81 to create a new instance of this class by our own supported service factory.
82 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further information!
84 // create some needed uno services and cache it
85 m_xModuleManager
= css::frame::ModuleManager::create( m_xContext
);
87 m_xDesktop
= css::frame::Desktop::create(m_xContext
);
89 m_xConfig
= css::uno::Reference
< css::container::XNameAccess
>(
90 ::comphelper::ConfigurationHelper::openConfig(
93 ::comphelper::ConfigurationHelper::E_READONLY
),
94 css::uno::UNO_QUERY_THROW
);
96 // ask for office locale
97 ::comphelper::ConfigurationHelper::readDirectKey(
102 ::comphelper::ConfigurationHelper::E_READONLY
) >>= m_sLocale
;
105 ::comphelper::ConfigurationHelper::readDirectKey(
110 ::comphelper::ConfigurationHelper::E_READONLY
) >>= m_sSystem
;
112 // Start listening for disposing events of these services,
113 // so we can react e.g. for an office shutdown
114 css::uno::Reference
< css::lang::XComponent
> xComponent
;
115 xComponent
= css::uno::Reference
< css::lang::XComponent
>(m_xModuleManager
, css::uno::UNO_QUERY
);
117 xComponent
->addEventListener(static_cast< css::lang::XEventListener
* >(this));
118 xComponent
= css::uno::Reference
< css::lang::XComponent
>(m_xDesktop
, css::uno::UNO_QUERY
);
120 xComponent
->addEventListener(static_cast< css::lang::XEventListener
* >(this));
121 xComponent
= css::uno::Reference
< css::lang::XComponent
>(m_xConfig
, css::uno::UNO_QUERY
);
123 xComponent
->addEventListener(static_cast< css::lang::XEventListener
* >(this));
127 //-----------------------------------------------
128 HelpOnStartup::HelpOnStartup(const css::uno::Reference
< css::uno::XComponentContext
>& xContext
)
130 , m_xContext (xContext
)
134 //-----------------------------------------------
135 HelpOnStartup::~HelpOnStartup()
139 //-----------------------------------------------
141 css::uno::Any SAL_CALL
HelpOnStartup::execute(const css::uno::Sequence
< css::beans::NamedValue
>& lArguments
)
142 throw(css::lang::IllegalArgumentException
,
143 css::uno::Exception
,
144 css::uno::RuntimeException
)
146 // Analyze the given arguments; try to locate a model there and
147 // classify it's used application module.
148 OUString sModule
= its_getModuleIdFromEnv(lArguments
);
150 // Attention: We are bound to events for openeing any document inside the office.
151 // That includes e.g. the help module itself. But we have to do nothing then!
152 if (sModule
.isEmpty())
153 return css::uno::Any();
155 // check current state of the help module
156 // a) help isnt open => show default page for the detected module
157 // b) help shows any other default page(!) => show default page for the detected module
158 // c) help shows any other content => do nothing (user travelled to any other content and leaved the set of default pages)
159 OUString sCurrentHelpURL
= its_getCurrentHelpURL();
160 sal_Bool bCurrentHelpURLIsAnyDefaultURL
= its_isHelpUrlADefaultOne(sCurrentHelpURL
);
161 sal_Bool bShowIt
= sal_False
;
164 if (sCurrentHelpURL
.isEmpty())
167 else if (bCurrentHelpURLIsAnyDefaultURL
)
172 // retrieve the help URL for the detected application module
173 OUString sModuleDependendHelpURL
= its_checkIfHelpEnabledAndGetURL(sModule
);
174 if (!sModuleDependendHelpURL
.isEmpty())
176 // Show this help page.
177 // Note: The help window brings itself to front ...
178 Help
* pHelp
= Application::GetHelp();
180 pHelp
->Start(sModuleDependendHelpURL
, 0);
184 return css::uno::Any();
187 //-----------------------------------------------
188 void SAL_CALL
HelpOnStartup::disposing(const css::lang::EventObject
& aEvent
)
189 throw(css::uno::RuntimeException
)
192 ResetableGuard
aLock(m_aLock
);
194 if (aEvent
.Source
== m_xModuleManager
)
195 m_xModuleManager
.clear();
196 else if (aEvent
.Source
== m_xDesktop
)
198 else if (aEvent
.Source
== m_xConfig
)
205 //-----------------------------------------------
206 OUString
HelpOnStartup::its_getModuleIdFromEnv(const css::uno::Sequence
< css::beans::NamedValue
>& lArguments
)
208 ::comphelper::SequenceAsHashMap
lArgs (lArguments
);
209 ::comphelper::SequenceAsHashMap lEnvironment
= lArgs
.getUnpackedValueOrDefault(PROP_ENVIRONMENT
, css::uno::Sequence
< css::beans::NamedValue
>());
210 ::comphelper::SequenceAsHashMap lJobConfig
= lArgs
.getUnpackedValueOrDefault(PROP_JOBCONFIG
, css::uno::Sequence
< css::beans::NamedValue
>());
212 // check for right environment.
213 // If its not a DocumentEvent, which triggered this job,
214 // we cant work correctly! => return immediately and do nothing
215 OUString sEnvType
= lEnvironment
.getUnpackedValueOrDefault(PROP_ENVTYPE
, OUString());
216 if (!sEnvType
.equals(ENVTYPE_DOCUMENTEVENT
))
219 css::uno::Reference
< css::frame::XModel
> xDoc
= lEnvironment
.getUnpackedValueOrDefault(PROP_MODEL
, css::uno::Reference
< css::frame::XModel
>());
223 // be sure that we work on top level documents only, which are registered
224 // on the desktop instance. Ignore e.g. life previews, which are top frames too ...
225 // but not registered at this global desktop instance.
226 css::uno::Reference
< css::frame::XDesktop
> xDesktopCheck
;
227 css::uno::Reference
< css::frame::XFrame
> xFrame
;
228 css::uno::Reference
< css::frame::XController
> xController
= xDoc
->getCurrentController();
229 if (xController
.is())
230 xFrame
= xController
->getFrame();
231 if (xFrame
.is() && xFrame
->isTop())
232 xDesktopCheck
= css::uno::Reference
< css::frame::XDesktop
>(xFrame
->getCreator(), css::uno::UNO_QUERY
);
233 if (!xDesktopCheck
.is())
236 // OK - now we are sure this document is a top level document.
239 ResetableGuard
aLock(m_aLock
);
240 css::uno::Reference
< css::frame::XModuleManager2
> xModuleManager
= m_xModuleManager
;
247 sModuleId
= xModuleManager
->identify(xDoc
);
249 catch(const css::uno::RuntimeException
&)
251 catch(const css::uno::Exception
&)
252 { sModuleId
= OUString(); }
257 //-----------------------------------------------
258 OUString
HelpOnStartup::its_getCurrentHelpURL()
261 ResetableGuard
aLock(m_aLock
);
262 css::uno::Reference
< css::frame::XDesktop2
> xDesktop
= m_xDesktop
;
269 css::uno::Reference
< css::frame::XFrame
> xHelp
= xDesktop
->findFrame(SPECIALTARGET_HELPTASK
, css::frame::FrameSearchFlag::CHILDREN
);
273 OUString sCurrentHelpURL
;
276 css::uno::Reference
< css::frame::XFramesSupplier
> xHelpRoot (xHelp
, css::uno::UNO_QUERY_THROW
);
277 css::uno::Reference
< css::container::XIndexAccess
> xHelpChildren(xHelpRoot
->getFrames(), css::uno::UNO_QUERY_THROW
);
279 css::uno::Reference
< css::frame::XFrame
> xHelpChild
;
280 css::uno::Reference
< css::frame::XController
> xHelpView
;
281 css::uno::Reference
< css::frame::XModel
> xHelpContent
;
283 xHelpChildren
->getByIndex(0) >>= xHelpChild
;
285 xHelpView
= xHelpChild
->getController();
287 xHelpContent
= xHelpView
->getModel();
288 if (xHelpContent
.is())
289 sCurrentHelpURL
= xHelpContent
->getURL();
291 catch(const css::uno::RuntimeException
&)
293 catch(const css::uno::Exception
&)
294 { sCurrentHelpURL
= OUString(); }
296 return sCurrentHelpURL
;
299 //-----------------------------------------------
300 ::sal_Bool
HelpOnStartup::its_isHelpUrlADefaultOne(const OUString
& sHelpURL
)
302 if (sHelpURL
.isEmpty())
306 ResetableGuard
aLock(m_aLock
);
307 css::uno::Reference
< css::container::XNameAccess
> xConfig
= m_xConfig
;
308 OUString sLocale
= m_sLocale
;
309 OUString sSystem
= m_sSystem
;
316 // check given help url against all default ones
317 const css::uno::Sequence
< OUString
> lModules
= xConfig
->getElementNames();
318 const OUString
* pModules
= lModules
.getConstArray();
319 ::sal_Int32 c
= lModules
.getLength();
326 css::uno::Reference
< css::container::XNameAccess
> xModuleConfig
;
327 xConfig
->getByName(pModules
[i
]) >>= xModuleConfig
;
328 if (!xModuleConfig
.is())
331 OUString sHelpBaseURL
;
332 xModuleConfig
->getByName(PROP_HELP_BASEURL
) >>= sHelpBaseURL
;
333 OUString sHelpURLForModule
= HelpOnStartup::ist_createHelpURL(sHelpBaseURL
, sLocale
, sSystem
);
334 if (sHelpURL
.equals(sHelpURLForModule
))
337 catch(const css::uno::RuntimeException
&)
339 catch(const css::uno::Exception
&)
346 //-----------------------------------------------
347 OUString
HelpOnStartup::its_checkIfHelpEnabledAndGetURL(const OUString
& sModule
)
350 ResetableGuard
aLock(m_aLock
);
351 css::uno::Reference
< css::container::XNameAccess
> xConfig
= m_xConfig
;
352 OUString sLocale
= m_sLocale
;
353 OUString sSystem
= m_sSystem
;
361 css::uno::Reference
< css::container::XNameAccess
> xModuleConfig
;
363 xConfig
->getByName(sModule
) >>= xModuleConfig
;
365 sal_Bool bHelpEnabled
= sal_False
;
366 if (xModuleConfig
.is())
367 xModuleConfig
->getByName(PROP_AUTOMATIC_HELP
) >>= bHelpEnabled
;
371 OUString sHelpBaseURL
;
372 xModuleConfig
->getByName(PROP_HELP_BASEURL
) >>= sHelpBaseURL
;
373 sHelpURL
= HelpOnStartup::ist_createHelpURL(sHelpBaseURL
, sLocale
, sSystem
);
376 catch(const css::uno::RuntimeException
&)
378 catch(const css::uno::Exception
&)
379 { sHelpURL
= OUString(); }
384 //-----------------------------------------------
385 OUString
HelpOnStartup::ist_createHelpURL(const OUString
& sBaseURL
,
386 const OUString
& sLocale
,
387 const OUString
& sSystem
)
389 OUStringBuffer
sHelpURL(256);
390 sHelpURL
.append (sBaseURL
);
391 sHelpURL
.appendAscii("?Language=");
392 sHelpURL
.append (sLocale
);
393 sHelpURL
.appendAscii("&System=" );
394 sHelpURL
.append (sSystem
);
396 return sHelpURL
.makeStringAndClear();
399 } // namespace framework
401 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */