20#include <core_resource.hxx>
23#include <com/sun/star/sdbc/SQLException.hpp>
24#include <com/sun/star/sdb/SQLContext.hpp>
29#include <osl/diagnose.h>
36#define RET_MORE RET_RETRY + 1
54 explicit ImageProvider(OUString defaultImageID)
59 const OUString& getImage()
const
75 const OUString& getLabel()
const
98 std::shared_ptr< ImageProvider >* ppProvider( &
m_pErrorImage );
99 OUString sNormalImageID(
"dialog-error");
103 case SQLExceptionInfo::TYPE::SQLWarning:
105 sNormalImageID =
"dialog-warning";
108 case SQLExceptionInfo::TYPE::SQLContext:
110 sNormalImageID =
"dialog-information";
117 if ( !ppProvider->get() )
118 (*ppProvider) = std::make_shared<ImageProvider>(sNormalImageID);
122 std::shared_ptr< LabelProvider >
const & getLabelProvider(
SQLExceptionInfo::TYPE _eType,
bool _bSubLabel )
const
124 std::shared_ptr< LabelProvider >* ppProvider( &
m_pErrorLabel );
129 case SQLExceptionInfo::TYPE::SQLWarning:
131 pLabelID = STR_EXCEPTION_WARNING;
134 case SQLExceptionInfo::TYPE::SQLContext:
136 pLabelID = _bSubLabel ? STR_EXCEPTION_DETAILS : STR_EXCEPTION_INFO;
142 if ( !ppProvider->get() )
143 (*ppProvider) = std::make_shared<LabelProvider>( pLabelID );
150 struct ExceptionDisplayInfo
167 bool lcl_hasDetails(
const ExceptionDisplayInfo& _displayInfo )
169 return ( !_displayInfo.sErrorCode.isEmpty() )
170 || ( !_displayInfo.sSQLState.isEmpty()
171 && _displayInfo.sSQLState !=
"S1000"
175 typedef std::vector< ExceptionDisplayInfo > ExceptionDisplayChain;
178 OUString lcl_stripOOoBaseVendor(
const OUString& _rErrorMessage )
180 OUString sErrorMessage( _rErrorMessage );
183 if ( sErrorMessage.startsWith( sVendorIdentifier ) )
186 sal_Int32 nStripLen( sVendorIdentifier.getLength() );
188 while ( ( sErrorMessage.getLength() > nStripLen )
189 && ( sErrorMessage[nStripLen] ==
' ' )
192 sErrorMessage = sErrorMessage.copy( nStripLen );
195 return sErrorMessage;
198 void lcl_buildExceptionChain(
const SQLExceptionInfo& _rErrorInfo,
const ProviderFactory& _rFactory, ExceptionDisplayChain& _out_rChain )
200 ExceptionDisplayChain().swap(_out_rChain);
203 while ( iter.hasMoreElements() )
207 iter.next( aCurrentElement );
209 const SQLException* pCurrentError = aCurrentElement;
210 OSL_ENSURE( pCurrentError,
"lcl_buildExceptionChain: iterator failure!" );
213 ExceptionDisplayInfo aDisplayInfo( aCurrentElement.
getType() );
215 aDisplayInfo.sMessage = pCurrentError->Message.trim();
216 aDisplayInfo.sSQLState = pCurrentError->SQLState;
217 if ( pCurrentError->ErrorCode )
218 aDisplayInfo.sErrorCode = OUString::number( pCurrentError->ErrorCode );
220 if ( aDisplayInfo.sMessage.isEmpty()
221 && !lcl_hasDetails( aDisplayInfo )
224 OSL_FAIL(
"lcl_buildExceptionChain: useless exception: no state, no error code, no message!" );
228 aDisplayInfo.pImageProvider = _rFactory.getImageProvider( aCurrentElement.
getType() );
229 aDisplayInfo.pLabelProvider = _rFactory.getLabelProvider( aCurrentElement.
getType(),
false );
231 _out_rChain.push_back( aDisplayInfo );
233 if ( aCurrentElement.
getType() == SQLExceptionInfo::TYPE::SQLContext )
235 const SQLContext* pContext = aCurrentElement;
236 if ( !pContext->Details.isEmpty() )
238 ExceptionDisplayInfo aSubInfo( aCurrentElement.
getType() );
240 aSubInfo.sMessage = pContext->Details;
241 aSubInfo.pImageProvider = _rFactory.getImageProvider( aCurrentElement.
getType() );
242 aSubInfo.pLabelProvider = _rFactory.getLabelProvider( aCurrentElement.
getType(),
true );
243 aSubInfo.bSubEntry =
true;
245 _out_rChain.push_back( aSubInfo );
251 void lcl_insertExceptionEntry(
weld::TreeView& rList,
size_t nElementPos,
const ExceptionDisplayInfo& rEntry)
253 rList.
append(OUString::number(nElementPos), rEntry.pLabelProvider->getLabel(), rEntry.pImageProvider->getImage());
270 OExceptionChainDialog(
weld::Window* pParent, ExceptionDisplayChain&& rExceptions);
278OExceptionChainDialog::OExceptionChainDialog(
weld::Window* pParent, ExceptionDisplayChain&& rExceptions)
279 : GenericDialogController(pParent,
"dbaccess/ui/sqlexception.ui",
"SQLExceptionDialog")
295 bool bHave22018 =
false;
296 size_t elementPos = 0;
301 bHave22018 = elem.sSQLState ==
"22018";
309 ProviderFactory aProviderFactory;
311 ExceptionDisplayInfo aInfo22018;
312 aInfo22018.sMessage =
DBA_RES( STR_EXPLAN_STRINGCONVERSION_ERROR );
313 aInfo22018.pLabelProvider = aProviderFactory.getLabelProvider( SQLExceptionInfo::TYPE::SQLContext,
false );
314 aInfo22018.pImageProvider = aProviderFactory.getImageProvider( SQLExceptionInfo::TYPE::SQLContext );
336 if ( !aExceptionInfo.sSQLState.isEmpty() )
341 if ( !aExceptionInfo.sErrorCode.isEmpty() )
346 if ( !sText.isEmpty() )
349 sText += aExceptionInfo.sMessage;
363 ProviderFactory aProviderFactory;
364 lcl_buildExceptionChain( _rExceptionInfo, aProviderFactory, aDisplayInfo );
372 sal_uInt16 nButtonID = 0;
375 case StandardButtonType::Yes:
379 case StandardButtonType::No:
383 case StandardButtonType::OK:
387 case StandardButtonType::Cancel:
391 case StandardButtonType::Retry:
395 case StandardButtonType::Help:
400 OSL_FAIL(
"lcl_addButton: invalid button id!" );
408void OSQLMessageBox::impl_fillMessages()
410 OSL_PRECOND( !
m_pImpl->aDisplayInfo.empty(),
"OSQLMessageBox::impl_fillMessages: nothing to display at all?" );
412 if (
m_pImpl->aDisplayInfo.empty() )
414 const ExceptionDisplayInfo* pSecondInfo =
nullptr;
416 const ExceptionDisplayInfo& rFirstInfo = *
m_pImpl->aDisplayInfo.begin();
417 if (
m_pImpl->aDisplayInfo.size() > 1 )
418 pSecondInfo = &
m_pImpl->aDisplayInfo[1];
419 OUString sPrimary, sSecondary;
420 sPrimary = rFirstInfo.sMessage;
429 bool bFirstElementIsContext = ( rFirstInfo.eType == SQLExceptionInfo::TYPE::SQLContext );
430 bool bSecondElementIsContext = ( pSecondInfo->eType == SQLExceptionInfo::TYPE::SQLContext );
432 if ( bFirstElementIsContext && pSecondInfo->bSubEntry )
433 sSecondary = pSecondInfo->sMessage;
434 if ( !bFirstElementIsContext && !bSecondElementIsContext )
435 sSecondary = pSecondInfo->sMessage;
439 m_xDialog->set_primary_text(lcl_stripOOoBaseVendor(sPrimary));
442 m_xDialog->set_secondary_text(lcl_stripOOoBaseVendor(sSecondary));
447 if ( _nStyle & MessBoxStyle::YesNoCancel )
449 lcl_addButton(
m_xDialog.get(), StandardButtonType::Yes,
bool(_nStyle & MessBoxStyle::DefaultYes));
450 lcl_addButton(
m_xDialog.get(), StandardButtonType::No,
bool(_nStyle & MessBoxStyle::DefaultNo));
451 lcl_addButton(
m_xDialog.get(), StandardButtonType::Cancel,
bool(_nStyle & MessBoxStyle::DefaultCancel));
453 else if ( _nStyle & MessBoxStyle::OkCancel )
455 lcl_addButton(
m_xDialog.get(), StandardButtonType::OK,
bool(_nStyle & MessBoxStyle::DefaultOk));
456 lcl_addButton(
m_xDialog.get(), StandardButtonType::Cancel,
bool(_nStyle & MessBoxStyle::DefaultCancel));
458 else if ( _nStyle & MessBoxStyle::YesNo )
460 lcl_addButton(
m_xDialog.get(), StandardButtonType::Yes,
bool(_nStyle & MessBoxStyle::DefaultYes));
461 lcl_addButton(
m_xDialog.get(), StandardButtonType::No,
bool(_nStyle & MessBoxStyle::DefaultNo));
463 else if ( _nStyle & MessBoxStyle::RetryCancel )
465 lcl_addButton(
m_xDialog.get(), StandardButtonType::Retry,
bool(_nStyle & MessBoxStyle::DefaultRetry));
466 lcl_addButton(
m_xDialog.get(), StandardButtonType::Cancel,
bool(_nStyle & MessBoxStyle::DefaultCancel));
468 else if ( _nStyle & MessBoxStyle::Ok )
470 lcl_addButton(
m_xDialog.get(), StandardButtonType::OK,
true);
473 if ( m_sHelpURL.isEmpty() )
476 lcl_addButton(
m_xDialog.get(), StandardButtonType::Help,
false);
488void OSQLMessageBox::impl_addDetailsButton()
490 size_t nFirstPageVisible =
m_xDialog->get_secondary_text().isEmpty() ? 1 : 2;
492 bool bMoreDetailsAvailable =
m_pImpl->aDisplayInfo.size() > nFirstPageVisible;
493 if ( !bMoreDetailsAvailable )
497 for (
auto const& error :
m_pImpl->aDisplayInfo)
499 if ( lcl_hasDetails(error) )
501 bMoreDetailsAvailable =
true;
507 if ( bMoreDetailsAvailable )
521 switch (
m_pImpl->aDisplayInfo[0].eType )
523 case SQLExceptionInfo::TYPE::SQLException:
eType =
Error;
break;
524 case SQLExceptionInfo::TYPE::SQLWarning:
eType =
Warning;
break;
525 case SQLExceptionInfo::TYPE::SQLContext:
eType =
Info;
break;
526 default: OSL_FAIL(
"OSQLMessageBox::Construct: invalid type!" );
533 OSL_FAIL(
"OSQLMessageBox::impl_initImage: unsupported image type!" );
536 eMessageType = VclMessageType::Info;
539 eMessageType = VclMessageType::Warning;
542 eMessageType = VclMessageType::Error;
545 eMessageType = VclMessageType::Question;
555 impl_createStandardButtons( _nStyle );
556 impl_addDetailsButton();
561 , m_sHelpURL(
std::move(sHelpURL))
569 aError.Message = rTitle;
570 aError.Details = rMessage;
571 if (pAdditionalErrorInfo)
572 aError.NextException = pAdditionalErrorInfo->get();
585 OExceptionChainDialog aDlg(
m_xDialog.get(), std::vector(
m_pImpl->aDisplayInfo));
591 const ::dbtools::SQLExceptionInfo* pAdditionalErrorInfo )
Reference< XExecutableDialog > m_xDialog
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, const ILibreOfficeKitNotifier *pNotifier=nullptr)
OUString GetURLPath(DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
INetProtocol GetProtocol() const
static const OUString & getMessagePrefix()
OSQLErrorBox(weld::Window *pParent, const OUString &_rMessage)
std::unique_ptr< SQLMessageBox_Impl > m_pImpl
void Construct(weld::Window *pParent, MessBoxStyle nStyle, MessageType eImage)
OSQLMessageBox(weld::Window *pParent, const dbtools::SQLExceptionInfo &_rException, MessBoxStyle _nStyle=MessBoxStyle::Ok|MessBoxStyle::DefaultOk, OUString _sHelpURL=OUString())
display an SQLException with auto-recognizing a main and a detailed message
virtual ~OSQLMessageBox() override
OSQLWarningBox(weld::Window *pParent, const OUString &_rMessage, MessBoxStyle _nStyle=MessBoxStyle::Ok|MessBoxStyle::DefaultOk, const ::dbtools::SQLExceptionInfo *_pAdditionalErrorInfo=nullptr)
static OUString getProductName()
virtual void set_default_response(int response)=0
virtual void add_button(const OUString &rText, int response, const OUString &rHelpId={})=0
void append(TreeIter *pRet=nullptr)
DECL_LINK(CheckNameHdl, SvxNameDialog &, bool)
#define LINK(Instance, Class, Member)
IMPL_LINK_NOARG(OApplicationController, OnClipboardChanged, TransferableDataHelper *, void)
IMPL_LINK_NOARG(OSQLMessageBox, ButtonClickHdl, weld::Button &, void)
std::shared_ptr< LabelProvider > m_pErrorLabel
std::unique_ptr< weld::TextView > m_xExceptionText
std::shared_ptr< LabelProvider > m_pWarningsLabel
std::shared_ptr< ImageProvider > pImageProvider
std::shared_ptr< ImageProvider > m_pErrorImage
std::shared_ptr< LabelProvider > m_pInfoLabel
SQLExceptionInfo::TYPE eType
std::shared_ptr< ImageProvider > m_pInfoImage
ExceptionDisplayChain m_aExceptions
std::unique_ptr< weld::TreeView > m_xExceptionList
std::shared_ptr< ImageProvider > m_pWarningsImage
std::shared_ptr< LabelProvider > pLabelProvider
OUString m_defaultImageID
OUString m_sErrorCodeLabel
OUString VCL_DLLPUBLIC GetStandardText(StandardButtonType eButton)
ExceptionDisplayChain aDisplayInfo
SQLMessageBox_Impl(const SQLExceptionInfo &_rExceptionInfo)