481 lines
13 KiB
C++
481 lines
13 KiB
C++
#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
|