diff --git a/src/skin/legacy/legacyskinparser.cpp b/src/skin/legacy/legacyskinparser.cpp index fe691a203c9..941201f3e8f 100644 --- a/src/skin/legacy/legacyskinparser.cpp +++ b/src/skin/legacy/legacyskinparser.cpp @@ -8,8 +8,10 @@ #include #include #include +#include #include "control/controlobject.h" +#include "control/controlpushbutton.h" #include "controllers/controllerlearningeventfilter.h" #include "controllers/controllermanager.h" #include "controllers/keyboard/keyboardeventfilter.h" @@ -23,6 +25,7 @@ #include "skin/legacy/launchimage.h" #include "skin/legacy/skincontext.h" #include "track/track.h" +#include "util/assert.h" #include "util/cmdlineargs.h" #include "util/timer.h" #include "util/valuetransformer.h" @@ -2358,8 +2361,6 @@ void LegacySkinParser::setupWidget(const QDomNode& node, } void LegacySkinParser::setupConnections(const QDomNode& node, WBaseWidget* pWidget) { - ControlParameterWidgetConnection* pLastLeftOrNoButtonConnection = nullptr; - for (QDomNode con = m_pContext->selectNode(node, "Connection"); !con.isNull(); con = con.nextSibling()) { @@ -2370,20 +2371,22 @@ void LegacySkinParser::setupConnections(const QDomNode& node, WBaseWidget* pWidg continue; } - ValueTransformer* pTransformer = nullptr; + std::unique_ptr pTransformer = nullptr; QDomElement transform = m_pContext->selectElement(con, "Transform"); if (!transform.isNull()) { - pTransformer = ValueTransformer::parseFromXml(transform, *m_pContext); + pTransformer = + ValueTransformer::parseFromXml(transform, *m_pContext); } QString property; if (m_pContext->hasNodeSelectString(con, "BindProperty", &property)) { //qDebug() << "Making property connection for" << property; - ControlWidgetPropertyConnection* pConnection = - new ControlWidgetPropertyConnection(pWidget, control->getKey(), - pTransformer, property); - pWidget->addPropertyConnection(pConnection); + pWidget->addPropertyConnection( + std::make_unique(pWidget, + control->getKey(), + std::move(pTransformer), + property)); } else { bool nodeValue; Qt::MouseButton state = parseButtonState(con, *m_pContext); @@ -2444,26 +2447,36 @@ void LegacySkinParser::setupConnections(const QDomNode& node, WBaseWidget* pWidg emitOption |= ControlParameterWidgetConnection::EMIT_DEFAULT; } - ControlParameterWidgetConnection* pConnection = new ControlParameterWidgetConnection( - pWidget, control->getKey(), pTransformer, - static_cast(directionOption), - static_cast(emitOption)); + auto pConnection = + std::make_unique(pWidget, + control->getKey(), + std::move(pTransformer), + static_cast(directionOption), + static_cast(emitOption)); switch (state) { case Qt::NoButton: - pWidget->addConnection(pConnection); if (directionOption & ControlParameterWidgetConnection::DIR_TO_WIDGET) { - pLastLeftOrNoButtonConnection = pConnection; + pWidget->addAndSetDisplayConnection(std::move(pConnection), + WBaseWidget::ConnectionSide::Right); + } else { + pWidget->addConnection(std::move(pConnection), + WBaseWidget::ConnectionSide::Right); } break; case Qt::LeftButton: - pWidget->addLeftConnection(pConnection); if (directionOption & ControlParameterWidgetConnection::DIR_TO_WIDGET) { - pLastLeftOrNoButtonConnection = pConnection; + pWidget->addAndSetDisplayConnection(std::move(pConnection), + WBaseWidget::ConnectionSide::Left); + } else { + pWidget->addConnection(std::move(pConnection), + WBaseWidget::ConnectionSide::Left); } break; case Qt::RightButton: - pWidget->addRightConnection(pConnection); + pWidget->addConnection(std::move(pConnection), WBaseWidget::ConnectionSide::Right); break; default: // can't happen. Nothing else is returned by parseButtonState(); @@ -2553,14 +2566,6 @@ void LegacySkinParser::setupConnections(const QDomNode& node, WBaseWidget* pWidg } } } - - // Legacy behavior: The last left-button or no-button connection with - // connectValueToWidget is the display connection. If no left-button or - // no-button connection exists, use the last right-button connection as the - // display connection. - if (pLastLeftOrNoButtonConnection != nullptr) { - pWidget->setDisplayConnection(pLastLeftOrNoButtonConnection); - } } void LegacySkinParser::addShortcutToToolTip(WBaseWidget* pWidget, diff --git a/src/test/wpushbutton_test.cpp b/src/test/wpushbutton_test.cpp index 1f3f328c450..111b59d007c 100644 --- a/src/test/wpushbutton_test.cpp +++ b/src/test/wpushbutton_test.cpp @@ -1,82 +1,59 @@ +#include "widget/wpushbutton.h" + #include #include -#include +#include -#include "mixxxtest.h" -#include "control/controlobject.h" -#include "control/controlproxy.h" #include "control/controlpushbutton.h" -#include "widget/wpushbutton.h" +#include "util/valuetransformer.h" #include "widget/controlwidgetconnection.h" +#include "widget/wbasewidget.h" -class WPushButtonTest : public MixxxTest { +class WPushButtonTest : public ::testing::Test { public: - WPushButtonTest() - : m_pGroup("[Channel1]") { - } - - protected: - void SetUp() override { - m_pTouchShift.reset(new ControlPushButton(ConfigKey("[Controls]", "touch_shift"))); - m_pButton.reset(new WPushButton()); - m_pButton->setStates(2); + // touchShift is needed internally to avoid a DEBUG_ASSERT + ControlPushButton touchShift = ConfigKey( + QStringLiteral("[Controls]"), QStringLiteral("touch_shift")); + ControlPushButton pushControl = ConfigKey(QStringLiteral("[Test]"), QStringLiteral("push")); + WPushButton pushButton = WPushButton(nullptr, + mixxx::control::ButtonMode::LongPressLatching, + mixxx::control::ButtonMode::Push); + + WPushButtonTest() { + pushControl.setButtonMode(mixxx::control::ButtonMode::LongPressLatching); + pushButton.setStates(2); + pushButton.addConnection( + std::make_unique( + &pushButton, + pushControl.getKey(), + nullptr, + ControlParameterWidgetConnection::DIR_FROM_AND_TO_WIDGET, + ControlParameterWidgetConnection::EMIT_ON_PRESS_AND_RELEASE), + WBaseWidget::ConnectionSide::Left); } - - QScopedPointer m_pButton; - QScopedPointer m_pTouchShift; - QTestEventList m_Events; - const char* m_pGroup; }; TEST_F(WPushButtonTest, QuickPressNoLatchTest) { - QScopedPointer pPushControl( - new ControlPushButton(ConfigKey("[Test]", "push"))); - pPushControl->setButtonMode(mixxx::control::ButtonMode::LongPressLatching); - - m_pButton.reset(new WPushButton(NULL, - mixxx::control::ButtonMode::LongPressLatching, - mixxx::control::ButtonMode::Push)); - m_pButton->setStates(2); - m_pButton->addLeftConnection( - new ControlParameterWidgetConnection( - m_pButton.data(), - pPushControl->getKey(), NULL, - ControlParameterWidgetConnection::DIR_FROM_AND_TO_WIDGET, - ControlParameterWidgetConnection::EMIT_ON_PRESS_AND_RELEASE)); - // This test can be flaky if the event simulator takes too long to deliver // the event. - m_Events.addMousePress(Qt::LeftButton); - m_Events.addDelay(100); - m_Events.addMouseRelease(Qt::LeftButton); + QTestEventList events; + events.addMousePress(Qt::LeftButton); + events.addDelay(100); + events.addMouseRelease(Qt::LeftButton); - m_Events.simulate(m_pButton.data()); + events.simulate(&pushButton); - ASSERT_EQ(0.0, m_pButton->getControlParameterLeft()); + ASSERT_EQ(0.0, pushButton.getControlParameterLeft()); } TEST_F(WPushButtonTest, LongPressLatchTest) { - QScopedPointer pPushControl( - new ControlPushButton(ConfigKey("[Test]", "push"))); - pPushControl->setButtonMode(mixxx::control::ButtonMode::LongPressLatching); - - m_pButton.reset(new WPushButton(NULL, - mixxx::control::ButtonMode::LongPressLatching, - mixxx::control::ButtonMode::Push)); - m_pButton->setStates(2); - m_pButton->addLeftConnection( - new ControlParameterWidgetConnection( - m_pButton.data(), - pPushControl->getKey(), NULL, - ControlParameterWidgetConnection::DIR_FROM_AND_TO_WIDGET, - ControlParameterWidgetConnection::EMIT_ON_PRESS_AND_RELEASE)); - - m_Events.addMousePress(Qt::LeftButton); - m_Events.addDelay(1000); - m_Events.addMouseRelease(Qt::LeftButton); + QTestEventList events; + events.addMousePress(Qt::LeftButton); + events.addDelay(1000); + events.addMouseRelease(Qt::LeftButton); - m_Events.simulate(m_pButton.data()); + events.simulate(&pushButton); - ASSERT_EQ(1.0, m_pButton->getControlParameterLeft()); + ASSERT_EQ(1.0, pushButton.getControlParameterLeft()); } diff --git a/src/util/valuetransformer.cpp b/src/util/valuetransformer.cpp index 60c60fe08b0..972c8a8ccc8 100644 --- a/src/util/valuetransformer.cpp +++ b/src/util/valuetransformer.cpp @@ -1,35 +1,126 @@ #include "util/valuetransformer.h" -ValueTransformer::ValueTransformer() { -} +#include +#include +#include +#include +#include + +#include "skin/legacy/skincontext.h" + +class TransformNode { + public: + TransformNode() { + } + virtual ~TransformNode() { + } + + virtual double transform(double argument) const = 0; + virtual double transformInverse(double argument) const = 0; +}; + +namespace { + +class TransformAdd : public TransformNode { + public: + TransformAdd(double addend) + : m_addend(addend) { + } + + double transform(double argument) const override { + return argument + m_addend; + } + + double transformInverse(double argument) const override { + return argument - m_addend; + } + + private: + double m_addend; +}; + +class TransformInvert : public TransformNode { + public: + double transform(double argument) const override { + return -argument; + } + + double transformInverse(double argument) const override { + return -argument; + } +}; + +class TransformNot : public TransformNode { + public: + double transform(double argument) const override { + return !static_cast(argument); + } + + double transformInverse(double argument) const override { + return !static_cast(argument); + } +}; + +class TransformIsEqual : public TransformNode { + public: + TransformIsEqual(double compareValue) + : m_compareValue(compareValue) { + } + + double transform(double argument) const override { + return argument == m_compareValue; + } + + double transformInverse(double argument) const override { + if (argument > 0.0) { + return m_compareValue; + } + return 0.0; + } -void ValueTransformer::addTransformer(TransformNode* pTransformer) { - m_transformers.append(pTransformer); + private: + double m_compareValue; +}; + +} // namespace + +void ValueTransformer::addTransformer(std::unique_ptr pTransformer) { + m_transformers.push_back(std::move(pTransformer)); } double ValueTransformer::transform(double argument) const { - foreach (const TransformNode* pNode, m_transformers) { + for (const auto& pNode : m_transformers) { argument = pNode->transform(argument); } return argument; } double ValueTransformer::transformInverse(double argument) const { - for (int i = m_transformers.size() - 1; i >= 0; --i) { - const TransformNode* pNode = m_transformers[i]; - argument = pNode->transformInverse(argument); + for (auto it = m_transformers.crbegin(); it != m_transformers.crend(); ++it) { + argument = (*it)->transformInverse(argument); } return argument; } +template +void ValueTransformer::addIfValidDouble(const QString& str) { + bool ok = false; + double value = str.toDouble(&ok); + if (ok) { + addTransformer(std::make_unique(value)); + } +} + // static -ValueTransformer* ValueTransformer::parseFromXml(const QDomElement& transformElement, - const SkinContext& context) { +std::unique_ptr ValueTransformer::parseFromXml( + const QDomElement& transformElement, const SkinContext& context) { if (transformElement.isNull() || !transformElement.hasChildNodes()) { return nullptr; } - ValueTransformer* pTransformer = new ValueTransformer(); + // constructor is private, so we can't use std::make_unique + auto pTransformer = std::unique_ptr(new ValueTransformer()); + QDomNodeList children = transformElement.childNodes(); for (int i = 0; i < children.count(); ++i) { QDomNode node = children.at(i); @@ -38,32 +129,21 @@ ValueTransformer* ValueTransformer::parseFromXml(const QDomElement& transformEle } QDomElement element = node.toElement(); - if (element.nodeName() == "Invert") { - pTransformer->addTransformer(new TransformInvert()); - } else if (element.nodeName() == "Add") { - QString value = context.nodeToString(element); - bool ok = false; - double addend = value.toDouble(&ok); - if (ok) { - pTransformer->addTransformer(new TransformAdd(addend)); - } - } else if (element.nodeName() == "Not") { - pTransformer->addTransformer(new TransformNot()); - } else if (element.nodeName() == "IsEqual") { - QString value = context.nodeToString(element); - bool ok = false; - double compareValue = value.toDouble(&ok); - if (ok) { - pTransformer->addTransformer(new TransformIsEqual(compareValue)); - } + QString name = element.nodeName(); + if (name == "Invert") { + pTransformer->addTransformer(std::make_unique()); + } else if (name == "Add") { + pTransformer->addIfValidDouble(context.nodeToString(element)); + } else if (name == "Not") { + pTransformer->addTransformer(std::make_unique()); + } else if (name == "IsEqual") { + pTransformer->addIfValidDouble(context.nodeToString(element)); } } return pTransformer; } -ValueTransformer::~ValueTransformer() { - foreach (TransformNode* node, m_transformers) { - delete node; - } -} +ValueTransformer::ValueTransformer() = default; + +ValueTransformer::~ValueTransformer() = default; diff --git a/src/util/valuetransformer.h b/src/util/valuetransformer.h index e3069ff2e91..e2e3e31d76a 100644 --- a/src/util/valuetransformer.h +++ b/src/util/valuetransformer.h @@ -1,95 +1,28 @@ #pragma once -#include -#include +#include +#include -#include "skin/legacy/skincontext.h" - -class TransformNode { - public: - TransformNode() {} - virtual ~TransformNode() {} - - virtual double transform(double argument) const = 0; - virtual double transformInverse(double argument) const = 0; -}; - -class TransformAdd : public TransformNode { - public: - TransformAdd(double addend) : m_addend(addend) {} - - double transform(double argument) const { - return argument + m_addend; - } - - double transformInverse(double argument) const { - return argument - m_addend; - } - - private: - double m_addend; -}; - -class TransformInvert : public TransformNode { - public: - TransformInvert() {} - - double transform(double argument) const { - return -argument; - } - - double transformInverse(double argument) const { - return -argument; - } -}; - -class TransformNot : public TransformNode { - public: - TransformNot() {} - - double transform(double argument) const { - return !static_cast(argument); - } - - double transformInverse(double argument) const { - return !static_cast(argument); - } -}; - -class TransformIsEqual : public TransformNode { - public: - TransformIsEqual(double compareValue) : - m_compareValue(compareValue) { - } - - double transform(double argument) const { - return argument == m_compareValue; - } - - double transformInverse(double argument) const { - if (argument > 0.0) { - return m_compareValue; - } - return 0.0; - } - - private: - double m_compareValue; -}; +class SkinContext; +class TransformNode; +class QDomElement; +class QString; class ValueTransformer { public: ~ValueTransformer(); + double transform(double argument) const; double transformInverse(double argument) const; - static ValueTransformer* parseFromXml(const QDomElement& transformElement, + static std::unique_ptr parseFromXml(const QDomElement& transformElement, const SkinContext& context); private: - ValueTransformer(); - - void addTransformer(TransformNode* pTransformer); + ValueTransformer(); // only accessible from parseFromXml, not deleted + void addTransformer(std::unique_ptr pTransformer); + template + void addIfValidDouble(const QString& str); - QList m_transformers; + std::vector> m_transformers; }; diff --git a/src/widget/controlwidgetconnection.cpp b/src/widget/controlwidgetconnection.cpp index 9fbf52a04b9..59ca921bef8 100644 --- a/src/widget/controlwidgetconnection.cpp +++ b/src/widget/controlwidgetconnection.cpp @@ -1,10 +1,12 @@ #include "widget/controlwidgetconnection.h" #include +#include #include "control/controlproxy.h" #include "moc_controlwidgetconnection.cpp" #include "util/assert.h" +#include "util/parented_ptr.h" #include "util/valuetransformer.h" #include "widget/wbasewidget.h" @@ -33,13 +35,16 @@ QMetaProperty propertyFromWidget(const QWidget* pWidget, const QString& name) { ControlWidgetConnection::ControlWidgetConnection( WBaseWidget* pBaseWidget, const ConfigKey& key, - ValueTransformer* pTransformer) - : m_pWidget(pBaseWidget), - m_pValueTransformer(pTransformer) { - m_pControl = new ControlProxy(key, this, ControlFlag::NoAssertIfMissing); + std::unique_ptr pTransformer) + : QObject(), + m_pWidget(pBaseWidget), + m_pControl(make_parented(key, this, ControlFlag::NoAssertIfMissing)), + m_pValueTransformer(std::move(pTransformer)) { m_pControl->connectValueChanged(this, &ControlWidgetConnection::slotControlValueChanged); } +ControlWidgetConnection::~ControlWidgetConnection() = default; + void ControlWidgetConnection::setControlParameter(double parameter) { if (m_pValueTransformer != nullptr) { parameter = m_pValueTransformer->transformInverse(parameter); @@ -64,14 +69,18 @@ double ControlWidgetConnection::getControlParameterForValue(double value) const } ControlParameterWidgetConnection::ControlParameterWidgetConnection( - WBaseWidget* pBaseWidget, const ConfigKey& key, - ValueTransformer* pTransformer, DirectionOption directionOption, + WBaseWidget* pBaseWidget, + const ConfigKey& key, + std::unique_ptr pTransformer, + DirectionOption directionOption, EmitOption emitOption) - : ControlWidgetConnection(pBaseWidget, key, pTransformer), + : ControlWidgetConnection(pBaseWidget, key, std::move(pTransformer)), m_directionOption(directionOption), m_emitOption(emitOption) { } +ControlParameterWidgetConnection::~ControlParameterWidgetConnection() = default; + void ControlParameterWidgetConnection::Init() { slotControlValueChanged(m_pControl->get()); } @@ -120,15 +129,17 @@ void ControlParameterWidgetConnection::setControlParameterUp(double v) { ControlWidgetPropertyConnection::ControlWidgetPropertyConnection( WBaseWidget* pBaseWidget, const ConfigKey& key, - ValueTransformer* pTransformer, + std::unique_ptr pTransformer, const QString& propertyName) - : ControlWidgetConnection(pBaseWidget, key, pTransformer), + : ControlWidgetConnection(pBaseWidget, key, std::move(pTransformer)), m_propertyName(propertyName), m_property(propertyFromWidget(pBaseWidget->toQWidget(), propertyName)) { // Initial update to synchronize the property in all the sub widgets slotControlValueChanged(m_pControl->get()); } +ControlWidgetPropertyConnection::~ControlWidgetPropertyConnection() = default; + QString ControlWidgetPropertyConnection::toDebugString() const { const ConfigKey& key = getKey(); return QString("%1,%2 Parameter: %3 Property: %4 Value: %5") diff --git a/src/widget/controlwidgetconnection.h b/src/widget/controlwidgetconnection.h index 1fc4417612d..6d7e48471d4 100644 --- a/src/widget/controlwidgetconnection.h +++ b/src/widget/controlwidgetconnection.h @@ -2,21 +2,22 @@ #include #include -#include #include +#include #include "control/controlproxy.h" -#include "util/valuetransformer.h" +#include "util/parented_ptr.h" class WBaseWidget; +class ValueTransformer; class ControlWidgetConnection : public QObject { Q_OBJECT public: - // Takes ownership of pControl and pTransformer. ControlWidgetConnection(WBaseWidget* pBaseWidget, - const ConfigKey& key, - ValueTransformer* pTransformer); + const ConfigKey& key, + std::unique_ptr pTransformer); + ~ControlWidgetConnection() override; double getControlParameter() const; double getControlParameterForValue(double value) const; @@ -38,10 +39,10 @@ class ControlWidgetConnection : public QObject { // This ControlProxys is created as parent to this and deleted by // the Qt object tree. This helps that they are deleted by the creating // thread, which is required to avoid segfaults. - ControlProxy* m_pControl; + parented_ptr m_pControl; private: - QScopedPointer m_pValueTransformer; + std::unique_ptr m_pValueTransformer; }; class ControlParameterWidgetConnection final : public ControlWidgetConnection { @@ -94,10 +95,12 @@ class ControlParameterWidgetConnection final : public ControlWidgetConnection { } ControlParameterWidgetConnection(WBaseWidget* pBaseWidget, - const ConfigKey& key, - ValueTransformer* pTransformer, - DirectionOption directionOption, - EmitOption emitOption); + const ConfigKey& key, + std::unique_ptr pTransformer, + DirectionOption directionOption, + EmitOption emitOption); + + ~ControlParameterWidgetConnection() override; void Init(); @@ -126,9 +129,11 @@ class ControlWidgetPropertyConnection final : public ControlWidgetConnection { Q_OBJECT public: ControlWidgetPropertyConnection(WBaseWidget* pBaseWidget, - const ConfigKey& key, - ValueTransformer* pTransformer, - const QString& propertyName); + const ConfigKey& key, + std::unique_ptr pTransformer, + const QString& propertyName); + + ~ControlWidgetPropertyConnection() override; QString toDebugString() const override; diff --git a/src/widget/wbasewidget.cpp b/src/widget/wbasewidget.cpp index 27427e25ff7..2e7df4352e5 100644 --- a/src/widget/wbasewidget.cpp +++ b/src/widget/wbasewidget.cpp @@ -9,21 +9,7 @@ WBaseWidget::WBaseWidget(QWidget* pWidget) m_pWidget(pWidget) { } -WBaseWidget::~WBaseWidget() { - m_pDisplayConnection = nullptr; - while (!m_leftConnections.isEmpty()) { - delete m_leftConnections.takeLast(); - } - while (!m_rightConnections.isEmpty()) { - delete m_rightConnections.takeLast(); - } - while (!m_connections.isEmpty()) { - delete m_connections.takeLast(); - } - while (!m_propertyConnections.isEmpty()) { - delete m_propertyConnections.takeLast(); - } -} +WBaseWidget::~WBaseWidget() = default; void WBaseWidget::Init() { if (m_pDisplayConnection) { @@ -31,46 +17,53 @@ void WBaseWidget::Init() { } } -void WBaseWidget::setDisplayConnection(ControlParameterWidgetConnection* pConnection) { - //qDebug() << "WBaseWidget::setDisplayConnection()" << pConnection->toDebugString(); - m_pDisplayConnection = pConnection; -} - -void WBaseWidget::addConnection(ControlParameterWidgetConnection* pConnection) { - m_connections.append(pConnection); -} - -void WBaseWidget::addLeftConnection(ControlParameterWidgetConnection* pConnection) { - m_leftConnections.append(pConnection); +void WBaseWidget::addConnection( + std::unique_ptr pConnection, + ConnectionSide side) { + switch (side) { + case ConnectionSide::None: + m_connections.push_back(std::move(pConnection)); + break; + case ConnectionSide::Left: + m_leftConnections.push_back(std::move(pConnection)); + break; + case ConnectionSide::Right: + m_rightConnections.push_back(std::move(pConnection)); + break; + } } -void WBaseWidget::addRightConnection(ControlParameterWidgetConnection* pConnection) { - m_rightConnections.append(pConnection); +void WBaseWidget::addAndSetDisplayConnection( + std::unique_ptr pConnection, + ConnectionSide side) { + m_pDisplayConnection = pConnection.get(); + addConnection(std::move(pConnection), side); } -void WBaseWidget::addPropertyConnection(ControlWidgetPropertyConnection* pConnection) { - m_propertyConnections.append(pConnection); +void WBaseWidget::addPropertyConnection( + std::unique_ptr pConnection) { + m_propertyConnections.push_back(std::move(pConnection)); } double WBaseWidget::getControlParameter() const { - if (!m_connections.isEmpty()) { + if (!m_connections.empty()) { return m_connections.at(0)->getControlParameter(); } return 0.0; } double WBaseWidget::getControlParameterLeft() const { - if (!m_leftConnections.isEmpty()) { + if (!m_leftConnections.empty()) { return m_leftConnections.at(0)->getControlParameter(); } - if (!m_connections.isEmpty()) { + if (!m_connections.empty()) { return m_connections.at(0)->getControlParameter(); } return 0.0; } double WBaseWidget::getControlParameterRight() const { - if (!m_rightConnections.isEmpty()) { + if (!m_rightConnections.empty()) { return m_rightConnections.at(0)->getControlParameter(); } return 0.0; @@ -84,63 +77,63 @@ double WBaseWidget::getControlParameterDisplay() const { } void WBaseWidget::resetControlParameter() { - for (ControlParameterWidgetConnection* pControlConnection : std::as_const(m_connections)) { + for (const auto& pControlConnection : std::as_const(m_connections)) { pControlConnection->resetControl(); } } void WBaseWidget::setControlParameter(double v) { - for (ControlParameterWidgetConnection* pControlConnection : std::as_const(m_connections)) { + for (const auto& pControlConnection : std::as_const(m_connections)) { pControlConnection->setControlParameter(v); } } void WBaseWidget::setControlParameterUp(double v) { - for (ControlParameterWidgetConnection* pControlConnection : std::as_const(m_connections)) { + for (const auto& pControlConnection : std::as_const(m_connections)) { pControlConnection->setControlParameterUp(v); } } void WBaseWidget::setControlParameterDown(double v) { - for (ControlParameterWidgetConnection* pControlConnection : std::as_const(m_connections)) { + for (const auto& pControlConnection : std::as_const(m_connections)) { pControlConnection->setControlParameterDown(v); } } void WBaseWidget::setControlParameterLeftDown(double v) { - if (!m_leftConnections.isEmpty()) { - for (ControlParameterWidgetConnection* pControlConnection : + if (!m_leftConnections.empty()) { + for (const auto& pControlConnection : std::as_const(m_leftConnections)) { pControlConnection->setControlParameterDown(v); } } else { - for (ControlParameterWidgetConnection* pControlConnection : std::as_const(m_connections)) { + for (const auto& pControlConnection : std::as_const(m_connections)) { pControlConnection->setControlParameterDown(v); } } } void WBaseWidget::setControlParameterLeftUp(double v) { - if (!m_leftConnections.isEmpty()) { - for (ControlParameterWidgetConnection* pControlConnection : + if (!m_leftConnections.empty()) { + for (const auto& pControlConnection : std::as_const(m_leftConnections)) { pControlConnection->setControlParameterUp(v); } } else { - for (ControlParameterWidgetConnection* pControlConnection : std::as_const(m_connections)) { + for (const auto& pControlConnection : std::as_const(m_connections)) { pControlConnection->setControlParameterUp(v); } } } void WBaseWidget::setControlParameterRightDown(double v) { - for (ControlParameterWidgetConnection* pControlConnection : std::as_const(m_rightConnections)) { + for (const auto& pControlConnection : std::as_const(m_rightConnections)) { pControlConnection->setControlParameterDown(v); } } void WBaseWidget::setControlParameterRightUp(double v) { - for (ControlParameterWidgetConnection* pControlConnection : std::as_const(m_rightConnections)) { + for (const auto& pControlConnection : std::as_const(m_rightConnections)) { pControlConnection->setControlParameterUp(v); } } @@ -193,14 +186,14 @@ void WBaseWidget::fillDebugTooltip(QStringList* debug) { << QString("SizeHint: %1").arg(toDebugString(m_pWidget->sizeHint())) << QString("MinimumSizeHint: %1").arg(toDebugString(m_pWidget->minimumSizeHint())); - for (ControlParameterWidgetConnection* pControlConnection : std::as_const(m_leftConnections)) { - *debug << QString("LeftConnection: %1").arg(pControlConnection->toDebugString()); + for (const auto& pControlConnection : std::as_const(m_leftConnections)) { + *debug << QString("LeftConnection: %1").arg(pControlConnection->toDebugString()); } - for (ControlParameterWidgetConnection* pControlConnection : std::as_const(m_rightConnections)) { - *debug << QString("RightConnection: %1").arg(pControlConnection->toDebugString()); + for (const auto& pControlConnection : std::as_const(m_rightConnections)) { + *debug << QString("RightConnection: %1").arg(pControlConnection->toDebugString()); } - for (ControlParameterWidgetConnection* pControlConnection : std::as_const(m_connections)) { - *debug << QString("Connection: %1").arg(pControlConnection->toDebugString()); + for (const auto& pControlConnection : std::as_const(m_connections)) { + *debug << QString("Connection: %1").arg(pControlConnection->toDebugString()); } if (m_pDisplayConnection) { *debug << QString("DisplayConnection: %1").arg(m_pDisplayConnection->toDebugString()); diff --git a/src/widget/wbasewidget.h b/src/widget/wbasewidget.h index aca5d52a4ca..c9e0834551e 100644 --- a/src/widget/wbasewidget.h +++ b/src/widget/wbasewidget.h @@ -2,7 +2,8 @@ #include #include -#include +#include +#include class ControlWidgetPropertyConnection; class ControlParameterWidgetConnection; @@ -12,6 +13,12 @@ class WBaseWidget { explicit WBaseWidget(QWidget* pWidget); virtual ~WBaseWidget(); + enum class ConnectionSide { + None, + Left, + Right + }; + virtual void Init(); QWidget* toQWidget() { @@ -37,29 +44,25 @@ class WBaseWidget { return m_baseTooltip; } - void addLeftConnection(ControlParameterWidgetConnection* pConnection); - void addRightConnection(ControlParameterWidgetConnection* pConnection); - void addConnection(ControlParameterWidgetConnection* pConnection); + void addConnection( + std::unique_ptr pConnection, + ConnectionSide side); - void addPropertyConnection(ControlWidgetPropertyConnection* pConnection); + void addPropertyConnection(std::unique_ptr pConnection); - // Set a ControlWidgetConnection to be the display connection for the - // widget. The connection should also be added via an addConnection method - // or it will not be deleted or receive updates. - void setDisplayConnection(ControlParameterWidgetConnection* pConnection); + // Add a ControlWidgetConnection to be the display connection for the + // widget. There can only be one DisplayConnection. Calling this multiple + // times will add each connection but only the last one is considered to be + // the DisplayConnection. + void addAndSetDisplayConnection( + std::unique_ptr pConnection, + ConnectionSide side); double getControlParameter() const; double getControlParameterLeft() const; double getControlParameterRight() const; double getControlParameterDisplay() const; - inline const QList& connections() const { - return m_connections; - }; - inline const QList& leftConnections() const { - return m_leftConnections; - }; - protected: // Whenever a connected control is changed, onConnectedControlChanged is @@ -86,12 +89,12 @@ class WBaseWidget { void updateTooltip(); virtual void fillDebugTooltip(QStringList* debug); - QList m_connections; + std::vector> m_connections; ControlParameterWidgetConnection* m_pDisplayConnection; - QList m_leftConnections; - QList m_rightConnections; + std::vector> m_leftConnections; + std::vector> m_rightConnections; - QList m_propertyConnections; + std::vector> m_propertyConnections; private: QWidget* m_pWidget; diff --git a/src/widget/whotcuebutton.cpp b/src/widget/whotcuebutton.cpp index 2adb77304d5..9e55ec23354 100644 --- a/src/widget/whotcuebutton.cpp +++ b/src/widget/whotcuebutton.cpp @@ -4,8 +4,11 @@ #include "mixer/playerinfo.h" #include "moc_whotcuebutton.cpp" +#include "skin/legacy/skincontext.h" #include "track/track.h" +#include "util/valuetransformer.h" #include "widget/controlwidgetconnection.h" +#include "widget/wbasewidget.h" namespace { constexpr int kDefaultDimBrightThreshold = 127; @@ -67,22 +70,21 @@ void WHotcueButton::setup(const QDomNode& node, const SkinContext& context) { m_pCoType->connectValueChanged(this, &WHotcueButton::slotTypeChanged); slotTypeChanged(m_pCoType->get()); - auto* pLeftConnection = new ControlParameterWidgetConnection( - this, - getLeftClickConfigKey(), // "activate" - nullptr, - ControlParameterWidgetConnection::DIR_FROM_WIDGET, - ControlParameterWidgetConnection::EMIT_ON_PRESS_AND_RELEASE); - addLeftConnection(pLeftConnection); - - auto* pDisplayConnection = new ControlParameterWidgetConnection( - this, - createConfigKey(QStringLiteral("status")), - nullptr, - ControlParameterWidgetConnection::DIR_TO_WIDGET, - ControlParameterWidgetConnection::EMIT_NEVER); - addConnection(pDisplayConnection); - setDisplayConnection(pDisplayConnection); + addConnection(std::make_unique( + this, + getLeftClickConfigKey(), // "activate" + nullptr, + ControlParameterWidgetConnection::DIR_FROM_WIDGET, + ControlParameterWidgetConnection::EMIT_ON_PRESS_AND_RELEASE), + WBaseWidget::ConnectionSide::Left); + + addAndSetDisplayConnection(std::make_unique( + this, + createConfigKey(QStringLiteral("status")), + nullptr, + ControlParameterWidgetConnection::DIR_TO_WIDGET, + ControlParameterWidgetConnection::EMIT_NEVER), + WBaseWidget::ConnectionSide::None); QDomNode con = context.selectNode(node, QStringLiteral("Connection")); if (!con.isNull()) { diff --git a/src/widget/woverview.cpp b/src/widget/woverview.cpp index ec267f647f0..2bbf7c69e00 100644 --- a/src/widget/woverview.cpp +++ b/src/widget/woverview.cpp @@ -234,13 +234,13 @@ void WOverview::setup(const QDomNode& node, const SkinContext& context) { // qDebug() << "WOverview : std::as_const(m_marks)" << m_marks.size(); // qDebug() << "WOverview : m_markRanges" << m_markRanges.size(); - if (!m_connections.isEmpty()) { - ControlParameterWidgetConnection* defaultConnection = m_connections.at(0); - if (defaultConnection) { - if (defaultConnection->getEmitOption() & + if (!m_connections.empty()) { + auto& pDefaultConnection = m_connections.at(0); + if (pDefaultConnection) { + if (pDefaultConnection->getEmitOption() & ControlParameterWidgetConnection::EMIT_DEFAULT) { // ON_PRESS means here value change on mouse move during press - defaultConnection->setEmitOption( + pDefaultConnection->setEmitOption( ControlParameterWidgetConnection::EMIT_ON_RELEASE); } } diff --git a/src/widget/wpushbutton.cpp b/src/widget/wpushbutton.cpp index 5cc3c188203..426acd2fefb 100644 --- a/src/widget/wpushbutton.cpp +++ b/src/widget/wpushbutton.cpp @@ -11,6 +11,7 @@ #include "control/controlobject.h" #include "control/controlpushbutton.h" #include "moc_wpushbutton.cpp" +#include "skin/legacy/skincontext.h" #include "util/debug.h" #include "widget/controlwidgetconnection.h" #include "widget/wpixmapstore.h" @@ -131,13 +132,13 @@ void WPushButton::setup(const QDomNode& node, const SkinContext& context) { } ControlParameterWidgetConnection* leftConnection = nullptr; - if (m_leftConnections.isEmpty()) { - if (!m_connections.isEmpty()) { + if (m_leftConnections.empty()) { + if (!m_connections.empty()) { // If no left connection is set, the this is the left connection - leftConnection = m_connections.at(0); + leftConnection = m_connections[0].get(); } } else { - leftConnection = m_leftConnections.at(0); + leftConnection = m_leftConnections[0].get(); } if (leftConnection) { @@ -186,8 +187,8 @@ void WPushButton::setup(const QDomNode& node, const SkinContext& context) { } } - if (!m_rightConnections.isEmpty()) { - ControlParameterWidgetConnection* rightConnection = m_rightConnections.at(0); + if (!m_rightConnections.empty()) { + auto& rightConnection = m_rightConnections[0]; bool rightClickForcePush = context.selectBool(node, "RightClickIsPushButton", false); m_rightButtonMode = mixxx::control::ButtonMode::Push; if (!rightClickForcePush) { diff --git a/src/widget/wpushbutton.h b/src/widget/wpushbutton.h index 1e4ff3ddf09..94fbad7e6b4 100644 --- a/src/widget/wpushbutton.h +++ b/src/widget/wpushbutton.h @@ -5,7 +5,7 @@ #include #include -#include "control/controlpushbutton.h" +#include "control/controlbuttonmode.h" #include "util/fpclassify.h" #include "util/performancetimer.h" #include "widget/wpixmapstore.h" diff --git a/src/widget/wslidercomposed.cpp b/src/widget/wslidercomposed.cpp index 52c6c0c60d8..8b127d8ab4c 100644 --- a/src/widget/wslidercomposed.cpp +++ b/src/widget/wslidercomposed.cpp @@ -6,6 +6,7 @@ #include #include "moc_wslidercomposed.cpp" +#include "skin/legacy/skincontext.h" #include "util/debug.h" #include "widget/controlwidgetconnection.h" #include "widget/wpixmapstore.h" @@ -162,13 +163,13 @@ void WSliderComposed::setup(const QDomNode& node, const SkinContext& context) { m_handler.setEventWhileDrag(false); } } - if (!m_connections.isEmpty()) { - ControlParameterWidgetConnection* defaultConnection = m_connections.at(0); - if (defaultConnection) { - if (defaultConnection->getEmitOption() & + if (!m_connections.empty()) { + auto& pDefaultConnection = m_connections[0]; + if (pDefaultConnection) { + if (pDefaultConnection->getEmitOption() & ControlParameterWidgetConnection::EMIT_DEFAULT) { // ON_PRESS means here value change on mouse move during press - defaultConnection->setEmitOption( + pDefaultConnection->setEmitOption( ControlParameterWidgetConnection::EMIT_ON_PRESS_AND_RELEASE); } }