Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / uui / source / iahndl-errorhandler.cxx
blob1faa1f59990b5ec9ff050434331c7fa4efd48a64
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <vcl/errinf.hxx>
21 #include <vcl/svapp.hxx>
22 #include <vcl/stdtext.hxx>
23 #include <vcl/weld.hxx>
25 #include <com/sun/star/task/XInteractionAbort.hpp>
26 #include <com/sun/star/task/XInteractionApprove.hpp>
27 #include <com/sun/star/task/XInteractionDisapprove.hpp>
28 #include <com/sun/star/task/XInteractionRetry.hpp>
30 #include <svx/svxerr.hxx>
31 #include <svx/dialogs.hrc>
32 #include <unotools/resmgr.hxx>
33 #include <osl/diagnose.h>
35 #include <ids.hxx>
36 #include <ids.hrc>
37 #include "getcontinuations.hxx"
39 #include "iahndl.hxx"
40 #include <memory>
42 using namespace com::sun::star;
44 namespace {
46 enum class MessageBoxStyle {
47 NONE = 0x0000,
48 Ok = 0x0001,
49 OkCancel = 0x0002,
50 YesNo = 0x0004,
51 YesNoCancel = 0x0008,
52 RetryCancel = 0x0010
55 DialogMask
56 executeErrorDialog(
57 weld::Window* pParent,
58 task::InteractionClassification eClassification,
59 OUString const & rContext,
60 OUString const & rMessage,
61 MessageBoxStyle nButtonMask)
63 SolarMutexGuard aGuard;
65 OUStringBuffer aText(rContext);
66 if (!rContext.isEmpty() && !rMessage.isEmpty())
67 aText.append(":\n");
68 //TODO! must be internationalized
69 aText.append(rMessage);
71 std::unique_ptr<weld::MessageDialog> xBox;
73 switch (eClassification)
75 case task::InteractionClassification_ERROR:
76 xBox.reset(Application::CreateMessageDialog(pParent,
77 VclMessageType::Error, VclButtonsType::NONE, aText.makeStringAndClear()));
78 break;
79 case task::InteractionClassification_WARNING:
80 xBox.reset(Application::CreateMessageDialog(pParent,
81 VclMessageType::Warning, VclButtonsType::NONE, aText.makeStringAndClear()));
82 break;
83 case task::InteractionClassification_INFO:
84 xBox.reset(Application::CreateMessageDialog(pParent,
85 VclMessageType::Info, VclButtonsType::NONE, aText.makeStringAndClear()));
86 break;
87 case task::InteractionClassification_QUERY:
88 xBox.reset(Application::CreateMessageDialog(pParent,
89 VclMessageType::Question, VclButtonsType::NONE, aText.makeStringAndClear()));
90 break;
91 default:
92 assert(false);
93 break;
97 switch (nButtonMask)
99 case MessageBoxStyle::NONE:
100 break;
101 case MessageBoxStyle::Ok:
102 xBox->add_button(GetStandardText(StandardButtonType::OK), static_cast<int>(DialogMask::ButtonsOk));
103 break;
104 case MessageBoxStyle::OkCancel:
105 xBox->add_button(GetStandardText(StandardButtonType::OK), static_cast<int>(DialogMask::ButtonsOk));
106 xBox->add_button(GetStandardText(StandardButtonType::Cancel), static_cast<int>(DialogMask::ButtonsCancel));
107 break;
108 case MessageBoxStyle::YesNo:
109 xBox->add_button(GetStandardText(StandardButtonType::Yes), static_cast<int>(DialogMask::ButtonsYes));
110 xBox->add_button(GetStandardText(StandardButtonType::No), static_cast<int>(DialogMask::ButtonsNo));
111 break;
112 case MessageBoxStyle::YesNoCancel:
113 xBox->add_button(GetStandardText(StandardButtonType::Yes), static_cast<int>(DialogMask::ButtonsYes));
114 xBox->add_button(GetStandardText(StandardButtonType::No), static_cast<int>(DialogMask::ButtonsNo));
115 xBox->add_button(GetStandardText(StandardButtonType::Cancel), static_cast<int>(DialogMask::ButtonsCancel));
116 break;
117 case MessageBoxStyle::RetryCancel:
118 xBox->add_button(GetStandardText(StandardButtonType::Retry), static_cast<int>(DialogMask::ButtonsRetry));
119 xBox->add_button(GetStandardText(StandardButtonType::Cancel), static_cast<int>(DialogMask::ButtonsCancel));
120 break;
123 return static_cast<DialogMask>(xBox->run());
128 void
129 UUIInteractionHelper::handleErrorHandlerRequest(
130 task::InteractionClassification eClassification,
131 ErrCode nErrorCode,
132 std::vector< OUString > const & rArguments,
133 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
134 rContinuations,
135 bool bObtainErrorStringOnly,
136 bool & bHasErrorString,
137 OUString & rErrorString)
139 if (bObtainErrorStringOnly)
141 bHasErrorString = isInformationalErrorMessageRequest(rContinuations);
142 if (!bHasErrorString)
143 return;
146 OUString aMessage;
148 enum Source { SOURCE_DEFAULT, SOURCE_SVX, SOURCE_UUI };
149 static char const * const aManager[3] = { "svt", "svx", "uui" };
150 static const ErrMsgCode* const aId[3]
151 = { RID_ERRHDL,
152 RID_SVXERRCODE,
153 RID_UUI_ERRHDL };
154 ErrCodeArea nErrorArea = nErrorCode.GetArea();
155 Source eSource =
156 nErrorArea < ErrCodeArea::Svx ? SOURCE_DEFAULT
157 : nErrorArea == ErrCodeArea::Svx ? SOURCE_SVX : SOURCE_UUI;
159 std::locale aResLocale = Translate::Create(aManager[eSource]);
160 ErrorResource aErrorResource(aId[eSource], aResLocale);
161 if (!aErrorResource.getString(nErrorCode, aMessage))
162 return;
165 aMessage = replaceMessageWithArguments( aMessage, rArguments );
167 if (bObtainErrorStringOnly)
169 rErrorString = aMessage;
170 return;
172 else
174 //TODO! It can happen that the buttons calculated below do not match
175 // the error text from the resource (e.g., some text that is not a
176 // question, but YES and NO buttons). Some error texts have
177 // ExtraData that specifies a set of buttons, but that data is not
178 // really useful, because a single error text may well make sense
179 // both with only an OK button and with RETRY and CANCEL buttons.
181 uno::Reference< task::XInteractionApprove > xApprove;
182 uno::Reference< task::XInteractionDisapprove > xDisapprove;
183 uno::Reference< task::XInteractionRetry > xRetry;
184 uno::Reference< task::XInteractionAbort > xAbort;
185 getContinuations(
186 rContinuations, &xApprove, &xDisapprove, &xRetry, &xAbort);
188 // The following mapping uses the bit mask
189 // Approve = 8,
190 // Disapprove = 4,
191 // Retry = 2,
192 // Abort = 1
194 // The mapping has five properties on which the code to select the
195 // correct continuation relies:
196 // 1 The OK button is mapped to Approve if that is available,
197 // otherwise to Abort if that is available, otherwise to none.
198 // 2 The CANCEL button is always mapped to Abort.
199 // 3 The RETRY button is always mapped to Retry.
200 // 4 The NO button is always mapped to Disapprove.
201 // 5 The YES button is always mapped to Approve.
203 // Because the WinBits button combinations are quite restricted, not
204 // every request can be served here.
206 // Finally, it seems to be better to leave default button
207 // determination to VCL (the favouring of CANCEL as default button
208 // seems to not always be what the user wants)...
209 MessageBoxStyle const aButtonMask[16]
210 = { MessageBoxStyle::NONE,
211 MessageBoxStyle::Ok /*| MessBoxStyle::DefaultOk*/, // Abort
212 MessageBoxStyle::NONE,
213 MessageBoxStyle::RetryCancel /*| MessBoxStyle::DefaultCancel*/, // Retry, Abort
214 MessageBoxStyle::NONE,
215 MessageBoxStyle::NONE,
216 MessageBoxStyle::NONE,
217 MessageBoxStyle::NONE,
218 MessageBoxStyle::Ok /*| MessBoxStyle::DefaultOk*/, // Approve
219 MessageBoxStyle::OkCancel /*| MessBoxStyle::DefaultCancel*/, // Approve, Abort
220 MessageBoxStyle::NONE,
221 MessageBoxStyle::NONE,
222 MessageBoxStyle::YesNo /*| MessBoxStyle::DefaultNo*/, // Approve, Disapprove
223 MessageBoxStyle::YesNoCancel /*| MessBoxStyle::DefaultCancel*/,
224 // Approve, Disapprove, Abort
225 MessageBoxStyle::NONE,
226 MessageBoxStyle::NONE };
228 MessageBoxStyle nButtonMask = aButtonMask[(xApprove.is() ? 8 : 0)
229 | (xDisapprove.is() ? 4 : 0)
230 | (xRetry.is() ? 2 : 0)
231 | (xAbort.is() ? 1 : 0)];
232 if (nButtonMask == MessageBoxStyle::NONE)
233 return;
235 //TODO! remove this backwards compatibility?
236 OUString aContext(m_aContextParam);
237 if (aContext.isEmpty() && nErrorCode != ERRCODE_NONE)
239 SolarMutexGuard aGuard;
240 ErrorContext * pContext = ErrorContext::GetContext();
241 if (pContext)
243 OUString aContextString;
244 if (pContext->GetString(nErrorCode, aContextString))
245 aContext = aContextString;
249 uno::Reference<awt::XWindow> xParent = getParentXWindow();
250 DialogMask nResult = executeErrorDialog(Application::GetFrameWeld(xParent),
251 eClassification, aContext, aMessage, nButtonMask );
253 switch (nResult)
255 case DialogMask::ButtonsOk:
256 OSL_ENSURE(xApprove.is() || xAbort.is(), "unexpected situation");
257 if (xApprove.is())
258 xApprove->select();
259 else if (xAbort.is())
260 xAbort->select();
261 break;
263 case DialogMask::ButtonsCancel:
264 OSL_ENSURE(xAbort.is(), "unexpected situation");
265 if (xAbort.is())
266 xAbort->select();
267 break;
269 case DialogMask::ButtonsRetry:
270 OSL_ENSURE(xRetry.is(), "unexpected situation");
271 if (xRetry.is())
272 xRetry->select();
273 break;
275 case DialogMask::ButtonsNo:
276 OSL_ENSURE(xDisapprove.is(), "unexpected situation");
277 if (xDisapprove.is())
278 xDisapprove->select();
279 break;
281 case DialogMask::ButtonsYes:
282 OSL_ENSURE(xApprove.is(), "unexpected situation");
283 if (xApprove.is())
284 xApprove->select();
285 break;
287 default: break;
293 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */