GnuCash  5.6-150-g038405b370+
gnc-date-format.c
1 /********************************************************************
2  * gnc-date-format.c -- Date formator widget *
3  * (GnuCash) *
4  * Copyright (C) 2003 Derek Atkins <derek@ihtfp.com> *
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 gnu@gnu.org *
22  ********************************************************************/
23 
24 /*
25  @NOTATION@
26 */
27 
28 /*
29  * Date format widget
30  *
31  * Authors: Derek Atkins <derek@ihtfp.com>
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 /* Perhaps it's better just to use MAX_DATE_LENGTH defined in gnc-date.h */
45 #define MAX_DATE_LEN 80
46 
47 /* This static indicates the debugging module that this .o belongs to. */
48 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_GUI;
49 
50 enum
51 {
52  FORMAT_CHANGED,
53  LAST_SIGNAL
54 };
55 
59 {
60  GtkBox hbox;
61 
62  GtkWidget* format_combobox;
63 
64  GtkWidget* label;
65  GtkWidget* table;
66 
67  GtkWidget* months_label;
68  GtkWidget* months_number;
69  GtkWidget* months_abbrev;
70  GtkWidget* months_name;
71 
72  GtkWidget* years_label;
73  GtkWidget* years_button;
74 
75  GtkWidget* custom_label;
76  GtkWidget* custom_entry;
77 
78  GtkWidget* sample_label;
79 };
80 
81 static guint date_format_signals [LAST_SIGNAL] = { 0 };
82 
83 static void gnc_date_format_finalize (GObject *object);
84 static void gnc_date_format_compute_format(GNCDateFormat *gdf);
85 
86 void gnc_ui_date_format_changed_cb(GtkWidget *unused, gpointer user_data);
87 
88 G_DEFINE_TYPE(GNCDateFormat, gnc_date_format, GTK_TYPE_BOX)
89 
90 static void
91 gnc_date_format_class_init (GNCDateFormatClass *klass)
92 {
93  GObjectClass *gobject_class = (GObjectClass *) klass;
94 
95  gobject_class->finalize = gnc_date_format_finalize;
96 
97  date_format_signals [FORMAT_CHANGED] =
98  g_signal_new ("format_changed",
99  G_OBJECT_CLASS_TYPE (gobject_class),
100  G_SIGNAL_RUN_FIRST,
101  0,
102  NULL,
103  NULL,
104  g_cclosure_marshal_VOID__VOID,
105  G_TYPE_NONE,
106  0);
107 }
108 
109 
110 static void
111 gnc_date_format_init (GNCDateFormat *gdf)
112 {
113  GtkBuilder *builder;
114  GtkWidget *dialog;
115 
116  g_return_if_fail(gdf);
117  g_return_if_fail(GNC_IS_DATE_FORMAT(gdf));
118 
119  gtk_orientable_set_orientation (GTK_ORIENTABLE(gdf), GTK_ORIENTATION_HORIZONTAL);
120 
121  // Set the name for this widget so it can be easily manipulated with css
122  gtk_widget_set_name (GTK_WIDGET(gdf), "gnc-id-date-format");
123 
124  /* Open up the Glade and set the signals */
125  builder = gtk_builder_new();
126  gnc_builder_add_from_file (builder, "gnc-date-format.glade", "format-liststore");
127  gnc_builder_add_from_file (builder, "gnc-date-format.glade", "gnc_date_format_window");
128 
129  gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, gdf);
130 
131  /* pull in all the child widgets */
132  gdf->label = GTK_WIDGET(gtk_builder_get_object (builder, "widget_label"));
133  gdf->format_combobox = GTK_WIDGET(gtk_builder_get_object (builder, "format_combobox"));
134 
135  gdf->months_label = GTK_WIDGET(gtk_builder_get_object (builder, "months_label"));
136  gdf->months_number = GTK_WIDGET(gtk_builder_get_object (builder, "month_number_button"));
137  gdf->months_abbrev = GTK_WIDGET(gtk_builder_get_object (builder, "month_abbrev_button"));
138  gdf->months_name = GTK_WIDGET(gtk_builder_get_object (builder, "month_name_button"));
139 
140  gdf->years_label = GTK_WIDGET(gtk_builder_get_object (builder, "years_label"));
141  gdf->years_button = GTK_WIDGET(gtk_builder_get_object (builder, "years_button"));
142 
143  gdf->custom_label = GTK_WIDGET(gtk_builder_get_object (builder, "format_label"));
144  gdf->custom_entry = GTK_WIDGET(gtk_builder_get_object (builder, "format_entry"));
145 
146  gdf->sample_label = GTK_WIDGET(gtk_builder_get_object (builder, "sample_label"));
147 
148  /* Set initial format to gnucash default */
149  gnc_date_format_set_format(gdf, QOF_DATE_FORMAT_UNSET);
150 
151  /* pull in the dialog and table widgets and play the reconnect game */
152  dialog = GTK_WIDGET(gtk_builder_get_object (builder, "gnc_date_format_window"));
153 
154  gdf->table = GTK_WIDGET(gtk_builder_get_object (builder, "date_format_table"));
155  g_object_ref (G_OBJECT(gdf->table));
156  gtk_container_remove (GTK_CONTAINER(dialog), gdf->table);
157  gtk_container_add (GTK_CONTAINER(gdf), gdf->table);
158  g_object_unref (G_OBJECT(gdf->table));
159 
160  g_object_unref(G_OBJECT(builder));
161 
162  /* Destroy the now empty window */
163  gtk_widget_destroy(dialog);
164 }
165 
166 
167 static void
168 gnc_date_format_finalize (GObject *object)
169 {
170  g_return_if_fail(object != NULL);
171  g_return_if_fail(GNC_IS_DATE_FORMAT(object));
172 
173  G_OBJECT_CLASS(gnc_date_format_parent_class)->finalize (object);
174 }
175 
176 
185 GtkWidget *
186 gnc_date_format_new (void)
187 {
188  return gnc_date_format_new_with_label (NULL);
189 }
190 
191 
192 GtkWidget *
193 gnc_date_format_new_without_label (void)
194 {
195  GtkWidget *widget = gnc_date_format_new_with_label(NULL);
196  GNCDateFormat *gdf = GNC_DATE_FORMAT(widget);
197 
198  // remove the first column which has the label
199  gtk_grid_remove_column (GTK_GRID(gdf->table), 0);
200  gdf->label = NULL;
201  return widget;
202 }
203 
204 
214 GtkWidget *
215 gnc_date_format_new_with_label (const char *label)
216 {
217  GNCDateFormat *gdf;
218 
219  gdf = g_object_new(GNC_TYPE_DATE_FORMAT, NULL);
220 
221  if (label)
222  gtk_label_set_text(GTK_LABEL(gdf->label), label);
223 
224  gnc_date_format_compute_format(gdf);
225  return GTK_WIDGET(gdf);
226 }
227 
228 
229 void
230 gnc_date_format_set_format (GNCDateFormat *gdf, QofDateFormat format)
231 {
232  g_return_if_fail(gdf);
233  g_return_if_fail(GNC_IS_DATE_FORMAT(gdf));
234 
235  gtk_combo_box_set_active(GTK_COMBO_BOX(gdf->format_combobox), format);
236  gnc_date_format_compute_format(gdf);
237 }
238 
239 
241 gnc_date_format_get_format (GNCDateFormat *gdf)
242 {
243  g_return_val_if_fail (gdf, QOF_DATE_FORMAT_LOCALE);
244  g_return_val_if_fail (GNC_IS_DATE_FORMAT(gdf), QOF_DATE_FORMAT_LOCALE);
245 
246  return gtk_combo_box_get_active(GTK_COMBO_BOX(gdf->format_combobox));
247 }
248 
249 
250 void
251 gnc_date_format_set_months (GNCDateFormat *gdf, GNCDateMonthFormat months)
252 {
253  GtkWidget *button = NULL;
254 
255  g_return_if_fail(gdf);
256  g_return_if_fail(GNC_IS_DATE_FORMAT(gdf));
257 
258  switch (months)
259  {
260  case GNCDATE_MONTH_NUMBER:
261  button = gdf->months_number;
262  break;
263  case GNCDATE_MONTH_ABBREV:
264  button = gdf->months_abbrev;
265  break;
266  case GNCDATE_MONTH_NAME:
267  button = gdf->months_name;
268  break;
269  default:
270  break;
271  }
272 
273  g_return_if_fail(button);
274 
275  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
276  gnc_date_format_compute_format(gdf);
277 }
278 
279 
281 gnc_date_format_get_months (GNCDateFormat *gdf)
282 {
283  g_return_val_if_fail(gdf, GNCDATE_MONTH_NUMBER);
284  g_return_val_if_fail(GNC_IS_DATE_FORMAT(gdf), GNCDATE_MONTH_NUMBER);
285 
286  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gdf->months_number)))
287  return GNCDATE_MONTH_NUMBER;
288  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gdf->months_abbrev)))
289  return GNCDATE_MONTH_ABBREV;
290  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gdf->months_name)))
291  return GNCDATE_MONTH_NAME;
292 
293  /* We should never reach this point */
294  g_assert(FALSE);
295  return GNCDATE_MONTH_NUMBER;
296 }
297 
298 
299 void
300 gnc_date_format_set_years (GNCDateFormat *gdf, gboolean include_century)
301 {
302  g_return_if_fail(gdf);
303  g_return_if_fail(GNC_IS_DATE_FORMAT(gdf));
304 
305  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gdf->years_button),
306  include_century);
307  gnc_date_format_compute_format(gdf);
308 }
309 
310 
311 gboolean
312 gnc_date_format_get_years (GNCDateFormat *gdf)
313 {
314  g_return_val_if_fail(gdf, FALSE);
315  g_return_val_if_fail(GNC_IS_DATE_FORMAT(gdf), FALSE);
316 
317  return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gdf->years_button));
318 }
319 
320 
321 void
322 gnc_date_format_set_custom (GNCDateFormat *gdf, const char *format)
323 {
324  g_return_if_fail(gdf);
325  g_return_if_fail(GNC_IS_DATE_FORMAT(gdf));
326 
327  if (format == NULL || *format == '\0')
328  return;
329 
330  gtk_entry_set_text(GTK_ENTRY(gdf->custom_entry), format);
331  gnc_date_format_compute_format(gdf);
332 }
333 
334 
335 const char *
336 gnc_date_format_get_custom (GNCDateFormat *gdf)
337 {
338  g_return_val_if_fail(gdf, "");
339  g_return_val_if_fail(GNC_IS_DATE_FORMAT(gdf), "");
340 
341  return gtk_entry_get_text(GTK_ENTRY(gdf->custom_entry));
342 }
343 
344 
345 void
346 gnc_ui_date_format_changed_cb(GtkWidget *unused, gpointer user_data)
347 {
348  GNCDateFormat * gdf = user_data;
349 
350  gnc_date_format_compute_format(gdf);
351 }
352 
353 
354 static void
355 gnc_date_format_enable_month (GNCDateFormat *gdf, gboolean sensitive)
356 {
357  gtk_widget_set_sensitive(gdf->months_label, sensitive);
358  gtk_widget_set_sensitive(gdf->months_number, sensitive);
359  gtk_widget_set_sensitive(gdf->months_abbrev, sensitive);
360  gtk_widget_set_sensitive(gdf->months_name, sensitive);
361 }
362 
363 
364 static void
365 gnc_date_format_enable_year (GNCDateFormat *gdf, gboolean sensitive)
366 {
367  gtk_widget_set_sensitive(gdf->years_label, sensitive);
368  gtk_widget_set_sensitive(gdf->years_button, sensitive);
369 }
370 
371 
372 static void
373 gnc_date_format_enable_format (GNCDateFormat *gdf, gboolean sensitive)
374 {
375  gtk_widget_set_sensitive(gdf->custom_label, sensitive);
376  gtk_widget_set_sensitive(gdf->custom_entry, sensitive);
377 }
378 
379 
380 void
381 gnc_date_format_refresh (GNCDateFormat *gdf)
382 {
383  int sel_option;
384  gboolean enable_year, enable_month, enable_custom, check_modifiers;
385  static gchar *format, *c;
386  gchar date_string[MAX_DATE_LEN];
387  time64 secs_now;
388  struct tm today;
389 
390  g_return_if_fail(gdf);
391  g_return_if_fail(GNC_IS_DATE_FORMAT(gdf));
392 
393  sel_option =
394  gtk_combo_box_get_active(GTK_COMBO_BOX(gdf->format_combobox));
395 
396  switch (sel_option)
397  {
399  format = g_strdup(gtk_entry_get_text(GTK_ENTRY(gdf->custom_entry)));
400  enable_year = enable_month = check_modifiers = FALSE;
401  enable_custom = TRUE;
402  break;
403 
406  case QOF_DATE_FORMAT_UTC:
407  format = g_strdup(qof_date_format_get_string(sel_option));
408  enable_year = enable_month = check_modifiers = enable_custom = FALSE;
409  break;
410 
411  case QOF_DATE_FORMAT_ISO:
412  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gdf->months_number), TRUE);
413  enable_year = check_modifiers = TRUE;
414  enable_month = enable_custom = FALSE;
415  break;
416 
417  default:
418  enable_year = enable_month = check_modifiers = TRUE;
419  enable_custom = FALSE;
420  break;
421  }
422 
423  /* Tweak widget sensitivities, as appropriate. */
424  gnc_date_format_enable_year(gdf, enable_year);
425  gnc_date_format_enable_month(gdf, enable_month);
426  gnc_date_format_enable_format(gdf, enable_custom);
427 
428  /* Update the format string based upon the user's preferences */
429  if (check_modifiers)
430  {
431  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gdf->months_number)))
432  {
433  format = g_strdup(qof_date_format_get_string(sel_option));
434  }
435  else
436  {
437  format = g_strdup(qof_date_text_format_get_string(sel_option));
438  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gdf->months_name)))
439  {
440  c = strchr(format, 'b');
441  if (c)
442  *c = 'B';
443  }
444  }
445  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gdf->years_button)))
446  {
447  c = strchr(format, 'y');
448  if (c)
449  *c = 'Y';
450  }
451  }
452 
453  /*
454  * Give feedback on the format string so users can see how it works
455  * without having to read the strftime man page. Prevent recursive
456  * signals.
457  */
458  g_signal_handlers_block_matched(gdf->custom_entry, G_SIGNAL_MATCH_DATA,
459  0, 0, NULL, NULL, gdf);
460  gtk_entry_set_text(GTK_ENTRY(gdf->custom_entry), format);
461  g_signal_handlers_unblock_matched(gdf->custom_entry, G_SIGNAL_MATCH_DATA,
462  0, 0, NULL, NULL, gdf);
463 
464  /* Visual feedback on what the date will look like. */
465  secs_now = gnc_time (NULL);
466  gnc_localtime_r (&secs_now, &today);
467  qof_strftime(date_string, MAX_DATE_LEN, format, &today);
468  gtk_label_set_text(GTK_LABEL(gdf->sample_label), date_string);
469  g_free(format);
470 }
471 
472 
473 static void
474 gnc_date_format_compute_format(GNCDateFormat *gdf)
475 {
476  g_return_if_fail(gdf);
477  g_return_if_fail(GNC_IS_DATE_FORMAT(gdf));
478 
479  /* refresh the widget */
480  gnc_date_format_refresh(gdf);
481 
482  /* Emit a signal that we've changed */
483  g_signal_emit(G_OBJECT(gdf), date_format_signals[FORMAT_CHANGED], 0);
484 }
ISO: yyyy-mm-dd.
Definition: gnc-date.h:127
gsize qof_strftime(gchar *buf, gsize max, const gchar *format, const struct tm *tm)
qof_strftime calls qof_format_time to print a given time and afterwards tries to put the result into ...
Definition: gnc-date.cpp:1056
Used by the check printing code.
Definition: gnc-date.h:130
No Fancy Date Format, use Global.
Definition: gnc-date.h:131
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.
Definition: gnc-date.cpp:114
UTC: 2004-12-12T23:39:11Z.
Definition: gnc-date.h:129
GNCDateMonthFormat
This is how to format the month, as a number, an abbreviated string, or the full name.
Definition: gnc-date.h:148
All type declarations for the whole Gnucash engine.
const gchar * qof_date_text_format_get_string(QofDateFormat df)
This function returns a strftime formatting string for printing a date using words and numbers (e...
Definition: gnc-date.cpp:524
time64 gnc_time(time64 *tbuf)
get the current time
Definition: gnc-date.cpp:261
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition: gnc-date.h:87
Take from locale information.
Definition: gnc-date.h:128
const gchar * qof_date_format_get_string(QofDateFormat df)
This function returns a strftime formatting string for printing an all numeric date (e...
Definition: gnc-date.cpp:501
QofDateFormat
Enum for determining a date format.
Definition: gnc-date.h:122