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_dbaccess.hxx" 30 31 #ifndef _DBAUI_SQLMESSAGE_HXX_ 32 #include "sqlmessage.hxx" 33 #endif 34 #ifndef _DBU_DLG_HRC_ 35 #include "dbu_dlg.hrc" 36 #endif 37 #ifndef _DBAUI_SQLMESSAGE_HRC_ 38 #include "sqlmessage.hrc" 39 #endif 40 #ifndef _COM_SUN_STAR_SDBC_SQLEXCEPTION_HPP_ 41 #include <com/sun/star/sdbc/SQLException.hpp> 42 #endif 43 #ifndef _COM_SUN_STAR_SDB_SQLCONTEXT_HPP_ 44 #include <com/sun/star/sdb/SQLContext.hpp> 45 #endif 46 #ifndef _SV_GROUP_HXX //autogen 47 #include <vcl/fixed.hxx> 48 #endif 49 #ifndef _SVTREEBOX_HXX 50 #include <svtools/svtreebx.hxx> 51 #endif 52 #ifndef _SVEDIT_HXX //autogen 53 #include <svtools/svmedit.hxx> 54 #endif 55 #ifndef _DBHELPER_DBEXCEPTION_HXX_ 56 #include <connectivity/dbexception.hxx> 57 #endif 58 #ifndef CONNECTIVITY_SQLERROR_HXX 59 #include <connectivity/sqlerror.hxx> 60 #endif 61 #ifndef _SV_MSGBOX_HXX //autogen 62 #include <vcl/msgbox.hxx> 63 #endif 64 #ifndef _UTL_CONFIGMGR_HXX_ 65 #include <unotools/configmgr.hxx> 66 #endif 67 #ifndef _SFX_SFXUNO_HXX 68 #include <sfx2/sfxuno.hxx> 69 #endif 70 #ifndef _DBA_DBACCESS_HELPID_HRC_ 71 #include "dbaccess_helpid.hrc" 72 #endif 73 #ifndef DBAUI_TOOLS_HXX 74 #include "UITools.hxx" 75 #endif 76 #ifndef _DBAUI_MODULE_DBU_HXX_ 77 #include "moduledbu.hxx" 78 #endif 79 80 #include <tools/urlobj.hxx> 81 82 #define BUTTONID_MORE BUTTONID_RETRY + 1 83 84 #define DIALOG_WIDTH 220 85 #define OUTER_MARGIN 6 86 #define IMAGE_SIZE 20 87 #define INNER_PADDING 3 88 #define TEXT_POS_X ( OUTER_MARGIN + IMAGE_SIZE + INNER_PADDING ) 89 90 using namespace dbtools; 91 using namespace com::sun::star::uno; 92 using namespace com::sun::star::sdb; 93 using namespace com::sun::star::sdbc; 94 95 //......................................................................... 96 namespace dbaui 97 { 98 //......................................................................... 99 100 namespace 101 { 102 //------------------------------------------------------------------------------ 103 class IImageProvider 104 { 105 public: 106 virtual Image getImage( bool _highContrast ) const = 0; 107 108 virtual ~IImageProvider() { } 109 }; 110 111 //------------------------------------------------------------------------------ 112 class ILabelProvider 113 { 114 public: 115 virtual String getLabel() const = 0; 116 117 virtual ~ILabelProvider() { }; 118 }; 119 120 //------------------------------------------------------------------------------ 121 class ImageProvider : public IImageProvider 122 { 123 private: 124 sal_uInt16 m_defaultImageID; 125 sal_uInt16 m_highContrastImageID; 126 127 mutable Image m_defaultImage; 128 mutable Image m_highContrastImage; 129 130 public: 131 ImageProvider( sal_uInt16 _defaultImageID, sal_uInt16 _highContrastImageID ) 132 :m_defaultImageID( _defaultImageID ) 133 ,m_highContrastImageID( _highContrastImageID ) 134 { 135 } 136 137 virtual Image getImage( bool _highContrast ) const 138 { 139 if ( _highContrast ) 140 { 141 if ( !m_highContrastImage ) 142 m_highContrastImage = Image( ModuleRes( m_highContrastImageID ) ); 143 return m_highContrastImage; 144 } 145 146 if ( !m_defaultImage ) 147 m_defaultImage = Image( ModuleRes( m_defaultImageID ) ); 148 return m_defaultImage; 149 } 150 }; 151 152 //------------------------------------------------------------------------------ 153 class LabelProvider : public ILabelProvider 154 { 155 private: 156 String m_label; 157 public: 158 LabelProvider( sal_uInt16 _labelResourceID ) 159 :m_label( ModuleRes( _labelResourceID ) ) 160 { 161 } 162 163 virtual String getLabel() const 164 { 165 return m_label; 166 } 167 }; 168 169 //------------------------------------------------------------------------------ 170 class ProviderFactory 171 { 172 private: 173 mutable ::boost::shared_ptr< IImageProvider > m_pErrorImage; 174 mutable ::boost::shared_ptr< IImageProvider > m_pWarningsImage; 175 mutable ::boost::shared_ptr< IImageProvider > m_pInfoImage; 176 mutable ::boost::shared_ptr< ILabelProvider > m_pErrorLabel; 177 mutable ::boost::shared_ptr< ILabelProvider > m_pWarningsLabel; 178 mutable ::boost::shared_ptr< ILabelProvider > m_pInfoLabel; 179 180 public: 181 ProviderFactory() 182 { 183 } 184 185 ::boost::shared_ptr< IImageProvider > getImageProvider( SQLExceptionInfo::TYPE _eType ) const 186 { 187 ::boost::shared_ptr< IImageProvider >* ppProvider( &m_pErrorImage ); 188 sal_uInt16 nNormalImageID( BMP_EXCEPTION_ERROR ); 189 sal_uInt16 nHCImageID( BMP_EXCEPTION_ERROR_SCH ); 190 191 switch ( _eType ) 192 { 193 case SQLExceptionInfo::SQL_WARNING: 194 ppProvider = &m_pWarningsImage; 195 nNormalImageID = BMP_EXCEPTION_WARNING; 196 nHCImageID = BMP_EXCEPTION_WARNING_SCH; 197 break; 198 199 case SQLExceptionInfo::SQL_CONTEXT: 200 ppProvider = &m_pInfoImage; 201 nNormalImageID = BMP_EXCEPTION_INFO; 202 nHCImageID = BMP_EXCEPTION_INFO_SCH; 203 break; 204 205 default: 206 break; 207 } 208 209 if ( !ppProvider->get() ) 210 ppProvider->reset( new ImageProvider( nNormalImageID, nHCImageID ) ); 211 return *ppProvider; 212 } 213 214 ::boost::shared_ptr< ILabelProvider > getLabelProvider( SQLExceptionInfo::TYPE _eType, bool _bSubLabel ) const 215 { 216 ::boost::shared_ptr< ILabelProvider >* ppProvider( &m_pErrorLabel ); 217 sal_uInt16 nLabelID( STR_EXCEPTION_ERROR ); 218 219 switch ( _eType ) 220 { 221 case SQLExceptionInfo::SQL_WARNING: 222 ppProvider = &m_pWarningsLabel; 223 nLabelID = STR_EXCEPTION_WARNING; 224 break; 225 226 case SQLExceptionInfo::SQL_CONTEXT: 227 ppProvider = &m_pInfoLabel; 228 nLabelID = _bSubLabel ? STR_EXCEPTION_DETAILS : STR_EXCEPTION_INFO; 229 break; 230 default: 231 break; 232 } 233 234 if ( !ppProvider->get() ) 235 ppProvider->reset( new LabelProvider( nLabelID ) ); 236 return *ppProvider; 237 } 238 239 }; 240 241 //------------------------------------------------------------------------------ 242 /// a stripped version of the SQLException, packed for displaying 243 struct ExceptionDisplayInfo 244 { 245 SQLExceptionInfo::TYPE eType; 246 247 ::boost::shared_ptr< IImageProvider > pImageProvider; 248 ::boost::shared_ptr< ILabelProvider > pLabelProvider; 249 250 bool bSubEntry; 251 252 String sMessage; 253 String sSQLState; 254 String sErrorCode; 255 256 ExceptionDisplayInfo() : eType( SQLExceptionInfo::UNDEFINED ), bSubEntry( false ) { } 257 ExceptionDisplayInfo( SQLExceptionInfo::TYPE _eType ) : eType( _eType ), bSubEntry( false ) { } 258 }; 259 260 static bool lcl_hasDetails( const ExceptionDisplayInfo& _displayInfo ) 261 { 262 return ( _displayInfo.sErrorCode.Len() ) 263 || ( _displayInfo.sSQLState.Len() 264 && !_displayInfo.sSQLState.EqualsAscii( "S1000" ) 265 ); 266 } 267 268 typedef ::std::vector< ExceptionDisplayInfo > ExceptionDisplayChain; 269 270 //------------------------------------------------------------------------------ 271 /// strips the [OOoBase] vendor identifier from the given error message, if applicable 272 ::rtl::OUString lcl_stripOOoBaseVendor( const ::rtl::OUString& _rErrorMessage ) 273 { 274 ::rtl::OUString sErrorMessage( _rErrorMessage ); 275 276 const ::rtl::OUString sVendorIdentifier( ::connectivity::SQLError::getMessagePrefix() ); 277 if ( sErrorMessage.indexOf( sVendorIdentifier ) == 0 ) 278 { 279 // characters to strip 280 sal_Int32 nStripLen( sVendorIdentifier.getLength() ); 281 // usually, there should be a whitespace between the vendor and the real message 282 while ( ( sErrorMessage.getLength() > nStripLen ) 283 && ( sErrorMessage[nStripLen] == ' ' ) 284 ) 285 ++nStripLen; 286 sErrorMessage = sErrorMessage.copy( nStripLen ); 287 } 288 289 return sErrorMessage; 290 } 291 292 //------------------------------------------------------------------------------ 293 void lcl_buildExceptionChain( const SQLExceptionInfo& _rErrorInfo, const ProviderFactory& _rFactory, ExceptionDisplayChain& _out_rChain ) 294 { 295 { 296 ExceptionDisplayChain empty; 297 _out_rChain.swap( empty ); 298 } 299 300 SQLExceptionIteratorHelper iter( _rErrorInfo ); 301 while ( iter.hasMoreElements() ) 302 { 303 // current chain element 304 SQLExceptionInfo aCurrentElement; 305 iter.next( aCurrentElement ); 306 307 const SQLException* pCurrentError = (const SQLException*)aCurrentElement; 308 DBG_ASSERT( pCurrentError, "lcl_buildExceptionChain: iterator failure!" ); 309 // hasMoreElements should not have returned <TRUE/> in this case 310 311 ExceptionDisplayInfo aDisplayInfo( aCurrentElement.getType() ); 312 313 aDisplayInfo.sMessage = pCurrentError->Message.trim(); 314 aDisplayInfo.sSQLState = pCurrentError->SQLState; 315 if ( pCurrentError->ErrorCode ) 316 aDisplayInfo.sErrorCode = String::CreateFromInt32( pCurrentError->ErrorCode ); 317 318 if ( !aDisplayInfo.sMessage.Len() 319 && !lcl_hasDetails( aDisplayInfo ) 320 ) 321 { 322 OSL_ENSURE( false, "lcl_buildExceptionChain: useles exception: no state, no error code, no message!" ); 323 continue; 324 } 325 326 aDisplayInfo.pImageProvider = _rFactory.getImageProvider( aCurrentElement.getType() ); 327 aDisplayInfo.pLabelProvider = _rFactory.getLabelProvider( aCurrentElement.getType(), false ); 328 329 _out_rChain.push_back( aDisplayInfo ); 330 331 if ( aCurrentElement.getType() == SQLExceptionInfo::SQL_CONTEXT ) 332 { 333 const SQLContext* pContext = (const SQLContext*)aCurrentElement; 334 if ( pContext->Details.getLength() ) 335 { 336 ExceptionDisplayInfo aSubInfo( aCurrentElement.getType() ); 337 338 aSubInfo.sMessage = pContext->Details; 339 aSubInfo.pImageProvider = _rFactory.getImageProvider( aCurrentElement.getType() ); 340 aSubInfo.pLabelProvider = _rFactory.getLabelProvider( aCurrentElement.getType(), true ); 341 aSubInfo.bSubEntry = true; 342 343 _out_rChain.push_back( aSubInfo ); 344 } 345 } 346 } 347 } 348 349 //------------------------------------------------------------------------------ 350 void lcl_insertExceptionEntry( SvTreeListBox& _rList, bool _bHiContrast, size_t _nElementPos, const ExceptionDisplayInfo& _rEntry ) 351 { 352 Image aEntryImage( _rEntry.pImageProvider->getImage( _bHiContrast ) ); 353 SvLBoxEntry* pListEntry = 354 _rList.InsertEntry( _rEntry.pLabelProvider->getLabel(), aEntryImage, aEntryImage ); 355 pListEntry->SetUserData( reinterpret_cast< void* >( _nElementPos ) ); 356 } 357 } 358 359 //============================================================================== 360 class OExceptionChainDialog : public ModalDialog 361 { 362 FixedLine m_aFrame; 363 FixedText m_aListLabel; 364 SvTreeListBox m_aExceptionList; 365 FixedText m_aDescLabel; 366 MultiLineEdit m_aExceptionText; 367 OKButton m_aOK; 368 369 String m_sStatusLabel; 370 String m_sErrorCodeLabel; 371 372 ExceptionDisplayChain m_aExceptions; 373 374 public: 375 OExceptionChainDialog( Window* pParent, const ExceptionDisplayChain& _rExceptions ); 376 ~OExceptionChainDialog(); 377 378 protected: 379 DECL_LINK(OnExceptionSelected, void*); 380 }; 381 382 DBG_NAME(OExceptionChainDialog) 383 //------------------------------------------------------------------------------ 384 OExceptionChainDialog::OExceptionChainDialog( Window* pParent, const ExceptionDisplayChain& _rExceptions ) 385 :ModalDialog(pParent, ModuleRes(DLG_SQLEXCEPTIONCHAIN)) 386 ,m_aFrame (this, ModuleRes(FL_DETAILS)) 387 ,m_aListLabel (this, ModuleRes(FT_ERRORLIST)) 388 ,m_aExceptionList (this, ModuleRes(CTL_ERRORLIST)) 389 ,m_aDescLabel (this, ModuleRes(FT_DESCRIPTION)) 390 ,m_aExceptionText (this, ModuleRes(ME_DESCRIPTION)) 391 ,m_aOK (this, ModuleRes(PB_OK)) 392 ,m_aExceptions( _rExceptions ) 393 { 394 DBG_CTOR(OExceptionChainDialog,NULL); 395 396 m_sStatusLabel = String( ModuleRes( STR_EXCEPTION_STATUS ) ); 397 m_sErrorCodeLabel = String( ModuleRes( STR_EXCEPTION_ERRORCODE ) ); 398 399 FreeResource(); 400 401 m_aExceptionList.SetSelectionMode(SINGLE_SELECTION); 402 m_aExceptionList.SetDragDropMode(0); 403 m_aExceptionList.EnableInplaceEditing(sal_False); 404 m_aExceptionList.SetStyle(m_aExceptionList.GetStyle() | WB_HASLINES | WB_HASBUTTONS | WB_HASBUTTONSATROOT | WB_HSCROLL); 405 406 m_aExceptionList.SetSelectHdl(LINK(this, OExceptionChainDialog, OnExceptionSelected)); 407 m_aExceptionList.SetNodeDefaultImages( ); 408 m_aExceptionText.SetReadOnly(sal_True); 409 410 bool bHave22018 = false; 411 bool bHiContrast = isHiContrast( this ); 412 size_t elementPos = 0; 413 414 for ( ExceptionDisplayChain::const_iterator loop = m_aExceptions.begin(); 415 loop != m_aExceptions.end(); 416 ++loop, ++elementPos 417 ) 418 { 419 lcl_insertExceptionEntry( m_aExceptionList, bHiContrast, elementPos, *loop ); 420 bHave22018 = loop->sSQLState.EqualsAscii( "22018" ); 421 } 422 423 // if the error has the code 22018, then add an additional explanation 424 // #i24021# / 2004-10-14 / frank.schoenheit@sun.com 425 if ( bHave22018 ) 426 { 427 ProviderFactory aProviderFactory; 428 429 ExceptionDisplayInfo aInfo22018; 430 aInfo22018.sMessage = String( ModuleRes( STR_EXPLAN_STRINGCONVERSION_ERROR ) ); 431 aInfo22018.pLabelProvider = aProviderFactory.getLabelProvider( SQLExceptionInfo::SQL_CONTEXT, false ); 432 aInfo22018.pImageProvider = aProviderFactory.getImageProvider( SQLExceptionInfo::SQL_CONTEXT ); 433 m_aExceptions.push_back( aInfo22018 ); 434 435 lcl_insertExceptionEntry( m_aExceptionList, bHiContrast, m_aExceptions.size() - 1, aInfo22018 ); 436 } 437 } 438 439 //------------------------------------------------------------------------------ 440 OExceptionChainDialog::~OExceptionChainDialog() 441 { 442 DBG_DTOR(OExceptionChainDialog,NULL); 443 } 444 445 //------------------------------------------------------------------------------ 446 IMPL_LINK(OExceptionChainDialog, OnExceptionSelected, void*, EMPTYARG) 447 { 448 SvLBoxEntry* pSelected = m_aExceptionList.FirstSelected(); 449 DBG_ASSERT(!pSelected || !m_aExceptionList.NextSelected(pSelected), "OExceptionChainDialog::OnExceptionSelected : multi selection ?"); 450 451 String sText; 452 453 if ( pSelected ) 454 { 455 size_t pos = reinterpret_cast< size_t >( pSelected->GetUserData() ); 456 const ExceptionDisplayInfo& aExceptionInfo( m_aExceptions[ pos ] ); 457 458 if ( aExceptionInfo.sSQLState.Len() ) 459 { 460 sText += m_sStatusLabel; 461 sText.AppendAscii(": "); 462 sText += aExceptionInfo.sSQLState; 463 sText.AppendAscii("\n"); 464 } 465 466 if ( aExceptionInfo.sErrorCode.Len() ) 467 { 468 sText += m_sErrorCodeLabel; 469 sText.AppendAscii(": "); 470 sText += aExceptionInfo.sErrorCode; 471 sText.AppendAscii("\n"); 472 } 473 474 if ( sText.Len() ) 475 sText.AppendAscii( "\n" ); 476 477 sText += aExceptionInfo.sMessage; 478 } 479 480 m_aExceptionText.SetText(sText); 481 482 return 0L; 483 } 484 485 //============================================================================== 486 //= SQLMessageBox_Impl 487 //============================================================================== 488 struct SQLMessageBox_Impl 489 { 490 ExceptionDisplayChain aDisplayInfo; 491 492 SQLMessageBox_Impl( const SQLExceptionInfo& _rExceptionInfo ) 493 { 494 // transform the exception chain to a form more suitable for displaying it here 495 ProviderFactory aProviderFactory; 496 lcl_buildExceptionChain( _rExceptionInfo, aProviderFactory, aDisplayInfo ); 497 } 498 }; 499 500 //------------------------------------------------------------------------------ 501 namespace 502 { 503 ::rtl::OUString lcl_getProductName() 504 { 505 ::rtl::OUString sProductName; 506 OSL_VERIFY( ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME ) >>= sProductName ); 507 return sProductName; 508 } 509 510 void lcl_positionInAppFont( const Window& _rParent, Window& _rChild, long _nX, long _nY, long _Width, long _Height ) 511 { 512 Point aPos = _rParent.LogicToPixel( Point( _nX, _nY ), MAP_APPFONT ); 513 Size aSize = _rParent.LogicToPixel( Size( _Width, _Height ), MAP_APPFONT ); 514 _rChild.SetPosSizePixel( aPos, aSize ); 515 } 516 517 void lcl_addButton( ButtonDialog& _rDialog, StandardButtonType _eType, bool _bDefault ) 518 { 519 sal_uInt16 nButtonID = 0; 520 switch ( _eType ) 521 { 522 case BUTTON_YES: nButtonID = BUTTONID_YES; break; 523 case BUTTON_NO: nButtonID = BUTTONID_NO; break; 524 case BUTTON_OK: nButtonID = BUTTONID_OK; break; 525 case BUTTON_CANCEL: nButtonID = BUTTONID_CANCEL; break; 526 case BUTTON_RETRY: nButtonID = BUTTONID_RETRY; break; 527 case BUTTON_HELP: nButtonID = BUTTONID_HELP; break; 528 default: 529 OSL_ENSURE( false, "lcl_addButton: invalid button id!" ); 530 break; 531 } 532 _rDialog.AddButton( _eType, nButtonID, _bDefault ? BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON : 0 ); 533 } 534 } 535 536 //------------------------------------------------------------------------------ 537 void OSQLMessageBox::impl_positionControls() 538 { 539 OSL_PRECOND( !m_pImpl->aDisplayInfo.empty(), "OSQLMessageBox::impl_positionControls: nothing to display at all?" ); 540 541 542 if ( m_pImpl->aDisplayInfo.empty() ) 543 return; 544 const ExceptionDisplayInfo* pSecondInfo = NULL; 545 546 const ExceptionDisplayInfo& rFirstInfo = *m_pImpl->aDisplayInfo.begin(); 547 if ( m_pImpl->aDisplayInfo.size() > 1 ) 548 pSecondInfo = &m_pImpl->aDisplayInfo[1]; 549 String sPrimary, sSecondary; 550 sPrimary = rFirstInfo.sMessage; 551 // one or two texts to display? 552 if ( pSecondInfo ) 553 { 554 // we show two elements in the main dialog if and only if one of 555 // - the first element in the chain is an SQLContext, and the second 556 // element denotes its sub entry 557 // - the first and the second element are both independent (i.e. the second 558 // is no sub entry), and none of them is a context. 559 bool bFirstElementIsContext = ( rFirstInfo.eType == SQLExceptionInfo::SQL_CONTEXT ); 560 bool bSecondElementIsContext = ( pSecondInfo->eType == SQLExceptionInfo::SQL_CONTEXT ); 561 562 if ( bFirstElementIsContext && pSecondInfo->bSubEntry ) 563 sSecondary = pSecondInfo->sMessage; 564 if ( !bFirstElementIsContext && !bSecondElementIsContext ) 565 sSecondary = pSecondInfo->sMessage; 566 } 567 568 // image 569 lcl_positionInAppFont( *this, m_aInfoImage, OUTER_MARGIN, OUTER_MARGIN, IMAGE_SIZE, IMAGE_SIZE ); 570 m_aInfoImage.Show(); 571 572 // primary text 573 lcl_positionInAppFont( *this, m_aTitle, TEXT_POS_X, OUTER_MARGIN, DIALOG_WIDTH - TEXT_POS_X - 2 * OUTER_MARGIN, 16 ); 574 sPrimary = lcl_stripOOoBaseVendor( sPrimary ); 575 m_aTitle.SetText( sPrimary ); 576 m_aTitle.Show(); 577 578 Rectangle aPrimaryRect( m_aTitle.GetPosPixel(), m_aTitle.GetSizePixel() ); 579 580 // secondary text (if applicable) 581 m_aMessage.SetStyle( m_aMessage.GetStyle() | WB_NOLABEL ); 582 sSecondary = lcl_stripOOoBaseVendor( sSecondary ); 583 m_aMessage.SetText( sSecondary ); 584 585 lcl_positionInAppFont( *this, m_aMessage, TEXT_POS_X, OUTER_MARGIN + 16 + 3, DIALOG_WIDTH - TEXT_POS_X - 2 * OUTER_MARGIN, 8 ); 586 Rectangle aSecondaryRect( m_aMessage.GetPosPixel(), m_aMessage.GetSizePixel() ); 587 588 bool bHaveSecondaryText = sSecondary.Len() != 0; 589 590 // determine which space the secondary text would occupy 591 if ( bHaveSecondaryText ) 592 aSecondaryRect = GetTextRect( aSecondaryRect, sSecondary, TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE | TEXT_DRAW_LEFT ); 593 else 594 aSecondaryRect.Bottom() = aSecondaryRect.Top() - 1; 595 596 // adjust secondary control height accordingly 597 m_aMessage.SetSizePixel( aSecondaryRect.GetSize() ); 598 m_aMessage.Show( aSecondaryRect.GetHeight() > 0 ); 599 600 // if there's no secondary text ... 601 if ( !bHaveSecondaryText ) 602 { // then give the primary text as much horizontal space as it needs 603 Rectangle aSuggestedRect( GetTextRect( aPrimaryRect, sPrimary, TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE | TEXT_DRAW_CENTER ) ); 604 aPrimaryRect.Right() = aPrimaryRect.Left() + aSuggestedRect.GetWidth(); 605 aPrimaryRect.Bottom() = aPrimaryRect.Top() + aSuggestedRect.GetHeight(); 606 // and center it horizontally 607 m_aTitle.SetStyle( ( m_aTitle.GetStyle() & ~WB_LEFT ) | WB_CENTER ); 608 609 Rectangle aInfoRect( m_aInfoImage.GetPosPixel(), m_aInfoImage.GetSizePixel() ); 610 // also, if it's not as high as the image ... 611 if ( aPrimaryRect.GetHeight() < m_aInfoImage.GetSizePixel().Height() ) 612 { // ... make it fit the image height 613 aPrimaryRect.Bottom() += aInfoRect.GetHeight() - aPrimaryRect.GetHeight(); 614 // and center it vertically 615 m_aTitle.SetStyle( m_aTitle.GetStyle() | WB_VCENTER ); 616 } 617 else 618 { // ... otherwise, center the image vertically, relative to the primary text 619 aInfoRect.Move( 0, ( aPrimaryRect.GetHeight() - aInfoRect.GetHeight() ) / 2 ); 620 m_aInfoImage.SetPosSizePixel( aInfoRect.TopLeft(), aInfoRect.GetSize() ); 621 } 622 623 m_aTitle.SetPosSizePixel( aPrimaryRect.TopLeft(), aPrimaryRect.GetSize() ); 624 } 625 626 // adjust dialog size accordingly 627 const Rectangle& rBottomTextRect( bHaveSecondaryText ? aSecondaryRect : aPrimaryRect ); 628 Size aBorderSize = LogicToPixel( Size( OUTER_MARGIN, OUTER_MARGIN ), MAP_APPFONT ); 629 Size aDialogSize( LogicToPixel( Size( DIALOG_WIDTH, 30 ), MAP_APPFONT ) ); 630 aDialogSize.Height() = rBottomTextRect.Bottom() + aBorderSize.Height(); 631 aDialogSize.Width() = aPrimaryRect.Right() + aBorderSize.Width(); 632 633 SetSizePixel( aDialogSize ); 634 SetPageSizePixel( aDialogSize ); 635 } 636 637 //------------------------------------------------------------------------------ 638 void OSQLMessageBox::impl_initImage( MessageType _eImage ) 639 { 640 switch (_eImage) 641 { 642 default: 643 DBG_ERROR( "OSQLMessageBox::impl_initImage: unsupported image type!" ); 644 645 case Info: 646 m_aInfoImage.SetImage(InfoBox::GetStandardImage()); 647 break; 648 case Warning: 649 m_aInfoImage.SetImage(WarningBox::GetStandardImage()); 650 break; 651 case Error: 652 m_aInfoImage.SetImage(ErrorBox::GetStandardImage()); 653 break; 654 case Query: 655 m_aInfoImage.SetImage(QueryBox::GetStandardImage()); 656 break; 657 } 658 } 659 660 //------------------------------------------------------------------------------ 661 void OSQLMessageBox::impl_createStandardButtons( WinBits _nStyle ) 662 { 663 if ( _nStyle & WB_YES_NO_CANCEL ) 664 { 665 lcl_addButton( *this, BUTTON_YES, ( _nStyle & WB_DEF_YES ) != 0 ); 666 lcl_addButton( *this, BUTTON_NO, ( _nStyle & WB_DEF_NO ) != 0 ); 667 lcl_addButton( *this, BUTTON_CANCEL, ( _nStyle & WB_DEF_CANCEL ) != 0 ); 668 } 669 else if ( _nStyle & WB_OK_CANCEL ) 670 { 671 lcl_addButton( *this, BUTTON_OK, ( _nStyle & WB_DEF_OK ) != 0 ); 672 lcl_addButton( *this, BUTTON_CANCEL, ( _nStyle & WB_DEF_CANCEL ) != 0 ); 673 } 674 else if ( _nStyle & WB_YES_NO ) 675 { 676 lcl_addButton( *this, BUTTON_YES, ( _nStyle & WB_DEF_YES ) != 0 ); 677 lcl_addButton( *this, BUTTON_NO, ( _nStyle & WB_DEF_NO ) != 0 ); 678 } 679 else if ( _nStyle & WB_RETRY_CANCEL ) 680 { 681 lcl_addButton( *this, BUTTON_RETRY, ( _nStyle & WB_DEF_RETRY ) != 0 ); 682 lcl_addButton( *this, BUTTON_CANCEL, ( _nStyle & WB_DEF_CANCEL ) != 0 ); 683 } 684 else 685 { 686 OSL_ENSURE( WB_OK & _nStyle, "OSQLMessageBox::impl_createStandardButtons: unsupported dialog style requested!" ); 687 AddButton( BUTTON_OK, BUTTONID_OK, BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON ); 688 } 689 690 if ( m_sHelpURL.getLength() ) 691 { 692 lcl_addButton( *this, BUTTON_HELP, false ); 693 694 rtl::OUString aTmp; 695 INetURLObject aHID( m_sHelpURL ); 696 if ( aHID.GetProtocol() == INET_PROT_HID ) 697 aTmp = aHID.GetURLPath(); 698 else 699 aTmp = m_sHelpURL; 700 701 SetHelpId( rtl::OUStringToOString( aTmp, RTL_TEXTENCODING_UTF8 ) ); 702 } 703 } 704 705 //------------------------------------------------------------------------------ 706 void OSQLMessageBox::impl_addDetailsButton() 707 { 708 size_t nFirstPageVisible = m_aMessage.IsVisible() ? 2 : 1; 709 710 bool bMoreDetailsAvailable = m_pImpl->aDisplayInfo.size() > nFirstPageVisible; 711 if ( !bMoreDetailsAvailable ) 712 { 713 // even if the text fits into what we can display, we might need to details button 714 // if there is more non-trivial information in the errors than the mere messages 715 for ( ExceptionDisplayChain::const_iterator error = m_pImpl->aDisplayInfo.begin(); 716 error != m_pImpl->aDisplayInfo.end(); 717 ++error 718 ) 719 { 720 if ( lcl_hasDetails( *error ) ) 721 { 722 bMoreDetailsAvailable = true; 723 break; 724 } 725 } 726 } 727 728 if ( bMoreDetailsAvailable ) 729 { 730 AddButton( BUTTON_MORE, BUTTONID_MORE, 0 ); 731 PushButton* pButton = GetPushButton( BUTTONID_MORE ); 732 OSL_ENSURE( pButton, "OSQLMessageBox::impl_addDetailsButton: just added this button, why isn't it there?" ); 733 pButton->SetClickHdl( LINK( this, OSQLMessageBox, ButtonClickHdl ) ); 734 pButton->SetUniqueId( UID_SQLERROR_BUTTONMORE ); 735 } 736 } 737 738 //------------------------------------------------------------------------------ 739 void OSQLMessageBox::Construct( WinBits _nStyle, MessageType _eImage ) 740 { 741 // Changed as per BugID 79541 Branding/Configuration 742 String sDialogTitle( lcl_getProductName() ); 743 SetText( sDialogTitle.AppendAscii( " Base" ) ); 744 745 // position and size the controls and the dialog, depending on whether we have one or two texts to display 746 impl_positionControls(); 747 748 // init the image 749 MessageType eType( _eImage ); 750 if ( eType == AUTO ) 751 { 752 switch ( m_pImpl->aDisplayInfo[0].eType ) 753 { 754 case SQLExceptionInfo::SQL_EXCEPTION: eType = Error; break; 755 case SQLExceptionInfo::SQL_WARNING: eType = Warning; break; 756 case SQLExceptionInfo::SQL_CONTEXT: eType = Info; break; 757 default: OSL_ENSURE( false, "OSQLMessageBox::Construct: invalid type!" ); 758 } 759 } 760 impl_initImage( eType ); 761 762 // create buttons 763 impl_createStandardButtons( _nStyle ); 764 impl_addDetailsButton(); 765 } 766 767 //------------------------------------------------------------------------------ 768 OSQLMessageBox::OSQLMessageBox(Window* _pParent, const SQLExceptionInfo& _rException, WinBits _nStyle, const ::rtl::OUString& _rHelpURL ) 769 :ButtonDialog( _pParent, WB_HORZ | WB_STDDIALOG ) 770 ,m_aInfoImage( this ) 771 ,m_aTitle( this, WB_WORDBREAK | WB_LEFT ) 772 ,m_aMessage( this, WB_WORDBREAK | WB_LEFT ) 773 ,m_sHelpURL( _rHelpURL ) 774 ,m_pImpl( new SQLMessageBox_Impl( _rException ) ) 775 { 776 Construct( _nStyle, AUTO ); 777 } 778 779 //------------------------------------------------------------------------------ 780 OSQLMessageBox::OSQLMessageBox( Window* _pParent, const UniString& _rTitle, const UniString& _rMessage, WinBits _nStyle, MessageType _eType, const ::dbtools::SQLExceptionInfo* _pAdditionalErrorInfo ) 781 :ButtonDialog( _pParent, WB_HORZ | WB_STDDIALOG ) 782 ,m_aInfoImage( this ) 783 ,m_aTitle( this, WB_WORDBREAK | WB_LEFT ) 784 ,m_aMessage( this, WB_WORDBREAK | WB_LEFT ) 785 { 786 SQLContext aError; 787 aError.Message = _rTitle; 788 aError.Details = _rMessage; 789 if ( _pAdditionalErrorInfo ) 790 aError.NextException = _pAdditionalErrorInfo->get(); 791 792 m_pImpl.reset( new SQLMessageBox_Impl( SQLExceptionInfo( aError ) ) ); 793 794 Construct( _nStyle, _eType ); 795 } 796 797 //-------------------------------------------------------------------------- 798 OSQLMessageBox::~OSQLMessageBox() 799 { 800 } 801 802 //-------------------------------------------------------------------------- 803 IMPL_LINK( OSQLMessageBox, ButtonClickHdl, Button *, /*pButton*/ ) 804 { 805 OExceptionChainDialog aDlg( this, m_pImpl->aDisplayInfo ); 806 aDlg.Execute(); 807 return 0; 808 } 809 810 //================================================================== 811 // OSQLWarningBox 812 //================================================================== 813 OSQLWarningBox::OSQLWarningBox( Window* _pParent, const UniString& _rMessage, WinBits _nStyle, 814 const ::dbtools::SQLExceptionInfo* _pAdditionalErrorInfo ) 815 :OSQLMessageBox( _pParent, String( ModuleRes( STR_STAT_WARNING ) ), _rMessage, _nStyle, OSQLMessageBox::Warning, _pAdditionalErrorInfo ) 816 { 817 } 818 819 //......................................................................... 820 } // namespace dbaui 821 //......................................................................... 822 823