fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / dbaccess / source / ui / dlg / sqlmessage.cxx
blob7dcf64813ef42e7d975bcc92c05096567b0460c2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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
44 #define IMAGE_SIZE 20
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;
53 namespace dbaui
56 namespace
58 class IImageProvider
60 public:
61 virtual Image getImage() const = 0;
63 virtual ~IImageProvider() { }
66 class ILabelProvider
68 public:
69 virtual OUString getLabel() const = 0;
71 virtual ~ILabelProvider() { };
74 class ImageProvider : public IImageProvider
76 private:
77 sal_uInt16 m_defaultImageID;
79 mutable Image m_defaultImage;
81 public:
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
97 private:
98 OUString m_label;
99 public:
100 LabelProvider( sal_uInt16 _labelResourceID )
101 :m_label( ModuleRes( _labelResourceID ) )
105 virtual OUString getLabel() const SAL_OVERRIDE
107 return m_label;
111 class ProviderFactory
113 private:
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;
121 public:
122 ProviderFactory()
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 );
131 switch ( _eType )
133 case SQLExceptionInfo::SQL_WARNING:
134 ppProvider = &m_pWarningsImage;
135 nNormalImageID = BMP_EXCEPTION_WARNING;
136 break;
138 case SQLExceptionInfo::SQL_CONTEXT:
139 ppProvider = &m_pInfoImage;
140 nNormalImageID = BMP_EXCEPTION_INFO;
141 break;
143 default:
144 break;
147 if ( !ppProvider->get() )
148 ppProvider->reset( new ImageProvider( nNormalImageID ) );
149 return *ppProvider;
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 );
157 switch ( _eType )
159 case SQLExceptionInfo::SQL_WARNING:
160 ppProvider = &m_pWarningsLabel;
161 nLabelID = STR_EXCEPTION_WARNING;
162 break;
164 case SQLExceptionInfo::SQL_CONTEXT:
165 ppProvider = &m_pInfoLabel;
166 nLabelID = _bSubLabel ? STR_EXCEPTION_DETAILS : STR_EXCEPTION_INFO;
167 break;
168 default:
169 break;
172 if ( !ppProvider->get() )
173 ppProvider->reset( new LabelProvider( nLabelID ) );
174 return *ppProvider;
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;
187 bool bSubEntry;
189 OUString sMessage;
190 OUString sSQLState;
191 OUString sErrorCode;
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] == ' ' )
221 ++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!" );
258 continue;
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;
303 public:
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();
313 protected:
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();
346 ++loop, ++elementPos
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
354 // #i24021#
355 if ( bHave22018 )
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 ?");
374 OUString sText;
376 if ( pSelected )
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;
384 sText += ": ";
385 sText += aExceptionInfo.sSQLState;
386 sText += "\n";
389 if ( !aExceptionInfo.sErrorCode.isEmpty() )
391 sText += m_sErrorCodeLabel;
392 sText += ": ";
393 sText += aExceptionInfo.sErrorCode;
394 sText += "\n";
397 if ( !sText.isEmpty() )
398 sText += "\n";
400 sText += aExceptionInfo.sMessage;
403 m_pExceptionText->SetText(sText);
405 return 0L;
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 );
421 namespace
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;
433 switch ( _eType )
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;
441 default:
442 OSL_FAIL( "lcl_addButton: invalid button id!" );
443 break;
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() )
454 return;
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?
463 if ( pSecondInfo )
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;
479 // image
480 lcl_positionInAppFont( *this, *m_aInfoImage.get(), OUTER_MARGIN, OUTER_MARGIN, IMAGE_SIZE, IMAGE_SIZE );
481 m_aInfoImage->Show();
483 // primary text
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 );
487 m_aTitle->Show();
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 );
504 else
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 );
528 else
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 )
550 switch (_eImage)
552 default:
553 OSL_FAIL( "OSQLMessageBox::impl_initImage: unsupported image type!" );
554 /* Fall through */
555 case Info:
556 m_aInfoImage->SetImage(InfoBox::GetStandardImage());
557 break;
558 case Warning:
559 m_aInfoImage->SetImage(WarningBox::GetStandardImage());
560 break;
561 case Error:
562 m_aInfoImage->SetImage(ErrorBox::GetStandardImage());
563 break;
564 case Query:
565 m_aInfoImage->SetImage(QueryBox::GetStandardImage());
566 break;
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 );
593 else
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 );
603 OUString aTmp;
604 INetURLObject aHID( m_sHelpURL );
605 if ( aHID.GetProtocol() == INetProtocol::Hid )
606 aTmp = aHID.GetURLPath();
607 else
608 aTmp = m_sHelpURL;
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();
625 ++error
628 if ( lcl_hasDetails( *error ) )
630 bMoreDetailsAvailable = true;
631 break;
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();
653 // init the image
654 MessageType eType( _eImage );
655 if ( eType == AUTO )
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 );
667 // create buttons
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) )
689 SQLContext aError;
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()
702 disposeOnce();
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 );
716 aDlg->Execute();
717 return 0;
720 // OSQLWarningBox
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 )
727 // OSQLErrorBox
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 )
734 } // namespace dbaui
736 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */