1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
/*
* SPDX-FileCopyrightText: 2012 Peter Penz <[email protected]>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "placesitemlistwidget.h"
#include <QStyleOption>
#include <KColorScheme>
#include <Solid/Device>
#include <Solid/NetworkShare>
#define CAPACITYBAR_HEIGHT 2
#define CAPACITYBAR_MARGIN 2
#define CAPACITYBAR_CACHE_TTL 60000
PlacesItemListWidget::PlacesItemListWidget(KItemListWidgetInformant* informant, QGraphicsItem* parent) :
KStandardItemListWidget(informant, parent)
, m_drawCapacityBar(false)
{
}
PlacesItemListWidget::~PlacesItemListWidget()
{
}
bool PlacesItemListWidget::isHidden() const
{
return data().value("isHidden").toBool() ||
data().value("isGroupHidden").toBool();
}
QPalette::ColorRole PlacesItemListWidget::normalTextColorRole() const
{
return QPalette::WindowText;
}
void PlacesItemListWidget::updateCapacityBar()
{
const QString udi = data().value("udi").toString();
if (udi.isEmpty()) {
resetCapacityBar();
return;
}
const Solid::Device device = Solid::Device(udi);
if (device.isDeviceInterface(Solid::DeviceInterface::NetworkShare)
|| device.isDeviceInterface(Solid::DeviceInterface::OpticalDrive)
|| device.isDeviceInterface(Solid::DeviceInterface::OpticalDisc)) {
resetCapacityBar();
return;
}
const QUrl url = data().value("url").toUrl();
if (url.isEmpty() || m_freeSpaceInfo.job || !m_freeSpaceInfo.lastUpdated.hasExpired()) {
// No url, job running or cache is still valid.
return;
}
m_freeSpaceInfo.job = KIO::fileSystemFreeSpace(url);
connect(
m_freeSpaceInfo.job,
&KIO::FileSystemFreeSpaceJob::result,
this,
[this](KIO::Job *job, KIO::filesize_t size, KIO::filesize_t available) {
// even if we receive an error we want to refresh lastUpdated to avoid repeatedly querying in this case
m_freeSpaceInfo.lastUpdated.setRemainingTime(CAPACITYBAR_CACHE_TTL);
if (job->error()) {
return;
}
m_freeSpaceInfo.size = size;
m_freeSpaceInfo.used = size - available;
m_freeSpaceInfo.usedRatio = (qreal)m_freeSpaceInfo.used / (qreal)m_freeSpaceInfo.size;
m_drawCapacityBar = size > 0;
update();
}
);
}
void PlacesItemListWidget::resetCapacityBar()
{
m_drawCapacityBar = false;
delete m_freeSpaceInfo.job;
m_freeSpaceInfo.lastUpdated.setRemainingTime(0);
m_freeSpaceInfo.size = 0;
m_freeSpaceInfo.used = 0;
m_freeSpaceInfo.usedRatio = 0;
}
void PlacesItemListWidget::polishEvent()
{
updateCapacityBar();
QGraphicsWidget::polishEvent();
}
void PlacesItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
KStandardItemListWidget::paint(painter, option, widget);
// We check if option=nullptr since it is null when the place is dragged (Bug #430441)
if (m_drawCapacityBar && option) {
const TextInfo* textInfo = m_textInfo.value("text");
if (textInfo) { // See KStandarItemListWidget::paint() for info on why we check textInfo.
painter->save();
const QRect capacityRect(
textInfo->pos.x(),
option->rect.top() + option->rect.height() - CAPACITYBAR_HEIGHT - CAPACITYBAR_MARGIN,
qMin((qreal)option->rect.width(), selectionRect().width()) - (textInfo->pos.x() - option->rect.left()),
CAPACITYBAR_HEIGHT
);
const QPalette pal = palette();
const QPalette::ColorGroup group = isActiveWindow() ? QPalette::Active : QPalette::Inactive;
// Background
const QColor bgColor = isSelected()
? pal.color(group, QPalette::Highlight).darker(180)
: pal.color(group, QPalette::Window).darker(120);
painter->fillRect(capacityRect, bgColor);
// Fill
const QRect fillRect(capacityRect.x(), capacityRect.y(), capacityRect.width() * m_freeSpaceInfo.usedRatio, capacityRect.height());
if (m_freeSpaceInfo.usedRatio >= 0.95) { // More than 95% full!
const QColor dangerUsedColor = KColorScheme(group, KColorScheme::View).foreground(KColorScheme::NegativeText).color();
painter->fillRect(fillRect, dangerUsedColor);
} else {
const QPalette::ColorRole role = isSelected() ? QPalette::HighlightedText : QPalette::Highlight;
const QColor normalUsedColor = styleOption().palette.color(group, role);
painter->fillRect(fillRect, normalUsedColor);
}
painter->restore();
}
}
updateCapacityBar();
}
|