From: erg Date: Thu, 15 Jul 2010 14:34:20 +0000 (+0000) Subject: Fix node list window to work when the datacolumns attribute is changed; X-Git-Tag: LAST_LIBGRAPH~32^2~1277 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a4e3f34a70a1155c944782036fc9961789f88507;p=graphviz Fix node list window to work when the datacolumns attribute is changed; add a button to export a selected subgraph with induced edges --- diff --git a/cmd/smyrna/draw.c b/cmd/smyrna/draw.c index 07003d2d4..41549b4c8 100755 --- a/cmd/smyrna/draw.c +++ b/cmd/smyrna/draw.c @@ -426,8 +426,6 @@ void SetFont(sdot_op * o, int param) /*for now we only support png files in 2d space, no image rotation*/ void InsertImage(sdot_op * o, int param) { - - float w,h,x,y,X,Y,Z; glCompImage *i; @@ -442,11 +440,9 @@ void InsertImage(sdot_op * o, int param) i = glCompImageNew(NULL, x, y); glCompImageLoadPng(i, o->op.u.image.name,0); i->common.functions.draw(i); - } - - } + void EmbedText(sdot_op* o, int param) { GLfloat x,y; diff --git a/cmd/smyrna/gui/datalistcallbacks.c b/cmd/smyrna/gui/datalistcallbacks.c index ea638565d..2516f39e2 100755 --- a/cmd/smyrna/gui/datalistcallbacks.c +++ b/cmd/smyrna/gui/datalistcallbacks.c @@ -75,5 +75,10 @@ void btnTVHideAll_clicked_cb(GtkWidget * widget, gpointer user_data) void btnTVSaveAs_clicked_cb(GtkWidget * widget, gpointer user_data) { - tv_save_as(); + tv_save_as(0); +} + +void btnTVSaveWith_clicked_cb(GtkWidget * widget, gpointer user_data) +{ + tv_save_as(1); } diff --git a/cmd/smyrna/tvnodes.c b/cmd/smyrna/tvnodes.c index f6730580b..5721068fb 100755 --- a/cmd/smyrna/tvnodes.c +++ b/cmd/smyrna/tvnodes.c @@ -19,92 +19,108 @@ #include "topviewfuncs.h" #include "memory.h" -typedef struct{ +typedef struct { GType type; - char* name; + char *name; int editable; -}gridCol; -typedef struct -{ +} gridCol; +typedef struct { int count; - gridCol** columns; + gridCol **columns; GtkTreeStore *store; - char* flds; -}grid; + char *flds; + char *buf; +} grid; + +static char* ID = "ID"; +static char* Name = "Name"; +static char* Visible = "Visible"; + +/* induceEdges: + * Add all edges of g which have both ends in sg to sg + */ +static void induceEdges (Agraph_t * g, Agraph_t * sg) +{ + Agnode_t *n; + Agedge_t *e; + + for (n = agfstnode(sg); n; n = agnxtnode(sg, n)) { + for (e = agfstout(g, n); e; e = agnxtout(g, e)) { + if (agsubnode(sg, aghead(e), 0)) { + agsubedge(sg, e, 1); + } + } + } +} /* call this function to create a subgraph from filtered nodes and maybe edges */ - -static int create_save_subgraph_from_filter(char *filename) +static int create_save_subgraph_from_filter(char *filename, int withEdges) { Agraph_t *subg = agsubg(view->g[view->activeGraph], "temp", 1); FILE *outputfile; - Agnode_t* v; - Agraph_t* g; + Agnode_t *v; + Agraph_t *g; + int ret; g = view->g[view->activeGraph]; for (v = agfstnode(g); v; v = agnxtnode(g, v)) { if (ND_selected(v)) agsubnode(subg, v, 1); } + if (withEdges) + induceEdges (view->g[view->activeGraph], subg); if ((outputfile = fopen(filename, "w"))) { - int ret = agwrite(subg, outputfile); - fclose (outputfile); - if (ret) { - agdelsubg(view->g[view->activeGraph], subg); - return 1; - } else { - agdelsubg(view->g[view->activeGraph], subg); - return 0; - } + ret = agwrite(subg, outputfile); + fclose(outputfile); } else { - agdelsubg(view->g[view->activeGraph], subg); - return 0; + fprintf (stderr, "Could not open %s for writing\n", filename); + ret = 1; } - - + agdelsubg(view->g[view->activeGraph], subg); + return ret; } -static void set_visibility(Agraph_t* g,int visibility) +static void set_visibility(Agraph_t * g, int visibility) { Agnode_t *v; - char bf1[2]; - char* bf2; - Agsym_t* visible_attr = GN_visible(g); - Agsym_t* selected_attr = GN_selected(g); + char *bf; + Agsym_t *visible_attr = GN_visible(g); + Agsym_t *selected_attr = GN_selected(g); - if (!visible_attr) - visible_attr = GN_visible(g) = agattr(g, AGNODE,"visible","1"); if (!selected_attr) return; - sprintf(bf1,"%d",visibility); - for (v = agfstnode(g); v; v = agnxtnode(g, v)) - { - bf2=agxget(v,selected_attr); - if((*bf2 == '\0') || (strcmp(bf2,"0")==0)) - continue; - agxset(v,visible_attr,bf1); + if (!visible_attr) + visible_attr = GN_visible(g) = agattr(g, AGNODE, "visible", "1"); + if (visibility) + bf = "1"; + else + bf = "0"; + for (v = agfstnode(g); v; v = agnxtnode(g, v)) { + if (!ND_selected(v)) continue; + agxset(v, visible_attr, bf); } } int tv_show_all(void) { - set_visibility(view->g[view->activeGraph],1); - updateSmGraph(view->g[view->activeGraph],view->Topview); + set_visibility(view->g[view->activeGraph], 1); + updateSmGraph(view->g[view->activeGraph], view->Topview); return 1; } int tv_hide_all(void) { - set_visibility(view->g[view->activeGraph],0); - updateSmGraph(view->g[view->activeGraph],view->Topview); + set_visibility(view->g[view->activeGraph], 0); + updateSmGraph(view->g[view->activeGraph], view->Topview); return 1; } -int tv_save_as(void) + +int tv_save_as(int withEdges) { GtkWidget *dialog; dialog = gtk_file_chooser_dialog_new("Save File", @@ -120,7 +136,7 @@ int tv_save_as(void) char *filename; filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - create_save_subgraph_from_filter(filename); + create_save_subgraph_from_filter(filename, withEdges); g_free(filename); gtk_widget_destroy(dialog); @@ -132,47 +148,57 @@ int tv_save_as(void) return 0; } - - -static void create_text_column(char* Title,GtkTreeView* tree,int asso,int editable) +static void create_text_column(char *Title, GtkTreeView * tree, int asso, + int editable) { - PangoColor c; + PangoColor c; GtkTreeViewColumn *column; GtkCellRendererText *renderer; - renderer = (GtkCellRendererText*)gtk_cell_renderer_text_new (); - ((GtkCellRenderer*)renderer)->mode=GTK_CELL_RENDERER_MODE_EDITABLE; - renderer->editable=editable; - c.blue=0; - c.green=1; - c.red=0; - renderer->foreground=c; - + renderer = (GtkCellRendererText *) gtk_cell_renderer_text_new(); + ((GtkCellRenderer *) renderer)->mode = GTK_CELL_RENDERER_MODE_EDITABLE; + renderer->editable = editable; + c.blue = 0; + c.green = 1; + c.red = 0; + renderer->foreground = c; - column = gtk_tree_view_column_new_with_attributes (Title,(GtkCellRenderer*)renderer,"text",asso,NULL); + column = + gtk_tree_view_column_new_with_attributes(Title, + (GtkCellRenderer *) + renderer, "text", asso, + NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column); - gtk_tree_view_column_set_resizable (column,1); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); + gtk_tree_view_column_set_resizable(column, 1); } -static void create_toggle_column(char* Title,GtkTreeView* tree,int asso,int editable) -{ - GtkTreeViewColumn *column; - GtkCellRendererToggle* renderer; - renderer =(GtkCellRendererToggle*)gtk_cell_renderer_toggle_new (); - renderer->activatable=editable; - g_object_set (G_OBJECT (renderer),"foreground", "red",NULL); - column = gtk_tree_view_column_new_with_attributes (Title,(GtkCellRenderer*)renderer,"active",asso,NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column); - gtk_tree_view_column_set_resizable (column,1); +static void create_toggle_column(char *Title, GtkTreeView * tree, int asso, + int editable) +{ + GtkTreeViewColumn *column; + GtkCellRendererToggle *renderer; + renderer = (GtkCellRendererToggle *) gtk_cell_renderer_toggle_new(); + renderer->activatable = editable; + /* g_object_set(G_OBJECT(renderer), "foreground", "red", NULL); */ + + column = + gtk_tree_view_column_new_with_attributes(Title, + (GtkCellRenderer *) + renderer, "active", asso, + NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); + gtk_tree_view_column_set_resizable(column, 1); } + #ifdef UNUSED -static int boolStrMap(char* str) +static int boolStrMap(char *str) { - if (strcmp(str,"1") ||strcmp(str,"true")|| strcmp(str,"TRUE") || strcmp(str,"True")) + if (strcmp(str, "1") || strcmp(str, "true") || strcmp(str, "TRUE") + || strcmp(str, "True")) return 1; return 0; @@ -180,202 +206,199 @@ static int boolStrMap(char* str) #endif -static void populate_data(Agraph_t* g,grid* grid) +static void populate_data(Agraph_t * g, grid * grid) { Agnode_t *v; - int id=0; + int id = 0; GtkTreeIter iter; - static GValue valueData; - static GValue* value; - + GValue value = {0}; char* bf; - value=&valueData; - - //GValue* g_value_init (GValue *value,GType g_type); -/* if(!value) - value=(GValue*)malloc(sizeof(GValue));*/ - value=g_value_init (value,G_TYPE_STRING); + gridCol* cp; for (v = agfstnode(g); v; v = agnxtnode(g, v)) { - if (!ND_selected(v)) continue; - gtk_tree_store_append (grid->store, &iter, NULL); - - for (id=1;id < grid->count;id ++) - { - g_value_unset (value); - value=g_value_init (value,grid->columns[id]->type); - if(id==1) - bf=agnameof(v); + if (!ND_selected(v)) + continue; + gtk_tree_store_append(grid->store, &iter, NULL); + + for (id = 0; id < grid->count; id++) { + cp = grid->columns[id]; + if (cp->name == ID) continue; + + if (cp->name == Name) + bf = agnameof(v); else - bf=agget(v,grid->columns[id]->name); - if((!bf) && (id !=2)) + bf = agget(v, cp->name); + if ((!bf) && (cp->name != Visible)) continue; - switch(grid->columns[id]->type) - { + g_value_init(&value, cp->type); + switch (grid->columns[id]->type) { case G_TYPE_BOOLEAN: - if(bf) - { - if((strcmp(bf,"1")==0) || (strcmp(bf,"true")==0) || (strcmp(bf,"True")==0)) - g_value_set_boolean (value, 1); - else - g_value_set_boolean (value, 0); - } + if (bf) { + if ((strcmp(bf, "1") == 0) || (strcmp(bf, "true") == 0) + || (strcmp(bf, "True") == 0)) + g_value_set_boolean(&value, 1); else - { - if(id==2) - g_value_set_boolean (value, 1); - } - + g_value_set_boolean(&value, 0); + } else { + if (cp->name == Visible) + g_value_set_boolean(&value, 1); + } break; default: - g_value_set_string (value, bf); + g_value_set_static_string(&value, bf); } - gtk_tree_store_set_value(grid->store,&iter,id,value); - } - + gtk_tree_store_set_value(grid->store, &iter, id, &value); + g_value_unset(&value); + } } } -static GtkTreeStore* update_tree_store(GtkTreeStore* store,int ncolumns,GType *types) +static GtkTreeStore *update_tree_store(GtkTreeStore * store, int ncolumns, + GType * types) { - if ((ncolumns ==0) || (types==NULL)) + if ((ncolumns == 0) || (types == NULL)) return NULL; - if(store) - { + if (store) { gtk_tree_store_clear(store); g_object_unref(store); } - - store=gtk_tree_store_newv (ncolumns,types); + + store = gtk_tree_store_newv(ncolumns, types); return store; } -static void create_column(gridCol* c,GtkTreeView *tree,int id) +static void create_column(gridCol * c, GtkTreeView * tree, int id) { if (!c) return; - switch (c->type) - { + switch (c->type) { case G_TYPE_STRING: case G_TYPE_INT: - create_text_column(c->name,tree,id,c->editable); + create_text_column(c->name, tree, id, c->editable); break; case G_TYPE_BOOLEAN: - create_toggle_column(c->name,tree,id,c->editable); + create_toggle_column(c->name, tree, id, c->editable); break; default: - create_text_column(c->name,tree,id,c->editable); + create_text_column(c->name, tree, id, c->editable); } } -GtkTreeView* update_tree (GtkTreeView *tree,grid* g) +static GtkTreeView *update_tree(GtkTreeView * tree, grid * g) { - GtkTreeStore* store=NULL; - GtkTreeViewColumn* column; + GtkTreeStore *store = NULL; + GtkTreeViewColumn *column; GType *types; - int id=0; + int id = 0; - if(tree) { - while ((column=gtk_tree_view_get_column(tree,0))) /*clear all columns*/ - gtk_tree_view_remove_column(tree,column); - store=(GtkTreeStore*)gtk_tree_view_get_model(tree); - } - else { - tree=(GtkTreeView*)gtk_tree_view_new(); - gtk_widget_show((GtkWidget*)tree); + if (tree) { + while ((column = gtk_tree_view_get_column(tree, 0))) /*clear all columns */ + gtk_tree_view_remove_column(tree, column); + store = (GtkTreeStore *) gtk_tree_view_get_model(tree); + } else { + tree = (GtkTreeView *) gtk_tree_view_new(); + gtk_widget_show((GtkWidget *) tree); - gtk_container_add((GtkContainer*)glade_xml_get_widget(xml, "scrolledwindow9"),(GtkWidget*)tree); + gtk_container_add((GtkContainer *) + glade_xml_get_widget(xml, "scrolledwindow9"), + (GtkWidget *) tree); } - if(g->count > 0) { - types=N_NEW(g->count, GType); - for (id=0;id < g->count;id++) - types[id]=g->columns[id]->type; - store=update_tree_store(g->store,g->count,types); - gtk_tree_view_set_model(tree,(GtkTreeModel*)store); - /*insert columns*/ - for (id=0;id < g->count;id ++) - create_column(g->columns[id],tree,id); + if (g->count > 0) { + types = N_NEW(g->count, GType); + for (id = 0; id < g->count; id++) + types[id] = g->columns[id]->type; + store = update_tree_store(g->store, g->count, types); + free (types); + gtk_tree_view_set_model(tree, (GtkTreeModel *) store); + /*insert columns */ + for (id = 0; id < g->count; id++) + create_column(g->columns[id], tree, id); } - g->store=store; + g->store = store; return tree; } -static void add_column(grid* g,char* name,int editable,GType g_type) +static void add_column(grid * g, char *name, int editable, GType g_type) { - if (*name == '\0') return; - g->columns=(gridCol**)realloc(g->columns,sizeof(gridCol*)*(g->count+1)); + if (*name == '\0') + return; + g->columns = + (gridCol **) realloc(g->columns, + sizeof(gridCol *) * (g->count + 1)); g->columns[g->count] = NEW(gridCol); - g->columns[g->count]->editable=editable; - g->columns[g->count]->name=strdup(name); - g->columns[g->count]->type=g_type; + g->columns[g->count]->editable = editable; + g->columns[g->count]->name = name; + g->columns[g->count]->type = g_type; g->count++; } -static void clear_grid(grid* g, char* flds) +static void clearGrid(grid * g) { int id; - if (g->count) { - for (id=0;id < g->count ; id++) { - free(g->columns[id]->name); - free (g->columns[id]); - } + for (id = 0; id < g->count; id++) { + free(g->columns[id]); } - free (g->columns); + free(g->columns); + free(g->buf); g->count = 0; g->columns = 0; - g->flds=flds; + g->flds = 0; } -static grid* initGrid(char* flds) +static grid *initGrid() { - grid* gr = NEW(grid); - gr->columns=NULL; - gr->count=0; - gr->flds=flds; + grid *gr = NEW(grid); + gr->columns = NULL; + gr->count = 0; + gr->buf = 0; return gr; } -static grid* update_columns(grid* g,char* str) +static grid *update_columns(grid * g, char *str) { /*free existing memory if necessary */ - char* a; - if(g) { - if (g->flds != str) clear_grid(g, str); - else return g; - } - else - g=initGrid(str); - add_column(g,"ID",0,G_TYPE_STRING); - add_column(g,"Name",0,G_TYPE_STRING); - add_column(g,"visible",0,G_TYPE_BOOLEAN); - if(!str) + char *a; + char *buf; + + if (g) { + if (g->flds != str) + clearGrid(g); + else + return g; + } else + g = initGrid(str); + /* add_column(g, ID, 0, G_TYPE_STRING); */ + add_column(g, Name, 0, G_TYPE_STRING); + /* add_column(g, visible, 0, G_TYPE_BOOLEAN); */ + if (!str) return g; - - a=strtok(str,","); - add_column(g,a,1,G_TYPE_STRING); - while ((a=strtok(NULL,","))) - add_column(g,a,1,G_TYPE_STRING); + + g->flds = str; + buf = strdup (str); /* need to dup because str is actual graph attribute value */ + a = strtok(buf, ","); + add_column(g, a, 1, G_TYPE_STRING); + while ((a = strtok(NULL, ","))) + add_column(g, a, 1, G_TYPE_STRING); return g; } -void setup_tree (Agraph_t* g) +void setup_tree(Agraph_t * g) { /* - G_TYPE_STRING: - G_TYPE_INT: - G_TYPE_BOOLEAN: - */ + G_TYPE_STRING: + G_TYPE_INT: + G_TYPE_BOOLEAN: + */ static GtkTreeView *tree; - static grid* gr; - char* buf = agget(g,"datacolumns"); + static grid *gr; + char *buf = agget(g, "datacolumns"); - gr = update_columns(gr,buf); - tree=update_tree (tree,gr); - populate_data(g,gr); + gr = update_columns(gr, buf); + tree = update_tree(tree, gr); + populate_data(g, gr); } - diff --git a/cmd/smyrna/tvnodes.h b/cmd/smyrna/tvnodes.h index d70e94c20..0852e8ec7 100755 --- a/cmd/smyrna/tvnodes.h +++ b/cmd/smyrna/tvnodes.h @@ -131,7 +131,7 @@ extern "C" { */ int tv_show_all(void); int tv_hide_all(void); - int tv_save_as(void); + int tv_save_as(int); void setup_tree (Agraph_t* g); #ifdef __cplusplus