~ubuntu-branches/ubuntu/precise/xfce4-panel/precise

1.1.18 by Cody A.W. Somerville
Import upstream version 4.5.93
1
/*
1.1.27 by Lionel Le Folgoc
Import upstream version 4.7.7
2
 * Copyright (C) 2007-2010 Nick Schermer <nick@xfce.org>
1.1.18 by Cody A.W. Somerville
Import upstream version 4.5.93
3
 *
1.1.27 by Lionel Le Folgoc
Import upstream version 4.7.7
4
 * This library is free software; you can redistribute it and/or modify it
1.1.18 by Cody A.W. Somerville
Import upstream version 4.5.93
5
 * under the terms of the GNU General Public License as published by the Free
6
 * Software Foundation; either version 2 of the License, or (at your option)
7
 * any later version.
8
 *
1.1.27 by Lionel Le Folgoc
Import upstream version 4.7.7
9
 * This library is distributed in the hope that it will be useful, but WITHOUT
1.1.18 by Cody A.W. Somerville
Import upstream version 4.5.93
10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12
 * more details.
13
 *
1.1.30 by Yves-Alexis Perez
Import upstream version 4.8.2
14
 * You should have received a copy of the GNU Lesser General Public
15
 * License along with this library; if not, write to the Free Software
16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1.1.3 by Jani Monoses
Import upstream version 4.3.0svn+r19850
17
 */
1 by Simon Huggins
Import upstream version 4.0.5
18
19
#ifdef HAVE_CONFIG_H
20
#include <config.h>
21
#endif
22
23
#ifdef HAVE_TIME_H
24
#include <time.h>
25
#endif
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
26
#ifdef HAVE_MATH_H
27
#include <math.h>
28
#endif
29
30
#include <gtk/gtk.h>
31
#include <exo/exo.h>
32
#include <libxfce4ui/libxfce4ui.h>
33
#include <libxfce4panel/libxfce4panel.h>
34
#include <common/panel-private.h>
35
#include <common/panel-xfconf.h>
36
#include <common/panel-utils.h>
1.1.18 by Cody A.W. Somerville
Import upstream version 4.5.93
37
38
#include "clock.h"
39
#include "clock-analog.h"
40
#include "clock-binary.h"
41
#include "clock-digital.h"
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
42
#include "clock-fuzzy.h"
1.1.18 by Cody A.W. Somerville
Import upstream version 4.5.93
43
#include "clock-lcd.h"
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
44
#include "clock-dialog_ui.h"
45
46
#define DEFAULT_TOOLTIP_FORMAT "%A %d %B %Y"
47
48
49
50
static void     clock_plugin_get_property              (GObject               *object,
51
                                                        guint                  prop_id,
52
                                                        GValue                *value,
53
                                                        GParamSpec            *pspec);
54
static void     clock_plugin_set_property              (GObject               *object,
55
                                                        guint                  prop_id,
56
                                                        const GValue          *value,
57
                                                        GParamSpec            *pspec);
58
static gboolean clock_plugin_leave_notify_event        (GtkWidget             *widget,
59
                                                        GdkEventCrossing      *event);
60
static gboolean clock_plugin_enter_notify_event        (GtkWidget             *widget,
61
                                                        GdkEventCrossing      *event);
62
static gboolean clock_plugin_button_press_event        (GtkWidget             *widget,
63
                                                        GdkEventButton        *event);
64
static void     clock_plugin_construct                 (XfcePanelPlugin       *panel_plugin);
65
static void     clock_plugin_free_data                 (XfcePanelPlugin       *panel_plugin);
66
static gboolean clock_plugin_size_changed              (XfcePanelPlugin       *panel_plugin,
67
                                                        gint                   size);
68
static void     clock_plugin_size_ratio_changed        (XfcePanelPlugin       *panel_plugin);
69
static void     clock_plugin_orientation_changed       (XfcePanelPlugin       *panel_plugin,
70
                                                        GtkOrientation         orientation);
