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