feat(power): switch power modes through power-profiles-daemon and add Balanced

main
reionwong 4 weeks ago
parent dc6bbefbf7
commit a0be4c2f0b

@ -0,0 +1,17 @@
<svg width="64" height="64" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="background" x1="32" x2="32" y1="64" y2="0" gradientUnits="userSpaceOnUse">
<stop stop-color="#1e82f0" offset="0"/>
<stop stop-color="#64beff" offset="1"/>
</linearGradient>
</defs>
<rect width="64" height="64" fill="url(#background)"/>
<g fill="none" stroke="#fff" stroke-linecap="round" stroke-width="6">
<path d="m13 42a19 19 0 0 1 38 0" opacity=".35"/>
<path d="m13 42a19 19 0 0 1 19-19" opacity=".85"/>
</g>
<g fill="#fff" opacity=".85">
<path d="m32 42v-12" stroke="#fff" stroke-linecap="round" stroke-width="3"/>
<circle cx="32" cy="42" r="3.5"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 695 B

@ -19,12 +19,22 @@
#include "powermanager.h"
#include <QDBusArgument>
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusMessage>
#include <QDBusPendingCallWatcher>
#include <QDBusPendingReply>
#include <QDBusVariant>
#include <QSettings>
namespace {
constexpr auto s_powerGroup = "Power";
const QString s_profilesService = QStringLiteral("org.freedesktop.UPower.PowerProfiles");
const QString s_profilesPath = QStringLiteral("/org/freedesktop/UPower/PowerProfiles");
const QString s_propertiesInterface = QStringLiteral("org.freedesktop.DBus.Properties");
int normalizedTimeout(int timeout)
{
return timeout < 0 ? -1 : qMax(1, timeout);
@ -67,12 +77,11 @@ void callPowerManager(const QString &method, const QVariant &value)
PowerManager::PowerManager(QObject *parent)
: QObject(parent)
, m_iface("com.cutefish.Services", "/com/cutefish/Services/Power",
"com.cutefish.Services.Power", QDBusConnection::sessionBus())
, m_mode(-1)
{
if (m_iface.isValid())
m_mode = m_iface.property("mode").toInt();
QDBusConnection::systemBus().connect(s_profilesService, s_profilesPath, s_propertiesInterface,
QStringLiteral("PropertiesChanged"), this,
SLOT(onProfilePropertiesChanged(QString, QVariantMap, QStringList)));
loadProfileProperties();
QSettings settings(QSettings::UserScope, "cutefish", "power");
m_batteryScreenOff = readTimeout(settings, QStringLiteral("BatteryScreenOff"),
@ -84,21 +93,101 @@ PowerManager::PowerManager(QObject *parent)
settings.endGroup();
}
int PowerManager::mode() const
QString PowerManager::profile() const
{
return m_mode;
return m_profile;
}
void PowerManager::setMode(int mode)
void PowerManager::setProfile(const QString &profile)
{
if (m_mode == mode)
if (m_profile == profile || !m_profiles.contains(profile))
return;
if (m_iface.isValid())
m_iface.asyncCall(QStringLiteral("setMode"), mode);
QDBusMessage message = QDBusMessage::createMethodCall(s_profilesService, s_profilesPath,
s_propertiesInterface, QStringLiteral("Set"));
message << s_profilesService << QStringLiteral("ActiveProfile")
<< QVariant::fromValue(QDBusVariant(profile));
auto *watcher = new QDBusPendingCallWatcher(QDBusConnection::systemBus().asyncCall(message), this);
connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) {
// A refused switch (e.g. by polkit) sends no PropertiesChanged; re-read the real profile.
if (watcher->isError())
loadProfileProperties();
watcher->deleteLater();
});
m_profile = profile;
emit profileChanged();
}
QStringList PowerManager::profiles() const
{
return m_profiles;
}
m_mode = mode;
emit modeChanged();
QString PowerManager::performanceDegraded() const
{
return m_performanceDegraded;
}
void PowerManager::onProfilePropertiesChanged(const QString &interface, const QVariantMap &changed,
const QStringList &invalidated)
{
Q_UNUSED(invalidated)
if (interface == s_profilesService)
updateProfileProperties(changed);
}
void PowerManager::loadProfileProperties()
{
QDBusMessage message = QDBusMessage::createMethodCall(s_profilesService, s_profilesPath,
s_propertiesInterface, QStringLiteral("GetAll"));
message << s_profilesService;
auto *watcher = new QDBusPendingCallWatcher(QDBusConnection::systemBus().asyncCall(message), this);
connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) {
QDBusPendingReply<QVariantMap> reply = *watcher;
if (!reply.isError())
updateProfileProperties(reply.value());
watcher->deleteLater();
});
}
void PowerManager::updateProfileProperties(const QVariantMap &properties)
{
auto it = properties.constFind(QStringLiteral("Profiles"));
if (it != properties.constEnd()) {
QStringList profiles;
const QDBusArgument argument = it->value<QDBusArgument>();
argument.beginArray();
while (!argument.atEnd()) {
QVariantMap profile;
argument >> profile;
profiles.append(profile.value(QStringLiteral("Profile")).toString());
}
argument.endArray();
if (m_profiles != profiles) {
m_profiles = profiles;
emit profilesChanged();
}
}
it = properties.constFind(QStringLiteral("ActiveProfile"));
if (it != properties.constEnd() && m_profile != it->toString()) {
m_profile = it->toString();
emit profileChanged();
}
it = properties.constFind(QStringLiteral("PerformanceDegraded"));
if (it != properties.constEnd() && m_performanceDegraded != it->toString()) {
m_performanceDegraded = it->toString();
emit performanceDegradedChanged();
}
}
int PowerManager::batteryScreenOff() const

@ -21,12 +21,15 @@
#define POWERMANAGER_H
#include <QObject>
#include <QDBusInterface>
#include <QStringList>
#include <QVariantMap>
class PowerManager : public QObject
{
Q_OBJECT
Q_PROPERTY(int mode READ mode WRITE setMode NOTIFY modeChanged)
Q_PROPERTY(QString profile READ profile WRITE setProfile NOTIFY profileChanged)
Q_PROPERTY(QStringList profiles READ profiles NOTIFY profilesChanged)
Q_PROPERTY(QString performanceDegraded READ performanceDegraded NOTIFY performanceDegradedChanged)
Q_PROPERTY(int batteryScreenOff READ batteryScreenOff WRITE setBatteryScreenOff NOTIFY batteryScreenOffChanged)
Q_PROPERTY(int acScreenOff READ acScreenOff WRITE setACScreenOff NOTIFY acScreenOffChanged)
Q_PROPERTY(bool acPreventSleep READ acPreventSleep WRITE setACPreventSleep NOTIFY acPreventSleepChanged)
@ -34,8 +37,11 @@ class PowerManager : public QObject
public:
explicit PowerManager(QObject *parent = nullptr);
int mode() const;
void setMode(int mode);
QString profile() const;
void setProfile(const QString &profile);
QStringList profiles() const;
QString performanceDegraded() const;
int batteryScreenOff() const;
void setBatteryScreenOff(int timeout);
@ -47,14 +53,24 @@ public:
void setACPreventSleep(bool prevent);
signals:
void modeChanged();
void profileChanged();
void profilesChanged();
void performanceDegradedChanged();
void batteryScreenOffChanged();
void acScreenOffChanged();
void acPreventSleepChanged();
private slots:
void onProfilePropertiesChanged(const QString &interface, const QVariantMap &changed,
const QStringList &invalidated);
private:
QDBusInterface m_iface;
int m_mode;
void loadProfileProperties();
void updateProfileProperties(const QVariantMap &properties);
QString m_profile;
QStringList m_profiles;
QString m_performanceDegraded;
int m_batteryScreenOff;
int m_acScreenOff;
bool m_acPreventSleep;

@ -56,6 +56,7 @@ ItemPage {
ColumnLayout {
Layout.fillWidth: true
spacing: Metrics.sectionLabelSpacing
visible: power.profiles.length > 0
SectionLabel {
text: qsTr("Mode")
@ -70,8 +71,19 @@ ItemPage {
text: qsTr("Power Save")
previewWidth: 80
previewHeight: 80
checked: power.mode === 0
onClicked: power.mode = 0
visible: power.profiles.indexOf("power-saver") >= 0
checked: power.profile === "power-saver"
onClicked: power.profile = "power-saver"
}
ImageSelectionItem {
source: "qrc:/images/balanced.svg"
text: qsTr("Balanced")
previewWidth: 80
previewHeight: 80
visible: power.profiles.indexOf("balanced") >= 0
checked: power.profile === "balanced"
onClicked: power.profile = "balanced"
}
ImageSelectionItem {
@ -79,8 +91,9 @@ ItemPage {
text: qsTr("Performance")
previewWidth: 80
previewHeight: 80
checked: power.mode === 1
onClicked: power.mode = 1
visible: power.profiles.indexOf("performance") >= 0
checked: power.profile === "performance"
onClicked: power.profile = "performance"
}
}
}
@ -91,7 +104,32 @@ ItemPage {
rightPadding: Metrics.cardHorizontalPadding
Layout.fillWidth: true
wrapMode: Text.WordWrap
text: qsTr("Performance mode: CPU and GPU frequencies will be increased, while power consumption and heat generation will be increased.")
visible: text !== ""
text: {
if (power.profile === "power-saver")
return qsTr("Reduces performance and power consumption.")
if (power.profile === "balanced")
return qsTr("Standard performance and power consumption.")
if (power.profile === "performance")
return qsTr("Higher performance, with more power consumption and heat.")
return ""
}
}
FishUI.Label {
color: FishUI.Theme.disabledTextColor
leftPadding: Metrics.cardHorizontalPadding
rightPadding: Metrics.cardHorizontalPadding
Layout.fillWidth: true
wrapMode: Text.WordWrap
visible: power.profile === "performance" && power.performanceDegraded !== ""
text: {
if (power.performanceDegraded.indexOf("lap-detected") >= 0)
return qsTr("Performance is limited because the computer is on your lap.")
if (power.performanceDegraded.indexOf("high-operating-temperature") >= 0)
return qsTr("Performance is limited because the computer is too hot.")
return qsTr("Performance is currently limited.")
}
}
}

@ -63,6 +63,7 @@
<file>images/sidebar/light/wallpaper.svg</file>
<file>qml/RoundedItem.qml</file>
<file>images/powersave.svg</file>
<file>images/balanced.svg</file>
<file>images/performance.svg</file>
<file>qml/Power/Main.qml</file>
<file>qml/About/Main.qml</file>

@ -545,27 +545,57 @@
</message>
<message>
<location filename="../src/qml/Display/Main.qml" line="+124"/>
<location filename="../src/qml/Power/Main.qml" line="+31"/>
<location filename="../src/qml/Power/Main.qml" line="+32"/>
<source>Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/qml/Power/Main.qml" line="+12"/>
<location filename="../src/qml/Power/Main.qml" line="+10"/>
<source>Power Save</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+7"/>
<location line="+10"/>
<source>Balanced</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+10"/>
<source>Performance</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+19"/>
<source>Reduces performance and power consumption.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+2"/>
<source>Standard performance and power consumption.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+2"/>
<source>Higher performance, with more power consumption and heat.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+14"/>
<source>Performance mode: CPU and GPU frequencies will be increased, while power consumption and heat generation will be increased.</source>
<source>Performance is limited because the computer is on your lap.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+13"/>
<location line="+2"/>
<source>Performance is limited because the computer is too hot.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+1"/>
<source>Performance is currently limited.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+10"/>
<source>Turn off display when inactive on battery</source>
<translation type="unfinished"></translation>
</message>

Loading…
Cancel
Save