Changeset 72413 in vbox for trunk/src/VBox/Frontends/VirtualBox
- Timestamp:
- Jun 1, 2018 5:15:08 PM (7 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox/src/globals
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp
r72389 r72413 171 171 #endif /* VBOX_WS_X11 */ 172 172 173 174 173 //#define VBOX_WITH_FULL_DETAILS_REPORT /* hidden for now */ 175 174 … … 178 177 179 178 180 // VBoxGlobal 181 //////////////////////////////////////////////////////////////////////////////// 179 class VBoxTranslator : public QTranslator 180 { 181 public: 182 183 VBoxTranslator (QObject *aParent = 0) 184 : QTranslator (aParent) {} 185 186 bool loadFile (const QString &aFileName) 187 { 188 QFile file (aFileName); 189 if (!file.open (QIODevice::ReadOnly)) 190 return false; 191 mData = file.readAll(); 192 return load ((uchar*) mData.data(), mData.size()); 193 } 194 195 private: 196 197 QByteArray mData; 198 }; 199 200 static VBoxTranslator *sTranslator = 0; 201 202 203 struct PortConfig 204 { 205 const char *name; 206 const ulong IRQ; 207 const ulong IOBase; 208 }; 209 210 static const PortConfig kComKnownPorts[] = 211 { 212 { "COM1", 4, 0x3F8 }, 213 { "COM2", 3, 0x2F8 }, 214 { "COM3", 4, 0x3E8 }, 215 { "COM4", 3, 0x2E8 }, 216 /* must not contain an element with IRQ=0 and IOBase=0 used to cause 217 * toCOMPortName() to return the "User-defined" string for these values. */ 218 }; 219 220 static const PortConfig kLptKnownPorts[] = 221 { 222 { "LPT1", 7, 0x378 }, 223 { "LPT2", 5, 0x278 }, 224 { "LPT1", 2, 0x3BC }, 225 /* must not contain an element with IRQ=0 and IOBase=0 used to cause 226 * toLPTPortName() to return the "User-defined" string for these values. */ 227 }; 182 228 183 229 … … 242 288 #ifdef VBOX_WS_MAC 243 289 , m_osRelease(MacOSXRelease_Old) 244 #endif /* VBOX_WS_MAC */ 245 , m_fWrappersValid(false) 246 , m_fVBoxSVCAvailable(true) 247 , m_fSeparateProcess(false) 248 , m_pMediumEnumerator(0) 249 , m_fEPInstallationRequested(false) 290 #endif 250 291 #ifdef VBOX_WS_X11 251 292 , m_fCompositingManagerRunning(false) 252 293 , m_enmWindowManagerType(X11WMType_Unknown) 253 #endif /* VBOX_WS_X11 */ 294 #endif 295 , mVerString("1.0") 296 , m_fSeparateProcess(false) 297 , mShowStartVMErrors(true) 254 298 #if defined(DEBUG_bird) 255 299 , mAgressiveCaching(false) … … 264 308 , mExecuteAllInIem(false) 265 309 , mWarpPct(100) 266 , mVerString("1.0") 310 , mSettingsPwSet(false) 311 , m_fWrappersValid(false) 312 , m_fVBoxSVCAvailable(true) 267 313 , m3DAvailable(-1) 268 , m SettingsPwSet(false)314 , m_pThreadPool(0) 269 315 , m_pIconPool(0) 270 , m_pThreadPool(0) 316 , m_pMediumEnumerator(0) 317 , m_fEPInstallationRequested(false) 271 318 { 272 319 /* Assign instance: */ … … 353 400 #endif /* VBOX_WS_MAC */ 354 401 355 /** 356 * Inner worker that for lazily querying for 3D support. 357 * 358 * Rational is that when starting a text mode guest (like DOS) that does not 359 * have 3D enabled, don't wast the developer's or user's time on launching the 360 * test application when starting the VM or editing it's settings. 361 * 362 * @returns true / false. 363 * @note If we ever end up checking this concurrently on multiple threads, use a 364 * RTONCE construct to serialize the efforts. 365 */ 366 bool VBoxGlobal::is3DAvailableWorker() const 367 { 368 #ifdef VBOX_WITH_CROGL 369 bool fSupported = VBoxOglIs3DAccelerationSupported(); 370 #else 371 bool fSupported = false; 372 #endif 373 unconst(this)->m3DAvailable = fSupported; 374 return fSupported; 375 } 376 402 bool VBoxGlobal::brandingIsActive (bool aForce /* = false*/) 403 { 404 if (aForce) 405 return true; 406 407 if (mBrandingConfig.isEmpty()) 408 { 409 mBrandingConfig = QDir(QApplication::applicationDirPath()).absolutePath(); 410 mBrandingConfig += "/custom/custom.ini"; 411 } 412 return QFile::exists (mBrandingConfig); 413 } 414 415 /** 416 * Gets a value from the custom .ini file 417 */ 418 QString VBoxGlobal::brandingGetKey (QString aKey) 419 { 420 QSettings s(mBrandingConfig, QSettings::IniFormat); 421 return s.value(QString("%1").arg(aKey)).toString(); 422 } 423 424 bool VBoxGlobal::processArgs() 425 { 426 bool fResult = false; 427 QStringList args = qApp->arguments(); 428 QList<QUrl> list; 429 for (int i = 1; i < args.size(); ++i) 430 { 431 /* We break out after the first parameter, cause there could be 432 parameters with arguments (e.g. --comment comment). */ 433 if (args.at(i).startsWith("-")) 434 break; 435 #ifdef VBOX_WS_MAC 436 QString strArg = ::darwinResolveAlias(args.at(i)); 437 #else /* VBOX_WS_MAC */ 438 QString strArg = args.at(i); 439 #endif /* !VBOX_WS_MAC */ 440 if ( !strArg.isEmpty() 441 && QFile::exists(strArg)) 442 list << QUrl::fromLocalFile(strArg); 443 } 444 if (!list.isEmpty()) 445 { 446 for (int i = 0; i < list.size(); ++i) 447 { 448 const QString& strFile = list.at(i).toLocalFile(); 449 if (VBoxGlobal::hasAllowedExtension(strFile, VBoxFileExts)) 450 { 451 CVirtualBox vbox = virtualBox(); 452 CMachine machine = vbox.FindMachine(strFile); 453 if (!machine.isNull()) 454 { 455 fResult = true; 456 launchMachine(machine); 457 /* Remove from the arg list. */ 458 list.removeAll(strFile); 459 } 460 } 461 } 462 } 463 if (!list.isEmpty()) 464 { 465 /* Store the URLs: */ 466 m_ArgUrlList = list; 467 /* Ask UIStarter to open them: */ 468 emit sigAskToOpenURLs(); 469 } 470 return fResult; 471 } 472 473 #ifdef VBOX_WITH_DEBUGGER_GUI 474 475 bool VBoxGlobal::isDebuggerEnabled() const 476 { 477 return isDebuggerWorker(&m_fDbgEnabled, GUI_Dbg_Enabled); 478 } 479 480 bool VBoxGlobal::isDebuggerAutoShowEnabled() const 481 { 482 return isDebuggerWorker(&m_fDbgAutoShow, GUI_Dbg_AutoShow); 483 } 484 485 bool VBoxGlobal::isDebuggerAutoShowCommandLineEnabled() const 486 { 487 return isDebuggerWorker(&m_fDbgAutoShowCommandLine, GUI_Dbg_AutoShow); 488 } 489 490 bool VBoxGlobal::isDebuggerAutoShowStatisticsEnabled() const 491 { 492 return isDebuggerWorker(&m_fDbgAutoShowStatistics, GUI_Dbg_AutoShow); 493 } 494 495 #endif /* VBOX_WITH_DEBUGGER_GUI */ 377 496 378 497 #ifdef VBOX_GUI_WITH_PIDFILE 498 379 499 void VBoxGlobal::createPidfile() 380 500 { … … 399 519 QFile::remove(m_strPidfile); 400 520 } 401 #endif 402 403 bool VBoxGlobal::brandingIsActive (bool aForce /* = false*/) 404 { 405 if (aForce) 406 return true; 407 408 if (mBrandingConfig.isEmpty()) 409 { 410 mBrandingConfig = QDir(QApplication::applicationDirPath()).absolutePath(); 411 mBrandingConfig += "/custom/custom.ini"; 412 } 413 return QFile::exists (mBrandingConfig); 414 } 415 416 /** 417 * Gets a value from the custom .ini file 418 */ 419 QString VBoxGlobal::brandingGetKey (QString aKey) 420 { 421 QSettings s(mBrandingConfig, QSettings::IniFormat); 422 return s.value(QString("%1").arg(aKey)).toString(); 423 } 424 425 #ifdef VBOX_WS_X11 426 QList<QRect> XGetDesktopList() 427 { 428 /* Prepare empty resulting list: */ 429 QList<QRect> result; 430 431 /* Get current display: */ 432 Display* pDisplay = QX11Info::display(); 433 434 /* If it's a Xinerama desktop: */ 435 if (XineramaIsActive(pDisplay)) 436 { 437 /* Reading Xinerama data: */ 438 int iScreens = 0; 439 XineramaScreenInfo *pScreensData = XineramaQueryScreens(pDisplay, &iScreens); 440 441 /* Fill resulting list: */ 442 for (int i = 0; i < iScreens; ++ i) 443 result << QRect(pScreensData[i].x_org, pScreensData[i].y_org, 444 pScreensData[i].width, pScreensData[i].height); 445 446 /* Free screens data: */ 447 XFree(pScreensData); 448 } 449 450 /* Return resulting list: */ 451 return result; 452 } 453 454 QList<Window> XGetWindowIDList() 455 { 456 /* Get current display: */ 457 Display *pDisplay = QX11Info::display(); 458 459 /* Get virtual desktop window: */ 460 Window window = QX11Info::appRootWindow(); 461 462 /* Get 'client list' atom: */ 463 Atom propNameAtom = XInternAtom(pDisplay, "_NET_CLIENT_LIST", True /* only if exists */); 464 465 /* Prepare empty resulting list: */ 466 QList<Window> result; 467 468 /* If atom does not exists return empty list: */ 469 if (propNameAtom == None) 470 return result; 471 472 /* Get atom value: */ 473 Atom realAtomType = None; 474 int iRealFormat = 0; 475 unsigned long uItemsCount = 0; 476 unsigned long uBytesAfter = 0; 477 unsigned char *pData = 0; 478 int rc = XGetWindowProperty(pDisplay, window, propNameAtom, 479 0, 0x7fffffff /*LONG_MAX*/, False /* delete */, 480 XA_WINDOW, &realAtomType, &iRealFormat, 481 &uItemsCount, &uBytesAfter, &pData); 482 483 /* If get property is failed return empty list: */ 484 if (rc != Success) 485 return result; 486 487 /* Fill resulting list with win ids: */ 488 Window *pWindowData = reinterpret_cast<Window*>(pData); 489 for (ulong i = 0; i < uItemsCount; ++ i) 490 result << pWindowData[i]; 491 492 /* Releasing resources: */ 493 XFree(pData); 494 495 /* Return resulting list: */ 496 return result; 497 } 498 499 QList<ulong> XGetStrut(Window window) 500 { 501 /* Get current display: */ 502 Display *pDisplay = QX11Info::display(); 503 504 /* Get 'strut' atom: */ 505 Atom propNameAtom = XInternAtom(pDisplay, "_NET_WM_STRUT_PARTIAL", True /* only if exists */); 506 507 /* Prepare empty resulting list: */ 508 QList<ulong> result; 509 510 /* If atom does not exists return empty list: */ 511 if (propNameAtom == None) 512 return result; 513 514 /* Get atom value: */ 515 Atom realAtomType = None; 516 int iRealFormat = 0; 517 ulong uItemsCount = 0; 518 ulong uBytesAfter = 0; 519 unsigned char *pData = 0; 520 int rc = XGetWindowProperty(pDisplay, window, propNameAtom, 521 0, LONG_MAX, False /* delete */, 522 XA_CARDINAL, &realAtomType, &iRealFormat, 523 &uItemsCount, &uBytesAfter, &pData); 524 525 /* If get property is failed return empty list: */ 526 if (rc != Success) 527 return result; 528 529 /* Fill resulting list with strut shifts: */ 530 ulong *pStrutsData = reinterpret_cast<ulong*>(pData); 531 for (ulong i = 0; i < uItemsCount; ++ i) 532 result << pStrutsData[i]; 533 534 /* Releasing resources: */ 535 XFree(pData); 536 537 /* Return resulting list: */ 538 return result; 539 } 540 #endif /* ifdef VBOX_WS_X11 */ 541 542 /** 543 * Returns the list of few guest OS types, queried from 544 * IVirtualBox corresponding to every family id. 545 */ 546 QList<CGuestOSType> VBoxGlobal::vmGuestOSFamilyList() const 547 { 548 QList<CGuestOSType> result; 549 for (int i = 0; i < m_guestOSFamilyIDs.size(); ++i) 550 result << m_guestOSTypes[i][0]; 551 return result; 552 } 553 554 /** 555 * Returns the list of all guest OS types, queried from 556 * IVirtualBox corresponding to passed family id. 557 */ 558 QList<CGuestOSType> VBoxGlobal::vmGuestOSTypeList(const QString &aFamilyId) const 559 { 560 AssertMsg(m_guestOSFamilyIDs.contains(aFamilyId), ("Family ID incorrect: '%s'.", aFamilyId.toLatin1().constData())); 561 return m_guestOSFamilyIDs.contains(aFamilyId) ? 562 m_guestOSTypes[m_guestOSFamilyIDs.indexOf(aFamilyId)] : QList<CGuestOSType>(); 563 } 564 565 QIcon VBoxGlobal::vmUserIcon(const CMachine &comMachine) const 566 { 567 /* Prepare fallback icon: */ 568 static QIcon nullIcon; 569 570 /* Make sure general icon-pool initialized: */ 571 AssertReturn(m_pIconPool, nullIcon); 572 573 /* Redirect to general icon-pool: */ 574 return m_pIconPool->userMachineIcon(comMachine); 575 } 576 577 QPixmap VBoxGlobal::vmUserPixmap(const CMachine &comMachine, const QSize &size) const 578 { 579 /* Prepare fallback pixmap: */ 580 static QPixmap nullPixmap; 581 582 /* Make sure general icon-pool initialized: */ 583 AssertReturn(m_pIconPool, nullPixmap); 584 585 /* Redirect to general icon-pool: */ 586 return m_pIconPool->userMachinePixmap(comMachine, size); 587 } 588 589 QPixmap VBoxGlobal::vmUserPixmapDefault(const CMachine &comMachine, QSize *pLogicalSize /* = 0 */) const 590 { 591 /* Prepare fallback pixmap: */ 592 static QPixmap nullPixmap; 593 594 /* Make sure general icon-pool initialized: */ 595 AssertReturn(m_pIconPool, nullPixmap); 596 597 /* Redirect to general icon-pool: */ 598 return m_pIconPool->userMachinePixmapDefault(comMachine, pLogicalSize); 599 } 600 601 QIcon VBoxGlobal::vmGuestOSTypeIcon(const QString &strOSTypeID) const 602 { 603 /* Prepare fallback icon: */ 604 static QIcon nullIcon; 605 606 /* Make sure general icon-pool initialized: */ 607 AssertReturn(m_pIconPool, nullIcon); 608 609 /* Redirect to general icon-pool: */ 610 return m_pIconPool->guestOSTypeIcon(strOSTypeID); 611 } 612 613 QPixmap VBoxGlobal::vmGuestOSTypePixmap(const QString &strOSTypeID, const QSize &size) const 614 { 615 /* Prepare fallback pixmap: */ 616 static QPixmap nullPixmap; 617 618 /* Make sure general icon-pool initialized: */ 619 AssertReturn(m_pIconPool, nullPixmap); 620 621 /* Redirect to general icon-pool: */ 622 return m_pIconPool->guestOSTypePixmap(strOSTypeID, size); 623 } 624 625 QPixmap VBoxGlobal::vmGuestOSTypePixmapDefault(const QString &strOSTypeID, QSize *pLogicalSize /* = 0 */) const 626 { 627 /* Prepare fallback pixmap: */ 628 static QPixmap nullPixmap; 629 630 /* Make sure general icon-pool initialized: */ 631 AssertReturn(m_pIconPool, nullPixmap); 632 633 /* Redirect to general icon-pool: */ 634 return m_pIconPool->guestOSTypePixmapDefault(strOSTypeID, pLogicalSize); 635 } 636 637 /** 638 * Returns the guest OS type object corresponding to the given type id of list 639 * containing OS types related to OS family determined by family id attribute. 640 * If the index is invalid a null object is returned. 641 */ 642 CGuestOSType VBoxGlobal::vmGuestOSType(const QString &aTypeId, 643 const QString &aFamilyId /* = QString::null */) const 644 { 645 QList <CGuestOSType> list; 646 if (m_guestOSFamilyIDs.contains (aFamilyId)) 647 { 648 list = m_guestOSTypes [m_guestOSFamilyIDs.indexOf (aFamilyId)]; 649 } 650 else 651 { 652 for (int i = 0; i < m_guestOSFamilyIDs.size(); ++ i) 653 list += m_guestOSTypes [i]; 654 } 655 for (int j = 0; j < list.size(); ++ j) 656 if (!list [j].GetId().compare (aTypeId)) 657 return list [j]; 658 AssertMsgFailed (("Type ID incorrect: '%s'.", aTypeId.toLatin1().constData())); 659 return CGuestOSType(); 660 } 661 662 /** 663 * Returns the description corresponding to the given guest OS type id. 664 */ 665 QString VBoxGlobal::vmGuestOSTypeDescription (const QString &aTypeId) const 666 { 667 for (int i = 0; i < m_guestOSFamilyIDs.size(); ++ i) 668 { 669 QList <CGuestOSType> list (m_guestOSTypes [i]); 670 for ( int j = 0; j < list.size(); ++ j) 671 if (!list [j].GetId().compare (aTypeId)) 672 return list [j].GetDescription(); 673 } 674 return QString::null; 675 } 676 677 struct PortConfig 678 { 679 const char *name; 680 const ulong IRQ; 681 const ulong IOBase; 682 }; 683 684 static const PortConfig kComKnownPorts[] = 685 { 686 { "COM1", 4, 0x3F8 }, 687 { "COM2", 3, 0x2F8 }, 688 { "COM3", 4, 0x3E8 }, 689 { "COM4", 3, 0x2E8 }, 690 /* must not contain an element with IRQ=0 and IOBase=0 used to cause 691 * toCOMPortName() to return the "User-defined" string for these values. */ 692 }; 693 694 static const PortConfig kLptKnownPorts[] = 695 { 696 { "LPT1", 7, 0x378 }, 697 { "LPT2", 5, 0x278 }, 698 { "LPT1", 2, 0x3BC }, 699 /* must not contain an element with IRQ=0 and IOBase=0 used to cause 700 * toLPTPortName() to return the "User-defined" string for these values. */ 701 }; 702 703 /** 704 * Returns the list of the standard COM port names (i.e. "COMx"). 705 */ 706 QStringList VBoxGlobal::COMPortNames() const 707 { 708 QStringList list; 709 for (size_t i = 0; i < RT_ELEMENTS (kComKnownPorts); ++ i) 710 list << kComKnownPorts [i].name; 711 712 return list; 713 } 714 715 /** 716 * Returns the list of the standard LPT port names (i.e. "LPTx"). 717 */ 718 QStringList VBoxGlobal::LPTPortNames() const 719 { 720 QStringList list; 721 for (size_t i = 0; i < RT_ELEMENTS (kLptKnownPorts); ++ i) 722 list << kLptKnownPorts [i].name; 723 724 return list; 725 } 726 727 /** 728 * Returns the name of the standard COM port corresponding to the given 729 * parameters, or "User-defined" (which is also returned when both 730 * @a aIRQ and @a aIOBase are 0). 731 */ 732 QString VBoxGlobal::toCOMPortName (ulong aIRQ, ulong aIOBase) const 733 { 734 for (size_t i = 0; i < RT_ELEMENTS (kComKnownPorts); ++ i) 735 if (kComKnownPorts [i].IRQ == aIRQ && 736 kComKnownPorts [i].IOBase == aIOBase) 737 return kComKnownPorts [i].name; 738 739 return mUserDefinedPortName; 740 } 741 742 /** 743 * Returns the name of the standard LPT port corresponding to the given 744 * parameters, or "User-defined" (which is also returned when both 745 * @a aIRQ and @a aIOBase are 0). 746 */ 747 QString VBoxGlobal::toLPTPortName (ulong aIRQ, ulong aIOBase) const 748 { 749 for (size_t i = 0; i < RT_ELEMENTS (kLptKnownPorts); ++ i) 750 if (kLptKnownPorts [i].IRQ == aIRQ && 751 kLptKnownPorts [i].IOBase == aIOBase) 752 return kLptKnownPorts [i].name; 753 754 return mUserDefinedPortName; 755 } 756 757 /** 758 * Returns port parameters corresponding to the given standard COM name. 759 * Returns @c true on success, or @c false if the given port name is not one 760 * of the standard names (i.e. "COMx"). 761 */ 762 bool VBoxGlobal::toCOMPortNumbers (const QString &aName, ulong &aIRQ, 763 ulong &aIOBase) const 764 { 765 for (size_t i = 0; i < RT_ELEMENTS (kComKnownPorts); ++ i) 766 if (strcmp (kComKnownPorts [i].name, aName.toUtf8().data()) == 0) 767 { 768 aIRQ = kComKnownPorts [i].IRQ; 769 aIOBase = kComKnownPorts [i].IOBase; 770 return true; 771 } 772 773 return false; 774 } 775 776 /** 777 * Returns port parameters corresponding to the given standard LPT name. 778 * Returns @c true on success, or @c false if the given port name is not one 779 * of the standard names (i.e. "LPTx"). 780 */ 781 bool VBoxGlobal::toLPTPortNumbers (const QString &aName, ulong &aIRQ, 782 ulong &aIOBase) const 783 { 784 for (size_t i = 0; i < RT_ELEMENTS (kLptKnownPorts); ++ i) 785 if (strcmp (kLptKnownPorts [i].name, aName.toUtf8().data()) == 0) 786 { 787 aIRQ = kLptKnownPorts [i].IRQ; 788 aIOBase = kLptKnownPorts [i].IOBase; 789 return true; 790 } 791 792 return false; 793 } 794 795 QString VBoxGlobal::details(const CMedium &cmedium, bool fPredictDiff, bool fUseHtml /* = true*/) 796 { 797 /* Search for corresponding UI medium: */ 798 const QString strMediumID = cmedium.isNull() ? UIMedium::nullID() : cmedium.GetId(); 799 UIMedium uimedium = medium(strMediumID); 800 if (!cmedium.isNull() && uimedium.isNull()) 801 { 802 /* UI medium may be new and not among our mediums, request enumeration: */ 803 startMediumEnumeration(); 804 805 /* Search for corresponding UI medium again: */ 806 807 uimedium = medium(strMediumID); 808 if (uimedium.isNull()) 809 { 810 /* Medium might be deleted already, return null string: */ 811 return QString(); 812 } 813 } 814 815 /* Return UI medium details: */ 816 return fUseHtml ? uimedium.detailsHTML(true /* aNoDiffs */, fPredictDiff) : 817 uimedium.details(true /* aNoDiffs */, fPredictDiff); 818 } 819 820 /** 821 * Returns the details of the given USB device as a single-line string. 822 */ 823 QString VBoxGlobal::details (const CUSBDevice &aDevice) const 824 { 825 QString sDetails; 826 if (aDevice.isNull()) 827 sDetails = tr("Unknown device", "USB device details"); 828 else 829 { 830 QVector<QString> devInfoVector = aDevice.GetDeviceInfo(); 831 QString m; 832 QString p; 833 834 if (devInfoVector.size() >= 1) 835 m = devInfoVector[0].trimmed(); 836 if (devInfoVector.size() >= 2) 837 p = devInfoVector[1].trimmed(); 838 839 if (m.isEmpty() && p.isEmpty()) 840 { 841 sDetails = 842 tr ("Unknown device %1:%2", "USB device details") 843 .arg (QString().sprintf ("%04hX", aDevice.GetVendorId())) 844 .arg (QString().sprintf ("%04hX", aDevice.GetProductId())); 845 } 846 else 847 { 848 if (p.toUpper().startsWith (m.toUpper())) 849 sDetails = p; 850 else 851 sDetails = m + " " + p; 852 } 853 ushort r = aDevice.GetRevision(); 854 if (r != 0) 855 sDetails += QString().sprintf (" [%04hX]", r); 856 } 857 858 return sDetails.trimmed(); 859 } 860 861 /** 862 * Returns the multi-line description of the given USB device. 863 */ 864 QString VBoxGlobal::toolTip (const CUSBDevice &aDevice) const 865 { 866 QString tip = 867 tr ("<nobr>Vendor ID: %1</nobr><br>" 868 "<nobr>Product ID: %2</nobr><br>" 869 "<nobr>Revision: %3</nobr>", "USB device tooltip") 870 .arg (QString().sprintf ("%04hX", aDevice.GetVendorId())) 871 .arg (QString().sprintf ("%04hX", aDevice.GetProductId())) 872 .arg (QString().sprintf ("%04hX", aDevice.GetRevision())); 873 874 QString ser = aDevice.GetSerialNumber(); 875 if (!ser.isEmpty()) 876 tip += QString (tr ("<br><nobr>Serial No. %1</nobr>", "USB device tooltip")) 877 .arg (ser); 878 879 /* add the state field if it's a host USB device */ 880 CHostUSBDevice hostDev (aDevice); 881 if (!hostDev.isNull()) 882 { 883 tip += QString (tr ("<br><nobr>State: %1</nobr>", "USB device tooltip")) 884 .arg (gpConverter->toString (hostDev.GetState())); 885 } 886 887 return tip; 888 } 889 890 /** 891 * Returns the multi-line description of the given USB filter 892 */ 893 QString VBoxGlobal::toolTip (const CUSBDeviceFilter &aFilter) const 894 { 895 QString tip; 896 897 QString vendorId = aFilter.GetVendorId(); 898 if (!vendorId.isEmpty()) 899 tip += tr ("<nobr>Vendor ID: %1</nobr>", "USB filter tooltip") 900 .arg (vendorId); 901 902 QString productId = aFilter.GetProductId(); 903 if (!productId.isEmpty()) 904 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Product ID: %2</nobr>", "USB filter tooltip") 905 .arg (productId); 906 907 QString revision = aFilter.GetRevision(); 908 if (!revision.isEmpty()) 909 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Revision: %3</nobr>", "USB filter tooltip") 910 .arg (revision); 911 912 QString product = aFilter.GetProduct(); 913 if (!product.isEmpty()) 914 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Product: %4</nobr>", "USB filter tooltip") 915 .arg (product); 916 917 QString manufacturer = aFilter.GetManufacturer(); 918 if (!manufacturer.isEmpty()) 919 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Manufacturer: %5</nobr>", "USB filter tooltip") 920 .arg (manufacturer); 921 922 QString serial = aFilter.GetSerialNumber(); 923 if (!serial.isEmpty()) 924 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Serial No.: %1</nobr>", "USB filter tooltip") 925 .arg (serial); 926 927 QString port = aFilter.GetPort(); 928 if (!port.isEmpty()) 929 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Port: %1</nobr>", "USB filter tooltip") 930 .arg (port); 931 932 /* add the state field if it's a host USB device */ 933 CHostUSBDevice hostDev (aFilter); 934 if (!hostDev.isNull()) 935 { 936 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>State: %1</nobr>", "USB filter tooltip") 937 .arg (gpConverter->toString (hostDev.GetState())); 938 } 939 940 return tip; 941 } 942 943 /** Returns the multi-line description of the given CHostVideoInputDevice filter. */ 944 QString VBoxGlobal::toolTip(const CHostVideoInputDevice &webcam) const 945 { 946 QStringList records; 947 948 QString strName = webcam.GetName(); 949 if (!strName.isEmpty()) 950 records << strName; 951 952 QString strPath = webcam.GetPath(); 953 if (!strPath.isEmpty()) 954 records << strPath; 955 956 return records.join("<br>"); 957 } 958 959 CSession VBoxGlobal::openSession(const QString &strId, KLockType lockType /* = KLockType_Shared */) 960 { 961 /* Prepare session: */ 962 CSession session; 963 964 /* Simulate try-catch block: */ 965 bool fSuccess = false; 966 do 967 { 968 /* Create empty session instance: */ 969 session.createInstance(CLSID_Session); 970 if (session.isNull()) 971 { 972 msgCenter().cannotOpenSession(session); 973 break; 974 } 975 976 /* Search for the corresponding machine: */ 977 CMachine machine = m_vbox.FindMachine(strId); 978 if (machine.isNull()) 979 { 980 msgCenter().cannotFindMachineById(m_vbox, strId); 981 break; 982 } 983 984 if (lockType == KLockType_VM) 985 session.SetName("GUI/Qt"); 986 987 /* Lock found machine to session: */ 988 machine.LockMachine(session, lockType); 989 if (!machine.isOk()) 990 { 991 msgCenter().cannotOpenSession(machine); 992 break; 993 } 994 995 /* Pass the language ID as the property to the guest: */ 996 if (session.GetType() == KSessionType_Shared) 997 { 998 CMachine startedMachine = session.GetMachine(); 999 /* Make sure that the language is in two letter code. 1000 * Note: if languageId() returns an empty string lang.name() will 1001 * return "C" which is an valid language code. */ 1002 QLocale lang(VBoxGlobal::languageId()); 1003 startedMachine.SetGuestPropertyValue("/VirtualBox/HostInfo/GUI/LanguageID", lang.name()); 1004 } 1005 1006 /* Success finally: */ 1007 fSuccess = true; 1008 } 1009 while (0); 1010 /* Cleanup try-catch block: */ 1011 if (!fSuccess) 1012 session.detach(); 1013 1014 /* Return session: */ 1015 return session; 1016 } 1017 1018 void VBoxGlobal::createMedium(const UIMedium &medium) 1019 { 1020 if (m_mediumEnumeratorDtorRwLock.tryLockForRead()) 1021 { 1022 /* Create medium in medium-enumerator: */ 1023 if (m_pMediumEnumerator) 1024 m_pMediumEnumerator->createMedium(medium); 1025 m_mediumEnumeratorDtorRwLock.unlock(); 1026 } 1027 } 1028 1029 void VBoxGlobal::deleteMedium(const QString &strMediumID) 1030 { 1031 if (m_mediumEnumeratorDtorRwLock.tryLockForRead()) 1032 { 1033 /* Delete medium from medium-enumerator: */ 1034 if (m_pMediumEnumerator) 1035 m_pMediumEnumerator->deleteMedium(strMediumID); 1036 m_mediumEnumeratorDtorRwLock.unlock(); 1037 } 1038 } 1039 1040 1041 /** 1042 * Create a VISO using the file open dialog. 1043 * 1044 * Temporarily caches (enumerate) it in GUI inner mediums cache. 1045 * 1046 * @returns Medium ID string, empty on abort. 1047 */ 1048 QString VBoxGlobal::createVisoMediumWithFileOpenDialog(QWidget *pParent, const QString &strMachineFolder) 1049 { 1050 AssertReturn(!strMachineFolder.isEmpty(), QString()); 1051 1052 /* Figure out where to start browsing for content. */ 1053 QString strDirectory = gEDataManager->recentFolderForVISOContent(); 1054 if (strDirectory.isEmpty()) 1055 strDirectory = QDir::homePath(); 1056 if (strDirectory.isEmpty()) 1057 strDirectory = homeFolder(); 1058 1059 /* Execute the open file dialog, getting a list of files & dirs back. */ 1060 /** @todo make it possible to select directories... */ 1061 QStringList files = QIFileDialog::getOpenFileNames(strDirectory, tr("All files (*)"), pParent, 1062 /// @todo tr("Please select files and directories to be on the VISO"), 1063 tr("Please select files to be on the VISO"), 1064 0, true /*aResolveSymlinks*/, false /*aSingleFile*/); 1065 1066 /* Return if no result. */ 1067 if (files.empty() || files[0].isEmpty()) 1068 return QString(); 1069 1070 /* Remember folder for the next time. */ 1071 gEDataManager->setRecentFolderForVISOContent(QFileInfo(files[0]).absolutePath()); 1072 1073 /* Produce the VISO. */ 1074 char szVisoPath[RTPATH_MAX]; 1075 int vrc = RTPathJoin(szVisoPath, sizeof(szVisoPath), strMachineFolder.toUtf8().constData(), "ad-hoc.viso"); 1076 if (RT_SUCCESS(vrc)) 1077 { 1078 PRTSTREAM pStrmViso; 1079 vrc = RTStrmOpen(szVisoPath, "w", &pStrmViso); 1080 if (RT_SUCCESS(vrc)) 1081 { 1082 RTUUID Uuid; 1083 vrc = RTUuidCreate(&Uuid); 1084 if (RT_SUCCESS(vrc)) 1085 { 1086 RTStrmPrintf(pStrmViso, "--iprt-iso-maker-file-marker-bourne-sh %RTuuid\n", &Uuid); 1087 1088 for (int iFile = 0; iFile < files.size(); iFile++) 1089 { 1090 QByteArray const utf8Name = files[iFile].toUtf8(); 1091 const char *apszArgv[2] = { utf8Name.constData(), NULL }; 1092 char *pszQuoted; 1093 vrc = RTGetOptArgvToString(&pszQuoted, apszArgv, RTGETOPTARGV_CNV_QUOTE_BOURNE_SH); 1094 if (RT_SUCCESS(vrc)) 1095 { 1096 RTStrmPrintf(pStrmViso, "%s\n", pszQuoted); 1097 RTStrFree(pszQuoted); 1098 } 1099 else 1100 break; 1101 } 1102 1103 RTStrmFlush(pStrmViso); 1104 if (RT_SUCCESS(vrc)) 1105 vrc = RTStrmError(pStrmViso); 1106 } 1107 1108 RTStrmClose(pStrmViso); 1109 } 1110 } 1111 1112 /* Done. */ 1113 if (RT_SUCCESS(vrc)) 1114 return openMedium(UIMediumType_DVD, QString(szVisoPath), pParent); 1115 1116 /** @todo error message. */ 1117 return QString(); 1118 } 1119 1120 /* Open some external medium using file open dialog 1121 * and temporary cache (enumerate) it in GUI inner mediums cache: */ 1122 QString VBoxGlobal::openMediumWithFileOpenDialog(UIMediumType mediumType, QWidget *pParent, 1123 const QString &strDefaultFolder /* = QString() */, 1124 bool fUseLastFolder /* = false */) 1125 { 1126 /* Initialize variables: */ 1127 QList < QPair <QString, QString> > filters; 1128 QStringList backends; 1129 QStringList prefixes; 1130 QString strFilter; 1131 QString strTitle; 1132 QString allType; 1133 QString strLastFolder; 1134 switch (mediumType) 1135 { 1136 case UIMediumType_HardDisk: 1137 { 1138 filters = vboxGlobal().HDDBackends(); 1139 strTitle = tr("Please choose a virtual hard disk file"); 1140 allType = tr("All virtual hard disk files (%1)"); 1141 strLastFolder = gEDataManager->recentFolderForHardDrives(); 1142 if (strLastFolder.isEmpty()) 1143 strLastFolder = gEDataManager->recentFolderForOpticalDisks(); 1144 if (strLastFolder.isEmpty()) 1145 strLastFolder = gEDataManager->recentFolderForFloppyDisks(); 1146 break; 1147 } 1148 case UIMediumType_DVD: 1149 { 1150 filters = vboxGlobal().DVDBackends(); 1151 strTitle = tr("Please choose a virtual optical disk file"); 1152 allType = tr("All virtual optical disk files (%1)"); 1153 strLastFolder = gEDataManager->recentFolderForOpticalDisks(); 1154 if (strLastFolder.isEmpty()) 1155 strLastFolder = gEDataManager->recentFolderForFloppyDisks(); 1156 if (strLastFolder.isEmpty()) 1157 strLastFolder = gEDataManager->recentFolderForHardDrives(); 1158 break; 1159 } 1160 case UIMediumType_Floppy: 1161 { 1162 filters = vboxGlobal().FloppyBackends(); 1163 strTitle = tr("Please choose a virtual floppy disk file"); 1164 allType = tr("All virtual floppy disk files (%1)"); 1165 strLastFolder = gEDataManager->recentFolderForFloppyDisks(); 1166 if (strLastFolder.isEmpty()) 1167 strLastFolder = gEDataManager->recentFolderForOpticalDisks(); 1168 if (strLastFolder.isEmpty()) 1169 strLastFolder = gEDataManager->recentFolderForHardDrives(); 1170 break; 1171 } 1172 default: 1173 break; 1174 } 1175 QString strHomeFolder = fUseLastFolder && !strLastFolder.isEmpty() ? strLastFolder : 1176 strDefaultFolder.isEmpty() ? vboxGlobal().homeFolder() : strDefaultFolder; 1177 1178 /* Prepare filters and backends: */ 1179 for (int i = 0; i < filters.count(); ++i) 1180 { 1181 /* Get iterated filter: */ 1182 QPair <QString, QString> item = filters.at(i); 1183 /* Create one backend filter string: */ 1184 backends << QString("%1 (%2)").arg(item.first).arg(item.second); 1185 /* Save the suffix's for the "All" entry: */ 1186 prefixes << item.second; 1187 } 1188 if (!prefixes.isEmpty()) 1189 backends.insert(0, allType.arg(prefixes.join(" ").trimmed())); 1190 backends << tr("All files (*)"); 1191 strFilter = backends.join(";;").trimmed(); 1192 1193 /* Create open file dialog: */ 1194 QStringList files = QIFileDialog::getOpenFileNames(strHomeFolder, strFilter, pParent, strTitle, 0, true, true); 1195 1196 /* If dialog has some result: */ 1197 if (!files.empty() && !files[0].isEmpty()) 1198 return openMedium(mediumType, files[0], pParent); 1199 1200 return QString(); 1201 } 1202 1203 QString VBoxGlobal::openMedium(UIMediumType mediumType, QString strMediumLocation, QWidget *pParent /* = 0*/) 1204 { 1205 /* Convert to native separators: */ 1206 strMediumLocation = QDir::toNativeSeparators(strMediumLocation); 1207 1208 /* Initialize variables: */ 1209 CVirtualBox vbox = virtualBox(); 1210 1211 /* Remember the path of the last chosen medium: */ 1212 switch (mediumType) 1213 { 1214 case UIMediumType_HardDisk: gEDataManager->setRecentFolderForHardDrives(QFileInfo(strMediumLocation).absolutePath()); break; 1215 case UIMediumType_DVD: gEDataManager->setRecentFolderForOpticalDisks(QFileInfo(strMediumLocation).absolutePath()); break; 1216 case UIMediumType_Floppy: gEDataManager->setRecentFolderForFloppyDisks(QFileInfo(strMediumLocation).absolutePath()); break; 1217 default: break; 1218 } 1219 1220 /* Update recently used list: */ 1221 QStringList recentMediumList; 1222 switch (mediumType) 1223 { 1224 case UIMediumType_HardDisk: recentMediumList = gEDataManager->recentListOfHardDrives(); break; 1225 case UIMediumType_DVD: recentMediumList = gEDataManager->recentListOfOpticalDisks(); break; 1226 case UIMediumType_Floppy: recentMediumList = gEDataManager->recentListOfFloppyDisks(); break; 1227 default: break; 1228 } 1229 if (recentMediumList.contains(strMediumLocation)) 1230 recentMediumList.removeAll(strMediumLocation); 1231 recentMediumList.prepend(strMediumLocation); 1232 while(recentMediumList.size() > 5) recentMediumList.removeLast(); 1233 switch (mediumType) 1234 { 1235 case UIMediumType_HardDisk: gEDataManager->setRecentListOfHardDrives(recentMediumList); break; 1236 case UIMediumType_DVD: gEDataManager->setRecentListOfOpticalDisks(recentMediumList); break; 1237 case UIMediumType_Floppy: gEDataManager->setRecentListOfFloppyDisks(recentMediumList); break; 1238 default: break; 1239 } 1240 1241 /* Open corresponding medium: */ 1242 CMedium cmedium = vbox.OpenMedium(strMediumLocation, mediumTypeToGlobal(mediumType), KAccessMode_ReadWrite, false); 1243 1244 if (vbox.isOk()) 1245 { 1246 /* Prepare vbox medium wrapper: */ 1247 UIMedium uimedium = medium(cmedium.GetId()); 1248 1249 /* First of all we should test if that medium already opened: */ 1250 if (uimedium.isNull()) 1251 { 1252 /* And create new otherwise: */ 1253 uimedium = UIMedium(cmedium, mediumType, KMediumState_Created); 1254 vboxGlobal().createMedium(uimedium); 1255 } 1256 1257 /* Return uimedium id: */ 1258 return uimedium.id(); 1259 } 1260 else 1261 msgCenter().cannotOpenMedium(vbox, mediumType, strMediumLocation, pParent); 1262 1263 return QString(); 1264 } 1265 1266 void VBoxGlobal::startMediumEnumeration() 1267 { 1268 /* Make sure VBoxGlobal is already valid: */ 1269 AssertReturnVoid(mValid); 1270 1271 /* Make sure medium-enumerator is already created: */ 1272 if (!m_pMediumEnumerator) 1273 return; 1274 1275 /* Make sure enumeration is not already started: */ 1276 if (isMediumEnumerationInProgress()) 1277 return; 1278 1279 /* Ignore the request during VBoxGlobal cleanup: */ 1280 if (s_fCleanupInProgress) 1281 return; 1282 1283 /* If asked to restore snapshot, don't do this till *after* we're done 1284 * restoring or the code with have a heart attack. */ 1285 if (shouldRestoreCurrentSnapshot()) 1286 return; 1287 1288 if (m_mediumEnumeratorDtorRwLock.tryLockForRead()) 1289 { 1290 /* Redirect request to medium-enumerator: */ 1291 if (m_pMediumEnumerator) 1292 m_pMediumEnumerator->enumerateMediums(); 1293 m_mediumEnumeratorDtorRwLock.unlock(); 1294 } 1295 } 1296 1297 bool VBoxGlobal::isMediumEnumerationInProgress() const 1298 { 1299 /* Redirect request to medium-enumerator: */ 1300 return m_pMediumEnumerator 1301 && m_pMediumEnumerator->isMediumEnumerationInProgress(); 1302 } 1303 1304 UIMedium VBoxGlobal::medium(const QString &strMediumID) const 1305 { 1306 if (m_mediumEnumeratorDtorRwLock.tryLockForRead()) 1307 { 1308 /* Redirect call to medium-enumerator: */ 1309 UIMedium result; 1310 if (m_pMediumEnumerator) 1311 result = m_pMediumEnumerator->medium(strMediumID); 1312 m_mediumEnumeratorDtorRwLock.unlock(); 1313 return result; 1314 } 1315 return UIMedium(); 1316 } 1317 1318 QList<QString> VBoxGlobal::mediumIDs() const 1319 { 1320 if (m_mediumEnumeratorDtorRwLock.tryLockForRead()) 1321 { 1322 /* Redirect call to medium-enumerator: */ 1323 QList<QString> result; 1324 if (m_pMediumEnumerator) 1325 result = m_pMediumEnumerator->mediumIDs(); 1326 m_mediumEnumeratorDtorRwLock.unlock(); 1327 return result; 1328 } 1329 return QList<QString>(); 1330 } 1331 1332 void VBoxGlobal::prepareStorageMenu(QMenu &menu, 1333 QObject *pListener, const char *pszSlotName, 1334 const CMachine &machine, const QString &strControllerName, const StorageSlot &storageSlot) 1335 { 1336 /* Current attachment attributes: */ 1337 const CMediumAttachment currentAttachment = machine.GetMediumAttachment(strControllerName, storageSlot.port, storageSlot.device); 1338 const CMedium currentMedium = currentAttachment.GetMedium(); 1339 const QString strCurrentID = currentMedium.isNull() ? QString() : currentMedium.GetId(); 1340 const QString strCurrentLocation = currentMedium.isNull() ? QString() : currentMedium.GetLocation(); 1341 1342 /* Other medium-attachments of same machine: */ 1343 const CMediumAttachmentVector attachments = machine.GetMediumAttachments(); 1344 1345 /* Determine device & medium types: */ 1346 const UIMediumType mediumType = mediumTypeToLocal(currentAttachment.GetType()); 1347 AssertMsgReturnVoid(mediumType != UIMediumType_Invalid, ("Incorrect storage medium type!\n")); 1348 1349 1350 /* Prepare open-existing-medium action: */ 1351 QAction *pActionOpenExistingMedium = menu.addAction(UIIconPool::iconSet(":/select_file_16px.png"), QString(), pListener, pszSlotName); 1352 pActionOpenExistingMedium->setData(QVariant::fromValue(UIMediumTarget(strControllerName, currentAttachment.GetPort(), currentAttachment.GetDevice(), 1353 mediumType))); 1354 pActionOpenExistingMedium->setText(QApplication::translate("UIMachineSettingsStorage", "Choose disk image...", "This is used for hard disks, optical media and floppies")); 1355 1356 /* Prepare ad-hoc-viso action for DVD-ROMs: */ 1357 if (mediumType == UIMediumType_DVD) 1358 { 1359 QAction *pActionAdHocViso = menu.addAction(UIIconPool::iconSet(":/select_file_16px.png"), QString(), 1360 pListener, pszSlotName); 1361 pActionAdHocViso->setData(QVariant::fromValue(UIMediumTarget(strControllerName, currentAttachment.GetPort(), 1362 currentAttachment.GetDevice(), mediumType, 1363 UIMediumTarget::UIMediumTargetType_CreateAdHocVISO))); 1364 pActionAdHocViso->setText(QApplication::translate("UIMachineSettingsStorage", "Create ad hoc VISO...", "This is used for optical media")); 1365 } 1366 1367 /* Insert separator: */ 1368 menu.addSeparator(); 1369 1370 1371 /* Get existing-host-drive vector: */ 1372 CMediumVector mediums; 1373 switch (mediumType) 1374 { 1375 case UIMediumType_DVD: mediums = vboxGlobal().host().GetDVDDrives(); break; 1376 case UIMediumType_Floppy: mediums = vboxGlobal().host().GetFloppyDrives(); break; 1377 default: break; 1378 } 1379 /* Prepare choose-existing-host-drive actions: */ 1380 foreach (const CMedium &medium, mediums) 1381 { 1382 /* Make sure host-drive usage is unique: */ 1383 bool fIsHostDriveUsed = false; 1384 foreach (const CMediumAttachment &otherAttachment, attachments) 1385 { 1386 if (otherAttachment != currentAttachment) 1387 { 1388 const CMedium &otherMedium = otherAttachment.GetMedium(); 1389 if (!otherMedium.isNull() && otherMedium.GetId() == medium.GetId()) 1390 { 1391 fIsHostDriveUsed = true; 1392 break; 1393 } 1394 } 1395 } 1396 /* If host-drives usage is unique: */ 1397 if (!fIsHostDriveUsed) 1398 { 1399 QAction *pActionChooseHostDrive = menu.addAction(UIMedium(medium, mediumType).name(), pListener, pszSlotName); 1400 pActionChooseHostDrive->setCheckable(true); 1401 pActionChooseHostDrive->setChecked(!currentMedium.isNull() && medium.GetId() == strCurrentID); 1402 pActionChooseHostDrive->setData(QVariant::fromValue(UIMediumTarget(strControllerName, currentAttachment.GetPort(), currentAttachment.GetDevice(), 1403 mediumType, UIMediumTarget::UIMediumTargetType_WithID, medium.GetId()))); 1404 } 1405 } 1406 1407 1408 /* Get recent-medium list: */ 1409 QStringList recentMediumList; 1410 QStringList recentMediumListUsed; 1411 switch (mediumType) 1412 { 1413 case UIMediumType_HardDisk: recentMediumList = gEDataManager->recentListOfHardDrives(); break; 1414 case UIMediumType_DVD: recentMediumList = gEDataManager->recentListOfOpticalDisks(); break; 1415 case UIMediumType_Floppy: recentMediumList = gEDataManager->recentListOfFloppyDisks(); break; 1416 default: break; 1417 } 1418 /* Prepare choose-recent-medium actions: */ 1419 foreach (const QString &strRecentMediumLocationBase, recentMediumList) 1420 { 1421 /* Confirm medium uniqueness: */ 1422 if (recentMediumListUsed.contains(strRecentMediumLocationBase)) 1423 continue; 1424 /* Mark medium as known: */ 1425 recentMediumListUsed << strRecentMediumLocationBase; 1426 /* Convert separators to native: */ 1427 const QString strRecentMediumLocation = QDir::toNativeSeparators(strRecentMediumLocationBase); 1428 /* Confirm medium presence: */ 1429 if (!QFile::exists(strRecentMediumLocation)) 1430 continue; 1431 /* Make sure recent-medium usage is unique: */ 1432 bool fIsRecentMediumUsed = false; 1433 foreach (const CMediumAttachment &otherAttachment, attachments) 1434 { 1435 if (otherAttachment != currentAttachment) 1436 { 1437 const CMedium &otherMedium = otherAttachment.GetMedium(); 1438 if (!otherMedium.isNull() && otherMedium.GetLocation() == strRecentMediumLocation) 1439 { 1440 fIsRecentMediumUsed = true; 1441 break; 1442 } 1443 } 1444 } 1445 /* If recent-medium usage is unique: */ 1446 if (!fIsRecentMediumUsed) 1447 { 1448 QAction *pActionChooseRecentMedium = menu.addAction(QFileInfo(strRecentMediumLocation).fileName(), pListener, pszSlotName); 1449 pActionChooseRecentMedium->setCheckable(true); 1450 pActionChooseRecentMedium->setChecked(!currentMedium.isNull() && strRecentMediumLocation == strCurrentLocation); 1451 pActionChooseRecentMedium->setData(QVariant::fromValue(UIMediumTarget(strControllerName, currentAttachment.GetPort(), currentAttachment.GetDevice(), 1452 mediumType, UIMediumTarget::UIMediumTargetType_WithLocation, strRecentMediumLocation))); 1453 pActionChooseRecentMedium->setToolTip(strRecentMediumLocation); 1454 } 1455 } 1456 1457 1458 /* Last action for optical/floppy attachments only: */ 1459 if (mediumType == UIMediumType_DVD || mediumType == UIMediumType_Floppy) 1460 { 1461 /* Insert separator: */ 1462 menu.addSeparator(); 1463 1464 /* Prepare unmount-current-medium action: */ 1465 QAction *pActionUnmountMedium = menu.addAction(QString(), pListener, pszSlotName); 1466 pActionUnmountMedium->setEnabled(!currentMedium.isNull()); 1467 pActionUnmountMedium->setData(QVariant::fromValue(UIMediumTarget(strControllerName, currentAttachment.GetPort(), currentAttachment.GetDevice()))); 1468 pActionUnmountMedium->setText(QApplication::translate("UIMachineSettingsStorage", "Remove disk from virtual drive")); 1469 if (mediumType == UIMediumType_DVD) 1470 pActionUnmountMedium->setIcon(UIIconPool::iconSet(":/cd_unmount_16px.png", ":/cd_unmount_disabled_16px.png")); 1471 else if (mediumType == UIMediumType_Floppy) 1472 pActionUnmountMedium->setIcon(UIIconPool::iconSet(":/fd_unmount_16px.png", ":/fd_unmount_disabled_16px.png")); 1473 } 1474 } 1475 1476 void VBoxGlobal::updateMachineStorage(const CMachine &constMachine, const UIMediumTarget &target) 1477 { 1478 /* Mount (by default): */ 1479 bool fMount = true; 1480 /* Null medium (by default): */ 1481 CMedium cmedium; 1482 /* With null ID (by default): */ 1483 QString strActualID; 1484 1485 /* Current mount-target attributes: */ 1486 const CStorageController currentController = constMachine.GetStorageControllerByName(target.name); 1487 const KStorageBus currentStorageBus = currentController.GetBus(); 1488 const CMediumAttachment currentAttachment = constMachine.GetMediumAttachment(target.name, target.port, target.device); 1489 const CMedium currentMedium = currentAttachment.GetMedium(); 1490 const QString strCurrentID = currentMedium.isNull() ? QString() : currentMedium.GetId(); 1491 const QString strCurrentLocation = currentMedium.isNull() ? QString() : currentMedium.GetLocation(); 1492 1493 /* Which additional info do we have? */ 1494 switch (target.type) 1495 { 1496 /* Do we have an exact ID or do we let the user open a medium? */ 1497 case UIMediumTarget::UIMediumTargetType_WithID: 1498 case UIMediumTarget::UIMediumTargetType_CreateAdHocVISO: 1499 { 1500 /* New mount-target attributes: */ 1501 QString strNewID; 1502 1503 /* Invoke file-open dialog to choose medium ID: */ 1504 if (target.mediumType != UIMediumType_Invalid && target.data.isNull()) 1505 { 1506 /* Keyboard can be captured by machine-view. 1507 * So we should clear machine-view focus to let file-open dialog get it. 1508 * That way the keyboard will be released too.. */ 1509 QWidget *pLastFocusedWidget = 0; 1510 if (QApplication::focusWidget()) 1511 { 1512 pLastFocusedWidget = QApplication::focusWidget(); 1513 pLastFocusedWidget->clearFocus(); 1514 } 1515 /* Call for file-open dialog: */ 1516 const QString strMachineFolder(QFileInfo(constMachine.GetSettingsFilePath()).absolutePath()); 1517 const QString strMediumID = target.type != UIMediumTarget::UIMediumTargetType_CreateAdHocVISO 1518 ? vboxGlobal().openMediumWithFileOpenDialog(target.mediumType, 1519 windowManager().mainWindowShown(), 1520 strMachineFolder) 1521 : vboxGlobal().createVisoMediumWithFileOpenDialog(windowManager().mainWindowShown(), 1522 strMachineFolder); 1523 /* Return focus back: */ 1524 if (pLastFocusedWidget) 1525 pLastFocusedWidget->setFocus(); 1526 /* Accept new medium ID: */ 1527 if (!strMediumID.isNull()) 1528 strNewID = strMediumID; 1529 /* Else just exit: */ 1530 else return; 1531 } 1532 /* Use medium ID which was passed: */ 1533 else if (!target.data.isNull() && target.data != strCurrentID) 1534 strNewID = target.data; 1535 1536 /* Should we mount or unmount? */ 1537 fMount = !strNewID.isEmpty(); 1538 1539 /* Prepare target medium: */ 1540 const UIMedium uimedium = vboxGlobal().medium(strNewID); 1541 cmedium = uimedium.medium(); 1542 strActualID = fMount ? strNewID : strCurrentID; 1543 break; 1544 } 1545 /* Do we have a resent location? */ 1546 case UIMediumTarget::UIMediumTargetType_WithLocation: 1547 { 1548 /* Open medium by location and get new medium ID if any: */ 1549 const QString strNewID = vboxGlobal().openMedium(target.mediumType, target.data); 1550 /* Else just exit: */ 1551 if (strNewID.isEmpty()) 1552 return; 1553 1554 /* Should we mount or unmount? */ 1555 fMount = strNewID != strCurrentID; 1556 1557 /* Prepare target medium: */ 1558 const UIMedium uimedium = fMount ? vboxGlobal().medium(strNewID) : UIMedium(); 1559 cmedium = fMount ? uimedium.medium() : CMedium(); 1560 strActualID = fMount ? strNewID : strCurrentID; 1561 break; 1562 } 1563 } 1564 1565 /* Do not unmount hard-drives: */ 1566 if (target.mediumType == UIMediumType_HardDisk && !fMount) 1567 return; 1568 1569 /* Get editable machine: */ 1570 CSession session; 1571 CMachine machine = constMachine; 1572 KSessionState sessionState = machine.GetSessionState(); 1573 /* Session state unlocked? */ 1574 if (sessionState == KSessionState_Unlocked) 1575 { 1576 /* Open own 'write' session: */ 1577 session = openSession(machine.GetId()); 1578 AssertReturnVoid(!session.isNull()); 1579 machine = session.GetMachine(); 1580 } 1581 /* Is it Selector UI call? */ 1582 else if (!isVMConsoleProcess()) 1583 { 1584 /* Open existing 'shared' session: */ 1585 session = openExistingSession(machine.GetId()); 1586 AssertReturnVoid(!session.isNull()); 1587 machine = session.GetMachine(); 1588 } 1589 /* Else this is Runtime UI call 1590 * which has session locked for itself. */ 1591 1592 /* Remount medium to the predefined port/device: */ 1593 bool fWasMounted = false; 1594 /* Hard drive case: */ 1595 if (target.mediumType == UIMediumType_HardDisk) 1596 { 1597 /* Detaching: */ 1598 machine.DetachDevice(target.name, target.port, target.device); 1599 fWasMounted = machine.isOk(); 1600 if (!fWasMounted) 1601 msgCenter().cannotDetachDevice(machine, UIMediumType_HardDisk, strCurrentLocation, 1602 StorageSlot(currentStorageBus, target.port, target.device)); 1603 else 1604 { 1605 /* Attaching: */ 1606 machine.AttachDevice(target.name, target.port, target.device, KDeviceType_HardDisk, cmedium); 1607 fWasMounted = machine.isOk(); 1608 if (!fWasMounted) 1609 msgCenter().cannotAttachDevice(machine, UIMediumType_HardDisk, strCurrentLocation, 1610 StorageSlot(currentStorageBus, target.port, target.device)); 1611 } 1612 } 1613 /* Optical/floppy drive case: */ 1614 else 1615 { 1616 /* Remounting: */ 1617 machine.MountMedium(target.name, target.port, target.device, cmedium, false /* force? */); 1618 fWasMounted = machine.isOk(); 1619 if (!fWasMounted) 1620 { 1621 /* Ask for force remounting: */ 1622 if (msgCenter().cannotRemountMedium(machine, vboxGlobal().medium(strActualID), 1623 fMount, true /* retry? */)) 1624 { 1625 /* Force remounting: */ 1626 machine.MountMedium(target.name, target.port, target.device, cmedium, true /* force? */); 1627 fWasMounted = machine.isOk(); 1628 if (!fWasMounted) 1629 msgCenter().cannotRemountMedium(machine, vboxGlobal().medium(strActualID), 1630 fMount, false /* retry? */); 1631 } 1632 } 1633 /* If mounting was successful: */ 1634 if (fWasMounted) 1635 { 1636 /* Disable First RUN Wizard: */ 1637 if (gEDataManager->machineFirstTimeStarted(machine.GetId())) 1638 gEDataManager->setMachineFirstTimeStarted(false, machine.GetId()); 1639 } 1640 } 1641 1642 /* Save settings: */ 1643 if (fWasMounted) 1644 { 1645 machine.SaveSettings(); 1646 if (!machine.isOk()) 1647 msgCenter().cannotSaveMachineSettings(machine, windowManager().mainWindowShown()); 1648 } 1649 1650 /* Close session to editable machine if necessary: */ 1651 if (!session.isNull()) 1652 session.UnlockMachine(); 1653 } 521 522 #endif /* VBOX_GUI_WITH_PIDFILE */ 1654 523 1655 524 /** … … 1712 581 "Comma-separated list of translators"); 1713 582 } 1714 1715 /**1716 * Changes the language of all global string constants according to the1717 * currently installed translations tables.1718 */1719 void VBoxGlobal::retranslateUi()1720 {1721 mUserDefinedPortName = tr ("User-defined", "serial port");1722 1723 mWarningIcon = UIIconPool::defaultIcon(UIIconPool::UIDefaultIconType_MessageBoxWarning).pixmap (16, 16);1724 Assert (!mWarningIcon.isNull());1725 1726 mErrorIcon = UIIconPool::defaultIcon(UIIconPool::UIDefaultIconType_MessageBoxCritical).pixmap (16, 16);1727 Assert (!mErrorIcon.isNull());1728 1729 /* Re-enumerate uimedium since they contain some translations too: */1730 if (mValid)1731 startMediumEnumeration();1732 1733 #ifdef VBOX_WS_X111734 /* As X11 do not have functionality for providing human readable key names,1735 * we keep a table of them, which must be updated when the language is changed. */1736 UINativeHotKey::retranslateKeyNames();1737 #endif /* VBOX_WS_X11 */1738 }1739 1740 // public static stuff1741 ////////////////////////////////////////////////////////////////////////////////1742 1743 /* static */1744 bool VBoxGlobal::isDOSType (const QString &aOSTypeId)1745 {1746 if (aOSTypeId.left (3) == "dos" ||1747 aOSTypeId.left (3) == "win" ||1748 aOSTypeId.left (3) == "os2")1749 return true;1750 1751 return false;1752 }1753 1754 class VBoxTranslator : public QTranslator1755 {1756 public:1757 1758 VBoxTranslator (QObject *aParent = 0)1759 : QTranslator (aParent) {}1760 1761 bool loadFile (const QString &aFileName)1762 {1763 QFile file (aFileName);1764 if (!file.open (QIODevice::ReadOnly))1765 return false;1766 mData = file.readAll();1767 return load ((uchar*) mData.data(), mData.size());1768 }1769 1770 private:1771 1772 QByteArray mData;1773 };1774 1775 static VBoxTranslator *sTranslator = 0;1776 583 1777 584 /* static */ … … 1821 628 { 1822 629 return s_strLoadedLanguageId; 630 } 631 632 /** 633 * This does exactly the same as QLocale::system().name() but corrects its 634 * wrong behavior on Linux systems (LC_NUMERIC for some strange reason takes 635 * precedence over any other locale setting in the QLocale::system() 636 * implementation). This implementation first looks at LC_ALL (as defined by 637 * SUS), then looks at LC_MESSAGES which is designed to define a language for 638 * program messages in case if it differs from the language for other locale 639 * categories. Then it looks for LANG and finally falls back to 640 * QLocale::system().name(). 641 * 642 * The order of precedence is well defined here: 643 * http://opengroup.org/onlinepubs/007908799/xbd/envvar.html 644 * 645 * @note This method will return "C" when the requested locale is invalid or 646 * when the "C" locale is set explicitly. 647 */ 648 /* static */ 649 QString VBoxGlobal::systemLanguageId() 650 { 651 #if defined (VBOX_WS_MAC) 652 /* QLocale return the right id only if the user select the format of the 653 * language also. So we use our own implementation */ 654 return ::darwinSystemLanguage(); 655 #elif defined (Q_OS_UNIX) 656 const char *s = RTEnvGet ("LC_ALL"); 657 if (s == 0) 658 s = RTEnvGet ("LC_MESSAGES"); 659 if (s == 0) 660 s = RTEnvGet ("LANG"); 661 if (s != 0) 662 return QLocale (s).name(); 663 #endif 664 return QLocale::system().name(); 1823 665 } 1824 666 … … 1970 812 } 1971 813 1972 QString VBoxGlobal::helpFile() const1973 {1974 #if defined (VBOX_WS_WIN)1975 const QString name = "VirtualBox";1976 const QString suffix = "chm";1977 #elif defined (VBOX_WS_MAC)1978 const QString name = "UserManual";1979 const QString suffix = "pdf";1980 #elif defined (VBOX_WS_X11)1981 # if defined VBOX_OSE1982 const QString name = "UserManual";1983 const QString suffix = "pdf";1984 # else1985 const QString name = "VirtualBox";1986 const QString suffix = "chm";1987 # endif1988 #endif1989 /* Where are the docs located? */1990 char szDocsPath[RTPATH_MAX];1991 int rc = RTPathAppDocs (szDocsPath, sizeof (szDocsPath));1992 AssertRC (rc);1993 /* Make sure that the language is in two letter code.1994 * Note: if languageId() returns an empty string lang.name() will1995 * return "C" which is an valid language code. */1996 QLocale lang (VBoxGlobal::languageId());1997 1998 /* Construct the path and the filename */1999 QString manual = QString ("%1/%2_%3.%4").arg (szDocsPath)2000 .arg (name)2001 .arg (lang.name())2002 .arg (suffix);2003 /* Check if a help file with that name exists */2004 QFileInfo fi (manual);2005 if (fi.exists())2006 return manual;2007 2008 /* Fall back to the standard */2009 manual = QString ("%1/%2.%4").arg (szDocsPath)2010 .arg (name)2011 .arg (suffix);2012 return manual;2013 }2014 2015 /**2016 * Replacement for QToolButton::setTextLabel() that handles the shortcut2017 * letter (if it is present in the argument string) as if it were a setText()2018 * call: the shortcut letter is used to automatically assign an "Alt+<letter>"2019 * accelerator key sequence to the given tool button.2020 *2021 * @note This method preserves the icon set if it was assigned before. Only2022 * the text label and the accelerator are changed.2023 *2024 * @param aToolButton Tool button to set the text label on.2025 * @param aTextLabel Text label to set.2026 */2027 /* static */2028 void VBoxGlobal::setTextLabel (QToolButton *aToolButton,2029 const QString &aTextLabel)2030 {2031 AssertReturnVoid (aToolButton != NULL);2032 2033 /* remember the icon set as setText() will kill it */2034 QIcon iset = aToolButton->icon();2035 /* re-use the setText() method to detect and set the accelerator */2036 aToolButton->setText (aTextLabel);2037 QKeySequence accel = aToolButton->shortcut();2038 aToolButton->setText (aTextLabel);2039 aToolButton->setIcon (iset);2040 /* set the accel last as setIconSet() would kill it */2041 aToolButton->setShortcut (accel);2042 }2043 2044 /**2045 * Performs direct and flipped search of position for \a aRectangle to make sure2046 * it is fully contained inside \a aBoundRegion region by moving & resizing2047 * \a aRectangle if necessary. Selects the minimum shifted result between direct2048 * and flipped variants.2049 */2050 /* static */2051 QRect VBoxGlobal::normalizeGeometry (const QRect &aRectangle, const QRegion &aBoundRegion,2052 bool aCanResize /* = true */)2053 {2054 /* Direct search for normalized rectangle */2055 QRect var1 (getNormalized (aRectangle, aBoundRegion, aCanResize));2056 2057 /* Flipped search for normalized rectangle */2058 QRect var2 (flip (getNormalized (flip (aRectangle).boundingRect(),2059 flip (aBoundRegion), aCanResize)).boundingRect());2060 2061 /* Calculate shift from starting position for both variants */2062 double length1 = sqrt (pow ((double) (var1.x() - aRectangle.x()), (double) 2) +2063 pow ((double) (var1.y() - aRectangle.y()), (double) 2));2064 double length2 = sqrt (pow ((double) (var2.x() - aRectangle.x()), (double) 2) +2065 pow ((double) (var2.y() - aRectangle.y()), (double) 2));2066 2067 /* Return minimum shifted variant */2068 return length1 > length2 ? var2 : var1;2069 }2070 2071 /**2072 * Ensures that the given rectangle \a aRectangle is fully contained within the2073 * region \a aBoundRegion by moving \a aRectangle if necessary. If \a aRectangle is2074 * larger than \a aBoundRegion, top left corner of \a aRectangle is aligned with the2075 * top left corner of maximum available rectangle and, if \a aCanResize is true,2076 * \a aRectangle is shrinked to become fully visible.2077 */2078 /* static */2079 QRect VBoxGlobal::getNormalized (const QRect &aRectangle, const QRegion &aBoundRegion,2080 bool /* aCanResize = true */)2081 {2082 /* Storing available horizontal sub-rectangles & vertical shifts */2083 int windowVertical = aRectangle.center().y();2084 QVector <QRect> rectanglesVector (aBoundRegion.rects());2085 QList <QRect> rectanglesList;2086 QList <int> shiftsList;2087 foreach (QRect currentItem, rectanglesVector)2088 {2089 int currentDelta = qAbs (windowVertical - currentItem.center().y());2090 int shift2Top = currentItem.top() - aRectangle.top();2091 int shift2Bot = currentItem.bottom() - aRectangle.bottom();2092 2093 int itemPosition = 0;2094 foreach (QRect item, rectanglesList)2095 {2096 int delta = qAbs (windowVertical - item.center().y());2097 if (delta > currentDelta) break; else ++ itemPosition;2098 }2099 rectanglesList.insert (itemPosition, currentItem);2100 2101 int shift2TopPos = 0;2102 foreach (int shift, shiftsList)2103 if (qAbs (shift) > qAbs (shift2Top)) break; else ++ shift2TopPos;2104 shiftsList.insert (shift2TopPos, shift2Top);2105 2106 int shift2BotPos = 0;2107 foreach (int shift, shiftsList)2108 if (qAbs (shift) > qAbs (shift2Bot)) break; else ++ shift2BotPos;2109 shiftsList.insert (shift2BotPos, shift2Bot);2110 }2111 2112 /* Trying to find the appropriate place for window */2113 QRect result;2114 for (int i = -1; i < shiftsList.size(); ++ i)2115 {2116 /* Move to appropriate vertical */2117 QRect rectangle (aRectangle);2118 if (i >= 0) rectangle.translate (0, shiftsList [i]);2119 2120 /* Search horizontal shift */2121 int maxShift = 0;2122 foreach (QRect item, rectanglesList)2123 {2124 QRect trectangle (rectangle.translated (item.left() - rectangle.left(), 0));2125 if (!item.intersects (trectangle))2126 continue;2127 2128 if (rectangle.left() < item.left())2129 {2130 int shift = item.left() - rectangle.left();2131 maxShift = qAbs (shift) > qAbs (maxShift) ? shift : maxShift;2132 }2133 else if (rectangle.right() > item.right())2134 {2135 int shift = item.right() - rectangle.right();2136 maxShift = qAbs (shift) > qAbs (maxShift) ? shift : maxShift;2137 }2138 }2139 2140 /* Shift across the horizontal direction */2141 rectangle.translate (maxShift, 0);2142 2143 /* Check the translated rectangle to feat the rules */2144 if (aBoundRegion.united (rectangle) == aBoundRegion)2145 result = rectangle;2146 2147 if (!result.isNull()) break;2148 }2149 2150 if (result.isNull())2151 {2152 /* Resize window to feat desirable size2153 * using max of available rectangles */2154 QRect maxRectangle;2155 quint64 maxSquare = 0;2156 foreach (QRect item, rectanglesList)2157 {2158 quint64 square = item.width() * item.height();2159 if (square > maxSquare)2160 {2161 maxSquare = square;2162 maxRectangle = item;2163 }2164 }2165 2166 result = aRectangle;2167 result.moveTo (maxRectangle.x(), maxRectangle.y());2168 if (maxRectangle.right() < result.right())2169 result.setRight (maxRectangle.right());2170 if (maxRectangle.bottom() < result.bottom())2171 result.setBottom (maxRectangle.bottom());2172 }2173 2174 return result;2175 }2176 2177 /**2178 * Returns the flipped (transposed) region.2179 */2180 /* static */2181 QRegion VBoxGlobal::flip (const QRegion &aRegion)2182 {2183 QRegion result;2184 QVector <QRect> rectangles (aRegion.rects());2185 foreach (QRect rectangle, rectangles)2186 result += QRect (rectangle.y(), rectangle.x(),2187 rectangle.height(), rectangle.width());2188 return result;2189 }2190 2191 /**2192 * Aligns the center of \a aWidget with the center of \a aRelative.2193 *2194 * If necessary, \a aWidget's position is adjusted to make it fully visible2195 * within the available desktop area. If \a aWidget is bigger then this area,2196 * it will also be resized unless \a aCanResize is false or there is an2197 * inappropriate minimum size limit (in which case the top left corner will be2198 * simply aligned with the top left corner of the available desktop area).2199 *2200 * \a aWidget must be a top-level widget. \a aRelative may be any widget, but2201 * if it's not top-level itself, its top-level widget will be used for2202 * calculations. \a aRelative can also be NULL, in which case \a aWidget will2203 * be centered relative to the available desktop area.2204 */2205 /* static */2206 void VBoxGlobal::centerWidget (QWidget *aWidget, QWidget *aRelative,2207 bool aCanResize /* = true */)2208 {2209 AssertReturnVoid (aWidget);2210 AssertReturnVoid (aWidget->isTopLevel());2211 2212 QRect deskGeo, parentGeo;2213 QWidget *w = aRelative;2214 if (w)2215 {2216 w = w->window();2217 deskGeo = gpDesktop->availableGeometry (w);2218 parentGeo = w->frameGeometry();2219 /* On X11/Gnome, geo/frameGeo.x() and y() are always 0 for top level2220 * widgets with parents, what a shame. Use mapToGlobal() to workaround. */2221 QPoint d = w->mapToGlobal (QPoint (0, 0));2222 d.rx() -= w->geometry().x() - w->x();2223 d.ry() -= w->geometry().y() - w->y();2224 parentGeo.moveTopLeft (d);2225 }2226 else2227 {2228 deskGeo = gpDesktop->availableGeometry();2229 parentGeo = deskGeo;2230 }2231 2232 /* On X11, there is no way to determine frame geometry (including WM2233 * decorations) before the widget is shown for the first time. Stupidly2234 * enumerate other top level widgets to find the thickest frame. The code2235 * is based on the idea taken from QDialog::adjustPositionInternal(). */2236 2237 int extraw = 0, extrah = 0;2238 2239 QWidgetList list = QApplication::topLevelWidgets();2240 QListIterator<QWidget*> it (list);2241 while ((extraw == 0 || extrah == 0) && it.hasNext())2242 {2243 int framew, frameh;2244 QWidget *current = it.next();2245 if (!current->isVisible())2246 continue;2247 2248 framew = current->frameGeometry().width() - current->width();2249 frameh = current->frameGeometry().height() - current->height();2250 2251 extraw = qMax (extraw, framew);2252 extrah = qMax (extrah, frameh);2253 }2254 2255 /// @todo (r=dmik) not sure if we really need this2256 #if 02257 /* sanity check for decoration frames. With embedding, we2258 * might get extraordinary values */2259 if (extraw == 0 || extrah == 0 || extraw > 20 || extrah > 50)2260 {2261 extrah = 50;2262 extraw = 20;2263 }2264 #endif2265 2266 /* On non-X11 platforms, the following would be enough instead of the2267 * above workaround: */2268 // QRect geo = frameGeometry();2269 QRect geo = QRect (0, 0, aWidget->width() + extraw,2270 aWidget->height() + extrah);2271 2272 geo.moveCenter (QPoint (parentGeo.x() + (parentGeo.width() - 1) / 2,2273 parentGeo.y() + (parentGeo.height() - 1) / 2));2274 2275 /* ensure the widget is within the available desktop area */2276 QRect newGeo = normalizeGeometry (geo, deskGeo, aCanResize);2277 #ifdef VBOX_WS_MAC2278 /* No idea why, but Qt doesn't respect if there is a unified toolbar on the2279 * ::move call. So manually add the height of the toolbar before setting2280 * the position. */2281 if (w)2282 newGeo.translate (0, ::darwinWindowToolBarHeight (aWidget));2283 #endif /* VBOX_WS_MAC */2284 2285 aWidget->move (newGeo.topLeft());2286 2287 if (aCanResize &&2288 (geo.width() != newGeo.width() || geo.height() != newGeo.height()))2289 aWidget->resize (newGeo.width() - extraw, newGeo.height() - extrah);2290 }2291 2292 814 /** 2293 815 * Returns the decimal separator for the current locale. … … 2487 1009 } 2488 1010 2489 /** 2490 * Returns the required video memory in bytes for the current desktop 2491 * resolution at maximum possible screen depth in bpp. 2492 */ 2493 /* static */ 2494 quint64 VBoxGlobal::requiredVideoMemory(const QString &strGuestOSTypeId, int cMonitors /* = 1 */) 2495 { 2496 /* We create a list of the size of all available host monitors. This list 2497 * is sorted by value and by starting with the biggest one, we calculate 2498 * the memory requirements for every guest screen. This is of course not 2499 * correct, but as we can't predict on which host screens the user will 2500 * open the guest windows, this is the best assumption we can do, cause it 2501 * is the worst case. */ 2502 const int cHostScreens = gpDesktop->screenCount(); 2503 QVector<int> screenSize(qMax(cMonitors, cHostScreens), 0); 2504 for (int i = 0; i < cHostScreens; ++i) 2505 { 2506 QRect r = gpDesktop->screenGeometry(i); 2507 screenSize[i] = r.width() * r.height(); 2508 } 2509 /* Now sort the vector */ 2510 qSort(screenSize.begin(), screenSize.end(), qGreater<int>()); 2511 /* For the case that there are more guest screens configured then host 2512 * screens available, replace all zeros with the greatest value in the 2513 * vector. */ 2514 for (int i = 0; i < screenSize.size(); ++i) 2515 if (screenSize.at(i) == 0) 2516 screenSize.replace(i, screenSize.at(0)); 2517 2518 quint64 needBits = 0; 2519 for (int i = 0; i < cMonitors; ++i) 2520 { 2521 /* Calculate summary required memory amount in bits */ 2522 needBits += (screenSize.at(i) * /* with x height */ 2523 32 + /* we will take the maximum possible bpp for now */ 2524 8 * _1M) + /* current cache per screen - may be changed in future */ 2525 8 * 4096; /* adapter info */ 2526 } 2527 /* Translate value into megabytes with rounding to highest side */ 2528 quint64 needMBytes = needBits % (8 * _1M) ? needBits / (8 * _1M) + 1 : 2529 needBits / (8 * _1M) /* convert to megabytes */; 2530 2531 if (strGuestOSTypeId.startsWith("Windows")) 2532 { 2533 /* Windows guests need offscreen VRAM too for graphics acceleration features: */ 2534 #ifdef VBOX_WITH_CRHGSMI 2535 if (isWddmCompatibleOsType(strGuestOSTypeId)) 2536 { 2537 /* wddm mode, there are two surfaces for each screen: shadow & primary */ 2538 needMBytes *= 3; 2539 } 2540 else 2541 #endif /* VBOX_WITH_CRHGSMI */ 2542 { 2543 needMBytes *= 2; 2544 } 2545 } 2546 2547 return needMBytes * _1M; 2548 } 2549 2550 /** 2551 * Puts soft hyphens after every path component in the given file name. 2552 * 2553 * @param aFileName File name (must be a full path name). 2554 */ 2555 /* static */ 2556 QString VBoxGlobal::locationForHTML (const QString &aFileName) 2557 { 2558 /// @todo (dmik) remove? 2559 // QString result = QDir::toNativeSeparators (fn); 2560 //#ifdef Q_OS_LINUX 2561 // result.replace ('/', "/<font color=red>­</font>"); 2562 //#else 2563 // result.replace ('\\', "\\<font color=red>­</font>"); 2564 //#endif 2565 // return result; 2566 QFileInfo fi (aFileName); 2567 return fi.fileName(); 1011 /* static */ 1012 QString VBoxGlobal::fullMediumFormatName(const QString &strBaseMediumFormatName) 1013 { 1014 if (strBaseMediumFormatName == "VDI") 1015 return tr("VDI (VirtualBox Disk Image)"); 1016 else if (strBaseMediumFormatName == "VMDK") 1017 return tr("VMDK (Virtual Machine Disk)"); 1018 else if (strBaseMediumFormatName == "VHD") 1019 return tr("VHD (Virtual Hard Disk)"); 1020 else if (strBaseMediumFormatName == "Parallels") 1021 return tr("HDD (Parallels Hard Disk)"); 1022 else if (strBaseMediumFormatName == "QED") 1023 return tr("QED (QEMU enhanced disk)"); 1024 else if (strBaseMediumFormatName == "QCOW") 1025 return tr("QCOW (QEMU Copy-On-Write)"); 1026 return strBaseMediumFormatName; 1027 } 1028 1029 /** 1030 * Returns the list of the standard COM port names (i.e. "COMx"). 1031 */ 1032 QStringList VBoxGlobal::COMPortNames() const 1033 { 1034 QStringList list; 1035 for (size_t i = 0; i < RT_ELEMENTS (kComKnownPorts); ++ i) 1036 list << kComKnownPorts [i].name; 1037 1038 return list; 1039 } 1040 1041 /** 1042 * Returns the name of the standard COM port corresponding to the given 1043 * parameters, or "User-defined" (which is also returned when both 1044 * @a aIRQ and @a aIOBase are 0). 1045 */ 1046 QString VBoxGlobal::toCOMPortName (ulong aIRQ, ulong aIOBase) const 1047 { 1048 for (size_t i = 0; i < RT_ELEMENTS (kComKnownPorts); ++ i) 1049 if (kComKnownPorts [i].IRQ == aIRQ && 1050 kComKnownPorts [i].IOBase == aIOBase) 1051 return kComKnownPorts [i].name; 1052 1053 return mUserDefinedPortName; 1054 } 1055 1056 /** 1057 * Returns port parameters corresponding to the given standard COM name. 1058 * Returns @c true on success, or @c false if the given port name is not one 1059 * of the standard names (i.e. "COMx"). 1060 */ 1061 bool VBoxGlobal::toCOMPortNumbers (const QString &aName, ulong &aIRQ, 1062 ulong &aIOBase) const 1063 { 1064 for (size_t i = 0; i < RT_ELEMENTS (kComKnownPorts); ++ i) 1065 if (strcmp (kComKnownPorts [i].name, aName.toUtf8().data()) == 0) 1066 { 1067 aIRQ = kComKnownPorts [i].IRQ; 1068 aIOBase = kComKnownPorts [i].IOBase; 1069 return true; 1070 } 1071 1072 return false; 1073 } 1074 1075 /** 1076 * Returns the list of the standard LPT port names (i.e. "LPTx"). 1077 */ 1078 QStringList VBoxGlobal::LPTPortNames() const 1079 { 1080 QStringList list; 1081 for (size_t i = 0; i < RT_ELEMENTS (kLptKnownPorts); ++ i) 1082 list << kLptKnownPorts [i].name; 1083 1084 return list; 1085 } 1086 1087 /** 1088 * Returns the name of the standard LPT port corresponding to the given 1089 * parameters, or "User-defined" (which is also returned when both 1090 * @a aIRQ and @a aIOBase are 0). 1091 */ 1092 QString VBoxGlobal::toLPTPortName (ulong aIRQ, ulong aIOBase) const 1093 { 1094 for (size_t i = 0; i < RT_ELEMENTS (kLptKnownPorts); ++ i) 1095 if (kLptKnownPorts [i].IRQ == aIRQ && 1096 kLptKnownPorts [i].IOBase == aIOBase) 1097 return kLptKnownPorts [i].name; 1098 1099 return mUserDefinedPortName; 1100 } 1101 1102 /** 1103 * Returns port parameters corresponding to the given standard LPT name. 1104 * Returns @c true on success, or @c false if the given port name is not one 1105 * of the standard names (i.e. "LPTx"). 1106 */ 1107 bool VBoxGlobal::toLPTPortNumbers (const QString &aName, ulong &aIRQ, 1108 ulong &aIOBase) const 1109 { 1110 for (size_t i = 0; i < RT_ELEMENTS (kLptKnownPorts); ++ i) 1111 if (strcmp (kLptKnownPorts [i].name, aName.toUtf8().data()) == 0) 1112 { 1113 aIRQ = kLptKnownPorts [i].IRQ; 1114 aIOBase = kLptKnownPorts [i].IOBase; 1115 return true; 1116 } 1117 1118 return false; 2568 1119 } 2569 1120 … … 2625 1176 } 2626 1177 2627 /* static */2628 QString VBoxGlobal::replaceHtmlEntities(QString strText)2629 {2630 return strText2631 .replace('&', "&")2632 .replace('<', "<")2633 .replace('>', ">")2634 .replace('\"', """);2635 }2636 2637 1178 /** 2638 1179 * Reformats the input string @a aStr so that: … … 2680 1221 return text; 2681 1222 } 2682 2683 /**2684 * This does exactly the same as QLocale::system().name() but corrects its2685 * wrong behavior on Linux systems (LC_NUMERIC for some strange reason takes2686 * precedence over any other locale setting in the QLocale::system()2687 * implementation). This implementation first looks at LC_ALL (as defined by2688 * SUS), then looks at LC_MESSAGES which is designed to define a language for2689 * program messages in case if it differs from the language for other locale2690 * categories. Then it looks for LANG and finally falls back to2691 * QLocale::system().name().2692 *2693 * The order of precedence is well defined here:2694 * http://opengroup.org/onlinepubs/007908799/xbd/envvar.html2695 *2696 * @note This method will return "C" when the requested locale is invalid or2697 * when the "C" locale is set explicitly.2698 */2699 /* static */2700 QString VBoxGlobal::systemLanguageId()2701 {2702 #if defined (VBOX_WS_MAC)2703 /* QLocale return the right id only if the user select the format of the2704 * language also. So we use our own implementation */2705 return ::darwinSystemLanguage();2706 #elif defined (Q_OS_UNIX)2707 const char *s = RTEnvGet ("LC_ALL");2708 if (s == 0)2709 s = RTEnvGet ("LC_MESSAGES");2710 if (s == 0)2711 s = RTEnvGet ("LANG");2712 if (s != 0)2713 return QLocale (s).name();2714 #endif2715 return QLocale::system().name();2716 }2717 2718 #if defined (VBOX_WS_X11)2719 2720 static char *XXGetProperty (Display *aDpy, Window aWnd,2721 Atom aPropType, const char *aPropName)2722 {2723 Atom propNameAtom = XInternAtom (aDpy, aPropName,2724 True /* only_if_exists */);2725 if (propNameAtom == None)2726 return NULL;2727 2728 Atom actTypeAtom = None;2729 int actFmt = 0;2730 unsigned long nItems = 0;2731 unsigned long nBytesAfter = 0;2732 unsigned char *propVal = NULL;2733 int rc = XGetWindowProperty (aDpy, aWnd, propNameAtom,2734 0, LONG_MAX, False /* delete */,2735 aPropType, &actTypeAtom, &actFmt,2736 &nItems, &nBytesAfter, &propVal);2737 if (rc != Success)2738 return NULL;2739 2740 return reinterpret_cast <char *> (propVal);2741 }2742 2743 static Bool XXSendClientMessage (Display *aDpy, Window aWnd, const char *aMsg,2744 unsigned long aData0 = 0, unsigned long aData1 = 0,2745 unsigned long aData2 = 0, unsigned long aData3 = 0,2746 unsigned long aData4 = 0)2747 {2748 Atom msgAtom = XInternAtom (aDpy, aMsg, True /* only_if_exists */);2749 if (msgAtom == None)2750 return False;2751 2752 XEvent ev;2753 2754 ev.xclient.type = ClientMessage;2755 ev.xclient.serial = 0;2756 ev.xclient.send_event = True;2757 ev.xclient.display = aDpy;2758 ev.xclient.window = aWnd;2759 ev.xclient.message_type = msgAtom;2760 2761 /* always send as 32 bit for now */2762 ev.xclient.format = 32;2763 ev.xclient.data.l [0] = aData0;2764 ev.xclient.data.l [1] = aData1;2765 ev.xclient.data.l [2] = aData2;2766 ev.xclient.data.l [3] = aData3;2767 ev.xclient.data.l [4] = aData4;2768 2769 return XSendEvent (aDpy, DefaultRootWindow (aDpy), False,2770 SubstructureRedirectMask, &ev) != 0;2771 }2772 2773 #endif2774 2775 /**2776 * Activates the specified window. If necessary, the window will be2777 * de-iconified activation.2778 *2779 * @note On X11, it is implied that @a aWid represents a window of the same2780 * display the application was started on.2781 *2782 * @param aWId Window ID to activate.2783 * @param aSwitchDesktop @c true to switch to the window's desktop before2784 * activation.2785 *2786 * @return @c true on success and @c false otherwise.2787 */2788 /* static */2789 bool VBoxGlobal::activateWindow (WId aWId, bool aSwitchDesktop /* = true */)2790 {2791 RT_NOREF(aSwitchDesktop);2792 bool result = true;2793 2794 #if defined (VBOX_WS_WIN)2795 2796 HWND handle = (HWND)aWId;2797 2798 if (IsIconic (handle))2799 result &= !!ShowWindow (handle, SW_RESTORE);2800 else if (!IsWindowVisible (handle))2801 result &= !!ShowWindow (handle, SW_SHOW);2802 2803 result &= !!SetForegroundWindow (handle);2804 2805 #elif defined (VBOX_WS_X11)2806 2807 Display *dpy = QX11Info::display();2808 2809 if (aSwitchDesktop)2810 {2811 /* try to find the desktop ID using the NetWM property */2812 CARD32 *desktop = (CARD32 *) XXGetProperty (dpy, aWId, XA_CARDINAL,2813 "_NET_WM_DESKTOP");2814 if (desktop == NULL)2815 /* if the NetWM properly is not supported try to find the desktop2816 * ID using the GNOME WM property */2817 desktop = (CARD32 *) XXGetProperty (dpy, aWId, XA_CARDINAL,2818 "_WIN_WORKSPACE");2819 2820 if (desktop != NULL)2821 {2822 Bool ok = XXSendClientMessage (dpy, DefaultRootWindow (dpy),2823 "_NET_CURRENT_DESKTOP",2824 *desktop);2825 if (!ok)2826 {2827 Log1WarningFunc(("Couldn't switch to desktop=%08X\n", desktop));2828 result = false;2829 }2830 XFree (desktop);2831 }2832 else2833 {2834 Log1WarningFunc(("Couldn't find a desktop ID for aWId=%08X\n", aWId));2835 result = false;2836 }2837 }2838 2839 Bool ok = XXSendClientMessage (dpy, aWId, "_NET_ACTIVE_WINDOW");2840 result &= !!ok;2841 2842 XRaiseWindow (dpy, aWId);2843 2844 #else2845 2846 NOREF (aWId);2847 NOREF (aSwitchDesktop);2848 AssertFailed();2849 result = false;2850 2851 #endif2852 2853 if (!result)2854 Log1WarningFunc(("Couldn't activate aWId=%08X\n", aWId));2855 2856 return result;2857 }2858 2859 #ifdef VBOX_WS_X112860 /* This method tests whether the current X11 window manager supports full-screen mode as we need it.2861 * Unfortunately the EWMH specification was not fully clear about whether we can expect to find2862 * all of these atoms on the _NET_SUPPORTED root window property, so we have to test with all2863 * interesting window managers. If this fails for a user when you think it should succeed2864 * they should try executing:2865 * xprop -root | egrep -w '_NET_WM_FULLSCREEN_MONITORS|_NET_WM_STATE|_NET_WM_STATE_FULLSCREEN'2866 * in an X11 terminal window.2867 * All three strings should be found under a property called "_NET_SUPPORTED(ATOM)". */2868 /* static */2869 bool VBoxGlobal::supportsFullScreenMonitorsProtocolX11()2870 {2871 /* Using a global to get at the display does not feel right, but that is2872 * how it is done elsewhere in the code. */2873 Display *pDisplay = QX11Info::display();2874 Atom atomSupported = XInternAtom(pDisplay, "_NET_SUPPORTED",2875 True /* only_if_exists */);2876 Atom atomWMFullScreenMonitors = XInternAtom(pDisplay,2877 "_NET_WM_FULLSCREEN_MONITORS",2878 True /* only_if_exists */);2879 Atom atomWMState = XInternAtom(pDisplay,2880 "_NET_WM_STATE",2881 True /* only_if_exists */);2882 Atom atomWMStateFullScreen = XInternAtom(pDisplay,2883 "_NET_WM_STATE_FULLSCREEN",2884 True /* only_if_exists */);2885 bool fFoundFullScreenMonitors = false;2886 bool fFoundState = false;2887 bool fFoundStateFullScreen = false;2888 Atom atomType;2889 int cFormat;2890 unsigned long cItems;2891 unsigned long cbLeft;2892 Atom *pAtomHints;2893 int rc;2894 unsigned i;2895 2896 if ( atomSupported == None || atomWMFullScreenMonitors == None2897 || atomWMState == None || atomWMStateFullScreen == None)2898 return false;2899 /* Get atom value: */2900 rc = XGetWindowProperty(pDisplay, DefaultRootWindow(pDisplay),2901 atomSupported, 0, 0x7fffffff /*LONG_MAX*/,2902 False /* delete */, XA_ATOM, &atomType,2903 &cFormat, &cItems, &cbLeft,2904 (unsigned char **)&pAtomHints);2905 if (rc != Success)2906 return false;2907 if (pAtomHints == NULL)2908 return false;2909 if (atomType == XA_ATOM && cFormat == 32 && cbLeft == 0)2910 for (i = 0; i < cItems; ++i)2911 {2912 if (pAtomHints[i] == atomWMFullScreenMonitors)2913 fFoundFullScreenMonitors = true;2914 if (pAtomHints[i] == atomWMState)2915 fFoundState = true;2916 if (pAtomHints[i] == atomWMStateFullScreen)2917 fFoundStateFullScreen = true;2918 }2919 XFree(pAtomHints);2920 return fFoundFullScreenMonitors && fFoundState && fFoundStateFullScreen;2921 }2922 2923 /* static */2924 bool VBoxGlobal::setFullScreenMonitorX11(QWidget *pWidget, ulong uScreenId)2925 {2926 return XXSendClientMessage(QX11Info::display(),2927 pWidget->window()->winId(),2928 "_NET_WM_FULLSCREEN_MONITORS",2929 uScreenId, uScreenId, uScreenId, uScreenId,2930 1 /* Source indication (1 = normal application) */);2931 }2932 2933 /* static */2934 QVector<Atom> VBoxGlobal::flagsNetWmState(QWidget *pWidget)2935 {2936 /* Get display: */2937 Display *pDisplay = QX11Info::display();2938 2939 /* Prepare atoms: */2940 QVector<Atom> resultNetWmState;2941 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */);2942 2943 /* Get the size of the property data: */2944 Atom actual_type;2945 int iActualFormat;2946 ulong uPropertyLength;2947 ulong uBytesLeft;2948 uchar *pPropertyData = 0;2949 if (XGetWindowProperty(pDisplay, pWidget->window()->winId(),2950 net_wm_state, 0, 0, False, XA_ATOM, &actual_type, &iActualFormat,2951 &uPropertyLength, &uBytesLeft, &pPropertyData) == Success &&2952 actual_type == XA_ATOM && iActualFormat == 32)2953 {2954 resultNetWmState.resize(uBytesLeft / 4);2955 XFree((char*)pPropertyData);2956 pPropertyData = 0;2957 2958 /* Fetch all data: */2959 if (XGetWindowProperty(pDisplay, pWidget->window()->winId(),2960 net_wm_state, 0, resultNetWmState.size(), False, XA_ATOM, &actual_type, &iActualFormat,2961 &uPropertyLength, &uBytesLeft, &pPropertyData) != Success)2962 resultNetWmState.clear();2963 else if (uPropertyLength != (ulong)resultNetWmState.size())2964 resultNetWmState.resize(uPropertyLength);2965 2966 /* Put it into resultNetWmState: */2967 if (!resultNetWmState.isEmpty())2968 memcpy(resultNetWmState.data(), pPropertyData, resultNetWmState.size() * sizeof(Atom));2969 if (pPropertyData)2970 XFree((char*)pPropertyData);2971 }2972 2973 /* Return result: */2974 return resultNetWmState;2975 }2976 2977 /* static */2978 bool VBoxGlobal::isFullScreenFlagSet(QWidget *pWidget)2979 {2980 /* Get display: */2981 Display *pDisplay = QX11Info::display();2982 2983 /* Prepare atoms: */2984 Atom net_wm_state_fullscreen = XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", True /* only if exists */);2985 2986 /* Check if flagsNetWmState(pWidget) contains full-screen flag: */2987 return flagsNetWmState(pWidget).contains(net_wm_state_fullscreen);2988 }2989 2990 /* static */2991 void VBoxGlobal::setFullScreenFlag(QWidget *pWidget)2992 {2993 /* Get display: */2994 Display *pDisplay = QX11Info::display();2995 2996 /* Prepare atoms: */2997 QVector<Atom> resultNetWmState = flagsNetWmState(pWidget);2998 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */);2999 Atom net_wm_state_fullscreen = XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", True /* only if exists */);3000 3001 /* Append resultNetWmState with fullscreen flag if necessary: */3002 if (!resultNetWmState.contains(net_wm_state_fullscreen))3003 {3004 resultNetWmState.append(net_wm_state_fullscreen);3005 /* Apply property to widget again: */3006 XChangeProperty(pDisplay, pWidget->window()->winId(),3007 net_wm_state, XA_ATOM, 32, PropModeReplace,3008 (unsigned char*)resultNetWmState.data(), resultNetWmState.size());3009 }3010 }3011 3012 /* static */3013 void VBoxGlobal::setSkipTaskBarFlag(QWidget *pWidget)3014 {3015 /* Get display: */3016 Display *pDisplay = QX11Info::display();3017 3018 /* Prepare atoms: */3019 QVector<Atom> resultNetWmState = flagsNetWmState(pWidget);3020 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */);3021 Atom net_wm_state_skip_taskbar = XInternAtom(pDisplay, "_NET_WM_STATE_SKIP_TASKBAR", True /* only if exists */);3022 3023 /* Append resultNetWmState with skip-taskbar flag if necessary: */3024 if (!resultNetWmState.contains(net_wm_state_skip_taskbar))3025 {3026 resultNetWmState.append(net_wm_state_skip_taskbar);3027 /* Apply property to widget again: */3028 XChangeProperty(pDisplay, pWidget->window()->winId(),3029 net_wm_state, XA_ATOM, 32, PropModeReplace,3030 (unsigned char*)resultNetWmState.data(), resultNetWmState.size());3031 }3032 }3033 3034 /* static */3035 void VBoxGlobal::setSkipPagerFlag(QWidget *pWidget)3036 {3037 /* Get display: */3038 Display *pDisplay = QX11Info::display();3039 3040 /* Prepare atoms: */3041 QVector<Atom> resultNetWmState = flagsNetWmState(pWidget);3042 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */);3043 Atom net_wm_state_skip_pager = XInternAtom(pDisplay, "_NET_WM_STATE_SKIP_PAGER", True /* only if exists */);3044 3045 /* Append resultNetWmState with skip-pager flag if necessary: */3046 if (!resultNetWmState.contains(net_wm_state_skip_pager))3047 {3048 resultNetWmState.append(net_wm_state_skip_pager);3049 /* Apply property to widget again: */3050 XChangeProperty(pDisplay, pWidget->window()->winId(),3051 net_wm_state, XA_ATOM, 32, PropModeReplace,3052 (unsigned char*)resultNetWmState.data(), resultNetWmState.size());3053 }3054 }3055 #endif /* VBOX_WS_X11 */3056 1223 3057 1224 /** … … 3107 1274 } 3108 1275 3109 /** 3110 * Joins two pixmaps horizontally with 2px space between them and returns the 3111 * result. 3112 * 3113 * @param aPM1 Left pixmap. 3114 * @param aPM2 Right pixmap. 3115 */ 3116 /* static */ 3117 QPixmap VBoxGlobal::joinPixmaps (const QPixmap &aPM1, const QPixmap &aPM2) 3118 { 3119 if (aPM1.isNull()) 3120 return aPM2; 3121 if (aPM2.isNull()) 3122 return aPM1; 3123 3124 QPixmap result (aPM1.width() + aPM2.width() + 2, 3125 qMax (aPM1.height(), aPM2.height())); 3126 result.fill (Qt::transparent); 3127 3128 QPainter painter (&result); 3129 painter.drawPixmap (0, 0, aPM1); 3130 painter.drawPixmap (aPM1.width() + 2, result.height() - aPM2.height(), aPM2); 3131 painter.end(); 3132 3133 return result; 3134 } 3135 3136 /** 3137 * Searches for a widget that with @a aName (if it is not NULL) which inherits 3138 * @a aClassName (if it is not NULL) and among children of @a aParent. If @a 3139 * aParent is NULL, all top-level widgets are searched. If @a aRecursive is 3140 * true, child widgets are recursively searched as well. 3141 */ 3142 /* static */ 3143 QWidget *VBoxGlobal::findWidget (QWidget *aParent, const char *aName, 3144 const char *aClassName /* = NULL */, 3145 bool aRecursive /* = false */) 3146 { 3147 if (aParent == NULL) 3148 { 3149 QWidgetList list = QApplication::topLevelWidgets(); 3150 foreach(QWidget *w, list) 3151 { 3152 if ((!aName || strcmp (w->objectName().toLatin1().constData(), aName) == 0) && 3153 (!aClassName || strcmp (w->metaObject()->className(), aClassName) == 0)) 3154 return w; 3155 if (aRecursive) 3156 { 3157 w = findWidget (w, aName, aClassName, aRecursive); 3158 if (w) 3159 return w; 3160 } 3161 } 3162 return NULL; 3163 } 3164 3165 /* Find the first children of aParent with the appropriate properties. 3166 * Please note that this call is recursively. */ 3167 QList<QWidget *> list = aParent->findChildren<QWidget*>(aName); 3168 foreach(QWidget *child, list) 3169 { 3170 if (!aClassName || strcmp (child->metaObject()->className(), aClassName) == 0) 3171 return child; 3172 } 3173 return NULL; 3174 } 3175 3176 /** 3177 * Figures out which medium formats are currently supported by VirtualBox for 3178 * the given device type. 3179 * Returned is a list of pairs with the form 3180 * <tt>{"Backend Name", "*.suffix1 .suffix2 ..."}</tt>. 3181 */ 3182 /* static */ 3183 QList <QPair <QString, QString> > VBoxGlobal::MediumBackends(KDeviceType enmType) 3184 { 3185 CSystemProperties systemProperties = vboxGlobal().virtualBox().GetSystemProperties(); 3186 QVector<CMediumFormat> mediumFormats = systemProperties.GetMediumFormats(); 3187 QList< QPair<QString, QString> > backendPropList; 3188 for (int i = 0; i < mediumFormats.size(); ++ i) 3189 { 3190 /* File extensions */ 3191 QVector <QString> fileExtensions; 3192 QVector <KDeviceType> deviceTypes; 3193 3194 mediumFormats [i].DescribeFileExtensions(fileExtensions, deviceTypes); 3195 3196 QStringList f; 3197 for (int a = 0; a < fileExtensions.size(); ++ a) 3198 if (deviceTypes [a] == enmType) 3199 f << QString ("*.%1").arg (fileExtensions [a]); 3200 /* Create a pair out of the backend description and all suffix's. */ 3201 if (!f.isEmpty()) 3202 backendPropList << QPair<QString, QString> (mediumFormats [i].GetName(), f.join(" ")); 3203 } 3204 return backendPropList; 3205 } 3206 3207 /** 3208 * Figures out which hard disk formats are currently supported by VirtualBox. 3209 * Returned is a list of pairs with the form 3210 * <tt>{"Backend Name", "*.suffix1 .suffix2 ..."}</tt>. 3211 */ 3212 /* static */ 3213 QList <QPair <QString, QString> > VBoxGlobal::HDDBackends() 3214 { 3215 return MediumBackends(KDeviceType_HardDisk); 3216 } 3217 3218 /** 3219 * Figures out which optical disk formats are currently supported by VirtualBox. 3220 * Returned is a list of pairs with the form 3221 * <tt>{"Backend Name", "*.suffix1 .suffix2 ..."}</tt>. 3222 */ 3223 /* static */ 3224 QList <QPair <QString, QString> > VBoxGlobal::DVDBackends() 3225 { 3226 return MediumBackends(KDeviceType_DVD); 3227 } 3228 3229 /** 3230 * Figures out which floppy disk formats are currently supported by VirtualBox. 3231 * Returned is a list of pairs with the form 3232 * <tt>{"Backend Name", "*.suffix1 .suffix2 ..."}</tt>. 3233 */ 3234 /* static */ 3235 QList <QPair <QString, QString> > VBoxGlobal::FloppyBackends() 3236 { 3237 return MediumBackends(KDeviceType_Floppy); 1276 /* static */ 1277 QString VBoxGlobal::replaceHtmlEntities(QString strText) 1278 { 1279 return strText 1280 .replace('&', "&") 1281 .replace('<', "<") 1282 .replace('>', ">") 1283 .replace('\"', """); 1284 } 1285 1286 QString VBoxGlobal::helpFile() const 1287 { 1288 #if defined (VBOX_WS_WIN) 1289 const QString name = "VirtualBox"; 1290 const QString suffix = "chm"; 1291 #elif defined (VBOX_WS_MAC) 1292 const QString name = "UserManual"; 1293 const QString suffix = "pdf"; 1294 #elif defined (VBOX_WS_X11) 1295 # if defined VBOX_OSE 1296 const QString name = "UserManual"; 1297 const QString suffix = "pdf"; 1298 # else 1299 const QString name = "VirtualBox"; 1300 const QString suffix = "chm"; 1301 # endif 1302 #endif 1303 /* Where are the docs located? */ 1304 char szDocsPath[RTPATH_MAX]; 1305 int rc = RTPathAppDocs (szDocsPath, sizeof (szDocsPath)); 1306 AssertRC (rc); 1307 /* Make sure that the language is in two letter code. 1308 * Note: if languageId() returns an empty string lang.name() will 1309 * return "C" which is an valid language code. */ 1310 QLocale lang (VBoxGlobal::languageId()); 1311 1312 /* Construct the path and the filename */ 1313 QString manual = QString ("%1/%2_%3.%4").arg (szDocsPath) 1314 .arg (name) 1315 .arg (lang.name()) 1316 .arg (suffix); 1317 /* Check if a help file with that name exists */ 1318 QFileInfo fi (manual); 1319 if (fi.exists()) 1320 return manual; 1321 1322 /* Fall back to the standard */ 1323 manual = QString ("%1/%2.%4").arg (szDocsPath) 1324 .arg (name) 1325 .arg (suffix); 1326 return manual; 3238 1327 } 3239 1328 … … 3255 1344 } 3256 1345 3257 #ifdef VBOX_WITH_CRHGSMI 3258 /* static */ 3259 bool VBoxGlobal::isWddmCompatibleOsType(const QString &strGuestOSTypeId) 3260 { 3261 return strGuestOSTypeId.startsWith("WindowsVista") 3262 || strGuestOSTypeId.startsWith("Windows7") 3263 || strGuestOSTypeId.startsWith("Windows8") 3264 || strGuestOSTypeId.startsWith("Windows81") 3265 || strGuestOSTypeId.startsWith("Windows10") 3266 || strGuestOSTypeId.startsWith("Windows2008") 3267 || strGuestOSTypeId.startsWith("Windows2012"); 3268 } 3269 #endif /* VBOX_WITH_CRHGSMI */ 3270 3271 /* static */ 3272 QString VBoxGlobal::fullMediumFormatName(const QString &strBaseMediumFormatName) 3273 { 3274 if (strBaseMediumFormatName == "VDI") 3275 return tr("VDI (VirtualBox Disk Image)"); 3276 else if (strBaseMediumFormatName == "VMDK") 3277 return tr("VMDK (Virtual Machine Disk)"); 3278 else if (strBaseMediumFormatName == "VHD") 3279 return tr("VHD (Virtual Hard Disk)"); 3280 else if (strBaseMediumFormatName == "Parallels") 3281 return tr("HDD (Parallels Hard Disk)"); 3282 else if (strBaseMediumFormatName == "QED") 3283 return tr("QED (QEMU enhanced disk)"); 3284 else if (strBaseMediumFormatName == "QCOW") 3285 return tr("QCOW (QEMU Copy-On-Write)"); 3286 return strBaseMediumFormatName; 3287 } 3288 3289 #ifdef RT_OS_LINUX 3290 /* static */ 3291 void VBoxGlobal::checkForWrongUSBMounted() 3292 { 3293 /* Make sure '/proc/mounts' exists and can be opened: */ 3294 QFile file("/proc/mounts"); 3295 if (!file.exists() || !file.open(QIODevice::ReadOnly | QIODevice::Text)) 3296 return; 3297 3298 /* Fetch contents: */ 3299 QStringList contents; 3300 for (;;) 3301 { 3302 QByteArray line = file.readLine(); 3303 if (line.isEmpty()) 3304 break; 3305 contents << line; 3306 } 3307 /* Grep contents for usbfs presence: */ 3308 QStringList grep1(contents.filter("/sys/bus/usb/drivers")); 3309 QStringList grep2(grep1.filter("usbfs")); 3310 if (grep2.isEmpty()) 3311 return; 3312 3313 /* Show corresponding warning: */ 3314 msgCenter().warnAboutWrongUSBMounted(); 3315 } 3316 #endif /* RT_OS_LINUX */ 3317 3318 /* static */ 3319 void VBoxGlobal::setMinimumWidthAccordingSymbolCount(QSpinBox *pSpinBox, int cCount) 3320 { 3321 /* Load options: */ 3322 QStyleOptionSpinBox option; 3323 option.initFrom(pSpinBox); 3324 3325 /* Acquire edit-field rectangle: */ 3326 QRect rect = pSpinBox->style()->subControlRect(QStyle::CC_SpinBox, 3327 &option, 3328 QStyle::SC_SpinBoxEditField, 3329 pSpinBox); 3330 3331 /* Calculate minimum-width magic: */ 3332 int iSpinBoxWidth = pSpinBox->width(); 3333 int iSpinBoxEditFieldWidth = rect.width(); 3334 int iSpinBoxDelta = qMax(0, iSpinBoxWidth - iSpinBoxEditFieldWidth); 3335 QFontMetrics metrics(pSpinBox->font(), pSpinBox); 3336 QString strDummy(cCount, '0'); 3337 int iTextWidth = metrics.width(strDummy); 3338 3339 /* Tune spin-box minimum-width: */ 3340 pSpinBox->setMinimumWidth(iTextWidth + iSpinBoxDelta); 1346 /** 1347 * Performs direct and flipped search of position for \a aRectangle to make sure 1348 * it is fully contained inside \a aBoundRegion region by moving & resizing 1349 * \a aRectangle if necessary. Selects the minimum shifted result between direct 1350 * and flipped variants. 1351 */ 1352 /* static */ 1353 QRect VBoxGlobal::normalizeGeometry (const QRect &aRectangle, const QRegion &aBoundRegion, 1354 bool aCanResize /* = true */) 1355 { 1356 /* Direct search for normalized rectangle */ 1357 QRect var1 (getNormalized (aRectangle, aBoundRegion, aCanResize)); 1358 1359 /* Flipped search for normalized rectangle */ 1360 QRect var2 (flip (getNormalized (flip (aRectangle).boundingRect(), 1361 flip (aBoundRegion), aCanResize)).boundingRect()); 1362 1363 /* Calculate shift from starting position for both variants */ 1364 double length1 = sqrt (pow ((double) (var1.x() - aRectangle.x()), (double) 2) + 1365 pow ((double) (var1.y() - aRectangle.y()), (double) 2)); 1366 double length2 = sqrt (pow ((double) (var2.x() - aRectangle.x()), (double) 2) + 1367 pow ((double) (var2.y() - aRectangle.y()), (double) 2)); 1368 1369 /* Return minimum shifted variant */ 1370 return length1 > length2 ? var2 : var1; 1371 } 1372 1373 /** 1374 * Ensures that the given rectangle \a aRectangle is fully contained within the 1375 * region \a aBoundRegion by moving \a aRectangle if necessary. If \a aRectangle is 1376 * larger than \a aBoundRegion, top left corner of \a aRectangle is aligned with the 1377 * top left corner of maximum available rectangle and, if \a aCanResize is true, 1378 * \a aRectangle is shrinked to become fully visible. 1379 */ 1380 /* static */ 1381 QRect VBoxGlobal::getNormalized (const QRect &aRectangle, const QRegion &aBoundRegion, 1382 bool /* aCanResize = true */) 1383 { 1384 /* Storing available horizontal sub-rectangles & vertical shifts */ 1385 int windowVertical = aRectangle.center().y(); 1386 QVector <QRect> rectanglesVector (aBoundRegion.rects()); 1387 QList <QRect> rectanglesList; 1388 QList <int> shiftsList; 1389 foreach (QRect currentItem, rectanglesVector) 1390 { 1391 int currentDelta = qAbs (windowVertical - currentItem.center().y()); 1392 int shift2Top = currentItem.top() - aRectangle.top(); 1393 int shift2Bot = currentItem.bottom() - aRectangle.bottom(); 1394 1395 int itemPosition = 0; 1396 foreach (QRect item, rectanglesList) 1397 { 1398 int delta = qAbs (windowVertical - item.center().y()); 1399 if (delta > currentDelta) break; else ++ itemPosition; 1400 } 1401 rectanglesList.insert (itemPosition, currentItem); 1402 1403 int shift2TopPos = 0; 1404 foreach (int shift, shiftsList) 1405 if (qAbs (shift) > qAbs (shift2Top)) break; else ++ shift2TopPos; 1406 shiftsList.insert (shift2TopPos, shift2Top); 1407 1408 int shift2BotPos = 0; 1409 foreach (int shift, shiftsList) 1410 if (qAbs (shift) > qAbs (shift2Bot)) break; else ++ shift2BotPos; 1411 shiftsList.insert (shift2BotPos, shift2Bot); 1412 } 1413 1414 /* Trying to find the appropriate place for window */ 1415 QRect result; 1416 for (int i = -1; i < shiftsList.size(); ++ i) 1417 { 1418 /* Move to appropriate vertical */ 1419 QRect rectangle (aRectangle); 1420 if (i >= 0) rectangle.translate (0, shiftsList [i]); 1421 1422 /* Search horizontal shift */ 1423 int maxShift = 0; 1424 foreach (QRect item, rectanglesList) 1425 { 1426 QRect trectangle (rectangle.translated (item.left() - rectangle.left(), 0)); 1427 if (!item.intersects (trectangle)) 1428 continue; 1429 1430 if (rectangle.left() < item.left()) 1431 { 1432 int shift = item.left() - rectangle.left(); 1433 maxShift = qAbs (shift) > qAbs (maxShift) ? shift : maxShift; 1434 } 1435 else if (rectangle.right() > item.right()) 1436 { 1437 int shift = item.right() - rectangle.right(); 1438 maxShift = qAbs (shift) > qAbs (maxShift) ? shift : maxShift; 1439 } 1440 } 1441 1442 /* Shift across the horizontal direction */ 1443 rectangle.translate (maxShift, 0); 1444 1445 /* Check the translated rectangle to feat the rules */ 1446 if (aBoundRegion.united (rectangle) == aBoundRegion) 1447 result = rectangle; 1448 1449 if (!result.isNull()) break; 1450 } 1451 1452 if (result.isNull()) 1453 { 1454 /* Resize window to feat desirable size 1455 * using max of available rectangles */ 1456 QRect maxRectangle; 1457 quint64 maxSquare = 0; 1458 foreach (QRect item, rectanglesList) 1459 { 1460 quint64 square = item.width() * item.height(); 1461 if (square > maxSquare) 1462 { 1463 maxSquare = square; 1464 maxRectangle = item; 1465 } 1466 } 1467 1468 result = aRectangle; 1469 result.moveTo (maxRectangle.x(), maxRectangle.y()); 1470 if (maxRectangle.right() < result.right()) 1471 result.setRight (maxRectangle.right()); 1472 if (maxRectangle.bottom() < result.bottom()) 1473 result.setBottom (maxRectangle.bottom()); 1474 } 1475 1476 return result; 1477 } 1478 1479 /** 1480 * Returns the flipped (transposed) region. 1481 */ 1482 /* static */ 1483 QRegion VBoxGlobal::flip (const QRegion &aRegion) 1484 { 1485 QRegion result; 1486 QVector <QRect> rectangles (aRegion.rects()); 1487 foreach (QRect rectangle, rectangles) 1488 result += QRect (rectangle.y(), rectangle.x(), 1489 rectangle.height(), rectangle.width()); 1490 return result; 1491 } 1492 1493 /** 1494 * Aligns the center of \a aWidget with the center of \a aRelative. 1495 * 1496 * If necessary, \a aWidget's position is adjusted to make it fully visible 1497 * within the available desktop area. If \a aWidget is bigger then this area, 1498 * it will also be resized unless \a aCanResize is false or there is an 1499 * inappropriate minimum size limit (in which case the top left corner will be 1500 * simply aligned with the top left corner of the available desktop area). 1501 * 1502 * \a aWidget must be a top-level widget. \a aRelative may be any widget, but 1503 * if it's not top-level itself, its top-level widget will be used for 1504 * calculations. \a aRelative can also be NULL, in which case \a aWidget will 1505 * be centered relative to the available desktop area. 1506 */ 1507 /* static */ 1508 void VBoxGlobal::centerWidget (QWidget *aWidget, QWidget *aRelative, 1509 bool aCanResize /* = true */) 1510 { 1511 AssertReturnVoid (aWidget); 1512 AssertReturnVoid (aWidget->isTopLevel()); 1513 1514 QRect deskGeo, parentGeo; 1515 QWidget *w = aRelative; 1516 if (w) 1517 { 1518 w = w->window(); 1519 deskGeo = gpDesktop->availableGeometry (w); 1520 parentGeo = w->frameGeometry(); 1521 /* On X11/Gnome, geo/frameGeo.x() and y() are always 0 for top level 1522 * widgets with parents, what a shame. Use mapToGlobal() to workaround. */ 1523 QPoint d = w->mapToGlobal (QPoint (0, 0)); 1524 d.rx() -= w->geometry().x() - w->x(); 1525 d.ry() -= w->geometry().y() - w->y(); 1526 parentGeo.moveTopLeft (d); 1527 } 1528 else 1529 { 1530 deskGeo = gpDesktop->availableGeometry(); 1531 parentGeo = deskGeo; 1532 } 1533 1534 /* On X11, there is no way to determine frame geometry (including WM 1535 * decorations) before the widget is shown for the first time. Stupidly 1536 * enumerate other top level widgets to find the thickest frame. The code 1537 * is based on the idea taken from QDialog::adjustPositionInternal(). */ 1538 1539 int extraw = 0, extrah = 0; 1540 1541 QWidgetList list = QApplication::topLevelWidgets(); 1542 QListIterator<QWidget*> it (list); 1543 while ((extraw == 0 || extrah == 0) && it.hasNext()) 1544 { 1545 int framew, frameh; 1546 QWidget *current = it.next(); 1547 if (!current->isVisible()) 1548 continue; 1549 1550 framew = current->frameGeometry().width() - current->width(); 1551 frameh = current->frameGeometry().height() - current->height(); 1552 1553 extraw = qMax (extraw, framew); 1554 extrah = qMax (extrah, frameh); 1555 } 1556 1557 /// @todo (r=dmik) not sure if we really need this 1558 #if 0 1559 /* sanity check for decoration frames. With embedding, we 1560 * might get extraordinary values */ 1561 if (extraw == 0 || extrah == 0 || extraw > 20 || extrah > 50) 1562 { 1563 extrah = 50; 1564 extraw = 20; 1565 } 1566 #endif 1567 1568 /* On non-X11 platforms, the following would be enough instead of the 1569 * above workaround: */ 1570 // QRect geo = frameGeometry(); 1571 QRect geo = QRect (0, 0, aWidget->width() + extraw, 1572 aWidget->height() + extrah); 1573 1574 geo.moveCenter (QPoint (parentGeo.x() + (parentGeo.width() - 1) / 2, 1575 parentGeo.y() + (parentGeo.height() - 1) / 2)); 1576 1577 /* ensure the widget is within the available desktop area */ 1578 QRect newGeo = normalizeGeometry (geo, deskGeo, aCanResize); 1579 #ifdef VBOX_WS_MAC 1580 /* No idea why, but Qt doesn't respect if there is a unified toolbar on the 1581 * ::move call. So manually add the height of the toolbar before setting 1582 * the position. */ 1583 if (w) 1584 newGeo.translate (0, ::darwinWindowToolBarHeight (aWidget)); 1585 #endif /* VBOX_WS_MAC */ 1586 1587 aWidget->move (newGeo.topLeft()); 1588 1589 if (aCanResize && 1590 (geo.width() != newGeo.width() || geo.height() != newGeo.height())) 1591 aWidget->resize (newGeo.width() - extraw, newGeo.height() - extrah); 3341 1592 } 3342 1593 … … 3431 1682 } 3432 1683 3433 #ifdef VBOX_WS_X11 1684 /** 1685 * Activates the specified window. If necessary, the window will be 1686 * de-iconified activation. 1687 * 1688 * @note On X11, it is implied that @a aWid represents a window of the same 1689 * display the application was started on. 1690 * 1691 * @param aWId Window ID to activate. 1692 * @param aSwitchDesktop @c true to switch to the window's desktop before 1693 * activation. 1694 * 1695 * @return @c true on success and @c false otherwise. 1696 */ 1697 /* static */ 1698 bool VBoxGlobal::activateWindow (WId aWId, bool aSwitchDesktop /* = true */) 1699 { 1700 RT_NOREF(aSwitchDesktop); 1701 bool result = true; 1702 1703 #if defined (VBOX_WS_WIN) 1704 1705 HWND handle = (HWND)aWId; 1706 1707 if (IsIconic (handle)) 1708 result &= !!ShowWindow (handle, SW_RESTORE); 1709 else if (!IsWindowVisible (handle)) 1710 result &= !!ShowWindow (handle, SW_SHOW); 1711 1712 result &= !!SetForegroundWindow (handle); 1713 1714 #elif defined (VBOX_WS_X11) 1715 1716 Display *dpy = QX11Info::display(); 1717 1718 if (aSwitchDesktop) 1719 { 1720 /* try to find the desktop ID using the NetWM property */ 1721 CARD32 *desktop = (CARD32 *) XXGetProperty (dpy, aWId, XA_CARDINAL, 1722 "_NET_WM_DESKTOP"); 1723 if (desktop == NULL) 1724 /* if the NetWM properly is not supported try to find the desktop 1725 * ID using the GNOME WM property */ 1726 desktop = (CARD32 *) XXGetProperty (dpy, aWId, XA_CARDINAL, 1727 "_WIN_WORKSPACE"); 1728 1729 if (desktop != NULL) 1730 { 1731 Bool ok = XXSendClientMessage (dpy, DefaultRootWindow (dpy), 1732 "_NET_CURRENT_DESKTOP", 1733 *desktop); 1734 if (!ok) 1735 { 1736 Log1WarningFunc(("Couldn't switch to desktop=%08X\n", desktop)); 1737 result = false; 1738 } 1739 XFree (desktop); 1740 } 1741 else 1742 { 1743 Log1WarningFunc(("Couldn't find a desktop ID for aWId=%08X\n", aWId)); 1744 result = false; 1745 } 1746 } 1747 1748 Bool ok = XXSendClientMessage (dpy, aWId, "_NET_ACTIVE_WINDOW"); 1749 result &= !!ok; 1750 1751 XRaiseWindow (dpy, aWId); 1752 1753 #else 1754 1755 NOREF (aWId); 1756 NOREF (aSwitchDesktop); 1757 AssertFailed(); 1758 result = false; 1759 1760 #endif 1761 1762 if (!result) 1763 Log1WarningFunc(("Couldn't activate aWId=%08X\n", aWId)); 1764 1765 return result; 1766 } 1767 1768 #if defined (VBOX_WS_X11) 1769 1770 static char *XXGetProperty (Display *aDpy, Window aWnd, 1771 Atom aPropType, const char *aPropName) 1772 { 1773 Atom propNameAtom = XInternAtom (aDpy, aPropName, 1774 True /* only_if_exists */); 1775 if (propNameAtom == None) 1776 return NULL; 1777 1778 Atom actTypeAtom = None; 1779 int actFmt = 0; 1780 unsigned long nItems = 0; 1781 unsigned long nBytesAfter = 0; 1782 unsigned char *propVal = NULL; 1783 int rc = XGetWindowProperty (aDpy, aWnd, propNameAtom, 1784 0, LONG_MAX, False /* delete */, 1785 aPropType, &actTypeAtom, &actFmt, 1786 &nItems, &nBytesAfter, &propVal); 1787 if (rc != Success) 1788 return NULL; 1789 1790 return reinterpret_cast <char *> (propVal); 1791 } 1792 1793 static Bool XXSendClientMessage (Display *aDpy, Window aWnd, const char *aMsg, 1794 unsigned long aData0 = 0, unsigned long aData1 = 0, 1795 unsigned long aData2 = 0, unsigned long aData3 = 0, 1796 unsigned long aData4 = 0) 1797 { 1798 Atom msgAtom = XInternAtom (aDpy, aMsg, True /* only_if_exists */); 1799 if (msgAtom == None) 1800 return False; 1801 1802 XEvent ev; 1803 1804 ev.xclient.type = ClientMessage; 1805 ev.xclient.serial = 0; 1806 ev.xclient.send_event = True; 1807 ev.xclient.display = aDpy; 1808 ev.xclient.window = aWnd; 1809 ev.xclient.message_type = msgAtom; 1810 1811 /* always send as 32 bit for now */ 1812 ev.xclient.format = 32; 1813 ev.xclient.data.l [0] = aData0; 1814 ev.xclient.data.l [1] = aData1; 1815 ev.xclient.data.l [2] = aData2; 1816 ev.xclient.data.l [3] = aData3; 1817 ev.xclient.data.l [4] = aData4; 1818 1819 return XSendEvent (aDpy, DefaultRootWindow (aDpy), False, 1820 SubstructureRedirectMask, &ev) != 0; 1821 } 1822 1823 /* This method tests whether the current X11 window manager supports full-screen mode as we need it. 1824 * Unfortunately the EWMH specification was not fully clear about whether we can expect to find 1825 * all of these atoms on the _NET_SUPPORTED root window property, so we have to test with all 1826 * interesting window managers. If this fails for a user when you think it should succeed 1827 * they should try executing: 1828 * xprop -root | egrep -w '_NET_WM_FULLSCREEN_MONITORS|_NET_WM_STATE|_NET_WM_STATE_FULLSCREEN' 1829 * in an X11 terminal window. 1830 * All three strings should be found under a property called "_NET_SUPPORTED(ATOM)". */ 1831 /* static */ 1832 bool VBoxGlobal::supportsFullScreenMonitorsProtocolX11() 1833 { 1834 /* Using a global to get at the display does not feel right, but that is 1835 * how it is done elsewhere in the code. */ 1836 Display *pDisplay = QX11Info::display(); 1837 Atom atomSupported = XInternAtom(pDisplay, "_NET_SUPPORTED", 1838 True /* only_if_exists */); 1839 Atom atomWMFullScreenMonitors = XInternAtom(pDisplay, 1840 "_NET_WM_FULLSCREEN_MONITORS", 1841 True /* only_if_exists */); 1842 Atom atomWMState = XInternAtom(pDisplay, 1843 "_NET_WM_STATE", 1844 True /* only_if_exists */); 1845 Atom atomWMStateFullScreen = XInternAtom(pDisplay, 1846 "_NET_WM_STATE_FULLSCREEN", 1847 True /* only_if_exists */); 1848 bool fFoundFullScreenMonitors = false; 1849 bool fFoundState = false; 1850 bool fFoundStateFullScreen = false; 1851 Atom atomType; 1852 int cFormat; 1853 unsigned long cItems; 1854 unsigned long cbLeft; 1855 Atom *pAtomHints; 1856 int rc; 1857 unsigned i; 1858 1859 if ( atomSupported == None || atomWMFullScreenMonitors == None 1860 || atomWMState == None || atomWMStateFullScreen == None) 1861 return false; 1862 /* Get atom value: */ 1863 rc = XGetWindowProperty(pDisplay, DefaultRootWindow(pDisplay), 1864 atomSupported, 0, 0x7fffffff /*LONG_MAX*/, 1865 False /* delete */, XA_ATOM, &atomType, 1866 &cFormat, &cItems, &cbLeft, 1867 (unsigned char **)&pAtomHints); 1868 if (rc != Success) 1869 return false; 1870 if (pAtomHints == NULL) 1871 return false; 1872 if (atomType == XA_ATOM && cFormat == 32 && cbLeft == 0) 1873 for (i = 0; i < cItems; ++i) 1874 { 1875 if (pAtomHints[i] == atomWMFullScreenMonitors) 1876 fFoundFullScreenMonitors = true; 1877 if (pAtomHints[i] == atomWMState) 1878 fFoundState = true; 1879 if (pAtomHints[i] == atomWMStateFullScreen) 1880 fFoundStateFullScreen = true; 1881 } 1882 XFree(pAtomHints); 1883 return fFoundFullScreenMonitors && fFoundState && fFoundStateFullScreen; 1884 } 1885 1886 /* static */ 1887 bool VBoxGlobal::setFullScreenMonitorX11(QWidget *pWidget, ulong uScreenId) 1888 { 1889 return XXSendClientMessage(QX11Info::display(), 1890 pWidget->window()->winId(), 1891 "_NET_WM_FULLSCREEN_MONITORS", 1892 uScreenId, uScreenId, uScreenId, uScreenId, 1893 1 /* Source indication (1 = normal application) */); 1894 } 1895 1896 /* static */ 1897 QVector<Atom> VBoxGlobal::flagsNetWmState(QWidget *pWidget) 1898 { 1899 /* Get display: */ 1900 Display *pDisplay = QX11Info::display(); 1901 1902 /* Prepare atoms: */ 1903 QVector<Atom> resultNetWmState; 1904 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */); 1905 1906 /* Get the size of the property data: */ 1907 Atom actual_type; 1908 int iActualFormat; 1909 ulong uPropertyLength; 1910 ulong uBytesLeft; 1911 uchar *pPropertyData = 0; 1912 if (XGetWindowProperty(pDisplay, pWidget->window()->winId(), 1913 net_wm_state, 0, 0, False, XA_ATOM, &actual_type, &iActualFormat, 1914 &uPropertyLength, &uBytesLeft, &pPropertyData) == Success && 1915 actual_type == XA_ATOM && iActualFormat == 32) 1916 { 1917 resultNetWmState.resize(uBytesLeft / 4); 1918 XFree((char*)pPropertyData); 1919 pPropertyData = 0; 1920 1921 /* Fetch all data: */ 1922 if (XGetWindowProperty(pDisplay, pWidget->window()->winId(), 1923 net_wm_state, 0, resultNetWmState.size(), False, XA_ATOM, &actual_type, &iActualFormat, 1924 &uPropertyLength, &uBytesLeft, &pPropertyData) != Success) 1925 resultNetWmState.clear(); 1926 else if (uPropertyLength != (ulong)resultNetWmState.size()) 1927 resultNetWmState.resize(uPropertyLength); 1928 1929 /* Put it into resultNetWmState: */ 1930 if (!resultNetWmState.isEmpty()) 1931 memcpy(resultNetWmState.data(), pPropertyData, resultNetWmState.size() * sizeof(Atom)); 1932 if (pPropertyData) 1933 XFree((char*)pPropertyData); 1934 } 1935 1936 /* Return result: */ 1937 return resultNetWmState; 1938 } 1939 1940 /* static */ 1941 bool VBoxGlobal::isFullScreenFlagSet(QWidget *pWidget) 1942 { 1943 /* Get display: */ 1944 Display *pDisplay = QX11Info::display(); 1945 1946 /* Prepare atoms: */ 1947 Atom net_wm_state_fullscreen = XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", True /* only if exists */); 1948 1949 /* Check if flagsNetWmState(pWidget) contains full-screen flag: */ 1950 return flagsNetWmState(pWidget).contains(net_wm_state_fullscreen); 1951 } 1952 1953 /* static */ 1954 void VBoxGlobal::setFullScreenFlag(QWidget *pWidget) 1955 { 1956 /* Get display: */ 1957 Display *pDisplay = QX11Info::display(); 1958 1959 /* Prepare atoms: */ 1960 QVector<Atom> resultNetWmState = flagsNetWmState(pWidget); 1961 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */); 1962 Atom net_wm_state_fullscreen = XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", True /* only if exists */); 1963 1964 /* Append resultNetWmState with fullscreen flag if necessary: */ 1965 if (!resultNetWmState.contains(net_wm_state_fullscreen)) 1966 { 1967 resultNetWmState.append(net_wm_state_fullscreen); 1968 /* Apply property to widget again: */ 1969 XChangeProperty(pDisplay, pWidget->window()->winId(), 1970 net_wm_state, XA_ATOM, 32, PropModeReplace, 1971 (unsigned char*)resultNetWmState.data(), resultNetWmState.size()); 1972 } 1973 } 1974 1975 /* static */ 1976 void VBoxGlobal::setSkipTaskBarFlag(QWidget *pWidget) 1977 { 1978 /* Get display: */ 1979 Display *pDisplay = QX11Info::display(); 1980 1981 /* Prepare atoms: */ 1982 QVector<Atom> resultNetWmState = flagsNetWmState(pWidget); 1983 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */); 1984 Atom net_wm_state_skip_taskbar = XInternAtom(pDisplay, "_NET_WM_STATE_SKIP_TASKBAR", True /* only if exists */); 1985 1986 /* Append resultNetWmState with skip-taskbar flag if necessary: */ 1987 if (!resultNetWmState.contains(net_wm_state_skip_taskbar)) 1988 { 1989 resultNetWmState.append(net_wm_state_skip_taskbar); 1990 /* Apply property to widget again: */ 1991 XChangeProperty(pDisplay, pWidget->window()->winId(), 1992 net_wm_state, XA_ATOM, 32, PropModeReplace, 1993 (unsigned char*)resultNetWmState.data(), resultNetWmState.size()); 1994 } 1995 } 1996 1997 /* static */ 1998 void VBoxGlobal::setSkipPagerFlag(QWidget *pWidget) 1999 { 2000 /* Get display: */ 2001 Display *pDisplay = QX11Info::display(); 2002 2003 /* Prepare atoms: */ 2004 QVector<Atom> resultNetWmState = flagsNetWmState(pWidget); 2005 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */); 2006 Atom net_wm_state_skip_pager = XInternAtom(pDisplay, "_NET_WM_STATE_SKIP_PAGER", True /* only if exists */); 2007 2008 /* Append resultNetWmState with skip-pager flag if necessary: */ 2009 if (!resultNetWmState.contains(net_wm_state_skip_pager)) 2010 { 2011 resultNetWmState.append(net_wm_state_skip_pager); 2012 /* Apply property to widget again: */ 2013 XChangeProperty(pDisplay, pWidget->window()->winId(), 2014 net_wm_state, XA_ATOM, 32, PropModeReplace, 2015 (unsigned char*)resultNetWmState.data(), resultNetWmState.size()); 2016 } 2017 } 2018 3434 2019 void VBoxGlobal::setWMClass(QWidget *pWidget, const QString &strNameString, const QString &strClassString) 3435 2020 { … … 3455 2040 XSetClassHint(QX11Info::display(), pWidget->window()->winId(), &windowClass); 3456 2041 } 2042 2043 QList<QRect> XGetDesktopList() 2044 { 2045 /* Prepare empty resulting list: */ 2046 QList<QRect> result; 2047 2048 /* Get current display: */ 2049 Display* pDisplay = QX11Info::display(); 2050 2051 /* If it's a Xinerama desktop: */ 2052 if (XineramaIsActive(pDisplay)) 2053 { 2054 /* Reading Xinerama data: */ 2055 int iScreens = 0; 2056 XineramaScreenInfo *pScreensData = XineramaQueryScreens(pDisplay, &iScreens); 2057 2058 /* Fill resulting list: */ 2059 for (int i = 0; i < iScreens; ++ i) 2060 result << QRect(pScreensData[i].x_org, pScreensData[i].y_org, 2061 pScreensData[i].width, pScreensData[i].height); 2062 2063 /* Free screens data: */ 2064 XFree(pScreensData); 2065 } 2066 2067 /* Return resulting list: */ 2068 return result; 2069 } 2070 2071 QList<Window> XGetWindowIDList() 2072 { 2073 /* Get current display: */ 2074 Display *pDisplay = QX11Info::display(); 2075 2076 /* Get virtual desktop window: */ 2077 Window window = QX11Info::appRootWindow(); 2078 2079 /* Get 'client list' atom: */ 2080 Atom propNameAtom = XInternAtom(pDisplay, "_NET_CLIENT_LIST", True /* only if exists */); 2081 2082 /* Prepare empty resulting list: */ 2083 QList<Window> result; 2084 2085 /* If atom does not exists return empty list: */ 2086 if (propNameAtom == None) 2087 return result; 2088 2089 /* Get atom value: */ 2090 Atom realAtomType = None; 2091 int iRealFormat = 0; 2092 unsigned long uItemsCount = 0; 2093 unsigned long uBytesAfter = 0; 2094 unsigned char *pData = 0; 2095 int rc = XGetWindowProperty(pDisplay, window, propNameAtom, 2096 0, 0x7fffffff /*LONG_MAX*/, False /* delete */, 2097 XA_WINDOW, &realAtomType, &iRealFormat, 2098 &uItemsCount, &uBytesAfter, &pData); 2099 2100 /* If get property is failed return empty list: */ 2101 if (rc != Success) 2102 return result; 2103 2104 /* Fill resulting list with win ids: */ 2105 Window *pWindowData = reinterpret_cast<Window*>(pData); 2106 for (ulong i = 0; i < uItemsCount; ++ i) 2107 result << pWindowData[i]; 2108 2109 /* Releasing resources: */ 2110 XFree(pData); 2111 2112 /* Return resulting list: */ 2113 return result; 2114 } 2115 2116 QList<ulong> XGetStrut(Window window) 2117 { 2118 /* Get current display: */ 2119 Display *pDisplay = QX11Info::display(); 2120 2121 /* Get 'strut' atom: */ 2122 Atom propNameAtom = XInternAtom(pDisplay, "_NET_WM_STRUT_PARTIAL", True /* only if exists */); 2123 2124 /* Prepare empty resulting list: */ 2125 QList<ulong> result; 2126 2127 /* If atom does not exists return empty list: */ 2128 if (propNameAtom == None) 2129 return result; 2130 2131 /* Get atom value: */ 2132 Atom realAtomType = None; 2133 int iRealFormat = 0; 2134 ulong uItemsCount = 0; 2135 ulong uBytesAfter = 0; 2136 unsigned char *pData = 0; 2137 int rc = XGetWindowProperty(pDisplay, window, propNameAtom, 2138 0, LONG_MAX, False /* delete */, 2139 XA_CARDINAL, &realAtomType, &iRealFormat, 2140 &uItemsCount, &uBytesAfter, &pData); 2141 2142 /* If get property is failed return empty list: */ 2143 if (rc != Success) 2144 return result; 2145 2146 /* Fill resulting list with strut shifts: */ 2147 ulong *pStrutsData = reinterpret_cast<ulong*>(pData); 2148 for (ulong i = 0; i < uItemsCount; ++ i) 2149 result << pStrutsData[i]; 2150 2151 /* Releasing resources: */ 2152 XFree(pData); 2153 2154 /* Return resulting list: */ 2155 return result; 2156 } 2157 #endif 2158 2159 /* static */ 2160 void VBoxGlobal::setMinimumWidthAccordingSymbolCount(QSpinBox *pSpinBox, int cCount) 2161 { 2162 /* Load options: */ 2163 QStyleOptionSpinBox option; 2164 option.initFrom(pSpinBox); 2165 2166 /* Acquire edit-field rectangle: */ 2167 QRect rect = pSpinBox->style()->subControlRect(QStyle::CC_SpinBox, 2168 &option, 2169 QStyle::SC_SpinBoxEditField, 2170 pSpinBox); 2171 2172 /* Calculate minimum-width magic: */ 2173 int iSpinBoxWidth = pSpinBox->width(); 2174 int iSpinBoxEditFieldWidth = rect.width(); 2175 int iSpinBoxDelta = qMax(0, iSpinBoxWidth - iSpinBoxEditFieldWidth); 2176 QFontMetrics metrics(pSpinBox->font(), pSpinBox); 2177 QString strDummy(cCount, '0'); 2178 int iTextWidth = metrics.width(strDummy); 2179 2180 /* Tune spin-box minimum-width: */ 2181 pSpinBox->setMinimumWidth(iTextWidth + iSpinBoxDelta); 2182 } 2183 2184 /** 2185 * Returns the list of few guest OS types, queried from 2186 * IVirtualBox corresponding to every family id. 2187 */ 2188 QList<CGuestOSType> VBoxGlobal::vmGuestOSFamilyList() const 2189 { 2190 QList<CGuestOSType> result; 2191 for (int i = 0; i < m_guestOSFamilyIDs.size(); ++i) 2192 result << m_guestOSTypes[i][0]; 2193 return result; 2194 } 2195 2196 /** 2197 * Returns the list of all guest OS types, queried from 2198 * IVirtualBox corresponding to passed family id. 2199 */ 2200 QList<CGuestOSType> VBoxGlobal::vmGuestOSTypeList(const QString &aFamilyId) const 2201 { 2202 AssertMsg(m_guestOSFamilyIDs.contains(aFamilyId), ("Family ID incorrect: '%s'.", aFamilyId.toLatin1().constData())); 2203 return m_guestOSFamilyIDs.contains(aFamilyId) ? 2204 m_guestOSTypes[m_guestOSFamilyIDs.indexOf(aFamilyId)] : QList<CGuestOSType>(); 2205 } 2206 2207 /** 2208 * Returns the guest OS type object corresponding to the given type id of list 2209 * containing OS types related to OS family determined by family id attribute. 2210 * If the index is invalid a null object is returned. 2211 */ 2212 CGuestOSType VBoxGlobal::vmGuestOSType(const QString &aTypeId, 2213 const QString &aFamilyId /* = QString::null */) const 2214 { 2215 QList <CGuestOSType> list; 2216 if (m_guestOSFamilyIDs.contains (aFamilyId)) 2217 { 2218 list = m_guestOSTypes [m_guestOSFamilyIDs.indexOf (aFamilyId)]; 2219 } 2220 else 2221 { 2222 for (int i = 0; i < m_guestOSFamilyIDs.size(); ++ i) 2223 list += m_guestOSTypes [i]; 2224 } 2225 for (int j = 0; j < list.size(); ++ j) 2226 if (!list [j].GetId().compare (aTypeId)) 2227 return list [j]; 2228 AssertMsgFailed (("Type ID incorrect: '%s'.", aTypeId.toLatin1().constData())); 2229 return CGuestOSType(); 2230 } 2231 2232 /** 2233 * Returns the description corresponding to the given guest OS type id. 2234 */ 2235 QString VBoxGlobal::vmGuestOSTypeDescription (const QString &aTypeId) const 2236 { 2237 for (int i = 0; i < m_guestOSFamilyIDs.size(); ++ i) 2238 { 2239 QList <CGuestOSType> list (m_guestOSTypes [i]); 2240 for ( int j = 0; j < list.size(); ++ j) 2241 if (!list [j].GetId().compare (aTypeId)) 2242 return list [j].GetDescription(); 2243 } 2244 return QString::null; 2245 } 2246 2247 /* static */ 2248 bool VBoxGlobal::isDOSType (const QString &aOSTypeId) 2249 { 2250 if (aOSTypeId.left (3) == "dos" || 2251 aOSTypeId.left (3) == "win" || 2252 aOSTypeId.left (3) == "os2") 2253 return true; 2254 2255 return false; 2256 } 2257 2258 bool VBoxGlobal::switchToMachine(CMachine &machine) 2259 { 2260 #ifdef VBOX_WS_MAC 2261 ULONG64 id = machine.ShowConsoleWindow(); 2262 #else 2263 WId id = (WId) machine.ShowConsoleWindow(); 2264 #endif 2265 AssertWrapperOk(machine); 2266 if (!machine.isOk()) 2267 return false; 2268 2269 /* winId = 0 it means the console window has already done everything 2270 * necessary to implement the "show window" semantics. */ 2271 if (id == 0) 2272 return true; 2273 2274 #if defined(VBOX_WS_WIN) || defined(VBOX_WS_X11) 2275 2276 return vboxGlobal().activateWindow(id, true); 2277 2278 #elif defined(VBOX_WS_MAC) 2279 /* 2280 * This is just for the case were the other process cannot steal 2281 * the focus from us. It will send us a PSN so we can try. 2282 */ 2283 ProcessSerialNumber psn; 2284 psn.highLongOfPSN = id >> 32; 2285 psn.lowLongOfPSN = (UInt32)id; 2286 # ifdef __clang__ 2287 # pragma GCC diagnostic push 2288 # pragma GCC diagnostic ignored "-Wdeprecated-declarations" 2289 OSErr rc = ::SetFrontProcess(&psn); 2290 # pragma GCC diagnostic pop 2291 # else 2292 OSErr rc = ::SetFrontProcess(&psn); 2293 # endif 2294 if (!rc) 2295 Log(("GUI: %#RX64 couldn't do SetFrontProcess on itself, the selector (we) had to do it...\n", id)); 2296 else 2297 Log(("GUI: Failed to bring %#RX64 to front. rc=%#x\n", id, rc)); 2298 return !rc; 2299 2300 #else 2301 2302 return false; 2303 2304 #endif 2305 2306 2307 /// @todo Below is the old method of switching to the console window 2308 // based on the process ID of the console process. It should go away 2309 // after the new (callback-based) method is fully tested. 2310 #if 0 2311 2312 if (!canSwitchTo()) 2313 return false; 2314 2315 #if defined (VBOX_WS_WIN) 2316 2317 HWND hwnd = mWinId; 2318 2319 /* if there are blockers (modal and modeless dialogs, etc), find the 2320 * topmost one */ 2321 HWND hwndAbove = NULL; 2322 do 2323 { 2324 hwndAbove = GetNextWindow(hwnd, GW_HWNDPREV); 2325 HWND hwndOwner; 2326 if (hwndAbove != NULL && 2327 ((hwndOwner = GetWindow(hwndAbove, GW_OWNER)) == hwnd || 2328 hwndOwner == hwndAbove)) 2329 hwnd = hwndAbove; 2330 else 2331 break; 2332 } 2333 while (1); 2334 2335 /* first, check that the primary window is visible */ 2336 if (IsIconic(mWinId)) 2337 ShowWindow(mWinId, SW_RESTORE); 2338 else if (!IsWindowVisible(mWinId)) 2339 ShowWindow(mWinId, SW_SHOW); 2340 2341 #if 0 2342 LogFlowFunc(("mWinId=%08X hwnd=%08X\n", mWinId, hwnd)); 2343 #endif 2344 2345 /* then, activate the topmost in the group */ 2346 AllowSetForegroundWindow(m_pid); 2347 SetForegroundWindow(hwnd); 2348 2349 return true; 2350 2351 #elif defined (VBOX_WS_X11) 2352 2353 return false; 2354 2355 #elif defined (VBOX_WS_MAC) 2356 2357 ProcessSerialNumber psn; 2358 OSStatus rc = ::GetProcessForPID(m_pid, &psn); 2359 if (!rc) 2360 { 2361 rc = ::SetFrontProcess(&psn); 2362 2363 if (!rc) 2364 { 2365 ShowHideProcess(&psn, true); 2366 return true; 2367 } 2368 } 2369 return false; 2370 2371 #else 2372 2373 return false; 2374 2375 #endif 2376 2377 #endif 2378 } 2379 2380 bool VBoxGlobal::launchMachine(CMachine &machine, LaunchMode enmLaunchMode /* = LaunchMode_Default */) 2381 { 2382 /* Switch to machine window(s) if possible: */ 2383 if ( machine.GetSessionState() == KSessionState_Locked /* precondition for CanShowConsoleWindow() */ 2384 && machine.CanShowConsoleWindow()) 2385 { 2386 /* For the Selector UI: */ 2387 if (!isVMConsoleProcess()) 2388 { 2389 /* Just switch to existing VM window: */ 2390 return VBoxGlobal::switchToMachine(machine); 2391 } 2392 /* For the Runtime UI: */ 2393 else 2394 { 2395 /* Only separate UI process can reach that place, 2396 * switch to existing VM window and exit. */ 2397 VBoxGlobal::switchToMachine(machine); 2398 return false; 2399 } 2400 } 2401 2402 if (enmLaunchMode != LaunchMode_Separate) 2403 { 2404 /* Make sure machine-state is one of required: */ 2405 KMachineState state = machine.GetState(); NOREF(state); 2406 AssertMsg( state == KMachineState_PoweredOff 2407 || state == KMachineState_Saved 2408 || state == KMachineState_Teleported 2409 || state == KMachineState_Aborted 2410 , ("Machine must be PoweredOff/Saved/Teleported/Aborted (%d)", state)); 2411 } 2412 2413 /* Create empty session instance: */ 2414 CSession session; 2415 session.createInstance(CLSID_Session); 2416 if (session.isNull()) 2417 { 2418 msgCenter().cannotOpenSession(session); 2419 return false; 2420 } 2421 2422 /* Configure environment: */ 2423 QString strEnv; 2424 #ifdef Q_OS_WIN 2425 /* Allow started VM process to be foreground window: */ 2426 AllowSetForegroundWindow(ASFW_ANY); 2427 #endif /* Q_OS_WIN */ 2428 #ifdef VBOX_WS_X11 2429 /* Make sure VM process will start on the same display as the VM selector: */ 2430 const char *pDisplay = RTEnvGet("DISPLAY"); 2431 if (pDisplay) 2432 strEnv.append(QString("DISPLAY=%1\n").arg(pDisplay)); 2433 const char *pXauth = RTEnvGet("XAUTHORITY"); 2434 if (pXauth) 2435 strEnv.append(QString("XAUTHORITY=%1\n").arg(pXauth)); 3457 2436 #endif /* VBOX_WS_X11 */ 2437 QString strType; 2438 switch (enmLaunchMode) 2439 { 2440 case LaunchMode_Default: strType = ""; break; 2441 case LaunchMode_Separate: strType = vboxGlobal().isSeparateProcess() ? "headless" : "separate"; break; 2442 case LaunchMode_Headless: strType = "headless"; break; 2443 default: AssertFailedReturn(false); 2444 } 2445 2446 /* Prepare "VM spawning" progress: */ 2447 CProgress progress = machine.LaunchVMProcess(session, strType, strEnv); 2448 if (!machine.isOk()) 2449 { 2450 /* If the VM is started separately and the VM process is already running, then it is OK. */ 2451 if (enmLaunchMode == LaunchMode_Separate) 2452 { 2453 KMachineState state = machine.GetState(); 2454 if ( state >= KMachineState_FirstOnline 2455 && state <= KMachineState_LastOnline) 2456 { 2457 /* Already running. */ 2458 return true; 2459 } 2460 } 2461 2462 msgCenter().cannotOpenSession(machine); 2463 return false; 2464 } 2465 2466 /* Postpone showing "VM spawning" progress. 2467 * Hope 1 minute will be enough to spawn any running VM silently, 2468 * otherwise we better show the progress... 2469 * If starting separately, then show the progress now. */ 2470 int iSpawningDuration = enmLaunchMode == LaunchMode_Separate ? 0 : 60000; 2471 msgCenter().showModalProgressDialog(progress, machine.GetName(), 2472 ":/progress_start_90px.png", 0, iSpawningDuration); 2473 if (!progress.isOk() || progress.GetResultCode() != 0) 2474 msgCenter().cannotOpenSession(progress, machine.GetName()); 2475 2476 /* Unlock machine, close session: */ 2477 session.UnlockMachine(); 2478 2479 /* True finally: */ 2480 return true; 2481 } 2482 2483 CSession VBoxGlobal::openSession(const QString &strId, KLockType lockType /* = KLockType_Shared */) 2484 { 2485 /* Prepare session: */ 2486 CSession session; 2487 2488 /* Simulate try-catch block: */ 2489 bool fSuccess = false; 2490 do 2491 { 2492 /* Create empty session instance: */ 2493 session.createInstance(CLSID_Session); 2494 if (session.isNull()) 2495 { 2496 msgCenter().cannotOpenSession(session); 2497 break; 2498 } 2499 2500 /* Search for the corresponding machine: */ 2501 CMachine machine = m_vbox.FindMachine(strId); 2502 if (machine.isNull()) 2503 { 2504 msgCenter().cannotFindMachineById(m_vbox, strId); 2505 break; 2506 } 2507 2508 if (lockType == KLockType_VM) 2509 session.SetName("GUI/Qt"); 2510 2511 /* Lock found machine to session: */ 2512 machine.LockMachine(session, lockType); 2513 if (!machine.isOk()) 2514 { 2515 msgCenter().cannotOpenSession(machine); 2516 break; 2517 } 2518 2519 /* Pass the language ID as the property to the guest: */ 2520 if (session.GetType() == KSessionType_Shared) 2521 { 2522 CMachine startedMachine = session.GetMachine(); 2523 /* Make sure that the language is in two letter code. 2524 * Note: if languageId() returns an empty string lang.name() will 2525 * return "C" which is an valid language code. */ 2526 QLocale lang(VBoxGlobal::languageId()); 2527 startedMachine.SetGuestPropertyValue("/VirtualBox/HostInfo/GUI/LanguageID", lang.name()); 2528 } 2529 2530 /* Success finally: */ 2531 fSuccess = true; 2532 } 2533 while (0); 2534 /* Cleanup try-catch block: */ 2535 if (!fSuccess) 2536 session.detach(); 2537 2538 /* Return session: */ 2539 return session; 2540 } 2541 2542 /** 2543 * Figures out which medium formats are currently supported by VirtualBox for 2544 * the given device type. 2545 * Returned is a list of pairs with the form 2546 * <tt>{"Backend Name", "*.suffix1 .suffix2 ..."}</tt>. 2547 */ 2548 /* static */ 2549 QList <QPair <QString, QString> > VBoxGlobal::MediumBackends(KDeviceType enmType) 2550 { 2551 CSystemProperties systemProperties = vboxGlobal().virtualBox().GetSystemProperties(); 2552 QVector<CMediumFormat> mediumFormats = systemProperties.GetMediumFormats(); 2553 QList< QPair<QString, QString> > backendPropList; 2554 for (int i = 0; i < mediumFormats.size(); ++ i) 2555 { 2556 /* File extensions */ 2557 QVector <QString> fileExtensions; 2558 QVector <KDeviceType> deviceTypes; 2559 2560 mediumFormats [i].DescribeFileExtensions(fileExtensions, deviceTypes); 2561 2562 QStringList f; 2563 for (int a = 0; a < fileExtensions.size(); ++ a) 2564 if (deviceTypes [a] == enmType) 2565 f << QString ("*.%1").arg (fileExtensions [a]); 2566 /* Create a pair out of the backend description and all suffix's. */ 2567 if (!f.isEmpty()) 2568 backendPropList << QPair<QString, QString> (mediumFormats [i].GetName(), f.join(" ")); 2569 } 2570 return backendPropList; 2571 } 2572 2573 /** 2574 * Figures out which hard disk formats are currently supported by VirtualBox. 2575 * Returned is a list of pairs with the form 2576 * <tt>{"Backend Name", "*.suffix1 .suffix2 ..."}</tt>. 2577 */ 2578 /* static */ 2579 QList <QPair <QString, QString> > VBoxGlobal::HDDBackends() 2580 { 2581 return MediumBackends(KDeviceType_HardDisk); 2582 } 2583 2584 /** 2585 * Figures out which optical disk formats are currently supported by VirtualBox. 2586 * Returned is a list of pairs with the form 2587 * <tt>{"Backend Name", "*.suffix1 .suffix2 ..."}</tt>. 2588 */ 2589 /* static */ 2590 QList <QPair <QString, QString> > VBoxGlobal::DVDBackends() 2591 { 2592 return MediumBackends(KDeviceType_DVD); 2593 } 2594 2595 /** 2596 * Figures out which floppy disk formats are currently supported by VirtualBox. 2597 * Returned is a list of pairs with the form 2598 * <tt>{"Backend Name", "*.suffix1 .suffix2 ..."}</tt>. 2599 */ 2600 /* static */ 2601 QList <QPair <QString, QString> > VBoxGlobal::FloppyBackends() 2602 { 2603 return MediumBackends(KDeviceType_Floppy); 2604 } 2605 2606 void VBoxGlobal::startMediumEnumeration() 2607 { 2608 /* Make sure VBoxGlobal is already valid: */ 2609 AssertReturnVoid(mValid); 2610 2611 /* Make sure medium-enumerator is already created: */ 2612 if (!m_pMediumEnumerator) 2613 return; 2614 2615 /* Make sure enumeration is not already started: */ 2616 if (isMediumEnumerationInProgress()) 2617 return; 2618 2619 /* Ignore the request during VBoxGlobal cleanup: */ 2620 if (s_fCleanupInProgress) 2621 return; 2622 2623 /* If asked to restore snapshot, don't do this till *after* we're done 2624 * restoring or the code with have a heart attack. */ 2625 if (shouldRestoreCurrentSnapshot()) 2626 return; 2627 2628 if (m_mediumEnumeratorDtorRwLock.tryLockForRead()) 2629 { 2630 /* Redirect request to medium-enumerator: */ 2631 if (m_pMediumEnumerator) 2632 m_pMediumEnumerator->enumerateMediums(); 2633 m_mediumEnumeratorDtorRwLock.unlock(); 2634 } 2635 } 2636 2637 bool VBoxGlobal::isMediumEnumerationInProgress() const 2638 { 2639 /* Redirect request to medium-enumerator: */ 2640 return m_pMediumEnumerator 2641 && m_pMediumEnumerator->isMediumEnumerationInProgress(); 2642 } 2643 2644 UIMedium VBoxGlobal::medium(const QString &strMediumID) const 2645 { 2646 if (m_mediumEnumeratorDtorRwLock.tryLockForRead()) 2647 { 2648 /* Redirect call to medium-enumerator: */ 2649 UIMedium result; 2650 if (m_pMediumEnumerator) 2651 result = m_pMediumEnumerator->medium(strMediumID); 2652 m_mediumEnumeratorDtorRwLock.unlock(); 2653 return result; 2654 } 2655 return UIMedium(); 2656 } 2657 2658 QList<QString> VBoxGlobal::mediumIDs() const 2659 { 2660 if (m_mediumEnumeratorDtorRwLock.tryLockForRead()) 2661 { 2662 /* Redirect call to medium-enumerator: */ 2663 QList<QString> result; 2664 if (m_pMediumEnumerator) 2665 result = m_pMediumEnumerator->mediumIDs(); 2666 m_mediumEnumeratorDtorRwLock.unlock(); 2667 return result; 2668 } 2669 return QList<QString>(); 2670 } 2671 2672 void VBoxGlobal::createMedium(const UIMedium &medium) 2673 { 2674 if (m_mediumEnumeratorDtorRwLock.tryLockForRead()) 2675 { 2676 /* Create medium in medium-enumerator: */ 2677 if (m_pMediumEnumerator) 2678 m_pMediumEnumerator->createMedium(medium); 2679 m_mediumEnumeratorDtorRwLock.unlock(); 2680 } 2681 } 2682 2683 void VBoxGlobal::deleteMedium(const QString &strMediumID) 2684 { 2685 if (m_mediumEnumeratorDtorRwLock.tryLockForRead()) 2686 { 2687 /* Delete medium from medium-enumerator: */ 2688 if (m_pMediumEnumerator) 2689 m_pMediumEnumerator->deleteMedium(strMediumID); 2690 m_mediumEnumeratorDtorRwLock.unlock(); 2691 } 2692 } 2693 2694 QString VBoxGlobal::openMedium(UIMediumType mediumType, QString strMediumLocation, QWidget *pParent /* = 0*/) 2695 { 2696 /* Convert to native separators: */ 2697 strMediumLocation = QDir::toNativeSeparators(strMediumLocation); 2698 2699 /* Initialize variables: */ 2700 CVirtualBox vbox = virtualBox(); 2701 2702 /* Remember the path of the last chosen medium: */ 2703 switch (mediumType) 2704 { 2705 case UIMediumType_HardDisk: gEDataManager->setRecentFolderForHardDrives(QFileInfo(strMediumLocation).absolutePath()); break; 2706 case UIMediumType_DVD: gEDataManager->setRecentFolderForOpticalDisks(QFileInfo(strMediumLocation).absolutePath()); break; 2707 case UIMediumType_Floppy: gEDataManager->setRecentFolderForFloppyDisks(QFileInfo(strMediumLocation).absolutePath()); break; 2708 default: break; 2709 } 2710 2711 /* Update recently used list: */ 2712 QStringList recentMediumList; 2713 switch (mediumType) 2714 { 2715 case UIMediumType_HardDisk: recentMediumList = gEDataManager->recentListOfHardDrives(); break; 2716 case UIMediumType_DVD: recentMediumList = gEDataManager->recentListOfOpticalDisks(); break; 2717 case UIMediumType_Floppy: recentMediumList = gEDataManager->recentListOfFloppyDisks(); break; 2718 default: break; 2719 } 2720 if (recentMediumList.contains(strMediumLocation)) 2721 recentMediumList.removeAll(strMediumLocation); 2722 recentMediumList.prepend(strMediumLocation); 2723 while(recentMediumList.size() > 5) recentMediumList.removeLast(); 2724 switch (mediumType) 2725 { 2726 case UIMediumType_HardDisk: gEDataManager->setRecentListOfHardDrives(recentMediumList); break; 2727 case UIMediumType_DVD: gEDataManager->setRecentListOfOpticalDisks(recentMediumList); break; 2728 case UIMediumType_Floppy: gEDataManager->setRecentListOfFloppyDisks(recentMediumList); break; 2729 default: break; 2730 } 2731 2732 /* Open corresponding medium: */ 2733 CMedium cmedium = vbox.OpenMedium(strMediumLocation, mediumTypeToGlobal(mediumType), KAccessMode_ReadWrite, false); 2734 2735 if (vbox.isOk()) 2736 { 2737 /* Prepare vbox medium wrapper: */ 2738 UIMedium uimedium = medium(cmedium.GetId()); 2739 2740 /* First of all we should test if that medium already opened: */ 2741 if (uimedium.isNull()) 2742 { 2743 /* And create new otherwise: */ 2744 uimedium = UIMedium(cmedium, mediumType, KMediumState_Created); 2745 vboxGlobal().createMedium(uimedium); 2746 } 2747 2748 /* Return uimedium id: */ 2749 return uimedium.id(); 2750 } 2751 else 2752 msgCenter().cannotOpenMedium(vbox, mediumType, strMediumLocation, pParent); 2753 2754 return QString(); 2755 } 2756 2757 /* Open some external medium using file open dialog 2758 * and temporary cache (enumerate) it in GUI inner mediums cache: */ 2759 QString VBoxGlobal::openMediumWithFileOpenDialog(UIMediumType mediumType, QWidget *pParent, 2760 const QString &strDefaultFolder /* = QString() */, 2761 bool fUseLastFolder /* = false */) 2762 { 2763 /* Initialize variables: */ 2764 QList < QPair <QString, QString> > filters; 2765 QStringList backends; 2766 QStringList prefixes; 2767 QString strFilter; 2768 QString strTitle; 2769 QString allType; 2770 QString strLastFolder; 2771 switch (mediumType) 2772 { 2773 case UIMediumType_HardDisk: 2774 { 2775 filters = vboxGlobal().HDDBackends(); 2776 strTitle = tr("Please choose a virtual hard disk file"); 2777 allType = tr("All virtual hard disk files (%1)"); 2778 strLastFolder = gEDataManager->recentFolderForHardDrives(); 2779 if (strLastFolder.isEmpty()) 2780 strLastFolder = gEDataManager->recentFolderForOpticalDisks(); 2781 if (strLastFolder.isEmpty()) 2782 strLastFolder = gEDataManager->recentFolderForFloppyDisks(); 2783 break; 2784 } 2785 case UIMediumType_DVD: 2786 { 2787 filters = vboxGlobal().DVDBackends(); 2788 strTitle = tr("Please choose a virtual optical disk file"); 2789 allType = tr("All virtual optical disk files (%1)"); 2790 strLastFolder = gEDataManager->recentFolderForOpticalDisks(); 2791 if (strLastFolder.isEmpty()) 2792 strLastFolder = gEDataManager->recentFolderForFloppyDisks(); 2793 if (strLastFolder.isEmpty()) 2794 strLastFolder = gEDataManager->recentFolderForHardDrives(); 2795 break; 2796 } 2797 case UIMediumType_Floppy: 2798 { 2799 filters = vboxGlobal().FloppyBackends(); 2800 strTitle = tr("Please choose a virtual floppy disk file"); 2801 allType = tr("All virtual floppy disk files (%1)"); 2802 strLastFolder = gEDataManager->recentFolderForFloppyDisks(); 2803 if (strLastFolder.isEmpty()) 2804 strLastFolder = gEDataManager->recentFolderForOpticalDisks(); 2805 if (strLastFolder.isEmpty()) 2806 strLastFolder = gEDataManager->recentFolderForHardDrives(); 2807 break; 2808 } 2809 default: 2810 break; 2811 } 2812 QString strHomeFolder = fUseLastFolder && !strLastFolder.isEmpty() ? strLastFolder : 2813 strDefaultFolder.isEmpty() ? vboxGlobal().homeFolder() : strDefaultFolder; 2814 2815 /* Prepare filters and backends: */ 2816 for (int i = 0; i < filters.count(); ++i) 2817 { 2818 /* Get iterated filter: */ 2819 QPair <QString, QString> item = filters.at(i); 2820 /* Create one backend filter string: */ 2821 backends << QString("%1 (%2)").arg(item.first).arg(item.second); 2822 /* Save the suffix's for the "All" entry: */ 2823 prefixes << item.second; 2824 } 2825 if (!prefixes.isEmpty()) 2826 backends.insert(0, allType.arg(prefixes.join(" ").trimmed())); 2827 backends << tr("All files (*)"); 2828 strFilter = backends.join(";;").trimmed(); 2829 2830 /* Create open file dialog: */ 2831 QStringList files = QIFileDialog::getOpenFileNames(strHomeFolder, strFilter, pParent, strTitle, 0, true, true); 2832 2833 /* If dialog has some result: */ 2834 if (!files.empty() && !files[0].isEmpty()) 2835 return openMedium(mediumType, files[0], pParent); 2836 2837 return QString(); 2838 } 2839 2840 /** 2841 * Create a VISO using the file open dialog. 2842 * 2843 * Temporarily caches (enumerate) it in GUI inner mediums cache. 2844 * 2845 * @returns Medium ID string, empty on abort. 2846 */ 2847 QString VBoxGlobal::createVisoMediumWithFileOpenDialog(QWidget *pParent, const QString &strMachineFolder) 2848 { 2849 AssertReturn(!strMachineFolder.isEmpty(), QString()); 2850 2851 /* Figure out where to start browsing for content. */ 2852 QString strDirectory = gEDataManager->recentFolderForVISOContent(); 2853 if (strDirectory.isEmpty()) 2854 strDirectory = QDir::homePath(); 2855 if (strDirectory.isEmpty()) 2856 strDirectory = homeFolder(); 2857 2858 /* Execute the open file dialog, getting a list of files & dirs back. */ 2859 /** @todo make it possible to select directories... */ 2860 QStringList files = QIFileDialog::getOpenFileNames(strDirectory, tr("All files (*)"), pParent, 2861 /// @todo tr("Please select files and directories to be on the VISO"), 2862 tr("Please select files to be on the VISO"), 2863 0, true /*aResolveSymlinks*/, false /*aSingleFile*/); 2864 2865 /* Return if no result. */ 2866 if (files.empty() || files[0].isEmpty()) 2867 return QString(); 2868 2869 /* Remember folder for the next time. */ 2870 gEDataManager->setRecentFolderForVISOContent(QFileInfo(files[0]).absolutePath()); 2871 2872 /* Produce the VISO. */ 2873 char szVisoPath[RTPATH_MAX]; 2874 int vrc = RTPathJoin(szVisoPath, sizeof(szVisoPath), strMachineFolder.toUtf8().constData(), "ad-hoc.viso"); 2875 if (RT_SUCCESS(vrc)) 2876 { 2877 PRTSTREAM pStrmViso; 2878 vrc = RTStrmOpen(szVisoPath, "w", &pStrmViso); 2879 if (RT_SUCCESS(vrc)) 2880 { 2881 RTUUID Uuid; 2882 vrc = RTUuidCreate(&Uuid); 2883 if (RT_SUCCESS(vrc)) 2884 { 2885 RTStrmPrintf(pStrmViso, "--iprt-iso-maker-file-marker-bourne-sh %RTuuid\n", &Uuid); 2886 2887 for (int iFile = 0; iFile < files.size(); iFile++) 2888 { 2889 QByteArray const utf8Name = files[iFile].toUtf8(); 2890 const char *apszArgv[2] = { utf8Name.constData(), NULL }; 2891 char *pszQuoted; 2892 vrc = RTGetOptArgvToString(&pszQuoted, apszArgv, RTGETOPTARGV_CNV_QUOTE_BOURNE_SH); 2893 if (RT_SUCCESS(vrc)) 2894 { 2895 RTStrmPrintf(pStrmViso, "%s\n", pszQuoted); 2896 RTStrFree(pszQuoted); 2897 } 2898 else 2899 break; 2900 } 2901 2902 RTStrmFlush(pStrmViso); 2903 if (RT_SUCCESS(vrc)) 2904 vrc = RTStrmError(pStrmViso); 2905 } 2906 2907 RTStrmClose(pStrmViso); 2908 } 2909 } 2910 2911 /* Done. */ 2912 if (RT_SUCCESS(vrc)) 2913 return openMedium(UIMediumType_DVD, QString(szVisoPath), pParent); 2914 2915 /** @todo error message. */ 2916 return QString(); 2917 } 2918 2919 void VBoxGlobal::prepareStorageMenu(QMenu &menu, 2920 QObject *pListener, const char *pszSlotName, 2921 const CMachine &machine, const QString &strControllerName, const StorageSlot &storageSlot) 2922 { 2923 /* Current attachment attributes: */ 2924 const CMediumAttachment currentAttachment = machine.GetMediumAttachment(strControllerName, storageSlot.port, storageSlot.device); 2925 const CMedium currentMedium = currentAttachment.GetMedium(); 2926 const QString strCurrentID = currentMedium.isNull() ? QString() : currentMedium.GetId(); 2927 const QString strCurrentLocation = currentMedium.isNull() ? QString() : currentMedium.GetLocation(); 2928 2929 /* Other medium-attachments of same machine: */ 2930 const CMediumAttachmentVector attachments = machine.GetMediumAttachments(); 2931 2932 /* Determine device & medium types: */ 2933 const UIMediumType mediumType = mediumTypeToLocal(currentAttachment.GetType()); 2934 AssertMsgReturnVoid(mediumType != UIMediumType_Invalid, ("Incorrect storage medium type!\n")); 2935 2936 2937 /* Prepare open-existing-medium action: */ 2938 QAction *pActionOpenExistingMedium = menu.addAction(UIIconPool::iconSet(":/select_file_16px.png"), QString(), pListener, pszSlotName); 2939 pActionOpenExistingMedium->setData(QVariant::fromValue(UIMediumTarget(strControllerName, currentAttachment.GetPort(), currentAttachment.GetDevice(), 2940 mediumType))); 2941 pActionOpenExistingMedium->setText(QApplication::translate("UIMachineSettingsStorage", "Choose disk image...", "This is used for hard disks, optical media and floppies")); 2942 2943 /* Prepare ad-hoc-viso action for DVD-ROMs: */ 2944 if (mediumType == UIMediumType_DVD) 2945 { 2946 QAction *pActionAdHocViso = menu.addAction(UIIconPool::iconSet(":/select_file_16px.png"), QString(), 2947 pListener, pszSlotName); 2948 pActionAdHocViso->setData(QVariant::fromValue(UIMediumTarget(strControllerName, currentAttachment.GetPort(), 2949 currentAttachment.GetDevice(), mediumType, 2950 UIMediumTarget::UIMediumTargetType_CreateAdHocVISO))); 2951 pActionAdHocViso->setText(QApplication::translate("UIMachineSettingsStorage", "Create ad hoc VISO...", "This is used for optical media")); 2952 } 2953 2954 /* Insert separator: */ 2955 menu.addSeparator(); 2956 2957 2958 /* Get existing-host-drive vector: */ 2959 CMediumVector mediums; 2960 switch (mediumType) 2961 { 2962 case UIMediumType_DVD: mediums = vboxGlobal().host().GetDVDDrives(); break; 2963 case UIMediumType_Floppy: mediums = vboxGlobal().host().GetFloppyDrives(); break; 2964 default: break; 2965 } 2966 /* Prepare choose-existing-host-drive actions: */ 2967 foreach (const CMedium &medium, mediums) 2968 { 2969 /* Make sure host-drive usage is unique: */ 2970 bool fIsHostDriveUsed = false; 2971 foreach (const CMediumAttachment &otherAttachment, attachments) 2972 { 2973 if (otherAttachment != currentAttachment) 2974 { 2975 const CMedium &otherMedium = otherAttachment.GetMedium(); 2976 if (!otherMedium.isNull() && otherMedium.GetId() == medium.GetId()) 2977 { 2978 fIsHostDriveUsed = true; 2979 break; 2980 } 2981 } 2982 } 2983 /* If host-drives usage is unique: */ 2984 if (!fIsHostDriveUsed) 2985 { 2986 QAction *pActionChooseHostDrive = menu.addAction(UIMedium(medium, mediumType).name(), pListener, pszSlotName); 2987 pActionChooseHostDrive->setCheckable(true); 2988 pActionChooseHostDrive->setChecked(!currentMedium.isNull() && medium.GetId() == strCurrentID); 2989 pActionChooseHostDrive->setData(QVariant::fromValue(UIMediumTarget(strControllerName, currentAttachment.GetPort(), currentAttachment.GetDevice(), 2990 mediumType, UIMediumTarget::UIMediumTargetType_WithID, medium.GetId()))); 2991 } 2992 } 2993 2994 2995 /* Get recent-medium list: */ 2996 QStringList recentMediumList; 2997 QStringList recentMediumListUsed; 2998 switch (mediumType) 2999 { 3000 case UIMediumType_HardDisk: recentMediumList = gEDataManager->recentListOfHardDrives(); break; 3001 case UIMediumType_DVD: recentMediumList = gEDataManager->recentListOfOpticalDisks(); break; 3002 case UIMediumType_Floppy: recentMediumList = gEDataManager->recentListOfFloppyDisks(); break; 3003 default: break; 3004 } 3005 /* Prepare choose-recent-medium actions: */ 3006 foreach (const QString &strRecentMediumLocationBase, recentMediumList) 3007 { 3008 /* Confirm medium uniqueness: */ 3009 if (recentMediumListUsed.contains(strRecentMediumLocationBase)) 3010 continue; 3011 /* Mark medium as known: */ 3012 recentMediumListUsed << strRecentMediumLocationBase; 3013 /* Convert separators to native: */ 3014 const QString strRecentMediumLocation = QDir::toNativeSeparators(strRecentMediumLocationBase); 3015 /* Confirm medium presence: */ 3016 if (!QFile::exists(strRecentMediumLocation)) 3017 continue; 3018 /* Make sure recent-medium usage is unique: */ 3019 bool fIsRecentMediumUsed = false; 3020 foreach (const CMediumAttachment &otherAttachment, attachments) 3021 { 3022 if (otherAttachment != currentAttachment) 3023 { 3024 const CMedium &otherMedium = otherAttachment.GetMedium(); 3025 if (!otherMedium.isNull() && otherMedium.GetLocation() == strRecentMediumLocation) 3026 { 3027 fIsRecentMediumUsed = true; 3028 break; 3029 } 3030 } 3031 } 3032 /* If recent-medium usage is unique: */ 3033 if (!fIsRecentMediumUsed) 3034 { 3035 QAction *pActionChooseRecentMedium = menu.addAction(QFileInfo(strRecentMediumLocation).fileName(), pListener, pszSlotName); 3036 pActionChooseRecentMedium->setCheckable(true); 3037 pActionChooseRecentMedium->setChecked(!currentMedium.isNull() && strRecentMediumLocation == strCurrentLocation); 3038 pActionChooseRecentMedium->setData(QVariant::fromValue(UIMediumTarget(strControllerName, currentAttachment.GetPort(), currentAttachment.GetDevice(), 3039 mediumType, UIMediumTarget::UIMediumTargetType_WithLocation, strRecentMediumLocation))); 3040 pActionChooseRecentMedium->setToolTip(strRecentMediumLocation); 3041 } 3042 } 3043 3044 3045 /* Last action for optical/floppy attachments only: */ 3046 if (mediumType == UIMediumType_DVD || mediumType == UIMediumType_Floppy) 3047 { 3048 /* Insert separator: */ 3049 menu.addSeparator(); 3050 3051 /* Prepare unmount-current-medium action: */ 3052 QAction *pActionUnmountMedium = menu.addAction(QString(), pListener, pszSlotName); 3053 pActionUnmountMedium->setEnabled(!currentMedium.isNull()); 3054 pActionUnmountMedium->setData(QVariant::fromValue(UIMediumTarget(strControllerName, currentAttachment.GetPort(), currentAttachment.GetDevice()))); 3055 pActionUnmountMedium->setText(QApplication::translate("UIMachineSettingsStorage", "Remove disk from virtual drive")); 3056 if (mediumType == UIMediumType_DVD) 3057 pActionUnmountMedium->setIcon(UIIconPool::iconSet(":/cd_unmount_16px.png", ":/cd_unmount_disabled_16px.png")); 3058 else if (mediumType == UIMediumType_Floppy) 3059 pActionUnmountMedium->setIcon(UIIconPool::iconSet(":/fd_unmount_16px.png", ":/fd_unmount_disabled_16px.png")); 3060 } 3061 } 3062 3063 void VBoxGlobal::updateMachineStorage(const CMachine &constMachine, const UIMediumTarget &target) 3064 { 3065 /* Mount (by default): */ 3066 bool fMount = true; 3067 /* Null medium (by default): */ 3068 CMedium cmedium; 3069 /* With null ID (by default): */ 3070 QString strActualID; 3071 3072 /* Current mount-target attributes: */ 3073 const CStorageController currentController = constMachine.GetStorageControllerByName(target.name); 3074 const KStorageBus currentStorageBus = currentController.GetBus(); 3075 const CMediumAttachment currentAttachment = constMachine.GetMediumAttachment(target.name, target.port, target.device); 3076 const CMedium currentMedium = currentAttachment.GetMedium(); 3077 const QString strCurrentID = currentMedium.isNull() ? QString() : currentMedium.GetId(); 3078 const QString strCurrentLocation = currentMedium.isNull() ? QString() : currentMedium.GetLocation(); 3079 3080 /* Which additional info do we have? */ 3081 switch (target.type) 3082 { 3083 /* Do we have an exact ID or do we let the user open a medium? */ 3084 case UIMediumTarget::UIMediumTargetType_WithID: 3085 case UIMediumTarget::UIMediumTargetType_CreateAdHocVISO: 3086 { 3087 /* New mount-target attributes: */ 3088 QString strNewID; 3089 3090 /* Invoke file-open dialog to choose medium ID: */ 3091 if (target.mediumType != UIMediumType_Invalid && target.data.isNull()) 3092 { 3093 /* Keyboard can be captured by machine-view. 3094 * So we should clear machine-view focus to let file-open dialog get it. 3095 * That way the keyboard will be released too.. */ 3096 QWidget *pLastFocusedWidget = 0; 3097 if (QApplication::focusWidget()) 3098 { 3099 pLastFocusedWidget = QApplication::focusWidget(); 3100 pLastFocusedWidget->clearFocus(); 3101 } 3102 /* Call for file-open dialog: */ 3103 const QString strMachineFolder(QFileInfo(constMachine.GetSettingsFilePath()).absolutePath()); 3104 const QString strMediumID = target.type != UIMediumTarget::UIMediumTargetType_CreateAdHocVISO 3105 ? vboxGlobal().openMediumWithFileOpenDialog(target.mediumType, 3106 windowManager().mainWindowShown(), 3107 strMachineFolder) 3108 : vboxGlobal().createVisoMediumWithFileOpenDialog(windowManager().mainWindowShown(), 3109 strMachineFolder); 3110 /* Return focus back: */ 3111 if (pLastFocusedWidget) 3112 pLastFocusedWidget->setFocus(); 3113 /* Accept new medium ID: */ 3114 if (!strMediumID.isNull()) 3115 strNewID = strMediumID; 3116 /* Else just exit: */ 3117 else return; 3118 } 3119 /* Use medium ID which was passed: */ 3120 else if (!target.data.isNull() && target.data != strCurrentID) 3121 strNewID = target.data; 3122 3123 /* Should we mount or unmount? */ 3124 fMount = !strNewID.isEmpty(); 3125 3126 /* Prepare target medium: */ 3127 const UIMedium uimedium = vboxGlobal().medium(strNewID); 3128 cmedium = uimedium.medium(); 3129 strActualID = fMount ? strNewID : strCurrentID; 3130 break; 3131 } 3132 /* Do we have a resent location? */ 3133 case UIMediumTarget::UIMediumTargetType_WithLocation: 3134 { 3135 /* Open medium by location and get new medium ID if any: */ 3136 const QString strNewID = vboxGlobal().openMedium(target.mediumType, target.data); 3137 /* Else just exit: */ 3138 if (strNewID.isEmpty()) 3139 return; 3140 3141 /* Should we mount or unmount? */ 3142 fMount = strNewID != strCurrentID; 3143 3144 /* Prepare target medium: */ 3145 const UIMedium uimedium = fMount ? vboxGlobal().medium(strNewID) : UIMedium(); 3146 cmedium = fMount ? uimedium.medium() : CMedium(); 3147 strActualID = fMount ? strNewID : strCurrentID; 3148 break; 3149 } 3150 } 3151 3152 /* Do not unmount hard-drives: */ 3153 if (target.mediumType == UIMediumType_HardDisk && !fMount) 3154 return; 3155 3156 /* Get editable machine: */ 3157 CSession session; 3158 CMachine machine = constMachine; 3159 KSessionState sessionState = machine.GetSessionState(); 3160 /* Session state unlocked? */ 3161 if (sessionState == KSessionState_Unlocked) 3162 { 3163 /* Open own 'write' session: */ 3164 session = openSession(machine.GetId()); 3165 AssertReturnVoid(!session.isNull()); 3166 machine = session.GetMachine(); 3167 } 3168 /* Is it Selector UI call? */ 3169 else if (!isVMConsoleProcess()) 3170 { 3171 /* Open existing 'shared' session: */ 3172 session = openExistingSession(machine.GetId()); 3173 AssertReturnVoid(!session.isNull()); 3174 machine = session.GetMachine(); 3175 } 3176 /* Else this is Runtime UI call 3177 * which has session locked for itself. */ 3178 3179 /* Remount medium to the predefined port/device: */ 3180 bool fWasMounted = false; 3181 /* Hard drive case: */ 3182 if (target.mediumType == UIMediumType_HardDisk) 3183 { 3184 /* Detaching: */ 3185 machine.DetachDevice(target.name, target.port, target.device); 3186 fWasMounted = machine.isOk(); 3187 if (!fWasMounted) 3188 msgCenter().cannotDetachDevice(machine, UIMediumType_HardDisk, strCurrentLocation, 3189 StorageSlot(currentStorageBus, target.port, target.device)); 3190 else 3191 { 3192 /* Attaching: */ 3193 machine.AttachDevice(target.name, target.port, target.device, KDeviceType_HardDisk, cmedium); 3194 fWasMounted = machine.isOk(); 3195 if (!fWasMounted) 3196 msgCenter().cannotAttachDevice(machine, UIMediumType_HardDisk, strCurrentLocation, 3197 StorageSlot(currentStorageBus, target.port, target.device)); 3198 } 3199 } 3200 /* Optical/floppy drive case: */ 3201 else 3202 { 3203 /* Remounting: */ 3204 machine.MountMedium(target.name, target.port, target.device, cmedium, false /* force? */); 3205 fWasMounted = machine.isOk(); 3206 if (!fWasMounted) 3207 { 3208 /* Ask for force remounting: */ 3209 if (msgCenter().cannotRemountMedium(machine, vboxGlobal().medium(strActualID), 3210 fMount, true /* retry? */)) 3211 { 3212 /* Force remounting: */ 3213 machine.MountMedium(target.name, target.port, target.device, cmedium, true /* force? */); 3214 fWasMounted = machine.isOk(); 3215 if (!fWasMounted) 3216 msgCenter().cannotRemountMedium(machine, vboxGlobal().medium(strActualID), 3217 fMount, false /* retry? */); 3218 } 3219 } 3220 /* If mounting was successful: */ 3221 if (fWasMounted) 3222 { 3223 /* Disable First RUN Wizard: */ 3224 if (gEDataManager->machineFirstTimeStarted(machine.GetId())) 3225 gEDataManager->setMachineFirstTimeStarted(false, machine.GetId()); 3226 } 3227 } 3228 3229 /* Save settings: */ 3230 if (fWasMounted) 3231 { 3232 machine.SaveSettings(); 3233 if (!machine.isOk()) 3234 msgCenter().cannotSaveMachineSettings(machine, windowManager().mainWindowShown()); 3235 } 3236 3237 /* Close session to editable machine if necessary: */ 3238 if (!session.isNull()) 3239 session.UnlockMachine(); 3240 } 3241 3242 QString VBoxGlobal::details(const CMedium &cmedium, bool fPredictDiff, bool fUseHtml /* = true*/) 3243 { 3244 /* Search for corresponding UI medium: */ 3245 const QString strMediumID = cmedium.isNull() ? UIMedium::nullID() : cmedium.GetId(); 3246 UIMedium uimedium = medium(strMediumID); 3247 if (!cmedium.isNull() && uimedium.isNull()) 3248 { 3249 /* UI medium may be new and not among our mediums, request enumeration: */ 3250 startMediumEnumeration(); 3251 3252 /* Search for corresponding UI medium again: */ 3253 3254 uimedium = medium(strMediumID); 3255 if (uimedium.isNull()) 3256 { 3257 /* Medium might be deleted already, return null string: */ 3258 return QString(); 3259 } 3260 } 3261 3262 /* Return UI medium details: */ 3263 return fUseHtml ? uimedium.detailsHTML(true /* aNoDiffs */, fPredictDiff) : 3264 uimedium.details(true /* aNoDiffs */, fPredictDiff); 3265 } 3266 3267 #ifdef RT_OS_LINUX 3268 /* static */ 3269 void VBoxGlobal::checkForWrongUSBMounted() 3270 { 3271 /* Make sure '/proc/mounts' exists and can be opened: */ 3272 QFile file("/proc/mounts"); 3273 if (!file.exists() || !file.open(QIODevice::ReadOnly | QIODevice::Text)) 3274 return; 3275 3276 /* Fetch contents: */ 3277 QStringList contents; 3278 for (;;) 3279 { 3280 QByteArray line = file.readLine(); 3281 if (line.isEmpty()) 3282 break; 3283 contents << line; 3284 } 3285 /* Grep contents for usbfs presence: */ 3286 QStringList grep1(contents.filter("/sys/bus/usb/drivers")); 3287 QStringList grep2(grep1.filter("usbfs")); 3288 if (grep2.isEmpty()) 3289 return; 3290 3291 /* Show corresponding warning: */ 3292 msgCenter().warnAboutWrongUSBMounted(); 3293 } 3294 #endif /* RT_OS_LINUX */ 3295 3296 /** 3297 * Returns the details of the given USB device as a single-line string. 3298 */ 3299 QString VBoxGlobal::details (const CUSBDevice &aDevice) const 3300 { 3301 QString sDetails; 3302 if (aDevice.isNull()) 3303 sDetails = tr("Unknown device", "USB device details"); 3304 else 3305 { 3306 QVector<QString> devInfoVector = aDevice.GetDeviceInfo(); 3307 QString m; 3308 QString p; 3309 3310 if (devInfoVector.size() >= 1) 3311 m = devInfoVector[0].trimmed(); 3312 if (devInfoVector.size() >= 2) 3313 p = devInfoVector[1].trimmed(); 3314 3315 if (m.isEmpty() && p.isEmpty()) 3316 { 3317 sDetails = 3318 tr ("Unknown device %1:%2", "USB device details") 3319 .arg (QString().sprintf ("%04hX", aDevice.GetVendorId())) 3320 .arg (QString().sprintf ("%04hX", aDevice.GetProductId())); 3321 } 3322 else 3323 { 3324 if (p.toUpper().startsWith (m.toUpper())) 3325 sDetails = p; 3326 else 3327 sDetails = m + " " + p; 3328 } 3329 ushort r = aDevice.GetRevision(); 3330 if (r != 0) 3331 sDetails += QString().sprintf (" [%04hX]", r); 3332 } 3333 3334 return sDetails.trimmed(); 3335 } 3336 3337 /** 3338 * Returns the multi-line description of the given USB device. 3339 */ 3340 QString VBoxGlobal::toolTip (const CUSBDevice &aDevice) const 3341 { 3342 QString tip = 3343 tr ("<nobr>Vendor ID: %1</nobr><br>" 3344 "<nobr>Product ID: %2</nobr><br>" 3345 "<nobr>Revision: %3</nobr>", "USB device tooltip") 3346 .arg (QString().sprintf ("%04hX", aDevice.GetVendorId())) 3347 .arg (QString().sprintf ("%04hX", aDevice.GetProductId())) 3348 .arg (QString().sprintf ("%04hX", aDevice.GetRevision())); 3349 3350 QString ser = aDevice.GetSerialNumber(); 3351 if (!ser.isEmpty()) 3352 tip += QString (tr ("<br><nobr>Serial No. %1</nobr>", "USB device tooltip")) 3353 .arg (ser); 3354 3355 /* add the state field if it's a host USB device */ 3356 CHostUSBDevice hostDev (aDevice); 3357 if (!hostDev.isNull()) 3358 { 3359 tip += QString (tr ("<br><nobr>State: %1</nobr>", "USB device tooltip")) 3360 .arg (gpConverter->toString (hostDev.GetState())); 3361 } 3362 3363 return tip; 3364 } 3365 3366 /** 3367 * Returns the multi-line description of the given USB filter 3368 */ 3369 QString VBoxGlobal::toolTip (const CUSBDeviceFilter &aFilter) const 3370 { 3371 QString tip; 3372 3373 QString vendorId = aFilter.GetVendorId(); 3374 if (!vendorId.isEmpty()) 3375 tip += tr ("<nobr>Vendor ID: %1</nobr>", "USB filter tooltip") 3376 .arg (vendorId); 3377 3378 QString productId = aFilter.GetProductId(); 3379 if (!productId.isEmpty()) 3380 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Product ID: %2</nobr>", "USB filter tooltip") 3381 .arg (productId); 3382 3383 QString revision = aFilter.GetRevision(); 3384 if (!revision.isEmpty()) 3385 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Revision: %3</nobr>", "USB filter tooltip") 3386 .arg (revision); 3387 3388 QString product = aFilter.GetProduct(); 3389 if (!product.isEmpty()) 3390 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Product: %4</nobr>", "USB filter tooltip") 3391 .arg (product); 3392 3393 QString manufacturer = aFilter.GetManufacturer(); 3394 if (!manufacturer.isEmpty()) 3395 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Manufacturer: %5</nobr>", "USB filter tooltip") 3396 .arg (manufacturer); 3397 3398 QString serial = aFilter.GetSerialNumber(); 3399 if (!serial.isEmpty()) 3400 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Serial No.: %1</nobr>", "USB filter tooltip") 3401 .arg (serial); 3402 3403 QString port = aFilter.GetPort(); 3404 if (!port.isEmpty()) 3405 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Port: %1</nobr>", "USB filter tooltip") 3406 .arg (port); 3407 3408 /* add the state field if it's a host USB device */ 3409 CHostUSBDevice hostDev (aFilter); 3410 if (!hostDev.isNull()) 3411 { 3412 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>State: %1</nobr>", "USB filter tooltip") 3413 .arg (gpConverter->toString (hostDev.GetState())); 3414 } 3415 3416 return tip; 3417 } 3418 3419 /** Returns the multi-line description of the given CHostVideoInputDevice filter. */ 3420 QString VBoxGlobal::toolTip(const CHostVideoInputDevice &webcam) const 3421 { 3422 QStringList records; 3423 3424 QString strName = webcam.GetName(); 3425 if (!strName.isEmpty()) 3426 records << strName; 3427 3428 QString strPath = webcam.GetPath(); 3429 if (!strPath.isEmpty()) 3430 records << strPath; 3431 3432 return records.join("<br>"); 3433 } 3458 3434 3459 3435 /* static */ … … 3545 3521 } 3546 3522 3547 // Public slots 3548 //////////////////////////////////////////////////////////////////////////////// 3523 /** 3524 * Inner worker that for lazily querying for 3D support. 3525 * 3526 * Rational is that when starting a text mode guest (like DOS) that does not 3527 * have 3D enabled, don't wast the developer's or user's time on launching the 3528 * test application when starting the VM or editing it's settings. 3529 * 3530 * @returns true / false. 3531 * @note If we ever end up checking this concurrently on multiple threads, use a 3532 * RTONCE construct to serialize the efforts. 3533 */ 3534 bool VBoxGlobal::is3DAvailableWorker() const 3535 { 3536 #ifdef VBOX_WITH_CROGL 3537 bool fSupported = VBoxOglIs3DAccelerationSupported(); 3538 #else 3539 bool fSupported = false; 3540 #endif 3541 unconst(this)->m3DAvailable = fSupported; 3542 return fSupported; 3543 } 3544 3545 #ifdef VBOX_WITH_CRHGSMI 3546 /* static */ 3547 bool VBoxGlobal::isWddmCompatibleOsType(const QString &strGuestOSTypeId) 3548 { 3549 return strGuestOSTypeId.startsWith("WindowsVista") 3550 || strGuestOSTypeId.startsWith("Windows7") 3551 || strGuestOSTypeId.startsWith("Windows8") 3552 || strGuestOSTypeId.startsWith("Windows81") 3553 || strGuestOSTypeId.startsWith("Windows10") 3554 || strGuestOSTypeId.startsWith("Windows2008") 3555 || strGuestOSTypeId.startsWith("Windows2012"); 3556 } 3557 #endif /* VBOX_WITH_CRHGSMI */ 3558 3559 /** 3560 * Returns the required video memory in bytes for the current desktop 3561 * resolution at maximum possible screen depth in bpp. 3562 */ 3563 /* static */ 3564 quint64 VBoxGlobal::requiredVideoMemory(const QString &strGuestOSTypeId, int cMonitors /* = 1 */) 3565 { 3566 /* We create a list of the size of all available host monitors. This list 3567 * is sorted by value and by starting with the biggest one, we calculate 3568 * the memory requirements for every guest screen. This is of course not 3569 * correct, but as we can't predict on which host screens the user will 3570 * open the guest windows, this is the best assumption we can do, cause it 3571 * is the worst case. */ 3572 const int cHostScreens = gpDesktop->screenCount(); 3573 QVector<int> screenSize(qMax(cMonitors, cHostScreens), 0); 3574 for (int i = 0; i < cHostScreens; ++i) 3575 { 3576 QRect r = gpDesktop->screenGeometry(i); 3577 screenSize[i] = r.width() * r.height(); 3578 } 3579 /* Now sort the vector */ 3580 qSort(screenSize.begin(), screenSize.end(), qGreater<int>()); 3581 /* For the case that there are more guest screens configured then host 3582 * screens available, replace all zeros with the greatest value in the 3583 * vector. */ 3584 for (int i = 0; i < screenSize.size(); ++i) 3585 if (screenSize.at(i) == 0) 3586 screenSize.replace(i, screenSize.at(0)); 3587 3588 quint64 needBits = 0; 3589 for (int i = 0; i < cMonitors; ++i) 3590 { 3591 /* Calculate summary required memory amount in bits */ 3592 needBits += (screenSize.at(i) * /* with x height */ 3593 32 + /* we will take the maximum possible bpp for now */ 3594 8 * _1M) + /* current cache per screen - may be changed in future */ 3595 8 * 4096; /* adapter info */ 3596 } 3597 /* Translate value into megabytes with rounding to highest side */ 3598 quint64 needMBytes = needBits % (8 * _1M) ? needBits / (8 * _1M) + 1 : 3599 needBits / (8 * _1M) /* convert to megabytes */; 3600 3601 if (strGuestOSTypeId.startsWith("Windows")) 3602 { 3603 /* Windows guests need offscreen VRAM too for graphics acceleration features: */ 3604 #ifdef VBOX_WITH_CRHGSMI 3605 if (isWddmCompatibleOsType(strGuestOSTypeId)) 3606 { 3607 /* wddm mode, there are two surfaces for each screen: shadow & primary */ 3608 needMBytes *= 3; 3609 } 3610 else 3611 #endif /* VBOX_WITH_CRHGSMI */ 3612 { 3613 needMBytes *= 2; 3614 } 3615 } 3616 3617 return needMBytes * _1M; 3618 } 3619 3620 QIcon VBoxGlobal::vmUserIcon(const CMachine &comMachine) const 3621 { 3622 /* Prepare fallback icon: */ 3623 static QIcon nullIcon; 3624 3625 /* Make sure general icon-pool initialized: */ 3626 AssertReturn(m_pIconPool, nullIcon); 3627 3628 /* Redirect to general icon-pool: */ 3629 return m_pIconPool->userMachineIcon(comMachine); 3630 } 3631 3632 QPixmap VBoxGlobal::vmUserPixmap(const CMachine &comMachine, const QSize &size) const 3633 { 3634 /* Prepare fallback pixmap: */ 3635 static QPixmap nullPixmap; 3636 3637 /* Make sure general icon-pool initialized: */ 3638 AssertReturn(m_pIconPool, nullPixmap); 3639 3640 /* Redirect to general icon-pool: */ 3641 return m_pIconPool->userMachinePixmap(comMachine, size); 3642 } 3643 3644 QPixmap VBoxGlobal::vmUserPixmapDefault(const CMachine &comMachine, QSize *pLogicalSize /* = 0 */) const 3645 { 3646 /* Prepare fallback pixmap: */ 3647 static QPixmap nullPixmap; 3648 3649 /* Make sure general icon-pool initialized: */ 3650 AssertReturn(m_pIconPool, nullPixmap); 3651 3652 /* Redirect to general icon-pool: */ 3653 return m_pIconPool->userMachinePixmapDefault(comMachine, pLogicalSize); 3654 } 3655 3656 QIcon VBoxGlobal::vmGuestOSTypeIcon(const QString &strOSTypeID) const 3657 { 3658 /* Prepare fallback icon: */ 3659 static QIcon nullIcon; 3660 3661 /* Make sure general icon-pool initialized: */ 3662 AssertReturn(m_pIconPool, nullIcon); 3663 3664 /* Redirect to general icon-pool: */ 3665 return m_pIconPool->guestOSTypeIcon(strOSTypeID); 3666 } 3667 3668 QPixmap VBoxGlobal::vmGuestOSTypePixmap(const QString &strOSTypeID, const QSize &size) const 3669 { 3670 /* Prepare fallback pixmap: */ 3671 static QPixmap nullPixmap; 3672 3673 /* Make sure general icon-pool initialized: */ 3674 AssertReturn(m_pIconPool, nullPixmap); 3675 3676 /* Redirect to general icon-pool: */ 3677 return m_pIconPool->guestOSTypePixmap(strOSTypeID, size); 3678 } 3679 3680 QPixmap VBoxGlobal::vmGuestOSTypePixmapDefault(const QString &strOSTypeID, QSize *pLogicalSize /* = 0 */) const 3681 { 3682 /* Prepare fallback pixmap: */ 3683 static QPixmap nullPixmap; 3684 3685 /* Make sure general icon-pool initialized: */ 3686 AssertReturn(m_pIconPool, nullPixmap); 3687 3688 /* Redirect to general icon-pool: */ 3689 return m_pIconPool->guestOSTypePixmapDefault(strOSTypeID, pLogicalSize); 3690 } 3691 3692 /** 3693 * Joins two pixmaps horizontally with 2px space between them and returns the 3694 * result. 3695 * 3696 * @param aPM1 Left pixmap. 3697 * @param aPM2 Right pixmap. 3698 */ 3699 /* static */ 3700 QPixmap VBoxGlobal::joinPixmaps (const QPixmap &aPM1, const QPixmap &aPM2) 3701 { 3702 if (aPM1.isNull()) 3703 return aPM2; 3704 if (aPM2.isNull()) 3705 return aPM1; 3706 3707 QPixmap result (aPM1.width() + aPM2.width() + 2, 3708 qMax (aPM1.height(), aPM2.height())); 3709 result.fill (Qt::transparent); 3710 3711 QPainter painter (&result); 3712 painter.drawPixmap (0, 0, aPM1); 3713 painter.drawPixmap (aPM1.width() + 2, result.height() - aPM2.height(), aPM2); 3714 painter.end(); 3715 3716 return result; 3717 } 3718 3719 /** 3720 * Replacement for QToolButton::setTextLabel() that handles the shortcut 3721 * letter (if it is present in the argument string) as if it were a setText() 3722 * call: the shortcut letter is used to automatically assign an "Alt+<letter>" 3723 * accelerator key sequence to the given tool button. 3724 * 3725 * @note This method preserves the icon set if it was assigned before. Only 3726 * the text label and the accelerator are changed. 3727 * 3728 * @param aToolButton Tool button to set the text label on. 3729 * @param aTextLabel Text label to set. 3730 */ 3731 /* static */ 3732 void VBoxGlobal::setTextLabel (QToolButton *aToolButton, 3733 const QString &aTextLabel) 3734 { 3735 AssertReturnVoid (aToolButton != NULL); 3736 3737 /* remember the icon set as setText() will kill it */ 3738 QIcon iset = aToolButton->icon(); 3739 /* re-use the setText() method to detect and set the accelerator */ 3740 aToolButton->setText (aTextLabel); 3741 QKeySequence accel = aToolButton->shortcut(); 3742 aToolButton->setText (aTextLabel); 3743 aToolButton->setIcon (iset); 3744 /* set the accel last as setIconSet() would kill it */ 3745 aToolButton->setShortcut (accel); 3746 } 3747 3748 /** 3749 * Puts soft hyphens after every path component in the given file name. 3750 * 3751 * @param aFileName File name (must be a full path name). 3752 */ 3753 /* static */ 3754 QString VBoxGlobal::locationForHTML (const QString &aFileName) 3755 { 3756 /// @todo (dmik) remove? 3757 // QString result = QDir::toNativeSeparators (fn); 3758 //#ifdef Q_OS_LINUX 3759 // result.replace ('/', "/<font color=red>­</font>"); 3760 //#else 3761 // result.replace ('\\', "\\<font color=red>­</font>"); 3762 //#endif 3763 // return result; 3764 QFileInfo fi (aFileName); 3765 return fi.fileName(); 3766 } 3767 3768 /** 3769 * Searches for a widget that with @a aName (if it is not NULL) which inherits 3770 * @a aClassName (if it is not NULL) and among children of @a aParent. If @a 3771 * aParent is NULL, all top-level widgets are searched. If @a aRecursive is 3772 * true, child widgets are recursively searched as well. 3773 */ 3774 /* static */ 3775 QWidget *VBoxGlobal::findWidget (QWidget *aParent, const char *aName, 3776 const char *aClassName /* = NULL */, 3777 bool aRecursive /* = false */) 3778 { 3779 if (aParent == NULL) 3780 { 3781 QWidgetList list = QApplication::topLevelWidgets(); 3782 foreach(QWidget *w, list) 3783 { 3784 if ((!aName || strcmp (w->objectName().toLatin1().constData(), aName) == 0) && 3785 (!aClassName || strcmp (w->metaObject()->className(), aClassName) == 0)) 3786 return w; 3787 if (aRecursive) 3788 { 3789 w = findWidget (w, aName, aClassName, aRecursive); 3790 if (w) 3791 return w; 3792 } 3793 } 3794 return NULL; 3795 } 3796 3797 /* Find the first children of aParent with the appropriate properties. 3798 * Please note that this call is recursively. */ 3799 QList<QWidget *> list = aParent->findChildren<QWidget*>(aName); 3800 foreach(QWidget *child, list) 3801 { 3802 if (!aClassName || strcmp (child->metaObject()->className(), aClassName) == 0) 3803 return child; 3804 } 3805 return NULL; 3806 } 3549 3807 3550 3808 /** … … 3639 3897 } 3640 3898 3641 // Protected members3642 ////////////////////////////////////////////////////////////////////////////////3643 3644 3899 bool VBoxGlobal::eventFilter (QObject *aObject, QEvent *aEvent) 3645 3900 { … … 3663 3918 } 3664 3919 3665 #ifdef VBOX_WITH_DEBUGGER_GUI 3666 3667 bool VBoxGlobal::isDebuggerEnabled() const 3668 { 3669 return isDebuggerWorker(&m_fDbgEnabled, GUI_Dbg_Enabled); 3670 } 3671 3672 bool VBoxGlobal::isDebuggerAutoShowEnabled() const 3673 { 3674 return isDebuggerWorker(&m_fDbgAutoShow, GUI_Dbg_AutoShow); 3675 } 3676 3677 bool VBoxGlobal::isDebuggerAutoShowCommandLineEnabled() const 3678 { 3679 return isDebuggerWorker(&m_fDbgAutoShowCommandLine, GUI_Dbg_AutoShow); 3680 } 3681 3682 bool VBoxGlobal::isDebuggerAutoShowStatisticsEnabled() const 3683 { 3684 return isDebuggerWorker(&m_fDbgAutoShowStatistics, GUI_Dbg_AutoShow); 3685 } 3686 3687 #endif /* VBOX_WITH_DEBUGGER_GUI */ 3688 3689 // Private members 3690 //////////////////////////////////////////////////////////////////////////////// 3691 3692 bool VBoxGlobal::processArgs() 3693 { 3694 bool fResult = false; 3695 QStringList args = qApp->arguments(); 3696 QList<QUrl> list; 3697 for (int i = 1; i < args.size(); ++i) 3698 { 3699 /* We break out after the first parameter, cause there could be 3700 parameters with arguments (e.g. --comment comment). */ 3701 if (args.at(i).startsWith("-")) 3702 break; 3703 #ifdef VBOX_WS_MAC 3704 QString strArg = ::darwinResolveAlias(args.at(i)); 3705 #else /* VBOX_WS_MAC */ 3706 QString strArg = args.at(i); 3707 #endif /* !VBOX_WS_MAC */ 3708 if ( !strArg.isEmpty() 3709 && QFile::exists(strArg)) 3710 list << QUrl::fromLocalFile(strArg); 3711 } 3712 if (!list.isEmpty()) 3713 { 3714 for (int i = 0; i < list.size(); ++i) 3715 { 3716 const QString& strFile = list.at(i).toLocalFile(); 3717 if (VBoxGlobal::hasAllowedExtension(strFile, VBoxFileExts)) 3718 { 3719 CVirtualBox vbox = virtualBox(); 3720 CMachine machine = vbox.FindMachine(strFile); 3721 if (!machine.isNull()) 3722 { 3723 fResult = true; 3724 launchMachine(machine); 3725 /* Remove from the arg list. */ 3726 list.removeAll(strFile); 3727 } 3728 } 3729 } 3730 } 3731 if (!list.isEmpty()) 3732 { 3733 /* Store the URLs: */ 3734 m_ArgUrlList = list; 3735 /* Ask UIStarter to open them: */ 3736 emit sigAskToOpenURLs(); 3737 } 3738 return fResult; 3920 /** 3921 * Changes the language of all global string constants according to the 3922 * currently installed translations tables. 3923 */ 3924 void VBoxGlobal::retranslateUi() 3925 { 3926 mUserDefinedPortName = tr ("User-defined", "serial port"); 3927 3928 mWarningIcon = UIIconPool::defaultIcon(UIIconPool::UIDefaultIconType_MessageBoxWarning).pixmap (16, 16); 3929 Assert (!mWarningIcon.isNull()); 3930 3931 mErrorIcon = UIIconPool::defaultIcon(UIIconPool::UIDefaultIconType_MessageBoxCritical).pixmap (16, 16); 3932 Assert (!mErrorIcon.isNull()); 3933 3934 /* Re-enumerate uimedium since they contain some translations too: */ 3935 if (mValid) 3936 startMediumEnumeration(); 3937 3938 #ifdef VBOX_WS_X11 3939 /* As X11 do not have functionality for providing human readable key names, 3940 * we keep a table of them, which must be updated when the language is changed. */ 3941 UINativeHotKey::retranslateKeyNames(); 3942 #endif /* VBOX_WS_X11 */ 3739 3943 } 3740 3944 … … 4225 4429 } 4226 4430 4227 #ifdef VBOX_WS_WIN4228 /* static */4229 BOOL VBoxGlobal::ShutdownBlockReasonCreateAPI(HWND hWnd, LPCWSTR pwszReason)4230 {4231 BOOL fResult = FALSE;4232 typedef BOOL(WINAPI *PFNSHUTDOWNBLOCKREASONCREATE)(HWND hWnd, LPCWSTR pwszReason);4233 4234 PFNSHUTDOWNBLOCKREASONCREATE pfn = (PFNSHUTDOWNBLOCKREASONCREATE)GetProcAddress(4235 GetModuleHandle(L"User32.dll"), "ShutdownBlockReasonCreate");4236 _ASSERTE(pfn);4237 if (pfn)4238 fResult = pfn(hWnd, pwszReason);4239 return fResult;4240 }4241 #endif4242 4243 4431 void VBoxGlobal::sltHandleCommitDataRequest(QSessionManager &manager) 4244 4432 { … … 4320 4508 } 4321 4509 4322 void VBoxGlobal::comWrappersReinit() 4323 { 4324 /* Re-fetch corresponding objects/values: */ 4325 m_host = virtualBox().GetHost(); 4326 m_strHomeFolder = virtualBox().GetHomeFolder(); 4327 4328 /* Re-initialize guest OS Type list: */ 4329 m_guestOSFamilyIDs.clear(); 4330 m_guestOSTypes.clear(); 4331 const CGuestOSTypeVector guestOSTypes = m_vbox.GetGuestOSTypes(); 4332 const int cGuestOSTypeCount = guestOSTypes.size(); 4333 AssertMsg(cGuestOSTypeCount > 0, ("Number of OS types must not be zero")); 4334 if (cGuestOSTypeCount > 0) 4335 { 4336 /* Here we ASSUME the 'Other' types are always the first, 4337 * so we remember them and will append them to the list when finished. 4338 * We do a two pass, first adding the specific types, then the two 'Other' types. */ 4339 for (int j = 0; j < 2; ++j) 4340 { 4341 int cMax = j == 0 ? cGuestOSTypeCount : RT_MIN(2, cGuestOSTypeCount); 4342 for (int i = j == 0 ? 2 : 0; i < cMax; ++i) 4343 { 4344 const CGuestOSType os = guestOSTypes.at(i); 4345 const QString strFamilyID = os.GetFamilyId(); 4346 if (!m_guestOSFamilyIDs.contains(strFamilyID)) 4347 { 4348 m_guestOSFamilyIDs << strFamilyID; 4349 m_guestOSTypes << QList<CGuestOSType>(); 4350 } 4351 m_guestOSTypes[m_guestOSFamilyIDs.indexOf(strFamilyID)].append(os); 4352 } 4353 } 4354 } 4355 4356 /* Mark wrappers valid: */ 4357 m_fWrappersValid = true; 4358 } 4510 #ifdef VBOX_WS_WIN 4511 /* static */ 4512 BOOL VBoxGlobal::ShutdownBlockReasonCreateAPI(HWND hWnd, LPCWSTR pwszReason) 4513 { 4514 BOOL fResult = FALSE; 4515 typedef BOOL(WINAPI *PFNSHUTDOWNBLOCKREASONCREATE)(HWND hWnd, LPCWSTR pwszReason); 4516 4517 PFNSHUTDOWNBLOCKREASONCREATE pfn = (PFNSHUTDOWNBLOCKREASONCREATE)GetProcAddress( 4518 GetModuleHandle(L"User32.dll"), "ShutdownBlockReasonCreate"); 4519 _ASSERTE(pfn); 4520 if (pfn) 4521 fResult = pfn(hWnd, pwszReason); 4522 return fResult; 4523 } 4524 #endif 4359 4525 4360 4526 #ifdef VBOX_WITH_DEBUGGER_GUI … … 4471 4637 #endif /* VBOX_WITH_DEBUGGER_GUI */ 4472 4638 4473 bool VBoxGlobal::switchToMachine(CMachine &machine) 4474 { 4475 #ifdef VBOX_WS_MAC 4476 ULONG64 id = machine.ShowConsoleWindow(); 4477 #else 4478 WId id = (WId) machine.ShowConsoleWindow(); 4479 #endif 4480 AssertWrapperOk(machine); 4481 if (!machine.isOk()) 4482 return false; 4483 4484 /* winId = 0 it means the console window has already done everything 4485 * necessary to implement the "show window" semantics. */ 4486 if (id == 0) 4487 return true; 4488 4489 #if defined(VBOX_WS_WIN) || defined(VBOX_WS_X11) 4490 4491 return vboxGlobal().activateWindow(id, true); 4492 4493 #elif defined(VBOX_WS_MAC) 4494 /* 4495 * This is just for the case were the other process cannot steal 4496 * the focus from us. It will send us a PSN so we can try. 4497 */ 4498 ProcessSerialNumber psn; 4499 psn.highLongOfPSN = id >> 32; 4500 psn.lowLongOfPSN = (UInt32)id; 4501 # ifdef __clang__ 4502 # pragma GCC diagnostic push 4503 # pragma GCC diagnostic ignored "-Wdeprecated-declarations" 4504 OSErr rc = ::SetFrontProcess(&psn); 4505 # pragma GCC diagnostic pop 4506 # else 4507 OSErr rc = ::SetFrontProcess(&psn); 4508 # endif 4509 if (!rc) 4510 Log(("GUI: %#RX64 couldn't do SetFrontProcess on itself, the selector (we) had to do it...\n", id)); 4511 else 4512 Log(("GUI: Failed to bring %#RX64 to front. rc=%#x\n", id, rc)); 4513 return !rc; 4514 4515 #else 4516 4517 return false; 4518 4519 #endif 4520 4521 4522 /// @todo Below is the old method of switching to the console window 4523 // based on the process ID of the console process. It should go away 4524 // after the new (callback-based) method is fully tested. 4525 #if 0 4526 4527 if (!canSwitchTo()) 4528 return false; 4529 4530 #if defined (VBOX_WS_WIN) 4531 4532 HWND hwnd = mWinId; 4533 4534 /* if there are blockers (modal and modeless dialogs, etc), find the 4535 * topmost one */ 4536 HWND hwndAbove = NULL; 4537 do 4538 { 4539 hwndAbove = GetNextWindow(hwnd, GW_HWNDPREV); 4540 HWND hwndOwner; 4541 if (hwndAbove != NULL && 4542 ((hwndOwner = GetWindow(hwndAbove, GW_OWNER)) == hwnd || 4543 hwndOwner == hwndAbove)) 4544 hwnd = hwndAbove; 4545 else 4546 break; 4547 } 4548 while (1); 4549 4550 /* first, check that the primary window is visible */ 4551 if (IsIconic(mWinId)) 4552 ShowWindow(mWinId, SW_RESTORE); 4553 else if (!IsWindowVisible(mWinId)) 4554 ShowWindow(mWinId, SW_SHOW); 4555 4556 #if 0 4557 LogFlowFunc(("mWinId=%08X hwnd=%08X\n", mWinId, hwnd)); 4558 #endif 4559 4560 /* then, activate the topmost in the group */ 4561 AllowSetForegroundWindow(m_pid); 4562 SetForegroundWindow(hwnd); 4563 4564 return true; 4565 4566 #elif defined (VBOX_WS_X11) 4567 4568 return false; 4569 4570 #elif defined (VBOX_WS_MAC) 4571 4572 ProcessSerialNumber psn; 4573 OSStatus rc = ::GetProcessForPID(m_pid, &psn); 4574 if (!rc) 4575 { 4576 rc = ::SetFrontProcess(&psn); 4577 4578 if (!rc) 4579 { 4580 ShowHideProcess(&psn, true); 4581 return true; 4582 } 4583 } 4584 return false; 4585 4586 #else 4587 4588 return false; 4589 4590 #endif 4591 4592 #endif 4593 } 4594 4595 bool VBoxGlobal::launchMachine(CMachine &machine, LaunchMode enmLaunchMode /* = LaunchMode_Default */) 4596 { 4597 /* Switch to machine window(s) if possible: */ 4598 if ( machine.GetSessionState() == KSessionState_Locked /* precondition for CanShowConsoleWindow() */ 4599 && machine.CanShowConsoleWindow()) 4600 { 4601 /* For the Selector UI: */ 4602 if (!isVMConsoleProcess()) 4603 { 4604 /* Just switch to existing VM window: */ 4605 return VBoxGlobal::switchToMachine(machine); 4606 } 4607 /* For the Runtime UI: */ 4608 else 4609 { 4610 /* Only separate UI process can reach that place, 4611 * switch to existing VM window and exit. */ 4612 VBoxGlobal::switchToMachine(machine); 4613 return false; 4614 } 4615 } 4616 4617 if (enmLaunchMode != LaunchMode_Separate) 4618 { 4619 /* Make sure machine-state is one of required: */ 4620 KMachineState state = machine.GetState(); NOREF(state); 4621 AssertMsg( state == KMachineState_PoweredOff 4622 || state == KMachineState_Saved 4623 || state == KMachineState_Teleported 4624 || state == KMachineState_Aborted 4625 , ("Machine must be PoweredOff/Saved/Teleported/Aborted (%d)", state)); 4626 } 4627 4628 /* Create empty session instance: */ 4629 CSession session; 4630 session.createInstance(CLSID_Session); 4631 if (session.isNull()) 4632 { 4633 msgCenter().cannotOpenSession(session); 4634 return false; 4635 } 4636 4637 /* Configure environment: */ 4638 QString strEnv; 4639 #ifdef Q_OS_WIN 4640 /* Allow started VM process to be foreground window: */ 4641 AllowSetForegroundWindow(ASFW_ANY); 4642 #endif /* Q_OS_WIN */ 4643 #ifdef VBOX_WS_X11 4644 /* Make sure VM process will start on the same display as the VM selector: */ 4645 const char *pDisplay = RTEnvGet("DISPLAY"); 4646 if (pDisplay) 4647 strEnv.append(QString("DISPLAY=%1\n").arg(pDisplay)); 4648 const char *pXauth = RTEnvGet("XAUTHORITY"); 4649 if (pXauth) 4650 strEnv.append(QString("XAUTHORITY=%1\n").arg(pXauth)); 4651 #endif /* VBOX_WS_X11 */ 4652 QString strType; 4653 switch (enmLaunchMode) 4654 { 4655 case LaunchMode_Default: strType = ""; break; 4656 case LaunchMode_Separate: strType = vboxGlobal().isSeparateProcess() ? "headless" : "separate"; break; 4657 case LaunchMode_Headless: strType = "headless"; break; 4658 default: AssertFailedReturn(false); 4659 } 4660 4661 /* Prepare "VM spawning" progress: */ 4662 CProgress progress = machine.LaunchVMProcess(session, strType, strEnv); 4663 if (!machine.isOk()) 4664 { 4665 /* If the VM is started separately and the VM process is already running, then it is OK. */ 4666 if (enmLaunchMode == LaunchMode_Separate) 4667 { 4668 KMachineState state = machine.GetState(); 4669 if ( state >= KMachineState_FirstOnline 4670 && state <= KMachineState_LastOnline) 4639 void VBoxGlobal::comWrappersReinit() 4640 { 4641 /* Re-fetch corresponding objects/values: */ 4642 m_host = virtualBox().GetHost(); 4643 m_strHomeFolder = virtualBox().GetHomeFolder(); 4644 4645 /* Re-initialize guest OS Type list: */ 4646 m_guestOSFamilyIDs.clear(); 4647 m_guestOSTypes.clear(); 4648 const CGuestOSTypeVector guestOSTypes = m_vbox.GetGuestOSTypes(); 4649 const int cGuestOSTypeCount = guestOSTypes.size(); 4650 AssertMsg(cGuestOSTypeCount > 0, ("Number of OS types must not be zero")); 4651 if (cGuestOSTypeCount > 0) 4652 { 4653 /* Here we ASSUME the 'Other' types are always the first, 4654 * so we remember them and will append them to the list when finished. 4655 * We do a two pass, first adding the specific types, then the two 'Other' types. */ 4656 for (int j = 0; j < 2; ++j) 4657 { 4658 int cMax = j == 0 ? cGuestOSTypeCount : RT_MIN(2, cGuestOSTypeCount); 4659 for (int i = j == 0 ? 2 : 0; i < cMax; ++i) 4671 4660 { 4672 /* Already running. */ 4673 return true; 4661 const CGuestOSType os = guestOSTypes.at(i); 4662 const QString strFamilyID = os.GetFamilyId(); 4663 if (!m_guestOSFamilyIDs.contains(strFamilyID)) 4664 { 4665 m_guestOSFamilyIDs << strFamilyID; 4666 m_guestOSTypes << QList<CGuestOSType>(); 4667 } 4668 m_guestOSTypes[m_guestOSFamilyIDs.indexOf(strFamilyID)].append(os); 4674 4669 } 4675 4670 } 4676 4677 msgCenter().cannotOpenSession(machine); 4678 return false; 4679 } 4680 4681 /* Postpone showing "VM spawning" progress. 4682 * Hope 1 minute will be enough to spawn any running VM silently, 4683 * otherwise we better show the progress... 4684 * If starting separately, then show the progress now. */ 4685 int iSpawningDuration = enmLaunchMode == LaunchMode_Separate ? 0 : 60000; 4686 msgCenter().showModalProgressDialog(progress, machine.GetName(), 4687 ":/progress_start_90px.png", 0, iSpawningDuration); 4688 if (!progress.isOk() || progress.GetResultCode() != 0) 4689 msgCenter().cannotOpenSession(progress, machine.GetName()); 4690 4691 /* Unlock machine, close session: */ 4692 session.UnlockMachine(); 4693 4694 /* True finally: */ 4695 return true; 4696 } 4697 4671 } 4672 4673 /* Mark wrappers valid: */ 4674 m_fWrappersValid = true; 4675 } -
trunk/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.h
r72389 r72413 63 63 Q_OBJECT 64 64 65 signals: 66 67 /** Asks listener to commit data. */ 68 void sigAskToCommitData(); 69 70 /** Asks listener to open URLs. */ 71 void sigAskToOpenURLs(); 72 73 /** Asks listener to recreate UI. */ 74 void sigAskToRestartUI(); 75 76 /** Notifies listeners about the VBoxSVC availability change. */ 77 void sigVBoxSVCAvailabilityChange(); 78 79 /* Notifiers: Medium-processing stuff: */ 80 void sigMediumCreated(const QString &strMediumID); 81 void sigMediumDeleted(const QString &strMediumID); 82 83 /* Notifiers: Medium-enumeration stuff: */ 84 void sigMediumEnumerationStarted(); 85 void sigMediumEnumerated(const QString &strMediumID); 86 void sigMediumEnumerationFinished(); 87 65 88 public: 66 89 … … 100 123 static void destroy(); 101 124 102 bool isValid() { return mValid; }103 125 bool isCleaningUp() { return s_fCleanupInProgress; } 104 126 … … 108 130 static uint qtCTVersion(); 109 131 132 bool isValid() { return mValid; } 133 110 134 QString vboxVersionString() const; 111 135 QString vboxVersionStringNormalized() const; 136 bool isBeta() const; 112 137 113 138 QString versionString() const { return mVerString; } 114 bool isBeta() const;115 116 /** Returns whether GUI is separate (from VM) process. */117 bool isSeparateProcess() const { return m_fSeparateProcess; }118 139 119 140 #ifdef VBOX_WS_MAC … … 123 144 MacOSXRelease osRelease() const { return m_osRelease; } 124 145 #endif /* VBOX_WS_MAC */ 146 147 #ifdef VBOX_WS_X11 148 /** X11: Returns whether the Window Manager we are running at is composition one. */ 149 bool isCompositingManagerRunning() const { return m_fCompositingManagerRunning; } 150 /** X11: Returns the type of the Window Manager we are running under. */ 151 X11WMType typeOfWindowManager() const { return m_enmWindowManagerType; } 152 #endif /* VBOX_WS_X11 */ 153 154 /* branding */ 155 bool brandingIsActive (bool aForce = false); 156 QString brandingGetKey (QString aKey); 157 158 static bool hasAllowedExtension(const QString &strExt, const QStringList &extList) 159 { 160 for (int i = 0; i < extList.size(); ++i) 161 if (strExt.endsWith(extList.at(i), Qt::CaseInsensitive)) 162 return true; 163 return false; 164 } 165 166 bool processArgs(); 167 168 QList<QUrl> &argUrlList() { return m_ArgUrlList; } 169 170 QString managedVMUuid() const { return vmUuid; } 171 bool isVMConsoleProcess() const { return !vmUuid.isNull(); } 172 /** Returns whether GUI is separate (from VM) process. */ 173 bool isSeparateProcess() const { return m_fSeparateProcess; } 174 bool showStartVMErrors() const { return mShowStartVMErrors; } 175 176 bool agressiveCaching() const { return mAgressiveCaching; } 177 178 /** Returns whether we should restore current snapshot before VM started. */ 179 bool shouldRestoreCurrentSnapshot() const { return mRestoreCurrentSnapshot; } 180 /** Defines whether we should fRestore current snapshot before VM started. */ 181 void setShouldRestoreCurrentSnapshot(bool fRestore) { mRestoreCurrentSnapshot = fRestore; } 182 183 bool hasFloppyImageToMount() const { return !m_strFloppyImage.isEmpty(); } 184 bool hasDvdImageToMount() const { return !m_strDvdImage.isEmpty(); } 185 QString const &getFloppyImage() const { return m_strFloppyImage; } 186 QString const &getDvdImage() const { return m_strDvdImage; } 187 188 bool isPatmDisabled() const { return mDisablePatm; } 189 bool isCsamDisabled() const { return mDisableCsam; } 190 bool isSupervisorCodeExecedRecompiled() const { return mRecompileSupervisor; } 191 bool isUserCodeExecedRecompiled() const { return mRecompileUser; } 192 bool areWeToExecuteAllInIem() const { return mExecuteAllInIem; } 193 bool isDefaultWarpPct() const { return mWarpPct == 100; } 194 uint32_t getWarpPct() const { return mWarpPct; } 195 196 #ifdef VBOX_WITH_DEBUGGER_GUI 197 bool isDebuggerEnabled() const; 198 bool isDebuggerAutoShowEnabled() const; 199 bool isDebuggerAutoShowCommandLineEnabled() const; 200 bool isDebuggerAutoShowStatisticsEnabled() const; 201 202 RTLDRMOD getDebuggerModule() const { return m_hVBoxDbg; } 203 #endif /* VBOX_WITH_DEBUGGER_GUI */ 204 205 bool shouldStartPaused() const 206 { 207 #ifdef VBOX_WITH_DEBUGGER_GUI 208 return m_enmStartRunning == StartRunning_Default ? isDebuggerAutoShowEnabled() : m_enmStartRunning == StartRunning_No; 209 #else 210 return false; 211 #endif 212 } 213 214 #ifdef VBOX_GUI_WITH_PIDFILE 215 void createPidfile(); 216 void deletePidfile(); 217 #endif 218 219 QString languageName() const; 220 QString languageCountry() const; 221 QString languageNameEnglish() const; 222 QString languageCountryEnglish() const; 223 QString languageTranslators() const; 224 225 /** Returns VBox language sub-directory. */ 226 static QString vboxLanguageSubDirectory(); 227 /** Returns VBox language file-base. */ 228 static QString vboxLanguageFileBase(); 229 /** Returns VBox language file-extension. */ 230 static QString vboxLanguageFileExtension(); 231 /** Returns VBox language ID reg-exp. */ 232 static QString vboxLanguageIdRegExp(); 233 /** Returns built in language name. */ 234 static QString vboxBuiltInLanguageName(); 235 236 static QString languageId(); 237 static QString systemLanguageId(); 238 239 static void loadLanguage (const QString &aLangId = QString::null); 240 241 static inline QString yearsToString (uint32_t cVal) 242 { 243 return tr("%n year(s)", "", cVal); 244 } 245 246 static inline QString monthsToString (uint32_t cVal) 247 { 248 return tr("%n month(s)", "", cVal); 249 } 250 251 static inline QString daysToString (uint32_t cVal) 252 { 253 return tr("%n day(s)", "", cVal); 254 } 255 256 static inline QString hoursToString (uint32_t cVal) 257 { 258 return tr("%n hour(s)", "", cVal); 259 } 260 261 static inline QString minutesToString (uint32_t cVal) 262 { 263 return tr("%n minute(s)", "", cVal); 264 } 265 266 static inline QString secondsToString (uint32_t cVal) 267 { 268 return tr("%n second(s)", "", cVal); 269 } 270 271 static QChar decimalSep(); 272 static QString sizeRegexp(); 273 274 static quint64 parseSize (const QString &); 275 static QString formatSize (quint64 aSize, uint aDecimal = 2, FormatSize aMode = FormatSize_Round); 276 277 /* Returns full medium-format name for the given base medium-format name: */ 278 static QString fullMediumFormatName(const QString &strBaseMediumFormatName); 279 280 QStringList COMPortNames() const; 281 QString toCOMPortName (ulong aIRQ, ulong aIOBase) const; 282 bool toCOMPortNumbers (const QString &aName, ulong &aIRQ, ulong &aIOBase) const; 283 284 QStringList LPTPortNames() const; 285 QString toLPTPortName (ulong aIRQ, ulong aIOBase) const; 286 bool toLPTPortNumbers (const QString &aName, ulong &aIRQ, ulong &aIOBase) const; 287 288 static QString highlight (const QString &aStr, bool aToolTip = false); 289 static QString emphasize (const QString &aStr); 290 static QString removeAccelMark (const QString &aText); 291 static QString insertKeyToActionText (const QString &aText, const QString &aKey); 292 293 static QString replaceHtmlEntities(QString strText); 294 295 QString helpFile() const; 296 static QString documentsPath(); 297 298 static QRect normalizeGeometry (const QRect &aRectangle, const QRegion &aBoundRegion, 299 bool aCanResize = true); 300 static QRect getNormalized (const QRect &aRectangle, const QRegion &aBoundRegion, 301 bool aCanResize = true); 302 static QRegion flip (const QRegion &aRegion); 303 304 static void centerWidget (QWidget *aWidget, QWidget *aRelative, 305 bool aCanResize = true); 306 307 /** Assigns top-level @a pWidget geometry passed as QRect coordinates. 308 * @note Take into account that this request may fail on X11. */ 309 static void setTopLevelGeometry(QWidget *pWidget, int x, int y, int w, int h); 310 /** Assigns top-level @a pWidget geometry passed as @a rect. 311 * @note Take into account that this request may fail on X11. */ 312 static void setTopLevelGeometry(QWidget *pWidget, const QRect &rect); 313 314 static bool activateWindow (WId aWId, bool aSwitchDesktop = true); 315 316 #ifdef VBOX_WS_X11 317 /** X11: Test whether the current window manager supports full screen mode. */ 318 static bool supportsFullScreenMonitorsProtocolX11(); 319 /** X11: Performs mapping of the passed @a pWidget to host-screen with passed @a uScreenId. */ 320 static bool setFullScreenMonitorX11(QWidget *pWidget, ulong uScreenId); 321 322 /** X11: Returns a list of current _NET_WM_STATE flags for passed @a pWidget. */ 323 static QVector<Atom> flagsNetWmState(QWidget *pWidget); 324 /** X11: Check whether _NET_WM_STATE_FULLSCREEN flag is set for passed @a pWidget. */ 325 static bool isFullScreenFlagSet(QWidget *pWidget); 326 /** X11: Sets _NET_WM_STATE_FULLSCREEN flag for passed @a pWidget. */ 327 static void setFullScreenFlag(QWidget *pWidget); 328 /** X11: Sets _NET_WM_STATE_SKIP_TASKBAR flag for passed @a pWidget. */ 329 static void setSkipTaskBarFlag(QWidget *pWidget); 330 /** X11: Sets _NET_WM_STATE_SKIP_PAGER flag for passed @a pWidget. */ 331 static void setSkipPagerFlag(QWidget *pWidget); 332 333 /** Assigns WM_CLASS property for passed @a pWidget. */ 334 static void setWMClass(QWidget *pWidget, const QString &strNameString, const QString &strClassString); 335 #endif /* VBOX_WS_X11 */ 336 337 /* Shame on Qt it hasn't stuff for tuning 338 * widget size suitable for reflecting content of desired size. 339 * For example QLineEdit, QSpinBox and similar widgets should have a methods 340 * to strict the minimum width to reflect at least [n] symbols. */ 341 static void setMinimumWidthAccordingSymbolCount(QSpinBox *pSpinBox, int cCount); 125 342 126 343 /** Try to acquire COM cleanup protection token for reading. */ … … 141 358 bool isVBoxSVCAvailable() const { return m_fVBoxSVCAvailable; } 142 359 143 /** Returns the thread-pool instance. */144 UIThreadPool* threadPool() const { return m_pThreadPool; }145 146 bool is3DAvailableWorker() const;147 bool is3DAvailable() const { if (m3DAvailable < 0) return is3DAvailableWorker(); return m3DAvailable != 0; }148 149 #ifdef VBOX_GUI_WITH_PIDFILE150 void createPidfile();151 void deletePidfile();152 #endif153 154 /* branding */155 bool brandingIsActive (bool aForce = false);156 QString brandingGetKey (QString aKey);157 158 bool processArgs();159 160 bool switchToMachine(CMachine &machine);161 162 bool launchMachine(CMachine &machine, LaunchMode enmLaunchMode = LaunchMode_Default);163 164 bool isVMConsoleProcess() const { return !vmUuid.isNull(); }165 bool showStartVMErrors() const { return mShowStartVMErrors; }166 QString managedVMUuid() const { return vmUuid; }167 QList<QUrl> &argUrlList() { return m_ArgUrlList; }168 169 /** Returns whether the Extension Pack installation was requested at startup. */170 bool isEPInstallationRequested() const { return m_fEPInstallationRequested; }171 /** Defines whether the Extension Pack installation was @a fRequested at startup. */172 void setEPInstallationRequested(bool fRequested) { m_fEPInstallationRequested = fRequested; }173 174 #ifdef VBOX_WS_X11175 /** X11: Returns whether the Window Manager we are running at is composition one. */176 bool isCompositingManagerRunning() const { return m_fCompositingManagerRunning; }177 /** X11: Returns the type of the Window Manager we are running under. */178 X11WMType typeOfWindowManager() const { return m_enmWindowManagerType; }179 #endif /* VBOX_WS_X11 */180 181 /** Returns whether we should restore current snapshot before VM started. */182 bool shouldRestoreCurrentSnapshot() const { return mRestoreCurrentSnapshot; }183 /** Defines whether we should fRestore current snapshot before VM started. */184 void setShouldRestoreCurrentSnapshot(bool fRestore) { mRestoreCurrentSnapshot = fRestore; }185 186 bool hasFloppyImageToMount() const { return !m_strFloppyImage.isEmpty(); }187 bool hasDvdImageToMount() const { return !m_strDvdImage.isEmpty(); }188 QString const &getFloppyImage() const { return m_strFloppyImage; }189 QString const &getDvdImage() const { return m_strDvdImage; }190 191 bool isPatmDisabled() const { return mDisablePatm; }192 bool isCsamDisabled() const { return mDisableCsam; }193 bool isSupervisorCodeExecedRecompiled() const { return mRecompileSupervisor; }194 bool isUserCodeExecedRecompiled() const { return mRecompileUser; }195 bool areWeToExecuteAllInIem() const { return mExecuteAllInIem; }196 bool isDefaultWarpPct() const { return mWarpPct == 100; }197 uint32_t getWarpPct() const { return mWarpPct; }198 199 #ifdef VBOX_WITH_DEBUGGER_GUI200 bool isDebuggerEnabled() const;201 bool isDebuggerAutoShowEnabled() const;202 bool isDebuggerAutoShowCommandLineEnabled() const;203 bool isDebuggerAutoShowStatisticsEnabled() const;204 205 RTLDRMOD getDebuggerModule() const { return m_hVBoxDbg; }206 #endif /* VBOX_WITH_DEBUGGER_GUI */207 208 bool shouldStartPaused() const209 {210 #ifdef VBOX_WITH_DEBUGGER_GUI211 return m_enmStartRunning == StartRunning_Default ? isDebuggerAutoShowEnabled() : m_enmStartRunning == StartRunning_No;212 #else213 return false;214 #endif215 }216 217 /* VBox enum to/from string/icon/color convertors */218 219 360 QList <CGuestOSType> vmGuestOSFamilyList() const; 220 361 QList <CGuestOSType> vmGuestOSTypeList (const QString &aFamilyId) const; 221 222 /** Returns icon defined for a passed @a comMachine. */223 QIcon vmUserIcon(const CMachine &comMachine) const;224 /** Returns pixmap of a passed @a size defined for a passed @a comMachine. */225 QPixmap vmUserPixmap(const CMachine &comMachine, const QSize &size) const;226 /** Returns pixmap defined for a passed @a comMachine.227 * In case if non-null @a pLogicalSize pointer provided, it will be updated properly. */228 QPixmap vmUserPixmapDefault(const CMachine &comMachine, QSize *pLogicalSize = 0) const;229 230 /** Returns pixmap corresponding to passed @a strOSTypeID. */231 QIcon vmGuestOSTypeIcon(const QString &strOSTypeID) const;232 /** Returns pixmap corresponding to passed @a strOSTypeID and @a size. */233 QPixmap vmGuestOSTypePixmap(const QString &strOSTypeID, const QSize &size) const;234 /** Returns pixmap corresponding to passed @a strOSTypeID.235 * In case if non-null @a pLogicalSize pointer provided, it will be updated properly. */236 QPixmap vmGuestOSTypePixmapDefault(const QString &strOSTypeID, QSize *pLogicalSize = 0) const;237 362 238 363 CGuestOSType vmGuestOSType (const QString &aTypeId, … … 240 365 QString vmGuestOSTypeDescription (const QString &aTypeId) const; 241 366 242 static inline QString yearsToString (uint32_t cVal) 243 { 244 return tr("%n year(s)", "", cVal); 245 } 246 247 static inline QString monthsToString (uint32_t cVal) 248 { 249 return tr("%n month(s)", "", cVal); 250 } 251 252 static inline QString daysToString (uint32_t cVal) 253 { 254 return tr("%n day(s)", "", cVal); 255 } 256 257 static inline QString hoursToString (uint32_t cVal) 258 { 259 return tr("%n hour(s)", "", cVal); 260 } 261 262 static inline QString minutesToString (uint32_t cVal) 263 { 264 return tr("%n minute(s)", "", cVal); 265 } 266 267 static inline QString secondsToString (uint32_t cVal) 268 { 269 return tr("%n second(s)", "", cVal); 270 } 271 272 QStringList COMPortNames() const; 273 QString toCOMPortName (ulong aIRQ, ulong aIOBase) const; 274 bool toCOMPortNumbers (const QString &aName, ulong &aIRQ, ulong &aIOBase) const; 275 276 QStringList LPTPortNames() const; 277 QString toLPTPortName (ulong aIRQ, ulong aIOBase) const; 278 bool toLPTPortNumbers (const QString &aName, ulong &aIRQ, ulong &aIOBase) const; 279 280 static bool hasAllowedExtension(const QString &strExt, const QStringList &extList) 281 { 282 for (int i = 0; i < extList.size(); ++i) 283 if (strExt.endsWith(extList.at(i), Qt::CaseInsensitive)) 284 return true; 285 return false; 286 } 287 288 QIcon icon(QFileIconProvider::IconType type) { return m_globalIconProvider.icon(type); } 289 QIcon icon(const QFileInfo &info) { return m_globalIconProvider.icon(info); } 290 291 QPixmap warningIcon() const { return mWarningIcon; } 292 QPixmap errorIcon() const { return mErrorIcon; } 293 294 /* details generators */ 295 296 QString details(const CMedium &medium, bool fPredictDiff, bool fUseHtml = true); 297 298 QString details (const CUSBDevice &aDevice) const; 299 QString toolTip (const CUSBDevice &aDevice) const; 300 QString toolTip (const CUSBDeviceFilter &aFilter) const; 301 QString toolTip(const CHostVideoInputDevice &webcam) const; 302 303 /* VirtualBox helpers */ 367 static bool isDOSType (const QString &aOSTypeId); 368 369 bool switchToMachine(CMachine &machine); 370 bool launchMachine(CMachine &machine, LaunchMode enmLaunchMode = LaunchMode_Default); 304 371 305 372 CSession openSession(const QString &aId, KLockType aLockType = KLockType_Write); 306 307 373 /** Shortcut to openSession (aId, true). */ 308 374 CSession openExistingSession(const QString &aId) { return openSession(aId, KLockType_Shared); } 309 375 310 /* API: Medium-processing stuff: */ 311 void createMedium(const UIMedium &medium); 312 void deleteMedium(const QString &strMediumID); 313 QString createVisoMediumWithFileOpenDialog(QWidget *pParent, const QString &strMachineFolder); 314 QString openMediumWithFileOpenDialog(UIMediumType mediumType, QWidget *pParent = 0, 315 const QString &strDefaultFolder = QString(), bool fUseLastFolder = true); 316 QString openMedium(UIMediumType mediumType, QString strMediumLocation, QWidget *pParent = 0); 376 static QList <QPair <QString, QString> > MediumBackends(KDeviceType enmDeviceType); 377 static QList <QPair <QString, QString> > HDDBackends(); 378 static QList <QPair <QString, QString> > DVDBackends(); 379 static QList <QPair <QString, QString> > FloppyBackends(); 317 380 318 381 /* API: Medium-enumeration stuff: */ 319 382 void startMediumEnumeration(); 320 bool agressiveCaching() const { return mAgressiveCaching; }321 383 bool isMediumEnumerationInProgress() const; 322 384 UIMedium medium(const QString &strMediumID) const; 323 385 QList<QString> mediumIDs() const; 386 void createMedium(const UIMedium &medium); 387 void deleteMedium(const QString &strMediumID); 388 389 /* API: Medium-processing stuff: */ 390 QString openMedium(UIMediumType mediumType, QString strMediumLocation, QWidget *pParent = 0); 391 392 QString openMediumWithFileOpenDialog(UIMediumType mediumType, QWidget *pParent = 0, 393 const QString &strDefaultFolder = QString(), bool fUseLastFolder = true); 394 395 QString createVisoMediumWithFileOpenDialog(QWidget *pParent, const QString &strMachineFolder); 324 396 325 397 /** Prepares storage menu according passed parameters. … … 336 408 void updateMachineStorage(const CMachine &constMachine, const UIMediumTarget &target); 337 409 338 /* various helpers */ 339 340 QString languageName() const; 341 QString languageCountry() const; 342 QString languageNameEnglish() const; 343 QString languageCountryEnglish() const; 344 QString languageTranslators() const; 345 346 void retranslateUi(); 347 348 /* public static stuff */ 349 350 static bool isDOSType (const QString &aOSTypeId); 351 352 /** Returns VBox language sub-directory. */ 353 static QString vboxLanguageSubDirectory(); 354 /** Returns VBox language file-base. */ 355 static QString vboxLanguageFileBase(); 356 /** Returns VBox language file-extension. */ 357 static QString vboxLanguageFileExtension(); 358 /** Returns VBox language ID reg-exp. */ 359 static QString vboxLanguageIdRegExp(); 360 /** Returns built in language name. */ 361 static QString vboxBuiltInLanguageName(); 362 static QString languageId(); 363 static void loadLanguage (const QString &aLangId = QString::null); 364 QString helpFile() const; 365 366 static void setTextLabel (QToolButton *aToolButton, const QString &aTextLabel); 367 368 static QRect normalizeGeometry (const QRect &aRectangle, const QRegion &aBoundRegion, 369 bool aCanResize = true); 370 static QRect getNormalized (const QRect &aRectangle, const QRegion &aBoundRegion, 371 bool aCanResize = true); 372 static QRegion flip (const QRegion &aRegion); 373 374 static void centerWidget (QWidget *aWidget, QWidget *aRelative, 375 bool aCanResize = true); 376 377 static QChar decimalSep(); 378 static QString sizeRegexp(); 379 380 static quint64 parseSize (const QString &); 381 static QString formatSize (quint64 aSize, uint aDecimal = 2, FormatSize aMode = FormatSize_Round); 382 383 static quint64 requiredVideoMemory(const QString &strGuestOSTypeId, int cMonitors = 1); 384 385 static QString locationForHTML (const QString &aFileName); 386 387 static QString highlight (const QString &aStr, bool aToolTip = false); 388 389 static QString replaceHtmlEntities(QString strText); 390 static QString emphasize (const QString &aStr); 391 392 static QString systemLanguageId(); 393 394 static bool activateWindow (WId aWId, bool aSwitchDesktop = true); 395 396 #ifdef VBOX_WS_X11 397 /** X11: Test whether the current window manager supports full screen mode. */ 398 static bool supportsFullScreenMonitorsProtocolX11(); 399 /** X11: Performs mapping of the passed @a pWidget to host-screen with passed @a uScreenId. */ 400 static bool setFullScreenMonitorX11(QWidget *pWidget, ulong uScreenId); 401 402 /** X11: Returns a list of current _NET_WM_STATE flags for passed @a pWidget. */ 403 static QVector<Atom> flagsNetWmState(QWidget *pWidget); 404 /** X11: Check whether _NET_WM_STATE_FULLSCREEN flag is set for passed @a pWidget. */ 405 static bool isFullScreenFlagSet(QWidget *pWidget); 406 /** X11: Sets _NET_WM_STATE_FULLSCREEN flag for passed @a pWidget. */ 407 static void setFullScreenFlag(QWidget *pWidget); 408 /** X11: Sets _NET_WM_STATE_SKIP_TASKBAR flag for passed @a pWidget. */ 409 static void setSkipTaskBarFlag(QWidget *pWidget); 410 /** X11: Sets _NET_WM_STATE_SKIP_PAGER flag for passed @a pWidget. */ 411 static void setSkipPagerFlag(QWidget *pWidget); 412 #endif /* VBOX_WS_X11 */ 413 414 static QString removeAccelMark (const QString &aText); 415 416 static QString insertKeyToActionText (const QString &aText, const QString &aKey); 417 418 static QPixmap joinPixmaps (const QPixmap &aPM1, const QPixmap &aPM2); 419 420 static QWidget *findWidget (QWidget *aParent, const char *aName, 421 const char *aClassName = NULL, 422 bool aRecursive = false); 423 424 static QList <QPair <QString, QString> > MediumBackends(KDeviceType enmDeviceType); 425 static QList <QPair <QString, QString> > HDDBackends(); 426 static QList <QPair <QString, QString> > DVDBackends(); 427 static QList <QPair <QString, QString> > FloppyBackends(); 428 429 static QString documentsPath(); 430 431 #ifdef VBOX_WITH_CRHGSMI 432 static bool isWddmCompatibleOsType(const QString &strGuestOSTypeId); 433 #endif /* VBOX_WITH_CRHGSMI */ 434 435 /* Returns full medium-format name for the given base medium-format name: */ 436 static QString fullMediumFormatName(const QString &strBaseMediumFormatName); 437 410 QString details(const CMedium &medium, bool fPredictDiff, bool fUseHtml = true); 438 411 439 412 #ifdef RT_OS_LINUX … … 441 414 #endif /* RT_OS_LINUX */ 442 415 443 /* Shame on Qt it hasn't stuff for tuning 444 * widget size suitable for reflecting content of desired size. 445 * For example QLineEdit, QSpinBox and similar widgets should have a methods 446 * to strict the minimum width to reflect at least [n] symbols. */ 447 static void setMinimumWidthAccordingSymbolCount(QSpinBox *pSpinBox, int cCount); 448 449 /** Assigns top-level @a pWidget geometry passed as QRect coordinates. 450 * @note Take into account that this request may fail on X11. */ 451 static void setTopLevelGeometry(QWidget *pWidget, int x, int y, int w, int h); 452 /** Assigns top-level @a pWidget geometry passed as @a rect. 453 * @note Take into account that this request may fail on X11. */ 454 static void setTopLevelGeometry(QWidget *pWidget, const QRect &rect); 455 456 #ifdef VBOX_WS_X11 457 /** Assigns WM_CLASS property for passed @a pWidget. */ 458 static void setWMClass(QWidget *pWidget, const QString &strNameString, const QString &strClassString); 459 #endif 416 QString details (const CUSBDevice &aDevice) const; 417 QString toolTip (const CUSBDevice &aDevice) const; 418 QString toolTip (const CUSBDeviceFilter &aFilter) const; 419 QString toolTip(const CHostVideoInputDevice &webcam) const; 460 420 461 421 /** Initiates the extension pack installation process. … … 469 429 QString *pstrExtPackName); 470 430 471 signals: 472 473 /** Asks listener to recreate UI. */ 474 void sigAskToRestartUI(); 475 /** Asks listener to open URLs. */ 476 void sigAskToOpenURLs(); 477 /** Asks listener to commit data. */ 478 void sigAskToCommitData(); 479 480 /** Notifies listeners about the VBoxSVC availability change. */ 481 void sigVBoxSVCAvailabilityChange(); 482 483 /* Notifiers: Medium-processing stuff: */ 484 void sigMediumCreated(const QString &strMediumID); 485 void sigMediumDeleted(const QString &strMediumID); 486 487 /* Notifiers: Medium-enumeration stuff: */ 488 void sigMediumEnumerationStarted(); 489 void sigMediumEnumerated(const QString &strMediumID); 490 void sigMediumEnumerationFinished(); 431 /** Returns whether the Extension Pack installation was requested at startup. */ 432 bool isEPInstallationRequested() const { return m_fEPInstallationRequested; } 433 /** Defines whether the Extension Pack installation was @a fRequested at startup. */ 434 void setEPInstallationRequested(bool fRequested) { m_fEPInstallationRequested = fRequested; } 435 436 bool is3DAvailableWorker() const; 437 bool is3DAvailable() const { if (m3DAvailable < 0) return is3DAvailableWorker(); return m3DAvailable != 0; } 438 439 #ifdef VBOX_WITH_CRHGSMI 440 static bool isWddmCompatibleOsType(const QString &strGuestOSTypeId); 441 #endif /* VBOX_WITH_CRHGSMI */ 442 443 static quint64 requiredVideoMemory(const QString &strGuestOSTypeId, int cMonitors = 1); 444 445 /** Returns the thread-pool instance. */ 446 UIThreadPool* threadPool() const { return m_pThreadPool; } 447 448 /** Returns icon defined for a passed @a comMachine. */ 449 QIcon vmUserIcon(const CMachine &comMachine) const; 450 /** Returns pixmap of a passed @a size defined for a passed @a comMachine. */ 451 QPixmap vmUserPixmap(const CMachine &comMachine, const QSize &size) const; 452 /** Returns pixmap defined for a passed @a comMachine. 453 * In case if non-null @a pLogicalSize pointer provided, it will be updated properly. */ 454 QPixmap vmUserPixmapDefault(const CMachine &comMachine, QSize *pLogicalSize = 0) const; 455 456 /** Returns pixmap corresponding to passed @a strOSTypeID. */ 457 QIcon vmGuestOSTypeIcon(const QString &strOSTypeID) const; 458 /** Returns pixmap corresponding to passed @a strOSTypeID and @a size. */ 459 QPixmap vmGuestOSTypePixmap(const QString &strOSTypeID, const QSize &size) const; 460 /** Returns pixmap corresponding to passed @a strOSTypeID. 461 * In case if non-null @a pLogicalSize pointer provided, it will be updated properly. */ 462 QPixmap vmGuestOSTypePixmapDefault(const QString &strOSTypeID, QSize *pLogicalSize = 0) const; 463 464 QIcon icon(QFileIconProvider::IconType type) { return m_globalIconProvider.icon(type); } 465 QIcon icon(const QFileInfo &info) { return m_globalIconProvider.icon(info); } 466 467 QPixmap warningIcon() const { return mWarningIcon; } 468 QPixmap errorIcon() const { return mErrorIcon; } 469 470 static QPixmap joinPixmaps (const QPixmap &aPM1, const QPixmap &aPM2); 471 472 static void setTextLabel (QToolButton *aToolButton, const QString &aTextLabel); 473 474 static QString locationForHTML (const QString &aFileName); 475 476 static QWidget *findWidget (QWidget *aParent, const char *aName, 477 const char *aClassName = NULL, 478 bool aRecursive = false); 491 479 492 480 public slots: … … 495 483 496 484 void sltGUILanguageChange(QString strLang); 485 486 protected: 487 488 bool eventFilter (QObject *, QEvent *); 489 490 void retranslateUi(); 497 491 498 492 protected slots: … … 507 501 /** Handles the VBoxSVC availability change. */ 508 502 void sltHandleVBoxSVCAvailabilityChange(bool fAvailable); 509 510 protected:511 512 bool eventFilter (QObject *, QEvent *);513 503 514 504 private: … … 525 515 virtual ~VBoxGlobal() /* override */; 526 516 527 /** Re-initializes COM wrappers and containers. */528 void comWrappersReinit();529 530 517 #ifdef VBOX_WS_WIN 531 518 /** Wraps WinAPI ShutdownBlockReasonCreate function. */ … … 539 526 #endif 540 527 528 /** Re-initializes COM wrappers and containers. */ 529 void comWrappersReinit(); 530 531 /** Holds the singleton VBoxGlobal instance. */ 532 static VBoxGlobal *s_pInstance; 533 534 /** Holds the currently loaded language ID. */ 535 static QString s_strLoadedLanguageId; 536 537 /** Holds whether VBoxGlobal cleanup is in progress. */ 538 static bool s_fCleanupInProgress; 539 541 540 #ifdef VBOX_GUI_WITH_SHARED_LIBRARY 542 541 /** Holds the UI type. */ … … 550 549 MacOSXRelease m_osRelease; 551 550 #endif /* VBOX_WS_MAC */ 552 553 /** COM cleanup protection token. */554 QReadWriteLock m_comCleanupProtectionToken;555 556 /** Holds the instance of VirtualBox client wrapper. */557 CVirtualBoxClient m_client;558 /** Holds the copy of VirtualBox object wrapper. */559 CVirtualBox m_vbox;560 /** Holds the copy of VirtualBox host-object wrapper. */561 CHost m_host;562 /** Holds the symbolic VirtualBox home-folder representation. */563 QString m_strHomeFolder;564 /** Holds the guest OS family IDs. */565 QList<QString> m_guestOSFamilyIDs;566 /** Holds the guest OS types for each family ID. */567 QList<QList<CGuestOSType> > m_guestOSTypes;568 569 /** Holds whether acquired COM wrappers are currently valid. */570 bool m_fWrappersValid;571 /** Holds whether VBoxSVC is currently available. */572 bool m_fVBoxSVCAvailable;573 574 /** Holds whether GUI is separate (from VM) process. */575 bool m_fSeparateProcess;576 577 QString vmUuid;578 QList<QUrl> m_ArgUrlList;579 580 /** Whether to show error message boxes for VM start errors. */581 bool mShowStartVMErrors;582 583 /* Variable: Medium-enumeration stuff: */584 UIMediumEnumerator *m_pMediumEnumerator;585 mutable QReadWriteLock m_mediumEnumeratorDtorRwLock;586 587 /** Holds whether the Extension Pack installation was requested at startup. */588 bool m_fEPInstallationRequested;589 551 590 552 #ifdef VBOX_WS_X11 … … 595 557 #endif /* VBOX_WS_X11 */ 596 558 559 QString mVerString; 560 QString mBrandingConfig; 561 562 QList<QUrl> m_ArgUrlList; 563 564 QString vmUuid; 565 /** Holds whether GUI is separate (from VM) process. */ 566 bool m_fSeparateProcess; 567 /** Whether to show error message boxes for VM start errors. */ 568 bool mShowStartVMErrors; 569 597 570 /** The --aggressive-caching / --no-aggressive-caching option. */ 598 571 bool mAgressiveCaching; 572 599 573 /** The --restore-current option. */ 600 574 bool mRestoreCurrentSnapshot; … … 640 614 #endif 641 615 642 #if defined (VBOX_WS_WIN) 643 DWORD dwHTMLHelpCookie; 644 #endif 645 646 QString mVerString; 647 QString mBrandingConfig; 648 649 int m3DAvailable; 650 651 QString mUserDefinedPortName; 652 653 QPixmap mWarningIcon, mErrorIcon; 654 655 QFileIconProvider m_globalIconProvider; 616 char mSettingsPw[256]; 617 bool mSettingsPwSet; 656 618 657 619 #ifdef VBOX_GUI_WITH_PIDFILE … … 659 621 #endif 660 622 661 char mSettingsPw[256]; 662 bool mSettingsPwSet; 623 QString mUserDefinedPortName; 624 625 /** COM cleanup protection token. */ 626 QReadWriteLock m_comCleanupProtectionToken; 627 628 /** Holds the instance of VirtualBox client wrapper. */ 629 CVirtualBoxClient m_client; 630 /** Holds the copy of VirtualBox object wrapper. */ 631 CVirtualBox m_vbox; 632 /** Holds the copy of VirtualBox host-object wrapper. */ 633 CHost m_host; 634 /** Holds the symbolic VirtualBox home-folder representation. */ 635 QString m_strHomeFolder; 636 637 /** Holds whether acquired COM wrappers are currently valid. */ 638 bool m_fWrappersValid; 639 /** Holds whether VBoxSVC is currently available. */ 640 bool m_fVBoxSVCAvailable; 641 642 /** Holds the guest OS family IDs. */ 643 QList<QString> m_guestOSFamilyIDs; 644 /** Holds the guest OS types for each family ID. */ 645 QList<QList<CGuestOSType> > m_guestOSTypes; 646 647 int m3DAvailable; 648 649 /** Holds the thread-pool instance. */ 650 UIThreadPool *m_pThreadPool; 663 651 664 652 /** General icon-pool. */ 665 653 UIIconPoolGeneral *m_pIconPool; 666 /** Holds the thread-pool instance. */ 667 UIThreadPool *m_pThreadPool; 654 655 QFileIconProvider m_globalIconProvider; 656 657 QPixmap mWarningIcon, mErrorIcon; 658 659 /* Variable: Medium-enumeration stuff: */ 660 mutable QReadWriteLock m_mediumEnumeratorDtorRwLock; 661 UIMediumEnumerator *m_pMediumEnumerator; 662 663 /** Holds whether the Extension Pack installation was requested at startup. */ 664 bool m_fEPInstallationRequested; 668 665 669 666 #if defined(VBOX_WS_WIN) && defined(VBOX_GUI_WITH_SHARED_LIBRARY) … … 673 670 #endif 674 671 675 /** Holds the singleton VBoxGlobal instance. */ 676 static VBoxGlobal *s_pInstance; 677 /** Holds whether VBoxGlobal cleanup is in progress. */ 678 static bool s_fCleanupInProgress; 679 /** Holds the currently loaded language ID. */ 680 static QString s_strLoadedLanguageId; 672 #if defined (VBOX_WS_WIN) 673 DWORD dwHTMLHelpCookie; 674 #endif 681 675 682 676 /** Allows for shortcut access. */ … … 688 682 689 683 #endif /* !___VBoxGlobal_h___ */ 690
Note:
See TracChangeset
for help on using the changeset viewer.