#include "widget/controlwidgetconnection.h" #include #include "control/controlproxy.h" #include "moc_controlwidgetconnection.cpp" #include "util/assert.h" #include "util/debug.h" #include "util/valuetransformer.h" #include "widget/wbasewidget.h" namespace { QMetaProperty propertyFromWidget(const QWidget* pWidget, const QString& name) { VERIFY_OR_DEBUG_ASSERT(!name.isEmpty()) { return QMetaProperty(); } VERIFY_OR_DEBUG_ASSERT(pWidget) { return QMetaProperty(); } const QMetaObject* meta = pWidget->metaObject(); VERIFY_OR_DEBUG_ASSERT(meta) { return QMetaProperty(); } const int id = meta->indexOfProperty(name.toLatin1().constData()); VERIFY_OR_DEBUG_ASSERT(id >= 0) { return QMetaProperty(); } return meta->property(id); } } // namespace ControlWidgetConnection::ControlWidgetConnection( WBaseWidget* pBaseWidget, const ConfigKey& key, ValueTransformer* pTransformer) : m_pWidget(pBaseWidget), m_pValueTransformer(pTransformer) { m_pControl = new ControlProxy(key, this, ControlFlag::NoAssertIfMissing); m_pControl->connectValueChanged(this, &ControlWidgetConnection::slotControlValueChanged); } void ControlWidgetConnection::setControlParameter(double parameter) { if (m_pValueTransformer != nullptr) { parameter = m_pValueTransformer->transformInverse(parameter); } m_pControl->setParameter(parameter); } double ControlWidgetConnection::getControlParameter() const { double parameter = m_pControl->getParameter(); if (m_pValueTransformer != nullptr) { parameter = m_pValueTransformer->transform(parameter); } return parameter; } double ControlWidgetConnection::getControlParameterForValue(double value) const { double parameter = m_pControl->getParameterForValue(value); if (m_pValueTransformer != nullptr) { parameter = m_pValueTransformer->transform(parameter); } return parameter; } ControlParameterWidgetConnection::ControlParameterWidgetConnection( WBaseWidget* pBaseWidget, const ConfigKey& key, ValueTransformer* pTransformer, DirectionOption directionOption, EmitOption emitOption) : ControlWidgetConnection(pBaseWidget, key, pTransformer), m_directionOption(directionOption), m_emitOption(emitOption) { } void ControlParameterWidgetConnection::Init() { slotControlValueChanged(m_pControl->get()); } QString ControlParameterWidgetConnection::toDebugString() const { const ConfigKey& key = getKey(); return QString("%1,%2 Parameter: %3 Value: %4 Direction: %5 Emit: %6") .arg(key.group, key.item, QString::number(m_pControl->getParameter()), QString::number(m_pControl->get()), directionOptionToString(m_directionOption), emitOptionToString(m_emitOption)); } void ControlParameterWidgetConnection::slotControlValueChanged(double value) { if (m_directionOption & DIR_TO_WIDGET) { const double parameter = getControlParameterForValue(value); m_pWidget->onConnectedControlChanged(parameter, value); } } void ControlParameterWidgetConnection::resetControl() { if (m_directionOption & DIR_FROM_WIDGET) { m_pControl->reset(); } } void ControlParameterWidgetConnection::setControlParameter(double v) { if (m_directionOption & DIR_FROM_WIDGET) { ControlWidgetConnection::setControlParameter(v); } } void ControlParameterWidgetConnection::setControlParameterDown(double v) { if ((m_directionOption & DIR_FROM_WIDGET) && (m_emitOption & EMIT_ON_PRESS)) { ControlWidgetConnection::setControlParameter(v); } } void ControlParameterWidgetConnection::setControlParameterUp(double v) { if ((m_directionOption & DIR_FROM_WIDGET) && (m_emitOption & EMIT_ON_RELEASE)) { ControlWidgetConnection::setControlParameter(v); } } ControlWidgetPropertyConnection::ControlWidgetPropertyConnection( WBaseWidget* pBaseWidget, const ConfigKey& key, ValueTransformer* pTransformer, const QString& propertyName) : ControlWidgetConnection(pBaseWidget, key, 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()); } QString ControlWidgetPropertyConnection::toDebugString() const { const ConfigKey& key = getKey(); return QString("%1,%2 Parameter: %3 Property: %4 Value: %5") .arg(key.group, key.item, QString::number(m_pControl->getParameter()), m_propertyName, m_property.read(m_pWidget->toQWidget()).toString()); } void ControlWidgetPropertyConnection::slotControlValueChanged(double v) { const double parameter = getControlParameterForValue(v); QVariant vParameter; if (m_property.type() == QVariant::Bool) { vParameter = (parameter > 0); } else { vParameter = parameter; } bool success = vParameter.convert(m_property.type()); VERIFY_OR_DEBUG_ASSERT(success) { return; } if (m_propertyValue == vParameter) { // don't repeat writing the same value that may stall the GUI // Comparing the property value directly does not work, because // in some cases (e.g. visible) it has to be propagated to the child widgets. return; } QWidget* pWidget = m_pWidget->toQWidget(); if (!m_property.write(pWidget, vParameter)) { const ConfigKey& key = getKey(); qWarning() << "Property" << m_propertyName << "was not defined for widget" << pWidget << "(parameter:" << parameter << ")" << key.group << key.item; return; } m_propertyValue = vParameter; // According to http://stackoverflow.com/a/3822243 this is the least // expensive way to restyle just this widget. pWidget->style()->unpolish(pWidget); pWidget->style()->polish(pWidget); // These calls don't always trigger the repaint, so call it explicitly. pWidget->repaint(); }