VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/extensions/QIMessageBox.cpp@ 82781

Last change on this file since 82781 was 76606, checked in by vboxsync, 5 years ago

FE/Qt: Cleaning out old precompiled header experiment.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.9 KB
Line 
1/* $Id: QIMessageBox.cpp 76606 2019-01-02 05:40:39Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - Qt extensions: QIMessageBox class implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/* Qt includes: */
19#include <QCheckBox>
20#include <QClipboard>
21#include <QHBoxLayout>
22#include <QLabel>
23#include <QMimeData>
24#include <QPushButton>
25#include <QStyle>
26#include <QVBoxLayout>
27
28/* GUI includes: */
29#include "QIArrowSplitter.h"
30#include "QIDialogButtonBox.h"
31#include "QILabel.h"
32#include "QIMessageBox.h"
33#include "UIIconPool.h"
34
35/* Other VBox includes: */
36#include <iprt/assert.h>
37
38
39QIMessageBox::QIMessageBox(const QString &strTitle, const QString &strMessage, AlertIconType iconType,
40 int iButton1 /* = 0*/, int iButton2 /* = 0*/, int iButton3 /* = 0*/, QWidget *pParent /* = 0*/)
41 : QIDialog(pParent)
42 , m_strTitle(strTitle)
43 , m_iconType(iconType)
44 , m_pLabelIcon(0)
45 , m_strMessage(strMessage)
46 , m_pLabelText(0)
47 , m_pFlagCheckBox(0)
48 , m_pDetailsContainer(0)
49 , m_iButton1(iButton1)
50 , m_iButton2(iButton2)
51 , m_iButton3(iButton3)
52 , m_iButtonEsc(0)
53 , m_pButton1(0)
54 , m_pButton2(0)
55 , m_pButton3(0)
56 , m_pButtonBox(0)
57 , m_fDone(false)
58{
59 /* Prepare: */
60 prepare();
61}
62
63void QIMessageBox::setDetailsText(const QString &strText)
64{
65 /* Make sure details-text is NOT empty: */
66 AssertReturnVoid(!strText.isEmpty());
67
68 /* Split details into paragraphs: */
69 QStringList paragraphs(strText.split("<!--EOP-->", QString::SkipEmptyParts));
70 /* Make sure details-text has at least one paragraph: */
71 AssertReturnVoid(!paragraphs.isEmpty());
72
73 /* Enumerate all the paragraphs: */
74 QStringPairList details;
75 foreach (const QString &strParagraph, paragraphs)
76 {
77 /* Split each paragraph into pairs: */
78 QStringList parts(strParagraph.split("<!--EOM-->", QString::KeepEmptyParts));
79 /* Make sure each paragraph consist of 2 parts: */
80 AssertReturnVoid(parts.size() == 2);
81 /* Append each pair into details-list: */
82 details << QStringPair(parts[0], parts[1]);
83 }
84
85 /* Pass details-list to details-container: */
86 m_pDetailsContainer->setDetails(details);
87 /* Update details-container finally: */
88 updateDetailsContainer();
89}
90
91bool QIMessageBox::flagChecked() const
92{
93 return m_pFlagCheckBox->isChecked();
94}
95
96void QIMessageBox::setFlagChecked(bool fChecked)
97{
98 m_pFlagCheckBox->setChecked(fChecked);
99}
100
101void QIMessageBox::setFlagText(const QString &strFlagText)
102{
103 /* Pass text to flag check-box: */
104 m_pFlagCheckBox->setText(strFlagText);
105 /* Update flag check-box finally: */
106 updateCheckBox();
107}
108
109void QIMessageBox::setButtonText(int iButton, const QString &strText)
110{
111 switch (iButton)
112 {
113 case 0: if (m_pButton1) m_pButton1->setText(strText); break;
114 case 1: if (m_pButton2) m_pButton2->setText(strText); break;
115 case 2: if (m_pButton3) m_pButton3->setText(strText); break;
116 default: break;
117 }
118}
119
120void QIMessageBox::polishEvent(QShowEvent *pPolishEvent)
121{
122 /* Tune text-label size: */
123 m_pLabelText->useSizeHintForWidth(m_pLabelText->width());
124 m_pLabelText->updateGeometry();
125
126 /* Call to base-class: */
127 QIDialog::polishEvent(pPolishEvent);
128
129 /* Update size finally: */
130 sltUpdateSize();
131}
132
133void QIMessageBox::closeEvent(QCloseEvent *pCloseEvent)
134{
135 if (m_fDone)
136 pCloseEvent->accept();
137 else
138 {
139 pCloseEvent->ignore();
140 reject();
141 }
142}
143
144void QIMessageBox::sltUpdateSize()
145{
146 /* Fix minimum possible size: */
147 setFixedSize(minimumSizeHint());
148}
149
150void QIMessageBox::sltCopy() const
151{
152 /* Create the error string with all errors. First the html version. */
153 QString strError = "<html><body><p>" + m_strMessage + "</p>";
154 foreach (const QStringPair &pair, m_pDetailsContainer->details())
155 strError += pair.first + pair.second + "<br>";
156 strError += "</body></html>";
157 strError.remove(QRegExp("</+qt>"));
158 strError = strError.replace(QRegExp("&nbsp;"), " ");
159 /* Create a new mime data object holding both the html and the plain text version. */
160 QMimeData *pMimeData = new QMimeData();
161 pMimeData->setHtml(strError);
162 /* Replace all the html entities. */
163 strError = strError.replace(QRegExp("<br>|</tr>"), "\n");
164 strError = strError.replace(QRegExp("</p>"), "\n\n");
165 strError = strError.remove(QRegExp("<[^>]*>"));
166 pMimeData->setText(strError);
167 /* Add the mime data to the global clipboard. */
168 QClipboard *pClipboard = QApplication::clipboard();
169 pClipboard->setMimeData(pMimeData);
170}
171
172void QIMessageBox::reject()
173{
174 if (m_iButtonEsc)
175 {
176 QDialog::reject();
177 setResult(m_iButtonEsc & AlertButtonMask);
178 }
179}
180
181void QIMessageBox::prepare()
182{
183 /* Set caption: */
184 setWindowTitle(m_strTitle);
185
186 /* Create main-layout: */
187 QVBoxLayout *pMainLayout = new QVBoxLayout(this);
188 AssertPtrReturnVoid(pMainLayout);
189 {
190 /* Configure main-layout: */
191#ifdef VBOX_WS_MAC
192 pMainLayout->setContentsMargins(40, 20, 40, 20);
193 pMainLayout->setSpacing(15);
194#else
195 pMainLayout->setSpacing(qApp->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing) * 2);
196#endif
197 /* Create top-layout: */
198 QHBoxLayout *pTopLayout = new QHBoxLayout;
199 AssertPtrReturnVoid(pTopLayout);
200 {
201 /* Configure top-layout: */
202 pTopLayout->setContentsMargins(0, 0, 0, 0);
203 /* Create icon-label: */
204 m_pLabelIcon = new QLabel;
205 AssertPtrReturnVoid(m_pLabelIcon);
206 {
207 /* Configure icon-label: */
208 m_pLabelIcon->setPixmap(standardPixmap(m_iconType, this));
209 m_pLabelIcon->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
210 m_pLabelIcon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
211 /* Add icon-label into top-layout: */
212 pTopLayout->addWidget(m_pLabelIcon);
213 }
214 /* Create text-label: */
215 m_pLabelText = new QILabel(m_strMessage);
216 AssertPtrReturnVoid(m_pLabelText);
217 {
218 /* Configure text-label: */
219 m_pLabelText->setWordWrap(true);
220 m_pLabelText->setAlignment(Qt::AlignLeft | Qt::AlignTop);
221 QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
222 sizePolicy.setHeightForWidth(true);
223 m_pLabelText->setSizePolicy(sizePolicy);
224 /* Add text-label into top-layout: */
225 pTopLayout->addWidget(m_pLabelText);
226 }
227 /* Add top-layout into main-layout: */
228 pMainLayout->addLayout(pTopLayout);
229 }
230 /* Create details-container: */
231 m_pDetailsContainer = new QIArrowSplitter;
232 AssertPtrReturnVoid(m_pDetailsContainer);
233 {
234 /* Configure container: */
235 connect(m_pDetailsContainer, &QIArrowSplitter::sigSizeHintChange,
236 this, &QIMessageBox::sltUpdateSize);
237 /* Add details-container into main-layout: */
238 pMainLayout->addWidget(m_pDetailsContainer);
239 /* Update details-container finally: */
240 updateDetailsContainer();
241 }
242 /* Create flag check-box: */
243 m_pFlagCheckBox = new QCheckBox;
244 AssertPtrReturnVoid(m_pFlagCheckBox);
245 {
246 /* Configure flag check-box: */
247 m_pFlagCheckBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
248 /* Add flag check-box into main-layout: */
249 pMainLayout->addWidget(m_pFlagCheckBox, 0, Qt::AlignHCenter | Qt::AlignVCenter);
250 /* Update flag check-box finally: */
251 updateCheckBox();
252 }
253 /* Create button-box: */
254 m_pButtonBox = new QIDialogButtonBox;
255 AssertPtrReturnVoid(m_pButtonBox);
256 {
257 /* Configure button-box: */
258 m_pButtonBox->setCenterButtons(true);
259 m_pButton1 = createButton(m_iButton1);
260 if (m_pButton1)
261 connect(m_pButton1, &QPushButton::clicked, this, &QIMessageBox::sltDone1);
262 m_pButton2 = createButton(m_iButton2);
263 if (m_pButton2)
264 connect(m_pButton2, &QPushButton::clicked, this, &QIMessageBox::sltDone2);
265 m_pButton3 = createButton(m_iButton3);
266 if (m_pButton3)
267 connect(m_pButton3, &QPushButton::clicked, this, &QIMessageBox::sltDone3);
268 /* Make sure Escape button always set: */
269 Assert(m_iButtonEsc);
270 /* If this is a critical message add a "Copy to clipboard" button: */
271 if (m_iconType == AlertIconType_Critical)
272 {
273 QPushButton *pCopyButton = createButton(AlertButton_Copy);
274 pCopyButton->setToolTip(tr("Copy all errors to the clipboard"));
275 connect(pCopyButton, &QPushButton::clicked, this, &QIMessageBox::sltCopy);
276 }
277 /* Add button-box into main-layout: */
278 pMainLayout->addWidget(m_pButtonBox);
279
280 /* Prepare focus. It is important to prepare focus after adding button-box to the layout as
281 * parenting the button-box to the QDialog changes default button focus by Qt: */
282 prepareFocus();
283 }
284 }
285}
286
287void QIMessageBox::prepareFocus()
288{
289 /* Configure default button and focus: */
290 if (m_pButton1 && (m_iButton1 & AlertButtonOption_Default))
291 {
292 m_pButton1->setDefault(true);
293 m_pButton1->setFocus();
294 }
295 if (m_pButton2 && (m_iButton2 & AlertButtonOption_Default))
296 {
297 m_pButton2->setDefault(true);
298 m_pButton2->setFocus();
299 }
300 if (m_pButton3 && (m_iButton3 & AlertButtonOption_Default))
301 {
302 m_pButton3->setDefault(true);
303 m_pButton3->setFocus();
304 }
305}
306
307QPushButton *QIMessageBox::createButton(int iButton)
308{
309 /* Not for AlertButton_NoButton: */
310 if (iButton == 0)
311 return 0;
312
313 /* Prepare button text & role: */
314 QString strText;
315 QDialogButtonBox::ButtonRole role;
316 switch (iButton & AlertButtonMask)
317 {
318 case AlertButton_Ok: strText = tr("OK"); role = QDialogButtonBox::AcceptRole; break;
319 case AlertButton_Cancel: strText = tr("Cancel"); role = QDialogButtonBox::RejectRole; break;
320 case AlertButton_Choice1: strText = tr("Yes"); role = QDialogButtonBox::YesRole; break;
321 case AlertButton_Choice2: strText = tr("No"); role = QDialogButtonBox::NoRole; break;
322 case AlertButton_Copy: strText = tr("Copy"); role = QDialogButtonBox::ActionRole; break;
323 default:
324 AssertMsgFailed(("Type %d is not supported!", iButton));
325 return 0;
326 }
327
328 /* Create push-button: */
329 QPushButton *pButton = m_pButtonBox->addButton(strText, role);
330
331 /* Configure <escape> button: */
332 if (iButton & AlertButtonOption_Escape)
333 m_iButtonEsc = iButton & AlertButtonMask;
334
335 /* Return button: */
336 return pButton;
337}
338
339void QIMessageBox::updateDetailsContainer()
340{
341 /* Details-container with details is always visible: */
342 m_pDetailsContainer->setVisible(!m_pDetailsContainer->details().isEmpty());
343 /* Update size: */
344 sltUpdateSize();
345}
346
347void QIMessageBox::updateCheckBox()
348{
349 /* Flag check-box with text is always visible: */
350 m_pFlagCheckBox->setVisible(!m_pFlagCheckBox->text().isEmpty());
351 /* Update size: */
352 sltUpdateSize();
353}
354
355/* static */
356QPixmap QIMessageBox::standardPixmap(AlertIconType iconType, QWidget *pWidget /* = 0*/)
357{
358 /* Prepare standard icon: */
359 QIcon icon;
360 switch (iconType)
361 {
362 case AlertIconType_Information: icon = UIIconPool::defaultIcon(UIIconPool::UIDefaultIconType_MessageBoxInformation, pWidget); break;
363 case AlertIconType_Warning: icon = UIIconPool::defaultIcon(UIIconPool::UIDefaultIconType_MessageBoxWarning, pWidget); break;
364 case AlertIconType_Critical: icon = UIIconPool::defaultIcon(UIIconPool::UIDefaultIconType_MessageBoxCritical, pWidget); break;
365 case AlertIconType_Question: icon = UIIconPool::defaultIcon(UIIconPool::UIDefaultIconType_MessageBoxQuestion, pWidget); break;
366 case AlertIconType_GuruMeditation: icon = UIIconPool::iconSet(":/meditation_32px.png"); break;
367 default: break;
368 }
369 /* Return empty pixmap if nothing found: */
370 if (icon.isNull())
371 return QPixmap();
372 /* Return pixmap of standard size if possible: */
373 QStyle *pStyle = pWidget ? pWidget->style() : QApplication::style();
374 int iSize = pStyle->pixelMetric(QStyle::PM_MessageBoxIconSize, 0, pWidget);
375 return icon.pixmap(iSize, iSize);
376}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use