[packages/kde4-kdebase-workspace] - more multibattery fixes

arekm arekm at pld-linux.org
Tue Jun 4 18:34:40 CEST 2013


commit 775841400e7e3a8a3ede3f2eded9bed765e350b0
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date:   Tue Jun 4 18:34:35 2013 +0200

    - more multibattery fixes

 kde4-kdebase-workspace-multibattery.patch | 2114 ++++++++++++++++++++++++++---
 1 file changed, 1955 insertions(+), 159 deletions(-)
---
diff --git a/kde4-kdebase-workspace-multibattery.patch b/kde4-kdebase-workspace-multibattery.patch
index 0612b3e..0f345b0 100644
--- a/kde4-kdebase-workspace-multibattery.patch
+++ b/kde4-kdebase-workspace-multibattery.patch
@@ -1,42 +1,93 @@
 diff --git a/plasma/generic/dataengines/powermanagement/powermanagementengine.cpp b/plasma/generic/dataengines/powermanagement/powermanagementengine.cpp
-index d1b9519..a79f5ab 100644
+index 33a6e03..f3a918a 100644
 --- a/plasma/generic/dataengines/powermanagement/powermanagementengine.cpp
 +++ b/plasma/generic/dataengines/powermanagement/powermanagementengine.cpp
-@@ -115,27 +115,31 @@ bool PowermanagementEngine::sourceRequestEvent(const QString &name)
+@@ -34,6 +34,7 @@
+ #include <KIdleTime>
+ 
+ #include <QtDBus/QDBusConnectionInterface>
++#include <QtDBus/QDBusError>
+ #include <QtDBus/QDBusInterface>
+ #include <QtDBus/QDBusMetaType>
+ #include <QtDBus/QDBusReply>
+@@ -58,23 +59,39 @@ PowermanagementEngine::~PowermanagementEngine()
+ 
+ void PowermanagementEngine::init()
+ {
+-    connect(Solid::DeviceNotifier::instance(), SIGNAL(deviceRemoved(QString)),
+-            this,                              SLOT(deviceRemoved(QString)));
+     connect(Solid::DeviceNotifier::instance(), SIGNAL(deviceAdded(QString)),
+             this,                              SLOT(deviceAdded(QString)));
++    connect(Solid::DeviceNotifier::instance(), SIGNAL(deviceRemoved(QString)),
++            this,                              SLOT(deviceRemoved(QString)));
+ 
++    // FIXME This check doesn't work, connect seems to always return true, hence the hack below
+     if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.Solid.PowerManagement")) {
+         if (!QDBusConnection::sessionBus().connect("org.kde.Solid.PowerManagement",
+-                                                   "/org/kde/Solid/PowerManagement",
+-                                                   "org.kde.Solid.PowerManagement",
++                                                   "/org/kde/Solid/PowerManagement/Actions/BrightnessControl",
++                                                   "org.kde.Solid.PowerManagement.Actions.BrightnessControl",
+                                                    "brightnessChanged", this,
+                                                    SLOT(screenBrightnessChanged(int)))) {
+             kDebug() << "error connecting to Brightness changes via dbus";
+-        }
+-        else {
++            brightnessControlsAvailableChanged(false);
++        } else {
+             sourceRequestEvent("PowerDevil");
+             screenBrightnessChanged(0);
++            brightnessControlsAvailableChanged(true);
+         }
++
++        if (!QDBusConnection::sessionBus().connect("org.kde.Solid.PowerManagement",
++                                                   "/org/kde/Solid/PowerManagement/Actions/KeyboardBrightnessControl",
++                                                   "org.kde.Solid.PowerManagement.Actions.KeyboardBrightnessControl",
++                                                   "keyboardBrightnessChanged", this,
++                                                   SLOT(keyboardBrightnessChanged(int)))) {
++            kDebug() << "error connecting to Keyboard Brightness changes via dbus";
++            keyboardBrightnessControlsAvailableChanged(false);
++        } else {
++            sourceRequestEvent("PowerDevil");
++            keyboardBrightnessChanged(0);
++            keyboardBrightnessControlsAvailableChanged(true);
++        }
++
+         if (!QDBusConnection::sessionBus().connect("org.kde.Solid.PowerManagement",
+                                                    "/org/kde/Solid/PowerManagement",
+                                                    "org.kde.Solid.PowerManagement",
+@@ -114,27 +131,32 @@ bool PowermanagementEngine::sourceRequestEvent(const QString &name)
          foreach (const Solid::Device &deviceBattery, listBattery) {
              const Solid::Battery* battery = deviceBattery.as<Solid::Battery>();
  
 -            if (battery && (battery->type() == Solid::Battery::PrimaryBattery ||
 -                            battery->type() == Solid::Battery::UpsBattery)) {
 -                const QString source = QString("Battery%1").arg(index++);
--
++            const QString source = QString("Battery%1").arg(index++);
+ 
 -                batterySources << source;
 -                m_batterySources[deviceBattery.udi()] = source;
--
++            batterySources << source;
++            m_batterySources[deviceBattery.udi()] = source;
+ 
 -                connect(battery, SIGNAL(chargeStateChanged(int,QString)), this,
 -                        SLOT(updateBatteryChargeState(int,QString)));
 -                connect(battery, SIGNAL(chargePercentChanged(int,QString)), this,
 -                        SLOT(updateBatteryChargePercent(int,QString)));
 -                connect(battery, SIGNAL(plugStateChanged(bool,QString)), this,
 -                        SLOT(updateBatteryPlugState(bool,QString)));
--
--                // Set initial values
--                updateBatteryChargeState(battery->chargeState(), deviceBattery.udi());
--                updateBatteryChargePercent(battery->chargePercent(), deviceBattery.udi());
--                updateBatteryPlugState(battery->isPlugged(), deviceBattery.udi());
--            }
-+            const QString source = QString("Battery%1").arg(index++);
-+
-+            batterySources << source;
-+            m_batterySources[deviceBattery.udi()] = source;
-+
 +            connect(battery, SIGNAL(chargeStateChanged(int,QString)), this,
 +                    SLOT(updateBatteryChargeState(int,QString)));
 +            connect(battery, SIGNAL(chargePercentChanged(int,QString)), this,
 +                    SLOT(updateBatteryChargePercent(int,QString)));
 +            connect(battery, SIGNAL(plugStateChanged(bool,QString)), this,
 +                    SLOT(updateBatteryPlugState(bool,QString)));
-+
+ 
+-                // Set initial values
+-                updateBatteryChargeState(battery->chargeState(), deviceBattery.udi());
+-                updateBatteryChargePercent(battery->chargePercent(), deviceBattery.udi());
+-                updateBatteryPlugState(battery->isPlugged(), deviceBattery.udi());
+-            }
 +            // Set initial values
 +            updateBatteryChargeState(battery->chargeState(), deviceBattery.udi());
 +            updateBatteryChargePercent(battery->chargePercent(), deviceBattery.udi());
@@ -45,6 +96,7 @@ index d1b9519..a79f5ab 100644
 +
 +            setData(source, "Vendor", deviceBattery.vendor());
 +            setData(source, "Product", deviceBattery.product());
++            setData(source, "Capacity", battery->capacity());
 +            setData(source, "Type", batteryType(battery));
          }
  
@@ -53,7 +105,46 @@ index d1b9519..a79f5ab 100644
          setData("Battery", "Has Battery", !batterySources.isEmpty());
          if (!batterySources.isEmpty()) {
              setData("Battery", "Sources", batterySources);
-@@ -199,6 +203,37 @@ bool PowermanagementEngine::sourceRequestEvent(const QString &name)
+@@ -180,14 +202,30 @@ bool PowermanagementEngine::sourceRequestEvent(const QString &name)
+             //kDebug() << "Sleepstate \"" << sleepstate << "\" supported.";
+         }
+     } else if (name == "PowerDevil") {
+-        QDBusMessage msg = QDBusMessage::createMethodCall("org.kde.Solid.PowerManagement",
+-                                                          "/org/kde/Solid/PowerManagement",
+-                                                          "org.kde.Solid.PowerManagement",
+-                                                          "brightness");
+-        QDBusPendingReply<int> reply = QDBusConnection::sessionBus().asyncCall(msg);
+-        QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
+-        QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+-                            this, SLOT(screenBrightnessReply(QDBusPendingCallWatcher*)));
++        QDBusMessage msg;
++        QDBusPendingReply<int> reply;
++
++        if (m_brightnessControlsAvailable) {
++          msg = QDBusMessage::createMethodCall("org.kde.Solid.PowerManagement",
++                                                            "/org/kde/Solid/PowerManagement/Actions/BrightnessControl",
++                                                            "org.kde.Solid.PowerManagement.Actions.BrightnessControl",
++                                                            "brightness");
++          reply = QDBusConnection::sessionBus().asyncCall(msg);
++          QDBusPendingCallWatcher *screenWatcher = new QDBusPendingCallWatcher(reply, this);
++          QObject::connect(screenWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
++                              this, SLOT(screenBrightnessReply(QDBusPendingCallWatcher*)));
++        }
++
++        if (m_keyboardBrightnessControlsAvailable) {
++          msg = QDBusMessage::createMethodCall("org.kde.Solid.PowerManagement",
++                                                            "/org/kde/Solid/PowerManagement/Actions/KeyboardBrightnessControl",
++                                                            "org.kde.Solid.PowerManagement.Actions.KeyboardBrightnessControl",
++                                                            "keyboardBrightness");
++          reply = QDBusConnection::sessionBus().asyncCall(msg);
++          QDBusPendingCallWatcher *keyboardWatcher = new QDBusPendingCallWatcher(reply, this);
++          QObject::connect(keyboardWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
++                              this, SLOT(keyboardBrightnessReply(QDBusPendingCallWatcher*)));
++        }
+     //any info concerning lock screen/screensaver goes here
+     } else if (name == "UserActivity") {
+         setData("UserActivity", "IdleTime", KIdleTime::instance()->idleTime());
+@@ -198,6 +236,37 @@ bool PowermanagementEngine::sourceRequestEvent(const QString &name)
      return true;
  }
  
@@ -61,37 +152,37 @@ index d1b9519..a79f5ab 100644
 +{
 +  switch(battery->type()) {
 +      case Solid::Battery::PrimaryBattery:
-+          return QString("Battery");
++          return QLatin1String("Battery");
 +          break;
 +      case Solid::Battery::UpsBattery:
-+          return QString("Ups");
++          return QLatin1String("Ups");
 +          break;
 +      case Solid::Battery::MonitorBattery:
-+          return QString("Monitor");
++          return QLatin1String("Monitor");
 +          break;
 +      case Solid::Battery::MouseBattery:
-+          return QString("Mouse");
++          return QLatin1String("Mouse");
 +          break;
 +      case Solid::Battery::KeyboardBattery:
-+          return QString("Keyboad");
++          return QLatin1String("Keyboad");
 +          break;
 +      case Solid::Battery::PdaBattery:
-+          return QString("Pda");
++          return QLatin1String("Pda");
 +          break;
 +      case Solid::Battery::PhoneBattery:
-+          return QString("Phone");
++          return QLatin1String("Phone");
 +          break;
 +      default:
-+          return QString("Unknown");
++          return QLatin1String("Unknown");
 +  }
 +
-+  return QString("Unknown");
++  return QLatin1String("Unknown");
 +}
 +
  bool PowermanagementEngine::updateSourceEvent(const QString &source)
  {
      if (source == "UserActivity") {
-@@ -244,6 +279,38 @@ void PowermanagementEngine::updateBatteryChargePercent(int newValue, const QStri
+@@ -243,6 +312,45 @@ void PowermanagementEngine::updateBatteryChargePercent(int newValue, const QStri
      setData(source, "Percent", newValue);
  }
  
@@ -109,7 +200,14 @@ index d1b9519..a79f5ab 100644
 +        if (batteryDataContainer) {
 +            const QString batteryVendor = batteryDataContainer->data()["Vendor"].toString();
 +            const QString batteryProduct = batteryDataContainer->data()["Product"].toString();
-+            if (!batteryProduct.isEmpty() && batteryProduct != "Unknown Battery") {
++
++            // Don't show battery name for primary power supply batteries. They usually have cryptic serial number names.
++            const QString batteryType = batteryDataContainer->data()["Type"].toString();
++            bool batteryIsPowerSupply = batteryDataContainer->data()["Is Power Supply"].toBool();
++            bool showBatteryName = batteryType != QLatin1String("Battery") ||
++                                   (batteryType != QLatin1String("Battery") && !batteryIsPowerSupply);
++
++            if (!batteryProduct.isEmpty() && batteryProduct != "Unknown Battery" && showBatteryName) {
 +                if (!batteryVendor.isEmpty()) {
 +                    setData(source, "Pretty Name", QString(batteryVendor + ' ' + batteryProduct));
 +                } else {
@@ -130,7 +228,17 @@ index d1b9519..a79f5ab 100644
  void PowermanagementEngine::updateAcPlugState(bool newState)
  {
      setData("AC Adapter", "Plugged in", newState);
-@@ -292,14 +359,23 @@ void PowermanagementEngine::deviceAdded(const QString& udi)
+@@ -273,8 +381,7 @@ void PowermanagementEngine::deviceAdded(const QString& udi)
+     if (device.isValid()) {
+         const Solid::Battery* battery = device.as<Solid::Battery>();
+ 
+-        if (battery && (battery->type() == Solid::Battery::PrimaryBattery ||
+-                        battery->type() == Solid::Battery::UpsBattery)) {
++        if (battery) {
+             int index = 0;
+             QStringList sourceNames(m_batterySources.values());
+             while (sourceNames.contains(QString("Battery%1").arg(index))) {
+@@ -291,14 +398,24 @@ void PowermanagementEngine::deviceAdded(const QString& udi)
                      SLOT(updateBatteryChargePercent(int,QString)));
              connect(battery, SIGNAL(plugStateChanged(bool,QString)), this,
                      SLOT(updateBatteryPlugState(bool,QString)));
@@ -145,6 +253,7 @@ index d1b9519..a79f5ab 100644
 +
 +            setData(source, "Vendor", device.vendor());
 +            setData(source, "Product", device.product());
++            setData(source, "Capacity", battery->capacity());
 +            setData(source, "Type", batteryType(battery));
  
              setData("Battery", "Sources", sourceNames);
@@ -154,11 +263,70 @@ index d1b9519..a79f5ab 100644
          }
      }
  }
+@@ -309,6 +426,18 @@ void PowermanagementEngine::batteryRemainingTimeChanged(qulonglong time)
+     setData("Battery", "Remaining msec", time);
+ }
+ 
++void PowermanagementEngine::brightnessControlsAvailableChanged(bool available)
++{
++    setData("PowerDevil", "Screen Brightness Available", available);
++    m_brightnessControlsAvailable = available;
++}
++
++void PowermanagementEngine::keyboardBrightnessControlsAvailableChanged(bool available)
++{
++    setData("PowerDevil", "Keyboard Brightness Available", available);
++    m_keyboardBrightnessControlsAvailable = available;
++}
++
+ void PowermanagementEngine::batteryRemainingTimeReply(QDBusPendingCallWatcher *watcher)
+ {
+     QDBusPendingReply<qulonglong> reply = *watcher;
+@@ -327,11 +456,18 @@ void PowermanagementEngine::screenBrightnessChanged(int brightness)
+     setData("PowerDevil", "Screen Brightness", brightness);
+ }
+ 
++void PowermanagementEngine::keyboardBrightnessChanged(int brightness)
++{
++    setData("PowerDevil", "Keyboard Brightness", brightness);
++}
++
+ void PowermanagementEngine::screenBrightnessReply(QDBusPendingCallWatcher *watcher)
+ {
+     QDBusPendingReply<int> reply = *watcher;
+     if (reply.isError()) {
+         kDebug() << "Error getting screen brightness: " << reply.error().message();
++        // FIXME Because the above check doesn't work, we unclaim backlight support as soon as it fails
++        brightnessControlsAvailableChanged(false);
+     } else {
+         screenBrightnessChanged(reply.value());
+     }
+@@ -339,6 +475,20 @@ void PowermanagementEngine::screenBrightnessReply(QDBusPendingCallWatcher *watch
+     watcher->deleteLater();
+ }
+ 
++void PowermanagementEngine::keyboardBrightnessReply(QDBusPendingCallWatcher *watcher)
++{
++    QDBusPendingReply<int> reply = *watcher;
++    if (reply.isError()) {
++        kDebug() << "Error getting keyboard brightness: " << reply.error().message();
++        // FIXME Because the above check doesn't work, we unclaim backlight support as soon as it fails
++        keyboardBrightnessControlsAvailableChanged(false);
++    } else {
++        keyboardBrightnessChanged(reply.value());
++    }
++
++    watcher->deleteLater();
++}
++
+ K_EXPORT_PLASMA_DATAENGINE(powermanagement, PowermanagementEngine)
+ 
+ #include "powermanagementengine.moc"
 diff --git a/plasma/generic/dataengines/powermanagement/powermanagementengine.h b/plasma/generic/dataengines/powermanagement/powermanagementengine.h
-index 35e9ecf..319a17c 100644
+index 512bf6e..dafb6c2 100644
 --- a/plasma/generic/dataengines/powermanagement/powermanagementengine.h
 +++ b/plasma/generic/dataengines/powermanagement/powermanagementengine.h
-@@ -54,7 +54,10 @@ private slots:
+@@ -54,21 +54,32 @@ private slots:
      void updateBatteryChargeState(int newState, const QString& udi);
      void updateBatteryPlugState(bool newState, const QString& udi);
      void updateBatteryChargePercent(int newValue, const QString& udi);
@@ -169,24 +337,130 @@ index 35e9ecf..319a17c 100644
      void deviceRemoved(const QString& udi);
      void deviceAdded(const QString& udi);
      void batteryRemainingTimeChanged(qulonglong time);
-@@ -64,6 +67,7 @@ private slots:
-     void brightnessControlsAvailableChanged(bool available);
+     void batteryRemainingTimeReply(QDBusPendingCallWatcher*);
+     void screenBrightnessChanged(int brightness);
++    void keyboardBrightnessChanged(int brightness);
+     void screenBrightnessReply(QDBusPendingCallWatcher *watcher);
++    void keyboardBrightnessReply(QDBusPendingCallWatcher *watcher);
++    void brightnessControlsAvailableChanged(bool available);
++    void keyboardBrightnessControlsAvailableChanged(bool available);
  
  private:
 +    QString batteryType(const Solid::Battery *battery);
      QStringList basicSourceNames() const;
  
      QStringList m_sources;
+ 
+     QHash<QString, QString> m_batterySources;  // <udi, Battery0>
+ 
++    bool m_brightnessControlsAvailable;
++    bool m_keyboardBrightnessControlsAvailable;
++
+ };
+ 
+ 
+diff --git a/plasma/generic/dataengines/powermanagement/powermanagementjob.cpp b/plasma/generic/dataengines/powermanagement/powermanagementjob.cpp
+index 1b0b8a0..06156d9 100644
+--- a/plasma/generic/dataengines/powermanagement/powermanagementjob.cpp
++++ b/plasma/generic/dataengines/powermanagement/powermanagementjob.cpp
+@@ -94,6 +94,10 @@ void PowerManagementJob::start()
+         setScreenBrightness(parameters().value("brightness").toInt());
+         setResult(true);
+         return;
++    } else if (operation == "setKeyboardBrightness") {
++        setKeyboardBrightness(parameters().value("brightness").toInt());
++        setResult(true);
++        return;
+     }
+ 
+     kDebug() << "don't know what to do with " << operation;
+@@ -103,8 +107,8 @@ void PowerManagementJob::start()
+ bool PowerManagementJob::suspend(const SuspendType &type)
+ {
+     QDBusMessage msg = QDBusMessage::createMethodCall("org.kde.Solid.PowerManagement",
+-                                                      "/org/kde/Solid/PowerManagement",
+-                                                      "org.kde.Solid.PowerManagement",
++                                                      "/org/kde/Solid/PowerManagement/Actions/SuspendSession",
++                                                      "org.kde.Solid.PowerManagement.Actions.SuspendSession",
+                                                       callForType(type));
+     QDBusConnection::sessionBus().asyncCall(msg);
+     return true;
+@@ -130,13 +134,23 @@ QString PowerManagementJob::callForType(const SuspendType &type)
+ void PowerManagementJob::setScreenBrightness(int value)
+ {
+     QDBusMessage msg = QDBusMessage::createMethodCall("org.kde.Solid.PowerManagement",
+-                                                      "/org/kde/Solid/PowerManagement",
+-                                                      "org.kde.Solid.PowerManagement",
++                                                      "/org/kde/Solid/PowerManagement/Actions/BrightnessControl",
++                                                      "org.kde.Solid.PowerManagement.Actions.BrightnessControl",
+                                                       "setBrightness");
+     msg << value;
+     QDBusConnection::sessionBus().asyncCall(msg);
+ }
+ 
++void PowerManagementJob::setKeyboardBrightness(int value)
++{
++    QDBusMessage msg = QDBusMessage::createMethodCall("org.kde.Solid.PowerManagement",
++                                                      "/org/kde/Solid/PowerManagement/Actions/KeyboardBrightnessControl",
++                                                      "org.kde.Solid.PowerManagement.Actions.KeyboardBrightnessControl",
++                                                      "setKeyboardBrightness");
++    msg << value;
++    QDBusConnection::sessionBus().asyncCall(msg);
++}
++
+ void PowerManagementJob::requestShutDown()
+ {
+     KWorkSpace::requestShutDown();
+diff --git a/plasma/generic/dataengines/powermanagement/powermanagementjob.h b/plasma/generic/dataengines/powermanagement/powermanagementjob.h
+index 3b974ab..c1c7bf4 100644
+--- a/plasma/generic/dataengines/powermanagement/powermanagementjob.h
++++ b/plasma/generic/dataengines/powermanagement/powermanagementjob.h
+@@ -1,6 +1,6 @@
+ /*
+  * Copyright 2011 Sebastian Kügler <sebas at kde.org>
+- * 
++ *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU Library General Public License version 2 as
+  * published by the Free Software Foundation
+@@ -41,6 +41,7 @@ class PowerManagementJob : public Plasma::ServiceJob
+         void requestShutDown();
+         QString callForType(const SuspendType &type);
+         void setScreenBrightness(int value);
++        void setKeyboardBrightness(int value);
+ };
+ 
+ #endif // POWERMANAGEMENTJOB_H
+diff --git a/plasma/generic/dataengines/powermanagement/powermanagementservice.operations b/plasma/generic/dataengines/powermanagement/powermanagementservice.operations
+index 533c00a..c9abbf9 100644
+--- a/plasma/generic/dataengines/powermanagement/powermanagementservice.operations
++++ b/plasma/generic/dataengines/powermanagement/powermanagementservice.operations
+@@ -37,4 +37,9 @@
+           <label>The value of the screen brightness</label>
+         </entry>
+     </group>
++    <group name="setKeyboardBrightness">
++        <entry name="brightness" type="Int">
++            <label>The value of the keyboard brightness</label>
++        </entry>
++    </group>
+ </kcfg>
 diff --git a/plasma/generic/applets/batterymonitor/contents/code/logic.js b/plasma/generic/applets/batterymonitor/contents/code/logic.js
-index 974694a..34a5060 100644
+index 974694a..9bd618d 100644
 --- a/plasma/generic/applets/batterymonitor/contents/code/logic.js
 +++ b/plasma/generic/applets/batterymonitor/contents/code/logic.js
-@@ -23,19 +23,24 @@ var disk = 1
+@@ -18,74 +18,159 @@
+  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  */
  
+-var ram = 0
+-var disk = 1
+-
  function updateCumulative() {
      var sum = 0;
 +    var count = 0;
      var charged = true;
++    var plugged = false;
      for (var i=0; i<batteries.count; i++) {
          var b = batteries.get(i);
 +        if (!b["Is Power Supply"]) {
@@ -194,6 +468,7 @@ index 974694a..34a5060 100644
 +        }
          if (b["Plugged in"]) {
              sum += b["Percent"];
++            plugged = true;
          }
          if (b["State"] != "NoCharge") {
              charged = false;
@@ -201,47 +476,57 @@ index 974694a..34a5060 100644
 +        count++;
      }
  
-     if (batteries.count > 0) {
+-    if (batteries.count > 0) {
 -        batteries.cumulativePercent = Math.round(sum/batteries.count);
-+        batteries.cumulativePercent = Math.round(sum/count);
++    if (count > 0) {
++      batteries.cumulativePercent = Math.round(sum/count);
      } else {
-         batteries.cumulativePercent = 0;
+-        batteries.cumulativePercent = 0;
++        // We don't have any power supply batteries
++        // Use the lowest value from any battery
++        if (batteries.count > 0) {
++            var b = lowestBattery();
++            batteries.cumulativePercent = b["Percent"];
++        } else {
++            batteries.cumulativePercent = 0;
++        }
      }
-@@ -46,34 +51,40 @@ function stringForState(batteryData) {
-     var pluggedIn = batteryData["Plugged in"];
-     var percent = batteryData["Percent"];
-     var state = batteryData["State"];
-+    var powerSupply = batteryData["Is Power Supply"];
- 
-+    var text="<b>";
-     if (pluggedIn) {
++    batteries.cumulativePluggedin = plugged;
+     batteries.allCharged = charged;
+ }
+ 
+-function stringForState(batteryData) {
+-    var pluggedIn = batteryData["Plugged in"];
+-    var percent = batteryData["Percent"];
+-    var state = batteryData["State"];
+-
+-    if (pluggedIn) {
 -        if (state == "NoCharge") {
 -            return i18n("<b>%1% (charged)</b>", percent);
 -        } else if (state == "Discharging") {
 -            return i18n("<b>%1% (discharging)</b>", percent);
 -        } else {//charging
 -            return i18n("<b>%1% (charging)</b>", percent);
-+        // According to UPower spec, the chargeState is only valid for primary batteries
-+        if (powerSupply) {
-+            switch(state) {
-+                case "NoCharge": text += i18n("%1% (charged)", percent); break;
-+                case "Discharging": text += i18n("%1% (discharging)", percent); break;
-+                default: text += i18n("%1% (charging)", percent);
-+            }
-+        } else {
-+            text += i18n("%1%", percent);
++function plasmoidStatus() {
++    var status = "PassiveStatus";
++    if (batteries.cumulativePluggedin) {
++        if (batteries.cumulativePercent <= 10) {
++            status = "NeedsAttentionStatus";
++        } else if (!batteries.allCharged) {
++            status = "ActiveStatus";
++        }
++    } else if (batteries.count > 0) { // in case your mouse gets low
++        if (batteries.cumulativePercent && batteries.cumulativePercent <= 10) {
++            status = "NeedsAttentionStatus";
          }
-+    } else {
-+        text += i18nc("Battery is not plugged in", "Not present");
      }
-+    text += "</b>";
- 
+-
 -    return i18nc("Battery is not plugged in", "<b>Not present</b>");
-+    return text;
++    return status;
  }
  
- function updateTooltip() {
-     var text="";
+-function updateTooltip() {
+-    var text="";
 -    for (var i=0; i<batteries.count; i++) {
 -        if (batteries.count == 1) {
 -            text += i18n("Battery:");
@@ -249,91 +534,1565 @@ index 974694a..34a5060 100644
 -            if (text != "") {
 -                text += "<br/>";
 -            }
++function lowestBattery() {
++    if (batteries.count == 0) {
++        return;
++    }
  
 -            text += i18nc("tooltip: placeholder is the battery ID", "Battery %1:", i+1);
-+    for (var i=0; i<batteries.count; i++) {
++    var lowestPercent = 100;
++    var lowestBattery;
++    for(var i=0; i<batteries.count; i++) {
 +        var b = batteries.get(i);
-+        if (text != "") {
-+            text += "<br/>";
++        if (b["Percent"] && b["Percent"] < lowestPercent) {
++            lowestPercent = b["Percent"];
++            lowestBattery = b;
          }
++    }
++    return b;
++}
  
 -        text += " ";
-+        text += b["Pretty Name"];
+-        text += stringForState(pmSource.data["Battery"+i]);
++function stringForBatteryState(batteryData) {
++    if (batteryData["Plugged in"]) {
++        switch(batteryData["State"]) {
++            case "NoCharge": return i18n("Not Charging");
++            case "Discharging": return i18n("Discharging");
++            case "FullyCharged": return i18n("Fully Charged");
++            default: return i18n("Charging");
++        }
++    } else {
++        return i18nc("Battery is currently not present in the bay","Not present");
+     }
++}
++
++function iconForBattery(batteryData,pluggedIn) {
++    switch(batteryData["Type"]) {
++        case "Monitor":
++            return "video-display";
++        case "Mouse":
++            return "input-mouse";
++        case "Keyboard":
++            return "input-keyboard";
++        case "Pda":
++            return "pda";
++        case "Phone":
++            return "phone";
++        default: // Primary and UPS
++            p = batteryData["Percent"];
++            if (p >= 90) {
++                fill = "100";
++            } else if (p >= 70) {
++                fill = "080";
++            } else if (p >= 50) {
++                fill = "060";
++            } else if (p >= 30) {
++                fill = "040";
++            } else if (p >= 10) {
++                fill = "caution";
++            } else {
++                fill = "low";
++            }
+ 
+-    if (text != "") {
+-        text += "<br/>";
++            if (pluggedIn && batteryData["Is Power Supply"]) {
++                return "battery-charging-" + fill;
++            } else {
++                if (p < 5) {
++                    return "dialog-warning"
++                }
++                return "battery-" + fill;
++            }
+     }
++}
++
++function updateTooltip() {
++    var image = "";
++    var text = "";
++    if (batteries.count == 0) {
++        image = "battery-missing";
++        text = i18n("No Batteries Available");
++    } else {
++        var hasPowerSupply = false;
 +
-+        text += ": ";
-         text += stringForState(pmSource.data["Battery"+i]);
++        text = "<table style='white-space: nowrap'>";
++        for(var i=0; i<batteries.count; i++) {
++            var b = batteries.get(i);
++            text += "<tr>";
++            text += "<td align='right'>" + i18nc("Placeholder is battery name", "%1:", b["Pretty Name"]) + " </td>";
++            text += "<td>" + i18nc("Placeholder is battery percentage", "%1%", b["Percent"]) + "</td>";
++            text += "</tr>";
+ 
+-    if (pmSource.data["AC Adapter"]) {
+-        text += i18nc("tooltip", "AC Adapter:") + " ";
+-        text += pmSource.data["AC Adapter"]["Plugged in"] ? i18nc("tooltip", "<b>Plugged in</b>") : i18nc("tooltip", "<b>Not plugged in</b>");
++            if (b["Is Power Supply"]) { hasPowerSupply = true; }
++        }
++        text += "</table>";
++
++        if (hasPowerSupply) {
++            var b = [];
++            b["Percent"] = batteries.cumulativePercent;
++            image = iconForBattery(b, pmSource.data["AC Adapter"]["Plugged in"] ? true : false);
++        } else {
++            var b = lowestBattery();
++            image = iconForBattery(b, false);
++        }
+     }
+     batteries.tooltipText = text;
++    batteries.tooltipImage = image;
+ }
+ 
+ function updateBrightness() {
+@@ -94,16 +179,26 @@ function updateBrightness() {
+         return;
      }
+     dialogItem.disableBrightnessUpdate = true;
+-    dialogItem.screenBrightness = pmSource.data["PowerDevil"]["Screen Brightness"];
++    if (pmSource.data["PowerDevil"]["Screen Brightness"]) {
++        dialogItem.screenBrightness = pmSource.data["PowerDevil"]["Screen Brightness"];
++    }
++    if (pmSource.data["PowerDevil"]["Keyboard Brightness"]) {
++        dialogItem.keyboardBrightness = pmSource.data["PowerDevil"]["Keyboard Brightness"];
++    }
+     dialogItem.disableBrightnessUpdate = false;
+ }
+ 
+-function callForType(type) {
+-    if (type == ram) {
+-        return "suspendToRam";
+-    } else if (type == disk) {
+-        return "suspendToDisk";
+-    }
++// TODO: give translated and formatted string with KGlobal::locale()->prettyFormatDuration(msec);
++function formatDuration(msec) {
++    if (msec == 0 || msec === undefined)
++        return "";
++
++    var time = new Date(msec);
++    var hours = time.getUTCHours();
++    var minutes = time.getUTCMinutes();
  
+-    return "suspendHybrid";
++    var str = "";
++    if (hours > 0) str += i18np("1 hour ", "%1 hours ", hours);
++    if (minutes > 0) str += i18np("1 minute", "%1 minutes", minutes);
++    return str;
+ }
+diff --git a/plasma/generic/applets/batterymonitor/contents/code/platform.js b/plasma/generic/applets/batterymonitor/contents/code/platform.js
+deleted file mode 100644
+index 59af3af..0000000
+--- a/plasma/generic/applets/batterymonitor/contents/code/platform.js
++++ /dev/null
+@@ -1,9 +0,0 @@
+-
+-function shouldOfferSuspend(pmSource) {
+-    return pmSource.data["Sleep States"]["Suspend"];
+-}
+-
+-function shouldOfferHibernate(pmSource) {
+-    return pmSource.data["Sleep States"]["Hibernate"];
+-}
+-
 diff --git a/plasma/generic/applets/batterymonitor/contents/config/main.xml b/plasma/generic/applets/batterymonitor/contents/config/main.xml
-index fc31b3e..28e4a8a 100644
+index fc31b3e..5e9e31d 100644
 --- a/plasma/generic/applets/batterymonitor/contents/config/main.xml
 +++ b/plasma/generic/applets/batterymonitor/contents/config/main.xml
-@@ -9,9 +9,6 @@
-     <entry name="showBatteryString" type="Bool">
-       <default>false</default>
-     </entry>
+@@ -6,12 +6,6 @@
+   <kcfgfile name=""/>
+ 
+   <group name="General">
+-    <entry name="showBatteryString" type="Bool">
+-      <default>false</default>
+-    </entry>
 -    <entry name="showMultipleBatteries" type="Bool">
 -      <default>false</default>
 -    </entry>
      <entry name="showRemainingTime" type="Bool">
        <default>false</default>
      </entry>
+diff --git a/plasma/generic/applets/batterymonitor/contents/ui/AcAdapterItem.qml b/plasma/generic/applets/batterymonitor/contents/ui/AcAdapterItem.qml
+new file mode 100644
+index 0000000..c2216f8
+--- /dev/null
++++ b/plasma/generic/applets/batterymonitor/contents/ui/AcAdapterItem.qml
+@@ -0,0 +1,87 @@
++/*
++ *   Copyright 2012-2013 Daniel Nicoletti <dantti12 at gmail.com>
++ *   Copyright 2013 Kai Uwe Broulik <kde at privat.broulik.de>
++ *
++ *   This program is free software; you can redistribute it and/or modify
++ *   it under the terms of the GNU Library General Public License as
++ *   published by the Free Software Foundation; either version 2 or
++ *   (at your option) any later version.
++ *
++ *   This program is distributed in the hope that it will be useful,
++ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *   GNU General Public License for more details
++ *
++ *   You should have received a copy of the GNU Library General Public
++ *   License along with this program; if not, write to the
++ *   Free Software Foundation, Inc.,
++ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
++ */
++
++import QtQuick 1.1
++import org.kde.plasma.core 0.1 as PlasmaCore
++import org.kde.plasma.components 0.1 as Components
++import org.kde.qtextracomponents 0.1
++
++Item {
++    id: brightnessItem
++    clip: true
++    width: parent.width
++    height: acIcon.height + padding.margins.top + padding.margins.bottom
++
++    property bool pluggedIn
++    property bool showTime
++    property string remainingString
++
++    QIconItem {
++        id: acIcon
++        width: theme.iconSizes.dialog
++        height: width
++        anchors {
++            top: parent.top
++            topMargin: padding.margins.top
++            left: parent.left
++            leftMargin: padding.margins.left
++        }
++
++        icon: pluggedIn ? QIcon("battery-charging-low") : QIcon("battery-low")
++    }
++
++    Components.Label {
++        id: acLabel
++        anchors {
++            top: acIcon.top
++            left: acIcon.right
++            leftMargin: 6
++        }
++        height: paintedHeight
++        text: i18n("AC Adapter")
++    }
++
++    Components.Label {
++        id: acStatus
++        anchors {
++            top: showTime ? acLabel.top : undefined
++            bottom: showTime ? undefined : acIcon.bottom
++            left: showTime ? acLabel.right : acIcon.right
++            leftMargin: showTime ? 3 : 6
++        }
++        height: paintedHeight
++        text: pluggedIn ? i18n("Plugged In") : i18n("Not Plugged In")
++        color: "#77"+(theme.textColor.toString().substr(1))
++    }
++
++    Components.Label {
++        id: acTime
++        anchors {
++            bottom: acIcon.bottom
++            left: acIcon.right
++            leftMargin: 6
++        }
++        height: paintedHeight
++        visible: showTime
++        text: pluggedIn ? i18n("Time remaining until full: %1", remainingString) : i18n("Time remaining until empty: %1", remainingString)
++        color: "#77"+(theme.textColor.toString().substr(1))
++    }
++}
++
+diff --git a/plasma/generic/applets/batterymonitor/contents/ui/BatteryIcon.qml b/plasma/generic/applets/batterymonitor/contents/ui/BatteryIcon.qml
+index 080ab51..6a49d34 100644
+--- a/plasma/generic/applets/batterymonitor/contents/ui/BatteryIcon.qml
++++ b/plasma/generic/applets/batterymonitor/contents/ui/BatteryIcon.qml
+@@ -21,15 +21,13 @@ import QtQuick 1.1
+ import org.kde.plasma.core 0.1 as PlasmaCore
+ 
+ Item {
+-    
+-    property bool monochrome
+     property bool hasBattery
+     property int percent
+     property bool pluggedIn
+-    
++
+     PlasmaCore.Svg {
+         id: svg
+-        imagePath: monochrome ? "icons/battery" : "widgets/battery-oxygen"
++        imagePath: "icons/battery"
+     }
+ 
+     PlasmaCore.SvgItem {
+@@ -39,25 +37,55 @@ Item {
+     }
+ 
+     PlasmaCore.SvgItem {
++        id: fillSvg
+         anchors.fill: parent
+         svg: svg
+         elementId: hasBattery ? fillElement(percent) : "Unavailable"
+-        visible: percent>10 || !hasBattery
++        visible: elementId != ""
+     }
+ 
+     function fillElement(p) {
+-        if (p >= 90) {
+-            return "Fill100";
+-        } else if (p >= 70) {
+-            return "Fill80";
+-        } else if (p >= 50) {
+-            return "Fill60";
+-        } else if (p > 20) {
+-            return "Fill40";
+-        } else if (p >= 10) {
+-            return "Fill20";
++        // We switched from having steps of 20 for the battery percentage to a more accurate
++        // step of 10. This means we break other and older themes.
++        // If the Fill10 element is not found, it is likely that the theme doesn't support
++        // that and we use the older method of obtaining the fill element.
++        if (!svg.hasElement("Fill10")) {
++            if (p >= 90) {
++                return "Fill100";
++            } else if (p >= 70) {
++                return "Fill80";
++            } else if (p >= 50) {
++                return "Fill60";
++            } else if (p > 20) {
++                return "Fill40";
++            } else if (p >= 10) {
++                return "Fill20";
++            }
++            return "";
++        } else {
++            if (p >= 95) {
++                return "Fill100";
++            } else if (p >= 85) {
++                return "Fill90";
++            } else if (p >= 75) {
++                return "Fill90";
++            } else if (p >= 65) {
++                return "Fill80";
++            } else if (p >= 55) {
++                return "Fill60";
++            } else if (p >= 45) {
++                return "Fill50";
++            } else if (p >= 35) {
++                return "Fill40";
++            } else if (p >= 25) {
++                return "Fill30";
++            } else if (p >= 15) {
++                return "Fill20";
++            } else if (p >= 5) {
++                return "Fill10";
++            }
++            return "";
+         }
+-        return "";
+     }
+ 
+     PlasmaCore.SvgItem {
+diff --git a/plasma/generic/applets/batterymonitor/contents/ui/BatteryItem.qml b/plasma/generic/applets/batterymonitor/contents/ui/BatteryItem.qml
+new file mode 100644
+index 0000000..81779ff
+--- /dev/null
++++ b/plasma/generic/applets/batterymonitor/contents/ui/BatteryItem.qml
+@@ -0,0 +1,310 @@
++/*
++ *   Copyright 2012-2013 Daniel Nicoletti <dantti12 at gmail.com>
++ *   Copyright 2013 Kai Uwe Broulik <kde at privat.broulik.de>
++ *
++ *   This program is free software; you can redistribute it and/or modify
++ *   it under the terms of the GNU Library General Public License as
++ *   published by the Free Software Foundation; either version 2 or
++ *   (at your option) any later version.
++ *
++ *   This program is distributed in the hope that it will be useful,
++ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *   GNU General Public License for more details
++ *
++ *   You should have received a copy of the GNU Library General Public
++ *   License along with this program; if not, write to the
++ *   Free Software Foundation, Inc.,
++ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
++ */
++
++import QtQuick 1.1
++import org.kde.plasma.core 0.1 as PlasmaCore
++import org.kde.plasma.components 0.1 as Components
++import org.kde.qtextracomponents 0.1
++import "plasmapackage:/code/logic.js" as Logic
++
++Item {
++    id: batteryItem
++    clip: true
++    width: batteryColumn.width
++    height: expanded ? batteryInfos.height + padding.margins.top + padding.margins.bottom * 2 + actionRow.height
++                     : batteryInfos.height + padding.margins.top + padding.margins.bottom
++
++    Behavior on height { PropertyAnimation {} }
++
++    property bool highlight
++    property bool expanded
++    property bool showChargeAnimation
++
++    property bool isPresent: !model["Is Power Supply"] || model["Plugged in"]
++
++    function updateSelection() {
++        var containsMouse = mouseArea.containsMouse;
++
++        if (highlight || expanded && containsMouse) {
++            padding.opacity = 1;
++        } else if (expanded) {
++            padding.opacity = 0.8;
++        } else if (containsMouse) {
++            padding.opacity = 0.65;
++        } else {
++            padding.opacity = 0;
++        }
++    }
++
++    PlasmaCore.FrameSvgItem {
++        id: padding
++        imagePath: "widgets/viewitem"
++        prefix: "hover"
++        opacity: 0
++        Behavior on opacity { PropertyAnimation {} }
++        anchors.fill: parent
++    }
++
++    MouseArea {
++        id: mouseArea
++        anchors.fill: parent
++        hoverEnabled: true
++        onEntered: updateSelection()
++        onExited: updateSelection()
++        onClicked: {
++            if (expanded) {
++                expanded = false;
++            } else {
++                expanded = true;
++                batteryItem.forceActiveFocus();
++            }
++            updateSelection();
++        }
++    }
++
++    Item {
++        id: batteryInfos
++        height: Math.max(batteryIcon.height, batteryNameLabel.height + batteryPercentBar.height)
++
++        anchors {
++            top: parent.top
++            topMargin: padding.margins.top
++            left: parent.left
++            leftMargin: padding.margins.left
++            right: parent.right
++            rightMargin: padding.margins.right
++        }
++
++        QIconItem {
++            id: batteryIcon
++            width: theme.iconSizes.dialog
++            height: width
++            anchors {
++                verticalCenter: parent.verticalCenter
++                left: parent.left
++            }
++            icon: QIcon(Logic.iconForBattery(model,pluggedIn))
++        }
++
++        SequentialAnimation {
++          id: chargeAnimation
++          running: showChargeAnimation && model["State"] == "Charging"
++          alwaysRunToEnd: true
++          loops: Animation.Infinite
++
++          NumberAnimation {
++              target: batteryIcon
++              properties: "opacity"
++              from: 1.0
++              to: 0.5
++              duration: 750
++              easing.type: Easing.InCubic
++          }
++          NumberAnimation {
++              target: batteryIcon
++              properties: "opacity"
++              from: 0.5
++              to: 1.0
++              duration: 750
++              easing.type: Easing.OutCubic
++          }
++        }
++
++        Components.Label {
++            id: batteryNameLabel
++            anchors {
++                verticalCenter: isPresent ? undefined : batteryIcon.verticalCenter
++                top: isPresent ? parent.top : undefined
++                left: batteryIcon.right
++                leftMargin: 6
++            }
++            height: paintedHeight
++            elide: Text.ElideRight
++            text: model["Pretty Name"]
++        }
++
++        Components.Label {
++            id: batteryStatusLabel
++            anchors {
++                top: batteryNameLabel.top
++                left: batteryNameLabel.right
++                leftMargin: 3
++            }
++            text: Logic.stringForBatteryState(model)
++            height: paintedHeight
++            visible: model["Is Power Supply"]
++            color: "#77"+(theme.textColor.toString().substr(1))
++        }
++
++        Components.ProgressBar {
++            id: batteryPercentBar
++            anchors {
++                bottom: parent.bottom
++                left: batteryIcon.right
++                leftMargin: 6
++                right: batteryPercent.left
++                rightMargin: 6
++            }
++            minimumValue: 0
++            maximumValue: 100
++            visible: isPresent
++            value: parseInt(model["Percent"])
++        }
++
++        Components.Label {
++            id: batteryPercent
++            anchors {
++                verticalCenter: batteryPercentBar.verticalCenter
++                right: parent.right
++            }
++            visible: isPresent
++            text: i18nc("Placeholder is battery percentage", "%1%", model["Percent"])
++        }
++    }
++
++    Column {
++        id: actionRow
++        opacity: expanded ? 1 : 0
++        width: parent.width
++        anchors {
++          top: batteryInfos.bottom
++          topMargin: padding.margins.bottom
++          left: parent.left
++          leftMargin: padding.margins.left
++          right: parent.right
++          rightMargin: padding.margins.right
++          bottomMargin: padding.margins.bottom
++        }
++        spacing: 4
++        Behavior on opacity { PropertyAnimation {} }
++
++        PlasmaCore.SvgItem {
++            svg: PlasmaCore.Svg {
++                id: lineSvg
++                imagePath: "widgets/line"
++            }
++            elementId: "horizontal-line"
++            height: lineSvg.elementSize("horizontal-line").height
++            width: parent.width
++        }
++
++        Row {
++            id: detailsRow
++            width: parent.width
++            spacing: 4
++
++            Column {
++                id: labelsColumn
++                Components.Label {
++                    height: paintedHeight
++                    width: parent.width
++                    horizontalAlignment: Text.AlignRight
++                    onPaintedWidthChanged: {
++                        if (paintedWidth > parent.width) { parent.width = paintedWidth; }
++                    }
++                    text: model["State"] == "Charging" ? i18n("Time To Full:") : i18n("Time To Empty:")
++                    visible: remainingTimeLabel.visible
++                    font.pointSize: theme.smallestFont.pointSize
++                    color: "#99"+(theme.textColor.toString().substr(1))
++                }
++                Components.Label {
++                    height: paintedHeight
++                    width: parent.width
++                    horizontalAlignment: Text.AlignRight
++                    onPaintedWidthChanged: {
++                        if (paintedWidth > parent.width) { parent.width = paintedWidth; }
++                    }
++                    text: i18n("Capacity:")
++                    visible: capacityLabel.visible
++                    font.pointSize: theme.smallestFont.pointSize
++                    color: "#99"+(theme.textColor.toString().substr(1))
++                }
++                Components.Label {
++                    height: paintedHeight
++                    width: parent.width
++                    horizontalAlignment: Text.AlignRight
++                    onPaintedWidthChanged: {
++                        if (paintedWidth > parent.width) { parent.width = paintedWidth; }
++                    }
++                    text: i18n("Vendor:")
++                    visible: vendorLabel.visible
++                    font.pointSize: theme.smallestFont.pointSize
++                    color: "#99"+(theme.textColor.toString().substr(1))
++                }
++                Components.Label {
++                    height: paintedHeight
++                    width: parent.width
++                    horizontalAlignment: Text.AlignRight
++                    onPaintedWidthChanged: {
++                        if (paintedWidth > parent.width) { parent.width = paintedWidth; }
++                    }
++                    text: i18n("Model:")
++                    visible: modelLabel.visible
++                    font.pointSize: theme.smallestFont.pointSize
++                    color: "#99"+(theme.textColor.toString().substr(1))
++                }
++            }
++            Column {
++                width: parent.width - labelsColumn.width - parent.spacing * 2
++                Components.Label { // Remaining Time
++                    id: remainingTimeLabel
++                    height: paintedHeight
++                    width: parent.width
++                    elide: Text.ElideRight
++                    text: Logic.formatDuration(model["Remaining Time"])
++                    visible: showRemainingTime && model["Is Power Supply"] && model["State"] != "NoCharge" && text
++                    font.pointSize: theme.smallestFont.pointSize
++                    color: "#99"+(theme.textColor.toString().substr(1))
++                }
++                Components.Label { // Capacity
++                    id: capacityLabel
++                    height: paintedHeight
++                    width: parent.width
++                    elide: Text.ElideRight
++                    text: i18nc("Placeholder is battery capacity", "%1%", model["Capacity"])
++                    visible: model["Capacity"] != "" && model["Capacity"] !== undefined
++                    font.pointSize: theme.smallestFont.pointSize
++                    color: "#99"+(theme.textColor.toString().substr(1))
++                }
++                Components.Label { // Vendor
++                    id: vendorLabel
++                    height: paintedHeight
++                    width: parent.width
++                    elide: Text.ElideRight
++                    text: model["Vendor"]
++                    visible: model["Vendor"] != "" && model["Vendor"] !== undefined
++                    font.pointSize: theme.smallestFont.pointSize
++                    color: "#99"+(theme.textColor.toString().substr(1))
++                }
++                Components.Label { // Model
++                    id: modelLabel
++                    height: paintedHeight
++                    width: parent.width
++                    elide: Text.ElideRight
++                    text: model["Product"]
++                    visible: model["Product"] != "" && model["Product"] !== undefined
++                    font.pointSize: theme.smallestFont.pointSize
++                    color: "#99"+(theme.textColor.toString().substr(1))
++                }
++            }
++        }
++    }
++}
++
+diff --git a/plasma/generic/applets/batterymonitor/contents/ui/BrightnessItem.qml b/plasma/generic/applets/batterymonitor/contents/ui/BrightnessItem.qml
+new file mode 100644
+index 0000000..34c596c
+--- /dev/null
++++ b/plasma/generic/applets/batterymonitor/contents/ui/BrightnessItem.qml
+@@ -0,0 +1,89 @@
++/*
++ *   Copyright 2012-2013 Daniel Nicoletti <dantti12 at gmail.com>
++ *   Copyright 2013 Kai Uwe Broulik <kde at privat.broulik.de>
++ *
++ *   This program is free software; you can redistribute it and/or modify
++ *   it under the terms of the GNU Library General Public License as
++ *   published by the Free Software Foundation; either version 2 or
++ *   (at your option) any later version.
++ *
++ *   This program is distributed in the hope that it will be useful,
++ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *   GNU General Public License for more details
++ *
++ *   You should have received a copy of the GNU Library General Public
++ *   License along with this program; if not, write to the
++ *   Free Software Foundation, Inc.,
++ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
++ */
++
++import QtQuick 1.1
++import org.kde.plasma.core 0.1 as PlasmaCore
++import org.kde.plasma.components 0.1 as Components
++import org.kde.qtextracomponents 0.1
++
++Item {
++    id: brightnessItem
++    clip: true
++    width: parent.width
++    height: Math.max(brightnessIcon.height, brightnessLabel.height + brightnessSlider.height) + padding.margins.top + padding.margins.bottom
++
++    property alias icon: brightnessIcon.icon
++    property alias label: brightnessLabel.text
++    property alias value: brightnessSlider.value
++
++    signal changed(int screenBrightness)
++
++    QIconItem {
++        id: brightnessIcon
++        width: theme.iconSizes.dialog
++        height: width
++        anchors {
++            verticalCenter: parent.verticalCenter
++            topMargin: padding.margins.top
++            bottomMargin: padding.margins.bottom
++            left: parent.left
++            leftMargin: padding.margins.left
++        }
++    }
++
++    Components.Label {
++        id: brightnessLabel
++        anchors {
++            top: parent.top
++            topMargin: padding.margins.top
++            left: brightnessIcon.right
++            leftMargin: 6
++        }
++        height: paintedHeight
++    }
++
++    Components.Slider {
++        id: brightnessSlider
++        anchors {
++            bottom: parent.bottom
++            bottomMargin: padding.margins.bottom
++            left: brightnessIcon.right
++            right: brightnessPercent.left
++            leftMargin: 6
++            rightMargin: 6
++        }
++        minimumValue: 0
++        maximumValue: 100
++        stepSize: 10
++        onValueChanged: changed(value)
++    }
++
++    Components.Label {
++        id: brightnessPercent
++        anchors {
++            right: parent.right
++            rightMargin: padding.margins.right
++            verticalCenter: brightnessSlider.verticalCenter
++        }
++        height: paintedHeight
++        text: i18nc("Placeholder is brightness percentage", "%1%", brightnessSlider.value)
++    }
++}
++
+diff --git a/plasma/generic/applets/batterymonitor/contents/ui/CompactRepresentation.qml b/plasma/generic/applets/batterymonitor/contents/ui/CompactRepresentation.qml
+new file mode 100644
+index 0000000..e9dc772
+--- /dev/null
++++ b/plasma/generic/applets/batterymonitor/contents/ui/CompactRepresentation.qml
+@@ -0,0 +1,112 @@
++/*
++*   Copyright 2011 Sebastian Kügler <sebas at kde.org>
++*   Copyright 2011 Viranch Mehta <viranch.mehta at gmail.com>
++*   Copyright 2013 Kai Uwe Broulik <kde at privat.broulik.de>
++*
++*   This program is free software; you can redistribute it and/or modify
++*   it under the terms of the GNU Library General Public License as
++*   published by the Free Software Foundation; either version 2 or
++*   (at your option) any later version.
++*
++*   This program is distributed in the hope that it will be useful,
++*   but WITHOUT ANY WARRANTY; without even the implied warranty of
++*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++*   GNU General Public License for more details
++*
++*   You should have received a copy of the GNU Library General Public
++*   License along with this program; if not, write to the
++*   Free Software Foundation, Inc.,
++*   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
++*/
++
++import QtQuick 1.1
++import org.kde.plasma.core 0.1 as PlasmaCore
++import org.kde.plasma.components 0.1 as Components
++import "plasmapackage:/code/logic.js" as Logic
++
++ListView {
++    id: view
++
++    property int minimumWidth
++    property int minimumHeight
++
++    property bool hasBattery
++
++    property QtObject pmSource
++    property QtObject batteries
++
++    property bool singleBattery
++
++    model: singleBattery ? 1 : batteries
++
++    anchors.fill: parent
++    orientation: ListView.Horizontal
++    interactive: false
++
++    function isConstrained() {
++        return (plasmoid.formFactor == Vertical || plasmoid.formFactor == Horizontal);
++    }
++
++    Component.onCompleted: {
++        if (!isConstrained()) {
++            minimumHeight = theme.iconSizes.dialog;
++            minimumWidth = minimumHeight * view.count;
++        } else {
++            // NOTE: Keep in sync with systray
++            minimumHeight = 24;
++            minimumWidth = 24;
++        }
++    }
++
++    delegate: Item {
++        id: batteryContainer
++
++        property bool hasBattery: view.singleBattery ? batteries.count : model["Plugged in"]
++        property int percent: view.singleBattery ? batteries.cumulativePercent : model["Percent"]
++        property bool pluggedIn: pmSource.data["AC Adapter"]["Plugged in"]
++
++        width: view.width/view.count
++        height: view.height
++
++        property real iconSize: Math.min(width, height)
++
++        Column {
++            anchors.fill: parent
++
++            BatteryIcon {
++                id: batteryIcon
++                anchors.centerIn: isConstrained() ? parent : undefined
++                anchors.horizontalCenter: isConstrained() ? undefined : parent.horizontalCenter
++                hasBattery: batteryContainer.hasBattery
++                percent: batteryContainer.percent
++                pluggedIn: batteryContainer.pluggedIn
++                height: isConstrained() ? batteryContainer.iconSize : batteryContainer.iconSize - batteryLabel.height
++                width: height
++            }
++
++            Components.Label {
++                id: batteryLabel
++                width: parent.width
++                height: paintedHeight
++                horizontalAlignment: Text.AlignHCenter
++                text: i18nc("battery percentage below battery icon", "%1%", percent)
++                font.pixelSize: Math.max(batteryContainer.iconSize/8, 10)
++                visible: !isConstrained()
++            }
++        }
++    }
++
++    MouseArea {
++        id: mouseArea
++        anchors.fill: parent
++        hoverEnabled: true
++        onClicked: plasmoid.togglePopup()
++
++        PlasmaCore.ToolTip {
++            id: tooltip
++            target: mouseArea
++            image: batteries.tooltipImage
++            subText: batteries.tooltipText
++        }
++    }
++}
 diff --git a/plasma/generic/applets/batterymonitor/contents/ui/PopupDialog.qml b/plasma/generic/applets/batterymonitor/contents/ui/PopupDialog.qml
-index 3ffb15f..bd9f491 100644
+index 76fb1ce..4f46834 100644
 --- a/plasma/generic/applets/batterymonitor/contents/ui/PopupDialog.qml
 +++ b/plasma/generic/applets/batterymonitor/contents/ui/PopupDialog.qml
-@@ -52,7 +52,7 @@ Item {
-         Repeater {
-             model: dialog.model
-             Components.Label {
+@@ -1,5 +1,6 @@
+ /*
+  *   Copyright 2011 Viranch Mehta <viranch.mehta at gmail.com>
++ *   Copyright 2013 Kai Uwe Broulik <kde at privat.broulik.de>
+  *
+  *   This program is free software; you can redistribute it and/or modify
+  *   it under the terms of the GNU Library General Public License as
+@@ -18,176 +19,106 @@
+  */
+ 
+ import QtQuick 1.1
++import org.kde.plasma.core 0.1 as PlasmaCore
+ import org.kde.plasma.components 0.1 as Components
++import org.kde.qtextracomponents 0.1
+ import "plasmapackage:/code/logic.js" as Logic
+ 
+ Item {
+     id: dialog
+-    width: childrenRect.width+24
+-    height: childrenRect.height+24
++    property int actualHeight: batteryColumn.implicitHeight + settingsColumn.height + separator.height + 10 // 10 = separator margins
+ 
+-    property alias model: batteryLabels.model
+-    property alias hasBattery: batteryIcon.hasBattery
+-    property alias percent: batteryIcon.percent
++    property alias model: batteryList.model
+     property bool pluggedIn
++    property bool showRemainingTime
++
++    property bool popupShown // somehow plasmoid.popupShowing isn't working
++
++    property bool isBrightnessAvailable
+     property alias screenBrightness: brightnessSlider.value
+-    property int remainingMsec
+-    property alias showSuspendButton: suspendButton.visible
+-    property alias showHibernateButton: hibernateButton.visible
+ 
++    property bool isKeyboardBrightnessAvailable
++    property alias keyboardBrightness: keyboardBrightnessSlider.value
+ 
+-    signal suspendClicked(int type)
+     signal brightnessChanged(int screenBrightness)
++    signal keyboardBrightnessChanged(int keyboardBrightness)
+     signal powermanagementChanged(bool checked)
+ 
++    PlasmaCore.FrameSvgItem {
++        id: padding
++        imagePath: "widgets/viewitem"
++        prefix: "hover"
++        opacity: 0
++    }
++
+     Column {
+-        id: labels
+-        spacing: 6
++        id: batteryColumn
++        spacing: 4
++        width: parent.width
+         anchors {
+-            top: parent.top
+             left: parent.left
+-            margins: 12
+-        }
+-        Repeater {
+-            model: dialog.model
+-            Components.Label {
 -                text: model.count>1 ? i18nc("Placeholder is the battery ID", "Battery %1:", index+1) : i18n("Battery:")
-+                text: model["Pretty Name"] + ':'
-                 width: labels.width
-                 horizontalAlignment: Text.AlignRight
-             }
+-                width: labels.width
+-                horizontalAlignment: Text.AlignRight
+-            }
+-        }
+-
+-        Components.Label {
+-            text: i18n("AC Adapter:")
+-            anchors.right: parent.right
+-            anchors.bottomMargin: 12
+-        }
+-
+-        Components.Label {
+-            text: i18nc("Label for remaining time", "Time Remaining:")
+-            visible: remainingTime.visible
+-            anchors.right: parent.right
+-        }
+-
+-        Components.Label {
+-            text: i18nc("Label for power management inhibition", "Power management enabled:")
+-            anchors.right: parent.right
++            right: parent.right
++            top: plasmoid.location == BottomEdge ? parent.top : undefined
++            bottom: plasmoid.location == BottomEdge ? undefined : parent.bottom
+         }
+ 
+-        Components.Label {
+-            text: i18n("Screen Brightness:")
+-            anchors.right: parent.right
++        Repeater {
++            id: batteryList
++            delegate: BatteryItem { showChargeAnimation: popupShown }
+         }
+     }
+ 
+     Column {
+-        id: values
+-        spacing: 6
+-        anchors {
+-            top: parent.top
+-            left: labels.right
+-            margins: 12
+-        }
++        id: settingsColumn
++        spacing: 0
++        width: parent.width
+ 
+-        Column {
+-            id: upperValues
+-            spacing: 6
+-            anchors {
+-                left: values.left
+-            }
+-
+-            Repeater {
+-                id: batteryLabels
+-                Components.Label {
+-                    text: Logic.stringForState(model)
+-                    font.weight: Font.Bold
+-                }
+-            }
+-
+-            Components.Label {
+-                text: dialog.pluggedIn ? i18n("Plugged in") : i18n("Not plugged in")
+-                font.weight: Font.Bold
+-                anchors.bottomMargin: 12
+-            }
+-
+-            Components.Label {
+-                id: remainingTime
+-                text: formatDuration(remainingMsec);
+-                font.weight: Font.Bold
+-                visible: text!=""
+-            }
+-        }
+-
+-        Column {
+-            id: lowerValues
+-            spacing: 6
+-            width: upperValues.width + batteryIcon.width * 2
+-            anchors {
+-                left: values.left
+-            }
+-            Components.CheckBox {
+-                checked: true
+-                onClicked: powermanagementChanged(checked)
+-                x: 1
+-            }
+-
+-            Components.Slider {
+-                id: brightnessSlider
+-                width: lowerValues.width
+-                minimumValue: 0
+-                maximumValue: 100
+-                stepSize: 10
+-                onValueChanged: brightnessChanged(value)
+-            }
++        anchors {
++            left: parent.left
++            right: parent.right
++            top: plasmoid.location == BottomEdge ? undefined : parent.top
++            bottom: plasmoid.location == BottomEdge ? parent.bottom : undefined
+         }
+-    }
+ 
+-    // TODO: give translated and formatted string with KGlobal::locale()->prettyFormatDuration(msec);
+-    function formatDuration(msec) {
+-        if (msec==0)
+-            return "";
+-
+-        var time = new Date(msec);
+-        var hours = time.getUTCHours();
+-        var minutes = time.getUTCMinutes();
+-        var str = "";
+-        if (hours > 0) str += i18np("1 hour ", "%1 hours ", hours);
+-        if (minutes > 0) str += i18np("1 minute", "%1 minutes", minutes);
+-        return str;
+-    }
++        BrightnessItem {
++            id: brightnessSlider
++            icon: QIcon("video-display")
++            label: i18n("Display Brightness")
++            visible: isBrightnessAvailable
++            onChanged: brightnessChanged(value)
+ 
+-    Row {
+-        anchors {
+-            top: values.bottom
+-            margins: 12
+-            right: values.right
+         }
+ 
+-        Components.ToolButton {
+-            id: suspendButton
+-            iconSource: "system-suspend"
+-            text: i18nc("Suspend the computer to RAM; translation should be short", "Sleep")
+-            onClicked: suspendClicked(Logic.ram)
++        BrightnessItem {
++            id: keyboardBrightnessSlider
++            icon: QIcon("input-keyboard")
++            label: i18n("Keyboard Brightness")
++            visible: isKeyboardBrightnessAvailable
++            onChanged: keyboardBrightnessChanged(value)
+         }
+ 
+-        Components.ToolButton {
+-            id: hibernateButton
+-            iconSource: "system-suspend-hibernate"
+-            text: i18nc("Suspend the computer to disk; translation should be short", "Hibernate")
+-            onClicked: suspendClicked(Logic.disk)
++        PowerManagementItem {
++            id: pmSwitch
++            onEnabledChanged: powermanagementChanged(enabled)
+         }
+     }
+ 
+-    BatteryIcon {
+-        id: batteryIcon
+-        monochrome: false
+-        pluggedIn: dialog.pluggedIn
++    PlasmaCore.SvgItem {
++        id: separator
++        svg: PlasmaCore.Svg {
++            id: lineSvg
++            imagePath: "widgets/line"
++        }
++        elementId: "horizontal-line"
++        height: lineSvg.elementSize("horizontal-line").height
++        width: parent.width
+         anchors {
+-            top: parent.top
+-            right: values.right
+-            topMargin: 12
++            top: plasmoid.location == BottomEdge ? undefined : settingsColumn.bottom
++            bottom: plasmoid.location == BottomEdge ? settingsColumn.top : undefined
++            leftMargin: padding.margins.left
++            rightMargin: padding.margins.right
++            topMargin: 5
++            bottomMargin: 5
+         }
+-        width: height
+-        height: hibernateButton.height * 2
+     }
+ }
+diff --git a/plasma/generic/applets/batterymonitor/contents/ui/PowerManagementItem.qml b/plasma/generic/applets/batterymonitor/contents/ui/PowerManagementItem.qml
+new file mode 100644
+index 0000000..c82a86d
+--- /dev/null
++++ b/plasma/generic/applets/batterymonitor/contents/ui/PowerManagementItem.qml
+@@ -0,0 +1,67 @@
++/*
++ *   Copyright 2012-2013 Daniel Nicoletti <dantti12 at gmail.com>
++ *   Copyright 2013 Kai Uwe Broulik <kde at privat.broulik.de>
++ *
++ *   This program is free software; you can redistribute it and/or modify
++ *   it under the terms of the GNU Library General Public License as
++ *   published by the Free Software Foundation; either version 2 or
++ *   (at your option) any later version.
++ *
++ *   This program is distributed in the hope that it will be useful,
++ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *   GNU General Public License for more details
++ *
++ *   You should have received a copy of the GNU Library General Public
++ *   License along with this program; if not, write to the
++ *   Free Software Foundation, Inc.,
++ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
++ */
++
++import QtQuick 1.1
++import org.kde.plasma.core 0.1 as PlasmaCore
++import org.kde.plasma.components 0.1 as Components
++import org.kde.qtextracomponents 0.1
++
++Item {
++    id: brightnessItem
++    clip: true
++    width: parent.width
++    height: Math.max(pmCheckBox.height, pmLabel.height) + padding.margins.top + padding.margins.bottom
++
++    property alias enabled: pmCheckBox.checked
++
++    signal enabledChanged(bool checked)
++
++    Components.CheckBox {
++        id: pmCheckBox
++        anchors {
++            verticalCenter: parent.verticalCenter
++            left: parent.left
++            leftMargin: padding.margins.left + (theme.iconSizes.dialog - width)
++            topMargin: padding.margins.top
++            bottomMargin: padding.margins.bottom
++        }
++        checked: true
++        onCheckedChanged: enabledChanged(checked)
++    }
++
++    Components.Label {
++        id: pmLabel
++        anchors {
++            verticalCenter: pmCheckBox.verticalCenter
++            left: pmCheckBox.right
++            leftMargin: 6
++        }
++        height: paintedHeight
++        text: i18n("Enable Power Management")
++    }
++
++    MouseArea {
++        anchors.fill: parent
++
++        onReleased: pmCheckBox.released();
++        onPressed: pmCheckBox.forceActiveFocus();
++    }
++}
++
+diff --git a/plasma/generic/applets/batterymonitor/contents/ui/ScrollableListView.qml b/plasma/generic/applets/batterymonitor/contents/ui/ScrollableListView.qml
+new file mode 100644
+index 0000000..c3cb818
+--- /dev/null
++++ b/plasma/generic/applets/batterymonitor/contents/ui/ScrollableListView.qml
+@@ -0,0 +1,58 @@
++/*
++ *   Copyright 2012 Daniel Nicoletti <dantti12 at gmail.com>
++ *
++ *   This program is free software; you can redistribute it and/or modify
++ *   it under the terms of the GNU Library General Public License as
++ *   published by the Free Software Foundation; either version 2 or
++ *   (at your option) any later version.
++ *
++ *   This program is distributed in the hope that it will be useful,
++ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *   GNU General Public License for more details
++ *
++ *   You should have received a copy of the GNU Library General Public
++ *   License along with this program; if not, write to the
++ *   Free Software Foundation, Inc.,
++ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
++ */
++
++import QtQuick 1.1
++import org.kde.plasma.core 0.1 as PlasmaCore
++import org.kde.plasma.components 0.1 as Components
++import org.kde.qtextracomponents 0.1
++
++FocusScope {
++    property alias delegate: list.delegate
++    property alias model: list.model
++    property alias view: list
++    property alias interactive: list.interactive
++    property alias currentIndex: list.currentIndex
++    signal countChanged()
++
++    Component.onCompleted: {
++        list.countChanged.connect(countChanged)
++    }
++
++    ListView {
++        id: list
++        clip: true
++        focus: true
++        anchors {
++            left:   parent.left
++            right:  scrollBar.visible ? scrollBar.left : parent.right
++            top :   parent.top
++            bottom: parent.bottom
++        }
++        boundsBehavior: Flickable.StopAtBounds
++    }
++    Components.ScrollBar {
++        id: scrollBar
++        flickableItem: list
++        anchors {
++            right: parent.right
++            top: list.top
++            bottom: list.bottom
++        }
++    }
++}
 diff --git a/plasma/generic/applets/batterymonitor/contents/ui/batterymonitor.qml b/plasma/generic/applets/batterymonitor/contents/ui/batterymonitor.qml
-index c69c3a5..3a58aae 100644
+index a5e1c13..f082c38 100644
 --- a/plasma/generic/applets/batterymonitor/contents/ui/batterymonitor.qml
 +++ b/plasma/generic/applets/batterymonitor/contents/ui/batterymonitor.qml
-@@ -49,13 +49,12 @@ Item {
-             property int minimumHeight
+@@ -1,6 +1,7 @@
+ /*
+  *   Copyright 2011 Sebastian Kügler <sebas at kde.org>
+  *   Copyright 2011 Viranch Mehta <viranch.mehta at gmail.com>
++ *   Copyright 2013 Kai Uwe Broulik <kde at privat.broulik.de>
+  *
+  *   This program is free software; you can redistribute it and/or modify
+  *   it under the terms of the GNU Library General Public License as
+@@ -21,128 +22,40 @@
+ import QtQuick 1.1
+ import org.kde.plasma.core 0.1 as PlasmaCore
+ import "plasmapackage:/code/logic.js" as Logic
+-import "plasmapackage:/code/platform.js" as Platform
  
-             property bool showOverlay: false
--            property bool showMultipleBatteries: false
-             property bool hasBattery: pmSource.data["Battery"]["Has Battery"]
+ Item {
+     id: batterymonitor
+-    property int minimumWidth: dialogItem.width
+-    property int minimumHeight: dialogItem.height
++    property int minimumWidth: theme.iconSizes.dialog * 9
++    property int minimumHeight: dialogItem.actualHeight
++    property int maximumHeight: dialogItem.actualHeight
+ 
+     property bool show_remaining_time: false
+ 
++    PlasmaCore.Theme { id: theme }
++
+     Component.onCompleted: {
++        plasmoid.aspectRatioMode = IgnoreAspectRatio
+         Logic.updateCumulative();
++        plasmoid.status = Logic.plasmoidStatus();
+         Logic.updateTooltip();
+         Logic.updateBrightness();
+         plasmoid.addEventListener('ConfigChanged', configChanged);
++        plasmoid.popupEvent.connect(popupEventSlot);
+     }
  
-             property QtObject pmSource: plasmoid.rootItem.pmSource
-             property QtObject batteries: plasmoid.rootItem.batteries
+     function configChanged() {
+         show_remaining_time = plasmoid.readConfig("showRemainingTime");
+     }
  
+-    property Component compactRepresentation: Component {
+-        ListView {
+-            id: view
+-
+-            property int minimumWidth
+-            property int minimumHeight
+-
+-            property bool showOverlay: false
+-            property bool showMultipleBatteries: false
+-            property bool hasBattery: pmSource.data["Battery"]["Has Battery"]
+-
+-            property QtObject pmSource: plasmoid.rootItem.pmSource
+-            property QtObject batteries: plasmoid.rootItem.batteries
+-
 -            property bool singleBattery: isConstrained() || !showMultipleBatteries || !hasBattery
-+            property bool singleBattery: isConstrained() || !hasBattery
+-
+-            model: singleBattery ? 1 : batteries
+-
+-            PlasmaCore.Theme { id: theme }
+-
+-            anchors.fill: parent
+-            orientation: ListView.Horizontal
+-
+-            function isConstrained() {
+-                return (plasmoid.formFactor == Vertical || plasmoid.formFactor == Horizontal);
+-            }
+-
+-            Component.onCompleted: {
+-                if (!isConstrained()) {
+-                    minimumWidth = 32;
+-                    minimumHeight = 32;
+-                }
+-                plasmoid.addEventListener('ConfigChanged', configChanged);
+-            }
+-
+-            function configChanged() {
+-                showOverlay = plasmoid.readConfig("showBatteryString");
+-                showMultipleBatteries = plasmoid.readConfig("showMultipleBatteries");
+-            }
+-
+-            delegate: Item {
+-                id: batteryContainer
+-
+-                property bool hasBattery: view.singleBattery ? batteries.cumulativePluggedin : model["Plugged in"]
+-                property int percent: view.singleBattery ? batteries.cumulativePercent : model["Percent"]
+-                property bool pluggedIn: pmSource.data["AC Adapter"]["Plugged in"]
+-
+-                width: view.width/view.count
+-                height: view.height
+-
+-                property real size: Math.min(width, height)
+-
+-                BatteryIcon {
+-                    id: batteryIcon
+-                    monochrome: true
+-                    hasBattery: parent.hasBattery
+-                    percent: parent.percent
+-                    pluggedIn: parent.pluggedIn
+-                    width: size; height: size
+-                    anchors.centerIn: parent
+-                }
+-
+-                Rectangle {
+-                    id: labelRect
+-                    // should be 40 when size is 90
+-                    width: Math.max(parent.size*4/9, 35)
+-                    height: width/2
+-                    anchors.centerIn: parent
+-                    color: theme.backgroundColor
+-                    border.color: "grey"
+-                    border.width: 2
+-                    radius: 4
+-                    opacity: hasBattery ? (showOverlay ? 0.7 : (isConstrained() ? 0 : mouseArea.containsMouse*0.7)) : 0
+-
+-                    Behavior on opacity { NumberAnimation { duration: 100 } }
+-                }
+-
+-                Text {
+-                    id: overlayText
+-                    text: i18nc("overlay on the battery, needs to be really tiny", "%1%", percent);
+-                    color: theme.textColor
+-                    font.pixelSize: Math.max(parent.size/8, 11)
+-                    anchors.centerIn: labelRect
+-                    // keep the opacity 1 when labelRect.opacity=0.7
+-                    opacity: labelRect.opacity/0.7
+-                }
+-            }
+-
+-            MouseArea {
+-                id: mouseArea
+-                anchors.fill: parent
+-                hoverEnabled: true
+-                onClicked: plasmoid.togglePopup()
++    function popupEventSlot(popped) {
++        dialogItem.popupShown = popped;
++    }
  
-             model: singleBattery ? 1 : batteries
+-                PlasmaCore.ToolTip {
+-                    id: tooltip
+-                    target: mouseArea
+-                    image: "battery"
+-                    subText: batteries.tooltipText
+-                }
+-            }
+-        }
++    property Component compactRepresentation: CompactRepresentation {
++        hasBattery: pmSource.data["Battery"]["Has Battery"]
++        pmSource: plasmoid.rootItem.pmSource
++        batteries: plasmoid.rootItem.batteries
++        singleBattery: isConstrained() || !hasBattery
+     }
  
-@@ -63,6 +62,7 @@ Item {
+     property QtObject pmSource: PlasmaCore.DataSource {
+@@ -150,12 +63,14 @@ Item {
+         engine: "powermanagement"
+         connectedSources: sources
+         onDataChanged: {
++            Logic.updateCumulative();
++            plasmoid.status = Logic.plasmoidStatus();
+             Logic.updateTooltip();
+             Logic.updateBrightness();
+         }
+         onSourceAdded: {
+             if (source == "Battery0") {
+-		disconnectSource(source);
++                disconnectSource(source);
+                 connectSource(source);
+             }
+         }
+@@ -173,44 +88,31 @@ Item {
  
-             anchors.fill: parent
-             orientation: ListView.Horizontal
-+            interactive: false
+         onDataChanged: {
+             Logic.updateCumulative();
+-
+-            var status = "PassiveStatus";
+-            if (batteries.cumulativePluggedin) {
+-                if (batteries.cumulativePercent <= 10) {
+-                    status = "NeedsAttentionStatus";
+-                } else if (!batteries.allCharged) {
+-                    status = "ActiveStatus";
+-                }
+-            }
+-            plasmoid.status = status;
++            plasmoid.status = Logic.plasmoidStatus();
+         }
  
-             function isConstrained() {
-                 return (plasmoid.formFactor == Vertical || plasmoid.formFactor == Horizontal);
-@@ -78,7 +78,6 @@ Item {
+         property int cumulativePercent
+-        property bool cumulativePluggedin: count > 0
++        property bool cumulativePluggedin
+         // true  --> all batteries charged
+         // false --> one of the batteries charging/discharging
+         property bool allCharged
+         property string tooltipText
++        property string tooltipImage
+     }
  
-             function configChanged() {
-                 showOverlay = plasmoid.readConfig("showBatteryString");
--                showMultipleBatteries = plasmoid.readConfig("showMultipleBatteries");
-             }
+     PopupDialog {
+         id: dialogItem
+         property bool disableBrightnessUpdate: false
+         model: batteries
+-        hasBattery: batteries.cumulativePluggedin
+-        percent: batteries.cumulativePercent
++        anchors.fill: parent
++
++        isBrightnessAvailable: pmSource.data["PowerDevil"]["Screen Brightness Available"] ? true : false
++        isKeyboardBrightnessAvailable: pmSource.data["PowerDevil"]["Keyboard Brightness Available"] ? true : false
++
++        showRemainingTime: show_remaining_time
++
+         pluggedIn: pmSource.data["AC Adapter"]["Plugged in"]
+-        remainingMsec: parent.show_remaining_time ? Number(pmSource.data["Battery"]["Remaining msec"]) : 0
+-        showSuspendButton: Platform.shouldOfferSuspend(pmSource)
+-        showHibernateButton: Platform.shouldOfferHibernate(pmSource)
  
-             delegate: Item {
+-        onSuspendClicked: {
+-            plasmoid.togglePopup();
+-            service = pmSource.serviceForSource("PowerDevil");
+-            var operationName = Logic.callForType(type);
+-            operation = service.operationDescription(operationName);
+-            service.startOperationCall(operation);
+-        }
+         onBrightnessChanged: {
+             if (disableBrightnessUpdate) {
+                 return;
+@@ -220,6 +122,15 @@ Item {
+             operation.brightness = screenBrightness;
+             service.startOperationCall(operation);
+         }
++        onKeyboardBrightnessChanged: {
++            if (disableBrightnessUpdate) {
++                return;
++            }
++            service = pmSource.serviceForSource("PowerDevil");
++            operation = service.operationDescription("setKeyboardBrightness");
++            operation.brightness = keyboardBrightness;
++            service.startOperationCall(operation);
++        }
+         property int cookie1: -1
+         property int cookie2: -1
+         onPowermanagementChanged: {
 diff --git a/plasma/generic/applets/batterymonitor/contents/ui/config.ui b/plasma/generic/applets/batterymonitor/contents/ui/config.ui
-index 3df38e2..bffc755 100644
+deleted file mode 100644
+index 3df38e2..0000000
 --- a/plasma/generic/applets/batterymonitor/contents/ui/config.ui
-+++ b/plasma/generic/applets/batterymonitor/contents/ui/config.ui
-@@ -25,16 +25,6 @@
-     </widget>
-    </item>
-    <item>
++++ /dev/null
+@@ -1,54 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8"?>
+-<ui version="4.0">
+- <class>batteryConfig</class>
+- <widget class="QWidget" name="batteryConfig">
+-  <property name="geometry">
+-   <rect>
+-    <x>0</x>
+-    <y>0</y>
+-    <width>247</width>
+-    <height>73</height>
+-   </rect>
+-  </property>
+-  <property name="windowTitle">
+-   <string>Configure Battery Monitor</string>
+-  </property>
+-  <layout class="QVBoxLayout" name="verticalLayout">
+-   <item>
+-    <widget class="QCheckBox" name="kcfg_showBatteryString">
+-     <property name="toolTip">
+-      <string/>
+-     </property>
+-     <property name="text">
+-      <string>Show charge &information</string>
+-     </property>
+-    </widget>
+-   </item>
+-   <item>
 -    <widget class="QCheckBox" name="kcfg_showMultipleBatteries">
 -     <property name="toolTip">
 -      <string/>
@@ -344,54 +2103,91 @@ index 3df38e2..bffc755 100644
 -    </widget>
 -   </item>
 -   <item>
-     <spacer name="verticalSpacer">
-      <property name="orientation">
-       <enum>Qt::Vertical</enum>
-From: Kai Uwe Broulik <kde at privat.broulik.de>
-Date: Mon, 20 May 2013 19:52:21 +0000
-Subject: No linebreak in tooltip. We do them manually anyways.
-X-Git-Url: http://quickgit.kde.org/?p=kde-workspace.git&a=commitdiff&h=175e902b88a2c6a1c1ca37f428208e83c1660937
----
-No linebreak in tooltip. We do them manually anyways.
-
-CCBUG: 317404
----
-
-
---- a/plasma/generic/applets/batterymonitor/contents/code/logic.js
-+++ b/plasma/generic/applets/batterymonitor/contents/code/logic.js
-@@ -96,7 +96,7 @@
-         text += i18nc("tooltip", "AC Adapter:") + " ";
-         text += pmSource.data["AC Adapter"]["Plugged in"] ? i18nc("tooltip", "<b>Plugged in</b>") : i18nc("tooltip", "<b>Not plugged in</b>");
-     }
--    batteries.tooltipText = text;
-+    batteries.tooltipText = "<p style='white-space: nowrap'>" + text + "</p>";
- }
+-    <spacer name="verticalSpacer">
+-     <property name="orientation">
+-      <enum>Qt::Vertical</enum>
+-     </property>
+-     <property name="sizeHint" stdset="0">
+-      <size>
+-       <width>20</width>
+-       <height>15</height>
+-      </size>
+-     </property>
+-    </spacer>
+-   </item>
+-  </layout>
+- </widget>
+- <resources/>
+- <connections/>
+-</ui>
+diff --git a/plasma/generic/applets/batterymonitor/metadata.desktop b/plasma/generic/applets/batterymonitor/metadata.desktop
+index cd8f1a2..2b70e2c 100644
+--- a/plasma/generic/applets/batterymonitor/metadata.desktop
++++ b/plasma/generic/applets/batterymonitor/metadata.desktop
+@@ -159,7 +159,6 @@ Comment[zh_CN]=查看电池电源的状态
+ Comment[zh_TW]=查看您的電池的電力狀態
+ Encoding=UTF-8
+ Keywords=Power Management;Battery;System;Energy;
+-Keywords[bs]=Upravljanje napajenjem, Baterija, Sistem, Energija
+ Keywords[ca]=Sistema de gestió d'energia;Bateria;Sistema;Energia;
+ Keywords[cs]=Správa napájení;Baterie;Systém;Energie;
+ Keywords[da]=Strømstyring;battery;system;energi;
+@@ -167,17 +166,16 @@ Keywords[de]=Energieverwaltungssystem;Akku;System;Energie;
+ Keywords[el]=Διαχείριση ισχύος·Μπαταρία·Σύστημα·Ενέργεια·
+ Keywords[es]=Gestión de energía;Batería;Sistema;Energía;
+ Keywords[fi]=Virranhallinta;Akku;Järjestelmä;Virransäästö;
+-Keywords[fr]=Gestion de l'énergie, Batterie, Système, Énergie, 
+-Keywords[gl]=Power Management;Battery;System;Energy;xestión da enerxía;batería;sistema;
++Keywords[fr]=Gestion de l'énergie, Batterie, Système, Énergie,
+ Keywords[hu]=Energiakezelés;Akkumulátor;Rendszer;Energia;
+-Keywords[ia]=Gestion de energia; Batteria;Systema; Energia;
+-Keywords[it]=Gestione energetica;Batteria;Sistema;Energia;
++Keywords[ia]=Gestion de energia;Batteria;Systema; Energia;
+ Keywords[kk]=Power Management;Battery;System;Energy;
+ Keywords[lt]=Energijos valdymas,Baterija,Sistema,Energija,akumuliatorius;
+ Keywords[mr]=वीज व्यवस्थापन; बॅटरी; प्रणाली; ऊर्जा;
+ Keywords[nb]=Strømstyring; Batteri; System; Energi;
+ Keywords[nl]=Energiebeheer;Batterij;Accu;Systeem;Energie;
+-Keywords[pl]=Zarządzanie energią;bateria;system;energia;
++Keywords[pa]=ਪਾਵਰ ਪਰਬੰਧ;ਬੈਟਰੀ;ਸਿਸਟਮ;ਊਰਜਾ;
++Keywords[pl]=Zarządzanie Energią;Bateria;System;Energia
+ Keywords[pt]=Gestão de Energia;Bateria;Sistema;Energia;
+ Keywords[pt_BR]=Gerenciamento de energia;Bateria;Sistema;Energia;
+ Keywords[ru]=Power Management;Battery;System;Energy;управление питанием;батарея;система;энергия;энергопотребление
+@@ -198,17 +196,17 @@ Type=Service
+ X-KDE-ServiceTypes=Plasma/Applet,Plasma/PopupApplet
  
- function updateBrightness() {
-
-From: Kai Uwe Broulik <kde at privat.broulik.de>
-Date: Tue, 21 May 2013 08:43:16 +0000
-Subject: Consider All The Batteries[tm]
-X-Git-Url: http://quickgit.kde.org/?p=kde-workspace.git&a=commitdiff&h=2fd181ef31382e071126ea2a401506d3b1aaa4af
----
-Consider All The Batteries[tm]
-When a new device was added, it wasn't added to the dataengine right away
-
-CCBUG: 317404
----
-
-
---- a/plasma/generic/dataengines/powermanagement/powermanagementengine.cpp
-+++ b/plasma/generic/dataengines/powermanagement/powermanagementengine.cpp
-@@ -341,8 +341,7 @@
-     if (device.isValid()) {
-         const Solid::Battery* battery = device.as<Solid::Battery>();
+ X-Plasma-API=declarativeappletscript
+-X-Plasma-DefaultSize=100,100
++X-Plasma-DefaultSize=450,300
+ X-Plasma-MainScript=ui/batterymonitor.qml
+ X-Plasma-ConfigPlugins=powerdevilprofilesconfig,powerdevilactivitiesconfig,powerdevilglobalconfig
+ X-Plasma-NotificationArea=true
  
--        if (battery && (battery->type() == Solid::Battery::PrimaryBattery ||
--                        battery->type() == Solid::Battery::UpsBattery)) {
-+        if (battery) {
-             int index = 0;
-             QStringList sourceNames(m_batterySources.values());
-             while (sourceNames.contains(QString("Battery%1").arg(index))) {
-
+-X-KDE-PluginInfo-Author=Sebastian Kügler
++X-KDE-PluginInfo-Author=Sebastian Kügler, Kai Uwe Broulik
+ X-KDE-PluginInfo-Category=System Information
+-X-KDE-PluginInfo-Email=sebas at kde.org
++X-KDE-PluginInfo-Email=sebas at kde.org, kde at privat.broulik.de
+ X-KDE-PluginInfo-License=GPL
+ X-KDE-PluginInfo-Name=battery
+-X-KDE-PluginInfo-Version=1.0
++X-KDE-PluginInfo-Version=2.0
+ X-KDE-PluginInfo-Website=http://vizZzion.org
+ X-KDE-PluginInfo-Depends=
+ X-KDE-PluginInfo-EnabledByDefault=true
+diff --git a/plasma/generic/applets/batterymonitor/platformcontents/touch/code/platform.js b/plasma/generic/applets/batterymonitor/platformcontents/touch/code/platform.js
+deleted file mode 100644
+index aa57ab8..0000000
+--- a/plasma/generic/applets/batterymonitor/platformcontents/touch/code/platform.js
++++ /dev/null
+@@ -1,9 +0,0 @@
+-
+-function shouldOfferSuspend() {
+-    return false;
+-}
+-
+-function shouldOfferHibernate() {
+-    return false;
+-}
+-
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/kde4-kdebase-workspace.git/commitdiff/775841400e7e3a8a3ede3f2eded9bed765e350b0




More information about the pld-cvs-commit mailing list