VirtualBox

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

Last change on this file since 35740 was 31319, checked in by vboxsync, 14 years ago

FE/Qt4-OSX: use sheet windows in scale mode

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.3 KB
Line 
1/* $Id: QIMessageBox.cpp 31319 2010-08-02 16:41:47Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: Qt GUI ("VirtualBox"):
5 * VirtualBox Qt extensions: QIMessageBox class implementation
6 */
7
8/*
9 * Copyright (C) 2006-2009 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20/* VBox includes */
21#include "VBoxDefs.h"
22#include "VBoxGlobal.h"
23#include "QIArrowSplitter.h"
24#include "QIMessageBox.h"
25#include "QILabel.h"
26#include "QIDialogButtonBox.h"
27#include "UIIconPool.h"
28#ifdef Q_WS_MAC
29# include "VBoxSelectorWnd.h"
30#endif /* Q_WS_MAC */
31
32/* Qt includes */
33#include <QHBoxLayout>
34#include <QLabel>
35#include <QPushButton>
36#include <QStyleOptionFocusRect>
37#include <QStylePainter>
38#include <QToolButton>
39#include <QKeyEvent>
40
41#ifdef Q_WS_MAC
42# include "UIMachineWindowFullscreen.h"
43# include "UIMachineWindowSeamless.h"
44#endif /* Q_WS_MAC */
45
46/** @class QIMessageBox
47 *
48 * The QIMessageBox class is a message box similar to QMessageBox.
49 * It partly implements the QMessageBox interface and adds some enhanced
50 * functionality.
51 */
52
53/**
54 * See QMessageBox for details.
55 */
56QIMessageBox::QIMessageBox (const QString &aCaption, const QString &aText,
57 Icon aIcon, int aButton0, int aButton1, int aButton2,
58 QWidget *aParent, const char *aName, bool aModal)
59 : QIDialog (aParent)
60 , mText (aText)
61 , mDetailsIndex (-1)
62 , mWasDone (false)
63 , mWasPolished (false)
64{
65#ifdef Q_WS_MAC
66 /* No sheets in another mode than normal for now. Firstly it looks ugly and
67 * secondly in some cases it is broken. */
68 if (vboxGlobal().isSheetWindowsAllowed(aParent))
69 setWindowFlags(Qt::Sheet);
70#endif /* Q_WS_MAC */
71
72 setWindowTitle (aCaption);
73 /* Necessary to later find some of the message boxes */
74 setObjectName (aName);
75 setModal (aModal);
76
77 mButton0 = aButton0;
78 mButton1 = aButton1;
79 mButton2 = aButton2;
80
81 QVBoxLayout *layout = new QVBoxLayout (this);
82#ifdef Q_WS_MAC
83 layout->setContentsMargins (40, 11, 40, 11);
84#else /* !Q_WS_MAC */
85 VBoxGlobal::setLayoutMargin (layout, 11);
86#endif /* !Q_WS_MAC */
87 layout->setSpacing (10);
88 layout->setSizeConstraint (QLayout::SetMinimumSize);
89
90 QWidget *main = new QWidget();
91
92 QHBoxLayout *hLayout = new QHBoxLayout (main);
93 VBoxGlobal::setLayoutMargin (hLayout, 0);
94 hLayout->setSpacing (10);
95 layout->addWidget (main);
96
97 mIconLabel = new QLabel();
98 mIconLabel->setPixmap (standardPixmap (aIcon));
99 mIconLabel->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Minimum);
100 mIconLabel->setAlignment (Qt::AlignHCenter | Qt::AlignTop);
101 hLayout->addWidget (mIconLabel);
102
103 QVBoxLayout* messageVBoxLayout = new QVBoxLayout();
104 VBoxGlobal::setLayoutMargin (messageVBoxLayout, 0);
105 messageVBoxLayout->setSpacing (10);
106 hLayout->addLayout (messageVBoxLayout);
107
108 mTextLabel = new QILabel (aText);
109 mTextLabel->setAlignment (Qt::AlignLeft | Qt::AlignTop);
110 mTextLabel->setWordWrap (true);
111 QSizePolicy sp (QSizePolicy::Minimum, QSizePolicy::Minimum);
112 sp.setHeightForWidth (true);
113 mTextLabel->setSizePolicy (sp);
114 messageVBoxLayout->addWidget (mTextLabel);
115
116 mFlagCB_Main = new QCheckBox();
117 mFlagCB_Main->hide();
118 messageVBoxLayout->addWidget (mFlagCB_Main);
119
120 mDetailsVBox = new QWidget();
121 layout->addWidget (mDetailsVBox);
122
123 QVBoxLayout* detailsVBoxLayout = new QVBoxLayout (mDetailsVBox);
124 VBoxGlobal::setLayoutMargin (detailsVBoxLayout, 0);
125 detailsVBoxLayout->setSpacing (10);
126
127 mDetailsText = new QTextEdit();
128 {
129 /* Calculate the minimum size dynamically, approx.
130 * for 40 chars, 4 lines & 2 <table> margins */
131 QFontMetrics fm = mDetailsText->fontMetrics();
132 mDetailsText->setMinimumSize (fm.width ('m') * 40,
133 fm.lineSpacing() * 4 + 4 * 2);
134 }
135 mDetailsText->setReadOnly (true);
136 mDetailsText->setSizePolicy (QSizePolicy::Expanding,
137 QSizePolicy::MinimumExpanding);
138 mDetailsSplitter = new QIArrowSplitter (mDetailsText);
139 connect (mDetailsSplitter, SIGNAL (showBackDetails()), this, SLOT (detailsBack()));
140 connect (mDetailsSplitter, SIGNAL (showNextDetails()), this, SLOT (detailsNext()));
141 detailsVBoxLayout->addWidget (mDetailsSplitter);
142
143 mFlagCB_Details = new QCheckBox();
144 mFlagCB_Details->hide();
145 detailsVBoxLayout->addWidget (mFlagCB_Details);
146
147 mSpacer = new QSpacerItem (0, 0);
148 layout->addItem (mSpacer);
149
150 mButtonBox = new QIDialogButtonBox;
151 mButtonBox->setCenterButtons (true);
152 layout->addWidget (mButtonBox);
153
154 mButtonEsc = 0;
155
156 mButton0PB = createButton (aButton0);
157 if (mButton0PB)
158 connect (mButton0PB, SIGNAL (clicked()), SLOT (done0()));
159 mButton1PB = createButton (aButton1);
160 if (mButton1PB)
161 connect (mButton1PB, SIGNAL (clicked()), SLOT (done1()));
162 mButton2PB = createButton (aButton2);
163 if (mButton2PB)
164 connect (mButton2PB, SIGNAL (clicked()), SLOT (done2()));
165
166 /* this call is a must -- it initializes mFlagCB and mSpacer */
167 setDetailsShown (false);
168}
169
170/**
171 * Returns the text of the given message box button.
172 * See QMessageBox::buttonText() for details.
173 *
174 * @param aButton Button index (0, 1 or 2).
175 */
176QString QIMessageBox::buttonText (int aButton) const
177{
178 switch (aButton)
179 {
180 case 0: if (mButton0PB) return mButton0PB->text(); break;
181 case 1: if (mButton1PB) return mButton1PB->text(); break;
182 case 2: if (mButton2PB) return mButton2PB->text(); break;
183 default: break;
184 }
185
186 return QString::null;
187}
188
189/**
190 * Sets the text of the given message box button.
191 * See QMessageBox::setButtonText() for details.
192 *
193 * @param aButton Button index (0, 1 or 2).
194 * @param aText New button text.
195 */
196void QIMessageBox::setButtonText (int aButton, const QString &aText)
197{
198 switch (aButton)
199 {
200 case 0: if (mButton0PB) mButton0PB->setText (aText); break;
201 case 1: if (mButton1PB) mButton1PB->setText (aText); break;
202 case 2: if (mButton2PB) mButton2PB->setText (aText); break;
203 default: break;
204 }
205}
206
207/** @fn QIMessageBox::flagText() const
208 *
209 * Returns the text of the optional message box flag. If the flag is hidden
210 * (by default) a null string is returned.
211 *
212 * @see #setFlagText()
213 */
214
215/**
216 * Sets the text for the optional message box flag (check box) that is
217 * displayed under the message text. Passing the null string as the argument
218 * will hide the flag. By default, the flag is hidden.
219 */
220void QIMessageBox::setFlagText (const QString &aText)
221{
222 if (aText.isNull())
223 {
224 mFlagCB->hide();
225 }
226 else
227 {
228 mFlagCB->setText (aText);
229 mFlagCB->show();
230 mFlagCB->setFocus();
231 }
232}
233
234/** @fn QIMessageBox::isFlagChecked() const
235 *
236 * Returns true if the optional message box flag is checked and false
237 * otherwise. By default, the flag is not checked.
238 *
239 * @see #setFlagChecked()
240 * @see #setFlagText()
241 */
242
243/** @fn QIMessageBox::setFlagChecked (bool)
244 *
245 * Sets the state of the optional message box flag to a value of the argument.
246 *
247 * @see #isFlagChecked()
248 * @see #setFlagText()
249 */
250
251QPushButton *QIMessageBox::createButton (int aButton)
252{
253 if (aButton == 0)
254 return 0;
255
256 QString text;
257 QDialogButtonBox::ButtonRole role;
258 switch (aButton & ButtonMask)
259 {
260 case Ok: text = tr ("OK"); role = QDialogButtonBox::AcceptRole; break;
261 case Yes: text = tr ("Yes"); role = QDialogButtonBox::YesRole; break;
262 case No: text = tr ("No"); role = QDialogButtonBox::NoRole; break;
263 case Cancel: text = tr ("Cancel"); role = QDialogButtonBox::RejectRole; break;
264 case Ignore: text = tr ("Ignore"); role = QDialogButtonBox::AcceptRole; break;
265 default:
266 AssertMsgFailed (("Type %d is not implemented", aButton));
267 return NULL;
268 }
269
270 QPushButton *b = mButtonBox->addButton (text, role);
271
272 if (aButton & Default)
273 {
274 b->setDefault (true);
275 b->setFocus();
276 }
277
278 if (aButton & Escape)
279 mButtonEsc = aButton & ButtonMask;
280
281 return b;
282}
283
284/** @fn QIMessageBox::detailsText() const
285 *
286 * Returns the text of the optional details box. The details box is empty
287 * by default, so QString::null will be returned.
288 *
289 * @see #setDetailsText()
290 */
291
292/**
293 * Sets the text for the optional details box. Note that the details box
294 * is hidden by default, call #setDetailsShown(true) to make it visible.
295 *
296 * @see #detailsText()
297 * @see #setDetailsShown()
298 */
299void QIMessageBox::setDetailsText (const QString &aText)
300{
301 AssertMsg (!aText.isEmpty(), ("Details text should NOT be empty."));
302
303 QStringList paragraphs (aText.split ("<!--EOP-->", QString::SkipEmptyParts));
304 AssertMsg (paragraphs.size() != 0, ("There should be at least one paragraph."));
305
306 foreach (QString paragraph, paragraphs)
307 {
308 QStringList parts (paragraph.split ("<!--EOM-->", QString::KeepEmptyParts));
309 AssertMsg (parts.size() == 2, ("Each paragraph should consist of 2 parts."));
310 mDetailsList << QPair <QString, QString> (parts [0], parts [1]);
311 }
312
313 mDetailsSplitter->setMultiPaging (mDetailsList.size() > 1);
314 mDetailsIndex = 0;
315 refreshDetails();
316}
317
318QPixmap QIMessageBox::standardPixmap (QIMessageBox::Icon aIcon)
319{
320 QIcon icon;
321 switch (aIcon)
322 {
323 case QIMessageBox::Information:
324 icon = UIIconPool::defaultIcon(UIIconPool::MessageBoxInformationIcon, this);
325 break;
326 case QMessageBox::Warning:
327 icon = UIIconPool::defaultIcon(UIIconPool::MessageBoxWarningIcon, this);
328 break;
329 case QIMessageBox::Critical:
330 icon = UIIconPool::defaultIcon(UIIconPool::MessageBoxCriticalIcon, this);
331 break;
332 case QIMessageBox::Question:
333 icon = UIIconPool::defaultIcon(UIIconPool::MessageBoxQuestionIcon, this);
334 break;
335 case QIMessageBox::GuruMeditation:
336 icon = QIcon(":/meditation_32px.png");
337 break;
338 default:
339 break;
340 }
341 if (!icon.isNull())
342 {
343 int size = style()->pixelMetric (QStyle::PM_MessageBoxIconSize, 0, this);
344 return icon.pixmap (size, size);
345 }else
346 return QPixmap();
347}
348
349void QIMessageBox::closeEvent (QCloseEvent *e)
350{
351 if (mWasDone)
352 e->accept();
353 else
354 e->ignore();
355}
356
357void QIMessageBox::showEvent (QShowEvent *e)
358{
359 if (!mWasPolished)
360 {
361 /* Polishing sub-widgets */
362 resize (minimumSizeHint());
363 qApp->processEvents();
364 mTextLabel->useSizeHintForWidth (mTextLabel->width());
365 mTextLabel->updateGeometry();
366 qApp->processEvents();
367 setFixedWidth (width());
368 mDetailsSplitter->toggleWidget();
369 mWasPolished = true;
370 }
371
372 QIDialog::showEvent (e);
373}
374
375void QIMessageBox::refreshDetails()
376{
377 /* Update message text iteself */
378 mTextLabel->setText (mText + mDetailsList [mDetailsIndex].first);
379 /* Update details table */
380 mDetailsText->setText (mDetailsList [mDetailsIndex].second);
381 setDetailsShown (!mDetailsText->toPlainText().isEmpty());
382
383 /* Update multi-paging system */
384 if (mDetailsList.size() > 1)
385 {
386 mDetailsSplitter->setButtonEnabled (true, mDetailsIndex < mDetailsList.size() - 1);
387 mDetailsSplitter->setButtonEnabled (false, mDetailsIndex > 0);
388 }
389
390 /* Update details label */
391 mDetailsSplitter->setName (mDetailsList.size() == 1 ? tr ("&Details") :
392 tr ("&Details (%1 of %2)").arg (mDetailsIndex + 1).arg (mDetailsList.size()));
393}
394
395/**
396 * Sets the visibility state of the optional details box
397 * to a value of the argument.
398 *
399 * @see #isDetailsShown()
400 * @see #setDetailsText()
401 */
402void QIMessageBox::setDetailsShown (bool aShown)
403{
404 if (aShown)
405 {
406 mFlagCB_Details->setVisible (mFlagCB_Main->isVisible());
407 mFlagCB_Details->setChecked (mFlagCB_Main->isChecked());
408 mFlagCB_Details->setText (mFlagCB_Main->text());
409 if (mFlagCB_Main->hasFocus())
410 mFlagCB_Details->setFocus();
411 mFlagCB_Main->setVisible (false);
412 mFlagCB = mFlagCB_Details;
413 mSpacer->changeSize (0, 0, QSizePolicy::Minimum, QSizePolicy::Minimum);
414 }
415
416 mDetailsVBox->setVisible (aShown);
417
418 if (!aShown)
419 {
420 mFlagCB_Main->setVisible (mFlagCB_Details->isVisible());
421 mFlagCB_Main->setChecked (mFlagCB_Details->isChecked());
422 mFlagCB_Main->setText (mFlagCB_Details->text());
423 if (mFlagCB_Details->hasFocus())
424 mFlagCB_Main->setFocus();
425 mFlagCB = mFlagCB_Main;
426 mSpacer->changeSize (0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
427 }
428}
429
430void QIMessageBox::detailsBack()
431{
432 if (mDetailsIndex > 0)
433 {
434 -- mDetailsIndex;
435 refreshDetails();
436 }
437}
438
439void QIMessageBox::detailsNext()
440{
441 if (mDetailsIndex < mDetailsList.size() - 1)
442 {
443 ++ mDetailsIndex;
444 refreshDetails();
445 }
446}
447
448void QIMessageBox::reject()
449{
450 if (mButtonEsc)
451 {
452 QDialog::reject();
453 setResult (mButtonEsc & ButtonMask);
454 }
455}
456
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use