/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * LXDE-Qt - a lightweight, Qt based, desktop toolset * http://razor-qt.org * * Copyright: 2012 Razor team * Authors: * Johannes Zellner * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "volumepopup.h" #include "audiodevice.h" #include #include #include #include #include #include #include #include #include "audioengine.h" #include #include VolumePopup::VolumePopup(QWidget* parent): QDialog(parent, Qt::Dialog | Qt::WindowStaysOnTopHint | Qt::CustomizeWindowHint | Qt::Popup | Qt::X11BypassWindowManagerHint), m_pos(0,0), m_anchor(Qt::TopLeftCorner), m_device(0) { m_mixerButton = new QPushButton(this); m_mixerButton->setObjectName("MixerLink"); m_mixerButton->setMinimumWidth(1); m_mixerButton->setToolTip(tr("Launch mixer")); m_mixerButton->setText(tr("Mi&xer")); m_mixerButton->setAutoDefault(false); m_volumeSlider = new QSlider(Qt::Vertical, this); m_volumeSlider->setTickPosition(QSlider::TicksBothSides); m_volumeSlider->setTickInterval(10); // the volume slider shows 0-100 and volumes of all devices // should be converted to percentages. m_volumeSlider->setRange(0, 100); m_volumeSlider->installEventFilter(this); m_muteToggleButton = new QPushButton(this); m_muteToggleButton->setIcon(XdgIcon::fromTheme(QStringList() << "audio-volume-muted")); m_muteToggleButton->setCheckable(true); m_muteToggleButton->setAutoDefault(false); QVBoxLayout *l = new QVBoxLayout(this); l->setSpacing(0); l->setMargin(0); l->addWidget(m_mixerButton, 0, Qt::AlignHCenter); l->addWidget(m_volumeSlider, 0, Qt::AlignHCenter); l->addWidget(m_muteToggleButton, 0, Qt::AlignHCenter); connect(m_mixerButton, SIGNAL(released()), this, SIGNAL(launchMixer())); connect(m_volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(handleSliderValueChanged(int))); connect(m_muteToggleButton, SIGNAL(clicked()), this, SLOT(handleMuteToggleClicked())); } bool VolumePopup::event(QEvent *event) { if(event->type() == QEvent::WindowDeactivate) { // qDebug("QEvent::WindowDeactivate"); hide(); } return QDialog::event(event); } bool VolumePopup::eventFilter(QObject * watched, QEvent * event) { if (watched == m_volumeSlider) { if (event->type() == QEvent::Wheel) { handleWheelEvent(dynamic_cast(event)); return true; } return false; } return QDialog::eventFilter(watched, event); } void VolumePopup::enterEvent(QEvent *event) { emit mouseEntered(); } void VolumePopup::leaveEvent(QEvent *event) { // qDebug("leaveEvent"); emit mouseLeft(); } void VolumePopup::handleSliderValueChanged(int value) { if (!m_device) return; // qDebug("VolumePopup::handleSliderValueChanged: %d\n", value); m_device->setVolume(value); QTimer::singleShot(0, this, [this] { QToolTip::showText(QCursor::pos(), m_volumeSlider->toolTip()); }); } void VolumePopup::handleMuteToggleClicked() { if (!m_device) return; m_device->toggleMute(); } void VolumePopup::handleDeviceVolumeChanged(int volume) { // qDebug() << "handleDeviceVolumeChanged" << "volume" << volume << "max" << max; // calling m_volumeSlider->setValue will trigger // handleSliderValueChanged(), which set the device volume // again, so we have to block the signals to avoid recursive // signal emission. m_volumeSlider->blockSignals(true); m_volumeSlider->setValue(volume); m_volumeSlider->setToolTip(QString("%1%").arg(volume)); dynamic_cast(*parent()).setToolTip(m_volumeSlider->toolTip()); //parent is the button on panel m_volumeSlider->blockSignals(false); // emit volumeChanged(percent); updateStockIcon(); } void VolumePopup::handleDeviceMuteChanged(bool mute) { m_muteToggleButton->setChecked(mute); updateStockIcon(); } void VolumePopup::updateStockIcon() { if (!m_device) return; QString iconName; if (m_device->volume() <= 0 || m_device->mute()) iconName = "audio-volume-muted"; else if (m_device->volume() <= 33) iconName = "audio-volume-low"; else if (m_device->volume() <= 66) iconName = "audio-volume-medium"; else iconName = "audio-volume-high"; m_muteToggleButton->setIcon(XdgIcon::fromTheme(iconName)); emit stockIconChanged(iconName); } void VolumePopup::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); realign(); } void VolumePopup::openAt(QPoint pos, Qt::Corner anchor) { m_pos = pos; m_anchor = anchor; realign(); show(); } void VolumePopup::handleWheelEvent(QWheelEvent *event) { m_volumeSlider->setSliderPosition(m_volumeSlider->sliderPosition() + (event->angleDelta().y() / QWheelEvent::DefaultDeltasPerStep * m_volumeSlider->singleStep())); } void VolumePopup::setDevice(AudioDevice *device) { if (device == m_device) return; // disconnect old device if (m_device) disconnect(m_device); m_device = device; if (m_device) { m_muteToggleButton->setChecked(m_device->mute()); handleDeviceVolumeChanged(m_device->volume()); connect(m_device, SIGNAL(volumeChanged(int)), this, SLOT(handleDeviceVolumeChanged(int))); connect(m_device, SIGNAL(muteChanged(bool)), this, SLOT(handleDeviceMuteChanged(bool))); } else updateStockIcon(); emit deviceChanged(); } void VolumePopup::setSliderStep(int step) { m_volumeSlider->setSingleStep(step); m_volumeSlider->setPageStep(step * 10); } void VolumePopup::realign() { QRect rect; rect.setSize(sizeHint()); switch (m_anchor) { case Qt::TopLeftCorner: rect.moveTopLeft(m_pos); break; case Qt::TopRightCorner: rect.moveTopRight(m_pos); break; case Qt::BottomLeftCorner: rect.moveBottomLeft(m_pos); break; case Qt::BottomRightCorner: rect.moveBottomRight(m_pos); break; } QRect screen = QApplication::desktop()->availableGeometry(m_pos); if (rect.right() > screen.right()) rect.moveRight(screen.right()); if (rect.bottom() > screen.bottom()) rect.moveBottom(screen.bottom()); move(rect.topLeft()); }