PowerMaster/util/TimeLine/timeLineItem.cpp

481 lines
13 KiB
C++
Raw Normal View History

#include "timeLineItem.h"
#include <QPainter>
namespace TimeLine
{
class TimeLineItemPrivate
{
public:
TimeLineItemPrivate();
QRect m_rect;
QRect m_titleRect;
QColor m_lineColor;
TimeUnit m_curTimeUnit;
QDateTime m_curTime;
QDateTime m_leftTime; //当前时间左边第一个需要输出展示的时间点
int m_curTimePos; //当前时间所在的位置(x值),默认在中间(=0)
int m_leftTimePos;
DisplayState m_curState;
int m_scaleSize; //时间刻度大小,单位为像素
int m_scaleFactor; //缩放倍数
bool m_leftMouseIsDown; //鼠标左键是否按下
QPointF m_mouseDownPoint; //鼠标左键按下的坐标
QDateTime m_mouseDownTime; //鼠标左键是按下坐标对应的时间
};
TimeLineItemPrivate::TimeLineItemPrivate()
{
m_lineColor = Qt::white;
m_curTimeUnit = TU_Year;
m_curTime = QDateTime::currentDateTime();
m_leftTime = m_curTime;
m_curTimePos = 0;
m_leftTimePos = 0;
m_curState = RealTime;
m_scaleSize = 100;
m_scaleFactor = 1;
}
TimeLineItem::TimeLineItem() :
d_ptr(new TimeLine::TimeLineItemPrivate)
{
}
TimeLineItem::~TimeLineItem()
{
delete d_ptr;
}
QRectF TimeLineItem::boundingRect() const
{
//return QRectF(-d_ptr->m_rect.width() / 2, -d_ptr->m_rect.height() / 2, d_ptr->m_rect.width(), d_ptr->m_rect.height());
return d_ptr->m_rect;
}
void TimeLineItem::updateBoundingRect(const QRect& r)
{
d_ptr->m_rect = QRect(-r.width() / 2, -r.height() / 2, r.width(), r.height());
d_ptr->m_titleRect = QRect(-r.width() / 2, -r.height() / 2, r.width(), 35);
d_ptr->m_curTimePos = d_ptr->m_rect.right() - 80;
}
void TimeLineItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
Q_UNUSED(widget);
QRect rect = boundingRect().toRect();
QPen pen = painter->pen();
QBrush brush = painter->brush();
QFont font = painter->font();
QString strCurState = "";
//绘制title包含当前日期显示、状态显示不同状态对应不同颜色
if(d_ptr->m_curState == RealTime)
{
brush.setColor(QColor(39, 102, 59));
brush.setStyle(Qt::SolidPattern);
strCurState = QString::fromWCharArray(L"实时数据");
}
else
{
brush.setColor(QColor(46, 53, 63));
brush.setStyle(Qt::SolidPattern);
strCurState = QString::fromWCharArray(L"历史数据");
}
QRect titleRect = d_ptr->m_titleRect;
painter->setBrush(brush);
painter->drawRect(titleRect);
//tiltle中的当前日期
pen.setColor(d_ptr->m_lineColor);
font.setFamily(QString::fromWCharArray(L"微软雅黑"));
font.setPointSize(10);
font.setBold(true);
painter->setPen(pen);
painter->setFont(font);
QFontMetrics metrics(font);
QString strCurTime = d_ptr->m_curTime.toString("yyyy-MM-dd");
QRect textRect = metrics.boundingRect(strCurTime);
painter->drawText(titleRect.x() + 10, titleRect.y() + (titleRect.height() - textRect.height()) * 0.5 + textRect.height() - 5, strCurTime);
//tiltle中的当前状态
textRect = metrics.boundingRect(strCurState);
painter->drawText(titleRect.x() + (titleRect.width() - textRect.width()) * 0.5, titleRect.y() + (titleRect.height() - textRect.height()) * 0.5 + textRect.height() - 5, strCurState);
//刻度线
drawScaleLine(painter);
//当前时间
painter->drawLine(d_ptr->m_curTimePos, d_ptr->m_titleRect.bottom() + 2, d_ptr->m_curTimePos, boundingRect().bottom());
}
void TimeLineItem::drawScaleLine(QPainter* p)
{
QPen pen = p->pen();
pen.setWidth(2);
p->setPen(pen);
QRect rect = boundingRect().toRect();
d_ptr->m_leftTime = calculateLeftTime();
d_ptr->m_leftTimePos = calculateLeftTimePos();
int x_Left = d_ptr->m_leftTimePos;
int x_Right = x_Left + d_ptr->m_scaleSize;
while(1)
{
if(x_Left < -rect.width() / 2 - 50)
break;
p->drawLine(x_Left, d_ptr->m_titleRect.bottom(), x_Left, d_ptr->m_titleRect.bottom() - 5);
drawTimeText(p, x_Left);
x_Left -= d_ptr->m_scaleSize;
}
while(1)
{
if(x_Right > rect.width() / 2 + 50)
break;
p->drawLine(x_Right, d_ptr->m_titleRect.bottom(), x_Right, d_ptr->m_titleRect.bottom() - 5);
drawTimeText(p, x_Right);
x_Right += d_ptr->m_scaleSize;
}
}
void TimeLineItem::drawTimeText(QPainter* p, int x)
{
QDateTime time = calculateTime(x);
QString text = "";
QString text1 = "";
switch(d_ptr->m_curTimeUnit)
{
case TU_Year:
{
text = time.toString("yyyy");
break;
}
case TU_Month:
{
int month = time.date().month();
if (month == 1)
text1 = time.toString("yyyy");
text = time.toString("MM");
break;
}
case TU_Day:
{
int day = time.date().day();
if (day == 1)
text1 = time.toString("yyyy-MM");
text = time.toString("dd");
break;
}
case TU_Hour:
{
int hour = time.time().hour();
if (hour == 0)
text1 = time.toString("MM-dd");
text = time.toString("hh");
break;
}
case TU_Minute_30:
case TU_Minute_20:
case TU_Minute_15:
case TU_Minute_10:
case TU_Minute_5:
case TU_Minute_3:
case TU_Minute_1:
{
int minute = time.time().minute();
if (minute == 0)
text1 = time.toString("MM-dd");
text = time.toString("hh:mm");
break;
}
case TU_Second_30:
case TU_Second_10:
case TU_Second_1:
{
int second = time.time().second();
if(second == 0)
text1 = time.toString("MM-dd");
text = time.toString("hh:mm:ss");
break;
}
case TU_MSecond_500:
case TU_MSecond_100:
case TU_MSecond_50:
case TU_MSecond_10:
{
int msec = time.time().msec();
if(msec == 0)
text1 = time.toString("MM-dd");
text = time.toString("mm:ss:z");
break;
}
default:
break;
}
QFont font = p->font();
// font.setFamily(QString::fromWCharArray(L"微软雅黑"));
// font.setPointSize(10);
// font.setBold(true);
// p->setFont(font);
QFontMetrics metrics(font);
if(!text.isEmpty())
{
QRect textRect = metrics.boundingRect(text);
p->drawText(x - textRect.width() * 0.5, d_ptr->m_titleRect.bottom() + textRect.height(), text);
}
if(!text1.isEmpty())
{
QRect textRect = metrics.boundingRect(text1);
p->drawText(x - textRect.width() * 0.5, d_ptr->m_titleRect.bottom() + textRect.height() * 2, text1);
}
}
QDateTime TimeLineItem::calculateLeftTime()
{
QDateTime dateTime;
QString strDateTime = d_ptr->m_curTime.toString("yyyyMMddhhmmssz");
switch(d_ptr->m_curTimeUnit)
{
case TU_Year:
strDateTime = strDateTime.left(4) + "01010000000";
break;
case TU_Month:
strDateTime = strDateTime.left(6) + "010000000";
break;
case TU_Day:
strDateTime = strDateTime.left(8) + "0000000";
break;
case TU_Hour:
strDateTime = strDateTime.left(10) + "00000";
break;
case TU_Minute_30:
strDateTime = strDateTime.left(12) + "000";
break;
case TU_Minute_20:
strDateTime = strDateTime.left(12) + "000";
break;
case TU_Minute_15:
strDateTime = strDateTime.left(12) + "000";
break;
case TU_Minute_10:
strDateTime = strDateTime.left(12) + "000";
break;
case TU_Minute_5:
strDateTime = strDateTime.left(12) + "000";
break;
case TU_Minute_3:
strDateTime = strDateTime.left(12) + "000";
break;
case TU_Minute_1:
strDateTime = strDateTime.left(12) + "000";
break;
case TU_Second_30:
strDateTime = strDateTime.left(14) + "0";
break;
case TU_Second_10:
strDateTime = strDateTime.left(14) + "0";
break;
case TU_Second_1:
strDateTime = strDateTime.left(14) + "0";
break;
case TU_MSecond_500:
break;
case TU_MSecond_100:
break;
case TU_MSecond_50:
break;
case TU_MSecond_10:
break;
default:
break;
}
dateTime = QDateTime::fromString(strDateTime, "yyyyMMddhhmmssz");
return dateTime;
}
int TimeLineItem::calculateLeftTimePos()
{
qint64 timeRange = d_ptr->m_leftTime.msecsTo(d_ptr->m_curTime);
qint64 scaleRange = 0;
switch(d_ptr->m_curTimeUnit)
{
case TU_Year:
scaleRange = 365 * 24 * 60 * 60 * (qint64)1000;
break;
case TU_Month:
scaleRange = 30 * 24 * 60 * 60 * (qint64)1000;
break;
case TU_Day:
scaleRange = 24 * 60 * 60 * 1000;
break;
case TU_Hour:
scaleRange = 60 * 60 *1000;
break;
case TU_Minute_30:
scaleRange = 30 * 60 *1000;
break;
case TU_Minute_20:
scaleRange = 20 * 60 *1000;
break;
case TU_Minute_15:
scaleRange = 15 * 60 *1000;
break;
case TU_Minute_10:
scaleRange = 10 * 60 *1000;
break;
case TU_Minute_5:
scaleRange = 5 * 60 *1000;
break;
case TU_Minute_3:
scaleRange = 3 * 60 *1000;
break;
case TU_Minute_1:
scaleRange = 60 * 1000;
break;
case TU_Second_30:
scaleRange = 30 * 1000;
break;
case TU_Second_10:
scaleRange = 10 * 1000;
break;
case TU_Second_1:
scaleRange = 1 * 1000;
break;
case TU_MSecond_500:
scaleRange = 500;
break;
case TU_MSecond_100:
scaleRange = 100;
break;
case TU_MSecond_50:
scaleRange = 50;
break;
case TU_MSecond_10:
scaleRange = 10;
break;
default:
break;
}
//qDebug() << timeRange << ", " << scaleRange;
double dRatio = (double)timeRange / scaleRange;
return d_ptr->m_curTimePos + (-d_ptr->m_scaleSize * dRatio);
}
QDateTime TimeLineItem::calculateTime(int x)
{
if(x == d_ptr->m_curTimePos)
return d_ptr->m_curTime;
QDateTime dateTime;
double dUnit = (double)(x - d_ptr->m_leftTimePos) / (double)d_ptr->m_scaleSize;
switch(d_ptr->m_curTimeUnit)
{
case TU_Year:
dateTime = d_ptr->m_leftTime.addYears((int)dUnit);//先计算年份
dateTime = dateTime.addMSecs(dateTime.date().daysInYear() * 24 * 60 * 60 * 1000 * (dUnit - (int)dUnit)); //再计算时间
break;
case TU_Month:
dateTime = d_ptr->m_leftTime.addMonths((int)dUnit);//先计算月份
dateTime = dateTime.addMSecs(dateTime.date().daysInMonth() * 24 * 60 * 60 * 1000 * (dUnit - (int)dUnit)); //再计算时间
break;
case TU_Day:
dateTime = d_ptr->m_leftTime.addMSecs(24 * 60 * 60 * 1000 * dUnit);
break;
case TU_Hour:
dateTime = d_ptr->m_leftTime.addMSecs(60 * 60 * 1000 * dUnit);
break;
case TU_Minute_30:
dateTime = d_ptr->m_leftTime.addMSecs(30 * 60 * 1000 * dUnit);
break;
case TU_Minute_20:
dateTime = d_ptr->m_leftTime.addMSecs(20 * 60 * 1000 * dUnit);
break;
case TU_Minute_15:
dateTime = d_ptr->m_leftTime.addMSecs(15 * 60 * 1000 * dUnit);
break;
case TU_Minute_10:
dateTime = d_ptr->m_leftTime.addMSecs(10 * 60 * 1000 * dUnit);
break;
case TU_Minute_5:
dateTime = d_ptr->m_leftTime.addMSecs(5 * 60 * 1000 * dUnit);
break;
case TU_Minute_3:
dateTime = d_ptr->m_leftTime.addMSecs(3 * 60 * 1000 * dUnit);
break;
case TU_Minute_1:
dateTime = d_ptr->m_leftTime.addMSecs(60 * 1000 * dUnit);
break;
case TU_Second_30:
dateTime = d_ptr->m_leftTime.addMSecs(30 * 1000 * dUnit);
break;
case TU_Second_10:
dateTime = d_ptr->m_leftTime.addMSecs(10 * 1000 * dUnit);
break;
case TU_Second_1:
dateTime = d_ptr->m_leftTime.addMSecs(1000 * dUnit);
break;
case TU_MSecond_500:
dateTime = d_ptr->m_leftTime.addMSecs(500 * dUnit);
break;
case TU_MSecond_100:
dateTime = d_ptr->m_leftTime.addMSecs(100 * dUnit);
break;
case TU_MSecond_50:
dateTime = d_ptr->m_leftTime.addMSecs(50 * dUnit);
break;
case TU_MSecond_10:
dateTime = d_ptr->m_leftTime.addMSecs(10 * dUnit);
break;
default:
break;
}
return dateTime;
}
void TimeLineItem::setLineColor(QColor color)
{
d_ptr->m_lineColor = color;
}
void TimeLineItem::setScaleSize(int size)
{
d_ptr->m_scaleSize = size;
}
void TimeLineItem::setState(DisplayState state)
{
d_ptr->m_curState = state;
}
void TimeLineItem::setTime(QDateTime time)
{
if(time > QDateTime::currentDateTime())
return;
d_ptr->m_curTime = time;
}
void TimeLineItem::zoomIn()
{
d_ptr->m_scaleFactor++;
if(d_ptr->m_scaleFactor > (int)TU_MSecond_10)
d_ptr->m_scaleFactor = (int)TU_MSecond_10;
d_ptr->m_curTimeUnit = (TimeUnit)d_ptr->m_scaleFactor;
prepareGeometryChange();
//qDebug() << d_ptr->m_curTimeUnit;
}
void TimeLineItem::zoomOut()
{
d_ptr->m_scaleFactor--;
if(d_ptr->m_scaleFactor < 1)
d_ptr->m_scaleFactor = 1;
d_ptr->m_curTimeUnit = (TimeUnit)d_ptr->m_scaleFactor;
prepareGeometryChange();
//qDebug() << d_ptr->m_curTimeUnit;
}
} // namespace TimeLine