Skip to content

Commit cd7d18e

Browse files
xionglinlinmhduiy
authored andcommitted
fix: fix blank area in security update log details view
1. Remove the dependency on getDetailInfos Q_INVOKABLE method by exposing DetailInfos and Expanded roles directly in the model 2. Add setExpanded Q_INVOKABLE method to the model to properly manage the expanded state 3. Sync data efficiently using syncData which avoids unnecessary beginResetModel/endResetModel when the pointer list hasn't changed 4. Simplify the QML view to use model.expanded and model.detailInfos directly from the model roles 5. Move the showDetails property from local state to model-backed state to persist expansion correctly when data refreshes 6. Use the model's setExpanded method when clicking "View More" or "Collapse" buttons 7. Add setExpanded/isExpanded methods to UpdateItemInfo to persist the expanded state per item 8. Fix the issue where the "View More" button was incorrectly visible due to stale local state 9. Replace clearAllData+addUpdateData pattern with syncData to prevent unnecessary model reset when only the selected state changes Log: Fixed security update log details display with proper expansion state management Influence: 1. Verify "View More" button appears correctly for security update items with detail logs 2. Click "View More" and verify the detail information displays correctly 3. Click "Collapse" and verify the details hide properly 4. Verify the expanded state persists when other updates or UI refreshes occur 5. Verify the "View More" button shows for items without details and does not expand to avoid blank areas 6. Test that checking/unchecking update items does not cause the list to scroll or collapse details 7. Verify the detail content displays correctly for both security updates and regular updates fix: 修复安全更新日志详情页出现空白区域问题 1. 通过直接暴露 DetailInfos 和 Expanded 角色到模型中,移除对 getDetailInfos Q_INVOKABLE 方法的依赖 2. 在模型中添加 setExpanded Q_INVOKABLE 方法来正确管理展开状态 3. 使用 syncData 方法高效同步数据,避免在指针列表未变化时触发不必要的 beginResetModel/endResetModel 4. 简化 QML 视图,直接使用模型角色 model.expanded 和 model.detailInfos 5. 将 showDetails 属性从本地状态迁移到模型支持的存储,以在数据刷新时正确 保持展开状态 6. 点击"查看详情"或"收起"按钮时,使用模型的 setExpanded 方法 7. 在 UpdateItemInfo 中添加 setExpanded/isExpanded 方法,以持久化每个项 目的展开状态 8. 修复由于本地状态过期导致"查看详情"按钮显示异常的问题 9. 使用 syncData 替代 clearAllData+addUpdateData 模式,防止仅在选中状态 变化时触发不必要的模型重置 Log: 修复安全更新日志详情显示问题,改进展开状态管理 Influence: 1. 验证安全更新项目在有详情日志时正确显示"查看详情"按钮 2. 点击"查看详情"后验证详情信息正确显示 3. 点击"收起"后验证详情正确隐藏 4. 验证在其他更新或UI刷新时展开状态保持不变 5. 验证无详情项目不显示"查看详情"按钮,避免出现空白区域 6. 测试勾选/取消勾选更新项目时,不会导致列表滚动或详情折叠 7. 验证详情内容在安全更新和普通更新中都能正确显示 PMS: BUG-367683 Change-Id: I383dadacaf4217e28e25b32e7ce55aebaf32506c
1 parent f849d61 commit cd7d18e

5 files changed

Lines changed: 292 additions & 236 deletions

File tree

src/dcc-update-plugin/operation/updateiteminfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ class UpdateItemInfo : public QObject {
6262
void setIsChecked(bool isChecked);
6363
bool isChecked() const { return m_isChecked; }
6464

65+
void setExpanded(bool expanded) { m_expanded = expanded; }
66+
bool isExpanded() const { return m_expanded; }
67+
6568
UpdateType updateType() const { return m_updateType; }
6669

6770
void setUpdateStatus(UpdatesStatus status);
@@ -91,6 +94,7 @@ class UpdateItemInfo : public QObject {
9194
QStringList m_packages;
9295
QList<DetailInfo> m_detailInfos;
9396
bool m_isChecked;
97+
bool m_expanded = false;
9498
UpdatesStatus m_updateStatus;
9599
QString m_typeString;
96100
};

src/dcc-update-plugin/operation/updatelistmodel.cpp

Lines changed: 62 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -48,25 +48,54 @@ QVariant UpdateListModel::data(const QModelIndex &index, int role) const
4848
return data->updateStatus();
4949
case IconName:
5050
return getIconName(data->updateType());
51+
case Expanded:
52+
return data->isExpanded();
53+
case DetailInfos: {
54+
QVariantList result;
55+
const auto& detailInfos = data->detailInfos();
56+
for (const auto& detail : detailInfos) {
57+
QVariantMap map;
58+
map["name"] = detail.name;
59+
map["updateTime"] = detail.updateTime;
60+
map["info"] = detail.info;
61+
map["link"] = detail.link;
62+
map["vulLevel"] = detail.vulLevel;
63+
result.append(map);
64+
}
65+
return result;
66+
}
5167
default:
5268
qCDebug(logDccUpdatePlugin) << "Unknown role requested:" << role;
5369
break;
5470
}
5571
return QVariant();
5672
}
5773

58-
void UpdateListModel::addUpdateData(UpdateItemInfo* itemData)
74+
void UpdateListModel::syncData(const QList<UpdateItemInfo *> &items)
5975
{
60-
qCDebug(logDccUpdatePlugin) << "Adding update data:" << itemData->name() << "type:" << itemData->updateType();
61-
int row = rowCount();
62-
beginInsertRows(QModelIndex(), row, row);
63-
m_updateLists.append(itemData);
64-
connect(itemData, &UpdateItemInfo::downloadSizeChanged, this, &UpdateListModel::refreshDownloadSize);
65-
endInsertRows();
76+
// 指针列表(含顺序)未变化,不触发 reset 避免滚动跳动。
77+
// item 内部数据(如异步获取的日志)的变更通过 dataChanged 通知视图刷新;
78+
if (items == m_updateLists) {
79+
if (!m_updateLists.isEmpty()) {
80+
emit dataChanged(index(0), index(m_updateLists.count() - 1));
81+
}
82+
refreshDownloadSize();
83+
emit visibilityChanged();
84+
return;
85+
}
86+
87+
beginResetModel();
88+
for (auto item : m_updateLists) {
89+
disconnect(item, &UpdateItemInfo::downloadSizeChanged, this, &UpdateListModel::refreshDownloadSize);
90+
}
91+
m_updateLists = items;
92+
for (auto item : m_updateLists) {
93+
connect(item, &UpdateItemInfo::downloadSizeChanged, this, &UpdateListModel::refreshDownloadSize, Qt::UniqueConnection);
94+
}
95+
endResetModel();
6696

6797
refreshDownloadSize();
6898
emit visibilityChanged();
69-
qCDebug(logDccUpdatePlugin) << "Update data added, total items:" << m_updateLists.size();
7099
}
71100

72101
QString UpdateListModel::getIconName(UpdateType type) const
@@ -180,6 +209,31 @@ void UpdateListModel::setChecked(int index, bool checked)
180209
}
181210
}
182211

