add ability to wrap lines

rename AWToolTip to AWDataAggregator object
drop hasOutput property from ExtScript
fix some bugs in AWKeysAggregator
This commit is contained in:
arcan1s
2015-09-12 02:32:31 +03:00
parent 0298a8c088
commit 0ba74b3130
18 changed files with 529 additions and 435 deletions

View File

@ -15,15 +15,18 @@
* along with awesome-widgets. If not, see http://www.gnu.org/licenses/ *
***************************************************************************/
#include "awtooltip.h"
#include "awdataaggregator.h"
#include <KI18n/KLocalizedString>
#include <QBuffer>
#include <math.h>
#include "awactions.h"
#include "awdebug.h"
AWToolTip::AWToolTip(QObject *parent, QVariantMap settings)
AWDataAggregator::AWDataAggregator(QObject *parent, QVariantMap settings)
: QObject(parent),
configuration(qvariant_cast<QVariantHash>(settings))
{
@ -37,6 +40,8 @@ AWToolTip::AWToolTip(QObject *parent, QVariantMap settings)
toolTipView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
toolTipView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
enablePopup = configuration[QString("notify")].toBool();
counts += configuration[QString("cpuTooltip")].toInt();
counts += configuration[QString("cpuclTooltip")].toInt();
counts += configuration[QString("memTooltip")].toInt();
@ -67,7 +72,7 @@ AWToolTip::AWToolTip(QObject *parent, QVariantMap settings)
}
AWToolTip::~AWToolTip()
AWDataAggregator::~AWDataAggregator()
{
qCDebug(LOG_AW);
@ -75,26 +80,36 @@ AWToolTip::~AWToolTip()
}
void AWToolTip::dataUpdate(QHash<QString, QString> values)
void AWDataAggregator::dataUpdate(QHash<QString, QString> values)
{
qCDebug(LOG_AW);
// battery update requires info is AC online or not
setData(QString("batTooltip"), values[QString("bat")].toFloat(),
values[QString("ac")] == configuration[QString("acOnline")]);
setData(values[QString("ac")] == configuration[QString("acOnline")],
QString("batTooltip"), values[QString("bat")].toFloat());
// usual case
setData(QString("cpuTooltip"), values[QString("cpu")].toFloat());
setData(QString("cpuTooltip"), values[QString("cpu")].toFloat(), 90.0);
setData(QString("cpuclTooltip"), values[QString("cpucl")].toFloat());
setData(QString("memTooltip"), values[QString("mem")].toFloat());
setData(QString("swapTooltip"), values[QString("swap")].toFloat());
setData(QString("memTooltip"), values[QString("mem")].toFloat(), 90.0);
setData(QString("swapTooltip"), values[QString("swap")].toFloat(), 0.0);
setData(QString("downTooltip"), values[QString("downkb")].toFloat());
setData(QString("upTooltip"), values[QString("upkb")].toFloat());
// additional check for network device
[this](const QString value) {
checkValue(QString("netdev"), currentNetworkDevice, value);
currentNetworkDevice = value;
}(values[QString("netdev")]);
// additional check for GPU load
[this](const float value) {
checkValue(QString("gpu"), value, 90.0);
currentGPULoad = value;
}(values[QString("gpu")].toFloat());
emit(toolTipPainted(htmlImage()));
emit(toolTipPainted(htmlImage(tooltipImage())));
}
QSize AWToolTip::getSize() const
QSize AWDataAggregator::getTooltipSize() const
{
qCDebug(LOG_AW);
@ -102,21 +117,20 @@ QSize AWToolTip::getSize() const
}
QString AWToolTip::htmlImage()
QString AWDataAggregator::htmlImage(const QPixmap source)
{
qCDebug(LOG_AW);
QPixmap rawImage = image();
QByteArray byteArray;
QBuffer buffer(&byteArray);
rawImage.save(&buffer, "PNG");
source.save(&buffer, "PNG");
return byteArray.isEmpty() ? QString() :
QString("<img src=\"data:image/png;base64,%1\"/>").arg(QString(byteArray.toBase64()));
}
QPixmap AWToolTip::image()
QPixmap AWDataAggregator::tooltipImage()
{
qCDebug(LOG_AW);
@ -129,53 +143,133 @@ QPixmap AWToolTip::image()
QBrush(QColor(configuration[QString("tooltipBackground")].toString())) :
QBrush(Qt::NoBrush));
bool down = false;
for (int i=0; i<requiredKeys.count(); i++) {
float normX = 100.0 / static_cast<float>(data[requiredKeys.at(i)].count());
float normY = 100.0 / (1.5 * boundaries[requiredKeys.at(i)]);
if (requiredKeys.at(i) != QString("batTooltip"))
pen.setColor(QColor(configuration[QString("%1Color").arg(requiredKeys.at(i))].toString()));
float shift = i * 100.0;
foreach(QString key, requiredKeys) {
// create frame
float normX = 100.0 / static_cast<float>(data[key].count());
float normY = 100.0 / (1.5 * boundaries[key]);
float shift = requiredKeys.indexOf(key) * 100.0;
if (down) shift -= 100.0;
for (int j=0; j<data[requiredKeys.at(i)].count()-1; j++) {
// apply pen color
if (key != QString("batTooltip"))
pen.setColor(QColor(configuration[QString("%1Color").arg(key)].toString()));
// paint data inside frame
for (int j=0; j<data[key].count()-1; j++) {
// some magic here
float x1 = j * normX + shift;
float y1 = - fabs(data[requiredKeys.at(i)].at(j)) * normY + 5.0;
float y1 = - fabs(data[key].at(j)) * normY + 5.0;
float x2 = (j + 1) * normX + shift;
float y2 = - fabs(data[requiredKeys.at(i)].at(j+1)) * normY + 5.0;
if (requiredKeys.at(i) == QString("batTooltip")) {
if (data[requiredKeys.at(i)].at(j+1) > 0)
float y2 = - fabs(data[key].at(j+1)) * normY + 5.0;
if (key == QString("batTooltip")) {
if (data[key].at(j+1) > 0)
pen.setColor(QColor(configuration[QString("batTooltipColor")].toString()));
else
pen.setColor(QColor(configuration[QString("batInTooltipColor")].toString()));
}
toolTipScene->addLine(x1, y1, x2, y2, pen);
}
if (requiredKeys.at(i) == QString("downTooltip")) down = true;
if (key == QString("downTooltip")) down = true;
}
return toolTipView->grab();
}
void AWToolTip::setData(const QString source, float value, const bool dontInvert)
void AWDataAggregator::checkValue(const QString source, const float value, const float extremum) const
{
qCDebug(LOG_AW);
qCDebug(LOG_AW) << "Notification source" << source;
qCDebug(LOG_AW) << "Value" << value;
qCDebug(LOG_AW) << "Called with extremum" << extremum;
if ((enablePopup) && (value > extremum) && (data[source].last() < extremum))
return AWActions::sendNotification(QString("event"), notificationText(source, value));
}
void AWDataAggregator::checkValue(const QString source, const QString current, const QString received) const
{
qCDebug(LOG_AW);
qCDebug(LOG_AW) << "Notification source" << source;
qCDebug(LOG_AW) << "Current value" << current;
qCDebug(LOG_AW) << "Received value" << received;
if ((enablePopup) && (current != received))
return AWActions::sendNotification(QString("event"), notificationText(source, received));
}
QString AWDataAggregator::notificationText(const QString source, const float value) const
{
qCDebug(LOG_AW);
qCDebug(LOG_AW) << "Notification source" << source;
qCDebug(LOG_AW) << "Value" << value;
QString output;
if (source == QString("batTooltip")) {
if (value > 0.0)
output = i18n("AC online");
else
output = i18n("AC offline");
} else if (source == QString("cpuTooltip")) {
output = i18n("High CPU load");
} else if (source == QString("memTooltip")) {
output = i18n("High memory usage");
} else if (source == QString("swapTooltip")) {
output = i18n("Swap is used");
} else if (source == QString("gpu")) {
output = i18n("High GPU load");
}
return output;
}
QString AWDataAggregator::notificationText(const QString source, const QString value) const
{
qCDebug(LOG_AW);
qCDebug(LOG_AW) << "Notification source" << source;
qCDebug(LOG_AW) << "Value" << value;
QString output;
if (source == QString("netdev")) {
output = i18n("Network device has been changed to %1", value);
}
return output;
}
void AWDataAggregator::setData(const QString source, float value, const float extremum)
{
qCDebug(LOG_AW);
qCDebug(LOG_AW) << "Source" << source;
qCDebug(LOG_AW) << "Value" << value;
qCDebug(LOG_AW) << "Do not invert value" << dontInvert;
qCDebug(LOG_AW) << "Called with extremum" << extremum;
if (data[source].count() == 0)
data[source].append(0.0);
else if (data[source].count() > configuration[QString("tooltipNumber")].toInt())
data[source].takeFirst();
data[source].removeFirst();
if (isnan(value)) value = 0.0;
// invert values for different battery colours
data[source].append(dontInvert ? value : -value);
// notifications
checkValue(source, value, extremum);
data[source].append(value);
if (source == QString("downTooltip")) {
QList<float> netValues = data[QString("downTooltip")] + data[QString("upTooltip")];
boundaries[QString("downTooltip")] = 1.2 * *std::max_element(netValues.cbegin(), netValues.cend());
boundaries[QString("upTooltip")] = boundaries[QString("downTooltip")];
}
}
void AWDataAggregator::setData(const bool dontInvert, const QString source, float value)
{
qCDebug(LOG_AW);
qCDebug(LOG_AW) << "Do not invert value" << dontInvert;
// invert values for different battery colours
value = dontInvert ? value : -value;
return setData(source, value, 0.0);
}

View File

@ -27,16 +27,16 @@
#include <QVariant>
class AWToolTip : public QObject
class AWDataAggregator : public QObject
{
Q_OBJECT
public:
explicit AWToolTip(QObject *parent = nullptr, QVariantMap settings = QVariantMap());
virtual ~AWToolTip();
QSize getSize() const;
QString htmlImage();
QPixmap image();
explicit AWDataAggregator(QObject *parent = nullptr, QVariantMap settings = QVariantMap());
virtual ~AWDataAggregator();
QSize getTooltipSize() const;
QString htmlImage(const QPixmap source);
QPixmap tooltipImage();
signals:
void updateData(QHash<QString, QString> values);
@ -49,13 +49,21 @@ private:
// ui
QGraphicsScene *toolTipScene = nullptr;
QGraphicsView *toolTipView = nullptr;
void setData(const QString source, float value,
const bool dontInvert = true);
void checkValue(const QString source, const float value, const float extremum) const;
void checkValue(const QString source, const QString current, const QString received) const;
QString notificationText(const QString source, const float value) const;
QString notificationText(const QString source, const QString value) const;
void setData(const QString source, float value, const float extremum = -1.0);
// different signature for battery device
void setData(const bool dontInvert, const QString source, float value);
// variables
int counts = 0;
QVariantHash configuration;
float currentGPULoad = 0.0;
QString currentNetworkDevice;
QHash<QString, float> boundaries;
QHash<QString, QList<float>> data;
bool enablePopup = false;
QStringList requiredKeys;
QSize size;
};

View File

@ -49,17 +49,20 @@ QString AWKeysAggregator::formater(const QVariant data, const QString key) const
QLocale loc = m_translate ? QLocale::system() : QLocale::c();
// case block
switch (m_formater[key]) {
case Float:
output = QString("%1").arg(data.toFloat(), 5, 'f', 1);
break;
case FloatTwoSymbols:
output = QString("%1").arg(data.toFloat(), 5, 'f', 2);
break;
case Integer:
output = QString("%1").arg(data.toFloat(), 4, 'f', 0);
break;
case IntegerThree:
output = QString("%1").arg(data.toFloat(), 3, 'f', 0);
break;
case Float:
output = QString("%1").arg(data.toFloat(), 5, 'f', 1);
break;
case FloatTwoSymbols:
output = QString("%1").arg(data.toFloat(), 5, 'f', 2);
case List:
output = data.toStringList().join(QChar(','));
break;
case ACFormat:
output = data.toBool() ? m_acOnline : m_acOffline;
@ -87,6 +90,9 @@ QString AWKeysAggregator::formater(const QVariant data, const QString key) const
case Temperature:
output = QString("%1").arg(temperature(data.toFloat()), 5, 'f', 1);
break;
case Time:
output = data.toDateTime().toString();
break;
case TimeCustom:
output = m_customTime;
[&output, loc, this](const QDateTime dt) {
@ -201,8 +207,8 @@ void AWKeysAggregator::setTranslate(const bool translate)
}
// TODO calculate: down, up, downunits, upunits, mem, swap
void AWKeysAggregator::registerSource(const QString source, const QString units)
// HACK units required to define should the value be calculated as temperature or fan data
QStringList AWKeysAggregator::registerSource(const QString source, const QString units)
{
qCDebug(LOG_AW);
qCDebug(LOG_AW) << "Source" << source;
@ -245,7 +251,8 @@ void AWKeysAggregator::registerSource(const QString source, const QString units)
} else if (source.contains(cpuclRegExp)) {
// cpucls
QString key = source;
key.remove(QString("cpu/")).remove(QString("/clock"));
key.remove(QString("cpu/cpu")).remove(QString("/clock"));
key = QString("cpucl%1").arg(key);
m_map[source] = key;
m_formater[key] = Integer;
} else if (source.startsWith(QString("custom"))) {
@ -270,16 +277,22 @@ void AWKeysAggregator::registerSource(const QString source, const QString units)
// read speed
QString device = source;
device.remove(QString("/Rate/rblk"));
QString key = QString("hddr%1").arg(m_devices[QString("disk")].indexOf(device));
m_map[source] = key;
m_formater[key] = Integer;
int index = m_devices[QString("disk")].indexOf(device);
if (index > -1) {
QString key = QString("hddr%1").arg(index);
m_map[source] = key;
m_formater[key] = Integer;
}
} else if (source.contains(hddwRegExp)) {
// write speed
QString device = source;
device.remove(QString("/Rate/wblk"));
QString key = QString("hddw%1").arg(m_devices[QString("disk")].indexOf(device));
m_map[source] = key;
m_formater[key] = Integer;
int index = m_devices[QString("disk")].indexOf(device);
if (index > -1) {
QString key = QString("hddw%1").arg(index);
m_map[source] = key;
m_formater[key] = Integer;
}
} else if (source == QString("gpu/load")) {
// gpu load
m_map[source] = QString("gpu");
@ -292,42 +305,52 @@ void AWKeysAggregator::registerSource(const QString source, const QString units)
// fill level
QString device = source;
device.remove(QString("partitions")).remove(QString("/filllevel"));
QString key = QString("hdd%1").arg(m_devices[QString("mount")].indexOf(device));
m_map[source] = key;
m_formater[key] = Float;
int index = m_devices[QString("mount")].indexOf(device);
if (index > -1) {
QString key = QString("hdd%1").arg(index);
m_map[source] = key;
m_formater[key] = Float;
}
} else if (source.contains(mountFreeRegExp)) {
// free space
QString device = source;
device.remove(QString("partitions")).remove(QString("/freespace"));
int index = m_devices[QString("mount")].indexOf(device);
// mb
QString key = QString("hddfreemb%1").arg(index);
m_map[source] = key;
m_formater[key] = MemMBFormat;
// gb
key = QString("hddfreegb%1").arg(index);
m_map.insertMulti(source, key);
m_formater[key] = MemGBFormat;
if (index > -1) {
// mb
QString key = QString("hddfreemb%1").arg(index);
m_map[source] = key;
m_formater[key] = MemMBFormat;
// gb
key = QString("hddfreegb%1").arg(index);
m_map.insertMulti(source, key);
m_formater[key] = MemGBFormat;
}
} else if (source.contains(mountUsedRegExp)) {
// used
QString device = source;
device.remove(QString("partitions")).remove(QString("/usedspace"));
int index = m_devices[QString("mount")].indexOf(device);
// mb
QString key = QString("hddmb%1").arg(index);
m_map[source] = key;
m_formater[key] = MemMBFormat;
// gb
key = QString("hddgb%1").arg(index);
m_map.insertMulti(source, key);
m_formater[key] = MemGBFormat;
if (index > -1) {
// mb
QString key = QString("hddmb%1").arg(index);
m_map[source] = key;
m_formater[key] = MemMBFormat;
// gb
key = QString("hddgb%1").arg(index);
m_map.insertMulti(source, key);
m_formater[key] = MemGBFormat;
}
} else if (source.startsWith(QString("hdd/temperature"))) {
// hdd temperature
QString device = source;
device.remove(QString("hdd/temperature"));
QString key = QString("hddtemp%1").arg(m_devices[QString("hdd")].indexOf(device));
m_map[source] = key;
m_formater[key] = Temperature;
int index = m_devices[QString("hdd")].indexOf(device);
if (index > -1) {
QString key = QString("hddtemp%1").arg(index);
m_map[source] = key;
m_formater[key] = Temperature;
}
} else if (source.startsWith(QString("cpu/system/loadavg"))) {
// load average
QString time = source;
@ -366,20 +389,21 @@ void AWKeysAggregator::registerSource(const QString source, const QString units)
} else if (source.contains(netRegExp)) {
// network speed
QString type = source.contains(QString("receiver")) ? QString("down") : QString("up");
// device name
int index = m_devices[QString("net")].indexOf(source.split(QChar('/'))[2]);
// kb
QString key = QString("%1kb%2").arg(type).arg(index);
m_map[source] = key;
m_formater[key] = Integer;
// smart
key = QString("%1%2").arg(type).arg(index);
m_map.insertMulti(source, key);
m_formater[key] = NetSmartFormat;
// units
key = QString("%1units%2").arg(type).arg(index);
m_map.insertMulti(source, key);
m_formater[key] = NetSmartUnits;
if (index > -1) {
// kb
QString key = QString("%1kb%2").arg(type).arg(index);
m_map[source] = key;
m_formater[key] = Integer;
// smart
key = QString("%1%2").arg(type).arg(index);
m_map.insertMulti(source, key);
m_formater[key] = NetSmartFormat;
// units
key = QString("%1units%2").arg(type).arg(index);
m_map.insertMulti(source, key);
m_formater[key] = NetSmartUnits;
}
} else if (source.startsWith(QString("upgrade"))) {
// package manager
QString key = source;
@ -399,7 +423,7 @@ void AWKeysAggregator::registerSource(const QString source, const QString units)
} else if (source == QString("ps/running/list")) {
// list of running processes
m_map[source] = QString("ps");
m_formater[QString("ps")] = NoFormat;
m_formater[QString("ps")] = List;
} else if (source == QString("ps/total/count")) {
// total processes count
m_map[source] = QString("pstotal");
@ -427,14 +451,19 @@ void AWKeysAggregator::registerSource(const QString source, const QString units)
m_map.insertMulti(source, QString("swapgb"));
m_formater[QString("swapgb")] = MemGBFormat;
} else if (source.startsWith(QString("lmsensors/"))) {
// temperature m_devices
QString key = QString("temp%1").arg(m_devices[QString("temp")].indexOf(source));
m_map[source] = key;
m_formater[key] = units == QString("°C") ? Temperature : Float;
// temperature
int index = m_devices[QString("temp")].indexOf(source);
// FIXME on DE initialization there are no units key
if (units.isEmpty()) return QStringList() << QString("temp%1").arg(index);
if (index > -1) {
QString key = QString("temp%1").arg(index);
m_map[source] = key;
m_formater[key] = units == QString("°C") ? Temperature : Integer;
}
} else if (source == QString("Local")) {
// time
m_map[source] = QString("time");
m_formater[QString("time")] = NoFormat;
m_formater[QString("time")] = Time;
// custom time
m_map.insertMulti(source, QString("ctime"));
m_formater[QString("ctime")] = TimeCustom;
@ -467,6 +496,8 @@ void AWKeysAggregator::registerSource(const QString source, const QString units)
m_map[source] = key;
m_formater[key] = NoFormat;
}
return keyFromSource(source);
}

View File

@ -38,10 +38,11 @@ class AWKeysAggregator : public QObject
enum FormaterType {
// general formaters
NoFormat = 0,
Integer,
IntegerThree,
Float,
FloatTwoSymbols,
Integer,
IntegerThree,
List,
// unit specific formaters
ACFormat,
MemGBFormat,
@ -49,6 +50,7 @@ class AWKeysAggregator : public QObject
NetSmartFormat,
NetSmartUnits,
Temperature,
Time,
TimeCustom,
TimeISO,
TimeLong,
@ -73,7 +75,7 @@ public:
void setTranslate(const bool translate);
public slots:
void registerSource(const QString source, const QString units);
QStringList registerSource(const QString source, const QString units);
private:
float temperature(const float temp) const;