Merge in circular progress

This commit is contained in:
johanneshilden 2017-09-29 16:43:09 +03:00
commit 9f049a8f19
11 changed files with 695 additions and 5 deletions

View File

@ -18,7 +18,9 @@ SOURCES = \
lib/qtmaterialstatetransition.cpp \
qtmaterialiconbutton.cpp \
qtmaterialprogress_internal.cpp \
qtmaterialprogress.cpp
qtmaterialprogress.cpp \
qtmaterialcircularprogress_internal.cpp \
qtmaterialcircularprogress.cpp
HEADERS = \
qtmaterialavatar_p.h \
qtmaterialavatar.h \
@ -49,6 +51,9 @@ HEADERS = \
qtmaterialiconbutton.h \
qtmaterialprogress_internal.h \
qtmaterialprogress_p.h \
qtmaterialprogress.h
qtmaterialprogress.h \
qtmaterialcircularprogress_internal.h \
qtmaterialcircularprogress_p.h \
qtmaterialcircularprogress.h
RESOURCES += \
resources.qrc

View File

@ -0,0 +1,254 @@
#include "qtmaterialcircularprogress.h"
#include "qtmaterialcircularprogress_p.h"
#include <QPropertyAnimation>
#include <QParallelAnimationGroup>
#include <QPainter>
#include "qtmaterialcircularprogress_internal.h"
#include "lib/qtmaterialstyle.h"
/*!
* \class QtMaterialCircularProgressPrivate
* \internal
*/
QtMaterialCircularProgressPrivate::QtMaterialCircularProgressPrivate(QtMaterialCircularProgress *q)
: q_ptr(q)
{
}
QtMaterialCircularProgressPrivate::~QtMaterialCircularProgressPrivate()
{
}
void QtMaterialCircularProgressPrivate::init()
{
Q_Q(QtMaterialCircularProgress);
delegate = new QtMaterialCircularProgressDelegate(q);
progressType = Material::IndeterminateProgress;
penWidth = 6.25;
size = 64;
useThemeColors = true;
q->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding,
QSizePolicy::MinimumExpanding));
QParallelAnimationGroup *group = new QParallelAnimationGroup(q);
group->setLoopCount(-1);
QPropertyAnimation *animation;
animation = new QPropertyAnimation(q);
animation->setPropertyName("dashLength");
animation->setTargetObject(delegate);
animation->setEasingCurve(QEasingCurve::InOutQuad);
animation->setStartValue(0.1);
animation->setKeyValueAt(0.15, 0.2);
animation->setKeyValueAt(0.6, 20);
animation->setKeyValueAt(0.7, 20);
animation->setEndValue(20);
animation->setDuration(2050);
group->addAnimation(animation);
animation = new QPropertyAnimation(q);
animation->setPropertyName("dashOffset");
animation->setTargetObject(delegate);
animation->setEasingCurve(QEasingCurve::InOutSine);
animation->setStartValue(0);
animation->setKeyValueAt(0.15, 0);
animation->setKeyValueAt(0.6, -7);
animation->setKeyValueAt(0.7, -7);
animation->setEndValue(-25);
animation->setDuration(2050);
group->addAnimation(animation);
animation = new QPropertyAnimation(q);
animation->setPropertyName("angle");
animation->setTargetObject(delegate);
animation->setStartValue(0);
animation->setEndValue(719);
animation->setDuration(2050);
group->addAnimation(animation);
group->start();
}
/*!
* \class QtMaterialCircularProgress
*/
QtMaterialCircularProgress::QtMaterialCircularProgress(QWidget *parent)
: QProgressBar(parent),
d_ptr(new QtMaterialCircularProgressPrivate(this))
{
d_func()->init();
}
QtMaterialCircularProgress::~QtMaterialCircularProgress()
{
}
void QtMaterialCircularProgress::setProgressType(Material::ProgressType type)
{
Q_D(QtMaterialCircularProgress);
d->progressType = type;
update();
}
Material::ProgressType QtMaterialCircularProgress::progressType() const
{
Q_D(const QtMaterialCircularProgress);
return d->progressType;
}
void QtMaterialCircularProgress::setUseThemeColors(bool value)
{
Q_D(QtMaterialCircularProgress);
if (d->useThemeColors == value) {
return;
}
d->useThemeColors = value;
update();
}
bool QtMaterialCircularProgress::useThemeColors() const
{
Q_D(const QtMaterialCircularProgress);
return d->useThemeColors;
}
void QtMaterialCircularProgress::setLineWidth(qreal width)
{
Q_D(QtMaterialCircularProgress);
d->penWidth = width;
update();
updateGeometry();
}
qreal QtMaterialCircularProgress::lineWidth() const
{
Q_D(const QtMaterialCircularProgress);
return d->penWidth;
}
void QtMaterialCircularProgress::setSize(int size)
{
Q_D(QtMaterialCircularProgress);
d->size = size;
update();
updateGeometry();
}
int QtMaterialCircularProgress::size() const
{
Q_D(const QtMaterialCircularProgress);
return d->size;
}
void QtMaterialCircularProgress::setColor(const QColor &color)
{
Q_D(QtMaterialCircularProgress);
d->color = color;
MATERIAL_DISABLE_THEME_COLORS
update();
}
QColor QtMaterialCircularProgress::color() const
{
Q_D(const QtMaterialCircularProgress);
if (d->useThemeColors || !d->color.isValid()) {
return QtMaterialStyle::instance().themeColor("primary1");
} else {
return d->color;
}
}
/*!
* \reimp
*/
QSize QtMaterialCircularProgress::sizeHint() const
{
Q_D(const QtMaterialCircularProgress);
const qreal s = d->size+d->penWidth+8;
return QSize(s, s);
}
/*!
* \reimp
*/
void QtMaterialCircularProgress::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
Q_D(QtMaterialCircularProgress);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
if (!isEnabled())
{
QPen pen;
pen.setCapStyle(Qt::RoundCap);
pen.setWidthF(d->penWidth);
pen.setColor(QtMaterialStyle::instance().themeColor("border"));
painter.setPen(pen);
painter.drawLine(rect().center()-QPointF(20, 20), rect().center()+QPointF(20, 20));
painter.drawLine(rect().center()+QPointF(20, -20), rect().center()-QPointF(20, -20));
return;
}
if (Material::IndeterminateProgress == d->progressType)
{
painter.translate(width()/2, height()/2);
painter.rotate(d->delegate->angle());
}
QPen pen;
pen.setCapStyle(Qt::RoundCap);
pen.setWidthF(d->penWidth);
pen.setColor(color());
if (Material::IndeterminateProgress == d->progressType)
{
QVector<qreal> pattern;
pattern << d->delegate->dashLength()*d->size/50 << 30*d->size/50;
pen.setDashOffset(d->delegate->dashOffset()*d->size/50);
pen.setDashPattern(pattern);
painter.setPen(pen);
painter.drawEllipse(QPoint(0, 0), d->size/2, d->size/2);
}
else
{
painter.setPen(pen);
const qreal x = (width()-d->size)/2;
const qreal y = (height()-d->size)/2;
const qreal a = 360*(value()-minimum())/(maximum()-minimum());
QPainterPath path;
path.arcMoveTo(x, y, d->size, d->size, 0);
path.arcTo(x, y, d->size, d->size, 0, a);
painter.drawPath(path);
}
}

