1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <cstddef>
23 
24 #include "updatehdl.hxx"
25 #include <helpids.h>
26 
27 #include <osl/diagnose.h>
28 #include <osl/file.hxx>
29 #include <rtl/ustring.hxx>
30 
31 #include <com/sun/star/uno/Sequence.h>
32 
33 #include <com/sun/star/awt/ActionEvent.hpp>
34 #include <com/sun/star/awt/PushButtonType.hpp>
35 #include <com/sun/star/awt/UnoControlDialog.hpp>
36 #include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
37 #include <com/sun/star/awt/WindowAttribute.hpp>
38 #include <com/sun/star/awt/XButton.hpp>
39 #include <com/sun/star/awt/XControl.hpp>
40 #include <com/sun/star/awt/XControlContainer.hpp>
41 #include <com/sun/star/awt/XMessageBox.hpp>
42 #include <com/sun/star/awt/XAnimation.hpp>
43 #include <com/sun/star/awt/XTopWindow.hpp>
44 #include <com/sun/star/awt/XVclWindowPeer.hpp>
45 #include <com/sun/star/awt/XVclContainer.hpp>
46 #include <com/sun/star/awt/XWindow.hpp>
47 #include <com/sun/star/awt/XWindow2.hpp>
48 
49 #include <com/sun/star/beans/PropertyValue.hpp>
50 #include <com/sun/star/beans/XPropertySet.hpp>
51 
52 #include <com/sun/star/configuration/theDefaultProvider.hpp>
53 
54 #include <com/sun/star/container/XNameContainer.hpp>
55 
56 #include <com/sun/star/frame/Desktop.hpp>
57 #include <com/sun/star/frame/TerminationVetoException.hpp>
58 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
59 #include <com/sun/star/task/InteractionHandler.hpp>
60 #include <com/sun/star/task/InteractionRequestStringResolver.hpp>
61 
62 #include <strings.hrc>
63 #include <unotools/resmgr.hxx>
64 #include <tools/urlobj.hxx>
65 #include <comphelper/diagnose_ex.hxx>
66 
67 constexpr OUString COMMAND_CLOSE = u"close"_ustr;
68 
69 constexpr OUString CTRL_THROBBER = u"throbber"_ustr;
70 constexpr OUString CTRL_PROGRESS = u"progress"_ustr;
71 
72 constexpr OUString TEXT_STATUS = u"text_status"_ustr;
73 constexpr OUString TEXT_PERCENT = u"text_percent"_ustr;
74 constexpr OUString TEXT_DESCRIPTION = u"text_description"_ustr;
75 
76 constexpr OUStringLiteral FIXED_LINE_MODEL = u"com.sun.star.awt.UnoControlFixedLineModel";
77 constexpr OUString FIXED_TEXT_MODEL = u"com.sun.star.awt.UnoControlFixedTextModel"_ustr;
78 constexpr OUString EDIT_FIELD_MODEL = u"com.sun.star.awt.UnoControlEditModel"_ustr;
79 constexpr OUString BUTTON_MODEL = u"com.sun.star.awt.UnoControlButtonModel"_ustr;
80 constexpr OUString GROUP_BOX_MODEL = u"com.sun.star.awt.UnoControlGroupBoxModel"_ustr;
81 
82 using namespace com::sun::star;
83 
84 
UpdateHandler(const uno::Reference<uno::XComponentContext> & rxContext,const rtl::Reference<IActionListener> & rxActionListener)85 UpdateHandler::UpdateHandler( const uno::Reference< uno::XComponentContext > & rxContext,
86                               const rtl::Reference< IActionListener > & rxActionListener ) :
87     mxContext( rxContext ),
88     mxActionListener( rxActionListener ),
89     meCurState( UPDATESTATES_COUNT ),
90     meLastState( UPDATESTATES_COUNT ),
91     mnPercent( 0 ),
92     mnLastCtrlState( -1 ),
93     mbDownloadBtnHasDots( false ),
94     mbVisible( false ),
95     mbStringsLoaded( false ),
96     mbMinimized( false ),
97     mbListenerAdded(false),
98     mbShowsMessageBox(false)
99 {
100 }
101 
102 
~UpdateHandler()103 UpdateHandler::~UpdateHandler()
104 {
105     mxContext = nullptr;
106     mxUpdDlg = nullptr;
107     mxInteractionHdl = nullptr;
108     mxActionListener = nullptr;
109 }
110 
111 
enableControls(short nCtrlState)112 void UpdateHandler::enableControls( short nCtrlState )
113 {
114     osl::MutexGuard aGuard( maMutex );
115 
116     if ( nCtrlState == mnLastCtrlState )
117         return;
118 
119     // the help button should always be the last button in the
120     // enum list and must never be disabled
121     for ( int i=0; i<HELP_BUTTON; i++ )
122     {
123         short nCurStateVal = static_cast<short>(nCtrlState >> i);
124         short nOldStateVal = static_cast<short>(mnLastCtrlState >> i);
125         if ( ( nCurStateVal & 0x01 ) != ( nOldStateVal & 0x01 ) )
126         {
127             bool bEnableControl = ( ( nCurStateVal & 0x01 ) == 0x01 );
128             setControlProperty( msButtonIDs[i], u"Enabled"_ustr, uno::Any( bEnableControl ) );
129         }
130     }
131 
132     mnLastCtrlState = nCtrlState;
133 }
134 
135 
setDownloadBtnLabel(bool bAppendDots)136 void UpdateHandler::setDownloadBtnLabel( bool bAppendDots )
137 {
138     osl::MutexGuard aGuard( maMutex );
139 
140     if ( mbDownloadBtnHasDots != bAppendDots )
141     {
142         OUString aLabel( msDownload );
143 
144         if ( bAppendDots )
145             aLabel += "...";
146 
147         setControlProperty( msButtonIDs[DOWNLOAD_BUTTON], u"Label"_ustr, uno::Any( aLabel ) );
148         setControlProperty( msButtonIDs[DOWNLOAD_BUTTON], u"HelpURL"_ustr, uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_DOWNLOAD2 )) );
149 
150         mbDownloadBtnHasDots = bAppendDots;
151     }
152 }
153 
154 
setState(UpdateState eState)155 void UpdateHandler::setState( UpdateState eState )
156 {
157     osl::MutexGuard aGuard( maMutex );
158 
159     meCurState = eState;
160 
161     if ( mxUpdDlg.is() && mbVisible )
162         updateState( meCurState );
163 }
164 
165 
isVisible() const166 bool UpdateHandler::isVisible() const
167 {
168     if ( !mxUpdDlg.is() ) return false;
169 
170     uno::Reference< awt::XWindow2 > xWindow( mxUpdDlg, uno::UNO_QUERY );
171 
172     if ( xWindow.is() )
173         return xWindow->isVisible();
174     else
175         return false;
176 }
177 
178 
setVisible(bool bVisible)179 void UpdateHandler::setVisible( bool bVisible )
180 {
181     osl::MutexGuard aGuard( maMutex );
182 
183     mbVisible = bVisible;
184 
185     if ( bVisible )
186     {
187         if ( !mxUpdDlg.is() )
188             createDialog();
189 
190         // this should never happen, but if it happens we better return here
191         if ( !mxUpdDlg.is() )
192             return;
193 
194         updateState( meCurState );
195 
196         uno::Reference< awt::XWindow > xWindow( mxUpdDlg, uno::UNO_QUERY );
197 
198         if ( xWindow.is() )
199             xWindow->setVisible( bVisible );
200 
201         uno::Reference< awt::XTopWindow > xTopWindow( mxUpdDlg, uno::UNO_QUERY );
202         if ( xTopWindow.is() )
203         {
204             xTopWindow->toFront();
205             if ( !mbListenerAdded )
206             {
207                 xTopWindow->addTopWindowListener( this );
208                 mbListenerAdded = true;
209             }
210         }
211     }
212     else if ( mxUpdDlg.is() )
213     {
214         uno::Reference< awt::XWindow > xWindow( mxUpdDlg, uno::UNO_QUERY );
215 
216         if ( xWindow.is() )
217             xWindow->setVisible( bVisible );
218     }
219 }
220 
221 
setProgress(sal_Int32 nPercent)222 void UpdateHandler::setProgress( sal_Int32 nPercent )
223 {
224     if ( nPercent > 100 )
225         nPercent = 100;
226     else if ( nPercent < 0 )
227         nPercent = 0;
228 
229     if ( nPercent != mnPercent )
230     {
231         osl::MutexGuard aGuard( maMutex );
232 
233         mnPercent = nPercent;
234         setControlProperty( CTRL_PROGRESS, u"ProgressValue"_ustr, uno::Any( nPercent ) );
235         setControlProperty( TEXT_PERCENT, u"Text"_ustr, uno::Any( substVariables(msPercent) ) );
236     }
237 }
238 
239 
setErrorMessage(const OUString & rErrorMsg)240 void UpdateHandler::setErrorMessage( const OUString& rErrorMsg )
241 {
242     setControlProperty( TEXT_DESCRIPTION, u"Text"_ustr, uno::Any( rErrorMsg ) );
243 }
244 
245 
setDownloadFile(std::u16string_view rFilePath)246 void UpdateHandler::setDownloadFile( std::u16string_view rFilePath )
247 {
248     std::size_t nLast = rFilePath.rfind( '/' );
249     if ( nLast != std::u16string_view::npos )
250     {
251         msDownloadFile = rFilePath.substr( nLast+1 );
252         const OUString aDownloadURL(rFilePath.substr( 0, nLast ));
253         osl::FileBase::getSystemPathFromFileURL( aDownloadURL, msDownloadPath );
254     }
255 }
256 
257 
getBubbleText(UpdateState eState)258 OUString UpdateHandler::getBubbleText( UpdateState eState )
259 {
260     osl::MutexGuard aGuard( maMutex );
261 
262     OUString sText;
263     sal_Int32 nIndex = static_cast<sal_Int32>(eState);
264 
265     loadStrings();
266 
267     if ( ( UPDATESTATE_UPDATE_AVAIL <= nIndex ) && ( nIndex < UPDATESTATES_COUNT ) )
268         sText = substVariables( msBubbleTexts[ nIndex - UPDATESTATE_UPDATE_AVAIL ] );
269 
270     return sText;
271 }
272 
273 
getBubbleTitle(UpdateState eState)274 OUString UpdateHandler::getBubbleTitle( UpdateState eState )
275 {
276     osl::MutexGuard aGuard( maMutex );
277 
278     OUString sText;
279     sal_Int32 nIndex = static_cast<sal_Int32>(eState);
280 
281     loadStrings();
282 
283     if ( ( UPDATESTATE_UPDATE_AVAIL <= nIndex ) && ( nIndex < UPDATESTATES_COUNT ) )
284         sText = substVariables( msBubbleTitles[ nIndex - UPDATESTATE_UPDATE_AVAIL] );
285 
286     return sText;
287 }
288 
289 
290 // XActionListener
291 
disposing(const lang::EventObject & rEvt)292 void SAL_CALL UpdateHandler::disposing( const lang::EventObject& rEvt )
293 {
294     if ( rEvt.Source == mxUpdDlg )
295         mxUpdDlg.clear();
296 }
297 
298 
actionPerformed(awt::ActionEvent const & rEvent)299 void SAL_CALL UpdateHandler::actionPerformed( awt::ActionEvent const & rEvent )
300 {
301     DialogControls eButton = BUTTON_COUNT;
302     for ( int i = 0; i < BUTTON_COUNT; i++ )
303     {
304         if ( rEvent.ActionCommand == msButtonIDs[i] )
305         {
306             eButton = static_cast<DialogControls>(i);
307             break;
308         }
309     }
310 
311     if ( rEvent.ActionCommand == COMMAND_CLOSE )
312     {
313         if ( ( mnLastCtrlState & ( 1 << CLOSE_BUTTON ) ) == ( 1 << CLOSE_BUTTON ) )
314             eButton = CLOSE_BUTTON;
315         else
316             eButton = CANCEL_BUTTON;
317     }
318 
319     switch ( eButton ) {
320         case CANCEL_BUTTON:
321         {
322             bool bCancel = true;
323 
324             if ( ( meCurState == UPDATESTATE_DOWNLOADING ) ||
325                  ( meCurState == UPDATESTATE_DOWNLOAD_PAUSED ) ||
326                  ( meCurState == UPDATESTATE_ERROR_DOWNLOADING ) )
327                 bCancel = showWarning( msCancelMessage );
328 
329             if ( bCancel )
330             {
331                 mxActionListener->cancel();
332                 setVisible( false );
333             }
334             break;
335         }
336         case CLOSE_BUTTON:
337             setVisible( false );
338             if ( meCurState == UPDATESTATE_ERROR_CHECKING )
339                 mxActionListener->closeAfterFailure();
340             break;
341         case DOWNLOAD_BUTTON:
342             mxActionListener->download();
343             break;
344         case PAUSE_BUTTON:
345             mxActionListener->pause();
346             break;
347         case RESUME_BUTTON:
348             mxActionListener->resume();
349             break;
350         case HELP_BUTTON:
351             break;
352         default:
353             OSL_FAIL( "UpdateHandler::actionPerformed: unknown command!" );
354     }
355 }
356 
357 // XTopWindowListener
358 
windowOpened(const lang::EventObject &)359 void SAL_CALL UpdateHandler::windowOpened( const lang::EventObject& )
360 {
361 }
362 
363 
windowClosing(const lang::EventObject & e)364 void SAL_CALL UpdateHandler::windowClosing( const lang::EventObject& e )
365 {
366     awt::ActionEvent aActionEvt;
367     aActionEvt.ActionCommand = COMMAND_CLOSE;
368     aActionEvt.Source = e.Source;
369 
370     actionPerformed( aActionEvt );
371 }
372 
373 
windowClosed(const lang::EventObject &)374 void SAL_CALL UpdateHandler::windowClosed( const lang::EventObject& )
375 {
376 }
377 
378 
windowMinimized(const lang::EventObject &)379 void SAL_CALL UpdateHandler::windowMinimized( const lang::EventObject& )
380 {
381     mbMinimized = true;
382 }
383 
384 
windowNormalized(const lang::EventObject &)385 void SAL_CALL UpdateHandler::windowNormalized( const lang::EventObject& )
386 {
387     mbMinimized = false;
388 }
389 
390 
windowActivated(const lang::EventObject &)391 void SAL_CALL UpdateHandler::windowActivated( const lang::EventObject& )
392 {
393 }
394 
395 
windowDeactivated(const lang::EventObject &)396 void SAL_CALL UpdateHandler::windowDeactivated( const lang::EventObject& )
397 {
398 }
399 
400 // XInteractionHandler
401 
handle(uno::Reference<task::XInteractionRequest> const & rRequest)402 void SAL_CALL UpdateHandler::handle( uno::Reference< task::XInteractionRequest > const & rRequest)
403 {
404     if ( !mxInteractionHdl.is() )
405     {
406         if( !mxContext.is() )
407             throw uno::RuntimeException( u"UpdateHandler:: empty component context"_ustr, *this );
408 
409         uno::Reference< lang::XMultiComponentFactory > xServiceManager(mxContext->getServiceManager());
410 
411         if( !xServiceManager.is() )
412             throw uno::RuntimeException( u"UpdateHandler: unable to obtain service manager from component context"_ustr, *this );
413 
414         mxInteractionHdl.set(
415             task::InteractionHandler::createWithParent(mxContext, nullptr),
416             uno::UNO_QUERY_THROW);
417     }
418     uno::Reference< task::XInteractionRequestStringResolver > xStrResolver =
419             task::InteractionRequestStringResolver::create( mxContext );
420     beans::Optional< OUString > aErrorText = xStrResolver->getStringFromInformationalRequest( rRequest );
421     if ( aErrorText.IsPresent )
422     {
423         setControlProperty( TEXT_DESCRIPTION, u"Text"_ustr, uno::Any( aErrorText.Value ) );
424 
425         uno::Sequence< uno::Reference< task::XInteractionContinuation > > xContinuations = rRequest->getContinuations();
426         if ( xContinuations.getLength() == 1 )
427         {
428             if ( meCurState == UPDATESTATE_CHECKING )
429                 setState( UPDATESTATE_ERROR_CHECKING );
430             else if ( meCurState == UPDATESTATE_DOWNLOADING )
431                 setState( UPDATESTATE_ERROR_DOWNLOADING );
432 
433             xContinuations[0]->select();
434         }
435         else
436             mxInteractionHdl->handle( rRequest );
437     }
438     else
439         mxInteractionHdl->handle( rRequest );
440 }
441 
442 
443 // XTerminateListener
444 
queryTermination(const lang::EventObject &)445 void SAL_CALL UpdateHandler::queryTermination( const lang::EventObject& )
446 {
447     if ( mbShowsMessageBox )
448     {
449         uno::Reference< awt::XTopWindow > xTopWindow( mxUpdDlg, uno::UNO_QUERY );
450         if ( xTopWindow.is() )
451             xTopWindow->toFront();
452 
453         throw frame::TerminationVetoException(
454             u"The office cannot be closed while displaying a warning!"_ustr,
455             static_cast<frame::XTerminateListener*>(this));
456     }
457     else
458         setVisible( false );
459 }
460 
461 
notifyTermination(const lang::EventObject &)462 void SAL_CALL UpdateHandler::notifyTermination( const lang::EventObject& )
463 {
464     osl::MutexGuard aGuard( maMutex );
465 
466     if ( mxUpdDlg.is() )
467     {
468         uno::Reference< awt::XTopWindow > xTopWindow( mxUpdDlg, uno::UNO_QUERY );
469         if ( xTopWindow.is() )
470             xTopWindow->removeTopWindowListener( this );
471 
472         uno::Reference< lang::XComponent > xComponent( mxUpdDlg, uno::UNO_QUERY );
473         if ( xComponent.is() )
474             xComponent->dispose();
475 
476         mxUpdDlg.clear();
477     }
478 }
479 
480 
updateState(UpdateState eState)481 void UpdateHandler::updateState( UpdateState eState )
482 {
483     if ( meLastState == eState )
484         return;
485 
486     OUString sText;
487 
488     switch ( eState )
489     {
490         case UPDATESTATE_CHECKING:
491             showControls( (1<<CANCEL_BUTTON) + (1<<THROBBER_CTRL) );
492             enableControls( 1<<CANCEL_BUTTON );
493             setControlProperty( TEXT_STATUS, u"Text"_ustr, uno::Any( substVariables(msChecking) ) );
494             setControlProperty( TEXT_DESCRIPTION, u"Text"_ustr, uno::Any( OUString() ) );
495             focusControl( CANCEL_BUTTON );
496             break;
497         case UPDATESTATE_ERROR_CHECKING:
498             showControls( 0 );
499             enableControls( 1 << CLOSE_BUTTON );
500             setControlProperty( TEXT_STATUS, u"Text"_ustr, uno::Any( substVariables(msCheckingError) ) );
501             focusControl( CLOSE_BUTTON );
502             break;
503         case UPDATESTATE_UPDATE_AVAIL:
504             showControls( 0 );
505             enableControls( ( 1 << CLOSE_BUTTON )  + ( 1 << DOWNLOAD_BUTTON ) );
506             setControlProperty( TEXT_STATUS, u"Text"_ustr, uno::Any( substVariables(msUpdFound) ) );
507 
508             sText = substVariables(msDownloadWarning);
509             if ( !msDescriptionMsg.isEmpty() )
510                 sText += "\n\n" + msDescriptionMsg;
511             setControlProperty( TEXT_DESCRIPTION, u"Text"_ustr, uno::Any( sText ) );
512 
513             setDownloadBtnLabel( false );
514             focusControl( DOWNLOAD_BUTTON );
515             break;
516         case UPDATESTATE_UPDATE_NO_DOWNLOAD:
517             showControls( 0 );
518             enableControls( ( 1 << CLOSE_BUTTON )  + ( 1 << DOWNLOAD_BUTTON ) );
519             setControlProperty( TEXT_STATUS, u"Text"_ustr, uno::Any( substVariables(msUpdFound) ) );
520 
521             sText = substVariables(msDownloadNotAvail);
522             if ( !msDescriptionMsg.isEmpty() )
523                 sText += "\n\n" + msDescriptionMsg;
524             setControlProperty( TEXT_DESCRIPTION, u"Text"_ustr, uno::Any( sText ) );
525 
526             setDownloadBtnLabel( true );
527             focusControl( DOWNLOAD_BUTTON );
528             break;
529         case UPDATESTATE_NO_UPDATE_AVAIL:
530         case UPDATESTATE_EXT_UPD_AVAIL:     // will only be set, when there are no office updates avail
531             showControls( 0 );
532             enableControls( 1 << CLOSE_BUTTON );
533             setControlProperty( TEXT_STATUS, u"Text"_ustr, uno::Any( substVariables(msNoUpdFound) ) );
534             setControlProperty( TEXT_DESCRIPTION, u"Text"_ustr, uno::Any( OUString() ) );
535             focusControl( CLOSE_BUTTON );
536             break;
537         case UPDATESTATE_DOWNLOADING:
538             showControls( (1<<PROGRESS_CTRL) + (1<<CANCEL_BUTTON) + (1<<PAUSE_BUTTON) + (1<<RESUME_BUTTON) );
539             enableControls( (1<<CLOSE_BUTTON) + (1<<CANCEL_BUTTON) + (1<<PAUSE_BUTTON) );
540             setControlProperty( TEXT_STATUS, u"Text"_ustr, uno::Any( substVariables(msDownloading) ) );
541             setControlProperty( TEXT_PERCENT, u"Text"_ustr, uno::Any( substVariables(msPercent) ) );
542             setControlProperty( TEXT_DESCRIPTION, u"Text"_ustr, uno::Any( substVariables(msDownloadWarning) ) );
543             setControlProperty( CTRL_PROGRESS, u"ProgressValue"_ustr, uno::Any( mnPercent ) );
544             focusControl( CLOSE_BUTTON );
545             break;
546         case UPDATESTATE_DOWNLOAD_PAUSED:
547             showControls( (1<<PROGRESS_CTRL) + (1<<CANCEL_BUTTON) + (1<<PAUSE_BUTTON) + (1<<RESUME_BUTTON) );
548             enableControls( (1<<CLOSE_BUTTON) + (1<<CANCEL_BUTTON) + (1<<RESUME_BUTTON) );
549             setControlProperty( TEXT_STATUS, u"Text"_ustr, uno::Any( substVariables(msDownloadPause) ) );
550             setControlProperty( TEXT_PERCENT, u"Text"_ustr, uno::Any( substVariables(msPercent) ) );
551             setControlProperty( TEXT_DESCRIPTION, u"Text"_ustr, uno::Any( substVariables(msDownloadWarning) ) );
552             setControlProperty( CTRL_PROGRESS, u"ProgressValue"_ustr, uno::Any( mnPercent ) );
553             focusControl( CLOSE_BUTTON );
554             break;
555         case UPDATESTATE_ERROR_DOWNLOADING:
556             showControls( (1<<PROGRESS_CTRL) + (1<<CANCEL_BUTTON) + (1<<PAUSE_BUTTON) + (1<<RESUME_BUTTON) );
557             enableControls( (1<<CLOSE_BUTTON) + (1<<CANCEL_BUTTON) );
558             setControlProperty( TEXT_STATUS, u"Text"_ustr, uno::Any( substVariables(msDownloadError) ) );
559             focusControl( CLOSE_BUTTON );
560             break;
561         case UPDATESTATE_DOWNLOAD_AVAIL:
562             showControls( 0 );
563             setControlProperty( TEXT_STATUS, u"Text"_ustr, uno::Any( substVariables(msReady2Install) ) );
564             setControlProperty( TEXT_DESCRIPTION, u"Text"_ustr, uno::Any( substVariables(msDownloadDescr) ) );
565             break;
566         case UPDATESTATE_AUTO_START:
567         case UPDATESTATES_COUNT:
568             //do nothing, only count!
569             break;
570     }
571 
572     meLastState = eState;
573 }
574 
loadString(const std::locale & rLocale,TranslateId pResourceId)575 OUString UpdateHandler::loadString(const std::locale& rLocale,
576                                    TranslateId pResourceId)
577 {
578     return Translate::get(pResourceId, rLocale);
579 }
580 
substVariables(const OUString & rSource) const581 OUString UpdateHandler::substVariables( const OUString &rSource ) const
582 {
583     return rSource
584         .replaceAll( "%NEXTVERSION", msNextVersion )
585         .replaceAll( "%DOWNLOAD_PATH", msDownloadPath )
586         .replaceAll( "%FILE_NAME", msDownloadFile )
587         .replaceAll( "%PERCENT", OUString::number( mnPercent ) );
588 }
589 
loadStrings()590 void UpdateHandler::loadStrings()
591 {
592     if ( mbStringsLoaded )
593         return;
594     else
595         mbStringsLoaded = true;
596 
597     std::locale loc = Translate::Create("pcr");
598 
599     msChecking      = loadString( loc, RID_UPDATE_STR_CHECKING );
600     msCheckingError = loadString( loc, RID_UPDATE_STR_CHECKING_ERR );
601     msNoUpdFound    = loadString( loc, RID_UPDATE_STR_NO_UPD_FOUND );
602 
603     msUpdFound      = loadString( loc, RID_UPDATE_STR_UPD_FOUND );
604     setFullVersion( msUpdFound );
605 
606     msDlgTitle      = loadString( loc, RID_UPDATE_STR_DLG_TITLE );
607     msDownloadPause = loadString( loc, RID_UPDATE_STR_DOWNLOAD_PAUSE );
608     msDownloadError = loadString( loc, RID_UPDATE_STR_DOWNLOAD_ERR );
609     msDownloadWarning = loadString( loc, RID_UPDATE_STR_DOWNLOAD_WARN );
610     msDownloadDescr =  loadString( loc, RID_UPDATE_STR_DOWNLOAD_DESCR );
611     msDownloadNotAvail = loadString( loc, RID_UPDATE_STR_DOWNLOAD_UNAVAIL );
612     msDownloading   = loadString( loc, RID_UPDATE_STR_DOWNLOADING );
613     msReady2Install = loadString( loc, RID_UPDATE_STR_READY_INSTALL );
614     msCancelMessage = loadString( loc, RID_UPDATE_STR_CANCEL_DOWNLOAD );
615     msOverwriteWarning = loadString( loc, RID_UPDATE_STR_OVERWRITE_WARNING );
616     msPercent       = loadString( loc, RID_UPDATE_STR_PERCENT );
617     msReloadWarning = loadString( loc, RID_UPDATE_STR_RELOAD_WARNING );
618     msReloadReload  = loadString( loc, RID_UPDATE_STR_RELOAD_RELOAD );
619     msReloadContinue = loadString( loc, RID_UPDATE_STR_RELOAD_CONTINUE );
620 
621     msStatusFL      = loadString( loc, RID_UPDATE_FT_STATUS );
622     msDescription   = loadString( loc, RID_UPDATE_FT_DESCRIPTION );
623 
624     msClose         = loadString( loc, RID_UPDATE_BTN_CLOSE );
625     msDownload      = loadString( loc, RID_UPDATE_BTN_DOWNLOAD );
626     msPauseBtn      = loadString( loc, RID_UPDATE_BTN_PAUSE );
627     msResumeBtn     = loadString( loc, RID_UPDATE_BTN_RESUME );
628     msCancelBtn     = loadString( loc, RID_UPDATE_BTN_CANCEL );
629 
630     std::pair<TranslateId, TranslateId> RID_UPDATE_BUBBLE[] =
631     {
632         { RID_UPDATE_BUBBLE_UPDATE_AVAIL, RID_UPDATE_BUBBLE_T_UPDATE_AVAIL },
633         { RID_UPDATE_BUBBLE_UPDATE_NO_DOWN, RID_UPDATE_BUBBLE_T_UPDATE_NO_DOWN },
634         { RID_UPDATE_BUBBLE_AUTO_START, RID_UPDATE_BUBBLE_T_AUTO_START },
635         { RID_UPDATE_BUBBLE_DOWNLOADING, RID_UPDATE_BUBBLE_T_DOWNLOADING },
636         { RID_UPDATE_BUBBLE_DOWNLOAD_PAUSED, RID_UPDATE_BUBBLE_T_DOWNLOAD_PAUSED },
637         { RID_UPDATE_BUBBLE_ERROR_DOWNLOADING, RID_UPDATE_BUBBLE_T_ERROR_DOWNLOADING },
638         { RID_UPDATE_BUBBLE_DOWNLOAD_AVAIL, RID_UPDATE_BUBBLE_T_DOWNLOAD_AVAIL },
639         { RID_UPDATE_BUBBLE_EXT_UPD_AVAIL, RID_UPDATE_BUBBLE_T_EXT_UPD_AVAIL }
640     };
641 
642     static_assert(SAL_N_ELEMENTS(RID_UPDATE_BUBBLE) == UPDATESTATES_COUNT - UPDATESTATE_UPDATE_AVAIL, "mismatch");
643 
644     // all update states before UPDATESTATE_UPDATE_AVAIL don't have a bubble
645     // so we can ignore them
646     for (size_t i = 0; i < SAL_N_ELEMENTS(RID_UPDATE_BUBBLE); ++i)
647     {
648         msBubbleTexts[i] = loadString(loc, RID_UPDATE_BUBBLE[i].first);
649         msBubbleTitles[i] = loadString(loc, RID_UPDATE_BUBBLE[i].second);
650     }
651 
652     for ( int i=0; i < BUTTON_COUNT; i++ )
653     {
654         msButtonIDs[ i ] = "BUTTON_" + OUString::number( i );
655     }
656 }
657 
658 
startThrobber(bool bStart)659 void UpdateHandler::startThrobber( bool bStart )
660 {
661     uno::Reference< awt::XControlContainer > xContainer( mxUpdDlg, uno::UNO_QUERY );
662     uno::Reference< awt::XAnimation > xThrobber( xContainer->getControl( CTRL_THROBBER ), uno::UNO_QUERY );
663 
664     if ( xThrobber.is() )
665     {
666         if ( bStart )
667             xThrobber->startAnimation();
668         else
669             xThrobber->stopAnimation();
670     }
671 
672     uno::Reference< awt::XWindow > xWindow( xContainer->getControl( CTRL_THROBBER ), uno::UNO_QUERY );
673     if (xWindow.is() )
674         xWindow->setVisible( bStart );
675 }
676 
677 
setControlProperty(const OUString & rCtrlName,const OUString & rPropName,const uno::Any & rPropValue)678 void UpdateHandler::setControlProperty( const OUString &rCtrlName,
679                                         const OUString &rPropName,
680                                         const uno::Any &rPropValue )
681 {
682     if ( !mxUpdDlg.is() ) return;
683 
684     uno::Reference< awt::XControlContainer > xContainer( mxUpdDlg, uno::UNO_QUERY );
685     uno::Reference< awt::XControl > xControl( xContainer->getControl( rCtrlName ), uno::UNO_SET_THROW );
686     uno::Reference< awt::XControlModel > xControlModel( xControl->getModel(), uno::UNO_SET_THROW );
687     uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY_THROW );
688 
689     try {
690         xPropSet->setPropertyValue( rPropName, rPropValue );
691     }
692     catch( const beans::UnknownPropertyException& )
693     {
694         TOOLS_WARN_EXCEPTION( "extensions.update", "UpdateHandler::setControlProperty" );
695     }
696 }
697 
698 
showControl(const OUString & rCtrlName,bool bShow)699 void UpdateHandler::showControl( const OUString &rCtrlName, bool bShow )
700 {
701     uno::Reference< awt::XControlContainer > xContainer( mxUpdDlg, uno::UNO_QUERY );
702 
703     if ( !xContainer.is() )
704     {
705         OSL_FAIL( "UpdateHandler::showControl: could not get control container!" );
706         return;
707     }
708 
709     uno::Reference< awt::XWindow > xWindow( xContainer->getControl( rCtrlName ), uno::UNO_QUERY );
710     if ( xWindow.is() )
711         xWindow->setVisible( bShow );
712 }
713 
714 
focusControl(DialogControls eID)715 void UpdateHandler::focusControl( DialogControls eID )
716 {
717     uno::Reference< awt::XControlContainer > xContainer( mxUpdDlg, uno::UNO_QUERY );
718 
719     if ( !xContainer.is() )
720     {
721         OSL_FAIL( "UpdateHandler::focusControl: could not get control container!" );
722         return;
723     }
724 
725     OSL_ENSURE( (eID < BUTTON_COUNT), "UpdateHandler::focusControl: id too big!" );
726 
727     uno::Reference< awt::XWindow > xWindow( xContainer->getControl( msButtonIDs[static_cast<short>(eID)] ), uno::UNO_QUERY );
728     if ( xWindow.is() )
729         xWindow->setFocus();
730 }
731 
732 
insertControlModel(uno::Reference<awt::XControlModel> const & rxDialogModel,OUString const & rServiceName,OUString const & rControlName,awt::Rectangle const & rPosSize,uno::Sequence<beans::NamedValue> const & rProps)733 void UpdateHandler::insertControlModel( uno::Reference< awt::XControlModel > const & rxDialogModel,
734                                         OUString const & rServiceName,
735                                         OUString const & rControlName,
736                                         awt::Rectangle const & rPosSize,
737                                         uno::Sequence< beans::NamedValue > const & rProps )
738 {
739     uno::Reference< lang::XMultiServiceFactory > xFactory (rxDialogModel, uno::UNO_QUERY_THROW);
740     uno::Reference< awt::XControlModel > xModel (xFactory->createInstance (rServiceName), uno::UNO_QUERY_THROW);
741     uno::Reference< beans::XPropertySet > xPropSet (xModel, uno::UNO_QUERY_THROW);
742 
743     for (beans::NamedValue const & prop : rProps)
744     {
745         xPropSet->setPropertyValue (prop.Name, prop.Value);
746     }
747 
748     // @see awt/UnoControlDialogElement.idl
749     xPropSet->setPropertyValue( u"Name"_ustr, uno::Any (rControlName) );
750     xPropSet->setPropertyValue( u"PositionX"_ustr, uno::Any (rPosSize.X) );
751     xPropSet->setPropertyValue( u"PositionY"_ustr, uno::Any (rPosSize.Y) );
752     xPropSet->setPropertyValue( u"Height"_ustr, uno::Any (rPosSize.Height) );
753     xPropSet->setPropertyValue( u"Width"_ustr, uno::Any (rPosSize.Width) );
754 
755     // insert by Name into DialogModel container
756     uno::Reference< container::XNameContainer > xContainer (rxDialogModel, uno::UNO_QUERY_THROW);
757     xContainer->insertByName( rControlName, uno::Any (uno::Reference< uno::XInterface >(xModel, uno::UNO_QUERY)));
758 }
759 
760 
setFullVersion(OUString & rString)761 void UpdateHandler::setFullVersion( OUString& rString )
762 {
763     uno::Reference< lang::XMultiServiceFactory > xConfigurationProvider(
764         css::configuration::theDefaultProvider::get( mxContext ) );
765 
766     beans::PropertyValue aProperty;
767     aProperty.Name  = "nodepath";
768     aProperty.Value <<= u"org.openoffice.Setup/Product"_ustr;
769 
770     uno::Sequence< uno::Any > aArgumentList{ uno::Any(aProperty) };
771 
772     uno::Reference< uno::XInterface > xConfigAccess = xConfigurationProvider->createInstanceWithArguments( u"com.sun.star.configuration.ConfigurationAccess"_ustr,
773                                                                          aArgumentList );
774 
775     uno::Reference< container::XNameAccess > xNameAccess( xConfigAccess, uno::UNO_QUERY_THROW );
776 
777     OUString aProductVersion;
778     xNameAccess->getByName(u"ooSetupVersion"_ustr) >>= aProductVersion;
779     OUString aProductFullVersion;
780     xNameAccess->getByName(u"ooSetupVersionAboutBox"_ustr) >>= aProductFullVersion;
781     rString = rString.replaceFirst( aProductVersion, aProductFullVersion );
782 }
783 
784 
showWarning(const OUString & rWarningText) const785 bool UpdateHandler::showWarning( const OUString &rWarningText ) const
786 {
787     bool bRet = false;
788 
789     uno::Reference< awt::XControl > xControl( mxUpdDlg, uno::UNO_QUERY );
790     if ( !xControl.is() ) return bRet;
791 
792     uno::Reference< awt::XWindowPeer > xPeer = xControl->getPeer();
793     if ( !xPeer.is() ) return bRet;
794 
795     uno::Reference< awt::XToolkit > xToolkit = xPeer->getToolkit();
796     if ( !xToolkit.is() ) return bRet;
797 
798     awt::WindowDescriptor aDescriptor;
799 
800     sal_Int32 nWindowAttributes = awt::WindowAttribute::BORDER | awt::WindowAttribute::MOVEABLE | awt::WindowAttribute::CLOSEABLE;
801     nWindowAttributes |= awt::VclWindowPeerAttribute::YES_NO;
802     nWindowAttributes |= awt::VclWindowPeerAttribute::DEF_NO;
803 
804     aDescriptor.Type              = awt::WindowClass_MODALTOP;
805     aDescriptor.WindowServiceName = "warningbox";
806     aDescriptor.ParentIndex       = -1;
807     aDescriptor.Parent            = xPeer;
808     aDescriptor.Bounds            = awt::Rectangle( 10, 10, 250, 150 );
809     aDescriptor.WindowAttributes  = nWindowAttributes;
810 
811     uno::Reference< awt::XMessageBox > xMsgBox( xToolkit->createWindow( aDescriptor ), uno::UNO_QUERY );
812     if ( xMsgBox.is() )
813     {
814         mbShowsMessageBox = true;
815         sal_Int16 nRet;
816         // xMsgBox->setCaptionText( msCancelTitle );
817         xMsgBox->setMessageText( rWarningText );
818         nRet = xMsgBox->execute();
819         if ( nRet == 2 ) // RET_YES == 2
820             bRet = true;
821         mbShowsMessageBox = false;
822     }
823 
824     uno::Reference< lang::XComponent > xComponent( xMsgBox, uno::UNO_QUERY );
825     if ( xComponent.is() )
826         xComponent->dispose();
827 
828     return bRet;
829 }
830 
831 
showWarning(const OUString & rWarningText,const OUString & rBtnText_1,const OUString & rBtnText_2) const832 bool UpdateHandler::showWarning( const OUString &rWarningText,
833                                  const OUString &rBtnText_1,
834                                  const OUString &rBtnText_2 ) const
835 {
836     bool bRet = false;
837 
838     uno::Reference< awt::XControl > xControl( mxUpdDlg, uno::UNO_QUERY );
839     if ( !xControl.is() ) return bRet;
840 
841     uno::Reference< awt::XWindowPeer > xPeer = xControl->getPeer();
842     if ( !xPeer.is() ) return bRet;
843 
844     uno::Reference< awt::XToolkit > xToolkit = xPeer->getToolkit();
845     if ( !xToolkit.is() ) return bRet;
846 
847     awt::WindowDescriptor aDescriptor;
848 
849     sal_Int32 nWindowAttributes = awt::WindowAttribute::BORDER | awt::WindowAttribute::MOVEABLE | awt::WindowAttribute::CLOSEABLE;
850     nWindowAttributes |= awt::VclWindowPeerAttribute::YES_NO;
851     nWindowAttributes |= awt::VclWindowPeerAttribute::DEF_NO;
852 
853     aDescriptor.Type              = awt::WindowClass_MODALTOP;
854     aDescriptor.WindowServiceName = "warningbox";
855     aDescriptor.ParentIndex       = -1;
856     aDescriptor.Parent            = xPeer;
857     aDescriptor.Bounds            = awt::Rectangle( 10, 10, 250, 150 );
858     aDescriptor.WindowAttributes  = nWindowAttributes;
859 
860     uno::Reference< awt::XMessageBox > xMsgBox( xToolkit->createWindow( aDescriptor ), uno::UNO_QUERY );
861     if ( xMsgBox.is() )
862     {
863         uno::Reference< awt::XVclContainer > xMsgBoxCtrls( xMsgBox, uno::UNO_QUERY );
864         if ( xMsgBoxCtrls.is() )
865         {
866             uno::Sequence< uno::Reference< awt::XWindow > > xChildren = xMsgBoxCtrls->getWindows();
867 
868             for (uno::Reference<awt::XWindow> const& child : xChildren)
869             {
870                 uno::Reference< awt::XVclWindowPeer > xMsgBoxCtrl( child, uno::UNO_QUERY );
871                 if ( xMsgBoxCtrl.is() )
872                 {
873                     bool bIsDefault = true;
874                     uno::Any aValue = xMsgBoxCtrl->getProperty( u"DefaultButton"_ustr );
875                     aValue >>= bIsDefault;
876                     if ( bIsDefault )
877                         xMsgBoxCtrl->setProperty( u"Text"_ustr, uno::Any( rBtnText_1 ) );
878                     else
879                         xMsgBoxCtrl->setProperty( u"Text"_ustr, uno::Any( rBtnText_2 ) );
880                 }
881             }
882         }
883 
884         sal_Int16 nRet;
885         // xMsgBox->setCaptionText( msCancelTitle );
886         mbShowsMessageBox = true;
887         xMsgBox->setMessageText( rWarningText );
888         nRet = xMsgBox->execute();
889         if ( nRet == 2 ) // RET_YES == 2
890             bRet = true;
891 
892         mbShowsMessageBox = false;
893     }
894 
895     uno::Reference< lang::XComponent > xComponent( xMsgBox, uno::UNO_QUERY );
896     if ( xComponent.is() )
897         xComponent->dispose();
898 
899     return bRet;
900 }
901 
902 
showOverwriteWarning(std::u16string_view rFileName) const903 bool UpdateHandler::showOverwriteWarning( std::u16string_view rFileName ) const
904 {
905     return showWarning(
906         (msReloadWarning
907          .replaceAll( "%FILENAME", rFileName )
908          .replaceAll( "%DOWNLOAD_PATH", msDownloadPath )),
909         msReloadContinue, msReloadReload );
910 }
911 
912 
showOverwriteWarning() const913 bool UpdateHandler::showOverwriteWarning() const
914 {
915     return showWarning( msOverwriteWarning );
916 }
917 
918 
919 #define BUTTON_HEIGHT       14
920 #define BUTTON_WIDTH        50
921 #define BUTTON_X_OFFSET      7
922 #define BUTTON_Y_OFFSET      3
923 #define LABEL_HEIGHT        10
924 
925 #define DIALOG_WIDTH       300
926 #define DIALOG_BORDER        5
927 #define INNER_BORDER         3
928 #define TEXT_OFFSET          1
929 #define BOX_HEIGHT1          ( LABEL_HEIGHT + 3*BUTTON_HEIGHT + 2*BUTTON_Y_OFFSET + 2*INNER_BORDER )
930 #define BOX_HEIGHT2         50
931 #define EDIT_WIDTH          ( DIALOG_WIDTH - 2 * DIALOG_BORDER )
932 #define BOX1_BTN_X          ( DIALOG_BORDER + EDIT_WIDTH - BUTTON_WIDTH - INNER_BORDER )
933 #define BOX1_BTN_Y          ( DIALOG_BORDER + LABEL_HEIGHT + INNER_BORDER)
934 #define THROBBER_WIDTH      16
935 #define THROBBER_HEIGHT     16
936 #define THROBBER_X_POS      ( DIALOG_BORDER + 8 )
937 #define THROBBER_Y_POS      ( DIALOG_BORDER + 23 )
938 #define BUTTON_BAR_HEIGHT   24
939 #define LABEL_OFFSET        ( LABEL_HEIGHT + 4 )
940 #define DIALOG_HEIGHT       ( BOX_HEIGHT1 + BOX_HEIGHT2 + LABEL_OFFSET + BUTTON_BAR_HEIGHT + 3 * DIALOG_BORDER )
941 #define LABEL_Y_POS         ( 2 * DIALOG_BORDER + BOX_HEIGHT1 )
942 #define EDIT2_Y_POS         ( LABEL_Y_POS + LABEL_HEIGHT )
943 #define BUTTON_BAR_Y_POS    ( EDIT2_Y_POS + DIALOG_BORDER + BOX_HEIGHT2 )
944 #define BUTTON_Y_POS        ( BUTTON_BAR_Y_POS + 8 )
945 #define CLOSE_BTN_X         ( DIALOG_WIDTH - DIALOG_BORDER - BUTTON_WIDTH )
946 #define INSTALL_BTN_X       ( CLOSE_BTN_X - 2 * BUTTON_X_OFFSET - BUTTON_WIDTH )
947 #define DOWNLOAD_BTN_X      ( INSTALL_BTN_X - BUTTON_X_OFFSET - BUTTON_WIDTH )
948 #define PROGRESS_WIDTH      80
949 #define PROGRESS_HEIGHT     10
950 #define PROGRESS_X_POS      ( DIALOG_BORDER + 8 )
951 #define PROGRESS_Y_POS      ( DIALOG_BORDER + 2*LABEL_OFFSET )
952 
953 
showControls(short nControls)954 void UpdateHandler::showControls( short nControls )
955 {
956     // The buttons from CANCEL_BUTTON to RESUME_BUTTON will be shown or
957     // hidden on demand
958     short nShiftMe;
959     for ( int i = 0; i <= int(RESUME_BUTTON); i++ )
960     {
961         nShiftMe = static_cast<short>(nControls >> i);
962         showControl( msButtonIDs[i], static_cast<bool>(nShiftMe & 0x01) );
963     }
964 
965     nShiftMe = static_cast<short>(nControls >> THROBBER_CTRL);
966     startThrobber( static_cast<bool>(nShiftMe & 0x01) );
967 
968     nShiftMe = static_cast<short>(nControls >> PROGRESS_CTRL);
969     showControl( CTRL_PROGRESS, static_cast<bool>(nShiftMe & 0x01) );
970     showControl( TEXT_PERCENT, static_cast<bool>(nShiftMe & 0x01) );
971 
972     // Status text needs to be smaller, when there are buttons at the right side of the dialog
973     if ( ( nControls & ( (1<<CANCEL_BUTTON) + (1<<PAUSE_BUTTON) + (1<<RESUME_BUTTON) ) )  != 0 )
974         setControlProperty( TEXT_STATUS, u"Width"_ustr, uno::Any( sal_Int32(EDIT_WIDTH - BUTTON_WIDTH - 2*INNER_BORDER - TEXT_OFFSET ) ) );
975     else
976         setControlProperty( TEXT_STATUS, u"Width"_ustr, uno::Any( sal_Int32(EDIT_WIDTH - 2*TEXT_OFFSET ) ) );
977 
978     // Status text needs to be taller, when we show the progress bar
979     if ( ( nControls & ( 1<<PROGRESS_CTRL ) ) != 0 )
980         setControlProperty( TEXT_STATUS, u"Height"_ustr, uno::Any( sal_Int32(LABEL_HEIGHT) ) );
981     else
982         setControlProperty( TEXT_STATUS, u"Height"_ustr, uno::Any( sal_Int32(BOX_HEIGHT1 - 4*TEXT_OFFSET - LABEL_HEIGHT ) ) );
983 }
984 
985 
createDialog()986 void UpdateHandler::createDialog()
987 {
988     if ( !mxContext.is() )
989     {
990         OSL_ASSERT( false );
991         return;
992     }
993 
994     if( mxContext.is() )
995     {
996         uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( mxContext );
997         xDesktop->addTerminateListener( this );
998     }
999 
1000     loadStrings();
1001 
1002     uno::Reference< lang::XMultiComponentFactory > xFactory( mxContext->getServiceManager(), uno::UNO_SET_THROW );
1003     uno::Reference< awt::XControlModel > xControlModel( xFactory->createInstanceWithContext(
1004                                                          u"com.sun.star.awt.UnoControlDialogModel"_ustr,
1005                                                          mxContext), uno::UNO_QUERY_THROW );
1006     {
1007         // @see awt/UnoControlDialogModel.idl
1008         uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY_THROW );
1009 
1010         xPropSet->setPropertyValue( u"Title"_ustr, uno::Any( msDlgTitle ) );
1011         xPropSet->setPropertyValue( u"Closeable"_ustr, uno::Any( true ) );
1012         xPropSet->setPropertyValue( u"Enabled"_ustr, uno::Any( true ) );
1013         xPropSet->setPropertyValue( u"Moveable"_ustr, uno::Any( true ) );
1014         xPropSet->setPropertyValue( u"Sizeable"_ustr, uno::Any( true ) );
1015         xPropSet->setPropertyValue( u"DesktopAsParent"_ustr, uno::Any( true ) );
1016         xPropSet->setPropertyValue( u"PositionX"_ustr, uno::Any(sal_Int32( 100 )) );
1017         xPropSet->setPropertyValue( u"PositionY"_ustr, uno::Any(sal_Int32( 100 )) );
1018         xPropSet->setPropertyValue( u"Width"_ustr, uno::Any(sal_Int32( DIALOG_WIDTH )) );
1019         xPropSet->setPropertyValue( u"Height"_ustr, uno::Any(sal_Int32( DIALOG_HEIGHT )) );
1020         xPropSet->setPropertyValue( u"HelpURL"_ustr, uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_DLG )) );
1021     }
1022     {   // Label (fixed text) <status>
1023         uno::Sequence< beans::NamedValue > aProps { { u"Label"_ustr, uno::Any( msStatusFL ) } };
1024 
1025         insertControlModel( xControlModel, FIXED_TEXT_MODEL, u"fixedLineStatus"_ustr,
1026                             awt::Rectangle( DIALOG_BORDER+1, DIALOG_BORDER, EDIT_WIDTH-2, LABEL_HEIGHT ),
1027                             aProps );
1028     }
1029     {   // box around <status> text
1030         uno::Sequence< beans::NamedValue > aProps;
1031 
1032         insertControlModel( xControlModel, GROUP_BOX_MODEL, u"StatusBox"_ustr,
1033                             awt::Rectangle( DIALOG_BORDER, DIALOG_BORDER + LABEL_HEIGHT, EDIT_WIDTH, BOX_HEIGHT1 - LABEL_HEIGHT ),
1034                             aProps );
1035     }
1036     {   // Text (multiline edit) <status>
1037         uno::Sequence< beans::NamedValue > aProps
1038         {
1039             { u"Text"_ustr, uno::Any( substVariables(msChecking) ) },
1040             { u"Border"_ustr, uno::Any( sal_Int16( 0 ) ) },
1041             { u"PaintTransparent"_ustr, uno::Any( true ) },
1042             { u"MultiLine"_ustr, uno::Any( true ) },
1043             { u"ReadOnly"_ustr, uno::Any( true ) },
1044             { u"AutoVScroll"_ustr, uno::Any( true ) },
1045             { u"HelpURL"_ustr, uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_STATUS )) }
1046         };
1047 
1048         insertControlModel( xControlModel, EDIT_FIELD_MODEL, TEXT_STATUS,
1049                             awt::Rectangle( DIALOG_BORDER + TEXT_OFFSET,
1050                                             DIALOG_BORDER + LABEL_HEIGHT + TEXT_OFFSET,
1051                                             EDIT_WIDTH - 2*TEXT_OFFSET,
1052                                             BOX_HEIGHT1 - 4*TEXT_OFFSET - LABEL_HEIGHT ),
1053                             aProps );
1054     }
1055     {   // Text (edit) <percent>
1056         uno::Sequence< beans::NamedValue > aProps
1057         {
1058             { u"Text"_ustr, uno::Any( substVariables(msPercent) ) },
1059             { u"Border"_ustr, uno::Any( sal_Int16( 0 ) ) },
1060             { u"PaintTransparent"_ustr, uno::Any( true ) },
1061             { u"ReadOnly"_ustr, uno::Any( true ) },
1062         };
1063 
1064         insertControlModel( xControlModel, EDIT_FIELD_MODEL, TEXT_PERCENT,
1065                             awt::Rectangle( PROGRESS_X_POS + PROGRESS_WIDTH + DIALOG_BORDER,
1066                                             PROGRESS_Y_POS,
1067                                             EDIT_WIDTH - PROGRESS_WIDTH - BUTTON_WIDTH - 2*DIALOG_BORDER,
1068                                             LABEL_HEIGHT ),
1069                             aProps );
1070     }
1071     {   // pause button
1072         uno::Sequence< beans::NamedValue > aProps
1073         {
1074             { u"DefaultButton"_ustr, uno::Any( false ) },
1075             { u"Enabled"_ustr, uno::Any( true ) },
1076             { u"PushButtonType"_ustr, uno::Any( sal_Int16(awt::PushButtonType_STANDARD) ) },
1077             { u"Label"_ustr, uno::Any( msPauseBtn ) },
1078             { u"HelpURL"_ustr, uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_PAUSE )) }
1079         };
1080 
1081         insertControlModel ( xControlModel, BUTTON_MODEL, msButtonIDs[PAUSE_BUTTON],
1082                              awt::Rectangle( BOX1_BTN_X, BOX1_BTN_Y, BUTTON_WIDTH, BUTTON_HEIGHT ),
1083                              aProps );
1084     }
1085     {   // resume button
1086         uno::Sequence< beans::NamedValue > aProps
1087         {
1088             { u"DefaultButton"_ustr, uno::Any( false ) },
1089             { u"Enabled"_ustr, uno::Any( true ) },
1090             { u"PushButtonType"_ustr, uno::Any( sal_Int16(awt::PushButtonType_STANDARD) ) },
1091             { u"Label"_ustr, uno::Any( msResumeBtn ) },
1092             { u"HelpURL"_ustr, uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_RESUME )) }
1093         };
1094 
1095         insertControlModel ( xControlModel, BUTTON_MODEL, msButtonIDs[RESUME_BUTTON],
1096                              awt::Rectangle( BOX1_BTN_X,
1097                                              BOX1_BTN_Y + BUTTON_Y_OFFSET + BUTTON_HEIGHT,
1098                                              BUTTON_WIDTH,
1099                                              BUTTON_HEIGHT ),
1100                              aProps );
1101     }
1102     {   // abort button
1103         uno::Sequence< beans::NamedValue > aProps
1104         {
1105             { u"DefaultButton"_ustr, uno::Any( false ) },
1106             { u"Enabled"_ustr, uno::Any( true ) },
1107             { u"PushButtonType"_ustr, uno::Any( sal_Int16(awt::PushButtonType_STANDARD) ) },
1108             { u"Label"_ustr, uno::Any( msCancelBtn ) },
1109             { u"HelpURL"_ustr, uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_CANCEL )) }
1110         };
1111 
1112         insertControlModel ( xControlModel, BUTTON_MODEL, msButtonIDs[CANCEL_BUTTON],
1113                              awt::Rectangle( BOX1_BTN_X,
1114                                              BOX1_BTN_Y + (2*(BUTTON_HEIGHT+BUTTON_Y_OFFSET)),
1115                                              BUTTON_WIDTH,
1116                                              BUTTON_HEIGHT ),
1117                              aProps );
1118     }
1119     {   // Label (FixedText) <description>
1120         uno::Sequence< beans::NamedValue > aProps { { u"Label"_ustr, uno::Any( msDescription ) } };
1121 
1122         insertControlModel( xControlModel, FIXED_TEXT_MODEL, u"fixedTextDescription"_ustr,
1123                             awt::Rectangle( DIALOG_BORDER+1, LABEL_Y_POS, EDIT_WIDTH-2, LABEL_HEIGHT ),
1124                             aProps );
1125     }
1126     {   // box around <description> text
1127         uno::Sequence< beans::NamedValue > aProps;
1128 
1129         insertControlModel( xControlModel, GROUP_BOX_MODEL, u"DescriptionBox"_ustr,
1130                             awt::Rectangle( DIALOG_BORDER, EDIT2_Y_POS, EDIT_WIDTH, BOX_HEIGHT2 ),
1131                             aProps );
1132     }
1133     {   // Text (MultiLineEdit) <description>
1134         uno::Sequence< beans::NamedValue > aProps
1135         {
1136             { u"Text"_ustr, uno::Any( OUString() ) },
1137             { u"Border"_ustr, uno::Any( sal_Int16( 0 ) ) },
1138             { u"PaintTransparent"_ustr, uno::Any( true ) },
1139             { u"MultiLine"_ustr, uno::Any( true ) },
1140             { u"ReadOnly"_ustr, uno::Any( true ) },
1141             { u"AutoVScroll"_ustr, uno::Any( true ) },
1142             { u"HelpURL"_ustr, uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_DESCRIPTION )) }
1143         };
1144 
1145         insertControlModel( xControlModel, EDIT_FIELD_MODEL, TEXT_DESCRIPTION,
1146                             awt::Rectangle( DIALOG_BORDER + TEXT_OFFSET,
1147                                             EDIT2_Y_POS + 2*TEXT_OFFSET,
1148                                             EDIT_WIDTH - 3*TEXT_OFFSET,
1149                                             BOX_HEIGHT2 - 3*TEXT_OFFSET ),
1150                             aProps );
1151     }
1152     {   // @see awt/UnoControlFixedLineModel.idl
1153         uno::Sequence< beans::NamedValue > aProps { { u"Orientation"_ustr, uno::Any( sal_Int32( 0 ) ) } };
1154 
1155         insertControlModel( xControlModel, FIXED_LINE_MODEL, u"fixedLine"_ustr,
1156                             awt::Rectangle( 0, BUTTON_BAR_Y_POS, DIALOG_WIDTH, 5 ),
1157                             aProps );
1158     }
1159     {   // close button // @see awt/UnoControlButtonModel.idl
1160         uno::Sequence< beans::NamedValue > aProps
1161         {
1162             { u"DefaultButton"_ustr, uno::Any( false ) },
1163             { u"Enabled"_ustr, uno::Any( true ) },
1164             // [property] short PushButtonType
1165             // with own "ButtonActionListener"
1166             { u"PushButtonType"_ustr, uno::Any( sal_Int16(awt::PushButtonType_STANDARD) ) },
1167             // with default ActionListener => endDialog().
1168             // setProperty( aProps, 2, "PushButtonType", uno::Any( sal_Int16(awt::PushButtonType_CANCEL) ) );
1169             // [property] string Label // only if PushButtonType_STANDARD
1170             { u"Label"_ustr, uno::Any( msClose ) },
1171             { u"HelpURL"_ustr, uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_CLOSE )) }
1172         };
1173 
1174         insertControlModel ( xControlModel, BUTTON_MODEL, msButtonIDs[ CLOSE_BUTTON ],
1175                              awt::Rectangle( CLOSE_BTN_X, BUTTON_Y_POS, BUTTON_WIDTH, BUTTON_HEIGHT ),
1176                              aProps );
1177     }
1178     {   // download button
1179         uno::Sequence< beans::NamedValue > aProps
1180         {
1181             { u"DefaultButton"_ustr, uno::Any( false ) },
1182             { u"Enabled"_ustr, uno::Any( true ) },
1183             { u"PushButtonType"_ustr, uno::Any( sal_Int16(awt::PushButtonType_STANDARD) ) },
1184             { u"Label"_ustr, uno::Any( msDownload ) },
1185             { u"HelpURL"_ustr, uno::Any(OUString( INET_HID_SCHEME + HID_CHECK_FOR_UPD_DOWNLOAD )) }
1186         };
1187 
1188         insertControlModel ( xControlModel, BUTTON_MODEL, msButtonIDs[DOWNLOAD_BUTTON],
1189                              awt::Rectangle( DOWNLOAD_BTN_X, BUTTON_Y_POS, BUTTON_WIDTH, BUTTON_HEIGHT ),
1190                              aProps );
1191     }
1192     {   // help button
1193         uno::Sequence< beans::NamedValue > aProps
1194         {
1195             { u"DefaultButton"_ustr, uno::Any( false ) },
1196             { u"Enabled"_ustr, uno::Any( true ) },
1197             { u"PushButtonType"_ustr, uno::Any( sal_Int16(awt::PushButtonType_HELP) ) }
1198         };
1199 
1200         insertControlModel( xControlModel, BUTTON_MODEL, msButtonIDs[HELP_BUTTON],
1201                             awt::Rectangle( DIALOG_BORDER, BUTTON_Y_POS, BUTTON_WIDTH, BUTTON_HEIGHT ),
1202                             aProps );
1203     }
1204     {   // @see awt/UnoControlThrobberModel.idl
1205         uno::Sequence< beans::NamedValue > aProps;
1206 
1207         insertControlModel( xControlModel, u"com.sun.star.awt.SpinningProgressControlModel"_ustr, CTRL_THROBBER,
1208                             awt::Rectangle( THROBBER_X_POS, THROBBER_Y_POS, THROBBER_WIDTH, THROBBER_HEIGHT),
1209                             aProps );
1210     }
1211     {    // @see awt/UnoControlProgressBarModel.idl
1212         uno::Sequence< beans::NamedValue > aProps
1213         {
1214             { u"Enabled"_ustr, uno::Any( true ) },
1215             { u"ProgressValue"_ustr, uno::Any( sal_Int32( 0 ) ) },
1216             { u"ProgressValueMax"_ustr, uno::Any( sal_Int32( 100 ) ) },
1217             { u"ProgressValueMin"_ustr, uno::Any( sal_Int32( 0 ) ) },
1218         };
1219         insertControlModel( xControlModel, u"com.sun.star.awt.UnoControlProgressBarModel"_ustr, CTRL_PROGRESS,
1220                             awt::Rectangle( PROGRESS_X_POS, PROGRESS_Y_POS, PROGRESS_WIDTH, PROGRESS_HEIGHT ),
1221                             aProps);
1222     }
1223 
1224     uno::Reference< awt::XUnoControlDialog > xControl = awt::UnoControlDialog::create( mxContext );
1225     xControl->setModel( xControlModel );
1226 
1227     if ( !mbVisible )
1228     {
1229         xControl->setVisible( false );
1230     }
1231 
1232     xControl->createPeer( nullptr, nullptr );
1233     {
1234         for ( int i = 0; i < HELP_BUTTON; i++ )
1235         {
1236             uno::Reference< awt::XButton > xButton ( xControl->getControl( msButtonIDs[i] ), uno::UNO_QUERY);
1237             if (xButton.is())
1238             {
1239                 xButton->setActionCommand( msButtonIDs[i] );
1240                 xButton->addActionListener( this );
1241             }
1242         }
1243     }
1244 
1245     mxUpdDlg.set( xControl, uno::UNO_QUERY_THROW );
1246     mnLastCtrlState = -1;
1247 }
1248 
1249 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1250