20 '''Visualize dot graphs via the xdot format.'''    22 __author__ = 
"Jose Fonseca"    44     from python_qt_binding.QtWidgets 
import QWidget, QMainWindow
    54     """Store pen attributes."""    58         self.
color = (0.0, 0.0, 0.0, 1.0)
    66         """Create a copy of this pen."""    68         pen.__dict__ = self.__dict__.copy()
    73         pen.color = (1, 0, 0, 1)
    74         pen.fillcolor = (1, .8, .8, 1)
    78     """Abstract base class for all the drawing shapes."""    83     def draw(self, cr, highlight=False):
    84         """Draw this shape with the given cairo context"""    85         raise NotImplementedError
    89             if not hasattr(self, 
'highlight_pen'):
    96     """Used to draw a text shape with a QPainter"""    98     LEFT, CENTER, RIGHT = -1, 0, 1
   109     def draw(self, painter, highlight=False):
   111         painter.setPen(QColor.fromRgbF(*pen.color))
   112         font = QFont(self.pen.fontname)
   114         fontMetrics = QFontMetrics(QFont(self.pen.fontname))
   115         scale = float(fontMetrics.width(self.
t)) / float(self.
w)
   117         if scale < 1.0 
or scale > 1.0:
   118             font.setPointSizeF(font.pointSizeF()/scale);
   120         painter.setFont(font)
   122                 self.
x - self.
w / 2.0,
   128     """Used to draw an ellipse shape with a QPainter"""   129     def __init__(self, pen, x0, y0, w, h, filled=False):
   138     def draw(self, painter, highlight=False):
   142             painter.setPen(QColor.fromRgbF(*pen.fillcolor))
   143             painter.setBrush(QColor.fromRgbF(*pen.fillcolor))
   145             painter.setPen(QPen(QBrush(QColor.fromRgbF(*pen.color)), pen.linewidth, pen.dash))
   146             painter.setBrush(Qt.NoBrush)
   147         painter.drawEllipse(self.
x0 - self.
w, self.
y0 - self.
h,  self.
w * 2,  self.
h * 2)
   151     """Used to draw a polygon with QPainter."""   159     def draw(self, painter, highlight=False):
   161         polygon_points = QPolygonF()
   163             polygon_points.append (QPointF(x, y))
   168             painter.setPen(QColor.fromRgbF(*pen.fillcolor))
   169             painter.setBrush(QColor.fromRgbF(*pen.fillcolor))
   171             painter.setPen(QPen(QBrush(QColor.fromRgbF(*pen.color)), pen.linewidth,
   172                                             pen.dash, Qt.SquareCap, Qt.MiterJoin))
   173             painter.setBrush(Qt.NoBrush)
   175         painter.drawPolygon(polygon_points)
   179     """Used to draw a line with QPainter."""   186     def draw(self, painter, highlight=False):
   188         painter.setPen(QPen(QBrush(QColor.fromRgbF(*pen.color)), pen.linewidth,
   189                                             pen.dash, Qt.SquareCap, Qt.MiterJoin))
   192         for x1, y1 
in self.
points[1:]:
   193             painter.drawLine(QPointF(x0, y0),  QPointF(x1, y1))
   198     """Used to draw a bezier curve with QPainter."""   206     def draw(self, painter, highlight=False):
   207         painter_path = QPainterPath()
   208         painter_path.moveTo(QPointF(*self.
points[0]))
   209         for i 
in xrange(1, len(self.
points), 3):
   210             painter_path.cubicTo(
   212                 QPointF(*self.
points[i + 1]),
   213                 QPointF(*self.
points[i + 2]))
   218             brush.setColor(QColor.fromRgbF(*pen.fillcolor))
   219             brush.setStyle(Qt.SolidPattern)
   220             painter.setBrush(brush)
   225             painter.setBrush(Qt.NoBrush)
   227         qpen.setStyle(pen.dash)
   228         qpen.setWidth(pen.linewidth)
   229         qpen.setColor(QColor.fromRgbF(*pen.color))
   231         painter.drawPath(painter_path)
   234     """Used to draw a set of shapes with QPainter."""   240     def draw(self, cr, highlight=False):
   242             shape.draw(cr, highlight=highlight)
   248     """Represents a graphviz URL."""   253         if highlight 
is None:
   254             highlight = set([item])
   258     """Represents a jump to another node's position on the canvas."""   260     def __init__(self, item, x, y, highlight=None, url=None):
   264         if highlight 
is None:
   265             highlight = set([item])
   273     """Base class for graph nodes and edges."""   276         CompoundShape.__init__(self, shapes)
   286     """An abstract node in the graph, it's spatial location, and it's visual representation."""   289         Element.__init__(self, shapes)
   302         """Used to check for 2D-picking via the mouse.   303         param x: The x position on the canvas   304         param y: The y position on the canvas   306         return self.
x1 <= x 
and x <= self.
x2 and self.
y1 <= y 
and y <= self.
y2   309         """Get the elemnt's metadata."""   313             return Url(self, self.
url)
   318             return Jump(self, self.
x, self.
y)
   325     return deltax*deltax + deltay*deltay
   331         Element.__init__(self, shapes)
   341             return Jump(self, self.dst.x, self.dst.y, highlight=set([self, self.
dst]),url=self.
url)
   343             return Jump(self, self.src.x, self.src.y, highlight=set([self, self.
src]),url=self.
url)
   350     def __init__(self, width=1, height=1, shapes=(), nodes=(), edges=(), subgraph_shapes={}):
   363     def draw(self, cr, highlight_items=None):
   364         if highlight_items 
is None:
   368         for edge 
in self.
edges:
   369             edge.draw(cr, highlight=(edge 
in highlight_items))
   370         for node 
in self.
nodes:
   371             node.draw(cr, highlight=(node 
in highlight_items))
   374         for node 
in self.
nodes:
   375             url = node.get_url(x, y)
   381         for edge 
in self.
edges:
   382             jump = edge.get_jump(x, y)
   385         for node 
in self.
nodes:
   386             jump = node.get_jump(x, y)
   394     """Parser for xdot drawing attributes.   396     - http://www.graphviz.org/doc/info/output.html#d:xdot   408         return self.
pos < len(self.
buf)
   411         buf = buf.replace(
'\\"', 
'"')
   412         buf = buf.replace(
'\\n', 
'\n')
   416         pos = self.buf.find(
" ", self.
pos)
   417         res = self.
buf[self.
pos:pos]
   419         while self.
pos < len(self.
buf) 
and self.
buf[self.
pos].isspace():
   436         pos = self.buf.find(
"-", self.
pos) + 1
   438         res = self.
buf[pos:self.
pos]
   439         while self.
pos < len(self.
buf) 
and self.
buf[self.
pos].isspace():
   458             hex2float = 
lambda h: float(int(h, 16)/255.0)
   459             r = hex2float(c[1:3])
   460             g = hex2float(c[3:5])
   461             b = hex2float(c[5:7])
   463                 a = hex2float(c[7:9])
   464             except (IndexError, ValueError):
   467         elif c1.isdigit() 
or c1 == 
".":
   469             h, s, v = map(float, c.replace(
",", 
" ").split())
   470             r, g, b = colorsys.hsv_to_rgb(h, s, v)
   478             color = gtk.gdk.color_parse(c)
   490             dummy, scheme, index = c.split(
'/')
   491             r, g, b = brewer_colors[scheme][int(index)]
   492         except (ValueError, KeyError):
   502         sys.stderr.write(
"unknown color '%s'\n" % c)
   511                 color = s.read_color()
   512                 if color 
is not None:
   515                 color = s.read_color()
   516                 if color 
is not None:
   520                 style = s.read_text()
   521                 if style.startswith(
"setlinewidth("):
   522                     lw = style.split(
"(")[1].split(
")")[0]
   525                 elif style 
in (
"solid", 
"dashed"):
   528                 size = s.read_float()
   532                 x, y = s.read_point()
   538                 x0, y0 = s.read_point()
   543                 x0, y0 = s.read_point()
   563                 sys.stderr.write(
"unknown xdot opcode '%s'\n" % op)
   569         return self.parser.transform(x, y)
   573             self.pen.fillcolor = color
   575             self.pen.color = color
   578         self.pen.linewidth = linewidth
   583             self.pen.dash = Qt.SolidLine
   584         elif style == 
"dashed":
   586             self.pen.dash = Qt.DashLine
   589         self.pen.fontsize = size
   590         self.pen.fontname = name
   624     def __init__(self, msg=None, filename=None, line=None, col=None):
   631         return ':'.join([str(part) 
for part 
in (self.
filename, self.
line, self.
col, self.
msg) 
if part != 
None])
   636     """Stateless scanner."""   647             flags |= re.IGNORECASE
   649             '|'.join([
'(' + regexp + 
')' for type, regexp, test_lit 
in self.
tokens]),
   656         mo = self.tokens_re.match(buf, pos)
   659             type, regexp, test_lit = self.
tokens[mo.lastindex - 1]
   662                 type = self.literals.get(text, type)
   663             return type, text, pos
   666             return self.symbols.get(c, 
None), c, pos + 1
   684     newline_re = re.compile(
r'\r\n?|\n')
   686     def __init__(self, buf = None, pos = 0, filename = None, fp = None):
   690                 length = os.path.getsize(fp.name)
   700                     buf = mmap.mmap(fileno, length, access = mmap.ACCESS_READ)
   701                     pos = os.lseek(fileno, 0, 1)
   709                 except AttributeError:
   725             type, text, endpos = self.scanner.next(self.
buf, pos)
   726             assert pos + len(text) == endpos
   728             type, text = self.filter(type, text)
   734                 msg = 
'unexpected char '   735                 if text >= 
' ' and text <= 
'~':
   738                     msg += 
"0x%X" % ord(text)
   742         return Token(type = type, text = text, line = line, col = col)
   747         for mo 
in self.newline_re.finditer(text, pos):
   754             tabpos = text.find(
'\t', pos)
   757             self.
col += tabpos - pos
   760         self.
col += len(text) - pos
   770         if self.lookahead.type != type:
   772                 msg = 
'unexpected token %r' % self.lookahead.text,
   773                 filename = self.lexer.filename,
   774                 line = self.lookahead.line,
   775                 col = self.lookahead.col)
   778         while self.lookahead.type != type:
   823         (ID, 
r'[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*', 
True),
   826         (ID, 
r'-?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)', 
False),
   829         (STR_ID, 
r'"[^"\\]*(?:\\.[^"\\]*)*"', 
False),
   832         (HTML_ID, 
r'<[^<>]*(?:<[^<>]*>[^<>]*)*>', 
False),
   835         (EDGE_OP, 
r'-[>-]', 
False),
   858         'subgraph': SUBGRAPH,
   874             text = text.replace(
'\\\r\n', 
'')
   875             text = text.replace(
'\\\r', 
'')
   876             text = text.replace(
'\\\n', 
'')
   878             text = text.replace(
'\\r', '\r')
   879             text = text.replace(
'\\n', 
'\n')
   880             text = text.replace(
'\\t', 
'\t')
   881             text = text.replace(
'\\', 
'')
   885         elif type == HTML_ID:
   895         Parser.__init__(self, lexer)
   905         if self.lookahead.type == STRICT:
   909         while self.lookahead.type != RCURLY:
   915         shapes_before = set(self.shapes)
   916         if self.lookahead.type == SUBGRAPH:
   918             if self.lookahead.type == ID:
   919                 id = self.lookahead.text
   921         if self.lookahead.type == LCURLY:
   923             while self.lookahead.type != RCURLY:
   926         new_shapes = set(self.shapes) - shapes_before
   927         self.subgraph_shapes[id] = [s 
for s 
in new_shapes 
if not any([s 
in ss 
for ss 
in self.subgraph_shapes.values()])]
   931         if self.lookahead.type == GRAPH:
   934             self.graph_attrs.update(attrs)
   936         elif self.lookahead.type == NODE:
   939         elif self.lookahead.type == EDGE:
   942         elif self.lookahead.type 
in (SUBGRAPH, LCURLY):
   946             if self.lookahead.type == EDGE_OP:
   949                 while self.lookahead.type == EDGE_OP:
   952                 for i 
in range(0, len(node_ids) - 1):
   953                     self.
handle_edge(node_ids[i], node_ids[i + 1], attrs)
   954             elif self.lookahead.type == EQUAL:
   960         if self.lookahead.type == SEMI:
   965         while self.lookahead.type == LSQUARE:
   967             while self.lookahead.type != RSQUARE:
   970                 if self.lookahead.type == COMMA:
   977         if self.lookahead.type == EQUAL:
   986         if self.lookahead.type == COLON:
   989             if self.lookahead.type == COLON:
  1002         id = self.lookahead.text
  1016 class XDotParser(DotParser):
  1020         DotParser.__init__(self, lexer)
  1039             xmin, ymin, xmax, ymax = map(float, bb.split(
","))
  1052         for attr 
in (
"_draw_", 
"_ldraw_", 
"_hdraw_", 
"_tdraw_", 
"_hldraw_", 
"_tldraw_"):
  1055                 self.shapes.extend(parser.parse())
  1064         w = float(attrs[
'width'])*72
  1065         h = float(attrs[
'height'])*72
  1067         for attr 
in (
"_draw_", 
"_ldraw_"):
  1070                 shapes.extend(parser.parse())
  1071         url = attrs.get(
'URL', 
None)
  1072         node = 
Node(x, y, w, h, shapes, url)
  1075             self.nodes.append(node)
  1085         for attr 
in (
"_draw_", 
"_ldraw_", 
"_hdraw_", 
"_tdraw_", 
"_hldraw_", 
"_tldraw_"):
  1088                 shapes.extend(parser.parse())
  1089         url = attrs.get(
'URL', 
None)
  1093             self.edges.append(
Edge(src, dst, points, shapes, url))
  1096         DotParser.parse(self)
  1099         for k,shapes in self.subgraph_shapes.iteritems():  1100           self.shapes += shapes  1106         x, y = pos.split(
",")
  1107         return self.
transform(float(x), float(y))
  1111         for entry 
in pos.split(
' '):
  1112             fields = entry.split(
',')
  1120                 points.append(self.
transform(float(x), float(y)))
  1141         self.dot_widget.connect(self.
timeout_id, SIGNAL(
'timeout()'), self.
tick)
  1142         self.timeout_id.start(int(self.
step * 1000))
  1147             self.timeout_id.stop()
  1163 class LinearAnimation(Animation):
  1169         Animation.start(self)
  1173         self.
animate(max(0, min(t, 1)))
  1176             self.timeout_id.stop() 
  1182 class MoveToAnimation(LinearAnimation):
  1185         Animation.__init__(self, dot_widget)
  1194         self.dot_widget.x = tx * t + sx * (1-t)
  1195         self.dot_widget.y = ty * t + sy * (1-t)
  1196         self.dot_widget.update()
  1201         MoveToAnimation.__init__(self, dot_widget, target_x, target_y)
  1211         rect = self.dot_widget.rect()
  1213         visible = min(rect.width(), rect.height()) / self.dot_widget.zoom_ratio
  1216             desired_middle_zoom = visible / distance
  1217             self.
extra_zoom = min(0, 4 * (desired_middle_zoom - middle_zoom))
  1221         self.dot_widget.zoom_ratio = c*t + b*t*(1-t) + a*(1-t)
  1222         self.dot_widget.zoom_to_fit_on_resize = 
False  1223         MoveToAnimation.animate(self, t)
  1240         self.
drag(deltax, deltay)
  1265 class NullAction(DragAction):
  1268         x, y = event.x(), event.y()
  1271         item = dot_widget.get_url(x, y)
  1273             item = dot_widget.get_jump(x, y)
  1274         if item 
is not None:
  1275             dot_widget.setCursor(Qt.PointingHandCursor)
  1276             dot_widget.set_highlight(item.highlight)
  1278             dot_widget.setCursor(Qt.ArrowCursor)
  1279             dot_widget.set_highlight(
None)
  1285         self.dot_widget.setCursor(Qt.ClosedHandCursor)
  1288         self.dot_widget.x += deltax / self.dot_widget.zoom_ratio
  1289         self.dot_widget.y += deltay / self.dot_widget.zoom_ratio
  1290         self.dot_widget.update()
  1293         self.dot_widget.cursor().setShape(Qt.ArrowCursor)
  1301         self.dot_widget.zoom_ratio *= 1.005 ** (deltax + deltay)
  1302         self.dot_widget.zoom_to_fit_on_resize = 
False  1303         self.dot_widget.update()
  1306         self.dot_widget.update()
  1312         self.dot_widget.update()
  1316         print "ERROR: UNIMPLEMENTED ZoomAreaAction.draw"  1319         painter.set_source_rgba(.5, .5, 1.0, 0.25)
  1324         painter.set_source_rgba(.5, .5, 1.0, 1.0)
  1325         painter.set_line_width(1)
  1333         x1, y1 = self.dot_widget.window_to_graph(self.
startmousex,
  1335         x2, y2 = self.dot_widget.window_to_graph(self.
stopmousex,
  1337         self.dot_widget.zoom_to_area(x1, y1, x2, y2)
  1340         self.dot_widget.update()
  1344     """Qt widget that draws dot graphs."""  1349         super(DotWidget,  self).
__init__(parent)
  1351         self.openfilename = 
None  1363         self.x, self.y = 0.0, 0.0
  1364         self.zoom_ratio = 1.0
  1365         self.zoom_to_fit_on_resize = 
False  1368         self.presstime = 
None  1369         self.highlight = 
None  1372         self.select_cbs = []
  1375         self.items_by_url = {}
  1377         self.setMouseTracking (
True) 
  1379     ZOOM_INCREMENT = 1.25
  1380     ZOOM_TO_FIT_MARGIN = 12
  1385         self.select_cbs.append(cb)
  1388         self.filter = filter
  1391         if isinstance(dotcode, unicode):
  1392             dotcode = dotcode.encode(
'utf8')
  1393         p = subprocess.Popen(
  1394             [self.filter, 
'-Txdot'],
  1395             stdin=subprocess.PIPE,
  1396             stdout=subprocess.PIPE,
  1397             stderr=subprocess.PIPE,
  1399             universal_newlines=
True  1401         xdotcode, error = p.communicate(dotcode)
  1402         if p.returncode != 0:
  1403             print "UNABLE TO SHELL TO DOT", error
  1412             self.set_xdotcode(xdotcode,center)
  1415             self.items_by_url = {}
  1416             for item 
in self.graph.nodes + self.graph.edges:
  1417                 if item.url 
is not None:
  1418                     self.items_by_url[item.url] = item
  1421             self.subgraph_shapes = self.graph.subgraph_shapes
  1423         except ParseError, ex:
  1432             self.openfilename = filename
  1438         self.graph = parser.parse()
  1439         self.zoom_image(self.zoom_ratio, center=center)
  1442         if self.openfilename 
is not None:
  1444                 fp = open(str(self.openfilename), 
"rb")
  1445                 self.set_dotcode(fp.read(), self.openfilename)
  1453         painter = QPainter (self)
  1454         painter.setRenderHint(QPainter.Antialiasing)
  1455         painter.setRenderHint(QPainter.TextAntialiasing)
  1456         painter.setRenderHint(QPainter.HighQualityAntialiasing)
  1468         painter.setClipping(
True)
  1469         painter.setClipRect(self.rect())
  1470         painter.setBackground(QBrush(Qt.blue,Qt.SolidPattern))
  1476         painter.translate(0.5*rect.width(), 0.5*rect.height())
  1477         painter.scale(self.zoom_ratio, self.zoom_ratio)
  1478         painter.translate(-self.x, -self.y)
  1480         self.graph.draw(painter, highlight_items=self.highlight)
  1483         self.drag_action.draw(painter)
  1487         return self.x, self.y
  1496         if self.highlight != items:
  1497             self.highlight = items
  1502             self.x = self.graph.width/2
  1503             self.y = self.graph.height/2
  1504         elif pos 
is not None:
  1509             x -= 0.5*rect.width()
  1511             y -= 0.5*rect.height()
  1512             self.x += x / self.zoom_ratio - x / zoom_ratio
  1513             self.y += y / self.zoom_ratio - y / zoom_ratio
  1514         self.zoom_ratio = zoom_ratio
  1515         self.zoom_to_fit_on_resize = 
False  1521         width = abs(x1 - x2)
  1522         height = abs(y1 - y2)
  1523         self.zoom_ratio = min(
  1524             float(rect.width())/float(width),
  1525             float(rect.height())/float(height)
  1527         self.zoom_to_fit_on_resize = 
False  1528         self.x = (x1 + x2) / 2
  1529         self.y = (y1 + y2) / 2
  1536         rect.setX (rect.x() + self.ZOOM_TO_FIT_MARGIN)
  1538         rect.setY (rect.y() + self.ZOOM_TO_FIT_MARGIN)
  1540         rect.setWidth(rect.width() - 2 * self.ZOOM_TO_FIT_MARGIN)
  1542         rect.setHeight(rect.height() - 2 * self.ZOOM_TO_FIT_MARGIN)
  1545             float(rect.width())/float(self.graph.width),
  1547             float(rect.height())/float(self.graph.height)
  1549         self.zoom_image(zoom_ratio, center=
True)
  1550         self.zoom_to_fit_on_resize = 
True  1554         self.zoom_image(self.zoom_ratio * self.ZOOM_INCREMENT)
  1558         self.zoom_image(self.zoom_ratio / self.ZOOM_INCREMENT)
  1566         self.zoom_image(1.0)
  1569         self.animation.stop()
  1570         self.drag_action.abort()
  1571         if event.key() == Qt.Key_Left:
  1572             self.x -= self.POS_INCREMENT/self.zoom_ratio
  1574         elif event.key() == Qt.Key_Right:
  1575             self.x += self.POS_INCREMENT/self.zoom_ratio
  1577         elif event.key() == Qt.Key_Up:
  1578             self.y -= self.POS_INCREMENT/self.zoom_ratio
  1580         elif event.key() == Qt.Key_Down:
  1581             self.y += self.POS_INCREMENT/self.zoom_ratio
  1583         elif event.key() == Qt.Key_PageUp:
  1584             self.zoom_image(self.zoom_ratio * self.ZOOM_INCREMENT)
  1586         elif event.key() == Qt.Key_PageDown:
  1587             self.zoom_image(self.zoom_ratio / self.ZOOM_INCREMENT)
  1589         elif event.key() == Qt.Key_PageUp:
  1590             self.drag_action.abort()
  1592         elif event.key() == Qt.Key_R:
  1594         elif event.key() == Qt.Key_F:
  1599         modifiers = event.modifiers()
  1600         if event.button() 
in (Qt.LeftButton, Qt.MidButton):
  1601             if modifiers & Qt.ControlModifier:
  1603             elif modifiers & Qt.ShiftModifier:
  1604                 return ZoomAreaAction
  1610         self.animation.stop()
  1611         self.drag_action.abort()
  1613         for cb 
in self.select_cbs:
  1616         action_type = self.get_drag_action(event)
  1617         self.drag_action = action_type(self)
  1618         self.drag_action.on_button_press(event)
  1620         self.presstime = time.time()
  1621         self.pressx = event.x()
  1622         self.pressy = event.y()
  1625     def is_click(self, event, click_fuzz=4, click_timeout=1.0):
  1626         if self.presstime 
is None:
  1631         deltax = self.pressx - event.x()
  1632         deltay = self.pressy - event.y()
  1633         return (time.time() < self.presstime + click_timeout
  1634                 and math.hypot(deltax, deltay) < click_fuzz)
  1637         self.drag_action.on_button_release(event)
  1639         if event.button() == Qt.LeftButton 
and self.is_click(event):
  1640             x, y = event.x(), event.y()
  1641             url = self.get_url(x, y)
  1643                 self.emit(SIGNAL(
"clicked"), unicode(url.url), event)
  1645                 self.emit(SIGNAL(
"clicked"), 
'none', event)
  1646                 jump = self.get_jump(x, y)
  1647                 if jump 
is not None:
  1648                     self.animate_to(jump.x, jump.y)
  1652         if event.button() == Qt.RightButton 
and self.is_click(event):
  1653             x, y = event.x(), event.y()
  1654             url = self.get_url(x, y)
  1656                 self.emit(SIGNAL(
"right_clicked"), unicode(url.url), event)
  1658                 self.emit(SIGNAL(
"right_clicked"), 
'none', event)
  1659                 jump = self.get_jump(x, y)
  1660                 if jump 
is not None:
  1661                     self.animate_to(jump.x, jump.y)
  1663         if event.button() 
in (Qt.LeftButton, Qt.MidButton):
  1671         if event.delta() > 0:
  1672             self.zoom_image(self.zoom_ratio * self.ZOOM_INCREMENT,
  1673                             pos=(event.x(), event.y()))
  1674         if event.delta() < 0:
  1675             self.zoom_image(self.zoom_ratio / self.ZOOM_INCREMENT,
  1676                             pos=(event.x(), event.y()))
  1679         self.drag_action.on_motion_notify(event)
  1681         for cb 
in self.select_cbs:
  1685         if self.zoom_to_fit_on_resize:
  1690         self.animation.start()
  1695         x -= 0.5*rect.width()
  1696         y -= 0.5*rect.height()
  1697         x /= self.zoom_ratio
  1698         y /= self.zoom_ratio
  1704         x, y = self.window_to_graph(x, y)
  1705         return self.graph.get_url(x, y)
  1708         x, y = self.window_to_graph(x, y)
  1709         return self.graph.get_jump(x, y)
  1717         super(DotWindow,  self).
__init__(
None)
  1719         self.setWindowTitle(QApplication.applicationName())
  1721         self.widget.setContextMenuPolicy(Qt.ActionsContextMenu)
  1722         self.setCentralWidget(self.
widget)
  1724         palette = QPalette ()
  1725         palette.setColor(QPalette.Background, Qt.white)
  1726         self.setPalette(palette)
  1731                 QKeySequence.Open, 
"fileopen", 
"Open an existing dot file")
  1733                 QKeySequence.Refresh, 
"view-refresh", 
"Reload opened dot file")
  1734         zoom_in_action = self.
create_action(
"Zoom In", self.widget.on_zoom_in,
  1735                 QKeySequence.ZoomIn, 
"zoom-in", 
"Zoom in")
  1736         zoom_out_action = self.
create_action(
"Zoom Out", self.widget.on_zoom_out,
  1737                 QKeySequence.ZoomIn, 
"zoom-out", 
"Zoom Out")
  1738         zoom_fit_action = self.
create_action(
"Zoom Fit", self.widget.on_zoom_fit,
  1739                 None, 
"zoom-fit-best", 
"Zoom Fit")
  1740         zoom_100_action = self.
create_action(
"Zoom 100%", self.widget.on_zoom_100,
  1741                 None, 
"zoom-original", 
"Zoom 100%")
  1747         file_toolbar = self.addToolBar(
"File")
  1748         file_toolbar.setObjectName(
"FileToolBar")
  1749         self.
add_actions(file_toolbar, (file_open_action, file_reload_action))
  1751         fileToolbar = self.addToolBar(
"Zoom")
  1752         fileToolbar.setObjectName(
"ZoomToolBar")
  1753         self.
add_actions(fileToolbar, (zoom_in_action, zoom_out_action,  zoom_fit_action,  zoom_100_action))
  1755         settings = QSettings()
  1757         size = settings.value(
"MainWindow/Size", QVariant(QSize(512, 512))).toSize()
  1759         position = settings.value(
"MainWindow/Position", QVariant(QPoint(0, 0))).toPoint()
  1762         self.restoreState(settings.value(
"MainWindow/State").toByteArray())
  1767     def create_action(self, text, slot=None, shortcut=None, icon=None,
  1768                      tip=
None, checkable=
False, signal=
"triggered()"):
  1769         action = QAction(text, self)
  1770         if icon 
is not None:
  1771             action.setIcon(QIcon.fromTheme(icon))
  1772         if shortcut 
is not None:
  1773             action.setShortcut(shortcut)
  1775             action.setToolTip(tip)
  1776             action.setStatusTip(tip)
  1777         if slot 
is not None:
  1778             self.connect(action, SIGNAL(signal), slot)
  1780             action.setCheckable(
True)
  1784         for action 
in actions:
  1786                 target.addSeparator()
  1788                 target.addAction(action)
  1792         if not hasattr(self, 
"last_mtime"):
  1795         current_mtime = os.stat(filename).st_mtime
  1803         self.widget.set_filter(filter)
  1806         if self.widget.set_dotcode(dotcode, filename):
  1807             self.setWindowTitle(os.path.basename(filename) + 
' - ' + QApplication.applicationName())
  1808             self.widget.zoom_to_fit()
  1811         if self.widget.set_xdotcode(xdotcode):
  1812             self.setWindowTitle(os.path.basename(filename) + 
' - ' + QApplication.applicationName())
  1813             self.widget.zoom_to_fit()
  1816         if filename 
is None:
  1817             action = self.sender()
  1818             if isinstance(action, QAction):
  1819                 filename = unicode(action.data().toString())
  1823             fp = file(filename, 
'rt')
  1831         dir = os.path.dirname(self.
filename) \
  1832                 if self.
filename is not None else "."  1834         filename = unicode(QFileDialog.getOpenFileName(self,
  1835                             "Open dot File", dir,
  1836                             "Dot files (%s)" % 
" ".join(formats)))
  1841         self.widget.reload()
  1844         self.file_menu.clear()
  1847                 if self.
filename is not None else None  1850             if fname != current 
and QFile.exists(fname):
  1851                 recent_files.append(fname)
  1853             self.file_menu.addSeparator()
  1854             for i, fname 
in enumerate(recent_files):
  1855                 action = QAction(QIcon(
":/icon.png"), 
"&%d %s" % (i + 1, QFileInfo(fname).fileName()), self)
  1856                 action.setData(QVariant(fname))
  1857                 self.connect(action, SIGNAL(
"triggered()"), self.
open_file)
  1858                 self.file_menu.addAction(action)
  1859         self.file_menu.addSeparator()
  1863         if filename 
is None:
  1865         if not self.recent_files.contains(filename):
  1866             self.recent_files.prepend(QString(filename))
  1867             while self.recent_files.count() > 14:
  1868                 self.recent_files.takeLast()
  1871         settings = QSettings()
  1872         filename = QVariant(QString(self.filename)) 
if self.filename 
is not None else QVariant()
  1873         settings.setValue(
"LastFile", filename)
  1874         recent_files = QVariant(self.recent_files) 
if self.recent_files 
else QVariant()
  1875         settings.setValue(
"RecentFiles", recent_files)
  1876         settings.setValue(
"MainWindow/Size", QVariant(self.size()))
  1883         settings.setValue(
"MainWindow/Position", QVariant(self.pos()))
  1885         settings.setValue(
"MainWindow/State", QVariant(self.saveState()))
  1891     parser = optparse.OptionParser(usage=
'\n\t%prog [file]', version=
'%%prog %s' % __version__)
  1895         type=
'choice', choices=(
'dot', 
'neato', 
'twopi', 
'circo', 
'fdp'),
  1896         dest=
'filter', default=
'dot',
  1897         help=
'graphviz filter: dot, neato, twopi, circo, or fdp [default: %default]')
  1899     (options, args) = parser.parse_args(sys.argv[1:])
  1901         parser.error(
'incorrect number of arguments')
  1903     app = QApplication(sys.argv)
  1904     app.setOrganizationName(
"RobotNV")
  1905     app.setOrganizationDomain(
"robotNV.com")
  1906     app.setApplicationName(
"Dot Viewer")
  1907     app.setWindowIcon(QIcon(
":/icon.png"))
  1915             win.set_dotcode(sys.stdin.read())
  1917             win.open_file(args[0])
  1920     sys.exit(app.exec_())
  1965     'accent3': [(127, 201, 127), (190, 174, 212), (253, 192, 134)],
  1966     'accent4': [(127, 201, 127), (190, 174, 212), (253, 192, 134), (255, 255, 153)],
  1967     'accent5': [(127, 201, 127), (190, 174, 212), (253, 192, 134), (255, 255, 153), (56, 108, 176)],
  1968     'accent6': [(127, 201, 127), (190, 174, 212), (253, 192, 134), (255, 255, 153), (56, 108, 176), (240, 2, 127)],
  1969     'accent7': [(127, 201, 127), (190, 174, 212), (253, 192, 134), (255, 255, 153), (56, 108, 176), (240, 2, 127), (191, 91, 23)],
  1970     'accent8': [(127, 201, 127), (190, 174, 212), (253, 192, 134), (255, 255, 153), (56, 108, 176), (240, 2, 127), (191, 91, 23), (102, 102, 102)],
  1971     'blues3': [(222, 235, 247), (158, 202, 225), (49, 130, 189)],
  1972     'blues4': [(239, 243, 255), (189, 215, 231), (107, 174, 214), (33, 113, 181)],
  1973     'blues5': [(239, 243, 255), (189, 215, 231), (107, 174, 214), (49, 130, 189), (8, 81, 156)],
  1974     'blues6': [(239, 243, 255), (198, 219, 239), (158, 202, 225), (107, 174, 214), (49, 130, 189), (8, 81, 156)],
  1975     'blues7': [(239, 243, 255), (198, 219, 239), (158, 202, 225), (107, 174, 214), (66, 146, 198), (33, 113, 181), (8, 69, 148)],
  1976     'blues8': [(247, 251, 255), (222, 235, 247), (198, 219, 239), (158, 202, 225), (107, 174, 214), (66, 146, 198), (33, 113, 181), (8, 69, 148)],
  1977     'blues9': [(247, 251, 255), (222, 235, 247), (198, 219, 239), (158, 202, 225), (107, 174, 214), (66, 146, 198), (33, 113, 181), (8, 81, 156), (8, 48, 107)],
  1978     'brbg10': [(84, 48, 5), (0, 60, 48), (140, 81, 10), (191, 129, 45), (223, 194, 125), (246, 232, 195), (199, 234, 229), (128, 205, 193), (53, 151, 143), (1, 102, 94)],
  1979     'brbg11': [(84, 48, 5), (1, 102, 94), (0, 60, 48), (140, 81, 10), (191, 129, 45), (223, 194, 125), (246, 232, 195), (245, 245, 245), (199, 234, 229), (128, 205, 193), (53, 151, 143)],
  1980     'brbg3': [(216, 179, 101), (245, 245, 245), (90, 180, 172)],
  1981     'brbg4': [(166, 97, 26), (223, 194, 125), (128, 205, 193), (1, 133, 113)],
  1982     'brbg5': [(166, 97, 26), (223, 194, 125), (245, 245, 245), (128, 205, 193), (1, 133, 113)],
  1983     'brbg6': [(140, 81, 10), (216, 179, 101), (246, 232, 195), (199, 234, 229), (90, 180, 172), (1, 102, 94)],
  1984     'brbg7': [(140, 81, 10), (216, 179, 101), (246, 232, 195), (245, 245, 245), (199, 234, 229), (90, 180, 172), (1, 102, 94)],
  1985     'brbg8': [(140, 81, 10), (191, 129, 45), (223, 194, 125), (246, 232, 195), (199, 234, 229), (128, 205, 193), (53, 151, 143), (1, 102, 94)],
  1986     'brbg9': [(140, 81, 10), (191, 129, 45), (223, 194, 125), (246, 232, 195), (245, 245, 245), (199, 234, 229), (128, 205, 193), (53, 151, 143), (1, 102, 94)],
  1987     'bugn3': [(229, 245, 249), (153, 216, 201), (44, 162, 95)],
  1988     'bugn4': [(237, 248, 251), (178, 226, 226), (102, 194, 164), (35, 139, 69)],
  1989     'bugn5': [(237, 248, 251), (178, 226, 226), (102, 194, 164), (44, 162, 95), (0, 109, 44)],
  1990     'bugn6': [(237, 248, 251), (204, 236, 230), (153, 216, 201), (102, 194, 164), (44, 162, 95), (0, 109, 44)],
  1991     'bugn7': [(237, 248, 251), (204, 236, 230), (153, 216, 201), (102, 194, 164), (65, 174, 118), (35, 139, 69), (0, 88, 36)],
  1992     'bugn8': [(247, 252, 253), (229, 245, 249), (204, 236, 230), (153, 216, 201), (102, 194, 164), (65, 174, 118), (35, 139, 69), (0, 88, 36)],
  1993     'bugn9': [(247, 252, 253), (229, 245, 249), (204, 236, 230), (153, 216, 201), (102, 194, 164), (65, 174, 118), (35, 139, 69), (0, 109, 44), (0, 68, 27)],
  1994     'bupu3': [(224, 236, 244), (158, 188, 218), (136, 86, 167)],
  1995     'bupu4': [(237, 248, 251), (179, 205, 227), (140, 150, 198), (136, 65, 157)],
  1996     'bupu5': [(237, 248, 251), (179, 205, 227), (140, 150, 198), (136, 86, 167), (129, 15, 124)],
  1997     'bupu6': [(237, 248, 251), (191, 211, 230), (158, 188, 218), (140, 150, 198), (136, 86, 167), (129, 15, 124)],
  1998     'bupu7': [(237, 248, 251), (191, 211, 230), (158, 188, 218), (140, 150, 198), (140, 107, 177), (136, 65, 157), (110, 1, 107)],
  1999     'bupu8': [(247, 252, 253), (224, 236, 244), (191, 211, 230), (158, 188, 218), (140, 150, 198), (140, 107, 177), (136, 65, 157), (110, 1, 107)],
  2000     'bupu9': [(247, 252, 253), (224, 236, 244), (191, 211, 230), (158, 188, 218), (140, 150, 198), (140, 107, 177), (136, 65, 157), (129, 15, 124), (77, 0, 75)],
  2001     'dark23': [(27, 158, 119), (217, 95, 2), (117, 112, 179)],
  2002     'dark24': [(27, 158, 119), (217, 95, 2), (117, 112, 179), (231, 41, 138)],
  2003     'dark25': [(27, 158, 119), (217, 95, 2), (117, 112, 179), (231, 41, 138), (102, 166, 30)],
  2004     'dark26': [(27, 158, 119), (217, 95, 2), (117, 112, 179), (231, 41, 138), (102, 166, 30), (230, 171, 2)],
  2005     'dark27': [(27, 158, 119), (217, 95, 2), (117, 112, 179), (231, 41, 138), (102, 166, 30), (230, 171, 2), (166, 118, 29)],
  2006     'dark28': [(27, 158, 119), (217, 95, 2), (117, 112, 179), (231, 41, 138), (102, 166, 30), (230, 171, 2), (166, 118, 29), (102, 102, 102)],
  2007     'gnbu3': [(224, 243, 219), (168, 221, 181), (67, 162, 202)],
  2008     'gnbu4': [(240, 249, 232), (186, 228, 188), (123, 204, 196), (43, 140, 190)],
  2009     'gnbu5': [(240, 249, 232), (186, 228, 188), (123, 204, 196), (67, 162, 202), (8, 104, 172)],
  2010     'gnbu6': [(240, 249, 232), (204, 235, 197), (168, 221, 181), (123, 204, 196), (67, 162, 202), (8, 104, 172)],
  2011     'gnbu7': [(240, 249, 232), (204, 235, 197), (168, 221, 181), (123, 204, 196), (78, 179, 211), (43, 140, 190), (8, 88, 158)],
  2012     'gnbu8': [(247, 252, 240), (224, 243, 219), (204, 235, 197), (168, 221, 181), (123, 204, 196), (78, 179, 211), (43, 140, 190), (8, 88, 158)],
  2013     'gnbu9': [(247, 252, 240), (224, 243, 219), (204, 235, 197), (168, 221, 181), (123, 204, 196), (78, 179, 211), (43, 140, 190), (8, 104, 172), (8, 64, 129)],
  2014     'greens3': [(229, 245, 224), (161, 217, 155), (49, 163, 84)],
  2015     'greens4': [(237, 248, 233), (186, 228, 179), (116, 196, 118), (35, 139, 69)],
  2016     'greens5': [(237, 248, 233), (186, 228, 179), (116, 196, 118), (49, 163, 84), (0, 109, 44)],
  2017     'greens6': [(237, 248, 233), (199, 233, 192), (161, 217, 155), (116, 196, 118), (49, 163, 84), (0, 109, 44)],
  2018     'greens7': [(237, 248, 233), (199, 233, 192), (161, 217, 155), (116, 196, 118), (65, 171, 93), (35, 139, 69), (0, 90, 50)],
  2019     'greens8': [(247, 252, 245), (229, 245, 224), (199, 233, 192), (161, 217, 155), (116, 196, 118), (65, 171, 93), (35, 139, 69), (0, 90, 50)],
  2020     'greens9': [(247, 252, 245), (229, 245, 224), (199, 233, 192), (161, 217, 155), (116, 196, 118), (65, 171, 93), (35, 139, 69), (0, 109, 44), (0, 68, 27)],
  2021     'greys3': [(240, 240, 240), (189, 189, 189), (99, 99, 99)],
  2022     'greys4': [(247, 247, 247), (204, 204, 204), (150, 150, 150), (82, 82, 82)],
  2023     'greys5': [(247, 247, 247), (204, 204, 204), (150, 150, 150), (99, 99, 99), (37, 37, 37)],
  2024     'greys6': [(247, 247, 247), (217, 217, 217), (189, 189, 189), (150, 150, 150), (99, 99, 99), (37, 37, 37)],
  2025     'greys7': [(247, 247, 247), (217, 217, 217), (189, 189, 189), (150, 150, 150), (115, 115, 115), (82, 82, 82), (37, 37, 37)],
  2026     'greys8': [(255, 255, 255), (240, 240, 240), (217, 217, 217), (189, 189, 189), (150, 150, 150), (115, 115, 115), (82, 82, 82), (37, 37, 37)],
  2027     'greys9': [(255, 255, 255), (240, 240, 240), (217, 217, 217), (189, 189, 189), (150, 150, 150), (115, 115, 115), (82, 82, 82), (37, 37, 37), (0, 0, 0)],
  2028     'oranges3': [(254, 230, 206), (253, 174, 107), (230, 85, 13)],
  2029     'oranges4': [(254, 237, 222), (253, 190, 133), (253, 141, 60), (217, 71, 1)],
  2030     'oranges5': [(254, 237, 222), (253, 190, 133), (253, 141, 60), (230, 85, 13), (166, 54, 3)],
  2031     'oranges6': [(254, 237, 222), (253, 208, 162), (253, 174, 107), (253, 141, 60), (230, 85, 13), (166, 54, 3)],
  2032     'oranges7': [(254, 237, 222), (253, 208, 162), (253, 174, 107), (253, 141, 60), (241, 105, 19), (217, 72, 1), (140, 45, 4)],
  2033     'oranges8': [(255, 245, 235), (254, 230, 206), (253, 208, 162), (253, 174, 107), (253, 141, 60), (241, 105, 19), (217, 72, 1), (140, 45, 4)],
  2034     'oranges9': [(255, 245, 235), (254, 230, 206), (253, 208, 162), (253, 174, 107), (253, 141, 60), (241, 105, 19), (217, 72, 1), (166, 54, 3), (127, 39, 4)],
  2035     'orrd3': [(254, 232, 200), (253, 187, 132), (227, 74, 51)],
  2036     'orrd4': [(254, 240, 217), (253, 204, 138), (252, 141, 89), (215, 48, 31)],
  2037     'orrd5': [(254, 240, 217), (253, 204, 138), (252, 141, 89), (227, 74, 51), (179, 0, 0)],
  2038     'orrd6': [(254, 240, 217), (253, 212, 158), (253, 187, 132), (252, 141, 89), (227, 74, 51), (179, 0, 0)],
  2039     'orrd7': [(254, 240, 217), (253, 212, 158), (253, 187, 132), (252, 141, 89), (239, 101, 72), (215, 48, 31), (153, 0, 0)],
  2040     'orrd8': [(255, 247, 236), (254, 232, 200), (253, 212, 158), (253, 187, 132), (252, 141, 89), (239, 101, 72), (215, 48, 31), (153, 0, 0)],
  2041     'orrd9': [(255, 247, 236), (254, 232, 200), (253, 212, 158), (253, 187, 132), (252, 141, 89), (239, 101, 72), (215, 48, 31), (179, 0, 0), (127, 0, 0)],
  2042     'paired10': [(166, 206, 227), (106, 61, 154), (31, 120, 180), (178, 223, 138), (51, 160, 44), (251, 154, 153), (227, 26, 28), (253, 191, 111), (255, 127, 0), (202, 178, 214)],
  2043     'paired11': [(166, 206, 227), (106, 61, 154), (255, 255, 153), (31, 120, 180), (178, 223, 138), (51, 160, 44), (251, 154, 153), (227, 26, 28), (253, 191, 111), (255, 127, 0), (202, 178, 214)],
  2044     'paired12': [(166, 206, 227), (106, 61, 154), (255, 255, 153), (177, 89, 40), (31, 120, 180), (178, 223, 138), (51, 160, 44), (251, 154, 153), (227, 26, 28), (253, 191, 111), (255, 127, 0), (202, 178, 214)],
  2045     'paired3': [(166, 206, 227), (31, 120, 180), (178, 223, 138)],
  2046     'paired4': [(166, 206, 227), (31, 120, 180), (178, 223, 138), (51, 160, 44)],
  2047     'paired5': [(166, 206, 227), (31, 120, 180), (178, 223, 138), (51, 160, 44), (251, 154, 153)],
  2048     'paired6': [(166, 206, 227), (31, 120, 180), (178, 223, 138), (51, 160, 44), (251, 154, 153), (227, 26, 28)],
  2049     'paired7': [(166, 206, 227), (31, 120, 180), (178, 223, 138), (51, 160, 44), (251, 154, 153), (227, 26, 28), (253, 191, 111)],
  2050     'paired8': [(166, 206, 227), (31, 120, 180), (178, 223, 138), (51, 160, 44), (251, 154, 153), (227, 26, 28), (253, 191, 111), (255, 127, 0)],
  2051     'paired9': [(166, 206, 227), (31, 120, 180), (178, 223, 138), (51, 160, 44), (251, 154, 153), (227, 26, 28), (253, 191, 111), (255, 127, 0), (202, 178, 214)],
  2052     'pastel13': [(251, 180, 174), (179, 205, 227), (204, 235, 197)],
  2053     'pastel14': [(251, 180, 174), (179, 205, 227), (204, 235, 197), (222, 203, 228)],
  2054     'pastel15': [(251, 180, 174), (179, 205, 227), (204, 235, 197), (222, 203, 228), (254, 217, 166)],
  2055     'pastel16': [(251, 180, 174), (179, 205, 227), (204, 235, 197), (222, 203, 228), (254, 217, 166), (255, 255, 204)],
  2056     'pastel17': [(251, 180, 174), (179, 205, 227), (204, 235, 197), (222, 203, 228), (254, 217, 166), (255, 255, 204), (229, 216, 189)],
  2057     'pastel18': [(251, 180, 174), (179, 205, 227), (204, 235, 197), (222, 203, 228), (254, 217, 166), (255, 255, 204), (229, 216, 189), (253, 218, 236)],
  2058     'pastel19': [(251, 180, 174), (179, 205, 227), (204, 235, 197), (222, 203, 228), (254, 217, 166), (255, 255, 204), (229, 216, 189), (253, 218, 236), (242, 242, 242)],
  2059     'pastel23': [(179, 226, 205), (253, 205, 172), (203, 213, 232)],
  2060     'pastel24': [(179, 226, 205), (253, 205, 172), (203, 213, 232), (244, 202, 228)],
  2061     'pastel25': [(179, 226, 205), (253, 205, 172), (203, 213, 232), (244, 202, 228), (230, 245, 201)],
  2062     'pastel26': [(179, 226, 205), (253, 205, 172), (203, 213, 232), (244, 202, 228), (230, 245, 201), (255, 242, 174)],
  2063     'pastel27': [(179, 226, 205), (253, 205, 172), (203, 213, 232), (244, 202, 228), (230, 245, 201), (255, 242, 174), (241, 226, 204)],
  2064     'pastel28': [(179, 226, 205), (253, 205, 172), (203, 213, 232), (244, 202, 228), (230, 245, 201), (255, 242, 174), (241, 226, 204), (204, 204, 204)],
  2065     'piyg10': [(142, 1, 82), (39, 100, 25), (197, 27, 125), (222, 119, 174), (241, 182, 218), (253, 224, 239), (230, 245, 208), (184, 225, 134), (127, 188, 65), (77, 146, 33)],
  2066     'piyg11': [(142, 1, 82), (77, 146, 33), (39, 100, 25), (197, 27, 125), (222, 119, 174), (241, 182, 218), (253, 224, 239), (247, 247, 247), (230, 245, 208), (184, 225, 134), (127, 188, 65)],
  2067     'piyg3': [(233, 163, 201), (247, 247, 247), (161, 215, 106)],
  2068     'piyg4': [(208, 28, 139), (241, 182, 218), (184, 225, 134), (77, 172, 38)],
  2069     'piyg5': [(208, 28, 139), (241, 182, 218), (247, 247, 247), (184, 225, 134), (77, 172, 38)],
  2070     'piyg6': [(197, 27, 125), (233, 163, 201), (253, 224, 239), (230, 245, 208), (161, 215, 106), (77, 146, 33)],
  2071     'piyg7': [(197, 27, 125), (233, 163, 201), (253, 224, 239), (247, 247, 247), (230, 245, 208), (161, 215, 106), (77, 146, 33)],
  2072     'piyg8': [(197, 27, 125), (222, 119, 174), (241, 182, 218), (253, 224, 239), (230, 245, 208), (184, 225, 134), (127, 188, 65), (77, 146, 33)],
  2073     'piyg9': [(197, 27, 125), (222, 119, 174), (241, 182, 218), (253, 224, 239), (247, 247, 247), (230, 245, 208), (184, 225, 134), (127, 188, 65), (77, 146, 33)],
  2074     'prgn10': [(64, 0, 75), (0, 68, 27), (118, 42, 131), (153, 112, 171), (194, 165, 207), (231, 212, 232), (217, 240, 211), (166, 219, 160), (90, 174, 97), (27, 120, 55)],
  2075     'prgn11': [(64, 0, 75), (27, 120, 55), (0, 68, 27), (118, 42, 131), (153, 112, 171), (194, 165, 207), (231, 212, 232), (247, 247, 247), (217, 240, 211), (166, 219, 160), (90, 174, 97)],
  2076     'prgn3': [(175, 141, 195), (247, 247, 247), (127, 191, 123)],
  2077     'prgn4': [(123, 50, 148), (194, 165, 207), (166, 219, 160), (0, 136, 55)],
  2078     'prgn5': [(123, 50, 148), (194, 165, 207), (247, 247, 247), (166, 219, 160), (0, 136, 55)],
  2079     'prgn6': [(118, 42, 131), (175, 141, 195), (231, 212, 232), (217, 240, 211), (127, 191, 123), (27, 120, 55)],
  2080     'prgn7': [(118, 42, 131), (175, 141, 195), (231, 212, 232), (247, 247, 247), (217, 240, 211), (127, 191, 123), (27, 120, 55)],
  2081     'prgn8': [(118, 42, 131), (153, 112, 171), (194, 165, 207), (231, 212, 232), (217, 240, 211), (166, 219, 160), (90, 174, 97), (27, 120, 55)],
  2082     'prgn9': [(118, 42, 131), (153, 112, 171), (194, 165, 207), (231, 212, 232), (247, 247, 247), (217, 240, 211), (166, 219, 160), (90, 174, 97), (27, 120, 55)],
  2083     'pubu3': [(236, 231, 242), (166, 189, 219), (43, 140, 190)],
  2084     'pubu4': [(241, 238, 246), (189, 201, 225), (116, 169, 207), (5, 112, 176)],
  2085     'pubu5': [(241, 238, 246), (189, 201, 225), (116, 169, 207), (43, 140, 190), (4, 90, 141)],
  2086     'pubu6': [(241, 238, 246), (208, 209, 230), (166, 189, 219), (116, 169, 207), (43, 140, 190), (4, 90, 141)],
  2087     'pubu7': [(241, 238, 246), (208, 209, 230), (166, 189, 219), (116, 169, 207), (54, 144, 192), (5, 112, 176), (3, 78, 123)],
  2088     'pubu8': [(255, 247, 251), (236, 231, 242), (208, 209, 230), (166, 189, 219), (116, 169, 207), (54, 144, 192), (5, 112, 176), (3, 78, 123)],
  2089     'pubu9': [(255, 247, 251), (236, 231, 242), (208, 209, 230), (166, 189, 219), (116, 169, 207), (54, 144, 192), (5, 112, 176), (4, 90, 141), (2, 56, 88)],
  2090     'pubugn3': [(236, 226, 240), (166, 189, 219), (28, 144, 153)],
  2091     'pubugn4': [(246, 239, 247), (189, 201, 225), (103, 169, 207), (2, 129, 138)],
  2092     'pubugn5': [(246, 239, 247), (189, 201, 225), (103, 169, 207), (28, 144, 153), (1, 108, 89)],
  2093     'pubugn6': [(246, 239, 247), (208, 209, 230), (166, 189, 219), (103, 169, 207), (28, 144, 153), (1, 108, 89)],
  2094     'pubugn7': [(246, 239, 247), (208, 209, 230), (166, 189, 219), (103, 169, 207), (54, 144, 192), (2, 129, 138), (1, 100, 80)],
  2095     'pubugn8': [(255, 247, 251), (236, 226, 240), (208, 209, 230), (166, 189, 219), (103, 169, 207), (54, 144, 192), (2, 129, 138), (1, 100, 80)],
  2096     'pubugn9': [(255, 247, 251), (236, 226, 240), (208, 209, 230), (166, 189, 219), (103, 169, 207), (54, 144, 192), (2, 129, 138), (1, 108, 89), (1, 70, 54)],
  2097     'puor10': [(127, 59, 8), (45, 0, 75), (179, 88, 6), (224, 130, 20), (253, 184, 99), (254, 224, 182), (216, 218, 235), (178, 171, 210), (128, 115, 172), (84, 39, 136)],
  2098     'puor11': [(127, 59, 8), (84, 39, 136), (45, 0, 75), (179, 88, 6), (224, 130, 20), (253, 184, 99), (254, 224, 182), (247, 247, 247), (216, 218, 235), (178, 171, 210), (128, 115, 172)],
  2099     'puor3': [(241, 163, 64), (247, 247, 247), (153, 142, 195)],
  2100     'puor4': [(230, 97, 1), (253, 184, 99), (178, 171, 210), (94, 60, 153)],
  2101     'puor5': [(230, 97, 1), (253, 184, 99), (247, 247, 247), (178, 171, 210), (94, 60, 153)],
  2102     'puor6': [(179, 88, 6), (241, 163, 64), (254, 224, 182), (216, 218, 235), (153, 142, 195), (84, 39, 136)],
  2103     'puor7': [(179, 88, 6), (241, 163, 64), (254, 224, 182), (247, 247, 247), (216, 218, 235), (153, 142, 195), (84, 39, 136)],
  2104     'puor8': [(179, 88, 6), (224, 130, 20), (253, 184, 99), (254, 224, 182), (216, 218, 235), (178, 171, 210), (128, 115, 172), (84, 39, 136)],
  2105     'puor9': [(179, 88, 6), (224, 130, 20), (253, 184, 99), (254, 224, 182), (247, 247, 247), (216, 218, 235), (178, 171, 210), (128, 115, 172), (84, 39, 136)],
  2106     'purd3': [(231, 225, 239), (201, 148, 199), (221, 28, 119)],
  2107     'purd4': [(241, 238, 246), (215, 181, 216), (223, 101, 176), (206, 18, 86)],
  2108     'purd5': [(241, 238, 246), (215, 181, 216), (223, 101, 176), (221, 28, 119), (152, 0, 67)],
  2109     'purd6': [(241, 238, 246), (212, 185, 218), (201, 148, 199), (223, 101, 176), (221, 28, 119), (152, 0, 67)],
  2110     'purd7': [(241, 238, 246), (212, 185, 218), (201, 148, 199), (223, 101, 176), (231, 41, 138), (206, 18, 86), (145, 0, 63)],
  2111     'purd8': [(247, 244, 249), (231, 225, 239), (212, 185, 218), (201, 148, 199), (223, 101, 176), (231, 41, 138), (206, 18, 86), (145, 0, 63)],
  2112     'purd9': [(247, 244, 249), (231, 225, 239), (212, 185, 218), (201, 148, 199), (223, 101, 176), (231, 41, 138), (206, 18, 86), (152, 0, 67), (103, 0, 31)],
  2113     'purples3': [(239, 237, 245), (188, 189, 220), (117, 107, 177)],
  2114     'purples4': [(242, 240, 247), (203, 201, 226), (158, 154, 200), (106, 81, 163)],
  2115     'purples5': [(242, 240, 247), (203, 201, 226), (158, 154, 200), (117, 107, 177), (84, 39, 143)],
  2116     'purples6': [(242, 240, 247), (218, 218, 235), (188, 189, 220), (158, 154, 200), (117, 107, 177), (84, 39, 143)],
  2117     'purples7': [(242, 240, 247), (218, 218, 235), (188, 189, 220), (158, 154, 200), (128, 125, 186), (106, 81, 163), (74, 20, 134)],
  2118     'purples8': [(252, 251, 253), (239, 237, 245), (218, 218, 235), (188, 189, 220), (158, 154, 200), (128, 125, 186), (106, 81, 163), (74, 20, 134)],
  2119     'purples9': [(252, 251, 253), (239, 237, 245), (218, 218, 235), (188, 189, 220), (158, 154, 200), (128, 125, 186), (106, 81, 163), (84, 39, 143), (63, 0, 125)],
  2120     'rdbu10': [(103, 0, 31), (5, 48, 97), (178, 24, 43), (214, 96, 77), (244, 165, 130), (253, 219, 199), (209, 229, 240), (146, 197, 222), (67, 147, 195), (33, 102, 172)],
  2121     'rdbu11': [(103, 0, 31), (33, 102, 172), (5, 48, 97), (178, 24, 43), (214, 96, 77), (244, 165, 130), (253, 219, 199), (247, 247, 247), (209, 229, 240), (146, 197, 222), (67, 147, 195)],
  2122     'rdbu3': [(239, 138, 98), (247, 247, 247), (103, 169, 207)],
  2123     'rdbu4': [(202, 0, 32), (244, 165, 130), (146, 197, 222), (5, 113, 176)],
  2124     'rdbu5': [(202, 0, 32), (244, 165, 130), (247, 247, 247), (146, 197, 222), (5, 113, 176)],
  2125     'rdbu6': [(178, 24, 43), (239, 138, 98), (253, 219, 199), (209, 229, 240), (103, 169, 207), (33, 102, 172)],
  2126     'rdbu7': [(178, 24, 43), (239, 138, 98), (253, 219, 199), (247, 247, 247), (209, 229, 240), (103, 169, 207), (33, 102, 172)],
  2127     'rdbu8': [(178, 24, 43), (214, 96, 77), (244, 165, 130), (253, 219, 199), (209, 229, 240), (146, 197, 222), (67, 147, 195), (33, 102, 172)],
  2128     'rdbu9': [(178, 24, 43), (214, 96, 77), (244, 165, 130), (253, 219, 199), (247, 247, 247), (209, 229, 240), (146, 197, 222), (67, 147, 195), (33, 102, 172)],
  2129     'rdgy10': [(103, 0, 31), (26, 26, 26), (178, 24, 43), (214, 96, 77), (244, 165, 130), (253, 219, 199), (224, 224, 224), (186, 186, 186), (135, 135, 135), (77, 77, 77)],
  2130     'rdgy11': [(103, 0, 31), (77, 77, 77), (26, 26, 26), (178, 24, 43), (214, 96, 77), (244, 165, 130), (253, 219, 199), (255, 255, 255), (224, 224, 224), (186, 186, 186), (135, 135, 135)],
  2131     'rdgy3': [(239, 138, 98), (255, 255, 255), (153, 153, 153)],
  2132     'rdgy4': [(202, 0, 32), (244, 165, 130), (186, 186, 186), (64, 64, 64)],
  2133     'rdgy5': [(202, 0, 32), (244, 165, 130), (255, 255, 255), (186, 186, 186), (64, 64, 64)],
  2134     'rdgy6': [(178, 24, 43), (239, 138, 98), (253, 219, 199), (224, 224, 224), (153, 153, 153), (77, 77, 77)],
  2135     'rdgy7': [(178, 24, 43), (239, 138, 98), (253, 219, 199), (255, 255, 255), (224, 224, 224), (153, 153, 153), (77, 77, 77)],
  2136     'rdgy8': [(178, 24, 43), (214, 96, 77), (244, 165, 130), (253, 219, 199), (224, 224, 224), (186, 186, 186), (135, 135, 135), (77, 77, 77)],
  2137     'rdgy9': [(178, 24, 43), (214, 96, 77), (244, 165, 130), (253, 219, 199), (255, 255, 255), (224, 224, 224), (186, 186, 186), (135, 135, 135), (77, 77, 77)],
  2138     'rdpu3': [(253, 224, 221), (250, 159, 181), (197, 27, 138)],
  2139     'rdpu4': [(254, 235, 226), (251, 180, 185), (247, 104, 161), (174, 1, 126)],
  2140     'rdpu5': [(254, 235, 226), (251, 180, 185), (247, 104, 161), (197, 27, 138), (122, 1, 119)],
  2141     'rdpu6': [(254, 235, 226), (252, 197, 192), (250, 159, 181), (247, 104, 161), (197, 27, 138), (122, 1, 119)],
  2142     'rdpu7': [(254, 235, 226), (252, 197, 192), (250, 159, 181), (247, 104, 161), (221, 52, 151), (174, 1, 126), (122, 1, 119)],
  2143     'rdpu8': [(255, 247, 243), (253, 224, 221), (252, 197, 192), (250, 159, 181), (247, 104, 161), (221, 52, 151), (174, 1, 126), (122, 1, 119)],
  2144     'rdpu9': [(255, 247, 243), (253, 224, 221), (252, 197, 192), (250, 159, 181), (247, 104, 161), (221, 52, 151), (174, 1, 126), (122, 1, 119), (73, 0, 106)],
  2145     'rdylbu10': [(165, 0, 38), (49, 54, 149), (215, 48, 39), (244, 109, 67), (253, 174, 97), (254, 224, 144), (224, 243, 248), (171, 217, 233), (116, 173, 209), (69, 117, 180)],
  2146     'rdylbu11': [(165, 0, 38), (69, 117, 180), (49, 54, 149), (215, 48, 39), (244, 109, 67), (253, 174, 97), (254, 224, 144), (255, 255, 191), (224, 243, 248), (171, 217, 233), (116, 173, 209)],
  2147     'rdylbu3': [(252, 141, 89), (255, 255, 191), (145, 191, 219)],
  2148     'rdylbu4': [(215, 25, 28), (253, 174, 97), (171, 217, 233), (44, 123, 182)],
  2149     'rdylbu5': [(215, 25, 28), (253, 174, 97), (255, 255, 191), (171, 217, 233), (44, 123, 182)],
  2150     'rdylbu6': [(215, 48, 39), (252, 141, 89), (254, 224, 144), (224, 243, 248), (145, 191, 219), (69, 117, 180)],
  2151     'rdylbu7': [(215, 48, 39), (252, 141, 89), (254, 224, 144), (255, 255, 191), (224, 243, 248), (145, 191, 219), (69, 117, 180)],
  2152     'rdylbu8': [(215, 48, 39), (244, 109, 67), (253, 174, 97), (254, 224, 144), (224, 243, 248), (171, 217, 233), (116, 173, 209), (69, 117, 180)],
  2153     'rdylbu9': [(215, 48, 39), (244, 109, 67), (253, 174, 97), (254, 224, 144), (255, 255, 191), (224, 243, 248), (171, 217, 233), (116, 173, 209), (69, 117, 180)],
  2154     'rdylgn10': [(165, 0, 38), (0, 104, 55), (215, 48, 39), (244, 109, 67), (253, 174, 97), (254, 224, 139), (217, 239, 139), (166, 217, 106), (102, 189, 99), (26, 152, 80)],
  2155     'rdylgn11': [(165, 0, 38), (26, 152, 80), (0, 104, 55), (215, 48, 39), (244, 109, 67), (253, 174, 97), (254, 224, 139), (255, 255, 191), (217, 239, 139), (166, 217, 106), (102, 189, 99)],
  2156     'rdylgn3': [(252, 141, 89), (255, 255, 191), (145, 207, 96)],
  2157     'rdylgn4': [(215, 25, 28), (253, 174, 97), (166, 217, 106), (26, 150, 65)],
  2158     'rdylgn5': [(215, 25, 28), (253, 174, 97), (255, 255, 191), (166, 217, 106), (26, 150, 65)],
  2159     'rdylgn6': [(215, 48, 39), (252, 141, 89), (254, 224, 139), (217, 239, 139), (145, 207, 96), (26, 152, 80)],
  2160     'rdylgn7': [(215, 48, 39), (252, 141, 89), (254, 224, 139), (255, 255, 191), (217, 239, 139), (145, 207, 96), (26, 152, 80)],
  2161     'rdylgn8': [(215, 48, 39), (244, 109, 67), (253, 174, 97), (254, 224, 139), (217, 239, 139), (166, 217, 106), (102, 189, 99), (26, 152, 80)],
  2162     'rdylgn9': [(215, 48, 39), (244, 109, 67), (253, 174, 97), (254, 224, 139), (255, 255, 191), (217, 239, 139), (166, 217, 106), (102, 189, 99), (26, 152, 80)],
  2163     'reds3': [(254, 224, 210), (252, 146, 114), (222, 45, 38)],
  2164     'reds4': [(254, 229, 217), (252, 174, 145), (251, 106, 74), (203, 24, 29)],
  2165     'reds5': [(254, 229, 217), (252, 174, 145), (251, 106, 74), (222, 45, 38), (165, 15, 21)],
  2166     'reds6': [(254, 229, 217), (252, 187, 161), (252, 146, 114), (251, 106, 74), (222, 45, 38), (165, 15, 21)],
  2167     'reds7': [(254, 229, 217), (252, 187, 161), (252, 146, 114), (251, 106, 74), (239, 59, 44), (203, 24, 29), (153, 0, 13)],
  2168     'reds8': [(255, 245, 240), (254, 224, 210), (252, 187, 161), (252, 146, 114), (251, 106, 74), (239, 59, 44), (203, 24, 29), (153, 0, 13)],
  2169     'reds9': [(255, 245, 240), (254, 224, 210), (252, 187, 161), (252, 146, 114), (251, 106, 74), (239, 59, 44), (203, 24, 29), (165, 15, 21), (103, 0, 13)],
  2170     'set13': [(228, 26, 28), (55, 126, 184), (77, 175, 74)],
  2171     'set14': [(228, 26, 28), (55, 126, 184), (77, 175, 74), (152, 78, 163)],
  2172     'set15': [(228, 26, 28), (55, 126, 184), (77, 175, 74), (152, 78, 163), (255, 127, 0)],
  2173     'set16': [(228, 26, 28), (55, 126, 184), (77, 175, 74), (152, 78, 163), (255, 127, 0), (255, 255, 51)],
  2174     'set17': [(228, 26, 28), (55, 126, 184), (77, 175, 74), (152, 78, 163), (255, 127, 0), (255, 255, 51), (166, 86, 40)],
  2175     'set18': [(228, 26, 28), (55, 126, 184), (77, 175, 74), (152, 78, 163), (255, 127, 0), (255, 255, 51), (166, 86, 40), (247, 129, 191)],
  2176     'set19': [(228, 26, 28), (55, 126, 184), (77, 175, 74), (152, 78, 163), (255, 127, 0), (255, 255, 51), (166, 86, 40), (247, 129, 191), (153, 153, 153)],
  2177     'set23': [(102, 194, 165), (252, 141, 98), (141, 160, 203)],
  2178     'set24': [(102, 194, 165), (252, 141, 98), (141, 160, 203), (231, 138, 195)],
  2179     'set25': [(102, 194, 165), (252, 141, 98), (141, 160, 203), (231, 138, 195), (166, 216, 84)],
  2180     'set26': [(102, 194, 165), (252, 141, 98), (141, 160, 203), (231, 138, 195), (166, 216, 84), (255, 217, 47)],
  2181     'set27': [(102, 194, 165), (252, 141, 98), (141, 160, 203), (231, 138, 195), (166, 216, 84), (255, 217, 47), (229, 196, 148)],
  2182     'set28': [(102, 194, 165), (252, 141, 98), (141, 160, 203), (231, 138, 195), (166, 216, 84), (255, 217, 47), (229, 196, 148), (179, 179, 179)],
  2183     'set310': [(141, 211, 199), (188, 128, 189), (255, 255, 179), (190, 186, 218), (251, 128, 114), (128, 177, 211), (253, 180, 98), (179, 222, 105), (252, 205, 229), (217, 217, 217)],
  2184     'set311': [(141, 211, 199), (188, 128, 189), (204, 235, 197), (255, 255, 179), (190, 186, 218), (251, 128, 114), (128, 177, 211), (253, 180, 98), (179, 222, 105), (252, 205, 229), (217, 217, 217)],
  2185     'set312': [(141, 211, 199), (188, 128, 189), (204, 235, 197), (255, 237, 111), (255, 255, 179), (190, 186, 218), (251, 128, 114), (128, 177, 211), (253, 180, 98), (179, 222, 105), (252, 205, 229), (217, 217, 217)],
  2186     'set33': [(141, 211, 199), (255, 255, 179), (190, 186, 218)],
  2187     'set34': [(141, 211, 199), (255, 255, 179), (190, 186, 218), (251, 128, 114)],
  2188     'set35': [(141, 211, 199), (255, 255, 179), (190, 186, 218), (251, 128, 114), (128, 177, 211)],
  2189     'set36': [(141, 211, 199), (255, 255, 179), (190, 186, 218), (251, 128, 114), (128, 177, 211), (253, 180, 98)],
  2190     'set37': [(141, 211, 199), (255, 255, 179), (190, 186, 218), (251, 128, 114), (128, 177, 211), (253, 180, 98), (179, 222, 105)],
  2191     'set38': [(141, 211, 199), (255, 255, 179), (190, 186, 218), (251, 128, 114), (128, 177, 211), (253, 180, 98), (179, 222, 105), (252, 205, 229)],
  2192     'set39': [(141, 211, 199), (255, 255, 179), (190, 186, 218), (251, 128, 114), (128, 177, 211), (253, 180, 98), (179, 222, 105), (252, 205, 229), (217, 217, 217)],
  2193     'spectral10': [(158, 1, 66), (94, 79, 162), (213, 62, 79), (244, 109, 67), (253, 174, 97), (254, 224, 139), (230, 245, 152), (171, 221, 164), (102, 194, 165), (50, 136, 189)],
  2194     'spectral11': [(158, 1, 66), (50, 136, 189), (94, 79, 162), (213, 62, 79), (244, 109, 67), (253, 174, 97), (254, 224, 139), (255, 255, 191), (230, 245, 152), (171, 221, 164), (102, 194, 165)],
  2195     'spectral3': [(252, 141, 89), (255, 255, 191), (153, 213, 148)],
  2196     'spectral4': [(215, 25, 28), (253, 174, 97), (171, 221, 164), (43, 131, 186)],
  2197     'spectral5': [(215, 25, 28), (253, 174, 97), (255, 255, 191), (171, 221, 164), (43, 131, 186)],
  2198     'spectral6': [(213, 62, 79), (252, 141, 89), (254, 224, 139), (230, 245, 152), (153, 213, 148), (50, 136, 189)],
  2199     'spectral7': [(213, 62, 79), (252, 141, 89), (254, 224, 139), (255, 255, 191), (230, 245, 152), (153, 213, 148), (50, 136, 189)],
  2200     'spectral8': [(213, 62, 79), (244, 109, 67), (253, 174, 97), (254, 224, 139), (230, 245, 152), (171, 221, 164), (102, 194, 165), (50, 136, 189)],
  2201     'spectral9': [(213, 62, 79), (244, 109, 67), (253, 174, 97), (254, 224, 139), (255, 255, 191), (230, 245, 152), (171, 221, 164), (102, 194, 165), (50, 136, 189)],
  2202     'ylgn3': [(247, 252, 185), (173, 221, 142), (49, 163, 84)],
  2203     'ylgn4': [(255, 255, 204), (194, 230, 153), (120, 198, 121), (35, 132, 67)],
  2204     'ylgn5': [(255, 255, 204), (194, 230, 153), (120, 198, 121), (49, 163, 84), (0, 104, 55)],
  2205     'ylgn6': [(255, 255, 204), (217, 240, 163), (173, 221, 142), (120, 198, 121), (49, 163, 84), (0, 104, 55)],
  2206     'ylgn7': [(255, 255, 204), (217, 240, 163), (173, 221, 142), (120, 198, 121), (65, 171, 93), (35, 132, 67), (0, 90, 50)],
  2207     'ylgn8': [(255, 255, 229), (247, 252, 185), (217, 240, 163), (173, 221, 142), (120, 198, 121), (65, 171, 93), (35, 132, 67), (0, 90, 50)],
  2208     'ylgn9': [(255, 255, 229), (247, 252, 185), (217, 240, 163), (173, 221, 142), (120, 198, 121), (65, 171, 93), (35, 132, 67), (0, 104, 55), (0, 69, 41)],
  2209     'ylgnbu3': [(237, 248, 177), (127, 205, 187), (44, 127, 184)],
  2210     'ylgnbu4': [(255, 255, 204), (161, 218, 180), (65, 182, 196), (34, 94, 168)],
  2211     'ylgnbu5': [(255, 255, 204), (161, 218, 180), (65, 182, 196), (44, 127, 184), (37, 52, 148)],
  2212     'ylgnbu6': [(255, 255, 204), (199, 233, 180), (127, 205, 187), (65, 182, 196), (44, 127, 184), (37, 52, 148)],
  2213     'ylgnbu7': [(255, 255, 204), (199, 233, 180), (127, 205, 187), (65, 182, 196), (29, 145, 192), (34, 94, 168), (12, 44, 132)],
  2214     'ylgnbu8': [(255, 255, 217), (237, 248, 177), (199, 233, 180), (127, 205, 187), (65, 182, 196), (29, 145, 192), (34, 94, 168), (12, 44, 132)],
  2215     'ylgnbu9': [(255, 255, 217), (237, 248, 177), (199, 233, 180), (127, 205, 187), (65, 182, 196), (29, 145, 192), (34, 94, 168), (37, 52, 148), (8, 29, 88)],
  2216     'ylorbr3': [(255, 247, 188), (254, 196, 79), (217, 95, 14)],
  2217     'ylorbr4': [(255, 255, 212), (254, 217, 142), (254, 153, 41), (204, 76, 2)],
  2218     'ylorbr5': [(255, 255, 212), (254, 217, 142), (254, 153, 41), (217, 95, 14), (153, 52, 4)],
  2219     'ylorbr6': [(255, 255, 212), (254, 227, 145), (254, 196, 79), (254, 153, 41), (217, 95, 14), (153, 52, 4)],
  2220     'ylorbr7': [(255, 255, 212), (254, 227, 145), (254, 196, 79), (254, 153, 41), (236, 112, 20), (204, 76, 2), (140, 45, 4)],
  2221     'ylorbr8': [(255, 255, 229), (255, 247, 188), (254, 227, 145), (254, 196, 79), (254, 153, 41), (236, 112, 20), (204, 76, 2), (140, 45, 4)],
  2222     'ylorbr9': [(255, 255, 229), (255, 247, 188), (254, 227, 145), (254, 196, 79), (254, 153, 41), (236, 112, 20), (204, 76, 2), (153, 52, 4), (102, 37, 6)],
  2223     'ylorrd3': [(255, 237, 160), (254, 178, 76), (240, 59, 32)],
  2224     'ylorrd4': [(255, 255, 178), (254, 204, 92), (253, 141, 60), (227, 26, 28)],
  2225     'ylorrd5': [(255, 255, 178), (254, 204, 92), (253, 141, 60), (240, 59, 32), (189, 0, 38)],
  2226     'ylorrd6': [(255, 255, 178), (254, 217, 118), (254, 178, 76), (253, 141, 60), (240, 59, 32), (189, 0, 38)],
  2227     'ylorrd7': [(255, 255, 178), (254, 217, 118), (254, 178, 76), (253, 141, 60), (252, 78, 42), (227, 26, 28), (177, 0, 38)],
  2228     'ylorrd8': [(255, 255, 204), (255, 237, 160), (254, 217, 118), (254, 178, 76), (253, 141, 60), (252, 78, 42), (227, 26, 28), (177, 0, 38)],
  2232 if __name__ == 
'__main__':
 
def __init__(self, pen, points, filled=False)
def set_dotcode(self, dotcode, filename='< stdin >', center=True)
def filter(self, type, text)
def __init__(self, pen, x0, y0, w, h, filled=False)
def __init__(self, type, text, line, col)
def select_pen(self, highlight)
def __init__(self, pen, x, y, j, w, t)
def draw(self, painter, highlight=False)
def drag(self, deltax, deltay)
def mouseReleaseEvent(self, event)
def set_filter(self, filter)
def __init__(self, x, y, w, h, shapes, url)
def add_recent_file(self, filename)
def __init__(self, shapes)
def set_current_pos(self, x, y)
def create_action(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()")
def handle_linewidth(self, linewidth)
def draw(self, cr, highlight=False)
def handle_graph(self, attrs)
def draw(self, painter, highlight=False)
def handle_edge(self, src_id, dst_id, attrs)
def __init__(self, parser, buf)
def handle_linestyle(self, style)
def __init__(self, item, x, y, highlight=None, url=None)
def update_file(self, filename)
def __init__(self, buf=None, pos=0, filename=None, fp=None)
def draw(self, painter, highlight=False)
def handle_bezier(self, points, filled=False)
def draw(self, cr, highlight_items=None)
def keyPressEvent(self, event)
def handle_ellipse(self, x0, y0, w, h, filled=False)
def wheelEvent(self, event)
def __init__(self, item, url, highlight=None)
def draw(self, cr, highlight=False)
def handle_edge(self, src_id, dst_id, attrs)
def __init__(self, dot_widget, target_x, target_y)
def on_motion_notify(self, event)
def draw(self, painter, highlight=False)
def zoom_image(self, zoom_ratio, center=False, pos=None)
def on_motion_notify(self, event)
def parse_node_pos(self, pos)
def handle_text(self, x, y, j, w, t)
def set_filter(self, filter)
def handle_line(self, points)
def drag(self, deltax, deltay)
def handle_node(self, id, attrs)
def __init__(self, pen, points)
def __init__(self, dot_widget, target_x, target_y)
def add_actions(self, target, actions)
def parse_edge_pos(self, pos)
def __init__(self, dot_widget)
def closeEvent(self, event)
def is_click(self, event, click_fuzz=4, click_timeout=1.0)
def __init__(self, shapes)
def transform(self, x, y)
def mousePressEvent(self, event)
def __init__(self, parent=None)
def lookup_color(self, c)
def animate_to(self, x, y)
def zoom_to_area(self, x1, y1, x2, y2)
def drag(self, deltax, deltay)
def __init__(self, xdotcode)
def square_distance(x1, y1, x2, y2)
def handle_node(self, id, attrs)
def set_xdotcode(self, xdotcode, center=True)
def on_button_press(self, event)
def on_area_scroll_event(self, area, event)
def get_current_pos(self)
def __init__(self, msg=None, filename=None, line=None, col=None)
def paintEvent(self, event=None)
def on_area_size_allocate(self, area, allocation)
def handle_font(self, size, name)
def __init__(self, width=1, height=1, shapes=(), nodes=(), edges=(), subgraph_shapes={})
def window_to_graph(self, x, y)
def is_inside(self, x, y)
def __init__(self, dot_widget)
def __init__(self, lexer)
def handle_polygon(self, points, filled=False)
def mouseMoveEvent(self, event)
def register_select_callback(self, cb)
User callbacks. 
def transform(self, x, y)
def handle_graph(self, attrs)
def __init__(self, src, dst, points, shapes, url)
def get_drag_action(self, event)
def on_button_release(self, event)
def set_highlight(self, items)
def set_xdotcode(self, xdotcode, filename='< stdin >')
def handle_color(self, color, filled=False)
def draw(self, painter, highlight=False)
def drag(self, deltax, deltay)
def __init__(self, lexer)
def __init__(self, pen, points, filled=False)
def update_file_menu(self)
def open_file(self, filename=None)
def set_dotcode(self, dotcode, filename='< stdin >')