class Mouse(object): """""" def __init__(self, view): self.view = view self.pos = QPoint() self.last_pos = QPoint() def dx(self): return self.pos.x() - self.last_pos.x() def dy(self): return self.pos.y() - self.last_pos.y()
def _draw_nodes(self, painter, topleft_point, bottomright_point): # draw nodes for block in self.blocks: # optimization: don't paint blocks that are outside of the current range block_topleft_point = QPoint(block.x, block.y) block_bottomright_point = QPoint(block.x + block.width, block.y + block.height) if block_topleft_point.x() > bottomright_point.x( ) or block_topleft_point.y() > bottomright_point.y(): continue elif block_bottomright_point.x() < topleft_point.x( ) or block_bottomright_point.y() < topleft_point.y(): continue block.paint(painter)
def mousePressEvent(self, event): mouse = QPoint(event.pos()) if event.buttons() & QtCore.Qt.LeftButton: # Click on hues? if self._hue_rect.contains(mouse.x(), mouse.y()): y = mouse.y() c = QtGui.QColor.fromHsvF(float(y) / self.height(), self._saturation, self._value) self.color = c # Click on colors? elif self._shades_rect.contains(mouse.x(), mouse.y()): # calculate saturation and value x = mouse.x() y = mouse.y() c = QtGui.QColor.fromHsvF(self._hue, 1 - float(y) / self._shades_rect.height(), float(x) / self._shades_rect.width()) self.color = c
def _draw_nodes(self, painter, topleft_point, bottomright_point): # draw nodes for block in self.blocks: # safety check if block.x is None or block.y is None: l.warning("Failed to assign coordinates to block %s.", block) continue # optimization: don't paint blocks that are outside of the current range block_topleft_point = QPoint(block.x, block.y) block_bottomright_point = QPoint(block.x + block.width, block.y + block.height) if block_topleft_point.x() > bottomright_point.x() or block_topleft_point.y() > bottomright_point.y(): continue elif block_bottomright_point.x() < topleft_point.x() or block_bottomright_point.y() < topleft_point.y(): continue block.paint(painter)
def mousePressEvent(self, event): mouse = QPoint(event.pos()) if event.buttons() & QtCore.Qt.LeftButton: # Click on hues? if self._hue_rect.contains(mouse.x(), mouse.y()): y = mouse.y() c = QtGui.QColor.fromHsvF( float(y) / self.height(), self._saturation, self._value) self.color = c # Click on colors? elif self._shades_rect.contains(mouse.x(), mouse.y()): # calculate saturation and value x = mouse.x() y = mouse.y() c = QtGui.QColor.fromHsvF( self._hue, 1 - float(y) / self._shades_rect.height(), float(x) / self._shades_rect.width()) self.color = c
def mousePressEvent(self, mouse_event): if mouse_event.button() == Qt.RightButton: if self._spec_index is None: print("spec_index is None") print(self) print(self._running_providers) return pos = mouse_event.pos() items = [ item for item in self.items(pos) if isinstance(item, NodeItem) and item._label.text() ] if len(items) != 1: print("wrong number of things", [x._label.text() for x in items]) return name = items[0]._label.text().rstrip('(default)').strip() if name not in self._spec_index.provider_names: print(name, "Not in list of providers") return provider = self._spec_index.providers[name] def start_trigger(): # TODO: replace 'capability_server' with user provided server name service_name = '/{0}/start_capability'.format( 'capability_server') rospy.wait_for_service(service_name) start_capability = rospy.ServiceProxy(service_name, StartCapability) start_capability(provider.implements, name) def stop_trigger(): # TODO: replace 'capability_server' with user provided server name service_name = '/{0}/stop_capability'.format( 'capability_server') rospy.wait_for_service(service_name) stop_capability = rospy.ServiceProxy(service_name, StopCapability) stop_capability(provider.implements) if name not in self._running_providers: trigger = start_trigger msg = "start => " else: trigger = stop_trigger msg = "stop => " menu = QMenu() action = menu.addAction(msg + name) action.triggered.connect(trigger) pos = mouse_event.globalPos() pos = QPoint(pos.x(), pos.y()) menu.exec_(pos) else: InteractiveGraphicsView.mousePressEvent(self, mouse_event)
def drawPoints(self, qp): ''' draw points for electrode positions and their connection lines to the plots ''' qp.setPen(Qt.white) qp.setBrush(Qt.white) for key, item in self.plots.iteritems(): pos = item.pos() pos = QPoint(pos.x()+item.size().width(), pos.y()+item.size().height()) qp.drawLine(pos, self.points[int(key)-1]) qp.drawEllipse(pos, 4,4) for pp in self.points: qp.drawEllipse(pp, 4,4)
def draw(self, painter, offset=Point()): cropped_image, x, y, width, height = self.__getCrop() origin_offset = QPoint(self.origin.x + offset.x, self.origin.y + offset.y) if self.rotated: old_transform = QTransform(painter.transform()) painter.setTransform(painter.transform().translate(origin_offset.x() + self.crop.size.height, origin_offset.y()).rotate(90, Qt.ZAxis)) painter.drawImage(0, 0, cropped_image) painter.setTransform(old_transform) else: painter.drawImage(origin_offset, cropped_image)
def show_instruction(self, insn_addr): block = self._insn_addr_to_block.get(insn_addr, None) if block is not None: pos = QPoint(*block.instruction_position(insn_addr)) pos_ = self._from_graph_pos(pos) # is it visible? if 0 <= pos_.x() < self.width() and 0 <= pos_.y() < self.height(): return # make it visible x, y = pos.x(), pos.y() self.horizontalScrollBar().setValue(x - 50) self.verticalScrollBar().setValue(y - 50)
def mousePressEvent(self, mouse_event): if mouse_event.button() == Qt.RightButton: if self._spec_index is None: print("spec_index is None") print(self) print(self._running_providers) return pos = mouse_event.pos() items = [item for item in self.items(pos) if isinstance(item, NodeItem) and item._label.text()] if len(items) != 1: print("wrong number of things", [x._label.text() for x in items]) return name = items[0]._label.text().rstrip('(default)').strip() if name not in self._spec_index.provider_names: print(name, "Not in list of providers") return provider = self._spec_index.providers[name] def start_trigger(): # TODO: replace 'capability_server' with user provided server name service_name = '/{0}/start_capability'.format('capability_server') rospy.wait_for_service(service_name) start_capability = rospy.ServiceProxy(service_name, StartCapability) start_capability(provider.implements, name) def stop_trigger(): # TODO: replace 'capability_server' with user provided server name service_name = '/{0}/stop_capability'.format('capability_server') rospy.wait_for_service(service_name) stop_capability = rospy.ServiceProxy(service_name, StopCapability) stop_capability(provider.implements) if name not in self._running_providers: trigger = start_trigger msg = "start => " else: trigger = stop_trigger msg = "stop => " menu = QMenu() action = menu.addAction(msg + name) action.triggered.connect(trigger) pos = mouse_event.globalPos() pos = QPoint(pos.x(), pos.y()) menu.exec_(pos) else: InteractiveGraphicsView.mousePressEvent(self, mouse_event)
class GLWidget(QGLWidget): def __init__(self, parent=None): super(GLWidget, self).__init__(parent) self.xRot = 0 self.yRot = 0 self.lastPos = QPoint() def minimumSizeHint(self): return QSize(50, 50) def sizeHint(self): return QSize(400, 400) def setXRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.xRot: self.xRot = angle self.updateGL() def setYRotation(self, angle): angle = self.normalizeAngle(angle) if angle != self.yRot: self.yRot = angle self.updateGL() def initializeGL(self): # gl one-time init code pass def paintGL(self): # do ALL the rendering (clear etc) pass def resizeGL(self, width, height): side = min(width, height) if side < 0: return GL.glViewport((width - side) // 2, (height - side) // 2, side, side) # TODO make the changed perspective known to libdicraft-render def mousePressEvent(self, event): self.lastPos = event.pos() def mouseMoveEvent(self, event): dx = event.x() - self.lastPos.x() dy = event.y() - self.lastPos.y() if event.buttons() & Qt.LeftButton: self.setXRotation(self.xRot + 8 * dy) self.setYRotation(self.yRot + 8 * dx) self.lastPos = event.pos() def normalizeAngle(self, angle): while angle < 0: angle += 360 * 16 while angle > 360 * 16: angle -= 360 * 16 return angle
class Circle(Figure): def __init__(self, *args, **kwargs): self.first_point = FirstPoint() self.second_point = SecondPoint() self.control = Control() Figure.__init__(self, self.first_point) self.center = QPoint() self.ctrl = QPoint() if 'center' in kwargs: self.center = kwargs['center'] if 'ctrl' in kwargs: self.ctrl = kwargs['ctrl'] if 'figure' in kwargs: self.center = QPoint(kwargs['figure']['center']['x'], kwargs['figure']['center']['y']) self.ctrl = QPoint(kwargs['figure']['ctrl']['x'], kwargs['figure']['ctrl']['y']) self.state = self.control if len(args) == 2: self.center = args[0] self.ctrl = args[1] if len(args) == 4: self.center = QPoint(args[0], args[1]) self.ctrl = QPoint(args[2], args[3]) def draw(self, painter, scale): painter.save() if not self.center.isNull() and not self.ctrl.isNull(): radius = distance(self.center, self.ctrl) painter.setPen(QPen(QBrush(QColor(232, 109, 21) if self.state is not self.control else QColor(21, 144, 232)), self.lineWidth(scale), Qt.SolidLine)) painter.setBrush(QBrush(QColor(21, 144, 232, 150))) painter.drawEllipse(self.center, radius, radius) self.drawControlPoint(painter, self.center, QColor(31, 174, 222), scale) self.drawControlPoint(painter, self.ctrl, QColor(222, 79, 31), scale) Figure.draw(self, painter, scale) painter.restore() def getDict(self): return { 'circle': { 'center': { 'x': self.center.x(), 'y': self.center.y(), }, 'ctrl': { 'x': self.ctrl.x(), 'y': self.ctrl.y(), } } } def __str__(self): return self.__repr__() def __repr__(self): return 'Circle(({x}, {y}), {radius})'.format(x=self.center.x(), y=self.center.y(), radius=distance(self.center, self.ctrl))
def __decompose(self, poly): lower_poly = [] upper_poly = [] upper_int = QPoint(0, 0) lower_int = QPoint(0, 0) upper_index = 0 lower_index = 0 closest_index = 0 p = QPoint(0, 0) for pi in poly: if is_reflex(poly, pi): pim1 = poly[-1 if pi is poly[0] else poly.index(pi) - 1] pip1 = poly[0 if pi is poly[-1] else poly.index(pi) + 1] self.reflex_vertices.append(pi) upper_dist = sys.maxint lower_dist = sys.maxint for pj in poly: pjm1 = poly[-1 if pj is poly[0] else poly.index(pj) - 1] pjp1 = poly[0 if pj is poly[-1] else poly.index(pj) + 1] if left(pim1, pi, pj) and right_on(pim1, pi, pjm1): p = intersection(pim1, pi, pj, pjm1) if right(pip1, pi, p): d = sqdist(pi, p) if d < lower_dist: lower_dist = d lower_int = p lower_index = poly.index(pj) if left(pip1, pi, pjp1) and right_on(pip1, pi, pj): p = intersection(pip1, pi, pj, pjp1) if left(pim1, pi, p): d = sqdist(pi, p) if d < upper_dist: upper_dist = d upper_int = p upper_index = poly.index(pj) i = poly.index(pi) if lower_index == ((upper_index + 1) % len(poly)): p.setX((lower_int.x() + upper_int.x()) / 2) p.setY((lower_int.y() + upper_int.y()) / 2) self.steiner_points.append(p) if i < upper_index: lower_poly += poly[i:upper_index + 1] lower_poly.append(p) upper_poly.append(p) if lower_index != 0: upper_poly += poly[lower_index:] upper_poly += poly[:i + 1] else: if i != 0: lower_poly += poly[i:] lower_poly += poly[:upper_index + 1] lower_poly.append(p) upper_poly.append(p) upper_poly += poly[lower_index:i + 1] else: if lower_index > upper_index: upper_index += len(poly) closest_dist = sys.float_info.max for j in xrange(lower_index, upper_index + 1): pj = poly[j % len(poly)] if left_on(pim1, pi, pj) and right_on(pip1, pi, pj): d = sqdist(pi, pj) if d < closest_dist: closest_dist = d closest_index = j % len(poly) if i < closest_index: lower_poly += poly[i:closest_index + 1] if closest_index != 0: upper_poly += poly[closest_index:] upper_poly += poly[:i + 1] else: if i != 0: lower_poly += poly[i:] lower_poly += poly[:closest_index + 1] upper_poly += poly[closest_index:i + 1] if len(lower_poly) < len(upper_poly): self.decompose(lower_poly) self.decompose(upper_poly) else: self.decompose(upper_poly) self.decompose(lower_poly) return self.polys.append(poly)
def __decompose(self, poly): lower_poly = [] upper_poly = [] upper_int = QPoint(0, 0) lower_int = QPoint(0, 0) upper_index = 0 lower_index = 0 closest_index = 0 p = QPoint(0, 0) for pi in poly: if is_reflex(poly, pi): pim1 = poly[-1 if pi is poly[0] else poly.index(pi) - 1] pip1 = poly[0 if pi is poly[-1] else poly.index(pi) + 1] self.reflex_vertices.append(pi) upper_dist = sys.maxint lower_dist = sys.maxint for pj in poly: pjm1 = poly[-1 if pj is poly[0] else poly.index(pj) - 1] pjp1 = poly[0 if pj is poly[-1] else poly.index(pj) + 1] if left(pim1, pi, pj) and right_on(pim1, pi, pjm1): p = intersection(pim1, pi, pj, pjm1) if right(pip1, pi, p): d = sqdist(pi, p) if d < lower_dist: lower_dist = d lower_int = p lower_index = poly.index(pj) if left(pip1, pi, pjp1) and right_on(pip1, pi, pj): p = intersection(pip1, pi, pj, pjp1) if left(pim1, pi, p): d = sqdist(pi, p) if d < upper_dist: upper_dist = d upper_int = p upper_index = poly.index(pj) i = poly.index(pi) if lower_index == ((upper_index + 1) % len(poly)): p.setX((lower_int.x() + upper_int.x()) / 2) p.setY((lower_int.y() + upper_int.y()) / 2) self.steiner_points.append(p) if i < upper_index: lower_poly += poly[i : upper_index + 1] lower_poly.append(p) upper_poly.append(p) if lower_index != 0: upper_poly += poly[lower_index:] upper_poly += poly[: i + 1] else: if i != 0: lower_poly += poly[i:] lower_poly += poly[: upper_index + 1] lower_poly.append(p) upper_poly.append(p) upper_poly += poly[lower_index : i + 1] else: if lower_index > upper_index: upper_index += len(poly) closest_dist = sys.float_info.max for j in xrange(lower_index, upper_index + 1): pj = poly[j % len(poly)] if left_on(pim1, pi, pj) and right_on(pip1, pi, pj): d = sqdist(pi, pj) if d < closest_dist: closest_dist = d closest_index = j % len(poly) if i < closest_index: lower_poly += poly[i : closest_index + 1] if closest_index != 0: upper_poly += poly[closest_index:] upper_poly += poly[: i + 1] else: if i != 0: lower_poly += poly[i:] lower_poly += poly[: closest_index + 1] upper_poly += poly[closest_index : i + 1] if len(lower_poly) < len(upper_poly): self.decompose(lower_poly) self.decompose(upper_poly) else: self.decompose(upper_poly) self.decompose(lower_poly) return self.polys.append(poly)
class Circle(Figure): def __init__(self, *args, **kwargs): self.first_point = FirstPoint() self.second_point = SecondPoint() self.control = Control() Figure.__init__(self, self.first_point) self.center = QPoint() self.ctrl = QPoint() if 'center' in kwargs: self.center = kwargs['center'] if 'ctrl' in kwargs: self.ctrl = kwargs['ctrl'] if 'figure' in kwargs: self.center = QPoint(kwargs['figure']['center']['x'], kwargs['figure']['center']['y']) self.ctrl = QPoint(kwargs['figure']['ctrl']['x'], kwargs['figure']['ctrl']['y']) self.state = self.control if len(args) == 2: self.center = args[0] self.ctrl = args[1] if len(args) == 4: self.center = QPoint(args[0], args[1]) self.ctrl = QPoint(args[2], args[3]) def draw(self, painter, scale): painter.save() if not self.center.isNull() and not self.ctrl.isNull(): radius = distance(self.center, self.ctrl) painter.setPen( QPen( QBrush( QColor(232, 109, 21) if self.state is not self. control else QColor(21, 144, 232)), self.lineWidth(scale), Qt.SolidLine)) painter.setBrush(QBrush(QColor(21, 144, 232, 150))) painter.drawEllipse(self.center, radius, radius) self.drawControlPoint(painter, self.center, QColor(31, 174, 222), scale) self.drawControlPoint(painter, self.ctrl, QColor(222, 79, 31), scale) Figure.draw(self, painter, scale) painter.restore() def getDict(self): return { 'circle': { 'center': { 'x': self.center.x(), 'y': self.center.y(), }, 'ctrl': { 'x': self.ctrl.x(), 'y': self.ctrl.y(), } } } def __str__(self): return self.__repr__() def __repr__(self): return 'Circle(({x}, {y}), {radius})'.format(x=self.center.x(), y=self.center.y(), radius=distance( self.center, self.ctrl))
class AntMotion(): def __init__(self): self.point = QPoint(0, 0) self.step_value = 2 # pixels self.last_step_direction = None self.last_step_value = None self.key_up = Qt.Key_W self.key_down = Qt.Key_S self.key_left = Qt.Key_A self.key_right = Qt.Key_D def _move(self, doStep, coordinate, direction, *args): if len(args) == 1: step_value = args[0] else: step_value = self.step_value if direction == 'up' or direction == 'left': doStep(coordinate - step_value) else: doStep(coordinate + step_value) self.last_step_direction = direction self.last_step_value = step_value def up(self, *args): self._move(self.point.setY, self.point.y(), 'up', *args) def down(self, *args): self._move(self.point.setY, self.point.y(), 'down', *args) def left(self, *args): self._move(self.point.setX, self.point.x(), 'left', *args) def right(self, *args): self._move(self.point.setX, self.point.x(), 'right', *args) def reinitLastStepDirection(self): self.last_step_direction = None def cancelLastStep(self): if 'up' == self.last_step_direction: self.down(self.last_step_value) elif 'down' == self.last_step_direction: self.up(self.last_step_value) elif 'left' == self.last_step_direction: self.right(self.last_step_value) elif 'right' == self.last_step_direction: self.left(self.last_step_value) self.reinitLastStepDirection() def setStep(self, newStep): self.step = newStep def setKeyUp(self, key): self.key_up = key def setKeyDown(self, key): self.key_down = key def setKeyLeft(self, key): self.key_left = key def setKeyRight(self, key): self.key_right = key
class Decision(VerticalSymbol): ''' SDL DECISION Symbol ''' _unique_followers = ['Comment'] _insertable_followers = ['DecisionAnswer', 'Task', 'ProcedureCall', 'Output', 'Decision', 'Label'] _terminal_followers = ['Join', 'State', 'ProcedureStop'] common_name = 'decision' # Define reserved keywords for the syntax highlighter blackbold = SDL_BLACKBOLD + ['\\b{}\\b'.format(word) for word in ('AND', 'OR')] redbold = SDL_REDBOLD completion_list = {'length', 'present'} def __init__(self, parent=None, ast=None): ast = ast or ogAST.Decision() # Define the point where all branches of the decision can join again self.connectionPoint = QPoint(ast.width / 2, ast.height + 30) super(Decision, self).__init__(parent, text=ast.inputString, x=ast.pos_x, y=ast.pos_y, hyperlink=ast.hyperlink) self.set_shape(ast.width, ast.height) self.setBrush(QColor(255, 255, 202)) self.minDistanceToSymbolAbove = 0 self.parser = ogParser self.text_alignment = Qt.AlignHCenter if ast.comment: Comment(parent=self, ast=ast.comment) @property def terminal_symbol(self): ''' Compute dynamically if the item is terminal by checking if all its branches end with a terminator ''' for branch in self.branches(): if not branch.last_branch_item.terminal_symbol: return False return True def branches(self): ''' Return the list of decision answers (as a generator) ''' return (branch for branch in self.childSymbols() if isinstance(branch, DecisionAnswer)) def check_syntax(self): ''' Redefined function, to check only the symbol, not recursively ''' _, syntax_errors, _, _, _ = self.parser.parseSingleElement( self.common_name, self.PR(recursive=False)) try: # LOG.error('\n'.join(syntax_errors)) self.scene().raise_syntax_errors(syntax_errors) except AttributeError: LOG.debug('raise_syntax_error raised an exception') def set_shape(self, width, height): ''' Define polygon points to draw the symbol ''' path = QPainterPath() path.moveTo(width / 2, 0) path.lineTo(width, height / 2) path.lineTo(width / 2, height) path.lineTo(0, height / 2) path.lineTo(width / 2, 0) self.setPath(path) super(Decision, self).set_shape(width, height) def resize_item(self, rect): ''' On resize event, make sure connection points are updated ''' delta_y = self.boundingRect().height() - rect.height() super(Decision, self).resize_item(rect) self.connectionPoint.setX(self.boundingRect().center().x()) self.connectionPoint.setY(self.connectionPoint.y() - delta_y) self.update_connections() def update_connections(self): ''' Redefined - update arrows shape below connection point ''' super(Decision, self).update_connections() for branch in self.branches(): for cnx in branch.last_branch_item.connections(): cnx.reshape() def updateConnectionPointPosition(self): ''' Compute the joining point of decision branches ''' new_y = 0 new_x = self.boundingRect().width() / 2.0 answers = False for branch in self.branches(): answers = True last_cnx = None last = branch.last_branch_item try: # To compute the branch length, we must keep only the symbols, # so we must remove the last connection (if any) last_cnx, = (c for c in last.childItems() if isinstance(c, Connection) and not isinstance(c.child, (Comment, HorizontalSymbol))) # Don't set parent item to None to avoid Qt segfault last_cnx.setParentItem(self) except ValueError: pass branch_len = branch.y() + ( branch.boundingRect() | branch.childrenBoundingRect()).height() try: last_cnx.setParentItem(last) except AttributeError: pass # If last item was a decision, use its connection point # position to get the length of the branch: try: branch_len = (last.connectionPoint.y() + self.mapFromScene(0, last.scenePos().y()).y()) except AttributeError: pass # Rounded with int() -> mandatory when view scale has changed new_y = int(max(new_y, branch_len)) if not answers: new_y = int(self.boundingRect().height()) new_y += 15 delta = new_y - self.connectionPoint.y() self.connectionPoint.setY(new_y) self.connectionPoint.setX(new_x) if delta != 0: child = self.next_aligned_symbol() try: child.moveBy(0, delta) except AttributeError: pass self.update_connections() def PR(self, recursive=True): ''' Get PR notation of a decision (possibly recursively) ''' comment = self.comment.PR() if self.comment else u';' pos = self.scenePos() result = [u'/* CIF DECISION ({x}, {y}), ({w}, {h}) */\n' '{hlink}' 'DECISION {d}{comment}'.format( hlink=self.text.PR(), d=unicode(self), x=int(pos.x()), y=int(pos.y()), w=int(self.boundingRect().width()), h=int(self.boundingRect().height()), comment=comment)] if recursive: for answer in self.branches(): if unicode(answer).lower().strip() == 'else': result.append(answer.PR()) else: result.insert(1, answer.PR()) result.append('ENDDECISION;') return u'\n'.join(result)
class Rectangle(Figure): def __init__(self, *args, **kwargs): self.first_point = FirstPoint() self.second_point = SecondPoint() self.control = Control() self.p1 = QPoint() self.p2 = QPoint() Figure.__init__(self, self.first_point) if 'x1' in kwargs and 'y1' in kwargs: self.p1 = QPoint(kwargs['x1'], kwargs['y1']) if 'x2' in kwargs and 'y2' in kwargs: self.p2 = QPoint(kwargs['x2'], kwargs['y2']) if 'p1' in kwargs: self.p1 = kwargs['p1'] if 'p2' in kwargs: self.p2 = kwargs['p2'] if len(args) == 2: self.p1 = args[0] self.p2 = args[1] if len(args) == 4: self.p1 = QPoint(args[0], args[1]) self.p2 = QPoint(args[2], args[3]) if 'figure' in kwargs: self.p1 = QPoint(kwargs['figure']['x1'], kwargs['figure']['y1']) self.p2 = QPoint(kwargs['figure']['x2'], kwargs['figure']['y2']) self.state = self.control def draw(self, painter, scale): painter.save() if not self.p1.isNull() and not self.p2.isNull(): painter.setPen(QPen(QBrush(QColor(232, 109, 21) if self.state is not self.control else QColor(21, 144, 232)), self.lineWidth(scale), Qt.SolidLine)) painter.setBrush(QBrush(QColor(21, 144, 232, 150))) painter.drawRect(QRect(self.p1, self.p2)) self.drawControlPoint(painter, self.p1, QColor(31, 174, 222), scale) self.drawControlPoint(painter, self.p2, QColor(222, 79, 31), scale) Figure.draw(self, painter, scale) painter.restore() def getDict(self): return { 'rect': { 'x1': self.p1.x(), 'y1': self.p1.y(), 'x2': self.p2.x(), 'y2': self.p2.y() } } def __str__(self): return self.__repr__() def __repr__(self): return 'Rectangle(({x1}, {y1}), ({x2}, {y2}))'.format(x1=self.p1.x(), y1=self.p1.y(), x2=self.p2.x(), y2=self.p2.y())
class Decision(VerticalSymbol): ''' SDL DECISION Symbol ''' _unique_followers = ['Comment'] _insertable_followers = ['DecisionAnswer', 'Task', 'ProcedureCall', 'Output', 'Decision', 'Label'] _terminal_followers = ['Join', 'State', 'ProcedureStop'] common_name = 'decision' # Define reserved keywords for the syntax highlighter blackbold = SDL_BLACKBOLD + ['\\b{}\\b'.format(word) for word in ('AND', 'OR')] redbold = SDL_REDBOLD def __init__(self, parent=None, ast=None): ast = ast or ogAST.Decision() self.ast = ast # Define the point where all branches of the decision can join again self.connectionPoint = QPoint(ast.width / 2, ast.height + 30) super(Decision, self).__init__(parent, text=ast.inputString, x=ast.pos_x or 0, y=ast.pos_y or 0, hyperlink=ast.hyperlink) self.set_shape(ast.width, ast.height) self.setBrush(QColor(255, 255, 202)) self.minDistanceToSymbolAbove = 0 self.parser = ogParser self.text_alignment = Qt.AlignHCenter if ast.comment: Comment(parent=self, ast=ast.comment) @property def terminal_symbol(self): ''' Compute dynamically if the item is terminal by checking if all its branches end with a terminator ''' for branch in self.branches(): if not branch.last_branch_item.terminal_symbol: return False return True @property def completion_list(self): ''' Set auto-completion list ''' return chain(variables_autocompletion(self), ('length', 'present')) def branches(self): ''' Return the list of decision answers (as a generator) ''' return (branch for branch in self.childSymbols() if isinstance(branch, DecisionAnswer)) def set_shape(self, width, height): ''' Define polygon points to draw the symbol ''' path = QPainterPath() path.moveTo(width / 2, 0) path.lineTo(width, height / 2) path.lineTo(width / 2, height) path.lineTo(0, height / 2) path.lineTo(width / 2, 0) self.setPath(path) super(Decision, self).set_shape(width, height) def resize_item(self, rect): ''' On resize event, make sure connection points are updated ''' delta_y = self.boundingRect().height() - rect.height() super(Decision, self).resize_item(rect) self.connectionPoint.setX(self.boundingRect().center().x()) self.connectionPoint.setY(self.connectionPoint.y() - delta_y) self.update_connections() def update_connections(self): ''' Redefined - update arrows shape below connection point ''' super(Decision, self).update_connections() for branch in self.branches(): for cnx in branch.last_branch_item.connections(): cnx.reshape() def updateConnectionPointPosition(self): ''' Compute the joining point of decision branches ''' new_y = 0 new_x = self.boundingRect().width() / 2.0 answers = False for branch in self.branches(): answers = True last_cnx = None last = branch.last_branch_item try: # To compute the branch length, we must keep only the symbols, # so we must remove the last connection (if any) last_cnx, = (c for c in last.childItems() if isinstance(c, Connection) and not isinstance(c.child, (Comment, HorizontalSymbol))) # Don't set parent item to None to avoid Qt segfault last_cnx.setParentItem(self) except ValueError: pass branch_len = branch.y() + ( branch.boundingRect() | branch.childrenBoundingRect()).height() try: last_cnx.setParentItem(last) except AttributeError: pass # If last item was a decision, use its connection point # position to get the length of the branch: try: branch_len = (last.connectionPoint.y() + self.mapFromScene(0, last.scenePos().y()).y()) except AttributeError: pass # Rounded with int() -> mandatory when view scale has changed new_y = int(max(new_y, branch_len)) if not answers: new_y = int(self.boundingRect().height()) new_y += 15 delta = new_y - self.connectionPoint.y() self.connectionPoint.setY(new_y) self.connectionPoint.setX(new_x) if delta != 0: child = self.next_aligned_symbol() try: child.pos_y += delta except AttributeError: pass self.update_connections()
class Decision(VerticalSymbol): ''' SDL DECISION Symbol ''' _unique_followers = ['Comment'] _insertable_followers = [ 'DecisionAnswer', 'Task', 'ProcedureCall', 'Output', 'Decision', 'Label' ] _terminal_followers = ['Join', 'State', 'ProcedureStop'] common_name = 'decision' # Define reserved keywords for the syntax highlighter blackbold = SDL_BLACKBOLD + [ '\\b{}\\b'.format(word) for word in ('AND', 'OR') ] redbold = SDL_REDBOLD completion_list = {'length', 'present'} def __init__(self, parent=None, ast=None): ast = ast or ogAST.Decision() # Define the point where all branches of the decision can join again self.connectionPoint = QPoint(ast.width / 2, ast.height + 30) super(Decision, self).__init__(parent, text=ast.inputString, x=ast.pos_x, y=ast.pos_y, hyperlink=ast.hyperlink) self.set_shape(ast.width, ast.height) self.setBrush(QColor(255, 255, 202)) self.minDistanceToSymbolAbove = 0 self.parser = ogParser self.text_alignment = Qt.AlignHCenter if ast.comment: Comment(parent=self, ast=ast.comment) @property def terminal_symbol(self): ''' Compute dynamically if the item is terminal by checking if all its branches end with a terminator ''' for branch in self.branches(): if not branch.last_branch_item.terminal_symbol: return False return True def branches(self): ''' Return the list of decision answers (as a generator) ''' return (branch for branch in self.childSymbols() if isinstance(branch, DecisionAnswer)) def check_syntax(self): ''' Redefined function, to check only the symbol, not recursively ''' _, syntax_errors, _, _, _ = self.parser.parseSingleElement( self.common_name, self.PR(recursive=False)) try: # LOG.error('\n'.join(syntax_errors)) self.scene().raise_syntax_errors(syntax_errors) except AttributeError: LOG.debug('raise_syntax_error raised an exception') def set_shape(self, width, height): ''' Define polygon points to draw the symbol ''' path = QPainterPath() path.moveTo(width / 2, 0) path.lineTo(width, height / 2) path.lineTo(width / 2, height) path.lineTo(0, height / 2) path.lineTo(width / 2, 0) self.setPath(path) super(Decision, self).set_shape(width, height) def resize_item(self, rect): ''' On resize event, make sure connection points are updated ''' delta_y = self.boundingRect().height() - rect.height() super(Decision, self).resize_item(rect) self.connectionPoint.setX(self.boundingRect().center().x()) self.connectionPoint.setY(self.connectionPoint.y() - delta_y) self.update_connections() def update_connections(self): ''' Redefined - update arrows shape below connection point ''' super(Decision, self).update_connections() for branch in self.branches(): for cnx in branch.last_branch_item.connections(): cnx.reshape() def updateConnectionPointPosition(self): ''' Compute the joining point of decision branches ''' new_y = 0 new_x = self.boundingRect().width() / 2.0 answers = False for branch in self.branches(): answers = True last_cnx = None last = branch.last_branch_item try: # To compute the branch length, we must keep only the symbols, # so we must remove the last connection (if any) last_cnx, = ( c for c in last.childItems() if isinstance(c, Connection) and not isinstance(c.child, (Comment, HorizontalSymbol))) # Don't set parent item to None to avoid Qt segfault last_cnx.setParentItem(self) except ValueError: pass branch_len = branch.y() + (branch.boundingRect() | branch.childrenBoundingRect()).height() try: last_cnx.setParentItem(last) except AttributeError: pass # If last item was a decision, use its connection point # position to get the length of the branch: try: branch_len = (last.connectionPoint.y() + self.mapFromScene(0, last.scenePos().y()).y()) except AttributeError: pass # Rounded with int() -> mandatory when view scale has changed new_y = int(max(new_y, branch_len)) if not answers: new_y = int(self.boundingRect().height()) new_y += 15 delta = new_y - self.connectionPoint.y() self.connectionPoint.setY(new_y) self.connectionPoint.setX(new_x) if delta != 0: child = self.next_aligned_symbol() try: child.moveBy(0, delta) except AttributeError: pass self.update_connections() def PR(self, recursive=True): ''' Get PR notation of a decision (possibly recursively) ''' comment = self.comment.PR() if self.comment else u';' pos = self.scenePos() result = [ u'/* CIF DECISION ({x}, {y}), ({w}, {h}) */\n' '{hlink}' 'DECISION {d}{comment}'.format(hlink=self.text.PR(), d=unicode(self), x=int(pos.x()), y=int(pos.y()), w=int(self.boundingRect().width()), h=int(self.boundingRect().height()), comment=comment) ] if recursive: for answer in self.branches(): if unicode(answer).lower().strip() == 'else': result.append(answer.PR()) else: result.insert(1, answer.PR()) result.append('ENDDECISION;') return u'\n'.join(result)
class Rectangle(Figure): def __init__(self, *args, **kwargs): self.first_point = FirstPoint() self.second_point = SecondPoint() self.control = Control() self.p1 = QPoint() self.p2 = QPoint() Figure.__init__(self, self.first_point) if 'x1' in kwargs and 'y1' in kwargs: self.p1 = QPoint(kwargs['x1'], kwargs['y1']) if 'x2' in kwargs and 'y2' in kwargs: self.p2 = QPoint(kwargs['x2'], kwargs['y2']) if 'p1' in kwargs: self.p1 = kwargs['p1'] if 'p2' in kwargs: self.p2 = kwargs['p2'] if len(args) == 2: self.p1 = args[0] self.p2 = args[1] if len(args) == 4: self.p1 = QPoint(args[0], args[1]) self.p2 = QPoint(args[2], args[3]) if 'figure' in kwargs: self.p1 = QPoint(kwargs['figure']['x1'], kwargs['figure']['y1']) self.p2 = QPoint(kwargs['figure']['x2'], kwargs['figure']['y2']) self.state = self.control def draw(self, painter, scale): painter.save() if not self.p1.isNull() and not self.p2.isNull(): painter.setPen( QPen( QBrush( QColor(232, 109, 21) if self.state is not self. control else QColor(21, 144, 232)), self.lineWidth(scale), Qt.SolidLine)) painter.setBrush(QBrush(QColor(21, 144, 232, 150))) painter.drawRect(QRect(self.p1, self.p2)) self.drawControlPoint(painter, self.p1, QColor(31, 174, 222), scale) self.drawControlPoint(painter, self.p2, QColor(222, 79, 31), scale) Figure.draw(self, painter, scale) painter.restore() def getDict(self): return { 'rect': { 'x1': self.p1.x(), 'y1': self.p1.y(), 'x2': self.p2.x(), 'y2': self.p2.y() } } def __str__(self): return self.__repr__() def __repr__(self): return 'Rectangle(({x1}, {y1}), ({x2}, {y2}))'.format(x1=self.p1.x(), y1=self.p1.y(), x2=self.p2.x(), y2=self.p2.y())