Index: trunk/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsInput.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsInput.cpp	(revision 65684)
+++ trunk/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsInput.cpp	(revision 65685)
@@ -54,6 +54,6 @@
 
 
-/** Global settings: Input page: Shortcut cell cache structure. */
-class UIShortcutCacheCell : public QITableViewCell
+/** Global settings: Input page: Shortcut cell data structure. */
+class UIDataShortcutCell : public QITableViewCell
 {
     Q_OBJECT;
@@ -64,5 +64,5 @@
       * @param  pParent  Brings the row this cell belongs too.
       * @param  strText  Brings the text describing this cell. */
-    UIShortcutCacheCell(QITableViewRow *pParent, const QString &strText)
+    UIDataShortcutCell(QITableViewRow *pParent, const QString &strText)
         : QITableViewCell(pParent)
         , m_strText(strText)
@@ -79,6 +79,6 @@
 
 
-/** Global settings: Input page: Shortcut cache structure. */
-class UIShortcutCacheRow : public QITableViewRow
+/** Global settings: Input page: Shortcut data structure. */
+class UIDataShortcutRow : public QITableViewRow
 {
     Q_OBJECT;
@@ -92,5 +92,5 @@
       * @param  strCurrentSequence  Brings the current held sequence.
       * @param  strDefaultSequence  Brings the default held sequence. */
-    UIShortcutCacheRow(QITableView *pParent,
+    UIDataShortcutRow(QITableView *pParent,
                        const QString &strKey,
                        const QString &strDescription,
@@ -108,5 +108,5 @@
 
     /** Constructs table row on the basis of @a other one. */
-    UIShortcutCacheRow(const UIShortcutCacheRow &other)
+    UIDataShortcutRow(const UIDataShortcutRow &other)
         : QITableViewRow(other.table())
         , m_strKey(other.key())
@@ -120,5 +120,5 @@
 
     /** Destructs table row. */
-    ~UIShortcutCacheRow()
+    ~UIDataShortcutRow()
     {
         /* Destroy cells: */
@@ -127,5 +127,5 @@
 
     /** Copies a table row from @a other one. */
-    UIShortcutCacheRow &operator=(const UIShortcutCacheRow &other)
+    UIDataShortcutRow &operator=(const UIDataShortcutRow &other)
     {
         /* Reassign variables: */
@@ -145,5 +145,5 @@
 
     /** Returns whether this row equals to @a other. */
-    bool operator==(const UIShortcutCacheRow &other) const
+    bool operator==(const UIDataShortcutRow &other) const
     {
         /* Compare by the key only: */
@@ -189,6 +189,6 @@
     {
         /* Create cells on the basis of description and current sequence: */
-        m_cells = qMakePair(new UIShortcutCacheCell(this, m_strDescription),
-                            new UIShortcutCacheCell(this, m_strCurrentSequence));
+        m_cells = qMakePair(new UIDataShortcutCell(this, m_strDescription),
+                            new UIDataShortcutCell(this, m_strCurrentSequence));
     }
 
@@ -213,16 +213,16 @@
 
     /** Holds the cell instances. */
-    QPair<UIShortcutCacheCell*, UIShortcutCacheCell*> m_cells;
+    QPair<UIDataShortcutCell*, UIDataShortcutCell*> m_cells;
 };
-typedef QList<UIShortcutCacheRow> UIShortcutCache;
-
-
-/** Global settings: Input page cache structure. */
-class UISettingsCacheGlobalInput
+typedef QList<UIDataShortcutRow> UIShortcutCache;
+
+
+/** Global settings: Input page data structure. */
+class UIDataSettingsGlobalInput
 {
 public:
 
     /** Constructs cache. */
-    UISettingsCacheGlobalInput()
+    UIDataSettingsGlobalInput()
         : m_fAutoCapture(false)
     {}
@@ -230,4 +230,6 @@
     /** Returns the shortcuts cache [full access]. */
     UIShortcutCache &shortcuts() { return m_shortcuts; }
+    /** Returns the shortcuts cache [read-only access]. */
+    const UIShortcutCache &shortcuts() const { return m_shortcuts; }
 
     /** Defines whether the keyboard auto-capture is @a fEnabled. */
@@ -235,4 +237,16 @@
     /** Returns whether the keyboard auto-capture is enabled. */
     bool autoCapture() const { return m_fAutoCapture; }
+
+    /** Returns whether the @a other passed data is equal to this one. */
+    bool equal(const UIDataSettingsGlobalInput &other) const
+    {
+        return (m_shortcuts == other.m_shortcuts) &&
+               (m_fAutoCapture == other.m_fAutoCapture);
+    }
+
+    /** Returns whether the @a other passed data is equal to this one. */
+    bool operator==(const UIDataSettingsGlobalInput &other) const { return equal(other); }
+    /** Returns whether the @a other passed data is different from this one. */
+    bool operator!=(const UIDataSettingsGlobalInput &other) const { return !equal(other); }
 
 private:
@@ -261,5 +275,5 @@
     /** Returns whether the @a item1 is more/less than the @a item2.
       * @note  Order depends on the one set through constructor, stored in m_order. */
-    bool operator()(const UIShortcutCacheRow &item1, const UIShortcutCacheRow &item2)
+    bool operator()(const UIDataShortcutRow &item1, const UIDataShortcutRow &item2)
     {
         switch (m_iColumn)
@@ -401,5 +415,5 @@
 {
     /* Load shortcuts: */
-    foreach (const UIShortcutCacheRow &item, shortcuts)
+    foreach (const UIDataShortcutRow &item, shortcuts)
     {
         /* Filter out unnecessary shortcuts: */
@@ -419,5 +433,5 @@
 {
     /* Save model items: */
-    foreach (const UIShortcutCacheRow &item, m_shortcuts)
+    foreach (const UIDataShortcutRow &item, m_shortcuts)
     {
         /* Search for corresponding cache item index: */
@@ -435,5 +449,5 @@
     /* Enumerate all the sequences: */
     QMap<QString, QString> usedSequences;
-    foreach (const UIShortcutCacheRow &item, m_shortcuts)
+    foreach (const UIDataShortcutRow &item, m_shortcuts)
         if (!item.currentSequence().isEmpty())
             usedSequences.insertMulti(item.currentSequence(), item.key());
@@ -624,5 +638,5 @@
                     int iIndex = index.row();
                     /* Set sequence to shortcut: */
-                    UIShortcutCacheRow &filteredShortcut = m_filteredShortcuts[iIndex];
+                    UIDataShortcutRow &filteredShortcut = m_filteredShortcuts[iIndex];
                     int iShortcutIndex = m_shortcuts.indexOf(filteredShortcut);
                     if (iShortcutIndex != -1)
@@ -652,9 +666,9 @@
     qStableSort(m_shortcuts.begin(), m_shortcuts.end(), UIShortcutCacheItemFunctor(iColumn, order));
     /* Make sure host-combo item is always the first one: */
-    UIShortcutCacheRow fakeHostComboItem(0, UIHostCombo::hostComboCacheKey(), QString(), QString(), QString());
+    UIDataShortcutRow fakeHostComboItem(0, UIHostCombo::hostComboCacheKey(), QString(), QString(), QString());
     int iIndexOfHostComboItem = m_shortcuts.indexOf(fakeHostComboItem);
     if (iIndexOfHostComboItem != -1)
     {
-        UIShortcutCacheRow hostComboItem = m_shortcuts.takeAt(iIndexOfHostComboItem);
+        UIDataShortcutRow hostComboItem = m_shortcuts.takeAt(iIndexOfHostComboItem);
         m_shortcuts.prepend(hostComboItem);
     }
@@ -684,5 +698,5 @@
     {
         /* Check if the description matches the filter: */
-        foreach (const UIShortcutCacheRow &item, m_shortcuts)
+        foreach (const UIDataShortcutRow &item, m_shortcuts)
         {
             /* If neither description nor sequence matches the filter, skip item: */
@@ -876,7 +890,13 @@
     UISettingsPageGlobal::fetchData(data);
 
-    /* Load to cache: */
-    m_pCache->shortcuts() << UIShortcutCacheRow(m_pMachineTable, UIHostCombo::hostComboCacheKey(), tr("Host Key Combination"),  m_settings.hostCombo(), QString());
-    const QMap<QString, UIShortcut>& shortcuts = gShortcutPool->shortcuts();
+    /* Clear cache initially: */
+    m_pCache->clear();
+
+    /* Prepare old data: */
+    UIDataSettingsGlobalInput oldData;
+
+    /* Gather old data: */
+    oldData.shortcuts() << UIDataShortcutRow(m_pMachineTable, UIHostCombo::hostComboCacheKey(), tr("Host Key Combination"),  m_settings.hostCombo(), QString());
+    const QMap<QString, UIShortcut> &shortcuts = gShortcutPool->shortcuts();
     const QList<QString> shortcutKeys = shortcuts.keys();
     foreach (const QString &strShortcutKey, shortcutKeys)
@@ -886,9 +906,12 @@
                                strShortcutKey.startsWith(GUI_Input_SelectorShortcuts) ? m_pSelectorTable : 0;
         AssertPtr(pParent);
-        m_pCache->shortcuts() << UIShortcutCacheRow(pParent, strShortcutKey, VBoxGlobal::removeAccelMark(shortcut.description()),
-                                                    shortcut.sequence().toString(QKeySequence::NativeText),
-                                                    shortcut.defaultSequence().toString(QKeySequence::NativeText));
-    }
-    m_pCache->setAutoCapture(m_settings.autoCapture());
+        oldData.shortcuts() << UIDataShortcutRow(pParent, strShortcutKey, VBoxGlobal::removeAccelMark(shortcut.description()),
+                                                 shortcut.sequence().toString(QKeySequence::NativeText),
+                                                 shortcut.defaultSequence().toString(QKeySequence::NativeText));
+    }
+    oldData.setAutoCapture(m_settings.autoCapture());
+
+    /* Cache old data: */
+    m_pCache->cacheInitialData(oldData);
 
     /* Upload properties & settings to data: */
@@ -898,8 +921,11 @@
 void UIGlobalSettingsInput::getFromCache()
 {
-    /* Fetch from cache: */
-    m_pSelectorModel->load(m_pCache->shortcuts());
-    m_pMachineModel->load(m_pCache->shortcuts());
-    m_pEnableAutoGrabCheckbox->setChecked(m_pCache->autoCapture());
+    /* Get old data from cache: */
+    const UIDataSettingsGlobalInput &oldData = m_pCache->base();
+
+    /* Load old data from cache: */
+    m_pSelectorModel->load(oldData.shortcuts());
+    m_pMachineModel->load(oldData.shortcuts());
+    m_pEnableAutoGrabCheckbox->setChecked(oldData.autoCapture());
 
     /* Revalidate: */
@@ -909,8 +935,14 @@
 void UIGlobalSettingsInput::putToCache()
 {
-    /* Upload to cache: */
-    m_pSelectorModel->save(m_pCache->shortcuts());
-    m_pMachineModel->save(m_pCache->shortcuts());
-    m_pCache->setAutoCapture(m_pEnableAutoGrabCheckbox->isChecked());
+    /* Prepare new data: */
+    UIDataSettingsGlobalInput newData = m_pCache->base();
+
+    /* Gather new data: */
+    m_pSelectorModel->save(newData.shortcuts());
+    m_pMachineModel->save(newData.shortcuts());
+    newData.setAutoCapture(m_pEnableAutoGrabCheckbox->isChecked());
+
+    /* Cache new data: */
+    m_pCache->cacheCurrentData(newData);
 }
 
@@ -920,14 +952,38 @@
     UISettingsPageGlobal::fetchData(data);
 
-    /* Save from cache: */
-    UIShortcutCacheRow fakeHostComboItem(0, UIHostCombo::hostComboCacheKey(), QString(), QString(), QString());
-    int iIndexOfHostComboItem = m_pCache->shortcuts().indexOf(fakeHostComboItem);
-    if (iIndexOfHostComboItem != -1)
-        m_settings.setHostCombo(m_pCache->shortcuts()[iIndexOfHostComboItem].currentSequence());
-    QMap<QString, QString> sequences;
-    foreach (const UIShortcutCacheRow &item, m_pCache->shortcuts())
-        sequences.insert(item.key(), item.currentSequence());
-    gShortcutPool->setOverrides(sequences);
-    m_settings.setAutoCapture(m_pCache->autoCapture());
+    // WORKAROUND:
+    // For now we are using out-of-the-box Qt functions to search for a corresponding shortcuts.
+    // Those functions assumes that container elements implement operator==() which we can use
+    // either for "index-match" (to just find shortcut item independent on parameters) or for
+    // "full-match" (to find exact shortcut item including all parameters) but not for both,
+    // so since "index-match" is most commonly used, we need separate "full-match" functor
+    // to check whether the shortcut item was changed, for now we can't do that.
+
+    /* Save host-combo shortcut from cache: */
+    UIDataShortcutRow fakeHostComboItem(0, UIHostCombo::hostComboCacheKey(), QString(), QString(), QString());
+    //const int iIndexOfHostComboItemBase = m_pCache->base().shortcuts().indexOf(fakeHostComboItem);
+    const int iIndexOfHostComboItemData = m_pCache->data().shortcuts().indexOf(fakeHostComboItem);
+    if (   iIndexOfHostComboItemData != -1
+        //&& iIndexOfHostComboItemData != iIndexOfHostComboItemBase
+        )
+        m_settings.setHostCombo(m_pCache->data().shortcuts().at(iIndexOfHostComboItemData).currentSequence());
+
+    /* Save other shortcut sequences from cache: */
+    QMap<QString, QString> sequencesBase;
+    QMap<QString, QString> sequencesData;
+    foreach (const UIDataShortcutRow &item, m_pCache->base().shortcuts())
+        sequencesBase.insert(item.key(), item.currentSequence());
+    foreach (const UIDataShortcutRow &item, m_pCache->data().shortcuts())
+        sequencesData.insert(item.key(), item.currentSequence());
+    if (sequencesData != sequencesBase)
+        gShortcutPool->setOverrides(sequencesData);
+
+    /* Save new data from cache: */
+    if (m_pCache->wasChanged())
+    {
+        /* Save other things from cache: */
+        if (m_pCache->data().autoCapture() != m_pCache->base().autoCapture())
+            m_settings.setAutoCapture(m_pCache->data().autoCapture());
+    }
 
     /* Upload properties & settings to data: */
@@ -964,5 +1020,4 @@
 }
 
-/* Navigation stuff: */
 void UIGlobalSettingsInput::setOrderAfter(QWidget *pWidget)
 {
@@ -971,5 +1026,4 @@
 }
 
-/* Translation stuff: */
 void UIGlobalSettingsInput::retranslateUi()
 {
Index: trunk/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsInput.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsInput.h	(revision 65684)
+++ trunk/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsInput.h	(revision 65685)
@@ -26,7 +26,8 @@
 class QTabWidget;
 class QLineEdit;
-class UISettingsCacheGlobalInput;
+class UIDataSettingsGlobalInput;
 class UIHotKeyTableModel;
 class UIHotKeyTable;
+typedef UISettingsCache<UIDataSettingsGlobalInput> UISettingsCacheGlobalInput;
 
 
