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