VirtualBox

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

Last change on this file since 105081 was 105081, checked in by vboxsync, 3 months ago

FE/Qt: Moving local machine related stuff from UICommon to new UILocalMachineStuff namespace; Reworking GUI to use it accordingly; Dependencies and includes cleanup.

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