VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/globals/UIErrorString.cpp

Last change on this file was 103710, checked in by vboxsync, 2 months ago

FE/Qt: Get rid of unwanted UICommon includes across whole the GUI.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.5 KB
Line 
1/* $Id: UIErrorString.cpp 103710 2024-03-06 16:53:27Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIErrorString class implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* Qt includes: */
29#include <QApplication>
30#include <QObject>
31#include <QPalette>
32
33/* GUI includes: */
34#include "UIErrorString.h"
35#include "UITranslator.h"
36
37/* COM includes: */
38#include "COMDefs.h"
39#include "CProgress.h"
40#include "CVirtualBoxErrorInfo.h"
41
42
43/* static */
44QString UIErrorString::formatRC(HRESULT rc)
45{
46 /** @todo r=bird: Not sure why we set the sign bit 31 bit for warnings.
47 * Maybe to try get the error variant? It won't really work for S_FALSE and
48 * probably a bunch of others too. I've modified it on windows to try get
49 * the exact one, the one with the top bit set, or just the value. */
50#ifdef RT_OS_WINDOWS
51 char szDefine[80];
52 if ( !SUCCEEDED_WARNING(rc)
53 || ( RTErrWinQueryDefine(rc, szDefine, sizeof(szDefine), true /*fFailIfUnknown*/) == VERR_NOT_FOUND
54 && RTErrWinQueryDefine(rc | 0x80000000, szDefine, sizeof(szDefine), true /*fFailIfUnknown*/) == VERR_NOT_FOUND))
55 RTErrWinQueryDefine(rc, szDefine, sizeof(szDefine), false /*fFailIfUnknown*/);
56
57 return QString::asprintf("%s", szDefine);
58#else
59 const char *pszDefine = RTErrCOMGet(SUCCEEDED_WARNING(rc) ? rc | 0x80000000 : rc)->pszDefine;
60 Assert(pszDefine);
61
62 return QString(pszDefine);
63#endif
64}
65
66/* static */
67QString UIErrorString::formatRCFull(HRESULT rc)
68{
69 /** @todo r=bird: See UIErrorString::formatRC for 31th bit discussion. */
70 char szHex[32];
71 RTStrPrintf(szHex, sizeof(szHex), "%#010X", rc);
72
73#ifdef RT_OS_WINDOWS
74 char szDefine[80];
75 ssize_t cchRet = RTErrWinQueryDefine(rc, szDefine, sizeof(szDefine), true /*fFailIfUnknown*/);
76 if (cchRet == VERR_NOT_FOUND && SUCCEEDED_WARNING(rc))
77 cchRet = RTErrWinQueryDefine(rc | 0x80000000, szDefine, sizeof(szDefine), true /*fFailIfUnknown*/);
78
79 if (cchRet != VERR_NOT_FOUND)
80 return QString(szDefine).append(" (").append(szHex).append(")");
81#else
82 const char *pszDefine = RTErrCOMGet(SUCCEEDED_WARNING(rc) ? rc | 0x80000000 : rc)->pszDefine;
83 Assert(pszDefine);
84
85 if (strncmp(pszDefine, RT_STR_TUPLE("Unknown ")))
86 return QString(pszDefine).append(" (").append(szHex).append(")");
87#endif
88 return QString(szHex);
89}
90
91/* static */
92QString UIErrorString::formatErrorInfo(const CProgress &comProgress)
93{
94 /* Check for API errors first: */
95 if (!comProgress.isOk())
96 return formatErrorInfo(static_cast<COMBaseWithEI>(comProgress));
97
98 /* For progress errors otherwise: */
99 CVirtualBoxErrorInfo comErrorInfo = comProgress.GetErrorInfo();
100 /* Handle valid error-info first: */
101 if (!comErrorInfo.isNull())
102 return formatErrorInfo(comErrorInfo);
103 /* Handle NULL error-info otherwise: */
104 return QString("<table bgcolor=%1 border=0 cellspacing=5 cellpadding=0 width=100%>"
105 "<tr><td>%2</td><td><tt>%3</tt></td></tr></table>")
106 .arg(QApplication::palette().color(QPalette::Active, QPalette::Window).name(QColor::HexRgb))
107 .arg(QApplication::translate("UIErrorString", "Result&nbsp;Code:", "error info"))
108 .arg(formatRCFull(comProgress.GetResultCode()))
109 .prepend("<!--EOM-->") /* move to details */;
110}
111
112/* static */
113QString UIErrorString::formatErrorInfo(const COMErrorInfo &comInfo, HRESULT wrapperRC /* = S_OK */)
114{
115 return QString("<qt>%1</qt>").arg(UIErrorString::errorInfoToString(comInfo, wrapperRC));
116}
117
118/* static */
119QString UIErrorString::formatErrorInfo(const CVirtualBoxErrorInfo &comInfo)
120{
121 return formatErrorInfo(COMErrorInfo(comInfo));
122}
123
124/* static */
125QString UIErrorString::formatErrorInfo(const COMBaseWithEI &comWrapper)
126{
127 Assert(comWrapper.lastRC() != S_OK);
128 return formatErrorInfo(comWrapper.errorInfo(), comWrapper.lastRC());
129}
130
131/* static */
132QString UIErrorString::formatErrorInfo(const COMResult &comRc)
133{
134 Assert(comRc.rc() != S_OK);
135 return formatErrorInfo(comRc.errorInfo(), comRc.rc());
136}
137
138/* static */
139QString UIErrorString::simplifiedErrorInfo(const COMErrorInfo &comInfo, HRESULT wrapperRC /* = S_OK */)
140{
141 return UIErrorString::errorInfoToSimpleString(comInfo, wrapperRC);
142}
143
144/* static */
145QString UIErrorString::simplifiedErrorInfo(const COMBaseWithEI &comWrapper)
146{
147 Assert(comWrapper.lastRC() != S_OK);
148 return simplifiedErrorInfo(comWrapper.errorInfo(), comWrapper.lastRC());
149}
150
151/* static */
152QString UIErrorString::errorInfoToString(const COMErrorInfo &comInfo, HRESULT wrapperRC)
153{
154 /* Compose complex details string with internal <!--EOM--> delimiter to
155 * make it possible to split string into info & details parts which will
156 * be used separately in QIMessageBox. */
157 QString strFormatted;
158
159 /* Check if details text is NOT empty: */
160 const QString strDetailsInfo = comInfo.text();
161 if (!strDetailsInfo.isEmpty())
162 {
163 /* Check if details text written in English (latin1) and translated: */
164 if ( strDetailsInfo == QString::fromLatin1(strDetailsInfo.toLatin1())
165 && strDetailsInfo != QObject::tr(strDetailsInfo.toLatin1().constData()))
166 strFormatted += QString("<p>%1.</p>").arg(UITranslator::emphasize(QObject::tr(strDetailsInfo.toLatin1().constData())));
167 else
168 strFormatted += QString("<p>%1.</p>").arg(UITranslator::emphasize(strDetailsInfo));
169 }
170
171 strFormatted += QString("<!--EOM--><table bgcolor=%1 border=0 cellspacing=5 cellpadding=0 width=100%>")
172 .arg(QApplication::palette().color(QPalette::Active, QPalette::Window).name(QColor::HexRgb));
173
174 bool fHaveResultCode = false;
175
176 if (comInfo.isBasicAvailable())
177 {
178#ifdef VBOX_WS_WIN
179 fHaveResultCode = comInfo.isFullAvailable();
180 bool fHaveComponent = true;
181 bool fHaveInterfaceID = true;
182#else /* !VBOX_WS_WIN */
183 fHaveResultCode = true;
184 bool fHaveComponent = comInfo.isFullAvailable();
185 bool fHaveInterfaceID = comInfo.isFullAvailable();
186#endif
187
188 if (fHaveResultCode)
189 {
190 strFormatted += QString("<tr><td>%1</td><td><tt>%2</tt></td></tr>")
191 .arg(QApplication::translate("UIErrorString", "Result&nbsp;Code:", "error info"))
192 .arg(formatRCFull(comInfo.resultCode()));
193 }
194
195 if (fHaveComponent)
196 strFormatted += QString("<tr><td>%1</td><td>%2</td></tr>")
197 .arg(QApplication::translate("UIErrorString", "Component:", "error info"), comInfo.component());
198
199 if (fHaveInterfaceID)
200 {
201 QString s = comInfo.interfaceID().toString();
202 if (!comInfo.interfaceName().isEmpty())
203 s = comInfo.interfaceName() + ' ' + s;
204 strFormatted += QString("<tr><td>%1</td><td>%2</td></tr>")
205 .arg(QApplication::translate("UIErrorString", "Interface:", "error info"), s);
206 }
207
208 if (!comInfo.calleeIID().isNull() && comInfo.calleeIID() != comInfo.interfaceID())
209 {
210 QString s = comInfo.calleeIID().toString();
211 if (!comInfo.calleeName().isEmpty())
212 s = comInfo.calleeName() + ' ' + s;
213 strFormatted += QString("<tr><td>%1</td><td>%2</td></tr>")
214 .arg(QApplication::translate("UIErrorString", "Callee:", "error info"), s);
215 }
216 }
217
218 if ( FAILED(wrapperRC)
219 && (!fHaveResultCode || wrapperRC != comInfo.resultCode()))
220 {
221 strFormatted += QString("<tr><td>%1</td><td><tt>%2</tt></td></tr>")
222 .arg(QApplication::translate("UIErrorString", "Callee&nbsp;RC:", "error info"))
223 .arg(formatRCFull(wrapperRC));
224 }
225
226 strFormatted += "</table>";
227
228 if (comInfo.next())
229 strFormatted = strFormatted + "<!--EOP-->" + errorInfoToString(*comInfo.next());
230
231 return strFormatted;
232}
233
234/* static */
235QString UIErrorString::errorInfoToSimpleString(const COMErrorInfo &comInfo, HRESULT wrapperRC /* = S_OK */)
236{
237 /* Compose complex details string with text and status code: */
238 QString strFormatted;
239
240 /* Check if details text is NOT empty: */
241 const QString strDetailsInfo = comInfo.text();
242 if (!strDetailsInfo.isEmpty())
243 strFormatted += strDetailsInfo;
244
245 /* Check if we have result code: */
246 bool fHaveResultCode = false;
247
248 if (comInfo.isBasicAvailable())
249 {
250#ifdef VBOX_WS_WIN
251 fHaveResultCode = comInfo.isFullAvailable();
252#else
253 fHaveResultCode = true;
254#endif
255
256 if (fHaveResultCode)
257 strFormatted += "; " + QString("Result Code: ") + formatRCFull(comInfo.resultCode());
258 }
259
260 if ( FAILED(wrapperRC)
261 && (!fHaveResultCode || wrapperRC != comInfo.resultCode()))
262 strFormatted += "; " + QString("Callee RC: ") + formatRCFull(wrapperRC);
263
264 /* Check if we have next error queued: */
265 if (comInfo.next())
266 strFormatted += "; " + errorInfoToSimpleString(*comInfo.next());
267
268 return strFormatted;
269}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use