71
static void     clock_plugin_configure_plugin          (XfcePanelPlugin       *panel_plugin);
72
static void     clock_plugin_set_mode                  (ClockPlugin           *plugin);
73
static gboolean clock_plugin_tooltip                   (gpointer               user_data);
74
static gboolean clock_plugin_timeout_running           (gpointer               user_data);
75
static void     clock_plugin_timeout_destroyed         (gpointer               user_data);
76
static gboolean clock_plugin_timeout_sync              (gpointer               user_data);
77
78
79
80
enum
81
{
82
  PROP_0,
83
  PROP_MODE,
84
  PROP_SHOW_FRAME,
85
  PROP_TOOLTIP_FORMAT,
1.1.27 by Lionel Le Folgoc
Import upstream version 4.7.7
86
  PROP_COMMAND,
87
  PROP_ROTATE_VERTICALLY
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
88
};
89
90
typedef enum
91
{
92
  CLOCK_PLUGIN_MODE_ANALOG = 0,
93
  CLOCK_PLUGIN_MODE_BINARY,
94
  CLOCK_PLUGIN_MODE_DIGITAL,
95
  CLOCK_PLUGIN_MODE_FUZZY,
96
  CLOCK_PLUGIN_MODE_LCD,
97
98
  /* defines */
99
  CLOCK_PLUGIN_MODE_MIN = CLOCK_PLUGIN_MODE_ANALOG,
100
  CLOCK_PLUGIN_MODE_MAX = CLOCK_PLUGIN_MODE_LCD,
101
  CLOCK_PLUGIN_MODE_DEFAULT = CLOCK_PLUGIN_MODE_DIGITAL
102
}
103
ClockPluginMode;
104
105
struct _ClockPluginClass
106
{
107
  XfcePanelPluginClass __parent__;
108
};
109
110
struct _ClockPlugin
111
{
112
  XfcePanelPlugin __parent__;
113
114
  GtkWidget          *clock;
115
  GtkWidget          *frame;
116
117
  guint               show_frame : 1;
118
  gchar              *command;
119
  ClockPluginMode     mode;
1.1.27 by Lionel Le Folgoc
Import upstream version 4.7.7
120
  guint               rotate_vertically : 1;
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
121
122
  gchar              *tooltip_format;
123
  ClockPluginTimeout *tooltip_timeout;
124
};
125
126
struct _ClockPluginTimeout
127
{
128
  guint       interval;
129
  GSourceFunc function;
130
  gpointer    data;
131
  guint       timeout_id;
132
  guint       restart : 1;
133
};
134
135
typedef struct
136
{
137
  ClockPlugin *plugin;
138
  GtkBuilder  *builder;
139
}
140
ClockPluginDialog;
141
142
static const gchar *tooltip_formats[] =
143
{
144
  DEFAULT_TOOLTIP_FORMAT,
145
  "%x",
146
  N_("Week %V"),
147
  NULL
148
};
149
150
static const gchar *digital_formats[] =
151
{
152
  DEFAULT_DIGITAL_FORMAT,
153
  "%T",
154
  "%r",
155
  "%I:%M %p",
156
  NULL
157
};
158
159
enum
160
{
161
  COLUMN_FORMAT,
162
  COLUMN_SEPARATOR,
163
  COLUMN_TEXT,
164
  N_COLUMNS
165
};
166
167
168
169
/* define the plugin */
170
XFCE_PANEL_DEFINE_PLUGIN (ClockPlugin, clock_plugin,
171
  xfce_clock_analog_register_type,
172
  xfce_clock_binary_register_type,
173
  xfce_clock_digital_register_type,
174
  xfce_clock_fuzzy_register_type,
175
  xfce_clock_lcd_register_type)
176
177
178
179
static void
180
clock_plugin_class_init (ClockPluginClass *klass)
181
{
182
  GObjectClass         *gobject_class;
183
  GtkWidgetClass       *widget_class;
184
  XfcePanelPluginClass *plugin_class;
185
186
  gobject_class = G_OBJECT_CLASS (klass);
187
  gobject_class->set_property = clock_plugin_set_property;
188
  gobject_class->get_property = clock_plugin_get_property;
189
190
  widget_class = GTK_WIDGET_CLASS (klass);
191
  widget_class->leave_notify_event = clock_plugin_leave_notify_event;
192
  widget_class->enter_notify_event = clock_plugin_enter_notify_event;
193
  widget_class->button_press_event = clock_plugin_button_press_event;
194
195
  plugin_class = XFCE_PANEL_PLUGIN_CLASS (klass);
196
  plugin_class->construct = clock_plugin_construct;
197
  plugin_class->free_data = clock_plugin_free_data;
198
  plugin_class->size_changed = clock_plugin_size_changed;
199
  plugin_class->orientation_changed = clock_plugin_orientation_changed;
200
  plugin_class->configure_plugin = clock_plugin_configure_plugin;
201
202
  g_object_class_install_property (gobject_class,
203
                                   PROP_MODE,
204
                                   g_param_spec_uint ("mode",
205
                                                      NULL, NULL,
206
                                                      CLOCK_PLUGIN_MODE_MIN,
207
                                                      CLOCK_PLUGIN_MODE_MAX,
208
                                                      CLOCK_PLUGIN_MODE_DEFAULT,
209
                                                      EXO_PARAM_READWRITE));
210
211
  g_object_class_install_property (gobject_class,
212
                                   PROP_SHOW_FRAME,
213
                                   g_param_spec_boolean ("show-frame",
214
                                                         NULL, NULL,
215
                                                         TRUE,
216
                                                         EXO_PARAM_READWRITE));
217
218
  g_object_class_install_property (gobject_class,
219
                                   PROP_TOOLTIP_FORMAT,
220
                                   g_param_spec_string ("tooltip-format",
221
                                                        NULL, NULL,
222
                                                        DEFAULT_TOOLTIP_FORMAT,
223
                                                        EXO_PARAM_READWRITE));
224
225
  g_object_class_install_property (gobject_class,
1.1.27 by Lionel Le Folgoc
Import upstream version 4.7.7
226
                                   PROP_ROTATE_VERTICALLY,
227
                                   g_param_spec_boolean ("rotate-vertically",
228
                                                         NULL, NULL,
229
                                                         FALSE,
230
                                                         EXO_PARAM_READWRITE));
231
232
  g_object_class_install_property (gobject_class,
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
233
                                   PROP_COMMAND,
234
                                   g_param_spec_string ("command",
235
                                                        NULL, NULL, NULL,
236
                                                        EXO_PARAM_READWRITE));
237
}
238
239
240
241
static void
242
clock_plugin_init (ClockPlugin *plugin)
243
{
244
  plugin->mode = CLOCK_PLUGIN_MODE_DEFAULT;
245
  plugin->clock = NULL;
246
  plugin->show_frame = TRUE;
247
  plugin->tooltip_format = g_strdup (DEFAULT_TOOLTIP_FORMAT);
248
  plugin->tooltip_timeout = NULL;
249
  plugin->command = NULL;
1.1.27 by Lionel Le Folgoc
Import upstream version 4.7.7
250
  plugin->rotate_vertically = FALSE;
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
251
252
  plugin->frame = gtk_frame_new (NULL);
253
  gtk_container_add (GTK_CONTAINER (plugin), plugin->frame);
254
  gtk_frame_set_shadow_type (GTK_FRAME (plugin->frame), GTK_SHADOW_ETCHED_IN);
255
  gtk_widget_show (plugin->frame);
256
}
257
258
259
260
static void
261
clock_plugin_get_property (GObject    *object,
262
                           guint       prop_id,
263
                           GValue     *value,
264
                           GParamSpec *pspec)
