Files

204 lines
6.3 KiB
Markdown

# DateVarSet 类分析与解决方案
## 一、类功能概述
`DateVarSet` 是一个用于日期变量设置的 Qt 界面类,继承自 `QWidget` 和 `ParaSettingUI`。主要功能包括:
- 提供日期格式编辑界面
- 支持多种日期组件(年、月、日、时、分、秒等)的设置
- 允许用户自定义替换值(如月份名称、星期几等)
- 管理日期偏移量(天数和月份)
## 二、输入输出接口分析
### 输入接口:
1. `void edit(PicDateItem* item)` - 编辑指定的日期项目
2. `void setDateModel(const DateItemModel& model)` - 设置日期模型数据
3. `void bindSysPara(SysPara *sysPara)` - 绑定系统参数
4. `void bindTxTEdit(QTextEdit* textEdit)` - 绑定文本编辑器
### 输出接口:
1. `DateItemModel dateModel()` - 获取当前日期模型
2. `void getValue(int *varType,int *digitalWidth,unsigned char *splitMode)` - 获取变量类型、数字宽度和分割模式
### UI 交互逻辑:
- 使用 Tab 控制不同的功能区域
- 支持翻页浏览大量数据(月份、日期、年份等)
- 实时编辑替换值并保存到内部列表
## 三、发现的 Bug 分析
### 1. 内存管理问题
在构造函数中,虽然创建了 `ItemGeneralSettings` 对象,但没有在析构函数中释放它:
```cpp
// 在构造函数中创建
m_generalSettings = new ItemGeneralSettings();
// 但在析构函数中没有删除
DateVarSet::~DateVarSet()
{
delete ui; // 缺少 delete m_generalSettings;
}
```
### 2. 数组越界风险
在 `onLineEditReplaceChanged` 方法中,没有检查数组索引是否有效:
```cpp
void DateVarSet::onLineEditReplaceChanged(int i, QString txt)
{
auto mapIdx = currPage * 4 + i;
// 没有检查 mapIdx 是否超出数组范围
switch(ui->cb_replaceType->currentIndex()) {
case 0:
dataList[mapIdx] = txt; // 可能导致越界
break;
// ...
}
}
```
### 3. 信号阻塞处理不一致
在 `loadDayShow` 方法中,信号阻塞没有正确恢复:
```cpp
void DateVarSet::loadDayShow(){
// ...
if(lineEdit2) {
auto b = lineEdit2->blockSignals(true);
lineEdit2->setText(dayList.at(i));
lineEdit2->blockSignals(false); // 直接设为false,而不是恢复原状态
}
}
```
### 4. 未使用的成员变量
`dataMap` 在 `DateItemModel` 中被标记为 "unused",但仍参与序列化操作。
### 5. 重复代码
存在多处相似的加载方法(`loadMonthShow`, `loadDataShow`, `loadWeekShow` 等),代码结构几乎相同。
### 6. 静态全局变量使用不当
使用了全局静态变量 `vartypeR` 和 `replaceValueMap`,这可能导致不同实例间的数据污染。
## 四、解决方案
### 1. 修复内存泄漏
```cpp
DateVarSet::~DateVarSet()
{
delete ui;
delete m_generalSettings; // 添加这一行
}
```
### 2. 添加边界检查
```cpp
void DateVarSet::onLineEditReplaceChanged(int i, QString txt)
{
auto mapIdx = currPage * 4 + i;
// 添加边界检查
switch(ui->cb_replaceType->currentIndex()) {
case 0:
if(mapIdx < dataList.size()) {
dataList[mapIdx] = txt;
}
break;
case 1:
if(mapIdx < weekList.size()) {
weekList[mapIdx] = txt;
}
break;
case 2:
if(mapIdx < monthList.size()) {
monthList[mapIdx] = txt;
}
break;
case 3:
if(mapIdx < yearList.size()) {
yearList[mapIdx] = txt;
}
break;
case 4:
if(mapIdx < dayList.size()) {
dayList[mapIdx] = txt;
}
break;
case 5:
if(mapIdx < hourList.size()) {
hourList[mapIdx] = txt;
}
break;
}
}
```
### 3. 修复信号阻塞
```cpp
void DateVarSet::loadDayShow(){
// ...
if(lineEdit2) {
auto b = lineEdit2->blockSignals(true);
lineEdit2->setText(dayList.at(i));
lineEdit2->blockSignals(b); // 恢复原始状态,不是硬编码为false
}
}
```
### 4. 重构重复代码
创建通用模板方法来替代重复的加载逻辑:
```cpp
template<typename T>
void DateVarSet::loadGenericShow(const QStringList& sourceList, int maxPages, int itemsPerPage = 4) {
if(currPage > maxPages) {
currPage = maxPages;
}
int objectIndex = 1;
for(int i = currPage * itemsPerPage; (i < (currPage + 1) * itemsPerPage) && (i < sourceList.size()); i++) {
QString strObject = QString("lineEditName") + QString::number(objectIndex);
QLineEdit *lineEdit = this->findChild<QLineEdit*>(strObject);
if(lineEdit) {
lineEdit->setText(QString::number(i + 1));
}
QString strObject2 = QString("lineEdit_Replace") + QString::number(objectIndex);
QLineEdit *lineEdit2 = this->findChild<QLineEdit*>(strObject2);
if(lineEdit2) {
auto b = lineEdit2->blockSignals(true);
lineEdit2->setText(sourceList.at(i));
lineEdit2->blockSignals(b);
}
objectIndex++;
}
}
```
### 5. 移除不必要的全局变量
将全局静态变量移入类中作为成员变量:
```cpp
private:
unsigned char m_varTypeR = 0x00;
QMap<int, QMap<int, QString>> m_replaceValueMap;
```
## 五、可移除的无用逻辑
根据要求,需要移除构造默认 `DateItemModel` 的逻辑。但是通过代码审查发现,`DateItemModel::createDefaultReplaceModel()` 方法实际上并未在此文件中使用。该方法存在于 `ViewModels.h` 中,但 `DateVarSet` 类并未调用它。
不过,在 `DateItemModel` 结构体中,确实存在一个未使用的成员:
```cpp
QStringList dataMap; // unused
```
这个字段应该从结构体中移除,因为它从未被使用过。
## 六、其他改进建议
1. **改进错误处理**:在 `edit` 方法中添加更详细的参数验证
2. **优化性能**:减少不必要的 UI 更新操作
3. **增强类型安全**:使用枚举代替魔法数字(如 `cb_replaceType` 的索引值)
4. **完善注释**:为复杂的业务逻辑添加详细注释
这些修改将提高代码的健壮性、可维护性和性能。
## 七、总结
`DateVarSet` 类存在多个潜在问题,主要包括内存泄漏、数组越界风险、代码重复和全局变量使用不当。通过上述解决方案可以显著改善代码质量,同时移除无用的 `dataMap` 字段可以简化数据结构。