RFC - edit nick names dialog added to gtk-gui.c

Amit Chaudhuri amit.k.chaudhuri at gmail.com
Fri Jan 11 08:02:34 PST 2013


Hi.

Attached is a diff which partially implements the edit nick names
functionality.  It leans heavily on the stand alone prototype Lubomir
worked up and a bunch of discussions with Dirk.  On advice, I've resisted
the urge to move this to separate files.

I believe it works for editing but for delete it only printf's my intended
hooks to complete.

The recent introduction of device_info cut across the previous code
slightly.  With the move to separate files for the newly named struct I had
to add a function to device.[ch] to return the head of list.  Is this a
complete no-no?

All comments etc. gratefully received.  As it is my first contribution
direct to list, please shout if things are wrong / awkward.  I think I'm ok
on whitespace and sign-offs...

Regards,

Amit
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.hohndel.org/pipermail/subsurface/attachments/20130111/a26d6bef/attachment.html>
-------------- next part --------------
diff --git a/device.c b/device.c
index 39f742a..5b74422 100644
--- a/device.c
+++ b/device.c
@@ -4,6 +4,11 @@
 
 static struct device_info *device_info_list;
 
+struct device_info *head_of_device_info_list(void)
+{
+	return device_info_list;
+}
+
 static int match_device_info(struct device_info *entry, const char *model, uint32_t deviceid)
 {
 	return !strcmp(entry->model, model) && entry->deviceid == deviceid;
diff --git a/device.h b/device.h
index 896bcb8..31e4a74 100644
--- a/device.h
+++ b/device.h
@@ -17,5 +17,6 @@ extern struct device_info *get_different_device_info(const char *model, uint32_t
 extern struct device_info *create_device_info(const char *model, uint32_t deviceid);
 extern struct device_info *remove_device_info(const char *model, uint32_t deviceid);
 extern void clear_device_saved_status(void);
+extern struct device_info *head_of_device_info_list(void);
 
 #endif
diff --git a/gtk-gui.c b/gtk-gui.c
index 4dcffbd..cc87974 100644
--- a/gtk-gui.c
+++ b/gtk-gui.c
@@ -1,4 +1,4 @@
-/* gtk-gui.c */
+  /* gtk-gui.c */
 /* gtk UI implementation */
 /* creates the window and overall layout
  * divelist, dive info, equipment and printing are handled in their own source files
@@ -36,6 +36,38 @@ const char *divelist_font;
 const char *default_filename;
 
 char *nicknamestring;
+static struct device_info *nicknamelist;
+static struct device_info *holdnicknames = NULL;
+
+static void clear_hold_nicknames(void){
+
+	if( !holdnicknames )
+		holdnicknames = (struct device_info *) malloc(sizeof( struct device_info ));
+
+	holdnicknames->model = NULL;
+	holdnicknames->deviceid = 0;
+	holdnicknames->serial_nr = NULL;
+	holdnicknames->firmware = NULL;
+	holdnicknames->nickname = NULL;
+	holdnicknames->next = NULL;
+	holdnicknames->saved = FALSE;
+
+}
+
+
+
+void dump_nickname_list_entry(struct device_info *nnl){
+
+	  printf("\n");
+	  printf("Address of entry is %p root is at %p\n", nnl, nicknamelist);
+	  printf("Model = %s\n",nnl->model);
+	  printf("Device = %x\n", nnl->deviceid);
+	  printf("Nickname = %s\n", nnl->nickname);
+	  printf("Address of next entry is %p\n",nnl->next);
+	  printf("\n");
+
+}
+
 
 static GtkWidget *dive_profile;
 static const char *default_dive_computer_vendor;
@@ -1129,6 +1161,225 @@ static void next_dc(GtkWidget *w, gpointer data)
 	repaint_dive();
 }
 
+
+/* list columns for nickname edit treeview */
+enum {
+	NE_MODEL,
+	NE_ID_STR,
+	NE_NICKNAME,
+	NE_NCOL
+};
+
+
+/* delete a selection of nicknames */
+static void edit_dc_delete_rows(GtkTreeView *view)
+{
+	GtkTreeModel *model;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	GtkTreeRowReference *ref;
+	GtkTreeSelection *selection;
+	GList *selected_rows, *list, *row_references = NULL;
+	guint len;
+
+	selection = gtk_tree_view_get_selection(view);
+	/* this isn't compatible bellow gtk 2.2, so should be done manually using 'for_each' ! */
+	selected_rows = gtk_tree_selection_get_selected_rows(selection, &model);
+
+	for (list = selected_rows; list; list = g_list_next(list)) {
+		path = list->data;
+		ref = gtk_tree_row_reference_new(model, path);
+		row_references = g_list_append(row_references, ref);
+	}
+	len = g_list_length(row_references);
+	if (len == 0){
+		//printf("Warn about empty selection?\n");
+		return;
+	}
+
+	clear_hold_nicknames();
+	printf("Call Dirk's delete function soon - after populating the holdnicknames structure with the list to delete\n");
+	for (list = row_references; list; list = g_list_next(list)) {
+		printf("Call to populate goes here...\n");
+		path = gtk_tree_row_reference_get_path((GtkTreeRowReference *)(list->data));
+		gtk_tree_model_get_iter(model, &iter, path);
+		gtk_list_store_remove(GTK_LIST_STORE (model), &iter);
+		gtk_tree_path_free(path);
+	}
+	printf("Commit delete here\n");
+	g_list_free(selected_rows);
+	g_list_free(row_references);
+	g_list_free(list);
+
+	if (gtk_tree_model_get_iter_first(model, &iter))
+		gtk_tree_selection_select_iter(selection, &iter);
+}
+
+/* repopulate the edited nickname cell of a DC */
+static void cell_edited_cb(GtkCellRendererText *cell,
+	gchar *path,
+	gchar *new_text,
+	gpointer store)
+{
+	/* iterator */
+	GtkTreeIter iter;
+	gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(store), &iter, path);
+
+	/* display new text */
+	gtk_list_store_set(GTK_LIST_STORE(store), &iter, NE_NICKNAME, new_text, -1);
+
+	/* params for remember_dc */
+	const char *model;
+	const char *deviceid_string;
+	uint32_t deviceid;
+	// and new_text
+	gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
+					  NE_MODEL, &model,
+					  NE_ID_STR, &deviceid_string,
+					  -1);
+	printf("Model: %s\n", model);
+	printf("Dev str: %s\n", deviceid_string);
+
+	/* extract deviceid */
+	int matched = -1;
+	matched = sscanf(deviceid_string, "0x%x8", &deviceid);
+	printf("Number of items matched equals = %d (hopefully 1) & ", matched);
+	printf("device id is %u\n", deviceid);
+
+	/* remember pending commit */
+	if(matched == 1){
+	  clear_hold_nicknames();
+	  holdnicknames->nickname = strdup(new_text);
+	  holdnicknames->model = strdup(model);
+	  holdnicknames->deviceid = deviceid;
+	  holdnicknames->next = NULL;
+	  holdnicknames->saved = FALSE;
+	}
+
+
+	/* tidy up */
+	// Did gtk malloc anything for me?
+
+}
+
+/* show the dialog to edit dc nicknames */
+static void edit_dc_nicknames(GtkWidget *w, gpointer data)
+{
+	const gint SUB_RESPONSE_DELETE = 1;
+	const gchar *C_INACTIVE = "#e8e8ee", *C_ACTIVE = "#ffffff";	// light grey & white RGB hex colour codes
+	GtkWidget *dialog, *confirm, *view, *scroll, *vbox;
+	GtkCellRenderer *renderer;
+	GtkTreeSelection *selection;
+	GtkTreeModel *model;
+	GtkListStore *store;
+	GtkTreeIter iter;
+	gint res = -1;
+
+	clear_hold_nicknames();	/* protect against user calling dialog, not editing and calling ok */
+
+	dialog = gtk_dialog_new_with_buttons( _("Edit Dive Computer Nicknames"),
+		GTK_WINDOW(main_window),
+		GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+		GTK_STOCK_DELETE,
+		SUB_RESPONSE_DELETE,
+		GTK_STOCK_CANCEL,
+		GTK_RESPONSE_CANCEL,
+		GTK_STOCK_APPLY,
+		GTK_RESPONSE_APPLY,
+		NULL);
+	gtk_widget_set_size_request(dialog, 500, 400);
+
+	scroll = gtk_scrolled_window_new(NULL, NULL);
+	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+	view = gtk_tree_view_new();
+	store = gtk_list_store_new(NE_NCOL, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+	model = GTK_TREE_MODEL(store);
+
+	/* columns */
+	renderer = gtk_cell_renderer_text_new();
+	g_object_set(renderer, "background", C_INACTIVE, NULL);
+	gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
+		-1, "Model", renderer, "text", NE_MODEL, NULL);
+
+	renderer = gtk_cell_renderer_text_new();
+	g_object_set(renderer, "background", C_INACTIVE, NULL);
+	gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
+		-1, "Device Id", renderer, "text", NE_ID_STR, NULL);
+
+	renderer = gtk_cell_renderer_text_new();
+	g_object_set(renderer, "background", C_INACTIVE, NULL);
+	gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
+		-1, "Nickname", renderer, "text", NE_NICKNAME, NULL);
+	g_object_set(renderer, "editable", TRUE, NULL);
+	g_object_set(renderer, "background", C_ACTIVE, NULL);
+	g_signal_connect(renderer, "edited", G_CALLBACK(cell_edited_cb), store);
+
+	gtk_tree_view_set_model(GTK_TREE_VIEW(view), model);
+	g_object_unref(model);
+
+	/* populate list store */
+	char id_string[11] = {0}; /* this buffer holds the id as hex string */
+
+	struct device_info * nnl = head_of_device_info_list();
+	while( nnl ) {
+
+	  dump_nickname_list_entry(nnl);
+
+	  sprintf(&id_string[0], "%#08x", nnl->deviceid);
+	  gtk_list_store_append(store, &iter);
+	  gtk_list_store_set(store, &iter,
+		  NE_MODEL, nnl->model,
+		  NE_ID_STR, id_string,
+		  NE_NICKNAME, nnl->nickname,
+		  -1);
+	  nnl = nnl->next;
+	}
+
+	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
+	gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
+	//gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
+
+	vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+	gtk_container_add(GTK_CONTAINER(scroll), view);
+	gtk_container_add(GTK_CONTAINER(vbox),
+		gtk_label_new(_("Edit a DC's nickname by double-clicking inside the 'Nickname' column")));
+	gtk_container_add(GTK_CONTAINER(vbox), scroll);
+	gtk_widget_set_size_request(scroll, 500, 300);
+	gtk_widget_show_all(dialog);
+
+	do {
+		res = gtk_dialog_run(GTK_DIALOG(dialog));
+		if (res == SUB_RESPONSE_DELETE) {
+			confirm = gtk_dialog_new_with_buttons(_("Delete DC nicknames"),
+				GTK_WINDOW(dialog),
+				GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+				GTK_STOCK_YES,
+				GTK_RESPONSE_YES,
+				GTK_STOCK_NO,
+				GTK_RESPONSE_NO,
+				NULL);
+			gtk_widget_set_size_request(confirm, 350, 90);
+			vbox = gtk_dialog_get_content_area(GTK_DIALOG(confirm));
+			gtk_container_add(GTK_CONTAINER(vbox),
+				gtk_label_new(_("Are you sure you want to delete the selected entries?")));
+			gtk_widget_show_all(confirm);
+			if (gtk_dialog_run(GTK_DIALOG(confirm)) == GTK_RESPONSE_YES)
+				edit_dc_delete_rows(GTK_TREE_VIEW(view));
+			gtk_widget_destroy(confirm);
+		}
+		if (res == GTK_RESPONSE_APPLY && holdnicknames->model != NULL ) {
+		  //printf("remember_dc\n");
+		  remember_dc(holdnicknames->model, holdnicknames->deviceid, holdnicknames->nickname, TRUE);
+		}
+	} while (res != GTK_RESPONSE_CANCEL && res != GTK_RESPONSE_DELETE_EVENT && res != GTK_RESPONSE_APPLY);
+	gtk_widget_destroy(dialog);
+}
+
+
+
+
+
 static GtkActionEntry menu_items[] = {
 	{ "FileMenuAction", NULL, N_("File"), NULL, NULL, NULL},
 	{ "LogMenuAction",  NULL, N_("Log"), NULL, NULL, NULL},
@@ -1155,6 +1406,7 @@ static GtkActionEntry menu_items[] = {
 	{ "ViewProfile",    NULL, N_("Profile"), CTRLCHAR "2", NULL, G_CALLBACK(view_profile) },
 	{ "ViewInfo",       NULL, N_("Info"), CTRLCHAR "3", NULL, G_CALLBACK(view_info) },
 	{ "ViewThree",      NULL, N_("Three"), CTRLCHAR "4", NULL, G_CALLBACK(view_three) },
+	{ "EditNames",      NULL, N_("Edit Names"), CTRLCHAR "E", NULL, G_CALLBACK(edit_dc_nicknames) },
 	{ "PrevDC",         NULL, N_("Prev DC"), NULL, NULL, G_CALLBACK(prev_dc) },
 	{ "NextDC",         NULL, N_("Next DC"), NULL, NULL, G_CALLBACK(next_dc) },
 	{ "InputPlan",      NULL, N_("Input Plan"), NULL, NULL, G_CALLBACK(input_plan) },
@@ -1187,6 +1439,7 @@ static const gchar* ui_string = " \
 			</menu> \
 			<menu name=\"LogMenu\" action=\"LogMenuAction\"> \
 				<menuitem name=\"Download From Dive Computer\" action=\"DownloadLog\" /> \
+				<menuitem name=\"Edit Dive Computer Names\" action=\"EditNames\" /> \
 				<separator name=\"Separator1\"/> \
 				<menuitem name=\"Add Dive\" action=\"AddDive\" /> \
 				<separator name=\"Separator2\"/> \


More information about the subsurface mailing list