VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/guestctrl/UIFileManagerOperationsPanel.cpp@ 100347

Last change on this file since 100347 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.0 KB
Line 
1/* $Id: UIFileManagerOperationsPanel.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIVMLogViewer class implementation.
4 */
5
6/*
7 * Copyright (C) 2010-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 <QHBoxLayout>
30#include <QGridLayout>
31#include <QLabel>
32#include <QMenu>
33#include <QProgressBar>
34#include <QScrollArea>
35#include <QScrollBar>
36#include <QStyle>
37
38
39/* GUI includes: */
40#include "QIToolButton.h"
41#include "QILabel.h"
42#include "UIErrorString.h"
43#include "UIIconPool.h"
44#include "UIFileManager.h"
45#include "UIFileManagerOperationsPanel.h"
46#include "UIProgressEventHandler.h"
47
48/* COM includes: */
49#include "CProgress.h"
50
51
52/*********************************************************************************************************************************
53* UIFileOperationProgressWidget definition. *
54*********************************************************************************************************************************/
55
56class UIFileOperationProgressWidget : public QIWithRetranslateUI<QFrame>
57{
58
59 Q_OBJECT;
60
61signals:
62
63 void sigProgressComplete(QUuid progressId);
64 void sigProgressFail(QString strErrorString, QString strSourceTableName, FileManagerLogType eLogType);
65 void sigFocusIn(QWidget *pWidget);
66 void sigFocusOut(QWidget *pWidget);
67
68public:
69
70 UIFileOperationProgressWidget(const CProgress &comProgress, const QString &strSourceTableName, QWidget *pParent = 0);
71 ~UIFileOperationProgressWidget();
72 bool isCompleted() const;
73 bool isCanceled() const;
74
75protected:
76
77 virtual void retranslateUi() RT_OVERRIDE;
78 virtual void focusInEvent(QFocusEvent *pEvent) RT_OVERRIDE;
79 virtual void focusOutEvent(QFocusEvent *pEvent) RT_OVERRIDE;
80
81private slots:
82
83 void sltHandleProgressPercentageChange(const QUuid &uProgressId, const int iPercent);
84 void sltHandleProgressComplete(const QUuid &uProgressId);
85 void sltCancelProgress();
86
87private:
88 enum OperationStatus
89 {
90 OperationStatus_NotStarted,
91 OperationStatus_Working,
92 OperationStatus_Paused,
93 OperationStatus_Canceled,
94 OperationStatus_Succeded,
95 OperationStatus_Failed,
96 OperationStatus_Invalid,
97 OperationStatus_Max
98 };
99
100 void prepare();
101 void prepareWidgets();
102 void prepareEventHandler();
103 void cleanupEventHandler();
104
105 OperationStatus m_eStatus;
106 CProgress m_comProgress;
107 UIProgressEventHandler *m_pEventHandler;
108 QGridLayout *m_pMainLayout;
109 QProgressBar *m_pProgressBar;
110 QIToolButton *m_pCancelButton;
111 QILabel *m_pStatusLabel;
112 QILabel *m_pOperationDescriptionLabel;
113 /** Name of the table from which this operation has originated. */
114 QString m_strSourceTableName;
115};
116
117
118/*********************************************************************************************************************************
119* UIFileOperationProgressWidget implementation. *
120*********************************************************************************************************************************/
121
122UIFileOperationProgressWidget::UIFileOperationProgressWidget(const CProgress &comProgress, const QString &strSourceTableName, QWidget *pParent /* = 0 */)
123 : QIWithRetranslateUI<QFrame>(pParent)
124 , m_eStatus(OperationStatus_NotStarted)
125 , m_comProgress(comProgress)
126 , m_pEventHandler(0)
127 , m_pMainLayout(0)
128 , m_pProgressBar(0)
129 , m_pCancelButton(0)
130 , m_pStatusLabel(0)
131 , m_pOperationDescriptionLabel(0)
132 , m_strSourceTableName(strSourceTableName)
133{
134 prepare();
135 setFocusPolicy(Qt::ClickFocus);
136 setStyleSheet("QFrame:focus { border-width: 1px; border-style: dashed; border-color: black; }");
137}
138
139UIFileOperationProgressWidget::~UIFileOperationProgressWidget()
140{
141 cleanupEventHandler();
142}
143
144bool UIFileOperationProgressWidget::isCompleted() const
145{
146 if (m_comProgress.isNull())
147 return true;
148 return m_comProgress.GetCompleted();
149}
150
151bool UIFileOperationProgressWidget::isCanceled() const
152{
153 if (m_comProgress.isNull())
154 return true;
155 return m_comProgress.GetCanceled();
156}
157
158void UIFileOperationProgressWidget::retranslateUi()
159{
160 if (m_pCancelButton)
161 m_pCancelButton->setToolTip(UIFileManager::tr("Cancel"));
162
163 switch (m_eStatus)
164 {
165 case OperationStatus_NotStarted:
166 m_pStatusLabel->setText(UIFileManager::tr("Not yet started"));
167 break;
168 case OperationStatus_Working:
169 m_pStatusLabel->setText(UIFileManager::tr("Working"));
170 break;
171 case OperationStatus_Paused:
172 m_pStatusLabel->setText(UIFileManager::tr("Paused"));
173 break;
174 case OperationStatus_Canceled:
175 m_pStatusLabel->setText(UIFileManager::tr("Canceled"));
176 break;
177 case OperationStatus_Succeded:
178 m_pStatusLabel->setText(UIFileManager::tr("Succeded"));
179 break;
180 case OperationStatus_Failed:
181 m_pStatusLabel->setText(UIFileManager::tr("Failed"));
182 break;
183 case OperationStatus_Invalid:
184 case OperationStatus_Max:
185 default:
186 m_pStatusLabel->setText(UIFileManager::tr("Invalid"));
187 break;
188 }
189}
190
191void UIFileOperationProgressWidget::focusInEvent(QFocusEvent *pEvent)
192{
193 QFrame::focusInEvent(pEvent);
194 emit sigFocusIn(this);
195}
196
197void UIFileOperationProgressWidget::focusOutEvent(QFocusEvent *pEvent)
198{
199 QFrame::focusOutEvent(pEvent);
200 emit sigFocusOut(this);
201}
202
203void UIFileOperationProgressWidget::prepare()
204{
205 prepareWidgets();
206 prepareEventHandler();
207 retranslateUi();
208}
209
210void UIFileOperationProgressWidget::prepareWidgets()
211{
212 m_pMainLayout = new QGridLayout;
213 if (!m_pMainLayout)
214 return;
215 //m_pMainLayout->setSpacing(0);
216
217 m_pOperationDescriptionLabel = new QILabel;
218 if (m_pOperationDescriptionLabel)
219 {
220 m_pOperationDescriptionLabel->setContextMenuPolicy(Qt::NoContextMenu);
221 m_pMainLayout->addWidget(m_pOperationDescriptionLabel, 0, 0, 1, 3);
222 if (!m_comProgress.isNull())
223 m_pOperationDescriptionLabel->setText(m_comProgress.GetDescription());
224 }
225
226 m_pProgressBar = new QProgressBar;
227 if (m_pProgressBar)
228 {
229 m_pProgressBar->setMinimum(0);
230 m_pProgressBar->setMaximum(100);
231 m_pProgressBar->setTextVisible(true);
232 m_pMainLayout->addWidget(m_pProgressBar, 1, 0, 1, 2);
233 }
234
235 m_pCancelButton = new QIToolButton;
236 if (m_pCancelButton)
237 {
238 m_pCancelButton->setIcon(QApplication::style()->standardIcon(QStyle::SP_DockWidgetCloseButton));
239 connect(m_pCancelButton, &QIToolButton::clicked, this, &UIFileOperationProgressWidget::sltCancelProgress);
240 if (!m_comProgress.isNull() && !m_comProgress.GetCancelable())
241 m_pCancelButton->setEnabled(false);
242 m_pMainLayout->addWidget(m_pCancelButton, 1, 2, 1, 1);
243 }
244
245 m_pStatusLabel = new QILabel;
246 if (m_pStatusLabel)
247 {
248 m_pStatusLabel->setContextMenuPolicy(Qt::NoContextMenu);
249 m_pMainLayout->addWidget(m_pStatusLabel, 1, 3, 1, 1);
250 }
251
252 setLayout(m_pMainLayout);
253 retranslateUi();
254}
255
256void UIFileOperationProgressWidget::prepareEventHandler()
257{
258 if (m_comProgress.isNull())
259 return;
260 m_pEventHandler = new UIProgressEventHandler(this, m_comProgress);
261 connect(m_pEventHandler, &UIProgressEventHandler::sigProgressPercentageChange,
262 this, &UIFileOperationProgressWidget::sltHandleProgressPercentageChange);
263 connect(m_pEventHandler, &UIProgressEventHandler::sigProgressTaskComplete,
264 this, &UIFileOperationProgressWidget::sltHandleProgressComplete);
265 m_eStatus = OperationStatus_Working;
266 retranslateUi();
267}
268
269void UIFileOperationProgressWidget::cleanupEventHandler()
270{
271 delete m_pEventHandler;
272 m_pEventHandler = 0;
273}
274
275void UIFileOperationProgressWidget::sltHandleProgressPercentageChange(const QUuid &uProgressId, const int iPercent)
276{
277 Q_UNUSED(uProgressId);
278 m_pProgressBar->setValue(iPercent);
279}
280
281void UIFileOperationProgressWidget::sltHandleProgressComplete(const QUuid &uProgressId)
282{
283 Q_UNUSED(uProgressId);
284 if (m_pCancelButton)
285 m_pCancelButton->setEnabled(false);
286
287 if (!m_comProgress.isOk() || m_comProgress.GetResultCode() != 0)
288 {
289 emit sigProgressFail(UIErrorString::formatErrorInfo(m_comProgress), m_strSourceTableName, FileManagerLogType_Error);
290 m_eStatus = OperationStatus_Failed;
291 }
292 else
293 {
294 emit sigProgressComplete(m_comProgress.GetId());
295 m_eStatus = OperationStatus_Succeded;
296 }
297 if (m_pProgressBar)
298 m_pProgressBar->setValue(100);
299
300 cleanupEventHandler();
301 retranslateUi();
302}
303
304void UIFileOperationProgressWidget::sltCancelProgress()
305{
306 m_comProgress.Cancel();
307 /* Since we dont have a "progress canceled" event we have to do this here: */
308 if (m_pCancelButton)
309 m_pCancelButton->setEnabled(false);
310 if (m_pProgressBar)
311 m_pProgressBar->setEnabled(false);
312 m_eStatus = OperationStatus_Canceled;
313 cleanupEventHandler();
314 retranslateUi();
315}
316
317
318/*********************************************************************************************************************************
319* UIFileManagerOperationsPanel implementation. *
320*********************************************************************************************************************************/
321
322UIFileManagerOperationsPanel::UIFileManagerOperationsPanel(QWidget *pParent /* = 0 */)
323 : UIDialogPanel(pParent)
324 , m_pScrollArea(0)
325 , m_pContainerWidget(0)
326 , m_pContainerLayout(0)
327 , m_pContainerSpaceItem(0)
328 , m_pWidgetInFocus(0)
329{
330 prepare();
331}
332
333void UIFileManagerOperationsPanel::addNewProgress(const CProgress &comProgress, const QString &strSourceTableName)
334{
335 if (!m_pContainerLayout)
336 return;
337
338 UIFileOperationProgressWidget *pOperationsWidget = new UIFileOperationProgressWidget(comProgress, strSourceTableName);
339 if (!pOperationsWidget)
340 return;
341 m_widgetSet.insert(pOperationsWidget);
342 m_pContainerLayout->insertWidget(m_pContainerLayout->count() - 1, pOperationsWidget);
343
344 connect(pOperationsWidget, &UIFileOperationProgressWidget::sigProgressComplete,
345 this, &UIFileManagerOperationsPanel::sigFileOperationComplete);
346 connect(pOperationsWidget, &UIFileOperationProgressWidget::sigProgressFail,
347 this, &UIFileManagerOperationsPanel::sigFileOperationFail);
348
349 connect(pOperationsWidget, &UIFileOperationProgressWidget::sigFocusIn,
350 this, &UIFileManagerOperationsPanel::sltHandleWidgetFocusIn);
351 connect(pOperationsWidget, &UIFileOperationProgressWidget::sigFocusOut,
352 this, &UIFileManagerOperationsPanel::sltHandleWidgetFocusOut);
353 sigShowPanel(this);
354}
355
356QString UIFileManagerOperationsPanel::panelName() const
357{
358 return "OperationsPanel";
359}
360
361void UIFileManagerOperationsPanel::prepareWidgets()
362{
363 if (!mainLayout())
364 return;
365
366 QPalette pal = QApplication::palette();
367 pal.setColor(QPalette::Active, QPalette::Window, pal.color(QPalette::Active, QPalette::Base));
368 setPalette(pal);
369
370 m_pScrollArea = new QScrollArea;
371 m_pContainerWidget = new QWidget;
372 m_pContainerLayout = new QVBoxLayout;
373 if (!m_pScrollArea || !m_pContainerWidget || !m_pContainerLayout)
374 return;
375
376 QScrollBar *pVerticalScrollBar = m_pScrollArea->verticalScrollBar();
377 if (pVerticalScrollBar)
378 QObject::connect(pVerticalScrollBar, &QScrollBar::rangeChanged, this, &UIFileManagerOperationsPanel::sltScrollToBottom);
379
380 m_pScrollArea->setBackgroundRole(QPalette::Window);
381 m_pScrollArea->setWidgetResizable(true);
382
383 mainLayout()->addWidget(m_pScrollArea);
384
385 m_pScrollArea->setWidget(m_pContainerWidget);
386 m_pContainerWidget->setLayout(m_pContainerLayout);
387 m_pContainerLayout->addStretch(4);
388}
389
390void UIFileManagerOperationsPanel::prepareConnections()
391{
392
393}
394
395void UIFileManagerOperationsPanel::retranslateUi()
396{
397 UIDialogPanel::retranslateUi();
398}
399
400void UIFileManagerOperationsPanel::contextMenuEvent(QContextMenuEvent *pEvent)
401{
402 QMenu *menu = new QMenu(this);
403
404 if (m_pWidgetInFocus)
405 {
406 QAction *pRemoveSelected = menu->addAction(UIFileManager::tr("Remove Selected"));
407 connect(pRemoveSelected, &QAction::triggered,
408 this, &UIFileManagerOperationsPanel::sltRemoveSelected);
409 }
410
411 QAction *pRemoveFinished = menu->addAction(UIFileManager::tr("Remove Finished"));
412 QAction *pRemoveAll = menu->addAction(UIFileManager::tr("Remove All"));
413
414 connect(pRemoveFinished, &QAction::triggered,
415 this, &UIFileManagerOperationsPanel::sltRemoveFinished);
416 connect(pRemoveAll, &QAction::triggered,
417 this, &UIFileManagerOperationsPanel::sltRemoveAll);
418
419 menu->exec(pEvent->globalPos());
420 delete menu;
421}
422
423void UIFileManagerOperationsPanel::sltRemoveFinished()
424{
425 QList<UIFileOperationProgressWidget*> widgetsToRemove;
426 foreach (QWidget *pWidget, m_widgetSet)
427 {
428 UIFileOperationProgressWidget *pProgressWidget = qobject_cast<UIFileOperationProgressWidget*>(pWidget);
429 if (pProgressWidget && pProgressWidget->isCompleted())
430 {
431 delete pProgressWidget;
432 widgetsToRemove << pProgressWidget;
433 }
434 }
435 foreach (UIFileOperationProgressWidget *pWidget, widgetsToRemove)
436 m_widgetSet.remove(pWidget);
437}
438
439void UIFileManagerOperationsPanel::sltRemoveAll()
440{
441 foreach (QWidget *pWidget, m_widgetSet)
442 {
443 if (pWidget)
444 {
445 delete pWidget;
446 }
447 }
448 m_widgetSet.clear();
449}
450
451void UIFileManagerOperationsPanel::sltRemoveSelected()
452{
453 if (!m_pWidgetInFocus)
454 return;
455 delete m_pWidgetInFocus;
456 m_widgetSet.remove(m_pWidgetInFocus);
457}
458
459void UIFileManagerOperationsPanel::sltHandleWidgetFocusIn(QWidget *pWidget)
460{
461 if (!pWidget)
462 return;
463 m_pWidgetInFocus = pWidget;
464}
465
466void UIFileManagerOperationsPanel::sltHandleWidgetFocusOut(QWidget *pWidget)
467{
468 if (!pWidget)
469 return;
470 m_pWidgetInFocus = 0;
471}
472
473void UIFileManagerOperationsPanel::sltScrollToBottom(int iMin, int iMax)
474{
475 Q_UNUSED(iMin);
476 if (m_pScrollArea)
477 m_pScrollArea->verticalScrollBar()->setValue(iMax);
478}
479
480#include "UIFileManagerOperationsPanel.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