]> git.madduck.net Git - etc/awesome.git/blob - widgets/yawn/init.lua

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

20c90b182a51664531551dadeebb019cd48cd271
[etc/awesome.git] / widgets / yawn / init.lua
1
2 --[[
3                                                   
4      Licensed under GNU General Public License v2 
5       * (c) 2013, Luke Bonham                     
6                                                   
7 --]]
8
9 local markup       = require("lain.util.markup")
10
11 local beautiful    = require("beautiful")
12 local naughty      = require("naughty")
13 local wibox        = require("wibox")
14
15 local debug        = { getinfo = debug.getinfo }
16 local io           = io
17 local os           = { date    = os.date,
18                        getenv  = os.getenv }
19 local string       = { find    = string.find,
20                        match   = string.match,
21                        gsub    = string.gsub,
22                        sub     = string.sub }
23 local tonumber     = tonumber
24
25 local setmetatable = setmetatable
26
27 -- YAhoo! Weather Notification
28 -- lain.widgets.yawn
29 local yawn =
30 {
31     units    = "",
32     forecast = "",
33     icon     = wibox.widget.imagebox(),
34     widget   = wibox.widget.textbox()
35 }
36
37 local project_path       = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]]
38 local localizations_path = project_path .. 'localizations/'
39 local icon_path          = project_path .. 'icons/'
40 local api_url            = 'http://weather.yahooapis.com/forecastrss'
41 local units_set          = '?u=c&w=' -- Default is Celsius
42 local language           = string.match(os.getenv("LANG"), "(%S*$*)[.]")
43 local weather_data       = nil
44 local notification       = nil
45 local city_id            = nil
46 local sky                = nil
47 local settings           = {}
48 local update_timer       = nil
49
50 local function fetch_weather(args)
51     local toshow = args.toshow or "forecast"
52
53     local url = api_url .. units_set .. city_id
54     local f = io.popen("curl --connect-timeout 1 -fsm 2 '"
55                        .. url .. "'" )
56     local text = f:read("*all")
57     f:close()
58
59     -- In case of no connection or invalid city ID
60     -- widgets won't display
61     if text == "" or text:match("City not found")
62     then
63         sky = icon_path .. "na.png"
64         yawn.icon:set_image(sky)
65         if text == "" then
66             weather_data = "Service not available at the moment."
67             return "N/A"
68         else
69             weather_data = "City not found!\n" ..
70                            "Are you sure " .. city_id ..
71                            " is your Yahoo city ID?"
72             return "?"
73         end
74     end
75
76     -- Processing raw data
77     weather_data = text:gsub("<.->", "")
78     weather_data = weather_data:match("Current Conditions:.-Full")
79     weather_data = weather_data:gsub("Current Conditions:.-\n", "Now: ")
80     weather_data = weather_data:gsub("Forecast:.-\n", "")
81     weather_data = weather_data:gsub("\nFull", "")
82     weather_data = weather_data:gsub("[\n]$", "")
83     weather_data = weather_data:gsub(" [-] " , ": ")
84     weather_data = weather_data:gsub("[.]", ",")
85     weather_data = weather_data:gsub("High: ", "")
86     weather_data = weather_data:gsub(" Low: ", " - ")
87
88     -- Getting info for text widget
89     local now      = weather_data:sub(weather_data:find("Now:")+5,
90                      weather_data:find("\n")-1)
91     local forecast = now:sub(1, now:find(",")-1)
92     local units    = now:sub(now:find(",")+2, -2)
93
94     -- Day/Night icon change
95     local hour = tonumber(os.date("%H"))
96     sky = icon_path
97
98     if forecast == "Clear"         or
99        forecast == "Fair"          or
100        forecast == "Partly Cloudy" or
101        forecast == "Mostly Cloudy"
102        then
103            if hour >= 6 and hour <= 18
104            then
105                sky = sky .. "Day"
106            else
107                sky = sky .. "Night"
108            end
109     end
110
111     sky = sky  .. forecast:gsub(" ", ""):gsub("/", "") .. ".png"
112
113     -- In case there's no defined icon for current forecast
114     f = io.popen(sky)
115     if f == nil then
116         sky = icon_path .. "na.png"
117     else
118         f:close()
119     end
120
121     -- Localization
122     local f = io.open(localizations_path .. language, "r")
123     if language:find("en_") == nil and f ~= nil
124     then
125         f:close()
126         for line in io.lines(localizations_path .. language)
127         do
128             word = string.sub(line, 1, line:find("|")-1)
129             translation = string.sub(line, line:find("|")+1)
130             weather_data = string.gsub(weather_data, word, translation)
131         end
132     end
133
134     -- Finally setting infos
135     both = weather_data:match(": %S+.-\n"):gsub(": ", "")
136     forecast = weather_data:match(": %S+.-,"):gsub(": ", ""):gsub(",", "\n")
137     units = units:gsub(" ", "")
138
139     yawn.forecast = markup(yawn.color, " " .. markup.font(beautiful.font, forecast) .. " ")
140     yawn.units = markup(yawn.color, " " .. markup.font(beautiful.font, units))
141     yawn.icon:set_image(sky)
142
143     if toshow == "forecast" then
144         return yawn.forecast
145     elseif toshow == "units" then
146         return yawn.units
147     else
148         return both 
149     end
150 end
151
152 function yawn.hide()
153     if notification ~= nil then
154         naughty.destroy(notification)
155         notification = nil
156     end
157 end
158
159 function yawn.show(t_out)
160     if yawn.widget._layout.text == "?"
161     then
162         if update_timer ~= nil
163         then
164             update_timer:emit_signal("timeout")
165         else
166             fetch_weather(settings)
167         end
168     end
169
170     yawn.hide()
171
172     notification = naughty.notify({
173         text = weather_data,
174         icon = sky,
175         timeout = t_out,
176         fg = yawn.color
177     })
178 end
179
180 function yawn.register(id, args)
181     local args = args or {}
182
183     settings = args 
184
185     yawn.color = args.color or beautiful.fg_normal or "#FFFFFF"
186
187     if args.u == "f" then units_set = '?u=f&w=' end
188
189     city_id = id
190
191     update_timer = timer({ timeout = 600 }) -- 10 mins
192     update_timer:connect_signal("timeout", function()
193         yawn.widget:set_markup(fetch_weather(settings))
194     end)
195     update_timer:start()
196     update_timer:emit_signal("timeout")
197
198     yawn.icon:connect_signal("mouse::enter", function()
199         yawn.show(0)
200     end)
201     yawn.icon:connect_signal("mouse::leave", function()
202         yawn.hide()
203     end)
204
205     return yawn
206 end
207
208 function yawn.attach(widget, id, args)
209     yawn.register(id, args)
210
211     widget:connect_signal("mouse::enter", function()
212         yawn.show(0)
213     end)
214
215     widget:connect_signal("mouse::leave", function()
216         yawn.hide()
217     end)
218 end
219
220 -- }}}
221
222 return setmetatable(yawn, { __call = function(_, ...) return yawn.register(...) end })