VirtualBox

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

Last change on this file since 102493 was 99841, checked in by vboxsync, 16 months ago

FE/Qt: bugref:10450: Qt6 compatibility bits for QString stuff; Replacing usage of QString::sprintf with QString::asprintf.

  • 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 99841 2023-05-18 11:05:14Z 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 "UICommon.h"
35#include "UIErrorString.h"
36#include "UITranslator.h"
37
38/* COM includes: */
39#include "COMDefs.h"
40#include "CProgress.h"
41#include "CVirtualBoxErrorInfo.h"
42
43
44/* static */
45QString UIErrorString::formatRC(HRESULT rc)
46{
47 /** @todo r=bird: Not sure why we set the sign bit 31 bit for warnings.
48 * Maybe to try get the error variant? It won't really work for S_FALSE and
49 * probably a bunch of others too. I've modified it on windows to try get
50 * the exact one, the one with the top bit set, or just the value. */
51#ifdef RT_OS_WINDOWS
52 char szDefine[80];
53 if ( !SUCCEEDED_WARNING(rc)
54 || ( RTErrWinQueryDefine(rc, szDefine, sizeof(szDefine), true /*fFailIfUnknown*/) == VERR_NOT_FOUND
55 && RTErrWinQueryDefine(rc | 0x80000000, szDefine, sizeof(szDefine), true /*fFailIfUnknown*/) == VERR_NOT_FOUND))
56 RTErrWinQueryDefine(rc, szDefine, sizeof(szDefine), false /*fFailIfUnknown*/);
57
58 return QString::asprintf("%s", szDefine);
59#else
60 const char *pszDefine = RTErrCOMGet(SUCCEEDED_WARNING(rc) ? rc | 0x80000000 : rc)->pszDefine;
61 Assert(pszDefine);
62
63 return QString(pszDefine);
64#endif
65}
66
67/* static */
68QString UIErrorString::formatRCFull(HRESULT rc)
69{
70 /** @todo r=bird: See UIErrorString::formatRC for 31th bit discussion. */
71 char szHex[32];
72 RTStrPrintf(szHex, sizeof(szHex), "%#010X", rc);
73
74#ifdef RT_OS_WINDOWS
75 char szDefine[80];
76 ssize_t cchRet = RTErrWinQueryDefine(rc, szDefine, sizeof(szDefine), true /*fFailIfUnknown*/);
77 if (cchRet == VERR_NOT_FOUND && SUCCEEDED_WARNING(rc))
78 cchRet = RTErrWinQueryDefine(rc | 0x80000000, szDefine, sizeof(szDefine), true /*fFailIfUnknown*/);
79
80 if (cchRet != VERR_NOT_FOUND)
81 return QString(szDefine).append(" (").append(szHex).append(")");
82#else
83 const char *pszDefine = RTErrCOMGet(SUCCEEDED_WARNING(rc) ? rc | 0x80000000 : rc)->pszDefine;
84 Assert(pszDefine);
85
86 if (strncmp(pszDefine, RT_STR_TUPLE("Unknown ")))
87 return QString(pszDefine).append(" (").append(szHex).append(")");
88#endif
89 return QString(szHex);
90}
91
92/* static */
93QString UIErrorString::formatErrorInfo(const CProgress &comProgress)
94{
95 /* Check for API errors first: */
96 if (!comProgress.isOk())
97 return formatErrorInfo(static_cast<COMBaseWithEI>(comProgress));
98
99 /* For progress errors otherwise: */
100 CVirtualBoxErrorInfo comErrorInfo = comProgress.GetErrorInfo();
101 /* Handle valid error-info first: */
102 if (!comErrorInfo.isNull())
103 return formatErrorInfo(comErrorInfo);
104 /* Handle NULL error-info otherwise: */
105 return QString("<table bgcolor=%1 border=0 cellspacing=5 cellpadding=0 width=100%>"
106 "<tr><td>%2</td><td><tt>%3</tt></td></tr></table>")
107 .arg(QApplication::palette().color(QPalette::Active, QPalette::Window).name(QColor::HexRgb))
108 .arg(QApplication::translate("UIErrorString", "Result&nbsp;Code:", "error info"))
109 .arg(formatRCFull(comProgress.GetResultCode()))
110 .prepend("<!--EOM-->") /* move to details */;
111}
112
113/* static */
114QString UIErrorString::formatErrorInfo(const COMErrorInfo &comInfo, HRESULT wrapperRC /* = S_OK */)
115{
116 return QString("<qt>%1</qt>").arg(UIErrorString::errorInfoToString(comInfo, wrapperRC));
117}
118
119/* static */
120QString UIErrorString::formatErrorInfo(const CVirtualBoxErrorInfo &comInfo)
121{
122 return formatErrorInfo(COMErrorInfo(comInfo));
123}
124
125/* static */
126QString UIErrorString::formatErrorInfo(const COMBaseWithEI &comWrapper)
127{
128 Assert(comWrapper.lastRC() != S_OK);
129 return formatErrorInfo(comWrapper.errorInfo(), comWrapper.lastRC());
130}
131
132/* static */
133QString UIErrorString::formatErrorInfo(const COMResult &comRc)
134{
135 Assert(comRc.rc() != S_OK);
136 return formatErrorInfo(comRc.errorInfo(), comRc.rc());
137}
138
139/* static */
140QString UIErrorString::simplifiedErrorInfo(const COMErrorInfo &comInfo, HRESULT wrapperRC /* = S_OK */)
141{
142 return UIErrorString::errorInfoToSimpleString(comInfo, wrapperRC);
143}
144
145/* static */
146QString UIErrorString::simplifiedErrorInfo(const COMBaseWithEI &comWrapper)
147{
148 Assert(comWrapper.lastRC() != S_OK);
149 return simplifiedErrorInfo(comWrapper.errorInfo(), comWrapper.lastRC());
150}
151
152/* static */
153QString UIErrorString::errorInfoToString(const COMErrorInfo &comInfo, HRESULT wrapperRC)
154{
155 /* Compose complex details string with internal <!--EOM--> delimiter to
156 * make it possible to split string into info & details parts which will
157 * be used separately in QIMessageBox. */
158 QString strFormatted;
159
160 /* Check if details text is NOT empty: */
161 const QString strDetailsInfo = comInfo.text();
162 if (!strDetailsInfo.isEmpty())
163 {
164 /* Check if details text written in English (latin1) and translated: */
165 if ( strDetailsInfo == QString::fromLatin1(strDetailsInfo.toLatin1())
166 && strDetailsInfo != QObject::tr(strDetailsInfo.toLatin1().constData()))
167 strFormatted += QString("<p>%1.</p>").arg(UITranslator::emphasize(QObject::tr(strDetailsInfo.toLatin1().constData())));
168 else
169 strFormatted += QString("<p>%1.</p>").arg(UITranslator::emphasize(strDetailsInfo));
170 }
171
172 strFormatted += QString("<!--EOM--><table bgcolor=%1 border=0 cellspacing=5 cellpadding=0 width=100%>")
173 .arg(QApplication::palette().color(QPalette::Active, QPalette::Window).name(QColor::HexRgb));
174
175 bool fHaveResultCode = false;
176
177 if (comInfo.isBasicAvailable())
178 {
179#ifdef VBOX_WS_WIN
180 fHaveResultCode = comInfo.isFullAvailable();
181 bool fHaveComponent = true;
182 bool fHaveInterfaceID = true;
183#else /* !VBOX_WS_WIN */
184 fHaveResultCode = true;
185 bool fHaveComponent = comInfo.isFullAvailable();
186 bool fHaveInterfaceID = comInfo.isFullAvailable();
187#endif
188
189 if (fHaveResultCode)
190 {
191 strFormatted += QString("<tr><td>%1</td><td><tt>%2</tt></td></tr>")
192 .arg(QApplication::translate("UIErrorString", "Result&nbsp;Code:", "error info"))
193 .arg(formatRCFull(comInfo.resultCode()));
194 }
195
196 if (fHaveComponent)
197 strFormatted += QString("<tr><td>%1</td><td>%2</td></tr>")
198 .arg(QApplication::translate("UIErrorString", "Component:", "error info"), comInfo.component());
199
200 if (fHaveInterfaceID)
201 {
202 QString s = comInfo.interfaceID().toString();
203 if (!comInfo.interfaceName().isEmpty())
204 s = comInfo.interfaceName() + ' ' + s;
205 strFormatted += QString("<tr><td>%1</td><td>%2</td></tr>")
206 .arg(QApplication::translate("UIErrorString", "Interface:", "error info"), s);
207 }
208
209 if (!comInfo.calleeIID().isNull() && comInfo.calleeIID() != comInfo.interfaceID())
210 {
211 QString s = comInfo.calleeIID().toString();
212 if (!comInfo.calleeName().isEmpty())
213 s = comInfo.calleeName() + ' ' + s;
214 strFormatted += QString("<tr><td>%1</td><td>%2</td></tr>")
215 .arg(QApplication::translate("UIErrorString", "Callee:", "error info"), s);
216 }
217 }
218
219 if ( FAILED(wrapperRC)
220 && (!fHaveResultCode || wrapperRC != comInfo.resultCode()))
221 {
222 strFormatted += QString("<tr><td>%1</td><td><tt>%2</tt></td></tr>")
223 .arg(QApplication::translate("UIErrorString", "Callee&nbsp;RC:", "error info"))
224 .arg(formatRCFull(wrapperRC));
225 }
226
227 strFormatted += "</table>";
228
229 if (comInfo.next())
230 strFormatted = strFormatted + "<!--EOP-->" + errorInfoToString(*comInfo.next());
231
232 return strFormatted;
233}
234
235/* static */
236QString UIErrorString::errorInfoToSimpleString(const COMErrorInfo &comInfo, HRESULT wrapperRC /* = S_OK */)
237{
238 /* Compose complex details string with text and status code: */
239 QString strFormatted;
240
241 /* Check if details text is NOT empty: */
242 const QString strDetailsInfo = comInfo.text();
243 if (!strDetailsInfo.isEmpty())
244 strFormatted += strDetailsInfo;
245
246 /* Check if we have result code: */
247 bool fHaveResultCode = false;
248
249 if (comInfo.isBasicAvailable())
250 {
251#ifdef VBOX_WS_WIN
252 fHaveResultCode = comInfo.isFullAvailable();
253#else
254 fHaveResultCode = true;
255#endif
256
257 if (fHaveResultCode)
258 strFormatted += "; " + QString("Result Code: ") + formatRCFull(comInfo.resultCode());
259 }
260
261 if ( FAILED(wrapperRC)
262 && (!fHaveResultCode || wrapperRC != comInfo.resultCode()))
263 strFormatted += "; " + QString("Callee RC: ") + formatRCFull(wrapperRC);
264
265 /* Check if we have next error queued: */
266 if (comInfo.next())
267 strFormatted += "; " + errorInfoToSimpleString(*comInfo.next());
268
269 return strFormatted;
270}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette