1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "sqlmessage.hxx"
21 #include "dbu_dlg.hrc"
22 #include <com/sun/star/sdbc/SQLException.hpp>
23 #include <com/sun/star/sdb/SQLContext.hpp>
24 #include <vcl/fixed.hxx>
25 #include <osl/diagnose.h>
26 #include <svtools/treelistbox.hxx>
27 #include "svtools/treelistentry.hxx"
28 #include <svtools/svmedit.hxx>
29 #include <connectivity/dbexception.hxx>
30 #include <connectivity/sqlerror.hxx>
31 #include <vcl/msgbox.hxx>
32 #include <unotools/configmgr.hxx>
33 #include <sfx2/sfxuno.hxx>
34 #include "dbaccess_helpid.hrc"
35 #include "UITools.hxx"
36 #include "moduledbu.hxx"
38 #include <tools/urlobj.hxx>
40 #define RET_MORE RET_RETRY + 1
42 #define DIALOG_WIDTH 220
43 #define OUTER_MARGIN 6
45 #define INNER_PADDING 3
46 #define TEXT_POS_X ( OUTER_MARGIN + IMAGE_SIZE + INNER_PADDING )
48 using namespace dbtools
;
49 using namespace com::sun::star::uno
;
50 using namespace com::sun::star::sdb
;
51 using namespace com::sun::star::sdbc
;
61 virtual Image
getImage() const = 0;
63 virtual ~IImageProvider() { }
69 virtual OUString
getLabel() const = 0;
71 virtual ~ILabelProvider() { };
74 class ImageProvider
: public IImageProvider
77 sal_uInt16 m_defaultImageID
;
79 mutable Image m_defaultImage
;
82 ImageProvider( sal_uInt16 _defaultImageID
)
83 :m_defaultImageID( _defaultImageID
)
87 virtual Image
getImage() const SAL_OVERRIDE
89 if ( !m_defaultImage
)
90 m_defaultImage
= Image( ModuleRes( m_defaultImageID
) );
91 return m_defaultImage
;
95 class LabelProvider
: public ILabelProvider
100 LabelProvider( sal_uInt16 _labelResourceID
)
101 :m_label( ModuleRes( _labelResourceID
) )
105 virtual OUString
getLabel() const SAL_OVERRIDE
111 class ProviderFactory
114 mutable ::boost::shared_ptr
< IImageProvider
> m_pErrorImage
;
115 mutable ::boost::shared_ptr
< IImageProvider
> m_pWarningsImage
;
116 mutable ::boost::shared_ptr
< IImageProvider
> m_pInfoImage
;
117 mutable ::boost::shared_ptr
< ILabelProvider
> m_pErrorLabel
;
118 mutable ::boost::shared_ptr
< ILabelProvider
> m_pWarningsLabel
;
119 mutable ::boost::shared_ptr
< ILabelProvider
> m_pInfoLabel
;
126 ::boost::shared_ptr
< IImageProvider
> getImageProvider( SQLExceptionInfo::TYPE _eType
) const
128 ::boost::shared_ptr
< IImageProvider
>* ppProvider( &m_pErrorImage
);
129 sal_uInt16
nNormalImageID( BMP_EXCEPTION_ERROR
);
133 case SQLExceptionInfo::SQL_WARNING
:
134 ppProvider
= &m_pWarningsImage
;
135 nNormalImageID
= BMP_EXCEPTION_WARNING
;
138 case SQLExceptionInfo::SQL_CONTEXT
:
139 ppProvider
= &m_pInfoImage
;
140 nNormalImageID
= BMP_EXCEPTION_INFO
;
147 if ( !ppProvider
->get() )
148 ppProvider
->reset( new ImageProvider( nNormalImageID
) );
152 ::boost::shared_ptr
< ILabelProvider
> getLabelProvider( SQLExceptionInfo::TYPE _eType
, bool _bSubLabel
) const
154 ::boost::shared_ptr
< ILabelProvider
>* ppProvider( &m_pErrorLabel
);
155 sal_uInt16
nLabelID( STR_EXCEPTION_ERROR
);
159 case SQLExceptionInfo::SQL_WARNING
:
160 ppProvider
= &m_pWarningsLabel
;
161 nLabelID
= STR_EXCEPTION_WARNING
;
164 case SQLExceptionInfo::SQL_CONTEXT
:
165 ppProvider
= &m_pInfoLabel
;
166 nLabelID
= _bSubLabel
? STR_EXCEPTION_DETAILS
: STR_EXCEPTION_INFO
;
172 if ( !ppProvider
->get() )
173 ppProvider
->reset( new LabelProvider( nLabelID
) );
179 /// a stripped version of the SQLException, packed for displaying
180 struct ExceptionDisplayInfo
182 SQLExceptionInfo::TYPE eType
;
184 ::boost::shared_ptr
< IImageProvider
> pImageProvider
;
185 ::boost::shared_ptr
< ILabelProvider
> pLabelProvider
;
193 ExceptionDisplayInfo() : eType( SQLExceptionInfo::UNDEFINED
), bSubEntry( false ) { }
194 ExceptionDisplayInfo( SQLExceptionInfo::TYPE _eType
) : eType( _eType
), bSubEntry( false ) { }
197 static bool lcl_hasDetails( const ExceptionDisplayInfo
& _displayInfo
)
199 return ( !_displayInfo
.sErrorCode
.isEmpty() )
200 || ( !_displayInfo
.sSQLState
.isEmpty()
201 && _displayInfo
.sSQLState
!= "S1000"
205 typedef ::std::vector
< ExceptionDisplayInfo
> ExceptionDisplayChain
;
207 /// strips the [OOoBase] vendor identifier from the given error message, if applicable
208 OUString
lcl_stripOOoBaseVendor( const OUString
& _rErrorMessage
)
210 OUString
sErrorMessage( _rErrorMessage
);
212 const OUString
sVendorIdentifier( ::connectivity::SQLError::getMessagePrefix() );
213 if ( sErrorMessage
.startsWith( sVendorIdentifier
) )
215 // characters to strip
216 sal_Int32
nStripLen( sVendorIdentifier
.getLength() );
217 // usually, there should be a whitespace between the vendor and the real message
218 while ( ( sErrorMessage
.getLength() > nStripLen
)
219 && ( sErrorMessage
[nStripLen
] == ' ' )
222 sErrorMessage
= sErrorMessage
.copy( nStripLen
);
225 return sErrorMessage
;
228 void lcl_buildExceptionChain( const SQLExceptionInfo
& _rErrorInfo
, const ProviderFactory
& _rFactory
, ExceptionDisplayChain
& _out_rChain
)
231 ExceptionDisplayChain empty
;
232 _out_rChain
.swap( empty
);
235 SQLExceptionIteratorHelper
iter( _rErrorInfo
);
236 while ( iter
.hasMoreElements() )
238 // current chain element
239 SQLExceptionInfo aCurrentElement
;
240 iter
.next( aCurrentElement
);
242 const SQLException
* pCurrentError
= (const SQLException
*)aCurrentElement
;
243 OSL_ENSURE( pCurrentError
, "lcl_buildExceptionChain: iterator failure!" );
244 // hasMoreElements should not have returned <TRUE/> in this case
246 ExceptionDisplayInfo
aDisplayInfo( aCurrentElement
.getType() );
248 aDisplayInfo
.sMessage
= pCurrentError
->Message
.trim();
249 aDisplayInfo
.sSQLState
= pCurrentError
->SQLState
;
250 if ( pCurrentError
->ErrorCode
)
251 aDisplayInfo
.sErrorCode
= OUString::number( pCurrentError
->ErrorCode
);
253 if ( aDisplayInfo
.sMessage
.isEmpty()
254 && !lcl_hasDetails( aDisplayInfo
)
257 OSL_FAIL( "lcl_buildExceptionChain: useless exception: no state, no error code, no message!" );
261 aDisplayInfo
.pImageProvider
= _rFactory
.getImageProvider( aCurrentElement
.getType() );
262 aDisplayInfo
.pLabelProvider
= _rFactory
.getLabelProvider( aCurrentElement
.getType(), false );
264 _out_rChain
.push_back( aDisplayInfo
);
266 if ( aCurrentElement
.getType() == SQLExceptionInfo::SQL_CONTEXT
)
268 const SQLContext
* pContext
= (const SQLContext
*)aCurrentElement
;
269 if ( !pContext
->Details
.isEmpty() )
271 ExceptionDisplayInfo
aSubInfo( aCurrentElement
.getType() );
273 aSubInfo
.sMessage
= pContext
->Details
;
274 aSubInfo
.pImageProvider
= _rFactory
.getImageProvider( aCurrentElement
.getType() );
275 aSubInfo
.pLabelProvider
= _rFactory
.getLabelProvider( aCurrentElement
.getType(), true );
276 aSubInfo
.bSubEntry
= true;
278 _out_rChain
.push_back( aSubInfo
);
284 void lcl_insertExceptionEntry( SvTreeListBox
& _rList
, size_t _nElementPos
, const ExceptionDisplayInfo
& _rEntry
)
286 Image
aEntryImage( _rEntry
.pImageProvider
->getImage() );
287 SvTreeListEntry
* pListEntry
=
288 _rList
.InsertEntry( _rEntry
.pLabelProvider
->getLabel(), aEntryImage
, aEntryImage
);
289 pListEntry
->SetUserData( reinterpret_cast< void* >( _nElementPos
) );
293 class OExceptionChainDialog
: public ModalDialog
295 VclPtr
<SvTreeListBox
> m_pExceptionList
;
296 VclPtr
<VclMultiLineEdit
> m_pExceptionText
;
298 OUString m_sStatusLabel
;
299 OUString m_sErrorCodeLabel
;
301 ExceptionDisplayChain m_aExceptions
;
304 OExceptionChainDialog( vcl::Window
* pParent
, const ExceptionDisplayChain
& _rExceptions
);
305 virtual ~OExceptionChainDialog() { disposeOnce(); }
306 virtual void dispose() SAL_OVERRIDE
308 m_pExceptionList
.clear();
309 m_pExceptionText
.clear();
310 ModalDialog::dispose();
314 DECL_LINK(OnExceptionSelected
, void*);
317 OExceptionChainDialog::OExceptionChainDialog(vcl::Window
* pParent
, const ExceptionDisplayChain
& _rExceptions
)
318 : ModalDialog(pParent
, "SQLExceptionDialog", "dbaccess/ui/sqlexception.ui")
319 , m_aExceptions(_rExceptions
)
321 get(m_pExceptionList
, "list");
322 Size
aListSize(LogicToPixel(Size(85, 93), MAP_APPFONT
));
323 m_pExceptionList
->set_width_request(aListSize
.Width());
324 m_pExceptionList
->set_height_request(aListSize
.Height());
325 get(m_pExceptionText
, "description");
326 Size
aTextSize(LogicToPixel(Size(125 , 93), MAP_APPFONT
));
327 m_pExceptionText
->set_width_request(aTextSize
.Width());
328 m_pExceptionText
->set_height_request(aTextSize
.Height());
330 m_sStatusLabel
= ModuleRes( STR_EXCEPTION_STATUS
);
331 m_sErrorCodeLabel
= ModuleRes( STR_EXCEPTION_ERRORCODE
);
333 m_pExceptionList
->SetSelectionMode(SINGLE_SELECTION
);
334 m_pExceptionList
->SetDragDropMode(DragDropMode::NONE
);
335 m_pExceptionList
->EnableInplaceEditing(false);
336 m_pExceptionList
->SetStyle(m_pExceptionList
->GetStyle() | WB_HASLINES
| WB_HASBUTTONS
| WB_HASBUTTONSATROOT
| WB_HSCROLL
);
338 m_pExceptionList
->SetSelectHdl(LINK(this, OExceptionChainDialog
, OnExceptionSelected
));
339 m_pExceptionList
->SetNodeDefaultImages( );
341 bool bHave22018
= false;
342 size_t elementPos
= 0;
344 for ( ExceptionDisplayChain::const_iterator loop
= m_aExceptions
.begin();
345 loop
!= m_aExceptions
.end();
349 lcl_insertExceptionEntry( *m_pExceptionList
, elementPos
, *loop
);
350 bHave22018
= loop
->sSQLState
== "22018";
353 // if the error has the code 22018, then add an additional explanation
357 ProviderFactory aProviderFactory
;
359 ExceptionDisplayInfo aInfo22018
;
360 aInfo22018
.sMessage
= ModuleRes( STR_EXPLAN_STRINGCONVERSION_ERROR
);
361 aInfo22018
.pLabelProvider
= aProviderFactory
.getLabelProvider( SQLExceptionInfo::SQL_CONTEXT
, false );
362 aInfo22018
.pImageProvider
= aProviderFactory
.getImageProvider( SQLExceptionInfo::SQL_CONTEXT
);
363 m_aExceptions
.push_back( aInfo22018
);
365 lcl_insertExceptionEntry( *m_pExceptionList
, m_aExceptions
.size() - 1, aInfo22018
);
369 IMPL_LINK_NOARG(OExceptionChainDialog
, OnExceptionSelected
)
371 SvTreeListEntry
* pSelected
= m_pExceptionList
->FirstSelected();
372 OSL_ENSURE(!pSelected
|| !m_pExceptionList
->NextSelected(pSelected
), "OExceptionChainDialog::OnExceptionSelected : multi selection ?");
378 size_t pos
= reinterpret_cast< size_t >( pSelected
->GetUserData() );
379 const ExceptionDisplayInfo
& aExceptionInfo( m_aExceptions
[ pos
] );
381 if ( !aExceptionInfo
.sSQLState
.isEmpty() )
383 sText
+= m_sStatusLabel
;
385 sText
+= aExceptionInfo
.sSQLState
;
389 if ( !aExceptionInfo
.sErrorCode
.isEmpty() )
391 sText
+= m_sErrorCodeLabel
;
393 sText
+= aExceptionInfo
.sErrorCode
;
397 if ( !sText
.isEmpty() )
400 sText
+= aExceptionInfo
.sMessage
;
403 m_pExceptionText
->SetText(sText
);
408 // SQLMessageBox_Impl
409 struct SQLMessageBox_Impl
411 ExceptionDisplayChain aDisplayInfo
;
413 SQLMessageBox_Impl( const SQLExceptionInfo
& _rExceptionInfo
)
415 // transform the exception chain to a form more suitable for displaying it here
416 ProviderFactory aProviderFactory
;
417 lcl_buildExceptionChain( _rExceptionInfo
, aProviderFactory
, aDisplayInfo
);
423 void lcl_positionInAppFont( const vcl::Window
& _rParent
, vcl::Window
& _rChild
, long _nX
, long _nY
, long _Width
, long _Height
)
425 Point aPos
= _rParent
.LogicToPixel( Point( _nX
, _nY
), MAP_APPFONT
);
426 Size aSize
= _rParent
.LogicToPixel( Size( _Width
, _Height
), MAP_APPFONT
);
427 _rChild
.SetPosSizePixel( aPos
, aSize
);
430 void lcl_addButton( ButtonDialog
& _rDialog
, StandardButtonType _eType
, bool _bDefault
)
432 sal_uInt16 nButtonID
= 0;
435 case StandardButtonType::Yes
: nButtonID
= RET_YES
; break;
436 case StandardButtonType::No
: nButtonID
= RET_NO
; break;
437 case StandardButtonType::OK
: nButtonID
= RET_OK
; break;
438 case StandardButtonType::Cancel
: nButtonID
= RET_CANCEL
; break;
439 case StandardButtonType::Retry
: nButtonID
= RET_RETRY
; break;
440 case StandardButtonType::Help
: nButtonID
= RET_HELP
; break;
442 OSL_FAIL( "lcl_addButton: invalid button id!" );
445 _rDialog
.AddButton( _eType
, nButtonID
, _bDefault
? ButtonDialogFlags::Default
| ButtonDialogFlags::Focus
: ButtonDialogFlags::NONE
);
449 void OSQLMessageBox::impl_positionControls()
451 OSL_PRECOND( !m_pImpl
->aDisplayInfo
.empty(), "OSQLMessageBox::impl_positionControls: nothing to display at all?" );
453 if ( m_pImpl
->aDisplayInfo
.empty() )
455 const ExceptionDisplayInfo
* pSecondInfo
= NULL
;
457 const ExceptionDisplayInfo
& rFirstInfo
= *m_pImpl
->aDisplayInfo
.begin();
458 if ( m_pImpl
->aDisplayInfo
.size() > 1 )
459 pSecondInfo
= &m_pImpl
->aDisplayInfo
[1];
460 OUString sPrimary
, sSecondary
;
461 sPrimary
= rFirstInfo
.sMessage
;
462 // one or two texts to display?
465 // we show two elements in the main dialog if and only if one of
466 // - the first element in the chain is an SQLContext, and the second
467 // element denotes its sub entry
468 // - the first and the second element are both independent (i.e. the second
469 // is no sub entry), and none of them is a context.
470 bool bFirstElementIsContext
= ( rFirstInfo
.eType
== SQLExceptionInfo::SQL_CONTEXT
);
471 bool bSecondElementIsContext
= ( pSecondInfo
->eType
== SQLExceptionInfo::SQL_CONTEXT
);
473 if ( bFirstElementIsContext
&& pSecondInfo
->bSubEntry
)
474 sSecondary
= pSecondInfo
->sMessage
;
475 if ( !bFirstElementIsContext
&& !bSecondElementIsContext
)
476 sSecondary
= pSecondInfo
->sMessage
;
480 lcl_positionInAppFont( *this, *m_aInfoImage
.get(), OUTER_MARGIN
, OUTER_MARGIN
, IMAGE_SIZE
, IMAGE_SIZE
);
481 m_aInfoImage
->Show();
484 lcl_positionInAppFont( *this, *m_aTitle
.get(), TEXT_POS_X
, OUTER_MARGIN
, DIALOG_WIDTH
- TEXT_POS_X
- 2 * OUTER_MARGIN
, 16 );
485 sPrimary
= lcl_stripOOoBaseVendor( sPrimary
);
486 m_aTitle
->SetText( sPrimary
);
489 Rectangle
aPrimaryRect( m_aTitle
->GetPosPixel(), m_aTitle
->GetSizePixel() );
491 // secondary text (if applicable)
492 m_aMessage
->SetStyle( m_aMessage
->GetStyle() | WB_NOLABEL
);
493 sSecondary
= lcl_stripOOoBaseVendor( sSecondary
);
494 m_aMessage
->SetText( sSecondary
);
496 lcl_positionInAppFont( *this, *m_aMessage
.get(), TEXT_POS_X
, OUTER_MARGIN
+ 16 + 3, DIALOG_WIDTH
- TEXT_POS_X
- 2 * OUTER_MARGIN
, 8 );
497 Rectangle
aSecondaryRect( m_aMessage
->GetPosPixel(), m_aMessage
->GetSizePixel() );
499 bool bHaveSecondaryText
= !sSecondary
.isEmpty();
501 // determine which space the secondary text would occupy
502 if ( bHaveSecondaryText
)
503 aSecondaryRect
= GetTextRect( aSecondaryRect
, sSecondary
, DrawTextFlags::WordBreak
| DrawTextFlags::MultiLine
| DrawTextFlags::Left
);
505 aSecondaryRect
.Bottom() = aSecondaryRect
.Top() - 1;
507 // adjust secondary control height accordingly
508 m_aMessage
->SetSizePixel( aSecondaryRect
.GetSize() );
509 m_aMessage
->Show( aSecondaryRect
.GetHeight() > 0 );
511 // if there's no secondary text ...
512 if ( !bHaveSecondaryText
)
513 { // then give the primary text as much horizontal space as it needs
514 Rectangle
aSuggestedRect( GetTextRect( aPrimaryRect
, sPrimary
, DrawTextFlags::WordBreak
| DrawTextFlags::MultiLine
| DrawTextFlags::Center
) );
515 aPrimaryRect
.Right() = aPrimaryRect
.Left() + aSuggestedRect
.GetWidth();
516 aPrimaryRect
.Bottom() = aPrimaryRect
.Top() + aSuggestedRect
.GetHeight();
517 // and center it horizontally
518 m_aTitle
->SetStyle( ( m_aTitle
->GetStyle() & ~WB_LEFT
) | WB_CENTER
);
520 Rectangle
aInfoRect( m_aInfoImage
->GetPosPixel(), m_aInfoImage
->GetSizePixel() );
521 // also, if it's not as high as the image ...
522 if ( aPrimaryRect
.GetHeight() < m_aInfoImage
->GetSizePixel().Height() )
523 { // ... make it fit the image height
524 aPrimaryRect
.Bottom() += aInfoRect
.GetHeight() - aPrimaryRect
.GetHeight();
525 // and center it vertically
526 m_aTitle
->SetStyle( m_aTitle
->GetStyle() | WB_VCENTER
);
529 { // ... otherwise, center the image vertically, relative to the primary text
530 aInfoRect
.Move( 0, ( aPrimaryRect
.GetHeight() - aInfoRect
.GetHeight() ) / 2 );
531 m_aInfoImage
->SetPosSizePixel( aInfoRect
.TopLeft(), aInfoRect
.GetSize() );
534 m_aTitle
->SetPosSizePixel( aPrimaryRect
.TopLeft(), aPrimaryRect
.GetSize() );
537 // adjust dialog size accordingly
538 const Rectangle
& rBottomTextRect( bHaveSecondaryText
? aSecondaryRect
: aPrimaryRect
);
539 Size aBorderSize
= LogicToPixel( Size( OUTER_MARGIN
, OUTER_MARGIN
), MAP_APPFONT
);
540 Size
aDialogSize( LogicToPixel( Size( DIALOG_WIDTH
, 30 ), MAP_APPFONT
) );
541 aDialogSize
.Height() = rBottomTextRect
.Bottom() + aBorderSize
.Height();
542 aDialogSize
.Width() = aPrimaryRect
.Right() + aBorderSize
.Width();
544 SetSizePixel( aDialogSize
);
545 SetPageSizePixel( aDialogSize
);
548 void OSQLMessageBox::impl_initImage( MessageType _eImage
)
553 OSL_FAIL( "OSQLMessageBox::impl_initImage: unsupported image type!" );
556 m_aInfoImage
->SetImage(InfoBox::GetStandardImage());
559 m_aInfoImage
->SetImage(WarningBox::GetStandardImage());
562 m_aInfoImage
->SetImage(ErrorBox::GetStandardImage());
565 m_aInfoImage
->SetImage(QueryBox::GetStandardImage());
570 void OSQLMessageBox::impl_createStandardButtons( WinBits _nStyle
)
572 if ( _nStyle
& WB_YES_NO_CANCEL
)
574 lcl_addButton( *this, StandardButtonType::Yes
, ( _nStyle
& WB_DEF_YES
) != 0 );
575 lcl_addButton( *this, StandardButtonType::No
, ( _nStyle
& WB_DEF_NO
) != 0 );
576 lcl_addButton( *this, StandardButtonType::Cancel
, ( _nStyle
& WB_DEF_CANCEL
) != 0 );
578 else if ( _nStyle
& WB_OK_CANCEL
)
580 lcl_addButton( *this, StandardButtonType::OK
, ( _nStyle
& WB_DEF_OK
) != 0 );
581 lcl_addButton( *this, StandardButtonType::Cancel
, ( _nStyle
& WB_DEF_CANCEL
) != 0 );
583 else if ( _nStyle
& WB_YES_NO
)
585 lcl_addButton( *this, StandardButtonType::Yes
, ( _nStyle
& WB_DEF_YES
) != 0 );
586 lcl_addButton( *this, StandardButtonType::No
, ( _nStyle
& WB_DEF_NO
) != 0 );
588 else if ( _nStyle
& WB_RETRY_CANCEL
)
590 lcl_addButton( *this, StandardButtonType::Retry
, ( _nStyle
& WB_DEF_RETRY
) != 0 );
591 lcl_addButton( *this, StandardButtonType::Cancel
, ( _nStyle
& WB_DEF_CANCEL
) != 0 );
595 OSL_ENSURE( WB_OK
& _nStyle
, "OSQLMessageBox::impl_createStandardButtons: unsupported dialog style requested!" );
596 AddButton( StandardButtonType::OK
, RET_OK
, ButtonDialogFlags::Default
| ButtonDialogFlags::Focus
);
599 if ( !m_sHelpURL
.isEmpty() )
601 lcl_addButton( *this, StandardButtonType::Help
, false );
604 INetURLObject
aHID( m_sHelpURL
);
605 if ( aHID
.GetProtocol() == INetProtocol::Hid
)
606 aTmp
= aHID
.GetURLPath();
610 SetHelpId( OUStringToOString( aTmp
, RTL_TEXTENCODING_UTF8
) );
614 void OSQLMessageBox::impl_addDetailsButton()
616 size_t nFirstPageVisible
= m_aMessage
->IsVisible() ? 2 : 1;
618 bool bMoreDetailsAvailable
= m_pImpl
->aDisplayInfo
.size() > nFirstPageVisible
;
619 if ( !bMoreDetailsAvailable
)
621 // even if the text fits into what we can display, we might need to details button
622 // if there is more non-trivial information in the errors than the mere messages
623 for ( ExceptionDisplayChain::const_iterator error
= m_pImpl
->aDisplayInfo
.begin();
624 error
!= m_pImpl
->aDisplayInfo
.end();
628 if ( lcl_hasDetails( *error
) )
630 bMoreDetailsAvailable
= true;
636 if ( bMoreDetailsAvailable
)
638 AddButton( StandardButtonType::More
, RET_MORE
);
639 PushButton
* pButton
= GetPushButton( RET_MORE
);
640 OSL_ENSURE( pButton
, "OSQLMessageBox::impl_addDetailsButton: just added this button, why isn't it there?" );
641 pButton
->SetClickHdl( LINK( this, OSQLMessageBox
, ButtonClickHdl
) );
642 pButton
->SetUniqueId( UID_SQLERROR_BUTTONMORE
);
646 void OSQLMessageBox::Construct( WinBits _nStyle
, MessageType _eImage
)
648 SetText( utl::ConfigManager::getProductName() + " Base" );
650 // position and size the controls and the dialog, depending on whether we have one or two texts to display
651 impl_positionControls();
654 MessageType
eType( _eImage
);
657 switch ( m_pImpl
->aDisplayInfo
[0].eType
)
659 case SQLExceptionInfo::SQL_EXCEPTION
: eType
= Error
; break;
660 case SQLExceptionInfo::SQL_WARNING
: eType
= Warning
; break;
661 case SQLExceptionInfo::SQL_CONTEXT
: eType
= Info
; break;
662 default: OSL_FAIL( "OSQLMessageBox::Construct: invalid type!" );
665 impl_initImage( eType
);
668 impl_createStandardButtons( _nStyle
);
669 impl_addDetailsButton();
672 OSQLMessageBox::OSQLMessageBox(vcl::Window
* _pParent
, const SQLExceptionInfo
& _rException
, WinBits _nStyle
, const OUString
& _rHelpURL
)
673 :ButtonDialog( _pParent
, WB_HORZ
| WB_STDDIALOG
)
674 ,m_aInfoImage( VclPtr
<FixedImage
>::Create(this) )
675 ,m_aTitle( VclPtr
<FixedText
>::Create(this, WB_WORDBREAK
| WB_LEFT
) )
676 ,m_aMessage( VclPtr
<FixedText
>::Create(this, WB_WORDBREAK
| WB_LEFT
) )
677 ,m_sHelpURL( _rHelpURL
)
678 ,m_pImpl( new SQLMessageBox_Impl( _rException
) )
680 Construct( _nStyle
, AUTO
);
683 OSQLMessageBox::OSQLMessageBox( vcl::Window
* _pParent
, const OUString
& _rTitle
, const OUString
& _rMessage
, WinBits _nStyle
, MessageType _eType
, const ::dbtools::SQLExceptionInfo
* _pAdditionalErrorInfo
)
684 :ButtonDialog( _pParent
, WB_HORZ
| WB_STDDIALOG
)
685 ,m_aInfoImage( VclPtr
<FixedImage
>::Create(this) )
686 ,m_aTitle( VclPtr
<FixedText
>::Create(this, WB_WORDBREAK
| WB_LEFT
) )
687 ,m_aMessage( VclPtr
<FixedText
>::Create(this, WB_WORDBREAK
| WB_LEFT
) )
690 aError
.Message
= _rTitle
;
691 aError
.Details
= _rMessage
;
692 if ( _pAdditionalErrorInfo
)
693 aError
.NextException
= _pAdditionalErrorInfo
->get();
695 m_pImpl
.reset( new SQLMessageBox_Impl( SQLExceptionInfo( aError
) ) );
697 Construct( _nStyle
, _eType
);
700 OSQLMessageBox::~OSQLMessageBox()
705 void OSQLMessageBox::dispose()
707 m_aInfoImage
.disposeAndClear();
708 m_aTitle
.disposeAndClear();
709 m_aMessage
.disposeAndClear();
710 ButtonDialog::dispose();
713 IMPL_LINK( OSQLMessageBox
, ButtonClickHdl
, Button
*, /*pButton*/ )
715 ScopedVclPtrInstance
< OExceptionChainDialog
> aDlg( this, m_pImpl
->aDisplayInfo
);
721 OSQLWarningBox::OSQLWarningBox( vcl::Window
* _pParent
, const OUString
& _rMessage
, WinBits _nStyle
,
722 const ::dbtools::SQLExceptionInfo
* _pAdditionalErrorInfo
)
723 :OSQLMessageBox( _pParent
, ModuleRes( STR_EXCEPTION_WARNING
), _rMessage
, _nStyle
, OSQLMessageBox::Warning
, _pAdditionalErrorInfo
)
728 OSQLErrorBox::OSQLErrorBox( vcl::Window
* _pParent
, const OUString
& _rMessage
, WinBits _nStyle
,
729 const ::dbtools::SQLExceptionInfo
* _pAdditionalErrorInfo
)
730 :OSQLMessageBox( _pParent
, ModuleRes( STR_EXCEPTION_ERROR
), _rMessage
, _nStyle
, OSQLMessageBox::Error
, _pAdditionalErrorInfo
)
736 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */