VirtualBox

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

Last change on this file since 103551 was 102928, checked in by vboxsync, 10 months ago

FE/Qt: bugref:6699. Use the old way of populating drive letters in case IGuestSession::getMountPoints throws and error.

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