VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/guestctrl/UIGuestControlFileTable.cpp@ 75284

Last change on this file since 75284 was 75284, checked in by vboxsync, 6 years ago

FE/Qt: bugref:6699. Modify file manager log related functions to enable different log types

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 42.4 KB
Line 
1/* $Id: UIGuestControlFileTable.cpp 75284 2018-11-06 13:28:12Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIGuestControlFileTable class implementation.
4 */
5
6/*
7 * Copyright (C) 2016-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifdef VBOX_WITH_PRECOMPILED_HEADERS
19# include <precomp.h>
20#else /* !VBOX_WITH_PRECOMPILED_HEADERS */
21
22/* Qt includes: */
23# include <QAction>
24# include <QComboBox>
25# include <QDateTime>
26# include <QDir>
27# include <QHeaderView>
28# include <QItemDelegate>
29# include <QGridLayout>
30# include <QMenu>
31# include <QSortFilterProxyModel>
32# include <QTextEdit>
33# include <QPushButton>
34
35/* GUI includes: */
36# include "QIDialog.h"
37# include "QIDialogButtonBox.h"
38# include "QILabel.h"
39# include "QILineEdit.h"
40# include "QIMessageBox.h"
41# include "UIActionPool.h"
42# include "UIErrorString.h"
43# include "UIGuestFileTable.h"
44# include "UIIconPool.h"
45# include "UIGuestControlFileTable.h"
46# include "UIGuestControlFileModel.h"
47# include "UIToolBar.h"
48
49/* COM includes: */
50# include "CFsObjInfo.h"
51# include "CGuestFsObjInfo.h"
52# include "CGuestDirectory.h"
53# include "CProgress.h"
54
55#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
56
57
58
59/*********************************************************************************************************************************
60* UIGuestControlFileView definition. *
61*********************************************************************************************************************************/
62
63/** Using QITableView causes the following problem when I click on the table items
64 Qt WARNING: Cannot creat accessible child interface for object: UIGuestControlFileView.....
65 so for now subclass QTableView */
66class UIGuestControlFileView : public QTableView
67{
68
69 Q_OBJECT;
70
71signals:
72
73 void sigSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected);
74
75public:
76
77 UIGuestControlFileView(QWidget * parent = 0);
78 bool hasSelection() const;
79
80protected:
81
82 virtual void selectionChanged(const QItemSelection & selected, const QItemSelection & deselected) /*override */;
83
84private:
85
86 void configure();
87 QWidget *m_pParent;
88};
89
90
91/*********************************************************************************************************************************
92* UIFileDelegate definition. *
93*********************************************************************************************************************************/
94/** A QItemDelegate child class to disable dashed lines drawn around selected cells in QTableViews */
95class UIFileDelegate : public QItemDelegate
96{
97
98 Q_OBJECT;
99
100protected:
101 virtual void drawFocus ( QPainter * /*painter*/, const QStyleOptionViewItem & /*option*/, const QRect & /*rect*/ ) const {}
102};
103
104
105/*********************************************************************************************************************************
106* UIFileStringInputDialog definition. *
107*********************************************************************************************************************************/
108
109/** A QIDialog child including a line edit whose text exposed when the dialog is accepted */
110class UIStringInputDialog : public QIDialog
111{
112
113 Q_OBJECT;
114
115public:
116
117 UIStringInputDialog(QWidget *pParent = 0, Qt::WindowFlags flags = 0);
118 QString getString() const;
119
120private:
121
122 QILineEdit *m_pLineEdit;
123
124};
125
126
127/*********************************************************************************************************************************
128* UIHostDirectoryDiskUsageComputer implementation. *
129*********************************************************************************************************************************/
130
131UIDirectoryDiskUsageComputer::UIDirectoryDiskUsageComputer(QObject *parent, QStringList pathList)
132 :QThread(parent)
133 , m_pathList(pathList)
134 , m_fOkToContinue(true)
135{
136}
137
138void UIDirectoryDiskUsageComputer::run()
139{
140 for (int i = 0; i < m_pathList.size(); ++i)
141 directoryStatisticsRecursive(m_pathList[i], m_resultStatistics);
142}
143
144void UIDirectoryDiskUsageComputer::stopRecursion()
145{
146 m_mutex.lock();
147 m_fOkToContinue = false;
148 m_mutex.unlock();
149}
150
151bool UIDirectoryDiskUsageComputer::isOkToContinue() const
152{
153 return m_fOkToContinue;
154}
155
156
157/*********************************************************************************************************************************
158* UIPathOperations implementation. *
159*********************************************************************************************************************************/
160
161const QChar UIPathOperations::delimiter = QChar('/');
162const QChar UIPathOperations::dosDelimiter = QChar('\\');
163
164/* static */ QString UIPathOperations::removeMultipleDelimiters(const QString &path)
165{
166 QString newPath(path);
167 QString doubleDelimiter(2, delimiter);
168
169 while (newPath.contains(doubleDelimiter) && !newPath.isEmpty())
170 newPath = newPath.replace(doubleDelimiter, delimiter);
171 return newPath;
172}
173
174/* static */ QString UIPathOperations::removeTrailingDelimiters(const QString &path)
175{
176 if (path.isNull() || path.isEmpty())
177 return QString();
178 QString newPath(path);
179 /* Make sure for we dont have any trailing delimiters: */
180 while (newPath.length() > 1 && newPath.at(newPath.length() - 1) == UIPathOperations::delimiter)
181 newPath.chop(1);
182 return newPath;
183}
184
185/* static */ QString UIPathOperations::addTrailingDelimiters(const QString &path)
186{
187 if (path.isNull() || path.isEmpty())
188 return QString();
189 QString newPath(path);
190 while (newPath.length() > 1 && newPath.at(newPath.length() - 1) != UIPathOperations::delimiter)
191 newPath += UIPathOperations::delimiter;
192 return newPath;
193}
194
195/* static */ QString UIPathOperations::addStartDelimiter(const QString &path)
196{
197 if (path.isEmpty())
198 return QString(path);
199 QString newPath(path);
200
201 if (doesPathStartWithDriveLetter(newPath))
202 {
203 if (newPath.at(newPath.length() - 1) != delimiter)
204 newPath += delimiter;
205 return newPath;
206 }
207 if (newPath.at(0) != delimiter)
208 newPath.insert(0, delimiter);
209 return newPath;
210}
211
212/* static */ QString UIPathOperations::sanitize(const QString &path)
213{
214 //return addStartDelimiter(removeTrailingDelimiters(removeMultipleDelimiters(path)));
215 QString newPath = addStartDelimiter(removeTrailingDelimiters(removeMultipleDelimiters(path))).replace(dosDelimiter, delimiter);
216 return newPath;
217}
218
219/* static */ QString UIPathOperations::mergePaths(const QString &path, const QString &baseName)
220{
221 QString newBase(baseName);
222 newBase = newBase.remove(delimiter);
223
224 /* make sure we have one and only one trailing '/': */
225 QString newPath(sanitize(path));
226 if(newPath.isEmpty())
227 newPath = delimiter;
228 if(newPath.at(newPath.length() - 1) != delimiter)
229 newPath += UIPathOperations::delimiter;
230 newPath += newBase;
231 return sanitize(newPath);
232}
233
234/* static */ QString UIPathOperations::getObjectName(const QString &path)
235{
236 if (path.length() <= 1)
237 return QString(path);
238
239 QString strTemp(sanitize(path));
240 if (strTemp.length() < 2)
241 return strTemp;
242 int lastSlashPosition = strTemp.lastIndexOf(UIPathOperations::delimiter);
243 if (lastSlashPosition == -1)
244 return QString();
245 return strTemp.right(strTemp.length() - lastSlashPosition - 1);
246}
247
248/* static */ QString UIPathOperations::getPathExceptObjectName(const QString &path)
249{
250 if (path.length() <= 1)
251 return QString(path);
252
253 QString strTemp(sanitize(path));
254 int lastSlashPosition = strTemp.lastIndexOf(UIPathOperations::delimiter);
255 if (lastSlashPosition == -1)
256 return QString();
257 return strTemp.left(lastSlashPosition + 1);
258}
259
260/* static */ QString UIPathOperations::constructNewItemPath(const QString &previousPath, const QString &newBaseName)
261{
262 if (previousPath.length() <= 1)
263 return QString(previousPath);
264 return sanitize(mergePaths(getPathExceptObjectName(previousPath), newBaseName));
265}
266
267/* static */ QStringList UIPathOperations::pathTrail(const QString &path)
268{
269 QStringList pathList = path.split(UIPathOperations::delimiter, QString::SkipEmptyParts);
270 if (!pathList.isEmpty() && doesPathStartWithDriveLetter(pathList[0]))
271 {
272 pathList[0] = addTrailingDelimiters(pathList[0]);
273 }
274 return pathList;
275}
276
277/* static */ bool UIPathOperations::doesPathStartWithDriveLetter(const QString &path)
278{
279 if (path.length() < 2)
280 return false;
281 /* search for ':' with the path: */
282 if (!path[0].isLetter())
283 return false;
284 if (path[1] != ':')
285 return false;
286 return true;
287}
288
289
290/*********************************************************************************************************************************
291* UIGuestControlFileView implementation. *
292*********************************************************************************************************************************/
293
294UIGuestControlFileView::UIGuestControlFileView(QWidget *parent)
295 :QTableView(parent)
296 , m_pParent(parent)
297{
298 configure();
299}
300
301void UIGuestControlFileView::configure()
302{
303 setContextMenuPolicy(Qt::CustomContextMenu);
304 setShowGrid(false);
305 setSelectionBehavior(QAbstractItemView::SelectRows);
306 verticalHeader()->setVisible(false);
307 setEditTriggers(QAbstractItemView::NoEditTriggers);
308 /* Minimize the row height: */
309 verticalHeader()->setDefaultSectionSize(verticalHeader()->minimumSectionSize());
310 setAlternatingRowColors(true);
311 installEventFilter(m_pParent);
312}
313
314bool UIGuestControlFileView::hasSelection() const
315{
316 QItemSelectionModel *pSelectionModel = selectionModel();
317 if (!pSelectionModel)
318 return false;
319 return pSelectionModel->hasSelection();
320}
321
322void UIGuestControlFileView::selectionChanged(const QItemSelection & selected, const QItemSelection & deselected)
323{
324 emit sigSelectionChanged(selected, deselected);
325 QTableView::selectionChanged(selected, deselected);
326}
327
328
329/*********************************************************************************************************************************
330* UIFileStringInputDialog implementation. *
331*********************************************************************************************************************************/
332
333UIStringInputDialog::UIStringInputDialog(QWidget *pParent /* = 0 */, Qt::WindowFlags flags /* = 0 */)
334 :QIDialog(pParent, flags)
335{
336 QVBoxLayout *layout = new QVBoxLayout(this);
337 m_pLineEdit = new QILineEdit(this);
338 layout->addWidget(m_pLineEdit);
339
340 QIDialogButtonBox *pButtonBox =
341 new QIDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
342 layout->addWidget(pButtonBox);
343 // {
344 // /* Configure button-box: */
345 connect(pButtonBox, &QIDialogButtonBox::accepted, this, &UIStringInputDialog::accept);
346 connect(pButtonBox, &QIDialogButtonBox::rejected, this, &UIStringInputDialog::reject);
347
348}
349
350QString UIStringInputDialog::getString() const
351{
352 if (!m_pLineEdit)
353 return QString();
354 return m_pLineEdit->text();
355}
356
357
358/*********************************************************************************************************************************
359* UIPropertiesDialog implementation. *
360*********************************************************************************************************************************/
361
362UIPropertiesDialog::UIPropertiesDialog(QWidget *pParent, Qt::WindowFlags flags)
363 :QIDialog(pParent, flags)
364 , m_pMainLayout(new QVBoxLayout)
365 , m_pInfoEdit(new QTextEdit)
366{
367 setLayout(m_pMainLayout);
368
369 if (m_pMainLayout)
370 m_pMainLayout->addWidget(m_pInfoEdit);
371 if (m_pInfoEdit)
372 {
373 m_pInfoEdit->setReadOnly(true);
374 m_pInfoEdit->setFrameStyle(QFrame::NoFrame);
375 }
376 QIDialogButtonBox *pButtonBox =
377 new QIDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, this);
378 m_pMainLayout->addWidget(pButtonBox);
379 connect(pButtonBox, &QIDialogButtonBox::accepted, this, &UIStringInputDialog::accept);
380}
381
382void UIPropertiesDialog::setPropertyText(const QString &strProperty)
383{
384 if (!m_pInfoEdit)
385 return;
386 m_strProperty = strProperty;
387 m_pInfoEdit->setHtml(strProperty);
388}
389
390void UIPropertiesDialog::addDirectoryStatistics(UIDirectoryStatistics directoryStatistics)
391{
392 if (!m_pInfoEdit)
393 return;
394 // QString propertyString = m_pInfoEdit->toHtml();
395 // propertyString += "<b>Total Size:</b> " + QString::number(directoryStatistics.m_totalSize) + QString(" bytes");
396 // if (directoryStatistics.m_totalSize >= UIGuestControlFileTable::m_iKiloByte)
397 // propertyString += " (" + UIGuestControlFileTable::humanReadableSize(directoryStatistics.m_totalSize) + ")";
398 // propertyString += "<br/>";
399 // propertyString += "<b>File Count:</b> " + QString::number(directoryStatistics.m_uFileCount);
400
401 // m_pInfoEdit->setHtml(propertyString);
402
403 QString detailsString(m_strProperty);
404 detailsString += "<br/>";
405 detailsString += "<b>Total Size:</b> " + QString::number(directoryStatistics.m_totalSize) + QString(" bytes");
406 if (directoryStatistics.m_totalSize >= UIGuestControlFileTable::m_iKiloByte)
407 detailsString += " (" + UIGuestControlFileTable::humanReadableSize(directoryStatistics.m_totalSize) + ")";
408 detailsString += "<br/>";
409
410 detailsString += "<b>File Count:</b> " + QString::number(directoryStatistics.m_uFileCount);
411
412 m_pInfoEdit->setHtml(detailsString);
413
414}
415
416/*********************************************************************************************************************************
417* UIDirectoryStatistics implementation.
418 *
419*********************************************************************************************************************************/
420
421UIDirectoryStatistics::UIDirectoryStatistics()
422 : m_totalSize(0)
423 , m_uFileCount(0)
424 , m_uDirectoryCount(0)
425 , m_uSymlinkCount(0)
426{
427}
428
429
430/*********************************************************************************************************************************
431* UIFileTableItem implementation. *
432*********************************************************************************************************************************/
433
434UIFileTableItem::UIFileTableItem(const QList<QVariant> &data,
435 UIFileTableItem *parent, FileObjectType type)
436 : m_itemData(data)
437 , m_parentItem(parent)
438 , m_bIsOpened(false)
439 , m_isTargetADirectory(false)
440 , m_type(type)
441 , m_isDriveItem(false)
442{
443}
444
445UIFileTableItem::~UIFileTableItem()
446{
447 qDeleteAll(m_childItems);
448 m_childItems.clear();
449}
450
451void UIFileTableItem::appendChild(UIFileTableItem *item)
452{
453 if (!item)
454 return;
455 m_childItems.append(item);
456
457 m_childMap.insert(item->name(), item);
458}
459
460UIFileTableItem *UIFileTableItem::child(int row) const
461{
462 return m_childItems.value(row);
463}
464
465UIFileTableItem *UIFileTableItem::child(const QString &path) const
466{
467 if (!m_childMap.contains(path))
468 return 0;
469 return m_childMap.value(path);
470}
471
472int UIFileTableItem::childCount() const
473{
474 return m_childItems.count();
475}
476
477int UIFileTableItem::columnCount() const
478{
479 return m_itemData.count();
480}
481
482QVariant UIFileTableItem::data(int column) const
483{
484 return m_itemData.value(column);
485}
486
487QString UIFileTableItem::name() const
488{
489 if (m_itemData.isEmpty() || !m_itemData[0].canConvert(QMetaType::QString))
490 return QString();
491 return m_itemData[0].toString();
492}
493
494void UIFileTableItem::setData(const QVariant &data, int index)
495{
496 if (index >= m_itemData.length())
497 return;
498 m_itemData[index] = data;
499}
500
501UIFileTableItem *UIFileTableItem::parentItem()
502{
503 return m_parentItem;
504}
505
506int UIFileTableItem::row() const
507{
508 if (m_parentItem)
509 return m_parentItem->m_childItems.indexOf(const_cast<UIFileTableItem*>(this));
510 return 0;
511}
512
513bool UIFileTableItem::isDirectory() const
514{
515 return m_type == FileObjectType_Directory;
516}
517
518bool UIFileTableItem::isSymLink() const
519{
520 return m_type == FileObjectType_SymLink;
521}
522
523bool UIFileTableItem::isFile() const
524{
525 return m_type == FileObjectType_File;
526}
527
528void UIFileTableItem::clearChildren()
529{
530 qDeleteAll(m_childItems);
531 m_childItems.clear();
532 m_childMap.clear();
533}
534
535bool UIFileTableItem::isOpened() const
536{
537 return m_bIsOpened;
538}
539
540void UIFileTableItem::setIsOpened(bool flag)
541{
542 m_bIsOpened = flag;
543}
544
545const QString &UIFileTableItem::path() const
546{
547 return m_strPath;
548}
549
550void UIFileTableItem::setPath(const QString &path)
551{
552 if (path.isNull() || path.isEmpty())
553 return;
554 m_strPath = path;
555 UIPathOperations::removeTrailingDelimiters(m_strPath);
556}
557
558bool UIFileTableItem::isUpDirectory() const
559{
560 if (!isDirectory())
561 return false;
562 if (data(0) == UIGuestControlFileModel::strUpDirectoryString)
563 return true;
564 return false;
565}
566
567FileObjectType UIFileTableItem::type() const
568{
569 return m_type;
570}
571
572const QString &UIFileTableItem::targetPath() const
573{
574 return m_strTargetPath;
575}
576
577void UIFileTableItem::setTargetPath(const QString &path)
578{
579 m_strTargetPath = path;
580}
581
582bool UIFileTableItem::isTargetADirectory() const
583{
584 return m_isTargetADirectory;
585}
586
587void UIFileTableItem::setIsTargetADirectory(bool flag)
588{
589 m_isTargetADirectory = flag;
590}
591
592void UIFileTableItem::setIsDriveItem(bool flag)
593{
594 m_isDriveItem = flag;
595}
596
597bool UIFileTableItem::isDriveItem() const
598{
599 return m_isDriveItem;
600}
601
602
603/*********************************************************************************************************************************
604* UIGuestControlFileTable implementation. *
605*********************************************************************************************************************************/
606const unsigned UIGuestControlFileTable::m_iKiloByte = 1000;
607UIGuestControlFileTable::UIGuestControlFileTable(UIActionPool *pActionPool, QWidget *pParent /* = 0 */)
608 :QIWithRetranslateUI<QWidget>(pParent)
609 , m_pRootItem(0)
610 , m_pLocationLabel(0)
611 , m_pPropertiesDialog(0)
612 , m_pActionPool(pActionPool)
613 , m_pToolBar(0)
614 , m_pModel(0)
615 , m_pView(0)
616 , m_pProxyModel(0)
617 , m_pMainLayout(0)
618 , m_pLocationComboBox(0)
619{
620 prepareObjects();
621}
622
623UIGuestControlFileTable::~UIGuestControlFileTable()
624{
625 delete m_pRootItem;
626}
627
628void UIGuestControlFileTable::reset()
629{
630 if (m_pModel)
631 m_pModel->beginReset();
632 delete m_pRootItem;
633 m_pRootItem = 0;
634 if (m_pModel)
635 m_pModel->endReset();
636 if (m_pLocationComboBox)
637 {
638 disconnect(m_pLocationComboBox, static_cast<void(QComboBox::*)(const QString&)>(&QComboBox::currentIndexChanged),
639 this, &UIGuestControlFileTable::sltLocationComboCurrentChange);
640 m_pLocationComboBox->clear();
641 connect(m_pLocationComboBox, static_cast<void(QComboBox::*)(const QString&)>(&QComboBox::currentIndexChanged),
642 this, &UIGuestControlFileTable::sltLocationComboCurrentChange);
643 }
644}
645
646void UIGuestControlFileTable::emitLogOutput(const QString& strOutput, FileManagerLogType eLogType)
647{
648 emit sigLogOutput(strOutput, eLogType);
649}
650
651void UIGuestControlFileTable::prepareObjects()
652{
653 m_pMainLayout = new QGridLayout();
654 if (!m_pMainLayout)
655 return;
656 m_pMainLayout->setSpacing(0);
657 m_pMainLayout->setContentsMargins(0, 0, 0, 0);
658 setLayout(m_pMainLayout);
659
660 m_pToolBar = new UIToolBar;
661 if (m_pToolBar)
662 {
663 m_pMainLayout->addWidget(m_pToolBar, 0, 0, 1, 5);
664 }
665
666 m_pLocationLabel = new QILabel;
667 if (m_pLocationLabel)
668 {
669 m_pMainLayout->addWidget(m_pLocationLabel, 1, 0, 1, 1);
670 }
671
672 m_pLocationComboBox = new QComboBox;
673 if (m_pLocationComboBox)
674 {
675 m_pMainLayout->addWidget(m_pLocationComboBox, 1, 1, 1, 4);
676 m_pLocationComboBox->setEditable(false);
677 connect(m_pLocationComboBox, static_cast<void(QComboBox::*)(const QString&)>(&QComboBox::currentIndexChanged),
678 this, &UIGuestControlFileTable::sltLocationComboCurrentChange);
679 }
680
681
682 m_pModel = new UIGuestControlFileModel(this);
683 if (!m_pModel)
684 return;
685
686 m_pProxyModel = new UIGuestControlFileProxyModel(this);
687 if (!m_pProxyModel)
688 return;
689 m_pProxyModel->setSourceModel(m_pModel);
690
691 m_pView = new UIGuestControlFileView(this);
692 if (m_pView)
693 {
694 m_pMainLayout->addWidget(m_pView, 2, 0, 5, 5);
695 m_pView->setModel(m_pProxyModel);
696 m_pView->setItemDelegate(new UIFileDelegate);
697 m_pView->setSortingEnabled(true);
698 m_pView->sortByColumn(0, Qt::AscendingOrder);
699
700 connect(m_pView, &UIGuestControlFileView::doubleClicked,
701 this, &UIGuestControlFileTable::sltItemDoubleClicked);
702 connect(m_pView, &UIGuestControlFileView::clicked,
703 this, &UIGuestControlFileTable::sltItemClicked);
704 connect(m_pView, &UIGuestControlFileView::sigSelectionChanged,
705 this, &UIGuestControlFileTable::sltSelectionChanged);
706 connect(m_pView, &UIGuestControlFileView::customContextMenuRequested,
707 this, &UIGuestControlFileTable::sltCreateFileViewContextMenu);
708
709 }
710 m_pSearchLineEdit = new QILineEdit;
711 if (m_pSearchLineEdit)
712 {
713 m_pMainLayout->addWidget(m_pSearchLineEdit, 8, 0, 1, 5);
714 m_pSearchLineEdit->hide();
715 m_pSearchLineEdit->setClearButtonEnabled(true);
716 connect(m_pSearchLineEdit, &QLineEdit::textChanged,
717 this, &UIGuestControlFileTable::sltSearchTextChanged);
718 }
719}
720
721void UIGuestControlFileTable::updateCurrentLocationEdit(const QString& strLocation)
722{
723 if (!m_pLocationComboBox)
724 return;
725 int itemIndex = m_pLocationComboBox->findText(strLocation,
726 Qt::MatchExactly | Qt::MatchCaseSensitive);
727 if (itemIndex == -1)
728 {
729 m_pLocationComboBox->insertItem(m_pLocationComboBox->count(), strLocation);
730 itemIndex = m_pLocationComboBox->count() - 1;
731 }
732 m_pLocationComboBox->setCurrentIndex(itemIndex);
733}
734
735void UIGuestControlFileTable::changeLocation(const QModelIndex &index)
736{
737 if (!index.isValid() || !m_pView)
738 return;
739 m_pView->setRootIndex(m_pProxyModel->mapFromSource(index));
740 m_pView->clearSelection();
741
742 UIFileTableItem *item = static_cast<UIFileTableItem*>(index.internalPointer());
743 if (item)
744 {
745 updateCurrentLocationEdit(item->path());
746 }
747 /** @todo check if we really need this and if not remove it */
748 //m_pModel->signalUpdate();
749}
750
751void UIGuestControlFileTable::initializeFileTree()
752{
753 if (m_pRootItem)
754 reset();
755
756 /* Root item: */
757 const QString startPath("/");
758 QList<QVariant> headData;
759 headData << "Name" << "Size" << "Change Time" << "Owner" << "Permissions";
760 m_pRootItem = new UIFileTableItem(headData, 0, FileObjectType_Directory);
761 QList<QVariant> startDirData;
762 startDirData << startPath << 4096 << QDateTime() << "" << "";
763 UIFileTableItem* startItem = new UIFileTableItem(startDirData, m_pRootItem, FileObjectType_Directory);
764
765 startItem->setPath(startPath);
766 m_pRootItem->appendChild(startItem);
767 startItem->setIsOpened(false);
768 populateStartDirectory(startItem);
769
770 m_pModel->signalUpdate();
771 updateCurrentLocationEdit(startPath);
772 m_pView->setRootIndex(m_pProxyModel->mapFromSource(m_pModel->rootIndex()));
773}
774
775void UIGuestControlFileTable::populateStartDirectory(UIFileTableItem *startItem)
776{
777 determineDriveLetters();
778 if (m_driveLetterList.isEmpty())
779 {
780 /* Read the root directory and get the list: */
781 readDirectory(startItem->path(), startItem, true);
782 }
783 else
784 {
785 for (int i = 0; i < m_driveLetterList.size(); ++i)
786 {
787 QList<QVariant> data;
788
789 data << m_driveLetterList[i] << 4096 << QDateTime() << "";
790 UIFileTableItem* driveItem = new UIFileTableItem(data, startItem, FileObjectType_Directory);
791 driveItem->setPath(m_driveLetterList[i]);
792 startItem->appendChild(driveItem);
793 driveItem->setIsOpened(false);
794 driveItem->setIsDriveItem(true);
795 startItem->setIsOpened(true);
796 }
797 }
798}
799
800void UIGuestControlFileTable::insertItemsToTree(QMap<QString,UIFileTableItem*> &map,
801 UIFileTableItem *parent, bool isDirectoryMap, bool isStartDir)
802{
803 if (parent)
804
805 /* Make sure we have an item representing up directory, and make sure it is not there for the start dir: */
806 if (isDirectoryMap)
807 {
808 if (!map.contains(UIGuestControlFileModel::strUpDirectoryString) && !isStartDir)
809 {
810 QList<QVariant> data;
811 data << UIGuestControlFileModel::strUpDirectoryString << 4096 << "";
812 UIFileTableItem *item = new UIFileTableItem(data, parent, FileObjectType_Directory);
813 item->setIsOpened(false);
814 map.insert(UIGuestControlFileModel::strUpDirectoryString, item);
815 }
816 else if (map.contains(UIGuestControlFileModel::strUpDirectoryString) && isStartDir)
817 {
818 map.remove(UIGuestControlFileModel::strUpDirectoryString);
819 }
820 }
821 for (QMap<QString,UIFileTableItem*>::const_iterator iterator = map.begin();
822 iterator != map.end(); ++iterator)
823 {
824 if (iterator.key() == "." || iterator.key().isEmpty())
825 continue;
826 parent->appendChild(iterator.value());
827 }
828}
829
830void UIGuestControlFileTable::sltItemDoubleClicked(const QModelIndex &index)
831{
832 if (!index.isValid() || !m_pModel || !m_pView)
833 return;
834 QModelIndex nIndex = m_pProxyModel ? m_pProxyModel->mapToSource(index) : index;
835 goIntoDirectory(nIndex);
836}
837
838void UIGuestControlFileTable::sltItemClicked(const QModelIndex &index)
839{
840 Q_UNUSED(index);
841 disableSelectionSearch();
842}
843
844void UIGuestControlFileTable::sltGoUp()
845{
846 if (!m_pView || !m_pModel)
847 return;
848 QModelIndex currentRoot = currentRootIndex();
849
850 if (!currentRoot.isValid())
851 return;
852 if (currentRoot != m_pModel->rootIndex())
853 {
854 QModelIndex parentIndex = currentRoot.parent();
855 if (parentIndex.isValid())
856 {
857 changeLocation(currentRoot.parent());
858 m_pView->selectRow(currentRoot.row());
859 }
860 }
861}
862
863void UIGuestControlFileTable::sltGoHome()
864{
865 goToHomeDirectory();
866}
867
868void UIGuestControlFileTable::sltRefresh()
869{
870 refresh();
871}
872
873void UIGuestControlFileTable::goIntoDirectory(const QModelIndex &itemIndex)
874{
875 if (!m_pModel)
876 return;
877
878 /* Make sure the colum is 0: */
879 QModelIndex index = m_pModel->index(itemIndex.row(), 0, itemIndex.parent());
880 if (!index.isValid())
881 return;
882
883 UIFileTableItem *item = static_cast<UIFileTableItem*>(index.internalPointer());
884 if (!item)
885 return;
886
887 /* check if we need to go up: */
888 if (item->isUpDirectory())
889 {
890 QModelIndex parentIndex = m_pModel->parent(m_pModel->parent(index));
891 if (parentIndex.isValid())
892 changeLocation(parentIndex);
893 return;
894 }
895
896 if (!item->isDirectory())
897 return;
898 if (!item->isOpened())
899 readDirectory(item->path(),item);
900 changeLocation(index);
901}
902
903void UIGuestControlFileTable::goIntoDirectory(const QStringList &pathTrail)
904{
905 UIFileTableItem *parent = getStartDirectoryItem();
906
907 for(int i = 0; i < pathTrail.size(); ++i)
908 {
909 if (!parent)
910 return;
911 /* Make sure parent is already opened: */
912 if (!parent->isOpened())
913 readDirectory(parent->path(), parent, parent == getStartDirectoryItem());
914 /* search the current path item among the parent's children: */
915 UIFileTableItem *item = parent->child(pathTrail.at(i));
916 if (!item)
917 return;
918 parent = item;
919 }
920 if (!parent)
921 return;
922 if (!parent->isOpened())
923 readDirectory(parent->path(), parent, parent == getStartDirectoryItem());
924 goIntoDirectory(parent);
925}
926
927void UIGuestControlFileTable::goIntoDirectory(UIFileTableItem *item)
928{
929 if (!item || !m_pModel)
930 return;
931 goIntoDirectory(m_pModel->index(item));
932}
933
934UIFileTableItem* UIGuestControlFileTable::indexData(const QModelIndex &index) const
935{
936 if (!index.isValid())
937 return 0;
938 return static_cast<UIFileTableItem*>(index.internalPointer());
939}
940
941void UIGuestControlFileTable::refresh()
942{
943 if (!m_pView || !m_pModel)
944 return;
945 QModelIndex currentIndex = currentRootIndex();
946
947 UIFileTableItem *treeItem = indexData(currentIndex);
948 if (!treeItem)
949 return;
950 bool isRootDir = (m_pModel->rootIndex() == currentIndex);
951 m_pModel->beginReset();
952 /* For now we clear the whole subtree (that isrecursively) which is an overkill: */
953 treeItem->clearChildren();
954 if (isRootDir)
955 populateStartDirectory(treeItem);
956 else
957 readDirectory(treeItem->path(), treeItem, isRootDir);
958 m_pModel->endReset();
959 m_pView->setRootIndex(m_pProxyModel->mapFromSource(currentIndex));
960 setSelectionDependentActionsEnabled(m_pView->hasSelection());
961}
962
963void UIGuestControlFileTable::relist()
964{
965 if (!m_pProxyModel)
966 return;
967 m_pProxyModel->invalidate();
968}
969
970void UIGuestControlFileTable::sltDelete()
971{
972 if (!m_pView || !m_pModel)
973 return;
974 QItemSelectionModel *selectionModel = m_pView->selectionModel();
975 if (!selectionModel)
976 return;
977
978 QModelIndexList selectedItemIndices = selectionModel->selectedRows();
979 for(int i = 0; i < selectedItemIndices.size(); ++i)
980 {
981 QModelIndex index =
982 m_pProxyModel ? m_pProxyModel->mapToSource(selectedItemIndices.at(i)) : selectedItemIndices.at(i);
983 deleteByIndex(index);
984 }
985 /** @todo dont refresh here, just delete the rows and update the table view: */
986 refresh();
987}
988
989void UIGuestControlFileTable::sltRename()
990{
991 if (!m_pView)
992 return;
993 QItemSelectionModel *selectionModel = m_pView->selectionModel();
994 if (!selectionModel)
995 return;
996
997 QModelIndexList selectedItemIndices = selectionModel->selectedRows();
998 if (selectedItemIndices.size() == 0)
999 return;
1000 QModelIndex modelIndex =
1001 m_pProxyModel ? m_pProxyModel->mapToSource(selectedItemIndices.at(0)) : selectedItemIndices.at(0);
1002 UIFileTableItem *item = indexData(modelIndex);
1003 if (!item || item->isUpDirectory())
1004 return;
1005 m_pView->edit(selectedItemIndices.at(0));
1006}
1007
1008void UIGuestControlFileTable::sltCreateNewDirectory()
1009{
1010 if (!m_pModel || !m_pView)
1011 return;
1012 QModelIndex currentIndex = currentRootIndex();
1013 if (!currentIndex.isValid())
1014 return;
1015 UIFileTableItem *item = static_cast<UIFileTableItem*>(currentIndex.internalPointer());
1016 if (!item)
1017 return;
1018
1019 QString newDirectoryName = getNewDirectoryName();
1020 if (newDirectoryName.isEmpty())
1021 return;
1022
1023 if (createDirectory(item->path(), newDirectoryName))
1024 {
1025 /** @todo instead of refreshing here (an overkill) just add the
1026 rows and update the tabel view: */
1027 sltRefresh();
1028 }
1029}
1030
1031void UIGuestControlFileTable::sltCopy()
1032{
1033
1034 m_copyCutBuffer = selectedItemPathList();
1035 // if (!m_copyCutBuffer.isEmpty())
1036 // m_pPaste->setEnabled(true);
1037 // else
1038 // m_pPaste->setEnabled(false);
1039}
1040
1041void UIGuestControlFileTable::sltCut()
1042{
1043 m_copyCutBuffer = selectedItemPathList();
1044 // if (!m_copyCutBuffer.isEmpty())
1045 // m_pPaste->setEnabled(true);
1046 // else
1047 // m_pPaste->setEnabled(false);
1048}
1049
1050void UIGuestControlFileTable::sltPaste()
1051{
1052 // paste them
1053 m_copyCutBuffer.clear();
1054 //m_pPaste->setEnabled(false);
1055}
1056
1057void UIGuestControlFileTable::sltShowProperties()
1058{
1059 showProperties();
1060}
1061
1062void UIGuestControlFileTable::sltSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected)
1063{
1064 Q_UNUSED(selected);
1065 Q_UNUSED(deselected);
1066 setSelectionDependentActionsEnabled(m_pView->hasSelection());
1067}
1068
1069void UIGuestControlFileTable::sltLocationComboCurrentChange(const QString &strLocation)
1070{
1071 QString comboLocation(UIPathOperations::sanitize(strLocation));
1072 if (comboLocation == currentDirectoryPath())
1073 return;
1074 goIntoDirectory(UIPathOperations::pathTrail(comboLocation));
1075}
1076
1077void UIGuestControlFileTable::sltSelectAll()
1078{
1079 if (!m_pModel || !m_pView)
1080 return;
1081 m_pView->selectAll();
1082 deSelectUpDirectoryItem();
1083}
1084
1085void UIGuestControlFileTable::sltInvertSelection()
1086{
1087 setSelectionForAll(QItemSelectionModel::Toggle | QItemSelectionModel::Rows);
1088 deSelectUpDirectoryItem();
1089}
1090
1091void UIGuestControlFileTable::sltSearchTextChanged(const QString &strText)
1092{
1093 performSelectionSearch(strText);
1094}
1095
1096void UIGuestControlFileTable::sltCreateFileViewContextMenu(const QPoint &point)
1097{
1098 QWidget *pSender = qobject_cast<QWidget*>(sender());
1099 if (!pSender)
1100 return;
1101 createFileViewContextMenu(pSender, point);
1102}
1103
1104void UIGuestControlFileTable::deSelectUpDirectoryItem()
1105{
1106 if (!m_pView)
1107 return;
1108 QItemSelectionModel *pSelectionModel = m_pView->selectionModel();
1109 if (!pSelectionModel)
1110 return;
1111 QModelIndex currentRoot = currentRootIndex();
1112 if (!currentRoot.isValid())
1113 return;
1114
1115 /* Make sure that "up directory item" (if exists) is deselected: */
1116 for (int i = 0; i < m_pModel->rowCount(currentRoot); ++i)
1117 {
1118 QModelIndex index = m_pModel->index(i, 0, currentRoot);
1119 if (!index.isValid())
1120 continue;
1121
1122 UIFileTableItem *item = static_cast<UIFileTableItem*>(index.internalPointer());
1123 if (item && item->isUpDirectory())
1124 {
1125 QModelIndex indexToDeselect = m_pProxyModel ? m_pProxyModel->mapFromSource(index) : index;
1126 pSelectionModel->select(indexToDeselect, QItemSelectionModel::Deselect | QItemSelectionModel::Rows);
1127 }
1128 }
1129}
1130
1131void UIGuestControlFileTable::setSelectionForAll(QItemSelectionModel::SelectionFlags flags)
1132{
1133 if (!m_pView)
1134 return;
1135 QItemSelectionModel *pSelectionModel = m_pView->selectionModel();
1136 if (!pSelectionModel)
1137 return;
1138 QModelIndex currentRoot = currentRootIndex();
1139 if (!currentRoot.isValid())
1140 return;
1141
1142 for (int i = 0; i < m_pModel->rowCount(currentRoot); ++i)
1143 {
1144 QModelIndex index = m_pModel->index(i, 0, currentRoot);
1145 if (!index.isValid())
1146 continue;
1147 QModelIndex indexToSelect = m_pProxyModel ? m_pProxyModel->mapFromSource(index) : index;
1148 pSelectionModel->select(indexToSelect, flags);
1149 }
1150}
1151
1152void UIGuestControlFileTable::setSelection(const QModelIndex &indexInProxyModel)
1153{
1154 if (!m_pView)
1155 return;
1156 QItemSelectionModel *selectionModel = m_pView->selectionModel();
1157 if (!selectionModel)
1158 return;
1159 selectionModel->select(indexInProxyModel, QItemSelectionModel::Current | QItemSelectionModel::Rows | QItemSelectionModel::Select);
1160 m_pView->scrollTo(indexInProxyModel, QAbstractItemView::EnsureVisible);
1161}
1162
1163void UIGuestControlFileTable::deleteByIndex(const QModelIndex &itemIndex)
1164{
1165 UIFileTableItem *treeItem = indexData(itemIndex);
1166 if (!treeItem)
1167 return;
1168 deleteByItem(treeItem);
1169}
1170
1171void UIGuestControlFileTable::retranslateUi()
1172{
1173}
1174
1175bool UIGuestControlFileTable::eventFilter(QObject *pObject, QEvent *pEvent) /* override */
1176{
1177 Q_UNUSED(pObject);
1178 if (pEvent->type() == QEvent::KeyPress)
1179 {
1180 QKeyEvent *pKeyEvent = dynamic_cast<QKeyEvent*>(pEvent);
1181 if (pKeyEvent)
1182 {
1183 if (pKeyEvent->key() == Qt::Key_Enter || pKeyEvent->key() == Qt::Key_Return)
1184 {
1185 if (m_pView && m_pModel)
1186 {
1187 /* Get the selected item. If there are 0 or more than 1 selection do nothing: */
1188 QItemSelectionModel *selectionModel = m_pView->selectionModel();
1189 if (selectionModel)
1190 {
1191 QModelIndexList selectedItemIndices = selectionModel->selectedRows();
1192 if (selectedItemIndices.size() == 1 && m_pModel)
1193 goIntoDirectory( m_pProxyModel->mapToSource(selectedItemIndices.at(0)));
1194 }
1195 }
1196 return true;
1197 }
1198 else if (pKeyEvent->key() == Qt::Key_Delete)
1199 {
1200 sltDelete();
1201 return true;
1202 }
1203 else if (pKeyEvent->key() == Qt::Key_Backspace)
1204 {
1205 sltGoUp();
1206 return true;
1207 }
1208 else if (pKeyEvent->text().length() == 1 && pKeyEvent->text().at(0).unicode() <= 127)
1209 {
1210 if (m_pSearchLineEdit)
1211 {
1212 m_pSearchLineEdit->show();
1213 QString strText = m_pSearchLineEdit->text();
1214 strText.append(pKeyEvent->text());
1215 m_pSearchLineEdit->setText(strText);
1216 }
1217 }
1218 }
1219 }
1220
1221 return false;
1222}
1223
1224UIFileTableItem *UIGuestControlFileTable::getStartDirectoryItem()
1225{
1226 if (!m_pRootItem)
1227 return 0;
1228 if (m_pRootItem->childCount() <= 0)
1229 return 0;
1230 return m_pRootItem->child(0);
1231}
1232
1233
1234QString UIGuestControlFileTable::getNewDirectoryName()
1235{
1236 UIStringInputDialog *dialog = new UIStringInputDialog();
1237 if (dialog->execute())
1238 {
1239 QString strDialog = dialog->getString();
1240 delete dialog;
1241 return strDialog;
1242 }
1243 delete dialog;
1244 return QString();
1245}
1246
1247QString UIGuestControlFileTable::currentDirectoryPath() const
1248{
1249 if (!m_pView)
1250 return QString();
1251 QModelIndex currentRoot = currentRootIndex();
1252 if (!currentRoot.isValid())
1253 return QString();
1254 UIFileTableItem *item = static_cast<UIFileTableItem*>(currentRoot.internalPointer());
1255 if (!item)
1256 return QString();
1257 /* be paranoid: */
1258 if (!item->isDirectory())
1259 return QString();
1260 return item->path();
1261}
1262
1263QStringList UIGuestControlFileTable::selectedItemPathList()
1264{
1265 QItemSelectionModel *selectionModel = m_pView->selectionModel();
1266 if (!selectionModel)
1267 return QStringList();
1268
1269 QStringList pathList;
1270 QModelIndexList selectedItemIndices = selectionModel->selectedRows();
1271 for(int i = 0; i < selectedItemIndices.size(); ++i)
1272 {
1273 QModelIndex index =
1274 m_pProxyModel ? m_pProxyModel->mapToSource(selectedItemIndices.at(i)) : selectedItemIndices.at(i);
1275 UIFileTableItem *item = static_cast<UIFileTableItem*>(index.internalPointer());
1276 if (!item)
1277 continue;
1278 pathList.push_back(item->path());
1279 }
1280 return pathList;
1281}
1282
1283CGuestFsObjInfo UIGuestControlFileTable::guestFsObjectInfo(const QString& path, CGuestSession &comGuestSession) const
1284{
1285 if (comGuestSession.isNull())
1286 return CGuestFsObjInfo();
1287 CGuestFsObjInfo comFsObjInfo = comGuestSession.FsObjQueryInfo(path, true /*aFollowSymlinks*/);
1288 if (!comFsObjInfo.isOk())
1289 return CGuestFsObjInfo();
1290 return comFsObjInfo;
1291}
1292
1293void UIGuestControlFileTable::setSelectionDependentActionsEnabled(bool fIsEnabled)
1294{
1295 foreach (QAction *pAction, m_selectionDependentActions)
1296 {
1297 pAction->setEnabled(fIsEnabled);
1298 }
1299}
1300
1301QString UIGuestControlFileTable::fileTypeString(FileObjectType type)
1302{
1303 QString strType("Unknown");
1304 switch(type)
1305 {
1306 case FileObjectType_File:
1307 strType = "File";
1308 break;
1309 case FileObjectType_Directory:
1310 strType = "Directory";
1311 break;
1312 case FileObjectType_SymLink:
1313 strType = "Symbolic Link";
1314 break;
1315 case FileObjectType_Other:
1316 strType = "Other";
1317 break;
1318
1319 case FileObjectType_Unknown:
1320 default:
1321 break;
1322 }
1323 return strType;
1324}
1325
1326/* static */ QString UIGuestControlFileTable::humanReadableSize(ULONG64 size)
1327{
1328 int i = 0;
1329 double dSize = size;
1330 const char* units[] = {" B", " kB", " MB", " GB", " TB", " PB", " EB", " ZB", " YB"};
1331 while (size > m_iKiloByte) {
1332 size /= m_iKiloByte;
1333 dSize /= (double) m_iKiloByte;
1334 i++;
1335 }
1336 if (i > 8)
1337 return QString();
1338
1339 QString strResult(QString::number(dSize, 'f', 2));
1340 strResult += units[i];
1341 return strResult;
1342}
1343
1344void UIGuestControlFileTable::sltReceiveDirectoryStatistics(UIDirectoryStatistics statistics)
1345{
1346 if (!m_pPropertiesDialog)
1347 return;
1348 m_pPropertiesDialog->addDirectoryStatistics(statistics);
1349}
1350
1351QModelIndex UIGuestControlFileTable::currentRootIndex() const
1352{
1353 if (!m_pView)
1354 return QModelIndex();
1355 if (!m_pProxyModel)
1356 return m_pView->rootIndex();
1357 return m_pProxyModel->mapToSource(m_pView->rootIndex());
1358}
1359
1360void UIGuestControlFileTable::performSelectionSearch(const QString &strSearchText)
1361{
1362 if (!m_pProxyModel | !m_pView || strSearchText.isEmpty())
1363 return;
1364
1365 int rowCount = m_pProxyModel->rowCount(m_pView->rootIndex());
1366 UIFileTableItem *pFoundItem = 0;
1367 QModelIndex index;
1368 for (int i = 0; i < rowCount && !pFoundItem; ++i)
1369 {
1370 index = m_pProxyModel->index(i, 0, m_pView->rootIndex());
1371 if (!index.isValid())
1372 continue;
1373 pFoundItem = static_cast<UIFileTableItem*>(m_pProxyModel->mapToSource(index).internalPointer());
1374 if (!pFoundItem)
1375 continue;
1376 const QString &strName = pFoundItem->name();
1377 if (!strName.startsWith(m_pSearchLineEdit->text(), Qt::CaseInsensitive))
1378 pFoundItem = 0;
1379 }
1380 if (pFoundItem)
1381 {
1382 /* Deselect anything that is already selected: */
1383 m_pView->clearSelection();
1384 setSelection(index);
1385 }
1386}
1387
1388void UIGuestControlFileTable::disableSelectionSearch()
1389{
1390 if (!m_pSearchLineEdit)
1391 return;
1392 m_pSearchLineEdit->blockSignals(true);
1393 m_pSearchLineEdit->clear();
1394 m_pSearchLineEdit->hide();
1395 m_pSearchLineEdit->blockSignals(false);
1396}
1397#include "UIGuestControlFileTable.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