Bug 421610 - Include logical dates in View->Filter

Change the register filter option 'Today' radio button to be a period
select widget. This will give some predefined relative options that are
the same as in the Preference dialog.
pull/2210/head
Robert Fewell 3 weeks ago
parent a780cd1a11
commit 35822232ca

@ -38,7 +38,9 @@
#include "gnc-date.h"
#include "gnc-date-edit.h"
#include "gnc-glib-utils.h"
#include "gnc-ui.h"
#include "gnc-state.h"
#include "gnc-period-select.h"
#include "gnc-prefs.h"
#include "gnc-ui-util.h"
#include "gnc-window.h"
@ -70,21 +72,35 @@ struct RegisterFilterDialog
GncPluginPage* plugin_page;
GtkWidget* dialog;
GtkWidget* table;
GtkWidget* start_date_choose;
GtkWidget* start_date_today;
GtkWidget* start_date;
GtkWidget* end_date_choose;
GtkWidget* end_date_today;
GtkWidget* start_earliest; //label
GtkWidget* start_relative_check; //checkbutton
GtkWidget* start_relative; //account period
GtkWidget* start_date_check; //checkbutton
GtkWidget* start_date; //date
GtkWidget* start_days_check; //checkbutton
GtkWidget* start_days; //spin
GtkWidget* end_latest;
GtkWidget* end_relative_check;
GtkWidget* end_relative;
GtkWidget* end_date_check;
GtkWidget* end_date;
GtkWidget* num_days;
GtkWidget* end_days_check;
GtkWidget* end_days;
cleared_match_t original_cleared_match;
time64 original_start_time;
time64 original_end_time;
int original_days;
bool original_save_filter;
GtkWidget* num_days;
bool show_save_button;
cleared_match_t original_cleared_match;
GncAccountingPeriod original_start_ap;
time64 original_start_time;
int original_start_days;
GncAccountingPeriod original_end_ap;
time64 original_end_time;
int original_end_days;
int original_days;
bool original_save_filter;
bool show_save_button;
};
extern "C"
@ -119,6 +135,15 @@ gnc_ppr_filter_save_cb (GtkToggleButton* button,
void
gnc_ppr_filter_days_changed_cb (GtkSpinButton* button,
RegisterFilterDialog* rfd);
void
gnc_ppr_filter_start_toggle_cb (GtkToggleButton* button,
RegisterFilterDialog* rfd);
void
gnc_ppr_filter_end_toggle_cb (GtkToggleButton* button,
RegisterFilterDialog* rfd);
void
gnc_ppr_filter_start_end_days_changed_cb (GtkSpinButton* button,
RegisterFilterDialog* rfd);
}
struct status_action
@ -191,6 +216,25 @@ ppr_filter_dmy2time (std::string date_string)
return gnc_mktime (&when);
}
/* This function subtracts a number of days from now to a time64 value */
static time64
get_time_for_days_ago (int days, bool use_day_start)
{
time64 time_val = 0;
if (days > 0)
{
struct tm tm;
if (use_day_start)
gnc_tm_get_today_start (&tm);
else
gnc_tm_get_today_end (&tm);
tm.tm_mday = tm.tm_mday - days;
time_val = gnc_mktime (&tm);
}
return time_val;
}
static std::vector<std::string>
split_filter_by_delimiter (std::string str, char delimiter)
{
@ -245,19 +289,96 @@ ppr_filter_load_filter (GNCSplitReg *gsr, GNCLedgerDisplayType ledger_type)
}
static void
set_filterdata_to_defaults (FilterData *fd)
set_filterdata_to_defaults (FilterData *fd, bool date_parts_only)
{
fd->cleared_match = (cleared_match_t)std::stol (DEFAULT_FILTER, nullptr, 16);
if (!date_parts_only)
{
fd->cleared_match = (cleared_match_t)std::stol (DEFAULT_FILTER, nullptr, 16);
fd->save_filter = false;
}
fd->start_ap = GNC_ACCOUNTING_PERIOD_INVALID;
fd->start_time = 0;
fd->start_days = 0;
fd->end_ap = GNC_ACCOUNTING_PERIOD_INVALID;
fd->end_time = 0;
fd->end_days = 0;
fd->days = 0;
fd->save_filter = false;
}
static int
get_trailing_int (const std::string split_filter, const std::string find_text)
{
int ret_int = -1;
std::size_t found = split_filter.find (find_text);
if (found != std::string::npos)
{
std::string found_str = split_filter.substr (found + find_text.length(), std::string::npos);
ret_int = std::stol (found_str, nullptr, 10);
}
return ret_int;
}
static void
update_fd_with_date_filter_parts (FilterData *fd, const std::string filter_part,
bool start_filter, int ap_trailing_int, int days_trailing_int)
{
if (ap_trailing_int != -1)
{
GDate *tmp_date = nullptr;
if (start_filter)
{
fd->start_ap = (GncAccountingPeriod)ap_trailing_int;
tmp_date = gnc_accounting_period_start_gdate (fd->start_ap, nullptr, nullptr);
}
else
{
fd->end_ap = (GncAccountingPeriod)ap_trailing_int;
tmp_date = gnc_accounting_period_end_gdate (fd->end_ap, nullptr, nullptr);
}
if (tmp_date)
{
if (start_filter)
fd->start_time = gnc_time64_get_day_start_gdate (tmp_date);
else
fd->end_time = gnc_time64_get_day_end_gdate (tmp_date);
g_date_free (tmp_date);
}
}
else
{
if (days_trailing_int != -1)
{
if (start_filter)
{
fd->start_days = days_trailing_int;
fd->start_time = get_time_for_days_ago (fd->start_days, true);
}
else
{
fd->end_days = days_trailing_int;
fd->end_time = get_time_for_days_ago (fd->end_days, false);
}
}
else
{
time64 tmp_time = ppr_filter_dmy2time (filter_part);
if (start_filter)
fd->start_time = gnc_time64_get_day_start (tmp_time);
else
fd->end_time = gnc_time64_get_day_end (tmp_time);
}
}
fd->save_filter = true;
}
static void
ppr_filter_load_filter_parts (GNCSplitReg *gsr, GNCLedgerDisplayType ledger_type, FilterData *fd)
{
set_filterdata_to_defaults (fd);
set_filterdata_to_defaults (fd, false);
fd->dialog = nullptr;
if (!gsr)
@ -282,18 +403,20 @@ ppr_filter_load_filter_parts (GNCSplitReg *gsr, GNCLedgerDisplayType ledger_type
{
PINFO("Loaded Filter Start Date is %s", split_filter[1].c_str());
fd->start_time = ppr_filter_dmy2time (split_filter[1]);
fd->start_time = gnc_time64_get_day_start (fd->start_time);
fd->save_filter = true;
int ap_trailing_int = get_trailing_int (split_filter[1], "SAP");
int days_trailing_int = get_trailing_int (split_filter[1], "SDAY");
update_fd_with_date_filter_parts (fd, split_filter[1], true, ap_trailing_int, days_trailing_int);
}
if (split_filter_size > 2 && (split_filter[2].compare (std::string ("0"))) != 0)
{
PINFO("Loaded Filter End Date is %s", split_filter[2].c_str());
fd->end_time = ppr_filter_dmy2time (split_filter[2]);
fd->end_time = gnc_time64_get_day_end (fd->end_time);
fd->save_filter = true;
int ap_trailing_int = get_trailing_int (split_filter[2], "EAP");
int days_trailing_int = get_trailing_int (split_filter[1], "EDAY");
update_fd_with_date_filter_parts (fd, split_filter[2], false, ap_trailing_int, days_trailing_int);
}
// set the default for the number of days
@ -356,18 +479,22 @@ ppr_filter_save_filter_parts (GNCSplitReg *gsr, FilterData *fd)
save_filter_str.append (buffer);
// start time
if (fd->start_time != 0)
{
if (fd->start_ap != GNC_ACCOUNTING_PERIOD_INVALID)
save_filter_str.append (";SAP" + std::to_string (fd->start_ap));
else if (fd->start_days > 0)
save_filter_str.append (";SDAY" + std::to_string (fd->start_days));
else if (fd->start_time != 0)
save_filter_str.append (";" + ppr_filter_time2dmy (fd->start_time));
}
else
save_filter_str.append (";0");
// end time
if (fd->end_time != 0)
{
if (fd->end_ap != GNC_ACCOUNTING_PERIOD_INVALID)
save_filter_str.append (";EAP" + std::to_string (fd->end_ap));
else if (fd->end_days > 0)
save_filter_str.append (";EDAY" + std::to_string (fd->end_days));
else if (fd->end_time != 0)
save_filter_str.append (";" + ppr_filter_time2dmy (fd->end_time));
}
else
save_filter_str.append (";0");
@ -580,13 +707,7 @@ ppr_filter_update_date_query (GncPluginPage* plugin_page)
if (fd->days > 0)
{
time64 start;
struct tm tm;
gnc_tm_get_today_start (&tm);
tm.tm_mday = tm.tm_mday - fd->days;
start = gnc_mktime (&tm);
time64 start = get_time_for_days_ago (fd->days, true);
xaccQueryAddDateMatchTT (query, TRUE, start, FALSE, 0, QOF_QUERY_AND);
}
@ -610,7 +731,7 @@ gnc_ppr_filter_clear_current_filter (GncPluginPage* plugin_page)
auto fd = gnc_plugin_page_register_get_filter_data (plugin_page);
set_filterdata_to_defaults (fd);
set_filterdata_to_defaults (fd, false);
ppr_filter_update_date_query (plugin_page);
}
@ -643,7 +764,7 @@ gnc_ppr_filter_update_register (GncPluginPage* plugin_page)
SplitRegister *reg = gnc_ledger_display_get_split_register (gsr->ledger);
if (reg->type != GENERAL_JOURNAL) // search ledger and the like
set_filterdata_to_defaults (fd);
set_filterdata_to_defaults (fd, false);
}
/* Update Query with Filter Status and Dates */
ppr_filter_update_status_query (plugin_page);
@ -695,18 +816,49 @@ gnc_ppr_filter_status_one_cb (GtkToggleButton* button,
}
static void
set_checkbutton_with_blocking (GtkWidget *widget,
set_sensitive_start_widget (RegisterFilterDialog *rfd, GtkWidget *enable_widget, gboolean active)
{
gtk_widget_set_sensitive (GTK_WIDGET(rfd->start_earliest), !active);
gtk_widget_set_sensitive (GTK_WIDGET(rfd->start_relative), FALSE);
gtk_widget_set_sensitive (GTK_WIDGET(rfd->start_date), FALSE);
gtk_widget_set_sensitive (GTK_WIDGET(rfd->start_days), FALSE);
gtk_widget_set_sensitive (GTK_WIDGET(enable_widget), active);
}
static void
set_sensitive_end_widget (RegisterFilterDialog *rfd, GtkWidget *enable_widget, gboolean active)
{
gtk_widget_set_sensitive (GTK_WIDGET(rfd->end_latest), !active);
gtk_widget_set_sensitive (GTK_WIDGET(rfd->end_relative), FALSE);
gtk_widget_set_sensitive (GTK_WIDGET(rfd->end_date), FALSE);
gtk_widget_set_sensitive (GTK_WIDGET(rfd->end_days), FALSE);
gtk_widget_set_sensitive (GTK_WIDGET(enable_widget), active);
}
static void
set_checkbutton_with_blocking (GtkWidget *widget1, GtkWidget *widget2,
GFunc function,
RegisterFilterDialog *rfd,
gboolean active)
{
PINFO("Block GtkToggleButton %p for setting active %s",
widget, active ? "TRUE" : "FALSE");
g_signal_handlers_block_by_func (widget,
widget1, active ? "TRUE" : "FALSE");
g_signal_handlers_block_by_func (widget1,
(gpointer)function, rfd);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), active);
g_signal_handlers_unblock_by_func (widget,
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget1), active);
g_signal_handlers_unblock_by_func (widget1,
(gpointer)function, rfd);
if (widget2)
{
PINFO("Block GtkToggleButton %p for setting active %s",
widget2, active ? "TRUE" : "FALSE");
g_signal_handlers_block_by_func (widget2,
(gpointer)function, rfd);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget2), active);
g_signal_handlers_unblock_by_func (widget2,
(gpointer)function, rfd);
}
}
/** This function is called whenever the "select all" status button is
@ -731,7 +883,7 @@ gnc_ppr_filter_status_select_all_cb (GtkButton* button,
/* Turn on all the check menu items */
for (const auto& action : status_actions)
{
set_checkbutton_with_blocking (action.widget,
set_checkbutton_with_blocking (action.widget, nullptr,
(GFunc)gnc_ppr_filter_status_one_cb,
rfd, TRUE);
}
@ -764,7 +916,7 @@ gnc_ppr_filter_status_clear_all_cb (GtkButton* button,
/* Turn off all the check menu items */
for (const auto& action : status_actions)
{
set_checkbutton_with_blocking (action.widget,
set_checkbutton_with_blocking (action.widget, nullptr,
(GFunc)gnc_ppr_filter_status_one_cb,
rfd, FALSE);
}
@ -775,6 +927,14 @@ gnc_ppr_filter_status_clear_all_cb (GtkButton* button,
LEAVE(" ");
}
static void
print_info_time64_date (const gchar *text, time64 date)
{
gchar *date_txt = qof_print_date (date);
PINFO("%s, %s", text, date_txt);
g_free (date_txt);
}
static void
get_filter_times (RegisterFilterDialog* rfd)
{
@ -782,33 +942,55 @@ get_filter_times (RegisterFilterDialog* rfd)
auto fd = gnc_plugin_page_register_get_filter_data (rfd->plugin_page);
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(rfd->start_date_choose)))
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(rfd->start_date_check)))
{
time_val = gnc_date_edit_get_date (GNC_DATE_EDIT(rfd->start_date));
time_val = gnc_time64_get_day_start (time_val);
fd->start_time = time_val;
fd->start_ap = GNC_ACCOUNTING_PERIOD_INVALID;
print_info_time64_date ("Start date is", fd->start_time);
}
else
else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(rfd->start_relative_check)))
{
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(rfd->start_date_today)))
fd->start_time = gnc_time64_get_today_start();
else
fd->start_time = 0;
auto *sdate = gnc_period_select_get_date (GNC_PERIOD_SELECT(rfd->start_relative));
fd->start_time = gnc_time64_get_day_start_gdate (sdate);
fd->start_ap = gnc_period_select_get_active (GNC_PERIOD_SELECT(rfd->start_relative));
print_info_time64_date ("Start date relative is", fd->start_time);
g_date_free (sdate);
}
else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(rfd->start_days_check)))
{
fd->start_time = get_time_for_days_ago (fd->start_days, true);
fd->start_ap = GNC_ACCOUNTING_PERIOD_INVALID;
print_info_time64_date ("Start date using days is", fd->start_time);
}
else
fd->start_time = 0;
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(rfd->end_date_choose)))
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(rfd->end_date_check)))
{
time_val = gnc_date_edit_get_date (GNC_DATE_EDIT(rfd->end_date));
time_val = gnc_time64_get_day_end (time_val);
fd->end_time = time_val;
fd->end_ap = GNC_ACCOUNTING_PERIOD_INVALID;
print_info_time64_date ("End date is", fd->end_time);
}
else
else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(rfd->end_relative_check)))
{
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(rfd->end_date_today)))
fd->end_time = gnc_time64_get_today_end();
else
fd->end_time = 0;
auto *edate = gnc_period_select_get_date (GNC_PERIOD_SELECT(rfd->end_relative));
fd->end_time = gnc_time64_get_day_end_gdate (edate);
fd->end_ap = gnc_period_select_get_active (GNC_PERIOD_SELECT(rfd->end_relative));
print_info_time64_date ("End date relative is", fd->end_time);
g_date_free (edate);
}
else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(rfd->end_days_check)))
{
fd->end_time = get_time_for_days_ago (fd->end_days, false);
fd->end_ap = GNC_ACCOUNTING_PERIOD_INVALID;
print_info_time64_date ("End date using days is", fd->end_time);
}
else
fd->end_time = 0;
}
/** This function is called when the radio buttons changes state. This
@ -851,9 +1033,7 @@ gnc_ppr_filter_select_range_cb (GtkRadioButton* button,
{
gtk_widget_set_sensitive (rfd->table, FALSE);
gtk_widget_set_sensitive (rfd->num_days, FALSE);
fd->start_time = 0;
fd->end_time = 0;
fd->days = 0;
set_filterdata_to_defaults (fd, true);
}
ppr_filter_update_date_query (rfd->plugin_page);
LEAVE(" ");
@ -986,6 +1166,169 @@ gnc_ppr_filter_end_cb (GtkWidget* radio,
LEAVE(" ");
}
static void
ppr_filter_relative_changed_cb (GtkWidget *widget,
RegisterFilterDialog* rfd)
{
g_return_if_fail (GNC_IS_PERIOD_SELECT(widget));
g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER(rfd->plugin_page));
ENTER("Period Select (%p), active_id %d, plugin_page %p",
widget, gnc_period_select_get_active (GNC_PERIOD_SELECT(widget)),
rfd->plugin_page);
get_filter_times (rfd);
ppr_filter_update_date_query (rfd->plugin_page);
LEAVE(" ");
}
/** This function is called when the "days ago" spin button is
* changed which is then saved and updates the time limitation on
* the register query. This is handled by a helper function as
* potentially all widgets will need to be examined.
*
* @param button A pointer to the "days ago" spin button.
*
* @param rfd A pointer to the filter dialog structure.
*/
void
gnc_ppr_filter_start_end_days_changed_cb (GtkSpinButton* button,
RegisterFilterDialog* rfd)
{
g_return_if_fail (GTK_IS_SPIN_BUTTON(button));
g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER(rfd->plugin_page));
ENTER("(button %p, page %p)", button, rfd->plugin_page);
auto fd = gnc_plugin_page_register_get_filter_data (rfd->plugin_page);
auto name = gtk_buildable_get_name (GTK_BUILDABLE(button));
if (g_strcmp0 (name, "start_days_spin") == 0)
fd->start_days = gtk_spin_button_get_value (GTK_SPIN_BUTTON(button));
if (g_strcmp0 (name, "end_days_spin") == 0)
fd->end_days = gtk_spin_button_get_value (GTK_SPIN_BUTTON(button));
get_filter_times (rfd);
ppr_filter_update_date_query (rfd->plugin_page);
LEAVE(" ");
}
/** This function is called when one of the check buttons for start
* relative or start date is changed. It activates the associated
* widget and deactivates the other.
*
* @param button A pointer to a GtkToggleButton widget.
*
* @param rfd A pointer to the filter dialog structure.
*/
void
gnc_ppr_filter_start_toggle_cb (GtkToggleButton* button,
RegisterFilterDialog* rfd)
{
g_return_if_fail (GTK_IS_CHECK_BUTTON(button));
g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER(rfd->plugin_page));
ENTER("Start toggle button (%p), plugin_page %p", button, rfd->plugin_page);
auto name = gtk_buildable_get_name (GTK_BUILDABLE(button));
gboolean active = gtk_toggle_button_get_active (button);
gtk_widget_set_sensitive (rfd->start_earliest, !active);
if (g_strcmp0 (name, "start_date_check") == 0)
{
set_sensitive_start_widget (rfd, rfd->start_date, active);
set_checkbutton_with_blocking (rfd->start_relative_check,
rfd->start_days_check,
(GFunc)gnc_ppr_filter_start_toggle_cb,
rfd, FALSE);
}
if (g_strcmp0 (name, "start_relative_check") == 0)
{
set_sensitive_start_widget (rfd, rfd->start_relative, active);
set_checkbutton_with_blocking (rfd->start_date_check,
rfd->start_days_check,
(GFunc)gnc_ppr_filter_start_toggle_cb,
rfd, FALSE);
}
if (g_strcmp0 (name, "start_days_check") == 0)
{
set_sensitive_start_widget (rfd, rfd->start_days, active);
set_checkbutton_with_blocking (rfd->start_date_check,
rfd->start_relative_check,
(GFunc)gnc_ppr_filter_start_toggle_cb,
rfd, FALSE);
}
get_filter_times (rfd);
ppr_filter_update_date_query (rfd->plugin_page);
LEAVE(" ");
}
/** This function is called when one of the check buttons for end
* relative or end date is changed. It activates the associated
* widget and deactivates the other.
*
* @param button A pointer to a GtkToggleButton widget.
*
* @param rfd A pointer to the filter dialog structure.
*/
void
gnc_ppr_filter_end_toggle_cb (GtkToggleButton* button,
RegisterFilterDialog* rfd)
{
g_return_if_fail (GTK_IS_CHECK_BUTTON(button));
g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER(rfd->plugin_page));
ENTER("End toggle button (%p), plugin_page %p", button, rfd->plugin_page);
auto name = gtk_buildable_get_name (GTK_BUILDABLE(button));
gboolean active = gtk_toggle_button_get_active (button);
gtk_widget_set_sensitive (rfd->end_latest, !active);
if (g_strcmp0 (name, "end_date_check") == 0)
{
set_sensitive_end_widget (rfd, rfd->end_date, active);
set_checkbutton_with_blocking (rfd->end_relative_check,
rfd->end_days_check,
(GFunc)gnc_ppr_filter_end_toggle_cb,
rfd, FALSE);
}
if (g_strcmp0 (name, "end_relative_check") == 0)
{
set_sensitive_end_widget (rfd, rfd->end_relative, active);
set_checkbutton_with_blocking (rfd->end_date_check,
rfd->end_days_check,
(GFunc)gnc_ppr_filter_end_toggle_cb,
rfd, FALSE);
}
if (g_strcmp0 (name, "end_days_check") == 0)
{
set_sensitive_end_widget (rfd, rfd->end_days, active);
set_checkbutton_with_blocking (rfd->end_date_check,
rfd->end_relative_check,
(GFunc)gnc_ppr_filter_end_toggle_cb,
rfd, FALSE);
}
get_filter_times (rfd);
ppr_filter_update_date_query (rfd->plugin_page);
LEAVE(" ");
}
/** This function is called whenever the save status is checked
* or unchecked. It will allow saving of the filter if required.
*
@ -1036,6 +1379,16 @@ gnc_ppr_filter_response_cb (GtkDialog* dialog,
auto fd = gnc_plugin_page_register_get_filter_data (rfd->plugin_page);
auto gsr = gnc_plugin_page_register_get_gsr (rfd->plugin_page);
if ((fd->start_time > 0 && fd->end_time > 0) && (fd->start_time > fd->end_time))
{
auto response = gnc_ok_cancel_dialog (GTK_WINDOW(rfd->dialog),
GTK_RESPONSE_CANCEL,
_("The Start date is after the End date.\n"
"Select Cancel to change dates.\n"));
if (response == GTK_RESPONSE_CANCEL)
return;
}
if (response != GTK_RESPONSE_OK)
{
/* Remove the old status match */
@ -1043,8 +1396,14 @@ gnc_ppr_filter_response_cb (GtkDialog* dialog,
gnc_plugin_register_set_enable_refresh (GNC_PLUGIN_PAGE_REGISTER(rfd->plugin_page), FALSE);
ppr_filter_update_status_query (rfd->plugin_page);
gnc_plugin_register_set_enable_refresh (GNC_PLUGIN_PAGE_REGISTER(rfd->plugin_page), TRUE);
fd->start_ap = rfd->original_start_ap;
fd->start_time = rfd->original_start_time;
fd->start_days = rfd->original_start_days;
fd->end_ap = rfd->original_end_ap;
fd->end_time = rfd->original_end_time;
fd->end_days = rfd->original_end_days;
fd->days = rfd->original_days;
fd->save_filter = rfd->original_save_filter;
ppr_filter_update_date_query (rfd->plugin_page);
@ -1067,6 +1426,30 @@ gnc_ppr_filter_response_cb (GtkDialog* dialog,
LEAVE(" ");
}
static GtkWidget *
setup_period_select (GtkBuilder *builder, gboolean start_type, const gchar *hbox_txt)
{
GtkWidget *period_select = GTK_WIDGET(gnc_period_select_new (start_type));
auto hbox = GTK_WIDGET(gtk_builder_get_object (builder, hbox_txt));
gtk_box_pack_start (GTK_BOX(hbox), period_select, TRUE, TRUE, 0);
gtk_widget_show (period_select);
gnc_period_select_set_active (GNC_PERIOD_SELECT(period_select), GNC_ACCOUNTING_PERIOD_TODAY);
gtk_widget_set_sensitive (GTK_WIDGET(period_select), FALSE);
return period_select;
}
static GtkWidget *
setup_date_edit (GtkBuilder *builder, const gchar *hbox_txt)
{
GtkWidget *date_widget = gnc_date_edit_new (gnc_time (nullptr), FALSE, FALSE);
auto hbox = GTK_WIDGET(gtk_builder_get_object (builder, hbox_txt));
gtk_box_pack_start (GTK_BOX(hbox), date_widget, TRUE, TRUE, 0);
gtk_widget_show (date_widget);
gtk_widget_set_sensitive (GTK_WIDGET(date_widget), FALSE);
return date_widget;
}
static void
ppr_filter_dialog_create (RegisterFilterDialog* rfd, FilterData *fd, Query *query)
{
@ -1074,10 +1457,10 @@ ppr_filter_dialog_create (RegisterFilterDialog* rfd, FilterData *fd, Query *quer
/* Create the dialog */
auto builder = gtk_builder_new();
gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade",
"days_adjustment");
gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade",
"filter_by_dialog");
gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade", "days_adjustment");
gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade", "start_days_adjustment");
gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade", "end_days_adjustment");
gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade", "filter_by_dialog");
auto dialog = GTK_WIDGET(gtk_builder_get_object (builder, "filter_by_dialog"));
rfd->dialog = dialog;
fd->dialog = rfd->dialog;
@ -1149,75 +1532,100 @@ ppr_filter_dialog_create (RegisterFilterDialog* rfd, FilterData *fd, Query *quer
rfd->table = table;
gtk_widget_set_sensitive (GTK_WIDGET(table), start_time || end_time);
rfd->start_date_choose = GTK_WIDGET(gtk_builder_get_object (builder, "start_date_choose"));
rfd->start_date_today = GTK_WIDGET(gtk_builder_get_object (builder, "start_date_today"));
rfd->end_date_choose = GTK_WIDGET(gtk_builder_get_object (builder, "end_date_choose"));
rfd->end_date_today = GTK_WIDGET(gtk_builder_get_object (builder, "end_date_today"));
rfd->start_earliest = GTK_WIDGET(gtk_builder_get_object (builder, "earliest_label"));
rfd->start_date_check = GTK_WIDGET(gtk_builder_get_object (builder, "start_date_check"));
rfd->start_relative_check = GTK_WIDGET(gtk_builder_get_object (builder, "start_relative_check"));
rfd->start_days_check = GTK_WIDGET(gtk_builder_get_object (builder, "start_days_check"));
bool sensitive;
{
rfd->start_relative = setup_period_select (builder, TRUE, "start_relative_hbox");
rfd->start_date = setup_date_edit (builder, "start_date_hbox");
rfd->start_days = GTK_WIDGET(gtk_builder_get_object (builder, "start_days_spin"));
/* Start date info */
if (start_time == 0)
{
button = GTK_WIDGET(gtk_builder_get_object(builder, "start_date_earliest"));
set_sensitive_start_widget (rfd, rfd->start_earliest, TRUE);
time_val = xaccQueryGetEarliestDateFound (query);
sensitive = false;
}
else
{
time_val = start_time;
if ((start_time >= gnc_time64_get_today_start()) &&
(start_time <= gnc_time64_get_today_end()))
rfd->original_start_ap = fd->start_ap;
if (fd->start_ap != GNC_ACCOUNTING_PERIOD_INVALID)
{
button = rfd->start_date_today;
sensitive = false;
set_sensitive_start_widget (rfd, rfd->start_relative, TRUE);
gnc_period_select_set_active (GNC_PERIOD_SELECT(rfd->start_relative), fd->start_ap);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(rfd->start_relative_check), TRUE);
}
else if (fd->start_days != 0)
{
set_sensitive_start_widget (rfd, rfd->start_days, TRUE);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(rfd->start_days_check), TRUE);
gtk_spin_button_set_value (GTK_SPIN_BUTTON(rfd->start_days), fd->start_days);
rfd->original_start_days = fd->start_days;
}
else
{
button = rfd->start_date_choose;
sensitive = true;
set_sensitive_start_widget (rfd, rfd->start_date, TRUE);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(rfd->start_date_check), TRUE);
}
time_val = start_time;
}
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), TRUE);
rfd->start_date = gnc_date_edit_new (gnc_time (nullptr), FALSE, FALSE);
auto hbox = GTK_WIDGET(gtk_builder_get_object (builder, "start_date_hbox"));
gtk_box_pack_start (GTK_BOX(hbox), rfd->start_date, TRUE, TRUE, 0);
gtk_widget_show (rfd->start_date);
gtk_widget_set_sensitive (GTK_WIDGET(rfd->start_date), bool_to_gboolean (sensitive));
g_signal_connect (G_OBJECT(rfd->start_relative), "changed",
G_CALLBACK(ppr_filter_relative_changed_cb), rfd);
if (time_val == 0)
time_val = gnc_time64_get_today_start();
gnc_date_edit_set_time (GNC_DATE_EDIT(rfd->start_date), time_val);
g_signal_connect (G_OBJECT(rfd->start_date), "date-changed",
G_CALLBACK(ppr_filter_gde_changed_cb), rfd);
}
rfd->end_latest = GTK_WIDGET(gtk_builder_get_object (builder, "latest_label"));
rfd->end_date_check = GTK_WIDGET(gtk_builder_get_object (builder, "end_date_check"));
rfd->end_relative_check = GTK_WIDGET(gtk_builder_get_object (builder, "end_relative_check"));
rfd->end_days_check = GTK_WIDGET(gtk_builder_get_object (builder, "end_days_check"));
{
rfd->end_relative = setup_period_select (builder, FALSE, "end_relative_hbox");
rfd->end_date = setup_date_edit (builder, "end_date_hbox");
rfd->end_days = GTK_WIDGET(gtk_builder_get_object (builder, "end_days_spin"));
/* End date info */
if (end_time == 0)
{
button = GTK_WIDGET(gtk_builder_get_object (builder, "end_date_latest"));
set_sensitive_end_widget (rfd, rfd->end_latest, TRUE);
time_val = xaccQueryGetLatestDateFound (query);
sensitive = false;
}
else
{
time_val = end_time;
if ((end_time >= gnc_time64_get_today_start()) &&
(end_time <= gnc_time64_get_today_end()))
rfd->original_end_ap = fd->end_ap;
if (fd->end_ap != GNC_ACCOUNTING_PERIOD_INVALID)
{
set_sensitive_end_widget (rfd, rfd->end_relative, TRUE);
gnc_period_select_set_active (GNC_PERIOD_SELECT(rfd->end_relative), fd->end_ap);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(rfd->end_relative_check), TRUE);
}
else if (fd->end_days != 0)
{
button = rfd->end_date_today;
sensitive = false;
set_sensitive_end_widget (rfd, rfd->end_days, TRUE);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(rfd->end_days_check), TRUE);
gtk_spin_button_set_value (GTK_SPIN_BUTTON(rfd->end_days), fd->end_days);
rfd->original_end_days = fd->end_days;
}
else
{
button = rfd->end_date_choose;
sensitive = true;
set_sensitive_end_widget (rfd, rfd->end_date, TRUE);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(rfd->end_date_check), TRUE);
}
time_val = end_time;
}
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(button), TRUE);
rfd->end_date = gnc_date_edit_new (gnc_time (nullptr), FALSE, FALSE);
auto hbox = GTK_WIDGET(gtk_builder_get_object (builder, "end_date_hbox"));
gtk_box_pack_start (GTK_BOX(hbox), rfd->end_date, TRUE, TRUE, 0);
gtk_widget_show (rfd->end_date);
gtk_widget_set_sensitive (GTK_WIDGET(rfd->end_date), bool_to_gboolean (sensitive));
g_signal_connect (G_OBJECT(rfd->end_relative), "changed",
G_CALLBACK(ppr_filter_relative_changed_cb), rfd);
if (time_val == 0)
time_val = gnc_time64_get_today_end();
gnc_date_edit_set_time (GNC_DATE_EDIT(rfd->end_date), time_val);
g_signal_connect (G_OBJECT(rfd->end_date), "date-changed",
G_CALLBACK(ppr_filter_gde_changed_cb), rfd);

