Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / uui / source / iahndl-errorhandler.cxx
blobaa893150e003b3865c1aa4b41bb3f75785b50735
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <memory>
31 #include "osl/mutex.hxx"
32 #include "vcl/svapp.hxx"
33 #include "vcl/msgbox.hxx"
35 #include "com/sun/star/task/XInteractionAbort.hpp"
36 #include "com/sun/star/task/XInteractionApprove.hpp"
37 #include "com/sun/star/task/XInteractionDisapprove.hpp"
38 #include "com/sun/star/task/XInteractionRetry.hpp"
40 #include "tools/errinf.hxx" // ErrorHandler, ErrorContext, ...
41 #include "svtools/svtools.hrc" // RID_ERRHDL
43 #include "ids.hrc"
44 #include "getcontinuations.hxx"
46 #include "iahndl.hxx"
48 using namespace com::sun::star;
50 namespace {
52 sal_uInt16
53 executeErrorDialog(
54 Window * pParent,
55 task::InteractionClassification eClassification,
56 rtl::OUString const & rContext,
57 rtl::OUString const & rMessage,
58 WinBits nButtonMask)
59 SAL_THROW((uno::RuntimeException))
61 SolarMutexGuard aGuard;
63 rtl::OUStringBuffer aText(rContext);
64 if (!rContext.isEmpty() && !rMessage.isEmpty())
65 aText.appendAscii(RTL_CONSTASCII_STRINGPARAM(":\n"));
66 //TODO! must be internationalized
67 aText.append(rMessage);
69 std::auto_ptr< MessBox > xBox;
70 try
72 switch (eClassification)
74 case task::InteractionClassification_ERROR:
75 xBox.reset(new ErrorBox(pParent,
76 nButtonMask,
77 aText.makeStringAndClear()));
78 break;
80 case task::InteractionClassification_WARNING:
81 xBox.reset(new WarningBox(pParent,
82 nButtonMask,
83 aText.makeStringAndClear()));
84 break;
86 case task::InteractionClassification_INFO:
87 if ((nButtonMask & 0x01F00000) == WB_DEF_OK)
88 //TODO! missing win bit button mask define (want to ignore
89 // any default button settings)...
90 xBox.reset(new InfoBox(pParent,
91 aText.makeStringAndClear()));
92 else
93 xBox.reset(new ErrorBox(pParent,
94 nButtonMask,
95 aText.makeStringAndClear()));
96 break;
98 case task::InteractionClassification_QUERY:
99 xBox.reset(new QueryBox(pParent,
100 nButtonMask,
101 aText.makeStringAndClear()));
102 break;
104 default:
105 OSL_ASSERT(false);
106 break;
109 catch (std::bad_alloc const &)
111 throw uno::RuntimeException(
112 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("out of memory")),
113 uno::Reference< uno::XInterface >());
116 sal_uInt16 aResult = xBox->Execute();
117 switch( aResult )
119 case BUTTONID_OK:
120 aResult = ERRCODE_BUTTON_OK;
121 break;
122 case BUTTONID_CANCEL:
123 aResult = ERRCODE_BUTTON_CANCEL;
124 break;
125 case BUTTONID_YES:
126 aResult = ERRCODE_BUTTON_YES;
127 break;
128 case BUTTONID_NO:
129 aResult = ERRCODE_BUTTON_NO;
130 break;
131 case BUTTONID_RETRY:
132 aResult = ERRCODE_BUTTON_RETRY;
133 break;
136 return aResult;
141 void
142 UUIInteractionHelper::handleErrorHandlerRequest(
143 task::InteractionClassification eClassification,
144 ErrCode nErrorCode,
145 std::vector< rtl::OUString > const & rArguments,
146 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
147 rContinuations,
148 bool bObtainErrorStringOnly,
149 bool & bHasErrorString,
150 rtl::OUString & rErrorString)
151 SAL_THROW((uno::RuntimeException))
153 if (bObtainErrorStringOnly)
155 bHasErrorString = isInformationalErrorMessageRequest(rContinuations);
156 if (!bHasErrorString)
157 return;
160 rtl::OUString aMessage;
162 enum Source { SOURCE_DEFAULT, SOURCE_CNT, SOURCE_SVX, SOURCE_UUI };
163 static char const * const aManager[4] = { "ofa", "cnt", "svx", "uui" };
164 static sal_uInt16 const aId[4]
165 = { RID_ERRHDL,
166 RID_CHAOS_START + 12,
167 // cf. chaos/source/inc/cntrids.hrc, where
168 // #define RID_CHAOS_ERRHDL (RID_CHAOS_START + 12)
169 RID_SVX_START + 350, // RID_SVXERRCODE
170 RID_UUI_ERRHDL };
171 ErrCode nErrorId = nErrorCode & ~ERRCODE_WARNING_MASK;
172 Source eSource = nErrorId < ERRCODE_AREA_LIB1 ?
173 SOURCE_DEFAULT :
174 nErrorId >= ERRCODE_AREA_CHAOS
175 && nErrorId < ERRCODE_AREA_CHAOS_END ?
176 SOURCE_CNT :
177 nErrorId >= ERRCODE_AREA_SVX
178 && nErrorId <= ERRCODE_AREA_SVX_END ?
179 SOURCE_SVX :
180 SOURCE_UUI;
182 SolarMutexGuard aGuard;
183 std::auto_ptr< ResMgr > xManager;
184 xManager.reset(ResMgr::CreateResMgr(aManager[eSource]));
185 if (!xManager.get())
186 return;
187 ResId aResId(aId[eSource], *xManager.get());
188 if (!ErrorResource(aResId).getString(nErrorCode, aMessage))
189 return;
192 aMessage = replaceMessageWithArguments( aMessage, rArguments );
194 if (bObtainErrorStringOnly)
196 rErrorString = aMessage;
197 return;
199 else
201 //TODO! It can happen that the buttons calculated below do not match
202 // the error text from the resource (e.g., some text that is not a
203 // question, but YES and NO buttons). Some error texts have
204 // ExtraData that specifies a set of buttons, but that data is not
205 // really useful, because a single error text may well make sense
206 // both with only an OK button and with RETRY and CANCEL buttons.
208 uno::Reference< task::XInteractionApprove > xApprove;
209 uno::Reference< task::XInteractionDisapprove > xDisapprove;
210 uno::Reference< task::XInteractionRetry > xRetry;
211 uno::Reference< task::XInteractionAbort > xAbort;
212 getContinuations(
213 rContinuations, &xApprove, &xDisapprove, &xRetry, &xAbort);
215 // The following mapping uses the bit mask
216 // Approve = 8,
217 // Disapprove = 4,
218 // Retry = 2,
219 // Abort = 1
221 // The mapping has five properties on which the code to select the
222 // correct continuation relies:
223 // 1 The OK button is mapped to Approve if that is available,
224 // otherwise to Abort if that is available, otherwise to none.
225 // 2 The CANCEL button is always mapped to Abort.
226 // 3 The RETRY button is always mapped to Retry.
227 // 4 The NO button is always mapped to Disapprove.
228 // 5 The YES button is always mapped to Approve.
230 // Because the WinBits button combinations are quite restricted, not
231 // every request can be served here.
233 // Finally, it seems to be better to leave default button
234 // determination to VCL (the favouring of CANCEL as default button
235 // seems to not always be what the user wants)...
236 WinBits const aButtonMask[16]
237 = { 0,
238 WB_OK /*| WB_DEF_OK*/, // Abort
240 WB_RETRY_CANCEL /*| WB_DEF_CANCEL*/, // Retry, Abort
245 WB_OK /*| WB_DEF_OK*/, // Approve
246 WB_OK_CANCEL /*| WB_DEF_CANCEL*/, // Approve, Abort
249 WB_YES_NO /*| WB_DEF_NO*/, // Approve, Disapprove
250 WB_YES_NO_CANCEL /*| WB_DEF_CANCEL*/,
251 // Approve, Disapprove, Abort
253 0 };
255 WinBits nButtonMask = aButtonMask[(xApprove.is() ? 8 : 0)
256 | (xDisapprove.is() ? 4 : 0)
257 | (xRetry.is() ? 2 : 0)
258 | (xAbort.is() ? 1 : 0)];
259 if (nButtonMask == 0)
260 return;
262 //TODO! remove this backwards compatibility?
263 rtl::OUString aContext(getContextProperty());
264 if (aContext.isEmpty() && nErrorCode != 0)
266 SolarMutexGuard aGuard;
267 ErrorContext * pContext = ErrorContext::GetContext();
268 if (pContext)
270 UniString aContextString;
271 if (pContext->GetString(nErrorCode, aContextString))
272 aContext = aContextString;
276 sal_uInt16 nResult = executeErrorDialog(
277 getParentProperty(), eClassification, aContext, aMessage, nButtonMask );
279 switch (nResult)
281 case ERRCODE_BUTTON_OK:
282 OSL_ENSURE(xApprove.is() || xAbort.is(), "unexpected situation");
283 if (xApprove.is())
284 xApprove->select();
285 else if (xAbort.is())
286 xAbort->select();
287 break;
289 case ERRCODE_BUTTON_CANCEL:
290 OSL_ENSURE(xAbort.is(), "unexpected situation");
291 if (xAbort.is())
292 xAbort->select();
293 break;
295 case ERRCODE_BUTTON_RETRY:
296 OSL_ENSURE(xRetry.is(), "unexpected situation");
297 if (xRetry.is())
298 xRetry->select();
299 break;
301 case ERRCODE_BUTTON_NO:
302 OSL_ENSURE(xDisapprove.is(), "unexpected situation");
303 if (xDisapprove.is())
304 xDisapprove->select();
305 break;
307 case ERRCODE_BUTTON_YES:
308 OSL_ENSURE(xApprove.is(), "unexpected situation");
309 if (xApprove.is())
310 xApprove->select();
311 break;
317 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */