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

Applets

battery.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright 2007-2008 by Riccardo Iaconelli <riccardo@kde.org>          *
00003  *   Copyright 2007-2008 by Sebastian Kuegler <sebas@kde.org>              *
00004  *   Copyright 2007 by Luka Renko <lure@kubuntu.org>                       *
00005  *                                                                         *
00006  *   This program is free software; you can redistribute it and/or modify  *
00007  *   it under the terms of the GNU General Public License as published by  *
00008  *   the Free Software Foundation; either version 2 of the License, or     *
00009  *   (at your option) any later version.                                   *
00010  *                                                                         *
00011  *   This program is distributed in the hope that it will be useful,       *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU General Public License for more details.                          *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU General Public License     *
00017  *   along with this program; if not, write to the                         *
00018  *   Free Software Foundation, Inc.,                                       *
00019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
00020  ***************************************************************************/
00021 
00022 #include "battery.h"
00023 
00024 #include <QApplication>
00025 #include <QDBusConnection>
00026 #include <QDBusInterface>
00027 #include <QPainter>
00028 #include <QStyleOptionGraphicsItem>
00029 #include <QFont>
00030 #include <QGraphicsSceneHoverEvent>
00031 #include <QGraphicsGridLayout>
00032 #include <QGraphicsLinearLayout>
00033 
00034 #include <KDebug>
00035 #include <KIcon>
00036 #include <KLocalizedString>
00037 #include <KSharedConfig>
00038 #include <KToolInvocation>
00039 #include <KDialog>
00040 #include <KColorScheme>
00041 #include <KConfigDialog>
00042 #include <KGlobalSettings>
00043 #include <KPushButton>
00044 
00045 #include <kworkspace/kworkspace.h>
00046 
00047 #include <solid/control/powermanager.h>
00048 #include <solid/powermanagement.h>
00049 
00050 #include <Plasma/Svg>
00051 #include <Plasma/Theme>
00052 #include <Plasma/Animator>
00053 #include <Plasma/Extender>
00054 #include <Plasma/ExtenderItem>
00055 #include <Plasma/PopupApplet>
00056 #include <Plasma/Label>
00057 #include <Plasma/Slider>
00058 #include <Plasma/PushButton>
00059 #include <Plasma/CheckBox>
00060 #include <Plasma/ComboBox>
00061 #include <Plasma/IconWidget>
00062 
00063 
00064 Battery::Battery(QObject *parent, const QVariantList &args)
00065     : Plasma::PopupApplet(parent, args),
00066       m_isEmbedded(false),
00067       m_extenderVisible(false),
00068       m_controlsLayout(0),
00069       m_batteryLayout(0),
00070       m_statusLabel(0),
00071       m_batteryLabel(0),
00072       m_profileLabel(0),
00073       m_profileCombo(0),
00074       m_brightnessSlider(0),
00075       m_theme(0),
00076       m_availableProfiles(QStringList()),
00077       m_currentProfile(0),
00078       m_animId(-1),
00079       m_alpha(1),
00080       m_fadeIn(false),
00081       m_acAnimId(-1),
00082       m_acAlpha(1),
00083       m_acFadeIn(false),
00084       m_batteryAnimId(-1),
00085       m_batteryAlpha(1),
00086       m_batteryFadeIn(true),
00087       m_isHovered(false),
00088       m_firstRun(true),
00089       m_numOfBattery(0),
00090       m_acadapter_plugged(false),
00091       m_remainingMSecs(0)
00092 {
00093     kDebug() << "Loading applet battery";
00094     setAcceptsHoverEvents(true);
00095     setHasConfigurationInterface(true);
00096     setPopupIcon(QIcon());
00097     resize(128, 128);
00098     setAspectRatioMode(Plasma::ConstrainedSquare );
00099     m_textRect = QRectF();
00100     m_remainingMSecs = 0;
00101     m_extenderApplet = 0;
00102     m_theme = new Plasma::Svg(this);
00103     m_theme->setImagePath("widgets/battery-oxygen");
00104     m_theme->setContainsMultipleImages(false);
00105 }
00106 
00107 void Battery::init()
00108 {
00109     KConfigGroup cg = config();
00110     m_showBatteryString = cg.readEntry("showBatteryString", false);
00111     m_showMultipleBatteries = cg.readEntry("showMultipleBatteries", !m_isEmbedded);
00112 
00113     showBattery(false);
00114     m_theme->resize(contentsRect().size());
00115     if (m_acadapter_plugged) {
00116         showAcAdapter(true);
00117     }
00118     showBattery(true);
00119 
00120     m_theme->resize(contentsRect().size());
00121     m_font = QApplication::font();
00122     m_font.setWeight(QFont::Bold);
00123 
00124     m_boxAlpha = 128;
00125     m_boxHoverAlpha = 192;
00126 
00127     readColors();
00128     connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), SLOT(readColors()));
00129     connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), SLOT(readColors()));
00130 
00131     const QStringList& battery_sources = dataEngine("powermanagement")->query("Battery")["sources"].toStringList();
00132 
00133     //connect sources
00134     connectSources();
00135 
00136     foreach (const QString &battery_source, battery_sources) {
00137         //kDebug() << "BatterySource:" << battery_source;
00138         dataUpdated(battery_source, dataEngine("powermanagement")->query(battery_source));
00139     }
00140     m_numOfBattery = battery_sources.size();
00141 
00142     dataUpdated("AC Adapter", dataEngine("powermanagement")->query("AC Adapter"));
00143 
00144     if (!m_isEmbedded) {
00145         Plasma::ExtenderItem *eItem = new Plasma::ExtenderItem(extender());
00146         eItem->setName("powermanagement");
00147         initBatteryExtender(eItem);
00148         extender()->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
00149     }
00150 }
00151 
00152 void Battery::constraintsEvent(Plasma::Constraints constraints)
00153 {
00154     //kDebug() << "ConstraintsEvent, Dude." << contentsRect();
00155     if (!m_showMultipleBatteries || m_numOfBattery < 2) {
00156         setAspectRatioMode(Plasma::Square);
00157     } else {
00158         setAspectRatioMode(Plasma::KeepAspectRatio);
00159     }
00160 
00161     if (constraints & (Plasma::FormFactorConstraint | Plasma::SizeConstraint)) {
00162         if (formFactor() == Plasma::Vertical) {
00163             if (!m_showMultipleBatteries) {
00164                 setMinimumHeight(qMax(m_textRect.height(), size().width()));
00165             } else {
00166                 setMinimumHeight(qMax(m_textRect.height(), size().width()*m_numOfBattery));
00167             }
00168             setMinimumWidth(0);
00169             //kDebug() << "Vertical FormFactor";
00170         } else if (formFactor() == Plasma::Horizontal) {
00171             if (!m_showMultipleBatteries) {
00172                 setMinimumWidth(qMax(m_textRect.width(), size().height()));
00173             } else {
00174                 setMinimumWidth(qMax(m_textRect.width(), size().height()*m_numOfBattery));
00175             }
00176             setMinimumHeight(0);
00177             //kDebug() << "Horizontal FormFactor" << m_textRect.width() << contentsRect().height();
00178         } else {
00179             setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
00180             setMinimumSize(KIconLoader::SizeSmall, KIconLoader::SizeSmall);
00181         }
00182 
00183         m_theme->resize(contentsRect().size().toSize());
00184         m_font.setPointSize(qMax(KGlobalSettings::smallestReadableFont().pointSize(),
00185                                  qRound(contentsRect().height() / 10)));
00186         update();
00187     }
00188 }
00189 
00190 void Battery::dataUpdated(const QString& source, const Plasma::DataEngine::Data &data)
00191 {
00192     if (source.startsWith("Battery")) {
00193         m_batteries_data[source] = data;
00194     } else if (source == "AC Adapter") {
00195         m_acadapter_plugged = data["Plugged in"].toBool();
00196         showAcAdapter(m_acadapter_plugged);
00197     } else if (source == "PowerDevil") {
00198         m_availableProfiles = data["availableProfiles"].toStringList();
00199         m_currentProfile = data["currentProfile"].toString();
00200         //kDebug() << "PowerDevil profiles:" << m_availableProfiles << "[" << m_currentProfile << "]";
00201     } else {
00202         kDebug() << "Applet::Dunno what to do with " << source;
00203     }
00204     if (source == "Battery0") {
00205         m_remainingMSecs  = data["Remaining msec"].toInt();
00206         //kDebug() << "Remaining msecs on battery:" << m_remainingMSecs;
00207     }
00208 
00209     updateStatus();
00210     update();
00211 }
00212 
00213 void Battery::createConfigurationInterface(KConfigDialog *parent)
00214 {
00215     QWidget *widget = new QWidget(parent);
00216     ui.setupUi(widget);
00217     parent->addPage(widget, i18n("General"), Applet::icon());
00218     connect(parent, SIGNAL(applyClicked()), this, SLOT(configAccepted()));
00219     connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted()));
00220     ui.showBatteryStringCheckBox->setChecked(m_showBatteryString ? Qt::Checked : Qt::Unchecked);
00221     ui.showMultipleBatteriesCheckBox->setChecked(m_showMultipleBatteries ? Qt::Checked : Qt::Unchecked);
00222 }
00223 
00224 void Battery::configAccepted()
00225 {
00226     KConfigGroup cg = config();
00227 
00228     if (m_showBatteryString != ui.showBatteryStringCheckBox->isChecked()) {
00229         m_showBatteryString = !m_showBatteryString;
00230         cg.writeEntry("showBatteryString", m_showBatteryString);
00231         showLabel(m_showBatteryString);
00232     }
00233 
00234     if (m_showMultipleBatteries != ui.showMultipleBatteriesCheckBox->isChecked()) {
00235         m_showMultipleBatteries = !m_showMultipleBatteries;
00236         cg.writeEntry("showMultipleBatteries", m_showMultipleBatteries);
00237         kDebug() << "Show multiple battery changed: " << m_showMultipleBatteries;
00238         emit sizeHintChanged(Qt::PreferredSize);
00239     }
00240 
00241     //reconnect sources
00242     disconnectSources();
00243     connectSources();
00244 
00245     emit configNeedsSaving();
00246 }
00247 
00248 void Battery::readColors()
00249 {
00250     m_textColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor);
00251     m_boxColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor);
00252     m_boxColor.setAlpha(m_boxAlpha);
00253 }
00254 
00255 void Battery::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
00256 {
00257     showLabel(true);
00258     //showAcAdapter(false); // to test the animation without constant plugging
00259     //showBattery(false); // to test the animation without constant plugging
00260     m_isHovered = true;
00261     Applet::hoverEnterEvent(event);
00262 }
00263 
00264 void Battery::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
00265 {
00266     if (!m_showBatteryString && !m_isEmbedded) {
00267         showLabel(false);
00268     }
00269     //showAcAdapter(true); // to test the animation without constant plugging
00270     //showBattery(true); // to test the animation without constant plugging
00271     //m_isHovered = false;
00272     Applet::hoverLeaveEvent(event);
00273 }
00274 
00275 Battery::~Battery()
00276 {
00277 }
00278 
00279 void Battery::suspend()
00280 {
00281     QDBusConnection dbus( QDBusConnection::sessionBus() );
00282     QDBusInterface iface( "org.kde.kded", "/modules/powerdevil", "org.kde.PowerDevil", dbus );
00283     iface.call( "suspend", Solid::Control::PowerManager::ToRam );
00284 }
00285 
00286 void Battery::hibernate()
00287 {
00288     QDBusConnection dbus( QDBusConnection::sessionBus() );
00289     QDBusInterface iface( "org.kde.kded", "/modules/powerdevil", "org.kde.PowerDevil", dbus );
00290     iface.call( "suspend", Solid::Control::PowerManager::ToDisk );
00291 }
00292 
00293 void Battery::brightnessChanged(const int brightness)
00294 {
00295     Solid::Control::PowerManager::setBrightness(brightness);
00296 }
00297 
00298 void Battery::updateSlider(const float brightness)
00299 {
00300     if (m_brightnessSlider->value() != (int)brightness) {
00301         m_brightnessSlider->setValue((int) brightness);
00302     }
00303 }
00304 
00305 void Battery::setFullBrightness()
00306 {
00307     brightnessChanged(100);
00308     updateSlider(100);
00309 }
00310 
00311 void Battery::setEmbedded(const bool embedded)
00312 {
00313     m_isEmbedded = embedded;
00314 }
00315 
00316 void Battery::initBatteryExtender(Plasma::ExtenderItem *item)
00317 {
00318     // We only show the extender for applets that are not embedded, as
00319     // that would create infinitve loops, you really don't want an applet
00320     // extender when the applet is embedded into another applet, such
00321     // as the battery applet is also embedded into the battery's extender.
00322     if (!m_isEmbedded) {
00323         int row = 0;
00324         int rowHeight = 20;
00325         int columnWidth = 120;
00326 
00327         QGraphicsWidget *controls = new QGraphicsWidget(item);
00328         //controls->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
00329         //controls->resize(500, 500);
00330         m_controlsLayout = new QGraphicsGridLayout(controls);
00331         m_controlsLayout->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00332 
00333         m_controlsLayout->setColumnPreferredWidth(0, rowHeight);
00334         m_controlsLayout->setColumnMinimumWidth(1, 2*columnWidth);
00335         m_controlsLayout->setColumnPreferredWidth(2, rowHeight);
00336         m_controlsLayout->setHorizontalSpacing(0);
00337 
00338         m_batteryLayout = new QGraphicsGridLayout(m_controlsLayout);
00339 
00340         //m_batteryLayout->setColumnPreferredWidth(0, 100);
00341         m_batteryLayout->setColumnPreferredWidth(1, columnWidth);
00342         //m_batteryLayout->setRowPreferredHeight(row, 60);
00343         m_batteryLabel = new Plasma::Label(controls);
00344         m_batteryLabel->setMinimumSize(200, 80);
00345         m_batteryLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00346 
00347         //m_batteryLabel->nativeWidget()->setWordWrap(false);
00348         m_batteryLabel->nativeWidget()->setAlignment(Qt::AlignTop);
00349         // FIXME: larger fonts screw up this label
00350         m_batteryLayout->addItem(m_batteryLabel, 0, 0, 1, 1, Qt::AlignLeft);
00351 
00352         Battery *m_extenderApplet = static_cast<Battery*>(Plasma::Applet::load("battery"));
00353         if (m_extenderApplet) {
00354             m_extenderApplet->setParent(this);
00355             m_extenderApplet->setAcceptsHoverEvents(false);
00356             m_extenderApplet->setParentItem(controls);
00357             m_extenderApplet->setEmbedded(true);
00358             m_extenderApplet->setMinimumSize(80, 80); // TODO: Multiple batteries?
00359             m_extenderApplet->resize(80, 80);
00360             m_extenderApplet->setBackgroundHints(NoBackground);
00361             m_extenderApplet->setFlag(QGraphicsItem::ItemIsMovable, false);
00362             m_extenderApplet->init();
00363             m_extenderApplet->showBatteryLabel(true);
00364             m_batteryLayout->addItem(m_extenderApplet, 0, 1, 1, 1, Qt::AlignRight);
00365             m_extenderApplet->updateConstraints(Plasma::StartupCompletedConstraint);
00366         }
00367 
00368         m_controlsLayout->addItem(m_batteryLayout, row, 0, 1, 3);
00369         row++;
00370 
00371         Plasma::Label *brightnessLabel = new Plasma::Label(controls);
00372         brightnessLabel->setText(i18n("Screen Brightness"));
00373         brightnessLabel->nativeWidget()->setWordWrap(false);
00374         m_controlsLayout->addItem(brightnessLabel, row, 0, 1, 3);
00375         brightnessLabel->nativeWidget()->setWordWrap(false);
00376         row++;
00377 
00378         m_brightnessSlider = new Plasma::Slider(controls);
00379         m_brightnessSlider->setRange(0, 100);
00380         m_brightnessSlider->setValue(Solid::Control::PowerManager::brightness());
00381         m_brightnessSlider->nativeWidget()->setTickInterval(10);
00382         m_brightnessSlider->setOrientation(Qt::Horizontal);
00383         connect(m_brightnessSlider, SIGNAL(valueChanged(int)),
00384                 this, SLOT(brightnessChanged(int)));
00385 
00386         Solid::Control::PowerManager::Notifier *notifier = Solid::Control::PowerManager::notifier();
00387 
00388         connect(notifier, SIGNAL(brightnessChanged(float)),
00389                 this, SLOT(updateSlider(float)));
00390         m_controlsLayout->addItem(m_brightnessSlider, row, 1, 1, 1);
00391 
00392         Plasma::IconWidget *brightnessIcon = new Plasma::IconWidget(controls);
00393         brightnessIcon->setIcon("ktip");
00394         connect(brightnessIcon, SIGNAL(clicked()),
00395                 this, SLOT(setFullBrightness()));
00396         brightnessIcon->setDrawBackground(true);
00397         brightnessIcon->setMinimumSize(rowHeight, rowHeight);
00398         m_controlsLayout->addItem(brightnessIcon, row, 2, 1, 1);
00399         m_controlsLayout->setRowSpacing(row, 10);
00400         row++;
00401 
00402         m_profileLabel = new Plasma::Label(controls);
00403         m_profileLabel->setText(i18n("Power Profile"));
00404         m_controlsLayout->addItem(m_profileLabel, row, 0, 1, 3);
00405         row++;
00406 
00407         m_profileCombo = new Plasma::ComboBox(controls);
00408         // This is necessary until Qt task #217874 is fixed
00409         m_profileCombo->setZValue(100);
00410         connect(m_profileCombo, SIGNAL(activated(QString)),
00411                 this, SLOT(setProfile(QString)));
00412 
00413         m_controlsLayout->addItem(m_profileCombo, row, 1, 1, 2);
00414         row++;
00415 
00416         Plasma::Label *actionsLabel = new Plasma::Label(controls);
00417         actionsLabel->setText(i18n("Actions"));
00418         actionsLabel->nativeWidget()->setWordWrap(false);
00419         m_controlsLayout->addItem(actionsLabel, row, 0, 1, 3);
00420         row++;
00421 
00422         QGraphicsGridLayout *actionsLayout = new QGraphicsGridLayout(m_controlsLayout);
00423         actionsLayout->setColumnSpacing(0, 0);
00424         actionsLayout->setColumnSpacing(1, 0);
00425 
00426         // Sleep and Hibernate buttons
00427         QSet<Solid::PowerManagement::SleepState> sleepstates = Solid::PowerManagement::supportedSleepStates();
00428         foreach (const Solid::PowerManagement::SleepState &sleepstate, sleepstates) {
00429             if (sleepstate == Solid::PowerManagement::StandbyState) {
00430                 // Not interesting at this point ...
00431 
00432             } else if (sleepstate == Solid::PowerManagement::SuspendState) {
00433                 Plasma::IconWidget *suspendButton = new Plasma::IconWidget(controls);
00434                 suspendButton->setIcon("system-suspend");
00435                 suspendButton->setText(i18n("Sleep"));
00436                 suspendButton->setOrientation(Qt::Horizontal);
00437                 suspendButton->setMaximumHeight(36);
00438                 suspendButton->setDrawBackground(true);
00439                 actionsLayout->addItem(suspendButton, 0, 0);
00440                 connect(suspendButton, SIGNAL(clicked()), this, SLOT(suspend()));
00441                 actionsLayout->setColumnSpacing(0, 20);
00442             } else if (sleepstate == Solid::PowerManagement::HibernateState) {
00443                 Plasma::IconWidget *hibernateButton = new Plasma::IconWidget(controls);
00444                 hibernateButton->setIcon("system-suspend-hibernate");
00445                 hibernateButton->setText(i18n("Hibernate"));
00446                 hibernateButton->setOrientation(Qt::Horizontal);
00447                 hibernateButton->setMaximumHeight(36);
00448                 hibernateButton->setDrawBackground(true);
00449                 actionsLayout->addItem(hibernateButton, 0, 1);
00450                 connect(hibernateButton, SIGNAL(clicked()), this, SLOT(hibernate()));
00451             }
00452         }
00453         m_controlsLayout->addItem(actionsLayout, row, 1, 1, 2);
00454         m_controlsLayout->setRowSpacing(row, 10);
00455         row++;
00456 
00457         // More settings button
00458         Plasma::IconWidget *configButton = new Plasma::IconWidget(controls);
00459         configButton->setText(i18n("More..."));
00460         configButton->setOrientation(Qt::Horizontal);
00461         configButton->setMaximumHeight(36);
00462         configButton->setDrawBackground(true);
00463         configButton->setIcon("preferences-system-power-management");
00464         //configButton->nativeWidget()->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
00465         connect(configButton, SIGNAL(clicked()), this, SLOT(openConfig()));
00466 
00467         //QGraphicsGridLayout *moreLayout = new QGraphicsGridLayout(m_controlsLayout);
00468         //moreLayout->setColumnPreferredWidth(0, columnWidth);
00469         actionsLayout->addItem(configButton, 1, 1, Qt::AlignLeft);
00470 
00471         //m_controlsLayout->addItem(moreLayout, row, 1, 1, 2);
00472 
00473         controls->setLayout(m_controlsLayout);
00474         item->setWidget(controls);
00475         item->setTitle(i18n("Power Management"));
00476     }
00477 }
00478 
00479 void Battery::popupEvent(bool show)
00480 {
00481     m_extenderVisible = show;
00482     updateStatus();
00483 }
00484 
00485 void Battery::updateStatus()
00486 {
00487     if (!m_extenderVisible) {
00488         return;
00489     }
00490 
00491     QString batteryLabelText = QString("<br />");
00492     if (m_numOfBattery && m_batteryLabel) {
00493         QHashIterator<QString, QHash<QString, QVariant > > battery_data(m_batteries_data);
00494         int bnum = 0;
00495         int hours = m_remainingMSecs/1000/3600;
00496         int minutes = qRound(m_remainingMSecs/60000) % 60;
00497 
00498         while (battery_data.hasNext()) {
00499             bnum++;
00500             battery_data.next();
00501             QString state = battery_data.value()["State"].toString();
00502             if (state == "Discharging" && m_remainingMSecs > 0) {
00503 
00504                 // FIXME: Somehow, m_extenderApplet is null here, so the label never becomes visible
00505                 if (m_extenderApplet) {
00506                     m_extenderApplet->showBatteryLabel(true);
00507                 }
00508 
00509                 // we don't have too much accuracy so only give hours and minutes
00510                 int msecs = hours * 1000 * 3600 + minutes * 60000;
00511                 batteryLabelText.append(i18n("Time remaining: <b>%1</b><br />", KGlobal::locale()->prettyFormatDuration(msecs)));
00512                 kDebug() << "hours:" << hours << "minutes:" << minutes;
00513                 /* might be useful for the tooltip
00514                 kDebug() << "hours:" << hours << "minutes:" << minutes;
00515                 QTime t = QTime(hours, minutes);
00516                 kDebug() << t;
00517                 KLocale tmpLocale(*KGlobal::locale());
00518                 tmpLocale.setTimeFormat("%k:h %Mm remaining");
00519                 kDebug() << tmpLocale.formatTime(t, false, true); // minutes, hours as duration
00520                 */
00521             } else {
00522                 if (m_extenderApplet) {
00523                     m_extenderApplet->showBatteryLabel(false);
00524                 }
00525                 if (m_numOfBattery == 0) {
00526                     //kDebug() << "zero batteries ...";
00527                 } else if (m_numOfBattery == 1) {
00528                     if (battery_data.value()["Plugged in"].toBool()) {
00529                         if (state == "NoCharge") {
00530                             batteryLabelText.append(i18n("<b>Battery:</b> %1% (fully charged)<br />", battery_data.value()["Percent"].toString()));
00531                         } else if (state == "Discharging") {
00532                             batteryLabelText.append(i18nc("Shown when a time estimate is not available", "<b>Battery:</b> %1% (discharging)<br />", battery_data.value()["Percent"].toString()));
00533                         } else {
00534                             batteryLabelText.append(i18n("<b>Battery:</b> %1% (charging)<br />", battery_data.value()["Percent"].toString()));
00535                         }
00536                     } else {
00537                         batteryLabelText.append(i18nc("Battery is not plugged in", "<b>Battery:</b> not present<br />"));
00538                     }
00539                 } else {
00540                     //kDebug() << "More batteries ...";
00541                     if (state == "NoCharge") {
00542                         batteryLabelText.append(i18n("<b>Battery %1:</b> %2% (fully charged)<br />", bnum, battery_data.value()["Percent"].toString()));
00543                     } else if (state == "Discharging") {
00544                         batteryLabelText.append(i18n("<b>Battery %1:</b> %2% (discharging)<br />", bnum, battery_data.value()["Percent"].toString()));
00545                     } else {
00546                         batteryLabelText.append(i18n("<b>Battery %1:</b> %2% (charging)<br />", bnum, battery_data.value()["Percent"].toString()));
00547                     }
00548                 }
00549             }
00550         }
00551 
00552         if (m_acadapter_plugged) {
00553             batteryLabelText.append(i18n("<b>AC Adapter:</b> Plugged in"));
00554         } else {
00555             batteryLabelText.append(i18n("<b>AC Adapter:</b> Not plugged in"));
00556         }
00557     } else {
00558         batteryLabelText.append(i18nc("Battery is not plugged in", "<b>Battery:</b> not present<br />"));
00559     }
00560     //kDebug() << batteryLabelText;
00561     if (m_batteryLabel) {
00562         m_batteryLabel->setText(batteryLabelText);
00563     }
00564     if (!m_availableProfiles.empty() && m_profileCombo) {
00565         m_profileCombo->clear();
00566         m_profileCombo->addItem(m_currentProfile);
00567         foreach (const QString &p, m_availableProfiles) {
00568             if (m_currentProfile != p) {
00569                 m_profileCombo->addItem(p);
00570             }
00571         }
00572     }
00573 
00574     if (m_profileLabel && m_profileCombo) {
00575         if (m_availableProfiles.empty()) {
00576             m_profileCombo->hide();
00577             m_profileLabel->hide();
00578         } else {
00579             m_profileCombo->show();
00580             m_profileLabel->show();
00581         }
00582     }
00583 
00584     if (m_brightnessSlider) {
00585         m_brightnessSlider->setValue(Solid::Control::PowerManager::brightness());
00586         kDebug() << "Updating brightness:" << Solid::Control::PowerManager::brightness();
00587     }
00588     //kDebug() << "SIZE LABEL" << m_batteryLabel->size() << m_batteryLabel->preferredSize() << m_batteryLabel->preferredSize();
00589     m_controlsLayout->setColumnMinimumWidth(1,280);
00590     m_batteryLayout->setColumnMinimumWidth(0,200);
00591     m_batteryLayout->invalidate();
00592     m_controlsLayout->invalidate();
00593 }
00594 
00595 void Battery::openConfig()
00596 {
00597     kDebug() << "opening powermanagement configuration dialog";
00598     QStringList args;
00599     args << "powerdevilconfig";
00600     KToolInvocation::kdeinitExec("kcmshell4", args);
00601 }
00602 
00603 void Battery::setProfile(const QString &profile)
00604 {
00605     if (m_currentProfile != profile) {
00606         kDebug() << "Changing power profile to " << profile;
00607         QDBusConnection dbus( QDBusConnection::sessionBus() );
00608         QDBusInterface iface( "org.kde.kded", "/modules/powerdevil", "org.kde.PowerDevil", dbus );
00609         iface.call( "refreshStatus" );
00610         iface.call( "setProfile", profile );
00611     }
00612 }
00613 
00614 void Battery::showLabel(bool show)
00615 {
00616     if (m_fadeIn == show) {
00617         return;
00618     }
00619     m_fadeIn = show;
00620     const int FadeInDuration = 150;
00621 
00622     if (m_animId != -1) {
00623         Plasma::Animator::self()->stopCustomAnimation(m_animId);
00624     }
00625     m_animId = Plasma::Animator::self()->customAnimation(40 / (1000 / FadeInDuration), FadeInDuration,
00626                                                       Plasma::Animator::EaseOutCurve, this,
00627                                                       "animationUpdate");
00628 }
00629 
00630 QRectF Battery::scaleRectF(const qreal progress, QRectF rect)
00631 {
00632     if (progress == 1) {
00633         return rect;
00634     }
00635     // Scale
00636     qreal w = rect.width()*progress;
00637     qreal h = rect.width()*progress;
00638 
00639     // Position centered
00640     rect.setX((rect.width() - w)/2);
00641     rect.setY((rect.height() - h)/2);
00642 
00643     rect.setWidth(w);
00644     rect.setHeight(h);
00645 
00646     return rect;
00647 }
00648 
00649 void Battery::showAcAdapter(bool show)
00650 {
00651     if (m_acFadeIn == show) {
00652         return;
00653     }
00654     m_acFadeIn = show;
00655     const int FadeInDuration = 600;
00656     // As long as the animation is running, we fake it's still plugged in so it gets
00657     // painted in paintInterface()
00658     m_acadapter_plugged = true;
00659 
00660     if (m_acAnimId != -1) {
00661         Plasma::Animator::self()->stopCustomAnimation(m_acAnimId);
00662     }
00663     m_acAnimId = Plasma::Animator::self()->customAnimation(40 / (1000 / FadeInDuration), FadeInDuration,
00664                                                       Plasma::Animator::EaseOutCurve, this,
00665                                                       "acAnimationUpdate");
00666 }
00667 
00668 void Battery::showBattery(bool show)
00669 {
00670     if (m_batteryFadeIn == show) {
00671         return;
00672     }
00673     m_batteryFadeIn = show;
00674     const int FadeInDuration = 300;
00675 
00676     if (m_batteryAnimId != -1) {
00677         Plasma::Animator::self()->stopCustomAnimation(m_batteryAnimId);
00678     }
00679     m_batteryAnimId = Plasma::Animator::self()->customAnimation(40 / (1000 / FadeInDuration), FadeInDuration,
00680                                                       Plasma::Animator::EaseOutCurve, this,
00681                                                       "batteryAnimationUpdate");
00682 }
00683 
00684 void Battery::animationUpdate(qreal progress)
00685 {
00686     if (progress == 1) {
00687         m_animId = -1;
00688     }
00689     if (!m_fadeIn) {
00690         qreal new_alpha = m_fadeIn ? progress : 1 - progress;
00691         m_alpha = qMin(new_alpha, m_alpha);
00692     } else {
00693         m_alpha = m_fadeIn ? progress : 1 - progress;
00694     }
00695     m_alpha = qMax(qreal(0.0), m_alpha);
00696     update();
00697 }
00698 
00699 void Battery::acAnimationUpdate(qreal progress)
00700 {
00701     if (progress == 1) {
00702         m_acAnimId = -1;
00703     }
00704     m_acAlpha = m_acFadeIn ? progress : 1 - progress;
00705     // During the fadeout animation, we had set it to true (and lie)
00706     // now the animation has ended, we _really_ set it to not show the adapter
00707     if (!m_acFadeIn && (progress == 1)) {
00708         m_acadapter_plugged = false;
00709         updateStatus();
00710     }
00711     update();
00712 }
00713 
00714 void Battery::batteryAnimationUpdate(qreal progress)
00715 {
00716     if (progress == 1) {
00717         m_batteryAnimId = -1;
00718     }
00719     m_batteryAlpha = m_batteryFadeIn ? progress : 1 - progress;
00720     update();
00721 }
00722 
00723 void Battery::paintLabel(QPainter *p, const QRect &contentsRect, const QString& labelText)
00724 {
00725     // Store font size, we want to restore it shortly
00726     int original_font_size = m_font.pointSize();
00727 
00728     // Fonts smaller than smallestReadableFont don't make sense.
00729     m_font.setPointSize(qMax(KGlobalSettings::smallestReadableFont().pointSize(), m_font.pointSize()));
00730     QFontMetrics fm(m_font);
00731     qreal text_width = fm.width(labelText);
00732 
00733     // Longer texts get smaller fonts
00734     if (labelText.length() > 4) {
00735         if (original_font_size/1.5 < KGlobalSettings::smallestReadableFont().pointSize()) {
00736             m_font.setPointSize((KGlobalSettings::smallestReadableFont().pointSize()));
00737         } else {
00738             m_font.setPointSizeF(original_font_size/1.5);
00739         }
00740         fm = QFontMetrics(m_font);
00741         text_width = (fm.width(labelText) * 1.2);
00742     } else {
00743         // Smaller texts get a wider box
00744         text_width = (text_width * 1.4);
00745     }
00746     if (formFactor() == Plasma::Horizontal ||
00747         formFactor() == Plasma::Vertical) {
00748         m_font = KGlobalSettings::smallestReadableFont();
00749         m_font.setWeight(QFont::Bold);
00750         fm = QFontMetrics(m_font);
00751         text_width = (fm.width(labelText)+8);
00752     }
00753     p->setFont(m_font);
00754 
00755     // Let's find a good position for painting the percentage on top of the battery
00756     m_textRect = QRectF(qMax(qreal(0.0), contentsRect.left() + (contentsRect.width() - text_width) / 2),
00757                             contentsRect.top() + ((contentsRect.height() - (int)fm.height()) / 2 * 0.9),
00758                             qMin(contentsRect.width(), (int)text_width),
00759                             fm.height() * 1.2 );
00760     //kDebug() << contentsRect << m_textRect;
00761     //p->setBrush(QColor("green"));
00762     //p->drawRect(m_textRect);
00763 
00764     if (m_firstRun) {
00765         m_firstRun = false;
00766         return;
00767     }
00768     // Poor man's highlighting
00769     m_boxColor.setAlphaF(m_alpha);
00770     p->setPen(m_boxColor);
00771     m_boxColor.setAlphaF(m_alpha*0.5);
00772     p->setBrush(m_boxColor);
00773 
00774     // Find sensible proportions for the rounded corners
00775     float round_prop = m_textRect.width() / m_textRect.height();
00776 
00777     // Tweak the rounding edge a bit with the proportions of the textbox
00778     qreal round_radius = 35.0;
00779     p->drawRoundedRect(m_textRect, round_radius / round_prop, round_radius, Qt::RelativeSize);
00780 
00781     m_textColor.setAlphaF(m_alpha);
00782     p->setPen(m_textColor);
00783     p->drawText(m_textRect, Qt::AlignCenter, labelText);
00784 
00785     // Reset font and box
00786     m_font.setPointSize(original_font_size);
00787     m_boxColor.setAlpha(m_boxAlpha);
00788 }
00789 
00790 void Battery::paintBattery(QPainter *p, const QRect &contentsRect, const int batteryPercent, const bool plugState)
00791 {
00792     if (m_theme->hasElement("Battery")) {
00793         m_theme->paint(p, scaleRectF(m_batteryAlpha, contentsRect), "Battery");
00794     }
00795 
00796     QString fill_element = QString();
00797     if (plugState) {
00798         if (batteryPercent > 95) {
00799             fill_element = "Fill100";
00800         } else if (batteryPercent > 80) {
00801             fill_element = "Fill80";
00802         } else if (batteryPercent > 50) {
00803             fill_element = "Fill60";
00804         } else if (batteryPercent > 20) {
00805             fill_element = "Fill40";
00806         } else if (batteryPercent > 10) {
00807             fill_element = "Fill20";
00808         } // Don't show a fillbar below 11% charged
00809     } else {
00810         fill_element = "Unavailable";
00811     }
00812     //kDebug() << "plugState:" << plugState;
00813 
00814     // Now let's find out which fillstate to show
00815     if (!fill_element.isEmpty()) {
00816         if (m_theme->hasElement(fill_element)) {
00817             m_theme->paint(p, scaleRectF(m_batteryAlpha, contentsRect), fill_element);
00818         } else {
00819             kDebug() << fill_element << " does not exist in svg";
00820         }
00821     }
00822 
00823     if (m_acadapter_plugged) {
00824         //QRectF ac_rect = QRectF(contentsRect.topLeft(), QSizeF(contentsRect.width()*m_acAlpha, contentsRect.height()*m_acAlpha));
00825         m_theme->paint(p, scaleRectF(m_acAlpha, contentsRect), "AcAdapter");
00826     }
00827 
00828     // For small FormFactors, we're drawing a shadow
00829     if (formFactor() == Plasma::Vertical ||
00830         formFactor() == Plasma::Horizontal) {
00831         if (plugState) {
00832             m_theme->paint(p, contentsRect, "Shadow");
00833         }
00834     }
00835     if (plugState && m_theme->hasElement("Overlay")) {
00836         m_theme->paint(p, scaleRectF(m_batteryAlpha, contentsRect), "Overlay");
00837     }
00838 }
00839 
00840 void Battery::paintInterface(QPainter *p, const QStyleOptionGraphicsItem *option, const QRect &contentsRect)
00841 {
00842     Q_UNUSED( option );
00843 
00844     p->setRenderHint(QPainter::SmoothPixmapTransform);
00845     p->setRenderHint(QPainter::Antialiasing);
00846 
00847     if (m_numOfBattery == 0) {
00848         QRectF ac_contentsRect(contentsRect.topLeft(), QSizeF(qMax(qreal(0.0), contentsRect.width() * m_acAlpha), qMax(qreal(0.0), contentsRect.height() * m_acAlpha)));
00849         if (m_acadapter_plugged) {
00850             m_theme->paint(p, ac_contentsRect, "AcAdapter");
00851         }
00852         paintBattery(p, contentsRect, 0, false);
00853         return;
00854     }
00855 
00856     if (m_isEmbedded || m_showMultipleBatteries || m_firstRun) {
00857         // paint each battery with own charge level
00858         int battery_num = 0;
00859         int width = contentsRect.width()/m_numOfBattery;
00860         QHashIterator<QString, QHash<QString, QVariant > > battery_data(m_batteries_data);
00861         while (battery_data.hasNext()) {
00862             battery_data.next();
00863             QRect corect = QRect(contentsRect.left()+battery_num*width,
00864                                  contentsRect.top(),
00865                                  width, contentsRect.height());
00866 
00867             // paint battery with appropriate charge level
00868             paintBattery(p, corect, battery_data.value()["Percent"].toInt(), battery_data.value()["Plugged in"].toBool());
00869 
00870             if (m_showBatteryString || m_isHovered || m_firstRun) {
00871                 // Show the charge percentage with a box on top of the battery
00872                 QString batteryLabel;
00873                 if (battery_data.value()["Plugged in"].toBool()) {
00874                     batteryLabel = battery_data.value()["Percent"].toString();
00875                     batteryLabel.append("%");
00876                     paintLabel(p, corect, batteryLabel);
00877                 }
00878             }
00879             ++battery_num;
00880         }
00881     } else {
00882         // paint only one battery and show cumulative charge level
00883         int battery_num = 0;
00884         int battery_charge = 0;
00885         bool has_battery = false;
00886         QHashIterator<QString, QHash<QString, QVariant > > battery_data(m_batteries_data);
00887         while (battery_data.hasNext()) {
00888             battery_data.next();
00889             if (battery_data.value()["Plugged in"].toBool()) {
00890                 battery_charge += battery_data.value()["Percent"].toInt();
00891                 has_battery = true;
00892                 ++battery_num;
00893             }
00894         }
00895         if (battery_num > 0) {
00896             battery_charge = battery_charge / battery_num;
00897         }
00898         // paint battery with appropriate charge level
00899         paintBattery(p, contentsRect,  battery_charge, has_battery);
00900         if (m_showBatteryString || m_isHovered) {
00901             // Show the charge percentage with a box on top of the battery
00902             QString batteryLabel;
00903             if (has_battery) {
00904                 batteryLabel = QString::number(battery_charge);
00905                 batteryLabel.append("%");
00906                 paintLabel(p, contentsRect, batteryLabel);
00907             }
00908         }
00909     }
00910 }
00911 
00912 void Battery::showBatteryLabel(bool show)
00913 {
00914     kDebug() << show;
00915     if (show != m_showBatteryString) {
00916         showLabel(show);
00917         m_showBatteryString = show;
00918     }
00919 }
00920 
00921 void Battery::connectSources()
00922 {
00923     const QStringList& battery_sources = dataEngine("powermanagement")->query("Battery")["sources"].toStringList();
00924 
00925     foreach (const QString &battery_source, battery_sources) {
00926         dataEngine("powermanagement")->connectSource(battery_source, this);
00927     }
00928 
00929     dataEngine("powermanagement")->connectSource("AC Adapter", this);
00930     dataEngine("powermanagement")->connectSource("PowerDevil", this);
00931 
00932     connect(dataEngine("powermanagement"), SIGNAL(sourceAdded(QString)),
00933             this,                          SLOT(sourceAdded(QString)));
00934     connect(dataEngine("powermanagement"), SIGNAL(sourceRemoved(QString)),
00935             this,                          SLOT(sourceRemoved(QString)));
00936 }
00937 
00938 void Battery::disconnectSources()
00939 {
00940     const QStringList& battery_sources = dataEngine("powermanagement")->query("Battery")["sources"].toStringList();
00941 
00942     foreach (const QString &battery_source ,battery_sources) {
00943         dataEngine("powermanagement")->disconnectSource(battery_source, this);
00944     }
00945 
00946     dataEngine("powermanagement")->disconnectSource("AC Adapter", this);
00947     dataEngine("powermanagement")->disconnectSource("PowerDevil", this);
00948 
00949     disconnect(SLOT(sourceAdded(QString)));
00950     disconnect(SLOT(sourceRemoved(QString)));
00951 }
00952 
00953 void Battery::sourceAdded(const QString& source)
00954 {
00955     if (source.startsWith("Battery") && source != "Battery") {
00956         dataEngine("powermanagement")->connectSource(source, this);
00957         m_numOfBattery++;
00958         constraintsEvent(Plasma::SizeConstraint);
00959         update();
00960     }
00961     if (source == "PowerDevil") {
00962         dataEngine("powermanagement")->connectSource(source, this);
00963     }
00964 }
00965 
00966 void Battery::sourceRemoved(const QString& source)
00967 {
00968     if (m_batteries_data.remove(source)) {
00969         m_numOfBattery--;
00970         constraintsEvent(Plasma::SizeConstraint);
00971         update();
00972     }
00973     if (source == "PowerDevil") {
00974         dataEngine("powermanagement")->disconnectSource(source, this);
00975     }
00976 }
00977 
00978 #include "battery.moc"

Applets

Skip menu "Applets"
  • 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