Custom volume control
This commit is contained in:
committed by
craig.p.drummond
parent
797bac910f
commit
42931e1066
@@ -210,7 +210,7 @@ set(CANTATA_SRCS gui/application.cpp gui/main.cpp gui/initialsettingswizard.cpp
|
||||
dynamic/dynamic.cpp dynamic/dynamicpage.cpp dynamic/dynamicproxymodel.cpp dynamic/dynamicruledialog.cpp dynamic/dynamicrulesdialog.cpp
|
||||
widgets/treeview.cpp widgets/listview.cpp widgets/itemview.cpp widgets/autohidingsplitter.cpp widgets/timeslider.cpp
|
||||
widgets/actionlabel.cpp widgets/playqueueview.cpp widgets/groupedview.cpp widgets/actionitemdelegate.cpp widgets/textbrowser.cpp
|
||||
widgets/coverwidget.cpp widgets/volumecontrol.cpp widgets/icons.cpp widgets/genrecombo.cpp widgets/toolbar.cpp widgets/menubutton.cpp
|
||||
widgets/coverwidget.cpp widgets/volumeslider.cpp widgets/icons.cpp widgets/genrecombo.cpp widgets/toolbar.cpp widgets/menubutton.cpp
|
||||
widgets/toolbutton.cpp widgets/wizardpage.cpp widgets/statuslabel.cpp widgets/searchwidget.cpp widgets/messageoverlay.cpp
|
||||
widgets/basicitemdelegate.cpp widgets/sizegrip.cpp widgets/sizewidget.cpp widgets/servicestatuslabel.cpp widgets/spacerwidget.cpp
|
||||
network/networkaccessmanager.cpp network/networkproxyfactory.cpp
|
||||
@@ -233,7 +233,7 @@ set(CANTATA_MOC_HDRS
|
||||
mpd/mpdconnection.h mpd/mpdstats.h mpd/mpdstatus.h
|
||||
dynamic/dynamic.h dynamic/dynamicpage.h dynamic/dynamicruledialog.h dynamic/dynamicrulesdialog.h
|
||||
widgets/treeview.h widgets/listview.h widgets/itemview.h widgets/autohidingsplitter.h widgets/timeslider.h widgets/actionlabel.h
|
||||
widgets/playqueueview.h widgets/groupedview.h widgets/actionitemdelegate.h widgets/coverwidget.h widgets/volumecontrol.h
|
||||
widgets/playqueueview.h widgets/groupedview.h widgets/actionitemdelegate.h widgets/coverwidget.h widgets/volumeslider.h
|
||||
widgets/genrecombo.h widgets/toolbar.h widgets/searchwidget.h widgets/messageoverlay.h
|
||||
network/networkaccessmanager.h
|
||||
context/togglelist.h context/ultimatelyrics.h context/ultimatelyricsprovider.h context/lyricsdialog.h
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
rather than waiting for then to be displayed. Again, no UI for this, and
|
||||
see README for details.
|
||||
32. Slimmer toolbar - song times are now at the ends of the time slider.
|
||||
33. Custom time slider.
|
||||
33. Custom time slider and volume control.
|
||||
34. Prompt before clearing playqueue.
|
||||
35. Only show config pages, and tabs, that are relevant to the enabled views.
|
||||
36. Show action short-cuts in tooltips.
|
||||
|
||||
2
README
2
README
@@ -389,7 +389,7 @@ streams.xml.gz with:
|
||||
</streams>
|
||||
|
||||
streams.xml.gz & icon.svg need to be placed into a gzip'ed tarball named
|
||||
Wicked Radio.streams
|
||||
Wicked Radio.streams.
|
||||
|
||||
With the above example, Cantata would list the following in the streams view:
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
#include "groupedview.h"
|
||||
#include "actionitemdelegate.h"
|
||||
#include "icons.h"
|
||||
#include "volumecontrol.h"
|
||||
#include "volumeslider.h"
|
||||
#include "action.h"
|
||||
#include "actioncollection.h"
|
||||
#include "stdactions.h"
|
||||
@@ -146,39 +146,6 @@ bool DeleteKeyEventHandler::eventFilter(QObject *obj, QEvent *event)
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
bool VolumeSliderEventHandler::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (QEvent::Wheel==event->type() && (!MPDConnection::self()->isMuted() || !qstrcmp("VolumeControl", obj->metaObject()->className()))) {
|
||||
int numDegrees = static_cast<QWheelEvent *>(event)->delta() / 8;
|
||||
int numSteps = numDegrees / 15;
|
||||
if (numSteps > 0) {
|
||||
for (int i = 0; i < numSteps; ++i) {
|
||||
StdActions::self()->increaseVolumeAction->trigger();
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i > numSteps; --i) {
|
||||
StdActions::self()->decreaseVolumeAction->trigger();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
bool VolumeButtonEventHandler::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (QEvent::MouseButtonPress==event->type() && Qt::MiddleButton==static_cast<QMouseEvent *>(event)->buttons()) {
|
||||
down=true;
|
||||
} else if (QEvent::MouseButtonRelease==event->type()) {
|
||||
if (down) {
|
||||
window->muteAction->trigger();
|
||||
}
|
||||
down=false;
|
||||
}
|
||||
return VolumeSliderEventHandler::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
static int nextKey(int &key) {
|
||||
int k=key;
|
||||
|
||||
@@ -288,7 +255,6 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
connectionsAction = ActionCollection::get()->createAction("connections", i18n("Collection"), "network-server");
|
||||
outputsAction = ActionCollection::get()->createAction("outputs", i18n("Outputs"), Icons::self()->speakerIcon);
|
||||
stopAfterTrackAction = ActionCollection::get()->createAction("stopaftertrack", i18n("Stop After Track"), Icons::self()->toolbarStopIcon);
|
||||
muteAction = ActionCollection::get()->createAction("mute", i18n("Mute"));
|
||||
addPlayQueueToStoredPlaylistAction = ActionCollection::get()->createAction("addpqtostoredplaylist", i18n("Add To Stored Playlist"), Icons::self()->playlistIcon);
|
||||
removeFromPlayQueueAction = ActionCollection::get()->createAction("removefromplaylist", i18n("Remove From Play Queue"), "list-remove");
|
||||
copyTrackInfoAction = ActionCollection::get()->createAction("copytrackinfo", i18n("Copy Track Info"));
|
||||
@@ -342,19 +308,14 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
updateNextTrack(-1);
|
||||
StdActions::self()->prevTrackAction->setEnabled(false);
|
||||
enableStopActions(false);
|
||||
volumeSlider->initActions();
|
||||
|
||||
addAction(StdActions::self()->increaseVolumeAction);
|
||||
addAction(StdActions::self()->decreaseVolumeAction);
|
||||
addAction(muteAction);
|
||||
#if defined ENABLE_KDE_SUPPORT
|
||||
StdActions::self()->prevTrackAction->setGlobalShortcut(KShortcut(Qt::Key_MediaPrevious));
|
||||
StdActions::self()->nextTrackAction->setGlobalShortcut(KShortcut(Qt::Key_MediaNext));
|
||||
StdActions::self()->playPauseTrackAction->setGlobalShortcut(KShortcut(Qt::Key_MediaPlay));
|
||||
StdActions::self()->stopPlaybackAction->setGlobalShortcut(KShortcut(Qt::Key_MediaStop));
|
||||
StdActions::self()->stopAfterCurrentTrackAction->setGlobalShortcut(KShortcut());
|
||||
StdActions::self()->increaseVolumeAction->setGlobalShortcut(KShortcut(Qt::Key_VolumeUp));
|
||||
StdActions::self()->decreaseVolumeAction->setGlobalShortcut(KShortcut(Qt::Key_VolumeDown));
|
||||
muteAction->setGlobalShortcut(KShortcut(Qt::Key_VolumeMute));
|
||||
#endif
|
||||
|
||||
copyTrackInfoAction->setShortcut(QKeySequence::Copy);
|
||||
@@ -374,13 +335,6 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
devicesTabAction->setShortcut(Qt::AltModifier+nextKey(pageKey));
|
||||
#endif // ENABLE_DEVICES_SUPPORT
|
||||
|
||||
volumeSliderEventHandler = new VolumeSliderEventHandler(this);
|
||||
volumeControl = new VolumeControl(volumeButton);
|
||||
volumeControl->installEventFilter(volumeSliderEventHandler);
|
||||
volumeControl->installSliderEventFilter(volumeSliderEventHandler);
|
||||
volumeButton->installEventFilter(new VolumeButtonEventHandler(this));
|
||||
volumeButton->setMenu(volumeControl);
|
||||
|
||||
connectionsAction->setMenu(new QMenu(this));
|
||||
connectionsGroup=new QActionGroup(connectionsAction->menu());
|
||||
outputsAction->setMenu(new QMenu(this));
|
||||
@@ -388,7 +342,6 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
addPlayQueueToStoredPlaylistAction->setMenu(PlaylistsModel::self()->menu());
|
||||
|
||||
menuButton->setMenu(mainMenu);
|
||||
volumeButton->setIcon(Icons::self()->toolbarVolumeHighIcon);
|
||||
|
||||
playPauseTrackButton->setDefaultAction(StdActions::self()->playPauseTrackAction);
|
||||
stopTrackButton->setDefaultAction(StdActions::self()->stopPlaybackAction);
|
||||
@@ -501,7 +454,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
QList<QToolButton *> playbackBtns;
|
||||
QList<QToolButton *> controlBtns;
|
||||
playbackBtns << prevTrackButton << stopTrackButton << playPauseTrackButton << nextTrackButton;
|
||||
controlBtns << volumeButton << menuButton << songInfoButton;
|
||||
controlBtns << menuButton << songInfoButton;
|
||||
|
||||
int playbackIconSize=28;
|
||||
int controlIconSize=22;
|
||||
@@ -761,11 +714,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
connect(StdActions::self()->stopPlaybackAction, SIGNAL(triggered(bool)), this, SLOT(stopPlayback()));
|
||||
connect(StdActions::self()->stopAfterCurrentTrackAction, SIGNAL(triggered(bool)), this, SLOT(stopAfterCurrentTrack()));
|
||||
connect(stopAfterTrackAction, SIGNAL(triggered(bool)), this, SLOT(stopAfterTrack()));
|
||||
connect(volumeControl, SIGNAL(valueChanged(int)), MPDConnection::self(), SLOT(setVolume(int)));
|
||||
connect(this, SIGNAL(setVolume(int)), MPDConnection::self(), SLOT(setVolume(int)));
|
||||
connect(StdActions::self()->increaseVolumeAction, SIGNAL(triggered(bool)), volumeControl, SLOT(increaseVolume()));
|
||||
connect(StdActions::self()->decreaseVolumeAction, SIGNAL(triggered(bool)), volumeControl, SLOT(decreaseVolume()));
|
||||
connect(muteAction, SIGNAL(triggered(bool)), MPDConnection::self(), SLOT(toggleMute()));
|
||||
connect(positionSlider, SIGNAL(sliderReleased()), this, SLOT(setPosition()));
|
||||
connect(randomPlayQueueAction, SIGNAL(triggered(bool)), MPDConnection::self(), SLOT(setRandom(bool)));
|
||||
connect(repeatPlayQueueAction, SIGNAL(triggered(bool)), MPDConnection::self(), SLOT(setRepeat(bool)));
|
||||
@@ -1639,13 +1588,13 @@ void MainWindow::startVolumeFade()
|
||||
}
|
||||
|
||||
stopState=StopState_Stopping;
|
||||
volumeSlider->setFadingStop(true);
|
||||
if (!volumeFade) {
|
||||
volumeFade = new QPropertyAnimation(this, "volume");
|
||||
volumeFade->setDuration(Settings::self()->stopFadeDuration());
|
||||
}
|
||||
origVolume=volume;
|
||||
lastVolume=volume;
|
||||
volumeFade->setStartValue(volume);
|
||||
origVolume=lastVolume=volumeSlider->value();
|
||||
volumeFade->setStartValue(origVolume);
|
||||
volumeFade->setEndValue(-1);
|
||||
volumeFade->start();
|
||||
}
|
||||
@@ -1659,11 +1608,16 @@ void MainWindow::stopVolumeFade()
|
||||
}
|
||||
}
|
||||
|
||||
int MainWindow::mpdVolume() const
|
||||
{
|
||||
return volumeSlider->value();
|
||||
}
|
||||
|
||||
void MainWindow::setMpdVolume(int v)
|
||||
{
|
||||
if (-1==v) {
|
||||
volume=origVolume;
|
||||
emit setVolume(origVolume);
|
||||
volumeSlider->setFadingStop(false);
|
||||
emit setVolume(volumeSlider->value());
|
||||
if (StopState_Stopping==stopState) {
|
||||
emit stop();
|
||||
}
|
||||
@@ -1942,44 +1896,6 @@ void MainWindow::updateStatus(MPDStatus * const status)
|
||||
}
|
||||
}
|
||||
|
||||
if (!stopState) {
|
||||
volume=status->volume();
|
||||
|
||||
if (volume<=0) {
|
||||
volumeButton->setIcon(Icons::self()->toolbarVolumeMutedIcon);
|
||||
} else if (volume<=33) {
|
||||
volumeButton->setIcon(Icons::self()->toolbarVolumeLowIcon);
|
||||
} else if (volume<=67) {
|
||||
volumeButton->setIcon(Icons::self()->toolbarVolumeMediumIcon);
|
||||
} else {
|
||||
volumeButton->setIcon(Icons::self()->toolbarVolumeHighIcon);
|
||||
}
|
||||
|
||||
volumeControl->blockSignals(true);
|
||||
if (volume<0) {
|
||||
volumeButton->setEnabled(false);
|
||||
volumeButton->setToolTip(i18n("Volume Disabled"));
|
||||
volumeControl->setToolTip(i18n("Volume Disabled"));
|
||||
volumeControl->setValue(0);
|
||||
} else {
|
||||
int unmuteVolume=-1;
|
||||
if (0==volume) {
|
||||
unmuteVolume=MPDConnection::self()->unmuteVolume();
|
||||
if (unmuteVolume>0) {
|
||||
volume=unmuteVolume;
|
||||
}
|
||||
}
|
||||
volumeButton->setEnabled(true);
|
||||
volumeButton->setToolTip(unmuteVolume>0 ? i18n("Volume %1% (Muted)", volume) : i18n("Volume %1%", volume));
|
||||
volumeControl->setToolTip(volumeButton->toolTip());
|
||||
volumeControl->setValue(volume);
|
||||
}
|
||||
muteAction->setEnabled(volumeButton->isEnabled());
|
||||
StdActions::self()->increaseVolumeAction->setEnabled(volumeButton->isEnabled());
|
||||
StdActions::self()->decreaseVolumeAction->setEnabled(volumeButton->isEnabled());
|
||||
volumeControl->blockSignals(false);
|
||||
}
|
||||
|
||||
randomPlayQueueAction->setChecked(status->random());
|
||||
repeatPlayQueueAction->setChecked(status->repeat());
|
||||
singlePlayQueueAction->setChecked(status->single());
|
||||
@@ -2774,7 +2690,7 @@ void MainWindow::showSearch()
|
||||
|
||||
bool MainWindow::fadeWhenStop() const
|
||||
{
|
||||
return fadeStop && volumeButton->isEnabled();
|
||||
return fadeStop && volumeSlider->isEnabled();
|
||||
}
|
||||
|
||||
void MainWindow::expandAll()
|
||||
|
||||
@@ -75,7 +75,6 @@ class QTimer;
|
||||
class QPropertyAnimation;
|
||||
class QActionGroup;
|
||||
class QDateTime;
|
||||
class VolumeControl;
|
||||
class TrayItem;
|
||||
class GtkProxyStyle;
|
||||
|
||||
@@ -104,26 +103,6 @@ private:
|
||||
QAction *act;
|
||||
};
|
||||
|
||||
class VolumeSliderEventHandler : public QObject
|
||||
{
|
||||
public:
|
||||
VolumeSliderEventHandler(MainWindow *w) : QObject((QObject *)w), window(w) { }
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event);
|
||||
protected:
|
||||
MainWindow * const window;
|
||||
};
|
||||
|
||||
class VolumeButtonEventHandler : public VolumeSliderEventHandler
|
||||
{
|
||||
public:
|
||||
VolumeButtonEventHandler(MainWindow *w) : VolumeSliderEventHandler(w), down(false) { }
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event);
|
||||
private:
|
||||
bool down;
|
||||
};
|
||||
|
||||
#ifdef ENABLE_KDE_SUPPORT
|
||||
class MainWindow : public KXmlGuiWindow, private Ui::MainWindow
|
||||
#else
|
||||
@@ -154,7 +133,7 @@ public:
|
||||
MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
int mpdVolume() const { return volume; }
|
||||
int mpdVolume() const;
|
||||
int currentTrackPosition() const;
|
||||
QString coverFile() const;
|
||||
|
||||
@@ -200,7 +179,7 @@ public Q_SLOTS:
|
||||
void configureShortcuts();
|
||||
void saveShortcuts();
|
||||
#endif
|
||||
void setMpdVolume(int );
|
||||
void setMpdVolume(int v);
|
||||
void songLoaded();
|
||||
void messageWidgetVisibility(bool v);
|
||||
void mpdConnectionStateChanged(bool connected);
|
||||
@@ -319,8 +298,6 @@ private:
|
||||
PlayQueueModel playQueueModel;
|
||||
PlayQueueProxyModel playQueueProxyModel;
|
||||
bool autoScrollPlayQueue;
|
||||
VolumeSliderEventHandler *volumeSliderEventHandler;
|
||||
VolumeControl *volumeControl;
|
||||
Action *prefAction;
|
||||
#ifdef ENABLE_KDE_SUPPORT
|
||||
Action *shortcutsAction;
|
||||
@@ -330,7 +307,6 @@ private:
|
||||
Action *outputsAction;
|
||||
QActionGroup *connectionsGroup;
|
||||
Action *stopAfterTrackAction;
|
||||
Action *muteAction;
|
||||
Action *removeFromPlayQueueAction;
|
||||
Action *addPlayQueueToStoredPlaylistAction;
|
||||
Action *promptClearPlayQueueAction;
|
||||
@@ -430,9 +406,6 @@ private:
|
||||
QMediaPlayer *httpStream;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
friend class VolumeSliderEventHandler;
|
||||
friend class VolumeButtonEventHandler;
|
||||
friend class CoverEventHandler;
|
||||
friend class TrayItem;
|
||||
};
|
||||
|
||||
@@ -108,10 +108,26 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="ToolButton" name="songInfoButton"/>
|
||||
<widget class="VolumeSlider" name="volumeSlider"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ToolButton" name="volumeButton"/>
|
||||
<spacer name="volumeSliderSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>4</width>
|
||||
<height>4</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ToolButton" name="songInfoButton"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MenuButton" name="menuButton"/>
|
||||
@@ -429,6 +445,11 @@
|
||||
<extends>QWidget</extends>
|
||||
<header>sizegrip.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>VolumeSlider</class>
|
||||
<extends>QSlider</extends>
|
||||
<header>volumeslider.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
@@ -37,6 +37,32 @@
|
||||
#include "song.h"
|
||||
#include "stdactions.h"
|
||||
|
||||
class VolumeSliderEventHandler : public QObject
|
||||
{
|
||||
public:
|
||||
VolumeSliderEventHandler(QObject *p) : QObject(p) { }
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (QEvent::Wheel==event->type()) {
|
||||
int numDegrees = static_cast<QWheelEvent *>(event)->delta() / 8;
|
||||
int numSteps = numDegrees / 15;
|
||||
if (numSteps > 0) {
|
||||
for (int i = 0; i < numSteps; ++i) {
|
||||
StdActions::self()->increaseVolumeAction->trigger();
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i > numSteps; --i) {
|
||||
StdActions::self()->decreaseVolumeAction->trigger();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
};
|
||||
|
||||
TrayItem::TrayItem(MainWindow *p)
|
||||
: QObject(p)
|
||||
, mw(p)
|
||||
@@ -93,7 +119,7 @@ void TrayItem::setup()
|
||||
}
|
||||
|
||||
trayItem = new QSystemTrayIcon(this);
|
||||
trayItem->installEventFilter(mw->volumeSliderEventHandler);
|
||||
trayItem->installEventFilter(new VolumeSliderEventHandler(this));
|
||||
trayItemMenu = new QMenu(0);
|
||||
trayItemMenu->addAction(StdActions::self()->prevTrackAction);
|
||||
trayItemMenu->addAction(StdActions::self()->playPauseTrackAction);
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Cantata
|
||||
*
|
||||
* Copyright (c) 2011-2013 Craig Drummond <craig.p.drummond@gmail.com>
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "volumecontrol.h"
|
||||
#include "icon.h"
|
||||
#include <QFrame>
|
||||
#include <QSlider>
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
#include <QApplication>
|
||||
|
||||
VolumeControl::VolumeControl(QWidget *parent)
|
||||
: QMenu(parent)
|
||||
{
|
||||
QFrame *w = new QFrame(this);
|
||||
slider = new QSlider(w);
|
||||
|
||||
QLabel *increase = new QLabel(QLatin1String("+"), w);
|
||||
QLabel *decrease = new QLabel(QLatin1String("-"), w);
|
||||
increase->setAlignment(Qt::AlignHCenter);
|
||||
decrease->setAlignment(Qt::AlignHCenter);
|
||||
|
||||
QVBoxLayout *l = new QVBoxLayout(w);
|
||||
l->setMargin(3);
|
||||
l->setSpacing(0);
|
||||
l->addWidget(increase);
|
||||
l->addWidget(slider);
|
||||
l->addWidget(decrease);
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->setMargin(0);
|
||||
layout->addWidget(w);
|
||||
connect(slider, SIGNAL(valueChanged(int)), SIGNAL(valueChanged(int)));
|
||||
int size=Icon::stdSize(QApplication::fontMetrics().height());
|
||||
|
||||
slider->setMinimumHeight(size*12);
|
||||
slider->setMaximumHeight(size*12);
|
||||
slider->setMinimumWidth(size*1.5);
|
||||
slider->setMaximumWidth(size*1.5);
|
||||
slider->setOrientation(Qt::Vertical);
|
||||
slider->setMinimum(0);
|
||||
slider->setMaximum(100);
|
||||
slider->setPageStep(5);
|
||||
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
VolumeControl::~VolumeControl()
|
||||
{
|
||||
}
|
||||
|
||||
void VolumeControl::installSliderEventFilter(QObject *filter)
|
||||
{
|
||||
slider->installEventFilter(filter);
|
||||
}
|
||||
|
||||
void VolumeControl::increaseVolume()
|
||||
{
|
||||
slider->triggerAction(QAbstractSlider::SliderPageStepAdd);
|
||||
}
|
||||
|
||||
void VolumeControl::decreaseVolume()
|
||||
{
|
||||
slider->triggerAction(QAbstractSlider::SliderPageStepSub);
|
||||
}
|
||||
|
||||
void VolumeControl::setValue(int v)
|
||||
{
|
||||
slider->setValue(v);
|
||||
}
|
||||
|
||||
302
widgets/volumeslider.cpp
Normal file
302
widgets/volumeslider.cpp
Normal file
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
* Cantata
|
||||
*
|
||||
* Copyright (c) 2011-2013 Craig Drummond <craig.p.drummond@gmail.com>
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "volumeslider.h"
|
||||
#include "localize.h"
|
||||
#include "mpdconnection.h"
|
||||
#include "mpdstatus.h"
|
||||
#include "action.h"
|
||||
#include "actioncollection.h"
|
||||
#include "stdactions.h"
|
||||
#include <QStyle>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QProxyStyle>
|
||||
#include <QApplication>
|
||||
#include <QLabel>
|
||||
#include <QMouseEvent>
|
||||
#include <QMenu>
|
||||
#ifdef ENABLE_KDE_SUPPORT
|
||||
#include <KDE/KShortcut>
|
||||
#endif
|
||||
|
||||
class ProxyStyle : public QProxyStyle
|
||||
{
|
||||
public:
|
||||
ProxyStyle()
|
||||
: QProxyStyle()
|
||||
{
|
||||
setBaseStyle(qApp->style());
|
||||
}
|
||||
|
||||
int styleHint(StyleHint stylehint, const QStyleOption *opt, const QWidget *widget, QStyleHintReturn *returnData) const
|
||||
{
|
||||
if (SH_Slider_AbsoluteSetButtons==stylehint) {
|
||||
return Qt::LeftButton|QProxyStyle::styleHint(stylehint, opt, widget, returnData);
|
||||
} else {
|
||||
return QProxyStyle::styleHint(stylehint, opt, widget, returnData);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static const int constWidthStep=4;
|
||||
static const int constHeightStep=2;
|
||||
|
||||
static QColor clampColor(const QColor &col)
|
||||
{
|
||||
static const int constMin=64;
|
||||
static const int constMax=196;
|
||||
|
||||
if (col.value()<constMin) {
|
||||
return QColor(constMin, constMin, constMin);
|
||||
} else if (col.value()>constMax) {
|
||||
return QColor(constMax, constMax, constMax);
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
||||
VolumeSlider::VolumeSlider(QWidget *p)
|
||||
: QSlider(p)
|
||||
, lineWidth(0)
|
||||
, shown(false)
|
||||
, down(false)
|
||||
, fadingStop(false)
|
||||
, muteAction(0)
|
||||
, menu(0)
|
||||
{
|
||||
int fontHeight=fontMetrics().height();
|
||||
setRange(0, 100);
|
||||
setPageStep(5);
|
||||
lineWidth=fontHeight>22 ? 2 : 1;
|
||||
|
||||
int w=lineWidth*constWidthStep*19;
|
||||
int h=lineWidth*constHeightStep*10;
|
||||
setFixedHeight(h+1);
|
||||
setFixedWidth(w);
|
||||
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
setOrientation(Qt::Horizontal);
|
||||
setStyle(new ProxyStyle());
|
||||
setStyleSheet(QString("QSlider::groove:horizontal {border: 0px;} "
|
||||
"QSlider::sub-page:horizontal {border: 0px;} "
|
||||
"QSlider::handle:horizontal {width: 1px; height:%1px; margin:0;}").arg(h));
|
||||
textCol=clampColor(palette().color(QPalette::Active, QPalette::Text));
|
||||
pixmaps[0]=pixmaps[1]=0;
|
||||
generatePixmaps();
|
||||
}
|
||||
|
||||
void VolumeSlider::initActions()
|
||||
{
|
||||
if (muteAction) {
|
||||
return;
|
||||
}
|
||||
muteAction = ActionCollection::get()->createAction("mute", i18n("Mute"));
|
||||
addAction(muteAction);
|
||||
#ifdef ENABLE_KDE_SUPPORT
|
||||
muteAction->setGlobalShortcut(KShortcut(Qt::Key_VolumeMute));
|
||||
StdActions::self()->increaseVolumeAction->setGlobalShortcut(KShortcut(Qt::Key_VolumeUp));
|
||||
StdActions::self()->decreaseVolumeAction->setGlobalShortcut(KShortcut(Qt::Key_VolumeDown));
|
||||
#endif
|
||||
connect(muteAction, SIGNAL(triggered(bool)), MPDConnection::self(), SLOT(toggleMute()));
|
||||
connect(MPDStatus::self(), SIGNAL(updated()), this, SLOT(updateMpdStatus()));
|
||||
connect(StdActions::self()->increaseVolumeAction, SIGNAL(triggered(bool)), this, SLOT(increaseVolume()));
|
||||
connect(StdActions::self()->decreaseVolumeAction, SIGNAL(triggered(bool)), this, SLOT(decreaseVolume()));
|
||||
connect(this, SIGNAL(valueChanged(int)), MPDConnection::self(), SLOT(setVolume(int)));
|
||||
}
|
||||
|
||||
void VolumeSlider::showEvent(QShowEvent *e)
|
||||
{
|
||||
if (!shown) {
|
||||
shown=true;
|
||||
QLabel lbl(parentWidget());
|
||||
lbl.ensurePolished();
|
||||
QColor col=clampColor(lbl.palette().text().color());
|
||||
|
||||
if (col!=textCol) {
|
||||
textCol=col;
|
||||
generatePixmaps();
|
||||
}
|
||||
}
|
||||
QSlider::showEvent(e);
|
||||
}
|
||||
|
||||
void VolumeSlider::paintEvent(QPaintEvent *)
|
||||
{
|
||||
bool reverse=Qt::RightToLeft==layoutDirection();
|
||||
QPainter p(this);
|
||||
bool muted=MPDConnection::self()->isMuted();
|
||||
if (muted) {
|
||||
p.setOpacity(0.25);
|
||||
}
|
||||
|
||||
int steps=(value()/10.0)+0.5;
|
||||
p.drawPixmap(0, 0, *(pixmaps[0]));
|
||||
if (steps>0) {
|
||||
if (steps<10) {
|
||||
p.setClipRect(reverse
|
||||
? QRect(width()-((steps*constWidthStep*2)-constWidthStep), 0, width(), height())
|
||||
: QRect(0, 0, (steps*constWidthStep*2)-constWidthStep, height()));
|
||||
p.setClipping(true);
|
||||
}
|
||||
p.drawPixmap(0, 0, *(pixmaps[1]));
|
||||
if (steps<10) {
|
||||
p.setClipping(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (muted) {
|
||||
p.setOpacity(1.0);
|
||||
}
|
||||
p.setPen(textCol);
|
||||
QFont f(font());
|
||||
f.setPixelSize(height()/2.0);
|
||||
p.setFont(f);
|
||||
|
||||
if (muted) {
|
||||
QFontMetrics fm(p.fontMetrics());
|
||||
QString text(fm.elidedText(i18n("Muted"), reverse ? Qt::ElideLeft : Qt::ElideRight, width(), QPalette::WindowText));
|
||||
p.drawText(rect(), Qt::AlignLeft, text);
|
||||
} else {
|
||||
p.drawText(rect(), Qt::AlignLeft, QString("%1%").arg(value()));
|
||||
}
|
||||
}
|
||||
|
||||
void VolumeSlider::mousePressEvent(QMouseEvent *ev)
|
||||
{
|
||||
if (Qt::MiddleButton==ev->buttons()) {
|
||||
down=true;
|
||||
} else {
|
||||
QSlider::mousePressEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
void VolumeSlider::mouseReleaseEvent(QMouseEvent *ev)
|
||||
{
|
||||
if (down) {
|
||||
down=false;
|
||||
muteAction->trigger();
|
||||
update();
|
||||
} else {
|
||||
QSlider::mouseReleaseEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
void VolumeSlider::contextMenuEvent(QContextMenuEvent *ev)
|
||||
{
|
||||
static const char *constValProp="val";
|
||||
if (!menu) {
|
||||
menu=new QMenu(this);
|
||||
menu->setTitle(i18n("Volume"));
|
||||
muteMenuAction=menu->addAction(i18n("Mute"));
|
||||
muteMenuAction->setProperty(constValProp, -1);
|
||||
for (int i=0; i<11; ++i) {
|
||||
menu->addAction(QString("%1%").arg(i*10))->setProperty(constValProp, i*10);
|
||||
}
|
||||
}
|
||||
|
||||
muteMenuAction->setText(MPDConnection::self()->isMuted() ? i18n("Unmute") : i18n("Mute"));
|
||||
QAction *ret = menu->exec(mapToGlobal(ev->pos()));
|
||||
if (ret) {
|
||||
int val=ret->property(constValProp).toInt();
|
||||
if (-1==val) {
|
||||
muteAction->trigger();
|
||||
} else {
|
||||
setValue(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VolumeSlider::updateMpdStatus()
|
||||
{
|
||||
if (fadingStop) {
|
||||
return;
|
||||
}
|
||||
|
||||
int volume=MPDStatus::self()->volume();
|
||||
|
||||
blockSignals(true);
|
||||
if (volume<0) {
|
||||
setEnabled(false);
|
||||
setToolTip(i18n("Volume Disabled"));
|
||||
setValue(0);
|
||||
} else {
|
||||
int unmuteVolume=-1;
|
||||
if (0==volume) {
|
||||
unmuteVolume=MPDConnection::self()->unmuteVolume();
|
||||
if (unmuteVolume>0) {
|
||||
volume=unmuteVolume;
|
||||
}
|
||||
}
|
||||
setEnabled(true);
|
||||
setToolTip(unmuteVolume>0 ? i18n("Volume %1% (Muted)", volume) : i18n("Volume %1%", volume));
|
||||
setValue(volume);
|
||||
}
|
||||
update();
|
||||
muteAction->setEnabled(isEnabled());
|
||||
StdActions::self()->increaseVolumeAction->setEnabled(isEnabled());
|
||||
StdActions::self()->decreaseVolumeAction->setEnabled(isEnabled());
|
||||
blockSignals(false);
|
||||
}
|
||||
|
||||
void VolumeSlider::increaseVolume()
|
||||
{
|
||||
triggerAction(QAbstractSlider::SliderPageStepAdd);
|
||||
}
|
||||
|
||||
void VolumeSlider::decreaseVolume()
|
||||
{
|
||||
triggerAction(QAbstractSlider::SliderPageStepSub);
|
||||
}
|
||||
|
||||
void VolumeSlider::generatePixmaps()
|
||||
{
|
||||
if (pixmaps[0]) {
|
||||
delete pixmaps[0];
|
||||
}
|
||||
if (pixmaps[1]) {
|
||||
delete pixmaps[1];
|
||||
}
|
||||
pixmaps[0]=generatePixmap(false);
|
||||
pixmaps[1]=generatePixmap(true);
|
||||
}
|
||||
|
||||
QPixmap * VolumeSlider::generatePixmap(bool filled)
|
||||
{
|
||||
bool reverse=Qt::RightToLeft==layoutDirection();
|
||||
QPixmap *pix=new QPixmap(size());
|
||||
pix->fill(Qt::transparent);
|
||||
QPainter p(pix);
|
||||
p.setPen(textCol);
|
||||
for (int i=0; i<10; ++i) {
|
||||
int barHeight=(lineWidth*constHeightStep)*(i+1);
|
||||
QRect r(reverse ? pix->width()-(constWidthStep+(i*lineWidth*constWidthStep*2))
|
||||
: i*lineWidth*constWidthStep*2,
|
||||
pix->height()-(barHeight+1), (lineWidth*constWidthStep)-1, barHeight);
|
||||
if (filled) {
|
||||
p.fillRect(r, textCol);
|
||||
} else {
|
||||
p.drawRect(r);
|
||||
}
|
||||
}
|
||||
return pix;
|
||||
}
|
||||
@@ -21,35 +21,52 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef VOLUMECONTROL_H
|
||||
#define VOLUMECONTROL_H
|
||||
#ifndef VOLUMESLIDER_H
|
||||
#define VOLUMESLIDER_H
|
||||
|
||||
#include <QMenu>
|
||||
#include <QSlider>
|
||||
#include <QColor>
|
||||
|
||||
class QSlider;
|
||||
class QPixmap;
|
||||
class QMenu;
|
||||
class Action;
|
||||
class QAction;
|
||||
|
||||
class VolumeControl : public QMenu
|
||||
class VolumeSlider : public QSlider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VolumeControl(QWidget *parent);
|
||||
virtual ~VolumeControl();
|
||||
VolumeSlider(QWidget *p=0);
|
||||
virtual ~VolumeSlider() { }
|
||||
|
||||
void installSliderEventFilter(QObject *filter);
|
||||
void initActions();
|
||||
void setFadingStop(bool f) { fadingStop=f; }
|
||||
void showEvent(QShowEvent *e);
|
||||
void paintEvent(QPaintEvent *ev);
|
||||
void mousePressEvent(QMouseEvent *ev);
|
||||
void mouseReleaseEvent(QMouseEvent *ev);
|
||||
void contextMenuEvent(QContextMenuEvent *ev);
|
||||
|
||||
public Q_SLOTS:
|
||||
private Q_SLOTS:
|
||||
void updateMpdStatus();
|
||||
void increaseVolume();
|
||||
void decreaseVolume();
|
||||
void setValue(int v);
|
||||
|
||||
QSlider * sliderWidget() { return slider; }
|
||||
|
||||
Q_SIGNALS:
|
||||
void valueChanged(int v);
|
||||
|
||||
private:
|
||||
QSlider *slider;
|
||||
void generatePixmaps();
|
||||
QPixmap * generatePixmap(bool filled);
|
||||
|
||||
private:
|
||||
int lineWidth;
|
||||
bool shown;
|
||||
bool down;
|
||||
bool fadingStop;
|
||||
QColor textCol;
|
||||
QPixmap *pixmaps[2];
|
||||
Action *muteAction;
|
||||
QAction *muteMenuAction;
|
||||
QMenu *menu;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user