VirtualBox

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

Last change on this file since 44503 was 44503, checked in by vboxsync, 11 years ago

Main: change API. Interface IMediumFormat was touched. Attribute capabilities got the type MediumFormatCapabilities and option safeArray. PR5434.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use