1 #include "widget/wbattery.h"
2
3 #include <QStyleOption>
4 #include <QStylePainter>
5
6 #include "moc_wbattery.cpp"
7 #include "util/battery/battery.h"
8 #include "util/math.h"
9
WBattery(QWidget * parent)10 WBattery::WBattery(QWidget* parent)
11 : WWidget(parent),
12 m_pBattery(Battery::getBattery(this)) {
13 setVisible(false);
14 if (m_pBattery) {
15 connect(m_pBattery.data(),
16 &Battery::stateChanged,
17 this,
18 &WBattery::slotStateChanged);
19 }
20 }
21
setup(const QDomNode & node,const SkinContext & context)22 void WBattery::setup(const QDomNode& node, const SkinContext& context) {
23 QDomElement backPath = context.selectElement(node, "BackPath");
24 if (!backPath.isNull()) {
25 setPixmap(&m_pPixmapBack,
26 context.getPixmapSource(backPath),
27 context.selectScaleMode(backPath, Paintable::TILE),
28 context.getScaleFactor());
29 }
30
31 QDomElement chargedPath = context.selectElement(node, "PixmapCharged");
32 if (!chargedPath.isNull()) {
33 setPixmap(&m_pPixmapCharged,
34 context.getPixmapSource(chargedPath),
35 context.selectScaleMode(chargedPath, Paintable::TILE),
36 context.getScaleFactor());
37 }
38
39 int numberStates = context.selectInt(node, "NumberStates");
40 if (numberStates < 0) {
41 numberStates = 0;
42 }
43
44 m_chargingPixmaps.resize(numberStates);
45 m_dischargingPixmaps.resize(numberStates);
46
47 QDomElement pixmapsCharging = context.selectElement(node, "PixmapsCharging");
48 if (!pixmapsCharging.isNull()) {
49 // TODO(XXX) inline SVG support via context.getPixmapSource.
50 QString chargingPath = context.nodeToString(pixmapsCharging);
51 Paintable::DrawMode mode = context.selectScaleMode(pixmapsCharging,
52 Paintable::TILE);
53 for (int i = 0; i < m_chargingPixmaps.size(); ++i) {
54 PixmapSource source = context.getPixmapSource(chargingPath.arg(i));
55 setPixmap(&m_chargingPixmaps[i], source, mode, context.getScaleFactor());
56 }
57 }
58
59 QDomElement pixmapsDischarging = context.selectElement(node, "PixmapsDischarging");
60 if (!pixmapsDischarging.isNull()) {
61 // TODO(XXX) inline SVG support via context.getPixmapSource.
62 QString dischargingPath = context.nodeToString(pixmapsDischarging);
63 Paintable::DrawMode mode = context.selectScaleMode(pixmapsDischarging,
64 Paintable::TILE);
65 for (int i = 0; i < m_dischargingPixmaps.size(); ++i) {
66 PixmapSource source = context.getPixmapSource(dischargingPath.arg(i));
67 setPixmap(&m_dischargingPixmaps[i], source, mode, context.getScaleFactor());
68 }
69 }
70
71 if (m_pBattery) {
72 m_pBattery->update();
73 }
74 }
75
formatMinutes(int minutes)76 QString formatMinutes(int minutes) {
77 if (minutes < 60) {
78 return QObject::tr("%1 minutes").arg(minutes);
79 }
80 return QObject::tr("%1:%2").arg(minutes/60)
81 .arg(minutes%60, 2, 10, QChar('0'));
82 }
83
pixmapIndexFromPercentage(double dPercentage,int numPixmaps)84 int pixmapIndexFromPercentage(double dPercentage, int numPixmaps) {
85 // See WDisplay::getActivePixmapIndex for more info on this.
86 int result = static_cast<int>(dPercentage / 100.0 * numPixmaps);
87 result = math_min(numPixmaps - 1, math_max(0, result));
88 return result;
89 }
90
formatTooltip(double dPercentage)91 QString WBattery::formatTooltip(double dPercentage) {
92 return QString::number(dPercentage, 'f', 0) + QStringLiteral("%");
93 }
94
slotStateChanged()95 void WBattery::slotStateChanged() {
96 int minutesLeft = m_pBattery ? m_pBattery->getMinutesLeft() : 0;
97 Battery::ChargingState chargingState = m_pBattery ?
98 m_pBattery->getChargingState() : Battery::UNKNOWN;
99 double dPercentage = m_pBattery ? m_pBattery->getPercentage() : 0;
100
101 if (chargingState != Battery::UNKNOWN) {
102 setBaseTooltip(formatTooltip(dPercentage));
103 }
104
105 m_pCurrentPixmap.clear();
106 switch (chargingState) {
107 case Battery::CHARGING:
108 if (!m_chargingPixmaps.isEmpty()) {
109 m_pCurrentPixmap = m_chargingPixmaps[
110 pixmapIndexFromPercentage(dPercentage,
111 m_chargingPixmaps.size())];
112 }
113 if (minutesLeft != Battery::TIME_UNKNOWN) {
114 appendBaseTooltip("\n" + tr("Time until charged: %1")
115 .arg(formatMinutes(minutesLeft)));
116 }
117 break;
118 case Battery::DISCHARGING:
119 if (!m_dischargingPixmaps.isEmpty()) {
120 m_pCurrentPixmap = m_dischargingPixmaps[
121 pixmapIndexFromPercentage(dPercentage,
122 m_dischargingPixmaps.size())];
123 }
124 if (minutesLeft != Battery::TIME_UNKNOWN) {
125 appendBaseTooltip("\n" + tr("Time left: %1")
126 .arg(formatMinutes(minutesLeft)));
127 }
128 break;
129 case Battery::CHARGED:
130 m_pCurrentPixmap = m_pPixmapCharged;
131 appendBaseTooltip("\n" + tr("Battery fully charged."));
132 break;
133 default:
134 break;
135 }
136 setVisible(chargingState != Battery::UNKNOWN);
137
138 // call parent's update() to show changes, this should call
139 // QWidget::update()
140 WWidget::update();
141 }
142
setPixmap(PaintablePointer * ppPixmap,const PixmapSource & source,Paintable::DrawMode mode,double scaleFactor)143 void WBattery::setPixmap(PaintablePointer* ppPixmap, const PixmapSource& source,
144 Paintable::DrawMode mode, double scaleFactor) {
145 PaintablePointer pPixmap = WPixmapStore::getPaintable(source, mode, scaleFactor);
146 if (pPixmap.isNull() || pPixmap->isNull()) {
147 qDebug() << this << "Error loading pixmap:" << source.getPath();
148 } else {
149 *ppPixmap = pPixmap;
150 if (mode == Paintable::FIXED) {
151 setFixedSize(pPixmap->size());
152 }
153 }
154 }
155
paintEvent(QPaintEvent *)156 void WBattery::paintEvent(QPaintEvent* /*unused*/) {
157 QStyleOption option;
158 option.initFrom(this);
159 QStylePainter p(this);
160 p.drawPrimitive(QStyle::PE_Widget, option);
161
162 if (m_pPixmapBack) {
163 m_pPixmapBack->draw(rect(), &p);
164 }
165
166 if (m_pCurrentPixmap) {
167 m_pCurrentPixmap->draw(rect(), &p);
168 }
169 }
170