GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gnc-date-format.c
1 /********************************************************************
2  * gnc-date-format.c -- Date formator widget *
3  * (GnuCash) *
4  * Copyright (C) 2003 Derek Atkins <[email protected]> *
5  * *
6  * This program is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU General Public License as *
8  * published by the Free Software Foundation; either version 2 of *
9  * the License, or (at your option) any later version. *
10  * *
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. *
15  * *
16  * You should have received a copy of the GNU General Public License*
17  * along with this program; if not, contact: *
18  * *
19  * Free Software Foundation Voice: +1-617-542-5942 *
20  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
21  * Boston, MA 02110-1301, USA [email protected] *
22  ********************************************************************/
23 
24 /*
25  @NOTATION@
26 */
27 
28 /*
29  * Date format widget
30  *
31  * Authors: Derek Atkins <[email protected]>
32  */
33 
34 #include "config.h"
35 
36 #include <gtk/gtk.h>
37 #include <string.h>
38 #include <stdio.h>
39 
40 #include "gnc-date-format.h"
41 #include "dialog-utils.h"
42 #include "gnc-engine.h"
43 
44 #ifndef HAVE_LOCALTIME_R
45 # include "localtime_r.h"
46 #endif
47 
48 /* Perhaps it's better just to use MAX_DATE_LENGTH defined in gnc-date.h */
49 #define MAX_DATE_LEN 80
50 
51 /* This static indicates the debugging module that this .o belongs to. */
52 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_GUI;
53 
54 enum
55 {
56  FORMAT_CHANGED,
57  LAST_SIGNAL
58 };
59 
61 
63 {
64  GtkWidget* format_combobox;
65 
66  GtkWidget* label;
67 
68  GtkWidget* months_label;
69  GtkWidget* months_number;
70  GtkWidget* months_abbrev;
71  GtkWidget* months_name;
72 
73  GtkWidget* years_label;
74  GtkWidget* years_button;
75 
76  GtkWidget* custom_label;
77  GtkWidget* custom_entry;
78 
79  GtkWidget* sample_label;
80 };
81 
82 #define GNC_DATE_FORMAT_GET_PRIVATE(o) \
83  (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_DATE_FORMAT, GNCDateFormatPriv))
84 
85 static guint date_format_signals [LAST_SIGNAL] = { 0 };
86 
87 static void gnc_date_format_init (GNCDateFormat *gdf);
88 static void gnc_date_format_class_init (GNCDateFormatClass *klass);
89 static void gnc_date_format_finalize (GObject *object);
90 static void gnc_date_format_compute_format(GNCDateFormat *gdf);
91 
92 void gnc_ui_date_format_changed_cb(GtkWidget *unused, gpointer user_data);
93 
94 static GtkHBoxClass *parent_class;
95 
101 GType
102 gnc_date_format_get_type (void)
103 {
104  static GType date_format_type = 0;
105 
106  if (!date_format_type)
107  {
108  static const GTypeInfo date_format_info =
109  {
110  sizeof (GNCDateFormatClass),
111  NULL,
112  NULL,
113  (GClassInitFunc) gnc_date_format_class_init,
114  NULL,
115  NULL,
116  sizeof (GNCDateFormat),
117  0,
118  (GInstanceInitFunc) gnc_date_format_init,
119  NULL,
120  };
121 
122  date_format_type = g_type_register_static(GTK_TYPE_HBOX,
123  "GNCDateFormat",
124  &date_format_info, 0);
125  }
126 
127  return date_format_type;
128 }
129 
130 
131 static void
132 gnc_date_format_class_init (GNCDateFormatClass *klass)
133 {
134  GObjectClass *gobject_class = (GObjectClass *) klass;
135 
136  parent_class = g_type_class_peek_parent(klass);
137 
138  gobject_class->finalize = gnc_date_format_finalize;
139 
140  g_type_class_add_private(klass, sizeof(GNCDateFormatPriv));
141 
142  date_format_signals [FORMAT_CHANGED] =
143  g_signal_new ("format_changed",
144  G_OBJECT_CLASS_TYPE (gobject_class),
145  G_SIGNAL_RUN_FIRST,
146  G_STRUCT_OFFSET (GNCDateFormatClass, format_changed),
147  NULL,
148  NULL,
149  g_cclosure_marshal_VOID__VOID,
150  G_TYPE_NONE,
151  0);
152 }
153 
154 
155 static void
156 gnc_date_format_init (GNCDateFormat *gdf)
157 {
158  GNCDateFormatPriv *priv;
159  GtkBuilder *builder;
160  GtkWidget *dialog, *table;
161 
162  g_return_if_fail(gdf);
163  g_return_if_fail(GNC_IS_DATE_FORMAT(gdf));
164 
165  /* Open up the Glade and set the signals */
166  builder = gtk_builder_new();
167  gnc_builder_add_from_file (builder, "gnc-date-format.glade", "format-liststore");
168  gnc_builder_add_from_file (builder, "gnc-date-format.glade", "GNC Date Format");
169 
170  gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, gdf);
171 
172  /* pull in all the child widgets */
173  priv = GNC_DATE_FORMAT_GET_PRIVATE(gdf);
174  priv->label = GTK_WIDGET(gtk_builder_get_object (builder, "widget_label"));
175  priv->format_combobox = GTK_WIDGET(gtk_builder_get_object (builder, "format_combobox"));
176 
177  priv->months_label = GTK_WIDGET(gtk_builder_get_object (builder, "months_label"));
178  priv->months_number = GTK_WIDGET(gtk_builder_get_object (builder, "month_number_button"));
179  priv->months_abbrev = GTK_WIDGET(gtk_builder_get_object (builder, "month_abbrev_button"));
180  priv->months_name = GTK_WIDGET(gtk_builder_get_object (builder, "month_name_button"));
181 
182  priv->years_label = GTK_WIDGET(gtk_builder_get_object (builder, "years_label"));
183  priv->years_button = GTK_WIDGET(gtk_builder_get_object (builder, "years_button"));
184 
185  priv->custom_label = GTK_WIDGET(gtk_builder_get_object (builder, "format_label"));
186  priv->custom_entry = GTK_WIDGET(gtk_builder_get_object (builder, "format_entry"));
187 
188  priv->sample_label = GTK_WIDGET(gtk_builder_get_object (builder, "sample_label"));
189 
190  /* Set initial format to gnucash default */
191  gnc_date_format_set_format(gdf, qof_date_format_get());
192 
193  /* pull in the dialog and table widgets and play the reconnect game */
194  dialog = GTK_WIDGET(gtk_builder_get_object (builder, "GNC Date Format"));
195 
196  table = GTK_WIDGET(gtk_builder_get_object (builder, "date_format_table"));
197  g_object_ref(G_OBJECT(table));
198  gtk_container_remove(GTK_CONTAINER(dialog), table);
199  gtk_container_add(GTK_CONTAINER(gdf), table);
200  g_object_unref(G_OBJECT(table));
201 
202  g_object_unref(G_OBJECT(builder));
203 
204  /* Destroy the now empty window */
205  gtk_widget_destroy(dialog);
206 }
207 
208 
209 static void
210 gnc_date_format_finalize (GObject *object)
211 {
212  g_return_if_fail(object != NULL);
213  g_return_if_fail(GNC_IS_DATE_FORMAT(object));
214 
215  if (G_OBJECT_CLASS(parent_class)->finalize)
216  (* G_OBJECT_CLASS(parent_class)->finalize) (object);
217 }
218 
219 
228 GtkWidget *
229 gnc_date_format_new (void)
230 {
231  return gnc_date_format_new_with_label (NULL);
232 }
233 
234 
235 GtkWidget *
236 gnc_date_format_new_without_label (void)
237 {
238  GtkWidget *widget = gnc_date_format_new_with_label(NULL);
239  GNCDateFormat *gdf = GNC_DATE_FORMAT(widget);
240  GNCDateFormatPriv *priv = GNC_DATE_FORMAT_GET_PRIVATE(gdf);
241 
242  gtk_widget_destroy(priv->label);
243  priv->label = NULL;
244 
245  return widget;
246 }
247 
248 
258 GtkWidget *
259 gnc_date_format_new_with_label (const char *label)
260 {
261  GNCDateFormat *gdf;
262  GNCDateFormatPriv *priv;
263 
264  gdf = g_object_new(GNC_TYPE_DATE_FORMAT, NULL);
265  priv = GNC_DATE_FORMAT_GET_PRIVATE(gdf);
266 
267  if (label)
268  gtk_label_set_text(GTK_LABEL(priv->label), label);
269 
270  gnc_date_format_compute_format(gdf);
271  return GTK_WIDGET(gdf);
272 }
273 
274 
275 void
276 gnc_date_format_set_format (GNCDateFormat *gdf, QofDateFormat format)
277 {
278  GNCDateFormatPriv *priv;
279 
280  g_return_if_fail(gdf);
281  g_return_if_fail(GNC_IS_DATE_FORMAT(gdf));
282 
283  priv = GNC_DATE_FORMAT_GET_PRIVATE(gdf);
284  gtk_combo_box_set_active(GTK_COMBO_BOX(priv->format_combobox), format);
285  gnc_date_format_compute_format(gdf);
286 }
287 
288 
290 gnc_date_format_get_format (GNCDateFormat *gdf)
291 {
292  GNCDateFormatPriv *priv;
293 
294  g_return_val_if_fail (gdf, QOF_DATE_FORMAT_LOCALE);
295  g_return_val_if_fail (GNC_IS_DATE_FORMAT(gdf), QOF_DATE_FORMAT_LOCALE);
296 
297  priv = GNC_DATE_FORMAT_GET_PRIVATE(gdf);
298  return gtk_combo_box_get_active(GTK_COMBO_BOX(priv->format_combobox));
299 }
300 
301 
302 void
303 gnc_date_format_set_months (GNCDateFormat *gdf, GNCDateMonthFormat months)
304 {
305  GNCDateFormatPriv *priv;
306  GtkWidget *button = NULL;
307 
308  g_return_if_fail(gdf);
309  g_return_if_fail(GNC_IS_DATE_FORMAT(gdf));
310 
311  priv = GNC_DATE_FORMAT_GET_PRIVATE(gdf);
312  switch (months)
313  {
314  case GNCDATE_MONTH_NUMBER:
315  button = priv->months_number;
316  break;
317  case GNCDATE_MONTH_ABBREV:
318  button = priv->months_abbrev;
319  break;
320  case GNCDATE_MONTH_NAME:
321  button = priv->months_name;
322  break;
323  default:
324  break;
325  }
326 
327  g_return_if_fail(button);
328 
329  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
330  gnc_date_format_compute_format(gdf);
331 }
332 
333 
335 gnc_date_format_get_months (GNCDateFormat *gdf)
336 {
337  GNCDateFormatPriv *priv;
338 
339  g_return_val_if_fail(gdf, GNCDATE_MONTH_NUMBER);
340  g_return_val_if_fail(GNC_IS_DATE_FORMAT(gdf), GNCDATE_MONTH_NUMBER);
341 
342  priv = GNC_DATE_FORMAT_GET_PRIVATE(gdf);
343  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->months_number)))
344  return GNCDATE_MONTH_NUMBER;
345  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->months_abbrev)))
346  return GNCDATE_MONTH_ABBREV;
347  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->months_name)))
348  return GNCDATE_MONTH_ABBREV;
349 
350  /* We should never reach this point */
351  g_assert(FALSE);
352  return GNCDATE_MONTH_NUMBER;
353 }
354 
355 
356 void
357 gnc_date_format_set_years (GNCDateFormat *gdf, gboolean include_century)
358 {
359  GNCDateFormatPriv *priv;
360 
361  g_return_if_fail(gdf);
362  g_return_if_fail(GNC_IS_DATE_FORMAT(gdf));
363 
364  priv = GNC_DATE_FORMAT_GET_PRIVATE(gdf);
365  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->years_button),
366  include_century);
367  gnc_date_format_compute_format(gdf);
368 }
369 
370 
371 gboolean
372 gnc_date_format_get_years (GNCDateFormat *gdf)
373 {
374  GNCDateFormatPriv *priv;
375 
376  g_return_val_if_fail(gdf, FALSE);
377  g_return_val_if_fail(GNC_IS_DATE_FORMAT(gdf), FALSE);
378 
379  priv = GNC_DATE_FORMAT_GET_PRIVATE(gdf);
380  return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->years_button));
381 }
382 
383 
384 void
385 gnc_date_format_set_custom (GNCDateFormat *gdf, const char *format)
386 {
387  GNCDateFormatPriv *priv;
388 
389  g_return_if_fail(gdf);
390  g_return_if_fail(GNC_IS_DATE_FORMAT(gdf));
391 
392  if (format == NULL || *format == '\0')
393  return;
394 
395  priv = GNC_DATE_FORMAT_GET_PRIVATE(gdf);
396  gtk_entry_set_text(GTK_ENTRY(priv->custom_entry), format);
397  gnc_date_format_compute_format(gdf);
398 }
399 
400 
401 const char *
402 gnc_date_format_get_custom (GNCDateFormat *gdf)
403 {
404  GNCDateFormatPriv *priv;
405 
406  g_return_val_if_fail(gdf, "");
407  g_return_val_if_fail(GNC_IS_DATE_FORMAT(gdf), "");
408 
409  priv = GNC_DATE_FORMAT_GET_PRIVATE(gdf);
410  return gtk_entry_get_text(GTK_ENTRY(priv->custom_entry));
411 }
412 
413 
414 void
415 gnc_ui_date_format_changed_cb(GtkWidget *unused, gpointer user_data)
416 {
417  GNCDateFormat * gdf = user_data;
418 
419  gnc_date_format_compute_format(gdf);
420 }
421 
422 
423 static void
424 gnc_date_format_enable_month (GNCDateFormat *gdf, gboolean sensitive)
425 {
426  GNCDateFormatPriv *priv;
427 
428  priv = GNC_DATE_FORMAT_GET_PRIVATE(gdf);
429  gtk_widget_set_sensitive(priv->months_label, sensitive);
430  gtk_widget_set_sensitive(priv->months_number, sensitive);
431  gtk_widget_set_sensitive(priv->months_abbrev, sensitive);
432  gtk_widget_set_sensitive(priv->months_name, sensitive);
433 }
434 
435 
436 static void
437 gnc_date_format_enable_year (GNCDateFormat *gdf, gboolean sensitive)
438 {
439  GNCDateFormatPriv *priv;
440 
441  priv = GNC_DATE_FORMAT_GET_PRIVATE(gdf);
442  gtk_widget_set_sensitive(priv->years_label, sensitive);
443  gtk_widget_set_sensitive(priv->years_button, sensitive);
444 }
445 
446 
447 static void
448 gnc_date_format_enable_format (GNCDateFormat *gdf, gboolean sensitive)
449 {
450  GNCDateFormatPriv *priv;
451 
452  priv = GNC_DATE_FORMAT_GET_PRIVATE(gdf);
453  gtk_widget_set_sensitive(priv->custom_label, sensitive);
454  gtk_widget_set_sensitive(priv->custom_entry, sensitive);
455 }
456 
457 
458 void
459 gnc_date_format_refresh (GNCDateFormat *gdf)
460 {
461  GNCDateFormatPriv *priv;
462  int sel_option;
463  gboolean enable_year, enable_month, enable_custom, check_modifiers;
464  static gchar *format, *c;
465  gchar date_string[MAX_DATE_LEN];
466  time64 secs_now;
467  struct tm today;
468 
469  g_return_if_fail(gdf);
470  g_return_if_fail(GNC_IS_DATE_FORMAT(gdf));
471 
472  priv = GNC_DATE_FORMAT_GET_PRIVATE(gdf);
473  sel_option =
474  gtk_combo_box_get_active(GTK_COMBO_BOX(priv->format_combobox));
475 
476  switch (sel_option)
477  {
479  format = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->custom_entry)));
480  enable_year = enable_month = check_modifiers = FALSE;
481  enable_custom = TRUE;
482  break;
483 
485  case QOF_DATE_FORMAT_UTC:
486  format = g_strdup(qof_date_format_get_string(sel_option));
487  enable_year = enable_month = check_modifiers = enable_custom = FALSE;
488  break;
489 
490  case QOF_DATE_FORMAT_ISO:
491  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->months_number), TRUE);
492  enable_year = check_modifiers = TRUE;
493  enable_month = enable_custom = FALSE;
494  break;
495 
496  default:
497  enable_year = enable_month = check_modifiers = TRUE;
498  enable_custom = FALSE;
499  break;
500  }
501 
502  /* Tweak widget sensitivities, as appropriate. */
503  gnc_date_format_enable_year(gdf, enable_year);
504  gnc_date_format_enable_month(gdf, enable_month);
505  gnc_date_format_enable_format(gdf, enable_custom);
506 
507  /* Update the format string based upon the user's preferences */
508  if (check_modifiers)
509  {
510  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->months_number)))
511  {
512  format = g_strdup(qof_date_format_get_string(sel_option));
513  }
514  else
515  {
516  format = g_strdup(qof_date_text_format_get_string(sel_option));
517  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->months_name)))
518  {
519  c = strchr(format, 'b');
520  if (c)
521  *c = 'B';
522  }
523  }
524  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->years_button)))
525  {
526  c = strchr(format, 'y');
527  if (c)
528  *c = 'Y';
529  }
530  }
531 
532  /*
533  * Give feedback on the format string so users can see how it works
534  * without having to read the strftime man page. Prevent recursive
535  * signals.
536  */
537  g_signal_handlers_block_matched(priv->custom_entry, G_SIGNAL_MATCH_DATA,
538  0, 0, NULL, NULL, gdf);
539  gtk_entry_set_text(GTK_ENTRY(priv->custom_entry), format);
540  g_signal_handlers_unblock_matched(priv->custom_entry, G_SIGNAL_MATCH_DATA,
541  0, 0, NULL, NULL, gdf);
542 
543  /* Visual feedback on what the date will look like. */
544  secs_now = gnc_time (NULL);
545  gnc_localtime_r (&secs_now, &today);
546  qof_strftime(date_string, MAX_DATE_LEN, format, &today);
547  gtk_label_set_text(GTK_LABEL(priv->sample_label), date_string);
548  g_free(format);
549 }
550 
551 
552 static void
553 gnc_date_format_compute_format(GNCDateFormat *gdf)
554 {
555  g_return_if_fail(gdf);
556  g_return_if_fail(GNC_IS_DATE_FORMAT(gdf));
557 
558  /* refresh the widget */
559  gnc_date_format_refresh(gdf);
560 
561  /* Emit a signal that we've changed */
562  g_signal_emit(G_OBJECT(gdf), date_format_signals[FORMAT_CHANGED], 0);
563 }
const gchar * qof_date_text_format_get_string(QofDateFormat df)
struct tm * gnc_localtime_r(const time64 *secs, struct tm *time)
fill out a time struct from a 64-bit time value adjusted for the current time zone.
const gchar * qof_date_format_get_string(QofDateFormat df)
GNCDateMonthFormat
Definition: gnc-date.h:150
gsize qof_strftime(gchar *buf, gsize max, const gchar *format, const struct tm *tm)
All type declarations for the whole Gnucash engine.
QofDateFormat qof_date_format_get(void)
time64 gnc_time(time64 *tbuf)
get the current local time
gint64 time64
Definition: gnc-date.h:83
QofDateFormat
Definition: gnc-date.h:121
const gchar * QofLogModule
Definition: qofid.h:89