File indexing completed on 2021-12-21 13:28:03

0001 /**
0002  * Copyright (c) 2009 Nikolaj Hald Nielsen <nhn@kde.org>
0003  * Copyright (c) 2009 Mark Kretschmann <kretschmann@kde.org>
0004  *
0005  * This program is free software; you can redistribute it and/or modify it under
0006  * the terms of the GNU General Public License as published by the Free Software
0007  * Foundation; either version 2 of the License, or (at your option) any later
0008  * version.
0009  *
0010  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0011  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0012  * PARTICULAR PURPOSE. See the GNU General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU General Public License along with
0015  * this program.  If not, see <http://www.gnu.org/licenses/>.
0016  */
0017 
0018 #include "volumepopupbutton.h"
0019 #include "slider.h"
0020 
0021 #include <KLocalizedString>
0022 
0023 #include <QAction>
0024 #include <QHBoxLayout>
0025 #include <QIcon>
0026 #include <QLabel>
0027 #include <QMenu>
0028 #include <QToolBar>
0029 #include <QVBoxLayout>
0030 #include <QWheelEvent>
0031 #include <QWidgetAction>
0032 
0033 #include "iconsupport.h"
0034 #include "juk.h"
0035 #include "playermanager.h"
0036 
0037 using namespace IconSupport;  // ""_icon
0038 
0039 VolumePopupButton::VolumePopupButton( QWidget * parent )
0040     : QToolButton( parent )
0041 {
0042     m_volumeBeforeMute = 0.0;
0043 
0044     //create the volume popup
0045     m_volumeMenu = new QMenu( this );
0046 
0047     auto mainWidget = new QWidget( this );
0048     mainWidget->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred );
0049 
0050     auto mainBox = new QVBoxLayout( mainWidget );
0051     mainBox->setContentsMargins( 0 ,  0 ,  0 ,  0 );
0052     mainBox->setSpacing( 0 );
0053 
0054     m_volumeLabel = new QLabel;
0055     m_volumeLabel->setAlignment( Qt::AlignHCenter );
0056     mainBox->addWidget( m_volumeLabel );
0057 
0058     auto sliderBox = new QWidget;
0059     sliderBox->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred );
0060 
0061     auto sliderBoxLayout = new QHBoxLayout( sliderBox );
0062     sliderBoxLayout->setSpacing( 0 );
0063     sliderBoxLayout->setContentsMargins( 0 ,  0 ,  0 ,  0 );
0064     mainBox->addWidget(sliderBox);
0065 
0066     m_volumeSlider = new VolumeSlider( 100, sliderBox, false );
0067     m_volumeSlider->setFixedHeight( 200 ); // FIXME HiDPI
0068     sliderBoxLayout->addWidget(m_volumeSlider);
0069 
0070     PlayerManager *player = JuK::JuKInstance()->playerManager();
0071 
0072     QWidgetAction *sliderActionWidget = new QWidgetAction( this );
0073     sliderActionWidget->setDefaultWidget( mainWidget );
0074 
0075     connect( m_volumeSlider, &VolumeSlider::volumeChanged, player, &PlayerManager::setVolume );
0076 
0077     m_muteAction = new QAction("audio-volume-muted"_icon, QString(), this );
0078     m_muteAction->setToolTip( i18n( "Mute/Unmute" ) );
0079     m_muteAction->setCheckable( true );
0080     m_muteAction->setChecked( player->muted() );
0081 
0082     connect( m_muteAction, SIGNAL(toggled(bool)), player, SLOT(setMuted(bool)) );
0083     connect( player, SIGNAL(mutedChanged(bool)), this, SLOT(muteStateChanged(bool)) );
0084 
0085     m_volumeMenu->addAction( sliderActionWidget );
0086     m_volumeMenu->addAction( m_muteAction );
0087 
0088     // set correct icon and label initially
0089     volumeChanged( player->volume() );
0090 
0091     connect( player, SIGNAL(volumeChanged(float)), this, SLOT(volumeChanged(float)) );
0092 }
0093 
0094 void
0095 VolumePopupButton::refresh()
0096 {
0097     volumeChanged( JuK::JuKInstance()->playerManager()->volume() );
0098 }
0099 
0100 void
0101 VolumePopupButton::volumeChanged( float newVolume )
0102 {
0103     if (!JuK::JuKInstance()->playerManager()->muted()) {
0104         m_volumeBeforeMute = newVolume;
0105     }
0106 
0107     if ( newVolume <= 0.0001 )
0108         setIcon("audio-volume-muted"_icon);
0109     else if ( newVolume < 0.34 )
0110         setIcon("audio-volume-low"_icon);
0111     else if ( newVolume < 0.67 )
0112         setIcon("audio-volume-medium"_icon);
0113     else
0114         setIcon("audio-volume-high"_icon);
0115 
0116     m_volumeLabel->setText( i18n( "%1%" , int( newVolume * 100 ) ) );
0117 
0118     if( newVolume != m_volumeSlider->value() )
0119         m_volumeSlider->setValue( newVolume * 100 );
0120 
0121     //make sure to uncheck mute toolbar when moving slider
0122     if ( newVolume > 0 )
0123         m_muteAction->setChecked( false );
0124 
0125     const KLocalizedString tip = m_muteAction->isChecked() ? ki18n( "Volume: %1% (muted)" ) : ki18n( "Volume: %1%" );
0126     setToolTip( tip.subs( int( 100 * newVolume ) ).toString() );
0127 }
0128 
0129 void
0130 VolumePopupButton::muteStateChanged( bool muted )
0131 {
0132     if ( muted )
0133     {
0134         const float volume = JuK::JuKInstance()->playerManager()->volume();
0135         setIcon("audio-volume-muted"_icon);
0136         setToolTip( i18n( "Volume: %1% (muted)", int( 100 * volume ) ) );
0137     }
0138     else
0139     {
0140         JuK::JuKInstance()->playerManager()->setVolume( m_volumeBeforeMute );
0141     }
0142 
0143     m_muteAction->setChecked( muted );
0144 }
0145 
0146 void
0147 VolumePopupButton::mouseReleaseEvent( QMouseEvent * event )
0148 {
0149     if( event->button() == Qt::LeftButton )
0150     {
0151         if ( m_volumeMenu->isVisible() )
0152             m_volumeMenu->hide();
0153         else
0154         {
0155             const QPoint pos( 0, height() );
0156             m_volumeMenu->exec( mapToGlobal( pos ) );
0157         }
0158     }
0159     else if( event->button() == Qt::MiddleButton )
0160     {
0161         muteStateChanged( JuK::JuKInstance()->playerManager()->mute() );
0162     }
0163 
0164     QToolButton::mouseReleaseEvent( event );
0165 }
0166 
0167 void
0168 VolumePopupButton::wheelEvent( QWheelEvent * event )
0169 {
0170     event->accept();
0171     PlayerManager *player = JuK::JuKInstance()->playerManager();
0172     float volume = qBound( 0.0f, player->volume() + float( event->angleDelta().y() ) / 4000.0f, 1.0f );
0173     player->setVolume( volume );
0174     volumeChanged( volume );
0175 }