def __refresh_comboBoxB_suggestion(self): '''Refresh comboxB, filled it with suggested node name, based on the value of comboxA.''' if self.m_radioBox_type.GetSelection() == 0: self.m_comboBox_nodeB.Clear() return # Save the value in old_v. old_v = self.m_comboBox_nodeB.GetValue() edges = self.data_graph.get_edges() nodes = self.data_graph.get_nodes() rawA = self.m_comboBox_nodeA.GetValue().strip().encode('utf8') # Remove label part from nA if existed. nA = self.__name_remove_label(rawA) # Get all node's name. s_n = set() need_remove_nodes = set() for n in nodes: _n = remove_double_quote( n.get_name() ) _l = remove_double_quote( n.get_label() ) _n_text = self.__name_add_label(_n, _l) if _n not in ['node', 'edge']: # Exclude wildcard node. s_n.add(_n_text) ### Remove the node without label appended. if _n != _n_text: need_remove_nodes.add(_n) # Get all end-nodes of edges if start ending not nA. for e in edges: nS = remove_double_quote( e.get_source() ) nD = remove_double_quote( e.get_destination() ) if nA != nS: s_n.add(nS); s_n.add(nD) else: nD = self.__name_remove_label(nD) need_remove_nodes.add(nD) if nA == nD: ### Find a self connected node.x need_remove_nodes.add(rawA) s_n = s_n - need_remove_nodes s_n = list(s_n); s_n.sort() self.m_comboBox_nodeB.Clear() for n in s_n: self.m_comboBox_nodeB.Append(n.decode('utf8')) # Restore the nodeA value. if old_v.encode('utf8') in s_n: self.m_comboBox_nodeB.SetValue(old_v) return
def getAppendValue(self): '''If "append node" checked, return node in string; else return nodes in tuple.''' vCheck = self.m_radioBox_type.GetSelection() vA = remove_double_quote( self.m_comboBox_nodeA.GetValue().encode('utf8') ) vB = remove_double_quote( self.m_comboBox_nodeB.GetValue().encode('utf8') ) if vCheck == 0: return 'node', self.__name_remove_label(vA) elif vCheck == 1: return 'edge', (self.__name_remove_label(vA), self.__name_remove_label(vB)) else: return 'subgraph', vA
def EG_get_all_edge_names(self, root_graph=None): """Get all edge names in the graph, include edges in all subgraph.""" if root_graph is None: root_graph = self edges = root_graph.get_edges() result = [(remove_double_quote(e.get_source()), remove_double_quote(e.get_destination())) for e in edges] sgs = root_graph.get_subgraphs() for sg in sgs: result += self.EG_get_all_edge_names(sg) return list(set(result))
def EG_get_all_edge_names(self, root_graph=None): '''Get all edge names in the graph, include edges in all subgraph.''' if root_graph is None: root_graph = self edges = root_graph.get_edges() result = [ ( remove_double_quote( e.get_source() ), \ remove_double_quote( e.get_destination() ) ) \ for e in edges ] sgs = root_graph.get_subgraphs() for sg in sgs: result += self.EG_get_all_edge_names(sg) return list(set(result))
def EG_get_subgraph_by_name(self, name, root_graph=None): '''Get node by name. Return None if not found.''' if root_graph is None: root_graph = self sg_name = remove_double_quote(name) sgs = root_graph.get_subgraphs() r = None for sg in sgs: _name = remove_double_quote(sg.get_name()) if _name == sg_name: r = sg break return r
def getAppendValue(self): '''If "append node" checked, return node in string; else return nodes in tuple.''' vCheck = self.m_radioBox_type.GetSelection() vA = remove_double_quote( self.m_comboBox_nodeA.GetValue() ) vB = remove_double_quote( self.m_comboBox_nodeB.GetValue() ) sH = self.m_comboBox_shape.GetValue() sT = self.m_comboBox_style.GetValue() if vCheck == 0: return 'node', escape_dot_string(vA) , (sH, sT) elif vCheck == 1: return 'edge', (escape_dot_string(vA), escape_dot_string(vB)) , (sH, sT) elif vCheck == 2: return 'subgraph', escape_dot_string(vA) elif vCheck == 3: return 'samerank', (escape_dot_string(vA), escape_dot_string(vB))
def EG_get_subgraph_by_name(self, name, root_graph=None): """Get node by name. Return None if not found.""" if root_graph is None: root_graph = self sg_name = remove_double_quote(name) sgs = root_graph.get_subgraphs() r = None for sg in sgs: _name = remove_double_quote(sg.get_name()) if _name == sg_name: r = sg break return r
def EG_get_node_by_name(self, name, root_graph=None): '''Get node by name. Return None if not found.''' if root_graph is None: root_graph = self n_name = remove_double_quote(name) nodes = root_graph.get_nodes() r = None for n in nodes: _name = remove_double_quote(n.get_name()) if _name == n_name: r = n break return r
def EG_get_node_by_name(self, name, root_graph=None): """Get node by name. Return None if not found.""" if root_graph is None: root_graph = self n_name = remove_double_quote(name) nodes = root_graph.get_nodes() r = None for n in nodes: _name = remove_double_quote(n.get_name()) if _name == n_name: r = n break return r
def update_graph(self, graph=None): '''Updata data graph and then refresh the whole UI. IF graph == None, just refresh the preview.''' if not (graph is None): self.data_graph = ExtGraph.ExtGraph(obj_dict=graph.obj_dict) self.m_tree.DeleteAllItems() self.m_pgManager1.Clear() ### Insert wildcard item at 1st. g_name = remove_double_quote(self.data_graph.get_name()) root = self.m_tree.AddRoot(g_name, 1) self.m_tree.SetItemData(root, ('graph', self.data_graph)) self.m_tree.SetItemImage(root, self.img_dict[('graph', 'color')]) self.__spread_tree(root) self.m_tree.ExpandAll() self.m_tree.SelectItem(root) self.onItemSelected(None) # Refresh image panel. self.data_graph.refresh_bitmap() # Set zoom ratio. self.bitmap_zoom_ratio = 1.0 self.m_staticText_zoom.SetLabel('Zoom:%3d%%'%100) else: # Just refresh image panel. self.data_graph.refresh_bitmap() # Set scroll. img = self.data_graph.get_bitmap() vw = img.GetWidth()*self.bitmap_zoom_ratio vh = img.GetHeight()*self.bitmap_zoom_ratio self.m_panel_paint.SetVirtualSize((vw, vh)) self.m_panel_paint.SetScrollRate(20,20) #self.m_panel_paint.SetScrollbars(1,1,vw, vh) self.m_panel_paint.Refresh() ### Set window title. title = 'Dot Editor' if self.file_path is None: if self.is_data_changed: title += ' - *' else: if self.is_data_changed: title = 'Dot Editor - *'+self.file_path else: title = 'Dot Editor - '+self.file_path self.SetTitle(title) return
def EG_get_edge_by_names(self, name_pair, root_graph=None): '''Get edge by names of source and destination. Return None if not found.''' if root_graph is None: root_graph = self nameA = remove_double_quote(name_pair[0]) nameB = remove_double_quote(name_pair[1]) edges = root_graph.get_edges() r = None for e in edges: n = remove_double_quote(e.get_source()) n1 = remove_double_quote(e.get_destination()) if ((n == nameA) and (n1 == nameB)): r = e break return r
def EG_get_edge_by_names(self, name_pair, root_graph=None): """Get edge by names of source and destination. Return None if not found.""" if root_graph is None: root_graph = self nameA = remove_double_quote(name_pair[0]) nameB = remove_double_quote(name_pair[1]) edges = root_graph.get_edges() r = None for e in edges: n = remove_double_quote(e.get_source()) n1 = remove_double_quote(e.get_destination()) if (n == nameA) and (n1 == nameB): r = e break return r
def __refresh_comboBoxA_suggestion(self): '''Refresh comboxA, filled it with suggested node name.''' edges = self.data_graph.get_edges() nodes = self.data_graph.get_nodes() # Save the value in old_v. old_v = self.m_comboBox_nodeA.GetValue() ### Generate suggestion when Appending Node. if self.m_radioBox_type.GetSelection() == 0: # Get all node's name. all_n = set() for n in nodes: all_n.add( remove_double_quote(n.get_name()) ) # Get all end-node of edges that not in all_n. s_n = set() for e in edges: nS = remove_double_quote( e.get_source() ) nD = remove_double_quote( e.get_destination() ) for n in [nS, nD]: if not (n in all_n): s_n.add(n) s_n = list(s_n); s_n.sort() ### Generate suggestion when Appending Edge. else: # Get all node name in graph. Include all end-nodes in edges. all_n = set() need_remove_nodes = set() for n in nodes: _n = remove_double_quote( n.get_name() ) _l = remove_double_quote( n.get_label() ) _n_text = self.__name_add_label(_n, _l) if _n not in ['node', 'edge']: # Exclude wildcard node. all_n.add(_n_text) ### Remove the node without label appended. if _n != _n_text: need_remove_nodes.add(_n) for e in edges: nS = remove_double_quote( e.get_source() ) nD = remove_double_quote( e.get_destination() ) all_n.add(nS); all_n.add(nD) s_n = all_n - need_remove_nodes s_n = list(s_n); s_n.sort() self.m_comboBox_nodeA.Clear() for n in s_n: self.m_comboBox_nodeA.Append(n.decode('utf8')) # Restore the nodeA value. if old_v.encode('utf8') in s_n: self.m_comboBox_nodeA.SetValue(old_v) return
def __spread_tree(self, rootid): '''A recursive function to add all data from graph into m_tree_ctrl.''' _, graph = self.m_tree.GetItemPyData(rootid) ### Add wildcard nodes. for n in ['node', 'edge']: n_id = self.m_tree.AppendItem(rootid, n) n_data = self.data_graph.EG_get_node_by_name(n, root_graph=graph) self.m_tree.SetItemPyData(n_id, ('node', n_data)) self.m_tree.SetItemImage(n_id, self.img_dict[(n, 'gray')]) ### Load nodes. for n in graph.get_nodes(): n_name = remove_double_quote( n.get_name() ) if n_name.lower() in ['node', 'edge']: ### Skip the wildcard node. continue n_id = self.m_tree.AppendItem(rootid, n_name.decode('utf8')) self.m_tree.SetItemPyData(n_id, ('node', n)) self.m_tree.SetItemImage(n_id, self.img_dict[('node', 'color')]) ### Load edges. for e in graph.get_edges(): n1 = remove_double_quote( e.get_source().decode('utf8') ) n2 = remove_double_quote( e.get_destination().decode('utf8') ) n_id = self.m_tree.AppendItem(rootid, "%s -> %s"%(n1,n2)) self.m_tree.SetItemPyData(n_id, ('edge', e)) self.m_tree.SetItemImage(n_id, self.img_dict[('edge', 'color')]) ### Load subgraphs. for sg in graph.get_subgraphs(): sg_name = remove_double_quote( sg.get_name().decode('utf8') ) n_id = self.m_tree.AppendItem(rootid, sg_name) self.m_tree.SetItemPyData(n_id, ('graph', sg)) self.m_tree.SetItemImage(n_id, self.img_dict[('graph', 'color')]) self.__spread_tree(n_id) return
def __spread_tree(self, rootid): '''A recursive function to add all data from graph into m_tree_ctrl.''' _, graph = self.m_tree.GetItemData(rootid) ### Add wildcard nodes. for n in ['node', 'edge']: n_id = self.m_tree.AppendItem(rootid, n) n_data = self.data_graph.EG_get_node_by_name(n, root_graph=graph) self.m_tree.SetItemData(n_id, ('node', n_data)) self.m_tree.SetItemImage(n_id, self.img_dict[(n, 'gray')]) ### Load nodes. for n in graph.get_nodes(): n_name = remove_double_quote( n.get_name() ) if n_name.lower() in ['node', 'edge']: ### Skip the wildcard node. continue n_id = self.m_tree.AppendItem(rootid, n_name) self.m_tree.SetItemData(n_id, ('node', n)) self.m_tree.SetItemImage(n_id, self.img_dict[('node', 'color')]) ### Load edges. for e in graph.get_edges(): n1 = remove_double_quote( e.get_source() ) n2 = remove_double_quote( e.get_destination() ) n_id = self.m_tree.AppendItem(rootid, "%s -> %s"%(n1,n2)) self.m_tree.SetItemData(n_id, ('edge', e)) self.m_tree.SetItemImage(n_id, self.img_dict[('edge', 'color')]) ### Load subgraphs. for sg in graph.get_subgraphs(): sg_name = remove_double_quote( sg.get_name() ) n_id = self.m_tree.AppendItem(rootid, sg_name) self.m_tree.SetItemData(n_id, ('graph', sg)) self.m_tree.SetItemImage(n_id, self.img_dict[('graph', 'color')]) self.__spread_tree(n_id) return
def StringToValue(self, s, flags): s = remove_double_quote(s).strip() # For emtpy value. if s == '': return True, None # Try to parse hex string. if s[0] == '#': try: if len(s) == 7: # RGB. r, g, b = colour.hex2rgb(s) return True, (255*r,255*g,255*b) elif len(s) == 9: # RGBA. r, g, b = colour.hex2rgb(s[:-2]) a = int(s[-2:], 16) return True, (255*r,255*g,255*b,a) else: return False except: return False # Try to parse HSV string. elif s[0].isdigit() or s[0] == '.': # Try to parse numbers try: # If get single int value. if s.isdigit(): return True, int(s) else: h,s,v = map(float, s.split(' ')) rgb = wx.Image.HSVtoRGB(wx.Image_HSVValue(h,s,v)) return True, (rgb.red, rgb.green, rgb.blue) except: return False # Color in string. else: scheme = self.__get_current_scheme() if scheme is None: return True, s colors = get_colors_in_scheme(scheme).keys() if s.strip() not in colors: return False return True, get_colors_in_scheme(scheme)[s]
def StringToValue(self, s, flags): s = remove_double_quote(s).strip() # For emtpy value. if s == '': return True, None # Try to parse hex string. if s[0] == '#': try: if len(s) == 7: # RGB. r, g, b = colour.hex2rgb(s) return True, (255*r,255*g,255*b) elif len(s) == 9: # RGBA. r, g, b = colour.hex2rgb(s[:-2]) a = int(s[-2:], 16) return True, (255*r,255*g,255*b,a) else: return False except: return False # Try to parse HSV string. elif s[0].isdigit() or s[0] == '.': # Try to parse numbers try: # If get single int value. if s.isdigit(): return True, int(s) else: h,s,v = map(float, s.split(' ')) rgb = wx.Image.HSVtoRGB(wx.Image_HSVValue(h,s,v)) return True, (rgb.red, rgb.green, rgb.blue) except: return False # Color in string. else: scheme = self.__get_current_scheme() if scheme is None: return True, s colors = get_colors_in_schcme(scheme).keys() if s.lower() not in colors: return False return True, s
def EG_get_all_node_names(self, root_graph=None): '''Get all node names in the graph, include nodes in all subgraph.''' if root_graph is None: root_graph = self nodes = root_graph.get_nodes() result = [ remove_double_quote(n.get_name()) for n in nodes ] sgs = root_graph.get_subgraphs() for sg in sgs: result += self.EG_get_all_node_names(sg) ### Remove wildcard node. try: result.remove('node'); result.remove('edge') except: pass return list(set(result))
def update_graph(self, graph=None): '''Updata data graph and then refresh the whole UI. IF graph == None, just refresh the preview.''' if not (graph is None): self.data_graph = ExtGraph.ExtGraph(obj_dict=graph.obj_dict) self.m_tree.DeleteAllItems() self.m_pgManager1.Clear() ### Insert wildcard item at 1st. g_name = remove_double_quote(self.data_graph.get_name().decode('utf8')) root = self.m_tree.AddRoot(g_name, 1) self.m_tree.SetItemPyData(root, ('graph', self.data_graph)) self.m_tree.SetItemImage(root, self.img_dict[('graph', 'color')]) self.__spread_tree(root) self.m_tree.ExpandAll() self.m_tree.SelectItem(root) ### Refresh image panel. self.data_graph.refresh_bitmap() img = self.data_graph.get_bitmap() self.m_panel_paint.SetVirtualSize((img.GetWidth(), \ img.GetHeight())) self.m_panel_paint.SetScrollRate(20,20) self.m_panel_paint.Refresh() ### Set window title. title = 'Dot Editor' if self.file_path is None: if self.is_data_changed: title += ' - *' else: if self.is_data_changed: title = 'Dot Editor - *'+self.file_path else: title = 'Dot Editor - '+self.file_path self.SetTitle(title) return
def EG_get_all_node_names(self, root_graph=None): """Get all node names in the graph, include nodes in all subgraph.""" if root_graph is None: root_graph = self nodes = root_graph.get_nodes() result = [remove_double_quote(n.get_name()) for n in nodes] sgs = root_graph.get_subgraphs() for sg in sgs: result += self.EG_get_all_node_names(sg) ### Remove wildcard node. try: result.remove("node") result.remove("edge") except: pass return list(set(result))
def onItemSelected(self, event): # If no item selected. selected_id = self.m_tree.GetSelection() if not selected_id.IsOk(): return i_name, i_type, item = self.GetSelectedItem() # Change the title of pg. _tail = '' if i_name in ['node', 'edge']: ### Change the wildcard item's type. i_type = i_name _tail = '(wildcard)' if selected_id == self.m_tree.GetRootItem(): _tail = '(global graph)' pg_title = i_type.capitalize() + ' Properties'+_tail self.m_staticText_pg.SetLabelText(pg_title) ### Read attrs from data_graph. data_attrs = {} if not item is None: data_attrs = item.get_attributes() ### Build PGManager. pm = self.m_pgManager1 pm.Clear() pm.AddPage() ### Very important!!! No-page would cause some strange thing happened. # Get attrs structure of the graph item. cates, _, attrs_dict = AttrsDef.get_dot_attr_structure(i_type) # Append pg items. for _c in cates: cat = wxpg.PropertyCategory(_c) pm.Append(cat) g_dict = attrs_dict[_c] groups = g_dict.keys(); # groups.sort() for _g in groups: a_list = g_dict[_g] if not _g is None: g_attr = wxpg.StringProperty(_g, value='<composed>') ### Magic string to compose child value. g_attr.Enable(False) g_attr.SetHelpString('attributes group of "%s", click left plus to expand.'%_g) g_id = pm.Append(g_attr) for a_name in a_list: pg = ExtPG.buildPG(a_name, i_type) if _g is None: pm.Append(pg) else: pm.AppendIn(g_id, pg) # Set attr value read from data_graph. if a_name in data_attrs.keys(): v = data_attrs[a_name] pg.SetValue(remove_double_quote(to_unicode(v))) # Set background to blue if attr value is different from default. pg.SetBackgroundColour('#ffffc0', -1) if not _g is None: pm.Collapse(_g) if cates.index(_c): pm.Collapse(_c) return
def onItemSelected(self, event): # If no item selected. selected_id = self.m_tree.GetSelection() if not selected_id.IsOk(): return i_name, i_type, item = self.GetSelectedItem() # Change the title of pg. _tail = '' if i_name in ['node', 'edge']: ### Change the wildcard item's type. i_type = i_name _tail = '(wildcard)' if selected_id == self.m_tree.GetRootItem(): _tail = '(global graph)' pg_title = i_type.capitalize() + ' Properties'+_tail self.m_staticText_pg.SetLabelText(pg_title) ### Read attrs from data_graph. data_attrs = {} if not item is None: data_attrs = item.get_attributes() ### Build PGManager. pm = self.m_pgManager1 pm.Clear() pm.AddPage() ### Very important!!! No-page would cause some strange thing happened. # Get attrs structure of the graph item. cates, _, attrs_dict = AttrsDef.get_dot_attr_structure(i_type) # Append pg items. for _c in cates: cat = wxpg.PropertyCategory(_c) pm.Append(cat) g_dict = attrs_dict[_c] groups = g_dict.keys(); # groups.sort() for _g in groups: a_list = g_dict[_g] if not _g is None: g_attr = wxpg.StringProperty(_g, value='<composed>') ### Magic string to compose child value. g_attr.Enable(False) g_attr.SetHelpString('attributes group of "%s", click left plus to expand.'%_g) g_id = pm.Append(g_attr) for a_name in a_list: pg = ExtPG.buildPG(a_name, i_type) if _g is None: pm.Append(pg) else: pm.AppendIn(g_id, pg) # Set attr value read from data_graph. if a_name in data_attrs.keys(): v = data_attrs[a_name] pg.SetValue(remove_double_quote(to_unicode(v).decode('utf8'))) # Set background to blue if attr value is different from default. pg.SetBackgroundColour('#ffffc0', -1) #if not _g is None: # pm.Collapse(g_attr) return
def __init__(self, diagram, verbose=False): self.verbose = verbose self.diagram = diagram '''Takes the dot graph as input''' self.entities = [] self.importants = [] self.relations = [] self.attributes = [] self.Graph = {} self.target = None self.relations_dict = {} self.attribute_dict = {} self.multi_value_attributes = {} for n in diagram.get_nodes(): if n.get_name() == self.EG_NODE_IGNORE or n.get_name( ) == self.EG_EDGE_IGNORE: continue if n.get_shape() == self.ENTITY_SHAPE: self.entities.append(remove_double_quote(n.get_name())) elif n.get_shape() == self.RELATION_SHAPE: self.relations.append(remove_double_quote(n.get_name())) else: self.attributes.append(remove_double_quote(n.get_name())) if n.get_peripheries(): self.multi_value_attributes[remove_double_quote( n.get_name())] = list() if n.get_fillcolor() == self.IMPORTANT_COLOR: self.importants.append(remove_double_quote(n.get_name())) elif n.get_fillcolor() == self.TARGET_COLOR: self.target = remove_double_quote(n.get_name()) elif n.get_fillcolor() == self.TARGET_COLOR_BK: self.target = remove_double_quote(n.get_name()) for edge in diagram.get_edges(): src = remove_double_quote(edge.get_source()) dest = remove_double_quote(edge.get_destination()) if edge.get_color() == self.ATTRIBUTE_EDGE: self.attribute_dict[src] = remove_double_quote(dest) if src in self.multi_value_attributes.keys(): self.multi_value_attributes[src] = [dest, src] if src in self.Graph: self.Graph[src].append(dest) else: self.Graph[src] = [dest] if dest in self.Graph: self.Graph[dest].append(src) else: self.Graph[dest] = [src] # IF Relation is destination add it in relations_dict with 1st attribute. if diagram.get_node(edge.get_destination())[0].get_shape( ) == self.RELATION_SHAPE: if dest in self.relations_dict: self.relations_dict[dest].append(src) else: self.relations_dict[dest] = [src] for edge in diagram.obj_dict['edges'].keys(): src = remove_double_quote(edge[0]) if remove_double_quote(edge[0]) in self.relations_dict: dest = remove_double_quote(edge[1]) if dest not in self.relations_dict[src]: self.relations_dict[src].append(dest) if self.verbose: print('Entities:', self.entities) print('Graph:', self.Graph) print('Relations:', self.relations_dict) print('Attributes:', self.attribute_dict) print('Multi-Value Attributes:', self.multi_value_attributes) print('Important:', self.importants) print('Target:', self.target)