merge the formfield patch from ooo-build
[ooovba.git] / framework / source / jobs / helponstartup.cxx
blob0c476593393751ba1f684b8b55bcc6dfb1131549
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: helponstartup.cxx,v $
10 * $Revision: 1.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
34 //_______________________________________________
35 // include own header
36 #include <jobs/helponstartup.hxx>
37 #include <threadhelp/resetableguard.hxx>
38 #include <loadenv/targethelper.hxx>
39 #include <services.h>
41 //_______________________________________________
42 // include others
43 #include <comphelper/configurationhelper.hxx>
44 #include <comphelper/sequenceashashmap.hxx>
45 #include <unotools/configmgr.hxx>
46 #include <vcl/svapp.hxx>
47 #include <vcl/help.hxx>
48 #include <rtl/ustrbuf.hxx>
50 //_______________________________________________
51 // include interfaces
52 #include <com/sun/star/frame/FrameSearchFlag.hpp>
53 #include <com/sun/star/frame/XFramesSupplier.hpp>
54 #include <com/sun/star/frame/XDesktop.hpp>
56 //_______________________________________________
57 // namespace
59 namespace framework{
61 //_______________________________________________
62 // definitions
64 // path to module config
65 static ::rtl::OUString CFG_PACKAGE_MODULES = ::rtl::OUString::createFromAscii("/org.openoffice.Setup/Office/Factories");
66 static ::rtl::OUString CFG_PACKAGE_SETUP = ::rtl::OUString::createFromAscii("/org.openoffice.Setup" );
67 static ::rtl::OUString CFG_PACKAGE_COMMON = ::rtl::OUString::createFromAscii("/org.openoffice.Office.Common" );
68 static ::rtl::OUString CFG_PATH_L10N = ::rtl::OUString::createFromAscii("L10N" );
69 static ::rtl::OUString CFG_PATH_HELP = ::rtl::OUString::createFromAscii("Help" );
70 static ::rtl::OUString CFG_KEY_LOCALE = ::rtl::OUString::createFromAscii("ooLocale" );
71 static ::rtl::OUString CFG_KEY_HELPSYSTEM = ::rtl::OUString::createFromAscii("System" );
73 // props of job environment
74 static ::rtl::OUString PROP_ENVIRONMENT = ::rtl::OUString::createFromAscii("Environment" );
75 static ::rtl::OUString PROP_JOBCONFIG = ::rtl::OUString::createFromAscii("JobConfig" );
76 static ::rtl::OUString PROP_ENVTYPE = ::rtl::OUString::createFromAscii("EnvType" );
77 static ::rtl::OUString PROP_MODEL = ::rtl::OUString::createFromAscii("Model" );
79 // props of module config
80 static ::rtl::OUString PROP_HELP_BASEURL = ::rtl::OUString::createFromAscii("ooSetupFactoryHelpBaseURL" );
81 static ::rtl::OUString PROP_AUTOMATIC_HELP = ::rtl::OUString::createFromAscii("ooSetupFactoryHelpOnOpen" );
83 // special value of job environment
84 static ::rtl::OUString ENVTYPE_DOCUMENTEVENT = ::rtl::OUString::createFromAscii("DOCUMENTEVENT" );
86 //-----------------------------------------------
88 DEFINE_XSERVICEINFO_MULTISERVICE(HelpOnStartup ,
89 ::cppu::OWeakObject ,
90 SERVICENAME_JOB ,
91 IMPLEMENTATIONNAME_HELPONSTARTUP)
93 DEFINE_INIT_SERVICE(HelpOnStartup,
95 /* Attention
96 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
97 to create a new instance of this class by our own supported service factory.
98 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
100 // create some needed uno services and cache it
101 m_xModuleManager = css::uno::Reference< css::frame::XModuleManager >(
102 m_xSMGR->createInstance(SERVICENAME_MODULEMANAGER),
103 css::uno::UNO_QUERY_THROW);
105 m_xDesktop = css::uno::Reference< css::frame::XFrame >(
106 m_xSMGR->createInstance(SERVICENAME_DESKTOP),
107 css::uno::UNO_QUERY_THROW);
109 m_xConfig = css::uno::Reference< css::container::XNameAccess >(
110 ::comphelper::ConfigurationHelper::openConfig(
111 m_xSMGR,
112 CFG_PACKAGE_MODULES,
113 ::comphelper::ConfigurationHelper::E_READONLY),
114 css::uno::UNO_QUERY_THROW);
116 // ask for office locale
117 ::comphelper::ConfigurationHelper::readDirectKey(
118 m_xSMGR,
119 CFG_PACKAGE_SETUP,
120 CFG_PATH_L10N,
121 CFG_KEY_LOCALE,
122 ::comphelper::ConfigurationHelper::E_READONLY) >>= m_sLocale;
124 // detect system
125 ::comphelper::ConfigurationHelper::readDirectKey(
126 m_xSMGR,
127 CFG_PACKAGE_COMMON,
128 CFG_PATH_HELP,
129 CFG_KEY_HELPSYSTEM,
130 ::comphelper::ConfigurationHelper::E_READONLY) >>= m_sSystem;
132 // Start listening for disposing events of these services,
133 // so we can react e.g. for an office shutdown
134 css::uno::Reference< css::lang::XComponent > xComponent;
135 xComponent = css::uno::Reference< css::lang::XComponent >(m_xModuleManager, css::uno::UNO_QUERY);
136 if (xComponent.is())
137 xComponent->addEventListener(static_cast< css::lang::XEventListener* >(this));
138 xComponent = css::uno::Reference< css::lang::XComponent >(m_xDesktop, css::uno::UNO_QUERY);
139 if (xComponent.is())
140 xComponent->addEventListener(static_cast< css::lang::XEventListener* >(this));
141 xComponent = css::uno::Reference< css::lang::XComponent >(m_xConfig, css::uno::UNO_QUERY);
142 if (xComponent.is())
143 xComponent->addEventListener(static_cast< css::lang::XEventListener* >(this));
147 //-----------------------------------------------
148 HelpOnStartup::HelpOnStartup(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
149 : ThreadHelpBase( )
150 , m_xSMGR (xSMGR)
154 //-----------------------------------------------
155 HelpOnStartup::~HelpOnStartup()
159 //-----------------------------------------------
160 // css.task.XJob
161 css::uno::Any SAL_CALL HelpOnStartup::execute(const css::uno::Sequence< css::beans::NamedValue >& lArguments)
162 throw(css::lang::IllegalArgumentException,
163 css::uno::Exception ,
164 css::uno::RuntimeException )
166 // Analyze the given arguments; try to locate a model there and
167 // classify it's used application module.
168 ::rtl::OUString sModule = its_getModuleIdFromEnv(lArguments);
170 // Attention: We are bound to events for openeing any document inside the office.
171 // That includes e.g. the help module itself. But we have to do nothing then!
172 if (!sModule.getLength())
173 return css::uno::Any();
175 // check current state of the help module
176 // a) help isnt open => show default page for the detected module
177 // b) help shows any other default page(!) => show default page for the detected module
178 // c) help shows any other content => do nothing (user travelled to any other content and leaved the set of default pages)
179 ::rtl::OUString sCurrentHelpURL = its_getCurrentHelpURL();
180 sal_Bool bCurrentHelpURLIsAnyDefaultURL = its_isHelpUrlADefaultOne(sCurrentHelpURL);
181 sal_Bool bShowIt = sal_False;
183 // a)
184 if (!sCurrentHelpURL.getLength())
185 bShowIt = sal_True;
186 else
187 // b)
188 if (bCurrentHelpURLIsAnyDefaultURL)
189 bShowIt = sal_True;
191 if (bShowIt)
193 // retrieve the help URL for the detected application module
194 ::rtl::OUString sModuleDependendHelpURL = its_checkIfHelpEnabledAndGetURL(sModule);
195 if (sModuleDependendHelpURL.getLength())
197 // Show this help page.
198 // Note: The help window brings itself to front ...
199 Help* pHelp = Application::GetHelp();
200 if (pHelp)
201 pHelp->Start(sModuleDependendHelpURL, 0);
205 return css::uno::Any();
208 //-----------------------------------------------
209 void SAL_CALL HelpOnStartup::disposing(const css::lang::EventObject& aEvent)
210 throw(css::uno::RuntimeException)
212 // SAFE ->
213 ResetableGuard aLock(m_aLock);
215 if (aEvent.Source == m_xModuleManager)
216 m_xModuleManager.clear();
217 else
218 if (aEvent.Source == m_xDesktop)
219 m_xDesktop.clear();
220 else
221 if (aEvent.Source == m_xConfig)
222 m_xConfig.clear();
224 aLock.unlock();
225 // <- SAFE
228 //-----------------------------------------------
229 ::rtl::OUString HelpOnStartup::its_getModuleIdFromEnv(const css::uno::Sequence< css::beans::NamedValue >& lArguments)
231 ::comphelper::SequenceAsHashMap lArgs (lArguments);
232 ::comphelper::SequenceAsHashMap lEnvironment = lArgs.getUnpackedValueOrDefault(PROP_ENVIRONMENT, css::uno::Sequence< css::beans::NamedValue >());
233 ::comphelper::SequenceAsHashMap lJobConfig = lArgs.getUnpackedValueOrDefault(PROP_JOBCONFIG , css::uno::Sequence< css::beans::NamedValue >());
235 // check for right environment.
236 // If its not a DocumentEvent, which triggered this job,
237 // we cant work correctly! => return immediatly and do nothing
238 ::rtl::OUString sEnvType = lEnvironment.getUnpackedValueOrDefault(PROP_ENVTYPE, ::rtl::OUString());
239 if (!sEnvType.equals(ENVTYPE_DOCUMENTEVENT))
240 return ::rtl::OUString();
242 css::uno::Reference< css::frame::XModel > xDoc = lEnvironment.getUnpackedValueOrDefault(PROP_MODEL, css::uno::Reference< css::frame::XModel >());
243 if (!xDoc.is())
244 return ::rtl::OUString();
246 // be sure that we work on top level documents only, which are registered
247 // on the desktop instance. Ignore e.g. life previews, which are top frames too ...
248 // but not registered at this global desktop instance.
249 css::uno::Reference< css::frame::XDesktop > xDesktopCheck;
250 css::uno::Reference< css::frame::XFrame > xFrame ;
251 css::uno::Reference< css::frame::XController > xController = xDoc->getCurrentController();
252 if (xController.is())
253 xFrame = xController->getFrame();
254 if (xFrame.is() && xFrame->isTop())
255 xDesktopCheck = css::uno::Reference< css::frame::XDesktop >(xFrame->getCreator(), css::uno::UNO_QUERY);
256 if (!xDesktopCheck.is())
257 return ::rtl::OUString();
259 // OK - now we are sure this document is a top level document.
260 // Classify it.
261 // SAFE ->
262 ResetableGuard aLock(m_aLock);
263 css::uno::Reference< css::frame::XModuleManager > xModuleManager = m_xModuleManager;
264 aLock.unlock();
265 // <- SAFE
267 if (!xModuleManager.is())
268 return ::rtl::OUString();
270 ::rtl::OUString sModuleId;
273 sModuleId = xModuleManager->identify(xDoc);
275 catch(const css::uno::RuntimeException& exRun)
276 { throw exRun; }
277 catch(const css::uno::Exception&)
278 { sModuleId = ::rtl::OUString(); }
280 return sModuleId;
283 //-----------------------------------------------
284 ::rtl::OUString HelpOnStartup::its_getCurrentHelpURL()
286 // SAFE ->
287 ResetableGuard aLock(m_aLock);
288 css::uno::Reference< css::frame::XFrame > xDesktop = m_xDesktop;
289 aLock.unlock();
290 // <- SAFE
292 if (!xDesktop.is())
293 return ::rtl::OUString();
295 css::uno::Reference< css::frame::XFrame > xHelp = xDesktop->findFrame(SPECIALTARGET_HELPTASK, css::frame::FrameSearchFlag::CHILDREN);
296 if (!xHelp.is())
297 return ::rtl::OUString();
299 ::rtl::OUString sCurrentHelpURL;
302 css::uno::Reference< css::frame::XFramesSupplier > xHelpRoot (xHelp , css::uno::UNO_QUERY_THROW);
303 css::uno::Reference< css::container::XIndexAccess > xHelpChilds(xHelpRoot->getFrames(), css::uno::UNO_QUERY_THROW);
305 css::uno::Reference< css::frame::XFrame > xHelpChild ;
306 css::uno::Reference< css::frame::XController > xHelpView ;
307 css::uno::Reference< css::frame::XModel > xHelpContent;
309 xHelpChilds->getByIndex(0) >>= xHelpChild;
310 if (xHelpChild.is())
311 xHelpView = xHelpChild->getController();
312 if (xHelpView.is())
313 xHelpContent = xHelpView->getModel();
314 if (xHelpContent.is())
315 sCurrentHelpURL = xHelpContent->getURL();
317 catch(css::uno::RuntimeException& exRun)
318 { throw exRun; }
319 catch(css::uno::Exception&)
320 { sCurrentHelpURL = ::rtl::OUString(); }
322 return sCurrentHelpURL;
325 //-----------------------------------------------
326 ::sal_Bool HelpOnStartup::its_isHelpUrlADefaultOne(const ::rtl::OUString& sHelpURL)
328 if (!sHelpURL.getLength())
329 return sal_False;
331 // SAFE ->
332 ResetableGuard aLock(m_aLock);
333 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR (m_xSMGR, css::uno::UNO_QUERY_THROW);
334 css::uno::Reference< css::container::XNameAccess > xConfig = m_xConfig;
335 ::rtl::OUString sLocale = m_sLocale;
336 ::rtl::OUString sSystem = m_sSystem;
337 aLock.unlock();
338 // <- SAFE
340 if (!xConfig.is())
341 return sal_False;
343 // check given help url against all default ones
344 const css::uno::Sequence< ::rtl::OUString > lModules = xConfig->getElementNames();
345 const ::rtl::OUString* pModules = lModules.getConstArray();
346 ::sal_Int32 c = lModules.getLength();
347 ::sal_Int32 i = 0;
349 for (i=0; i<c; ++i)
353 css::uno::Reference< css::container::XNameAccess > xModuleConfig;
354 xConfig->getByName(pModules[i]) >>= xModuleConfig;
355 if (!xModuleConfig.is())
356 continue;
358 ::rtl::OUString sHelpBaseURL;
359 xModuleConfig->getByName(PROP_HELP_BASEURL) >>= sHelpBaseURL;
360 ::rtl::OUString sHelpURLForModule = HelpOnStartup::ist_createHelpURL(sHelpBaseURL, sLocale, sSystem);
361 if (sHelpURL.equals(sHelpURLForModule))
362 return sal_True;
364 catch(const css::uno::RuntimeException& exRun)
365 { throw exRun; }
366 catch(const css::uno::Exception&)
370 return sal_False;
373 //-----------------------------------------------
374 ::rtl::OUString HelpOnStartup::its_checkIfHelpEnabledAndGetURL(const ::rtl::OUString& sModule)
376 // SAFE ->
377 ResetableGuard aLock(m_aLock);
378 css::uno::Reference< css::container::XNameAccess > xConfig = m_xConfig;
379 ::rtl::OUString sLocale = m_sLocale;
380 ::rtl::OUString sSystem = m_sSystem;
381 aLock.unlock();
382 // <- SAFE
384 ::rtl::OUString sHelpURL;
388 css::uno::Reference< css::container::XNameAccess > xModuleConfig;
389 if (xConfig.is())
390 xConfig->getByName(sModule) >>= xModuleConfig;
392 sal_Bool bHelpEnabled = sal_False;
393 if (xModuleConfig.is())
394 xModuleConfig->getByName(PROP_AUTOMATIC_HELP) >>= bHelpEnabled;
396 if (bHelpEnabled)
398 ::rtl::OUString sHelpBaseURL;
399 xModuleConfig->getByName(PROP_HELP_BASEURL) >>= sHelpBaseURL;
400 sHelpURL = HelpOnStartup::ist_createHelpURL(sHelpBaseURL, sLocale, sSystem);
403 catch(const css::uno::RuntimeException& exRun)
404 { throw exRun; }
405 catch(const css::uno::Exception&)
406 { sHelpURL = ::rtl::OUString(); }
408 return sHelpURL;
411 //-----------------------------------------------
412 ::rtl::OUString HelpOnStartup::ist_createHelpURL(const ::rtl::OUString& sBaseURL,
413 const ::rtl::OUString& sLocale ,
414 const ::rtl::OUString& sSystem )
416 ::rtl::OUStringBuffer sHelpURL(256);
417 sHelpURL.append (sBaseURL );
418 sHelpURL.appendAscii("?Language=");
419 sHelpURL.append (sLocale );
420 sHelpURL.appendAscii("&System=" );
421 sHelpURL.append (sSystem );
423 return sHelpURL.makeStringAndClear();
426 } // namespace framework