summaryrefslogtreecommitdiff
path: root/framework/source/jobs/helponstartup.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'framework/source/jobs/helponstartup.cxx')
-rw-r--r--framework/source/jobs/helponstartup.cxx426
1 files changed, 426 insertions, 0 deletions
diff --git a/framework/source/jobs/helponstartup.cxx b/framework/source/jobs/helponstartup.cxx
new file mode 100644
index 000000000000..ec84096eda94
--- /dev/null
+++ b/framework/source/jobs/helponstartup.cxx
@@ -0,0 +1,426 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_framework.hxx"
+
+//_______________________________________________
+// include own header
+#include <jobs/helponstartup.hxx>
+#include <threadhelp/resetableguard.hxx>
+#include <loadenv/targethelper.hxx>
+#include <services.h>
+
+//_______________________________________________
+// include others
+#include <comphelper/configurationhelper.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+#include <unotools/configmgr.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/help.hxx>
+#include <rtl/ustrbuf.hxx>
+
+//_______________________________________________
+// include interfaces
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/frame/XFramesSupplier.hpp>
+#include <com/sun/star/frame/XDesktop.hpp>
+
+//_______________________________________________
+// namespace
+
+namespace framework{
+
+//_______________________________________________
+// definitions
+
+// path to module config
+static ::rtl::OUString CFG_PACKAGE_MODULES (RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Setup/Office/Factories"));
+static ::rtl::OUString CFG_PACKAGE_SETUP (RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Setup"));
+static ::rtl::OUString CFG_PACKAGE_COMMON (RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.Common"));
+static ::rtl::OUString CFG_PATH_L10N (RTL_CONSTASCII_USTRINGPARAM("L10N"));
+static ::rtl::OUString CFG_PATH_HELP (RTL_CONSTASCII_USTRINGPARAM("Help"));
+static ::rtl::OUString CFG_KEY_LOCALE (RTL_CONSTASCII_USTRINGPARAM("ooLocale"));
+static ::rtl::OUString CFG_KEY_HELPSYSTEM (RTL_CONSTASCII_USTRINGPARAM("System"));
+
+// props of job environment
+static ::rtl::OUString PROP_ENVIRONMENT (RTL_CONSTASCII_USTRINGPARAM("Environment"));
+static ::rtl::OUString PROP_JOBCONFIG (RTL_CONSTASCII_USTRINGPARAM("JobConfig"));
+static ::rtl::OUString PROP_ENVTYPE (RTL_CONSTASCII_USTRINGPARAM("EnvType"));
+static ::rtl::OUString PROP_MODEL (RTL_CONSTASCII_USTRINGPARAM("Model"));
+
+// props of module config
+static ::rtl::OUString PROP_HELP_BASEURL (RTL_CONSTASCII_USTRINGPARAM("ooSetupFactoryHelpBaseURL"));
+static ::rtl::OUString PROP_AUTOMATIC_HELP (RTL_CONSTASCII_USTRINGPARAM("ooSetupFactoryHelpOnOpen"));
+
+// special value of job environment
+static ::rtl::OUString ENVTYPE_DOCUMENTEVENT (RTL_CONSTASCII_USTRINGPARAM("DOCUMENTEVENT"));
+
+//-----------------------------------------------
+
+DEFINE_XSERVICEINFO_MULTISERVICE(HelpOnStartup ,
+ ::cppu::OWeakObject ,
+ SERVICENAME_JOB ,
+ IMPLEMENTATIONNAME_HELPONSTARTUP)
+
+DEFINE_INIT_SERVICE(HelpOnStartup,
+ {
+ /* Attention
+ I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
+ to create a new instance of this class by our own supported service factory.
+ see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
+ */
+ // create some needed uno services and cache it
+ m_xModuleManager = css::uno::Reference< css::frame::XModuleManager >(
+ m_xSMGR->createInstance(SERVICENAME_MODULEMANAGER),
+ css::uno::UNO_QUERY_THROW);
+
+ m_xDesktop = css::uno::Reference< css::frame::XFrame >(
+ m_xSMGR->createInstance(SERVICENAME_DESKTOP),
+ css::uno::UNO_QUERY_THROW);
+
+ m_xConfig = css::uno::Reference< css::container::XNameAccess >(
+ ::comphelper::ConfigurationHelper::openConfig(
+ m_xSMGR,
+ CFG_PACKAGE_MODULES,
+ ::comphelper::ConfigurationHelper::E_READONLY),
+ css::uno::UNO_QUERY_THROW);
+
+ // ask for office locale
+ ::comphelper::ConfigurationHelper::readDirectKey(
+ m_xSMGR,
+ CFG_PACKAGE_SETUP,
+ CFG_PATH_L10N,
+ CFG_KEY_LOCALE,
+ ::comphelper::ConfigurationHelper::E_READONLY) >>= m_sLocale;
+
+ // detect system
+ ::comphelper::ConfigurationHelper::readDirectKey(
+ m_xSMGR,
+ CFG_PACKAGE_COMMON,
+ CFG_PATH_HELP,
+ CFG_KEY_HELPSYSTEM,
+ ::comphelper::ConfigurationHelper::E_READONLY) >>= m_sSystem;
+
+ // Start listening for disposing events of these services,
+ // so we can react e.g. for an office shutdown
+ css::uno::Reference< css::lang::XComponent > xComponent;
+ xComponent = css::uno::Reference< css::lang::XComponent >(m_xModuleManager, css::uno::UNO_QUERY);
+ if (xComponent.is())
+ xComponent->addEventListener(static_cast< css::lang::XEventListener* >(this));
+ xComponent = css::uno::Reference< css::lang::XComponent >(m_xDesktop, css::uno::UNO_QUERY);
+ if (xComponent.is())
+ xComponent->addEventListener(static_cast< css::lang::XEventListener* >(this));
+ xComponent = css::uno::Reference< css::lang::XComponent >(m_xConfig, css::uno::UNO_QUERY);
+ if (xComponent.is())
+ xComponent->addEventListener(static_cast< css::lang::XEventListener* >(this));
+ }
+ )
+
+//-----------------------------------------------
+HelpOnStartup::HelpOnStartup(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
+ : ThreadHelpBase( )
+ , m_xSMGR (xSMGR)
+{
+}
+
+//-----------------------------------------------
+HelpOnStartup::~HelpOnStartup()
+{
+}
+
+//-----------------------------------------------
+// css.task.XJob
+css::uno::Any SAL_CALL HelpOnStartup::execute(const css::uno::Sequence< css::beans::NamedValue >& lArguments)
+ throw(css::lang::IllegalArgumentException,
+ css::uno::Exception ,
+ css::uno::RuntimeException )
+{
+ // Analyze the given arguments; try to locate a model there and
+ // classify it's used application module.
+ ::rtl::OUString sModule = its_getModuleIdFromEnv(lArguments);
+
+ // Attention: We are bound to events for openeing any document inside the office.
+ // That includes e.g. the help module itself. But we have to do nothing then!
+ if (!sModule.getLength())
+ return css::uno::Any();
+
+ // check current state of the help module
+ // a) help isnt open => show default page for the detected module
+ // b) help shows any other default page(!) => show default page for the detected module
+ // c) help shows any other content => do nothing (user travelled to any other content and leaved the set of default pages)
+ ::rtl::OUString sCurrentHelpURL = its_getCurrentHelpURL();
+ sal_Bool bCurrentHelpURLIsAnyDefaultURL = its_isHelpUrlADefaultOne(sCurrentHelpURL);
+ sal_Bool bShowIt = sal_False;
+
+ // a)
+ if (!sCurrentHelpURL.getLength())
+ bShowIt = sal_True;
+ else
+ // b)
+ if (bCurrentHelpURLIsAnyDefaultURL)
+ bShowIt = sal_True;
+
+ if (bShowIt)
+ {
+ // retrieve the help URL for the detected application module
+ ::rtl::OUString sModuleDependendHelpURL = its_checkIfHelpEnabledAndGetURL(sModule);
+ if (sModuleDependendHelpURL.getLength())
+ {
+ // Show this help page.
+ // Note: The help window brings itself to front ...
+ Help* pHelp = Application::GetHelp();
+ if (pHelp)
+ pHelp->Start(sModuleDependendHelpURL, 0);
+ }
+ }
+
+ return css::uno::Any();
+}
+
+//-----------------------------------------------
+void SAL_CALL HelpOnStartup::disposing(const css::lang::EventObject& aEvent)
+ throw(css::uno::RuntimeException)
+{
+ // SAFE ->
+ ResetableGuard aLock(m_aLock);
+
+ if (aEvent.Source == m_xModuleManager)
+ m_xModuleManager.clear();
+ else
+ if (aEvent.Source == m_xDesktop)
+ m_xDesktop.clear();
+ else
+ if (aEvent.Source == m_xConfig)
+ m_xConfig.clear();
+
+ aLock.unlock();
+ // <- SAFE
+}
+
+//-----------------------------------------------
+::rtl::OUString HelpOnStartup::its_getModuleIdFromEnv(const css::uno::Sequence< css::beans::NamedValue >& lArguments)
+{
+ ::comphelper::SequenceAsHashMap lArgs (lArguments);
+ ::comphelper::SequenceAsHashMap lEnvironment = lArgs.getUnpackedValueOrDefault(PROP_ENVIRONMENT, css::uno::Sequence< css::beans::NamedValue >());
+ ::comphelper::SequenceAsHashMap lJobConfig = lArgs.getUnpackedValueOrDefault(PROP_JOBCONFIG , css::uno::Sequence< css::beans::NamedValue >());
+
+ // check for right environment.
+ // If its not a DocumentEvent, which triggered this job,
+ // we cant work correctly! => return immediatly and do nothing
+ ::rtl::OUString sEnvType = lEnvironment.getUnpackedValueOrDefault(PROP_ENVTYPE, ::rtl::OUString());
+ if (!sEnvType.equals(ENVTYPE_DOCUMENTEVENT))
+ return ::rtl::OUString();
+
+ css::uno::Reference< css::frame::XModel > xDoc = lEnvironment.getUnpackedValueOrDefault(PROP_MODEL, css::uno::Reference< css::frame::XModel >());
+ if (!xDoc.is())
+ return ::rtl::OUString();
+
+ // be sure that we work on top level documents only, which are registered
+ // on the desktop instance. Ignore e.g. life previews, which are top frames too ...
+ // but not registered at this global desktop instance.
+ css::uno::Reference< css::frame::XDesktop > xDesktopCheck;
+ css::uno::Reference< css::frame::XFrame > xFrame ;
+ css::uno::Reference< css::frame::XController > xController = xDoc->getCurrentController();
+ if (xController.is())
+ xFrame = xController->getFrame();
+ if (xFrame.is() && xFrame->isTop())
+ xDesktopCheck = css::uno::Reference< css::frame::XDesktop >(xFrame->getCreator(), css::uno::UNO_QUERY);
+ if (!xDesktopCheck.is())
+ return ::rtl::OUString();
+
+ // OK - now we are sure this document is a top level document.
+ // Classify it.
+ // SAFE ->
+ ResetableGuard aLock(m_aLock);
+ css::uno::Reference< css::frame::XModuleManager > xModuleManager = m_xModuleManager;
+ aLock.unlock();
+ // <- SAFE
+
+ if (!xModuleManager.is())
+ return ::rtl::OUString();
+
+ ::rtl::OUString sModuleId;
+ try
+ {
+ sModuleId = xModuleManager->identify(xDoc);
+ }
+ catch(const css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ catch(const css::uno::Exception&)
+ { sModuleId = ::rtl::OUString(); }
+
+ return sModuleId;
+}
+
+//-----------------------------------------------
+::rtl::OUString HelpOnStartup::its_getCurrentHelpURL()
+{
+ // SAFE ->
+ ResetableGuard aLock(m_aLock);
+ css::uno::Reference< css::frame::XFrame > xDesktop = m_xDesktop;
+ aLock.unlock();
+ // <- SAFE
+
+ if (!xDesktop.is())
+ return ::rtl::OUString();
+
+ css::uno::Reference< css::frame::XFrame > xHelp = xDesktop->findFrame(SPECIALTARGET_HELPTASK, css::frame::FrameSearchFlag::CHILDREN);
+ if (!xHelp.is())
+ return ::rtl::OUString();
+
+ ::rtl::OUString sCurrentHelpURL;
+ try
+ {
+ css::uno::Reference< css::frame::XFramesSupplier > xHelpRoot (xHelp , css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::container::XIndexAccess > xHelpChilds(xHelpRoot->getFrames(), css::uno::UNO_QUERY_THROW);
+
+ css::uno::Reference< css::frame::XFrame > xHelpChild ;
+ css::uno::Reference< css::frame::XController > xHelpView ;
+ css::uno::Reference< css::frame::XModel > xHelpContent;
+
+ xHelpChilds->getByIndex(0) >>= xHelpChild;
+ if (xHelpChild.is())
+ xHelpView = xHelpChild->getController();
+ if (xHelpView.is())
+ xHelpContent = xHelpView->getModel();
+ if (xHelpContent.is())
+ sCurrentHelpURL = xHelpContent->getURL();
+ }
+ catch(css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ catch(css::uno::Exception&)
+ { sCurrentHelpURL = ::rtl::OUString(); }
+
+ return sCurrentHelpURL;
+}
+
+//-----------------------------------------------
+::sal_Bool HelpOnStartup::its_isHelpUrlADefaultOne(const ::rtl::OUString& sHelpURL)
+{
+ if (!sHelpURL.getLength())
+ return sal_False;
+
+ // SAFE ->
+ ResetableGuard aLock(m_aLock);
+ css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR (m_xSMGR, css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::container::XNameAccess > xConfig = m_xConfig;
+ ::rtl::OUString sLocale = m_sLocale;
+ ::rtl::OUString sSystem = m_sSystem;
+ aLock.unlock();
+ // <- SAFE
+
+ if (!xConfig.is())
+ return sal_False;
+
+ // check given help url against all default ones
+ const css::uno::Sequence< ::rtl::OUString > lModules = xConfig->getElementNames();
+ const ::rtl::OUString* pModules = lModules.getConstArray();
+ ::sal_Int32 c = lModules.getLength();
+ ::sal_Int32 i = 0;
+
+ for (i=0; i<c; ++i)
+ {
+ try
+ {
+ css::uno::Reference< css::container::XNameAccess > xModuleConfig;
+ xConfig->getByName(pModules[i]) >>= xModuleConfig;
+ if (!xModuleConfig.is())
+ continue;
+
+ ::rtl::OUString sHelpBaseURL;
+ xModuleConfig->getByName(PROP_HELP_BASEURL) >>= sHelpBaseURL;
+ ::rtl::OUString sHelpURLForModule = HelpOnStartup::ist_createHelpURL(sHelpBaseURL, sLocale, sSystem);
+ if (sHelpURL.equals(sHelpURLForModule))
+ return sal_True;
+ }
+ catch(const css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ catch(const css::uno::Exception&)
+ {}
+ }
+
+ return sal_False;
+}
+
+//-----------------------------------------------
+::rtl::OUString HelpOnStartup::its_checkIfHelpEnabledAndGetURL(const ::rtl::OUString& sModule)
+{
+ // SAFE ->
+ ResetableGuard aLock(m_aLock);
+ css::uno::Reference< css::container::XNameAccess > xConfig = m_xConfig;
+ ::rtl::OUString sLocale = m_sLocale;
+ ::rtl::OUString sSystem = m_sSystem;
+ aLock.unlock();
+ // <- SAFE
+
+ ::rtl::OUString sHelpURL;
+
+ try
+ {
+ css::uno::Reference< css::container::XNameAccess > xModuleConfig;
+ if (xConfig.is())
+ xConfig->getByName(sModule) >>= xModuleConfig;
+
+ sal_Bool bHelpEnabled = sal_False;
+ if (xModuleConfig.is())
+ xModuleConfig->getByName(PROP_AUTOMATIC_HELP) >>= bHelpEnabled;
+
+ if (bHelpEnabled)
+ {
+ ::rtl::OUString sHelpBaseURL;
+ xModuleConfig->getByName(PROP_HELP_BASEURL) >>= sHelpBaseURL;
+ sHelpURL = HelpOnStartup::ist_createHelpURL(sHelpBaseURL, sLocale, sSystem);
+ }
+ }
+ catch(const css::uno::RuntimeException& exRun)
+ { throw exRun; }
+ catch(const css::uno::Exception&)
+ { sHelpURL = ::rtl::OUString(); }
+
+ return sHelpURL;
+}
+
+//-----------------------------------------------
+::rtl::OUString HelpOnStartup::ist_createHelpURL(const ::rtl::OUString& sBaseURL,
+ const ::rtl::OUString& sLocale ,
+ const ::rtl::OUString& sSystem )
+{
+ ::rtl::OUStringBuffer sHelpURL(256);
+ sHelpURL.append (sBaseURL );
+ sHelpURL.appendAscii("?Language=");
+ sHelpURL.append (sLocale );
+ sHelpURL.appendAscii("&System=" );
+ sHelpURL.append (sSystem );
+
+ return sHelpURL.makeStringAndClear();
+}
+
+} // namespace framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */