Something went wrong. Try again.
Mixxx DJ software with MCP, Subsonic/Navidrome streaming library support — browse and load tracks from your self-hosted music server mixxx.org
subsonic navidrome streaming audio dj mac linux midi
Something went wrong. Try again.
C++
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393#include "widget/wslidercomposed.h"
#include <QStringView>#include <QStyleOption>#include <QStylePainter>#include <QtDebug>
#include "moc_wslidercomposed.cpp"#include "skin/legacy/skincontext.h"#include "util/debug.h"#include "widget/controlwidgetconnection.h"#include "widget/wpixmapstore.h"#include "widget/wskincolor.h"
WSliderComposed::WSliderComposed(QWidget* parent) : WWidget(parent), m_dHandleLength(0.0), m_dSliderLength(0.0), m_bHorizontal(false), m_dBarWidth(0.0), m_dBarBgWidth(0.0), m_dBarStart(0.0), m_dBarEnd(0.0), m_dBarBgStart(0.0), m_dBarBgEnd(0.0), m_dBarAxisPos(0.0), m_bBarUnipolar(true), m_barColor(nullptr), m_barBgColor(nullptr), m_barPenCap(Qt::FlatCap), m_pSlider(nullptr), m_pHandle(nullptr) {}
WSliderComposed::~WSliderComposed() { unsetPixmaps();}
bool WSliderComposed::tryParseHorizontal(const QDomNode& node) const { QDomNode horiNode = SkinContext::selectNode(node, "Horizontal"); if (!horiNode.isNull()) { QDomNode child = horiNode.firstChild(); if (!child.isNull() && child.isText()) { // No support for variables. if (child.nodeValue().contains("true", Qt::CaseInsensitive)) { return true; } } } return false;}
void WSliderComposed::setup(const QDomNode& node, const SkinContext& context) { // Setup pixmaps unsetPixmaps();
m_bHorizontal = context.selectBool(node, "Horizontal", false);
double scaleFactor = context.getScaleFactor(); QDomElement slider = context.selectElement(node, "Slider"); if (!slider.isNull()) { // The implicit default in <1.12.0 was FIXED so we keep it for backwards // compatibility. PixmapSource sourceSlider = context.getPixmapSource(slider); setSliderPixmap( sourceSlider, context.selectScaleMode(slider, Paintable::DrawMode::Fixed), scaleFactor); }
m_dSliderLength = m_bHorizontal ? width() : height(); m_handler.setSliderLength(m_dSliderLength);
QDomElement handle = context.selectElement(node, "Handle"); PixmapSource sourceHandle = context.getPixmapSource(handle); // The implicit default in <1.12.0 was FIXED so we keep it for backwards // compatibility. setHandlePixmap( sourceHandle, context.selectScaleMode(handle, Paintable::DrawMode::Fixed), scaleFactor);
// Set up the level bar. QColor barColor = context.selectColor(node, "BarColor"); context.hasNodeSelectDouble(node, "BarWidth", &m_dBarWidth); if (barColor.isValid() && m_dBarWidth > 0.0) { m_barColor = WSkinColor::getCorrectColor(barColor); m_dBarWidth *= scaleFactor; QString margins; QString bgMargins; if (context.hasNodeSelectString(node, "BarMargins", &margins)) { int comma = margins.indexOf(","); if (comma > 0 && comma < margins.size()) { bool m1ok; bool m2ok; QStringView marginsView(margins);#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) double m1 = (marginsView.first(comma)).toDouble(&m1ok); double m2 = (marginsView.sliced(comma + 1)).toDouble(&m2ok);#else QLocale c(QLocale::C); double m1 = c.toDouble(marginsView.left(comma), &m1ok); double m2 = c.toDouble(marginsView.mid(comma + 1), &m2ok);#endif if (m1ok && m2ok) { m_dBarStart = m1 * scaleFactor; m_dBarEnd = m2 * scaleFactor; } } }
// Set up the bar background if there's a valid color set. // If the background width and margins are not set explicitly // we simply adopt the settings of the level bar. QColor barBgColor = context.selectColor(node, "BarBgColor"); if (barBgColor.isValid()) { m_barBgColor = WSkinColor::getCorrectColor(barBgColor); if (context.hasNodeSelectDouble(node, "BarBgWidth", &m_dBarBgWidth)) { if (m_dBarBgWidth > 0.0) { m_dBarBgWidth *= scaleFactor; } } else { m_dBarBgWidth = m_dBarWidth; } if (context.hasNodeSelectString(node, "BarBgMargins", &bgMargins)) { int comma = bgMargins.indexOf(","); if (comma > 0 && comma + 1 < margins.size()) { bool m1ok; bool m2ok; QStringView bgMarginsView(bgMargins);#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) double m1 = (bgMarginsView.first(comma)).toDouble(&m1ok); double m2 = (bgMarginsView.sliced(comma + 1)).toDouble(&m2ok);#else QLocale c(QLocale::C); double m1 = c.toDouble(bgMarginsView.left(comma), &m1ok); double m2 = c.toDouble(bgMarginsView.mid(comma + 1), &m2ok);#endif if (m1ok && m2ok) { m_dBarBgStart = m1 * scaleFactor; m_dBarBgEnd = m2 * scaleFactor; } } } else { m_dBarBgStart = m_dBarStart; m_dBarBgEnd = m_dBarEnd; } } // Shift the bar center line to the right or to the bottom (horizontal sliders) if (context.hasNodeSelectDouble(node, "BarAxisPos", &m_dBarAxisPos)) { m_dBarAxisPos *= scaleFactor; } // Draw the bar from 0 by default, from bottom or from left (horizontal) m_bBarUnipolar = context.selectBool(node, "BarUnipolar", true); if (context.selectBool(node, "BarRoundCaps", false)) { m_barPenCap = Qt::RoundCap; } }
QString eventWhileDrag; if (context.hasNodeSelectString(node, "EventWhileDrag", &eventWhileDrag)) { if (eventWhileDrag.contains("no")) { m_handler.setEventWhileDrag(false); } } 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 pDefaultConnection->setEmitOption( ControlParameterWidgetConnection::EMIT_ON_PRESS_AND_RELEASE); } } }
setFocusPolicy(Qt::NoFocus);}
void WSliderComposed::setSliderPixmap(const PixmapSource& sourceSlider, Paintable::DrawMode drawMode, double scaleFactor) { m_pSlider = WPixmapStore::getPaintable(sourceSlider, drawMode, scaleFactor); if (!m_pSlider) { qDebug() << "WSliderComposed: Error loading slider pixmap:" << sourceSlider.getPath(); } else if (drawMode == Paintable::DrawMode::Fixed) { // Set size of widget, using size of slider pixmap setFixedSize(m_pSlider->size()); }}
void WSliderComposed::setHandlePixmap( const PixmapSource& sourceHandle, Paintable::DrawMode mode, double scaleFactor) { m_handler.setHorizontal(m_bHorizontal); m_pHandle = WPixmapStore::getPaintable(sourceHandle, mode, scaleFactor); m_dHandleLength = calculateHandleLength(); m_handler.setHandleLength(m_dHandleLength); if (!m_pHandle) { qDebug() << "WSliderComposed: Error loading handle pixmap:" << sourceHandle.getPath(); } else { // Value is unused in WSliderComposed. onConnectedControlChanged(getControlParameter(), 0); update(); }}
void WSliderComposed::unsetPixmaps() { m_pSlider.reset(); m_pHandle.reset();}
void WSliderComposed::mouseMoveEvent(QMouseEvent * e) { m_handler.mouseMoveEvent(this, e);}
void WSliderComposed::wheelEvent(QWheelEvent *e) { m_handler.wheelEvent(this, e);}
void WSliderComposed::mouseReleaseEvent(QMouseEvent * e) { m_handler.mouseReleaseEvent(this, e);}
void WSliderComposed::mousePressEvent(QMouseEvent * e) { m_handler.mousePressEvent(this, e);}
void WSliderComposed::mouseDoubleClickEvent(QMouseEvent* e) { m_handler.mouseDoubleClickEvent(this, e);}
void WSliderComposed::paintEvent(QPaintEvent * /*unused*/) { QStyleOption option; option.initFrom(this); QStylePainter p(this); p.drawPrimitive(QStyle::PE_Widget, option);
if (m_pSlider && !m_pSlider->isNull()) { m_pSlider->draw(rect(), &p); }
// Draw level bar underneath handle if (m_barColor.isValid() && m_dBarWidth > 0.0) { drawBar(&p); }
if (m_pHandle && !m_pHandle->isNull()) { // Slider position rounded, verify this for HiDPI : bug 1479037 double drawPos = round(m_handler.parameterToPosition(getControlParameterDisplay())); QRectF targetRect; if (m_bHorizontal) { // The handle's draw mode determines whether it is stretched. targetRect = QRectF(drawPos, 0, m_dHandleLength, height()); } else { // The handle's draw mode determines whether it is stretched. targetRect = QRectF(0, drawPos, width(), m_dHandleLength); } m_pHandle->draw(targetRect, &p); }}
void WSliderComposed::drawBar(QPainter* pPainter) { double x1; double x2; double y1; double y2; double value;
// Draw bar background if (m_dBarBgWidth > 0.0) { QPen barBgPen = QPen(m_barBgColor); barBgPen.setWidthF(m_dBarBgWidth); barBgPen.setCapStyle(m_barPenCap); pPainter->setPen(barBgPen); QLineF barBg; if (m_bHorizontal) { barBg = QLineF(m_dBarBgStart, m_dBarAxisPos, width() - m_dBarBgEnd, m_dBarAxisPos); } else { barBg = QLineF(m_dBarAxisPos, height() - m_dBarBgEnd, m_dBarAxisPos, m_dBarBgStart); } pPainter->drawLine(barBg); }
QPen barPen = QPen(m_barColor); barPen.setWidthF(m_dBarWidth); barPen.setCapStyle(m_barPenCap); pPainter->setPen(barPen);
if (m_bHorizontal) { // Left to right increases the parameter value = getControlParameterDisplay(); if (m_bBarUnipolar) { // draw from the left x1 = m_dBarStart; } else { // draw from center x1 = m_dBarStart + (width() - m_dBarStart -m_dBarEnd) / 2; } x2 = m_dBarStart + value * (width() - m_dBarStart - m_dBarEnd); y1 = m_dBarAxisPos; y2 = y1; } else { // vertical slider // Sliders usually increase parameters when moved UP, but pixels // are count top to bottom, so we flip the scale value = 1.0 - getControlParameterDisplay(); x1 = m_dBarAxisPos; x2 = x1; if (m_bBarUnipolar) { // draw from bottom y1 = height() - m_dBarEnd; } else { // draw from center y1 = m_dBarEnd + (height() - m_dBarStart - m_dBarEnd) / 2; } y2 = m_dBarStart + value * (height() - m_dBarStart - m_dBarEnd); } pPainter->drawLine(QLineF(x1, y1, x2, y2));}
void WSliderComposed::resizeEvent(QResizeEvent* pEvent) { Q_UNUSED(pEvent);
m_dHandleLength = calculateHandleLength(); m_handler.setHandleLength(m_dHandleLength); m_dSliderLength = m_bHorizontal ? width() : height(); m_handler.setSliderLength(m_dSliderLength); m_handler.resizeEvent(this, pEvent);
// Re-calculate state based on our new width/height. onConnectedControlChanged(getControlParameter(), 0);}
void WSliderComposed::onConnectedControlChanged(double dParameter, double /*dValue*/) { m_handler.onConnectedControlChanged(this, dParameter);}
void WSliderComposed::fillDebugTooltip(QStringList* debug) { WWidget::fillDebugTooltip(debug); int sliderLength = m_bHorizontal ? width() : height(); *debug << QString("Horizontal: %1").arg(toDebugString(m_bHorizontal)) << QString("SliderPosition: %1").arg( m_handler.parameterToPosition(getControlParameterDisplay())) << QString("SliderLength: %1").arg(sliderLength) << QString("HandleLength: %1").arg(m_dHandleLength);}
double WSliderComposed::calculateHandleLength() { if (m_pHandle) { Paintable::DrawMode mode = m_pHandle->drawMode(); if (m_bHorizontal) { // Stretch the pixmap to be the height of the widget. if (mode == Paintable::DrawMode::Fixed || mode == Paintable::DrawMode::Stretch || mode == Paintable::DrawMode::Tile || m_pHandle->height() == 0.0) { return m_pHandle->width(); } else if (mode == Paintable::DrawMode::StretchAspect) { const int iHeight = m_pHandle->height(); if (iHeight == 0) { qDebug() << "WSliderComposed: Invalid height."; return 0.0; } const qreal aspect = static_cast<qreal>(m_pHandle->width()) / iHeight; return aspect * height(); } } else { // Stretch the pixmap to be the width of the widget. if (mode == Paintable::DrawMode::Fixed || mode == Paintable::DrawMode::Stretch || mode == Paintable::DrawMode::Tile || m_pHandle->width() == 0.0) { return m_pHandle->height(); } else if (mode == Paintable::DrawMode::StretchAspect) { const int iWidth = m_pHandle->width(); if (iWidth == 0) { qDebug() << "WSliderComposed: Invalid width."; return 0.0; } const qreal aspect = static_cast<qreal>(m_pHandle->height()) / iWidth; return aspect * width(); } } } return 0;}
void WSliderComposed::inputActivity() { update();}