xref: /core/vcl/source/window/errinf.cxx (revision 63d676e7)
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 <utility>
25 #include <vcl/errinf.hxx>
26 
27 #include <algorithm>
28 #include <vector>
29 
30 class ErrorHandler;
31 
32 namespace {
33 
GetErrorRegistry()34     ErrorRegistry& GetErrorRegistry()
35     {
36         static ErrorRegistry gErrorRegistry;
37         return gErrorRegistry;
38     }
39 
40 }
41 
CreateString(const ErrCodeMsg & nInfo,OUString & rStr)42 bool ErrorStringFactory::CreateString(const ErrCodeMsg& nInfo, OUString& rStr)
43 {
44     for(const ErrorHandler *pHdlr : GetErrorRegistry().errorHandlers)
45     {
46         if(pHdlr->CreateString(nInfo, rStr))
47             return true;
48     }
49     return false;
50 }
51 
ErrorRegistry()52 ErrorRegistry::ErrorRegistry()
53     : pDsp(nullptr)
54     , bIsWindowDsp(false)
55     , m_bLock(false)
56 {
57 }
58 
RegisterDisplay(BasicDisplayErrorFunc * aDsp)59 void ErrorRegistry::RegisterDisplay(BasicDisplayErrorFunc *aDsp)
60 {
61     ErrorRegistry &rData = GetErrorRegistry();
62     rData.bIsWindowDsp = false;
63     rData.pDsp = reinterpret_cast< DisplayFnPtr >(aDsp);
64 }
65 
RegisterDisplay(WindowDisplayErrorFunc * aDsp)66 void ErrorRegistry::RegisterDisplay(WindowDisplayErrorFunc *aDsp)
67 {
68     ErrorRegistry &rData = GetErrorRegistry();
69     rData.bIsWindowDsp = true;
70     rData.pDsp = reinterpret_cast< DisplayFnPtr >(aDsp);
71 }
72 
SetLock(bool bLock)73 void ErrorRegistry::SetLock(bool bLock)
74 {
75     ErrorRegistry& rData = GetErrorRegistry();
76     rData.m_bLock = bLock;
77 }
78 
GetLock()79 bool ErrorRegistry::GetLock()
80 {
81     ErrorRegistry& rData = GetErrorRegistry();
82     return rData.m_bLock;
83 }
84 
Reset()85 void ErrorRegistry::Reset()
86 {
87     ErrorRegistry &rData = GetErrorRegistry();
88     rData = ErrorRegistry();
89 }
90 
aDspFunc(const OUString & rErr,const OUString & rAction)91 static void aDspFunc(const OUString &rErr, const OUString &rAction)
92 {
93     SAL_WARN("vcl", "Action: " << rAction << " Error: " << rErr);
94 }
95 
ErrorHandler()96 ErrorHandler::ErrorHandler()
97 {
98     ErrorRegistry &rData = GetErrorRegistry();
99     rData.errorHandlers.insert(rData.errorHandlers.begin(), this);
100 
101     if(!rData.pDsp)
102         ErrorRegistry::RegisterDisplay(&aDspFunc);
103 }
104 
~ErrorHandler()105 ErrorHandler::~ErrorHandler()
106 {
107     auto &rErrorHandlers = GetErrorRegistry().errorHandlers;
108     std::erase(rErrorHandlers, this);
109 }
110 
GetErrorString(const ErrCodeMsg & nErrCode,OUString & rErrStr)111 bool ErrorHandler::GetErrorString(const ErrCodeMsg& nErrCode, OUString& rErrStr)
112 {
113     OUString aErr;
114 
115     if(!nErrCode || nErrCode == ERRCODE_ABORT)
116         return false;
117 
118     if (ErrorStringFactory::CreateString(nErrCode, aErr))
119     {
120         rErrStr = aErr;
121         return true;
122     }
123 
124     return false;
125 }
126 
HandleError(const ErrCodeMsg & nErr,weld::Window * pParent,DialogMask nFlags)127 DialogMask ErrorHandler::HandleError(const ErrCodeMsg& nErr, weld::Window *pParent, DialogMask nFlags)
128 {
129     if (nErr == ERRCODE_NONE || nErr == ERRCODE_ABORT)
130         return DialogMask::NONE;
131 
132     ErrorRegistry &rData = GetErrorRegistry();
133     OUString aAction;
134 
135     if (!rData.contexts.empty())
136     {
137         rData.contexts.front()->GetString(nErr, aAction);
138 
139         for(ErrorContext *pCtx : rData.contexts)
140         {
141             if(pCtx->GetParent())
142             {
143                 pParent = pCtx->GetParent();
144                 break;
145             }
146         }
147     }
148 
149     bool bWarning = nErr.IsWarning();
150     DialogMask nErrFlags = DialogMask::ButtonDefaultsOk | DialogMask::ButtonsOk;
151     if (bWarning)
152         nErrFlags |= DialogMask::MessageWarning;
153     else
154         nErrFlags |= DialogMask::MessageError;
155 
156     if( nErr.GetDialogMask() != DialogMask::NONE )
157         nErrFlags = nErr.GetDialogMask();
158 
159     OUString aErr;
160     if (ErrorStringFactory::CreateString(nErr, aErr))
161     {
162         if (!rData.pDsp || rData.m_bLock)
163         {
164             SAL_WARN( "vcl", "Action: " << aAction <<  "Error: " << aErr);
165         }
166         else
167         {
168             if(!rData.bIsWindowDsp)
169             {
170                 (*reinterpret_cast<BasicDisplayErrorFunc*>(rData.pDsp))(aErr,aAction);
171                 return DialogMask::NONE;
172             }
173             else
174             {
175                 if (nFlags != DialogMask::MAX)
176                     nErrFlags = nFlags;
177 
178                 return (*reinterpret_cast<WindowDisplayErrorFunc*>(rData.pDsp))(
179                     pParent, nErrFlags, aErr, aAction);
180             }
181         }
182     }
183 
184     SAL_WARN( "vcl", "Error not handled " << nErr);
185     // Error 1 (ERRCODE_ABORT) is classified as a General Error in sfx
186     if (nErr.GetCode() != ERRCODE_ABORT)
187         HandleError(ERRCODE_ABORT);
188     else
189         OSL_FAIL("ERRCODE_ABORT not handled");
190 
191     return DialogMask::NONE;
192 }
193 
194 struct ImplErrorContext
195 {
196     weld::Window *pWin;
197 };
198 
ErrorContext(weld::Window * pWinP)199 ErrorContext::ErrorContext(weld::Window *pWinP)
200     : pImpl( new ImplErrorContext )
201 {
202     pImpl->pWin = pWinP;
203     GetErrorRegistry().contexts.insert(GetErrorRegistry().contexts.begin(), this);
204 }
205 
~ErrorContext()206 ErrorContext::~ErrorContext()
207 {
208     auto &rContexts = GetErrorRegistry().contexts;
209     std::erase(rContexts, this);
210 }
211 
GetContext()212 ErrorContext *ErrorContext::GetContext()
213 {
214     return GetErrorRegistry().contexts.empty() ? nullptr : GetErrorRegistry().contexts.front();
215 }
216 
GetParent()217 weld::Window* ErrorContext::GetParent()
218 {
219     return pImpl ? pImpl->pWin : nullptr;
220 }
221 
222 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
223