VirtualBox

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

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

scm --update-copyright-year

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

© 2023 Oracle
ContactPrivacy policyTerms of Use