VirtualBox

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

Last change on this file was 106061, checked in by vboxsync, 8 weeks ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 106.9 KB
Line 
1/* $Id: UIMessageCenter.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIMessageCenter class implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2024 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 <QAbstractButton>
30#include <QApplication>
31#include <QDir>
32#include <QFileInfo>
33#include <QLocale>
34#include <QProcess>
35#include <QThread>
36#include <QWindow>
37#ifdef VBOX_WS_MAC
38# include <QPushButton>
39#endif
40
41/* GUI includes: */
42#include "QIMessageBox.h"
43#include "UICommon.h"
44#include "UIConverter.h"
45#include "UIErrorString.h"
46#include "UIExtraDataManager.h"
47#include "UIGlobalSession.h"
48#include "UIHelpBrowserDialog.h"
49#include "UIHostComboEditor.h"
50#include "UIIconPool.h"
51#include "UIMedium.h"
52#include "UIMessageCenter.h"
53#include "UIModalWindowManager.h"
54#include "UINotificationCenter.h"
55#include "UIProgressDialog.h"
56#include "UITranslator.h"
57#include "UIVersion.h"
58#include "VBoxAboutDlg.h"
59#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
60# include "UINetworkRequestManager.h"
61#endif
62#ifdef VBOX_OSE
63# include "UINotificationCenter.h"
64#endif
65#ifdef VBOX_WS_MAC
66# include "VBoxUtils-darwin.h"
67#endif
68#ifdef VBOX_WS_WIN
69# include <Htmlhelp.h>
70#endif
71
72/* COM includes: */
73#include "CAppliance.h"
74#include "CBooleanFormValue.h"
75#include "CChoiceFormValue.h"
76#include "CCloudClient.h"
77#include "CCloudMachine.h"
78#include "CCloudProfile.h"
79#include "CCloudProvider.h"
80#include "CCloudProviderManager.h"
81#include "CConsole.h"
82#include "CDHCPServer.h"
83#include "CDisplay.h"
84#include "CExtPack.h"
85#include "CExtPackFile.h"
86#include "CExtPackManager.h"
87#include "CForm.h"
88#include "CHostNetworkInterface.h"
89#include "CMachine.h"
90#include "CMediumAttachment.h"
91#include "CMediumFormat.h"
92#include "CNATEngine.h"
93#include "CNATNetwork.h"
94#include "CRangedIntegerFormValue.h"
95#include "CSerialPort.h"
96#include "CSharedFolder.h"
97#include "CSnapshot.h"
98#include "CStorageController.h"
99#include "CStringFormValue.h"
100#include "CSystemProperties.h"
101#include "CUnattended.h"
102#include "CVFSExplorer.h"
103#include "CVirtualBoxErrorInfo.h"
104#include "CVirtualSystemDescription.h"
105#include "CVirtualSystemDescriptionForm.h"
106#ifdef VBOX_WITH_DRAG_AND_DROP
107# include "CDnDSource.h"
108# include "CDnDTarget.h"
109# include "CGuest.h"
110#endif
111
112/* Other VBox includes: */
113#include <iprt/errcore.h>
114#include <iprt/param.h>
115#include <iprt/path.h>
116
117
118/* static */
119UIMessageCenter *UIMessageCenter::s_pInstance = 0;
120UIMessageCenter *UIMessageCenter::instance() { return s_pInstance; }
121
122/* static */
123void UIMessageCenter::create()
124{
125 /* Make sure instance is NOT created yet: */
126 if (s_pInstance)
127 {
128 AssertMsgFailed(("UIMessageCenter instance is already created!"));
129 return;
130 }
131
132 /* Create instance: */
133 new UIMessageCenter;
134 /* Prepare instance: */
135 s_pInstance->prepare();
136}
137
138/* static */
139void UIMessageCenter::destroy()
140{
141 /* Make sure instance is NOT destroyed yet: */
142 if (!s_pInstance)
143 {
144 AssertMsgFailed(("UIMessageCenter instance is already destroyed!"));
145 return;
146 }
147
148 /* Cleanup instance: */
149 s_pInstance->cleanup();
150 /* Destroy instance: */
151 delete s_pInstance;
152}
153
154void UIMessageCenter::setWarningShown(const QString &strWarningName, bool fWarningShown) const
155{
156 if (fWarningShown && !m_warnings.contains(strWarningName))
157 m_warnings.append(strWarningName);
158 else if (!fWarningShown && m_warnings.contains(strWarningName))
159 m_warnings.removeAll(strWarningName);
160}
161
162bool UIMessageCenter::warningShown(const QString &strWarningName) const
163{
164 return m_warnings.contains(strWarningName);
165}
166
167int UIMessageCenter::message(QWidget *pParent, MessageType enmType,
168 const QString &strMessage,
169 const QString &strDetails,
170 const char *pcszAutoConfirmId /* = 0*/,
171 int iButton1 /* = 0*/,
172 int iButton2 /* = 0*/,
173 int iButton3 /* = 0*/,
174 const QString &strButtonText1 /* = QString() */,
175 const QString &strButtonText2 /* = QString() */,
176 const QString &strButtonText3 /* = QString() */,
177 const QString &strHelpKeyword /* = QString() */) const
178{
179 /* If this is NOT a GUI thread: */
180 if (thread() != QThread::currentThread())
181 {
182 /* We have to throw a blocking signal
183 * to show a message-box in the GUI thread: */
184 emit sigToShowMessageBox(pParent, enmType,
185 strMessage, strDetails,
186 iButton1, iButton2, iButton3,
187 strButtonText1, strButtonText2, strButtonText3,
188 QString(pcszAutoConfirmId), strHelpKeyword);
189 /* Inter-thread communications are not yet implemented: */
190 return 0;
191 }
192 /* In usual case we can chow a message-box directly: */
193 return showMessageBox(pParent, enmType,
194 strMessage, strDetails,
195 iButton1, iButton2, iButton3,
196 strButtonText1, strButtonText2, strButtonText3,
197 QString(pcszAutoConfirmId), strHelpKeyword);
198}
199
200void UIMessageCenter::error(QWidget *pParent, MessageType enmType,
201 const QString &strMessage,
202 const QString &strDetails,
203 const char *pcszAutoConfirmId /* = 0*/,
204 const QString &strHelpKeyword /* = QString() */) const
205{
206 message(pParent, enmType, strMessage, strDetails, pcszAutoConfirmId,
207 AlertButton_Ok | AlertButtonOption_Default | AlertButtonOption_Escape, 0 /* Button 2 */, 0 /* Button 3 */,
208 QString() /* strButtonText1 */, QString() /* strButtonText2 */, QString() /* strButtonText3 */, strHelpKeyword);
209}
210
211bool UIMessageCenter::errorWithQuestion(QWidget *pParent, MessageType enmType,
212 const QString &strMessage,
213 const QString &strDetails,
214 const char *pcszAutoConfirmId /* = 0*/,
215 const QString &strOkButtonText /* = QString()*/,
216 const QString &strCancelButtonText /* = QString()*/,
217 const QString &strHelpKeyword /* = QString()*/) const
218{
219 return (message(pParent, enmType, strMessage, strDetails, pcszAutoConfirmId,
220 AlertButton_Ok | AlertButtonOption_Default,
221 AlertButton_Cancel | AlertButtonOption_Escape,
222 0 /* third button */,
223 strOkButtonText,
224 strCancelButtonText,
225 QString() /* third button text*/,
226 strHelpKeyword) &
227 AlertButtonMask) == AlertButton_Ok;
228}
229
230void UIMessageCenter::alert(QWidget *pParent, MessageType enmType,
231 const QString &strMessage,
232 const char *pcszAutoConfirmId /* = 0*/,
233 const QString &strHelpKeyword /* = QString()*/) const
234{
235 error(pParent, enmType, strMessage, QString(), pcszAutoConfirmId, strHelpKeyword);
236}
237
238int UIMessageCenter::question(QWidget *pParent, MessageType enmType,
239 const QString &strMessage,
240 const char *pcszAutoConfirmId/* = 0*/,
241 int iButton1 /* = 0*/,
242 int iButton2 /* = 0*/,
243 int iButton3 /* = 0*/,
244 const QString &strButtonText1 /* = QString()*/,
245 const QString &strButtonText2 /* = QString()*/,
246 const QString &strButtonText3 /* = QString()*/) const
247{
248 return message(pParent, enmType, strMessage, QString(), pcszAutoConfirmId,
249 iButton1, iButton2, iButton3, strButtonText1, strButtonText2, strButtonText3);
250}
251
252bool UIMessageCenter::questionBinary(QWidget *pParent, MessageType enmType,
253 const QString &strMessage,
254 const char *pcszAutoConfirmId /* = 0*/,
255 const QString &strOkButtonText /* = QString()*/,
256 const QString &strCancelButtonText /* = QString()*/,
257 bool fDefaultFocusForOk /* = true*/) const
258{
259 return fDefaultFocusForOk ?
260 ((question(pParent, enmType, strMessage, pcszAutoConfirmId,
261 AlertButton_Ok | AlertButtonOption_Default,
262 AlertButton_Cancel | AlertButtonOption_Escape,
263 0 /* third button */,
264 strOkButtonText,
265 strCancelButtonText,
266 QString() /* third button */) &
267 AlertButtonMask) == AlertButton_Ok) :
268 ((question(pParent, enmType, strMessage, pcszAutoConfirmId,
269 AlertButton_Ok,
270 AlertButton_Cancel | AlertButtonOption_Default | AlertButtonOption_Escape,
271 0 /* third button */,
272 strOkButtonText,
273 strCancelButtonText,
274 QString() /* third button */) &
275 AlertButtonMask) == AlertButton_Ok);
276}
277
278int UIMessageCenter::questionTrinary(QWidget *pParent, MessageType enmType,
279 const QString &strMessage,
280 const char *pcszAutoConfirmId /* = 0*/,
281 const QString &strChoice1ButtonText /* = QString()*/,
282 const QString &strChoice2ButtonText /* = QString()*/,
283 const QString &strCancelButtonText /* = QString()*/) const
284{
285 return question(pParent, enmType, strMessage, pcszAutoConfirmId,
286 AlertButton_Choice1,
287 AlertButton_Choice2 | AlertButtonOption_Default,
288 AlertButton_Cancel | AlertButtonOption_Escape,
289 strChoice1ButtonText,
290 strChoice2ButtonText,
291 strCancelButtonText);
292}
293
294int UIMessageCenter::messageWithOption(QWidget *pParent, MessageType enmType,
295 const QString &strMessage,
296 const QString &strOptionText,
297 bool fDefaultOptionValue /* = true */,
298 int iButton1 /* = 0*/,
299 int iButton2 /* = 0*/,
300 int iButton3 /* = 0*/,
301 const QString &strButtonName1 /* = QString() */,
302 const QString &strButtonName2 /* = QString() */,
303 const QString &strButtonName3 /* = QString() */) const
304{
305 /* If no buttons are set, using single 'OK' button: */
306 if (iButton1 == 0 && iButton2 == 0 && iButton3 == 0)
307 iButton1 = AlertButton_Ok | AlertButtonOption_Default;
308
309 /* Assign corresponding title and icon: */
310 QString strTitle;
311 AlertIconType icon;
312 switch (enmType)
313 {
314 default:
315 case MessageType_Info:
316 strTitle = tr("VirtualBox - Information", "msg box title");
317 icon = AlertIconType_Information;
318 break;
319 case MessageType_Question:
320 strTitle = tr("VirtualBox - Question", "msg box title");
321 icon = AlertIconType_Question;
322 break;
323 case MessageType_Warning:
324 strTitle = tr("VirtualBox - Warning", "msg box title");
325 icon = AlertIconType_Warning;
326 break;
327 case MessageType_Error:
328 strTitle = tr("VirtualBox - Error", "msg box title");
329 icon = AlertIconType_Critical;
330 break;
331 case MessageType_Critical:
332 strTitle = tr("VirtualBox - Critical Error", "msg box title");
333 icon = AlertIconType_Critical;
334 break;
335 case MessageType_GuruMeditation:
336 strTitle = "VirtualBox - Guru Meditation"; /* don't translate this */
337 icon = AlertIconType_GuruMeditation;
338 break;
339 }
340
341 /* Create message-box: */
342 QWidget *pBoxParent = windowManager().realParentWindow(pParent ? pParent : windowManager().mainWindowShown());
343 QPointer<QIMessageBox> pBox = new QIMessageBox(strTitle, strMessage, icon,
344 iButton1, iButton2, iButton3, pBoxParent);
345 windowManager().registerNewParent(pBox, pBoxParent);
346
347 /* Load option: */
348 if (!strOptionText.isNull())
349 {
350 pBox->setFlagText(strOptionText);
351 pBox->setFlagChecked(fDefaultOptionValue);
352 }
353
354 /* Configure button-text: */
355 if (!strButtonName1.isNull())
356 pBox->setButtonText(0, strButtonName1);
357 if (!strButtonName2.isNull())
358 pBox->setButtonText(1, strButtonName2);
359 if (!strButtonName3.isNull())
360 pBox->setButtonText(2, strButtonName3);
361
362 /* Show box: */
363 int rc = pBox->exec();
364
365 /* Make sure box still valid: */
366 if (!pBox)
367 return rc;
368
369 /* Save option: */
370 if (pBox->flagChecked())
371 rc |= AlertOption_CheckBox;
372
373 /* Delete message-box: */
374 if (pBox)
375 delete pBox;
376
377 return rc;
378}
379
380bool UIMessageCenter::showModalProgressDialog(CProgress &progress,
381 const QString &strTitle,
382 const QString &strImage /* = "" */,
383 QWidget *pParent /* = 0*/,
384 int cMinDuration /* = 2000 */)
385{
386 /* Prepare result: */
387 bool fRc = false;
388
389 /* Gather suitable dialog parent: */
390 QWidget *pDlgParent = windowManager().realParentWindow(pParent ? pParent : windowManager().mainWindowShown());
391
392 /* Prepare pixmap: */
393 QPixmap pixmap;
394 if (!strImage.isEmpty())
395 {
396 const qreal fDevicePixelRatio = pDlgParent && pDlgParent->windowHandle() ? pDlgParent->windowHandle()->devicePixelRatio() : 1;
397 pixmap = UIIconPool::iconSet(strImage).pixmap(QSize(90, 90), fDevicePixelRatio);
398 }
399
400 /* Create progress-dialog: */
401 QPointer<UIProgressDialog> pProgressDlg = new UIProgressDialog(progress, strTitle, &pixmap, cMinDuration, pDlgParent);
402 if (pProgressDlg)
403 {
404 /* Register it as new parent: */
405 windowManager().registerNewParent(pProgressDlg, pDlgParent);
406
407 /* Run the dialog with the 350 ms refresh interval. */
408 pProgressDlg->run(350);
409
410 /* Make sure progress-dialog still valid: */
411 if (pProgressDlg)
412 {
413 /* Delete progress-dialog: */
414 delete pProgressDlg;
415 fRc = true;
416 }
417 }
418
419 /* Return result: */
420 return fRc;
421}
422
423void UIMessageCenter::cannotFindLanguage(const QString &strLangId, const QString &strNlsPath) const
424{
425 alert(0, MessageType_Error,
426 tr("<p>Could not find a language file for the language <b>%1</b> in the directory <b><nobr>%2</nobr></b>.</p>"
427 "<p>The language will be temporarily reset to the system default language. "
428 "Please go to the <b>Preferences</b> window which you can open from the <b>File</b> menu of the "
429 "VirtualBox Manager window, and select one of the existing languages on the <b>Language</b> page.</p>")
430 .arg(strLangId).arg(strNlsPath));
431}
432
433void UIMessageCenter::cannotLoadLanguage(const QString &strLangFile) const
434{
435 alert(0, MessageType_Error,
436 tr("<p>Could not load the language file <b><nobr>%1</nobr></b>. "
437 "<p>The language will be temporarily reset to English (built-in). "
438 "Please go to the <b>Preferences</b> window which you can open from the <b>File</b> menu of the "
439 "VirtualBox Manager window, and select one of the existing languages on the <b>Language</b> page.</p>")
440 .arg(strLangFile));
441}
442
443void UIMessageCenter::cannotInitUserHome(const QString &strUserHome) const
444{
445 error(0, MessageType_Critical,
446 tr("<p>Failed to initialize COM because the VirtualBox global "
447 "configuration directory <b><nobr>%1</nobr></b> is not accessible. "
448 "Please check the permissions of this directory and of its parent directory.</p>"
449 "<p>The application will now terminate.</p>")
450 .arg(strUserHome),
451 UIErrorString::formatErrorInfo(COMErrorInfo()));
452}
453
454void UIMessageCenter::cannotInitCOM(HRESULT rc) const
455{
456 error(0, MessageType_Critical,
457 tr("<p>Failed to initialize COM or to find the VirtualBox COM server. "
458 "Most likely, the VirtualBox server is not running or failed to start.</p>"
459 "<p>The application will now terminate.</p>"),
460 UIErrorString::formatErrorInfo(COMErrorInfo(), rc));
461}
462
463void UIMessageCenter::cannotHandleRuntimeOption(const QString &strOption) const
464{
465 alert(0, MessageType_Error,
466 tr("<b>%1</b> is an option for the VirtualBox VM runner (VirtualBoxVM) application, not the VirtualBox Manager.")
467 .arg(strOption));
468}
469
470#ifdef RT_OS_LINUX
471void UIMessageCenter::warnAboutWrongUSBMounted() const
472{
473 alert(0, MessageType_Warning,
474 tr("You seem to have the USBFS filesystem mounted at /sys/bus/usb/drivers. "
475 "We strongly recommend that you change this, as it is a severe mis-configuration of "
476 "your system which could cause USB devices to fail in unexpected ways."),
477 "warnAboutWrongUSBMounted");
478}
479#endif /* RT_OS_LINUX */
480
481void UIMessageCenter::cannotStartSelector() const
482{
483 alert(0, MessageType_Critical,
484 tr("<p>Cannot start the VirtualBox Manager due to local restrictions.</p>"
485 "<p>The application will now terminate.</p>"));
486}
487
488void UIMessageCenter::cannotStartRuntime() const
489{
490 /* Prepare error string: */
491 const QString strError = tr("<p>You must specify a machine to start, using the command line.</p><p>%1</p>",
492 "There will be a usage text passed as argument.");
493
494 /* Prepare Usage, it can change in future: */
495 const QString strTable = QString("<table cellspacing=0 style='white-space:pre'>%1</table>");
496 const QString strUsage = tr("<tr>"
497 "<td>Usage: VirtualBoxVM --startvm &lt;name|UUID&gt;</td>"
498 "</tr>"
499 "<tr>"
500 "<td>Starts the VirtualBox virtual machine with the given "
501 "name or unique identifier (UUID).</td>"
502 "</tr>");
503
504 /* Show error: */
505 alert(0, MessageType_Error, strError.arg(strTable.arg(strUsage)));
506}
507
508void UIMessageCenter::cannotCreateVirtualBoxClient(const CVirtualBoxClient &comClient) const
509{
510 error(0, MessageType_Critical,
511 tr("<p>Failed to create the VirtualBoxClient COM object.</p>"
512 "<p>The application will now terminate.</p>"),
513 UIErrorString::formatErrorInfo(comClient));
514}
515
516void UIMessageCenter::cannotAcquireVirtualBox(const CVirtualBoxClient &comClient) const
517{
518 QString err = tr("<p>Failed to acquire the VirtualBox COM object.</p>"
519 "<p>The application will now terminate.</p>");
520#if defined(VBOX_WS_NIX) || defined(VBOX_WS_MAC)
521 if (comClient.lastRC() == NS_ERROR_SOCKET_FAIL)
522 err += tr("<p>The reason for this error are most likely wrong permissions of the IPC "
523 "daemon socket due to an installation problem. Please check the permissions of "
524 "<font color=blue>'/tmp'</font> and <font color=blue>'/tmp/.vbox-*-ipc/'</font></p>");
525#endif
526 error(0, MessageType_Critical, err, UIErrorString::formatErrorInfo(comClient));
527}
528
529void UIMessageCenter::cannotFindMachineByName(const CVirtualBox &comVBox, const QString &strName) const
530{
531 error(0, MessageType_Error,
532 tr("There is no virtual machine named <b>%1</b>.")
533 .arg(strName),
534 UIErrorString::formatErrorInfo(comVBox));
535}
536
537void UIMessageCenter::cannotFindMachineById(const CVirtualBox &comVBox, const QUuid &uId) const
538{
539 error(0, MessageType_Error,
540 tr("There is no virtual machine with the identifier <b>%1</b>.")
541 .arg(uId.toString()),
542 UIErrorString::formatErrorInfo(comVBox));
543}
544
545void UIMessageCenter::cannotSetExtraData(const CVirtualBox &comVBox, const QString &strKey, const QString &strValue)
546{
547 error(0, MessageType_Error,
548 tr("Failed to set the global VirtualBox extra data for key <i>%1</i> to value <i>{%2}</i>.")
549 .arg(strKey, strValue),
550 UIErrorString::formatErrorInfo(comVBox));
551}
552
553void UIMessageCenter::cannotOpenMedium(const CVirtualBox &comVBox, const QString &strLocation, QWidget *pParent /* = 0 */) const
554{
555 /* Show the error: */
556 error(pParent, MessageType_Error,
557 tr("Failed to open the disk image file <nobr><b>%1</b></nobr>.").arg(strLocation), UIErrorString::formatErrorInfo(comVBox));
558}
559
560void UIMessageCenter::cannotOpenSession(const CSession &comSession) const
561{
562 error(0, MessageType_Error,
563 tr("Failed to create a new session."),
564 UIErrorString::formatErrorInfo(comSession));
565}
566
567void UIMessageCenter::cannotOpenSession(const CMachine &comMachine) const
568{
569 error(0, MessageType_Error,
570 tr("Failed to open a session for the virtual machine <b>%1</b>.")
571 .arg(CMachine(comMachine).GetName()),
572 UIErrorString::formatErrorInfo(comMachine));
573}
574
575void UIMessageCenter::cannotOpenSession(const CProgress &comProgress, const QString &strMachineName) const
576{
577 error(0, MessageType_Error,
578 tr("Failed to open a session for the virtual machine <b>%1</b>.")
579 .arg(strMachineName),
580 UIErrorString::formatErrorInfo(comProgress));
581}
582
583void UIMessageCenter::cannotSetExtraData(const CMachine &machine, const QString &strKey, const QString &strValue)
584{
585 error(0, MessageType_Error,
586 tr("Failed to set the extra data for key <i>%1</i> of machine <i>%2</i> to value <i>{%3}</i>.")
587 .arg(strKey, CMachine(machine).GetName(), strValue),
588 UIErrorString::formatErrorInfo(machine));
589}
590
591void UIMessageCenter::cannotAttachDevice(const CMachine &machine, UIMediumDeviceType enmType,
592 const QString &strLocation, const StorageSlot &storageSlot,
593 QWidget *pParent /* = 0*/)
594{
595 QString strMessage;
596 switch (enmType)
597 {
598 case UIMediumDeviceType_HardDisk:
599 {
600 strMessage = tr("Failed to attach the hard disk (<nobr><b>%1</b></nobr>) to the slot <i>%2</i> of the machine <b>%3</b>.")
601 .arg(strLocation).arg(gpConverter->toString(storageSlot)).arg(CMachine(machine).GetName());
602 break;
603 }
604 case UIMediumDeviceType_DVD:
605 {
606 strMessage = tr("Failed to attach the optical drive (<nobr><b>%1</b></nobr>) to the slot <i>%2</i> of the machine <b>%3</b>.")
607 .arg(strLocation).arg(gpConverter->toString(storageSlot)).arg(CMachine(machine).GetName());
608 break;
609 }
610 case UIMediumDeviceType_Floppy:
611 {
612 strMessage = tr("Failed to attach the floppy drive (<nobr><b>%1</b></nobr>) to the slot <i>%2</i> of the machine <b>%3</b>.")
613 .arg(strLocation).arg(gpConverter->toString(storageSlot)).arg(CMachine(machine).GetName());
614 break;
615 }
616 default:
617 break;
618 }
619 error(pParent, MessageType_Error,
620 strMessage, UIErrorString::formatErrorInfo(machine));
621}
622
623void UIMessageCenter::cannotDetachDevice(const CMachine &machine, UIMediumDeviceType enmType,
624 const QString &strLocation, const StorageSlot &storageSlot,
625 QWidget *pParent /* = 0*/) const
626{
627 /* Prepare the message: */
628 QString strMessage;
629 switch (enmType)
630 {
631 case UIMediumDeviceType_HardDisk:
632 {
633 strMessage = tr("Failed to detach the hard disk (<nobr><b>%1</b></nobr>) from the slot <i>%2</i> of the machine <b>%3</b>.")
634 .arg(strLocation, gpConverter->toString(storageSlot), CMachine(machine).GetName());
635 break;
636 }
637 case UIMediumDeviceType_DVD:
638 {
639 strMessage = tr("Failed to detach the optical drive (<nobr><b>%1</b></nobr>) from the slot <i>%2</i> of the machine <b>%3</b>.")
640 .arg(strLocation, gpConverter->toString(storageSlot), CMachine(machine).GetName());
641 break;
642 }
643 case UIMediumDeviceType_Floppy:
644 {
645 strMessage = tr("Failed to detach the floppy drive (<nobr><b>%1</b></nobr>) from the slot <i>%2</i> of the machine <b>%3</b>.")
646 .arg(strLocation, gpConverter->toString(storageSlot), CMachine(machine).GetName());
647 break;
648 }
649 default:
650 break;
651 }
652 /* Show the error: */
653 error(pParent, MessageType_Error, strMessage, UIErrorString::formatErrorInfo(machine));
654}
655
656bool UIMessageCenter::cannotRemountMedium(const CMachine &machine, const UIMedium &medium, bool fMount,
657 bool fRetry, QWidget *pParent /* = 0*/) const
658{
659 /* Compose the message: */
660 QString strMessage;
661 switch (medium.type())
662 {
663 case UIMediumDeviceType_DVD:
664 {
665 if (fMount)
666 {
667 strMessage = tr("<p>Unable to insert the virtual optical disk <nobr><b>%1</b></nobr> into the machine <b>%2</b>.</p>");
668 if (fRetry)
669 strMessage += tr("<p>Would you like to try to force insertion of this disk?</p>");
670 }
671 else
672 {
673 strMessage = tr("<p>Unable to eject the virtual optical disk <nobr><b>%1</b></nobr> from the machine <b>%2</b>.</p>");
674 if (fRetry)
675 strMessage += tr("<p>Would you like to try to force ejection of this disk?</p>");
676 }
677 break;
678 }
679 case UIMediumDeviceType_Floppy:
680 {
681 if (fMount)
682 {
683 strMessage = tr("<p>Unable to insert the virtual floppy disk <nobr><b>%1</b></nobr> into the machine <b>%2</b>.</p>");
684 if (fRetry)
685 strMessage += tr("<p>Would you like to try to force insertion of this disk?</p>");
686 }
687 else
688 {
689 strMessage = tr("<p>Unable to eject the virtual floppy disk <nobr><b>%1</b></nobr> from the machine <b>%2</b>.</p>");
690 if (fRetry)
691 strMessage += tr("<p>Would you like to try to force ejection of this disk?</p>");
692 }
693 break;
694 }
695 default:
696 break;
697 }
698 /* Show the messsage: */
699 if (fRetry)
700 return errorWithQuestion(pParent, MessageType_Question,
701 strMessage.arg(medium.isHostDrive() ? medium.name() : medium.location(), CMachine(machine).GetName()),
702 UIErrorString::formatErrorInfo(machine),
703 0 /* Auto Confirm ID */,
704 tr("Force Unmount"));
705 error(pParent, MessageType_Error,
706 strMessage.arg(medium.isHostDrive() ? medium.name() : medium.location(), CMachine(machine).GetName()),
707 UIErrorString::formatErrorInfo(machine));
708 return false;
709}
710
711void UIMessageCenter::cannotSetHostSettings(const CHost &comHost, QWidget *pParent /* = 0 */) const
712{
713 error(pParent, MessageType_Critical,
714 tr("Failed to set global host settings."),
715 UIErrorString::formatErrorInfo(comHost));
716}
717
718void UIMessageCenter::cannotSetSystemProperties(const CSystemProperties &properties, QWidget *pParent /* = 0*/) const
719{
720 error(pParent, MessageType_Critical,
721 tr("Failed to set global VirtualBox properties."),
722 UIErrorString::formatErrorInfo(properties));
723}
724
725void UIMessageCenter::cannotSaveMachineSettings(const CMachine &machine, QWidget *pParent /* = 0*/) const
726{
727 error(pParent, MessageType_Error,
728 tr("Failed to save the settings of the virtual machine <b>%1</b> to <b><nobr>%2</nobr></b>.")
729 .arg(CMachine(machine).GetName(), CMachine(machine).GetSettingsFilePath()),
730 UIErrorString::formatErrorInfo(machine));
731}
732
733void UIMessageCenter::cannotAddDiskEncryptionPassword(const CConsole &console)
734{
735 error(0, MessageType_Error,
736 tr("Bad password or authentication failure."),
737 UIErrorString::formatErrorInfo(console));
738}
739
740bool UIMessageCenter::confirmResetMachine(const QString &strNames) const
741{
742 return questionBinary(0, MessageType_Question,
743 tr("<p>Do you really want to reset the following virtual machines?</p>"
744 "<p><b>%1</b></p><p>This will cause any unsaved data "
745 "in applications running inside it to be lost.</p>")
746 .arg(strNames),
747 "confirmResetMachine" /* auto-confirm id */,
748 tr("Reset", "machine"));
749}
750
751void UIMessageCenter::cannotSaveSettings(const QString strDetails, QWidget *pParent /* = 0 */) const
752{
753 error(pParent, MessageType_Error,
754 tr("Failed to save the settings."),
755 strDetails);
756}
757
758void UIMessageCenter::warnAboutUnaccessibleUSB(const COMBaseWithEI &object, QWidget *pParent /* = 0*/) const
759{
760 /* If IMachine::GetUSBController(), IHost::GetUSBDevices() etc. return
761 * E_NOTIMPL, it means the USB support is intentionally missing
762 * (as in the OSE version). Don't show the error message in this case. */
763 COMResult res(object);
764 if (res.rc() == E_NOTIMPL)
765 return;
766 /* Show the error: */
767 error(pParent, res.isWarning() ? MessageType_Warning : MessageType_Error,
768 tr("Failed to access the USB subsystem."),
769 UIErrorString::formatErrorInfo(res),
770 "warnAboutUnaccessibleUSB");
771}
772
773void UIMessageCenter::warnAboutStateChange(QWidget *pParent /* = 0*/) const
774{
775 if (warningShown("warnAboutStateChange"))
776 return;
777 setWarningShown("warnAboutStateChange", true);
778
779 alert(pParent, MessageType_Warning,
780 tr("The virtual machine that you are changing has been started. "
781 "Only certain settings can be changed while a machine is running. "
782 "All other changes will be lost if you close this window now."));
783
784 setWarningShown("warnAboutStateChange", false);
785}
786
787bool UIMessageCenter::confirmSettingsDiscarding(QWidget *pParent /* = 0 */) const
788{
789 return questionBinary(pParent, MessageType_Question,
790 tr("<p>The machine settings were changed.</p>"
791 "<p>Would you like to discard the changed settings or to keep editing them?</p>"),
792 0 /* auto-confirm id */,
793 tr("Discard changes"), tr("Keep editing"));
794
795}
796
797bool UIMessageCenter::confirmSettingsReloading(QWidget *pParent /* = 0 */) const
798{
799 if (warningShown("confirmSettingsReloading"))
800 return false;
801 setWarningShown("confirmSettingsReloading", true);
802
803 const bool fResult = questionBinary(pParent, MessageType_Question,
804 tr("<p>The machine settings were changed while you were editing them. "
805 "You currently have unsaved setting changes.</p>"
806 "<p>Would you like to reload the changed settings or to keep your own changes?</p>"),
807 0 /* auto-confirm id */,
808 tr("Reload settings"), tr("Keep changes"));
809
810 setWarningShown("confirmSettingsReloading", false);
811
812 return fResult;
813}
814
815int UIMessageCenter::confirmRemovingOfLastDVDDevice(QWidget *pParent /* = 0*/) const
816{
817 return questionBinary(pParent, MessageType_Info,
818 tr("<p>Are you sure you want to delete the optical drive?</p>"
819 "<p>You will not be able to insert any optical disks or ISO images "
820 "or install the Guest Additions without it!</p>"),
821 0 /* auto-confirm id */,
822 tr("Remove", "medium") /* ok button text */,
823 QString() /* cancel button text */,
824 false /* ok button by default? */);
825}
826
827bool UIMessageCenter::confirmStorageBusChangeWithOpticalRemoval(QWidget *pParent /* = 0 */) const
828{
829 return questionBinary(pParent, MessageType_Question,
830 tr("<p>This controller has optical devices attached. You have requested storage bus "
831 "change to type which doesn't support optical devices.</p><p>If you proceed optical "
832 "devices will be removed.</p>"));
833}
834
835bool UIMessageCenter::confirmStorageBusChangeWithExcessiveRemoval(QWidget *pParent /* = 0 */) const
836{
837 return questionBinary(pParent, MessageType_Question,
838 tr("<p>This controller has devices attached. You have requested storage bus change to "
839 "type which supports smaller amount of attached devices.</p><p>If you proceed "
840 "excessive devices will be removed.</p>"));
841}
842
843bool UIMessageCenter::warnAboutIncorrectPort(QWidget *pParent /* = 0 */) const
844{
845 alert(pParent, MessageType_Error,
846 tr("The current port forwarding rules are not valid. "
847 "None of the host or guest port values may be set to zero."));
848 return false;
849}
850
851bool UIMessageCenter::warnAboutIncorrectAddress(QWidget *pParent /* = 0 */) const
852{
853 alert(pParent, MessageType_Error,
854 tr("The current port forwarding rules are not valid. "
855 "All of the host or guest address values should be correct or empty."));
856 return false;
857}
858
859bool UIMessageCenter::warnAboutEmptyGuestAddress(QWidget *pParent /* = 0 */) const
860{
861 alert(pParent, MessageType_Error,
862 tr("The current port forwarding rules are not valid. "
863 "None of the guest address values may be empty."));
864 return false;
865}
866
867bool UIMessageCenter::warnAboutNameShouldBeUnique(QWidget *pParent /* = 0 */) const
868{
869 alert(pParent, MessageType_Error,
870 tr("The current port forwarding rules are not valid. "
871 "Rule names should be unique."));
872 return false;
873}
874
875bool UIMessageCenter::warnAboutRulesConflict(QWidget *pParent /* = 0 */) const
876{
877 alert(pParent, MessageType_Error,
878 tr("The current port forwarding rules are not valid. "
879 "Few rules have same host ports and conflicting IP addresses."));
880 return false;
881}
882
883bool UIMessageCenter::confirmCancelingPortForwardingDialog(QWidget *pParent /* = 0 */) const
884{
885 return questionBinary(pParent, MessageType_Question,
886 tr("<p>There are unsaved changes in the port forwarding configuration.</p>"
887 "<p>If you proceed your changes will be discarded.</p>"),
888 0 /* auto-confirm id */,
889 QString() /* ok button text */,
890 QString() /* cancel button text */,
891 false /* ok button by default? */);
892}
893
894bool UIMessageCenter::confirmRestoringDefaultKeys(QWidget *pParent /* = 0 */) const
895{
896 return questionBinary(pParent, MessageType_Question,
897 tr("<p>You are going to restore default secure boot keys.</p>"
898 "<p>If you proceed your current keys will be rewritten. "
899 "You may not be able to boot affected VM anymore.</p>"),
900 0 /* auto-confirm id */,
901 QString() /* ok button text */,
902 QString() /* cancel button text */,
903 false /* ok button by default? */);
904}
905
906bool UIMessageCenter::warnAboutInaccessibleMedia() const
907{
908 return questionBinary(0, MessageType_Warning,
909 tr("<p>One or more disk image files are not currently accessible. As a result, you will "
910 "not be able to operate virtual machines that use these files until "
911 "they become accessible later.</p>"
912 "<p>Press <b>Check</b> to open the Virtual Media Manager window and "
913 "see which files are inaccessible, or press <b>Ignore</b> to "
914 "ignore this message.</p>"),
915 "warnAboutInaccessibleMedia",
916 tr("Check", "inaccessible media message box"), tr("Ignore"));
917}
918
919bool UIMessageCenter::confirmDiscardSavedState(const QString &strNames) const
920{
921 return questionBinary(0, MessageType_Question,
922 tr("<p>Are you sure you want to discard the saved state of "
923 "the following virtual machines?</p><p><b>%1</b></p>"
924 "<p>This operation is equivalent to resetting or powering off "
925 "the machine without doing a proper shutdown of the guest OS.</p>")
926 .arg(strNames),
927 0 /* auto-confirm id */,
928 tr("Discard", "saved state"));
929}
930
931bool UIMessageCenter::confirmTerminateCloudInstance(const QString &strNames) const
932{
933 return questionBinary(0, MessageType_Question,
934 tr("<p>Are you sure you want to terminate the cloud instance "
935 "of the following virtual machines?</p><p><b>%1</b></p>")
936 .arg(strNames),
937 0 /* auto-confirm id */,
938 tr("Terminate", "cloud instance"));
939}
940
941bool UIMessageCenter::confirmACPIShutdownMachine(const QString &strNames) const
942{
943 return questionBinary(0, MessageType_Question,
944 tr("<p>Do you really want to send an ACPI shutdown signal "
945 "to the following virtual machines?</p><p><b>%1</b></p>")
946 .arg(strNames),
947 "confirmACPIShutdownMachine" /* auto-confirm id */,
948 tr("ACPI Shutdown", "machine"));
949}
950
951bool UIMessageCenter::confirmPowerOffMachine(const QString &strNames) const
952{
953 return questionBinary(0, MessageType_Question,
954 tr("<p>Do you really want to power off the following virtual machines?</p>"
955 "<p><b>%1</b></p><p>This will cause any unsaved data in applications "
956 "running inside it to be lost.</p>")
957 .arg(strNames),
958 "confirmPowerOffMachine" /* auto-confirm id */,
959 tr("Power Off", "machine"));
960}
961
962bool UIMessageCenter::confirmStartMultipleMachines(const QString &strNames) const
963{
964 return questionBinary(0, MessageType_Question,
965 tr("<p>You are about to start all of the following virtual machines:</p>"
966 "<p><b>%1</b></p><p>This could take some time and consume a lot of "
967 "host system resources. Do you wish to proceed?</p>").arg(strNames),
968 "confirmStartMultipleMachines" /* auto-confirm id */);
969}
970
971bool UIMessageCenter::confirmAutomaticCollisionResolve(const QString &strName, const QString &strGroupName) const
972{
973 return questionBinary(0, MessageType_Question,
974 tr("<p>You are trying to move group <nobr><b>%1</b></nobr> to group "
975 "<nobr><b>%2</b></nobr> which already have another item with the same name.</p>"
976 "<p>Would you like to automatically rename it?</p>")
977 .arg(strName, strGroupName),
978 0 /* auto-confirm id */,
979 tr("Rename"));
980}
981
982void UIMessageCenter::cannotSetGroups(const CMachine &machine) const
983{
984 /* Compose machine name: */
985 QString strName = CMachine(machine).GetName();
986 if (strName.isEmpty())
987 strName = QFileInfo(CMachine(machine).GetSettingsFilePath()).baseName();
988 /* Show the error: */
989 error(0, MessageType_Error,
990 tr("Failed to set groups of the virtual machine <b>%1</b>.")
991 .arg(strName),
992 UIErrorString::formatErrorInfo(machine));
993}
994
995bool UIMessageCenter::confirmMachineItemRemoval(const QStringList &names) const
996{
997 return questionBinary(0, MessageType_Question,
998 tr("<p>You are about to remove following virtual machine items from the machine list:</p>"
999 "<p><b>%1</b></p><p>Do you wish to proceed?</p>")
1000 .arg(names.join(", ")),
1001 0 /* auto-confirm id */,
1002 tr("Remove") /* ok button text */,
1003 QString() /* cancel button text */,
1004 false /* ok button by default? */);
1005}
1006
1007int UIMessageCenter::confirmMachineRemoval(const QList<CMachine> &machines) const
1008{
1009 /* Enumerate the machines: */
1010 int cInacessibleMachineCount = 0;
1011 bool fMachineWithHardDiskPresent = false;
1012 QString strMachineNames;
1013 foreach (const CMachine &machine, machines)
1014 {
1015 /* Prepare machine name: */
1016 QString strMachineName;
1017 if (machine.GetAccessible())
1018 {
1019 /* Just get machine name: */
1020 strMachineName = machine.GetName();
1021 /* Enumerate the attachments: */
1022 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments();
1023 foreach (const CMediumAttachment &attachment, attachments)
1024 {
1025 /* Check if the medium is a hard disk: */
1026 if (attachment.GetType() == KDeviceType_HardDisk)
1027 {
1028 /* Check if that hard disk isn't shared.
1029 * If hard disk is shared, it will *never* be deleted: */
1030 QVector<QUuid> usedMachineList = attachment.GetMedium().GetMachineIds();
1031 if (usedMachineList.size() == 1)
1032 {
1033 fMachineWithHardDiskPresent = true;
1034 break;
1035 }
1036 }
1037 }
1038 }
1039 else
1040 {
1041 /* Compose machine name: */
1042 QFileInfo fi(machine.GetSettingsFilePath());
1043 strMachineName = UICommon::hasAllowedExtension(fi.completeSuffix(), VBoxFileExts) ? fi.completeBaseName() : fi.fileName();
1044 /* Increment inacessible machine count: */
1045 ++cInacessibleMachineCount;
1046 }
1047 /* Append machine name to the full name string: */
1048 strMachineNames += QString(strMachineNames.isEmpty() ? "<b>%1</b>" : ", <b>%1</b>").arg(strMachineName);
1049 }
1050
1051 /* Prepare message text: */
1052 QString strText = cInacessibleMachineCount == machines.size() ?
1053 tr("<p>You are about to remove following inaccessible virtual machines from the machine list:</p>"
1054 "<p>%1</p>"
1055 "<p>Do you wish to proceed?</p>")
1056 .arg(strMachineNames) :
1057 fMachineWithHardDiskPresent ?
1058 tr("<p>You are about to remove following virtual machines from the machine list:</p>"
1059 "<p>%1</p>"
1060 "<p>Would you like to delete the files containing the virtual machine from your hard disk as well? "
1061 "Doing this will also remove the files containing the machine's virtual hard disks "
1062 "if they are not in use by another machine.</p>")
1063 .arg(strMachineNames) :
1064 tr("<p>You are about to remove following virtual machines from the machine list:</p>"
1065 "<p>%1</p>"
1066 "<p>Would you like to delete the files containing the virtual machine from your hard disk as well?</p>")
1067 .arg(strMachineNames);
1068
1069 /* Prepare message itself: */
1070 return cInacessibleMachineCount == machines.size() ?
1071 message(0, MessageType_Question,
1072 strText, QString(),
1073 0 /* auto-confirm id */,
1074 AlertButton_Ok,
1075 AlertButton_Cancel | AlertButtonOption_Default | AlertButtonOption_Escape,
1076 0,
1077 tr("Remove")) :
1078 message(0, MessageType_Question,
1079 strText, QString(),
1080 0 /* auto-confirm id */,
1081 AlertButton_Choice1,
1082 AlertButton_Choice2,
1083 AlertButton_Cancel | AlertButtonOption_Default | AlertButtonOption_Escape,
1084 tr("Delete all files"),
1085 tr("Remove only"));
1086}
1087
1088int UIMessageCenter::confirmCloudMachineRemoval(const QList<CCloudMachine> &machines) const
1089{
1090 /* Enumerate the machines: */
1091 QStringList machineNames;
1092 foreach (const CCloudMachine &comMachine, machines)
1093 {
1094 /* Append machine name to the full name string: */
1095 if (comMachine.GetAccessible())
1096 machineNames << QString("<b>%1</b>").arg(comMachine.GetName());
1097 }
1098
1099 /* Prepare message text: */
1100 QString strText = tr("<p>You are about to remove following cloud virtual machines from the machine list:</p>"
1101 "<p>%1</p>"
1102 "<p>Would you like to delete the instances and boot volumes of these machines as well?</p>")
1103 .arg(machineNames.join(", "));
1104
1105 /* Prepare message itself: */
1106 return message(0, MessageType_Question,
1107 strText, QString(),
1108 0 /* auto-confirm id */,
1109 AlertButton_Choice1,
1110 AlertButton_Choice2,
1111 AlertButton_Cancel | AlertButtonOption_Default | AlertButtonOption_Escape,
1112 tr("Delete everything"),
1113 tr("Remove only"));
1114}
1115
1116int UIMessageCenter::confirmSnapshotRestoring(const QString &strSnapshotName, bool fAlsoCreateNewSnapshot) const
1117{
1118 return fAlsoCreateNewSnapshot ?
1119 messageWithOption(0, MessageType_Question,
1120 tr("<p>You are about to restore snapshot <nobr><b>%1</b></nobr>.</p>"
1121 "<p>You can create a snapshot of the current state of the virtual machine first by checking the box below; "
1122 "if you do not do this the current state will be permanently lost. Do you wish to proceed?</p>")
1123 .arg(strSnapshotName),
1124 tr("Create a snapshot of the current machine state"),
1125 !gEDataManager->messagesWithInvertedOption().contains("confirmSnapshotRestoring"),
1126 AlertButton_Ok,
1127 AlertButton_Cancel | AlertButtonOption_Default | AlertButtonOption_Escape,
1128 0 /* 3rd button */,
1129 tr("Restore"), tr("Cancel"), QString() /* 3rd button text */) :
1130 message(0, MessageType_Question,
1131 tr("<p>Are you sure you want to restore snapshot <nobr><b>%1</b></nobr>?</p>")
1132 .arg(strSnapshotName),
1133 QString() /* details */,
1134 0 /* auto-confirm id */,
1135 AlertButton_Ok,
1136 AlertButton_Cancel | AlertButtonOption_Default | AlertButtonOption_Escape,
1137 0 /* 3rd button */,
1138 tr("Restore"), tr("Cancel"), QString() /* 3rd button text */);
1139}
1140
1141bool UIMessageCenter::confirmSnapshotRemoval(const QString &strSnapshotName) const
1142{
1143 return questionBinary(0, MessageType_Question,
1144 tr("<p>Deleting the snapshot will cause the state information saved in it to be lost, and storage data spread over "
1145 "several image files that VirtualBox has created together with the snapshot will be merged into one file. "
1146 "This can be a lengthy process, and the information in the snapshot cannot be recovered.</p>"
1147 "</p>Are you sure you want to delete the selected snapshot <b>%1</b>?</p>")
1148 .arg(strSnapshotName),
1149 0 /* auto-confirm id */,
1150 tr("Delete") /* ok button text */,
1151 QString() /* cancel button text */,
1152 false /* ok button by default? */);
1153}
1154
1155bool UIMessageCenter::warnAboutSnapshotRemovalFreeSpace(const QString &strSnapshotName,
1156 const QString &strTargetImageName,
1157 const QString &strTargetImageMaxSize,
1158 const QString &strTargetFileSystemFree) const
1159{
1160 return questionBinary(0, MessageType_Question,
1161 tr("<p>Deleting the snapshot %1 will temporarily need more storage space. In the worst case the size of image %2 will grow by %3, "
1162 "however on this filesystem there is only %4 free.</p><p>Running out of storage space during the merge operation can result in "
1163 "corruption of the image and the VM configuration, i.e. loss of the VM and its data.</p><p>You may continue with deleting "
1164 "the snapshot at your own risk.</p>")
1165 .arg(strSnapshotName, strTargetImageName, strTargetImageMaxSize, strTargetFileSystemFree),
1166 0 /* auto-confirm id */,
1167 tr("Delete") /* ok button text */,
1168 QString() /* cancel button text */,
1169 false /* ok button by default? */);
1170}
1171
1172bool UIMessageCenter::confirmInstallExtensionPack(const QString &strPackName, const QString &strPackVersion,
1173 const QString &strPackDescription, QWidget *pParent /* = 0*/) const
1174{
1175 return questionBinary(pParent, MessageType_Question,
1176 tr("<p>You are about to install a VirtualBox extension pack. "
1177 "Extension packs complement the functionality of VirtualBox and can contain system level software "
1178 "that could be potentially harmful to your system. Please review the description below and only proceed "
1179 "if you have obtained the extension pack from a trusted source.</p>"
1180 "<p><table cellpadding=0 cellspacing=5>"
1181 "<tr><td><b>Name:&nbsp;&nbsp;</b></td><td>%1</td></tr>"
1182 "<tr><td><b>Version:&nbsp;&nbsp;</b></td><td>%2</td></tr>"
1183 "<tr><td><b>Description:&nbsp;&nbsp;</b></td><td>%3</td></tr>"
1184 "</table></p>")
1185 .arg(strPackName).arg(strPackVersion).arg(strPackDescription),
1186 0 /* auto-confirm id */,
1187 tr("Install", "extension pack"));
1188}
1189
1190bool UIMessageCenter::confirmReplaceExtensionPack(const QString &strPackName, const QString &strPackVersionNew,
1191 const QString &strPackVersionOld, const QString &strPackDescription,
1192 QWidget *pParent /* = 0*/) const
1193{
1194 /* Prepare initial message: */
1195 QString strBelehrung = tr("Extension packs complement the functionality of VirtualBox and can contain "
1196 "system level software that could be potentially harmful to your system. "
1197 "Please review the description below and only proceed if you have obtained "
1198 "the extension pack from a trusted source.");
1199
1200 /* Compare versions: */
1201 QByteArray ba1 = strPackVersionNew.toUtf8();
1202 QByteArray ba2 = strPackVersionOld.toUtf8();
1203 int iVerCmp = RTStrVersionCompare(ba1.constData(), ba2.constData());
1204
1205 /* Show the question: */
1206 bool fRc;
1207 if (iVerCmp > 0)
1208 fRc = questionBinary(pParent, MessageType_Question,
1209 tr("<p>An older version of the extension pack is already installed, would you like to upgrade? "
1210 "<p>%1</p>"
1211 "<p><table cellpadding=0 cellspacing=5>"
1212 "<tr><td><b>Name:&nbsp;&nbsp;</b></td><td>%2</td></tr>"
1213 "<tr><td><b>New Version:&nbsp;&nbsp;</b></td><td>%3</td></tr>"
1214 "<tr><td><b>Current Version:&nbsp;&nbsp;</b></td><td>%4</td></tr>"
1215 "<tr><td><b>Description:&nbsp;&nbsp;</b></td><td>%5</td></tr>"
1216 "</table></p>")
1217 .arg(strBelehrung).arg(strPackName).arg(strPackVersionNew).arg(strPackVersionOld).arg(strPackDescription),
1218 0 /* auto-confirm id */,
1219 tr("&Upgrade"));
1220 else if (iVerCmp < 0)
1221 fRc = questionBinary(pParent, MessageType_Question,
1222 tr("<p>An newer version of the extension pack is already installed, would you like to downgrade? "
1223 "<p>%1</p>"
1224 "<p><table cellpadding=0 cellspacing=5>"
1225 "<tr><td><b>Name:&nbsp;&nbsp;</b></td><td>%2</td></tr>"
1226 "<tr><td><b>New Version:&nbsp;&nbsp;</b></td><td>%3</td></tr>"
1227 "<tr><td><b>Current Version:&nbsp;&nbsp;</b></td><td>%4</td></tr>"
1228 "<tr><td><b>Description:&nbsp;&nbsp;</b></td><td>%5</td></tr>"
1229 "</table></p>")
1230 .arg(strBelehrung).arg(strPackName).arg(strPackVersionNew).arg(strPackVersionOld).arg(strPackDescription),
1231 0 /* auto-confirm id */,
1232 tr("&Downgrade"));
1233 else
1234 fRc = questionBinary(pParent, MessageType_Question,
1235 tr("<p>The extension pack is already installed with the same version, would you like reinstall it? "
1236 "<p>%1</p>"
1237 "<p><table cellpadding=0 cellspacing=5>"
1238 "<tr><td><b>Name:&nbsp;&nbsp;</b></td><td>%2</td></tr>"
1239 "<tr><td><b>Version:&nbsp;&nbsp;</b></td><td>%3</td></tr>"
1240 "<tr><td><b>Description:&nbsp;&nbsp;</b></td><td>%4</td></tr>"
1241 "</table></p>")
1242 .arg(strBelehrung).arg(strPackName).arg(strPackVersionOld).arg(strPackDescription),
1243 0 /* auto-confirm id */,
1244 tr("&Reinstall"));
1245 return fRc;
1246}
1247
1248bool UIMessageCenter::confirmRemoveExtensionPack(const QString &strPackName, QWidget *pParent /* = 0*/) const
1249{
1250 return questionBinary(pParent, MessageType_Question,
1251 tr("<p>You are about to remove the VirtualBox extension pack <b>%1</b>.</p>"
1252 "<p>Are you sure you want to proceed?</p>")
1253 .arg(strPackName),
1254 0 /* auto-confirm id */,
1255 tr("Remove") /* ok button text */,
1256 QString() /* cancel button text */,
1257 false /* ok button by default? */);
1258}
1259
1260bool UIMessageCenter::confirmMediumRelease(const UIMedium &medium, bool fInduced, QWidget *pParent /* = 0 */) const
1261{
1262 /* Prepare the usage: */
1263 QStringList usage;
1264 CVirtualBox vbox = gpGlobalSession->virtualBox();
1265 foreach (const QUuid &uMachineID, medium.curStateMachineIds())
1266 {
1267 CMachine machine = vbox.FindMachine(uMachineID.toString());
1268 if (!vbox.isOk() || machine.isNull())
1269 continue;
1270 usage << machine.GetName();
1271 }
1272 /* Show the question: */
1273 return !fInduced
1274 ? questionBinary(pParent, MessageType_Question,
1275 tr("<p>Are you sure you want to release the disk image file <nobr><b>%1</b></nobr>?</p>"
1276 "<p>This will detach it from the following virtual machine(s): <b>%2</b>.</p>")
1277 .arg(medium.location(), usage.join(", ")),
1278 0 /* auto-confirm id */,
1279 tr("Release", "detach medium"))
1280 : questionBinary(pParent, MessageType_Question,
1281 tr("<p>The changes you requested require this disk to "
1282 "be released from the machines it is attached to.</p>"
1283 "<p>Are you sure you want to release the disk image file <nobr><b>%1</b></nobr>?</p>"
1284 "<p>This will detach it from the following virtual machine(s): <b>%2</b>.</p>")
1285 .arg(medium.location(), usage.join(", ")),
1286 0 /* auto-confirm id */,
1287 tr("Release", "detach medium"));
1288}
1289
1290bool UIMessageCenter::confirmMediumRemoval(const UIMedium &medium, QWidget *pParent /* = 0*/) const
1291{
1292 /* Prepare the message: */
1293 QString strMessage;
1294 switch (medium.type())
1295 {
1296 case UIMediumDeviceType_HardDisk:
1297 {
1298 strMessage = tr("<p>Are you sure you want to remove the virtual hard disk "
1299 "<nobr><b>%1</b></nobr> from the list of known disk image files?</p>");
1300 /* Compose capabilities flag: */
1301 qulonglong caps = 0;
1302 QVector<KMediumFormatCapabilities> capabilities;
1303 capabilities = medium.medium().GetMediumFormat().GetCapabilities();
1304 for (int i = 0; i < capabilities.size(); ++i)
1305 caps |= capabilities[i];
1306 /* Check capabilities for additional options: */
1307 if (caps & KMediumFormatCapabilities_File)
1308 {
1309 if (medium.state() == KMediumState_Inaccessible)
1310 strMessage += tr("<p>As this hard disk is inaccessible its image file"
1311 " cannot be deleted.</p>");
1312 }
1313 break;
1314 }
1315 case UIMediumDeviceType_DVD:
1316 {
1317 strMessage = tr("<p>Are you sure you want to remove the virtual optical disk "
1318 "<nobr><b>%1</b></nobr> from the list of known disk image files?</p>");
1319 strMessage += tr("<p>Note that the storage unit of this medium will not be "
1320 "deleted and that it will be possible to use it later again.</p>");
1321 break;
1322 }
1323 case UIMediumDeviceType_Floppy:
1324 {
1325 strMessage = tr("<p>Are you sure you want to remove the virtual floppy disk "
1326 "<nobr><b>%1</b></nobr> from the list of known disk image files?</p>");
1327 strMessage += tr("<p>Note that the storage unit of this medium will not be "
1328 "deleted and that it will be possible to use it later again.</p>");
1329 break;
1330 }
1331 default:
1332 break;
1333 }
1334 /* Show the question: */
1335 return questionBinary(pParent, MessageType_Question,
1336 strMessage.arg(medium.location()),
1337 0 /* auto-confirm id */,
1338 tr("Remove", "medium") /* ok button text */,
1339 QString() /* cancel button text */,
1340 false /* ok button by default? */);
1341}
1342
1343int UIMessageCenter::confirmDeleteHardDiskStorage(const QString &strLocation, QWidget *pParent /* = 0*/) const
1344{
1345 return questionTrinary(pParent, MessageType_Question,
1346 tr("<p>Do you want to delete the storage unit of the virtual hard disk "
1347 "<nobr><b>%1</b></nobr>?</p>"
1348 "<p>If you select <b>Delete</b> then the specified storage unit "
1349 "will be permanently deleted. This operation <b>cannot be "
1350 "undone</b>.</p>"
1351 "<p>If you select <b>Keep</b> then the hard disk will be only "
1352 "removed from the list of known hard disks, but the storage unit "
1353 "will be left untouched which makes it possible to add this hard "
1354 "disk to the list later again.</p>")
1355 .arg(strLocation),
1356 0 /* auto-confirm id */,
1357 tr("Delete", "hard disk storage"),
1358 tr("Keep", "hard disk storage"));
1359}
1360
1361bool UIMessageCenter::confirmInaccesibleMediaClear(const QStringList &mediaNameList, UIMediumDeviceType enmType, QWidget *pParent /* = 0 */)
1362{
1363 if (mediaNameList.isEmpty())
1364 return false;
1365
1366 if (enmType != UIMediumDeviceType_DVD && enmType != UIMediumDeviceType_Floppy)
1367 return false;
1368
1369 QString strDetails("<!--EOM-->");
1370 QString strDetailMessage;
1371
1372 if (enmType == UIMediumDeviceType_DVD)
1373 strDetailMessage = tr("The list of inaccessible DVDs is as follows:");
1374 else
1375 strDetailMessage = tr("The list of inaccessible floppy disks is as follows:");
1376
1377
1378 if (!strDetailMessage.isEmpty())
1379 strDetails.prepend(QString("<p>%1.</p>").arg(UITranslator::emphasize(strDetailMessage)));
1380
1381 strDetails += QString("<table bgcolor=%1 border=0 cellspacing=5 cellpadding=0 width=100%>")
1382 .arg(QApplication::palette().color(QPalette::Active, QPalette::Window).name(QColor::HexRgb));
1383 foreach (const QString &strDVD, mediaNameList)
1384 strDetails += QString("<tr><td>%1</td></tr>").arg(strDVD);
1385 strDetails += QString("</table>");
1386
1387 if (!strDetails.isEmpty())
1388 strDetails = "<qt>" + strDetails + "</qt>";
1389
1390 if (enmType == UIMediumDeviceType_DVD)
1391 return message(pParent,
1392 MessageType_Question,
1393 tr("<p>This will clear the optical disk list by releasing inaccessible DVDs"
1394 " from the virtual machines they are attached to"
1395 " and removing them from the list of registered media.<p>"
1396 "Are you sure?"),
1397 strDetails,
1398 0 /* auto-confirm id */,
1399 AlertButton_Ok,
1400 AlertButton_Cancel | AlertButtonOption_Default | AlertButtonOption_Escape,
1401 0 /* third button */,
1402 tr("Clear") /* ok button text */,
1403 QString() /* cancel button text */,
1404 QString() /* 3rd button text */,
1405 QString() /* help keyword */);
1406 else
1407 return message(pParent,
1408 MessageType_Question,
1409 tr("<p>This will clear the floppy disk list by releasing inaccessible disks"
1410 " from the virtual machines they are attached to"
1411 " and removing them from the list of registered media.<p>"
1412 "Are you sure?"),
1413 strDetails,
1414 0 /* auto-confirm id */,
1415 AlertButton_Ok,
1416 AlertButton_Cancel | AlertButtonOption_Default | AlertButtonOption_Escape,
1417 0 /* third button */,
1418 tr("Clear") /* ok button text */,
1419 QString() /* cancel button text */,
1420 QString() /* 3rd button text */,
1421 QString() /* help keyword */);
1422}
1423
1424bool UIMessageCenter::confirmVisoDiscard(QWidget *pParent /* = 0*/) const
1425{
1426 return questionBinary(pParent, MessageType_Question,
1427 tr("<p>To open a VISO file you will have to discard the current content.</p>"
1428 "<p>Are you sure you want to proceed?</p>"),
1429 0 /* auto-confirm id */,
1430 tr("Discard") /* ok button text */,
1431 QString() /* cancel button text */,
1432 false /* ok button by default? */);
1433}
1434
1435bool UIMessageCenter::confirmCloudNetworkRemoval(const QString &strName, QWidget *pParent /* = 0*/) const
1436{
1437 return questionBinary(pParent, MessageType_Question,
1438 tr("<p>Do you want to remove the cloud network <nobr><b>%1</b>?</nobr></p>"
1439 "<p>If this network is in use by one or more virtual "
1440 "machine network adapters these adapters will no longer be "
1441 "usable until you correct their settings by either choosing "
1442 "a different network name or a different adapter attachment "
1443 "type.</p>")
1444 .arg(strName),
1445 0 /* auto-confirm id */,
1446 tr("Remove") /* ok button text */,
1447 QString() /* cancel button text */,
1448 false /* ok button by default? */);
1449}
1450
1451bool UIMessageCenter::confirmHostNetworkInterfaceRemoval(const QString &strName, QWidget *pParent /* = 0 */) const
1452{
1453 return questionBinary(pParent, MessageType_Question,
1454 tr("<p>Deleting this host-only network will remove "
1455 "the host-only interface this network is based on. Do you want to "
1456 "remove the (host-only network) interface <nobr><b>%1</b>?</nobr></p>"
1457 "<p><b>Note:</b> this interface may be in use by one or more "
1458 "virtual network adapters belonging to one of your VMs. "
1459 "After it is removed, these adapters will no longer be usable until "
1460 "you correct their settings by either choosing a different interface "
1461 "name or a different adapter attachment type.</p>")
1462 .arg(strName),
1463 0 /* auto-confirm id */,
1464 tr("Remove") /* ok button text */,
1465 QString() /* cancel button text */,
1466 false /* ok button by default? */);
1467}
1468
1469bool UIMessageCenter::confirmHostOnlyNetworkRemoval(const QString &strName, QWidget *pParent /* = 0 */) const
1470{
1471 return questionBinary(pParent, MessageType_Question,
1472 tr("<p>Do you want to remove the host-only network <nobr><b>%1</b>?</nobr></p>"
1473 "<p>If this network is in use by one or more virtual "
1474 "machine network adapters these adapters will no longer be "
1475 "usable until you correct their settings by either choosing "
1476 "a different network name or a different adapter attachment "
1477 "type.</p>")
1478 .arg(strName),
1479 0 /* auto-confirm id */,
1480 tr("Remove") /* ok button text */,
1481 QString() /* cancel button text */,
1482 false /* ok button by default? */);
1483}
1484
1485bool UIMessageCenter::confirmNATNetworkRemoval(const QString &strName, QWidget *pParent /* = 0*/) const
1486{
1487 return questionBinary(pParent, MessageType_Question,
1488 tr("<p>Do you want to remove the NAT network <nobr><b>%1</b>?</nobr></p>"
1489 "<p>If this network is in use by one or more virtual "
1490 "machine network adapters these adapters will no longer be "
1491 "usable until you correct their settings by either choosing "
1492 "a different network name or a different adapter attachment "
1493 "type.</p>")
1494 .arg(strName),
1495 0 /* auto-confirm id */,
1496 tr("Remove") /* ok button text */,
1497 QString() /* cancel button text */,
1498 false /* ok button by default? */);
1499}
1500
1501bool UIMessageCenter::confirmCloudProfileRemoval(const QString &strName, QWidget *pParent /* = 0 */) const
1502{
1503 return questionBinary(pParent, MessageType_Question,
1504 tr("<p>Do you want to remove the cloud profile <nobr><b>%1</b>?</nobr></p>")
1505 .arg(strName),
1506 0 /* auto-confirm id */,
1507 tr("Remove") /* ok button text */,
1508 QString() /* cancel button text */,
1509 false /* ok button by default? */);
1510}
1511
1512bool UIMessageCenter::confirmCloudProfilesImport(QWidget *pParent /* = 0 */) const
1513{
1514 return questionBinary(pParent, MessageType_Question,
1515 tr("<p>Do you want to import cloud profiles from external files?</p>"
1516 "<p>VirtualBox cloud profiles will be overwritten and their data will be lost.</p>"),
1517 0 /* auto-confirm id */,
1518 tr("Import") /* ok button text */,
1519 QString() /* cancel button text */,
1520 false /* ok button by default? */);
1521}
1522
1523int UIMessageCenter::confirmCloudProfileManagerClosing(QWidget *pParent /* = 0 */) const
1524{
1525 return question(pParent, MessageType_Question,
1526 tr("<p>Do you want to close the Cloud Profile Manager?</p>"
1527 "<p>There seems to be an unsaved changes. "
1528 "You can choose to <b>Accept</b> or <b>Reject</b> them automatically "
1529 "or cancel to keep the dialog opened.</p>"),
1530 0 /* auto-confirm id */,
1531 AlertButton_Choice1,
1532 AlertButton_Choice2,
1533 AlertButton_Cancel | AlertButtonOption_Default | AlertButtonOption_Escape,
1534 tr("Accept", "cloud profile manager changes"),
1535 tr("Reject", "cloud profile manager changes"));
1536}
1537
1538bool UIMessageCenter::confirmCloudConsoleApplicationRemoval(const QString &strName, QWidget *pParent /* = 0 */) const
1539{
1540 return questionBinary(pParent, MessageType_Question,
1541 tr("<p>Do you want to remove the cloud console application <nobr><b>%1</b>?</nobr></p>")
1542 .arg(strName),
1543 0 /* auto-confirm id */,
1544 tr("Remove") /* ok button text */,
1545 QString() /* cancel button text */,
1546 false /* ok button by default? */);
1547}
1548
1549bool UIMessageCenter::confirmCloudConsoleProfileRemoval(const QString &strName, QWidget *pParent /* = 0 */) const
1550{
1551 return questionBinary(pParent, MessageType_Question,
1552 tr("<p>Do you want to remove the cloud console profile <nobr><b>%1</b>?</nobr></p>")
1553 .arg(strName),
1554 0 /* auto-confirm id */,
1555 tr("Remove") /* ok button text */,
1556 QString() /* cancel button text */,
1557 false /* ok button by default? */);
1558}
1559
1560#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
1561bool UIMessageCenter::confirmLookingForGuestAdditions() const
1562{
1563 return questionBinary(0, MessageType_Question,
1564 tr("<p>Could not find the <b>VirtualBox Guest Additions</b> disk image file.</p>"
1565 "<p>Do you wish to download this disk image file from the Internet?</p>"),
1566 0 /* auto-confirm id */,
1567 tr("Download"));
1568}
1569
1570bool UIMessageCenter::confirmDownloadGuestAdditions(const QString &strUrl, qulonglong uSize) const
1571{
1572 return questionBinary(windowManager().mainWindowShown(), MessageType_Question,
1573 tr("<p>Are you sure you want to download the <b>VirtualBox Guest Additions</b> disk image file "
1574 "from <nobr><a href=\"%1\">%1</a></nobr> (size %2 bytes)?</p>")
1575 .arg(strUrl, QLocale(UITranslator::languageId()).toString(uSize)),
1576 0 /* auto-confirm id */,
1577 tr("Download"));
1578}
1579
1580void UIMessageCenter::cannotSaveGuestAdditions(const QString &strURL, const QString &strTarget) const
1581{
1582 alert(windowManager().mainWindowShown(), MessageType_Error,
1583 tr("<p>The <b>VirtualBox Guest Additions</b> disk image file has been successfully downloaded "
1584 "from <nobr><a href=\"%1\">%1</a></nobr> "
1585 "but can't be saved locally as <nobr><b>%2</b>.</nobr></p>"
1586 "<p>Please choose another location for that file.</p>")
1587 .arg(strURL, strTarget));
1588}
1589
1590bool UIMessageCenter::proposeMountGuestAdditions(const QString &strUrl, const QString &strSrc) const
1591{
1592 return questionBinary(windowManager().mainWindowShown(), MessageType_Question,
1593 tr("<p>The <b>VirtualBox Guest Additions</b> disk image file has been successfully downloaded "
1594 "from <nobr><a href=\"%1\">%1</a></nobr> "
1595 "and saved locally as <nobr><b>%2</b>.</nobr></p>"
1596 "<p>Do you wish to continue with Guest Additions installation?</p>")
1597 .arg(strUrl, strSrc),
1598 0 /* auto-confirm id */,
1599 tr("Continue", "agree with additions installation"));
1600}
1601
1602bool UIMessageCenter::confirmLookingForUserManual(const QString &strMissedLocation) const
1603{
1604 return questionBinary(0, MessageType_Question,
1605 tr("<p>Could not find the <b>VirtualBox User Guide</b> <nobr><b>%1</b>.</nobr></p>"
1606 "<p>Do you wish to download this file from the Internet?</p>")
1607 .arg(strMissedLocation),
1608 0 /* auto-confirm id */,
1609 tr("Download"));
1610}
1611
1612bool UIMessageCenter::confirmDownloadUserManual(const QString &strURL, qulonglong uSize) const
1613{
1614 return questionBinary(windowManager().mainWindowShown(), MessageType_Question,
1615 tr("<p>Are you sure you want to download the <b>VirtualBox User Guide</b> "
1616 "from <nobr><a href=\"%1\">%1</a></nobr> (size %2 bytes)?</p>")
1617 .arg(strURL, QLocale(UITranslator::languageId()).toString(uSize)),
1618 0 /* auto-confirm id */,
1619 tr("Download"));
1620}
1621
1622void UIMessageCenter::cannotSaveUserManual(const QString &strURL, const QString &strTarget) const
1623{
1624 alert(windowManager().mainWindowShown(), MessageType_Error,
1625 tr("<p>The VirtualBox User Guide has been successfully downloaded "
1626 "from <nobr><a href=\"%1\">%1</a></nobr> "
1627 "but can't be saved locally as <nobr><b>%2</b>.</nobr></p>"
1628 "<p>Please choose another location for that file.</p>")
1629 .arg(strURL, strTarget));
1630}
1631
1632bool UIMessageCenter::confirmLookingForExtensionPack(const QString &strExtPackName, const QString &strExtPackVersion) const
1633{
1634 return questionBinary(windowManager().mainWindowShown(), MessageType_Question,
1635 tr("<p>You have an old version (%1) of the <b><nobr>%2</nobr></b> installed.</p>"
1636 "<p>Do you wish to download latest one from the Internet?</p>")
1637 .arg(strExtPackVersion).arg(strExtPackName),
1638 0 /* auto-confirm id */,
1639 tr("Download"));
1640}
1641
1642bool UIMessageCenter::confirmDownloadExtensionPack(const QString &strExtPackName, const QString &strURL, qulonglong uSize) const
1643{
1644 return questionBinary(windowManager().mainWindowShown(), MessageType_Question,
1645 tr("<p>Are you sure you want to download the <b><nobr>%1</nobr></b> "
1646 "from <nobr><a href=\"%2\">%2</a></nobr> (size %3 bytes)?</p>")
1647 .arg(strExtPackName, strURL, QLocale(UITranslator::languageId()).toString(uSize)),
1648 0 /* auto-confirm id */,
1649 tr("Download"));
1650}
1651
1652void UIMessageCenter::cannotSaveExtensionPack(const QString &strExtPackName, const QString &strFrom, const QString &strTo) const
1653{
1654 alert(windowManager().mainWindowShown(), MessageType_Error,
1655 tr("<p>The <b><nobr>%1</nobr></b> has been successfully downloaded "
1656 "from <nobr><a href=\"%2\">%2</a></nobr> "
1657 "but can't be saved locally as <nobr><b>%3</b>.</nobr></p>"
1658 "<p>Please choose another location for that file.</p>")
1659 .arg(strExtPackName, strFrom, strTo));
1660}
1661
1662bool UIMessageCenter::proposeInstallExtentionPack(const QString &strExtPackName, const QString &strFrom, const QString &strTo) const
1663{
1664 return questionBinary(windowManager().mainWindowShown(), MessageType_Question,
1665 tr("<p>The <b><nobr>%1</nobr></b> has been successfully downloaded "
1666 "from <nobr><a href=\"%2\">%2</a></nobr> "
1667 "and saved locally as <nobr><b>%3</b>.</nobr></p>"
1668 "<p>Do you wish to install this extension pack?</p>")
1669 .arg(strExtPackName, strFrom, strTo),
1670 0 /* auto-confirm id */,
1671 tr("Install", "extension pack"));
1672}
1673
1674bool UIMessageCenter::proposeDeleteExtentionPack(const QString &strTo) const
1675{
1676 return questionBinary(windowManager().mainWindowShown(), MessageType_Question,
1677 tr("Do you want to delete the downloaded file <nobr><b>%1</b></nobr>?")
1678 .arg(strTo),
1679 0 /* auto-confirm id */,
1680 tr("Delete", "extension pack"));
1681}
1682
1683bool UIMessageCenter::proposeDeleteOldExtentionPacks(const QStringList &strFiles) const
1684{
1685 return questionBinary(windowManager().mainWindowShown(), MessageType_Question,
1686 tr("Do you want to delete following list of files <nobr><b>%1</b></nobr>?")
1687 .arg(strFiles.join(",")),
1688 0 /* auto-confirm id */,
1689 tr("Delete", "extension pack"));
1690}
1691#endif /* VBOX_GUI_WITH_NETWORK_MANAGER */
1692
1693bool UIMessageCenter::cannotRestoreSnapshot(const CMachine &machine, const QString &strSnapshotName, const QString &strMachineName) const
1694{
1695 error(0, MessageType_Error,
1696 tr("Failed to restore the snapshot <b>%1</b> of the virtual machine <b>%2</b>.")
1697 .arg(strSnapshotName, strMachineName),
1698 UIErrorString::formatErrorInfo(machine));
1699 return false;
1700}
1701
1702bool UIMessageCenter::cannotRestoreSnapshot(const CProgress &progress, const QString &strSnapshotName, const QString &strMachineName) const
1703{
1704 error(0, MessageType_Error,
1705 tr("Failed to restore the snapshot <b>%1</b> of the virtual machine <b>%2</b>.")
1706 .arg(strSnapshotName, strMachineName),
1707 UIErrorString::formatErrorInfo(progress));
1708 return false;
1709}
1710
1711void UIMessageCenter::cannotStartMachine(const CConsole &console, const QString &strName) const
1712{
1713 error(0, MessageType_Error,
1714 tr("Failed to start the virtual machine <b>%1</b>.")
1715 .arg(strName),
1716 UIErrorString::formatErrorInfo(console));
1717}
1718
1719void UIMessageCenter::cannotStartMachine(const CProgress &progress, const QString &strName) const
1720{
1721 error(0, MessageType_Error,
1722 tr("Failed to start the virtual machine <b>%1</b>.")
1723 .arg(strName),
1724 UIErrorString::formatErrorInfo(progress));
1725}
1726
1727bool UIMessageCenter::warnAboutNetworkInterfaceNotFound(const QString &strMachineName, const QString &strIfNames) const
1728{
1729 return questionBinary(0, MessageType_Error,
1730 tr("<p>Could not start the machine <b>%1</b> because the following "
1731 "physical network interfaces were not found:</p><p><b>%2</b></p>"
1732 "<p>You can either change the machine's network settings or stop the machine.</p>")
1733 .arg(strMachineName, strIfNames),
1734 0 /* auto-confirm id */,
1735 tr("Change Network Settings"), tr("Close VM"));
1736}
1737
1738void UIMessageCenter::warnAboutVBoxSVCUnavailable() const
1739{
1740 alert(0, MessageType_Critical,
1741 tr("<p>A critical error has occurred while running the virtual "
1742 "machine and the machine execution should be stopped.</p>"
1743 ""
1744 "<p>For help, please see the Community section on "
1745 "<a href=https://www.virtualbox.org>https://www.virtualbox.org</a> "
1746 "or your support contract. Please provide the contents of the "
1747 "log file <tt>VBox.log</tt>, "
1748 "which you can find in the virtual machine log directory, "
1749 "as well as a description of what you were doing when this error happened. "
1750 ""
1751 "Note that you can also access the above file by selecting <b>Show Log</b> "
1752 "from the <b>Machine</b> menu of the main VirtualBox window.</p>"
1753 ""
1754 "<p>Press <b>OK</b> to power off the machine.</p>"),
1755 0 /* auto-confirm id */);
1756}
1757
1758bool UIMessageCenter::warnAboutGuruMeditation(const QString &strLogFolder)
1759{
1760 return questionBinary(0, MessageType_GuruMeditation,
1761 tr("<p>A critical error has occurred while running the virtual "
1762 "machine and the machine execution has been stopped.</p>"
1763 ""
1764 "<p>For help, please see the Community section on "
1765 "<a href=https://www.virtualbox.org>https://www.virtualbox.org</a> "
1766 "or your support contract. Please provide the contents of the "
1767 "log file <tt>VBox.log</tt> and the image file <tt>VBox.png</tt>, "
1768 "which you can find in the <nobr><b>%1</b></nobr> directory, "
1769 "as well as a description of what you were doing when this error happened. "
1770 ""
1771 "Note that you can also access the above files by selecting <b>Show Log</b> "
1772 "from the <b>Machine</b> menu of the main VirtualBox window.</p>"
1773 ""
1774 "<p>Press <b>OK</b> if you want to power off the machine "
1775 "or press <b>Ignore</b> if you want to leave it as is for debugging. "
1776 "Please note that debugging requires special knowledge and tools, "
1777 "so it is recommended to press <b>OK</b> now.</p>")
1778 .arg(strLogFolder),
1779 0 /* auto-confirm id */,
1780 QIMessageBox::tr("OK"),
1781 tr("Ignore"));
1782}
1783
1784void UIMessageCenter::showRuntimeError(MessageType emnMessageType, const QString &strErrorId, const QString &strErrorMsg) const
1785{
1786 /* Gather suitable severity and confirm id: */
1787 QString strSeverity;
1788 QByteArray autoConfimId = "showRuntimeError.";
1789 switch (emnMessageType)
1790 {
1791 case MessageType_Warning:
1792 {
1793 strSeverity = tr("<nobr>Warning</nobr>", "runtime error info");
1794 autoConfimId += "warning.";
1795 break;
1796 }
1797 case MessageType_Error:
1798 {
1799 strSeverity = tr("<nobr>Non-Fatal Error</nobr>", "runtime error info");
1800 autoConfimId += "error.";
1801 break;
1802 }
1803 case MessageType_Critical:
1804 {
1805 strSeverity = tr("<nobr>Fatal Error</nobr>", "runtime error info");
1806 autoConfimId += "fatal.";
1807 break;
1808 }
1809 default:
1810 break;
1811 }
1812 autoConfimId += strErrorId.toUtf8();
1813
1814 /* Format error-details: */
1815 QString formatted("<!--EOM-->");
1816 if (!strErrorMsg.isEmpty())
1817 formatted.prepend(QString("<p>%1.</p>").arg(UITranslator::emphasize(strErrorMsg)));
1818 if (!strErrorId.isEmpty())
1819 formatted += QString("<table bgcolor=%1 border=0 cellspacing=5 "
1820 "cellpadding=0 width=100%>"
1821 "<tr><td>%2</td><td>%3</td></tr>"
1822 "<tr><td>%4</td><td>%5</td></tr>"
1823 "</table>")
1824 .arg(QApplication::palette().color(QPalette::Active, QPalette::Window).name(QColor::HexRgb))
1825 .arg(tr("<nobr>Error ID:</nobr>", "runtime error info"), strErrorId)
1826 .arg(tr("Severity:", "runtime error info"), strSeverity);
1827 if (!formatted.isEmpty())
1828 formatted = "<qt>" + formatted + "</qt>";
1829
1830 /* Show the error: */
1831 switch (emnMessageType)
1832 {
1833 case MessageType_Warning:
1834 {
1835 /** @todo r=bird: This is a very annoying message as it refers to invisible text
1836 * below. User have to expand "Details" to see what actually went wrong.
1837 * Probably a good idea to check strErrorId and see if we can come up with better
1838 * messages here, at least for common stuff like DvdOrFloppyImageInaccesssible... */
1839 error(0, emnMessageType,
1840 tr("<p>The virtual machine execution ran into a non-fatal problem as described below. "
1841 "We suggest that you take appropriate action to prevent the problem from recurring.</p>"),
1842 formatted, autoConfimId.data());
1843 break;
1844 }
1845 case MessageType_Error:
1846 {
1847 error(0, emnMessageType,
1848 tr("<p>An error has occurred during virtual machine execution! "
1849 "The error details are shown below. You may try to correct the error "
1850 "and resume the virtual machine execution.</p>"),
1851 formatted, autoConfimId.data());
1852 break;
1853 }
1854 case MessageType_Critical:
1855 {
1856 error(0, emnMessageType,
1857 tr("<p>A fatal error has occurred during virtual machine execution! "
1858 "The virtual machine will be powered off. Please copy the following error message "
1859 "using the clipboard to help diagnose the problem:</p>"),
1860 formatted, autoConfimId.data());
1861 break;
1862 }
1863 default:
1864 break;
1865 }
1866}
1867
1868bool UIMessageCenter::confirmInputCapture(bool &fAutoConfirmed) const
1869{
1870 int rc = question(0, MessageType_Info,
1871 tr("<p>You have <b>clicked the mouse</b> inside the Virtual Machine display or pressed the <b>host key combo</b>. "
1872 "This will cause the Virtual Machine to <b>capture</b> the host mouse pointer (only if the mouse pointer "
1873 "integration is not currently supported by the guest OS) and the keyboard, which will make them "
1874 "unavailable to other applications running on your host machine.</p>"
1875 "<p>You can press the <b>host key combo</b> at any time to <b>uncapture</b> the keyboard and mouse "
1876 "(if it is captured) and return them to normal operation. "
1877 "The currently assigned host key combo is shown on the status bar at the bottom of the Virtual Machine window, "
1878 "next to the&nbsp;<img src=:/hostkey_16px.png/>&nbsp;icon. "
1879 "This icon, together with the mouse icon placed nearby, indicate the current keyboard and mouse capture state.</p>") +
1880 tr("<p>The host key combo is currently defined as <b>%1</b>.</p>", "additional message box paragraph")
1881 .arg(UIHostCombo::toReadableString(gEDataManager->hostKeyCombination())),
1882 "confirmInputCapture",
1883 AlertButton_Ok | AlertButtonOption_Default,
1884 AlertButton_Cancel | AlertButtonOption_Escape,
1885 0,
1886 tr("Capture", "do input capture"));
1887 /* Was the message auto-confirmed? */
1888 fAutoConfirmed = (rc & AlertOption_AutoConfirmed);
1889 /* True if "Ok" was pressed: */
1890 return (rc & AlertButtonMask) == AlertButton_Ok;
1891}
1892
1893bool UIMessageCenter::confirmGoingFullscreen(const QString &strHotKey) const
1894{
1895 return questionBinary(0, MessageType_Info,
1896 tr("<p>The virtual machine window will be now switched to <b>full-screen</b> mode. "
1897 "You can go back to windowed mode at any time by pressing <b>%1</b>.</p>"
1898 "<p>Note that the <i>Host</i> key is currently defined as <b>%2</b>.</p>"
1899 "<p>Note that the main menu bar is hidden in full-screen mode. "
1900 "You can access it by pressing <b>Host+Home</b>.</p>")
1901 .arg(strHotKey, UIHostCombo::toReadableString(gEDataManager->hostKeyCombination())),
1902 "confirmGoingFullscreen",
1903 tr("Switch"));
1904}
1905
1906bool UIMessageCenter::confirmGoingSeamless(const QString &strHotKey) const
1907{
1908 return questionBinary(0, MessageType_Info,
1909 tr("<p>The virtual machine window will be now switched to <b>Seamless</b> mode. "
1910 "You can go back to windowed mode at any time by pressing <b>%1</b>.</p>"
1911 "<p>Note that the <i>Host</i> key is currently defined as <b>%2</b>.</p>"
1912 "<p>Note that the main menu bar is hidden in seamless mode. "
1913 "You can access it by pressing <b>Host+Home</b>.</p>")
1914 .arg(strHotKey, UIHostCombo::toReadableString(gEDataManager->hostKeyCombination())),
1915 "confirmGoingSeamless",
1916 tr("Switch"));
1917}
1918
1919bool UIMessageCenter::confirmGoingScale(const QString &strHotKey) const
1920{
1921 return questionBinary(0, MessageType_Info,
1922 tr("<p>The virtual machine window will be now switched to <b>Scale</b> mode. "
1923 "You can go back to windowed mode at any time by pressing <b>%1</b>.</p>"
1924 "<p>Note that the <i>Host</i> key is currently defined as <b>%2</b>.</p>"
1925 "<p>Note that the main menu bar is hidden in scaled mode. "
1926 "You can access it by pressing <b>Host+Home</b>.</p>")
1927 .arg(strHotKey, UIHostCombo::toReadableString(gEDataManager->hostKeyCombination())),
1928 "confirmGoingScale",
1929 tr("Switch"));
1930}
1931
1932bool UIMessageCenter::cannotEnterFullscreenMode(ULONG /* uWidth */, ULONG /* uHeight */, ULONG /* uBpp */, ULONG64 uMinVRAM) const
1933{
1934 return questionBinary(0, MessageType_Warning,
1935 tr("<p>Could not switch the guest display to full-screen mode due to insufficient guest video memory.</p>"
1936 "<p>You should configure the virtual machine to have at least <b>%1</b> of video memory.</p>"
1937 "<p>Press <b>Ignore</b> to switch to full-screen mode anyway or press <b>Cancel</b> to cancel the operation.</p>")
1938 .arg(UITranslator::formatSize(uMinVRAM)),
1939 0 /* auto-confirm id */,
1940 tr("Ignore"));
1941}
1942
1943void UIMessageCenter::cannotEnterSeamlessMode(ULONG /* uWidth */, ULONG /* uHeight */, ULONG /* uBpp */, ULONG64 uMinVRAM) const
1944{
1945 alert(0, MessageType_Error,
1946 tr("<p>Could not enter seamless mode due to insufficient guest "
1947 "video memory.</p>"
1948 "<p>You should configure the virtual machine to have at "
1949 "least <b>%1</b> of video memory.</p>")
1950 .arg(UITranslator::formatSize(uMinVRAM)));
1951}
1952
1953bool UIMessageCenter::cannotSwitchScreenInFullscreen(quint64 uMinVRAM) const
1954{
1955 return questionBinary(0, MessageType_Warning,
1956 tr("<p>Could not change the guest screen to this host screen due to insufficient guest video memory.</p>"
1957 "<p>You should configure the virtual machine to have at least <b>%1</b> of video memory.</p>"
1958 "<p>Press <b>Ignore</b> to switch the screen anyway or press <b>Cancel</b> to cancel the operation.</p>")
1959 .arg(UITranslator::formatSize(uMinVRAM)),
1960 0 /* auto-confirm id */,
1961 tr("Ignore"));
1962}
1963
1964void UIMessageCenter::cannotSwitchScreenInSeamless(quint64 uMinVRAM) const
1965{
1966 alert(0, MessageType_Error,
1967 tr("<p>Could not change the guest screen to this host screen "
1968 "due to insufficient guest video memory.</p>"
1969 "<p>You should configure the virtual machine to have at "
1970 "least <b>%1</b> of video memory.</p>")
1971 .arg(UITranslator::formatSize(uMinVRAM)));
1972}
1973
1974#ifdef VBOX_WITH_DRAG_AND_DROP
1975void UIMessageCenter::cannotDropDataToGuest(const CDnDTarget &dndTarget, QWidget *pParent /* = 0 */) const
1976{
1977 error(pParent, MessageType_Error,
1978 tr("Drag and drop operation from host to guest failed."),
1979 UIErrorString::formatErrorInfo(dndTarget));
1980}
1981
1982void UIMessageCenter::cannotDropDataToGuest(const CProgress &progress, QWidget *pParent /* = 0 */) const
1983{
1984 error(pParent, MessageType_Error,
1985 tr("Drag and drop operation from host to guest failed."),
1986 UIErrorString::formatErrorInfo(progress));
1987}
1988
1989void UIMessageCenter::cannotDropDataToHost(const CDnDSource &dndSource, QWidget *pParent /* = 0 */) const
1990{
1991 error(pParent, MessageType_Error,
1992 tr("Drag and drop operation from guest to host failed."),
1993 UIErrorString::formatErrorInfo(dndSource));
1994}
1995
1996void UIMessageCenter::cannotDropDataToHost(const CProgress &progress, QWidget *pParent /* = 0 */) const
1997{
1998 error(pParent, MessageType_Error,
1999 tr("Drag and drop operation from guest to host failed."),
2000 UIErrorString::formatErrorInfo(progress));
2001}
2002#endif /* VBOX_WITH_DRAG_AND_DROP */
2003
2004bool UIMessageCenter::confirmHardDisklessMachine(QWidget *pParent /* = 0*/) const
2005{
2006 return questionBinary(pParent, MessageType_Warning,
2007 tr("You are about to create a new virtual machine without a hard disk. "
2008 "You will not be able to install an operating system on the machine "
2009 "until you add one. In the mean time you will only be able to start the "
2010 "machine using a virtual optical disk or from the network."),
2011 0 /* auto-confirm id */,
2012 tr("Continue", "agree to create VM with no hard disk attached"),
2013 tr("Go Back", "reject to create VM with no hard disk attached"));
2014}
2015
2016bool UIMessageCenter::confirmExportMachinesInSaveState(const QStringList &machineNames, QWidget *pParent /* = 0*/) const
2017{
2018 return questionBinary(pParent, MessageType_Warning,
2019 tr("<p>The %n following virtual machine(s) are currently in a saved state: <b>%1</b></p>"
2020 "<p>If you continue the runtime state of the exported machine(s) will be discarded. "
2021 "The other machine(s) will not be changed.</p>",
2022 "This text is never used with n == 0. Feel free to drop the %n where possible, "
2023 "we only included it because of problems with Qt Linguist (but the user can see "
2024 "how many machines are in the list and doesn't need to be told).", machineNames.size())
2025 .arg(machineNames.join(", ")),
2026 0 /* auto-confirm id */,
2027 tr("Continue", "agree to export VMs without saved-state"));
2028}
2029
2030bool UIMessageCenter::confirmOverridingFile(const QString &strPath, QWidget *pParent /* = 0*/) const
2031{
2032 return questionBinary(pParent, MessageType_Question,
2033 tr("A file named <b>%1</b> already exists. "
2034 "Are you sure you want to replace it?<br /><br />"
2035 "Replacing it will overwrite its contents.")
2036 .arg(strPath),
2037 0 /* auto-confirm id */,
2038 QString() /* ok button text */,
2039 QString() /* cancel button text */,
2040 false /* ok button by default? */);
2041}
2042
2043bool UIMessageCenter::confirmOverridingFiles(const QVector<QString> &strPaths, QWidget *pParent /* = 0*/) const
2044{
2045 /* If it is only one file use the single question versions above: */
2046 if (strPaths.size() == 1)
2047 return confirmOverridingFile(strPaths.at(0), pParent);
2048 else if (strPaths.size() > 1)
2049 return questionBinary(pParent, MessageType_Question,
2050 tr("The following files already exist:<br /><br />%1<br /><br />"
2051 "Are you sure you want to replace them? "
2052 "Replacing them will overwrite their contents.")
2053 .arg(QStringList(strPaths.toList()).join("<br />")),
2054 0 /* auto-confirm id */,
2055 QString() /* ok button text */,
2056 QString() /* cancel button text */,
2057 false /* ok button by default? */);
2058 else
2059 return true;
2060}
2061
2062void UIMessageCenter::cannotCreateMediumStorage(const CVirtualBox &comVBox, const QString &strLocation, QWidget *pParent /* = 0 */) const
2063{
2064 error(pParent, MessageType_Error,
2065 tr("Failed to create the virtual disk image storage <nobr><b>%1</b>.</nobr>")
2066 .arg(strLocation),
2067 UIErrorString::formatErrorInfo(comVBox));
2068}
2069
2070void UIMessageCenter::sltShowHelpWebDialog()
2071{
2072 uiCommon().openURL("https://www.virtualbox.org");
2073}
2074
2075void UIMessageCenter::sltShowBugTracker()
2076{
2077 uiCommon().openURL("https://www.virtualbox.org/wiki/Bugtracker");
2078}
2079
2080void UIMessageCenter::sltShowForums()
2081{
2082 uiCommon().openURL("https://forums.virtualbox.org/");
2083}
2084
2085void UIMessageCenter::sltShowOracle()
2086{
2087 uiCommon().openURL("https://www.oracle.com/us/technologies/virtualization/virtualbox/overview/index.html");
2088}
2089
2090void UIMessageCenter::sltShowOnlineDocumentation()
2091{
2092 uiCommon().openURL("https://docs.oracle.com/en/virtualization/virtualbox/7.0/user/index.html");
2093}
2094
2095void UIMessageCenter::sltShowHelpAboutDialog()
2096{
2097 CVirtualBox vbox = gpGlobalSession->virtualBox();
2098 const QString strFullVersion = UIVersionInfo::brandingIsActive()
2099 ? QString("%1 r%2 - %3").arg(vbox.GetVersion())
2100 .arg(vbox.GetRevision())
2101 .arg(UIVersionInfo::brandingGetKey("Name"))
2102 : QString("%1 r%2").arg(vbox.GetVersion())
2103 .arg(vbox.GetRevision());
2104 (new VBoxAboutDlg(windowManager().mainWindowShown(), strFullVersion))->show();
2105}
2106
2107void UIMessageCenter::sltResetSuppressedMessages()
2108{
2109 /* Nullify suppressed message list: */
2110 gEDataManager->setSuppressedMessages(QStringList());
2111}
2112
2113void UIMessageCenter::sltShowMessageBox(QWidget *pParent, MessageType enmType,
2114 const QString &strMessage, const QString &strDetails,
2115 int iButton1, int iButton2, int iButton3,
2116 const QString &strButtonText1, const QString &strButtonText2, const QString &strButtonText3,
2117 const QString &strAutoConfirmId, const QString &strHelpKeyword) const
2118{
2119 /* Now we can show a message-box directly: */
2120 showMessageBox(pParent, enmType,
2121 strMessage, strDetails,
2122 iButton1, iButton2, iButton3,
2123 strButtonText1, strButtonText2, strButtonText3,
2124 strAutoConfirmId, strHelpKeyword);
2125}
2126
2127UIMessageCenter::UIMessageCenter()
2128{
2129 /* Assign instance: */
2130 s_pInstance = this;
2131}
2132
2133UIMessageCenter::~UIMessageCenter()
2134{
2135 /* Unassign instance: */
2136 s_pInstance = 0;
2137}
2138
2139void UIMessageCenter::prepare()
2140{
2141 /* Register required objects as meta-types: */
2142 qRegisterMetaType<CProgress>();
2143 qRegisterMetaType<CHost>();
2144 qRegisterMetaType<CMachine>();
2145 qRegisterMetaType<CConsole>();
2146 qRegisterMetaType<CHostNetworkInterface>();
2147 qRegisterMetaType<UIMediumDeviceType>();
2148 qRegisterMetaType<StorageSlot>();
2149
2150 /* Prepare interthread connection: */
2151 qRegisterMetaType<MessageType>();
2152 // Won't go until we are supporting C++11 or at least variadic templates everywhere.
2153 // connect(this, &UIMessageCenter::sigToShowMessageBox,
2154 // this, &UIMessageCenter::sltShowMessageBox,
2155 connect(this, SIGNAL(sigToShowMessageBox(QWidget*, MessageType,
2156 const QString&, const QString&,
2157 int, int, int,
2158 const QString&, const QString&, const QString&,
2159 const QString&, const QString&)),
2160 this, SLOT(sltShowMessageBox(QWidget*, MessageType,
2161 const QString&, const QString&,
2162 int, int, int,
2163 const QString&, const QString&, const QString&,
2164 const QString&, const QString&)),
2165 Qt::BlockingQueuedConnection);
2166
2167 /* Translations for Main.
2168 * Please make sure they corresponds to the strings coming from Main one-by-one symbol! */
2169 tr("Could not load the Host USB Proxy Service (VERR_FILE_NOT_FOUND). The service might not be installed on the host computer");
2170 tr("VirtualBox is not currently allowed to access USB devices. You can change this by adding your user to the 'vboxusers' group. Please see the user guide for a more detailed explanation");
2171 tr("VirtualBox is not currently allowed to access USB devices. You can change this by allowing your user to access the 'usbfs' folder and files. Please see the user guide for a more detailed explanation");
2172 tr("The USB Proxy Service has not yet been ported to this host");
2173 tr("Could not load the Host USB Proxy service");
2174}
2175
2176void UIMessageCenter::cleanup()
2177{
2178 /* Nothing for now... */
2179}
2180
2181int UIMessageCenter::showMessageBox(QWidget *pParent, MessageType enmType,
2182 const QString &strMessage, const QString &strDetails,
2183 int iButton1, int iButton2, int iButton3,
2184 const QString &strButtonText1, const QString &strButtonText2, const QString &strButtonText3,
2185 const QString &strAutoConfirmId, const QString &strHelpKeyword) const
2186{
2187 /* Choose the 'default' button: */
2188 if (iButton1 == 0 && iButton2 == 0 && iButton3 == 0)
2189 iButton1 = AlertButton_Ok | AlertButtonOption_Default;
2190
2191 /* Check if message-box was auto-confirmed before: */
2192 QStringList confirmedMessageList;
2193 if (!strAutoConfirmId.isEmpty())
2194 {
2195 const QUuid uID = uiCommon().uiType() == UIType_RuntimeUI
2196 ? uiCommon().managedVMUuid()
2197 : UIExtraDataManager::GlobalID;
2198 confirmedMessageList = gEDataManager->suppressedMessages(uID);
2199 if ( confirmedMessageList.contains(strAutoConfirmId)
2200 || confirmedMessageList.contains("allMessageBoxes")
2201 || confirmedMessageList.contains("all") )
2202 {
2203 int iResultCode = AlertOption_AutoConfirmed;
2204 if (iButton1 & AlertButtonOption_Default)
2205 iResultCode |= (iButton1 & AlertButtonMask);
2206 if (iButton2 & AlertButtonOption_Default)
2207 iResultCode |= (iButton2 & AlertButtonMask);
2208 if (iButton3 & AlertButtonOption_Default)
2209 iResultCode |= (iButton3 & AlertButtonMask);
2210 return iResultCode;
2211 }
2212 }
2213
2214 /* Choose title and icon: */
2215 QString title;
2216 AlertIconType icon;
2217 switch (enmType)
2218 {
2219 default:
2220 case MessageType_Info:
2221 title = tr("VirtualBox - Information", "msg box title");
2222 icon = AlertIconType_Information;
2223 break;
2224 case MessageType_Question:
2225 title = tr("VirtualBox - Question", "msg box title");
2226 icon = AlertIconType_Question;
2227 break;
2228 case MessageType_Warning:
2229 title = tr("VirtualBox - Warning", "msg box title");
2230 icon = AlertIconType_Warning;
2231 break;
2232 case MessageType_Error:
2233 title = tr("VirtualBox - Error", "msg box title");
2234 icon = AlertIconType_Critical;
2235 break;
2236 case MessageType_Critical:
2237 title = tr("VirtualBox - Critical Error", "msg box title");
2238 icon = AlertIconType_Critical;
2239 break;
2240 case MessageType_GuruMeditation:
2241 title = "VirtualBox - Guru Meditation"; /* don't translate this */
2242 icon = AlertIconType_GuruMeditation;
2243 break;
2244 }
2245
2246 /* Create message-box: */
2247 QWidget *pMessageBoxParent = windowManager().realParentWindow(pParent ? pParent : windowManager().mainWindowShown());
2248 QPointer<QIMessageBox> pMessageBox = new QIMessageBox(title, strMessage, icon,
2249 iButton1, iButton2, iButton3,
2250 pMessageBoxParent, strHelpKeyword);
2251 windowManager().registerNewParent(pMessageBox, pMessageBoxParent);
2252
2253 /* Prepare auto-confirmation check-box: */
2254 if (!strAutoConfirmId.isEmpty())
2255 {
2256 pMessageBox->setFlagText(tr("Do not show this message again", "msg box flag"));
2257 pMessageBox->setFlagChecked(false);
2258 }
2259
2260 /* Configure details: */
2261 if (!strDetails.isEmpty())
2262 pMessageBox->setDetailsText(strDetails);
2263
2264 /* Configure button-text: */
2265 if (!strButtonText1.isNull())
2266 pMessageBox->setButtonText(0, strButtonText1);
2267 if (!strButtonText2.isNull())
2268 pMessageBox->setButtonText(1, strButtonText2);
2269 if (!strButtonText3.isNull())
2270 pMessageBox->setButtonText(2, strButtonText3);
2271
2272 /* Show message-box: */
2273 int iResultCode = pMessageBox->exec();
2274
2275 /* Make sure message-box still valid: */
2276 if (!pMessageBox)
2277 return iResultCode;
2278
2279 /* Remember auto-confirmation check-box value: */
2280 if (!strAutoConfirmId.isEmpty())
2281 {
2282 if (pMessageBox->flagChecked())
2283 {
2284 confirmedMessageList << strAutoConfirmId;
2285 gEDataManager->setSuppressedMessages(confirmedMessageList);
2286 }
2287 }
2288
2289 /* Delete message-box: */
2290 delete pMessageBox;
2291
2292 /* Return result-code: */
2293 return iResultCode;
2294}
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