weather-summary.c 33.9 KB
Newer Older
1
/*  Copyright (c) 2003-2012 Xfce Development Team
2
 *
3 4 5 6
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
7
 *
8 9 10 11
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
12
 *
13 14 15 16
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
17 18 19
 */

#ifdef HAVE_CONFIG_H
20
#include <config.h>
21 22
#endif

23
#include <libxfce4ui/libxfce4ui.h>
24

Nick Schermer's avatar
Nick Schermer committed
25 26 27 28 29 30
#include "weather-parsers.h"
#include "weather-data.h"
#include "weather.h"
#include "weather-summary.h"
#include "weather-translate.h"
#include "weather-icon.h"
31

32

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
static gboolean
lnk_clicked(GtkTextTag *tag,
            GObject *obj,
            GdkEvent *event,
            GtkTextIter *iter,
            GtkWidget *textview);


#define BORDER 8

#define APPEND_BTEXT(text)                                          \
    gtk_text_buffer_insert_with_tags(GTK_TEXT_BUFFER(buffer),       \
                                     &iter, text, -1, btag, NULL);

#define APPEND_TEXT_ITEM_REAL(text)                 \
    gtk_text_buffer_insert(GTK_TEXT_BUFFER(buffer), \
                           &iter, text, -1);        \
    g_free(value);

#define APPEND_TEXT_ITEM(text, item)                            \
53 54
    rawvalue = get_data(conditions, data->units, item,          \
                        FALSE, data->night_time);               \
55
    unit = get_unit(data->units, item);                         \
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
    value = g_strdup_printf("\t%s%s%s%s%s\n",                   \
                            text, text ? ": " : "",             \
                            rawvalue,                           \
                            strcmp(unit, "°") ? " " : "",       \
                            unit);                              \
    g_free(rawvalue);                                           \
    APPEND_TEXT_ITEM_REAL(value);

#define APPEND_LINK_ITEM(prefix, text, url, lnk_tag)                    \
    gtk_text_buffer_insert(GTK_TEXT_BUFFER(buffer),                     \
                           &iter, prefix, -1);                          \
    gtk_text_buffer_insert_with_tags(GTK_TEXT_BUFFER(buffer),           \
                                     &iter, text, -1, lnk_tag, NULL);   \
    gtk_text_buffer_insert(GTK_TEXT_BUFFER(buffer),                     \
                           &iter, "\n", -1);                            \
    g_object_set_data_full(G_OBJECT(lnk_tag), "url", g_strdup(url), g_free); \
    g_signal_connect(G_OBJECT(lnk_tag), "event",                        \
                     G_CALLBACK(lnk_clicked), NULL);
74

Harald Judt's avatar
Harald Judt committed
75 76 77 78 79 80 81 82 83 84 85 86
#define ATTACH_DAYTIME_HEADER(title, pos)               \
    if (data->forecast_layout == FC_LAYOUT_CALENDAR)    \
        gtk_table_attach_defaults                       \
            (GTK_TABLE(table),                          \
             add_forecast_header(title, 90.0, &darkbg), \
             0, 1, pos, pos+1);                         \
    else                                                \
        gtk_table_attach_defaults                       \
            (GTK_TABLE(table),                          \
             add_forecast_header(title, 0.0, &darkbg),  \
             pos, pos+1, 0, 1);                         \

87
#define APPEND_TOOLTIP_ITEM(description, item)                  \
88 89
    value = get_data(fcdata, data->units, item,                 \
                     data->round, data->night_time);            \
90 91 92 93 94 95
    unit = get_unit(data->units, item);                         \
    g_string_append_printf(text, description, value,            \
                           strcmp(unit, "°") ? " " : "",        \
                           unit);                               \
    g_free(value);

96

97 98 99 100 101 102
static gboolean
lnk_clicked(GtkTextTag *tag,
            GObject *obj,
            GdkEvent *event,
            GtkTextIter *iter,
            GtkWidget *textview)
103
{
104 105
    const gchar *url;
    gchar *str;
106

107 108 109 110 111 112 113 114 115 116
    if (event->type == GDK_BUTTON_RELEASE) {
        url = g_object_get_data(G_OBJECT(tag), "url");
        str = g_strdup_printf("exo-open --launch WebBrowser %s", url);
        g_spawn_command_line_async(str, NULL);
        g_free(str);
    } else if (event->type == GDK_LEAVE_NOTIFY)
        gdk_window_set_cursor(gtk_text_view_get_window(GTK_TEXT_VIEW(obj),
                                                       GTK_TEXT_WINDOW_TEXT),
                              NULL);
    return FALSE;
117 118
}

119

120
static gboolean
121
icon_clicked (GtkWidget *widget,
122
              GdkEventButton *event,
123
              gpointer user_data)
124
{
125
    return lnk_clicked(user_data, NULL, (GdkEvent *) (event), NULL, NULL);
126 127
}

128 129 130 131

static gboolean
view_motion_notify(GtkWidget *widget,
                   GdkEventMotion *event,
Harald Judt's avatar
Harald Judt committed
132
                   summary_details *sum)
