2026年5月23日暂存

This commit is contained in:
2026-05-23 14:16:57 +08:00
parent c8a5a121c9
commit 1cb9d5ac42
59 changed files with 15774 additions and 8662 deletions
+17 -3
View File
@@ -87,7 +87,16 @@ BarcodeEditor::~BarcodeEditor()
delete ui;
}
void BarcodeEditor::bindViewModel(const BarcodeViewModel& vm)
void BarcodeEditor::bindSysPara(SysPara *sysPara)
{
if (!sysPara) {
qWarning() << "BarcodeEditor::bindSysPara: null pointer passed, ignored";
return;
}
m_sysPara = sysPara;
}
void BarcodeEditor::bindViewModel(const BarcodeViewModel &vm)
{
m_vm = vm;
@@ -221,7 +230,7 @@ BarcodeViewModel BarcodeEditor::viewModel()
void BarcodeEditor::restoreViewModel()
{
m_vm.generalSettingsVM = ItemGeneralSettingsVM();
m_vm.generalSettingsVM = TextItemModel();
m_vm.contentPattern = "";
m_vm.counterViewModel = CounterViewModel();
m_vm.dateViewModel = DateItemModel::createDefaultReplaceModel();
@@ -238,7 +247,12 @@ void BarcodeEditor::applyCounterConfigToSysPara()
{
if(!m_vm.contentPattern.contains("{c}"))
return;
if (!m_sysPara) {
qWarning() << "BarcodeEditor::applyCounterConfigToSysPara: m_sysPara is null, skipping";
return;
}
CounterEditorVM cnt = m_counterEditor->viewModel();
if(cnt.counterType == COUNTER_TYPE_1) {
m_sysPara->para.cnt1StartValue = cnt.counter1.startValue;
+2 -2
View File
@@ -26,7 +26,7 @@ enum BarcodeType {
* 仅当 contentPattern 含有相应变量时,counterViewModel / dateViewModel 字段才有意义。
*/
struct BarcodeViewModel {
ItemGeneralSettingsVM generalSettingsVM; // 通用设置视图模型
TextItemModel generalSettingsVM; // 通用设置视图模型
QString contentPattern; // 条形码内容模版,例如 "ABC{t}{c1}"
CounterViewModel counterViewModel; // 计数器视图模型
DateItemModel dateViewModel; // 日期视图模型
@@ -104,7 +104,7 @@ public:
*
* @param sysPara
*/
void bindSysPara(SysPara* sysPara) { m_sysPara = sysPara; }
void bindSysPara(SysPara* sysPara);
/**
* @brief 注入条形码视图模型(纯结构体,按值拷贝)
+16 -16
View File
@@ -126,7 +126,7 @@ QSpinBox::down-arrow {
<widget class="QSpinBox" name="BarCodeScale">
<property name="geometry">
<rect>
<x>300</x>
<x>280</x>
<y>150</y>
<width>60</width>
<height>31</height>
@@ -173,9 +173,9 @@ QSpinBox::down-arrow {
<widget class="QComboBox" name="BarCodeDot">
<property name="geometry">
<rect>
<x>190</x>
<y>150</y>
<width>71</width>
<x>70</x>
<y>230</y>
<width>111</width>
<height>31</height>
</rect>
</property>
@@ -213,10 +213,10 @@ QSpinBox::down-arrow {
<widget class="QCheckBox" name="checkBoxAddText">
<property name="geometry">
<rect>
<x>330</x>
<y>240</y>
<width>83</width>
<height>16</height>
<x>280</x>
<y>230</y>
<width>150</width>
<height>31</height>
</rect>
</property>
<property name="sizePolicy">
@@ -240,7 +240,7 @@ QSpinBox::down-arrow {
<rect>
<x>70</x>
<y>150</y>
<width>71</width>
<width>111</width>
<height>31</height>
</rect>
</property>
@@ -248,9 +248,9 @@ QSpinBox::down-arrow {
<widget class="QComboBox" name="comboBoxInkColor">
<property name="geometry">
<rect>
<x>300</x>
<x>280</x>
<y>70</y>
<width>81</width>
<width>111</width>
<height>31</height>
</rect>
</property>
@@ -271,8 +271,8 @@ QSpinBox::down-arrow {
<widget class="QLabel" name="label_7">
<property name="geometry">
<rect>
<x>190</x>
<y>120</y>
<x>70</x>
<y>200</y>
<width>76</width>
<height>23</height>
</rect>
@@ -299,7 +299,7 @@ QSpinBox::down-arrow {
<rect>
<x>70</x>
<y>70</y>
<width>140</width>
<width>161</width>
<height>31</height>
</rect>
</property>
@@ -319,7 +319,7 @@ QSpinBox::down-arrow {
<widget class="QLabel" name="lab123">
<property name="geometry">
<rect>
<x>300</x>
<x>280</x>
<y>40</y>
<width>76</width>
<height>23</height>
@@ -335,7 +335,7 @@ QSpinBox::down-arrow {
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>300</x>
<x>280</x>
<y>120</y>
<width>129</width>
<height>23</height>
+39 -9
View File
@@ -6,6 +6,7 @@
#include "BarCode/barcode.h"
#include <QPainter>
#include <cstring>
#include <QDebug>
/**
* @brief 将libqrencode的QRcode结构渲染成QImage
@@ -308,10 +309,15 @@ static QImage generateBarCodeImage(const QString &content, int barCodeType)
return generateBarCodeImage(content, vm);
}
QString generateTxtFromDateItemModel(const DateItemModel &model, const QDateTime &time)
QString ItemUtils::generateTxtFromDateItemModel(const DateItemModel &model, const QDateTime &time)
{
QString result = model.datetimePattern;
if (!time.isValid()) {
qWarning() << "generateTxtFromDateItemModel: invalid QDateTime passed";
return result;
}
// 应用偏移量
QDateTime applyDateTime = time;
if(model.monthsOffset != 0) {
@@ -341,19 +347,37 @@ QString generateTxtFromDateItemModel(const DateItemModel &model, const QDateTime
// 匹配两位数月份 MM
i = result.indexOf("MM");
if(i != -1) {
result.replace(i, 2, model.monthsMap[applyDateTime.date().month() - 1]);
int monthIdx = applyDateTime.date().month() - 1;
if (monthIdx >= 0 && monthIdx < model.monthsMap.size()) {
result.replace(i, 2, model.monthsMap[monthIdx]);
} else {
qWarning() << "generateTxtFromDateItemModel: monthsMap index out of range:" << monthIdx;
result.replace(i, 2, QString::number(applyDateTime.date().month()).rightJustified(2, '0'));
}
}
// 匹配两位数日期 dd
i = result.indexOf("dd");
if(i != -1) {
result.replace(i, 2, model.daysMap[applyDateTime.date().day() - 1]);
int dayIdx = applyDateTime.date().day() - 1;
if (dayIdx >= 0 && dayIdx < model.daysMap.size()) {
result.replace(i, 2, model.daysMap[dayIdx]);
} else {
qWarning() << "generateTxtFromDateItemModel: daysMap index out of range:" << dayIdx;
result.replace(i, 2, QString::number(applyDateTime.date().day()).rightJustified(2, '0'));
}
}
// 匹配两位数小时 HH
i = result.indexOf("HH");
if(i != -1) {
result.replace(i, 2, model.hoursMap[applyDateTime.time().hour()]);
int hourIdx = applyDateTime.time().hour();
if (hourIdx >= 0 && hourIdx < model.hoursMap.size()) {
result.replace(i, 2, model.hoursMap[hourIdx]);
} else {
qWarning() << "generateTxtFromDateItemModel: hoursMap index out of range:" << hourIdx;
result.replace(i, 2, QString::number(applyDateTime.time().hour()).rightJustified(2, '0'));
}
}
// 匹配两位数分钟 mm
@@ -373,7 +397,13 @@ QString generateTxtFromDateItemModel(const DateItemModel &model, const QDateTime
// 格式化周几 w
i = result.indexOf("w");
if (i != -1) {
result.replace(i, 1, model.weeksMap[applyDateTime.date().dayOfWeek() - 1]);
int weekIdx = applyDateTime.date().dayOfWeek() - 1;
if (weekIdx >= 0 && weekIdx < model.weeksMap.size()) {
result.replace(i, 1, model.weeksMap[weekIdx]);
} else {
qWarning() << "generateTxtFromDateItemModel: weeksMap index out of range:" << weekIdx;
result.replace(i, 1, QString::number(applyDateTime.date().dayOfWeek()));
}
}
// 格式化年中周数 c
@@ -386,7 +416,7 @@ QString generateTxtFromDateItemModel(const DateItemModel &model, const QDateTime
}
QString generateTxtFromBarcodeViewModel(const BarcodeViewModel &vm, const std::array<int, 2> counterValues, const QDateTime &time)
QString ItemUtils::generateTxtFromBarcodeViewModel(const BarcodeViewModel &vm, const std::array<int, 2> counterValues, const QDateTime &time)
{
QString txt = vm.contentPattern;
auto pos = vm.contentPattern.indexOf("{t}");
@@ -424,7 +454,7 @@ QString generateTxtFromBarcodeViewModel(const BarcodeViewModel &vm, const std::a
* - BARCODE_TYPE_BARCODE: DlgBarcodeFormatVM(完整配置)或 int(条形码类型索引,使用默认值)
* @return QImage 生成的图像;失败返回空QImage
*/
QImage generateBarcodeImage(const QString &content, BarcodeType type, const QVariant &format)
QImage ItemUtils::generateBarcodeImage(const QString &content, BarcodeType type, const QVariant &format)
{
if (content.isEmpty()) {
return QImage();
@@ -516,7 +546,7 @@ end:
return img.copy(clipRect);
}
QImage txtToImage(const QString &txt, const QFont &font, const QColor &fgColor, const QColor &bgColor)
QImage ItemUtils::txtToImage(const QString &txt, const QFont &font, const QColor &fgColor, const QColor &bgColor)
{
if (txt.isEmpty()) {
return QImage();
+63 -60
View File
@@ -9,68 +9,71 @@
#include <array>
#include <QImage>
/**
* @brief 根据日期视图模型和时间生成字符串
* @param model 包含日期格式模版和相关配置的视图模型
* @param time 用于生成字符串的时间
* @return QString 生成的字符串
* @remark
* 该函数根据 model.datetimePattern 中的格式模版生成字符串,支持以下格式:
* - yyyy: 四位数年份,支持替换为自定义字符串(通过 model.yearsMap)
* - YY: 两位数年份
* - MM: 两位数月份,支持替换为自定义字符串(通过 model.monthsMap)
* - dd: 两位数日期,支持替换为自定义字符串(通过 model.daysMap)
* - HH: 两位数小时,支持替换为自定义字符串(通过 model.hoursMap)
* - mm: 两位数分钟
* - ss: 两位数秒钟
* - w: 星期几,支持替换为自定义字符串(通过 model.weeksMap)
* - c: 年中周数
*/
QString generateTxtFromDateItemModel(const DateItemModel& model, const QDateTime& time);
/**
* @brief 根据条形码视图模型的内容模版生成字符串,
* 生成的字符串可用于创建条形码或二维码
*
* @example
* input: "ABC_{c}_{t}"
* output: "ABC_1230_2026/04/30"
*
* @remark
* 函数根据vm中的 contentPattern 是否存在变量模版,如果存在计数器变量,则使用 counterViewModel 格式化,同理也处理时间变量。
*
* @param vm 包含格式化所需的内容模版及相关配置
* @param counterValues 所有计数器的当前值,counterValues[0] 为计数器1的当前值,counterValues[1]为计数器2的当前值......
* @param time 要用于格式化的时间,通常是当前时间
* @return QString 格式化后的字符串
*
*/
QString generateTxtFromBarcodeViewModel(const BarcodeViewModel& vm, const std::array<int, 2> counterValues, const QDateTime& time);
namespace ItemUtils
{
/**
* @brief 根据日期视图模型和时间生成字符串
* @param model 包含日期格式模版和相关配置的视图模型
* @param time 用于生成字符串的时间
* @return QString 生成的字符串
* @remark
* 该函数根据 model.datetimePattern 中的格式模版生成字符串,支持以下格式:
* - yyyy: 四位数年份,支持替换为自定义字符串(通过 model.yearsMap)
* - YY: 两位数年份
* - MM: 两位数月份,支持替换为自定义字符串(通过 model.monthsMap)
* - dd: 两位数日期,支持替换为自定义字符串(通过 model.daysMap)
* - HH: 两位数小时,支持替换为自定义字符串(通过 model.hoursMap)
* - mm: 两位数分钟
* - ss: 两位数秒钟
* - w: 星期几,支持替换为自定义字符串(通过 model.weeksMap)
* - c: 年中周数
*/
QString generateTxtFromDateItemModel(const DateItemModel& model, const QDateTime& time);
/**
* @brief 根据条形码类型和内容生成条形码或二维码图像
* @param content 已格式化的文本内容
* @param type 条码类型
* @param format 配置参数
* @return QImage 生成的图像;如果失败返回空图像
* @note
* format 参数类型:
* - BARCODE_TYPE_QRCODE: DlgQrcodeFormatVM 或 int
* - BARCODE_TYPE_BARCODE: DlgBarcodeFormatVM 或 int
* 如果 format 是 int 类型, 对于 QR Code,0 表示 Data Matrix,1 表示 QR Code;对于条形码,int 值对应 DlgBarcodeFormatVM 中 type 的索引。
* 如果 format 是 int 类型,则使用默认配置并根据 int 值选择二维码或条形码的子类型;如果 format 是对应的 VM 类型,则使用其中的详细配置。
*/
QImage generateBarcodeImage(const QString& content, BarcodeType type, const QVariant& format);
/**
* @brief 根据条形码视图模型的内容模版生成字符串,
* 生成的字符串可用于创建条形码或二维码
*
* @example
* input: "ABC_{c}_{t}"
* output: "ABC_1230_2026/04/30"
*
* @remark
* 函数根据vm中的 contentPattern 是否存在变量模版,如果存在计数器变量,则使用 counterViewModel 格式化,同理也处理时间变量。
*
* @param vm 包含格式化所需的内容模版及相关配置
* @param counterValues 所有计数器的当前值,counterValues[0] 为计数器1的当前值,counterValues[1]为计数器2的当前值......
* @param time 要用于格式化的时间,通常是当前时间
* @return QString 格式化后的字符串
*
*/
QString generateTxtFromBarcodeViewModel(const BarcodeViewModel& vm, const std::array<int, 2> counterValues, const QDateTime& time);
/**
* @brief 将文本转换为图像
* @param txt 要转换的文本
* @param font 文本使用的字体
* @param fgColor 文本颜色,默认为黑色
* @param bgColor 背景颜色,默认为白色
* @return QImage 转换后的图像
* @note 返回的字符串图像会裁剪至最小边界以节省空间。例如字符串"aaa"的高度会比"bbbjjj"小,因为前者没有上下行部分。
*/
QImage txtToImage(const QString& txt, const QFont& font, const QColor& fgColor = Qt::black, const QColor& bgColor = Qt::white);
/**
* @brief 根据条形码类型和内容生成条形码或二维码图像
* @param content 已格式化的文本内容
* @param type 条码类型
* @param format 配置参数
* @return QImage 生成的图像;如果失败返回空图像
* @note
* format 参数类型:
* - BARCODE_TYPE_QRCODE: DlgQrcodeFormatVM 或 int
* - BARCODE_TYPE_BARCODE: DlgBarcodeFormatVM 或 int
* 如果 format 是 int 类型, 对于 QR Code,0 表示 Data Matrix,1 表示 QR Code;对于条形码,int 值对应 DlgBarcodeFormatVM 中 type 的索引。
* 如果 format 是 int 类型,则使用默认配置并根据 int 值选择二维码或条形码的子类型;如果 format 是对应的 VM 类型,则使用其中的详细配置。
*/
QImage generateBarcodeImage(const QString& content, BarcodeType type, const QVariant& format);
/**
* @brief 将文本转换为图像
* @param txt 要转换的文本
* @param font 文本使用的字体
* @param fgColor 文本颜色,默认为黑色
* @param bgColor 背景颜色,默认为白色
* @return QImage 转换后的图像
* @note 返回的字符串图像会裁剪至最小边界以节省空间。例如字符串"aaa"的高度会比"bbbjjj"小,因为前者没有上下行部分。
*/
QImage txtToImage(const QString& txt, const QFont& font, const QColor& fgColor = Qt::black, const QColor& bgColor = Qt::white);
}
#endif // _ITEM_COMMON_H_
+2 -2
View File
@@ -38,7 +38,7 @@ void ItemGeneralSettings::edit(PicTextItem *item)
m_currItem = item;
// 从item快照创建ViewModel(如果item为空,使用默认值)
setViewModel(ItemGeneralSettingsVM::fromItem(item));
setViewModel(TextItemModel::fromItem(item));
}
void ItemGeneralSettings::initUI()
@@ -53,7 +53,7 @@ void ItemGeneralSettings::initUI()
ui->counterIDSpinBox->setValue(0);
}
void ItemGeneralSettings::setViewModel(const ItemGeneralSettingsVM &vm)
void ItemGeneralSettings::setViewModel(const TextItemModel &vm)
{
m_vmSnapshot = vm;
m_vm = vm;
+4 -44
View File
@@ -11,46 +11,6 @@ namespace Ui {
class ItemGeneralSettings;
}
/**
* @brief 图元通用属性的ViewModel
*
* 目的:解耦UI编辑器与PicTextItem,支持灵活的数据绑定和批量操作。
* UI修改属性时先更新VM,再决定何时应用到item(实时或延迟)。
*/
struct ItemGeneralSettingsVM {
// 图元类型,用于判断是否显示字间距
SourceType sourceType = SourceType::UNKNOWN;
ItemDirectionType direction = NORMAL;
int boldMultiple = 1;
int letterSpace = 0;
bool colorReversal = false;
std::function<QImage()> imageGenerator; // 图片生成函数
// 便利方法:从PicTextItem快照创建VM
static ItemGeneralSettingsVM fromItem(PicTextItem *item) {
ItemGeneralSettingsVM vm;
if (item) {
vm.sourceType = item->sourceType();
vm.direction = item->direction();
vm.boldMultiple = item->boldMultiple();
vm.letterSpace = item->letterSpace();
vm.colorReversal = item->colorReversal();
}
return vm;
}
// 检查是否有改动
bool hasDifference(const ItemGeneralSettingsVM &other) const {
return sourceType != other.sourceType ||
direction != other.direction ||
boldMultiple != other.boldMultiple ||
letterSpace != other.letterSpace ||
colorReversal != other.colorReversal;
}
};
class ItemGeneralSettings : public QWidget
{
Q_OBJECT
@@ -72,14 +32,14 @@ public:
*
* @param vm
*/
void setViewModel(const ItemGeneralSettingsVM& vm);
void setViewModel(const TextItemModel& vm);
/**
* @brief 获取当前ViewModel
*
* 调用者可以检查是否有改动,并决定是否应用
*/
ItemGeneralSettingsVM viewModel() const { return m_vm; }
TextItemModel viewModel() const { return m_vm; }
/**
* @brief 将ViewModel的属性应用到指定的PicTextItem
@@ -117,10 +77,10 @@ private:
PicTextItem* m_currItem = nullptr;
// UI编辑的状态,独立于m_currItem
ItemGeneralSettingsVM m_vm;
TextItemModel m_vm;
// 初始加载时的VM状态,用于检测改动
ItemGeneralSettingsVM m_vmSnapshot;
TextItemModel m_vmSnapshot;
QPainter m_painter;
};
+3 -3
View File
@@ -26,7 +26,7 @@ void PicDateItem::setSource(QVariant var)
if(m_model.datetimePattern.isEmpty())
return;
m_currDateTimeStr = generateTxtFromDateItemModel(m_model, QDateTime::currentDateTime());
m_currDateTimeStr = ItemUtils::generateTxtFromDateItemModel(m_model, QDateTime::currentDateTime());
applyModify();
}
@@ -47,13 +47,13 @@ bool PicDateItem::updateDatetimeStr()
return false;
if(m_currDateTimeStr.isEmpty()) {
m_currDateTimeStr = generateTxtFromDateItemModel(m_model, QDateTime::currentDateTime());
m_currDateTimeStr = ItemUtils::generateTxtFromDateItemModel(m_model, QDateTime::currentDateTime());
applyModify();
return true;
}
auto now = QDateTime::currentDateTime();
auto str = generateTxtFromDateItemModel(m_model, now);
auto str = ItemUtils::generateTxtFromDateItemModel(m_model, now);
if(str == m_currDateTimeStr) {
return false;
}
+9 -15
View File
@@ -52,22 +52,20 @@ ScheduleShiftsEditor::~ScheduleShiftsEditor()
delete ui;
}
void ScheduleShiftsEditor::edit(PicScheduleShiftItem* item)
void ScheduleShiftsEditor::setItemModel(QVector<ScheduleModel> schedulesModel, TextItemModel txtModel)
{
m_backup.clear();
m_generalSettings->edit(item);
if(item) {
item->saveAttrs(m_backup);
m_dataModel = item->schedules();
}
else {
m_dataModel.clear();
}
m_generalSettings->setViewModel(txtModel);
m_dataModel = schedulesModel;
applyDataModel();
}
const QVector<ScheduleModel>& ScheduleShiftsEditor::dataModel() const
TextItemModel ScheduleShiftsEditor::textItemModel()
{
return m_generalSettings->viewModel();
}
const QVector<ScheduleModel>& ScheduleShiftsEditor::scheduleModel() const
{
return m_dataModel;
}
@@ -79,10 +77,6 @@ PicScheduleShiftItem *ScheduleShiftsEditor::currEditItem()
void ScheduleShiftsEditor::onBtnCloseClicked()
{
if(currEditItem()) {
currEditItem()->setAttrs(m_backup);
}
emit rejected();
}
+5 -3
View File
@@ -35,7 +35,11 @@ public:
void edit(PicScheduleShiftItem* item);
const QVector<ScheduleModel>& dataModel() const;
void setItemModel(QVector<ScheduleModel> schedulesModel, TextItemModel txtModel);
TextItemModel textItemModel();
const QVector<ScheduleModel>& scheduleModel() const;
PicScheduleShiftItem* currEditItem();
@@ -59,8 +63,6 @@ private:
Ui::ScheduleShiftsEditor *ui;
QVector<ScheduleModel> m_dataModel;
ItemGeneralSettings* m_generalSettings = nullptr;
QXmlStreamAttributes m_backup;
};
#endif // SCHEDULESHIFTSEDITOR_H
+13 -2
View File
@@ -37,17 +37,23 @@ void PicCodeItem::setBarcodeViewModel(const BarcodeViewModel &vm)
{
m_vm = vm;
m_currCodeTxt = "";
setTextItemModel(m_vm.generalSettingsVM);
updateVariants();
qInfo() << "Barcode model: \r\n" << qPrintable(BarcodeViewModel::toString(vm));
}
BarcodeViewModel PicCodeItem::barcodeViewModel()
{
m_vm.generalSettingsVM = textItemModel();
return m_vm;
}
bool PicCodeItem::updateVariants(const QVector<int> counters)
{
if (counters.size() < 2) {
qWarning() << "PicCodeItem::updateVariants: counters size insufficient:" << counters.size() << ", expected >= 2";
return false;
}
m_currCounterValues = counters;
return updateVariants();
}
@@ -70,10 +76,15 @@ void PicCodeItem::saveCustomAttrs(QXmlStreamAttributes &attrs)
bool PicCodeItem::updateVariants()
{
auto txt = generateTxtFromBarcodeViewModel(m_vm, {m_currCounterValues[0], m_currCounterValues[1]}, QDateTime::currentDateTime());
if (m_currCounterValues.size() < 2) {
qWarning() << "PicCodeItem::updateVariants: m_currCounterValues size < 2, cannot generate barcode text";
return false;
}
auto txt = ItemUtils::generateTxtFromBarcodeViewModel(m_vm, {m_currCounterValues[0], m_currCounterValues[1]}, QDateTime::currentDateTime());
if(txt != m_currCodeTxt || m_currCodeTxt.isEmpty()) {
m_currCodeTxt = txt;
m_codeImage = generateBarcodeImage(txt, m_vm.type, m_vm.format);
m_codeImage = ItemUtils::generateBarcodeImage(txt, m_vm.type, m_vm.format);
applyModify();
return true;
}
+26
View File
@@ -300,6 +300,19 @@ QImage PicTextItem::preview()
{
return m_itemImage;
}
void PicTextItem::setTextItemModel(const TextItemModel &model)
{
setLetterSpace(model.letterSpace);
setBoldMultiple(model.boldMultiple);
setDirection(model.direction);
setColorReversal(model.colorReversal);
}
TextItemModel PicTextItem::textItemModel()
{
return TextItemModel::fromItem(this);
}
//! [1]
QVariant PicTextItem::itemChange(GraphicsItemChange change,
const QVariant &value)
@@ -441,3 +454,16 @@ QPointF PicTextItem::clampItemPos(const QPointF &p)
return QPointF (std::min(qreal(scene()->width() - boundingRect().width()), std::max(0.0, p.x())),
std::min(qreal(scene()->height() - boundingRect().height()), std::max(0.0, p.y())));
}
TextItemModel TextItemModel::fromItem(PicTextItem *item)
{
TextItemModel vm;
if (item) {
vm.sourceType = item->sourceType();
vm.direction = item->direction();
vm.boldMultiple = item->boldMultiple();
vm.letterSpace = item->letterSpace();
vm.colorReversal = item->colorReversal();
}
return vm;
}
+37
View File
@@ -42,6 +42,39 @@ enum SourceType{
COUNTER,
};
class PicTextItem;
/**
* @brief 图元通用属性的ViewModel
*
* 目的:解耦UI编辑器与PicTextItem,支持灵活的数据绑定和批量操作。
* UI修改属性时先更新VM,再决定何时应用到item(实时或延迟)。
*/
struct TextItemModel {
// 图元类型,用于判断是否显示字间距
SourceType sourceType = SourceType::UNKNOWN;
ItemDirectionType direction = NORMAL;
int boldMultiple = 1;
int letterSpace = 0;
bool colorReversal = false;
std::function<QImage()> imageGenerator; // 图片生成函数
// 便利方法:从PicTextItem快照创建VM
static TextItemModel fromItem(PicTextItem *item);
// 检查是否有改动
bool hasDifference(const TextItemModel &other) const {
return sourceType != other.sourceType ||
direction != other.direction ||
boldMultiple != other.boldMultiple ||
letterSpace != other.letterSpace ||
colorReversal != other.colorReversal;
}
};
class PicTextItem : public QGraphicsTextItem
{
Q_OBJECT
@@ -121,6 +154,10 @@ public:
*/
QImage preview();
void setTextItemModel(const TextItemModel& model);
TextItemModel textItemModel();
signals:
void lostFocus(PicTextItem *item);
void selectedChange(QGraphicsItem *item);