/* $Id: VBoxGlobalSettings.cpp 35730 2011-01-27 10:49:44Z vboxsync $ */ /** @file * * VBox frontends: Qt GUI ("VirtualBox"): * VBoxGlobalSettingsData, VBoxGlobalSettings class implementation */ /* * Copyright (C) 2006-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. */ #ifdef VBOX_WITH_PRECOMPILED_HEADERS # include "precomp.h" #else /* !VBOX_WITH_PRECOMPILED_HEADERS */ /* Qt includes */ #include #include #include #include "VBoxGlobalSettings.h" #include "UIHotKeyEditor.h" #include "COMDefs.h" #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ /** @class VBoxGlobalSettingsData * * The VBoxGlobalSettingsData class encapsulates the global settings * of the VirtualBox. */ VBoxGlobalSettingsData::VBoxGlobalSettingsData() { /* default settings */ #if defined (Q_WS_WIN) hostCombo = "163"; // VK_RCONTROL #elif defined (Q_WS_X11) hostCombo = "65508"; // XK_Control_R #elif defined (Q_WS_MAC) hostCombo = "55"; // QZ_LMETA #else # warning "port me!" #endif autoCapture = true; guiFeatures = QString::null; languageId = QString::null; maxGuestRes = "auto"; remapScancodes = QString::null; trayIconEnabled = false; presentationModeEnabled = false; hostScreenSaverDisabled = false; } VBoxGlobalSettingsData::VBoxGlobalSettingsData (const VBoxGlobalSettingsData &that) { hostCombo = that.hostCombo; autoCapture = that.autoCapture; guiFeatures = that.guiFeatures; languageId = that.languageId; maxGuestRes = that.maxGuestRes; remapScancodes = that.remapScancodes; trayIconEnabled = that.trayIconEnabled; presentationModeEnabled = that.presentationModeEnabled; hostScreenSaverDisabled = that.hostScreenSaverDisabled; } VBoxGlobalSettingsData::~VBoxGlobalSettingsData() { } bool VBoxGlobalSettingsData::operator== (const VBoxGlobalSettingsData &that) const { return this == &that || (hostCombo == that.hostCombo && autoCapture == that.autoCapture && guiFeatures == that.guiFeatures && languageId == that.languageId && maxGuestRes == that.maxGuestRes && remapScancodes == that.remapScancodes && trayIconEnabled == that.trayIconEnabled && presentationModeEnabled == that.presentationModeEnabled && hostScreenSaverDisabled == that.hostScreenSaverDisabled ); } /** @class VBoxGlobalSettings * * The VBoxGlobalSettings class is a wrapper class for VBoxGlobalSettingsData * to implement implicit sharing of VirtualBox global data. */ /* Defined in VBoxGlobal.cpp */ extern const char *gVBoxLangIDRegExp; static struct { const char *publicName; const char *name; const char *rx; bool canDelete; } gPropertyMap[] = { { "GUI/Input/HostCombo", "hostCombo", "0|\\d*[1-9]\\d*(,\\d*[1-9]\\d*)?(,\\d*[1-9]\\d*)?", true }, { "GUI/Input/AutoCapture", "autoCapture", "true|false", true }, { "GUI/Customizations", "guiFeatures", "\\S+", true }, { "GUI/LanguageID", "languageId", gVBoxLangIDRegExp, true }, { "GUI/MaxGuestResolution", "maxGuestRes", "\\d*[1-9]\\d*,\\d*[1-9]\\d*|any|auto", true }, { "GUI/RemapScancodes", "remapScancodes", "(\\d+=\\d+,)*\\d+=\\d+", true }, { "GUI/TrayIcon/Enabled", "trayIconEnabled", "true|false", true }, #ifdef Q_WS_MAC { VBoxDefs::GUI_PresentationModeEnabled, "presentationModeEnabled", "true|false", true }, #endif /* Q_WS_MAC */ { "GUI/HostScreenSaverDisabled", "hostScreenSaverDisabled", "true|false", true } }; void VBoxGlobalSettings::setHostCombo (const QString &hostCombo) { if (!UIHotKeyCombination::isValidKeyCombo (hostCombo)) { last_err = tr ("'%1' is an invalid host-combination code-sequence.").arg (hostCombo); return; } mData()->hostCombo = hostCombo; resetError(); } bool VBoxGlobalSettings::isFeatureActive (const char *aFeature) const { QStringList featureList = data()->guiFeatures.split (','); return featureList.contains (aFeature); } /** * Loads the settings from the (global) extra data area of VirtualBox. * * If an error occurs while accessing extra data area, the method immediately * returns and the vbox argument will hold all error info (and therefore * vbox.isOk() will be false to indicate this). * * If an error occurs while setting the value of some property, the method * also returns immediately. #operator !() will return false in this case * and #lastError() will contain the error message. * * @note This method emits the #propertyChanged() signal. */ void VBoxGlobalSettings::load (CVirtualBox &vbox) { for (size_t i = 0; i < SIZEOF_ARRAY (gPropertyMap); i++) { QString value = vbox.GetExtraData (gPropertyMap [i].publicName); if (!vbox.isOk()) return; // empty value means the key is absent. it is ok, the default will apply if (value.isEmpty()) continue; // try to set the property validating it against rx setPropertyPrivate (i, value); if (!(*this)) break; } } /** * Saves the settings to the (global) extra data area of VirtualBox. * * If an error occurs while accessing extra data area, the method immediately * returns and the vbox argument will hold all error info (and therefore * vbox.isOk() will be false to indicate this). */ void VBoxGlobalSettings::save (CVirtualBox &vbox) const { for (size_t i = 0; i < SIZEOF_ARRAY (gPropertyMap); i++) { QVariant value = property (gPropertyMap [i].name); Assert (value.isValid() && value.canConvert (QVariant::String)); vbox.SetExtraData (gPropertyMap [i].publicName, value.toString()); if (!vbox.isOk()) return; } } /** * Returns a value of the property with the given public name * or QString::null if there is no such public property. */ QString VBoxGlobalSettings::publicProperty (const QString &publicName) const { for (size_t i = 0; i < SIZEOF_ARRAY (gPropertyMap); i++) { if (gPropertyMap [i].publicName == publicName) { QVariant value = property (gPropertyMap [i].name); Assert (value.isValid() && value.canConvert (QVariant::String)); if (value.isValid() && value.canConvert (QVariant::String)) return value.toString(); else break; } } return QString::null; } /** * Sets a value of a property with the given public name. * Returns false if the specified property is not found, and true otherwise. * * This method (as opposed to #setProperty (const char *name, const QVariant& value)) * validates the value against the property's regexp. * * If an error occurs while setting the value of the property, #operator !() * will return false after this method returns true, and #lastError() will contain * the error message. * * @note This method emits the #propertyChanged() signal. */ bool VBoxGlobalSettings::setPublicProperty (const QString &publicName, const QString &value) { for (size_t i = 0; i < SIZEOF_ARRAY (gPropertyMap); i++) { if (gPropertyMap [i].publicName == publicName) { setPropertyPrivate (i, value); return true; } } return false; } void VBoxGlobalSettings::setPropertyPrivate (size_t index, const QString &value) { if (value.isEmpty()) { if (!gPropertyMap [index].canDelete) { last_err = tr ("Cannot delete the key '%1'.") .arg (gPropertyMap [index].publicName); return; } } else { if (!QRegExp (gPropertyMap [index].rx).exactMatch (value)) { last_err = tr ("The value '%1' of the key '%2' doesn't match the " "regexp constraint '%3'.") .arg (value, gPropertyMap [index].publicName, gPropertyMap [index].rx); return; } } QVariant oldVal = property (gPropertyMap [index].name); Assert (oldVal.isValid() && oldVal.canConvert (QVariant::String)); if (oldVal.isValid() && oldVal.canConvert (QVariant::String) && oldVal.toString() != value) { bool ok = setProperty (gPropertyMap [index].name, value); Assert (ok); if (ok) { /* The individual setter may have set a specific error */ if (!last_err.isNull()) return; last_err = QString::null; emit propertyChanged (gPropertyMap [index].publicName, gPropertyMap [index].name); } } }