File indexing completed on 2023-05-30 11:30:53

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 <QLabel>
0026 #include <QMenu>
0027 #include <QVBoxLayout>
0028 #include <QWheelEvent>
0029 #include <QWidgetAction>
0030 
0031 #include "iconsupport.h"
0032 #include "juk.h"
0033 #include "playermanager.h"
0034 
0035 using namespace IconSupport;  // ""_icon
0036 
0037 VolumePopupButton::VolumePopupButton( QWidget * parent )
0038     : QToolButton( parent )
0039 {
0040     m_volumeBeforeMute = 0.0;
0041 
0042     //create the volume popup
0043     m_volumeMenu = new QMenu( this );
0044 
0045     auto mainWidget = new QWidget( this );
0046     mainWidget->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred );
0047 
0048     auto mainBox = new QVBoxLayout( mainWidget );
0049     mainBox->setContentsMargins( 0 ,  0 ,  0 ,  0 );
0050     mainBox->setSpacing( 0 );
0051 
0052     m_volumeLabel = new QLabel;
0053     m_volumeLabel->setAlignment( Qt::AlignHCenter );
0054     mainBox->addWidget( m_volumeLabel );
0055 
0056     auto sliderBox = new QWidget;
0057     sliderBox->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred );
0058 
0059     auto sliderBoxLayout = new QHBoxLayout( sliderBox );
0060     sliderBoxLayout->setSpacing( 0 );
0061     sliderBoxLayout->setContentsMargins( 0 ,  0 ,  0 ,  0 );
0062     mainBox->addWidget(sliderBox);
0063 
0064     m_volumeSlider = new VolumeSlider( 100, sliderBox, false );
0065     m_volumeSlider->setFixedHeight( 200 ); // FIXME HiDPI
0066     sliderBoxLayout->addWidget(m_volumeSlider);
0067 
0068     PlayerManager *player = JuK::JuKInstance()->playerManager();
0069 
0070     QWidgetAction *sliderActionWidget = new QWidgetAction( this );
0071     sliderActionWidget->setDefaultWidget( mainWidget );
0072 
0073     connect( m_volumeSlider, &VolumeSlider::volumeChanged, player, &PlayerManager::setVolume );
0074 
0075     m_muteAction = new QAction("audio-volume-muted"_icon, QString(), this );
0076     m_muteAction->setToolTip( i18n( "Mute/Unmute" ) );
0077     m_muteAction->setCheckable( true );
0078     m_muteAction->setChecked( player->muted() );
0079 
0080     connect( m_muteAction, SIGNAL(toggled(bool)), player, SLOT(setMuted(bool)) );
0081     connect( player, SIGNAL(mutedChanged(bool)), this, SLOT(muteStateChanged(bool)) );
0082 
0083     m_volumeMenu->addAction( sliderActionWidget );
0084     m_volumeMenu->addAction( m_muteAction );
0085 
0086     // set correct icon and label initially
0087     volumeChanged( player->volume() );
0088 
0089     connect( player, SIGNAL(volumeChanged(float)), this, SLOT(volumeChanged(float)) );
0090 }
0091 
0092 void
0093 VolumePopupButton::refresh()
0094 {
0095     volumeChanged( JuK::JuKInstance()->playerManager()->volume() );
0096 }
0097 
0098 void
0099 VolumePopupButton::volumeChanged( float newVolume )
0100 {
0101     if (!JuK::JuKInstance()->playerManager()->muted()) {
0102         m_volumeBeforeMute = newVolume;
0103     }
0104 
0105     if ( newVolume <= 0.0001 )
0106         setIcon("audio-volume-muted"_icon);
0107     else if ( newVolume < 0.34 )
0108         setIcon("audio-volume-low"_icon);
0109     else if ( newVolume < 0.67 )
0110         setIcon("audio-volume-medium"_icon);
0111     else
0112         setIcon("audio-volume-high"_icon);
0113 
0114     m_volumeLabel->setText( i18n( "%1%" , int( newVolume * 100 ) ) );
0115 
0116     if( newVolume != m_volumeSlider->value() )
0117         m_volumeSlider->setValue( newVolume * 100 );
0118 
0119     //make sure to uncheck mute toolbar when moving slider
0120     if ( newVolume > 0 )
0121         m_muteAction->setChecked( false );
0122 
0123     const KLocalizedString tip = m_muteAction->isChecked() ? ki18n( "Volume: %1% (muted)" ) : ki18n( "Volume: %1%" );
0124     setToolTip( tip.subs( int( 100 * newVolume ) ).toString() );
0125 }
0126 
0127 void
0128 VolumePopupButton::muteStateChanged( bool muted )
0129 {
0130     if ( muted )
0131     {
0132         const float volume = JuK::JuKInstance()->playerManager()->volume();
0133         setIcon("audio-volume-muted"_icon);
0134         setToolTip( i18n( "Volume: %1% (muted)", int( 100 * volume ) ) );
0135     }
0136     else
0137     {
0138         JuK::JuKInstance()->playerManager()->setVolume( m_volumeBeforeMute );
0139     }
0140 
0141     m_muteAction->setChecked( muted );
0142 }
0143 
0144 void
0145 VolumePopupButton::mouseReleaseEvent( QMouseEvent * event )
0146 {
0147     if( event->button() == Qt::LeftButton )
0148     {
0149         if ( m_volumeMenu->isVisible() )
0150             m_volumeMenu->hide();
0151         else
0152         {
0153             const QPoint pos( 0, height() );
0154             m_volumeMenu->exec( mapToGlobal( pos ) );
0155         }
0156     }
0157     else if( event->button() == Qt::MiddleButton )
0158     {
0159         muteStateChanged( JuK::JuKInstance()->playerManager()->mute() );
0160     }
0161 
0162     QToolButton::mouseReleaseEvent( event );
0163 }
0164 
0165 void
0166 VolumePopupButton::wheelEvent( QWheelEvent * event )
0167 {
0168     event->accept();
0169     PlayerManager *player = JuK::JuKInstance()->playerManager();
0170     float volume = qBound( 0.0f, player->volume() + float( event->angleDelta().y() ) / 4000.0f, 1.0f );
0171     player->setVolume( volume );
0172     volumeChanged( volume );
0173 }