265
{
266
  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (object);
267
268
  switch (prop_id)
269
    {
270
    case PROP_MODE:
271
      g_value_set_uint (value, plugin->mode);
272
      break;
273
274
    case PROP_SHOW_FRAME:
275
      g_value_set_boolean (value, plugin->show_frame);
276
      break;
277
278
    case PROP_TOOLTIP_FORMAT:
279
      g_value_set_string (value, plugin->tooltip_format);
280
      break;
281
282
    case PROP_COMMAND:
283
      g_value_set_string (value, plugin->command);
284
      break;
285
1.1.27 by Lionel Le Folgoc
Import upstream version 4.7.7
286
    case PROP_ROTATE_VERTICALLY:
287
      g_value_set_boolean (value, plugin->rotate_vertically);
288
      break;
289
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
290
    default:
291
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
292
      break;
293
    }
294
}
295
296
297
298
static void
299
clock_plugin_set_property (GObject      *object,
300
                           guint         prop_id,
301
                           const GValue *value,
302
                           GParamSpec   *pspec)
303
{
304
  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (object);
305
  gboolean     show_frame;
1.1.27 by Lionel Le Folgoc
Import upstream version 4.7.7
306
  gboolean     rotate_vertically;
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
307
308
  switch (prop_id)
309
    {
310
    case PROP_MODE:
311
      if (plugin->mode != g_value_get_uint (value))
312
        {
313
          plugin->mode = g_value_get_uint (value);
314
          clock_plugin_set_mode (plugin);
315
        }
316
      break;
317
318
    case PROP_SHOW_FRAME:
319
      show_frame = g_value_get_boolean (value);
320
      if (plugin->show_frame != show_frame)
321
        {
322
          plugin->show_frame = show_frame;
323
          gtk_frame_set_shadow_type (GTK_FRAME (plugin->frame),
324
              show_frame ? GTK_SHADOW_ETCHED_IN : GTK_SHADOW_NONE);
325
        }
326
      break;
327
328
    case PROP_TOOLTIP_FORMAT:
329
      g_free (plugin->tooltip_format);
330
      plugin->tooltip_format = g_value_dup_string (value);
331
      break;
332
333
    case PROP_COMMAND:
334
      g_free (plugin->command);
335
      plugin->command = g_value_dup_string (value);
336
      break;
337
1.1.27 by Lionel Le Folgoc
Import upstream version 4.7.7
338
    case PROP_ROTATE_VERTICALLY:
339
      rotate_vertically = g_value_get_boolean (value);
340
      if (plugin->rotate_vertically != rotate_vertically)
341
        {
342
          plugin->rotate_vertically = rotate_vertically;
343
          clock_plugin_set_mode (plugin);
344
        }
345
      break;
346
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
347
    default:
348
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
349
      break;
350
    }
351
}
352
353
354
355
static gboolean
356
clock_plugin_leave_notify_event (GtkWidget        *widget,
357
                                 GdkEventCrossing *event)
358
{
359
  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (widget);
360
361
  /* stop a running tooltip timeout when we leave the widget */
362
  if (plugin->tooltip_timeout != NULL)
363
    {
364
      clock_plugin_timeout_free (plugin->tooltip_timeout);
365
      plugin->tooltip_timeout = NULL;
366
    }
367
368
  return FALSE;
369
}
370
371
372
373
static gboolean
374
clock_plugin_enter_notify_event (GtkWidget        *widget,
375
                                 GdkEventCrossing *event)
376
{
377
  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (widget);
378
  guint        interval;
379
380
  /* start the tooltip timeout if needed */
381
  if (plugin->tooltip_timeout == NULL)
382
    {
383
      interval = clock_plugin_interval_from_format (plugin->tooltip_format);
384
      plugin->tooltip_timeout = clock_plugin_timeout_new (interval, clock_plugin_tooltip, plugin);
385
    }
386
387
  return FALSE;
388
}
389
390
391
392
static gboolean
393
clock_plugin_button_press_event (GtkWidget      *widget,
394
                                 GdkEventButton *event)
