|
GnuCash 2.4.99
|
00001 /* 00002 * gnc-period-select.c -- Accounting Period selection widget 00003 * 00004 * Copyright (c) 2005 David Hampton <hampton@employees.org> 00005 * All rights reserved. 00006 * 00007 * Gnucash is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Library General Public License 00009 * as published by the Free Software Foundation; either version 2 of the 00010 * License, or (at your option) any later version. 00011 * 00012 * Gnucash is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Library General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, contact: 00019 * 00020 * Free Software Foundation Voice: +1-617-542-5942 00021 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 00022 * Boston, MA 02110-1301, USA gnu@gnu.org 00023 */ 00024 00032 #include "config.h" 00033 00034 #include <gtk/gtk.h> 00035 #include <glib/gi18n.h> 00036 00037 #include "gnc-date.h" 00038 #include "gnc-gconf-utils.h" 00039 #include "gnc-period-select.h" 00040 00041 enum 00042 { 00043 PROP_0, 00044 PROP_FY_END, 00045 PROP_SHOW_DATE, 00046 PROP_DATE_BASE, 00047 }; 00048 00049 enum 00050 { 00051 CHANGED, 00052 LAST_SIGNAL 00053 }; 00054 00055 static guint signals[LAST_SIGNAL] = { 0 }; 00056 00058 static void gnc_period_select_init (GncPeriodSelect *gce); 00059 static void gnc_period_select_class_init (GncPeriodSelectClass *class); 00060 static void gnc_period_select_finalize (GObject *object); 00061 00062 static GtkComboBoxClass *parent_class; 00063 00064 00065 const gchar *start_strings[GNC_ACCOUNTING_PERIOD_LAST] = 00066 { 00067 /* CY Strings */ 00068 N_("Today"), 00069 N_("Start of this month"), 00070 N_("Start of previous month"), 00071 N_("Start of this quarter"), 00072 N_("Start of previous quarter"), 00073 N_("Start of this year"), 00074 N_("Start of previous year"), 00075 00076 /* FY Strings */ 00077 N_("Start of this accounting period"), 00078 N_("Start of previous accounting period"), 00079 }; 00080 00081 const gchar *end_strings[GNC_ACCOUNTING_PERIOD_LAST] = 00082 { 00083 /* CY Strings */ 00084 N_("Today"), 00085 N_("End of this month"), 00086 N_("End of previous month"), 00087 N_("End of this quarter"), 00088 N_("End of previous quarter"), 00089 N_("End of this year"), 00090 N_("End of previous year"), 00091 00092 /* FY Strings */ 00093 N_("End of this accounting period"), 00094 N_("End of previous accounting period"), 00095 }; 00096 00097 00100 typedef struct _GncPeriodSelectPrivate GncPeriodSelectPrivate; 00101 struct _GncPeriodSelectPrivate 00102 { 00103 GtkWidget *selector; 00104 00105 gboolean start; 00106 GDate *fy_end; 00107 00108 GDate *date_base; 00109 GtkWidget *date_label; 00110 GtkWidget *date_align; 00111 }; 00112 00113 #define GNC_PERIOD_SELECT_GET_PRIVATE(o) \ 00114 (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_PERIOD_SELECT, GncPeriodSelectPrivate)) 00115 00116 00117 /************************************************************/ 00118 /* Signal Functions */ 00119 /************************************************************/ 00120 00121 /* Tells a GncPeriodSelect object to emit a "changed" signal. 00122 */ 00123 void 00124 gnc_period_select_changed (GncPeriodSelect *period) 00125 { 00126 g_return_if_fail(GNC_IS_PERIOD_SELECT(period)); 00127 00128 g_signal_emit(G_OBJECT(period), signals[CHANGED], 0); 00129 } 00130 00131 00137 static void 00138 gnc_period_sample_update_date_label (GncPeriodSelect *period) 00139 { 00140 GncPeriodSelectPrivate *priv; 00141 gchar *time_string; 00142 time_t secs; 00143 00144 g_return_if_fail(GNC_IS_PERIOD_SELECT(period)); 00145 priv = GNC_PERIOD_SELECT_GET_PRIVATE(period); 00146 if (!priv->date_label) 00147 return; 00148 secs = gnc_period_select_get_time(GNC_PERIOD_SELECT(period)); 00149 time_string = qof_print_date(secs); 00150 gtk_label_set_label(GTK_LABEL(priv->date_label), time_string); 00151 g_free(time_string); 00152 } 00153 00154 00165 static void 00166 gnc_period_sample_combobox_changed (GtkComboBox *box, GncPeriodSelect *period) 00167 { 00168 g_return_if_fail(GNC_IS_PERIOD_SELECT(period)); 00169 00170 /* Update this widget */ 00171 gnc_period_sample_update_date_label(period); 00172 00173 /* Pass it on... */ 00174 gnc_period_select_changed(period); 00175 } 00176 00177 00188 static void 00189 gnc_period_sample_new_date_format (GConfEntry *unused, 00190 GncPeriodSelect *period) 00191 { 00192 gnc_period_sample_update_date_label(period); 00193 } 00194 00195 00196 /************************************************************/ 00197 /* Property Functions */ 00198 /************************************************************/ 00199 00203 /* Get the current value of the fiscal year end setting from a 00204 * GncPeriodSelect widget. If the result is NULL then fiscal years 00205 * are not currently supported. 00206 */ 00207 GDate * 00208 gnc_period_select_get_fy_end (GncPeriodSelect *period) 00209 { 00210 GncPeriodSelectPrivate *priv; 00211 priv = GNC_PERIOD_SELECT_GET_PRIVATE(period); 00212 00213 g_return_val_if_fail(period != NULL, NULL); 00214 g_return_val_if_fail(GNC_IS_PERIOD_SELECT(period), NULL); 00215 00216 priv = GNC_PERIOD_SELECT_GET_PRIVATE(period); 00217 if (!priv->fy_end) 00218 return NULL; 00219 return g_date_new_dmy(g_date_get_day(priv->fy_end), 00220 g_date_get_month(priv->fy_end), 00221 G_DATE_BAD_YEAR); 00222 } 00223 00224 00225 /* Set the fiscal year end on a GncPeriodSelect widget. If set to a 00226 * value other than NULL then widget will include fiscal accounting 00227 * period like "this fiscal year". 00228 */ 00229 void 00230 gnc_period_select_set_fy_end (GncPeriodSelect *period, const GDate *fy_end) 00231 { 00232 GncPeriodSelectPrivate *priv; 00233 const gchar *label; 00234 gint i; 00235 00236 g_return_if_fail(period != NULL); 00237 g_return_if_fail(GNC_IS_PERIOD_SELECT(period)); 00238 00239 priv = GNC_PERIOD_SELECT_GET_PRIVATE(period); 00240 if (priv->fy_end) 00241 g_date_free(priv->fy_end); 00242 00243 if (fy_end) 00244 { 00245 priv->fy_end = g_date_new_dmy(g_date_get_day(fy_end), 00246 g_date_get_month(fy_end), 00247 G_DATE_BAD_YEAR); 00248 } 00249 else 00250 { 00251 priv->fy_end = NULL; 00252 } 00253 00254 if (fy_end) 00255 { 00256 for (i = GNC_ACCOUNTING_PERIOD_CYEAR_LAST; i < GNC_ACCOUNTING_PERIOD_FYEAR_LAST; i++) 00257 { 00258 label = priv->start ? _(start_strings[i]) : _(end_strings[i]); 00259 gtk_combo_box_append_text(GTK_COMBO_BOX(priv->selector), label); 00260 } 00261 } 00262 else 00263 { 00264 for (i = GNC_ACCOUNTING_PERIOD_FYEAR_LAST - 1; i >= GNC_ACCOUNTING_PERIOD_FYEAR_LAST; i--) 00265 { 00266 gtk_combo_box_remove_text(GTK_COMBO_BOX(priv->selector), i); 00267 } 00268 } 00269 } 00270 00271 00272 static void 00273 gnc_period_select_set_date_common (GncPeriodSelect *period, const GDate *date) 00274 { 00275 GncPeriodSelectPrivate *priv; 00276 00277 priv = GNC_PERIOD_SELECT_GET_PRIVATE(period); 00278 if (date) 00279 { 00280 if (priv->date_base) 00281 g_date_free(priv->date_base); 00282 priv->date_base = g_date_new_dmy(g_date_get_day(date), 00283 g_date_get_month(date), 00284 g_date_get_year(date)); 00285 if (priv->date_label == NULL) 00286 { 00287 priv->date_align = gtk_alignment_new(0.5, 0.5, 0, 0); 00288 gtk_alignment_set_padding(GTK_ALIGNMENT(priv->date_align), 0, 0, 6, 0); 00289 gtk_box_pack_start_defaults(GTK_BOX(period), priv->date_align); 00290 priv->date_label = gtk_label_new(""); 00291 gtk_container_add(GTK_CONTAINER(priv->date_align), priv->date_label); 00292 gtk_widget_show_all(priv->date_align); 00293 } 00294 gnc_period_sample_update_date_label(period); 00295 return; 00296 } 00297 00298 if (priv->date_base) 00299 { 00300 g_date_free(priv->date_base); 00301 priv->date_base = NULL; 00302 gtk_widget_destroy(priv->date_align); 00303 priv->date_align = NULL; 00304 priv->date_label = NULL; 00305 } 00306 } 00307 00308 00309 /* Get the current value of the "show date" setting from a 00310 * GncPeriodSelect widget. 00311 */ 00312 gboolean 00313 gnc_period_select_get_show_date (GncPeriodSelect *period) 00314 { 00315 GncPeriodSelectPrivate *priv; 00316 00317 g_return_val_if_fail(period != NULL, FALSE); 00318 g_return_val_if_fail(GNC_IS_PERIOD_SELECT(period), FALSE); 00319 00320 priv = GNC_PERIOD_SELECT_GET_PRIVATE(period); 00321 return (priv->date_base != NULL); 00322 } 00323 00324 /* Set the "show date" setting on a GncPeriodSelect widget. If set 00325 * to TRUE then a GtkLabel will be used to show the date 00326 * corresponding to the selected time period. 00327 */ 00328 void 00329 gnc_period_select_set_show_date (GncPeriodSelect *period, const gboolean show_date) 00330 { 00331 GDate date; 00332 00333 g_return_if_fail(period != NULL); 00334 g_return_if_fail(GNC_IS_PERIOD_SELECT(period)); 00335 00336 if (show_date) 00337 { 00338 g_date_clear(&date, 1); 00339 g_date_set_time_t(&date, time (NULL)); 00340 gnc_period_select_set_date_common(period, &date); 00341 } 00342 else 00343 { 00344 gnc_period_select_set_date_common(period, NULL); 00345 } 00346 } 00347 00348 00349 GDate * 00350 gnc_period_select_get_date_base (GncPeriodSelect *period) 00351 { 00352 GncPeriodSelectPrivate *priv; 00353 00354 g_return_val_if_fail(period != NULL, NULL); 00355 g_return_val_if_fail(GNC_IS_PERIOD_SELECT(period), NULL); 00356 00357 priv = GNC_PERIOD_SELECT_GET_PRIVATE(period); 00358 if (!priv->date_base) 00359 return NULL; 00360 return g_date_new_dmy(g_date_get_day(priv->date_base), 00361 g_date_get_month(priv->date_base), 00362 g_date_get_year(priv->date_base)); 00363 } 00364 00365 00366 /* Set the base date used by a GncPeriodSelect widget. All example 00367 * dates presented by the widget will be computed from this date. 00368 */ 00369 void 00370 gnc_period_select_set_date_base (GncPeriodSelect *period, const GDate *date_base) 00371 { 00372 g_return_if_fail(period != NULL); 00373 g_return_if_fail(GNC_IS_PERIOD_SELECT(period)); 00374 00375 gnc_period_select_set_date_common(period, date_base); 00376 } 00377 00378 00386 static void 00387 gnc_period_select_get_property (GObject *object, 00388 guint prop_id, 00389 GValue *value, 00390 GParamSpec *pspec) 00391 { 00392 GncPeriodSelect *period = GNC_PERIOD_SELECT(object); 00393 00394 switch (prop_id) 00395 { 00396 case PROP_FY_END: 00397 g_value_set_pointer(value, gnc_period_select_get_fy_end(period)); 00398 break; 00399 case PROP_SHOW_DATE: 00400 g_value_set_boolean(value, gnc_period_select_get_show_date(period)); 00401 break; 00402 case PROP_DATE_BASE: 00403 g_value_set_pointer(value, gnc_period_select_get_date_base(period)); 00404 break; 00405 default: 00406 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); 00407 break; 00408 } 00409 } 00410 00411 00420 static void 00421 gnc_period_select_set_property (GObject *object, 00422 guint prop_id, 00423 const GValue *value, 00424 GParamSpec *pspec) 00425 { 00426 GncPeriodSelect *period = GNC_PERIOD_SELECT(object); 00427 00428 switch (prop_id) 00429 { 00430 case PROP_FY_END: 00431 gnc_period_select_set_fy_end(period, g_value_get_pointer(value)); 00432 break; 00433 case PROP_SHOW_DATE: 00434 gnc_period_select_set_show_date(period, g_value_get_boolean(value)); 00435 break; 00436 case PROP_DATE_BASE: 00437 gnc_period_select_set_date_base(period, g_value_get_pointer(value)); 00438 break; 00439 default: 00440 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); 00441 break; 00442 } 00443 } 00444 00447 /************************************************************/ 00448 /* Core Implementation */ 00449 /************************************************************/ 00450 00454 /* Returns the GType of a GncPeriodSelect widget. 00455 */ 00456 GType 00457 gnc_period_select_get_type (void) 00458 { 00459 static GType period_select_type = 0; 00460 00461 if (period_select_type == 0) 00462 { 00463 static const GTypeInfo period_select_info = 00464 { 00465 sizeof (GncPeriodSelectClass), 00466 NULL, 00467 NULL, 00468 (GClassInitFunc) gnc_period_select_class_init, 00469 NULL, 00470 NULL, 00471 sizeof (GncPeriodSelect), 00472 0, /* n_preallocs */ 00473 (GInstanceInitFunc) gnc_period_select_init, 00474 NULL 00475 }; 00476 00477 period_select_type = g_type_register_static(GTK_TYPE_HBOX, 00478 "GncPeriodSelect", 00479 &period_select_info, 0); 00480 } 00481 00482 return period_select_type; 00483 } 00484 00485 00495 static void 00496 gnc_period_select_class_init (GncPeriodSelectClass *klass) 00497 { 00498 GObjectClass *gobject_class; 00499 00500 parent_class = g_type_class_peek_parent(klass); 00501 00502 gobject_class = G_OBJECT_CLASS(klass); 00503 gobject_class->set_property = gnc_period_select_set_property; 00504 gobject_class->get_property = gnc_period_select_get_property; 00505 gobject_class->finalize = gnc_period_select_finalize; 00506 00507 00508 signals[CHANGED] = g_signal_new("changed", 00509 G_OBJECT_CLASS_TYPE (klass), 00510 G_SIGNAL_RUN_FIRST, 00511 G_STRUCT_OFFSET(GncPeriodSelectClass, changed), 00512 NULL, NULL, 00513 g_cclosure_marshal_VOID__VOID, 00514 G_TYPE_NONE, 00515 0); 00516 00517 00518 g_object_class_install_property(gobject_class, 00519 PROP_FY_END, 00520 g_param_spec_pointer("fy-end", 00521 "Fiscal Year End", 00522 "The fiscal year to use for this widget", 00523 G_PARAM_READWRITE)); 00524 g_object_class_install_property(gobject_class, 00525 PROP_SHOW_DATE, 00526 g_param_spec_boolean("show-date", 00527 "Show Date", 00528 "Show the start/end date of the accouting period in this widget", 00529 FALSE, 00530 G_PARAM_READWRITE)); 00531 g_object_class_install_property(gobject_class, 00532 PROP_DATE_BASE, 00533 g_param_spec_pointer("date-base", 00534 "Date Base", 00535 "The starting date to use for display calculations", 00536 G_PARAM_READWRITE)); 00537 00538 g_type_class_add_private(klass, sizeof(GncPeriodSelectPrivate)); 00539 } 00540 00541 00550 static void 00551 gnc_period_select_init (GncPeriodSelect *period) 00552 { 00553 GncPeriodSelectPrivate *priv; 00554 00555 priv = GNC_PERIOD_SELECT_GET_PRIVATE(period); 00556 priv->start = TRUE; 00557 } 00558 00559 00570 static void 00571 gnc_period_select_finalize (GObject *object) 00572 { 00573 GncPeriodSelectPrivate *priv; 00574 GncPeriodSelect *period; 00575 00576 g_return_if_fail (object != NULL); 00577 g_return_if_fail (GNC_IS_PERIOD_SELECT (object)); 00578 00579 period = GNC_PERIOD_SELECT(object); 00580 priv = GNC_PERIOD_SELECT_GET_PRIVATE(period); 00581 00582 /* Stop tracking changes to date formatting */ 00583 gnc_gconf_general_remove_cb(KEY_DATE_FORMAT, 00584 (GncGconfGeneralCb)gnc_period_sample_new_date_format, period); 00585 00586 /* The selector and date_label were added to the hbox. They will be 00587 * freed automatically. */ 00588 if (priv->fy_end) 00589 g_date_free(priv->fy_end); 00590 if (priv->date_base) 00591 g_date_free(priv->date_base); 00592 00593 /* Do not free the private data structure. It is part of a larger 00594 * memory block allocated by the type system. */ 00595 00596 if (G_OBJECT_CLASS(parent_class)->finalize) 00597 (* G_OBJECT_CLASS(parent_class)->finalize) (object); 00598 } 00599 00600 00601 /* Create a new GncPeriodSelect widget which is used to select a 00602 * accounting period like "previous month" or "this year". 00603 * 00604 * @param starting_labels If set to TRUE then all the labels will 00605 * refer to the "Start of...". If FALSE, labels will refer to "End 00606 * of...". 00607 * 00608 * @return A GncPeriodSelect widget. 00609 */ 00610 GtkWidget * 00611 gnc_period_select_new (gboolean starting_labels) 00612 { 00613 GncPeriodSelectPrivate *priv; 00614 GncPeriodSelect *period; 00615 const gchar *label; 00616 gint i; 00617 00618 period = g_object_new(GNC_TYPE_PERIOD_SELECT, NULL); 00619 00620 /* Set up private data structures */ 00621 priv = GNC_PERIOD_SELECT_GET_PRIVATE(period); 00622 priv->selector = gtk_combo_box_new_text(); 00623 priv->start = starting_labels; 00624 00625 /* Add the internal widgets to the hbox */ 00626 gtk_box_pack_start_defaults(GTK_BOX(period), priv->selector); 00627 gtk_widget_show(priv->selector); 00628 00629 /* Find out when the combo box changes */ 00630 g_signal_connect(G_OBJECT(priv->selector), "changed", 00631 G_CALLBACK(gnc_period_sample_combobox_changed), period); 00632 00633 /* Build all the labels except the fiscal year labels */ 00634 for (i = 0; i < GNC_ACCOUNTING_PERIOD_CYEAR_LAST; i++) 00635 { 00636 label = starting_labels ? _(start_strings[i]) : _(end_strings[i]); 00637 gtk_combo_box_append_text(GTK_COMBO_BOX(priv->selector), label); 00638 } 00639 00640 /* Track changes to date formatting */ 00641 gnc_gconf_general_register_cb(KEY_DATE_FORMAT, 00642 (GncGconfGeneralCb)gnc_period_sample_new_date_format, period); 00643 00644 return GTK_WIDGET (period); 00645 } 00646 00647 00648 /* Create a new GncPeriodSelect widget from a glade file. The int1 00649 * argument passed from glade is used to determine whether the widget 00650 * uses labels for start times or end times. A non-zero int2 00651 * argument indicates that an example date should be shown. 00652 */ 00653 GtkWidget * 00654 gnc_period_select_new_glade (gchar *widget_name, 00655 gchar *string1, gchar *string2, 00656 gint int1, gint int2) 00657 { 00658 GtkWidget *widget; 00659 widget = gnc_period_select_new(int1 != 0); 00660 if (int2) 00661 gnc_period_select_set_show_date(GNC_PERIOD_SELECT(widget), TRUE); 00662 gtk_widget_show(widget); 00663 return widget; 00664 } 00665 00668 /************************************************************/ 00669 /* Auxiliary Functions */ 00670 /************************************************************/ 00671 00672 00673 /* Set which item in the GncPeriodSelect is initially selected. This 00674 * is used to set the initial selection before the widget is shown to 00675 * the user. 00676 */ 00677 void 00678 gnc_period_select_set_active (GncPeriodSelect *period, 00679 GncAccountingPeriod which) 00680 { 00681 GncPeriodSelectPrivate *priv; 00682 00683 g_return_if_fail(period != NULL); 00684 g_return_if_fail(GNC_IS_PERIOD_SELECT(period)); 00685 g_return_if_fail(which >= 0); 00686 g_return_if_fail(which < GNC_ACCOUNTING_PERIOD_LAST); 00687 00688 priv = GNC_PERIOD_SELECT_GET_PRIVATE(period); 00689 gtk_combo_box_set_active(GTK_COMBO_BOX(priv->selector), which); 00690 } 00691 00692 00693 /* Get the currently selected accounting period from a 00694 * GncPeriodSelect widget. This is used to retrieve the user's 00695 * selection in the form of an enum. 00696 */ 00697 GncAccountingPeriod 00698 gnc_period_select_get_active (GncPeriodSelect *period) 00699 { 00700 GncPeriodSelectPrivate *priv; 00701 00702 g_return_val_if_fail(period != NULL, -1); 00703 g_return_val_if_fail(GNC_IS_PERIOD_SELECT(period), -1); 00704 00705 priv = GNC_PERIOD_SELECT_GET_PRIVATE(period); 00706 return gtk_combo_box_get_active(GTK_COMBO_BOX(priv->selector)); 00707 } 00708 00709 00710 /* Get the currently selected accounting period choice from a 00711 * GncPeriodSelect widget. This is used to retrieve the user's 00712 * selection in the form of a GDate. 00713 */ 00714 GDate * 00715 gnc_period_select_get_date (GncPeriodSelect *period) 00716 { 00717 GncPeriodSelectPrivate *priv; 00718 GncAccountingPeriod which; 00719 00720 g_return_val_if_fail(period != NULL, 0); 00721 g_return_val_if_fail(GNC_IS_PERIOD_SELECT(period), 0); 00722 00723 priv = GNC_PERIOD_SELECT_GET_PRIVATE(period); 00724 which = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->selector)); 00725 if (which == -1) 00726 return NULL; 00727 00728 if (priv->start) 00729 return gnc_accounting_period_start_gdate(which, priv->fy_end, 00730 priv->date_base); 00731 return gnc_accounting_period_end_gdate(which, priv->fy_end, 00732 priv->date_base); 00733 } 00734 00735 00736 /* Get the currently selected accounting period from a 00737 * GncPeriodSelect widget. This is used to retrieve the user's 00738 * selection in the form of an timestamp. 00739 */ 00740 time_t 00741 gnc_period_select_get_time (GncPeriodSelect *period) 00742 { 00743 GncPeriodSelectPrivate *priv; 00744 GncAccountingPeriod which; 00745 00746 g_return_val_if_fail(period != NULL, 0); 00747 g_return_val_if_fail(GNC_IS_PERIOD_SELECT(period), 0); 00748 00749 priv = GNC_PERIOD_SELECT_GET_PRIVATE(period); 00750 which = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->selector)); 00751 if (which == -1) 00752 return 0; 00753 00754 if (priv->start) 00755 return gnc_accounting_period_start_timet(which, priv->fy_end, 00756 priv->date_base); 00757 return gnc_accounting_period_end_timet(which, priv->fy_end, 00758 priv->date_base); 00759 } 00760
1.7.4