PowerMaster/util/TimeLine/timeLineItem.cpp

633 lines
18 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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_rightTime; //当前时间右边第一个需要输出展示的时间点
int m_curTimePos; //当前时间所在的位置(x值),默认在中间(=0)
int m_rightTimePos;
int m_scaleSize; //时间刻度大小,单位为像素
int m_scaleFactor; //缩放倍数
bool m_leftMouseIsDown; //鼠标左键是否按下
QPointF m_mouseDownPoint; //鼠标左键按下的坐标
QDateTime m_mouseDownTime; //鼠标左键是按下坐标对应的时间
DateTimeWidgetState m_curState;
};
TimeLineItemPrivate::TimeLineItemPrivate()
{
m_lineColor = Qt::white;
m_curTimeUnit = TU_Minute_1;
m_curTime = QDateTime::currentDateTime();/*QDateTime::fromString("2024-12-10 20:15:00", "yyyy-MM-dd hh:mm:ss");*/
m_rightTime = m_curTime;
m_curTimePos = 0;
m_rightTimePos = 0;
m_curState = realTime;
m_scaleSize = 100;
m_scaleFactor = (int)m_curTimeUnit;
}
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_rightTime = calculateRightTime();
d_ptr->m_rightTimePos = calculateRightTimePos();
int x_Right = d_ptr->m_rightTimePos;
int x_Left = x_Right - d_ptr->m_scaleSize;
while(1)
{
if(x_Right > rect.width() / 2 + d_ptr->m_scaleSize * 2)
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;
}
while(1)
{
if(x_Left < -rect.width() / 2 - d_ptr->m_scaleSize * 2)
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;
}
}
void TimeLineItem::drawTimeText(QPainter* p, int x)
{
QDateTime time = getTime(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("MM/dd");
break;
}
case TU_Hour:
{
int hour = time.time().hour();
if (hour == 0)
text1 = time.toString("MM/dd");
text = time.toString("hh:mm");
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 hour = time.time().hour();
if (hour == 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 minute = time.time().minute();
// if(minute == 0)
// text1 = time.toString("MM-dd hh:mm");
text = time.toString("hh:mm:ss");
break;
}
case TU_MSecond_500:
case TU_MSecond_100:
case TU_MSecond_50:
case TU_MSecond_10:
{
// int minute = time.time().minute();
// if(minute == 0)
// text1 = time.toString("MM-dd hh:mm");
text = time.toString("hh:mm:ss.zzz");
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::calculateRightTime()
{
//必须保证时间点在整点时刻上例如20mRange时刻点为20:00、20:20、20:40、21:003mRange时刻点为20:0020:03、20:06...20:57、21:00。
//所以时间区间一定可以被所在但愿整除比如不能出现7m的时间单元
QDateTime dateTime;
QString strDateTime = d_ptr->m_curTime.toString("yyyyMMddhhmmsszzz");;
switch(d_ptr->m_curTimeUnit)
{
case TU_Year:
{
strDateTime = d_ptr->m_curTime.addYears(1).toString("yyyyMMddhhmmsszzz");
strDateTime = strDateTime.left(4) + "0101000000000";
break;
}
case TU_Month:
{
strDateTime = d_ptr->m_curTime.addMonths(1).toString("yyyyMMddhhmmsszzz");
strDateTime = strDateTime.left(6) + "01000000000";
break;
}
case TU_Day:
{
strDateTime = d_ptr->m_curTime.addDays(1).toString("yyyyMMddhhmmsszzz");
strDateTime = strDateTime.left(8) + "000000000";
break;
}
case TU_Hour:
{
strDateTime = d_ptr->m_curTime.addSecs(60 * 60).toString("yyyyMMddhhmmsszzz");
strDateTime = strDateTime.left(10) + "0000000";
break;
}
case TU_Minute_30:
{
strDateTime = d_ptr->m_curTime.addSecs(30 * 60).toString("yyyyMMddhhmmsszzz");
strDateTime = strDateTime.left(10) + "0000000";
break;
}
case TU_Minute_20:
{
QString strBeginTime = strDateTime.left(10) + "0000000";
dateTime = QDateTime::fromString(strBeginTime, "yyyyMMddhhmmsszzz");
while(1)
{
dateTime = dateTime.addSecs(20 * 60);
if(dateTime >= d_ptr->m_curTime)
return dateTime;
}
break;
}
case TU_Minute_15:
{
QString strBeginTime = strDateTime.left(10) + "0000000";
dateTime = QDateTime::fromString(strBeginTime, "yyyyMMddhhmmsszzz");
while(1)
{
dateTime = dateTime.addSecs(15 * 60);
if(dateTime >= d_ptr->m_curTime)
return dateTime;
}
break;
break;
}
case TU_Minute_10:
{
QString strBeginTime = strDateTime.left(10) + "0000000";
dateTime = QDateTime::fromString(strBeginTime, "yyyyMMddhhmmsszzz");
while(1)
{
dateTime = dateTime.addSecs(10 * 60);
if(dateTime >= d_ptr->m_curTime)
return dateTime;
}
break;
}
case TU_Minute_5:
{
QString strBeginTime = strDateTime.left(10) + "0000000";
dateTime = QDateTime::fromString(strBeginTime, "yyyyMMddhhmmsszzz");
while(1)
{
dateTime = dateTime.addSecs(5 * 60);
if(dateTime >= d_ptr->m_curTime)
return dateTime;
}
break;
}
case TU_Minute_3:
{
QString strBeginTime = strDateTime.left(10) + "0000000";
dateTime = QDateTime::fromString(strBeginTime, "yyyyMMddhhmmsszzz");
while(1)
{
dateTime = dateTime.addSecs(3 * 60);
if(dateTime >= d_ptr->m_curTime)
return dateTime;
}
break;
}
case TU_Minute_1:
{
strDateTime = d_ptr->m_curTime.addSecs(1 * 60).toString("yyyyMMddhhmmsszzz");
strDateTime = strDateTime.left(12) + "00000";
break;
}
case TU_Second_30:
{
strDateTime = d_ptr->m_curTime.addSecs(30).toString("yyyyMMddhhmmsszzz");
strDateTime = strDateTime.left(12) + "00000";
break;
}
case TU_Second_10:
{
QString strBeginTime = strDateTime.left(12) + "00000";
dateTime = QDateTime::fromString(strBeginTime, "yyyyMMddhhmmsszzz");
while(1)
{
dateTime = dateTime.addSecs(10);
if(dateTime >= d_ptr->m_curTime)
return dateTime;
}
break;
}
case TU_Second_1:
{
strDateTime = d_ptr->m_curTime.addSecs(1).toString("yyyyMMddhhmmsszzz");
strDateTime = strDateTime.left(14) + "000";
break;
}
case TU_MSecond_500:
{
strDateTime = d_ptr->m_curTime.addMSecs(500).toString("yyyyMMddhhmmsszzz");
strDateTime = strDateTime.left(14) + "000";
break;
}
case TU_MSecond_100:
{
strDateTime = d_ptr->m_curTime.addMSecs(100).toString("yyyyMMddhhmmsszzz");
strDateTime = strDateTime.left(15) + "00";
break;
}
case TU_MSecond_50:
{
strDateTime = d_ptr->m_curTime.addMSecs(50).toString("yyyyMMddhhmmsszzz");
strDateTime = strDateTime.left(15) + "00";
break;
}
case TU_MSecond_10:
{
strDateTime = d_ptr->m_curTime.addMSecs(10).toString("yyyyMMddhhmmsszzz");
strDateTime = strDateTime.left(16) + "0";
break;
}
default:
break;
}
dateTime = QDateTime::fromString(strDateTime, "yyyyMMddhhmmsszzz");
return dateTime;
}
int TimeLineItem::calculateRightTimePos()
{
qint64 timeRange = d_ptr->m_rightTime.msecsTo(d_ptr->m_curTime); //右时刻晚于当前时刻,返回负值
timeRange = -timeRange;
qint64 scaleRange = 0;
switch(d_ptr->m_curTimeUnit)
{
case TU_Year:
scaleRange = d_ptr->m_curTime.date().daysInYear() * 24 * 60 * 60 * (qint64)1000;
break;
case TU_Month:
scaleRange = d_ptr->m_curTime.date().daysInMonth() * 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 / (double)scaleRange;
//qDebug() << "leftTime:" << d_ptr->m_rightTime.toString("yyyy/MM/dd hh:mm:ss");
return d_ptr->m_curTimePos + (d_ptr->m_scaleSize * dRatio);
}
QDateTime TimeLineItem::calculateTime(double dUnit)
{
QDateTime dateTime;
switch(d_ptr->m_curTimeUnit)
{
case TU_Year:
{
dateTime = d_ptr->m_rightTime.addYears((int)dUnit);//先计算年份
dateTime = dateTime.addMSecs(dateTime.date().daysInYear() * 24 * 60 * 60 * (qint64)1000 * (dUnit - (int)dUnit)); //再计算时间
break;
}
case TU_Month:
{
dateTime = d_ptr->m_rightTime.addMonths((int)dUnit);//先计算月份
dateTime = dateTime.addMSecs(dateTime.date().daysInMonth() * 24 * 60 * 60 * (qint64)1000 * (dUnit - (int)dUnit)); //再计算时间
break;
}
case TU_Day:
dateTime = d_ptr->m_rightTime.addMSecs(24 * 60 * 60 * 1000 * dUnit);
break;
case TU_Hour:
dateTime = d_ptr->m_rightTime.addMSecs(60 * 60 * 1000 * dUnit);
break;
case TU_Minute_30:
dateTime = d_ptr->m_rightTime.addMSecs(30 * 60 * 1000 * dUnit);
break;
case TU_Minute_20:
dateTime = d_ptr->m_rightTime.addMSecs(20 * 60 * 1000 * dUnit);
break;
case TU_Minute_15:
dateTime = d_ptr->m_rightTime.addMSecs(15 * 60 * 1000 * dUnit);
break;
case TU_Minute_10:
dateTime = d_ptr->m_rightTime.addMSecs(10 * 60 * 1000 * dUnit);
break;
case TU_Minute_5:
dateTime = d_ptr->m_rightTime.addMSecs(5 * 60 * 1000 * dUnit);
break;
case TU_Minute_3:
dateTime = d_ptr->m_rightTime.addMSecs(3 * 60 * 1000 * dUnit);
break;
case TU_Minute_1:
dateTime = d_ptr->m_rightTime.addMSecs(60 * 1000 * dUnit);
break;
case TU_Second_30:
dateTime = d_ptr->m_rightTime.addMSecs(30 * 1000 * dUnit);
break;
case TU_Second_10:
dateTime = d_ptr->m_rightTime.addMSecs(10 * 1000 * dUnit);
break;
case TU_Second_1:
dateTime = d_ptr->m_rightTime.addMSecs(1000 * dUnit);
break;
case TU_MSecond_500:
dateTime = d_ptr->m_rightTime.addMSecs(500 * dUnit);
break;
case TU_MSecond_100:
dateTime = d_ptr->m_rightTime.addMSecs(100 * dUnit);
break;
case TU_MSecond_50:
dateTime = d_ptr->m_rightTime.addMSecs(50 * dUnit);
break;
case TU_MSecond_10:
dateTime = d_ptr->m_rightTime.addMSecs(10 * dUnit);
break;
default:
break;
}
return dateTime;
}
QDateTime TimeLineItem::getTime(int x)
{
double dUnit = (double)(x - d_ptr->m_rightTimePos) / (double)d_ptr->m_scaleSize;
return calculateTime(dUnit);
}
qint64 TimeLineItem::getOffsetTimeValue(int x)
{
double dUnit = (double)(x) / (double)d_ptr->m_scaleSize;
//在极小的时间刻度下做一定的倍数放大,从而让拖拽更平滑
switch(d_ptr->m_curTimeUnit)
{
case TU_MSecond_100:
dUnit = dUnit * 2;
break;
case TU_MSecond_50:
dUnit = dUnit * 5;
break;
case TU_MSecond_10:
{
if(dUnit < 0)
dUnit = -0.1;
else if(dUnit > 0)
dUnit = 0.1;
//dUnit = dUnit * 10;
}
break;
default:
break;
}
QDateTime dateTime = calculateTime(dUnit);
//qDebug() << dUnit << " " << dateTime.toString("hh:mm:ss.zzz");
qint64 value = d_ptr->m_rightTime.msecsTo(dateTime);
return value;
}
void TimeLineItem::setLineColor(QColor color)
{
d_ptr->m_lineColor = color;
}
void TimeLineItem::setScaleSize(int size)
{
d_ptr->m_scaleSize = size;
}
void TimeLineItem::setState(DateTimeWidgetState state)
{
d_ptr->m_curState = state;
}
void TimeLineItem::setTime(const QDateTime& time)
{
if(time > QDateTime::currentDateTime())
return;
//qDebug() << "currTime:" << time.toString("hh:mm:ss.zzz");
d_ptr->m_curTime = time;
prepareGeometryChange();
}
QDateTime TimeLineItem::time()
{
return d_ptr->m_curTime;
}
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;
}
void TimeLineItem::setTimeUnit(TimeUnit unit)
{
d_ptr->m_curTimeUnit = unit;
}
TimeUnit TimeLineItem::timeUnit()
{
return d_ptr->m_curTimeUnit;
}
} // namespace TimeLine