diff options
author | RJ Ryan <rryan@mixxx.org> | 2014-11-22 02:30:43 -0500 |
---|---|---|
committer | RJ Ryan <rryan@mixxx.org> | 2014-11-22 02:30:43 -0500 |
commit | c053443aecadc8467135505f984ee8a9fc0fe2a9 (patch) | |
tree | d904a5c911a5b9e56100b7db47ac610c96c0f947 /src/widget | |
parent | 43fb6aed0f58626ef674345f5cc7d768a8a45efd (diff) |
Eliminate massive code duplication between WPushButton and WEffectPushButton.
Diffstat (limited to 'src/widget')
-rw-r--r-- | src/widget/weffectpushbutton.cpp | 405 | ||||
-rw-r--r-- | src/widget/weffectpushbutton.h | 77 | ||||
-rw-r--r-- | src/widget/wpushbutton.cpp | 17 | ||||
-rw-r--r-- | src/widget/wpushbutton.h | 6 |
4 files changed, 47 insertions, 458 deletions
diff --git a/src/widget/weffectpushbutton.cpp b/src/widget/weffectpushbutton.cpp index 77eb07bb40..3f884b9b96 100644 --- a/src/widget/weffectpushbutton.cpp +++ b/src/widget/weffectpushbutton.cpp @@ -1,175 +1,20 @@ #include "widget/weffectpushbutton.h" -#include <QStylePainter> -#include <QStyleOption> -#include <QPixmap> #include <QtDebug> -#include <QMouseEvent> -#include <QTouchEvent> -#include <QPaintEvent> -#include <QApplication> -#include "widget/wpixmapstore.h" -#include "controlobject.h" -#include "controlpushbutton.h" -#include "control/controlbehavior.h" -#include "util/debug.h" #include "widget/effectwidgetutils.h" WEffectPushButton::WEffectPushButton(QWidget* pParent, EffectsManager* pEffectsManager) - : WWidget(pParent), - m_leftButtonMode(ControlPushButton::PUSH), - m_rightButtonMode(ControlPushButton::PUSH), + : WPushButton(pParent), m_pEffectsManager(pEffectsManager) { - setStates(0); -} - -WEffectPushButton::WEffectPushButton(QWidget* pParent, ControlPushButton::ButtonMode leftButtonMode, - ControlPushButton::ButtonMode rightButtonMode) - : WWidget(pParent), - m_leftButtonMode(leftButtonMode), - m_rightButtonMode(rightButtonMode) { - setStates(0); } WEffectPushButton::~WEffectPushButton() { } void WEffectPushButton::setup(QDomNode node, const SkinContext& context) { - // Number of states - int iNumStates = context.selectInt(node, "NumberStates"); - setStates(iNumStates); - - // Set background pixmap if available - if (context.hasNode(node, "BackPath")) { - QString mode_str = context.selectAttributeString( - context.selectElement(node, "BackPath"), "scalemode", "TILE"); - PixmapSource backSource = context.getPixmapSource(context.selectNode(node, "BackPath")); - if (!backSource.isEmpty()) { - setPixmapBackground(backSource, Paintable::DrawModeFromString(mode_str)); - } - } - - // Load pixmaps for associated states - QDomNode state = context.selectNode(node, "State"); - while (!state.isNull()) { - if (state.isElement() && state.nodeName() == "State") { - int iState = context.selectInt(state, "Number"); - if (iState < m_iNoStates) { - PixmapSource pixmapSource; - - pixmapSource = context.getPixmapSource(context.selectNode(state, "Unpressed")); - if (!pixmapSource.isEmpty()) { - setPixmap(iState, false, pixmapSource); - } - - pixmapSource = context.getPixmapSource(context.selectNode(state, "Pressed")); - if (!pixmapSource.isEmpty()) { - setPixmap(iState, true, pixmapSource); - } - - m_text.replace(iState, context.selectString(state, "Text")); - QString alignment = context.selectString(state, "Alignment"); - if (alignment == "left") { - m_align.replace(iState, Qt::AlignLeft); - } else if (alignment == "right") { - m_align.replace(iState, Qt::AlignRight); - } else { - // Default is center. - m_align.replace(iState, Qt::AlignCenter); - } - } - } - state = state.nextSibling(); - } - - ControlParameterWidgetConnection* leftConnection = NULL; - if (m_leftConnections.isEmpty()) { - if (!m_connections.isEmpty()) { - // If no left connection is set, the this is the left connection - leftConnection = m_connections.at(0); - } - } else { - leftConnection = m_leftConnections.at(0); - } - - if (leftConnection) { - bool leftClickForcePush = context.selectBool(node, "LeftClickIsPushButton", false); - m_leftButtonMode = ControlPushButton::PUSH; - if (!leftClickForcePush) { - const ConfigKey& configKey = leftConnection->getKey(); - ControlPushButton* p = dynamic_cast<ControlPushButton*>( - ControlObject::getControl(configKey)); - if (p) { - m_leftButtonMode = p->getButtonMode(); - } - } - if (leftConnection->getEmitOption() & - ControlParameterWidgetConnection::EMIT_DEFAULT) { - switch (m_leftButtonMode) { - case ControlPushButton::PUSH: - case ControlPushButton::LONGPRESSLATCHING: - case ControlPushButton::POWERWINDOW: - leftConnection->setEmitOption( - ControlParameterWidgetConnection::EMIT_ON_PRESS_AND_RELEASE); - break; - default: - leftConnection->setEmitOption( - ControlParameterWidgetConnection::EMIT_ON_PRESS); - break; - } - } - if (leftConnection->getDirectionOption() & - ControlParameterWidgetConnection::DIR_DEFAULT) { - if (m_pDisplayConnection == leftConnection) { - leftConnection->setDirectionOption(ControlParameterWidgetConnection::DIR_FROM_AND_TO_WIDGET); - } else { - leftConnection->setDirectionOption(ControlParameterWidgetConnection::DIR_FROM_WIDGET); - if (m_pDisplayConnection->getDirectionOption() & - ControlParameterWidgetConnection::DIR_DEFAULT) { - m_pDisplayConnection->setDirectionOption(ControlParameterWidgetConnection::DIR_TO_WIDGET); - } - } - } - } - - if (!m_rightConnections.isEmpty()) { - ControlParameterWidgetConnection* rightConnection = m_rightConnections.at(0); - bool rightClickForcePush = context.selectBool(node, "RightClickIsPushButton", false); - m_rightButtonMode = ControlPushButton::PUSH; - if (!rightClickForcePush) { - const ConfigKey configKey = rightConnection->getKey(); - ControlPushButton* p = dynamic_cast<ControlPushButton*>( - ControlObject::getControl(configKey)); - if (p) { - m_rightButtonMode = p->getButtonMode(); - if (m_rightButtonMode != ControlPushButton::PUSH) { - qWarning() - << "WEffectPushButton::setup: Connecting a Pushbutton not in PUSH mode is not implemented\n" - << "Please set <RightClickIsPushButton>true</RightClickIsPushButton>"; - } - } - } - if (rightConnection->getEmitOption() & - ControlParameterWidgetConnection::EMIT_DEFAULT) { - switch (m_rightButtonMode) { - case ControlPushButton::PUSH: - case ControlPushButton::LONGPRESSLATCHING: - case ControlPushButton::POWERWINDOW: - leftConnection->setEmitOption( - ControlParameterWidgetConnection::EMIT_ON_PRESS_AND_RELEASE); - break; - default: - leftConnection->setEmitOption( - ControlParameterWidgetConnection::EMIT_ON_PRESS); - break; - } - } - if (rightConnection->getDirectionOption() & - ControlParameterWidgetConnection::DIR_DEFAULT) { - rightConnection->setDirectionOption(ControlParameterWidgetConnection::DIR_FROM_WIDGET); - } - } + // Setup parent class. + WPushButton::setup(node, context); m_pButtonMenu = new QMenu(this); connect(m_pButtonMenu, SIGNAL(triggered(QAction*)), @@ -195,254 +40,52 @@ void WEffectPushButton::setup(QDomNode node, const SkinContext& context) { } } -void WEffectPushButton::setStates(int iStates) { - m_bPressed = false; - m_iNoStates = iStates; - m_activeTouchButton = Qt::NoButton; - - m_pressedPixmaps.resize(iStates); - m_unpressedPixmaps.resize(iStates); - m_text.resize(iStates); - m_align.resize(iStates); -} - -void WEffectPushButton::setPixmap(int iState, bool bPressed, - const PixmapSource& source) { - QVector<PaintablePointer>& pixmaps = bPressed ? - m_pressedPixmaps : m_unpressedPixmaps; - - if (iState < 0 || iState >= pixmaps.size()) { - return; - } - - PaintablePointer pPixmap = WPixmapStore::getPaintable(source, - Paintable::STRETCH); - - if (pPixmap.isNull() || pPixmap->isNull()) { - // Only log if it looks like the user tried to specify a pixmap. - if (!source.isEmpty()) { - qDebug() << "WEffectPushButton: Error loading pixmap:" - << source.getPath(); - } - } else { - // Set size of widget equal to pixmap size - setFixedSize(pPixmap->size()); - } - pixmaps.replace(iState, pPixmap); -} - -void WEffectPushButton::setPixmapBackground(const PixmapSource &source, - Paintable::DrawMode mode) { - // Load background pixmap - m_pPixmapBack = WPixmapStore::getPaintable(source, mode); - if (!source.isEmpty() && - (m_pPixmapBack.isNull() || m_pPixmapBack->isNull())) { - // Only log if it looks like the user tried to specify a pixmap. - qDebug() << "WEffectPushButton: Error loading background pixmap:" - << source.getPath(); - } -} - void WEffectPushButton::onConnectedControlChanged(double dParameter, double dValue) { - Q_UNUSED(dParameter); - // Enums are not currently represented using parameter space so it doesn't - // make sense to use the parameter here yet. - if (m_iNoStates == 1) { - m_bPressed = (dValue == 1.0); - } - foreach (QAction* action, m_pButtonMenu->actions()) { if (action->data().toDouble() == dValue) { action->setChecked(true); break; } } - - - double value = getControlParameterDisplay(); - if (isnan(value) || m_iNoStates == 0) { - return; - } - - int idx = static_cast<int>(value) % m_iNoStates; - emit(displayValueChanged(idx)); - // According to http://stackoverflow.com/a/3822243 this is the least - // expensive way to restyle just this widget. - // Since we expect button connections to not change at high frequency we - // don't try to detect whether things have changed for WEffectPushButton, we just - // re-render. - style()->unpolish(this); - style()->polish(this); - // These calls don't always trigger the repaint, so call it explicitly. - repaint(); + WPushButton::onConnectedControlChanged(dParameter, dValue); } -void WEffectPushButton::paintEvent(QPaintEvent* e) { - Q_UNUSED(e); - QStyleOption option; - option.initFrom(this); - QStylePainter p(this); - p.drawPrimitive(QStyle::PE_Widget, option); - - if (m_iNoStates == 0) { - return; - } - - if (m_pPixmapBack) { - m_pPixmapBack->draw(0, 0, &p); - } - - const QVector<PaintablePointer>& pixmaps = m_bPressed ? - m_pressedPixmaps : m_unpressedPixmaps; - - - // m_text, m_pressedPixmaps and m_unpressedPixmaps are all the same size (as - // per setup()) so if one is empty, all are empty. - if (pixmaps.isEmpty()) { - return; - } - - int idx = readDisplayValue(); - // Just in case m_iNoStates is somehow different from pixmaps.size(). - if (idx < 0) { - idx = 0; - } else if (idx >= pixmaps.size()) { - idx = pixmaps.size() - 1; - } - - PaintablePointer pPixmap = pixmaps.at(idx); - if (!pPixmap.isNull() && !pPixmap->isNull()) { - pPixmap->draw(0, 0, &p); - } - - QString text = m_text.at(idx); - if (!text.isEmpty()) { - p.drawText(rect(), m_align.at(idx), text); - } -} - -void WEffectPushButton::mousePressEvent(QMouseEvent * e) { - const bool leftClick = e->button() == Qt::LeftButton; +void WEffectPushButton::mousePressEvent(QMouseEvent* e) { const bool rightClick = e->button() == Qt::RightButton; - if (rightClick && m_pButtonMenu->actions().size()) { m_pButtonMenu->exec(e->globalPos()); - } - - if (m_leftButtonMode == ControlPushButton::POWERWINDOW - && m_iNoStates == 2) { - if (leftClick) { - if (getControlParameterLeft() == 0.0) { - m_clickTimer.setSingleShot(true); - m_clickTimer.start(ControlPushButtonBehavior::kPowerWindowTimeMillis); - } - m_bPressed = true; - setControlParameterLeftDown(1.0); - update(); - } - // discharge right clicks here, because is used for latching in POWERWINDOW mode return; } - if (leftClick) { - double emitValue; - if (m_leftButtonMode == ControlPushButton::PUSH - || m_iNoStates == 1) { - // This is either forced to behave like a push button on left-click - // or this is a push button. - emitValue = 1.0; - } else { - // Toggle thru the states - emitValue = getControlParameterLeft(); - if (!isnan(emitValue) && m_iNoStates) { - emitValue = static_cast<int>(emitValue + 1.0) % m_iNoStates; - } - if (m_leftButtonMode == ControlPushButton::LONGPRESSLATCHING) { - m_clickTimer.setSingleShot(true); - m_clickTimer.start(ControlPushButtonBehavior::kLongPressLatchingTimeMillis); - } + // Pass all other press events to the base class. + WPushButton::mousePressEvent(e); - // Check the corresponding QAction - foreach (QAction* action, m_pButtonMenu->actions()) { - if (action->data().toDouble() == emitValue) { - action->setChecked(true); - break; - } - } + // The push handler may have set the left value. Check the corresponding + // QAction. + double leftValue = getControlParameterLeft(); + foreach (QAction* action, m_pButtonMenu->actions()) { + if (action->data().toDouble() == leftValue) { + action->setChecked(true); + break; } - m_bPressed = true; - setControlParameterLeftDown(emitValue); - update(); } } -void WEffectPushButton::focusOutEvent(QFocusEvent* e) { - Q_UNUSED(e); - if (e->reason() != Qt::MouseFocusReason) { - // Since we support multi touch there is no reason to reset - // the pressed flag if the Primary touch point is moved to an - // other widget - m_bPressed = false; - update(); - } -} +void WEffectPushButton::mouseReleaseEvent(QMouseEvent* e) { + // Pass all other press events to the base class. + WPushButton::mousePressEvent(e); -void WEffectPushButton::mouseReleaseEvent(QMouseEvent * e) { - const bool leftClick = e->button() == Qt::LeftButton; - const bool rightClick = e->button() == Qt::RightButton; - - if (m_leftButtonMode == ControlPushButton::POWERWINDOW - && m_iNoStates == 2) { - if (leftClick) { - const bool rightButtonDown = QApplication::mouseButtons() & Qt::RightButton; - if (m_bPressed && !m_clickTimer.isActive() && !rightButtonDown) { - // Release button after timer, but not if right button is clicked - setControlParameterLeftUp(0.0); - } - m_bPressed = false; - } else if (rightClick) { - m_bPressed = false; - } - update(); - return; - } - - if (leftClick) { - double emitValue = getControlParameterLeft(); - if (m_leftButtonMode == ControlPushButton::PUSH - || m_iNoStates == 1) { - // This is a Pushbutton - emitValue = 0.0; - } else { - if (m_leftButtonMode == ControlPushButton::LONGPRESSLATCHING - && m_clickTimer.isActive() && emitValue >= 1.0) { - // revert toggle if button is released too early - if (!isnan(emitValue) && m_iNoStates) { - emitValue = static_cast<int>(emitValue - 1.0) % m_iNoStates; - } - } else { - // Nothing special happens when releasing a normal toggle button - } + // The release handler may have set the left value. Check the corresponding + // QAction. + double leftValue = getControlParameterLeft(); + foreach (QAction* action, m_pButtonMenu->actions()) { + if (action->data().toDouble() == leftValue) { + action->setChecked(true); + break; } - m_bPressed = false; - setControlParameterLeftUp(emitValue); - update(); } } -void WEffectPushButton::fillDebugTooltip(QStringList* debug) { - WWidget::fillDebugTooltip(debug); - *debug << QString("NumberStates: %1").arg(m_iNoStates) - << QString("LeftCurrentState: %1").arg( - static_cast<int>(getControlParameterLeft()) % - (m_iNoStates > 0 ? m_iNoStates : 1)) - << QString("Pressed: %1").arg(toDebugString(m_bPressed)) - << QString("LeftButtonMode: %1") - .arg(ControlPushButton::buttonModeToString(m_leftButtonMode)) - << QString("RightButtonMode: %1") - .arg(ControlPushButton::buttonModeToString(m_rightButtonMode)); -} - void WEffectPushButton::parameterUpdated() { m_pButtonMenu->clear(); const QList<QPair<QString, double> >& options = m_pEffectParameterSlot->getManifest().getSteps(); diff --git a/src/widget/weffectpushbutton.h b/src/widget/weffectpushbutton.h index ff1902a2dd..780469bb4f 100644 --- a/src/widget/weffectpushbutton.h +++ b/src/widget/weffectpushbutton.h @@ -2,98 +2,35 @@ #define WEFFECTPUSHBUTTON_H #include <QMenu> -#include <QPaintEvent> -#include <QPixmap> -#include <QString> -#include <QPaintEvent> +#include <QAction> #include <QMouseEvent> -#include <QFocusEvent> -#include <QTimer> -#include <QVector> +#include <QDomNode> +#include <QWidget> -#include "widget/wwidget.h" -#include "widget/wpixmapstore.h" -#include "controlpushbutton.h" +#include "widget/wpushbutton.h" #include "skin/skincontext.h" -#include "controlwidgetconnection.h" #include "effects/effectsmanager.h" -class WEffectPushButton : public WWidget { +class WEffectPushButton : public WPushButton { Q_OBJECT public: WEffectPushButton(QWidget* pParent, EffectsManager* pEffectsManager); - // Used by WEffectPushButtonTest. - WEffectPushButton(QWidget* pParent, ControlPushButton::ButtonMode leftButtonMode, - ControlPushButton::ButtonMode rightButtonMode); virtual ~WEffectPushButton(); - Q_PROPERTY(bool pressed READ isPressed); - - bool isPressed() const { - return m_bPressed; - } - - // The displayValue property is used to restyle the pushbutton with CSS. - // The declaration #MyButton[displayValue="0"] { } will define the style - // when the widget is in state 0. This allows for effects like reversing - // background and foreground colors to indicate enabled/disabled state. - Q_PROPERTY(int displayValue READ readDisplayValue NOTIFY displayValueChanged) - - int readDisplayValue() const { - double value = getControlParameterDisplay(); - int idx = static_cast<int>(value) % m_iNoStates; - return idx; - } - - void setup(QDomNode node, const SkinContext& context); - - // Sets the number of states associated with this button, and removes - // associated pixmaps. - void setStates(int iStatesW); - - signals: - void displayValueChanged(int value); + virtual void setup(QDomNode node, const SkinContext& context); public slots: - void onConnectedControlChanged(double dParameter, double dValue); + virtual void onConnectedControlChanged(double dParameter, double dValue); protected: - virtual void paintEvent(QPaintEvent*); virtual void mousePressEvent(QMouseEvent* e); virtual void mouseReleaseEvent(QMouseEvent* e); - virtual void focusOutEvent(QFocusEvent* e); - void fillDebugTooltip(QStringList* debug); private slots: void parameterUpdated(); void slotActionChosen(QAction* action); private: - // Associates a pixmap of a given state of the button with the widget - void setPixmap(int iState, bool bPressed, const PixmapSource &source); - - // Associates a background pixmap with the widget. This is only needed if - // the button pixmaps contains alpha channel values. - void setPixmapBackground(const PixmapSource &source, Paintable::DrawMode mode); - - // True, if the button is currently pressed - bool m_bPressed; - - // Array of associated pixmaps - int m_iNoStates; - QVector<QString> m_text; - QVector<PaintablePointer> m_pressedPixmaps; - QVector<PaintablePointer> m_unpressedPixmaps; - - // Associated background pixmap - PaintablePointer m_pPixmapBack; - - // short click toggle button long click push button - ControlPushButton::ButtonMode m_leftButtonMode; - ControlPushButton::ButtonMode m_rightButtonMode; - QTimer m_clickTimer; - QVector<int> m_align; - EffectsManager* m_pEffectsManager; EffectParameterSlotBasePointer m_pEffectParameterSlot; QMenu* m_pButtonMenu; diff --git a/src/widget/wpushbutton.cpp b/src/widget/wpushbutton.cpp index fc4f5c0c54..5b57a74f71 100644 --- a/src/widget/wpushbutton.cpp +++ b/src/widget/wpushbutton.cpp @@ -31,6 +31,7 @@ #include "controlpushbutton.h" #include "control/controlbehavior.h" #include "util/debug.h" +#include "util/math.h" WPushButton::WPushButton(QWidget* pParent) : WWidget(pParent), @@ -247,8 +248,11 @@ void WPushButton::onConnectedControlChanged(double dParameter, double dValue) { } double value = getControlParameterDisplay(); - int idx = static_cast<int>(value) % m_iNoStates; - emit(displayValueChanged(idx)); + if (!isnan(value) && m_iNoStates > 0) { + int idx = static_cast<int>(value) % m_iNoStates; + emit(displayValueChanged(idx)); + } + // According to http://stackoverflow.com/a/3822243 this is the least // expensive way to restyle just this widget. // Since we expect button connections to not change at high frequency we @@ -344,7 +348,10 @@ void WPushButton::mousePressEvent(QMouseEvent * e) { emitValue = 1.0; } else { // Toggle thru the states - emitValue = static_cast<int>(getControlParameterLeft() + 1.0) % m_iNoStates; + emitValue = getControlParameterLeft(); + if (!isnan(emitValue) && m_iNoStates > 0) { + emitValue = static_cast<int>(emitValue + 1.0) % m_iNoStates; + } if (m_leftButtonMode == ControlPushButton::LONGPRESSLATCHING) { m_clickTimer.setSingleShot(true); m_clickTimer.start(ControlPushButtonBehavior::kLongPressLatchingTimeMillis); @@ -410,7 +417,9 @@ void WPushButton::mouseReleaseEvent(QMouseEvent * e) { if (m_leftButtonMode == ControlPushButton::LONGPRESSLATCHING && m_clickTimer.isActive() && emitValue >= 1.0) { // revert toggle if button is released too early - emitValue = static_cast<int>(emitValue - 1.0) % m_iNoStates; + if (!isnan(emitValue) && m_iNoStates > 0) { + emitValue = static_cast<int>(emitValue - 1.0) % m_iNoStates; + } } else { // Nothing special happens when releasing a normal toggle button } diff --git a/src/widget/wpushbutton.h b/src/widget/wpushbutton.h index d69e851bbc..a7d40884d4 100644 --- a/src/widget/wpushbutton.h +++ b/src/widget/wpushbutton.h @@ -60,7 +60,7 @@ class WPushButton : public WWidget { return idx; } - void setup(QDomNode node, const SkinContext& context); + virtual void setup(QDomNode node, const SkinContext& context); // Sets the number of states associated with this button, and removes // associated pixmaps. @@ -70,7 +70,7 @@ class WPushButton : public WWidget { void displayValueChanged(int value); public slots: - void onConnectedControlChanged(double dParameter, double dValue); + virtual void onConnectedControlChanged(double dParameter, double dValue); protected: virtual void paintEvent(QPaintEvent*); @@ -79,7 +79,7 @@ class WPushButton : public WWidget { virtual void focusOutEvent(QFocusEvent* e); void fillDebugTooltip(QStringList* debug); - private: + protected: // Associates a pixmap of a given state of the button with the widget void setPixmap(int iState, bool bPressed, PixmapSource source); |