VirtualBox

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

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

FE/Qt: 6234: Support for VM groups: Error-handling for group-saving mechanism.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 139.4 KB
Line 
1/* $Id: UIMessageCenter.cpp 42998 2012-08-27 14:09:06Z 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
1202void UIMessageCenter::cannotSwitchScreenInSeamless(quint64 uMinVRAM)
1203{
1204 message(mainMachineWindowShown(), Error,
1205 tr("<p>Could not change the guest screen to this host screen "
1206 "due to insufficient guest video memory.</p>"
1207 "<p>You should configure the virtual machine to have at "
1208 "least <b>%1</b> of video memory.</p>")
1209 .arg(VBoxGlobal::formatSize(uMinVRAM)));
1210}
1211
1212int UIMessageCenter::cannotSwitchScreenInFullscreen(quint64 uMinVRAM)
1213{
1214 return message(mainMachineWindowShown(), Warning,
1215 tr("<p>Could not change the guest screen to this host screen "
1216 "due to insufficient guest video memory.</p>"
1217 "<p>You should configure the virtual machine to have at "
1218 "least <b>%1</b> of video memory.</p>"
1219 "<p>Press <b>Ignore</b> to switch the screen anyway "
1220 "or press <b>Cancel</b> to cancel the operation.</p>")
1221 .arg(VBoxGlobal::formatSize(uMinVRAM)),
1222 0, /* pcszAutoConfirmId */
1223 QIMessageBox::Ignore | QIMessageBox::Default,
1224 QIMessageBox::Cancel | QIMessageBox::Escape);
1225}
1226
1227int UIMessageCenter::cannotEnterFullscreenMode()
1228{
1229 return message(mainMachineWindowShown(), Error,
1230 tr("<p>Can not switch the guest display to fullscreen mode. You "
1231 "have more virtual screens configured than physical screens are "
1232 "attached to your host.</p><p>Please either lower the virtual "
1233 "screens in your VM configuration or attach additional screens "
1234 "to your host.</p>"),
1235 0, /* pcszAutoConfirmId */
1236 QIMessageBox::Ok | QIMessageBox::Default);
1237}
1238
1239int UIMessageCenter::cannotEnterSeamlessMode()
1240{
1241 return message(mainMachineWindowShown(), Error,
1242 tr("<p>Can not switch the guest display to seamless mode. You "
1243 "have more virtual screens configured than physical screens are "
1244 "attached to your host.</p><p>Please either lower the virtual "
1245 "screens in your VM configuration or attach additional screens "
1246 "to your host.</p>"),
1247 0, /* pcszAutoConfirmId */
1248 QIMessageBox::Ok | QIMessageBox::Default);
1249}
1250
1251void UIMessageCenter::notifyAboutCollisionOnGroupRemovingCantBeResolved(const QString &strName, const QString &strGroupName)
1252{
1253 message(&vboxGlobal().selectorWnd(),
1254 Error,
1255 tr("<p>You are trying to move machine <nobr><b>%1</b></nobr> "
1256 "to group <nobr><b>%2</b></nobr> which already have sub-group <nobr><b>%1</b></nobr>.</p>"
1257 "<p>Please resolve this name-conflict and try again.</p>")
1258 .arg(strName, strGroupName),
1259 0, /* auto-confirm id */
1260 QIMessageBox::Ok | QIMessageBox::Default);
1261}
1262
1263int UIMessageCenter::askAboutCollisionOnGroupRemoving(const QString &strName, const QString &strGroupName)
1264{
1265 return message(&vboxGlobal().selectorWnd(),
1266 Question,
1267 tr("<p>You are trying to move group <nobr><b>%1</b></nobr> "
1268 "to group <nobr><b>%2</b></nobr> which already have another item with the same name.</p>"
1269 "<p>Would you like to automatically rename it?</p>")
1270 .arg(strName, strGroupName),
1271 0, /* auto-confirm id */
1272 QIMessageBox::Ok,
1273 QIMessageBox::Cancel | QIMessageBox::Escape | QIMessageBox::Default,
1274 0,
1275 tr("Rename"));
1276}
1277
1278int UIMessageCenter::confirmMachineItemRemoval(const QStringList &names)
1279{
1280 return message(&vboxGlobal().selectorWnd(),
1281 Question,
1282 tr("<p>You are about to remove following virtual "
1283 "machine items from the machine list:</p>"
1284 "<p><b>%1</b></p>"
1285 "<p>Do you wish to proceed?</p>").arg(names.join(", ")),
1286 0, /* auto-confirm id */
1287 QIMessageBox::Ok,
1288 QIMessageBox::Cancel | QIMessageBox::Escape | QIMessageBox::Default,
1289 0,
1290 tr("Remove"));
1291}
1292
1293int UIMessageCenter::confirmMachineDeletion(const QList<CMachine> &machines)
1294{
1295 /* Enumerate VMs: */
1296 int cInacessibleVMCount = 0;
1297 bool fVMWithHDPresent = false;
1298 QString strVMNames;
1299 for (int i = 0; i < machines.size(); ++i)
1300 {
1301 /* Get iterated VM: */
1302 const CMachine &machine = machines[i];
1303 /* Prepare VM name: */
1304 QString strMachineName;
1305 if (machine.GetAccessible())
1306 {
1307 /* Get VM name: */
1308 strMachineName = machine.GetName();
1309 /* Enumerate attachments: */
1310 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments();
1311 for (int i = 0; !fVMWithHDPresent && i < attachments.size(); ++i)
1312 {
1313 /* Get current attachment: */
1314 const CMediumAttachment &attachment = attachments.at(i);
1315 /* Check if the medium is a hard disk: */
1316 if (attachment.GetType() == KDeviceType_HardDisk)
1317 {
1318 /* Check if that hard disk isn't shared.
1319 * If hard disk is shared, it will *never* be deleted: */
1320 QVector<QString> ids = attachment.GetMedium().GetMachineIds();
1321 if (ids.size() == 1)
1322 {
1323 fVMWithHDPresent = true;
1324 break;
1325 }
1326 }
1327 }
1328 }
1329 else
1330 {
1331 /* Get VM name: */
1332 QFileInfo fi(machine.GetSettingsFilePath());
1333 strMachineName = VBoxGlobal::hasAllowedExtension(fi.completeSuffix(), VBoxFileExts) ? fi.completeBaseName() : fi.fileName();
1334 /* Increment inacessible VM count: */
1335 ++cInacessibleVMCount;
1336 }
1337
1338 /* Compose VM name list: */
1339 strVMNames += QString(strVMNames.isEmpty() ? "<b>%1</b>" : ", <b>%1</b>").arg(strMachineName);
1340 }
1341
1342 /* Prepare message text: */
1343 QString strText = cInacessibleVMCount == machines.size() ?
1344 tr("<p>You are about to remove following inaccessible virtual machines from the machine list:</p>"
1345 "<p>%1</p>"
1346 "<p>Do you wish to proceed?</p>")
1347 .arg(strVMNames) :
1348 fVMWithHDPresent ?
1349 tr("<p>You are about to remove following virtual machines from the machine list:</p>"
1350 "<p>%1</p>"
1351 "<p>Would you like to delete the files containing the virtual machine from your hard disk as well? "
1352 "Doing this will also remove the files containing the machine's virtual hard disks "
1353 "if they are not in use by another machine.</p>")
1354 .arg(strVMNames) :
1355 tr("<p>You are about to remove following virtual machines from the machine list:</p>"
1356 "<p>%1</p>"
1357 "<p>Would you like to delete the files containing the virtual machine from your hard disk as well?</p>")
1358 .arg(strVMNames);
1359
1360 /* Prepare message itself: */
1361 return cInacessibleVMCount == machines.size() ?
1362 message(&vboxGlobal().selectorWnd(),
1363 Question,
1364 strText,
1365 0, /* auto-confirm id */
1366 QIMessageBox::Ok,
1367 QIMessageBox::Cancel | QIMessageBox::Escape | QIMessageBox::Default,
1368 0,
1369 tr("Remove")) :
1370 message(&vboxGlobal().selectorWnd(),
1371 Question,
1372 strText,
1373 0, /* auto-confirm id */
1374 QIMessageBox::Yes,
1375 QIMessageBox::No,
1376 QIMessageBox::Cancel | QIMessageBox::Escape | QIMessageBox::Default,
1377 tr("Delete all files"),
1378 tr("Remove only"));
1379}
1380
1381bool UIMessageCenter::confirmDiscardSavedState(const QString &strNames)
1382{
1383 return messageOkCancel(&vboxGlobal().selectorWnd(), Question,
1384 tr("<p>Are you sure you want to discard the saved state of "
1385 "the following virtual machines?</p><p><b>%1</b></p>"
1386 "<p>This operation is equivalent to resetting or powering off "
1387 "the machine without doing a proper shutdown of the guest OS.</p>")
1388 .arg(strNames),
1389 0 /* pcszAutoConfirmId */,
1390 tr("Discard", "saved state"));
1391}
1392
1393void UIMessageCenter::cannotSetGroups(const CMachine &machine)
1394{
1395 COMResult res(machine);
1396 QString name = machine.GetName();
1397 if (name.isEmpty())
1398 name = QFileInfo(machine.GetSettingsFilePath()).baseName();
1399
1400 message(mainWindowShown(), Error,
1401 tr("Failed to set groups of the virtual machine <b>%1</b>.").arg(name),
1402 formatErrorInfo(res));
1403}
1404
1405void UIMessageCenter::cannotChangeMediumType(QWidget *pParent,
1406 const CMedium &medium,
1407 KMediumType oldMediumType,
1408 KMediumType newMediumType)
1409{
1410 message(pParent ? pParent : mainWindowShown(), Error,
1411 tr("<p>Error changing medium type from <b>%1</b> to <b>%2</b>.</p>")
1412 .arg(gpConverter->toString(oldMediumType)).arg(gpConverter->toString(newMediumType)),
1413 formatErrorInfo(medium));
1414}
1415
1416bool UIMessageCenter::confirmReleaseMedium(QWidget *pParent,
1417 const UIMedium &aMedium,
1418 const QString &strUsage)
1419{
1420 /** @todo (translation-related): the gender of "the" in translations
1421 * will depend on the gender of aMedium.type(). */
1422 return messageOkCancel(pParent, Question,
1423 tr("<p>Are you sure you want to release the %1 "
1424 "<nobr><b>%2</b></nobr>?</p>"
1425 "<p>This will detach it from the "
1426 "following virtual machine(s): <b>%3</b>.</p>")
1427 .arg(mediumToAccusative(aMedium.type()))
1428 .arg(aMedium.location())
1429 .arg(strUsage),
1430 0 /* pcszAutoConfirmId */,
1431 tr("Release", "detach medium"));
1432}
1433
1434bool UIMessageCenter::confirmRemoveMedium(QWidget *pParent,
1435 const UIMedium &aMedium)
1436{
1437 /** @todo (translation-related): the gender of "the" in translations
1438 * will depend on the gender of aMedium.type(). */
1439 QString msg =
1440 tr("<p>Are you sure you want to remove the %1 "
1441 "<nobr><b>%2</b></nobr> from the list of known media?</p>")
1442 .arg(mediumToAccusative(aMedium.type()))
1443 .arg(aMedium.location());
1444
1445 if (aMedium.type() == UIMediumType_HardDisk &&
1446 aMedium.medium().GetMediumFormat().GetCapabilities() & MediumFormatCapabilities_File)
1447 {
1448 if (aMedium.state() == KMediumState_Inaccessible)
1449 msg +=
1450 tr("Note that as this hard disk is inaccessible its "
1451 "storage unit cannot be deleted right now.");
1452 else
1453 msg +=
1454 tr("The next dialog will let you choose whether you also "
1455 "want to delete the storage unit of this hard disk or "
1456 "keep it for later usage.");
1457 }
1458 else
1459 msg +=
1460 tr("<p>Note that the storage unit of this medium will not be "
1461 "deleted and that it will be possible to use it later again.</p>");
1462
1463 return messageOkCancel(pParent, Question, msg,
1464 "confirmRemoveMedium", /* pcszAutoConfirmId */
1465 tr("Remove", "medium"));
1466}
1467
1468void UIMessageCenter::sayCannotOverwriteHardDiskStorage(QWidget *pParent,
1469 const QString &strLocation)
1470{
1471 message(pParent, Info,
1472 tr("<p>The hard disk storage unit at location <b>%1</b> already "
1473 "exists. You cannot create a new virtual hard disk that uses this "
1474 "location because it can be already used by another virtual hard "
1475 "disk.</p>"
1476 "<p>Please specify a different location.</p>")
1477 .arg(strLocation));
1478}
1479
1480int UIMessageCenter::confirmDeleteHardDiskStorage(QWidget *pParent, const QString &strLocation)
1481{
1482 return message(pParent, Question,
1483 tr("<p>Do you want to delete the storage unit of the hard disk "
1484 "<nobr><b>%1</b></nobr>?</p>"
1485 "<p>If you select <b>Delete</b> then the specified storage unit "
1486 "will be permanently deleted. This operation <b>cannot be "
1487 "undone</b>.</p>"
1488 "<p>If you select <b>Keep</b> then the hard disk will be only "
1489 "removed from the list of known hard disks, but the storage unit "
1490 "will be left untouched which makes it possible to add this hard "
1491 "disk to the list later again.</p>")
1492 .arg(strLocation),
1493 0, /* pcszAutoConfirmId */
1494 QIMessageBox::Yes,
1495 QIMessageBox::No | QIMessageBox::Default,
1496 QIMessageBox::Cancel | QIMessageBox::Escape,
1497 tr("Delete", "hard disk storage"),
1498 tr("Keep", "hard disk storage"));
1499}
1500
1501void UIMessageCenter::cannotDeleteHardDiskStorage(QWidget *pParent,
1502 const CMedium &medium,
1503 const CProgress &progress)
1504{
1505 /* below, we use CMedium (medium) to preserve current error info
1506 * for formatErrorInfo() */
1507
1508 message(pParent, Error,
1509 tr("Failed to delete the storage unit of the hard disk <b>%1</b>.")
1510 .arg(CMedium(medium).GetLocation()),
1511 !medium.isOk() ? formatErrorInfo(medium) :
1512 !progress.isOk() ? formatErrorInfo(progress) :
1513 formatErrorInfo(progress.GetErrorInfo()));
1514}
1515
1516int UIMessageCenter::askAboutHardDiskAttachmentCreation(QWidget *pParent,
1517 const QString &strControllerName)
1518{
1519 return message(pParent, Question,
1520 tr("<p>You are about to add a virtual hard disk to controller <b>%1</b>.</p>"
1521 "<p>Would you like to create a new, empty file to hold the disk contents or select an existing one?</p>")
1522 .arg(strControllerName),
1523 0, /* pcszAutoConfirmId */
1524 QIMessageBox::Yes,
1525 QIMessageBox::No,
1526 QIMessageBox::Cancel | QIMessageBox::Default | QIMessageBox::Escape,
1527 tr("Create &new disk", "add attachment routine"),
1528 tr("&Choose existing disk", "add attachment routine"));
1529}
1530
1531int UIMessageCenter::askAboutOpticalAttachmentCreation(QWidget *pParent,
1532 const QString &strControllerName)
1533{
1534 return message(pParent, Question,
1535 tr("<p>You are about to add a new CD/DVD drive to controller <b>%1</b>.</p>"
1536 "<p>Would you like to choose a virtual CD/DVD disk to put in the drive "
1537 "or to leave it empty for now?</p>")
1538 .arg(strControllerName),
1539 0, /* pcszAutoConfirmId */
1540 QIMessageBox::Yes,
1541 QIMessageBox::No,
1542 QIMessageBox::Cancel | QIMessageBox::Default | QIMessageBox::Escape,
1543 tr("&Choose disk", "add attachment routine"),
1544 tr("Leave &empty", "add attachment routine"));
1545}
1546
1547int UIMessageCenter::askAboutFloppyAttachmentCreation(QWidget *pParent,
1548 const QString &strControllerName)
1549{
1550 return message(pParent, Question,
1551 tr("<p>You are about to add a new floppy drive to controller <b>%1</b>.</p>"
1552 "<p>Would you like to choose a virtual floppy 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::confirmRemovingOfLastDVDDevice() const
1564{
1565 return messageOkCancel(QApplication::activeWindow(), Info,
1566 tr("<p>Are you sure you want to delete the CD/DVD-ROM device?</p>"
1567 "<p>You will not be able to mount any CDs or ISO images "
1568 "or install the Guest Additions without it!</p>"),
1569 0, /* pcszAutoConfirmId */
1570 tr("&Remove", "medium"));
1571}
1572
1573void UIMessageCenter::cannotCreateHardDiskStorage(QWidget *pParent,
1574 const CVirtualBox &vbox,
1575 const QString &strLocation,
1576 const CMedium &medium,
1577 const CProgress &progress)
1578{
1579 message(pParent, Error,
1580 tr("Failed to create the hard disk storage <nobr><b>%1</b>.</nobr>")
1581 .arg(strLocation),
1582 !vbox.isOk() ? formatErrorInfo(vbox) :
1583 !medium.isOk() ? formatErrorInfo(medium) :
1584 !progress.isOk() ? formatErrorInfo(progress) :
1585 formatErrorInfo(progress.GetErrorInfo()));
1586}
1587
1588void UIMessageCenter::cannotDetachDevice(QWidget *pParent,
1589 const CMachine &machine,
1590 UIMediumType type,
1591 const QString &strLocation,
1592 const StorageSlot &storageSlot)
1593{
1594 QString strMessage;
1595 switch (type)
1596 {
1597 case UIMediumType_HardDisk:
1598 {
1599 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>.")
1600 .arg(strLocation).arg(gpConverter->toString(storageSlot)).arg(CMachine(machine).GetName());
1601 break;
1602 }
1603 case UIMediumType_DVD:
1604 {
1605 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>.")
1606 .arg(strLocation).arg(gpConverter->toString(storageSlot)).arg(CMachine(machine).GetName());
1607 break;
1608 }
1609 case UIMediumType_Floppy:
1610 {
1611 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>.")
1612 .arg(strLocation).arg(gpConverter->toString(storageSlot)).arg(CMachine(machine).GetName());
1613 break;
1614 }
1615 default:
1616 break;
1617 }
1618 message(pParent ? pParent : mainWindowShown(), Error, strMessage, formatErrorInfo(machine));
1619}
1620
1621int UIMessageCenter::cannotRemountMedium(QWidget *pParent,
1622 const CMachine &machine,
1623 const UIMedium &aMedium,
1624 bool fMount,
1625 bool fRetry)
1626{
1627 /** @todo (translation-related): the gender of "the" in translations
1628 * will depend on the gender of aMedium.type(). */
1629 QString text;
1630 if (fMount)
1631 {
1632 text = tr("Unable to mount the %1 <nobr><b>%2</b></nobr> on the machine <b>%3</b>.");
1633 if (fRetry) text += tr(" Would you like to force mounting of this medium?");
1634 }
1635 else
1636 {
1637 text = tr("Unable to unmount the %1 <nobr><b>%2</b></nobr> from the machine <b>%3</b>.");
1638 if (fRetry) text += tr(" Would you like to force unmounting of this medium?");
1639 }
1640 if (fRetry)
1641 {
1642 return messageOkCancel(pParent ? pParent : mainWindowShown(), Question, text
1643 .arg(mediumToAccusative(aMedium.type(), aMedium.isHostDrive()))
1644 .arg(aMedium.isHostDrive() ? aMedium.name() : aMedium.location())
1645 .arg(CMachine(machine).GetName()),
1646 formatErrorInfo(machine),
1647 0 /* Auto Confirm ID */,
1648 tr("Force Unmount"));
1649 }
1650 else
1651 {
1652 return message(pParent ? pParent : mainWindowShown(), Error, text
1653 .arg(mediumToAccusative(aMedium.type(), aMedium.isHostDrive()))
1654 .arg(aMedium.isHostDrive() ? aMedium.name() : aMedium.location())
1655 .arg(CMachine(machine).GetName()),
1656 formatErrorInfo(machine));
1657 }
1658}
1659
1660void UIMessageCenter::cannotOpenMedium(QWidget *pParent,
1661 const CVirtualBox &vbox,
1662 UIMediumType type,
1663 const QString &strLocation)
1664{
1665 /** @todo (translation-related): the gender of "the" in translations
1666 * will depend on the gender of aMedium.type(). */
1667 message(pParent ? pParent : mainWindowShown(), Error,
1668 tr("Failed to open the %1 <nobr><b>%2</b></nobr>.")
1669 .arg(mediumToAccusative(type))
1670 .arg(strLocation),
1671 formatErrorInfo(vbox));
1672}
1673
1674void UIMessageCenter::cannotCloseMedium(QWidget *pParent,
1675 const UIMedium &aMedium,
1676 const COMResult &rc)
1677{
1678 /** @todo (translation-related): the gender of "the" in translations
1679 * will depend on the gender of aMedium.type(). */
1680 message(pParent, Error,
1681 tr("Failed to close the %1 <nobr><b>%2</b></nobr>.")
1682 .arg(mediumToAccusative(aMedium.type()))
1683 .arg(aMedium.location()),
1684 formatErrorInfo(rc));
1685}
1686
1687void UIMessageCenter::cannotOpenSession(const CSession &session)
1688{
1689 Assert(session.isNull());
1690
1691 message(
1692 mainWindowShown(),
1693 Error,
1694 tr("Failed to create a new session."),
1695 formatErrorInfo(session)
1696 );
1697}
1698
1699void UIMessageCenter::cannotOpenSession(const CVirtualBox &vbox,
1700 const CMachine &machine,
1701 const CProgress &progress)
1702{
1703 Assert(!vbox.isOk() || progress.isOk());
1704
1705 QString name = machine.GetName();
1706 if (name.isEmpty())
1707 name = QFileInfo(machine.GetSettingsFilePath()).baseName();
1708
1709 message(
1710 mainWindowShown(),
1711 Error,
1712 tr("Failed to open a session for the virtual machine <b>%1</b>.")
1713 .arg(name),
1714 !vbox.isOk() ? formatErrorInfo(vbox) :
1715 formatErrorInfo(progress.GetErrorInfo())
1716 );
1717}
1718
1719void UIMessageCenter::cannotOpenSession(const CMachine &machine)
1720{
1721 COMResult res(machine);
1722 QString name = machine.GetName();
1723 if (name.isEmpty())
1724 name = QFileInfo(machine.GetSettingsFilePath()).baseName();
1725
1726 message(mainWindowShown(), Error,
1727 tr("Failed to open a session for the virtual machine <b>%1</b>.").arg(name),
1728 formatErrorInfo(res));
1729}
1730
1731void UIMessageCenter::cannotGetMediaAccessibility(const UIMedium &aMedium)
1732{
1733 message(qApp->activeWindow(), Error,
1734 tr("Failed to determine the accessibility state of the medium "
1735 "<nobr><b>%1</b></nobr>.")
1736 .arg(aMedium.location()),
1737 formatErrorInfo(aMedium.result()));
1738}
1739
1740int UIMessageCenter::confirmDeletingHostInterface(const QString &strName,
1741 QWidget *pParent)
1742{
1743 return msgCenter().message(pParent, UIMessageCenter::Question,
1744 tr("<p>Deleting this host-only network will remove "
1745 "the host-only interface this network is based on. Do you want to "
1746 "remove the (host-only network) interface <nobr><b>%1</b>?</nobr></p>"
1747 "<p><b>Note:</b> this interface may be in use by one or more "
1748 "virtual network adapters belonging to one of your VMs. "
1749 "After it is removed, these adapters will no longer be usable until "
1750 "you correct their settings by either choosing a different interface "
1751 "name or a different adapter attachment type.</p>").arg(strName),
1752 0, /* pcszAutoConfirmId */
1753 QIMessageBox::Ok | QIMessageBox::Default,
1754 QIMessageBox::Cancel | QIMessageBox::Escape);
1755}
1756
1757void UIMessageCenter::cannotAttachUSBDevice(const CConsole &console,
1758 const QString &device)
1759{
1760 /* preserve the current error info before calling the object again */
1761 COMResult res(console);
1762
1763 message(mainMachineWindowShown(), Error,
1764 tr("Failed to attach the USB device <b>%1</b> "
1765 "to the virtual machine <b>%2</b>.")
1766 .arg(device)
1767 .arg(console.GetMachine().GetName()),
1768 formatErrorInfo(res));
1769}
1770
1771void UIMessageCenter::cannotAttachUSBDevice(const CConsole &console,
1772 const QString &device,
1773 const CVirtualBoxErrorInfo &error)
1774{
1775 message(mainMachineWindowShown(), Error,
1776 tr("Failed to attach the USB device <b>%1</b> "
1777 "to the virtual machine <b>%2</b>.")
1778 .arg(device)
1779 .arg(console.GetMachine().GetName()),
1780 formatErrorInfo(error));
1781}
1782
1783void UIMessageCenter::cannotDetachUSBDevice(const CConsole &console,
1784 const QString &device)
1785{
1786 /* preserve the current error info before calling the object again */
1787 COMResult res(console);
1788
1789 message(mainMachineWindowShown(), Error,
1790 tr("Failed to detach the USB device <b>%1</b> "
1791 "from the virtual machine <b>%2</b>.")
1792 .arg(device)
1793 .arg(console.GetMachine().GetName()),
1794 formatErrorInfo(res));
1795}
1796
1797void UIMessageCenter::cannotDetachUSBDevice(const CConsole &console,
1798 const QString &device,
1799 const CVirtualBoxErrorInfo &error)
1800{
1801 message(mainMachineWindowShown(), Error,
1802 tr("Failed to detach the USB device <b>%1</b> "
1803 "from the virtual machine <b>%2</b>.")
1804 .arg(device)
1805 .arg(console.GetMachine().GetName()),
1806 formatErrorInfo(error));
1807}
1808
1809void UIMessageCenter::remindAboutGuestAdditionsAreNotActive(QWidget *pParent)
1810{
1811 message(pParent, Warning,
1812 tr("<p>The VirtualBox Guest Additions do not appear to be "
1813 "available on this virtual machine, and shared folders "
1814 "cannot be used without them. To use shared folders inside "
1815 "the virtual machine, please install the Guest Additions "
1816 "if they are not installed, or re-install them if they are "
1817 "not working correctly, by selecting <b>Install Guest Additions</b> "
1818 "from the <b>Devices</b> menu. "
1819 "If they are installed but the machine is not yet fully started "
1820 "then shared folders will be available once it is.</p>"),
1821 "remindAboutGuestAdditionsAreNotActive");
1822}
1823
1824bool UIMessageCenter::cannotFindGuestAdditions()
1825{
1826 return messageYesNo(mainMachineWindowShown(), Question,
1827 tr("<p>Could not find the VirtualBox Guest Additions "
1828 "CD image file.</nobr></p><p>Do you wish to "
1829 "download this CD image from the Internet?</p>"));
1830}
1831
1832void UIMessageCenter::cannotMountGuestAdditions(const QString &strMachineName)
1833{
1834 message(mainMachineWindowShown(), Error,
1835 tr("<p>Could not insert the VirtualBox Guest Additions "
1836 "installer CD image into the virtual machine <b>%1</b>, as the machine "
1837 "has no CD/DVD-ROM drives. Please add a drive using the "
1838 "storage page of the virtual machine settings dialog.</p>")
1839 .arg(strMachineName));
1840}
1841
1842bool UIMessageCenter::confirmDownloadAdditions(const QString &strUrl, qulonglong uSize)
1843{
1844 QLocale loc(VBoxGlobal::languageId());
1845 return messageOkCancel(networkManagerOrMainMachineWindowShown(), Question,
1846 tr("<p>Are you sure you want to download the VirtualBox "
1847 "Guest Additions CD image from "
1848 "<nobr><a href=\"%1\">%2</a></nobr> "
1849 "(size %3 bytes)?</p>").arg(strUrl).arg(strUrl).arg(loc.toString(uSize)),
1850 0, /* pcszAutoConfirmId */
1851 tr("Download", "additions"));
1852}
1853
1854bool UIMessageCenter::confirmMountAdditions(const QString &strUrl, const QString &strSrc)
1855{
1856 return messageOkCancel(networkManagerOrMainMachineWindowShown(), Question,
1857 tr("<p>The VirtualBox Guest Additions CD image has been "
1858 "successfully downloaded from "
1859 "<nobr><a href=\"%1\">%2</a></nobr> "
1860 "and saved locally as <nobr><b>%3</b>.</nobr></p>"
1861 "<p>Do you wish to register this CD image and mount it "
1862 "on the virtual CD/DVD drive?</p>")
1863 .arg(strUrl).arg(strUrl).arg(strSrc),
1864 0, /* pcszAutoConfirmId */
1865 tr("Mount", "additions"));
1866}
1867
1868void UIMessageCenter::warnAboutAdditionsCantBeSaved(const QString &strTarget)
1869{
1870 message(networkManagerOrMainMachineWindowShown(), Error,
1871 tr("<p>Failed to save the downloaded file as <nobr><b>%1</b>.</nobr></p>")
1872 .arg(QDir::toNativeSeparators(strTarget)));
1873}
1874
1875bool UIMessageCenter::askAboutUserManualDownload(const QString &strMissedLocation)
1876{
1877 return messageOkCancel(mainWindowShown(), Question,
1878 tr("<p>Could not find the VirtualBox User Manual "
1879 "<nobr><b>%1</b>.</nobr></p><p>Do you wish to "
1880 "download this file from the Internet?</p>")
1881 .arg(strMissedLocation),
1882 0, /* Auto-confirm Id */
1883 tr("Download", "additions"));
1884}
1885
1886bool UIMessageCenter::confirmUserManualDownload(const QString &strURL, qulonglong uSize)
1887{
1888 QLocale loc(VBoxGlobal::languageId());
1889 return messageOkCancel(networkManagerOrMainWindowShown(), Question,
1890 tr("<p>Are you sure you want to download the VirtualBox "
1891 "User Manual from "
1892 "<nobr><a href=\"%1\">%2</a></nobr> "
1893 "(size %3 bytes)?</p>").arg(strURL).arg(strURL).arg(loc.toString(uSize)),
1894 0, /* Auto-confirm Id */
1895 tr("Download", "additions"));
1896}
1897
1898void UIMessageCenter::warnAboutUserManualDownloaded(const QString &strURL, const QString &strTarget)
1899{
1900 message(networkManagerOrMainWindowShown(), Warning,
1901 tr("<p>The VirtualBox User Manual has been "
1902 "successfully downloaded from "
1903 "<nobr><a href=\"%1\">%2</a></nobr> "
1904 "and saved locally as <nobr><b>%3</b>.</nobr></p>")
1905 .arg(strURL).arg(strURL).arg(strTarget));
1906}
1907
1908void UIMessageCenter::warnAboutUserManualCantBeSaved(const QString &strURL, const QString &strTarget)
1909{
1910 message(networkManagerOrMainWindowShown(), Error,
1911 tr("<p>The VirtualBox User Manual has been "
1912 "successfully downloaded from "
1913 "<nobr><a href=\"%1\">%2</a></nobr> "
1914 "but can't be saved locally as <nobr><b>%3</b>.</nobr></p>"
1915 "<p>Please choose another location for that file.</p>")
1916 .arg(strURL).arg(strURL).arg(strTarget));
1917}
1918
1919bool UIMessageCenter::proposeDownloadExtensionPack(const QString &strExtPackName, const QString &strExtPackVersion)
1920{
1921 return messageOkCancel(mainWindowShown(),
1922 Question,
1923 tr("<p>You have an old version (%1) of the <b><nobr>%2</nobr></b> installed.</p>"
1924 "<p>Do you wish to download latest one from the Internet?</p>")
1925 .arg(strExtPackVersion).arg(strExtPackName),
1926 0, /* Auto-confirm Id */
1927 tr("Download", "extension pack"));
1928}
1929
1930bool UIMessageCenter::requestUserDownloadExtensionPack(const QString &strExtPackName, const QString &strExtPackVersion, const QString &strVBoxVersion)
1931{
1932 return message(mainWindowShown(), Info,
1933 tr("<p>You have version %1 of the <b><nobr>%2</nobr></b> installed.</p>"
1934 "<p>You should download and install version %3 of this extension pack from Oracle!</p>")
1935 .arg(strExtPackVersion).arg(strExtPackName).arg(strVBoxVersion),
1936 0, /* Auto-confirm Id */
1937 QIMessageBox::Ok | QIMessageBox::Default,
1938 0,
1939 0,
1940 tr("Ok", "extension pack"));
1941}
1942
1943bool UIMessageCenter::confirmDownloadExtensionPack(const QString &strExtPackName, const QString &strURL, qulonglong uSize)
1944{
1945 QLocale loc(VBoxGlobal::languageId());
1946 return messageOkCancel(networkManagerOrMainWindowShown(), Question,
1947 tr("<p>Are you sure you want to download the <b><nobr>%1</nobr></b> "
1948 "from <nobr><a href=\"%2\">%2</a></nobr> (size %3 bytes)?</p>")
1949 .arg(strExtPackName, strURL, loc.toString(uSize)),
1950 0, /* Auto-confirm Id */
1951 tr("Download", "extension pack"));
1952}
1953
1954bool UIMessageCenter::proposeInstallExtentionPack(const QString &strExtPackName, const QString &strFrom, const QString &strTo)
1955{
1956 return messageOkCancel(networkManagerOrMainWindowShown(), Question,
1957 tr("<p>The <b><nobr>%1</nobr></b> has been "
1958 "successfully downloaded from <nobr><a href=\"%2\">%2</a></nobr> "
1959 "and saved locally as <nobr><b>%3</b>.</nobr></p>"
1960 "<p>Do you wish to install this extension pack?</p>")
1961 .arg(strExtPackName, strFrom, strTo),
1962 0, /* Auto-confirm Id */
1963 tr ("Install", "extension pack"));
1964}
1965
1966void UIMessageCenter::warnAboutExtentionPackCantBeSaved(const QString &strExtPackName, const QString &strFrom, const QString &strTo)
1967{
1968 message(networkManagerOrMainWindowShown(), Error,
1969 tr("<p>The <b><nobr>%1</nobr></b> has been "
1970 "successfully downloaded from <nobr><a href=\"%2\">%2</a></nobr> "
1971 "but can't be saved locally as <nobr><b>%3</b>.</nobr></p>"
1972 "<p>Please choose another location for that file.</p>")
1973 .arg(strExtPackName, strFrom, strTo));
1974}
1975
1976void UIMessageCenter::cannotConnectRegister(QWidget *pParent,
1977 const QString &strUrl,
1978 const QString &strReason)
1979{
1980 /* we don't want to expose the registration script URL to the user
1981 * if he simply doesn't have an internet connection */
1982 Q_UNUSED(strUrl);
1983
1984 message(pParent, Error,
1985 tr("<p>Failed to connect to the VirtualBox online "
1986 "registration service due to the following error:</p><p><b>%1</b></p>")
1987 .arg(strReason));
1988}
1989
1990void UIMessageCenter::showRegisterResult(QWidget *pParent,
1991 const QString &strResult)
1992{
1993 if (strResult == "OK")
1994 {
1995 /* On successful registration attempt */
1996 message(pParent, Info,
1997 tr("<p>Congratulations! You have been successfully registered "
1998 "as a user of VirtualBox.</p>"
1999 "<p>Thank you for finding time to fill out the "
2000 "registration form!</p>"));
2001 }
2002 else
2003 {
2004 QString parsed;
2005
2006 /* Else parse and translate special key-words */
2007 if (strResult == "AUTHFAILED")
2008 parsed = tr("<p>Invalid e-mail address or password specified.</p>");
2009
2010 message(pParent, Error,
2011 tr("<p>Failed to register the VirtualBox product.</p><p>%1</p>")
2012 .arg(parsed.isNull() ? strResult : parsed));
2013 }
2014}
2015
2016void UIMessageCenter::showUpdateSuccess(const QString &strVersion, const QString &strLink)
2017{
2018 message(networkManagerOrMainWindowShown(), Info,
2019 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>"
2020 "<p>You can download this version using the link:</p>"
2021 "<p><a href=%2>%3</a></p>")
2022 .arg(strVersion, strLink, strLink));
2023}
2024
2025void UIMessageCenter::showUpdateNotFound()
2026{
2027 message(networkManagerOrMainWindowShown(), Info,
2028 tr("You are already running the most recent version of VirtualBox."));
2029}
2030
2031bool UIMessageCenter::askAboutCancelAllNetworkRequest(QWidget *pParent)
2032{
2033 return messageOkCancel(pParent, Question, tr("Do you wish to cancel all current network operations?"));
2034}
2035
2036/**
2037 * @return @c true if the user has confirmed input capture (this is always
2038 * the case if the dialog was autoconfirmed). @a pfAutoConfirmed, when not
2039 * NULL, will receive @c true if the dialog wasn't actually shown.
2040 */
2041bool UIMessageCenter::confirmInputCapture(bool *pfAutoConfirmed /* = NULL */)
2042{
2043 int rc = message(mainMachineWindowShown(), Info,
2044 tr("<p>You have <b>clicked the mouse</b> inside the Virtual Machine display "
2045 "or pressed the <b>host key</b>. This will cause the Virtual Machine to "
2046 "<b>capture</b> the host mouse pointer (only if the mouse pointer "
2047 "integration is not currently supported by the guest OS) and the "
2048 "keyboard, which will make them unavailable to other applications "
2049 "running on your host machine."
2050 "</p>"
2051 "<p>You can press the <b>host key</b> at any time to <b>uncapture</b> the "
2052 "keyboard and mouse (if it is captured) and return them to normal "
2053 "operation. The currently assigned host key is shown on the status bar "
2054 "at the bottom of the Virtual Machine window, next to the&nbsp;"
2055 "<img src=:/hostkey_16px.png/>&nbsp;icon. This icon, together "
2056 "with the mouse icon placed nearby, indicate the current keyboard "
2057 "and mouse capture state."
2058 "</p>") +
2059 tr("<p>The host key is currently defined as <b>%1</b>.</p>",
2060 "additional message box paragraph")
2061 .arg(UIHotKeyCombination::toReadableString(vboxGlobal().settings().hostCombo())),
2062 "confirmInputCapture",
2063 QIMessageBox::Ok | QIMessageBox::Default,
2064 QIMessageBox::Cancel | QIMessageBox::Escape,
2065 0,
2066 tr("Capture", "do input capture"));
2067
2068 if (pfAutoConfirmed)
2069 *pfAutoConfirmed = (rc & AutoConfirmed);
2070
2071 return (rc & QIMessageBox::ButtonMask) == QIMessageBox::Ok;
2072}
2073
2074void UIMessageCenter::remindAboutAutoCapture()
2075{
2076 message(mainMachineWindowShown(), Info,
2077 tr("<p>You have the <b>Auto capture keyboard</b> option turned on. "
2078 "This will cause the Virtual Machine to automatically <b>capture</b> "
2079 "the keyboard every time the VM window is activated and make it "
2080 "unavailable to other applications running on your host machine: "
2081 "when the keyboard is captured, all keystrokes (including system ones "
2082 "like Alt-Tab) will be directed to the VM."
2083 "</p>"
2084 "<p>You can press the <b>host key</b> at any time to <b>uncapture</b> the "
2085 "keyboard and mouse (if it is captured) and return them to normal "
2086 "operation. The currently assigned host key is shown on the status bar "
2087 "at the bottom of the Virtual Machine window, next to the&nbsp;"
2088 "<img src=:/hostkey_16px.png/>&nbsp;icon. This icon, together "
2089 "with the mouse icon placed nearby, indicate the current keyboard "
2090 "and mouse capture state."
2091 "</p>") +
2092 tr("<p>The host key is currently defined as <b>%1</b>.</p>",
2093 "additional message box paragraph")
2094 .arg(UIHotKeyCombination::toReadableString(vboxGlobal().settings().hostCombo())),
2095 "remindAboutAutoCapture");
2096}
2097
2098void UIMessageCenter::remindAboutMouseIntegration(bool fSupportsAbsolute)
2099{
2100 if (isAlreadyShown("remindAboutMouseIntegration"))
2101 return;
2102 setShownStatus("remindAboutMouseIntegration");
2103
2104 static const char *kNames [2] =
2105 {
2106 "remindAboutMouseIntegrationOff",
2107 "remindAboutMouseIntegrationOn"
2108 };
2109
2110 /* Close the previous (outdated) window if any. We use kName as
2111 * pcszAutoConfirmId which is also used as the widget name by default. */
2112 {
2113 QWidget *outdated =
2114 VBoxGlobal::findWidget(NULL, kNames [int (!fSupportsAbsolute)],
2115 "QIMessageBox");
2116 if (outdated)
2117 outdated->close();
2118 }
2119
2120 if (fSupportsAbsolute)
2121 {
2122 message(mainMachineWindowShown(), Info,
2123 tr("<p>The Virtual Machine reports that the guest OS supports "
2124 "<b>mouse pointer integration</b>. This means that you do not "
2125 "need to <i>capture</i> the mouse pointer to be able to use it "
2126 "in your guest OS -- all "
2127 "mouse actions you perform when the mouse pointer is over the "
2128 "Virtual Machine's display are directly sent to the guest OS. "
2129 "If the mouse is currently captured, it will be automatically "
2130 "uncaptured."
2131 "</p>"
2132 "<p>The mouse icon on the status bar will look like&nbsp;"
2133 "<img src=:/mouse_seamless_16px.png/>&nbsp;to inform you that mouse "
2134 "pointer integration is supported by the guest OS and is "
2135 "currently turned on."
2136 "</p>"
2137 "<p><b>Note</b>: Some applications may behave incorrectly in "
2138 "mouse pointer integration mode. You can always disable it for "
2139 "the current session (and enable it again) by selecting the "
2140 "corresponding action from the menu bar."
2141 "</p>"),
2142 kNames [1] /* pcszAutoConfirmId */);
2143 }
2144 else
2145 {
2146 message(mainMachineWindowShown(), Info,
2147 tr("<p>The Virtual Machine reports that the guest OS does not "
2148 "support <b>mouse pointer integration</b> in the current video "
2149 "mode. You need to capture the mouse (by clicking over the VM "
2150 "display or pressing the host key) in order to use the "
2151 "mouse inside the guest OS.</p>"),
2152 kNames [0] /* pcszAutoConfirmId */);
2153 }
2154
2155 clearShownStatus("remindAboutMouseIntegration");
2156}
2157
2158/**
2159 * @return @c false if the dialog wasn't actually shown (i.e. it was
2160 * autoconfirmed).
2161 */
2162bool UIMessageCenter::remindAboutPausedVMInput()
2163{
2164 int rc = message(
2165 mainMachineWindowShown(),
2166 Info,
2167 tr("<p>The Virtual Machine is currently in the <b>Paused</b> state and "
2168 "not able to see any keyboard or mouse input. If you want to "
2169 "continue to work inside the VM, you need to resume it by selecting the "
2170 "corresponding action from the menu bar.</p>"),
2171 "remindAboutPausedVMInput"
2172 );
2173 return !(rc & AutoConfirmed);
2174}
2175
2176/** @return true if the user has chosen to show the Disk Manager Window */
2177bool UIMessageCenter::remindAboutInaccessibleMedia()
2178{
2179 int rc = message(&vboxGlobal().selectorWnd(), Warning,
2180 tr("<p>One or more virtual hard disks, CD/DVD or "
2181 "floppy media are not currently accessible. As a result, you will "
2182 "not be able to operate virtual machines that use these media until "
2183 "they become accessible later.</p>"
2184 "<p>Press <b>Check</b> to open the Virtual Media Manager window and "
2185 "see what media are inaccessible, or press <b>Ignore</b> to "
2186 "ignore this message.</p>"),
2187 "remindAboutInaccessibleMedia",
2188 QIMessageBox::Ok | QIMessageBox::Default,
2189 QIMessageBox::Ignore | QIMessageBox::Escape,
2190 0,
2191 tr("Check", "inaccessible media message box"));
2192
2193 return rc == QIMessageBox::Ok; /* implies !AutoConfirmed */
2194}
2195
2196/**
2197 * Shows user a proposal to either convert configuration files or
2198 * Exit the application leaving all as already is.
2199 *
2200 * @param strFileList List of files for auto-conversion (may use Qt HTML).
2201 * @param fAfterRefresh @true when called after the VM refresh.
2202 *
2203 * @return QIMessageBox::Ok (Save + Backup), QIMessageBox::Cancel (Exit)
2204 */
2205int UIMessageCenter::warnAboutSettingsAutoConversion(const QString &strFileList,
2206 bool fAfterRefresh)
2207{
2208 if (!fAfterRefresh)
2209 {
2210 /* Common variant for all VMs */
2211 return message(mainWindowShown(), Info,
2212 tr("<p>Your existing VirtualBox settings files will be automatically "
2213 "converted from the old format to a new format required by the "
2214 "new version of VirtualBox.</p>"
2215 "<p>Press <b>OK</b> to start VirtualBox now or press <b>Exit</b> if "
2216 "you want to terminate the VirtualBox "
2217 "application without any further actions.</p>"),
2218 NULL /* pcszAutoConfirmId */,
2219 QIMessageBox::Ok | QIMessageBox::Default,
2220 QIMessageBox::Cancel | QIMessageBox::Escape,
2221 0,
2222 0,
2223 tr("E&xit", "warnAboutSettingsAutoConversion message box"));
2224 }
2225 else
2226 {
2227 /* Particular VM variant */
2228 return message(mainWindowShown(), Info,
2229 tr("<p>The following VirtualBox settings files will be automatically "
2230 "converted from the old format to a new format required by the "
2231 "new version of VirtualBox.</p>"
2232 "<p>Press <b>OK</b> to start VirtualBox now or press <b>Exit</b> if "
2233 "you want to terminate the VirtualBox "
2234 "application without any further actions.</p>"),
2235 QString("<!--EOM-->%1").arg(strFileList),
2236 NULL /* pcszAutoConfirmId */,
2237 QIMessageBox::Ok | QIMessageBox::Default,
2238 QIMessageBox::Cancel | QIMessageBox::Escape,
2239 0,
2240 0,
2241 tr("E&xit", "warnAboutSettingsAutoConversion message box"));
2242 }
2243}
2244
2245/**
2246 * @param strHotKey Fullscreen hot key as defined in the menu.
2247 *
2248 * @return @c true if the user has chosen to go fullscreen (this is always
2249 * the case if the dialog was autoconfirmed).
2250 */
2251bool UIMessageCenter::confirmGoingFullscreen(const QString &strHotKey)
2252{
2253 return messageOkCancel(mainMachineWindowShown(), Info,
2254 tr("<p>The virtual machine window will be now switched to <b>fullscreen</b> mode. "
2255 "You can go back to windowed mode at any time by pressing <b>%1</b>.</p>"
2256 "<p>Note that the <i>Host</i> key is currently defined as <b>%2</b>.</p>"
2257 "<p>Note that the main menu bar is hidden in fullscreen mode. "
2258 "You can access it by pressing <b>Host+Home</b>.</p>")
2259 .arg(strHotKey)
2260 .arg(UIHotKeyCombination::toReadableString(vboxGlobal().settings().hostCombo())),
2261 "confirmGoingFullscreen",
2262 tr("Switch", "fullscreen"));
2263}
2264
2265/**
2266 * @param strHotKey Seamless hot key as defined in the menu.
2267 *
2268 * @return @c true if the user has chosen to go seamless (this is always
2269 * the case if the dialog was autoconfirmed).
2270 */
2271bool UIMessageCenter::confirmGoingSeamless(const QString &strHotKey)
2272{
2273 return messageOkCancel(mainMachineWindowShown(), Info,
2274 tr("<p>The virtual machine window will be now switched to <b>Seamless</b> mode. "
2275 "You can go back to windowed mode at any time by pressing <b>%1</b>.</p>"
2276 "<p>Note that the <i>Host</i> key is currently defined as <b>%2</b>.</p>"
2277 "<p>Note that the main menu bar is hidden in seamless mode. "
2278 "You can access it by pressing <b>Host+Home</b>.</p>")
2279 .arg(strHotKey)
2280 .arg(UIHotKeyCombination::toReadableString(vboxGlobal().settings().hostCombo())),
2281 "confirmGoingSeamless",
2282 tr("Switch", "seamless"));
2283}
2284
2285/**
2286 * @param strHotKey Scale hot key as defined in the menu.
2287 *
2288 * @return @c true if the user has chosen to go scale (this is always
2289 * the case if the dialog was autoconfirmed).
2290 */
2291bool UIMessageCenter::confirmGoingScale(const QString &strHotKey)
2292{
2293 return messageOkCancel(mainMachineWindowShown(), Info,
2294 tr("<p>The virtual machine window will be now switched to <b>Scale</b> mode. "
2295 "You can go back to windowed mode at any time by pressing <b>%1</b>.</p>"
2296 "<p>Note that the <i>Host</i> key is currently defined as <b>%2</b>.</p>"
2297 "<p>Note that the main menu bar is hidden in scale mode. "
2298 "You can access it by pressing <b>Host+Home</b>.</p>")
2299 .arg(strHotKey)
2300 .arg(UIHotKeyCombination::toReadableString(vboxGlobal().settings().hostCombo())),
2301 "confirmGoingScale",
2302 tr("Switch", "scale"));
2303}
2304
2305/**
2306 * Returns @c true if the user has selected to power off the machine.
2307 */
2308bool UIMessageCenter::remindAboutGuruMeditation(const CConsole &console,
2309 const QString &strLogFolder)
2310{
2311 Q_UNUSED(console);
2312
2313 int rc = message(mainMachineWindowShown(), GuruMeditation,
2314 tr("<p>A critical error has occurred while running the virtual "
2315 "machine and the machine execution has been stopped.</p>"
2316 ""
2317 "<p>For help, please see the Community section on "
2318 "<a href=http://www.virtualbox.org>http://www.virtualbox.org</a> "
2319 "or your support contract. Please provide the contents of the "
2320 "log file <tt>VBox.log</tt> and the image file <tt>VBox.png</tt>, "
2321 "which you can find in the <nobr><b>%1</b></nobr> directory, "
2322 "as well as a description of what you were doing when this error "
2323 "happened. "
2324 ""
2325 "Note that you can also access the above files by selecting "
2326 "<b>Show Log</b> from the <b>Machine</b> menu of the main "
2327 "VirtualBox window.</p>"
2328 ""
2329 "<p>Press <b>OK</b> if you want to power off the machine "
2330 "or press <b>Ignore</b> if you want to leave it as is for debugging. "
2331 "Please note that debugging requires special knowledge and tools, so "
2332 "it is recommended to press <b>OK</b> now.</p>")
2333 .arg(strLogFolder),
2334 0, /* pcszAutoConfirmId */
2335 QIMessageBox::Ok | QIMessageBox::Default,
2336 QIMessageBox::Ignore | QIMessageBox::Escape);
2337
2338 return rc == QIMessageBox::Ok;
2339}
2340
2341/**
2342 * @return @c true if the user has selected to reset the machine.
2343 */
2344bool UIMessageCenter::confirmVMReset(const QString &strNames)
2345{
2346 return messageOkCancel(mainMachineWindowShown(), Question,
2347 tr("<p>Do you really want to reset the following virtual machines?</p>"
2348 "<p><b>%1</b></p><p>This will cause any unsaved data "
2349 "in applications running inside it to be lost.</p>")
2350 .arg(strNames),
2351 "confirmVMReset" /* pcszAutoConfirmId */,
2352 tr("Reset", "machine"));
2353}
2354
2355bool UIMessageCenter::confirmVMACPIShutdown(const QString &strNames)
2356{
2357 return messageOkCancel(mainMachineWindowShown(), Question,
2358 tr("<p>Do you really want to send an ACPI shutdown signal "
2359 "to the following virtual machines?</p><p><b>%1</b></p>")
2360 .arg(strNames),
2361 "confirmVMACPIShutdown" /* pcszAutoConfirmId */,
2362 tr("ACPI Shutdown", "machine"));
2363}
2364
2365bool UIMessageCenter::confirmVMPowerOff(const QString &strNames)
2366{
2367 return messageOkCancel(mainMachineWindowShown(), Question,
2368 tr("<p>Do you really want to power off the following virtual machines?</p>"
2369 "<p><b>%1</b></p><p>This will cause any unsaved data in applications "
2370 "running inside it to be lost.</p>")
2371 .arg(strNames),
2372 "confirmVMPowerOff" /* pcszAutoConfirmId */,
2373 tr("Power Off", "machine"));
2374}
2375
2376void UIMessageCenter::warnAboutCannotRemoveMachineFolder(QWidget *pParent, const QString &strFolderName)
2377{
2378 QFileInfo fi(strFolderName);
2379 message(pParent ? pParent : mainWindowShown(), Critical,
2380 tr("<p>Cannot remove the machine folder <nobr><b>%1</b>.</nobr></p>"
2381 "<p>Please check that this folder really exists and that you have permissions to remove it.</p>")
2382 .arg(fi.fileName()));
2383}
2384
2385void UIMessageCenter::warnAboutCannotRewriteMachineFolder(QWidget *pParent, const QString &strFolderName)
2386{
2387 QFileInfo fi(strFolderName);
2388 message(pParent ? pParent : mainWindowShown(), Critical,
2389 tr("<p>Cannot create the machine folder <b>%1</b> in the parent folder <nobr><b>%2</b>.</nobr></p>"
2390 "<p>This folder already exists and possibly belongs to another machine.</p>")
2391 .arg(fi.fileName()).arg(fi.absolutePath()));
2392}
2393
2394void UIMessageCenter::warnAboutCannotCreateMachineFolder(QWidget *pParent, const QString &strFolderName)
2395{
2396 QFileInfo fi(strFolderName);
2397 message(pParent ? pParent : mainWindowShown(), Critical,
2398 tr("<p>Cannot create the machine folder <b>%1</b> in the parent folder <nobr><b>%2</b>.</nobr></p>"
2399 "<p>Please check that the parent really exists and that you have permissions to create the machine folder.</p>")
2400 .arg(fi.fileName()).arg(fi.absolutePath()));
2401}
2402
2403/**
2404 * @return @c true if the user has selected to continue without attaching a
2405 * hard disk.
2406 */
2407bool UIMessageCenter::confirmHardDisklessMachine(QWidget *pParent)
2408{
2409 return message(pParent, Warning,
2410 tr("You are about to create a new virtual machine without a hard drive. "
2411 "You will not be able to install an operating system on the machine "
2412 "until you add one. In the mean time you will only be able to start the "
2413 "machine using a virtual optical disk or from the network."),
2414 0, /* pcszAutoConfirmId */
2415 QIMessageBox::Ok,
2416 QIMessageBox::Cancel | QIMessageBox::Default | QIMessageBox::Escape,
2417 0,
2418 tr("Continue", "no hard disk attached"),
2419 tr("Go Back", "no hard disk attached")) == QIMessageBox::Ok;
2420}
2421
2422void UIMessageCenter::cannotRunInSelectorMode()
2423{
2424 message(mainWindowShown(), Critical,
2425 tr("<p>Cannot run VirtualBox in <i>VM Selector</i> "
2426 "mode due to local restrictions.</p>"
2427 "<p>The application will now terminate.</p>"));
2428}
2429
2430void UIMessageCenter::cannotImportAppliance(CAppliance *pAppliance,
2431 QWidget *pParent /* = NULL */) const
2432{
2433 if (pAppliance->isNull())
2434 {
2435 message(pParent ? pParent : mainWindowShown(),
2436 Error,
2437 tr("Failed to open appliance."));
2438 }
2439 else
2440 {
2441 /* Preserve the current error info before calling the object again */
2442 COMResult res(*pAppliance);
2443
2444 /* Add the warnings in the case of an early error */
2445 QVector<QString> w = pAppliance->GetWarnings();
2446 QString wstr;
2447 foreach(const QString &str, w)
2448 wstr += QString("<br />Warning: %1").arg(str);
2449 if (!wstr.isEmpty())
2450 wstr = "<br />" + wstr;
2451
2452 message(pParent ? pParent : mainWindowShown(),
2453 Error,
2454 tr("Failed to open/interpret appliance <b>%1</b>.").arg(pAppliance->GetPath()),
2455 wstr +
2456 formatErrorInfo(res));
2457 }
2458}
2459
2460void UIMessageCenter::cannotImportAppliance(const CProgress &progress,
2461 CAppliance* pAppliance,
2462 QWidget *pParent /* = NULL */) const
2463{
2464 AssertWrapperOk(progress);
2465
2466 message(pParent ? pParent : mainWindowShown(),
2467 Error,
2468 tr("Failed to import appliance <b>%1</b>.").arg(pAppliance->GetPath()),
2469 formatErrorInfo(progress.GetErrorInfo()));
2470}
2471
2472void UIMessageCenter::cannotCheckFiles(const CProgress &progress,
2473 QWidget *pParent /* = NULL */) const
2474{
2475 AssertWrapperOk(progress);
2476
2477 message(pParent ? pParent : mainWindowShown(),
2478 Error,
2479 tr("Failed to check files."),
2480 formatErrorInfo(progress.GetErrorInfo()));
2481}
2482
2483void UIMessageCenter::cannotRemoveFiles(const CProgress &progress,
2484 QWidget *pParent /* = NULL */) const
2485{
2486 AssertWrapperOk(progress);
2487
2488 message(pParent ? pParent : mainWindowShown(),
2489 Error,
2490 tr("Failed to remove file."),
2491 formatErrorInfo(progress.GetErrorInfo()));
2492}
2493
2494bool UIMessageCenter::confirmExportMachinesInSaveState(const QStringList &strMachineNames,
2495 QWidget *pParent /* = NULL */) const
2496{
2497 return messageOkCancel(pParent ? pParent : mainWindowShown(), Warning,
2498 tr("<p>The %n following virtual machine(s) are currently in a saved state: <b>%1</b></p>"
2499 "<p>If you continue the runtime state of the exported machine(s) "
2500 "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).",
2501 strMachineNames.size()).arg(VBoxGlobal::toHumanReadableList(strMachineNames)),
2502 0 /* pcszAutoConfirmId */,
2503 tr("Continue"), tr("Cancel"));
2504}
2505
2506void UIMessageCenter::cannotExportAppliance(CAppliance *pAppliance,
2507 QWidget *pParent /* = NULL */) const
2508{
2509 if (pAppliance->isNull())
2510 {
2511 message(pParent ? pParent : mainWindowShown(),
2512 Error,
2513 tr("Failed to create appliance."));
2514 }
2515 else
2516 {
2517 /* Preserve the current error info before calling the object again */
2518 COMResult res(*pAppliance);
2519
2520 message(pParent ? pParent : mainWindowShown(),
2521 Error,
2522 tr("Failed to prepare the export of the appliance <b>%1</b>.").arg(pAppliance->GetPath()),
2523 formatErrorInfo(res));
2524 }
2525}
2526
2527void UIMessageCenter::cannotExportAppliance(const CMachine &machine,
2528 CAppliance *pAppliance,
2529 QWidget *pParent /* = NULL */) const
2530{
2531 if (pAppliance->isNull() ||
2532 machine.isNull())
2533 {
2534 message(pParent ? pParent : mainWindowShown(),
2535 Error,
2536 tr("Failed to create an appliance."));
2537 }
2538 else
2539 {
2540 message(pParent ? pParent : mainWindowShown(),
2541 Error,
2542 tr("Failed to prepare the export of the appliance <b>%1</b>.").arg(pAppliance->GetPath()),
2543 formatErrorInfo(machine));
2544 }
2545}
2546
2547void UIMessageCenter::cannotExportAppliance(const CProgress &progress,
2548 CAppliance* pAppliance,
2549 QWidget *pParent /* = NULL */) const
2550{
2551 AssertWrapperOk(progress);
2552
2553 message(pParent ? pParent : mainWindowShown(),
2554 Error,
2555 tr("Failed to export appliance <b>%1</b>.").arg(pAppliance->GetPath()),
2556 formatErrorInfo(progress.GetErrorInfo()));
2557}
2558
2559void UIMessageCenter::cannotUpdateGuestAdditions(const CProgress &progress,
2560 QWidget *pParent /* = NULL */) const
2561{
2562 AssertWrapperOk(progress);
2563
2564 message(pParent ? pParent : mainWindowShown(),
2565 Error,
2566 tr("Failed to update Guest Additions. The Guest Additions installation image will be mounted to provide a manual installation."),
2567 formatErrorInfo(progress.GetErrorInfo()));
2568}
2569
2570void UIMessageCenter::cannotOpenExtPack(const QString &strFilename,
2571 const CExtPackManager &extPackManager,
2572 QWidget *pParent)
2573{
2574 message(pParent ? pParent : mainWindowShown(),
2575 Error,
2576 tr("Failed to open the Extension Pack <b>%1</b>.").arg(strFilename),
2577 formatErrorInfo(extPackManager));
2578}
2579
2580void UIMessageCenter::badExtPackFile(const QString &strFilename,
2581 const CExtPackFile &extPackFile,
2582 QWidget *pParent)
2583{
2584 message(pParent ? pParent : mainWindowShown(),
2585 Error,
2586 tr("Failed to open the Extension Pack <b>%1</b>.").arg(strFilename),
2587 "<!--EOM-->" + extPackFile.GetWhyUnusable());
2588}
2589
2590void UIMessageCenter::cannotInstallExtPack(const QString &strFilename,
2591 const CExtPackFile &extPackFile,
2592 const CProgress &progress,
2593 QWidget *pParent)
2594{
2595 if (!pParent)
2596 pParent = mainWindowShown();
2597 QString strErrInfo = !extPackFile.isOk() || progress.isNull()
2598 ? formatErrorInfo(extPackFile) : formatErrorInfo(progress.GetErrorInfo());
2599 message(pParent,
2600 Error,
2601 tr("Failed to install the Extension Pack <b>%1</b>.").arg(strFilename),
2602 strErrInfo);
2603}
2604
2605void UIMessageCenter::cannotUninstallExtPack(const QString &strPackName, const CExtPackManager &extPackManager,
2606 const CProgress &progress, QWidget *pParent)
2607{
2608 if (!pParent)
2609 pParent = mainWindowShown();
2610 QString strErrInfo = !extPackManager.isOk() || progress.isNull()
2611 ? formatErrorInfo(extPackManager) : formatErrorInfo(progress.GetErrorInfo());
2612 message(pParent,
2613 Error,
2614 tr("Failed to uninstall the Extension Pack <b>%1</b>.").arg(strPackName),
2615 strErrInfo);
2616}
2617
2618bool UIMessageCenter::confirmInstallingPackage(const QString &strPackName, const QString &strPackVersion,
2619 const QString &strPackDescription, QWidget *pParent)
2620{
2621 return messageOkCancel(pParent ? pParent : mainWindowShown(),
2622 Question,
2623 tr("<p>You are about to install a VirtualBox extension pack. "
2624 "Extension packs complement the functionality of VirtualBox and can contain system level software "
2625 "that could be potentially harmful to your system. Please review the description below and only proceed "
2626 "if you have obtained the extension pack from a trusted source.</p>"
2627 "<p><table cellpadding=0 cellspacing=0>"
2628 "<tr><td><b>Name:&nbsp;&nbsp;</b></td><td>%1</td></tr>"
2629 "<tr><td><b>Version:&nbsp;&nbsp;</b></td><td>%2</td></tr>"
2630 "<tr><td><b>Description:&nbsp;&nbsp;</b></td><td>%3</td></tr>"
2631 "</table></p>")
2632 .arg(strPackName).arg(strPackVersion).arg(strPackDescription),
2633 0,
2634 tr("&Install"));
2635}
2636
2637bool UIMessageCenter::confirmReplacePackage(const QString &strPackName, const QString &strPackVersionNew,
2638 const QString &strPackVersionOld, const QString &strPackDescription,
2639 QWidget *pParent)
2640{
2641 if (!pParent)
2642 pParent = pParent ? pParent : mainWindowShown(); /* this is boring stuff that messageOkCancel should do! */
2643
2644 QString strBelehrung = tr("Extension packs complement the functionality of VirtualBox and can contain "
2645 "system level software that could be potentially harmful to your system. "
2646 "Please review the description below and only proceed if you have obtained "
2647 "the extension pack from a trusted source.");
2648
2649 QByteArray ba1 = strPackVersionNew.toUtf8();
2650 QByteArray ba2 = strPackVersionOld.toUtf8();
2651 int iVerCmp = RTStrVersionCompare(ba1.constData(), ba2.constData());
2652
2653 bool fRc;
2654 if (iVerCmp > 0)
2655 fRc = messageOkCancel(pParent,
2656 Question,
2657 tr("<p>An older version of the extension pack is already installed, would you like to upgrade? "
2658 "<p>%1</p>"
2659 "<p><table cellpadding=0 cellspacing=0>"
2660 "<tr><td><b>Name:&nbsp;&nbsp;</b></td><td>%2</td></tr>"
2661 "<tr><td><b>New Version:&nbsp;&nbsp;</b></td><td>%3</td></tr>"
2662 "<tr><td><b>Current Version:&nbsp;&nbsp;</b></td><td>%4</td></tr>"
2663 "<tr><td><b>Description:&nbsp;&nbsp;</b></td><td>%5</td></tr>"
2664 "</table></p>")
2665 .arg(strBelehrung).arg(strPackName).arg(strPackVersionNew).arg(strPackVersionOld).arg(strPackDescription),
2666 0,
2667 tr("&Upgrade"));
2668 else if (iVerCmp < 0)
2669 fRc = messageOkCancel(pParent,
2670 Question,
2671 tr("<p>An newer version of the extension pack is already installed, would you like to downgrade? "
2672 "<p>%1</p>"
2673 "<p><table cellpadding=0 cellspacing=0>"
2674 "<tr><td><b>Name:&nbsp;&nbsp;</b></td><td>%2</td></tr>"
2675 "<tr><td><b>New Version:&nbsp;&nbsp;</b></td><td>%3</td></tr>"
2676 "<tr><td><b>Current Version:&nbsp;&nbsp;</b></td><td>%4</td></tr>"
2677 "<tr><td><b>Description:&nbsp;&nbsp;</b></td><td>%5</td></tr>"
2678 "</table></p>")
2679 .arg(strBelehrung).arg(strPackName).arg(strPackVersionNew).arg(strPackVersionOld).arg(strPackDescription),
2680 0,
2681 tr("&Downgrade"));
2682 else
2683 fRc = messageOkCancel(pParent,
2684 Question,
2685 tr("<p>The extension pack is already installed with the same version, would you like reinstall it? "
2686 "<p>%1</p>"
2687 "<p><table cellpadding=0 cellspacing=0>"
2688 "<tr><td><b>Name:&nbsp;&nbsp;</b></td><td>%2</td></tr>"
2689 "<tr><td><b>Version:&nbsp;&nbsp;</b></td><td>%3</td></tr>"
2690 "<tr><td><b>Description:&nbsp;&nbsp;</b></td><td>%4</td></tr>"
2691 "</table></p>")
2692 .arg(strBelehrung).arg(strPackName).arg(strPackVersionOld).arg(strPackDescription),
2693 0,
2694 tr("&Reinstall"));
2695 return fRc;
2696}
2697
2698bool UIMessageCenter::confirmRemovingPackage(const QString &strPackName, QWidget *pParent)
2699{
2700 return messageOkCancel(pParent ? pParent : mainWindowShown(),
2701 Question,
2702 tr("<p>You are about to remove the VirtualBox extension pack <b>%1</b>.</p>"
2703 "<p>Are you sure you want to proceed?</p>").arg(strPackName),
2704 0,
2705 tr("&Remove"));
2706}
2707
2708void UIMessageCenter::notifyAboutExtPackInstalled(const QString &strPackName, QWidget *pParent)
2709{
2710 message(pParent ? pParent : mainWindowShown(),
2711 Info,
2712 tr("The extension pack <br><nobr><b>%1</b><nobr><br> was installed successfully.").arg(strPackName));
2713}
2714
2715void UIMessageCenter::warnAboutIncorrectPort(QWidget *pParent) const
2716{
2717 message(pParent, Error,
2718 tr("The current port forwarding rules are not valid. "
2719 "None of the host or guest port values may be set to zero."));
2720}
2721
2722bool UIMessageCenter::confirmCancelingPortForwardingDialog(QWidget *pParent) const
2723{
2724 return messageOkCancel(pParent, Question,
2725 tr("<p>There are unsaved changes in the port forwarding configuration.</p>"
2726 "<p>If you proceed your changes will be discarded.</p>"));
2727}
2728
2729void UIMessageCenter::showRuntimeError(const CConsole &console, bool fFatal,
2730 const QString &strErrorId,
2731 const QString &strErrorMsg) const
2732{
2733 /// @todo (r=dmik) it's just a preliminary box. We need to:
2734 // - for fFatal errors and non-fFatal with-retry errors, listen for a
2735 // VM state signal to automatically close the message if the VM
2736 // (externally) leaves the Paused state while it is shown.
2737 // - make warning messages modeless
2738 // - add common buttons like Retry/Save/PowerOff/whatever
2739
2740 QByteArray autoConfimId = "showRuntimeError.";
2741
2742 CConsole console1 = console;
2743 KMachineState state = console1.GetState();
2744 Type type;
2745 QString severity;
2746
2747 if (fFatal)
2748 {
2749 /* the machine must be paused on fFatal errors */
2750 Assert(state == KMachineState_Paused);
2751 if (state != KMachineState_Paused)
2752 console1.Pause();
2753 type = Critical;
2754 severity = tr("<nobr>Fatal Error</nobr>", "runtime error info");
2755 autoConfimId += "fatal.";
2756 }
2757 else if (state == KMachineState_Paused)
2758 {
2759 type = Error;
2760 severity = tr("<nobr>Non-Fatal Error</nobr>", "runtime error info");
2761 autoConfimId += "error.";
2762 }
2763 else
2764 {
2765 type = Warning;
2766 severity = tr("<nobr>Warning</nobr>", "runtime error info");
2767 autoConfimId += "warning.";
2768 }
2769
2770 autoConfimId += strErrorId.toUtf8();
2771
2772 QString formatted("<!--EOM-->");
2773
2774 if (!strErrorMsg.isEmpty())
2775 formatted.prepend(QString("<p>%1.</p>").arg(vboxGlobal().emphasize(strErrorMsg)));
2776
2777 if (!strErrorId.isEmpty())
2778 formatted += QString("<table bgcolor=#EEEEEE border=0 cellspacing=0 "
2779 "cellpadding=0 width=100%>"
2780 "<tr><td>%1</td><td>%2</td></tr>"
2781 "<tr><td>%3</td><td>%4</td></tr>"
2782 "</table>")
2783 .arg(tr("<nobr>Error ID: </nobr>", "runtime error info"),
2784 strErrorId)
2785 .arg(tr("Severity: ", "runtime error info"),
2786 severity);
2787
2788 if (!formatted.isEmpty())
2789 formatted = "<qt>" + formatted + "</qt>";
2790
2791 int rc = 0;
2792
2793 if (type == Critical)
2794 {
2795 rc = message(mainMachineWindowShown(), type,
2796 tr("<p>A fatal error has occurred during virtual machine execution! "
2797 "The virtual machine will be powered off. Please copy the "
2798 "following error message using the clipboard to help diagnose "
2799 "the problem:</p>"),
2800 formatted, autoConfimId.data());
2801
2802 /* always power down after a fFatal error */
2803 console1.PowerDown();
2804 }
2805 else if (type == Error)
2806 {
2807 rc = message(mainMachineWindowShown(), type,
2808 tr("<p>An error has occurred during virtual machine execution! "
2809 "The error details are shown below. You may try to correct "
2810 "the error and resume the virtual machine "
2811 "execution.</p>"),
2812 formatted, autoConfimId.data());
2813 }
2814 else
2815 {
2816 rc = message(mainMachineWindowShown(), type,
2817 tr("<p>The virtual machine execution may run into an error "
2818 "condition as described below. "
2819 "We suggest that you take "
2820 "an appropriate action to avert the error."
2821 "</p>"),
2822 formatted, autoConfimId.data());
2823 }
2824
2825 NOREF(rc);
2826}
2827
2828/* static */
2829QString UIMessageCenter::mediumToAccusative(UIMediumType type, bool fIsHostDrive /* = false */)
2830{
2831 QString strType =
2832 type == UIMediumType_HardDisk ?
2833 tr("hard disk", "failed to mount ...") :
2834 type == UIMediumType_DVD && fIsHostDrive ?
2835 tr("CD/DVD", "failed to mount ... host-drive") :
2836 type == UIMediumType_DVD && !fIsHostDrive ?
2837 tr("CD/DVD image", "failed to mount ...") :
2838 type == UIMediumType_Floppy && fIsHostDrive ?
2839 tr("floppy", "failed to mount ... host-drive") :
2840 type == UIMediumType_Floppy && !fIsHostDrive ?
2841 tr("floppy image", "failed to mount ...") :
2842 QString::null;
2843
2844 Assert(!strType.isNull());
2845 return strType;
2846}
2847
2848/**
2849 * Formats the given COM result code as a human-readable string.
2850 *
2851 * If a mnemonic name for the given result code is found, a string in format
2852 * "MNEMONIC_NAME (0x12345678)" is returned where the hex number is the result
2853 * code as is. If no mnemonic name is found, then the raw hex number only is
2854 * returned (w/o pParenthesis).
2855 *
2856 * @param rc COM result code to format.
2857 */
2858/* static */
2859QString UIMessageCenter::formatRC(HRESULT rc)
2860{
2861 QString str;
2862
2863 PCRTCOMERRMSG msg = NULL;
2864 const char *errMsg = NULL;
2865
2866 /* first, try as is (only set bit 31 bit for warnings) */
2867 if (SUCCEEDED_WARNING(rc))
2868 msg = RTErrCOMGet(rc | 0x80000000);
2869 else
2870 msg = RTErrCOMGet(rc);
2871
2872 if (msg != NULL)
2873 errMsg = msg->pszDefine;
2874
2875#if defined (Q_WS_WIN)
2876
2877 PCRTWINERRMSG winMsg = NULL;
2878
2879 /* if not found, try again using RTErrWinGet with masked off top 16bit */
2880 if (msg == NULL)
2881 {
2882 winMsg = RTErrWinGet(rc & 0xFFFF);
2883
2884 if (winMsg != NULL)
2885 errMsg = winMsg->pszDefine;
2886 }
2887
2888#endif
2889
2890 if (errMsg != NULL && *errMsg != '\0')
2891 str.sprintf("%s (0x%08X)", errMsg, rc);
2892 else
2893 str.sprintf("0x%08X", rc);
2894
2895 return str;
2896}
2897
2898/* static */
2899QString UIMessageCenter::formatErrorInfo(const COMErrorInfo &info,
2900 HRESULT wrapperRC /* = S_OK */)
2901{
2902 QString formatted = errorInfoToString(info, wrapperRC);
2903 return QString("<qt>%1</qt>").arg(formatted);
2904}
2905
2906void UIMessageCenter::cannotCreateHostInterface(const CHost &host, QWidget *pParent /* = 0 */)
2907{
2908 if (thread() == QThread::currentThread())
2909 sltCannotCreateHostInterface(host, pParent);
2910 else
2911 emit sigCannotCreateHostInterface(host, pParent);
2912}
2913
2914void UIMessageCenter::cannotCreateHostInterface(const CProgress &progress, QWidget *pParent /* = 0 */)
2915{
2916 if (thread() == QThread::currentThread())
2917 sltCannotCreateHostInterface(progress, pParent);
2918 else
2919 emit sigCannotCreateHostInterface(progress, pParent);
2920}
2921
2922void UIMessageCenter::cannotRemoveHostInterface(const CHost &host, const CHostNetworkInterface &iface,
2923 QWidget *pParent /* = 0 */)
2924{
2925 if (thread() == QThread::currentThread())
2926 sltCannotRemoveHostInterface(host, iface ,pParent);
2927 else
2928 emit sigCannotRemoveHostInterface(host, iface, pParent);
2929}
2930
2931void UIMessageCenter::cannotRemoveHostInterface(const CProgress &progress, const CHostNetworkInterface &iface,
2932 QWidget *pParent /* = 0 */)
2933{
2934 if (thread() == QThread::currentThread())
2935 sltCannotRemoveHostInterface(progress, iface, pParent);
2936 else
2937 emit sigCannotRemoveHostInterface(progress, iface, pParent);
2938}
2939
2940void UIMessageCenter::cannotAttachDevice(const CMachine &machine, UIMediumType type,
2941 const QString &strLocation, const StorageSlot &storageSlot,
2942 QWidget *pParent /* = 0 */)
2943{
2944 if (thread() == QThread::currentThread())
2945 sltCannotAttachDevice(machine, type, strLocation, storageSlot, pParent);
2946 else
2947 emit sigCannotAttachDevice(machine, type, strLocation, storageSlot, pParent);
2948}
2949
2950void UIMessageCenter::cannotCreateSharedFolder(const CMachine &machine, const QString &strName,
2951 const QString &strPath, QWidget *pParent /* = 0 */)
2952{
2953 if (thread() == QThread::currentThread())
2954 sltCannotCreateSharedFolder(machine, strName, strPath, pParent);
2955 else
2956 emit sigCannotCreateSharedFolder(machine, strName, strPath, pParent);
2957}
2958
2959void UIMessageCenter::cannotRemoveSharedFolder(const CMachine &machine, const QString &strName,
2960 const QString &strPath, QWidget *pParent /* = 0 */)
2961{
2962 if (thread() == QThread::currentThread())
2963 sltCannotRemoveSharedFolder(machine, strName, strPath, pParent);
2964 else
2965 emit sigCannotRemoveSharedFolder(machine, strName, strPath, pParent);
2966}
2967
2968void UIMessageCenter::cannotCreateSharedFolder(const CConsole &console, const QString &strName,
2969 const QString &strPath, QWidget *pParent /* = 0 */)
2970{
2971 if (thread() == QThread::currentThread())
2972 sltCannotCreateSharedFolder(console, strName, strPath, pParent);
2973 else
2974 emit sigCannotCreateSharedFolder(console, strName, strPath, pParent);
2975}
2976
2977void UIMessageCenter::cannotRemoveSharedFolder(const CConsole &console, const QString &strName,
2978 const QString &strPath, QWidget *pParent /* = 0 */)
2979{
2980 if (thread() == QThread::currentThread())
2981 sltCannotRemoveSharedFolder(console, strName, strPath, pParent);
2982 else
2983 emit sigCannotRemoveSharedFolder(console, strName, strPath, pParent);
2984}
2985
2986#ifdef VBOX_WITH_DRAG_AND_DROP
2987void UIMessageCenter::cannotDropData(const CGuest &guest,
2988 QWidget *pParent /* = 0 */) const
2989{
2990 message(pParent ? pParent : mainWindowShown(),
2991 Error,
2992 tr("Failed to drop data."),
2993 formatErrorInfo(guest));
2994}
2995
2996void UIMessageCenter::cannotDropData(const CProgress &progress,
2997 QWidget *pParent /* = 0 */) const
2998{
2999 AssertWrapperOk(progress);
3000
3001 message(pParent ? pParent : mainWindowShown(),
3002 Error,
3003 tr("Failed to drop data."),
3004 formatErrorInfo(progress.GetErrorInfo()));
3005}
3006#endif /* VBOX_WITH_DRAG_AND_DROP */
3007
3008void UIMessageCenter::remindAboutWrongColorDepth(ulong uRealBPP, ulong uWantedBPP)
3009{
3010 emit sigRemindAboutWrongColorDepth(uRealBPP, uWantedBPP);
3011}
3012
3013void UIMessageCenter::showGenericError(COMBaseWithEI *object, QWidget *pParent /* = 0 */)
3014{
3015 if ( !object
3016 || object->lastRC() == S_OK)
3017 return;
3018
3019 message(pParent ? pParent : mainWindowShown(),
3020 Error,
3021 tr("Sorry, some generic error happens."),
3022 formatErrorInfo(*object));
3023}
3024
3025// Public slots
3026/////////////////////////////////////////////////////////////////////////////
3027
3028void UIMessageCenter::remindAboutUnsupportedUSB2(const QString &strExtPackName, QWidget *pParent)
3029{
3030 emit sigRemindAboutUnsupportedUSB2(strExtPackName, pParent);
3031}
3032
3033void UIMessageCenter::sltShowHelpWebDialog()
3034{
3035 vboxGlobal().openURL("http://www.virtualbox.org");
3036}
3037
3038void UIMessageCenter::sltShowHelpAboutDialog()
3039{
3040 CVirtualBox vbox = vboxGlobal().virtualBox();
3041 QString strFullVersion;
3042 if (vboxGlobal().brandingIsActive())
3043 {
3044 strFullVersion = QString("%1 r%2 - %3").arg(vbox.GetVersion())
3045 .arg(vbox.GetRevision())
3046 .arg(vboxGlobal().brandingGetKey("Name"));
3047 }
3048 else
3049 {
3050 strFullVersion = QString("%1 r%2").arg(vbox.GetVersion())
3051 .arg(vbox.GetRevision());
3052 }
3053 AssertWrapperOk(vbox);
3054
3055 (new VBoxAboutDlg(mainWindowShown(), strFullVersion))->show();
3056}
3057
3058void UIMessageCenter::sltShowHelpHelpDialog()
3059{
3060#ifndef VBOX_OSE
3061 /* For non-OSE version we just open it: */
3062 sltShowUserManual(vboxGlobal().helpFile());
3063#else /* #ifndef VBOX_OSE */
3064 /* For OSE version we have to check if it present first: */
3065 QString strUserManualFileName1 = vboxGlobal().helpFile();
3066 QString strShortFileName = QFileInfo(strUserManualFileName1).fileName();
3067 QString strUserManualFileName2 = QDir(vboxGlobal().virtualBox().GetHomeFolder()).absoluteFilePath(strShortFileName);
3068 /* Show if user manual already present: */
3069 if (QFile::exists(strUserManualFileName1))
3070 sltShowUserManual(strUserManualFileName1);
3071 else if (QFile::exists(strUserManualFileName2))
3072 sltShowUserManual(strUserManualFileName2);
3073 /* If downloader is running already: */
3074 else if (UIDownloaderUserManual::current())
3075 {
3076 /* Just show network access manager: */
3077 gNetworkManager->show();
3078 }
3079 /* Else propose to download user manual: */
3080 else if (askAboutUserManualDownload(strUserManualFileName1))
3081 {
3082 /* Create User Manual downloader: */
3083 UIDownloaderUserManual *pDl = UIDownloaderUserManual::create();
3084 /* After downloading finished => show User Manual: */
3085 connect(pDl, SIGNAL(sigDownloadFinished(const QString&)), this, SLOT(sltShowUserManual(const QString&)));
3086 /* Start downloading: */
3087 pDl->start();
3088 }
3089#endif /* #ifdef VBOX_OSE */
3090}
3091
3092void UIMessageCenter::sltResetSuppressedMessages()
3093{
3094 CVirtualBox vbox = vboxGlobal().virtualBox();
3095 vbox.SetExtraData(GUI_SuppressMessages, QString::null);
3096}
3097
3098void UIMessageCenter::sltShowUserManual(const QString &strLocation)
3099{
3100#if defined (Q_WS_WIN32)
3101 HtmlHelp(GetDesktopWindow(), strLocation.utf16(), HH_DISPLAY_TOPIC, NULL);
3102#elif defined (Q_WS_X11)
3103# ifndef VBOX_OSE
3104 char szViewerPath[RTPATH_MAX];
3105 int rc;
3106 rc = RTPathAppPrivateArch(szViewerPath, sizeof(szViewerPath));
3107 AssertRC(rc);
3108 QProcess::startDetached(QString(szViewerPath) + "/kchmviewer", QStringList(strLocation));
3109# else /* #ifndef VBOX_OSE */
3110 vboxGlobal().openURL("file://" + strLocation);
3111# endif /* #ifdef VBOX_OSE */
3112#elif defined (Q_WS_MAC)
3113 vboxGlobal().openURL("file://" + strLocation);
3114#endif
3115}
3116
3117void UIMessageCenter::sltCannotCreateHostInterface(const CHost &host, QWidget *pParent)
3118{
3119 message(pParent ? pParent : mainWindowShown(), Error,
3120 tr("Failed to create the host-only network interface."),
3121 formatErrorInfo(host));
3122}
3123
3124void UIMessageCenter::sltCannotCreateHostInterface(const CProgress &progress, QWidget *pParent)
3125{
3126 message(pParent ? pParent : mainWindowShown(), Error,
3127 tr("Failed to create the host-only network interface."),
3128 formatErrorInfo(progress.GetErrorInfo()));
3129}
3130
3131void UIMessageCenter::sltCannotRemoveHostInterface(const CHost &host, const CHostNetworkInterface &iface, QWidget *pParent)
3132{
3133 message(pParent ? pParent : mainWindowShown(), Error,
3134 tr("Failed to remove the host network interface <b>%1</b>.")
3135 .arg(iface.GetName()),
3136 formatErrorInfo(host));
3137}
3138
3139void UIMessageCenter::sltCannotRemoveHostInterface(const CProgress &progress, const CHostNetworkInterface &iface, QWidget *pParent)
3140{
3141 message(pParent ? pParent : mainWindowShown(), Error,
3142 tr("Failed to remove the host network interface <b>%1</b>.")
3143 .arg(iface.GetName()),
3144 formatErrorInfo(progress.GetErrorInfo()));
3145}
3146
3147void UIMessageCenter::sltCannotAttachDevice(const CMachine &machine, UIMediumType type,
3148 const QString &strLocation, const StorageSlot &storageSlot,
3149 QWidget *pParent)
3150{
3151 QString strMessage;
3152 switch (type)
3153 {
3154 case UIMediumType_HardDisk:
3155 {
3156 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>.")
3157 .arg(strLocation).arg(gpConverter->toString(storageSlot)).arg(CMachine(machine).GetName());
3158 break;
3159 }
3160 case UIMediumType_DVD:
3161 {
3162 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>.")
3163 .arg(strLocation).arg(gpConverter->toString(storageSlot)).arg(CMachine(machine).GetName());
3164 break;
3165 }
3166 case UIMediumType_Floppy:
3167 {
3168 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>.")
3169 .arg(strLocation).arg(gpConverter->toString(storageSlot)).arg(CMachine(machine).GetName());
3170 break;
3171 }
3172 default:
3173 break;
3174 }
3175 message(pParent ? pParent : mainWindowShown(), Error, strMessage, formatErrorInfo(machine));
3176}
3177
3178void UIMessageCenter::sltCannotCreateSharedFolder(const CMachine &machine, const QString &strName,
3179 const QString &strPath, QWidget *pParent)
3180{
3181 message(pParent ? pParent : mainMachineWindowShown(), Error,
3182 tr("Failed to create the shared folder <b>%1</b> "
3183 "(pointing to <nobr><b>%2</b></nobr>) "
3184 "for the virtual machine <b>%3</b>.")
3185 .arg(strName)
3186 .arg(strPath)
3187 .arg(CMachine(machine).GetName()),
3188 formatErrorInfo(machine));
3189}
3190
3191void UIMessageCenter::sltCannotRemoveSharedFolder(const CMachine &machine, const QString &strName,
3192 const QString &strPath, QWidget *pParent)
3193{
3194 message(pParent ? pParent : mainMachineWindowShown(), Error,
3195 tr("Failed to remove the shared folder <b>%1</b> "
3196 "(pointing to <nobr><b>%2</b></nobr>) "
3197 "from the virtual machine <b>%3</b>.")
3198 .arg(strName)
3199 .arg(strPath)
3200 .arg(CMachine(machine).GetName()),
3201 formatErrorInfo(machine));
3202}
3203
3204void UIMessageCenter::sltCannotCreateSharedFolder(const CConsole &console, const QString &strName,
3205 const QString &strPath, QWidget *pParent)
3206{
3207 message(pParent ? pParent : mainMachineWindowShown(), Error,
3208 tr("Failed to create the shared folder <b>%1</b> "
3209 "(pointing to <nobr><b>%2</b></nobr>) "
3210 "for the virtual machine <b>%3</b>.")
3211 .arg(strName)
3212 .arg(strPath)
3213 .arg(CConsole(console).GetMachine().GetName()),
3214 formatErrorInfo(console));
3215}
3216
3217void UIMessageCenter::sltCannotRemoveSharedFolder(const CConsole &console, const QString &strName,
3218 const QString &strPath, QWidget *pParent)
3219{
3220 message(pParent ? pParent : mainMachineWindowShown(), Error,
3221 tr("<p>Failed to remove the shared folder <b>%1</b> "
3222 "(pointing to <nobr><b>%2</b></nobr>) "
3223 "from the virtual machine <b>%3</b>.</p>"
3224 "<p>Please close all programs in the guest OS that "
3225 "may be using this shared folder and try again.</p>")
3226 .arg(strName)
3227 .arg(strPath)
3228 .arg(CConsole(console).GetMachine().GetName()),
3229 formatErrorInfo(console));
3230}
3231
3232void UIMessageCenter::sltRemindAboutWrongColorDepth(ulong uRealBPP, ulong uWantedBPP)
3233{
3234 const char *kName = "remindAboutWrongColorDepth";
3235
3236 /* Close the previous (outdated) window if any. We use kName as
3237 * pcszAutoConfirmId which is also used as the widget name by default. */
3238 {
3239 QWidget *outdated = VBoxGlobal::findWidget(NULL, kName, "QIMessageBox");
3240 if (outdated)
3241 outdated->close();
3242 }
3243
3244 message(mainMachineWindowShown(), Info,
3245 tr("<p>The virtual machine window is optimized to work in "
3246 "<b>%1&nbsp;bit</b> color mode but the "
3247 "virtual display is currently set to <b>%2&nbsp;bit</b>.</p>"
3248 "<p>Please open the display properties dialog of the guest OS and "
3249 "select a <b>%3&nbsp;bit</b> color mode, if it is available, for "
3250 "best possible performance of the virtual video subsystem.</p>"
3251 "<p><b>Note</b>. Some operating systems, like OS/2, may actually "
3252 "work in 32&nbsp;bit mode but report it as 24&nbsp;bit "
3253 "(16 million colors). You may try to select a different color "
3254 "mode to see if this message disappears or you can simply "
3255 "disable the message now if you are sure the required color "
3256 "mode (%4&nbsp;bit) is not available in the guest OS.</p>")
3257 .arg(uWantedBPP).arg(uRealBPP).arg(uWantedBPP).arg(uWantedBPP),
3258 kName);
3259}
3260
3261void UIMessageCenter::sltRemindAboutUnsupportedUSB2(const QString &strExtPackName, QWidget *pParent)
3262{
3263 if (isAlreadyShown("sltRemindAboutUnsupportedUSB2"))
3264 return;
3265 setShownStatus("sltRemindAboutUnsupportedUSB2");
3266
3267 message(pParent ? pParent : mainMachineWindowShown(), Warning,
3268 tr("<p>USB 2.0 is currently enabled for this virtual machine. "
3269 "However, this requires the <b><nobr>%1</nobr></b> to be installed.</p>"
3270 "<p>Please install the Extension Pack from the VirtualBox download site. "
3271 "After this you will be able to re-enable USB 2.0. "
3272 "It will be disabled in the meantime unless you cancel the current settings changes.</p>")
3273 .arg(strExtPackName));
3274
3275 clearShownStatus("sltRemindAboutUnsupportedUSB2");
3276}
3277
3278UIMessageCenter::UIMessageCenter()
3279{
3280 /* Register required objects as meta-types: */
3281 qRegisterMetaType<CProgress>();
3282 qRegisterMetaType<CHost>();
3283 qRegisterMetaType<CMachine>();
3284 qRegisterMetaType<CConsole>();
3285 qRegisterMetaType<CHostNetworkInterface>();
3286 qRegisterMetaType<UIMediumType>();
3287 qRegisterMetaType<StorageSlot>();
3288
3289 /* Prepare required connections: */
3290 connect(this, SIGNAL(sigCannotCreateHostInterface(const CHost&, QWidget*)),
3291 this, SLOT(sltCannotCreateHostInterface(const CHost&, QWidget*)),
3292 Qt::BlockingQueuedConnection);
3293 connect(this, SIGNAL(sigCannotCreateHostInterface(const CProgress&, QWidget*)),
3294 this, SLOT(sltCannotCreateHostInterface(const CProgress&, QWidget*)),
3295 Qt::BlockingQueuedConnection);
3296 connect(this, SIGNAL(sigCannotRemoveHostInterface(const CHost&, const CHostNetworkInterface&, QWidget*)),
3297 this, SLOT(sltCannotRemoveHostInterface(const CHost&, const CHostNetworkInterface&, QWidget*)),
3298 Qt::BlockingQueuedConnection);
3299 connect(this, SIGNAL(sigCannotRemoveHostInterface(const CProgress&, const CHostNetworkInterface&, QWidget*)),
3300 this, SLOT(sltCannotRemoveHostInterface(const CProgress&, const CHostNetworkInterface&, QWidget*)),
3301 Qt::BlockingQueuedConnection);
3302 connect(this, SIGNAL(sigCannotAttachDevice(const CMachine&, UIMediumType, const QString&, const StorageSlot&, QWidget*)),
3303 this, SLOT(sltCannotAttachDevice(const CMachine&, UIMediumType, const QString&, const StorageSlot&, QWidget*)),
3304 Qt::BlockingQueuedConnection);
3305 connect(this, SIGNAL(sigCannotCreateSharedFolder(const CMachine&, const QString&, const QString&, QWidget*)),
3306 this, SLOT(sltCannotCreateSharedFolder(const CMachine&, const QString&, const QString&, QWidget*)),
3307 Qt::BlockingQueuedConnection);
3308 connect(this, SIGNAL(sigCannotRemoveSharedFolder(const CMachine&, const QString&, const QString&, QWidget*)),
3309 this, SLOT(sltCannotRemoveSharedFolder(const CMachine&, const QString&, const QString&, QWidget*)),
3310 Qt::BlockingQueuedConnection);
3311 connect(this, SIGNAL(sigCannotCreateSharedFolder(const CConsole&, const QString&, const QString&, QWidget*)),
3312 this, SLOT(sltCannotCreateSharedFolder(const CConsole&, const QString&, const QString&, QWidget*)),
3313 Qt::BlockingQueuedConnection);
3314 connect(this, SIGNAL(sigCannotRemoveSharedFolder(const CConsole&, const QString&, const QString&, QWidget*)),
3315 this, SLOT(sltCannotRemoveSharedFolder(const CConsole&, const QString&, const QString&, QWidget*)),
3316 Qt::BlockingQueuedConnection);
3317 connect(this, SIGNAL(sigRemindAboutWrongColorDepth(ulong, ulong)),
3318 this, SLOT(sltRemindAboutWrongColorDepth(ulong, ulong)), Qt::QueuedConnection);
3319 connect(this, SIGNAL(sigRemindAboutUnsupportedUSB2(const QString&, QWidget*)),
3320 this, SLOT(sltRemindAboutUnsupportedUSB2(const QString&, QWidget*)), Qt::QueuedConnection);
3321
3322 /* Translations for Main.
3323 * Please make sure they corresponds to the strings coming from Main one-by-one symbol! */
3324 tr("Could not load the Host USB Proxy Service (VERR_FILE_NOT_FOUND). The service might not be installed on the host computer");
3325 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");
3326 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");
3327 tr("The USB Proxy Service has not yet been ported to this host");
3328 tr("Could not load the Host USB Proxy service");
3329}
3330
3331/* Returns a reference to the global VirtualBox message center instance: */
3332UIMessageCenter &UIMessageCenter::instance()
3333{
3334 static UIMessageCenter global_instance;
3335 return global_instance;
3336}
3337
3338QString UIMessageCenter::errorInfoToString(const COMErrorInfo &info,
3339 HRESULT wrapperRC /* = S_OK */)
3340{
3341 /* Compose complex details string with internal <!--EOM--> delimiter to
3342 * make it possible to split string into info & details parts which will
3343 * be used separately in QIMessageBox */
3344 QString formatted;
3345
3346 /* Check if details text is NOT empty: */
3347 QString strDetailsInfo = info.text();
3348 if (!strDetailsInfo.isEmpty())
3349 {
3350 /* Check if details text written in English (latin1) and translated: */
3351 if (strDetailsInfo == QString::fromLatin1(strDetailsInfo.toLatin1()) &&
3352 strDetailsInfo != tr(strDetailsInfo.toLatin1().constData()))
3353 formatted += QString("<p>%1.</p>").arg(vboxGlobal().emphasize(tr(strDetailsInfo.toLatin1().constData())));
3354 else
3355 formatted += QString("<p>%1.</p>").arg(vboxGlobal().emphasize(strDetailsInfo));
3356 }
3357
3358 formatted += "<!--EOM--><table bgcolor=#EEEEEE border=0 cellspacing=0 "
3359 "cellpadding=0 width=100%>";
3360
3361 bool haveResultCode = false;
3362
3363 if (info.isBasicAvailable())
3364 {
3365#if defined (Q_WS_WIN)
3366 haveResultCode = info.isFullAvailable();
3367 bool haveComponent = true;
3368 bool haveInterfaceID = true;
3369#else /* defined (Q_WS_WIN) */
3370 haveResultCode = true;
3371 bool haveComponent = info.isFullAvailable();
3372 bool haveInterfaceID = info.isFullAvailable();
3373#endif
3374
3375 if (haveResultCode)
3376 {
3377 formatted += QString("<tr><td>%1</td><td><tt>%2</tt></td></tr>")
3378 .arg(tr("Result&nbsp;Code: ", "error info"))
3379 .arg(formatRC(info.resultCode()));
3380 }
3381
3382 if (haveComponent)
3383 formatted += QString("<tr><td>%1</td><td>%2</td></tr>")
3384 .arg(tr("Component: ", "error info"), info.component());
3385
3386 if (haveInterfaceID)
3387 {
3388 QString s = info.interfaceID();
3389 if (!info.interfaceName().isEmpty())
3390 s = info.interfaceName() + ' ' + s;
3391 formatted += QString("<tr><td>%1</td><td>%2</td></tr>")
3392 .arg(tr("Interface: ", "error info"), s);
3393 }
3394
3395 if (!info.calleeIID().isNull() && info.calleeIID() != info.interfaceID())
3396 {
3397 QString s = info.calleeIID();
3398 if (!info.calleeName().isEmpty())
3399 s = info.calleeName() + ' ' + s;
3400 formatted += QString("<tr><td>%1</td><td>%2</td></tr>")
3401 .arg(tr("Callee: ", "error info"), s);
3402 }
3403 }
3404
3405 if (FAILED (wrapperRC) &&
3406 (!haveResultCode || wrapperRC != info.resultCode()))
3407 {
3408 formatted += QString("<tr><td>%1</td><td><tt>%2</tt></td></tr>")
3409 .arg(tr("Callee&nbsp;RC: ", "error info"))
3410 .arg(formatRC(wrapperRC));
3411 }
3412
3413 formatted += "</table>";
3414
3415 if (info.next())
3416 formatted = formatted + "<!--EOP-->" + errorInfoToString(*info.next());
3417
3418 return formatted;
3419}
3420
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use