-
Notifications
You must be signed in to change notification settings - Fork 41
Feat: add HeaderInfoTableWidget for displaying device information #632
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| // SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. | ||
| // | ||
| // SPDX-License-Identifier: GPL-3.0-or-later | ||
|
|
||
| #include <DApplication> | ||
|
Check warning on line 5 in deepin-devicemanager/src/Widget/headerinfotableDelegate.cpp
|
||
| #include <DPaletteHelper> | ||
|
Check warning on line 6 in deepin-devicemanager/src/Widget/headerinfotableDelegate.cpp
|
||
| #include <DPalette> | ||
|
Check warning on line 7 in deepin-devicemanager/src/Widget/headerinfotableDelegate.cpp
|
||
|
|
||
| #include "headerinfotableDelegate.h" | ||
|
|
||
| DWIDGET_USE_NAMESPACE | ||
|
|
||
| HeaderInfoDelegate::HeaderInfoDelegate(QObject *parent) | ||
| : QStyledItemDelegate(parent) | ||
| { | ||
| } | ||
|
|
||
| void HeaderInfoDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const | ||
| { | ||
| QStyleOptionViewItem opt(option); | ||
| initStyleOption(&opt, index); | ||
|
|
||
| QWidget *wnd = DApplication::activeWindow(); | ||
|
Check warning on line 23 in deepin-devicemanager/src/Widget/headerinfotableDelegate.cpp
|
||
| DPalette::ColorGroup cg = wnd ? DPalette::Active : DPalette::Inactive; | ||
| auto palette = DPaletteHelper::instance()->palette(option.widget); | ||
|
|
||
| if (opt.state & QStyle::State_Selected) { | ||
| QColor highlightColor = palette.color(cg, DPalette::HighlightedText); | ||
| opt.palette.setColor(QPalette::Text, highlightColor); | ||
| opt.palette.setColor(QPalette::WindowText, highlightColor); | ||
| } else { | ||
| QColor normalColor = palette.color(cg, DPalette::Text); | ||
| opt.palette.setColor(QPalette::Text, normalColor); | ||
| opt.palette.setColor(QPalette::WindowText, normalColor); | ||
| } | ||
|
|
||
| QStyledItemDelegate::paint(painter, opt, index); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| // SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. | ||
| // | ||
| // SPDX-License-Identifier: GPL-3.0-or-later | ||
|
|
||
| #ifndef HEADERINFOTABLEDELEGATE_H | ||
| #define HEADERINFOTABLEDELEGATE_H | ||
|
|
||
| #include <QStyledItemDelegate> | ||
|
Check warning on line 8 in deepin-devicemanager/src/Widget/headerinfotableDelegate.h
|
||
|
|
||
| class HeaderInfoDelegate : public QStyledItemDelegate | ||
| { | ||
| public: | ||
| explicit HeaderInfoDelegate(QObject *parent = nullptr); | ||
|
|
||
| void paint(QPainter *painter, const QStyleOptionViewItem &option, | ||
| const QModelIndex &index) const override; | ||
| }; | ||
|
|
||
| #endif | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| // SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. | ||
| // | ||
| // SPDX-License-Identifier: GPL-3.0-or-later | ||
|
|
||
| #include "headerinfotablewidget.h" | ||
| #include "headerinfotableDelegate.h" | ||
| #include "MacroDefinition.h" | ||
|
Check warning on line 7 in deepin-devicemanager/src/Widget/headerinfotablewidget.cpp
|
||
|
|
||
| #include <DApplication> | ||
|
Check warning on line 9 in deepin-devicemanager/src/Widget/headerinfotablewidget.cpp
|
||
| #include <DPaletteHelper> | ||
|
Check warning on line 10 in deepin-devicemanager/src/Widget/headerinfotablewidget.cpp
|
||
|
|
||
| #include <QHeaderView> | ||
|
Check warning on line 12 in deepin-devicemanager/src/Widget/headerinfotablewidget.cpp
|
||
| #include <QPainter> | ||
|
Check warning on line 13 in deepin-devicemanager/src/Widget/headerinfotablewidget.cpp
|
||
| #include <QPainterPath> | ||
|
|
||
| DWIDGET_USE_NAMESPACE | ||
|
|
||
| static constexpr int kColumnCount { 2 }; | ||
|
|
||
| HeaderInfoTableWidget::HeaderInfoTableWidget(DWidget *parent) | ||
| : DTableWidget(parent) | ||
| { | ||
| initUI(); | ||
| } | ||
|
|
||
| void HeaderInfoTableWidget::updateData(const QList<QPair<QString, QString>> &data) | ||
| { | ||
| clear(); | ||
| int nRow = data.size(); | ||
| setRowCount(nRow); | ||
|
|
||
| QWidget *wnd = DApplication::activeWindow(); | ||
| DPalette::ColorGroup cg = wnd ? DPalette::Active : DPalette::Inactive; | ||
| auto palette = DPaletteHelper::instance()->palette(this); | ||
| QColor colorEven = palette.color(cg, DPalette::Base); | ||
| QColor colorOdd = palette.color(cg, DPalette::ItemBackground); | ||
|
|
||
| for (int i = 0; i < nRow; ++i) { | ||
| QTableWidgetItem *itemFirst = new QTableWidgetItem(data[i].first); | ||
| itemFirst->setFlags(itemFirst->flags() & ~Qt::ItemIsSelectable); | ||
| itemFirst->setBackground(i % 2 == 0 ? colorEven : colorOdd); | ||
| setItem(i, 0, itemFirst); | ||
| QTableWidgetItem *itemSecond = new QTableWidgetItem(data[i].second); | ||
| itemSecond->setFlags(itemSecond->flags() & ~Qt::ItemIsSelectable); | ||
| itemSecond->setBackground(i % 2 == 0 ? colorEven : colorOdd); | ||
| setItem(i, 1, itemSecond); | ||
| } | ||
|
|
||
| // 调整控件高度,使内容刚好完全显示,不出现垂直滚动条 | ||
| if (nRow > 0) { | ||
| // 为了保持底部圆角,给表格高度留出 2px 余量;避免内容铺满viewport导致圆角被覆盖 | ||
| setFixedHeight(ROW_HEIGHT * nRow + 2); | ||
| } else { | ||
| setFixedHeight(0); | ||
| } | ||
| } | ||
|
|
||
| void HeaderInfoTableWidget::initUI() | ||
| { | ||
| setColumnCount(kColumnCount); | ||
| this->setEditTriggers(QAbstractItemView::NoEditTriggers); | ||
| this->setVerticalScrollMode(QAbstractItemView::ScrollMode::ScrollPerPixel); | ||
| setSelectionMode(QAbstractItemView::NoSelection); | ||
| setSelectionBehavior(QAbstractItemView::SelectItems); | ||
| this->setFocusPolicy(Qt::NoFocus); | ||
| // 设置无边框, 避免原始方形外框干扰圆角绘制 | ||
| this->setFrameStyle(QFrame::NoFrame); | ||
| this->setShowGrid(false); | ||
| this->viewport()->setAutoFillBackground(true); | ||
| m_delegate = new HeaderInfoDelegate(this); | ||
| this->setItemDelegate(m_delegate); | ||
| setAlternatingRowColors(true); | ||
| this->verticalHeader()->setVisible(false); | ||
| this->horizontalHeader()->setVisible(false); | ||
| this->setSortingEnabled(false); | ||
| this->horizontalHeader()->setStretchLastSection(true); | ||
| this->verticalHeader()->setDefaultSectionSize(ROW_HEIGHT); | ||
| this->horizontalHeader()->setDefaultSectionSize(180); | ||
| this->setAttribute(Qt::WA_TranslucentBackground); | ||
| this->setWindowFlags(Qt::FramelessWindowHint); | ||
| } | ||
|
|
||
| void HeaderInfoTableWidget::paintEvent(QPaintEvent *event) | ||
| { | ||
| DTableWidget::paintEvent(event); | ||
|
|
||
| QWidget *wnd = DApplication::activeWindow(); | ||
| DPalette::ColorGroup cg = wnd ? DPalette::Active : DPalette::Inactive; | ||
|
|
||
| auto palette = DPaletteHelper::instance()->palette(this); | ||
|
|
||
| QRect rect = viewport()->rect().adjusted(0, 0, -1, -1); | ||
| int width = 1; | ||
| int radius = 8; | ||
|
|
||
| QPainter painter(this->viewport()); | ||
| painter.setRenderHint(QPainter::Antialiasing, true); | ||
|
|
||
| QPainterPath paintPathOut; | ||
| paintPathOut.addRoundedRect(rect, radius, radius); | ||
|
|
||
| QRect rectIn = QRect(rect.x() + width, rect.y() + width, rect.width() - width * 2, rect.height() - width * 2); | ||
| QPainterPath paintPathIn; | ||
| paintPathIn.addRoundedRect(rectIn, radius, radius); | ||
|
|
||
| QPainterPath paintPath = paintPathOut.subtracted(paintPathIn); | ||
| QBrush bgBrush(palette.color(cg, DPalette::FrameBorder)); | ||
| painter.fillPath(paintPath, bgBrush); | ||
|
|
||
| QPen pen = painter.pen(); | ||
| pen.setWidth(width); | ||
| pen.setColor(palette.color(cg, DPalette::FrameBorder)); | ||
| painter.setPen(pen); | ||
| painter.drawRoundedRect(rectIn, radius, radius); | ||
|
|
||
| // Draw vertical divider between first and second columns (same as DetailTreeView) | ||
| QLine vline(rect.topLeft().x() + 179, rect.topLeft().y(), rect.bottomLeft().x() + 179, rect.bottomLeft().y()); | ||
| painter.drawLine(vline); | ||
|
Comment on lines
+117
to
+118
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): Hardcoded divider position will desync if the column width changes (resize, DPI, style). The X-position is hardcoded to 179 while the first column width is 180 and can change (resize, DPI, layout). When that happens, the divider won’t align with the column border. Please compute the position dynamically (e.g., |
||
| } | ||
|
|
||
| void HeaderInfoTableWidget::clear() | ||
| { | ||
| DTableWidget::clear(); | ||
| setRowCount(0); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| // SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. | ||
| // | ||
| // SPDX-License-Identifier: GPL-3.0-or-later | ||
|
|
||
| #ifndef HEADERINFOTABLEWIDGET_H | ||
| #define HEADERINFOTABLEWIDGET_H | ||
|
|
||
| #include <DTableWidget> | ||
| #include <DWidget> | ||
|
|
||
| #include <QObject> | ||
|
|
||
| class HeaderInfoTableWidget : public DTK_WIDGET_NAMESPACE::DTableWidget | ||
| { | ||
| Q_OBJECT | ||
| public: | ||
| explicit HeaderInfoTableWidget(DTK_WIDGET_NAMESPACE::DWidget *parent = nullptr); | ||
| void updateData(const QList<QPair<QString, QString>> &data); | ||
|
|
||
| protected: | ||
| void paintEvent(QPaintEvent *event) override; | ||
|
|
||
| private: | ||
| void initUI(); | ||
| void clear(); | ||
| class HeaderInfoDelegate *m_delegate = nullptr; | ||
| }; | ||
|
|
||
| #endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (complexity): Consider refactoring palette handling, geometry calculations, and the
clear()helper to remove duplication, magic numbers, and surprising overrides while keeping the widget’s behavior unchanged.You can reduce complexity and keep behavior by extracting the repeated palette logic, deriving geometry from the table state, and clarifying the
clear()override.1. Centralize palette/color-group logic
updateData()andpaintEvent()both compute the active window, color group, and palette. Extract this into a small helper:Then use it in both places:
This keeps the color behavior identical but removes duplication and makes future palette changes localized.
2. Derive divider position from header instead of magic constant
The
179constant is implicitly tied to the header’s default section size of180. Use the header API to compute the divider, so column width changes stay in sync:This preserves the look while removing the hard-coded coupling between
179and180.3. Clarify and avoid shadowing
clear()Your private
clear()shadowsQTableWidget::clear()and addssetRowCount(0). To make intent clearer and reduce surprise, rename and use a more descriptive helper:Then in
updateData():This keeps the exact behavior but avoids shadowing the base
clear()and makes the reset semantics explicit.4. Optionally extract border drawing into a helper
If you want to further simplify
paintEvent(), move the border logic into a separate private method, keepingpaintEvent()focused:This keeps all visuals intact while making
paintEvent()much easier to read and maintain.