update credits
[LibreOffice.git] / framework / source / jobs / helponstartup.cxx
blob19b35a40f4b88e3a10a1c9c6b1addefe588c7bea
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 .
21 //_______________________________________________
22 // include own header
23 #include <jobs/helponstartup.hxx>
24 #include <threadhelp/resetableguard.hxx>
25 #include <loadenv/targethelper.hxx>
26 #include <services.h>
28 //_______________________________________________
29 // include others
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 //_______________________________________________
38 // include interfaces
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>
45 namespace framework{
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 ,
73 ::cppu::OWeakObject ,
74 SERVICENAME_JOB ,
75 IMPLEMENTATIONNAME_HELPONSTARTUP)
77 DEFINE_INIT_SERVICE(HelpOnStartup,
79 /* Attention
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(
91 m_xContext,
92 CFG_PACKAGE_MODULES,
93 ::comphelper::ConfigurationHelper::E_READONLY),
94 css::uno::UNO_QUERY_THROW);
96 // ask for office locale
97 ::comphelper::ConfigurationHelper::readDirectKey(
98 m_xContext,
99 CFG_PACKAGE_SETUP,
100 CFG_PATH_L10N,
101 CFG_KEY_LOCALE,
102 ::comphelper::ConfigurationHelper::E_READONLY) >>= m_sLocale;
104 // detect system
105 ::comphelper::ConfigurationHelper::readDirectKey(
106 m_xContext,
107 CFG_PACKAGE_COMMON,
108 CFG_PATH_HELP,
109 CFG_KEY_HELPSYSTEM,
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);
116 if (xComponent.is())
117 xComponent->addEventListener(static_cast< css::lang::XEventListener* >(this));
118 xComponent = css::uno::Reference< css::lang::XComponent >(m_xDesktop, css::uno::UNO_QUERY);
119 if (xComponent.is())
120 xComponent->addEventListener(static_cast< css::lang::XEventListener* >(this));
121 xComponent = css::uno::Reference< css::lang::XComponent >(m_xConfig, css::uno::UNO_QUERY);
122 if (xComponent.is())
123 xComponent->addEventListener(static_cast< css::lang::XEventListener* >(this));
127 //-----------------------------------------------
128 HelpOnStartup::HelpOnStartup(const css::uno::Reference< css::uno::XComponentContext >& xContext)
129 : ThreadHelpBase( )
130 , m_xContext (xContext)
134 //-----------------------------------------------
135 HelpOnStartup::~HelpOnStartup()
139 //-----------------------------------------------
140 // css.task.XJob
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;
163 // a)
164 if (sCurrentHelpURL.isEmpty())
165 bShowIt = sal_True;
166 // b)
167 else if (bCurrentHelpURLIsAnyDefaultURL)
168 bShowIt = sal_True;
170 if (bShowIt)
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();
179 if (pHelp)
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)
191 // SAFE ->
192 ResetableGuard aLock(m_aLock);
194 if (aEvent.Source == m_xModuleManager)
195 m_xModuleManager.clear();
196 else if (aEvent.Source == m_xDesktop)
197 m_xDesktop.clear();
198 else if (aEvent.Source == m_xConfig)
199 m_xConfig.clear();
201 aLock.unlock();
202 // <- SAFE
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))
217 return OUString();
219 css::uno::Reference< css::frame::XModel > xDoc = lEnvironment.getUnpackedValueOrDefault(PROP_MODEL, css::uno::Reference< css::frame::XModel >());
220 if (!xDoc.is())
221 return OUString();
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())
234 return OUString();
236 // OK - now we are sure this document is a top level document.
237 // Classify it.
238 // SAFE ->
239 ResetableGuard aLock(m_aLock);
240 css::uno::Reference< css::frame::XModuleManager2 > xModuleManager = m_xModuleManager;
241 aLock.unlock();
242 // <- SAFE
244 OUString sModuleId;
247 sModuleId = xModuleManager->identify(xDoc);
249 catch(const css::uno::RuntimeException&)
250 { throw; }
251 catch(const css::uno::Exception&)
252 { sModuleId = OUString(); }
254 return sModuleId;
257 //-----------------------------------------------
258 OUString HelpOnStartup::its_getCurrentHelpURL()
260 // SAFE ->
261 ResetableGuard aLock(m_aLock);
262 css::uno::Reference< css::frame::XDesktop2 > xDesktop = m_xDesktop;
263 aLock.unlock();
264 // <- SAFE
266 if (!xDesktop.is())
267 return OUString();
269 css::uno::Reference< css::frame::XFrame > xHelp = xDesktop->findFrame(SPECIALTARGET_HELPTASK, css::frame::FrameSearchFlag::CHILDREN);
270 if (!xHelp.is())
271 return OUString();
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;
284 if (xHelpChild.is())
285 xHelpView = xHelpChild->getController();
286 if (xHelpView.is())
287 xHelpContent = xHelpView->getModel();
288 if (xHelpContent.is())
289 sCurrentHelpURL = xHelpContent->getURL();
291 catch(const css::uno::RuntimeException&)
292 { throw; }
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())
303 return sal_False;
305 // SAFE ->
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;
310 aLock.unlock();
311 // <- SAFE
313 if (!xConfig.is())
314 return sal_False;
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();
320 ::sal_Int32 i = 0;
322 for (i=0; i<c; ++i)
326 css::uno::Reference< css::container::XNameAccess > xModuleConfig;
327 xConfig->getByName(pModules[i]) >>= xModuleConfig;
328 if (!xModuleConfig.is())
329 continue;
331 OUString sHelpBaseURL;
332 xModuleConfig->getByName(PROP_HELP_BASEURL) >>= sHelpBaseURL;
333 OUString sHelpURLForModule = HelpOnStartup::ist_createHelpURL(sHelpBaseURL, sLocale, sSystem);
334 if (sHelpURL.equals(sHelpURLForModule))
335 return sal_True;
337 catch(const css::uno::RuntimeException&)
338 { throw; }
339 catch(const css::uno::Exception&)
343 return sal_False;
346 //-----------------------------------------------
347 OUString HelpOnStartup::its_checkIfHelpEnabledAndGetURL(const OUString& sModule)
349 // SAFE ->
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;
354 aLock.unlock();
355 // <- SAFE
357 OUString sHelpURL;
361 css::uno::Reference< css::container::XNameAccess > xModuleConfig;
362 if (xConfig.is())
363 xConfig->getByName(sModule) >>= xModuleConfig;
365 sal_Bool bHelpEnabled = sal_False;
366 if (xModuleConfig.is())
367 xModuleConfig->getByName(PROP_AUTOMATIC_HELP) >>= bHelpEnabled;
369 if (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&)
377 { throw; }
378 catch(const css::uno::Exception&)
379 { sHelpURL = OUString(); }
381 return sHelpURL;
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: */