VirtualBox

Changeset 95077 in vbox for trunk/src/VBox


Ignore:
Timestamp:
May 24, 2022 3:10:30 PM (3 years ago)
Author:
vboxsync
Message:

FE/Qt/Ds: bugref:6899: Machine settings: Shared Folders page accessibility improvements; Moving editor related stuff into separate UISharedFoldersEditor widget.

Location:
trunk/src/VBox/Frontends/VirtualBox
Files:
4 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk

    r95031 r95077  
    922922        src/settings/editors/UIScaleFactorEditor.h \
    923923        src/settings/editors/UISharedClipboardEditor.h \
     924        src/settings/editors/UISharedFoldersEditor.h \
    924925        src/settings/editors/UIShortcutConfigurationEditor.h \
    925926        src/settings/editors/UISnapshotFolderEditor.h \
     
    10801081        src/settings/editors/UIHotKeyEditor.cpp \
    10811082        src/settings/editors/UILanguageSettingsEditor.cpp \
     1083        src/settings/editors/UISharedFoldersEditor.cpp \
    10821084        src/settings/editors/UIShortcutConfigurationEditor.cpp \
    10831085        src/settings/machine/UIMachineSettingsNetwork.cpp \
    10841086        src/settings/machine/UIMachineSettingsSerial.cpp \
    1085         src/settings/machine/UIMachineSettingsSF.cpp \
    10861087        src/settings/machine/UIMachineSettingsStorage.cpp \
    10871088        src/settings/machine/UIMachineSettingsUSB.cpp \
     
    14911492        src/settings/editors/UIScaleFactorEditor.cpp \
    14921493        src/settings/editors/UISharedClipboardEditor.cpp \
     1494        src/settings/editors/UISharedFoldersEditor.cpp \
    14931495        src/settings/editors/UIShortcutConfigurationEditor.cpp \
    14941496        src/settings/editors/UISnapshotFolderEditor.cpp \
  • trunk/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataDefs.h

    r94651 r95077  
    876876
    877877
     878/** Common UI: Shared Folder types. */
     879enum UISharedFolderType
     880{
     881    UISharedFolderType_Machine,
     882    UISharedFolderType_Console
     883};
     884
     885
    878886/** Common UI: Wizard types. */
    879887enum WizardType
  • trunk/src/VBox/Frontends/VirtualBox/src/settings/editors/UISharedFoldersEditor.cpp

    r95076 r95077  
    11/* $Id$ */
    22/** @file
    3  * VBox Qt GUI - UILanguageSettingsEditor class implementation.
     3 * VBox Qt GUI - UISharedFoldersEditor class implementation.
    44 */
    55
     
    1717
    1818/* Qt includes: */
    19 #include <QDir>
    2019#include <QHeaderView>
    21 #include <QPainter>
     20#include <QMenu>
    2221#include <QRegExp>
    23 #include <QTranslator>
     22#include <QTimer>
    2423#include <QVBoxLayout>
    2524
    2625/* GUI includes: */
    2726#include "QILabelSeparator.h"
    28 #include "QIRichTextLabel.h"
     27#include "QIToolBar.h"
    2928#include "QITreeWidget.h"
    30 #include "UILanguageSettingsEditor.h"
    31 #include "UITranslator.h"
    32 
    33 /* Other VBox includes: */
    34 #include <iprt/assert.h>
    35 #include <iprt/errcore.h>
    36 #include <iprt/path.h>
    37 
    38 
    39 /** QITreeWidgetItem subclass representing language tree-widget item. */
    40 class UILanguageItem : public QITreeWidgetItem
     29#include "UIIconPool.h"
     30#include "UIMachineSettingsSFDetails.h"
     31#include "UISharedFoldersEditor.h"
     32#include "VBoxUtils.h"
     33
     34
     35/** Shared Folder tree-widget item. */
     36class SFTreeViewItem : public QITreeWidgetItem, public UIDataSharedFolder
    4137{
    4238    Q_OBJECT;
     
    4440public:
    4541
    46     /** Constructs language tree-widget item passing @a pParent to the base-class.
    47       * @param  translator  Brings the translator this item is related to.
    48       * @param  strId       Brings the language ID this item is related to.
    49       * @param  fBuiltIn    Brings whether the language this item related to is built in. */
    50     UILanguageItem(QITreeWidget *pParent, const QTranslator &translator,
    51                    const QString &strId, bool fBuiltIn = false);
    52     /** Constructs language tree-widget item passing @a pParent to the base-class.
    53       * @param  strId       Brings the language ID this item is related to.
    54       * @note   This is a constructor for an invalid language ID (i.e. when a
    55       *         language file is missing or corrupt). */
    56     UILanguageItem(QITreeWidget *pParent, const QString &strId);
    57     /** Constructs language tree-widget item passing @a pParent to the base-class.
    58       * @note   This is a constructor for a default language ID
    59       *         (column 1 will be set to QString()). */
    60     UILanguageItem(QITreeWidget *pParent);
    61 
    62     /** Returns whether this item is for built in language. */
    63     bool isBuiltIn() const { return m_fBuiltIn; }
    64 
    65     /** Returns whether this item is less than @a another one. */
    66     bool operator<(const QTreeWidgetItem &another) const;
     42    /** Format type. */
     43    enum FormatType
     44    {
     45        FormatType_Invalid,
     46        FormatType_EllipsisStart,
     47        FormatType_EllipsisMiddle,
     48        FormatType_EllipsisEnd,
     49        FormatType_EllipsisFile
     50    };
     51
     52    /** Constructs shared folder type (root) item.
     53      * @param  pParent    Brings the item parent.
     54      * @param  enmFormat  Brings the item format type. */
     55    SFTreeViewItem(QITreeWidget *pParent, FormatType enmFormat);
     56    /** Constructs shared folder (child) item.
     57      * @param  pParent    Brings the item parent.
     58      * @param  enmFormat  Brings the item format type. */
     59    SFTreeViewItem(SFTreeViewItem *pParent, FormatType enmFormat);
     60
     61    /** Returns whether this item is less than the @a other one. */
     62    bool operator<(const QTreeWidgetItem &other) const;
     63
     64    /** Returns child item number @a iIndex. */
     65    SFTreeViewItem *child(int iIndex) const;
     66
     67    /** Returns text of item number @a iIndex. */
     68    QString getText(int iIndex) const;
     69
     70    /** Updates item fields. */
     71    void updateFields();
     72
     73    /** Adjusts item layout. */
     74    void adjustText();
     75
     76protected:
     77
     78    /** Returns default text. */
     79    virtual QString defaultText() const RT_OVERRIDE;
    6780
    6881private:
    6982
    70     /** Performs translation using passed @a translator for a
    71       * passed @a pContext, @a pSourceText and @a pComment. */
    72     QString tratra(const QTranslator &translator, const char *pContext,
    73                    const char *pSourceText, const char *pComment);
    74 
    75     /** Holds whether this item is for built in language. */
    76     bool  m_fBuiltIn;
     83    /** Performs item @a iColumn processing. */
     84    void processColumn(int iColumn);
     85
     86    /** Holds the item format type. */
     87    FormatType   m_enmFormat;
     88    /** Holds the item text fields. */
     89    QStringList  m_fields;
    7790};
    7891
    7992
    8093/*********************************************************************************************************************************
    81 *   Class UILanguageItem implementation.                                                                                         *
     94*   Class SFTreeViewItem implementation.                                                                                         *
    8295*********************************************************************************************************************************/
    8396
    84 UILanguageItem::UILanguageItem(QITreeWidget *pParent, const QTranslator &translator,
    85                                const QString &strId, bool fBuiltIn /* = false */)
     97SFTreeViewItem::SFTreeViewItem(QITreeWidget *pParent, FormatType enmFormat)
    8698    : QITreeWidgetItem(pParent)
    87     , m_fBuiltIn(fBuiltIn)
    88 {
    89     Assert(!strId.isEmpty());
    90 
    91     /* Note: context/source/comment arguments below must match strings used in UITranslator::languageName() and friends
    92      *       (the latter are the source of information for the lupdate tool that generates translation files). */
    93 
    94     const QString strNativeLanguage = tratra(translator, "@@@", "English", "Native language name");
    95     const QString strNativeCountry = tratra(translator, "@@@", "--", "Native language country name "
    96                                                                      "(empty if this language is for all countries)");
    97 
    98     const QString strEnglishLanguage = tratra(translator, "@@@", "English", "Language name, in English");
    99     const QString strEnglishCountry = tratra(translator, "@@@", "--", "Language country name, in English "
    100                                                                       "(empty if native country name is empty)");
    101 
    102     const QString strTranslatorsName = tratra(translator, "@@@", "Oracle Corporation", "Comma-separated list of translators");
    103 
    104     QString strItemName = strNativeLanguage;
    105     QString strLanguageName = strEnglishLanguage;
    106 
    107     if (!m_fBuiltIn)
    108     {
    109         if (strNativeCountry != "--")
    110             strItemName += " (" + strNativeCountry + ")";
    111 
    112         if (strEnglishCountry != "--")
    113             strLanguageName += " (" + strEnglishCountry + ")";
    114 
    115         if (strItemName != strLanguageName)
    116             strLanguageName = strItemName + " / " + strLanguageName;
    117     }
     99    , m_enmFormat(enmFormat)
     100{
     101    setFirstColumnSpanned(true);
     102    setFlags(flags() ^ Qt::ItemIsSelectable);
     103}
     104
     105SFTreeViewItem::SFTreeViewItem(SFTreeViewItem *pParent, FormatType enmFormat)
     106    : QITreeWidgetItem(pParent)
     107    , m_enmFormat(enmFormat)
     108{
     109}
     110
     111bool SFTreeViewItem::operator<(const QTreeWidgetItem &other) const
     112{
     113    /* Root items should always been sorted by type field: */
     114    return parentItem() ? text(0) < other.text(0) :
     115                          text(1) < other.text(1);
     116}
     117
     118SFTreeViewItem *SFTreeViewItem::child(int iIndex) const
     119{
     120    QTreeWidgetItem *pItem = QTreeWidgetItem::child(iIndex);
     121    return pItem ? static_cast<SFTreeViewItem*>(pItem) : 0;
     122}
     123
     124QString SFTreeViewItem::getText(int iIndex) const
     125{
     126    return iIndex >= 0 && iIndex < m_fields.size() ? m_fields.at(iIndex) : QString();
     127}
     128
     129void SFTreeViewItem::updateFields()
     130{
     131    /* Clear fields: */
     132    m_fields.clear();
     133
     134    /* For root items: */
     135    if (!parentItem())
     136        m_fields << m_strName
     137                 << QString::number((int)m_enmType);
     138    /* For child items: */
    118139    else
    119     {
    120         strItemName += tr(" (built-in)", "Language");
    121         strLanguageName += tr(" (built-in)", "Language");
    122     }
    123 
    124     setText(0, strItemName);
    125     setText(1, strId);
    126     setText(2, strLanguageName);
    127     setText(3, strTranslatorsName);
    128 
    129     /* Current language appears in bold: */
    130     if (text(1) == UITranslator::languageId())
    131     {
    132         QFont fnt = font(0);
    133         fnt.setBold(true);
    134         setFont(0, fnt);
    135     }
    136 }
    137 
    138 UILanguageItem::UILanguageItem(QITreeWidget *pParent, const QString &strId)
    139     : QITreeWidgetItem(pParent)
    140     , m_fBuiltIn(false)
    141 {
    142     Assert(!strId.isEmpty());
    143 
    144     setText(0, QString("<%1>").arg(strId));
    145     setText(1, strId);
    146     setText(2, tr("<unavailable>", "Language"));
    147     setText(3, tr("<unknown>", "Author(s)"));
    148 
    149     /* Invalid language appears in italic: */
    150     QFont fnt = font(0);
    151     fnt.setItalic(true);
    152     setFont(0, fnt);
    153 }
    154 
    155 UILanguageItem::UILanguageItem(QITreeWidget *pParent)
    156     : QITreeWidgetItem(pParent)
    157     , m_fBuiltIn(false)
    158 {
    159     setText(0, tr("Default", "Language"));
    160     setText(1, QString());
    161     /* Empty strings of some reasonable length to prevent the info part
    162      * from being shrinked too much when the list wants to be wider */
    163     setText(2, "                ");
    164     setText(3, "                ");
    165 
    166     /* Default language item appears in italic: */
    167     QFont fnt = font(0);
    168     fnt.setItalic(true);
    169     setFont(0, fnt);
    170 }
    171 
    172 bool UILanguageItem::operator<(const QTreeWidgetItem &another) const
    173 {
    174     QString thisId = text(1);
    175     QString thatId = another.text(1);
    176     if (thisId.isNull())
    177         return true;
    178     if (thatId.isNull())
    179         return false;
    180     if (m_fBuiltIn)
    181         return true;
    182     if (another.type() == ItemType && ((UILanguageItem*)&another)->m_fBuiltIn)
    183         return false;
    184     return QITreeWidgetItem::operator<(another);
    185 }
    186 
    187 QString UILanguageItem::tratra(const QTranslator &translator, const char *pContext,
    188                                const char *pSourceText, const char *pComment)
    189 {
    190     QString strMsg = translator.translate(pContext, pSourceText, pComment);
    191     /* Return the source text if no translation is found: */
    192     if (strMsg.isEmpty())
    193         strMsg = QString(pSourceText);
    194     return strMsg;
     140        m_fields << m_strName
     141                 << m_strPath
     142                 << (m_fWritable ? tr("Full") : tr("Read-only"))
     143                 << (m_fAutoMount ? tr("Yes") : "")
     144                 << m_strAutoMountPoint;
     145
     146    /* Adjust item layout: */
     147    adjustText();
     148}
     149
     150void SFTreeViewItem::adjustText()
     151{
     152    for (int i = 0; i < treeWidget()->columnCount(); ++i)
     153        processColumn(i);
     154}
     155
     156QString SFTreeViewItem::defaultText() const
     157{
     158    return parentItem()
     159         ? tr("%1, %2: %3, %4: %5, %6: %7, %8: %9",
     160              "col.1 text, col.2 name: col.2 text, col.3 name: col.3 text, col.4 name: col.4 text, col.5 name: col.5 text")
     161              .arg(text(0))
     162              .arg(parentTree()->headerItem()->text(1)).arg(text(1))
     163              .arg(parentTree()->headerItem()->text(2)).arg(text(2))
     164              .arg(parentTree()->headerItem()->text(3)).arg(text(3))
     165              .arg(parentTree()->headerItem()->text(4)).arg(text(4))
     166         : text(0);
     167}
     168
     169void SFTreeViewItem::processColumn(int iColumn)
     170{
     171    QString strOneString = getText(iColumn);
     172    if (strOneString.isNull())
     173        return;
     174    const QFontMetrics fm = treeWidget()->fontMetrics();
     175#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
     176    const int iOldSize = fm.horizontalAdvance(strOneString);
     177#else
     178    const int iOldSize = fm.width(strOneString);
     179#endif
     180    const int iItemIndent = parentItem() ? treeWidget()->indentation() * 2 : treeWidget()->indentation();
     181#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
     182    int iIndentSize = fm.horizontalAdvance(" ... ");
     183#else
     184    int iIndentSize = fm.width(" ... ");
     185#endif
     186    if (iColumn == 0)
     187        iIndentSize += iItemIndent;
     188    const int cWidth = !parentItem() ? treeWidget()->viewport()->width() : treeWidget()->columnWidth(iColumn);
     189
     190    /* Compress text: */
     191    int iStart = 0;
     192    int iFinish = 0;
     193    int iPosition = 0;
     194    int iTextWidth = 0;
     195    do
     196    {
     197#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
     198        iTextWidth = fm.horizontalAdvance(strOneString);
     199#else
     200        iTextWidth = fm.width(strOneString);
     201#endif
     202        if (   iTextWidth
     203            && iTextWidth + iIndentSize > cWidth)
     204        {
     205            iStart = 0;
     206            iFinish = strOneString.length();
     207
     208            /* Selecting remove position: */
     209            switch (m_enmFormat)
     210            {
     211                case FormatType_EllipsisStart:
     212                    iPosition = iStart;
     213                    break;
     214                case FormatType_EllipsisMiddle:
     215                    iPosition = (iFinish - iStart) / 2;
     216                    break;
     217                case FormatType_EllipsisEnd:
     218                    iPosition = iFinish - 1;
     219                    break;
     220                case FormatType_EllipsisFile:
     221                {
     222                    const QRegExp regExp("([\\\\/][^\\\\^/]+[\\\\/]?$)");
     223                    const int iNewFinish = regExp.indexIn(strOneString);
     224                    if (iNewFinish != -1)
     225                        iFinish = iNewFinish;
     226                    iPosition = (iFinish - iStart) / 2;
     227                    break;
     228                }
     229                default:
     230                    AssertMsgFailed(("Invalid format type\n"));
     231            }
     232
     233            if (iPosition == iFinish)
     234               break;
     235
     236            strOneString.remove(iPosition, 1);
     237        }
     238    }
     239    while (   iTextWidth
     240           && (iTextWidth + iIndentSize > cWidth));
     241
     242    if (iPosition || m_enmFormat == FormatType_EllipsisFile)
     243        strOneString.insert(iPosition, "...");
     244#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
     245    const int iNewSize = fm.horizontalAdvance(strOneString);
     246#else
     247    const int iNewSize = fm.width(strOneString);
     248#endif
     249    setText(iColumn, iNewSize < iOldSize ? strOneString : m_fields.at(iColumn));
     250    setToolTip(iColumn, text(iColumn) == getText(iColumn) ? QString() : getText(iColumn));
     251
     252    /* Calculate item's size-hint: */
     253#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
     254    setSizeHint(iColumn, QSize(fm.horizontalAdvance(QString("  %1  ").arg(getText(iColumn))), fm.height()));
     255#else
     256    setSizeHint(iColumn, QSize(fm.width(QString("  %1  ").arg(getText(iColumn))), fm.height()));
     257#endif
    195258}
    196259
    197260
    198261/*********************************************************************************************************************************
    199 *   Class UILanguageSettingsEditor implementation.                                                                               *
     262*   Class UISharedFoldersEditor implementation.                                                                                  *
    200263*********************************************************************************************************************************/
    201264
    202 UILanguageSettingsEditor::UILanguageSettingsEditor(QWidget *pParent /* = 0 */)
     265UISharedFoldersEditor::UISharedFoldersEditor(QWidget *pParent /* = 0 */)
    203266    : QIWithRetranslateUI<QWidget>(pParent)
    204     , m_fPolished(false)
    205267    , m_pLabelSeparator(0)
    206268    , m_pTreeWidget(0)
    207     , m_pLabelInfo(0)
    208269{
    209270    prepare();
    210271}
    211272
    212 void UILanguageSettingsEditor::setValue(const QString &strValue)
     273void UISharedFoldersEditor::setValue(const QList<UIDataSharedFolder> &guiValue)
    213274{
    214275    /* Update cached value and
    215276     * tree-widget if value has changed: */
    216     if (m_strValue != strValue)
    217     {
    218         m_strValue = strValue;
    219         if (m_pTreeWidget)
    220             reloadLanguageTree(m_strValue);
    221     }
    222 }
    223 
    224 QString UILanguageSettingsEditor::value() const
    225 {
    226     QTreeWidgetItem *pCurrentItem = m_pTreeWidget ? m_pTreeWidget->currentItem() : 0;
    227     return pCurrentItem ? pCurrentItem->text(1) : m_strValue;
    228 }
    229 
    230 void UILanguageSettingsEditor::retranslateUi()
     277    if (m_guiValue != guiValue)
     278    {
     279        m_guiValue = guiValue;
     280        reloadTree();
     281    }
     282}
     283
     284QList<UIDataSharedFolder> UISharedFoldersEditor::value() const
     285{
     286    /* Sanity check: */
     287    if (!m_pTreeWidget)
     288        return m_guiValue;
     289
     290    /* Prepare result: */
     291    QList<UIDataSharedFolder> result;
     292
     293    /* For each folder type: */
     294    QTreeWidgetItem *pMainRootItem = m_pTreeWidget->invisibleRootItem();
     295    for (int iFolderTypeIndex = 0; iFolderTypeIndex < pMainRootItem->childCount(); ++iFolderTypeIndex)
     296    {
     297        /* Get folder root item: */
     298        const SFTreeViewItem *pFolderTypeRoot = static_cast<SFTreeViewItem*>(pMainRootItem->child(iFolderTypeIndex));
     299
     300        /* For each folder of current type: */
     301        for (int iFolderIndex = 0; iFolderIndex < pFolderTypeRoot->childCount(); ++iFolderIndex)
     302        {
     303            /* Gather and cache new data: */
     304            const SFTreeViewItem *pItem = static_cast<SFTreeViewItem*>(pFolderTypeRoot->child(iFolderIndex));
     305            result << *pItem;
     306        }
     307    }
     308
     309    /* Return result: */
     310    return result;
     311}
     312
     313void UISharedFoldersEditor::setFeatureAvailable(bool fAvailable)
     314{
     315    if (m_pLabelSeparator)
     316        m_pLabelSeparator->setEnabled(fAvailable);
     317    if (m_pTreeWidget)
     318        m_pTreeWidget->setEnabled(fAvailable);
     319    if (m_pToolbar)
     320        m_pToolbar->setEnabled(fAvailable);
     321}
     322
     323void UISharedFoldersEditor::setFoldersAvailable(UISharedFolderType enmType, bool fAvailable)
     324{
     325    m_foldersAvailable[enmType] = fAvailable;
     326    updateRootItemsVisibility();
     327}
     328
     329void UISharedFoldersEditor::retranslateUi()
    231330{
    232331    /* Translate separator label: */
    233332    if (m_pLabelSeparator)
    234         m_pLabelSeparator->setText(tr("&Interface Languages"));
     333        m_pLabelSeparator->setText(tr("Shared &Folders"));
    235334
    236335    /* Translate tree-widget: */
    237336    if (m_pTreeWidget)
    238337    {
    239         m_pTreeWidget->setWhatsThis(tr("Lists all available user interface languages. The effective language is written "
    240                                        "in bold. Select Default to reset to the system default language."));
     338        m_pTreeWidget->setWhatsThis(tr("Lists all shared folders accessible to this machine. Use 'net use x: \\\\vboxsvr\\share' "
     339                                       "to access a shared folder named <i>share</i> from a DOS-like OS, or 'mount -t vboxsf "
     340                                       "share mount_point' to access it from a Linux OS. This feature requires Guest Additions."));
    241341
    242342        /* Translate tree-widget header: */
     
    244344        if (pTreeWidgetHeaderItem)
    245345        {
    246             pTreeWidgetHeaderItem->setText(3, tr("Author"));
    247             pTreeWidgetHeaderItem->setText(2, tr("Language"));
    248             pTreeWidgetHeaderItem->setText(1, tr("Id"));
     346            pTreeWidgetHeaderItem->setText(4, tr("At"));
     347            pTreeWidgetHeaderItem->setText(3, tr("Auto Mount"));
     348            pTreeWidgetHeaderItem->setText(2, tr("Access"));
     349            pTreeWidgetHeaderItem->setText(1, tr("Path"));
    249350            pTreeWidgetHeaderItem->setText(0, tr("Name"));
    250351        }
    251352
    252353        /* Update tree-widget contents finally: */
    253         reloadLanguageTree(m_strValue);
    254     }
    255 }
    256 
    257 void UILanguageSettingsEditor::showEvent(QShowEvent *pEvent)
     354        reloadTree();
     355    }
     356
     357    /* Translate actions: */
     358    if (m_pActionAdd)
     359    {
     360        m_pActionAdd->setText(tr("Add Shared Folder"));
     361        m_pActionAdd->setToolTip(tr("Adds new shared folder."));
     362        m_pActionAdd->setToolTip(m_pActionAdd->whatsThis());
     363    }
     364    if (m_pActionEdit)
     365    {
     366        m_pActionEdit->setText(tr("Edit Shared Folder"));
     367        m_pActionEdit->setToolTip(tr("Edits selected shared folder."));
     368        m_pActionEdit->setToolTip(m_pActionEdit->whatsThis());
     369    }
     370    if (m_pActionRemove)
     371    {
     372        m_pActionRemove->setText(tr("Remove Shared Folder"));
     373        m_pActionRemove->setToolTip(tr("Removes selected shared folder."));
     374        m_pActionRemove->setToolTip(m_pActionRemove->whatsThis());
     375    }
     376}
     377
     378void UISharedFoldersEditor::showEvent(QShowEvent *pEvent)
    258379{
    259380    /* Call to base-class: */
    260381    QIWithRetranslateUI<QWidget>::showEvent(pEvent);
    261382
    262     /* Polish if necessary: */
    263     if (!m_fPolished)
    264     {
    265         polishEvent(pEvent);
    266         m_fPolished = true;
    267     }
    268 }
    269 
    270 void UILanguageSettingsEditor::polishEvent(QShowEvent * /* pEvent */)
    271 {
    272     /* Remember current info-label width: */
    273     m_pLabelInfo->setMinimumTextWidth(m_pLabelInfo->width());
    274 }
    275 
    276 void UILanguageSettingsEditor::sltHandleItemPainting(QTreeWidgetItem *pItem, QPainter *pPainter)
    277 {
    278     /* We are always expecting an item: */
     383    /* Connect header-resize signal just before widget is shown
     384     * after all the items properly loaded and initialized: */
     385    connect(m_pTreeWidget->header(), &QHeaderView::sectionResized,
     386            this, &UISharedFoldersEditor::sltAdjustTreeFields,
     387            Qt::UniqueConnection);
     388
     389    /* Adjusting size after all pending show events are processed: */
     390    QTimer::singleShot(0, this, SLOT(sltAdjustTree()));
     391}
     392
     393void UISharedFoldersEditor::resizeEvent(QResizeEvent * /* pEvent */)
     394{
     395    sltAdjustTree();
     396}
     397
     398void UISharedFoldersEditor::sltAdjustTree()
     399{
     400    /*
     401     * Calculates required columns sizes to max out column 2
     402     * and let all other columns stay at their minimum sizes.
     403     *
     404     * Columns
     405     * 0 = Tree view / name
     406     * 1 = Path
     407     * 2 = Writable flag
     408     * 3 = Auto-mount flag
     409     * 4 = Auto mount point
     410     */
     411    QAbstractItemView *pItemView = m_pTreeWidget;
     412    QHeaderView *pItemHeader = m_pTreeWidget->header();
     413    const int iTotal = m_pTreeWidget->viewport()->width();
     414
     415    const int mw0 = qMax(pItemView->sizeHintForColumn(0), pItemHeader->sectionSizeHint(0));
     416    const int mw2 = qMax(pItemView->sizeHintForColumn(2), pItemHeader->sectionSizeHint(2));
     417    const int mw3 = qMax(pItemView->sizeHintForColumn(3), pItemHeader->sectionSizeHint(3));
     418    const int mw4 = qMax(pItemView->sizeHintForColumn(4), pItemHeader->sectionSizeHint(4));
     419#if 0 /** @todo Neither approach is perfect.  Short folder names, short paths, plenty of white space, but there is often '...' in column 0. */
     420
     421    const int w0 = mw0 < iTotal / 5 ? mw0 : iTotal / 5;
     422    const int w2 = mw2 < iTotal / 5 ? mw2 : iTotal / 5;
     423    const int w3 = mw3 < iTotal / 5 ? mw3 : iTotal / 5;
     424    const int w4 = mw4 < iTotal / 5 ? mw4 : iTotal / 5;
     425
     426    /* Giving 1st column all the available space. */
     427    const int w1 = iTotal - w0 - w2 - w3 - w4;
     428#else
     429    const int mw1 = qMax(pItemView->sizeHintForColumn(1), pItemHeader->sectionSizeHint(1));
     430    const int iHintTotal = mw0 + mw1 + mw2 + mw3 + mw4;
     431    int w0, w1, w2, w3, w4;
     432    int cExcess = iTotal - iHintTotal;
     433    if (cExcess >= 0)
     434    {
     435        /* give excess width to column 1 (path) */
     436        w0 = mw0;
     437        w1 = mw1 + cExcess;
     438        w2 = mw2;
     439        w3 = mw3;
     440        w4 = mw4;
     441    }
     442    else
     443    {
     444        w0 = mw0 < iTotal / 5 ? mw0 : iTotal / 5;
     445        w2 = mw2 < iTotal / 5 ? mw2 : iTotal / 5;
     446        w3 = mw3 < iTotal / 5 ? mw3 : iTotal / 5;
     447        w4 = mw4 < iTotal / 5 ? mw4 : iTotal / 5;
     448        w1 = iTotal - w0 - w2 - w3 - w4;
     449    }
     450#endif
     451    m_pTreeWidget->setColumnWidth(0, w0);
     452    m_pTreeWidget->setColumnWidth(1, w1);
     453    m_pTreeWidget->setColumnWidth(2, w2);
     454    m_pTreeWidget->setColumnWidth(3, w3);
     455    m_pTreeWidget->setColumnWidth(4, w4);
     456}
     457
     458void UISharedFoldersEditor::sltAdjustTreeFields()
     459{
     460    QTreeWidgetItem *pMainRoot = m_pTreeWidget->invisibleRootItem();
     461    for (int i = 0; i < pMainRoot->childCount(); ++i)
     462    {
     463        SFTreeViewItem *pSubRoot = static_cast<SFTreeViewItem*>(pMainRoot->child(i));
     464        pSubRoot->adjustText();
     465        for (int j = 0; j < pSubRoot->childCount(); ++j)
     466        {
     467            SFTreeViewItem *pItem = static_cast<SFTreeViewItem*>(pSubRoot->child(j));
     468            pItem->adjustText();
     469        }
     470    }
     471}
     472
     473void UISharedFoldersEditor::sltHandleCurrentItemChange(QTreeWidgetItem *pCurrentItem)
     474{
     475    if (pCurrentItem && pCurrentItem->parent() && !pCurrentItem->isSelected())
     476        pCurrentItem->setSelected(true);
     477    const bool fAddEnabled = pCurrentItem;
     478    const bool fRemoveEnabled = fAddEnabled && pCurrentItem->parent();
     479    m_pActionAdd->setEnabled(fAddEnabled);
     480    m_pActionEdit->setEnabled(fRemoveEnabled);
     481    m_pActionRemove->setEnabled(fRemoveEnabled);
     482}
     483
     484void UISharedFoldersEditor::sltHandleDoubleClick(QTreeWidgetItem *pItem)
     485{
     486    const bool fEditEnabled = pItem && pItem->parent();
     487    if (fEditEnabled)
     488        sltEditFolder();
     489}
     490
     491void UISharedFoldersEditor::sltHandleContextMenuRequest(const QPoint &position)
     492{
     493    QMenu menu;
     494    QTreeWidgetItem *pItem = m_pTreeWidget->itemAt(position);
     495    if (m_pTreeWidget->isEnabled() && pItem && pItem->flags() & Qt::ItemIsSelectable)
     496    {
     497        menu.addAction(m_pActionEdit);
     498        menu.addAction(m_pActionRemove);
     499    }
     500    else
     501    {
     502        menu.addAction(m_pActionAdd);
     503    }
     504    if (!menu.isEmpty())
     505        menu.exec(m_pTreeWidget->viewport()->mapToGlobal(position));
     506}
     507
     508void UISharedFoldersEditor::sltAddFolder()
     509{
     510    /* Configure folder details dialog: */
     511    UIMachineSettingsSFDetails dlgFolderDetails(UIMachineSettingsSFDetails::AddType,
     512                                                m_foldersAvailable.value(UISharedFolderType_Console),
     513                                                usedList(true),
     514                                                this);
     515
     516    /* Run folder details dialog: */
     517    if (dlgFolderDetails.exec() == QDialog::Accepted)
     518    {
     519        const QString strName = dlgFolderDetails.name();
     520        const QString strPath = dlgFolderDetails.path();
     521        const UISharedFolderType enmType = dlgFolderDetails.isPermanent() ? UISharedFolderType_Machine : UISharedFolderType_Console;
     522        /* Shared folder's name & path could not be empty: */
     523        Assert(!strName.isEmpty() && !strPath.isEmpty());
     524
     525        /* Prepare new data: */
     526        UIDataSharedFolder newFolderData;
     527        newFolderData.m_enmType = enmType;
     528        newFolderData.m_strName = strName;
     529        newFolderData.m_strPath = strPath;
     530        newFolderData.m_fWritable = dlgFolderDetails.isWriteable();
     531        newFolderData.m_fAutoMount = dlgFolderDetails.isAutoMounted();
     532        newFolderData.m_strAutoMountPoint = dlgFolderDetails.autoMountPoint();
     533
     534        /* Add new folder item: */
     535        addSharedFolderItem(newFolderData, true /* its new? */);
     536
     537        /* Sort tree-widget before adjusting: */
     538        m_pTreeWidget->sortItems(0, Qt::AscendingOrder);
     539        /* Adjust tree-widget finally: */
     540        sltAdjustTree();
     541    }
     542}
     543
     544void UISharedFoldersEditor::sltEditFolder()
     545{
     546    /* Check current folder item: */
     547    SFTreeViewItem *pItem = static_cast<SFTreeViewItem*>(m_pTreeWidget->currentItem());
    279548    AssertPtrReturnVoid(pItem);
    280     AssertReturnVoid(pItem->type() == QITreeWidgetItem::ItemType);
    281 
    282     /* An item of required type: */
    283     QITreeWidgetItem *pItemOfRequiredType = QITreeWidgetItem::toItem(pItem);
    284     AssertPtrReturnVoid(pItemOfRequiredType);
    285 
    286     /* A language item to be honest :) */
    287     UILanguageItem *pLanguageItem = qobject_cast<UILanguageItem*>(pItemOfRequiredType);
    288     AssertPtrReturnVoid(pLanguageItem);
    289 
    290     /* For built in language item: */
    291     if (pLanguageItem->isBuiltIn())
    292     {
    293         /* We are drawing a separator line in the tree: */
    294         const QRect rect = m_pTreeWidget->visualItemRect(pLanguageItem);
    295         pPainter->setPen(m_pTreeWidget->palette().color(QPalette::Window));
    296         pPainter->drawLine(rect.x(), rect.y() + rect.height() - 1,
    297                            rect.x() + rect.width(), rect.y() + rect.height() - 1);
    298     }
    299 }
    300 
    301 void UILanguageSettingsEditor::sltHandleCurrentItemChange(QTreeWidgetItem *pCurrentItem)
    302 {
    303     /* Make sure item chosen: */
    304     if (!pCurrentItem)
    305         return;
    306 
    307     /* Disable labels for the Default language item: */
    308     const bool fEnabled = !pCurrentItem->text (1).isNull();
    309     m_pLabelInfo->setEnabled(fEnabled);
    310     m_pLabelInfo->setText(QString("<table>"
    311                                   "<tr><td>%1&nbsp;</td><td>%2</td></tr>"
    312                                   "<tr><td>%3&nbsp;</td><td>%4</td></tr>"
    313                                   "</table>")
    314                                   .arg(tr("Language:"))
    315                                   .arg(pCurrentItem->text(2))
    316                                   .arg(tr("Author(s):"))
    317                                   .arg(pCurrentItem->text(3)));
    318 }
    319 
    320 void UILanguageSettingsEditor::prepare()
     549    AssertPtrReturnVoid(pItem->parentItem());
     550
     551    /* Configure folder details dialog: */
     552    UIMachineSettingsSFDetails dlgFolderDetails(UIMachineSettingsSFDetails::EditType,
     553                                                m_foldersAvailable.value(UISharedFolderType_Console),
     554                                                usedList(false),
     555                                                this);
     556    dlgFolderDetails.setPath(pItem->m_strPath);
     557    dlgFolderDetails.setName(pItem->m_strName);
     558    dlgFolderDetails.setPermanent(pItem->m_enmType == UISharedFolderType_Machine);
     559    dlgFolderDetails.setWriteable(pItem->m_fWritable);
     560    dlgFolderDetails.setAutoMount(pItem->m_fAutoMount);
     561    dlgFolderDetails.setAutoMountPoint(pItem->m_strAutoMountPoint);
     562
     563    /* Run folder details dialog: */
     564    if (dlgFolderDetails.exec() == QDialog::Accepted)
     565    {
     566        const QString strName = dlgFolderDetails.name();
     567        const QString strPath = dlgFolderDetails.path();
     568        const UISharedFolderType enmType = dlgFolderDetails.isPermanent() ? UISharedFolderType_Machine : UISharedFolderType_Console;
     569        /* Shared folder's name & path could not be empty: */
     570        Assert(!strName.isEmpty() && !strPath.isEmpty());
     571
     572        /* Update edited tree-widget item: */
     573        pItem->m_enmType = enmType;
     574        pItem->m_strName = strName;
     575        pItem->m_strPath = strPath;
     576        pItem->m_fWritable = dlgFolderDetails.isWriteable();
     577        pItem->m_fAutoMount = dlgFolderDetails.isAutoMounted();
     578        pItem->m_strAutoMountPoint = dlgFolderDetails.autoMountPoint();
     579        pItem->updateFields();
     580
     581        /* Searching for a root of the edited tree-widget item: */
     582        SFTreeViewItem *pRoot = root(enmType);
     583        if (pItem->parentItem() != pRoot)
     584        {
     585            /* Move the tree-widget item to a new location: */
     586            pItem->parentItem()->takeChild(pItem->parentItem()->indexOfChild(pItem));
     587            pRoot->insertChild(pRoot->childCount(), pItem);
     588
     589            /* Update tree-widget: */
     590            m_pTreeWidget->scrollToItem(pItem);
     591            m_pTreeWidget->setCurrentItem(pItem);
     592            sltHandleCurrentItemChange(pItem);
     593        }
     594
     595        /* Sort tree-widget before adjusting: */
     596        m_pTreeWidget->sortItems(0, Qt::AscendingOrder);
     597        /* Adjust tree-widget finally: */
     598        sltAdjustTree();
     599    }
     600}
     601
     602void UISharedFoldersEditor::sltRemoveFolder()
     603{
     604    /* Check current folder item: */
     605    QTreeWidgetItem *pItem = m_pTreeWidget->currentItem();
     606    AssertPtrReturnVoid(pItem);
     607
     608    /* Delete corresponding item: */
     609    delete pItem;
     610
     611    /* Adjust tree-widget finally: */
     612    sltAdjustTree();
     613}
     614
     615void UISharedFoldersEditor::prepare()
     616{
     617    /* Prepare everything: */
     618    prepareWidgets();
     619    prepareConnections();
     620
     621    /* Apply language settings: */
     622    retranslateUi();
     623}
     624
     625void UISharedFoldersEditor::prepareWidgets()
    321626{
    322627    /* Prepare main layout: */
    323     QVBoxLayout *pLayoutMain = new QVBoxLayout(this);
    324     if (pLayoutMain)
    325     {
    326         pLayoutMain->setContentsMargins(0, 0, 0, 0);
     628    QVBoxLayout *pLayout = new QVBoxLayout(this);
     629    if (pLayout)
     630    {
     631        pLayout->setContentsMargins(0, 0, 0, 0);
    327632
    328633        /* Prepare separator: */
    329634        m_pLabelSeparator = new QILabelSeparator(this);
    330635        if (m_pLabelSeparator)
    331             pLayoutMain->addWidget(m_pLabelSeparator);
    332 
    333         /* Prepare tree-widget: */
    334         m_pTreeWidget = new QITreeWidget(this);
    335         if (m_pTreeWidget)
     636            pLayout->addWidget(m_pLabelSeparator);
     637
     638        /* Prepare view layout: */
     639        m_pLayoutTree = new QHBoxLayout;
     640        if (m_pLayoutTree)
    336641        {
    337             if (m_pLabelSeparator)
    338                 m_pLabelSeparator->setBuddy(m_pTreeWidget);
    339             m_pTreeWidget->header()->hide();
    340             m_pTreeWidget->setColumnCount(4);
    341             m_pTreeWidget->hideColumn(1);
    342             m_pTreeWidget->hideColumn(2);
    343             m_pTreeWidget->hideColumn(3);
    344             m_pTreeWidget->setRootIsDecorated(false);
    345 
    346             pLayoutMain->addWidget(m_pTreeWidget);
     642            m_pLayoutTree->setContentsMargins(0, 0, 0, 0);
     643            m_pLayoutTree->setSpacing(3);
     644
     645            /* Prepare tree-widget: */
     646            prepareTreeWidget();
     647            /* Prepare toolbar: */
     648            prepareToolbar();
     649
     650            pLayout->addLayout(m_pLayoutTree);
    347651        }
    348 
    349         /* Prepare info label: */
    350         m_pLabelInfo = new QIRichTextLabel(this);
    351         if (m_pLabelInfo)
     652    }
     653}
     654
     655void UISharedFoldersEditor::prepareTreeWidget()
     656{
     657    /* Prepare shared folders tree-widget: */
     658    m_pTreeWidget = new QITreeWidget(this);
     659    if (m_pTreeWidget)
     660    {
     661        if (m_pLabelSeparator)
     662            m_pLabelSeparator->setBuddy(m_pTreeWidget);
     663        m_pTreeWidget->header()->setSectionsMovable(false);
     664        m_pTreeWidget->setMinimumSize(QSize(0, 200));
     665        m_pTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
     666        m_pTreeWidget->setUniformRowHeights(true);
     667        m_pTreeWidget->setAllColumnsShowFocus(true);
     668
     669        m_pLayoutTree->addWidget(m_pTreeWidget);
     670    }
     671}
     672
     673void UISharedFoldersEditor::prepareToolbar()
     674{
     675    /* Prepare shared folders toolbar: */
     676    m_pToolbar = new QIToolBar(this);
     677    if (m_pToolbar)
     678    {
     679        const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
     680        m_pToolbar->setIconSize(QSize(iIconMetric, iIconMetric));
     681        m_pToolbar->setOrientation(Qt::Vertical);
     682
     683        /* Prepare 'add shared folder' action: */
     684        m_pActionAdd = m_pToolbar->addAction(UIIconPool::iconSet(":/sf_add_16px.png",
     685                                                                 ":/sf_add_disabled_16px.png"),
     686                                             QString(), this, SLOT(sltAddFolder()));
     687        if (m_pActionAdd)
     688            m_pActionAdd->setShortcuts(QList<QKeySequence>() << QKeySequence("Ins") << QKeySequence("Ctrl+N"));
     689
     690        /* Prepare 'edit shared folder' action: */
     691        m_pActionEdit = m_pToolbar->addAction(UIIconPool::iconSet(":/sf_edit_16px.png",
     692                                                                  ":/sf_edit_disabled_16px.png"),
     693                                              QString(), this, SLOT(sltEditFolder()));
     694        if (m_pActionEdit)
     695            m_pActionEdit->setShortcuts(QList<QKeySequence>() << QKeySequence("Space") << QKeySequence("F2"));
     696
     697        /* Prepare 'remove shared folder' action: */
     698        m_pActionRemove = m_pToolbar->addAction(UIIconPool::iconSet(":/sf_remove_16px.png",
     699                                                                    ":/sf_remove_disabled_16px.png"),
     700                                                QString(), this, SLOT(sltRemoveFolder()));
     701        if (m_pActionRemove)
     702            m_pActionRemove->setShortcuts(QList<QKeySequence>() << QKeySequence("Del") << QKeySequence("Ctrl+R"));
     703
     704        m_pLayoutTree->addWidget(m_pToolbar);
     705    }
     706}
     707
     708void UISharedFoldersEditor::prepareConnections()
     709{
     710    /* Configure tree-widget connections: */
     711    connect(m_pTreeWidget, &QITreeWidget::currentItemChanged,
     712            this, &UISharedFoldersEditor::sltHandleCurrentItemChange);
     713    connect(m_pTreeWidget, &QITreeWidget::itemDoubleClicked,
     714            this, &UISharedFoldersEditor::sltHandleDoubleClick);
     715    connect(m_pTreeWidget, &QITreeWidget::customContextMenuRequested,
     716            this, &UISharedFoldersEditor::sltHandleContextMenuRequest);
     717}
     718
     719QStringList UISharedFoldersEditor::usedList(bool fIncludeSelected)
     720{
     721    /* Make the used names list: */
     722    QStringList list;
     723    QTreeWidgetItemIterator it(m_pTreeWidget);
     724    while (*it)
     725    {
     726        if ((*it)->parent() && (fIncludeSelected || !(*it)->isSelected()))
     727            list << static_cast<SFTreeViewItem*>(*it)->getText(0);
     728        ++it;
     729    }
     730    return list;
     731}
     732
     733SFTreeViewItem *UISharedFoldersEditor::root(UISharedFolderType enmSharedFolderType)
     734{
     735    /* Search for the corresponding root item among all the top-level items: */
     736    SFTreeViewItem *pRootItem = 0;
     737    QTreeWidgetItem *pMainRootItem = m_pTreeWidget->invisibleRootItem();
     738    for (int iFolderTypeIndex = 0; iFolderTypeIndex < pMainRootItem->childCount(); ++iFolderTypeIndex)
     739    {
     740        /* Get iterated item: */
     741        SFTreeViewItem *pIteratedItem = static_cast<SFTreeViewItem*>(pMainRootItem->child(iFolderTypeIndex));
     742        /* If iterated item type is what we are looking for: */
     743        if (pIteratedItem->m_enmType == enmSharedFolderType)
    352744        {
    353             m_pLabelInfo->setWordWrapMode(QTextOption::WordWrap);
    354             m_pLabelInfo->setMinimumHeight(QFontMetrics(m_pLabelInfo->font(), m_pLabelInfo).height() * 5);
    355 
    356             pLayoutMain->addWidget(m_pLabelInfo);
     745            /* Remember the item: */
     746            pRootItem = static_cast<SFTreeViewItem*>(pIteratedItem);
     747            /* And break further search: */
     748            break;
    357749        }
    358750    }
    359 
    360     /* Prepare connections: */
    361     connect(m_pTreeWidget, &QITreeWidget::painted, this, &UILanguageSettingsEditor::sltHandleItemPainting);
    362     connect(m_pTreeWidget, &QITreeWidget::currentItemChanged, this, &UILanguageSettingsEditor::sltHandleCurrentItemChange);
    363 
    364     /* Apply language settings: */
    365     retranslateUi();
    366 }
    367 
    368 void UILanguageSettingsEditor::reloadLanguageTree(const QString &strLanguageId)
    369 {
    370     /* Clear languages tree: */
     751    /* Return root item: */
     752    return pRootItem;
     753}
     754
     755void UISharedFoldersEditor::setRootItemVisible(UISharedFolderType enmSharedFolderType, bool fVisible)
     756{
     757    /* Search for the corresponding root item among all the top-level items: */
     758    SFTreeViewItem *pRootItem = root(enmSharedFolderType);
     759    /* If root item, we are looking for, still not found: */
     760    if (!pRootItem)
     761    {
     762        /* Create new shared folder type item: */
     763        pRootItem = new SFTreeViewItem(m_pTreeWidget, SFTreeViewItem::FormatType_EllipsisEnd);
     764        if (pRootItem)
     765        {
     766            /* Configure item: */
     767            pRootItem->m_enmType = enmSharedFolderType;
     768            switch (enmSharedFolderType)
     769            {
     770                case UISharedFolderType_Machine: pRootItem->m_strName = tr(" Machine Folders"); break;
     771                case UISharedFolderType_Console: pRootItem->m_strName = tr(" Transient Folders"); break;
     772                default: break;
     773            }
     774            pRootItem->updateFields();
     775        }
     776    }
     777    /* Expand/collaps it if necessary: */
     778    pRootItem->setExpanded(fVisible);
     779    /* And hide/show it if necessary: */
     780    pRootItem->setHidden(!fVisible);
     781}
     782
     783void UISharedFoldersEditor::updateRootItemsVisibility()
     784{
     785    /* Update (show/hide) machine (permanent) root item: */
     786    setRootItemVisible(UISharedFolderType_Machine, m_foldersAvailable.value(UISharedFolderType_Machine));
     787    /* Update (show/hide) console (temporary) root item: */
     788    setRootItemVisible(UISharedFolderType_Console, m_foldersAvailable.value(UISharedFolderType_Console));
     789}
     790
     791void UISharedFoldersEditor::addSharedFolderItem(const UIDataSharedFolder &sharedFolderData, bool fChoose)
     792{
     793    /* Create shared folder item: */
     794    SFTreeViewItem *pItem = new SFTreeViewItem(root(sharedFolderData.m_enmType), SFTreeViewItem::FormatType_EllipsisFile);
     795    if (pItem)
     796    {
     797        /* Configure item: */
     798        pItem->m_enmType = sharedFolderData.m_enmType;
     799        pItem->m_strName = sharedFolderData.m_strName;
     800        pItem->m_strPath = sharedFolderData.m_strPath;
     801        pItem->m_fWritable = sharedFolderData.m_fWritable;
     802        pItem->m_fAutoMount = sharedFolderData.m_fAutoMount;
     803        pItem->m_strAutoMountPoint = sharedFolderData.m_strAutoMountPoint;
     804        pItem->updateFields();
     805
     806        /* Select this item if it's new: */
     807        if (fChoose)
     808        {
     809            m_pTreeWidget->scrollToItem(pItem);
     810            m_pTreeWidget->setCurrentItem(pItem);
     811            sltHandleCurrentItemChange(pItem);
     812        }
     813    }
     814}
     815
     816void UISharedFoldersEditor::reloadTree()
     817{
     818    /* Sanity check: */
     819    if (!m_pTreeWidget)
     820        return;
     821
     822    /* Clear list initially: */
    371823    m_pTreeWidget->clear();
    372824
    373     /* Load languages tree: */
    374     char szNlsPath[RTPATH_MAX];
    375     const int rc = RTPathAppPrivateNoArch(szNlsPath, sizeof(szNlsPath));
    376     AssertRC(rc);
    377     const QString strNlsPath = QString(szNlsPath) + UITranslator::vboxLanguageSubDirectory();
    378     QDir nlsDir(strNlsPath);
    379     QStringList files = nlsDir.entryList(QStringList(QString("%1*%2").arg(UITranslator::vboxLanguageFileBase(),
    380                                                                           UITranslator::vboxLanguageFileExtension())),
    381                                          QDir::Files);
    382 
    383     QTranslator translator;
    384     /* Add the default language: */
    385     new UILanguageItem(m_pTreeWidget);
    386     /* Add the built-in language: */
    387     new UILanguageItem(m_pTreeWidget, translator, UITranslator::vboxBuiltInLanguageName(), true /* built-in */);
    388     /* Add all existing languages */
    389     for (QStringList::Iterator it = files.begin(); it != files.end(); ++it)
    390     {
    391         QString strFileName = *it;
    392         QRegExp regExp(UITranslator::vboxLanguageFileBase() + UITranslator::vboxLanguageIdRegExp());
    393         int iPos = regExp.indexIn(strFileName);
    394         if (iPos == -1)
    395             continue;
    396 
    397         /* Skip any English version, cause this is extra handled: */
    398         QString strLanguage = regExp.cap(2);
    399         if (strLanguage.toLower() == "en")
    400             continue;
    401 
    402         bool fLoadOk = translator.load(strFileName, strNlsPath);
    403         if (!fLoadOk)
    404             continue;
    405 
    406         new UILanguageItem(m_pTreeWidget, translator, regExp.cap(1));
    407     }
    408 
    409     /* Adjust selector list: */
    410     m_pTreeWidget->resizeColumnToContents(0);
    411 
    412     /* Search for necessary language: */
    413     QList<QTreeWidgetItem*> itemsList = m_pTreeWidget->findItems(strLanguageId, Qt::MatchExactly, 1);
    414     QTreeWidgetItem *pItem = itemsList.isEmpty() ? 0 : itemsList[0];
    415     if (!pItem)
    416     {
    417         /* Add an pItem for an invalid language to represent it in the list: */
    418         pItem = new UILanguageItem(m_pTreeWidget, strLanguageId);
    419         m_pTreeWidget->resizeColumnToContents(0);
    420     }
    421     Assert(pItem);
    422     if (pItem)
    423         m_pTreeWidget->setCurrentItem(pItem);
    424 
    425     m_pTreeWidget->sortItems(0, Qt::AscendingOrder);
    426     m_pTreeWidget->scrollToItem(pItem);
    427 }
    428 
    429 
    430 #include "UILanguageSettingsEditor.moc"
     825    /* Update root items visibility: */
     826    updateRootItemsVisibility();
     827
     828    /* For each folder => load it from cache: */
     829    foreach (const UIDataSharedFolder &guiData, m_guiValue)
     830        addSharedFolderItem(guiData, false /* its new? */);
     831
     832    /* Choose first folder as current: */
     833    m_pTreeWidget->setCurrentItem(m_pTreeWidget->topLevelItem(0));
     834    sltHandleCurrentItemChange(m_pTreeWidget->currentItem());
     835}
     836
     837
     838#include "UISharedFoldersEditor.moc"
  • trunk/src/VBox/Frontends/VirtualBox/src/settings/editors/UISharedFoldersEditor.h

    r95076 r95077  
    11/* $Id$ */
    22/** @file
    3  * VBox Qt GUI - UILanguageSettingsEditor class declaration.
     3 * VBox Qt GUI - UISharedFoldersEditor class declaration.
    44 */
    55
     
    1616 */
    1717
    18 #ifndef FEQT_INCLUDED_SRC_settings_editors_UILanguageSettingsEditor_h
    19 #define FEQT_INCLUDED_SRC_settings_editors_UILanguageSettingsEditor_h
     18#ifndef FEQT_INCLUDED_SRC_settings_editors_UISharedFoldersEditor_h
     19#define FEQT_INCLUDED_SRC_settings_editors_UISharedFoldersEditor_h
    2020#ifndef RT_WITHOUT_PRAGMA_ONCE
    2121# pragma once
     
    2424/* GUI includes: */
    2525#include "QIWithRetranslateUI.h"
     26#include "UIExtraDataDefs.h"
    2627
    2728/* Forward declartions: */
     29class QHBoxLayout;
    2830class QTreeWidgetItem;
    2931class QILabelSeparator;
    30 class QIRichTextLabel;
     32class QIToolBar;
    3133class QITreeWidget;
     34class SFTreeViewItem;
    3235
    33 /** QWidget subclass used as a language settings editor. */
    34 class SHARED_LIBRARY_STUFF UILanguageSettingsEditor : public QIWithRetranslateUI<QWidget>
     36/** Shared Folder data. */
     37struct UIDataSharedFolder
     38{
     39    /** Constructs data. */
     40    UIDataSharedFolder()
     41        : m_enmType(UISharedFolderType_Machine)
     42        , m_strName()
     43        , m_strPath()
     44        , m_fWritable(false)
     45        , m_fAutoMount(false)
     46        , m_strAutoMountPoint()
     47    {}
     48
     49    /** Returns whether the @a other passed data is equal to this one. */
     50    bool equal(const UIDataSharedFolder &other) const
     51    {
     52        return true
     53               && m_enmType == other.m_enmType
     54               && m_strName == other.m_strName
     55               && m_strPath == other.m_strPath
     56               && m_fWritable == other.m_fWritable
     57               && m_fAutoMount == other.m_fAutoMount
     58               && m_strAutoMountPoint == other.m_strAutoMountPoint
     59               ;
     60    }
     61
     62    /** Returns whether the @a other passed data is equal to this one. */
     63    bool operator==(const UIDataSharedFolder &other) const { return equal(other); }
     64    /** Returns whether the @a other passed data is different from this one. */
     65    bool operator!=(const UIDataSharedFolder &other) const { return !equal(other); }
     66
     67    /** Holds the shared folder type. */
     68    UISharedFolderType  m_enmType;
     69    /** Holds the shared folder name. */
     70    QString             m_strName;
     71    /** Holds the shared folder path. */
     72    QString             m_strPath;
     73    /** Holds whether the shared folder should be writeable. */
     74    bool                m_fWritable;
     75    /** Holds whether the shared folder should be auto-mounted at startup. */
     76    bool                m_fAutoMount;
     77    /** Where in the guest to try auto mount the shared folder (drive for
     78     * Windows & OS/2, path for unixy guests). */
     79    QString             m_strAutoMountPoint;
     80};
     81
     82/** QWidget subclass used as a shared folders editor. */
     83class SHARED_LIBRARY_STUFF UISharedFoldersEditor : public QIWithRetranslateUI<QWidget>
    3584{
    3685    Q_OBJECT;
     
    3988
    4089    /** Constructs editor passing @a pParent to the base-class. */
    41     UILanguageSettingsEditor(QWidget *pParent = 0);
     90    UISharedFoldersEditor(QWidget *pParent = 0);
    4291
    4392    /** Defines editor @a strValue. */
    44     void setValue(const QString &strValue);
     93    void setValue(const QList<UIDataSharedFolder> &guiValue);
    4594    /** Returns editor value. */
    46     QString value() const;
     95    QList<UIDataSharedFolder> value() const;
     96
     97    /** Defines whether feature @a fAvailable. */
     98    void setFeatureAvailable(bool fAvailable);
     99    /** Defines whether folders of certain @a enmType are @a fAvailable. */
     100    void setFoldersAvailable(UISharedFolderType enmType, bool fAvailable);
    47101
    48102protected:
     
    53107    /** Handles show @a pEvent. */
    54108    virtual void showEvent(QShowEvent *pEvent) RT_OVERRIDE;
    55     /** Handles polish @a pEvent. */
    56     virtual void polishEvent(QShowEvent *pEvent);
     109
     110    /** Handles resize @a pEvent. */
     111    virtual void resizeEvent(QResizeEvent *pEvent) RT_OVERRIDE;
    57112
    58113private slots:
    59114
    60     /** Handles @a pItem painting with passed @a pPainter. */
    61     void sltHandleItemPainting(QTreeWidgetItem *pItem, QPainter *pPainter);
     115    /** Performs request to adjust tree. */
     116    void sltAdjustTree();
     117    /** Performs request to adjust tree fields. */
     118    void sltAdjustTreeFields();
    62119
    63120    /** Handles @a pCurrentItem change. */
    64121    void sltHandleCurrentItemChange(QTreeWidgetItem *pCurrentItem);
     122    /** Handles @a pItem double-click. */
     123    void sltHandleDoubleClick(QTreeWidgetItem *pItem);
     124    /** Handles context menu request for @a position. */
     125    void sltHandleContextMenuRequest(const QPoint &position);
     126
     127    /** Handles command to add shared folder. */
     128    void sltAddFolder();
     129    /** Handles command to edit shared folder. */
     130    void sltEditFolder();
     131    /** Handles command to remove shared folder. */
     132    void sltRemoveFolder();
    65133
    66134private:
     
    68136    /** Prepares all. */
    69137    void prepare();
    70     /** Cleanups all. */
    71     void cleanup();
     138    /** Prepares widgets. */
     139    void prepareWidgets();
     140    /** Prepare tree-widget. */
     141    void prepareTreeWidget();
     142    /** Prepare tool-bar. */
     143    void prepareToolbar();
     144    /** Prepares connections. */
     145    void prepareConnections();
    72146
    73     /** Reloads language list, choosing item with @a strLanguageId as current. */
    74     void reloadLanguageTree(const QString &strLanguageId);
     147    /** Returns a list of used shared folder names. */
     148    QStringList usedList(bool fIncludeSelected);
    75149
    76     /** Holds whether the page is polished. */
    77     bool  m_fPolished;
     150    /** Returns the tree-view root item for corresponding shared folder @a type. */
     151    SFTreeViewItem *root(UISharedFolderType type);
     152    /** Defines whether the root item of @a enmFoldersType is @a fVisible. */
     153    void setRootItemVisible(UISharedFolderType enmFoldersType, bool fVisible);
     154    /** Updates root item visibility. */
     155    void updateRootItemsVisibility();
     156    /** Creates shared folder item based on passed @a data. */
     157    void addSharedFolderItem(const UIDataSharedFolder &sharedFolderData, bool fChoose);
     158    /** Reloads tree. */
     159    void reloadTree();
    78160
    79161    /** Holds the value to be set. */
    80     QString  m_strValue;
     162    QList<UIDataSharedFolder>  m_guiValue;
     163
     164    /** Holds whether folders of certain type are available. */
     165    QMap<UISharedFolderType, bool>  m_foldersAvailable;
    81166
    82167    /** @name Widgets
    83168     * @{ */
    84         /** Holds the separator label instance. */
     169        /** Holds the widget separator instance. */
    85170        QILabelSeparator *m_pLabelSeparator;
     171        /** Holds the tree layout instance. */
     172        QHBoxLayout      *m_pLayoutTree;
    86173        /** Holds the tree-widget instance. */
    87174        QITreeWidget     *m_pTreeWidget;
    88         /** Holds the info label instance. */
    89         QIRichTextLabel  *m_pLabelInfo;
     175        /** Holds the toolbar instance. */
     176        QIToolBar        *m_pToolbar;
     177        /** Holds the 'add shared folder' action instance. */
     178        QAction          *m_pActionAdd;
     179        /** Holds the 'edit shared folder' action instance. */
     180        QAction          *m_pActionEdit;
     181        /** Holds the 'remove shared folder' action instance. */
     182        QAction          *m_pActionRemove;
    90183    /** @} */
    91184};
    92185
    93 #endif /* !FEQT_INCLUDED_SRC_settings_editors_UILanguageSettingsEditor_h */
     186#endif /* !FEQT_INCLUDED_SRC_settings_editors_UISharedFoldersEditor_h */
  • trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsSF.cpp

    r94667 r95077  
    1717
    1818/* Qt includes: */
    19 #include <QHeaderView>
    20 #include <QMenu>
    21 #include <QRegExp>
    22 #include <QTimer>
    2319#include <QVBoxLayout>
    2420
    2521/* GUI includes: */
    26 #include "QILabelSeparator.h"
    27 #include "QITreeWidget.h"
    28 #include "UICommon.h"
    2922#include "UIErrorString.h"
    30 #include "UIIconPool.h"
    3123#include "UIMachineSettingsSF.h"
    32 #include "UIMachineSettingsSFDetails.h"
    33 #include "QIToolBar.h"
    34 #include "VBoxUtils.h"
     24#include "UISharedFoldersEditor.h"
    3525
    3626
     
    3929{
    4030    /** Constructs data. */
    41     UIDataSettingsSharedFolder()
    42         : m_enmType(MachineType)
    43         , m_strName()
    44         , m_strPath()
    45         , m_fWritable(false)
    46         , m_fAutoMount(false)
    47         , m_strAutoMountPoint()
    48     {}
     31    UIDataSettingsSharedFolder() {}
    4932
    5033    /** Returns whether the @a other passed data is equal to this one. */
     
    5235    {
    5336        return true
    54                && m_enmType == other.m_enmType
    55                && m_strName == other.m_strName
    56                && m_strPath == other.m_strPath
    57                && m_fWritable == other.m_fWritable
    58                && m_fAutoMount == other.m_fAutoMount
    59                && m_strAutoMountPoint == other.m_strAutoMountPoint
     37               && m_guiData == other.m_guiData
    6038               ;
    6139    }
     
    6644    bool operator!=(const UIDataSettingsSharedFolder &other) const { return !equal(other); }
    6745
    68     /** Holds the shared folder type. */
    69     UISharedFolderType  m_enmType;
    70     /** Holds the shared folder name. */
    71     QString             m_strName;
    72     /** Holds the shared folder path. */
    73     QString             m_strPath;
    74     /** Holds whether the shared folder should be writeable. */
    75     bool                m_fWritable;
    76     /** Holds whether the shared folder should be auto-mounted at startup. */
    77     bool                m_fAutoMount;
    78     /** Where in the guest to try auto mount the shared folder (drive for
    79      * Windows & OS/2, path for unixy guests). */
    80     QString             m_strAutoMountPoint;
     46    /** Holds the shared folder data. */
     47    UIDataSharedFolder  m_guiData;
    8148};
    8249
     
    9562
    9663
    97 /** Machine settings: Shared Folder tree-widget item. */
    98 class SFTreeViewItem : public QITreeWidgetItem, public UIDataSettingsSharedFolder
    99 {
    100     Q_OBJECT;
    101 
    102 public:
    103 
    104     /** Format type. */
    105     enum FormatType
    106     {
    107         FormatType_Invalid,
    108         FormatType_EllipsisStart,
    109         FormatType_EllipsisMiddle,
    110         FormatType_EllipsisEnd,
    111         FormatType_EllipsisFile,
    112     };
    113 
    114     /** Constructs shared folder type (root) item.
    115       * @param  pParent    Brings the item parent.
    116       * @param  enmFormat  Brings the item format type. */
    117     SFTreeViewItem(QITreeWidget *pParent, FormatType enmFormat)
    118         : QITreeWidgetItem(pParent)
    119         , m_enmFormat(enmFormat)
    120     {
    121         setFirstColumnSpanned(true);
    122         setFlags(flags() ^ Qt::ItemIsSelectable);
    123     }
    124 
    125     /** Constructs shared folder (child) item.
    126       * @param  pParent    Brings the item parent.
    127       * @param  enmFormat  Brings the item format type. */
    128     SFTreeViewItem(SFTreeViewItem *pParent, FormatType enmFormat)
    129         : QITreeWidgetItem(pParent)
    130         , m_enmFormat(enmFormat)
    131     {
    132     }
    133 
    134     /** Returns whether this item is less than the @a other one. */
    135     bool operator<(const QTreeWidgetItem &other) const
    136     {
    137         /* Root items should always been sorted by type field: */
    138         return parentItem() ? text(0) < other.text(0) :
    139                               text(1) < other.text(1);
    140     }
    141 
    142     /** Returns child item number @a iIndex. */
    143     SFTreeViewItem *child(int iIndex) const
    144     {
    145         QTreeWidgetItem *pItem = QTreeWidgetItem::child(iIndex);
    146         return pItem ? static_cast<SFTreeViewItem*>(pItem) : 0;
    147     }
    148 
    149     /** Returns text of item number @a iIndex. */
    150     QString getText(int iIndex) const
    151     {
    152         return iIndex >= 0 && iIndex < m_fields.size() ? m_fields.at(iIndex) : QString();
    153     }
    154 
    155     /** Updates item fields. */
    156     void updateFields()
    157     {
    158         /* Clear fields: */
    159         m_fields.clear();
    160 
    161         /* For root items: */
    162         if (!parentItem())
    163             m_fields << m_strName
    164                      << QString::number((int)m_enmType);
    165         /* For child items: */
    166         else
    167             m_fields << m_strName
    168                      << m_strPath
    169                      << (m_fWritable ? tr("Full") : tr("Read-only"))
    170                      << (m_fAutoMount ? tr("Yes") : "")
    171                      << m_strAutoMountPoint;
    172 
    173         /* Adjust item layout: */
    174         adjustText();
    175     }
    176 
    177     /** Adjusts item layout. */
    178     void adjustText()
    179     {
    180         for (int i = 0; i < treeWidget()->columnCount(); ++i)
    181             processColumn(i);
    182     }
    183 
    184 protected:
    185 
    186     /** Returns default text. */
    187     virtual QString defaultText() const RT_OVERRIDE
    188     {
    189         return parentItem()
    190              ? tr("%1, %2: %3, %4: %5, %6: %7, %8: %9",
    191                   "col.1 text, col.2 name: col.2 text, col.3 name: col.3 text, col.4 name: col.4 text, col.5 name: col.5 text")
    192                   .arg(text(0))
    193                   .arg(parentTree()->headerItem()->text(1)).arg(text(1))
    194                   .arg(parentTree()->headerItem()->text(2)).arg(text(2))
    195                   .arg(parentTree()->headerItem()->text(3)).arg(text(3))
    196                   .arg(parentTree()->headerItem()->text(4)).arg(text(4))
    197              : text(0);
    198     }
    199 
    200 private:
    201 
    202     /** Performs item @a iColumn processing. */
    203     void processColumn(int iColumn)
    204     {
    205         QString strOneString = getText(iColumn);
    206         if (strOneString.isNull())
    207             return;
    208         const QFontMetrics fm = treeWidget()->fontMetrics();
    209 #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
    210         const int iOldSize = fm.horizontalAdvance(strOneString);
    211 #else
    212         const int iOldSize = fm.width(strOneString);
    213 #endif
    214         const int iItemIndent = parentItem() ? treeWidget()->indentation() * 2 : treeWidget()->indentation();
    215 #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
    216         int iIndentSize = fm.horizontalAdvance(" ... ");
    217 #else
    218         int iIndentSize = fm.width(" ... ");
    219 #endif
    220         if (iColumn == 0)
    221             iIndentSize += iItemIndent;
    222         const int cWidth = !parentItem() ? treeWidget()->viewport()->width() : treeWidget()->columnWidth(iColumn);
    223 
    224         /* Compress text: */
    225         int iStart = 0;
    226         int iFinish = 0;
    227         int iPosition = 0;
    228         int iTextWidth = 0;
    229         do
    230         {
    231 #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
    232             iTextWidth = fm.horizontalAdvance(strOneString);
    233 #else
    234             iTextWidth = fm.width(strOneString);
    235 #endif
    236             if (   iTextWidth
    237                 && iTextWidth + iIndentSize > cWidth)
    238             {
    239                 iStart = 0;
    240                 iFinish = strOneString.length();
    241 
    242                 /* Selecting remove position: */
    243                 switch (m_enmFormat)
    244                 {
    245                     case FormatType_EllipsisStart:
    246                         iPosition = iStart;
    247                         break;
    248                     case FormatType_EllipsisMiddle:
    249                         iPosition = (iFinish - iStart) / 2;
    250                         break;
    251                     case FormatType_EllipsisEnd:
    252                         iPosition = iFinish - 1;
    253                         break;
    254                     case FormatType_EllipsisFile:
    255                     {
    256                         const QRegExp regExp("([\\\\/][^\\\\^/]+[\\\\/]?$)");
    257                         const int iNewFinish = regExp.indexIn(strOneString);
    258                         if (iNewFinish != -1)
    259                             iFinish = iNewFinish;
    260                         iPosition = (iFinish - iStart) / 2;
    261                         break;
    262                     }
    263                     default:
    264                         AssertMsgFailed(("Invalid format type\n"));
    265                 }
    266 
    267                 if (iPosition == iFinish)
    268                    break;
    269 
    270                 strOneString.remove(iPosition, 1);
    271             }
    272         }
    273         while (   iTextWidth
    274                && (iTextWidth + iIndentSize > cWidth));
    275 
    276         if (iPosition || m_enmFormat == FormatType_EllipsisFile)
    277             strOneString.insert(iPosition, "...");
    278 #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
    279         const int iNewSize = fm.horizontalAdvance(strOneString);
    280 #else
    281         const int iNewSize = fm.width(strOneString);
    282 #endif
    283         setText(iColumn, iNewSize < iOldSize ? strOneString : m_fields.at(iColumn));
    284         setToolTip(iColumn, text(iColumn) == getText(iColumn) ? QString() : getText(iColumn));
    285 
    286         /* Calculate item's size-hint: */
    287 #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
    288         setSizeHint(iColumn, QSize(fm.horizontalAdvance(QString("  %1  ").arg(getText(iColumn))), fm.height()));
    289 #else
    290         setSizeHint(iColumn, QSize(fm.width(QString("  %1  ").arg(getText(iColumn))), fm.height()));
    291 #endif
    292     }
    293 
    294     /** Holds the item format type. */
    295     FormatType   m_enmFormat;
    296     /** Holds the item text fields. */
    297     QStringList  m_fields;
    298 };
    299 
    300 
    30164UIMachineSettingsSF::UIMachineSettingsSF()
    30265    : m_pCache(0)
    303     , m_pLabelSeparator(0)
    304     , m_pLayoutTree(0)
    305     , m_pTreeWidget(0)
    306     , m_pToolbar(0)
    307     , m_pActionAdd(0)
    308     , m_pActionEdit(0)
    309     , m_pActionRemove(0)
     66    , m_pEditorSharedFolders(0)
    31067{
    31168    prepare();
     
    31471UIMachineSettingsSF::~UIMachineSettingsSF()
    31572{
    316     /* Cleanup: */
    31773    cleanup();
    31874}
     
    34197    QMultiMap<UISharedFolderType, CSharedFolder> folders;
    34298    /* Load machine (permanent) folders if allowed: */
    343     if (isSharedFolderTypeSupported(MachineType))
    344     {
    345         foreach (const CSharedFolder &folder, getSharedFolders(MachineType))
    346             folders.insert(MachineType, folder);
     99    if (isSharedFolderTypeSupported(UISharedFolderType_Machine))
     100    {
     101        foreach (const CSharedFolder &folder, getSharedFolders(UISharedFolderType_Machine))
     102            folders.insert(UISharedFolderType_Machine, folder);
    347103    }
    348104    /* Load console (temporary) folders if allowed: */
    349     if (isSharedFolderTypeSupported(ConsoleType))
    350     {
    351         foreach (const CSharedFolder &folder, getSharedFolders(ConsoleType))
    352             folders.insert(ConsoleType, folder);
     105    if (isSharedFolderTypeSupported(UISharedFolderType_Console))
     106    {
     107        foreach (const CSharedFolder &folder, getSharedFolders(UISharedFolderType_Console))
     108            folders.insert(UISharedFolderType_Console, folder);
    353109    }
    354110
     
    369125            {
    370126                /* Gather old data: */
    371                 oldFolderData.m_enmType = enmFolderType;
    372                 oldFolderData.m_strName = comFolder.GetName();
    373                 oldFolderData.m_strPath = comFolder.GetHostPath();
    374                 oldFolderData.m_fWritable = comFolder.GetWritable();
    375                 oldFolderData.m_fAutoMount = comFolder.GetAutoMount();
    376                 oldFolderData.m_strAutoMountPoint = comFolder.GetAutoMountPoint();
     127                oldFolderData.m_guiData.m_enmType = enmFolderType;
     128                oldFolderData.m_guiData.m_strName = comFolder.GetName();
     129                oldFolderData.m_guiData.m_strPath = comFolder.GetHostPath();
     130                oldFolderData.m_guiData.m_fWritable = comFolder.GetWritable();
     131                oldFolderData.m_guiData.m_fAutoMount = comFolder.GetAutoMount();
     132                oldFolderData.m_guiData.m_strAutoMountPoint = comFolder.GetAutoMountPoint();
    377133                /* Override folder cache key: */
    378                 strFolderKey = oldFolderData.m_strName;
     134                strFolderKey = oldFolderData.m_guiData.m_strName;
    379135            }
    380136
     
    395151    /* Sanity check: */
    396152    if (   !m_pCache
    397         || !m_pTreeWidget)
     153        || !m_pEditorSharedFolders)
    398154        return;
    399155
    400     /* Clear list initially: */
    401     m_pTreeWidget->clear();
    402 
    403     /* Update root items visibility: */
    404     updateRootItemsVisibility();
    405 
    406     /* For each folder => load it from cache: */
     156    /* Load old data from cache: */
     157    QList<UIDataSharedFolder> folders;
    407158    for (int iFolderIndex = 0; iFolderIndex < m_pCache->childCount(); ++iFolderIndex)
    408         addSharedFolderItem(m_pCache->child(iFolderIndex).base(), false /* its new? */);
    409 
    410     /* Choose first folder as current: */
    411     m_pTreeWidget->setCurrentItem(m_pTreeWidget->topLevelItem(0));
    412     sltHandleCurrentItemChange(m_pTreeWidget->currentItem());
     159        folders << m_pCache->child(iFolderIndex).base().m_guiData;
     160    m_pEditorSharedFolders->setValue(folders);
    413161
    414162    /* Polish page finally: */
     
    420168    /* Sanity check: */
    421169    if (   !m_pCache
    422         || !m_pTreeWidget)
     170        || !m_pEditorSharedFolders)
    423171        return;
    424172
     
    426174    UIDataSettingsSharedFolders newFoldersData;
    427175
    428     /* For each folder type: */
    429     QTreeWidgetItem *pMainRootItem = m_pTreeWidget->invisibleRootItem();
    430     for (int iFolderTypeIndex = 0; iFolderTypeIndex < pMainRootItem->childCount(); ++iFolderTypeIndex)
    431     {
    432         /* Get folder root item: */
    433         const SFTreeViewItem *pFolderTypeRoot = static_cast<SFTreeViewItem*>(pMainRootItem->child(iFolderTypeIndex));
    434 
    435         /* For each folder of current type: */
    436         for (int iFolderIndex = 0; iFolderIndex < pFolderTypeRoot->childCount(); ++iFolderIndex)
    437         {
    438             /* Gather and cache new data: */
    439             const SFTreeViewItem *pItem = static_cast<SFTreeViewItem*>(pFolderTypeRoot->child(iFolderIndex));
    440             m_pCache->child(pItem->m_strName).cacheCurrentData(*pItem);
    441         }
    442     }
    443 
    444176    /* Cache new data: */
     177    foreach (const UIDataSharedFolder &guiData, m_pEditorSharedFolders->value())
     178    {
     179        /* Gather and cache new data: */
     180        UIDataSettingsSharedFolder newFolderData;
     181        newFolderData.m_guiData = guiData;
     182        m_pCache->child(newFolderData.m_guiData.m_strName).cacheCurrentData(newFolderData);
     183    }
    445184    m_pCache->cacheCurrentData(newFoldersData);
    446185}
     
    460199void UIMachineSettingsSF::retranslateUi()
    461200{
    462     m_pLabelSeparator->setText(tr("Shared &Folders"));
    463     QTreeWidgetItem *pQTreeWidgetItem = m_pTreeWidget->headerItem();
    464     pQTreeWidgetItem->setText(4, tr("At"));
    465     pQTreeWidgetItem->setText(3, tr("Auto Mount"));
    466     pQTreeWidgetItem->setText(2, tr("Access"));
    467     pQTreeWidgetItem->setText(1, tr("Path"));
    468     pQTreeWidgetItem->setText(0, tr("Name"));
    469     m_pTreeWidget->setWhatsThis(tr("Lists all shared folders accessible to this machine. Use 'net use x: \\\\vboxsvr\\share' "
    470                                    "to access a shared folder named <i>share</i> from a DOS-like OS, or 'mount -t vboxsf share "
    471                                    "mount_point' to access it from a Linux OS. This feature requires Guest Additions."));
    472 
    473     m_pActionAdd->setText(tr("Add Shared Folder"));
    474     m_pActionEdit->setText(tr("Edit Shared Folder"));
    475     m_pActionRemove->setText(tr("Remove Shared Folder"));
    476 
    477     m_pActionAdd->setToolTip(tr("Adds new shared folder."));
    478     m_pActionEdit->setToolTip(tr("Edits selected shared folder."));
    479     m_pActionRemove->setToolTip(tr("Removes selected shared folder."));
    480 
    481     m_pActionAdd->setToolTip(m_pActionAdd->whatsThis());
    482     m_pActionEdit->setToolTip(m_pActionEdit->whatsThis());
    483     m_pActionRemove->setToolTip(m_pActionRemove->whatsThis());
    484201}
    485202
    486203void UIMachineSettingsSF::polishPage()
    487204{
    488     /* Polish shared folders page availability: */
    489     m_pLabelSeparator->setEnabled(isMachineInValidMode());
    490     m_pToolbar->setEnabled(isMachineInValidMode());
    491     m_pToolbar->setEnabled(isMachineInValidMode());
    492 
    493     /* Update root items visibility: */
    494     updateRootItemsVisibility();
    495 }
    496 
    497 void UIMachineSettingsSF::showEvent(QShowEvent *pEvent)
    498 {
    499     /* Call to base-class: */
    500     UISettingsPageMachine::showEvent(pEvent);
    501 
    502     /* Connect header-resize signal just before widget is shown after all the items properly loaded and initialized: */
    503     connect(m_pTreeWidget->header(), &QHeaderView::sectionResized, this, &UIMachineSettingsSF::sltAdjustTreeFields);
    504 
    505     /* Adjusting size after all pending show events are processed: */
    506     QTimer::singleShot(0, this, SLOT(sltAdjustTree()));
    507 }
    508 
    509 void UIMachineSettingsSF::resizeEvent(QResizeEvent * /* pEvent */)
    510 {
    511     sltAdjustTree();
    512 }
    513 
    514 void UIMachineSettingsSF::sltAddFolder()
    515 {
    516     /* Configure folder details dialog: */
    517     UIMachineSettingsSFDetails dlgFolderDetails(UIMachineSettingsSFDetails::AddType,
    518                                                 isSharedFolderTypeSupported(ConsoleType),
    519                                                 usedList(true),
    520                                                 this);
    521 
    522     /* Run folder details dialog: */
    523     if (dlgFolderDetails.exec() == QDialog::Accepted)
    524     {
    525         const QString strName = dlgFolderDetails.name();
    526         const QString strPath = dlgFolderDetails.path();
    527         const UISharedFolderType enmType = dlgFolderDetails.isPermanent() ? MachineType : ConsoleType;
    528         /* Shared folder's name & path could not be empty: */
    529         Assert(!strName.isEmpty() && !strPath.isEmpty());
    530 
    531         /* Prepare new data: */
    532         UIDataSettingsSharedFolder newFolderData;
    533         newFolderData.m_enmType = enmType;
    534         newFolderData.m_strName = strName;
    535         newFolderData.m_strPath = strPath;
    536         newFolderData.m_fWritable = dlgFolderDetails.isWriteable();
    537         newFolderData.m_fAutoMount = dlgFolderDetails.isAutoMounted();
    538         newFolderData.m_strAutoMountPoint = dlgFolderDetails.autoMountPoint();
    539 
    540         /* Add new folder item: */
    541         addSharedFolderItem(newFolderData, true /* its new? */);
    542 
    543         /* Sort tree-widget before adjusting: */
    544         m_pTreeWidget->sortItems(0, Qt::AscendingOrder);
    545         /* Adjust tree-widget finally: */
    546         sltAdjustTree();
    547     }
    548 }
    549 
    550 void UIMachineSettingsSF::sltEditFolder()
    551 {
    552     /* Check current folder item: */
    553     SFTreeViewItem *pItem = static_cast<SFTreeViewItem*>(m_pTreeWidget->currentItem());
    554     AssertPtrReturnVoid(pItem);
    555     AssertPtrReturnVoid(pItem->parentItem());
    556 
    557     /* Configure folder details dialog: */
    558     UIMachineSettingsSFDetails dlgFolderDetails(UIMachineSettingsSFDetails::EditType,
    559                                                 isSharedFolderTypeSupported(ConsoleType),
    560                                                 usedList(false),
    561                                                 this);
    562     dlgFolderDetails.setPath(pItem->m_strPath);
    563     dlgFolderDetails.setName(pItem->m_strName);
    564     dlgFolderDetails.setPermanent(pItem->m_enmType == MachineType);
    565     dlgFolderDetails.setWriteable(pItem->m_fWritable);
    566     dlgFolderDetails.setAutoMount(pItem->m_fAutoMount);
    567     dlgFolderDetails.setAutoMountPoint(pItem->m_strAutoMountPoint);
    568 
    569     /* Run folder details dialog: */
    570     if (dlgFolderDetails.exec() == QDialog::Accepted)
    571     {
    572         const QString strName = dlgFolderDetails.name();
    573         const QString strPath = dlgFolderDetails.path();
    574         const UISharedFolderType enmType = dlgFolderDetails.isPermanent() ? MachineType : ConsoleType;
    575         /* Shared folder's name & path could not be empty: */
    576         Assert(!strName.isEmpty() && !strPath.isEmpty());
    577 
    578         /* Update edited tree-widget item: */
    579         pItem->m_enmType = enmType;
    580         pItem->m_strName = strName;
    581         pItem->m_strPath = strPath;
    582         pItem->m_fWritable = dlgFolderDetails.isWriteable();
    583         pItem->m_fAutoMount = dlgFolderDetails.isAutoMounted();
    584         pItem->m_strAutoMountPoint = dlgFolderDetails.autoMountPoint();
    585         pItem->updateFields();
    586 
    587         /* Searching for a root of the edited tree-widget item: */
    588         SFTreeViewItem *pRoot = root(enmType);
    589         if (pItem->parentItem() != pRoot)
    590         {
    591             /* Move the tree-widget item to a new location: */
    592             pItem->parentItem()->takeChild(pItem->parentItem()->indexOfChild(pItem));
    593             pRoot->insertChild(pRoot->childCount(), pItem);
    594 
    595             /* Update tree-widget: */
    596             m_pTreeWidget->scrollToItem(pItem);
    597             m_pTreeWidget->setCurrentItem(pItem);
    598             sltHandleCurrentItemChange(pItem);
    599         }
    600 
    601         /* Sort tree-widget before adjusting: */
    602         m_pTreeWidget->sortItems(0, Qt::AscendingOrder);
    603         /* Adjust tree-widget finally: */
    604         sltAdjustTree();
    605     }
    606 }
    607 
    608 void UIMachineSettingsSF::sltRemoveFolder()
    609 {
    610     /* Check current folder item: */
    611     QTreeWidgetItem *pItem = m_pTreeWidget->currentItem();
    612     AssertPtrReturnVoid(pItem);
    613 
    614     /* Delete corresponding item: */
    615     delete pItem;
    616 
    617     /* Adjust tree-widget finally: */
    618     sltAdjustTree();
    619 }
    620 
    621 void UIMachineSettingsSF::sltHandleCurrentItemChange(QTreeWidgetItem *pCurrentItem)
    622 {
    623     if (pCurrentItem && pCurrentItem->parent() && !pCurrentItem->isSelected())
    624         pCurrentItem->setSelected(true);
    625     const bool fAddEnabled = pCurrentItem;
    626     const bool fRemoveEnabled = fAddEnabled && pCurrentItem->parent();
    627     m_pActionAdd->setEnabled(fAddEnabled);
    628     m_pActionEdit->setEnabled(fRemoveEnabled);
    629     m_pActionRemove->setEnabled(fRemoveEnabled);
    630 }
    631 
    632 void UIMachineSettingsSF::sltHandleDoubleClick(QTreeWidgetItem *pItem)
    633 {
    634     const bool fEditEnabled = pItem && pItem->parent();
    635     if (fEditEnabled)
    636         sltEditFolder();
    637 }
    638 
    639 void UIMachineSettingsSF::sltHandleContextMenuRequest(const QPoint &position)
    640 {
    641     QMenu menu;
    642     QTreeWidgetItem *pItem = m_pTreeWidget->itemAt(position);
    643     if (m_pTreeWidget->isEnabled() && pItem && pItem->flags() & Qt::ItemIsSelectable)
    644     {
    645         menu.addAction(m_pActionEdit);
    646         menu.addAction(m_pActionRemove);
    647     }
    648     else
    649     {
    650         menu.addAction(m_pActionAdd);
    651     }
    652     if (!menu.isEmpty())
    653         menu.exec(m_pTreeWidget->viewport()->mapToGlobal(position));
    654 }
    655 
    656 void UIMachineSettingsSF::sltAdjustTree()
    657 {
    658     /*
    659      * Calculates required columns sizes to max out column 2
    660      * and let all other columns stay at their minimum sizes.
    661      *
    662      * Columns
    663      * 0 = Tree view / name
    664      * 1 = Path
    665      * 2 = Writable flag
    666      * 3 = Auto-mount flag
    667      * 4 = Auto mount point
    668      */
    669     QAbstractItemView *pItemView = m_pTreeWidget;
    670     QHeaderView *pItemHeader = m_pTreeWidget->header();
    671     const int iTotal = m_pTreeWidget->viewport()->width();
    672 
    673     const int mw0 = qMax(pItemView->sizeHintForColumn(0), pItemHeader->sectionSizeHint(0));
    674     const int mw2 = qMax(pItemView->sizeHintForColumn(2), pItemHeader->sectionSizeHint(2));
    675     const int mw3 = qMax(pItemView->sizeHintForColumn(3), pItemHeader->sectionSizeHint(3));
    676     const int mw4 = qMax(pItemView->sizeHintForColumn(4), pItemHeader->sectionSizeHint(4));
    677 #if 0 /** @todo Neither approach is perfect.  Short folder names, short paths, plenty of white space, but there is often '...' in column 0. */
    678 
    679     const int w0 = mw0 < iTotal / 5 ? mw0 : iTotal / 5;
    680     const int w2 = mw2 < iTotal / 5 ? mw2 : iTotal / 5;
    681     const int w3 = mw3 < iTotal / 5 ? mw3 : iTotal / 5;
    682     const int w4 = mw4 < iTotal / 5 ? mw4 : iTotal / 5;
    683 
    684     /* Giving 1st column all the available space. */
    685     const int w1 = iTotal - w0 - w2 - w3 - w4;
    686 #else
    687     const int mw1 = qMax(pItemView->sizeHintForColumn(1), pItemHeader->sectionSizeHint(1));
    688     const int iHintTotal = mw0 + mw1 + mw2 + mw3 + mw4;
    689     int w0, w1, w2, w3, w4;
    690     int cExcess = iTotal - iHintTotal;
    691     if (cExcess >= 0)
    692     {
    693         /* give excess width to column 1 (path) */
    694         w0 = mw0;
    695         w1 = mw1 + cExcess;
    696         w2 = mw2;
    697         w3 = mw3;
    698         w4 = mw4;
    699     }
    700     else
    701     {
    702         w0 = mw0 < iTotal / 5 ? mw0 : iTotal / 5;
    703         w2 = mw2 < iTotal / 5 ? mw2 : iTotal / 5;
    704         w3 = mw3 < iTotal / 5 ? mw3 : iTotal / 5;
    705         w4 = mw4 < iTotal / 5 ? mw4 : iTotal / 5;
    706         w1 = iTotal - w0 - w2 - w3 - w4;
    707     }
    708 #endif
    709     m_pTreeWidget->setColumnWidth(0, w0);
    710     m_pTreeWidget->setColumnWidth(1, w1);
    711     m_pTreeWidget->setColumnWidth(2, w2);
    712     m_pTreeWidget->setColumnWidth(3, w3);
    713     m_pTreeWidget->setColumnWidth(4, w4);
    714 }
    715 
    716 void UIMachineSettingsSF::sltAdjustTreeFields()
    717 {
    718     QTreeWidgetItem *pMainRoot = m_pTreeWidget->invisibleRootItem();
    719     for (int i = 0; i < pMainRoot->childCount(); ++i)
    720     {
    721         SFTreeViewItem *pSubRoot = static_cast<SFTreeViewItem*>(pMainRoot->child(i));
    722         pSubRoot->adjustText();
    723         for (int j = 0; j < pSubRoot->childCount(); ++j)
    724         {
    725             SFTreeViewItem *pItem = static_cast<SFTreeViewItem*>(pSubRoot->child(j));
    726             pItem->adjustText();
    727         }
    728     }
     205    /* Polish availability: */
     206    m_pEditorSharedFolders->setFeatureAvailable(isMachineInValidMode());
     207    m_pEditorSharedFolders->setFoldersAvailable(UISharedFolderType_Machine, isSharedFolderTypeSupported(UISharedFolderType_Machine));
     208    m_pEditorSharedFolders->setFoldersAvailable(UISharedFolderType_Console, isSharedFolderTypeSupported(UISharedFolderType_Console));
    729209}
    730210
     
    746226{
    747227    /* Prepare main layout: */
    748     QVBoxLayout *pLayoutMain = new QVBoxLayout(this);
    749     if (pLayoutMain)
    750     {
    751         /* Prepare separator: */
    752         m_pLabelSeparator = new QILabelSeparator(this);
    753         if (m_pLabelSeparator)
    754             pLayoutMain->addWidget(m_pLabelSeparator);
    755 
    756         /* Prepare view layout: */
    757         m_pLayoutTree = new QHBoxLayout;
    758         if (m_pLayoutTree)
    759         {
    760             m_pLayoutTree->setContentsMargins(0, 0, 0, 0);
    761             m_pLayoutTree->setSpacing(3);
    762 
    763             /* Prepare tree-widget: */
    764             prepareTreeWidget();
    765             /* Prepare toolbar: */
    766             prepareToolbar();
    767 
    768             pLayoutMain->addLayout(m_pLayoutTree);
    769         }
    770     }
    771 }
    772 
    773 void UIMachineSettingsSF::prepareTreeWidget()
    774 {
    775     /* Prepare shared folders tree-widget: */
    776     m_pTreeWidget = new QITreeWidget(this);
    777     if (m_pTreeWidget)
    778     {
    779         if (m_pLabelSeparator)
    780             m_pLabelSeparator->setBuddy(m_pTreeWidget);
    781         m_pTreeWidget->header()->setSectionsMovable(false);
    782         m_pTreeWidget->setMinimumSize(QSize(0, 200));
    783         m_pTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
    784         m_pTreeWidget->setUniformRowHeights(true);
    785         m_pTreeWidget->setAllColumnsShowFocus(true);
    786 
    787         m_pLayoutTree->addWidget(m_pTreeWidget);
    788     }
    789 }
    790 
    791 void UIMachineSettingsSF::prepareToolbar()
    792 {
    793     /* Prepare shared folders toolbar: */
    794     m_pToolbar = new QIToolBar(this);
    795     if (m_pToolbar)
    796     {
    797         const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
    798         m_pToolbar->setIconSize(QSize(iIconMetric, iIconMetric));
    799         m_pToolbar->setOrientation(Qt::Vertical);
    800 
    801         /* Prepare 'add shared folder' action: */
    802         m_pActionAdd = m_pToolbar->addAction(UIIconPool::iconSet(":/sf_add_16px.png",
    803                                                                  ":/sf_add_disabled_16px.png"),
    804                                              QString(), this, SLOT(sltAddFolder()));
    805         if (m_pActionAdd)
    806             m_pActionAdd->setShortcuts(QList<QKeySequence>() << QKeySequence("Ins") << QKeySequence("Ctrl+N"));
    807 
    808         /* Prepare 'edit shared folder' action: */
    809         m_pActionEdit = m_pToolbar->addAction(UIIconPool::iconSet(":/sf_edit_16px.png",
    810                                                                   ":/sf_edit_disabled_16px.png"),
    811                                               QString(), this, SLOT(sltEditFolder()));
    812         if (m_pActionEdit)
    813             m_pActionEdit->setShortcuts(QList<QKeySequence>() << QKeySequence("Space") << QKeySequence("F2"));
    814 
    815         /* Prepare 'remove shared folder' action: */
    816         m_pActionRemove = m_pToolbar->addAction(UIIconPool::iconSet(":/sf_remove_16px.png",
    817                                                                     ":/sf_remove_disabled_16px.png"),
    818                                                 QString(), this, SLOT(sltRemoveFolder()));
    819         if (m_pActionRemove)
    820             m_pActionRemove->setShortcuts(QList<QKeySequence>() << QKeySequence("Del") << QKeySequence("Ctrl+R"));
    821 
    822         m_pLayoutTree->addWidget(m_pToolbar);
     228    QVBoxLayout *pLayout = new QVBoxLayout(this);
     229    if (pLayout)
     230    {
     231        /* Prepare settings editor: */
     232        m_pEditorSharedFolders = new UISharedFoldersEditor;
     233        if (m_pEditorSharedFolders)
     234            pLayout->addWidget(m_pEditorSharedFolders);
     235
     236        pLayout->addStretch();
    823237    }
    824238}
     
    826240void UIMachineSettingsSF::prepareConnections()
    827241{
    828     /* Configure tree-widget connections: */
    829     connect(m_pTreeWidget, &QITreeWidget::currentItemChanged,
    830             this, &UIMachineSettingsSF::sltHandleCurrentItemChange);
    831     connect(m_pTreeWidget, &QITreeWidget::itemDoubleClicked,
    832             this, &UIMachineSettingsSF::sltHandleDoubleClick);
    833     connect(m_pTreeWidget, &QITreeWidget::customContextMenuRequested,
    834             this, &UIMachineSettingsSF::sltHandleContextMenuRequest);
    835242}
    836243
     
    842249}
    843250
    844 SFTreeViewItem *UIMachineSettingsSF::root(UISharedFolderType enmSharedFolderType)
    845 {
    846     /* Search for the corresponding root item among all the top-level items: */
    847     SFTreeViewItem *pRootItem = 0;
    848     QTreeWidgetItem *pMainRootItem = m_pTreeWidget->invisibleRootItem();
    849     for (int iFolderTypeIndex = 0; iFolderTypeIndex < pMainRootItem->childCount(); ++iFolderTypeIndex)
    850     {
    851         /* Get iterated item: */
    852         SFTreeViewItem *pIteratedItem = static_cast<SFTreeViewItem*>(pMainRootItem->child(iFolderTypeIndex));
    853         /* If iterated item type is what we are looking for: */
    854         if (pIteratedItem->m_enmType == enmSharedFolderType)
    855         {
    856             /* Remember the item: */
    857             pRootItem = static_cast<SFTreeViewItem*>(pIteratedItem);
    858             /* And break further search: */
    859             break;
    860         }
    861     }
    862     /* Return root item: */
    863     return pRootItem;
    864 }
    865 
    866 QStringList UIMachineSettingsSF::usedList(bool fIncludeSelected)
    867 {
    868     /* Make the used names list: */
    869     QStringList list;
    870     QTreeWidgetItemIterator it(m_pTreeWidget);
    871     while (*it)
    872     {
    873         if ((*it)->parent() && (fIncludeSelected || !(*it)->isSelected()))
    874             list << static_cast<SFTreeViewItem*>(*it)->getText(0);
    875         ++it;
    876     }
    877     return list;
    878 }
    879 
    880251bool UIMachineSettingsSF::isSharedFolderTypeSupported(UISharedFolderType enmSharedFolderType) const
    881252{
    882     bool fIsSharedFolderTypeSupported = false;
    883253    switch (enmSharedFolderType)
    884254    {
    885         case MachineType:
    886             fIsSharedFolderTypeSupported = isMachineInValidMode();
    887             break;
    888         case ConsoleType:
    889             fIsSharedFolderTypeSupported = isMachineOnline();
    890             break;
    891         default:
    892             break;
    893     }
    894     return fIsSharedFolderTypeSupported;
    895 }
    896 
    897 void UIMachineSettingsSF::updateRootItemsVisibility()
    898 {
    899     /* Update (show/hide) machine (permanent) root item: */
    900     setRootItemVisible(MachineType, isSharedFolderTypeSupported(MachineType));
    901     /* Update (show/hide) console (temporary) root item: */
    902     setRootItemVisible(ConsoleType, isSharedFolderTypeSupported(ConsoleType));
    903 }
    904 
    905 void UIMachineSettingsSF::setRootItemVisible(UISharedFolderType enmSharedFolderType, bool fVisible)
    906 {
    907     /* Search for the corresponding root item among all the top-level items: */
    908     SFTreeViewItem *pRootItem = root(enmSharedFolderType);
    909     /* If root item, we are looking for, still not found: */
    910     if (!pRootItem)
    911     {
    912         /* Create new shared folder type item: */
    913         pRootItem = new SFTreeViewItem(m_pTreeWidget, SFTreeViewItem::FormatType_EllipsisEnd);
    914         AssertPtrReturnVoid(pRootItem);
    915         {
    916             /* Configure item: */
    917             pRootItem->m_enmType = enmSharedFolderType;
    918             switch (enmSharedFolderType)
    919             {
    920                 case MachineType: pRootItem->m_strName = tr(" Machine Folders"); break;
    921                 case ConsoleType: pRootItem->m_strName = tr(" Transient Folders"); break;
    922                 default: break;
    923             }
    924             pRootItem->updateFields();
    925         }
    926     }
    927     /* Expand/collaps it if necessary: */
    928     pRootItem->setExpanded(fVisible);
    929     /* And hide/show it if necessary: */
    930     pRootItem->setHidden(!fVisible);
    931 }
    932 
    933 void UIMachineSettingsSF::addSharedFolderItem(const UIDataSettingsSharedFolder &sharedFolderData, bool fChoose)
    934 {
    935     /* Create shared folder item: */
    936     SFTreeViewItem *pItem = new SFTreeViewItem(root(sharedFolderData.m_enmType), SFTreeViewItem::FormatType_EllipsisFile);
    937     AssertPtrReturnVoid(pItem);
    938     {
    939         /* Configure item: */
    940         pItem->m_enmType = sharedFolderData.m_enmType;
    941         pItem->m_strName = sharedFolderData.m_strName;
    942         pItem->m_strPath = sharedFolderData.m_strPath;
    943         pItem->m_fWritable = sharedFolderData.m_fWritable;
    944         pItem->m_fAutoMount = sharedFolderData.m_fAutoMount;
    945         pItem->m_strAutoMountPoint = sharedFolderData.m_strAutoMountPoint;
    946         pItem->updateFields();
    947 
    948         /* Select this item if it's new: */
    949         if (fChoose)
    950         {
    951             m_pTreeWidget->scrollToItem(pItem);
    952             m_pTreeWidget->setCurrentItem(pItem);
    953             sltHandleCurrentItemChange(pItem);
    954         }
     255        case UISharedFolderType_Machine: return isMachineInValidMode();
     256        case UISharedFolderType_Console: return isMachineOnline();
     257        default: return false;
    955258    }
    956259}
     
    975278        switch (enmFoldersType)
    976279        {
    977             case MachineType:
     280            case UISharedFolderType_Machine:
    978281            {
    979282                /* Make sure machine was specified: */
     
    989292                break;
    990293            }
    991             case ConsoleType:
     294            case UISharedFolderType_Console:
    992295            {
    993296                /* Make sure console was specified: */
     
    1080383        /* Get folder data: */
    1081384        const UIDataSettingsSharedFolder &newFolderData = folderCache.base();
    1082         const UISharedFolderType enmFoldersType = newFolderData.m_enmType;
    1083         const QString strFolderName = newFolderData.m_strName;
     385        const UISharedFolderType enmFoldersType = newFolderData.m_guiData.m_enmType;
     386        const QString strFolderName = newFolderData.m_guiData.m_strName;
    1084387
    1085388        /* Get current folders: */
     
    1099402            switch (enmFoldersType)
    1100403            {
    1101                 case MachineType:
     404                case UISharedFolderType_Machine:
    1102405                {
    1103406                    /* Remove existing folder: */
     
    1112415                    break;
    1113416                }
    1114                 case ConsoleType:
     417                case UISharedFolderType_Console:
    1115418                {
    1116419                    /* Remove existing folder: */
     
    1138441    /* Get folder data: */
    1139442    const UIDataSettingsSharedFolder &newFolderData = folderCache.data();
    1140     const UISharedFolderType enmFoldersType = newFolderData.m_enmType;
    1141     const QString strFolderName = newFolderData.m_strName;
    1142     const QString strFolderPath = newFolderData.m_strPath;
    1143     const bool fIsWritable = newFolderData.m_fWritable;
    1144     const bool fIsAutoMount = newFolderData.m_fAutoMount;
    1145     const QString strAutoMountPoint = newFolderData.m_strAutoMountPoint;
     443    const UISharedFolderType enmFoldersType = newFolderData.m_guiData.m_enmType;
     444    const QString strFolderName = newFolderData.m_guiData.m_strName;
     445    const QString strFolderPath = newFolderData.m_guiData.m_strPath;
     446    const bool fIsWritable = newFolderData.m_guiData.m_fWritable;
     447    const bool fIsAutoMount = newFolderData.m_guiData.m_fAutoMount;
     448    const QString strAutoMountPoint = newFolderData.m_guiData.m_strAutoMountPoint;
    1146449
    1147450    /* Get current folders: */
     
    1160463        switch (enmFoldersType)
    1161464        {
    1162             case MachineType:
     465            case UISharedFolderType_Machine:
    1163466            {
    1164467                /* Create new folder: */
     
    1170473                break;
    1171474            }
    1172             case ConsoleType:
     475            case UISharedFolderType_Console:
    1173476            {
    1174477                /* Create new folder: */
     
    1188491    return fSuccess;
    1189492}
    1190 
    1191 
    1192 #include "UIMachineSettingsSF.moc"
  • trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsSF.h

    r94333 r95077  
    2929
    3030/* Forward declarations: */
    31 class QHBoxLayout;
    32 class QTreeWidgetItem;
    33 class QITreeWidget;
    34 class QILabelSeparator;
    35 class SFTreeViewItem;
    36 class QIToolBar;
     31class UISharedFoldersEditor;
    3732
    3833struct UIDataSettingsSharedFolder;
    3934struct UIDataSettingsSharedFolders;
    40 enum UISharedFolderType { MachineType, ConsoleType };
    4135typedef UISettingsCache<UIDataSettingsSharedFolder> UISettingsCacheSharedFolder;
    4236typedef UISettingsCachePool<UIDataSettingsSharedFolders, UISettingsCacheSharedFolder> UISettingsCacheSharedFolders;
     
    8074    virtual void polishPage() RT_OVERRIDE;
    8175
    82     /** Handles show @a pEvent. */
    83     virtual void showEvent(QShowEvent *aEvent) RT_OVERRIDE;
    84 
    85     /** Handles resize @a pEvent. */
    86     virtual void resizeEvent(QResizeEvent *pEvent) RT_OVERRIDE;
    87 
    88 private slots:
    89 
    90     /** Handles command to add shared folder. */
    91     void sltAddFolder();
    92     /** Handles command to edit shared folder. */
    93     void sltEditFolder();
    94     /** Handles command to remove shared folder. */
    95     void sltRemoveFolder();
    96 
    97     /** Handles @a pCurrentItem change. */
    98     void sltHandleCurrentItemChange(QTreeWidgetItem *pCurrentItem);
    99     /** Handles @a pItem double-click. */
    100     void sltHandleDoubleClick(QTreeWidgetItem *pItem);
    101     /** Handles context menu request for @a position. */
    102     void sltHandleContextMenuRequest(const QPoint &position);
    103 
    104     /** Performs request to adjust tree. */
    105     void sltAdjustTree();
    106     /** Performs request to adjust tree fields. */
    107     void sltAdjustTreeFields();
    108 
    10976private:
    11077
     
    11380    /** Prepares Widgets. */
    11481    void prepareWidgets();
    115     /** Prepares shared folders tree-wdget. */
    116     void prepareTreeWidget();
    117     /** Prepares shared folders toolbar. */
    118     void prepareToolbar();
    11982    /** Prepares connections. */
    12083    void prepareConnections();
     
    12285    void cleanup();
    12386
    124     /** Returns the tree-view root item for corresponding shared folder @a type. */
    125     SFTreeViewItem *root(UISharedFolderType type);
    126     /** Returns a list of used shared folder names. */
    127     QStringList usedList(bool fIncludeSelected);
    128 
    12987    /** Returns whether the corresponding @a enmFoldersType supported. */
    13088    bool isSharedFolderTypeSupported(UISharedFolderType enmFoldersType) const;
    131     /** Updates root item visibility. */
    132     void updateRootItemsVisibility();
    133     /** Defines whether the root item of @a enmFoldersType is @a fVisible. */
    134     void setRootItemVisible(UISharedFolderType enmFoldersType, bool fVisible);
    135 
    136     /** Creates shared folder item based on passed @a data. */
    137     void addSharedFolderItem(const UIDataSettingsSharedFolder &sharedFolderData, bool fChoose);
    13889
    13990    /** Gathers a vector of shared folders of the passed @a enmFoldersType. */
     
    156107    /** @name Widgets
    157108      * @{ */
    158         /** Holds the widget separator instance. */
    159         QILabelSeparator *m_pLabelSeparator;
    160         /** Holds the tree layout instance. */
    161         QHBoxLayout      *m_pLayoutTree;
    162         /** Holds the tree-widget instance. */
    163         QITreeWidget     *m_pTreeWidget;
    164         /** Holds the toolbar instance. */
    165         QIToolBar        *m_pToolbar;
    166         /** Holds the 'add shared folder' action instance. */
    167         QAction          *m_pActionAdd;
    168         /** Holds the 'edit shared folder' action instance. */
    169         QAction          *m_pActionEdit;
    170         /** Holds the 'remove shared folder' action instance. */
    171         QAction          *m_pActionRemove;
     109        /** Holds the shared folders editor instance. */
     110        UISharedFoldersEditor *m_pEditorSharedFolders;
    172111    /** @} */
    173112};
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette