• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

SolidModules

halpower.cpp

Go to the documentation of this file.
00001  /*  This file is part of the KDE project
00002     Copyright (C) 2006 Kevin Ottens <ervin@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Library General Public
00006     License version 2 as published by the Free Software Foundation.
00007 
00008     This library is distributed in the hope that it will be useful,
00009     but WITHOUT ANY WARRANTY; without even the implied warranty of
00010     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011     Library General Public License for more details.
00012 
00013     You should have received a copy of the GNU Library General Public License
00014     along with this library; see the file COPYING.LIB.  If not, write to
00015     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016     Boston, MA 02110-1301, USA.
00017 
00018 */
00019 
00020 #include "halpower.h"
00021 
00022 #include <QtDBus/QDBusReply>
00023 
00024 #include <kdebug.h>
00025 
00026 #include "halsuspendjob.h"
00027 
00028 #include <solid/deviceinterface.h>
00029 #include <solid/acadapter.h>
00030 #include <solid/battery.h>
00031 #include <solid/button.h>
00032 #include <solid/genericinterface.h>
00033 
00034 HalPower::HalPower(QObject *parent, const QStringList  & /*args */)
00035     : PowerManager(parent),
00036       m_halComputer("org.freedesktop.Hal",
00037                      "/org/freedesktop/Hal/devices/computer",
00038                      "org.freedesktop.Hal.Device",
00039                      QDBusConnection::systemBus()),
00040       m_halPowerManagement("org.freedesktop.Hal",
00041                             "/org/freedesktop/Hal/devices/computer",
00042                             "org.freedesktop.Hal.Device.SystemPowerManagement",
00043                             QDBusConnection::systemBus()),
00044       m_halCpuFreq("org.freedesktop.Hal",
00045                     "/org/freedesktop/Hal/devices/computer",
00046                     "org.freedesktop.Hal.Device.CPUFreq",
00047                     QDBusConnection::systemBus()),
00048       m_halManager("org.freedesktop.Hal",
00049                     "/org/freedesktop/Hal/Manager",
00050                     "org.freedesktop.Hal.Manager",
00051                     QDBusConnection::systemBus())
00052 {
00053     connect(Solid::DeviceNotifier::instance(), SIGNAL(deviceRemoved(const QString &)),
00054             this, SLOT(slotDeviceRemoved(const QString &)));
00055     connect(Solid::DeviceNotifier::instance(), SIGNAL(deviceAdded(const QString &)),
00056             this, SLOT(slotDeviceAdded(const QString &)));
00057 
00058     m_pluggedAdapterCount = 0;
00059     computeAcAdapters();
00060 
00061     computeBatteries();
00062     updateBatteryStats();
00063 
00064     computeButtons();
00065 }
00066 
00067 HalPower::~HalPower()
00068 {
00069     QList<Solid::Device *> devices;
00070 
00071     devices << m_acAdapters.values();
00072     devices << m_batteries.values();
00073     devices << m_buttons.values();
00074 
00075     foreach (Solid::Device *dev, devices)
00076     {
00077         delete dev;
00078     }
00079 }
00080 
00081 QStringList HalPower::supportedSchemes() const
00082 {
00083     return QStringList() << "performance" << "powersaving";
00084 }
00085 
00086 QString HalPower::schemeDescription(const QString &schemeName) const
00087 {
00088     if (schemeName=="performance")
00089     {
00090         return "Use all the performances of the system";
00091     }
00092     else if (schemeName=="powersaving")
00093     {
00094         return "Try to keep as much power as possible to improve battery life";
00095     }
00096     else
00097     {
00098         return QString();
00099     }
00100 
00101     return QString();
00102 }
00103 
00104 QString HalPower::scheme() const
00105 {
00106     // FIXME: We miss an accessor in HAL to make scheme management useful
00107     return QString();
00108 }
00109 
00110 bool HalPower::setScheme(const QString &name)
00111 {
00112     bool powersave;
00113 
00114     if (name=="powersaving")
00115     {
00116         powersave = true;
00117     }
00118     else if (name=="performance")
00119     {
00120         powersave = false;
00121     }
00122     else
00123     {
00124         return false;
00125     }
00126 
00127     QDBusReply<int> reply = m_halPowerManagement.call("SetPowerSave", powersave);
00128 
00129     if (reply.isValid())
00130     {
00131         int code = reply;
00132         return code==0;
00133     }
00134     else
00135     {
00136         return false;
00137     }
00138 }
00139 
00140 Solid::Control::PowerManager::BatteryState HalPower::batteryState() const
00141 {
00142     if (m_batteries.size()==0)
00143     {
00144         return Solid::Control::PowerManager::NoBatteryState;
00145     }
00146     else if (m_currentBatteryCharge <= m_criticalBatteryCharge)
00147     {
00148         return Solid::Control::PowerManager::Critical;
00149     }
00150     else if (m_currentBatteryCharge <= m_lowBatteryCharge)
00151     {
00152         return Solid::Control::PowerManager::Low;
00153     }
00154     else if (m_currentBatteryCharge <= m_warningBatteryCharge)
00155     {
00156         return Solid::Control::PowerManager::Warning;
00157     }
00158     else
00159     {
00160         return Solid::Control::PowerManager::Normal;
00161     }
00162 }
00163 
00164 int HalPower::batteryChargePercent() const
00165 {
00166     if (!m_maxBatteryCharge) return 0;
00167 
00168     return (m_currentBatteryCharge *100)/m_maxBatteryCharge;
00169 }
00170 
00171 Solid::Control::PowerManager::AcAdapterState HalPower::acAdapterState() const
00172 {
00173     if (m_acAdapters.size()==0)
00174     {
00175         return Solid::Control::PowerManager::UnknownAcAdapterState;
00176     }
00177     else if (m_pluggedAdapterCount==0)
00178     {
00179         return Solid::Control::PowerManager::Unplugged;
00180     }
00181     else
00182     {
00183         return Solid::Control::PowerManager::Plugged;
00184     }
00185 }
00186 
00187 Solid::Control::PowerManager::SuspendMethods HalPower::supportedSuspendMethods() const
00188 {
00189     Solid::Control::PowerManager::SuspendMethods supported = Solid::Control::PowerManager::UnknownSuspendMethod;
00190 
00191     QDBusReply<bool> reply = m_halComputer.call("GetPropertyBoolean", "power_management.can_hibernate");
00192 
00193     if (reply.isValid())
00194     {
00195         bool can_suspend = reply;
00196         if (can_suspend)
00197         {
00198             supported |= Solid::Control::PowerManager::ToRam;
00199         }
00200     }
00201     else
00202     {
00203         kDebug() << reply.error().name() << ": " << reply.error().message();
00204     }
00205 
00206     reply = m_halComputer.call("GetPropertyBoolean", "power_management.can_hibernate");
00207 
00208     if (reply.isValid())
00209     {
00210         bool can_hibernate = reply;
00211         if (can_hibernate)
00212         {
00213             supported |= Solid::Control::PowerManager::ToDisk;
00214         }
00215     }
00216     else
00217     {
00218         kDebug() << reply.error().name() << ": " << reply.error().message();
00219     }
00220 
00221     return supported;
00222 }
00223 
00224 KJob *HalPower::suspend(Solid::Control::PowerManager::SuspendMethod method) const
00225 {
00226     return new HalSuspendJob(m_halPowerManagement,
00227                              method, supportedSuspendMethods());
00228 }
00229 
00230 Solid::Control::PowerManager::CpuFreqPolicies HalPower::supportedCpuFreqPolicies() const
00231 {
00232     QDBusReply<QStringList> reply = m_halCpuFreq.call("GetCPUFreqAvailableGovernors");
00233 
00234     if (!reply.isValid())
00235     {
00236         return Solid::Control::PowerManager::UnknownCpuFreqPolicy;
00237     }
00238     else
00239     {
00240         QStringList governors = reply;
00241         Solid::Control::PowerManager::CpuFreqPolicies policies = Solid::Control::PowerManager::UnknownCpuFreqPolicy;
00242 
00243         foreach (QString governor, governors)
00244         {
00245             if (governor == "ondemand")
00246             {
00247                 policies|= Solid::Control::PowerManager::OnDemand;
00248             }
00249             else if (governor == "userspace")
00250             {
00251                 policies|= Solid::Control::PowerManager::Userspace;
00252             }
00253             else if (governor == "powersave")
00254             {
00255                 policies|= Solid::Control::PowerManager::Powersave;
00256             }
00257             else if (governor == "performance")
00258             {
00259                 policies|= Solid::Control::PowerManager::Performance;
00260             }
00261             else if (governor == "conservative")
00262             {
00263                 policies|= Solid::Control::PowerManager::Conservative;
00264             }
00265             else
00266             {
00267                 kWarning() << "Unknown governor: " << governor ;
00268             }
00269         }
00270 
00271         return policies;
00272     }
00273 }
00274 
00275 Solid::Control::PowerManager::CpuFreqPolicy HalPower::cpuFreqPolicy() const
00276 {
00277     QDBusReply<QString> reply = m_halCpuFreq.call("GetCPUFreqGovernor");
00278 
00279     if (!reply.isValid())
00280     {
00281         return Solid::Control::PowerManager::UnknownCpuFreqPolicy;
00282     }
00283     else
00284     {
00285         QString governor = reply;
00286 
00287         if (governor == "ondemand")
00288         {
00289             return Solid::Control::PowerManager::OnDemand;
00290         }
00291         else if (governor == "userspace")
00292         {
00293             return Solid::Control::PowerManager::Userspace;
00294         }
00295         else if (governor == "powersave")
00296         {
00297             return Solid::Control::PowerManager::Powersave;
00298         }
00299         else if (governor == "performance")
00300         {
00301             return Solid::Control::PowerManager::Performance;
00302         }
00303         else if (governor == "conservative")
00304         {
00305             return Solid::Control::PowerManager::Conservative;
00306         }
00307         else
00308         {
00309             return Solid::Control::PowerManager::UnknownCpuFreqPolicy;
00310         }
00311     }
00312 }
00313 
00314 bool HalPower::setCpuFreqPolicy(Solid::Control::PowerManager::CpuFreqPolicy newPolicy)
00315 {
00316     QString governor;
00317 
00318     switch(newPolicy)
00319     {
00320     case Solid::Control::PowerManager::OnDemand:
00321         governor = "ondemand";
00322         break;
00323     case Solid::Control::PowerManager::Userspace:
00324         governor = "userspace";
00325         break;
00326     case Solid::Control::PowerManager::Powersave:
00327         governor = "powersave";
00328         break;
00329     case Solid::Control::PowerManager::Performance:
00330         governor = "performance";
00331         break;
00332     case Solid::Control::PowerManager::Conservative:
00333         governor = "conservative";
00334         break;
00335     default:
00336         return false;
00337     }
00338 
00339     QDBusReply<int> reply = m_halCpuFreq.call("SetCPUFreqGovernor", governor);
00340 
00341     if (reply.isValid())
00342     {
00343         int code = reply;
00344         return code==0;
00345     }
00346     else
00347     {
00348         return false;
00349     }
00350 }
00351 
00352 bool HalPower::canDisableCpu(int /*cpuNum */) const
00353 {
00354     return false;
00355 }
00356 
00357 bool HalPower::setCpuEnabled(int /*cpuNum */, bool /*enabled */)
00358 {
00359     return false;
00360 }
00361 
00362 Solid::Control::PowerManager::BrightnessControlsList HalPower::brightnessControlsAvailable()
00363 {
00364     Solid::Control::PowerManager::BrightnessControlsList deviceList;
00365     foreach(const QString &name, m_halManager.call("FindDeviceByCapability", "laptop_panel").arguments().at(0).toStringList())
00366     {
00367         deviceList.insert(name, Solid::Control::PowerManager::Screen);
00368     }
00369     foreach(const QString &name, m_halManager.call("FindDeviceByCapability", "keyboard_backlight").arguments().at(0).toStringList())
00370     {
00371         deviceList.insert(name, Solid::Control::PowerManager::Keyboard);
00372     }
00373     return deviceList;
00374 }
00375 
00376 float HalPower::brightness(const QString &device)
00377 {
00378     float brightness;
00379     if(m_halManager.call("FindDeviceByCapability", "laptop_panel").arguments().at(0).toStringList().contains(device))
00380     {
00381         QDBusInterface deviceInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device.LaptopPanel", QDBusConnection::systemBus());
00382         brightness = deviceInterface.call("GetBrightness").arguments().at(0).toDouble();
00383         if(deviceInterface.lastError().isValid())
00384         {
00385             return 0;
00386         }
00387         else
00388         {
00389             QDBusInterface propertyInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device", QDBusConnection::systemBus());
00390             int levels = propertyInterface.call("GetProperty", "laptop_panel.num_levels").arguments().at(0).toInt();
00391             return (float)(100*(brightness/(levels-1)));
00392         }
00393     }
00394     if(m_halManager.call("FindDeviceByCapability", "keyboard_backlight").arguments().at(0).toStringList().contains(device))
00395     {
00396         QDBusInterface deviceInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device.KeyboardBacklight", QDBusConnection::systemBus()); //TODO - I dont have a backlight enabled keyboard, so I'm guessing a bit here. Could someone please check this.
00397         brightness = deviceInterface.call("GetBrightness").arguments().at(0).toDouble();
00398         if(deviceInterface.lastError().isValid())
00399         {
00400             return 0;
00401         }
00402         else
00403         {
00404             QDBusInterface propertyInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device", QDBusConnection::systemBus());
00405             int levels = propertyInterface.call("GetProperty", "keyboard_backlight.num_levels").arguments().at(0).toInt();
00406             return (float)(100*(brightness/(levels-1)));
00407         }
00408     }
00409     return 0;
00410 }
00411 
00412 bool HalPower::setBrightness(float brightness, const QString &device)
00413 {
00414     if(m_halManager.call("FindDeviceByCapability", "laptop_panel").arguments().at(0).toStringList().contains(device))
00415     {
00416         QDBusInterface propertyInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device", QDBusConnection::systemBus());
00417         int levels = propertyInterface.call("GetProperty", "laptop_panel.num_levels").arguments().at(0).toInt();
00418         QDBusInterface deviceInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device.LaptopPanel", QDBusConnection::systemBus());
00419         deviceInterface.call("SetBrightness", qRound((levels-1)*(brightness/100.0))); // .0? The right way? Feels hackish.
00420         if(!deviceInterface.lastError().isValid())
00421         {
00422             emit(brightnessChanged(brightness));
00423             return true;
00424         }
00425     }
00426     if(m_halManager.call("FindDeviceByCapability", "keyboard_backlight").arguments().at(0).toStringList().contains(device))
00427     {
00428         QDBusInterface propertyInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device", QDBusConnection::systemBus());
00429         int levels = propertyInterface.call("GetProperty", "keyboard_backlight.num_levels").arguments().at(0).toInt();
00430         QDBusInterface deviceInterface("org.freedesktop.Hal", device, "org.freedesktop.Hal.Device.KeyboardBacklight", QDBusConnection::systemBus()); //TODO - I dont have a backlight enabled keyboard, so I'm guessing a bit here. Could someone please check this.
00431         deviceInterface.call("SetBrightness", qRound((levels-1)*(brightness/100.0)));
00432         if(!deviceInterface.lastError().isValid())
00433         {
00434             emit(brightnessChanged(brightness));
00435             return true;
00436         }
00437     }
00438     return false;
00439 }
00440 
00441 void HalPower::computeAcAdapters()
00442 {
00443     QList<Solid::Device> adapters
00444         = Solid::Device::listFromType(Solid::DeviceInterface::AcAdapter);
00445 
00446     foreach (Solid::Device adapter, adapters)
00447     {
00448         m_acAdapters[adapter.udi()] = new Solid::Device(adapter);
00449         connect(m_acAdapters[adapter.udi()]->as<Solid::AcAdapter>(), SIGNAL(plugStateChanged(bool, const QString &)),
00450                  this, SLOT(slotPlugStateChanged(bool)));
00451 
00452         if (m_acAdapters[adapter.udi()]->as<Solid::AcAdapter>()!=0
00453           && m_acAdapters[adapter.udi()]->as<Solid::AcAdapter>()->isPlugged())
00454         {
00455             m_pluggedAdapterCount++;
00456         }
00457     }
00458 }
00459 
00460 void HalPower::computeBatteries()
00461 {
00462     QList<Solid::Device> batteries
00463         = Solid::Device::listFromQuery("Battery.type == 'PrimaryBattery'");
00464 
00465     foreach (Solid::Device battery, batteries)
00466     {
00467         m_batteries[battery.udi()] = new Solid::Device(battery);
00468         connect(m_batteries[battery.udi()]->as<Solid::Battery>(), SIGNAL(chargePercentChanged(int, const QString &)),
00469                  this, SLOT(updateBatteryStats()));
00470     }
00471 
00472     updateBatteryStats();
00473 }
00474 
00475 void HalPower::computeButtons()
00476 {
00477     QList<Solid::Device> buttons
00478         = Solid::Device::listFromType(Solid::DeviceInterface::Button);
00479 
00480     foreach (Solid::Device button, buttons)
00481     {
00482         m_buttons[button.udi()] = new Solid::Device(button);
00483         connect(m_buttons[button.udi()]->as<Solid::Button>(), SIGNAL(pressed(Solid::Button::ButtonType, const QString &)),
00484                  this, SLOT(slotButtonPressed(Solid::Button::ButtonType)));
00485     }
00486 }
00487 
00488 void HalPower::updateBatteryStats()
00489 {
00490     m_currentBatteryCharge = 0;
00491     m_maxBatteryCharge = 0;
00492     m_warningBatteryCharge = 0;
00493     m_lowBatteryCharge = 0;
00494     m_criticalBatteryCharge = 0;
00495 
00496     foreach (Solid::Device *d, m_batteries.values())
00497     {
00498         Solid::GenericInterface *interface = d->as<Solid::GenericInterface>();
00499 
00500         if (interface == 0) continue;
00501 
00502         m_currentBatteryCharge+= interface->property("battery.charge_level.current").toInt();
00503         m_maxBatteryCharge+= interface->property("battery.charge_level.last_full").toInt();
00504         m_warningBatteryCharge+= interface->property("battery.charge_level.warning").toInt();
00505         m_lowBatteryCharge+= interface->property("battery.charge_level.low").toInt();
00506     }
00507 
00508     m_criticalBatteryCharge = m_lowBatteryCharge/2;
00509 }
00510 
00511 void HalPower::slotPlugStateChanged(bool newState)
00512 {
00513     if (newState)
00514     {
00515         if(m_pluggedAdapterCount == 0)
00516         {
00517             emit acAdapterStateChanged(Solid::Control::PowerManager::Plugged);
00518         }
00519         m_pluggedAdapterCount++;
00520     }
00521     else
00522     {
00523         if(m_pluggedAdapterCount == 1)
00524         {
00525             emit acAdapterStateChanged(Solid::Control::PowerManager::Unplugged);
00526         }
00527         m_pluggedAdapterCount--;
00528     }
00529 }
00530 
00531 void HalPower::slotButtonPressed(Solid::Button::ButtonType type)
00532 {
00533     Solid::Button *button = qobject_cast<Solid::Button *>(sender());
00534 
00535     if (button == 0) return;
00536 
00537     switch(type)
00538     {
00539     case Solid::Button::PowerButton:
00540         emit buttonPressed(Solid::Control::PowerManager::PowerButton);
00541         break;
00542     case Solid::Button::SleepButton:
00543         emit buttonPressed(Solid::Control::PowerManager::SleepButton);
00544         break;
00545     case Solid::Button::LidButton:
00546         if (button->stateValue())
00547         {
00548             emit buttonPressed(Solid::Control::PowerManager::LidClose);
00549         }
00550         else
00551         {
00552             emit buttonPressed(Solid::Control::PowerManager::LidOpen);
00553         }
00554         break;
00555     default:
00556         kWarning() << "Unknown button type" ;
00557         break;
00558     }
00559 }
00560 
00561 void HalPower::slotDeviceAdded(const QString &udi)
00562 {
00563     Solid::Device *device = new Solid::Device(udi);
00564     if (device->is<Solid::AcAdapter>())
00565     {
00566         m_acAdapters[udi] = device;
00567         connect(m_acAdapters[udi]->as<Solid::AcAdapter>(), SIGNAL(plugStateChanged(bool, const QString &)),
00568                  this, SLOT(slotPlugStateChanged(bool)));
00569 
00570         if (m_acAdapters[udi]->as<Solid::AcAdapter>()!=0
00571           && m_acAdapters[udi]->as<Solid::AcAdapter>()->isPlugged())
00572         {
00573             m_pluggedAdapterCount++;
00574         }
00575     }
00576     else if (device->is<Solid::Battery>())
00577     {
00578         m_batteries[udi] = device;
00579         connect(m_batteries[udi]->as<Solid::Battery>(), SIGNAL(chargePercentChanged(int, const QString &)),
00580                  this, SLOT(updateBatteryStats()));
00581     }
00582     else if (device->is<Solid::Button>())
00583     {
00584         m_buttons[udi] = device;
00585         connect(m_buttons[udi]->as<Solid::Button>(), SIGNAL(pressed(int, const QString &)),
00586                  this, SLOT(slotButtonPressed(int)));
00587     }
00588     else
00589     {
00590         delete device;
00591     }
00592 }
00593 
00594 void HalPower::slotDeviceRemoved(const QString &udi)
00595 {
00596     Solid::Device *device = 0;
00597 
00598     device = m_acAdapters.take(udi);
00599 
00600     if (device!=0)
00601     {
00602         delete device;
00603 
00604         m_pluggedAdapterCount = 0;
00605 
00606         foreach (Solid::Device *d, m_acAdapters.values())
00607         {
00608             if (d->as<Solid::AcAdapter>()!=0
00609               && d->as<Solid::AcAdapter>()->isPlugged())
00610             {
00611                 m_pluggedAdapterCount++;
00612             }
00613         }
00614 
00615         return;
00616     }
00617 
00618     device = m_batteries.take(udi);
00619 
00620     if (device!=0)
00621     {
00622         delete device;
00623         updateBatteryStats();
00624         return;
00625     }
00626 
00627     device = m_buttons.take(udi);
00628 
00629     if (device!=0)
00630     {
00631         delete device;
00632         return;
00633     }
00634 }
00635 
00636 #include "halpower.moc"

SolidModules

Skip menu "SolidModules"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libplasma
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal