LibreOffice Module vcl (master)  1
errinf.cxx
Go to the documentation of this file.
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 #include <osl/diagnose.h>
21 #include <sal/log.hxx>
22 
23 #include <tools/debug.hxx>
24 #include <vcl/errinf.hxx>
25 
26 #include <algorithm>
27 #include <vector>
28 
29 class ErrorHandler;
30 
31 namespace {
32 
33  ErrorRegistry& GetErrorRegistry()
34  {
35  static ErrorRegistry gErrorRegistry;
36  return gErrorRegistry;
37  }
38 
39 }
40 
41 bool ErrorStringFactory::CreateString(const ErrorInfo* pInfo, OUString& rStr)
42 {
43  for(const ErrorHandler *pHdlr : GetErrorRegistry().errorHandlers)
44  {
45  if(pHdlr->CreateString(pInfo, rStr))
46  return true;
47  }
48  return false;
49 }
50 
52  : pDsp(nullptr)
53  , bIsWindowDsp(false)
54  , m_bLock(false)
55  , nNextError(0)
56 {
57  for(DynamicErrorInfo*& rp : ppDynErrInfo)
58  rp = nullptr;
59 }
60 
62 {
63  ErrorRegistry &rData = GetErrorRegistry();
64  rData.bIsWindowDsp = false;
65  rData.pDsp = reinterpret_cast< DisplayFnPtr >(aDsp);
66 }
67 
69 {
70  ErrorRegistry &rData = GetErrorRegistry();
71  rData.bIsWindowDsp = true;
72  rData.pDsp = reinterpret_cast< DisplayFnPtr >(aDsp);
73 }
74 
75 void ErrorRegistry::SetLock(bool bLock)
76 {
77  ErrorRegistry& rData = GetErrorRegistry();
78  rData.m_bLock = bLock;
79 }
80 
82 {
83  ErrorRegistry& rData = GetErrorRegistry();
84  return rData.m_bLock;
85 }
86 
88 {
89  ErrorRegistry &rData = GetErrorRegistry();
90  rData = ErrorRegistry();
91 }
92 
93 static void aDspFunc(const OUString &rErr, const OUString &rAction)
94 {
95  SAL_WARN("vcl", "Action: " << rAction << " Error: " << rErr);
96 }
97 
98 ErrorHandler::ErrorHandler()
99 {
100  ErrorRegistry &rData = GetErrorRegistry();
101  rData.errorHandlers.insert(rData.errorHandlers.begin(), this);
102 
103  if(!rData.pDsp)
105 }
106 
107 ErrorHandler::~ErrorHandler()
108 {
109  auto &rErrorHandlers = GetErrorRegistry().errorHandlers;
110  rErrorHandlers.erase( ::std::remove(rErrorHandlers.begin(), rErrorHandlers.end(), this),
111  rErrorHandlers.end());
112 }
113 
114 bool ErrorHandler::GetErrorString(ErrCode nErrCodeId, OUString& rErrStr)
115 {
116  OUString aErr;
117 
118  if(!nErrCodeId || nErrCodeId == ERRCODE_ABORT)
119  return false;
120 
121  std::unique_ptr<ErrorInfo> pInfo = ErrorInfo::GetErrorInfo(nErrCodeId);
122 
123  if (ErrorStringFactory::CreateString(pInfo.get(),aErr))
124  {
125  rErrStr = aErr;
126  return true;
127  }
128 
129  return false;
130 }
131 
132 DialogMask ErrorHandler::HandleError(ErrCode nErrCodeId, weld::Window *pParent, DialogMask nFlags)
133 {
134  if (nErrCodeId == ERRCODE_NONE || nErrCodeId == ERRCODE_ABORT)
135  return DialogMask::NONE;
136 
137  ErrorRegistry &rData = GetErrorRegistry();
138  std::unique_ptr<ErrorInfo> pInfo = ErrorInfo::GetErrorInfo(nErrCodeId);
139  OUString aAction;
140 
141  if (!rData.contexts.empty())
142  {
143  rData.contexts.front()->GetString(pInfo->GetErrorCode(), aAction);
144 
145  for(ErrorContext *pCtx : rData.contexts)
146  {
147  if(pCtx->GetParent())
148  {
149  pParent = pCtx->GetParent();
150  break;
151  }
152  }
153  }
154 
155  bool bWarning = nErrCodeId.IsWarning();
157  if (bWarning)
158  nErrFlags |= DialogMask::MessageWarning;
159  else
160  nErrFlags |= DialogMask::MessageError;
161 
162  DynamicErrorInfo* pDynPtr = dynamic_cast<DynamicErrorInfo*>(pInfo.get());
163  if(pDynPtr)
164  {
165  DialogMask nDynFlags = pDynPtr->GetDialogMask();
166  if( nDynFlags != DialogMask::NONE )
167  nErrFlags = nDynFlags;
168  }
169 
170  OUString aErr;
171  if (ErrorStringFactory::CreateString(pInfo.get(), aErr))
172  {
173  if (!rData.pDsp || rData.m_bLock)
174  {
175  SAL_WARN( "vcl", "Action: " << aAction << "Error: " << aErr);
176  }
177  else
178  {
179  if(!rData.bIsWindowDsp)
180  {
181  (*reinterpret_cast<BasicDisplayErrorFunc*>(rData.pDsp))(aErr,aAction);
182  return DialogMask::NONE;
183  }
184  else
185  {
186  if (nFlags != DialogMask::MAX)
187  nErrFlags = nFlags;
188 
189  return (*reinterpret_cast<WindowDisplayErrorFunc*>(rData.pDsp))(
190  pParent, nErrFlags, aErr, aAction);
191  }
192  }
193  }
194 
195  SAL_WARN( "vcl", "Error not handled " << pInfo->GetErrorCode());
196  // Error 1 (ERRCODE_ABORT) is classified as a General Error in sfx
197  if (pInfo->GetErrorCode() != ERRCODE_ABORT)
198  HandleError(ERRCODE_ABORT);
199  else
200  OSL_FAIL("ERRCODE_ABORT not handled");
201 
202  return DialogMask::NONE;
203 }
204 
206 {
208 };
209 
211  : pImpl( new ImplErrorContext )
212 {
213  pImpl->pWin = pWinP;
214  GetErrorRegistry().contexts.insert(GetErrorRegistry().contexts.begin(), this);
215 }
216 
218 {
219  auto &rContexts = GetErrorRegistry().contexts;
220  rContexts.erase( ::std::remove(rContexts.begin(), rContexts.end(), this), rContexts.end());
221 }
222 
224 {
225  return GetErrorRegistry().contexts.empty() ? nullptr : GetErrorRegistry().contexts.front();
226 }
227 
229 {
230  return pImpl ? pImpl->pWin : nullptr;
231 }
232 
234 {
235  friend class DynamicErrorInfo;
236  friend class ErrorInfo;
237 
238 private:
240  : nMask(nInMask)
241  {
242  }
244  static void UnRegisterError(DynamicErrorInfo const *);
245  static std::unique_ptr<ErrorInfo> GetDynamicErrorInfo(ErrCode nId);
246 
249 
250 };
251 
253 {
254  // Register dynamic identifier
255  ErrorRegistry& rData = GetErrorRegistry();
256  nErrId = ErrCode(((sal_uInt32(rData.nNextError) + 1) << ERRCODE_DYNAMIC_SHIFT) +
257  sal_uInt32(pDynErrInfo->GetErrorCode()));
258 
259  if(rData.ppDynErrInfo[rData.nNextError])
260  delete rData.ppDynErrInfo[rData.nNextError];
261 
262  rData.ppDynErrInfo[rData.nNextError] = pDynErrInfo;
263 
264  if(++rData.nNextError>=ERRCODE_DYNAMIC_COUNT)
265  rData.nNextError=0;
266 }
267 
269 {
270  DynamicErrorInfo **ppDynErrInfo = GetErrorRegistry().ppDynErrInfo;
271  sal_uInt32 nIdx = ErrCode(*pDynErrInfo).GetDynamic() - 1;
272  DBG_ASSERT(ppDynErrInfo[nIdx] == pDynErrInfo, "ErrHdl: Error not found");
273 
274  if(ppDynErrInfo[nIdx]==pDynErrInfo)
275  ppDynErrInfo[nIdx]=nullptr;
276 }
277 
278 std::unique_ptr<ErrorInfo> ImplDynamicErrorInfo::GetDynamicErrorInfo(ErrCode nId)
279 {
280  sal_uInt32 nIdx = nId.GetDynamic() - 1;
281  DynamicErrorInfo* pDynErrInfo = GetErrorRegistry().ppDynErrInfo[nIdx];
282 
283  if(pDynErrInfo && ErrCode(*pDynErrInfo)==nId)
284  return std::unique_ptr<ErrorInfo>(pDynErrInfo);
285  else
286  return std::make_unique<ErrorInfo>(nId.StripDynamic());
287 }
288 
289 std::unique_ptr<ErrorInfo> ErrorInfo::GetErrorInfo(ErrCode nId)
290 {
291  if(nId.IsDynamic())
293  else
294  return std::make_unique<ErrorInfo>(nId);
295 }
296 
298 {
299 }
300 
302 : ErrorInfo(nArgUserId),
303  pImpl(new ImplDynamicErrorInfo(nMask))
304 {
305  pImpl->RegisterError(this);
306 }
307 
309 {
311 }
312 
313 DynamicErrorInfo::operator ErrCode() const
314 {
315  return pImpl->nErrId;
316 }
317 
319 {
320  return pImpl->nMask;
321 }
322 
324  ErrCode nArgUserId, const OUString& aStringP, DialogMask nMask)
325 : DynamicErrorInfo(nArgUserId, nMask), aString(aStringP)
326 {
327 }
328 
329 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static bool CreateString(const ErrorInfo *, OUString &)
Definition: errinf.cxx:41
DisplayFnPtr pDsp
Definition: errinf.hxx:75
void RegisterError(DynamicErrorInfo *)
Definition: errinf.cxx:252
const ContentProperties & rData
virtual ~ErrorContext()
Definition: errinf.cxx:217
std::vector< ErrorHandler * > errorHandlers
Definition: errinf.hxx:82
bool bIsWindowDsp
Definition: errinf.hxx:76
DialogMask GetDialogMask() const
Definition: errinf.cxx:318
DialogMask
Definition: errinf.hxx:88
DynamicErrorInfo(ErrCode nUserId, DialogMask nMask)
Definition: errinf.cxx:301
#define ERRCODE_DYNAMIC_SHIFT
Definition: errcode.hxx:51
weld::Window * GetParent()
Definition: errinf.cxx:228
bool m_bLock
Definition: errinf.hxx:78
virtual ~DynamicErrorInfo() override
Definition: errinf.cxx:308
ImplDynamicErrorInfo(DialogMask nInMask)
Definition: errinf.cxx:239
#define DBG_ASSERT(sCon, aError)
DialogMask WindowDisplayErrorFunc(weld::Window *, DialogMask eMask, const OUString &rErr, const OUString &rAction)
Definition: errinf.hxx:50
std::unique_ptr< ImplDynamicErrorInfo > pImpl
Definition: errinf.hxx:173
ErrorContext(weld::Window *pWin)
Definition: errinf.cxx:210
std::unique_ptr< ImplErrorContext > pImpl
Definition: errinf.hxx:223
static ErrorContext * GetContext()
Definition: errinf.cxx:223
void BasicDisplayErrorFunc(const OUString &rErr, const OUString &rAction)
Definition: errinf.hxx:53
static void Reset()
Definition: errinf.cxx:87
ErrCode const & GetErrorCode() const
Definition: errinf.hxx:153
DialogMask nMask
Definition: errinf.cxx:248
static std::unique_ptr< ErrorInfo > GetDynamicErrorInfo(ErrCode nId)
Definition: errinf.cxx:278
static bool GetLock()
Definition: errinf.cxx:81
sal_uInt32 GetDynamic() const
Definition: errcode.hxx:116
#define ERRCODE_NONE
Definition: errcode.hxx:196
virtual ~ErrorInfo()
Definition: errinf.cxx:297
void(* DisplayFnPtr)()
Definition: errinf.hxx:48
static void SetLock(bool bLock)
Definition: errinf.cxx:75
bool IsWarning() const
Definition: errcode.hxx:100
DynamicErrorInfo * ppDynErrInfo[ERRCODE_DYNAMIC_COUNT]
Definition: errinf.hxx:85
bool IsDynamic() const
Definition: errcode.hxx:112
std::vector< ErrorContext * > contexts
Definition: errinf.hxx:83
StringErrorInfo(ErrCode nUserId, const OUString &aStringP, DialogMask nMask=DialogMask::NONE)
Definition: errinf.cxx:323
weld::Window * pWin
Definition: errinf.cxx:207
static void RegisterDisplay(BasicDisplayErrorFunc *)
Definition: errinf.cxx:61
#define ERRCODE_ABORT
Definition: errcode.hxx:268
#define ERRCODE_DYNAMIC_COUNT
Definition: errcode.hxx:55
#define SAL_WARN(area, stream)
static std::unique_ptr< ErrorInfo > GetErrorInfo(ErrCode)
Definition: errinf.cxx:289
sal_uInt16 nNextError
Definition: errinf.hxx:80
static void aDspFunc(const OUString &rErr, const OUString &rAction)
Definition: errinf.cxx:93
static void UnRegisterError(DynamicErrorInfo const *)
Definition: errinf.cxx:268
ErrCode StripDynamic() const
Definition: errcode.hxx:120