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