diff --git a/src/mumble/InlineWidgets.cpp b/src/mumble/InlineWidgets.cpp index 4105d5d8819..dd0cc336de6 100644 --- a/src/mumble/InlineWidgets.cpp +++ b/src/mumble/InlineWidgets.cpp @@ -9,32 +9,6 @@ #include #include -UpDownKeyEventFilter::UpDownKeyEventFilter(QObject *parent) : QObject(parent) { -} - -bool UpDownKeyEventFilter::eventFilter(QObject *obj, QEvent *event) { - // Converts up/down to tab/backtab - // Useful when overriding interactive QWidgetActions such as sliders - - if (event->type() == QEvent::KeyPress) { - QKeyEvent *keyEvent = static_cast< QKeyEvent * >(event); - - if (keyEvent->key() == Qt::Key_Up) { - QKeyEvent *keyPress = new QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier); - QApplication::sendEvent(QApplication::focusWidget(), keyPress); - return true; - } - - if (keyEvent->key() == Qt::Key_Down) { - QKeyEvent *keyPress = new QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier); - QApplication::sendEvent(QApplication::focusWidget(), keyPress); - return true; - } - } - - return QObject::eventFilter(obj, event); -} - OverrideTabOrderFilter::OverrideTabOrderFilter(QObject *parent, QWidget *target) : QObject(parent), focusTarget(target) { } diff --git a/src/mumble/InlineWidgets.h b/src/mumble/InlineWidgets.h index 9819945bb0d..89c4e4eccb3 100644 --- a/src/mumble/InlineWidgets.h +++ b/src/mumble/InlineWidgets.h @@ -10,16 +10,6 @@ #include #include -class UpDownKeyEventFilter : public QObject { - Q_OBJECT - -public: - UpDownKeyEventFilter(QObject *parent); - -protected: - bool eventFilter(QObject *obj, QEvent *event) override; -}; - class OverrideTabOrderFilter : public QObject { Q_OBJECT diff --git a/src/mumble/ListenerVolumeSlider.cpp b/src/mumble/ListenerVolumeSlider.cpp index 6db5a8fdd3e..ede6c59aba5 100644 --- a/src/mumble/ListenerVolumeSlider.cpp +++ b/src/mumble/ListenerVolumeSlider.cpp @@ -40,6 +40,7 @@ void ListenerVolumeSlider::on_VolumeSlider_changeCompleted() { } VolumeAdjustment adjustment = VolumeAdjustment::fromDBAdjustment(m_volumeSlider->value()); + updateLabelValue(); if (handler->m_version >= Mumble::Protocol::PROTOBUF_INTRODUCTION_VERSION) { // With the new audio protocol, volume adjustments for listeners are handled on the server and thus we want diff --git a/src/mumble/MainWindow.cpp b/src/mumble/MainWindow.cpp index 6d5fa95fca7..988f2655ad2 100644 --- a/src/mumble/MainWindow.cpp +++ b/src/mumble/MainWindow.cpp @@ -67,6 +67,7 @@ #endif #include +#include #include #include #include diff --git a/src/mumble/MenuLabel.cpp b/src/mumble/MenuLabel.cpp index 1655a5f5156..3fff56add30 100644 --- a/src/mumble/MenuLabel.cpp +++ b/src/mumble/MenuLabel.cpp @@ -4,16 +4,56 @@ // Mumble source tree or at . #include "MenuLabel.h" +#include "widgets/EventFilters.h" #include -MenuLabel::MenuLabel(const QString &text, QObject *parent) : QWidgetAction(parent), m_text(text) { +MenuLabel::MenuLabel(const QString &text, QObject *parent) + : QWidgetAction(parent), m_text(text), m_accessibleName(""), m_accessibleDescription("") { setMenuRole(QAction::NoRole); } QWidget *MenuLabel::createWidget(QWidget *parent) { QLabel *label = new QLabel(m_text, parent); - label->setFocusPolicy(Qt::TabFocus); + + label->setAccessibleName(m_accessibleName); + label->setAccessibleDescription(m_accessibleDescription); + //label->setFocusPolicy(Qt::TabFocus); + label->installEventFilter(new SkipFocusEventFilter(label)); return label; } + +QString MenuLabel::text() { + return m_text; +} + +void MenuLabel::setText(const QString &text) { + m_text = text; + + QLabel *label = qobject_cast< QLabel * >(defaultWidget()); + if (label) { + label->setText(text); + label->update(); + } +} + +void MenuLabel::setAccessibleName(const QString &name) { + m_accessibleName = name; + + QLabel *label = qobject_cast< QLabel * >(defaultWidget()); + if (label) { + label->setAccessibleName(m_accessibleName); + label->update(); + } +} + +void MenuLabel::setAccessibleDescription(const QString &description) { + m_accessibleDescription = description; + + QLabel *label = qobject_cast< QLabel * >(defaultWidget()); + if (label) { + label->setAccessibleDescription(m_accessibleDescription); + label->update(); + } +} diff --git a/src/mumble/MenuLabel.h b/src/mumble/MenuLabel.h index 22aa6225659..a6803ea3d9c 100644 --- a/src/mumble/MenuLabel.h +++ b/src/mumble/MenuLabel.h @@ -17,11 +17,18 @@ class MenuLabel : public QWidgetAction { public: MenuLabel(const QString &text, QObject *parent = nullptr); + QString text(); + void setText(const QString &name); + void setAccessibleName(const QString &name); + void setAccessibleDescription(const QString &description); + protected: QWidget *createWidget(QWidget *parent) override; private: - const QString m_text; + QString m_text; + QString m_accessibleName; + QString m_accessibleDescription; }; #endif diff --git a/src/mumble/UserLocalVolumeSlider.cpp b/src/mumble/UserLocalVolumeSlider.cpp index ea3f23fa4a3..dcb4f880b12 100644 --- a/src/mumble/UserLocalVolumeSlider.cpp +++ b/src/mumble/UserLocalVolumeSlider.cpp @@ -43,5 +43,7 @@ void UserLocalVolumeSlider::on_VolumeSlider_changeCompleted() { } else { Global::get().mw->logChangeNotPermanent(QObject::tr("Local Volume Adjustment..."), user); } + + updateLabelValue(); } } diff --git a/src/mumble/UserLocalVolumeSlider.h b/src/mumble/UserLocalVolumeSlider.h index b79f574710b..707e75cf0c5 100644 --- a/src/mumble/UserLocalVolumeSlider.h +++ b/src/mumble/UserLocalVolumeSlider.h @@ -23,8 +23,8 @@ class UserLocalVolumeSlider : public VolumeSliderWidgetAction { void setUser(unsigned int sessionId); private slots: - void on_VolumeSlider_valueChanged(int value); - void on_VolumeSlider_changeCompleted(); + void on_VolumeSlider_valueChanged(int value) override; + void on_VolumeSlider_changeCompleted() override; }; #endif diff --git a/src/mumble/VolumeSliderWidgetAction.cpp b/src/mumble/VolumeSliderWidgetAction.cpp index 7553ae68b9f..aca255532be 100644 --- a/src/mumble/VolumeSliderWidgetAction.cpp +++ b/src/mumble/VolumeSliderWidgetAction.cpp @@ -4,22 +4,30 @@ // Mumble source tree or at . #include "VolumeSliderWidgetAction.h" -#include "InlineWidgets.h" +#include "MumbleApplication.h" #include "VolumeAdjustment.h" #include "widgets/EventFilters.h" #include #include +#include +#include VolumeSliderWidgetAction::VolumeSliderWidgetAction(QWidget *parent) - : QWidgetAction(parent), m_volumeSlider(make_qt_unique< QSlider >(Qt::Horizontal, parent)) { + : QWidgetAction(parent), + m_widget(make_qt_unique< QWidget >(parent)), + m_volumeSlider(new QSlider(Qt::Horizontal, parent)), + m_label(new QLabel("0 db", parent)) { + m_volumeSlider->setMinimum(-30); m_volumeSlider->setMaximum(30); - m_volumeSlider->setAccessibleName(tr("Slider for volume adjustment")); - m_volumeSlider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + m_volumeSlider->setAccessibleName(tr("Local volume adjustment")); + + m_label->setStyleSheet("QLabel { margin-left: 0px; padding: 0px; }"); + m_volumeSlider->setStyleSheet("QSlider { margin-right: 0px; }"); KeyEventObserver *keyEventFilter = new KeyEventObserver(this, QEvent::KeyRelease, false, - { Qt::Key_Left, Qt::Key_Right, Qt::Key_Up, Qt::Key_Down }); + { Qt::Key_Left, Qt::Key_Right }); m_volumeSlider->installEventFilter(keyEventFilter); // The list of wheel events observed seems odd at first. We have to check for multiple @@ -33,27 +41,50 @@ VolumeSliderWidgetAction::VolumeSliderWidgetAction(QWidget *parent) new MouseWheelEventObserver(this, { Qt::ScrollMomentum, Qt::ScrollUpdate, Qt::ScrollEnd }, false); m_volumeSlider->installEventFilter(wheelEventFilter); - connect(m_volumeSlider.get(), &QSlider::valueChanged, this, + connect(m_volumeSlider, &QSlider::valueChanged, this, &VolumeSliderWidgetAction::on_VolumeSlider_valueChanged); - connect(m_volumeSlider.get(), &QSlider::sliderReleased, this, + connect(m_volumeSlider, &QSlider::sliderReleased, this, + [=]() { m_volumeSlider->setFocus(Qt::TabFocusReason); updateLabelValue(false); }); + connect(m_volumeSlider, &QSlider::sliderReleased, this, &VolumeSliderWidgetAction::on_VolumeSlider_changeCompleted); connect(keyEventFilter, &KeyEventObserver::keyEventObserved, this, &VolumeSliderWidgetAction::on_VolumeSlider_changeCompleted); connect(wheelEventFilter, &MouseWheelEventObserver::wheelEventObserved, this, &VolumeSliderWidgetAction::on_VolumeSlider_changeCompleted); - setDefaultWidget(m_volumeSlider.get()); - UpDownKeyEventFilter *eventFilter = new UpDownKeyEventFilter(this); m_volumeSlider->installEventFilter(eventFilter); m_volumeSlider->setProperty("mouseTracking", true); + + QHBoxLayout *layout = new QHBoxLayout(); + layout->addWidget(m_volumeSlider); + layout->addWidget(m_label); + layout->setContentsMargins(0, 0, -1, 0); + layout->setSpacing(3); + m_widget->setLayout(layout); + + m_widget->setFocusProxy(m_volumeSlider); + m_widget->setFocusPolicy(Qt::TabFocus); + + setDefaultWidget(m_widget.get()); +} + +void VolumeSliderWidgetAction::updateLabelValue(bool checkMouseButtons) { + if (checkMouseButtons && MumbleApplication::instance()->mouseButtons() != Qt::NoButton) { + // Do not update the label while the user is dragging the slider. + // This will otherwise cause a glitchy experience. + return; + } + + m_label->setText(QString("%01dB").arg(m_volumeSlider->value())); } void VolumeSliderWidgetAction::updateSliderValue(float value) { int dbShift = VolumeAdjustment::toIntegerDBAdjustment(value); m_volumeSlider->setValue(dbShift); updateTooltip(dbShift); + updateLabelValue(false); } void VolumeSliderWidgetAction::updateTooltip(int value) { diff --git a/src/mumble/VolumeSliderWidgetAction.h b/src/mumble/VolumeSliderWidgetAction.h index 25bb408670f..28f95097c2b 100644 --- a/src/mumble/VolumeSliderWidgetAction.h +++ b/src/mumble/VolumeSliderWidgetAction.h @@ -11,6 +11,8 @@ #include "QtUtils.h" class QSlider; +class QHBoxLayout; +class QLabel; class VolumeSliderWidgetAction : public QWidgetAction { Q_OBJECT @@ -19,8 +21,11 @@ class VolumeSliderWidgetAction : public QWidgetAction { VolumeSliderWidgetAction(QWidget *parent = nullptr); protected: - qt_unique_ptr< QSlider > m_volumeSlider; + qt_unique_ptr< QWidget > m_widget; + QSlider* m_volumeSlider; + QLabel* m_label; + void updateLabelValue(bool checkMouseButtons = true); void updateSliderValue(float value); void displayTooltip(int value); void updateTooltip(int value); diff --git a/src/mumble/widgets/EventFilters.cpp b/src/mumble/widgets/EventFilters.cpp index c194ac957c9..7fad27bae81 100644 --- a/src/mumble/widgets/EventFilters.cpp +++ b/src/mumble/widgets/EventFilters.cpp @@ -7,10 +7,15 @@ #include +#include #include #include #include +#include +#include +#include + KeyEventObserver::KeyEventObserver(QObject *parent, QEvent::Type eventType, bool consume, std::vector< Qt::Key > keys) : QObject(parent), m_eventType(eventType), m_consume(consume), m_keys(std::move(keys)) { } @@ -66,3 +71,56 @@ bool MouseWheelEventObserver::eventFilter(QObject *obj, QEvent *event) { return m_consume; } + + +UpDownKeyEventFilter::UpDownKeyEventFilter(QObject *parent) : QObject(parent) { +} + +bool UpDownKeyEventFilter::eventFilter(QObject *obj, QEvent *event) { + // Converts up/down to tab/backtab + // Useful when overriding interactive QWidgetActions such as sliders + + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast< QKeyEvent * >(event); + + if (keyEvent->key() == Qt::Key_Up) { + QKeyEvent *keyPress = new QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier); + QApplication::sendEvent(QApplication::focusWidget(), keyPress); + return true; + } + + if (keyEvent->key() == Qt::Key_Down) { + QKeyEvent *keyPress = new QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier); + QApplication::sendEvent(QApplication::focusWidget(), keyPress); + return true; + } + } + + return QObject::eventFilter(obj, event); +} + +SkipFocusEventFilter::SkipFocusEventFilter(QObject *parent) : QObject(parent) { +} + +bool SkipFocusEventFilter::eventFilter(QObject *obj, QEvent *event) { + if (event->type() == QEvent::KeyRelease) { + QKeyEvent *keyEvent = static_cast< QKeyEvent * >(event); + + qDebug() << keyEvent->key(); + qDebug() << (QApplication::focusWidget() == obj); + + if (keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Backtab) { + QKeyEvent *keyPress = new QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier); + QApplication::sendEvent(QApplication::focusWidget(), keyPress); + return true; + } + + if (keyEvent->key() == Qt::Key_Down || keyEvent->key() == Qt::Key_Tab) { + QKeyEvent *keyPress = new QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier); + QApplication::sendEvent(QApplication::focusWidget(), keyPress); + return true; + } + } + + return QObject::eventFilter(obj, event); +} diff --git a/src/mumble/widgets/EventFilters.h b/src/mumble/widgets/EventFilters.h index ef1aa7076ae..ad26b65978f 100644 --- a/src/mumble/widgets/EventFilters.h +++ b/src/mumble/widgets/EventFilters.h @@ -47,4 +47,24 @@ class MouseWheelEventObserver : public QObject { bool m_consume; }; +class UpDownKeyEventFilter : public QObject { + Q_OBJECT + +public: + UpDownKeyEventFilter(QObject *parent); + +protected: + bool eventFilter(QObject *obj, QEvent *event) override; +}; + +class SkipFocusEventFilter : public QObject { + Q_OBJECT + +public: + SkipFocusEventFilter(QObject *parent); + +protected: + bool eventFilter(QObject *obj, QEvent *event) override; +}; + #endif