133
{
Harald Judt's avatar
Harald Judt committed
134 135 136 137 138
    GtkTextIter iter;
    GtkTextTag *tag;
    GSList *tags;
    GSList *cur;
    gint bx, by;
139

Harald Judt's avatar
Harald Judt committed
140
    if (event->x != -1 && event->y != -1) {
Harald Judt's avatar
Harald Judt committed
141
        gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(sum->text_view),
142 143
                                              GTK_TEXT_WINDOW_WIDGET,
                                              event->x, event->y, &bx, &by);
Harald Judt's avatar
Harald Judt committed
144
        gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(sum->text_view),
145 146 147
                                           &iter, bx, by);
        tags = gtk_text_iter_get_tags(&iter);
        for (cur = tags; cur != NULL; cur = cur->next) {
Harald Judt's avatar
Harald Judt committed
148
            tag = cur->data;
149
            if (g_object_get_data(G_OBJECT(tag), "url")) {
Harald Judt's avatar
Harald Judt committed
150 151 152 153
                gdk_window_set_cursor
                    (gtk_text_view_get_window(GTK_TEXT_VIEW(sum->text_view),
                                              GTK_TEXT_WINDOW_TEXT),
                     sum->hand_cursor);
154 155 156
                return FALSE;
            }
        }
157
    }
Harald Judt's avatar
Harald Judt committed
158 159 160 161 162
    if (!sum->on_icon)
        gdk_window_set_cursor
            (gtk_text_view_get_window(GTK_TEXT_VIEW(sum->text_view),
                                      GTK_TEXT_WINDOW_TEXT),
             sum->text_cursor);
163
    return FALSE;
164 165
}

166 167 168 169

static gboolean
icon_motion_notify(GtkWidget *widget,
                   GdkEventMotion *event,
Harald Judt's avatar
Harald Judt committed
170
                   summary_details *sum)
171
{
Harald Judt's avatar
Harald Judt committed
172 173 174 175 176
    sum->on_icon = TRUE;
    gdk_window_set_cursor
        (gtk_text_view_get_window(GTK_TEXT_VIEW(sum->text_view),
                                  GTK_TEXT_WINDOW_TEXT),
         sum->hand_cursor);
177
    return FALSE;
178 179
}

180 181 182 183

static gboolean
view_leave_notify(GtkWidget *widget,
                  GdkEventMotion *event,
Harald Judt's avatar
Harald Judt committed
184
                  summary_details *sum)
185
{
Harald Judt's avatar
Harald Judt committed
186 187 188 189 190
    sum->on_icon = FALSE;
    gdk_window_set_cursor
        (gtk_text_view_get_window(GTK_TEXT_VIEW(sum->text_view),
                                  GTK_TEXT_WINDOW_TEXT),
         sum->text_cursor);
191
    return FALSE;
192 193
}

194 195 196

static void
view_scrolled_cb(GtkAdjustment *adj,
Harald Judt's avatar
Harald Judt committed
197
                 summary_details *sum)
198
{
Harald Judt's avatar
Harald Judt committed
199 200
    gint x, y, x1, y1;

Harald Judt's avatar
Harald Judt committed
201 202 203 204
    if (sum->icon_ebox) {
        x1 = sum->text_view->allocation.width - 191 - 15;
        y1 = sum->text_view->requisition.height - 60 - 15;
        gtk_text_view_buffer_to_window_coords(GTK_TEXT_VIEW(sum->text_view),
205 206
                                              GTK_TEXT_WINDOW_TEXT,
                                              x1, y1, &x, &y);
Harald Judt's avatar
Harald Judt committed
207 208
        gtk_text_view_move_child(GTK_TEXT_VIEW(sum->text_view),
                                 sum->icon_ebox, x, y);
209
    }
210 211
}

212 213 214 215 216

static void
view_size_allocate_cb(GtkWidget *widget,
                      GtkAllocation *allocation,
                      gpointer data)
217
{
Harald Judt's avatar
Harald Judt committed
218
    view_scrolled_cb(NULL, data);
219
}
220

221 222 223

static gchar *
get_logo_path(void)
224
{
225 226 227 228 229 230 231
    gchar *cache_dir, *logo_path;

    cache_dir = get_cache_directory();
    logo_path = g_strconcat(cache_dir, G_DIR_SEPARATOR_S,
                            "weather_logo.gif", NULL);
    g_free(cache_dir);
    return logo_path;
232 233
}

234

235
static void
236 237 238
logo_fetched(SoupSession *session,
             SoupMessage *msg,
             gpointer user_data)
239
{
240
    if (msg && msg->response_body && msg->response_body->length > 0) {
241 242 243
        gchar *path = get_logo_path();
        GError *error = NULL;
        GdkPixbuf *pixbuf = NULL;
244 245 246 247
        if (!g_file_set_contents(path, msg->response_body->data,
                                 msg->response_body->length, &error)) {
            g_warning("Error downloading met.no logo image to %s, "
                      "err %s\n", path, error ? error->message : "?");
248 249 250 251 252 253 254 255 256 257 258
            g_error_free(error);
            g_free(path);
            return;
        }
        pixbuf = gdk_pixbuf_new_from_file(path, NULL);
        g_free(path);
        if (pixbuf) {
            gtk_image_set_from_pixbuf(GTK_IMAGE(user_data), pixbuf);
            g_object_unref(pixbuf);
        }
    }
259 260
}

261 262

static GtkWidget *
263
weather_summary_get_logo(plugin_data *data)
264
{
265
    GtkWidget *image = gtk_image_new();
Harald Judt's avatar
Harald Judt committed
266
    GdkPixbuf *pixbuf;
267 268 269 270 271
    gchar *path = get_logo_path();

    pixbuf = gdk_pixbuf_new_from_file(path, NULL);
    g_free(path);
    if (pixbuf == NULL)
272 273
        weather_http_queue_request(data->session,
                                   "http://met.no/filestore/met.no-logo.gif",
274
                                   logo_fetched, image);
275 276 277 278 279
    else {
        gtk_image_set_from_pixbuf(GTK_IMAGE(image), pixbuf);
        g_object_unref(pixbuf);
    }
    return image;
280
}
281

282

283
static GtkWidget *
284
create_summary_tab(plugin_data *data)
285
{
286 287 288
    GtkTextBuffer *buffer;
    GtkTextIter iter;
    GtkTextTag *btag, *ltag0, *ltag1;
Harald Judt's avatar
Harald Judt committed
289
    GtkWidget *view, *frame, *scrolled, *icon;
290 291 292 293
    GtkAdjustment *adj;
    GdkColor lnk_color;
    xml_time *conditions;
    const gchar *unit;
Harald Judt's avatar
Harald Judt committed
294
    gchar *value, *rawvalue, *wind;
295 296
    gchar *interval_start, *interval_end, *point, *last_weather_update;
    gchar *sunrise, *sunset, *moonrise, *moonset;
Harald Judt's avatar
Harald Judt committed
297
    summary_details *sum;
298

Harald Judt's avatar
Harald Judt committed
299 300 301 302 303 304 305
    sum = g_slice_new0(summary_details);
    sum->on_icon = FALSE;
    sum->hand_cursor = gdk_cursor_new(GDK_HAND2);
    sum->text_cursor = gdk_cursor_new(GDK_XTERM);
    data->summary_details = sum;

    sum->text_view = view = gtk_text_view_new();
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
    gtk_text_view_set_editable(GTK_TEXT_VIEW(view), FALSE);
    gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(view), FALSE);
    frame = gtk_frame_new(NULL);
    scrolled = gtk_scrolled_window_new(NULL, NULL);

    gtk_container_add(GTK_CONTAINER(scrolled), view);
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);

    gtk_container_set_border_width(GTK_CONTAINER(frame), BORDER);
    gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
    gtk_container_add(GTK_CONTAINER(frame), scrolled);

    buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
    gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(buffer), &iter, 0);
    btag = gtk_text_buffer_create_tag(buffer, NULL, "weight",
                                      PANGO_WEIGHT_BOLD, NULL);

    gdk_color_parse("#0000ff", &lnk_color);
    ltag0 = gtk_text_buffer_create_tag(buffer, "lnk0",
                                       "foreground-gdk", &lnk_color, NULL);
    ltag1 = gtk_text_buffer_create_tag(buffer, "lnk1",
                                       "foreground-gdk", &lnk_color, NULL);

    conditions = get_current_conditions(data->weatherdata);
    APPEND_BTEXT(_("Coordinates\n"));
    APPEND_TEXT_ITEM(_("Altitude"), ALTITUDE);
    APPEND_TEXT_ITEM(_("Latitude"), LATITUDE);
    APPEND_TEXT_ITEM(_("Longitude"), LONGITUDE);

336 337
    /* TRANSLATORS: Please use as many \t as appropriate to align the
       date/time values as in the original. */
338
    APPEND_BTEXT(_("\nTime\n"));
339 340 341 342 343 344 345
    last_weather_update = format_date(data->weather_update->last, NULL, TRUE);
    value = g_strdup_printf(_("\tLast updated:\t%s\n\n"),
                            last_weather_update);
    g_free(last_weather_update);
    APPEND_TEXT_ITEM_REAL(value);

    point = format_date(conditions->point, NULL, TRUE);
346
    value = g_strdup_printf
Harald Judt's avatar
Harald Judt committed
347
        (_("\tTemperatures, wind, atmosphere and cloud data calculated\n"
348
           "\tfor:\t\t\t%s\n"),
349
         point);
350
    g_free(point);
351 352
    APPEND_TEXT_ITEM_REAL(value);

353 354
    interval_start = format_date(conditions->start, NULL, TRUE);
    interval_end = format_date(conditions->end, NULL, TRUE);
355
    value = g_strdup_printf
Harald Judt's avatar
Harald Judt committed
356
        (_("\n\tPrecipitation and the weather symbol have been calculated\n"
357 358 359
           "\tusing the following time interval:\n"
           "\tStart:\t\t%s\n"
           "\tEnd:\t\t%s\n"),
360 361
         interval_start,
         interval_end);
362 363
    g_free(interval_end);
    g_free(interval_start);
364 365
    APPEND_TEXT_ITEM_REAL(value);

366
    /* sun and moon */
367
    APPEND_BTEXT(_("\nAstronomical Data\n"));
