static void _object_remove(DiagramData *dia, Layer *layer, DiaObject *obj, DiagramTreeModel *dtm) { GtkTreePath *path; GtkTreeIter _iter; GtkTreeIter *iter = &_iter; gboolean last_child = layer_object_count (layer) == 0; g_return_if_fail (DIA_DIAGRAM(dia) != NULL); NODE_DIAGRAM(iter) = dia; NODE_LAYER(iter) = layer; NODE_OBJECT(iter) = obj; path = _dtm_get_path (GTK_TREE_MODEL (dtm), iter); gtk_tree_model_row_deleted (GTK_TREE_MODEL (dtm), path); gtk_tree_path_free (path); /* enforce update - but the arrow on layer does not vanish */ if (last_child) { NODE_OBJECT(iter) = NULL; path = _dtm_get_path (GTK_TREE_MODEL (dtm), iter); gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (dtm), path, iter); gtk_tree_path_free (path); } }
/* listen on the diagram for object add/remove */ static void _object_add (DiagramData *dia, Layer *layer, DiaObject *obj, DiagramTreeModel *dtm) { GtkTreePath *path; GtkTreeIter _iter; GtkTreeIter *iter = &_iter; /* a bit backward: the first child is in the diagram, but not the tree yet */ gboolean had_child = layer_object_count (layer) > 1; g_return_if_fail (DIA_DIAGRAM(dia) != NULL); NODE_DIAGRAM(iter) = dia; NODE_LAYER(iter) = layer; NODE_OBJECT(iter) = obj; /* FIXME: this may get called before the layer is added to the tree */ path = _dtm_get_path (GTK_TREE_MODEL (dtm), iter); if (path) { gtk_tree_model_row_inserted (GTK_TREE_MODEL (dtm), path, iter); /* enforce update */ if (!had_child && gtk_tree_path_up (path)) gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (dtm), path, &_iter); gtk_tree_path_free (path); } }
/* SORTABLE * Wrapper around the original model to allow sorting by various columns IDs */ static gint cmp_diagram (GtkTreeIter *a, GtkTreeIter *b) { DiagramData *pa = NODE_DIAGRAM(a), *pb = NODE_DIAGRAM(b); gchar *na, *nb; gint ret; if (pa == pb) return 0; na = diagram_get_name (DIA_DIAGRAM(pa)); nb = diagram_get_name (DIA_DIAGRAM(pa)); if (!na || !nb) return (na > nb) ? -1 : 1; ret = strcmp (na, nb); g_free (na); g_free (nb); return ret; }
/** Connects a python function to a signal. * @param self The PyDiaDiagram this is a method of. * @param args A tuple containing the arguments, a str for signal name * and a callable object (like a function) */ static PyObject * PyDiaDiagram_ConnectAfter(PyDiaDiagram *self, PyObject *args) { PyObject *func; char *signal; /* Check arguments */ if (!PyArg_ParseTuple(args, "sO:connect_after",&signal,&func)) return NULL; /* Check that the arg is callable */ if (!PyCallable_Check(func)) { PyErr_SetString(PyExc_TypeError, "Second parameter must be callable"); return NULL; } /* check if the signals name is valid */ if ( strcmp("removed",signal) == 0 || strcmp("selection_changed",signal) == 0) { Py_INCREF(func); /* stay alive, where to kill ?? */ /* connect to signal after by signal name */ if (strcmp("removed",signal) == 0) { g_signal_connect_after(DIA_DIAGRAM(self->dia),"removed",G_CALLBACK(PyDiaDiagram_CallbackRemoved), func); } if (strcmp("selection_changed",signal) == 0) { g_signal_connect_after(DIA_DIAGRAM(self->dia),"selection_changed",G_CALLBACK(PyDiaDiagram_CallbackSelectionChanged), func); } Py_INCREF(Py_None); return Py_None; } else { PyErr_SetString(PyExc_TypeError, "Wrong signal name"); return NULL; } }
static void diagram_finalize(GObject *object) { Diagram *dia = DIA_DIAGRAM(object); assert(dia->displays==NULL); if (dia->filename) g_free(dia->filename); dia->filename = NULL; G_OBJECT_CLASS (parent_class)->finalize (object); }
static void _dtm_init (DiagramTreeModel *dtm) { /* connect to intersting state changes */ g_signal_connect (G_OBJECT (dia_application_get ()), "diagram_add", G_CALLBACK (_diagram_add), dtm); g_signal_connect (G_OBJECT (dia_application_get ()), "diagram_change", G_CALLBACK (_diagram_change), dtm); g_signal_connect (G_OBJECT(dia_application_get ()), "diagram_remove", G_CALLBACK (_diagram_remove), dtm); /* also connect to every already existing diagram */ { GList *list = dia_open_diagrams(); while (list) { _dtm_listen_on_diagram (dtm, DIA_DIAGRAM(list->data)); list = g_list_next (list); } } }
static void _object_remove(DiagramData *dia, Layer *layer, DiaObject *obj, DiagramTreeModel *dtm) { GtkTreePath *path; GtkTreeIter _iter; GtkTreeIter *iter = &_iter; g_return_if_fail (DIA_DIAGRAM(dia) != NULL); NODE_DIAGRAM(iter) = dia; NODE_LAYER(iter) = layer; NODE_OBJECT(iter) = obj; path = _dtm_get_path (GTK_TREE_MODEL (dtm), iter); gtk_tree_model_row_deleted (GTK_TREE_MODEL (dtm), path); gtk_tree_path_free (path); }
static void diagram_dispose (GObject *object) { Diagram *dia = DIA_DIAGRAM(object); assert(dia->displays==NULL); if (g_list_index(open_diagrams, dia) >= 0) { dia_diagram_remove(dia); open_diagrams = g_list_remove(open_diagrams, dia); layer_dialog_update_diagram_list(); } if (dia->undo) undo_destroy(dia->undo); dia->undo = NULL; diagram_cleanup_autosave(dia); G_OBJECT_CLASS (parent_class)->dispose (object); }
static void _dtm_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, GValue *value) { switch (column) { case DIAGRAM_COLUMN : g_value_init (value, G_TYPE_OBJECT); g_value_set_object (value, NODE_DIAGRAM(iter)); break; case LAYER_COLUMN : g_value_init (value, G_TYPE_POINTER); g_value_set_pointer (value, NODE_LAYER(iter)); break; case OBJECT_COLUMN : g_value_init (value, G_TYPE_POINTER); g_value_set_pointer (value, NODE_OBJECT(iter)); break; case NAME_COLUMN : g_value_init (value, G_TYPE_STRING); /* deduce the requested name from the iter */ if (NODE_OBJECT(iter)) g_value_set_string (value, object_get_displayname (NODE_OBJECT (iter))); else if (NODE_LAYER(iter)) g_value_set_string (value, layer_get_name (NODE_LAYER (iter))); else if (NODE_DIAGRAM(iter)) g_value_set_string (value, diagram_get_name (DIA_DIAGRAM(NODE_DIAGRAM(iter)))); else /* warn on it? */ g_value_set_string (value, NULL); break; default : g_assert_not_reached (); } }
/* listen on the diagram for object add/remove */ static void _object_add (DiagramData *dia, Layer *layer, DiaObject *obj, DiagramTreeModel *dtm) { GtkTreePath *path; GtkTreeIter _iter; GtkTreeIter *iter = &_iter; g_return_if_fail (DIA_DIAGRAM(dia) != NULL); NODE_DIAGRAM(iter) = dia; NODE_LAYER(iter) = layer; NODE_OBJECT(iter) = obj; /* FIXME: this may get called before the layer is added to the tree */ path = _dtm_get_path (GTK_TREE_MODEL (dtm), iter); if (path) { gtk_tree_model_row_inserted (GTK_TREE_MODEL (dtm), path, iter); gtk_tree_path_free (path); } }
static PyObject * PyDiaDiagramData_GetAttr(PyDiaDiagramData *self, gchar *attr) { Diagram *diagram = DIA_DIAGRAM(self->data); if (!strcmp(attr, "__members__")) return Py_BuildValue("[ssssssssssss]", "extents", "bg_color", "paper", "layers", "active_layer", "grid_width", "grid_visible", "hguides", "vguides", "layers", "active_layer", "selected" ); else if (!strcmp(attr, "extents")) return PyDiaRectangle_New(&self->data->extents, NULL); else if (!strcmp(attr, "bg_color")) { return PyDiaColor_New (&(self->data->bg_color)); } else if (!strcmp(attr, "layers")) { guint i, len = self->data->layers->len; PyObject *ret = PyTuple_New(len); for (i = 0; i < len; i++) PyTuple_SetItem(ret, i, PyDiaLayer_New( g_ptr_array_index(self->data->layers, i))); return ret; } else if (!strcmp(attr, "active_layer")) { return PyDiaLayer_New(self->data->active_layer); } else if (!strcmp(attr, "paper")) { return PyDiaPaperinfo_New (&self->data->paper); } else if (diagram && !strcmp(attr, "grid_width")) return Py_BuildValue("(dd)", diagram->grid.width_x, diagram->grid.width_y); else if (diagram && !strcmp(attr, "grid_visible")) return Py_BuildValue("(ii)", diagram->grid.visible_x, diagram->grid.visible_y); else if (diagram && !strcmp(attr, "hguides")) { int len = diagram->guides.nhguides; PyObject *ret = PyTuple_New(len); int i; for (i = 0; i < len; i++) PyTuple_SetItem(ret, i, PyFloat_FromDouble(diagram->guides.hguides[i])); return ret; } else if (diagram && !strcmp(attr, "vguides")) { int len = diagram->guides.nvguides; PyObject *ret = PyTuple_New(len); int i; for (i = 0; i < len; i++) PyTuple_SetItem(ret, i, PyFloat_FromDouble(diagram->guides.vguides[i])); return ret; } else if (!strcmp(attr, "layers")) { guint i, len = self->data->layers->len; PyObject *ret = PyTuple_New(len); for (i = 0; i < len; i++) PyTuple_SetItem(ret, i, PyDiaLayer_New( g_ptr_array_index(self->data->layers, i))); return ret; } else if (!strcmp(attr, "active_layer")) { return PyDiaLayer_New(self->data->active_layer); } else if (!strcmp(attr, "selected")) { PyObject *ret; GList *tmp; gint i; ret = PyTuple_New(g_list_length(self->data->selected)); for (i = 0, tmp = self->data->selected; tmp; i++, tmp = tmp->next) PyTuple_SetItem(ret, i, PyDiaObject_New((DiaObject *)tmp->data)); return ret; } return Py_FindMethod(PyDiaDiagramData_Methods, (PyObject *)self, attr); }
/*! * \brief Calback function invoking layout algorithms from Dia's menu * \ingroup LayoutPlugin */ static ObjectChange * layout_callback (DiagramData *data, const gchar *filename, guint flags, /* further additions */ void *user_data, GraphCreateFunc func) { ObjectChange *changes = NULL; GList *nodes = NULL, *edges = NULL, *list; const char *algorithm = (const char*)user_data; /* from the selection create two lists */ list = data_get_sorted_selected (data); while (list) { DiaObject *o = (DiaObject *)list->data; if (!maybe_edge (o)) nodes = g_list_append (nodes, o); //FIXME: neither 1 nor num_handles-1 is guaranteed to be the second connection // it entirely depends on the objects implementation else if ( o->num_handles > 1 && o->handles[0]->connected_to && (o->handles[1]->connected_to || o->handles[o->num_handles-1]->connected_to)) edges = g_list_append (edges, o); list = g_list_next(list); } if (g_list_length (edges) < 1 || g_list_length (nodes) < 2) { message_warning (_("Please select edges and nodes to layout.")); } else { IGraph *g = func ? func () : NULL; if (!g) message_error (_("Graph creation failed")); else { std::vector<double> coords; /* transfer nodes and edges */ for (list = nodes; list != NULL; list = g_list_next(list)) { DiaObject *o = (DiaObject *)list->data; const Rectangle *bbox = dia_object_get_bounding_box (o); g->AddNode (bbox->left, bbox->top, bbox->right, bbox->bottom); } for (list = edges; list != NULL; list = g_list_next(list)) { DiaObject *o = (DiaObject *)list->data; DiaObject *src = o->handles[0]->connected_to->object; // see above: there is no guarantee ... DiaObject *dst = o->handles[1]->connected_to ? o->handles[1]->connected_to->object : o->handles[o->num_handles-1]->connected_to->object; if (_obj_get_bends (o, coords)) g->AddEdge (g_list_index (nodes, src), g_list_index (nodes, dst), &coords[0], coords.size()); else g->AddEdge (g_list_index (nodes, src), g_list_index (nodes, dst), NULL, 0); } IGraph::eResult res; if ((res = g->Layout (algorithm)) != IGraph::SUCCESS) { const char *sErr; switch (res) { case IGraph::NO_MODULE : sErr = _("No such module."); break; case IGraph::OUT_OF_MEMORY : sErr = _("Out of memory."); break; case IGraph::NO_TREE: sErr = _("Not a tree."); break; case IGraph::NO_FOREST: sErr = _("Not a forest."); break; case IGraph::FAILED_ALGORITHM: sErr = _("Failed algorithm."); break; case IGraph::FAILED_PRECONDITION: sErr = _("Failed precondition."); break; case IGraph::CRASHED : sErr = _("OGDF crashed."); break; default : sErr = _("Unknown reason"); break; } message_warning (_("Layout '%s' failed.\n%s"), (const char*)user_data, sErr); } else { changes = change_list_create (); /* transfer back information */ int n; for (n = 0, list = nodes; list != NULL; list = g_list_next (list), ++n) { Point pt; if (g->GetNodePosition (n, &pt.x, &pt.y)) { DiaObject *o = (DiaObject *)list->data; GPtrArray *props = g_ptr_array_new (); //FIXME: can't use "obj_pos", it is not read in usual update_data impementations // "elem_corner" will only work for Element derived classes, but that covers most // of the cases here ... prop_list_add_point (props, "elem_corner", &pt); change_list_add (changes, object_apply_props (o, props)); } } // first update to reuse the connected points diagram_update_connections_selection(DIA_DIAGRAM (data)); /* use edge bends, if any */ int e; for (e = 0, list = edges; list != NULL; list = g_list_next (list), ++e) { DiaObject *o = (DiaObject *)list->data; // number of bends / 2 is the number of points int n = g->GetEdgeBends (e, NULL, 0); if (n >= 0) { // with 0 it is just a reset of the exisiting line try { coords.resize (n); } catch (std::bad_alloc& ex) { g_warning ("%s", ex.what()); continue; } g->GetEdgeBends (e, &coords[0], n); change_list_add (changes, _obj_set_bends (o, coords)); } } /* update view */ diagram_update_connections_selection(DIA_DIAGRAM (data)); } g->Release (); } } g_list_free (nodes); g_list_free (edges); return changes; }