diff --git a/scene/PicDateItem.cpp b/scene/PicDateItem.cpp index 7bde8e3..3a3a5d4 100644 --- a/scene/PicDateItem.cpp +++ b/scene/PicDateItem.cpp @@ -1,9 +1,80 @@ #include "PicDateItem.h" #include #include +#include +#include #include "LogInfo.h" #include "ItemCommon.h" +// 生成可能的最长时间字符串供尺寸计算使用(基于像素宽度) +static QString generateMaxDateTimeString(const DateItemModel &model, const QFont &font) +{ + if (model.datetimePattern.isEmpty()) + return QString(); + + QString s = model.datetimePattern; + + QFontMetrics fm(font); + + auto longestFromList = [&fm] (const QStringList &lst, const QString &fallback) { + int bestW = -1; + QString best; + for (const auto &v : lst) { + int w = fm.horizontalAdvance(v); + if (w > bestW) { bestW = w; best = v; } + } + return best.isEmpty() ? fallback : best; + }; + + int i = s.indexOf("yyyy"); + if (i != -1) { + QString repl; + if (!model.yearsMap.isEmpty()) { + for (auto v : model.yearsMap.values()) if (v.length() > repl.length()) repl = v; + } else { + repl = QString::number(QDate::currentDate().year()); + } + s.replace(i, 4, repl); + } + + i = s.indexOf("YY"); + if (i != -1) { + // 以像素宽度为准,'88' 通常足够宽 + s.replace(i, 2, QString("88")); + } + + i = s.indexOf("MM"); + if (i != -1) { + s.replace(i, 2, longestFromList(model.monthsMap, QString("88"))); + } + + i = s.indexOf("dd"); + if (i != -1) { + s.replace(i, 2, longestFromList(model.daysMap, QString("88"))); + } + + i = s.indexOf("HH"); + if (i != -1) { + s.replace(i, 2, longestFromList(model.hoursMap, QString("88"))); + } + + QRegExp minutePattern("mm"); + if (s.contains(minutePattern)) s.replace(minutePattern, QString("88")); + + QRegExp secondPattern("ss"); + if (s.contains(secondPattern)) s.replace(secondPattern, QString("88")); + + i = s.indexOf("w"); + if (i != -1) { + s.replace(i, 1, longestFromList(model.weeksMap, QString("888"))); + } + + QRegExp weekNumberPattern("c"); + if (s.contains(weekNumberPattern)) s.replace(weekNumberPattern, QString("88")); + + return s; +} + PicDateItem::PicDateItem(QGraphicsItem *parent, QGraphicsScene *scene, const SourceType type) :PicTextItem(parent, scene, type) { @@ -33,6 +104,27 @@ void PicDateItem::setSource(QVariant var) void PicDateItem::setModel(DateItemModel model) { m_model = std::move(model); + + // 计时:测量生成最长字符串和字体度量两段耗时 + QElapsedTimer t1; + t1.start(); + m_maxDateTimeStr = generateMaxDateTimeString(m_model, font()); + qint64 genUs = t1.nsecsElapsed() / 1000; // microseconds + + QElapsedTimer t2; + t2.start(); + if (m_maxDateTimeStr.isEmpty()) { + m_maxSize = QSize(); + } else { + QFontMetrics fm(font()); + int w = fm.horizontalAdvance(m_maxDateTimeStr); + int h = fm.height(); + m_maxSize = QSize(w, h); + } + qint64 fmUs = t2.nsecsElapsed() / 1000; // microseconds + + qDebug() << "PicDateItem::setModel timing(us): generate=" << genUs << ", fm=" << fmUs << ", total=" << (genUs + fmUs); + setSource(m_model.datetimePattern); } @@ -84,6 +176,38 @@ QImage PicDateItem::itemImage() if(m_model.datetimePattern.isEmpty()) return QImage(); - auto ret = strToImage(m_currDateTimeStr); - return ret; + auto currImg = strToImage(m_currDateTimeStr); + + if (m_maxSize.isEmpty()) + return currImg; + + int width = qMax(currImg.width(), m_maxSize.width()); + int height = qMax(currImg.height(), m_maxSize.height()); + + QImage img(width, height, QImage::Format_ARGB32); + img.fill(QColor(0,0,0,0).rgba()); + + QPainter painter(&img); + int y = (height - currImg.height()) / 2; + painter.drawImage(0, y, currImg); + painter.end(); + + return img; +} + +QRectF PicDateItem::boundingRect() const +{ + // 优先使用已经应用变换后的 m_itemImage(与 PicTextItem 保持一致) + if (!m_itemImage.isNull()) { + return QRectF(0, 0, m_itemImage.width(), m_itemImage.height()); + } + + // 否则基于缓存的最大像素尺寸和粗体倍数估算 + int w = m_maxSize.width(); + int h = m_maxSize.height(); + if (w <= 0 || h <= 0) + return QGraphicsTextItem::boundingRect(); + + qreal bw = qreal(w) * qMax(1, m_boldMultiple); + return QRectF(0, 0, bw, qreal(h)); } \ No newline at end of file diff --git a/scene/PicDateItem.h b/scene/PicDateItem.h index 86f6e2d..32c01ae 100644 --- a/scene/PicDateItem.h +++ b/scene/PicDateItem.h @@ -35,6 +35,10 @@ private: DateItemModel m_model; QString m_currDateTimeStr; + QString m_maxDateTimeStr; + QSize m_maxSize; // 缓存最长字符串的像素宽高 + + virtual QRectF boundingRect() const override; }; #endif // PIC_DATE_ITEM_H