395
{
396
  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (widget);
397
  GError      *error = NULL;
398
399
  if (event->button == 1
400
      && event->type == GDK_2BUTTON_PRESS
401
      && !exo_str_is_empty (plugin->command))
402
    {
403
      /* launch command */
404
      if (!gdk_spawn_command_line_on_screen (gtk_widget_get_screen (widget),
405
                                             plugin->command, &error))
406
        {
407
          xfce_dialog_show_error (NULL, error, _("Failed to execute clock command"));
408
          g_error_free (error);
409
        }
410
411
      return TRUE;
412
    }
413
414
  return (*GTK_WIDGET_CLASS (clock_plugin_parent_class)->button_press_event) (widget, event);
415
}
416
417
418
419
static void
420
clock_plugin_construct (XfcePanelPlugin *panel_plugin)
421
{
422
  ClockPlugin         *plugin = XFCE_CLOCK_PLUGIN (panel_plugin);
423
  const PanelProperty  properties[] =
424
  {
425
    { "mode", G_TYPE_UINT },
426
    { "show-frame", G_TYPE_BOOLEAN },
427
    { "tooltip-format", G_TYPE_STRING },
428
    { "command", G_TYPE_STRING },
1.1.27 by Lionel Le Folgoc
Import upstream version 4.7.7
429
    { "rotate-vertically", G_TYPE_BOOLEAN },
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
430
    { NULL }
431
  };
432
433
  /* show configure */
434
  xfce_panel_plugin_menu_show_configure (panel_plugin);
435
436
  /* connect all properties */
437
  panel_properties_bind (NULL, G_OBJECT (panel_plugin),
438
                         xfce_panel_plugin_get_property_base (panel_plugin),
439
                         properties, FALSE);
440
441
  /* make sure a mode is set */
442
  if (plugin->mode == CLOCK_PLUGIN_MODE_DEFAULT)
443
    clock_plugin_set_mode (plugin);
444
}
445
446
447
448
static void
449
clock_plugin_free_data (XfcePanelPlugin *panel_plugin)
450
{
451
  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (panel_plugin);
452
453
  if (plugin->tooltip_timeout != NULL)
454
    clock_plugin_timeout_free (plugin->tooltip_timeout);
455
456
  g_free (plugin->tooltip_format);
457
  g_free (plugin->command);
458
}
459
460
461
462
static gboolean
463
clock_plugin_size_changed (XfcePanelPlugin *panel_plugin,
464
                           gint             size)
465
{
466
  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (panel_plugin);
467
  gdouble      ratio;
468
  gint         ratio_size;
469
  gint         border = 0;
1.1.27 by Lionel Le Folgoc
Import upstream version 4.7.7
470
  gint         offset;
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
471
472
  if (plugin->clock == NULL)
473
    return TRUE;
474
475
  /* set the frame border */
476
  if (plugin->show_frame && size > 26)
477
    border = 1;
478
  gtk_container_set_border_width (GTK_CONTAINER (plugin->frame), border);
479
480
  /* get the width:height ratio */
481
  g_object_get (G_OBJECT (plugin->clock), "size-ratio", &ratio, NULL);
1.1.27 by Lionel Le Folgoc
Import upstream version 4.7.7
482
  if (ratio > 0)
483
    {
484
      offset = MAX (plugin->frame->style->xthickness, plugin->frame->style->ythickness) + border;
485
      offset *= 2;
486
      ratio_size = size - offset;
487
    }
488
  else
489
    {
490
      ratio_size = -1;
491
      offset = 0;
492
    }
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
493
494
  /* set the clock size */
495
  if (xfce_panel_plugin_get_orientation (panel_plugin) == GTK_ORIENTATION_HORIZONTAL)
496
    {
1.1.27 by Lionel Le Folgoc
Import upstream version 4.7.7
497
      if (ratio > 0)
498
        {
499
          ratio_size = ceil (ratio_size * ratio);
500
          ratio_size += offset;
501
        }
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
502
503
      gtk_widget_set_size_request (GTK_WIDGET (panel_plugin), ratio_size, size);
504
    }
505
  else
506
    {
1.1.27 by Lionel Le Folgoc
Import upstream version 4.7.7
507
      if (ratio > 0)
508
        {
509
          ratio_size = ceil (ratio_size / ratio);
510
          ratio_size += offset;
511
        }
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
512
513
      gtk_widget_set_size_request (GTK_WIDGET (panel_plugin), size, ratio_size);
514
    }
515
516
  return TRUE;
517
}
518
519
520
521
static void
522
clock_plugin_size_ratio_changed (XfcePanelPlugin *panel_plugin)
523
{
524
  clock_plugin_size_changed (panel_plugin, xfce_panel_plugin_get_size (panel_plugin));
525
}
526
527
528
529
static void
530
clock_plugin_orientation_changed (XfcePanelPlugin *panel_plugin,
531
                                  GtkOrientation   orientation)
532
{
533
  /* do a size update */
534
  clock_plugin_size_changed (panel_plugin, xfce_panel_plugin_get_size (panel_plugin));
535
}
536
537
538
539
static void
540
clock_plugin_configure_plugin_mode_changed (GtkComboBox       *combo,
541
                                            ClockPluginDialog *dialog)
