VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/guestctrl/UIFileManager.cpp@ 100347

Last change on this file since 100347 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 30.2 KB
Line 
1/* $Id: UIFileManager.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIFileManager class implementation.
4 */
5
6/*
7 * Copyright (C) 2016-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* Qt includes: */
29#include <QHBoxLayout>
30#include <QPushButton>
31#include <QSplitter>
32
33/* GUI includes: */
34#include "QITabWidget.h"
35#include "QITreeWidget.h"
36#include "QIToolBar.h"
37#include "UIActionPool.h"
38#include "UICommon.h"
39#include "UIConverter.h"
40#include "UIErrorString.h"
41#include "UIExtraDataManager.h"
42#include "UIIconPool.h"
43#include "UIFileManager.h"
44#include "UIFileManagerOptionsPanel.h"
45#include "UIFileManagerLogPanel.h"
46#include "UIFileManagerOperationsPanel.h"
47#include "UIFileManagerGuestTable.h"
48#include "UIFileManagerHostTable.h"
49#include "UIGuestControlInterface.h"
50#include "UIVirtualMachineItem.h"
51
52/* COM includes: */
53#include "CConsole.h"
54#include "CFsObjInfo.h"
55#include "CGuestDirectory.h"
56#include "CGuestFsObjInfo.h"
57#include "CGuestSession.h"
58
59
60/*********************************************************************************************************************************
61* UIFileOperationsList definition. *
62*********************************************************************************************************************************/
63
64class UIFileOperationsList : public QITreeWidget
65{
66 Q_OBJECT;
67public:
68
69 UIFileOperationsList(QWidget *pParent = 0);
70};
71
72
73/*********************************************************************************************************************************
74* UIFileManagerOptions implementation. *
75*********************************************************************************************************************************/
76
77UIFileManagerOptions *UIFileManagerOptions::m_pInstance = 0;
78
79UIFileManagerOptions* UIFileManagerOptions::instance()
80{
81 if (!m_pInstance)
82 m_pInstance = new UIFileManagerOptions;
83 return m_pInstance;
84}
85
86void UIFileManagerOptions::create()
87{
88 if (m_pInstance)
89 return;
90 m_pInstance = new UIFileManagerOptions;
91}
92
93void UIFileManagerOptions::destroy()
94{
95 delete m_pInstance;
96 m_pInstance = 0;
97}
98
99 UIFileManagerOptions::~UIFileManagerOptions()
100{
101}
102
103UIFileManagerOptions::UIFileManagerOptions()
104 : fListDirectoriesOnTop(true)
105 , fAskDeleteConfirmation(false)
106 , fShowHumanReadableSizes(true)
107 , fShowHiddenObjects(true)
108{
109}
110
111/*********************************************************************************************************************************
112* UIFileOperationsList implementation. *
113*********************************************************************************************************************************/
114
115UIFileOperationsList::UIFileOperationsList(QWidget *pParent)
116 :QITreeWidget(pParent)
117{}
118
119
120/*********************************************************************************************************************************
121* UIFileManager implementation. *
122*********************************************************************************************************************************/
123
124UIFileManager::UIFileManager(EmbedTo enmEmbedding, UIActionPool *pActionPool,
125 const CMachine &comMachine, QWidget *pParent, bool fShowToolbar)
126 : QIWithRetranslateUI<QWidget>(pParent)
127 , m_pMainLayout(0)
128 , m_pVerticalSplitter(0)
129 , m_pFileTableSplitter(0)
130 , m_pToolBar(0)
131 , m_pVerticalToolBar(0)
132 , m_pHostFileTable(0)
133 , m_pGuestTablesContainer(0)
134 , m_enmEmbedding(enmEmbedding)
135 , m_pActionPool(pActionPool)
136 , m_fShowToolbar(fShowToolbar)
137 , m_pOptionsPanel(0)
138 , m_pLogPanel(0)
139 , m_pOperationsPanel(0)
140 , m_fCommitDataSignalReceived(false)
141{
142 loadOptions();
143 prepareObjects();
144 prepareConnections();
145 retranslateUi();
146 restorePanelVisibility();
147 UIFileManagerOptions::create();
148 uiCommon().setHelpKeyword(this, "guestadd-gc-file-manager");
149
150 if (!comMachine.isNull())
151 setMachines( QVector<QUuid>() << comMachine.GetId());
152}
153
154UIFileManager::~UIFileManager()
155{
156 UIFileManagerOptions::destroy();
157 if (m_pGuestTablesContainer)
158 {
159 for (int i = 0; i < m_pGuestTablesContainer->count(); ++i)
160 {
161 UIFileManagerGuestTable *pTable = qobject_cast<UIFileManagerGuestTable*>(m_pGuestTablesContainer->widget(i));
162 if (pTable)
163 pTable->disconnect();
164 }
165 }
166}
167
168QMenu *UIFileManager::menu() const
169{
170 if (!m_pActionPool)
171 return 0;
172 return m_pActionPool->action(UIActionIndex_M_FileManager)->menu();
173}
174
175void UIFileManager::retranslateUi()
176{
177}
178
179void UIFileManager::prepareObjects()
180{
181 /* m_pMainLayout is the outer most layout containing the main toolbar and splitter widget: */
182 m_pMainLayout = new QVBoxLayout(this);
183 if (!m_pMainLayout)
184 return;
185
186 /* Configure layout: */
187 m_pMainLayout->setContentsMargins(0, 0, 0, 0);
188#ifdef VBOX_WS_MAC
189 m_pMainLayout->setSpacing(10);
190#else
191 m_pMainLayout->setSpacing(qApp->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing) / 2);
192#endif
193
194 if (m_fShowToolbar)
195 prepareToolBar();
196
197 QWidget *pTopWidget = new QWidget;
198 QVBoxLayout *pTopLayout = new QVBoxLayout;
199 pTopLayout->setSpacing(0);
200 pTopLayout->setContentsMargins(0, 0, 0, 0);
201 pTopWidget->setLayout(pTopLayout);
202
203 m_pFileTableSplitter = new QSplitter;
204
205 if (m_pFileTableSplitter)
206 {
207 m_pFileTableSplitter->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
208 m_pFileTableSplitter->setContentsMargins(0, 0, 0, 0);
209
210 /* This widget hosts host file table and vertical toolbar. */
211 QWidget *pHostTableAndVerticalToolbarWidget = new QWidget;
212 QHBoxLayout *pHostTableAndVerticalToolbarLayout = new QHBoxLayout(pHostTableAndVerticalToolbarWidget);
213 pHostTableAndVerticalToolbarLayout->setSpacing(0);
214 pHostTableAndVerticalToolbarLayout->setContentsMargins(0, 0, 0, 0);
215
216 m_pHostFileTable = new UIFileManagerHostTable(m_pActionPool);
217 if (m_pHostFileTable)
218 pHostTableAndVerticalToolbarLayout->addWidget(m_pHostFileTable);
219
220 m_pFileTableSplitter->addWidget(pHostTableAndVerticalToolbarWidget);
221 prepareVerticalToolBar(pHostTableAndVerticalToolbarLayout);
222
223 m_pGuestTablesContainer = new QITabWidget;
224 if (m_pGuestTablesContainer)
225 {
226 m_pGuestTablesContainer->setTabPosition(QTabWidget::East);
227 m_pGuestTablesContainer->setTabBarAutoHide(true);
228 m_pFileTableSplitter->addWidget(m_pGuestTablesContainer);
229 }
230 m_pFileTableSplitter->setStretchFactor(0, 1);
231 m_pFileTableSplitter->setStretchFactor(1, 1);
232 }
233
234 pTopLayout->addWidget(m_pFileTableSplitter);
235 for (int i = 0; i < m_pFileTableSplitter->count(); ++i)
236 m_pFileTableSplitter->setCollapsible(i, false);
237
238 /* Create options and session panels and insert them into pTopLayout: */
239 prepareOptionsAndSessionPanels(pTopLayout);
240
241 /** Vertical splitter has 3 widgets. Log panel as bottom most one, operations panel on top of it,
242 * and pTopWidget which contains everthing else: */
243 m_pVerticalSplitter = new QSplitter;
244 if (m_pVerticalSplitter)
245 {
246 m_pMainLayout->addWidget(m_pVerticalSplitter);
247 m_pVerticalSplitter->setOrientation(Qt::Vertical);
248 m_pVerticalSplitter->setHandleWidth(4);
249
250 m_pVerticalSplitter->addWidget(pTopWidget);
251 /* Prepare operations and log panels and insert them into splitter: */
252 prepareOperationsAndLogPanels(m_pVerticalSplitter);
253
254 for (int i = 0; i < m_pVerticalSplitter->count(); ++i)
255 m_pVerticalSplitter->setCollapsible(i, false);
256 m_pVerticalSplitter->setStretchFactor(0, 3);
257 m_pVerticalSplitter->setStretchFactor(1, 1);
258 m_pVerticalSplitter->setStretchFactor(2, 1);
259 }
260}
261
262void UIFileManager::prepareVerticalToolBar(QHBoxLayout *layout)
263{
264 m_pVerticalToolBar = new QIToolBar;
265 if (!m_pVerticalToolBar && !m_pActionPool)
266 return;
267
268 m_pVerticalToolBar->setOrientation(Qt::Vertical);
269
270 /* Add to dummy QWidget to toolbar to center the action icons vertically: */
271 QWidget *topSpacerWidget = new QWidget(this);
272 topSpacerWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
273 topSpacerWidget->setVisible(true);
274 QWidget *bottomSpacerWidget = new QWidget(this);
275 bottomSpacerWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
276 bottomSpacerWidget->setVisible(true);
277
278 m_pVerticalToolBar->addWidget(topSpacerWidget);
279 if (m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToHost))
280 {
281 m_pVerticalToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToHost));
282 m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToHost)->setEnabled(false);
283 }
284 if (m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToGuest))
285 {
286 m_pVerticalToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToGuest));
287 m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToGuest)->setEnabled(false);
288 }
289
290 m_pVerticalToolBar->addWidget(bottomSpacerWidget);
291
292 layout ->addWidget(m_pVerticalToolBar);
293}
294
295void UIFileManager::prepareConnections()
296{
297 if (m_pActionPool)
298 {
299 if (m_pActionPool->action(UIActionIndex_M_FileManager_T_Options))
300 connect(m_pActionPool->action(UIActionIndex_M_FileManager_T_Options), &QAction::toggled,
301 this, &UIFileManager::sltPanelActionToggled);
302 if (m_pActionPool->action(UIActionIndex_M_FileManager_T_Log))
303 connect(m_pActionPool->action(UIActionIndex_M_FileManager_T_Log), &QAction::toggled,
304 this, &UIFileManager::sltPanelActionToggled);
305 if (m_pActionPool->action(UIActionIndex_M_FileManager_T_Operations))
306 connect(m_pActionPool->action(UIActionIndex_M_FileManager_T_Operations), &QAction::toggled,
307 this, &UIFileManager::sltPanelActionToggled);
308 if (m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToHost))
309 connect(m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToHost), &QAction::triggered,
310 this, &UIFileManager::sltCopyGuestToHost);
311 if (m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToGuest))
312 connect(m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToGuest), &QAction::triggered,
313 this, &UIFileManager::sltCopyHostToGuest);
314 }
315 if (m_pOptionsPanel)
316 {
317 connect(m_pOptionsPanel, &UIFileManagerOptionsPanel::sigHidePanel,
318 this, &UIFileManager::sltHandleHidePanel);
319 connect(m_pOptionsPanel, &UIFileManagerOptionsPanel::sigShowPanel,
320 this, &UIFileManager::sltHandleShowPanel);
321 connect(m_pOptionsPanel, &UIFileManagerOptionsPanel::sigOptionsChanged,
322 this, &UIFileManager::sltHandleOptionsUpdated);
323 }
324 if (m_pLogPanel)
325 {
326 connect(m_pLogPanel, &UIFileManagerLogPanel::sigHidePanel,
327 this, &UIFileManager::sltHandleHidePanel);
328 connect(m_pLogPanel, &UIFileManagerLogPanel::sigShowPanel,
329 this, &UIFileManager::sltHandleShowPanel);
330 }
331
332 if (m_pOperationsPanel)
333 {
334 connect(m_pOperationsPanel, &UIFileManagerOperationsPanel::sigHidePanel,
335 this, &UIFileManager::sltHandleHidePanel);
336 connect(m_pOperationsPanel, &UIFileManagerOperationsPanel::sigShowPanel,
337 this, &UIFileManager::sltHandleShowPanel);
338 }
339 if (m_pHostFileTable)
340 {
341 connect(m_pHostFileTable, &UIFileManagerHostTable::sigLogOutput,
342 this, &UIFileManager::sltReceieveLogOutput);
343 connect(m_pHostFileTable, &UIFileManagerHostTable::sigDeleteConfirmationOptionChanged,
344 this, &UIFileManager::sltHandleOptionsUpdated);
345 connect(m_pHostFileTable, &UIFileManagerGuestTable::sigSelectionChanged,
346 this, &UIFileManager::sltFileTableSelectionChanged);
347 }
348 if (m_pGuestTablesContainer)
349 connect(m_pGuestTablesContainer, &QITabWidget::currentChanged, this,
350 &UIFileManager::sltCurrentTabChanged);
351
352 connect(&uiCommon(), &UICommon::sigAskToCommitData,
353 this, &UIFileManager::sltCommitDataSignalReceived);
354}
355
356void UIFileManager::prepareToolBar()
357{
358 /* Create toolbar: */
359 m_pToolBar = new QIToolBar(parentWidget());
360 if (m_pToolBar)
361 {
362 /* Configure toolbar: */
363 const int iIconMetric = (int)(QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize));
364 m_pToolBar->setIconSize(QSize(iIconMetric, iIconMetric));
365 m_pToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
366
367 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_T_Options));
368 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_T_Operations));
369 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_T_Log));
370
371#ifdef VBOX_WS_MAC
372 /* Check whether we are embedded into a stack: */
373 if (m_enmEmbedding == EmbedTo_Stack)
374 {
375 /* Add into layout: */
376 m_pMainLayout->addWidget(m_pToolBar);
377 }
378#else
379 /* Add into layout: */
380 m_pMainLayout->addWidget(m_pToolBar);
381#endif
382 }
383}
384
385void UIFileManager::sltReceieveLogOutput(QString strOutput, const QString &strMachineName, FileManagerLogType eLogType)
386{
387 appendLog(strOutput, strMachineName, eLogType);
388}
389
390void UIFileManager::sltCopyGuestToHost()
391{
392 copyToHost();
393}
394
395void UIFileManager::sltCopyHostToGuest()
396{
397 copyToGuest();
398}
399
400void UIFileManager::sltPanelActionToggled(bool fChecked)
401{
402 QAction *pSenderAction = qobject_cast<QAction*>(sender());
403 if (!pSenderAction)
404 return;
405 UIDialogPanel* pPanel = 0;
406 /* Look for the sender() within the m_panelActionMap's values: */
407 for (QMap<UIDialogPanel*, QAction*>::const_iterator iterator = m_panelActionMap.begin();
408 iterator != m_panelActionMap.end(); ++iterator)
409 {
410 if (iterator.value() == pSenderAction)
411 pPanel = iterator.key();
412 }
413 if (!pPanel)
414 return;
415 if (fChecked)
416 showPanel(pPanel);
417 else
418 hidePanel(pPanel);
419}
420
421void UIFileManager::sltReceieveNewFileOperation(const CProgress &comProgress, const QString &strTableName)
422{
423 if (m_pOperationsPanel)
424 m_pOperationsPanel->addNewProgress(comProgress, strTableName);
425}
426
427void UIFileManager::sltFileOperationComplete(QUuid progressId)
428{
429 Q_UNUSED(progressId);
430 if (m_pHostFileTable)
431 m_pHostFileTable->refresh();
432 /// @todo we need to refresh only the table from which the completed file operation has originated
433 for (int i = 0; i < m_pGuestTablesContainer->count(); ++i)
434 {
435 UIFileManagerGuestTable *pTable = qobject_cast<UIFileManagerGuestTable*>(m_pGuestTablesContainer->widget(i));
436 if (pTable)
437 pTable->refresh();
438 }
439}
440
441void UIFileManager::sltHandleOptionsUpdated()
442{
443 if (m_pOptionsPanel)
444 m_pOptionsPanel->update();
445
446 for (int i = 0; i < m_pGuestTablesContainer->count(); ++i)
447 {
448 UIFileManagerGuestTable *pTable = qobject_cast<UIFileManagerGuestTable*>(m_pGuestTablesContainer->widget(i));
449 if (pTable)
450 pTable->optionsUpdated();
451 }
452 if (m_pHostFileTable)
453 m_pHostFileTable->optionsUpdated();
454 saveOptions();
455}
456
457void UIFileManager::sltHandleHidePanel(UIDialogPanel *pPanel)
458{
459 hidePanel(pPanel);
460}
461
462void UIFileManager::sltHandleShowPanel(UIDialogPanel *pPanel)
463{
464 showPanel(pPanel);
465}
466
467void UIFileManager::sltCommitDataSignalReceived()
468{
469 m_fCommitDataSignalReceived = true;
470}
471
472void UIFileManager::sltFileTableSelectionChanged(bool fHasSelection)
473{
474 /* If we dont have a guest session running that actions should stay disabled: */
475 if (!currentGuestTable() || !currentGuestTable()->isGuestSessionRunning())
476 {
477 m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToGuest)->setEnabled(false);
478 m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToHost)->setEnabled(false);
479 return;
480 }
481
482 /* Enable/disable vertical toolbar actions: */
483 UIFileManagerGuestTable *pGuestTable = qobject_cast<UIFileManagerGuestTable*>(sender());
484
485 /* If the signal is coming from a guest table which is not the current one just dont do anything: */
486 if (pGuestTable && pGuestTable != currentGuestTable())
487 return;
488
489 if (pGuestTable)
490 {
491 if (m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToHost))
492 m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToHost)->setEnabled(fHasSelection);
493 return;
494 }
495
496 if (sender() == m_pHostFileTable && m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToGuest))
497 m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToGuest)->setEnabled(fHasSelection);
498}
499
500void UIFileManager::sltCurrentTabChanged(int iIndex)
501{
502 Q_UNUSED(iIndex);
503 setVerticalToolBarActionsEnabled();
504
505 /* Mark the current guest table: */
506 UIFileManagerGuestTable *pCurrentGuestTable = currentGuestTable();
507 if (!pCurrentGuestTable)
508 return;
509 for (int i = 0; i < m_pGuestTablesContainer->count(); ++i)
510 {
511 UIFileManagerGuestTable *pTable = qobject_cast<UIFileManagerGuestTable*>(m_pGuestTablesContainer->widget(i));
512 if (!pTable)
513 continue;
514 pTable->setIsCurrent(pTable == pCurrentGuestTable);
515 }
516 /* Disable host file table if guest session is not running: */
517 if (m_pHostFileTable)
518 m_pHostFileTable->setEnabled(pCurrentGuestTable->isGuestSessionRunning());
519 /* Disable/enable file table submenus of the menu: */
520 UIMenu *pGuestSubmenu = m_pActionPool->action(UIActionIndex_M_FileManager_M_GuestSubmenu)->menu();
521 if (pGuestSubmenu)
522 pGuestSubmenu->setEnabled(pCurrentGuestTable->isGuestSessionRunning());
523 UIMenu *pHostSubmenu = m_pActionPool->action(UIActionIndex_M_FileManager_M_HostSubmenu)->menu();
524 if (pHostSubmenu)
525 pHostSubmenu->setEnabled(pCurrentGuestTable->isGuestSessionRunning());
526}
527
528void UIFileManager::sltGuestFileTableStateChanged(bool fIsRunning)
529{
530 if (m_pHostFileTable)
531 m_pHostFileTable->setEnabled(fIsRunning);
532}
533
534void UIFileManager::setVerticalToolBarActionsEnabled()
535{
536 if (!m_pGuestTablesContainer)
537 return;
538 UIFileManagerGuestTable *pTable = currentGuestTable();
539 if (!pTable)
540 return;
541
542 bool fRunning = pTable->isGuestSessionRunning();
543 if (m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToHost))
544 m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToHost)->setEnabled(fRunning && pTable->hasSelection());
545
546 if (m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToGuest))
547 {
548 bool fHostHasSelection = m_pHostFileTable ? m_pHostFileTable->hasSelection() : false;
549 m_pActionPool->action(UIActionIndex_M_FileManager_S_CopyToGuest)->setEnabled(fRunning && fHostHasSelection);
550 }
551}
552
553void UIFileManager::copyToHost()
554{
555 if (m_pGuestTablesContainer && m_pHostFileTable)
556 {
557 UIFileManagerGuestTable *pGuestFileTable = currentGuestTable();
558 if (pGuestFileTable)
559 pGuestFileTable->copyGuestToHost(m_pHostFileTable->currentDirectoryPath());
560 }
561}
562
563void UIFileManager::copyToGuest()
564{
565 if (m_pGuestTablesContainer && m_pHostFileTable)
566 {
567 UIFileManagerGuestTable *pGuestFileTable = currentGuestTable();
568 if (pGuestFileTable)
569 pGuestFileTable->copyHostToGuest(m_pHostFileTable->selectedItemPathList());
570 }
571}
572
573void UIFileManager::prepareOptionsAndSessionPanels(QVBoxLayout *pLayout)
574{
575 if (!pLayout)
576 return;
577
578 m_pOptionsPanel = new UIFileManagerOptionsPanel(0 /*parent */, UIFileManagerOptions::instance());
579 if (m_pOptionsPanel)
580 {
581 m_pOptionsPanel->hide();
582 m_panelActionMap.insert(m_pOptionsPanel, m_pActionPool->action(UIActionIndex_M_FileManager_T_Options));
583 pLayout->addWidget(m_pOptionsPanel);
584 }
585}
586
587void UIFileManager::prepareOperationsAndLogPanels(QSplitter *pSplitter)
588{
589 if (!pSplitter)
590 return;
591 m_pOperationsPanel = new UIFileManagerOperationsPanel;
592 if (m_pOperationsPanel)
593 {
594 m_pOperationsPanel->hide();
595 connect(m_pOperationsPanel, &UIFileManagerOperationsPanel::sigFileOperationComplete,
596 this, &UIFileManager::sltFileOperationComplete);
597 connect(m_pOperationsPanel, &UIFileManagerOperationsPanel::sigFileOperationFail,
598 this, &UIFileManager::sltReceieveLogOutput);
599 m_panelActionMap.insert(m_pOperationsPanel, m_pActionPool->action(UIActionIndex_M_FileManager_T_Operations));
600 }
601 pSplitter->addWidget(m_pOperationsPanel);
602 m_pLogPanel = new UIFileManagerLogPanel;
603 if (m_pLogPanel)
604 {
605 m_pLogPanel->hide();
606 m_panelActionMap.insert(m_pLogPanel, m_pActionPool->action(UIActionIndex_M_FileManager_T_Log));
607 }
608 pSplitter->addWidget(m_pLogPanel);
609}
610
611
612template<typename T>
613QStringList UIFileManager::getFsObjInfoStringList(const T &fsObjectInfo) const
614{
615 QStringList objectInfo;
616 if (!fsObjectInfo.isOk())
617 return objectInfo;
618 objectInfo << fsObjectInfo.GetName();
619 return objectInfo;
620}
621
622void UIFileManager::saveOptions()
623{
624 if (m_fCommitDataSignalReceived)
625 return;
626 /* Save the options: */
627 UIFileManagerOptions *pOptions = UIFileManagerOptions::instance();
628 if (pOptions)
629 {
630 gEDataManager->setFileManagerOptions(pOptions->fListDirectoriesOnTop,
631 pOptions->fAskDeleteConfirmation,
632 pOptions->fShowHumanReadableSizes,
633 pOptions->fShowHiddenObjects);
634 }
635}
636
637void UIFileManager::restorePanelVisibility()
638{
639 /** Make sure the actions are set to not-checked. this prevents an unlikely
640 * bug when the extrakey for the visible panels are manually modified: */
641 foreach(QAction* pAction, m_panelActionMap.values())
642 {
643 pAction->blockSignals(true);
644 pAction->setChecked(false);
645 pAction->blockSignals(false);
646 }
647
648 /* Load the visible panel list and show them: */
649 QStringList strNameList = gEDataManager->fileManagerVisiblePanels();
650 foreach(const QString strName, strNameList)
651 {
652 foreach(UIDialogPanel* pPanel, m_panelActionMap.keys())
653 {
654 if (strName == pPanel->panelName())
655 {
656 showPanel(pPanel);
657 break;
658 }
659 }
660 }
661}
662
663void UIFileManager::loadOptions()
664{
665 /* Load options: */
666 UIFileManagerOptions *pOptions = UIFileManagerOptions::instance();
667 if (pOptions)
668 {
669 pOptions->fListDirectoriesOnTop = gEDataManager->fileManagerListDirectoriesFirst();
670 pOptions->fAskDeleteConfirmation = gEDataManager->fileManagerShowDeleteConfirmation();
671 pOptions->fShowHumanReadableSizes = gEDataManager->fileManagerShowHumanReadableSizes();
672 pOptions->fShowHiddenObjects = gEDataManager->fileManagerShowHiddenObjects();
673 }
674}
675
676void UIFileManager::hidePanel(UIDialogPanel* panel)
677{
678 if (!m_pActionPool)
679 return;
680 if (panel && panel->isVisible())
681 panel->setVisible(false);
682 QMap<UIDialogPanel*, QAction*>::iterator iterator = m_panelActionMap.find(panel);
683 if (iterator != m_panelActionMap.end())
684 {
685 if (iterator.value() && iterator.value()->isChecked())
686 iterator.value()->setChecked(false);
687 }
688 m_visiblePanelsList.removeAll(panel);
689 manageEscapeShortCut();
690 savePanelVisibility();
691}
692
693void UIFileManager::showPanel(UIDialogPanel* panel)
694{
695 if (panel && panel->isHidden())
696 panel->setVisible(true);
697 QMap<UIDialogPanel*, QAction*>::iterator iterator = m_panelActionMap.find(panel);
698 if (iterator != m_panelActionMap.end())
699 {
700 if (!iterator.value()->isChecked())
701 iterator.value()->setChecked(true);
702 }
703 if (!m_visiblePanelsList.contains(panel))
704 m_visiblePanelsList.push_back(panel);
705 manageEscapeShortCut();
706 savePanelVisibility();
707}
708
709void UIFileManager::manageEscapeShortCut()
710{
711 /* if there is no visible panels give the escape shortcut to parent dialog: */
712 if (m_visiblePanelsList.isEmpty())
713 {
714 emit sigSetCloseButtonShortCut(QKeySequence(Qt::Key_Escape));
715 return;
716 }
717 /* Take the escape shortcut from the dialog: */
718 emit sigSetCloseButtonShortCut(QKeySequence());
719 /* Just loop thru the visible panel list and set the esc key to the
720 panel which made visible latest */
721 for (int i = 0; i < m_visiblePanelsList.size() - 1; ++i)
722 m_visiblePanelsList[i]->setCloseButtonShortCut(QKeySequence());
723
724 m_visiblePanelsList.back()->setCloseButtonShortCut(QKeySequence(Qt::Key_Escape));
725}
726
727void UIFileManager::appendLog(const QString &strLog, const QString &strMachineName, FileManagerLogType eLogType)
728{
729 if (!m_pLogPanel)
730 return;
731 m_pLogPanel->appendLog(strLog, strMachineName, eLogType);
732}
733
734void UIFileManager::savePanelVisibility()
735{
736 if (m_fCommitDataSignalReceived)
737 return;
738 /* Save a list of currently visible panels: */
739 QStringList strNameList;
740 foreach(UIDialogPanel* pPanel, m_visiblePanelsList)
741 strNameList.append(pPanel->panelName());
742 gEDataManager->setFileManagerVisiblePanels(strNameList);
743}
744
745void UIFileManager::setSelectedVMListItems(const QList<UIVirtualMachineItem*> &items)
746{
747 AssertReturnVoid(m_pGuestTablesContainer);
748 QVector<QUuid> selectedMachines;
749
750 foreach (const UIVirtualMachineItem *item, items)
751 {
752 if (!item)
753 continue;
754 selectedMachines << item->id();
755 }
756 QUuid lastSelection = selectedMachines.isEmpty() ? QUuid() : selectedMachines.last();
757 /** Iterate through the current tabs and add any machine id for which we have a running guest session to the
758 * list of machine ids we want to have a tab for: */
759 for (int i = 0; i < m_pGuestTablesContainer->count(); ++i)
760 {
761 UIFileManagerGuestTable *pTable = qobject_cast<UIFileManagerGuestTable*>(m_pGuestTablesContainer->widget(i));
762 if (!pTable || !pTable->isGuestSessionRunning())
763 continue;
764 if (!selectedMachines.contains(pTable->machineId()))
765 selectedMachines << pTable->machineId();
766 }
767
768 setMachines(selectedMachines, lastSelection);
769}
770
771void UIFileManager::setMachines(const QVector<QUuid> &machineIds, const QUuid &lastSelectedMachineId /* = QUuid() */)
772{
773 AssertReturnVoid(m_pGuestTablesContainer);
774
775 /* List of machines that are newly added to selected machine list: */
776 QVector<QUuid> newSelections;
777 QVector<QUuid> unselectedMachines(m_machineIds);
778
779 foreach (const QUuid &id, machineIds)
780 {
781 unselectedMachines.removeAll(id);
782 if (!m_machineIds.contains(id))
783 newSelections << id;
784 }
785 m_machineIds = machineIds;
786
787 addTabs(newSelections);
788 removeTabs(unselectedMachines);
789 if (!lastSelectedMachineId.isNull())
790 {
791 int iIndexToSelect = -1;
792 for (int i = 0; i < m_pGuestTablesContainer->count() && iIndexToSelect == -1; ++i)
793 {
794 UIFileManagerGuestTable *pTable = qobject_cast<UIFileManagerGuestTable*>(m_pGuestTablesContainer->widget(i));
795 if (!pTable)
796 continue;
797 if (lastSelectedMachineId == pTable->machineId())
798 iIndexToSelect = i;
799 }
800 if (iIndexToSelect != -1)
801 m_pGuestTablesContainer->setCurrentIndex(iIndexToSelect);
802 }
803}
804
805void UIFileManager::removeTabs(const QVector<QUuid> &machineIdsToRemove)
806{
807 if (!m_pGuestTablesContainer)
808 return;
809 QVector<UIFileManagerGuestTable*> removeList;
810
811 for (int i = m_pGuestTablesContainer->count() - 1; i >= 0; --i)
812 {
813 UIFileManagerGuestTable *pTable = qobject_cast<UIFileManagerGuestTable*>(m_pGuestTablesContainer->widget(i));
814 if (!pTable)
815 continue;
816 if (machineIdsToRemove.contains(pTable->machineId()))
817 {
818 removeList << pTable;
819 m_pGuestTablesContainer->removeTab(i);
820 }
821 }
822 qDeleteAll(removeList.begin(), removeList.end());
823}
824
825void UIFileManager::addTabs(const QVector<QUuid> &machineIdsToAdd)
826{
827 if (!m_pGuestTablesContainer)
828 return;
829
830 foreach (const QUuid &id, machineIdsToAdd)
831 {
832 CMachine comMachine = uiCommon().virtualBox().FindMachine(id.toString());
833 if (comMachine.isNull())
834 continue;
835 UIFileManagerGuestTable *pGuestFileTable = new UIFileManagerGuestTable(m_pActionPool, comMachine, m_pGuestTablesContainer);
836 m_pGuestTablesContainer->addTab(pGuestFileTable, comMachine.GetName());
837 if (pGuestFileTable)
838 {
839 connect(pGuestFileTable, &UIFileManagerGuestTable::sigLogOutput,
840 this, &UIFileManager::sltReceieveLogOutput);
841 connect(pGuestFileTable, &UIFileManagerGuestTable::sigSelectionChanged,
842 this, &UIFileManager::sltFileTableSelectionChanged);
843 connect(pGuestFileTable, &UIFileManagerGuestTable::sigNewFileOperation,
844 this, &UIFileManager::sltReceieveNewFileOperation);
845 connect(pGuestFileTable, &UIFileManagerGuestTable::sigDeleteConfirmationOptionChanged,
846 this, &UIFileManager::sltHandleOptionsUpdated);
847 connect(pGuestFileTable, &UIFileManagerGuestTable::sigStateChanged,
848 this, &UIFileManager::sltGuestFileTableStateChanged);
849 }
850 }
851}
852
853UIFileManagerGuestTable *UIFileManager::currentGuestTable()
854{
855 if (!m_pGuestTablesContainer)
856 return 0;
857 return qobject_cast<UIFileManagerGuestTable*>(m_pGuestTablesContainer->currentWidget());
858}
859#include "UIFileManager.moc"
Note: See TracBrowser for help on using the repository browser.

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