/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include "updatehdl.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include constexpr OUString COMMAND_CLOSE = u"close"_ustr; constexpr OUString CTRL_THROBBER = u"throbber"_ustr; constexpr OUString CTRL_PROGRESS = u"progress"_ustr; constexpr OUString TEXT_STATUS = u"text_status"_ustr; constexpr OUString TEXT_PERCENT = u"text_percent"_ustr; constexpr OUString TEXT_DESCRIPTION = u"text_description"_ustr; constexpr OUStringLiteral FIXED_LINE_MODEL = u"com.sun.star.awt.UnoControlFixedLineModel"; constexpr OUString FIXED_TEXT_MODEL = u"com.sun.star.awt.UnoControlFixedTextModel"_ustr; constexpr OUString EDIT_FIELD_MODEL = u"com.sun.star.awt.UnoControlEditModel"_ustr; constexpr OUString BUTTON_MODEL = u"com.sun.star.awt.UnoControlButtonModel"_ustr; constexpr OUString GROUP_BOX_MODEL = u"com.sun.star.awt.UnoControlGroupBoxModel"_ustr; using namespace com::sun::star; UpdateHandler::UpdateHandler( const uno::Reference< uno::XComponentContext > & rxContext, const rtl::Reference< IActionListener > & rxActionListener ) : mxContext( rxContext ), mxActionListener( rxActionListener ), meCurState( UPDATESTATES_COUNT ), meLastState( UPDATESTATES_COUNT ), mnPercent( 0 ), mnLastCtrlState( -1 ), mbDownloadBtnHasDots( false ), mbVisible( false ), mbStringsLoaded( false ), mbMinimized( false ), mbListenerAdded(false), mbShowsMessageBox(false) { } UpdateHandler::~UpdateHandler() { mxContext = nullptr; mxUpdDlg = nullptr; mxInteractionHdl = nullptr; mxActionListener = nullptr; } void UpdateHandler::enableControls( short nCtrlState ) { osl::MutexGuard aGuard( maMutex ); if ( nCtrlState == mnLastCtrlState ) return; // the help button should always be the last button in the // enum list and must never be disabled for ( int i=0; i(nCtrlState >> i); short nOldStateVal = static_cast(mnLastCtrlState >> i); if ( ( nCurStateVal & 0x01 ) != ( nOldStateVal & 0x01 ) ) { bool bEnableControl = ( ( nCurStateVal & 0x01 ) == 0x01 ); setControlProperty( msButtonIDs[i], "Enabled", uno::Any( bEnableControl ) ); } } mnLastCtrlState = nCtrlState; } void UpdateHandler::setDownloadBtnLabel( bool bAppendDots ) { osl::MutexGuard aGuard( maMutex ); if ( mbDownloadBtnHasDots != bAppendDots ) { OUString aLabel( msDownload ); if ( bAppendDots ) aLabel += "..."; setControlProperty( msButtonIDs[DOWNLOAD_BUTTON], "Label", uno::Any( aLabel ) ); setControlProperty( msButtonIDs[DOWNLOAD_BUTTON], "HelpURL", uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_DOWNLOAD2 )) ); mbDownloadBtnHasDots = bAppendDots; } } void UpdateHandler::setState( UpdateState eState ) { osl::MutexGuard aGuard( maMutex ); meCurState = eState; if ( mxUpdDlg.is() && mbVisible ) updateState( meCurState ); } bool UpdateHandler::isVisible() const { if ( !mxUpdDlg.is() ) return false; uno::Reference< awt::XWindow2 > xWindow( mxUpdDlg, uno::UNO_QUERY ); if ( xWindow.is() ) return xWindow->isVisible(); else return false; } void UpdateHandler::setVisible( bool bVisible ) { osl::MutexGuard aGuard( maMutex ); mbVisible = bVisible; if ( bVisible ) { if ( !mxUpdDlg.is() ) createDialog(); // this should never happen, but if it happens we better return here if ( !mxUpdDlg.is() ) return; updateState( meCurState ); uno::Reference< awt::XWindow > xWindow( mxUpdDlg, uno::UNO_QUERY ); if ( xWindow.is() ) xWindow->setVisible( bVisible ); uno::Reference< awt::XTopWindow > xTopWindow( mxUpdDlg, uno::UNO_QUERY ); if ( xTopWindow.is() ) { xTopWindow->toFront(); if ( !mbListenerAdded ) { xTopWindow->addTopWindowListener( this ); mbListenerAdded = true; } } } else if ( mxUpdDlg.is() ) { uno::Reference< awt::XWindow > xWindow( mxUpdDlg, uno::UNO_QUERY ); if ( xWindow.is() ) xWindow->setVisible( bVisible ); } } void UpdateHandler::setProgress( sal_Int32 nPercent ) { if ( nPercent > 100 ) nPercent = 100; else if ( nPercent < 0 ) nPercent = 0; if ( nPercent != mnPercent ) { osl::MutexGuard aGuard( maMutex ); mnPercent = nPercent; setControlProperty( CTRL_PROGRESS, "ProgressValue", uno::Any( nPercent ) ); setControlProperty( TEXT_PERCENT, "Text", uno::Any( substVariables(msPercent) ) ); } } void UpdateHandler::setErrorMessage( const OUString& rErrorMsg ) { setControlProperty( TEXT_DESCRIPTION, "Text", uno::Any( rErrorMsg ) ); } void UpdateHandler::setDownloadFile( std::u16string_view rFilePath ) { std::size_t nLast = rFilePath.rfind( '/' ); if ( nLast != std::u16string_view::npos ) { msDownloadFile = rFilePath.substr( nLast+1 ); const OUString aDownloadURL(rFilePath.substr( 0, nLast )); osl::FileBase::getSystemPathFromFileURL( aDownloadURL, msDownloadPath ); } } OUString UpdateHandler::getBubbleText( UpdateState eState ) { osl::MutexGuard aGuard( maMutex ); OUString sText; sal_Int32 nIndex = static_cast(eState); loadStrings(); if ( ( UPDATESTATE_UPDATE_AVAIL <= nIndex ) && ( nIndex < UPDATESTATES_COUNT ) ) sText = substVariables( msBubbleTexts[ nIndex - UPDATESTATE_UPDATE_AVAIL ] ); return sText; } OUString UpdateHandler::getBubbleTitle( UpdateState eState ) { osl::MutexGuard aGuard( maMutex ); OUString sText; sal_Int32 nIndex = static_cast(eState); loadStrings(); if ( ( UPDATESTATE_UPDATE_AVAIL <= nIndex ) && ( nIndex < UPDATESTATES_COUNT ) ) sText = substVariables( msBubbleTitles[ nIndex - UPDATESTATE_UPDATE_AVAIL] ); return sText; } // XActionListener void SAL_CALL UpdateHandler::disposing( const lang::EventObject& rEvt ) { if ( rEvt.Source == mxUpdDlg ) mxUpdDlg.clear(); } void SAL_CALL UpdateHandler::actionPerformed( awt::ActionEvent const & rEvent ) { DialogControls eButton = BUTTON_COUNT; for ( int i = 0; i < BUTTON_COUNT; i++ ) { if ( rEvent.ActionCommand == msButtonIDs[i] ) { eButton = static_cast(i); break; } } if ( rEvent.ActionCommand == COMMAND_CLOSE ) { if ( ( mnLastCtrlState & ( 1 << CLOSE_BUTTON ) ) == ( 1 << CLOSE_BUTTON ) ) eButton = CLOSE_BUTTON; else eButton = CANCEL_BUTTON; } switch ( eButton ) { case CANCEL_BUTTON: { bool bCancel = true; if ( ( meCurState == UPDATESTATE_DOWNLOADING ) || ( meCurState == UPDATESTATE_DOWNLOAD_PAUSED ) || ( meCurState == UPDATESTATE_ERROR_DOWNLOADING ) ) bCancel = showWarning( msCancelMessage ); if ( bCancel ) { mxActionListener->cancel(); setVisible( false ); } break; } case CLOSE_BUTTON: setVisible( false ); if ( meCurState == UPDATESTATE_ERROR_CHECKING ) mxActionListener->closeAfterFailure(); break; case DOWNLOAD_BUTTON: mxActionListener->download(); break; case PAUSE_BUTTON: mxActionListener->pause(); break; case RESUME_BUTTON: mxActionListener->resume(); break; case HELP_BUTTON: break; default: OSL_FAIL( "UpdateHandler::actionPerformed: unknown command!" ); } } // XTopWindowListener void SAL_CALL UpdateHandler::windowOpened( const lang::EventObject& ) { } void SAL_CALL UpdateHandler::windowClosing( const lang::EventObject& e ) { awt::ActionEvent aActionEvt; aActionEvt.ActionCommand = COMMAND_CLOSE; aActionEvt.Source = e.Source; actionPerformed( aActionEvt ); } void SAL_CALL UpdateHandler::windowClosed( const lang::EventObject& ) { } void SAL_CALL UpdateHandler::windowMinimized( const lang::EventObject& ) { mbMinimized = true; } void SAL_CALL UpdateHandler::windowNormalized( const lang::EventObject& ) { mbMinimized = false; } void SAL_CALL UpdateHandler::windowActivated( const lang::EventObject& ) { } void SAL_CALL UpdateHandler::windowDeactivated( const lang::EventObject& ) { } // XInteractionHandler void SAL_CALL UpdateHandler::handle( uno::Reference< task::XInteractionRequest > const & rRequest) { if ( !mxInteractionHdl.is() ) { if( !mxContext.is() ) throw uno::RuntimeException( "UpdateHandler:: empty component context", *this ); uno::Reference< lang::XMultiComponentFactory > xServiceManager(mxContext->getServiceManager()); if( !xServiceManager.is() ) throw uno::RuntimeException( "UpdateHandler: unable to obtain service manager from component context", *this ); mxInteractionHdl.set( task::InteractionHandler::createWithParent(mxContext, nullptr), uno::UNO_QUERY_THROW); } uno::Reference< task::XInteractionRequestStringResolver > xStrResolver = task::InteractionRequestStringResolver::create( mxContext ); beans::Optional< OUString > aErrorText = xStrResolver->getStringFromInformationalRequest( rRequest ); if ( aErrorText.IsPresent ) { setControlProperty( TEXT_DESCRIPTION, "Text", uno::Any( aErrorText.Value ) ); uno::Sequence< uno::Reference< task::XInteractionContinuation > > xContinuations = rRequest->getContinuations(); if ( xContinuations.getLength() == 1 ) { if ( meCurState == UPDATESTATE_CHECKING ) setState( UPDATESTATE_ERROR_CHECKING ); else if ( meCurState == UPDATESTATE_DOWNLOADING ) setState( UPDATESTATE_ERROR_DOWNLOADING ); xContinuations[0]->select(); } else mxInteractionHdl->handle( rRequest ); } else mxInteractionHdl->handle( rRequest ); } // XTerminateListener void SAL_CALL UpdateHandler::queryTermination( const lang::EventObject& ) { if ( mbShowsMessageBox ) { uno::Reference< awt::XTopWindow > xTopWindow( mxUpdDlg, uno::UNO_QUERY ); if ( xTopWindow.is() ) xTopWindow->toFront(); throw frame::TerminationVetoException( "The office cannot be closed while displaying a warning!", static_cast(this)); } else setVisible( false ); } void SAL_CALL UpdateHandler::notifyTermination( const lang::EventObject& ) { osl::MutexGuard aGuard( maMutex ); if ( mxUpdDlg.is() ) { uno::Reference< awt::XTopWindow > xTopWindow( mxUpdDlg, uno::UNO_QUERY ); if ( xTopWindow.is() ) xTopWindow->removeTopWindowListener( this ); uno::Reference< lang::XComponent > xComponent( mxUpdDlg, uno::UNO_QUERY ); if ( xComponent.is() ) xComponent->dispose(); mxUpdDlg.clear(); } } void UpdateHandler::updateState( UpdateState eState ) { if ( meLastState == eState ) return; OUString sText; switch ( eState ) { case UPDATESTATE_CHECKING: showControls( (1< RID_UPDATE_BUBBLE[] = { { RID_UPDATE_BUBBLE_UPDATE_AVAIL, RID_UPDATE_BUBBLE_T_UPDATE_AVAIL }, { RID_UPDATE_BUBBLE_UPDATE_NO_DOWN, RID_UPDATE_BUBBLE_T_UPDATE_NO_DOWN }, { RID_UPDATE_BUBBLE_AUTO_START, RID_UPDATE_BUBBLE_T_AUTO_START }, { RID_UPDATE_BUBBLE_DOWNLOADING, RID_UPDATE_BUBBLE_T_DOWNLOADING }, { RID_UPDATE_BUBBLE_DOWNLOAD_PAUSED, RID_UPDATE_BUBBLE_T_DOWNLOAD_PAUSED }, { RID_UPDATE_BUBBLE_ERROR_DOWNLOADING, RID_UPDATE_BUBBLE_T_ERROR_DOWNLOADING }, { RID_UPDATE_BUBBLE_DOWNLOAD_AVAIL, RID_UPDATE_BUBBLE_T_DOWNLOAD_AVAIL }, { RID_UPDATE_BUBBLE_EXT_UPD_AVAIL, RID_UPDATE_BUBBLE_T_EXT_UPD_AVAIL } }; static_assert(SAL_N_ELEMENTS(RID_UPDATE_BUBBLE) == UPDATESTATES_COUNT - UPDATESTATE_UPDATE_AVAIL, "mismatch"); // all update states before UPDATESTATE_UPDATE_AVAIL don't have a bubble // so we can ignore them for (size_t i = 0; i < SAL_N_ELEMENTS(RID_UPDATE_BUBBLE); ++i) { msBubbleTexts[i] = loadString(loc, RID_UPDATE_BUBBLE[i].first); msBubbleTitles[i] = loadString(loc, RID_UPDATE_BUBBLE[i].second); } for ( int i=0; i < BUTTON_COUNT; i++ ) { msButtonIDs[ i ] = "BUTTON_" + OUString::number( i ); } } void UpdateHandler::startThrobber( bool bStart ) { uno::Reference< awt::XControlContainer > xContainer( mxUpdDlg, uno::UNO_QUERY ); uno::Reference< awt::XAnimation > xThrobber( xContainer->getControl( CTRL_THROBBER ), uno::UNO_QUERY ); if ( xThrobber.is() ) { if ( bStart ) xThrobber->startAnimation(); else xThrobber->stopAnimation(); } uno::Reference< awt::XWindow > xWindow( xContainer->getControl( CTRL_THROBBER ), uno::UNO_QUERY ); if (xWindow.is() ) xWindow->setVisible( bStart ); } void UpdateHandler::setControlProperty( const OUString &rCtrlName, const OUString &rPropName, const uno::Any &rPropValue ) { if ( !mxUpdDlg.is() ) return; uno::Reference< awt::XControlContainer > xContainer( mxUpdDlg, uno::UNO_QUERY ); uno::Reference< awt::XControl > xControl( xContainer->getControl( rCtrlName ), uno::UNO_SET_THROW ); uno::Reference< awt::XControlModel > xControlModel( xControl->getModel(), uno::UNO_SET_THROW ); uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY_THROW ); try { xPropSet->setPropertyValue( rPropName, rPropValue ); } catch( const beans::UnknownPropertyException& ) { TOOLS_WARN_EXCEPTION( "extensions.update", "UpdateHandler::setControlProperty" ); } } void UpdateHandler::showControl( const OUString &rCtrlName, bool bShow ) { uno::Reference< awt::XControlContainer > xContainer( mxUpdDlg, uno::UNO_QUERY ); if ( !xContainer.is() ) { OSL_FAIL( "UpdateHandler::showControl: could not get control container!" ); return; } uno::Reference< awt::XWindow > xWindow( xContainer->getControl( rCtrlName ), uno::UNO_QUERY ); if ( xWindow.is() ) xWindow->setVisible( bShow ); } void UpdateHandler::focusControl( DialogControls eID ) { uno::Reference< awt::XControlContainer > xContainer( mxUpdDlg, uno::UNO_QUERY ); if ( !xContainer.is() ) { OSL_FAIL( "UpdateHandler::focusControl: could not get control container!" ); return; } OSL_ENSURE( (eID < BUTTON_COUNT), "UpdateHandler::focusControl: id too big!" ); uno::Reference< awt::XWindow > xWindow( xContainer->getControl( msButtonIDs[static_cast(eID)] ), uno::UNO_QUERY ); if ( xWindow.is() ) xWindow->setFocus(); } void UpdateHandler::insertControlModel( uno::Reference< awt::XControlModel > const & rxDialogModel, OUString const & rServiceName, OUString const & rControlName, awt::Rectangle const & rPosSize, uno::Sequence< beans::NamedValue > const & rProps ) { uno::Reference< lang::XMultiServiceFactory > xFactory (rxDialogModel, uno::UNO_QUERY_THROW); uno::Reference< awt::XControlModel > xModel (xFactory->createInstance (rServiceName), uno::UNO_QUERY_THROW); uno::Reference< beans::XPropertySet > xPropSet (xModel, uno::UNO_QUERY_THROW); for (beans::NamedValue const & prop : rProps) { xPropSet->setPropertyValue (prop.Name, prop.Value); } // @see awt/UnoControlDialogElement.idl xPropSet->setPropertyValue( "Name", uno::Any (rControlName) ); xPropSet->setPropertyValue( "PositionX", uno::Any (rPosSize.X) ); xPropSet->setPropertyValue( "PositionY", uno::Any (rPosSize.Y) ); xPropSet->setPropertyValue( "Height", uno::Any (rPosSize.Height) ); xPropSet->setPropertyValue( "Width", uno::Any (rPosSize.Width) ); // insert by Name into DialogModel container uno::Reference< container::XNameContainer > xContainer (rxDialogModel, uno::UNO_QUERY_THROW); xContainer->insertByName( rControlName, uno::Any (uno::Reference< uno::XInterface >(xModel, uno::UNO_QUERY))); } void UpdateHandler::setFullVersion( OUString& rString ) { uno::Reference< lang::XMultiServiceFactory > xConfigurationProvider( css::configuration::theDefaultProvider::get( mxContext ) ); beans::PropertyValue aProperty; aProperty.Name = "nodepath"; aProperty.Value <<= OUString("org.openoffice.Setup/Product"); uno::Sequence< uno::Any > aArgumentList{ uno::Any(aProperty) }; uno::Reference< uno::XInterface > xConfigAccess = xConfigurationProvider->createInstanceWithArguments( "com.sun.star.configuration.ConfigurationAccess", aArgumentList ); uno::Reference< container::XNameAccess > xNameAccess( xConfigAccess, uno::UNO_QUERY_THROW ); OUString aProductVersion; xNameAccess->getByName("ooSetupVersion") >>= aProductVersion; OUString aProductFullVersion; xNameAccess->getByName("ooSetupVersionAboutBox") >>= aProductFullVersion; rString = rString.replaceFirst( aProductVersion, aProductFullVersion ); } bool UpdateHandler::showWarning( const OUString &rWarningText ) const { bool bRet = false; uno::Reference< awt::XControl > xControl( mxUpdDlg, uno::UNO_QUERY ); if ( !xControl.is() ) return bRet; uno::Reference< awt::XWindowPeer > xPeer = xControl->getPeer(); if ( !xPeer.is() ) return bRet; uno::Reference< awt::XToolkit > xToolkit = xPeer->getToolkit(); if ( !xToolkit.is() ) return bRet; awt::WindowDescriptor aDescriptor; sal_Int32 nWindowAttributes = awt::WindowAttribute::BORDER | awt::WindowAttribute::MOVEABLE | awt::WindowAttribute::CLOSEABLE; nWindowAttributes |= awt::VclWindowPeerAttribute::YES_NO; nWindowAttributes |= awt::VclWindowPeerAttribute::DEF_NO; aDescriptor.Type = awt::WindowClass_MODALTOP; aDescriptor.WindowServiceName = "warningbox"; aDescriptor.ParentIndex = -1; aDescriptor.Parent = xPeer; aDescriptor.Bounds = awt::Rectangle( 10, 10, 250, 150 ); aDescriptor.WindowAttributes = nWindowAttributes; uno::Reference< awt::XMessageBox > xMsgBox( xToolkit->createWindow( aDescriptor ), uno::UNO_QUERY ); if ( xMsgBox.is() ) { mbShowsMessageBox = true; sal_Int16 nRet; // xMsgBox->setCaptionText( msCancelTitle ); xMsgBox->setMessageText( rWarningText ); nRet = xMsgBox->execute(); if ( nRet == 2 ) // RET_YES == 2 bRet = true; mbShowsMessageBox = false; } uno::Reference< lang::XComponent > xComponent( xMsgBox, uno::UNO_QUERY ); if ( xComponent.is() ) xComponent->dispose(); return bRet; } bool UpdateHandler::showWarning( const OUString &rWarningText, const OUString &rBtnText_1, const OUString &rBtnText_2 ) const { bool bRet = false; uno::Reference< awt::XControl > xControl( mxUpdDlg, uno::UNO_QUERY ); if ( !xControl.is() ) return bRet; uno::Reference< awt::XWindowPeer > xPeer = xControl->getPeer(); if ( !xPeer.is() ) return bRet; uno::Reference< awt::XToolkit > xToolkit = xPeer->getToolkit(); if ( !xToolkit.is() ) return bRet; awt::WindowDescriptor aDescriptor; sal_Int32 nWindowAttributes = awt::WindowAttribute::BORDER | awt::WindowAttribute::MOVEABLE | awt::WindowAttribute::CLOSEABLE; nWindowAttributes |= awt::VclWindowPeerAttribute::YES_NO; nWindowAttributes |= awt::VclWindowPeerAttribute::DEF_NO; aDescriptor.Type = awt::WindowClass_MODALTOP; aDescriptor.WindowServiceName = "warningbox"; aDescriptor.ParentIndex = -1; aDescriptor.Parent = xPeer; aDescriptor.Bounds = awt::Rectangle( 10, 10, 250, 150 ); aDescriptor.WindowAttributes = nWindowAttributes; uno::Reference< awt::XMessageBox > xMsgBox( xToolkit->createWindow( aDescriptor ), uno::UNO_QUERY ); if ( xMsgBox.is() ) { uno::Reference< awt::XVclContainer > xMsgBoxCtrls( xMsgBox, uno::UNO_QUERY ); if ( xMsgBoxCtrls.is() ) { uno::Sequence< uno::Reference< awt::XWindow > > xChildren = xMsgBoxCtrls->getWindows(); for ( uno::Reference< awt::XWindow > const & child : std::as_const(xChildren) ) { uno::Reference< awt::XVclWindowPeer > xMsgBoxCtrl( child, uno::UNO_QUERY ); if ( xMsgBoxCtrl.is() ) { bool bIsDefault = true; uno::Any aValue = xMsgBoxCtrl->getProperty( "DefaultButton" ); aValue >>= bIsDefault; if ( bIsDefault ) xMsgBoxCtrl->setProperty( "Text", uno::Any( rBtnText_1 ) ); else xMsgBoxCtrl->setProperty( "Text", uno::Any( rBtnText_2 ) ); } } } sal_Int16 nRet; // xMsgBox->setCaptionText( msCancelTitle ); mbShowsMessageBox = true; xMsgBox->setMessageText( rWarningText ); nRet = xMsgBox->execute(); if ( nRet == 2 ) // RET_YES == 2 bRet = true; mbShowsMessageBox = false; } uno::Reference< lang::XComponent > xComponent( xMsgBox, uno::UNO_QUERY ); if ( xComponent.is() ) xComponent->dispose(); return bRet; } bool UpdateHandler::showOverwriteWarning( std::u16string_view rFileName ) const { return showWarning( (msReloadWarning .replaceAll( "%FILENAME", rFileName ) .replaceAll( "%DOWNLOAD_PATH", msDownloadPath )), msReloadContinue, msReloadReload ); } bool UpdateHandler::showOverwriteWarning() const { return showWarning( msOverwriteWarning ); } #define BUTTON_HEIGHT 14 #define BUTTON_WIDTH 50 #define BUTTON_X_OFFSET 7 #define BUTTON_Y_OFFSET 3 #define LABEL_HEIGHT 10 #define DIALOG_WIDTH 300 #define DIALOG_BORDER 5 #define INNER_BORDER 3 #define TEXT_OFFSET 1 #define BOX_HEIGHT1 ( LABEL_HEIGHT + 3*BUTTON_HEIGHT + 2*BUTTON_Y_OFFSET + 2*INNER_BORDER ) #define BOX_HEIGHT2 50 #define EDIT_WIDTH ( DIALOG_WIDTH - 2 * DIALOG_BORDER ) #define BOX1_BTN_X ( DIALOG_BORDER + EDIT_WIDTH - BUTTON_WIDTH - INNER_BORDER ) #define BOX1_BTN_Y ( DIALOG_BORDER + LABEL_HEIGHT + INNER_BORDER) #define THROBBER_WIDTH 16 #define THROBBER_HEIGHT 16 #define THROBBER_X_POS ( DIALOG_BORDER + 8 ) #define THROBBER_Y_POS ( DIALOG_BORDER + 23 ) #define BUTTON_BAR_HEIGHT 24 #define LABEL_OFFSET ( LABEL_HEIGHT + 4 ) #define DIALOG_HEIGHT ( BOX_HEIGHT1 + BOX_HEIGHT2 + LABEL_OFFSET + BUTTON_BAR_HEIGHT + 3 * DIALOG_BORDER ) #define LABEL_Y_POS ( 2 * DIALOG_BORDER + BOX_HEIGHT1 ) #define EDIT2_Y_POS ( LABEL_Y_POS + LABEL_HEIGHT ) #define BUTTON_BAR_Y_POS ( EDIT2_Y_POS + DIALOG_BORDER + BOX_HEIGHT2 ) #define BUTTON_Y_POS ( BUTTON_BAR_Y_POS + 8 ) #define CLOSE_BTN_X ( DIALOG_WIDTH - DIALOG_BORDER - BUTTON_WIDTH ) #define INSTALL_BTN_X ( CLOSE_BTN_X - 2 * BUTTON_X_OFFSET - BUTTON_WIDTH ) #define DOWNLOAD_BTN_X ( INSTALL_BTN_X - BUTTON_X_OFFSET - BUTTON_WIDTH ) #define PROGRESS_WIDTH 80 #define PROGRESS_HEIGHT 10 #define PROGRESS_X_POS ( DIALOG_BORDER + 8 ) #define PROGRESS_Y_POS ( DIALOG_BORDER + 2*LABEL_OFFSET ) void UpdateHandler::showControls( short nControls ) { // The buttons from CANCEL_BUTTON to RESUME_BUTTON will be shown or // hidden on demand short nShiftMe; for ( int i = 0; i <= int(RESUME_BUTTON); i++ ) { nShiftMe = static_cast(nControls >> i); showControl( msButtonIDs[i], static_cast(nShiftMe & 0x01) ); } nShiftMe = static_cast(nControls >> THROBBER_CTRL); startThrobber( static_cast(nShiftMe & 0x01) ); nShiftMe = static_cast(nControls >> PROGRESS_CTRL); showControl( CTRL_PROGRESS, static_cast(nShiftMe & 0x01) ); showControl( TEXT_PERCENT, static_cast(nShiftMe & 0x01) ); // Status text needs to be smaller, when there are buttons at the right side of the dialog if ( ( nControls & ( (1< xDesktop = frame::Desktop::create( mxContext ); xDesktop->addTerminateListener( this ); } loadStrings(); uno::Reference< lang::XMultiComponentFactory > xFactory( mxContext->getServiceManager(), uno::UNO_SET_THROW ); uno::Reference< awt::XControlModel > xControlModel( xFactory->createInstanceWithContext( "com.sun.star.awt.UnoControlDialogModel", mxContext), uno::UNO_QUERY_THROW ); { // @see awt/UnoControlDialogModel.idl uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY_THROW ); xPropSet->setPropertyValue( "Title", uno::Any( msDlgTitle ) ); xPropSet->setPropertyValue( "Closeable", uno::Any( true ) ); xPropSet->setPropertyValue( "Enabled", uno::Any( true ) ); xPropSet->setPropertyValue( "Moveable", uno::Any( true ) ); xPropSet->setPropertyValue( "Sizeable", uno::Any( true ) ); xPropSet->setPropertyValue( "DesktopAsParent", uno::Any( true ) ); xPropSet->setPropertyValue( "PositionX", uno::Any(sal_Int32( 100 )) ); xPropSet->setPropertyValue( "PositionY", uno::Any(sal_Int32( 100 )) ); xPropSet->setPropertyValue( "Width", uno::Any(sal_Int32( DIALOG_WIDTH )) ); xPropSet->setPropertyValue( "Height", uno::Any(sal_Int32( DIALOG_HEIGHT )) ); xPropSet->setPropertyValue( "HelpURL", uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_DLG )) ); } { // Label (fixed text) uno::Sequence< beans::NamedValue > aProps { { "Label", uno::Any( msStatusFL ) } }; insertControlModel( xControlModel, FIXED_TEXT_MODEL, "fixedLineStatus", awt::Rectangle( DIALOG_BORDER+1, DIALOG_BORDER, EDIT_WIDTH-2, LABEL_HEIGHT ), aProps ); } { // box around text uno::Sequence< beans::NamedValue > aProps; insertControlModel( xControlModel, GROUP_BOX_MODEL, "StatusBox", awt::Rectangle( DIALOG_BORDER, DIALOG_BORDER + LABEL_HEIGHT, EDIT_WIDTH, BOX_HEIGHT1 - LABEL_HEIGHT ), aProps ); } { // Text (multiline edit) uno::Sequence< beans::NamedValue > aProps { { "Text", uno::Any( substVariables(msChecking) ) }, { "Border", uno::Any( sal_Int16( 0 ) ) }, { "PaintTransparent", uno::Any( true ) }, { "MultiLine", uno::Any( true ) }, { "ReadOnly", uno::Any( true ) }, { "AutoVScroll", uno::Any( true ) }, { "HelpURL", uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_STATUS )) } }; insertControlModel( xControlModel, EDIT_FIELD_MODEL, TEXT_STATUS, awt::Rectangle( DIALOG_BORDER + TEXT_OFFSET, DIALOG_BORDER + LABEL_HEIGHT + TEXT_OFFSET, EDIT_WIDTH - 2*TEXT_OFFSET, BOX_HEIGHT1 - 4*TEXT_OFFSET - LABEL_HEIGHT ), aProps ); } { // Text (edit) uno::Sequence< beans::NamedValue > aProps { { "Text", uno::Any( substVariables(msPercent) ) }, { "Border", uno::Any( sal_Int16( 0 ) ) }, { "PaintTransparent", uno::Any( true ) }, { "ReadOnly", uno::Any( true ) }, }; insertControlModel( xControlModel, EDIT_FIELD_MODEL, TEXT_PERCENT, awt::Rectangle( PROGRESS_X_POS + PROGRESS_WIDTH + DIALOG_BORDER, PROGRESS_Y_POS, EDIT_WIDTH - PROGRESS_WIDTH - BUTTON_WIDTH - 2*DIALOG_BORDER, LABEL_HEIGHT ), aProps ); } { // pause button uno::Sequence< beans::NamedValue > aProps { { "DefaultButton", uno::Any( false ) }, { "Enabled", uno::Any( true ) }, { "PushButtonType", uno::Any( sal_Int16(awt::PushButtonType_STANDARD) ) }, { "Label", uno::Any( msPauseBtn ) }, { "HelpURL", uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_PAUSE )) } }; insertControlModel ( xControlModel, BUTTON_MODEL, msButtonIDs[PAUSE_BUTTON], awt::Rectangle( BOX1_BTN_X, BOX1_BTN_Y, BUTTON_WIDTH, BUTTON_HEIGHT ), aProps ); } { // resume button uno::Sequence< beans::NamedValue > aProps { { "DefaultButton", uno::Any( false ) }, { "Enabled", uno::Any( true ) }, { "PushButtonType", uno::Any( sal_Int16(awt::PushButtonType_STANDARD) ) }, { "Label", uno::Any( msResumeBtn ) }, { "HelpURL", uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_RESUME )) } }; insertControlModel ( xControlModel, BUTTON_MODEL, msButtonIDs[RESUME_BUTTON], awt::Rectangle( BOX1_BTN_X, BOX1_BTN_Y + BUTTON_Y_OFFSET + BUTTON_HEIGHT, BUTTON_WIDTH, BUTTON_HEIGHT ), aProps ); } { // abort button uno::Sequence< beans::NamedValue > aProps { { "DefaultButton", uno::Any( false ) }, { "Enabled", uno::Any( true ) }, { "PushButtonType", uno::Any( sal_Int16(awt::PushButtonType_STANDARD) ) }, { "Label", uno::Any( msCancelBtn ) }, { "HelpURL", uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_CANCEL )) } }; insertControlModel ( xControlModel, BUTTON_MODEL, msButtonIDs[CANCEL_BUTTON], awt::Rectangle( BOX1_BTN_X, BOX1_BTN_Y + (2*(BUTTON_HEIGHT+BUTTON_Y_OFFSET)), BUTTON_WIDTH, BUTTON_HEIGHT ), aProps ); } { // Label (FixedText) uno::Sequence< beans::NamedValue > aProps { { "Label", uno::Any( msDescription ) } }; insertControlModel( xControlModel, FIXED_TEXT_MODEL, "fixedTextDescription", awt::Rectangle( DIALOG_BORDER+1, LABEL_Y_POS, EDIT_WIDTH-2, LABEL_HEIGHT ), aProps ); } { // box around text uno::Sequence< beans::NamedValue > aProps; insertControlModel( xControlModel, GROUP_BOX_MODEL, "DescriptionBox", awt::Rectangle( DIALOG_BORDER, EDIT2_Y_POS, EDIT_WIDTH, BOX_HEIGHT2 ), aProps ); } { // Text (MultiLineEdit) uno::Sequence< beans::NamedValue > aProps { { "Text", uno::Any( OUString() ) }, { "Border", uno::Any( sal_Int16( 0 ) ) }, { "PaintTransparent", uno::Any( true ) }, { "MultiLine", uno::Any( true ) }, { "ReadOnly", uno::Any( true ) }, { "AutoVScroll", uno::Any( true ) }, { "HelpURL", uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_DESCRIPTION )) } }; insertControlModel( xControlModel, EDIT_FIELD_MODEL, TEXT_DESCRIPTION, awt::Rectangle( DIALOG_BORDER + TEXT_OFFSET, EDIT2_Y_POS + 2*TEXT_OFFSET, EDIT_WIDTH - 3*TEXT_OFFSET, BOX_HEIGHT2 - 3*TEXT_OFFSET ), aProps ); } { // @see awt/UnoControlFixedLineModel.idl uno::Sequence< beans::NamedValue > aProps { { "Orientation", uno::Any( sal_Int32( 0 ) ) } }; insertControlModel( xControlModel, FIXED_LINE_MODEL, "fixedLine", awt::Rectangle( 0, BUTTON_BAR_Y_POS, DIALOG_WIDTH, 5 ), aProps ); } { // close button // @see awt/UnoControlButtonModel.idl uno::Sequence< beans::NamedValue > aProps { { "DefaultButton", uno::Any( false ) }, { "Enabled", uno::Any( true ) }, // [property] short PushButtonType // with own "ButtonActionListener" { "PushButtonType", uno::Any( sal_Int16(awt::PushButtonType_STANDARD) ) }, // with default ActionListener => endDialog(). // setProperty( aProps, 2, "PushButtonType", uno::Any( sal_Int16(awt::PushButtonType_CANCEL) ) ); // [property] string Label // only if PushButtonType_STANDARD { "Label", uno::Any( msClose ) }, { "HelpURL", uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_CLOSE )) } }; insertControlModel ( xControlModel, BUTTON_MODEL, msButtonIDs[ CLOSE_BUTTON ], awt::Rectangle( CLOSE_BTN_X, BUTTON_Y_POS, BUTTON_WIDTH, BUTTON_HEIGHT ), aProps ); } { // download button uno::Sequence< beans::NamedValue > aProps { { "DefaultButton", uno::Any( false ) }, { "Enabled", uno::Any( true ) }, { "PushButtonType", uno::Any( sal_Int16(awt::PushButtonType_STANDARD) ) }, { "Label", uno::Any( msDownload ) }, { "HelpURL", uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_DOWNLOAD )) } }; insertControlModel ( xControlModel, BUTTON_MODEL, msButtonIDs[DOWNLOAD_BUTTON], awt::Rectangle( DOWNLOAD_BTN_X, BUTTON_Y_POS, BUTTON_WIDTH, BUTTON_HEIGHT ), aProps ); } { // help button uno::Sequence< beans::NamedValue > aProps { { "DefaultButton", uno::Any( false ) }, { "Enabled", uno::Any( true ) }, { "PushButtonType", uno::Any( sal_Int16(awt::PushButtonType_HELP) ) } }; insertControlModel( xControlModel, BUTTON_MODEL, msButtonIDs[HELP_BUTTON], awt::Rectangle( DIALOG_BORDER, BUTTON_Y_POS, BUTTON_WIDTH, BUTTON_HEIGHT ), aProps ); } { // @see awt/UnoControlThrobberModel.idl uno::Sequence< beans::NamedValue > aProps; insertControlModel( xControlModel, "com.sun.star.awt.SpinningProgressControlModel", CTRL_THROBBER, awt::Rectangle( THROBBER_X_POS, THROBBER_Y_POS, THROBBER_WIDTH, THROBBER_HEIGHT), aProps ); } { // @see awt/UnoControlProgressBarModel.idl uno::Sequence< beans::NamedValue > aProps { { "Enabled", uno::Any( true ) }, { "ProgressValue", uno::Any( sal_Int32( 0 ) ) }, { "ProgressValueMax", uno::Any( sal_Int32( 100 ) ) }, { "ProgressValueMin", uno::Any( sal_Int32( 0 ) ) }, }; insertControlModel( xControlModel, "com.sun.star.awt.UnoControlProgressBarModel", CTRL_PROGRESS, awt::Rectangle( PROGRESS_X_POS, PROGRESS_Y_POS, PROGRESS_WIDTH, PROGRESS_HEIGHT ), aProps); } uno::Reference< awt::XUnoControlDialog > xControl = awt::UnoControlDialog::create( mxContext ); xControl->setModel( xControlModel ); if ( !mbVisible ) { xControl->setVisible( false ); } xControl->createPeer( nullptr, nullptr ); { for ( int i = 0; i < HELP_BUTTON; i++ ) { uno::Reference< awt::XButton > xButton ( xControl->getControl( msButtonIDs[i] ), uno::UNO_QUERY); if (xButton.is()) { xButton->setActionCommand( msButtonIDs[i] ); xButton->addActionListener( this ); } } } mxUpdDlg.set( xControl, uno::UNO_QUERY_THROW ); mnLastCtrlState = -1; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */