VirtualBox

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

Last change on this file since 43138 was 43138, checked in by vboxsync, 12 years ago

BUGZ:3965 Allow user to change network configuration on VM start if any of involved physical network interfaces missing.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 140.1 KB
Line 
1/* $Id: UIMessageCenter.cpp 43138 2012-08-31 13:26:04Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: Qt GUI ("VirtualBox"):
5 * UIMessageCenter class implementation
6 */
7
8/*
9 * Copyright (C) 2006-2012 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20/* Qt includes: */
21#include <QDir>
22#include <QDesktopWidget>
23#include <QFileInfo>
24#include <QLocale>
25#include <QThread>
26#include <QProcess>
27#ifdef Q_WS_MAC
28# include <QPushButton>
29#endif /* Q_WS_MAC */
30
31/* GUI includes: */
32#include "UIMessageCenter.h"
33#include "VBoxGlobal.h"
34#include "UISelectorWindow.h"
35#include "UIProgressDialog.h"
36#include "UINetworkManager.h"
37#include "UINetworkManagerDialog.h"
38#include "UIConverter.h"
39#ifdef VBOX_OSE
40# include "UIDownloaderUserManual.h"
41#endif /* VBOX_OSE */
42#include "UIMachine.h"
43#include "VBoxAboutDlg.h"
44#include "UIHotKeyEditor.h"
45#ifdef Q_WS_MAC
46# include "VBoxUtils-darwin.h"
47#endif /* Q_WS_MAC */
48#ifdef Q_WS_WIN
49# include <Htmlhelp.h>
50#endif /* Q_WS_WIN */
51
52/* COM includes: */
53#include "CConsole.h"
54#include "CMachine.h"
55#include "CSystemProperties.h"
56#include "CVirtualBoxErrorInfo.h"
57#include "CMediumAttachment.h"
58#include "CMediumFormat.h"
59#include "CAppliance.h"
60#include "CExtPackManager.h"
61#include "CExtPackFile.h"
62#include "CHostNetworkInterface.h"
63#ifdef VBOX_WITH_DRAG_AND_DROP
64# include "CGuest.h"
65#endif /* VBOX_WITH_DRAG_AND_DROP */
66
67/* Other VBox includes: */
68#include <iprt/err.h>
69#include <iprt/param.h>
70#include <iprt/path.h>
71
72bool UIMessageCenter::isAnyWarningShown()
73{
74 /* Check if at least one warning is alive!
75 * All warnings are stored in m_warnings list as live pointers,
76 * this is why if some warning was deleted from another place,
77 * its pointer here will equal NULL... */
78 for (int i = 0; i < m_warnings.size(); ++i)
79 if (m_warnings[i])
80 return true;
81 return false;
82}
83
84bool UIMessageCenter::isAlreadyShown(const QString &strWarningName) const
85{
86 return m_strShownWarnings.contains(strWarningName);
87}
88
89void UIMessageCenter::setShownStatus(const QString &strWarningName)
90{
91 if (!m_strShownWarnings.contains(strWarningName))
92 m_strShownWarnings.append(strWarningName);
93}
94
95void UIMessageCenter::clearShownStatus(const QString &strWarningName)
96{
97 if (m_strShownWarnings.contains(strWarningName))
98 m_strShownWarnings.removeAll(strWarningName);
99}
100
101void UIMessageCenter::closeAllWarnings()
102{
103 /* Broadcast signal to perform emergent
104 * closing + deleting all the opened warnings. */
105 emit sigToCloseAllWarnings();
106}
107
108/**
109 * Shows a message box of the given type with the given text and with buttons
110 * according to arguments b1, b2 and b3 (in the same way as QMessageBox does
111 * it), and returns the user's choice.
112 *
113 * When all button arguments are zero, a single 'Ok' button is shown.
114 *
115 * If pcszAutoConfirmId is not null, then the message box will contain a
116 * checkbox "Don't show this message again" below the message text and its
117 * state will be saved in the global config. When the checkbox is in the
118 * checked state, this method doesn't actually show the message box but
119 * returns immediately. The return value in this case is the same as if the
120 * user has pressed the Enter key or the default button, but with
121 * AutoConfirmed bit set (AutoConfirmed alone is returned when no default
122 * button is defined in button arguments).
123 *
124 * @param pParent
125 * Parent widget or 0 to use the desktop as the pParent. Also,
126 * #mainWindowShown can be used to determine the currently shown VBox
127 * main window (Selector or Console).
128 * @param type
129 * One of values of the Type enum, that defines the message box
130 * title and icon.
131 * @param strMessage
132 * Message text to display (can contain simple Qt-html tags).
133 * @param strDetails
134 * Detailed message description displayed under the main message text using
135 * QTextEdit (that provides rich text support and scrollbars when necessary).
136 * If equals to QString::null, no details text box is shown.
137 * @param pcszAutoConfirmId
138 * ID used to save the auto confirmation state across calls. If null,
139 * the auto confirmation feature is turned off (and no checkbox is shown)
140 * @param button1
141 * First button code or 0, see QIMessageBox for a list of codes.
142 * @param button2
143 * Second button code or 0, see QIMessageBox for a list of codes.
144 * @param button3
145 * Third button code or 0, see QIMessageBox for a list of codes.
146 * @param strText1
147 * Optional custom text for the first button.
148 * @param strText2
149 * Optional custom text for the second button.
150 * @param strText3
151 * Optional custom text for the third button.
152 *
153 * @return
154 * code of the button pressed by the user
155 */
156int UIMessageCenter::message(QWidget *pParent, Type type, const QString &strMessage,
157 const QString &strDetails /* = QString::null */,
158 const char *pcszAutoConfirmId /* = 0 */,
159 int button1 /* = 0 */,
160 int button2 /* = 0 */,
161 int button3 /* = 0 */,
162 const QString &strText1 /* = QString::null */,
163 const QString &strText2 /* = QString::null */,
164 const QString &strText3 /* = QString::null */) const
165{
166 if (button1 == 0 && button2 == 0 && button3 == 0)
167 button1 = QIMessageBox::Ok | QIMessageBox::Default;
168
169 CVirtualBox vbox;
170 QStringList msgs;
171
172 if (pcszAutoConfirmId)
173 {
174 vbox = vboxGlobal().virtualBox();
175 msgs = vbox.GetExtraData(GUI_SuppressMessages).split(',');
176 if (msgs.contains(pcszAutoConfirmId))
177 {
178 int rc = AutoConfirmed;
179 if (button1 & QIMessageBox::Default)
180 rc |= (button1 & QIMessageBox::ButtonMask);
181 if (button2 & QIMessageBox::Default)
182 rc |= (button2 & QIMessageBox::ButtonMask);
183 if (button3 & QIMessageBox::Default)
184 rc |= (button3 & QIMessageBox::ButtonMask);
185 return rc;
186 }
187 }
188
189 QString title;
190 QIMessageBox::Icon icon;
191
192 switch (type)
193 {
194 default:
195 case Info:
196 title = tr("VirtualBox - Information", "msg box title");
197 icon = QIMessageBox::Information;
198 break;
199 case Question:
200 title = tr("VirtualBox - Question", "msg box title");
201 icon = QIMessageBox::Question;
202 break;
203 case Warning:
204 title = tr("VirtualBox - Warning", "msg box title");
205 icon = QIMessageBox::Warning;
206 break;
207 case Error:
208 title = tr("VirtualBox - Error", "msg box title");
209 icon = QIMessageBox::Critical;
210 break;
211 case Critical:
212 title = tr("VirtualBox - Critical Error", "msg box title");
213 icon = QIMessageBox::Critical;
214 break;
215 case GuruMeditation:
216 title = "VirtualBox - Guru Meditation"; /* don't translate this */
217 icon = QIMessageBox::GuruMeditation;
218 break;
219 }
220
221 QPointer<QIMessageBox> box = new QIMessageBox(title, strMessage, icon, button1, button2,
222 button3, pParent, pcszAutoConfirmId);
223 connect(this, SIGNAL(sigToCloseAllWarnings()), box, SLOT(deleteLater()));
224
225 if (!strText1.isNull())
226 box->setButtonText(0, strText1);
227 if (!strText2.isNull())
228 box->setButtonText(1, strText2);
229 if (!strText3.isNull())
230 box->setButtonText(2, strText3);
231
232 if (!strDetails.isEmpty())
233 box->setDetailsText(strDetails);
234
235 if (pcszAutoConfirmId)
236 {
237 box->setFlagText(tr("Do not show this message again", "msg box flag"));
238 box->setFlagChecked(false);
239 }
240
241 m_warnings << box;
242 int rc = box->exec();
243 if (box && m_warnings.contains(box))
244 m_warnings.removeAll(box);
245
246 if (pcszAutoConfirmId)
247 {
248 if (box && box->isFlagChecked())
249 {
250 msgs << pcszAutoConfirmId;
251 vbox.SetExtraData(GUI_SuppressMessages, msgs.join(","));
252 }
253 }
254
255 if (box)
256 delete box;
257
258 return rc;
259}
260
261/** @fn message(QWidget *, Type, const QString &, const char *, int, int,
262 * int, const QString &, const QString &, const QString &)
263 *
264 * A shortcut to #message() that doesn't require to specify the details
265 * text(QString::null is assumed).
266 */
267
268/** @fn messageYesNo(QWidget *, Type, const QString &, const QString &, const char *)
269 *
270 * A shortcut to #message() that shows 'Yes' and 'No' buttons ('Yes' is the
271 * default) and returns true when the user selects Yes.
272 */
273
274/** @fn messageYesNo(QWidget *, Type, const QString &, const char *)
275 *
276 * A shortcut to #messageYesNo() that doesn't require to specify the details
277 * text(QString::null is assumed).
278 */
279
280int UIMessageCenter::messageWithOption(QWidget *pParent,
281 Type type,
282 const QString &strMessage,
283 const QString &strOptionText,
284 bool fDefaultOptionValue /* = true */,
285 const QString &strDetails /* = QString::null */,
286 int iButton1 /* = 0 */,
287 int iButton2 /* = 0 */,
288 int iButton3 /* = 0 */,
289 const QString &strButtonName1 /* = QString::null */,
290 const QString &strButtonName2 /* = QString::null */,
291 const QString &strButtonName3 /* = QString::null */) const
292{
293 /* If no buttons are set, using single 'OK' button: */
294 if (iButton1 == 0 && iButton2 == 0 && iButton3 == 0)
295 iButton1 = QIMessageBox::Ok | QIMessageBox::Default;
296
297 /* Assign corresponding title and icon: */
298 QString strTitle;
299 QIMessageBox::Icon icon;
300 switch (type)
301 {
302 default:
303 case Info:
304 strTitle = tr("VirtualBox - Information", "msg box title");
305 icon = QIMessageBox::Information;
306 break;
307 case Question:
308 strTitle = tr("VirtualBox - Question", "msg box title");
309 icon = QIMessageBox::Question;
310 break;
311 case Warning:
312 strTitle = tr("VirtualBox - Warning", "msg box title");
313 icon = QIMessageBox::Warning;
314 break;
315 case Error:
316 strTitle = tr("VirtualBox - Error", "msg box title");
317 icon = QIMessageBox::Critical;
318 break;
319 case Critical:
320 strTitle = tr("VirtualBox - Critical Error", "msg box title");
321 icon = QIMessageBox::Critical;
322 break;
323 case GuruMeditation:
324 strTitle = "VirtualBox - Guru Meditation"; /* don't translate this */
325 icon = QIMessageBox::GuruMeditation;
326 break;
327 }
328
329 /* Create message-box: */
330 if (QPointer<QIMessageBox> pBox = new QIMessageBox(strTitle, strMessage, icon,
331 iButton1, iButton2, iButton3, pParent))
332 {
333 /* Append the list of all warnings with current: */
334 m_warnings << pBox;
335
336 /* Setup message-box connections: */
337 connect(this, SIGNAL(sigToCloseAllWarnings()), pBox, SLOT(deleteLater()));
338
339 /* Assign other text values: */
340 if (!strOptionText.isNull())
341 {
342 pBox->setFlagText(strOptionText);
343 pBox->setFlagChecked(fDefaultOptionValue);
344 }
345 if (!strButtonName1.isNull())
346 pBox->setButtonText(0, strButtonName1);
347 if (!strButtonName2.isNull())
348 pBox->setButtonText(1, strButtonName2);
349 if (!strButtonName3.isNull())
350 pBox->setButtonText(2, strButtonName3);
351 if (!strDetails.isEmpty())
352 pBox->setDetailsText(strDetails);
353
354 /* Show the message box: */
355 int iResultCode = pBox->exec();
356
357 /* Its possible what message-box will be deleted during some event-processing procedure,
358 * in that case pBox will be null right after pBox->exec() returns from it's event-pool,
359 * so we have to check this too: */
360 if (pBox)
361 {
362 /* Cleanup the list of all warnings from current: */
363 if (m_warnings.contains(pBox))
364 m_warnings.removeAll(pBox);
365
366 /* Check if option was chosen: */
367 if (pBox->isFlagChecked())
368 iResultCode |= QIMessageBox::OptionChosen;
369
370 /* Destroy message-box: */
371 if (pBox)
372 delete pBox;
373
374 /* Return final result: */
375 return iResultCode;
376 }
377 }
378 return 0;
379}
380
381/**
382 * Shows a modal progress dialog using a CProgress object passed as an
383 * argument to track the progress.
384 *
385 * @param progress progress object to track
386 * @param aTitle title prefix
387 * @param pParent pParent widget
388 * @param aMinDuration time (ms) that must pass before the dialog appears
389 */
390bool UIMessageCenter::showModalProgressDialog(CProgress &progress,
391 const QString &strTitle,
392 const QString &strImage /* = "" */,
393 QWidget *pParent /* = 0 */,
394 bool fSheetOnDarwin /* = false */,
395 int cMinDuration /* = 2000 */)
396{
397 QPixmap *pPixmap = 0;
398 if (!strImage.isEmpty())
399 pPixmap = new QPixmap(strImage);
400
401 UIProgressDialog progressDlg(progress, strTitle, pPixmap, fSheetOnDarwin, cMinDuration, pParent ? pParent : mainWindowShown());
402 /* Run the dialog with the 350 ms refresh interval. */
403 progressDlg.run(350);
404
405 if (pPixmap)
406 delete pPixmap;
407
408 return true;
409}
410
411/**
412 * Returns what main window (VM selector or main VM window) is now shown, or
413 * zero if none of them. Main VM window takes precedence.
414 */
415QWidget* UIMessageCenter::mainWindowShown() const
416{
417 /* It may happen that this method is called during VBoxGlobal
418 * initialization or even after it failed (for example, to show some
419 * error message). Return no main window in this case: */
420 if (!vboxGlobal().isValid())
421 return 0;
422
423 if (vboxGlobal().isVMConsoleProcess())
424 {
425 if (vboxGlobal().vmWindow() && vboxGlobal().vmWindow()->isVisible()) /* VM window is visible */
426 return vboxGlobal().vmWindow(); /* return that window */
427 }
428 else
429 {
430 if (vboxGlobal().selectorWnd().isVisible()) /* VM selector is visible */
431 return &vboxGlobal().selectorWnd(); /* return that window */
432 }
433
434 return 0;
435}
436
437/**
438 * Returns main machine window is now shown, or zero if none of them.
439 */
440QWidget* UIMessageCenter::mainMachineWindowShown() const
441{
442 /* It may happen that this method is called during VBoxGlobal
443 * initialization or even after it failed (for example, to show some
444 * error message). Return no main window in this case: */
445 if (!vboxGlobal().isValid())
446 return 0;
447
448 if (vboxGlobal().vmWindow() && vboxGlobal().vmWindow()->isVisible()) /* VM window is visible */
449 return vboxGlobal().vmWindow(); /* return that window */
450
451 return 0;
452}
453
454/**
455 * Returns network access manager window if visible
456 * and window returned by mainWindowShown() otherwise.
457 */
458QWidget* UIMessageCenter::networkManagerOrMainWindowShown() const
459{
460 return gNetworkManager->window()->isVisible() ? gNetworkManager->window() : mainWindowShown();
461}
462
463/**
464 * Returns network access manager window if visible
465 * and window returned by mainMachineWindowShown() otherwise.
466 */
467QWidget* UIMessageCenter::networkManagerOrMainMachineWindowShown() const
468{
469 return gNetworkManager->window()->isVisible() ? gNetworkManager->window() : mainMachineWindowShown();
470}
471
472bool UIMessageCenter::askForOverridingFile(const QString& strPath, QWidget *pParent /* = NULL */)
473{
474 return messageYesNo(pParent, Question, tr("A file named <b>%1</b> already exists. Are you sure you want to replace it?<br /><br />Replacing it will overwrite its contents.").arg(strPath));
475}
476
477bool UIMessageCenter::askForOverridingFiles(const QVector<QString>& strPaths, QWidget *pParent /* = NULL */)
478{
479 if (strPaths.size() == 1)
480 /* If it is only one file use the single question versions above */
481 return askForOverridingFile(strPaths.at(0), pParent);
482 else if (strPaths.size() > 1)
483 return messageYesNo(pParent, Question, tr("The following files already exist:<br /><br />%1<br /><br />Are you sure you want to replace them? Replacing them will overwrite their contents.").arg(QStringList(strPaths.toList()).join("<br />")));
484 else
485 return true;
486}
487
488bool UIMessageCenter::askForOverridingFileIfExists(const QString& strPath, QWidget *pParent /* = NULL */)
489{
490 QFileInfo fi(strPath);
491 if (fi.exists())
492 return askForOverridingFile(strPath, pParent);
493 else
494 return true;
495}
496
497bool UIMessageCenter::askForOverridingFilesIfExists(const QVector<QString>& strPaths, QWidget *pParent /* = NULL */)
498{
499 QVector<QString> existingFiles;
500 foreach(const QString &file, strPaths)
501 {
502 QFileInfo fi(file);
503 if (fi.exists())
504 existingFiles << fi.absoluteFilePath();
505 }
506 if (existingFiles.size() == 1)
507 /* If it is only one file use the single question versions above */
508 return askForOverridingFileIfExists(existingFiles.at(0), pParent);
509 else if (existingFiles.size() > 1)
510 return askForOverridingFiles(existingFiles, pParent);
511 else
512 return true;
513}
514
515void UIMessageCenter::checkForMountedWrongUSB()
516{
517#ifdef RT_OS_LINUX
518 QFile file("/proc/mounts");
519 if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text))
520 {
521 QStringList contents;
522 for (;;)
523 {
524 QByteArray line = file.readLine();
525 if (line.isEmpty())
526 break;
527 contents << line;
528 }
529 QStringList grep1(contents.filter("/sys/bus/usb/drivers"));
530 QStringList grep2(grep1.filter("usbfs"));
531 if (!grep2.isEmpty())
532 message(mainWindowShown(), Warning,
533 tr("You seem to have the USBFS filesystem mounted at /sys/bus/usb/drivers. "
534 "We strongly recommend that you change this, as it is a severe mis-configuration of "
535 "your system which could cause USB devices to fail in unexpected ways."),
536 "checkForMountedWrongUSB");
537 }
538#endif
539}
540
541void UIMessageCenter::showBETAWarning()
542{
543 message
544 (0, Warning,
545 tr("You are running a prerelease version of VirtualBox. "
546 "This version is not suitable for production use."));
547}
548
549void UIMessageCenter::showBEBWarning()
550{
551 message
552 (0, Warning,
553 tr("You are running an EXPERIMENTAL build of VirtualBox. "
554 "This version is not suitable for production use."));
555}
556
557#ifdef Q_WS_X11
558void UIMessageCenter::cannotFindLicenseFiles(const QString &strPath)
559{
560 message
561 (0, UIMessageCenter::Error,
562 tr("Failed to find license files in "
563 "<nobr><b>%1</b></nobr>.")
564 .arg(strPath));
565}
566#endif
567
568void UIMessageCenter::cannotOpenLicenseFile(QWidget *pParent, const QString &strPath)
569{
570 message
571 (pParent, UIMessageCenter::Error,
572 tr("Failed to open the license file <nobr><b>%1</b></nobr>. "
573 "Check file permissions.")
574 .arg(strPath));
575}
576
577void UIMessageCenter::cannotOpenURL(const QString &strUrl)
578{
579 message
580 (mainWindowShown(), UIMessageCenter::Error,
581 tr("Failed to open <tt>%1</tt>. Make sure your desktop environment "
582 "can properly handle URLs of this type.")
583 .arg(strUrl));
584}
585
586void UIMessageCenter::cannotFindLanguage(const QString &strLangId, const QString &strNlsPath)
587{
588 message(0, UIMessageCenter::Error,
589 tr("<p>Could not find a language file for the language "
590 "<b>%1</b> in the directory <b><nobr>%2</nobr></b>.</p>"
591 "<p>The language will be temporarily reset to the system "
592 "default language. Please go to the <b>Preferences</b> "
593 "dialog which you can open from the <b>File</b> menu of the "
594 "main VirtualBox window, and select one of the existing "
595 "languages on the <b>Language</b> page.</p>")
596 .arg(strLangId).arg(strNlsPath));
597}
598
599void UIMessageCenter::cannotLoadLanguage(const QString &strLangFile)
600{
601 message(0, UIMessageCenter::Error,
602 tr("<p>Could not load the language file <b><nobr>%1</nobr></b>. "
603 "<p>The language will be temporarily reset to English (built-in). "
604 "Please go to the <b>Preferences</b> "
605 "dialog which you can open from the <b>File</b> menu of the "
606 "main VirtualBox window, and select one of the existing "
607 "languages on the <b>Language</b> page.</p>")
608 .arg(strLangFile));
609}
610
611void UIMessageCenter::cannotInitCOM(HRESULT rc)
612{
613 message(0, Critical,
614 tr("<p>Failed to initialize COM or to find the VirtualBox COM server. "
615 "Most likely, the VirtualBox server is not running "
616 "or failed to start.</p>"
617 "<p>The application will now terminate.</p>"),
618 formatErrorInfo(COMErrorInfo(), rc));
619}
620
621void UIMessageCenter::cannotInitUserHome(const QString &strUserHome)
622{
623 message(0, Critical,
624 tr("<p>Failed to initialize COM because the VirtualBox global "
625 "configuration directory <b><nobr>%1</nobr></b> is not accessible. "
626 "Please check the permissions of this directory and of its parent "
627 "directory.</p>"
628 "<p>The application will now terminate.</p>").arg(strUserHome),
629 formatErrorInfo(COMErrorInfo()));
630}
631
632void UIMessageCenter::cannotCreateVirtualBox(const CVirtualBox &vbox)
633{
634 message(0, Critical,
635 tr("<p>Failed to create the VirtualBox COM object.</p>"
636 "<p>The application will now terminate.</p>"),
637 formatErrorInfo(vbox));
638}
639
640void UIMessageCenter::cannotLoadGlobalConfig(const CVirtualBox &vbox, const QString &strError)
641{
642 /* preserve the current error info before calling the object again */
643 COMResult res(vbox);
644
645 message(mainWindowShown(), Critical,
646 tr("<p>Failed to load the global GUI configuration from "
647 "<b><nobr>%1</nobr></b>.</p>"
648 "<p>The application will now terminate.</p>")
649 .arg(vbox.GetSettingsFilePath()),
650 !res.isOk() ? formatErrorInfo(res)
651 : QString("<!--EOM--><p>%1</p>").arg(vboxGlobal().emphasize(strError)));
652}
653
654void UIMessageCenter::cannotSaveGlobalConfig(const CVirtualBox &vbox)
655{
656 /* preserve the current error info before calling the object again */
657 COMResult res(vbox);
658
659 message(mainWindowShown(), Critical,
660 tr("<p>Failed to save the global GUI configuration to "
661 "<b><nobr>%1</nobr></b>.</p>"
662 "<p>The application will now terminate.</p>")
663 .arg(vbox.GetSettingsFilePath()),
664 formatErrorInfo(res));
665}
666
667void UIMessageCenter::cannotSetSystemProperties(const CSystemProperties &props)
668{
669 message(mainWindowShown(), Critical,
670 tr("Failed to set global VirtualBox properties."),
671 formatErrorInfo(props));
672}
673
674void UIMessageCenter::cannotAccessUSB(const COMBaseWithEI &object)
675{
676 /* If IMachine::GetUSBController(), IHost::GetUSBDevices() etc. return
677 * E_NOTIMPL, it means the USB support is intentionally missing
678 * (as in the OSE version). Don't show the error message in this case. */
679 COMResult res(object);
680 if (res.rc() == E_NOTIMPL)
681 return;
682
683 message(mainWindowShown(), res.isWarning() ? Warning : Error,
684 tr("Failed to access the USB subsystem."),
685 formatErrorInfo(res),
686 "cannotAccessUSB");
687}
688
689void UIMessageCenter::cannotCreateMachine(const CVirtualBox &vbox, QWidget *pParent /* = 0 */)
690{
691 message(
692 pParent ? pParent : mainWindowShown(),
693 Error,
694 tr("Failed to create a new virtual machine."),
695 formatErrorInfo(vbox)
696 );
697}
698
699void UIMessageCenter::cannotCreateMachine(const CVirtualBox &vbox,
700 const CMachine &machine,
701 QWidget *pParent /* = 0 */)
702{
703 message(
704 pParent ? pParent : mainWindowShown(),
705 Error,
706 tr("Failed to create a new virtual machine <b>%1</b>.")
707 .arg(machine.GetName()),
708 formatErrorInfo(vbox)
709 );
710}
711
712void UIMessageCenter::cannotOpenMachine(QWidget *pParent, const QString &strMachinePath, const CVirtualBox &vbox)
713{
714 message(pParent ? pParent : mainWindowShown(),
715 Error,
716 tr("Failed to open virtual machine located in %1.")
717 .arg(strMachinePath),
718 formatErrorInfo(vbox));
719}
720
721void UIMessageCenter::cannotRegisterMachine(const CVirtualBox &vbox,
722 const CMachine &machine,
723 QWidget *pParent)
724{
725 message(pParent ? pParent : mainWindowShown(),
726 Error,
727 tr("Failed to register the virtual machine <b>%1</b>.")
728 .arg(machine.GetName()),
729 formatErrorInfo(vbox));
730}
731
732void UIMessageCenter::cannotReregisterMachine(QWidget *pParent, const QString &strMachinePath, const QString &strMachineName)
733{
734 message(pParent ? pParent : mainWindowShown(),
735 Error,
736 tr("Failed to add virtual machine <b>%1</b> located in <i>%2</i> because its already present.")
737 .arg(strMachineName).arg(strMachinePath));
738}
739
740void UIMessageCenter::cannotApplyMachineSettings(const CMachine &machine, const COMResult &res)
741{
742 message(
743 mainWindowShown(),
744 Error,
745 tr("Failed to apply the settings to the virtual machine <b>%1</b>.")
746 .arg(machine.GetName()),
747 formatErrorInfo(res)
748 );
749}
750
751void UIMessageCenter::cannotSaveMachineSettings(const CMachine &machine, QWidget *pParent /* = 0 */)
752{
753 /* preserve the current error info before calling the object again */
754 COMResult res(machine);
755
756 message(pParent ? pParent : mainWindowShown(), Error,
757 tr("Failed to save the settings of the virtual machine "
758 "<b>%1</b> to <b><nobr>%2</nobr></b>.")
759 .arg(machine.GetName(), machine.GetSettingsFilePath()),
760 formatErrorInfo(res));
761}
762
763/**
764 * @param fStrict If |false|, this method will silently return if the COM
765 * result code is E_NOTIMPL.
766 */
767void UIMessageCenter::cannotLoadMachineSettings(const CMachine &machine,
768 bool fStrict /* = true */,
769 QWidget *pParent /* = 0 */)
770{
771 /* If COM result code is E_NOTIMPL, it means the requested object or
772 * function is intentionally missing (as in the OSE version). Don't show
773 * the error message in this case. */
774 COMResult res(machine);
775 if (!fStrict && res.rc() == E_NOTIMPL)
776 return;
777
778 message(pParent ? pParent : mainWindowShown(), Error,
779 tr("Failed to load the settings of the virtual machine "
780 "<b>%1</b> from <b><nobr>%2</nobr></b>.")
781 .arg(machine.GetName(), machine.GetSettingsFilePath()),
782 formatErrorInfo(res));
783}
784
785bool UIMessageCenter::confirmedSettingsReloading(QWidget *pParent)
786{
787 int rc = message(pParent, Question,
788 tr("<p>The machine settings were changed while you were editing them. "
789 "You currently have unsaved setting changes.</p>"
790 "<p>Would you like to reload the changed settings or to keep your own changes?</p>"), 0,
791 QIMessageBox::Yes, QIMessageBox::No | QIMessageBox::Default | QIMessageBox::Escape, 0,
792 tr("Reload settings"), tr("Keep changes"), 0);
793 return rc == QIMessageBox::Yes;
794}
795
796void UIMessageCenter::warnAboutStateChange(QWidget *pParent)
797{
798 if (isAlreadyShown("warnAboutStateChange"))
799 return;
800 setShownStatus("warnAboutStateChange");
801
802 message(pParent ? pParent : mainWindowShown(), Warning,
803 tr("The virtual machine that you are changing has been started. "
804 "Only certain settings can be changed while a machine is running. "
805 "All other changes will be lost if you close this window now."));
806
807 clearShownStatus("warnAboutStateChange");
808}
809
810void UIMessageCenter::cannotStartMachine(const CConsole &console)
811{
812 /* preserve the current error info before calling the object again */
813 COMResult res(console);
814
815 message(mainWindowShown(), Error,
816 tr("Failed to start the virtual machine <b>%1</b>.")
817 .arg(console.GetMachine().GetName()),
818 formatErrorInfo(res));
819}
820
821void UIMessageCenter::cannotStartMachine(const CProgress &progress)
822{
823 AssertWrapperOk(progress);
824 CConsole console(CProgress(progress).GetInitiator());
825 AssertWrapperOk(console);
826
827 message(
828 mainWindowShown(),
829 Error,
830 tr("Failed to start the virtual machine <b>%1</b>.")
831 .arg(console.GetMachine().GetName()),
832 formatErrorInfo(progress.GetErrorInfo())
833 );
834}
835
836void UIMessageCenter::cannotPauseMachine(const CConsole &console)
837{
838 /* preserve the current error info before calling the object again */
839 COMResult res(console);
840
841 message(mainWindowShown(), Error,
842 tr("Failed to pause the execution of the virtual machine <b>%1</b>.")
843 .arg(console.GetMachine().GetName()),
844 formatErrorInfo(res));
845}
846
847void UIMessageCenter::cannotResumeMachine(const CConsole &console)
848{
849 /* preserve the current error info before calling the object again */
850 COMResult res(console);
851
852 message(mainWindowShown(), Error,
853 tr("Failed to resume the execution of the virtual machine <b>%1</b>.")
854 .arg(console.GetMachine().GetName()),
855 formatErrorInfo(res));
856}
857
858void UIMessageCenter::cannotACPIShutdownMachine(const CConsole &console)
859{
860 /* preserve the current error info before calling the object again */
861 COMResult res(console);
862
863 message(mainWindowShown(), Error,
864 tr("Failed to send the ACPI Power Button press event to the "
865 "virtual machine <b>%1</b>.")
866 .arg(console.GetMachine().GetName()),
867 formatErrorInfo(res));
868}
869
870void UIMessageCenter::cannotSaveMachineState(const CConsole &console)
871{
872 /* preserve the current error info before calling the object again */
873 COMResult res(console);
874
875 message(mainWindowShown(), Error,
876 tr("Failed to save the state of the virtual machine <b>%1</b>.")
877 .arg(console.GetMachine().GetName()),
878 formatErrorInfo(res));
879}
880
881void UIMessageCenter::cannotSaveMachineState(const CProgress &progress)
882{
883 AssertWrapperOk(progress);
884 CConsole console(CProgress(progress).GetInitiator());
885 AssertWrapperOk(console);
886
887 message(
888 mainWindowShown(),
889 Error,
890 tr("Failed to save the state of the virtual machine <b>%1</b>.")
891 .arg(console.GetMachine().GetName()),
892 formatErrorInfo(progress.GetErrorInfo())
893 );
894}
895
896void UIMessageCenter::cannotCreateClone(const CMachine &machine,
897 QWidget *pParent /* = 0 */)
898{
899 message(
900 pParent ? pParent : mainWindowShown(),
901 Error,
902 tr("Failed to clone the virtual machine <b>%1</b>.")
903 .arg(machine.GetName()),
904 formatErrorInfo(machine)
905 );
906}
907
908void UIMessageCenter::cannotCreateClone(const CMachine &machine,
909 const CProgress &progress,
910 QWidget *pParent /* = 0 */)
911{
912 AssertWrapperOk(progress);
913
914 message(pParent ? pParent : mainWindowShown(),
915 Error,
916 tr("Failed to clone the virtual machine <b>%1</b>.")
917 .arg(machine.GetName()),
918 formatErrorInfo(progress.GetErrorInfo())
919 );
920}
921
922void UIMessageCenter::cannotTakeSnapshot(const CConsole &console)
923{
924 /* preserve the current error info before calling the object again */
925 COMResult res(console);
926
927 message(mainWindowShown(), Error,
928 tr("Failed to create a snapshot of the virtual machine <b>%1</b>.")
929 .arg(console.GetMachine().GetName()),
930 formatErrorInfo(res));
931}
932
933void UIMessageCenter::cannotTakeSnapshot(const CProgress &progress)
934{
935 AssertWrapperOk(progress);
936 CConsole console(CProgress(progress).GetInitiator());
937 AssertWrapperOk(console);
938
939 message(
940 mainWindowShown(),
941 Error,
942 tr("Failed to create a snapshot of the virtual machine <b>%1</b>.")
943 .arg(console.GetMachine().GetName()),
944 formatErrorInfo(progress.GetErrorInfo())
945 );
946}
947
948void UIMessageCenter::cannotStopMachine(const CConsole &console)
949{
950 /* preserve the current error info before calling the object again */
951 COMResult res(console);
952
953 message(mainWindowShown(), Error,
954 tr("Failed to stop the virtual machine <b>%1</b>.")
955 .arg(console.GetMachine().GetName()),
956 formatErrorInfo(res));
957}
958
959void UIMessageCenter::cannotStopMachine(const CProgress &progress)
960{
961 AssertWrapperOk(progress);
962 CConsole console(CProgress(progress).GetInitiator());
963 AssertWrapperOk(console);
964
965 message(mainWindowShown(), Error,
966 tr("Failed to stop the virtual machine <b>%1</b>.")
967 .arg(console.GetMachine().GetName()),
968 formatErrorInfo(progress.GetErrorInfo()));
969}
970
971void UIMessageCenter::cannotDeleteMachine(const CMachine &machine)
972{
973 /* preserve the current error info before calling the object again */
974 COMResult res(machine);
975
976 message(mainWindowShown(),
977 Error,
978 tr("Failed to remove the virtual machine <b>%1</b>.").arg(machine.GetName()),
979 !machine.isOk() ? formatErrorInfo(machine) : formatErrorInfo(res));
980}
981
982void UIMessageCenter::cannotDeleteMachine(const CMachine &machine, const CProgress &progress)
983{
984 message(mainWindowShown(),
985 Error,
986 tr("Failed to remove the virtual machine <b>%1</b>.").arg(machine.GetName()),
987 formatErrorInfo(progress.GetErrorInfo()));
988}
989
990void UIMessageCenter::cannotDiscardSavedState(const CConsole &console)
991{
992 /* preserve the current error info before calling the object again */
993 COMResult res(console);
994
995 message(mainWindowShown(), Error,
996 tr("Failed to discard the saved state of the virtual machine <b>%1</b>.")
997 .arg(console.GetMachine().GetName()),
998 formatErrorInfo(res));
999}
1000
1001void UIMessageCenter::cannotSendACPIToMachine()
1002{
1003 message(mainWindowShown(), Warning,
1004 tr("You are trying to shut down the guest with the ACPI power "
1005 "button. This is currently not possible because the guest "
1006 "does not support software shutdown."));
1007}
1008
1009bool UIMessageCenter::warnAboutVirtNotEnabled64BitsGuest(bool fHWVirtExSupported)
1010{
1011 if (fHWVirtExSupported)
1012 return messageOkCancel(mainWindowShown(), Error,
1013 tr("<p>VT-x/AMD-V hardware acceleration has been enabled, but is "
1014 "not operational. Your 64-bit guest will fail to detect a "
1015 "64-bit CPU and will not be able to boot.</p><p>Please ensure "
1016 "that you have enabled VT-x/AMD-V properly in the BIOS of your "
1017 "host computer.</p>"),
1018 0 /* pcszAutoConfirmId */,
1019 tr("Close VM"), tr("Continue"));
1020 else
1021 return messageOkCancel(mainWindowShown(), Error,
1022 tr("<p>VT-x/AMD-V hardware acceleration is not available on your system. "
1023 "Your 64-bit guest will fail to detect a 64-bit CPU and will "
1024 "not be able to boot."),
1025 0 /* pcszAutoConfirmId */,
1026 tr("Close VM"), tr("Continue"));
1027}
1028
1029bool UIMessageCenter::warnAboutVirtNotEnabledGuestRequired(bool fHWVirtExSupported)
1030{
1031 if (fHWVirtExSupported)
1032 return messageOkCancel(mainWindowShown(), Error,
1033 tr("<p>VT-x/AMD-V hardware acceleration has been enabled, but is "
1034 "not operational. Certain guests (e.g. OS/2 and QNX) require "
1035 "this feature.</p><p>Please ensure "
1036 "that you have enabled VT-x/AMD-V properly in the BIOS of your "
1037 "host computer.</p>"),
1038 0 /* pcszAutoConfirmId */,
1039 tr("Close VM"), tr("Continue"));
1040 else
1041 return messageOkCancel(mainWindowShown(), Error,
1042 tr("<p>VT-x/AMD-V hardware acceleration is not available on your system. "
1043 "Certain guests (e.g. OS/2 and QNX) require this feature and will "
1044 "fail to boot without it.</p>"),
1045 0 /* pcszAutoConfirmId */,
1046 tr("Close VM"), tr("Continue"));
1047}
1048
1049int UIMessageCenter::askAboutSnapshotRestoring(const QString &strSnapshotName, bool fAlsoCreateNewSnapshot)
1050{
1051 return fAlsoCreateNewSnapshot ?
1052 messageWithOption(mainWindowShown(), Question,
1053 tr("<p>You are about to restore snapshot <nobr><b>%1</b></nobr>.</p>"
1054 "<p>You can create a snapshot of the current state of the virtual machine first by checking the box below; "
1055 "if you do not do this the current state will be permanently lost. Do you wish to proceed?</p>")
1056 .arg(strSnapshotName),
1057 tr("Create a snapshot of the current machine state"),
1058 !vboxGlobal().virtualBox().GetExtraDataStringList(GUI_InvertMessageOption).contains("askAboutSnapshotRestoring"),
1059 QString::null /* details */,
1060 QIMessageBox::Ok | QIMessageBox::Default,
1061 QIMessageBox::Cancel | QIMessageBox::Escape,
1062 0 /* 3rd button */,
1063 tr("Restore"), tr("Cancel"), QString::null /* 3rd button text */) :
1064 message(mainWindowShown(), Question,
1065 tr("<p>Are you sure you want to restore snapshot <nobr><b>%1</b></nobr>?</p>").arg(strSnapshotName),
1066 0 /* auto-confirmation token */,
1067 QIMessageBox::Ok | QIMessageBox::Default,
1068 QIMessageBox::Cancel | QIMessageBox::Escape,
1069 0 /* 3rd button */,
1070 tr("Restore"), tr("Cancel"), QString::null /* 3rd button text */);
1071}
1072
1073bool UIMessageCenter::askAboutSnapshotDeleting(const QString &strSnapshotName)
1074{
1075 return messageOkCancel(mainWindowShown(), Question,
1076 tr("<p>Deleting the snapshot will cause the state information saved in it to be lost, and disk data spread over "
1077 "several image files that VirtualBox has created together with the snapshot will be merged into one file. This can be a lengthy process, and the information "
1078 "in the snapshot cannot be recovered.</p></p>Are you sure you want to delete the selected snapshot <b>%1</b>?</p>")
1079 .arg(strSnapshotName),
1080 /* Do NOT allow this message to be disabled! */
1081 NULL /* pcszAutoConfirmId */,
1082 tr("Delete"), tr("Cancel"));
1083}
1084
1085bool UIMessageCenter::askAboutSnapshotDeletingFreeSpace(const QString &strSnapshotName,
1086 const QString &strTargetImageName,
1087 const QString &strTargetImageMaxSize,
1088 const QString &strTargetFileSystemFree)
1089{
1090 return messageOkCancel(mainWindowShown(), Question,
1091 tr("<p>Deleting the snapshot %1 will temporarily need more disk space. In the worst case the size of image %2 will grow by %3, "
1092 "however on this filesystem there is only %4 free.</p><p>Running out of disk space during the merge operation can result in "
1093 "corruption of the image and the VM configuration, i.e. loss of the VM and its data.</p><p>You may continue with deleting "
1094 "the snapshot at your own risk.</p>")
1095 .arg(strSnapshotName)
1096 .arg(strTargetImageName)
1097 .arg(strTargetImageMaxSize)
1098 .arg(strTargetFileSystemFree),
1099 /* Do NOT allow this message to be disabled! */
1100 NULL /* pcszAutoConfirmId */,
1101 tr("Delete"), tr("Cancel"));
1102}
1103
1104void UIMessageCenter::cannotRestoreSnapshot(const CConsole &console,
1105 const QString &strSnapshotName)
1106{
1107 message(mainWindowShown(), Error,
1108 tr("Failed to restore the snapshot <b>%1</b> of the virtual machine <b>%2</b>.")
1109 .arg(strSnapshotName)
1110 .arg(CConsole(console).GetMachine().GetName()),
1111 formatErrorInfo(console));
1112}
1113
1114void UIMessageCenter::cannotRestoreSnapshot(const CProgress &progress,
1115 const QString &strSnapshotName)
1116{
1117 CConsole console(CProgress(progress).GetInitiator());
1118
1119 message(mainWindowShown(), Error,
1120 tr("Failed to restore the snapshot <b>%1</b> of the virtual machine <b>%2</b>.")
1121 .arg(strSnapshotName)
1122 .arg(console.GetMachine().GetName()),
1123 formatErrorInfo(progress.GetErrorInfo()));
1124}
1125
1126void UIMessageCenter::cannotDeleteSnapshot(const CConsole &console,
1127 const QString &strSnapshotName)
1128{
1129 message(mainWindowShown(), Error,
1130 tr("Failed to delete the snapshot <b>%1</b> of the virtual machine <b>%2</b>.")
1131 .arg(strSnapshotName)
1132 .arg(CConsole(console).GetMachine().GetName()),
1133 formatErrorInfo(console));
1134}
1135
1136void UIMessageCenter::cannotDeleteSnapshot(const CProgress &progress,
1137 const QString &strSnapshotName)
1138{
1139 CConsole console(CProgress(progress).GetInitiator());
1140
1141 message(mainWindowShown(), Error,
1142 tr("Failed to delete the snapshot <b>%1</b> of the virtual machine <b>%2</b>.")
1143 .arg(strSnapshotName)
1144 .arg(console.GetMachine().GetName()),
1145 formatErrorInfo(progress.GetErrorInfo()));
1146}
1147
1148void UIMessageCenter::cannotFindSnapshotByName(QWidget *pParent,
1149 const CMachine &machine,
1150 const QString &strName) const
1151{
1152 message(pParent ? pParent : mainWindowShown(), Error,
1153 tr("Can't find snapshot named <b>%1</b>.")
1154 .arg(strName),
1155 formatErrorInfo(machine)
1156 );
1157}
1158
1159void UIMessageCenter::cannotFindMachineByName(const CVirtualBox &vbox,
1160 const QString &name)
1161{
1162 message(
1163 QApplication::desktop()->screen(QApplication::desktop()->primaryScreen()),
1164 Error,
1165 tr("There is no virtual machine named <b>%1</b>.")
1166 .arg(name),
1167 formatErrorInfo(vbox)
1168 );
1169}
1170
1171void UIMessageCenter::cannotEnterSeamlessMode(ULONG /* uWidth */,
1172 ULONG /* uHeight */,
1173 ULONG /* uBpp */,
1174 ULONG64 uMinVRAM)
1175{
1176 message(mainMachineWindowShown(), Error,
1177 tr("<p>Could not enter seamless mode due to insufficient guest "
1178 "video memory.</p>"
1179 "<p>You should configure the virtual machine to have at "
1180 "least <b>%1</b> of video memory.</p>")
1181 .arg(VBoxGlobal::formatSize(uMinVRAM)));
1182}
1183
1184int UIMessageCenter::cannotEnterFullscreenMode(ULONG /* uWidth */,
1185 ULONG /* uHeight */,
1186 ULONG /* uBpp */,
1187 ULONG64 uMinVRAM)
1188{
1189 return message(mainMachineWindowShown(), Warning,
1190 tr("<p>Could not switch the guest display to fullscreen mode due "
1191 "to insufficient guest video memory.</p>"
1192 "<p>You should configure the virtual machine to have at "
1193 "least <b>%1</b> of video memory.</p>"
1194 "<p>Press <b>Ignore</b> to switch to fullscreen mode anyway "
1195 "or press <b>Cancel</b> to cancel the operation.</p>")
1196 .arg(VBoxGlobal::formatSize(uMinVRAM)),
1197 0, /* pcszAutoConfirmId */
1198 QIMessageBox::Ignore | QIMessageBox::Default,
1199 QIMessageBox::Cancel | QIMessageBox::Escape);
1200}
1201
1202bool UIMessageCenter::cannotStartWithoutNetworkIf(const QString &strMachineName,
1203 const QString &strIfNames)
1204{
1205 return messageOkCancel(mainMachineWindowShown(), Error,
1206 tr("<p>Could not start the machine <b>%1</b> because the "
1207 "following physical network interfaces were not found:</p>"
1208 "<p><b>%2</b></p>"
1209 "<p>You can either change the machine's network "
1210 "settings or stop the machine.</p>")
1211 .arg(strMachineName)
1212 .arg(strIfNames),
1213 0, /* pcszAutoConfirmId */
1214 tr("Change Network Settings"),
1215 tr("Close Virtual Machine"));
1216}
1217
1218void UIMessageCenter::cannotSwitchScreenInSeamless(quint64 uMinVRAM)
1219{
1220 message(mainMachineWindowShown(), Error,
1221 tr("<p>Could not change the guest screen to this host screen "
1222 "due to insufficient guest video memory.</p>"
1223 "<p>You should configure the virtual machine to have at "
1224 "least <b>%1</b> of video memory.</p>")
1225 .arg(VBoxGlobal::formatSize(uMinVRAM)));
1226}
1227
1228int UIMessageCenter::cannotSwitchScreenInFullscreen(quint64 uMinVRAM)
1229{
1230 return message(mainMachineWindowShown(), Warning,
1231 tr("<p>Could not change the guest screen to this host screen "
1232 "due to insufficient guest video memory.</p>"
1233 "<p>You should configure the virtual machine to have at "
1234 "least <b>%1</b> of video memory.</p>"
1235 "<p>Press <b>Ignore</b> to switch the screen anyway "
1236 "or press <b>Cancel</b> to cancel the operation.</p>")
1237 .arg(VBoxGlobal::formatSize(uMinVRAM)),
1238 0, /* pcszAutoConfirmId */
1239 QIMessageBox::Ignore | QIMessageBox::Default,
1240 QIMessageBox::Cancel | QIMessageBox::Escape);
1241}
1242
1243int UIMessageCenter::cannotEnterFullscreenMode()
1244{
1245 return message(mainMachineWindowShown(), Error,
1246 tr("<p>Can not switch the guest display to fullscreen mode. You "
1247 "have more virtual screens configured than physical screens are "
1248 "attached to your host.</p><p>Please either lower the virtual "
1249 "screens in your VM configuration or attach additional screens "
1250 "to your host.</p>"),
1251 0, /* pcszAutoConfirmId */
1252 QIMessageBox::Ok | QIMessageBox::Default);
1253}
1254
1255int UIMessageCenter::cannotEnterSeamlessMode()
1256{
1257 return message(mainMachineWindowShown(), Error,
1258 tr("<p>Can not switch the guest display to seamless mode. You "
1259 "have more virtual screens configured than physical screens are "
1260 "attached to your host.</p><p>Please either lower the virtual "
1261 "screens in your VM configuration or attach additional screens "
1262 "to your host.</p>"),
1263 0, /* pcszAutoConfirmId */
1264 QIMessageBox::Ok | QIMessageBox::Default);
1265}
1266
1267void UIMessageCenter::notifyAboutCollisionOnGroupRemovingCantBeResolved(const QString &strName, const QString &strGroupName)
1268{
1269 message(&vboxGlobal().selectorWnd(),
1270 Error,
1271 tr("<p>You are trying to move machine <nobr><b>%1</b></nobr> "
1272 "to group <nobr><b>%2</b></nobr> which already have sub-group <nobr><b>%1</b></nobr>.</p>"
1273 "<p>Please resolve this name-conflict and try again.</p>")
1274 .arg(strName, strGroupName),
1275 0, /* auto-confirm id */
1276 QIMessageBox::Ok | QIMessageBox::Default);
1277}
1278
1279int UIMessageCenter::askAboutCollisionOnGroupRemoving(const QString &strName, const QString &strGroupName)
1280{
1281 return message(&vboxGlobal().selectorWnd(),
1282 Question,
1283 tr("<p>You are trying to move group <nobr><b>%1</b></nobr> "
1284 "to group <nobr><b>%2</b></nobr> which already have another item with the same name.</p>"
1285 "<p>Would you like to automatically rename it?</p>")
1286 .arg(strName, strGroupName),
1287 0, /* auto-confirm id */
1288 QIMessageBox::Ok,
1289 QIMessageBox::Cancel | QIMessageBox::Escape | QIMessageBox::Default,
1290 0,
1291 tr("Rename"));
1292}
1293
1294int UIMessageCenter::confirmMachineItemRemoval(const QStringList &names)
1295{
1296 return message(&vboxGlobal().selectorWnd(),
1297 Question,
1298 tr("<p>You are about to remove following virtual "
1299 "machine items from the machine list:</p>"
1300 "<p><b>%1</b></p>"
1301 "<p>Do you wish to proceed?</p>").arg(names.join(", ")),
1302 0, /* auto-confirm id */
1303 QIMessageBox::Ok,
1304 QIMessageBox::Cancel | QIMessageBox::Escape | QIMessageBox::Default,
1305 0,
1306 tr("Remove"));
1307}
1308
1309int UIMessageCenter::confirmMachineDeletion(const QList<CMachine> &machines)
1310{
1311 /* Enumerate VMs: */
1312 int cInacessibleVMCount = 0;
1313 bool fVMWithHDPresent = false;
1314 QString strVMNames;
1315 for (int i = 0; i < machines.size(); ++i)
1316 {
1317 /* Get iterated VM: */
1318 const CMachine &machine = machines[i];
1319 /* Prepare VM name: */
1320 QString strMachineName;
1321 if (machine.GetAccessible())
1322 {
1323 /* Get VM name: */
1324 strMachineName = machine.GetName();
1325 /* Enumerate attachments: */
1326 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments();
1327 for (int i = 0; !fVMWithHDPresent && i < attachments.size(); ++i)
1328 {
1329 /* Get current attachment: */
1330 const CMediumAttachment &attachment = attachments.at(i);
1331 /* Check if the medium is a hard disk: */
1332 if (attachment.GetType() == KDeviceType_HardDisk)
1333 {
1334 /* Check if that hard disk isn't shared.
1335 * If hard disk is shared, it will *never* be deleted: */
1336 QVector<QString> ids = attachment.GetMedium().GetMachineIds();
1337 if (ids.size() == 1)
1338 {
1339 fVMWithHDPresent = true;
1340 break;
1341 }
1342 }
1343 }
1344 }
1345 else
1346 {
1347 /* Get VM name: */
1348 QFileInfo fi(machine.GetSettingsFilePath());
1349 strMachineName = VBoxGlobal::hasAllowedExtension(fi.completeSuffix(), VBoxFileExts) ? fi.completeBaseName() : fi.fileName();
1350 /* Increment inacessible VM count: */
1351 ++cInacessibleVMCount;
1352 }
1353
1354 /* Compose VM name list: */
1355 strVMNames += QString(strVMNames.isEmpty() ? "<b>%1</b>" : ", <b>%1</b>").arg(strMachineName);
1356 }
1357
1358 /* Prepare message text: */
1359 QString strText = cInacessibleVMCount == machines.size() ?
1360 tr("<p>You are about to remove following inaccessible virtual machines from the machine list:</p>"
1361 "<p>%1</p>"
1362 "<p>Do you wish to proceed?</p>")
1363 .arg(strVMNames) :
1364 fVMWithHDPresent ?
1365 tr("<p>You are about to remove following virtual machines from the machine list:</p>"
1366 "<p>%1</p>"
1367 "<p>Would you like to delete the files containing the virtual machine from your hard disk as well? "
1368 "Doing this will also remove the files containing the machine's virtual hard disks "
1369 "if they are not in use by another machine.</p>")
1370 .arg(strVMNames) :
1371 tr("<p>You are about to remove following virtual machines from the machine list:</p>"
1372 "<p>%1</p>"
1373 "<p>Would you like to delete the files containing the virtual machine from your hard disk as well?</p>")
1374 .arg(strVMNames);
1375
1376 /* Prepare message itself: */
1377 return cInacessibleVMCount == machines.size() ?
1378 message(&vboxGlobal().selectorWnd(),
1379 Question,
1380 strText,
1381 0, /* auto-confirm id */
1382 QIMessageBox::Ok,
1383 QIMessageBox::Cancel | QIMessageBox::Escape | QIMessageBox::Default,
1384 0,
1385 tr("Remove")) :
1386 message(&vboxGlobal().selectorWnd(),
1387 Question,
1388 strText,
1389 0, /* auto-confirm id */
1390 QIMessageBox::Yes,
1391 QIMessageBox::No,
1392 QIMessageBox::Cancel | QIMessageBox::Escape | QIMessageBox::Default,
1393 tr("Delete all files"),
1394 tr("Remove only"));
1395}
1396
1397bool UIMessageCenter::confirmDiscardSavedState(const QString &strNames)
1398{
1399 return messageOkCancel(&vboxGlobal().selectorWnd(), Question,
1400 tr("<p>Are you sure you want to discard the saved state of "
1401 "the following virtual machines?</p><p><b>%1</b></p>"
1402 "<p>This operation is equivalent to resetting or powering off "
1403 "the machine without doing a proper shutdown of the guest OS.</p>")
1404 .arg(strNames),
1405 0 /* pcszAutoConfirmId */,
1406 tr("Discard", "saved state"));
1407}
1408
1409void UIMessageCenter::cannotSetGroups(const CMachine &machine)
1410{
1411 COMResult res(machine);
1412 QString name = machine.GetName();
1413 if (name.isEmpty())
1414 name = QFileInfo(machine.GetSettingsFilePath()).baseName();
1415
1416 message(mainWindowShown(), Error,
1417 tr("Failed to set groups of the virtual machine <b>%1</b>.").arg(name),
1418 formatErrorInfo(res));
1419}
1420
1421void UIMessageCenter::cannotChangeMediumType(QWidget *pParent,
1422 const CMedium &medium,
1423 KMediumType oldMediumType,
1424 KMediumType newMediumType)
1425{
1426 message(pParent ? pParent : mainWindowShown(), Error,
1427 tr("<p>Error changing medium type from <b>%1</b> to <b>%2</b>.</p>")
1428 .arg(gpConverter->toString(oldMediumType)).arg(gpConverter->toString(newMediumType)),
1429 formatErrorInfo(medium));
1430}
1431
1432bool UIMessageCenter::confirmReleaseMedium(QWidget *pParent,
1433 const UIMedium &aMedium,
1434 const QString &strUsage)
1435{
1436 /** @todo (translation-related): the gender of "the" in translations
1437 * will depend on the gender of aMedium.type(). */
1438 return messageOkCancel(pParent, Question,
1439 tr("<p>Are you sure you want to release the %1 "
1440 "<nobr><b>%2</b></nobr>?</p>"
1441 "<p>This will detach it from the "
1442 "following virtual machine(s): <b>%3</b>.</p>")
1443 .arg(mediumToAccusative(aMedium.type()))
1444 .arg(aMedium.location())
1445 .arg(strUsage),
1446 0 /* pcszAutoConfirmId */,
1447 tr("Release", "detach medium"));
1448}
1449
1450bool UIMessageCenter::confirmRemoveMedium(QWidget *pParent,
1451 const UIMedium &aMedium)
1452{
1453 /** @todo (translation-related): the gender of "the" in translations
1454 * will depend on the gender of aMedium.type(). */
1455 QString msg =
1456 tr("<p>Are you sure you want to remove the %1 "
1457 "<nobr><b>%2</b></nobr> from the list of known media?</p>")
1458 .arg(mediumToAccusative(aMedium.type()))
1459 .arg(aMedium.location());
1460
1461 if (aMedium.type() == UIMediumType_HardDisk &&
1462 aMedium.medium().GetMediumFormat().GetCapabilities() & MediumFormatCapabilities_File)
1463 {
1464 if (aMedium.state() == KMediumState_Inaccessible)
1465 msg +=
1466 tr("Note that as this hard disk is inaccessible its "
1467 "storage unit cannot be deleted right now.");
1468 else
1469 msg +=
1470 tr("The next dialog will let you choose whether you also "
1471 "want to delete the storage unit of this hard disk or "
1472 "keep it for later usage.");
1473 }
1474 else
1475 msg +=
1476 tr("<p>Note that the storage unit of this medium will not be "
1477 "deleted and that it will be possible to use it later again.</p>");
1478
1479 return messageOkCancel(pParent, Question, msg,
1480 "confirmRemoveMedium", /* pcszAutoConfirmId */
1481 tr("Remove", "medium"));
1482}
1483
1484void UIMessageCenter::sayCannotOverwriteHardDiskStorage(QWidget *pParent,
1485 const QString &strLocation)
1486{
1487 message(pParent, Info,
1488 tr("<p>The hard disk storage unit at location <b>%1</b> already "
1489 "exists. You cannot create a new virtual hard disk that uses this "
1490 "location because it can be already used by another virtual hard "
1491 "disk.</p>"
1492 "<p>Please specify a different location.</p>")
1493 .arg(strLocation));
1494}
1495
1496int UIMessageCenter::confirmDeleteHardDiskStorage(QWidget *pParent, const QString &strLocation)
1497{
1498 return message(pParent, Question,
1499 tr("<p>Do you want to delete the storage unit of the hard disk "
1500 "<nobr><b>%1</b></nobr>?</p>"
1501 "<p>If you select <b>Delete</b> then the specified storage unit "
1502 "will be permanently deleted. This operation <b>cannot be "
1503 "undone</b>.</p>"
1504 "<p>If you select <b>Keep</b> then the hard disk will be only "
1505 "removed from the list of known hard disks, but the storage unit "
1506 "will be left untouched which makes it possible to add this hard "
1507 "disk to the list later again.</p>")
1508 .arg(strLocation),
1509 0, /* pcszAutoConfirmId */
1510 QIMessageBox::Yes,
1511 QIMessageBox::No | QIMessageBox::Default,
1512 QIMessageBox::Cancel | QIMessageBox::Escape,
1513 tr("Delete", "hard disk storage"),
1514 tr("Keep", "hard disk storage"));
1515}
1516
1517void UIMessageCenter::cannotDeleteHardDiskStorage(QWidget *pParent,
1518 const CMedium &medium,
1519 const CProgress &progress)
1520{
1521 /* below, we use CMedium (medium) to preserve current error info
1522 * for formatErrorInfo() */
1523
1524 message(pParent, Error,
1525 tr("Failed to delete the storage unit of the hard disk <b>%1</b>.")
1526 .arg(CMedium(medium).GetLocation()),
1527 !medium.isOk() ? formatErrorInfo(medium) :
1528 !progress.isOk() ? formatErrorInfo(progress) :
1529 formatErrorInfo(progress.GetErrorInfo()));
1530}
1531
1532int UIMessageCenter::askAboutHardDiskAttachmentCreation(QWidget *pParent,
1533 const QString &strControllerName)
1534{
1535 return message(pParent, Question,
1536 tr("<p>You are about to add a virtual hard disk to controller <b>%1</b>.</p>"
1537 "<p>Would you like to create a new, empty file to hold the disk contents or select an existing one?</p>")
1538 .arg(strControllerName),
1539 0, /* pcszAutoConfirmId */
1540 QIMessageBox::Yes,
1541 QIMessageBox::No,
1542 QIMessageBox::Cancel | QIMessageBox::Default | QIMessageBox::Escape,
1543 tr("Create &new disk", "add attachment routine"),
1544 tr("&Choose existing disk", "add attachment routine"));
1545}
1546
1547int UIMessageCenter::askAboutOpticalAttachmentCreation(QWidget *pParent,
1548 const QString &strControllerName)
1549{
1550 return message(pParent, Question,
1551 tr("<p>You are about to add a new CD/DVD drive to controller <b>%1</b>.</p>"
1552 "<p>Would you like to choose a virtual CD/DVD disk to put in the drive "
1553 "or to leave it empty for now?</p>")
1554 .arg(strControllerName),
1555 0, /* pcszAutoConfirmId */
1556 QIMessageBox::Yes,
1557 QIMessageBox::No,
1558 QIMessageBox::Cancel | QIMessageBox::Default | QIMessageBox::Escape,
1559 tr("&Choose disk", "add attachment routine"),
1560 tr("Leave &empty", "add attachment routine"));
1561}
1562
1563int UIMessageCenter::askAboutFloppyAttachmentCreation(QWidget *pParent,
1564 const QString &strControllerName)
1565{
1566 return message(pParent, Question,
1567 tr("<p>You are about to add a new floppy drive to controller <b>%1</b>.</p>"
1568 "<p>Would you like to choose a virtual floppy disk to put in the drive "
1569 "or to leave it empty for now?</p>")
1570 .arg(strControllerName),
1571 0, /* pcszAutoConfirmId */
1572 QIMessageBox::Yes,
1573 QIMessageBox::No,
1574 QIMessageBox::Cancel | QIMessageBox::Default | QIMessageBox::Escape,
1575 tr("&Choose disk", "add attachment routine"),
1576 tr("Leave &empty", "add attachment routine"));
1577}
1578
1579int UIMessageCenter::confirmRemovingOfLastDVDDevice() const
1580{
1581 return messageOkCancel(QApplication::activeWindow(), Info,
1582 tr("<p>Are you sure you want to delete the CD/DVD-ROM device?</p>"
1583 "<p>You will not be able to mount any CDs or ISO images "
1584 "or install the Guest Additions without it!</p>"),
1585 0, /* pcszAutoConfirmId */
1586 tr("&Remove", "medium"));
1587}
1588
1589void UIMessageCenter::cannotCreateHardDiskStorage(QWidget *pParent,
1590 const CVirtualBox &vbox,
1591 const QString &strLocation,
1592 const CMedium &medium,
1593 const CProgress &progress)
1594{
1595 message(pParent, Error,
1596 tr("Failed to create the hard disk storage <nobr><b>%1</b>.</nobr>")
1597 .arg(strLocation),
1598 !vbox.isOk() ? formatErrorInfo(vbox) :
1599 !medium.isOk() ? formatErrorInfo(medium) :
1600 !progress.isOk() ? formatErrorInfo(progress) :
1601 formatErrorInfo(progress.GetErrorInfo()));
1602}
1603
1604void UIMessageCenter::cannotDetachDevice(QWidget *pParent,
1605 const CMachine &machine,
1606 UIMediumType type,
1607 const QString &strLocation,
1608 const StorageSlot &storageSlot)
1609{
1610 QString strMessage;
1611 switch (type)
1612 {
1613 case UIMediumType_HardDisk:
1614 {
1615 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>.")
1616 .arg(strLocation).arg(gpConverter->toString(storageSlot)).arg(CMachine(machine).GetName());
1617 break;
1618 }
1619 case UIMediumType_DVD:
1620 {
1621 strMessage = tr("Failed to detach the CD/DVD device (<nobr><b>%1</b></nobr>) from the slot <i>%2</i> of the machine <b>%3</b>.")
1622 .arg(strLocation).arg(gpConverter->toString(storageSlot)).arg(CMachine(machine).GetName());
1623 break;
1624 }
1625 case UIMediumType_Floppy:
1626 {
1627 strMessage = tr("Failed to detach the floppy device (<nobr><b>%1</b></nobr>) from the slot <i>%2</i> of the machine <b>%3</b>.")
1628 .arg(strLocation).arg(gpConverter->toString(storageSlot)).arg(CMachine(machine).GetName());
1629 break;
1630 }
1631 default:
1632 break;
1633 }
1634 message(pParent ? pParent : mainWindowShown(), Error, strMessage, formatErrorInfo(machine));
1635}
1636
1637int UIMessageCenter::cannotRemountMedium(QWidget *pParent,
1638 const CMachine &machine,
1639 const UIMedium &aMedium,
1640 bool fMount,
1641 bool fRetry)
1642{
1643 /** @todo (translation-related): the gender of "the" in translations
1644 * will depend on the gender of aMedium.type(). */
1645 QString text;
1646 if (fMount)
1647 {
1648 text = tr("Unable to mount the %1 <nobr><b>%2</b></nobr> on the machine <b>%3</b>.");
1649 if (fRetry) text += tr(" Would you like to force mounting of this medium?");
1650 }
1651 else
1652 {
1653 text = tr("Unable to unmount the %1 <nobr><b>%2</b></nobr> from the machine <b>%3</b>.");
1654 if (fRetry) text += tr(" Would you like to force unmounting of this medium?");
1655 }
1656 if (fRetry)
1657 {
1658 return messageOkCancel(pParent ? pParent : mainWindowShown(), Question, text
1659 .arg(mediumToAccusative(aMedium.type(), aMedium.isHostDrive()))
1660 .arg(aMedium.isHostDrive() ? aMedium.name() : aMedium.location())
1661 .arg(CMachine(machine).GetName()),
1662 formatErrorInfo(machine),
1663 0 /* Auto Confirm ID */,
1664 tr("Force Unmount"));
1665 }
1666 else
1667 {
1668 return message(pParent ? pParent : mainWindowShown(), Error, text
1669 .arg(mediumToAccusative(aMedium.type(), aMedium.isHostDrive()))
1670 .arg(aMedium.isHostDrive() ? aMedium.name() : aMedium.location())
1671 .arg(CMachine(machine).GetName()),
1672 formatErrorInfo(machine));
1673 }
1674}
1675
1676void UIMessageCenter::cannotOpenMedium(QWidget *pParent,
1677 const CVirtualBox &vbox,
1678 UIMediumType type,
1679 const QString &strLocation)
1680{
1681 /** @todo (translation-related): the gender of "the" in translations
1682 * will depend on the gender of aMedium.type(). */
1683 message(pParent ? pParent : mainWindowShown(), Error,
1684 tr("Failed to open the %1 <nobr><b>%2</b></nobr>.")
1685 .arg(mediumToAccusative(type))
1686 .arg(strLocation),
1687 formatErrorInfo(vbox));
1688}
1689
1690void UIMessageCenter::cannotCloseMedium(QWidget *pParent,
1691 const UIMedium &aMedium,
1692 const COMResult &rc)
1693{
1694 /** @todo (translation-related): the gender of "the" in translations
1695 * will depend on the gender of aMedium.type(). */
1696 message(pParent, Error,
1697 tr("Failed to close the %1 <nobr><b>%2</b></nobr>.")
1698 .arg(mediumToAccusative(aMedium.type()))
1699 .arg(aMedium.location()),
1700 formatErrorInfo(rc));
1701}
1702
1703void UIMessageCenter::cannotOpenSession(const CSession &session)
1704{
1705 Assert(session.isNull());
1706
1707 message(
1708 mainWindowShown(),
1709 Error,
1710 tr("Failed to create a new session."),
1711 formatErrorInfo(session)
1712 );
1713}
1714
1715void UIMessageCenter::cannotOpenSession(const CVirtualBox &vbox,
1716 const CMachine &machine,
1717 const CProgress &progress)
1718{
1719 Assert(!vbox.isOk() || progress.isOk());
1720
1721 QString name = machine.GetName();
1722 if (name.isEmpty())
1723 name = QFileInfo(machine.GetSettingsFilePath()).baseName();
1724
1725 message(
1726 mainWindowShown(),
1727 Error,
1728 tr("Failed to open a session for the virtual machine <b>%1</b>.")
1729 .arg(name),
1730 !vbox.isOk() ? formatErrorInfo(vbox) :
1731 formatErrorInfo(progress.GetErrorInfo())
1732 );
1733}
1734
1735void UIMessageCenter::cannotOpenSession(const CMachine &machine)
1736{
1737 COMResult res(machine);
1738 QString name = machine.GetName();
1739 if (name.isEmpty())
1740 name = QFileInfo(machine.GetSettingsFilePath()).baseName();
1741
1742 message(mainWindowShown(), Error,
1743 tr("Failed to open a session for the virtual machine <b>%1</b>.").arg(name),
1744 formatErrorInfo(res));
1745}
1746
1747void UIMessageCenter::cannotGetMediaAccessibility(const UIMedium &aMedium)
1748{
1749 message(qApp->activeWindow(), Error,
1750 tr("Failed to determine the accessibility state of the medium "
1751 "<nobr><b>%1</b></nobr>.")
1752 .arg(aMedium.location()),
1753 formatErrorInfo(aMedium.result()));
1754}
1755
1756int UIMessageCenter::confirmDeletingHostInterface(const QString &strName,
1757 QWidget *pParent)
1758{
1759 return msgCenter().message(pParent, UIMessageCenter::Question,
1760 tr("<p>Deleting this host-only network will remove "
1761 "the host-only interface this network is based on. Do you want to "
1762 "remove the (host-only network) interface <nobr><b>%1</b>?</nobr></p>"
1763 "<p><b>Note:</b> this interface may be in use by one or more "
1764 "virtual network adapters belonging to one of your VMs. "
1765 "After it is removed, these adapters will no longer be usable until "
1766 "you correct their settings by either choosing a different interface "
1767 "name or a different adapter attachment type.</p>").arg(strName),
1768 0, /* pcszAutoConfirmId */
1769 QIMessageBox::Ok | QIMessageBox::Default,
1770 QIMessageBox::Cancel | QIMessageBox::Escape);
1771}
1772
1773void UIMessageCenter::cannotAttachUSBDevice(const CConsole &console,
1774 const QString &device)
1775{
1776 /* preserve the current error info before calling the object again */
1777 COMResult res(console);
1778
1779 message(mainMachineWindowShown(), Error,
1780 tr("Failed to attach the USB device <b>%1</b> "
1781 "to the virtual machine <b>%2</b>.")
1782 .arg(device)
1783 .arg(console.GetMachine().GetName()),
1784 formatErrorInfo(res));
1785}
1786
1787void UIMessageCenter::cannotAttachUSBDevice(const CConsole &console,
1788 const QString &device,
1789 const CVirtualBoxErrorInfo &error)
1790{
1791 message(mainMachineWindowShown(), Error,
1792 tr("Failed to attach the USB device <b>%1</b> "
1793 "to the virtual machine <b>%2</b>.")
1794 .arg(device)
1795 .arg(console.GetMachine().GetName()),
1796 formatErrorInfo(error));
1797}
1798
1799void UIMessageCenter::cannotDetachUSBDevice(const CConsole &console,
1800 const QString &device)
1801{
1802 /* preserve the current error info before calling the object again */
1803 COMResult res(console);
1804
1805 message(mainMachineWindowShown(), Error,
1806 tr("Failed to detach the USB device <b>%1</b> "
1807 "from the virtual machine <b>%2</b>.")
1808 .arg(device)
1809 .arg(console.GetMachine().GetName()),
1810 formatErrorInfo(res));
1811}
1812
1813void UIMessageCenter::cannotDetachUSBDevice(const CConsole &console,
1814 const QString &device,
1815 const CVirtualBoxErrorInfo &error)
1816{
1817 message(mainMachineWindowShown(), Error,
1818 tr("Failed to detach the USB device <b>%1</b> "
1819 "from the virtual machine <b>%2</b>.")
1820 .arg(device)
1821 .arg(console.GetMachine().GetName()),
1822 formatErrorInfo(error));
1823}
1824
1825void UIMessageCenter::remindAboutGuestAdditionsAreNotActive(QWidget *pParent)
1826{
1827 message(pParent, Warning,
1828 tr("<p>The VirtualBox Guest Additions do not appear to be "
1829 "available on this virtual machine, and shared folders "
1830 "cannot be used without them. To use shared folders inside "
1831 "the virtual machine, please install the Guest Additions "
1832 "if they are not installed, or re-install them if they are "
1833 "not working correctly, by selecting <b>Install Guest Additions</b> "
1834 "from the <b>Devices</b> menu. "
1835 "If they are installed but the machine is not yet fully started "
1836 "then shared folders will be available once it is.</p>"),
1837 "remindAboutGuestAdditionsAreNotActive");
1838}
1839
1840bool UIMessageCenter::cannotFindGuestAdditions()
1841{
1842 return messageYesNo(mainMachineWindowShown(), Question,
1843 tr("<p>Could not find the VirtualBox Guest Additions "
1844 "CD image file.</nobr></p><p>Do you wish to "
1845 "download this CD image from the Internet?</p>"));
1846}
1847
1848void UIMessageCenter::cannotMountGuestAdditions(const QString &strMachineName)
1849{
1850 message(mainMachineWindowShown(), Error,
1851 tr("<p>Could not insert the VirtualBox Guest Additions "
1852 "installer CD image into the virtual machine <b>%1</b>, as the machine "
1853 "has no CD/DVD-ROM drives. Please add a drive using the "
1854 "storage page of the virtual machine settings dialog.</p>")
1855 .arg(strMachineName));
1856}
1857
1858bool UIMessageCenter::confirmDownloadAdditions(const QString &strUrl, qulonglong uSize)
1859{
1860 QLocale loc(VBoxGlobal::languageId());
1861 return messageOkCancel(networkManagerOrMainMachineWindowShown(), Question,
1862 tr("<p>Are you sure you want to download the VirtualBox "
1863 "Guest Additions CD image from "
1864 "<nobr><a href=\"%1\">%2</a></nobr> "
1865 "(size %3 bytes)?</p>").arg(strUrl).arg(strUrl).arg(loc.toString(uSize)),
1866 0, /* pcszAutoConfirmId */
1867 tr("Download", "additions"));
1868}
1869
1870bool UIMessageCenter::confirmMountAdditions(const QString &strUrl, const QString &strSrc)
1871{
1872 return messageOkCancel(networkManagerOrMainMachineWindowShown(), Question,
1873 tr("<p>The VirtualBox Guest Additions CD image has been "
1874 "successfully downloaded from "
1875 "<nobr><a href=\"%1\">%2</a></nobr> "
1876 "and saved locally as <nobr><b>%3</b>.</nobr></p>"
1877 "<p>Do you wish to register this CD image and mount it "
1878 "on the virtual CD/DVD drive?</p>")
1879 .arg(strUrl).arg(strUrl).arg(strSrc),
1880 0, /* pcszAutoConfirmId */
1881 tr("Mount", "additions"));
1882}
1883
1884void UIMessageCenter::warnAboutAdditionsCantBeSaved(const QString &strTarget)
1885{
1886 message(networkManagerOrMainMachineWindowShown(), Error,
1887 tr("<p>Failed to save the downloaded file as <nobr><b>%1</b>.</nobr></p>")
1888 .arg(QDir::toNativeSeparators(strTarget)));
1889}
1890
1891bool UIMessageCenter::askAboutUserManualDownload(const QString &strMissedLocation)
1892{
1893 return messageOkCancel(mainWindowShown(), Question,
1894 tr("<p>Could not find the VirtualBox User Manual "
1895 "<nobr><b>%1</b>.</nobr></p><p>Do you wish to "
1896 "download this file from the Internet?</p>")
1897 .arg(strMissedLocation),
1898 0, /* Auto-confirm Id */
1899 tr("Download", "additions"));
1900}
1901
1902bool UIMessageCenter::confirmUserManualDownload(const QString &strURL, qulonglong uSize)
1903{
1904 QLocale loc(VBoxGlobal::languageId());
1905 return messageOkCancel(networkManagerOrMainWindowShown(), Question,
1906 tr("<p>Are you sure you want to download the VirtualBox "
1907 "User Manual from "
1908 "<nobr><a href=\"%1\">%2</a></nobr> "
1909 "(size %3 bytes)?</p>").arg(strURL).arg(strURL).arg(loc.toString(uSize)),
1910 0, /* Auto-confirm Id */
1911 tr("Download", "additions"));
1912}
1913
1914void UIMessageCenter::warnAboutUserManualDownloaded(const QString &strURL, const QString &strTarget)
1915{
1916 message(networkManagerOrMainWindowShown(), Warning,
1917 tr("<p>The VirtualBox User Manual has been "
1918 "successfully downloaded from "
1919 "<nobr><a href=\"%1\">%2</a></nobr> "
1920 "and saved locally as <nobr><b>%3</b>.</nobr></p>")
1921 .arg(strURL).arg(strURL).arg(strTarget));
1922}
1923
1924void UIMessageCenter::warnAboutUserManualCantBeSaved(const QString &strURL, const QString &strTarget)
1925{
1926 message(networkManagerOrMainWindowShown(), Error,
1927 tr("<p>The VirtualBox User Manual has been "
1928 "successfully downloaded from "
1929 "<nobr><a href=\"%1\">%2</a></nobr> "
1930 "but can't be saved locally as <nobr><b>%3</b>.</nobr></p>"
1931 "<p>Please choose another location for that file.</p>")
1932 .arg(strURL).arg(strURL).arg(strTarget));
1933}
1934
1935bool UIMessageCenter::proposeDownloadExtensionPack(const QString &strExtPackName, const QString &strExtPackVersion)
1936{
1937 return messageOkCancel(mainWindowShown(),
1938 Question,
1939 tr("<p>You have an old version (%1) of the <b><nobr>%2</nobr></b> installed.</p>"
1940 "<p>Do you wish to download latest one from the Internet?</p>")
1941 .arg(strExtPackVersion).arg(strExtPackName),
1942 0, /* Auto-confirm Id */
1943 tr("Download", "extension pack"));
1944}
1945
1946bool UIMessageCenter::requestUserDownloadExtensionPack(const QString &strExtPackName, const QString &strExtPackVersion, const QString &strVBoxVersion)
1947{
1948 return message(mainWindowShown(), Info,
1949 tr("<p>You have version %1 of the <b><nobr>%2</nobr></b> installed.</p>"
1950 "<p>You should download and install version %3 of this extension pack from Oracle!</p>")
1951 .arg(strExtPackVersion).arg(strExtPackName).arg(strVBoxVersion),
1952 0, /* Auto-confirm Id */
1953 QIMessageBox::Ok | QIMessageBox::Default,
1954 0,
1955 0,
1956 tr("Ok", "extension pack"));
1957}
1958
1959bool UIMessageCenter::confirmDownloadExtensionPack(const QString &strExtPackName, const QString &strURL, qulonglong uSize)
1960{
1961 QLocale loc(VBoxGlobal::languageId());
1962 return messageOkCancel(networkManagerOrMainWindowShown(), Question,
1963 tr("<p>Are you sure you want to download the <b><nobr>%1</nobr></b> "
1964 "from <nobr><a href=\"%2\">%2</a></nobr> (size %3 bytes)?</p>")
1965 .arg(strExtPackName, strURL, loc.toString(uSize)),
1966 0, /* Auto-confirm Id */
1967 tr("Download", "extension pack"));
1968}
1969
1970bool UIMessageCenter::proposeInstallExtentionPack(const QString &strExtPackName, const QString &strFrom, const QString &strTo)
1971{
1972 return messageOkCancel(networkManagerOrMainWindowShown(), Question,
1973 tr("<p>The <b><nobr>%1</nobr></b> has been "
1974 "successfully downloaded from <nobr><a href=\"%2\">%2</a></nobr> "
1975 "and saved locally as <nobr><b>%3</b>.</nobr></p>"
1976 "<p>Do you wish to install this extension pack?</p>")
1977 .arg(strExtPackName, strFrom, strTo),
1978 0, /* Auto-confirm Id */
1979 tr ("Install", "extension pack"));
1980}
1981
1982void UIMessageCenter::warnAboutExtentionPackCantBeSaved(const QString &strExtPackName, const QString &strFrom, const QString &strTo)
1983{
1984 message(networkManagerOrMainWindowShown(), Error,
1985 tr("<p>The <b><nobr>%1</nobr></b> has been "
1986 "successfully downloaded from <nobr><a href=\"%2\">%2</a></nobr> "
1987 "but can't be saved locally as <nobr><b>%3</b>.</nobr></p>"
1988 "<p>Please choose another location for that file.</p>")
1989 .arg(strExtPackName, strFrom, strTo));
1990}
1991
1992void UIMessageCenter::cannotConnectRegister(QWidget *pParent,
1993 const QString &strUrl,
1994 const QString &strReason)
1995{
1996 /* we don't want to expose the registration script URL to the user
1997 * if he simply doesn't have an internet connection */
1998 Q_UNUSED(strUrl);
1999
2000 message(pParent, Error,
2001 tr("<p>Failed to connect to the VirtualBox online "
2002 "registration service due to the following error:</p><p><b>%1</b></p>")
2003 .arg(strReason));
2004}
2005
2006void UIMessageCenter::showRegisterResult(QWidget *pParent,
2007 const QString &strResult)
2008{
2009 if (strResult == "OK")
2010 {
2011 /* On successful registration attempt */
2012 message(pParent, Info,
2013 tr("<p>Congratulations! You have been successfully registered "
2014 "as a user of VirtualBox.</p>"
2015 "<p>Thank you for finding time to fill out the "
2016 "registration form!</p>"));
2017 }
2018 else
2019 {
2020 QString parsed;
2021
2022 /* Else parse and translate special key-words */
2023 if (strResult == "AUTHFAILED")
2024 parsed = tr("<p>Invalid e-mail address or password specified.</p>");
2025
2026 message(pParent, Error,
2027 tr("<p>Failed to register the VirtualBox product.</p><p>%1</p>")
2028 .arg(parsed.isNull() ? strResult : parsed));
2029 }
2030}
2031
2032void UIMessageCenter::showUpdateSuccess(const QString &strVersion, const QString &strLink)
2033{
2034 message(networkManagerOrMainWindowShown(), Info,
2035 tr("<p>A new version of VirtualBox has been released! Version <b>%1</b> is available at <a href=\"http://www.virtualbox.org/\">virtualbox.org</a>.</p>"
2036 "<p>You can download this version using the link:</p>"
2037 "<p><a href=%2>%3</a></p>")
2038 .arg(strVersion, strLink, strLink));
2039}
2040
2041void UIMessageCenter::showUpdateNotFound()
2042{
2043 message(networkManagerOrMainWindowShown(), Info,
2044 tr("You are already running the most recent version of VirtualBox."));
2045}
2046
2047bool UIMessageCenter::askAboutCancelAllNetworkRequest(QWidget *pParent)
2048{
2049 return messageOkCancel(pParent, Question, tr("Do you wish to cancel all current network operations?"));
2050}
2051
2052/**
2053 * @return @c true if the user has confirmed input capture (this is always
2054 * the case if the dialog was autoconfirmed). @a pfAutoConfirmed, when not
2055 * NULL, will receive @c true if the dialog wasn't actually shown.
2056 */
2057bool UIMessageCenter::confirmInputCapture(bool *pfAutoConfirmed /* = NULL */)
2058{
2059 int rc = message(mainMachineWindowShown(), Info,
2060 tr("<p>You have <b>clicked the mouse</b> inside the Virtual Machine display "
2061 "or pressed the <b>host key</b>. This will cause the Virtual Machine to "
2062 "<b>capture</b> the host mouse pointer (only if the mouse pointer "
2063 "integration is not currently supported by the guest OS) and the "
2064 "keyboard, which will make them unavailable to other applications "
2065 "running on your host machine."
2066 "</p>"
2067 "<p>You can press the <b>host key</b> at any time to <b>uncapture</b> the "
2068 "keyboard and mouse (if it is captured) and return them to normal "
2069 "operation. The currently assigned host key is shown on the status bar "
2070 "at the bottom of the Virtual Machine window, next to the&nbsp;"
2071 "<img src=:/hostkey_16px.png/>&nbsp;icon. This icon, together "
2072 "with the mouse icon placed nearby, indicate the current keyboard "
2073 "and mouse capture state."
2074 "</p>") +
2075 tr("<p>The host key is currently defined as <b>%1</b>.</p>",
2076 "additional message box paragraph")
2077 .arg(UIHotKeyCombination::toReadableString(vboxGlobal().settings().hostCombo())),
2078 "confirmInputCapture",
2079 QIMessageBox::Ok | QIMessageBox::Default,
2080 QIMessageBox::Cancel | QIMessageBox::Escape,
2081 0,
2082 tr("Capture", "do input capture"));
2083
2084 if (pfAutoConfirmed)
2085 *pfAutoConfirmed = (rc & AutoConfirmed);
2086
2087 return (rc & QIMessageBox::ButtonMask) == QIMessageBox::Ok;
2088}
2089
2090void UIMessageCenter::remindAboutAutoCapture()
2091{
2092 message(mainMachineWindowShown(), Info,
2093 tr("<p>You have the <b>Auto capture keyboard</b> option turned on. "
2094 "This will cause the Virtual Machine to automatically <b>capture</b> "
2095 "the keyboard every time the VM window is activated and make it "
2096 "unavailable to other applications running on your host machine: "
2097 "when the keyboard is captured, all keystrokes (including system ones "
2098 "like Alt-Tab) will be directed to the VM."
2099 "</p>"
2100 "<p>You can press the <b>host key</b> at any time to <b>uncapture</b> the "
2101 "keyboard and mouse (if it is captured) and return them to normal "
2102 "operation. The currently assigned host key is shown on the status bar "
2103 "at the bottom of the Virtual Machine window, next to the&nbsp;"
2104 "<img src=:/hostkey_16px.png/>&nbsp;icon. This icon, together "
2105 "with the mouse icon placed nearby, indicate the current keyboard "
2106 "and mouse capture state."
2107 "</p>") +
2108 tr("<p>The host key is currently defined as <b>%1</b>.</p>",
2109 "additional message box paragraph")
2110 .arg(UIHotKeyCombination::toReadableString(vboxGlobal().settings().hostCombo())),
2111 "remindAboutAutoCapture");
2112}
2113
2114void UIMessageCenter::remindAboutMouseIntegration(bool fSupportsAbsolute)
2115{
2116 if (isAlreadyShown("remindAboutMouseIntegration"))
2117 return;
2118 setShownStatus("remindAboutMouseIntegration");
2119
2120 static const char *kNames [2] =
2121 {
2122 "remindAboutMouseIntegrationOff",
2123 "remindAboutMouseIntegrationOn"
2124 };
2125
2126 /* Close the previous (outdated) window if any. We use kName as
2127 * pcszAutoConfirmId which is also used as the widget name by default. */
2128 {
2129 QWidget *outdated =
2130 VBoxGlobal::findWidget(NULL, kNames [int (!fSupportsAbsolute)],
2131 "QIMessageBox");
2132 if (outdated)
2133 outdated->close();
2134 }
2135
2136 if (fSupportsAbsolute)
2137 {
2138 message(mainMachineWindowShown(), Info,
2139 tr("<p>The Virtual Machine reports that the guest OS supports "
2140 "<b>mouse pointer integration</b>. This means that you do not "
2141 "need to <i>capture</i> the mouse pointer to be able to use it "
2142 "in your guest OS -- all "
2143 "mouse actions you perform when the mouse pointer is over the "
2144 "Virtual Machine's display are directly sent to the guest OS. "
2145 "If the mouse is currently captured, it will be automatically "
2146 "uncaptured."
2147 "</p>"
2148 "<p>The mouse icon on the status bar will look like&nbsp;"
2149 "<img src=:/mouse_seamless_16px.png/>&nbsp;to inform you that mouse "
2150 "pointer integration is supported by the guest OS and is "
2151 "currently turned on."
2152 "</p>"
2153 "<p><b>Note</b>: Some applications may behave incorrectly in "
2154 "mouse pointer integration mode. You can always disable it for "
2155 "the current session (and enable it again) by selecting the "
2156 "corresponding action from the menu bar."
2157 "</p>"),
2158 kNames [1] /* pcszAutoConfirmId */);
2159 }
2160 else
2161 {
2162 message(mainMachineWindowShown(), Info,
2163 tr("<p>The Virtual Machine reports that the guest OS does not "
2164 "support <b>mouse pointer integration</b> in the current video "
2165 "mode. You need to capture the mouse (by clicking over the VM "
2166 "display or pressing the host key) in order to use the "
2167 "mouse inside the guest OS.</p>"),
2168 kNames [0] /* pcszAutoConfirmId */);
2169 }
2170
2171 clearShownStatus("remindAboutMouseIntegration");
2172}
2173
2174/**
2175 * @return @c false if the dialog wasn't actually shown (i.e. it was
2176 * autoconfirmed).
2177 */
2178bool UIMessageCenter::remindAboutPausedVMInput()
2179{
2180 int rc = message(
2181 mainMachineWindowShown(),
2182 Info,
2183 tr("<p>The Virtual Machine is currently in the <b>Paused</b> state and "
2184 "not able to see any keyboard or mouse input. If you want to "
2185 "continue to work inside the VM, you need to resume it by selecting the "
2186 "corresponding action from the menu bar.</p>"),
2187 "remindAboutPausedVMInput"
2188 );
2189 return !(rc & AutoConfirmed);
2190}
2191
2192/** @return true if the user has chosen to show the Disk Manager Window */
2193bool UIMessageCenter::remindAboutInaccessibleMedia()
2194{
2195 int rc = message(&vboxGlobal().selectorWnd(), Warning,
2196 tr("<p>One or more virtual hard disks, CD/DVD or "
2197 "floppy media are not currently accessible. As a result, you will "
2198 "not be able to operate virtual machines that use these media until "
2199 "they become accessible later.</p>"
2200 "<p>Press <b>Check</b> to open the Virtual Media Manager window and "
2201 "see what media are inaccessible, or press <b>Ignore</b> to "
2202 "ignore this message.</p>"),
2203 "remindAboutInaccessibleMedia",
2204 QIMessageBox::Ok | QIMessageBox::Default,
2205 QIMessageBox::Ignore | QIMessageBox::Escape,
2206 0,
2207 tr("Check", "inaccessible media message box"));
2208
2209 return rc == QIMessageBox::Ok; /* implies !AutoConfirmed */
2210}
2211
2212/**
2213 * Shows user a proposal to either convert configuration files or
2214 * Exit the application leaving all as already is.
2215 *
2216 * @param strFileList List of files for auto-conversion (may use Qt HTML).
2217 * @param fAfterRefresh @true when called after the VM refresh.
2218 *
2219 * @return QIMessageBox::Ok (Save + Backup), QIMessageBox::Cancel (Exit)
2220 */
2221int UIMessageCenter::warnAboutSettingsAutoConversion(const QString &strFileList,
2222 bool fAfterRefresh)
2223{
2224 if (!fAfterRefresh)
2225 {
2226 /* Common variant for all VMs */
2227 return message(mainWindowShown(), Info,
2228 tr("<p>Your existing VirtualBox settings files will be automatically "
2229 "converted from the old format to a new format required by the "
2230 "new version of VirtualBox.</p>"
2231 "<p>Press <b>OK</b> to start VirtualBox now or press <b>Exit</b> if "
2232 "you want to terminate the VirtualBox "
2233 "application without any further actions.</p>"),
2234 NULL /* pcszAutoConfirmId */,
2235 QIMessageBox::Ok | QIMessageBox::Default,
2236 QIMessageBox::Cancel | QIMessageBox::Escape,
2237 0,
2238 0,
2239 tr("E&xit", "warnAboutSettingsAutoConversion message box"));
2240 }
2241 else
2242 {
2243 /* Particular VM variant */
2244 return message(mainWindowShown(), Info,
2245 tr("<p>The following VirtualBox settings files will be automatically "
2246 "converted from the old format to a new format required by the "
2247 "new version of VirtualBox.</p>"
2248 "<p>Press <b>OK</b> to start VirtualBox now or press <b>Exit</b> if "
2249 "you want to terminate the VirtualBox "
2250 "application without any further actions.</p>"),
2251 QString("<!--EOM-->%1").arg(strFileList),
2252 NULL /* pcszAutoConfirmId */,
2253 QIMessageBox::Ok | QIMessageBox::Default,
2254 QIMessageBox::Cancel | QIMessageBox::Escape,
2255 0,
2256 0,
2257 tr("E&xit", "warnAboutSettingsAutoConversion message box"));
2258 }
2259}
2260
2261/**
2262 * @param strHotKey Fullscreen hot key as defined in the menu.
2263 *
2264 * @return @c true if the user has chosen to go fullscreen (this is always
2265 * the case if the dialog was autoconfirmed).
2266 */
2267bool UIMessageCenter::confirmGoingFullscreen(const QString &strHotKey)
2268{
2269 return messageOkCancel(mainMachineWindowShown(), Info,
2270 tr("<p>The virtual machine window will be now switched to <b>fullscreen</b> mode. "
2271 "You can go back to windowed mode at any time by pressing <b>%1</b>.</p>"
2272 "<p>Note that the <i>Host</i> key is currently defined as <b>%2</b>.</p>"
2273 "<p>Note that the main menu bar is hidden in fullscreen mode. "
2274 "You can access it by pressing <b>Host+Home</b>.</p>")
2275 .arg(strHotKey)
2276 .arg(UIHotKeyCombination::toReadableString(vboxGlobal().settings().hostCombo())),
2277 "confirmGoingFullscreen",
2278 tr("Switch", "fullscreen"));
2279}
2280
2281/**
2282 * @param strHotKey Seamless hot key as defined in the menu.
2283 *
2284 * @return @c true if the user has chosen to go seamless (this is always
2285 * the case if the dialog was autoconfirmed).
2286 */
2287bool UIMessageCenter::confirmGoingSeamless(const QString &strHotKey)
2288{
2289 return messageOkCancel(mainMachineWindowShown(), Info,
2290 tr("<p>The virtual machine window will be now switched to <b>Seamless</b> mode. "
2291 "You can go back to windowed mode at any time by pressing <b>%1</b>.</p>"
2292 "<p>Note that the <i>Host</i> key is currently defined as <b>%2</b>.</p>"
2293 "<p>Note that the main menu bar is hidden in seamless mode. "
2294 "You can access it by pressing <b>Host+Home</b>.</p>")
2295 .arg(strHotKey)
2296 .arg(UIHotKeyCombination::toReadableString(vboxGlobal().settings().hostCombo())),
2297 "confirmGoingSeamless",
2298 tr("Switch", "seamless"));
2299}
2300
2301/**
2302 * @param strHotKey Scale hot key as defined in the menu.
2303 *
2304 * @return @c true if the user has chosen to go scale (this is always
2305 * the case if the dialog was autoconfirmed).
2306 */
2307bool UIMessageCenter::confirmGoingScale(const QString &strHotKey)
2308{
2309 return messageOkCancel(mainMachineWindowShown(), Info,
2310 tr("<p>The virtual machine window will be now switched to <b>Scale</b> mode. "
2311 "You can go back to windowed mode at any time by pressing <b>%1</b>.</p>"
2312 "<p>Note that the <i>Host</i> key is currently defined as <b>%2</b>.</p>"
2313 "<p>Note that the main menu bar is hidden in scale mode. "
2314 "You can access it by pressing <b>Host+Home</b>.</p>")
2315 .arg(strHotKey)
2316 .arg(UIHotKeyCombination::toReadableString(vboxGlobal().settings().hostCombo())),
2317 "confirmGoingScale",
2318 tr("Switch", "scale"));
2319}
2320
2321/**
2322 * Returns @c true if the user has selected to power off the machine.
2323 */
2324bool UIMessageCenter::remindAboutGuruMeditation(const CConsole &console,
2325 const QString &strLogFolder)
2326{
2327 Q_UNUSED(console);
2328
2329 int rc = message(mainMachineWindowShown(), GuruMeditation,
2330 tr("<p>A critical error has occurred while running the virtual "
2331 "machine and the machine execution has been stopped.</p>"
2332 ""
2333 "<p>For help, please see the Community section on "
2334 "<a href=http://www.virtualbox.org>http://www.virtualbox.org</a> "
2335 "or your support contract. Please provide the contents of the "
2336 "log file <tt>VBox.log</tt> and the image file <tt>VBox.png</tt>, "
2337 "which you can find in the <nobr><b>%1</b></nobr> directory, "
2338 "as well as a description of what you were doing when this error "
2339 "happened. "
2340 ""
2341 "Note that you can also access the above files by selecting "
2342 "<b>Show Log</b> from the <b>Machine</b> menu of the main "
2343 "VirtualBox window.</p>"
2344 ""
2345 "<p>Press <b>OK</b> if you want to power off the machine "
2346 "or press <b>Ignore</b> if you want to leave it as is for debugging. "
2347 "Please note that debugging requires special knowledge and tools, so "
2348 "it is recommended to press <b>OK</b> now.</p>")
2349 .arg(strLogFolder),
2350 0, /* pcszAutoConfirmId */
2351 QIMessageBox::Ok | QIMessageBox::Default,
2352 QIMessageBox::Ignore | QIMessageBox::Escape);
2353
2354 return rc == QIMessageBox::Ok;
2355}
2356
2357/**
2358 * @return @c true if the user has selected to reset the machine.
2359 */
2360bool UIMessageCenter::confirmVMReset(const QString &strNames)
2361{
2362 return messageOkCancel(mainMachineWindowShown(), Question,
2363 tr("<p>Do you really want to reset the following virtual machines?</p>"
2364 "<p><b>%1</b></p><p>This will cause any unsaved data "
2365 "in applications running inside it to be lost.</p>")
2366 .arg(strNames),
2367 "confirmVMReset" /* pcszAutoConfirmId */,
2368 tr("Reset", "machine"));
2369}
2370
2371bool UIMessageCenter::confirmVMACPIShutdown(const QString &strNames)
2372{
2373 return messageOkCancel(mainMachineWindowShown(), Question,
2374 tr("<p>Do you really want to send an ACPI shutdown signal "
2375 "to the following virtual machines?</p><p><b>%1</b></p>")
2376 .arg(strNames),
2377 "confirmVMACPIShutdown" /* pcszAutoConfirmId */,
2378 tr("ACPI Shutdown", "machine"));
2379}
2380
2381bool UIMessageCenter::confirmVMPowerOff(const QString &strNames)
2382{
2383 return messageOkCancel(mainMachineWindowShown(), Question,
2384 tr("<p>Do you really want to power off the following virtual machines?</p>"
2385 "<p><b>%1</b></p><p>This will cause any unsaved data in applications "
2386 "running inside it to be lost.</p>")
2387 .arg(strNames),
2388 "confirmVMPowerOff" /* pcszAutoConfirmId */,
2389 tr("Power Off", "machine"));
2390}
2391
2392void UIMessageCenter::warnAboutCannotRemoveMachineFolder(QWidget *pParent, const QString &strFolderName)
2393{
2394 QFileInfo fi(strFolderName);
2395 message(pParent ? pParent : mainWindowShown(), Critical,
2396 tr("<p>Cannot remove the machine folder <nobr><b>%1</b>.</nobr></p>"
2397 "<p>Please check that this folder really exists and that you have permissions to remove it.</p>")
2398 .arg(fi.fileName()));
2399}
2400
2401void UIMessageCenter::warnAboutCannotRewriteMachineFolder(QWidget *pParent, const QString &strFolderName)
2402{
2403 QFileInfo fi(strFolderName);
2404 message(pParent ? pParent : mainWindowShown(), Critical,
2405 tr("<p>Cannot create the machine folder <b>%1</b> in the parent folder <nobr><b>%2</b>.</nobr></p>"
2406 "<p>This folder already exists and possibly belongs to another machine.</p>")
2407 .arg(fi.fileName()).arg(fi.absolutePath()));
2408}
2409
2410void UIMessageCenter::warnAboutCannotCreateMachineFolder(QWidget *pParent, const QString &strFolderName)
2411{
2412 QFileInfo fi(strFolderName);
2413 message(pParent ? pParent : mainWindowShown(), Critical,
2414 tr("<p>Cannot create the machine folder <b>%1</b> in the parent folder <nobr><b>%2</b>.</nobr></p>"
2415 "<p>Please check that the parent really exists and that you have permissions to create the machine folder.</p>")
2416 .arg(fi.fileName()).arg(fi.absolutePath()));
2417}
2418
2419/**
2420 * @return @c true if the user has selected to continue without attaching a
2421 * hard disk.
2422 */
2423bool UIMessageCenter::confirmHardDisklessMachine(QWidget *pParent)
2424{
2425 return message(pParent, Warning,
2426 tr("You are about to create a new virtual machine without a hard drive. "
2427 "You will not be able to install an operating system on the machine "
2428 "until you add one. In the mean time you will only be able to start the "
2429 "machine using a virtual optical disk or from the network."),
2430 0, /* pcszAutoConfirmId */
2431 QIMessageBox::Ok,
2432 QIMessageBox::Cancel | QIMessageBox::Default | QIMessageBox::Escape,
2433 0,
2434 tr("Continue", "no hard disk attached"),
2435 tr("Go Back", "no hard disk attached")) == QIMessageBox::Ok;
2436}
2437
2438void UIMessageCenter::cannotRunInSelectorMode()
2439{
2440 message(mainWindowShown(), Critical,
2441 tr("<p>Cannot run VirtualBox in <i>VM Selector</i> "
2442 "mode due to local restrictions.</p>"
2443 "<p>The application will now terminate.</p>"));
2444}
2445
2446void UIMessageCenter::cannotImportAppliance(CAppliance *pAppliance,
2447 QWidget *pParent /* = NULL */) const
2448{
2449 if (pAppliance->isNull())
2450 {
2451 message(pParent ? pParent : mainWindowShown(),
2452 Error,
2453 tr("Failed to open appliance."));
2454 }
2455 else
2456 {
2457 /* Preserve the current error info before calling the object again */
2458 COMResult res(*pAppliance);
2459
2460 /* Add the warnings in the case of an early error */
2461 QVector<QString> w = pAppliance->GetWarnings();
2462 QString wstr;
2463 foreach(const QString &str, w)
2464 wstr += QString("<br />Warning: %1").arg(str);
2465 if (!wstr.isEmpty())
2466 wstr = "<br />" + wstr;
2467
2468 message(pParent ? pParent : mainWindowShown(),
2469 Error,
2470 tr("Failed to open/interpret appliance <b>%1</b>.").arg(pAppliance->GetPath()),
2471 wstr +
2472 formatErrorInfo(res));
2473 }
2474}
2475
2476void UIMessageCenter::cannotImportAppliance(const CProgress &progress,
2477 CAppliance* pAppliance,
2478 QWidget *pParent /* = NULL */) const
2479{
2480 AssertWrapperOk(progress);
2481
2482 message(pParent ? pParent : mainWindowShown(),
2483 Error,
2484 tr("Failed to import appliance <b>%1</b>.").arg(pAppliance->GetPath()),
2485 formatErrorInfo(progress.GetErrorInfo()));
2486}
2487
2488void UIMessageCenter::cannotCheckFiles(const CProgress &progress,
2489 QWidget *pParent /* = NULL */) const
2490{
2491 AssertWrapperOk(progress);
2492
2493 message(pParent ? pParent : mainWindowShown(),
2494 Error,
2495 tr("Failed to check files."),
2496 formatErrorInfo(progress.GetErrorInfo()));
2497}
2498
2499void UIMessageCenter::cannotRemoveFiles(const CProgress &progress,
2500 QWidget *pParent /* = NULL */) const
2501{
2502 AssertWrapperOk(progress);
2503
2504 message(pParent ? pParent : mainWindowShown(),
2505 Error,
2506 tr("Failed to remove file."),
2507 formatErrorInfo(progress.GetErrorInfo()));
2508}
2509
2510bool UIMessageCenter::confirmExportMachinesInSaveState(const QStringList &strMachineNames,
2511 QWidget *pParent /* = NULL */) const
2512{
2513 return messageOkCancel(pParent ? pParent : mainWindowShown(), Warning,
2514 tr("<p>The %n following virtual machine(s) are currently in a saved state: <b>%1</b></p>"
2515 "<p>If you continue the runtime state of the exported machine(s) "
2516 "will be discarded. The other machine(s) will not be changed.</p>", "This text is never used with n == 0. Feel free to drop the %n where possible, we only included it because of problems with Qt Linguist (but the user can see how many machines are in the list and doesn't need to be told).",
2517 strMachineNames.size()).arg(VBoxGlobal::toHumanReadableList(strMachineNames)),
2518 0 /* pcszAutoConfirmId */,
2519 tr("Continue"), tr("Cancel"));
2520}
2521
2522void UIMessageCenter::cannotExportAppliance(CAppliance *pAppliance,
2523 QWidget *pParent /* = NULL */) const
2524{
2525 if (pAppliance->isNull())
2526 {
2527 message(pParent ? pParent : mainWindowShown(),
2528 Error,
2529 tr("Failed to create appliance."));
2530 }
2531 else
2532 {
2533 /* Preserve the current error info before calling the object again */
2534 COMResult res(*pAppliance);
2535
2536 message(pParent ? pParent : mainWindowShown(),
2537 Error,
2538 tr("Failed to prepare the export of the appliance <b>%1</b>.").arg(pAppliance->GetPath()),
2539 formatErrorInfo(res));
2540 }
2541}
2542
2543void UIMessageCenter::cannotExportAppliance(const CMachine &machine,
2544 CAppliance *pAppliance,
2545 QWidget *pParent /* = NULL */) const
2546{
2547 if (pAppliance->isNull() ||
2548 machine.isNull())
2549 {
2550 message(pParent ? pParent : mainWindowShown(),
2551 Error,
2552 tr("Failed to create an appliance."));
2553 }
2554 else
2555 {
2556 message(pParent ? pParent : mainWindowShown(),
2557 Error,
2558 tr("Failed to prepare the export of the appliance <b>%1</b>.").arg(pAppliance->GetPath()),
2559 formatErrorInfo(machine));
2560 }
2561}
2562
2563void UIMessageCenter::cannotExportAppliance(const CProgress &progress,
2564 CAppliance* pAppliance,
2565 QWidget *pParent /* = NULL */) const
2566{
2567 AssertWrapperOk(progress);
2568
2569 message(pParent ? pParent : mainWindowShown(),
2570 Error,
2571 tr("Failed to export appliance <b>%1</b>.").arg(pAppliance->GetPath()),
2572 formatErrorInfo(progress.GetErrorInfo()));
2573}
2574
2575void UIMessageCenter::cannotUpdateGuestAdditions(const CProgress &progress,
2576 QWidget *pParent /* = NULL */) const
2577{
2578 AssertWrapperOk(progress);
2579
2580 message(pParent ? pParent : mainWindowShown(),
2581 Error,
2582 tr("Failed to update Guest Additions. The Guest Additions installation image will be mounted to provide a manual installation."),
2583 formatErrorInfo(progress.GetErrorInfo()));
2584}
2585
2586void UIMessageCenter::cannotOpenExtPack(const QString &strFilename,
2587 const CExtPackManager &extPackManager,
2588 QWidget *pParent)
2589{
2590 message(pParent ? pParent : mainWindowShown(),
2591 Error,
2592 tr("Failed to open the Extension Pack <b>%1</b>.").arg(strFilename),
2593 formatErrorInfo(extPackManager));
2594}
2595
2596void UIMessageCenter::badExtPackFile(const QString &strFilename,
2597 const CExtPackFile &extPackFile,
2598 QWidget *pParent)
2599{
2600 message(pParent ? pParent : mainWindowShown(),
2601 Error,
2602 tr("Failed to open the Extension Pack <b>%1</b>.").arg(strFilename),
2603 "<!--EOM-->" + extPackFile.GetWhyUnusable());
2604}
2605
2606void UIMessageCenter::cannotInstallExtPack(const QString &strFilename,
2607 const CExtPackFile &extPackFile,
2608 const CProgress &progress,
2609 QWidget *pParent)
2610{
2611 if (!pParent)
2612 pParent = mainWindowShown();
2613 QString strErrInfo = !extPackFile.isOk() || progress.isNull()
2614 ? formatErrorInfo(extPackFile) : formatErrorInfo(progress.GetErrorInfo());
2615 message(pParent,
2616 Error,
2617 tr("Failed to install the Extension Pack <b>%1</b>.").arg(strFilename),
2618 strErrInfo);
2619}
2620
2621void UIMessageCenter::cannotUninstallExtPack(const QString &strPackName, const CExtPackManager &extPackManager,
2622 const CProgress &progress, QWidget *pParent)
2623{
2624 if (!pParent)
2625 pParent = mainWindowShown();
2626 QString strErrInfo = !extPackManager.isOk() || progress.isNull()
2627 ? formatErrorInfo(extPackManager) : formatErrorInfo(progress.GetErrorInfo());
2628 message(pParent,
2629 Error,
2630 tr("Failed to uninstall the Extension Pack <b>%1</b>.").arg(strPackName),
2631 strErrInfo);
2632}
2633
2634bool UIMessageCenter::confirmInstallingPackage(const QString &strPackName, const QString &strPackVersion,
2635 const QString &strPackDescription, QWidget *pParent)
2636{
2637 return messageOkCancel(pParent ? pParent : mainWindowShown(),
2638 Question,
2639 tr("<p>You are about to install a VirtualBox extension pack. "
2640 "Extension packs complement the functionality of VirtualBox and can contain system level software "
2641 "that could be potentially harmful to your system. Please review the description below and only proceed "
2642 "if you have obtained the extension pack from a trusted source.</p>"
2643 "<p><table cellpadding=0 cellspacing=0>"
2644 "<tr><td><b>Name:&nbsp;&nbsp;</b></td><td>%1</td></tr>"
2645 "<tr><td><b>Version:&nbsp;&nbsp;</b></td><td>%2</td></tr>"
2646 "<tr><td><b>Description:&nbsp;&nbsp;</b></td><td>%3</td></tr>"
2647 "</table></p>")
2648 .arg(strPackName).arg(strPackVersion).arg(strPackDescription),
2649 0,
2650 tr("&Install"));
2651}
2652
2653bool UIMessageCenter::confirmReplacePackage(const QString &strPackName, const QString &strPackVersionNew,
2654 const QString &strPackVersionOld, const QString &strPackDescription,
2655 QWidget *pParent)
2656{
2657 if (!pParent)
2658 pParent = pParent ? pParent : mainWindowShown(); /* this is boring stuff that messageOkCancel should do! */
2659
2660 QString strBelehrung = tr("Extension packs complement the functionality of VirtualBox and can contain "
2661 "system level software that could be potentially harmful to your system. "
2662 "Please review the description below and only proceed if you have obtained "
2663 "the extension pack from a trusted source.");
2664
2665 QByteArray ba1 = strPackVersionNew.toUtf8();
2666 QByteArray ba2 = strPackVersionOld.toUtf8();
2667 int iVerCmp = RTStrVersionCompare(ba1.constData(), ba2.constData());
2668
2669 bool fRc;
2670 if (iVerCmp > 0)
2671 fRc = messageOkCancel(pParent,
2672 Question,
2673 tr("<p>An older version of the extension pack is already installed, would you like to upgrade? "
2674 "<p>%1</p>"
2675 "<p><table cellpadding=0 cellspacing=0>"
2676 "<tr><td><b>Name:&nbsp;&nbsp;</b></td><td>%2</td></tr>"
2677 "<tr><td><b>New Version:&nbsp;&nbsp;</b></td><td>%3</td></tr>"
2678 "<tr><td><b>Current Version:&nbsp;&nbsp;</b></td><td>%4</td></tr>"
2679 "<tr><td><b>Description:&nbsp;&nbsp;</b></td><td>%5</td></tr>"
2680 "</table></p>")
2681 .arg(strBelehrung).arg(strPackName).arg(strPackVersionNew).arg(strPackVersionOld).arg(strPackDescription),
2682 0,
2683 tr("&Upgrade"));
2684 else if (iVerCmp < 0)
2685 fRc = messageOkCancel(pParent,
2686 Question,
2687 tr("<p>An newer version of the extension pack is already installed, would you like to downgrade? "
2688 "<p>%1</p>"
2689 "<p><table cellpadding=0 cellspacing=0>"
2690 "<tr><td><b>Name:&nbsp;&nbsp;</b></td><td>%2</td></tr>"
2691 "<tr><td><b>New Version:&nbsp;&nbsp;</b></td><td>%3</td></tr>"
2692 "<tr><td><b>Current Version:&nbsp;&nbsp;</b></td><td>%4</td></tr>"
2693 "<tr><td><b>Description:&nbsp;&nbsp;</b></td><td>%5</td></tr>"
2694 "</table></p>")
2695 .arg(strBelehrung).arg(strPackName).arg(strPackVersionNew).arg(strPackVersionOld).arg(strPackDescription),
2696 0,
2697 tr("&Downgrade"));
2698 else
2699 fRc = messageOkCancel(pParent,
2700 Question,
2701 tr("<p>The extension pack is already installed with the same version, would you like reinstall it? "
2702 "<p>%1</p>"
2703 "<p><table cellpadding=0 cellspacing=0>"
2704 "<tr><td><b>Name:&nbsp;&nbsp;</b></td><td>%2</td></tr>"
2705 "<tr><td><b>Version:&nbsp;&nbsp;</b></td><td>%3</td></tr>"
2706 "<tr><td><b>Description:&nbsp;&nbsp;</b></td><td>%4</td></tr>"
2707 "</table></p>")
2708 .arg(strBelehrung).arg(strPackName).arg(strPackVersionOld).arg(strPackDescription),
2709 0,
2710 tr("&Reinstall"));
2711 return fRc;
2712}
2713
2714bool UIMessageCenter::confirmRemovingPackage(const QString &strPackName, QWidget *pParent)
2715{
2716 return messageOkCancel(pParent ? pParent : mainWindowShown(),
2717 Question,
2718 tr("<p>You are about to remove the VirtualBox extension pack <b>%1</b>.</p>"
2719 "<p>Are you sure you want to proceed?</p>").arg(strPackName),
2720 0,
2721 tr("&Remove"));
2722}
2723
2724void UIMessageCenter::notifyAboutExtPackInstalled(const QString &strPackName, QWidget *pParent)
2725{
2726 message(pParent ? pParent : mainWindowShown(),
2727 Info,
2728 tr("The extension pack <br><nobr><b>%1</b><nobr><br> was installed successfully.").arg(strPackName));
2729}
2730
2731void UIMessageCenter::warnAboutIncorrectPort(QWidget *pParent) const
2732{
2733 message(pParent, Error,
2734 tr("The current port forwarding rules are not valid. "
2735 "None of the host or guest port values may be set to zero."));
2736}
2737
2738bool UIMessageCenter::confirmCancelingPortForwardingDialog(QWidget *pParent) const
2739{
2740 return messageOkCancel(pParent, Question,
2741 tr("<p>There are unsaved changes in the port forwarding configuration.</p>"
2742 "<p>If you proceed your changes will be discarded.</p>"));
2743}
2744
2745void UIMessageCenter::showRuntimeError(const CConsole &console, bool fFatal,
2746 const QString &strErrorId,
2747 const QString &strErrorMsg) const
2748{
2749 /// @todo (r=dmik) it's just a preliminary box. We need to:
2750 // - for fFatal errors and non-fFatal with-retry errors, listen for a
2751 // VM state signal to automatically close the message if the VM
2752 // (externally) leaves the Paused state while it is shown.
2753 // - make warning messages modeless
2754 // - add common buttons like Retry/Save/PowerOff/whatever
2755
2756 QByteArray autoConfimId = "showRuntimeError.";
2757
2758 CConsole console1 = console;
2759 KMachineState state = console1.GetState();
2760 Type type;
2761 QString severity;
2762
2763 if (fFatal)
2764 {
2765 /* the machine must be paused on fFatal errors */
2766 Assert(state == KMachineState_Paused);
2767 if (state != KMachineState_Paused)
2768 console1.Pause();
2769 type = Critical;
2770 severity = tr("<nobr>Fatal Error</nobr>", "runtime error info");
2771 autoConfimId += "fatal.";
2772 }
2773 else if (state == KMachineState_Paused)
2774 {
2775 type = Error;
2776 severity = tr("<nobr>Non-Fatal Error</nobr>", "runtime error info");
2777 autoConfimId += "error.";
2778 }
2779 else
2780 {
2781 type = Warning;
2782 severity = tr("<nobr>Warning</nobr>", "runtime error info");
2783 autoConfimId += "warning.";
2784 }
2785
2786 autoConfimId += strErrorId.toUtf8();
2787
2788 QString formatted("<!--EOM-->");
2789
2790 if (!strErrorMsg.isEmpty())
2791 formatted.prepend(QString("<p>%1.</p>").arg(vboxGlobal().emphasize(strErrorMsg)));
2792
2793 if (!strErrorId.isEmpty())
2794 formatted += QString("<table bgcolor=#EEEEEE border=0 cellspacing=0 "
2795 "cellpadding=0 width=100%>"
2796 "<tr><td>%1</td><td>%2</td></tr>"
2797 "<tr><td>%3</td><td>%4</td></tr>"
2798 "</table>")
2799 .arg(tr("<nobr>Error ID: </nobr>", "runtime error info"),
2800 strErrorId)
2801 .arg(tr("Severity: ", "runtime error info"),
2802 severity);
2803
2804 if (!formatted.isEmpty())
2805 formatted = "<qt>" + formatted + "</qt>";
2806
2807 int rc = 0;
2808
2809 if (type == Critical)
2810 {
2811 rc = message(mainMachineWindowShown(), type,
2812 tr("<p>A fatal error has occurred during virtual machine execution! "
2813 "The virtual machine will be powered off. Please copy the "
2814 "following error message using the clipboard to help diagnose "
2815 "the problem:</p>"),
2816 formatted, autoConfimId.data());
2817
2818 /* always power down after a fFatal error */
2819 console1.PowerDown();
2820 }
2821 else if (type == Error)
2822 {
2823 rc = message(mainMachineWindowShown(), type,
2824 tr("<p>An error has occurred during virtual machine execution! "
2825 "The error details are shown below. You may try to correct "
2826 "the error and resume the virtual machine "
2827 "execution.</p>"),
2828 formatted, autoConfimId.data());
2829 }
2830 else
2831 {
2832 rc = message(mainMachineWindowShown(), type,
2833 tr("<p>The virtual machine execution may run into an error "
2834 "condition as described below. "
2835 "We suggest that you take "
2836 "an appropriate action to avert the error."
2837 "</p>"),
2838 formatted, autoConfimId.data());
2839 }
2840
2841 NOREF(rc);
2842}
2843
2844/* static */
2845QString UIMessageCenter::mediumToAccusative(UIMediumType type, bool fIsHostDrive /* = false */)
2846{
2847 QString strType =
2848 type == UIMediumType_HardDisk ?
2849 tr("hard disk", "failed to mount ...") :
2850 type == UIMediumType_DVD && fIsHostDrive ?
2851 tr("CD/DVD", "failed to mount ... host-drive") :
2852 type == UIMediumType_DVD && !fIsHostDrive ?
2853 tr("CD/DVD image", "failed to mount ...") :
2854 type == UIMediumType_Floppy && fIsHostDrive ?
2855 tr("floppy", "failed to mount ... host-drive") :
2856 type == UIMediumType_Floppy && !fIsHostDrive ?
2857 tr("floppy image", "failed to mount ...") :
2858 QString::null;
2859
2860 Assert(!strType.isNull());
2861 return strType;
2862}
2863
2864/**
2865 * Formats the given COM result code as a human-readable string.
2866 *
2867 * If a mnemonic name for the given result code is found, a string in format
2868 * "MNEMONIC_NAME (0x12345678)" is returned where the hex number is the result
2869 * code as is. If no mnemonic name is found, then the raw hex number only is
2870 * returned (w/o pParenthesis).
2871 *
2872 * @param rc COM result code to format.
2873 */
2874/* static */
2875QString UIMessageCenter::formatRC(HRESULT rc)
2876{
2877 QString str;
2878
2879 PCRTCOMERRMSG msg = NULL;
2880 const char *errMsg = NULL;
2881
2882 /* first, try as is (only set bit 31 bit for warnings) */
2883 if (SUCCEEDED_WARNING(rc))
2884 msg = RTErrCOMGet(rc | 0x80000000);
2885 else
2886 msg = RTErrCOMGet(rc);
2887
2888 if (msg != NULL)
2889 errMsg = msg->pszDefine;
2890
2891#if defined (Q_WS_WIN)
2892
2893 PCRTWINERRMSG winMsg = NULL;
2894
2895 /* if not found, try again using RTErrWinGet with masked off top 16bit */
2896 if (msg == NULL)
2897 {
2898 winMsg = RTErrWinGet(rc & 0xFFFF);
2899
2900 if (winMsg != NULL)
2901 errMsg = winMsg->pszDefine;
2902 }
2903
2904#endif
2905
2906 if (errMsg != NULL && *errMsg != '\0')
2907 str.sprintf("%s (0x%08X)", errMsg, rc);
2908 else
2909 str.sprintf("0x%08X", rc);
2910
2911 return str;
2912}
2913
2914/* static */
2915QString UIMessageCenter::formatErrorInfo(const COMErrorInfo &info,
2916 HRESULT wrapperRC /* = S_OK */)
2917{
2918 QString formatted = errorInfoToString(info, wrapperRC);
2919 return QString("<qt>%1</qt>").arg(formatted);
2920}
2921
2922void UIMessageCenter::cannotCreateHostInterface(const CHost &host, QWidget *pParent /* = 0 */)
2923{
2924 if (thread() == QThread::currentThread())
2925 sltCannotCreateHostInterface(host, pParent);
2926 else
2927 emit sigCannotCreateHostInterface(host, pParent);
2928}
2929
2930void UIMessageCenter::cannotCreateHostInterface(const CProgress &progress, QWidget *pParent /* = 0 */)
2931{
2932 if (thread() == QThread::currentThread())
2933 sltCannotCreateHostInterface(progress, pParent);
2934 else
2935 emit sigCannotCreateHostInterface(progress, pParent);
2936}
2937
2938void UIMessageCenter::cannotRemoveHostInterface(const CHost &host, const CHostNetworkInterface &iface,
2939 QWidget *pParent /* = 0 */)
2940{
2941 if (thread() == QThread::currentThread())
2942 sltCannotRemoveHostInterface(host, iface ,pParent);
2943 else
2944 emit sigCannotRemoveHostInterface(host, iface, pParent);
2945}
2946
2947void UIMessageCenter::cannotRemoveHostInterface(const CProgress &progress, const CHostNetworkInterface &iface,
2948 QWidget *pParent /* = 0 */)
2949{
2950 if (thread() == QThread::currentThread())
2951 sltCannotRemoveHostInterface(progress, iface, pParent);
2952 else
2953 emit sigCannotRemoveHostInterface(progress, iface, pParent);
2954}
2955
2956void UIMessageCenter::cannotAttachDevice(const CMachine &machine, UIMediumType type,
2957 const QString &strLocation, const StorageSlot &storageSlot,
2958 QWidget *pParent /* = 0 */)
2959{
2960 if (thread() == QThread::currentThread())
2961 sltCannotAttachDevice(machine, type, strLocation, storageSlot, pParent);
2962 else
2963 emit sigCannotAttachDevice(machine, type, strLocation, storageSlot, pParent);
2964}
2965
2966void UIMessageCenter::cannotCreateSharedFolder(const CMachine &machine, const QString &strName,
2967 const QString &strPath, QWidget *pParent /* = 0 */)
2968{
2969 if (thread() == QThread::currentThread())
2970 sltCannotCreateSharedFolder(machine, strName, strPath, pParent);
2971 else
2972 emit sigCannotCreateSharedFolder(machine, strName, strPath, pParent);
2973}
2974
2975void UIMessageCenter::cannotRemoveSharedFolder(const CMachine &machine, const QString &strName,
2976 const QString &strPath, QWidget *pParent /* = 0 */)
2977{
2978 if (thread() == QThread::currentThread())
2979 sltCannotRemoveSharedFolder(machine, strName, strPath, pParent);
2980 else
2981 emit sigCannotRemoveSharedFolder(machine, strName, strPath, pParent);
2982}
2983
2984void UIMessageCenter::cannotCreateSharedFolder(const CConsole &console, const QString &strName,
2985 const QString &strPath, QWidget *pParent /* = 0 */)
2986{
2987 if (thread() == QThread::currentThread())
2988 sltCannotCreateSharedFolder(console, strName, strPath, pParent);
2989 else
2990 emit sigCannotCreateSharedFolder(console, strName, strPath, pParent);
2991}
2992
2993void UIMessageCenter::cannotRemoveSharedFolder(const CConsole &console, const QString &strName,
2994 const QString &strPath, QWidget *pParent /* = 0 */)
2995{
2996 if (thread() == QThread::currentThread())
2997 sltCannotRemoveSharedFolder(console, strName, strPath, pParent);
2998 else
2999 emit sigCannotRemoveSharedFolder(console, strName, strPath, pParent);
3000}
3001
3002#ifdef VBOX_WITH_DRAG_AND_DROP
3003void UIMessageCenter::cannotDropData(const CGuest &guest,
3004 QWidget *pParent /* = 0 */) const
3005{
3006 message(pParent ? pParent : mainWindowShown(),
3007 Error,
3008 tr("Failed to drop data."),
3009 formatErrorInfo(guest));
3010}
3011
3012void UIMessageCenter::cannotDropData(const CProgress &progress,
3013 QWidget *pParent /* = 0 */) const
3014{
3015 AssertWrapperOk(progress);
3016
3017 message(pParent ? pParent : mainWindowShown(),
3018 Error,
3019 tr("Failed to drop data."),
3020 formatErrorInfo(progress.GetErrorInfo()));
3021}
3022#endif /* VBOX_WITH_DRAG_AND_DROP */
3023
3024void UIMessageCenter::remindAboutWrongColorDepth(ulong uRealBPP, ulong uWantedBPP)
3025{
3026 emit sigRemindAboutWrongColorDepth(uRealBPP, uWantedBPP);
3027}
3028
3029void UIMessageCenter::showGenericError(COMBaseWithEI *object, QWidget *pParent /* = 0 */)
3030{
3031 if ( !object
3032 || object->lastRC() == S_OK)
3033 return;
3034
3035 message(pParent ? pParent : mainWindowShown(),
3036 Error,
3037 tr("Sorry, some generic error happens."),
3038 formatErrorInfo(*object));
3039}
3040
3041// Public slots
3042/////////////////////////////////////////////////////////////////////////////
3043
3044void UIMessageCenter::remindAboutUnsupportedUSB2(const QString &strExtPackName, QWidget *pParent)
3045{
3046 emit sigRemindAboutUnsupportedUSB2(strExtPackName, pParent);
3047}
3048
3049void UIMessageCenter::sltShowHelpWebDialog()
3050{
3051 vboxGlobal().openURL("http://www.virtualbox.org");
3052}
3053
3054void UIMessageCenter::sltShowHelpAboutDialog()
3055{
3056 CVirtualBox vbox = vboxGlobal().virtualBox();
3057 QString strFullVersion;
3058 if (vboxGlobal().brandingIsActive())
3059 {
3060 strFullVersion = QString("%1 r%2 - %3").arg(vbox.GetVersion())
3061 .arg(vbox.GetRevision())
3062 .arg(vboxGlobal().brandingGetKey("Name"));
3063 }
3064 else
3065 {
3066 strFullVersion = QString("%1 r%2").arg(vbox.GetVersion())
3067 .arg(vbox.GetRevision());
3068 }
3069 AssertWrapperOk(vbox);
3070
3071 (new VBoxAboutDlg(mainWindowShown(), strFullVersion))->show();
3072}
3073
3074void UIMessageCenter::sltShowHelpHelpDialog()
3075{
3076#ifndef VBOX_OSE
3077 /* For non-OSE version we just open it: */
3078 sltShowUserManual(vboxGlobal().helpFile());
3079#else /* #ifndef VBOX_OSE */
3080 /* For OSE version we have to check if it present first: */
3081 QString strUserManualFileName1 = vboxGlobal().helpFile();
3082 QString strShortFileName = QFileInfo(strUserManualFileName1).fileName();
3083 QString strUserManualFileName2 = QDir(vboxGlobal().virtualBox().GetHomeFolder()).absoluteFilePath(strShortFileName);
3084 /* Show if user manual already present: */
3085 if (QFile::exists(strUserManualFileName1))
3086 sltShowUserManual(strUserManualFileName1);
3087 else if (QFile::exists(strUserManualFileName2))
3088 sltShowUserManual(strUserManualFileName2);
3089 /* If downloader is running already: */
3090 else if (UIDownloaderUserManual::current())
3091 {
3092 /* Just show network access manager: */
3093 gNetworkManager->show();
3094 }
3095 /* Else propose to download user manual: */
3096 else if (askAboutUserManualDownload(strUserManualFileName1))
3097 {
3098 /* Create User Manual downloader: */
3099 UIDownloaderUserManual *pDl = UIDownloaderUserManual::create();
3100 /* After downloading finished => show User Manual: */
3101 connect(pDl, SIGNAL(sigDownloadFinished(const QString&)), this, SLOT(sltShowUserManual(const QString&)));
3102 /* Start downloading: */
3103 pDl->start();
3104 }
3105#endif /* #ifdef VBOX_OSE */
3106}
3107
3108void UIMessageCenter::sltResetSuppressedMessages()
3109{
3110 CVirtualBox vbox = vboxGlobal().virtualBox();
3111 vbox.SetExtraData(GUI_SuppressMessages, QString::null);
3112}
3113
3114void UIMessageCenter::sltShowUserManual(const QString &strLocation)
3115{
3116#if defined (Q_WS_WIN32)
3117 HtmlHelp(GetDesktopWindow(), strLocation.utf16(), HH_DISPLAY_TOPIC, NULL);
3118#elif defined (Q_WS_X11)
3119# ifndef VBOX_OSE
3120 char szViewerPath[RTPATH_MAX];
3121 int rc;
3122 rc = RTPathAppPrivateArch(szViewerPath, sizeof(szViewerPath));
3123 AssertRC(rc);
3124 QProcess::startDetached(QString(szViewerPath) + "/kchmviewer", QStringList(strLocation));
3125# else /* #ifndef VBOX_OSE */
3126 vboxGlobal().openURL("file://" + strLocation);
3127# endif /* #ifdef VBOX_OSE */
3128#elif defined (Q_WS_MAC)
3129 vboxGlobal().openURL("file://" + strLocation);
3130#endif
3131}
3132
3133void UIMessageCenter::sltCannotCreateHostInterface(const CHost &host, QWidget *pParent)
3134{
3135 message(pParent ? pParent : mainWindowShown(), Error,
3136 tr("Failed to create the host-only network interface."),
3137 formatErrorInfo(host));
3138}
3139
3140void UIMessageCenter::sltCannotCreateHostInterface(const CProgress &progress, QWidget *pParent)
3141{
3142 message(pParent ? pParent : mainWindowShown(), Error,
3143 tr("Failed to create the host-only network interface."),
3144 formatErrorInfo(progress.GetErrorInfo()));
3145}
3146
3147void UIMessageCenter::sltCannotRemoveHostInterface(const CHost &host, const CHostNetworkInterface &iface, QWidget *pParent)
3148{
3149 message(pParent ? pParent : mainWindowShown(), Error,
3150 tr("Failed to remove the host network interface <b>%1</b>.")
3151 .arg(iface.GetName()),
3152 formatErrorInfo(host));
3153}
3154
3155void UIMessageCenter::sltCannotRemoveHostInterface(const CProgress &progress, const CHostNetworkInterface &iface, QWidget *pParent)
3156{
3157 message(pParent ? pParent : mainWindowShown(), Error,
3158 tr("Failed to remove the host network interface <b>%1</b>.")
3159 .arg(iface.GetName()),
3160 formatErrorInfo(progress.GetErrorInfo()));
3161}
3162
3163void UIMessageCenter::sltCannotAttachDevice(const CMachine &machine, UIMediumType type,
3164 const QString &strLocation, const StorageSlot &storageSlot,
3165 QWidget *pParent)
3166{
3167 QString strMessage;
3168 switch (type)
3169 {
3170 case UIMediumType_HardDisk:
3171 {
3172 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>.")
3173 .arg(strLocation).arg(gpConverter->toString(storageSlot)).arg(CMachine(machine).GetName());
3174 break;
3175 }
3176 case UIMediumType_DVD:
3177 {
3178 strMessage = tr("Failed to attach the CD/DVD device (<nobr><b>%1</b></nobr>) to the slot <i>%2</i> of the machine <b>%3</b>.")
3179 .arg(strLocation).arg(gpConverter->toString(storageSlot)).arg(CMachine(machine).GetName());
3180 break;
3181 }
3182 case UIMediumType_Floppy:
3183 {
3184 strMessage = tr("Failed to attach the floppy device (<nobr><b>%1</b></nobr>) to the slot <i>%2</i> of the machine <b>%3</b>.")
3185 .arg(strLocation).arg(gpConverter->toString(storageSlot)).arg(CMachine(machine).GetName());
3186 break;
3187 }
3188 default:
3189 break;
3190 }
3191 message(pParent ? pParent : mainWindowShown(), Error, strMessage, formatErrorInfo(machine));
3192}
3193
3194void UIMessageCenter::sltCannotCreateSharedFolder(const CMachine &machine, const QString &strName,
3195 const QString &strPath, QWidget *pParent)
3196{
3197 message(pParent ? pParent : mainMachineWindowShown(), Error,
3198 tr("Failed to create the shared folder <b>%1</b> "
3199 "(pointing to <nobr><b>%2</b></nobr>) "
3200 "for the virtual machine <b>%3</b>.")
3201 .arg(strName)
3202 .arg(strPath)
3203 .arg(CMachine(machine).GetName()),
3204 formatErrorInfo(machine));
3205}
3206
3207void UIMessageCenter::sltCannotRemoveSharedFolder(const CMachine &machine, const QString &strName,
3208 const QString &strPath, QWidget *pParent)
3209{
3210 message(pParent ? pParent : mainMachineWindowShown(), Error,
3211 tr("Failed to remove the shared folder <b>%1</b> "
3212 "(pointing to <nobr><b>%2</b></nobr>) "
3213 "from the virtual machine <b>%3</b>.")
3214 .arg(strName)
3215 .arg(strPath)
3216 .arg(CMachine(machine).GetName()),
3217 formatErrorInfo(machine));
3218}
3219
3220void UIMessageCenter::sltCannotCreateSharedFolder(const CConsole &console, const QString &strName,
3221 const QString &strPath, QWidget *pParent)
3222{
3223 message(pParent ? pParent : mainMachineWindowShown(), Error,
3224 tr("Failed to create the shared folder <b>%1</b> "
3225 "(pointing to <nobr><b>%2</b></nobr>) "
3226 "for the virtual machine <b>%3</b>.")
3227 .arg(strName)
3228 .arg(strPath)
3229 .arg(CConsole(console).GetMachine().GetName()),
3230 formatErrorInfo(console));
3231}
3232
3233void UIMessageCenter::sltCannotRemoveSharedFolder(const CConsole &console, const QString &strName,
3234 const QString &strPath, QWidget *pParent)
3235{
3236 message(pParent ? pParent : mainMachineWindowShown(), Error,
3237 tr("<p>Failed to remove the shared folder <b>%1</b> "
3238 "(pointing to <nobr><b>%2</b></nobr>) "
3239 "from the virtual machine <b>%3</b>.</p>"
3240 "<p>Please close all programs in the guest OS that "
3241 "may be using this shared folder and try again.</p>")
3242 .arg(strName)
3243 .arg(strPath)
3244 .arg(CConsole(console).GetMachine().GetName()),
3245 formatErrorInfo(console));
3246}
3247
3248void UIMessageCenter::sltRemindAboutWrongColorDepth(ulong uRealBPP, ulong uWantedBPP)
3249{
3250 const char *kName = "remindAboutWrongColorDepth";
3251
3252 /* Close the previous (outdated) window if any. We use kName as
3253 * pcszAutoConfirmId which is also used as the widget name by default. */
3254 {
3255 QWidget *outdated = VBoxGlobal::findWidget(NULL, kName, "QIMessageBox");
3256 if (outdated)
3257 outdated->close();
3258 }
3259
3260 message(mainMachineWindowShown(), Info,
3261 tr("<p>The virtual machine window is optimized to work in "
3262 "<b>%1&nbsp;bit</b> color mode but the "
3263 "virtual display is currently set to <b>%2&nbsp;bit</b>.</p>"
3264 "<p>Please open the display properties dialog of the guest OS and "
3265 "select a <b>%3&nbsp;bit</b> color mode, if it is available, for "
3266 "best possible performance of the virtual video subsystem.</p>"
3267 "<p><b>Note</b>. Some operating systems, like OS/2, may actually "
3268 "work in 32&nbsp;bit mode but report it as 24&nbsp;bit "
3269 "(16 million colors). You may try to select a different color "
3270 "mode to see if this message disappears or you can simply "
3271 "disable the message now if you are sure the required color "
3272 "mode (%4&nbsp;bit) is not available in the guest OS.</p>")
3273 .arg(uWantedBPP).arg(uRealBPP).arg(uWantedBPP).arg(uWantedBPP),
3274 kName);
3275}
3276
3277void UIMessageCenter::sltRemindAboutUnsupportedUSB2(const QString &strExtPackName, QWidget *pParent)
3278{
3279 if (isAlreadyShown("sltRemindAboutUnsupportedUSB2"))
3280 return;
3281 setShownStatus("sltRemindAboutUnsupportedUSB2");
3282
3283 message(pParent ? pParent : mainMachineWindowShown(), Warning,
3284 tr("<p>USB 2.0 is currently enabled for this virtual machine. "
3285 "However, this requires the <b><nobr>%1</nobr></b> to be installed.</p>"
3286 "<p>Please install the Extension Pack from the VirtualBox download site. "
3287 "After this you will be able to re-enable USB 2.0. "
3288 "It will be disabled in the meantime unless you cancel the current settings changes.</p>")
3289 .arg(strExtPackName));
3290
3291 clearShownStatus("sltRemindAboutUnsupportedUSB2");
3292}
3293
3294UIMessageCenter::UIMessageCenter()
3295{
3296 /* Register required objects as meta-types: */
3297 qRegisterMetaType<CProgress>();
3298 qRegisterMetaType<CHost>();
3299 qRegisterMetaType<CMachine>();
3300 qRegisterMetaType<CConsole>();
3301 qRegisterMetaType<CHostNetworkInterface>();
3302 qRegisterMetaType<UIMediumType>();
3303 qRegisterMetaType<StorageSlot>();
3304
3305 /* Prepare required connections: */
3306 connect(this, SIGNAL(sigCannotCreateHostInterface(const CHost&, QWidget*)),
3307 this, SLOT(sltCannotCreateHostInterface(const CHost&, QWidget*)),
3308 Qt::BlockingQueuedConnection);
3309 connect(this, SIGNAL(sigCannotCreateHostInterface(const CProgress&, QWidget*)),
3310 this, SLOT(sltCannotCreateHostInterface(const CProgress&, QWidget*)),
3311 Qt::BlockingQueuedConnection);
3312 connect(this, SIGNAL(sigCannotRemoveHostInterface(const CHost&, const CHostNetworkInterface&, QWidget*)),
3313 this, SLOT(sltCannotRemoveHostInterface(const CHost&, const CHostNetworkInterface&, QWidget*)),
3314 Qt::BlockingQueuedConnection);
3315 connect(this, SIGNAL(sigCannotRemoveHostInterface(const CProgress&, const CHostNetworkInterface&, QWidget*)),
3316 this, SLOT(sltCannotRemoveHostInterface(const CProgress&, const CHostNetworkInterface&, QWidget*)),
3317 Qt::BlockingQueuedConnection);
3318 connect(this, SIGNAL(sigCannotAttachDevice(const CMachine&, UIMediumType, const QString&, const StorageSlot&, QWidget*)),
3319 this, SLOT(sltCannotAttachDevice(const CMachine&, UIMediumType, const QString&, const StorageSlot&, QWidget*)),
3320 Qt::BlockingQueuedConnection);
3321 connect(this, SIGNAL(sigCannotCreateSharedFolder(const CMachine&, const QString&, const QString&, QWidget*)),
3322 this, SLOT(sltCannotCreateSharedFolder(const CMachine&, const QString&, const QString&, QWidget*)),
3323 Qt::BlockingQueuedConnection);
3324 connect(this, SIGNAL(sigCannotRemoveSharedFolder(const CMachine&, const QString&, const QString&, QWidget*)),
3325 this, SLOT(sltCannotRemoveSharedFolder(const CMachine&, const QString&, const QString&, QWidget*)),
3326 Qt::BlockingQueuedConnection);
3327 connect(this, SIGNAL(sigCannotCreateSharedFolder(const CConsole&, const QString&, const QString&, QWidget*)),
3328 this, SLOT(sltCannotCreateSharedFolder(const CConsole&, const QString&, const QString&, QWidget*)),
3329 Qt::BlockingQueuedConnection);
3330 connect(this, SIGNAL(sigCannotRemoveSharedFolder(const CConsole&, const QString&, const QString&, QWidget*)),
3331 this, SLOT(sltCannotRemoveSharedFolder(const CConsole&, const QString&, const QString&, QWidget*)),
3332 Qt::BlockingQueuedConnection);
3333 connect(this, SIGNAL(sigRemindAboutWrongColorDepth(ulong, ulong)),
3334 this, SLOT(sltRemindAboutWrongColorDepth(ulong, ulong)), Qt::QueuedConnection);
3335 connect(this, SIGNAL(sigRemindAboutUnsupportedUSB2(const QString&, QWidget*)),
3336 this, SLOT(sltRemindAboutUnsupportedUSB2(const QString&, QWidget*)), Qt::QueuedConnection);
3337
3338 /* Translations for Main.
3339 * Please make sure they corresponds to the strings coming from Main one-by-one symbol! */
3340 tr("Could not load the Host USB Proxy Service (VERR_FILE_NOT_FOUND). The service might not be installed on the host computer");
3341 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 manual for a more detailed explanation");
3342 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 manual for a more detailed explanation");
3343 tr("The USB Proxy Service has not yet been ported to this host");
3344 tr("Could not load the Host USB Proxy service");
3345}
3346
3347/* Returns a reference to the global VirtualBox message center instance: */
3348UIMessageCenter &UIMessageCenter::instance()
3349{
3350 static UIMessageCenter global_instance;
3351 return global_instance;
3352}
3353
3354QString UIMessageCenter::errorInfoToString(const COMErrorInfo &info,
3355 HRESULT wrapperRC /* = S_OK */)
3356{
3357 /* Compose complex details string with internal <!--EOM--> delimiter to
3358 * make it possible to split string into info & details parts which will
3359 * be used separately in QIMessageBox */
3360 QString formatted;
3361
3362 /* Check if details text is NOT empty: */
3363 QString strDetailsInfo = info.text();
3364 if (!strDetailsInfo.isEmpty())
3365 {
3366 /* Check if details text written in English (latin1) and translated: */
3367 if (strDetailsInfo == QString::fromLatin1(strDetailsInfo.toLatin1()) &&
3368 strDetailsInfo != tr(strDetailsInfo.toLatin1().constData()))
3369 formatted += QString("<p>%1.</p>").arg(vboxGlobal().emphasize(tr(strDetailsInfo.toLatin1().constData())));
3370 else
3371 formatted += QString("<p>%1.</p>").arg(vboxGlobal().emphasize(strDetailsInfo));
3372 }
3373
3374 formatted += "<!--EOM--><table bgcolor=#EEEEEE border=0 cellspacing=0 "
3375 "cellpadding=0 width=100%>";
3376
3377 bool haveResultCode = false;
3378
3379 if (info.isBasicAvailable())
3380 {
3381#if defined (Q_WS_WIN)
3382 haveResultCode = info.isFullAvailable();
3383 bool haveComponent = true;
3384 bool haveInterfaceID = true;
3385#else /* defined (Q_WS_WIN) */
3386 haveResultCode = true;
3387 bool haveComponent = info.isFullAvailable();
3388 bool haveInterfaceID = info.isFullAvailable();
3389#endif
3390
3391 if (haveResultCode)
3392 {
3393 formatted += QString("<tr><td>%1</td><td><tt>%2</tt></td></tr>")
3394 .arg(tr("Result&nbsp;Code: ", "error info"))
3395 .arg(formatRC(info.resultCode()));
3396 }
3397
3398 if (haveComponent)
3399 formatted += QString("<tr><td>%1</td><td>%2</td></tr>")
3400 .arg(tr("Component: ", "error info"), info.component());
3401
3402 if (haveInterfaceID)
3403 {
3404 QString s = info.interfaceID();
3405 if (!info.interfaceName().isEmpty())
3406 s = info.interfaceName() + ' ' + s;
3407 formatted += QString("<tr><td>%1</td><td>%2</td></tr>")
3408 .arg(tr("Interface: ", "error info"), s);
3409 }
3410
3411 if (!info.calleeIID().isNull() && info.calleeIID() != info.interfaceID())
3412 {
3413 QString s = info.calleeIID();
3414 if (!info.calleeName().isEmpty())
3415 s = info.calleeName() + ' ' + s;
3416 formatted += QString("<tr><td>%1</td><td>%2</td></tr>")
3417 .arg(tr("Callee: ", "error info"), s);
3418 }
3419 }
3420
3421 if (FAILED (wrapperRC) &&
3422 (!haveResultCode || wrapperRC != info.resultCode()))
3423 {
3424 formatted += QString("<tr><td>%1</td><td><tt>%2</tt></td></tr>")
3425 .arg(tr("Callee&nbsp;RC: ", "error info"))
3426 .arg(formatRC(wrapperRC));
3427 }
3428
3429 formatted += "</table>";
3430
3431 if (info.next())
3432 formatted = formatted + "<!--EOP-->" + errorInfoToString(*info.next());
3433
3434 return formatted;
3435}
3436
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use