Changeset 104901 in vbox
- Timestamp:
- Jun 12, 2024 4:22:14 PM (9 months ago)
- svn:sync-xref-src-repo-rev:
- 163503
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 10 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r104514 r104901 1449 1449 src/medium/UIMediumSearchWidget.cpp \ 1450 1450 src/medium/UIMediumSelector.cpp \ 1451 src/medium/UIMediumTools.cpp \ 1451 1452 src/medium/viso/UIVisoContentBrowser.cpp \ 1452 1453 src/medium/viso/UIVisoCreator.cpp \ -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UICommon.cpp
r104899 r104901 30 30 #include <QDesktopServices> 31 31 #include <QDir> 32 #include <QFileDialog>33 #include <QGraphicsWidget>34 #include <QLibraryInfo>35 32 #include <QLocale> 36 #include <QMenu>37 #include <QMutex>38 #include <QProcess>39 #include <QProgressDialog>40 33 #include <QSessionManager> 41 34 #include <QSettings> … … 44 37 #include <QStyleOptionSpinBox> 45 38 #include <QThread> 46 #include <QTimer>47 #include <QToolButton>48 39 #include <QToolTip> 49 #include <Q Translator>40 #include <QUrl> 50 41 #ifdef VBOX_WS_WIN 51 42 # include <QStyleFactory> … … 56 47 57 48 /* GUI includes: */ 58 #include "QIDialogButtonBox.h"59 #include "QIFileDialog.h"60 #include "QIMessageBox.h"61 #include "QIWithRestorableGeometry.h"62 49 #include "UICommon.h" 63 50 #include "UIConverter.h" … … 67 54 #include "UIExtraDataDefs.h" 68 55 #include "UIExtraDataManager.h" 69 #include "UIFDCreationDialog.h"70 56 #include "UIIconPool.h" 71 57 #include "UILoggingDefs.h" 72 58 #include "UIMedium.h" 73 59 #include "UIMediumEnumerator.h" 74 #include "UIMediumSelector.h"75 60 #include "UIMessageCenter.h" 76 61 #include "UIModalWindowManager.h" … … 84 69 #include "UIVirtualBoxClientEventHandler.h" 85 70 #include "UIVirtualBoxEventHandler.h" 86 #include "UIVisoCreator.h"87 #include "UIWizardNewVD.h"88 71 #ifdef VBOX_WS_MAC 89 72 # include "UICocoaApplication.h" 90 # include "UIMachineWindowFullscreen.h"91 # include "UIMachineWindowSeamless.h"92 73 #endif 93 74 #ifdef VBOX_WS_WIN … … 103 84 104 85 /* COM includes: */ 105 #include "CAudioAdapter.h"106 86 #include "CCloudMachine.h" 107 #include "CConsole.h"108 87 #include "CHostUSBDevice.h" 109 88 #include "CHostVideoInputDevice.h" 110 89 #include "CMachine.h" 90 #include "CMedium.h" 111 91 #include "CMediumAttachment.h" 112 #include "CNetworkAdapter.h"113 #include "CSerialPort.h"114 #include "CSharedFolder.h"115 #include "CSnapshot.h"116 #include "CStorageController.h"117 92 #include "CSystemProperties.h" 118 #include "CUSBController.h"119 93 #include "CUSBDevice.h" 120 94 #include "CUSBDeviceFilter.h" 121 #include "CUSBDeviceFilters.h"122 #include "CVRDEServer.h"123 95 #include <VBox/com/VirtualBox.h> /* For GUEST_OS_ID_STR_PARTIAL. */ 124 96 … … 1464 1436 { 1465 1437 emit sigCloudMachineRegistered(strProviderShortName, strProfileName, comMachine); 1466 }1467 1468 QUuid UICommon::openMedium(UIMediumDeviceType enmMediumType, QString strMediumLocation, QWidget *pParent /* = 0 */)1469 {1470 /* Convert to native separators: */1471 strMediumLocation = QDir::toNativeSeparators(strMediumLocation);1472 1473 /* Initialize variables: */1474 CVirtualBox comVBox = gpGlobalSession->virtualBox();1475 1476 /* Open corresponding medium: */1477 CMedium comMedium = comVBox.OpenMedium(strMediumLocation, mediumTypeToGlobal(enmMediumType), KAccessMode_ReadWrite, false);1478 1479 if (comVBox.isOk())1480 {1481 /* Prepare vbox medium wrapper: */1482 UIMedium guiMedium = gpMediumEnumerator->medium(comMedium.GetId());1483 1484 /* First of all we should test if that medium already opened: */1485 if (guiMedium.isNull())1486 {1487 /* And create new otherwise: */1488 guiMedium = UIMedium(comMedium, enmMediumType, KMediumState_Created);1489 gpMediumEnumerator->createMedium(guiMedium);1490 }1491 1492 /* Return guiMedium id: */1493 return guiMedium.id();1494 }1495 else1496 msgCenter().cannotOpenMedium(comVBox, strMediumLocation, pParent);1497 1498 return QUuid();1499 }1500 1501 QUuid UICommon::openMediumWithFileOpenDialog(UIMediumDeviceType enmMediumType, QWidget *pParent,1502 const QString &strDefaultFolder /* = QString() */,1503 bool fUseLastFolder /* = false */)1504 {1505 /* Initialize variables: */1506 QList<QPair <QString, QString> > filters;1507 QStringList backends;1508 QStringList prefixes;1509 QString strFilter;1510 QString strTitle;1511 QString allType;1512 QString strLastFolder = UIMediumEnumerator::defaultFolderPathForType(enmMediumType);1513 1514 /* For DVDs and Floppies always check first the last recently used medium folder. For hard disk use1515 the caller's setting: */1516 fUseLastFolder = (enmMediumType == UIMediumDeviceType_DVD) || (enmMediumType == UIMediumDeviceType_Floppy);1517 1518 switch (enmMediumType)1519 {1520 case UIMediumDeviceType_HardDisk:1521 {1522 filters = HDDBackends(gpGlobalSession->virtualBox());1523 strTitle = tr("Please choose a virtual hard disk file");1524 allType = tr("All virtual hard disk files (%1)");1525 break;1526 }1527 case UIMediumDeviceType_DVD:1528 {1529 filters = DVDBackends(gpGlobalSession->virtualBox());1530 strTitle = tr("Please choose a virtual optical disk file");1531 allType = tr("All virtual optical disk files (%1)");1532 break;1533 }1534 case UIMediumDeviceType_Floppy:1535 {1536 filters = FloppyBackends(gpGlobalSession->virtualBox());1537 strTitle = tr("Please choose a virtual floppy disk file");1538 allType = tr("All virtual floppy disk files (%1)");1539 break;1540 }1541 default:1542 break;1543 }1544 QString strHomeFolder = fUseLastFolder && !strLastFolder.isEmpty() ? strLastFolder :1545 strDefaultFolder.isEmpty() ? gpGlobalSession->homeFolder() : strDefaultFolder;1546 1547 /* Prepare filters and backends: */1548 for (int i = 0; i < filters.count(); ++i)1549 {1550 /* Get iterated filter: */1551 QPair<QString, QString> item = filters.at(i);1552 /* Create one backend filter string: */1553 backends << QString("%1 (%2)").arg(item.first).arg(item.second);1554 /* Save the suffix's for the "All" entry: */1555 prefixes << item.second;1556 }1557 if (!prefixes.isEmpty())1558 backends.insert(0, allType.arg(prefixes.join(" ").trimmed()));1559 backends << tr("All files (*)");1560 strFilter = backends.join(";;").trimmed();1561 1562 /* Create open file dialog: */1563 QStringList files = QIFileDialog::getOpenFileNames(strHomeFolder, strFilter, pParent, strTitle, 0, true, true);1564 1565 /* If dialog has some result: */1566 if (!files.empty() && !files[0].isEmpty())1567 {1568 QUuid uMediumId = openMedium(enmMediumType, files[0], pParent);1569 if (enmMediumType == UIMediumDeviceType_DVD || enmMediumType == UIMediumDeviceType_Floppy ||1570 (enmMediumType == UIMediumDeviceType_HardDisk && fUseLastFolder))1571 gpMediumEnumerator->updateRecentlyUsedMediumListAndFolder(enmMediumType, gpMediumEnumerator->medium(uMediumId).location());1572 return uMediumId;1573 }1574 return QUuid();1575 }1576 1577 QUuid UICommon::openMediumCreatorDialog(UIActionPool *pActionPool, QWidget *pParent, UIMediumDeviceType enmMediumType,1578 const QString &strDefaultFolder /* = QString() */,1579 const QString &strMachineName /* = QString() */,1580 const QString &strMachineGuestOSTypeId /*= QString() */)1581 {1582 /* Depending on medium-type: */1583 QUuid uMediumId;1584 switch (enmMediumType)1585 {1586 case UIMediumDeviceType_HardDisk:1587 uMediumId = UIWizardNewVD::createVDWithWizard(pParent, strDefaultFolder, strMachineName, strMachineGuestOSTypeId);1588 break;1589 case UIMediumDeviceType_DVD:1590 uMediumId = UIVisoCreatorDialog::createViso(pActionPool, pParent, strDefaultFolder, strMachineName);1591 break;1592 case UIMediumDeviceType_Floppy:1593 uMediumId = UIFDCreationDialog::createFloppyDisk(pParent, strDefaultFolder, strMachineName);1594 break;1595 default:1596 break;1597 }1598 if (uMediumId.isNull())1599 return QUuid();1600 1601 /* Update the recent medium list only if the medium type is floppy since updating when a VISO is created is not optimal: */1602 if (enmMediumType == UIMediumDeviceType_Floppy)1603 gpMediumEnumerator->updateRecentlyUsedMediumListAndFolder(enmMediumType, gpMediumEnumerator->medium(uMediumId).location());1604 return uMediumId;1605 }1606 1607 void UICommon::prepareStorageMenu(QMenu *pMenu,1608 QObject *pListener, const char *pszSlotName,1609 const CMachine &comMachine, const QString &strControllerName, const StorageSlot &storageSlot)1610 {1611 /* Current attachment attributes: */1612 const CMediumAttachment comCurrentAttachment = comMachine.GetMediumAttachment(strControllerName,1613 storageSlot.port,1614 storageSlot.device);1615 const CMedium comCurrentMedium = comCurrentAttachment.GetMedium();1616 const QUuid uCurrentID = comCurrentMedium.isNull() ? QUuid() : comCurrentMedium.GetId();1617 const QString strCurrentLocation = comCurrentMedium.isNull() ? QString() : comCurrentMedium.GetLocation();1618 1619 /* Other medium-attachments of same machine: */1620 const CMediumAttachmentVector comAttachments = comMachine.GetMediumAttachments();1621 1622 /* Determine device & medium types: */1623 const UIMediumDeviceType enmMediumType = mediumTypeToLocal(comCurrentAttachment.GetType());1624 AssertMsgReturnVoid(enmMediumType != UIMediumDeviceType_Invalid, ("Incorrect storage medium type!\n"));1625 1626 /* Prepare open-existing-medium action: */1627 QAction *pActionOpenExistingMedium = pMenu->addAction(UIIconPool::iconSet(":/select_file_16px.png"),1628 QString(), pListener, pszSlotName);1629 pActionOpenExistingMedium->setData(QVariant::fromValue(UIMediumTarget(strControllerName, comCurrentAttachment.GetPort(),1630 comCurrentAttachment.GetDevice(), enmMediumType)));1631 pActionOpenExistingMedium->setText(QApplication::translate("UIMachineSettingsStorage", "Choose/Create a disk image..."));1632 1633 1634 /* Prepare open medium file action: */1635 QAction *pActionFileSelector = pMenu->addAction(UIIconPool::iconSet(":/select_file_16px.png"),1636 QString(), pListener, pszSlotName);1637 pActionFileSelector->setData(QVariant::fromValue(UIMediumTarget(strControllerName, comCurrentAttachment.GetPort(),1638 comCurrentAttachment.GetDevice(), enmMediumType,1639 UIMediumTarget::UIMediumTargetType_WithFileDialog)));1640 pActionFileSelector->setText(QApplication::translate("UIMachineSettingsStorage", "Choose a disk file..."));1641 1642 1643 /* Insert separator: */1644 pMenu->addSeparator();1645 1646 /* Get existing-host-drive vector: */1647 CMediumVector comMedia;1648 switch (enmMediumType)1649 {1650 case UIMediumDeviceType_DVD: comMedia = gpGlobalSession->host().GetDVDDrives(); break;1651 case UIMediumDeviceType_Floppy: comMedia = gpGlobalSession->host().GetFloppyDrives(); break;1652 default: break;1653 }1654 /* Prepare choose-existing-host-drive actions: */1655 foreach (const CMedium &comMedium, comMedia)1656 {1657 /* Make sure host-drive usage is unique: */1658 bool fIsHostDriveUsed = false;1659 foreach (const CMediumAttachment &comOtherAttachment, comAttachments)1660 {1661 if (comOtherAttachment != comCurrentAttachment)1662 {1663 const CMedium &comOtherMedium = comOtherAttachment.GetMedium();1664 if (!comOtherMedium.isNull() && comOtherMedium.GetId() == comMedium.GetId())1665 {1666 fIsHostDriveUsed = true;1667 break;1668 }1669 }1670 }1671 /* If host-drives usage is unique: */1672 if (!fIsHostDriveUsed)1673 {1674 QAction *pActionChooseHostDrive = pMenu->addAction(UIMedium(comMedium, enmMediumType).name(), pListener, pszSlotName);1675 pActionChooseHostDrive->setCheckable(true);1676 pActionChooseHostDrive->setChecked(!comCurrentMedium.isNull() && comMedium.GetId() == uCurrentID);1677 pActionChooseHostDrive->setData(QVariant::fromValue(UIMediumTarget(strControllerName,1678 comCurrentAttachment.GetPort(),1679 comCurrentAttachment.GetDevice(),1680 enmMediumType,1681 UIMediumTarget::UIMediumTargetType_WithID,1682 comMedium.GetId().toString())));1683 }1684 }1685 1686 /* Get recent-medium list: */1687 QStringList recentMediumList;1688 QStringList recentMediumListUsed;1689 switch (enmMediumType)1690 {1691 case UIMediumDeviceType_HardDisk: recentMediumList = gEDataManager->recentListOfHardDrives(); break;1692 case UIMediumDeviceType_DVD: recentMediumList = gEDataManager->recentListOfOpticalDisks(); break;1693 case UIMediumDeviceType_Floppy: recentMediumList = gEDataManager->recentListOfFloppyDisks(); break;1694 default: break;1695 }1696 /* Prepare choose-recent-medium actions: */1697 foreach (const QString &strRecentMediumLocationBase, recentMediumList)1698 {1699 /* Confirm medium uniqueness: */1700 if (recentMediumListUsed.contains(strRecentMediumLocationBase))1701 continue;1702 /* Mark medium as known: */1703 recentMediumListUsed << strRecentMediumLocationBase;1704 /* Convert separators to native: */1705 const QString strRecentMediumLocation = QDir::toNativeSeparators(strRecentMediumLocationBase);1706 /* Confirm medium presence: */1707 if (!QFile::exists(strRecentMediumLocation))1708 continue;1709 /* Make sure recent-medium usage is unique: */1710 bool fIsRecentMediumUsed = false;1711 if (enmMediumType != UIMediumDeviceType_DVD)1712 {1713 foreach (const CMediumAttachment &otherAttachment, comAttachments)1714 {1715 if (otherAttachment != comCurrentAttachment)1716 {1717 const CMedium &comOtherMedium = otherAttachment.GetMedium();1718 if (!comOtherMedium.isNull() && comOtherMedium.GetLocation() == strRecentMediumLocation)1719 {1720 fIsRecentMediumUsed = true;1721 break;1722 }1723 }1724 }1725 }1726 /* If recent-medium usage is unique: */1727 if (!fIsRecentMediumUsed)1728 {1729 QAction *pActionChooseRecentMedium = pMenu->addAction(QFileInfo(strRecentMediumLocation).fileName(),1730 pListener, pszSlotName);1731 pActionChooseRecentMedium->setCheckable(true);1732 pActionChooseRecentMedium->setChecked(!comCurrentMedium.isNull() && strRecentMediumLocation == strCurrentLocation);1733 pActionChooseRecentMedium->setData(QVariant::fromValue(UIMediumTarget(strControllerName,1734 comCurrentAttachment.GetPort(),1735 comCurrentAttachment.GetDevice(),1736 enmMediumType,1737 UIMediumTarget::UIMediumTargetType_WithLocation,1738 strRecentMediumLocation)));1739 pActionChooseRecentMedium->setToolTip(strRecentMediumLocation);1740 }1741 }1742 1743 /* Last action for optical/floppy attachments only: */1744 if (enmMediumType == UIMediumDeviceType_DVD || enmMediumType == UIMediumDeviceType_Floppy)1745 {1746 /* Insert separator: */1747 pMenu->addSeparator();1748 1749 /* Prepare unmount-current-medium action: */1750 QAction *pActionUnmountMedium = pMenu->addAction(QString(), pListener, pszSlotName);1751 pActionUnmountMedium->setEnabled(!comCurrentMedium.isNull());1752 pActionUnmountMedium->setData(QVariant::fromValue(UIMediumTarget(strControllerName, comCurrentAttachment.GetPort(),1753 comCurrentAttachment.GetDevice())));1754 pActionUnmountMedium->setText(QApplication::translate("UIMachineSettingsStorage", "Remove disk from virtual drive"));1755 if (enmMediumType == UIMediumDeviceType_DVD)1756 pActionUnmountMedium->setIcon(UIIconPool::iconSet(":/cd_unmount_16px.png", ":/cd_unmount_disabled_16px.png"));1757 else if (enmMediumType == UIMediumDeviceType_Floppy)1758 pActionUnmountMedium->setIcon(UIIconPool::iconSet(":/fd_unmount_16px.png", ":/fd_unmount_disabled_16px.png"));1759 }1760 }1761 1762 void UICommon::updateMachineStorage(const CMachine &comConstMachine, const UIMediumTarget &target, UIActionPool *pActionPool)1763 {1764 /* Mount (by default): */1765 bool fMount = true;1766 /* Null medium (by default): */1767 CMedium comMedium;1768 /* With null ID (by default): */1769 QUuid uActualID;1770 1771 /* Current mount-target attributes: */1772 const CStorageController comCurrentController = comConstMachine.GetStorageControllerByName(target.name);1773 const KStorageBus enmCurrentStorageBus = comCurrentController.GetBus();1774 const CMediumAttachment comCurrentAttachment = comConstMachine.GetMediumAttachment(target.name, target.port, target.device);1775 const CMedium comCurrentMedium = comCurrentAttachment.GetMedium();1776 const QUuid uCurrentID = comCurrentMedium.isNull() ? QUuid() : comCurrentMedium.GetId();1777 const QString strCurrentLocation = comCurrentMedium.isNull() ? QString() : comCurrentMedium.GetLocation();1778 1779 /* Which additional info do we have? */1780 switch (target.type)1781 {1782 /* Do we have an exact ID or do we let the user open a medium? */1783 case UIMediumTarget::UIMediumTargetType_WithID:1784 case UIMediumTarget::UIMediumTargetType_WithFileDialog:1785 case UIMediumTarget::UIMediumTargetType_CreateAdHocVISO:1786 case UIMediumTarget::UIMediumTargetType_CreateFloppyDisk:1787 {1788 /* New mount-target attributes: */1789 QUuid uNewID;1790 1791 /* Invoke file-open dialog to choose medium ID: */1792 if (target.mediumType != UIMediumDeviceType_Invalid && target.data.isNull())1793 {1794 /* Keyboard can be captured by machine-view.1795 * So we should clear machine-view focus to let file-open dialog get it.1796 * That way the keyboard will be released too.. */1797 QWidget *pLastFocusedWidget = 0;1798 if (QApplication::focusWidget())1799 {1800 pLastFocusedWidget = QApplication::focusWidget();1801 pLastFocusedWidget->clearFocus();1802 }1803 /* Call for file-open dialog: */1804 const QString strMachineFolder(QFileInfo(comConstMachine.GetSettingsFilePath()).absolutePath());1805 QUuid uMediumID;1806 if (target.type == UIMediumTarget::UIMediumTargetType_WithID)1807 {1808 int iDialogReturn = UIMediumSelector::openMediumSelectorDialog(windowManager().mainWindowShown(), target.mediumType,1809 uCurrentID, uMediumID,1810 strMachineFolder, comConstMachine.GetName(),1811 comConstMachine.GetOSTypeId(), true /*fEnableCreate */,1812 comConstMachine.GetId(), pActionPool);1813 if (iDialogReturn == UIMediumSelector::ReturnCode_LeftEmpty &&1814 (target.mediumType == UIMediumDeviceType_DVD || target.mediumType == UIMediumDeviceType_Floppy))1815 fMount = false;1816 }1817 else if (target.type == UIMediumTarget::UIMediumTargetType_WithFileDialog)1818 {1819 uMediumID = openMediumWithFileOpenDialog(target.mediumType, windowManager().mainWindowShown(),1820 strMachineFolder, false /* fUseLastFolder */);1821 }1822 else if(target.type == UIMediumTarget::UIMediumTargetType_CreateAdHocVISO)1823 UIVisoCreatorDialog::createViso(pActionPool, windowManager().mainWindowShown(),1824 strMachineFolder, comConstMachine.GetName());1825 1826 else if(target.type == UIMediumTarget::UIMediumTargetType_CreateFloppyDisk)1827 uMediumID = UIFDCreationDialog::createFloppyDisk(windowManager().mainWindowShown(), strMachineFolder, comConstMachine.GetName());1828 1829 /* Return focus back: */1830 if (pLastFocusedWidget)1831 pLastFocusedWidget->setFocus();1832 /* Accept new medium ID: */1833 if (!uMediumID.isNull())1834 uNewID = uMediumID;1835 else1836 /* Else just exit in case left empty is not chosen in medium selector dialog: */1837 if (fMount)1838 return;1839 }1840 /* Use medium ID which was passed: */1841 else if (!target.data.isNull() && target.data != uCurrentID.toString())1842 uNewID = QUuid(target.data);1843 1844 /* Should we mount or unmount? */1845 fMount = !uNewID.isNull();1846 1847 /* Prepare target medium: */1848 const UIMedium guiMedium = gpMediumEnumerator->medium(uNewID);1849 comMedium = guiMedium.medium();1850 uActualID = fMount ? uNewID : uCurrentID;1851 break;1852 }1853 /* Do we have a recent location? */1854 case UIMediumTarget::UIMediumTargetType_WithLocation:1855 {1856 /* Open medium by location and get new medium ID if any: */1857 const QUuid uNewID = openMedium(target.mediumType, target.data);1858 /* Else just exit: */1859 if (uNewID.isNull())1860 return;1861 1862 /* Should we mount or unmount? */1863 fMount = uNewID != uCurrentID;1864 1865 /* Prepare target medium: */1866 const UIMedium guiMedium = fMount ? gpMediumEnumerator->medium(uNewID) : UIMedium();1867 comMedium = fMount ? guiMedium.medium() : CMedium();1868 uActualID = fMount ? uNewID : uCurrentID;1869 break;1870 }1871 }1872 1873 /* Do not unmount hard-drives: */1874 if (target.mediumType == UIMediumDeviceType_HardDisk && !fMount)1875 return;1876 1877 /* Get editable machine & session: */1878 CMachine comMachine = comConstMachine;1879 CSession comSession = tryToOpenSessionFor(comMachine);1880 1881 /* Remount medium to the predefined port/device: */1882 bool fWasMounted = false;1883 /* Hard drive case: */1884 if (target.mediumType == UIMediumDeviceType_HardDisk)1885 {1886 /* Detaching: */1887 comMachine.DetachDevice(target.name, target.port, target.device);1888 fWasMounted = comMachine.isOk();1889 if (!fWasMounted)1890 msgCenter().cannotDetachDevice(comMachine, UIMediumDeviceType_HardDisk, strCurrentLocation,1891 StorageSlot(enmCurrentStorageBus, target.port, target.device));1892 else1893 {1894 /* Attaching: */1895 comMachine.AttachDevice(target.name, target.port, target.device, KDeviceType_HardDisk, comMedium);1896 fWasMounted = comMachine.isOk();1897 if (!fWasMounted)1898 msgCenter().cannotAttachDevice(comMachine, UIMediumDeviceType_HardDisk, strCurrentLocation,1899 StorageSlot(enmCurrentStorageBus, target.port, target.device));1900 }1901 }1902 /* Optical/floppy drive case: */1903 else1904 {1905 /* Remounting: */1906 comMachine.MountMedium(target.name, target.port, target.device, comMedium, false /* force? */);1907 fWasMounted = comMachine.isOk();1908 if (!fWasMounted)1909 {1910 /* Ask for force remounting: */1911 if (msgCenter().cannotRemountMedium(comMachine, gpMediumEnumerator->medium(uActualID),1912 fMount, true /* retry? */))1913 {1914 /* Force remounting: */1915 comMachine.MountMedium(target.name, target.port, target.device, comMedium, true /* force? */);1916 fWasMounted = comMachine.isOk();1917 if (!fWasMounted)1918 msgCenter().cannotRemountMedium(comMachine, gpMediumEnumerator->medium(uActualID),1919 fMount, false /* retry? */);1920 }1921 }1922 }1923 1924 /* Save settings: */1925 if (fWasMounted)1926 {1927 comMachine.SaveSettings();1928 if (!comMachine.isOk())1929 msgCenter().cannotSaveMachineSettings(comMachine, windowManager().mainWindowShown());1930 }1931 1932 /* Close session to editable comMachine if necessary: */1933 if (!comSession.isNull())1934 comSession.UnlockMachine();1935 1438 } 1936 1439 -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UICommon.h
r104899 r104901 44 44 45 45 /* COM includes: */ 46 #include "CMedium.h"47 46 #include "CSession.h" 48 47 #include "KGraphicsControllerType.h" … … 50 49 51 50 /* Forward declarations: */ 52 class QMenu;53 51 class QSessionManager; 54 52 class QSpinBox; … … 56 54 class CHostVideoInputDevice; 57 55 class CMachine; 56 class CMedium; 58 57 class CUSBDevice; 59 class UIActionPool;60 class UIMedium;61 58 class UIThreadPool; 62 59 class UITranslationEventListener; … … 303 300 /** @name COM: Virtual Media stuff. 304 301 * @{ */ 305 /** Opens external medium by passed @a strMediumLocation.306 * @param enmMediumType Brings the medium type.307 * @param pParent Brings the dialog parent.308 * @param strMediumLocation Brings the file path to load medium from.309 * @param pParent Brings the dialog parent. */310 QUuid openMedium(UIMediumDeviceType enmMediumType, QString strMediumLocation, QWidget *pParent = 0);311 312 /** Opens external medium using file-open dialog.313 * @param enmMediumType Brings the medium type.314 * @param pParent Brings the dialog parent.315 * @param strDefaultFolder Brings the folder to browse for medium.316 * @param fUseLastFolder Brings whether we should propose to use last used folder. */317 QUuid openMediumWithFileOpenDialog(UIMediumDeviceType enmMediumType, QWidget *pParent = 0,318 const QString &strDefaultFolder = QString(), bool fUseLastFolder = false);319 320 /** Creates and shows a dialog (wizard) to create a medium of type @a enmMediumType.321 * @param pParent Passes the parent of the dialog,322 * @param enmMediumType Passes the medium type,323 * @param strMachineName Passes the name of the machine,324 * @param strMachineFolder Passes the machine folder,325 * @param strMachineGuestOSTypeId Passes the type ID of machine's guest os,326 * @param fEnableCreate Passes whether to show/enable create action in the medium selector dialog,327 * returns QUuid of the new medium */328 QUuid openMediumCreatorDialog(UIActionPool *pActionPool, QWidget *pParent, UIMediumDeviceType enmMediumType,329 const QString &strMachineFolder = QString(), const QString &strMachineName = QString(),330 const QString &strMachineGuestOSTypeId = QString());331 332 /** Prepares storage menu according passed parameters.333 * @param menu Brings the #QMenu to be prepared.334 * @param pListener Brings the listener #QObject, this @a menu being prepared for.335 * @param pszSlotName Brings the name of the SLOT in the @a pListener above, this menu will be handled with.336 * @param comMachine Brings the #CMachine object, this @a menu being prepared for.337 * @param strControllerName Brings the name of the #CStorageController in the @a machine above.338 * @param storageSlot Brings the #StorageSlot of the storage controller with @a strControllerName above. */339 void prepareStorageMenu(QMenu *pMenu,340 QObject *pListener, const char *pszSlotName,341 const CMachine &comMachine, const QString &strControllerName, const StorageSlot &storageSlot);342 /** Updates @a comConstMachine storage with data described by @a target. */343 void updateMachineStorage(const CMachine &comConstMachine, const UIMediumTarget &target, UIActionPool *pActionPool);344 345 302 /** Generates details for passed @a comMedium. 346 303 * @param fPredictDiff Brings whether medium will be marked differencing on attaching. -
trunk/src/VBox/Frontends/VirtualBox/src/manager/details/UIDetailsElement.cpp
r104585 r104901 59 59 #include "UIIconPool.h" 60 60 #include "UIMachineAttributeSetter.h" 61 #include "UIMediumTools.h" 61 62 #include "UINameAndSystemEditor.h" 62 63 #include "UINetworkAttachmentEditor.h" … … 696 697 697 698 /* Update current machine mount-target: */ 698 uiCommon().updateMachineStorage(machine(), target, gpManager->actionPool());699 UIMediumTools::updateMachineStorage(machine(), target, gpManager->actionPool()); 699 700 } 700 701 … … 1077 1078 1078 1079 /* Fill storage-menu: */ 1079 uiCommon().prepareStorageMenu(&menu, this, SLOT(sltMountStorageMedium()),1080 machine(), strControllerName, storageSlot);1080 UIMediumTools::prepareStorageMenu(&menu, this, SLOT(sltMountStorageMedium()), 1081 machine(), strControllerName, storageSlot); 1081 1082 1082 1083 /* Exec menu: */ -
trunk/src/VBox/Frontends/VirtualBox/src/medium/UIMediumManager.cpp
r104891 r104901 56 56 #include "UIMediumManager.h" 57 57 #include "UIMediumSearchWidget.h" 58 #include "UIMediumTools.h" 58 59 #include "UIMessageCenter.h" 59 60 #include "UINotificationCenter.h" … … 460 461 { 461 462 QString strDefaultMachineFolder = gpGlobalSession->virtualBox().GetSystemProperties().GetDefaultMachineFolder(); 462 uiCommon().openMediumWithFileOpenDialog(currentMediumType(), this,463 strDefaultMachineFolder, true /* use most recent medium folder */);463 UIMediumTools::openMediumWithFileOpenDialog(currentMediumType(), this, 464 strDefaultMachineFolder, true /* use most recent medium folder */); 464 465 } 465 466 … … 473 474 emit sigCreateMedium(); 474 475 else 475 uiCommon().openMediumCreatorDialog(m_pActionPool, this, currentMediumType());476 UIMediumTools::openMediumCreatorDialog(m_pActionPool, this, currentMediumType()); 476 477 } 477 478 -
trunk/src/VBox/Frontends/VirtualBox/src/medium/UIMediumSelector.cpp
r104899 r104901 49 49 #include "UIMediumSearchWidget.h" 50 50 #include "UIMediumSelector.h" 51 #include "UIMediumTools.h" 51 52 #include "UIMessageCenter.h" 52 53 #include "UIModalWindowManager.h" … … 494 495 void UIMediumSelector::sltAddMedium() 495 496 { 496 QUuid uMediumID = uiCommon().openMediumWithFileOpenDialog(m_enmMediumType, this, m_strMachineFolder, true /* fUseLastFolder */); 497 QUuid uMediumID = UIMediumTools::openMediumWithFileOpenDialog(m_enmMediumType, this, m_strMachineFolder, 498 true /* fUseLastFolder */); 497 499 if (uMediumID.isNull()) 498 500 return; … … 503 505 void UIMediumSelector::sltCreateMedium() 504 506 { 505 QUuid uMediumId = uiCommon().openMediumCreatorDialog(m_pActionPool, this, m_enmMediumType, m_strMachineFolder,506 m_strMachineName, m_strMachineGuestOSTypeId);507 QUuid uMediumId = UIMediumTools::openMediumCreatorDialog(m_pActionPool, this, m_enmMediumType, m_strMachineFolder, 508 m_strMachineName, m_strMachineGuestOSTypeId); 507 509 /* Make sure that the data structure is updated and newly created medium is selected and visible: */ 508 510 sltHandleMediumCreated(uMediumId); -
trunk/src/VBox/Frontends/VirtualBox/src/medium/UIMediumTools.cpp
r104899 r104901 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - UI Commonclass implementation.3 * VBox Qt GUI - UIMediumTools class implementation. 4 4 */ 5 5 … … 28 28 /* Qt includes: */ 29 29 #include <QApplication> 30 #include <QDesktopServices>31 30 #include <QDir> 32 #include <QFileDialog>33 #include <QGraphicsWidget>34 #include <QLibraryInfo>35 #include <QLocale>36 31 #include <QMenu> 37 #include <QMutex>38 #include <QProcess>39 #include <QProgressDialog>40 #include <QSessionManager>41 #include <QSettings>42 #include <QSpinBox>43 #include <QStandardPaths>44 #include <QStyleOptionSpinBox>45 #include <QThread>46 #include <QTimer>47 #include <QToolButton>48 #include <QToolTip>49 #include <QTranslator>50 #ifdef VBOX_WS_WIN51 # include <QStyleFactory>52 #endif53 #ifdef VBOX_GUI_WITH_PIDFILE54 # include <QTextStream>55 #endif56 32 57 33 /* GUI includes: */ 58 #include "QIDialogButtonBox.h"59 34 #include "QIFileDialog.h" 60 #include "QIMessageBox.h"61 #include "QIWithRestorableGeometry.h"62 35 #include "UICommon.h" 63 #include "UIConverter.h"64 #include "UIDesktopWidgetWatchdog.h"65 #include "UIGlobalSession.h"66 #include "UIGuestOSType.h"67 #include "UIExtraDataDefs.h"68 36 #include "UIExtraDataManager.h" 69 37 #include "UIFDCreationDialog.h" 38 #include "UIGlobalSession.h" 70 39 #include "UIIconPool.h" 71 #include "UILoggingDefs.h"72 #include "UIMedium.h"73 40 #include "UIMediumEnumerator.h" 74 41 #include "UIMediumSelector.h" 42 #include "UIMediumTools.h" 75 43 #include "UIMessageCenter.h" 76 44 #include "UIModalWindowManager.h" 77 #include "UINotificationCenter.h"78 #include "UIPopupCenter.h"79 #include "UIShortcutPool.h"80 #include "UIThreadPool.h"81 #include "UITranslator.h"82 #include "UITranslationEventListener.h"83 #include "UIVersion.h"84 #include "UIVirtualBoxClientEventHandler.h"85 #include "UIVirtualBoxEventHandler.h"86 45 #include "UIVisoCreator.h" 87 46 #include "UIWizardNewVD.h" 88 #ifdef VBOX_WS_MAC89 # include "UICocoaApplication.h"90 # include "UIMachineWindowFullscreen.h"91 # include "UIMachineWindowSeamless.h"92 #endif93 #ifdef VBOX_WS_WIN94 # include "VBoxUtils-win.h"95 #endif96 #ifdef VBOX_WS_NIX97 # include "UIHostComboEditor.h"98 #endif99 #ifdef VBOX_GUI_WITH_NETWORK_MANAGER100 # include "UINetworkRequestManager.h"101 # include "UIUpdateManager.h"102 #endif103 47 104 48 /* COM includes: */ 105 #include "CAudioAdapter.h"106 #include "CCloudMachine.h"107 #include "CConsole.h"108 #include "CHostUSBDevice.h"109 #include "CHostVideoInputDevice.h"110 49 #include "CMachine.h" 111 #include "CMediumAttachment.h" 112 #include "CNetworkAdapter.h" 113 #include "CSerialPort.h" 114 #include "CSharedFolder.h" 115 #include "CSnapshot.h" 50 #include "CMedium.h" 51 #include "CSession.h" 116 52 #include "CStorageController.h" 117 #include "CSystemProperties.h" 118 #include "CUSBController.h" 119 #include "CUSBDevice.h" 120 #include "CUSBDeviceFilter.h" 121 #include "CUSBDeviceFilters.h" 122 #include "CVRDEServer.h" 123 #include <VBox/com/VirtualBox.h> /* For GUEST_OS_ID_STR_PARTIAL. */ 124 125 /* Other VBox includes: */ 126 #include <iprt/asm.h> 127 #include <iprt/ctype.h> 128 #include <iprt/env.h> 129 #include <iprt/err.h> 130 #include <iprt/file.h> 131 #include <iprt/ldr.h> 132 #include <iprt/param.h> 133 #include <iprt/path.h> 134 #include <iprt/stream.h> 135 #include <iprt/system.h> 136 #include <VBox/sup.h> 137 #include <VBox/VBoxOGL.h> 138 #include <VBox/vd.h> 139 #include <VBox/com/Guid.h> 140 141 /* VirtualBox interface declarations: */ 142 #include <VBox/com/VirtualBox.h> 143 144 /* External includes: */ 145 #ifdef VBOX_WS_MAC 146 # include <sys/utsname.h> 147 #endif 148 #ifdef VBOX_WS_NIX 149 # include <xcb/xcb.h> 150 #endif 151 152 /* Namespaces: */ 153 using namespace UIExtraDataDefs; 154 using namespace UIMediumDefs; 155 156 157 /* static */ 158 UICommon *UICommon::s_pInstance = 0; 159 160 /* static */ 161 void UICommon::create(UIType enmType) 162 { 163 /* Make sure instance is NOT created yet: */ 164 AssertReturnVoid(!s_pInstance); 165 166 /* Create instance: */ 167 new UICommon(enmType); 168 /* Prepare instance: */ 169 s_pInstance->prepare(); 170 } 171 172 /* static */ 173 void UICommon::destroy() 174 { 175 /* Make sure instance is NOT destroyed yet: */ 176 AssertPtrReturnVoid(s_pInstance); 177 178 /* Cleanup instance: 179 * 1. By default, automatically on QApplication::aboutToQuit() signal. 180 * 2. But if QApplication was not started at all and we perform 181 * early shutdown, we should do cleanup ourselves. */ 182 if (s_pInstance->isValid()) 183 s_pInstance->cleanup(); 184 /* Destroy instance: */ 185 delete s_pInstance; 186 } 187 188 UICommon::UICommon(UIType enmType) 189 : m_enmType(enmType) 190 , m_fValid(false) 191 , m_fCleaningUp(false) 192 #ifdef VBOX_WS_WIN 193 , m_fDataCommitted(false) 194 #endif 195 #ifdef VBOX_WS_MAC 196 , m_enmMacOSVersion(MacOSXRelease_Old) 197 #endif 198 #ifdef VBOX_WS_NIX 199 , m_enmWindowManagerType(X11WMType_Unknown) 200 , m_fCompositingManagerRunning(false) 201 , m_enmDisplayServerType(VBGHDISPLAYSERVERTYPE_NONE) 202 #endif 203 , m_fDarkMode(false) 204 , m_fSeparateProcess(false) 205 , m_fShowStartVMErrors(true) 206 #if defined(DEBUG_bird) 207 , m_fAgressiveCaching(false) 208 #else 209 , m_fAgressiveCaching(true) 210 #endif 211 , m_fRestoreCurrentSnapshot(false) 212 , m_fNoKeyboardGrabbing(false) 213 , m_fExecuteAllInIem(false) 214 , m_uWarpPct(100) 215 #ifdef VBOX_WITH_DEBUGGER_GUI 216 , m_fDbgEnabled(0) 217 , m_fDbgAutoShow(0) 218 , m_fDbgAutoShowCommandLine(0) 219 , m_fDbgAutoShowStatistics(0) 220 , m_hVBoxDbg(NIL_RTLDRMOD) 221 , m_enmLaunchRunning(LaunchRunning_Default) 222 #endif 223 , m_fSettingsPwSet(false) 224 , m_pThreadPool(0) 225 , m_pThreadPoolCloud(0) 226 , m_pTranlationEventListener(0) 227 { 228 /* Assign instance: */ 229 s_pInstance = this; 230 } 231 232 UICommon::~UICommon() 233 { 234 /* Unassign instance: */ 235 s_pInstance = 0; 236 } 237 238 void UICommon::prepare() 239 { 240 /* Make sure QApplication cleanup us on exit: */ 241 #ifndef VBOX_IS_QT6_OR_LATER /** @todo qt6: ... */ 242 qApp->setFallbackSessionManagementEnabled(false); 243 #endif 244 connect(qApp, &QGuiApplication::aboutToQuit, 245 this, &UICommon::sltCleanup); 246 #ifndef VBOX_GUI_WITH_CUSTOMIZATIONS1 247 /* Make sure we handle host OS session shutdown as well: */ 248 connect(qApp, &QGuiApplication::commitDataRequest, 249 this, &UICommon::sltHandleCommitDataRequest); 250 #endif /* VBOX_GUI_WITH_CUSTOMIZATIONS1 */ 251 252 #ifdef VBOX_WS_MAC 253 /* Determine OS release early: */ 254 m_enmMacOSVersion = determineOsRelease(); 255 #endif 256 257 #ifdef VBOX_WS_NIX 258 /* Detect display server type: */ 259 m_enmDisplayServerType = VBGHDisplayServerTypeDetect(); 260 #endif 261 262 /* Create converter: */ 263 UIConverter::create(); 264 265 /* Create desktop-widget watchdog: */ 266 UIDesktopWidgetWatchdog::create(); 267 268 /* Create message-center: */ 269 UIMessageCenter::create(); 270 /* Create popup-center: */ 271 UIPopupCenter::create(); 272 273 /* Prepare general icon-pool: */ 274 UIIconPoolGeneral::create(); 275 276 /* Load translation based on the current locale: */ 277 UITranslator::loadLanguage(); 278 279 /* Init COM: */ 280 UIGlobalSession::create(); 281 if (!gpGlobalSession->prepare()) 282 return; 283 connect(gpGlobalSession, &UIGlobalSession::sigVBoxSVCAvailabilityChange, 284 this, &UICommon::sltHandleVBoxSVCAvailabilityChange); 285 286 /* Prepare thread-pool instances: */ 287 m_pThreadPool = new UIThreadPool(3 /* worker count */, 5000 /* worker timeout */); 288 m_pThreadPoolCloud = new UIThreadPool(2 /* worker count */, 1000 /* worker timeout */); 289 290 /* Load whether host OS is in Dark mode: */ 291 #if defined(VBOX_WS_MAC) 292 m_fDarkMode = UICocoaApplication::instance()->isDarkMode(); 293 #elif defined(VBOX_WS_WIN) 294 m_fDarkMode = isWindowsInDarkMode(); 295 #else /* Linux, BSD, Solaris */ 296 m_fDarkMode = isPaletteInDarkMode(); 297 #endif /* Linux, BSD, Solaris */ 298 /* Load color theme: */ 299 loadColorTheme(); 300 301 /* Load translation based on the user settings: */ 302 QString strLanguageId = gEDataManager->languageId(); 303 if (!strLanguageId.isNull()) 304 UITranslator::loadLanguage(strLanguageId); 305 306 retranslateUi(); 307 308 /* Create translation event listener instance: */ 309 UITranslationEventListener::create(); 310 311 connect(gEDataManager, &UIExtraDataManager::sigLanguageChange, 312 this, &UICommon::sltGUILanguageChange); 313 connect(gEDataManager, &UIExtraDataManager::sigFontScaleFactorChanged, 314 this, &UICommon::sltHandleFontScaleFactorChanged); 315 316 qApp->installEventFilter(this); 317 318 /* process command line */ 319 320 UIVisualStateType visualStateType = UIVisualStateType_Invalid; 321 322 #ifdef VBOX_WS_NIX 323 /* Check whether we have compositing manager running: */ 324 m_fCompositingManagerRunning = NativeWindowSubsystem::isCompositingManagerRunning(X11ServerAvailable()); 325 326 /* Acquire current Window Manager type: */ 327 m_enmWindowManagerType = NativeWindowSubsystem::windowManagerType(X11ServerAvailable()); 328 #endif /* VBOX_WS_NIX */ 329 330 #ifdef VBOX_WITH_DEBUGGER_GUI 331 # ifdef VBOX_WITH_DEBUGGER_GUI_MENU 332 initDebuggerVar(&m_fDbgEnabled, "VBOX_GUI_DBG_ENABLED", GUI_Dbg_Enabled, true); 333 # else 334 initDebuggerVar(&m_fDbgEnabled, "VBOX_GUI_DBG_ENABLED", GUI_Dbg_Enabled, false); 335 # endif 336 initDebuggerVar(&m_fDbgAutoShow, "VBOX_GUI_DBG_AUTO_SHOW", GUI_Dbg_AutoShow, false); 337 m_fDbgAutoShowCommandLine = m_fDbgAutoShowStatistics = m_fDbgAutoShow; 338 #endif 339 340 /* 341 * Parse the command line options. 342 * 343 * This is a little sloppy but we're trying to tighten it up. Unfortuately, 344 * both on X11 and darwin (IIRC) there might be additional arguments aimed 345 * for client libraries with GUI processes. So, using RTGetOpt or similar 346 * is a bit hard since we have to cope with unknown options. 347 */ 348 m_fShowStartVMErrors = true; 349 bool startVM = false; 350 bool fSeparateProcess = false; 351 QString vmNameOrUuid; 352 353 const QStringList &arguments = QCoreApplication::arguments(); 354 const int argc = arguments.size(); 355 int i = 1; 356 while (i < argc) 357 { 358 const QByteArray &argBytes = arguments.at(i).toUtf8(); 359 const char *arg = argBytes.constData(); 360 enum { OptType_Unknown, OptType_VMRunner, OptType_VMSelector, OptType_MaybeBoth } enmOptType = OptType_Unknown; 361 /* NOTE: the check here must match the corresponding check for the 362 * options to start a VM in main.cpp and hardenedmain.cpp exactly, 363 * otherwise there will be weird error messages. */ 364 if ( !::strcmp(arg, "--startvm") 365 || !::strcmp(arg, "-startvm")) 366 { 367 enmOptType = OptType_VMRunner; 368 if (++i < argc) 369 { 370 vmNameOrUuid = arguments.at(i); 371 startVM = true; 372 } 373 } 374 else if (!::strcmp(arg, "-separate") || !::strcmp(arg, "--separate")) 375 { 376 enmOptType = OptType_VMRunner; 377 fSeparateProcess = true; 378 } 379 #ifdef VBOX_GUI_WITH_PIDFILE 380 else if (!::strcmp(arg, "-pidfile") || !::strcmp(arg, "--pidfile")) 381 { 382 enmOptType = OptType_MaybeBoth; 383 if (++i < argc) 384 m_strPidFile = arguments.at(i); 385 } 386 #endif /* VBOX_GUI_WITH_PIDFILE */ 387 /* Visual state type options: */ 388 else if (!::strcmp(arg, "-normal") || !::strcmp(arg, "--normal")) 389 { 390 enmOptType = OptType_MaybeBoth; 391 visualStateType = UIVisualStateType_Normal; 392 } 393 else if (!::strcmp(arg, "-fullscreen") || !::strcmp(arg, "--fullscreen")) 394 { 395 enmOptType = OptType_MaybeBoth; 396 visualStateType = UIVisualStateType_Fullscreen; 397 } 398 else if (!::strcmp(arg, "-seamless") || !::strcmp(arg, "--seamless")) 399 { 400 enmOptType = OptType_MaybeBoth; 401 visualStateType = UIVisualStateType_Seamless; 402 } 403 else if (!::strcmp(arg, "-scale") || !::strcmp(arg, "--scale")) 404 { 405 enmOptType = OptType_MaybeBoth; 406 visualStateType = UIVisualStateType_Scale; 407 } 408 /* Passwords: */ 409 else if (!::strcmp(arg, "--settingspw")) 410 { 411 enmOptType = OptType_MaybeBoth; 412 if (++i < argc) 413 { 414 RTStrCopy(m_astrSettingsPw, sizeof(m_astrSettingsPw), arguments.at(i).toLocal8Bit().constData()); 415 m_fSettingsPwSet = true; 416 } 417 } 418 else if (!::strcmp(arg, "--settingspwfile")) 419 { 420 enmOptType = OptType_MaybeBoth; 421 if (++i < argc) 422 { 423 const QByteArray &argFileBytes = arguments.at(i).toLocal8Bit(); 424 const char *pszFile = argFileBytes.constData(); 425 bool fStdIn = !::strcmp(pszFile, "stdin"); 426 int vrc = VINF_SUCCESS; 427 PRTSTREAM pStrm; 428 if (!fStdIn) 429 vrc = RTStrmOpen(pszFile, "r", &pStrm); 430 else 431 pStrm = g_pStdIn; 432 if (RT_SUCCESS(vrc)) 433 { 434 size_t cbFile; 435 vrc = RTStrmReadEx(pStrm, m_astrSettingsPw, sizeof(m_astrSettingsPw) - 1, &cbFile); 436 if (RT_SUCCESS(vrc)) 437 { 438 if (cbFile >= sizeof(m_astrSettingsPw) - 1) 439 cbFile = sizeof(m_astrSettingsPw) - 1; 440 unsigned i; 441 for (i = 0; i < cbFile && !RT_C_IS_CNTRL(m_astrSettingsPw[i]); i++) 442 ; 443 m_astrSettingsPw[i] = '\0'; 444 m_fSettingsPwSet = true; 445 } 446 if (!fStdIn) 447 RTStrmClose(pStrm); 448 } 449 } 450 } 451 /* Misc options: */ 452 else if (!::strcmp(arg, "-comment") || !::strcmp(arg, "--comment")) 453 { 454 enmOptType = OptType_MaybeBoth; 455 ++i; 456 } 457 else if (!::strcmp(arg, "--no-startvm-errormsgbox")) 458 { 459 enmOptType = OptType_VMRunner; 460 m_fShowStartVMErrors = false; 461 } 462 else if (!::strcmp(arg, "--aggressive-caching")) 463 { 464 enmOptType = OptType_MaybeBoth; 465 m_fAgressiveCaching = true; 466 } 467 else if (!::strcmp(arg, "--no-aggressive-caching")) 468 { 469 enmOptType = OptType_MaybeBoth; 470 m_fAgressiveCaching = false; 471 } 472 else if (!::strcmp(arg, "--restore-current")) 473 { 474 enmOptType = OptType_VMRunner; 475 m_fRestoreCurrentSnapshot = true; 476 } 477 else if (!::strcmp(arg, "--no-keyboard-grabbing")) 478 { 479 enmOptType = OptType_VMRunner; 480 m_fNoKeyboardGrabbing = true; 481 } 482 /* Ad hoc VM reconfig options: */ 483 else if (!::strcmp(arg, "--fda")) 484 { 485 enmOptType = OptType_VMRunner; 486 if (++i < argc) 487 m_uFloppyImage = QUuid(arguments.at(i)); 488 } 489 else if (!::strcmp(arg, "--dvd") || !::strcmp(arg, "--cdrom")) 490 { 491 enmOptType = OptType_VMRunner; 492 if (++i < argc) 493 m_uDvdImage = QUuid(arguments.at(i)); 494 } 495 /* VMM Options: */ 496 else if (!::strcmp(arg, "--execute-all-in-iem")) 497 { 498 enmOptType = OptType_VMRunner; 499 m_fExecuteAllInIem = true; 500 } 501 else if (!::strcmp(arg, "--driverless")) 502 enmOptType = OptType_VMRunner; 503 else if (!::strcmp(arg, "--warp-pct")) 504 { 505 enmOptType = OptType_VMRunner; 506 if (++i < argc) 507 m_uWarpPct = RTStrToUInt32(arguments.at(i).toLocal8Bit().constData()); 508 } 509 #ifdef VBOX_WITH_DEBUGGER_GUI 510 /* Debugger/Debugging options: */ 511 else if (!::strcmp(arg, "-dbg") || !::strcmp(arg, "--dbg")) 512 { 513 enmOptType = OptType_VMRunner; 514 setDebuggerVar(&m_fDbgEnabled, true); 515 } 516 else if (!::strcmp( arg, "-debug") || !::strcmp(arg, "--debug")) 517 { 518 enmOptType = OptType_VMRunner; 519 setDebuggerVar(&m_fDbgEnabled, true); 520 setDebuggerVar(&m_fDbgAutoShow, true); 521 setDebuggerVar(&m_fDbgAutoShowCommandLine, true); 522 setDebuggerVar(&m_fDbgAutoShowStatistics, true); 523 } 524 else if (!::strcmp(arg, "--debug-command-line")) 525 { 526 enmOptType = OptType_VMRunner; 527 setDebuggerVar(&m_fDbgEnabled, true); 528 setDebuggerVar(&m_fDbgAutoShow, true); 529 setDebuggerVar(&m_fDbgAutoShowCommandLine, true); 530 } 531 else if (!::strcmp(arg, "--debug-statistics")) 532 { 533 enmOptType = OptType_VMRunner; 534 setDebuggerVar(&m_fDbgEnabled, true); 535 setDebuggerVar(&m_fDbgAutoShow, true); 536 setDebuggerVar(&m_fDbgAutoShowStatistics, true); 537 } 538 else if (!::strcmp(arg, "--statistics-expand") || !::strcmp(arg, "--stats-expand")) 539 { 540 enmOptType = OptType_VMRunner; 541 if (++i < argc) 542 { 543 if (!m_strDbgStatisticsExpand.isEmpty()) 544 m_strDbgStatisticsExpand.append('|'); 545 m_strDbgStatisticsExpand.append(arguments.at(i)); 546 } 547 } 548 else if (!::strncmp(arg, RT_STR_TUPLE("--statistics-expand=")) || !::strncmp(arg, RT_STR_TUPLE("--stats-expand="))) 549 { 550 enmOptType = OptType_VMRunner; 551 if (!m_strDbgStatisticsExpand.isEmpty()) 552 m_strDbgStatisticsExpand.append('|'); 553 m_strDbgStatisticsExpand.append(arguments.at(i).section('=', 1)); 554 } 555 else if (!::strcmp(arg, "--statistics-filter") || !::strcmp(arg, "--stats-filter")) 556 { 557 enmOptType = OptType_VMRunner; 558 if (++i < argc) 559 m_strDbgStatisticsFilter = arguments.at(i); 560 } 561 else if (!::strncmp(arg, RT_STR_TUPLE("--statistics-filter=")) || !::strncmp(arg, RT_STR_TUPLE("--stats-filter="))) 562 { 563 enmOptType = OptType_VMRunner; 564 m_strDbgStatisticsFilter = arguments.at(i).section('=', 1); 565 } 566 else if (!::strcmp(arg, "--statistics-config") || !::strcmp(arg, "--stats-config")) 567 { 568 enmOptType = OptType_VMRunner; 569 if (++i < argc) 570 m_strDbgStatisticsConfig = arguments.at(i); 571 } 572 else if (!::strncmp(arg, RT_STR_TUPLE("--statistics-config=")) || !::strncmp(arg, RT_STR_TUPLE("--stats-config="))) 573 { 574 enmOptType = OptType_VMRunner; 575 m_strDbgStatisticsConfig = arguments.at(i).section('=', 1); 576 } 577 else if (!::strcmp(arg, "-no-debug") || !::strcmp(arg, "--no-debug")) 578 { 579 enmOptType = OptType_VMRunner; 580 setDebuggerVar(&m_fDbgEnabled, false); 581 setDebuggerVar(&m_fDbgAutoShow, false); 582 setDebuggerVar(&m_fDbgAutoShowCommandLine, false); 583 setDebuggerVar(&m_fDbgAutoShowStatistics, false); 584 } 585 /* Not quite debug options, but they're only useful with the debugger bits. */ 586 else if (!::strcmp(arg, "--start-paused")) 587 { 588 enmOptType = OptType_VMRunner; 589 m_enmLaunchRunning = LaunchRunning_No; 590 } 591 else if (!::strcmp(arg, "--start-running")) 592 { 593 enmOptType = OptType_VMRunner; 594 m_enmLaunchRunning = LaunchRunning_Yes; 595 } 596 #endif 597 if (enmOptType == OptType_VMRunner && m_enmType != UIType_RuntimeUI) 598 msgCenter().cannotHandleRuntimeOption(arg); 599 600 i++; 601 } 602 603 if (uiType() == UIType_RuntimeUI && startVM) 604 { 605 /* m_fSeparateProcess makes sense only if a VM is started. */ 606 m_fSeparateProcess = fSeparateProcess; 607 608 /* Search for corresponding VM: */ 609 QUuid uuid = QUuid(vmNameOrUuid); 610 const CVirtualBox comVBox = gpGlobalSession->virtualBox(); 611 const CMachine comMachine = comVBox.FindMachine(vmNameOrUuid); 612 if (!uuid.isNull()) 613 { 614 if (comMachine.isNull() && showStartVMErrors()) 615 return msgCenter().cannotFindMachineById(comVBox, uuid); 616 } 617 else 618 { 619 if (comMachine.isNull() && showStartVMErrors()) 620 return msgCenter().cannotFindMachineByName(comVBox, vmNameOrUuid); 621 } 622 m_uManagedVMId = comMachine.GetId(); 623 624 if (m_fSeparateProcess) 625 { 626 /* Create a log file for VirtualBoxVM process. */ 627 QString str = comMachine.GetLogFolder(); 628 com::Utf8Str logDir(str.toUtf8().constData()); 629 630 /* make sure the Logs folder exists */ 631 if (!RTDirExists(logDir.c_str())) 632 RTDirCreateFullPath(logDir.c_str(), 0700); 633 634 com::Utf8Str logFile = com::Utf8StrFmt("%s%cVBoxUI.log", 635 logDir.c_str(), RTPATH_DELIMITER); 636 637 com::VBoxLogRelCreate("GUI (separate)", logFile.c_str(), 638 RTLOGFLAGS_PREFIX_TIME_PROG | RTLOGFLAGS_RESTRICT_GROUPS, 639 "all all.restrict -default.restrict", 640 "VBOX_RELEASE_LOG", RTLOGDEST_FILE, 641 32768 /* cMaxEntriesPerGroup */, 642 0 /* cHistory */, 0 /* uHistoryFileTime */, 643 0 /* uHistoryFileSize */, NULL); 644 } 645 } 646 647 /* For Selector UI: */ 648 if (uiType() == UIType_ManagerUI) 649 { 650 /* We should create separate logging file for VM selector: */ 651 char szLogFile[RTPATH_MAX]; 652 const char *pszLogFile = NULL; 653 com::GetVBoxUserHomeDirectory(szLogFile, sizeof(szLogFile)); 654 RTPathAppend(szLogFile, sizeof(szLogFile), "selectorwindow.log"); 655 pszLogFile = szLogFile; 656 /* Create release logger, to file: */ 657 com::VBoxLogRelCreate("GUI VM Selector Window", 658 pszLogFile, 659 RTLOGFLAGS_PREFIX_TIME_PROG, 660 "all", 661 "VBOX_GUI_SELECTORWINDOW_RELEASE_LOG", 662 RTLOGDEST_FILE | RTLOGDEST_F_NO_DENY, 663 UINT32_MAX, 664 10, 665 60 * 60, 666 _1M, 667 NULL /*pErrInfo*/); 668 669 LogRel(("Qt version: %s\n", UIVersionInfo::qtRTVersionString().toUtf8().constData())); 670 } 671 672 if (m_fSettingsPwSet) 673 { 674 CVirtualBox comVBox = gpGlobalSession->virtualBox(); 675 comVBox.SetSettingsSecret(m_astrSettingsPw); 676 } 677 678 if (visualStateType != UIVisualStateType_Invalid && !m_uManagedVMId.isNull()) 679 gEDataManager->setRequestedVisualState(visualStateType, m_uManagedVMId); 680 681 #ifdef VBOX_WITH_DEBUGGER_GUI 682 /* For Runtime UI: */ 683 if (uiType() == UIType_RuntimeUI) 684 { 685 /* Setup the debugger GUI: */ 686 if (RTEnvExist("VBOX_GUI_NO_DEBUGGER")) 687 m_fDbgEnabled = m_fDbgAutoShow = m_fDbgAutoShowCommandLine = m_fDbgAutoShowStatistics = false; 688 if (m_fDbgEnabled) 689 { 690 RTERRINFOSTATIC ErrInfo; 691 RTErrInfoInitStatic(&ErrInfo); 692 int vrc = SUPR3HardenedLdrLoadAppPriv("VBoxDbg", &m_hVBoxDbg, RTLDRLOAD_FLAGS_LOCAL, &ErrInfo.Core); 693 if (RT_FAILURE(vrc)) 694 { 695 m_hVBoxDbg = NIL_RTLDRMOD; 696 m_fDbgAutoShow = m_fDbgAutoShowCommandLine = m_fDbgAutoShowStatistics = false; 697 LogRel(("Failed to load VBoxDbg, rc=%Rrc - %s\n", vrc, ErrInfo.Core.pszMsg)); 698 } 699 } 700 } 701 #endif 702 703 m_fValid = true; 704 705 /* Create medium-enumerator but don't do any immediate caching: */ 706 UIMediumEnumerator::create(); 707 { 708 /* Prepare medium-enumerator: */ 709 connect(gpMediumEnumerator, &UIMediumEnumerator::sigMediumCreated, 710 this, &UICommon::sigMediumCreated); 711 connect(gpMediumEnumerator, &UIMediumEnumerator::sigMediumDeleted, 712 this, &UICommon::sigMediumDeleted); 713 connect(gpMediumEnumerator, &UIMediumEnumerator::sigMediumEnumerationStarted, 714 this, &UICommon::sigMediumEnumerationStarted); 715 connect(gpMediumEnumerator, &UIMediumEnumerator::sigMediumEnumerated, 716 this, &UICommon::sigMediumEnumerated); 717 connect(gpMediumEnumerator, &UIMediumEnumerator::sigMediumEnumerationFinished, 718 this, &UICommon::sigMediumEnumerationFinished); 719 } 720 721 /* Create shortcut pool: */ 722 UIShortcutPool::create(uiType()); 723 724 #ifdef VBOX_GUI_WITH_NETWORK_MANAGER 725 /* Create network manager: */ 726 UINetworkRequestManager::create(); 727 728 /* Schedule update manager: */ 729 UIUpdateManager::schedule(); 730 #endif /* VBOX_GUI_WITH_NETWORK_MANAGER */ 731 732 #ifdef RT_OS_LINUX 733 /* Make sure no wrong USB mounted: */ 734 checkForWrongUSBMounted(); 735 #endif /* RT_OS_LINUX */ 736 737 iOriginalFontPixelSize = qApp->font().pixelSize(); 738 iOriginalFontPointSize = qApp->font().pointSize(); 739 sltHandleFontScaleFactorChanged(gEDataManager->fontScaleFactor()); 740 } 741 742 void UICommon::cleanup() 743 { 744 LogRel(("GUI: UICommon: Handling aboutToQuit request..\n")); 745 746 /// @todo Shouldn't that be protected with a mutex or something? 747 /* Remember that the cleanup is in progress preventing any unwanted 748 * stuff which could be called from the other threads: */ 749 m_fCleaningUp = true; 750 751 #ifdef VBOX_WS_WIN 752 /* Ask listeners to commit data if haven't yet: */ 753 if (!m_fDataCommitted) 754 { 755 emit sigAskToCommitData(); 756 m_fDataCommitted = true; 757 } 758 #else 759 /* Ask listeners to commit data: */ 760 emit sigAskToCommitData(); 761 #endif 762 763 #ifdef VBOX_WITH_DEBUGGER_GUI 764 /* For Runtime UI: */ 765 if ( uiType() == UIType_RuntimeUI 766 && m_hVBoxDbg != NIL_RTLDRMOD) 767 { 768 RTLdrClose(m_hVBoxDbg); 769 m_hVBoxDbg = NIL_RTLDRMOD; 770 } 771 #endif 772 773 #ifdef VBOX_GUI_WITH_NETWORK_MANAGER 774 /* Shutdown update manager: */ 775 UIUpdateManager::shutdown(); 776 777 /* Destroy network manager: */ 778 UINetworkRequestManager::destroy(); 779 #endif /* VBOX_GUI_WITH_NETWORK_MANAGER */ 780 781 /* Destroy shortcut pool: */ 782 UIShortcutPool::destroy(); 783 784 #ifdef VBOX_GUI_WITH_PIDFILE 785 deletePidfile(); 786 #endif /* VBOX_GUI_WITH_PIDFILE */ 787 788 /* Destroy medium-enumerator: */ 789 UIMediumEnumerator::destroy(); 790 791 /* Destroy the global (VirtualBox and VirtualBoxClient) Main event 792 * handlers which are used in both Manager and Runtime UIs. */ 793 UIVirtualBoxEventHandler::destroy(); 794 UIVirtualBoxClientEventHandler::destroy(); 795 796 /* Destroy the extra-data manager finally after everything 797 * above which could use it already destroyed: */ 798 UIExtraDataManager::destroy(); 799 800 /* Destroy converter: */ 801 UIConverter::destroy(); 802 803 /* Cleanup thread-pools: */ 804 delete m_pThreadPool; 805 m_pThreadPool = 0; 806 delete m_pThreadPoolCloud; 807 m_pThreadPoolCloud = 0; 808 809 /* First, make sure we don't use COM any more: */ 810 emit sigAskToDetachCOM(); 811 812 /* Cleanup COM: */ 813 gpGlobalSession->cleanup(); 814 UIGlobalSession::destroy(); 815 816 /* Notify listener it can close UI now: */ 817 emit sigAskToCloseUI(); 818 819 /* Cleanup general icon-pool: */ 820 UIIconPoolGeneral::destroy(); 821 822 /* Destroy popup-center: */ 823 UIPopupCenter::destroy(); 824 /* Destroy message-center: */ 825 UIMessageCenter::destroy(); 826 827 /* Destroy desktop-widget watchdog: */ 828 UIDesktopWidgetWatchdog::destroy(); 829 830 /* Destroy translation event listener instance: */ 831 UITranslationEventListener::destroy(); 832 833 m_fValid = false; 834 835 LogRel(("GUI: UICommon: aboutToQuit request handled!\n")); 836 } 837 838 #ifdef VBOX_WS_MAC 839 /* static */ 840 MacOSXRelease UICommon::determineOsRelease() 841 { 842 /* Prepare 'utsname' struct: */ 843 utsname info; 844 if (uname(&info) != -1) 845 { 846 /* Cut the major release index of the string we have, s.a. 'man uname': */ 847 const int iRelease = QString(info.release).section('.', 0, 0).toInt(); 848 /* Check boundaries: */ 849 if (iRelease <= MacOSXRelease_FirstUnknown) 850 return MacOSXRelease_Old; 851 else if (iRelease >= MacOSXRelease_LastUnknown) 852 return MacOSXRelease_New; 853 else 854 return (MacOSXRelease)iRelease; 855 } 856 /* Return 'Old' by default: */ 857 return MacOSXRelease_Old; 858 } 859 #endif /* VBOX_WS_MAC */ 860 861 #ifdef VBOX_WS_NIX 862 bool UICommon::X11ServerAvailable() const 863 { 864 return VBGHDisplayServerTypeIsXAvailable(m_enmDisplayServerType); 865 } 866 867 VBGHDISPLAYSERVERTYPE UICommon::displayServerType() const 868 { 869 return m_enmDisplayServerType; 870 } 871 #endif 872 873 QString UICommon::hostOperatingSystem() const 874 { 875 const CHost comHost = gpGlobalSession->host(); 876 return comHost.GetOperatingSystem(); 877 } 878 879 #if defined(VBOX_WS_MAC) 880 // Provided by UICocoaApplication .. 881 882 #elif defined(VBOX_WS_WIN) 883 884 bool UICommon::isWindowsInDarkMode() const 885 { 886 /* Load saved color theme: */ 887 UIColorThemeType enmColorTheme = gEDataManager->colorTheme(); 888 889 /* Check whether we have dark system theme requested: */ 890 if (enmColorTheme == UIColorThemeType_Auto) 891 { 892 QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 893 QSettings::NativeFormat); 894 if (settings.value("AppsUseLightTheme") == 0) 895 enmColorTheme = UIColorThemeType_Dark; 896 } 897 898 /* Return result: */ 899 return enmColorTheme == UIColorThemeType_Dark; 900 } 901 902 #else /* Linux, BSD, Solaris */ 903 904 bool UICommon::isPaletteInDarkMode() const 905 { 906 const QPalette pal = qApp->palette(); 907 const QColor background = pal.color(QPalette::Active, QPalette::Window); 908 const double dLuminance = (0.299 * background.red() + 0.587 * background.green() + 0.114 * background.blue()) / 255; 909 return dLuminance < 0.5; 910 } 911 #endif /* Linux, BSD, Solaris */ 912 913 void UICommon::loadColorTheme() 914 { 915 #if defined (VBOX_WS_MAC) 916 /* macOS has Window color hardcoded somewhere inside, Qt has no access to it, 917 * moreover these colors are influenced by window background blending, 918 * making Qt default colors incredibly inconsistent with native macOS apps. */ 919 920 /* Redefine colors for known OS types: */ 921 enum ColorSlot 922 { 923 ColorSlot_DarkActive, 924 ColorSlot_DarkInactive, 925 ColorSlot_DarkAlternate, 926 ColorSlot_LightActive, 927 ColorSlot_LightInactive, 928 ColorSlot_LightAlternate, 929 }; 930 QMap<ColorSlot, QColor> colors; 931 switch (osRelease()) 932 { 933 case MacOSXRelease_BigSur: 934 { 935 colors[ColorSlot_DarkActive] = QColor("#282628"); 936 colors[ColorSlot_DarkInactive] = QColor("#2E292E"); 937 colors[ColorSlot_LightActive] = QColor("#E7E2E3"); 938 colors[ColorSlot_LightInactive] = QColor("#EEE9EA"); 939 break; 940 } 941 case MacOSXRelease_Monterey: 942 { 943 colors[ColorSlot_DarkActive] = QColor("#252328"); 944 colors[ColorSlot_DarkInactive] = QColor("#2A2630"); 945 colors[ColorSlot_LightActive] = QColor("#E1DEE4"); 946 colors[ColorSlot_LightInactive] = QColor("#EEE8E9"); 947 break; 948 } 949 case MacOSXRelease_Ventura: 950 { 951 colors[ColorSlot_DarkActive] = QColor("#322827"); 952 colors[ColorSlot_DarkInactive] = QColor("#332A28"); 953 colors[ColorSlot_LightActive] = QColor("#E5E0DF"); 954 colors[ColorSlot_LightInactive] = QColor("#ECE7E5"); 955 break; 956 } 957 default: 958 break; 959 } 960 /* Redefine colors common for various OS types: */ 961 // we do it only if we have redefined something above: 962 if (!colors.isEmpty()) 963 { 964 colors[ColorSlot_DarkAlternate] = QColor("#2F2A2F"); 965 colors[ColorSlot_LightAlternate] = QColor("#F4F5F5"); 966 } 967 968 /* Do we have redefined colors? */ 969 if (!colors.isEmpty()) 970 { 971 QPalette pal = qApp->palette(); 972 if (isInDarkMode()) 973 { 974 pal.setColor(QPalette::Active, QPalette::Window, colors.value(ColorSlot_DarkActive)); 975 pal.setColor(QPalette::Inactive, QPalette::Window, colors.value(ColorSlot_DarkInactive)); 976 pal.setColor(QPalette::Active, QPalette::AlternateBase, colors.value(ColorSlot_DarkAlternate)); 977 pal.setColor(QPalette::Inactive, QPalette::AlternateBase, colors.value(ColorSlot_DarkAlternate)); 978 } 979 else 980 { 981 pal.setColor(QPalette::Active, QPalette::Window, colors.value(ColorSlot_LightActive)); 982 pal.setColor(QPalette::Inactive, QPalette::Window, colors.value(ColorSlot_LightInactive)); 983 pal.setColor(QPalette::Active, QPalette::AlternateBase, colors.value(ColorSlot_LightAlternate)); 984 pal.setColor(QPalette::Inactive, QPalette::AlternateBase, colors.value(ColorSlot_LightAlternate)); 985 } 986 qApp->setPalette(pal); 987 } 988 989 #elif defined(VBOX_WS_WIN) 990 991 /* For the Dark mode! */ 992 if (isInDarkMode()) 993 { 994 qApp->setStyle(QStyleFactory::create("Fusion")); 995 QPalette darkPalette; 996 QColor windowColor1 = QColor(59, 60, 61); 997 QColor windowColor2 = QColor(63, 64, 65); 998 QColor baseColor1 = QColor(46, 47, 48); 999 QColor baseColor2 = QColor(56, 57, 58); 1000 QColor disabledColor = QColor(113, 114, 115); 1001 darkPalette.setColor(QPalette::Window, windowColor1); 1002 darkPalette.setColor(QPalette::WindowText, Qt::white); 1003 darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, disabledColor); 1004 darkPalette.setColor(QPalette::Base, baseColor1); 1005 darkPalette.setColor(QPalette::AlternateBase, baseColor2); 1006 darkPalette.setColor(QPalette::PlaceholderText, disabledColor); 1007 darkPalette.setColor(QPalette::Text, Qt::white); 1008 darkPalette.setColor(QPalette::Disabled, QPalette::Text, disabledColor); 1009 darkPalette.setColor(QPalette::Button, windowColor2); 1010 darkPalette.setColor(QPalette::ButtonText, Qt::white); 1011 darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, disabledColor); 1012 darkPalette.setColor(QPalette::BrightText, Qt::red); 1013 darkPalette.setColor(QPalette::Link, QColor(179, 214, 242)); 1014 darkPalette.setColor(QPalette::Highlight, QColor(29, 84, 92)); 1015 darkPalette.setColor(QPalette::HighlightedText, Qt::white); 1016 darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, disabledColor); 1017 qApp->setPalette(darkPalette); 1018 qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2b2b2b; border: 1px solid #737373; }"); 1019 } 1020 1021 #else /* Linux, BSD, Solaris */ 1022 1023 /* For the Dark mode! */ 1024 if (isInDarkMode()) 1025 { 1026 // WORKAROUND: 1027 // Have seen it on Linux with Qt5 but still see it with Qt6. 1028 // In Dark themes on KDE (at least) PlaceholderText foreground 1029 // is indistinguishable on Base background. 1030 1031 /* Acquire global palette: */ 1032 QPalette darkPalette = qApp->palette(); 1033 1034 /* Get text base color: */ 1035 const QColor base = darkPalette.color(QPalette::Active, QPalette::Base); 1036 1037 /* Get possible foreground colors: */ 1038 const QColor simpleText = darkPalette.color(QPalette::Active, QPalette::Text); 1039 const QColor placeholderText = darkPalette.color(QPalette::Active, QPalette::PlaceholderText); 1040 QColor lightText = simpleText.black() < placeholderText.black() ? simpleText : placeholderText; 1041 QColor darkText = simpleText.black() > placeholderText.black() ? simpleText : placeholderText; 1042 if (lightText.black() > 128) 1043 lightText = QColor(Qt::white); 1044 lightText = lightText.darker(150); 1045 if (darkText.black() < 128) 1046 darkText = QColor(Qt::black); 1047 darkText = darkText.lighter(150); 1048 1049 /* Measure base luminance: */ 1050 double dLuminance = (0.299 * base.red() + 0.587 * base.green() + 0.114 * base.blue()) / 255; 1051 1052 /* Adjust color accordingly: */ 1053 darkPalette.setColor(QPalette::Active, QPalette::PlaceholderText, 1054 dLuminance > 0.5 ? darkText : lightText); 1055 1056 /* Put palette back: */ 1057 qApp->setPalette(darkPalette); 1058 } 1059 1060 #endif /* Linux, BSD, Solaris */ 1061 } 1062 1063 bool UICommon::processArgs() 1064 { 1065 /* Among those arguments: */ 1066 bool fResult = false; 1067 const QStringList args = qApp->arguments(); 1068 1069 /* We are looking for a list of file URLs passed to the executable: */ 1070 QList<QUrl> listArgUrls; 1071 for (int i = 1; i < args.size(); ++i) 1072 { 1073 /* But we break out after the first parameter, cause there 1074 * could be parameters with arguments (e.g. --comment comment). */ 1075 if (args.at(i).startsWith("-")) 1076 break; 1077 1078 #ifdef VBOX_WS_MAC 1079 const QString strArg = ::darwinResolveAlias(args.at(i)); 1080 #else 1081 const QString strArg = args.at(i); 1082 #endif 1083 1084 /* So if the argument file exists, we add it to URL list: */ 1085 if ( !strArg.isEmpty() 1086 && QFile::exists(strArg)) 1087 listArgUrls << QUrl::fromLocalFile(QFileInfo(strArg).absoluteFilePath()); 1088 } 1089 1090 /* If there are file URLs: */ 1091 if (!listArgUrls.isEmpty()) 1092 { 1093 /* We enumerate them and: */ 1094 for (int i = 0; i < listArgUrls.size(); ++i) 1095 { 1096 /* Check which of them has allowed VM extensions: */ 1097 const QUrl url = listArgUrls.at(i); 1098 const QString strFile = url.toLocalFile(); 1099 if (UICommon::hasAllowedExtension(strFile, VBoxFileExts)) 1100 { 1101 /* So that we could run existing VMs: */ 1102 CVirtualBox comVBox = gpGlobalSession->virtualBox(); 1103 CMachine comMachine = comVBox.FindMachine(strFile); 1104 if (!comMachine.isNull()) 1105 { 1106 fResult = true; 1107 launchMachine(comMachine); 1108 /* And remove their URLs from the ULR list: */ 1109 listArgUrls.removeAll(url); 1110 } 1111 } 1112 } 1113 } 1114 1115 /* And if there are *still* URLs: */ 1116 if (!listArgUrls.isEmpty()) 1117 { 1118 /* We store them, they will be handled later: */ 1119 m_listArgUrls = listArgUrls; 1120 } 1121 1122 return fResult; 1123 } 1124 1125 bool UICommon::argumentUrlsPresent() const 1126 { 1127 return !m_listArgUrls.isEmpty(); 1128 } 1129 1130 QList<QUrl> UICommon::takeArgumentUrls() 1131 { 1132 const QList<QUrl> result = m_listArgUrls; 1133 m_listArgUrls.clear(); 1134 return result; 1135 } 1136 1137 #ifdef VBOX_WITH_DEBUGGER_GUI 1138 1139 bool UICommon::isDebuggerEnabled() const 1140 { 1141 return isDebuggerWorker(&m_fDbgEnabled, GUI_Dbg_Enabled); 1142 } 1143 1144 bool UICommon::isDebuggerAutoShowEnabled() const 1145 { 1146 return isDebuggerWorker(&m_fDbgAutoShow, GUI_Dbg_AutoShow); 1147 } 1148 1149 bool UICommon::isDebuggerAutoShowCommandLineEnabled() const 1150 { 1151 return isDebuggerWorker(&m_fDbgAutoShowCommandLine, GUI_Dbg_AutoShow); 1152 } 1153 1154 bool UICommon::isDebuggerAutoShowStatisticsEnabled() const 1155 { 1156 return isDebuggerWorker(&m_fDbgAutoShowStatistics, GUI_Dbg_AutoShow); 1157 } 1158 1159 #endif /* VBOX_WITH_DEBUGGER_GUI */ 1160 1161 bool UICommon::shouldStartPaused() const 1162 { 1163 #ifdef VBOX_WITH_DEBUGGER_GUI 1164 return m_enmLaunchRunning == LaunchRunning_Default ? isDebuggerAutoShowEnabled() : m_enmLaunchRunning == LaunchRunning_No; 1165 #else 1166 return false; 1167 #endif 1168 } 1169 1170 #ifdef VBOX_GUI_WITH_PIDFILE 1171 1172 void UICommon::createPidfile() 1173 { 1174 if (!m_strPidFile.isEmpty()) 1175 { 1176 const qint64 iPid = qApp->applicationPid(); 1177 QFile file(m_strPidFile); 1178 if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) 1179 { 1180 QTextStream out(&file); 1181 out << iPid << endl; 1182 } 1183 else 1184 LogRel(("Failed to create pid file %s\n", m_strPidFile.toUtf8().constData())); 1185 } 1186 } 1187 1188 void UICommon::deletePidfile() 1189 { 1190 if ( !m_strPidFile.isEmpty() 1191 && QFile::exists(m_strPidFile)) 1192 QFile::remove(m_strPidFile); 1193 } 1194 1195 #endif /* VBOX_GUI_WITH_PIDFILE */ 1196 1197 /* static */ 1198 bool UICommon::switchToMachine(CMachine &comMachine) 1199 { 1200 #ifdef VBOX_WS_MAC 1201 const ULONG64 id = comMachine.ShowConsoleWindow(); 1202 #else 1203 const WId id = (WId)comMachine.ShowConsoleWindow(); 1204 #endif 1205 Assert(comMachine.isOk()); 1206 if (!comMachine.isOk()) 1207 return false; 1208 1209 // WORKAROUND: 1210 // id == 0 means the console window has already done everything 1211 // necessary to implement the "show window" semantics. 1212 if (id == 0) 1213 return true; 1214 1215 #if defined(VBOX_WS_WIN) || defined(VBOX_WS_NIX) 1216 1217 return UIDesktopWidgetWatchdog::activateWindow(id, true); 1218 1219 #elif defined(VBOX_WS_MAC) 1220 1221 // WORKAROUND: 1222 // This is just for the case were the other process cannot steal 1223 // the focus from us. It will send us a PSN so we can try. 1224 ProcessSerialNumber psn; 1225 psn.highLongOfPSN = id >> 32; 1226 psn.lowLongOfPSN = (UInt32)id; 1227 # ifdef __clang__ 1228 # pragma GCC diagnostic push 1229 # pragma GCC diagnostic ignored "-Wdeprecated-declarations" 1230 OSErr rc = ::SetFrontProcess(&psn); 1231 # pragma GCC diagnostic pop 1232 # else 1233 OSErr rc = ::SetFrontProcess(&psn); 1234 # endif 1235 if (!rc) 1236 Log(("GUI: %#RX64 couldn't do SetFrontProcess on itself, the selector (we) had to do it...\n", id)); 1237 else 1238 Log(("GUI: Failed to bring %#RX64 to front. rc=%#x\n", id, rc)); 1239 return !rc; 1240 1241 #else 1242 1243 return false; 1244 1245 #endif 1246 } 1247 1248 /* static */ 1249 bool UICommon::launchMachine(CMachine &comMachine, UILaunchMode enmLaunchMode /* = UILaunchMode_Default */) 1250 { 1251 /* Switch to machine window(s) if possible: */ 1252 if ( comMachine.GetSessionState() == KSessionState_Locked /* precondition for CanShowConsoleWindow() */ 1253 && comMachine.CanShowConsoleWindow()) 1254 { 1255 switch (uiCommon().uiType()) 1256 { 1257 /* For Selector UI: */ 1258 case UIType_ManagerUI: 1259 { 1260 /* Just switch to existing VM window: */ 1261 return switchToMachine(comMachine); 1262 } 1263 /* For Runtime UI: */ 1264 case UIType_RuntimeUI: 1265 { 1266 /* Only separate UI process can reach that place. 1267 * Switch to existing VM window and exit. */ 1268 switchToMachine(comMachine); 1269 return false; 1270 } 1271 } 1272 } 1273 1274 /* Not for separate UI (which can connect to machine in any state): */ 1275 if (enmLaunchMode != UILaunchMode_Separate) 1276 { 1277 /* Make sure machine-state is one of required: */ 1278 const KMachineState enmState = comMachine.GetState(); NOREF(enmState); 1279 AssertMsg( enmState == KMachineState_PoweredOff 1280 || enmState == KMachineState_Saved 1281 || enmState == KMachineState_Teleported 1282 || enmState == KMachineState_Aborted 1283 || enmState == KMachineState_AbortedSaved 1284 , ("Machine must be PoweredOff/Saved/Teleported/Aborted (%d)", enmState)); 1285 } 1286 1287 /* Create empty session instance: */ 1288 CSession comSession; 1289 comSession.createInstance(CLSID_Session); 1290 if (comSession.isNull()) 1291 { 1292 msgCenter().cannotOpenSession(comSession); 1293 return false; 1294 } 1295 1296 /* Configure environment: */ 1297 QVector<QString> astrEnv; 1298 #ifdef VBOX_WS_WIN 1299 /* Allow started VM process to be foreground window: */ 1300 AllowSetForegroundWindow(ASFW_ANY); 1301 #endif 1302 #ifdef VBOX_WS_NIX 1303 /* Make sure VM process will start on the same 1304 * display as window this wrapper is called from: */ 1305 const char *pDisplay = RTEnvGet("DISPLAY"); 1306 if (pDisplay) 1307 astrEnv.append(QString("DISPLAY=%1").arg(pDisplay)); 1308 const char *pXauth = RTEnvGet("XAUTHORITY"); 1309 if (pXauth) 1310 astrEnv.append(QString("XAUTHORITY=%1").arg(pXauth)); 1311 #endif 1312 QString strType; 1313 switch (enmLaunchMode) 1314 { 1315 case UILaunchMode_Default: strType = ""; break; 1316 case UILaunchMode_Separate: strType = uiCommon().isSeparateProcess() ? "headless" : "separate"; break; 1317 case UILaunchMode_Headless: strType = "headless"; break; 1318 default: AssertFailedReturn(false); 1319 } 1320 1321 /* Prepare "VM spawning" progress: */ 1322 CProgress comProgress = comMachine.LaunchVMProcess(comSession, strType, astrEnv); 1323 if (!comMachine.isOk()) 1324 { 1325 /* If the VM is started separately and the VM process is already running, then it is OK. */ 1326 if (enmLaunchMode == UILaunchMode_Separate) 1327 { 1328 const KMachineState enmState = comMachine.GetState(); 1329 if ( enmState >= KMachineState_FirstOnline 1330 && enmState <= KMachineState_LastOnline) 1331 { 1332 /* Already running: */ 1333 return true; 1334 } 1335 } 1336 1337 msgCenter().cannotOpenSession(comMachine); 1338 return false; 1339 } 1340 1341 /* Show "VM spawning" progress: */ 1342 msgCenter().showModalProgressDialog(comProgress, comMachine.GetName(), 1343 ":/progress_start_90px.png", 0, 0); 1344 if (!comProgress.isOk() || comProgress.GetResultCode() != 0) 1345 msgCenter().cannotOpenSession(comProgress, comMachine.GetName()); 1346 1347 /* Unlock machine, close session: */ 1348 comSession.UnlockMachine(); 1349 1350 /* True finally: */ 1351 return true; 1352 } 1353 1354 CSession UICommon::openSession(QUuid uId, KLockType enmLockType /* = KLockType_Write */) 1355 { 1356 /* Prepare session: */ 1357 CSession comSession; 1358 1359 /* Make sure uId isn't null: */ 1360 if (uId.isNull()) 1361 uId = managedVMUuid(); 1362 if (uId.isNull()) 1363 return comSession; 1364 1365 /* Simulate try-catch block: */ 1366 bool fSuccess = false; 1367 do 1368 { 1369 /* Create empty session instance: */ 1370 comSession.createInstance(CLSID_Session); 1371 if (comSession.isNull()) 1372 { 1373 msgCenter().cannotOpenSession(comSession); 1374 break; 1375 } 1376 1377 /* Search for the corresponding machine: */ 1378 const CVirtualBox comVBox = gpGlobalSession->virtualBox(); 1379 CMachine comMachine = comVBox.FindMachine(uId.toString()); 1380 if (comMachine.isNull()) 1381 { 1382 msgCenter().cannotFindMachineById(comVBox, uId); 1383 break; 1384 } 1385 1386 if (enmLockType == KLockType_VM) 1387 comSession.SetName("GUI/Qt"); 1388 1389 /* Lock found machine to session: */ 1390 comMachine.LockMachine(comSession, enmLockType); 1391 if (!comMachine.isOk()) 1392 { 1393 msgCenter().cannotOpenSession(comMachine); 1394 break; 1395 } 1396 1397 /* Pass the language ID as the property to the guest: */ 1398 if (comSession.GetType() == KSessionType_Shared) 1399 { 1400 CMachine comStartedMachine = comSession.GetMachine(); 1401 /* Make sure that the language is in two letter code. 1402 * Note: if languageId() returns an empty string lang.name() will 1403 * return "C" which is an valid language code. */ 1404 QLocale lang(UITranslator::languageId()); 1405 comStartedMachine.SetGuestPropertyValue("/VirtualBox/HostInfo/GUI/LanguageID", lang.name()); 1406 } 1407 1408 /* Success finally: */ 1409 fSuccess = true; 1410 } 1411 while (0); 1412 /* Cleanup try-catch block: */ 1413 if (!fSuccess) 1414 comSession.detach(); 1415 1416 /* Return session: */ 1417 return comSession; 1418 } 1419 1420 CSession UICommon::openSession(KLockType enmLockType /* = KLockType_Write */) 1421 { 1422 /* Pass to function above: */ 1423 return openSession(managedVMUuid(), enmLockType); 1424 } 1425 1426 CSession UICommon::tryToOpenSessionFor(CMachine &comMachine) 1427 { 1428 /* Prepare session: */ 1429 CSession comSession; 1430 1431 /* Session state unlocked? */ 1432 if (comMachine.GetSessionState() == KSessionState_Unlocked) 1433 { 1434 /* Open own 'write' session: */ 1435 comSession = openSession(comMachine.GetId()); 1436 AssertReturn(!comSession.isNull(), CSession()); 1437 comMachine = comSession.GetMachine(); 1438 } 1439 /* Is this a Selector UI call? */ 1440 else if (uiType() == UIType_ManagerUI) 1441 { 1442 /* Open existing 'shared' session: */ 1443 comSession = openExistingSession(comMachine.GetId()); 1444 AssertReturn(!comSession.isNull(), CSession()); 1445 comMachine = comSession.GetMachine(); 1446 } 1447 /* Else this is Runtime UI call 1448 * which has session locked for itself. */ 1449 1450 /* Return session: */ 1451 return comSession; 1452 } 1453 1454 void UICommon::notifyCloudMachineUnregistered(const QString &strProviderShortName, 1455 const QString &strProfileName, 1456 const QUuid &uId) 1457 { 1458 emit sigCloudMachineUnregistered(strProviderShortName, strProfileName, uId); 1459 } 1460 1461 void UICommon::notifyCloudMachineRegistered(const QString &strProviderShortName, 1462 const QString &strProfileName, 1463 const CCloudMachine &comMachine) 1464 { 1465 emit sigCloudMachineRegistered(strProviderShortName, strProfileName, comMachine); 1466 } 1467 1468 QUuid UICommon::openMedium(UIMediumDeviceType enmMediumType, QString strMediumLocation, QWidget *pParent /* = 0 */) 53 54 QUuid UIMediumTools::openMedium(UIMediumDeviceType enmMediumType, 55 const QString &strMediumLocation, 56 QWidget *pParent /* = 0 */) 1469 57 { 1470 58 /* Convert to native separators: */ 1471 strMediumLocation = QDir::toNativeSeparators(strMediumLocation);59 const QString strLocation = QDir::toNativeSeparators(strMediumLocation); 1472 60 1473 61 /* Initialize variables: */ … … 1475 63 1476 64 /* Open corresponding medium: */ 1477 CMedium comMedium = comVBox.OpenMedium(str MediumLocation, mediumTypeToGlobal(enmMediumType), KAccessMode_ReadWrite, false);65 CMedium comMedium = comVBox.OpenMedium(strLocation, mediumTypeToGlobal(enmMediumType), KAccessMode_ReadWrite, false); 1478 66 1479 67 if (comVBox.isOk()) … … 1494 82 } 1495 83 else 1496 msgCenter().cannotOpenMedium(comVBox, str MediumLocation, pParent);84 msgCenter().cannotOpenMedium(comVBox, strLocation, pParent); 1497 85 1498 86 return QUuid(); 1499 87 } 1500 88 1501 QUuid UICommon::openMediumWithFileOpenDialog(UIMediumDeviceType enmMediumType, QWidget *pParent, 1502 const QString &strDefaultFolder /* = QString() */, 1503 bool fUseLastFolder /* = false */) 89 QUuid UIMediumTools::openMediumWithFileOpenDialog(UIMediumDeviceType enmMediumType, 90 QWidget *pParent, 91 const QString &strDefaultFolder /* = QString() */, 92 bool fUseLastFolder /* = false */) 1504 93 { 1505 94 /* Initialize variables: */ … … 1512 101 QString strLastFolder = UIMediumEnumerator::defaultFolderPathForType(enmMediumType); 1513 102 1514 /* For DVDs and Floppies always check first the last recently used medium folder. For hard disk use1515 103 /* For DVDs and Floppies always check first the last recently used medium folder. 104 * For hard disk use the caller's setting: */ 1516 105 fUseLastFolder = (enmMediumType == UIMediumDeviceType_DVD) || (enmMediumType == UIMediumDeviceType_Floppy); 1517 106 … … 1521 110 { 1522 111 filters = HDDBackends(gpGlobalSession->virtualBox()); 1523 strTitle = tr("Please choose a virtual hard disk file");1524 allType = tr("All virtual hard disk files (%1)");112 strTitle = UICommon::tr("Please choose a virtual hard disk file"); 113 allType = UICommon::tr("All virtual hard disk files (%1)"); 1525 114 break; 1526 115 } … … 1528 117 { 1529 118 filters = DVDBackends(gpGlobalSession->virtualBox()); 1530 strTitle = tr("Please choose a virtual optical disk file");1531 allType = tr("All virtual optical disk files (%1)");119 strTitle = UICommon::tr("Please choose a virtual optical disk file"); 120 allType = UICommon::tr("All virtual optical disk files (%1)"); 1532 121 break; 1533 122 } … … 1535 124 { 1536 125 filters = FloppyBackends(gpGlobalSession->virtualBox()); 1537 strTitle = tr("Please choose a virtual floppy disk file");1538 allType = tr("All virtual floppy disk files (%1)");126 strTitle = UICommon::tr("Please choose a virtual floppy disk file"); 127 allType = UICommon::tr("All virtual floppy disk files (%1)"); 1539 128 break; 1540 129 } … … 1557 146 if (!prefixes.isEmpty()) 1558 147 backends.insert(0, allType.arg(prefixes.join(" ").trimmed())); 1559 backends << tr("All files (*)");148 backends << UICommon::tr("All files (*)"); 1560 149 strFilter = backends.join(";;").trimmed(); 1561 150 … … 1575 164 } 1576 165 1577 QUuid UICommon::openMediumCreatorDialog(UIActionPool *pActionPool, QWidget *pParent, UIMediumDeviceType enmMediumType, 1578 const QString &strDefaultFolder /* = QString() */, 1579 const QString &strMachineName /* = QString() */, 1580 const QString &strMachineGuestOSTypeId /*= QString() */) 166 QUuid UIMediumTools::openMediumCreatorDialog(UIActionPool *pActionPool, 167 QWidget *pParent, 168 UIMediumDeviceType enmMediumType, 169 const QString &strDefaultFolder /* = QString() */, 170 const QString &strMachineName /* = QString() */, 171 const QString &strMachineGuestOSTypeId /*= QString() */) 1581 172 { 1582 173 /* Depending on medium-type: */ … … 1605 196 } 1606 197 1607 void UICommon::prepareStorageMenu(QMenu *pMenu, 1608 QObject *pListener, const char *pszSlotName, 1609 const CMachine &comMachine, const QString &strControllerName, const StorageSlot &storageSlot) 198 void UIMediumTools::prepareStorageMenu(QMenu *pMenu, 199 QObject *pListener, 200 const char *pszSlotName, 201 const CMachine &comMachine, 202 const QString &strControllerName, 203 const StorageSlot &storageSlot) 1610 204 { 1611 205 /* Current attachment attributes: */ … … 1760 354 } 1761 355 1762 void UICommon::updateMachineStorage(const CMachine &comConstMachine, const UIMediumTarget &target, UIActionPool *pActionPool) 356 void UIMediumTools::updateMachineStorage(const CMachine &comConstMachine, 357 const UIMediumTarget &target, 358 UIActionPool *pActionPool) 1763 359 { 1764 360 /* Mount (by default): */ … … 1877 473 /* Get editable machine & session: */ 1878 474 CMachine comMachine = comConstMachine; 1879 CSession comSession = tryToOpenSessionFor(comMachine);475 CSession comSession = uiCommon().tryToOpenSessionFor(comMachine); 1880 476 1881 477 /* Remount medium to the predefined port/device: */ … … 1934 530 comSession.UnlockMachine(); 1935 531 } 1936 1937 QString UICommon::storageDetails(const CMedium &comMedium, bool fPredictDiff, bool fUseHtml /* = true */)1938 {1939 /* Search for corresponding UI medium: */1940 const QUuid uMediumID = comMedium.isNull() ? UIMedium::nullID() : comMedium.GetId();1941 UIMedium guiMedium = gpMediumEnumerator->medium(uMediumID);1942 if (!comMedium.isNull() && guiMedium.isNull())1943 {1944 /* UI medium may be new and not among cached media, request enumeration: */1945 gpMediumEnumerator->enumerateMedia(CMediumVector() << comMedium);1946 1947 /* Search for corresponding UI medium again: */1948 guiMedium = gpMediumEnumerator->medium(uMediumID);1949 if (guiMedium.isNull())1950 {1951 /* Medium might be deleted already, return null string: */1952 return QString();1953 }1954 }1955 1956 /* For differencing hard-disk we have to request1957 * enumeration of whole tree based in it's root item: */1958 if ( comMedium.isNotNull()1959 && comMedium.GetDeviceType() == KDeviceType_HardDisk)1960 {1961 /* Traverse through parents to root to catch it: */1962 CMedium comRootMedium;1963 CMedium comParentMedium = comMedium.GetParent();1964 while (comParentMedium.isNotNull())1965 {1966 comRootMedium = comParentMedium;1967 comParentMedium = comParentMedium.GetParent();1968 }1969 /* Enumerate root if it's found and wasn't cached: */1970 if (comRootMedium.isNotNull())1971 {1972 const QUuid uRootId = comRootMedium.GetId();1973 if (gpMediumEnumerator->medium(uRootId).isNull())1974 gpMediumEnumerator->enumerateMedia(CMediumVector() << comRootMedium);1975 }1976 }1977 1978 /* Return UI medium details: */1979 return fUseHtml ? guiMedium.detailsHTML(true /* no diffs? */, fPredictDiff) :1980 guiMedium.details(true /* no diffs? */, fPredictDiff);1981 }1982 1983 /* static */1984 bool UICommon::acquireAmountOfImmutableImages(const CMachine &comMachine, ulong &cAmount)1985 {1986 /* Acquire state: */1987 ulong cAmountOfImmutableImages = 0;1988 const KMachineState enmState = comMachine.GetState();1989 bool fSuccess = comMachine.isOk();1990 if (!fSuccess)1991 UINotificationMessage::cannotAcquireMachineParameter(comMachine);1992 else1993 {1994 /// @todo Who knows why 13 years ago this condition was added ..1995 if (enmState == KMachineState_Paused)1996 {1997 const CMediumAttachmentVector comAttachments = comMachine.GetMediumAttachments();1998 fSuccess = comMachine.isOk();1999 if (!fSuccess)2000 UINotificationMessage::cannotAcquireMachineParameter(comMachine);2001 else2002 {2003 /* Calculate the amount of immutable attachments: */2004 foreach (const CMediumAttachment &comAttachment, comAttachments)2005 {2006 /* Get the medium: */2007 const CMedium comMedium = comAttachment.GetMedium();2008 if ( comMedium.isNull() /* Null medium is valid case as well */2009 || comMedium.GetParent().isNull() /* Null parent is valid case as well */)2010 continue;2011 /* Get the base medium: */2012 const CMedium comBaseMedium = comMedium.GetBase();2013 fSuccess = comMedium.isOk();2014 if (!fSuccess)2015 UINotificationMessage::cannotAcquireMediumParameter(comMedium);2016 else2017 {2018 const KMediumType enmType = comBaseMedium.GetType();2019 fSuccess = comBaseMedium.isOk();2020 if (!fSuccess)2021 UINotificationMessage::cannotAcquireMediumParameter(comBaseMedium);2022 else if (enmType == KMediumType_Immutable)2023 ++cAmountOfImmutableImages;2024 }2025 if (!fSuccess)2026 break;2027 }2028 }2029 }2030 }2031 if (fSuccess)2032 cAmount = cAmountOfImmutableImages;2033 return fSuccess;2034 }2035 2036 #ifdef RT_OS_LINUX2037 /* static */2038 void UICommon::checkForWrongUSBMounted()2039 {2040 /* Make sure '/proc/mounts' exists and can be opened: */2041 QFile file("/proc/mounts");2042 if (!file.exists() || !file.open(QIODevice::ReadOnly | QIODevice::Text))2043 return;2044 2045 /* Fetch contents: */2046 QStringList contents;2047 for (;;)2048 {2049 QByteArray line = file.readLine();2050 if (line.isEmpty())2051 break;2052 contents << line;2053 }2054 /* Grep contents for usbfs presence: */2055 QStringList grep1(contents.filter("/sys/bus/usb/drivers"));2056 QStringList grep2(grep1.filter("usbfs"));2057 if (grep2.isEmpty())2058 return;2059 2060 /* Show corresponding warning: */2061 msgCenter().warnAboutWrongUSBMounted();2062 }2063 #endif /* RT_OS_LINUX */2064 2065 /* static */2066 QString UICommon::usbDetails(const CUSBDevice &comDevice)2067 {2068 QString strDetails;2069 if (comDevice.isNull())2070 strDetails = tr("Unknown device", "USB device details");2071 else2072 {2073 QVector<QString> devInfoVector = comDevice.GetDeviceInfo();2074 QString strManufacturer;2075 QString strProduct;2076 2077 if (devInfoVector.size() >= 1)2078 strManufacturer = devInfoVector[0].trimmed();2079 if (devInfoVector.size() >= 2)2080 strProduct = devInfoVector[1].trimmed();2081 2082 if (strManufacturer.isEmpty() && strProduct.isEmpty())2083 {2084 strDetails =2085 tr("Unknown device %1:%2", "USB device details")2086 .arg(QString::number(comDevice.GetVendorId(), 16).toUpper().rightJustified(4, '0'))2087 .arg(QString::number(comDevice.GetProductId(), 16).toUpper().rightJustified(4, '0'));2088 }2089 else2090 {2091 if (strProduct.toUpper().startsWith(strManufacturer.toUpper()))2092 strDetails = strProduct;2093 else2094 strDetails = strManufacturer + " " + strProduct;2095 }2096 ushort iRev = comDevice.GetRevision();2097 if (iRev != 0)2098 {2099 strDetails += " [";2100 strDetails += QString::number(iRev, 16).toUpper().rightJustified(4, '0');2101 strDetails += "]";2102 }2103 }2104 2105 return strDetails.trimmed();2106 }2107 2108 /* static */2109 QString UICommon::usbToolTip(const CUSBDevice &comDevice)2110 {2111 QString strTip =2112 tr("<nobr>Vendor ID: %1</nobr><br>"2113 "<nobr>Product ID: %2</nobr><br>"2114 "<nobr>Revision: %3</nobr>", "USB device tooltip")2115 .arg(QString::number(comDevice.GetVendorId(), 16).toUpper().rightJustified(4, '0'))2116 .arg(QString::number(comDevice.GetProductId(), 16).toUpper().rightJustified(4, '0'))2117 .arg(QString::number(comDevice.GetRevision(), 16).toUpper().rightJustified(4, '0'));2118 2119 const QString strSerial = comDevice.GetSerialNumber();2120 if (!strSerial.isEmpty())2121 strTip += QString(tr("<br><nobr>Serial No. %1</nobr>", "USB device tooltip"))2122 .arg(strSerial);2123 2124 /* Add the state field if it's a host USB device: */2125 CHostUSBDevice hostDev(comDevice);2126 if (!hostDev.isNull())2127 {2128 strTip += QString(tr("<br><nobr>State: %1</nobr>", "USB device tooltip"))2129 .arg(gpConverter->toString(hostDev.GetState()));2130 }2131 2132 return strTip;2133 }2134 2135 /* static */2136 QString UICommon::usbToolTip(const CUSBDeviceFilter &comFilter)2137 {2138 QString strTip;2139 2140 const QString strVendorId = comFilter.GetVendorId();2141 if (!strVendorId.isEmpty())2142 strTip += tr("<nobr>Vendor ID: %1</nobr>", "USB filter tooltip")2143 .arg(strVendorId);2144 2145 const QString strProductId = comFilter.GetProductId();2146 if (!strProductId.isEmpty())2147 strTip += strTip.isEmpty() ? "":"<br/>" + tr("<nobr>Product ID: %2</nobr>", "USB filter tooltip")2148 .arg(strProductId);2149 2150 const QString strRevision = comFilter.GetRevision();2151 if (!strRevision.isEmpty())2152 strTip += strTip.isEmpty() ? "":"<br/>" + tr("<nobr>Revision: %3</nobr>", "USB filter tooltip")2153 .arg(strRevision);2154 2155 const QString strProduct = comFilter.GetProduct();2156 if (!strProduct.isEmpty())2157 strTip += strTip.isEmpty() ? "":"<br/>" + tr("<nobr>Product: %4</nobr>", "USB filter tooltip")2158 .arg(strProduct);2159 2160 const QString strManufacturer = comFilter.GetManufacturer();2161 if (!strManufacturer.isEmpty())2162 strTip += strTip.isEmpty() ? "":"<br/>" + tr("<nobr>Manufacturer: %5</nobr>", "USB filter tooltip")2163 .arg(strManufacturer);2164 2165 const QString strSerial = comFilter.GetSerialNumber();2166 if (!strSerial.isEmpty())2167 strTip += strTip.isEmpty() ? "":"<br/>" + tr("<nobr>Serial No.: %1</nobr>", "USB filter tooltip")2168 .arg(strSerial);2169 2170 const QString strPort = comFilter.GetPort();2171 if (!strPort.isEmpty())2172 strTip += strTip.isEmpty() ? "":"<br/>" + tr("<nobr>Port: %1</nobr>", "USB filter tooltip")2173 .arg(strPort);2174 2175 /* Add the state field if it's a host USB device: */2176 CHostUSBDevice hostDev(comFilter);2177 if (!hostDev.isNull())2178 {2179 strTip += strTip.isEmpty() ? "":"<br/>" + tr("<nobr>State: %1</nobr>", "USB filter tooltip")2180 .arg(gpConverter->toString(hostDev.GetState()));2181 }2182 2183 return strTip;2184 }2185 2186 /* static */2187 QString UICommon::usbToolTip(const CHostVideoInputDevice &comWebcam)2188 {2189 QStringList records;2190 2191 const QString strName = comWebcam.GetName();2192 if (!strName.isEmpty())2193 records << strName;2194 2195 const QString strPath = comWebcam.GetPath();2196 if (!strPath.isEmpty())2197 records << strPath;2198 2199 return records.join("<br>");2200 }2201 2202 int UICommon::supportedRecordingFeatures() const2203 {2204 int iSupportedFlag = 0;2205 CSystemProperties comProperties = gpGlobalSession->virtualBox().GetSystemProperties();2206 foreach (const KRecordingFeature &enmFeature, comProperties.GetSupportedRecordingFeatures())2207 iSupportedFlag |= enmFeature;2208 return iSupportedFlag;2209 }2210 2211 /* static */2212 QString UICommon::helpFile()2213 {2214 const QString strName = "UserManual";2215 const QString strSuffix = "qhc";2216 2217 /* Where are the docs located? */2218 char szDocsPath[RTPATH_MAX];2219 int rc = RTPathAppDocs(szDocsPath, sizeof(szDocsPath));2220 AssertRC(rc);2221 2222 /* Make sure that the language is in two letter code.2223 * Note: if languageId() returns an empty string lang.name() will2224 * return "C" which is an valid language code. */2225 QLocale lang(UITranslator::languageId());2226 2227 /* Construct the path and the filename: */2228 QString strManual = QString("%1/%2_%3.%4").arg(szDocsPath)2229 .arg(strName)2230 .arg(lang.name())2231 .arg(strSuffix);2232 2233 /* Check if a help file with that name exists: */2234 QFileInfo fi(strManual);2235 if (fi.exists())2236 return strManual;2237 2238 /* Fall back to the standard: */2239 strManual = QString("%1/%2.%4").arg(szDocsPath)2240 .arg(strName)2241 .arg(strSuffix);2242 return strManual;2243 }2244 2245 /* static */2246 QString UICommon::documentsPath()2247 {2248 QString strPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);2249 QDir dir(strPath);2250 if (dir.exists())2251 return QDir::cleanPath(dir.canonicalPath());2252 else2253 {2254 dir.setPath(QDir::homePath() + "/Documents");2255 if (dir.exists())2256 return QDir::cleanPath(dir.canonicalPath());2257 else2258 return QDir::homePath();2259 }2260 }2261 2262 /* static */2263 bool UICommon::hasAllowedExtension(const QString &strFileName, const QStringList &extensions)2264 {2265 foreach (const QString &strExtension, extensions)2266 if (strFileName.endsWith(strExtension, Qt::CaseInsensitive))2267 return true;2268 return false;2269 }2270 2271 /* static */2272 QString UICommon::findUniqueFileName(const QString &strFullFolderPath, const QString &strBaseFileName)2273 {2274 QDir folder(strFullFolderPath);2275 if (!folder.exists())2276 return strBaseFileName;2277 QFileInfoList folderContent = folder.entryInfoList();2278 QSet<QString> fileNameSet;2279 foreach (const QFileInfo &fileInfo, folderContent)2280 {2281 /* Remove the extension : */2282 fileNameSet.insert(fileInfo.completeBaseName());2283 }2284 int iSuffix = 0;2285 QString strNewName(strBaseFileName);2286 while (fileNameSet.contains(strNewName))2287 {2288 strNewName = strBaseFileName + QString("_") + QString::number(++iSuffix);2289 }2290 return strNewName;2291 }2292 2293 /* static */2294 void UICommon::setMinimumWidthAccordingSymbolCount(QSpinBox *pSpinBox, int cCount)2295 {2296 /* Shame on Qt it hasn't stuff for tuning2297 * widget size suitable for reflecting content of desired size.2298 * For example QLineEdit, QSpinBox and similar widgets should have a methods2299 * to strict the minimum width to reflect at least [n] symbols. */2300 2301 /* Load options: */2302 QStyleOptionSpinBox option;2303 option.initFrom(pSpinBox);2304 2305 /* Acquire edit-field rectangle: */2306 QRect rect = pSpinBox->style()->subControlRect(QStyle::CC_SpinBox,2307 &option,2308 QStyle::SC_SpinBoxEditField,2309 pSpinBox);2310 2311 /* Calculate minimum-width magic: */2312 const int iSpinBoxWidth = pSpinBox->width();2313 const int iSpinBoxEditFieldWidth = rect.width();2314 const int iSpinBoxDelta = qMax(0, iSpinBoxWidth - iSpinBoxEditFieldWidth);2315 const QFontMetrics metrics(pSpinBox->font(), pSpinBox);2316 const QString strDummy(cCount, '0');2317 const int iTextWidth = metrics.horizontalAdvance(strDummy);2318 2319 /* Tune spin-box minimum-width: */2320 pSpinBox->setMinimumWidth(iTextWidth + iSpinBoxDelta);2321 }2322 2323 #ifdef VBOX_WITH_3D_ACCELERATION2324 /* static */2325 bool UICommon::isWddmCompatibleOsType(const QString &strGuestOSTypeId)2326 {2327 return strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("WindowsVista"))2328 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows7"))2329 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows8"))2330 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows81"))2331 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows10"))2332 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows11"))2333 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows2008"))2334 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows2012"))2335 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows2016"))2336 || strGuestOSTypeId.startsWith(GUEST_OS_ID_STR_PARTIAL("Windows2019"));2337 }2338 #endif /* VBOX_WITH_3D_ACCELERATION */2339 2340 /* static */2341 quint64 UICommon::requiredVideoMemory(const QString &strGuestOSTypeId, int cMonitors /* = 1 */)2342 {2343 /* We create a list of the size of all available host monitors. This list2344 * is sorted by value and by starting with the biggest one, we calculate2345 * the memory requirements for every guest screen. This is of course not2346 * correct, but as we can't predict on which host screens the user will2347 * open the guest windows, this is the best assumption we can do, cause it2348 * is the worst case. */2349 const int cHostScreens = UIDesktopWidgetWatchdog::screenCount();2350 QVector<int> screenSize(qMax(cMonitors, cHostScreens), 0);2351 for (int i = 0; i < cHostScreens; ++i)2352 {2353 QRect r = gpDesktop->screenGeometry(i);2354 screenSize[i] = r.width() * r.height();2355 }2356 /* Now sort the vector: */2357 std::sort(screenSize.begin(), screenSize.end(), std::greater<int>());2358 /* For the case that there are more guest screens configured then host2359 * screens available, replace all zeros with the greatest value in the2360 * vector. */2361 for (int i = 0; i < screenSize.size(); ++i)2362 if (screenSize.at(i) == 0)2363 screenSize.replace(i, screenSize.at(0));2364 2365 quint64 uNeedBits = 0;2366 for (int i = 0; i < cMonitors; ++i)2367 {2368 /* Calculate summary required memory amount in bits: */2369 uNeedBits += (screenSize.at(i) * /* with x height */2370 32 + /* we will take the maximum possible bpp for now */2371 8 * _1M) + /* current cache per screen - may be changed in future */2372 8 * 4096; /* adapter info */2373 }2374 /* Translate value into megabytes with rounding to highest side: */2375 quint64 uNeedMBytes = uNeedBits % (8 * _1M)2376 ? uNeedBits / (8 * _1M) + 12377 : uNeedBits / (8 * _1M) /* convert to megabytes */;2378 2379 if (strGuestOSTypeId.startsWith("Windows"))2380 {2381 /* Windows guests need offscreen VRAM too for graphics acceleration features: */2382 #ifdef VBOX_WITH_3D_ACCELERATION2383 if (isWddmCompatibleOsType(strGuestOSTypeId))2384 {2385 /* WDDM mode, there are two surfaces for each screen: shadow & primary: */2386 uNeedMBytes *= 3;2387 }2388 else2389 #endif /* VBOX_WITH_3D_ACCELERATION */2390 {2391 uNeedMBytes *= 2;2392 }2393 }2394 2395 return uNeedMBytes * _1M;2396 }2397 2398 KGraphicsControllerType UICommon::getRecommendedGraphicsController(const QString &strGuestOSTypeId) const2399 {2400 return gpGlobalSession->guestOSTypeManager().getRecommendedGraphicsController(strGuestOSTypeId);2401 }2402 2403 /* static */2404 void UICommon::setHelpKeyword(QObject *pObject, const QString &strHelpKeyword)2405 {2406 if (pObject)2407 pObject->setProperty("helpkeyword", strHelpKeyword);2408 }2409 2410 /* static */2411 QString UICommon::helpKeyword(const QObject *pObject)2412 {2413 if (!pObject)2414 return QString();2415 return pObject->property("helpkeyword").toString();2416 }2417 2418 bool UICommon::openURL(const QString &strUrl) const2419 {2420 /** Service event. */2421 class ServiceEvent : public QEvent2422 {2423 public:2424 2425 /** Constructs service event on th basis of passed @a fResult. */2426 ServiceEvent(bool fResult)2427 : QEvent(QEvent::User)2428 , m_fResult(fResult)2429 {}2430 2431 /** Returns the result which event brings. */2432 bool result() const { return m_fResult; }2433 2434 private:2435 2436 /** Holds the result which event brings. */2437 bool m_fResult;2438 };2439 2440 /** Service client object. */2441 class ServiceClient : public QEventLoop2442 {2443 public:2444 2445 /** Constructs service client on the basis of passed @a fResult. */2446 ServiceClient()2447 : m_fResult(false)2448 {}2449 2450 /** Returns the result which event brings. */2451 bool result() const { return m_fResult; }2452 2453 private:2454 2455 /** Handles any Qt @a pEvent. */2456 bool event(QEvent *pEvent) RT_OVERRIDE RT_FINAL2457 {2458 /* Handle service event: */2459 if (pEvent->type() == QEvent::User)2460 {2461 ServiceEvent *pServiceEvent = static_cast<ServiceEvent*>(pEvent);2462 m_fResult = pServiceEvent->result();2463 pServiceEvent->accept();2464 quit();2465 return true;2466 }2467 return false;2468 }2469 2470 bool m_fResult;2471 };2472 2473 /** Service server object. */2474 class ServiceServer : public QThread2475 {2476 public:2477 2478 /** Constructs service server on the basis of passed @a client and @a strUrl. */2479 ServiceServer(ServiceClient &client, const QString &strUrl)2480 : m_client(client), m_strUrl(strUrl) {}2481 2482 private:2483 2484 /** Executes thread task. */2485 void run() RT_OVERRIDE RT_FINAL2486 {2487 QApplication::postEvent(&m_client, new ServiceEvent(QDesktopServices::openUrl(m_strUrl)));2488 }2489 2490 /** Holds the client reference. */2491 ServiceClient &m_client;2492 /** Holds the URL to be processed. */2493 const QString &m_strUrl;2494 };2495 2496 /* Create client & server: */2497 ServiceClient client;2498 ServiceServer server(client, strUrl);2499 server.start();2500 client.exec();2501 server.wait();2502 2503 /* Acquire client result: */2504 bool fResult = client.result();2505 if (!fResult)2506 UINotificationMessage::cannotOpenURL(strUrl);2507 2508 return fResult;2509 }2510 2511 void UICommon::sltGUILanguageChange(QString strLanguage)2512 {2513 /* Make sure medium-enumeration is not in progress! */2514 AssertReturnVoid(!gpMediumEnumerator->isMediumEnumerationInProgress());2515 /* Load passed language: */2516 UITranslator::loadLanguage(strLanguage);2517 }2518 2519 void UICommon::sltHandleMediumCreated(const CMedium &comMedium)2520 {2521 /* Acquire device type: */2522 const KDeviceType enmDeviceType = comMedium.GetDeviceType();2523 if (!comMedium.isOk())2524 UINotificationMessage::cannotAcquireMediumParameter(comMedium);2525 else2526 {2527 /* Convert to medium type: */2528 const UIMediumDeviceType enmMediumType = mediumTypeToLocal(enmDeviceType);2529 2530 /* Make sure we cached created medium in GUI: */2531 gpMediumEnumerator->createMedium(UIMedium(comMedium, enmMediumType, KMediumState_Created));2532 }2533 }2534 2535 void UICommon::sltHandleMachineCreated(const CMachine &comMachine)2536 {2537 /* Register created machine. */2538 CVirtualBox comVBox = gpGlobalSession->virtualBox();2539 comVBox.RegisterMachine(comMachine);2540 if (!comVBox.isOk())2541 UINotificationMessage::cannotRegisterMachine(comVBox, comMachine.GetName());2542 }2543 2544 void UICommon::sltHandleCloudMachineAdded(const QString &strProviderShortName,2545 const QString &strProfileName,2546 const CCloudMachine &comMachine)2547 {2548 /* Make sure we cached added cloud VM in GUI: */2549 notifyCloudMachineRegistered(strProviderShortName,2550 strProfileName,2551 comMachine);2552 }2553 2554 bool UICommon::eventFilter(QObject *pObject, QEvent *pEvent)2555 {2556 /** @todo Just use the QIWithRetranslateUI3 template wrapper. */2557 2558 if ( pEvent->type() == QEvent::LanguageChange2559 && pObject->isWidgetType()2560 && qobject_cast<QWidget*>(pObject)->isWindow())2561 {2562 /* Catch the language change event before any other widget gets it in2563 * order to invalidate cached string resources (like the details view2564 * templates) that may be used by other widgets. */2565 QWidgetList list = QApplication::topLevelWidgets();2566 if (list.first() == pObject)2567 {2568 /* Call this only once per every language change (see2569 * QApplication::installTranslator() for details): */2570 retranslateUi();2571 }2572 }2573 2574 /* Handle application palette change event: */2575 if ( pEvent->type() == QEvent::ApplicationPaletteChange2576 && pObject == windowManager().mainWindowShown())2577 {2578 #if defined(VBOX_WS_MAC)2579 const bool fDarkMode = UICocoaApplication::instance()->isDarkMode();2580 #elif defined(VBOX_WS_WIN)2581 const bool fDarkMode = isWindowsInDarkMode();2582 #else /* Linux, BSD, Solaris */2583 const bool fDarkMode = isPaletteInDarkMode();2584 #endif /* Linux, BSD, Solaris */2585 if (m_fDarkMode != fDarkMode)2586 {2587 m_fDarkMode = fDarkMode;2588 loadColorTheme();2589 emit sigThemeChange();2590 }2591 }2592 2593 /* Call to base-class: */2594 return QObject::eventFilter(pObject, pEvent);2595 }2596 2597 void UICommon::sltHandleFontScaleFactorChanged(int iFontScaleFactor)2598 {2599 QFont appFont = qApp->font();2600 2601 /* Let's round up some double var: */2602 auto roundUp = [](double dValue)2603 {2604 const int iValue = dValue;2605 return dValue > (double)iValue ? iValue + 1 : iValue;2606 };2607 2608 /* Do we have pixel font? */2609 if (iOriginalFontPixelSize != -1)2610 appFont.setPixelSize(roundUp(iFontScaleFactor / 100.f * iOriginalFontPixelSize));2611 /* Point font otherwise: */2612 else2613 appFont.setPointSize(roundUp(iFontScaleFactor / 100.f * iOriginalFontPointSize));2614 2615 qApp->setFont(appFont);2616 }2617 2618 void UICommon::retranslateUi()2619 {2620 /* Re-enumerate uimedium since they contain some translations too: */2621 if (isValid())2622 gpMediumEnumerator->refreshMedia();2623 2624 #ifdef VBOX_WS_NIX2625 // WORKAROUND:2626 // As X11 do not have functionality for providing human readable key names,2627 // we keep a table of them, which must be updated when the language is changed.2628 UINativeHotKey::retranslateKeyNames();2629 #endif2630 }2631 2632 #ifndef VBOX_GUI_WITH_CUSTOMIZATIONS12633 void UICommon::sltHandleCommitDataRequest(QSessionManager &manager)2634 {2635 LogRel(("GUI: UICommon: Commit data request...\n"));2636 2637 /* Ask listener to commit data: */2638 emit sigAskToCommitData();2639 # ifdef VBOX_WS_WIN2640 m_fDataCommitted = true;2641 # endif2642 2643 /* Depending on UI type: */2644 switch (uiType())2645 {2646 /* For Runtime UI: */2647 case UIType_RuntimeUI:2648 {2649 /* Thin clients will be able to shutdown properly,2650 * but for fat clients: */2651 if (!isSeparateProcess())2652 {2653 # if defined(VBOX_WS_MAC) && defined(VBOX_IS_QT6_OR_LATER) /** @todo qt6: ... */2654 Q_UNUSED(manager);2655 /* This code prevents QWindowSystemInterface::handleApplicationTermination2656 for running, so among other things QApplication::closeAllWindows isn't2657 called and we're somehow stuck in a half closed down state. That said,2658 just disabling this isn't sufficent, there we also have to accept() the2659 QCloseEvent in UIMachineWindow. */2660 /** @todo qt6: This isn't quite the right fix, I bet... I'm sure I haven't2661 * quite understood all that's going on here. So, leaving this for2662 * the real GUI experts to look into... :-) */2663 # else2664 // WORKAROUND:2665 // We can't save VM state in one go for fat clients, so we have to ask session manager to cancel shutdown.2666 // To next major release this should be removed in any case, since there will be no fat clients after all.2667 manager.cancel();2668 2669 # ifdef VBOX_WS_WIN2670 // WORKAROUND:2671 // In theory that's Qt5 who should allow us to provide canceling reason as well, but that functionality2672 // seems to be missed in Windows platform plugin, so we are making that ourselves.2673 NativeWindowSubsystem::ShutdownBlockReasonCreateAPI((HWND)windowManager().mainWindowShown()->winId(), L"VM is still running.");2674 # endif2675 # endif2676 }2677 2678 break;2679 }2680 default:2681 break;2682 }2683 }2684 #endif /* !VBOX_GUI_WITH_CUSTOMIZATIONS1 */2685 2686 void UICommon::sltHandleVBoxSVCAvailabilityChange(bool fAvailable)2687 {2688 /* If VBoxSVC is available: */2689 if (fAvailable)2690 {2691 /* For Selector UI: */2692 if (uiType() == UIType_ManagerUI)2693 {2694 /* Recreate Main event listeners: */2695 UIVirtualBoxEventHandler::destroy();2696 UIVirtualBoxClientEventHandler::destroy();2697 UIExtraDataManager::destroy();2698 UIExtraDataManager::instance();2699 UIVirtualBoxEventHandler::instance();2700 UIVirtualBoxClientEventHandler::instance();2701 /* Ask UIStarter to restart UI: */2702 emit sigAskToRestartUI();2703 }2704 }2705 }2706 2707 #ifdef VBOX_WITH_DEBUGGER_GUI2708 2709 # define UICOMMON_DBG_CFG_VAR_FALSE (0)2710 # define UICOMMON_DBG_CFG_VAR_TRUE (1)2711 # define UICOMMON_DBG_CFG_VAR_MASK (1)2712 # define UICOMMON_DBG_CFG_VAR_CMD_LINE RT_BIT(3)2713 # define UICOMMON_DBG_CFG_VAR_DONE RT_BIT(4)2714 2715 void UICommon::initDebuggerVar(int *piDbgCfgVar, const char *pszEnvVar, const char *pszExtraDataName, bool fDefault)2716 {2717 QString strEnvValue;2718 char szEnvValue[256];2719 int rc = RTEnvGetEx(RTENV_DEFAULT, pszEnvVar, szEnvValue, sizeof(szEnvValue), NULL);2720 if (RT_SUCCESS(rc))2721 {2722 strEnvValue = QString::fromUtf8(&szEnvValue[0]).toLower().trimmed();2723 if (strEnvValue.isEmpty())2724 strEnvValue = "yes";2725 }2726 else if (rc != VERR_ENV_VAR_NOT_FOUND)2727 strEnvValue = "veto";2728 2729 CVirtualBox comVBox = gpGlobalSession->virtualBox();2730 QString strExtraValue = comVBox.GetExtraData(pszExtraDataName).toLower().trimmed();2731 if (strExtraValue.isEmpty())2732 strExtraValue = QString();2733 2734 if ( strEnvValue.contains("veto") || strExtraValue.contains("veto"))2735 *piDbgCfgVar = UICOMMON_DBG_CFG_VAR_DONE | UICOMMON_DBG_CFG_VAR_FALSE;2736 else if (strEnvValue.isNull() && strExtraValue.isNull())2737 *piDbgCfgVar = fDefault ? UICOMMON_DBG_CFG_VAR_TRUE : UICOMMON_DBG_CFG_VAR_FALSE;2738 else2739 {2740 QString *pStr = !strEnvValue.isEmpty() ? &strEnvValue : &strExtraValue;2741 if ( pStr->startsWith("y") // yes2742 || pStr->startsWith("e") // enabled2743 || pStr->startsWith("t") // true2744 || pStr->startsWith("on")2745 || pStr->toLongLong() != 0)2746 *piDbgCfgVar = UICOMMON_DBG_CFG_VAR_TRUE;2747 else if ( pStr->startsWith("n") // o2748 || pStr->startsWith("d") // disable2749 || pStr->startsWith("f") // false2750 || pStr->startsWith("off")2751 || pStr->contains("veto") /* paranoia */2752 || pStr->toLongLong() == 0)2753 *piDbgCfgVar = UICOMMON_DBG_CFG_VAR_FALSE;2754 else2755 {2756 LogFunc(("Ignoring unknown value '%s' for '%s'\n", pStr->toUtf8().constData(), pStr == &strEnvValue ? pszEnvVar : pszExtraDataName));2757 *piDbgCfgVar = fDefault ? UICOMMON_DBG_CFG_VAR_TRUE : UICOMMON_DBG_CFG_VAR_FALSE;2758 }2759 }2760 }2761 2762 void UICommon::setDebuggerVar(int *piDbgCfgVar, bool fState)2763 {2764 if (!(*piDbgCfgVar & UICOMMON_DBG_CFG_VAR_DONE))2765 *piDbgCfgVar = (fState ? UICOMMON_DBG_CFG_VAR_TRUE : UICOMMON_DBG_CFG_VAR_FALSE)2766 | UICOMMON_DBG_CFG_VAR_CMD_LINE;2767 }2768 2769 bool UICommon::isDebuggerWorker(int *piDbgCfgVar, const char *pszExtraDataName) const2770 {2771 if (!(*piDbgCfgVar & UICOMMON_DBG_CFG_VAR_DONE))2772 {2773 const QString str = gEDataManager->debugFlagValue(pszExtraDataName);2774 if (str.contains("veto"))2775 *piDbgCfgVar = UICOMMON_DBG_CFG_VAR_DONE | UICOMMON_DBG_CFG_VAR_FALSE;2776 else if (str.isEmpty() || (*piDbgCfgVar & UICOMMON_DBG_CFG_VAR_CMD_LINE))2777 *piDbgCfgVar |= UICOMMON_DBG_CFG_VAR_DONE;2778 else if ( str.startsWith("y") // yes2779 || str.startsWith("e") // enabled2780 || str.startsWith("t") // true2781 || str.startsWith("on")2782 || str.toLongLong() != 0)2783 *piDbgCfgVar = UICOMMON_DBG_CFG_VAR_DONE | UICOMMON_DBG_CFG_VAR_TRUE;2784 else if ( str.startsWith("n") // no2785 || str.startsWith("d") // disable2786 || str.startsWith("f") // false2787 || str.toLongLong() == 0)2788 *piDbgCfgVar = UICOMMON_DBG_CFG_VAR_DONE | UICOMMON_DBG_CFG_VAR_FALSE;2789 else2790 *piDbgCfgVar |= UICOMMON_DBG_CFG_VAR_DONE;2791 }2792 2793 return (*piDbgCfgVar & UICOMMON_DBG_CFG_VAR_MASK) == UICOMMON_DBG_CFG_VAR_TRUE;2794 }2795 2796 #endif /* VBOX_WITH_DEBUGGER_GUI */ -
trunk/src/VBox/Frontends/VirtualBox/src/medium/UIMediumTools.h
r104899 r104901 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - UI Commonclass declaration.3 * VBox Qt GUI - UIMediumTools class declaration. 4 4 */ 5 5 … … 26 26 */ 27 27 28 #ifndef FEQT_INCLUDED_SRC_ globals_UICommon_h29 #define FEQT_INCLUDED_SRC_ globals_UICommon_h28 #ifndef FEQT_INCLUDED_SRC_medium_UIMediumTools_h 29 #define FEQT_INCLUDED_SRC_medium_UIMediumTools_h 30 30 #ifndef RT_WITHOUT_PRAGMA_ONCE 31 31 # pragma once … … 33 33 34 34 /* Qt includes: */ 35 #include <Q Object>35 #include <QUuid> 36 36 37 37 /* GUI includes: */ 38 #include "UIDefs.h"39 38 #include "UILibraryDefs.h" 40 39 #include "UIMediumDefs.h" 41 #ifdef VBOX_WS_NIX42 # include "VBoxUtils-nix.h"43 #endif44 45 /* COM includes: */46 #include "CMedium.h"47 #include "CSession.h"48 #include "KGraphicsControllerType.h"49 #include "KLockType.h"50 40 51 41 /* Forward declarations: */ 52 42 class QMenu; 53 class Q SessionManager;54 class QS pinBox;55 class CCloudMachine;56 class CHostVideoInputDevice;43 class QObject; 44 class QString; 45 class QWidget; 46 class UIActionPool; 57 47 class CMachine; 58 class CUSBDevice;59 class UIActionPool;60 class UIMedium;61 class UIThreadPool;62 class UITranslationEventListener;63 48 64 /** QObject subclass containing common GUI functionality. */65 class SHARED_LIBRARY_STUFF UICommon : public QObject 49 /** UIMediumTools namespace. */ 50 namespace UIMediumTools 66 51 { 67 Q_OBJECT; 52 /** Opens external medium from passed @a strMediumLocation. 53 * @param enmMediumType Brings the medium type. 54 * @param strMediumLocation Brings the file path to load medium from. 55 * @param pParent Brings the error dialog parent. */ 56 SHARED_LIBRARY_STUFF QUuid openMedium(UIMediumDeviceType enmMediumType, 57 const QString &strMediumLocation, 58 QWidget *pParent = 0); 68 59 69 signals: 60 /** Opens external medium using file-open dialog. 61 * @param enmMediumType Brings the medium type. 62 * @param pParent Brings the dialog parent. 63 * @param strDefaultFolder Brings the folder to browse for medium. 64 * @param fUseLastFolder Brings whether we should propose to use last used folder. */ 65 SHARED_LIBRARY_STUFF QUuid openMediumWithFileOpenDialog(UIMediumDeviceType enmMediumType, 66 QWidget *pParent = 0, 67 const QString &strDefaultFolder = QString(), 68 bool fUseLastFolder = false); 70 69 71 /** @name Common stuff. 72 * @{ */ 73 /** Asks #UIStarter listener to restart UI. */ 74 void sigAskToRestartUI(); 75 /** Asks #UIStarter listener to close UI. */ 76 void sigAskToCloseUI(); 70 /** Creates and shows a dialog (wizard) to create a medium of type @a enmMediumType. 71 * @param pActionPool Brings the action-pool. 72 * @param pParent Brings the parent of the dialog, 73 * @param enmMediumType Brings the medium type, 74 * @param strMachineFolder Brings the machine folder, 75 * @param strMachineName Brings the name of the machine, 76 * @param strMachineGuestOSTypeId Brings the type ID of machine's guest os, 77 * returns QUuid of the new medium. */ 78 SHARED_LIBRARY_STUFF QUuid openMediumCreatorDialog(UIActionPool *pActionPool, 79 QWidget *pParent, 80 UIMediumDeviceType enmMediumType, 81 const QString &strMachineFolder = QString(), 82 const QString &strMachineName = QString(), 83 const QString &strMachineGuestOSTypeId = QString()); 77 84 78 /** Asks listeners to commit data. */ 79 void sigAskToCommitData(); 80 /** Asks listeners to detach COM. */ 81 void sigAskToDetachCOM(); 82 /** @} */ 85 /** Prepares storage menu according passed parameters. 86 * @param pMenu Brings the #QMenu to be prepared. 87 * @param pListener Brings the listener #QObject, this @a menu being prepared for. 88 * @param pszSlotName Brings the name of the SLOT in the @a pListener above, this menu will be handled with. 89 * @param comMachine Brings the #CMachine object, this @a menu being prepared for. 90 * @param strControllerName Brings the name of the #CStorageController in the @a machine above. 91 * @param storageSlot Brings the #StorageSlot of the storage controller with @a strControllerName above. */ 92 SHARED_LIBRARY_STUFF void prepareStorageMenu(QMenu *pMenu, 93 QObject *pListener, 94 const char *pszSlotName, 95 const CMachine &comMachine, 96 const QString &strControllerName, 97 const StorageSlot &storageSlot); 83 98 84 /** @name Theme stuff. 85 * @{ */ 86 /** Notifies listeners about theme change. */ 87 void sigThemeChange(); 88 /** @} */ 99 /** Updates @a comConstMachine storage with data described by @a target. 100 * @param comConstMachine Brings the machine to update. 101 * @param target Brings the medium target to update machine with. 102 * @param pActionPool Brings the action-pool. */ 103 SHARED_LIBRARY_STUFF void updateMachineStorage(const CMachine &comConstMachine, 104 const UIMediumTarget &target, 105 UIActionPool *pActionPool); 106 } 107 /* Using this namespace globally: */ 108 using namespace UIMediumTools; 89 109 90 /** @name Cloud Virtual Machine stuff. 91 * @{ */ 92 /** Notifies listeners about cloud VM was unregistered. 93 * @param strProviderShortName Brings provider short name. 94 * @param strProfileName Brings profile name. 95 * @param uId Brings cloud VM id. */ 96 void sigCloudMachineUnregistered(const QString &strProviderShortName, 97 const QString &strProfileName, 98 const QUuid &uId); 99 /** Notifies listeners about cloud VM was registered. 100 * @param strProviderShortName Brings provider short name. 101 * @param strProfileName Brings profile name. 102 * @param comMachine Brings cloud VM. */ 103 void sigCloudMachineRegistered(const QString &strProviderShortName, 104 const QString &strProfileName, 105 const CCloudMachine &comMachine); 106 /** @} */ 107 108 /** @name COM: Virtual Media stuff. 109 * @{ */ 110 /** Notifies listeners about medium with certain @a uMediumID created. */ 111 void sigMediumCreated(const QUuid &uMediumID); 112 /** Notifies listeners about medium with certain @a uMediumID deleted. */ 113 void sigMediumDeleted(const QUuid &uMediumID); 114 115 /** Notifies listeners about medium-enumeration started. */ 116 void sigMediumEnumerationStarted(); 117 /** Notifies listeners about medium with certain @a uMediumID enumerated. */ 118 void sigMediumEnumerated(const QUuid &uMediumID); 119 /** Notifies listeners about medium-enumeration finished. */ 120 void sigMediumEnumerationFinished(); 121 /** @} */ 122 123 public: 124 125 /** VM launch running options. */ 126 enum LaunchRunning 127 { 128 LaunchRunning_Default, /**< Default (depends on debug settings). */ 129 LaunchRunning_No, /**< Start the VM paused. */ 130 LaunchRunning_Yes /**< Start the VM running. */ 131 }; 132 133 /** Returns UICommon instance. */ 134 static UICommon *instance() { return s_pInstance; } 135 /** Creates UICommon instance of passed @a enmType. */ 136 static void create(UIType enmType); 137 /** Destroys UICommon instance. */ 138 static void destroy(); 139 140 /** @name General stuff. 141 * @{ */ 142 /** Returns the UI type. */ 143 UIType uiType() const { return m_enmType; } 144 145 /** Returns whether UICommon instance is properly initialized. */ 146 bool isValid() const { return m_fValid; } 147 /** Returns whether UICommon instance cleanup is in progress. */ 148 bool isCleaningUp() const { return m_fCleaningUp; } 149 /** @} */ 150 151 /** @name Host OS stuff. 152 * @{ */ 153 #ifdef VBOX_WS_MAC 154 /** macOS: Returns #MacOSXRelease determined by <i>uname</i> call. */ 155 static MacOSXRelease determineOsRelease(); 156 /** macOS: Returns #MacOSXRelease determined during UICommon prepare routine. */ 157 MacOSXRelease osRelease() const { return m_enmMacOSVersion; } 158 #endif 159 160 #ifdef VBOX_WS_NIX 161 /** X11: Returns the type of the Window Manager we are running under. */ 162 X11WMType typeOfWindowManager() const { return m_enmWindowManagerType; } 163 /** X11: Returns whether the Window Manager we are running under is composition one. */ 164 bool isCompositingManagerRunning() const { return m_fCompositingManagerRunning; } 165 /** Returns true if the detected display server type is either xorg or xwayland. */ 166 bool X11ServerAvailable() const; 167 /** Returns display server type. */ 168 VBGHDISPLAYSERVERTYPE displayServerType() const; 169 #endif 170 /** Returns the name of the host OS by using IHost::getOperatingSystem. */ 171 QString hostOperatingSystem() const; 172 173 #if defined(VBOX_WS_MAC) 174 // Provided by UICocoaApplication .. 175 #elif defined(VBOX_WS_WIN) 176 /** Returns whether Windows host is in Dark mode. */ 177 bool isWindowsInDarkMode() const; 178 #else /* Linux, BSD, Solaris */ 179 /** Returns whether palette is in Dark mode. */ 180 bool isPaletteInDarkMode() const; 181 #endif /* Linux, BSD, Solaris */ 182 183 /** Returns whether host OS is in Dark mode. */ 184 bool isInDarkMode() const { return m_fDarkMode; } 185 186 /** Loads the color theme. */ 187 void loadColorTheme(); 188 /** @} */ 189 190 /** @name Process arguments stuff. 191 * @{ */ 192 /** Process application args. */ 193 bool processArgs(); 194 195 /** Returns whether there are unhandled URL arguments present. */ 196 bool argumentUrlsPresent() const; 197 /** Takes and returns the URL argument list while clearing the source. */ 198 QList<QUrl> takeArgumentUrls(); 199 200 /** Returns the --startvm option value (managed VM id). */ 201 QUuid managedVMUuid() const { return m_uManagedVMId; } 202 /** Returns the --separate option value (whether GUI process is separate from VM process). */ 203 bool isSeparateProcess() const { return m_fSeparateProcess; } 204 /** Returns the --no-startvm-errormsgbox option value (whether startup VM errors are disabled). */ 205 bool showStartVMErrors() const { return m_fShowStartVMErrors; } 206 207 /** Returns the --aggressive-caching / --no-aggressive-caching option value (whether medium-enumeration is required). */ 208 bool agressiveCaching() const { return m_fAgressiveCaching; } 209 210 /** Returns the --restore-current option value (whether we should restore current snapshot before VM started). */ 211 bool shouldRestoreCurrentSnapshot() const { return m_fRestoreCurrentSnapshot; } 212 /** Defines whether we should fRestore current snapshot before VM started. */ 213 void setShouldRestoreCurrentSnapshot(bool fRestore) { m_fRestoreCurrentSnapshot = fRestore; } 214 215 /** Returns the --no-keyboard-grabbing option value (whether we should restore 216 * grab the keyboard or not - for debugging). */ 217 bool shouldNotGrabKeyboard() const { return m_fNoKeyboardGrabbing; } 218 219 /** Returns the --fda option value (whether we have floppy image). */ 220 bool hasFloppyImageToMount() const { return !m_uFloppyImage.isNull(); } 221 /** Returns the --dvd | --cdrom option value (whether we have DVD image). */ 222 bool hasDvdImageToMount() const { return !m_uDvdImage.isNull(); } 223 /** Returns floppy image name. */ 224 QUuid getFloppyImage() const { return m_uFloppyImage; } 225 /** Returns DVD image name. */ 226 QUuid getDvdImage() const { return m_uDvdImage; } 227 228 /** Returns the --execute-all-in-iem option value. */ 229 bool areWeToExecuteAllInIem() const { return m_fExecuteAllInIem; } 230 /** Returns whether --warp-factor option value is equal to 100. */ 231 bool isDefaultWarpPct() const { return m_uWarpPct == 100; } 232 /** Returns the --warp-factor option value. */ 233 uint32_t getWarpPct() const { return m_uWarpPct; } 234 235 #ifdef VBOX_WITH_DEBUGGER_GUI 236 /** Holds whether the debugger should be accessible. */ 237 bool isDebuggerEnabled() const; 238 /** Holds whether to show the debugger automatically with the console. */ 239 bool isDebuggerAutoShowEnabled() const; 240 /** Holds whether to show the command line window when m_fDbgAutoShow is set. */ 241 bool isDebuggerAutoShowCommandLineEnabled() const; 242 /** Holds whether to show the statistics window when m_fDbgAutoShow is set. */ 243 bool isDebuggerAutoShowStatisticsEnabled() const; 244 /** Returns the combined --statistics-expand values. */ 245 QString const getDebuggerStatisticsExpand() const { return m_strDbgStatisticsExpand; } 246 /** Returns the --statistics-filter value. */ 247 QString const getDebuggerStatisticsFilter() const { return m_strDbgStatisticsFilter; } 248 /** Returns the --statistics-config value. */ 249 QString const getDebuggerStatisticsConfig() const { return m_strDbgStatisticsConfig; } 250 251 /** VBoxDbg module handle. */ 252 RTLDRMOD getDebuggerModule() const { return m_hVBoxDbg; } 253 #endif 254 255 /** Returns whether VM should start paused. */ 256 bool shouldStartPaused() const; 257 258 #ifdef VBOX_GUI_WITH_PIDFILE 259 /** Creates PID file. */ 260 void createPidfile(); 261 /** Deletes PID file. */ 262 void deletePidfile(); 263 #endif 264 /** @} */ 265 266 /** @name COM: Virtual Machine stuff. 267 * @{ */ 268 /** Switches to certain @a comMachine. */ 269 static bool switchToMachine(CMachine &comMachine); 270 /** Launches certain @a comMachine in specified @a enmLaunchMode. */ 271 static bool launchMachine(CMachine &comMachine, UILaunchMode enmLaunchMode = UILaunchMode_Default); 272 273 /** Opens session of certain @a enmLockType for VM with certain @a uId. */ 274 CSession openSession(QUuid uId, KLockType enmLockType = KLockType_Write); 275 /** Opens session of certain @a enmLockType for currently chosen VM. */ 276 CSession openSession(KLockType enmLockType = KLockType_Write); 277 /** Opens session of KLockType_Shared type for VM with certain @a uId. */ 278 CSession openExistingSession(const QUuid &uId) { return openSession(uId, KLockType_Shared); } 279 /** Tries to guess if new @a comSession needs to be opened for certain @a comMachine, 280 * if yes, new session of required type will be opened and machine will be updated, 281 * otherwise, no session will be created and machine will be left unchanged. */ 282 CSession tryToOpenSessionFor(CMachine &comMachine); 283 /** @} */ 284 285 /** @name COM: Cloud Virtual Machine stuff. 286 * @{ */ 287 /** Notifies listeners about cloud VM was unregistered. 288 * @param strProviderShortName Brings provider short name. 289 * @param strProfileName Brings profile name. 290 * @param uId Brings cloud VM id. */ 291 void notifyCloudMachineUnregistered(const QString &strProviderShortName, 292 const QString &strProfileName, 293 const QUuid &uId); 294 /** Notifies listeners about cloud VM was registered. 295 * @param strProviderShortName Brings provider short name. 296 * @param strProfileName Brings profile name. 297 * @param comMachine Brings cloud VM. */ 298 void notifyCloudMachineRegistered(const QString &strProviderShortName, 299 const QString &strProfileName, 300 const CCloudMachine &comMachine); 301 /** @} */ 302 303 /** @name COM: Virtual Media stuff. 304 * @{ */ 305 /** Opens external medium by passed @a strMediumLocation. 306 * @param enmMediumType Brings the medium type. 307 * @param pParent Brings the dialog parent. 308 * @param strMediumLocation Brings the file path to load medium from. 309 * @param pParent Brings the dialog parent. */ 310 QUuid openMedium(UIMediumDeviceType enmMediumType, QString strMediumLocation, QWidget *pParent = 0); 311 312 /** Opens external medium using file-open dialog. 313 * @param enmMediumType Brings the medium type. 314 * @param pParent Brings the dialog parent. 315 * @param strDefaultFolder Brings the folder to browse for medium. 316 * @param fUseLastFolder Brings whether we should propose to use last used folder. */ 317 QUuid openMediumWithFileOpenDialog(UIMediumDeviceType enmMediumType, QWidget *pParent = 0, 318 const QString &strDefaultFolder = QString(), bool fUseLastFolder = false); 319 320 /** Creates and shows a dialog (wizard) to create a medium of type @a enmMediumType. 321 * @param pParent Passes the parent of the dialog, 322 * @param enmMediumType Passes the medium type, 323 * @param strMachineName Passes the name of the machine, 324 * @param strMachineFolder Passes the machine folder, 325 * @param strMachineGuestOSTypeId Passes the type ID of machine's guest os, 326 * @param fEnableCreate Passes whether to show/enable create action in the medium selector dialog, 327 * returns QUuid of the new medium */ 328 QUuid openMediumCreatorDialog(UIActionPool *pActionPool, QWidget *pParent, UIMediumDeviceType enmMediumType, 329 const QString &strMachineFolder = QString(), const QString &strMachineName = QString(), 330 const QString &strMachineGuestOSTypeId = QString()); 331 332 /** Prepares storage menu according passed parameters. 333 * @param menu Brings the #QMenu to be prepared. 334 * @param pListener Brings the listener #QObject, this @a menu being prepared for. 335 * @param pszSlotName Brings the name of the SLOT in the @a pListener above, this menu will be handled with. 336 * @param comMachine Brings the #CMachine object, this @a menu being prepared for. 337 * @param strControllerName Brings the name of the #CStorageController in the @a machine above. 338 * @param storageSlot Brings the #StorageSlot of the storage controller with @a strControllerName above. */ 339 void prepareStorageMenu(QMenu *pMenu, 340 QObject *pListener, const char *pszSlotName, 341 const CMachine &comMachine, const QString &strControllerName, const StorageSlot &storageSlot); 342 /** Updates @a comConstMachine storage with data described by @a target. */ 343 void updateMachineStorage(const CMachine &comConstMachine, const UIMediumTarget &target, UIActionPool *pActionPool); 344 345 /** Generates details for passed @a comMedium. 346 * @param fPredictDiff Brings whether medium will be marked differencing on attaching. 347 * @param fUseHtml Brings whether HTML subsets should be used in the generated output. */ 348 QString storageDetails(const CMedium &comMedium, bool fPredictDiff, bool fUseHtml = true); 349 350 /** Calculates @a cAmount of immutable images used by @a comMachine specified. */ 351 static bool acquireAmountOfImmutableImages(const CMachine &comMachine, ulong &cAmount); 352 /** @} */ 353 354 /** @name COM: USB stuff. 355 * @{ */ 356 #ifdef RT_OS_LINUX 357 /** Verifies that USB drivers are properly configured on Linux. */ 358 static void checkForWrongUSBMounted(); 359 #endif 360 361 /** Generates details for passed USB @a comDevice. */ 362 static QString usbDetails(const CUSBDevice &comDevice); 363 /** Generates tool-tip for passed USB @a comDevice. */ 364 static QString usbToolTip(const CUSBDevice &comDevice); 365 /** Generates tool-tip for passed USB @a comFilter. */ 366 static QString usbToolTip(const CUSBDeviceFilter &comFilter); 367 /** Generates tool-tip for passed USB @a comWebcam. */ 368 static QString usbToolTip(const CHostVideoInputDevice &comWebcam); 369 /** @} */ 370 371 /** @name COM: Recording stuff. 372 * @{ */ 373 /** Returns supported recording features flag. */ 374 int supportedRecordingFeatures() const; 375 /** @} */ 376 377 /** @name File-system stuff. 378 * @{ */ 379 /** Returns full help file name. */ 380 static QString helpFile(); 381 382 /** Returns documents path. */ 383 static QString documentsPath(); 384 385 /** Returns whether passed @a strFileName ends with one of allowed extension in the @a extensions list. */ 386 static bool hasAllowedExtension(const QString &strFileName, const QStringList &extensions); 387 388 /** Returns a file name (unique up to extension) wrt. @a strFullFolderPath folder content. Starts 389 * searching strBaseFileName and adds suffixes until a unique file name is found. */ 390 static QString findUniqueFileName(const QString &strFullFolderPath, const QString &strBaseFileName); 391 /** @} */ 392 393 /** @name Widget stuff. 394 * @{ */ 395 /** Assigns minimum @a pSpinBox to correspond to @a cCount digits. */ 396 static void setMinimumWidthAccordingSymbolCount(QSpinBox *pSpinBox, int cCount); 397 /** @} */ 398 399 /** @name Display stuff. 400 * @{ */ 401 #ifdef VBOX_WITH_3D_ACCELERATION 402 /** Returns whether guest OS type with passed @a strGuestOSTypeId is WDDM compatible. */ 403 static bool isWddmCompatibleOsType(const QString &strGuestOSTypeId); 404 #endif 405 /** Returns the required video memory in bytes for the current desktop 406 * resolution at maximum possible screen depth in bpp. */ 407 static quint64 requiredVideoMemory(const QString &strGuestOSTypeId, int cMonitors = 1); 408 KGraphicsControllerType getRecommendedGraphicsController(const QString &strGuestOSTypeId) const; 409 /** @} */ 410 411 /** @name Thread stuff. 412 * @{ */ 413 /** Returns the thread-pool instance. */ 414 UIThreadPool *threadPool() const { return m_pThreadPool; } 415 /** Returns the thread-pool instance for cloud needs. */ 416 UIThreadPool *threadPoolCloud() const { return m_pThreadPoolCloud; } 417 /** @} */ 418 419 /** @name Context sensitive help related functionality 420 * @{ */ 421 /** Sets the property for help keyword on a QObject 422 * @param pObject The object to set the help keyword property on 423 * @param strKeyword The values of the key word property. */ 424 static void setHelpKeyword(QObject *pObject, const QString &strHelpKeyword); 425 /** Returns the property for help keyword of a QObject. If no such property exists returns an empty QString. 426 * @param pWidget The object to get the help keyword property from. */ 427 static QString helpKeyword(const QObject *pWidget); 428 /** @} */ 429 430 public slots: 431 432 /** @name Process arguments stuff. 433 * @{ */ 434 /** Opens the specified URL using OS/Desktop capabilities. */ 435 bool openURL(const QString &strURL) const; 436 /** @} */ 437 438 /** @name Localization stuff. 439 * @{ */ 440 /** Handles language change to new @a strLanguage. */ 441 void sltGUILanguageChange(QString strLanguage); 442 /** @} */ 443 444 /** @name Media related stuff. 445 * @{ */ 446 /** Handles signal about medium was created. */ 447 void sltHandleMediumCreated(const CMedium &comMedium); 448 /** @} */ 449 450 /** @name Machine related stuff. 451 * @{ */ 452 /** Handles signal about machine was created. */ 453 void sltHandleMachineCreated(const CMachine &comMachine); 454 /** @} */ 455 456 /** @name Cloud Machine related stuff. 457 * @{ */ 458 /** Handles signal about cloud machine was added. */ 459 void sltHandleCloudMachineAdded(const QString &strProviderShortName, 460 const QString &strProfileName, 461 const CCloudMachine &comMachine); 462 /** @} */ 463 464 protected: 465 466 /** Preprocesses any Qt @a pEvent for passed @a pObject. */ 467 virtual bool eventFilter(QObject *pObject, QEvent *pEvent) RT_OVERRIDE; 468 469 /** Handles translation event. */ 470 virtual void retranslateUi(); 471 472 protected slots: 473 474 /** Calls for cleanup() functionality. */ 475 void sltCleanup() { cleanup(); } 476 477 #ifndef VBOX_GUI_WITH_CUSTOMIZATIONS1 478 /** @name Common stuff. 479 * @{ */ 480 /** Handles @a manager request for emergency session shutdown. */ 481 void sltHandleCommitDataRequest(QSessionManager &manager); 482 /** @} */ 483 #endif /* VBOX_GUI_WITH_CUSTOMIZATIONS1 */ 484 485 /** @name COM stuff. 486 * @{ */ 487 /** Handles the VBoxSVC availability change. */ 488 void sltHandleVBoxSVCAvailabilityChange(bool fAvailable); 489 /** @} */ 490 491 /* Handle font scale factor change. */ 492 void sltHandleFontScaleFactorChanged(int iFontScaleFactor); 493 494 private: 495 496 /** Construcs global VirtualBox object of passed @a enmType. */ 497 UICommon(UIType enmType); 498 /** Destrucs global VirtualBox object. */ 499 virtual ~UICommon() RT_OVERRIDE RT_FINAL; 500 501 /** Prepares all. */ 502 void prepare(); 503 /** Cleanups all. */ 504 void cleanup(); 505 506 /** @name Process arguments stuff. 507 * @{ */ 508 #ifdef VBOX_WITH_DEBUGGER_GUI 509 /** Initializes a debugger config variable. 510 * @param piDbgCfgVar Brings the debugger config variable to init. 511 * @param pszEnvVar Brings the environment variable name relating to this variable. 512 * @param pszExtraDataName Brings the extra data name relating to this variable. 513 * @param fDefault Brings the default value. */ 514 void initDebuggerVar(int *piDbgCfgVar, const char *pszEnvVar, const char *pszExtraDataName, bool fDefault = false); 515 /** Set a debugger config variable according according to start up argument. 516 * @param piDbgCfgVar Brings the debugger config variable to set. 517 * @param fState Brings the value from the command line. */ 518 void setDebuggerVar(int *piDbgCfgVar, bool fState); 519 /** Checks the state of a debugger config variable, updating it with the machine settings on the first invocation. 520 * @param piDbgCfgVar Brings the debugger config variable to consult. 521 * @param pszExtraDataName Brings the extra data name relating to this variable. */ 522 bool isDebuggerWorker(int *piDbgCfgVar, const char *pszExtraDataName) const; 523 #endif 524 /** @} */ 525 526 /** Holds the singleton UICommon instance. */ 527 static UICommon *s_pInstance; 528 529 /** @name General stuff. 530 * @{ */ 531 /** Holds the UI type. */ 532 UIType m_enmType; 533 534 /** Holds whether UICommon instance is properly initialized. */ 535 bool m_fValid; 536 /** Holds whether UICommon instance cleanup is in progress. */ 537 bool m_fCleaningUp; 538 #ifdef VBOX_WS_WIN 539 /** Holds whether overall GUI data is committed. */ 540 bool m_fDataCommitted; 541 #endif 542 /** @} */ 543 544 /** @name Host OS stuff. 545 * @{ */ 546 #ifdef VBOX_WS_MAC 547 /** macOS: Holds the #MacOSXRelease determined using <i>uname</i> call. */ 548 MacOSXRelease m_enmMacOSVersion; 549 #endif 550 551 #ifdef VBOX_WS_NIX 552 /** X11: Holds the #X11WMType of the Window Manager we are running under. */ 553 X11WMType m_enmWindowManagerType; 554 /** X11: Holds whether the Window Manager we are running at is composition one. */ 555 bool m_fCompositingManagerRunning; 556 /** Unixes: Holds the display server type. */ 557 VBGHDISPLAYSERVERTYPE m_enmDisplayServerType; 558 #endif 559 560 /** Holds whether host OS is in Dark mode. */ 561 bool m_fDarkMode; 562 /** @} */ 563 564 /** @name Process arguments stuff. 565 * @{ */ 566 /** Holds the URL arguments list. */ 567 QList<QUrl> m_listArgUrls; 568 569 /** Holds the --startvm option value (managed VM id). */ 570 QUuid m_uManagedVMId; 571 /** Holds the --separate option value (whether GUI process is separate from VM process). */ 572 bool m_fSeparateProcess; 573 /** Holds the --no-startvm-errormsgbox option value (whether startup VM errors are disabled). */ 574 bool m_fShowStartVMErrors; 575 576 /** Holds the --aggressive-caching / --no-aggressive-caching option value (whether medium-enumeration is required). */ 577 bool m_fAgressiveCaching; 578 579 /** Holds the --restore-current option value. */ 580 bool m_fRestoreCurrentSnapshot; 581 582 /** Holds the --no-keyboard-grabbing option value. */ 583 bool m_fNoKeyboardGrabbing; 584 585 /** Holds the --fda option value (floppy image). */ 586 QUuid m_uFloppyImage; 587 /** Holds the --dvd | --cdrom option value (DVD image). */ 588 QUuid m_uDvdImage; 589 590 /** Holds the --execute-all-in-iem option value. */ 591 bool m_fExecuteAllInIem; 592 /** Holds the --warp-factor option value. */ 593 uint32_t m_uWarpPct; 594 595 #ifdef VBOX_WITH_DEBUGGER_GUI 596 /** Holds whether the debugger should be accessible. */ 597 mutable int m_fDbgEnabled; 598 /** Holds whether to show the debugger automatically with the console. */ 599 mutable int m_fDbgAutoShow; 600 /** Holds whether to show the command line window when m_fDbgAutoShow is set. */ 601 mutable int m_fDbgAutoShowCommandLine; 602 /** Holds whether to show the statistics window when m_fDbgAutoShow is set. */ 603 mutable int m_fDbgAutoShowStatistics; 604 /** Pattern of statistics to expand when opening the viewer. */ 605 QString m_strDbgStatisticsExpand; 606 /** The statistics viewer main filter pattern. */ 607 QString m_strDbgStatisticsFilter; 608 /** The statistics viewer advanced filter configuration and possibly more. */ 609 QString m_strDbgStatisticsConfig; 610 611 /** VBoxDbg module handle. */ 612 RTLDRMOD m_hVBoxDbg; 613 614 /** Holds whether --start-running, --start-paused or nothing was given. */ 615 LaunchRunning m_enmLaunchRunning; 616 #endif 617 618 /** Holds the --settingspw option value or the content of --settingspwfile. */ 619 char m_astrSettingsPw[256]; 620 /** Holds the --settingspwfile option value. */ 621 bool m_fSettingsPwSet; 622 623 #ifdef VBOX_GUI_WITH_PIDFILE 624 /** Holds the --pidfile option value (application PID file path). */ 625 QString m_strPidFile; 626 #endif 627 /** @} */ 628 629 /** @name Thread stuff. 630 * @{ */ 631 /** Holds the thread-pool instance. */ 632 UIThreadPool *m_pThreadPool; 633 /** Holds the thread-pool instance for cloud needs. */ 634 UIThreadPool *m_pThreadPoolCloud; 635 /** @} */ 636 637 /** @name Font scaling related variables. 638 * @{ */ 639 int iOriginalFontPixelSize; 640 int iOriginalFontPointSize; 641 /** @} */ 642 643 UITranslationEventListener *m_pTranlationEventListener; 644 /** Allows for shortcut access. */ 645 friend UICommon &uiCommon(); 646 }; 647 648 /** Singleton UICommon 'official' name. */ 649 inline UICommon &uiCommon() { return *UICommon::instance(); } 650 651 #endif /* !FEQT_INCLUDED_SRC_globals_UICommon_h */ 110 #endif /* !FEQT_INCLUDED_SRC_medium_UIMediumTools_h */ -
trunk/src/VBox/Frontends/VirtualBox/src/medium/viso/UIVisoCreator.cpp
r104899 r104901 50 50 #include "UILoggingDefs.h" 51 51 #include "UIMediumEnumerator.h" 52 #include "UIMediumTools.h" 52 53 #include "UIMessageCenter.h" 53 54 #include "UIModalWindowManager.h" … … 962 963 QString strFilePath = pVisoCreator->visoFileFullPath(); 963 964 gEDataManager->setVISOCreatorRecentFolder(pVisoCreator->currentPath()); 964 mediumId = uiCommon().openMedium(UIMediumDeviceType_DVD, strFilePath);965 mediumId = UIMediumTools::openMedium(UIMediumDeviceType_DVD, strFilePath); 965 966 } 966 967 } -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp
r104461 r104901 68 68 #include "UIMachineWindow.h" 69 69 #include "UIMedium.h" 70 #include "UIMediumTools.h" 70 71 #include "UIMessageCenter.h" 71 72 #include "UIModalWindowManager.h" … … 3027 3028 QFileInfo bootMediumFileInfo(strISOPath); 3028 3029 if (bootMediumFileInfo.exists() && bootMediumFileInfo.isReadable()) 3029 uimachine()->mountBootMedium( uiCommon().openMedium(UIMediumDeviceType_DVD, strISOPath));3030 uimachine()->mountBootMedium(UIMediumTools::openMedium(UIMediumDeviceType_DVD, strISOPath)); 3030 3031 3031 3032 if (iResult == static_cast<int>(UIBootFailureDialog::ReturnCode_Reset)) -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp
r104891 r104901 50 50 #include "UIMediumEnumerator.h" 51 51 #include "UIMessageCenter.h" 52 #include "UIMediumTools.h" 52 53 #include "UIModalWindowManager.h" 53 54 #include "UIMousePointerShapeData.h" … … 1020 1021 { 1021 1022 CMachine comMachine = machine(); 1022 uiCommon().prepareStorageMenu(pMenu,1023 pListener, pszSlotName,1024 comMachine, strControllerName, storageSlot);1023 UIMediumTools::prepareStorageMenu(pMenu, 1024 pListener, pszSlotName, 1025 comMachine, strControllerName, storageSlot); 1025 1026 } 1026 1027 … … 1028 1029 { 1029 1030 CMachine comMachine = machine(); 1030 uiCommon().updateMachineStorage(comMachine, target, pActionPool);1031 UIMediumTools::updateMachineStorage(comMachine, target, pActionPool); 1031 1032 } 1032 1033 -
trunk/src/VBox/Frontends/VirtualBox/src/settings/editors/UIStorageSettingsEditor.cpp
r104891 r104901 63 63 #include "UIMediumEnumerator.h" 64 64 #include "UIMediumSelector.h" 65 #include "UIMediumTools.h" 65 66 #include "UIMessageCenter.h" 66 67 #include "UIStorageSettingsEditor.h" … … 3928 3929 const QString strMachineFolder(QFileInfo(m_strMachineSettingsFilePath).absolutePath()); 3929 3930 3930 QUuid uMediumId = uiCommon().openMediumWithFileOpenDialog(m_pMediumIdHolder->type(), QApplication::activeWindow(), strMachineFolder); 3931 QUuid uMediumId = UIMediumTools::openMediumWithFileOpenDialog(m_pMediumIdHolder->type(), 3932 QApplication::activeWindow(), 3933 strMachineFolder); 3931 3934 if (uMediumId.isNull()) 3932 3935 return; … … 3954 3957 const UIMediumDeviceType enmMediumType = (UIMediumDeviceType)mediumInfoList[0].toUInt(); 3955 3958 const QString strMediumLocation = mediumInfoList[1]; 3956 const QUuid uMediumId = uiCommon().openMedium(enmMediumType, strMediumLocation, this);3959 const QUuid uMediumId = UIMediumTools::openMedium(enmMediumType, strMediumLocation, this); 3957 3960 if (!uMediumId.isNull()) 3958 3961 m_pMediumIdHolder->setId(uMediumId);
Note:
See TracChangeset
for help on using the changeset viewer.