add CircleIndicator
This commit is contained in:
174
libs/widgets/circleindicator.cpp
Normal file
174
libs/widgets/circleindicator.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
#include "circleindicator.h"
|
||||
|
||||
#include "qad_types.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QBoxLayout>
|
||||
#include <QLayout>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QStyleOption>
|
||||
#include <qmath.h>
|
||||
|
||||
template<typename T>
|
||||
inline T qClamp(T v, T min, T max) {
|
||||
return qMin<T>(max, qMax<T>(min, v));
|
||||
}
|
||||
|
||||
|
||||
CircleIndicator::CircleIndicator(QWidget * parent): QWidget(parent) {
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
CircleIndicator::~CircleIndicator() {}
|
||||
|
||||
|
||||
int CircleIndicator::heightForWidth(int) const {
|
||||
return width();
|
||||
}
|
||||
|
||||
|
||||
bool CircleIndicator::hasHeightForWidth() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void CircleIndicator::init() {
|
||||
connect(&anim, &QVariantAnimation::valueChanged, this, [this](QVariant v) {
|
||||
m_value_visual = v.toDouble();
|
||||
update();
|
||||
});
|
||||
anim.setDuration(200);
|
||||
anim.setEasingCurve(QEasingCurve::OutQuad);
|
||||
fill_color = QColor(255, 245, 60);
|
||||
back_color = QColor(216, 216, 216);
|
||||
border_color = Qt::darkGray;
|
||||
}
|
||||
|
||||
|
||||
QSize CircleIndicator::minimumSizeHint() const {
|
||||
return QSize(40, 40) * appScale();
|
||||
}
|
||||
|
||||
|
||||
QSize CircleIndicator::sizeHint() const {
|
||||
return QSize(120, 120) * appScale();
|
||||
}
|
||||
|
||||
|
||||
void CircleIndicator::paintEvent(QPaintEvent *) {
|
||||
QPainter p(this);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
float w = width(), h = height(), r = qMin<float>(w, h) / 2.f, thick = qMax<double>(1., r / 80.);
|
||||
r -= thick;
|
||||
float thin = qMax<double>(1., thick / 3.), lr = r * bar_ / 100.;
|
||||
p.translate(w / 2.f, h / 2.f);
|
||||
p.save();
|
||||
p.rotate(m_angle_offset + 90.);
|
||||
QRectF rct(-r, -r, r + r, r + r);
|
||||
double range = maximum() - minimum();
|
||||
double nv = qClamp<double>((m_value_visual - minimum()) / qMax(range, 1.E-3), 0., 1.) * 100.;
|
||||
QPainterPath path, path2;
|
||||
QPointF tp;
|
||||
path.arcMoveTo(rct, angle_gap);
|
||||
tp = path.currentPosition();
|
||||
path.arcTo(rct, angle_gap, 360 - angle_gap - angle_gap);
|
||||
rct.adjust(lr, lr, -lr, -lr);
|
||||
path2.arcMoveTo(rct, -angle_gap);
|
||||
path2.arcTo(rct, -angle_gap, -360 + angle_gap + angle_gap);
|
||||
path2.lineTo(tp);
|
||||
path.connectPath(path2);
|
||||
p.setPen(QPen(border_color, thick));
|
||||
QConicalGradient grad;
|
||||
double v = qClamp((1. - nv / (100. - thin / 3.6)) * ((360. - angle_gap - angle_gap) / 360.) + (angle_gap / 360.), 0., 1.);
|
||||
grad.setColorAt(1., fill_color);
|
||||
grad.setColorAt(qClamp(v + thin / 360., 0., 1.), fill_color);
|
||||
grad.setColorAt(v, back_color);
|
||||
grad.setColorAt(0., back_color);
|
||||
p.setBrush(grad);
|
||||
p.drawPath(path);
|
||||
|
||||
float hs = (r - lr) / 1.2;
|
||||
QRect ir(-hs, -hs, hs + hs, hs + hs);
|
||||
p.restore();
|
||||
if (m_text.isEmpty()) return;
|
||||
p.setPen(palette().text().color());
|
||||
auto tbr = p.boundingRect({}, m_text);
|
||||
if (tbr.isEmpty()) return;
|
||||
double tscl = qMin(ir.width() / tbr.width(), ir.height() / tbr.height());
|
||||
p.scale(tscl, tscl);
|
||||
p.drawText(ir, Qt::AlignCenter, m_text);
|
||||
}
|
||||
|
||||
|
||||
void CircleIndicator::animate() {
|
||||
anim.stop();
|
||||
anim.setStartValue(m_value_visual);
|
||||
anim.setEndValue(m_value);
|
||||
anim.start();
|
||||
}
|
||||
|
||||
|
||||
void CircleIndicator::setValue(double v) {
|
||||
if (m_value == v) return;
|
||||
m_value = qClamp(v, minimum(), maximum());
|
||||
animate();
|
||||
}
|
||||
|
||||
|
||||
void CircleIndicator::setMinimum(double ll) {
|
||||
m_minimum = ll;
|
||||
setValue(qClamp(value(), minimum(), maximum()));
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void CircleIndicator::setMaximum(double hl) {
|
||||
m_maximum = hl;
|
||||
setValue(qClamp(value(), minimum(), maximum()));
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void CircleIndicator::setFillColor(const QColor & c) {
|
||||
fill_color = c;
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void CircleIndicator::setBorderColor(const QColor & c) {
|
||||
border_color = c;
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void CircleIndicator::setText(const QString & t) {
|
||||
m_text = t;
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void CircleIndicator::setBackColor(const QColor & c) {
|
||||
back_color = c;
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void CircleIndicator::setAngleGap(double a) {
|
||||
angle_gap = qClamp<double>(a, 0., 180.);
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void CircleIndicator::setBarSize(double a) {
|
||||
bar_ = qClamp<double>(a, 0., 100.);
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void CircleIndicator::setAngleStartOffset(double a) {
|
||||
m_angle_offset = a;
|
||||
update();
|
||||
}
|
||||
80
libs/widgets/circleindicator.h
Normal file
80
libs/widgets/circleindicator.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#ifndef circleindicator_H
|
||||
#define circleindicator_H
|
||||
|
||||
#include "qad_widgets_export.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QTime>
|
||||
#include <QVariantAnimation>
|
||||
#include <QWidget>
|
||||
|
||||
|
||||
class QAD_WIDGETS_EXPORT CircleIndicator: public QWidget {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor)
|
||||
Q_PROPERTY(QColor backColor READ backColor WRITE setBackColor)
|
||||
Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor)
|
||||
Q_PROPERTY(QString text READ text WRITE setText)
|
||||
Q_PROPERTY(double angleStartOffset READ angleStartOffset WRITE setAngleStartOffset)
|
||||
Q_PROPERTY(double angleGap READ angleGap WRITE setAngleGap)
|
||||
Q_PROPERTY(double barSize READ barSize WRITE setBarSize)
|
||||
Q_PROPERTY(double value READ value WRITE setValue)
|
||||
Q_PROPERTY(double minimum READ minimum WRITE setMinimum)
|
||||
Q_PROPERTY(double maximum READ maximum WRITE setMaximum)
|
||||
|
||||
public:
|
||||
explicit CircleIndicator(QWidget * parent = 0);
|
||||
~CircleIndicator();
|
||||
|
||||
double value() const { return m_value; }
|
||||
double minimum() const { return m_minimum; }
|
||||
double maximum() const { return m_maximum; }
|
||||
|
||||
QColor backColor() const { return back_color; }
|
||||
void setBackColor(const QColor & c);
|
||||
|
||||
QColor fillColor() const { return fill_color; }
|
||||
void setFillColor(const QColor & c);
|
||||
|
||||
QColor borderColor() const { return border_color; }
|
||||
void setBorderColor(const QColor & c);
|
||||
|
||||
QString text() const { return m_text; }
|
||||
void setText(const QString & t);
|
||||
|
||||
double angleStartOffset() const { return m_angle_offset; }
|
||||
void setAngleStartOffset(double a);
|
||||
|
||||
double angleGap() const { return angle_gap; }
|
||||
void setAngleGap(double a);
|
||||
|
||||
double barSize() const { return bar_; }
|
||||
void setBarSize(double a);
|
||||
|
||||
int heightForWidth(int) const;
|
||||
bool hasHeightForWidth() const;
|
||||
|
||||
private:
|
||||
void init();
|
||||
QSize minimumSizeHint() const;
|
||||
QSize sizeHint() const;
|
||||
void paintEvent(QPaintEvent *);
|
||||
void animate();
|
||||
|
||||
QColor fill_color, back_color, border_color;
|
||||
QString m_text;
|
||||
QVariantAnimation anim;
|
||||
double m_value = 0., m_value_visual = 0., m_minimum = 0., m_maximum = 100.;
|
||||
double m_angle_offset = 0., angle_gap = 20., bar_ = 30.;
|
||||
|
||||
public slots:
|
||||
void enable() { setEnabled(true); }
|
||||
void disable() { setEnabled(false); }
|
||||
|
||||
void setValue(double v);
|
||||
void setMinimum(double m);
|
||||
void setMaximum(double m);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
69
libs/widgets/plugin/circleindicatorplugin.cpp
Normal file
69
libs/widgets/plugin/circleindicatorplugin.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "circleindicatorplugin.h"
|
||||
|
||||
#include "circleindicator.h"
|
||||
|
||||
#include <QtCore/QtPlugin>
|
||||
|
||||
|
||||
CircleIndicatorPlugin::CircleIndicatorPlugin(QObject * parent): QObject(parent) {
|
||||
m_initialized = false;
|
||||
}
|
||||
|
||||
|
||||
void CircleIndicatorPlugin::initialize(QDesignerFormEditorInterface * /* core */) {
|
||||
if (m_initialized) return;
|
||||
|
||||
// Add extension registrations, etc. here
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
|
||||
bool CircleIndicatorPlugin::isInitialized() const {
|
||||
return m_initialized;
|
||||
}
|
||||
|
||||
|
||||
QWidget * CircleIndicatorPlugin::createWidget(QWidget * parent) {
|
||||
return new CircleIndicator(parent);
|
||||
}
|
||||
|
||||
|
||||
QString CircleIndicatorPlugin::name() const {
|
||||
return QLatin1String("CircleIndicator");
|
||||
}
|
||||
|
||||
|
||||
QString CircleIndicatorPlugin::group() const {
|
||||
return QLatin1String("Display Widgets");
|
||||
}
|
||||
|
||||
|
||||
QIcon CircleIndicatorPlugin::icon() const {
|
||||
return QIcon(/*":/icons/clineedit.png"*/);
|
||||
}
|
||||
|
||||
|
||||
QString CircleIndicatorPlugin::toolTip() const {
|
||||
return QLatin1String("Circle indicator with text");
|
||||
}
|
||||
|
||||
|
||||
QString CircleIndicatorPlugin::whatsThis() const {
|
||||
return QLatin1String("Circle indicator with text");
|
||||
}
|
||||
|
||||
|
||||
bool CircleIndicatorPlugin::isContainer() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
QString CircleIndicatorPlugin::domXml() const {
|
||||
return QLatin1String("<widget class=\"CircleIndicator\" name=\"circleIndicator\">\n</widget>\n");
|
||||
}
|
||||
|
||||
|
||||
QString CircleIndicatorPlugin::includeFile() const {
|
||||
return QLatin1String("circleindicator.h");
|
||||
}
|
||||
36
libs/widgets/plugin/circleindicatorplugin.h
Normal file
36
libs/widgets/plugin/circleindicatorplugin.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef circleindicatorplugin_H
|
||||
#define circleindicatorplugin_H
|
||||
|
||||
#include <QObject>
|
||||
#if QT_VERSION >= 0x050000
|
||||
# include <QtUiPlugin/QDesignerCustomWidgetInterface>
|
||||
#else
|
||||
# include <QDesignerCustomWidgetInterface>
|
||||
#endif
|
||||
|
||||
class CircleIndicatorPlugin
|
||||
: public QObject
|
||||
, public QDesignerCustomWidgetInterface {
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QDesignerCustomWidgetInterface)
|
||||
|
||||
public:
|
||||
CircleIndicatorPlugin(QObject * parent = 0);
|
||||
|
||||
bool isContainer() const;
|
||||
bool isInitialized() const;
|
||||
QIcon icon() const;
|
||||
QString domXml() const;
|
||||
QString group() const;
|
||||
QString includeFile() const;
|
||||
QString name() const;
|
||||
QString toolTip() const;
|
||||
QString whatsThis() const;
|
||||
QWidget * createWidget(QWidget * parent);
|
||||
void initialize(QDesignerFormEditorInterface * core);
|
||||
|
||||
private:
|
||||
bool m_initialized;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "qad_widgets.h"
|
||||
|
||||
#include "circleindicatorplugin.h"
|
||||
#include "clineeditplugin.h"
|
||||
#include "colorbuttonplugin.h"
|
||||
#include "ecomboboxplugin.h"
|
||||
@@ -21,24 +22,28 @@
|
||||
|
||||
|
||||
QADWidgets::QADWidgets(QObject * parent): QObject(parent) {
|
||||
m_widgets.append(new SpinSliderPlugin(this));
|
||||
m_widgets.append(new ColorButtonPlugin(this));
|
||||
m_widgets.append(new ShortcutsPlugin(this));
|
||||
m_widgets.append(new CLineEditPlugin(this));
|
||||
m_widgets.append(new QIPEditPlugin(this));
|
||||
m_widgets.append(new QPointEditPlugin(this));
|
||||
m_widgets.append(new QRectEditPlugin(this));
|
||||
m_widgets.append(new EComboBoxPlugin(this));
|
||||
m_widgets.append(new QPIConsolePlugin(this));
|
||||
m_widgets.append(new IconedLabelPlugin(this));
|
||||
m_widgets.append(new QCodeEditPlugin(this));
|
||||
m_widgets.append(new QVariantEditPlugin(this));
|
||||
m_widgets.append(new QPIConfigPlugin(this));
|
||||
m_widgets.append(new EvalSpinBoxPlugin(this));
|
||||
m_widgets.append(new ImageViewPlugin(this));
|
||||
m_widgets.append(new ScrollSpinBoxPlugin(this));
|
||||
m_widgets.append(new RangeSliderPlugin(this));
|
||||
m_widgets.append(new StateIconPlugin(this));
|
||||
// clang-format off
|
||||
m_widgets
|
||||
<< new SpinSliderPlugin(this)
|
||||
<< new ColorButtonPlugin(this)
|
||||
<< new ShortcutsPlugin(this)
|
||||
<< new CLineEditPlugin(this)
|
||||
<< new QIPEditPlugin(this)
|
||||
<< new QPointEditPlugin(this)
|
||||
<< new QRectEditPlugin(this)
|
||||
<< new EComboBoxPlugin(this)
|
||||
<< new QPIConsolePlugin(this)
|
||||
<< new IconedLabelPlugin(this)
|
||||
<< new QCodeEditPlugin(this)
|
||||
<< new QVariantEditPlugin(this)
|
||||
<< new QPIConfigPlugin(this)
|
||||
<< new EvalSpinBoxPlugin(this)
|
||||
<< new ImageViewPlugin(this)
|
||||
<< new ScrollSpinBoxPlugin(this)
|
||||
<< new RangeSliderPlugin(this)
|
||||
<< new StateIconPlugin(this)
|
||||
<< new CircleIndicatorPlugin(this);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user