Commit 60d001b6 authored by Jonathan Marten's avatar Jonathan Marten

VolumeSliderExtraData: Eliminate class and source files

Since every slider is now a VolumeSlider, that class can maintain
the extra data.  Simplifies the implementation of MDWSlider.
parent 455635f8
......@@ -620,14 +620,13 @@ void MDWSlider::addSliders( QBoxLayout *volLayout, char type, Volume& vol,
subcontrolLabel = createLabel(this, subcontrolTranslation, orientation(), true);
volLayout->addWidget(subcontrolLabel);
QAbstractSlider *slider = new VolumeSlider(orientation(), this);
VolumeSlider *slider = new VolumeSlider(orientation(), this);
slider->setMinimum(minvol);
slider->setMaximum(maxvol);
slider->setPageStep(maxvol / Volume::VOLUME_PAGESTEP_DIVISOR);
slider->setValue( vol.getVolume( vc.chid ) );
volumeValues.push_back( vol.getVolume( vc.chid ) );
extraData(slider).setSubcontrolLabel(subcontrolLabel);
if (orientation()==Qt::Vertical) slider->setMinimumHeight(minSliderSize);
else slider->setMinimumWidth(minSliderSize);
......@@ -635,7 +634,8 @@ void MDWSlider::addSliders( QBoxLayout *volLayout, char type, Volume& vol,
slider->setStyleSheet("QSlider { background-color: " + profileControl()->getBackgroundColor() + " }");
}
extraData(slider).setChid(vc.chid);
slider->setSubControlLabel(subcontrolLabel);
slider->setChannelId(vc.chid);
if ( type == 'p' ) {
slider->setToolTip( tooltipText );
......@@ -655,25 +655,6 @@ void MDWSlider::addSliders( QBoxLayout *volLayout, char type, Volume& vol,
}
}
/**
* Return the VolumeSliderExtraData from either VolumeSlider or KSmallSlider.
* You MUST extend this method, should you decide to add more Slider Widget classes.
*
* @param slider
* @return
*/
VolumeSliderExtraData& MDWSlider::extraData(QAbstractSlider *slider)
{
VolumeSlider* sl = qobject_cast<VolumeSlider*>(slider);
if ( sl )
return sl->extraData;
// TODO: temporary dummy value
static VolumeSliderExtraData ed;
return (ed);
}
void MDWSlider::sliderPressed()
{
......@@ -720,32 +701,36 @@ MDWSlider::setStereoLinkedInternal(QList<QAbstractSlider *>& ref_sliders, bool s
return;
bool first = true;
for (QAbstractSlider *slider1 : ref_sliders)
for (QAbstractSlider *slider : ref_sliders)
{
slider1->setVisible(!m_linked || first); // One slider (the 1st) is always shown
extraData(slider1).getSubcontrolLabel()->setVisible(!m_linked && showSubcontrolLabels); // (*)
first = false;
/* (*) cesken: I have excluded the "|| first" check because the text would not be nice:
* It would be "Left" or "Capture Left", while it should be "Playback" and "Capture" in the "linked" case.
*
* But the only affected situation is when we have playback AND capture on the same control, where we show no label.
* It would be nice to put at least a "Capture" label on the capture subcontrol instead.
* To achieve this we would need to exchange the Text on the first capture subcontrol dynamically. This can
* be done, but I'll leave this open for now.
*/
}
slider->setVisible(!m_linked || first); // One slider (the 1st) is always shown
const VolumeSlider *vs = qobject_cast<VolumeSlider *>(slider);
// cesken: Not including "|| first" in the check below because the text would
// not look nice: it would show "Left" or "Capture Left", while it should
// be "Playback" and "Capture" in the "linked" case.
//
// But the only affected situation is when we have playback AND capture on
// the same control, where we show no label. It would be nice to at least
// put a "Capture" label on the capture subcontrol instead. To achieve this
// we would need to change the text on the first capture subcontrol dynamically.
// This can be done, but I'll leave this open for now.
if (vs!=nullptr) vs->subControlLabel()->setVisible(!m_linked && showSubcontrolLabels);
// Redo the tickmarks to last slider in the slider list.
// The implementation is not obvious, so lets explain:
// We ALWAYS have tickmarks on the LAST slider. Sometimes the slider is not shown, and then we just don't bother.
// a) So, if the last slider has tickmarks, we can always call setTicks( true ).
// b) if the last slider has NO tickmarks, there ae no tickmarks at all, and we don't need to redo the tickmarks.
QSlider* slider = qobject_cast<QSlider*>( ref_sliders.last() );
if( slider && slider->tickPosition() != QSlider::NoTicks)
setTicks( true );
first = false;
}
// Redo the tickmarks for the last slider in the slider list.
//
// The implementation is not obvious, so let's explain: We ALWAYS have tickmarks
// on the LAST slider. Sometimes the slider is not shown, and then we just don't bother.
//
// a) So, if the last slider has tickmarks, we can always call setTicks(true).
//
// b) if the last slider has NO tickmarks, there are no tickmarks at all, and we
// don't need to redo the tickmarks.
QSlider *slider = qobject_cast<QSlider *>(ref_sliders.last());
if (slider!=nullptr && slider->tickPosition()!=QSlider::NoTicks) setTicks(true);
}
......@@ -839,9 +824,8 @@ void MDWSlider::volumeChangeInternal(Volume& vol, QList<QAbstractSlider *>& ref_
{
for (int i = 0; i<ref_sliders.count(); ++i)
{ // iterate over all sliders
// TODO: const
QAbstractSlider *sliderWidget = ref_sliders[i];
vol.setVolume(extraData(sliderWidget).getChid(), sliderWidget->value());
const VolumeSlider *vs = qobject_cast<VolumeSlider *>(ref_sliders.at(i));
if (vs!=nullptr) vol.setVolume(vs->channelId(), vs->value());
}
}
}
......@@ -968,14 +952,15 @@ void MDWSlider::updateInternal(Volume& vol, QList<QAbstractSlider *>& ref_slider
{
for (int i = 0; i<ref_sliders.count(); ++i)
{ // for all sliders
QAbstractSlider *slider = ref_sliders.at( i );
Volume::ChannelID chid = extraData(slider).getChid();
VolumeSlider *slider = qobject_cast<VolumeSlider *>(ref_sliders.at(i));
if (slider==nullptr) continue;
Volume::ChannelID chid = slider->channelId();
long useVolume = muted ? 0 : vol.getVolumeForGUI(chid);
int volume_index;
QSignalBlocker blocker(slider);
// --- Avoid feedback loops START -----------------
volume_index = volumeValues.indexOf(useVolume);
const int volume_index = volumeValues.indexOf(useVolume);
if (volume_index>-1 && --m_waitForSoundSetComplete<1)
{
m_waitForSoundSetComplete = 0;
......
......@@ -119,8 +119,6 @@ private:
bool hasMuteButton() const { return (m_muteButton!=nullptr); }
bool hasCaptureLED() const { return (m_captureButton!=nullptr); }
VolumeSliderExtraData &extraData(QAbstractSlider *slider);
QString calculatePlaybackIcon(MediaController::PlayState playState);
QWidget *guiAddButtonSpacer();
void guiAddCaptureButton(const QString &captureTooltipText);
......
......@@ -24,19 +24,50 @@
#include <QStyleOption>
#include <QFontMetrics>
VolumeSlider::VolumeSlider(Qt::Orientation orientation, QWidget* parent) : QSlider(orientation, parent)
,m_orientation(orientation),m_tooltip(new QLabel(parent,Qt::ToolTip))
VolumeSlider::VolumeSlider(Qt::Orientation orientation, QWidget* parent)
: QSlider(orientation, parent)
{
m_orientation = orientation;
// The 'tooltip' shows the value when the slider is dragged.
m_tooltip = new QLabel(parent, Qt::ToolTip);
// Set a size large enough to show all values up to 100.
QFontMetrics metrics(m_tooltip->font());
//Setting a size big enough for all values less than 100
QRect labelRect = metrics.boundingRect("88");
// m_tooltip->setContentsMargins(3,1,3,1);
QRect labelRect = metrics.boundingRect("100");
m_tooltip->setMinimumWidth(labelRect.width()+5);
m_tooltip->setMinimumHeight(labelRect.height()+3);
m_tooltip->setAlignment(Qt::AlignCenter);
// m_tooltip->setAlignment(Qt::AlignVCenter);
// Extra data formerly in 'VolumeSliderExtraData'
m_chid = Volume::NOCHANNEL;
m_subControlLabel = nullptr;
}
void VolumeSlider::updateToolTip()
{
// The value is a percentage here, but it is not displayed with a "%" suffix due
// to size limitations.
//
// 1) The following operates on the value of one individual channel slider, and thus
// represents only the value of that channel. This is technically not 100% sound
// for a corner case: the average of all channels should be displayed in the "joined
// slider mode". On the other hand, in that "joined slider mode" the slider should
// already represent the average of all channels. And as soon as you move the slider,
// all channels are changed. So it is likely really exact enough.
//
// 2) Future directions: It would be better to do the percentage calculation in the
// Volume class, as it handles corner cases like muting. But due to "auto-unmuting"
// the value is also correct here. As the VolumeSlider class currently holds no pointer
// or reference to the "underlying" Volume object, a bit of code "duplication" is
// acceptable here.
qreal percentReal = (100.0*value())/(maximum()-minimum());
int percent = qRound(percentReal);
m_tooltip->setText(QString::number(percent));
}
void VolumeSlider::mousePressEvent(QMouseEvent* event)
{
QSlider::mousePressEvent(event);
......@@ -56,21 +87,7 @@ void VolumeSlider::mousePressEvent(QMouseEvent* event)
m_tooltip->move(mapToGlobal(sliderHandle.topLeft()).x(),mapToGlobal(sliderHandle.topLeft()).y()+height());
}
/**
* 1) The following operates on the value of one individual channel slider, and thus is representing only the
* value of that channel. This is technically not 100% sound for a corner case: The average of all channels
* should be displayed in the "joined slider mode". On the other hand, in "joined slider mode", the slider
* should already represent the average of all channels. And as soon as you move the slider, all channels
* are changed. So it is likely really exact enough.
*
* 2) Future directions: It would be better to do the percentage calculation via the Volume class, as it
* handles corner cases like muting. But due to "auto-unmuting" the value is factually also correct. As the
* VolumeSlider class currently holds no pointer/reference to the "underlying" Volume object, a bit code
* "duplication" is acceptable here.
*/
qreal percentReal = (100.0*value())/(maximum()-minimum());
int percent = qRound(percentReal);
m_tooltip->setText(QString::number(percent));
updateToolTip();
m_tooltip->show();
}
}
......@@ -87,34 +104,17 @@ void VolumeSlider::mouseMoveEvent(QMouseEvent* event)
QStyleOptionSlider opt;
initStyleOption(&opt);
QRect sliderHandle = style()->subControlRect(QStyle::CC_Slider,&opt,QStyle::SC_SliderHandle,this);
const QRect sliderHandle = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
qreal percentReal = (100.0*value())/(maximum()-minimum());
int percent = qRound(percentReal);
//Change width of label if percent becomes 100
if (percent == 100)
updateToolTip();
if (m_orientation==Qt::Vertical)
{
QFontMetrics metrics(m_tooltip->font());
QRect labelRect = metrics.boundingRect("100");
m_tooltip->resize(labelRect.width(),m_tooltip->height());
}
else if(m_tooltip->width() > m_tooltip->minimumWidth())
{
m_tooltip->resize(m_tooltip->minimumWidth(),m_tooltip->height());
}
m_tooltip->setText(QString::number(percent));
if (m_orientation == Qt::Vertical)
{
m_tooltip->move(mapToGlobal(sliderHandle.topLeft()).x()+width(),mapToGlobal(sliderHandle.topLeft()).y());
m_tooltip->move(mapToGlobal(sliderHandle.topLeft()).x()+width(),
mapToGlobal(sliderHandle.topLeft()).y());
}
else
{
m_tooltip->move(mapToGlobal(sliderHandle.topLeft()).x(),mapToGlobal(sliderHandle.topLeft()).y()+height());
m_tooltip->move(mapToGlobal(sliderHandle.topLeft()).x(),
mapToGlobal(sliderHandle.topLeft()).y()+height());
}
//qCDebug(KMIX_LOG) << "Position is"<<mapToGlobal(sliderHandle.topLeft()).x()<<","<<mapToGlobal(sliderHandle.topLeft()).y();
//qCDebug(KMIX_LOG) << "Volume is "<<percent;
}
......@@ -27,23 +27,36 @@
#include <QLabel>
#include <QMouseEvent>
#include "volumesliderextradata.h"
#include "core/volume.h"
class VolumeSlider : public QSlider
{
Q_OBJECT
Qt::Orientation m_orientation;
QLabel* m_tooltip;
Q_OBJECT
public:
VolumeSlider(Qt::Orientation orientation, QWidget *parent);
virtual ~VolumeSlider() = default;
Volume::ChannelID channelId() const { return (m_chid); }
void setChannelId(Volume::ChannelID chid) { m_chid = chid; }
QWidget *subControlLabel() const { return (m_subControlLabel); }
void setSubControlLabel(QWidget *subControlLabel) { m_subControlLabel = subControlLabel; }
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
public:
VolumeSlider(Qt::Orientation orientation, QWidget* parent); // : QSlider(orientation, parent);
private:
void updateToolTip();
Qt::Orientation m_orientation;
QLabel *m_tooltip;
VolumeSliderExtraData extraData;
Volume::ChannelID m_chid;
QWidget *m_subControlLabel;
};
#endif
//-*-C++-*-
/*
* KMix -- KDE's full featured mini mixer
*
*
* Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef VOLUMESLIDEREXTRADATA_H
#define VOLUMESLIDEREXTRADATA_H
#include <QAbstractSlider>
#include "core/volume.h"
class VolumeSliderExtraData
{
public:
VolumeSliderExtraData() : chid(Volume::NOCHANNEL) {}
~VolumeSliderExtraData() {}
void setChid(Volume::ChannelID chid) { this->chid = chid; }
Volume::ChannelID getChid() { return chid; }
void setSubcontrolLabel(QWidget *subcontrolLabel) { this->subcontrolLabel = subcontrolLabel; }
QWidget* getSubcontrolLabel() {return subcontrolLabel; }
protected:
Volume::ChannelID chid;
QWidget *subcontrolLabel = nullptr;
};
class AbstractVolumeSlider : public QAbstractSlider, public VolumeSliderExtraData
{
};
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment