/* * SPDX-FileCopyrightText: Copyright 2023 Jakob Petsovits * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "powerdevilmigrateconfig.h" #include "powerdevilenums.h" #include #include #include #include #include #include // std::min, std::max #include // std::invoke #include // std::remove_cvref_t using namespace Qt::StringLiterals; namespace { template struct IdentityTransformer { std::remove_cvref_t operator()(T t) { return std::move(t); } }; } // anonymous namespace namespace PowerDevil { void migrateActivitiesConfig(KSharedConfig::Ptr profilesConfig) { KConfigGroup migrationGroup = profilesConfig->group(QStringLiteral("Migration")); if (migrationGroup.hasKey("MigratedActivitiesToPlasma6")) { return; } // Activity special behavior config written via ActivitySettings, reading must be done manually. const KConfigGroup oldActivitiesGroup = profilesConfig->group(QStringLiteral("Activities")); if (!oldActivitiesGroup.exists()) { return; } // Every activity has its own group identified by its UUID. for (const QString &activityId : oldActivitiesGroup.groupList()) { const KConfigGroup oldConfig = oldActivitiesGroup.group(activityId); PowerDevil::ActivitySettings newConfig(activityId); if (oldConfig.readEntry("mode", "None") == u"SpecialBehavior") { if (const KConfigGroup oldSB = oldConfig.group(QStringLiteral("SpecialBehavior")); oldSB.exists()) { newConfig.setInhibitScreenManagement(oldSB.readEntry("noScreenManagement", false)); newConfig.setInhibitSuspend(oldSB.readEntry("noSuspend", false)); } } newConfig.save(); } migrationGroup.writeEntry("MigratedActivitiesToPlasma6", "powerdevilrc"); profilesConfig->sync(); } void ensureLockScreenIdleTimeoutInKScreenLockerKCM(int seconds) { KSharedConfig::Ptr lockerConfig = KSharedConfig::openConfig(QStringLiteral("kscreenlockerrc")); KConfigGroup group = lockerConfig->group(QStringLiteral("Daemon")); if (group.readEntry("Autolock", true) == false) { group.deleteEntry("Autolock"); // reset to default true value group.writeEntry("Timeout", std::max(1, std::min(group.readEntry("Timeout", 5), seconds / 60))); } lockerConfig->sync(); } void migrateProfilesConfig(KSharedConfig::Ptr profilesConfig, bool isMobile, bool isVM, bool canSuspend) { KConfigGroup migrationGroup = profilesConfig->group(QStringLiteral("Migration")); if (migrationGroup.hasKey(QStringLiteral("MigratedProfilesToPlasma6"))) { return; } for (const auto &profileName : {QStringLiteral("AC"), QStringLiteral("Battery"), QStringLiteral("LowBattery")}) { const KConfigGroup oldProfileGroup = profilesConfig->group(profileName); if (!oldProfileGroup.exists()) { continue; } PowerDevil::ProfileSettings profileSettings(profileName, isMobile, isVM, canSuspend); auto migrateEntry = [&]>(KConfigGroup & oldGroup, const QString &oldKey, void (ProfileSettings::*setter)(T), Transformer transform = IdentityTransformer()) { if (!oldGroup.hasKey(oldKey)) { return; } // We know oldKey exists, so use any T value as default because we don't care what's in it T newValue = std::invoke(transform, oldGroup.readEntry(oldKey, std::remove_cvref_t{})); (profileSettings.*setter)(newValue); }; if (KConfigGroup group = oldProfileGroup.group(QStringLiteral("KeyboardBrightnessControl")); group.exists()) { profileSettings.setUseProfileSpecificKeyboardBrightness(true); migrateEntry(group, u"value"_s, &ProfileSettings::setKeyboardBrightness); } else { profileSettings.setUseProfileSpecificKeyboardBrightness(false); } if (KConfigGroup group = oldProfileGroup.group(QStringLiteral("BrightnessControl")); group.exists()) { profileSettings.setUseProfileSpecificDisplayBrightness(true); migrateEntry(group, u"value"_s, &ProfileSettings::setDisplayBrightness); } else { profileSettings.setUseProfileSpecificDisplayBrightness(false); } if (KConfigGroup group = oldProfileGroup.group(QStringLiteral("DimDisplay")); group.exists()) { profileSettings.setDimDisplayWhenIdle(true); migrateEntry(group, u"idleTime"_s, &ProfileSettings::setDimDisplayIdleTimeoutSec, [](int oldMsec) { return oldMsec / 1000; // standarize on using seconds, see powerdevil issue #3 on KDE Invent }); } else { profileSettings.setDimDisplayWhenIdle(false); } if (KConfigGroup group = oldProfileGroup.group(QStringLiteral("DPMSControl")); group.exists()) { profileSettings.setTurnOffDisplayWhenIdle(true); // The "DPMSControl" group used seconds for "idleTime". Unlike other groups which // used milliseconds in Plasma 5, this one doesn't need division by 1000. migrateEntry(group, u"idleTime"_s, &ProfileSettings::setTurnOffDisplayIdleTimeoutSec); migrateEntry(group, u"idleTimeoutWhenLocked"_s, &ProfileSettings::setTurnOffDisplayIdleTimeoutWhenLockedSec); migrateEntry(group, u"lockBeforeTurnOff"_s, &ProfileSettings::setLockBeforeTurnOffDisplay); } else { profileSettings.setTurnOffDisplayWhenIdle(false); } bool suspendThenHibernate = false; bool hybridSuspend = false; bool migrateLockScreenIdleTimeout = false; if (KConfigGroup group = oldProfileGroup.group(QStringLiteral("SuspendSession")); group.exists()) { if (group.readEntry("suspendThenHibernate", false)) { suspendThenHibernate = true; } migrateEntry(group, u"suspendType"_s, &ProfileSettings::setAutoSuspendAction, [&](uint oldAction) { if (oldAction == 4 /* the old PowerButtonAction::SuspendHybrid */) { hybridSuspend = true; return qToUnderlying(PowerButtonAction::Sleep); } if (oldAction == qToUnderlying(PowerButtonAction::LockScreen)) { migrateLockScreenIdleTimeout = true; // see bottom of function return qToUnderlying(PowerButtonAction::NoAction); } return oldAction; }); migrateEntry(group, u"idleTime"_s, &ProfileSettings::setAutoSuspendIdleTimeoutSec, [](int oldMsec) { return oldMsec / 1000; // standarize on using seconds, see powerdevil issue #3 on KDE Invent }); // Note: setSleepMode() is called at the end, completing this section. } else { profileSettings.setAutoSuspendAction(qToUnderlying(PowerButtonAction::NoAction)); } if (KConfigGroup group = oldProfileGroup.group(QStringLiteral("HandleButtonEvents")); group.exists()) { migrateEntry(group, u"powerButtonAction"_s, &ProfileSettings::setPowerButtonAction, [&](uint oldAction) { if (oldAction == 4 /* the old PowerButtonAction::SuspendHybrid */) { hybridSuspend = true; return qToUnderlying(PowerButtonAction::Sleep); } return oldAction; }); migrateEntry(group, u"powerDownAction"_s, &ProfileSettings::setPowerDownAction, [&](uint oldAction) { if (oldAction == 4 /* the old PowerButtonAction::SuspendHybrid */) { hybridSuspend = true; return qToUnderlying(PowerButtonAction::Sleep); } return oldAction; }); migrateEntry(group, u"lidAction"_s, &ProfileSettings::setLidAction, [&](uint oldAction) { if (oldAction == 4 /* the old PowerButtonAction::SuspendHybrid */) { hybridSuspend = true; return qToUnderlying(PowerButtonAction::Sleep); } return oldAction; }); migrateEntry(group, u"triggerLidActionWhenExternalMonitorPresent"_s, &ProfileSettings::setInhibitLidActionWhenExternalMonitorPresent, [](bool shouldTrigger) { return !shouldTrigger; }); } else { profileSettings.setPowerButtonAction(qToUnderlying(PowerButtonAction::NoAction)); profileSettings.setPowerDownAction(qToUnderlying(PowerButtonAction::NoAction)); profileSettings.setLidAction(qToUnderlying(PowerButtonAction::NoAction)); } if (KConfigGroup group = oldProfileGroup.group(QStringLiteral("PowerProfile")); group.exists()) { migrateEntry(group, u"profile"_s, &ProfileSettings::setPowerProfile); } if (KConfigGroup group = oldProfileGroup.group(QStringLiteral("RunScript")); group.exists()) { switch (group.readEntry("scriptPhase", 0)) { case 0: // on profile load migrateEntry(group, u"scriptCommand"_s, &ProfileSettings::setProfileLoadCommand); break; case 1: // on profile unload migrateEntry(group, u"scriptCommand"_s, &ProfileSettings::setProfileUnloadCommand); break; case 2: // on idle timeout migrateEntry(group, u"scriptCommand"_s, &ProfileSettings::setIdleTimeoutCommand); break; } migrateEntry(group, u"idleTime"_s, &ProfileSettings::setRunScriptIdleTimeoutSec, [](int oldMsec) { return oldMsec / 1000; // standarize on using seconds, see powerdevil issue #3 on KDE Invent }); } if (suspendThenHibernate) { profileSettings.setSleepMode(qToUnderlying(SleepMode::SuspendThenHibernate)); } else if (hybridSuspend) { profileSettings.setSleepMode(qToUnderlying(SleepMode::HybridSuspend)); } if (migrateLockScreenIdleTimeout) { // We had two different settings for this, ditch this and only keep the one in kscreenlockerrc ensureLockScreenIdleTimeoutInKScreenLockerKCM(profileSettings.autoSuspendIdleTimeoutSec()); } profileSettings.save(); } migrationGroup.writeEntry("MigratedProfilesToPlasma6", "powerdevilrc"); profilesConfig->sync(); } void migrateConfig(bool isMobile, bool isVM, bool canSuspend) { KSharedConfig::Ptr profilesConfig = KSharedConfig::openConfig(QStringLiteral("powermanagementprofilesrc")); // TODO KF7 (or perhaps earlier): Remove Plasma 5->6 migration code and delete powermanagementprofilesrc migrateActivitiesConfig(profilesConfig); migrateProfilesConfig(profilesConfig, isMobile, isVM, canSuspend); } } // namespace PowerDevil