Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions src/source/page/progresspage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,24 +100,35 @@ void ProgressPage::setProgress(double dPercent)
dPercent = 0;
}

// 原先用「整数百分比是否变大」过滤更新,会导致子百分比进度(如 1.1%、1.2%)全部被丢弃,
// 从而永远不调用 calSpeedAndRemainingTime,速度与剩余时间一直停在「计算中」。
// 这里改为:进度必须单调递增(浮点),进度条仍可按四舍五入刷新。
// Accept sub-percent progress, but keep it monotonic.
if (dPercent <= m_dProgressPercent) {
qDebug() << "Progress not increased, current:" << m_dProgressPercent << "new:" << dPercent;
return;
}

m_dProgressPercent = dPercent;

const int iPercent = qMin(100, qRound(dPercent));
if (iPercent != m_iPerent) {
const bool percentChanged = (iPercent != m_iPerent);
if (percentChanged) {
m_iPerent = iPercent;
m_pProgressBar->setValue(m_iPerent); // 进度条刷新值
m_pProgressBar->update();
}

qInfo() << "Updating progress:" << dPercent << "% (bar" << m_iPerent << "%)";
// 节流:进度可能非常密集(子百分比频繁变化),每次都刷新速度/剩余时间会拖慢任务并造成显示抖动。
// 规则:整数进度变化必刷;否则最多每 200ms 刷一次速度/剩余时间。
if (!m_uiUpdateTimer.isValid()) {
m_uiUpdateTimer.start();
}
const bool timeToUpdate = (m_uiUpdateTimer.elapsed() >= 200);
if (!percentChanged && !timeToUpdate) {
return;
}
if (timeToUpdate) {
m_uiUpdateTimer.restart();
}

qDebug() << "Updating progress:" << dPercent << "% (bar" << m_iPerent << "%)";
// 刷新界面显示
double dSpeed = 0.0;
qint64 qRemainingTime = 0;
Expand Down Expand Up @@ -171,13 +182,19 @@ void ProgressPage::resetProgress()
m_iPerent = 0;
m_dProgressPercent = -1.0;
m_qConsumeTime = 0;
if (m_uiUpdateTimer.isValid()) {
m_uiUpdateTimer.invalidate();
}
}

void ProgressPage::restartTimer()
{
qDebug() << "restartTimer";
m_qConsumeTime = 0;
m_timer.restart();
if (m_uiUpdateTimer.isValid()) {
m_uiUpdateTimer.invalidate();
}
}

void ProgressPage::setPushButtonCheckable(bool a, bool b)
Expand Down
1 change: 1 addition & 0 deletions src/source/page/progresspage.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ private Q_SLOTS:
double m_dProgressPercent = -1.0;
QElapsedTimer m_timer; //计时器
qint64 m_qConsumeTime = 0; //消耗时间
QElapsedTimer m_uiUpdateTimer; // UI 刷新节流计时器(避免解压高频进度拖慢)

QString m_strArchiveName;
};
Expand Down
80 changes: 70 additions & 10 deletions src/source/tree/datatreeview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@
#include "datatreeview.h"
#include "treeheaderview.h"
#include "datamodel.h"
#include "itemviewrowhoverproxystyle.h"
#include "uitools.h"

Check warning on line 10 in src/source/tree/datatreeview.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "uitools.h" not found.

#include <DApplication>

Check warning on line 12 in src/source/tree/datatreeview.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <DApplication> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <DStyle>

Check warning on line 13 in src/source/tree/datatreeview.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <DStyle> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <DGuiApplicationHelper>

Check warning on line 14 in src/source/tree/datatreeview.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <DGuiApplicationHelper> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <QApplication>

Check warning on line 16 in src/source/tree/datatreeview.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QApplication> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QColor>

Check warning on line 17 in src/source/tree/datatreeview.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QColor> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QMouseEvent>

Check warning on line 18 in src/source/tree/datatreeview.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QMouseEvent> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QPainter>

Check warning on line 19 in src/source/tree/datatreeview.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QPainter> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QHeaderView>

Check warning on line 20 in src/source/tree/datatreeview.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QHeaderView> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QMimeData>
#include <QDebug>
#include <QScrollBar>
Expand Down Expand Up @@ -201,6 +204,11 @@
setContextMenuPolicy(Qt::CustomContextMenu); // 设置自定义右键菜单
setAcceptDrops(true);

