taffybar-0.3.0: src/System/Taffybar/Battery.hs
{-# LANGUAGE OverloadedStrings #-}
-- | This module provides battery widgets using the UPower system
-- service.
--
-- Currently it reports only the first battery it finds. If it does
-- not find a batterym it just returns an obnoxious widget with
-- warning text in it. Battery hotplugging is not supported. These
-- more advanced features could be supported if there is interest.
module System.Taffybar.Battery (
batteryBarNew,
textBatteryNew,
defaultBatteryConfig
) where
import Data.Int
import Graphics.UI.Gtk
import Text.Printf
import Text.StringTemplate
import System.Information.Battery
import System.Taffybar.Widgets.PollingBar
import System.Taffybar.Widgets.PollingLabel
battInfo :: BatteryContext -> String -> IO String
battInfo ctxt fmt = do
info <- getBatteryInfo ctxt
let battPctNum :: Int
battPctNum = floor (batteryPercentage info)
formatTime :: Int64 -> String
formatTime seconds =
let minutes = seconds `div` 60
hours = minutes `div` 60
minutes' = minutes `mod` 60
in printf "%02d:%02d" hours minutes'
battTime :: String
battTime = case (batteryState info) of
BatteryStateCharging -> (formatTime $ batteryTimeToFull info)
BatteryStateDischarging -> (formatTime $ batteryTimeToEmpty info)
_ -> "-"
tpl = newSTMP fmt
tpl' = setManyAttrib [ ("percentage", show battPctNum)
, ("time", battTime)
] tpl
return $ render tpl'
-- | A simple textual battery widget that auto-updates once every
-- polling period (specified in seconds). The displayed format is
-- specified format string where $percentage$ is replaced with the
-- percentage of battery remaining and $time$ is replaced with the
-- time until the battery is fully charged/discharged.
textBatteryNew :: String -- ^ Display format
-> Double -- ^ Poll period in seconds
-> IO Widget
textBatteryNew fmt pollSeconds = do
battCtxt <- batteryContextNew
case battCtxt of
Nothing -> labelNew (Just "No battery") >>= return . toWidget
Just ctxt -> do
l <- pollingLabelNew "" pollSeconds (battInfo ctxt fmt)
widgetShowAll l
return l
-- | Returns the current battery percent as a double in the range [0,
-- 1]
battPct :: BatteryContext -> IO Double
battPct ctxt = do
info <- getBatteryInfo ctxt
return (batteryPercentage info / 100)
-- | A default configuration for the graphical battery display. The
-- bar will be red when power is critical (< 10%), green if it is full
-- (> 90%), and grey otherwise.
--
-- You can customize this with any of the options in 'BarConfig'
defaultBatteryConfig :: BarConfig
defaultBatteryConfig =
defaultBarConfig colorFunc
where
colorFunc pct
| pct < 0.1 = (1, 0, 0)
| pct < 0.9 = (0.5, 0.5, 0.5)
| otherwise = (0, 1, 0)
-- | A fancy graphical battery widget that represents the current
-- charge as a colored vertical bar. There is also a textual
-- percentage readout next to the bar.
batteryBarNew :: BarConfig -- ^ Configuration options for the bar display
-> Double -- ^ Polling period in seconds
-> IO Widget
batteryBarNew battCfg pollSeconds = do
battCtxt <- batteryContextNew
case battCtxt of
Nothing -> labelNew (Just "No battery") >>= return . toWidget
Just ctxt -> do
-- This is currently pretty inefficient - each poll period it
-- queries the battery twice (once for the label and once for
-- the bar).
--
-- Converting it to combine the two shouldn't be hard.
b <- hBoxNew False 1
txt <- textBatteryNew "$percentage$%" pollSeconds
bar <- pollingBarNew battCfg pollSeconds (battPct ctxt)
boxPackStart b bar PackNatural 0
boxPackStart b txt PackNatural 0
widgetShowAll b
return (toWidget b)