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
~IImageProvider()104 virtual ~IImageProvider() { }
105 };
106
107 //------------------------------------------------------------------------------
108 class ILabelProvider
109 {
110 public:
111 virtual String getLabel() const = 0;
112
~ILabelProvider()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:
ImageProvider(sal_uInt16 _defaultImageID,sal_uInt16 _highContrastImageID)127 ImageProvider( sal_uInt16 _defaultImageID, sal_uInt16 _highContrastImageID )
128 :m_defaultImageID( _defaultImageID )
129 ,m_highContrastImageID( _highContrastImageID )
130 {
131 }
132
getImage(bool _highContrast) const133 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:
LabelProvider(sal_uInt16 _labelResourceID)154 LabelProvider( sal_uInt16 _labelResourceID )
155 :m_label( ModuleRes( _labelResourceID ) )
156 {
157 }
158
getLabel() const159 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:
ProviderFactory()177 ProviderFactory()
178 {
179 }
180
getImageProvider(SQLExceptionInfo::TYPE _eType) const181 ::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
getLabelProvider(SQLExceptionInfo::TYPE _eType,bool _bSubLabel) const210 ::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
ExceptionDisplayInfodbaui::__anon1ecee0660111::ExceptionDisplayInfo252 ExceptionDisplayInfo() : eType( SQLExceptionInfo::UNDEFINED ), bSubEntry( false ) { }
ExceptionDisplayInfodbaui::__anon1ecee0660111::ExceptionDisplayInfo253 ExceptionDisplayInfo( SQLExceptionInfo::TYPE _eType ) : eType( _eType ), bSubEntry( false ) { }
254 };
255
lcl_hasDetails(const ExceptionDisplayInfo & _displayInfo)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
lcl_stripOOoBaseVendor(const::rtl::OUString & _rErrorMessage)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 //------------------------------------------------------------------------------
lcl_buildExceptionChain(const SQLExceptionInfo & _rErrorInfo,const ProviderFactory & _rFactory,ExceptionDisplayChain & _out_rChain)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 //------------------------------------------------------------------------------
lcl_insertExceptionEntry(SvTreeListBox & _rList,bool _bHiContrast,size_t _nElementPos,const ExceptionDisplayInfo & _rEntry)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
DBG_NAME(OExceptionChainDialog)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 //------------------------------------------------------------------------------
~OExceptionChainDialog()436 OExceptionChainDialog::~OExceptionChainDialog()
437 {
438 DBG_DTOR(OExceptionChainDialog,NULL);
439 }
440
441 //------------------------------------------------------------------------------
IMPL_LINK(OExceptionChainDialog,OnExceptionSelected,void *,EMPTYARG)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
SQLMessageBox_Impldbaui::SQLMessageBox_Impl488 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 {
lcl_getProductName()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
lcl_positionInAppFont(const Window & _rParent,Window & _rChild,long _nX,long _nY,long _Width,long _Height)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
lcl_addButton(ButtonDialog & _rDialog,StandardButtonType _eType,bool _bDefault)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 //------------------------------------------------------------------------------
impl_positionControls()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 //------------------------------------------------------------------------------
impl_initImage(MessageType _eImage)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 //------------------------------------------------------------------------------
impl_createStandardButtons(WinBits _nStyle)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 //------------------------------------------------------------------------------
impl_addDetailsButton()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 //------------------------------------------------------------------------------
Construct(WinBits _nStyle,MessageType _eImage)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 //------------------------------------------------------------------------------
OSQLMessageBox(Window * _pParent,const SQLExceptionInfo & _rException,WinBits _nStyle,const::rtl::OUString & _rHelpURL)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 //------------------------------------------------------------------------------
OSQLMessageBox(Window * _pParent,const UniString & _rTitle,const UniString & _rMessage,WinBits _nStyle,MessageType _eType,const::dbtools::SQLExceptionInfo * _pAdditionalErrorInfo)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 //--------------------------------------------------------------------------
~OSQLMessageBox()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 //==================================================================
OSQLWarningBox(Window * _pParent,const UniString & _rMessage,WinBits _nStyle,const::dbtools::SQLExceptionInfo * _pAdditionalErrorInfo)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