212+
void UpdateListModel::setExpanded(int index, bool expanded)
213+
{
214+
if (index >= 0 && index < m_updateLists.count()) {
215+
if (m_updateLists[index]->isExpanded() == expanded) {
216+
return;
217+
}
218+
m_updateLists[index]->setExpanded(expanded);
219+
220+
QModelIndex changedIndex = this->index(index);
221+
emit dataChanged(changedIndex, changedIndex, { Expanded });
222+
} else {
223+
qCWarning(logDccUpdatePlugin) << "Invalid index for setExpanded:" << index;
224+
}
225+
}
226+
227+
void UpdateListModel::collapseAll()
228+
{
229+
for (int i = 0; i < m_updateLists.count(); ++i) {
230+
if (m_updateLists[i]->isExpanded()) {
231+
m_updateLists[i]->setExpanded(false);
232+
emit dataChanged(index(i), index(i), { Expanded });
233+
}
234+
}
235+
}
236+
183237
int UpdateListModel::getAllUpdateType() const
184238
{
185239
qCDebug(logDccUpdatePlugin) << "Getting combined update type for all checked items";
@@ -191,23 +245,3 @@ int UpdateListModel::getAllUpdateType() const
191245
}
192246
return updateType;
193247
}
194-
195-
QVariantList UpdateListModel::getDetailInfos(int index) const
196-
{
197-
QVariantList result;
198-
if (index >= 0 && index < m_updateLists.count()) {
199-
const auto& detailInfos = m_updateLists[index]->detailInfos();
200-
for (const auto& detail : detailInfos) {
201-
QVariantMap map;
202-
map["name"] = detail.name;
203-
map["updateTime"] = detail.updateTime;
204-
map["info"] = detail.info;
205-
map["link"] = detail.link;
206-
map["vulLevel"] = detail.vulLevel;
207-
result.append(map);
208-
}
209-
} else {
210-
qCWarning(logDccUpdatePlugin) << "Invalid index for getDetailInfos:" << index;
211-
}
212-
return result;
213-
}

src/dcc-update-plugin/operation/updatelistmodel.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ class UpdateListModel : public QAbstractListModel
2424
ReleaseTime,
2525
Checked,
2626
UpdateStatus,
27-
IconName
27+
IconName,
28+
Expanded,
29+
DetailInfos
2830
};
2931

3032
explicit UpdateListModel(QObject *parent = nullptr);
@@ -34,12 +36,17 @@ class UpdateListModel : public QAbstractListModel
3436

3537
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
3638

37-
void addUpdateData(UpdateItemInfo *itemData);
39+
// 用目标列表整体同步模型内容;当内容与当前一致时不发出任何信号,
40+
// 避免无意义的 beginResetModel/endResetModel 造成视图重建与滚动跳动
41+
void syncData(const QList<UpdateItemInfo *> &items);
3842

3943
void clearAllData();
4044

4145
Q_INVOKABLE void setChecked(int index, bool checked);
4246

47+
Q_INVOKABLE void setExpanded(int index, bool expanded);
48+
Q_INVOKABLE void collapseAll();
49+
4350
Q_INVOKABLE int getAllUpdateType() const;
4451

4552
QString getIconName(UpdateType type) const;
@@ -54,6 +61,8 @@ class UpdateListModel : public QAbstractListModel
5461
roles[Checked] = "checked";
5562
roles[UpdateStatus] = "updateStatus";
5663
roles[IconName] = "iconName";
64+
roles[Expanded] = "expanded";
65+
roles[DetailInfos] = "detailInfos";
5766
return roles;
5867
}
5968

@@ -62,7 +71,6 @@ class UpdateListModel : public QAbstractListModel
6271
QString downloadSize() const;
6372

6473
Q_INVOKABLE UpdateType getUpdateType(int index) const;
65-
Q_INVOKABLE QVariantList getDetailInfos(int index) const;
6674

6775
public Q_SLOTS:
6876
void refreshDownloadSize();

src/dcc-update-plugin/operation/updatemodel.cpp

