Merge lp:~ted/indicator-datetime/configurable-format into lp:indicator-datetime/0.3
- configurable-format
- Merge into trunk
Proposed by
Ted Gould
Status: | Merged |
---|---|
Merged at revision: | 16 |
Proposed branch: | lp:~ted/indicator-datetime/configurable-format |
Merge into: | lp:indicator-datetime/0.3 |
Diff against target: |
906 lines (+690/-32) 5 files modified
.bzrignore (+1/-0) configure.ac (+9/-1) data/Makefile.am (+4/-0) data/org.ayatana.indicator.datetime.gschema.xml (+61/-0) src/indicator-datetime.c (+615/-31) |
To merge this branch: | bzr merge lp:~ted/indicator-datetime/configurable-format |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Cody Russell (community) | Approve | ||
Review via email: mp+30160@code.launchpad.net |
Commit message
Description of the change
Making it so that the clock is very configurable via gsettings. I think that we can now support any time format any crazy country can throw at us! Whew!
To post a comment you must log in.
Revision history for this message
Cody Russell (bratsche) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file '.bzrignore' | |||
2 | --- .bzrignore 2010-07-07 22:01:53 +0000 | |||
3 | +++ .bzrignore 2010-07-16 22:03:40 +0000 | |||
4 | @@ -6,3 +6,4 @@ | |||
5 | 6 | po/indicator-datetime.pot | 6 | po/indicator-datetime.pot |
6 | 7 | indicator-datetime-[0-9].[0-9].[0-9].tar.gz | 7 | indicator-datetime-[0-9].[0-9].[0-9].tar.gz |
7 | 8 | data/indicator-datetime.service | 8 | data/indicator-datetime.service |
8 | 9 | data/org.ayatana.indicator.datetime.gschema.valid | ||
9 | 9 | 10 | ||
10 | === modified file 'configure.ac' | |||
11 | --- configure.ac 2010-07-15 15:30:50 +0000 | |||
12 | +++ configure.ac 2010-07-16 22:03:40 +0000 | |||
13 | @@ -35,15 +35,23 @@ | |||
14 | 35 | INDICATOR_REQUIRED_VERSION=0.3.0 | 35 | INDICATOR_REQUIRED_VERSION=0.3.0 |
15 | 36 | DBUSMENUGLIB_REQUIRED_VERSION=0.1.1 | 36 | DBUSMENUGLIB_REQUIRED_VERSION=0.1.1 |
16 | 37 | DBUSMENUGTK_REQUIRED_VERSION=0.1.1 | 37 | DBUSMENUGTK_REQUIRED_VERSION=0.1.1 |
17 | 38 | GIO_REQUIRED_VERSION=2.25.0 | ||
18 | 38 | 39 | ||
19 | 39 | PKG_CHECK_MODULES(INDICATOR, indicator >= $INDICATOR_REQUIRED_VERSION | 40 | PKG_CHECK_MODULES(INDICATOR, indicator >= $INDICATOR_REQUIRED_VERSION |
20 | 40 | dbusmenu-glib >= $DBUSMENUGLIB_REQUIRED_VERSION | 41 | dbusmenu-glib >= $DBUSMENUGLIB_REQUIRED_VERSION |
22 | 41 | dbusmenu-gtk >= $DBUSMENUGTK_REQUIRED_VERSION) | 42 | dbusmenu-gtk >= $DBUSMENUGTK_REQUIRED_VERSION |
23 | 43 | gio-2.0 >= $GIO_REQUIRED_VERSION) | ||
24 | 42 | 44 | ||
25 | 43 | AC_SUBST(INDICATOR_CFLAGS) | 45 | AC_SUBST(INDICATOR_CFLAGS) |
26 | 44 | AC_SUBST(INDICATOR_LIBS) | 46 | AC_SUBST(INDICATOR_LIBS) |
27 | 45 | 47 | ||
28 | 46 | ########################### | 48 | ########################### |
29 | 49 | # Grab the GSettings Macros | ||
30 | 50 | ########################### | ||
31 | 51 | |||
32 | 52 | GLIB_GSETTINGS | ||
33 | 53 | |||
34 | 54 | ########################### | ||
35 | 47 | # Check to see if we're local | 55 | # Check to see if we're local |
36 | 48 | ########################### | 56 | ########################### |
37 | 49 | 57 | ||
38 | 50 | 58 | ||
39 | === modified file 'data/Makefile.am' | |||
40 | --- data/Makefile.am 2010-05-19 02:47:35 +0000 | |||
41 | +++ data/Makefile.am 2010-07-16 22:03:40 +0000 | |||
42 | @@ -1,5 +1,9 @@ | |||
43 | 1 | #SUBDIRS = icons | 1 | #SUBDIRS = icons |
44 | 2 | 2 | ||
45 | 3 | gsettings_SCHEMAS = \ | ||
46 | 4 | org.ayatana.indicator.datetime.gschema.xml | ||
47 | 5 | @GSETTINGS_RULES@ | ||
48 | 6 | |||
49 | 3 | dbus_servicesdir = $(DBUSSERVICEDIR) | 7 | dbus_servicesdir = $(DBUSSERVICEDIR) |
50 | 4 | dbus_services_DATA = indicator-datetime.service | 8 | dbus_services_DATA = indicator-datetime.service |
51 | 5 | 9 | ||
52 | 6 | 10 | ||
53 | === added file 'data/org.ayatana.indicator.datetime.gschema.xml' | |||
54 | --- data/org.ayatana.indicator.datetime.gschema.xml 1970-01-01 00:00:00 +0000 | |||
55 | +++ data/org.ayatana.indicator.datetime.gschema.xml 2010-07-16 22:03:40 +0000 | |||
56 | @@ -0,0 +1,61 @@ | |||
57 | 1 | <schemalist> | ||
58 | 2 | <enum id="time-enum"> | ||
59 | 3 | <value nick="locale-default" value="0" /> | ||
60 | 4 | <value nick="12-hour" value="1" /> | ||
61 | 5 | <value nick="24-hour" value="2" /> | ||
62 | 6 | <value nick="custom" value="3" /> | ||
63 | 7 | </enum> | ||
64 | 8 | <schema id="org.ayatana.indicator.datetime" path="/apps/indicators/datetime/" gettext-domain="indicator-datetime"> | ||
65 | 9 | <key name="time-format" enum="time-enum"> | ||
66 | 10 | <default>'locale-default'</default> | ||
67 | 11 | <summary>What the time format should be</summary> | ||
68 | 12 | <description> | ||
69 | 13 | Controls the time format that is displayed in the indicator. For almost | ||
70 | 14 | all users this should be the default for their locale. If you think the | ||
71 | 15 | setting is wrong for your locale please join or talk to the translation | ||
72 | 16 | team for your langauge. If you just want something different you can | ||
73 | 17 | adjust this to be either 12 or 24 time. Or, you can use a custom format | ||
74 | 18 | string and set the custom-time-format setting. | ||
75 | 19 | </description> | ||
76 | 20 | </key> | ||
77 | 21 | <key name="show-seconds" type="b"> | ||
78 | 22 | <default>false</default> | ||
79 | 23 | <summary>Show the number of seconds in the indicator</summary> | ||
80 | 24 | <description> | ||
81 | 25 | Makes the datetime indicator show the number of seconds in the indicator. | ||
82 | 26 | It's important to note that this will cause additional battery drain as | ||
83 | 27 | the time will update 60 times as often, so it is not recommended. Also, | ||
84 | 28 | this setting will be ignored if the time-format value is set to custom. | ||
85 | 29 | </description> | ||
86 | 30 | </key> | ||
87 | 31 | <key name="show-day" type="b"> | ||
88 | 32 | <default>false</default> | ||
89 | 33 | <summary>Show the day of the week in the indicator</summary> | ||
90 | 34 | <description> | ||
91 | 35 | Puts the day of the week on the panel along with the time and/or date | ||
92 | 36 | depending on settings. This setting will be ignored if the time-format | ||
93 | 37 | value is set to custom. | ||
94 | 38 | </description> | ||
95 | 39 | </key> | ||
96 | 40 | <key name="show-date" type="b"> | ||
97 | 41 | <default>false</default> | ||
98 | 42 | <summary>Show the month and date in the indicator</summary> | ||
99 | 43 | <description> | ||
100 | 44 | Puts the month and the date in the panel along with the time and/or day | ||
101 | 45 | of the week depending on settings. This setting will be ignored if the | ||
102 | 46 | time-format value is set to custom. | ||
103 | 47 | </description> | ||
104 | 48 | </key> | ||
105 | 49 | <key name="custom-time-format" type="s"> | ||
106 | 50 | <default>"%l:%M %p"</default> | ||
107 | 51 | <summary>The format string passed to strftime</summary> | ||
108 | 52 | <description> | ||
109 | 53 | The format of the time and/or date that is visible on the panel when using | ||
110 | 54 | the indicator. For most users this will be a set of predefined values as | ||
111 | 55 | determined by the configuration utility, but advanced users can change it | ||
112 | 56 | to anything strftime can accept. Look at the man page on strftime for | ||
113 | 57 | more information. | ||
114 | 58 | </description> | ||
115 | 59 | </key> | ||
116 | 60 | </schema> | ||
117 | 61 | </schemalist> | ||
118 | 0 | 62 | ||
119 | === modified file 'src/indicator-datetime.c' | |||
120 | --- src/indicator-datetime.c 2010-07-12 20:51:03 +0000 | |||
121 | +++ src/indicator-datetime.c 2010-07-16 22:03:40 +0000 | |||
122 | @@ -27,6 +27,7 @@ | |||
123 | 27 | #include <glib.h> | 27 | #include <glib.h> |
124 | 28 | #include <glib-object.h> | 28 | #include <glib-object.h> |
125 | 29 | #include <glib/gi18n-lib.h> | 29 | #include <glib/gi18n-lib.h> |
126 | 30 | #include <gio/gio.h> | ||
127 | 30 | 31 | ||
128 | 31 | /* Indicator Stuff */ | 32 | /* Indicator Stuff */ |
129 | 32 | #include <libindicator/indicator.h> | 33 | #include <libindicator/indicator.h> |
130 | @@ -63,12 +64,57 @@ | |||
131 | 63 | GtkLabel * label; | 64 | GtkLabel * label; |
132 | 64 | guint timer; | 65 | guint timer; |
133 | 65 | 66 | ||
134 | 67 | gchar * time_string; | ||
135 | 68 | |||
136 | 69 | gint time_mode; | ||
137 | 70 | gboolean show_seconds; | ||
138 | 71 | gboolean show_date; | ||
139 | 72 | gboolean show_day; | ||
140 | 73 | gchar * custom_string; | ||
141 | 74 | |||
142 | 66 | guint idle_measure; | 75 | guint idle_measure; |
143 | 67 | gint max_width; | 76 | gint max_width; |
144 | 68 | 77 | ||
145 | 69 | IndicatorServiceManager * sm; | 78 | IndicatorServiceManager * sm; |
146 | 70 | DbusmenuGtkMenu * menu; | 79 | DbusmenuGtkMenu * menu; |
148 | 71 | }; | 80 | |
149 | 81 | GSettings * settings; | ||
150 | 82 | }; | ||
151 | 83 | |||
152 | 84 | /* Enum for the properties so that they can be quickly | ||
153 | 85 | found and looked up. */ | ||
154 | 86 | enum { | ||
155 | 87 | PROP_0, | ||
156 | 88 | PROP_TIME_FORMAT, | ||
157 | 89 | PROP_SHOW_SECONDS, | ||
158 | 90 | PROP_SHOW_DAY, | ||
159 | 91 | PROP_SHOW_DATE, | ||
160 | 92 | PROP_CUSTOM_TIME_FORMAT | ||
161 | 93 | }; | ||
162 | 94 | |||
163 | 95 | #define PROP_TIME_FORMAT_S "time-format" | ||
164 | 96 | #define PROP_SHOW_SECONDS_S "show-seconds" | ||
165 | 97 | #define PROP_SHOW_DAY_S "show-day" | ||
166 | 98 | #define PROP_SHOW_DATE_S "show-date" | ||
167 | 99 | #define PROP_CUSTOM_TIME_FORMAT_S "custom-time-format" | ||
168 | 100 | |||
169 | 101 | #define SETTINGS_INTERFACE "org.ayatana.indicator.datetime" | ||
170 | 102 | #define SETTINGS_TIME_FORMAT_S "time-format" | ||
171 | 103 | #define SETTINGS_SHOW_SECONDS_S "show-seconds" | ||
172 | 104 | #define SETTINGS_SHOW_DAY_S "show-day" | ||
173 | 105 | #define SETTINGS_SHOW_DATE_S "show-date" | ||
174 | 106 | #define SETTINGS_CUSTOM_TIME_FORMAT_S "custom-time-format" | ||
175 | 107 | |||
176 | 108 | enum { | ||
177 | 109 | SETTINGS_TIME_LOCALE = 0, | ||
178 | 110 | SETTINGS_TIME_12_HOUR = 1, | ||
179 | 111 | SETTINGS_TIME_24_HOUR = 2, | ||
180 | 112 | SETTINGS_TIME_CUSTOM = 3 | ||
181 | 113 | }; | ||
182 | 114 | |||
183 | 115 | #define DEFAULT_TIME_12_FORMAT "%l:%M %p" | ||
184 | 116 | #define DEFAULT_TIME_24_FORMAT "%H:%M" | ||
185 | 117 | #define DEFAULT_TIME_FORMAT DEFAULT_TIME_12_FORMAT | ||
186 | 72 | 118 | ||
187 | 73 | #define INDICATOR_DATETIME_GET_PRIVATE(o) \ | 119 | #define INDICATOR_DATETIME_GET_PRIVATE(o) \ |
188 | 74 | (G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATOR_DATETIME_TYPE, IndicatorDatetimePrivate)) | 120 | (G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATOR_DATETIME_TYPE, IndicatorDatetimePrivate)) |
189 | @@ -77,10 +123,18 @@ | |||
190 | 77 | 123 | ||
191 | 78 | static void indicator_datetime_class_init (IndicatorDatetimeClass *klass); | 124 | static void indicator_datetime_class_init (IndicatorDatetimeClass *klass); |
192 | 79 | static void indicator_datetime_init (IndicatorDatetime *self); | 125 | static void indicator_datetime_init (IndicatorDatetime *self); |
193 | 126 | static void set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); | ||
194 | 127 | static void get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); | ||
195 | 80 | static void indicator_datetime_dispose (GObject *object); | 128 | static void indicator_datetime_dispose (GObject *object); |
196 | 81 | static void indicator_datetime_finalize (GObject *object); | 129 | static void indicator_datetime_finalize (GObject *object); |
197 | 82 | static GtkLabel * get_label (IndicatorObject * io); | 130 | static GtkLabel * get_label (IndicatorObject * io); |
198 | 83 | static GtkMenu * get_menu (IndicatorObject * io); | 131 | static GtkMenu * get_menu (IndicatorObject * io); |
199 | 132 | static GVariant * bind_enum_set (const GValue * value, const GVariantType * type, gpointer user_data); | ||
200 | 133 | static gboolean bind_enum_get (GValue * value, GVariant * variant, gpointer user_data); | ||
201 | 134 | static gchar * generate_format_string (IndicatorDatetime * self); | ||
202 | 135 | static struct tm * update_label (IndicatorDatetime * io); | ||
203 | 136 | static void guess_label_size (IndicatorDatetime * self); | ||
204 | 137 | static void setup_timer (IndicatorDatetime * self, struct tm * ltime); | ||
205 | 84 | 138 | ||
206 | 85 | /* Indicator Module Config */ | 139 | /* Indicator Module Config */ |
207 | 86 | INDICATOR_SET_VERSION | 140 | INDICATOR_SET_VERSION |
208 | @@ -98,11 +152,52 @@ | |||
209 | 98 | object_class->dispose = indicator_datetime_dispose; | 152 | object_class->dispose = indicator_datetime_dispose; |
210 | 99 | object_class->finalize = indicator_datetime_finalize; | 153 | object_class->finalize = indicator_datetime_finalize; |
211 | 100 | 154 | ||
212 | 155 | object_class->set_property = set_property; | ||
213 | 156 | object_class->get_property = get_property; | ||
214 | 157 | |||
215 | 101 | IndicatorObjectClass * io_class = INDICATOR_OBJECT_CLASS(klass); | 158 | IndicatorObjectClass * io_class = INDICATOR_OBJECT_CLASS(klass); |
216 | 102 | 159 | ||
217 | 103 | io_class->get_label = get_label; | 160 | io_class->get_label = get_label; |
218 | 104 | io_class->get_menu = get_menu; | 161 | io_class->get_menu = get_menu; |
219 | 105 | 162 | ||
220 | 163 | g_object_class_install_property (object_class, | ||
221 | 164 | PROP_TIME_FORMAT, | ||
222 | 165 | g_param_spec_int(PROP_TIME_FORMAT_S, | ||
223 | 166 | "A choice of which format should be used on the panel", | ||
224 | 167 | "Chooses between letting the locale choose the time, 12-hour time, 24-time or using the custom string passed to strftime().", | ||
225 | 168 | SETTINGS_TIME_LOCALE, /* min */ | ||
226 | 169 | SETTINGS_TIME_CUSTOM, /* max */ | ||
227 | 170 | SETTINGS_TIME_LOCALE, /* default */ | ||
228 | 171 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | ||
229 | 172 | g_object_class_install_property (object_class, | ||
230 | 173 | PROP_SHOW_SECONDS, | ||
231 | 174 | g_param_spec_boolean(PROP_SHOW_SECONDS_S, | ||
232 | 175 | "Whether to show seconds in the indicator.", | ||
233 | 176 | "Shows seconds along with the time in the indicator. Also effects refresh interval.", | ||
234 | 177 | FALSE, /* default */ | ||
235 | 178 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | ||
236 | 179 | g_object_class_install_property (object_class, | ||
237 | 180 | PROP_SHOW_DAY, | ||
238 | 181 | g_param_spec_boolean(PROP_SHOW_DAY_S, | ||
239 | 182 | "Whether to show the day of the week in the indicator.", | ||
240 | 183 | "Shows the day of the week along with the time in the indicator.", | ||
241 | 184 | FALSE, /* default */ | ||
242 | 185 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | ||
243 | 186 | g_object_class_install_property (object_class, | ||
244 | 187 | PROP_SHOW_DATE, | ||
245 | 188 | g_param_spec_boolean(PROP_SHOW_DATE_S, | ||
246 | 189 | "Whether to show the day and month in the indicator.", | ||
247 | 190 | "Shows the day and month along with the time in the indicator.", | ||
248 | 191 | FALSE, /* default */ | ||
249 | 192 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | ||
250 | 193 | g_object_class_install_property (object_class, | ||
251 | 194 | PROP_CUSTOM_TIME_FORMAT, | ||
252 | 195 | g_param_spec_string(PROP_CUSTOM_TIME_FORMAT_S, | ||
253 | 196 | "The format that is used to show the time on the panel.", | ||
254 | 197 | "A format string in the form used to pass to strftime to make a string for displaying on the panel.", | ||
255 | 198 | DEFAULT_TIME_FORMAT, | ||
256 | 199 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); | ||
257 | 200 | |||
258 | 106 | return; | 201 | return; |
259 | 107 | } | 202 | } |
260 | 108 | 203 | ||
261 | @@ -117,9 +212,51 @@ | |||
262 | 117 | self->priv->idle_measure = 0; | 212 | self->priv->idle_measure = 0; |
263 | 118 | self->priv->max_width = 0; | 213 | self->priv->max_width = 0; |
264 | 119 | 214 | ||
265 | 215 | self->priv->time_string = g_strdup(DEFAULT_TIME_FORMAT); | ||
266 | 216 | |||
267 | 217 | self->priv->time_mode = SETTINGS_TIME_LOCALE; | ||
268 | 218 | self->priv->show_seconds = FALSE; | ||
269 | 219 | self->priv->show_date = FALSE; | ||
270 | 220 | self->priv->show_day = FALSE; | ||
271 | 221 | self->priv->custom_string = g_strdup(DEFAULT_TIME_FORMAT); | ||
272 | 222 | |||
273 | 120 | self->priv->sm = NULL; | 223 | self->priv->sm = NULL; |
274 | 121 | self->priv->menu = NULL; | 224 | self->priv->menu = NULL; |
275 | 122 | 225 | ||
276 | 226 | self->priv->settings = g_settings_new(SETTINGS_INTERFACE); | ||
277 | 227 | if (self->priv->settings != NULL) { | ||
278 | 228 | g_settings_bind_with_mapping(self->priv->settings, | ||
279 | 229 | SETTINGS_TIME_FORMAT_S, | ||
280 | 230 | self, | ||
281 | 231 | PROP_TIME_FORMAT_S, | ||
282 | 232 | G_SETTINGS_BIND_DEFAULT, | ||
283 | 233 | bind_enum_get, | ||
284 | 234 | bind_enum_set, | ||
285 | 235 | NULL, NULL); /* Userdata and destroy func */ | ||
286 | 236 | g_settings_bind(self->priv->settings, | ||
287 | 237 | SETTINGS_SHOW_SECONDS_S, | ||
288 | 238 | self, | ||
289 | 239 | PROP_SHOW_SECONDS_S, | ||
290 | 240 | G_SETTINGS_BIND_DEFAULT); | ||
291 | 241 | g_settings_bind(self->priv->settings, | ||
292 | 242 | SETTINGS_SHOW_DAY_S, | ||
293 | 243 | self, | ||
294 | 244 | PROP_SHOW_DAY_S, | ||
295 | 245 | G_SETTINGS_BIND_DEFAULT); | ||
296 | 246 | g_settings_bind(self->priv->settings, | ||
297 | 247 | SETTINGS_SHOW_DATE_S, | ||
298 | 248 | self, | ||
299 | 249 | PROP_SHOW_DATE_S, | ||
300 | 250 | G_SETTINGS_BIND_DEFAULT); | ||
301 | 251 | g_settings_bind(self->priv->settings, | ||
302 | 252 | SETTINGS_CUSTOM_TIME_FORMAT_S, | ||
303 | 253 | self, | ||
304 | 254 | PROP_CUSTOM_TIME_FORMAT_S, | ||
305 | 255 | G_SETTINGS_BIND_DEFAULT); | ||
306 | 256 | } else { | ||
307 | 257 | g_warning("Unable to get settings for '" SETTINGS_INTERFACE "'"); | ||
308 | 258 | } | ||
309 | 259 | |||
310 | 123 | self->priv->sm = indicator_service_manager_new_version(SERVICE_NAME, SERVICE_VERSION); | 260 | self->priv->sm = indicator_service_manager_new_version(SERVICE_NAME, SERVICE_VERSION); |
311 | 124 | 261 | ||
312 | 125 | return; | 262 | return; |
313 | @@ -155,6 +292,11 @@ | |||
314 | 155 | self->priv->sm = NULL; | 292 | self->priv->sm = NULL; |
315 | 156 | } | 293 | } |
316 | 157 | 294 | ||
317 | 295 | if (self->priv->settings != NULL) { | ||
318 | 296 | g_object_unref(G_OBJECT(self->priv->settings)); | ||
319 | 297 | self->priv->settings = NULL; | ||
320 | 298 | } | ||
321 | 299 | |||
322 | 158 | G_OBJECT_CLASS (indicator_datetime_parent_class)->dispose (object); | 300 | G_OBJECT_CLASS (indicator_datetime_parent_class)->dispose (object); |
323 | 159 | return; | 301 | return; |
324 | 160 | } | 302 | } |
325 | @@ -162,11 +304,181 @@ | |||
326 | 162 | static void | 304 | static void |
327 | 163 | indicator_datetime_finalize (GObject *object) | 305 | indicator_datetime_finalize (GObject *object) |
328 | 164 | { | 306 | { |
329 | 307 | IndicatorDatetime * self = INDICATOR_DATETIME(object); | ||
330 | 308 | |||
331 | 309 | if (self->priv->time_string != NULL) { | ||
332 | 310 | g_free(self->priv->time_string); | ||
333 | 311 | self->priv->time_string = NULL; | ||
334 | 312 | } | ||
335 | 313 | |||
336 | 314 | if (self->priv->custom_string != NULL) { | ||
337 | 315 | g_free(self->priv->custom_string); | ||
338 | 316 | self->priv->custom_string = NULL; | ||
339 | 317 | } | ||
340 | 165 | 318 | ||
341 | 166 | G_OBJECT_CLASS (indicator_datetime_parent_class)->finalize (object); | 319 | G_OBJECT_CLASS (indicator_datetime_parent_class)->finalize (object); |
342 | 167 | return; | 320 | return; |
343 | 168 | } | 321 | } |
344 | 169 | 322 | ||
345 | 323 | /* Turns the int value into a string GVariant */ | ||
346 | 324 | static GVariant * | ||
347 | 325 | bind_enum_set (const GValue * value, const GVariantType * type, gpointer user_data) | ||
348 | 326 | { | ||
349 | 327 | switch (g_value_get_int(value)) { | ||
350 | 328 | case SETTINGS_TIME_LOCALE: | ||
351 | 329 | return g_variant_new_string("locale-default"); | ||
352 | 330 | case SETTINGS_TIME_12_HOUR: | ||
353 | 331 | return g_variant_new_string("12-hour"); | ||
354 | 332 | case SETTINGS_TIME_24_HOUR: | ||
355 | 333 | return g_variant_new_string("24-hour"); | ||
356 | 334 | case SETTINGS_TIME_CUSTOM: | ||
357 | 335 | return g_variant_new_string("custom"); | ||
358 | 336 | default: | ||
359 | 337 | return NULL; | ||
360 | 338 | } | ||
361 | 339 | } | ||
362 | 340 | |||
363 | 341 | /* Turns a string GVariant into an int value */ | ||
364 | 342 | static gboolean | ||
365 | 343 | bind_enum_get (GValue * value, GVariant * variant, gpointer user_data) | ||
366 | 344 | { | ||
367 | 345 | const gchar * str = g_variant_get_string(variant, NULL); | ||
368 | 346 | gint output = 0; | ||
369 | 347 | |||
370 | 348 | if (g_strcmp0(str, "locale-default") == 0) { | ||
371 | 349 | output = SETTINGS_TIME_LOCALE; | ||
372 | 350 | } else if (g_strcmp0(str, "12-hour") == 0) { | ||
373 | 351 | output = SETTINGS_TIME_12_HOUR; | ||
374 | 352 | } else if (g_strcmp0(str, "24-hour") == 0) { | ||
375 | 353 | output = SETTINGS_TIME_24_HOUR; | ||
376 | 354 | } else if (g_strcmp0(str, "custom") == 0) { | ||
377 | 355 | output = SETTINGS_TIME_CUSTOM; | ||
378 | 356 | } else { | ||
379 | 357 | return FALSE; | ||
380 | 358 | } | ||
381 | 359 | |||
382 | 360 | g_value_set_int(value, output); | ||
383 | 361 | return TRUE; | ||
384 | 362 | } | ||
385 | 363 | |||
386 | 364 | /* Sets a property on the object */ | ||
387 | 365 | static void | ||
388 | 366 | set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) | ||
389 | 367 | { | ||
390 | 368 | IndicatorDatetime * self = INDICATOR_DATETIME(object); | ||
391 | 369 | gboolean update = FALSE; | ||
392 | 370 | |||
393 | 371 | switch(prop_id) { | ||
394 | 372 | case PROP_TIME_FORMAT: { | ||
395 | 373 | gint newval = g_value_get_int(value); | ||
396 | 374 | if (newval != self->priv->time_mode) { | ||
397 | 375 | update = TRUE; | ||
398 | 376 | self->priv->time_mode = newval; | ||
399 | 377 | } | ||
400 | 378 | break; | ||
401 | 379 | } | ||
402 | 380 | case PROP_SHOW_SECONDS: | ||
403 | 381 | if (g_value_get_boolean(value) != self->priv->show_seconds) { | ||
404 | 382 | self->priv->show_seconds = !self->priv->show_seconds; | ||
405 | 383 | if (self->priv->time_mode != SETTINGS_TIME_CUSTOM) { | ||
406 | 384 | update = TRUE; | ||
407 | 385 | setup_timer(self, NULL); | ||
408 | 386 | } | ||
409 | 387 | } | ||
410 | 388 | break; | ||
411 | 389 | case PROP_SHOW_DAY: | ||
412 | 390 | if (g_value_get_boolean(value) != self->priv->show_day) { | ||
413 | 391 | self->priv->show_day = !self->priv->show_day; | ||
414 | 392 | if (self->priv->time_mode != SETTINGS_TIME_CUSTOM) { | ||
415 | 393 | update = TRUE; | ||
416 | 394 | } | ||
417 | 395 | } | ||
418 | 396 | break; | ||
419 | 397 | case PROP_SHOW_DATE: | ||
420 | 398 | if (g_value_get_boolean(value) != self->priv->show_date) { | ||
421 | 399 | self->priv->show_date = !self->priv->show_date; | ||
422 | 400 | if (self->priv->time_mode != SETTINGS_TIME_CUSTOM) { | ||
423 | 401 | update = TRUE; | ||
424 | 402 | } | ||
425 | 403 | } | ||
426 | 404 | break; | ||
427 | 405 | case PROP_CUSTOM_TIME_FORMAT: { | ||
428 | 406 | const gchar * newstr = g_value_get_string(value); | ||
429 | 407 | if (g_strcmp0(newstr, self->priv->custom_string) != 0) { | ||
430 | 408 | if (self->priv->custom_string != NULL) { | ||
431 | 409 | g_free(self->priv->custom_string); | ||
432 | 410 | self->priv->custom_string = NULL; | ||
433 | 411 | } | ||
434 | 412 | self->priv->custom_string = g_strdup(newstr); | ||
435 | 413 | if (self->priv->time_mode == SETTINGS_TIME_CUSTOM) { | ||
436 | 414 | update = TRUE; | ||
437 | 415 | setup_timer(self, NULL); | ||
438 | 416 | } | ||
439 | 417 | } | ||
440 | 418 | break; | ||
441 | 419 | } | ||
442 | 420 | default: | ||
443 | 421 | G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); | ||
444 | 422 | return; | ||
445 | 423 | } | ||
446 | 424 | |||
447 | 425 | if (!update) { | ||
448 | 426 | return; | ||
449 | 427 | } | ||
450 | 428 | |||
451 | 429 | /* Get the new format string */ | ||
452 | 430 | gchar * newformat = generate_format_string(self); | ||
453 | 431 | |||
454 | 432 | /* check to ensure the format really changed */ | ||
455 | 433 | if (g_strcmp0(self->priv->time_string, newformat) == 0) { | ||
456 | 434 | g_free(newformat); | ||
457 | 435 | return; | ||
458 | 436 | } | ||
459 | 437 | |||
460 | 438 | /* Okay now process the change */ | ||
461 | 439 | if (self->priv->time_string != NULL) { | ||
462 | 440 | g_free(self->priv->time_string); | ||
463 | 441 | self->priv->time_string = NULL; | ||
464 | 442 | } | ||
465 | 443 | self->priv->time_string = newformat; | ||
466 | 444 | |||
467 | 445 | /* And update everything */ | ||
468 | 446 | update_label(self); | ||
469 | 447 | guess_label_size(self); | ||
470 | 448 | |||
471 | 449 | return; | ||
472 | 450 | } | ||
473 | 451 | |||
474 | 452 | /* Gets a property from the object */ | ||
475 | 453 | static void | ||
476 | 454 | get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) | ||
477 | 455 | { | ||
478 | 456 | IndicatorDatetime * self = INDICATOR_DATETIME(object); | ||
479 | 457 | |||
480 | 458 | switch(prop_id) { | ||
481 | 459 | case PROP_TIME_FORMAT: | ||
482 | 460 | g_value_set_int(value, self->priv->time_mode); | ||
483 | 461 | break; | ||
484 | 462 | case PROP_SHOW_SECONDS: | ||
485 | 463 | g_value_set_boolean(value, self->priv->show_seconds); | ||
486 | 464 | break; | ||
487 | 465 | case PROP_SHOW_DAY: | ||
488 | 466 | g_value_set_boolean(value, self->priv->show_day); | ||
489 | 467 | break; | ||
490 | 468 | case PROP_SHOW_DATE: | ||
491 | 469 | g_value_set_boolean(value, self->priv->show_date); | ||
492 | 470 | break; | ||
493 | 471 | case PROP_CUSTOM_TIME_FORMAT: | ||
494 | 472 | g_value_set_string(value, self->priv->custom_string); | ||
495 | 473 | break; | ||
496 | 474 | default: | ||
497 | 475 | G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); | ||
498 | 476 | return; | ||
499 | 477 | } | ||
500 | 478 | |||
501 | 479 | return; | ||
502 | 480 | } | ||
503 | 481 | |||
504 | 170 | /* Looks at the size of the label, if it grew beyond what we | 482 | /* Looks at the size of the label, if it grew beyond what we |
505 | 171 | thought was the max, make sure it doesn't shrink again. */ | 483 | thought was the max, make sure it doesn't shrink again. */ |
506 | 172 | static gboolean | 484 | static gboolean |
507 | @@ -190,12 +502,12 @@ | |||
508 | 190 | } | 502 | } |
509 | 191 | 503 | ||
510 | 192 | /* Updates the label to be the current time. */ | 504 | /* Updates the label to be the current time. */ |
512 | 193 | static void | 505 | static struct tm * |
513 | 194 | update_label (IndicatorDatetime * io) | 506 | update_label (IndicatorDatetime * io) |
514 | 195 | { | 507 | { |
515 | 196 | IndicatorDatetime * self = INDICATOR_DATETIME(io); | 508 | IndicatorDatetime * self = INDICATOR_DATETIME(io); |
516 | 197 | 509 | ||
518 | 198 | if (self->priv->label == NULL) return; | 510 | if (self->priv->label == NULL) return NULL; |
519 | 199 | 511 | ||
520 | 200 | gchar longstr[128]; | 512 | gchar longstr[128]; |
521 | 201 | time_t t; | 513 | time_t t; |
522 | @@ -206,10 +518,10 @@ | |||
523 | 206 | if (ltime == NULL) { | 518 | if (ltime == NULL) { |
524 | 207 | g_debug("Error getting local time"); | 519 | g_debug("Error getting local time"); |
525 | 208 | gtk_label_set_label(self->priv->label, _("Error getting time")); | 520 | gtk_label_set_label(self->priv->label, _("Error getting time")); |
527 | 209 | return; | 521 | return NULL; |
528 | 210 | } | 522 | } |
529 | 211 | 523 | ||
531 | 212 | strftime(longstr, 128, "%l:%M %p", ltime); | 524 | strftime(longstr, 128, self->priv->time_string, ltime); |
532 | 213 | 525 | ||
533 | 214 | gchar * utf8 = g_locale_to_utf8(longstr, -1, NULL, NULL, NULL); | 526 | gchar * utf8 = g_locale_to_utf8(longstr, -1, NULL, NULL, NULL); |
534 | 215 | gtk_label_set_label(self->priv->label, utf8); | 527 | gtk_label_set_label(self->priv->label, utf8); |
535 | @@ -219,24 +531,43 @@ | |||
536 | 219 | self->priv->idle_measure = g_idle_add(idle_measure, io); | 531 | self->priv->idle_measure = g_idle_add(idle_measure, io); |
537 | 220 | } | 532 | } |
538 | 221 | 533 | ||
540 | 222 | return; | 534 | return ltime; |
541 | 223 | } | 535 | } |
542 | 224 | 536 | ||
543 | 225 | /* Runs every minute and updates the time */ | 537 | /* Runs every minute and updates the time */ |
544 | 226 | gboolean | 538 | gboolean |
546 | 227 | minute_timer_func (gpointer user_data) | 539 | timer_func (gpointer user_data) |
547 | 228 | { | 540 | { |
548 | 229 | IndicatorDatetime * self = INDICATOR_DATETIME(user_data); | 541 | IndicatorDatetime * self = INDICATOR_DATETIME(user_data); |
549 | 542 | self->priv->timer = 0; | ||
550 | 543 | struct tm * ltime = update_label(self); | ||
551 | 544 | setup_timer(self, ltime); | ||
552 | 545 | return FALSE; | ||
553 | 546 | } | ||
554 | 230 | 547 | ||
558 | 231 | if (self->priv->label != NULL) { | 548 | /* Configure the timer to run the next time through */ |
559 | 232 | update_label(self); | 549 | static void |
560 | 233 | return TRUE; | 550 | setup_timer (IndicatorDatetime * self, struct tm * ltime) |
561 | 551 | { | ||
562 | 552 | if (self->priv->timer != 0) { | ||
563 | 553 | g_source_remove(self->priv->timer); | ||
564 | 554 | self->priv->timer = 0; | ||
565 | 555 | } | ||
566 | 556 | |||
567 | 557 | if (self->priv->show_seconds) { | ||
568 | 558 | self->priv->timer = g_timeout_add_seconds(1, timer_func, self); | ||
569 | 234 | } else { | 559 | } else { |
572 | 235 | self->priv->timer = 0; | 560 | if (ltime == NULL) { |
573 | 236 | return FALSE; | 561 | time_t t; |
574 | 562 | t = time(NULL); | ||
575 | 563 | ltime = localtime(&t); | ||
576 | 564 | } | ||
577 | 565 | |||
578 | 566 | /* Plus 2 so we're just after the minute, don't want to be early. */ | ||
579 | 567 | self->priv->timer = g_timeout_add_seconds(60 - ltime->tm_sec + 2, timer_func, self); | ||
580 | 237 | } | 568 | } |
581 | 238 | 569 | ||
583 | 239 | return FALSE; | 570 | return; |
584 | 240 | } | 571 | } |
585 | 241 | 572 | ||
586 | 242 | /* Does a quick meausre of how big the string is in | 573 | /* Does a quick meausre of how big the string is in |
587 | @@ -254,33 +585,203 @@ | |||
588 | 254 | return width; | 585 | return width; |
589 | 255 | } | 586 | } |
590 | 256 | 587 | ||
591 | 588 | /* Format for the table of strftime() modifiers to what | ||
592 | 589 | we need to check when determining the length */ | ||
593 | 590 | typedef struct _strftime_type_t strftime_type_t; | ||
594 | 591 | struct _strftime_type_t { | ||
595 | 592 | char character; | ||
596 | 593 | gint mask; | ||
597 | 594 | }; | ||
598 | 595 | |||
599 | 596 | enum { | ||
600 | 597 | STRFTIME_MASK_NONE = 0, /* Hours or minutes as we always test those */ | ||
601 | 598 | STRFTIME_MASK_SECONDS = 1 << 0, /* Seconds count */ | ||
602 | 599 | STRFTIME_MASK_AMPM = 1 << 1, /* AM/PM counts */ | ||
603 | 600 | STRFTIME_MASK_WEEK = 1 << 2, /* Day of the week maters (Sat, Sun, etc.) */ | ||
604 | 601 | STRFTIME_MASK_DAY = 1 << 3, /* Day of the month counts (Feb 1st) */ | ||
605 | 602 | STRFTIME_MASK_MONTH = 1 << 4, /* Which month matters */ | ||
606 | 603 | STRFTIME_MASK_YEAR = 1 << 5, /* Which year matters */ | ||
607 | 604 | /* Last entry, combines all previous */ | ||
608 | 605 | STRFTIME_MASK_ALL = (STRFTIME_MASK_SECONDS | STRFTIME_MASK_AMPM | STRFTIME_MASK_WEEK | STRFTIME_MASK_DAY | STRFTIME_MASK_MONTH | STRFTIME_MASK_YEAR) | ||
609 | 606 | }; | ||
610 | 607 | |||
611 | 608 | /* A table taken from the man page of strftime to what the different | ||
612 | 609 | characters can effect. These are worst case in that we need to | ||
613 | 610 | test the length based on all these things to ensure that we have | ||
614 | 611 | a reasonable string lenght measurement. */ | ||
615 | 612 | const static strftime_type_t strftime_type[] = { | ||
616 | 613 | {'a', STRFTIME_MASK_WEEK}, | ||
617 | 614 | {'A', STRFTIME_MASK_WEEK}, | ||
618 | 615 | {'b', STRFTIME_MASK_MONTH}, | ||
619 | 616 | {'B', STRFTIME_MASK_MONTH}, | ||
620 | 617 | {'c', STRFTIME_MASK_ALL}, /* We don't know, so we have to assume all */ | ||
621 | 618 | {'C', STRFTIME_MASK_YEAR}, | ||
622 | 619 | {'d', STRFTIME_MASK_MONTH}, | ||
623 | 620 | {'D', STRFTIME_MASK_MONTH | STRFTIME_MASK_YEAR | STRFTIME_MASK_DAY}, | ||
624 | 621 | {'e', STRFTIME_MASK_DAY}, | ||
625 | 622 | {'F', STRFTIME_MASK_MONTH | STRFTIME_MASK_YEAR | STRFTIME_MASK_DAY}, | ||
626 | 623 | {'G', STRFTIME_MASK_YEAR}, | ||
627 | 624 | {'g', STRFTIME_MASK_YEAR}, | ||
628 | 625 | {'h', STRFTIME_MASK_MONTH}, | ||
629 | 626 | {'j', STRFTIME_MASK_DAY}, | ||
630 | 627 | {'m', STRFTIME_MASK_MONTH}, | ||
631 | 628 | {'p', STRFTIME_MASK_AMPM}, | ||
632 | 629 | {'P', STRFTIME_MASK_AMPM}, | ||
633 | 630 | {'r', STRFTIME_MASK_AMPM}, | ||
634 | 631 | {'s', STRFTIME_MASK_SECONDS}, | ||
635 | 632 | {'S', STRFTIME_MASK_SECONDS}, | ||
636 | 633 | {'T', STRFTIME_MASK_SECONDS}, | ||
637 | 634 | {'u', STRFTIME_MASK_WEEK}, | ||
638 | 635 | {'U', STRFTIME_MASK_DAY | STRFTIME_MASK_MONTH}, | ||
639 | 636 | {'V', STRFTIME_MASK_DAY | STRFTIME_MASK_MONTH}, | ||
640 | 637 | {'w', STRFTIME_MASK_DAY}, | ||
641 | 638 | {'W', STRFTIME_MASK_DAY | STRFTIME_MASK_MONTH}, | ||
642 | 639 | {'x', STRFTIME_MASK_YEAR | STRFTIME_MASK_MONTH | STRFTIME_MASK_DAY | STRFTIME_MASK_WEEK}, | ||
643 | 640 | {'X', STRFTIME_MASK_SECONDS}, | ||
644 | 641 | {'y', STRFTIME_MASK_YEAR}, | ||
645 | 642 | {'Y', STRFTIME_MASK_YEAR}, | ||
646 | 643 | /* Last one */ | ||
647 | 644 | {0, 0} | ||
648 | 645 | }; | ||
649 | 646 | |||
650 | 257 | #define FAT_NUMBER 8 | 647 | #define FAT_NUMBER 8 |
651 | 258 | 648 | ||
652 | 649 | /* Looks through the characters in the format string to | ||
653 | 650 | ensure that we can figure out which of the things we | ||
654 | 651 | need to check in determining the length. */ | ||
655 | 652 | static gint | ||
656 | 653 | generate_strftime_bitmask (IndicatorDatetime * self) | ||
657 | 654 | { | ||
658 | 655 | gint retval = 0; | ||
659 | 656 | glong strlength = g_utf8_strlen(self->priv->time_string, -1); | ||
660 | 657 | gint i; | ||
661 | 658 | g_debug("Evaluating bitmask for '%s'", self->priv->time_string); | ||
662 | 659 | |||
663 | 660 | for (i = 0; i < strlength; i++) { | ||
664 | 661 | if (self->priv->time_string[i] == '%' && i + 1 < strlength) { | ||
665 | 662 | gchar evalchar = self->priv->time_string[i + 1]; | ||
666 | 663 | |||
667 | 664 | /* If we're using alternate formats we need to skip those characters */ | ||
668 | 665 | if (evalchar == 'E' || evalchar == 'O') { | ||
669 | 666 | if (i + 2 < strlength) { | ||
670 | 667 | evalchar = self->priv->time_string[i + 2]; | ||
671 | 668 | } else { | ||
672 | 669 | continue; | ||
673 | 670 | } | ||
674 | 671 | } | ||
675 | 672 | |||
676 | 673 | /* Let's look at that character in the table */ | ||
677 | 674 | int j; | ||
678 | 675 | for (j = 0; strftime_type[j].character != 0; j++) { | ||
679 | 676 | if (strftime_type[j].character == evalchar) { | ||
680 | 677 | retval |= strftime_type[j].mask; | ||
681 | 678 | break; | ||
682 | 679 | } | ||
683 | 680 | } | ||
684 | 681 | } | ||
685 | 682 | } | ||
686 | 683 | |||
687 | 684 | return retval; | ||
688 | 685 | } | ||
689 | 686 | |||
690 | 687 | /* Build an array up of all the time values that we want to check | ||
691 | 688 | for length to ensure we're in a good place */ | ||
692 | 689 | static void | ||
693 | 690 | build_timeval_array (GArray * timevals, gint mask) | ||
694 | 691 | { | ||
695 | 692 | struct tm mytm = {0}; | ||
696 | 693 | |||
697 | 694 | /* Sun 12/28/8888 00:00 */ | ||
698 | 695 | mytm.tm_hour = 0; | ||
699 | 696 | mytm.tm_mday = 28; | ||
700 | 697 | mytm.tm_mon = 11; | ||
701 | 698 | mytm.tm_year = 8888 - 1900; | ||
702 | 699 | mytm.tm_wday = 0; | ||
703 | 700 | mytm.tm_yday = 363; | ||
704 | 701 | g_array_append_val(timevals, mytm); | ||
705 | 702 | |||
706 | 703 | if (mask & STRFTIME_MASK_AMPM) { | ||
707 | 704 | /* Sun 12/28/8888 12:00 */ | ||
708 | 705 | mytm.tm_hour = 12; | ||
709 | 706 | g_array_append_val(timevals, mytm); | ||
710 | 707 | } | ||
711 | 708 | |||
712 | 709 | /* NOTE: Ignoring year 8888 should handle it */ | ||
713 | 710 | |||
714 | 711 | if (mask & STRFTIME_MASK_MONTH) { | ||
715 | 712 | gint oldlen = timevals->len; | ||
716 | 713 | gint i, j; | ||
717 | 714 | for (i = 0; i < oldlen; i++) { | ||
718 | 715 | for (j = 0; j < 11; j++) { | ||
719 | 716 | struct tm localval = g_array_index(timevals, struct tm, i); | ||
720 | 717 | localval.tm_mon = j; | ||
721 | 718 | /* Not sure if I need to adjust yday & wday, hope not */ | ||
722 | 719 | g_array_append_val(timevals, localval); | ||
723 | 720 | } | ||
724 | 721 | } | ||
725 | 722 | } | ||
726 | 723 | |||
727 | 724 | /* Doing these together as it seems like just slightly more | ||
728 | 725 | coverage on the numerical days, but worth it. */ | ||
729 | 726 | if (mask & (STRFTIME_MASK_WEEK | STRFTIME_MASK_DAY)) { | ||
730 | 727 | gint oldlen = timevals->len; | ||
731 | 728 | gint i, j; | ||
732 | 729 | for (i = 0; i < oldlen; i++) { | ||
733 | 730 | for (j = 22; j < 28; j++) { | ||
734 | 731 | struct tm localval = g_array_index(timevals, struct tm, i); | ||
735 | 732 | |||
736 | 733 | gint diff = 28 - j; | ||
737 | 734 | |||
738 | 735 | localval.tm_mday = j; | ||
739 | 736 | localval.tm_wday = localval.tm_wday - diff; | ||
740 | 737 | if (localval.tm_wday < 0) { | ||
741 | 738 | localval.tm_wday += 7; | ||
742 | 739 | } | ||
743 | 740 | localval.tm_yday = localval.tm_yday - diff; | ||
744 | 741 | |||
745 | 742 | g_array_append_val(timevals, localval); | ||
746 | 743 | } | ||
747 | 744 | } | ||
748 | 745 | } | ||
749 | 746 | |||
750 | 747 | return; | ||
751 | 748 | } | ||
752 | 749 | |||
753 | 259 | /* Try to get a good guess at what a maximum width of the entire | 750 | /* Try to get a good guess at what a maximum width of the entire |
754 | 260 | string would be. */ | 751 | string would be. */ |
755 | 261 | static void | 752 | static void |
756 | 262 | guess_label_size (IndicatorDatetime * self) | 753 | guess_label_size (IndicatorDatetime * self) |
757 | 263 | { | 754 | { |
758 | 755 | /* This is during startup. */ | ||
759 | 756 | if (self->priv->label == NULL) return; | ||
760 | 757 | |||
761 | 264 | GtkStyle * style = gtk_widget_get_style(GTK_WIDGET(self->priv->label)); | 758 | GtkStyle * style = gtk_widget_get_style(GTK_WIDGET(self->priv->label)); |
762 | 265 | PangoContext * context = gtk_widget_get_pango_context(GTK_WIDGET(self->priv->label)); | 759 | PangoContext * context = gtk_widget_get_pango_context(GTK_WIDGET(self->priv->label)); |
779 | 266 | 760 | gint * max_width = &(self->priv->max_width); | |
780 | 267 | /* TRANSLATORS: This string is used for measuring the size of | 761 | gint posibilitymask = generate_strftime_bitmask(self); |
781 | 268 | the font used for showing the time and is not shown to the | 762 | |
782 | 269 | user anywhere. */ | 763 | /* Build the array of possibilities that we want to test */ |
783 | 270 | gchar * am_str = g_strdup_printf(_("%d%d:%d%d AM"), FAT_NUMBER, FAT_NUMBER, FAT_NUMBER, FAT_NUMBER); | 764 | GArray * timevals = g_array_new(FALSE, TRUE, sizeof(struct tm)); |
784 | 271 | gint am_width = measure_string(style, context, am_str); | 765 | build_timeval_array(timevals, posibilitymask); |
785 | 272 | g_free(am_str); | 766 | |
786 | 273 | 767 | g_debug("Checking against %d posible times", timevals->len); | |
787 | 274 | /* TRANSLATORS: This string is used for measuring the size of | 768 | gint check_time; |
788 | 275 | the font used for showing the time and is not shown to the | 769 | for (check_time = 0; check_time < timevals->len; check_time++) { |
789 | 276 | user anywhere. */ | 770 | gchar longstr[128]; |
790 | 277 | gchar * pm_str = g_strdup_printf(_("%d%d:%d%d PM"), FAT_NUMBER, FAT_NUMBER, FAT_NUMBER, FAT_NUMBER); | 771 | strftime(longstr, 128, self->priv->time_string, &(g_array_index(timevals, struct tm, check_time))); |
791 | 278 | gint pm_width = measure_string(style, context, pm_str); | 772 | |
792 | 279 | g_free(pm_str); | 773 | gchar * utf8 = g_locale_to_utf8(longstr, -1, NULL, NULL, NULL); |
793 | 280 | 774 | gint length = measure_string(style, context, utf8); | |
794 | 281 | self->priv->max_width = MAX(am_width, pm_width); | 775 | g_free(utf8); |
795 | 776 | |||
796 | 777 | if (length > *max_width) { | ||
797 | 778 | *max_width = length; | ||
798 | 779 | } | ||
799 | 780 | } | ||
800 | 781 | |||
801 | 782 | g_array_free(timevals, TRUE); | ||
802 | 783 | |||
803 | 282 | gtk_widget_set_size_request(GTK_WIDGET(self->priv->label), self->priv->max_width, -1); | 784 | gtk_widget_set_size_request(GTK_WIDGET(self->priv->label), self->priv->max_width, -1); |
804 | 283 | |||
805 | 284 | g_debug("Guessing max time width: %d", self->priv->max_width); | 785 | g_debug("Guessing max time width: %d", self->priv->max_width); |
806 | 285 | 786 | ||
807 | 286 | return; | 787 | return; |
808 | @@ -298,6 +799,89 @@ | |||
809 | 298 | return; | 799 | return; |
810 | 299 | } | 800 | } |
811 | 300 | 801 | ||
812 | 802 | /* Tries to figure out what our format string should be. Lots | ||
813 | 803 | of translator comments in here. */ | ||
814 | 804 | static gchar * | ||
815 | 805 | generate_format_string (IndicatorDatetime * self) | ||
816 | 806 | { | ||
817 | 807 | if (self->priv->time_mode == SETTINGS_TIME_CUSTOM) { | ||
818 | 808 | return g_strdup(self->priv->custom_string); | ||
819 | 809 | } | ||
820 | 810 | |||
821 | 811 | gboolean twelvehour = TRUE; | ||
822 | 812 | |||
823 | 813 | if (self->priv->time_mode == SETTINGS_TIME_LOCALE) { | ||
824 | 814 | /* TRANSLATORS: This string is used to determine the default | ||
825 | 815 | clock style for your locale. If it is the string '12' then | ||
826 | 816 | the default will be a 12-hour clock using AM/PM string. If | ||
827 | 817 | it is '24' then it will be a 24-hour clock. Users may over | ||
828 | 818 | ride this setting so it's still important to translate the | ||
829 | 819 | other strings no matter how this is set. */ | ||
830 | 820 | const gchar * locale_default = _("12"); | ||
831 | 821 | |||
832 | 822 | if (g_strcmp0(locale_default, "24") == 0) { | ||
833 | 823 | twelvehour = FALSE; | ||
834 | 824 | } | ||
835 | 825 | } else if (self->priv->time_mode == SETTINGS_TIME_24_HOUR) { | ||
836 | 826 | twelvehour = FALSE; | ||
837 | 827 | } | ||
838 | 828 | |||
839 | 829 | const gchar * time_string = NULL; | ||
840 | 830 | if (twelvehour) { | ||
841 | 831 | if (self->priv->show_seconds) { | ||
842 | 832 | /* TRANSLATORS: A format string for the strftime function for | ||
843 | 833 | a clock showing 12-hour time with seconds. */ | ||
844 | 834 | time_string = _("%l:%M:%S %p"); | ||
845 | 835 | } else { | ||
846 | 836 | /* TRANSLATORS: A format string for the strftime function for | ||
847 | 837 | a clock showing 12-hour time. */ | ||
848 | 838 | time_string = _(DEFAULT_TIME_12_FORMAT); | ||
849 | 839 | } | ||
850 | 840 | } else { | ||
851 | 841 | if (self->priv->show_seconds) { | ||
852 | 842 | /* TRANSLATORS: A format string for the strftime function for | ||
853 | 843 | a clock showing 24-hour time with seconds. */ | ||
854 | 844 | time_string = _("%H:%M:%S"); | ||
855 | 845 | } else { | ||
856 | 846 | /* TRANSLATORS: A format string for the strftime function for | ||
857 | 847 | a clock showing 24-hour time. */ | ||
858 | 848 | time_string = _(DEFAULT_TIME_24_FORMAT); | ||
859 | 849 | } | ||
860 | 850 | } | ||
861 | 851 | |||
862 | 852 | /* Checkpoint, let's not fail */ | ||
863 | 853 | g_return_val_if_fail(time_string != NULL, g_strdup(DEFAULT_TIME_FORMAT)); | ||
864 | 854 | |||
865 | 855 | /* If there's no date or day let's just leave now and | ||
866 | 856 | not worry about the rest of this code */ | ||
867 | 857 | if (!self->priv->show_date && !self->priv->show_day) { | ||
868 | 858 | return g_strdup(time_string); | ||
869 | 859 | } | ||
870 | 860 | |||
871 | 861 | const gchar * date_string = NULL; | ||
872 | 862 | if (self->priv->show_date && self->priv->show_day) { | ||
873 | 863 | /* TRANSLATORS: This is a format string passed to strftime to represent | ||
874 | 864 | the day of the week, the month and the day of the month. */ | ||
875 | 865 | date_string = _("%a %b %e"); | ||
876 | 866 | } else if (self->priv->show_date) { | ||
877 | 867 | /* TRANSLATORS: This is a format string passed to strftime to represent | ||
878 | 868 | the month and the day of the month. */ | ||
879 | 869 | date_string = _("%b %e"); | ||
880 | 870 | } else if (self->priv->show_day) { | ||
881 | 871 | /* TRANSLATORS: This is a format string passed to strftime to represent | ||
882 | 872 | the day of the week. */ | ||
883 | 873 | date_string = _("%a"); | ||
884 | 874 | } | ||
885 | 875 | |||
886 | 876 | /* Check point, we should have a date string */ | ||
887 | 877 | g_return_val_if_fail(date_string != NULL, g_strdup(time_string)); | ||
888 | 878 | |||
889 | 879 | /* TRANSLATORS: This is a format string passed to strftime to combine the | ||
890 | 880 | date and the time. The value of "%s, %s" would result in a string like | ||
891 | 881 | this in US English 12-hour time: 'Fri Jul 16, 11:50 AM' */ | ||
892 | 882 | return g_strdup_printf(_("%s, %s"), date_string, time_string); | ||
893 | 883 | } | ||
894 | 884 | |||
895 | 301 | /* Grabs the label. Creates it if it doesn't | 885 | /* Grabs the label. Creates it if it doesn't |
896 | 302 | exist already */ | 886 | exist already */ |
897 | 303 | static GtkLabel * | 887 | static GtkLabel * |
898 | @@ -316,7 +900,7 @@ | |||
899 | 316 | } | 900 | } |
900 | 317 | 901 | ||
901 | 318 | if (self->priv->timer == 0) { | 902 | if (self->priv->timer == 0) { |
903 | 319 | self->priv->timer = g_timeout_add_seconds(60, minute_timer_func, self); | 903 | setup_timer(self, NULL); |
904 | 320 | } | 904 | } |
905 | 321 | 905 | ||
906 | 322 | return self->priv->label; | 906 | return self->priv->label; |