/* * text has been dragged into the watch tree view */ static void on_watch_dragged_callback(GtkWidget *wgt, GdkDragContext *context, int x, int y, GtkSelectionData *seldata, guint info, guint _time, gpointer userdata) { /* string that is dragged */ gchar *expression = (gchar*)seldata->data; GtkTreePath *path = NULL; GtkTreeViewDropPosition pos; GtkTreePath *empty_path; GtkTreeIter newvar; /* lookup for where the text has been dropped */ gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(wtree), x, y, &path, &pos); /* if dropped into last row - insert before it */ empty_path = wtree_empty_path(); if (!gtk_tree_path_compare(empty_path, path)) pos = GTK_TREE_VIEW_DROP_BEFORE; gtk_tree_path_free(empty_path); /* if dropped into children area - insert before parent */ if (gtk_tree_path_get_depth(path) > 1) { while (gtk_tree_path_get_depth(path) > 1) gtk_tree_path_up(path); pos = GTK_TREE_VIEW_DROP_BEFORE; } /* insert new row */ if (path) { GtkTreeIter sibling; gtk_tree_model_get_iter(wmodel, &sibling, path); if (GTK_TREE_VIEW_DROP_BEFORE == pos || GTK_TREE_VIEW_DROP_INTO_OR_BEFORE == pos) gtk_tree_store_insert_before(wstore, &newvar, NULL, &sibling); else gtk_tree_store_insert_after(wstore, &newvar, NULL, &sibling); } else { GtkTreeIter empty; wtree_empty_row(&empty); gtk_tree_store_insert_before(wstore, &newvar, NULL, &empty); } /* if debugger is active (in stopped condition) - add to run-time watch list * if not - just set new expession in the tree view */ if (DBS_STOPPED == debug_state) { variable *var = active_module->add_watch(expression); change_watch(GTK_TREE_VIEW(wtree), &newvar, var); } else variable_set_name_only(wstore, &newvar, expression); config_set_debug_changed(); }
/* * iterating function to collect all watches */ gboolean watches_foreach_collect(GtkTreeModel *_model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { if (gtk_tree_path_compare(path, wtree_empty_path()) && 1 == gtk_tree_path_get_depth(path)) { gchar *watch; gtk_tree_model_get ( _model, iter, W_NAME, &watch, -1); GList **watches = (GList**)data; *watches = g_list_append(*watches, watch); } return FALSE; }
/* * key has been pressed while being in watch tree view */ static gboolean on_watch_key_pressed_callback(GtkWidget *widget, GdkEvent *event, gpointer user_data) { /* handling only Delete button pressing * that means "delete selected rows" */ int keyval = ((GdkEventKey*)event)->keyval; if (keyval != GDK_Delete) return FALSE; /* get selected rows */ GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(wtree)); GList *rows = gtk_tree_selection_get_selected_rows(selection, &wmodel); /* empty row path */ GtkTreePath *empty_path = wtree_empty_path(); /* check whether only empty row was selected */ if (1 != gtk_tree_selection_count_selected_rows(selection) || gtk_tree_path_compare((GtkTreePath*)rows->data, empty_path)) { /* path reference to select after deleteing finishes */ GtkTreeRowReference *reference_to_select = NULL; /* get references to the rows */ GList *references = NULL; GList *iter = rows; while (iter) { GtkTreePath *path = (GtkTreePath*)iter->data; /* move up paths to the root elements */ while (gtk_tree_path_get_depth(path) > 1) gtk_tree_path_up(path); /* add path reference if it's not an empty row*/ if (gtk_tree_path_compare(path, empty_path)) references = g_list_append(references, gtk_tree_row_reference_new(wmodel, path)); iter = iter->next; } /* iterate through references and remove */ iter = references; while (iter) { GtkTreeRowReference *reference = (GtkTreeRowReference*)iter->data; /* check for valid reference because two or more equal refernces could be put in the list if several child items of the same node were selected and the path for the current reference was already deleted */ if (gtk_tree_row_reference_valid(reference)) { GtkTreePath *path = gtk_tree_row_reference_get_path(reference); if (!reference_to_select) { /* select upper sibling of the upper selected row that has unselected upper sibling */ GtkTreePath *sibling = gtk_tree_path_copy(path); if(gtk_tree_path_prev(sibling)) { if (!gtk_tree_selection_path_is_selected(selection, sibling)) reference_to_select = gtk_tree_row_reference_new(gtk_tree_view_get_model(GTK_TREE_VIEW(wtree)), sibling); } else if (gtk_tree_path_next(sibling), gtk_tree_path_compare(path, sibling)) reference_to_select = gtk_tree_row_reference_new(gtk_tree_view_get_model(GTK_TREE_VIEW(wtree)), sibling); } /* get iterator */ GtkTreeIter titer; gtk_tree_model_get_iter(wmodel, &titer, path); /* remove from the debug session, if it's active */ if (DBS_STOPPED == debug_state) { gchar *internal = NULL; gtk_tree_model_get ( wmodel, &titer, W_INTERNAL, &internal, -1); active_module->remove_watch(internal); g_free(internal); } gtk_tree_store_remove(wstore, &titer); gtk_tree_path_free(path); } iter = iter->next; } /* if all (with or without empty row) was selected - set empty row as a path to be selected after deleting */ if (!reference_to_select) { GtkTreePath *path = wtree_empty_path(); reference_to_select = gtk_tree_row_reference_new (gtk_tree_view_get_model(GTK_TREE_VIEW(wtree)), path); gtk_tree_path_free(path); } /* set selection */ gtk_tree_selection_unselect_all(selection); GtkTreePath *path_to_select = gtk_tree_row_reference_get_path(reference_to_select); gtk_tree_selection_select_path(selection, path_to_select); gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(widget), path_to_select, NULL, TRUE, 0.5, 0.5); gtk_tree_path_free(path_to_select); /* free references list */ g_list_foreach (references, (GFunc)gtk_tree_row_reference_free, NULL); g_list_free (references); config_set_debug_changed(); } gtk_tree_path_free(empty_path); /* free rows list */ g_list_foreach (rows, (GFunc)gtk_tree_path_free, NULL); g_list_free (rows); return FALSE; }
/* * watch expression has been changed */ static void on_watch_changed(GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer user_data) { /* get iterator to the changed row */ GtkTreeIter iter; GtkTreePath *tree_path = gtk_tree_path_new_from_string (path); gtk_tree_model_get_iter ( gtk_tree_view_get_model(GTK_TREE_VIEW(wtree)), &iter, tree_path); /* get oldvalue */ gchar* oldvalue; gtk_tree_model_get ( wmodel, &iter, W_NAME, &oldvalue, -1); gchar *internal = NULL; gtk_tree_model_get ( wmodel, &iter, W_INTERNAL, &internal, -1); /* check if it is empty row */ GtkTreePath *empty_path = wtree_empty_path(); gboolean is_empty_row = !gtk_tree_path_compare (tree_path, empty_path); gtk_tree_path_free(empty_path); gchar *striped = g_strstrip(g_strdup(new_text)); if (!strlen(striped) && !is_empty_row && dialogs_show_question(_("Delete variable?"))) { /* if new value is empty string on non-empty row * offer to delete watch */ gtk_tree_store_remove(wstore, &iter); if (DBS_STOPPED == debug_state) active_module->remove_watch(internal); config_set_debug_changed(); } else if (strcmp(oldvalue, striped)) { /* new value is non empty */ /* insert new row if changing was the last empty row */ GtkTreeIter newiter; if (is_empty_row) gtk_tree_store_insert_before(wstore, &newiter, NULL, &iter); /* set expression */ variable_set_name_only(wstore, is_empty_row ? &newiter : &iter, striped); /* if debug is active - remove old watch and add new one */ if (DBS_STOPPED == debug_state) { active_module->remove_watch(internal); variable *newvar = active_module->add_watch(striped); change_watch(GTK_TREE_VIEW(wtree), is_empty_row ? &newiter : &iter, newvar); } /* if new watch has been added - set selection to the new created row */ if (is_empty_row) { GtkTreePath *_path = gtk_tree_model_get_path(wmodel, &newiter); GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(wtree)); gtk_tree_selection_unselect_all(selection); gtk_tree_selection_select_path(selection, _path); gtk_tree_path_free(_path); } config_set_debug_changed(); } /* free resources */ gtk_tree_path_free(tree_path); g_free(oldvalue); g_free(internal); g_free(striped); }