542
{
543
  guint    i, active, mode;
544
  GObject *object;
545
  struct {
546
    const gchar *widget;
547
    const gchar *binding;
548
    const gchar *property;
549
  } names[] = {
550
    { "show-seconds", "show-seconds", "active" },
551
    { "true-binary", "true-binary", "active" },
552
    { "show-military", "show-military", "active" },
553
    { "flash-separators", "flash-separators", "active" },
554
    { "show-meridiem", "show-meridiem", "active" },
555
    { "digital-box", "digital-format", "text" },
556
    { "fuzziness-box", "fuzziness", "value" },
557
    { "show-inactive", "show-inactive", "active" },
558
    { "show-grid", "show-grid", "active" },
559
  };
560
561
  panel_return_if_fail (GTK_IS_COMBO_BOX (combo));
562
  panel_return_if_fail (GTK_IS_BUILDER (dialog->builder));
563
  panel_return_if_fail (XFCE_IS_CLOCK_PLUGIN (dialog->plugin));
564
565
  /* the active items for each mode */
566
  mode = gtk_combo_box_get_active (combo);
567
  switch (mode)
568
    {
569
    case CLOCK_PLUGIN_MODE_ANALOG:
570
      active = 1 << 1;
571
      break;
572
573
    case CLOCK_PLUGIN_MODE_BINARY:
574
      active = 1 << 1 | 1 << 2 | 1 << 8 | 1 << 9;
575
      break;
576
577
    case CLOCK_PLUGIN_MODE_DIGITAL:
578
      active = 1 << 6;
579
      break;
580
581
    case CLOCK_PLUGIN_MODE_FUZZY:
582
      active = 1 << 7;
583
      break;
584
585
    case CLOCK_PLUGIN_MODE_LCD:
586
      active = 1 << 1 | 1 << 3 | 1 << 4 | 1 << 5;
587
      break;
588
589
    default:
590
      panel_assert_not_reached ();
591
      active = 0;
592
      break;
593
    }
594
595
  /* show or hide the dialog widgets */
596
  for (i = 0; i < G_N_ELEMENTS (names); i++)
597
    {
598
      object = gtk_builder_get_object (dialog->builder, names[i].widget);
599
      panel_return_if_fail (GTK_IS_WIDGET (object));
600
      if (PANEL_HAS_FLAG (active, 1 << (i + 1)))
601
        gtk_widget_show (GTK_WIDGET (object));
602
      else
603
        gtk_widget_hide (GTK_WIDGET (object));
604
    }
605
606
  /* make sure the new mode is set */
607
  if (dialog->plugin->mode != mode)
608
    g_object_set (G_OBJECT (dialog->plugin), "mode", mode, NULL);
609
  panel_return_if_fail (G_IS_OBJECT (dialog->plugin->clock));
610
611
  /* connect the exo bindings */
612
  for (i = 0; i < G_N_ELEMENTS (names); i++)
613
    {
614
      if (PANEL_HAS_FLAG (active, 1 << (i + 1)))
615
        {
616
          object = gtk_builder_get_object (dialog->builder, names[i].binding);
617
          panel_return_if_fail (G_IS_OBJECT (object));
618
          exo_mutual_binding_new (G_OBJECT (dialog->plugin->clock), names[i].binding,
619
                                  G_OBJECT (object), names[i].property);
620
        }
621
    }
622
}
623
624
625
626
static void
627
clock_plugin_configure_plugin_chooser_changed (GtkComboBox *combo,
628
                                               GtkEntry    *entry)
629
{
630
  GtkTreeIter   iter;
631
  GtkTreeModel *model;
632
  gchar        *format;
633
634
  panel_return_if_fail (GTK_IS_COMBO_BOX (combo));
635
  panel_return_if_fail (GTK_IS_ENTRY (entry));
636
637
  if (gtk_combo_box_get_active_iter (combo, &iter))
638
    {
639
      model = gtk_combo_box_get_model (combo);
640
      gtk_tree_model_get (model, &iter, COLUMN_FORMAT, &format, -1);
641
642
      if (format != NULL)
643
        {
644
          gtk_entry_set_text (entry, format);
645
          gtk_widget_hide (GTK_WIDGET (entry));
646
          g_free (format);
647
        }
648
      else
649
        {
650
          gtk_widget_show (GTK_WIDGET (entry));
651
        }
652
    }
653
}
654
655
656
657
static gboolean
658
clock_plugin_configure_plugin_chooser_separator (GtkTreeModel *model,
659
                                                 GtkTreeIter  *iter,
660
                                                 gpointer      user_data)
661
{
662
  gboolean separator;
663
664
  gtk_tree_model_get (model, iter, COLUMN_SEPARATOR, &separator, -1);
665
666
  return separator;
667
}
668
669
670
671
static void
672
clock_plugin_configure_plugin_chooser_fill (GtkComboBox *combo,
673
                                            GtkEntry    *entry,
674
                                            const gchar *formats[])
675
{
676
  guint         i;
677
  GtkListStore *store;
678
  gchar        *preview;
679
  struct tm     now;
680
  GtkTreeIter   iter;
681
  const gchar  *active_format;
682
  gboolean      has_active = FALSE;
683
684
  panel_return_if_fail (GTK_IS_COMBO_BOX (combo));
685
  panel_return_if_fail (GTK_IS_ENTRY (entry));
686
687
  gtk_combo_box_set_row_separator_func (combo,
688
      clock_plugin_configure_plugin_chooser_separator, NULL, NULL);
689
690
  store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_STRING);