368 369 370 371 372 373 374 375
    if (data->astrodata) {
        if (data->astrodata->sun_never_rises) {
            value = g_strdup(_("\tSunrise:\t\tThe sun never rises today.\n"));
            APPEND_TEXT_ITEM_REAL(value);
        } else if (data->astrodata->sun_never_sets) {
            value = g_strdup(_("\tSunset:\t\tThe sun never sets today.\n"));
            APPEND_TEXT_ITEM_REAL(value);
        } else {
376
            sunrise = format_date(data->astrodata->sunrise, NULL, TRUE);
377
            value = g_strdup_printf(_("\tSunrise:\t\t%s\n"), sunrise);
378
            g_free(sunrise);
379 380
            APPEND_TEXT_ITEM_REAL(value);

381
            sunset = format_date(data->astrodata->sunset, NULL, TRUE);
382
            value = g_strdup_printf(_("\tSunset:\t\t%s\n\n"), sunset);
383
            g_free(sunset);
384 385 386 387 388 389 390 391 392 393 394 395
            APPEND_TEXT_ITEM_REAL(value);
        }

        if (data->astrodata->moon_phase)
            value = g_strdup_printf(_("\tMoon phase:\t%s\n"),
                                    translate_moon_phase
                                    (data->astrodata->moon_phase));
        else
            value = g_strdup(_("\tMoon phase:\tUnknown\n"));
        APPEND_TEXT_ITEM_REAL(value);

        if (data->astrodata->moon_never_rises) {
396 397
            value =
                g_strdup(_("\tMoonrise:\tThe moon never rises today.\n"));
398 399
            APPEND_TEXT_ITEM_REAL(value);
        } else if (data->astrodata->moon_never_sets) {
400 401
            value =
                g_strdup(_("\tMoonset:\tThe moon never sets today.\n"));
402 403
            APPEND_TEXT_ITEM_REAL(value);
        } else {
404
            moonrise = format_date(data->astrodata->moonrise, NULL, TRUE);
405
            value = g_strdup_printf(_("\tMoonrise:\t%s\n"), moonrise);
406
            g_free(moonrise);
407 408
            APPEND_TEXT_ITEM_REAL(value);

409
            moonset = format_date(data->astrodata->moonset, NULL, TRUE);
410
            value = g_strdup_printf(_("\tMoonset:\t%s\n"), moonset);
411
            g_free(moonset);
412 413 414 415 416 417 418 419
            APPEND_TEXT_ITEM_REAL(value);
        }
    } else {
        value = g_strdup(_("\tData not available, will use sane "
                           "default values for night and day.\n"));
        APPEND_TEXT_ITEM_REAL(value);
    }

Harald Judt's avatar
Harald Judt committed
420 421
    /* temperatures */
    APPEND_BTEXT(_("\nTemperatures\n"));
422
    APPEND_TEXT_ITEM(_("Temperature"), TEMPERATURE);
Harald Judt's avatar
Harald Judt committed
423
    APPEND_TEXT_ITEM(_("Dew point"), DEWPOINT);
424 425 426

    /* wind */
    APPEND_BTEXT(_("\nWind\n"));
427 428 429 430
    wind = get_data(conditions, data->units, WIND_SPEED,
                    FALSE, data->night_time);
    rawvalue = get_data(conditions, data->units, WIND_BEAUFORT,
                        FALSE, data->night_time);
431 432 433 434
    value = g_strdup_printf(_("\t%s: %s %s (%s on the Beaufort scale)\n"),
                            _("Speed"), wind,
                            get_unit(data->units, WIND_SPEED),
                            rawvalue);
435 436 437 438
    g_free(rawvalue);
    g_free(wind);
    APPEND_TEXT_ITEM_REAL(value);

439 440
    rawvalue = get_data(conditions, data->units, WIND_DIRECTION,
                        FALSE, data->night_time);
441 442
    wind = translate_wind_direction(rawvalue);
    g_free(rawvalue);
443 444
    rawvalue = get_data(conditions, data->units, WIND_DIRECTION_DEG,
                        FALSE, data->night_time);
445 446
    value = g_strdup_printf("\t%s: %s (%s%s)\n", _("Direction"),
                            wind, rawvalue,
447
                            get_unit(data->units, WIND_DIRECTION_DEG));
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
    g_free(rawvalue);
    g_free(wind);
    APPEND_TEXT_ITEM_REAL(value);

    /* precipitation */
    APPEND_BTEXT(_("\nPrecipitations\n"));
    APPEND_TEXT_ITEM(_("Precipitations amount"), PRECIPITATIONS);

    /* atmosphere */
    APPEND_BTEXT(_("\nAtmosphere\n"));
    APPEND_TEXT_ITEM(_("Pressure"), PRESSURE);
    APPEND_TEXT_ITEM(_("Humidity"), HUMIDITY);

    /* clouds */
    APPEND_BTEXT(_("\nClouds\n"));
    APPEND_TEXT_ITEM(_("Fog"), FOG);
    APPEND_TEXT_ITEM(_("Low clouds"), CLOUDS_LOW);
    APPEND_TEXT_ITEM(_("Medium clouds"), CLOUDS_MED);
    APPEND_TEXT_ITEM(_("High clouds"), CLOUDS_HIGH);
    APPEND_TEXT_ITEM(_("Cloudiness"), CLOUDINESS);

    APPEND_BTEXT(_("\nData from The Norwegian Meteorological Institute\n"));
    value = g_strdup("http://met.no");
    g_object_set_data_full(G_OBJECT(ltag0), "url", value, g_free);
    APPEND_LINK_ITEM("\t", _("Thanks to met.no"), "http://met.no/", ltag1);

    g_signal_connect(G_OBJECT(view), "motion-notify-event",
Harald Judt's avatar
Harald Judt committed
475
                     G_CALLBACK(view_motion_notify), sum);
476
    g_signal_connect(G_OBJECT(view), "leave-notify-event",
Harald Judt's avatar
Harald Judt committed
477
                     G_CALLBACK(view_leave_notify), sum);
478

Harald Judt's avatar
Harald Judt committed
479
    icon = weather_summary_get_logo(data);
480

Harald Judt's avatar
Harald Judt committed
481 482
    if (icon) {
        sum->icon_ebox = gtk_event_box_new();
483 484
        gtk_event_box_set_visible_window(GTK_EVENT_BOX(sum->icon_ebox), FALSE);
        gtk_container_add(GTK_CONTAINER(sum->icon_ebox), icon);
485
        gtk_text_view_add_child_in_window(GTK_TEXT_VIEW(view),
Harald Judt's avatar
Harald Judt committed
486
                                          sum->icon_ebox,
487
                                          GTK_TEXT_WINDOW_TEXT, 0, 0);
Harald Judt's avatar
Harald Judt committed
488
        gtk_widget_show_all(sum->icon_ebox);
489 490 491
        adj =
            gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scrolled));
        g_signal_connect(G_OBJECT(adj), "value-changed",
Harald Judt's avatar
Harald Judt committed
492
                         G_CALLBACK(view_scrolled_cb), sum);
493
        g_signal_connect(G_OBJECT(view), "size_allocate",
Harald Judt's avatar
Harald Judt committed
494 495 496 497 498 499 500 501 502
                         G_CALLBACK(view_size_allocate_cb), sum);
        g_signal_connect(G_OBJECT(sum->icon_ebox), "button-release-event",
                         G_CALLBACK(icon_clicked), ltag0);
        g_signal_connect(G_OBJECT(sum->icon_ebox), "enter-notify-event",
                         G_CALLBACK(icon_motion_notify), sum);
        g_signal_connect(G_OBJECT(sum->icon_ebox), "motion-notify-event",
                         G_CALLBACK(icon_motion_notify), sum);
        g_signal_connect(G_OBJECT(sum->icon_ebox), "leave-notify-event",
                         G_CALLBACK(view_leave_notify), sum);
503
    }
Harald Judt's avatar
Harald Judt committed
504

505
    return frame;
506
}
507

508

Harald Judt's avatar
Harald Judt committed
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
static gchar *
get_dayname(gint day)
{
    struct tm fcday_tm;
    time_t now_t = time(NULL), fcday_t;
    gint weekday;

    fcday_tm = *localtime(&now_t);
    fcday_t = time_calc_day(fcday_tm, day);
    weekday = localtime(&fcday_t)->tm_wday;
    switch (day) {
    case 0:
        return g_strdup_printf(_("Today"));
    case 1:
        return g_strdup_printf(_("Tomorrow"));
    default:
        return translate_day(weekday);
    }
}


530 531 532 533 534 535 536 537 538 539
static gchar *
forecast_cell_get_tooltip_text(plugin_data *data,
                               xml_time *fcdata)
{
    GString *text;
    gchar *result, *value;
    const gchar *unit;

    /* TRANSLATORS: Please use \t as needed to properly align the values */
    text = g_string_new(_("<b>Times used for calculation</b>\n"));
540
    value = format_date(fcdata->start, NULL, TRUE);
541 542
    g_string_append_printf(text, _("Interval start:\t\t\t%s\n"), value);
    g_free(value);
543
    value = format_date(fcdata->end, NULL, TRUE);
544 545
    g_string_append_printf(text, _("Interval end:\t\t\t%s\n"), value);
    g_free(value);
546
    value = format_date(fcdata->point, NULL, TRUE);
547 548 549
    g_string_append_printf(text, _("Data calculated for:\t%s\n\n"), value);
    g_free(value);

Harald Judt's avatar
Harald Judt committed
550 551 552
    g_string_append(text, _("<b>Temperatures</b>\n"));
    APPEND_TOOLTIP_ITEM(_("Dew point:\t\t\t%s%s%s\n\n"), DEWPOINT);

553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
    g_string_append(text, _("<b>Atmosphere</b>\n"));
    APPEND_TOOLTIP_ITEM(_("Pressure:\t%s%s%s\n"), PRESSURE);
    APPEND_TOOLTIP_ITEM(_("Humidity:\t%s%s%s\n\n"), HUMIDITY);

    g_string_append(text, _("<b>Precipitations</b>\n"));
    APPEND_TOOLTIP_ITEM(_("Amount:\t\t%s%s%s\n\n"), PRECIPITATIONS);

    g_string_append(text, _("<b>Clouds</b>\n"));
    APPEND_TOOLTIP_ITEM(_("Fog:\t\t%s%s%s\n"), FOG);
    APPEND_TOOLTIP_ITEM(_("Low:\t\t%s%s%s\n"), CLOUDS_LOW);
    APPEND_TOOLTIP_ITEM(_("Medium\t\t%s%s%s\n"), CLOUDS_MED);
    APPEND_TOOLTIP_ITEM(_("High:\t\t%s%s%s\n"), CLOUDS_HIGH);
    APPEND_TOOLTIP_ITEM(_("Cloudiness:\t%s%s%s"), CLOUDINESS);

    /* Free GString only and return its character data */
    result = text->str;
    g_string_free(text, FALSE);
    return result;
}


574
static GtkWidget *
Harald Judt's avatar
Harald Judt committed
575 576
wrap_forecast_cell(const GtkWidget *widget,
                   const GdkColor *color)
577
{
578
    GtkWidget *ebox;
Harald Judt's avatar
Harald Judt committed
579

580 581 582 583 584 585 586 587 588 589 590
    ebox = gtk_event_box_new();
    if (color == NULL)
        gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
    else {
        gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), TRUE);
        gtk_widget_modify_bg(GTK_WIDGET(ebox), GTK_STATE_NORMAL, color);
    }
    gtk_container_add(GTK_CONTAINER(ebox), GTK_WIDGET(widget));
    return ebox;
}

591

592
static GtkWidget *
593 594 595
add_forecast_header(const gchar *text,
                    const gdouble angle,
                    const GdkColor *color)
596
{
Harald Judt's avatar
Harald Judt committed
597
    GtkWidget *label, *align;
598 599
    gchar *str;

600 601 602 603 604
    if (angle)
        align = gtk_alignment_new(1, 1, 0, 1);
    else
        align = gtk_alignment_new(1, 1, 1, 0);
    gtk_container_set_border_width(GTK_CONTAINER(align), 4);
605 606

    label = gtk_label_new(NULL);
Harald Judt's avatar
Harald Judt committed
607
    gtk_label_set_angle(GTK_LABEL(label), angle);
608 609 610
    str = g_strdup_printf("<span foreground=\"white\"><b>%s</b></span>", text ? text : "");
    gtk_label_set_markup(GTK_LABEL(label), str);
    g_free(str);
Harald Judt's avatar
Harald Judt committed
611
    gtk_container_add(GTK_CONTAINER(align), GTK_WIDGET(label));
Harald Judt's avatar
Harald Judt committed
612
    return wrap_forecast_cell(align, color);
613 614
}

615

616
static GtkWidget *
617
add_forecast_cell(plugin_data *data,
Harald Judt's avatar
Harald Judt committed
618 619
                  gint day,
                  gint daytime)
620
{
Harald Judt's avatar
Harald Judt committed
621
    GtkWidget *box, *label, *image;
622
    GdkPixbuf *icon;
623
    const GdkColor black = {0, 0x0000, 0x0000, 0x0000};
Harald Judt's avatar
Harald Judt committed
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
    gchar *wind_speed, *wind_direction, *value, *rawvalue;
    xml_time *fcdata;

    box = gtk_vbox_new(FALSE, 0);

    fcdata = make_forecast_data(data->weatherdata, day, daytime);
    if (fcdata == NULL)
        return box;

    if (fcdata->location == NULL) {
        xml_time_free(fcdata);
        return box;
    }

    /* symbol */
639 640
    rawvalue = get_data(fcdata, data->units, SYMBOL,
                        FALSE, data->night_time);
Harald Judt's avatar
Harald Judt committed
641 642 643 644 645 646 647 648
    icon = get_icon(data->icon_theme, rawvalue, 48, (daytime == NIGHT));
    g_free(rawvalue);
    image = gtk_image_new_from_pixbuf(icon);
    gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(image), TRUE, TRUE, 0);
    if (G_LIKELY(icon))
        g_object_unref(G_OBJECT(icon));

    /* symbol description */
649 650
    rawvalue = get_data(fcdata, data->units, SYMBOL,
                        FALSE, data->night_time);
Harald Judt's avatar
Harald Judt committed
651 652 653 654 655 656 657 658 659 660 661
    value = g_strdup_printf("%s",
                            translate_desc(rawvalue, (daytime == NIGHT)));
    g_free(rawvalue);
    label = gtk_label_new(NULL);
    gtk_label_set_markup(GTK_LABEL(label), value);
    if (!(day % 2))
        gtk_widget_modify_fg(GTK_WIDGET(label), GTK_STATE_NORMAL, &black);
    gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(label), TRUE, TRUE, 0);
    g_free(value);

    /* temperature */
662 663
    rawvalue = get_data(fcdata, data->units, TEMPERATURE,
                        data->round, data->night_time);
Harald Judt's avatar
Harald Judt committed
664 665 666 667 668 669 670 671 672 673
    value = g_strdup_printf("%s %s", rawvalue,
                            get_unit(data->units, TEMPERATURE));
    g_free(rawvalue);
    label = gtk_label_new(value);
    if (!(day % 2))
        gtk_widget_modify_fg(GTK_WIDGET(label), GTK_STATE_NORMAL, &black);
    gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(label), TRUE, TRUE, 0);
    g_free(value);

    /* wind direction and speed */
674 675
    rawvalue = get_data(fcdata, data->units, WIND_DIRECTION,
                        FALSE, data->night_time);
Harald Judt's avatar
Harald Judt committed
676
    wind_direction = translate_wind_direction(rawvalue);
677 678
    wind_speed = get_data(fcdata, data->units, WIND_SPEED,
                          data->round, data->night_time);
Harald Judt's avatar
Harald Judt committed
679 680 681 682 683 684 685 686 687 688 689 690 691
    value = g_strdup_printf("%s %s %s", wind_direction, wind_speed,
                            get_unit(data->units, WIND_SPEED));
    g_free(wind_speed);
    g_free(wind_direction);
    g_free(rawvalue);
    label = gtk_label_new(value);
    if (!(day % 2))
        gtk_widget_modify_fg(GTK_WIDGET(label), GTK_STATE_NORMAL, &black);
    gtk_box_pack_start(GTK_BOX(box), label, TRUE, TRUE, 0);
    g_free(value);

    gtk_widget_set_size_request(GTK_WIDGET(box), 150, -1);

692 693 694 695
    value = forecast_cell_get_tooltip_text(data, fcdata);
    gtk_widget_set_tooltip_markup(GTK_WIDGET(box), value);
    g_free(value);

Harald Judt's avatar
Harald Judt committed
696 697 698 699 700 701
    xml_time_free(fcdata);
    return box;
}


