From 211ad41b12cb7dc628e6eb8376bebb478c428430 Mon Sep 17 00:00:00 2001 From: gongheng Date: Fri, 8 May 2026 15:55:01 +0800 Subject: [PATCH] fix(export): align table header and content in exported TXT file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace fixed QTextStream::setFieldWidth with display-width-aware padding. Add displayWidth() to calculate CJK characters as 1.5 columns, and use two-pass scanning in EXPORT_TO_TXT to compute per-column max width for accurate alignment. 修复导出TXT文件中表头与内容列不对齐的问题。 用基于显示宽度的空格填充替换固定setFieldWidth方式, 新增displayWidth计算CJK字符为1.5列宽度, 通过两遍扫描计算每列最大宽度实现精确对齐。 Log: 修复导出TXT文件表头与内容列不对齐 Bug: https://pms.uniontech.com/bug-view-357619.html Influence: 导出TXT文件时,表头和内容的列能正确对齐,中英文混排场景下不再错位。 --- .../src/DeviceManager/DeviceInfo.cpp | 45 ++++++++++--------- .../src/DeviceManager/DeviceInfo.h | 16 +++++-- deepin-devicemanager/src/MacroDefinition.h | 20 +++++++-- 3 files changed, 52 insertions(+), 29 deletions(-) diff --git a/deepin-devicemanager/src/DeviceManager/DeviceInfo.cpp b/deepin-devicemanager/src/DeviceManager/DeviceInfo.cpp index 0bd871f43..4bdac5dcf 100644 --- a/deepin-devicemanager/src/DeviceManager/DeviceInfo.cpp +++ b/deepin-devicemanager/src/DeviceManager/DeviceInfo.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later @@ -330,7 +330,21 @@ void DeviceBaseInfo::baseInfoToTxt(QTextStream &out, QList 0x7E || (code >= 0xA1 && code <= 0xFF)) + width += 1.5; + else + width += 1; + } + return width; +} + +void DeviceBaseInfo::tableInfoToTxt(QTextStream &out, const QList &colWidths) { // 获取表格内容 getTableData(); @@ -339,21 +353,15 @@ void DeviceBaseInfo::tableInfoToTxt(QTextStream &out) if (m_TableDataTr.size() < 1) return; - // 设置占位宽度 - QString text = m_TableDataTr[0]; - out.setFieldWidth(int(text.size() * 1.5)); - out.setFieldAlignment(QTextStream::FieldAlignment::AlignRight); - - foreach (auto item, m_TableDataTr) { - out.setFieldWidth(28); - out << item; + for (int col = 0; col < m_TableDataTr.size(); ++col) { + double w = (col < colWidths.size()) ? colWidths[col] : 30; + int pad = qMax(0, int(w - displayWidth(m_TableDataTr[col]))); + out << m_TableDataTr[col] << QString(pad, ' '); } - - out.setFieldWidth(0); out << "\n"; } -void DeviceBaseInfo::tableHeaderToTxt(QTextStream &out) +void DeviceBaseInfo::tableHeaderToTxt(QTextStream &out, const QList &colWidths) { // 获取表头 getTableHeader(); @@ -362,17 +370,12 @@ void DeviceBaseInfo::tableHeaderToTxt(QTextStream &out) if (m_TableHeaderTr.size() < 1) return; - // 设置占位宽度 - QString text = m_TableHeaderTr[0]; - out.setFieldWidth(int(text.size() * 1.5)); - out.setFieldAlignment(QTextStream::FieldAlignment::AlignLeft); - out << "\n"; for (int col = 0; col < m_TableHeaderTr.size() - 1; ++col) { - out.setFieldWidth(30); - out << m_TableHeaderTr[col]; + double w = (col < colWidths.size()) ? colWidths[col] : 30; + int pad = qMax(0, int(w - displayWidth(m_TableHeaderTr[col]))); + out << m_TableHeaderTr[col] << QString(pad, ' '); } - out.setFieldWidth(0); out << "\n"; } diff --git a/deepin-devicemanager/src/DeviceManager/DeviceInfo.h b/deepin-devicemanager/src/DeviceManager/DeviceInfo.h index c09880818..3338617f9 100644 --- a/deepin-devicemanager/src/DeviceManager/DeviceInfo.h +++ b/deepin-devicemanager/src/DeviceManager/DeviceInfo.h @@ -1,5 +1,4 @@ -// Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2019 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later @@ -334,14 +333,23 @@ class DeviceBaseInfo : public QObject /** * @brief tableInfoToTxt:表格内容写到txt * @param out:txt文件流 + * @param colWidths:每列的显示宽度列表 */ - void tableInfoToTxt(QTextStream &out); + void tableInfoToTxt(QTextStream &out, const QList &colWidths); /** * @brief tableHeaderToTxt:表头信息写到txt * @param out:txt文件流 + * @param colWidths:每列的显示宽度列表 */ - void tableHeaderToTxt(QTextStream &out); + void tableHeaderToTxt(QTextStream &out, const QList &colWidths); + + /** + * @brief displayWidth:计算字符串的显示宽度(CJK字符算1.5,其余算1) + * @param str:输入字符串 + * @return 显示宽度 + */ + static double displayWidth(const QString &str); /** * @brief tableInfoToHtml:表格内容写到html diff --git a/deepin-devicemanager/src/MacroDefinition.h b/deepin-devicemanager/src/MacroDefinition.h index 59d68b19c..0064dfe62 100644 --- a/deepin-devicemanager/src/MacroDefinition.h +++ b/deepin-devicemanager/src/MacroDefinition.h @@ -1,5 +1,4 @@ -// Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. -// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2019 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: GPL-3.0-or-later @@ -33,9 +32,22 @@ \ /**添加Table信息**/ \ if (deviceLst.size() > 1) { \ - deviceLst[0]->tableHeaderToTxt(out); \ + /* 第一遍扫描:计算每列最大显示宽度 */ \ + const QStringList &_hdr = deviceLst[0]->getTableHeader(); \ + int _colCount = _hdr.size() - 1; \ + QList _colWidths; \ + for (int _c = 0; _c < _colCount; ++_c) \ + _colWidths.append(DeviceBaseInfo::displayWidth(_hdr[_c]) + 4); \ + foreach (auto _dev, deviceLst) { \ + const QStringList &_dat = _dev->getTableData(); \ + for (int _c = 0; _c < qMin(_dat.size(), _colCount); ++_c) { \ + double _w = DeviceBaseInfo::displayWidth(_dat[_c]) + 4; \ + if (_w > _colWidths[_c]) _colWidths[_c] = _w; \ + } \ + } \ + deviceLst[0]->tableHeaderToTxt(out, _colWidths); \ foreach (auto device, deviceLst) { \ - device->tableInfoToTxt(out); \ + device->tableInfoToTxt(out, _colWidths); \ } \ } \ \