Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

+397
View File
@@ -0,0 +1,397 @@
/**
* @RDE_HEADER@
* Gui Plugin for Battery Monitor
* $Id$
* $HeadURL$
* $Author$
# Created by Mike Wille, NLE, 2019-01-21
*/
#include "bat_gui_plugin.h"
#include <LtsNotification/lts_notification.h>
#include <LtsSession/lts_session.h>
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <LtsWidgets/lts_message_dialog.h>
#include <LtsWidgets/lts_base_layout_widget.h>
#ifdef Q_OS_WIN
#include <Windows.h> // windows battery api
#include <wlanapi.h>
#endif
#include <QProcess>
#include <math.h>
namespace Battery
{
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session)
{
return std::make_shared<InterfaceImpl>(session);
}
InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session)
: GuiPluginBase::Interface(session, NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("BatteryGui"))
, m_noti(nullptr)
, m_notiWlan(nullptr)
, m_warnedLow(false)
, m_warnedCritical(false)
, m_issi(QString())
, m_signal(0)
{
connect(m_session, &LtsSession::LtsSession::signalDoneInitializingSession, // workaround to only receive the signal once
this, &InterfaceImpl::onInitDone);
}
void InterfaceImpl::onInitDone()
{
disconnect(m_session, &LtsSession::LtsSession::signalDoneInitializingSession,
this, nullptr); // workaround to only receive the signal once
checkWlanStatus();
}
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
{
QVector<LtsWidgets::PluginData> ret;
LtsWidgets::PluginData plData;
plData.identifier = QLatin1String("CreateBatteryNoti");
plData.createInstant = LtsWidgets::CreateInstantType::CreateInstantAndDiscardAction;
plData.directFunc = [this](const LtsWidgets::PluginData &)
{
m_noti = m_session->createNotification(QStringLiteral("BatteryMonitor"));
m_noti->setIcon(QIcon(QStringLiteral("icon:battery-unknown.svg")));
m_noti->setAction([this]()
{
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), m_noti->tooltip(), tr("Current battery status"));
});
slotCheckBatteryStatus();
QTimer *t = new QTimer(this);
t->setInterval(10000);
connect(t, &QTimer::timeout,
this, &InterfaceImpl::slotCheckBatteryStatus);
t->start();
};
ret.append(plData);
//Wlan Connection
plData.directFunc = [this](const LtsWidgets::PluginData &)
{
m_notiWlan = m_session->createNotification(QStringLiteral("TabOcWlanConnection"));
m_notiWlan->setToolTip(tr("No Wlan Connection"));
m_notiWlan->setAction([this]()
{
LtsWidgets::LtsMessageDialog::showMessage(m_session->baseLayout(), m_notiWlan->tooltip());
});
};
ret.append(plData);
connect(&m_timer, &QTimer::timeout, this, &InterfaceImpl::checkWlanStatus);
m_timer.setInterval(1000);
m_timer.start();
return ret;
}
//#define FAKE_CHARGE
#ifdef FAKE_CHARGE
static int fakeCharge = 100;
#endif
bool InterfaceImpl::getBatteryStatus(bool &hasAC, uint8_t &charge, int32_t &lifetime)
{
#ifdef FAKE_CHARGE
// substracts 10% battery charge per status update (5 secs) - turns to 100 again after hitting 0
hasAC = false;
charge = fakeCharge;
fakeCharge -= 10;
if (fakeCharge < 0)
fakeCharge = 100;
//lifetime = 9000; // 2 hours & 30 minutes (in secs)
lifetime = 1800; // 0 hours & 30 minutes (in secs)
return true;
#else
#ifdef Q_OS_WIN
SYSTEM_POWER_STATUS status;
if (!GetSystemPowerStatus(&status))
{
ERROR_LOG(m_logger) << "GetSystemPowerStatus failed";
return false;
}
hasAC = (status.ACLineStatus == 1); // The classic: Microsoft's Boolean is not boolean
charge = status.BatteryLifePercent;
lifetime = status.BatteryLifeTime;
if (charge == 255)
return false;
return true;
#else // linux
// TODO: linux
QProcess upower;
QString text;
QString arg;
upower.setProgram(QStringLiteral("upower"));
upower.setProcessChannelMode(QProcess::MergedChannels);
QStringList args;
// first check for BATTERY NAME
args << QStringLiteral("-e");
upower.setArguments(args);
upower.start();
upower.waitForStarted();
upower.waitForFinished(1000);
while( upower.canReadLine())
{
QString line = QString::fromUtf8(upower.readLine().trimmed());
if (line.contains(QStringLiteral("BAT")))
arg = line;
}
if (arg.isEmpty())
return false;
args.clear();
args << QStringLiteral("-i");
//args << QStringLiteral("/org/freedesktop/UPower/devices/battery_BAT0");
args << arg ;
upower.setArguments(args);
//std::cout << "Try Starting upower " << upower.arguments().join(" ").toStdString()<< std::endl;
upower.start();
upower.waitForStarted();
upower.waitForFinished(1000);
if (!upower.canReadLine())
return false;
while( upower.canReadLine())
{
const QString &line = QString::fromUtf8(upower.readLine().trimmed());
// std::cout << "line: " << line.toStdString() <<std::endl;
if (line.startsWith(QStringLiteral("state")))
{
QStringList parts = line.split(QLatin1Char(':'));
if (parts.size() > 1)
{
if (parts.at(1).contains(QStringLiteral("discharging")))
hasAC = false;
else
hasAC = true;
}
}
if (line.contains(QStringLiteral(" to ")))
{
QStringList parts = line.split(QLatin1Char(':'));
if (parts.size() > 1)
{
text = parts.at(1);
text = text.trimmed();
QStringList time = text.split(QLatin1Char(' '));
if (time.size() > 1)
{
QString timeinX = time.at(0);
int p1 = 0;
int p2 = 0;
QStringList timeSplitt = timeinX.split(QLatin1Char('.'));
if (timeSplitt.size() > 1)
{
p2 = timeSplitt.at(1).toInt();
}
p1 = timeSplitt.at(0).toInt();
if (time.at(1).contains(QStringLiteral("minutes")))
{
p1 *=60;
p2 = (60/10*p2);
}
else
{
p1 = p1*60*60;
p2 = ((60/10)*p2)*60;
}
lifetime = p1 + p2;
}
}
}
if (line.startsWith(QStringLiteral("percentage")))
{
QStringList parts = line.split(QLatin1Char(':'));
if (parts.size() > 1)
{
QString chargeString = parts.at(1);
chargeString.chop(1);
charge = chargeString.toInt();
}
}
}
//std::cout << "HAS AC: " << hasAC << " percentage: " << charge << " STATE: " << text.toStdString() << " Lifetime: " << lifetime << std::endl;
DEBUG_LOG(m_logger) << "HAS AC: " << hasAC << " percentage: " << charge << " STATE: " << text.toStdString() << " Lifetime: " << lifetime << " seconds";
return true;
#endif // end linux
#endif
}
void InterfaceImpl::checkWlanStatus()
{
bool bConnected = false;
#ifdef Q_OS_WIN
HANDLE hClient;
DWORD NegociationVersion;
DWORD dwResult = WlanOpenHandle(WLAN_API_VERSION, nullptr, &NegociationVersion, &hClient);
if (dwResult == ERROR_SUCCESS)
{
PWLAN_INTERFACE_INFO_LIST pIfList = nullptr;
dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList);
if (dwResult == ERROR_SUCCESS)
{
for (DWORD i = 0; i < pIfList->dwNumberOfItems; i++)
{
const auto &ifInfo = pIfList->InterfaceInfo[i];
PWLAN_AVAILABLE_NETWORK_LIST pBssList = nullptr;
dwResult = WlanGetAvailableNetworkList(hClient, &ifInfo.InterfaceGuid,
0, nullptr, &pBssList);
if (dwResult == ERROR_SUCCESS)
{
for (DWORD j = 0; j < pBssList->dwNumberOfItems; j++) {
const auto &bssEntry = pBssList->Network[j];
if (bssEntry.dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED)
{
bConnected = true;
m_issi = QString::fromLocal8Bit(reinterpret_cast<const char*>(&bssEntry.dot11Ssid.ucSSID[0]));
m_signal = bssEntry.wlanSignalQuality;
break;
}
}
}
WlanFreeMemory(pBssList);
if (bConnected)
break;
}
WlanFreeMemory(pIfList);
}
WlanCloseHandle(hClient, nullptr);
}
#endif
setWlanStatus(bConnected);
}
void InterfaceImpl::slotCheckBatteryStatus()
{
if (m_noti == nullptr)
return;
bool hasAC = false;
uint8_t charge = 255;
int32_t lifetime = 0;
bool success = getBatteryStatus(hasAC, charge, lifetime);
QString statusText;
QString filename;
if (!success)
{
statusText = tr("unknown");
filename = QStringLiteral("icon:battery-unknown.svg");
}
else
{
int chargeFile = 0;
if (charge < 11) // this '11' thing ruins the easy 4-liner I had here first..
chargeFile = 0;
else if (charge < 21)
chargeFile = 20;
else if (charge < 41)
chargeFile = 40;
else if (charge < 61)
chargeFile = 60;
else if (charge < 81)
chargeFile = 80;
else
chargeFile = 100;
filename = QStringLiteral("icon:battery-%1-%2.svg")
.arg(QString::number(chargeFile),
hasAC ? QStringLiteral("charging") : QStringLiteral("discharging"));
if (hasAC)
statusText = tr("Charging");
else
statusText = tr("Discharging");
statusText += QStringLiteral(", ");
statusText += QString::number(charge);
statusText += QStringLiteral("%");
statusText += QStringLiteral(" - %1 hour(s) and %2 minute(s) estimated remaining").arg(lifetime / 60 / 60).arg((lifetime / 60) % 60);
}
QString tooltip(tr("Battery status: %1").arg(statusText));
m_noti->setIcon(QIcon(filename));
m_noti->setToolTip(tooltip);
if (!hasAC)
{
if (charge < 21 && !m_warnedLow)
{
m_warnedLow = true;
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), tr("Battery charge is low, please plug the AC adapter in soon"));
}
else if (charge < 11 && !m_warnedCritical)
{
m_warnedCritical = true;
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), tr("Battery charge is critical, please plug the AC adapter in now!"));
}
}
else
{
m_warnedLow = false;
m_warnedCritical = false;
}
}
void InterfaceImpl::setWlanStatus(bool isConnected)
{
if (!m_notiWlan)
return;
if (isConnected)
{
m_notiWlan->setToolTip(tr("Connected to Wlan %1 \nSignal strength %2 %").arg(m_issi).arg(m_signal));
if (m_signal > 0)
{
if (m_signal > 85)
m_notiWlan->setIcon(QIcon(QStringLiteral("icon:wireless-green.svg")));
else if (m_signal > 70)
m_notiWlan->setIcon(QIcon(QStringLiteral("icon:wireless-yellow.svg")));
else
m_notiWlan->setIcon(QIcon(QStringLiteral("icon:wireless-orange.svg")));
}
else
m_notiWlan->setIcon(QIcon(QStringLiteral("icon:wireless-green.svg")));
}
else
{
m_notiWlan->setToolTip(tr("No Wlan Connection"));
m_notiWlan->setIcon(QIcon(QStringLiteral("icon:wireless-red.svg")));
}
}
} // namespace Battery