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