office-gobmx/desktop/source/deployment/gui/dp_gui_cmdenv.cxx
Ivo Hinkelmann 0442b1601e INTEGRATION: CWS jl49 (1.9.8); FILE MERGED
2006/12/05 11:30:52 jl 1.9.8.3: #70481#
2006/11/27 14:17:37 jl 1.9.8.2: #i70481# handling LicenseIndividualAgreementException and ProgressCommandEnv can now be used without the main dialog
2006/11/22 17:51:59 sb 1.9.8.1: #i70481# Factored out dependency handling.
2006-12-20 16:57:01 +00:00

510 lines
18 KiB
C++

/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: dp_gui_cmdenv.cxx,v $
*
* $Revision: 1.11 $
*
* last change: $Author: ihi $ $Date: 2006-12-20 17:57:01 $
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2005 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library 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 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_desktop.hxx"
#include "dp_gui.hrc"
#include "dp_gui.h"
#include "dp_gui_cmdenv.h"
#include "dp_gui_shared.hxx"
#include "dp_gui_dependencydialog.hxx"
#include "dp_dependencies.hxx"
#include "dp_version.hxx"
#include "comphelper/anytostring.hxx"
#include "com/sun/star/lang/WrappedTargetException.hpp"
#include "com/sun/star/beans/PropertyValue.hpp"
#include "com/sun/star/task/XInteractionAbort.hpp"
#include "com/sun/star/task/XInteractionApprove.hpp"
#include "com/sun/star/deployment/DependencyException.hpp"
#include "com/sun/star/deployment/LicenseException.hpp"
#include "com/sun/star/deployment/LicenseIndividualAgreementException.hpp"
#include "com/sun/star/deployment/VersionException.hpp"
#include "com/sun/star/deployment/InstallException.hpp"
#include "com/sun/star/deployment/ui/LicenseDialog.hpp"
#include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp"
#include "tools/resid.hxx"
#include "tools/rcid.h"
#include "vcl/msgbox.hxx"
#include "vcl/threadex.hxx"
#include "toolkit/helper/vclunohelper.hxx"
#include "boost/bind.hpp"
namespace css = ::com::sun::star;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::ucb;
using ::rtl::OUString;
namespace {
rtl::OUString getVersion(
css::uno::Reference< css::deployment::XPackage > const & package)
{
rtl::OUString s(package->getVersion());
return s.getLength() == 0
? rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0")) : s;
}
}
namespace dp_gui
{
//______________________________________________________________________________
void ProgressCommandEnv::ProgressDialog::CancelButtonImpl::Click()
{
m_dialog->m_cmdEnv->m_aborted = true;
if (m_dialog->m_cmdEnv->m_xAbortChannel.is())
{
try {
m_dialog->m_cmdEnv->m_xAbortChannel->sendAbort();
}
catch (RuntimeException &) {
OSL_ENSURE( 0, "### unexpected RuntimeException!" );
}
}
}
void ProgressCommandEnv::solarthread_dtor()
{
if (m_progressDialog.get() != 0) {
const ::vos::OGuard guard( Application::GetSolarMutex() );
m_progressDialog->SetModalInputMode( FALSE );
m_progressDialog.reset();
}
}
Dialog * ProgressCommandEnv::activeDialog() {
Dialog * p = m_progressDialog.get();
return p == NULL ? m_dialog : p;
}
//______________________________________________________________________________
ProgressCommandEnv::~ProgressCommandEnv()
{
vcl::solarthread::syncExecute(
boost::bind( &ProgressCommandEnv::solarthread_dtor, this ) );
}
//______________________________________________________________________________
ProgressCommandEnv::ProgressDialog::ProgressDialog(
ProgressCommandEnv * cmdEnv )
: Dialog( cmdEnv->m_dialog, WB_STDMODAL ),
m_cmdEnv( cmdEnv )
{
SetModalInputMode( TRUE );
}
//______________________________________________________________________________
IMPL_LINK( ProgressCommandEnv, executeDialog, ::osl::Condition *, pCond )
{
{
DialogImpl *mainDialog = dynamic_cast<dp_gui::DialogImpl*>(m_dialog);
if (mainDialog == NULL)
{
OSL_ASSERT(0);
return 0;
}
::std::auto_ptr<ProgressDialog> that( new ProgressDialog( this ) );
that->SetHelpId( HID_PACKAGE_MANAGER_PROGRESS );
that->SetStyle( that->GetStyle() & ~WB_CLOSEABLE ); // non-closeable
that->SetText( m_title );
long totalWidth = that->LogicToPixel(
Size( 250, 0 ), MapMode( MAP_APPFONT ) ).getWidth();
long barWidth = totalWidth -
(2 * mainDialog->m_borderLeftTopSpace.getWidth());
long posY = mainDialog->m_borderLeftTopSpace.getHeight();
that->m_ftCurrentAction.reset( new FixedText( that.get() ) );
that->m_ftCurrentAction->SetPosSizePixel(
mainDialog->m_borderLeftTopSpace.getWidth(), posY,
barWidth, mainDialog->m_ftFontHeight );
posY += (mainDialog->m_ftFontHeight +
mainDialog->m_descriptionYSpace);
that->m_statusBar.reset(
new StatusBar( that.get(), WB_LEFT | WB_3DLOOK ) );
that->m_statusBar->SetPosSizePixel(
mainDialog->m_borderLeftTopSpace.getWidth(), posY,
barWidth, mainDialog->m_ftFontHeight + 4 );
posY += (mainDialog->m_ftFontHeight + 4 +
mainDialog->m_unrelatedSpace.getHeight());
that->m_cancelButton.reset(
new ProgressDialog::CancelButtonImpl( that.get() ) );
that->m_cancelButton->SetHelpId( HID_PACKAGE_MANAGER_PROGRESS_CANCEL );
that->m_cancelButton->SetPosSizePixel(
(totalWidth - mainDialog->m_buttonSize.getWidth()) / 2,
posY,
mainDialog->m_buttonSize.getWidth(),
mainDialog->m_buttonSize.getHeight() );
posY += mainDialog->m_buttonSize.getHeight();
that->SetSizePixel(
Size( totalWidth,
posY + mainDialog->m_borderRightBottomSpace.getHeight() ) );
that->m_ftCurrentAction->Show();
that->m_statusBar->Show();
that->m_cancelButton->Show();
that->Show();
m_progressDialog = that;
}
pCond->set();
return 0;
}
//______________________________________________________________________________
void ProgressCommandEnv::showProgress( sal_Int32 progressSections )
{
m_progressSections = progressSections;
m_currentProgressSection = 0;
m_currentInnerProgress = 0;
if (m_progressDialog.get() == 0) {
::osl::Condition cond;
Application::PostUserEvent(
LINK( this, ProgressCommandEnv, executeDialog ), &cond );
cond.wait();
}
}
//______________________________________________________________________________
void ProgressCommandEnv::progressSection(
String const & text, Reference<task::XAbortChannel> const & xAbortChannel )
{
m_xAbortChannel = xAbortChannel;
if (! m_aborted)
{
++m_currentProgressSection;
m_currentInnerProgress = 0;
if (m_progressDialog.get() != 0) {
const ::vos::OGuard guard( Application::GetSolarMutex() );
if (m_progressDialog->m_statusBar->IsProgressMode())
m_progressDialog->m_statusBar->EndProgressMode();
m_progressDialog->m_statusBar->StartProgressMode( text );
m_progressDialog->m_ftCurrentAction->SetText( String() );
updateProgress();
}
}
}
//______________________________________________________________________________
void ProgressCommandEnv::updateProgress( OUString const & text )
{
if (m_progressDialog.get() != 0)
{
const ::vos::OGuard guard( Application::GetSolarMutex() );
if (text.getLength() > 0)
m_progressDialog->m_ftCurrentAction->SetText( text );
// xxx todo: how to do better?
m_progressDialog->m_statusBar->SetProgressValue(
static_cast<USHORT>(
(((m_currentProgressSection - 1) +
(m_currentInnerProgress >= 20
? 0.99 : (double)m_currentInnerProgress / 20.0)) * 100)
/ m_progressSections ) % 101 );
// static_cast<USHORT>(
// ((m_currentProgressSection +
// (1.0 - (m_currentInnerProgress == 0
// ? 1.0 : 1.0 / m_currentInnerProgress))) * 100)
// / m_progressSections ) % 101 );
}
}
// XCommandEnvironment
//______________________________________________________________________________
Reference<task::XInteractionHandler> ProgressCommandEnv::getInteractionHandler()
throw (RuntimeException)
{
return this;
}
//______________________________________________________________________________
Reference<XProgressHandler> ProgressCommandEnv::getProgressHandler()
throw (RuntimeException)
{
return this;
}
// XInteractionHandler
//______________________________________________________________________________
void ProgressCommandEnv::handle(
Reference<task::XInteractionRequest> const & xRequest )
throw (RuntimeException)
{
Any request( xRequest->getRequest() );
OSL_ASSERT( request.getValueTypeClass() == TypeClass_EXCEPTION );
#if OSL_DEBUG_LEVEL > 1
OSL_TRACE( "[dp_gui_cmdenv.cxx] incoming request:\n%s\n",
::rtl::OUStringToOString( ::comphelper::anyToString(request),
RTL_TEXTENCODING_UTF8 ).getStr() );
#endif
lang::WrappedTargetException wtExc;
deployment::DependencyException depExc;
deployment::LicenseException licExc;
deployment::LicenseIndividualAgreementException licAgreementExc;
deployment::VersionException verExc;
deployment::InstallException instExc;
// selections:
bool approve = false;
bool abort = false;
if (request >>= wtExc) {
// handable deployment error signalled, e.g.
// bundle item registration failed, notify cause only:
Any cause;
deployment::DeploymentException dpExc;
if (wtExc.TargetException >>= dpExc)
cause = dpExc.Cause;
else {
CommandFailedException cfExc;
if (wtExc.TargetException >>= cfExc)
cause = cfExc.Reason;
else
cause = wtExc.TargetException;
}
update_( cause );
// ignore intermediate errors of legacy packages, i.e.
// former pkgchk behaviour:
const Reference<deployment::XPackage> xPackage(
wtExc.Context, UNO_QUERY );
OSL_ASSERT( xPackage.is() );
if (xPackage.is()) {
const Reference<deployment::XPackageTypeInfo> xPackageType(
xPackage->getPackageType() );
OSL_ASSERT( xPackageType.is() );
if (xPackageType.is()) {
approve = (xPackage->isBundle() &&
xPackageType->getMediaType().matchAsciiL(
RTL_CONSTASCII_STRINGPARAM(
"application/"
"vnd.sun.star.legacy-package-bundle") ));
}
}
abort = !approve;
}
else if (request >>= depExc)
{
std::vector< rtl::OUString > deps;
for (sal_Int32 i = 0; i < depExc.UnsatisfiedDependencies.getLength();
++i)
{
deps.push_back(
dp_misc::Dependencies::name(depExc.UnsatisfiedDependencies[i]));
}
{
vos::OGuard guard(Application::GetSolarMutex());
short n = DependencyDialog(activeDialog(), deps).Execute();
// Distinguish between closing the dialog and programatically
// canceling the dialog (headless VCL):
approve = n == RET_OK
|| n == RET_CANCEL && !Application::IsDialogCancelEnabled();
}
}
else if (request >>= licAgreementExc)
{
vos::OGuard aSolarGuard( Application::GetSolarMutex() );
ResId warnId(WARNINGBOX_NOSHAREDALLOWED, DeploymentGuiResMgr::get());
WarningBox warn(activeDialog(), warnId);
String msgText = warn.GetMessText();
msgText.SearchAndReplaceAllAscii( "%PRODUCTNAME", BrandName::get() );
msgText.SearchAndReplaceAllAscii("%NAME", licExc.ExtensionName);
warn.SetMessText(msgText);
warn.Execute();
abort = true;
}
else if (request >>= licExc)
{
Reference<ui::dialogs::XExecutableDialog> xDialog(
css::deployment::ui::LicenseDialog::create(
m_xContext, VCLUnoHelper::GetInterface(activeDialog()), licExc.Text ) );
sal_Int16 res = xDialog->execute();
if (res == css::ui::dialogs::ExecutableDialogResults::CANCEL)
abort = true;
else if (res == css::ui::dialogs::ExecutableDialogResults::OK)
approve = true;
else
{
OSL_ASSERT(0);
}
}
else if (request >>= verExc)
{
sal_uInt32 id;
switch (dp_misc::comparePackageVersions(
verExc.New, verExc.Deployed))
{
case dp_misc::LESS:
id = RID_QUERYBOX_VERSION_LESS;
break;
case dp_misc::EQUAL:
id = RID_QUERYBOX_VERSION_EQUAL;
break;
default: // dp_misc::GREATER
id = RID_QUERYBOX_VERSION_GREATER;
break;
}
{
vos::OGuard guard(Application::GetSolarMutex());
InfoBox box(activeDialog(), ResId(id, DeploymentGuiResMgr::get()));
String s(box.GetMessText());
s.SearchAndReplaceAllAscii("$NAME", verExc.New->getName());
s.SearchAndReplaceAllAscii("$NEW", getVersion(verExc.New));
s.SearchAndReplaceAllAscii(
"$DEPLOYED", getVersion(verExc.Deployed));
box.SetMessText(s);
approve = box.Execute() == RET_OK;
abort = !approve;
}
}
else if (request >>= instExc)
{
//Only if the unopgk was started with gui + extension then we ask the user
if (!m_bAskWhenInstalling)
{
approve = true;
}
else
{
vos::OGuard guard(Application::GetSolarMutex());
InfoBox box(activeDialog(), ResId(RID_QUERYBOX_INSTALL_EXTENSION, DeploymentGuiResMgr::get()));
box.SetText(m_mainDialog->GetText());
String s(box.GetMessText());
s.SearchAndReplaceAllAscii("%NAME", instExc.New->getDisplayName());
box.SetMessText(s);
approve = box.Execute() == RET_OK;
abort = !approve;
}
}
if (approve == false && abort == false)
{
// forward to UUI handler:
if (! m_xHandler.is()) {
// late init:
Sequence<Any> handlerArgs( 1 );
handlerArgs[ 0 ] <<= beans::PropertyValue(
OUSTR("Context"), -1, Any(m_title),
beans::PropertyState_DIRECT_VALUE );
m_xHandler.set( m_xContext->getServiceManager()
->createInstanceWithArgumentsAndContext(
OUSTR("com.sun.star.uui.InteractionHandler"),
handlerArgs, m_xContext ), UNO_QUERY_THROW );
}
m_xHandler->handle( xRequest );
}
else
{
// select:
Sequence< Reference<task::XInteractionContinuation> > conts(
xRequest->getContinuations() );
Reference<task::XInteractionContinuation> const * pConts =
conts.getConstArray();
sal_Int32 len = conts.getLength();
for ( sal_Int32 pos = 0; pos < len; ++pos )
{
if (approve) {
Reference<task::XInteractionApprove> xInteractionApprove(
pConts[ pos ], UNO_QUERY );
if (xInteractionApprove.is()) {
xInteractionApprove->select();
// don't query again for ongoing continuations:
approve = false;
}
}
else if (abort) {
Reference<task::XInteractionAbort> xInteractionAbort(
pConts[ pos ], UNO_QUERY );
if (xInteractionAbort.is()) {
xInteractionAbort->select();
// don't query again for ongoing continuations:
abort = false;
}
}
}
}
}
// XProgressHandler
//______________________________________________________________________________
void ProgressCommandEnv::push( Any const & Status )
throw (RuntimeException)
{
update_( Status );
}
//______________________________________________________________________________
void ProgressCommandEnv::update_( Any const & Status )
throw (RuntimeException)
{
DialogImpl *mainDialog = dynamic_cast<dp_gui::DialogImpl*>(m_dialog);
if (mainDialog == NULL)
return;
OUString text;
if (Status.hasValue() && !(Status >>= text)) {
if (Status.getValueTypeClass() == TypeClass_EXCEPTION)
text = static_cast<Exception const *>(Status.getValue())->Message;
if (text.getLength() == 0)
text = ::comphelper::anyToString(Status); // fallback
mainDialog->errbox( text );
}
updateProgress( text );
++m_currentInnerProgress;
}
//______________________________________________________________________________
void ProgressCommandEnv::update( Any const & Status )
throw (RuntimeException)
{
update_( Status );
}
//______________________________________________________________________________
void ProgressCommandEnv::pop() throw (RuntimeException)
{
update_( Any() ); // no message
}
}