class TreeNode(VBoxNode): def __init__(self, parent, name, title, data): VBoxNode.__init__(self) self.padding = (0, 0, 0, 0) self.expand_to_fill = False self.name = name self.parent = parent self.data = data self.children = [] self.is_step_list = False if title is not None: self.content = TextRectangle(title) self.content.set_fill_color(0.83137254901960789, 0.92941176470588238, 0.99215686274509807, 1) self.items.append(self.content) self.extra_bottom_space = 0 def __repr__(self): return "<node %s>"%self.content.text def process(self): for ch in self.children: ch.process() self.calc() def render(self, c): VBoxNode.render(self, c) self.render_shadow(c) def minimal_space_required_space_for_ref_to(self, c, ch): return 0 def layout(self, c, x, y): self.calc(c) self.pos = (x, y)
class MaterializedTableTreeNode(TableTreeNode): def __init__(self, context, parent, name, title, data): TableTreeNode.__init__(self, context, parent, name, title, data) self.expand_to_fill = True self.padding = 0, 10, 10, 10 self.set_body_text("SUBQUERY, materialized from") self.body.set_fill_color(0.8, 0.8, 0.8, 0.5) self.body.set_color(0, 0, 0, 1) flags = self.get_flags() self.subtitle = TextRectangle("\n".join(flags)) self.subtitle.border_color = None self.subtitle.set_fill_color(0.8, 0.8, 0.8, 0.3) self.subtitle.line_spacing = 0 self.subtitle.padding = 2, 10, 5, 10 self.subtitle.font_size = 10 self.items.append(self.subtitle) def set_fill_color(self, r, g, b, a): self.heading.set_fill_color(r, g, b, 0.6) def process(self): for ch in self.children: if ch.name == "materialized_from_subquery": self.subquery_info = ch.data # remove the subquery node for cch in ch.children: cch.parent = self self.children.remove(ch) self.children.extend(ch.children) break self.subtitle.text = "\n".join(self.get_flags(self.subquery_info)) TableTreeNode.process(self) def do_render(self, c): def leftmost(node): x = node.pos[0] for ch in node.children: x = min(x, leftmost(ch)) return x self.do_render_attachments(c) self.apply_attributes(c) x, y = self.pos w, h = self.gsize xx = leftmost(self) VBoxNode.do_render(self, c) c.save() c.set_source_rgba(1, 0, 0, 1) c.set_source_rgba(0.7, 0.7, 0.7, 1) c.set_dash([3.0, 2.0], 0) c.rectangle(xx+0.5, y+0.5, w, h) c.stroke() c.restore()
def __init__(self, parent, name, title, data): VBoxNode.__init__(self) self.padding = (0, 0, 0, 0) self.expand_to_fill = False self.name = name self.parent = parent self.data = data self.children = [] self.content = TextRectangle(title) self.content.set_fill_color(0.83137254901960789, 0.92941176470588238, 0.99215686274509807, 1) self.items.append(self.content) self.extra_bottom_space = 0
def __init__(self, parent, name, title, data): VBoxNode.__init__(self) self.padding = (0, 0, 0, 0) self.expand_to_fill = False self.name = name self.parent = parent self.data = data self.children = [] self.content = TextRectangle(title) self.content.set_border_color(1, 1, 1, 0) self.content.set_fill_color(1, 1, 1, 0) self.items.append(self.content) self.extra_bottom_space = 0
def set_body_text(self, body): if self.body: self.body.text = body else: self.body = TextRectangle(body) r, g, b, a = self.heading.fill_color self.body.set_fill_color(r, g, b, 0.7) self.body.set_color(*self.heading.color) self.body.border_color = self.border_color if self.flags_box: self.body.draw_vertices = False, False, True, False else: self.body.draw_vertices = None self.body.padding = 3, 5, 5, 5 self.items.append(self.body)
def __init__(self, parent, name, title, data): TableTreeNode.__init__(self, parent, name, title, data) self.expand_to_fill = True self.padding = 0, 10, 10, 10 self.set_body_text("SUBQUERY, materialized from") self.body.set_fill_color(0.8, 0.8, 0.8, 0.5) self.body.set_color(0, 0, 0, 1) flags = self.get_flags() self.subtitle = TextRectangle("\n".join(flags)) self.subtitle.border_color = None self.subtitle.set_fill_color(0.8, 0.8, 0.8, 0.3) self.subtitle.line_spacing = 0 self.subtitle.padding = 2, 10, 5, 10 self.subtitle.font_size = 10 self.items.append(self.subtitle)
def __init__(self, parent, name, title, data): TreeNode.__init__(self, parent, name, title, data) self.border_color = 125.0 / 255, 125.0 / 255, 125.0 / 255, 1 self.heading = self.content self.heading.border_color = None self.references = {} self.heading.set_icon("../../images/grt/structs/db.Table.16x16.png") self.heading.set_color(1, 1, 1, 1) self.body = None self.flags_box = None flags = [] if data.has_key("using_join_buffer"): flags.append("join buf (%s)" % data["using_join_buffer"]) if flags: self.flags_box = TextRectangle("\n".join(flags)) self.flags_box.set_color(*self.heading.color) self.items.append(self.flags_box)
def __init__(self, parent, name, title, data): TreeNode.__init__(self, parent, name, title, data) self.flags = TextRectangle("\n".join(self.get_flags())) self.content.border_color = None self.flags.border_color = None self.flags.font_size = 10 self.flags.padding = 0, 5, 5, 5 self.items.append(self.flags) self.set_fill_color(0.92941176470588238, 0.99215686274509807,0.83137254901960789, 1)
class PlainTextNode(VBoxNode): def __init__(self, parent, name, title, data): VBoxNode.__init__(self) self.padding = (0, 0, 0, 0) self.expand_to_fill = False self.name = name self.parent = parent self.data = data self.children = [] self.content = TextRectangle(title) self.content.set_border_color(1, 1, 1, 0) self.content.set_fill_color(1, 1, 1, 0) self.items.append(self.content) self.extra_bottom_space = 0 def __repr__(self): return "<node %s>"%self.content.text def process(self): for ch in self.children: ch.process()
class TreeNode(VBoxNode): def __init__(self, parent, name, title, data): VBoxNode.__init__(self) self.padding = (0, 0, 0, 0) self.expand_to_fill = False self.name = name self.parent = parent self.data = data self.children = [] self.content = TextRectangle(title) self.content.set_fill_color(0.83137254901960789, 0.92941176470588238, 0.99215686274509807, 1) self.items.append(self.content) self.extra_bottom_space = 0 def __repr__(self): return "<node %s>" % self.content.text def get_flags(self, data=None): if not data: data = self.data flags = [] for f in [ "using_temporary_table", "dependent", "using_filesort", "cacheable" ]: if data.get(f, False): flags.append(f) return flags def process(self): for ch in self.children: ch.process() def do_render(self, c): VBoxNode.do_render(self, c) self.render_shadow(c) def minimal_space_required_space_for_ref_to(self, c, ch): return 0
class TreeNode(VBoxNode): def __init__(self, parent, name, title, data): VBoxNode.__init__(self) self.padding = (0, 0, 0, 0) self.expand_to_fill = False self.name = name self.parent = parent self.data = data self.children = [] self.content = TextRectangle(title) self.content.set_fill_color(0.83137254901960789, 0.92941176470588238, 0.99215686274509807, 1) self.items.append(self.content) self.extra_bottom_space = 0 def __repr__(self): return "<node %s>"%self.content.text def get_flags(self, data = None): if not data: data = self.data flags = [] for f in ["using_temporary_table", "dependent", "using_filesort", "cacheable"]: if data.get(f, False): flags.append(f) return flags def process(self): for ch in self.children: ch.process() def do_render(self, c): VBoxNode.do_render(self, c) self.render_shadow(c) def minimal_space_required_space_for_ref_to(self, c, ch): return 0
def __init__(self, context, parent, name, title, data): TableTreeNode.__init__(self, context, parent, name, title, data) self.expand_to_fill = True self.padding = 0, 10, 10, 10 self.set_body_text("SUBQUERY, materialized from") self.body.set_fill_color(0.8, 0.8, 0.8, 0.5) self.body.set_color(0, 0, 0, 1) flags = self.get_flags() self.subtitle = TextRectangle("\n".join(flags)) self.subtitle.border_color = None self.subtitle.set_fill_color(0.8, 0.8, 0.8, 0.3) self.subtitle.line_spacing = 0 self.subtitle.padding = 2, 10, 5, 10 self.subtitle.font_size = 10 self.items.append(self.subtitle)
def __init__(self, parent, name, data): TreeNode.__init__(self, parent, name, "SUBQUERY", data) self.padding = (0, 10, 25, 10) self.expand_to_fill = True self.content.border_color = None self.content.fill_color = (0.8, 0.8, 0.8, 0.5) self.content.line_spacing = 0 self.content.padding = 5, 10, 5, 10 self.subtitle = TextRectangle("\n".join(self.get_flags())) self.subtitle.border_color = None self.subtitle.fill_color = (0.8, 0.8, 0.8, 0.3) self.subtitle.line_spacing = 0 self.subtitle.padding = 2, 10, 5, 10 self.subtitle.font_size = 10 self.items.append(self.subtitle)
def __init__(self, context, parent, name, title, data): TreeNode.__init__(self, parent, name, title, data) self.context = context self.border_color = 125.0/255, 125.0/255, 125.0/255, 1 self.heading = self.content self.heading.border_color = None self.references = {} self.heading.set_icon("../../images/grt/structs/db.Table.16x16.png") self.heading.set_color(1, 1, 1, 1) self.body = None self.flags_box = None self.attached_text = None flags = [] if data.has_key("using_join_buffer"): flags.append("join buf (%s)" % data["using_join_buffer"]) if flags: self.flags_box = TextRectangle("\n".join(flags)) self.flags_box.set_color(*self.heading.color) self.items.append(self.flags_box)
class TableTreeNode(TreeNode): def __init__(self, context, parent, name, title, data): TreeNode.__init__(self, parent, name, title, data) self.context = context self.border_color = 125.0/255, 125.0/255, 125.0/255, 1 self.heading = self.content self.heading.border_color = None self.references = {} self.heading.set_icon("../../images/grt/structs/db.Table.16x16.png") self.heading.set_color(1, 1, 1, 1) self.body = None self.flags_box = None self.attached_text = None flags = [] if data.has_key("using_join_buffer"): flags.append("join buf (%s)" % data["using_join_buffer"]) if flags: self.flags_box = TextRectangle("\n".join(flags)) self.flags_box.set_color(*self.heading.color) self.items.append(self.flags_box) def __repr__(self): return "<table: %s>"%self.heading.text def set_body_text(self, body): if self.body: self.body.text = body else: self.body = TextRectangle(body) r, g, b, a = self.heading.fill_color self.body.set_fill_color(r, g, b, 0.7) self.body.set_color(*self.heading.color) self.body.border_color = self.border_color if self.flags_box: self.body.draw_vertices = False, False, True, False else: self.body.draw_vertices = None self.body.padding = 3, 5, 5, 5 self.items.append(self.body) def set_fill_color(self, r, g, b, a = 1.0): self.heading.set_fill_color(r, g, b, a) if self.body: self.body.set_fill_color(r, g, b, 0.7) if self.flags_box: self.flags_box.set_fill_color(r, g, b, 0.7) def stroke_line_to_parent(self, c, node, vertical): if vertical: p1, p2 = TreeNode.stroke_line_to_parent_v(self, c, node) else: p1, p2 = TreeNode.stroke_line_to_parent_h(self, c, node) filtered = self.data.get("filtered", None) rows = self.data.get("rows", None) if filtered is not None and rows is not None: c.set_source_rgb(0.1, 0.5, 0.1) total = str(int(filtered*rows/100.0)) x, y = (p1[0]+p2[0])/2, (p1[1]+p2[1])/2 cairo_utils.show_centered_text_with_background(c, x, y, total, (1,1,1)) def process(self): TreeNode.process(self) attached_condition = self.data.get("attached_condition", "") if attached_condition: self.context["attached_conditions"].append((self.name, attached_condition)) i = len(self.context["attached_conditions"]) condition_length = self.context.get("opt_condition_length", 32) self.attached_text = "attached_condition[%i]: %s%s" % (i, attached_condition[:condition_length], "..." if len(attached_condition) > condition_length else "") def do_render_attachments(self, c): c.set_line_width(self.line_width) c.save() c.set_source_rgba(0.1, 0.1, 0.5, 1) x, y = self.pos w, h = self.size if self.data.has_key("rows"): cairo_utils.show_centered_text_with_background(c, self.center()[0], y-12, str(self.data["rows"]), (1,1,1)) if self.attached_text: c.set_font_size(9) ext = c.text_extents(self.attached_text) padding = 4 c.set_source_rgba(0xcc/255.0, 0xcc/255.0, 0xcc/255.0, 1) c.rounded_rect(x + 10, y + self.size[1], ext.width + 2*padding, ext.height + 2*padding, 7) c.stroke_preserve() c.set_source_rgba(0xeb/255.0, 0xeb/255.0, 0xeb/255.0, 1) c.fill() c.set_source_rgba(0x30/255.0, 0x30/255.0, 0x30/255.0, 1) c.move_to(int(x + 10 + padding) + 0.5, int(y+self.size[1] + ext.height - (ext.height + ext.y_bearing) + padding) + 0.5) c.show_text(self.attached_text) c.restore() def do_render(self, c): self.do_render_attachments(c) x, y = self.pos w, h = self.size c.set_source_rgba(*self.border_color) c.rectangle(x+0.5, y+0.5, w, h) c.stroke() self.render_shadow(c) def minimal_space_required_space_for_ref_to(self, c, ch): if ch not in self.references: return 0 ref_cols = self.references[ch] l = None for r in ref_cols: if len(r) > l: l = r c.set_font_size(11) ext = c.text_extents(l) return ext.width+10+10 def calc(self, c): TreeNode.calc(self, c) if self.references: self.extra_bottom_space = 50 def stroke_ref_to(self, c, ch): p1 = ch.center() p2 = self.center() d = self.parent.children.index(self) - self.parent.children.index(ch) if d < 0: p1s, p1e = self.right_vertex() p2s, p2e = ch.left_vertex() else: p1s, p1e = self.left_vertex() p2s, p2e = ch.right_vertex() e = intersect_lines(p2s, p2e, p1, p2) s = intersect_lines(p1s, p1e, p1, p2) if s and e: self.stroke_ref(c, s, e, d, self.references[ch]) else: print s, e def stroke_ref(self, c, p1, p2, d, columns): def px(p1, p2, d): return (int(p1[0]+(p2[0]-p1[0])/4)+0.5, int(p1[1]+d*25)+0.5) c.set_line_width(1) c.move_to(p1[0], int(p1[1])+0.5) if d > 1: p11 = px(p1, p2, d) p22 = px(p2, p1, d) text_y = (p2[1]+p1[1])/2 + 20*d c.curve_to(p11[0], p11[1], p22[0], p22[1], p2[0], p2[1]) else: text_y = (p2[1]+p1[1])/2 c.line_to(p2[0], int(p2[1])+0.5) c.stroke() if columns: c.save() c.set_font_size(11) ext = c.text_extents(columns[0]) x = p2[0] + ((p1[0]-p2[0]) - ext.width)/2 y = text_y c.set_source_rgba(0.1, 0.1, 0.1, 1) cairo_utils.show_text_lines_with_border(c, int(x), int(y), "\n".join(columns), 0) c.restore() if d > 1: draw_arrow_head(c, p2, p22) else: draw_arrow_head(c, p2, p1)
class TableTreeNode(TreeNode): def __init__(self, parent, name, title, data): TreeNode.__init__(self, parent, name, title, data) self.border_color = 125.0 / 255, 125.0 / 255, 125.0 / 255, 1 self.heading = self.content self.heading.border_color = None self.references = {} self.heading.set_icon("../../images/grt/structs/db.Table.16x16.png") self.heading.set_color(1, 1, 1, 1) self.body = None self.flags_box = None flags = [] if data.has_key("using_join_buffer"): flags.append("join buf (%s)" % data["using_join_buffer"]) if flags: self.flags_box = TextRectangle("\n".join(flags)) self.flags_box.set_color(*self.heading.color) self.items.append(self.flags_box) def __repr__(self): return "<table: %s>" % self.heading.text def set_body_text(self, body): if self.body: self.body.text = body else: self.body = TextRectangle(body) r, g, b, a = self.heading.fill_color self.body.set_fill_color(r, g, b, 0.7) self.body.set_color(*self.heading.color) self.body.border_color = self.border_color if self.flags_box: self.body.draw_vertices = False, False, True, False else: self.body.draw_vertices = None self.body.padding = 3, 5, 5, 5 self.items.append(self.body) def set_fill_color(self, r, g, b, a=1.0): self.heading.set_fill_color(r, g, b, a) if self.body: self.body.set_fill_color(r, g, b, 0.7) if self.flags_box: self.flags_box.set_fill_color(r, g, b, 0.7) def stroke_line_to_parent(self, c, node, vertical): if vertical: p1, p2 = TreeNode.stroke_line_to_parent_v(self, c, node) else: p1, p2 = TreeNode.stroke_line_to_parent_h(self, c, node) filtered = self.data.get("filtered", None) rows = self.data.get("rows", None) if filtered is not None and rows is not None: c.set_source_rgb(0.1, 0.5, 0.1) total = str(int(filtered * rows / 100.0)) x, y = (p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2 cairo_utils.show_centered_text_with_background( c, x, y, total, (1, 1, 1)) def do_render_attachments(self, c): c.set_line_width(self.line_width) c.save() c.set_source_rgba(0.1, 0.1, 0.5, 1) x, y = self.pos w, h = self.size if self.data.has_key("rows"): cairo_utils.show_centered_text_with_background( c, self.center()[0], y - 12, str(self.data["rows"]), (1, 1, 1)) cond = self.data.get("attached_condition", None) if cond: c.set_font_size(9) suffix = "" while len(cond) > 10: ext = c.text_extents(cond) if ext.width > self.gsize[0] * 1.2: cond = cond[:-1] suffix = "..." else: break ext = c.text_extents(cond + suffix) padding = 4 c.set_source_rgba(0xcc / 255.0, 0xcc / 255.0, 0xcc / 255.0, 1) c.rounded_rect(x + 10, y + self.gsize[1], ext.width + 2 * padding, ext.height + 2 * padding, 7) c.stroke_preserve() c.set_source_rgba(0xeb / 255.0, 0xeb / 255.0, 0xeb / 255.0, 1) c.fill() c.set_source_rgba(0x30 / 255.0, 0x30 / 255.0, 0x30 / 255.0, 1) c.move_to( int(x + 10 + padding) + 0.5, int(y + self.gsize[1] + ext.height - (ext.height + ext.y_bearing) + padding) + 0.5) c.show_text(cond + suffix) c.restore() def do_render(self, c): self.do_render_attachments(c) x, y = self.pos w, h = self.size c.set_source_rgba(*self.border_color) c.rectangle(x + 0.5, y + 0.5, w, h) c.stroke() self.render_shadow(c) def minimal_space_required_space_for_ref_to(self, c, ch): if ch not in self.references: return 0 ref_cols = self.references[ch] l = None for r in ref_cols: if len(r) > l: l = r c.set_font_size(11) ext = c.text_extents(l) return ext.width + 10 + 10 def calc(self, c): TreeNode.calc(self, c) if self.references: self.extra_bottom_space = 50 def stroke_ref_to(self, c, ch): p1 = ch.center() p2 = self.center() d = self.parent.children.index(self) - self.parent.children.index(ch) if d < 0: p1s, p1e = self.right_vertex() p2s, p2e = ch.left_vertex() else: p1s, p1e = self.left_vertex() p2s, p2e = ch.right_vertex() e = intersect_lines(p2s, p2e, p1, p2) s = intersect_lines(p1s, p1e, p1, p2) if s and e: self.stroke_ref(c, s, e, d, self.references[ch]) else: print s, e def stroke_ref(self, c, p1, p2, d, columns): def px(p1, p2, d): return (int(p1[0] + (p2[0] - p1[0]) / 4) + 0.5, int(p1[1] + d * 25) + 0.5) c.set_line_width(1) c.move_to(p1[0], int(p1[1]) + 0.5) if d > 1: p11 = px(p1, p2, d) p22 = px(p2, p1, d) text_y = (p2[1] + p1[1]) / 2 + 20 * d c.curve_to(p11[0], p11[1], p22[0], p22[1], p2[0], p2[1]) else: text_y = (p2[1] + p1[1]) / 2 c.line_to(p2[0], int(p2[1]) + 0.5) c.stroke() if columns: c.save() c.set_font_size(11) ext = c.text_extents(columns[0]) x = p2[0] + ((p1[0] - p2[0]) - ext.width) / 2 y = text_y c.set_source_rgba(0.1, 0.1, 0.1, 1) cairo_utils.show_text_lines_with_border(c, int(x), int(y), "\n".join(columns), 0) c.restore() if d > 1: draw_arrow_head(c, p2, p22) else: draw_arrow_head(c, p2, p1)