bump product version to 6.4.0.3
[LibreOffice.git] / vcl / source / window / errinf.cxx
blobf1e9109f5afb86481de590659bf7b1565576acfa
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 <rtl/instance.hxx>
22 #include <sal/log.hxx>
24 #include <tools/debug.hxx>
25 #include <vcl/errinf.hxx>
27 #include <algorithm>
28 #include <vector>
30 class ErrorHandler;
31 class TheErrorRegistry: public rtl::Static<ErrorRegistry, TheErrorRegistry> {};
33 class ErrorStringFactory
35 public:
36 static bool CreateString(const ErrorInfo*, OUString&);
39 bool ErrorStringFactory::CreateString(const ErrorInfo* pInfo, OUString& rStr)
41 for(const ErrorHandler *pHdlr : TheErrorRegistry::get().errorHandlers)
43 if(pHdlr->CreateString(pInfo, rStr))
44 return true;
46 return false;
49 ErrorRegistry::ErrorRegistry()
50 : pDsp(nullptr)
51 , bIsWindowDsp(false)
52 , nNextError(0)
54 for(DynamicErrorInfo*& rp : ppDynErrInfo)
55 rp = nullptr;
58 void ErrorRegistry::RegisterDisplay(BasicDisplayErrorFunc *aDsp)
60 ErrorRegistry &rData = TheErrorRegistry::get();
61 rData.bIsWindowDsp = false;
62 rData.pDsp = reinterpret_cast< DisplayFnPtr >(aDsp);
65 void ErrorRegistry::RegisterDisplay(WindowDisplayErrorFunc *aDsp)
67 ErrorRegistry &rData = TheErrorRegistry::get();
68 rData.bIsWindowDsp = true;
69 rData.pDsp = reinterpret_cast< DisplayFnPtr >(aDsp);
72 static void aDspFunc(const OUString &rErr, const OUString &rAction)
74 SAL_WARN("vcl", "Action: " << rAction << " Error: " << rErr);
77 ErrorHandler::ErrorHandler()
79 ErrorRegistry &rData = TheErrorRegistry::get();
80 rData.errorHandlers.insert(rData.errorHandlers.begin(), this);
82 if(!rData.pDsp)
83 ErrorRegistry::RegisterDisplay(&aDspFunc);
86 ErrorHandler::~ErrorHandler()
88 auto &rErrorHandlers = TheErrorRegistry::get().errorHandlers;
89 rErrorHandlers.erase( ::std::remove(rErrorHandlers.begin(), rErrorHandlers.end(), this),
90 rErrorHandlers.end());
93 bool ErrorHandler::GetErrorString(ErrCode nErrCodeId, OUString& rErrStr)
95 OUString aErr;
97 if(!nErrCodeId || nErrCodeId == ERRCODE_ABORT)
98 return false;
100 std::unique_ptr<ErrorInfo> pInfo = ErrorInfo::GetErrorInfo(nErrCodeId);
102 if (ErrorStringFactory::CreateString(pInfo.get(),aErr))
104 rErrStr = aErr;
105 return true;
108 return false;
111 DialogMask ErrorHandler::HandleError(ErrCode nErrCodeId, weld::Window *pParent, DialogMask nFlags)
113 if (nErrCodeId == ERRCODE_NONE || nErrCodeId == ERRCODE_ABORT)
114 return DialogMask::NONE;
116 ErrorRegistry &rData = TheErrorRegistry::get();
117 std::unique_ptr<ErrorInfo> pInfo = ErrorInfo::GetErrorInfo(nErrCodeId);
118 OUString aAction;
120 if (!rData.contexts.empty())
122 rData.contexts.front()->GetString(pInfo->GetErrorCode(), aAction);
124 for(ErrorContext *pCtx : rData.contexts)
126 if(pCtx->GetParent())
128 pParent = pCtx->GetParent();
129 break;
134 bool bWarning = nErrCodeId.IsWarning();
135 DialogMask nErrFlags = DialogMask::ButtonDefaultsOk | DialogMask::ButtonsOk;
136 if (bWarning)
137 nErrFlags |= DialogMask::MessageWarning;
138 else
139 nErrFlags |= DialogMask::MessageError;
141 DynamicErrorInfo* pDynPtr = dynamic_cast<DynamicErrorInfo*>(pInfo.get());
142 if(pDynPtr)
144 DialogMask nDynFlags = pDynPtr->GetDialogMask();
145 if( nDynFlags != DialogMask::NONE )
146 nErrFlags = nDynFlags;
149 OUString aErr;
150 if (ErrorStringFactory::CreateString(pInfo.get(), aErr))
152 if(!rData.pDsp)
154 SAL_WARN( "vcl", "Action: " << aAction << "Error: " << aErr);
156 else
158 if(!rData.bIsWindowDsp)
160 (*reinterpret_cast<BasicDisplayErrorFunc*>(rData.pDsp))(aErr,aAction);
161 return DialogMask::NONE;
163 else
165 if (nFlags != DialogMask::MAX)
166 nErrFlags = nFlags;
168 return (*reinterpret_cast<WindowDisplayErrorFunc*>(rData.pDsp))(
169 pParent, nErrFlags, aErr, aAction);
174 SAL_WARN( "vcl", "Error not handled " << pInfo->GetErrorCode());
175 // Error 1 (ERRCODE_ABORT) is classified as a General Error in sfx
176 if (pInfo->GetErrorCode() != ERRCODE_ABORT)
177 HandleError(ERRCODE_ABORT);
178 else
179 OSL_FAIL("ERRCODE_ABORT not handled");
181 return DialogMask::NONE;
184 struct ImplErrorContext
186 weld::Window *pWin;
189 ErrorContext::ErrorContext(weld::Window *pWinP)
190 : pImpl( new ImplErrorContext )
192 pImpl->pWin = pWinP;
193 TheErrorRegistry::get().contexts.insert(TheErrorRegistry::get().contexts.begin(), this);
196 ErrorContext::~ErrorContext()
198 auto &rContexts = TheErrorRegistry::get().contexts;
199 rContexts.erase( ::std::remove(rContexts.begin(), rContexts.end(), this), rContexts.end());
202 ErrorContext *ErrorContext::GetContext()
204 return TheErrorRegistry::get().contexts.empty() ? nullptr : TheErrorRegistry::get().contexts.front();
207 weld::Window* ErrorContext::GetParent()
209 return pImpl ? pImpl->pWin : nullptr;
212 class ImplDynamicErrorInfo
214 friend class DynamicErrorInfo;
215 friend class ErrorInfo;
217 private:
218 explicit ImplDynamicErrorInfo(DialogMask nInMask)
219 : nMask(nInMask)
222 void RegisterError(DynamicErrorInfo *);
223 static void UnRegisterError(DynamicErrorInfo const *);
224 static std::unique_ptr<ErrorInfo> GetDynamicErrorInfo(ErrCode nId);
226 ErrCode nErrId;
227 DialogMask const nMask;
231 void ImplDynamicErrorInfo::RegisterError(DynamicErrorInfo *pDynErrInfo)
233 // Register dynamic identifier
234 ErrorRegistry& rData = TheErrorRegistry::get();
235 nErrId = ErrCode(((sal_uInt32(rData.nNextError) + 1) << ERRCODE_DYNAMIC_SHIFT) +
236 sal_uInt32(pDynErrInfo->GetErrorCode()));
238 if(rData.ppDynErrInfo[rData.nNextError])
239 delete rData.ppDynErrInfo[rData.nNextError];
241 rData.ppDynErrInfo[rData.nNextError] = pDynErrInfo;
243 if(++rData.nNextError>=ERRCODE_DYNAMIC_COUNT)
244 rData.nNextError=0;
247 void ImplDynamicErrorInfo::UnRegisterError(DynamicErrorInfo const *pDynErrInfo)
249 DynamicErrorInfo **ppDynErrInfo = TheErrorRegistry::get().ppDynErrInfo;
250 sal_uInt32 nIdx = ErrCode(*pDynErrInfo).GetDynamic() - 1;
251 DBG_ASSERT(ppDynErrInfo[nIdx] == pDynErrInfo, "ErrHdl: Error not found");
253 if(ppDynErrInfo[nIdx]==pDynErrInfo)
254 ppDynErrInfo[nIdx]=nullptr;
257 std::unique_ptr<ErrorInfo> ImplDynamicErrorInfo::GetDynamicErrorInfo(ErrCode nId)
259 sal_uInt32 nIdx = nId.GetDynamic() - 1;
260 DynamicErrorInfo* pDynErrInfo = TheErrorRegistry::get().ppDynErrInfo[nIdx];
262 if(pDynErrInfo && ErrCode(*pDynErrInfo)==nId)
263 return std::unique_ptr<ErrorInfo>(pDynErrInfo);
264 else
265 return std::make_unique<ErrorInfo>(nId.StripDynamic());
268 std::unique_ptr<ErrorInfo> ErrorInfo::GetErrorInfo(ErrCode nId)
270 if(nId.IsDynamic())
271 return ImplDynamicErrorInfo::GetDynamicErrorInfo(nId);
272 else
273 return std::make_unique<ErrorInfo>(nId);
276 ErrorInfo::~ErrorInfo()
280 DynamicErrorInfo::DynamicErrorInfo(ErrCode nArgUserId, DialogMask nMask)
281 : ErrorInfo(nArgUserId),
282 pImpl(new ImplDynamicErrorInfo(nMask))
284 pImpl->RegisterError(this);
287 DynamicErrorInfo::~DynamicErrorInfo()
289 ImplDynamicErrorInfo::UnRegisterError(this);
292 DynamicErrorInfo::operator ErrCode() const
294 return pImpl->nErrId;
297 DialogMask DynamicErrorInfo::GetDialogMask() const
299 return pImpl->nMask;
302 StringErrorInfo::StringErrorInfo(
303 ErrCode nArgUserId, const OUString& aStringP, DialogMask nMask)
304 : DynamicErrorInfo(nArgUserId, nMask), aString(aStringP)
308 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */