Commit 754ee1fe authored by Jasem Mutlaq's avatar Jasem Mutlaq

Initial work for Ekos summary screen

parent d5aad66a
......@@ -447,6 +447,7 @@ set(kstars_extra_SRCS
auxiliary/profileinfo.cpp
auxiliary/filedownloader.cpp
auxiliary/kspaths.cpp
auxiliary/QRoundProgressBar.cpp
time/simclock.cpp
time/kstarsdatetime.cpp
time/timezonerule.cpp
......
/*
* QRoundProgressBar - a circular progress bar Qt widget.
*
* Sintegrial Technologies (c) 2015-now
*
* The software is freeware and is distributed "as is" with the complete source codes.
* Anybody is free to use it in any software projects, either commercial or non-commercial.
* Please do not remove this copyright message and remain the name of the author unchanged.
*
* It is very appreciated if you produce some feedback to us case you are going to use
* the software.
*
* Please send your questions, suggestions, and information about found issues to the
*
* sintegrial@gmail.com
*
*/
#include "QRoundProgressBar.h"
#include <QtGui/QPainter>
QRoundProgressBar::QRoundProgressBar(QWidget *parent) :
QWidget(parent),
m_min(0), m_max(100),
m_value(25),
m_nullPosition(PositionTop),
m_barStyle(StyleDonut),
m_outlinePenWidth(1),
m_dataPenWidth(1),
m_rebuildBrush(false),
m_format("%p%"),
m_decimals(1),
m_updateFlags(UF_PERCENT)
{
}
void QRoundProgressBar::setRange(double min, double max)
{
m_min = min;
m_max = max;
if (m_max < m_min)
qSwap(m_max, m_min);
if (m_value < m_min)
m_value = m_min;
else if (m_value > m_max)
m_value = m_max;
if (!m_gradientData.isEmpty())
m_rebuildBrush = true;
update();
}
void QRoundProgressBar::setMinimum(double min)
{
setRange(min, m_max);
}
void QRoundProgressBar::setMaximum(double max)
{
setRange(m_min, max);
}
void QRoundProgressBar::setValue(double val)
{
if (m_value != val)
{
if (val < m_min)
m_value = m_min;
else if (val > m_max)
m_value = m_max;
else
m_value = val;
update();
}
}
void QRoundProgressBar::setValue(int val)
{
setValue(double(val));
}
void QRoundProgressBar::setNullPosition(double position)
{
if (position != m_nullPosition)
{
m_nullPosition = position;
if (!m_gradientData.isEmpty())
m_rebuildBrush = true;
update();
}
}
void QRoundProgressBar::setBarStyle(QRoundProgressBar::BarStyle style)
{
if (style != m_barStyle)
{
m_barStyle = style;
update();
}
}
void QRoundProgressBar::setOutlinePenWidth(double penWidth)
{
if (penWidth != m_outlinePenWidth)
{
m_outlinePenWidth = penWidth;
update();
}
}
void QRoundProgressBar::setDataPenWidth(double penWidth)
{
if (penWidth != m_dataPenWidth)
{
m_dataPenWidth = penWidth;
update();
}
}
void QRoundProgressBar::setDataColors(const QGradientStops &stopPoints)
{
if (stopPoints != m_gradientData)
{
m_gradientData = stopPoints;
m_rebuildBrush = true;
update();
}
}
void QRoundProgressBar::setFormat(const QString &format)
{
if (format != m_format)
{
m_format = format;
valueFormatChanged();
}
}
void QRoundProgressBar::resetFormat()
{
m_format = QString::null;
valueFormatChanged();
}
void QRoundProgressBar::setDecimals(int count)
{
if (count >= 0 && count != m_decimals)
{
m_decimals = count;
valueFormatChanged();
}
}
void QRoundProgressBar::paintEvent(QPaintEvent* /*event*/)
{
double outerRadius = qMin(width(), height());
QRectF baseRect(1, 1, outerRadius-2, outerRadius-2);
QImage buffer(outerRadius, outerRadius, QImage::Format_ARGB32_Premultiplied);
QPainter p(&buffer);
p.setRenderHint(QPainter::Antialiasing);
// data brush
rebuildDataBrushIfNeeded();
// background
drawBackground(p, buffer.rect());
// base circle
drawBase(p, baseRect);
// data circle
double arcStep = 360.0 / (m_max - m_min) * m_value;
drawValue(p, baseRect, m_value, arcStep);
// center circle
double innerRadius(0);
QRectF innerRect;
calculateInnerRect(baseRect, outerRadius, innerRect, innerRadius);
drawInnerBackground(p, innerRect);
// text
drawText(p, innerRect, innerRadius, m_value);
// finally draw the bar
p.end();
QPainter painter(this);
painter.fillRect(baseRect, palette().background());
painter.drawImage(0,0, buffer);
}
void QRoundProgressBar::drawBackground(QPainter &p, const QRectF &baseRect)
{
p.fillRect(baseRect, palette().background());
}
void QRoundProgressBar::drawBase(QPainter &p, const QRectF &baseRect)
{
switch (m_barStyle)
{
case StyleDonut:
p.setPen(QPen(palette().shadow().color(), m_outlinePenWidth));
p.setBrush(palette().base());
p.drawEllipse(baseRect);
break;
case StylePie:
p.setPen(QPen(palette().base().color(), m_outlinePenWidth));
p.setBrush(palette().base());
p.drawEllipse(baseRect);
break;
case StyleLine:
p.setPen(QPen(palette().base().color(), m_outlinePenWidth));
p.setBrush(Qt::NoBrush);
p.drawEllipse(baseRect.adjusted(m_outlinePenWidth/2, m_outlinePenWidth/2, -m_outlinePenWidth/2, -m_outlinePenWidth/2));
break;
default:;
}
}
void QRoundProgressBar::drawValue(QPainter &p, const QRectF &baseRect, double value, double arcLength)
{
// nothing to draw
if (value == m_min)
return;
// for Line style
if (m_barStyle == StyleLine)
{
p.setPen(QPen(palette().highlight().color(), m_dataPenWidth));
p.setBrush(Qt::NoBrush);
p.drawArc(baseRect.adjusted(m_outlinePenWidth/2, m_outlinePenWidth/2, -m_outlinePenWidth/2, -m_outlinePenWidth/2),
m_nullPosition * 16,
-arcLength * 16);
return;
}
// for Pie and Donut styles
QPainterPath dataPath;
dataPath.setFillRule(Qt::WindingFill);
// pie segment outer
dataPath.moveTo(baseRect.center());
dataPath.arcTo(baseRect, m_nullPosition, -arcLength);
dataPath.lineTo(baseRect.center());
p.setBrush(palette().highlight());
p.setPen(QPen(palette().shadow().color(), m_dataPenWidth));
p.drawPath(dataPath);
}
void QRoundProgressBar::calculateInnerRect(const QRectF &/*baseRect*/, double outerRadius, QRectF &innerRect, double &innerRadius)
{
// for Line style
if (m_barStyle == StyleLine)
{
innerRadius = outerRadius - m_outlinePenWidth;
}
else // for Pie and Donut styles
{
innerRadius = outerRadius * 0.75;
}
double delta = (outerRadius - innerRadius) / 2;
innerRect = QRectF(delta, delta, innerRadius, innerRadius);
}
void QRoundProgressBar::drawInnerBackground(QPainter &p, const QRectF &innerRect)
{
if (m_barStyle == StyleDonut)
{
p.setBrush(palette().alternateBase());
p.drawEllipse(innerRect);
}
}
void QRoundProgressBar::drawText(QPainter &p, const QRectF &innerRect, double innerRadius, double value)
{
if (m_format.isEmpty())
return;
// !!! to revise
QFont f(font());
f.setPixelSize(innerRadius * qMax(0.05, (0.35 - (double)m_decimals * 0.08)));
p.setFont(f);
QRectF textRect(innerRect);
p.setPen(palette().text().color());
p.drawText(textRect, Qt::AlignCenter, valueToText(value));
}
QString QRoundProgressBar::valueToText(double value) const
{
QString textToDraw(m_format);
if (m_updateFlags & UF_VALUE)
textToDraw.replace("%v", QString::number(value, 'f', m_decimals));
if (m_updateFlags & UF_PERCENT)
{
double procent = (value - m_min) / (m_max - m_min) * 100.0;
textToDraw.replace("%p", QString::number(procent, 'f', m_decimals));
}
if (m_updateFlags & UF_MAX)
textToDraw.replace("%m", QString::number(m_max - m_min + 1, 'f', m_decimals));
return textToDraw;
}
void QRoundProgressBar::valueFormatChanged()
{
m_updateFlags = 0;
if (m_format.contains("%v"))
m_updateFlags |= UF_VALUE;
if (m_format.contains("%p"))
m_updateFlags |= UF_PERCENT;
if (m_format.contains("%m"))
m_updateFlags |= UF_MAX;
update();
}
void QRoundProgressBar::rebuildDataBrushIfNeeded()
{
if (m_rebuildBrush)
{
m_rebuildBrush = false;
QConicalGradient dataBrush;
dataBrush.setCenter(0.5,0.5);
dataBrush.setCoordinateMode(QGradient::StretchToDeviceMode);
// invert colors
for (int i = 0; i < m_gradientData.count(); i++)
{
dataBrush.setColorAt(1.0 - m_gradientData.at(i).first, m_gradientData.at(i).second);
}
// angle
dataBrush.setAngle(m_nullPosition);
QPalette p(palette());
p.setBrush(QPalette::Highlight, dataBrush);
setPalette(p);
}
}
/*
* QRoundProgressBar - a circular progress bar Qt widget.
*
* Sintegrial Technologies (c) 2015-now
*
* The software is freeware and is distributed "as is" with the complete source codes.
* Anybody is free to use it in any software projects, either commercial or non-commercial.
* Please do not remove this copyright message and remain the name of the author unchanged.
*
* It is very appreciated if you produce some feedback to us case you are going to use
* the software.
*
* Please send your questions, suggestions, and information about found issues to the
*
* sintegrial@gmail.com
*
*/
#ifndef QROUNDPROGRESSBAR_H
#define QROUNDPROGRESSBAR_H
#include <QWidget>
/**
* @brief The QRoundProgressBar class represents a circular progress bar and maintains its API
* similar to the *QProgressBar*.
*
* ### Styles
* QRoundProgressBar currently supports Donut, Pie and Line styles. See setBarStyle() for more details.
*
* ### Colors
* Generally QRoundProgressBar uses its palette and font attributes to define how it will look.
*
* The following \a QPalette members are considered:
* - *QPalette::Window* background of the whole widget (normally should be set to Qt::NoBrush)
* - *QPalette::Base* background of the non-filled progress bar area (should be set to Qt::NoBrush to make it transparent)
* - *QPalette::AlternateBase* background of the central circle where the text is shown (for \a Donut style)
* - *QPalette::Shadow* foreground of the non-filled progress bar area (i.e. border color)
* - *QPalette::Highlight* background of the filled progress bar area
* - *QPalette::Text* color of the text shown in the center
*
* Create a \a QPalette with given attributes and apply it via `setPalette()`.
*
* ### Color gradient
* \a Donut and \a Pie styles allow to use color gradient for currernt value area instead of plain brush fill.
* See setDataColors() for more details.
*
* ### Value text
* Value text is generally drawn inside the QRoundProgressBar using its `font()` and \a QPalette::Text role from its `palette()`.
*
* To define pattern of the text, use setFormat() function (see Qt's \a QProgressBar for more details).
*
* To define number of decimals to be shown, use setDecimals() function.
*
* ### Font
* To use own font for value text, apply it via `setFont()`.
*
* By default, font size will be adjusted automatically to fit the inner circle of the widget.
*/
class QRoundProgressBar : public QWidget
{
Q_OBJECT
public:
explicit QRoundProgressBar(QWidget *parent = 0);
static const int PositionLeft = 180;
static const int PositionTop = 90;
static const int PositionRight = 0;
static const int PositionBottom = -90;
/**
* @brief Return position (in degrees) of minimum value.
* \sa setNullPosition
*/
double nullPosition() const { return m_nullPosition; }
/**
* @brief Defines position of minimum value.
* @param position position on the circle (in degrees) of minimum value
* \sa nullPosition
*/
void setNullPosition(double position);
/**
* @brief The BarStyle enum defines general look of the progress bar.
*/
enum BarStyle
{
/// Donut style (filled torus around the text)
StyleDonut,
/// Pie style (filled pie segment with the text in center)
StylePie,
/// Line style (thin round line around the text)
StyleLine
};
/**
* @brief Sets visual style of the widget.
* \sa barStyle
*/
void setBarStyle(BarStyle style);
/**
* @brief Returns current progree bar style.
* \sa setBarStyle
*/
BarStyle barStyle() const { return m_barStyle; }
/**
* @brief Sets width of the outline circle pen.
* @param penWidth width of the outline circle pen (in pixels)
*/
void setOutlinePenWidth(double penWidth);
/**
* @brief Returns width of the outline circle pen.
*/
double outlinePenWidth() const { return m_outlinePenWidth; }
/**
* @brief Sets width of the data circle pen.
* @param penWidth width of the data circle pen (in pixels)
*/
void setDataPenWidth(double penWidth);
/**
* @brief Returns width of the data circle pen.
*/
double dataPenWidth() const { return m_dataPenWidth; }
/**
* @brief Sets colors of the visible data and makes gradient brush from them.
* Gradient colors can be set for \a Donut and \a Pie styles (see setBarStyle() function).
*
* *Warning*: this function will override widget's `palette()` to set dynamically created gradient brush.
*
* @param stopPoints List of colors (should have at least 2 values, see Qt's \a QGradientStops for more details).
* Color value at point 0 corresponds to the minimum() value, while color value at point 1
* corresponds to the maximum(). Other colors will be distributed accordingly to the defined ranges (see setRange()).
*/
void setDataColors(const QGradientStops& stopPoints);
/**
* @brief Defines the string used to generate the current text.
* If no format is set, no text will be shown.
* @param format see \a QProgressBar's format description
* \sa setDecimals
*/
void setFormat(const QString& format);
/**
* @brief Sets format string to empty string. No text will be shown therefore.
* See setFormat() for more information.
*/
void resetFormat();
/**
* @brief Returns the string used to generate the current text.
*/
QString format() const { return m_format; }
/**
* @brief Sets number of decimals to show after the comma (default is 1).
* \sa setFormat
*/
void setDecimals(int count);
/**
* @brief Returns number of decimals to show after the comma (default is 1).
* \sa setFormat, setDecimals
*/
int decimals() const { return m_decimals; }
/**
* @brief Returns current value shown on the widget.
* \sa setValue()
*/
double value() const { return m_value; }
/**
* @brief Returns minimum of the allowed value range.
* \sa setMinimum, setRange
*/
double minimum() const { return m_min; }
/**
* @brief Returns maximum of the allowed value range.
* \sa setMaximum, setRange
*/
double maximum() const { return m_max; }
public Q_SLOTS:
/**
* @brief Defines minimum und maximum of the allowed value range.
* If the current value does not fit into the range, it will be automatically adjusted.
* @param min minimum of the allowed value range
* @param max maximum of the allowed value range
*/
void setRange(double min, double max);
/**
* @brief Defines minimum of the allowed value range.
* If the current value does not fit into the range, it will be automatically adjusted.
* @param min minimum of the allowed value range
* \sa setRange
*/
void setMinimum(double min);
/**
* @brief Defines maximum of the allowed value range.
* If the current value does not fit into the range, it will be automatically adjusted.
* @param max maximum of the allowed value range
* \sa setRange
*/
void setMaximum(double max);
/**
* @brief Sets a value which will be shown on the widget.
* @param val must be between minimum() and maximum()
*/
void setValue(double val);
/**
* @brief Integer version of the previous slot.
* @param val must be between minimum() and maximum()
*/
void setValue(int val);
protected:
virtual void paintEvent(QPaintEvent *event);
virtual void drawBackground(QPainter& p, const QRectF& baseRect);
virtual void drawBase(QPainter& p, const QRectF& baseRect);
virtual void drawValue(QPainter& p, const QRectF& baseRect, double value, double arcLength);
virtual void calculateInnerRect(const QRectF& baseRect, double outerRadius, QRectF& innerRect, double& innerRadius);
virtual void drawInnerBackground(QPainter& p, const QRectF& innerRect);
virtual void drawText(QPainter& p, const QRectF& innerRect, double innerRadius, double value);
virtual QString valueToText(double value) const;
virtual void valueFormatChanged();
virtual QSize minimumSizeHint() const { return QSize(32,32); }
virtual bool hasHeightForWidth() const { return true; }
virtual int heightForWidth(int w) const { return w; }
void rebuildDataBrushIfNeeded();
double m_min, m_max;
double m_value;
double m_nullPosition;
BarStyle m_barStyle;
double m_outlinePenWidth, m_dataPenWidth;
QGradientStops m_gradientData;
bool m_rebuildBrush;
QString m_format;
int m_decimals;
static const int UF_VALUE = 1;
static const int UF_PERCENT = 2;
static const int UF_MAX = 4;
int m_updateFlags;
};
#endif // QROUNDPROGRESSBAR_H
......@@ -27,6 +27,7 @@
#include "profileeditor.h"
#include "profileinfo.h"
#include "QProgressIndicator.h"