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