def __draw_link(self, vlink: VLink): """Draw a link.""" if vlink.name == 'ground' or (not vlink.points): return points = self.__points_pos(vlink) pen = QPen() # Rearrange: Put the nearest point to the next position. qpoints = convex_hull(points, as_qpoint=True) if (self.select_mode == SelectMode.Link and self.vlinks.index(vlink) in self.selections): pen.setWidth(self.link_width + 6) pen.setColor(Qt.black if self.monochrome else QColor(161, 16, 239)) self.painter.setPen(pen) self.painter.drawPolygon(*qpoints) pen.setWidth(self.link_width) pen.setColor(Qt.black if self.monochrome else QColor(*vlink.color)) self.painter.setPen(pen) brush = QColor(Qt.darkGray) if self.monochrome else QColor( 226, 219, 190) brush.setAlphaF(self.transparency) self.painter.setBrush(brush) self.painter.drawPolygon(*qpoints) self.painter.setBrush(Qt.NoBrush) if not self.show_point_mark: return pen.setColor(Qt.darkGray) self.painter.setPen(pen) p_count = len(points) cen_x = sum(p[0] for p in points) / p_count cen_y = sum(p[1] for p in points) / p_count self.painter.drawText(QRectF(cen_x - 50, cen_y - 50, 100, 100), Qt.AlignCenter, f'[{vlink.name}]')
def solutionPolygon( self, func: str, args: Sequence[str], target: str, pos: Union[Tuple[VPoint, ...], Dict[int, Tuple[float, float]]] ) -> Tuple[List[QPointF], QColor]: """Get solution polygon.""" if func == 'PLLP': color = QColor(121, 171, 252) params = [args[0], args[-1]] elif func == 'PLAP': color = QColor(249, 84, 216) params = [args[0]] else: if func == 'PLPP': color = QColor(94, 255, 185) else: # PXY color = QColor(249, 175, 27) params = [args[0]] params.append(target) tmp_list = [] for name in params: try: index = int(name.replace('P', '')) except ValueError: continue else: x, y = pos[index] tmp_list.append(QPointF(x, -y) * self.zoom) return tmp_list, color
def __draw_point(self, i: int, vpoint: VPoint): """Draw a point.""" if vpoint.type in {VJoint.P, VJoint.RP}: pen = QPen(QColor(*vpoint.color)) pen.setWidth(2) # Draw slot point and pin point. for j, (cx, cy) in enumerate(vpoint.c): if not vpoint.links: grounded = False else: grounded = vpoint.links[j] == 'ground' # Slot point. if j == 0 or vpoint.type == VJoint.P: pen.setColor(Qt.black if self.monochrome else QColor( *vpoint.color)) self.painter.setPen(pen) cp = QPointF(cx, -cy) * self.zoom jr = self.joint_size * (2 if j == 0 else 1) rp = QPointF(jr, -jr) self.painter.drawRect(QRectF(cp + rp, cp - rp)) if self.show_point_mark: pen.setColor(Qt.darkGray) self.painter.setPen(pen) text = f"[Point{i}]" if self.show_dimension: text += f":({cx:.02f}, {cy:.02f})" self.painter.drawText(cp + rp, text) else: self.draw_point(i, cx, cy, grounded, vpoint.color) # Slider line pen.setColor(QColor(*vpoint.color).darker()) self.painter.setPen(pen) qline_m = QLineF( QPointF(vpoint.c[1][0], -vpoint.c[1][1]) * self.zoom, QPointF(vpoint.c[0][0], -vpoint.c[0][1]) * self.zoom) nv = qline_m.normalVector() nv.setLength(self.joint_size) nv.setPoints(nv.p2(), nv.p1()) qline_1 = nv.normalVector() qline_1.setLength(qline_m.length()) self.painter.drawLine(qline_1) nv.setLength(nv.length() * 2) nv.setPoints(nv.p2(), nv.p1()) qline_2 = nv.normalVector() qline_2.setLength(qline_m.length()) qline_2.setAngle(qline_2.angle() + 180) self.painter.drawLine(qline_2) else: self.draw_point(i, vpoint.cx, vpoint.cy, vpoint.grounded(), vpoint.color) # For selects function. if self.select_mode == SelectMode.Joint and (i in self.selections): pen = QPen(QColor(161, 16, 239)) pen.setWidth(3) self.painter.setPen(pen) self.painter.drawRect(vpoint.cx * self.zoom - 12, vpoint.cy * -self.zoom - 12, 24, 24)
def drawSolution(self, func: str, args: Tuple[str], target: str): """Draw the solution triangle.""" params = [args[0], args[-1]] params.append(target) if func == 'PLLP': color = QColor(121, 171, 252) else: color = QColor(249, 84, 216) color.setAlpha(255) pen = QPen() pen.setColor(color) pen.setWidth(self.r) self.painter.setPen(pen) for n in (0, 1): x, y = self.pos[int(params[-1].replace('P', ''))] x2, y2 = self.pos[int(params[n].replace('P', ''))] self.drawArrow( x*self.zoom, y*-self.zoom, x2*self.zoom, y2*-self.zoom ) color.setAlpha(30) self.painter.setBrush(QBrush(color)) qpoints = [] for name in params: x, y = self.pos[int(name.replace('P', ''))] qpoints.append(QPointF(x*self.zoom, y*-self.zoom)) self.painter.drawPolygon(*qpoints)
def __init__(self, parent): super(NCEditor, self).__init__(parent) # Set the default font. if system() == "Windows": font_name = "Courier New" else: font_name = "Mono" self.font = QFont(font_name) self.font.setFixedPitch(True) self.font.setPointSize(14) self.setFont(self.font) self.setMarginsFont(self.font) self.setUtf8(True) self.setEolMode(QsciScintilla.EolUnix) # Margin 0 is used for line numbers. font_metrics = QFontMetrics(self.font) self.setMarginsFont(self.font) self.setMarginWidth(0, font_metrics.width("0000") + 4) self.setMarginLineNumbers(0, True) self.setMarginsBackgroundColor(QColor("#cccccc")) # Current line visible with special background color. self.setCaretLineVisible(True) self.setCaretLineBackgroundColor(QColor("#ffe4e4")) # Don't want to see the horizontal scrollbar at all. self.setWrapMode(QsciScintilla.WrapWord) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # Keyword indicator [1] self.indicatorDefine(QsciScintilla.BoxIndicator, 1) self.cursorPositionChanged.connect(self.__catch_word)
def __drawLink(self, vlink: VLink): """Draw a link.""" points = [] for i in vlink.points: vpoint = self.Points[i] if vpoint.type == 1 or vpoint.type == 2: coordinate = vpoint.c[0 if (vlink.name == vpoint.links[0]) else 1] x = coordinate[0] * self.zoom y = coordinate[1] * -self.zoom else: x = vpoint.cx * self.zoom y = vpoint.cy * -self.zoom points.append((x, y)) pen = QPen(vlink.color) pen.setWidth(self.linkWidth) self.painter.setPen(pen) brush = QColor(226, 219, 190) brush.setAlphaF(self.transparency) self.painter.setBrush(brush) #Rearrange: Put the nearest point to the next position. qpoints = convex_hull(points) if qpoints: self.painter.drawPolygon(*qpoints) self.painter.setBrush(Qt.NoBrush) if ((not self.showPointMark) or (vlink.name == 'ground') or (not qpoints)): return pen.setColor(Qt.darkGray) self.painter.setPen(pen) cenX = sum(p[0] for p in points) / len(points) cenY = sum(p[1] for p in points) / len(points) self.painter.drawText(QPointF(cenX, cenY), '[{}]'.format(vlink.name))
def on_save_atlas_clicked(self): """Save function as same as type synthesis widget.""" count = self.collection_list.count() if not count: return lateral, ok = QInputDialog.getInt(self, "Atlas", "The number of lateral:", 5, 1, 10) if not ok: return fileName = self.outputTo("Atlas image", Qt_images) if not fileName: return icon_size = self.collection_list.iconSize() width = icon_size.width() image_main = QImage( QSize(lateral * width if count > lateral else count * width, ((count // lateral) + bool(count % lateral)) * width), self.collection_list.item(0).icon().pixmap( icon_size).toImage().format()) image_main.fill(QColor(Qt.white).rgb()) painter = QPainter(image_main) for row in range(count): image = self.collection_list.item(row).icon().pixmap( icon_size).toImage() painter.drawImage( QPointF(row % lateral * width, row // lateral * width), image) painter.end() pixmap = QPixmap() pixmap.convertFromImage(image_main) pixmap.save(fileName, format=QFileInfo(fileName).suffix()) self.saveReplyBox("Atlas", fileName)
def __drawSlvsRanges(self): """Draw solving range.""" pen = QPen() self.painter.setFont(QFont("Arial", self.fontSize + 5)) pen.setWidth(5) for i, (tag, rect) in enumerate(self.ranges.items()): range_color = QColor(colorNum(i + 1)) range_color.setAlpha(30) self.painter.setBrush(range_color) range_color.setAlpha(255) pen.setColor(range_color) self.painter.setPen(pen) cx = rect.x() * self.zoom cy = rect.y() * -self.zoom if rect.width(): self.painter.drawRect( QRectF(cx, cy, rect.width() * self.zoom, rect.height() * self.zoom)) else: self.painter.drawEllipse(QPointF(cx, cy), 3, 3) range_color.setAlpha(255) pen.setColor(range_color) self.painter.setPen(pen) self.painter.drawText(QPointF(cx + 6, cy - 6), tag) self.painter.setBrush(Qt.NoBrush)
def __draw_link(self, name: str, points: List[int]): """Draw link function. The link color will be the default color. """ color = color_qt('Blue') pen = QPen(color) pen.setWidth(self.link_width) self.painter.setPen(pen) brush = QColor(226, 219, 190) brush.setAlphaF(0.70) self.painter.setBrush(brush) qpoints = tuple( QPointF(self.pos[i][0], -self.pos[i][1]) * self.zoom for i in points if self.pos[i] and (not isnan(self.pos[i][0])) ) if len(qpoints) == len(points): self.painter.drawPolygon(*qpoints) self.painter.setBrush(Qt.NoBrush) if self.show_point_mark and (name != 'ground') and qpoints: pen.setColor(Qt.darkGray) self.painter.setPen(pen) self.painter.setFont(QFont('Arial', self.font_size)) text = f"[{name}]" cen_x = sum(self.pos[i][0] for i in points if self.pos[i]) cen_y = sum(self.pos[i][1] for i in points if self.pos[i]) self.painter.drawText(QPointF(cen_x, -cen_y) * self.zoom / len(points), text)
def draw_point(self, i: int, cx, cy, fix: bool, color: Tuple[int, int, int]): """Draw a joint.""" pen = QPen(Qt.black if self.monochrome else QColor(*color)) pen.setWidth(2) self.painter.setPen(pen) x = cx * self.zoom y = cy * -self.zoom if fix: bottom = y + 20 width = 10 # Draw a triangle below. self.painter.drawPolygon(QPointF(x, y), QPointF(x - width, bottom), QPointF(x + width, bottom)) r = self.joint_size * 2 else: r = self.joint_size self.painter.drawEllipse(QPointF(x, y), r, r) if not self.show_point_mark: return pen.setColor(Qt.darkGray) pen.setWidth(2) self.painter.setPen(pen) text = f"[{i}]" if type(i) is str else f"[Point{i}]" if self.show_dimension: text += f":({cx:.02f}, {cy:.02f})" self.painter.drawText(QPointF(x, y) + QPointF(6, -6), text)
def drawLink(self, name: str, points: Tuple[int]): """Draw linkage function. The link color will be the default color. """ color = colorQt('Blue') pen = QPen(color) pen.setWidth(self.linkWidth) self.painter.setPen(pen) brush = QColor(226, 219, 190) brush.setAlphaF(0.70) self.painter.setBrush(brush) qpoints = tuple( QPointF(self.Point[i][0] * self.zoom, self.Point[i][1] * -self.zoom) for i in points if self.Point[i] and not isnan(self.Point[i][0])) if len(qpoints) == len(points): self.painter.drawPolygon(*qpoints) self.painter.setBrush(Qt.NoBrush) if self.showPointMark and name != 'ground' and qpoints: pen.setColor(Qt.darkGray) self.painter.setPen(pen) self.painter.setFont(QFont('Arial', self.fontSize)) text = "[{}]".format(name) cenX = sum(self.Point[i][0] for i in points if self.Point[i]) cenY = sum(self.Point[i][1] for i in points if self.Point[i]) cenX *= self.zoom / len(points) cenY *= -self.zoom / len(points) self.painter.drawText(QPointF(cenX, cenY), text)
def Topologic_result_context_menu(self, point): """Context menu for the type synthesis results.""" index = self.Topologic_result.currentIndex().row() self.add_collection.setEnabled(index>-1) self.copy_edges.setEnabled(index>-1) self.copy_image.setEnabled(index>-1) action = self.popMenu_topo.exec_(self.Topologic_result.mapToGlobal(point)) if not action: return clipboard = QApplication.clipboard() if action==self.add_collection: self.addCollection(self.answer[index].edges) elif action==self.copy_edges: clipboard.setText(str(self.answer[index].edges)) elif action==self.copy_image: #Turn the transparent background to white. image1 = self.atlas_image() image2 = QImage(image1.size(), image1.format()) image2.fill(QColor(Qt.white).rgb()) painter = QPainter(image2) painter.drawImage(QPointF(0, 0), image1) painter.end() pixmap = QPixmap() pixmap.convertFromImage(image2) clipboard.setPixmap(pixmap)
def __draw_path(self): """Draw paths. Recording first.""" paths = self.path_record or self.path.path or self.path_preview if len(self.vpoints) != len(paths): return if paths is self.path_preview: o_path = chain(enumerate(self.path_preview), self.slider_path_preview.items()) else: o_path = enumerate(paths) pen = QPen() for i, path in o_path: if self.path.show != i and self.path.show != -1: continue if self.monochrome: color = Qt.gray elif self.vpoints[i].color is None: color = color_qt('Green') else: color = QColor(*self.vpoints[i].color) pen.setColor(color) pen.setWidth(self.path_width) self.painter.setPen(pen) if self.path.curve: self.draw_curve(path) else: self.draw_dot(path)
def paintEvent(self, event): """Drawing functions.""" width = self.width() height = self.height() if ((self.width_old is not None) and ((self.width_old != width) or (self.height_old != height))): self.ox += (width - self.width_old) / 2 self.oy += (height - self.height_old) / 2 super(DynamicCanvas, self).paintEvent(event) self.painter.setFont(QFont('Arial', self.fontSize)) if self.freemove != FreeMode.NoFreeMove: #Draw a colored frame for free move mode. pen = QPen() if self.freemove == FreeMode.Translate: pen.setColor(QColor(161, 105, 229)) elif self.freemove == FreeMode.Rotate: pen.setColor(QColor(219, 162, 6)) elif self.freemove == FreeMode.Reflect: pen.setColor(QColor(79, 249, 193)) pen.setWidth(8) self.painter.setPen(pen) self.__drawFrame() #Draw links except ground. for vlink in self.Links[1:]: self.__drawLink(vlink) #Draw path. if self.Path.show != -2: self.__drawPath() #Draw solving path. if self.showTargetPath: self.__drawSlvsRanges() self._BaseCanvas__drawTargetPath() #Draw points. for i, vpoint in enumerate(self.Points): self.__drawPoint(i, vpoint) #Rectangular selection if self.Selector.RectangularSelection: pen = QPen(Qt.gray) pen.setWidth(1) self.painter.setPen(pen) self.painter.drawRect( QRectF(QPointF(self.Selector.x, self.Selector.y), QPointF(self.Selector.sx, self.Selector.sy))) self.painter.end() #Record the widget size. self.width_old = width self.height_old = height
def __drawPoint(self, i: int, vpoint: VPoint): """Draw a point.""" if vpoint.type == 1 or vpoint.type == 2: #Draw slider silder_points = vpoint.c for j, (cx, cy) in enumerate(silder_points): if vpoint.type == 1: if j == 0: self._BaseCanvas__drawPoint( i, cx, cy, vpoint.links[j] == 'ground', vpoint.color) else: pen = QPen(vpoint.color) pen.setWidth(2) self.painter.setPen(pen) r = 5 self.painter.drawRect( QRectF( QPointF(cx * self.zoom + r, cy * -self.zoom + r), QPointF(cx * self.zoom - r, cy * -self.zoom - r))) elif vpoint.type == 2: if j == 0: self._BaseCanvas__drawPoint( i, cx, cy, vpoint.links[j] == 'ground', vpoint.color) else: #Turn off point mark. showPointMark = self.showPointMark self.showPointMark = False self._BaseCanvas__drawPoint( i, cx, cy, vpoint.links[j] == 'ground', vpoint.color) self.showPointMark = showPointMark pen = QPen(vpoint.color.darker()) pen.setWidth(2) self.painter.setPen(pen) x_all = tuple(cx for cx, cy in silder_points) if x_all: p_left = silder_points[x_all.index(min(x_all))] p_right = silder_points[x_all.index(max(x_all))] if p_left == p_right: y_all = tuple(cy for cx, cy in silder_points) p_left = silder_points[y_all.index(min(y_all))] p_right = silder_points[y_all.index(max(y_all))] self.painter.drawLine( QPointF(p_left[0] * self.zoom, p_left[1] * -self.zoom), QPointF(p_right[0] * self.zoom, p_right[1] * -self.zoom)) else: self._BaseCanvas__drawPoint(i, vpoint.cx, vpoint.cy, vpoint.grounded(), vpoint.color) #For selects function. if i in self.pointsSelection: pen = QPen(QColor(161, 16, 239)) pen.setWidth(3) self.painter.setPen(pen) self.painter.drawRect(vpoint.cx * self.zoom - 12, vpoint.cy * -self.zoom - 12, 24, 24)
def paintEvent(self, event): """Drawing functions.""" width = self.width() height = self.height() if self.width_old != width or self.height_old != height: self.ox += (width - self.width_old) / 2 self.oy += (height - self.height_old) / 2 super(DynamicCanvas, self).paintEvent(event) self.painter.setFont(QFont('Arial', self.fontSize)) if self.freemove: #Draw a colored frame for free move mode. pen = QPen() if self.freemove == 1: pen.setColor(QColor(161, 105, 229)) elif self.freemove == 2: pen.setColor(QColor(219, 162, 6)) elif self.freemove == 3: pen.setColor(QColor(79, 249, 193)) pen.setWidth(8) self.painter.setPen(pen) self.drawFrame() if self.Selector.RectangularSelection: pen = QPen(Qt.gray) pen.setWidth(1) self.painter.setPen(pen) self.painter.drawRect( QRectF(QPointF(self.Selector.x, self.Selector.y), QPointF(self.Selector.sx, self.Selector.sy))) #Draw links. for vlink in self.Link[1:]: self.drawLink(vlink) #Draw path. if self.Path.show > -2: self.drawPath() #Draw solving path. if self.showTargetPath: self.drawSlvsRanges() self.drawTargetPath() #Draw points. for i, vpoint in enumerate(self.Point): self.drawPoint(i, vpoint) self.painter.end() self.width_old = width self.height_old = height
def __drawSolution(self, func: str, args: Tuple[str], target: str, pos: TypeVar('Coords', Tuple[VPoint], Dict[int, Tuple[float, float]])): """Draw the solution triangle.""" if func == 'PLLP': color = QColor(121, 171, 252) params = [args[0], args[-1]] elif func == 'PLAP': color = QColor(249, 84, 216) params = [args[0]] elif func == 'PLPP': color = QColor(94, 255, 185) params = [args[0]] params.append(target) pen = QPen() pen.setColor(color) pen.setWidth(RADIUS) self.painter.setPen(pen) def drawArrow(n: int) -> bool: """Draw arrow and return True if done.""" try: x, y = pos[int(params[-1].replace('P', ''))] x2, y2 = pos[int(params[n].replace('P', ''))] except ValueError: return False else: self.__drawArrow(x * self.zoom, y * -self.zoom, x2 * self.zoom, y2 * -self.zoom) return True if not drawArrow(0): return if func == 'PLLP': if not drawArrow(1): return color.setAlpha(30) self.painter.setBrush(QBrush(color)) qpoints = [] for name in params: x, y = pos[int(name.replace('P', ''))] qpoints.append(QPointF(x * self.zoom, y * -self.zoom)) self.painter.drawPolygon(*qpoints) self.painter.setBrush(Qt.NoBrush)
def graph(G: Graph, width: int, engine: [str, Dict[int, Tuple[float, float]]], node_mode: bool = False, except_node: int = None) -> QIcon: """Draw a linkage graph.""" try: pos = engine_picker(G, engine, node_mode) except EngineError as e: raise e width_ = -inf for x, y in pos.values(): if abs(x) > width_: width_ = x if abs(y) > width_: width_ = y width_ *= 2 * 1.2 image = QImage(QSize(width_, width_), QImage.Format_ARGB32_Premultiplied) image.fill(Qt.transparent) painter = QPainter(image) painter.translate(image.width() / 2, image.height() / 2) pen = QPen() r = width_ / 50 pen.setWidth(r) painter.setPen(pen) if node_mode: for l1, l2 in G.edges: painter.drawLine(QPointF(pos[l1][0], -pos[l1][1]), QPointF(pos[l2][0], -pos[l2][1])) else: painter.setBrush(QBrush(QColor(226, 219, 190, 150))) for link in G.nodes: if link == except_node: continue #Distance sorted function from canvas painter.drawPolygon(*convex_hull([(pos[n][0], -pos[n][1]) for n, edge in edges_view(G) if link in edge])) for k, (x, y) in pos.items(): if node_mode: color = colorNum(len(list(G.neighbors(k))) - 1) else: if except_node in tuple(G.edges)[k]: color = colorQt('Green') else: color = colorQt('Blue') pen.setColor(color) painter.setPen(pen) painter.setBrush(QBrush(color)) painter.drawEllipse(QPointF(x, -y), r, r) painter.end() icon = QIcon(QPixmap.fromImage(image).scaledToWidth(width)) return icon
def __save_atlas(self): """Saving all the atlas to image file. We should turn transparent background to white first. Then using QImage class to merge into one image. """ file_name = "" lateral = 0 if self.save_edges_auto.isChecked(): lateral, ok = QInputDialog.getInt(self, "Atlas", "The number of lateral:", 5, 1, 10) if not ok: return file_name = self.outputTo("Atlas image", qt_image_format) if file_name: reply = QMessageBox.question( self, "Type synthesis", "Do you want to Re-synthesis?", (QMessageBox.Yes | QMessageBox.YesToAll | QMessageBox.Cancel), QMessageBox.Yes) if reply == QMessageBox.Yes: self.__structure_synthesis() elif reply == QMessageBox.YesToAll: self.__structure_synthesis_all() count = self.structure_list.count() if not count: return if not lateral: lateral, ok = QInputDialog.getInt(self, "Atlas", "The number of lateral:", 5, 1, 10) if not ok: return if not file_name: file_name = self.outputTo("Atlas image", qt_image_format) if not file_name: return width = self.structure_list.iconSize().width() image_main = QImage( QSize(lateral * width if count > lateral else count * width, ((count // lateral) + bool(count % lateral)) * width), self.__atlas_image(0).format()) image_main.fill(QColor(Qt.white).rgb()) painter = QPainter(image_main) for row in range(count): image = self.__atlas_image(row) painter.drawImage( QPointF(row % lateral * width, row // lateral * width), image) painter.end() pixmap = QPixmap() pixmap.convertFromImage(image_main) pixmap.save(file_name, format=QFileInfo(file_name).suffix()) self.saveReplyBox("Atlas", file_name)
def __init__(self, parent=None): super(KeywordSyntax, self).__init__(parent) keyword = QTextCharFormat() keyword.setForeground(QBrush(Qt.darkBlue, Qt.SolidPattern)) keyword.setFontWeight(QFont.Bold) number = QTextCharFormat() number.setForeground(QBrush(QColor(0, 127, 127), Qt.SolidPattern)) annotation = QTextCharFormat() annotation.setForeground(QBrush(QColor(61, 158, 77), Qt.SolidPattern)) decorator = QTextCharFormat() decorator.setForeground(QBrush(QColor(158, 140, 61), Qt.SolidPattern)) function = QTextCharFormat() function.setFontWeight(QFont.Bold) function.setForeground(QBrush(QColor(10, 147, 111), Qt.SolidPattern)) string = QTextCharFormat() string.setForeground(QBrush(QColor(127, 0, 127), Qt.SolidPattern)) boolean = QTextCharFormat() boolean.setForeground(QBrush(QColor(64, 112, 144), Qt.SolidPattern)) self.highlightingRules = [ HighlightRule(QRegExp(r'\b[+-]?[0-9]+[lL]?\b'), number), HighlightRule(QRegExp(r'\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b'), number), HighlightRule( QRegExp(r'\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b'), number), HighlightRule(QRegExp(r'\bdef\b\s*(\w+)'), function), HighlightRule(QRegExp(r'\bclass\b\s*(\w+)'), function) ] self.highlightingRules += [ HighlightRule(QRegExp("\\b" + key + "\\b"), keyword) for key in [ 'print', 'pass', 'def', 'class', 'from', 'is', 'as', 'import', 'for', 'in', 'if', 'else', 'elif', 'raise' ] ] self.highlightingRules += [ HighlightRule(QRegExp("\\b" + key + "\\b"), boolean) for key in ['self', 'True', 'False'] ] self.highlightingRules += [ HighlightRule(QRegExp("'''"), string), HighlightRule(QRegExp('"""'), string), HighlightRule(QRegExp(r'"[^"\\]*(\\.[^"\\]*)*"'), string), HighlightRule(QRegExp(r"'[^'\\]*(\\.[^'\\]*)*'"), string), HighlightRule(QRegExp(r'@[^(\n|\()]*'), decorator), HighlightRule(QRegExp(r'#[^\n]*'), annotation) ]
def draw_slvs_ranges(self): """Draw solving range.""" pen = QPen() pen.setWidth(5) for i, (tag, rect) in enumerate(self.ranges.items()): range_color = QColor(color_num(i + 1)) range_color.setAlpha(30) self.painter.setBrush(range_color) range_color.setAlpha(255) pen.setColor(range_color) self.painter.setPen(pen) cx = rect.x() * self.zoom cy = rect.y() * -self.zoom if rect.width(): self.painter.drawRect( QRectF(QPointF(cx, cy), QSizeF(rect.width(), rect.height()) * self.zoom)) else: self.painter.drawEllipse(QPointF(cx, cy), 3, 3) range_color.setAlpha(255) pen.setColor(range_color) self.painter.setPen(pen) self.painter.drawText(QPointF(cx, cy) + QPointF(6, -6), tag) self.painter.setBrush(Qt.NoBrush)
return QColor(*color_rgb(name)) def color_num(color_index: int) -> QColor: """Get color by index.""" return color_qt(colorNames[color_index % len(colorNames)]) def color_icon(name: str, size: int = 20) -> QIcon: """Get color block as QIcon by name.""" color_block = QPixmap(QSize(size, size)) color_block.fill(color_qt(name)) return QIcon(color_block) # Target path color: (road, dot, brush) _path_color = ( # Blue - Green (QColor(69, 247, 232), QColor(3, 163, 120), QColor(74, 178, 176, 30)), # Yellow - Green (QColor(187, 221, 75), QColor(103, 124, 12), QColor(242, 242, 4, 30)), # Red - Yellow (QColor(252, 110, 27), QColor(237, 129, 66), QColor(242, 158, 109, 30)), # Purple - Blue (QColor(115, 0, 145), QColor(220, 104, 249), QColor(198, 137, 214, 30))) def target_path_style(color_index: int) -> QColor: """Get path colors.""" return _path_color[color_index % len(_path_color)]
def __set_chart(self, tab_name: str, pos_x: int, pos_y: int): """Setting charts by data index. pos_x / pos_y: [0], [1], [2] time_fitness: List[List[Tuple[gen, fitness, time]]] """ axis_x = QCategoryAxis() axis_y = QValueAxis() axis_x.setLabelsPosition(QCategoryAxis.AxisLabelsPositionOnValue) axis_x.setMin(0) axis_y.setTickCount(11) if self.__algorithm_data: # Just copy references from algorithm data. plot = [data['time_fitness'] for data in self.__algorithm_data] # X max. max_x = int(max([max([tnf[pos_x] for tnf in data]) for data in plot]) * 100) axis_x.setMax(max_x) i10 = int(max_x / 10) if i10: for i in range(0, max_x + 1, i10): axis_x.append(str(i / 100), i) else: for i in range(0, 1000, 100): axis_x.append(str(i / 100), i) # Y max. max_y = max(max([tnf[pos_y] for tnf in data]) for data in plot) + 10 else: plot = None # Y max. max_y = 100 max_y -= max_y % 10 axis_y.setRange(0., max_y) chart = DataChart(self.__title, axis_x, axis_y) # Append data set. for i, data in enumerate(self.__algorithm_data): line = QLineSeries() scatter = QScatterSeries() line.setName(f"{i}: {data['Algorithm']}") scatter.setMarkerSize(7) scatter.setColor(QColor(110, 190, 30)) for e in plot[self.__algorithm_data.index(data)]: y = e[pos_y] x = e[pos_x] * 100 line.append(QPointF(x, y)) scatter.append(QPointF(x, y)) for series in (line, scatter): chart.addSeries(series) series.attachAxis(axis_x) series.attachAxis(axis_y) chart.legend().markers(scatter)[0].setVisible(False) # Add chart into tab widget widget = QWidget() self.tabWidget.addTab(widget, QIcon(), tab_name) layout = QVBoxLayout(widget) layout.setContentsMargins(2, 2, 2, 2) chart_view = QChartView(chart) chart_view.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) layout.addWidget(chart_view)
def __init__(self, parent: QWidget): """UI settings.""" super(TextEditor, self).__init__(parent) # Set the default font. if system() == "Linux": font_name = "DejaVu Sans Mono" elif system() == "Windows": font_name = "Courier New" elif system() == "Darwin": font_name = "Andale Mono" else: font_name = "Courier New" self.font = QFont(font_name) self.font.setFixedPitch(True) self.font.setPointSize(14) self.setFont(self.font) self.setMarginsFont(self.font) self.setUtf8(True) self.setEolMode(QsciScintilla.EolUnix) # Margin 0 is used for line numbers. font_metrics = QFontMetrics(self.font) self.setMarginsFont(self.font) self.setMarginWidth(0, font_metrics.width("0000") + 4) self.setMarginLineNumbers(0, True) self.setMarginsBackgroundColor(QColor("#cccccc")) # Brace matching. self.setBraceMatching(QsciScintilla.SloppyBraceMatch) # Current line visible with special background color. self.setCaretLineVisible(True) self.setCaretLineBackgroundColor(QColor("#ffe4e4")) # Set lexer. self.lexer_option = "Markdown" self.set_highlighter("Markdown") self.SendScintilla(QsciScintilla.SCI_STYLESETFONT, 1, font_name.encode('utf-8')) # Don't want to see the horizontal scrollbar at all. self.setWrapMode(QsciScintilla.WrapWord) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # Auto completion. self.setAutoCompletionCaseSensitivity(True) self.setAutoCompletionSource(QsciScintilla.AcsDocument) self.setAutoCompletionThreshold(2) # Edge mode. self.setEdgeMode(QsciScintilla.EdgeNone) self.setEdgeColumn(80) self.setEdgeColor(Qt.blue) # Indentations. self.setAutoIndent(True) self.setIndentationsUseTabs(False) self.setTabWidth(4) self.setTabIndents(True) self.setBackspaceUnindents(True) self.setIndentationGuides(True) # Widget size. self.setMinimumSize(400, 450) # Remove trailing blanks. self.__no_trailing_blanks = True # Spell checker indicator [0] self.indicatorDefine(QsciScintilla.SquiggleIndicator, 0) # Keyword indicator [1] self.indicatorDefine(QsciScintilla.BoxIndicator, 1) self.cursorPositionChanged.connect(self.__catch_word) self.word = "" # Undo redo self.__set_command(QsciCommand.Redo, Qt.ControlModifier | Qt.ShiftModifier | Qt.Key_Z)
def setChart(self, tabName: str, posX: int, posY: int): '''Setting charts by data index. posX / posY: [0] / [1] / [2] TimeAndFitness: List[List[Tuple[gen, fitness, time]]] ''' if self.mechanism_data: if type(self.mechanism_data[0]['TimeAndFitness'][0]) == float: TimeAndFitness = [[ (data['lastGen'] * i / len(data['TimeAndFitness']), Tnf, 0) for i, Tnf in enumerate(data['TimeAndFitness']) ] for data in self.mechanism_data] else: #Just copy from mechanism_data TimeAndFitness = [[Tnf for Tnf in data['TimeAndFitness']] for data in self.mechanism_data] axisX = QCategoryAxis() axisY = QValueAxis() axisX.setLabelsPosition(QCategoryAxis.AxisLabelsPositionOnValue) axisX.setMin(0) axisY.setTickCount(11) #X maxima if self.mechanism_data: maximaX = int( max([ max([Tnf[posX] for Tnf in data]) for data in TimeAndFitness ]) * 100) axisX.setMax(maximaX) i10 = int(maximaX / 10) if i10: for i in range(0, maximaX + 1, i10): axisX.append(str(i / 100), i) else: for i in range(0, 1000, 100): axisX.append(str(i / 100), i) #Y maxima if self.mechanism_data: maximaY = max( [max([Tnf[posY] for Tnf in data]) for data in TimeAndFitness]) + 10 else: maximaY = 100 maximaY -= maximaY % 10 axisY.setRange(0., maximaY) chart = DataChart(self.Title, axisX, axisY) #Append datasets for data in self.mechanism_data: line = QLineSeries() scatter = QScatterSeries() gen = data['lastGen'] Tnf = TimeAndFitness[self.mechanism_data.index(data)] points = Tnf[:-1] if Tnf[-1] == Tnf[-2] else Tnf line.setName("{}({} gen): {}".format(data['Algorithm'], gen, data['Expression'])) scatter.setMarkerSize(7) scatter.setColor(QColor(110, 190, 30)) for i, e in enumerate(points): y = e[posY] x = e[posX] * 100 line.append(QPointF(x, y)) scatter.append(QPointF(x, y)) for series in [line, scatter]: chart.addSeries(series) series.attachAxis(axisX) series.attachAxis(axisY) chart.legend().markers(scatter)[0].setVisible(False) #Add chart into tab widget widget = QWidget() self.tabWidget.addTab(widget, QIcon(), tabName) layout = QVBoxLayout(widget) layout.setContentsMargins(2, 2, 2, 2) chartView = QChartView(chart) chartView.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) layout.addWidget(chartView)
__author__ = "Yuan Chang" __copyright__ = "Copyright (C) 2016-2018" __license__ = "AGPL" __email__ = "*****@*****.**" from core.QtModules import ( QColor, Qt, QIcon, QPixmap, QSize, ) """Color dictionary.""" color_list = { 'Red': QColor(172, 68, 68), 'Green': QColor(110, 190, 30), 'Blue': QColor(68, 120, 172), 'Cyan': Qt.cyan, 'Magenta': Qt.magenta, 'Brick-Red': QColor(255, 130, 130), 'Yellow': Qt.yellow, 'Gray': Qt.gray, 'Orange': QColor(225, 165, 0), 'Pink': QColor(225, 192, 230), 'Black': Qt.black, 'White': Qt.white, 'Dark-Red': Qt.darkRed, 'Dark-Green': Qt.darkGreen, 'Dark-Blue': Qt.darkBlue, 'Dark-Cyan': Qt.darkCyan,
def paintEvent(self, event): """Draw the structure.""" width = self.width() height = self.height() if self.pos: x_right, x_left, y_top, y_bottom = self.__zoom_to_fit_limit() x_diff = x_left - x_right y_diff = y_top - y_bottom x_diff = x_diff if x_diff else 1 y_diff = y_diff if y_diff else 1 if width / x_diff < height / y_diff: factor = width / x_diff else: factor = height / y_diff self.zoom = factor * 0.75 self.ox = width / 2 - (x_left + x_right) / 2 * self.zoom self.oy = height / 2 + (y_top + y_bottom) / 2 * self.zoom else: if width <= height: self.zoom = width / PreviewCanvas.view_size else: self.zoom = height / PreviewCanvas.view_size self.ox = width / 2 self.oy = height / 2 super(PreviewCanvas, self).paintEvent(event) pen = QPen() pen.setWidth(self.joint_size) self.painter.setPen(pen) if self.monochrome: color = QColor(Qt.darkGray) else: color = QColor(226, 219, 190) color.setAlpha(150) self.painter.setBrush(QBrush(color)) # Links for link in self.G.nodes: if link == self.grounded: continue points = [] # Points that is belong with the link. for num, edge in edges_view(self.G): if link in edge: if num in self.same: num = self.same[num] x, y = self.pos[num] points.append((x * self.zoom, y * -self.zoom)) # Customize points. for name, link_ in self.cus.items(): if link == link_: x, y = self.pos[name] points.append((x * self.zoom, y * -self.zoom)) self.painter.drawPolygon(*convex_hull(points, as_qpoint=True)) # Nodes for node, (x, y) in self.pos.items(): if node in self.same: continue x *= self.zoom y *= -self.zoom if self.monochrome: color = Qt.black elif node in self.driver: color = color_qt('Red') elif node in self.target: color = color_qt('Orange') elif self.get_status(node): color = color_qt('Green') else: color = color_qt('Blue') pen.setColor(color) self.painter.setPen(pen) self.painter.setBrush(QBrush(color)) self.painter.drawEllipse(QPointF(x, y), self.joint_size, self.joint_size) pen.setColor(Qt.black) self.painter.setPen(pen) # Text of node. pen.setColor(Qt.black) self.painter.setPen(pen) for node, (x, y) in self.pos.items(): if node in self.same: continue x *= self.zoom x += 2 * self.joint_size y *= -self.zoom y -= 2 * self.joint_size self.painter.drawText(QPointF(x, y), f'P{node}') self.painter.end()
def paintEvent(self, event): """Draw the structure.""" width = self.width() height = self.height() if self.pos: x_right, x_left, y_top, y_bottom = self.__zoom_to_fit_limit() x_diff = x_left - x_right y_diff = y_top - y_bottom x_diff = x_diff if x_diff else 1 y_diff = y_diff if y_diff else 1 if width / x_diff < height / y_diff: factor = width / x_diff else: factor = height / y_diff self.zoom = factor * 0.95 self.ox = width / 2 - (x_left + x_right) / 2 * self.zoom self.oy = height / 2 + (y_top + y_bottom) / 2 * self.zoom else: sq_w = 240 self.zoom = (width / sq_w) if (width <= height) else (height / sq_w) self.ox = width / 2 self.oy = height / 2 super(PreviewCanvas, self).paintEvent(event) pen = QPen() pen.setWidth(self.joint_size) self.painter.setPen(pen) self.painter.setBrush(QBrush(QColor(226, 219, 190, 150))) # Links for link in self.G.nodes: if link == self.grounded: continue points = [] # Points that is belong with the link. for num, edge in edges_view(self.G): if link in edge: if num in self.same: num = self.same[num] x, y = self.pos[num] points.append((x * self.zoom, y * -self.zoom)) # Customize points. for name, link_ in self.cus.items(): if link == link_: x, y = self.pos[int(name.replace('P', ''))] points.append((x * self.zoom, y * -self.zoom)) self.painter.drawPolygon(*convex_hull(points, as_qpoint=True)) # Nodes for node, (x, y) in self.pos.items(): if node in self.same: continue x *= self.zoom y *= -self.zoom if node in (self.Driver, self.Target): if node == self.Driver: pen.setColor(color_qt('Red')) elif node == self.Target: pen.setColor(color_qt('Yellow')) self.painter.setPen(pen) self.painter.drawEllipse(QPointF(x, y), self.joint_size, self.joint_size) if self.getStatus(node): color = color_qt('Dark-Magenta') else: color = color_qt('Green') pen.setColor(color) self.painter.setPen(pen) self.painter.setBrush(QBrush(color)) self.painter.drawEllipse(QPointF(x, y), self.joint_size, self.joint_size) pen.setColor(color_qt('Black')) self.painter.setPen(pen) # Solutions if self.showSolutions: solutions = self.get_solutions() if solutions: for expr in solutions.split(';'): self.drawSolution( io.str_before(expr, '['), io.str_between(expr, '[', ']').split(','), io.str_between(expr, '(', ')'), self.pos ) # Text of node. pen.setColor(Qt.black) self.painter.setPen(pen) for node, (x, y) in self.pos.items(): if node in self.same: continue x *= self.zoom x += 2 * self.joint_size y *= -self.zoom y -= 2 * self.joint_size self.painter.drawText(QPointF(x, y), f'P{node}') self.painter.end()
def to_graph(graph: Graph, width: int, engine: Union[str, Dict[int, Tuple[float, float]]], node_mode: bool = False, except_node: int = None) -> QIcon: """Draw a generalized chain graph.""" pos: Pos = engine_picker(graph, engine, node_mode) width_bound = -float('inf') for x, y in pos.values(): if abs(x) > width_bound: width_bound = x if abs(y) > width_bound: width_bound = y width_bound *= 2.2 image = QImage(QSize(int(width_bound), int(width_bound)), QImage.Format_ARGB32_Premultiplied) image.fill(Qt.transparent) painter = QPainter(image) painter.translate(image.width() / 2, image.height() / 2) pen = QPen() r = width_bound / 50 pen.setWidth(int(r)) painter.setPen(pen) # Draw edges. if node_mode: for l1, l2 in graph.edges: if except_node in {l1, l2}: pen.setColor(color_qt('Gray')) else: pen.setColor(color_qt('Black')) painter.setPen(pen) painter.drawLine(QPointF(pos[l1][0], -pos[l1][1]), QPointF(pos[l2][0], -pos[l2][1])) else: painter.setBrush(QBrush(QColor(226, 219, 190, 150))) for link in graph.nodes: if link == except_node: pen.setColor(color_qt('Gray')) else: pen.setColor(color_qt('Black')) painter.setPen(pen) painter.drawPolygon(*convex_hull([(pos[n][0], -pos[n][1]) for n, edge in edges_view(graph) if link in edge], as_qpoint=True)) # Draw nodes. for k, (x, y) in pos.items(): if node_mode: color = color_num(len(list(graph.neighbors(k))) - 1) if k == except_node: color.setAlpha(150) else: if except_node in dict(edges_view(graph))[k]: color = color_qt('Green') else: color = color_qt('Blue') pen.setColor(color) painter.setPen(pen) painter.setBrush(QBrush(color)) painter.drawEllipse(QPointF(x, -y), r, r) painter.end() icon = QIcon(QPixmap.fromImage(image).scaledToWidth(width)) return icon
def color_qt(name: str) -> QColor: """Get color and translate to QColor.""" return QColor(*color_rgb(name))