[26719] | 1 | /* $Id: VBoxGlobalSettings.cpp 41689 2012-06-13 17:13:36Z vboxsync $ */
|
---|
[382] | 2 | /** @file
|
---|
| 3 | *
|
---|
| 4 | * VBox frontends: Qt GUI ("VirtualBox"):
|
---|
[2354] | 5 | * VBoxGlobalSettingsData, VBoxGlobalSettings class implementation
|
---|
[382] | 6 | */
|
---|
| 7 |
|
---|
| 8 | /*
|
---|
[35730] | 9 | * Copyright (C) 2006-2011 Oracle Corporation
|
---|
[382] | 10 | *
|
---|
| 11 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
| 12 | * available from http://www.virtualbox.org. This file is free software;
|
---|
| 13 | * you can redistribute it and/or modify it under the terms of the GNU
|
---|
[5999] | 14 | * General Public License (GPL) as published by the Free Software
|
---|
| 15 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
| 16 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
| 17 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
[382] | 18 | */
|
---|
| 19 |
|
---|
[25526] | 20 | #ifdef VBOX_WITH_PRECOMPILED_HEADERS
|
---|
| 21 | # include "precomp.h"
|
---|
| 22 | #else /* !VBOX_WITH_PRECOMPILED_HEADERS */
|
---|
[41587] | 23 |
|
---|
| 24 | /* Qt includes: */
|
---|
[7721] | 25 | #include <QString>
|
---|
| 26 | #include <QRegExp>
|
---|
| 27 | #include <QVariant>
|
---|
[382] | 28 |
|
---|
[41587] | 29 | /* GUI includes: */
|
---|
[41689] | 30 | #include "UIDefs.h"
|
---|
[2354] | 31 | #include "VBoxGlobalSettings.h"
|
---|
[35730] | 32 | #include "UIHotKeyEditor.h"
|
---|
[41587] | 33 |
|
---|
| 34 | /* COM includes: */
|
---|
| 35 | #include "COMEnums.h"
|
---|
| 36 | #include "CVirtualBox.h"
|
---|
| 37 |
|
---|
[25526] | 38 | #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
|
---|
[382] | 39 |
|
---|
[2354] | 40 | /** @class VBoxGlobalSettingsData
|
---|
[382] | 41 | *
|
---|
[33540] | 42 | * The VBoxGlobalSettingsData class encapsulates the global settings
|
---|
[382] | 43 | * of the VirtualBox.
|
---|
| 44 | */
|
---|
| 45 |
|
---|
[2354] | 46 | VBoxGlobalSettingsData::VBoxGlobalSettingsData()
|
---|
[382] | 47 | {
|
---|
| 48 | /* default settings */
|
---|
[35730] | 49 | #if defined (Q_WS_WIN)
|
---|
| 50 | hostCombo = "163"; // VK_RCONTROL
|
---|
[382] | 51 | #elif defined (Q_WS_X11)
|
---|
[35730] | 52 | hostCombo = "65508"; // XK_Control_R
|
---|
[1285] | 53 | #elif defined (Q_WS_MAC)
|
---|
[35730] | 54 | hostCombo = "55"; // QZ_LMETA
|
---|
[382] | 55 | #else
|
---|
[1285] | 56 | # warning "port me!"
|
---|
[382] | 57 | #endif
|
---|
| 58 | autoCapture = true;
|
---|
[1435] | 59 | guiFeatures = QString::null;
|
---|
[2022] | 60 | languageId = QString::null;
|
---|
[8888] | 61 | maxGuestRes = "auto";
|
---|
[21711] | 62 | remapScancodes = QString::null;
|
---|
[37544] | 63 | proxySettings = QString::null;
|
---|
[14908] | 64 | trayIconEnabled = false;
|
---|
[25318] | 65 | presentationModeEnabled = false;
|
---|
[32100] | 66 | hostScreenSaverDisabled = false;
|
---|
[382] | 67 | }
|
---|
| 68 |
|
---|
[5132] | 69 | VBoxGlobalSettingsData::VBoxGlobalSettingsData (const VBoxGlobalSettingsData &that)
|
---|
| 70 | {
|
---|
[35730] | 71 | hostCombo = that.hostCombo;
|
---|
[382] | 72 | autoCapture = that.autoCapture;
|
---|
[1435] | 73 | guiFeatures = that.guiFeatures;
|
---|
[2022] | 74 | languageId = that.languageId;
|
---|
[8888] | 75 | maxGuestRes = that.maxGuestRes;
|
---|
[21711] | 76 | remapScancodes = that.remapScancodes;
|
---|
[37544] | 77 | proxySettings = that.proxySettings;
|
---|
[14455] | 78 | trayIconEnabled = that.trayIconEnabled;
|
---|
[25318] | 79 | presentationModeEnabled = that.presentationModeEnabled;
|
---|
[32100] | 80 | hostScreenSaverDisabled = that.hostScreenSaverDisabled;
|
---|
[382] | 81 | }
|
---|
| 82 |
|
---|
[2354] | 83 | VBoxGlobalSettingsData::~VBoxGlobalSettingsData()
|
---|
[382] | 84 | {
|
---|
| 85 | }
|
---|
| 86 |
|
---|
[5132] | 87 | bool VBoxGlobalSettingsData::operator== (const VBoxGlobalSettingsData &that) const
|
---|
[382] | 88 | {
|
---|
[5132] | 89 | return this == &that ||
|
---|
[35730] | 90 | (hostCombo == that.hostCombo &&
|
---|
[5132] | 91 | autoCapture == that.autoCapture &&
|
---|
| 92 | guiFeatures == that.guiFeatures &&
|
---|
[8888] | 93 | languageId == that.languageId &&
|
---|
[14455] | 94 | maxGuestRes == that.maxGuestRes &&
|
---|
[21711] | 95 | remapScancodes == that.remapScancodes &&
|
---|
[37544] | 96 | proxySettings == that.proxySettings &&
|
---|
[25318] | 97 | trayIconEnabled == that.trayIconEnabled &&
|
---|
[32100] | 98 | presentationModeEnabled == that.presentationModeEnabled &&
|
---|
| 99 | hostScreenSaverDisabled == that.hostScreenSaverDisabled
|
---|
[15664] | 100 | );
|
---|
[382] | 101 | }
|
---|
| 102 |
|
---|
[2354] | 103 | /** @class VBoxGlobalSettings
|
---|
[382] | 104 | *
|
---|
[2354] | 105 | * The VBoxGlobalSettings class is a wrapper class for VBoxGlobalSettingsData
|
---|
[382] | 106 | * to implement implicit sharing of VirtualBox global data.
|
---|
| 107 | */
|
---|
| 108 |
|
---|
[2158] | 109 | /* Defined in VBoxGlobal.cpp */
|
---|
| 110 | extern const char *gVBoxLangIDRegExp;
|
---|
| 111 |
|
---|
[382] | 112 | static struct
|
---|
| 113 | {
|
---|
| 114 | const char *publicName;
|
---|
| 115 | const char *name;
|
---|
| 116 | const char *rx;
|
---|
[2067] | 117 | bool canDelete;
|
---|
[382] | 118 | }
|
---|
| 119 | gPropertyMap[] =
|
---|
| 120 | {
|
---|
[35880] | 121 | { "GUI/Input/HostKeyCombination", "hostCombo", "0|\\d*[1-9]\\d*(,\\d*[1-9]\\d*)?(,\\d*[1-9]\\d*)?", true },
|
---|
[25318] | 122 | { "GUI/Input/AutoCapture", "autoCapture", "true|false", true },
|
---|
| 123 | { "GUI/Customizations", "guiFeatures", "\\S+", true },
|
---|
| 124 | { "GUI/LanguageID", "languageId", gVBoxLangIDRegExp, true },
|
---|
| 125 | { "GUI/MaxGuestResolution", "maxGuestRes", "\\d*[1-9]\\d*,\\d*[1-9]\\d*|any|auto", true },
|
---|
| 126 | { "GUI/RemapScancodes", "remapScancodes", "(\\d+=\\d+,)*\\d+=\\d+", true },
|
---|
[37544] | 127 | { "GUI/ProxySettings", "proxySettings", "[\\s\\S]*", true },
|
---|
[25318] | 128 | { "GUI/TrayIcon/Enabled", "trayIconEnabled", "true|false", true },
|
---|
[15664] | 129 | #ifdef Q_WS_MAC
|
---|
[41689] | 130 | { GUI_PresentationModeEnabled, "presentationModeEnabled", "true|false", true },
|
---|
[15664] | 131 | #endif /* Q_WS_MAC */
|
---|
[35730] | 132 | { "GUI/HostScreenSaverDisabled", "hostScreenSaverDisabled", "true|false", true }
|
---|
[382] | 133 | };
|
---|
| 134 |
|
---|
[35730] | 135 | void VBoxGlobalSettings::setHostCombo (const QString &hostCombo)
|
---|
[382] | 136 | {
|
---|
[35730] | 137 | if (!UIHotKeyCombination::isValidKeyCombo (hostCombo))
|
---|
[382] | 138 | {
|
---|
[35730] | 139 | last_err = tr ("'%1' is an invalid host-combination code-sequence.").arg (hostCombo);
|
---|
[382] | 140 | return;
|
---|
| 141 | }
|
---|
[35730] | 142 | mData()->hostCombo = hostCombo;
|
---|
[382] | 143 | resetError();
|
---|
| 144 | }
|
---|
| 145 |
|
---|
[2354] | 146 | bool VBoxGlobalSettings::isFeatureActive (const char *aFeature) const
|
---|
[1435] | 147 | {
|
---|
[7721] | 148 | QStringList featureList = data()->guiFeatures.split (',');
|
---|
[1435] | 149 | return featureList.contains (aFeature);
|
---|
| 150 | }
|
---|
| 151 |
|
---|
[382] | 152 | /**
|
---|
| 153 | * Loads the settings from the (global) extra data area of VirtualBox.
|
---|
| 154 | *
|
---|
[33540] | 155 | * If an error occurs while accessing extra data area, the method immediately
|
---|
[382] | 156 | * returns and the vbox argument will hold all error info (and therefore
|
---|
| 157 | * vbox.isOk() will be false to indicate this).
|
---|
| 158 | *
|
---|
[33540] | 159 | * If an error occurs while setting the value of some property, the method
|
---|
[382] | 160 | * also returns immediately. #operator !() will return false in this case
|
---|
| 161 | * and #lastError() will contain the error message.
|
---|
| 162 | *
|
---|
| 163 | * @note This method emits the #propertyChanged() signal.
|
---|
| 164 | */
|
---|
[2354] | 165 | void VBoxGlobalSettings::load (CVirtualBox &vbox)
|
---|
[382] | 166 | {
|
---|
[35879] | 167 | for (size_t i = 0; i < SIZEOF_ARRAY(gPropertyMap); i++)
|
---|
[382] | 168 | {
|
---|
[35879] | 169 | QString value = vbox.GetExtraData(gPropertyMap[i].publicName);
|
---|
[382] | 170 | if (!vbox.isOk())
|
---|
| 171 | return;
|
---|
[35879] | 172 | /* Check for the host key upgrade path. */
|
---|
| 173 | if ( value.isEmpty()
|
---|
[35880] | 174 | && QString(gPropertyMap[i].publicName) == "GUI/Input/HostKeyCombination")
|
---|
[35879] | 175 | value = vbox.GetExtraData("GUI/Input/HostKey");
|
---|
| 176 | /* Empty value means the key is absent. It is OK, the default will
|
---|
| 177 | * apply. */
|
---|
[20977] | 178 | if (value.isEmpty())
|
---|
[382] | 179 | continue;
|
---|
[35879] | 180 | /* Try to set the property validating it against rx. */
|
---|
| 181 | setPropertyPrivate(i, value);
|
---|
[382] | 182 | if (!(*this))
|
---|
| 183 | break;
|
---|
| 184 | }
|
---|
| 185 | }
|
---|
| 186 |
|
---|
| 187 | /**
|
---|
| 188 | * Saves the settings to the (global) extra data area of VirtualBox.
|
---|
| 189 | *
|
---|
[33540] | 190 | * If an error occurs while accessing extra data area, the method immediately
|
---|
[382] | 191 | * returns and the vbox argument will hold all error info (and therefore
|
---|
| 192 | * vbox.isOk() will be false to indicate this).
|
---|
| 193 | */
|
---|
[2354] | 194 | void VBoxGlobalSettings::save (CVirtualBox &vbox) const
|
---|
[382] | 195 | {
|
---|
| 196 | for (size_t i = 0; i < SIZEOF_ARRAY (gPropertyMap); i++)
|
---|
| 197 | {
|
---|
| 198 | QVariant value = property (gPropertyMap [i].name);
|
---|
[7721] | 199 | Assert (value.isValid() && value.canConvert (QVariant::String));
|
---|
[382] | 200 |
|
---|
| 201 | vbox.SetExtraData (gPropertyMap [i].publicName, value.toString());
|
---|
| 202 | if (!vbox.isOk())
|
---|
| 203 | return;
|
---|
| 204 | }
|
---|
| 205 | }
|
---|
| 206 |
|
---|
| 207 | /**
|
---|
| 208 | * Returns a value of the property with the given public name
|
---|
| 209 | * or QString::null if there is no such public property.
|
---|
| 210 | */
|
---|
[2354] | 211 | QString VBoxGlobalSettings::publicProperty (const QString &publicName) const
|
---|
[382] | 212 | {
|
---|
| 213 | for (size_t i = 0; i < SIZEOF_ARRAY (gPropertyMap); i++)
|
---|
| 214 | {
|
---|
| 215 | if (gPropertyMap [i].publicName == publicName)
|
---|
| 216 | {
|
---|
| 217 | QVariant value = property (gPropertyMap [i].name);
|
---|
[7721] | 218 | Assert (value.isValid() && value.canConvert (QVariant::String));
|
---|
[382] | 219 |
|
---|
[7721] | 220 | if (value.isValid() && value.canConvert (QVariant::String))
|
---|
[382] | 221 | return value.toString();
|
---|
| 222 | else
|
---|
| 223 | break;
|
---|
| 224 | }
|
---|
| 225 | }
|
---|
| 226 |
|
---|
| 227 | return QString::null;
|
---|
| 228 | }
|
---|
| 229 |
|
---|
| 230 | /**
|
---|
[2463] | 231 | * Sets a value of a property with the given public name.
|
---|
| 232 | * Returns false if the specified property is not found, and true otherwise.
|
---|
[382] | 233 | *
|
---|
| 234 | * This method (as opposed to #setProperty (const char *name, const QVariant& value))
|
---|
| 235 | * validates the value against the property's regexp.
|
---|
| 236 | *
|
---|
[33540] | 237 | * If an error occurs while setting the value of the property, #operator !()
|
---|
[2463] | 238 | * will return false after this method returns true, and #lastError() will contain
|
---|
[382] | 239 | * the error message.
|
---|
| 240 | *
|
---|
| 241 | * @note This method emits the #propertyChanged() signal.
|
---|
| 242 | */
|
---|
[2354] | 243 | bool VBoxGlobalSettings::setPublicProperty (const QString &publicName, const QString &value)
|
---|
[382] | 244 | {
|
---|
| 245 | for (size_t i = 0; i < SIZEOF_ARRAY (gPropertyMap); i++)
|
---|
| 246 | {
|
---|
| 247 | if (gPropertyMap [i].publicName == publicName)
|
---|
| 248 | {
|
---|
| 249 | setPropertyPrivate (i, value);
|
---|
| 250 | return true;
|
---|
| 251 | }
|
---|
| 252 | }
|
---|
| 253 |
|
---|
| 254 | return false;
|
---|
| 255 | }
|
---|
| 256 |
|
---|
[10219] | 257 | void VBoxGlobalSettings::setPropertyPrivate (size_t index, const QString &value)
|
---|
[382] | 258 | {
|
---|
[20977] | 259 | if (value.isEmpty())
|
---|
[382] | 260 | {
|
---|
[2067] | 261 | if (!gPropertyMap [index].canDelete)
|
---|
| 262 | {
|
---|
| 263 | last_err = tr ("Cannot delete the key '%1'.")
|
---|
| 264 | .arg (gPropertyMap [index].publicName);
|
---|
| 265 | return;
|
---|
| 266 | }
|
---|
[382] | 267 | }
|
---|
[2067] | 268 | else
|
---|
| 269 | {
|
---|
| 270 | if (!QRegExp (gPropertyMap [index].rx).exactMatch (value))
|
---|
| 271 | {
|
---|
| 272 | last_err = tr ("The value '%1' of the key '%2' doesn't match the "
|
---|
| 273 | "regexp constraint '%3'.")
|
---|
| 274 | .arg (value, gPropertyMap [index].publicName,
|
---|
| 275 | gPropertyMap [index].rx);
|
---|
| 276 | return;
|
---|
| 277 | }
|
---|
| 278 | }
|
---|
[382] | 279 |
|
---|
| 280 | QVariant oldVal = property (gPropertyMap [index].name);
|
---|
[7721] | 281 | Assert (oldVal.isValid() && oldVal.canConvert (QVariant::String));
|
---|
[382] | 282 |
|
---|
[7721] | 283 | if (oldVal.isValid() && oldVal.canConvert (QVariant::String) &&
|
---|
[382] | 284 | oldVal.toString() != value)
|
---|
| 285 | {
|
---|
| 286 | bool ok = setProperty (gPropertyMap [index].name, value);
|
---|
| 287 | Assert (ok);
|
---|
| 288 | if (ok)
|
---|
[2067] | 289 | {
|
---|
[5132] | 290 | /* The individual setter may have set a specific error */
|
---|
| 291 | if (!last_err.isNull())
|
---|
| 292 | return;
|
---|
| 293 |
|
---|
[2067] | 294 | last_err = QString::null;
|
---|
[382] | 295 | emit propertyChanged (gPropertyMap [index].publicName,
|
---|
| 296 | gPropertyMap [index].name);
|
---|
[2067] | 297 | }
|
---|
[382] | 298 | }
|
---|
| 299 | }
|
---|
| 300 |
|
---|