1 | /* $Id: UIMachineSettingsSF.cpp 37126 2011-05-17 13:56:50Z vboxsync $ */
|
---|
2 | /** @file
|
---|
3 | *
|
---|
4 | * VBox frontends: Qt4 GUI ("VirtualBox"):
|
---|
5 | * UIMachineSettingsSF class implementation
|
---|
6 | */
|
---|
7 |
|
---|
8 | /*
|
---|
9 | * Copyright (C) 2008-2011 Oracle Corporation
|
---|
10 | *
|
---|
11 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
12 | * available from http://www.virtualbox.org. This file is free software;
|
---|
13 | * you can redistribute it and/or modify it under the terms of the GNU
|
---|
14 | * General Public License (GPL) as published by the Free Software
|
---|
15 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
16 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
17 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
18 | */
|
---|
19 |
|
---|
20 | /* Local includes */
|
---|
21 | #include "UIIconPool.h"
|
---|
22 | #include "VBoxGlobal.h"
|
---|
23 | #include "VBoxProblemReporter.h"
|
---|
24 | #include "VBoxUtils.h"
|
---|
25 | #include "UIMachineSettingsSF.h"
|
---|
26 | #include "UIMachineSettingsSFDetails.h"
|
---|
27 |
|
---|
28 | /* Global includes */
|
---|
29 | #include <QHeaderView>
|
---|
30 | #include <QTimer>
|
---|
31 |
|
---|
32 | class SFTreeViewItem : public QTreeWidgetItem
|
---|
33 | {
|
---|
34 | public:
|
---|
35 |
|
---|
36 | enum { SFTreeViewItemType = QTreeWidgetItem::UserType + 1 };
|
---|
37 |
|
---|
38 | enum FormatType
|
---|
39 | {
|
---|
40 | IncorrectFormat = 0,
|
---|
41 | EllipsisStart = 1,
|
---|
42 | EllipsisMiddle = 2,
|
---|
43 | EllipsisEnd = 3,
|
---|
44 | EllipsisFile = 4
|
---|
45 | };
|
---|
46 |
|
---|
47 | /* Root Item */
|
---|
48 | SFTreeViewItem (QTreeWidget *aParent, const QStringList &aFields, FormatType aFormat)
|
---|
49 | : QTreeWidgetItem (aParent, aFields, SFTreeViewItemType), mFormat (aFormat)
|
---|
50 | {
|
---|
51 | setFirstColumnSpanned (true);
|
---|
52 | setFlags (flags() ^ Qt::ItemIsSelectable);
|
---|
53 | }
|
---|
54 |
|
---|
55 | /* Child Item */
|
---|
56 | SFTreeViewItem (SFTreeViewItem *aParent, const QStringList &aFields, FormatType aFormat)
|
---|
57 | : QTreeWidgetItem (aParent, aFields, SFTreeViewItemType), mFormat (aFormat)
|
---|
58 | {
|
---|
59 | updateText (aFields);
|
---|
60 | }
|
---|
61 |
|
---|
62 | bool operator< (const QTreeWidgetItem &aOther) const
|
---|
63 | {
|
---|
64 | /* Root items should always been sorted by id-field. */
|
---|
65 | return parent() ? text (0).toLower() < aOther.text (0).toLower() :
|
---|
66 | text (1).toLower() < aOther.text (1).toLower();
|
---|
67 | }
|
---|
68 |
|
---|
69 | SFTreeViewItem* child (int aIndex) const
|
---|
70 | {
|
---|
71 | QTreeWidgetItem *item = QTreeWidgetItem::child (aIndex);
|
---|
72 | return item && item->type() == SFTreeViewItemType ? static_cast <SFTreeViewItem*> (item) : 0;
|
---|
73 | }
|
---|
74 |
|
---|
75 | QString getText (int aIndex) const
|
---|
76 | {
|
---|
77 | return aIndex >= 0 && aIndex < (int)mTextList.size() ? mTextList [aIndex] : QString::null;
|
---|
78 | }
|
---|
79 |
|
---|
80 | void updateText (const QStringList &aFields)
|
---|
81 | {
|
---|
82 | mTextList.clear();
|
---|
83 | mTextList << aFields;
|
---|
84 | adjustText();
|
---|
85 | }
|
---|
86 |
|
---|
87 | void adjustText()
|
---|
88 | {
|
---|
89 | for (int i = 0; i < treeWidget()->columnCount(); ++ i)
|
---|
90 | processColumn (i);
|
---|
91 | }
|
---|
92 |
|
---|
93 | private:
|
---|
94 |
|
---|
95 | void processColumn (int aColumn)
|
---|
96 | {
|
---|
97 | QString oneString = getText (aColumn);
|
---|
98 | if (oneString.isNull())
|
---|
99 | return;
|
---|
100 | QFontMetrics fm = treeWidget()->fontMetrics();
|
---|
101 | int oldSize = fm.width (oneString);
|
---|
102 | int indentSize = fm.width (" ... ");
|
---|
103 | int itemIndent = parent() ? treeWidget()->indentation() * 2 : treeWidget()->indentation();
|
---|
104 | if (aColumn == 0)
|
---|
105 | indentSize += itemIndent;
|
---|
106 | int cWidth = treeWidget()->columnWidth (aColumn);
|
---|
107 |
|
---|
108 | /* Compress text */
|
---|
109 | int start = 0;
|
---|
110 | int finish = 0;
|
---|
111 | int position = 0;
|
---|
112 | int textWidth = 0;
|
---|
113 | do
|
---|
114 | {
|
---|
115 | textWidth = fm.width (oneString);
|
---|
116 | if (textWidth + indentSize > cWidth)
|
---|
117 | {
|
---|
118 | start = 0;
|
---|
119 | finish = oneString.length();
|
---|
120 |
|
---|
121 | /* Selecting remove position */
|
---|
122 | switch (mFormat)
|
---|
123 | {
|
---|
124 | case EllipsisStart:
|
---|
125 | position = start;
|
---|
126 | break;
|
---|
127 | case EllipsisMiddle:
|
---|
128 | position = (finish - start) / 2;
|
---|
129 | break;
|
---|
130 | case EllipsisEnd:
|
---|
131 | position = finish - 1;
|
---|
132 | break;
|
---|
133 | case EllipsisFile:
|
---|
134 | {
|
---|
135 | QRegExp regExp ("([\\\\/][^\\\\^/]+[\\\\/]?$)");
|
---|
136 | int newFinish = regExp.indexIn (oneString);
|
---|
137 | if (newFinish != -1)
|
---|
138 | finish = newFinish;
|
---|
139 | position = (finish - start) / 2;
|
---|
140 | break;
|
---|
141 | }
|
---|
142 | default:
|
---|
143 | AssertMsgFailed (("Invalid format type\n"));
|
---|
144 | }
|
---|
145 |
|
---|
146 | if (position == finish)
|
---|
147 | break;
|
---|
148 |
|
---|
149 | oneString.remove (position, 1);
|
---|
150 | }
|
---|
151 | }
|
---|
152 | while (textWidth + indentSize > cWidth);
|
---|
153 |
|
---|
154 | if (position || mFormat == EllipsisFile) oneString.insert (position, "...");
|
---|
155 | int newSize = fm.width (oneString);
|
---|
156 | setText (aColumn, newSize < oldSize ? oneString : mTextList [aColumn]);
|
---|
157 | setToolTip (aColumn, text (aColumn) == getText (aColumn) ? QString::null : getText (aColumn));
|
---|
158 |
|
---|
159 | /* Calculate item's size-hint */
|
---|
160 | setSizeHint (aColumn, QSize (fm.width (QString (" %1 ").arg (getText (aColumn))), 100));
|
---|
161 | }
|
---|
162 |
|
---|
163 | FormatType mFormat;
|
---|
164 | QStringList mTextList;
|
---|
165 | };
|
---|
166 |
|
---|
167 | UIMachineSettingsSF::UIMachineSettingsSF()
|
---|
168 | : mNewAction(0), mEdtAction(0), mDelAction(0)
|
---|
169 | {
|
---|
170 | /* Apply UI decorations */
|
---|
171 | Ui::UIMachineSettingsSF::setupUi (this);
|
---|
172 |
|
---|
173 | /* Prepare actions */
|
---|
174 | mNewAction = new QAction (this);
|
---|
175 | mEdtAction = new QAction (this);
|
---|
176 | mDelAction = new QAction (this);
|
---|
177 |
|
---|
178 | mNewAction->setShortcut (QKeySequence ("Ins"));
|
---|
179 | mEdtAction->setShortcut (QKeySequence ("Ctrl+Space"));
|
---|
180 | mDelAction->setShortcut (QKeySequence ("Del"));
|
---|
181 |
|
---|
182 | mNewAction->setIcon(UIIconPool::iconSet(":/add_shared_folder_16px.png",
|
---|
183 | ":/add_shared_folder_disabled_16px.png"));
|
---|
184 | mEdtAction->setIcon(UIIconPool::iconSet(":/edit_shared_folder_16px.png",
|
---|
185 | ":/edit_shared_folder_disabled_16px.png"));
|
---|
186 | mDelAction->setIcon(UIIconPool::iconSet(":/remove_shared_folder_16px.png",
|
---|
187 | ":/remove_shared_folder_disabled_16px.png"));
|
---|
188 |
|
---|
189 | /* Prepare toolbar */
|
---|
190 | mTbFolders->setUsesTextLabel (false);
|
---|
191 | mTbFolders->setIconSize (QSize (16, 16));
|
---|
192 | mTbFolders->setOrientation (Qt::Vertical);
|
---|
193 | mTbFolders->addAction (mNewAction);
|
---|
194 | mTbFolders->addAction (mEdtAction);
|
---|
195 | mTbFolders->addAction (mDelAction);
|
---|
196 |
|
---|
197 | /* Setup connections */
|
---|
198 | mTwFolders->header()->setMovable (false);
|
---|
199 | connect (mNewAction, SIGNAL (triggered (bool)), this, SLOT (addTriggered()));
|
---|
200 | connect (mEdtAction, SIGNAL (triggered (bool)), this, SLOT (edtTriggered()));
|
---|
201 | connect (mDelAction, SIGNAL (triggered (bool)), this, SLOT (delTriggered()));
|
---|
202 | connect (mTwFolders, SIGNAL (currentItemChanged (QTreeWidgetItem *, QTreeWidgetItem *)),
|
---|
203 | this, SLOT (processCurrentChanged (QTreeWidgetItem *)));
|
---|
204 | connect (mTwFolders, SIGNAL (itemDoubleClicked (QTreeWidgetItem *, int)),
|
---|
205 | this, SLOT (processDoubleClick (QTreeWidgetItem *)));
|
---|
206 | connect (mTwFolders, SIGNAL (customContextMenuRequested (const QPoint &)),
|
---|
207 | this, SLOT (showContextMenu (const QPoint &)));
|
---|
208 |
|
---|
209 | retranslateUi();
|
---|
210 | }
|
---|
211 |
|
---|
212 | void UIMachineSettingsSF::resizeEvent (QResizeEvent *aEvent)
|
---|
213 | {
|
---|
214 | NOREF(aEvent);
|
---|
215 | adjustList();
|
---|
216 | }
|
---|
217 |
|
---|
218 | /* Load data to cashe from corresponding external object(s),
|
---|
219 | * this task COULD be performed in other than GUI thread: */
|
---|
220 | void UIMachineSettingsSF::loadToCacheFrom(QVariant &data)
|
---|
221 | {
|
---|
222 | /* Fetch data to machine: */
|
---|
223 | UISettingsPageMachine::fetchData(data);
|
---|
224 |
|
---|
225 | /* Clear cache initially: */
|
---|
226 | m_cache.clear();
|
---|
227 |
|
---|
228 | /* Load machine (permanent) shared folders into shared folders cache if possible: */
|
---|
229 | if (isSharedFolderTypeSupported(MachineType))
|
---|
230 | loadToCacheFrom(MachineType);
|
---|
231 | /* Load console (temporary) shared folders into shared folders cache if possible: */
|
---|
232 | if (isSharedFolderTypeSupported(ConsoleType))
|
---|
233 | loadToCacheFrom(ConsoleType);
|
---|
234 |
|
---|
235 | /* Upload machine to data: */
|
---|
236 | UISettingsPageMachine::uploadData(data);
|
---|
237 | }
|
---|
238 |
|
---|
239 | void UIMachineSettingsSF::loadToCacheFrom(UISharedFolderType sharedFoldersType)
|
---|
240 | {
|
---|
241 | /* Get current shared folders: */
|
---|
242 | CSharedFolderVector sharedFolders = getSharedFolders(sharedFoldersType);
|
---|
243 |
|
---|
244 | /* For each shared folder: */
|
---|
245 | for (int iFolderIndex = 0; iFolderIndex < sharedFolders.size(); ++iFolderIndex)
|
---|
246 | {
|
---|
247 | /* Prepare cache key & data: */
|
---|
248 | QString strSharedFolderKey = QString::number(iFolderIndex);
|
---|
249 | UIDataSettingsSharedFolder sharedFolderData;
|
---|
250 |
|
---|
251 | /* Check if shared folder exists: */
|
---|
252 | const CSharedFolder &folder = sharedFolders[iFolderIndex];
|
---|
253 | if (!folder.isNull())
|
---|
254 | {
|
---|
255 | /* Gather shared folder values: */
|
---|
256 | sharedFolderData.m_type = sharedFoldersType;
|
---|
257 | sharedFolderData.m_strName = folder.GetName();
|
---|
258 | sharedFolderData.m_strHostPath = folder.GetHostPath();
|
---|
259 | sharedFolderData.m_fAutoMount = folder.GetAutoMount();
|
---|
260 | sharedFolderData.m_fWritable = folder.GetWritable();
|
---|
261 | /* Override shared folder cache key: */
|
---|
262 | strSharedFolderKey = sharedFolderData.m_strName;
|
---|
263 | }
|
---|
264 |
|
---|
265 | /* Cache shared folder data: */
|
---|
266 | m_cache.child(strSharedFolderKey).cacheInitialData(sharedFolderData);
|
---|
267 | }
|
---|
268 | }
|
---|
269 |
|
---|
270 | /* Load data to corresponding widgets from cache,
|
---|
271 | * this task SHOULD be performed in GUI thread only: */
|
---|
272 | void UIMachineSettingsSF::getFromCache()
|
---|
273 | {
|
---|
274 | /* Clear list initially: */
|
---|
275 | mTwFolders->clear();
|
---|
276 |
|
---|
277 | /* Update root items visibility: */
|
---|
278 | updateRootItemsVisibility();
|
---|
279 |
|
---|
280 | /* Load shared folders data: */
|
---|
281 | for (int iFolderIndex = 0; iFolderIndex < m_cache.childCount(); ++iFolderIndex)
|
---|
282 | {
|
---|
283 | /* Get shared folder data: */
|
---|
284 | const UIDataSettingsSharedFolder &sharedFolderData = m_cache.child(iFolderIndex).base();
|
---|
285 | /* Prepare item fields: */
|
---|
286 | QStringList fields;
|
---|
287 | fields << sharedFolderData.m_strName
|
---|
288 | << sharedFolderData.m_strHostPath
|
---|
289 | << (sharedFolderData.m_fAutoMount ? mTrYes : "")
|
---|
290 | << (sharedFolderData.m_fWritable ? mTrFull : mTrReadOnly);
|
---|
291 | /* Create new shared folders item: */
|
---|
292 | new SFTreeViewItem(root(sharedFolderData.m_type), fields, SFTreeViewItem::EllipsisFile);
|
---|
293 | }
|
---|
294 | /* Ensure current item fetched: */
|
---|
295 | mTwFolders->setCurrentItem(mTwFolders->topLevelItem(0));
|
---|
296 | processCurrentChanged(mTwFolders->currentItem());
|
---|
297 |
|
---|
298 | /* Polish page finally: */
|
---|
299 | polishPage();
|
---|
300 | }
|
---|
301 |
|
---|
302 | /* Save data from corresponding widgets to cache,
|
---|
303 | * this task SHOULD be performed in GUI thread only: */
|
---|
304 | void UIMachineSettingsSF::putToCache()
|
---|
305 | {
|
---|
306 | /* For each shared folder type: */
|
---|
307 | QTreeWidgetItem *pMainRootItem = mTwFolders->invisibleRootItem();
|
---|
308 | for (int iFodlersTypeIndex = 0; iFodlersTypeIndex < pMainRootItem->childCount(); ++iFodlersTypeIndex)
|
---|
309 | {
|
---|
310 | /* Get shared folder root item: */
|
---|
311 | SFTreeViewItem *pFolderTypeRoot = static_cast<SFTreeViewItem*>(pMainRootItem->child(iFodlersTypeIndex));
|
---|
312 | UISharedFolderType sharedFolderType = (UISharedFolderType)pFolderTypeRoot->text(1).toInt();
|
---|
313 | /* For each shared folder of current type: */
|
---|
314 | for (int iFoldersIndex = 0; iFoldersIndex < pFolderTypeRoot->childCount(); ++iFoldersIndex)
|
---|
315 | {
|
---|
316 | SFTreeViewItem *pFolderItem = static_cast<SFTreeViewItem*>(pFolderTypeRoot->child(iFoldersIndex));
|
---|
317 | UIDataSettingsSharedFolder sharedFolderData;
|
---|
318 | sharedFolderData.m_type = sharedFolderType;
|
---|
319 | sharedFolderData.m_strName = pFolderItem->getText(0);
|
---|
320 | sharedFolderData.m_strHostPath = pFolderItem->getText(1);
|
---|
321 | sharedFolderData.m_fAutoMount = pFolderItem->getText(2) == mTrYes ? true : false;
|
---|
322 | sharedFolderData.m_fWritable = pFolderItem->getText(3) == mTrFull ? true : false;
|
---|
323 | m_cache.child(sharedFolderData.m_strName).cacheCurrentData(sharedFolderData);
|
---|
324 | }
|
---|
325 | }
|
---|
326 | }
|
---|
327 |
|
---|
328 | /* Save data from cache to corresponding external object(s),
|
---|
329 | * this task COULD be performed in other than GUI thread: */
|
---|
330 | void UIMachineSettingsSF::saveFromCacheTo(QVariant &data)
|
---|
331 | {
|
---|
332 | /* Fetch data to machine: */
|
---|
333 | UISettingsPageMachine::fetchData(data);
|
---|
334 |
|
---|
335 | /* Check if shared folders data was changed at all: */
|
---|
336 | if (m_cache.wasChanged())
|
---|
337 | {
|
---|
338 | /* Save machine (permanent) shared folders if possible: */
|
---|
339 | if (isSharedFolderTypeSupported(MachineType))
|
---|
340 | saveFromCacheTo(MachineType);
|
---|
341 | /* Save console (temporary) shared folders if possible: */
|
---|
342 | if (isSharedFolderTypeSupported(ConsoleType))
|
---|
343 | saveFromCacheTo(ConsoleType);
|
---|
344 | }
|
---|
345 |
|
---|
346 | /* Upload machine to data: */
|
---|
347 | UISettingsPageMachine::uploadData(data);
|
---|
348 | }
|
---|
349 |
|
---|
350 | void UIMachineSettingsSF::saveFromCacheTo(UISharedFolderType sharedFoldersType)
|
---|
351 | {
|
---|
352 | /* For each shared folder data set: */
|
---|
353 | for (int iSharedFolderIndex = 0; iSharedFolderIndex < m_cache.childCount(); ++iSharedFolderIndex)
|
---|
354 | {
|
---|
355 | /* Check if this shared folder data was actually changed: */
|
---|
356 | const UICacheSettingsSharedFolder &sharedFolderCache = m_cache.child(iSharedFolderIndex);
|
---|
357 | if (sharedFolderCache.wasChanged())
|
---|
358 | {
|
---|
359 | /* If shared folder was removed: */
|
---|
360 | if (sharedFolderCache.wasRemoved())
|
---|
361 | {
|
---|
362 | /* Get shared folder data: */
|
---|
363 | const UIDataSettingsSharedFolder &sharedFolderData = sharedFolderCache.base();
|
---|
364 | /* Check if thats shared folder of required type before removing: */
|
---|
365 | if (sharedFolderData.m_type == sharedFoldersType)
|
---|
366 | removeSharedFolder(sharedFolderCache);
|
---|
367 | }
|
---|
368 |
|
---|
369 | /* If shared folder was created: */
|
---|
370 | if (sharedFolderCache.wasCreated())
|
---|
371 | {
|
---|
372 | /* Get shared folder data: */
|
---|
373 | const UIDataSettingsSharedFolder &sharedFolderData = sharedFolderCache.data();
|
---|
374 | /* Check if thats shared folder of required type before creating: */
|
---|
375 | if (sharedFolderData.m_type == sharedFoldersType)
|
---|
376 | createSharedFolder(sharedFolderCache);
|
---|
377 | }
|
---|
378 |
|
---|
379 | /* If shared folder was changed: */
|
---|
380 | if (sharedFolderCache.wasUpdated())
|
---|
381 | {
|
---|
382 | /* Get shared folder data: */
|
---|
383 | const UIDataSettingsSharedFolder &sharedFolderData = sharedFolderCache.data();
|
---|
384 | /* Check if thats shared folder of required type before recreating: */
|
---|
385 | if (sharedFolderData.m_type == sharedFoldersType)
|
---|
386 | {
|
---|
387 | removeSharedFolder(sharedFolderCache);
|
---|
388 | createSharedFolder(sharedFolderCache);
|
---|
389 | }
|
---|
390 | }
|
---|
391 | }
|
---|
392 | }
|
---|
393 | }
|
---|
394 |
|
---|
395 | void UIMachineSettingsSF::setOrderAfter (QWidget *aWidget)
|
---|
396 | {
|
---|
397 | setTabOrder (aWidget, mTwFolders);
|
---|
398 | }
|
---|
399 |
|
---|
400 | void UIMachineSettingsSF::retranslateUi()
|
---|
401 | {
|
---|
402 | /* Translate uic generated strings */
|
---|
403 | Ui::UIMachineSettingsSF::retranslateUi (this);
|
---|
404 |
|
---|
405 | mNewAction->setText (tr ("&Add Shared Folder"));
|
---|
406 | mEdtAction->setText (tr ("&Edit Shared Folder"));
|
---|
407 | mDelAction->setText (tr ("&Remove Shared Folder"));
|
---|
408 |
|
---|
409 | mNewAction->setToolTip (mNewAction->text().remove ('&') +
|
---|
410 | QString (" (%1)").arg (mNewAction->shortcut().toString()));
|
---|
411 | mEdtAction->setToolTip (mEdtAction->text().remove ('&') +
|
---|
412 | QString (" (%1)").arg (mEdtAction->shortcut().toString()));
|
---|
413 | mDelAction->setToolTip (mDelAction->text().remove ('&') +
|
---|
414 | QString (" (%1)").arg (mDelAction->shortcut().toString()));
|
---|
415 |
|
---|
416 | mNewAction->setWhatsThis (tr ("Adds a new shared folder definition."));
|
---|
417 | mEdtAction->setWhatsThis (tr ("Edits the selected shared folder definition."));
|
---|
418 | mDelAction->setWhatsThis (tr ("Removes the selected shared folder definition."));
|
---|
419 |
|
---|
420 | mTrFull = tr ("Full");
|
---|
421 | mTrReadOnly = tr ("Read-only");
|
---|
422 | mTrYes = tr ("Yes"); /** @todo Need to figure out if this string is necessary at all! */
|
---|
423 | }
|
---|
424 |
|
---|
425 | void UIMachineSettingsSF::addTriggered()
|
---|
426 | {
|
---|
427 | /* Invoke Add-Box Dialog */
|
---|
428 | UIMachineSettingsSFDetails dlg (UIMachineSettingsSFDetails::AddType, isSharedFolderTypeSupported(ConsoleType), usedList (true), this);
|
---|
429 | if (dlg.exec() == QDialog::Accepted)
|
---|
430 | {
|
---|
431 | QString name = dlg.name();
|
---|
432 | QString path = dlg.path();
|
---|
433 | bool isPermanent = dlg.isPermanent();
|
---|
434 | /* Shared folder's name & path could not be empty */
|
---|
435 | Assert (!name.isEmpty() && !path.isEmpty());
|
---|
436 | /* Appending a new listview item to the root */
|
---|
437 | QStringList fields;
|
---|
438 | fields << name /* name */ << path /* path */
|
---|
439 | << (dlg.isAutoMounted() ? mTrYes : "" /* auto mount? */)
|
---|
440 | << (dlg.isWriteable() ? mTrFull : mTrReadOnly /* writable? */);
|
---|
441 | SFTreeViewItem *item = new SFTreeViewItem (root(isPermanent ? MachineType : ConsoleType),
|
---|
442 | fields, SFTreeViewItem::EllipsisFile);
|
---|
443 | mTwFolders->sortItems (0, Qt::AscendingOrder);
|
---|
444 | mTwFolders->scrollToItem (item);
|
---|
445 | mTwFolders->setCurrentItem (item);
|
---|
446 | processCurrentChanged (item);
|
---|
447 | mTwFolders->setFocus();
|
---|
448 | adjustList();
|
---|
449 | }
|
---|
450 | }
|
---|
451 |
|
---|
452 | void UIMachineSettingsSF::edtTriggered()
|
---|
453 | {
|
---|
454 | /* Check selected item */
|
---|
455 | QTreeWidgetItem *selectedItem = mTwFolders->selectedItems().size() == 1 ? mTwFolders->selectedItems() [0] : 0;
|
---|
456 | SFTreeViewItem *item = selectedItem && selectedItem->type() == SFTreeViewItem::SFTreeViewItemType ?
|
---|
457 | static_cast <SFTreeViewItem*> (selectedItem) : 0;
|
---|
458 | Assert (item);
|
---|
459 | Assert (item->parent());
|
---|
460 |
|
---|
461 | /* Invoke Edit-Box Dialog */
|
---|
462 | UIMachineSettingsSFDetails dlg (UIMachineSettingsSFDetails::EditType, isSharedFolderTypeSupported(ConsoleType), usedList (false), this);
|
---|
463 | dlg.setPath (item->getText (1));
|
---|
464 | dlg.setName (item->getText (0));
|
---|
465 | dlg.setPermanent ((UISharedFolderType)item->parent()->text (1).toInt() != ConsoleType);
|
---|
466 | dlg.setAutoMount (item->getText (2) == mTrYes);
|
---|
467 | dlg.setWriteable (item->getText (3) == mTrFull);
|
---|
468 | if (dlg.exec() == QDialog::Accepted)
|
---|
469 | {
|
---|
470 | QString name = dlg.name();
|
---|
471 | QString path = dlg.path();
|
---|
472 | bool isPermanent = dlg.isPermanent();
|
---|
473 | /* Shared folder's name & path could not be empty */
|
---|
474 | Assert (!name.isEmpty() && !path.isEmpty());
|
---|
475 | /* Searching new root for the selected listview item */
|
---|
476 | SFTreeViewItem *pRoot = root(isPermanent ? MachineType : ConsoleType);
|
---|
477 | /* Updating an edited listview item */
|
---|
478 | QStringList fields;
|
---|
479 | fields << name /* name */ << path /* path */
|
---|
480 | << (dlg.isAutoMounted() ? mTrYes : "" /* auto mount? */)
|
---|
481 | << (dlg.isWriteable() ? mTrFull : mTrReadOnly /* writable? */);
|
---|
482 | item->updateText (fields);
|
---|
483 | mTwFolders->sortItems (0, Qt::AscendingOrder);
|
---|
484 | if (item->parent() != pRoot)
|
---|
485 | {
|
---|
486 | /* Move the selected item into new location */
|
---|
487 | item->parent()->takeChild (item->parent()->indexOfChild (item));
|
---|
488 | pRoot->insertChild (pRoot->childCount(), item);
|
---|
489 | mTwFolders->scrollToItem (item);
|
---|
490 | mTwFolders->setCurrentItem (item);
|
---|
491 | processCurrentChanged (item);
|
---|
492 | mTwFolders->setFocus();
|
---|
493 | }
|
---|
494 | adjustList();
|
---|
495 | }
|
---|
496 | }
|
---|
497 |
|
---|
498 | void UIMachineSettingsSF::delTriggered()
|
---|
499 | {
|
---|
500 | QTreeWidgetItem *selectedItem = mTwFolders->selectedItems().size() == 1 ? mTwFolders->selectedItems() [0] : 0;
|
---|
501 | Assert (selectedItem);
|
---|
502 | delete selectedItem;
|
---|
503 | adjustList();
|
---|
504 | }
|
---|
505 |
|
---|
506 | void UIMachineSettingsSF::processCurrentChanged (QTreeWidgetItem *aCurrentItem)
|
---|
507 | {
|
---|
508 | if (aCurrentItem && aCurrentItem->parent() && !aCurrentItem->isSelected())
|
---|
509 | aCurrentItem->setSelected (true);
|
---|
510 | QString key = !aCurrentItem ? QString::null : aCurrentItem->parent() ?
|
---|
511 | aCurrentItem->parent()->text (1) : aCurrentItem->text (1);
|
---|
512 | bool addEnabled = aCurrentItem;
|
---|
513 | bool removeEnabled = addEnabled && aCurrentItem->parent();
|
---|
514 | mNewAction->setEnabled (addEnabled);
|
---|
515 | mEdtAction->setEnabled (removeEnabled);
|
---|
516 | mDelAction->setEnabled (removeEnabled);
|
---|
517 | }
|
---|
518 |
|
---|
519 | void UIMachineSettingsSF::processDoubleClick (QTreeWidgetItem *aItem)
|
---|
520 | {
|
---|
521 | bool editEnabled = aItem && aItem->parent();
|
---|
522 | if (editEnabled)
|
---|
523 | edtTriggered();
|
---|
524 | }
|
---|
525 |
|
---|
526 | void UIMachineSettingsSF::showContextMenu(const QPoint &pos)
|
---|
527 | {
|
---|
528 | QMenu menu;
|
---|
529 | QTreeWidgetItem *pItem = mTwFolders->itemAt(pos);
|
---|
530 | if (mTwFolders->isEnabled() && pItem && pItem->flags() & Qt::ItemIsSelectable)
|
---|
531 | {
|
---|
532 | menu.addAction(mEdtAction);
|
---|
533 | menu.addAction(mDelAction);
|
---|
534 | }
|
---|
535 | else
|
---|
536 | {
|
---|
537 | menu.addAction(mNewAction);
|
---|
538 | }
|
---|
539 | if (!menu.isEmpty())
|
---|
540 | menu.exec(mTwFolders->viewport()->mapToGlobal(pos));
|
---|
541 | }
|
---|
542 |
|
---|
543 | void UIMachineSettingsSF::adjustList()
|
---|
544 | {
|
---|
545 | /*
|
---|
546 | * Calculates required columns sizes to max out column 2
|
---|
547 | * and let all other columns stay at their minimum sizes.
|
---|
548 | *
|
---|
549 | * Columns
|
---|
550 | * 0 = Tree view
|
---|
551 | * 1 = Shared Folder name
|
---|
552 | * 2 = Auto-mount flag
|
---|
553 | * 3 = Writable flag
|
---|
554 | */
|
---|
555 | QAbstractItemView *itemView = mTwFolders;
|
---|
556 | QHeaderView *itemHeader = mTwFolders->header();
|
---|
557 | int total = mTwFolders->viewport()->width();
|
---|
558 |
|
---|
559 | int mw0 = qMax (itemView->sizeHintForColumn (0), itemHeader->sectionSizeHint (0));
|
---|
560 | int mw2 = qMax (itemView->sizeHintForColumn (2), itemHeader->sectionSizeHint (2));
|
---|
561 | int mw3 = qMax (itemView->sizeHintForColumn (3), itemHeader->sectionSizeHint (3));
|
---|
562 |
|
---|
563 | int w0 = mw0 < total / 4 ? mw0 : total / 4;
|
---|
564 | int w2 = mw2 < total / 4 ? mw2 : total / 4;
|
---|
565 | int w3 = mw3 < total / 4 ? mw3 : total / 4;
|
---|
566 |
|
---|
567 | /* Giving 1st column all the available space. */
|
---|
568 | mTwFolders->setColumnWidth (0, w0);
|
---|
569 | mTwFolders->setColumnWidth (1, total - w0 - w2 - w3);
|
---|
570 | mTwFolders->setColumnWidth (2, w2);
|
---|
571 | mTwFolders->setColumnWidth (3, w3);
|
---|
572 | }
|
---|
573 |
|
---|
574 | void UIMachineSettingsSF::adjustFields()
|
---|
575 | {
|
---|
576 | QTreeWidgetItem *mainRoot = mTwFolders->invisibleRootItem();
|
---|
577 | for (int i = 0; i < mainRoot->childCount(); ++ i)
|
---|
578 | {
|
---|
579 | QTreeWidgetItem *subRoot = mainRoot->child (i);
|
---|
580 | for (int j = 0; j < subRoot->childCount(); ++ j)
|
---|
581 | {
|
---|
582 | SFTreeViewItem *item = subRoot->child (j) &&
|
---|
583 | subRoot->child (j)->type() == SFTreeViewItem::SFTreeViewItemType ?
|
---|
584 | static_cast <SFTreeViewItem*> (subRoot->child (j)) : 0;
|
---|
585 | if (item)
|
---|
586 | item->adjustText();
|
---|
587 | }
|
---|
588 | }
|
---|
589 | }
|
---|
590 |
|
---|
591 | void UIMachineSettingsSF::showEvent (QShowEvent *aEvent)
|
---|
592 | {
|
---|
593 | UISettingsPageMachine::showEvent (aEvent);
|
---|
594 |
|
---|
595 | /* Connect header-resize signal just before widget is shown after all the items properly loaded and initialized. */
|
---|
596 | connect (mTwFolders->header(), SIGNAL (sectionResized (int, int, int)), this, SLOT (adjustFields()));
|
---|
597 |
|
---|
598 | /* Adjusting size after all pending show events are processed. */
|
---|
599 | QTimer::singleShot (0, this, SLOT (adjustList()));
|
---|
600 | }
|
---|
601 |
|
---|
602 | SFTreeViewItem* UIMachineSettingsSF::root(UISharedFolderType sharedFolderType)
|
---|
603 | {
|
---|
604 | /* Search for the corresponding root item among all the top-level items: */
|
---|
605 | SFTreeViewItem *pRootItem = 0;
|
---|
606 | QTreeWidgetItem *pMainRootItem = mTwFolders->invisibleRootItem();
|
---|
607 | for (int iFolderTypeIndex = 0; iFolderTypeIndex < pMainRootItem->childCount(); ++iFolderTypeIndex)
|
---|
608 | {
|
---|
609 | /* Get iterated item: */
|
---|
610 | QTreeWidgetItem *pIteratedItem = pMainRootItem->child(iFolderTypeIndex);
|
---|
611 | /* If iterated item type is what we are looking for: */
|
---|
612 | if (pIteratedItem->text(1).toInt() == sharedFolderType)
|
---|
613 | {
|
---|
614 | /* Remember the item: */
|
---|
615 | pRootItem = static_cast<SFTreeViewItem*>(pIteratedItem);
|
---|
616 | /* And break further search: */
|
---|
617 | break;
|
---|
618 | }
|
---|
619 | }
|
---|
620 | /* Return root item: */
|
---|
621 | return pRootItem;
|
---|
622 | }
|
---|
623 |
|
---|
624 | SFoldersNameList UIMachineSettingsSF::usedList (bool aIncludeSelected)
|
---|
625 | {
|
---|
626 | /* Make the used names list: */
|
---|
627 | SFoldersNameList list;
|
---|
628 | QTreeWidgetItemIterator it (mTwFolders);
|
---|
629 | while (*it)
|
---|
630 | {
|
---|
631 | if ((*it)->parent() && (aIncludeSelected || !(*it)->isSelected()) &&
|
---|
632 | (*it)->type() == SFTreeViewItem::SFTreeViewItemType)
|
---|
633 | {
|
---|
634 | SFTreeViewItem *item = static_cast <SFTreeViewItem*> (*it);
|
---|
635 | UISharedFolderType type = (UISharedFolderType) item->parent()->text (1).toInt();
|
---|
636 | list << qMakePair (item->getText (0), type);
|
---|
637 | }
|
---|
638 | ++ it;
|
---|
639 | }
|
---|
640 | return list;
|
---|
641 | }
|
---|
642 |
|
---|
643 | bool UIMachineSettingsSF::isSharedFolderTypeSupported(UISharedFolderType sharedFolderType) const
|
---|
644 | {
|
---|
645 | bool fIsSharedFolderTypeSupported = false;
|
---|
646 | switch (sharedFolderType)
|
---|
647 | {
|
---|
648 | case MachineType:
|
---|
649 | fIsSharedFolderTypeSupported = isMachineInValidMode();
|
---|
650 | break;
|
---|
651 | case ConsoleType:
|
---|
652 | fIsSharedFolderTypeSupported = isMachineSaved() || isMachineOnline();
|
---|
653 | break;
|
---|
654 | default:
|
---|
655 | break;
|
---|
656 | }
|
---|
657 | return fIsSharedFolderTypeSupported;
|
---|
658 | }
|
---|
659 |
|
---|
660 | void UIMachineSettingsSF::updateRootItemsVisibility()
|
---|
661 | {
|
---|
662 | /* Update (show/hide) machine (permanent) root item: */
|
---|
663 | setRootItemVisible(MachineType, isSharedFolderTypeSupported(MachineType));
|
---|
664 | /* Update (show/hide) console (temporary) root item: */
|
---|
665 | setRootItemVisible(ConsoleType, isSharedFolderTypeSupported(ConsoleType));
|
---|
666 | }
|
---|
667 |
|
---|
668 | void UIMachineSettingsSF::setRootItemVisible(UISharedFolderType sharedFolderType, bool fVisible)
|
---|
669 | {
|
---|
670 | /* Search for the corresponding root item among all the top-level items: */
|
---|
671 | SFTreeViewItem *pRootItem = root(sharedFolderType);
|
---|
672 | /* If root item, we are looking for, still not found: */
|
---|
673 | if (!pRootItem)
|
---|
674 | {
|
---|
675 | /* Prepare fields for the new root item: */
|
---|
676 | QStringList fields;
|
---|
677 | /* Depending on folder type: */
|
---|
678 | switch (sharedFolderType)
|
---|
679 | {
|
---|
680 | case MachineType:
|
---|
681 | fields << tr(" Machine Folders") << QString::number(MachineType);
|
---|
682 | break;
|
---|
683 | case ConsoleType:
|
---|
684 | fields << tr(" Transient Folders") << QString::number(ConsoleType);
|
---|
685 | break;
|
---|
686 | default:
|
---|
687 | break;
|
---|
688 | }
|
---|
689 | /* And create the new root item: */
|
---|
690 | pRootItem = new SFTreeViewItem(mTwFolders, fields, SFTreeViewItem::EllipsisEnd);
|
---|
691 | }
|
---|
692 | /* Expand/collaps it if necessary: */
|
---|
693 | pRootItem->setExpanded(fVisible);
|
---|
694 | /* And hide/show it if necessary: */
|
---|
695 | pRootItem->setHidden(!fVisible);
|
---|
696 | }
|
---|
697 |
|
---|
698 | void UIMachineSettingsSF::polishPage()
|
---|
699 | {
|
---|
700 | /* Update widgets availability: */
|
---|
701 | mNameSeparator->setEnabled(isMachineInValidMode());
|
---|
702 | mTwFolders->setEnabled(isMachineInValidMode());
|
---|
703 | mTbFolders->setEnabled(isMachineInValidMode());
|
---|
704 |
|
---|
705 | /* Update root items visibility: */
|
---|
706 | updateRootItemsVisibility();
|
---|
707 | }
|
---|
708 |
|
---|
709 | CSharedFolderVector UIMachineSettingsSF::getSharedFolders(UISharedFolderType sharedFoldersType)
|
---|
710 | {
|
---|
711 | CSharedFolderVector sharedFolders;
|
---|
712 | if (isSharedFolderTypeSupported(sharedFoldersType))
|
---|
713 | {
|
---|
714 | switch (sharedFoldersType)
|
---|
715 | {
|
---|
716 | case MachineType:
|
---|
717 | {
|
---|
718 | AssertMsg(!m_machine.isNull(), ("Machine is NOT set!\n"));
|
---|
719 | sharedFolders = m_machine.GetSharedFolders();
|
---|
720 | break;
|
---|
721 | }
|
---|
722 | case ConsoleType:
|
---|
723 | {
|
---|
724 | AssertMsg(!m_console.isNull(), ("Console is NOT set!\n"));
|
---|
725 | sharedFolders = m_console.GetSharedFolders();
|
---|
726 | break;
|
---|
727 | }
|
---|
728 | default:
|
---|
729 | break;
|
---|
730 | }
|
---|
731 | }
|
---|
732 | return sharedFolders;
|
---|
733 | }
|
---|
734 |
|
---|
735 | bool UIMachineSettingsSF::removeSharedFolder(const UICacheSettingsSharedFolder &folderCache)
|
---|
736 | {
|
---|
737 | /* Get shared folder data: */
|
---|
738 | const UIDataSettingsSharedFolder &folderData = folderCache.base();
|
---|
739 | QString strName = folderData.m_strName;
|
---|
740 | QString strPath = folderData.m_strHostPath;
|
---|
741 | UISharedFolderType sharedFoldersType = folderData.m_type;
|
---|
742 |
|
---|
743 | /* Get current shared folders: */
|
---|
744 | CSharedFolderVector sharedFolders = getSharedFolders(sharedFoldersType);
|
---|
745 | /* Check that such shared folder really exists: */
|
---|
746 | CSharedFolder sharedFolder;
|
---|
747 | for (int iSharedFolderIndex = 0; iSharedFolderIndex < sharedFolders.size(); ++iSharedFolderIndex)
|
---|
748 | if (sharedFolders[iSharedFolderIndex].GetName() == strName)
|
---|
749 | sharedFolder = sharedFolders[iSharedFolderIndex];
|
---|
750 | if (!sharedFolder.isNull())
|
---|
751 | {
|
---|
752 | /* Remove existing shared folder: */
|
---|
753 | switch(sharedFoldersType)
|
---|
754 | {
|
---|
755 | case MachineType:
|
---|
756 | {
|
---|
757 | m_machine.RemoveSharedFolder(strName);
|
---|
758 | if (!m_machine.isOk())
|
---|
759 | {
|
---|
760 | /* Mark the page as failed: */
|
---|
761 | setFailed(true);
|
---|
762 | /* Show error message: */
|
---|
763 | vboxProblem().cannotRemoveSharedFolder(m_machine, strName, strPath);
|
---|
764 | /* Finish early: */
|
---|
765 | return false;
|
---|
766 | }
|
---|
767 | break;
|
---|
768 | }
|
---|
769 | case ConsoleType:
|
---|
770 | {
|
---|
771 | m_console.RemoveSharedFolder(strName);
|
---|
772 | if (!m_console.isOk())
|
---|
773 | {
|
---|
774 | /* Mark the page as failed: */
|
---|
775 | setFailed(true);
|
---|
776 | /* Show error message: */
|
---|
777 | vboxProblem().cannotRemoveSharedFolder(m_console, strName, strPath);
|
---|
778 | /* Finish early: */
|
---|
779 | return false;
|
---|
780 | }
|
---|
781 | break;
|
---|
782 | }
|
---|
783 | default:
|
---|
784 | break;
|
---|
785 | }
|
---|
786 | }
|
---|
787 | return true;
|
---|
788 | }
|
---|
789 |
|
---|
790 | bool UIMachineSettingsSF::createSharedFolder(const UICacheSettingsSharedFolder &folderCache)
|
---|
791 | {
|
---|
792 | /* Get shared folder data: */
|
---|
793 | const UIDataSettingsSharedFolder &folderData = folderCache.data();
|
---|
794 | QString strName = folderData.m_strName;
|
---|
795 | QString strPath = folderData.m_strHostPath;
|
---|
796 | bool fIsWritable = folderData.m_fWritable;
|
---|
797 | bool fIsAutoMount = folderData.m_fAutoMount;
|
---|
798 | UISharedFolderType sharedFoldersType = folderData.m_type;
|
---|
799 |
|
---|
800 | /* Get current shared folders: */
|
---|
801 | CSharedFolderVector sharedFolders = getSharedFolders(sharedFoldersType);
|
---|
802 | /* Check if such shared folder do not exists: */
|
---|
803 | CSharedFolder sharedFolder;
|
---|
804 | for (int iSharedFolderIndex = 0; iSharedFolderIndex < sharedFolders.size(); ++iSharedFolderIndex)
|
---|
805 | if (sharedFolders[iSharedFolderIndex].GetName() == strName)
|
---|
806 | sharedFolder = sharedFolders[iSharedFolderIndex];
|
---|
807 | if (sharedFolder.isNull())
|
---|
808 | {
|
---|
809 | /* Create new shared folder: */
|
---|
810 | switch(sharedFoldersType)
|
---|
811 | {
|
---|
812 | case MachineType:
|
---|
813 | {
|
---|
814 | m_machine.CreateSharedFolder(strName, strPath, fIsWritable, fIsAutoMount);
|
---|
815 | if (!m_machine.isOk())
|
---|
816 | {
|
---|
817 | /* Mark the page as failed: */
|
---|
818 | setFailed(true);
|
---|
819 | /* Show error message: */
|
---|
820 | vboxProblem().cannotCreateSharedFolder(m_machine, strName, strPath);
|
---|
821 | /* Finish early: */
|
---|
822 | return false;
|
---|
823 | }
|
---|
824 | break;
|
---|
825 | }
|
---|
826 | case ConsoleType:
|
---|
827 | {
|
---|
828 | /* Create new shared folder: */
|
---|
829 | m_console.CreateSharedFolder(strName, strPath, fIsWritable, fIsAutoMount);
|
---|
830 | if (!m_console.isOk())
|
---|
831 | {
|
---|
832 | /* Mark the page as failed: */
|
---|
833 | setFailed(true);
|
---|
834 | /* Show error message: */
|
---|
835 | vboxProblem().cannotCreateSharedFolder(m_console, strName, strPath);
|
---|
836 | /* Finish early: */
|
---|
837 | return false;
|
---|
838 | }
|
---|
839 | break;
|
---|
840 | }
|
---|
841 | default:
|
---|
842 | break;
|
---|
843 | }
|
---|
844 | }
|
---|
845 | return true;
|
---|
846 | }
|
---|