@ -34,18 +34,22 @@
#define __GNC_PLUGIN_PAGE_REGISTER_FILTER_HPP
#include <gtk/gtk.h>
#include "gnc-split-reg.h"
#include "gnc-accounting-period.h"
#include "gnc-plugin-page.h"
#include <stdbool.h>
struct FilterData
{
GtkWidget* dialog;
cleared_match_t cleared_match;
time64 start_time;
time64 end_time;
int days;
bool save_filter;
GtkWidget* dialog;
cleared_match_t cleared_match;
GncAccountingPeriod start_ap;
time64 start_time;
int start_days;
GncAccountingPeriod end_ap;
time64 end_time;
int end_days;
int days;
bool save_filter;
};
void gnc_ppr_filter_set_tooltip (GncPluginPage* plugin_page, struct FilterData *fd);

@ -7,6 +7,16 @@
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
<object class="GtkAdjustment" id="end_days_adjustment">
<property name="upper">1100</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
<object class="GtkAdjustment" id="start_days_adjustment">
<property name="upper">1100</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
<object class="GtkDialog" id="filter_by_dialog">
<property name="can-focus">False</property>
<property name="border-width">6</property>
@ -97,7 +107,7 @@
<property name="can-focus">False</property>
<child>
<object class="GtkRadioButton" id="filter_show_days">
<property name="label" translatable="yes">Show _number of days</property>
<property name="label" translatable="yes">Show _from days ago</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
@ -155,18 +165,28 @@ If 0, all previous days included</property>
</packing>
</child>
<child>
<!-- n-columns=3 n-rows=7 -->
<!-- n-columns=2 n-rows=8 -->
<object class="GtkGrid" id="select_range_table">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-top">12</property>
<property name="row-spacing">3</property>
<property name="column-spacing">6</property>
<child>
<object class="GtkLabel" id="label847683">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label847682">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="halign">start</property>
<property name="label" translatable="yes" comments="Filter By Dialog, Date Tab, Start section">Start</property>
</object>
<packing>
@ -175,129 +195,139 @@ If 0, all previous days included</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="start_date_earliest">
<property name="label" translatable="yes">_Earliest</property>
<object class="GtkCheckButton" id="start_relative_check">
<property name="label" translatable="yes">Re_lative</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="halign">start</property>
<property name="use-underline">True</property>
<property name="draw-indicator">True</property>
<signal name="clicked" handler="gnc_ppr_filter_start_cb" swapped="no"/>
<signal name="toggled" handler="gnc_ppr_filter_start_toggle_cb" swapped="no"/>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="end_date_choose">
<property name="label" translatable="yes">Choo_se Date</property>
<object class="GtkCheckButton" id="start_date_check">
<property name="label" translatable="yes">C_hoose Date</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="halign">start</property>
<property name="use-underline">True</property>
<property name="draw-indicator">True</property>
<signal name="clicked" handler="gnc_ppr_filter_end_cb" swapped="no"/>
<signal name="toggled" handler="gnc_ppr_filter_start_toggle_cb" swapped="no"/>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">6</property>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="end_date_today">
<property name="label" translatable="yes">Toda_y</property>
<object class="GtkCheckButton" id="start_days_check">
<property name="label" translatable="yes">_Days ago</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="halign">start</property>
<property name="use-underline">True</property>
<property name="draw-indicator">True</property>
<property name="group">end_date_choose</property>
<signal name="clicked" handler="gnc_ppr_filter_end_cb" swapped="no"/>
<signal name="toggled" handler="gnc_ppr_filter_start_toggle_cb" swapped="no"/>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">5</property>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="end_date_latest">
<property name="label" translatable="yes">_Latest</property>
<object class="GtkBox" id="start_date_hbox">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="halign">start</property>
<property name="use-underline">True</property>
<property name="draw-indicator">True</property>
<property name="group">end_date_choose</property>
<signal name="clicked" handler="gnc_ppr_filter_end_cb" swapped="no"/>
<property name="can-focus">False</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">4</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label847683">
<object class="GtkBox" id="start_relative_hbox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="left-attach">0</property>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="start_days_spin">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="tooltip-text" translatable="yes">Valid range is 0 to 1100 days
If 0, all previous days included</property>
<property name="text" translatable="yes">0</property>
<property name="adjustment">start_days_adjustment</property>
<property name="numeric">True</property>
<signal name="value-changed" handler="gnc_ppr_filter_start_end_days_changed_cb" swapped="no"/>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label847684">
<object class="GtkCheckButton" id="end_relative_check">
<property name="label" translatable="yes">Rela_tive</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes" comments="Filter By Dialog, Date Tab, End section">End</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="use-underline">True</property>
<property name="draw-indicator">True</property>
<signal name="toggled" handler="gnc_ppr_filter_end_toggle_cb" swapped="no"/>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">4</property>
<property name="top-attach">5</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="start_date_choose">
<property name="label" translatable="yes">C_hoose Date</property>
<object class="GtkCheckButton" id="end_date_check">
<property name="label" translatable="yes">Choo_se Date</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="halign">start</property>
<property name="use-underline">True</property>
<property name="draw-indicator">True</property>
<property name="group">start_date_earliest</property>
<signal name="clicked" handler="gnc_ppr_filter_start_cb" swapped="no"/>
<signal name="toggled" handler="gnc_ppr_filter_end_toggle_cb" swapped="no"/>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
<property name="left-attach">0</property>
<property name="top-attach">6</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="start_date_today">
<property name="label" translatable="yes">_Today</property>
<object class="GtkCheckButton" id="end_days_check">
<property name="label" translatable="yes">Days a_go</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="halign">start</property>
<property name="use-underline">True</property>
<property name="draw-indicator">True</property>
<property name="group">start_date_earliest</property>
<signal name="clicked" handler="gnc_ppr_filter_start_cb" swapped="no"/>
<signal name="toggled" handler="gnc_ppr_filter_end_toggle_cb" swapped="no"/>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
<property name="left-attach">0</property>
<property name="top-attach">7</property>
</packing>
</child>
<child>
<object class="GtkBox" id="start_date_hbox">
<object class="GtkBox" id="end_date_hbox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
@ -305,12 +335,12 @@ If 0, all previous days included</property>
</child>
</object>
<packing>
<property name="left-attach">2</property>
<property name="top-attach">2</property>
<property name="left-attach">1</property>
<property name="top-attach">6</property>
</packing>
</child>
<child>
<object class="GtkBox" id="end_date_hbox">
<object class="GtkBox" id="end_relative_hbox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
@ -318,36 +348,63 @@ If 0, all previous days included</property>
</child>
</object>
<packing>
<property name="left-attach">2</property>
<property name="top-attach">6</property>
<property name="left-attach">1</property>
<property name="top-attach">5</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
<object class="GtkSpinButton" id="end_days_spin">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="tooltip-text" translatable="yes">Valid range is 0 to 1100 days
If 0, all previous days included</property>
<property name="text" translatable="yes">0</property>
<property name="adjustment">end_days_adjustment</property>
<property name="numeric">True</property>
<signal name="value-changed" handler="gnc_ppr_filter_start_end_days_changed_cb" swapped="no"/>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">7</property>
</packing>
</child>
<child>
<placeholder/>
<object class="GtkLabel" id="label847684">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="margin-top">12</property>
<property name="label" translatable="yes" comments="Filter By Dialog, Date Tab, End section">End</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">4</property>
</packing>
</child>
<child>
<placeholder/>
<object class="GtkLabel" id="earliest_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Earliest</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<placeholder/>
<object class="GtkLabel" id="latest_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="margin-top">12</property>
<property name="label" translatable="yes">Latest</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">4</property>
</packing>
</child>
<child>
<placeholder/>

Loading…
Cancel
Save