00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00134 connectSources();
00135
00136 foreach (const QString &battery_source, battery_sources) {
00137
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
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
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
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
00201 } else {
00202 kDebug() << "Applet::Dunno what to do with " << source;
00203 }
00204 if (source == "Battery0") {
00205 m_remainingMSecs = data["Remaining msec"].toInt();
00206
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
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
00259
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
00270
00271
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
00319
00320
00321
00322 if (!m_isEmbedded) {
00323 int row = 0;
00324 int rowHeight = 20;
00325 int columnWidth = 120;
00326
00327 QGraphicsWidget *controls = new QGraphicsWidget(item);
00328
00329
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
00341 m_batteryLayout->setColumnPreferredWidth(1, columnWidth);
00342
00343 m_batteryLabel = new Plasma::Label(controls);
00344 m_batteryLabel->setMinimumSize(200, 80);
00345 m_batteryLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00346
00347
00348 m_batteryLabel->nativeWidget()->setAlignment(Qt::AlignTop);
00349
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);
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
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
00427 QSet<Solid::PowerManagement::SleepState> sleepstates = Solid::PowerManagement::supportedSleepStates();
00428 foreach (const Solid::PowerManagement::SleepState &sleepstate, sleepstates) {
00429 if (sleepstate == Solid::PowerManagement::StandbyState) {
00430
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
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
00465 connect(configButton, SIGNAL(clicked()), this, SLOT(openConfig()));
00466
00467
00468
00469 actionsLayout->addItem(configButton, 1, 1, Qt::AlignLeft);
00470
00471
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
00505 if (m_extenderApplet) {
00506 m_extenderApplet->showBatteryLabel(true);
00507 }
00508
00509
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
00514
00515
00516
00517
00518
00519
00520
00521 } else {
00522 if (m_extenderApplet) {
00523 m_extenderApplet->showBatteryLabel(false);
00524 }
00525 if (m_numOfBattery == 0) {
00526
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
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
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
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
00636 qreal w = rect.width()*progress;
00637 qreal h = rect.width()*progress;
00638
00639
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
00657
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
00706
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
00726 int original_font_size = m_font.pointSize();
00727
00728
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
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
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
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
00761
00762
00763
00764 if (m_firstRun) {
00765 m_firstRun = false;
00766 return;
00767 }
00768
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
00775 float round_prop = m_textRect.width() / m_textRect.height();
00776
00777
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
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 }
00809 } else {
00810 fill_element = "Unavailable";
00811 }
00812
00813
00814
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
00825 m_theme->paint(p, scaleRectF(m_acAlpha, contentsRect), "AcAdapter");
00826 }
00827
00828
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
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
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
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
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
00899 paintBattery(p, contentsRect, battery_charge, has_battery);
00900 if (m_showBatteryString || m_isHovered) {
00901
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"