Commit 9e91a6a4 authored by Jonathan Marten's avatar Jonathan Marten

Change the capture check box into a "record" icon

Using new class ToggleToolButton which handles switching between two
specified pixmaps, or between a pixmap and the disabled-looking (but not
disabled-acting) version of it.  Makes the layout much neater because
the mute and capture buttons are now the same size.
parent 911735e2
......@@ -243,6 +243,7 @@ set(kmixgui_SRCS
gui/dialogselectmaster.cpp
gui/dialogchoosebackends.cpp
gui/guiprofile.cpp
gui/toggletoolbutton.cpp
)
add_library(kmixgui STATIC
......
......@@ -33,7 +33,7 @@
//#include <phonon/audiooutput.h>
//#include <phonon/backendcapabilities.h>
MediaController::MediaController(QString controlId) :
MediaController::MediaController(const QString &controlId) :
id(controlId), playState(PlayUnknown)
{
mediaPlayControl = false;
......@@ -63,20 +63,16 @@ MediaController::MediaController(QString controlId) :
*/
}
MediaController::~MediaController()
{
}
/**
* Returns whether this device has at least one media player control.
* @return
*/
bool MediaController::hasControls()
bool MediaController::hasControls() const
{
return mediaPlayControl | mediaNextControl | mediaPrevControl;
}
MediaController::PlayState MediaController::getPlayState()
MediaController::PlayState MediaController::getPlayState() const
{
return playState;
}
......
......@@ -41,8 +41,8 @@ class KMIXCORE_EXPORT MediaController
public:
enum PlayState { PlayPaused, PlayPlaying, PlayStopped, PlayUnknown };
explicit MediaController(QString);
virtual ~MediaController();
explicit MediaController(const QString &controlId);
virtual ~MediaController() = default;
void addMediaPlayControl() { mediaPlayControl = true; };
void addMediaNextControl() { mediaNextControl = true; };
......@@ -50,10 +50,10 @@ public:
bool hasMediaPlayControl() { return mediaPlayControl; };
bool hasMediaNextControl() { return mediaNextControl; };
bool hasMediaPrevControl() { return mediaPrevControl; };
bool hasControls();
bool hasControls() const;
MediaController::PlayState getPlayState();
MediaController::PlayState getPlayState() const;
void setPlayState(PlayState playState);
bool canSkipNext();
......
......@@ -26,17 +26,11 @@
#include <kconfig.h>
#include <kglobalaccel.h>
#include <kactioncollection.h>
#include <ktoggleaction.h>
#include <QCoreApplication>
#include <QIcon>
#include <qtoolbutton.h>
#include <QObject>
#include <QCheckBox>
#include <QToolButton>
#include <QMenu>
#include <QLabel>
#include <qpixmap.h>
#include <QBoxLayout>
#include <QGridLayout>
#include <QAction>
......@@ -49,12 +43,9 @@
#include "gui/ksmallslider.h"
#include "gui/verticaltext.h"
#include "gui/mdwmoveaction.h"
#include "gui/toggletoolbutton.h"
static const KIconLoader::Group iconLoadGroup = KIconLoader::Small;
static const KIconLoader::Group iconSizeGroup = KIconLoader::Toolbar;
static const int iconSmallSize = 10;
bool MDWSlider::debugMe = false;
......@@ -262,18 +253,18 @@ bool MDWSlider::hasCaptureLED() const
void MDWSlider::guiAddCaptureButton(const QString &captureTooltipText)
{
m_captureButton = new QCheckBox(i18n("cap"), this);
m_captureButton = new ToggleToolButton("media-record", this);
m_captureButton->setSmallSize(m_small);
m_captureButton->installEventFilter(this);
connect(m_captureButton, SIGNAL(toggled(bool)), this, SLOT(setRecsrc(bool)));
connect(m_captureButton, SIGNAL(clicked(bool)), this, SLOT(toggleRecsrc()));
m_captureButton->setToolTip(captureTooltipText);
}
void MDWSlider::guiAddMuteButton(const QString &muteTooltipText)
{
m_muteButton = new QToolButton(this);
m_muteButton->setAutoRaise(true);
m_muteButton->setCheckable(false);
setIcon("audio-volume-muted", m_muteButton);
m_muteButton = new ToggleToolButton("audio-volume-high", this);
m_muteButton->setInactiveIcon("audio-volume-muted");
m_muteButton->setSmallSize(m_small);
m_muteButton->installEventFilter(this);
connect(m_muteButton, SIGNAL(clicked(bool)), this, SLOT(toggleMuted()));
m_muteButton->setToolTip(muteTooltipText);
......@@ -290,7 +281,7 @@ void MDWSlider::guiAddControlLabel(Qt::Alignment alignment, const QString &chann
void MDWSlider::guiAddControlIcon(const QString &tooltipText)
{
m_controlIcon = new QLabel(this);
setIcon(m_mixdevice->iconName(), m_controlIcon);
ToggleToolButton::setIndicatorIcon(m_mixdevice->iconName(), m_controlIcon, m_small);
m_controlIcon->setToolTip(tooltipText);
m_controlIcon->installEventFilter(this);
}
......@@ -320,7 +311,7 @@ QSize MDWSlider::controlButtonSize()
if (!m_controlButtonSize.isValid()) // not calculated yet
{
auto *buttonSpacer = new QToolButton();
setIcon("unknown", buttonSpacer);
ToggleToolButton::setIndicatorIcon("unknown", buttonSpacer, m_small);
m_controlButtonSize = buttonSpacer->sizeHint();
qCDebug(KMIX_LOG) << m_controlButtonSize;
delete buttonSpacer;
......@@ -342,7 +333,7 @@ void MDWSlider::createWidgets( bool showMuteButton, bool showCaptureLED, bool in
const bool wantsCaptureLED = showCaptureLED && includeCapture;
const bool wantsMuteButton = showMuteButton && includePlayback;
MediaController *mediaController = m_mixdevice->getMediaController();
const MediaController *mediaController = m_mixdevice->getMediaController();
const bool wantsMediaControls = mediaController->hasControls();
const QString channelName = m_mixdevice->readableName();
......@@ -552,11 +543,11 @@ void MDWSlider::addMediaControls(QBoxLayout* volLayout)
QToolButton* MDWSlider::addMediaButton(QString iconName, QLayout* layout, QWidget *parent)
{
QToolButton *lbl = new QToolButton(parent);
lbl->setIconSize(QSize(IconSize(iconSizeGroup), IconSize(iconSizeGroup)));
lbl->setIconSize(QSize(IconSize(KIconLoader::Toolbar), IconSize(KIconLoader::Toolbar)));
lbl->setAutoRaise(true);
lbl->setCheckable(false);
setIcon(iconName, lbl);
ToggleToolButton::setIndicatorIcon(iconName, lbl);
layout->addWidget(lbl);
return lbl;
......@@ -572,7 +563,7 @@ void MDWSlider::updateMediaButton()
MediaController* mediaController = mixDevice()->getMediaController();
QString mediaIconName = calculatePlaybackIcon(mediaController->getPlayState());
setIcon(mediaIconName, m_mediaPlayButton);
ToggleToolButton::setIndicatorIcon(mediaIconName, m_mediaPlayButton);
}
void MDWSlider::mediaPrev(bool)
......@@ -591,12 +582,6 @@ void MDWSlider::mediaPlay(bool)
}
static QPixmap loadIcon(const QString &filename, KIconLoader::Group group)
{
return (KIconLoader::global()->loadIcon(filename, group, IconSize(iconSizeGroup)));
}
static QWidget *createLabel(QWidget *parent, const QString &label, Qt::Orientation orient, bool small)
{
QFont qf;
......@@ -717,55 +702,6 @@ void MDWSlider::sliderReleased()
}
/**
* Loads the icon with the given @p iconName in the size KIconLoader::Small,
* and applies it to the @p label widget. The widget must be either a
* QLabel or a QToolButton.
*/
void MDWSlider::setIcon(const QString &filename, QWidget *label)
{
QPixmap miniDevPM = loadIcon(filename, iconLoadGroup);
if (miniDevPM.isNull())
{
qCWarning(KMIX_LOG) << "Could not get pixmap for" << filename;
return;
}
// TODO: why is this happening on every control change?
qDebug() << "loaded" << filename << "pixmap size" << miniDevPM.size();
if (m_small) // small size, scale icon
{
QMatrix t;
t.scale(double(iconSmallSize)/miniDevPM.width(), double(iconSmallSize)/miniDevPM.height());
miniDevPM = miniDevPM.transformed(t);
label->resize(iconSmallSize, iconSmallSize);
}
else // not small size
{
label->setMinimumSize(IconSize(iconSizeGroup), IconSize(iconSizeGroup));
}
label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
QLabel *lbl = qobject_cast<QLabel *>(label);
if (lbl!=nullptr)
{
lbl->setPixmap(miniDevPM);
lbl->setAlignment(Qt::AlignHCenter | Qt::AlignCenter);
}
else
{
QToolButton *tbt = qobject_cast<QToolButton *>(label);
if (tbt!=nullptr)
{
tbt->setIcon(miniDevPM);
}
}
}
QString MDWSlider::iconName()
{
return m_mixdevice->iconName();
......@@ -844,8 +780,7 @@ MDWSlider::setTicks( bool value )
/**
* Enables or disables tickmarks
* Please note that always only the first and last slider has tickmarks.
*
* Please note that always only the first and last slider have tickmarks.
*/
void MDWSlider::setTicksInternal(QList<QAbstractSlider *>& ref_sliders, bool ticks)
{
......@@ -1125,20 +1060,18 @@ void MDWSlider::updateInternal(Volume& vol, QList<QAbstractSlider *>& ref_slider
} // for all sliders
// update mute
if( m_muteButton != 0 )
// update mute state
if (m_muteButton!=nullptr)
{
QSignalBlocker blocker(m_muteButton);
// TODO: this is the cause of setIcon() being called on every control change
QString muteIcon = m_mixdevice->isMuted() ? "audio-volume-muted" : "audio-volume-high";
setIcon(muteIcon, m_muteButton);
m_muteButton->setActive(!m_mixdevice->isMuted());
}
if( m_captureButton )
// update capture state
if (m_captureButton!=nullptr)
{
QSignalBlocker blocker(m_captureButton);
m_captureButton->setChecked( m_mixdevice->isRecSource() );
m_captureButton->setActive(m_mixdevice->isRecSource());
}
}
......@@ -1284,7 +1217,7 @@ bool MDWSlider::eventFilter(QObject *obj, QEvent *ev)
if (slider!=nullptr)
{
//qCDebug(KMIX_LOG) << "identified as over slider" << slider;
//qCDebug(KMIX_LOG) << "identified for slider" << slider;
QCoreApplication::sendEvent(slider, ev);
}
......
......@@ -23,12 +23,14 @@
#ifndef MDWSLIDER_H
#define MDWSLIDER_H
#include "volumeslider.h"
#include <QCheckBox>
#include <QList>
#include <QWidget>
#include <qlist.h>
#include <qpixmap.h>
#include <kiconloader.h>
#include "gui/volumeslider.h"
#include "gui/mixdevicewidget.h"
#include "core/volume.h"
class QBoxLayout;
class QGridLayout;
......@@ -36,14 +38,10 @@ class QToolButton;
class QLabel;
class QMenu;
#include <kiconloader.h>
class MixDevice;
class VerticalText;
class ViewBase;
#include "gui/mixdevicewidget.h"
#include "core/volume.h"
class ToggleToolButton;
class MDWSlider : public MixDeviceWidget
......@@ -85,10 +83,8 @@ public:
bool hasMuteButton() const;
bool hasCaptureLED() const;
static VolumeSliderExtraData DummVolumeSliderExtraData;
static bool debugMe;
public slots:
void toggleRecsrc();
void toggleMuted();
......@@ -120,12 +116,9 @@ private slots:
void mediaPrev(bool);
private:
void setIcon(const QString &filename, QWidget *label);
// QPixmap loadIcon( QString filename, KIconLoader::Group group );
void createWidgets( bool showMuteLED, bool showCaptureLED, bool includeMixer );
void addSliders( QBoxLayout *volLayout, char type, Volume& vol,
QList<QAbstractSlider *>& ref_sliders, QString tooltipText );
//void addDefaultLabel(QBoxLayout *layout, Qt::Orientation orientation);
// Methods that are called two times from a wrapper. Once for playabck, once for capture
void setStereoLinkedInternal( QList< QAbstractSlider* >& ref_sliders, bool showSubcontrolLabels);
......@@ -152,8 +145,8 @@ private:
QLabel *m_controlIcon;
QLabel *m_controlLabel; // is either QLabel or VerticalText
QToolButton* m_muteButton;
QCheckBox* m_captureButton;
ToggleToolButton *m_muteButton;
ToggleToolButton *m_captureButton;
QToolButton *m_mediaPlayButton;
QSize m_controlButtonSize;
......
/*
* KMix -- KDE's full featured mini mixer
*
* Copyright (C) 2018 Jonathan Marten <jjm@keelhaul.me.uk>
*
* 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, see
* <http://www.gnu.org/licenses>.
*/
#include "toggletoolbutton.h"
#include <qicon.h>
#include <qlabel.h>
#include <kiconloader.h>
#include <kiconeffect.h>
#include <kmix_debug.h>
static const KIconLoader::Group iconLoadGroup = KIconLoader::Small;
static const KIconLoader::Group iconSizeGroup = KIconLoader::Toolbar;
static const int iconSmallSize = 10;
ToggleToolButton::ToggleToolButton(const QString &activeIconName, QWidget *pnt)
: QToolButton(pnt)
{
qCDebug(KMIX_LOG) << activeIconName;
mActiveLoaded = mInactiveLoaded = false;
mActiveIcon = activeIconName;
mSmallSize = false;
mIsActive = true;
mFirstTime = true;
setCheckable(false);
setAutoRaise(true);
}
// based on MDWSlider::setIcon()
QPixmap getPixmap(const QString &name, bool small = false)
{
qCDebug(KMIX_LOG) << name << "small?" << small;
QPixmap pix = KIconLoader::global()->loadIcon(name, iconLoadGroup, IconSize(iconSizeGroup));
if (pix.isNull()) qCWarning(KMIX_LOG) << "failed for" << name;
else
{
qCDebug(KMIX_LOG) << "loaded" << name << "size" << pix.size();
if (small) // want small size, so scale pixmap
{
pix = pix.scaled(iconSmallSize, iconSmallSize);
qCDebug(KMIX_LOG) << "scaled to size" << pix.size();
}
}
// Return the allocated pixmap even if it failed to load, so that
// the caller can tell and only one load attempt will be made.
return (pix);
}
void ToggleToolButton::setActive(bool active)
{
if (!mFirstTime && (active==mIsActive)) return; // no change required
mIsActive = active; // record required state
mFirstTime = false; // note now initialised
QPixmap *pix = nullptr; // new pixmap to set
if (mIsActive) // look at new state
{
if (mActivePixmap.isNull()) // need pixmap for active state
{ // only if not already tried
if (!mActiveLoaded) mActivePixmap = getPixmap(mActiveIcon, mSmallSize);
mActiveLoaded = true; // note not to try again
}
pix = &mActivePixmap; // the pixmap to use
}
else // want inactive state
{
if (mInactivePixmap.isNull()) // need pixmap for inactive state
{
if (!mInactiveIcon.isEmpty()) // inactive icon is set
{
if (!mInactiveLoaded) mInactivePixmap = getPixmap(mInactiveIcon, mSmallSize);
}
else
{
qCDebug(KMIX_LOG) << "want inactive but no name set";
// need to derive from active state
if (!mActiveLoaded) mActivePixmap = getPixmap(mActiveIcon, mSmallSize);
mActiveLoaded = true; // only if not already tried
if (mActivePixmap.isNull()) qCWarning(KMIX_LOG) << "want inactive but no active available";
else
{
mInactivePixmap = KIconLoader::global()->iconEffect()->apply(mActivePixmap,
KIconLoader::Toolbar,
KIconLoader::DisabledState);
}
}
mInactiveLoaded = true; // note not to try again
}
pix = &mInactivePixmap; // the pixmap to use
}
if (pix->isNull()) return; // pixmap not available
setIcon(*pix); // set button pixmap
}
/**
* Loads the icon with the given @p iconName in the size KIconLoader::Small,
* and applies it to the @p label widget. The widget must be either a
* QLabel or a QToolButton.
*
* Originally @c MDWSlider::setIcon(), moved here because it uses the same
* icon size parameters as a @c ToggleToolButton, and it can share @c getPixmap().
*/
void ToggleToolButton::setIndicatorIcon(const QString &iconName, QWidget *label, bool small)
{
QPixmap pix = getPixmap(iconName, small);
if (pix.isNull())
{
qCWarning(KMIX_LOG) << "Could not get pixmap for" << iconName;
return;
}
qDebug() << "loaded" << iconName << "pixmap size" << pix.size();
if (small) // small size, set for scaled icon
{
label->resize(iconSmallSize, iconSmallSize);
}
else // not small size
{
label->resize(IconSize(iconSizeGroup), IconSize(iconSizeGroup));
}
label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
QLabel *lbl = qobject_cast<QLabel *>(label);
if (lbl!=nullptr)
{
lbl->setPixmap(pix);
lbl->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
}
else
{
QToolButton *tbt = qobject_cast<QToolButton *>(label);
if (tbt!=nullptr) tbt->setIcon(pix); // works because implicit QPixmap -> QIcon
}
}
//-*-C++-*-
/*
* KMix -- KDE's full featured mini mixer
*
* Copyright (C) 2018 Jonathan Marten <jjm@keelhaul.me.uk>
*
* 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, see
* <http://www.gnu.org/licenses>.
*/
#ifndef TOGGLETOOLBUTTON_H
#define TOGGLETOOLBUTTON_H
#include <qtoolbutton.h>
#include <qpixmap.h>
/**
* A tool button that can maintain two pixmaps, for an active and inactive state.
*
* @see QToolButton
**/
class ToggleToolButton : public QToolButton
{
Q_OBJECT
public:
explicit ToggleToolButton(const QString &activeIconName, QWidget *pnt = nullptr);
virtual ~ToggleToolButton() = default;
void setActive(bool active = true);
void setSmallSize(bool small = true) { mSmallSize = small; }
bool isActive() const { return (mIsActive); }
void setActiveIcon(const QString &name) { mActiveIcon = name; }
void setInactiveIcon(const QString &name) { mInactiveIcon = name; }
static void setIndicatorIcon(const QString &iconName, QWidget *label, bool small = false);
private:
bool mSmallSize;
QString mActiveIcon;
QString mInactiveIcon;
bool mIsActive;
bool mFirstTime;
QPixmap mActivePixmap;
bool mActiveLoaded;
QPixmap mInactivePixmap;
bool mInactiveLoaded;
};
#endif // TOGGLETOOLBUTTON_H
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