/* * Pixmap Dial, a custom Qt4 widget * Copyright (C) 2011-2013 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or 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 General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "pixmapdial.hpp" #include #include #include #include PixmapDial::PixmapDial(QWidget* parent) : QDial(parent), fPixmap(":/bitmaps/dial_01d.png"), fPixmapNum("01"), fCustomPaint(CUSTOM_PAINT_NULL), fOrientation(fPixmap.width() > fPixmap.height() ? HORIZONTAL : VERTICAL), fHovered(false), fHoverStep(HOVER_MIN), fLabel(""), fLabelPos(0.0f, 0.0f), fLabelWidth(0), fLabelHeight(0), fLabelGradient(0, 0, 0, 1) { fLabelFont.setPointSize(6); if (palette().window().color().lightness() > 100) { // Light background const QColor c(palette().dark().color()); fColor1 = c; fColor2 = QColor(c.red(), c.green(), c.blue(), 0); fColorT[0] = palette().buttonText().color(); fColorT[1] = palette().mid().color(); } else { // Dark background fColor1 = QColor(0, 0, 0, 255); fColor2 = QColor(0, 0, 0, 0); fColorT[0] = Qt::white; fColorT[1] = Qt::darkGray; } updateSizes(); } int PixmapDial::getSize() const { return fSize; } void PixmapDial::setCustomPaint(CustomPaint paint) { fCustomPaint = paint; fLabelPos.setY(fSize + fLabelHeight/2); update(); } void PixmapDial::setEnabled(bool enabled) { if (isEnabled() != enabled) { fPixmap.load(QString(":/bitmaps/dial_%1%2.png").arg(fPixmapNum).arg(enabled ? "" : "d")); updateSizes(); update(); } QDial::setEnabled(enabled); } void PixmapDial::setLabel(QString label) { fLabel = label; fLabelWidth = QFontMetrics(font()).width(label); fLabelHeight = QFontMetrics(font()).height(); fLabelPos.setX(float(fSize)/2.0f - float(fLabelWidth)/2.0f); fLabelPos.setY(fSize + fLabelHeight); fLabelGradient.setColorAt(0.0f, fColor1); fLabelGradient.setColorAt(0.6f, fColor1); fLabelGradient.setColorAt(1.0f, fColor2); fLabelGradient.setStart(0, float(fSize)/2.0f); fLabelGradient.setFinalStop(0, fSize + fLabelHeight + 5); fLabelGradientRect = QRectF(float(fSize)/8.0f, float(fSize)/2.0f, float(fSize*6)/8.0f, fSize+fLabelHeight+5); update(); } void PixmapDial::setPixmap(int pixmapId) { fPixmapNum.sprintf("%02i", pixmapId); fPixmap.load(QString(":/bitmaps/dial_%1%2.png").arg(fPixmapNum).arg(isEnabled() ? "" : "d")); if (fPixmap.width() > fPixmap.height()) fOrientation = HORIZONTAL; else fOrientation = VERTICAL; updateSizes(); update(); } QSize PixmapDial::minimumSizeHint() const { return QSize(fSize, fSize); } QSize PixmapDial::sizeHint() const { return QSize(fSize, fSize); } void PixmapDial::updateSizes() { fWidth = fPixmap.width(); fHeight = fPixmap.height(); if (fWidth < 1) fWidth = 1; if (fHeight < 1) fHeight = 1; if (fOrientation == HORIZONTAL) { fSize = fHeight; fCount = fWidth/fHeight; } else { fSize = fWidth; fCount = fHeight/fWidth; } setMinimumSize(fSize, fSize + fLabelHeight + 5); setMaximumSize(fSize, fSize + fLabelHeight + 5); } void PixmapDial::enterEvent(QEvent* event) { fHovered = true; if (fHoverStep == HOVER_MIN) fHoverStep = HOVER_MIN + 1; QDial::enterEvent(event); } void PixmapDial::leaveEvent(QEvent* event) { fHovered = false; if (fHoverStep == HOVER_MAX) fHoverStep = HOVER_MAX - 1; QDial::leaveEvent(event); } void PixmapDial::paintEvent(QPaintEvent* event) { event->accept(); QPainter painter(this); painter.save(); painter.setRenderHint(QPainter::Antialiasing, true); if (! fLabel.isEmpty()) { if (fCustomPaint == CUSTOM_PAINT_NULL) { painter.setPen(fColor2); painter.setBrush(fLabelGradient); painter.drawRect(fLabelGradientRect); } painter.setFont(fLabelFont); painter.setPen(fColorT[isEnabled() ? 0 : 1]); painter.drawText(fLabelPos, fLabel); } if (isEnabled()) { float current = value()-minimum(); float divider = maximum()-minimum(); if (divider == 0.0f) return; float value = current/divider; QRectF source, target(0.0f, 0.0f, fSize, fSize); int xpos, ypos, per = (fCount-1)*value; if (fOrientation == HORIZONTAL) { xpos = fSize*per; ypos = 0.0f; } else { xpos = 0.0f; ypos = fSize*per; } source = QRectF(xpos, ypos, fSize, fSize); painter.drawPixmap(target, fPixmap, source); // Custom knobs (Dry/Wet and Volume) if (fCustomPaint == CUSTOM_PAINT_CARLA_WET || fCustomPaint == CUSTOM_PAINT_CARLA_VOL) { // knob color QColor colorGreen(0x5D, 0xE7, 0x3D, 191 + fHoverStep*7); QColor colorBlue(0x3E, 0xB8, 0xBE, 191 + fHoverStep*7); // draw small circle QRectF ballRect(8.0f, 8.0f, 15.0f, 15.0f); QPainterPath ballPath; ballPath.addEllipse(ballRect); //painter.drawRect(ballRect); float tmpValue = (0.375f + 0.75f*value); float ballValue = tmpValue - std::floor(tmpValue); QPointF ballPoint(ballPath.pointAtPercent(ballValue)); // draw arc int startAngle = 216*16; int spanAngle = -252*16*value; if (fCustomPaint == CUSTOM_PAINT_CARLA_WET) { painter.setBrush(colorBlue); painter.setPen(QPen(colorBlue, 0)); painter.drawEllipse(QRectF(ballPoint.x(), ballPoint.y(), 2.2f, 2.2f)); QConicalGradient gradient(15.5f, 15.5f, -45); gradient.setColorAt(0.0f, colorBlue); gradient.setColorAt(0.125f, colorBlue); gradient.setColorAt(0.625f, colorGreen); gradient.setColorAt(0.75f, colorGreen); gradient.setColorAt(0.76f, colorGreen); gradient.setColorAt(1.0f, colorGreen); painter.setBrush(gradient); painter.setPen(QPen(gradient, 3)); } else { painter.setBrush(colorBlue); painter.setPen(QPen(colorBlue, 0)); painter.drawEllipse(QRectF(ballPoint.x(), ballPoint.y(), 2.2f, 2.2f)); painter.setBrush(colorBlue); painter.setPen(QPen(colorBlue, 3)); } painter.drawArc(4.0f, 4.0f, 26.0f, 26.0f, startAngle, spanAngle); } // Custom knobs (L and R) else if (fCustomPaint == CUSTOM_PAINT_CARLA_L || fCustomPaint == CUSTOM_PAINT_CARLA_R) { // knob color QColor color(0xAD + fHoverStep*5, 0xD5 + fHoverStep*4, 0x4B + fHoverStep*5); // draw small circle QRectF ballRect(7.0f, 8.0f, 11.0f, 12.0f); QPainterPath ballPath; ballPath.addEllipse(ballRect); //painter.drawRect(ballRect); float tmpValue = (0.375f + 0.75f*value); float ballValue = tmpValue - std::floor(tmpValue); QPointF ballPoint(ballPath.pointAtPercent(ballValue)); painter.setBrush(color); painter.setPen(QPen(color, 0)); painter.drawEllipse(QRectF(ballPoint.x(), ballPoint.y(), 2.0f, 2.0f)); int startAngle, spanAngle; // draw arc if (fCustomPaint == CUSTOM_PAINT_CARLA_L) { startAngle = 216*16; spanAngle = -252.0*16*value; } else if (fCustomPaint == CUSTOM_PAINT_CARLA_R) { startAngle = 324.0*16; spanAngle = 252.0*16*(1.0-value); } else return; painter.setPen(QPen(color, 2)); painter.drawArc(3.5f, 4.5f, 22.0f, 22.0f, startAngle, spanAngle); if (HOVER_MIN < fHoverStep && fHoverStep < HOVER_MAX) { fHoverStep += fHovered ? 1 : -1; QTimer::singleShot(20, this, SLOT(update())); } } if (HOVER_MIN < fHoverStep && fHoverStep < HOVER_MAX) { fHoverStep += fHovered ? 1 : -1; QTimer::singleShot(20, this, SLOT(update())); } } else { QRectF target(0.0f, 0.0f, fSize, fSize); painter.drawPixmap(target, fPixmap, target); } painter.restore(); } void PixmapDial::resizeEvent(QResizeEvent* event) { updateSizes(); QDial::resizeEvent(event); }