office-gobmx/framework/source/jobs/helponstartup.cxx

424 lines
17 KiB
C++

/* -*- 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.
*
************************************************************************/
//_______________________________________________
// 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.isEmpty())
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.isEmpty())
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.isEmpty())
{
// 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&)
{ throw; }
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 > xHelpChildren(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;
xHelpChildren->getByIndex(0) >>= xHelpChild;
if (xHelpChild.is())
xHelpView = xHelpChild->getController();
if (xHelpView.is())
xHelpContent = xHelpView->getModel();
if (xHelpContent.is())
sCurrentHelpURL = xHelpContent->getURL();
}
catch(const css::uno::RuntimeException&)
{ throw; }
catch(const css::uno::Exception&)
{ sCurrentHelpURL = ::rtl::OUString(); }
return sCurrentHelpURL;
}
//-----------------------------------------------
::sal_Bool HelpOnStartup::its_isHelpUrlADefaultOne(const ::rtl::OUString& sHelpURL)
{
if (sHelpURL.isEmpty())
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&)
{ throw; }
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&)
{ throw; }
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: */