setMouseTracking(true);
auto *hoverProxyStyle = new ItemViewRowHoverProxyStyle(QApplication::style(), this);
hoverProxyStyle->setParent(QCoreApplication::instance());
setStyle(hoverProxyStyle);

m_selectionModel = selectionModel();
}

Expand Down Expand Up @@ -247,6 +255,12 @@
void DataTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const
{
// qDebug() << "Drawing row";
Q_ASSERT(m_selectionModel);
if (!m_selectionModel) {
QTreeView::drawRow(painter, options, index);
return;
}

painter->save();
painter->setRenderHint(QPainter::Antialiasing);

Expand Down Expand Up @@ -278,23 +292,21 @@
auto margin = style->pixelMetric(DStyle::PM_ContentsMargins, &options);
//根据实际情况设置颜色,奇数行为灰色
auto palette = options.palette;
QBrush background;
QBrush zebraBrush;
bool bVis = m_pHeaderView->getpreLbl()->isVisible();
if (bVis ? (index.row() & 1) : !(index.row() & 1)) {
if(DGuiApplicationHelper::DarkType == DGuiApplicationHelper::instance()->themeType()) {
background = QColor(255, 255, 255, 12);
zebraBrush = QColor(255, 255, 255, 12);
} else {
background = palette.color(cg, DPalette::AlternateBase);
zebraBrush = palette.color(cg, DPalette::AlternateBase);
}
} else {
background = palette.color(cg, DPalette::Base);
}
if (options.state & DStyle::State_Enabled) {
if (m_selectionModel->isSelected(index)) {
background = palette.color(cg, DPalette::Highlight);
}
zebraBrush = palette.color(cg, DPalette::Base);
}

const bool selected = (options.state & DStyle::State_Enabled) && m_selectionModel->isSelected(index);
const bool hoverRow = (options.state & DStyle::State_Enabled) && index.row() == m_hoverRow && !selected;

// 绘制整行背景,高度-2以让高分屏非整数缩放比例下无被选中的蓝色细线,防止原来通过delegate绘制单元格交替颜色背景出现的高分屏非整数缩放比例下qrect精度问题导致的横向单元格间出现白色边框
QPainterPath path;
QRect rowRect { options.rect.x() - header()->offset(),
Expand All @@ -305,7 +317,30 @@
rowRect.setWidth(rowRect.width() - margin);

path.addRoundedRect(rowRect, radius, radius);
painter->fillPath(path, background);
painter->fillPath(path, zebraBrush);

if (hoverRow) {
QStyleOptionViewItem hoverOpt = options;
hoverOpt.state &= ~QStyle::State_Selected;
hoverOpt.state |= QStyle::State_MouseOver;
hoverOpt.rect = rowRect;

// Use the original base style to paint the row hover background,
// since our proxy style clears State_MouseOver to prevent per-cell hover.
painter->save();
// Keep rounded corners: style hover may be rectangular, so clip it.
painter->setClipPath(path);
if (auto *proxy = dynamic_cast<ItemViewRowHoverProxyStyle *>(this->style())) {
proxy->baseStyle()->drawPrimitive(QStyle::PE_PanelItemViewRow, &hoverOpt, painter, this);
} else {
style->drawPrimitive(QStyle::PE_PanelItemViewRow, &hoverOpt, painter, this);
}
painter->restore();
}

if (selected) {
painter->fillPath(path, palette.color(cg, DPalette::Highlight));
}

QTreeView::drawRow(painter, options, index);
// draw focus
Expand Down Expand Up @@ -475,9 +510,23 @@
DTreeView::mouseReleaseEvent(event);
}

void DataTreeView::updateHoverRowFromPosition(const QPoint &pos)
{
const QModelIndex idx = indexAt(pos);
const int newRow = idx.isValid() ? idx.row() : -1;
if (newRow != m_hoverRow) {
m_hoverRow = newRow;
viewport()->update();
}
}

void DataTreeView::mouseMoveEvent(QMouseEvent *event)
{
// qDebug() << "Mouse move at position:" << event->pos();
if (!m_isPressed) {
updateHoverRowFromPosition(event->pos());
}

if (m_isPressed) {
//最小距离为防误触和双向滑动时,只触发横向或者纵向的
int touchmindistance = 2;
Expand Down Expand Up @@ -505,6 +554,17 @@
m_lastTouchBeginPos = event->pos();
return;
}

DTreeView::mouseMoveEvent(event);
}

void DataTreeView::leaveEvent(QEvent *event)
{
if (m_hoverRow >= 0) {
m_hoverRow = -1;
viewport()->update();
}
DTreeView::leaveEvent(event);
}

void DataTreeView::keyPressEvent(QKeyEvent *event)
Expand Down
6 changes: 6 additions & 0 deletions src/source/tree/datatreeview.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@

#include <DTreeView>

#include <QStyledItemDelegate>

Check warning on line 13 in src/source/tree/datatreeview.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QStyledItemDelegate> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDir>
#include <QPoint>
#include <QTime>

#include <QEvent>

DWIDGET_USE_NAMESPACE

class DataModel;
Expand Down Expand Up @@ -78,6 +81,7 @@

void mouseReleaseEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void leaveEvent(QEvent *event) override;
/**
* @brief keyPressEvent 键盘事件 delete、enter、Alt+M
* @param event
Expand Down Expand Up @@ -107,6 +111,7 @@
* @brief resizeColumnWidth 重置列宽度
*/
void resizeColumnWidth();
void updateHoverRowFromPosition(const QPoint &pos);

Q_SIGNALS:
/**
Expand Down Expand Up @@ -155,6 +160,7 @@
private:
Qt::FocusReason m_reson;
QItemSelectionModel *m_selectionModel = nullptr;
int m_hoverRow = -1;

};

Expand Down
32 changes: 32 additions & 0 deletions src/source/tree/itemviewrowhoverproxystyle.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (C) 2022 ~ 2026 Uniontech Software Technology Co.,Ltd.
// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "itemviewrowhoverproxystyle.h"
#include "datatreeview.h"

#include <QStyleOptionViewItem>

ItemViewRowHoverProxyStyle::ItemViewRowHoverProxyStyle(QStyle *baseStyle, DataTreeView *treeView)
: QProxyStyle(baseStyle)
, m_treeView(treeView)
{
// Lifetime is managed by the creator (we typically parent to qApp).
}

void ItemViewRowHoverProxyStyle::drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option,
QPainter *painter, const QWidget *widget) const
{
if (element == QStyle::PE_PanelItemViewRow && option && m_treeView && widget == m_treeView) {
if (const auto *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option)) {
if (vopt->state.testFlag(QStyle::State_MouseOver)) {
QStyleOptionViewItem copy(*vopt);
copy.state &= ~QStyle::State_MouseOver;
QProxyStyle::drawPrimitive(element, &copy, painter, widget);
return;
}
}
}
QProxyStyle::drawPrimitive(element, option, painter, widget);
}
32 changes: 32 additions & 0 deletions src/source/tree/itemviewrowhoverproxystyle.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (C) 2022 ~ 2026 Uniontech Software Technology Co.,Ltd.
// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef ITEMVIEWROWHOVERPROXYSTYLE_H
#define ITEMVIEWROWHOVERPROXYSTYLE_H

#include <QProxyStyle>
#include <QPointer>

class DataTreeView;

/**
* Clears State_MouseOver before PE_PanelItemViewRow so DStyle does not paint
* per-cell hover; DataTreeView draws full-row hover instead (mirrors how
* selection is not double-drawn per cell).
*/
class ItemViewRowHoverProxyStyle : public QProxyStyle
{
public:
explicit ItemViewRowHoverProxyStyle(QStyle *baseStyle, DataTreeView *treeView);

protected:
void drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option,
QPainter *painter, const QWidget *widget) const override;

private:
QPointer<DataTreeView> m_treeView;
};

#endif
2 changes: 2 additions & 0 deletions src/source/tree/uncompressview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ void UnCompressView::mousePressEvent(QMouseEvent *event)
void UnCompressView:: mouseMoveEvent(QMouseEvent *event)
{
// qDebug() << "Mouse move event at position:" << event->pos();
updateHoverRowFromPosition(event->pos());

if (m_isPressed) {
// qDebug() << "Is pressed";
//最小距离为防误触和双向滑动时,只触发横向或者纵向的
Expand Down
Loading