VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/guestctrl/UIFileManagerGuestTable.cpp@ 103982

Last change on this file since 103982 was 103771, checked in by vboxsync, 9 months ago

FE/Qt: UICommon: Switching dependency from UICommon to UIGlobalSession whenever is possible.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 61.4 KB
Line 
1/* $Id: UIFileManagerGuestTable.cpp 103771 2024-03-11 15:16:04Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIFileManagerGuestTable 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 <QDateTime>
30#include <QFileInfo>
31#include <QHBoxLayout>
32#include <QPushButton>
33#include <QUuid>
34
35/* GUI includes: */
36#include "QILabel.h"
37#include "UIActionPool.h"
38#include "UIConverter.h"
39#include "UICommon.h"
40#include "UIErrorString.h"
41#include "UIFileSystemModel.h"
42#include "UIFileManager.h"
43#include "UIFileManagerHostTable.h"
44#include "UIFileManagerGuestTable.h"
45#include "UIFileTableNavigationWidget.h"
46#include "UIGlobalSession.h"
47#include "UIIconPool.h"
48#include "UIMessageCenter.h"
49#include "UIPathOperations.h"
50#include "UIUserNamePasswordEditor.h"
51#include "UIVirtualBoxEventHandler.h"
52#include "QILineEdit.h"
53#include "QIToolBar.h"
54
55/* COM includes: */
56#include "CConsole.h"
57#include "CFsObjInfo.h"
58#include "CGuestFsObjInfo.h"
59#include "CGuestDirectory.h"
60#include "CProgress.h"
61#include "CGuestSessionStateChangedEvent.h"
62
63/* Other VBox includes: */
64#include <iprt/err.h>
65
66/*********************************************************************************************************************************
67* UIGuestSessionWidget definition. *
68*********************************************************************************************************************************/
69/** A QWidget extension containing text entry fields for password and username and buttons to
70 * start/stop a guest session. */
71class UIGuestSessionWidget : public QIWithRetranslateUI<QWidget>
72{
73 Q_OBJECT;
74
75signals:
76
77 void sigOpenSession(QString strUserName, QString strPassword);
78 void sigCloseSession();
79
80public:
81
82 UIGuestSessionWidget(QWidget *pParent = 0);
83 /** Disables certain widget after a guest session has been opened. */
84 void switchSessionOpenMode();
85 /** Makes sure certain widgets are enabled so that a guest session can be opened. */
86 void switchSessionCloseMode();
87 void markForError(bool fMarkForError);
88 void setStatusLabelIconAndToolTip(const QIcon &icon, const QString &strToolTip);
89 void setLoginWidgetsEnabled(bool fEnabled);
90
91protected:
92
93 void retranslateUi() RT_OVERRIDE;
94 void keyPressEvent(QKeyEvent * pEvent) RT_OVERRIDE;
95 void showEvent(QShowEvent *pEvent) RT_OVERRIDE;
96
97private slots:
98
99 void sltButtonClick();
100 void sltHandleTextChanged(const QString &strText);
101
102private:
103
104 enum ButtonMode
105 {
106 ButtonMode_Open,
107 ButtonMode_Close
108 };
109
110 void prepareWidgets();
111 void updateButton();
112
113 ButtonMode m_enmButtonMode;
114 QILineEdit *m_pUserNameEdit;
115 UIPasswordLineEdit *m_pPasswordEdit;
116 QPushButton *m_pButton;
117 QHBoxLayout *m_pMainLayout;
118 QColor m_defaultBaseColor;
119 QColor m_errorBaseColor;
120 bool m_fMarkedForError;
121 QLabel *m_pStatusIconLabel;
122};
123
124
125/*********************************************************************************************************************************
126* UIGuestSessionWidget implementation. *
127*********************************************************************************************************************************/
128
129UIGuestSessionWidget::UIGuestSessionWidget(QWidget *pParent /* = 0 */)
130 : QIWithRetranslateUI<QWidget>(pParent)
131 , m_enmButtonMode(ButtonMode_Open)
132 , m_pUserNameEdit(0)
133 , m_pPasswordEdit(0)
134 , m_pButton(0)
135 , m_pMainLayout(0)
136 , m_fMarkedForError(0)
137 , m_pStatusIconLabel(0)
138{
139 prepareWidgets();
140}
141
142void UIGuestSessionWidget::prepareWidgets()
143{
144 m_pMainLayout = new QHBoxLayout(this);
145 if (!m_pMainLayout)
146 return;
147
148 m_pMainLayout->setContentsMargins(0, 0, 0, 0);
149
150 m_pUserNameEdit = new QILineEdit;
151 if (m_pUserNameEdit)
152 {
153 m_pMainLayout->addWidget(m_pUserNameEdit, 2);
154 m_pUserNameEdit->setPlaceholderText(QApplication::translate("UIFileManager", "User Name"));
155 m_defaultBaseColor = m_pUserNameEdit->palette().color(QPalette::Base);
156 m_errorBaseColor = QColor(m_defaultBaseColor.red(),
157 0.5 * m_defaultBaseColor.green(),
158 0.5 * m_defaultBaseColor.blue());
159 connect(m_pUserNameEdit, &QILineEdit::textChanged,
160 this, &UIGuestSessionWidget::sltHandleTextChanged);
161 }
162
163 m_pPasswordEdit = new UIPasswordLineEdit;
164 if (m_pPasswordEdit)
165 {
166 m_pMainLayout->addWidget(m_pPasswordEdit, 2);
167 m_pPasswordEdit->setPlaceholderText(QApplication::translate("UIFileManager", "Password"));
168 m_pPasswordEdit->setEchoMode(QLineEdit::Password);
169 connect(m_pPasswordEdit, &UIPasswordLineEdit::textChanged,
170 this, &UIGuestSessionWidget::sltHandleTextChanged);
171 }
172
173 m_pButton = new QPushButton;
174 if (m_pButton)
175 {
176 m_pMainLayout->addWidget(m_pButton);
177 connect(m_pButton, &QPushButton::clicked, this, &UIGuestSessionWidget::sltButtonClick);
178 }
179 m_pStatusIconLabel = new QLabel(this);
180 if (m_pStatusIconLabel)
181 {
182 m_pMainLayout->addWidget(m_pStatusIconLabel);
183 m_pStatusIconLabel->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
184 }
185
186 m_pMainLayout->insertStretch(-1, 1);
187 switchSessionOpenMode();
188 retranslateUi();
189}
190
191void UIGuestSessionWidget::sltButtonClick()
192{
193 if (m_enmButtonMode == ButtonMode_Open && m_pUserNameEdit && m_pPasswordEdit)
194 emit sigOpenSession(m_pUserNameEdit->text(), m_pPasswordEdit->text());
195 else if (m_enmButtonMode == ButtonMode_Close)
196 emit sigCloseSession();
197}
198
199void UIGuestSessionWidget::sltHandleTextChanged(const QString &strText)
200{
201 Q_UNUSED(strText);
202 markForError(false);
203}
204
205void UIGuestSessionWidget::retranslateUi()
206{
207 if (m_pUserNameEdit)
208 {
209 m_pUserNameEdit->setToolTip(QApplication::translate("UIFileManager", "User name to authenticate session creation"));
210 m_pUserNameEdit->setPlaceholderText(QApplication::translate("UIFileManager", "User Name"));
211
212 }
213 if (m_pPasswordEdit)
214 {
215 m_pPasswordEdit->setToolTip(QApplication::translate("UIFileManager", "Password to authenticate session creation"));
216 m_pPasswordEdit->setPlaceholderText(QApplication::translate("UIFileManager", "Password"));
217 }
218
219 if (m_pButton)
220 {
221 if (m_enmButtonMode == ButtonMode_Open)
222 {
223 m_pButton->setText(QApplication::translate("UIFileManager", "Open Session"));
224 m_pButton->setToolTip(QApplication::translate("UIFileManager", "Open Session"));
225 }
226 else
227 {
228 m_pButton->setText(QApplication::translate("UIFileManager", "Close Session"));
229 m_pButton->setToolTip(QApplication::translate("UIFileManager", "Close Session"));
230 }
231 }
232}
233
234void UIGuestSessionWidget::keyPressEvent(QKeyEvent * pEvent)
235{
236 /* Emit sigOpenSession upon enter press: */
237 if (pEvent->key() == Qt::Key_Enter || pEvent->key() == Qt::Key_Return)
238 {
239 if ((m_pUserNameEdit && m_pUserNameEdit->hasFocus()) ||
240 (m_pPasswordEdit && m_pPasswordEdit->hasFocus()))
241 sigOpenSession(m_pUserNameEdit->text(), m_pPasswordEdit->text());
242 }
243 QWidget::keyPressEvent(pEvent);
244}
245
246void UIGuestSessionWidget::showEvent(QShowEvent *pEvent)
247{
248 QIWithRetranslateUI<QWidget>::showEvent(pEvent);
249 if (m_pUserNameEdit)
250 m_pUserNameEdit->setFocus();
251}
252
253void UIGuestSessionWidget::switchSessionOpenMode()
254{
255 if (m_pUserNameEdit)
256 m_pUserNameEdit->setEnabled(true);
257 if (m_pPasswordEdit)
258 m_pPasswordEdit->setEnabled(true);
259 m_enmButtonMode = ButtonMode_Open;
260 retranslateUi();
261}
262
263void UIGuestSessionWidget::switchSessionCloseMode()
264{
265 if (m_pUserNameEdit)
266 m_pUserNameEdit->setEnabled(false);
267 if (m_pPasswordEdit)
268 m_pPasswordEdit->setEnabled(false);
269 m_enmButtonMode = ButtonMode_Close;
270 retranslateUi();
271}
272
273void UIGuestSessionWidget::markForError(bool fMarkForError)
274{
275 if (m_fMarkedForError == fMarkForError)
276 return;
277 m_fMarkedForError = fMarkForError;
278
279 if (m_pUserNameEdit)
280 {
281 QPalette mPalette = m_pUserNameEdit->palette();
282 if (m_fMarkedForError)
283 mPalette.setColor(QPalette::Base, m_errorBaseColor);
284 else
285 mPalette.setColor(QPalette::Base, m_defaultBaseColor);
286 m_pUserNameEdit->setPalette(mPalette);
287 }
288 if (m_pPasswordEdit)
289 {
290 QPalette mPalette = m_pPasswordEdit->palette();
291 if (m_fMarkedForError)
292 mPalette.setColor(QPalette::Base, m_errorBaseColor);
293 else
294 mPalette.setColor(QPalette::Base, m_defaultBaseColor);
295 m_pPasswordEdit->setPalette(mPalette);
296 }
297}
298
299void UIGuestSessionWidget::setStatusLabelIconAndToolTip(const QIcon &icon, const QString &strToolTip)
300{
301 if (!m_pStatusIconLabel)
302 return;
303 const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_ButtonIconSize);
304 m_pStatusIconLabel->setPixmap(icon.pixmap(QSize(iIconMetric, iIconMetric)));
305 m_pStatusIconLabel->setToolTip(strToolTip);
306}
307
308void UIGuestSessionWidget::setLoginWidgetsEnabled(bool fEnabled)
309{
310 if (m_pUserNameEdit)
311 m_pUserNameEdit->setEnabled(fEnabled);
312 if (m_pPasswordEdit)
313 m_pPasswordEdit->setEnabled(fEnabled);
314 if (m_pButton)
315 m_pButton->setEnabled(fEnabled);
316}
317
318
319/*********************************************************************************************************************************
320* UIGuestDirectoryDiskUsageComputer definition. *
321*********************************************************************************************************************************/
322
323/** Open directories recursively and sum the disk usage. Don't block the GUI thread while doing this */
324class UIGuestDirectoryDiskUsageComputer : public UIDirectoryDiskUsageComputer
325{
326 Q_OBJECT;
327
328public:
329
330 UIGuestDirectoryDiskUsageComputer(QObject *parent, QStringList strStartPath, const CGuestSession &session);
331
332protected:
333
334 virtual void run() RT_OVERRIDE;
335 virtual void directoryStatisticsRecursive(const QString &path, UIDirectoryStatistics &statistics) RT_OVERRIDE;
336
337private:
338
339 CGuestSession m_comGuestSession;
340};
341
342
343/*********************************************************************************************************************************
344* UIGuestDirectoryDiskUsageComputer implementation. *
345*********************************************************************************************************************************/
346
347UIGuestDirectoryDiskUsageComputer::UIGuestDirectoryDiskUsageComputer(QObject *parent, QStringList pathList, const CGuestSession &session)
348 :UIDirectoryDiskUsageComputer(parent, pathList)
349 , m_comGuestSession(session)
350{
351}
352
353void UIGuestDirectoryDiskUsageComputer::run()
354{
355 /* Initialize COM: */
356 COMBase::InitializeCOM(false);
357 UIDirectoryDiskUsageComputer::run();
358 /* Cleanup COM: */
359 COMBase::CleanupCOM();
360}
361
362void UIGuestDirectoryDiskUsageComputer::directoryStatisticsRecursive(const QString &path, UIDirectoryStatistics &statistics)
363{
364 if (m_comGuestSession.isNull())
365 return;
366 /* Prevent modification of the continue flag while reading: */
367 m_mutex.lock();
368 /* Check if m_fOkToContinue is set to false. if so just end recursion: */
369 if (!isOkToContinue())
370 {
371 m_mutex.unlock();
372 return;
373 }
374 m_mutex.unlock();
375
376 CGuestFsObjInfo fileInfo = m_comGuestSession.FsObjQueryInfo(path, true);
377
378 if (!m_comGuestSession.isOk())
379 return;
380 /* if the object is a file or a symlink then read the size and return: */
381 if (fileInfo.GetType() == KFsObjType_File)
382 {
383 statistics.m_totalSize += fileInfo.GetObjectSize();
384 ++statistics.m_uFileCount;
385 sigResultUpdated(statistics);
386 return;
387 }
388 else if (fileInfo.GetType() == KFsObjType_Symlink)
389 {
390 statistics.m_totalSize += fileInfo.GetObjectSize();
391 ++statistics.m_uSymlinkCount;
392 sigResultUpdated(statistics);
393 return;
394 }
395
396 if (fileInfo.GetType() != KFsObjType_Directory)
397 return;
398 /* Open the directory to start reading its content: */
399 QVector<KDirectoryOpenFlag> flag(1, KDirectoryOpenFlag_None);
400 CGuestDirectory directory = m_comGuestSession.DirectoryOpen(path, /*aFilter*/ "", flag);
401 if (!m_comGuestSession.isOk())
402 return;
403
404 if (directory.isOk())
405 {
406 CFsObjInfo fsInfo = directory.Read();
407 while (fsInfo.isOk())
408 {
409 if (fsInfo.GetType() == KFsObjType_File)
410 statistics.m_uFileCount++;
411 else if (fsInfo.GetType() == KFsObjType_Symlink)
412 statistics.m_uSymlinkCount++;
413 else if(fsInfo.GetType() == KFsObjType_Directory)
414 {
415 QString dirPath = UIPathOperations::mergePaths(path, fsInfo.GetName());
416 directoryStatisticsRecursive(dirPath, statistics);
417 }
418 }
419 }
420 sigResultUpdated(statistics);
421}
422
423UIFileManagerGuestTable::UIFileManagerGuestTable(UIActionPool *pActionPool, const CMachine &comMachine, QWidget *pParent /*= 0*/)
424 :UIFileManagerTable(pActionPool, pParent)
425 , m_comMachine(comMachine)
426 , m_pGuestSessionWidget(0)
427 , m_fIsCurrent(false)
428 , pszMinimumGuestAdditionVersion("6.1")
429{
430 setModelFileSystem(isWindowsFileSystem());
431 if (!m_comMachine.isNull())
432 m_strTableName = m_comMachine.GetName();
433 prepareToolbar();
434 prepareGuestSessionPanel();
435 prepareActionConnections();
436 connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigMachineStateChange,
437 this, &UIFileManagerGuestTable::sltMachineStateChange);
438 connect(&uiCommon(), &UICommon::sigAskToCommitData,
439 this, &UIFileManagerGuestTable::sltCommitDataSignalReceived);
440
441 if (m_pActionPool && m_pActionPool->action(UIActionIndex_M_FileManager_T_GuestSession))
442 m_pActionPool->action(UIActionIndex_M_FileManager_T_GuestSession)->setChecked(true);
443
444 if (!m_comMachine.isNull() && m_comMachine.GetState() == KMachineState_Running)
445 openMachineSession();
446 setStateAndEnableWidgets();
447
448 retranslateUi();
449}
450
451UIFileManagerGuestTable::~UIFileManagerGuestTable()
452{
453 cleanAll();
454}
455
456void UIFileManagerGuestTable::initFileTable()
457{
458 if (!m_comGuestSession.isOk() || m_comGuestSession.GetStatus() != KGuestSessionStatus_Started)
459 return;
460 /* To determine the path separator we need to have a valid guest session: */
461 determinePathSeparator();
462 initializeFileTree();
463}
464
465void UIFileManagerGuestTable::retranslateUi()
466{
467 if (m_pLocationLabel)
468 m_pLocationLabel->setText(UIFileManager::tr("Guest File System:"));
469
470 if (m_pGuestSessionWidget)
471 {
472 QIcon icon;
473 QString strWarningText;
474 switch (m_enmState)
475 {
476 case State_InvalidMachineReference:
477 strWarningText = UIFileManager::tr("Machine reference is invalid.");
478 icon = UIIconPool::iconSet(":/status_error_16px.png");
479 break;
480 case State_MachineNotRunning:
481 strWarningText = UIFileManager::tr("File manager cannot work since the selected guest is not currently running.");
482 icon = UIIconPool::iconSet(":/status_error_16px.png");
483 break;
484 case State_MachinePaused:
485 strWarningText = UIFileManager::tr("File manager cannot work since the guest is paused.");
486 icon = UIIconPool::iconSet(":/session_info_16px.png");
487 break;
488 case State_NoGuestAdditions:
489 strWarningText = UIFileManager::tr("File manager cannot work since no guest additions were detected.");
490 icon = UIIconPool::iconSet(":/status_error_16px.png");
491 break;
492 case State_GuestAdditionsTooOld:
493 strWarningText = UIFileManager::tr("File manager cannot work. The guest additions need to be updated.");
494 icon = UIIconPool::iconSet(":/status_error_16px.png");
495 break;
496 case State_SessionPossible:
497 strWarningText = UIFileManager::tr("Enter a valid user name and password to initiate the file manager.");
498 icon = UIIconPool::iconSet(":/session_info_16px.png");
499 break;
500 case State_SessionRunning:
501 strWarningText = UIFileManager::tr("Guest control session is running.");
502 icon = UIIconPool::iconSet(":/status_check_16px.png");
503 break;
504 case State_SessionError:
505 strWarningText = UIFileManager::tr("Some error has occurred. Please check the log panel.");
506 icon = UIIconPool::iconSet(":/status_error_16px.png");
507 break;
508 default:
509 break;
510 }
511 m_pGuestSessionWidget->setStatusLabelIconAndToolTip(icon, strWarningText);
512 }
513
514 UIFileManagerTable::retranslateUi();
515}
516
517bool UIFileManagerGuestTable::readDirectory(const QString& strPath,
518 UIFileSystemItem *parent, bool isStartDir /*= false*/)
519{
520 if (!parent)
521 return false;
522
523 CGuestDirectory directory;
524 QVector<KDirectoryOpenFlag> flag;
525 flag.push_back(KDirectoryOpenFlag_None);
526
527 directory = m_comGuestSession.DirectoryOpen(UIPathOperations::sanitize(strPath), /*aFilter*/ "", flag);
528 if (!m_comGuestSession.isOk())
529 {
530 emit sigLogOutput(UIErrorString::formatErrorInfo(m_comGuestSession), m_strTableName, FileManagerLogType_Error);
531 return false;
532 }
533
534 parent->setIsOpened(true);
535 if (directory.isOk())
536 {
537 int const cMaxEntries = _4K; /* Maximum number of entries to read at once per List() call. */
538 bool fUseRead = false; /* Whether to use the Read() API or the newer (faster) List() call. */
539
540 QVector<CFsObjInfo> vecFsInfo = directory.List(cMaxEntries);
541 /* IGuestDirectory::List() will return VBOX_E_NOT_SUPPORTED if older Guest Additions are installed. */
542 if (directory.rc() == VBOX_E_NOT_SUPPORTED)
543 {
544 CFsObjInfo fsInfo = directory.Read();
545 if (directory.isOk())
546 {
547 vecFsInfo.push_back(fsInfo);
548 fUseRead = true;
549 }
550 }
551
552 QMap<QString, UIFileSystemItem*> fileObjects;
553
554 while (directory.isOk())
555 {
556 for (int i = 0; i < vecFsInfo.size(); i++)
557 {
558 CFsObjInfo const &fsInfo = vecFsInfo[i];
559
560 if (fsInfo.GetName() != "." && fsInfo.GetName() != "..")
561 {
562 QVector<QVariant> data;
563 QDateTime changeTime = QDateTime::fromMSecsSinceEpoch(fsInfo.GetChangeTime()/RT_NS_1MS);
564 KFsObjType fsObjectType = fileType(fsInfo);
565 UIFileSystemItem *item = new UIFileSystemItem(fsInfo.GetName(), parent, fsObjectType);
566 if (!item)
567 continue;
568 item->setData(static_cast<qulonglong>(fsInfo.GetObjectSize()), UIFileSystemModelData_Size);
569 item->setData(changeTime, UIFileSystemModelData_ChangeTime);
570 item->setData(fsInfo.GetUserName(), UIFileSystemModelData_Owner);
571 item->setData(permissionString(fsInfo), UIFileSystemModelData_Permissions);
572 item->setIsOpened(false);
573 item->setIsHidden(isFileObjectHidden(fsInfo));
574 fileObjects.insert(fsInfo.GetName(), item);
575 /* @todo. We will need to wait a fully implemented SymlinkRead function
576 * to be able to handle sym links properly: */
577 // QString path = UIPathOperations::mergePaths(strPath, fsInfo.GetName());
578 // QVector<KSymlinkReadFlag> aFlags;
579 // printf("%s %s %s\n", qPrintable(fsInfo.GetName()), qPrintable(path),
580 // qPrintable(m_comGuestSession.SymlinkRead(path, aFlags)));
581 }
582 }
583
584 if (fUseRead)
585 {
586 CFsObjInfo fsInfo = directory.Read();
587 if (directory.isOk())
588 {
589 vecFsInfo.clear();
590 vecFsInfo.push_back(fsInfo);
591 }
592 }
593 else
594 vecFsInfo = directory.List(cMaxEntries);
595 }
596
597 checkDotDot(fileObjects, parent, isStartDir);
598 }
599 else
600 {
601 directory.Close();
602 return false;
603 }
604 directory.Close();
605 return true;
606}
607
608void UIFileManagerGuestTable::deleteByItem(UIFileSystemItem *item)
609{
610 if (!item)
611 return;
612 if (item->isUpDirectory())
613 return;
614
615 if (item->isDirectory())
616 {
617 QVector<KDirectoryRemoveRecFlag> aFlags(1, KDirectoryRemoveRecFlag_ContentAndDir);
618 m_comGuestSession.DirectoryRemoveRecursive(UIPathOperations::removeTrailingDelimiters(item->path()), aFlags);
619 }
620 else
621 m_comGuestSession.FsObjRemove(UIPathOperations::removeTrailingDelimiters(item->path()));
622 if (!m_comGuestSession.isOk())
623 {
624 emit sigLogOutput(QString(item->path()).append(" could not be deleted"), m_strTableName, FileManagerLogType_Error);
625 emit sigLogOutput(UIErrorString::formatErrorInfo(m_comGuestSession), m_strTableName, FileManagerLogType_Error);
626 }
627}
628
629void UIFileManagerGuestTable::goToHomeDirectory()
630{
631 if (m_comGuestSession.isNull())
632 return;
633 if (!rootItem() || rootItem()->childCount() <= 0)
634 return;
635 UIFileSystemItem *startDirItem = rootItem()->child(0);
636 if (!startDirItem)
637 return;
638
639 QString userHome = UIPathOperations::sanitize(m_comGuestSession.GetUserHome());
640 if (!m_comGuestSession.isOk())
641 {
642 emit sigLogOutput(UIErrorString::formatErrorInfo(m_comGuestSession), m_strTableName, FileManagerLogType_Error);
643 return;
644 }
645#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
646 QStringList pathList = userHome.split(UIPathOperations::delimiter, Qt::SkipEmptyParts);
647#else
648 QStringList pathList = userHome.split(UIPathOperations::delimiter, QString::SkipEmptyParts);
649#endif
650 goIntoDirectory(UIPathOperations::pathTrail(userHome));
651}
652
653bool UIFileManagerGuestTable::renameItem(UIFileSystemItem *item, const QString &strOldPath)
654{
655 if (!item || item->isUpDirectory())
656 return false;
657 //QString newPath = UIPathOperations::removeTrailingDelimiters(UIPathOperations::constructNewItemPath(item->path(), newBaseName));
658 QVector<KFsObjRenameFlag> aFlags(1, KFsObjRenameFlag_Replace);
659
660 m_comGuestSession.FsObjRename(strOldPath, item->path(), aFlags);
661
662 if (!m_comGuestSession.isOk())
663 {
664 emit sigLogOutput(UIErrorString::formatErrorInfo(m_comGuestSession), m_strTableName, FileManagerLogType_Error);
665 return false;
666 }
667
668 return true;
669}
670
671bool UIFileManagerGuestTable::createDirectory(const QString &path, const QString &directoryName)
672{
673 QString newDirectoryPath = UIPathOperations::mergePaths(path, directoryName);
674 QVector<KDirectoryCreateFlag> flags(1, KDirectoryCreateFlag_None);
675
676 m_comGuestSession.DirectoryCreate(newDirectoryPath, 0/*aMode*/, flags);
677
678 if (!m_comGuestSession.isOk())
679 {
680 emit sigLogOutput(newDirectoryPath.append(" could not be created"), m_strTableName, FileManagerLogType_Error);
681 emit sigLogOutput(UIErrorString::formatErrorInfo(m_comGuestSession), m_strTableName, FileManagerLogType_Error);
682 return false;
683 }
684 emit sigLogOutput(newDirectoryPath.append(" has been created"), m_strTableName, FileManagerLogType_Info);
685 return true;
686}
687
688void UIFileManagerGuestTable::copyHostToGuest(const QStringList &hostSourcePathList,
689 const QString &strDestination /* = QString() */)
690{
691 if (!checkGuestSession())
692 return;
693 QVector<QString> sourcePaths = hostSourcePathList.toVector();
694 /* Remove empty source paths. Typically happens when up directory is selected: */
695 sourcePaths.removeAll(QString());
696
697 QVector<QString> aFilters;
698 QVector<QString> aFlags;
699 QString strDestinationPath = UIPathOperations::addTrailingDelimiters(strDestination);
700 if (strDestinationPath.isEmpty())
701 strDestinationPath = UIPathOperations::addTrailingDelimiters(currentDirectoryPath());
702
703 if (strDestinationPath.isEmpty())
704 {
705 emit sigLogOutput("No destination for copy operation", m_strTableName, FileManagerLogType_Error);
706 return;
707 }
708 if (sourcePaths.empty())
709 {
710 emit sigLogOutput("No source for copy operation", m_strTableName, FileManagerLogType_Error);
711 return;
712 }
713 QString strDirectoryFlags("CopyIntoExisting,Recursive,FollowLinks");
714 QString strFileFlags("FollowLinks");
715
716 for (int i = 0; i < sourcePaths.size(); ++i)
717 {
718 sourcePaths[i] = UIPathOperations::removeTrailingDelimiters(sourcePaths[i]);
719 KFsObjType enmFileType = UIFileManagerHostTable::fileType(sourcePaths[i]);
720 if (enmFileType == KFsObjType_Unknown)
721 emit sigLogOutput(QString("Querying information for host item %1 failed.").arg(sourcePaths[i]), m_strTableName, FileManagerLogType_Error);
722 /* If the source is an directory, make sure to add the appropriate flag to make copying work
723 * into existing directories on the guest. This otherwise would fail (default): */
724 else if (enmFileType == KFsObjType_Directory)
725 aFlags << strDirectoryFlags;
726 else
727 aFlags << strFileFlags;
728 }
729
730 CProgress progress = m_comGuestSession.CopyToGuest(sourcePaths, aFilters, aFlags, strDestinationPath);
731 if (!checkGuestSession())
732 return;
733 emit sigNewFileOperation(progress, m_strTableName);
734}
735
736QUuid UIFileManagerGuestTable::machineId()
737{
738 if (m_comMachine.isNull())
739 return QUuid();
740 return m_comMachine.GetId();
741}
742
743bool UIFileManagerGuestTable::isGuestSessionRunning() const
744{
745 return m_enmState == State_SessionRunning;
746}
747
748void UIFileManagerGuestTable::setIsCurrent(bool fIsCurrent)
749{
750 if (m_fIsCurrent == fIsCurrent)
751 return;
752 m_fIsCurrent = fIsCurrent;
753 prepareActionConnections();
754}
755
756void UIFileManagerGuestTable::copyGuestToHost(const QString& hostDestinationPath)
757{
758 if (!checkGuestSession())
759 return;
760 QVector<QString> sourcePaths = selectedItemPathList().toVector();
761 QVector<QString> aFilters;
762 QVector<QString> aFlags;
763
764 /* Remove empty source paths. Typically happens when up directory is selected: */
765 sourcePaths.removeAll(QString());
766
767 if (hostDestinationPath.isEmpty())
768 {
769 emit sigLogOutput("No destination for copy operation", m_strTableName, FileManagerLogType_Error);
770 return;
771 }
772 if (sourcePaths.empty())
773 {
774 emit sigLogOutput("No source for copy operation", m_strTableName, FileManagerLogType_Error);
775 return;
776 }
777
778 QString strDestinationPath = UIPathOperations::addTrailingDelimiters(hostDestinationPath);
779 QString strDirectoryFlags("CopyIntoExisting,Recursive,FollowLinks");
780 QString strFileFlags;
781 //foreach (const QString &strSource, sourcePaths)
782 for (int i = 0; i < sourcePaths.size(); ++i)
783 {
784 sourcePaths[i] = UIPathOperations::removeTrailingDelimiters(sourcePaths[i]);
785 /** @todo Cache this info and use the item directly, which has this info already? */
786
787 /* If the source is an directory, make sure to add the appropriate flag to make copying work
788 * into existing directories on the guest. This otherwise would fail (default). */
789 CGuestFsObjInfo fileInfo = m_comGuestSession.FsObjQueryInfo(sourcePaths[i], true);
790 if (!m_comGuestSession.isOk())
791 {
792 emit sigLogOutput(UIErrorString::formatErrorInfo(m_comGuestSession), m_strTableName, FileManagerLogType_Error);
793 return;
794 }
795
796 if (fileType(fileInfo) == KFsObjType_Directory)
797 aFlags << strDirectoryFlags;
798 else
799 aFlags << strFileFlags;
800
801 }
802
803 CProgress progress = m_comGuestSession.CopyFromGuest(sourcePaths, aFilters, aFlags, strDestinationPath);
804 if (!checkGuestSession())
805 return;
806 emit sigNewFileOperation(progress, m_strTableName);
807}
808
809KFsObjType UIFileManagerGuestTable::fileType(const CFsObjInfo &fsInfo)
810{
811 if (fsInfo.isNull() || !fsInfo.isOk())
812 return KFsObjType_Unknown;
813 if (fsInfo.GetType() == KFsObjType_Directory)
814 return KFsObjType_Directory;
815 else if (fsInfo.GetType() == KFsObjType_File)
816 return KFsObjType_File;
817 else if (fsInfo.GetType() == KFsObjType_Symlink)
818 return KFsObjType_Symlink;
819
820 return KFsObjType_Unknown;
821}
822
823KFsObjType UIFileManagerGuestTable::fileType(const CGuestFsObjInfo &fsInfo)
824{
825 if (fsInfo.isNull() || !fsInfo.isOk())
826 return KFsObjType_Unknown;
827 if (fsInfo.GetType() == KFsObjType_Directory)
828 return KFsObjType_Directory;
829 else if (fsInfo.GetType() == KFsObjType_File)
830 return KFsObjType_File;
831 else if (fsInfo.GetType() == KFsObjType_Symlink)
832 return KFsObjType_Symlink;
833
834 return KFsObjType_Unknown;
835}
836
837
838QString UIFileManagerGuestTable::fsObjectPropertyString()
839{
840 QStringList selectedObjects = selectedItemPathList();
841 if (selectedObjects.isEmpty())
842 return QString();
843 if (selectedObjects.size() == 1)
844 {
845 if (selectedObjects.at(0).isNull())
846 return QString();
847
848 CGuestFsObjInfo fileInfo = m_comGuestSession.FsObjQueryInfo(selectedObjects.at(0), false /*aFollowSymlinks*/);
849 if (!m_comGuestSession.isOk())
850 {
851 emit sigLogOutput(UIErrorString::formatErrorInfo(m_comGuestSession), m_strTableName, FileManagerLogType_Error);
852 return QString();
853 }
854
855 QStringList propertyStringList;
856
857 /* Name: */
858 propertyStringList << UIFileManager::tr("<b>Name:</b> %1<br/>").arg(UIPathOperations::getObjectName(fileInfo.GetName()));
859
860 /* Size: */
861 LONG64 size = fileInfo.GetObjectSize();
862 propertyStringList << UIFileManager::tr("<b>Size:</b> %1 bytes").arg(QString::number(size));
863 if (size >= UIFileManagerTable::m_iKiloByte)
864 propertyStringList << QString(" (%1)<br/>").arg(humanReadableSize(size));
865 else
866 propertyStringList << QString("<br/>");
867
868 /* Allocated size: */
869 size = fileInfo.GetAllocatedSize();
870 propertyStringList << UIFileManager::tr("<b>Allocated:</b> %1 bytes").arg(QString::number(size));
871 if (size >= UIFileManagerTable::m_iKiloByte)
872 propertyStringList << QString(" (%1)<br/>").arg(humanReadableSize(size));
873 else
874 propertyStringList << QString("<br/>");
875
876 /* Type: */
877 QString str;
878 KFsObjType const enmType = fileInfo.GetType();
879 switch (enmType)
880 {
881 case KFsObjType_Directory: str = UIFileManager::tr("directory"); break;
882 case KFsObjType_File: str = UIFileManager::tr("file"); break;
883 case KFsObjType_Symlink: str = UIFileManager::tr("symbolic link"); break;
884 case KFsObjType_DevChar: str = UIFileManager::tr("character device"); break;
885 case KFsObjType_DevBlock: str = UIFileManager::tr("block device"); break;
886 case KFsObjType_Fifo: str = UIFileManager::tr("fifo"); break;
887 case KFsObjType_Socket: str = UIFileManager::tr("socket"); break;
888 case KFsObjType_WhiteOut: str = UIFileManager::tr("whiteout"); break;
889 case KFsObjType_Unknown: str = UIFileManager::tr("unknown"); break;
890 default: str = UIFileManager::tr("illegal-value"); break;
891 }
892 propertyStringList << UIFileManager::tr("<b>Type:</b> %1<br/>").arg(str);
893
894 /* INode number, device, link count: */
895 propertyStringList << UIFileManager::tr("<b>INode:</b> %1<br/>").arg(fileInfo.GetNodeId());
896 propertyStringList << UIFileManager::tr("<b>Device:</b> %1<br/>").arg(fileInfo.GetNodeIdDevice()); /** @todo hex */
897 propertyStringList << UIFileManager::tr("<b>Hardlinks:</b> %1<br/>").arg(fileInfo.GetHardLinks());
898
899 /* Attributes: */
900 str = fileInfo.GetFileAttributes();
901 if (!str.isEmpty())
902 {
903 int offSpace = str.indexOf(' ');
904 if (offSpace < 0)
905 offSpace = str.length();
906 propertyStringList << UIFileManager::tr("<b>Mode:</b> %1<br/>").arg(str.left(offSpace));
907 propertyStringList << UIFileManager::tr("<b>Attributes:</b> %1<br/>").arg(str.mid(offSpace + 1).trimmed());
908 }
909
910 /* Character/block device ID: */
911 ULONG uDeviceNo = fileInfo.GetDeviceNumber();
912 if (uDeviceNo != 0 || enmType == KFsObjType_DevChar || enmType == KFsObjType_DevBlock)
913 propertyStringList << UIFileManager::tr("<b>Device ID:</b> %1<br/>").arg(uDeviceNo); /** @todo hex */
914
915 /* Owner: */
916 propertyStringList << UIFileManager::tr("<b>Owner:</b> %1 (%2)<br/>").
917 arg(fileInfo.GetUserName()).arg(fileInfo.GetUID());
918 propertyStringList << UIFileManager::tr("<b>Group:</b> %1 (%2)<br/>").
919 arg(fileInfo.GetGroupName()).arg(fileInfo.GetGID());
920
921 /* Timestamps: */
922 propertyStringList << UIFileManager::tr("<b>Birth:</b> %1<br/>").
923 arg(QDateTime::fromMSecsSinceEpoch(fileInfo.GetBirthTime() / RT_NS_1MS).toString());
924 propertyStringList << UIFileManager::tr("<b>Change:</b> %1<br/>").
925 arg(QDateTime::fromMSecsSinceEpoch(fileInfo.GetChangeTime() / RT_NS_1MS).toString());
926 propertyStringList << UIFileManager::tr("<b>Modified:</b> %1<br/>").
927 arg(QDateTime::fromMSecsSinceEpoch(fileInfo.GetModificationTime() / RT_NS_1MS).toString());
928 propertyStringList << UIFileManager::tr("<b>Access:</b> %1<br/>").
929 arg(QDateTime::fromMSecsSinceEpoch(fileInfo.GetAccessTime() / RT_NS_1MS).toString());
930
931 /* Join the list elements into a single string seperated by empty string: */
932 return propertyStringList.join(QString());
933 }
934
935 int fileCount = 0;
936 int directoryCount = 0;
937 ULONG64 totalSize = 0;
938
939 for(int i = 0; i < selectedObjects.size(); ++i)
940 {
941 CGuestFsObjInfo fileInfo = m_comGuestSession.FsObjQueryInfo(selectedObjects.at(0), true);
942 if (!m_comGuestSession.isOk())
943 {
944 emit sigLogOutput(UIErrorString::formatErrorInfo(m_comGuestSession), m_strTableName, FileManagerLogType_Error);
945 continue;
946 }
947
948 KFsObjType type = fileType(fileInfo);
949
950 if (type == KFsObjType_File)
951 ++fileCount;
952 if (type == KFsObjType_Directory)
953 ++directoryCount;
954 totalSize += fileInfo.GetObjectSize();
955 }
956 QStringList propertyStringList;
957 propertyStringList << UIFileManager::tr("<b>Selected:</b> %1 files and %2 directories<br/>").
958 arg(QString::number(fileCount)).arg(QString::number(directoryCount));
959 propertyStringList << UIFileManager::tr("<b>Size (non-recursive):</b> %1 bytes").arg(QString::number(totalSize));
960 if (totalSize >= m_iKiloByte)
961 propertyStringList << QString(" (%1)").arg(humanReadableSize(totalSize));
962
963 return propertyStringList.join(QString());;
964}
965
966void UIFileManagerGuestTable::showProperties()
967{
968 if (m_comGuestSession.isNull())
969 return;
970 QString fsPropertyString = fsObjectPropertyString();
971 if (fsPropertyString.isEmpty())
972 return;
973
974 m_pPropertiesDialog = new UIPropertiesDialog(this);
975 if (!m_pPropertiesDialog)
976 return;
977
978 QStringList selectedObjects = selectedItemPathList();
979 if (selectedObjects.size() == 0)
980 return;
981
982 m_pPropertiesDialog->setWindowTitle(UIFileManager::tr("Properties"));
983 m_pPropertiesDialog->setPropertyText(fsPropertyString);
984 m_pPropertiesDialog->execute();
985
986 delete m_pPropertiesDialog;
987 m_pPropertiesDialog = 0;
988}
989
990void UIFileManagerGuestTable::determineDriveLetters()
991{
992 if (m_comGuestSession.isNull())
993 return;
994
995 KPathStyle pathStyle = m_comGuestSession.GetPathStyle();
996 if (pathStyle != KPathStyle_DOS)
997 return;
998
999 m_driveLetterList.clear();
1000
1001 QVector<QString> mountPoints = m_comGuestSession.GetMountPoints();
1002 if (m_comGuestSession.isOk())
1003 {
1004 foreach (const QString &strPoint, mountPoints)
1005 m_driveLetterList.push_back(UIPathOperations::replaceDosDelimeter(strPoint));
1006 }
1007 else
1008 {
1009 for (int i = 'A'; i <= 'Z'; ++i)
1010 {
1011 QString path((char)i);
1012 path += ":/";
1013 bool exists = m_comGuestSession.DirectoryExists(path, false /* aFollowSymlinks */);
1014 if (exists)
1015 m_driveLetterList.push_back(path);
1016 }
1017 }
1018}
1019
1020void UIFileManagerGuestTable::determinePathSeparator()
1021{
1022 if (m_comGuestSession.isNull())
1023 return;
1024 KPathStyle pathStyle = m_comGuestSession.GetPathStyle();
1025 if (pathStyle == KPathStyle_DOS)
1026 setPathSeparator(UIPathOperations::dosDelimiter);
1027}
1028
1029void UIFileManagerGuestTable::prepareToolbar()
1030{
1031 if (m_pToolBar && m_pActionPool)
1032 {
1033 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_GoBackward));
1034 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_GoForward));
1035 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_GoUp));
1036 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_GoHome));
1037 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Refresh));
1038 m_pToolBar->addSeparator();
1039 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Delete));
1040 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Rename));
1041 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_CreateNewDirectory));
1042
1043 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Copy));
1044 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Cut));
1045 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Paste));
1046 m_pToolBar->addSeparator();
1047 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_SelectAll));
1048 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_InvertSelection));
1049 m_pToolBar->addSeparator();
1050 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_ShowProperties));
1051 m_selectionDependentActions.insert(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Delete));
1052 m_selectionDependentActions.insert(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Rename));
1053 m_selectionDependentActions.insert(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Copy));
1054 m_selectionDependentActions.insert(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Cut));
1055 m_selectionDependentActions.insert(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_ShowProperties));
1056
1057 /* Hide these actions for now until we have a suitable guest-to-guest copy function: */
1058 m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Copy)->setVisible(false);
1059 m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Cut)->setVisible(false);
1060 m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Paste)->setVisible(false);
1061
1062 m_pToolBar->addSeparator();
1063 m_pToolBar->addAction(m_pActionPool->action(UIActionIndex_M_FileManager_T_GuestSession));
1064 }
1065
1066 setSelectionDependentActionsEnabled(false);
1067 setPasteActionEnabled(false);
1068}
1069
1070void UIFileManagerGuestTable::createFileViewContextMenu(const QWidget *pWidget, const QPoint &point)
1071{
1072 if (!pWidget)
1073 return;
1074
1075 QMenu menu;
1076 menu.addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_GoBackward));
1077 menu.addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_GoForward));
1078 menu.addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_GoUp));
1079
1080 menu.addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_GoHome));
1081 menu.addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Refresh));
1082 menu.addSeparator();
1083 menu.addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Delete));
1084 menu.addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Rename));
1085 menu.addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_CreateNewDirectory));
1086 menu.addSeparator();
1087 menu.addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Copy));
1088 menu.addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Cut));
1089 menu.addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Paste));
1090 menu.addSeparator();
1091 menu.addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_SelectAll));
1092 menu.addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_InvertSelection));
1093 menu.addSeparator();
1094 menu.addAction(m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_ShowProperties));
1095 menu.exec(pWidget->mapToGlobal(point));
1096}
1097
1098void UIFileManagerGuestTable::setPasteActionEnabled(bool fEnabled)
1099{
1100 m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Paste)->setEnabled(fEnabled);
1101}
1102
1103void UIFileManagerGuestTable::pasteCutCopiedObjects()
1104{
1105}
1106
1107void UIFileManagerGuestTable::manageConnection(bool fConnect, QAction *pAction, void (UIFileManagerGuestTable::*fptr)(void))
1108{
1109 if (!pAction || !fptr)
1110 return;
1111 if (fConnect)
1112 connect(pAction, &QAction::triggered, this, fptr);
1113 else
1114 disconnect(pAction, 0, this, 0);
1115}
1116
1117void UIFileManagerGuestTable::prepareActionConnections()
1118{
1119 if (m_pActionPool->action(UIActionIndex_M_FileManager_T_GuestSession))
1120 {
1121 if (m_fIsCurrent)
1122 connect(m_pActionPool->action(UIActionIndex_M_FileManager_T_GuestSession), &QAction::toggled,
1123 this, &UIFileManagerGuestTable::sltGuestSessionPanelToggled);
1124 else
1125 disconnect(m_pActionPool->action(UIActionIndex_M_FileManager_T_GuestSession), 0, this, 0);
1126 }
1127
1128 manageConnection(m_fIsCurrent, m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_GoUp), &UIFileManagerTable::sltGoUp);
1129 manageConnection(m_fIsCurrent, m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_GoHome), &UIFileManagerTable::sltGoHome);
1130 manageConnection(m_fIsCurrent, m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_GoBackward), &UIFileManagerTable::sltGoBackward);
1131 manageConnection(m_fIsCurrent, m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_GoForward), &UIFileManagerTable::sltGoForward);
1132 manageConnection(m_fIsCurrent, m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Refresh), &UIFileManagerTable::sltRefresh);
1133 manageConnection(m_fIsCurrent, m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Delete), &UIFileManagerTable::sltDelete);
1134 manageConnection(m_fIsCurrent, m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Rename), &UIFileManagerTable::sltRename);
1135 manageConnection(m_fIsCurrent, m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Copy), &UIFileManagerTable::sltCopy);
1136 manageConnection(m_fIsCurrent, m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Cut), &UIFileManagerTable::sltCut);
1137 manageConnection(m_fIsCurrent, m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_Paste), &UIFileManagerTable::sltPaste);
1138 manageConnection(m_fIsCurrent, m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_SelectAll), &UIFileManagerTable::sltSelectAll);
1139 manageConnection(m_fIsCurrent, m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_InvertSelection), &UIFileManagerTable::sltInvertSelection);
1140 manageConnection(m_fIsCurrent, m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_ShowProperties), &UIFileManagerTable::sltShowProperties);
1141 manageConnection(m_fIsCurrent, m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_CreateNewDirectory), &UIFileManagerTable::sltCreateNewDirectory);
1142
1143 /* Also disable/enable go forward/backward actions: */
1144 toggleForwardBackwardActions();
1145}
1146
1147void UIFileManagerGuestTable::prepareGuestSessionPanel()
1148{
1149 if (m_pMainLayout)
1150 {
1151 m_pGuestSessionWidget = new UIGuestSessionWidget;
1152 if (m_pGuestSessionWidget)
1153 {
1154 m_pMainLayout->addWidget(m_pGuestSessionWidget, m_pMainLayout->rowCount(), 0, 1, m_pMainLayout->columnCount());
1155 m_pGuestSessionWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
1156 connect(m_pGuestSessionWidget, &UIGuestSessionWidget::sigOpenSession,
1157 this, &UIFileManagerGuestTable::sltOpenGuestSession);
1158 connect(m_pGuestSessionWidget, &UIGuestSessionWidget::sigCloseSession,
1159 this, &UIFileManagerGuestTable::sltHandleCloseSessionRequest);
1160 }
1161 }
1162}
1163
1164bool UIFileManagerGuestTable::checkGuestSession()
1165{
1166 if (!m_comGuestSession.isOk())
1167 {
1168 emit sigLogOutput(UIErrorString::formatErrorInfo(m_comGuestSession), m_strTableName, FileManagerLogType_Error);
1169 return false;
1170 }
1171 return true;
1172}
1173
1174QString UIFileManagerGuestTable::permissionString(const CFsObjInfo &fsInfo)
1175{
1176 /* Attributes: */
1177 QString strAttributes = fsInfo.GetFileAttributes();
1178
1179 if (strAttributes.isEmpty())
1180 return strAttributes;
1181
1182 int offSpace = strAttributes.indexOf(' ');
1183 if (offSpace < 0)
1184 offSpace = strAttributes.length();
1185 return strAttributes.left(offSpace);
1186}
1187
1188bool UIFileManagerGuestTable::isFileObjectHidden(const CFsObjInfo &fsInfo)
1189{
1190 QString strAttributes = fsInfo.GetFileAttributes();
1191
1192 if (strAttributes.isEmpty())
1193 return false;
1194
1195 int offSpace = strAttributes.indexOf(' ');
1196 if (offSpace < 0)
1197 offSpace = strAttributes.length();
1198 QString strRight(strAttributes.mid(offSpace + 1).trimmed());
1199
1200 if (strRight.indexOf('H', Qt::CaseSensitive) == -1)
1201 return false;
1202 return true;
1203}
1204
1205void UIFileManagerGuestTable::sltGuestSessionPanelToggled(bool fChecked)
1206{
1207 if (m_pGuestSessionWidget)
1208 m_pGuestSessionWidget->setVisible(fChecked);
1209}
1210
1211void UIFileManagerGuestTable::sltMachineStateChange(const QUuid &uMachineId, const KMachineState enmMachineState)
1212{
1213 if (uMachineId.isNull() || m_comMachine.isNull() || uMachineId != m_comMachine.GetId())
1214 return;
1215
1216 if (enmMachineState == KMachineState_Running)
1217 openMachineSession();
1218 else if (enmMachineState != KMachineState_Paused)
1219 cleanAll();
1220 setStateAndEnableWidgets();
1221}
1222
1223bool UIFileManagerGuestTable::closeMachineSession()
1224{
1225 if (!m_comGuest.isNull())
1226 m_comGuest.detach();
1227
1228 if (!m_comConsole.isNull())
1229 m_comConsole.detach();
1230
1231 if (!m_comSession.isNull())
1232 {
1233 m_comSession.UnlockMachine();
1234 m_comSession.detach();
1235 }
1236 return true;
1237}
1238
1239bool UIFileManagerGuestTable::openMachineSession()
1240{
1241 if (m_comMachine.isNull())
1242 {
1243 emit sigLogOutput("Invalid machine reference", m_strTableName, FileManagerLogType_Error);
1244 return false;
1245 }
1246 m_comSession = uiCommon().openSession(m_comMachine.GetId(), KLockType_Shared);
1247 if (m_comSession.isNull())
1248 {
1249 emit sigLogOutput("Could not open machine session", m_strTableName, FileManagerLogType_Error);
1250 return false;
1251 }
1252
1253 m_comConsole = m_comSession.GetConsole();
1254 if (m_comConsole.isNull())
1255 {
1256 emit sigLogOutput("Machine console is invalid", m_strTableName, FileManagerLogType_Error);
1257 return false;
1258 }
1259
1260 m_comGuest = m_comConsole.GetGuest();
1261 if (m_comGuest.isNull())
1262 {
1263 emit sigLogOutput("Guest reference is invalid", m_strTableName, FileManagerLogType_Error);
1264 return false;
1265 }
1266
1267 /* Prepare guest listener for guest session related events: */
1268 {
1269 QVector<KVBoxEventType> eventTypes;
1270 eventTypes << KVBoxEventType_OnGuestSessionRegistered;
1271 prepareListener(m_pQtGuestListener, m_comGuestListener, m_comGuest.GetEventSource(), eventTypes);
1272 connect(m_pQtGuestListener->getWrapped(), &UIMainEventListener::sigGuestSessionUnregistered,
1273 this, &UIFileManagerGuestTable::sltGuestSessionUnregistered);
1274 connect(m_pQtGuestListener->getWrapped(), &UIMainEventListener::sigGuestSessionRegistered,
1275 this, &UIFileManagerGuestTable::sltGuestSessionRegistered);
1276 }
1277
1278 /* Prepare console listener for guest additions state change events: */
1279 {
1280 QVector<KVBoxEventType> eventTypes;
1281 eventTypes << KVBoxEventType_OnAdditionsStateChanged;
1282 prepareListener(m_pQtConsoleListener, m_comConsoleListener, m_comConsole.GetEventSource(), eventTypes);
1283 connect(m_pQtConsoleListener->getWrapped(), &UIMainEventListener::sigAdditionsChange,
1284 this, &UIFileManagerGuestTable::sltAdditionsStateChange);
1285 }
1286 emit sigLogOutput("Shared machine session opened", m_strTableName, FileManagerLogType_Info);
1287 return true;
1288}
1289
1290int UIFileManagerGuestTable::isGuestAdditionsAvailable(const char* pszMinimumVersion)
1291{
1292 if (m_comGuest.isNull() || !pszMinimumVersion)
1293 return 0;
1294
1295 /* Guest control stuff is in userland: */
1296 if (!m_comGuest.GetAdditionsStatus(KAdditionsRunLevelType_Userland))
1297 return 0;
1298
1299 if (!m_comGuest.isOk())
1300 return 0;
1301
1302 /* Check the related GA facility: */
1303 LONG64 iLastUpdatedIgnored;
1304 if (m_comGuest.GetFacilityStatus(KAdditionsFacilityType_VBoxService, iLastUpdatedIgnored) != KAdditionsFacilityStatus_Active)
1305 return 0;
1306
1307 if (!m_comGuest.isOk())
1308 return 0;
1309
1310 /* Check if GA is new enough to have the goodies: */
1311 QString strGAVersion = m_comGuest.GetAdditionsVersion();
1312 int iCode = RTStrVersionCompare(strGAVersion.toUtf8().constData(), pszMinimumVersion);
1313 if (iCode >= 0)
1314 return 1;
1315 else
1316 return -1;
1317
1318 return 0;
1319}
1320
1321void UIFileManagerGuestTable::cleanupGuestListener()
1322{
1323 if (!m_pQtGuestListener.isNull())
1324 {
1325 m_pQtGuestListener->getWrapped()->disconnect();
1326 if (!m_comGuest.isNull())
1327 cleanupListener(m_pQtGuestListener, m_comGuestListener, m_comGuest.GetEventSource());
1328 }
1329}
1330
1331void UIFileManagerGuestTable::cleanupGuestSessionListener()
1332{
1333 if (!m_pQtSessionListener.isNull())
1334 {
1335 m_pQtSessionListener->getWrapped()->disconnect();
1336 if (!m_comGuestSession.isNull())
1337 cleanupListener(m_pQtSessionListener, m_comSessionListener, m_comGuestSession.GetEventSource());
1338 }
1339}
1340
1341void UIFileManagerGuestTable::cleanupConsoleListener()
1342{
1343 if (!m_pQtConsoleListener.isNull())
1344 {
1345 m_pQtConsoleListener->getWrapped()->disconnect();
1346 if (!m_comConsole.isNull())
1347 cleanupListener(m_pQtConsoleListener, m_comConsoleListener, m_comConsole.GetEventSource());
1348 }
1349}
1350
1351void UIFileManagerGuestTable::prepareListener(ComObjPtr<UIMainEventListenerImpl> &QtListener,
1352 CEventListener &comEventListener,
1353 CEventSource comEventSource, QVector<KVBoxEventType>& eventTypes)
1354{
1355 if (!comEventSource.isOk())
1356 return;
1357 /* Create event listener instance: */
1358 QtListener.createObject();
1359 QtListener->init(new UIMainEventListener, this);
1360 comEventListener = CEventListener(QtListener);
1361
1362 /* Register event listener for CProgress event source: */
1363 comEventSource.RegisterListener(comEventListener, eventTypes, FALSE /* active? */);
1364
1365 /* Register event sources in their listeners as well: */
1366 QtListener->getWrapped()->registerSource(comEventSource, comEventListener);
1367}
1368
1369void UIFileManagerGuestTable::cleanupListener(ComObjPtr<UIMainEventListenerImpl> &QtListener,
1370 CEventListener &comEventListener,
1371 CEventSource comEventSource)
1372{
1373 if (!comEventSource.isOk())
1374 return;
1375 /* Unregister everything: */
1376 QtListener->getWrapped()->unregisterSources();
1377 QtListener.setNull();
1378 /* Make sure VBoxSVC is available: */
1379 if (!gpGlobalSession->isVBoxSVCAvailable())
1380 return;
1381
1382 /* Unregister event listener for CProgress event source: */
1383 comEventSource.UnregisterListener(comEventListener);
1384}
1385
1386void UIFileManagerGuestTable::sltGuestSessionUnregistered(CGuestSession guestSession)
1387{
1388 if (guestSession.isNull())
1389 return;
1390 if (guestSession == m_comGuestSession && !m_comGuestSession.isNull())
1391 {
1392 m_comGuestSession.detach();
1393 emit sigLogOutput("Guest session unregistered", m_strTableName, FileManagerLogType_Info);
1394 }
1395}
1396
1397void UIFileManagerGuestTable::sltGuestSessionRegistered(CGuestSession guestSession)
1398{
1399 if (guestSession == m_comGuestSession && !m_comGuestSession.isNull())
1400 emit sigLogOutput("Guest session registered", m_strTableName, FileManagerLogType_Info);
1401}
1402
1403void UIFileManagerGuestTable::sltGuestSessionStateChanged(const CGuestSessionStateChangedEvent &cEvent)
1404{
1405 if (cEvent.isOk())
1406 {
1407 CVirtualBoxErrorInfo cErrorInfo = cEvent.GetError();
1408 if (cErrorInfo.GetResultDetail() < VINF_SUCCESS)
1409 emit sigLogOutput(cErrorInfo.GetText(), m_strTableName, FileManagerLogType_Error);
1410
1411 if (m_pGuestSessionWidget)
1412 m_pGuestSessionWidget->markForError(cErrorInfo.GetResultDetail() == VERR_AUTHENTICATION_FAILURE);
1413 }
1414
1415 setStateAndEnableWidgets();
1416
1417 if (m_comGuestSession.isNull())
1418 emit sigLogOutput("Guest session is invalid!", m_strTableName, FileManagerLogType_Error);
1419 else
1420 {
1421 if (m_comGuestSession.isOk())
1422 {
1423 emit sigLogOutput(QString("%1: %2").arg("Guest session status has changed").arg(gpConverter->toString(m_comGuestSession.GetStatus())),
1424 m_strTableName, FileManagerLogType_Info);
1425
1426 switch (m_comGuestSession.GetStatus())
1427 {
1428 case KGuestSessionStatus_Started:
1429 {
1430 initFileTable();
1431 break;
1432 }
1433 case KGuestSessionStatus_Terminating:
1434 case KGuestSessionStatus_Terminated:
1435 case KGuestSessionStatus_TimedOutKilled:
1436 case KGuestSessionStatus_TimedOutAbnormally:
1437 case KGuestSessionStatus_Down:
1438 case KGuestSessionStatus_Error:
1439 {
1440 cleanupGuestSessionListener();
1441 closeGuestSession();
1442 break;
1443 }
1444 case KGuestSessionStatus_Undefined:
1445 case KGuestSessionStatus_Starting:
1446 case KGuestSessionStatus_Max:
1447 default:
1448 break;
1449 }
1450 }
1451 else
1452 emit sigLogOutput(UIErrorString::formatErrorInfo(m_comGuestSession), m_strTableName, FileManagerLogType_Error);
1453 }
1454}
1455
1456void UIFileManagerGuestTable::sltOpenGuestSession(QString strUserName, QString strPassword)
1457{
1458 if (strUserName.isEmpty())
1459 {
1460 emit sigLogOutput("No user name is given", m_strTableName, FileManagerLogType_Error);
1461 if (m_pGuestSessionWidget)
1462 m_pGuestSessionWidget->markForError(true);
1463 return;
1464 }
1465 openGuestSession(strUserName, strPassword);
1466}
1467
1468void UIFileManagerGuestTable::toggleForwardBackwardActions()
1469{
1470 if (!m_pNavigationWidget)
1471 return;
1472 if (m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_GoForward))
1473 m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_GoForward)->setEnabled(m_pNavigationWidget->canGoForward());
1474 if (m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_GoBackward))
1475 m_pActionPool->action(UIActionIndex_M_FileManager_S_Guest_GoBackward)->setEnabled(m_pNavigationWidget->canGoBackward());
1476}
1477
1478void UIFileManagerGuestTable::setState()
1479{
1480 if (m_comMachine.isNull())
1481 {
1482 m_enmState = State_InvalidMachineReference;
1483 return;
1484 }
1485 if (m_comMachine.GetState() == KMachineState_Paused)
1486 {
1487 m_enmState = State_MachinePaused;
1488 return;
1489 }
1490 if (m_comMachine.GetState() != KMachineState_Running)
1491 {
1492 m_enmState = State_MachineNotRunning;
1493 return;
1494 }
1495
1496 int iGADetectCode = isGuestAdditionsAvailable(pszMinimumGuestAdditionVersion);
1497 if (iGADetectCode == 0)
1498 {
1499 m_enmState = State_NoGuestAdditions;
1500 return;
1501 }
1502 else if (iGADetectCode == -1)
1503 {
1504 m_enmState = State_GuestAdditionsTooOld;
1505 return;
1506 }
1507
1508 if (!m_comGuestSession.isNull() && m_comGuestSession.GetStatus() == KGuestSessionStatus_Started)
1509 {
1510 m_enmState = State_SessionRunning;
1511 return;
1512 }
1513 if (!m_comGuestSession.isNull() && m_comGuestSession.GetStatus() == KGuestSessionStatus_Error)
1514 {
1515 m_enmState = State_SessionError;
1516 return;
1517 }
1518 m_enmState = State_SessionPossible;
1519}
1520
1521void UIFileManagerGuestTable::setStateAndEnableWidgets()
1522{
1523 setState();
1524 setSessionDependentWidgetsEnabled();
1525 retranslateUi();
1526}
1527
1528void UIFileManagerGuestTable::sltHandleCloseSessionRequest()
1529{
1530 cleanupGuestSessionListener();
1531 closeGuestSession();
1532 setStateAndEnableWidgets();
1533}
1534
1535void UIFileManagerGuestTable::sltCommitDataSignalReceived()
1536{
1537 cleanAll();
1538 if (!m_comMachine.isNull())
1539 m_comMachine.detach();
1540}
1541
1542void UIFileManagerGuestTable::sltAdditionsStateChange()
1543{
1544 setStateAndEnableWidgets();
1545}
1546
1547void UIFileManagerGuestTable::setSessionDependentWidgetsEnabled()
1548{
1549 /* Disable menu actions if guest session is not running: */
1550 UIMenu *pGuestSubmenu = m_pActionPool->action(UIActionIndex_M_FileManager_M_GuestSubmenu)->menu();
1551 if (pGuestSubmenu)
1552 pGuestSubmenu->setEnabled(m_enmState == State_SessionRunning);
1553 UIMenu *pHostSubmenu = m_pActionPool->action(UIActionIndex_M_FileManager_M_HostSubmenu)->menu();
1554 if (pHostSubmenu)
1555 pHostSubmenu->setEnabled(m_enmState == State_SessionRunning);
1556
1557 /*Manage the guest session (login) widget: */
1558 if (m_pGuestSessionWidget)
1559 {
1560 m_pGuestSessionWidget->setLoginWidgetsEnabled(m_enmState == State_SessionPossible ||
1561 m_enmState == State_SessionRunning ||
1562 m_enmState == State_SessionError);
1563 if (m_enmState == State_SessionPossible)
1564 m_pGuestSessionWidget->switchSessionOpenMode();
1565 else if (m_enmState == State_SessionRunning)
1566 m_pGuestSessionWidget->switchSessionCloseMode();
1567 }
1568 /* Call to parent: */
1569 setSessionWidgetsEnabled(m_enmState == State_SessionRunning);
1570
1571 emit sigStateChanged(m_enmState == State_SessionRunning);
1572}
1573
1574bool UIFileManagerGuestTable::isWindowsFileSystem() const
1575{
1576 if (!m_comMachine.isOk())
1577 return false;
1578 return m_comMachine.GetOSTypeId().contains("windows", Qt::CaseInsensitive);
1579}
1580
1581bool UIFileManagerGuestTable::openGuestSession(const QString &strUserName, const QString &strPassword)
1582{
1583 if (m_comGuest.isNull())
1584 {
1585 emit sigLogOutput("Guest reference is invalid", m_strTableName, FileManagerLogType_Error);
1586 return false;
1587 }
1588
1589 int iGADetectCode = isGuestAdditionsAvailable(pszMinimumGuestAdditionVersion);
1590 if (iGADetectCode == 0)
1591 {
1592 emit sigLogOutput("Could not find Guest Additions",
1593 m_strTableName, FileManagerLogType_Error);
1594 if (m_pGuestSessionWidget)
1595 m_pGuestSessionWidget->markForError(true);
1596 return false;
1597 }
1598 else if (iGADetectCode == -1)
1599 {
1600 emit sigLogOutput(QString("%1 %2").arg("The Guest Additions are older than ").arg(pszMinimumGuestAdditionVersion),
1601 m_strTableName, FileManagerLogType_Error);
1602 if (m_pGuestSessionWidget)
1603 m_pGuestSessionWidget->markForError(true);
1604 return false;
1605 }
1606
1607 m_comGuestSession = m_comGuest.CreateSession(strUserName, strPassword,
1608 QString() /* Domain */, "File Manager Session");
1609 if (m_comGuestSession.isNull())
1610 {
1611 emit sigLogOutput("Could not create guest session", m_strTableName, FileManagerLogType_Error);
1612 return false;
1613 }
1614
1615 if (!m_comGuestSession.isOk())
1616 {
1617 emit sigLogOutput(UIErrorString::formatErrorInfo(m_comGuestSession), m_strTableName, FileManagerLogType_Error);
1618 return false;
1619 }
1620
1621 QVector<KVBoxEventType> eventTypes(QVector<KVBoxEventType>() << KVBoxEventType_OnGuestSessionStateChanged);
1622 prepareListener(m_pQtSessionListener, m_comSessionListener, m_comGuestSession.GetEventSource(), eventTypes);
1623 qRegisterMetaType<CGuestSessionStateChangedEvent>();
1624 connect(m_pQtSessionListener->getWrapped(), &UIMainEventListener::sigGuestSessionStatedChanged,
1625 this, &UIFileManagerGuestTable::sltGuestSessionStateChanged);
1626
1627 return true;
1628}
1629
1630void UIFileManagerGuestTable::closeGuestSession()
1631{
1632 if (!m_comGuestSession.isNull())
1633 {
1634 m_comGuestSession.Close();
1635 m_comGuestSession.detach();
1636 emit sigLogOutput("Guest session is closed", m_strTableName, FileManagerLogType_Info);
1637 }
1638 reset();
1639}
1640
1641void UIFileManagerGuestTable::cleanAll()
1642{
1643 cleanupConsoleListener();
1644 cleanupGuestListener();
1645 cleanupGuestSessionListener();
1646
1647 closeGuestSession();
1648 closeMachineSession();
1649}
1650
1651#include "UIFileManagerGuestTable.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