diff options
Diffstat (limited to 'desktop/source/deployment/gui/dp_gui_updatedialog.cxx')
-rw-r--r-- | desktop/source/deployment/gui/dp_gui_updatedialog.cxx | 1301 |
1 files changed, 1301 insertions, 0 deletions
diff --git a/desktop/source/deployment/gui/dp_gui_updatedialog.cxx b/desktop/source/deployment/gui/dp_gui_updatedialog.cxx new file mode 100644 index 000000000000..b27cd8da81fe --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_updatedialog.cxx @@ -0,0 +1,1301 @@ +/************************************************************************* + * + * 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_desktop.hxx" + +#include "sal/config.h" + +#include <cstddef> +#include <limits> +#include <map> +#include <memory> +#include <utility> +#include <vector> + + +#include "boost/optional.hpp" +#include "com/sun/star/awt/Rectangle.hpp" +#include "com/sun/star/awt/WindowAttribute.hpp" +#include "com/sun/star/awt/WindowClass.hpp" +#include "com/sun/star/awt/WindowDescriptor.hpp" +#include "com/sun/star/awt/XThrobber.hpp" +#include "com/sun/star/awt/XToolkit.hpp" +#include "com/sun/star/awt/XWindow.hpp" +#include "com/sun/star/awt/XWindowPeer.hpp" +#include "com/sun/star/beans/NamedValue.hpp" +#include "com/sun/star/beans/Optional.hpp" +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/container/XNameAccess.hpp" +#include "com/sun/star/deployment/DeploymentException.hpp" +#include "com/sun/star/deployment/UpdateInformationProvider.hpp" +#include "com/sun/star/deployment/XPackage.hpp" +#include "com/sun/star/deployment/XExtensionManager.hpp" +#include "com/sun/star/deployment/ExtensionManager.hpp" +#include "com/sun/star/deployment/XUpdateInformationProvider.hpp" +#include "com/sun/star/frame/XDesktop.hpp" +#include "com/sun/star/frame/XDispatch.hpp" +#include "com/sun/star/frame/XDispatchProvider.hpp" +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "com/sun/star/lang/XMultiComponentFactory.hpp" +#include "com/sun/star/system/SystemShellExecuteFlags.hpp" +#include "com/sun/star/system/XSystemShellExecute.hpp" +#include "com/sun/star/task/XAbortChannel.hpp" +#include "com/sun/star/task/XJob.hpp" +#include "com/sun/star/ucb/CommandAbortedException.hpp" +#include "com/sun/star/ucb/CommandFailedException.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/util/URL.hpp" +#include "com/sun/star/util/XURLTransformer.hpp" +#include "com/sun/star/xml/dom/XElement.hpp" +#include "com/sun/star/xml/dom/XNode.hpp" +#include "osl/diagnose.h" +#include "rtl/bootstrap.hxx" +#include "rtl/ref.hxx" +#include "rtl/string.h" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "svtools/svlbitm.hxx" +#include "svtools/svlbox.hxx" +#include <svtools/controldims.hrc> +#include "svx/checklbx.hxx" +#include "tools/gen.hxx" +#include "tools/link.hxx" +#include "tools/resid.hxx" +#include "tools/resmgr.hxx" +#include "tools/solar.h" +#include "tools/string.hxx" +#include "vcl/button.hxx" +#include "vcl/dialog.hxx" +#include "vcl/fixed.hxx" +#include "vcl/image.hxx" +#include "vcl/msgbox.hxx" +#include "vcl/svapp.hxx" +#include "vos/mutex.hxx" + +#include "comphelper/processfactory.hxx" + +#include "dp_dependencies.hxx" +#include "dp_descriptioninfoset.hxx" +#include "dp_identifier.hxx" +#include "dp_version.hxx" +#include "dp_misc.h" +#include "dp_update.hxx" + +#include "dp_gui.h" +#include "dp_gui.hrc" +#include "dp_gui_thread.hxx" +#include "dp_gui_updatedata.hxx" +#include "dp_gui_updatedialog.hxx" +#include "dp_gui_shared.hxx" +#include "dp_gui_system.hxx" + +class KeyEvent; +class MouseEvent; +class Window; +namespace com { namespace sun { namespace star { namespace uno { + class XComponentContext; +} } } } + +namespace css = ::com::sun::star; + +using dp_gui::UpdateDialog; + +namespace { + +static sal_Unicode const LF = 0x000A; +static sal_Unicode const CR = 0x000D; + +enum Kind { ENABLED_UPDATE, DISABLED_UPDATE, GENERAL_ERROR, SPECIFIC_ERROR }; + +rtl::OUString confineToParagraph(rtl::OUString const & text) { + // Confine arbitrary text to a single paragraph in a dp_gui::AutoScrollEdit. + // This assumes that U+000A and U+000D are the only paragraph separators in + // a dp_gui::AutoScrollEdit, and that replacing them with a single space + // each is acceptable: + return text.replace(LF, ' ').replace(CR, ' '); +} +} + +struct UpdateDialog::DisabledUpdate { + rtl::OUString name; + css::uno::Sequence< rtl::OUString > unsatisfiedDependencies; + // We also want to show release notes and publisher for disabled updates + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > aUpdateInfo; +}; + +struct UpdateDialog::SpecificError { + rtl::OUString name; + rtl::OUString message; +}; + +union UpdateDialog::IndexUnion{ + std::vector< dp_gui::UpdateData >::size_type enabledUpdate; + std::vector< UpdateDialog::DisabledUpdate >::size_type disabledUpdate; + std::vector< rtl::OUString >::size_type generalError; + std::vector< UpdateDialog::SpecificError >::size_type specificError; +}; + +struct UpdateDialog::Index { + static std::auto_ptr< UpdateDialog::Index const > newEnabledUpdate( + std::vector< dp_gui::UpdateData >::size_type n); + + static std::auto_ptr< UpdateDialog::Index const > newDisabledUpdate( + std::vector< UpdateDialog::DisabledUpdate >::size_type n); + + static std::auto_ptr< UpdateDialog::Index const > newGeneralError( + std::vector< rtl::OUString >::size_type n); + + static std::auto_ptr< UpdateDialog::Index const > newSpecificError( + std::vector< UpdateDialog::SpecificError >::size_type n); + + Kind kind; + IndexUnion index; + +private: + explicit Index(Kind theKind); +}; + +std::auto_ptr< UpdateDialog::Index const > +UpdateDialog::Index::newEnabledUpdate( + std::vector< dp_gui::UpdateData >::size_type n) +{ + UpdateDialog::Index * p = new UpdateDialog::Index(ENABLED_UPDATE); + p->index.enabledUpdate = n; + return std::auto_ptr< UpdateDialog::Index const >(p); +} + +std::auto_ptr< UpdateDialog::Index const > +UpdateDialog::Index::newDisabledUpdate( + std::vector< UpdateDialog::DisabledUpdate >::size_type n) +{ + UpdateDialog::Index * p = new UpdateDialog::Index(DISABLED_UPDATE); + p->index.disabledUpdate = n; + return std::auto_ptr< UpdateDialog::Index const >(p); +} + +std::auto_ptr< UpdateDialog::Index const > UpdateDialog::Index::newGeneralError( + std::vector< rtl::OUString >::size_type n) +{ + UpdateDialog::Index * p = new UpdateDialog::Index(GENERAL_ERROR); + p->index.generalError = n; + return std::auto_ptr< UpdateDialog::Index const >(p); +} + +std::auto_ptr< UpdateDialog::Index const > +UpdateDialog::Index::newSpecificError( + std::vector< UpdateDialog::SpecificError >::size_type n) +{ + UpdateDialog::Index * p = new UpdateDialog::Index(SPECIFIC_ERROR); + p->index.specificError = n; + return std::auto_ptr< UpdateDialog::Index const >(p); +} + +UpdateDialog::Index::Index(Kind theKind): kind(theKind) {} + +class UpdateDialog::Thread: public dp_gui::Thread { +public: + Thread( + css::uno::Reference< css::uno::XComponentContext > const & context, + UpdateDialog & dialog, + const std::vector< css::uno::Reference< css::deployment::XPackage > > & vExtensionList); + + void stop(); + +private: + Thread(UpdateDialog::Thread &); // not defined + void operator =(UpdateDialog::Thread &); // not defined + + struct Entry { + explicit Entry( + css::uno::Reference< css::deployment::XPackage > const & thePackage, + rtl::OUString const & theVersion); + + css::uno::Reference< css::deployment::XPackage > package; + rtl::OUString version; + //Indicates that the extension provides its own update URLs. + //If this is true, then we must not use the default update + //URL to find the update information. + bool bProvidesOwnUpdate; + css::uno::Reference< css::xml::dom::XNode > info; + UpdateDialog::DisabledUpdate disableUpdate; + dp_gui::UpdateData updateData; + }; + + // A multimap in case an extension is installed in "user", "shared" or "bundled" + typedef std::map< rtl::OUString, Entry > Map; + + virtual ~Thread(); + + virtual void execute(); +#if 0 + void handleGeneralError(css::uno::Any const & exception) const; +#endif + void handleSpecificError( + css::uno::Reference< css::deployment::XPackage > const & package, + css::uno::Any const & exception) const; + + css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > + getUpdateInformation( + css::uno::Reference< css::deployment::XPackage > const & package, + css::uno::Sequence< rtl::OUString > const & urls, + rtl::OUString const & identifier) const; + + void getOwnUpdateInformation( + css::uno::Reference< css::deployment::XPackage > const & package, + Map * map); + + ::rtl::OUString getUpdateDisplayString( + dp_gui::UpdateData const & data, ::rtl::OUString const & version = ::rtl::OUString()) const; + + void prepareUpdateData( + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > const & updateInfo, + UpdateDialog::DisabledUpdate & out_du, + dp_gui::UpdateData & out_data) const; + + bool update( + UpdateDialog::DisabledUpdate const & du, + dp_gui::UpdateData const & data) const; + + css::uno::Reference< css::uno::XComponentContext > m_context; + UpdateDialog & m_dialog; + std::vector< css::uno::Reference< css::deployment::XPackage > > m_vExtensionList; + css::uno::Reference< css::deployment::XUpdateInformationProvider > m_updateInformation; + css::uno::Reference< css::task::XInteractionHandler > m_xInteractionHdl; + + // guarded by Application::GetSolarMutex(): + css::uno::Reference< css::task::XAbortChannel > m_abort; + bool m_stop; +}; + +UpdateDialog::Thread::Thread( + css::uno::Reference< css::uno::XComponentContext > const & context, + UpdateDialog & dialog, + const std::vector< css::uno::Reference< css::deployment::XPackage > > &vExtensionList): + m_context(context), + m_dialog(dialog), + m_vExtensionList(vExtensionList), + m_updateInformation( + css::deployment::UpdateInformationProvider::create(context)), + m_stop(false) +{ + if( m_context.is() ) + { + css::uno::Reference< css::lang::XMultiComponentFactory > xServiceManager( m_context->getServiceManager() ); + + if( xServiceManager.is() ) + { + m_xInteractionHdl = css::uno::Reference< css::task::XInteractionHandler > ( + xServiceManager->createInstanceWithContext( OUSTR( "com.sun.star.task.InteractionHandler" ), m_context), + css::uno::UNO_QUERY ); + if ( m_xInteractionHdl.is() ) + m_updateInformation->setInteractionHandler( m_xInteractionHdl ); + } + } +} + +void UpdateDialog::Thread::stop() { + css::uno::Reference< css::task::XAbortChannel > abort; + { + vos::OGuard g(Application::GetSolarMutex()); + abort = m_abort; + m_stop = true; + } + if (abort.is()) { + abort->sendAbort(); + } + m_updateInformation->cancel(); +} + +UpdateDialog::Thread::Entry::Entry( + css::uno::Reference< css::deployment::XPackage > const & thePackage, + rtl::OUString const & theVersion): + + package(thePackage), + version(theVersion), + bProvidesOwnUpdate(false), + updateData(thePackage) +{ +} + +UpdateDialog::Thread::~Thread() +{ + if ( m_xInteractionHdl.is() ) + m_updateInformation->setInteractionHandler( css::uno::Reference< css::task::XInteractionHandler > () ); +} + +void UpdateDialog::Thread::execute() +{ + { + vos::OGuard g( Application::GetSolarMutex() ); + if ( m_stop ) { + return; + } + } + css::uno::Reference<css::deployment::XExtensionManager> extMgr = + css::deployment::ExtensionManager::get(m_context); + + std::vector<std::pair<css::uno::Reference<css::deployment::XPackage>, css::uno::Any > > errors; + + dp_misc::UpdateInfoMap updateInfoMap = dp_misc::getOnlineUpdateInfos( + m_context, extMgr, m_updateInformation, &m_vExtensionList, errors); + + typedef std::vector<std::pair<css::uno::Reference<css::deployment::XPackage>, + css::uno::Any> >::const_iterator ITERROR; + for (ITERROR ite = errors.begin(); ite != errors.end(); ite ++) + handleSpecificError(ite->first, ite->second); + + for (dp_misc::UpdateInfoMap::iterator i(updateInfoMap.begin()); i != updateInfoMap.end(); i++) + { + dp_misc::UpdateInfo const & info = i->second; + UpdateData updateData(info.extension); + DisabledUpdate disableUpdate; + //determine if online updates meet the requirements + prepareUpdateData(info.info, disableUpdate, updateData); + + //determine if the update is installed in the user or shared repository + rtl::OUString sOnlineVersion; + if (info.info.is()) + sOnlineVersion = info.version; + rtl::OUString sVersionUser; + rtl::OUString sVersionShared; + rtl::OUString sVersionBundled; + css::uno::Sequence< css::uno::Reference< css::deployment::XPackage> > extensions; + try { + extensions = extMgr->getExtensionsWithSameIdentifier( + dp_misc::getIdentifier(info.extension), info.extension->getName(), + css::uno::Reference<css::ucb::XCommandEnvironment>()); + } catch (css::lang::IllegalArgumentException& ) { + OSL_ASSERT(0); + } + OSL_ASSERT(extensions.getLength() == 3); + if (extensions[0].is() ) + sVersionUser = extensions[0]->getVersion(); + if (extensions[1].is() ) + sVersionShared = extensions[1]->getVersion(); + if (extensions[2].is() ) + sVersionBundled = extensions[2]->getVersion(); + + bool bSharedReadOnly = extMgr->isReadOnlyRepository(OUSTR("shared")); + + dp_misc::UPDATE_SOURCE sourceUser = dp_misc::isUpdateUserExtension( + bSharedReadOnly, sVersionUser, sVersionShared, sVersionBundled, sOnlineVersion); + dp_misc::UPDATE_SOURCE sourceShared = dp_misc::isUpdateSharedExtension( + bSharedReadOnly, sVersionShared, sVersionBundled, sOnlineVersion); + + css::uno::Reference<css::deployment::XPackage> updateSource; + if (sourceUser != dp_misc::UPDATE_SOURCE_NONE) + { + if (sourceUser == dp_misc::UPDATE_SOURCE_SHARED) + { + updateData.aUpdateSource = extensions[1]; + updateData.updateVersion = extensions[1]->getVersion(); + } + else if (sourceUser == dp_misc::UPDATE_SOURCE_BUNDLED) + { + updateData.aUpdateSource = extensions[2]; + updateData.updateVersion = extensions[2]->getVersion(); + } + if (!update(disableUpdate, updateData)) + return; + } + + if (sourceShared != dp_misc::UPDATE_SOURCE_NONE) + { + if (sourceShared == dp_misc::UPDATE_SOURCE_BUNDLED) + { + updateData.aUpdateSource = extensions[2]; + updateData.updateVersion = extensions[2]->getVersion(); + } + updateData.bIsShared = true; + if (!update(disableUpdate, updateData)) + return; + } + } + + + vos::OGuard g(Application::GetSolarMutex()); + if (!m_stop) { + m_dialog.checkingDone(); + } +} +#if 0 +void UpdateDialog::Thread::handleGeneralError(css::uno::Any const & exception) + const +{ + rtl::OUString message; + css::uno::Exception e; + if (exception >>= e) { + message = e.Message; + } + vos::OGuard g(Application::GetSolarMutex()); + if (!m_stop) { + m_dialog.addGeneralError(message); + } +} +#endif +//Parameter package can be null +void UpdateDialog::Thread::handleSpecificError( + css::uno::Reference< css::deployment::XPackage > const & package, + css::uno::Any const & exception) const +{ + UpdateDialog::SpecificError data; + if (package.is()) + data.name = package->getDisplayName(); + css::uno::Exception e; + if (exception >>= e) { + data.message = e.Message; + } + vos::OGuard g(Application::GetSolarMutex()); + if (!m_stop) { + m_dialog.addSpecificError(data); + } +} + +::rtl::OUString UpdateDialog::Thread::getUpdateDisplayString( + dp_gui::UpdateData const & data, ::rtl::OUString const & version) const +{ + OSL_ASSERT(data.aInstalledPackage.is()); + rtl::OUStringBuffer b(data.aInstalledPackage->getDisplayName()); + b.append(static_cast< sal_Unicode >(' ')); + { + vos::OGuard g( Application::GetSolarMutex() ); + if(!m_stop) + b.append(m_dialog.m_version); + } + b.append(static_cast< sal_Unicode >(' ')); + if (version.getLength()) + b.append(version); + else + b.append(data.updateVersion); + + if (data.sWebsiteURL.getLength()) + { + b.append(static_cast< sal_Unicode >(' ')); + { + vos::OGuard g( Application::GetSolarMutex() ); + if(!m_stop) + b.append(m_dialog.m_browserbased); + } + } + return b.makeStringAndClear(); +} + +/** out_data will only be filled if all dependencies are ok. + */ +void UpdateDialog::Thread::prepareUpdateData( + css::uno::Reference< css::xml::dom::XNode > const & updateInfo, + UpdateDialog::DisabledUpdate & out_du, + dp_gui::UpdateData & out_data) const +{ + if (!updateInfo.is()) + return; + dp_misc::DescriptionInfoset infoset(m_context, updateInfo); + OSL_ASSERT(infoset.getVersion().getLength() != 0); + css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > ds( + dp_misc::Dependencies::check(infoset)); + + out_du.aUpdateInfo = updateInfo; + out_du.unsatisfiedDependencies.realloc(ds.getLength()); + for (sal_Int32 i = 0; i < ds.getLength(); ++i) { + out_du.unsatisfiedDependencies[i] = dp_misc::Dependencies::getErrorText(ds[i]); + } + + const ::boost::optional< ::rtl::OUString> updateWebsiteURL(infoset.getLocalizedUpdateWebsiteURL()); + + out_du.name = getUpdateDisplayString(out_data, infoset.getVersion()); + + if (out_du.unsatisfiedDependencies.getLength() == 0) + { + out_data.aUpdateInfo = updateInfo; + out_data.updateVersion = infoset.getVersion(); + if (updateWebsiteURL) + out_data.sWebsiteURL = *updateWebsiteURL; + } +} + +bool UpdateDialog::Thread::update( + UpdateDialog::DisabledUpdate const & du, + dp_gui::UpdateData const & data) const +{ + bool ret = false; + if (du.unsatisfiedDependencies.getLength() == 0) + { + vos::OGuard g(Application::GetSolarMutex()); + if (!m_stop) { + m_dialog.addEnabledUpdate(getUpdateDisplayString(data), data); + } + ret = !m_stop; + } else { + vos::OGuard g(Application::GetSolarMutex()); + if (!m_stop) { + m_dialog.addDisabledUpdate(du); + } + ret = !m_stop; + } + return ret; +} + +// UpdateDialog ---------------------------------------------------------- +UpdateDialog::UpdateDialog( + css::uno::Reference< css::uno::XComponentContext > const & context, + Window * parent, + const std::vector<css::uno::Reference< css::deployment::XPackage > > &vExtensionList, + std::vector< dp_gui::UpdateData > * updateData): + ModalDialog(parent,DpGuiResId(RID_DLG_UPDATE)), + m_context(context), + m_checking(this, DpGuiResId(RID_DLG_UPDATE_CHECKING)), + m_update(this, DpGuiResId(RID_DLG_UPDATE_UPDATE)), + m_updates( + *this, DpGuiResId(RID_DLG_UPDATE_UPDATES), + Image(DpGuiResId(RID_DLG_UPDATE_NORMALALERT)), + Image(DpGuiResId(RID_DLG_UPDATE_HIGHCONTRASTALERT))), + m_all(this, DpGuiResId(RID_DLG_UPDATE_ALL)), + m_description(this, DpGuiResId(RID_DLG_UPDATE_DESCRIPTION)), + m_PublisherLabel(this, DpGuiResId(RID_DLG_UPDATE_PUBLISHER_LABEL)), + m_PublisherLink(this, DpGuiResId(RID_DLG_UPDATE_PUBLISHER_LINK)), + m_ReleaseNotesLabel(this, DpGuiResId(RID_DLG_UPDATE_RELEASENOTES_LABEL)), + m_ReleaseNotesLink(this, DpGuiResId(RID_DLG_UPDATE_RELEASENOTES_LINK)), + m_descriptions(this, DpGuiResId(RID_DLG_UPDATE_DESCRIPTIONS)), + m_line(this, DpGuiResId(RID_DLG_UPDATE_LINE)), + m_help(this, DpGuiResId(RID_DLG_UPDATE_HELP)), + m_ok(this, DpGuiResId(RID_DLG_UPDATE_OK)), + m_cancel(this, DpGuiResId(RID_DLG_UPDATE_CANCEL)), + m_error(String(DpGuiResId(RID_DLG_UPDATE_ERROR))), + m_none(String(DpGuiResId(RID_DLG_UPDATE_NONE))), + m_noInstallable(String(DpGuiResId(RID_DLG_UPDATE_NOINSTALLABLE))), + m_failure(String(DpGuiResId(RID_DLG_UPDATE_FAILURE))), + m_unknownError(String(DpGuiResId(RID_DLG_UPDATE_UNKNOWNERROR))), + m_noDescription(String(DpGuiResId(RID_DLG_UPDATE_NODESCRIPTION))), + m_noInstall(String(DpGuiResId(RID_DLG_UPDATE_NOINSTALL))), + m_noDependency(String(DpGuiResId(RID_DLG_UPDATE_NODEPENDENCY))), + m_noDependencyCurVer(String(DpGuiResId(RID_DLG_UPDATE_NODEPENDENCY_CUR_VER))), + m_browserbased(String(DpGuiResId(RID_DLG_UPDATE_BROWSERBASED))), + m_version(String(DpGuiResId(RID_DLG_UPDATE_VERSION))), + m_updateData(*updateData), + m_thread( + new UpdateDialog::Thread( + context, *this, vExtensionList)), + m_nFirstLineDelta(0), + m_nOneLineMissing(0) + // TODO: check! +// , +// m_extensionManagerDialog(extensionManagerDialog) +{ + OSL_ASSERT(updateData != NULL); + + m_xExtensionManager = css::deployment::ExtensionManager::get( context ); + + css::uno::Reference< css::awt::XToolkit > toolkit; + try { + toolkit = css::uno::Reference< css::awt::XToolkit >( + (css::uno::Reference< css::lang::XMultiComponentFactory >( + m_context->getServiceManager(), + css::uno::UNO_QUERY_THROW)-> + createInstanceWithContext( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.Toolkit")), + m_context)), + css::uno::UNO_QUERY_THROW); + } catch (css::uno::RuntimeException &) { + throw; + } catch (css::uno::Exception & e) { + throw css::uno::RuntimeException(e.Message, e.Context); + } + Control c(this, DpGuiResId(RID_DLG_UPDATE_THROBBER)); + Point pos(c.GetPosPixel()); + Size size(c.GetSizePixel()); + try { + m_throbber = css::uno::Reference< css::awt::XThrobber >( + toolkit->createWindow( + css::awt::WindowDescriptor( + css::awt::WindowClass_SIMPLE, + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Throbber")), + GetComponentInterface(), 0, + css::awt::Rectangle( + pos.X(), pos.Y(), size.Width(), size.Height()), + css::awt::WindowAttribute::SHOW)), + css::uno::UNO_QUERY_THROW); + } catch (css::lang::IllegalArgumentException & e) { + throw css::uno::RuntimeException(e.Message, e.Context); + } + m_updates.SetSelectHdl(LINK(this, UpdateDialog, selectionHandler)); + m_all.SetToggleHdl(LINK(this, UpdateDialog, allHandler)); + m_ok.SetClickHdl(LINK(this, UpdateDialog, okHandler)); + m_cancel.SetClickHdl(LINK(this, UpdateDialog, cancelHandler)); + if ( ! dp_misc::office_is_running()) + m_help.Disable(); + FreeResource(); + + initDescription(); +} + +UpdateDialog::~UpdateDialog() { + for (USHORT i = 0; i < m_updates.getItemCount(); ++i) { + delete static_cast< UpdateDialog::Index const * >( + m_updates.GetEntryData(i)); + } +} + +BOOL UpdateDialog::Close() { + m_thread->stop(); + return ModalDialog::Close(); +} + +short UpdateDialog::Execute() { + m_throbber->start(); + m_thread->launch(); + return ModalDialog::Execute(); +} + +UpdateDialog::CheckListBox::CheckListBox( + UpdateDialog & dialog, ResId const & resource, + Image const & normalStaticImage, Image const & highContrastStaticImage): + SvxCheckListBox( + &dialog, resource, normalStaticImage, highContrastStaticImage), + m_dialog(dialog) +{} + +UpdateDialog::CheckListBox::~CheckListBox() {} + +USHORT UpdateDialog::CheckListBox::getItemCount() const { + ULONG i = GetEntryCount(); + OSL_ASSERT(i <= std::numeric_limits< USHORT >::max()); + return sal::static_int_cast< USHORT >(i); +} + +void UpdateDialog::CheckListBox::MouseButtonDown(MouseEvent const & event) { + // When clicking on a selected entry in an SvxCheckListBox, the entry's + // checkbox is toggled on mouse button down: + SvxCheckListBox::MouseButtonDown(event); + m_dialog.enableOk(); +} + +void UpdateDialog::CheckListBox::MouseButtonUp(MouseEvent const & event) { + // When clicking on an entry's checkbox in an SvxCheckListBox, the entry's + // checkbox is toggled on mouse button up: + SvxCheckListBox::MouseButtonUp(event); + m_dialog.enableOk(); +} + +void UpdateDialog::CheckListBox::KeyInput(KeyEvent const & event) { + SvxCheckListBox::KeyInput(event); + m_dialog.enableOk(); +} + +void UpdateDialog::insertItem( + rtl::OUString const & name, USHORT position, + std::auto_ptr< UpdateDialog::Index const > index, SvLBoxButtonKind kind) +{ + m_updates.InsertEntry( + name, position, + const_cast< void * >(static_cast< void const * >(index.release())), + kind); + //TODO #i72487#: UpdateDialog::Index potentially leaks as the exception + // behavior of SvxCheckListBox::InsertEntry is unspecified +} + +void UpdateDialog::addAdditional( + rtl::OUString const & name, USHORT position, + std::auto_ptr< UpdateDialog::Index const > index, SvLBoxButtonKind kind) +{ + m_all.Enable(); + if (m_all.IsChecked()) { + insertItem(name, position, index, kind); + m_update.Enable(); + m_updates.Enable(); + m_description.Enable(); + m_descriptions.Enable(); + } +} + +void UpdateDialog::addEnabledUpdate( + rtl::OUString const & name, dp_gui::UpdateData const & data) +{ + std::vector< dp_gui::UpdateData >::size_type n = m_enabledUpdates.size(); + m_enabledUpdates.push_back(data); + insertItem( + name, sal::static_int_cast< USHORT >(n), + UpdateDialog::Index::newEnabledUpdate(n), + SvLBoxButtonKind_enabledCheckbox); + // position overflow is rather harmless + m_updates.CheckEntryPos(sal::static_int_cast< USHORT >(n)); + //TODO #i72487#: fragile computation; insertItem should instead return + // pos + m_update.Enable(); + m_updates.Enable(); + m_description.Enable(); + m_descriptions.Enable(); +} + +void UpdateDialog::addDisabledUpdate(UpdateDialog::DisabledUpdate const & data) +{ + std::vector< UpdateDialog::DisabledUpdate >::size_type n = + m_disabledUpdates.size(); + m_disabledUpdates.push_back(data); + addAdditional( + data.name, sal::static_int_cast< USHORT >(m_enabledUpdates.size() + n), + UpdateDialog::Index::newDisabledUpdate(n), + SvLBoxButtonKind_disabledCheckbox); + // position overflow is rather harmless +} +#if 0 +void UpdateDialog::addGeneralError(rtl::OUString const & message) { + std::vector< rtl::OUString >::size_type n = m_generalErrors.size(); + m_generalErrors.push_back(message); + addAdditional( + m_error, + sal::static_int_cast< USHORT >( + m_enabledUpdates.size() + m_disabledUpdates.size() + n), + UpdateDialog::Index::newGeneralError(n), SvLBoxButtonKind_staticImage); + // position overflow is rather harmless +} +#endif +void UpdateDialog::addSpecificError(UpdateDialog::SpecificError const & data) { + std::vector< UpdateDialog::SpecificError >::size_type n = + m_specificErrors.size(); + m_specificErrors.push_back(data); + addAdditional( + data.name, LISTBOX_APPEND, UpdateDialog::Index::newSpecificError(n), + SvLBoxButtonKind_staticImage); +} + +void UpdateDialog::checkingDone() { + m_checking.Hide(); + m_throbber->stop(); + css::uno::Reference< css::awt::XWindow >( + m_throbber, css::uno::UNO_QUERY_THROW)->setVisible(false); + if (m_updates.getItemCount() == 0) + { + clearDescription(); + m_description.Enable(); + m_descriptions.Enable(); + showDescription( + ( m_disabledUpdates.empty() && m_generalErrors.empty() && m_specificErrors.empty() ) + ? m_none : m_noInstallable, false ); + } + enableOk(); +} + +void UpdateDialog::enableOk() { + if (!m_checking.IsVisible()) { + m_ok.Enable(m_updates.GetCheckedEntryCount() != 0); + } +} + +// ********************************************************************************* +void UpdateDialog::createNotifyJob( bool bPrepareOnly, + css::uno::Sequence< css::uno::Sequence< rtl::OUString > > &rItemList ) +{ + if ( !dp_misc::office_is_running() ) + return; + + // notify update check job + try + { + css::uno::Reference< css::lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); + css::uno::Reference< css::lang::XMultiServiceFactory > xConfigProvider( + xFactory->createInstance( OUSTR( "com.sun.star.configuration.ConfigurationProvider" )), + css::uno::UNO_QUERY_THROW); + + css::beans::PropertyValue aProperty; + aProperty.Name = OUSTR( "nodepath" ); + aProperty.Value = css::uno::makeAny( OUSTR("org.openoffice.Office.Addons/AddonUI/OfficeHelp/UpdateCheckJob") ); + + css::uno::Sequence< css::uno::Any > aArgumentList( 1 ); + aArgumentList[0] = css::uno::makeAny( aProperty ); + + css::uno::Reference< css::container::XNameAccess > xNameAccess( + xConfigProvider->createInstanceWithArguments( + OUSTR("com.sun.star.configuration.ConfigurationAccess"), aArgumentList ), + css::uno::UNO_QUERY_THROW ); + + css::util::URL aURL; + xNameAccess->getByName(OUSTR("URL")) >>= aURL.Complete; + + css::uno::Reference < css::util::XURLTransformer > xTransformer( xFactory->createInstance( OUSTR( "com.sun.star.util.URLTransformer" ) ), + css::uno::UNO_QUERY_THROW ); + + xTransformer->parseStrict(aURL); + + css::uno::Reference < css::frame::XDesktop > xDesktop( xFactory->createInstance( OUSTR( "com.sun.star.frame.Desktop" ) ), + css::uno::UNO_QUERY_THROW ); + css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider( xDesktop->getCurrentFrame(), + css::uno::UNO_QUERY_THROW ); + css::uno::Reference< css::frame::XDispatch > xDispatch = xDispatchProvider->queryDispatch(aURL, rtl::OUString(), 0); + + if( xDispatch.is() ) + { + css::uno::Sequence< css::beans::PropertyValue > aPropList(2); + aProperty.Name = OUSTR( "updateList" ); + aProperty.Value = css::uno::makeAny( rItemList ); + aPropList[0] = aProperty; + aProperty.Name = OUSTR( "prepareOnly" ); + aProperty.Value = css::uno::makeAny( bPrepareOnly ); + aPropList[1] = aProperty; + + xDispatch->dispatch(aURL, aPropList ); + } + } + catch( const css::uno::Exception& e ) + { + dp_misc::TRACE( OUSTR("Caught exception: ") + + e.Message + OUSTR("\n thread terminated.\n\n")); + } +} + +// ********************************************************************************* +void UpdateDialog::notifyMenubar( bool bPrepareOnly, bool bRecheckOnly ) +{ + if ( !dp_misc::office_is_running() ) + return; + + css::uno::Sequence< css::uno::Sequence< rtl::OUString > > aItemList; + sal_Int32 nCount = 0; + + if ( ! bRecheckOnly ) + { + for ( sal_Int16 i = 0; i < m_updates.getItemCount(); ++i ) + { + css::uno::Sequence< rtl::OUString > aItem(2); + + UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >(m_updates.GetEntryData(i)); + + if ( p->kind == ENABLED_UPDATE ) + { + dp_gui::UpdateData aUpdData = m_enabledUpdates[ p->index.enabledUpdate ]; + aItem[0] = dp_misc::getIdentifier( aUpdData.aInstalledPackage ); + + dp_misc::DescriptionInfoset aInfoset( m_context, aUpdData.aUpdateInfo ); + aItem[1] = aInfoset.getVersion(); + } + else if ( p->kind == DISABLED_UPDATE ) + continue; + else + continue; + + aItemList.realloc( nCount + 1 ); + aItemList[ nCount ] = aItem; + nCount += 1; + } + } + createNotifyJob( bPrepareOnly, aItemList ); +} + +// ********************************************************************************* + +void UpdateDialog::initDescription() +{ + m_PublisherLabel.Hide(); + m_PublisherLink.Hide(); + m_ReleaseNotesLabel.Hide(); + m_ReleaseNotesLink.Hide(); + m_descriptions.Hide(); + + Link aLink = LINK( this, UpdateDialog, hyperlink_clicked ); + m_PublisherLink.SetClickHdl( aLink ); + m_ReleaseNotesLink.SetClickHdl( aLink ); + + long nTextWidth = m_PublisherLabel.GetCtrlTextWidth( m_PublisherLabel.GetText() ); + long nTemp = m_ReleaseNotesLabel.GetTextWidth( m_ReleaseNotesLabel.GetText() ); + if ( nTemp > nTextWidth ) + nTextWidth = nTemp; + nTextWidth = nTextWidth * 110 / 100; + + Size aNewSize = m_PublisherLabel.GetSizePixel(); + if ( nTextWidth > aNewSize.Width() ) + { + long nDelta = nTextWidth - aNewSize.Width(); + aNewSize.Width() = nTextWidth; + m_PublisherLabel.SetSizePixel( aNewSize ); + m_ReleaseNotesLabel.SetSizePixel( aNewSize ); + + aNewSize = m_PublisherLink.GetSizePixel(); + aNewSize.Width() = aNewSize.Width() - nDelta; + Point aNewPos = m_PublisherLink.GetPosPixel(); + aNewPos.X() = aNewPos.X() + nDelta; + m_PublisherLink.SetPosSizePixel( aNewPos, aNewSize ); + aNewPos.Y() = m_ReleaseNotesLink.GetPosPixel().Y(); + m_ReleaseNotesLink.SetPosSizePixel( aNewPos, aNewSize ); + } + + m_aFirstLinePos = m_descriptions.GetPosPixel(); + m_aFirstLineSize = m_descriptions.GetSizePixel(); + Size aMarginSize = LogicToPixel( Size( RSC_SP_CTRL_GROUP_X, RSC_SP_CTRL_GROUP_Y ), MAP_APPFONT ); + Point aThirdLinePos = m_ReleaseNotesLabel.GetPosPixel(); + aThirdLinePos.Y() = aThirdLinePos.Y() + m_ReleaseNotesLabel.GetSizePixel().Height() + aMarginSize.Height(); + m_nFirstLineDelta = aThirdLinePos.Y() - m_aFirstLinePos.Y(); + m_nOneLineMissing = m_ReleaseNotesLabel.GetPosPixel().Y() - m_PublisherLabel.GetPosPixel().Y(); +} + +void UpdateDialog::clearDescription() +{ + String sEmpty; + m_PublisherLabel.Hide(); + m_PublisherLink.Hide(); + m_PublisherLink.SetDescription( sEmpty ); + m_PublisherLink.SetURL( sEmpty ); + m_ReleaseNotesLabel.Hide(); + m_ReleaseNotesLink.Hide(); + m_ReleaseNotesLink.SetURL( sEmpty ); + if ( m_PublisherLabel.GetPosPixel().Y() == m_ReleaseNotesLabel.GetPosPixel().Y() ) + { + Point aNewPos = m_ReleaseNotesLabel.GetPosPixel(); + aNewPos.Y() += m_nOneLineMissing; + m_ReleaseNotesLabel.SetPosPixel( aNewPos ); + aNewPos = m_ReleaseNotesLink.GetPosPixel(); + aNewPos.Y() += m_nOneLineMissing; + m_ReleaseNotesLink.SetPosPixel( aNewPos ); + } + m_descriptions.Hide(); + m_descriptions.Clear(); + m_descriptions.SetPosSizePixel( m_aFirstLinePos, m_aFirstLineSize ); +} + +bool UpdateDialog::showDescription(css::uno::Reference< css::xml::dom::XNode > const & aUpdateInfo) +{ + dp_misc::DescriptionInfoset infoset(m_context, aUpdateInfo); + return showDescription(infoset.getLocalizedPublisherNameAndURL(), + infoset.getLocalizedReleaseNotesURL()); +} + +bool UpdateDialog::showDescription(css::uno::Reference< css::deployment::XPackage > const & aExtension) +{ + OSL_ASSERT(aExtension.is()); + css::beans::StringPair pubInfo = aExtension->getPublisherInfo(); + return showDescription(std::make_pair(pubInfo.First, pubInfo.Second), + OUSTR("")); +} + +bool UpdateDialog::showDescription(std::pair< rtl::OUString, rtl::OUString > const & pairPublisher, + rtl::OUString const & sReleaseNotes) +{ + rtl::OUString sPub = pairPublisher.first; + rtl::OUString sURL = pairPublisher.second; + + if ( sPub.getLength() == 0 && sURL.getLength() == 0 && sReleaseNotes.getLength() == 0 ) + // nothing to show + return false; + + bool bPublisher = false; + if ( sPub.getLength() > 0 ) + { + m_PublisherLabel.Show(); + m_PublisherLink.Show(); + m_PublisherLink.SetDescription( sPub ); + m_PublisherLink.SetURL( sURL ); + bPublisher = true; + } + + if ( sReleaseNotes.getLength() > 0 ) + { + if ( !bPublisher ) + { + m_ReleaseNotesLabel.SetPosPixel( m_PublisherLabel.GetPosPixel() ); + m_ReleaseNotesLink.SetPosPixel( m_PublisherLink.GetPosPixel() ); + } + m_ReleaseNotesLabel.Show(); + m_ReleaseNotesLink.Show(); + m_ReleaseNotesLink.SetURL( sReleaseNotes ); + } + return true; +} + +bool UpdateDialog::showDescription( const String& rDescription, bool bWithPublisher ) +{ + if ( rDescription.Len() == 0 ) + // nothing to show + return false; + + if ( bWithPublisher ) + { + bool bOneLineMissing = !m_ReleaseNotesLabel.IsVisible() || !m_PublisherLabel.IsVisible(); + Point aNewPos = m_aFirstLinePos; + aNewPos.Y() += m_nFirstLineDelta; + if ( bOneLineMissing ) + aNewPos.Y() -= m_nOneLineMissing; + Size aNewSize = m_aFirstLineSize; + aNewSize.Height() -= m_nFirstLineDelta; + if ( bOneLineMissing ) + aNewSize.Height() += m_nOneLineMissing; + m_descriptions.SetPosSizePixel( aNewPos, aNewSize ); + } + m_descriptions.Show(); + m_descriptions.SetDescription( rDescription ); + return true; +} + +bool UpdateDialog::isReadOnly( const css::uno::Reference< css::deployment::XPackage > &xPackage ) const +{ + if ( m_xExtensionManager.is() && xPackage.is() ) + { + return m_xExtensionManager->isReadOnlyRepository( xPackage->getRepositoryName() ); + } + else + return true; +} + +IMPL_LINK(UpdateDialog, selectionHandler, void *, EMPTYARG) +{ + rtl::OUStringBuffer b; + bool bInserted = false; + UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >( + m_updates.GetEntryData(m_updates.GetSelectEntryPos())); + clearDescription(); + + if (p != NULL) + { + //When the index is greater or equal than the amount of enabled updates then the "Show all" + //button is probably checked. Then we show first all enabled and then the disabled + //updates. + USHORT pos = m_updates.GetSelectEntryPos(); + const std::vector< dp_gui::UpdateData >::size_type sizeEnabled = + m_enabledUpdates.size(); + const std::vector< UpdateDialog::DisabledUpdate >::size_type sizeDisabled = + m_disabledUpdates.size(); + if (pos < sizeEnabled) + { + if (m_enabledUpdates[pos].aUpdateSource.is()) + bInserted = showDescription(m_enabledUpdates[pos].aUpdateSource); + else + bInserted = showDescription(m_enabledUpdates[pos].aUpdateInfo); + } + else if (pos >= sizeEnabled + && pos < (sizeEnabled + sizeDisabled)) + bInserted = showDescription(m_disabledUpdates[pos - sizeEnabled].aUpdateInfo); + + switch (p->kind) + { + case ENABLED_UPDATE: + { + b.append(m_noDescription); + break; + } + case DISABLED_UPDATE: + { + UpdateDialog::DisabledUpdate & data = m_disabledUpdates[ + p->index.disabledUpdate]; + if (data.unsatisfiedDependencies.getLength() != 0) + { + // create error string for version mismatch + ::rtl::OUString sVersion( RTL_CONSTASCII_USTRINGPARAM("%VERSION") ); + sal_Int32 nPos = m_noDependencyCurVer.indexOf( sVersion ); + if ( nPos >= 0 ) + { + ::rtl::OUString sCurVersion( RTL_CONSTASCII_USTRINGPARAM( "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":Version:OOOPackageVersion}")); + ::rtl::Bootstrap::expandMacros(sCurVersion); + m_noDependencyCurVer = m_noDependencyCurVer.replaceAt( nPos, sVersion.getLength(), sCurVersion ); + } + + b.append(m_noInstall); + b.append(LF); + b.append(m_noDependency); + for (sal_Int32 i = 0; + i < data.unsatisfiedDependencies.getLength(); ++i) + { + b.append(LF); + b.appendAscii(RTL_CONSTASCII_STRINGPARAM(" ")); + // U+2003 EM SPACE would be better than two spaces, + // but some fonts do not contain it + b.append( + confineToParagraph( + data.unsatisfiedDependencies[i])); + } + b.append(LF); + b.appendAscii(RTL_CONSTASCII_STRINGPARAM(" ")); + b.append(m_noDependencyCurVer); + } + break; + } + case GENERAL_ERROR: + { + rtl::OUString & msg = m_generalErrors[p->index.generalError]; + b.append(m_failure); + b.append(LF); + b.append(msg.getLength() == 0 ? m_unknownError : msg); + break; + } + case SPECIFIC_ERROR: + { + UpdateDialog::SpecificError & data = m_specificErrors[ + p->index.specificError]; + b.append(m_failure); + b.append(LF); + b.append( + data.message.getLength() == 0 + ? m_unknownError : data.message); + break; + } + default: + OSL_ASSERT(false); + break; + } + } + + showDescription( b.makeStringAndClear(), bInserted ); + return 0; +} + +IMPL_LINK(UpdateDialog, allHandler, void *, EMPTYARG) { + if (m_all.IsChecked()) { + m_update.Enable(); + m_updates.Enable(); + m_description.Enable(); + m_descriptions.Enable(); + std::vector< UpdateDialog::DisabledUpdate >::size_type n1 = 0; + for (std::vector< UpdateDialog::DisabledUpdate >::iterator i( + m_disabledUpdates.begin()); + i != m_disabledUpdates.end(); ++i) + { + insertItem( + i->name, LISTBOX_APPEND, + UpdateDialog::Index::newDisabledUpdate(n1++), + SvLBoxButtonKind_disabledCheckbox); + } + std::vector< rtl::OUString >::size_type n2 = 0; + for (std::vector< rtl::OUString >::iterator i(m_generalErrors.begin()); + i != m_generalErrors.end(); ++i) + { + insertItem( + m_error, LISTBOX_APPEND, + UpdateDialog::Index::newGeneralError(n2++), + SvLBoxButtonKind_staticImage); + } + std::vector< UpdateDialog::SpecificError >::size_type n3 = 0; + for (std::vector< UpdateDialog::SpecificError >::iterator i( + m_specificErrors.begin()); + i != m_specificErrors.end(); ++i) + { + insertItem( + i->name, LISTBOX_APPEND, + UpdateDialog::Index::newSpecificError(n3++), + SvLBoxButtonKind_staticImage); + } + } else { + for (USHORT i = 0; i < m_updates.getItemCount();) { + UpdateDialog::Index const * p = + static_cast< UpdateDialog::Index const * >( + m_updates.GetEntryData(i)); + if (p->kind != ENABLED_UPDATE) { + m_updates.RemoveEntry(i); + //TODO #i72487#: UpdateDialog::Index potentially leaks as + // SvxCheckListBox::RemoveEntry's exception behavior is + // unspecified + delete p; + } else { + ++i; + } + } + + if (m_updates.getItemCount() == 0) + { + clearDescription(); + m_update.Disable(); + m_updates.Disable(); + if (m_checking.IsVisible()) + m_description.Disable(); + else + showDescription(m_noInstallable,false); + } + } + return 0; +} + +IMPL_LINK(UpdateDialog, okHandler, void *, EMPTYARG) +{ + //If users are going to update a shared extension then we need + //to warn them + typedef ::std::vector<UpdateData>::const_iterator CIT; + for (CIT i = m_enabledUpdates.begin(); i < m_enabledUpdates.end(); i++) + { + OSL_ASSERT(i->aInstalledPackage.is()); + //If the user has no write access to the shared folder then the update + //for a shared extension is disable, that is it cannot be in m_enabledUpdates +// OSL_ASSERT(isReadOnly(i->aInstalledPackage) == sal_False); +#if 0 + // TODO: check! + OSL_ASSERT(m_extensionManagerDialog.get()); + if (RET_CANCEL == m_extensionManagerDialog->continueUpdateForSharedExtension( + this, i->aPackageManager)) + { + EndDialog(RET_CANCEL); + } +#endif + } + + + for (USHORT i = 0; i < m_updates.getItemCount(); ++i) { + UpdateDialog::Index const * p = + static_cast< UpdateDialog::Index const * >( + m_updates.GetEntryData(i)); + if (p->kind == ENABLED_UPDATE && m_updates.IsChecked(i)) { + m_updateData.push_back(m_enabledUpdates[p->index.enabledUpdate]); + } + } + + EndDialog(RET_OK); + return 0; +} + +IMPL_LINK(UpdateDialog, cancelHandler, void *, EMPTYARG) { + m_thread->stop(); + EndDialog(RET_CANCEL); + return 0; +} + +IMPL_LINK( UpdateDialog, hyperlink_clicked, svt::FixedHyperlink*, pHyperlink ) +{ + ::rtl::OUString sURL; + if ( pHyperlink ) + sURL = ::rtl::OUString( pHyperlink->GetURL() ); + if ( sURL.getLength() == 0 ) + return 0; + + try + { + css::uno::Reference< css::system::XSystemShellExecute > xSystemShellExecute( + m_context->getServiceManager()->createInstanceWithContext( + OUSTR( "com.sun.star.system.SystemShellExecute" ), + m_context), css::uno::UNO_QUERY_THROW); + //throws css::lang::IllegalArgumentException, css::system::SystemShellExecuteException + xSystemShellExecute->execute( + sURL, ::rtl::OUString(), css::system::SystemShellExecuteFlags::DEFAULTS); + } + catch (css::uno::Exception& ) + { + } + + return 1; +} |