[Gnucash-changes] Add a selection widget and non-gui supporting
functions for choosing
David Hampton
hampton at cvs.gnucash.org
Sun Oct 2 15:59:34 EDT 2005
Log Message:
-----------
Add a selection widget and non-gui supporting functions for choosing
accounting periods.
Tags:
----
gnucash-gnome2-dev
Modified Files:
--------------
gnucash/src/app-utils:
Makefile.am
gnucash/src/gnome-utils:
Makefile.am
Added Files:
-----------
gnucash/src/app-utils:
gnc-accounting-period.c
gnc-accounting-period.h
gnucash/src/gnome-utils:
gnc-period-select.c
gnc-period-select.h
Revision Data
-------------
Index: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/app-utils/Makefile.am,v
retrieving revision 1.29.4.11
retrieving revision 1.29.4.12
diff -Lsrc/app-utils/Makefile.am -Lsrc/app-utils/Makefile.am -u -r1.29.4.11 -r1.29.4.12
--- src/app-utils/Makefile.am
+++ src/app-utils/Makefile.am
@@ -18,6 +18,7 @@
file-utils.c \
gfec.c \
global-options.c \
+ gnc-accounting-period.c \
gnc-component-manager.c \
gnc-druid.c \
gnc-druid-cb.c \
@@ -43,6 +44,7 @@
gfec.h \
global-options.h \
gnc-basic-gobject.h \
+ gnc-accounting-period.h \
gnc-component-manager.h \
gnc-druid.h \
gnc-druid-cb.h \
--- /dev/null
+++ src/app-utils/gnc-accounting-period.h
@@ -0,0 +1,172 @@
+/*
+ * gnc-accounting-period.h --
+ *
+ * Copyright (c) 2005 David Hampton <hampton at employees.org>
+ * All rights reserved.
+ *
+ * GnuCash is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Gnucash is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652
+ * Boston, MA 02111-1307, USA gnu at gnu.org
+ */
+
+/** @addtogroup GUI
+ @{ */
+/** @file gnc-accounting-period.h
+ @brief General utilities for dealing with accounting periods.
+ @author David Hampton <hampton at employees.org>
+
+ These are general utility functions for specifying an accounting
+ period and converting it to a value usable by the gnucash engine.
+ The choice of src/app-utils is arbitrary as these utilities don't
+ fit well anywhere else. They are at a higher level than a GDate,
+ so they don't fit in src/core-utils/gnc-gdate-utils.c. They don't
+ operate on engine data structures, so they don't belong in
+ src/engine/Period.c. Putting them into src/engine/gnc-date.c
+ would be the best place for them, but then that creates a new
+ dependancy from the src/engine directory to the src/core-utils
+ directory that doesn't currently exist. Since that might be a
+ problem for CashUtils, the app-file directory was chosen.
+*/
+
+#ifndef GNC_ACCOUNTING_PERIOD_H
+#define GNC_ACCOUNTING_PERIOD_H
+
+#include <glib.h>
+#include <time.h>
+
+/**
+ * This specifies a time interval.
+ */
+typedef enum {
+ GNC_ACCOUNTING_PERIOD_TODAY,
+ GNC_ACCOUNTING_PERIOD_MONTH,
+ GNC_ACCOUNTING_PERIOD_MONTH_PREV,
+ GNC_ACCOUNTING_PERIOD_QUARTER,
+ GNC_ACCOUNTING_PERIOD_QUARTER_PREV,
+ GNC_ACCOUNTING_PERIOD_CYEAR,
+ GNC_ACCOUNTING_PERIOD_CYEAR_PREV,
+ GNC_ACCOUNTING_PERIOD_CYEAR_LAST,
+
+ GNC_ACCOUNTING_PERIOD_FYEAR = GNC_ACCOUNTING_PERIOD_CYEAR_LAST,
+ GNC_ACCOUNTING_PERIOD_FYEAR_PREV,
+ GNC_ACCOUNTING_PERIOD_FYEAR_LAST,
+ GNC_ACCOUNTING_PERIOD_LAST = GNC_ACCOUNTING_PERIOD_FYEAR_LAST,
+} GncAccountingPeriod;
+
+
+/** \name Accounting Periods */
+/** @{ */
+
+/** This function returns the starting date for an accounting period.
+ * The date will be computed based upon the type of accounting
+ * interval requested, an optional fiscal year end value, and an
+ * optional time value.
+ *
+ * @param which An enum specifying the type of accounting period.
+ *
+ * @param fy_end This argument specifies the month and day of the
+ * fiscal year end. If the accounting period specified in the
+ * 'which' parameter is not a fiscal accounting period, this variable
+ * is ignored and may be NULL. Note: the year field of this argument
+ * is always ignored.
+ *
+ * @param contains This argument specifies the origin time value used
+ * by the calculations in this function. If this value is NULL, the
+ * origin will be the current time.
+ *
+ * @return The starting day of the specified time interval, as a
+ * GDate. */
+GDate *gnc_accounting_period_start_gdate (GncAccountingPeriod which,
+ const GDate *fy_end,
+ const GDate *contains);
+
+
+/** This function returns the starting time for an accounting period.
+ * The time will be computed based upon the type of accounting
+ * interval requested, an optional fiscal year end value, and an
+ * optional time value.
+ *
+ * @param which An enum specifying the type of accounting period.
+ *
+ * @param fy_end This argument specifies the month and day of the
+ * fiscal year end. If the accounting period specified in the
+ * 'which' parameter is not a fiscal accounting period, this variable
+ * is ignored and may be NULL. Note: the year field of this argument
+ * is always ignored.
+ *
+ * @param contains This argument specifies the origin time value used
+ * by the calculations in this function. If this value is NULL, the
+ * origin will be the current time.
+ *
+ * @return The starting second of the specified time interval, based
+ * on a zero value of January 1st, 1970. */
+time_t gnc_accounting_period_start_timet (GncAccountingPeriod which,
+ const GDate *fy_end,
+ const GDate *contains);
+
+
+/** This function returns the ending date for an accounting period.
+ * The date will be computed based upon the type of accounting
+ * interval requested, an optional fiscal year end value, and an
+ * optional time value.
+ *
+ * @param which An enum specifying the type of accounting period.
+ *
+ * @param fy_end This argument specifies the month and day of the
+ * fiscal year end. If the accounting period specified in the
+ * 'which' parameter is not a fiscal accounting period, this variable
+ * is ignored and may be NULL. Note: the year field of this argument
+ * is always ignored.
+ *
+ * @param contains This argument specifies the origin time value used
+ * by the calculations in this function. If this value is NULL, the
+ * origin will be the current time.
+ *
+ * @return The final day of the specified time interval, as a
+ * GDate. */
+GDate *gnc_accounting_period_end_gdate (GncAccountingPeriod which,
+ const GDate *fy_end,
+ const GDate *contains);
+
+
+/** This function returns the ending time for an accounting period.
+ * The time will be computed based upon the type of accounting
+ * interval requested, an optional fiscal year end value, and an
+ * optional time value.
+ *
+ * @param which An enum specifying the type of accounting period.
+ *
+ * @param fy_end This argument specifies the month and day of the
+ * fiscal year end. If the accounting period specified in the
+ * 'which' parameter is not a fiscal accounting period, this variable
+ * is ignored and may be NULL. Note: the year field of this argument
+ * is always ignored.
+ *
+ * @param contains This argument specifies the origin time value used
+ * by the calculations in this function. If this value is NULL, the
+ * origin will be the current time.
+ *
+ * @return The ending second of the specified time interval, based
+ * on a zero value of January 1st, 1970. */
+time_t gnc_accounting_period_end_timet (GncAccountingPeriod which,
+ const GDate *fy_end,
+ const GDate *contains);
+/** @} */
+
+#endif /* GNC_ACCOUNTING_PERIOD_H */
+
+/** @} */
+
--- /dev/null
+++ src/app-utils/gnc-accounting-period.c
@@ -0,0 +1,226 @@
+/*
+ * gnc-accounting-period.c --
+ *
+ * Copyright (c) 2005 David Hampton <hampton at employees.org>
+ * All rights reserved.
+ *
+ * GnuCash is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Gnucash is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652
+ * Boston, MA 02111-1307, USA gnu at gnu.org
+ */
+
+/** @addtogroup GUI
+ @{ */
+/** @file gnc-accounting-period.c
+ @brief General utilities for dealing with accounting periods.
+ @author David Hampton <hampton at employees.org>
+
+ These are general utility functions for specifying an accounting
+ period and converting it to a value usable by the gnucash engine.
+ The choice of src/app-utils is arbitrary as these utilities don't
+ fit well anywhere else. They are at a higher level than a GDate,
+ so they don't fit in src/core-utils/gnc-gdate-utils.c. They don't
+ operate on engine data structures, so they don't belong in
+ src/engine/Period.c. Putting them into src/engine/gnc-date.c
+ would be the best place for them, but then that creates a new
+ dependancy from the src/engine directory to the src/core-utils
+ directory that doesn't currently exist. Since that might be a
+ problem for CashUtils, the app-file directory was chosen.
+*/
+
+#include "config.h"
+#include "gnc-accounting-period.h"
+#include "gnc-gdate-utils.h"
+
+GDate *
+gnc_accounting_period_start_gdate (GncAccountingPeriod which,
+ const GDate *fy_end,
+ const GDate *contains)
+{
+ GDate *date;
+
+ if (contains) {
+ date = g_date_new_dmy(g_date_get_day(contains),
+ g_date_get_month(contains),
+ g_date_get_year(contains));
+ } else {
+ date = g_date_new();
+ g_date_set_time(date, time(NULL));
+ }
+
+ switch (which) {
+ default:
+ g_message("Undefined relative time constant %d", which);
+ g_date_free(date);
+ return NULL;
+
+ case GNC_ACCOUNTING_PERIOD_TODAY:
+ /* Already have today's date */
+ break;
+
+ case GNC_ACCOUNTING_PERIOD_MONTH:
+ gnc_gdate_set_month_start(date);
+ break;
+
+ case GNC_ACCOUNTING_PERIOD_MONTH_PREV:
+ gnc_gdate_set_prev_month_start(date);
+ break;
+
+ case GNC_ACCOUNTING_PERIOD_QUARTER:
+ gnc_gdate_set_quarter_start(date);
+ break;
+
+ case GNC_ACCOUNTING_PERIOD_QUARTER_PREV:
+ gnc_gdate_set_prev_quarter_start(date);
+ break;
+
+ case GNC_ACCOUNTING_PERIOD_CYEAR:
+ gnc_gdate_set_year_start(date);
+ break;
+
+ case GNC_ACCOUNTING_PERIOD_CYEAR_PREV:
+ gnc_gdate_set_prev_year_start(date);
+ break;
+
+ case GNC_ACCOUNTING_PERIOD_FYEAR:
+ if (fy_end == NULL) {
+ g_message("Request for fisal year value but no fiscal year end value provided.");
+ g_date_free(date);
+ return NULL;
+ }
+ gnc_gdate_set_fiscal_year_start(date, fy_end);
+ break;
+
+ case GNC_ACCOUNTING_PERIOD_FYEAR_PREV:
+ if (fy_end == NULL) {
+ g_message("Request for fisal year value but no fiscal year end value provided.");
+ g_date_free(date);
+ return NULL;
+ }
+ gnc_gdate_set_prev_fiscal_year_start(date, fy_end);
+ break;
+ }
+ return date;
+}
+
+time_t
+gnc_accounting_period_start_timet (GncAccountingPeriod which,
+ const GDate *fy_end,
+ const GDate *contains)
+{
+ GDate *date;
+ time_t secs;
+
+ date = gnc_accounting_period_start_gdate(which, fy_end, contains);
+ if (!date)
+ return 0;
+
+ secs = gnc_timet_get_day_start_gdate(date);
+ g_date_free(date);
+ return secs;
+}
+
+GDate *
+gnc_accounting_period_end_gdate (GncAccountingPeriod which,
+ const GDate *fy_end,
+ const GDate *contains)
+{
+ GDate *date;
+
+ if (contains) {
+ date = g_date_new_dmy(g_date_get_day(contains),
+ g_date_get_month(contains),
+ g_date_get_year(contains));
+ } else {
+ date = g_date_new();
+ g_date_set_time(date, time(NULL));
+ }
+
+ switch (which) {
+ default:
+ g_message("Undefined relative time constant %d", which);
+ g_date_free(date);
+ return 0;
+
+ case GNC_ACCOUNTING_PERIOD_TODAY:
+ /* Already have today's date */
+ break;
+
+ case GNC_ACCOUNTING_PERIOD_MONTH:
+ gnc_gdate_set_month_end(date);
+ break;
+
+ case GNC_ACCOUNTING_PERIOD_MONTH_PREV:
+ gnc_gdate_set_prev_month_end(date);
+ break;
+
+ case GNC_ACCOUNTING_PERIOD_QUARTER:
+ gnc_gdate_set_quarter_end(date);
+ break;
+
+ case GNC_ACCOUNTING_PERIOD_QUARTER_PREV:
+ gnc_gdate_set_prev_quarter_end(date);
+ break;
+
+ case GNC_ACCOUNTING_PERIOD_CYEAR:
+ gnc_gdate_set_year_end(date);
+ break;
+
+ case GNC_ACCOUNTING_PERIOD_CYEAR_PREV:
+ gnc_gdate_set_prev_year_end(date);
+ break;
+
+ case GNC_ACCOUNTING_PERIOD_FYEAR:
+ if (fy_end == NULL) {
+ g_message("Request for fisal year value but no fiscal year end value provided.");
+ g_date_free(date);
+ return 0;
+ }
+ gnc_gdate_set_fiscal_year_end(date, fy_end);
+ break;
+
+ case GNC_ACCOUNTING_PERIOD_FYEAR_PREV:
+ if (fy_end == NULL) {
+ g_message("Request for fisal year value but no fiscal year end value provided.");
+ g_date_free(date);
+ return 0;
+ }
+ gnc_gdate_set_prev_fiscal_year_end(date, fy_end);
+ break;
+ }
+
+ return date;
+}
+
+time_t
+gnc_accounting_period_end_timet (GncAccountingPeriod which,
+ const GDate *fy_end,
+ const GDate *contains)
+{
+ GDate *date;
+ time_t secs;
+
+ date = gnc_accounting_period_end_gdate(which, fy_end, contains);
+ if (!date)
+ return 0;
+
+ secs = gnc_timet_get_day_end_gdate(date);
+ g_date_free(date);
+ return secs ;
+}
+
+
+/** @} */
Index: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome-utils/Makefile.am,v
retrieving revision 1.48.2.38
retrieving revision 1.48.2.39
diff -Lsrc/gnome-utils/Makefile.am -Lsrc/gnome-utils/Makefile.am -u -r1.48.2.38 -r1.48.2.39
--- src/gnome-utils/Makefile.am
+++ src/gnome-utils/Makefile.am
@@ -77,6 +77,7 @@
gnc-plugin-menu-additions.c \
gnc-plugin-page.c \
gnc-plugin.c \
+ gnc-period-select.c \
gnc-query-list.c \
gnc-splash.c \
gnc-tree-model.c \
@@ -139,6 +140,7 @@
gnc-plugin-menu-additions.h \
gnc-plugin-page.h \
gnc-plugin.h \
+ gnc-period-select.h \
gnc-query-list.h \
gnc-splash.h \
gnc-tree-model.h \
--- /dev/null
+++ src/gnome-utils/gnc-period-select.h
@@ -0,0 +1,199 @@
+/*
+ * gnc-period-select.h -- Accounting period selection widget
+ *
+ * Copyright (c) 2005 David Hampton <hampton at employees.org>
+ * All rights reserved.
+ *
+ * GnuCash is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Gnucash is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652
+ * Boston, MA 02111-1307, USA gnu at gnu.org
+ */
+
+/** @addtogroup GUI
+ @{ */
+/** @file gnc-period-select.h
+ @brief A custom widget for selecting accounting periods.
+ @author David Hampton <hampton at employees.org>
+*/
+
+#ifndef GNC_PERIOD_SELECT_H
+#define GNC_PERIOD_SELECT_H
+
+#include <gtk/gtk.h>
+#include "gnc-accounting-period.h"
+
+G_BEGIN_DECLS
+
+#define GNC_TYPE_PERIOD_SELECT (gnc_period_select_get_type())
+#define GNC_PERIOD_SELECT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GNC_TYPE_PERIOD_SELECT, GncPeriodSelect))
+#define GNC_PERIOD_SELECT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GNC_TYPE_PERIOD_SELECT, GncPeriodSelectClass))
+#define GNC_IS_PERIOD_SELECT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_PERIOD_SELECT))
+
+/* typedefs & structures */
+typedef struct {
+ GtkHBox hbox;
+} GncPeriodSelect;
+
+typedef struct {
+ GtkHBoxClass hbox;
+
+ /* Signals */
+ void (*changed) (GncPeriodSelect *period);
+
+} GncPeriodSelectClass;
+
+
+/** @name GncPeriodSelect Widget Implementation
+ @{ */
+
+/** Returns the GType of a GncPeriodSelect widget.
+ */
+GType gnc_period_select_get_type (void);
+
+
+/** Tells a GncPeriodSelect object to emit a "changed" signal.
+ *
+ * @param period The GncPeriodSelect object that should emit the
+ * signal.
+ */
+void gnc_period_select_changed (GncPeriodSelect *period);
+
+
+/** Create a new GncPeriodSelect widget which is used to select a
+ * accounting period like "previous month" or "this year".
+ *
+ * @param starting_labels If set to TRUE then all the labels will
+ * refer to the "Start of...". If FALSE, labels will refer to "End
+ * of...".
+ *
+ * @return A newly created GncPeriodSelect widget.
+ */
+GtkWidget *gnc_period_select_new (gboolean starting_labels);
+
+
+/** Create a new GncPeriodSelect widget from a glade file. The int1
+ * argument passed from glade is used to determine whether the widget
+ * uses labels for start times or end times. A non-zero int2
+ * argument indicates that an example date should be shown.
+ *
+ * @return A newly created GncPeriodSelect widget.
+ */
+GtkWidget * gnc_period_select_new_glade (gchar *widget_name,
+ gchar *string1, gchar *string2,
+ gint int1, gint int2);
+/** @} */
+
+
+/** @name GncPeriodSelect Properties
+ @{ */
+
+/** Set the fiscal year end on a GncPeriodSelect widget. If set to a
+ * value other than NULL then widget will include fiscal accounting
+ * period like "this fiscal year".
+ *
+ * @param period The GncPeriodSelect widget to update.
+ *
+ * @param fy_end The new fiscal year end value, or NULL if no fiscal
+ * year is set. Note that only the month and day fields need be
+ * valid in the provided GDate.
+ */
+void gnc_period_select_set_fy_end (GncPeriodSelect *period, const GDate *fy_end);
+
+
+/** Get the current value of the fiscal year end setting from a
+ * GncPeriodSelect widget. If the result is NULL then fiscal years
+ * are not currently supported.
+ *
+ * @param period The GncPeriodSelect widget to query.
+ *
+ * @return A pointer to a GDate containing the fiscal year end value,
+ * or NULL if no fiscal year end is set. Note that only the month
+ * and day fields are valid in the returned GDate.
+ */
+GDate *gnc_period_select_get_fy_end (GncPeriodSelect *period);
+
+
+/** Get the current value of the "show sample" setting from a
+ * GncPeriodSelect widget.
+ */
+gboolean
+gnc_period_select_get_show_date (GncPeriodSelect *period);
+
+
+/** Set the "show sample" setting on a GncPeriodSelect widget. If set
+ * to TRUE then a GtkLabel will be used to show the date
+ * corresponding to the selected time period.
+ */
+void gnc_period_select_set_show_date (GncPeriodSelect *period, const gboolean show_date);
+
+
+GDate *gnc_period_select_get_date_base (GncPeriodSelect *period);
+
+/* Set the base date used by a GncPeriodSelect widget. All example
+ * dates presented by the widget will be computed from this date.
+ */
+void gnc_period_select_set_date_base (GncPeriodSelect *period, const GDate *sample_base);
+
+/** @} */
+
+
+/** Set which item in the GncPeriodSelect is initially selected. This
+ * is used to set the initial selection before the widget is shown to
+ * the user.
+ *
+ * @param period The selection widget to update.
+ *
+ * @param which The accounting period that should be selected.
+ */
+void gnc_period_select_set_active (GncPeriodSelect *period, GncAccountingPeriod which);
+
+
+/** Get the currently selected accounting period from a
+ * GncPeriodSelect widget. This is used to retrieve the user's
+ * selection in the form of an enum.
+ *
+ * @param period The selection widget to query.
+ *
+ * @return An enum indicating the user's choice of accounting period.
+ */
+GncAccountingPeriod gnc_period_select_get_active (GncPeriodSelect *period);
+
+
+/** Get the currently selected accounting period choice from a
+ * GncPeriodSelect widget. This is used to retrieve the user's
+ * selection in the form of a GDate.
+ *
+ * @param period The selection widget to query.
+ *
+ * @return The starting/ending time. */
+GDate *gnc_period_select_get_date (GncPeriodSelect *period);
+
+/** Get the currently selected accounting period choice from a
+ * GncPeriodSelect widget. This is used to retrieve the user's
+ * selection in the form of an timestamp.
+ *
+ * @param period The selection widget to query.
+ *
+ * @return The starting/ending time (in seconds since 1970-01-01) of
+ * the accounting period selected by the user.
+ */
+time_t gnc_period_select_get_time (GncPeriodSelect *period);
+
+G_END_DECLS
+
+#endif /* GNC_PERIOD_SELECT_H */
+
+/** @} */
--- /dev/null
+++ src/gnome-utils/gnc-period-select.c
@@ -0,0 +1,738 @@
+/*
+ * gnc-period-select.c -- Accounting Period selection widget
+ *
+ * Copyright (c) 2005 David Hampton <hampton at employees.org>
+ * All rights reserved.
+ *
+ * Gnucash is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Gnucash is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652
+ * Boston, MA 02111-1307, USA gnu at gnu.org
+ */
+
+/** @addtogroup GUI
+ @{ */
+/** @file gnc-period-select.c
+ @brief A custom widget for selecting accounting periods.
+ @author David Hampton <hampton at employees.org>
+*/
+
+#include <config.h>
+
+#include "gnc-date.h"
+#include "gnc-gconf-utils.h"
+#include "gnc-period-select.h"
+#include "messages.h"
+
+enum {
+ PROP_0,
+ PROP_FY_END,
+ PROP_SHOW_DATE,
+ PROP_DATE_BASE,
+};
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/** Declarations *********************************************************/
+static void gnc_period_select_init (GncPeriodSelect *gce);
+static void gnc_period_select_class_init (GncPeriodSelectClass *class);
+static void gnc_period_select_finalize (GObject *object);
+
+static GtkComboBoxClass *parent_class;
+
+
+const gchar *start_strings[GNC_ACCOUNTING_PERIOD_LAST] = {
+ /* CY Strings */
+ N_("Today"),
+ N_("Start of this month"),
+ N_("Start of previous month"),
+ N_("Start of this quarter"),
+ N_("Start of previous quarter"),
+ N_("Start of this year"),
+ N_("Start of previous year"),
+
+ /* FY Strings */
+ N_("Start of this fiscal year"),
+ N_("Start of previous fiscal year"),
+};
+
+const gchar *end_strings[GNC_ACCOUNTING_PERIOD_LAST] = {
+ /* CY Strings */
+ N_("Today"),
+ N_("End of this month"),
+ N_("End of previous month"),
+ N_("End of this quarter"),
+ N_("End of previous quarter"),
+ N_("End of this year"),
+ N_("End of previous year"),
+
+ /* FY Strings */
+ N_("End of this fiscal year"),
+ N_("End of previous fiscal year"),
+};
+
+
+/** Private Data Structure ***********************************************/
+
+typedef struct _GncPeriodSelectPrivate GncPeriodSelectPrivate;
+struct _GncPeriodSelectPrivate
+{
+ GtkWidget *selector;
+
+ gboolean start;
+ GDate *fy_end;
+
+ GDate *date_base;
+ GtkWidget *date_label;
+ GtkWidget *date_align;
+};
+
+#define GNC_PERIOD_SELECT_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_PERIOD_SELECT, GncPeriodSelectPrivate))
+
+
+/************************************************************/
+/* Signal Functions */
+/************************************************************/
+
+/* Tells a GncPeriodSelect object to emit a "changed" signal.
+ */
+void
+gnc_period_select_changed (GncPeriodSelect *period)
+{
+ g_return_if_fail(GNC_IS_PERIOD_SELECT(period));
+
+ g_signal_emit(G_OBJECT(period), signals[CHANGED], 0);
+}
+
+
+/** Update the user visible sample date label if it exists on this
+ * widget. This label is for user feedback only.
+ *
+ * @param period The GncPeriodSelect object to update.
+ */
+static void
+gnc_period_sample_update_date_label (GncPeriodSelect *period)
+{
+ GncPeriodSelectPrivate *priv;
+ gchar *time_string;
+ time_t secs;
+
+ g_return_if_fail(GNC_IS_PERIOD_SELECT(period));
+ priv = GNC_PERIOD_SELECT_GET_PRIVATE(period);
+ if (!priv->date_label)
+ return;
+ secs = gnc_period_select_get_time(GNC_PERIOD_SELECT(period));
+ time_string = qof_print_date(secs);
+ gtk_label_set_label(GTK_LABEL(priv->date_label), time_string);
+ g_free(time_string);
+}
+
+
+/** Handle the "changed" signal from the GtkComboBox that is embedded
+ * in this GncPeriodSelect object. When called, this function
+ * updates the feedback label embedded in the object, then generates
+ * another "changed" signal so that a developer can see that
+ * something in the object changed.
+ *
+ * @param box The combo box that changed.
+ *
+ * @param period The GncPeriodSelect containing the combo box.
+ */
+static void
+gnc_period_sample_combobox_changed (GtkComboBox *box, GncPeriodSelect *period)
+{
+ g_return_if_fail(GNC_IS_PERIOD_SELECT(period));
+
+ /* Update this widget */
+ gnc_period_sample_update_date_label(period);
+
+ /* Pass it on... */
+ gnc_period_select_changed(period);
+}
+
+
+/** Handle an application wide change in the date format. This
+ * function will be called when the GConf key for the date format is
+ * updated. It doesn't really care what the new format is, because
+ * the date string is generated elsewhere. It just needs to know to
+ * update the date label so that it matches the newly selected format.
+ *
+ * @param unused The new value for the Gnucash date format.
+ *
+ * @param period The GncPeriodSelect that needs to be updated.
+ */
+static void
+gnc_period_sample_new_date_format (GConfEntry *unused,
+ GncPeriodSelect *period)
+{
+ gnc_period_sample_update_date_label(period);
+}
+
+
+/************************************************************/
+/* Property Functions */
+/************************************************************/
+
+/** @name GncPeriodSelect Properties
+ @{ */
+
+/* Get the current value of the fiscal year end setting from a
+ * GncPeriodSelect widget. If the result is NULL then fiscal years
+ * are not currently supported.
+ */
+GDate *
+gnc_period_select_get_fy_end (GncPeriodSelect *period)
+{
+ GncPeriodSelectPrivate *priv;
+ priv = GNC_PERIOD_SELECT_GET_PRIVATE(period);
+
+ g_return_val_if_fail(period != NULL, NULL);
+ g_return_val_if_fail(GNC_IS_PERIOD_SELECT(period), NULL);
+
+ priv = GNC_PERIOD_SELECT_GET_PRIVATE(period);
+ if (!priv->fy_end)
+ return NULL;
+ return g_date_new_dmy(g_date_get_day(priv->fy_end),
+ g_date_get_month(priv->fy_end),
+ G_DATE_BAD_YEAR);
+}
+
+
+/* Set the fiscal year end on a GncPeriodSelect widget. If set to a
+ * value other than NULL then widget will include fiscal accounting
+ * period like "this fiscal year".
+ */
+void
+gnc_period_select_set_fy_end (GncPeriodSelect *period, const GDate *fy_end)
+{
+ GncPeriodSelectPrivate *priv;
+ const gchar *label;
+ gint i;
+
+ g_return_if_fail(period != NULL);
+ g_return_if_fail(GNC_IS_PERIOD_SELECT(period));
+
+ priv = GNC_PERIOD_SELECT_GET_PRIVATE(period);
+ if (priv->fy_end)
+ g_date_free(priv->fy_end);
+
+ if (fy_end) {
+ priv->fy_end = g_date_new_dmy(g_date_get_day(fy_end),
+ g_date_get_month(fy_end),
+ G_DATE_BAD_YEAR);
+ } else {
+ priv->fy_end = NULL;
+ }
+
+ if (fy_end) {
+ for (i = GNC_ACCOUNTING_PERIOD_CYEAR_LAST; i < GNC_ACCOUNTING_PERIOD_FYEAR_LAST; i++) {
+ label = priv->start ? _(start_strings[i]) : _(end_strings[i]);
+ gtk_combo_box_append_text(GTK_COMBO_BOX(priv->selector), label);
+ }
+ } else {
+ for (i = GNC_ACCOUNTING_PERIOD_FYEAR_LAST - 1; i >= GNC_ACCOUNTING_PERIOD_FYEAR_LAST; i--) {
+ gtk_combo_box_remove_text(GTK_COMBO_BOX(priv->selector), i);
+ }
+ }
+}
+
+
+static void
+gnc_period_select_set_date_common (GncPeriodSelect *period, const GDate *date)
+{
+ GncPeriodSelectPrivate *priv;
+
+ priv = GNC_PERIOD_SELECT_GET_PRIVATE(period);
+ if (date) {
+ if (priv->date_base)
+ g_date_free(priv->date_base);
+ priv->date_base = g_date_new_dmy(g_date_get_day(date),
+ g_date_get_month(date),
+ g_date_get_year(date));
+ if (priv->date_label == NULL) {
+ priv->date_align = gtk_alignment_new(0.5, 0.5, 0, 0);
+ gtk_alignment_set_padding(GTK_ALIGNMENT(priv->date_align), 0, 0, 6, 0);
+ gtk_box_pack_start_defaults(GTK_BOX(period), priv->date_align);
+ priv->date_label = gtk_label_new("");
+ gtk_container_add(GTK_CONTAINER(priv->date_align), priv->date_label);
+ gtk_widget_show_all(priv->date_align);
+ }
+ gnc_period_sample_update_date_label(period);
+ return;
+ }
+
+ if (priv->date_base) {
+ g_date_free(priv->date_base);
+ priv->date_base = NULL;
+ gtk_widget_destroy(priv->date_align);
+ priv->date_align = NULL;
+ priv->date_label = NULL;
+ }
+}
+
+
+/* Get the current value of the "show date" setting from a
+ * GncPeriodSelect widget.
+ */
+gboolean
+gnc_period_select_get_show_date (GncPeriodSelect *period)
+{
+ GncPeriodSelectPrivate *priv;
+
+ g_return_val_if_fail(period != NULL, FALSE);
+ g_return_val_if_fail(GNC_IS_PERIOD_SELECT(period), FALSE);
+
+ priv = GNC_PERIOD_SELECT_GET_PRIVATE(period);
+ return (priv->date_base != NULL);
+}
+
+/* Set the "show date" setting on a GncPeriodSelect widget. If set
+ * to TRUE then a GtkLabel will be used to show the date
+ * corresponding to the selected time period.
+ */
+void
+gnc_period_select_set_show_date (GncPeriodSelect *period, const gboolean show_date)
+{
+ GDate date;
+
+ g_return_if_fail(period != NULL);
+ g_return_if_fail(GNC_IS_PERIOD_SELECT(period));
+
+ if (show_date) {
+ g_date_clear(&date, 1);
+ g_date_set_time(&date, time (NULL));
+ gnc_period_select_set_date_common(period, &date);
+ } else {
+ gnc_period_select_set_date_common(period, NULL);
+ }
+}
+
+
+GDate *
+gnc_period_select_get_date_base (GncPeriodSelect *period)
+{
+ GncPeriodSelectPrivate *priv;
+
+ g_return_val_if_fail(period != NULL, NULL);
+ g_return_val_if_fail(GNC_IS_PERIOD_SELECT(period), NULL);
+
+ priv = GNC_PERIOD_SELECT_GET_PRIVATE(period);
+ if (!priv->date_base)
+ return NULL;
+ return g_date_new_dmy(g_date_get_day(priv->date_base),
+ g_date_get_month(priv->date_base),
+ g_date_get_year(priv->date_base));
+}
+
+
+/* Set the base date used by a GncPeriodSelect widget. All example
+ * dates presented by the widget will be computed from this date.
+ */
+void
+gnc_period_select_set_date_base (GncPeriodSelect *period, const GDate *date_base)
+{
+ g_return_if_fail(period != NULL);
+ g_return_if_fail(GNC_IS_PERIOD_SELECT(period));
+
+ gnc_period_select_set_date_common(period, date_base);
+}
+
+
+/** Retrieve a property specific to this GncPeriodSelect object. This is
+ * nothing more than a dispatch function for routines that can be
+ * called directly. It has the nice feature of allowing a single
+ * function call to retrieve multiple properties.
+ *
+ * @internal
+ */
+static void
+gnc_period_select_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GncPeriodSelect *period = GNC_PERIOD_SELECT(object);
+
+ switch (prop_id)
+ {
+ case PROP_FY_END:
+ g_value_set_pointer(value, gnc_period_select_get_fy_end(period));
+ break;
+ case PROP_SHOW_DATE:
+ g_value_set_boolean(value, gnc_period_select_get_show_date(period));
+ break;
+ case PROP_DATE_BASE:
+ g_value_set_pointer(value, gnc_period_select_get_date_base(period));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+
+/** Set a property specific to this GncPeriodSelect object. This is
+ * nothing more than a dispatch function for routines that can be
+ * called directly. It has the nice feature of allowing a new widget
+ * to be created with a varargs list specifying the properties,
+ * instead of having to explicitly call each property function.
+ *
+ * @internal
+ */
+static void
+gnc_period_select_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GncPeriodSelect *period = GNC_PERIOD_SELECT(object);
+
+ switch (prop_id)
+ {
+ case PROP_FY_END:
+ gnc_period_select_set_fy_end(period, g_value_get_pointer(value));
+ break;
+ case PROP_SHOW_DATE:
+ gnc_period_select_set_show_date(period, g_value_get_boolean(value));
+ break;
+ case PROP_DATE_BASE:
+ gnc_period_select_set_date_base(period, g_value_get_pointer(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+/** @} */
+
+/************************************************************/
+/* Core Implementation */
+/************************************************************/
+
+/** @name GncPeriodSelect Core Implementation
+ @{ */
+
+/* Returns the GType of a GncPeriodSelect widget.
+ */
+GType
+gnc_period_select_get_type (void)
+{
+ static GType period_select_type = 0;
+
+ if (period_select_type == 0) {
+ static const GTypeInfo period_select_info = {
+ sizeof (GncPeriodSelectClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) gnc_period_select_class_init,
+ NULL,
+ NULL,
+ sizeof (GncPeriodSelect),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gnc_period_select_init,
+ NULL
+ };
+
+ period_select_type = g_type_register_static(GTK_TYPE_HBOX,
+ "GncPeriodSelect",
+ &period_select_info, 0);
+ }
+
+ return period_select_type;
+}
+
+
+/** Initialize the class for the a Period Selection widget. This
+ * will set up any function pointers that override functions in the
+ * parent class, and also installs the proprieties that are unique to
+ * this class.
+ *
+ * @param klass The new class structure created by the object system.
+ *
+ * @internal
+ */
+static void
+gnc_period_select_class_init (GncPeriodSelectClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ parent_class = g_type_class_peek_parent(klass);
+
+ gobject_class = G_OBJECT_CLASS(klass);
+ gobject_class->set_property = gnc_period_select_set_property;
+ gobject_class->get_property = gnc_period_select_get_property;
+ gobject_class->finalize = gnc_period_select_finalize;
+
+
+ signals[CHANGED] = g_signal_new("changed",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET(GncPeriodSelectClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+
+ g_object_class_install_property(gobject_class,
+ PROP_FY_END,
+ g_param_spec_pointer("fy-end",
+ "Fiscal Year End",
+ "The fiscal year to use for this widget",
+ G_PARAM_READWRITE));
+ g_object_class_install_property(gobject_class,
+ PROP_SHOW_DATE,
+ g_param_spec_boolean("show-date",
+ "Show Date",
+ "Show the start/end date of the accouting period in this widget",
+ FALSE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property(gobject_class,
+ PROP_DATE_BASE,
+ g_param_spec_pointer("date-base",
+ "Date Base",
+ "The starting date to use for display calculations",
+ G_PARAM_READWRITE));
+
+ g_type_class_add_private(klass, sizeof(GncPeriodSelectPrivate));
+}
+
+
+/** Initialize a new instance of a gnucash accounting period selection
+ * widget. This function allocates and initializes the object
+ * private storage space.
+ *
+ * @param period The new object instance created by the object system.
+ *
+ * @internal
+ */
+static void
+gnc_period_select_init (GncPeriodSelect *period)
+{
+ GncPeriodSelectPrivate *priv;
+
+ priv = GNC_PERIOD_SELECT_GET_PRIVATE(period);
+ priv->start = TRUE;
+}
+
+
+/** Finalize the GncPeriodSelect object. This function is called from
+ * the G_Object level to complete the destruction of the object. It
+ * should release any memory not previously released by the destroy
+ * function (i.e. the private data structure), then chain up to the
+ * parent's destroy function.
+ *
+ * @param object The object being destroyed.
+ *
+ * @internal
+ */
+static void
+gnc_period_select_finalize (GObject *object)
+{
+ GncPeriodSelectPrivate *priv;
+ GncPeriodSelect *period;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GNC_IS_PERIOD_SELECT (object));
+
+ period = GNC_PERIOD_SELECT(object);
+ priv = GNC_PERIOD_SELECT_GET_PRIVATE(period);
+
+ /* Stop tracking changes to date formatting */
+ gnc_gconf_general_remove_cb(KEY_DATE_FORMAT,
+ (GncGconfGeneralCb)gnc_period_sample_new_date_format, period);
+
+ /* The selector and date_label were added to the hbox. They will be
+ * freed automatically. */
+ if (priv->fy_end)
+ g_date_free(priv->fy_end);
+ if (priv->date_base)
+ g_date_free(priv->date_base);
+
+ /* Do not free the private data structure. It is part of a larger
+ * memory block allocated by the type system. */
+
+ if (G_OBJECT_CLASS(parent_class)->finalize)
+ (* G_OBJECT_CLASS(parent_class)->finalize) (object);
+}
+
+
+/* Create a new GncPeriodSelect widget which is used to select a
+ * accounting period like "previous month" or "this year".
+ *
+ * @param starting_labels If set to TRUE then all the labels will
+ * refer to the "Start of...". If FALSE, labels will refer to "End
+ * of...".
+ *
+ * @return A GncPeriodSelect widget.
+ */
+GtkWidget *
+gnc_period_select_new (gboolean starting_labels)
+{
+ GncPeriodSelectPrivate *priv;
+ GncPeriodSelect *period;
+ const gchar *label;
+ gint i;
+
+ period = g_object_new(GNC_TYPE_PERIOD_SELECT, NULL);
+
+ /* Set up private data structures */
+ priv = GNC_PERIOD_SELECT_GET_PRIVATE(period);
+ priv->selector = gtk_combo_box_new_text();
+ priv->start = starting_labels;
+
+ /* Add the internal widgets to the hbox */
+ gtk_box_pack_start_defaults(GTK_BOX(period), priv->selector);
+ gtk_widget_show(priv->selector);
+
+ /* Find out when the combo box changes */
+ g_signal_connect(G_OBJECT(priv->selector), "changed",
+ G_CALLBACK(gnc_period_sample_combobox_changed), period);
+
+ /* Build all the labels except the fiscal year labels */
+ for (i = 0; i < GNC_ACCOUNTING_PERIOD_CYEAR_LAST; i++) {
+ label = starting_labels ? _(start_strings[i]) : _(end_strings[i]);
+ gtk_combo_box_append_text(GTK_COMBO_BOX(priv->selector), label);
+ }
+
+ /* Track changes to date formatting */
+ gnc_gconf_general_register_cb(KEY_DATE_FORMAT,
+ (GncGconfGeneralCb)gnc_period_sample_new_date_format, period);
+
+ return GTK_WIDGET (period);
+}
+
+
+/* Create a new GncPeriodSelect widget from a glade file. The int1
+ * argument passed from glade is used to determine whether the widget
+ * uses labels for start times or end times. A non-zero int2
+ * argument indicates that an example date should be shown.
+ */
+GtkWidget *
+gnc_period_select_new_glade (gchar *widget_name,
+ gchar *string1, gchar *string2,
+ gint int1, gint int2)
+{
+ GtkWidget *widget;
+ widget = gnc_period_select_new(int1 != 0);
+ if (int2)
+ gnc_period_select_set_show_date(GNC_PERIOD_SELECT(widget), TRUE);
+ gtk_widget_show(widget);
+ return widget;
+}
+
+/** @} */
+
+/************************************************************/
+/* Auxiliary Functions */
+/************************************************************/
+
+
+/* Set which item in the GncPeriodSelect is initially selected. This
+ * is used to set the initial selection before the widget is shown to
+ * the user.
+ */
+void
+gnc_period_select_set_active (GncPeriodSelect *period,
+ GncAccountingPeriod which)
+{
+ GncPeriodSelectPrivate *priv;
+
+ g_return_if_fail(period != NULL);
+ g_return_if_fail(GNC_IS_PERIOD_SELECT(period));
+ g_return_if_fail(which >= 0);
+ g_return_if_fail(which < GNC_ACCOUNTING_PERIOD_LAST);
+
+ priv = GNC_PERIOD_SELECT_GET_PRIVATE(period);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(priv->selector), which);
+}
+
+
+/* Get the currently selected accounting period from a
+ * GncPeriodSelect widget. This is used to retrieve the user's
+ * selection in the form of an enum.
+ */
+GncAccountingPeriod
+gnc_period_select_get_active (GncPeriodSelect *period)
+{
+ GncPeriodSelectPrivate *priv;
+
+ g_return_val_if_fail(period != NULL, -1);
+ g_return_val_if_fail(GNC_IS_PERIOD_SELECT(period), -1);
+
+ priv = GNC_PERIOD_SELECT_GET_PRIVATE(period);
+ return gtk_combo_box_get_active(GTK_COMBO_BOX(priv->selector));
+}
+
+
+/* Get the currently selected accounting period choice from a
+ * GncPeriodSelect widget. This is used to retrieve the user's
+ * selection in the form of a GDate.
+ */
+GDate *
+gnc_period_select_get_date (GncPeriodSelect *period)
+{
+ GncPeriodSelectPrivate *priv;
+ GncAccountingPeriod which;
+
+ g_return_val_if_fail(period != NULL, 0);
+ g_return_val_if_fail(GNC_IS_PERIOD_SELECT(period), 0);
+
+ priv = GNC_PERIOD_SELECT_GET_PRIVATE(period);
+ which = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->selector));
+ if (which == -1)
+ return NULL;
+
+ if (priv->start)
+ return gnc_accounting_period_start_gdate(which, priv->fy_end,
+ priv->date_base);
+ return gnc_accounting_period_end_gdate(which, priv->fy_end,
+ priv->date_base);
+}
+
+
+/* Get the currently selected accounting period from a
+ * GncPeriodSelect widget. This is used to retrieve the user's
+ * selection in the form of an timestamp.
+ */
+time_t
+gnc_period_select_get_time (GncPeriodSelect *period)
+{
+ GncPeriodSelectPrivate *priv;
+ GncAccountingPeriod which;
+
+ g_return_val_if_fail(period != NULL, 0);
+ g_return_val_if_fail(GNC_IS_PERIOD_SELECT(period), 0);
+
+ priv = GNC_PERIOD_SELECT_GET_PRIVATE(period);
+ which = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->selector));
+ if (which == -1)
+ return 0;
+
+ if (priv->start)
+ return gnc_accounting_period_start_timet(which, priv->fy_end,
+ priv->date_base);
+ return gnc_accounting_period_end_timet(which, priv->fy_end,
+ priv->date_base);
+}
+
+/** @} */
More information about the gnucash-changes
mailing list