Lines changed: 40 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -862,41 +862,18 @@ void UpdateModel::refreshUpdateStatus()
862862
void UpdateModel::refreshUpdateUiModel()
863863
{
864864
qCDebug(logDccUpdatePlugin) << "Refreshing update UI models";
865-
if (m_preUpdatelistModel) {
866-
m_preUpdatelistModel->clearAllData();
867-
}
868865

869-
if (m_downloadinglistModel) {
870-
m_downloadinglistModel->clearAllData();
871-
}
872-
873-
if (m_installinglistModel) {
874-
m_installinglistModel->clearAllData();
875-
}
876-
877-
if (m_installCompleteListModel) {
878-
m_installCompleteListModel->clearAllData();
879-
}
880-
881-
if (m_installFailedListModel) {
882-
m_installFailedListModel->clearAllData();
883-
}
884-
885-
if (m_downloadFailedListModel) {
886-
m_downloadFailedListModel->clearAllData();
887-
}
888-
889-
if (m_preInstallListModel) {
890-
m_preInstallListModel->clearAllData();
891-
}
892-
893-
if (m_backingUpListModel) {
894-
m_backingUpListModel->clearAllData();
895-
}
896-
897-
if (m_backupFailedListModel) {
898-
m_backupFailedListModel->clearAllData();
899-
}
866+
// 先按目标状态分桶,再用 syncData 整体同步;内容未变化的模型不会触发 reset,
867+
// 从而避免勾选 CheckBox 等仅改变选中态的场景下列表重建与滚动跳动
868+
QList<UpdateItemInfo *> preUpdateList;
869+
QList<UpdateItemInfo *> downloadingList;
870+
QList<UpdateItemInfo *> preInstallList;
871+
QList<UpdateItemInfo *> downloadFailedList;
872+
QList<UpdateItemInfo *> installingList;
873+
QList<UpdateItemInfo *> installCompleteList;
874+
QList<UpdateItemInfo *> installFailedList;
875+
QList<UpdateItemInfo *> backingUpList;
876+
QList<UpdateItemInfo *> backupFailedList;
900877

901878
for (auto item : m_allUpdateInfos.values()) {
902879
qCDebug(logDccUpdatePlugin) << "refresh Update Ui:" << item->updateType() << item->updateStatus() << item->isUpdateModeEnabled();
@@ -905,44 +882,63 @@ void UpdateModel::refreshUpdateUiModel()
905882

906883
switch (item->updateStatus()) {
907884
case Updated:
908-
m_installCompleteListModel->addUpdateData(item);
885+
installCompleteList.append(item);
909886
break;
910887
case UpdatesAvailable:
911-
m_preUpdatelistModel->addUpdateData(item);
888+
preUpdateList.append(item);
912889
break;
913890
case DownloadWaiting:
914891
case Downloading:
915892
case DownloadPaused:
916893
case UpgradeWaiting:
917-
m_downloadinglistModel->addUpdateData(item);
894+
downloadingList.append(item);
918895
break;
919896
case Downloaded:
920-
m_preInstallListModel->addUpdateData(item);
897+
preInstallList.append(item);
921898
break;
922899
case DownloadFailed:
923-
m_downloadFailedListModel->addUpdateData(item);
900+
downloadFailedList.append(item);
924901
break;
925902
case UpgradeReady:
926903
case Upgrading:
927-
m_installinglistModel->addUpdateData(item);
904+
installingList.append(item);
928905
break;
929906
case UpgradeFailed:
930-
m_installFailedListModel->addUpdateData(item);
907+
installFailedList.append(item);
931908
break;
932909
case UpgradeSuccess:
933910
case UpgradeComplete:
934-
m_installCompleteListModel->addUpdateData(item);
911+
installCompleteList.append(item);
935912
break;
936913
case BackingUp:
937914
case BackupSuccess:
938-
m_backingUpListModel->addUpdateData(item);
915+
backingUpList.append(item);
939916
break;
940917
case BackupFailed:
941-
m_backupFailedListModel->addUpdateData(item);
918+
backupFailedList.append(item);
942919
default:
943920
break;
944921
}
945922
}
923+
924+
if (m_preUpdatelistModel)
925+
m_preUpdatelistModel->syncData(preUpdateList);
926+
if (m_downloadinglistModel)
927+
m_downloadinglistModel->syncData(downloadingList);
928+
if (m_preInstallListModel)
929+
m_preInstallListModel->syncData(preInstallList);
930+
if (m_downloadFailedListModel)
931+
m_downloadFailedListModel->syncData(downloadFailedList);
932+
if (m_installinglistModel)
933+
m_installinglistModel->syncData(installingList);
934+
if (m_installCompleteListModel)
935+
m_installCompleteListModel->syncData(installCompleteList);
936+
if (m_installFailedListModel)
937+
m_installFailedListModel->syncData(installFailedList);
938+
if (m_backingUpListModel)
939+
m_backingUpListModel->syncData(backingUpList);
940+
if (m_backupFailedListModel)
941+
m_backupFailedListModel->syncData(backupFailedList);
946942
}
947943

948944
void UpdateModel::updateAvailableState()

0 commit comments

Comments
 (0)