def add_color_scale(self): x_init = self.position[0] + self.margin + self.width y_init = self.position[1] + self.margin square_size = 20 text_title = QGraphicsSimpleTextItem("clearance") text_title.setPos(x_init, y_init - square_size) self.addToGroup(text_title) for i in range(10): x = x_init y = y_init + 9 * square_size - i * square_size rect = QGraphicsRectItem(x, y, square_size, square_size) pen = QPen() pen.setWidth(0.01) value = (float(i)/9 * (self.vertical_clearance_max - self.vertical_clearance_min)) + self.vertical_clearance_min color = self.color_interpolation.get_interpolation_from_value(value) brush = QBrush(color) rect.setPen(pen) rect.setBrush(brush) self.addToGroup(rect) if i == 0: text_start = QGraphicsSimpleTextItem("%.2f m" % float(self.vertical_clearance_min)) text_start.setPos(x + square_size + 5, y) self.addToGroup(text_start) if i == 9: text_end = QGraphicsSimpleTextItem("%.2f m" % float(self.vertical_clearance_max)) text_end.setPos(x + square_size + 5, y) self.addToGroup(text_end) else: value = self.vertical_clearance_min + (self.vertical_clearance_max-self.vertical_clearance_min) * i/9 text = QGraphicsSimpleTextItem("%.2f m" % value) text.setPos(x + square_size + 5, y) self.addToGroup(text)
def __init__(self, *args): super(Demo, self).__init__(*args) loadUi('MainWindow.ui', self) scene = QGraphicsScene() rectItem = QGraphicsRectItem(QRectF(0, 0, 320, 240)) rectItem.setBrush(Qt.red) #rectItem.setPen(Qt.NoPen) rectItem.setFlag(QGraphicsItem.ItemIsMovable) scene.addItem(rectItem) ellipseItem = QGraphicsEllipseItem(QRectF(0, 0, 200, 200)) ellipseItem.setBrush(Qt.blue) #ellipseItem.setPen(Qt.NoPen) ellipseItem.setFlag(QGraphicsItem.ItemIsMovable) scene.addItem(ellipseItem) rectSizeGripItem = SizeGripItem(SimpleResizer(rectItem), rectItem) ellipseSizeGripItem = SizeGripItem(SimpleResizer(ellipseItem), ellipseItem) graphicsView = QGraphicsView(self) graphicsView.setScene(scene) self.setCentralWidget(graphicsView)
def __init__(self, parent=None): QGraphicsScene.__init__(self, parent) # hold the set of keys we're pressing self.keys_pressed = set() # use a timer to get 60Hz refresh (hopefully) self.timer = QBasicTimer() self.timer.start(FRAME_TIME_MS, self) bg = QGraphicsRectItem() bg.setRect(-1, -1, SCREEN_WIDTH + 2, SCREEN_HEIGHT + 2) bg.setBrush(QBrush(Qt.black)) self.addItem(bg) self.player = Player() self.player.setPos((SCREEN_WIDTH - self.player.pixmap().width()) / 2, (SCREEN_HEIGHT - self.player.pixmap().height()) / 2) self.bullets = [ Bullet(PLAYER_BULLET_X_OFFSETS[0], PLAYER_BULLET_Y), Bullet(PLAYER_BULLET_X_OFFSETS[1], PLAYER_BULLET_Y) ] for b in self.bullets: b.setPos(SCREEN_WIDTH, SCREEN_HEIGHT) self.addItem(b) self.addItem(self.player) self.view = QGraphicsView(self) self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.view.show() self.view.setFixedSize(SCREEN_WIDTH, SCREEN_HEIGHT) self.setSceneRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)
class GraphicsScene(QGraphicsScene): def __init__(self): super().__init__() self._pos = QPointF() self._current_item = None # Полупрозрачный цвет self._item_color = QColor(0, 0, 255, 128) def mousePressEvent(self, event): super().mousePressEvent(event) self._pos = event.scenePos() self._current_item = QGraphicsRectItem() self._current_item.setBrush(self._item_color) self.addItem(self._current_item) self._current_item.setRect(QRectF(self._pos, self._pos)) def mouseMoveEvent(self, event): super().mouseMoveEvent(event) if self._current_item: rect = QRectF(self._pos, event.scenePos()).normalized() self._current_item.setRect(rect) def mouseReleaseEvent(self, event): super().mouseReleaseEvent(event) # Убираем после отпускания кнопки мыши self.removeItem(self._current_item) self._current_item = None
def display_markers(self): """Mark all the markers, from the dataset. This function should be called only when we load the dataset or when we change the settings. """ for rect in self.idx_markers: self.scene.removeItem(rect) self.idx_markers = [] markers = [] if self.parent.info.markers is not None: if self.parent.value('marker_show'): markers = self.parent.info.markers for mrk in markers: rect = QGraphicsRectItem(mrk['start'], BARS['markers']['pos0'], mrk['end'] - mrk['start'], BARS['markers']['pos1']) self.scene.addItem(rect) color = self.parent.value('marker_color') rect.setPen(QPen(QColor(color))) rect.setBrush(QBrush(QColor(color))) rect.setZValue(-5) self.idx_markers.append(rect)
def mark_quality(self, start_time, length, qual_name): """Mark signal quality, only add the new ones. Parameters ---------- start_time : int start time in s of the epoch being scored. length : int duration in s of the epoch being scored. qual_name : str one of the stages defined in global stages. """ y_pos = BARS['quality']['pos0'] height = 10 # the -1 is really important, otherwise we stay on the edge of the rect old_score = self.scene.itemAt(start_time + length / 2, y_pos + height - 1, self.transform()) # check we are not removing the black border if old_score is not None and old_score.pen() == NoPen: lg.debug('Removing old score at {}'.format(start_time)) self.scene.removeItem(old_score) self.idx_annot.remove(old_score) if qual_name == 'Poor': rect = QGraphicsRectItem(start_time, y_pos, length, height) rect.setPen(NoPen) rect.setBrush(Qt.black) self.scene.addItem(rect) self.idx_annot.append(rect)
def mark_stages(self, start_time, length, stage_name): """Mark stages, only add the new ones. Parameters ---------- start_time : int start time in s of the epoch being scored. length : int duration in s of the epoch being scored. stage_name : str one of the stages defined in global stages. """ y_pos = BARS['stage']['pos0'] # the -1 is really important, otherwise we stay on the edge of the rect old_score = self.scene.itemAt( start_time + length / 2, y_pos + STAGES[stage_name]['pos0'] + STAGES[stage_name]['pos1'] - 1, self.transform()) # check we are not removing the black border if old_score is not None and old_score.pen() == NoPen: lg.debug('Removing old score at {}'.format(start_time)) self.scene.removeItem(old_score) self.idx_annot.remove(old_score) rect = QGraphicsRectItem(start_time, y_pos + STAGES[stage_name]['pos0'], length, STAGES[stage_name]['pos1']) rect.setPen(NoPen) rect.setBrush(STAGES[stage_name]['color']) self.scene.addItem(rect) self.idx_annot.append(rect)
def simplex_run(self): args = { 'height': self.ui.inputHeight.value(), 'length': self.ui.inputLength.value(), 'calc_a': self.ui.inputCalcA.value(), 'calc_b': self.ui.inputCalcB.value(), 'calc_c': self.ui.inputCalcC.value(), 'gradual': self.ui.inputGradual.checkState() } simplex = sw.SimplexGenerator(args) self.ui.creationBar.setMaximum(args.get('height') * args.get('length')) counter = 0 for p in simplex.createelevation(): counter += 1 item = QGraphicsRectItem(3 * p.get('x'), 3 * p.get('y'), 3, 3) item.setBrush(QColor(*simplex.decidebiome(p.get('elev')))) self.scene.addItem(item) self.ui.creationBar.setValue(counter) if args.get('gradual'): # Update for each 100th pixel to keep performance so-and-so if counter % 100 == 0: QApplication.processEvents()
class ReadoutView(View): class Orientation(Enum): horizontal = 1 vertical = 2 def __init__(self, model): super().__init__(model) self.graphics_item = QGraphicsRectItem(0, 0, 9, 9) self.graphics_item.setBrush(Qt.black) inner_rect_item = QGraphicsRectItem(1, 1, 7, 7, self.graphics_item) inner_rect_item.setBrush(Qt.white) self.text_item = None self.orientation = ReadoutView.Orientation.horizontal def line(self): for child in self.graphics_item.childItems(): if isinstance(child, QGraphicsLineItem): return child.line() def line_item(self): for child in self.graphics_item.childItems(): if isinstance(child, QGraphicsLineItem): return child def init_text(self): width = self.graphics_item.boundingRect().width() height = self.graphics_item.boundingRect().height() self.text_item = QGraphicsTextItem(self.graphics_item) self.text_item.setPos(width / 2 + 2, -height)
class FuncItem(KineticsDisplayItem): name = constants.ITEM """Class for displaying Functions""" #fontMetrics = None font = QtGui.QFont(KineticsDisplayItem.defaultFontName) font.setPointSize(KineticsDisplayItem.defaultFontSize) fontMetrics = QtGui.QFontMetrics(font) def __init__(self, mobj, parent): super(FuncItem, self).__init__(mobj, parent) self.setFlag(QGraphicsItem.ItemIsMovable, True) iconmap_file = (os.path.join(config.settings[config.KEY_ICON_DIR], 'classIcon/Function.png')) self.funcImage = QtGui.QImage(iconmap_file).scaled(15, 33) self.bg = QGraphicsRectItem(self) self.bg.setAcceptHoverEvents(True) self.gobj = QGraphicsPixmapItem( QtGui.QPixmap.fromImage(self.funcImage), self.bg) self.gobj.setAcceptHoverEvents(True) self.gobj.mobj = self.mobj funcdoc = (moose.element(self.mobj.path)).expr self.gobj.setToolTip(funcdoc) def setDisplayProperties(self, x, y, textcolor, bgcolor): """Set the display properties of this item.""" poolt = ["ZombieBufPool", "BufPool", "ZombiePool", "Pool"] if self.gobj.mobj.parent.className in poolt: self.setGeometry(0, 30, self.gobj.boundingRect().width(), self.gobj.boundingRect().height()) else: self.setGeometry(x, y, self.gobj.boundingRect().width(), self.gobj.boundingRect().height()) self.bg.setBrush(QtGui.QBrush(bgcolor)) self.setFlag(QGraphicsItem.ItemIsMovable, False) def refresh(self, scale): pass def boundingRect(self): ''' reimplimenting boundingRect for redrawning ''' return QtCore.QRectF(0, 0, self.gobj.boundingRect().width(), self.gobj.boundingRect().height()) def updateSlot(self): return None def updateColor(self, bgcolor): return None def updateRect(self, ratio): return None def returnColor(self): return (self.bg.brush().color()) def updateValue(self, gobj, funcdoc='Not Available'): self.gobj.setToolTip(funcdoc)
def makeRoad(self, parent): self.line_space = (parent.height() / (LINE_COUNT - 2)) - LINE_H bg = QGraphicsRectItem() bg.setRect(0, 0, parent.width(), parent.height()) bg.setBrush(QBrush(Qt.gray)) self.scene.addItem(bg) self.lines = [] self.topLineIndex = 0 ax = (parent.width() / 2) - (LINE_W / 2) for i in range(LINE_COUNT): line = QGraphicsRectItem() ay = (i - 1) * (LINE_H + self.line_space) line.setRect(0, 0, LINE_W, LINE_H) line.setPos(ax, ay) line.setBrush(QBrush(Qt.white)) self.scene.addItem(line) self.lines.append(line) """ Because of the lines, the scene isn't in the middle """ """ So we add an extra rectangle to center the scene """ spaceFill = QGraphicsRectItem() ay = (LINE_COUNT - 1) * (LINE_H + self.line_space) - self.line_space spaceFill.setRect(ax, ay, LINE_W, self.line_space) self.scene.addItem(spaceFill) self.setFixedSize(parent.width(), parent.height())
def mark_stages(self, start_time, length, stage_name): """Mark stages, only add the new ones. Parameters ---------- start_time : int start time in s of the epoch being scored. length : int duration in s of the epoch being scored. stage_name : str one of the stages defined in global stages. """ y_pos = BARS['stage']['pos0'] # the -1 is really important, otherwise we stay on the edge of the rect old_score = self.scene.itemAt(start_time + length / 2, y_pos + STAGES[stage_name]['pos0'] + STAGES[stage_name]['pos1'] - 1, self.transform()) # check we are not removing the black border if old_score is not None and old_score.pen() == NoPen: lg.debug('Removing old score at {}'.format(start_time)) self.scene.removeItem(old_score) self.idx_annot.remove(old_score) rect = QGraphicsRectItem(start_time, y_pos + STAGES[stage_name]['pos0'], length, STAGES[stage_name]['pos1']) rect.setPen(NoPen) rect.setBrush(STAGES[stage_name]['color']) self.scene.addItem(rect) self.idx_annot.append(rect)
class Window(QMainWindow, QGraphicsView): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowTitle('Proof of concept') self.setWindowIcon(QIcon('web.png')) # self.setGeometry(3000, 3000, 250, 150) # vbox = QVBoxLayout() # self.setLayout(vbox) self.initView() self.button = QPushButton('Test', self) self.button.move(50, 50) self.button.clicked.connect(self.myButtonClicked) self.statusBar() self.showMaximized() def myButtonClicked(self, event): sender = self.sender() self.statusBar().showMessage(sender.text() + ' was pressed') def initView(self): QGraphicsView.__init__(self) self.scene = QGraphicsScene() blueBrush =QBrush(QColor('blue')) outlinePen=QPen(QColor('black')) self.myRect = QGraphicsRectItem(100, 30, 80, 100) self.myRect.setBrush(blueBrush) self.myRect.setPen(outlinePen) self.scene.addItem(self.myRect) self.scene.setSceneRect(0, 0, 3000, 3000) self.view = QGraphicsView(self.scene,self) self.view.resize(3000,3000) def keyPressEvent(self, e): # override ! if e.key() == Qt.Key_Escape: self.close() elif e.key() == Qt.Key_W: self.statusBar().showMessage("UP pressed") self.myRect.setY(self.myRect.y()+1) self.show() elif e.key() == Qt.Key_D: self.statusBar().showMessage("RIGHT pressed") self.myRect.setX(self.myRect.x()+1) self.show() elif e.key() == Qt.Key_S: self.statusBar().showMessage("DOWN pressed") self.myRect.setY(self.myRect.y()-1) self.show() elif e.key() == Qt.Key_A: self.statusBar().showMessage("LEFT pressed") self.myRect.setX(self.myRect.x()-1) # self.myRect.setPos(self.myRect.x(),self.myRect.y()-) self.show()
class Infoscene(QGraphicsScene): def __init__(self, cam, menu, parent=None): QGraphicsScene.__init__(self, parent) self.view = cam self.menu = menu bg = QGraphicsRectItem() bg.setRect(0, 0, globals.SCREEN_WIDTH, globals.SCREEN_HEIGHT) bg.setBrush(QBrush(Qt.black)) self.addItem(bg) self.button1 = QGraphicsRectItem(40, 500, 110, 60) self.button1.setBrush(QBrush(QtGui.QColor(38, 38, 38))) self.addItem(self.button1) self.buttonFont = QtGui.QFont() self.buttonFont.setPointSize(20) self.textFont = QtGui.QFont() self.textFont.setPointSize(18) self.titleFont = QtGui.QFont() self.titleFont.setPointSize(30) self.b1 = QtWidgets.QGraphicsTextItem('BACK') self.b1.setDefaultTextColor(QtGui.QColor(255, 0, 0)) self.b1.setPos(43, 500) self.b1.setFont(self.buttonFont) self.addItem(self.b1) self.title = QtWidgets.QGraphicsTextItem('How To Play') self.title.setDefaultTextColor(QtGui.QColor(255, 0, 0)) self.title.setPos(200, 25) self.title.setFont(self.titleFont) self.addItem(self.title) text = ( 'Kario can move with left and right arrow keys and jump with space. ' + 'Your job is to collect every price as quickly as possible but be aware of ' + 'turtle enemys: If they touch you, you will die! How ever, you can' + 'distroy them by jumping on them. If you have collected all of the ' + 'prices and succesfully make it to the goal, you win the level!') self.text = QtWidgets.QGraphicsTextItem(text) self.text.setDefaultTextColor(QtGui.QColor(255, 255, 255)) self.text.setPos(85, 130) self.text.setFont(self.textFont) self.text.adjustSize() self.addItem(self.text) self.view.update_scene(self) def mousePressEvent(self, QMouseEvent): if (QMouseEvent.scenePos().x() >= 40 and QMouseEvent.scenePos().x() <= 40 + 110 and QMouseEvent.scenePos().y() >= 500 and QMouseEvent.scenePos().y() <= 500 + 60): self.view.update_scene(self.menu)
class StimulusGraphicsScene(QGraphicsScene): def __init__(self, parent=None): super().__init__(parent) self._invert = False self.homography_transform = None self.setBackgroundBrush(Qt.black) monitor_width = 3200 monitor_height = 1800 self.background_image = QGraphicsRectItem(0, 0, 1, 1) brush = QBrush() brush.setStyle(Qt.SolidPattern) brush.setColor(Qt.black) self.background_image.setBrush(brush) self.addItem(self.background_image) self.visible_group = QGraphicsItemGroup() self.visible_stimuli = [] # self.sceneRectChanged.connect(self.on_sceneRectChanged) # test_rect = QGraphicsRectItem(-50, -50, 100, 100) # brush2 = QBrush() # brush2.setStyle(Qt.CrossPattern) # brush2.setColor(Qt.blue) # test_rect.setBrush(brush2) # self.addItem(test_rect) # self.test_rect = test_rect #test_rect.setPos(monitor_width/2, monitor_height/2) def display_points(self, points): #log.debug("Adding {} to scene.".format(points)) for p in self.visible_stimuli: self.removeItem(p) self.visible_stimuli = [] for p in points: log.debug("Adding at {} of size {}".format(p.pos(), p.rect().width())) self.addItem(p) self.visible_stimuli.append(p) # self.update() @property def invert(self): return self._invert @invert.setter def invert(self, value): self._invert = value self.update() def update_background(self): self.background_image.setRect(self.sceneRect())
def display_houses(self): for i in range(self.nb_houses): width, height = self.color_rect.boundingRect().getRect()[2:] set_color = QColor() set_color.setNamedColor("#00FF00") house = QGraphicsRectItem(width / 4 * i + 5, height / 4, width / 4 - 10, height / 2) house.setParentItem(self.color_rect) house.setBrush(QBrush(set_color, style=Qt.Dense1Pattern))
def init_background(self): window_bg = QGraphicsRectItem() window_bg.setRect(-OFSET[0], -OFSET[1], SCREEN_WIDTH, SCREEN_HEIGHT) window_bg.setBrush(QBrush(QColor(130, 128, 129))) self.addItem(window_bg) game_bg = QGraphicsRectItem() game_bg.setRect(0, 0, WIDTH - 1, HEIGHT - 1) game_bg.setBrush(QBrush(Qt.black)) self.addItem(game_bg)
def color_tile(self, color): set_color = QColor() set_color.setNamedColor(color) color_rect = QGraphicsRectItem(0, 0, 150, 25, parent=self.color_property) color_rect.setBrush(QBrush(set_color, style=Qt.SolidPattern)) return color_rect
def set_boxes(self, boxes): for box in boxes: box_item = QGraphicsRectItem() box_item.setPen(QPen(Qt.red, 4)) box_item.setBrush(QBrush(Qt.NoBrush)) box_item.setZValue(1) self.scene.addItem(box_item) box_item.hide() box_item.setRect(QRectF(box[0], box[1], box[2]-box[0], box[3]-box[1])) self.box_item_list.append(box_item)
def __init__(self, model): super().__init__(model) self.graphics_item = QGraphicsRectItem(0, 0, 9, 9) self.graphics_item.setBrush(Qt.black) inner_rect_item = QGraphicsRectItem(1, 1, 7, 7, self.graphics_item) inner_rect_item.setBrush(Qt.white) self.text_item = None self.orientation = ReadoutView.Orientation.horizontal
def show_text(self, text, size): self.update() window_bg = QGraphicsRectItem() window_bg.setRect(-OFSET[0], -OFSET[1], SCREEN_WIDTH, SCREEN_HEIGHT) window_bg.setBrush(QBrush(Qt.black)) self.addItem(window_bg) self.text = QGraphicsTextItem(text) self.text.setDefaultTextColor(Qt.white) self.text.setPos(window_bg.rect().center() - QPoint(120, size)) self.text.setFont(QFont('Press Start', int(size))) self.addItem(self.text)
def printAttributes(self, background, border, text): """ Prints the attributes of the node The attributes are a key, value pair :param background: background color of the node :param border: border color for the node :param text: text color for the node """ y = self.y() + self.headerHeight x = self.x() self.attributesHeight = 0 for k, v in self.node.attributes.items(): key = QGraphicsTextItem() key.setFont(Configuration.font) key.setDefaultTextColor(QColor(text)) key.setTextWidth(100) key.setPlainText(k) keyHeight = int(key.boundingRect().height() / 20 + 0.5) * 20 value = QGraphicsTextItem() value.setFont(Configuration.font) value.setDefaultTextColor(QColor(text)) value.setTextWidth(100) value.setPlainText(v) valueHeight = int(value.boundingRect().height() / 20 + 0.5) * 20 height = valueHeight if valueHeight > keyHeight else keyHeight keyRect = QGraphicsRectItem() keyRect.setRect(x, y, 100, height) valueRect = QGraphicsRectItem() valueRect.setRect(x + 100, y, 100, height) keyRect.setBrush(QBrush(QColor(background))) valueRect.setBrush(QBrush(QColor(background))) keyRect.setPen(QPen(QColor(border), 2)) valueRect.setPen(QPen(QColor(border), 2)) key.setPos(x, y - 2) value.setPos(x + 100, y - 2) self.attributes.addToGroup(keyRect) self.attributes.addToGroup(valueRect) self.attributes.addToGroup(key) self.attributes.addToGroup(value) y = y + height self.attributesHeight += height self.addToGroup(self.attributes)
class PickingStation(VisualizerGraphicItem): def __init__(self, ID=0, x=0, y=0): super(self.__class__, self).__init__(ID, x, y) self._kind_name = 'pickingStation' self._items = [] self._graphics_item = QGraphicsRectItem(self) self._items.append(QGraphicsRectItem(self._graphics_item)) self._items.append(QGraphicsRectItem(self._graphics_item)) self._text = QGraphicsTextItem(self._graphics_item) def set_rect(self, rect): scale = config.get('display', 'id_font_scale') bold = config.get('display', 'id_font_bold') self._text.setFont(QFont('', rect.width() * 0.08 * scale)) self._text.setPos(rect.x(), rect.y() + 0.6 * rect.height()) self._text.setDefaultTextColor( QColor(config.get('display', 'id_font_color'))) if self._display_mode == 0: if bold: self._text.setHtml('<b>P(' + str(self._id) + ')</b>') else: self._text.setHtml('P(' + str(self._id) + ')') self._graphics_item.setRect(rect.x(), rect.y(), rect.width(), rect.height()) self._items[0].setRect(rect.x() + rect.width() / 5, rect.y(), rect.width() / 5, rect.height()) self._items[1].setRect(rect.x() + rect.width() / 5 * 3, rect.y(), rect.width() / 5, rect.height()) elif self._display_mode == 1: self._text.setPlainText('') self._graphics_item.setRect(rect.x(), rect.y(), rect.width(), rect.height()) self._items[0].setRect(rect.x() + rect.width() / 5, rect.y(), rect.width() / 5, rect.height()) self._items[1].setRect(rect.x() + rect.width() / 5 * 3, rect.y(), rect.width() / 5, rect.height()) def determine_color(self, number, count, pattern=None): color = self._colors[0] color2 = self._colors[1] color.setAlpha(150) color2.setAlpha(150) brush = QBrush(color) brush2 = QBrush(color2) self._graphics_item.setBrush(brush) self._items[0].setBrush(brush2) self._items[1].setBrush(brush2) def get_rect(self): return self._graphics_item.rect()
def display_annotations(self): """Mark all the bookmarks/events, from annotations. This function is similar to display_markers, but they are called at different stages (f.e. when loading annotations file), so we keep them separate """ for rect in self.idx_annot: self.scene.removeItem(rect) self.idx_annot = [] if self.parent.notes.annot is None: return bookmarks = [] events = [] if self.parent.value('annot_show'): bookmarks = self.parent.notes.annot.get_bookmarks() events = self.parent.notes.get_selected_events() annotations = bookmarks + events for annot in annotations: rect = QGraphicsRectItem(annot['start'], BARS['annot']['pos0'], annot['end'] - annot['start'], BARS['annot']['pos1']) self.scene.addItem(rect) if annot in bookmarks: color = self.parent.value('annot_bookmark_color') if annot in events: color = convert_name_to_color(annot['name']) rect.setPen(QPen(QColor(color), LINE_WIDTH)) rect.setBrush(QBrush(QColor(color))) rect.setZValue(-5) self.idx_annot.append(rect) for epoch in self.parent.notes.annot.epochs: self.mark_stages(epoch['start'], epoch['end'] - epoch['start'], epoch['stage']) self.mark_quality(epoch['start'], epoch['end'] - epoch['start'], epoch['quality']) cycles = self.parent.notes.annot.rater.find('cycles') cyc_starts = [float(mrkr.text) for mrkr in cycles.findall('cyc_start')] cyc_ends = [float(mrkr.text) for mrkr in cycles.findall('cyc_end')] for mrkr in cyc_starts: self.mark_cycles(mrkr, 30) # TODO: better width solution for mrkr in cyc_ends: self.mark_cycles(mrkr, 30, end=True)
def __init__(self, process, *__args): super().__init__() rect = QGraphicsRectItem(*__args) self.addToGroup(rect) rect.setAcceptHoverEvents(True) self.process = process self.neighbours = [] self.action = process if process.process['thread']: rect.setBrush(QColor(255, 250, 205))
def create_scene_tile(self, x: int, y: int, tile) -> QGraphicsItem: x, y = self.pos_to_scene(x, y) width = 2 * qt_drawings.tile_size if tile.is_horizontal else qt_drawings.tile_size height = qt_drawings.tile_size if tile.is_horizontal else 2 * qt_drawings.tile_size item = QGraphicsRectItem(0, 0, width, height) item.setPos(x, y) item.setBrush(qt_drawings.tile_to_brush(tile)) item.setPen(qt_drawings.black_pen) self.scene.addItem(item) return item
def render_monitors(self, monitors): pen = QPen() pen.setWidth(10) brush = QBrush() scene = QGraphicsScene() for mon in monitors: this_rect = QGraphicsRectItem(mon.x(), mon.y(), mon.width(), mon.height()) this_rect.setPen(pen) this_rect.setBrush(brush) this_rect.setZValue(1) scene.addItem(this_rect) self.monitor_display.setScene(scene) self.monitor_display.fitInView(scene.sceneRect(), Qt.KeepAspectRatio)
def __init__(self, model): super().__init__(model) if isinstance(self.model, models.PushInletSocket): self.graphics_item = GraphicsPushSocketItem(model, 0, 0, 15, 15) self.graphics_item.setBrush(Qt.black) inner_rect_item = QGraphicsRectItem(1, 1, 13, 13, self.graphics_item) inner_rect_item.setBrush(Qt.white) self.socket_marker_item = QGraphicsRectItem( 4, 4, 7, 7, inner_rect_item) self.socket_marker_item.setBrush(Qt.red) self.socket_marker_item.setOpacity(0.3) elif isinstance(self.model, models.PushOutletSocket): self.graphics_item = GraphicsPushSocketItem(model, 0, 0, 15, 15) self.graphics_item.setBrush(Qt.black) inner_rect_item = QGraphicsRectItem(2, 2, 11, 11, self.graphics_item) inner_rect_item.setBrush(Qt.white) self.socket_marker_item = QGraphicsRectItem( 4, 4, 7, 7, inner_rect_item) self.socket_marker_item.setBrush(Qt.red) self.socket_marker_item.setOpacity(0.3) elif isinstance(self.model, models.PullInletSocket): self.graphics_item = GraphicsPullSocketItem(model, 0, 0, 15, 15) self.graphics_item.setBrush(Qt.black) inner_circle_item = QGraphicsEllipseItem(1, 1, 13, 13, self.graphics_item) inner_circle_item.setBrush(Qt.white) self.socket_marker_item = QGraphicsEllipseItem( 4, 4, 7, 7, inner_circle_item) self.socket_marker_item.setBrush(Qt.red) self.socket_marker_item.setOpacity(0.3) elif isinstance(self.model, models.PullOutletSocket): self.graphics_item = GraphicsPullSocketItem(model, 0, 0, 15, 15) self.graphics_item.setBrush(Qt.black) inner_circle_item = QGraphicsEllipseItem(2, 2, 11, 11, self.graphics_item) inner_circle_item.setBrush(Qt.white) self.socket_marker_item = QGraphicsEllipseItem( 4, 4, 7, 7, inner_circle_item) self.socket_marker_item.setBrush(Qt.red) self.socket_marker_item.setOpacity(0.3)
def draw(self, defending, status, scene, size): """function draw :param defending: bool :param status: str {'Charge', 'Shoot', 'Stand'} :param scene: QGraphicsScene :param size: QSize no return """ if not isinstance(defending, bool): raise ValueError('defending must be a boolean') if not isinstance(status, str) or (status != 'Charge' and status != 'Shoot' and status != 'Stand'): raise ValueError('status must be a str in {\'Charge\', \'Shoot\', \'Stand\'}') self.unitType.draw(defending, status, scene, size) flag_width = self.nation.flag.width() * 10 / self.nation.flag.height() item = scene.addPixmap(self.nation.flag.scaled(flag_width, 10)) item.setPos(size.width() - 5 - flag_width, 0) # life bar item1 = QGraphicsRectItem(0, size.height() - 10, size.width() - 5, 5) item1.setBrush(QBrush(Qt.white)) item2 = QGraphicsRectItem(0, size.height() - 10, self.unitStrength / 100 * (size.width() - 5), 5) item2.setBrush(QBrush(Qt.green)) # moral bar item3 = QGraphicsRectItem(0, size.height() - 15, size.width() - 5, 5) item3.setBrush(QBrush(Qt.white)) item4 = QGraphicsRectItem(0, size.height() - 15, self.moral / 100 * (size.width() - 5), 5) item4.setBrush(QBrush(Qt.blue)) scene.addItem(item1) scene.addItem(item2) scene.addItem(item3) scene.addItem(item4)
def draw(self, defending, status, scene, size): """function draw :param defending: bool :param status: str {'Charge', 'Shoot', 'Stand'} :param scene: QGraphicsScene :param size: QSize no return """ if not isinstance(defending, bool): raise ValueError("defending must be a boolean") if not isinstance(status, str) or (status != "Charge" and status != "Shoot" and status != "Stand"): raise ValueError("status must be a str in {'Charge', 'Shoot', 'Stand'}") self.unitType.draw(defending, status, scene, size) flag_width = self.nation.flag.width() * 10 / self.nation.flag.height() item = scene.addPixmap(self.nation.flag.scaled(flag_width, 10)) item.setPos(size.width() - 5 - flag_width, 0) # life bar item1 = QGraphicsRectItem(0, size.height() - 10, size.width() - 5, 5) item1.setBrush(QBrush(Qt.white)) item2 = QGraphicsRectItem(0, size.height() - 10, self.unitStrength / 100 * (size.width() - 5), 5) item2.setBrush(QBrush(Qt.green)) # moral bar item3 = QGraphicsRectItem(0, size.height() - 15, size.width() - 5, 5) item3.setBrush(QBrush(Qt.white)) item4 = QGraphicsRectItem(0, size.height() - 15, self.moral / 100 * (size.width() - 5), 5) item4.setBrush(QBrush(Qt.blue)) scene.addItem(item1) scene.addItem(item2) scene.addItem(item3) scene.addItem(item4)
def updateGraphicsRectItem(rect: QGraphicsRectItem, rectF: QRectF = None, pen: QPen = None, brush: QBrush = None): """ 更新QGraphicsRectItem属性 :param rect: QGraphicsRectItem :param rectF: 矩形rect :param pen: 边框画笔 :param brush: 填充画刷 """ if rectF: rect.setRect(rectF) if pen: rect.setPen(pen) if brush: rect.setBrush(brush)
def display_current(self): """Create a rectangle showing the current window.""" if self.idx_current in self.scene.items(): self.scene.removeItem(self.idx_current) item = QGraphicsRectItem(0, CURR['pos0'], self.parent.value('window_length'), CURR['pos1']) # it's necessary to create rect first, and then move it item.setPos(self.parent.value('window_start'), 0) item.setPen(QPen(Qt.lightGray)) item.setBrush(QBrush(Qt.lightGray)) item.setZValue(-10) self.scene.addItem(item) self.idx_current = item
def get_elements(self, cell, height): result = [] current = [] rectangles = self.doc.elementsByTagName('rect') for i in range(rectangles.size()): rect = rectangles.item(i).toElement() fill = '#aaaaaa' item = QGraphicsRectItem(float(rect.attribute('x')), float(rect.attribute('y')), float(rect.attribute('width')), float(rect.attribute('height'))) item.setBrush(QBrush(QColor(fill))) result.append(item) if rect.attribute('id') == str(cell): side_fill = fill size = item.rect().getRect() for j in range(1, height+1): x = size[0] - 12 * j y = size[1] - 20 * j if j == height: side_fill = '#ff0000' top = QGraphicsRectItem(x, y, size[2], size[3]) top.setBrush(QBrush(QColor(fill).darker(200))) current.append(top) path = QPainterPath() path.moveTo(x + size[2], y + size[3]) path.lineTo(x + size[2] + 12, y + size[3] + 20) path.lineTo(x + 12, y + size[3] + 20) path.lineTo(x, y + size[3]) front = QGraphicsPathItem(path) front.setBrush(QBrush(QColor(side_fill))) current.append(front) path = QPainterPath() path.moveTo(x + size[2], y + size[3]) path.lineTo(x + size[2] + 12, y + size[3] + 20) path.lineTo(x + size[2] + 12, y + 20) path.lineTo(x + size[2], y) right = QGraphicsPathItem(path) right.setBrush(QBrush(QColor(side_fill).lighter())) current.append(right) return result + current
def add_tree_items( self, block_type ): # switch colour depending on type (expeneses / income) for it in self.blocks: # loop through dict list # Construct a square object rect = QGraphicsRectItem(it["x"], it["y"], it["dx"], it["dy"]) if block_type == "income": rect.setBrush(QColor.fromRgb(97, 247, 255)) elif block_type == "expenses": rect.setBrush(QColor.fromRgb(255, 105, 97)) self.scene.addItem(rect) return self.scene
class AnimatedClock(): updateTimer = None calDataLock = threading.Lock() calDataUpdated = False curCalendars = None def __init__(self, scene, widthClkTextArea, heightClkTextArea, borders, updateSecs): self.masterScene = scene self.widthClkTextArea = widthClkTextArea self.heightClkTextArea = heightClkTextArea self.borders = borders self.updateSecs = updateSecs # Background self.textBkgd = QGraphicsRectItem(0, 0, self.widthClkTextArea, self.heightClkTextArea) self.textBkgd.setPos(self.borders[3], self.borders[0]) self.textBkgd.setBrush(QColor("light green")) self.textBkgd.setZValue(10) scene.addItem(self.textBkgd) # Text Item self.textItem = QGraphicsTextItem() self.textItem.setFont(QFont("Segoe UI", 80)) self.textItem.setDefaultTextColor(QColor("black")) self.textItem.setPos(QPointF(self.borders[3]+10,self.borders[0]+5)) self.textItem.setHtml("<B>Clock</B>") self.textItem.setZValue(20) self.textItem.setTextWidth(self.widthClkTextArea-20) scene.addItem(self.textItem) def start(self): self.updateTimer = QTimer() self.updateTimer.setInterval(self.updateSecs * 1000) self.updateTimer.timeout.connect(self.updateClock) self.updateTimer.start() def stop (self): if self.updateTimer != None: self.updateTimer.stop() def updateClock(self): localtime = time.localtime() # dateString = time.strftime("%a %d %b %Y", localtime) timeString = time.strftime("%H:%M:%S", localtime) self.textItem.setHtml(timeString) # self.textItem.setTextWidth(self.widthCalTextArea-20) self.textItem.update()
def create_map_points(self): self.map_points_text_items = [] self.map_points_items = [] for map_point in self.map_data.map_points: color = QColor().fromRgb(map_point.r, map_point.g, map_point.b) rect = QGraphicsRectItem( QRectF( QPointF(map_point.x, map_point.y), QSizeF(5 / self.scale_ratio, 5 / self.scale_ratio) ) ) rect.setPen(QPen(Qt.black, 1 / self.scale_ratio)) rect.setBrush(color) self.map_points_items.append(rect) text = QGraphicsTextItem(map_point.text) text.setDefaultTextColor(color) text.setPos(map_point.x, map_point.y) text.setFont(QFont('Times New Roman', 8 / self.scale_ratio, 2)) self.map_points_text_items.append(text)
def display_annotations(self): """Mark all the bookmarks/events, from annotations. This function is similar to display_markers, but they are called at different stages (f.e. when loading annotations file), so we keep them separate """ for rect in self.idx_annot: self.scene.removeItem(rect) self.idx_annot = [] if self.parent.notes.annot is None: return bookmarks = [] events = [] if self.parent.value('annot_show'): bookmarks = self.parent.notes.annot.get_bookmarks() events = self.parent.notes.get_selected_events() annotations = bookmarks + events for annot in annotations: rect = QGraphicsRectItem(annot['start'], BARS['annot']['pos0'], annot['end'] - annot['start'], BARS['annot']['pos1']) self.scene.addItem(rect) if annot in bookmarks: color = self.parent.value('annot_bookmark_color') if annot in events: color = convert_name_to_color(annot['name']) rect.setPen(QPen(QColor(color), LINE_WIDTH)) rect.setBrush(QBrush(QColor(color))) rect.setZValue(-5) self.idx_annot.append(rect) for epoch in self.parent.notes.annot.epochs: self.mark_stages(epoch['start'], epoch['end'] - epoch['start'], epoch['stage'])
class CustomDragWidget(QGraphicsWidget): def __init__(self,): super().__init__() self.squareItem = QGraphicsRectItem() self.squareItem.setBrush(QBrush(QColor(Qt.blue))) self.squareItem.setPen(QPen(QColor(Qt.black), 2)) self.squareItem.setRect(0, 0, 50, 50) self.squareItem.setParentItem(self) self.setAcceptDrops(True) def mousePressEvent(self, event): mime = QMimeData() itemData = QByteArray() mime.setData('application/x-dnditemdata', itemData) drag = QDrag(self) drag.setMimeData(mime) drag.exec_(Qt.MoveAction) def dropEvent(self, event): event.accept()
def drawGrid(self): black_notes = [2,4,6,9,11] scale_bar = QGraphicsRectItem(0, 0, self.grid_width, self.note_height, self.piano) scale_bar.setPos(self.piano_width, 0) scale_bar.setBrush(QColor(100,100,100)) clearpen = QPen(QColor(0,0,0,0)) for i in range(self.end_octave - self.start_octave, self.start_octave - self.start_octave, -1): for j in range(self.notes_in_octave, 0, -1): scale_bar = QGraphicsRectItem(0, 0, self.grid_width, self.note_height, self.piano) scale_bar.setPos(self.piano_width, self.note_height * j + self.octave_height * (i - 1)) scale_bar.setPen(clearpen) if j not in black_notes: scale_bar.setBrush(QColor(120,120,120)) else: scale_bar.setBrush(QColor(100,100,100)) measure_pen = QPen(QColor(0, 0, 0, 120), 3) half_measure_pen = QPen(QColor(0, 0, 0, 40), 2) line_pen = QPen(QColor(0, 0, 0, 40)) for i in range(0, int(self.num_measures) + 1): measure = QGraphicsLineItem(0, 0, 0, self.piano_height + self.header_height - measure_pen.width(), self.header) measure.setPos(self.measure_width * i, 0.5 * measure_pen.width()) measure.setPen(measure_pen) if i < self.num_measures: number = QGraphicsSimpleTextItem('%d' % (i + 1), self.header) number.setPos(self.measure_width * i + 5, 2) number.setBrush(Qt.white) for j in self.frange(0, self.time_sig[0]*self.grid_div/self.time_sig[1], 1.): line = QGraphicsLineItem(0, 0, 0, self.piano_height, self.header) line.setZValue(1.0) line.setPos(self.measure_width * i + self.value_width * j, self.header_height) if j == self.time_sig[0]*self.grid_div/self.time_sig[1] / 2.0: line.setPen(half_measure_pen) else: line.setPen(line_pen)
def display_markers(self): """Add markers on top of first plot.""" for item in self.idx_markers: self.scene.removeItem(item) self.idx_markers = [] window_start = self.parent.value('window_start') window_length = self.parent.value('window_length') window_end = window_start + window_length y_distance = self.parent.value('y_distance') markers = [] if self.parent.info.markers is not None: if self.parent.value('marker_show'): markers = self.parent.info.markers for mrk in markers: if window_start <= mrk['end'] and window_end >= mrk['start']: mrk_start = max((mrk['start'], window_start)) mrk_end = min((mrk['end'], window_end)) color = QColor(self.parent.value('marker_color')) item = QGraphicsRectItem(mrk_start, 0, mrk_end - mrk_start, len(self.idx_label) * y_distance) item.setPen(color) item.setBrush(color) item.setZValue(-9) self.scene.addItem(item) item = TextItem_with_BG(color.darker(200)) item.setText(mrk['name']) item.setPos(mrk['start'], len(self.idx_label) * self.parent.value('y_distance')) item.setFlag(QGraphicsItem.ItemIgnoresTransformations) item.setRotation(-90) self.scene.addItem(item) self.idx_markers.append(item)
def add_height_clearance_graph(self): vertical_clearance = self.clearance_analysis.vertical_clearance x_init = self.graph_zero[0] + self.line_extend y_init = self.graph_zero[1] y_unit_distance = self.clearance_analysis.sampling_distance * self.height_multiplier x_unit_distance = self.clearance_analysis.section_distance * self.length_multiplier for i in range(len(vertical_clearance)): for j in range(len(vertical_clearance[i])): vertical_distance = vertical_clearance[i][j] if vertical_distance: vertical_distance_value = vertical_distance[0] scene_x = (vertical_distance[1].point.Y() * self.length_multiplier + x_init) - x_unit_distance/2 scene_y = (vertical_distance[1].point.X() * self.height_multiplier + y_init) - y_unit_distance/2 rect = QGraphicsRectItem(scene_x, scene_y, x_unit_distance, y_unit_distance) color = self.color_interpolation.get_interpolation_from_value(vertical_distance_value) pen = QPen() pen.setStyle(Qt.NoPen) brush = QBrush(color) rect.setPen(pen) rect.setBrush(brush) rect.setZValue(-1.0) self.addToGroup(rect) pass
class CalendarDesklet(Desklet): def __init__(self): super().__init__() self.model = CalendarModel() self.cursor_pos = None self.cursor = QGraphicsRectItem(self.root) self.header = QGraphicsSimpleTextItem(self.root) self.weekdays = [] days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] for day in days: self.weekdays.append(QGraphicsSimpleTextItem(day, self.root)) self.header_line = QGraphicsLineItem(self.root) self.days = [] for _ in range(0, 6 * 7): self.days.append(QGraphicsSimpleTextItem(self.root)) def next_month(self): self.model.next_month() self.layout() def previous_month(self): self.model.previous_month() self.layout() def set_rect(self, rect): super().set_rect(rect) self.layout() def set_style(self, style): super().set_style(style) font = QFont(style.font) font.setPixelSize(48) self.header.setBrush(style.midcolor) self.header.setFont(font) font = QFont(style.font) font.setPixelSize(32) self.header_line.setPen(style.foreground_color) self.cursor.setBrush(style.midcolor) self.cursor.setPen(QPen(Qt.NoPen)) for widget in self.weekdays: widget.setFont(font) widget.setBrush(style.foreground_color) for widget in self.days: widget.setFont(font) widget.setBrush(self.style.foreground_color) self.layout() def layout(self): cell_width = (self.rect.width()) / 7.0 cell_height = (self.rect.height() - 64) / 7.0 x = self.rect.left() y = self.rect.top() fm = QFontMetrics(self.header.font()) rect = fm.boundingRect(self.header.text()) self.header.setPos(x + self.rect.width() / 2 - rect.width() / 2, y) y += fm.height() for row, day in enumerate(self.weekdays): fm = QFontMetrics(day.font()) rect = fm.boundingRect(day.text()) day.setPos(x + row * cell_width + cell_width / 2 - rect.width() / 2, y) y += fm.height() self.header_line.setLine(x, y, x + self.rect.width() - 3, y) y += 8 for n, widget in enumerate(self.days): col = n % 7 row = n // 7 rect = fm.boundingRect(widget.text()) widget.setPos(x + col * cell_width + cell_width / 2 - rect.width() / 2, y + row * cell_height + cell_height / 2 - fm.height() / 2) # if day.month != self.now.month: # widget.setBrush(self.style.midcolor) # else: if self.cursor_pos is not None: self.cursor.setRect(x + self.cursor_pos[0] * cell_width, y + self.cursor_pos[1] * cell_height, cell_width, cell_height) self.cursor.show() else: self.cursor.hide() def update(self, now): self.model.update(now) # update header self.header.setText( date(self.model.year, self.model.month, 1).strftime("%B %Y")) # calculate the date of the top/left calendar entry current_date = date(self.model.year, self.model.month, 1) current_date = current_date - timedelta(current_date.weekday()) self.cursor_pos = None for n, widget in enumerate(self.days): col = n % 7 row = n // 7 if current_date == self.model.today: self.cursor_pos = (col, row) widget.setText("%d" % current_date.day) self.days[n] = widget current_date += timedelta(days=1) self.layout()
class BankNodeItem (NodeItem): maincolor = FlPalette.bank altcolor = FlPalette.bankvar label = "%s Bank" def __init__ (self, nodeobj, parent=None, view=None, state=1): super().__init__(nodeobj, parent, view, state) self.rect = QRectF() self.setZValue(-1) self.updatecomment() self.updatebanktype() self.updatebankmode() def nudgechildren(self): super().nudgechildren() for sub in self.sublist(): sub.setrank(self) def sublist (self): ID = self.nodeobj.ID itemtable = self.view.itemtable if self.state == 1 and ID in itemtable and not self.iscollapsed(): children = [] for child in self.nodeobj.subnodes: if child in itemtable[ID]: item = itemtable[ID][child] else: continue if item.state > -1: children.append(item) return children else: return [] def treeposition (self, ranks=None): self.updatelayout(external=True) return super().treeposition(ranks) def graphicsetup (self): super().graphicsetup() darkbrush = QBrush(FlPalette.bg) nopen = QPen(0) viewport = self.view.viewport() self.btypeicon = QGraphicsPixmapItemCond(self.icon, self, viewport) self.btypeicon.setPos(self.iconx-self.style.itemmargin-self.iwidth, self.style.itemmargin) self.iconx = self.btypeicon.x() self.fggroup.addToGroup(self.btypeicon) self.centerbox = QGraphicsRectItem(self) self.centerbox.setCacheMode(QGraphicsItem.DeviceCoordinateCache) self.centerbox.setRect(QRectF()) self.centerbox.setBrush(darkbrush) self.centerbox.setPen(nopen) self.centerbox.setPos(0, self.nodelabel.y()+self.nodelabel.boundingRect().height()+self.style.itemmargin*2) self.fggroup.addToGroup(self.centerbox) def updatebanktype (self): types = {"talk": "(T)", "response": "(R)", "": ""} self.nodelabel.setText("%s Bank %s" % (self.realid(), types[self.nodeobj.banktype])) def updatebankmode (self): icons = {"First": "bank-first", "All": "bank-all", "Append": "bank-append", "": "blank"} pixmap = self.pixmap("images/%s.png" % icons[self.nodeobj.bankmode]) self.btypeicon.setPixmap(pixmap) if self.nodeobj.bankmode: self.btypeicon.setToolTip("Bank mode: %s" % self.nodeobj.bankmode) else: self.btypeicon.setToolTip("") def updatecenterbox (self): verticalpos = self.centerbox.y() maxwidth = self.style.nodetextwidth subnodes = self.sublist() for subnode in subnodes: if subnode.nodeobj.typename == "bank": subnode.updatelayout(external=True) noderect = subnode.boundingRect() nodeheight = noderect.height() nodewidth = noderect.width() subnode.show() subnode.yoffset = self.mapToScene(0,verticalpos + nodeheight/2+self.style.activemargin).y()-self.y_bottom() verticalpos += nodeheight+self.style.activemargin*2 maxwidth = max(maxwidth, nodewidth) centerrect = self.centerbox.rect() centerrect.setWidth(maxwidth+self.style.selectmargin*2) centerrect.setHeight(verticalpos-self.centerbox.y()) self.centerbox.setRect(centerrect) centerrect = self.centerbox.mapRectToParent(centerrect) self.comment.setY(centerrect.bottom()+self.style.itemmargin) def updatelayout (self, external=False): subnodes = self.sublist() if self.iscollapsed(): rect = self.nodelabel.mapRectToParent(self.nodelabel.boundingRect()) else: self.updatecenterbox() rect = self.fggroup.childrenBoundingRect() mainrect = rect.marginsAdded(self.style.banknodemargins) self.mainbox.setRect(mainrect) self.shadowbox.setRect(mainrect) self.selectbox.setRect(mainrect.marginsAdded(self.style.selectmargins)) activerect = mainrect.marginsAdded(self.style.activemargins) self.activebox.setRect(activerect) oldypos = self.centerbox.mapToScene(self.centerbox.pos()).y() self.graphgroup.setPos(-activerect.width()//2-activerect.x(), -activerect.height()//2-activerect.y()) newypos = self.centerbox.mapToScene(self.centerbox.pos()).y() for subnode in subnodes: subnode.yoffset += newypos - oldypos subnode.setY(self.y()) self.prepareGeometryChange() self.rect = self.graphgroup.mapRectToParent(mainrect) if not external: self.view.updatelayout() def setY (self, y): super().setY(y) for subnode in self.sublist(): subnode.setY(y) def contextMenuEvent (self, event): menu = QMenu() if self.isselected(): window = FlGlob.mainwindow menu.addAction(window.actions["collapse"]) if self.isghost(): menu.addAction(window.actions["selectreal"]) menu.addAction(window.actions["copynode"]) menu.addMenu(window.subnodemenu) menu.addMenu(window.addmenu) menu.addAction(window.actions["moveup"]) menu.addAction(window.actions["movedown"]) menu.addAction(window.actions["parentswap"]) menu.addAction(window.actions["unlinknode"]) menu.addAction(window.actions["unlinkstree"]) menu.addAction(window.actions["settemplate"]) menu.addMenu(window.transformmenu) if not menu.isEmpty(): menu.exec_(event.screenPos())
def refresh(self): if not self._mdlPlots or not self._mdlOutline or not self._mdlCharacter: return if not self.isVisible(): return LINE_HEIGHT = 18 SPACING = 3 TEXT_WIDTH = self.sldTxtSize.value() CIRCLE_WIDTH = 10 LEVEL_HEIGHT = 12 s = self.scene s.clear() # Get Max Level (max depth) root = self._mdlOutline.rootItem def maxLevel(item, level=0, max=0): if level > max: max = level for c in item.children(): m = maxLevel(c, level + 1) if m > max: max = m return max MAX_LEVEL = maxLevel(root) # Get the list of tracked items (array of references) trackedItems = [] if self.actPlots.isChecked(): trackedItems += self.plotReferences() if self.actCharacters.isChecked(): trackedItems += self.charactersReferences() ROWS_HEIGHT = len(trackedItems) * (LINE_HEIGHT + SPACING ) fm = QFontMetrics(s.font()) max_name = 0 for ref in trackedItems: name = references.title(ref) max_name = max(fm.width(name), max_name) TITLE_WIDTH = max_name + 2 * SPACING # Add Folders and Texts outline = OutlineRect(0, 0, 0, ROWS_HEIGHT + SPACING + MAX_LEVEL * LEVEL_HEIGHT) s.addItem(outline) outline.setPos(TITLE_WIDTH + SPACING, 0) refCircles = [] # a list of all references, to be added later on the lines # A Function to add a rect with centered elided text def addRectText(x, w, parent, text="", level=0, tooltip=""): deltaH = LEVEL_HEIGHT if level else 0 r = OutlineRect(0, 0, w, parent.rect().height()-deltaH, parent, title=text) r.setPos(x, deltaH) txt = QGraphicsSimpleTextItem(text, r) f = txt.font() f.setPointSize(8) fm = QFontMetricsF(f) elidedText = fm.elidedText(text, Qt.ElideMiddle, w) txt.setFont(f) txt.setText(elidedText) txt.setPos(r.boundingRect().center() - txt.boundingRect().center()) txt.setY(0) return r # A function to returns an item's width, by counting its children def itemWidth(item): if item.isFolder(): r = 0 for c in item.children(): r += itemWidth(c) return r or TEXT_WIDTH else: return TEXT_WIDTH def listItems(item, rect, level=0): delta = 0 for child in item.children(): w = itemWidth(child) if child.isFolder(): parent = addRectText(delta, w, rect, child.title(), level, tooltip=child.title()) parent.setToolTip(references.tooltip(references.textReference(child.ID()))) listItems(child, parent, level + 1) else: rectChild = addRectText(delta, TEXT_WIDTH, rect, "", level, tooltip=child.title()) rectChild.setToolTip(references.tooltip(references.textReference(child.ID()))) # Find tracked references in that scene (or parent folders) for ref in trackedItems: result = [] # Tests if POV scenePOV = False # Will hold true of character is POV of the current text, not containing folder if references.type(ref) == references.CharacterLetter: ID = references.ID(ref) c = child while c: if c.POV() == ID: result.append(c.ID()) if c == child: scenePOV = True c = c.parent() # Search in notes/references c = child while c: result += references.findReferencesTo(ref, c, recursive=False) c = c.parent() if result: ref2 = result[0] # Create a RefCircle with the reference c = RefCircle(TEXT_WIDTH / 2, - CIRCLE_WIDTH / 2, CIRCLE_WIDTH, ID=ref2, important=scenePOV) # Store it, with the position of that item, to display it on the line later on refCircles.append((ref, c, rect.mapToItem(outline, rectChild.pos()))) delta += w listItems(root, outline) OUTLINE_WIDTH = itemWidth(root) # Add Tracked items i = 0 itemsRect = s.addRect(0, 0, 0, 0) itemsRect.setPos(0, MAX_LEVEL * LEVEL_HEIGHT + SPACING) # Set of colors for plots (as long as they don't have their own colors) colors = [ "#D97777", "#AE5F8C", "#D9A377", "#FFC2C2", "#FFDEC2", "#D2A0BC", "#7B0F0F", "#7B400F", "#620C3D", "#AA3939", "#AA6C39", "#882D61", "#4C0000", "#4C2200", "#3D0022", ] for ref in trackedItems: if references.type(ref) == references.CharacterLetter: color = self._mdlCharacter.getCharacterByID(references.ID(ref)).color() else: color = QColor(colors[i % len(colors)]) # Rect r = QGraphicsRectItem(0, 0, TITLE_WIDTH, LINE_HEIGHT, itemsRect) r.setPen(QPen(Qt.NoPen)) r.setBrush(QBrush(color)) r.setPos(0, i * LINE_HEIGHT + i * SPACING) r.setToolTip(references.tooltip(ref)) i += 1 # Text name = references.title(ref) txt = QGraphicsSimpleTextItem(name, r) txt.setPos(r.boundingRect().center() - txt.boundingRect().center()) # Line line = PlotLine(0, 0, OUTLINE_WIDTH + SPACING, 0) line.setPos(TITLE_WIDTH, r.mapToScene(r.rect().center()).y()) s.addItem(line) line.setPen(QPen(color, 5)) line.setToolTip(references.tooltip(ref)) # We add the circles / references to text, on the line for ref2, circle, pos in refCircles: if ref2 == ref: circle.setParentItem(line) circle.setPos(pos.x(), 0) # self.view.fitInView(0, 0, TOTAL_WIDTH, i * LINE_HEIGHT, Qt.KeepAspectRatioByExpanding) # KeepAspectRatio self.view.setSceneRect(0, 0, 0, 0)
class PaintArea(QGraphicsView): def __init__(self, width=10, parent=None): QGraphicsView.__init__(self, parent) self._frame = None self._instructions = None self.setScene(QGraphicsScene(self)) self._items = self.scene().createItemGroup([]) self.setMouseTracking(True) self.pen = QPen(Qt.black, width, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin) self.painting = False self.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) self.viewport().setCursor(self.getCursor()) self.updateScene() def updateScene(self): if self._frame: self.scene().setBackgroundBrush(Qt.gray) oldCanvas = self.canvas() self.setSceneRect(QRectF(self.contentsRect())) self.centerScene() self.scaleItems(oldCanvas, self.canvas()) def centerScene(self): self.centerFrame() self.centerInstructions() def scaleItems(self, oldCanvas, newCanvas): pass def canvas(self): if self._frame: return self._frame.rect() return QRectF(self.contentsRect()) def fitInstructions(self): textSize = self._instructions.document().size() factor = min(self.canvas().size().width() / textSize.width(), self.canvas().size().height() / textSize.height()) f = self._instructions.font() f.setPointSizeF(f.pointSizeF() * factor) self._instructions.setFont(f) def centerInstructions(self): if self._instructions: self.fitInstructions() size = self.size() textSize = self._instructions.document().size() self._instructions.setPos((size.width() - textSize.width()) / 2.0, (size.height() - textSize.height()) / 2.0) def setInstructions(self, text): if self._instructions: self._instructions.setPlainText(text) else: self._instructions = self.scene().addText(text, QFont('Arial', 10, QFont.Bold)) self._instructions.setZValue(-1) self._instructions.setDefaultTextColor(QColor(220, 220, 220)) self._text = text self.centerInstructions() def setFrame(self, width, height): if self._frame: self._frame.setRect(0, 0, width, height) else: self.addFrame(QRectF(0, 0, width, height)) self.centerScene() def addFrame(self, rect): self._frame = QGraphicsRectItem(rect) self._frame.setPen(QPen(Qt.NoPen)) self._frame.setBrush(Qt.white) self._frame.setZValue(-2) self.scene().addItem(self._frame) def centerFrame(self): if self._frame: rect = self._frame.rect() size = self.contentsRect() factor = min((size.width() + 1) / rect.width(), (size.height() + 1) / rect.height()) w, h = rect.width() * factor, rect.height() * factor self._frame.setRect(size.x() + (size.width() - w) / 2.0, size.y() + (size.height() - h) / 2.0, w, h) def resizeEvent(self, event): self.updateScene() def setBrushSize(self, size): self.pen.setWidth(size) self.viewport().setCursor(self.getCursor()) def render(self, painter): if self._instructions: self.scene().removeItem(self._instructions) self.scene().render(painter, source=self.scene().itemsBoundingRect()) if self._instructions: self.scene().addItem(self._instructions) def getLines(self): items = [item for item in self.scene().items() if item.group() == self._items] return self.canvas(), items def clear(self): for item in self.scene().items(): if item.group() == self._items: self._items.removeFromGroup(item) def getCursor(self): antialiasing_margin = 1 size = self.pen.width() pixmap = QPixmap(size + antialiasing_margin * 2, size + antialiasing_margin * 2) pixmap.fill(Qt.transparent) painter = QPainter(pixmap) painter.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) painter.drawEllipse(QRectF(QPointF(antialiasing_margin, antialiasing_margin), QSizeF(size, size))) painter.end() return QCursor(pixmap) def addLine(self, start, end): if start == end: delta = QPointF(.0001, 0) end = start - delta line = self.scene().addLine(QLineF(start, end), self.pen) self._items.addToGroup(line) def drawPoint(self, pos): delta = QPointF(.0001, 0) line = self.scene().addLine(QLineF(pos, pos - delta), self.pen) self._items.addToGroup(line) def mousePressEvent(self, event): self.start = QPointF(self.mapToScene(event.pos())) self.painting = True self.addLine(self.start, self.start) def mouseReleaseEvent(self, event): self.painting = False def mouseMoveEvent(self, event): pos = QPointF(self.mapToScene(event.pos())) if self.painting: self.addLine(self.start, pos) self.start = pos
def mouseMoveEvent(self, event): """When normal selection, update power spectrum with current selection. Otherwise, show the range of the new marker. """ if not self.scene: return if self.idx_sel in self.scene.items(): self.scene.removeItem(self.idx_sel) self.idx_sel = None chk_marker = self.parent.notes.action['new_bookmark'].isChecked() chk_event = self.parent.notes.action['new_event'].isChecked() if chk_marker or chk_event: xy_scene = self.mapToScene(event.pos()) y_distance = self.parent.value('y_distance') pos = QRectF(self.sel_xy[0], 0, xy_scene.x() - self.sel_xy[0], len(self.idx_label) * y_distance) item = QGraphicsRectItem(pos.normalized()) item.setPen(NoPen) if chk_marker: color = QColor(self.parent.value('annot_bookmark_color')) elif chk_event: eventtype = self.parent.notes.idx_eventtype.currentText() color = convert_name_to_color(eventtype) item.setBrush(QBrush(color.lighter(115))) item.setZValue(-10) self.scene.addItem(item) self.idx_sel = item return xy_scene = self.mapToScene(event.pos()) pos = QRectF(self.sel_xy[0], self.sel_xy[1], xy_scene.x() - self.sel_xy[0], xy_scene.y() - self.sel_xy[1]) self.idx_sel = QGraphicsRectItem(pos.normalized()) self.idx_sel.setPen(QPen(QColor(LINE_COLOR), LINE_WIDTH)) self.scene.addItem(self.idx_sel) if self.idx_info in self.scene.items(): self.scene.removeItem(self.idx_info) duration = '{0:0.2f}s'.format(abs(xy_scene.x() - self.sel_xy[0])) # get y-size, based on scaling too y = abs(xy_scene.y() - self.sel_xy[1]) scale = self.parent.value('y_scale') * self.chan_scale[self.sel_chan] height = '{0:0.3f}uV'.format(y / scale) item = TextItem_with_BG() item.setText(duration + ' ' + height) item.setPos(self.sel_xy[0], self.sel_xy[1]) self.scene.addItem(item) self.idx_info = item trial = 0 time = self.parent.traces.data.axis['time'][trial] beg_win = min((self.sel_xy[0], xy_scene.x())) end_win = max((self.sel_xy[0], xy_scene.x())) time_of_interest = time[(time >= beg_win) & (time < end_win)] if len(time_of_interest) > MINIMUM_N_SAMPLES: data = self.parent.traces.data(trial=trial, chan=self.chan[self.sel_chan], time=time_of_interest) n_data = len(data) n_pad = (power(2, ceil(log2(n_data))) - n_data) / 2 data = pad(data, (int(ceil(n_pad)), int(floor(n_pad))), 'constant') self.parent.spectrum.display(data)
class MapScene(QGraphicsScene): selectedObjectItemsChanged = pyqtSignal() ## # Constructor. ## def __init__(self, parent): super().__init__(parent) self.mMapDocument = None self.mSelectedTool = None self.mActiveTool = None self.mObjectSelectionItem = None self.mUnderMouse = False self.mCurrentModifiers = Qt.NoModifier, self.mDarkRectangle = QGraphicsRectItem() self.mDefaultBackgroundColor = Qt.darkGray self.mLayerItems = QVector() self.mObjectItems = QMap() self.mObjectLineWidth = 0.0 self.mSelectedObjectItems = QSet() self.mLastMousePos = QPointF() self.mShowTileObjectOutlines = False self.mHighlightCurrentLayer = False self.mGridVisible = False self.setBackgroundBrush(self.mDefaultBackgroundColor) tilesetManager = TilesetManager.instance() tilesetManager.tilesetChanged.connect(self.tilesetChanged) tilesetManager.repaintTileset.connect(self.tilesetChanged) prefs = preferences.Preferences.instance() prefs.showGridChanged.connect(self.setGridVisible) prefs.showTileObjectOutlinesChanged.connect(self.setShowTileObjectOutlines) prefs.objectTypesChanged.connect(self.syncAllObjectItems) prefs.highlightCurrentLayerChanged.connect(self.setHighlightCurrentLayer) prefs.gridColorChanged.connect(self.update) prefs.objectLineWidthChanged.connect(self.setObjectLineWidth) self.mDarkRectangle.setPen(QPen(Qt.NoPen)) self.mDarkRectangle.setBrush(Qt.black) self.mDarkRectangle.setOpacity(darkeningFactor) self.addItem(self.mDarkRectangle) self.mGridVisible = prefs.showGrid() self.mObjectLineWidth = prefs.objectLineWidth() self.mShowTileObjectOutlines = prefs.showTileObjectOutlines() self.mHighlightCurrentLayer = prefs.highlightCurrentLayer() # Install an event filter so that we can get key events on behalf of the # active tool without having to have the current focus. QCoreApplication.instance().installEventFilter(self) ## # Destructor. ## def __del__(self): if QCoreApplication.instance(): QCoreApplication.instance().removeEventFilter(self) ## # Returns the map document this scene is displaying. ## def mapDocument(self): return self.mMapDocument ## # Sets the map this scene displays. ## def setMapDocument(self, mapDocument): if (self.mMapDocument): self.mMapDocument.disconnect() if (not self.mSelectedObjectItems.isEmpty()): self.mSelectedObjectItems.clear() self.selectedObjectItemsChanged.emit() self.mMapDocument = mapDocument if (self.mMapDocument): renderer = self.mMapDocument.renderer() renderer.setObjectLineWidth(self.mObjectLineWidth) renderer.setFlag(RenderFlag.ShowTileObjectOutlines, self.mShowTileObjectOutlines) self.mMapDocument.mapChanged.connect(self.mapChanged) self.mMapDocument.regionChanged.connect(self.repaintRegion) self.mMapDocument.tileLayerDrawMarginsChanged.connect(self.tileLayerDrawMarginsChanged) self.mMapDocument.layerAdded.connect(self.layerAdded) self.mMapDocument.layerRemoved.connect(self.layerRemoved) self.mMapDocument.layerChanged.connect(self.layerChanged) self.mMapDocument.objectGroupChanged.connect(self.objectGroupChanged) self.mMapDocument.imageLayerChanged.connect(self.imageLayerChanged) self.mMapDocument.currentLayerIndexChanged.connect(self.currentLayerIndexChanged) self.mMapDocument.tilesetTileOffsetChanged.connect(self.tilesetTileOffsetChanged) self.mMapDocument.objectsInserted.connect(self.objectsInserted) self.mMapDocument.objectsRemoved.connect(self.objectsRemoved) self.mMapDocument.objectsChanged.connect(self.objectsChanged) self.mMapDocument.objectsIndexChanged.connect(self.objectsIndexChanged) self.mMapDocument.selectedObjectsChanged.connect(self.updateSelectedObjectItems) self.refreshScene() ## # Returns whether the tile grid is visible. ## def isGridVisible(self): return self.mGridVisible ## # Returns the set of selected map object items. ## def selectedObjectItems(self): return QSet(self.mSelectedObjectItems) ## # Sets the set of selected map object items. This translates to a call to # MapDocument.setSelectedObjects. ## def setSelectedObjectItems(self, items): # Inform the map document about the newly selected objects selectedObjects = QList() #selectedObjects.reserve(items.size()) for item in items: selectedObjects.append(item.mapObject()) self.mMapDocument.setSelectedObjects(selectedObjects) ## # Returns the MapObjectItem associated with the given \a mapObject. ## def itemForObject(self, object): return self.mObjectItems[object] ## # Enables the selected tool at this map scene. # Therefore it tells that tool, that this is the active map scene. ## def enableSelectedTool(self): if (not self.mSelectedTool or not self.mMapDocument): return self.mActiveTool = self.mSelectedTool self.mActiveTool.activate(self) self.mCurrentModifiers = QApplication.keyboardModifiers() if (self.mCurrentModifiers != Qt.NoModifier): self.mActiveTool.modifiersChanged(self.mCurrentModifiers) if (self.mUnderMouse): self.mActiveTool.mouseEntered() self.mActiveTool.mouseMoved(self.mLastMousePos, Qt.KeyboardModifiers()) def disableSelectedTool(self): if (not self.mActiveTool): return if (self.mUnderMouse): self.mActiveTool.mouseLeft() self.mActiveTool.deactivate(self) self.mActiveTool = None ## # Sets the currently selected tool. ## def setSelectedTool(self, tool): self.mSelectedTool = tool ## # QGraphicsScene.drawForeground override that draws the tile grid. ## def drawForeground(self, painter, rect): if (not self.mMapDocument or not self.mGridVisible): return offset = QPointF() # Take into account the offset of the current layer layer = self.mMapDocument.currentLayer() if layer: offset = layer.offset() painter.translate(offset) prefs = preferences.Preferences.instance() self.mMapDocument.renderer().drawGrid(painter, rect.translated(-offset), prefs.gridColor()) ## # Override for handling enter and leave events. ## def event(self, event): x = event.type() if x==QEvent.Enter: self.mUnderMouse = True if (self.mActiveTool): self.mActiveTool.mouseEntered() elif x==QEvent.Leave: self.mUnderMouse = False if (self.mActiveTool): self.mActiveTool.mouseLeft() else: pass return super().event(event) def keyPressEvent(self, event): if (self.mActiveTool): self.mActiveTool.keyPressed(event) if (not (self.mActiveTool and event.isAccepted())): super().keyPressEvent(event) def mouseMoveEvent(self, mouseEvent): self.mLastMousePos = mouseEvent.scenePos() if (not self.mMapDocument): return super().mouseMoveEvent(mouseEvent) if (mouseEvent.isAccepted()): return if (self.mActiveTool): self.mActiveTool.mouseMoved(mouseEvent.scenePos(), mouseEvent.modifiers()) mouseEvent.accept() def mousePressEvent(self, mouseEvent): super().mousePressEvent(mouseEvent) if (mouseEvent.isAccepted()): return if (self.mActiveTool): mouseEvent.accept() self.mActiveTool.mousePressed(mouseEvent) def mouseReleaseEvent(self, mouseEvent): super().mouseReleaseEvent(mouseEvent) if (mouseEvent.isAccepted()): return if (self.mActiveTool): mouseEvent.accept() self.mActiveTool.mouseReleased(mouseEvent) ## # Override to ignore drag enter events. ## def dragEnterEvent(self, event): event.ignore() ## # Sets whether the tile grid is visible. ## def setGridVisible(self, visible): if (self.mGridVisible == visible): return self.mGridVisible = visible self.update() def setObjectLineWidth(self, lineWidth): if (self.mObjectLineWidth == lineWidth): return self.mObjectLineWidth = lineWidth if (self.mMapDocument): self.mMapDocument.renderer().setObjectLineWidth(lineWidth) # Changing the line width can change the size of the object items if (not self.mObjectItems.isEmpty()): for item in self.mObjectItems: item[1].syncWithMapObject() self.update() def setShowTileObjectOutlines(self, enabled): if (self.mShowTileObjectOutlines == enabled): return self.mShowTileObjectOutlines = enabled if (self.mMapDocument): self.mMapDocument.renderer().setFlag(RenderFlag.ShowTileObjectOutlines, enabled) if (not self.mObjectItems.isEmpty()): self.update() ## # Sets whether the current layer should be highlighted. ## def setHighlightCurrentLayer(self, highlightCurrentLayer): if (self.mHighlightCurrentLayer == highlightCurrentLayer): return self.mHighlightCurrentLayer = highlightCurrentLayer self.updateCurrentLayerHighlight() ## # Refreshes the map scene. ## def refreshScene(self): self.mLayerItems.clear() self.mObjectItems.clear() self.removeItem(self.mDarkRectangle) self.clear() self.addItem(self.mDarkRectangle) if (not self.mMapDocument): self.setSceneRect(QRectF()) return self.updateSceneRect() map = self.mMapDocument.map() self.mLayerItems.resize(map.layerCount()) if (map.backgroundColor().isValid()): self.setBackgroundBrush(map.backgroundColor()) else: self.setBackgroundBrush(self.mDefaultBackgroundColor) layerIndex = 0 for layer in map.layers(): layerItem = self.createLayerItem(layer) layerItem.setZValue(layerIndex) self.addItem(layerItem) self.mLayerItems[layerIndex] = layerItem layerIndex += 1 tileSelectionItem = TileSelectionItem(self.mMapDocument) tileSelectionItem.setZValue(10000 - 2) self.addItem(tileSelectionItem) self.mObjectSelectionItem = ObjectSelectionItem(self.mMapDocument) self.mObjectSelectionItem.setZValue(10000 - 1) self.addItem(self.mObjectSelectionItem) self.updateCurrentLayerHighlight() ## # Repaints the specified region. The region is in tile coordinates. ## def repaintRegion(self, region, layer): renderer = self.mMapDocument.renderer() margins = self.mMapDocument.map().drawMargins() for r in region.rects(): boundingRect = QRectF(renderer.boundingRect(r)) self.update(QRectF(renderer.boundingRect(r).adjusted(-margins.left(), -margins.top(), margins.right(), margins.bottom()))) boundingRect.translate(layer.offset()) self.update(boundingRect) def currentLayerIndexChanged(self): self.updateCurrentLayerHighlight() # New layer may have a different offset, affecting the grid if self.mGridVisible: self.update() ## # Adapts the scene, layers and objects to new map size, orientation or # background color. ## def mapChanged(self): self.updateSceneRect() for item in self.mLayerItems: tli = item if type(tli) == TileLayerItem: tli.syncWithTileLayer() for item in self.mObjectItems.values(): item.syncWithMapObject() map = self.mMapDocument.map() if (map.backgroundColor().isValid()): self.setBackgroundBrush(map.backgroundColor()) else: self.setBackgroundBrush(self.mDefaultBackgroundColor) def tilesetChanged(self, tileset): if (not self.mMapDocument): return if (contains(self.mMapDocument.map().tilesets(), tileset)): self.update() def tileLayerDrawMarginsChanged(self, tileLayer): index = self.mMapDocument.map().layers().indexOf(tileLayer) item = self.mLayerItems.at(index) item.syncWithTileLayer() def layerAdded(self, index): layer = self.mMapDocument.map().layerAt(index) layerItem = self.createLayerItem(layer) self.addItem(layerItem) self.mLayerItems.insert(index, layerItem) z = 0 for item in self.mLayerItems: item.setZValue(z) z += 1 def layerRemoved(self, index): self.mLayerItems.remove(index) ## # A layer has changed. This can mean that the layer visibility, opacity or # offset changed. ## def layerChanged(self, index): layer = self.mMapDocument.map().layerAt(index) layerItem = self.mLayerItems.at(index) layerItem.setVisible(layer.isVisible()) multiplier = 1 if (self.mHighlightCurrentLayer and self.mMapDocument.currentLayerIndex() < index): multiplier = opacityFactor layerItem.setOpacity(layer.opacity() * multiplier) layerItem.setPos(layer.offset()) # Layer offset may have changed, affecting the scene rect and grid self.updateSceneRect() if self.mGridVisible: self.update() ## # When an object group has changed it may mean its color or drawing order # changed, which affects all its objects. ## def objectGroupChanged(self, objectGroup): self.objectsChanged(objectGroup.objects()) self.objectsIndexChanged(objectGroup, 0, objectGroup.objectCount() - 1) ## # When an image layer has changed, it may change size and it may look # differently. ## def imageLayerChanged(self, imageLayer): index = self.mMapDocument.map().layers().indexOf(imageLayer) item = self.mLayerItems.at(index) item.syncWithImageLayer() item.update() ## # When the tile offset of a tileset has changed, it can affect the bounding # rect of all tile layers and tile objects. It also requires a full repaint. ## def tilesetTileOffsetChanged(self, tileset): self.update() for item in self.mLayerItems: tli = item if type(tli) == TileLayerItem: tli.syncWithTileLayer() for item in self.mObjectItems: cell = item.mapObject().cell() if (not cell.isEmpty() and cell.tile.tileset() == tileset): item.syncWithMapObject() ## # Inserts map object items for the given objects. ## def objectsInserted(self, objectGroup, first, last): ogItem = None # Find the object group item for the object group for item in self.mLayerItems: ogi = item if type(ogi)==ObjectGroupItem: if (ogi.objectGroup() == objectGroup): ogItem = ogi break drawOrder = objectGroup.drawOrder() for i in range(first, last+1): object = objectGroup.objectAt(i) item = MapObjectItem(object, self.mMapDocument, ogItem) if (drawOrder == ObjectGroup.DrawOrder.TopDownOrder): item.setZValue(item.y()) else: item.setZValue(i) self.mObjectItems.insert(object, item) ## # Removes the map object items related to the given objects. ## def objectsRemoved(self, objects): for o in objects: i = self.mObjectItems.find(o) self.mSelectedObjectItems.remove(i) # python would not force delete QGraphicsItem self.removeItem(i) self.mObjectItems.erase(o) ## # Updates the map object items related to the given objects. ## def objectsChanged(self, objects): for object in objects: item = self.itemForObject(object) item.syncWithMapObject() ## # Updates the Z value of the objects when appropriate. ## def objectsIndexChanged(self, objectGroup, first, last): if (objectGroup.drawOrder() != ObjectGroup.DrawOrder.IndexOrder): return for i in range(first, last+1): item = self.itemForObject(objectGroup.objectAt(i)) item.setZValue(i) def updateSelectedObjectItems(self): objects = self.mMapDocument.selectedObjects() items = QSet() for object in objects: item = self.itemForObject(object) if item: items.insert(item) self.mSelectedObjectItems = items self.selectedObjectItemsChanged.emit() def syncAllObjectItems(self): for item in self.mObjectItems: item.syncWithMapObject() def createLayerItem(self, layer): layerItem = None tl = layer.asTileLayer() if tl: layerItem = TileLayerItem(tl, self.mMapDocument) else: og = layer.asObjectGroup() if og: drawOrder = og.drawOrder() ogItem = ObjectGroupItem(og) objectIndex = 0 for object in og.objects(): item = MapObjectItem(object, self.mMapDocument, ogItem) if (drawOrder == ObjectGroup.DrawOrder.TopDownOrder): item.setZValue(item.y()) else: item.setZValue(objectIndex) self.mObjectItems.insert(object, item) objectIndex += 1 layerItem = ogItem else: il = layer.asImageLayer() if il: layerItem = ImageLayerItem(il, self.mMapDocument) layerItem.setVisible(layer.isVisible()) return layerItem def updateSceneRect(self): mapSize = self.mMapDocument.renderer().mapSize() sceneRect = QRectF(0, 0, mapSize.width(), mapSize.height()) margins = self.mMapDocument.map().computeLayerOffsetMargins() sceneRect.adjust(-margins.left(), -margins.top(), margins.right(), margins.bottom()) self.setSceneRect(sceneRect) self.mDarkRectangle.setRect(sceneRect) def updateCurrentLayerHighlight(self): if (not self.mMapDocument): return currentLayerIndex = self.mMapDocument.currentLayerIndex() if (not self.mHighlightCurrentLayer or currentLayerIndex == -1): self.mDarkRectangle.setVisible(False) # Restore opacity for all layers for i in range(self.mLayerItems.size()): layer = self.mMapDocument.map().layerAt(i) self.mLayerItems.at(i).setOpacity(layer.opacity()) return # Darken layers below the current layer self.mDarkRectangle.setZValue(currentLayerIndex - 0.5) self.mDarkRectangle.setVisible(True) # Set layers above the current layer to half opacity for i in range(1, self.mLayerItems.size()): layer = self.mMapDocument.map().layerAt(i) if currentLayerIndex < i: _x = opacityFactor else: _x = 1 multiplier = _x self.mLayerItems.at(i).setOpacity(layer.opacity() * multiplier) def eventFilter(self, object, event): x = event.type() if x==QEvent.KeyPress or x==QEvent.KeyRelease: keyEvent = event newModifiers = keyEvent.modifiers() if (self.mActiveTool and newModifiers != self.mCurrentModifiers): self.mActiveTool.modifiersChanged(newModifiers) self.mCurrentModifiers = newModifiers else: pass return False
class ForcedXoverNode3(QGraphicsRectItem): """ This is a QGraphicsRectItem to allow actions and also a QGraphicsSimpleTextItem to allow a label to be drawn Attributes: is_forward (TYPE): Description """ def __init__(self, virtual_helix_item, xover_item, strand3p, idx): """Summary Args: virtual_helix_item (cadnano.gui.views.pathview.virtualhelixitem.VirtualHelixItem): from vhi xover_item (TYPE): Description strand3p (Strand): reference to the 3' strand idx (int): the base index within the virtual helix """ super(ForcedXoverNode3, self).__init__(virtual_helix_item) self._vhi = virtual_helix_item self._xover_item = xover_item self._idx = idx self.is_forward = strand3p.strandSet().isForward() self._is_on_top = self.is_forward self._partner_virtual_helix = virtual_helix_item self._blank_thing = QGraphicsRectItem(_blankRect, self) self._blank_thing.setBrush(QBrush(Qt.white)) self._path_thing = QGraphicsPathItem(self) self.configurePath() self._label = None self.setPen(_NO_PEN) self.setBrush(_NO_BRUSH) self.setRect(_rect) self.setZValue(styles.ZENDPOINTITEM + 1) # end def def updateForFloatFromVHI(self, virtual_helix_item, is_forward, idx_x, idx_y): """ Args: virtual_helix_item (cadnano.gui.views.pathview.virtualhelixitem.VirtualHelixItem): Description is_forward (TYPE): Description idx_x (TYPE): Description idx_y (TYPE): Description """ self._vhi = virtual_helix_item self.setParentItem(virtual_helix_item) self._idx = idx_x self._is_on_top = self.is_forward = True if is_forward else False self.updatePositionAndAppearance(is_from_strand=False) # end def def updateForFloatFromStrand(self, virtual_helix_item, strand3p, idx): """ Args: virtual_helix_item (cadnano.gui.views.pathview.virtualhelixitem.VirtualHelixItem): Description strand3p (Strand): reference to the 3' strand idx (int): the base index within the virtual helix """ self._vhi = virtual_helix_item self._strand = strand3p self.setParentItem(virtual_helix_item) self._idx = idx self._is_on_top = self.is_forward = strand3p.strandSet().isForward() self.updatePositionAndAppearance() # end def def configurePath(self): """Summary Returns: TYPE: Description """ self._path_thing.setBrush(getBrushObj(_PENCIL_COLOR)) path = PPR3 if self.is_forward else PPL3 offset = -_BASE_WIDTH if self.is_forward else _BASE_WIDTH self._path_thing.setPath(path) self._path_thing.setPos(offset, 0) offset = -_BASE_WIDTH if self.is_forward else 0 self._blank_thing.setPos(offset, 0) self._blank_thing.show() self._path_thing.show() # end def def refreshXover(self): """Summary Returns: TYPE: Description """ self._xover_item.refreshXover() # end def def setPartnerVirtualHelix(self, virtual_helix_item): """Summary Args: virtual_helix_item (cadnano.gui.views.pathview.virtualhelixitem.VirtualHelixItem): Description Returns: TYPE: Description """ self._partner_virtual_helix = virtual_helix_item # end def def idx(self): """Summary Returns: TYPE: Description """ return self._idx # end def def virtualHelixItem(self): """Summary Returns: TYPE: Description """ return self._vhi # end def def point(self): """Summary Returns: TYPE: Description """ return self._vhi.upperLeftCornerOfBaseType(self._idx, self.is_forward) # end def def floatPoint(self): """Summary Returns: TYPE: Description """ pt = self.pos() return pt.x(), pt.y() # end def def isForward(self): """Summary Returns: TYPE: Description """ return self.is_forward # end def def updatePositionAndAppearance(self, is_from_strand=True): """ Sets position by asking the VirtualHelixItem Sets appearance by choosing among pre-defined painterpaths (from normalstrandgraphicsitem) depending on drawing direction. Args: is_from_strand (bool, optional): Description """ self.setPos(*self.point()) n5 = self._xover_item._node5 if is_from_strand: from_strand, from_idx = (n5._strand, n5._idx) if n5 != self else (None, None) if self._strand.canInstallXoverAt(self._idx, from_strand, from_idx): self.configurePath() # We can only expose a 5' end. But on which side? is_left = True if self.is_forward else False self._updateLabel(is_left) else: self.hideItems() else: self.hideItems() # end def def remove(self): """Clean up this joint """ scene = self.scene() scene.removeItem(self._label) self._label = None scene.removeItem(self._path_thing) self._path_thing = None scene.removeItem(self._blank_thing) self._blank_thing = None scene.removeItem(self) # end def def _updateLabel(self, is_left): """Called by updatePositionAndAppearance during init. Updates drawing and position of the label. Args: is_left (TYPE): Description """ lbl = self._label if self._idx is not None: bw = _BASE_WIDTH num = self._partner_virtual_helix.idNum() tBR = _FM.tightBoundingRect(str(num)) half_label_h = tBR.height()/2.0 half_label_w = tBR.width()/2.0 # determine x and y positions label_x = bw/2.0 - half_label_w if self._is_on_top: label_y = -0.25*half_label_h - 0.5 - 0.5*bw else: label_y = 2*half_label_h + 0.5 + 0.5*bw # adjust x for left vs right label_x_offset = 0.25*bw if is_left else -0.25*bw label_x += label_x_offset # adjust x for numeral 1 if num == 1: label_x -= half_label_w/2.0 # create text item if lbl is None: lbl = QGraphicsSimpleTextItem(str(num), self) lbl.setPos(label_x, label_y) lbl.setBrush(_ENAB_BRUSH) lbl.setFont(_TO_HELIX_NUM_FONT) self._label = lbl lbl.setText(str(self._partner_virtual_helix.idNum())) lbl.show() # end if # end def def hideItems(self): """Summary Returns: TYPE: Description """ if self._label: self._label.hide() if self._blank_thing: self._path_thing.hide() if self._blank_thing: self._blank_thing.hide()
class PianoRoll(QGraphicsScene): '''the piano roll''' midievent = pyqtSignal(list) measureupdate = pyqtSignal(int) modeupdate = pyqtSignal(str) def __init__(self, time_sig = '4/4', num_measures = 4, quantize_val = '1/8'): QGraphicsScene.__init__(self) self.setBackgroundBrush(QColor(50, 50, 50)) self.mousePos = QPointF() self.notes = [] self.selected_notes = [] self.piano_keys = [] self.marquee_select = False self.insert_mode = False self.velocity_mode = False self.place_ghost = False self.ghost_note = None self.default_ghost_vel = 100 self.ghost_vel = self.default_ghost_vel ## dimensions self.padding = 2 ## piano dimensions self.note_height = 10 self.start_octave = -2 self.end_octave = 8 self.notes_in_octave = 12 self.total_notes = (self.end_octave - self.start_octave) \ * self.notes_in_octave + 1 self.piano_height = self.note_height * self.total_notes self.octave_height = self.notes_in_octave * self.note_height self.piano_width = 34 ## height self.header_height = 20 self.total_height = self.piano_height - self.note_height + self.header_height #not sure why note_height is subtracted ## width self.full_note_width = 250 # i.e. a 4/4 note self.snap_value = None self.quantize_val = quantize_val ### dummy vars that will be changed self.time_sig = 0 self.measure_width = 0 self.num_measures = 0 self.max_note_length = 0 self.grid_width = 0 self.value_width = 0 self.grid_div = 0 self.piano = None self.header = None self.play_head = None self.setTimeSig(time_sig) self.setMeasures(num_measures) self.setGridDiv() self.default_length = 1. / self.grid_div # ------------------------------------------------------------------------- # Callbacks def movePlayHead(self, transport_info): # TODO: need conversion between frames and PPQ x = 105. # works for 120bpm total_duration = self.time_sig[0] * self.num_measures * x pos = transport_info['frame'] / x frac = (pos % total_duration) / total_duration self.play_head.setPos(QPointF(frac * self.grid_width, 0)) def setTimeSig(self, time_sig): try: new_time_sig = list(map(float, time_sig.split('/'))) if len(new_time_sig)==2: self.time_sig = new_time_sig self.measure_width = self.full_note_width * self.time_sig[0]/self.time_sig[1] self.max_note_length = self.num_measures * self.time_sig[0]/self.time_sig[1] self.grid_width = self.measure_width * self.num_measures self.setGridDiv() except ValueError: pass def setMeasures(self, measures): try: self.num_measures = float(measures) self.max_note_length = self.num_measures * self.time_sig[0]/self.time_sig[1] self.grid_width = self.measure_width * self.num_measures self.refreshScene() except: pass def setDefaultLength(self, length): try: v = list(map(float, length.split('/'))) if len(v) < 3: self.default_length = \ v[0] if len(v)==1 else \ v[0] / v[1] pos = self.enforce_bounds(self.mousePos) if self.insert_mode: self.makeGhostNote(pos.x(), pos.y()) except ValueError: pass def setGridDiv(self, div=None): if not div: div = self.quantize_val try: val = list(map(int, div.split('/'))) if len(val) < 3: self.quantize_val = div self.grid_div = val[0] if len(val)==1 else val[1] self.value_width = self.full_note_width / float(self.grid_div) if self.grid_div else None self.setQuantize(div) self.refreshScene() except ValueError: pass def setQuantize(self, value): try: val = list(map(float, value.split('/'))) if len(val) == 1: self.quantize(val[0]) self.quantize_val = value elif len(val) == 2: self.quantize(val[0] / val[1]) self.quantize_val = value except ValueError: pass # ------------------------------------------------------------------------- # Event Callbacks def keyPressEvent(self, event): QGraphicsScene.keyPressEvent(self, event) if event.key() == Qt.Key_F: if not self.insert_mode: self.velocity_mode = False self.insert_mode = True self.makeGhostNote(self.mousePos.x(), self.mousePos.y()) self.modeupdate.emit('insert_mode') elif self.insert_mode: self.insert_mode = False if self.place_ghost: self.place_ghost = False self.removeItem(self.ghost_note) self.ghost_note = None self.modeupdate.emit('') elif event.key() == Qt.Key_D: if self.velocity_mode: self.velocity_mode = False self.modeupdate.emit('') else: if self.insert_mode: self.removeItem(self.ghost_note) self.ghost_note = None self.insert_mode = False self.place_ghost = False self.velocity_mode = True self.modeupdate.emit('velocity_mode') elif event.key() == Qt.Key_A: if all((note.isSelected() for note in self.notes)): for note in self.notes: note.setSelected(False) self.selected_notes = [] else: for note in self.notes: note.setSelected(True) self.selected_notes = self.notes[:] elif event.key() in (Qt.Key_Delete, Qt.Key_Backspace): self.notes = [note for note in self.notes if note not in self.selected_notes] for note in self.selected_notes: self.removeItem(note) self.midievent.emit(["midievent-remove", note.note[0], note.note[1], note.note[2], note.note[3]]) del note self.selected_notes = [] def mousePressEvent(self, event): QGraphicsScene.mousePressEvent(self, event) if not (any(key.pressed for key in self.piano_keys) or any(note.pressed for note in self.notes)): for note in self.selected_notes: note.setSelected(False) self.selected_notes = [] if event.button() == Qt.LeftButton: if self.insert_mode: self.place_ghost = True else: self.marquee_select = True self.marquee_rect = QRectF(event.scenePos().x(), event.scenePos().y(), 1, 1) self.marquee = QGraphicsRectItem(self.marquee_rect) self.marquee.setBrush(QColor(255, 255, 255, 100)) self.addItem(self.marquee) else: for s_note in self.notes: if s_note.pressed and s_note in self.selected_notes: break elif s_note.pressed and s_note not in self.selected_notes: for note in self.selected_notes: note.setSelected(False) self.selected_notes = [s_note] break for note in self.selected_notes: if not self.velocity_mode: note.mousePressEvent(event) def mouseMoveEvent(self, event): QGraphicsScene.mouseMoveEvent(self, event) self.mousePos = event.scenePos() if not (any((key.pressed for key in self.piano_keys))): m_pos = event.scenePos() if self.insert_mode and self.place_ghost: #placing a note m_width = self.ghost_rect.x() + self.ghost_rect_orig_width if m_pos.x() > m_width: m_new_x = self.snap(m_pos.x()) self.ghost_rect.setRight(m_new_x) self.ghost_note.setRect(self.ghost_rect) #self.adjust_note_vel(event) else: m_pos = self.enforce_bounds(m_pos) if self.insert_mode: #ghostnote follows mouse around (m_new_x, m_new_y) = self.snap(m_pos.x(), m_pos.y()) self.ghost_rect.moveTo(m_new_x, m_new_y) try: self.ghost_note.setRect(self.ghost_rect) except RuntimeError: self.ghost_note = None self.makeGhostNote(m_new_x, m_new_y) elif self.marquee_select: marquee_orig_pos = event.buttonDownScenePos(Qt.LeftButton) if marquee_orig_pos.x() < m_pos.x() and marquee_orig_pos.y() < m_pos.y(): self.marquee_rect.setBottomRight(m_pos) elif marquee_orig_pos.x() < m_pos.x() and marquee_orig_pos.y() > m_pos.y(): self.marquee_rect.setTopRight(m_pos) elif marquee_orig_pos.x() > m_pos.x() and marquee_orig_pos.y() < m_pos.y(): self.marquee_rect.setBottomLeft(m_pos) elif marquee_orig_pos.x() > m_pos.x() and marquee_orig_pos.y() > m_pos.y(): self.marquee_rect.setTopLeft(m_pos) self.marquee.setRect(self.marquee_rect) self.selected_notes = [] for item in self.collidingItems(self.marquee): if item in self.notes: self.selected_notes.append(item) for note in self.notes: if note in self.selected_notes: note.setSelected(True) else: note.setSelected(False) elif self.velocity_mode: if Qt.LeftButton == event.buttons(): for note in self.selected_notes: note.updateVelocity(event) elif not self.marquee_select: #move selected if Qt.LeftButton == event.buttons(): x = y = False if any(note.back.stretch for note in self.selected_notes): x = True elif any(note.front.stretch for note in self.selected_notes): y = True for note in self.selected_notes: note.back.stretch = x note.front.stretch = y note.moveEvent(event) def mouseReleaseEvent(self, event): if not (any((key.pressed for key in self.piano_keys)) or any((note.pressed for note in self.notes))): if event.button() == Qt.LeftButton: if self.place_ghost and self.insert_mode: self.place_ghost = False note_start = self.get_note_start_from_x(self.ghost_rect.x()) note_num = self.get_note_num_from_y(self.ghost_rect.y()) note_length = self.get_note_length_from_x(self.ghost_rect.width()) self.drawNote(note_num, note_start, note_length, self.ghost_vel) self.midievent.emit(["midievent-add", note_num, note_start, note_length, self.ghost_vel]) self.makeGhostNote(self.mousePos.x(), self.mousePos.y()) elif self.marquee_select: self.marquee_select = False self.removeItem(self.marquee) elif not self.marquee_select: for note in self.selected_notes: old_info = note.note[:] note.mouseReleaseEvent(event) if self.velocity_mode: note.setSelected(True) if not old_info == note.note: self.midievent.emit(["midievent-remove", old_info[0], old_info[1], old_info[2], old_info[3]]) self.midievent.emit(["midievent-add", note.note[0], note.note[1], note.note[2], note.note[3]]) # ------------------------------------------------------------------------- # Internal Functions def drawHeader(self): self.header = QGraphicsRectItem(0, 0, self.grid_width, self.header_height) #self.header.setZValue(1.0) self.header.setPos(self.piano_width, 0) self.addItem(self.header) def drawPiano(self): piano_keys_width = self.piano_width - self.padding labels = ('B','Bb','A','Ab','G','Gb','F','E','Eb','D','Db','C') black_notes = (2,4,6,9,11) piano_label = QFont() piano_label.setPointSize(6) self.piano = QGraphicsRectItem(0, 0, piano_keys_width, self.piano_height) self.piano.setPos(0, self.header_height) self.addItem(self.piano) key = PianoKeyItem(piano_keys_width, self.note_height, self.piano) label = QGraphicsSimpleTextItem('C8', key) label.setPos(18, 1) label.setFont(piano_label) key.setBrush(QColor(255, 255, 255)) for i in range(self.end_octave - self.start_octave, self.start_octave - self.start_octave, -1): for j in range(self.notes_in_octave, 0, -1): if j in black_notes: key = PianoKeyItem(piano_keys_width/1.4, self.note_height, self.piano) key.setBrush(QColor(0, 0, 0)) key.setZValue(1.0) key.setPos(0, self.note_height * j + self.octave_height * (i - 1)) elif (j - 1) and (j + 1) in black_notes: key = PianoKeyItem(piano_keys_width, self.note_height * 2, self.piano) key.setBrush(QColor(255, 255, 255)) key.setPos(0, self.note_height * j + self.octave_height * (i - 1) - self.note_height/2.) elif (j - 1) in black_notes: key = PianoKeyItem(piano_keys_width, self.note_height * 3./2, self.piano) key.setBrush(QColor(255, 255, 255)) key.setPos(0, self.note_height * j + self.octave_height * (i - 1) - self.note_height/2.) elif (j + 1) in black_notes: key = PianoKeyItem(piano_keys_width, self.note_height * 3./2, self.piano) key.setBrush(QColor(255, 255, 255)) key.setPos(0, self.note_height * j + self.octave_height * (i - 1)) if j == 12: label = QGraphicsSimpleTextItem('{}{}'.format(labels[j - 1], self.end_octave - i), key ) label.setPos(18, 6) label.setFont(piano_label) self.piano_keys.append(key) def drawGrid(self): black_notes = [2,4,6,9,11] scale_bar = QGraphicsRectItem(0, 0, self.grid_width, self.note_height, self.piano) scale_bar.setPos(self.piano_width, 0) scale_bar.setBrush(QColor(100,100,100)) clearpen = QPen(QColor(0,0,0,0)) for i in range(self.end_octave - self.start_octave, self.start_octave - self.start_octave, -1): for j in range(self.notes_in_octave, 0, -1): scale_bar = QGraphicsRectItem(0, 0, self.grid_width, self.note_height, self.piano) scale_bar.setPos(self.piano_width, self.note_height * j + self.octave_height * (i - 1)) scale_bar.setPen(clearpen) if j not in black_notes: scale_bar.setBrush(QColor(120,120,120)) else: scale_bar.setBrush(QColor(100,100,100)) measure_pen = QPen(QColor(0, 0, 0, 120), 3) half_measure_pen = QPen(QColor(0, 0, 0, 40), 2) line_pen = QPen(QColor(0, 0, 0, 40)) for i in range(0, int(self.num_measures) + 1): measure = QGraphicsLineItem(0, 0, 0, self.piano_height + self.header_height - measure_pen.width(), self.header) measure.setPos(self.measure_width * i, 0.5 * measure_pen.width()) measure.setPen(measure_pen) if i < self.num_measures: number = QGraphicsSimpleTextItem('%d' % (i + 1), self.header) number.setPos(self.measure_width * i + 5, 2) number.setBrush(Qt.white) for j in self.frange(0, self.time_sig[0]*self.grid_div/self.time_sig[1], 1.): line = QGraphicsLineItem(0, 0, 0, self.piano_height, self.header) line.setZValue(1.0) line.setPos(self.measure_width * i + self.value_width * j, self.header_height) if j == self.time_sig[0]*self.grid_div/self.time_sig[1] / 2.0: line.setPen(half_measure_pen) else: line.setPen(line_pen) def drawPlayHead(self): self.play_head = QGraphicsLineItem(self.piano_width, self.header_height, self.piano_width, self.total_height) self.play_head.setPen(QPen(QColor(255,255,255,50), 2)) self.play_head.setZValue(1.) self.addItem(self.play_head) def refreshScene(self): list(map(self.removeItem, self.notes)) self.selected_notes = [] self.piano_keys = [] self.clear() self.drawPiano() self.drawHeader() self.drawGrid() self.drawPlayHead() for note in self.notes[:]: if note.note[1] >= (self.num_measures * self.time_sig[0]): self.notes.remove(note) self.midievent.emit(["midievent-remove", note.note[0], note.note[1], note.note[2], note.note[3]]) elif note.note[2] > self.max_note_length: new_note = note.note[:] new_note[2] = self.max_note_length self.notes.remove(note) self.drawNote(new_note[0], new_note[1], self.max_note_length, new_note[3], False) self.midievent.emit(["midievent-remove", note.note[0], note.note[1], note.note[2], note.note[3]]) self.midievent.emit(["midievent-add", new_note[0], new_note[1], new_note[2], new_note[3]]) list(map(self.addItem, self.notes)) if self.views(): self.views()[0].setSceneRect(self.itemsBoundingRect()) def clearNotes(self): self.clear() self.notes = [] self.selected_notes = [] self.drawPiano() self.drawHeader() self.drawGrid() def makeGhostNote(self, pos_x, pos_y): """creates the ghostnote that is placed on the scene before the real one is.""" if self.ghost_note: self.removeItem(self.ghost_note) length = self.full_note_width * self.default_length (start, note) = self.snap(pos_x, pos_y) self.ghost_vel = self.default_ghost_vel self.ghost_rect = QRectF(start, note, length, self.note_height) self.ghost_rect_orig_width = self.ghost_rect.width() self.ghost_note = QGraphicsRectItem(self.ghost_rect) self.ghost_note.setBrush(QColor(230, 221, 45, 100)) self.addItem(self.ghost_note) def drawNote(self, note_num, note_start=None, note_length=None, note_velocity=None, add=True): """ note_num: midi number, 0 - 127 note_start: 0 - (num_measures * time_sig[0]) so this is in beats note_length: 0 - (num_measures * time_sig[0]/time_sig[1]) this is in measures note_velocity: 0 - 127 """ info = [note_num, note_start, note_length, note_velocity] if not note_start % (self.num_measures * self.time_sig[0]) == note_start: #self.midievent.emit(["midievent-remove", note_num, note_start, note_length, note_velocity]) while not note_start % (self.num_measures * self.time_sig[0]) == note_start: self.setMeasures(self.num_measures+1) self.measureupdate.emit(self.num_measures) self.refreshScene() x_start = self.get_note_x_start(note_start) if note_length > self.max_note_length: note_length = self.max_note_length + 0.25 x_length = self.get_note_x_length(note_length) y_pos = self.get_note_y_pos(note_num) note = NoteItem(self.note_height, x_length, info) note.setPos(x_start, y_pos) self.notes.append(note) if add: self.addItem(note) # ------------------------------------------------------------------------- # Helper Functions def frange(self, x, y, t): while x < y: yield x x += t def quantize(self, value): self.snap_value = float(self.full_note_width) * value if value else None def snap(self, pos_x, pos_y = None): if self.snap_value: pos_x = int(round((pos_x - self.piano_width) / self.snap_value)) \ * self.snap_value + self.piano_width if pos_y: pos_y = int((pos_y - self.header_height) / self.note_height) \ * self.note_height + self.header_height return (pos_x, pos_y) if pos_y else pos_x def adjust_note_vel(self, event): m_pos = event.scenePos() #bind velocity to vertical mouse movement self.ghost_vel += (event.lastScenePos().y() - m_pos.y())/10 if self.ghost_vel < 0: self.ghost_vel = 0 elif self.ghost_vel > 127: self.ghost_vel = 127 m_width = self.ghost_rect.x() + self.ghost_rect_orig_width if m_pos.x() < m_width: m_pos.setX(m_width) m_new_x = self.snap(m_pos.x()) self.ghost_rect.setRight(m_new_x) self.ghost_note.setRect(self.ghost_rect) def enforce_bounds(self, pos): if pos.x() < self.piano_width: pos.setX(self.piano_width) elif pos.x() > self.grid_width + self.piano_width: pos.setX(self.grid_width + self.piano_width) if pos.y() < self.header_height + self.padding: pos.setY(self.header_height + self.padding) return pos def get_note_start_from_x(self, note_x): return (note_x - self.piano_width) / (self.grid_width / self.num_measures / self.time_sig[0]) def get_note_x_start(self, note_start): return self.piano_width + \ (self.grid_width / self.num_measures / self.time_sig[0]) * note_start def get_note_x_length(self, note_length): return float(self.time_sig[1]) / self.time_sig[0] * note_length * self.grid_width / self.num_measures def get_note_length_from_x(self, note_x): return float(self.time_sig[0]) / self.time_sig[1] * self.num_measures / self.grid_width \ * note_x def get_note_y_pos(self, note_num): return self.header_height + self.note_height * (self.total_notes - note_num - 1) def get_note_num_from_y(self, note_y_pos): return -(((note_y_pos - self.header_height) / self.note_height) - self.total_notes + 1)
class NodeItem(QGraphicsItem): def __init__ (self, nodeobj, parent=None, view=None, state=1): super().__init__() self.edge = None self.linkIDs = None self.children = None self.childpos = None self.nodeobj = nodeobj self.style = FlGlob.mainwindow.style self.view = weakref.proxy(view) self.refID = parent.realid() if parent is not None else None self.state = state self.setrank(parent) self.setCursor(Qt.ArrowCursor) self.yoffset = 0 self.graphicsetup() self.setstate(state) def id (self): return (self.refID, self.nodeobj.ID) def realid (self): return self.nodeobj.ID def childlist (self, generate=False): ID = self.nodeobj.ID itemtable = self.view.itemtable if self.state == 1 and ID in itemtable and not self.iscollapsed(): if self.children and self.nodeobj.linkIDs == self.linkIDs and None not in [c() for c in self.children]: ret = self.children else: children = [] for child in self.nodeobj.linkIDs: if child in itemtable[ID]: item = itemtable[ID][child] else: continue children.append(weakref.ref(item)) self.linkIDs = self.nodeobj.linkIDs.copy() self.children = children ret = children else: ret = [] if generate: x = self.x() y = self.y() self.childpos = [] for target in ret: t = target() self.childpos.append((t.x()+t.boundingRect().left()-self.style.activemargin-x, t.y()-y)) if self.edge: if self.childpos != self.edge.childpos: self.edge.prepareGeometryChange() self.edge.sourceright = self.boundingRect().right() self.edge.update(self.edge.boundingRect()) return ret def setedge (self, edge): self.edge = edge edge.setX(self.x()) def setactive (self, active): if active: self.activebox.show() self.mainbox.setBrush(QBrush(self.altcolor)) else: self.activebox.hide() self.mainbox.setBrush(QBrush(self.maincolor)) def setselected (self, selected): if selected: self.selectbox.show() else: self.selectbox.hide() def setstate (self, state): self.state = state if state == 1: # normal self.show() self.graphgroup.setOpacity(1) self.shadowbox.show() elif state == 0: # ghost self.show() self.graphgroup.setOpacity(0.7) self.shadowbox.hide() elif state == -1: # hidden self.hide() def setplaymode (self, playmode): if playmode: self.setOpacity(0.5) else: self.setOpacity(1) def setY (self, y): parent = self.view.itembyID(self.refID) y += self.getyoffset() if self.edge is not None: self.edge.setY(y) super().setY(y) def setrank (self, parent): if parent is None: return if self.issubnode(): x = parent.x() self.setX(x) else: x = parent.x()+self.style.rankwidth self.setX(x) self.nudgechildren() if self.edge is not None: self.edge.setX(x) def nudgechildren (self): for child in self.childlist(): child().setrank(self) def getyoffset (self): if self.nodeobj.nodebank == -1: return self.yoffset else: return self.view.itembyID(self.refID).getyoffset() + self.yoffset def hide (self): super().hide() if self.edge: self.edge.hide() def show (self): super().show() if self.edge: self.edge.show() def issubnode (self): return self.nodeobj.nodebank is not -1 def isghost (self): return not self.state def realnode (self): return self.view.itembyID(self.nodeobj.ID) def isactive (self): return self.view.activenode is self def isselected (self): return self.view.selectednode is self def iscollapsed (self): return self.id() in self.view.collapsednodes def y_top (self): return self.y() - self.boundingRect().height()//2 def y_bottom (self): return self.y() + self.boundingRect().height()//2 def bulkshift (self, children, diff): self.setY(self.y() + diff) if children is None: children = [c() for c in self.childlist()] for child in children: child.bulkshift(None, diff) def treeposition (self, ranks=None): if ranks is None: ranks = dict() localranks = dict() children = [c() for c in self.childlist()] for child in children: localranks = child.treeposition(localranks) rank = self.x() // self.style.rankwidth if children: top = children[0].y_top() bottom = children[-1].y_bottom() self.setY((top+bottom)//2) localranks[rank] = [self.y_top, self.y_bottom] streeshift = None for r in localranks: if r in ranks: rankshift = ranks[r][1]() + self.style.rowgap - localranks[r][0]() if streeshift is None or rankshift > streeshift: streeshift = rankshift ranks[r][1] = localranks[r][1] else: ranks[r] = localranks[r] if streeshift: self.bulkshift(children, streeshift) return ranks def siblings (self): if self.refID is None: return None parent = self.view.nodecontainer.nodes[self.refID] if self.issubnode(): return parent.subnodes else: return parent.linkIDs def siblingabove (self): sibs = self.siblings() if sibs is None or self.nodeobj.ID not in sibs: return None myindex = sibs.index(self.nodeobj.ID) if myindex: sibID = (self.refID, sibs[myindex-1]) return self.view.itembyfullID(sibID) else: return None def siblingbelow (self): sibs = self.siblings() if sibs is None or self.nodeobj.ID not in sibs: return None myindex = sibs.index(self.nodeobj.ID) if len(sibs) > myindex+1: sibID = (self.refID, sibs[myindex+1]) return self.view.itembyfullID(sibID) else: return None def subtreesize (self, depth=-1): """Find vertical extents of a subtree. Returns min/max y coordinates up to given depth (negative depth means whole subtree).""" # calculate child positions for EgdeItem only once when calculating scenerect if depth<0: generate = True else: generate = False children = [c() for c in self.childlist(generate=generate)] maxdepth = abs(depth) if children and depth: nextdepth = depth-1 ymin = self.y_top() ymax = self.y_bottom() for child in children: top, bottom, depth = child.subtreesize(nextdepth) ymin = min(ymin, top) ymax = max(ymax, bottom) maxdepth = max(maxdepth, depth) else: ymin = self.y_top() ymax = self.y_bottom() return ymin, ymax, maxdepth def boundingRect (self): return self.rect def paint (self, painter, style, widget): pass def pixmap (self, path): return QPixmap(path).scaledToWidth(self.style.boldheight, Qt.SmoothTransformation) def graphicsetup (self): lightbrush = QBrush(FlPalette.light) mainbrush = QBrush(self.maincolor) altbrush = QBrush(self.altcolor) nopen = QPen(0) viewport = self.view.viewport() self.graphgroup = QGraphicsItemGroup(self) self.fggroup = QGraphicsItemGroup(self) self.shadowbox = QGraphicsRectItem(self) self.shadowbox.setCacheMode(QGraphicsItem.DeviceCoordinateCache) self.shadowbox.setBrush(FlPalette.dark) self.shadowbox.setPen(nopen) self.shadowbox.setPos(*(self.style.shadowoffset,)*2) self.graphgroup.addToGroup(self.shadowbox) self.activebox = QGraphicsRectItem(self) self.activebox.setCacheMode(QGraphicsItem.DeviceCoordinateCache) activepen = QPen(self.maincolor, self.style.selectmargin, join=Qt.MiterJoin) self.activebox.setPen(activepen) self.activebox.hide() self.graphgroup.addToGroup(self.activebox) self.selectbox = QGraphicsRectItem(self) self.selectbox.setCacheMode(QGraphicsItem.DeviceCoordinateCache) selectpen = QPen(FlPalette.light, self.style.selectmargin, join=Qt.MiterJoin) self.selectbox.setPen(selectpen) self.selectbox.hide() self.graphgroup.addToGroup(self.selectbox) self.mainbox = QGraphicsRectItem(self) self.mainbox.setCacheMode(QGraphicsItem.DeviceCoordinateCache) self.mainbox.setBrush(mainbrush) self.mainbox.setPen(nopen) self.graphgroup.addToGroup(self.mainbox) self.nodelabel = QGraphicsSimpleTextItemCond(self, viewport) self.nodelabel.setBrush(lightbrush) self.nodelabel.setFont(self.style.boldfont) self.nodelabel.setText(self.label % self.realid()) self.nodelabel.setPos(self.style.itemmargin, self.style.itemmargin) self.fggroup.addToGroup(self.nodelabel) self.icon = self.pixmap("images/blank.png") self.iwidth = self.icon.width() self.iconx = self.style.nodetextwidth self.condicon = QGraphicsPixmapItemCond(self.icon, self, viewport) self.condicon.setPos(self.iconx-self.iwidth, self.style.itemmargin) self.iconx = self.condicon.x() self.fggroup.addToGroup(self.condicon) self.randicon = QGraphicsPixmapItemCond(self.icon, self, viewport) self.randicon.setPos(self.iconx-self.style.itemmargin-self.iwidth, self.style.itemmargin) self.iconx = self.randicon.x() self.fggroup.addToGroup(self.randicon) self.exiticon = QGraphicsPixmapItemCond(self.icon, self, viewport) self.exiticon.setPos(self.iconx-self.style.itemmargin-self.iwidth, self.style.itemmargin) self.iconx = self.exiticon.x() self.fggroup.addToGroup(self.exiticon) self.entericon = QGraphicsPixmapItemCond(self.icon, self, viewport) self.entericon.setPos(self.iconx-self.style.itemmargin-self.iwidth, self.style.itemmargin) self.iconx = self.entericon.x() self.fggroup.addToGroup(self.entericon) self.persisticon = QGraphicsPixmapItemCond(self.icon, self, viewport) self.persisticon.setPos(self.iconx-self.style.itemmargin-self.iwidth, self.style.itemmargin) self.iconx = self.persisticon.x() self.fggroup.addToGroup(self.persisticon) self.comment = QGraphicsTextItemCond(self, viewport) self.comment.setTextWidth(self.style.nodetextwidth) self.comment.setDefaultTextColor(FlPalette.light) self.comment.setPos(0, self.nodelabel.y()+self.nodelabel.boundingRect().height()+self.style.itemmargin) self.fggroup.addToGroup(self.comment) self.graphgroup.addToGroup(self.fggroup) self.view.nodedocs[self.realid()]["comment"].contentsChanged.connect(self.updatecomment) self.updatecondition() self.updateenterscripts() self.updateexitscripts() self.updaterandweight() self.updatepersistence() # Never call updatelayout() from here (or any inheritable reimplementation)! def collapse (self, collapse): for item in self.fggroup.childItems(): if item is not self.nodelabel: if collapse: item.hide() else: item.show() self.updatelayout() def updatecondition (self): icons = {True: "key", False: "blank"} pixmap = self.pixmap("images/%s.png" % icons[self.nodeobj.hascond()]) self.condicon.setPixmap(pixmap) if self.nodeobj.hascond(): self.condicon.setToolTip("Condition") else: self.condicon.setToolTip("") def updateenterscripts (self): icons = {True: "script-enter", False: "blank"} pixmap = self.pixmap("images/%s.png" % icons[self.nodeobj.hasenterscripts()]) self.entericon.setPixmap(pixmap) if self.nodeobj.hasenterscripts(): self.entericon.setToolTip("Enter Scripts") else: self.entericon.setToolTip("") def updateexitscripts (self): icons = {True: "script-exit", False: "blank"} pixmap = self.pixmap("images/%s.png" % icons[self.nodeobj.hasexitscripts()]) self.exiticon.setPixmap(pixmap) if self.nodeobj.hasexitscripts(): self.exiticon.setToolTip("Exit Scripts") else: self.exiticon.setToolTip("") def updaterandweight (self): icons = {True: "dice", False: "blank"} pixmap = self.pixmap("images/%s.png" % icons[bool(self.nodeobj.randweight)]) self.randicon.setPixmap(pixmap) if self.nodeobj.randweight: self.randicon.setToolTip("Random Weight: %s" % self.nodeobj.randweight) else: self.randicon.setToolTip("") def updatepersistence (self): icons = {"Mark": "mark", "OncePerConv": "once", "OnceEver": "onceever", "": "blank"} pixmap = self.pixmap("images/%s.png" % icons[self.nodeobj.persistence]) self.persisticon.setPixmap(pixmap) if self.nodeobj.persistence: self.persisticon.setToolTip("Persistence: %s" % self.nodeobj.persistence) else: self.persisticon.setToolTip("") def updatecomment (self): self.fggroup.removeFromGroup(self.comment) contents = self.view.nodedocs[self.realid()]["comment"].toPlainText() if not contents: self.comment.hide() else: self.comment.show() self.comment.setPlainText(contents) self.fggroup.addToGroup(self.comment) self.updatelayout() def updatelayout (self): if self.iscollapsed(): rect = self.nodelabel.mapRectToParent(self.nodelabel.boundingRect()) else: rect = self.fggroup.childrenBoundingRect() mainrect = rect.marginsAdded(self.style.nodemargins) self.mainbox.setRect(mainrect) self.shadowbox.setRect(mainrect) self.selectbox.setRect(mainrect.marginsAdded(self.style.selectmargins)) activerect = mainrect.marginsAdded(self.style.activemargins) self.activebox.setRect(activerect) self.graphgroup.setPos(-activerect.width()//2-activerect.x(), -activerect.height()//2-activerect.y()) self.prepareGeometryChange() self.rect = self.graphgroup.mapRectToParent(mainrect) self.view.updatelayout() def mouseDoubleClickEvent (self, event): super().mouseDoubleClickEvent(event) event.accept() if event.button() == Qt.LeftButton: self.view.setactivenode(self) def mousePressEvent (self, event): super().mousePressEvent(event) if event.button() & (Qt.LeftButton | Qt.RightButton) : self.view.setselectednode(self) event.accept() def __repr__ (self): return "<%s %s>" % (type(self).__name__, self.id())
def updateLine(self): if self.points is not None: diameter = 2*self.radius rect = QRectF(-self.radius, -self.radius, diameter, diameter) if self.itemPos is not None: # TODO: NaNの時のEllipseItemの挙動を考える point = self.points[self.itemPos] if not isinstance(self.item, self.itemType): print("call") scene = self.scene() if scene is not None: scene.removeItem(self.item) self.item = self.itemType(self) self.item.setZValue(10) self.item.setBrush(self.color) self.item.setRect(rect) self.setItemIsMovable(self.isItemMovable) elif self.drawItemFlag: self.item.show() self.item.setPos(*point) self.item.mouseMoveEvent = self.generateItemMouseMoveEvent(self.item, point) self.item.mousePressEvent = self.generateItemMousePressEvent(self.item, point) self.textItem.setPos(*point) prev_range = range(self.itemPos, -1, -self.markDelta)[1:] next_range = range(self.itemPos, len(self.points), self.markDelta)[1:] num_mark = len(prev_range) + len(next_range) rect_half = QRectF(-self.radius/2, -self.radius/2, diameter/2, diameter/2) while num_mark < len(self.markItemList) and len(self.markItemList)!=0: markItem = self.markItemList.pop() markTextItem = self.markTextItemList.pop() scene = self.scene() if scene is not None: scene.removeItem(markItem) scene.removeItem(markTextItem) current_path = os.path.dirname(os.path.realpath(__file__)) while len(self.markItemList) < num_mark: # TODO: 目盛りを矢印に. # markItem = QGraphicsSvgItem(os.path.join(current_path, "svg", "small_arrow.svg"), self) markItem = QGraphicsRectItem(self) markItem.setBrush(Qt.black) markItem.setRect(rect_half) markItem.setZValue(9) # markItem.setFlags(QGraphicsItem.ItemIgnoresParentOpacity) # markItem.setOpacity(1) # print(markItem.boundingRect()) # xlate = markItem.boundingRect().center() # t = QTransform() # # t.translate(xlate.x(), xlate.y()) # t.rotate(90) # t.scale(0.03, 0.03) # # t.translate(-xlate.x(), -xlate.y()) # markItem.setTransform(t) self.markItemList.append(markItem) markTextItem = GraphicsTextItemWithBackground(self) markTextItem.setBackgroundColor(Qt.black) markTextItem.setDefaultTextColor(Qt.white) self.markTextItemList.append(markTextItem) for markItem, markTextItem, index in zip(self.markItemList, self.markTextItemList, chain(prev_range, next_range)): markItem.setPos(*self.points[index]) markTextItem.setPos(*self.points[index]) markTextItem.setPlainText(str(int((index-self.itemPos)/self.markDelta))) if self.drawMarkItemFlag: markItem.show() markTextItem.show() else: markItem.hide() markTextItem.hide() else: self.item.hide() self.textItem.hide() for item, textItem in zip(self.markItemList, self.markTextItemList): item.hide() textItem.hide() self.update()
class SvgView(QGraphicsView): Native, OpenGL, Image = range(3) def __init__(self, parent=None): super(SvgView, self).__init__(parent) self.renderer = SvgView.Native self.svgItem = None self.backgroundItem = None self.outlineItem = None self.image = QImage() self.setScene(QGraphicsScene(self)) self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setDragMode(QGraphicsView.ScrollHandDrag) self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate) # Prepare background check-board pattern. tilePixmap = QPixmap(64, 64) tilePixmap.fill(Qt.white) tilePainter = QPainter(tilePixmap) color = QColor(220, 220, 220) tilePainter.fillRect(0, 0, 32, 32, color) tilePainter.fillRect(32, 32, 32, 32, color) tilePainter.end() self.setBackgroundBrush(QBrush(tilePixmap)) def drawBackground(self, p, rect): p.save() p.resetTransform() p.drawTiledPixmap(self.viewport().rect(), self.backgroundBrush().texture()) p.restore() def openFile(self, svg_file): if not svg_file.exists(): return s = self.scene() if self.backgroundItem: drawBackground = self.backgroundItem.isVisible() else: drawBackground = False if self.outlineItem: drawOutline = self.outlineItem.isVisible() else: drawOutline = True s.clear() self.resetTransform() self.svgItem = QGraphicsSvgItem(svg_file.fileName()) self.svgItem.setFlags(QGraphicsItem.ItemClipsToShape) self.svgItem.setCacheMode(QGraphicsItem.NoCache) self.svgItem.setZValue(0) self.backgroundItem = QGraphicsRectItem(self.svgItem.boundingRect()) self.backgroundItem.setBrush(Qt.white) self.backgroundItem.setPen(QPen(Qt.NoPen)) self.backgroundItem.setVisible(drawBackground) self.backgroundItem.setZValue(-1) self.outlineItem = QGraphicsRectItem(self.svgItem.boundingRect()) outline = QPen(Qt.black, 2, Qt.DashLine) outline.setCosmetic(True) self.outlineItem.setPen(outline) self.outlineItem.setBrush(QBrush(Qt.NoBrush)) self.outlineItem.setVisible(drawOutline) self.outlineItem.setZValue(1) s.addItem(self.backgroundItem) s.addItem(self.svgItem) s.addItem(self.outlineItem) s.setSceneRect(self.outlineItem.boundingRect().adjusted(-10, -10, 10, 10)) def setRenderer(self, renderer): self.renderer = renderer if self.renderer == SvgView.OpenGL: if QGLFormat.hasOpenGL(): self.setViewport(QGLWidget(QGLFormat(QGL.SampleBuffers))) else: self.setViewport(QWidget()) def setHighQualityAntialiasing(self, highQualityAntialiasing): if QGLFormat.hasOpenGL(): self.setRenderHint(QPainter.HighQualityAntialiasing, highQualityAntialiasing) def setViewBackground(self, enable): if self.backgroundItem: self.backgroundItem.setVisible(enable) def setViewOutline(self, enable): if self.outlineItem: self.outlineItem.setVisible(enable) def paintEvent(self, event): if self.renderer == SvgView.Image: if self.image.size() != self.viewport().size(): self.image = QImage(self.viewport().size(), QImage.Format_ARGB32_Premultiplied) imagePainter = QPainter(self.image) QGraphicsView.render(self, imagePainter) imagePainter.end() p = QPainter(self.viewport()) p.drawImage(0, 0, self.image) else: super(SvgView, self).paintEvent(event) def wheelEvent(self, event): print(event.angleDelta().y()) factor = pow(1.2, event.angleDelta().y() / 240.0) self.scale(factor, factor) event.accept()
class ZoomableScene(QGraphicsScene): def __init__(self, parent=None): super().__init__(parent) self.noise_area = None self.ones_area = None self.zeros_area = None self.ones_arrow = None self.zeros_arrow = None self.selection_area = ROI(0, 0, 0, 0, fillcolor=constants.SELECTION_COLOR, opacity=constants.SELECTION_OPACITY) self.addItem(self.selection_area) def draw_noise_area(self, y, h): x = self.sceneRect().x() w = self.sceneRect().width() if self.ones_area is not None: self.ones_area.hide() if self.zeros_area is not None: self.zeros_area.hide() if self.noise_area is None or self.noise_area.scene() != self: roi = ROI(x, y, w, h, fillcolor=constants.NOISE_COLOR, opacity=constants.NOISE_OPACITY) # roi.setPen(QPen(constants.NOISE_COLOR, Qt.FlatCap)) self.noise_area = roi self.addItem(self.noise_area) else: self.noise_area.show() self.noise_area.setY(y) self.noise_area.height = h def draw_sep_area(self, y_mid): x = self.sceneRect().x() y = self.sceneRect().y() h = self.sceneRect().height() w = self.sceneRect().width() if self.noise_area is not None: self.noise_area.hide() if self.ones_area is None: self.ones_area = QGraphicsRectItem(x, y, w, h / 2 + y_mid) self.ones_area.setBrush(constants.ONES_AREA_COLOR) self.ones_area.setOpacity(constants.SEPARATION_OPACITY) self.ones_area.setPen(QPen(constants.TRANSPARENT_COLOR, Qt.FlatCap)) self.addItem(self.ones_area) else: self.ones_area.show() self.ones_area.setRect(x, y, w, h / 2 + y_mid) start = y + h / 2 + y_mid if self.zeros_area is None: self.zeros_area = QGraphicsRectItem(x, start, w, (y + h) - start) self.zeros_area.setBrush(constants.ZEROS_AREA_COLOR) self.zeros_area.setOpacity(constants.SEPARATION_OPACITY) self.zeros_area.setPen(QPen(constants.TRANSPARENT_COLOR, Qt.FlatCap)) self.addItem(self.zeros_area) else: self.zeros_area.show() self.zeros_area.setRect(x, start, w, (y + h) - start) def clear(self): self.noise_area = None self.ones_area = None self.zeros_area = None self.zeros_arrow = None self.ones_arrow = None self.selection_area = None super().clear() def dragEnterEvent(self, event: QGraphicsSceneDragDropEvent): event.accept() def dragMoveEvent(self, event: QGraphicsSceneDragDropEvent): event.accept()
class AnimatedCalendar(): updatesRunning = False updateTimer = None listUpdateThread = None calDataLock = threading.Lock() calDataUpdated = False curCalendars = None def __init__(self, scene, widthCalTextArea, heightCalTextArea, borders, calFeeds, calUpdateSecs): self.masterScene = scene self.widthCalTextArea = widthCalTextArea self.heightCalTextArea = heightCalTextArea self.borders = borders self.calFeeds = calFeeds self.calendarUpdateSecs = calUpdateSecs # Background self.textBkgd = QGraphicsRectItem(0, 0, self.widthCalTextArea, self.heightCalTextArea) self.textBkgd.setPos(self.borders[3], self.borders[0]) self.textBkgd.setBrush(QColor("light green")) self.textBkgd.setZValue(10) scene.addItem(self.textBkgd) # Text Item self.textItem = QGraphicsTextItem() self.textItem.setFont(QFont("Segoe UI", 24)) self.textItem.setDefaultTextColor(QColor("black")) self.textItem.setPos(QPointF(self.borders[3]+10,self.borders[0]+10)) self.textItem.setHtml("<B>Hello</B>Hello") self.textItem.setZValue(20) self.textItem.setTextWidth(self.widthCalTextArea-20) scene.addItem(self.textItem) def start(self): self.updatesRunning = True QTimer.singleShot(100, self.updateCalendar) self.listUpdateThread = CalendarUpdateThread(self, self.calFeeds, self.calendarUpdateSecs) self.listUpdateThread.start() # print("CalStarted") def stop (self): self.updatesRunning = False if self.updateTimer != None: self.updateTimer.stop() if self.listUpdateThread != None: self.listUpdateThread.stop() def setNewCalendarEntries(self, calendars): with self.calDataLock: self.curCalendars = calendars self.calDataUpdated = True def updateCalendar(self): # print("Update cal") with self.calDataLock: if self.calDataUpdated and self.curCalendars != None: for calEvents in self.curCalendars: calStr = "" lastDay = -1 for anEvent in calEvents: # date, duration, summary, location, UID eventDate = anEvent[0] duration = anEvent[1] summary = anEvent[2] location = anEvent[3] if lastDay != eventDate.day: if lastDay != -1: calStr += "<br/>" calStr += "<b>" + anEvent[0].strftime("%a") + " (" + anEvent[0].strftime("%d %B)") + ")</b><br/>" lastDay = eventDate.day strDurTime = str(duration).rpartition(":")[0] durStr = (str(duration.days) + "day" + ("s" if duration.days != 1 else "")) if duration.days > 0 else strDurTime locStr = "<small>("+location+")</small>" if location != "" else "" calStr += anEvent[0].strftime("%H:%M") + " <small>(" + durStr + ")</small> " + summary + " " + locStr + "<br/>" # print (anEvent) # print(date) self.textItem.setHtml(calStr) self.textItem.setTextWidth(self.widthCalTextArea-20) self.textItem.update() self.calDataUpdated = False if not self.updatesRunning: return self.updateTimer = QTimer() self.updateTimer.setInterval(5000) self.updateTimer.setSingleShot(True) self.updateTimer.timeout.connect(self.updateCalendar) self.updateTimer.start()
def refresh(self): if not self._mdlPlots or not self._mdlOutline or not self._mdlPersos: pass LINE_HEIGHT = 18 SPACING = 3 TEXT_WIDTH = self.sldTxtSize.value() CIRCLE_WIDTH = 10 LEVEL_HEIGHT = 12 s = self.scene s.clear() # Get Max Level (max depth) root = self._mdlOutline.rootItem def maxLevel(item, level=0, max=0): if level > max: max = level for c in item.children(): m = maxLevel(c, level + 1) if m > max: max = m return max MAX_LEVEL = maxLevel(root) # Generate left entries # (As of now, plot only) plotsID = self._mdlPlots.getPlotsByImportance() trackedItems = [] fm = QFontMetrics(s.font()) max_name = 0 for importance in plotsID: for ID in importance: name = self._mdlPlots.getPlotNameByID(ID) ref = references.plotReference(ID, searchable=True) trackedItems.append((ID, ref, name)) max_name = max(fm.width(name), max_name) ROWS_HEIGHT = len(trackedItems) * (LINE_HEIGHT + SPACING ) TITLE_WIDTH = max_name + 2 * SPACING # Add Folders and Texts outline = OutlineRect(0, 0, 0, ROWS_HEIGHT + SPACING + MAX_LEVEL * LEVEL_HEIGHT) s.addItem(outline) outline.setPos(TITLE_WIDTH + SPACING, 0) refCircles = [] # a list of all references, to be added later on the lines # A Function to add a rect with centered elided text def addRectText(x, w, parent, text="", level=0, tooltip=""): deltaH = LEVEL_HEIGHT if level else 0 r = OutlineRect(0, 0, w, parent.rect().height()-deltaH, parent, title=text) r.setPos(x, deltaH) txt = QGraphicsSimpleTextItem(text, r) f = txt.font() f.setPointSize(8) fm = QFontMetricsF(f) elidedText = fm.elidedText(text, Qt.ElideMiddle, w) txt.setFont(f) txt.setText(elidedText) txt.setPos(r.boundingRect().center() - txt.boundingRect().center()) txt.setY(0) return r # A function to returns an item's width, by counting its children def itemWidth(item): if item.isFolder(): r = 0 for c in item.children(): r += itemWidth(c) return r or TEXT_WIDTH else: return TEXT_WIDTH def listItems(item, rect, level=0): delta = 0 for child in item.children(): w = itemWidth(child) if child.isFolder(): parent = addRectText(delta, w, rect, child.title(), level, tooltip=child.title()) parent.setToolTip(references.tooltip(references.textReference(child.ID()))) listItems(child, parent, level + 1) else: rectChild = addRectText(delta, TEXT_WIDTH, rect, "", level, tooltip=child.title()) rectChild.setToolTip(references.tooltip(references.textReference(child.ID()))) # Find tracked references in that scene (or parent folders) for ID, ref, name in trackedItems: result = [] c = child while c: result += references.findReferencesTo(ref, c, recursive=False) c = c.parent() if result: ref2 = result[0] # Create a RefCircle with the reference c = RefCircle(TEXT_WIDTH / 2, - CIRCLE_WIDTH / 2, CIRCLE_WIDTH, ID=ref2) # Store it, with the position of that item, to display it on the line later on refCircles.append((ref, c, rect.mapToItem(outline, rectChild.pos()))) delta += w listItems(root, outline) OUTLINE_WIDTH = itemWidth(root) # Add Plots i = 0 itemsRect = s.addRect(0, 0, 0, 0) itemsRect.setPos(0, MAX_LEVEL * LEVEL_HEIGHT + SPACING) for ID, ref, name in trackedItems: color = randomColor() # Rect r = QGraphicsRectItem(0, 0, TITLE_WIDTH, LINE_HEIGHT, itemsRect) r.setPen(QPen(Qt.NoPen)) r.setBrush(QBrush(color)) r.setPos(0, i * LINE_HEIGHT + i * SPACING) i += 1 # Text txt = QGraphicsSimpleTextItem(name, r) txt.setPos(r.boundingRect().center() - txt.boundingRect().center()) # Line line = PlotLine(0, 0, OUTLINE_WIDTH + SPACING, 0) line.setPos(TITLE_WIDTH, r.mapToScene(r.rect().center()).y()) s.addItem(line) line.setPen(QPen(color, 5)) line.setToolTip(self.tr("Plot: ") + name) # We add the circles / references to text, on the line for ref2, circle, pos in refCircles: if ref2 == ref: circle.setParentItem(line) circle.setPos(pos.x(), 0) # self.view.fitInView(0, 0, TOTAL_WIDTH, i * LINE_HEIGHT, Qt.KeepAspectRatioByExpanding) # KeepAspectRatio self.view.setSceneRect(0, 0, 0, 0)
class ForcedXoverNode3(QGraphicsRectItem): """ This is a QGraphicsRectItem to allow actions and also a QGraphicsSimpleTextItem to allow a label to be drawn """ def __init__(self, virtual_helix_item, xover_item, strand3p, idx): super(ForcedXoverNode3, self).__init__(virtual_helix_item) self._vhi = virtual_helix_item self._xover_item = xover_item self._idx = idx self._is_on_top = virtual_helix_item.isStrandOnTop(strand3p) self._is_drawn_5_to_3 = strand3p.strandSet().isDrawn5to3() self._strand_type = strand3p.strandSet().strandType() self._partner_virtual_helix = virtual_helix_item self._blank_thing = QGraphicsRectItem(_blankRect, self) self._blank_thing.setBrush(QBrush(Qt.white)) self._path_thing = QGraphicsPathItem(self) self.configurePath() self.setPen(_NO_PEN) self._label = None self.setPen(_NO_PEN) self.setBrush(_NO_BRUSH) self.setRect(_rect) self.setZValue(styles.ZENDPOINTITEM + 1) # end def def updateForFloatFromVHI(self, virtual_helix_item, strand_type, idx_x, idx_y): """ """ self._vhi = virtual_helix_item self.setParentItem(virtual_helix_item) self._strand_type = strand_type self._idx = idx_x self._is_on_top = self._is_drawn_5_to_3 = True if idx_y == 0 else False self.updatePositionAndAppearance(is_from_strand=False) # end def def updateForFloatFromStrand(self, virtual_helix_item, strand3p, idx): """ """ self._vhi = virtual_helix_item self._strand = strand3p self.setParentItem(virtual_helix_item) self._idx = idx self._is_on_top = virtual_helix_item.isStrandOnTop(strand3p) self._is_drawn_5_to_3 = strand3p.strandSet().isDrawn5to3() self._strand_type = strand3p.strandSet().strandType() self.updatePositionAndAppearance() # end def def strandType(self): return self._strand_type # end def def configurePath(self): self._path_thing.setBrush(QBrush(styles.RED_STROKE)) path = PPR3 if self._is_drawn_5_to_3 else PPL3 offset = -_BASE_WIDTH if self._is_drawn_5_to_3 else _BASE_WIDTH self._path_thing.setPath(path) self._path_thing.setPos(offset, 0) offset = -_BASE_WIDTH if self._is_drawn_5_to_3 else 0 self._blank_thing.setPos(offset, 0) self._blank_thing.show() self._path_thing.show() # end def def refreshXover(self): self._xover_item.refreshXover() # end def def setPartnerVirtualHelix(self, virtual_helix_item): self._partner_virtual_helix = virtual_helix_item # end def def idx(self): return self._idx # end def def virtualHelixItem(self): return self._vhi # end def def point(self): return self._vhi.upperLeftCornerOfBaseType(self._idx, self._strand_type) # end def def floatPoint(self): pt = self.pos() return pt.x(), pt.y() # end def def isOnTop(self): return self._is_on_top # end def def isDrawn5to3(self): return self._is_drawn_5_to_3 # end def def updatePositionAndAppearance(self, is_from_strand=True): """ Sets position by asking the VirtualHelixItem Sets appearance by choosing among pre-defined painterpaths (from normalstrandgraphicsitem) depending on drawing direction. """ self.setPos(*self.point()) n5 = self._xover_item._node5 if is_from_strand: from_strand, from_idx = (n5._strand, n5._idx) if n5 != self else (None, None) if self._strand.canInstallXoverAt(self._idx, from_strand, from_idx): self.configurePath() # We can only expose a 5' end. But on which side? is_left = True if self._is_drawn_5_to_3 else False self._updateLabel(is_left) else: self.hideItems() else: self.hideItems() # end def def updateConnectivity(self): is_left = True if self._is_drawn_5_to_3 else False self._updateLabel(is_left) # end def def remove(self): """ Clean up this joint """ scene = self.scene() scene.removeItem(self._label) self._label = None scene.removeItem(self._path_thing) self._path_thing = None scene.removeItem(self._blank_thing) self._blank_thing = None scene.removeItem(self) # end def def _updateLabel(self, is_left): """ Called by updatePositionAndAppearance during init, or later by updateConnectivity. Updates drawing and position of the label. """ lbl = self._label if self._idx != None: bw = _BASE_WIDTH num = self._partner_virtual_helix.number() tBR = _FM.tightBoundingRect(str(num)) half_label_h = tBR.height()/2.0 half_label_w = tBR.width()/2.0 # determine x and y positions label_x = bw/2.0 - half_label_w if self._is_on_top: label_y = -0.25*half_label_h - 0.5 - 0.5*bw else: label_y = 2*half_label_h + 0.5 + 0.5*bw # adjust x for left vs right label_x_offset = 0.25*bw if is_left else -0.25*bw label_x += label_x_offset # adjust x for numeral 1 if num == 1: label_x -= half_label_w/2.0 # create text item if lbl == None: lbl = QGraphicsSimpleTextItem(str(num), self) lbl.setPos(label_x, label_y) lbl.setBrush(_ENAB_BRUSH) lbl.setFont(_TO_HELIX_NUM_FONT) self._label = lbl lbl.setText( str(self._partner_virtual_helix.number()) ) lbl.show() # end if # end def def hideItems(self): if self._label: self._label.hide() if self._blank_thing: self._path_thing.hide() if self._blank_thing: self._blank_thing.hide()