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