Merging upstream version 0.7.0 (Closes: #493243, #510888, #567617, #699414, #709777...
[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 #include "location.h"
22 #include "weatherwidget.h"
23 #include "yahooutil.h"
24 #include "logutil.h"
25
26 #include "plugin.h"
27
28 #include <glib.h>
29 #include <glib/gi18n.h>
30 #include <gtk/gtk.h>
31 #include <stdlib.h>
32
33 /* Need to maintain count for bookkeeping */
34 static gint g_iCount = 0;
35
36 typedef struct
37 {
38 gint iMyId_;
39 GtkWidget *pWeather_;
40 config_setting_t *pConfig_;
41 } WeatherPluginPrivate;
42
43
44 /**
45 * Weather Plugin destructor.
46 *
47 * @param pData Pointer to the plugin data (private).
48 */
49 static void
50 weather_destructor(gpointer pData)
51 {
52 WeatherPluginPrivate * pPriv = (WeatherPluginPrivate *) pData;
53
54 LXW_LOG(LXW_DEBUG, "weather_destructor(%d): %d", pPriv->iMyId_, g_iCount);
55
56 g_free(pPriv);
57
58 --g_iCount;
59
60 if (g_iCount == 0)
61 {
62 cleanupYahooUtil();
63
64 cleanupLogUtil();
65 }
66 }
67
68 /**
69 * Weather Plugin constructor
70 *
71 * @param pPlugin Pointer to the PluginClass wrapper instance.
72 * @param setting Pointer to the configuration settings for this plugin.
73 *
74 * @return Pointer to a new weather widget.
75 */
76 static GtkWidget *
77 weather_constructor(LXPanel *pPanel, config_setting_t *pConfig)
78 {
79 WeatherPluginPrivate * pPriv = g_new0(WeatherPluginPrivate, 1);
80
81 pPriv->pConfig_ = pConfig;
82
83 /* There is one more now... */
84 ++g_iCount;
85
86 pPriv->iMyId_ = g_iCount;
87
88 if (g_iCount == 1)
89 {
90 initializeLogUtil("syslog");
91
92 setMaxLogLevel(LXW_ERROR);
93
94 initializeYahooUtil();
95 }
96
97 LXW_LOG(LXW_DEBUG, "weather_constructor()");
98
99 GtkWidget * pWidg = gtk_weather_new(FALSE);
100
101 pPriv->pWeather_ = pWidg;
102
103 GtkWidget * pEventBox = gtk_event_box_new();
104
105 lxpanel_plugin_set_data(pEventBox, pPriv, weather_destructor);
106 gtk_container_add(GTK_CONTAINER(pEventBox), pWidg);
107
108 gtk_widget_set_has_window(pEventBox, FALSE);
109
110 gtk_widget_show_all(pEventBox);
111
112 /* use config settings */
113 LocationInfo * pLocation = g_new0(LocationInfo, 1);
114 const char *pczDummy = NULL;
115 int iDummyVal = 0;
116
117 if (config_setting_lookup_string(pConfig, "alias", &pczDummy))
118 {
119 pLocation->pcAlias_ = g_strndup(pczDummy, (pczDummy) ? strlen(pczDummy) : 0);
120 }
121 else
122 {
123 LXW_LOG(LXW_ERROR, "Weather: could not lookup alias in config.");
124 }
125
126 if (config_setting_lookup_string(pConfig, "city", &pczDummy))
127 {
128 pLocation->pcCity_ = g_strndup(pczDummy, (pczDummy) ? strlen(pczDummy) : 0);
129 }
130 else
131 {
132 LXW_LOG(LXW_ERROR, "Weather: could not lookup city in config.");
133 }
134
135 if (config_setting_lookup_string(pConfig, "state", &pczDummy))
136 {
137 pLocation->pcState_ = g_strndup(pczDummy, (pczDummy) ? strlen(pczDummy) : 0);
138 }
139 else
140 {
141 LXW_LOG(LXW_ERROR, "Weather: could not lookup state in config.");
142 }
143
144 if (config_setting_lookup_string(pConfig, "country", &pczDummy))
145 {
146 pLocation->pcCountry_ = g_strndup(pczDummy, (pczDummy) ? strlen(pczDummy) : 0);
147 }
148 else
149 {
150 LXW_LOG(LXW_ERROR, "Weather: could not lookup country in config.");
151 }
152
153 if (config_setting_lookup_string(pConfig, "woeid", &pczDummy))
154 {
155 pLocation->pcWOEID_ = g_strndup(pczDummy, (pczDummy) ? strlen(pczDummy) : 0);
156 }
157 else if (config_setting_lookup_int(pConfig, "woeid", &iDummyVal))
158 {
159 pLocation->pcWOEID_ = g_strdup_printf("%d", iDummyVal);
160 }
161 else
162 {
163 LXW_LOG(LXW_ERROR, "Weather: could not lookup woeid in config.");
164 }
165
166 if (config_setting_lookup_string(pConfig, "units", &pczDummy))
167 {
168 pLocation->cUnits_ = pczDummy[0];
169 }
170 else
171 {
172 LXW_LOG(LXW_ERROR, "Weather: could not lookup units in config.");
173 }
174
175 if (config_setting_lookup_int(pConfig, "interval", &iDummyVal))
176 {
177 pLocation->uiInterval_ = (guint)iDummyVal;
178 }
179 else
180 {
181 LXW_LOG(LXW_ERROR, "Weather: could not lookup interval in config.");
182 }
183
184 iDummyVal = 0;
185 if (config_setting_lookup_int(pConfig, "enabled", &iDummyVal))
186 {
187 pLocation->bEnabled_ = (gint)iDummyVal;
188 }
189 else
190 {
191 LXW_LOG(LXW_ERROR, "Weather: could not lookup enabled flag in config.");
192 }
193
194
195 if (pLocation->pcAlias_ && pLocation->pcWOEID_)
196 {
197 GValue locationValue = G_VALUE_INIT;
198
199 g_value_init(&locationValue, G_TYPE_POINTER);
200
201 /* location is copied by the widget */
202 g_value_set_pointer(&locationValue, pLocation);
203
204 g_object_set_property(G_OBJECT(pWidg),
205 "location",
206 &locationValue);
207 }
208
209 freeLocation(pLocation);
210
211 return pEventBox;
212 }
213
214 /**
215 * Weather Plugin callback to save configuration
216 *
217 * @param pWidget Pointer to this widget.
218 */
219 void weather_save_configuration(GtkWidget * pWeather, LocationInfo * pLocation)
220 {
221 GtkWidget * pWidget = gtk_widget_get_parent(pWeather);
222 WeatherPluginPrivate * pPriv = NULL;
223
224 if (pWidget)
225 {
226 pPriv = (WeatherPluginPrivate *) lxpanel_plugin_get_data(pWidget);
227 }
228 if (pPriv == NULL)
229 {
230 LXW_LOG(LXW_ERROR, "Weather: weather_save_configuration() for invalid widget");
231 return;
232 }
233
234 LXW_LOG(LXW_DEBUG, "weather_save_configuration(%d)", pPriv->iMyId_);
235
236 if (pLocation)
237 {
238 /* save configuration */
239 config_group_set_string(pPriv->pConfig_, "alias", pLocation->pcAlias_);
240 config_group_set_string(pPriv->pConfig_, "city", pLocation->pcCity_);
241 config_group_set_string(pPriv->pConfig_, "state", pLocation->pcState_);
242 config_group_set_string(pPriv->pConfig_, "country", pLocation->pcCountry_);
243 config_group_set_string(pPriv->pConfig_, "woeid", pLocation->pcWOEID_);
244
245 char units[2] = {0};
246 if (snprintf(units, 2, "%c", pLocation->cUnits_) > 0)
247 {
248 config_group_set_string(pPriv->pConfig_, "units", units);
249 }
250
251 config_group_set_int(pPriv->pConfig_, "interval", (int) pLocation->uiInterval_);
252 config_group_set_int(pPriv->pConfig_, "enabled", (int) pLocation->bEnabled_);
253 }
254
255 }
256
257 /**
258 * Weather Plugin configuration change callback.
259 *
260 * @param pPanel Pointer to the panel instance.
261 * @param pPlugin Pointer to the PluginClass wrapper instance.
262 */
263 static void
264 weather_configuration_changed(LXPanel *pPanel, GtkWidget *pWidget)
265 {
266 LXW_LOG(LXW_DEBUG, "weather_configuration_changed()");
267
268 if (pPanel && pWidget)
269 {
270 LXW_LOG(LXW_DEBUG,
271 " orientation: %s, width: %d, height: %d, icon size: %d\n",
272 (panel_get_orientation(pPanel) == GTK_ORIENTATION_HORIZONTAL)?"HORIZONTAL":
273 (panel_get_orientation(pPanel) == GTK_ORIENTATION_VERTICAL)?"VERTICAL":"NONE",
274 pPanel->width, panel_get_height(pPanel),
275 panel_get_icon_size(pPanel));
276 }
277 }
278
279 /**
280 * Weather Plugin configuration dialog callback.
281 *
282 * @param pPanel Pointer to the panel instance.
283 * @param pWidget Pointer to the Plugin widget instance.
284 * @param pParent Pointer to the GtkWindow parent.
285 *
286 * @return Instance of the widget.
287 */
288 static GtkWidget *
289 weather_configure(LXPanel *pPanel G_GNUC_UNUSED, GtkWidget *pWidget)
290 {
291 LXW_LOG(LXW_DEBUG, "weather_configure()");
292
293 WeatherPluginPrivate * pPriv = (WeatherPluginPrivate *) lxpanel_plugin_get_data(pWidget);
294
295 GtkWidget * pDialog = gtk_weather_create_preferences_dialog(GTK_WIDGET(pPriv->pWeather_));
296
297 return pDialog;
298 }
299
300 FM_DEFINE_MODULE(lxpanel_gtk, weather)
301
302 /**
303 * Definition of the weather plugin module
304 */
305 LXPanelPluginInit fm_module_init_lxpanel_gtk =
306 {
307 .name = N_("Weather Plugin"),
308 .description = N_("Show weather conditions for a location."),
309
310 // API functions
311 .new_instance = weather_constructor,
312 .config = weather_configure,
313 .reconfigure = weather_configuration_changed
314 };