691
  gtk_combo_box_set_model (combo, GTK_TREE_MODEL (store));
692
693
  clock_plugin_get_localtime (&now);
694
695
  active_format = gtk_entry_get_text (entry);
696
697
  for (i = 0; formats[i] != NULL; i++)
698
    {
699
      preview = clock_plugin_strdup_strftime (_(formats[i]), &now);
700
      gtk_list_store_insert_with_values (store, &iter, i,
701
                                         COLUMN_FORMAT, _(formats[i]),
702
                                         COLUMN_TEXT, preview, -1);
703
      g_free (preview);
704
705
      if (has_active == FALSE
706
          && !exo_str_is_empty (active_format)
707
          && strcmp (active_format, formats[i]) == 0)
708
        {
709
          gtk_combo_box_set_active_iter (combo, &iter);
710
          gtk_widget_hide (GTK_WIDGET (entry));
711
          has_active = TRUE;
712
        }
713
    }
714
715
  gtk_list_store_insert_with_values (store, NULL, i++,
716
                                     COLUMN_SEPARATOR, TRUE, -1);
717
718
  gtk_list_store_insert_with_values (store, &iter, i++,
719
                                     COLUMN_TEXT, _("Custom Format"), -1);
720
  if (!has_active)
721
    {
722
      gtk_combo_box_set_active_iter (combo, &iter);
723
      gtk_widget_show (GTK_WIDGET (entry));
724
    }
725
726
  g_signal_connect (G_OBJECT (combo), "changed",
727
      G_CALLBACK (clock_plugin_configure_plugin_chooser_changed), entry);
728
729
  g_object_unref (G_OBJECT (store));
