| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_dbaccess.hxx" |
| |
| #ifndef _DBAUI_SQLMESSAGE_HXX_ |
| #include "sqlmessage.hxx" |
| #endif |
| #ifndef _DBU_DLG_HRC_ |
| #include "dbu_dlg.hrc" |
| #endif |
| #ifndef _DBAUI_SQLMESSAGE_HRC_ |
| #include "sqlmessage.hrc" |
| #endif |
| #ifndef _COM_SUN_STAR_SDBC_SQLEXCEPTION_HPP_ |
| #include <com/sun/star/sdbc/SQLException.hpp> |
| #endif |
| #ifndef _COM_SUN_STAR_SDB_SQLCONTEXT_HPP_ |
| #include <com/sun/star/sdb/SQLContext.hpp> |
| #endif |
| #ifndef _SV_GROUP_HXX //autogen |
| #include <vcl/fixed.hxx> |
| #endif |
| #ifndef _SVTREEBOX_HXX |
| #include <svtools/svtreebx.hxx> |
| #endif |
| #ifndef _SVEDIT_HXX //autogen |
| #include <svtools/svmedit.hxx> |
| #endif |
| #ifndef _DBHELPER_DBEXCEPTION_HXX_ |
| #include <connectivity/dbexception.hxx> |
| #endif |
| #ifndef CONNECTIVITY_SQLERROR_HXX |
| #include <connectivity/sqlerror.hxx> |
| #endif |
| #ifndef _SV_MSGBOX_HXX //autogen |
| #include <vcl/msgbox.hxx> |
| #endif |
| #ifndef _UTL_CONFIGMGR_HXX_ |
| #include <unotools/configmgr.hxx> |
| #endif |
| #ifndef _SFX_SFXUNO_HXX |
| #include <sfx2/sfxuno.hxx> |
| #endif |
| #ifndef _DBA_DBACCESS_HELPID_HRC_ |
| #include "dbaccess_helpid.hrc" |
| #endif |
| #ifndef DBAUI_TOOLS_HXX |
| #include "UITools.hxx" |
| #endif |
| #ifndef _DBAUI_MODULE_DBU_HXX_ |
| #include "moduledbu.hxx" |
| #endif |
| |
| #include <tools/urlobj.hxx> |
| |
| #define BUTTONID_MORE BUTTONID_RETRY + 1 |
| |
| #define DIALOG_WIDTH 220 |
| #define OUTER_MARGIN 6 |
| #define IMAGE_SIZE 20 |
| #define INNER_PADDING 3 |
| #define TEXT_POS_X ( OUTER_MARGIN + IMAGE_SIZE + INNER_PADDING ) |
| |
| using namespace dbtools; |
| using namespace com::sun::star::uno; |
| using namespace com::sun::star::sdb; |
| using namespace com::sun::star::sdbc; |
| |
| //......................................................................... |
| namespace dbaui |
| { |
| //......................................................................... |
| |
| namespace |
| { |
| //------------------------------------------------------------------------------ |
| class IImageProvider |
| { |
| public: |
| virtual Image getImage( bool _highContrast ) const = 0; |
| |
| virtual ~IImageProvider() { } |
| }; |
| |
| //------------------------------------------------------------------------------ |
| class ILabelProvider |
| { |
| public: |
| virtual String getLabel() const = 0; |
| |
| virtual ~ILabelProvider() { }; |
| }; |
| |
| //------------------------------------------------------------------------------ |
| class ImageProvider : public IImageProvider |
| { |
| private: |
| sal_uInt16 m_defaultImageID; |
| sal_uInt16 m_highContrastImageID; |
| |
| mutable Image m_defaultImage; |
| mutable Image m_highContrastImage; |
| |
| public: |
| ImageProvider( sal_uInt16 _defaultImageID, sal_uInt16 _highContrastImageID ) |
| :m_defaultImageID( _defaultImageID ) |
| ,m_highContrastImageID( _highContrastImageID ) |
| { |
| } |
| |
| virtual Image getImage( bool _highContrast ) const |
| { |
| if ( _highContrast ) |
| { |
| if ( !m_highContrastImage ) |
| m_highContrastImage = Image( ModuleRes( m_highContrastImageID ) ); |
| return m_highContrastImage; |
| } |
| |
| if ( !m_defaultImage ) |
| m_defaultImage = Image( ModuleRes( m_defaultImageID ) ); |
| return m_defaultImage; |
| } |
| }; |
| |
| //------------------------------------------------------------------------------ |
| class LabelProvider : public ILabelProvider |
| { |
| private: |
| String m_label; |
| public: |
| LabelProvider( sal_uInt16 _labelResourceID ) |
| :m_label( ModuleRes( _labelResourceID ) ) |
| { |
| } |
| |
| virtual String getLabel() const |
| { |
| return m_label; |
| } |
| }; |
| |
| //------------------------------------------------------------------------------ |
| class ProviderFactory |
| { |
| private: |
| mutable ::boost::shared_ptr< IImageProvider > m_pErrorImage; |
| mutable ::boost::shared_ptr< IImageProvider > m_pWarningsImage; |
| mutable ::boost::shared_ptr< IImageProvider > m_pInfoImage; |
| mutable ::boost::shared_ptr< ILabelProvider > m_pErrorLabel; |
| mutable ::boost::shared_ptr< ILabelProvider > m_pWarningsLabel; |
| mutable ::boost::shared_ptr< ILabelProvider > m_pInfoLabel; |
| |
| public: |
| ProviderFactory() |
| { |
| } |
| |
| ::boost::shared_ptr< IImageProvider > getImageProvider( SQLExceptionInfo::TYPE _eType ) const |
| { |
| ::boost::shared_ptr< IImageProvider >* ppProvider( &m_pErrorImage ); |
| sal_uInt16 nNormalImageID( BMP_EXCEPTION_ERROR ); |
| sal_uInt16 nHCImageID( BMP_EXCEPTION_ERROR_SCH ); |
| |
| switch ( _eType ) |
| { |
| case SQLExceptionInfo::SQL_WARNING: |
| ppProvider = &m_pWarningsImage; |
| nNormalImageID = BMP_EXCEPTION_WARNING; |
| nHCImageID = BMP_EXCEPTION_WARNING_SCH; |
| break; |
| |
| case SQLExceptionInfo::SQL_CONTEXT: |
| ppProvider = &m_pInfoImage; |
| nNormalImageID = BMP_EXCEPTION_INFO; |
| nHCImageID = BMP_EXCEPTION_INFO_SCH; |
| break; |
| |
| default: |
| break; |
| } |
| |
| if ( !ppProvider->get() ) |
| ppProvider->reset( new ImageProvider( nNormalImageID, nHCImageID ) ); |
| return *ppProvider; |
| } |
| |
| ::boost::shared_ptr< ILabelProvider > getLabelProvider( SQLExceptionInfo::TYPE _eType, bool _bSubLabel ) const |
| { |
| ::boost::shared_ptr< ILabelProvider >* ppProvider( &m_pErrorLabel ); |
| sal_uInt16 nLabelID( STR_EXCEPTION_ERROR ); |
| |
| switch ( _eType ) |
| { |
| case SQLExceptionInfo::SQL_WARNING: |
| ppProvider = &m_pWarningsLabel; |
| nLabelID = STR_EXCEPTION_WARNING; |
| break; |
| |
| case SQLExceptionInfo::SQL_CONTEXT: |
| ppProvider = &m_pInfoLabel; |
| nLabelID = _bSubLabel ? STR_EXCEPTION_DETAILS : STR_EXCEPTION_INFO; |
| break; |
| default: |
| break; |
| } |
| |
| if ( !ppProvider->get() ) |
| ppProvider->reset( new LabelProvider( nLabelID ) ); |
| return *ppProvider; |
| } |
| |
| }; |
| |
| //------------------------------------------------------------------------------ |
| /// a stripped version of the SQLException, packed for displaying |
| struct ExceptionDisplayInfo |
| { |
| SQLExceptionInfo::TYPE eType; |
| |
| ::boost::shared_ptr< IImageProvider > pImageProvider; |
| ::boost::shared_ptr< ILabelProvider > pLabelProvider; |
| |
| bool bSubEntry; |
| |
| String sMessage; |
| String sSQLState; |
| String sErrorCode; |
| |
| ExceptionDisplayInfo() : eType( SQLExceptionInfo::UNDEFINED ), bSubEntry( false ) { } |
| ExceptionDisplayInfo( SQLExceptionInfo::TYPE _eType ) : eType( _eType ), bSubEntry( false ) { } |
| }; |
| |
| static bool lcl_hasDetails( const ExceptionDisplayInfo& _displayInfo ) |
| { |
| return ( _displayInfo.sErrorCode.Len() ) |
| || ( _displayInfo.sSQLState.Len() |
| && !_displayInfo.sSQLState.EqualsAscii( "S1000" ) |
| ); |
| } |
| |
| typedef ::std::vector< ExceptionDisplayInfo > ExceptionDisplayChain; |
| |
| //------------------------------------------------------------------------------ |
| /// strips the [OOoBase] vendor identifier from the given error message, if applicable |
| ::rtl::OUString lcl_stripOOoBaseVendor( const ::rtl::OUString& _rErrorMessage ) |
| { |
| ::rtl::OUString sErrorMessage( _rErrorMessage ); |
| |
| const ::rtl::OUString sVendorIdentifier( ::connectivity::SQLError::getMessagePrefix() ); |
| if ( sErrorMessage.indexOf( sVendorIdentifier ) == 0 ) |
| { |
| // characters to strip |
| sal_Int32 nStripLen( sVendorIdentifier.getLength() ); |
| // usually, there should be a whitespace between the vendor and the real message |
| while ( ( sErrorMessage.getLength() > nStripLen ) |
| && ( sErrorMessage[nStripLen] == ' ' ) |
| ) |
| ++nStripLen; |
| sErrorMessage = sErrorMessage.copy( nStripLen ); |
| } |
| |
| return sErrorMessage; |
| } |
| |
| //------------------------------------------------------------------------------ |
| void lcl_buildExceptionChain( const SQLExceptionInfo& _rErrorInfo, const ProviderFactory& _rFactory, ExceptionDisplayChain& _out_rChain ) |
| { |
| { |
| ExceptionDisplayChain empty; |
| _out_rChain.swap( empty ); |
| } |
| |
| SQLExceptionIteratorHelper iter( _rErrorInfo ); |
| while ( iter.hasMoreElements() ) |
| { |
| // current chain element |
| SQLExceptionInfo aCurrentElement; |
| iter.next( aCurrentElement ); |
| |
| const SQLException* pCurrentError = (const SQLException*)aCurrentElement; |
| DBG_ASSERT( pCurrentError, "lcl_buildExceptionChain: iterator failure!" ); |
| // hasMoreElements should not have returned <TRUE/> in this case |
| |
| ExceptionDisplayInfo aDisplayInfo( aCurrentElement.getType() ); |
| |
| aDisplayInfo.sMessage = pCurrentError->Message.trim(); |
| aDisplayInfo.sSQLState = pCurrentError->SQLState; |
| if ( pCurrentError->ErrorCode ) |
| aDisplayInfo.sErrorCode = String::CreateFromInt32( pCurrentError->ErrorCode ); |
| |
| if ( !aDisplayInfo.sMessage.Len() |
| && !lcl_hasDetails( aDisplayInfo ) |
| ) |
| { |
| OSL_ENSURE( false, "lcl_buildExceptionChain: useles exception: no state, no error code, no message!" ); |
| continue; |
| } |
| |
| aDisplayInfo.pImageProvider = _rFactory.getImageProvider( aCurrentElement.getType() ); |
| aDisplayInfo.pLabelProvider = _rFactory.getLabelProvider( aCurrentElement.getType(), false ); |
| |
| _out_rChain.push_back( aDisplayInfo ); |
| |
| if ( aCurrentElement.getType() == SQLExceptionInfo::SQL_CONTEXT ) |
| { |
| const SQLContext* pContext = (const SQLContext*)aCurrentElement; |
| if ( pContext->Details.getLength() ) |
| { |
| ExceptionDisplayInfo aSubInfo( aCurrentElement.getType() ); |
| |
| aSubInfo.sMessage = pContext->Details; |
| aSubInfo.pImageProvider = _rFactory.getImageProvider( aCurrentElement.getType() ); |
| aSubInfo.pLabelProvider = _rFactory.getLabelProvider( aCurrentElement.getType(), true ); |
| aSubInfo.bSubEntry = true; |
| |
| _out_rChain.push_back( aSubInfo ); |
| } |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void lcl_insertExceptionEntry( SvTreeListBox& _rList, bool _bHiContrast, size_t _nElementPos, const ExceptionDisplayInfo& _rEntry ) |
| { |
| Image aEntryImage( _rEntry.pImageProvider->getImage( _bHiContrast ) ); |
| SvLBoxEntry* pListEntry = |
| _rList.InsertEntry( _rEntry.pLabelProvider->getLabel(), aEntryImage, aEntryImage ); |
| pListEntry->SetUserData( reinterpret_cast< void* >( _nElementPos ) ); |
| } |
| } |
| |
| //============================================================================== |
| class OExceptionChainDialog : public ModalDialog |
| { |
| FixedLine m_aFrame; |
| FixedText m_aListLabel; |
| SvTreeListBox m_aExceptionList; |
| FixedText m_aDescLabel; |
| MultiLineEdit m_aExceptionText; |
| OKButton m_aOK; |
| |
| String m_sStatusLabel; |
| String m_sErrorCodeLabel; |
| |
| ExceptionDisplayChain m_aExceptions; |
| |
| public: |
| OExceptionChainDialog( Window* pParent, const ExceptionDisplayChain& _rExceptions ); |
| ~OExceptionChainDialog(); |
| |
| protected: |
| DECL_LINK(OnExceptionSelected, void*); |
| }; |
| |
| DBG_NAME(OExceptionChainDialog) |
| //------------------------------------------------------------------------------ |
| OExceptionChainDialog::OExceptionChainDialog( Window* pParent, const ExceptionDisplayChain& _rExceptions ) |
| :ModalDialog(pParent, ModuleRes(DLG_SQLEXCEPTIONCHAIN)) |
| ,m_aFrame (this, ModuleRes(FL_DETAILS)) |
| ,m_aListLabel (this, ModuleRes(FT_ERRORLIST)) |
| ,m_aExceptionList (this, ModuleRes(CTL_ERRORLIST)) |
| ,m_aDescLabel (this, ModuleRes(FT_DESCRIPTION)) |
| ,m_aExceptionText (this, ModuleRes(ME_DESCRIPTION)) |
| ,m_aOK (this, ModuleRes(PB_OK)) |
| ,m_aExceptions( _rExceptions ) |
| { |
| DBG_CTOR(OExceptionChainDialog,NULL); |
| |
| m_sStatusLabel = String( ModuleRes( STR_EXCEPTION_STATUS ) ); |
| m_sErrorCodeLabel = String( ModuleRes( STR_EXCEPTION_ERRORCODE ) ); |
| |
| FreeResource(); |
| |
| m_aExceptionList.SetSelectionMode(SINGLE_SELECTION); |
| m_aExceptionList.SetDragDropMode(0); |
| m_aExceptionList.EnableInplaceEditing(sal_False); |
| m_aExceptionList.SetStyle(m_aExceptionList.GetStyle() | WB_HASLINES | WB_HASBUTTONS | WB_HASBUTTONSATROOT | WB_HSCROLL); |
| |
| m_aExceptionList.SetSelectHdl(LINK(this, OExceptionChainDialog, OnExceptionSelected)); |
| m_aExceptionList.SetNodeDefaultImages( ); |
| m_aExceptionText.SetReadOnly(sal_True); |
| |
| bool bHave22018 = false; |
| bool bHiContrast = isHiContrast( this ); |
| size_t elementPos = 0; |
| |
| for ( ExceptionDisplayChain::const_iterator loop = m_aExceptions.begin(); |
| loop != m_aExceptions.end(); |
| ++loop, ++elementPos |
| ) |
| { |
| lcl_insertExceptionEntry( m_aExceptionList, bHiContrast, elementPos, *loop ); |
| bHave22018 = loop->sSQLState.EqualsAscii( "22018" ); |
| } |
| |
| // if the error has the code 22018, then add an additional explanation |
| // #i24021# / 2004-10-14 / frank.schoenheit@sun.com |
| if ( bHave22018 ) |
| { |
| ProviderFactory aProviderFactory; |
| |
| ExceptionDisplayInfo aInfo22018; |
| aInfo22018.sMessage = String( ModuleRes( STR_EXPLAN_STRINGCONVERSION_ERROR ) ); |
| aInfo22018.pLabelProvider = aProviderFactory.getLabelProvider( SQLExceptionInfo::SQL_CONTEXT, false ); |
| aInfo22018.pImageProvider = aProviderFactory.getImageProvider( SQLExceptionInfo::SQL_CONTEXT ); |
| m_aExceptions.push_back( aInfo22018 ); |
| |
| lcl_insertExceptionEntry( m_aExceptionList, bHiContrast, m_aExceptions.size() - 1, aInfo22018 ); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| OExceptionChainDialog::~OExceptionChainDialog() |
| { |
| DBG_DTOR(OExceptionChainDialog,NULL); |
| } |
| |
| //------------------------------------------------------------------------------ |
| IMPL_LINK(OExceptionChainDialog, OnExceptionSelected, void*, EMPTYARG) |
| { |
| SvLBoxEntry* pSelected = m_aExceptionList.FirstSelected(); |
| DBG_ASSERT(!pSelected || !m_aExceptionList.NextSelected(pSelected), "OExceptionChainDialog::OnExceptionSelected : multi selection ?"); |
| |
| String sText; |
| |
| if ( pSelected ) |
| { |
| size_t pos = reinterpret_cast< size_t >( pSelected->GetUserData() ); |
| const ExceptionDisplayInfo& aExceptionInfo( m_aExceptions[ pos ] ); |
| |
| if ( aExceptionInfo.sSQLState.Len() ) |
| { |
| sText += m_sStatusLabel; |
| sText.AppendAscii(": "); |
| sText += aExceptionInfo.sSQLState; |
| sText.AppendAscii("\n"); |
| } |
| |
| if ( aExceptionInfo.sErrorCode.Len() ) |
| { |
| sText += m_sErrorCodeLabel; |
| sText.AppendAscii(": "); |
| sText += aExceptionInfo.sErrorCode; |
| sText.AppendAscii("\n"); |
| } |
| |
| if ( sText.Len() ) |
| sText.AppendAscii( "\n" ); |
| |
| sText += aExceptionInfo.sMessage; |
| } |
| |
| m_aExceptionText.SetText(sText); |
| |
| return 0L; |
| } |
| |
| //============================================================================== |
| //= SQLMessageBox_Impl |
| //============================================================================== |
| struct SQLMessageBox_Impl |
| { |
| ExceptionDisplayChain aDisplayInfo; |
| |
| SQLMessageBox_Impl( const SQLExceptionInfo& _rExceptionInfo ) |
| { |
| // transform the exception chain to a form more suitable for displaying it here |
| ProviderFactory aProviderFactory; |
| lcl_buildExceptionChain( _rExceptionInfo, aProviderFactory, aDisplayInfo ); |
| } |
| }; |
| |
| //------------------------------------------------------------------------------ |
| namespace |
| { |
| ::rtl::OUString lcl_getProductName() |
| { |
| ::rtl::OUString sProductName; |
| OSL_VERIFY( ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME ) >>= sProductName ); |
| return sProductName; |
| } |
| |
| void lcl_positionInAppFont( const Window& _rParent, Window& _rChild, long _nX, long _nY, long _Width, long _Height ) |
| { |
| Point aPos = _rParent.LogicToPixel( Point( _nX, _nY ), MAP_APPFONT ); |
| Size aSize = _rParent.LogicToPixel( Size( _Width, _Height ), MAP_APPFONT ); |
| _rChild.SetPosSizePixel( aPos, aSize ); |
| } |
| |
| void lcl_addButton( ButtonDialog& _rDialog, StandardButtonType _eType, bool _bDefault ) |
| { |
| sal_uInt16 nButtonID = 0; |
| switch ( _eType ) |
| { |
| case BUTTON_YES: nButtonID = BUTTONID_YES; break; |
| case BUTTON_NO: nButtonID = BUTTONID_NO; break; |
| case BUTTON_OK: nButtonID = BUTTONID_OK; break; |
| case BUTTON_CANCEL: nButtonID = BUTTONID_CANCEL; break; |
| case BUTTON_RETRY: nButtonID = BUTTONID_RETRY; break; |
| case BUTTON_HELP: nButtonID = BUTTONID_HELP; break; |
| default: |
| OSL_ENSURE( false, "lcl_addButton: invalid button id!" ); |
| break; |
| } |
| _rDialog.AddButton( _eType, nButtonID, _bDefault ? BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON : 0 ); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OSQLMessageBox::impl_positionControls() |
| { |
| OSL_PRECOND( !m_pImpl->aDisplayInfo.empty(), "OSQLMessageBox::impl_positionControls: nothing to display at all?" ); |
| |
| |
| if ( m_pImpl->aDisplayInfo.empty() ) |
| return; |
| const ExceptionDisplayInfo* pSecondInfo = NULL; |
| |
| const ExceptionDisplayInfo& rFirstInfo = *m_pImpl->aDisplayInfo.begin(); |
| if ( m_pImpl->aDisplayInfo.size() > 1 ) |
| pSecondInfo = &m_pImpl->aDisplayInfo[1]; |
| String sPrimary, sSecondary; |
| sPrimary = rFirstInfo.sMessage; |
| // one or two texts to display? |
| if ( pSecondInfo ) |
| { |
| // we show two elements in the main dialog if and only if one of |
| // - the first element in the chain is an SQLContext, and the second |
| // element denotes its sub entry |
| // - the first and the second element are both independent (i.e. the second |
| // is no sub entry), and none of them is a context. |
| bool bFirstElementIsContext = ( rFirstInfo.eType == SQLExceptionInfo::SQL_CONTEXT ); |
| bool bSecondElementIsContext = ( pSecondInfo->eType == SQLExceptionInfo::SQL_CONTEXT ); |
| |
| if ( bFirstElementIsContext && pSecondInfo->bSubEntry ) |
| sSecondary = pSecondInfo->sMessage; |
| if ( !bFirstElementIsContext && !bSecondElementIsContext ) |
| sSecondary = pSecondInfo->sMessage; |
| } |
| |
| // image |
| lcl_positionInAppFont( *this, m_aInfoImage, OUTER_MARGIN, OUTER_MARGIN, IMAGE_SIZE, IMAGE_SIZE ); |
| m_aInfoImage.Show(); |
| |
| // primary text |
| lcl_positionInAppFont( *this, m_aTitle, TEXT_POS_X, OUTER_MARGIN, DIALOG_WIDTH - TEXT_POS_X - 2 * OUTER_MARGIN, 16 ); |
| sPrimary = lcl_stripOOoBaseVendor( sPrimary ); |
| m_aTitle.SetText( sPrimary ); |
| m_aTitle.Show(); |
| |
| Rectangle aPrimaryRect( m_aTitle.GetPosPixel(), m_aTitle.GetSizePixel() ); |
| |
| // secondary text (if applicable) |
| m_aMessage.SetStyle( m_aMessage.GetStyle() | WB_NOLABEL ); |
| sSecondary = lcl_stripOOoBaseVendor( sSecondary ); |
| m_aMessage.SetText( sSecondary ); |
| |
| lcl_positionInAppFont( *this, m_aMessage, TEXT_POS_X, OUTER_MARGIN + 16 + 3, DIALOG_WIDTH - TEXT_POS_X - 2 * OUTER_MARGIN, 8 ); |
| Rectangle aSecondaryRect( m_aMessage.GetPosPixel(), m_aMessage.GetSizePixel() ); |
| |
| bool bHaveSecondaryText = sSecondary.Len() != 0; |
| |
| // determine which space the secondary text would occupy |
| if ( bHaveSecondaryText ) |
| aSecondaryRect = GetTextRect( aSecondaryRect, sSecondary, TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE | TEXT_DRAW_LEFT ); |
| else |
| aSecondaryRect.Bottom() = aSecondaryRect.Top() - 1; |
| |
| // adjust secondary control height accordingly |
| m_aMessage.SetSizePixel( aSecondaryRect.GetSize() ); |
| m_aMessage.Show( aSecondaryRect.GetHeight() > 0 ); |
| |
| // if there's no secondary text ... |
| if ( !bHaveSecondaryText ) |
| { // then give the primary text as much horizontal space as it needs |
| Rectangle aSuggestedRect( GetTextRect( aPrimaryRect, sPrimary, TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE | TEXT_DRAW_CENTER ) ); |
| aPrimaryRect.Right() = aPrimaryRect.Left() + aSuggestedRect.GetWidth(); |
| aPrimaryRect.Bottom() = aPrimaryRect.Top() + aSuggestedRect.GetHeight(); |
| // and center it horizontally |
| m_aTitle.SetStyle( ( m_aTitle.GetStyle() & ~WB_LEFT ) | WB_CENTER ); |
| |
| Rectangle aInfoRect( m_aInfoImage.GetPosPixel(), m_aInfoImage.GetSizePixel() ); |
| // also, if it's not as high as the image ... |
| if ( aPrimaryRect.GetHeight() < m_aInfoImage.GetSizePixel().Height() ) |
| { // ... make it fit the image height |
| aPrimaryRect.Bottom() += aInfoRect.GetHeight() - aPrimaryRect.GetHeight(); |
| // and center it vertically |
| m_aTitle.SetStyle( m_aTitle.GetStyle() | WB_VCENTER ); |
| } |
| else |
| { // ... otherwise, center the image vertically, relative to the primary text |
| aInfoRect.Move( 0, ( aPrimaryRect.GetHeight() - aInfoRect.GetHeight() ) / 2 ); |
| m_aInfoImage.SetPosSizePixel( aInfoRect.TopLeft(), aInfoRect.GetSize() ); |
| } |
| |
| m_aTitle.SetPosSizePixel( aPrimaryRect.TopLeft(), aPrimaryRect.GetSize() ); |
| } |
| |
| // adjust dialog size accordingly |
| const Rectangle& rBottomTextRect( bHaveSecondaryText ? aSecondaryRect : aPrimaryRect ); |
| Size aBorderSize = LogicToPixel( Size( OUTER_MARGIN, OUTER_MARGIN ), MAP_APPFONT ); |
| Size aDialogSize( LogicToPixel( Size( DIALOG_WIDTH, 30 ), MAP_APPFONT ) ); |
| aDialogSize.Height() = rBottomTextRect.Bottom() + aBorderSize.Height(); |
| aDialogSize.Width() = aPrimaryRect.Right() + aBorderSize.Width(); |
| |
| SetSizePixel( aDialogSize ); |
| SetPageSizePixel( aDialogSize ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OSQLMessageBox::impl_initImage( MessageType _eImage ) |
| { |
| switch (_eImage) |
| { |
| default: |
| DBG_ERROR( "OSQLMessageBox::impl_initImage: unsupported image type!" ); |
| |
| case Info: |
| m_aInfoImage.SetImage(InfoBox::GetStandardImage()); |
| break; |
| case Warning: |
| m_aInfoImage.SetImage(WarningBox::GetStandardImage()); |
| break; |
| case Error: |
| m_aInfoImage.SetImage(ErrorBox::GetStandardImage()); |
| break; |
| case Query: |
| m_aInfoImage.SetImage(QueryBox::GetStandardImage()); |
| break; |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OSQLMessageBox::impl_createStandardButtons( WinBits _nStyle ) |
| { |
| if ( _nStyle & WB_YES_NO_CANCEL ) |
| { |
| lcl_addButton( *this, BUTTON_YES, ( _nStyle & WB_DEF_YES ) != 0 ); |
| lcl_addButton( *this, BUTTON_NO, ( _nStyle & WB_DEF_NO ) != 0 ); |
| lcl_addButton( *this, BUTTON_CANCEL, ( _nStyle & WB_DEF_CANCEL ) != 0 ); |
| } |
| else if ( _nStyle & WB_OK_CANCEL ) |
| { |
| lcl_addButton( *this, BUTTON_OK, ( _nStyle & WB_DEF_OK ) != 0 ); |
| lcl_addButton( *this, BUTTON_CANCEL, ( _nStyle & WB_DEF_CANCEL ) != 0 ); |
| } |
| else if ( _nStyle & WB_YES_NO ) |
| { |
| lcl_addButton( *this, BUTTON_YES, ( _nStyle & WB_DEF_YES ) != 0 ); |
| lcl_addButton( *this, BUTTON_NO, ( _nStyle & WB_DEF_NO ) != 0 ); |
| } |
| else if ( _nStyle & WB_RETRY_CANCEL ) |
| { |
| lcl_addButton( *this, BUTTON_RETRY, ( _nStyle & WB_DEF_RETRY ) != 0 ); |
| lcl_addButton( *this, BUTTON_CANCEL, ( _nStyle & WB_DEF_CANCEL ) != 0 ); |
| } |
| else |
| { |
| OSL_ENSURE( WB_OK & _nStyle, "OSQLMessageBox::impl_createStandardButtons: unsupported dialog style requested!" ); |
| AddButton( BUTTON_OK, BUTTONID_OK, BUTTONDIALOG_DEFBUTTON | BUTTONDIALOG_FOCUSBUTTON ); |
| } |
| |
| if ( m_sHelpURL.getLength() ) |
| { |
| lcl_addButton( *this, BUTTON_HELP, false ); |
| |
| rtl::OUString aTmp; |
| INetURLObject aHID( m_sHelpURL ); |
| if ( aHID.GetProtocol() == INET_PROT_HID ) |
| aTmp = aHID.GetURLPath(); |
| else |
| aTmp = m_sHelpURL; |
| |
| SetHelpId( rtl::OUStringToOString( aTmp, RTL_TEXTENCODING_UTF8 ) ); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OSQLMessageBox::impl_addDetailsButton() |
| { |
| size_t nFirstPageVisible = m_aMessage.IsVisible() ? 2 : 1; |
| |
| bool bMoreDetailsAvailable = m_pImpl->aDisplayInfo.size() > nFirstPageVisible; |
| if ( !bMoreDetailsAvailable ) |
| { |
| // even if the text fits into what we can display, we might need to details button |
| // if there is more non-trivial information in the errors than the mere messages |
| for ( ExceptionDisplayChain::const_iterator error = m_pImpl->aDisplayInfo.begin(); |
| error != m_pImpl->aDisplayInfo.end(); |
| ++error |
| ) |
| { |
| if ( lcl_hasDetails( *error ) ) |
| { |
| bMoreDetailsAvailable = true; |
| break; |
| } |
| } |
| } |
| |
| if ( bMoreDetailsAvailable ) |
| { |
| AddButton( BUTTON_MORE, BUTTONID_MORE, 0 ); |
| PushButton* pButton = GetPushButton( BUTTONID_MORE ); |
| OSL_ENSURE( pButton, "OSQLMessageBox::impl_addDetailsButton: just added this button, why isn't it there?" ); |
| pButton->SetClickHdl( LINK( this, OSQLMessageBox, ButtonClickHdl ) ); |
| pButton->SetUniqueId( UID_SQLERROR_BUTTONMORE ); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void OSQLMessageBox::Construct( WinBits _nStyle, MessageType _eImage ) |
| { |
| // Changed as per BugID 79541 Branding/Configuration |
| String sDialogTitle( lcl_getProductName() ); |
| SetText( sDialogTitle.AppendAscii( " Base" ) ); |
| |
| // position and size the controls and the dialog, depending on whether we have one or two texts to display |
| impl_positionControls(); |
| |
| // init the image |
| MessageType eType( _eImage ); |
| if ( eType == AUTO ) |
| { |
| switch ( m_pImpl->aDisplayInfo[0].eType ) |
| { |
| case SQLExceptionInfo::SQL_EXCEPTION: eType = Error; break; |
| case SQLExceptionInfo::SQL_WARNING: eType = Warning; break; |
| case SQLExceptionInfo::SQL_CONTEXT: eType = Info; break; |
| default: OSL_ENSURE( false, "OSQLMessageBox::Construct: invalid type!" ); |
| } |
| } |
| impl_initImage( eType ); |
| |
| // create buttons |
| impl_createStandardButtons( _nStyle ); |
| impl_addDetailsButton(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| OSQLMessageBox::OSQLMessageBox(Window* _pParent, const SQLExceptionInfo& _rException, WinBits _nStyle, const ::rtl::OUString& _rHelpURL ) |
| :ButtonDialog( _pParent, WB_HORZ | WB_STDDIALOG ) |
| ,m_aInfoImage( this ) |
| ,m_aTitle( this, WB_WORDBREAK | WB_LEFT ) |
| ,m_aMessage( this, WB_WORDBREAK | WB_LEFT ) |
| ,m_sHelpURL( _rHelpURL ) |
| ,m_pImpl( new SQLMessageBox_Impl( _rException ) ) |
| { |
| Construct( _nStyle, AUTO ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| OSQLMessageBox::OSQLMessageBox( Window* _pParent, const UniString& _rTitle, const UniString& _rMessage, WinBits _nStyle, MessageType _eType, const ::dbtools::SQLExceptionInfo* _pAdditionalErrorInfo ) |
| :ButtonDialog( _pParent, WB_HORZ | WB_STDDIALOG ) |
| ,m_aInfoImage( this ) |
| ,m_aTitle( this, WB_WORDBREAK | WB_LEFT ) |
| ,m_aMessage( this, WB_WORDBREAK | WB_LEFT ) |
| { |
| SQLContext aError; |
| aError.Message = _rTitle; |
| aError.Details = _rMessage; |
| if ( _pAdditionalErrorInfo ) |
| aError.NextException = _pAdditionalErrorInfo->get(); |
| |
| m_pImpl.reset( new SQLMessageBox_Impl( SQLExceptionInfo( aError ) ) ); |
| |
| Construct( _nStyle, _eType ); |
| } |
| |
| //-------------------------------------------------------------------------- |
| OSQLMessageBox::~OSQLMessageBox() |
| { |
| } |
| |
| //-------------------------------------------------------------------------- |
| IMPL_LINK( OSQLMessageBox, ButtonClickHdl, Button *, /*pButton*/ ) |
| { |
| OExceptionChainDialog aDlg( this, m_pImpl->aDisplayInfo ); |
| aDlg.Execute(); |
| return 0; |
| } |
| |
| //================================================================== |
| // OSQLWarningBox |
| //================================================================== |
| OSQLWarningBox::OSQLWarningBox( Window* _pParent, const UniString& _rMessage, WinBits _nStyle, |
| const ::dbtools::SQLExceptionInfo* _pAdditionalErrorInfo ) |
| :OSQLMessageBox( _pParent, String( ModuleRes( STR_STAT_WARNING ) ), _rMessage, _nStyle, OSQLMessageBox::Warning, _pAdditionalErrorInfo ) |
| { |
| } |
| |
| //......................................................................... |
| } // namespace dbaui |
| //......................................................................... |
| |