Merging upstream version 0.8.0 (Closes: #639729, #761971).
[debian/lxpanel.git] / plugins / weather / weather.c
1 /**
2 * Copyright (c) 2012-2014 Piotr Sipika; see the AUTHORS file for more.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * See the COPYRIGHT file for more information.
19 */
20
21 #ifndef USE_STANDALONE
22
23 #include "location.h"
24 #include "weatherwidget.h"
25 #include "yahooutil.h"
26 #include "logutil.h"
27
28 #include "plugin.h"
29
30 #include <glib.h>
31 #include <glib/gi18n.h>
32 #include <gtk/gtk.h>
33 #include <stdlib.h>
34
35 /* Need to maintain count for bookkeeping */
36 static gint g_iCount = 0;
37
38 typedef struct
39 {
40 gint iMyId_;
41 GtkWidget *pWeather_;
42 config_setting_t *pConfig_;
43 LXPanel *pPanel_;
44 } WeatherPluginPrivate;
45
46
47 /**
48 * Weather Plugin destructor.
49 *
50 * @param pData Pointer to the plugin data (private).
51 */
52 static void
53 weather_destructor(gpointer pData)
54 {
55 WeatherPluginPrivate * pPriv = (WeatherPluginPrivate *) pData;
56
57 LXW_LOG(LXW_DEBUG, "weather_destructor(%d): %d", pPriv->iMyId_, g_iCount);
58
59 g_free(pPriv);
60
61 --g_iCount;
62
63 if (g_iCount == 0)
64 {
65 cleanupYahooUtil();
66
67 cleanupLogUtil();
68 }
69 }
70
71 /**
72 * Weather Plugin constructor
73 *
74 * @param pPlugin Pointer to the PluginClass wrapper instance.
75 * @param setting Pointer to the configuration settings for this plugin.
76 *
77 * @return Pointer to a new weather widget.
78 */
79 static GtkWidget *
80 weather_constructor(LXPanel *pPanel, config_setting_t *pConfig)
81 {
82 WeatherPluginPrivate * pPriv = g_new0(WeatherPluginPrivate, 1);
83
84 pPriv->pConfig_ = pConfig;
85 pPriv->pPanel_ = pPanel;
86
87 /* There is one more now... */
88 ++g_iCount;
89
90 pPriv->iMyId_ = g_iCount;
91
92 if (g_iCount == 1)
93 {
94 initializeLogUtil("syslog");
95
96 setMaxLogLevel(LXW_ERROR);
97
98 initializeYahooUtil();
99 }
100
101 LXW_LOG(LXW_DEBUG, "weather_constructor()");
102
103 GtkWidget * pWidg = gtk_weather_new();
104
105 pPriv->pWeather_ = pWidg;
106
107 GtkWidget * pEventBox = gtk_event_box_new();
108
109 lxpanel_plugin_set_data(pEventBox, pPriv, weather_destructor);
110 gtk_container_add(GTK_CONTAINER(pEventBox), pWidg);
111
112 gtk_widget_set_has_window(pEventBox, FALSE);
113
114 gtk_widget_show_all(pEventBox);
115
116 /* use config settings */
117 LocationInfo * pLocation = g_new0(LocationInfo, 1);
118 const char *pczDummy = NULL;
119 int iDummyVal = 0;
120
121 if (config_setting_lookup_string(pConfig, "alias", &pczDummy))
122 {
123 pLocation->pcAlias_ = g_strndup(pczDummy, (pczDummy) ? strlen(pczDummy) : 0);
124 }
125 else if (config_setting_lookup_int(pConfig, "alias", &iDummyVal))
126 {
127 pLocation->pcAlias_ = g_strdup_printf("%d", iDummyVal);
128 }
129 else
130 {
131 LXW_LOG(LXW_ERROR, "Weather: could not lookup alias in config.");
132 }
133
134 if (config_setting_lookup_string(pConfig, "city", &pczDummy))
135 {
136 pLocation->pcCity_ = g_strndup(pczDummy, (pczDummy) ? strlen(pczDummy) : 0);
137 }
138 else
139 {
140 LXW_LOG(LXW_ERROR, "Weather: could not lookup city in config.");
141 }
142
143 if (config_setting_lookup_string(pConfig, "state", &pczDummy))
144 {
145 pLocation->pcState_ = g_strndup(pczDummy, (pczDummy) ? strlen(pczDummy) : 0);
146 }
147 else
148 {
149 LXW_LOG(LXW_ERROR, "Weather: could not lookup state in config.");
150 }
151
152 if (config_setting_lookup_string(pConfig, "country", &pczDummy))
153 {
154 pLocation->pcCountry_ = g_strndup(pczDummy, (pczDummy) ? strlen(pczDummy) : 0);
155 }
156 else
157 {
158 LXW_LOG(LXW_ERROR, "Weather: could not lookup country in config.");
159 }
160
161 if (config_setting_lookup_string(pConfig, "woeid", &pczDummy))
162 {
163 pLocation->pcWOEID_ = g_strndup(pczDummy, (pczDummy) ? strlen(pczDummy) : 0);
164 }
165 else if (config_setting_lookup_int(pConfig, "woeid", &iDummyVal))
166 {
167 pLocation->pcWOEID_ = g_strdup_printf("%d", iDummyVal);
168 }
169 else
170 {
171 LXW_LOG(LXW_ERROR, "Weather: could not lookup woeid in config.");
172 }
173
174 if (config_setting_lookup_string(pConfig, "units", &pczDummy))
175 {
176 pLocation->cUnits_ = pczDummy[0];
177 }
178 else
179 {
180 LXW_LOG(LXW_ERROR, "Weather: could not lookup units in config.");
181 }
182
183 if (config_setting_lookup_int(pConfig, "interval", &iDummyVal))
184 {
185 pLocation->uiInterval_ = (guint)iDummyVal;
186 }
187 else
188 {
189 LXW_LOG(LXW_ERROR, "Weather: could not lookup interval in config.");
190 }
191
192 iDummyVal = 0;
193 if (config_setting_lookup_int(pConfig, "enabled", &iDummyVal))
194 {
195 pLocation->bEnabled_ = (gint)iDummyVal;
196 }
197 else
198 {
199 LXW_LOG(LXW_ERROR, "Weather: could not lookup enabled flag in config.");
200 }
201
202 if (pLocation->pcAlias_ && pLocation->pcWOEID_)
203 {
204 GValue locationValue = G_VALUE_INIT;
205
206 g_value_init(&locationValue, G_TYPE_POINTER);
207
208 /* location is copied by the widget */
209 g_value_set_pointer(&locationValue, pLocation);
210
211 g_object_set_property(G_OBJECT(pWidg),
212 "location",
213 &locationValue);
214 }
215
216 freeLocation(pLocation);
217
218 return pEventBox;
219 }
220
221 /**
222 * Weather Plugin callback to save configuration
223 *
224 * @param pWidget Pointer to this widget.
225 */
226 void weather_save_configuration(GtkWidget * pWeather, LocationInfo * pLocation)
227 {
228 GtkWidget * pWidget = gtk_widget_get_parent(pWeather);
229 WeatherPluginPrivate * pPriv = NULL;
230
231 if (pWidget)
232 {
233 pPriv = (WeatherPluginPrivate *) lxpanel_plugin_get_data(pWidget);
234 }
235 if (pPriv == NULL)
236 {
237 LXW_LOG(LXW_ERROR, "Weather: weather_save_configuration() for invalid widget");
238 return;
239 }
240
241 LXW_LOG(LXW_DEBUG, "weather_save_configuration(%d)", pPriv->iMyId_);
242
243 if (pLocation)
244 {
245 /* save configuration */
246 config_group_set_string(pPriv->pConfig_, "alias", pLocation->pcAlias_);
247 config_group_set_string(pPriv->pConfig_, "city", pLocation->pcCity_);
248 config_group_set_string(pPriv->pConfig_, "state", pLocation->pcState_);
249 config_group_set_string(pPriv->pConfig_, "country", pLocation->pcCountry_);
250 config_group_set_string(pPriv->pConfig_, "woeid", pLocation->pcWOEID_);
251
252 char units[2] = {0};
253 if (snprintf(units, 2, "%c", pLocation->cUnits_) > 0)
254 {
255 config_group_set_string(pPriv->pConfig_, "units", units);
256 }
257
258 config_group_set_int(pPriv->pConfig_, "interval", (int) pLocation->uiInterval_);
259 config_group_set_int(pPriv->pConfig_, "enabled", (int) pLocation->bEnabled_);
260 }
261
262 }
263
264 void weather_set_label_text(GtkWidget * pWeather, GtkWidget * label, const gchar * text)
265 {
266 GtkWidget * pWidget = gtk_widget_get_parent(pWeather);
267 WeatherPluginPrivate * pPriv = NULL;
268
269 if (pWidget)
270 {
271 pPriv = (WeatherPluginPrivate *) lxpanel_plugin_get_data(pWidget);
272 }
273 if (pPriv == NULL)
274 {
275 LXW_LOG(LXW_ERROR, "Weather: weather_set_label_text() for invalid widget");
276 return;
277 }
278
279 lxpanel_draw_label_text(pPriv->pPanel_, label, text, TRUE, 1, TRUE);
280 }
281
282 /**
283 * Weather Plugin configuration change callback.
284 *
285 * @param pPanel Pointer to the panel instance.
286 * @param pPlugin Pointer to the PluginClass wrapper instance.
287 */
288 static void
289 weather_configuration_changed(LXPanel *pPanel, GtkWidget *pWidget)
290 {
291 LXW_LOG(LXW_DEBUG, "weather_configuration_changed()");
292
293 if (pPanel && pWidget)
294 {
295 LXW_LOG(LXW_DEBUG,
296 " orientation: %s, width: %d, height: %d, icon size: %d\n",
297 (panel_get_orientation(pPanel) == GTK_ORIENTATION_HORIZONTAL)?"HORIZONTAL":
298 (panel_get_orientation(pPanel) == GTK_ORIENTATION_VERTICAL)?"VERTICAL":"NONE",
299 pPanel->width, panel_get_height(pPanel),
300 panel_get_icon_size(pPanel));
301 }
302 }
303
304 /**
305 * Weather Plugin configuration dialog callback.
306 *
307 * @param pPanel Pointer to the panel instance.
308 * @param pWidget Pointer to the Plugin widget instance.
309 * @param pParent Pointer to the GtkWindow parent.
310 *
311 * @return Instance of the widget.
312 */
313 static GtkWidget *
314 weather_configure(LXPanel *pPanel G_GNUC_UNUSED, GtkWidget *pWidget)
315 {
316 LXW_LOG(LXW_DEBUG, "weather_configure()");
317
318 WeatherPluginPrivate * pPriv = (WeatherPluginPrivate *) lxpanel_plugin_get_data(pWidget);
319
320 GtkWidget * pDialog = gtk_weather_create_preferences_dialog(GTK_WIDGET(pPriv->pWeather_));
321
322 return pDialog;
323 }
324
325 FM_DEFINE_MODULE(lxpanel_gtk, weather)
326
327 /**
328 * Definition of the weather plugin module
329 */
330 LXPanelPluginInit fm_module_init_lxpanel_gtk =
331 {
332 .name = N_("Weather Plugin"),
333 .description = N_("Show weather conditions for a location."),
334
335 // API functions
336 .new_instance = weather_constructor,
337 .config = weather_configure,
338 .reconfigure = weather_configuration_changed
339 };
340 #endif /* USE_STANDALONE */