bump product version to 7.6.3.2-android
[LibreOffice.git] / vcl / source / window / errinf.cxx
blob7dc1b3253874ce25a0b4f3c1e183dfd674b08c6b
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 <osl/diagnose.h>
21 #include <sal/log.hxx>
23 #include <tools/debug.hxx>
24 #include <utility>
25 #include <vcl/errinf.hxx>
27 #include <algorithm>
28 #include <vector>
30 class ErrorHandler;
32 namespace {
34 ErrorRegistry& GetErrorRegistry()
36 static ErrorRegistry gErrorRegistry;
37 return gErrorRegistry;
42 bool ErrorStringFactory::CreateString(const ErrorInfo* pInfo, OUString& rStr)
44 for(const ErrorHandler *pHdlr : GetErrorRegistry().errorHandlers)
46 if(pHdlr->CreateString(pInfo, rStr))
47 return true;
49 return false;
52 ErrorRegistry::ErrorRegistry()
53 : pDsp(nullptr)
54 , bIsWindowDsp(false)
55 , m_bLock(false)
56 , nNextError(0)
58 for(DynamicErrorInfo*& rp : ppDynErrInfo)
59 rp = nullptr;
62 void ErrorRegistry::RegisterDisplay(BasicDisplayErrorFunc *aDsp)
64 ErrorRegistry &rData = GetErrorRegistry();
65 rData.bIsWindowDsp = false;
66 rData.pDsp = reinterpret_cast< DisplayFnPtr >(aDsp);
69 void ErrorRegistry::RegisterDisplay(WindowDisplayErrorFunc *aDsp)
71 ErrorRegistry &rData = GetErrorRegistry();
72 rData.bIsWindowDsp = true;
73 rData.pDsp = reinterpret_cast< DisplayFnPtr >(aDsp);
76 void ErrorRegistry::SetLock(bool bLock)
78 ErrorRegistry& rData = GetErrorRegistry();
79 rData.m_bLock = bLock;
82 bool ErrorRegistry::GetLock()
84 ErrorRegistry& rData = GetErrorRegistry();
85 return rData.m_bLock;
88 void ErrorRegistry::Reset()
90 ErrorRegistry &rData = GetErrorRegistry();
91 rData = ErrorRegistry();
94 static void aDspFunc(const OUString &rErr, const OUString &rAction)
96 SAL_WARN("vcl", "Action: " << rAction << " Error: " << rErr);
99 ErrorHandler::ErrorHandler()
101 ErrorRegistry &rData = GetErrorRegistry();
102 rData.errorHandlers.insert(rData.errorHandlers.begin(), this);
104 if(!rData.pDsp)
105 ErrorRegistry::RegisterDisplay(&aDspFunc);
108 ErrorHandler::~ErrorHandler()
110 auto &rErrorHandlers = GetErrorRegistry().errorHandlers;
111 rErrorHandlers.erase( ::std::remove(rErrorHandlers.begin(), rErrorHandlers.end(), this),
112 rErrorHandlers.end());
115 bool ErrorHandler::GetErrorString(ErrCode nErrCodeId, OUString& rErrStr)
117 OUString aErr;
119 if(!nErrCodeId || nErrCodeId == ERRCODE_ABORT)
120 return false;
122 std::unique_ptr<ErrorInfo> pInfo = ErrorInfo::GetErrorInfo(nErrCodeId);
124 if (ErrorStringFactory::CreateString(pInfo.get(),aErr))
126 rErrStr = aErr;
127 return true;
130 return false;
133 DialogMask ErrorHandler::HandleError(ErrCode nErrCodeId, weld::Window *pParent, DialogMask nFlags)
135 if (nErrCodeId == ERRCODE_NONE || nErrCodeId == ERRCODE_ABORT)
136 return DialogMask::NONE;
138 ErrorRegistry &rData = GetErrorRegistry();
139 std::unique_ptr<ErrorInfo> pInfo = ErrorInfo::GetErrorInfo(nErrCodeId);
140 OUString aAction;
142 if (!rData.contexts.empty())
144 rData.contexts.front()->GetString(pInfo->GetErrorCode(), aAction);
146 for(ErrorContext *pCtx : rData.contexts)
148 if(pCtx->GetParent())
150 pParent = pCtx->GetParent();
151 break;
156 bool bWarning = nErrCodeId.IsWarning();
157 DialogMask nErrFlags = DialogMask::ButtonDefaultsOk | DialogMask::ButtonsOk;
158 if (bWarning)
159 nErrFlags |= DialogMask::MessageWarning;
160 else
161 nErrFlags |= DialogMask::MessageError;
163 DynamicErrorInfo* pDynPtr = dynamic_cast<DynamicErrorInfo*>(pInfo.get());
164 if(pDynPtr)
166 DialogMask nDynFlags = pDynPtr->GetDialogMask();
167 if( nDynFlags != DialogMask::NONE )
168 nErrFlags = nDynFlags;
171 OUString aErr;
172 if (ErrorStringFactory::CreateString(pInfo.get(), aErr))
174 if (!rData.pDsp || rData.m_bLock)
176 SAL_WARN( "vcl", "Action: " << aAction << "Error: " << aErr);
178 else
180 if(!rData.bIsWindowDsp)
182 (*reinterpret_cast<BasicDisplayErrorFunc*>(rData.pDsp))(aErr,aAction);
183 return DialogMask::NONE;
185 else
187 if (nFlags != DialogMask::MAX)
188 nErrFlags = nFlags;
190 return (*reinterpret_cast<WindowDisplayErrorFunc*>(rData.pDsp))(
191 pParent, nErrFlags, aErr, aAction);
196 SAL_WARN( "vcl", "Error not handled " << pInfo->GetErrorCode());
197 // Error 1 (ERRCODE_ABORT) is classified as a General Error in sfx
198 if (pInfo->GetErrorCode() != ERRCODE_ABORT)
199 HandleError(ERRCODE_ABORT);
200 else
201 OSL_FAIL("ERRCODE_ABORT not handled");
203 return DialogMask::NONE;
206 struct ImplErrorContext
208 weld::Window *pWin;
211 ErrorContext::ErrorContext(weld::Window *pWinP)
212 : pImpl( new ImplErrorContext )
214 pImpl->pWin = pWinP;
215 GetErrorRegistry().contexts.insert(GetErrorRegistry().contexts.begin(), this);
218 ErrorContext::~ErrorContext()
220 auto &rContexts = GetErrorRegistry().contexts;
221 rContexts.erase( ::std::remove(rContexts.begin(), rContexts.end(), this), rContexts.end());
224 ErrorContext *ErrorContext::GetContext()
226 return GetErrorRegistry().contexts.empty() ? nullptr : GetErrorRegistry().contexts.front();
229 weld::Window* ErrorContext::GetParent()
231 return pImpl ? pImpl->pWin : nullptr;
234 class ImplDynamicErrorInfo
236 friend class DynamicErrorInfo;
237 friend class ErrorInfo;
239 private:
240 explicit ImplDynamicErrorInfo(DialogMask nInMask)
241 : nMask(nInMask)
244 void RegisterError(DynamicErrorInfo *);
245 static void UnRegisterError(DynamicErrorInfo const *);
246 static std::unique_ptr<ErrorInfo> GetDynamicErrorInfo(ErrCode nId);
248 ErrCode nErrId;
249 DialogMask nMask;
253 void ImplDynamicErrorInfo::RegisterError(DynamicErrorInfo *pDynErrInfo)
255 // Register dynamic identifier
256 ErrorRegistry& rData = GetErrorRegistry();
257 nErrId = ErrCode(((sal_uInt32(rData.nNextError) + 1) << ERRCODE_DYNAMIC_SHIFT) +
258 sal_uInt32(pDynErrInfo->GetErrorCode()));
260 if(rData.ppDynErrInfo[rData.nNextError])
261 delete rData.ppDynErrInfo[rData.nNextError];
263 rData.ppDynErrInfo[rData.nNextError] = pDynErrInfo;
265 if(++rData.nNextError>=ERRCODE_DYNAMIC_COUNT)
266 rData.nNextError=0;
269 void ImplDynamicErrorInfo::UnRegisterError(DynamicErrorInfo const *pDynErrInfo)
271 DynamicErrorInfo **ppDynErrInfo = GetErrorRegistry().ppDynErrInfo;
272 sal_uInt32 nIdx = ErrCode(*pDynErrInfo).GetDynamic() - 1;
273 DBG_ASSERT(ppDynErrInfo[nIdx] == pDynErrInfo, "ErrHdl: Error not found");
275 if(ppDynErrInfo[nIdx]==pDynErrInfo)
276 ppDynErrInfo[nIdx]=nullptr;
279 std::unique_ptr<ErrorInfo> ImplDynamicErrorInfo::GetDynamicErrorInfo(ErrCode nId)
281 sal_uInt32 nIdx = nId.GetDynamic() - 1;
282 DynamicErrorInfo* pDynErrInfo = GetErrorRegistry().ppDynErrInfo[nIdx];
284 if(pDynErrInfo && ErrCode(*pDynErrInfo)==nId)
285 return std::unique_ptr<ErrorInfo>(pDynErrInfo);
286 else
287 return std::make_unique<ErrorInfo>(nId.StripDynamic());
290 std::unique_ptr<ErrorInfo> ErrorInfo::GetErrorInfo(ErrCode nId)
292 if(nId.IsDynamic())
293 return ImplDynamicErrorInfo::GetDynamicErrorInfo(nId);
294 else
295 return std::make_unique<ErrorInfo>(nId);
298 ErrorInfo::~ErrorInfo()
302 DynamicErrorInfo::DynamicErrorInfo(ErrCode nArgUserId, DialogMask nMask)
303 : ErrorInfo(nArgUserId),
304 pImpl(new ImplDynamicErrorInfo(nMask))
306 pImpl->RegisterError(this);
309 DynamicErrorInfo::~DynamicErrorInfo()
311 ImplDynamicErrorInfo::UnRegisterError(this);
314 DynamicErrorInfo::operator ErrCode() const
316 return pImpl->nErrId;
319 DialogMask DynamicErrorInfo::GetDialogMask() const
321 return pImpl->nMask;
324 StringErrorInfo::StringErrorInfo(
325 ErrCode nArgUserId, OUString aStringP, DialogMask nMask)
326 : DynamicErrorInfo(nArgUserId, nMask), aString(std::move(aStringP))
330 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */