static gint
_enabled_comparator(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data)
{
    GncSxListTreeModelAdapter *adapter = GNC_SX_LIST_TREE_MODEL_ADAPTER(user_data);
    GncSxInstances *a_inst, *b_inst;

    a_inst = gsltma_get_sx_instances_from_orig_iter(adapter, a);
    b_inst = gsltma_get_sx_instances_from_orig_iter(adapter, b);

    if (xaccSchedXactionGetEnabled(a_inst->sx) && !xaccSchedXactionGetEnabled(b_inst->sx)) return 1;
    if (!xaccSchedXactionGetEnabled(a_inst->sx) && xaccSchedXactionGetEnabled(b_inst->sx)) return -1;
    return 0;
}
static void
gsltma_populate_tree_store(GncSxListTreeModelAdapter *model)
{
    GtkTreeIter iter;
    GList *list;

    for (list = model->instances->sx_instance_list; list != NULL; list = list->next)
    {
        GncSxInstances *instances = (GncSxInstances*)list->data;
        gchar *frequency_str;
        char last_occur_date_buf[MAX_DATE_LENGTH+1];
        char next_occur_date_buf[MAX_DATE_LENGTH+1];

        frequency_str = recurrenceListToCompactString(gnc_sx_get_schedule(instances->sx));

        _format_conditional_date(xaccSchedXactionGetLastOccurDate(instances->sx),
                                 last_occur_date_buf, MAX_DATE_LENGTH);
        _format_conditional_date(&instances->next_instance_date,
                                 next_occur_date_buf, MAX_DATE_LENGTH);

        gtk_tree_store_append(model->orig, &iter, NULL);
        gtk_tree_store_set(model->orig, &iter,
                           SXLTMA_COL_NAME, xaccSchedXactionGetName(instances->sx),
                           SXLTMA_COL_ENABLED, xaccSchedXactionGetEnabled(instances->sx),
                           SXLTMA_COL_FREQUENCY, frequency_str,
                           SXLTMA_COL_LAST_OCCUR, last_occur_date_buf,
                           SXLTMA_COL_NEXT_OCCUR, next_occur_date_buf,
                           -1);
        g_free(frequency_str);
    }
}
static void
gsidca_instances_added_cb(GncSxInstanceModel *model, SchedXaction *sx_added, gpointer user_data)
{
    GncSxInstanceDenseCalAdapter *adapter = GNC_SX_INSTANCE_DENSE_CAL_ADAPTER(user_data);
    g_debug("instance added\n");
    if (xaccSchedXactionGetEnabled(sx_added))
    {
        g_signal_emit_by_name(adapter, "added", GPOINTER_TO_UINT(sx_added));
    }
}
static void
gsidca_instances_updated_cb(GncSxInstanceModel *model, SchedXaction *sx_updated, gpointer user_data)
{
    GncSxInstanceDenseCalAdapter *adapter = GNC_SX_INSTANCE_DENSE_CAL_ADAPTER(user_data);
    gnc_sx_instance_model_update_sx_instances(model, sx_updated);
    g_debug("instances updated\n");
    if (xaccSchedXactionGetEnabled(sx_updated))
    {
        g_signal_emit_by_name(adapter, "update", GPOINTER_TO_UINT((gpointer)sx_updated));
    }
    else
    {
        g_signal_emit_by_name(adapter, "removing", GPOINTER_TO_UINT((gpointer)sx_updated));
    }
}
static GList*
gsidca_get_contained(GncDenseCalModel *model)
{
    GncSxInstanceDenseCalAdapter *adapter = GNC_SX_INSTANCE_DENSE_CAL_ADAPTER(model);
    //"removing return gnc_g_list_map(instances->sxes, sx_to_tag, null);
    GList *list = NULL, *sxes;
    for (sxes = adapter->instances->sx_instance_list; sxes != NULL; sxes = sxes->next)
    {
        GncSxInstances *sx_instances = (GncSxInstances*)sxes->data;
        if (xaccSchedXactionGetEnabled(sx_instances->sx))
        {
            list = g_list_append(list, GUINT_TO_POINTER(GPOINTER_TO_UINT(sx_instances->sx)));
        }
    }
    return list;
}
GncSxInstanceModel*
gnc_sx_get_instances(GDate *range_end, gboolean include_disabled)
{
    GList *all_sxes = gnc_book_get_schedxactions(gnc_get_current_book())->sx_list;
    GncSxInstanceModel *instances;

    g_assert(range_end != NULL);
    g_assert(g_date_valid(range_end));

    instances = gnc_sx_instance_model_new();
    instances->include_disabled = include_disabled;
    instances->range_end = *range_end;

    if (include_disabled)
    {
        instances->sx_instance_list = gnc_g_list_map(all_sxes, (GncGMapFunc)_gnc_sx_gen_instances, range_end);
    }
    else
    {
        GList *sx_iter = g_list_first(all_sxes);
        GList *enabled_sxes = NULL;

        for (; sx_iter != NULL; sx_iter = sx_iter->next)
        {
            SchedXaction *sx = (SchedXaction*)sx_iter->data;
            if (xaccSchedXactionGetEnabled(sx))
            {
                enabled_sxes = g_list_append(enabled_sxes, sx);
            }
        }
        instances->sx_instance_list = gnc_g_list_map(enabled_sxes, (GncGMapFunc)_gnc_sx_gen_instances, range_end);
        g_list_free(enabled_sxes);
    }

    return instances;
}
static void
_gnc_sx_instance_event_handler(QofInstance *ent, QofEventId event_type, gpointer user_data, gpointer evt_data)
{
    GncSxInstanceModel *instances = GNC_SX_INSTANCE_MODEL(user_data);

    /* selection rules {
    //   (gnc_collection_get_schedxaction_list(book), GNC_EVENT_ITEM_ADDED)
    //   (gnc_collection_get_schedxaction_list(book), GNC_EVENT_ITEM_REMOVED)
    //   (GNC_IS_SX(ent), QOF_EVENT_MODIFIED)
    // } */
    if (!(GNC_IS_SX(ent) || GNC_IS_SXES(ent)))
        return;

    if (GNC_IS_SX(ent))
    {
        SchedXaction *sx;
        gboolean sx_is_in_model = FALSE;

        sx = GNC_SX(ent);
        // only send `updated` if it's actually in the model
        sx_is_in_model = (g_list_find_custom(instances->sx_instance_list, sx, (GCompareFunc)_gnc_sx_instance_find_by_sx) != NULL);
        if (event_type & QOF_EVENT_MODIFY)
        {
            if (sx_is_in_model)
            {
                if (instances->include_disabled || xaccSchedXactionGetEnabled(sx))
                {
                    g_signal_emit_by_name(instances, "updated", (gpointer)sx);
                }
                else
                {
                    /* the sx was enabled but is now disabled */
                    g_signal_emit_by_name(instances, "removing", (gpointer)sx);
                }
            }
            else
            {
                /* determine if this is a legitimate SX or just a "one-off" / being created */
                GList *all_sxes = gnc_book_get_schedxactions(gnc_get_current_book())->sx_list;
                if (g_list_find(all_sxes, sx) && (!instances->include_disabled && xaccSchedXactionGetEnabled(sx)))
                {
                    /* it's moved from disabled to enabled, add the instances */
                    instances->sx_instance_list
                    = g_list_append(instances->sx_instance_list,
                                    _gnc_sx_gen_instances((gpointer)sx, (gpointer) & instances->range_end));
                    g_signal_emit_by_name(instances, "added", (gpointer)sx);
                }
            }
        }
        /* else { unsupported event type; ignore } */
    }
    else if (GNC_IS_SXES(ent))
    {
        SchedXactions *sxes = GNC_SXES(ent);
        SchedXaction *sx = GNC_SX(evt_data);

        sxes = NULL;
        if (event_type & GNC_EVENT_ITEM_REMOVED)
        {
            GList *instances_link;
            instances_link = g_list_find_custom(instances->sx_instance_list, sx, (GCompareFunc)_gnc_sx_instance_find_by_sx);
            if (instances_link != NULL)
            {
                g_signal_emit_by_name(instances, "removing", (gpointer)sx);
            }
            else if (instances->include_disabled)
            {
                g_warning("could not remove instances that do not exist in the model");
            }
        }
        else if (event_type & GNC_EVENT_ITEM_ADDED)
        {
            if (instances->include_disabled || xaccSchedXactionGetEnabled(sx))
            {
                /* generate instances, add to instance list, emit update. */
                instances->sx_instance_list
                = g_list_append(instances->sx_instance_list,
                                _gnc_sx_gen_instances((gpointer)sx, (gpointer) & instances->range_end));
                g_signal_emit_by_name(instances, "added", (gpointer)sx);
            }
        }
        /* else { g_critical("unsupported event type [%d]\n", event_type); } */
    }
}