2
* Digital-clock applet for Awn (based on applet by Ryan Rushton)
4
* Copyright (C) 2010 Michal Hruby <michal.mhr@gmail.com>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
* Author : Michal Hruby <michal.mhr@gmail.com>
24
using DesktopAgnostic.Config;
26
class DigitalClock : AppletSimple
28
private const string EVOLUTION_COMMAND =
29
"evolution calendar:///?startdate=%(year)02d%(month)02d%(day)02dT120000";
30
private const string TIME_ADMIN_COMMAND = "gksudo time-admin";
31
private const string[] authors = {
32
"Michal Hruby <michal.mhr@gmail.com>"
35
private Gtk.Menu _menu;
36
private Awn.Dialog dialog;
37
private OverlayText time_overlay;
38
private OverlayText am_pm_overlay;
39
private OverlayText day_overlay;
40
private OverlayText date_overlay;
42
private DesktopAgnostic.Config.Client client;
43
private string[] current_time = null;
45
private DigitalClockPrefs? prefs = null;
47
public bool is_12_hour { get; set; }
48
public bool show_date { get; set; default = true; }
49
public bool date_before_time { get; set; }
50
public string calendar_command { get; set; default = EVOLUTION_COMMAND; }
51
public string datetime_command { get; set; default = TIME_ADMIN_COMMAND; }
53
public DigitalClock (string canonical_name, string uid, int panel_id)
55
Object(canonical_name: canonical_name, uid: uid, panel_id: panel_id);
57
this.display_name = Gettext._ ("Digital Clock");
58
this.clicked.connect (this.on_clicked);
59
this.context_menu_popup.connect (this.on_context_menu_popup);
61
this.client = Awn.Config.get_default_for_applet (this);
62
this.client.bind (GROUP_DEFAULT, "hour12", this, "is_12_hour",
63
true, BindMethod.FALLBACK);
64
this.client.bind (GROUP_DEFAULT, "show_date", this, "show_date",
65
true, BindMethod.FALLBACK);
66
this.client.bind (GROUP_DEFAULT, "dbt", this, "date_before_time",
67
true, BindMethod.FALLBACK);
68
this.client.bind ("commands", "calendar", this, "calendar_command",
69
true, BindMethod.FALLBACK);
70
this.client.bind ("commands", "adjust_datetime", this, "datetime_command",
71
true, BindMethod.FALLBACK);
73
this.time_overlay = new OverlayText ();
74
this.time_overlay.apply_effects = true;
75
this.add_overlay(this.time_overlay);
77
this.am_pm_overlay = new OverlayText();
78
this.am_pm_overlay.apply_effects = true;
79
this.add_overlay(this.am_pm_overlay);
81
this.day_overlay = new OverlayText();
82
this.day_overlay.apply_effects = true;
83
this.add_overlay(this.day_overlay);
85
this.date_overlay = new OverlayText();
86
this.date_overlay.apply_effects = true;
87
this.add_overlay(this.date_overlay);
89
// we'll just use overlays, but AwnIcon doesn't like not having icon set,
90
// so we'll give it 1x1 transparent pixbuf
91
Gdk.Pixbuf pixbuf = new Gdk.Pixbuf (Gdk.Colorspace.RGB, true, 8, 1, 1);
93
this.set_icon_pixbuf (pixbuf);
95
this.position_changed.connect (this.refresh_overlays);
96
this.size_changed.connect (this.refresh_overlays);
97
this.notify.connect (this.force_refresh);
99
this.refresh_overlays ();
100
this.update_clock ();
102
Timeout.add_seconds (1, () => { this.update_clock (); return true; });
104
this.init_calendar ();
110
this.dialog = new Awn.Dialog.for_widget (this);
111
this.dialog.hide_on_unfocus = true;
113
Gtk.Calendar calendar = new Gtk.Calendar ();
114
calendar.set_display_options (Gtk.CalendarDisplayOptions.SHOW_HEADING |
115
Gtk.CalendarDisplayOptions.SHOW_DAY_NAMES |
116
Gtk.CalendarDisplayOptions.SHOW_WEEK_NUMBERS);
117
calendar.day_selected_double_click.connect (this.start_external_calendar);
119
this.dialog.set_title (_ ("Calendar"));
120
this.dialog.add (calendar);
124
start_external_calendar (Gtk.Calendar calendar)
126
uint year, month, day;
127
calendar.get_date (out year, out month, out day);
130
// damn, this one is pretty complicated to do in Vala
133
"import subprocess;" +
134
"data = {'year': %u, 'month': %u, 'day': %u};".printf (year, month, day) +
135
"command = '%s';".printf (this.calendar_command) +
136
"subprocess.Popen(command % data, shell=True);" +
139
Process.spawn_command_line_async (python_cmd);
145
this.current_time = null;
146
this.refresh_overlays ();
147
this.update_clock ();
153
Gtk.PositionType position = this.get_pos_type ();
154
int size = this.get_size ();
156
this.am_pm_overlay.active = false;
157
this.day_overlay.active = this.show_date;
158
this.date_overlay.active = this.show_date;
160
if (position == Gtk.PositionType.TOP || position == Gtk.PositionType.BOTTOM)
162
// horizontal orientation
163
if (this.date_before_time || !this.show_date)
165
// date on left of time / no date
166
int width = this.show_date ? size * 11 / 5 : size * 3 / 2;
168
this.get_icon ().set_custom_paint (width, size);
170
this.time_overlay.font_sizing = this.show_date ? 22 : 25;
171
this.time_overlay.gravity = this.show_date || this.is_12_hour ?
172
Gdk.Gravity.NORTH_EAST : Gdk.Gravity.CENTER;
174
this.day_overlay.font_sizing = 14;
175
this.day_overlay.gravity = Gdk.Gravity.WEST;
176
this.day_overlay.y_adj = 0;
178
this.date_overlay.font_sizing = 14;
179
this.date_overlay.gravity = Gdk.Gravity.SOUTH_WEST;
183
this.am_pm_overlay.active = true;
184
this.am_pm_overlay.font_sizing = 14;
185
this.am_pm_overlay.gravity = Gdk.Gravity.SOUTH_EAST;
191
int width = this.is_12_hour ? size * 17 / 10 : size * 6 / 5;
193
this.get_icon ().set_custom_paint (width, size);
195
this.time_overlay.font_sizing = this.is_12_hour ? 17 : 18;
196
this.time_overlay.gravity = Gdk.Gravity.NORTH;
198
this.day_overlay.font_sizing = 14;
199
this.day_overlay.gravity = Gdk.Gravity.CENTER;
200
this.day_overlay.y_adj = 0.05;
202
this.date_overlay.font_sizing = 14;
203
this.date_overlay.gravity = Gdk.Gravity.SOUTH;
208
// side orientation, no support for "Date before time"
219
this.get_icon ().set_custom_paint (size, height);
221
this.time_overlay.font_sizing = this.is_12_hour ? 10 : 15;
222
if (!this.show_date) this.time_overlay.font_sizing *= 2;
223
this.time_overlay.gravity = this.show_date ?
224
Gdk.Gravity.NORTH : Gdk.Gravity.CENTER;
226
this.day_overlay.font_sizing = 12;
227
this.day_overlay.gravity = Gdk.Gravity.CENTER;
228
this.day_overlay.y_adj = 0.05;
230
this.date_overlay.font_sizing = 12;
231
this.date_overlay.gravity = Gdk.Gravity.SOUTH;
238
if (!this.time_string_changed ()) return;
240
if (!this.is_12_hour || this.am_pm_overlay.active)
242
this.time_overlay.text = current_time[0];
243
this.am_pm_overlay.text = current_time[1];
247
this.time_overlay.text = "%s %s".printf (current_time[0],
251
this.day_overlay.text = current_time[2];
252
this.date_overlay.text = current_time[3];
255
private bool time_string_changed ()
257
string[] cur_time = this.get_time_string ();
259
if (this.current_time == null)
261
this.current_time = cur_time;
265
for (int i=0; i<this.current_time.length; i++)
267
if (this.current_time[i] != cur_time[i])
269
this.current_time = cur_time;
277
private static string format_current_time (string format)
279
time_t cur_time_t = time_t ();
280
Time cur_time = Time.local (cur_time_t);
282
return cur_time.format (format);
285
private string[] get_time_string ()
287
string[] full_date = new string[4];
289
time_t cur_time_t = time_t ();
290
Time cur_time = Time.local (cur_time_t);
294
full_date[0] = cur_time.format ("%I:%M");
295
full_date[1] = cur_time.format ("%p");
299
full_date[0] = cur_time.format ("%H:%M");
303
full_date[2] = cur_time.format ("%a");
304
full_date[3] = cur_time.format ("%b %d");
312
Gtk.WidgetFlags flags = this.dialog.get_flags () & Gtk.WidgetFlags.VISIBLE;
313
if (flags != Gtk.WidgetFlags.VISIBLE)
315
this.dialog.show_all ();
324
on_context_menu_popup (Gdk.EventButton event)
326
if (this._menu == null)
328
Gtk.ImageMenuItem image_item;
329
Gtk.MenuItem menu_item;
330
Gtk.Widget about_item;
332
this._menu = this.create_default_menu () as Gtk.Menu;
334
// "Copy Time" menu item
335
image_item = new Gtk.ImageMenuItem.with_label (_ ("Copy Time"));
336
image_item.set_image (new Gtk.Image.from_stock (Gtk.STOCK_COPY,
338
image_item.activate.connect ((w) =>
340
unowned Gtk.Clipboard cb = Gtk.Clipboard.get (Gdk.SELECTION_CLIPBOARD);
343
cb.set_text (format_current_time ("%I:%M %p"), -1);
347
cb.set_text (format_current_time ("%H:%M"), -1);
351
this._menu.append (image_item);
353
// "Copy Date" menu item
354
image_item = new Gtk.ImageMenuItem.with_label (_ ("Copy Date"));
355
image_item.set_image (new Gtk.Image.from_stock (Gtk.STOCK_COPY,
357
image_item.activate.connect ((w) =>
359
unowned Gtk.Clipboard cb = Gtk.Clipboard.get (Gdk.SELECTION_CLIPBOARD);
360
cb.set_text (format_current_time ("%A, %B %d %Y"), -1);
363
this._menu.append (image_item);
365
// "Adjust Date & Time" menu item
366
image_item = new Gtk.ImageMenuItem.with_label (_ ("Adjust Date & Time"));
367
image_item.set_image (new Gtk.Image.from_stock (Gtk.STOCK_EDIT,
369
image_item.activate.connect ((w) =>
371
if (this.datetime_command.length > 0)
373
Process.spawn_command_line_async (this.datetime_command);
377
this._menu.append (image_item);
380
menu_item = new Gtk.SeparatorMenuItem ();
382
this._menu.append (menu_item);
384
image_item = new Gtk.ImageMenuItem.from_stock (Gtk.STOCK_PREFERENCES, null);
385
image_item.activate.connect ((w) =>
387
if (this.prefs == null)
389
this.prefs = new DigitalClockPrefs (this);
391
this.prefs.get_dialog ().run ();
392
this.prefs.get_dialog ().destroy ();
398
var dialog = this.prefs.get_dialog ();
399
dialog.present_with_time (Gtk.get_current_event_time ());
403
this._menu.append (image_item);
406
Gtk.MenuItem separator = new Gtk.SeparatorMenuItem ();
408
this._menu.append (separator);
410
about_item = this.create_about_item ("Copyright © 2010 Michal Hruby",
411
AppletLicense.GPLV2, Build.VERSION,
412
Gettext._ ("Displays digital clock."),
413
null, null, "awn-applet-digital-clock",
414
null, authors, null, null);
416
this._menu.append (about_item as Gtk.MenuItem);
418
this._menu.set_screen (null);
419
this._menu.popup (null, null, null, event.button, event.time);
424
awn_applet_factory_initp (string canonical_name, string uid, int panel_id)
427
Gettext.bindtextdomain (Build.GETTEXT_PACKAGE, Build.LOCALEDIR);
428
Gettext.textdomain (Build.GETTEXT_PACKAGE);
430
return new DigitalClock (canonical_name, uid, panel_id);
433
// vim:ft=vala:et:ts=2 sts=2 sw=2:ai:cindent