View File

@ -0,0 +1,48 @@
#ifndef QTMATERIALCIRCULARPROGRESS_H
#define QTMATERIALCIRCULARPROGRESS_H
#include <QtWidgets/QProgressBar>
#include "lib/qtmaterialtheme.h"
class QtMaterialCircularProgressPrivate;
class QtMaterialCircularProgress : public QProgressBar
{
Q_OBJECT
Q_PROPERTY(qreal lineWidth WRITE setLineWidth READ lineWidth)
Q_PROPERTY(qreal size WRITE setSize READ size)
Q_PROPERTY(QColor color WRITE setColor READ color)
public:
explicit QtMaterialCircularProgress(QWidget *parent = 0);
~QtMaterialCircularProgress();
void setProgressType(Material::ProgressType type);
Material::ProgressType progressType() const;
void setUseThemeColors(bool value);
bool useThemeColors() const;
void setLineWidth(qreal width);
qreal lineWidth() const;
void setSize(int size);
int size() const;
void setColor(const QColor &color);
QColor color() const;
QSize sizeHint() const Q_DECL_OVERRIDE;
protected:
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
const QScopedPointer<QtMaterialCircularProgressPrivate> d_ptr;
private:
Q_DISABLE_COPY(QtMaterialCircularProgress)
Q_DECLARE_PRIVATE(QtMaterialCircularProgress)
};
#endif // QTMATERIALCIRCULARPROGRESS_H

View File

@ -0,0 +1,20 @@
#include "qtmaterialcircularprogress_internal.h"
/*!
* \class QtMaterialCircularProgressDelegate
* \internal
*/
QtMaterialCircularProgressDelegate::QtMaterialCircularProgressDelegate(QtMaterialCircularProgress *parent)
: QObject(parent),
m_progress(parent),
m_dashOffset(0),
m_dashLength(89),
m_angle(0)
{
Q_ASSERT(parent);
}
QtMaterialCircularProgressDelegate::~QtMaterialCircularProgressDelegate()
{
}

View File

@ -0,0 +1,70 @@
#ifndef QTMATERIALCIRCULARPROGRESS_INTERNAL_H
#define QTMATERIALCIRCULARPROGRESS_INTERNAL_H
#include <QObject>
#include "qtmaterialcircularprogress.h"
class QtMaterialCircularProgressDelegate : public QObject
{
Q_OBJECT
Q_PROPERTY(qreal dashOffset WRITE setDashOffset READ dashOffset)
Q_PROPERTY(qreal dashLength WRITE setDashLength READ dashLength)
Q_PROPERTY(int angle WRITE setAngle READ angle)
public:
QtMaterialCircularProgressDelegate(QtMaterialCircularProgress *parent);
~QtMaterialCircularProgressDelegate();
inline void setDashOffset(qreal offset);
inline qreal dashOffset() const;
inline void setDashLength(qreal length);
inline qreal dashLength() const;
inline void setAngle(int angle);
inline int angle() const;
private:
Q_DISABLE_COPY(QtMaterialCircularProgressDelegate)
QtMaterialCircularProgress *const m_progress;
qreal m_dashOffset;
qreal m_dashLength;
int m_angle;
};
inline void QtMaterialCircularProgressDelegate::setDashOffset(qreal offset)
{
m_dashOffset = offset;
m_progress->update();
}
inline qreal QtMaterialCircularProgressDelegate::dashOffset() const
{
return m_dashOffset;
}
inline void QtMaterialCircularProgressDelegate::setDashLength(qreal length)
{
m_dashLength = length;
m_progress->update();
}
inline qreal QtMaterialCircularProgressDelegate::dashLength() const
{
return m_dashLength;
}
inline void QtMaterialCircularProgressDelegate::setAngle(int angle)
{
m_angle = angle;
m_progress->update();
}
inline int QtMaterialCircularProgressDelegate::angle() const
{
return m_angle;
}
#endif // QTMATERIALCIRCULARPROGRESS_INTERNAL_H

View File

@ -0,0 +1,30 @@
#ifndef QTMATERIALCIRCULARPROGRESS_P_H
#define QTMATERIALCIRCULARPROGRESS_P_H
#include <QtGlobal>
#include "lib/qtmaterialtheme.h"
class QtMaterialCircularProgress;
class QtMaterialCircularProgressDelegate;
class QtMaterialCircularProgressPrivate
{
Q_DISABLE_COPY(QtMaterialCircularProgressPrivate)
Q_DECLARE_PUBLIC(QtMaterialCircularProgress)
public:
QtMaterialCircularProgressPrivate(QtMaterialCircularProgress *q);
~QtMaterialCircularProgressPrivate();
void init();
QtMaterialCircularProgress *const q_ptr;
QtMaterialCircularProgressDelegate *delegate;
Material::ProgressType progressType;
QColor color;
qreal penWidth;
int size;
bool useThemeColors;
};
#endif // QTMATERIALCIRCULARPROGRESS_P_H

View File

@ -0,0 +1,102 @@
#include "circularprogresssettingseditor.h"
#include <QVBoxLayout>
#include <QColorDialog>
#include "qtmaterialcircularprogress.h"
CircularProgressSettingsEditor::CircularProgressSettingsEditor(QWidget *parent)
: QWidget(parent),
ui(new Ui::CircularProgressSettingsForm),
m_progress(new QtMaterialCircularProgress)
{
QVBoxLayout *layout = new QVBoxLayout;
setLayout(layout);
QWidget *widget = new QWidget;
layout->addWidget(widget);
QWidget *canvas = new QWidget;
canvas->setStyleSheet("QWidget { background: white; }");
layout->addWidget(canvas);
ui->setupUi(widget);
layout->setContentsMargins(20, 20, 20, 20);
layout = new QVBoxLayout;
canvas->setLayout(layout);
layout->addWidget(m_progress);
layout->setAlignment(m_progress, Qt::AlignCenter);
setupForm();
connect(ui->disabledCheckBox, SIGNAL(toggled(bool)), this, SLOT(updateWidget()));
connect(ui->progressTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateWidget()));
connect(ui->progressSlider, SIGNAL(valueChanged(int)), this, SLOT(updateWidget()));
connect(ui->lineWidthDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(updateWidget()));
connect(ui->sizeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateWidget()));
connect(ui->useThemeColorsCheckBox, SIGNAL(toggled(bool)), this, SLOT(updateWidget()));
connect(ui->colorToolButton, SIGNAL(pressed()), this, SLOT(selectColor()));
ui->sizeSpinBox->setRange(10, 200);
ui->progressSlider->setRange(0, 100);
}
CircularProgressSettingsEditor::~CircularProgressSettingsEditor()
{
delete ui;
}
void CircularProgressSettingsEditor::setupForm()
{
switch (m_progress->progressType())
{
case Material::DeterminateProgress:
ui->progressTypeComboBox->setCurrentIndex(0);
break;
case Material::IndeterminateProgress:
ui->progressTypeComboBox->setCurrentIndex(1);
break;
default:
break;
}
ui->disabledCheckBox->setChecked(!m_progress->isEnabled());
ui->progressSlider->setValue(m_progress->value());
ui->lineWidthDoubleSpinBox->setValue(m_progress->lineWidth());
ui->sizeSpinBox->setValue(m_progress->size());
ui->useThemeColorsCheckBox->setChecked(m_progress->useThemeColors());
}
void CircularProgressSettingsEditor::updateWidget()
{
switch (ui->progressTypeComboBox->currentIndex())
{
case 0:
m_progress->setProgressType(Material::DeterminateProgress);
break;
case 1:
m_progress->setProgressType(Material::IndeterminateProgress);
break;
default:
break;
}
m_progress->setDisabled(ui->disabledCheckBox->isChecked());
m_progress->setValue(ui->progressSlider->value());
m_progress->setLineWidth(ui->lineWidthDoubleSpinBox->value());
m_progress->setSize(ui->sizeSpinBox->value());
m_progress->setUseThemeColors(ui->useThemeColorsCheckBox->isChecked());
}
void CircularProgressSettingsEditor::selectColor()
{
QColorDialog dialog;
if (dialog.exec()) {
QColor color = dialog.selectedColor();
QString senderName = sender()->objectName();
if ("colorToolButton" == senderName) {
m_progress->setColor(color);
ui->colorLineEdit->setText(color.name(QColor::HexRgb));
}
}
setupForm();
}

View File

@ -0,0 +1,27 @@
#ifndef CIRCULARPROGRESSSETTINGSEDITOR_H
#define CIRCULARPROGRESSSETTINGSEDITOR_H
#include <QWidget>
#include "ui_circularprogresssettingsform.h"
class QtMaterialCircularProgress;
class CircularProgressSettingsEditor : public QWidget
{
Q_OBJECT
public:
explicit CircularProgressSettingsEditor(QWidget *parent = 0);
~CircularProgressSettingsEditor();
protected slots:
void setupForm();
void updateWidget();
void selectColor();
private:
Ui::CircularProgressSettingsForm *const ui;
QtMaterialCircularProgress *const m_progress;
};
#endif // CIRCULARPROGRESSSETTINGSEDITOR_H

View File

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CircularProgressSettingsForm</class>
<widget class="QWidget" name="CircularProgressSettingsForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QWidget" name="formLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>221</width>
<height>197</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="disabledLabel">
<property name="text">
<string>Disabled</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="disabledCheckBox"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="progressTypeLabel">
<property name="text">
<string>Progress type</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="progressTypeComboBox">
<item>
<property name="text">
<string>Determinate</string>
</property>
</item>
<item>
<property name="text">
<string>Indeterminate</string>
</property>
</item>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lineWidthLabel">
<property name="text">
<string>Line width</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="lineWidthDoubleSpinBox"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="sizeLabel">
<property name="text">
<string>Size</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="sizeSpinBox"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="useThemeColorsLabel">
<property name="text">
<string>Use theme colors</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="useThemeColorsCheckBox"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="colorLabel">
<property name="text">
<string>Color</string>
</property>
</widget>
</item>
<item row="6" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="colorLineEdit"/>
</item>
<item>
<widget class="QToolButton" name="colorToolButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="progressLabel">
<property name="text">
<string>Progress</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSlider" name="progressSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -9,7 +9,8 @@ SOURCES = mainwindow.cpp \
raisedbuttonsettingseditor.cpp \
flatbuttonsettingseditor.cpp \
iconbuttonsettingseditor.cpp \
progresssettingseditor.cpp
progresssettingseditor.cpp \
circularprogresssettingseditor.cpp
HEADERS = mainwindow.h \
avatarsettingseditor.h \
badgesettingseditor.h \
@ -18,7 +19,8 @@ HEADERS = mainwindow.h \
raisedbuttonsettingseditor.h \
flatbuttonsettingseditor.h \
iconbuttonsettingseditor.h \
progresssettingseditor.h
progresssettingseditor.h \
circularprogresssettingseditor.h
LIBS += ../components/libcomponents.a
INCLUDEPATH += ../components/
TARGET = ../examples-exe
@ -33,4 +35,5 @@ FORMS += \
fabsettingsform.ui \
flatbuttonsettingsform.ui \
iconbuttonsettingsform.ui \
progresssettingsform.ui
progresssettingsform.ui \
circularprogresssettingsform.ui

View File

@ -10,6 +10,7 @@
#include "flatbuttonsettingseditor.h"
#include "iconbuttonsettingseditor.h"
#include "progresssettingseditor.h"
#include "circularprogresssettingseditor.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
@ -37,10 +38,12 @@ MainWindow::MainWindow(QWidget *parent)
FlatButtonSettingsEditor *flatButton = new FlatButtonSettingsEditor;
IconButtonSettingsEditor *iconButton = new IconButtonSettingsEditor;
ProgressSettingsEditor *progress = new ProgressSettingsEditor;
CircularProgressSettingsEditor *circularProgress = new CircularProgressSettingsEditor;
stack->addWidget(avatar);
stack->addWidget(badge);
stack->addWidget(checkbox);
stack->addWidget(circularProgress);
stack->addWidget(fab);
stack->addWidget(flatButton);
stack->addWidget(iconButton);
@ -50,6 +53,7 @@ MainWindow::MainWindow(QWidget *parent)
list->addItem("Avatar");
list->addItem("Badge");
list->addItem("Checkbox");
list->addItem("Circular Progress");
list->addItem("Floating Action Button");
list->addItem("Flat Button");
list->addItem("Icon Button");