730
}
731
732
733
734
static void
735
clock_plugin_configure_plugin_free (gpointer user_data)
736
{
737
  g_slice_free (ClockPluginDialog, user_data);
738
}
739
740
741
742
static void
743
clock_plugin_configure_plugin (XfcePanelPlugin *panel_plugin)
744
{
745
  ClockPlugin       *plugin = XFCE_CLOCK_PLUGIN (panel_plugin);
746
  ClockPluginDialog *dialog;
747
  GtkBuilder        *builder;
748
  GObject           *window;
749
  GObject           *object;
750
  GObject           *combo;
751
752
  panel_return_if_fail (XFCE_IS_CLOCK_PLUGIN (plugin));
753
754
  /* setup the dialog */
755
  PANEL_UTILS_LINK_4UI
756
  builder = panel_utils_builder_new (panel_plugin, clock_dialog_ui,
757
                                     clock_dialog_ui_length, &window);
758
  if (G_UNLIKELY (builder == NULL))
759
    return;
760
761
  dialog = g_slice_new0 (ClockPluginDialog);
762
  dialog->plugin = plugin;
763
  dialog->builder = builder;
764
765
  object = gtk_builder_get_object (builder, "mode");
766
  g_signal_connect_data (G_OBJECT (object), "changed",
767
      G_CALLBACK (clock_plugin_configure_plugin_mode_changed), dialog,
768
      (GClosureNotify) clock_plugin_configure_plugin_free, 0);
769
  exo_mutual_binding_new (G_OBJECT (plugin), "mode",
770
                          G_OBJECT (object), "active");
771
772
  object = gtk_builder_get_object (builder, "show-frame");
773
  exo_mutual_binding_new (G_OBJECT (plugin), "show-frame",
774
                          G_OBJECT (object), "active");
775
776
  object = gtk_builder_get_object (builder, "tooltip-format");
777
  exo_mutual_binding_new (G_OBJECT (plugin), "tooltip-format",
778
                          G_OBJECT (object), "text");
779
  combo = gtk_builder_get_object (builder, "tooltip-chooser");
780
  clock_plugin_configure_plugin_chooser_fill (GTK_COMBO_BOX (combo),
781
                                              GTK_ENTRY (object),
782
                                              tooltip_formats);
783
784
  object = gtk_builder_get_object (builder, "digital-format");
785
  combo = gtk_builder_get_object (builder, "digital-chooser");
786
  clock_plugin_configure_plugin_chooser_fill (GTK_COMBO_BOX (combo),
787
                                              GTK_ENTRY (object),
788
                                              digital_formats);
789
790
  gtk_widget_show (GTK_WIDGET (window));
791
}
792
793
794
795
static void
796
clock_plugin_set_mode (ClockPlugin *plugin)
797
{
798
  const PanelProperty properties[][5] =
799
  {
800
    { /* analog */
801
      { "show-seconds", G_TYPE_BOOLEAN },
802
      { NULL },
803
    },
804
    { /* binary */
805
      { "show-seconds", G_TYPE_BOOLEAN },
806
      { "true-binary", G_TYPE_BOOLEAN },
807
      { "show-inactive", G_TYPE_BOOLEAN },
808
      { "show-grid", G_TYPE_BOOLEAN },
809
      { NULL },
810
    },
811
    { /* digital */
812
      { "digital-format", G_TYPE_STRING },
813
      { NULL },
814
    },
815
    { /* fuzzy */
816
      { "fuzziness", G_TYPE_UINT },
817
      { NULL },
818
    },
819
    { /* lcd */
820
      { "show-seconds", G_TYPE_BOOLEAN },
821
      { "show-military", G_TYPE_BOOLEAN },
822
      { "show-meridiem", G_TYPE_BOOLEAN },
823
      { "flash-separators", G_TYPE_BOOLEAN },
824
      { NULL },
825
    }
826
  };
827
828
  panel_return_if_fail (XFCE_IS_CLOCK_PLUGIN (plugin));
829
830
  if (plugin->clock != NULL)
831
    gtk_widget_destroy (plugin->clock);
832
833
  /* create a new clock */
834
  if (plugin->mode == CLOCK_PLUGIN_MODE_ANALOG)
835
    plugin->clock = xfce_clock_analog_new ();
836
  else if (plugin->mode == CLOCK_PLUGIN_MODE_BINARY)
837
    plugin->clock = xfce_clock_binary_new ();
838
  else if (plugin->mode == CLOCK_PLUGIN_MODE_DIGITAL)
839
    plugin->clock = xfce_clock_digital_new ();
840
  else if (plugin->mode == CLOCK_PLUGIN_MODE_FUZZY)
841
    plugin->clock = xfce_clock_fuzzy_new ();
842
  else
843
    plugin->clock = xfce_clock_lcd_new ();
844
845
  panel_properties_bind (NULL, G_OBJECT (plugin->clock),
846
                         xfce_panel_plugin_get_property_base (XFCE_PANEL_PLUGIN (plugin)),
847
                         properties[plugin->mode], FALSE);
848
849
  gtk_container_add (GTK_CONTAINER (plugin->frame), plugin->clock);
850
  clock_plugin_size_changed (XFCE_PANEL_PLUGIN (plugin),
851
      xfce_panel_plugin_get_size (XFCE_PANEL_PLUGIN (plugin)));
1.1.27 by Lionel Le Folgoc
Import upstream version 4.7.7
852
853
  if (plugin->rotate_vertically)
854
    exo_binding_new (G_OBJECT (plugin), "orientation", G_OBJECT (plugin->clock), "orientation");
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
855
856
  /* watch width/height changes */
857
  g_signal_connect_swapped (G_OBJECT (plugin->clock), "notify::size-ratio",
858
      G_CALLBACK (clock_plugin_size_ratio_changed), plugin);
1.1.27 by Lionel Le Folgoc
Import upstream version 4.7.7
859
860
  gtk_widget_show (plugin->clock);
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
861
}
862
863
864
865
static gboolean
866
clock_plugin_tooltip (gpointer user_data)
867
{
868
  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (user_data);
869
  gchar       *string;
870
  struct tm    tm;
871
872
  /* get the local time */
873
  clock_plugin_get_localtime (&tm);
874
875
  /* set the tooltip */
876
  string = clock_plugin_strdup_strftime (plugin->tooltip_format, &tm);
877
  gtk_widget_set_tooltip_markup (GTK_WIDGET (plugin), string);
878
  g_free (string);
879
880
  /* make sure the tooltip is up2date */
881
  gtk_widget_trigger_tooltip_query (GTK_WIDGET (plugin));
882
883
  /* keep the timeout running */
884
  return TRUE;
885
}
886
887
888
889
static gboolean
890
clock_plugin_timeout_running (gpointer user_data)
891
{
892
  ClockPluginTimeout *timeout = user_data;
893
  gboolean            result;
894
  struct tm           tm;
895
896
  result = (timeout->function) (timeout->data);
897
898
  /* check if the timeout still runs in time if updating once a minute */
899
  if (result && timeout->interval == CLOCK_INTERVAL_MINUTE)
900
    {
901
      /* sync again when we don't run on time */
902
      clock_plugin_get_localtime (&tm);
903
      timeout->restart = tm.tm_sec != 0;
904
    }
905
906
  return result && !timeout->restart;
907
}
908
909
910
911
static void
912
clock_plugin_timeout_destroyed (gpointer user_data)
913
{
914
  ClockPluginTimeout *timeout = user_data;
915
916
  timeout->timeout_id = 0;
917
918
  if (G_UNLIKELY (timeout->restart))
919
    clock_plugin_timeout_set_interval (timeout, timeout->interval);
920
}
921
922
923
924
static gboolean
925
clock_plugin_timeout_sync (gpointer user_data)
926
{
927
  ClockPluginTimeout *timeout = user_data;
928
929
  /* run the user function */
930
  if ((timeout->function) (timeout->data))
931
    {
932
      /* start the real timeout */
933
      timeout->timeout_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, timeout->interval,
934
                                                        clock_plugin_timeout_running, timeout,
935
                                                        clock_plugin_timeout_destroyed);
936
    }
937
  else
938
    {
939
      timeout->timeout_id = 0;
940
    }
941
942
  /* stop the sync timeout */
943
  return FALSE;
944
}
945
946
947
948
ClockPluginTimeout *
949
clock_plugin_timeout_new (guint       interval,
950
                          GSourceFunc function,
951
                          gpointer    data)
952
{
953
  ClockPluginTimeout *timeout;
954
955
  panel_return_val_if_fail (interval > 0, NULL);
956
  panel_return_val_if_fail (function != NULL, NULL);
957
958
  timeout = g_slice_new0 (ClockPluginTimeout);
959
  timeout->interval = 0;
960
  timeout->function = function;
961
  timeout->data = data;
962
  timeout->timeout_id = 0;
963
  timeout->restart = FALSE;
964
965
  clock_plugin_timeout_set_interval (timeout, interval);
966
967
  return timeout;
968
}
969
970
971
972
void
973
clock_plugin_timeout_set_interval (ClockPluginTimeout *timeout,
974
                                   guint               interval)
