Rename panel, plugin, and plugin_class to Panel, Plugin, and
[lxde/lxpanel.git] / src / plugins / dclock.c
CommitLineData
239cb032 1/**
a99ee9e1
JH
2 * Copyright (c) 2006 LxDE Developers, see the file AUTHORS for details.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
a52c2257
HJYP
18
19#include <time.h>
20#include <sys/time.h>
21#include <sys/types.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
e7cb732b 25#include <glib/gi18n.h>
0e300420 26#include <pthread.h>
a52c2257
HJYP
27
28#include "panel.h"
29#include "misc.h"
30#include "plugin.h"
15c1aa11 31#include "glib-mem.h"
a52c2257 32
a52c2257
HJYP
33#include "dbg.h"
34
a52c2257
HJYP
35#define DEFAULT_TIP_FORMAT "%A %x"
36#define DEFAULT_CLOCK_FORMAT "%R"
37
38typedef struct {
39 GtkWidget *eb;
40 GtkWidget *main;
41 GtkWidget *clockw;
ba99d2f1 42 GtkWidget *calwin;
a52c2257
HJYP
43 GtkTooltips *tip;
44 char *tfmt;
45 char *cfmt;
46 char *action;
47 short lastDay;
2de71c90 48 int bold;
a52c2257 49 int timer;
2de71c90
FC
50 int usefontcolor;
51 GdkColor *gfontcolor;
ba99d2f1 52 gboolean cal_show;
a52c2257
HJYP
53} dclock;
54
a97d06a6 55static void
22242ed4 56update_label_orient( Plugin* p );
a52c2257 57
ba99d2f1
FC
58static GtkWidget *create_calendar()
59{
60 GtkWidget *win;
61 GtkWidget *calendar;
62
63 /* create a new window */
64 win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
22242ed4 65 gtk_window_set_default_size(GTK_WINDOW(win), 180, 180);
ba99d2f1 66 gtk_window_set_decorated(GTK_WINDOW(win), FALSE);
22242ed4
HJYP
67 gtk_window_set_resizable (GTK_WINDOW(win), FALSE);
68 gtk_container_set_border_width(GTK_CONTAINER(win), 0);
ba99d2f1
FC
69 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(win), TRUE);
70 gtk_window_set_skip_pager_hint(GTK_WINDOW(win), TRUE);
22242ed4 71 gtk_window_set_type_hint(GTK_WINDOW(win), GDK_WINDOW_TYPE_HINT_DOCK);
ba99d2f1 72 gtk_window_set_position(GTK_WINDOW(win), GTK_WIN_POS_MOUSE);
22242ed4
HJYP
73 gtk_window_stick (GTK_WINDOW(win));
74
75 GtkVBox* box = gtk_vbox_new(FALSE, 0);
ba99d2f1
FC
76
77 /* calendar */
78 calendar = gtk_calendar_new();
79 gtk_calendar_display_options(GTK_CALENDAR(calendar),
80 GTK_CALENDAR_SHOW_WEEK_NUMBERS |
81 GTK_CALENDAR_SHOW_DAY_NAMES |
82 GTK_CALENDAR_SHOW_HEADING);
22242ed4
HJYP
83// gtk_container_add(GTK_CONTAINER(win), calendar);
84 gtk_box_pack_start_defaults( box, calendar );
85 gtk_container_add(GTK_CONTAINER(win), box);
ba99d2f1
FC
86
87 gtk_widget_show_all(win);
88
89 RET(win);
90}
91
0e300420
FC
92static int
93actionProcess( void *arg )
94{
95 ENTER;
96 RET(system((char *) arg));
97}
98
a52c2257
HJYP
99static gboolean
100clicked( GtkWidget *widget, gpointer dummy, dclock *dc)
101{
102 ENTER2;
0e300420
FC
103 if( dc->action ) {
104 pthread_t actionThread;
105 pthread_create(&actionThread, NULL, actionProcess, dc->action);
ba99d2f1
FC
106 } else {
107 if (!dc->cal_show) {
108 dc->cal_show = TRUE;
109 dc->calwin = create_calendar();
110 } else {
111 dc->cal_show = FALSE;
112 gtk_widget_destroy(dc->calwin);
113 dc->calwin = NULL;
114 }
0e300420 115 }
a52c2257
HJYP
116 RET2(TRUE);
117}
118
a52c2257
HJYP
119static gint
120clock_update(gpointer data )
121{
122 char output[64], str[64];
123 time_t now;
124 struct tm * detail;
125 dclock *dc;
126 gchar *utf8;
a97d06a6 127
a52c2257
HJYP
128 ENTER;
129 g_assert(data != NULL);
130 dc = (dclock *)data;
a97d06a6 131
a52c2257
HJYP
132 time(&now);
133 detail = localtime(&now);
faa2693d
HJYP
134 strftime(output, sizeof(output),
135 (dc->cfmt ? dc->cfmt : DEFAULT_CLOCK_FORMAT), detail);
2de71c90
FC
136
137 if (dc->bold&&dc->usefontcolor)
138 g_snprintf(str, 64, "<span color=\"#%06x\"><b>%s</b></span>", gcolor2rgb24(dc->gfontcolor), output);
139 else if (dc->bold)
140 g_snprintf(str, 64, "<b>%s</b>", output);
15c1aa11 141 else if (dc->usefontcolor)
2de71c90
FC
142 g_snprintf(str, 64, "<span color=\"#%06x\">%s</span>", gcolor2rgb24(dc->gfontcolor), output);
143 else
144 g_snprintf(str, 64, "%s", output);
145
faa2693d 146 gtk_label_set_markup (GTK_LABEL(dc->clockw), str);
a52c2257
HJYP
147
148 if (detail->tm_mday != dc->lastDay) {
cfc83537 149 dc->lastDay = detail->tm_mday ;
faa2693d
HJYP
150 strftime (output, sizeof(output),
151 (dc->tfmt ? dc->tfmt : DEFAULT_TIP_FORMAT), detail);
cfc83537 152 if ((utf8 = g_locale_to_utf8(output, -1, NULL, NULL, NULL))) {
faa2693d 153 gtk_tooltips_set_tip(dc->tip, dc->main, utf8, NULL);
cfc83537
HJYP
154 g_free(utf8);
155 }
a52c2257 156 }
2de71c90 157
a52c2257
HJYP
158 RET(TRUE);
159}
160
161
162static int
22242ed4 163dclock_constructor(Plugin *p, char** fp)
a52c2257
HJYP
164{
165 line s;
166 dclock *dc;
8ccd023a 167
a52c2257 168 ENTER;
15c1aa11 169 dc = g_slice_new0(dclock);
a52c2257
HJYP
170 g_return_val_if_fail(dc != NULL, 0);
171 p->priv = dc;
8ccd023a 172
a52c2257 173 s.len = 256;
07863d51 174 dc->cfmt = dc->tfmt = dc->action = dc->bold = 0;
0e300420 175 dc->bold = TRUE;
ba99d2f1 176 dc->cal_show = FALSE;
db449f6e
HJYP
177 if( fp )
178 {
179 while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END) {
180 if (s.type == LINE_NONE) {
181 ERR( "dclock: illegal token %s\n", s.str);
182 goto error;
183 }
184 if (s.type == LINE_VAR) {
a97d06a6 185 if (!g_ascii_strcasecmp(s.t[0], "ClockFmt"))
db449f6e
HJYP
186 dc->cfmt = g_strdup(s.t[1]);
187 else if (!g_ascii_strcasecmp(s.t[0], "TooltipFmt"))
188 dc->tfmt = g_strdup(s.t[1]);
189 else if (!g_ascii_strcasecmp(s.t[0], "Action"))
190 dc->action = g_strdup(s.t[1]);
0e300420 191 else if (!g_ascii_strcasecmp(s.t[0], "BoldFont"))
2de71c90 192 dc->bold = str2num(bool_pair, s.t[1], 0);
db449f6e
HJYP
193 else {
194 ERR( "dclock: unknown var %s\n", s.t[0]);
195 goto error;
196 }
197 } else {
198 ERR( "dclock: illegal in this context %s\n", s.str);
a52c2257
HJYP
199 goto error;
200 }
a52c2257
HJYP
201 }
202 }
a52c2257 203 dc->main = gtk_event_box_new();
faa2693d 204
7f0eb503
FC
205 g_signal_connect (G_OBJECT (dc->main), "button_press_event",
206 G_CALLBACK (clicked), (gpointer) dc);
8ccd023a 207 dc->clockw = gtk_label_new("");
a52c2257
HJYP
208 gtk_misc_set_alignment(GTK_MISC(dc->clockw), 0.5, 0.5);
209 gtk_misc_set_padding(GTK_MISC(dc->clockw), 4, 0);
a97d06a6 210 update_label_orient( p );
a52c2257
HJYP
211 gtk_container_add(GTK_CONTAINER(dc->main), dc->clockw);
212 gtk_widget_show_all(dc->main);
239cb032
HJYP
213
214 dc->tip = p->panel->tooltips;
15556f61 215
a52c2257 216 dc->tip = gtk_tooltips_new();
3806c5aa
HJYP
217#if GLIB_CHECK_VERSION( 2, 10, 0 )
218 g_object_ref_sink( dc->tip );
219#else
220 g_object_ref( dc->tip );
221 gtk_object_sink( dc->tip );
222#endif
15556f61 223
a52c2257 224 dc->timer = g_timeout_add(1000, (GSourceFunc) clock_update, (gpointer)dc);
8ccd023a 225
2de71c90
FC
226 /* font color */
227 if (p->panel->usefontcolor)
228 dc->gfontcolor = &p->panel->gfontcolor;
229
230 dc->usefontcolor = p->panel->usefontcolor;
231
8ccd023a 232 clock_update( dc );
4542c20d 233
22242ed4 234 /* store the created Plugin widget in Plugin->pwid */
4542c20d
HJYP
235 p->pwid = dc->main;
236
a52c2257
HJYP
237 RET(1);
238
239 error:
240 g_free(dc->cfmt);
241 g_free(dc->tfmt);
242 g_free(dc->action);
15c1aa11 243 g_slice_free(dclock, dc);
a52c2257
HJYP
244 RET(0);
245}
246
247
248static void
22242ed4 249dclock_destructor(Plugin *p)
a52c2257 250{
15c1aa11
HJYP
251 dclock *dc = (dclock *)p->priv;
252
253 ENTER;
254 dc = (dclock *) p->priv;
255 if (dc->timer)
256 g_source_remove(dc->timer);
4542c20d 257
15c1aa11 258 /* g_object_unref( dc->tip ); */
9d61a76d 259 gtk_widget_destroy(dc->calwin);
15c1aa11
HJYP
260 g_free(dc->cfmt);
261 g_free(dc->tfmt);
262 g_free(dc->action);
263 g_slice_free(dclock, dc);
264 RET();
a52c2257
HJYP
265}
266
22242ed4 267static void apply_config( Plugin* p )
cfc83537
HJYP
268{
269 /* NOTE: This dirty hack is used to force the update of tooltip
270 because tooltip will be updated when dc->lastDay != today.
271 */
272 dclock* dc = (dclock*)p->priv;
273 --dc->lastDay;
274 clock_update( dc );
275}
276
22242ed4 277static void dclock_config( Plugin *p, GtkWindow* parent )
8ccd023a 278{
04883e73 279 GtkWidget* dlg;
8ccd023a 280 dclock *dc = (dclock *)p->priv;
04883e73 281 dlg = create_generic_config_dlg( _(p->class->name),
5a343ad5
JH
282 GTK_WIDGET(parent),
283 (GSourceFunc) apply_config, (gpointer) p,
04883e73
HJYP
284 _("Clock Format"), &dc->cfmt, G_TYPE_STRING,
285 _("Tooltip Format"), &dc->tfmt, G_TYPE_STRING,
286 _("Action"), &dc->action, G_TYPE_STRING,
0e300420 287 _("Bold font"), &dc->bold, G_TYPE_BOOLEAN,
04883e73 288 NULL );
5a343ad5 289 gtk_window_present( GTK_WINDOW(dlg) );
8ccd023a
HJYP
290}
291
22242ed4 292static void save_config( Plugin* p, FILE* fp )
9c97f69e
HJYP
293{
294 dclock *dc = (dclock *)p->priv;
295 lxpanel_put_str( fp, "ClockFmt", dc->cfmt );
296 lxpanel_put_str( fp, "TooltipFmt", dc->tfmt );
297 lxpanel_put_str( fp, "Action", dc->action );
0e300420 298 lxpanel_put_int( fp, "BoldFont", dc->bold );
9c97f69e
HJYP
299}
300
a97d06a6 301static void
22242ed4 302update_label_orient( Plugin* p )
a97d06a6
HJYP
303{
304 dclock *dc = (dclock *)p->priv;
305 GtkLabel* label = GTK_LABEL(dc->clockw);
306 /* FIXME: gtk+ has only limited support for this, sigh! */
307 gdouble angle;
308 if( p->panel->edge == EDGE_LEFT )
309 angle = 90.0;
310 else if( p->panel->edge == EDGE_RIGHT )
311 angle = 270.0;
312 else
313 angle = 0.0;
314 gtk_label_set_angle( GTK_LABEL(label), angle );
315}
316
22242ed4 317PluginClass dclock_plugin_class = {
a52c2257
HJYP
318 fname: NULL,
319 count: 0,
320
321 type : "dclock",
ce522551 322 name : N_("Digital Clock"),
a52c2257 323 version: "1.0",
e7cb732b 324 description : N_("Display Digital clock and Tooltip"),
a52c2257
HJYP
325
326 constructor : dclock_constructor,
327 destructor : dclock_destructor,
9c97f69e 328 config : dclock_config,
a97d06a6
HJYP
329 save : save_config,
330 orientation : update_label_orient
a52c2257 331};