int recurrenceCmp(Recurrence *a, Recurrence *b) { PeriodType period_a, period_b; int a_order_index, b_order_index; g_return_val_if_fail(a != NULL && b != NULL, 0); g_return_val_if_fail(a != NULL, 1); g_return_val_if_fail(b != NULL, -1); period_a = recurrenceGetPeriodType(a); period_b = recurrenceGetPeriodType(b); a_order_index = cmp_order_indexes[period_a]; b_order_index = cmp_order_indexes[period_b]; if (a_order_index != b_order_index) { return a_order_index - b_order_index; } else if (a_order_index == cmp_order_indexes[PERIOD_MONTH]) { // re-order intra-month options: a_order_index = cmp_monthly_order_indexes[period_a]; b_order_index = cmp_monthly_order_indexes[period_b]; g_assert(a_order_index != -1 && b_order_index != -1); if (a_order_index != b_order_index) return a_order_index - b_order_index; } /* else { the basic periods are equal; compare the multipliers } */ { int a_mult, b_mult; a_mult = recurrenceGetMultiplier(a); b_mult = recurrenceGetMultiplier(b); return a_mult - b_mult; } }
static void _fixup_recurrence_start_dates(const GDate *sx_start_date, GList *schedule) { GList *iter; for (iter = schedule; iter != NULL; iter = iter->next) { Recurrence *r; GDate start, next; r = (Recurrence*)iter->data; start = *sx_start_date; g_date_subtract_days(&start, 1); g_date_clear(&next, 1); recurrenceNextInstance(r, &start, &next); g_return_if_fail(g_date_valid(&next)); { gchar date_str[128]; gchar *sched_str; g_date_strftime(date_str, 127, "%x", &next); sched_str = recurrenceToString(r); g_debug("setting recurrence [%s] start date to [%s]", sched_str, date_str); g_free(sched_str); } recurrenceSet(r, recurrenceGetMultiplier(r), recurrenceGetPeriodType(r), &next, recurrenceGetWeekendAdjust(r)); } if (g_list_length(schedule) == 1 && recurrenceGetPeriodType((Recurrence*)g_list_nth_data(schedule, 0)) == PERIOD_ONCE) { char date_buf[128]; Recurrence *fixup = (Recurrence*)g_list_nth_data(schedule, 0); g_date_strftime(date_buf, 127, "%x", sx_start_date); recurrenceSet(fixup, 1, PERIOD_ONCE, sx_start_date, WEEKEND_ADJ_NONE); g_debug("fixed up period=ONCE Recurrence to date [%s]", date_buf); } }
static void _weekly_list_to_compact_string(GList *rs, GString *buf) { int dow_idx; char dow_present_bits = 0; int multiplier = -1; for (; rs != NULL; rs = rs->next) { Recurrence *r = (Recurrence*)rs->data; GDate date = recurrenceGetDate(r); GDateWeekday dow = g_date_get_weekday(&date); if (dow == G_DATE_BAD_WEEKDAY) { g_critical("bad weekday pretty-printing recurrence"); continue; } dow_present_bits |= (1 << (dow % 7)); // there's not necessarily a single multiplier, but for all intents // and purposes this will be fine. multiplier = recurrenceGetMultiplier(r); } g_string_printf(buf, "%s", _("Weekly")); if (multiplier > 1) { /* translators: %u is the recurrence multipler, i.e. this event should occur every %u'th week. */ g_string_append_printf(buf, _(" (x%u)"), multiplier); } g_string_append_printf(buf, ": "); // @@fixme: this is only Sunday-started weeks. :/ for (dow_idx = 0; dow_idx < 7; dow_idx++) { if ((dow_present_bits & (1 << dow_idx)) != 0) { gchar dbuf[10]; gnc_dow_abbrev(dbuf, 10, dow_idx); g_string_append_unichar(buf, g_utf8_get_char(dbuf)); } else { g_string_append_printf(buf, "-"); } } }
/* Mult of zero is usually not valid, but it gets regularized to 1, so the effect is just that we end up testing mult of 1 twice, plus the regularization. */ static void test_all() { Recurrence r; GDate d_start, d_start_reg; GDate d_ref, d_next; guint16 mult, mult_reg; PeriodType pt, pt_reg; WeekendAdjust wadj, wadj_reg; gint32 j1, j2; gint i_ref; for (pt = PERIOD_ONCE; pt < NUM_PERIOD_TYPES; pt++) { for (wadj = WEEKEND_ADJ_NONE; wadj < NUM_WEEKEND_ADJS; wadj++) { for (j1 = JULIAN_START; j1 < JULIAN_START + NUM_DATES_TO_TEST; j1++) { g_date_set_julian(&d_start, j1); for (i_ref = 0; i_ref < NUM_DATES_TO_TEST_REF; i_ref++) { j2 = (guint32) get_random_int_in_range(1, 1 << 19); g_date_set_julian(&d_ref, j2); for (mult = 0; mult < NUM_MULT_TO_TEST; mult++) { recurrenceSet(&r, mult, pt, &d_start, wadj); pt_reg = recurrenceGetPeriodType(&r); d_start_reg = recurrenceGetDate(&r); mult_reg = recurrenceGetMultiplier(&r); wadj_reg = recurrenceGetWeekendAdjust(&r); recurrenceNextInstance(&r, &d_ref, &d_next); check_valid(&d_next, &d_ref, &d_start_reg, mult_reg, pt_reg, wadj_reg); } } } } } }
static void _setup_weekly_recurrence(GncFrequency *gf, Recurrence *r) { GDate recurrence_date; GDateWeekday day_of_week; guint multiplier = recurrenceGetMultiplier(r); const char *checkbox_widget_name; GtkWidget *weekday_checkbox; GtkWidget *multipler_spin = glade_xml_get_widget(gf->gxml, "weekly_spin"); gtk_spin_button_set_value(GTK_SPIN_BUTTON(multipler_spin), multiplier); recurrence_date = recurrenceGetDate(r); day_of_week = g_date_get_weekday(&recurrence_date); g_assert(day_of_week >= G_DATE_MONDAY && day_of_week <= G_DATE_SUNDAY); // this `mod 7' is explicit knowledge of the values of (monday=1)-based // GDateWeekday, vs. our (sunday=0)-based checkbox names array. checkbox_widget_name = CHECKBOX_NAMES[day_of_week % 7]; weekday_checkbox = glade_xml_get_widget(gf->gxml, checkbox_widget_name); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(weekday_checkbox), TRUE); }
void gnc_recurrence_set(GncRecurrence *gr, const Recurrence *r) { PeriodType pt; guint mult; GDate start; g_return_if_fail(gr && r); pt = recurrenceGetPeriodType(r); mult = recurrenceGetMultiplier(r); start = recurrenceGetDate(r); gtk_spin_button_set_value(gr->gsb_mult, (gdouble) mult); // is there some better way? { time64 t; t = gnc_time64_get_day_start_gdate (&start); gnc_date_edit_set_time (GNC_DATE_EDIT(gr->gde_start), t); } set_pt_ui(gr, pt); }
void gnc_frequency_setup(GncFrequency *gf, GList *recurrences, const GDate *start_date) { gboolean made_changes = FALSE; // setup start-date, if present if (start_date != NULL && g_date_valid(start_date)) { gnc_date_edit_set_gdate(gf->startDate, start_date); made_changes = TRUE; } if (recurrences == NULL) { goto maybe_signal; // return... } if (g_list_length(recurrences) > 1) { if (recurrenceListIsWeeklyMultiple(recurrences)) { for (; recurrences != NULL; recurrences = recurrences->next) { _setup_weekly_recurrence(gf, (Recurrence*)recurrences->data); } gtk_notebook_set_current_page(gf->nb, PAGE_WEEKLY); gtk_combo_box_set_active(gf->freqComboBox, PAGE_WEEKLY); } else if (recurrenceListIsSemiMonthly(recurrences)) { Recurrence *first, *second; GtkWidget *multiplier_spin; GtkWidget *dom_combobox; first = (Recurrence*)g_list_nth_data(recurrences, 0); second = (Recurrence*)g_list_nth_data(recurrences, 1); multiplier_spin = glade_xml_get_widget(gf->gxml, "semimonthly_spin"); gtk_spin_button_set_value(GTK_SPIN_BUTTON(multiplier_spin), recurrenceGetMultiplier(first)); dom_combobox = glade_xml_get_widget(gf->gxml, "semimonthly_first"); gtk_combo_box_set_active(GTK_COMBO_BOX(dom_combobox), _get_monthly_combobox_index(first)); dom_combobox = glade_xml_get_widget(gf->gxml, "semimonthly_first_weekend"); gtk_combo_box_set_active(GTK_COMBO_BOX(dom_combobox), recurrenceGetWeekendAdjust(first)); dom_combobox = glade_xml_get_widget(gf->gxml, "semimonthly_second"); gtk_combo_box_set_active(GTK_COMBO_BOX(dom_combobox), _get_monthly_combobox_index(second)); dom_combobox = glade_xml_get_widget(gf->gxml, "semimonthly_second_weekend"); gtk_combo_box_set_active(GTK_COMBO_BOX(dom_combobox), recurrenceGetWeekendAdjust(second)); gtk_notebook_set_current_page(gf->nb, PAGE_SEMI_MONTHLY); gtk_combo_box_set_active(gf->freqComboBox, PAGE_SEMI_MONTHLY); } else { g_error("unknown composite recurrence with [%d] entries", g_list_length(recurrences)); } } else { Recurrence *r = (Recurrence*)recurrences->data; g_debug("recurrence period [%d]", recurrenceGetPeriodType(r)); switch (recurrenceGetPeriodType(r)) { case PERIOD_ONCE: { GDate recurrence_date = recurrenceGetDate(r); if (g_date_compare(start_date, &recurrence_date) != 0) { char start_date_str[128], recur_date_str[128]; g_date_strftime(start_date_str, 127, "%x", start_date); g_date_strftime(recur_date_str, 127, "%x", &recurrence_date); g_critical("start_date [%s] != recurrence_date [%s]", start_date_str, recur_date_str); } gtk_notebook_set_current_page(gf->nb, PAGE_ONCE); gtk_combo_box_set_active(gf->freqComboBox, PAGE_ONCE); } break; case PERIOD_DAY: { guint multiplier; GtkWidget *spin_button; multiplier = recurrenceGetMultiplier(r); spin_button = glade_xml_get_widget(gf->gxml, "daily_spin"); gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_button), multiplier); made_changes = TRUE; gtk_notebook_set_current_page(gf->nb, PAGE_DAILY); gtk_combo_box_set_active(gf->freqComboBox, PAGE_DAILY); } break; case PERIOD_WEEK: { _setup_weekly_recurrence(gf, r); gtk_notebook_set_current_page(gf->nb, PAGE_WEEKLY); gtk_combo_box_set_active(gf->freqComboBox, PAGE_WEEKLY); } break; case PERIOD_END_OF_MONTH: case PERIOD_MONTH: case PERIOD_YEAR: case PERIOD_LAST_WEEKDAY: case PERIOD_NTH_WEEKDAY: { guint multiplier; GtkWidget *multipler_spin, *day_of_month, *weekend_mode; multipler_spin = glade_xml_get_widget(gf->gxml, "monthly_spin"); multiplier = recurrenceGetMultiplier(r); if (recurrenceGetPeriodType(r) == PERIOD_YEAR) multiplier *= 12; gtk_spin_button_set_value(GTK_SPIN_BUTTON(multipler_spin), multiplier); day_of_month = glade_xml_get_widget(gf->gxml, "monthly_day"); gtk_combo_box_set_active(GTK_COMBO_BOX(day_of_month), _get_monthly_combobox_index(r)); weekend_mode = glade_xml_get_widget(gf->gxml, "monthly_weekend"); gtk_combo_box_set_active(GTK_COMBO_BOX(weekend_mode), recurrenceGetWeekendAdjust(r)); gtk_notebook_set_current_page(gf->nb, PAGE_MONTHLY); gtk_combo_box_set_active(gf->freqComboBox, PAGE_MONTHLY); } break; default: g_error("unknown recurrence period type [%d]", recurrenceGetPeriodType(r)); break; } } maybe_signal: if (made_changes) g_signal_emit_by_name(gf, "changed"); }
gchar* recurrenceListToCompactString(GList *rs) { GString *buf = g_string_sized_new(16); if (g_list_length(rs) == 0) { g_string_printf(buf, "%s", _("None")); goto rtn; } if (g_list_length(rs) > 1) { if (recurrenceListIsWeeklyMultiple(rs)) { _weekly_list_to_compact_string(rs, buf); } else if (recurrenceListIsSemiMonthly(rs)) { Recurrence *first, *second; first = (Recurrence*)g_list_nth_data(rs, 0); second = (Recurrence*)g_list_nth_data(rs, 1); if (recurrenceGetMultiplier(first) != recurrenceGetMultiplier(second)) { g_warning("lying about non-equal semi-monthly recurrence multiplier: %d vs. %d", recurrenceGetMultiplier(first), recurrenceGetMultiplier(second)); } g_string_printf(buf, "%s", _("Semi-monthly")); g_string_append_printf(buf, " "); if (recurrenceGetMultiplier(first) > 1) { /* translators: %u is the recurrence multiplier number */ g_string_append_printf(buf, _(" (x%u)"), recurrenceGetMultiplier(first)); } g_string_append_printf(buf, ": "); _monthly_append_when(first, buf); g_string_append_printf(buf, ", "); _monthly_append_when(second, buf); } else { /* translators: %d is the number of Recurrences in the list. */ g_string_printf(buf, _("Unknown, %d-size list."), g_list_length(rs)); } } else { Recurrence *r = (Recurrence*)g_list_nth_data(rs, 0); guint multiplier = recurrenceGetMultiplier(r); switch (recurrenceGetPeriodType(r)) { case PERIOD_ONCE: { g_string_printf(buf, "%s", _("Once")); } break; case PERIOD_DAY: { g_string_printf(buf, "%s", _("Daily")); if (multiplier > 1) { /* translators: %u is the recurrence multiplier. */ g_string_append_printf(buf, _(" (x%u)"), multiplier); } } break; case PERIOD_WEEK: { _weekly_list_to_compact_string(rs, buf); } break; case PERIOD_MONTH: case PERIOD_END_OF_MONTH: case PERIOD_LAST_WEEKDAY: { g_string_printf(buf, "%s", _("Monthly")); if (multiplier > 1) { /* translators: %u is the recurrence multiplier. */ g_string_append_printf(buf, _(" (x%u)"), multiplier); } g_string_append_printf(buf, ": "); _monthly_append_when(r, buf); } break; case PERIOD_NTH_WEEKDAY: { //g_warning("nth weekday not handled"); //g_string_printf(buf, "@fixme: nth weekday not handled"); g_string_printf(buf, "%s", _("Monthly")); if (multiplier > 1) { /* translators: %u is the recurrence multiplier. */ g_string_append_printf(buf, _(" (x%u)"), multiplier); } g_string_append_printf(buf, ": "); _monthly_append_when(r, buf); } break; case PERIOD_YEAR: { g_string_printf(buf, "%s", _("Yearly")); if (multiplier > 1) { /* translators: %u is the recurrence multiplier. */ g_string_append_printf(buf, _(" (x%u)"), multiplier); } } break; default: g_error("unknown Recurrence period %d", recurrenceGetPeriodType(r)); break; } } rtn: return g_string_free(buf, FALSE); }