static GtkWidget *
702
make_forecast(plugin_data *data)
Harald Judt's avatar
Harald Judt committed
703 704 705
{
    GtkWidget *table, *ebox, *box, *align;
    GtkWidget *forecast_box;
706 707
    const GdkColor lightbg = {0, 0xeaea, 0xeaea, 0xeaea};
    const GdkColor darkbg = {0, 0x6666, 0x6666, 0x6666};
Harald Judt's avatar
Harald Judt committed
708
    gchar *dayname;
Harald Judt's avatar
Harald Judt committed
709 710 711 712 713 714 715
    gint i;
    daytime daytime;

    if (data->forecast_layout == FC_LAYOUT_CALENDAR)
        table = gtk_table_new(5, data->forecast_days + 1, FALSE);
    else
        table = gtk_table_new(data->forecast_days + 1, 5, FALSE);
716 717 718 719 720 721 722

    gtk_table_set_row_spacings(GTK_TABLE(table), 0);
    gtk_table_set_col_spacings(GTK_TABLE(table), 0);

    /* empty upper left corner */
    box = gtk_vbox_new(FALSE, 0);
    gtk_table_attach_defaults(GTK_TABLE(table),
Harald Judt's avatar
Harald Judt committed
723
                              wrap_forecast_cell(box, &darkbg),
724 725 726
                              0, 1, 0, 1);

    /* daytime headers */
Harald Judt's avatar
Harald Judt committed
727 728 729 730
    ATTACH_DAYTIME_HEADER(_("Morning"), 1);
    ATTACH_DAYTIME_HEADER(_("Afternoon"), 2);
    ATTACH_DAYTIME_HEADER(_("Evening"), 3);
    ATTACH_DAYTIME_HEADER(_("Night"), 4);
731

732
    for (i = 0; i < data->forecast_days; i++) {
733
        /* forecast day headers */
Harald Judt's avatar
Harald Judt committed
734 735 736
        dayname = get_dayname(i);
        if (data->forecast_layout == FC_LAYOUT_CALENDAR)
            ebox = add_forecast_header(dayname, 0.0, &darkbg);
737
        else
Harald Judt's avatar
Harald Judt committed
738
            ebox = add_forecast_header(dayname, 90.0, &darkbg);
Harald Judt's avatar
Harald Judt committed
739
        g_free(dayname);
740

Harald Judt's avatar
Harald Judt committed
741 742 743 744 745 746
        if (data->forecast_layout == FC_LAYOUT_CALENDAR)
            gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(ebox),
                                      i+1, i+2, 0, 1);
        else
            gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(ebox),
                                      0, 1, i+1, i+2);
747

748
        /* get forecast data for each daytime */
749
        for (daytime = MORNING; daytime <= NIGHT; daytime++) {
Harald Judt's avatar
Harald Judt committed
750
            forecast_box = add_forecast_cell(data, i, daytime);
Harald Judt's avatar
Harald Judt committed
751 752 753
            align = gtk_alignment_new(0.5, 0.5, 1, 1);
            gtk_container_set_border_width(GTK_CONTAINER(align), 4);
            gtk_container_add(GTK_CONTAINER(align), GTK_WIDGET(forecast_box));
754
            if (i % 2)
Harald Judt's avatar
Harald Judt committed
755
                ebox = wrap_forecast_cell(align, NULL);
756
            else
Harald Judt's avatar
Harald Judt committed
757 758
                ebox = wrap_forecast_cell(align, &lightbg);

Harald Judt's avatar
Harald Judt committed
759 760 761 762 763 764 765 766
            if (data->forecast_layout == FC_LAYOUT_CALENDAR)
                gtk_table_attach_defaults(GTK_TABLE(table),
                                          GTK_WIDGET(ebox),
                                          i+1, i+2, 1+daytime, 2+daytime);
            else
                gtk_table_attach_defaults(GTK_TABLE(table),
                                          GTK_WIDGET(ebox),
                                          1+daytime, 2+daytime, i+1, i+2);
767 768 769
        }
    }
    return table;
770 771
}

772

773
static GtkWidget *
774
create_forecast_tab(plugin_data *data)
775
{
776
    GtkWidget *ebox, *align, *hbox, *scrolled, *table;
777
    GdkWindow *window;
778
    GdkScreen *screen;
779
    GdkRectangle rect;
Harald Judt's avatar
Harald Judt committed
780 781
    gint monitor_num = 0, h_need, h_max, height;
    gint w_need, w_max, width;
782

783 784 785 786 787 788 789 790 791 792
    /* To avoid causing a GDK assertion, determine the monitor
     * geometry using the weather icon window, which has already been
     * realized in contrast to the summary window. Then calculate the
     * maximum height we may use, subtracting some sane value just to
     * be on the safe side. */
    window = GDK_WINDOW(gtk_widget_get_window(GTK_WIDGET(data->iconimage)));
    screen = GDK_SCREEN(gdk_window_get_screen(window));
    if (G_LIKELY(window && screen))
        monitor_num = gdk_screen_get_monitor_at_window(screen, window);
    gdk_screen_get_monitor_geometry(screen, monitor_num, &rect);
793

Harald Judt's avatar
Harald Judt committed
794 795 796
    /* calculate maximum width and height */
    h_max = rect.height - 250;
    w_max = rect.width - 50;
797

Harald Judt's avatar
Harald Judt committed
798 799 800 801 802 803 804 805
    /* calculate needed space using a good arbitrary value */
    if (data->forecast_layout == FC_LAYOUT_CALENDAR) {
        w_need = ((data->forecast_days < 8) ? data->forecast_days : 7) * 142;
        h_need = 500;
    } else {
        w_need = (rect.width <= 720) ? 650 : 700;
        h_need = data->forecast_days * 110;
    }
806 807 808 809

    /* generate the forecast table */
    table = GTK_WIDGET(make_forecast(data));

Harald Judt's avatar
Harald Judt committed
810
    /* generate the containing widgets */
811
    align = gtk_alignment_new(0.5, 0, 0.5, 0);
Harald Judt's avatar
Harald Judt committed
812 813 814 815
    if ((data->forecast_layout == FC_LAYOUT_CALENDAR &&
         w_need < w_max && data->forecast_days < 8) ||
        (data->forecast_layout == FC_LAYOUT_LIST && h_need < h_max)) {
        /* no scroll window needed, just align the contents */
816 817 818 819
        gtk_container_add(GTK_CONTAINER(align), GTK_WIDGET(table));
        gtk_container_set_border_width(GTK_CONTAINER(align), BORDER);
        return align;
    } else {
Harald Judt's avatar
Harald Judt committed
820
        /* contents too big, scroll window needed */
821 822 823 824 825 826 827
        hbox = gtk_hbox_new(FALSE, 0);
        gtk_box_pack_start(GTK_BOX(hbox), table, TRUE, FALSE, 0);
        gtk_container_add(GTK_CONTAINER(align), GTK_WIDGET(hbox));

        scrolled = gtk_scrolled_window_new (NULL, NULL);
        gtk_container_set_border_width(GTK_CONTAINER(scrolled), BORDER);

828 829
        gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled),
                                              align);
