mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Merge Bob Fewell's 'bug799179' into stable.
This commit is contained in:
commit
ef094082b1
@ -63,6 +63,7 @@ G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_GUI_SX;
|
||||
#define GNC_PREF_SET_REVIEW "review-transactions"
|
||||
#define GNC_PREF_SLR_SORT_COL "sort-column"
|
||||
#define GNC_PREF_SLR_SORT_ASC "sort-ascending"
|
||||
#define GNC_PREF_SLR_SORT_DEPTH "sort-depth"
|
||||
|
||||
struct _GncSxSinceLastRunDialog
|
||||
{
|
||||
@ -74,6 +75,7 @@ struct _GncSxSinceLastRunDialog
|
||||
GList *created_txns;
|
||||
|
||||
GtkCellEditable *temp_ce; // used when editing values
|
||||
gint sort_selection_depth; // used when sorting transaction column
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@ -103,10 +105,7 @@ static void gnc_sx_slr_tree_model_adapter_dispose (GObject *obj);
|
||||
static void gnc_sx_slr_tree_model_adapter_finalize (GObject *obj);
|
||||
|
||||
GncSxInstanceModel* gnc_sx_slr_tree_model_adapter_get_instance_model (GncSxSlrTreeModelAdapter *slr_model);
|
||||
GncSxInstances* gnc_sx_slr_tree_model_adapter_get_sx_instances (GncSxSlrTreeModelAdapter *model, GtkTreeIter *iter);
|
||||
static GncSxInstances* _gnc_sx_slr_tree_model_adapter_get_sx_instances (GncSxSlrTreeModelAdapter *model,
|
||||
GtkTreeIter *iter,
|
||||
gboolean check_depth);
|
||||
|
||||
/** @return null if the iter is not actually an GncSxInstance. **/
|
||||
GncSxInstance* gnc_sx_slr_model_get_instance (GncSxSlrTreeModelAdapter *model, GtkTreeIter *iter);
|
||||
static GncSxInstance* _gnc_sx_slr_model_get_instance (GncSxSlrTreeModelAdapter *model,
|
||||
@ -124,7 +123,7 @@ void gnc_sx_slr_model_effect_change (GncSxSlrTreeModelAdapter *model,
|
||||
GList **created_transaction_guids,
|
||||
GList **creation_errors);
|
||||
|
||||
GtkTreeModel* gnc_sx_get_slr_state_model(void);
|
||||
GtkTreeModel* gnc_sx_get_slr_state_model (void);
|
||||
|
||||
#define GNC_TYPE_SX_SLR_TREE_MODEL_ADAPTER (gnc_sx_slr_tree_model_adapter_get_type ())
|
||||
#define GNC_SX_SLR_TREE_MODEL_ADAPTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_SX_SLR_TREE_MODEL_ADAPTER, GncSxSlrTreeModelAdapter))
|
||||
@ -141,6 +140,12 @@ static void close_handler (gpointer user_data);
|
||||
static void dialog_destroy_cb (GtkWidget *object, GncSxSinceLastRunDialog *app_dialog);
|
||||
static void dialog_response_cb (GtkDialog *dialog, gint response_id, GncSxSinceLastRunDialog *app_dialog);
|
||||
|
||||
#define debug_path(fn, text, path) {\
|
||||
gchar *path_string = gtk_tree_path_to_string (path);\
|
||||
fn("%s %s", text, path_string? path_string : "NULL");\
|
||||
g_free (path_string);\
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
static void
|
||||
@ -334,6 +339,7 @@ gsslrtma_proxy_rows_reordered (GtkTreeModel *treemodel,
|
||||
enum
|
||||
{
|
||||
SLR_MODEL_COL_NAME = 0,
|
||||
SLR_MODEL_COL_INSTANCE_PTR,
|
||||
SLR_MODEL_COL_INSTANCE_STATE,
|
||||
SLR_MODEL_COL_VARAIBLE_VALUE,
|
||||
SLR_MODEL_COL_INSTANCE_VISIBILITY,
|
||||
@ -345,11 +351,11 @@ enum
|
||||
static void
|
||||
gnc_sx_slr_tree_model_adapter_init (GncSxSlrTreeModelAdapter *adapter)
|
||||
{
|
||||
// columns: thing-name, instance-state, variable-value, instance-visible, variable-visible, instance_state_sensitivity, date
|
||||
// at depth=0: <sx>, N/A, N/A, N/A N/A, N/A N/A
|
||||
// at depth=1: <instance>, <state>, N/A, <valid>, N/A, <valid> <date>
|
||||
// at depth=2: <variable>, N/A, <value>, N/A, <valid>, N/A N/A
|
||||
adapter->real = gtk_tree_store_new (7, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_INT64);
|
||||
// columns: thing-name, ptr, instance-state, variable-value, instance-visible, variable-visible, instance_state_sensitivity, date
|
||||
// at depth=0: <sx>, instances, N/A, N/A N/A, N/A N/A N/A
|
||||
// at depth=1: <instance>, instance, <state>, N/A, <valid>, N/A, <valid> <date>
|
||||
// at depth=2: <variable>, var, N/A, <value>, N/A, <valid>, N/A N/A
|
||||
adapter->real = gtk_tree_store_new (8, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_INT64);
|
||||
|
||||
g_signal_connect (adapter->real, "row-changed", G_CALLBACK(gsslrtma_proxy_row_changed), adapter);
|
||||
g_signal_connect (adapter->real, "row-deleted", G_CALLBACK(gsslrtma_proxy_row_deleted), adapter);
|
||||
@ -454,8 +460,16 @@ gsslrtma_populate_tree_store (GncSxSlrTreeModelAdapter *model)
|
||||
SLR_MODEL_COL_VARIABLE_VISIBILITY, FALSE,
|
||||
SLR_MODEL_COL_INSTANCE_STATE_SENSITIVITY, FALSE,
|
||||
SLR_MODEL_COL_INSTANCE_DATE, INT64_MAX,
|
||||
SLR_MODEL_COL_INSTANCE_PTR, instances,
|
||||
-1);
|
||||
|
||||
if (qof_log_check (GNC_MOD_GUI_SX, QOF_LOG_DEBUG))
|
||||
{
|
||||
gchar *path_str = gtk_tree_path_to_string (gtk_tree_model_get_path (GTK_TREE_MODEL(model->real), &sx_tree_iter));
|
||||
DEBUG("Add schedule [%s], instances %p at path [%s]", xaccSchedXactionGetName (instances->sx), instances, path_str);
|
||||
g_free (path_str);
|
||||
}
|
||||
|
||||
// Insert instance information
|
||||
{
|
||||
GList *inst_iter;
|
||||
@ -481,6 +495,7 @@ gsslrtma_populate_tree_store (GncSxSlrTreeModelAdapter *model)
|
||||
SLR_MODEL_COL_VARIABLE_VISIBILITY, FALSE,
|
||||
SLR_MODEL_COL_INSTANCE_STATE_SENSITIVITY, inst->state != SX_INSTANCE_STATE_CREATED,
|
||||
SLR_MODEL_COL_INSTANCE_DATE, t,
|
||||
SLR_MODEL_COL_INSTANCE_PTR, inst,
|
||||
-1);
|
||||
|
||||
// Insert variable information
|
||||
@ -521,6 +536,7 @@ gsslrtma_populate_tree_store (GncSxSlrTreeModelAdapter *model)
|
||||
SLR_MODEL_COL_VARIABLE_VISIBILITY, TRUE,
|
||||
SLR_MODEL_COL_INSTANCE_STATE_SENSITIVITY, FALSE,
|
||||
SLR_MODEL_COL_INSTANCE_DATE, INT64_MAX,
|
||||
SLR_MODEL_COL_INSTANCE_PTR, var,
|
||||
-1);
|
||||
g_string_free (tmp_str, TRUE);
|
||||
}
|
||||
@ -543,30 +559,6 @@ gnc_sx_slr_tree_model_adapter_get_instance_model (GncSxSlrTreeModelAdapter *slr_
|
||||
return slr_model->instances;
|
||||
}
|
||||
|
||||
GncSxInstances*
|
||||
gnc_sx_slr_tree_model_adapter_get_sx_instances (GncSxSlrTreeModelAdapter *model, GtkTreeIter *iter)
|
||||
{
|
||||
return _gnc_sx_slr_tree_model_adapter_get_sx_instances (model, iter, TRUE);
|
||||
}
|
||||
|
||||
static GncSxInstances*
|
||||
_gnc_sx_slr_tree_model_adapter_get_sx_instances (GncSxSlrTreeModelAdapter *model, GtkTreeIter *iter, gboolean check_depth)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
gint *indices, index;
|
||||
path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), iter);
|
||||
if (check_depth && gtk_tree_path_get_depth (path) != 1)
|
||||
{
|
||||
gtk_tree_path_free (path);
|
||||
return NULL;
|
||||
}
|
||||
indices = gtk_tree_path_get_indices (path);
|
||||
index = indices[0];
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
return (GncSxInstances*)g_list_nth_data (gnc_sx_instance_model_get_sx_instances_list (model->instances), index);
|
||||
}
|
||||
|
||||
GncSxInstance*
|
||||
gnc_sx_slr_model_get_instance (GncSxSlrTreeModelAdapter *model, GtkTreeIter *iter)
|
||||
{
|
||||
@ -576,33 +568,51 @@ gnc_sx_slr_model_get_instance (GncSxSlrTreeModelAdapter *model, GtkTreeIter *ite
|
||||
static GncSxInstance*
|
||||
_gnc_sx_slr_model_get_instance (GncSxSlrTreeModelAdapter *model, GtkTreeIter *iter, gboolean check_depth)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
GtkTreePath *model_path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), iter);
|
||||
gint *indices, instances_index, instance_index;
|
||||
GncSxInstances *instances;
|
||||
path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), iter);
|
||||
if (check_depth && gtk_tree_path_get_depth (path) != 2)
|
||||
GncSxInstance *instance = NULL;
|
||||
GtkTreeIter new_iter;
|
||||
|
||||
debug_path (DEBUG, "model path is:", model_path);
|
||||
|
||||
if (check_depth && gtk_tree_path_get_depth (model_path) != 2)
|
||||
{
|
||||
gtk_tree_path_free (path);
|
||||
PWARN("path depth not equal to 2");
|
||||
gtk_tree_path_free (model_path);
|
||||
return NULL;
|
||||
}
|
||||
indices = gtk_tree_path_get_indices (path);
|
||||
|
||||
if (gtk_tree_path_get_depth (model_path) == 1)
|
||||
{
|
||||
PWARN("path depth equal to 1");
|
||||
gtk_tree_path_free (model_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
indices = gtk_tree_path_get_indices (model_path);
|
||||
instances_index = indices[0];
|
||||
instance_index = indices[1];
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
instances = (GncSxInstances*)g_list_nth_data (gnc_sx_instance_model_get_sx_instances_list (model->instances), instances_index);
|
||||
if (instance_index < 0 || instance_index >= g_list_length (instances->instance_list))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
gtk_tree_path_free (model_path);
|
||||
|
||||
return (GncSxInstance*)g_list_nth_data (instances->instance_list, instance_index);
|
||||
model_path = gtk_tree_path_new_from_indices (instances_index, instance_index, -1);
|
||||
|
||||
debug_path (DEBUG, "new model path is:", model_path);
|
||||
|
||||
if (gtk_tree_model_get_iter (GTK_TREE_MODEL(model), &new_iter, model_path))
|
||||
gtk_tree_model_get (GTK_TREE_MODEL(model), &new_iter, SLR_MODEL_COL_INSTANCE_PTR, &instance, -1);
|
||||
|
||||
gtk_tree_path_free (model_path);
|
||||
|
||||
DEBUG("instance is %p", instance);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gnc_sx_slr_model_get_instance_and_variable (GncSxSlrTreeModelAdapter *model, GtkTreeIter *iter, GncSxInstance **instance_loc, GncSxVariable **var_loc)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
GtkTreePath *model_path;
|
||||
gint *indices, variable_index;
|
||||
GncSxInstance *instance;
|
||||
GList *variables;
|
||||
@ -610,22 +620,33 @@ gnc_sx_slr_model_get_instance_and_variable (GncSxSlrTreeModelAdapter *model, Gtk
|
||||
instance = _gnc_sx_slr_model_get_instance (model, iter, FALSE);
|
||||
if (instance == NULL)
|
||||
{
|
||||
gchar *iter_str = gtk_tree_model_get_string_from_iter (GTK_TREE_MODEL(model), iter);
|
||||
PWARN("instance is NULL for iter %s", iter_str);
|
||||
g_free (iter_str);
|
||||
return FALSE;
|
||||
}
|
||||
variables = gnc_sx_instance_get_variables (instance);
|
||||
|
||||
path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), iter);
|
||||
if (gtk_tree_path_get_depth (path) != 3)
|
||||
model_path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), iter);
|
||||
if (gtk_tree_path_get_depth (model_path) != 3)
|
||||
{
|
||||
gtk_tree_path_free (path);
|
||||
gchar *path_str = gtk_tree_path_to_string (model_path);
|
||||
PWARN("invalid path [%s] for variable, not at depth 3", path_str);
|
||||
gtk_tree_path_free (model_path);
|
||||
g_free (path_str);
|
||||
return FALSE;
|
||||
}
|
||||
indices = gtk_tree_path_get_indices (path);
|
||||
|
||||
debug_path (DEBUG, "model path is:", model_path);
|
||||
|
||||
indices = gtk_tree_path_get_indices (model_path);
|
||||
variable_index = indices[2];
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
gtk_tree_path_free (model_path);
|
||||
|
||||
if (variable_index < 0 || variable_index >= g_list_length (variables))
|
||||
{
|
||||
PWARN("variable index %d out of range", variable_index);
|
||||
g_list_free (variables);
|
||||
return FALSE;
|
||||
}
|
||||
@ -637,21 +658,12 @@ gnc_sx_slr_model_get_instance_and_variable (GncSxSlrTreeModelAdapter *model, Gtk
|
||||
|
||||
if (var_loc != NULL)
|
||||
{
|
||||
// *var_loc = (GncSxVariable*)g_list_nth_data(variables, variable_index);
|
||||
GList *list_iter = variables;
|
||||
for (; list_iter != NULL; list_iter = list_iter->next)
|
||||
{
|
||||
GncSxVariable *var = (GncSxVariable*)list_iter->data;
|
||||
if (!var->editable)
|
||||
continue;
|
||||
if (variable_index-- == 0)
|
||||
{
|
||||
*var_loc = var;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
GncSxVariable *var;
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL(model), iter, SLR_MODEL_COL_INSTANCE_PTR, &var, -1);
|
||||
|
||||
*var_loc = var;
|
||||
}
|
||||
g_list_free (variables);
|
||||
return TRUE;
|
||||
}
|
||||
@ -675,30 +687,102 @@ _variable_list_index (GList *variables, GncSxVariable *variable)
|
||||
return -1;
|
||||
}
|
||||
|
||||
typedef struct _findInstanceData
|
||||
{
|
||||
gpointer find_item;
|
||||
GtkTreePath *found_path;
|
||||
} FindInstanceData;
|
||||
|
||||
static gboolean
|
||||
for_each_find_item (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data)
|
||||
{
|
||||
FindInstanceData* to_find = (FindInstanceData*)user_data;
|
||||
gpointer item;
|
||||
|
||||
gtk_tree_model_get (model, iter, SLR_MODEL_COL_INSTANCE_PTR, &item, -1);
|
||||
|
||||
if (item == to_find->find_item)
|
||||
{
|
||||
to_find->found_path = gtk_tree_path_copy (path);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GtkTreePath*
|
||||
_get_model_path_for_item (GtkTreeModel *model, gpointer find_item)
|
||||
{
|
||||
GtkTreePath *model_path = NULL;
|
||||
FindInstanceData* to_find_data;
|
||||
|
||||
to_find_data = (FindInstanceData*)g_new0 (FindInstanceData, 1);
|
||||
to_find_data->find_item = find_item;
|
||||
to_find_data->found_path = NULL;
|
||||
|
||||
gtk_tree_model_foreach (model, (GtkTreeModelForeachFunc)for_each_find_item, to_find_data);
|
||||
|
||||
if (to_find_data->found_path)
|
||||
{
|
||||
model_path = gtk_tree_path_copy (to_find_data->found_path);
|
||||
gtk_tree_path_free (to_find_data->found_path);
|
||||
}
|
||||
g_free (to_find_data);
|
||||
|
||||
return model_path;
|
||||
}
|
||||
|
||||
static GtkTreePath*
|
||||
_get_model_path_for_instance (GtkTreeModel *model, GncSxInstance *instance)
|
||||
{
|
||||
return _get_model_path_for_item (model, instance);
|
||||
}
|
||||
|
||||
static GtkTreePath*
|
||||
_get_model_path_for_instances (GtkTreeModel *model, GncSxInstances *instances)
|
||||
{
|
||||
return _get_model_path_for_item (model, instances);
|
||||
}
|
||||
|
||||
static GtkTreePath*
|
||||
_get_path_for_variable (GncSxSinceLastRunDialog *app_dialog, GncSxInstance *instance, GncSxVariable *variable)
|
||||
{
|
||||
GList *variables;
|
||||
int indices[3];
|
||||
GtkTreePath *path, *child_path;
|
||||
GncSxSlrTreeModelAdapter *model = app_dialog->editing_model;
|
||||
GtkTreeModel *sort_model = gtk_tree_view_get_model (app_dialog->instance_view);
|
||||
gint *indices, instances_index, instance_index, variable_index;
|
||||
GtkTreePath *view_path, *model_path;
|
||||
GList *variables;
|
||||
|
||||
indices[0] = g_list_index (gnc_sx_instance_model_get_sx_instances_list (model->instances), instance->parent);
|
||||
if (indices[0] == -1)
|
||||
return NULL;
|
||||
indices[1] = g_list_index (instance->parent->instance_list, instance);
|
||||
if (indices[1] == -1)
|
||||
model_path = _get_model_path_for_instance (GTK_TREE_MODEL(model), instance);
|
||||
|
||||
if (!model_path)
|
||||
{
|
||||
PWARN("model path is NULL for instance %p", instance);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
debug_path (DEBUG, "instance model path is:", model_path);
|
||||
|
||||
indices = gtk_tree_path_get_indices (model_path);
|
||||
instances_index = indices[0];
|
||||
instance_index = indices[1];
|
||||
|
||||
gtk_tree_path_free (model_path);
|
||||
|
||||
variables = gnc_sx_instance_get_variables (instance);
|
||||
indices[2] = _variable_list_index (variables, variable);
|
||||
variable_index = _variable_list_index (variables, variable);
|
||||
g_list_free (variables);
|
||||
if (indices[2] == -1)
|
||||
if (variable_index == -1)
|
||||
return NULL;
|
||||
child_path = gtk_tree_path_new_from_indices (indices[0], indices[1], indices[2], -1);
|
||||
path = gtk_tree_model_sort_convert_child_path_to_path (GTK_TREE_MODEL_SORT(sort_model), child_path);
|
||||
gtk_tree_path_free (child_path);
|
||||
return path;
|
||||
|
||||
model_path = gtk_tree_path_new_from_indices (instances_index, instance_index, variable_index, -1);
|
||||
debug_path (DEBUG, "model variable path is:", model_path);
|
||||
|
||||
view_path = gtk_tree_model_sort_convert_child_path_to_path (GTK_TREE_MODEL_SORT(sort_model), model_path);
|
||||
gtk_tree_path_free (model_path);
|
||||
|
||||
debug_path (DEBUG, "return view variable path is:", view_path);
|
||||
|
||||
return view_path;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -718,26 +802,45 @@ gsslrtma_updated_cb (GncSxInstanceModel *instances, SchedXaction *updated_sx, gp
|
||||
}
|
||||
|
||||
static void
|
||||
gsslrtma_removing_cb (GncSxInstanceModel *instances, SchedXaction *to_remove_sx, gpointer user_data)
|
||||
gsslrtma_removing_cb (GncSxInstanceModel *inst_model, SchedXaction *to_remove_sx, gpointer user_data)
|
||||
{
|
||||
GncSxSlrTreeModelAdapter *model = GNC_SX_SLR_TREE_MODEL_ADAPTER(user_data);
|
||||
GtkTreePath *model_path;
|
||||
GtkTreeIter tree_iter;
|
||||
GList *iter;
|
||||
int index = 0;
|
||||
GncSxInstances *instances;
|
||||
|
||||
// get index, create path, remove
|
||||
for (iter = gnc_sx_instance_model_get_sx_instances_list (instances); iter != NULL; iter = iter->next, index++)
|
||||
for (iter = gnc_sx_instance_model_get_sx_instances_list (inst_model); iter != NULL; iter = iter->next, index++)
|
||||
{
|
||||
GncSxInstances *instances = (GncSxInstances*)iter->data;
|
||||
instances = (GncSxInstances*)iter->data;
|
||||
if (instances->sx == to_remove_sx)
|
||||
break;
|
||||
}
|
||||
if (iter == NULL)
|
||||
{
|
||||
PWARN("could not find sx %p in the model", to_remove_sx);
|
||||
return; // couldn't find sx in our model, which is weird.
|
||||
if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL(model->real), &tree_iter, NULL, index))
|
||||
return; // perr(couldn't get something that should exist.
|
||||
}
|
||||
|
||||
model_path = _get_model_path_for_instances (GTK_TREE_MODEL(model), instances);
|
||||
|
||||
debug_path (DEBUG, "remove model_path", model_path);
|
||||
|
||||
if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(model->real), &tree_iter, model_path))
|
||||
{
|
||||
gchar *path_str = gtk_tree_path_to_string (model_path);
|
||||
PWARN("invalid path [%s] for instances %p to remove", path_str, instances);
|
||||
gtk_tree_path_free (model_path);
|
||||
g_free (path_str);
|
||||
return;
|
||||
}
|
||||
gtk_tree_path_free (model_path);
|
||||
|
||||
gtk_tree_store_remove (model->real, &tree_iter);
|
||||
|
||||
gnc_sx_instance_model_remove_sx_instances (instances, to_remove_sx);
|
||||
gnc_sx_instance_model_remove_sx_instances (inst_model, to_remove_sx);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -858,11 +961,12 @@ gnc_sx_sxsincelast_book_opened (void)
|
||||
static GtkTreePath *
|
||||
instance_get_model_path (GtkTreeView *view, const gchar *path)
|
||||
{
|
||||
GtkTreePath *sort_path = gtk_tree_path_new_from_string (path);
|
||||
GtkTreePath *view_path = gtk_tree_path_new_from_string (path);
|
||||
GtkTreeModelSort *sort_model = GTK_TREE_MODEL_SORT(gtk_tree_view_get_model (view));
|
||||
GtkTreePath *model_path = gtk_tree_model_sort_convert_path_to_child_path (sort_model, sort_path);
|
||||
|
||||
gtk_tree_path_free (sort_path);
|
||||
GtkTreePath *model_path = gtk_tree_model_sort_convert_path_to_child_path (sort_model, view_path);
|
||||
|
||||
gtk_tree_path_free (view_path);
|
||||
|
||||
return model_path;
|
||||
}
|
||||
@ -873,11 +977,15 @@ instance_state_changed_cb (GtkCellRendererText *cell,
|
||||
const gchar *value,
|
||||
GncSxSinceLastRunDialog *dialog)
|
||||
{
|
||||
GtkTreeIter tree_iter;
|
||||
GncSxInstance *inst;
|
||||
int i;
|
||||
GncSxInstanceState new_state;
|
||||
GtkTreePath *model_path = instance_get_model_path (dialog->instance_view, path);
|
||||
GtkTreeIter tree_iter;
|
||||
|
||||
DEBUG("change instance state to [%s] at path [%s]", value, path);
|
||||
|
||||
debug_path (DEBUG, "instance model path is:", model_path);
|
||||
|
||||
for (i = 0; i < SX_INSTANCE_STATE_CREATED; i++)
|
||||
{
|
||||
@ -886,7 +994,7 @@ instance_state_changed_cb (GtkCellRendererText *cell,
|
||||
}
|
||||
if (i == SX_INSTANCE_STATE_CREATED)
|
||||
{
|
||||
g_warning ("unknown value [%s]", value);
|
||||
PWARN("unknown value [%s]", value);
|
||||
return;
|
||||
}
|
||||
new_state = i;
|
||||
@ -894,18 +1002,21 @@ instance_state_changed_cb (GtkCellRendererText *cell,
|
||||
if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(dialog->editing_model), &tree_iter, model_path))
|
||||
{
|
||||
gtk_tree_path_free (model_path);
|
||||
g_warning ("unknown path [%s]", path);
|
||||
PWARN("unknown path [%s]", path);
|
||||
return;
|
||||
}
|
||||
gtk_tree_path_free (model_path);
|
||||
|
||||
inst = gnc_sx_slr_model_get_instance (dialog->editing_model, &tree_iter);
|
||||
|
||||
if (inst == NULL)
|
||||
{
|
||||
g_warning ("invalid path [%s]", path);
|
||||
PWARN("invalid path [%s]", path);
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG("instance is %p", inst);
|
||||
|
||||
gnc_sx_instance_model_change_instance_state (dialog->editing_model->instances, inst, new_state);
|
||||
}
|
||||
|
||||
@ -931,12 +1042,14 @@ variable_value_changed_cb (GtkCellRendererText *cell,
|
||||
{
|
||||
GncSxVariable *var = NULL;
|
||||
GncSxInstance *inst;
|
||||
GtkTreeIter tree_iter;
|
||||
gnc_numeric parsed_num;
|
||||
char *endStr = NULL;
|
||||
GtkTreePath *model_path = instance_get_model_path (dialog->instance_view, path);
|
||||
GtkTreeIter tree_iter;
|
||||
|
||||
DEBUG ("variable to [%s] at path [%s]", value, path);
|
||||
DEBUG("change variable to [%s] at view path [%s]", value, path);
|
||||
|
||||
debug_path (DEBUG, "instance model path is:", model_path);
|
||||
|
||||
dialog->temp_ce = NULL;
|
||||
control_scroll_bars (dialog);
|
||||
@ -944,14 +1057,14 @@ variable_value_changed_cb (GtkCellRendererText *cell,
|
||||
if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(dialog->editing_model), &tree_iter, model_path))
|
||||
{
|
||||
gtk_tree_path_free (model_path);
|
||||
g_warning ("invalid path [%s]", path);
|
||||
PWARN("invalid path [%s]", path);
|
||||
return;
|
||||
}
|
||||
gtk_tree_path_free (model_path);
|
||||
|
||||
if (!gnc_sx_slr_model_get_instance_and_variable (dialog->editing_model, &tree_iter, &inst, &var))
|
||||
{
|
||||
g_critical ("path [%s] doesn't correspond to a valid variable", path);
|
||||
PWARN("path [%s] doesn't correspond to a valid variable", path);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -967,7 +1080,7 @@ variable_value_changed_cb (GtkCellRendererText *cell,
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("error parsing value [%s]", value);
|
||||
PWARN("error parsing value [%s]", value);
|
||||
}
|
||||
g_free (value_copy);
|
||||
return;
|
||||
@ -999,31 +1112,41 @@ variable_value_cancel_changed_cb (GtkCellRenderer *renderer, gpointer user_data)
|
||||
}
|
||||
|
||||
static gint
|
||||
_transaction_sort_func (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer user_data)
|
||||
_sort_text (const gchar *text_a, const gchar *text_b)
|
||||
{
|
||||
gchar *a_caseless, *b_caseless;
|
||||
gint rtn = 0;
|
||||
|
||||
if (text_a == NULL && text_b == NULL) return 0;
|
||||
if (text_a == NULL) return 1;
|
||||
if (text_b == NULL) return -1;
|
||||
|
||||
a_caseless = g_utf8_casefold (text_a, -1);
|
||||
b_caseless = g_utf8_casefold (text_b, -1);
|
||||
rtn = g_strcmp0 (a_caseless, b_caseless);
|
||||
g_free (a_caseless);
|
||||
g_free (b_caseless);
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static gint
|
||||
_transaction_sort_func_date (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b)
|
||||
{
|
||||
GtkTreePath *path_a = gtk_tree_model_get_path (model, iter_a);
|
||||
|
||||
if (gtk_tree_path_get_depth (path_a) != 1)
|
||||
{
|
||||
gtk_tree_path_free (path_a);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
gint child_num_a = gtk_tree_model_iter_has_child (model, iter_a) ? 1 : 0;
|
||||
gint child_num_b = gtk_tree_model_iter_has_child (model, iter_b) ? 1 : 0;
|
||||
gint depth = gtk_tree_path_get_depth (path_a);
|
||||
gint64 date_a = 0, date_b = 0;
|
||||
gint rtn = 0;
|
||||
|
||||
gtk_tree_path_free (path_a);
|
||||
|
||||
if (child_num_a > child_num_b)
|
||||
rtn = -1;
|
||||
if (child_num_b > child_num_a)
|
||||
rtn = 1;
|
||||
if (depth == 3)
|
||||
return rtn;
|
||||
|
||||
if ((child_num_a == 1) && (child_num_b == 1))
|
||||
// if top level, look at the first date for order
|
||||
if (depth == 1)
|
||||
{
|
||||
GtkTreeIter child_iter_a, child_iter_b;
|
||||
gint64 date_a = 0, date_b = 0;
|
||||
|
||||
if (gtk_tree_model_iter_nth_child (model, &child_iter_a, iter_a, 0))
|
||||
gtk_tree_model_get (model, &child_iter_a, SLR_MODEL_COL_INSTANCE_DATE, &date_a, -1);
|
||||
@ -1035,75 +1158,81 @@ _transaction_sort_func (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *i
|
||||
rtn = 1;
|
||||
if (date_b > date_a)
|
||||
rtn = -1;
|
||||
|
||||
if (rtn == 0) // if dates are equal, look at name
|
||||
{
|
||||
gchar *name_text_a, *name_text_b;
|
||||
|
||||
gtk_tree_model_get (model, iter_a, SLR_MODEL_COL_NAME, &name_text_a, -1);
|
||||
gtk_tree_model_get (model, iter_b, SLR_MODEL_COL_NAME, &name_text_b, -1);
|
||||
|
||||
rtn = _sort_text (name_text_a, name_text_b);
|
||||
|
||||
g_free (name_text_a);
|
||||
g_free (name_text_b);
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
if (((child_num_a == 0) && (child_num_b == 0)) || rtn == 0)
|
||||
{
|
||||
gchar *name_text_a, *name_text_b;
|
||||
gtk_tree_model_get (model, iter_a, SLR_MODEL_COL_INSTANCE_DATE, &date_a, -1);
|
||||
gtk_tree_model_get (model, iter_b, SLR_MODEL_COL_INSTANCE_DATE, &date_b, -1);
|
||||
|
||||
if (date_a > date_b)
|
||||
rtn = 1;
|
||||
if (date_b > date_a)
|
||||
rtn = -1;
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static gint
|
||||
_transaction_sort_func_desc (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b)
|
||||
{
|
||||
GtkTreePath *path_a = gtk_tree_model_get_path (model, iter_a);
|
||||
gint depth = gtk_tree_path_get_depth (path_a);
|
||||
gchar *name_text_a, *name_text_b;
|
||||
gint rtn = 0;
|
||||
|
||||
gtk_tree_path_free (path_a);
|
||||
|
||||
if (depth == 3)
|
||||
return rtn;
|
||||
|
||||
if (depth == 1)
|
||||
{
|
||||
gtk_tree_model_get (model, iter_a, SLR_MODEL_COL_NAME, &name_text_a, -1);
|
||||
gtk_tree_model_get (model, iter_b, SLR_MODEL_COL_NAME, &name_text_b, -1);
|
||||
|
||||
rtn = safe_utf8_collate (name_text_a, name_text_b);
|
||||
rtn = _sort_text (name_text_a, name_text_b);
|
||||
|
||||
g_free (name_text_a);
|
||||
g_free (name_text_b);
|
||||
}
|
||||
|
||||
if (depth == 2)
|
||||
{
|
||||
gint64 date_a = 0, date_b = 0;
|
||||
|
||||
gtk_tree_model_get (model, iter_a, SLR_MODEL_COL_INSTANCE_DATE, &date_a, -1);
|
||||
gtk_tree_model_get (model, iter_b, SLR_MODEL_COL_INSTANCE_DATE, &date_b, -1);
|
||||
|
||||
if (date_a > date_b)
|
||||
rtn = 1;
|
||||
if (date_b > date_a)
|
||||
rtn = -1;
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static gint
|
||||
_status_sort_func (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer user_data)
|
||||
_transaction_sort_func (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer user_data)
|
||||
{
|
||||
gint rtn = 0;
|
||||
GtkTreePath *path_a = gtk_tree_model_get_path (model, iter_a);
|
||||
GncSxSinceLastRunDialog *dialog = user_data;
|
||||
|
||||
if (gtk_tree_path_get_depth (path_a) != 1)
|
||||
{
|
||||
gtk_tree_path_free (path_a);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
gint child_num_a = gtk_tree_model_iter_has_child (model, iter_a) ? 1 : 0;
|
||||
gint child_num_b = gtk_tree_model_iter_has_child (model, iter_b) ? 1 : 0;
|
||||
|
||||
gtk_tree_path_free (path_a);
|
||||
|
||||
if (child_num_a > child_num_b)
|
||||
rtn = -1;
|
||||
if (child_num_b > child_num_a)
|
||||
rtn = 1;
|
||||
|
||||
if ((child_num_a == 1) && (child_num_b == 1))
|
||||
{
|
||||
GtkTreeIter child_iter_a, child_iter_b;
|
||||
gchar *state_text_a = NULL, *state_text_b = NULL;
|
||||
|
||||
if (gtk_tree_model_iter_nth_child (model, &child_iter_a, iter_a, 0))
|
||||
gtk_tree_model_get (model, &child_iter_a, SLR_MODEL_COL_INSTANCE_STATE, &state_text_a, -1);
|
||||
|
||||
if (gtk_tree_model_iter_nth_child (model, &child_iter_b, iter_b, 0))
|
||||
gtk_tree_model_get (model, &child_iter_b, SLR_MODEL_COL_INSTANCE_STATE, &state_text_b, -1);
|
||||
|
||||
rtn = safe_utf8_collate (state_text_a, state_text_b);
|
||||
|
||||
g_free (state_text_a);
|
||||
g_free (state_text_b);
|
||||
}
|
||||
|
||||
if (((child_num_a == 0) && (child_num_b == 0)) || rtn == 0)
|
||||
{
|
||||
gchar *name_text_a, *name_text_b;
|
||||
|
||||
gtk_tree_model_get (model, iter_a, SLR_MODEL_COL_NAME, &name_text_a, -1);
|
||||
gtk_tree_model_get (model, iter_b, SLR_MODEL_COL_NAME, &name_text_b, -1);
|
||||
|
||||
rtn = safe_utf8_collate (name_text_a, name_text_b);
|
||||
|
||||
g_free (name_text_a);
|
||||
g_free (name_text_b);
|
||||
}
|
||||
return rtn;
|
||||
if (dialog->sort_selection_depth == 1)
|
||||
return _transaction_sort_func_desc (model, iter_a, iter_b);
|
||||
else
|
||||
return _transaction_sort_func_date (model, iter_a, iter_b);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -1130,6 +1259,66 @@ scroll_event (GtkWidget *widget, GdkEventScroll *event, gpointer user_data)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
set_transaction_sort_column_tooltip (GncSxSinceLastRunDialog *dialog)
|
||||
{
|
||||
GtkTreeViewColumn *col = gtk_tree_view_get_column (GTK_TREE_VIEW(dialog->instance_view), 0);
|
||||
const gchar *date_text = _("Highlight a date first to sort by occurrence date.");
|
||||
const gchar *sched_text = _("Highlight a schedule first to sort by schedule name.");
|
||||
gchar *tooltip;
|
||||
|
||||
if (dialog->sort_selection_depth == 1)
|
||||
tooltip = g_strconcat (sched_text, " *\n", date_text, NULL);
|
||||
else
|
||||
tooltip = g_strconcat (sched_text, "\n", date_text, " *", NULL);
|
||||
|
||||
gtk_widget_set_tooltip_text (gtk_tree_view_column_get_button (col), tooltip);
|
||||
g_free (tooltip);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
follow_select_tree_path (GtkTreeView *view)
|
||||
{
|
||||
GtkTreeSelection *selection = gtk_tree_view_get_selection (view);
|
||||
GtkTreeModel *sort_model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (gtk_tree_selection_get_selected (selection, &sort_model, &iter))
|
||||
{
|
||||
GtkTreePath *view_path = gtk_tree_model_get_path (sort_model, &iter);
|
||||
|
||||
gtk_tree_view_scroll_to_cell (view, view_path, NULL, TRUE, 0.5, 0.0);
|
||||
|
||||
gtk_tree_path_free (view_path);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
sort_column_changed (GtkTreeSortable* self, gpointer user_data)
|
||||
{
|
||||
// this is triggered before a sort change
|
||||
GncSxSinceLastRunDialog *dialog = user_data;
|
||||
GtkTreeIter iter;
|
||||
GtkTreeSelection *selection = gtk_tree_view_get_selection (dialog->instance_view);
|
||||
GtkTreeModel *sort_model;
|
||||
|
||||
if (gtk_tree_selection_get_selected (selection, &sort_model, &iter))
|
||||
{
|
||||
GtkTreePath *view_path = gtk_tree_model_get_path (sort_model, &iter);
|
||||
|
||||
dialog->sort_selection_depth = gtk_tree_path_get_depth (view_path);
|
||||
|
||||
gtk_tree_path_free (view_path);
|
||||
}
|
||||
else
|
||||
dialog->sort_selection_depth = 1;
|
||||
|
||||
set_transaction_sort_column_tooltip (dialog);
|
||||
|
||||
g_idle_add ((GSourceFunc)follow_select_tree_path, dialog->instance_view);
|
||||
}
|
||||
|
||||
GncSxSinceLastRunDialog*
|
||||
gnc_ui_sx_since_last_run_dialog (GtkWindow *parent, GncSxInstanceModel *sx_instances, GList *auto_created_txn_guids)
|
||||
{
|
||||
@ -1172,9 +1361,14 @@ gnc_ui_sx_since_last_run_dialog (GtkWindow *parent, GncSxInstanceModel *sx_insta
|
||||
g_object_unref (sort_model);
|
||||
|
||||
/* default sort order */
|
||||
dialog->sort_selection_depth = gnc_prefs_get_int (GNC_PREFS_GROUP_STARTUP, GNC_PREF_SLR_SORT_DEPTH);
|
||||
gboolean sort_ascending = gnc_prefs_get_bool (GNC_PREFS_GROUP_STARTUP, GNC_PREF_SLR_SORT_ASC);
|
||||
gint sort_column = gnc_prefs_get_int (GNC_PREFS_GROUP_STARTUP, GNC_PREF_SLR_SORT_COL);
|
||||
GtkSortType sort_type = sort_ascending ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING;
|
||||
|
||||
if (sort_column != 0)
|
||||
sort_column = 0;
|
||||
|
||||
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(sort_model),
|
||||
sort_column, sort_type);
|
||||
|
||||
@ -1192,6 +1386,8 @@ gnc_ui_sx_since_last_run_dialog (GtkWindow *parent, GncSxInstanceModel *sx_insta
|
||||
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(sort_model), SLR_MODEL_COL_NAME,
|
||||
_transaction_sort_func, dialog, NULL);
|
||||
|
||||
set_transaction_sort_column_tooltip (dialog);
|
||||
|
||||
renderer = gtk_cell_renderer_combo_new ();
|
||||
g_object_set (G_OBJECT(renderer),
|
||||
"model", gnc_sx_get_slr_state_model (),
|
||||
@ -1213,10 +1409,8 @@ gnc_ui_sx_since_last_run_dialog (GtkWindow *parent, GncSxInstanceModel *sx_insta
|
||||
"sensitive", SLR_MODEL_COL_INSTANCE_STATE_SENSITIVITY,
|
||||
NULL);
|
||||
|
||||
gtk_tree_view_column_set_sort_column_id (col, SLR_MODEL_COL_INSTANCE_STATE);
|
||||
|
||||
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(sort_model), SLR_MODEL_COL_INSTANCE_STATE,
|
||||
_status_sort_func, dialog, NULL);
|
||||
g_signal_connect (G_OBJECT(sort_model), "sort-column-changed",
|
||||
G_CALLBACK(sort_column_changed), dialog);
|
||||
|
||||
renderer = gtk_cell_renderer_pixbuf_new ();
|
||||
g_object_set (G_OBJECT(renderer),
|
||||
@ -1325,6 +1519,8 @@ close_handler (gpointer user_data)
|
||||
|
||||
gnc_prefs_set_bool (GNC_PREFS_GROUP_STARTUP, GNC_PREF_SLR_SORT_ASC, sort_ascending);
|
||||
gnc_prefs_set_int (GNC_PREFS_GROUP_STARTUP, GNC_PREF_SLR_SORT_COL, column);
|
||||
gnc_prefs_set_int (GNC_PREFS_GROUP_STARTUP, GNC_PREF_SLR_SORT_DEPTH,
|
||||
app_dialog->sort_selection_depth);
|
||||
}
|
||||
|
||||
gnc_save_window_size (GNC_PREFS_GROUP_STARTUP, GTK_WINDOW(app_dialog->dialog));
|
||||
@ -1361,7 +1557,7 @@ dialog_response_cb (GtkDialog *dialog, gint response_id, GncSxSinceLastRunDialog
|
||||
gint unbound_len;
|
||||
unbound_variables = gnc_sx_instance_model_check_variables (app_dialog->editing_model->instances);
|
||||
unbound_len = g_list_length (unbound_variables);
|
||||
PINFO ("%d variables unbound", unbound_len);
|
||||
PINFO("%d variables unbound", unbound_len);
|
||||
if (unbound_len > 0)
|
||||
{
|
||||
// focus first variable
|
||||
@ -1408,7 +1604,7 @@ dialog_response_cb (GtkDialog *dialog, gint response_id, GncSxSinceLastRunDialog
|
||||
gnc_close_gui_component (app_dialog->component_id);
|
||||
break;
|
||||
default:
|
||||
g_error ("unknown response id [%d]", response_id);
|
||||
PWARN("unknown response id [%d]", response_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,11 @@
|
||||
<summary>Set the sort direction in the "since last run" dialog.</summary>
|
||||
<description>This settings sets the sort direction in the "since last run" dialog.</description>
|
||||
</key>
|
||||
<key name="sort-depth" type="i">
|
||||
<default>1</default>
|
||||
<summary>The depth used in the tree to sort in the "since last run" dialog.</summary>
|
||||
<description>The depth used in the tree to sort in the "since last run" dialog.</description>
|
||||
</key>
|
||||
</schema>
|
||||
<schema id="org.gnucash.GnuCash.dialogs.sxs.transaction-editor" path="/org/gnucash/GnuCash/dialogs/scheduled-trans/transaction-editor/">
|
||||
<key name="create-auto" type="b">
|
||||
|
Loading…
Reference in New Issue
Block a user