VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIStatusBarEditorWindow.cpp@ 82781

Last change on this file since 82781 was 80955, checked in by vboxsync, 5 years ago

FE/Qt: bugref:8938. Changing connection syntax under the widget subfolder.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.9 KB
Line 
1/* $Id: UIStatusBarEditorWindow.cpp 80955 2019-09-23 17:27:06Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIStatusBarEditorWindow class implementation.
4 */
5
6/*
7 * Copyright (C) 2014-2019 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/* Qt includes: */
19#include <QAccessibleWidget>
20#include <QCheckBox>
21#include <QDrag>
22#include <QHBoxLayout>
23#include <QMimeData>
24#include <QMouseEvent>
25#include <QPainter>
26#include <QPaintEvent>
27#include <QPixmap>
28#include <QStatusBar>
29#include <QStyleOption>
30#include <QStylePainter>
31
32/* GUI includes: */
33#include "QIToolButton.h"
34#include "UICommon.h"
35#include "UIConverter.h"
36#include "UIExtraDataManager.h"
37#include "UIIconPool.h"
38#include "UIMachineWindow.h"
39#include "UIStatusBarEditorWindow.h"
40
41/* Forward declarations: */
42class QAccessibleInterface;
43class QMouseEvent;
44class QObject;
45class QPixmap;
46class QPoint;
47class QSize;
48
49
50/** QWidget subclass used as status-bar editor button. */
51class UIStatusBarEditorButton : public QIWithRetranslateUI<QWidget>
52{
53 Q_OBJECT;
54
55signals:
56
57 /** Notifies about click. */
58 void sigClick();
59
60 /** Notifies about drag-object destruction. */
61 void sigDragObjectDestroy();
62
63public:
64
65 /** Holds the mime-type for the D&D system. */
66 static const QString MimeType;
67
68 /** Constructs the button of passed @a enmType. */
69 UIStatusBarEditorButton(IndicatorType enmType);
70
71 /** Returns button type. */
72 IndicatorType type() const { return m_enmType; }
73
74 /** Returns button size-hint. */
75 QSize sizeHint() const { return m_size; }
76
77 /** Returns whether button is checked. */
78 bool isChecked() const;
79 /** Defines whether button is @a fChecked. */
80 void setChecked(bool fChecked);
81
82protected:
83
84 /** Handles any Qt @a pEvent. */
85 virtual bool event(QEvent *pEvent) /* override */;
86
87 /** Handles translation event. */
88 virtual void retranslateUi() /* override */;
89
90 /** Handles paint @a pEvent. */
91 virtual void paintEvent(QPaintEvent *pEvent) /* override */;
92
93 /** Handles mouse-press @a pEvent. */
94 virtual void mousePressEvent(QMouseEvent *pEvent);
95 /** Handles mouse-release @a pEvent. */
96 virtual void mouseReleaseEvent(QMouseEvent *pEvent);
97 /** Handles mouse-enter @a pEvent. */
98 virtual void enterEvent(QEvent *pEvent);
99 /** Handles mouse-leave @a pEvent. */
100 virtual void leaveEvent(QEvent *pEvent);
101 /** Handles mouse-move @a pEvent. */
102 virtual void mouseMoveEvent(QMouseEvent *pEvent);
103
104private:
105
106 /** Prepares all. */
107 void prepare();
108
109 /** Updates pixmap. */
110 void updatePixmap();
111
112 /** Holds the button type. */
113 IndicatorType m_enmType;
114 /** Holds the button size. */
115 QSize m_size;
116 /** Holds the button pixmap. */
117 QPixmap m_pixmap;
118 /** Holds the button pixmap size. */
119 QSize m_pixmapSize;
120 /** Holds whether button is checked. */
121 bool m_fChecked;
122 /** Holds whether button is hovered. */
123 bool m_fHovered;
124 /** Holds the last mouse-press position. */
125 QPoint m_mousePressPosition;
126};
127
128
129/** QAccessibleWidget extension used as an accessibility interface for UIStatusBarEditor buttons. */
130class UIAccessibilityInterfaceForUIStatusBarEditorButton : public QAccessibleWidget
131{
132public:
133
134 /** Returns an accessibility interface for passed @a strClassname and @a pObject. */
135 static QAccessibleInterface *pFactory(const QString &strClassname, QObject *pObject);
136
137 /** Constructs an accessibility interface passing @a pWidget to the base-class. */
138 UIAccessibilityInterfaceForUIStatusBarEditorButton(QWidget *pWidget);
139
140 /** Returns a text for the passed @a enmTextRole. */
141 virtual QString text(QAccessible::Text enmTextRole) const /* override */;
142
143 /** Returns the state. */
144 virtual QAccessible::State state() const /* override */;
145
146private:
147
148 /** Returns corresponding toolbar button. */
149 UIStatusBarEditorButton *button() const { return qobject_cast<UIStatusBarEditorButton*>(widget()); }
150};
151
152
153/*********************************************************************************************************************************
154* Class UIAccessibilityInterfaceForUIStatusBarEditorButton implementation. *
155*********************************************************************************************************************************/
156
157/* static */
158QAccessibleInterface *UIAccessibilityInterfaceForUIStatusBarEditorButton::pFactory(const QString &strClassname, QObject *pObject)
159{
160 /* Creating toolbar button accessibility interface: */
161 if ( pObject
162 && strClassname == QLatin1String("UIStatusBarEditorButton"))
163 return new UIAccessibilityInterfaceForUIStatusBarEditorButton(qobject_cast<QWidget*>(pObject));
164
165 /* Null by default: */
166 return 0;
167}
168
169UIAccessibilityInterfaceForUIStatusBarEditorButton::UIAccessibilityInterfaceForUIStatusBarEditorButton(QWidget *pWidget)
170 : QAccessibleWidget(pWidget, QAccessible::CheckBox)
171{
172}
173
174QString UIAccessibilityInterfaceForUIStatusBarEditorButton::text(QAccessible::Text /* enmTextRole */) const
175{
176 /* Make sure view still alive: */
177 AssertPtrReturn(button(), QString());
178
179 /* Return view tool-tip: */
180 return gpConverter->toString(button()->type());
181}
182
183QAccessible::State UIAccessibilityInterfaceForUIStatusBarEditorButton::state() const /* override */
184{
185 /* Prepare the button state: */
186 QAccessible::State state;
187
188 /* Make sure button still alive: */
189 AssertPtrReturn(button(), state);
190
191 /* Compose the button state: */
192 state.checkable = true;
193 state.checked = button()->isChecked();
194
195 /* Return the button state: */
196 return state;
197}
198
199
200/*********************************************************************************************************************************
201* Class UIStatusBarEditorButton implementation. *
202*********************************************************************************************************************************/
203
204/* static */
205const QString UIStatusBarEditorButton::MimeType = QString("application/virtualbox;value=IndicatorType");
206
207UIStatusBarEditorButton::UIStatusBarEditorButton(IndicatorType enmType)
208 : m_enmType(enmType)
209 , m_fChecked(false)
210 , m_fHovered(false)
211{
212 prepare();
213}
214
215bool UIStatusBarEditorButton::isChecked() const
216{
217 return m_fChecked;
218}
219
220void UIStatusBarEditorButton::setChecked(bool fChecked)
221{
222 /* Update 'checked' state: */
223 m_fChecked = fChecked;
224 /* Update: */
225 update();
226}
227
228bool UIStatusBarEditorButton::event(QEvent *pEvent)
229{
230 /* Handle know event types: */
231 switch (pEvent->type())
232 {
233 case QEvent::Show:
234 case QEvent::ScreenChangeInternal:
235 {
236 /* Update pixmap: */
237 updatePixmap();
238 break;
239 }
240 default:
241 break;
242 }
243
244 /* Call to base-class: */
245 return QIWithRetranslateUI<QWidget>::event(pEvent);
246}
247
248void UIStatusBarEditorButton::retranslateUi()
249{
250 /* Translate tool-tip: */
251 setToolTip(UIStatusBarEditorWidget::tr("<nobr><b>Click</b> to toggle indicator presence.</nobr><br>"
252 "<nobr><b>Drag&Drop</b> to change indicator position.</nobr>"));
253}
254
255void UIStatusBarEditorButton::paintEvent(QPaintEvent *)
256{
257 /* Create style-painter: */
258 QStylePainter painter(this);
259 /* Prepare option set for check-box: */
260 QStyleOptionButton option;
261 option.initFrom(this);
262 /* Use the size of 'this': */
263 option.rect = QRect(0, 0, width(), height());
264 /* But do not use hover bit of 'this' since
265 * we already have another hovered-state representation: */
266 if (option.state & QStyle::State_MouseOver)
267 option.state &= ~QStyle::State_MouseOver;
268 /* Remember checked-state: */
269 if (m_fChecked)
270 option.state |= QStyle::State_On;
271 /* Draw check-box for hovered-state: */
272 if (m_fHovered)
273 painter.drawControl(QStyle::CE_CheckBox, option);
274 /* Draw pixmap for unhovered-state: */
275 else
276 {
277 QRect pixmapRect = QRect(QPoint(0, 0), m_pixmapSize);
278 pixmapRect.moveCenter(option.rect.center());
279 painter.drawItemPixmap(pixmapRect, Qt::AlignCenter, m_pixmap);
280 }
281}
282
283void UIStatusBarEditorButton::mousePressEvent(QMouseEvent *pEvent)
284{
285 /* We are interested in left button only: */
286 if (pEvent->button() != Qt::LeftButton)
287 return;
288
289 /* Remember mouse-press position: */
290 m_mousePressPosition = pEvent->globalPos();
291}
292
293void UIStatusBarEditorButton::mouseReleaseEvent(QMouseEvent *pEvent)
294{
295 /* We are interested in left button only: */
296 if (pEvent->button() != Qt::LeftButton)
297 return;
298
299 /* Forget mouse-press position: */
300 m_mousePressPosition = QPoint();
301
302 /* Notify about click: */
303 emit sigClick();
304}
305
306void UIStatusBarEditorButton::enterEvent(QEvent *)
307{
308 /* Make sure button isn't hovered: */
309 if (m_fHovered)
310 return;
311
312 /* Invert hovered state: */
313 m_fHovered = true;
314 /* Update: */
315 update();
316}
317
318void UIStatusBarEditorButton::leaveEvent(QEvent *)
319{
320 /* Make sure button is hovered: */
321 if (!m_fHovered)
322 return;
323
324 /* Invert hovered state: */
325 m_fHovered = false;
326 /* Update: */
327 update();
328}
329
330void UIStatusBarEditorButton::mouseMoveEvent(QMouseEvent *pEvent)
331{
332 /* Make sure item isn't already dragged: */
333 if (m_mousePressPosition.isNull())
334 return QWidget::mouseMoveEvent(pEvent);
335
336 /* Make sure item is really dragged: */
337 if (QLineF(pEvent->globalPos(), m_mousePressPosition).length() <
338 QApplication::startDragDistance())
339 return QWidget::mouseMoveEvent(pEvent);
340
341 /* Revoke hovered state: */
342 m_fHovered = false;
343 /* Update: */
344 update();
345
346 /* Initialize dragging: */
347 m_mousePressPosition = QPoint();
348 QDrag *pDrag = new QDrag(this);
349 connect(pDrag, SIGNAL(destroyed(QObject*)), this, SIGNAL(sigDragObjectDestroy()));
350 QMimeData *pMimeData = new QMimeData;
351 pMimeData->setData(MimeType, gpConverter->toInternalString(m_enmType).toLatin1());
352 pDrag->setMimeData(pMimeData);
353 pDrag->setPixmap(m_pixmap);
354 pDrag->exec();
355}
356
357void UIStatusBarEditorButton::prepare()
358{
359 /* Track mouse events: */
360 setMouseTracking(true);
361
362 /* Calculate icon size: */
363 const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
364 m_pixmapSize = QSize(iIconMetric, iIconMetric);
365
366 /* Cache button size-hint: */
367 QStyleOptionButton option;
368 option.initFrom(this);
369 const QRect minRect = QApplication::style()->subElementRect(QStyle::SE_CheckBoxIndicator, &option);
370 m_size = m_pixmapSize.expandedTo(minRect.size());
371
372 /* Update pixmap: */
373 updatePixmap();
374
375 /* Translate finally: */
376 retranslateUi();
377}
378
379void UIStatusBarEditorButton::updatePixmap()
380{
381 /* Recache pixmap for assigned type: */
382 const QIcon icon = gpConverter->toIcon(m_enmType);
383 if (window())
384 m_pixmap = icon.pixmap(window()->windowHandle(), m_pixmapSize);
385 else
386 m_pixmap = icon.pixmap(m_pixmapSize);
387}
388
389
390/*********************************************************************************************************************************
391* Class UIStatusBarEditorWindow implementation. *
392*********************************************************************************************************************************/
393
394UIStatusBarEditorWindow::UIStatusBarEditorWindow(UIMachineWindow *pParent)
395 : UISlidingToolBar(pParent, pParent->statusBar(), new UIStatusBarEditorWidget(0, false, uiCommon().managedVMUuid()), UISlidingToolBar::Position_Bottom)
396{
397}
398
399
400/*********************************************************************************************************************************
401* Class UIStatusBarEditorWidget implementation. *
402*********************************************************************************************************************************/
403
404UIStatusBarEditorWidget::UIStatusBarEditorWidget(QWidget *pParent,
405 bool fStartedFromVMSettings /* = true */,
406 const QUuid &uMachineID /* = QString() */)
407 : QIWithRetranslateUI2<QWidget>(pParent)
408 , m_fPrepared(false)
409 , m_fStartedFromVMSettings(fStartedFromVMSettings)
410 , m_uMachineID(uMachineID)
411 , m_pMainLayout(0), m_pButtonLayout(0)
412 , m_pButtonClose(0)
413 , m_pCheckBoxEnable(0)
414 , m_pButtonDropToken(0)
415 , m_fDropAfterTokenButton(true)
416{
417 /* Prepare: */
418 prepare();
419}
420
421void UIStatusBarEditorWidget::setMachineID(const QUuid &uMachineID)
422{
423 /* Remember new machine ID: */
424 m_uMachineID = uMachineID;
425 /* Prepare: */
426 prepare();
427}
428
429bool UIStatusBarEditorWidget::isStatusBarEnabled() const
430{
431 /* For VM settings only: */
432 AssertReturn(m_fStartedFromVMSettings, false);
433
434 /* Acquire enable-checkbox if possible: */
435 AssertPtrReturn(m_pCheckBoxEnable, false);
436 return m_pCheckBoxEnable->isChecked();
437}
438
439void UIStatusBarEditorWidget::setStatusBarEnabled(bool fEnabled)
440{
441 /* For VM settings only: */
442 AssertReturnVoid(m_fStartedFromVMSettings);
443
444 /* Update enable-checkbox if possible: */
445 AssertPtrReturnVoid(m_pCheckBoxEnable);
446 m_pCheckBoxEnable->setChecked(fEnabled);
447}
448
449void UIStatusBarEditorWidget::setStatusBarConfiguration(const QList<IndicatorType> &restrictions,
450 const QList<IndicatorType> &order)
451{
452 /* Cache passed restrictions: */
453 m_restrictions = restrictions;
454
455 /* Cache passed order: */
456 m_order = order;
457 /* Append order with missed indicators: */
458 for (int iType = IndicatorType_Invalid; iType < IndicatorType_Max; ++iType)
459 if (iType != IndicatorType_Invalid && iType != IndicatorType_KeyboardExtension &&
460 !m_order.contains((IndicatorType)iType))
461 m_order << (IndicatorType)iType;
462
463 /* Update configuration for all existing buttons: */
464 foreach (const IndicatorType &enmType, m_order)
465 {
466 /* Get button: */
467 UIStatusBarEditorButton *pButton = m_buttons.value(enmType);
468 /* Make sure button exists: */
469 if (!pButton)
470 continue;
471 /* Update button 'checked' state: */
472 pButton->setChecked(!m_restrictions.contains(enmType));
473 /* Make sure it have valid position: */
474 const int iWantedIndex = position(enmType);
475 const int iActualIndex = m_pButtonLayout->indexOf(pButton);
476 if (iActualIndex != iWantedIndex)
477 {
478 /* Re-inject button into main-layout at proper position: */
479 m_pButtonLayout->removeWidget(pButton);
480 m_pButtonLayout->insertWidget(iWantedIndex, pButton);
481 }
482 }
483}
484
485void UIStatusBarEditorWidget::retranslateUi()
486{
487 /* Translate close-button if necessary: */
488 if (!m_fStartedFromVMSettings && m_pButtonClose)
489 m_pButtonClose->setToolTip(tr("Close"));
490 /* Translate enable-checkbox if necessary: */
491 if (m_fStartedFromVMSettings && m_pCheckBoxEnable)
492 m_pCheckBoxEnable->setToolTip(tr("Enable Status Bar"));
493}
494
495void UIStatusBarEditorWidget::paintEvent(QPaintEvent *)
496{
497 /* Prepare painter: */
498 QPainter painter(this);
499
500 /* Prepare palette colors: */
501 const QPalette pal = palette();
502 QColor color0 = pal.color(QPalette::Window);
503 QColor color1 = pal.color(QPalette::Window).lighter(110);
504 color1.setAlpha(0);
505 QColor color2 = pal.color(QPalette::Window).darker(200);
506#if defined(VBOX_WS_WIN) || defined(VBOX_WS_X11)
507 QColor color3 = pal.color(QPalette::Window).darker(120);
508#endif /* VBOX_WS_WIN || VBOX_WS_X11 */
509
510 /* Acquire metric: */
511 const int iMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4;
512
513 /* Left corner: */
514 QRadialGradient grad1(QPointF(iMetric, iMetric), iMetric);
515 {
516 grad1.setColorAt(0, color2);
517 grad1.setColorAt(1, color1);
518 }
519 /* Right corner: */
520 QRadialGradient grad2(QPointF(width() - iMetric, iMetric), iMetric);
521 {
522 grad2.setColorAt(0, color2);
523 grad2.setColorAt(1, color1);
524 }
525 /* Top line: */
526 QLinearGradient grad3(QPointF(iMetric, 0), QPointF(iMetric, iMetric));
527 {
528 grad3.setColorAt(0, color1);
529 grad3.setColorAt(1, color2);
530 }
531 /* Left line: */
532 QLinearGradient grad4(QPointF(0, iMetric), QPointF(iMetric, iMetric));
533 {
534 grad4.setColorAt(0, color1);
535 grad4.setColorAt(1, color2);
536 }
537 /* Right line: */
538 QLinearGradient grad5(QPointF(width(), iMetric), QPointF(width() - iMetric, iMetric));
539 {
540 grad5.setColorAt(0, color1);
541 grad5.setColorAt(1, color2);
542 }
543
544 /* Paint shape/shadow: */
545 painter.fillRect(QRect(iMetric, iMetric, width() - iMetric * 2, height() - iMetric), color0); // background
546 painter.fillRect(QRect(0, 0, iMetric, iMetric), grad1); // left corner
547 painter.fillRect(QRect(width() - iMetric, 0, iMetric, iMetric), grad2); // right corner
548 painter.fillRect(QRect(iMetric, 0, width() - iMetric * 2, iMetric), grad3); // bottom line
549 painter.fillRect(QRect(0, iMetric, iMetric, height() - iMetric), grad4); // left line
550 painter.fillRect(QRect(width() - iMetric, iMetric, iMetric, height() - iMetric), grad5); // right line
551
552#if defined(VBOX_WS_WIN) || defined(VBOX_WS_X11)
553 /* Paint frames: */
554 painter.save();
555 painter.setPen(color3);
556 painter.drawLine(QLine(QPoint(iMetric + 1, iMetric + 1),
557 QPoint(width() - 1 - iMetric - 1, iMetric + 1)));
558 painter.drawLine(QLine(QPoint(width() - 1 - iMetric - 1, iMetric + 1),
559 QPoint(width() - 1 - iMetric - 1, height() - 1)));
560 painter.drawLine(QLine(QPoint(width() - 1 - iMetric - 1, height() - 1),
561 QPoint(iMetric + 1, height() - 1)));
562 painter.drawLine(QLine(QPoint(iMetric + 1, height() - 1),
563 QPoint(iMetric + 1, iMetric + 1)));
564 painter.restore();
565#endif /* VBOX_WS_WIN || VBOX_WS_X11 */
566
567 /* Paint drop token: */
568 if (m_pButtonDropToken)
569 {
570 QStyleOption option;
571 option.state |= QStyle::State_Horizontal;
572 const QRect geo = m_pButtonDropToken->geometry();
573 option.rect = !m_fDropAfterTokenButton ?
574 QRect(geo.topLeft() - QPoint(iMetric, iMetric),
575 geo.bottomLeft() + QPoint(0, iMetric)) :
576 QRect(geo.topRight() - QPoint(0, iMetric),
577 geo.bottomRight() + QPoint(iMetric, iMetric));
578 QApplication::style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator,
579 &option, &painter);
580 }
581}
582
583void UIStatusBarEditorWidget::dragEnterEvent(QDragEnterEvent *pEvent)
584{
585 /* Make sure event is valid: */
586 AssertPtrReturnVoid(pEvent);
587 /* And mime-data is set: */
588 const QMimeData *pMimeData = pEvent->mimeData();
589 AssertPtrReturnVoid(pMimeData);
590 /* Make sure mime-data format is valid: */
591 if (!pMimeData->hasFormat(UIStatusBarEditorButton::MimeType))
592 return;
593
594 /* Accept drag-enter event: */
595 pEvent->acceptProposedAction();
596}
597
598void UIStatusBarEditorWidget::dragMoveEvent(QDragMoveEvent *pEvent)
599{
600 /* Make sure event is valid: */
601 AssertPtrReturnVoid(pEvent);
602 /* And mime-data is set: */
603 const QMimeData *pMimeData = pEvent->mimeData();
604 AssertPtrReturnVoid(pMimeData);
605 /* Make sure mime-data format is valid: */
606 if (!pMimeData->hasFormat(UIStatusBarEditorButton::MimeType))
607 return;
608
609 /* Reset token: */
610 m_pButtonDropToken = 0;
611 m_fDropAfterTokenButton = true;
612
613 /* Get event position: */
614 const QPoint pos = pEvent->pos();
615 /* Search for most suitable button: */
616 foreach (const IndicatorType &enmType, m_order)
617 {
618 m_pButtonDropToken = m_buttons.value(enmType);
619 const QRect geo = m_pButtonDropToken->geometry();
620 if (pos.x() < geo.center().x())
621 {
622 m_fDropAfterTokenButton = false;
623 break;
624 }
625 }
626 /* Update: */
627 update();
628}
629
630void UIStatusBarEditorWidget::dragLeaveEvent(QDragLeaveEvent *)
631{
632 /* Reset token: */
633 m_pButtonDropToken = 0;
634 m_fDropAfterTokenButton = true;
635 /* Update: */
636 update();
637}
638
639void UIStatusBarEditorWidget::dropEvent(QDropEvent *pEvent)
640{
641 /* Make sure event is valid: */
642 AssertPtrReturnVoid(pEvent);
643 /* And mime-data is set: */
644 const QMimeData *pMimeData = pEvent->mimeData();
645 AssertPtrReturnVoid(pMimeData);
646 /* Make sure mime-data format is valid: */
647 if (!pMimeData->hasFormat(UIStatusBarEditorButton::MimeType))
648 return;
649
650 /* Make sure token-button set: */
651 if (!m_pButtonDropToken)
652 return;
653
654 /* Determine type of token-button: */
655 const IndicatorType tokenType = m_pButtonDropToken->type();
656 /* Determine type of dropped-button: */
657 const QString strDroppedType =
658 QString::fromLatin1(pMimeData->data(UIStatusBarEditorButton::MimeType));
659 const IndicatorType droppedType =
660 gpConverter->fromInternalString<IndicatorType>(strDroppedType);
661
662 /* Make sure these types are different: */
663 if (droppedType == tokenType)
664 return;
665
666 /* Remove type of dropped-button: */
667 m_order.removeAll(droppedType);
668 /* Insert type of dropped-button into position of token-button: */
669 int iPosition = m_order.indexOf(tokenType);
670 if (m_fDropAfterTokenButton)
671 ++iPosition;
672 m_order.insert(iPosition, droppedType);
673
674 if (m_fStartedFromVMSettings)
675 {
676 /* Reapply status-bar configuration from cache: */
677 setStatusBarConfiguration(m_restrictions, m_order);
678 }
679 else
680 {
681 /* Save updated status-bar indicator order: */
682 gEDataManager->setStatusBarIndicatorOrder(m_order, machineID());
683 }
684}
685
686void UIStatusBarEditorWidget::sltHandleConfigurationChange(const QUuid &uMachineID)
687{
688 /* Skip unrelated machine IDs: */
689 if (machineID() != uMachineID)
690 return;
691
692 /* Recache status-bar configuration: */
693 setStatusBarConfiguration(gEDataManager->restrictedStatusBarIndicators(machineID()),
694 gEDataManager->statusBarIndicatorOrder(machineID()));
695}
696
697void UIStatusBarEditorWidget::sltHandleButtonClick()
698{
699 /* Make sure sender is valid: */
700 UIStatusBarEditorButton *pButton = qobject_cast<UIStatusBarEditorButton*>(sender());
701 AssertPtrReturnVoid(pButton);
702
703 /* Get sender type: */
704 const IndicatorType enmType = pButton->type();
705
706 /* Invert restriction for sender type: */
707 if (m_restrictions.contains(enmType))
708 m_restrictions.removeAll(enmType);
709 else
710 m_restrictions.append(enmType);
711
712 if (m_fStartedFromVMSettings)
713 {
714 /* Reapply status-bar configuration from cache: */
715 setStatusBarConfiguration(m_restrictions, m_order);
716 }
717 else
718 {
719 /* Save updated status-bar indicator restrictions: */
720 gEDataManager->setRestrictedStatusBarIndicators(m_restrictions, machineID());
721 }
722}
723
724void UIStatusBarEditorWidget::sltHandleDragObjectDestroy()
725{
726 /* Reset token: */
727 m_pButtonDropToken = 0;
728 m_fDropAfterTokenButton = true;
729 /* Update: */
730 update();
731}
732
733void UIStatusBarEditorWidget::prepare()
734{
735 /* Do nothing if already prepared: */
736 if (m_fPrepared)
737 return;
738
739 /* Do not prepare if machine ID is not set: */
740 if (m_uMachineID.isNull())
741 return;
742
743 /* Install tool-bar button accessibility interface factory: */
744 QAccessible::installFactory(UIAccessibilityInterfaceForUIStatusBarEditorButton::pFactory);
745
746 /* Track D&D events: */
747 setAcceptDrops(true);
748
749 /* Create main-layout: */
750 m_pMainLayout = new QHBoxLayout(this);
751 AssertPtrReturnVoid(m_pMainLayout);
752 {
753 /* Configure main-layout: */
754 int iLeft, iTop, iRight, iBottom;
755 m_pMainLayout->getContentsMargins(&iLeft, &iTop, &iRight, &iBottom);
756 /* Acquire metric: */
757 const int iStandardMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 2;
758 const int iMinimumMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) / 4;
759 /* Standard margins should not be too small/large: */
760 iLeft = iStandardMetric;
761 iTop = iStandardMetric;
762 iRight = iStandardMetric;
763 iBottom = iStandardMetric;
764 /* Bottom margin should be smaller for the common case: */
765 if (iBottom >= iMinimumMetric)
766 iBottom -= iMinimumMetric;
767 /* Left margin should be bigger for the settings case: */
768 if (m_fStartedFromVMSettings)
769 iLeft += iMinimumMetric;
770 /* Apply margins/spacing finally: */
771 m_pMainLayout->setContentsMargins(iLeft, iTop, iRight, iBottom);
772 m_pMainLayout->setSpacing(0);
773 /* Create close-button if necessary: */
774 if (!m_fStartedFromVMSettings)
775 {
776 m_pButtonClose = new QIToolButton;
777 AssertPtrReturnVoid(m_pButtonClose);
778 {
779 /* Configure close-button: */
780 m_pButtonClose->setFocusPolicy(Qt::StrongFocus);
781 m_pButtonClose->setShortcut(Qt::Key_Escape);
782 m_pButtonClose->setIcon(UIIconPool::iconSet(":/ok_16px.png"));
783 connect(m_pButtonClose, SIGNAL(clicked(bool)), this, SIGNAL(sigCancelClicked()));
784 /* Add close-button into main-layout: */
785 m_pMainLayout->addWidget(m_pButtonClose);
786 }
787 }
788 /* Create enable-checkbox if necessary: */
789 else
790 {
791 m_pCheckBoxEnable = new QCheckBox;
792 AssertPtrReturnVoid(m_pCheckBoxEnable);
793 {
794 /* Configure enable-checkbox: */
795 m_pCheckBoxEnable->setFocusPolicy(Qt::StrongFocus);
796 /* Add enable-checkbox into main-layout: */
797 m_pMainLayout->addWidget(m_pCheckBoxEnable);
798 }
799 }
800 /* Insert stretch: */
801 m_pMainLayout->addStretch();
802 /* Create button-layout: */
803 m_pButtonLayout = new QHBoxLayout;
804 AssertPtrReturnVoid(m_pButtonLayout);
805 {
806 /* Configure button-layout: */
807 m_pButtonLayout->setContentsMargins(0, 0, 0, 0);
808#ifdef VBOX_WS_MAC
809 m_pButtonLayout->setSpacing(5);
810#else
811 m_pButtonLayout->setSpacing(qApp->style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing) / 2);
812#endif
813 /* Add button-layout into main-layout: */
814 m_pMainLayout->addLayout(m_pButtonLayout);
815 }
816 /* Prepare status buttons: */
817 prepareStatusButtons();
818 }
819
820 /* Mark as prepared: */
821 m_fPrepared = true;
822
823 /* Translate contents: */
824 retranslateUi();
825}
826
827void UIStatusBarEditorWidget::prepareStatusButtons()
828{
829 /* Create status buttons: */
830 for (int i = IndicatorType_Invalid; i < IndicatorType_Max; ++i)
831 {
832 /* Get current type: */
833 const IndicatorType enmType = (IndicatorType)i;
834 /* Skip inappropriate types: */
835 if (enmType == IndicatorType_Invalid || enmType == IndicatorType_KeyboardExtension)
836 continue;
837 /* Create status button: */
838 prepareStatusButton(enmType);
839 }
840
841 if (!m_fStartedFromVMSettings)
842 {
843 /* Cache status-bar configuration: */
844 setStatusBarConfiguration(gEDataManager->restrictedStatusBarIndicators(machineID()),
845 gEDataManager->statusBarIndicatorOrder(machineID()));
846 /* And listen for the status-bar configuration changes after that: */
847 connect(gEDataManager, &UIExtraDataManager::sigStatusBarConfigurationChange,
848 this, &UIStatusBarEditorWidget::sltHandleConfigurationChange);
849 }
850}
851
852void UIStatusBarEditorWidget::prepareStatusButton(IndicatorType enmType)
853{
854 /* Create status button: */
855 UIStatusBarEditorButton *pButton = new UIStatusBarEditorButton(enmType);
856 AssertPtrReturnVoid(pButton);
857 {
858 /* Configure status button: */
859 connect(pButton, &UIStatusBarEditorButton::sigClick, this, &UIStatusBarEditorWidget::sltHandleButtonClick);
860 connect(pButton, &UIStatusBarEditorButton::sigDragObjectDestroy, this, &UIStatusBarEditorWidget::sltHandleDragObjectDestroy);
861 /* Add status button into button-layout: */
862 m_pButtonLayout->addWidget(pButton);
863 /* Insert status button into map: */
864 m_buttons.insert(enmType, pButton);
865 }
866}
867
868int UIStatusBarEditorWidget::position(IndicatorType enmType) const
869{
870 int iPosition = 0;
871 foreach (const IndicatorType &iteratedType, m_order)
872 if (iteratedType == enmType)
873 return iPosition;
874 else
875 ++iPosition;
876 return iPosition;
877}
878
879
880#include "UIStatusBarEditorWindow.moc"
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use