830
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
831 832
                                       GTK_POLICY_AUTOMATIC,
                                       GTK_POLICY_AUTOMATIC);
Harald Judt's avatar
Harald Judt committed
833 834 835 836 837 838

        /* set scroll window size */
        width = (w_need > w_max) ? w_max : w_need;
        height = (h_need > h_max) ? h_max : h_need;
        gtk_widget_set_size_request(GTK_WIDGET(scrolled), width, height);

839
        ebox = gtk_event_box_new();
840
        gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), TRUE);
841 842
        gtk_container_add(GTK_CONTAINER(ebox), GTK_WIDGET(scrolled));
        return ebox;
843
    }
844
}
845

846

847
static void
848 849
summary_dialog_response(const GtkWidget *dlg,
                        const gint response,
850
                        GtkWidget *window)
851
{
852 853
    if (response == GTK_RESPONSE_ACCEPT)
        gtk_widget_destroy(window);
854 855
}

856

857 858 859 860 861 862 863 864 865 866 867 868
static void
cb_notebook_page_switched(GtkNotebook *notebook,
                          GtkNotebookPage *page,
                          guint page_num,
                          gpointer user_data)
{
    plugin_data *data = (plugin_data *) user_data;

    data->summary_remember_tab = page_num;
}


869
GtkWidget *
870
create_summary_window(plugin_data *data)
871
{
872
    GtkWidget *window, *notebook, *vbox, *hbox, *label;
Harald Judt's avatar
Harald Judt committed
873
    gchar *title, *symbol;
874 875 876
    GdkPixbuf *icon;
    xml_time *conditions;

877 878
    conditions = get_current_conditions(data->weatherdata);
    window = xfce_titled_dialog_new_with_buttons(_("Weather Report"),
879 880 881 882 883
                                                 NULL,
                                                 GTK_DIALOG_NO_SEPARATOR,
                                                 GTK_STOCK_CLOSE,
                                                 GTK_RESPONSE_ACCEPT, NULL);
    if (data->location_name != NULL) {
884
        title = g_strdup_printf("%s", data->location_name);
885 886 887 888 889
        xfce_titled_dialog_set_subtitle(XFCE_TITLED_DIALOG(window), title);
        g_free(title);
    }

    vbox = gtk_vbox_new(FALSE, 0);
Harald Judt's avatar
Harald Judt committed
890
    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), vbox, TRUE, TRUE, 0);
891

892 893
    symbol = get_data(conditions, data->units, SYMBOL,
                      FALSE, data->night_time);
894
    icon = get_icon(data->icon_theme, symbol, 48, data->night_time);
Harald Judt's avatar
Harald Judt committed
895
    g_free(symbol);
896 897 898 899 900 901

    gtk_window_set_icon(GTK_WINDOW(window), icon);

    if (G_LIKELY(icon))
        g_object_unref(G_OBJECT(icon));

902 903
    if (data->location_name == NULL || data->weatherdata == NULL ||
        data->weatherdata->current_conditions == NULL) {
904 905 906 907 908 909 910 911 912 913 914 915 916 917 918
        hbox = gtk_hbox_new(FALSE, 0);
        if (data->location_name == NULL)
            label = gtk_label_new(_("Please set a location in the plugin settings."));
        else
            label = gtk_label_new(_("Currently no data available."));
        gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
                           TRUE, TRUE, 0);

        gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
                           TRUE, TRUE, 0);
        gtk_window_set_default_size(GTK_WINDOW(window), 500, 400);
    } else {
        notebook = gtk_notebook_new();
        gtk_container_set_border_width(GTK_CONTAINER(notebook), BORDER);
        gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
919
                                 create_forecast_tab(data),
920 921 922 923 924
                                 gtk_label_new_with_mnemonic(_("_Forecast")));
        gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
                                 create_summary_tab(data),
                                 gtk_label_new_with_mnemonic(_("_Details")));
        gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
925 926 927 928
        gtk_widget_show_all(GTK_WIDGET(notebook));
        gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), data->summary_remember_tab);
        g_signal_connect(GTK_NOTEBOOK(notebook), "switch-page",
                         G_CALLBACK(cb_notebook_page_switched), data);
929 930 931 932 933 934
    }

    g_signal_connect(G_OBJECT(window), "response",
                     G_CALLBACK(summary_dialog_response), window);

    return window;
935
}
Harald Judt's avatar
Harald Judt committed
936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953


void
summary_details_free(summary_details *sum)
{
    g_assert(sum != NULL);
    if (G_UNLIKELY(sum == NULL))
        return;

    sum->icon_ebox = NULL;
    sum->text_view = NULL;
    if (sum->hand_cursor)
        gdk_cursor_unref(sum->hand_cursor);
    sum->hand_cursor = NULL;
    if (sum->text_cursor)
        gdk_cursor_unref(sum->text_cursor);
    sum->text_cursor = NULL;
}