975
{
976
  struct tm tm;
977
  guint     next_interval;
978
  gboolean  restart = timeout->restart;
979
980
  panel_return_if_fail (timeout != NULL);
981
  panel_return_if_fail (interval > 0);
982
983
  /* leave if nothing changed and we're not restarting */
984
  if (!restart && timeout->interval == interval)
985
    return;
986
  timeout->interval = interval;
987
  timeout->restart = FALSE;
988
989
  /* stop running timeout */
990
  if (G_LIKELY (timeout->timeout_id != 0))
991
    g_source_remove (timeout->timeout_id);
992
  timeout->timeout_id = 0;
993
994
  /* run function when not restarting, leave if it returns false */
995
  if (!restart && !(timeout->function) (timeout->data))
996
    return;
997
998
  /* get the seconds to the next internal */
999
  if (interval == CLOCK_INTERVAL_MINUTE)
1000
    {
1001
      clock_plugin_get_localtime (&tm);
1002
      next_interval = 60 - tm.tm_sec;
1003
    }
1004
  else
1005
    {
1006
      next_interval = 0;
1007
    }
1008
1009
  if (next_interval > 0)
1010
    {
1011
      /* start the sync timeout */
1012
      timeout->timeout_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, next_interval,
1013
                                                        clock_plugin_timeout_sync,
1014
                                                        timeout, NULL);
1015
    }
1016
  else
1017
    {
1018
      /* directly start running the normal timeout */
1019
      timeout->timeout_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, interval,
1020
                                                        clock_plugin_timeout_running, timeout,
1021
                                                        clock_plugin_timeout_destroyed);
1022
    }
1023
}
1024
1025
1026
1027
void
1028
clock_plugin_timeout_free (ClockPluginTimeout *timeout)
1029
{
1030
  panel_return_if_fail (timeout != NULL);
1031
1032
  timeout->restart = FALSE;
1033
  if (G_LIKELY (timeout->timeout_id != 0))
1034
    g_source_remove (timeout->timeout_id);
1035
  g_slice_free (ClockPluginTimeout, timeout);
1036
}
1037
1038
1039
1040
void
1041
clock_plugin_get_localtime (struct tm *tm)
1042
{
1043
  time_t now = time (NULL);
1.1.18 by Cody A.W. Somerville
Import upstream version 4.5.93
1044
1045
#ifndef HAVE_LOCALTIME_R
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
1046
  struct tm *tmbuf;
1.1.18 by Cody A.W. Somerville
Import upstream version 4.5.93
1047
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
1048
  tmbuf = localtime (&now);
1049
  *tm = *tmbuf;
1.1.18 by Cody A.W. Somerville
Import upstream version 4.5.93
1050
#else
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
1051
  localtime_r (&now, tm);
1052
#endif
1053
}
1054
1055
1056
1057
gchar *
1058
clock_plugin_strdup_strftime (const gchar     *format,
1059
                              const struct tm *tm)
1060
{
1061
  gchar *converted, *result;
1062
  gsize  length;
1063
  gchar  buffer[1024];
1064
1065
  /* leave when format is null */
1066
  if (G_UNLIKELY (exo_str_is_empty (format)))
1067
    return NULL;
1068
1069
  /* convert to locale, because that's what strftime uses */
1070
  converted = g_locale_from_utf8 (format, -1, NULL, NULL, NULL);
1071
  if (G_UNLIKELY (converted == NULL))
1072
    return NULL;
1073
1074
  /* parse the time string */
1075
  length = strftime (buffer, sizeof (buffer), converted, tm);
1076
  if (G_UNLIKELY (length == 0))
1077
    buffer[0] = '\0';
1078
1079
  /* convert the string back to utf-8 */
1080
  result = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
1081
1082
  /* cleanup */
1083
  g_free (converted);
1084
1085
  return result;
1086
}
1087
1088
1089
1090
guint
1091
clock_plugin_interval_from_format (const gchar *format)
1092
{
1093
  const gchar *p;
1094
1095
  if (G_UNLIKELY (exo_str_is_empty (format)))
1096
      return CLOCK_INTERVAL_MINUTE;
1097
1098
  for (p = format; *p != '\0'; ++p)
1099
    {
1100
      if (p[0] == '%' && p[1] != '\0')
1.1.18 by Cody A.W. Somerville
Import upstream version 4.5.93
1101
        {
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
1102
          switch (*++p)
1.1.18 by Cody A.W. Somerville
Import upstream version 4.5.93
1103
            {
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
1104
            case 'c':
1105
            case 'N':
1106
            case 'r':
1107
            case 's':
1108
            case 'S':
1109
            case 'T':
1110
            case 'X':
1111
              return CLOCK_INTERVAL_SECOND;
1.1.18 by Cody A.W. Somerville
Import upstream version 4.5.93
1112
            }
1113
        }
1114
    }
1115
1.1.25 by Lionel Le Folgoc
Import upstream version 4.7.5
1116
  return CLOCK_INTERVAL_MINUTE;
1117
}