#include "timeLineItem.h" #include 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