VirtualBox

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

Last change on this file since 104586 was 104586, checked in by vboxsync, 7 months ago

FE/Qt: bugref:10450: Get rid of pre-5.14 code related to QString/QStringList splitting.

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