class TakeDragGame(QWidget): def __init__(self, parent=None): super(TakeDragGame, self).__init__(parent) # This is always the same self.dot2 = QGraphicsTextItem(':') self.dot1 = QGraphicsTextItem(':') self.animations = [] self.digits = [] self.main_layout = QHBoxLayout() self.setLayout(self.main_layout) self.scene = QGraphicsScene() self.scene.setSceneRect(0, 0, 600, 400) self.view = QGraphicsView() self.view.setScene(self.scene) # TODO: Check if its better with opengl or not # self.view.setViewport(QtOpenGL.QGLWidget()) self.main_layout.addWidget(self.view) # self.setWindowState(Qt.WindowMaximized) self.view.setAlignment(Qt.AlignTop | Qt.AlignLeft) self.image_bank = None self.create_and_add_images() # self.scene.setBackgroundBrush(QBrush(Qt.red, Qt.SolidPattern)) # self.populate() # self.animator = QTimer() # self.animator.timeout.connect(self.animate) # self.animate() def create_and_add_images(self): self.load_images_json_file() self.add_background_to_image() self.add_background_from_image() if self.image_bank is not None: for image_id in self.image_bank.keys(): if "clothes" in self.image_bank[image_id]["categories"]: image_path = self.image_bank[image_id]["path"] new_image = DraggableItem(image_path, self.background_from_image) new_image.moved_signal.moved.connect(self.item_moved) self.image_bank[image_id]["widget"] = new_image newpos_x = self.background_from_image.boundingRect().width() / 2 - new_image.boundingRect().width() / 2 newpos_y = self.background_from_image.boundingRect().height() / 2 - new_image.boundingRect().height() / 2 new_image.setPos(newpos_x, newpos_y) # self.scene.addItem(new_image) new_image.setZValue(30) def item_moved(self, pos): widget = self.sender().get_parent() print widget.zValue() print self.background_from_image.zValue() print self.background_to_image.zValue() item_br = widget.sceneBoundingRect() if self.background_from_image.sceneBoundingRect().contains(item_br): widget.setParentItem(self.background_from_image) newpos_x = self.background_from_image.boundingRect().width() / 2 - widget.boundingRect().width() / 2 newpos_y = self.background_from_image.boundingRect().height() / 2 - widget.boundingRect().height() / 2 # self.background_to_image.stackBefore(self.background_from_image) widget.setPos(newpos_x, newpos_y) elif self.background_to_image.sceneBoundingRect().contains(item_br): widget.setParentItem(self.background_to_image) newpos_x = self.background_to_image.boundingRect().width() / 2 - widget.boundingRect().width() / 2 newpos_y = self.background_to_image.boundingRect().height() / 2 - widget.boundingRect().height() / 2 # self.background_from_image.stackBefore(self.background_to_image) widget.setPos(newpos_x, newpos_y) def load_images_json_file(self): with open(os.path.join(CURRENT_PATH, './resources/images.json')) as f: self.image_bank = json.load(f) def add_background_from_image(self, ): assert self.image_bank is not None, "Images need to be loaded before calling this method (try load_images_json_file)" if "Background from" in self.image_bank: background_from_pixmap = QPixmap(self.image_bank["Background from"]["path"]) self.background_from_image = QGraphicsPixmapItem(background_from_pixmap) self.scene.addItem(self.background_from_image) self.background_from_image.setZValue(2) def add_background_to_image(self, ): assert self.image_bank is not None, "Images need to be loaded before calling this method (try load_images_json_file)" if "Background to" in self.image_bank: background_to_pixmap = QPixmap(self.image_bank["Background to"]["path"]) self.background_to_image = QGraphicsPixmapItem(background_to_pixmap) self.scene.addItem(self.background_to_image) self.background_to_image.setZValue(2) def resizeEvent(self, event): view_size = self.view.size() new_background_height = (1.5 / 4.) * view_size.height() background_to_pixmap = QPixmap(self.image_bank["Background to"]["path"]) background_to_pixmap = background_to_pixmap.scaled(new_background_height, new_background_height, Qt.KeepAspectRatio) if not self.background_to_image: self.background_to_image = QGraphicsPixmapItem(background_to_pixmap) else: self.background_to_image.setPixmap(background_to_pixmap) sugested_x_position = int(2 * (view_size.width() / 3.)) if sugested_x_position < 0: sugested_x_position = 0 sugested_y_position = int(view_size.height() / 2. - background_to_pixmap.size().height() / 2) if sugested_y_position < 0: sugested_y_position = 0 self.background_to_image.setPos(sugested_x_position, sugested_y_position) ##################### new_background_height = (2.2 / 4.) * view_size.height() background_from_pixmap = QPixmap(self.image_bank["Background from"]["path"]) background_from_pixmap = background_from_pixmap.scaled(new_background_height, new_background_height, Qt.KeepAspectRatio) if not self.background_to_image: self.background_from_image = QGraphicsPixmapItem(background_from_pixmap) else: self.background_from_image.setPixmap(background_from_pixmap) sugested_x_position = int(view_size.width() / 5. - background_from_pixmap.size().height() / 2) if sugested_x_position < 0: sugested_x_position = 0 sugested_y_position = int(view_size.height() / 2. - background_from_pixmap.size().height() / 2) if sugested_y_position < 0: sugested_y_position = 0 self.background_from_image.setPos(sugested_x_position, sugested_y_position) #### new_widget_height = (1 / 4.) * view_size.height() if self.image_bank is not None: for image_id in self.image_bank.keys(): if "clothes" in self.image_bank[image_id]["categories"]: widget = self.image_bank[image_id]["widget"] pixmap = widget.pixmap pixmap = pixmap.scaled(new_widget_height, new_widget_height, Qt.KeepAspectRatio) widget.setPixmap(pixmap) print widget.moved_flag if not widget.moved_flag: newpos_x = self.background_from_image.boundingRect().width() / 2 - widget.boundingRect().width() / 2 newpos_y = self.background_from_image.boundingRect().height() / 2 - widget.boundingRect().height() / 2 widget.setPos(newpos_x, newpos_y) super(TakeDragGame, self).resizeEvent(event)
class EditLinksNode(QGraphicsWidget): """ A Node representation with channel anchors. `direction` specifies the layout (default `Qt.LeftToRight` will have icon on the left and channels on the right). """ def __init__(self, parent=None, direction=Qt.LeftToRight, node=None, icon=None, iconSize=None, **args): QGraphicsWidget.__init__(self, parent, **args) self.setAcceptedMouseButtons(Qt.NoButton) self.__direction = direction self.setLayout(QGraphicsLinearLayout(Qt.Horizontal)) # Set the maximum size, otherwise the layout can't grow beyond its # sizeHint (and we need it to grow so the widget can grow and keep the # contents centered vertically. self.layout().setMaximumSize(QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)) self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.__iconSize = iconSize or QSize(64, 64) self.__icon = icon self.__iconItem = QGraphicsPixmapItem(self) self.__iconLayoutItem = GraphicsItemLayoutItem(item=self.__iconItem) self.__channelLayout = QGraphicsGridLayout() self.__channelAnchors = [] if self.__direction == Qt.LeftToRight: self.layout().addItem(self.__iconLayoutItem) self.layout().addItem(self.__channelLayout) channel_alignemnt = Qt.AlignRight else: self.layout().addItem(self.__channelLayout) self.layout().addItem(self.__iconLayoutItem) channel_alignemnt = Qt.AlignLeft self.layout().setAlignment(self.__iconLayoutItem, Qt.AlignCenter) self.layout().setAlignment(self.__channelLayout, Qt.AlignVCenter | channel_alignemnt) if node is not None: self.setSchemeNode(node) def setIconSize(self, size): """ Set the icon size for the node. """ if size != self.__iconSize: self.__iconSize = QSize(size) if self.__icon: self.__iconItem.setPixmap(self.__icon.pixmap(size)) self.__iconLayoutItem.updateGeometry() def iconSize(self): """ Return the icon size. """ return QSize(self.__iconSize) def setIcon(self, icon): """ Set the icon to display. """ if icon != self.__icon: self.__icon = QIcon(icon) self.__iconItem.setPixmap(icon.pixmap(self.iconSize())) self.__iconLayoutItem.updateGeometry() def icon(self): """ Return the icon. """ return QIcon(self.__icon) def setSchemeNode(self, node): """ Set an instance of `SchemeNode`. The widget will be initialized with its icon and channels. """ self.node = node if self.__direction == Qt.LeftToRight: channels = node.output_channels() else: channels = node.input_channels() self.channels = channels loader = icon_loader.from_description(node.description) icon = loader.get(node.description.icon) self.setIcon(icon) label_template = ('<div align="{align}">' '<b class="channelname">{name}</b><br/>' '<span class="typename">{typename}</span>' '</div>') if self.__direction == Qt.LeftToRight: align = "right" label_alignment = Qt.AlignVCenter | Qt.AlignRight anchor_alignment = Qt.AlignVCenter | Qt.AlignLeft label_row = 0 anchor_row = 1 else: align = "left" label_alignment = Qt.AlignVCenter | Qt.AlignLeft anchor_alignment = Qt.AlignVCenter | Qt.AlignLeft label_row = 1 anchor_row = 0 self.__channelAnchors = [] grid = self.__channelLayout for i, channel in enumerate(channels): text = label_template.format(align=align, name=escape(channel.name), typename=escape(channel.type)) text_item = GraphicsTextWidget(self) text_item.setHtml(text) text_item.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) grid.addItem(text_item, i, label_row, alignment=label_alignment) anchor = ChannelAnchor(self, channel=channel, rect=QRectF(0, 0, 20, 20)) anchor.setBrush(self.palette().brush(QPalette.Mid)) layout_item = GraphicsItemLayoutItem(grid, item=anchor) grid.addItem(layout_item, i, anchor_row, alignment=anchor_alignment) if hasattr(channel, "description"): text_item.setToolTip((channel.description)) self.__channelAnchors.append(anchor) def anchor(self, channel): """ Return the anchor item for the `channel` name. """ for anchor in self.__channelAnchors: if anchor.channel() == channel: return anchor raise ValueError(channel.name) def paint(self, painter, option, widget=None): painter.save() palette = self.palette() border = palette.brush(QPalette.Mid) pen = QPen(border, 1) pen.setCosmetic(True) painter.setPen(pen) painter.setBrush(palette.brush(QPalette.Window)) brect = self.boundingRect() painter.drawRoundedRect(brect, 4, 4) painter.restore()
class ProbabilitiesItem(orangeqt.PlotItem): """ Displays class probabilities in the background :param classifier: The classifier for which the probabilities are calculated :type classifier: orange.P2NN :param granularity: The size of individual cells :type granularity: int :param scale: The data scale factor :type scale: float :param spacing: The space between cells :param spacing: int :param rect: The rectangle into which to draw the probabilities. If unspecified, the entire plot is used. :type rect: QRectF """ def __init__(self, classifier, granularity, scale, spacing, rect=None): orangeqt.PlotItem.__init__(self) self.classifier = classifier self.rect = rect self.granularity = granularity self.scale = scale self.spacing = spacing self.pixmap_item = QGraphicsPixmapItem(self) self.set_in_background(True) self.setZValue(ProbabilitiesZValue) def update_properties(self): ## Mostly copied from OWScatterPlotGraph if not self.plot(): return if not self.rect: x, y = self.axes() self.rect = self.plot().data_rect_for_axes(x, y) s = self.graph_transform().mapRect(self.rect).size().toSize() if not s.isValid(): return rx = s.width() ry = s.height() rx -= rx % self.granularity ry -= ry % self.granularity p = self.graph_transform().map(QPointF( 0, 0)) - self.graph_transform().map(self.rect.topLeft()) p = p.toPoint() ox = p.x() oy = -p.y() if self.classifier.classVar.is_continuous: imagebmp = orangeom.potentialsBitmap(self.classifier, rx, ry, ox, oy, self.granularity, self.scale) palette = [ qRgb(255. * i / 255., 255. * i / 255., 255 - (255. * i / 255.)) for i in range(255) ] + [qRgb(255, 255, 255)] else: imagebmp, nShades = orangeom.potentialsBitmap( self.classifier, rx, ry, ox, oy, self.granularity, self.scale, self.spacing) palette = [] sortedClasses = get_variable_values_sorted( self.classifier.domain.classVar) for cls in self.classifier.classVar.values: color = self.plot().discPalette.getRGB( sortedClasses.index(cls)) towhite = [255 - c for c in color] for s in range(nShades): si = 1 - float(s) / nShades palette.append( qRgb(*tuple( [color[i] + towhite[i] * si for i in (0, 1, 2)]))) palette.extend( [qRgb(255, 255, 255) for i in range(256 - len(palette))]) self.potentialsImage = QImage(imagebmp, rx, ry, QImage.Format_Indexed8) self.potentialsImage.setColorTable( ColorPaletteDlg.signedPalette(palette ) if qVersion() < "4.5" else palette) self.potentialsImage.setNumColors(256) self.pixmap_item.setPixmap(QPixmap.fromImage(self.potentialsImage)) self.pixmap_item.setPos(self.graph_transform().map( self.rect.bottomLeft())) def data_rect(self): return self.rect if self.rect else QRectF()
class ProbabilitiesItem(orangeqt.PlotItem): """ Displays class probabilities in the background :param classifier: The classifier for which the probabilities are calculated :type classifier: orange.P2NN :param granularity: The size of individual cells :type granularity: int :param scale: The data scale factor :type scale: float :param spacing: The space between cells :param spacing: int :param rect: The rectangle into which to draw the probabilities. If unspecified, the entire plot is used. :type rect: QRectF """ def __init__(self, classifier, granularity, scale, spacing, rect=None): orangeqt.PlotItem.__init__(self) self.classifier = classifier self.rect = rect self.granularity = granularity self.scale = scale self.spacing = spacing self.pixmap_item = QGraphicsPixmapItem(self) self.set_in_background(True) self.setZValue(ProbabilitiesZValue) def update_properties(self): ## Mostly copied from OWScatterPlotGraph if not self.plot(): return if not self.rect: x, y = self.axes() self.rect = self.plot().data_rect_for_axes(x, y) s = self.graph_transform().mapRect(self.rect).size().toSize() if not s.isValid(): return rx = s.width() ry = s.height() rx -= rx % self.granularity ry -= ry % self.granularity p = self.graph_transform().map(QPointF(0, 0)) - self.graph_transform().map(self.rect.topLeft()) p = p.toPoint() ox = p.x() oy = -p.y() if isinstance(self.classifier.classVar, ContinuousVariable): imagebmp = orangeom.potentialsBitmap(self.classifier, rx, ry, ox, oy, self.granularity, self.scale) palette = [qRgb(255.0 * i / 255.0, 255.0 * i / 255.0, 255 - (255.0 * i / 255.0)) for i in range(255)] + [ qRgb(255, 255, 255) ] else: imagebmp, nShades = orangeom.potentialsBitmap( self.classifier, rx, ry, ox, oy, self.granularity, self.scale, self.spacing ) palette = [] sortedClasses = get_variable_values_sorted(self.classifier.domain.classVar) for cls in self.classifier.classVar.values: color = self.plot().discPalette.getRGB(sortedClasses.index(cls)) towhite = [255 - c for c in color] for s in range(nShades): si = 1 - float(s) / nShades palette.append(qRgb(*tuple([color[i] + towhite[i] * si for i in (0, 1, 2)]))) palette.extend([qRgb(255, 255, 255) for i in range(256 - len(palette))]) self.potentialsImage = QImage(imagebmp, rx, ry, QImage.Format_Indexed8) self.potentialsImage.setColorTable(ColorPaletteDlg.signedPalette(palette) if qVersion() < "4.5" else palette) self.potentialsImage.setNumColors(256) self.pixmap_item.setPixmap(QPixmap.fromImage(self.potentialsImage)) self.pixmap_item.setPos(self.graph_transform().map(self.rect.bottomLeft())) def data_rect(self): return self.rect if self.rect else QRectF()
class Scene(QGraphicsScene): def __init__(self, lblXY, spinId, spinX, spinY, btnAddEdge, btnDeleteEdge, spinCommRange, spinEnvX, spinEnvY, comboChannelType): super(self.__class__, self).__init__() self.net = pymote.Network() self.net_dict = {} #for keeping pairs of net_node and scene_node self.comm_range = 200 self.curr_id = 1 self.node_size = 15 self.node_color = QtCore.Qt.blue self.pressed_color = QtCore.Qt.red self.lblXY = lblXY #shows x,y position on scene self.spinId = spinId self.spinId.setEnabled(False) self.spinX = spinX self.spinY = spinY self.btnAddEdge = btnAddEdge self.btnDeleteEdge = btnDeleteEdge self.spinEnvX = spinEnvX self.spinEnvY = spinEnvY self.comboChannelType = comboChannelType self.hide_btn_edge() #on start: auto edge mode selected -> buttons add and delete edge not needed self.hide_pressed_item_data() #on start: no item is pressed -> hide item data self.spinCommRange = spinCommRange self.spinCommRange.setValue(self.comm_range) self.f_show_radius = False self.f_auto_edge = True self.f_move = False self.f_moved = False self.f_show_env = True self.f_opening_net = False self.option = 0 self.edge_option = 0 self.last_pressed_node = 0 self.radius = 0 self.environment = pymote.Environment() self.scene_env = 0 self.envX = 600 self.envY = 600 self.channel_type = self.comboChannelType.currentText() self.setSceneRect(QtCore.QRectF(0, -self.envY, self.envX, self.envY)) def ini_scene(self): self.clear() new_net = pymote.Network() self.net = new_net self.net_dict.clear() self.curr_id = 1 self.option = 0 self.edge_option = 0 self.last_pressed_node = 0 self.radius = 0 self.environment = pymote.Environment() self.scene_env = 0 def get_net(self): return self.net def hide_pressed_item_data(self): #self.spinId.setEnable(False) self.spinId.setValue(0) self.spinX.setEnabled(False) self.spinX.setValue(0) self.spinY.setEnabled(False) self.spinY.setValue(0) def show_pressed_item_data(self): #self.spinId.setEnable(True) self.spinId.setValue(self.last_pressed_node.node_id) self.spinX.setEnabled(True) self.spinX.setValue(self.last_pressed_node.get_X()) self.spinY.setEnabled(True) self.spinY.setValue(-self.last_pressed_node.get_Y()) def hide_btn_edge(self): self.btnAddEdge.setEnabled(False) self.btnDeleteEdge.setEnabled(False) def show_btn_edge(self): self.btnAddEdge.setEnabled(True) self.btnDeleteEdge.setEnabled(True) def auto_add_edge(self, toggle): if toggle.isChecked() == True: self.f_auto_edge = True self.hide_btn_edge() self.delete_all_edges() self.net.recalculate_edges() self.draw_all_edges() else: self.f_auto_edge = False self.show_btn_edge() def show_radius(self, toggle): if toggle.isChecked() == True: self.f_show_radius = True if self.last_pressed_node != 0 and self.option == 0: self.draw_radius(self.last_pressed_node.get_X() + self.node_size/2, self.last_pressed_node.get_Y() + self.node_size/2, self.comm_range) else: self.f_show_radius = False if self.radius != 0: self.delete_radius() def show_env(self, toggle): if toggle.isChecked() == True: self.f_show_env =True if self.scene_env != 0: self.scene_env.show() else: self.f_show_env = False if self.scene_env != 0: self.delete_env() def draw_radius(self, x, y, comm_range): self.radius = Radius(x, y, comm_range) self.addItem(self.radius) def delete_radius(self): self.removeItem(self.radius) self.radius = 0 # def search_node_by_id(self): # f_found = False # # if self.last_pressed_node != 0: # if self.last_pressed_node.node_id != self.spinId.value(): # self.last_pressed_node.setBrush(self.node_color) # for n in self.items(): # if isinstance(n, Node): # if n.node_id == self.spinId.value(): # if self.radius != 0 and self.f_show_radius: # size = n.comm_range # self.radius.setRect(n.get_X() - size, n.get_Y() - size, size * 2, size * 2) # self.last_pressed_node = n # n.setBrush(self.pressed_color) # self.spinX.setValue(n.get_X()) # self.spinY.setValue(-n.get_Y()) # f_found = True # # if not f_found: # self.last_pressed_node = 0 # self.spinX.setValue(0) # self.spinY.setValue(0) # if self.radius != 0: # self.delete_radius() def change_node_x(self): if self.last_pressed_node != 0 and not self.f_move: if self.last_pressed_node.get_X() != self.spinX.value(): self.spin_value_changed(True) def change_node_y(self): if self.last_pressed_node != 0 and not self.f_move: if -self.last_pressed_node.get_Y() != self.spinY.value(): self.spin_value_changed(False) def spin_value_changed(self, f_isX): if not self.f_auto_edge: self.move_edges(self.last_pressed_node, self.spinX.value(), self.spinY.value()) if self.f_auto_edge and not self.f_moved: #delete edges before node is moved edges = list() for edge in self.last_pressed_node.edges: edges.append(edge) for edge in edges: self._delete_edge(edge, True) if f_isX: self.last_pressed_node.setX(self.spinX.value() - self.last_pressed_node.get_iniX()) self.last_pressed_node.node_label.setX(self.spinX.value()) else: self.last_pressed_node.setY(-self.spinY.value() - self.last_pressed_node.get_iniY()) self.last_pressed_node.node_label.setY(-self.spinY.value()) net_node, n = self.get_nodes_from_net(self.last_pressed_node, 0) self.net.pos[net_node] = [self.spinX.value(), self.spinY.value()] if self.f_auto_edge and not self.f_moved: self.net.recalculate_edges([self.last_pressed_node.net_node]) self.draw_recalc_edges(self.last_pressed_node.net_node) def change_comm_range(self): self.comm_range = self.spinCommRange.value() if self.last_pressed_node != 0: self.last_pressed_node.set_comm_range(self.comm_range) net_node, n = self.get_nodes_from_net(self.last_pressed_node, 0) net_node.commRange = self.comm_range if self.radius != 0: size = self.comm_range self.radius.setRect(self.radius.get_iniX() - size, self.radius.get_iniY() - size, size * 2, size * 2) def change_node_env_x(self): self.envX = self.spinEnvX.value() #TODO: dodati promjenu velicine env u net.env self.setSceneRect(QtCore.QRectF(0, -self.envY, self.envX, self.envY)) def change_node_env_y(self): self.envY = self.spinEnvY.value() #TODO: dodati promjenu velicine env u net.env self.setSceneRect(QtCore.QRectF(0, -self.envY, self.envX, self.envY)) def change_channel_type(self): if self.comboChannelType.currentIndex() == 0: self.net.channelType = pymote.channeltype.Udg(self.net.environment) elif self.comboChannelType.currentIndex() == 1: self.net.channelType = pymote.channeltype.SquareDisc(self.net.environment) if not self.f_opening_net and self.f_auto_edge: self.delete_all_edges() self.net.recalculate_edges() self.draw_all_edges() def draw_net(self, net): self.ini_scene() self.net = net self.f_opening_net = True max_id = 0 for net_node in net: node = self.draw_node(net.pos[net_node][0], net.pos[net_node][1], net_node.id, net_node.commRange, net_node) self.net_dict[net_node] = node if net_node.id > max_id: max_id = net_node.id self.curr_id = max_id + 1 self.draw_all_edges() self.environment = net.environment img = Image.fromarray(net.environment.im[::-1, :], 'L') img.save('env.png') self.draw_env('env.png') combo_index = -1 if isinstance(net.channelType, pymote.channeltype.Udg): combo_index = 0 elif isinstance(net.channelType, pymote.channeltype.SquareDisc): combo_index = 1 self.comboChannelType.setCurrentIndex(combo_index) self.f_opening_net = False def draw_node(self, x, y, node_id, comm_range, net_node): node_label = Label(str(node_id), x, -y) self.addItem(node_label) node = Node(x - self.node_size/2, -y - self.node_size/2, self.node_size, node_id, node_label, comm_range, net_node) node.setBrush(self.node_color) self.addItem(node) return node def draw_edge(self, node1, node2): edge = Edge(node1, node2) self.addItem(edge) node1.add_edge_to_list(edge) node2.add_edge_to_list(edge) return edge def draw_all_edges(self): net = self.net edges = list() for net_node in self.net: for n in net.adj[net_node].keys(): f_draw_edge = True for e in edges: #check if edge already drawn if (e[0] == net_node.id and e[1] == n.id) or (e[1] == net_node.id and e[0] == n.id): f_draw_edge = False if f_draw_edge: node = self.net_dict[net_node] adj_node = self.net_dict[n] self.draw_edge(node, adj_node) edges.append((net_node.id, n.id)) def delete_all_edges(self): for item in self.items(): if isinstance(item, Edge): self._delete_edge(item, True) def draw_recalc_edges(self, net_node): node = self.net_dict[net_node] for n in self.net.adj[net_node].keys(): adj_node = self.net_dict[n] self.draw_edge(node, adj_node) def open_env(self): filters = ['Environment image (*.png)', 'All files (*)'] selectedFilter = 'Environment image (*.png)' filters = ';;'.join(filters) fname = QFileDialog.getOpenFileName( self.parent(), "Choose a file to open", '', filters, selectedFilter) if fname: try: self.environment.__init__(path = str(fname)) self.net.environment = self.environment self.draw_env(fname) except Exception as e: print ("Error opening file %s" % str(e)), QMessageBox.critical( self, "Error opening file", str(e), QMessageBox.Ok, QMessageBox.NoButton) def draw_env(self, image): if self.scene_env == 0: self.scene_env = QGraphicsPixmapItem() else: self.removeItem(self.scene_env) self.scene_env.setPixmap(QPixmap(image)) if self.scene_env != 0: self.scene_env.setPos(0, -self.environment.im.shape[1]) self.addItem(self.scene_env) self.scene_env.setZValue(-1) if not self.f_show_env: self.scene_env.hide() self.spinEnvX.setValue(self.environment.im.shape[0]) self.spinEnvY.setValue(self.environment.im.shape[1]) if self.f_auto_edge: self.delete_all_edges() self.net.recalculate_edges() self.draw_all_edges() def delete_env(self): if self.scene_env != 0: self.scene_env.hide() def option_change(self): if self.radius != 0: self.delete_radius() if self.edge_option != 0: self.edge_option = 0 self.deselect_node() if self.last_pressed_node != 0: self.deselect_node() def move_node(self): self.option_change() self.option = 0 def add_node(self): self.option_change() self.option = 1 def _add_node(self, x, y): #add node to network net_node = pymote.Node() self.net.add_node(net_node, (x, y)) net_node.id = self.curr_id net_node.commRange = self.comm_range #add node to scene node = self.draw_node(x, y, self.curr_id, self.comm_range, net_node) self.net_dict[net_node] = node self.curr_id = self.curr_id + 1 '''when adding new node to network pymote calls recalculate_edges, if USE MODEL OF COMMUNICATON TO AUTO EDGES is not selected then we need to remove those edges''' if not self.f_auto_edge: self.net.adj[net_node].clear() for n in self.net: if self.net.adj[n].has_key(net_node): del self.net.adj[n][net_node] else: self.draw_recalc_edges(net_node) def delete_node(self): self.option_change() self.option = 2 def _delete_node(self, node): #delete node edges from scene edges = list() for edge in node.edges: edges.append(edge) for edge in edges: self._delete_edge(edge, False) self.removeItem(node) self.removeItem(node.node_label) #delete node from network self.net.remove_node(node.net_node) del self.net_dict[node.net_node] def add_edge(self): self.option_change() self.option = 3 def _add_edge(self, pressed_node): if pressed_node != 0: if self.edge_option == 0: self.select_node(pressed_node) self.edge_option = 1 if self.edge_option == 1 and self.last_pressed_node != pressed_node and self.last_pressed_node != 0: self.edge_option = 2 edge_exists = self.find_edge(pressed_node, self.last_pressed_node) if edge_exists != 0: self.edge_option = 0 self.deselect_node() if self.edge_option == 2: self.draw_edge(self.last_pressed_node, pressed_node) self.edge_option = 0 #add edge to net.adj node1, node2 = self.get_nodes_from_net(self.last_pressed_node, pressed_node) if node1 != 0 and node2 != 0: self.net.adj[node1][node2] = [] self.net.adj[node2][node1] = [] self.deselect_node() elif pressed_node == 0 and self.edge_option == 1: self.edge_option = 0 self.deselect_node() def delete_edge(self): self.option_change() self.option = 4 def _delete_edge(self, edge, f_recal_called): n1 = edge.node1 n2 = edge.node2 n1.remove_edge_from_list(edge) n2.remove_edge_from_list(edge) self.removeItem(edge) #delete edge from net.adj if not f_recal_called: node1, node2 = self.get_nodes_from_net(n1, n2) if node1 != 0 and node2 != 0: self.delete_edge_from_adj(node1, node2) self.delete_edge_from_adj(node2, node1) def get_nodes_from_net(self, n1, n2): node1 = 0 node2 = 0 for n in self.net: if n.id == n1.node_id: node1 = n if n2 != 0: if n.id == n2.node_id: node2 = n return (node1, node2) def delete_edge_from_adj(self, node, del_n): del self.net.adj[node][del_n] def find_edge(self, node, n): for e in node.edges: if (n.get_X() == e.line().x1() and n.get_Y() == e.line().y1()) or (n.get_X() == e.line().x2() and n.get_Y() == e.line().y2()): return e return 0 def select_node(self, node): self.last_pressed_node = node node.setBrush(self.pressed_color) if self.option == 0: self.show_pressed_item_data() if self.f_show_radius: self.draw_radius(node.get_X() + self.node_size/2, node.get_Y() + self.node_size/2, self.last_pressed_node.comm_range) def deselect_node(self): self.last_pressed_node.setBrush(self.node_color) self.last_pressed_node = 0 self.hide_pressed_item_data() if self.radius != 0: self.delete_radius() def move_edges(self, node, x, y): for edge in node.edges: if edge.line().x1() == node.get_X() and edge.line().y1() == node.get_Y(): edge.setLine(x, y, edge.line().x2(), edge.line().y2()) else: edge.setLine(edge.line().x1(), edge.line().y1(), x, y) def mousePressEvent(self, e): mouseX = e.scenePos().x() mouseY = -e.scenePos().y() pressed_node = 0 pressed_edge = 0 self.f_move = True for item in self.items(e.scenePos()): if pressed_node == 0 and isinstance(item, Node): pressed_node = item if pressed_edge == 0 and isinstance(item, Edge): pressed_edge = item #on new mouse press deselect last node (only if option add edge is not selected) if self.last_pressed_node != 0: if self.edge_option != 1: self.deselect_node() if self.option == 1: #draw node self._add_node(mouseX, mouseY) elif self.option == 2: #delete node if pressed_node != 0: self._delete_node(pressed_node) elif self.option == 3: #add edge self._add_edge(pressed_node) elif self.option == 4: #delete edge if pressed_edge != 0: self._delete_edge(pressed_edge, False) #select new pressed node and save it if pressed_node != 0: if self.option == 0: self.select_node(pressed_node) self.spinCommRange.setValue(pressed_node.comm_range) else: self.last_pressed_node = 0 def mouseMoveEvent(self, e): mouseX = e.scenePos().x() mouseY = e.scenePos().y() self.lblXY.setText('x: ' + str(mouseX) + ' y: ' + str(-mouseY)) if self.last_pressed_node != 0 and self.f_move: node = self.last_pressed_node self.f_moved = True if self.option == 0: #when moving node, move his edges if not self.f_auto_edge: self.move_edges(node, mouseX, mouseY) #move node node.setX(mouseX - node.get_iniX()) node.setY(mouseY - node.get_iniY()) node.node_label.setPos(mouseX, mouseY) net_node, n = self.get_nodes_from_net(node, 0) self.net.pos[net_node][0] = mouseX self.net.pos[net_node][1] = -mouseY if self.f_auto_edge: edges = list() for edge in node.edges: edges.append(edge) for edge in edges: self._delete_edge(edge, True) self.spinX.setValue(mouseX) self.spinY.setValue(-mouseY) #move radius if self.f_show_radius and (self.option == 1 or (self.option == 0 and self.last_pressed_node != 0 and self.f_move)): if self.radius == 0 and self.option == 1: self.draw_radius(mouseX, mouseY, self.comm_range) elif self.radius != 0: self.radius.setX(mouseX - self.radius.get_iniX()) self.radius.setY(mouseY - self.radius.get_iniY()) def mouseReleaseEvent(self, e): if self.f_auto_edge and self.last_pressed_node != 0 and self.option == 0 and self.f_moved: self.net.recalculate_edges([self.last_pressed_node.net_node]) self.draw_recalc_edges(self.last_pressed_node.net_node) self.f_move = False self.f_moved = False
class SlideshowFrame(object): def __init__(self, win, rect, filename, metadata): self.win = win self.rect = rect self.filename = filename self.metadata = metadata if self.metadata: self.line1 = self.metadata['Name'] self.line2 = "%s Mission" % (self.metadata['Mission']) self.line3 = "%s" % (self.metadata['Time']) else: self.line1 = "" self.line2 = "" self.line3 = "" self.image = QGraphicsPixmapItem() self.win.scene.addItem(self.image) self.image.setTransformationMode(Qt.SmoothTransformation) self.use_two_lines = True self.fontsize1 = 32 self.fontsize2 = 26 self.fontsize3 = 24 self.font1 = QFont('Times New Roman', self.fontsize1) self.font2 = QFont('Times New Roman', self.fontsize2) self.font3 = QFont('Times New Roman', self.fontsize3) self.title1 = self.win.scene.addText(self.line1, self.font1) self.title1.setDefaultTextColor(Qt.white) self.title1.setVisible(False) self.title2 = self.win.scene.addText(self.line2, self.font2) self.title2.setDefaultTextColor(Qt.white) self.title2.setVisible(False) self.title3 = self.win.scene.addText(self.line3, self.font3) self.title3.setDefaultTextColor(Qt.white) self.title3.setVisible(False) self.reservedHeight = 128 self.padding = 20 self.hide() def move(self, x, y): self.rect = QRectF(x, y, self.rect.width(), self.rect.height()) def __rotate(self, metadata, origImgSize): # Qt only handles orientation properly from v5.5 try: # try directly to get the tag, because sometimes get_tags() returns # tags that don't actually are in the file rot = metadata['Exif.Image.Orientation'] except KeyError: # guess :-/ rot = '1' # see http://www.daveperrett.com/images/articles/2012-07-28-exif-orientation-handling-is-a-ghetto/EXIF_Orientations.jpg # we have to 'undo' the rotations, so the numbers are negative if rot == '1': rotate = 0 imgSize = origImgSize if rot == '8': rotate = -90 imgSize = QSize(origImgSize.height(), origImgSize.width()) if rot == '3': rotate = -180 imgSize = origImgSize if rot == '6': rotate = -270 imgSize = QSize(origImgSize.height(), origImgSize.width()) # undo the last rotation and apply the new one self.image.setRotation(rotate) return imgSize def __zoomFit(self, imgSize): reservedHeight = self.reservedHeight + self.padding * 2 hZoom = self.rect.width() / imgSize.width() vZoom = (self.rect.height() - reservedHeight) / imgSize.height() scale = min(hZoom, vZoom) self.image.setScale(scale) width = imgSize.width() * scale height = imgSize.height() * scale self.image.setPos( (self.rect.width() - width) / 2 + self.rect.x(), (self.rect.height() - reservedHeight - height) / 2 + self.rect.y()) def layoutText(self): reservedHeight = self.reservedHeight + self.padding vertical_spacing = (self.reservedHeight - self.title1.boundingRect().height() - self.title2.boundingRect().height() - self.title3.boundingRect().height()) / 3 x = (self.rect.width() - self.title1.boundingRect().width()) / 2 y = self.rect.height() - reservedHeight + vertical_spacing self.title1.setPos(x + self.rect.x(), y + self.rect.y()) x = (self.rect.width() - self.title2.boundingRect().width()) / 2 y = self.rect.height( ) - reservedHeight + vertical_spacing * 2 + self.title1.boundingRect( ).height() self.title2.setPos(x + self.rect.x(), y + self.rect.y()) x = (self.rect.width() - self.title3.boundingRect().width()) / 2 y = self.rect.height( ) - reservedHeight + vertical_spacing * 3 + self.title1.boundingRect( ).height() + self.title2.boundingRect().height() self.title3.setPos(x + self.rect.x(), y + self.rect.y()) def show(self): img = QPixmap(self.filename) try: metadata = GExiv2.Metadata(self.filename) except GLib.Error as e: print(repr(e)) return self.image.setPixmap(img) self.image.setScale(1.0) self.image.setRotation(0) imgSize = self.__rotate(metadata, img.size()) self.__zoomFit(imgSize) self.layoutText() self.title1.setVisible(True) self.title2.setVisible(True) self.title3.setVisible(True) self.image.setVisible(True) def hide(self): self.title1.setVisible(False) self.title2.setVisible(False) self.title3.setVisible(False) self.image.setVisible(False) self.image.setPixmap(QPixmap()) def showImage(self, file, md): self.metadata = md try: metadata = GExiv2.Metadata(file) except GLib.Error as e: print(repr(e)) return img = QPixmap(file) self.image.setPixmap(img) self.image.setScale(1.0) self.image.setRotation(0) imgSize = self.__rotate(metadata, img.size()) self.__zoomFit(imgSize) self.layoutMetadata()
class EditLinksNode(QGraphicsWidget): """ A Node representation with channel anchors. `direction` specifies the layout (default `Qt.LeftToRight` will have icon on the left and channels on the right). """ def __init__(self, parent=None, direction=Qt.LeftToRight, node=None, icon=None, iconSize=None, **args): QGraphicsWidget.__init__(self, parent, **args) self.setAcceptedMouseButtons(Qt.NoButton) self.__direction = direction self.setLayout(QGraphicsLinearLayout(Qt.Horizontal)) # Set the maximum size, otherwise the layout can't grow beyond its # sizeHint (and we need it to grow so the widget can grow and keep the # contents centered vertically. self.layout().setMaximumSize(QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)) self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.__iconSize = iconSize or QSize(64, 64) self.__icon = icon self.__iconItem = QGraphicsPixmapItem(self) self.__iconLayoutItem = GraphicsItemLayoutItem(item=self.__iconItem) self.__channelLayout = QGraphicsGridLayout() self.__channelAnchors = [] if self.__direction == Qt.LeftToRight: self.layout().addItem(self.__iconLayoutItem) self.layout().addItem(self.__channelLayout) channel_alignemnt = Qt.AlignRight else: self.layout().addItem(self.__channelLayout) self.layout().addItem(self.__iconLayoutItem) channel_alignemnt = Qt.AlignLeft self.layout().setAlignment(self.__iconLayoutItem, Qt.AlignCenter) self.layout().setAlignment(self.__channelLayout, Qt.AlignVCenter | channel_alignemnt) if node is not None: self.setSchemeNode(node) def setIconSize(self, size): """ Set the icon size for the node. """ if size != self.__iconSize: self.__iconSize = QSize(size) if self.__icon: self.__iconItem.setPixmap(self.__icon.pixmap(size)) self.__iconLayoutItem.updateGeometry() def iconSize(self): """ Return the icon size. """ return QSize(self.__iconSize) def setIcon(self, icon): """ Set the icon to display. """ if icon != self.__icon: self.__icon = QIcon(icon) self.__iconItem.setPixmap(icon.pixmap(self.iconSize())) self.__iconLayoutItem.updateGeometry() def icon(self): """ Return the icon. """ return QIcon(self.__icon) def setSchemeNode(self, node): """ Set an instance of `SchemeNode`. The widget will be initialized with its icon and channels. """ self.node = node if self.__direction == Qt.LeftToRight: channels = node.output_channels() else: channels = node.input_channels() self.channels = channels loader = icon_loader.from_description(node.description) icon = loader.get(node.description.icon) self.setIcon(icon) label_template = ('<div align="{align}">' '<b class="channelname">{name}</b><br/>' '<span class="typename">{typename}</span>' '</div>') if self.__direction == Qt.LeftToRight: align = "right" label_alignment = Qt.AlignVCenter | Qt.AlignRight anchor_alignment = Qt.AlignVCenter | Qt.AlignLeft label_row = 0 anchor_row = 1 else: align = "left" label_alignment = Qt.AlignVCenter | Qt.AlignLeft anchor_alignment = Qt.AlignVCenter | Qt.AlignLeft label_row = 1 anchor_row = 0 self.__channelAnchors = [] grid = self.__channelLayout for i, channel in enumerate(channels): text = label_template.format(align=align, name=escape(channel.name), typename=escape(channel.type)) text_item = GraphicsTextWidget(self) text_item.setHtml(text) text_item.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) grid.addItem(text_item, i, label_row, alignment=label_alignment) anchor = ChannelAnchor(self, channel=channel, rect=QRectF(0, 0, 20, 20)) anchor.setBrush(self.palette().brush(QPalette.Mid)) layout_item = GraphicsItemLayoutItem(grid, item=anchor) grid.addItem(layout_item, i, anchor_row, alignment=anchor_alignment) if hasattr(channel, "description"): text_item.setToolTip((channel.description)) self.__channelAnchors.append(anchor) def anchor(self, channel): """ Return the anchor item for the `channel` name. """ for anchor in self.__channelAnchors: if anchor.channel() == channel: return anchor raise ValueError(channel.name) def paint(self, painter, option, widget=None): painter.save() palette = self.palette() border = palette.brush(QPalette.Mid) pen = QPen(border, 1) pen.setCosmetic(True) painter.setPen(pen) painter.setBrush(palette.brush(QPalette.Window)) brect = self.boundingRect() painter.drawRoundedRect(brect, 4, 4) painter.restore()