Update ooo320-m1
[ooovba.git] / dbaccess / source / ui / dlg / sqlmessage.cxx
bloba6743baf6f5f974dce65dc3c2b385abed32c0f75
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sqlmessage.cxx,v $
10 * $Revision: 1.30 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_dbaccess.hxx"
34 #ifndef _DBAUI_SQLMESSAGE_HXX_
35 #include "sqlmessage.hxx"
36 #endif
37 #ifndef _DBU_DLG_HRC_
38 #include "dbu_dlg.hrc"
39 #endif
40 #ifndef _DBAUI_SQLMESSAGE_HRC_
41 #include "sqlmessage.hrc"
42 #endif
43 #ifndef _COM_SUN_STAR_SDBC_SQLEXCEPTION_HPP_
44 #include <com/sun/star/sdbc/SQLException.hpp>
45 #endif
46 #ifndef _COM_SUN_STAR_SDB_SQLCONTEXT_HPP_
47 #include <com/sun/star/sdb/SQLContext.hpp>
48 #endif
49 #ifndef _SV_GROUP_HXX //autogen
50 #include <vcl/fixed.hxx>
51 #endif
52 #ifndef _SVTREEBOX_HXX
53 #include <svtools/svtreebx.hxx>
54 #endif
55 #ifndef _SVEDIT_HXX //autogen
56 #include <svtools/svmedit.hxx>
57 #endif
58 #ifndef _DBHELPER_DBEXCEPTION_HXX_
59 #include <connectivity/dbexception.hxx>
60 #endif
61 #ifndef CONNECTIVITY_SQLERROR_HXX
62 #include <connectivity/sqlerror.hxx>
63 #endif
64 #ifndef _SV_MSGBOX_HXX //autogen
65 #include <vcl/msgbox.hxx>
66 #endif
67 #ifndef _UTL_CONFIGMGR_HXX_
68 #include <unotools/configmgr.hxx>
69 #endif
70 #ifndef _SFX_SFXUNO_HXX
71 #include <sfx2/sfxuno.hxx>
72 #endif
73 #ifndef _DBA_DBACCESS_HELPID_HRC_
74 #include "dbaccess_helpid.hrc"
75 #endif
76 #ifndef DBAUI_TOOLS_HXX
77 #include "UITools.hxx"
78 #endif
79 #ifndef _DBAUI_MODULE_DBU_HXX_
80 #include "moduledbu.hxx"
81 #endif
83 #define BUTTONID_MORE BUTTONID_RETRY + 1
85 #define DIALOG_WIDTH 220
86 #define OUTER_MARGIN 6
87 #define IMAGE_SIZE 20
88 #define INNER_PADDING 3
89 #define TEXT_POS_X ( OUTER_MARGIN + IMAGE_SIZE + INNER_PADDING )
91 using namespace dbtools;
92 using namespace com::sun::star::uno;
93 using namespace com::sun::star::sdb;
94 using namespace com::sun::star::sdbc;
96 //.........................................................................
97 namespace dbaui
99 //.........................................................................
101 namespace
103 //------------------------------------------------------------------------------
104 class IImageProvider
106 public:
107 virtual Image getImage( bool _highContrast ) const = 0;
109 virtual ~IImageProvider() { }
112 //------------------------------------------------------------------------------
113 class ILabelProvider
115 public:
116 virtual String getLabel() const = 0;
118 virtual ~ILabelProvider() { };
121 //------------------------------------------------------------------------------
122 class ImageProvider : public IImageProvider
124 private:
125 USHORT m_defaultImageID;
126 USHORT m_highContrastImageID;
128 mutable Image m_defaultImage;
129 mutable Image m_highContrastImage;
131 public:
132 ImageProvider( USHORT _defaultImageID, USHORT _highContrastImageID )
133 :m_defaultImageID( _defaultImageID )
134 ,m_highContrastImageID( _highContrastImageID )
138 virtual Image getImage( bool _highContrast ) const
140 if ( _highContrast )
142 if ( !m_highContrastImage )
143 m_highContrastImage = Image( ModuleRes( m_highContrastImageID ) );
144 return m_highContrastImage;
147 if ( !m_defaultImage )
148 m_defaultImage = Image( ModuleRes( m_defaultImageID ) );
149 return m_defaultImage;
153 //------------------------------------------------------------------------------
154 class LabelProvider : public ILabelProvider
156 private:
157 String m_label;
158 public:
159 LabelProvider( USHORT _labelResourceID )
160 :m_label( ModuleRes( _labelResourceID ) )
164 virtual String getLabel() const
166 return m_label;
170 //------------------------------------------------------------------------------
171 class ProviderFactory
173 private:
174 mutable ::boost::shared_ptr< IImageProvider > m_pErrorImage;
175 mutable ::boost::shared_ptr< IImageProvider > m_pWarningsImage;
176 mutable ::boost::shared_ptr< IImageProvider > m_pInfoImage;
177 mutable ::boost::shared_ptr< ILabelProvider > m_pErrorLabel;
178 mutable ::boost::shared_ptr< ILabelProvider > m_pWarningsLabel;
179 mutable ::boost::shared_ptr< ILabelProvider > m_pInfoLabel;
181 public:
182 ProviderFactory()
186 ::boost::shared_ptr< IImageProvider > getImageProvider( SQLExceptionInfo::TYPE _eType ) const
188 ::boost::shared_ptr< IImageProvider >* ppProvider( &m_pErrorImage );
189 USHORT nNormalImageID( BMP_EXCEPTION_ERROR );
190 USHORT nHCImageID( BMP_EXCEPTION_ERROR_SCH );
192 switch ( _eType )
194 case SQLExceptionInfo::SQL_WARNING:
195 ppProvider = &m_pWarningsImage;
196 nNormalImageID = BMP_EXCEPTION_WARNING;
197 nHCImageID = BMP_EXCEPTION_WARNING_SCH;
198 break;
200 case SQLExceptionInfo::SQL_CONTEXT:
201 ppProvider = &m_pInfoImage;
202 nNormalImageID = BMP_EXCEPTION_INFO;
203 nHCImageID = BMP_EXCEPTION_INFO_SCH;
204 break;
206 default:
207 break;
210 if ( !ppProvider->get() )
211 ppProvider->reset( new ImageProvider( nNormalImageID, nHCImageID ) );
212 return *ppProvider;
215 ::boost::shared_ptr< ILabelProvider > getLabelProvider( SQLExceptionInfo::TYPE _eType, bool _bSubLabel ) const
217 ::boost::shared_ptr< ILabelProvider >* ppProvider( &m_pErrorLabel );
218 USHORT nLabelID( STR_EXCEPTION_ERROR );
220 switch ( _eType )
222 case SQLExceptionInfo::SQL_WARNING:
223 ppProvider = &m_pWarningsLabel;
224 nLabelID = STR_EXCEPTION_WARNING;
225 break;
227 case SQLExceptionInfo::SQL_CONTEXT:
228 ppProvider = &m_pInfoLabel;
229 nLabelID = _bSubLabel ? STR_EXCEPTION_DETAILS : STR_EXCEPTION_INFO;
230 break;
231 default:
232 break;
235 if ( !ppProvider->get() )
236 ppProvider->reset( new LabelProvider( nLabelID ) );
237 return *ppProvider;
242 //------------------------------------------------------------------------------
243 /// a stripped version of the SQLException, packed for displaying
244 struct ExceptionDisplayInfo
246 SQLExceptionInfo::TYPE eType;
248 ::boost::shared_ptr< IImageProvider > pImageProvider;
249 ::boost::shared_ptr< ILabelProvider > pLabelProvider;
251 bool bSubEntry;
253 String sMessage;
254 String sSQLState;
255 String sErrorCode;
257 ExceptionDisplayInfo() : eType( SQLExceptionInfo::UNDEFINED ), bSubEntry( false ) { }
258 ExceptionDisplayInfo( SQLExceptionInfo::TYPE _eType ) : eType( _eType ), bSubEntry( false ) { }
261 static bool lcl_hasDetails( const ExceptionDisplayInfo& _displayInfo )
263 return ( _displayInfo.sErrorCode.Len() )
264 || ( _displayInfo.sSQLState.Len()
265 && !_displayInfo.sSQLState.EqualsAscii( "S1000" )
269 typedef ::std::vector< ExceptionDisplayInfo > ExceptionDisplayChain;
271 //------------------------------------------------------------------------------
272 /// strips the [OOoBase] vendor identifier from the given error message, if applicable
273 ::rtl::OUString lcl_stripOOoBaseVendor( const ::rtl::OUString& _rErrorMessage )
275 ::rtl::OUString sErrorMessage( _rErrorMessage );
277 const ::rtl::OUString sVendorIdentifier( ::connectivity::SQLError::getMessagePrefix() );
278 if ( sErrorMessage.indexOf( sVendorIdentifier ) == 0 )
280 // characters to strip
281 sal_Int32 nStripLen( sVendorIdentifier.getLength() );
282 // usually, there should be a whitespace between the vendor and the real message
283 while ( ( sErrorMessage.getLength() > nStripLen )
284 && ( sErrorMessage[nStripLen] == ' ' )
286 ++nStripLen;
287 sErrorMessage = sErrorMessage.copy( nStripLen );
290 return sErrorMessage;
293 //------------------------------------------------------------------------------
294 void lcl_buildExceptionChain( const SQLExceptionInfo& _rErrorInfo, const ProviderFactory& _rFactory, ExceptionDisplayChain& _out_rChain )
297 ExceptionDisplayChain empty;
298 _out_rChain.swap( empty );
301 SQLExceptionIteratorHelper iter( _rErrorInfo );
302 while ( iter.hasMoreElements() )
304 // current chain element
305 SQLExceptionInfo aCurrentElement;
306 iter.next( aCurrentElement );
308 const SQLException* pCurrentError = (const SQLException*)aCurrentElement;
309 DBG_ASSERT( pCurrentError, "lcl_buildExceptionChain: iterator failure!" );
310 // hasMoreElements should not have returned <TRUE/> in this case
312 ExceptionDisplayInfo aDisplayInfo( aCurrentElement.getType() );
314 aDisplayInfo.sMessage = pCurrentError->Message.trim();
315 aDisplayInfo.sSQLState = pCurrentError->SQLState;
316 if ( pCurrentError->ErrorCode )
317 aDisplayInfo.sErrorCode = String::CreateFromInt32( pCurrentError->ErrorCode );
319 if ( !aDisplayInfo.sMessage.Len()
320 && !lcl_hasDetails( aDisplayInfo )
323 OSL_ENSURE( false, "lcl_buildExceptionChain: useles exception: no state, no error code, no message!" );
324 continue;
327 aDisplayInfo.pImageProvider = _rFactory.getImageProvider( aCurrentElement.getType() );
328 aDisplayInfo.pLabelProvider = _rFactory.getLabelProvider( aCurrentElement.getType(), false );
330 _out_rChain.push_back( aDisplayInfo );
332 if ( aCurrentElement.getType() == SQLExceptionInfo::SQL_CONTEXT )
334 const SQLContext* pContext = (const SQLContext*)aCurrentElement;
335 if ( pContext->Details.getLength() )
337 ExceptionDisplayInfo aSubInfo( aCurrentElement.getType() );
339 aSubInfo.sMessage = pContext->Details;
340 aSubInfo.pImageProvider = _rFactory.getImageProvider( aCurrentElement.getType() );
341 aSubInfo.pLabelProvider = _rFactory.getLabelProvider( aCurrentElement.getType(), true );
342 aSubInfo.bSubEntry = true;
344 _out_rChain.push_back( aSubInfo );
350 //------------------------------------------------------------------------------
351 void lcl_insertExceptionEntry( SvTreeListBox& _rList, bool _bHiContrast, size_t _nElementPos, const ExceptionDisplayInfo& _rEntry )
353 Image aEntryImage( _rEntry.pImageProvider->getImage( _bHiContrast ) );
354 SvLBoxEntry* pListEntry =
355 _rList.InsertEntry( _rEntry.pLabelProvider->getLabel(), aEntryImage, aEntryImage );
356 pListEntry->SetUserData( reinterpret_cast< void* >( _nElementPos ) );
360 //==============================================================================
361 class OExceptionChainDialog : public ModalDialog
363 FixedLine m_aFrame;
364 FixedText m_aListLabel;
365 SvTreeListBox m_aExceptionList;
366 FixedText m_aDescLabel;
367 MultiLineEdit m_aExceptionText;
368 OKButton m_aOK;
370 String m_sStatusLabel;
371 String m_sErrorCodeLabel;
373 ExceptionDisplayChain m_aExceptions;
375 public:
376 OExceptionChainDialog( Window* pParent, const ExceptionDisplayChain& _rExceptions );
377 ~OExceptionChainDialog();
379 protected:
380 DECL_LINK(OnExceptionSelected, void*);
383 DBG_NAME(OExceptionChainDialog)
384 //------------------------------------------------------------------------------
385 OExceptionChainDialog::OExceptionChainDialog( Window* pParent, const ExceptionDisplayChain& _rExceptions )
386 :ModalDialog(pParent, ModuleRes(DLG_SQLEXCEPTIONCHAIN))
387 ,m_aFrame (this, ModuleRes(FL_DETAILS))
388 ,m_aListLabel (this, ModuleRes(FT_ERRORLIST))
389 ,m_aExceptionList (this, ModuleRes(CTL_ERRORLIST))
390 ,m_aDescLabel (this, ModuleRes(FT_DESCRIPTION))
391 ,m_aExceptionText (this, ModuleRes(ME_DESCRIPTION))
392 ,m_aOK (this, ModuleRes(PB_OK))
393 ,m_aExceptions( _rExceptions )
395 DBG_CTOR(OExceptionChainDialog,NULL);
397 m_sStatusLabel = String( ModuleRes( STR_EXCEPTION_STATUS ) );
398 m_sErrorCodeLabel = String( ModuleRes( STR_EXCEPTION_ERRORCODE ) );
400 FreeResource();
402 m_aExceptionList.SetSelectionMode(SINGLE_SELECTION);
403 m_aExceptionList.SetDragDropMode(0);
404 m_aExceptionList.EnableInplaceEditing(sal_False);
405 m_aExceptionList.SetWindowBits(WB_HASLINES | WB_HASBUTTONS | WB_HASBUTTONSATROOT | WB_HSCROLL);
407 m_aExceptionList.SetSelectHdl(LINK(this, OExceptionChainDialog, OnExceptionSelected));
408 m_aExceptionList.SetNodeDefaultImages( );
409 m_aExceptionText.SetReadOnly(sal_True);
411 bool bHave22018 = false;
412 bool bHiContrast = isHiContrast( this );
413 size_t elementPos = 0;
415 for ( ExceptionDisplayChain::const_iterator loop = m_aExceptions.begin();
416 loop != m_aExceptions.end();
417 ++loop, ++elementPos
420 lcl_insertExceptionEntry( m_aExceptionList, bHiContrast, elementPos, *loop );
421 bHave22018 = loop->sSQLState.EqualsAscii( "22018" );
424 // if the error has the code 22018, then add an additional explanation
425 // #i24021# / 2004-10-14 / frank.schoenheit@sun.com
426 if ( bHave22018 )
428 ProviderFactory aProviderFactory;
430 ExceptionDisplayInfo aInfo22018;
431 aInfo22018.sMessage = String( ModuleRes( STR_EXPLAN_STRINGCONVERSION_ERROR ) );
432 aInfo22018.pLabelProvider = aProviderFactory.getLabelProvider( SQLExceptionInfo::SQL_CONTEXT, false );
433 aInfo22018.pImageProvider = aProviderFactory.getImageProvider( SQLExceptionInfo::SQL_CONTEXT );
434 m_aExceptions.push_back( aInfo22018 );
436 lcl_insertExceptionEntry( m_aExceptionList, bHiContrast, m_aExceptions.size() - 1, aInfo22018 );
440 //------------------------------------------------------------------------------
441 OExceptionChainDialog::~OExceptionChainDialog()
443 DBG_DTOR(OExceptionChainDialog,NULL);
446 //------------------------------------------------------------------------------
447 IMPL_LINK(OExceptionChainDialog, OnExceptionSelected, void*, EMPTYARG)
449 SvLBoxEntry* pSelected = m_aExceptionList.FirstSelected();
450 DBG_ASSERT(!pSelected || !m_aExceptionList.NextSelected(pSelected), "OExceptionChainDialog::OnExceptionSelected : multi selection ?");
452 String sText;
454 if ( pSelected )
456 size_t pos = reinterpret_cast< size_t >( pSelected->GetUserData() );
457 const ExceptionDisplayInfo& aExceptionInfo( m_aExceptions[ pos ] );
459 if ( aExceptionInfo.sSQLState.Len() )
461 sText += m_sStatusLabel;
462 sText.AppendAscii(": ");
463 sText += aExceptionInfo.sSQLState;
464 sText.AppendAscii("\n");
467 if ( aExceptionInfo.sErrorCode.Len() )
469 sText += m_sErrorCodeLabel;
470 sText.AppendAscii(": ");
471 sText += aExceptionInfo.sErrorCode;
472 sText.AppendAscii("\n");
475 if ( sText.Len() )
476 sText.AppendAscii( "\n" );
478 sText += aExceptionInfo.sMessage;
481 m_aExceptionText.SetText(sText);
483 return 0L;
486 //==============================================================================
487 //= SQLMessageBox_Impl
488 //==============================================================================
489 struct SQLMessageBox_Impl
491 ExceptionDisplayChain aDisplayInfo;
493 SQLMessageBox_Impl( const SQLExceptionInfo& _rExceptionInfo )
495 // transform the exception chain to a form more suitable for displaying it here
496 ProviderFactory aProviderFactory;
497 lcl_buildExceptionChain( _rExceptionInfo, aProviderFactory, aDisplayInfo );
501 //------------------------------------------------------------------------------
502 namespace
504 ::rtl::OUString lcl_getProductName()
506 ::rtl::OUString sProductName;
507 OSL_VERIFY( ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME ) >>= sProductName );
508 return sProductName;
511 void lcl_positionInAppFont( const Window& _rParent, Window& _rChild, long _nX, long _nY, long _Width, long _Height )
513 Point aPos = _rParent.LogicToPixel( Point( _nX, _nY ), MAP_APPFONT );
514 Size aSize = _rParent.LogicToPixel( Size( _Width, _Height ), MAP_APPFONT );
515 _rChild.SetPosSizePixel( aPos, aSize );
518 void lcl_addButton( ButtonDialog& _rDialog, StandardButtonType _eType, bool _bDefault )
520 USHORT nButtonID = 0;
521 switch ( _eType )
523 case BUTTON_YES: nButtonID = BUTTONID_YES; break;
524 case BUTTON_NO: nButtonID = BUTTONID_NO; break;
525 case BUTTON_OK: nButtonID = BUTTONID_OK; break;
526 case BUTTON_CANCEL: nButtonID = BUTTONID_CANCEL; break;
527 case BUTTON_RETRY: nButtonID = BUTTONID_RETRY; break;
528 case BUTTON_HELP: nButtonID = BUTTONID_HELP; break;
529 default:
530 OSL_ENSURE( false, "lcl_addButton: invalid button id!" );
531 break;
533 _rDialog.AddButton( _eType, nButtonID, _bDefault ? BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON : 0 );
537 //------------------------------------------------------------------------------
538 void OSQLMessageBox::impl_positionControls()
540 OSL_PRECOND( !m_pImpl->aDisplayInfo.empty(), "OSQLMessageBox::impl_positionControls: nothing to display at all?" );
543 if ( m_pImpl->aDisplayInfo.empty() )
544 return;
545 const ExceptionDisplayInfo* pSecondInfo = NULL;
547 const ExceptionDisplayInfo& rFirstInfo = *m_pImpl->aDisplayInfo.begin();
548 if ( m_pImpl->aDisplayInfo.size() > 1 )
549 pSecondInfo = &m_pImpl->aDisplayInfo[1];
550 String sPrimary, sSecondary;
551 sPrimary = rFirstInfo.sMessage;
552 // one or two texts to display?
553 if ( pSecondInfo )
555 // we show two elements in the main dialog if and only if one of
556 // - the first element in the chain is an SQLContext, and the second
557 // element denotes its sub entry
558 // - the first and the second element are both independent (i.e. the second
559 // is no sub entry), and none of them is a context.
560 bool bFirstElementIsContext = ( rFirstInfo.eType == SQLExceptionInfo::SQL_CONTEXT );
561 bool bSecondElementIsContext = ( pSecondInfo->eType == SQLExceptionInfo::SQL_CONTEXT );
563 if ( bFirstElementIsContext && pSecondInfo->bSubEntry )
564 sSecondary = pSecondInfo->sMessage;
565 if ( !bFirstElementIsContext && !bSecondElementIsContext )
566 sSecondary = pSecondInfo->sMessage;
569 // image
570 lcl_positionInAppFont( *this, m_aInfoImage, OUTER_MARGIN, OUTER_MARGIN, IMAGE_SIZE, IMAGE_SIZE );
571 m_aInfoImage.Show();
573 // primary text
574 lcl_positionInAppFont( *this, m_aTitle, TEXT_POS_X, OUTER_MARGIN, DIALOG_WIDTH - TEXT_POS_X - 2 * OUTER_MARGIN, 16 );
575 sPrimary = lcl_stripOOoBaseVendor( sPrimary );
576 m_aTitle.SetText( sPrimary );
577 m_aTitle.Show();
579 Rectangle aPrimaryRect( m_aTitle.GetPosPixel(), m_aTitle.GetSizePixel() );
581 // secondary text (if applicable)
582 m_aMessage.SetStyle( m_aMessage.GetStyle() | WB_NOLABEL );
583 sSecondary = lcl_stripOOoBaseVendor( sSecondary );
584 m_aMessage.SetText( sSecondary );
586 lcl_positionInAppFont( *this, m_aMessage, TEXT_POS_X, OUTER_MARGIN + 16 + 3, DIALOG_WIDTH - TEXT_POS_X - 2 * OUTER_MARGIN, 8 );
587 Rectangle aSecondaryRect( m_aMessage.GetPosPixel(), m_aMessage.GetSizePixel() );
589 bool bHaveSecondaryText = sSecondary.Len() != 0;
591 // determine which space the secondary text would occupy
592 if ( bHaveSecondaryText )
593 aSecondaryRect = GetTextRect( aSecondaryRect, sSecondary, TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE | TEXT_DRAW_LEFT );
594 else
595 aSecondaryRect.Bottom() = aSecondaryRect.Top() - 1;
597 // adjust secondary control height accordingly
598 m_aMessage.SetSizePixel( aSecondaryRect.GetSize() );
599 m_aMessage.Show( aSecondaryRect.GetHeight() > 0 );
601 // if there's no secondary text ...
602 if ( !bHaveSecondaryText )
603 { // then give the primary text as much horizontal space as it needs
604 Rectangle aSuggestedRect( GetTextRect( aPrimaryRect, sPrimary, TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE | TEXT_DRAW_CENTER ) );
605 aPrimaryRect.Right() = aPrimaryRect.Left() + aSuggestedRect.GetWidth();
606 aPrimaryRect.Bottom() = aPrimaryRect.Top() + aSuggestedRect.GetHeight();
607 // and center it horizontally
608 m_aTitle.SetStyle( ( m_aTitle.GetStyle() & ~WB_LEFT ) | WB_CENTER );
610 Rectangle aInfoRect( m_aInfoImage.GetPosPixel(), m_aInfoImage.GetSizePixel() );
611 // also, if it's not as high as the image ...
612 if ( aPrimaryRect.GetHeight() < m_aInfoImage.GetSizePixel().Height() )
613 { // ... make it fit the image height
614 aPrimaryRect.Bottom() += aInfoRect.GetHeight() - aPrimaryRect.GetHeight();
615 // and center it vertically
616 m_aTitle.SetStyle( m_aTitle.GetStyle() | WB_VCENTER );
618 else
619 { // ... otherwise, center the image vertically, relative to the primary text
620 aInfoRect.Move( 0, ( aPrimaryRect.GetHeight() - aInfoRect.GetHeight() ) / 2 );
621 m_aInfoImage.SetPosSizePixel( aInfoRect.TopLeft(), aInfoRect.GetSize() );
624 m_aTitle.SetPosSizePixel( aPrimaryRect.TopLeft(), aPrimaryRect.GetSize() );
627 // adjust dialog size accordingly
628 const Rectangle& rBottomTextRect( bHaveSecondaryText ? aSecondaryRect : aPrimaryRect );
629 Size aBorderSize = LogicToPixel( Size( OUTER_MARGIN, OUTER_MARGIN ), MAP_APPFONT );
630 Size aDialogSize( LogicToPixel( Size( DIALOG_WIDTH, 30 ), MAP_APPFONT ) );
631 aDialogSize.Height() = rBottomTextRect.Bottom() + aBorderSize.Height();
632 aDialogSize.Width() = aPrimaryRect.Right() + aBorderSize.Width();
634 SetSizePixel( aDialogSize );
635 SetPageSizePixel( aDialogSize );
638 //------------------------------------------------------------------------------
639 void OSQLMessageBox::impl_initImage( MessageType _eImage )
641 switch (_eImage)
643 default:
644 DBG_ERROR( "OSQLMessageBox::impl_initImage: unsupported image type!" );
646 case Info:
647 m_aInfoImage.SetImage(InfoBox::GetStandardImage());
648 break;
649 case Warning:
650 m_aInfoImage.SetImage(WarningBox::GetStandardImage());
651 break;
652 case Error:
653 m_aInfoImage.SetImage(ErrorBox::GetStandardImage());
654 break;
655 case Query:
656 m_aInfoImage.SetImage(QueryBox::GetStandardImage());
657 break;
661 //------------------------------------------------------------------------------
662 void OSQLMessageBox::impl_createStandardButtons( WinBits _nStyle )
664 if ( _nStyle & WB_YES_NO_CANCEL )
666 lcl_addButton( *this, BUTTON_YES, ( _nStyle & WB_DEF_YES ) != 0 );
667 lcl_addButton( *this, BUTTON_NO, ( _nStyle & WB_DEF_NO ) != 0 );
668 lcl_addButton( *this, BUTTON_CANCEL, ( _nStyle & WB_DEF_CANCEL ) != 0 );
670 else if ( _nStyle & WB_OK_CANCEL )
672 lcl_addButton( *this, BUTTON_OK, ( _nStyle & WB_DEF_OK ) != 0 );
673 lcl_addButton( *this, BUTTON_CANCEL, ( _nStyle & WB_DEF_CANCEL ) != 0 );
675 else if ( _nStyle & WB_YES_NO )
677 lcl_addButton( *this, BUTTON_YES, ( _nStyle & WB_DEF_YES ) != 0 );
678 lcl_addButton( *this, BUTTON_NO, ( _nStyle & WB_DEF_NO ) != 0 );
680 else if ( _nStyle & WB_RETRY_CANCEL )
682 lcl_addButton( *this, BUTTON_RETRY, ( _nStyle & WB_DEF_RETRY ) != 0 );
683 lcl_addButton( *this, BUTTON_CANCEL, ( _nStyle & WB_DEF_CANCEL ) != 0 );
685 else
687 OSL_ENSURE( WB_OK & _nStyle, "OSQLMessageBox::impl_createStandardButtons: unsupported dialog style requested!" );
688 AddButton( BUTTON_OK, BUTTONID_OK, BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON );
691 if ( m_sHelpURL.getLength() )
693 lcl_addButton( *this, BUTTON_HELP, false );
695 SmartId aHelpId( m_sHelpURL );
696 if ( m_sHelpURL.indexOfAsciiL( "HID:", 4 ) == 0 )
697 aHelpId = SmartId( m_sHelpURL.copy( 4 ).toInt32() );
699 SetSmartHelpId( aHelpId );
703 //------------------------------------------------------------------------------
704 void OSQLMessageBox::impl_addDetailsButton()
706 size_t nFirstPageVisible = m_aMessage.IsVisible() ? 2 : 1;
708 bool bMoreDetailsAvailable = m_pImpl->aDisplayInfo.size() > nFirstPageVisible;
709 if ( !bMoreDetailsAvailable )
711 // even if the text fits into what we can display, we might need to details button
712 // if there is more non-trivial information in the errors than the mere messages
713 for ( ExceptionDisplayChain::const_iterator error = m_pImpl->aDisplayInfo.begin();
714 error != m_pImpl->aDisplayInfo.end();
715 ++error
718 if ( lcl_hasDetails( *error ) )
720 bMoreDetailsAvailable = true;
721 break;
726 if ( bMoreDetailsAvailable )
728 AddButton( BUTTON_MORE, BUTTONID_MORE, 0 );
729 PushButton* pButton = GetPushButton( BUTTONID_MORE );
730 OSL_ENSURE( pButton, "OSQLMessageBox::impl_addDetailsButton: just added this button, why isn't it there?" );
731 pButton->SetClickHdl( LINK( this, OSQLMessageBox, ButtonClickHdl ) );
732 pButton->SetUniqueId( UID_SQLERROR_BUTTONMORE );
736 //------------------------------------------------------------------------------
737 void OSQLMessageBox::Construct( WinBits _nStyle, MessageType _eImage )
739 // Changed as per BugID 79541 Branding/Configuration
740 String sDialogTitle( lcl_getProductName() );
741 SetText( sDialogTitle.AppendAscii( " Base" ) );
743 // position and size the controls and the dialog, depending on whether we have one or two texts to display
744 impl_positionControls();
746 // init the image
747 MessageType eType( _eImage );
748 if ( eType == AUTO )
750 switch ( m_pImpl->aDisplayInfo[0].eType )
752 case SQLExceptionInfo::SQL_EXCEPTION: eType = Error; break;
753 case SQLExceptionInfo::SQL_WARNING: eType = Warning; break;
754 case SQLExceptionInfo::SQL_CONTEXT: eType = Info; break;
755 default: OSL_ENSURE( false, "OSQLMessageBox::Construct: invalid type!" );
758 impl_initImage( eType );
760 // create buttons
761 impl_createStandardButtons( _nStyle );
762 impl_addDetailsButton();
765 //------------------------------------------------------------------------------
766 OSQLMessageBox::OSQLMessageBox(Window* _pParent, const SQLExceptionInfo& _rException, WinBits _nStyle, const ::rtl::OUString& _rHelpURL )
767 :ButtonDialog( _pParent, WB_HORZ | WB_STDDIALOG )
768 ,m_aInfoImage( this )
769 ,m_aTitle( this, WB_WORDBREAK | WB_LEFT )
770 ,m_aMessage( this, WB_WORDBREAK | WB_LEFT )
771 ,m_sHelpURL( _rHelpURL )
772 ,m_pImpl( new SQLMessageBox_Impl( _rException ) )
774 Construct( _nStyle, AUTO );
777 //------------------------------------------------------------------------------
778 OSQLMessageBox::OSQLMessageBox( Window* _pParent, const UniString& _rTitle, const UniString& _rMessage, WinBits _nStyle, MessageType _eType, const ::dbtools::SQLExceptionInfo* _pAdditionalErrorInfo )
779 :ButtonDialog( _pParent, WB_HORZ | WB_STDDIALOG )
780 ,m_aInfoImage( this )
781 ,m_aTitle( this, WB_WORDBREAK | WB_LEFT )
782 ,m_aMessage( this, WB_WORDBREAK | WB_LEFT )
784 SQLContext aError;
785 aError.Message = _rTitle;
786 aError.Details = _rMessage;
787 if ( _pAdditionalErrorInfo )
788 aError.NextException = _pAdditionalErrorInfo->get();
790 m_pImpl.reset( new SQLMessageBox_Impl( SQLExceptionInfo( aError ) ) );
792 Construct( _nStyle, _eType );
795 //--------------------------------------------------------------------------
796 OSQLMessageBox::~OSQLMessageBox()
800 //--------------------------------------------------------------------------
801 IMPL_LINK( OSQLMessageBox, ButtonClickHdl, Button *, /*pButton*/ )
803 OExceptionChainDialog aDlg( this, m_pImpl->aDisplayInfo );
804 aDlg.Execute();
805 return 0;
808 //==================================================================
809 // OSQLWarningBox
810 //==================================================================
811 OSQLWarningBox::OSQLWarningBox( Window* _pParent, const UniString& _rMessage, WinBits _nStyle,
812 const ::dbtools::SQLExceptionInfo* _pAdditionalErrorInfo )
813 :OSQLMessageBox( _pParent, String( ModuleRes( STR_STAT_WARNING ) ), _rMessage, _nStyle, OSQLMessageBox::Warning, _pAdditionalErrorInfo )
817 //.........................................................................
818 } // namespace dbaui
819 //.........................................................................