class Video(QWidget): def __init__(self): # init the widget QWidget.__init__(self) # set up the scene self.scene=QGraphicsScene() self.scene.setSceneRect(0,0,800,600) # add a view of that scene self.view = QGraphicsView() self.view.setScene(self.scene) self.view.setRenderHint(QPainter.Antialiasing) self.view.setFixedSize(800,600) self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # set the screen sync val = "1" # Set for nVidia linux os.environ["__GL_SYNC_TO_VBLANK"] = val # Set for recent linux Mesa DRI Radeon os.environ["LIBGL_SYNC_REFRESH"] = val qglf = QGLFormat() qglf.setSampleBuffers(True) #qglf.setSwapInterval(1) self.glw = QGLWidget(qglf) self.glw.setAutoBufferSwap(False) self.view.setViewport(self.glw) QTimer.singleShot(0,self.glw.swapBuffers) def swapBuffers(self): # first call the swap on the QGLWidget self.glw.swapBuffers() self.glw.makeCurrent() # The following is taken from the PsychToolbox # Draw a single pixel in left-top area of back-buffer. # This will wait/stall the rendering pipeline # until the buffer flip has happened, aka immediately after the VBL has started. # We need the pixel as "synchronization token", so the following glFinish() really # waits for VBL instead of just "falling through" due to the asynchronous nature of # OpenGL: glDrawBuffer(GL_BACK) # We draw our single pixel with an alpha-value of zero - so effectively it doesn't # change the color buffer - just the z-buffer if z-writes are enabled... glColor4f(0.0,0.0,0.0,0.0) glBegin(GL_POINTS) glVertex2i(10,10) glEnd() # This glFinish() will wait until point drawing is finished, ergo backbuffer was ready # for drawing, ergo buffer swap in sync with start of VBL has happened. glFinish() def show(self): # shows the viewer widget self.view.show()
def __init__(self, model, title = None): super(GraphWidget, self).__init__() self.timerId = 0 scene = QGraphicsScene(self) scene.setItemIndexMethod(QtGui.QGraphicsScene.NoIndex) scene.setSceneRect(-200, -200, 640, 400) self.gscene = scene; self.setScene(scene) self.setCacheMode(QtGui.QGraphicsView.CacheBackground) self.setViewportUpdateMode(QtGui.QGraphicsView.BoundingRectViewportUpdate) self.setRenderHint(QtGui.QPainter.Antialiasing) self.setTransformationAnchor(QtGui.QGraphicsView.AnchorUnderMouse) self.setResizeAnchor(QtGui.QGraphicsView.AnchorViewCenter) self.model = model; self.whitebrush = QBrush(Qt.white); self.redbrush = QBrush(Qt.red) self.drawNetwork(self.gscene, self.model); #setttings of the window self.scale(1.2,1.2); self.setMinimumSize(640, 480); if title == None: self.setWindowTitle("Network Visualisation"); else: self.setWindowTitle("Network Visualisation -" + title);
def main(): app = QApplication(sys.argv) grview = QGraphicsView() scene = QGraphicsScene() scene.setSceneRect(0, 0, 680, 459) scene.addPixmap(QPixmap('01.png')) grview.setScene(scene) item = GraphicsRectItem(0, 0, 300, 150) scene.addItem(item) grview.fitInView(scene.sceneRect(), Qt.KeepAspectRatio) grview.show() sys.exit(app.exec_())
def __init__(self, *args): scene = QGraphicsScene(args[0]) scene.setSceneRect(0,0,600.0,SCENE_HEIGHT) QGraphicsView.__init__(self, scene, *args) scene = self.scene() self.yAxis = scene.addLine(PADDING, PADDING, PADDING, scene.height() - PADDING) self.xAxis = scene.addLine(PADDING, scene.height() - PADDING, scene.width() - PADDING, scene.height() - PADDING) self.bars = [] self.barLabels = [] self.xLabels = [] self.yLabels = [] self.values = [] self.show() self.raise_()
def render_drop_shadow_frame(pixmap, shadow_rect, shadow_color, offset, radius, rect_fill_color): pixmap.fill(QColor(0, 0, 0, 0)) scene = QGraphicsScene() rect = QGraphicsRectItem(shadow_rect) rect.setBrush(QColor(rect_fill_color)) rect.setPen(QPen(Qt.NoPen)) scene.addItem(rect) effect = QGraphicsDropShadowEffect(color=shadow_color, blurRadius=radius, offset=offset) rect.setGraphicsEffect(effect) scene.setSceneRect(QRectF(QPointF(0, 0), QSizeF(pixmap.size()))) painter = QPainter(pixmap) scene.render(painter) painter.end() scene.clear() scene.deleteLater() return pixmap
class PlotPreview(QDialog): def __init__(self, thread, parent): QDialog.__init__(self, parent) self.ui = Ui_PlotPreview() self.ui.setupUi(self) self.parent = parent icon = QIcon() icon.addPixmap(QPixmap(":/icons/reload.png"), QIcon.Normal, QIcon.Off) self.update_btn = QPushButton(icon, "Update") self.ui.buttonBox.addButton(self.update_btn, QDialogButtonBox.ApplyRole) self.update_btn.clicked.connect(self.render_image) self._pix = None self._image_list = None self._thread = thread self.scene = QGraphicsScene() self.scene.setSceneRect(0,0,1,1) self.ui.imageView.setScene(self.scene) self.pix_item = None self.ui.imageView.setEnabled(False) self.ui.imageView.setInteractive(False) self.ui.imageView.setDragMode(QGraphicsView.ScrollHandDrag) self.pic_w = None self.pic_c = None self.show_pic_w = None self.show_pic_c = None timer = QTimer(self) timer.setSingleShot(True) timer.setInterval(500) self.timer = timer timer.timeout.connect(self.render_image) if parameters.instance.use_OpenGL: self.ui.imageView.setViewport(QGLWidget(QGLFormat(QGL.SampleBuffers))) def __del__(self): self.ui.imageView.setScene(None) cleanQObject(self) @property def thread(self): '''Thread object drawing the img''' return self._thread @thread.setter def thread(self, value): if self._thread != value: self._thread = value @property def pix(self): '''Image to be previewed. :returntype: `QImage`''' return self._pix @pix.setter def pix(self, pix): self.ui.imageView.setEnabled(True) self._pix = pix if self.pix_item is not None: self.scene.removeItem(self.pix_item) self.pix_item = self.scene.addPixmap(QPixmap.fromImage(pix)) self.scene.setSceneRect(QRectF(self.pix.rect())) if self.show_pic_w: self.show_pic_w.close() self.show_pic_w = None if self.pic_w: self.show_pic_w = QLabel(self, Qt.Window) #self.show_pic_w.setAttribute(Qt.WA_DeleteOnClose) self.show_pic_w.setPicture(self.pic_w) self.show_pic_w.show() self.show_pic_w.raise_() if self.show_pic_c: self.show_pic_c.close() self.show_pic_c = None if self.pic_c: self.show_pic_c = QLabel(self, Qt.Window) #self.show_pic_c.setAttribute(Qt.WA_DeleteOnClose) self.show_pic_c.setPicture(self.pic_c) self.show_pic_c.show() self.show_pic_c.raise_() log_debug("Received image") @property def image_list(self): '''List of images to paint''' return tuple(self._image_list) @image_list.setter def image_list(self, value): value = list(value) if self._image_list != value: self._image_list = value self.ui.imageList.clear() for img in value: self.ui.imageList.addItem(img) self.ui.autoUpdate.setEnabled(True) self.ui.zoomIn.setEnabled(True) self.ui.zoomOut.setEnabled(True) self.ui.zoom1.setEnabled(True) self.ui.zoomFit.setEnabled(True) self.ui.imageList.setEnabled(True) @pyqtSignature("") def on_zoomIn_clicked(self): self.ui.imageView.scale(2,2) @pyqtSignature("") def on_zoomOut_clicked(self): self.ui.imageView.scale(.5,.5) @pyqtSignature("") def on_zoom1_clicked(self): self.ui.imageView.setTransform(QTransform()) @pyqtSignature("") def on_zoomFit_clicked(self): self.ui.imageView.fitInView(QRectF(self.pix.rect()), Qt.KeepAspectRatio) @pyqtSignature("") def request_render_image(self): if self.isVisible(): if parameters.instance.use_thread: self.timer.start() else: self.render_image() @pyqtSignature("") def render_image(self): if self.isVisible(): i = self.ui.imageList.currentIndex() log_debug("Launch computing for image %d" % i) if self.thread.render_single(i) is None: QMessageBox.information(self, "Failed rendering image", "The renderer is busy and could not render the image.\nTry again later") else: self.ui.imageView.setEnabled(False) @pyqtSignature("int") def on_imageList_currentIndexChanged(self, value): self.render_image() @pyqtSignature("bool") def on_autoUpdate_toggled(self, value): self.parent.auto_update = value if value: self.request_render_image() def showEvent(self, event): self.render_image() def reject(self): self.close() def closeEvent(self, event): self.parent.preview_button.setChecked(False) if self.show_pic_w is not None: self.show_pic_w.close() self.show_pic_w = None if self.show_pic_c is not None: self.show_pic_c.close() self.show_pic_c = None
class DualImageView(QGraphicsView): VERTICAL = 0 HORIZONTAL = 1 IMAGE_A = 0 IMAGE_B = 1 # no argument signal images_changed = pyqtSignal() annotations_changed = pyqtSignal() annotation_selected = pyqtSignal(int) no_selection = pyqtSignal() # click/point signals image_a_click = pyqtSignal(int,int) image_b_click = pyqtSignal(int,int) # keyboard key_event = pyqtSignal(int) def __init__(self, main_win): super(QGraphicsView,self).__init__(main_win) self.parent_ = main_win self.main_win_ = main_win self.setInteractive(True) self.setStyleSheet("QGraphicsView { border: none; }") self.scene_ = QGraphicsScene(0,0,0,0,self.parent_) self.image_item_ = self.scene_.addPixmap(QPixmap()) self.image_item_.setPos(0,0) #self.ann_group_ = QGraphicsItemGroup() #self.ann_group_.setPos(0,0) #self.scene_.addItem(self.ann_group_) self.setScene(self.scene_) self.scene_.selectionChanged.connect(self.on_selection_changed) # TODO: handle orientation self.orientation_ = DualImageView.VERTICAL self.images_ = [None, None] self.composite_ = None self.annotations_ = [] self.dim_ = 0 self.offset_ = np.array([0,0]) self.cancel_click_ = False self.images_changed.connect(self.on_images_changed) self.annotations_changed.connect(self.on_annotations_changed) def on_selection_changed(self): log.debug("on_selection_changed") selected = self.scene_.selectedItems() if len(selected) > 0: self.cancel_click_ = True selected = self.scene_.selectedItems()[0] idx = -1 for a in self.annotations_: idx += 1 if a.item == selected: log.debug(" emitting selection {0}".format(idx)) self.annotation_selected.emit(idx) else: self.no_selection.emit() @property def image_b_offset(self): return np.array([0,self.dim_],dtype=np.int32) def point_in_image(self, p): if p[1] < self.dim_: return 0 else: return 1 def point_to_image(self, which, p): if which == DualImageView.IMAGE_B: return p - self.image_b_offset return p def image_to_view(self, which, p): if which == DualImageView.IMAGE_B: return p + self.image_b_offset return p def on_images_changed(self): imga = self.images_[0] imgb = self.images_[1] width = max(imga.shape[1],imgb.shape[1]) heighta = imga.shape[0] heightb = imgb.shape[0] height = heighta + heightb self.dim_ = heighta self.offset_ = np.array([0,heighta]) # this assumes rgb images :-( comp = np.empty((height,width,imga.shape[2]),dtype=imga.dtype) comp[0:heighta,:imga.shape[1],:] = imga comp[heighta:(heighta+heightb),:imgb.shape[1],:] = imgb self.composite_ = comp qimg = qn.array2qimage(self.composite_) pix = QPixmap.fromImage(qimg) self.image_item_.setPixmap(pix) self.scene_.setSceneRect(0,0, width, height) self.repaint() def on_annotations_changed(self): #log.debug("on_annotations_changed") # self.scene_.removeItem(self.ann_group_) # self.ann_group_ = QGraphicsItemGroup() # self.ann_group_.setHandlesChildEvents(False) # self.ann_group_.setPos(0,0) # for a in self.annotations_: # log.debug(" adding item") # self.ann_group_.addToGroup(a.get_item()) # self.scene_.addItem(self.ann_group_) self.repaint() def transform_raw_pt(self, ev): pt = self.mapToScene(ev.x(), ev.y()) return np.array([int(pt.x()), int(pt.y())], dtype=np.int32) def clear(self): self.images_ = [None,None] self.composite_ = None self.annotations_ = None self.images_changed.emit() self.annotations_changed.emit() def set_images(self, img_pair): self.images_ = img_pair self.images_changed.emit() # @property # def annotations(self): # return self.annotations_ # @annotations.setter # def annotations(self, anns): # self.annotations_ = anns # self.annotations_changed.emit() # def set_annotations(self, anns): # self.annotations_ = anns # self.annotations_changed.emit() def paintEvent(self, ev): painter = QPainter(self.viewport()) painter.fillRect(0,0,self.viewport().width(),self.viewport().height(), QColor(0,0,0)) painter.end() QGraphicsView.paintEvent(self, ev) def annotation(self, idx): return self.annotations_[idx] def clear_annotations(self): for a in self.annotations_: self.scene_.removeItem(a.item) self.annotations_ = [] self.annotations_changed.emit() def add_annotation(self, ann): ann.changed.connect(self.on_annotations_changed) self.annotations_.append(ann) self.scene_.addItem(ann.item) self.annotations_changed.emit() return len(self.annotations_) - 1 def remove_last_annotation(self): self.scene_.removeItem(self.annotations_[-1].item) del self.annotations_[-1] self.annotations_changed.emit() def remove_annotation(self, idx): self.scene_.removeItem(self.annotations_[idx].item) del self.annotations_[idx] self.annotations_changed.emit() def mousePressEvent(self, ev): super(DualImageView,self).mousePressEvent(ev) if self.cancel_click_: return log.debug("mouse pressed: " + str(ev)) self.img_local_pt = self.transform_raw_pt(ev) def mouseReleaseEvent(self, ev): super(DualImageView,self).mouseReleaseEvent(ev) if self.cancel_click_: self.cancel_click_ = False return log.debug("mouse released: " + str(ev)) rel_pt = self.transform_raw_pt(ev) delta = rel_pt - self.img_local_pt if abs(delta[0]) < 3 and abs(delta[1] < 3): # it was a successful click self.mouseClicked(self.img_local_pt) else: # recognize this as a rectangle drag self.mouseDragged(self.img_local_pt, delta) def mouseDragged(self, pt, delta): log.debug("mouse dragged: {0}, {1}".format(pt,delta)) def mouseClicked(self, pt): log.debug("mouse clicked: {0}".format(pt)) if pt[1] < self.dim_: self.image_a_click.emit(pt[0],pt[1]) else: self.image_b_click.emit(pt[0],pt[1] - self.dim_) # handle the keyboard events here! def keyPressEvent(self, ev): pass def keyReleaseEvent(self, ev): k = ev.key() self.key_event.emit(k)
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 View(QGraphicsView): TEXT_COLOR = QColor(1,1,1) BOLDISH = QFont("Times", 30, QFont.Bold) NORMALISH = QFont("Times", 30, QFont.Normal) def __init__(self): QGraphicsView.__init__(self) self.resize(1024, 768) self.qtscene = None self.references = [] def display_question(self, question, answers, selected_index = None, correct = None): self._init_scene() x = 50 y = 25 item = QGraphicsSimpleTextItem(question) item.setBrush(self.TEXT_COLOR) item.setFont(self.BOLDISH) item.setX(x) item.setY(y) self.qtscene.addItem(item) self.references.append(item) y += 75 for index, answer in enumerate(answers): index += 1 item = QGraphicsSimpleTextItem("%s) %s" % (index, answer)) item.setBrush(self.TEXT_COLOR) item.setFont(self.NORMALISH) item.setX(x) item.setY(y) item.setAcceptHoverEvents(True) self.qtscene.addItem(item) self.references.append(item) #TODO: do not register click but do show check or not if not selected_index: item.hoverEnterEvent = partial(self.on_hover_answer, item) item.hoverLeaveEvent = partial(self.on_unhover_answer, item) item.mousePressEvent = partial(self.on_click_answer, index) elif selected_index == index: if correct: item = QGraphicsSimpleTextItem(u"\u2713") item.setBrush(QBrush(QColor(0,150,0))) item.setX(0) else: item = QGraphicsSimpleTextItem("X") item.setBrush(QBrush(QColor(255,0,0))) item.setX(3) item.setFont(self.BOLDISH) item.setY(y) self.qtscene.addItem(item) self.references.append(item) y += 50 return x, y def display_answer(self, question, answers, correct_answer, description, selected_index, correct): x, y = self.display_question(question, answers, selected_index, correct) #TODO pass what to check and if right or wrong y += 50 item = QGraphicsSimpleTextItem("Correct Answer: %s" % correct_answer) item.setBrush(self.TEXT_COLOR) font = QFont(self.BOLDISH) font.setUnderline(True) item.setFont(font) item.setX(x) item.setY(y) self.qtscene.addItem(item) self.references.append(item) y += 60 item = QGraphicsSimpleTextItem(make_pretty(description, 55)) item.setBrush(self.TEXT_COLOR) item.setFont(self.NORMALISH) item.setX(x) item.setY(y) self.qtscene.addItem(item) self.references.append(item) item = QPushButton('Next') item.clicked.connect(self.on_next) item.setFont(self.BOLDISH) item.move(x+700, y) self.qtscene.addWidget(item) self.references.append(item) def _init_scene(self): self.qtscene = QGraphicsScene(self) self.qtscene.setSceneRect(QRectF(0, 0, 1000, 750)) brush = QBrush(QColor(240,245,250)) self.qtscene.setBackgroundBrush(brush) self.setScene(self.qtscene) self.references = [] def on_next(self, event): self.next() def on_hover_answer(self, item, event): item.setBrush(QBrush(QColor(100,1,1))) def on_unhover_answer(self, item, event): item.setBrush(self.TEXT_COLOR) def on_click_answer(self, answer_index, event): self.select_answer(answer_index) def keyPressEvent(self, ev): if ev.key() == Qt.Key_Escape: self.quit() def quit(self): qApp.quit()
class OWHierarchicalClustering(widget.OWWidget): name = "Hierarchical Clustering" description = ("Hierarchical clustering based on distance matrix, and " "a dendrogram viewer.") icon = "icons/HierarchicalClustering.svg" priority = 2100 inputs = [("Distances", Orange.misc.DistMatrix, "set_distances")] outputs = [("Selected Data", Orange.data.Table), ("Other Data", Orange.data.Table)] #: Selected linkage linkage = settings.Setting(1) #: Index of the selected annotation item (variable, ...) annotation_idx = settings.Setting(0) #: Selected tree pruning (none/max depth) pruning = settings.Setting(0) #: Maximum depth when max depth pruning is selected max_depth = settings.Setting(10) #: Selected cluster selection method (none, cut distance, top n) selection_method = settings.Setting(0) #: Cut height ratio wrt root height cut_ratio = settings.Setting(75.0) #: Number of top clusters to select top_n = settings.Setting(3) append_clusters = settings.Setting(True) cluster_role = settings.Setting(2) cluster_name = settings.Setting("Cluster") autocommit = settings.Setting(False) #: Cluster variable domain role AttributeRole, ClassRole, MetaRole = 0, 1, 2 def __init__(self, parent=None): super().__init__(parent) self.matrix = None self.items = None self.linkmatrix = None self.root = None self._displayed_root = None self.cutoff_height = 0.0 gui.comboBox(gui.widgetBox(self.controlArea, "Linkage"), self, "linkage", items=LINKAGE, callback=self._invalidate_clustering) box = gui.widgetBox(self.controlArea, "Annotation") self.label_cb = gui.comboBox( box, self, "annotation_idx", callback=self._update_labels) self.label_cb.setModel(itemmodels.VariableListModel()) self.label_cb.model()[:] = ["None", "Enumeration"] box = gui.radioButtons( self.controlArea, self, "pruning", box="Pruning", callback=self._invalidate_pruning ) grid = QGridLayout() box.layout().addLayout(grid) grid.addWidget( gui.appendRadioButton(box, "None", addToLayout=False), 0, 0 ) self.max_depth_spin = gui.spin( box, self, "max_depth", minv=1, maxv=100, callback=self._invalidate_pruning, keyboardTracking=False ) grid.addWidget( gui.appendRadioButton(box, "Max depth", addToLayout=False), 1, 0) grid.addWidget(self.max_depth_spin, 1, 1) box = gui.radioButtons( self.controlArea, self, "selection_method", box="Selection", callback=self._selection_method_changed) grid = QGridLayout() box.layout().addLayout(grid) grid.addWidget( gui.appendRadioButton(box, "Manual", addToLayout=False), 0, 0 ) grid.addWidget( gui.appendRadioButton(box, "Height ratio", addToLayout=False), 1, 0 ) self.cut_ratio_spin = gui.spin( box, self, "cut_ratio", 0, 100, step=1e-1, spinType=float, callback=self._selection_method_changed ) self.cut_ratio_spin.setSuffix("%") grid.addWidget(self.cut_ratio_spin, 1, 1) grid.addWidget( gui.appendRadioButton(box, "Top N", addToLayout=False), 2, 0 ) self.top_n_spin = gui.spin(box, self, "top_n", 1, 20, callback=self._selection_method_changed) grid.addWidget(self.top_n_spin, 2, 1) box.layout().addLayout(grid) self.controlArea.layout().addStretch() box = gui.widgetBox(self.controlArea, "Output") gui.checkBox(box, self, "append_clusters", "Append cluster IDs", callback=self._invalidate_output) ibox = gui.indentedBox(box) name_edit = gui.lineEdit(ibox, self, "cluster_name") name_edit.editingFinished.connect(self._invalidate_output) cb = gui.comboBox( ibox, self, "cluster_role", callback=self._invalidate_output, items=["Attribute", "Class variable", "Meta variable"] ) form = QFormLayout( fieldGrowthPolicy=QFormLayout.AllNonFixedFieldsGrow, labelAlignment=Qt.AlignLeft, spacing=8 ) form.addRow("Name", name_edit) form.addRow("Place", cb) ibox.layout().addSpacing(5) ibox.layout().addLayout(form) ibox.layout().addSpacing(5) gui.auto_commit(box, self, "autocommit", "Send data", "Auto send is on", box=False) self.scene = QGraphicsScene() self.view = QGraphicsView( self.scene, horizontalScrollBarPolicy=Qt.ScrollBarAlwaysOff, verticalScrollBarPolicy=Qt.ScrollBarAlwaysOn, alignment=Qt.AlignLeft | Qt.AlignVCenter ) def axis_view(orientation): ax = pg.AxisItem(orientation=orientation, maxTickLength=7) scene = QGraphicsScene() scene.addItem(ax) view = QGraphicsView( scene, horizontalScrollBarPolicy=Qt.ScrollBarAlwaysOff, verticalScrollBarPolicy=Qt.ScrollBarAlwaysOn, alignment=Qt.AlignLeft | Qt.AlignVCenter ) view.setFixedHeight(ax.size().height()) ax.line = SliderLine(orientation=Qt.Horizontal, length=ax.size().height()) scene.addItem(ax.line) return view, ax self.top_axis_view, self.top_axis = axis_view("top") self.mainArea.layout().setSpacing(1) self.mainArea.layout().addWidget(self.top_axis_view) self.mainArea.layout().addWidget(self.view) self.bottom_axis_view, self.bottom_axis = axis_view("bottom") self.mainArea.layout().addWidget(self.bottom_axis_view) self._main_graphics = QGraphicsWidget() self._main_layout = QGraphicsLinearLayout(Qt.Horizontal) self._main_layout.setSpacing(1) self._main_graphics.setLayout(self._main_layout) self.scene.addItem(self._main_graphics) self.dendrogram = DendrogramWidget() self.dendrogram.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.dendrogram.selectionChanged.connect(self._invalidate_output) self.dendrogram.selectionEdited.connect(self._selection_edited) fm = self.fontMetrics() self.dendrogram.setContentsMargins( 5, fm.lineSpacing() / 2, 5, fm.lineSpacing() / 2 ) self.labels = GraphicsSimpleTextList() self.labels.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.labels.setAlignment(Qt.AlignLeft) self.labels.setMaximumWidth(200) self.labels.layout().setSpacing(0) self._main_layout.addItem(self.dendrogram) self._main_layout.addItem(self.labels) self._main_layout.setAlignment( self.dendrogram, Qt.AlignLeft | Qt.AlignVCenter) self._main_layout.setAlignment( self.labels, Qt.AlignLeft | Qt.AlignVCenter) self.view.viewport().installEventFilter(self) self.top_axis_view.viewport().installEventFilter(self) self.bottom_axis_view.viewport().installEventFilter(self) self._main_graphics.installEventFilter(self) self.cut_line = SliderLine(self.dendrogram, orientation=Qt.Horizontal) self.cut_line.valueChanged.connect(self._dendrogram_slider_changed) self.cut_line.hide() self.bottom_axis.line.valueChanged.connect(self._axis_slider_changed) self.top_axis.line.valueChanged.connect(self._axis_slider_changed) self.dendrogram.geometryChanged.connect(self._dendrogram_geom_changed) self._set_cut_line_visible(self.selection_method == 1) def set_distances(self, matrix): self.matrix = matrix self._invalidate_clustering() self._set_items(matrix.row_items if matrix is not None else None) def _set_items(self, items): self.items = items if items is None: self.label_cb.model()[:] = ["None", "Enumeration"] elif isinstance(items, Orange.data.Table): vars = list(items.domain) self.label_cb.model()[:] = ["None", "Enumeration"] + vars elif isinstance(items, list) and \ all(isinstance(var, Orange.data.Variable) for var in items): self.label_cb.model()[:] = ["None", "Enumeration", "Name"] else: self.label_cb.model()[:] = ["None", "Enumeration"] self.annotation_idx = min(self.annotation_idx, len(self.label_cb.model()) - 1) def handleNewSignals(self): self._update_labels() def _clear_plot(self): self.labels.set_labels([]) self.dendrogram.set_root(None) def _set_displayed_root(self, root): self._clear_plot() self._displayed_root = root self.dendrogram.set_root(root) self._update_labels() self._main_graphics.resize( self._main_graphics.size().width(), self._main_graphics.sizeHint(Qt.PreferredSize).height() ) self._main_graphics.layout().activate() def _update(self): self._clear_plot() distances = self.matrix if distances is not None: # Convert to flat upper triangular distances i, j = numpy.triu_indices(distances.X.shape[0], k=1) distances = distances.X[i, j] method = LINKAGE[self.linkage].lower() Z = scipy.cluster.hierarchy.linkage( distances, method=method ) tree = tree_from_linkage(Z) self.linkmatrix = Z self.root = tree self.top_axis.setRange(tree.value.height, 0.0) self.bottom_axis.setRange(tree.value.height, 0.0) if self.pruning: self._set_displayed_root(prune(tree, level=self.max_depth)) else: self._set_displayed_root(tree) else: self.linkmatrix = None self.root = None self._set_displayed_root(None) self._apply_selection() def _update_labels(self): labels = [] if self.root and self._displayed_root: indices = [leaf.value.index for leaf in leaves(self.root)] if self.annotation_idx == 0: labels = [] elif self.annotation_idx == 1: labels = [str(i) for i in indices] elif isinstance(self.items, Orange.data.Table): var = self.label_cb.model()[self.annotation_idx] col = self.items[:, var] labels = [var.repr_val(next(iter(row))) for row in col] labels = [labels[idx] for idx in indices] else: labels = [] if labels and self._displayed_root is not self.root: joined = leaves(self._displayed_root) labels = [", ".join(labels[leaf.value.first: leaf.value.last]) for leaf in joined] self.labels.set_labels(labels) self.labels.setMinimumWidth(1 if labels else -1) def _invalidate_clustering(self): self._update() self._update_labels() def _invalidate_output(self): self.commit() def _invalidate_pruning(self): if self.root: selection = self.dendrogram.selected_nodes() ranges = [node.value.range for node in selection] if self.pruning: self._set_displayed_root( prune(self.root, level=self.max_depth)) else: self._set_displayed_root(self.root) selected = [node for node in preorder(self._displayed_root) if node.value.range in ranges] self.dendrogram.set_selected_clusters(selected) self._apply_selection() def commit(self): items = getattr(self.matrix, "items", self.items) if not items: # nothing to commit return selection = self.dendrogram.selected_nodes() selection = sorted(selection, key=lambda c: c.value.first) indices = [leaf.value.index for leaf in leaves(self.root)] maps = [indices[node.value.first:node.value.last] for node in selection] selected_indices = list(chain(*maps)) unselected_indices = sorted(set(range(self.root.value.last)) - set(selected_indices)) selected = [items[k] for k in selected_indices] unselected = [items[k] for k in unselected_indices] if not selected: self.send("Selected Data", None) self.send("Other Data", None) return selected_data = unselected_data = None if isinstance(items, Orange.data.Table): c = numpy.zeros(len(items)) for i, indices in enumerate(maps): c[indices] = i c[unselected_indices] = len(maps) mask = c != len(maps) if self.append_clusters: clust_var = Orange.data.DiscreteVariable( str(self.cluster_name), values=["Cluster {}".format(i + 1) for i in range(len(maps))] + ["Other"], ordered=True ) data, domain = items, items.domain attrs = domain.attributes class_ = domain.class_vars metas = domain.metas if self.cluster_role == self.AttributeRole: attrs = attrs + (clust_var,) elif self.cluster_role == self.ClassRole: class_ = class_ + (clust_var,) elif self.cluster_role == self.MetaRole: metas = metas + (clust_var,) domain = Orange.data.Domain(attrs, class_, metas) data = Orange.data.Table(domain, data) data.get_column_view(clust_var)[0][:] = c else: data = items if selected: selected_data = data[mask] if unselected: unselected_data = data[~mask] self.send("Selected Data", selected_data) self.send("Other Data", unselected_data) def sizeHint(self): return QSize(800, 500) def eventFilter(self, obj, event): if obj is self.view.viewport() and event.type() == QEvent.Resize: width = self.view.viewport().width() - 2 self._main_graphics.setMaximumWidth(width) self._main_graphics.setMinimumWidth(width) self._main_graphics.layout().activate() elif event.type() == QEvent.MouseButtonPress and \ (obj is self.top_axis_view.viewport() or obj is self.bottom_axis_view.viewport()): self.selection_method = 1 # Map click point to cut line local coordinates pos = self.top_axis_view.mapToScene(event.pos()) cut = self.top_axis.line.mapFromScene(pos) self.top_axis.line.setValue(cut.x()) # update the line visibility, output, ... self._selection_method_changed() return super().eventFilter(obj, event) def _dendrogram_geom_changed(self): pos = self.dendrogram.pos_at_height(self.cutoff_height) geom = self.dendrogram.geometry() crect = self.dendrogram.contentsRect() self._set_slider_value(pos.x(), geom.width()) self.cut_line.setLength(geom.height()) self.top_axis.resize(crect.width(), self.top_axis.height()) self.top_axis.setPos(geom.left() + crect.left(), 0) self.top_axis.line.setPos(self.cut_line.scenePos().x(), 0) self.bottom_axis.resize(crect.width(), self.bottom_axis.height()) self.bottom_axis.setPos(geom.left() + crect.left(), 0) self.bottom_axis.line.setPos(self.cut_line.scenePos().x(), 0) geom = self._main_graphics.geometry() assert geom.topLeft() == QPointF(0, 0) self.scene.setSceneRect(geom) geom.setHeight(self.top_axis.size().height()) self.top_axis.scene().setSceneRect(geom) self.bottom_axis.scene().setSceneRect(geom) def _axis_slider_changed(self, value): self.cut_line.setValue(value) def _dendrogram_slider_changed(self, value): p = QPointF(value, 0) cl_height = self.dendrogram.height_at(p) self.set_cutoff_height(cl_height) # Sync the cut positions between the dendrogram and the axis. self._set_slider_value(value, self.dendrogram.size().width()) def _set_slider_value(self, value, span): with blocked(self.cut_line): self.cut_line.setValue(value) self.cut_line.setRange(0, span) with blocked(self.top_axis.line): self.top_axis.line.setValue(value) self.top_axis.line.setRange(0, span) with blocked(self.bottom_axis.line): self.bottom_axis.line.setValue(value) self.bottom_axis.line.setRange(0, span) def set_cutoff_height(self, height): self.cutoff_height = height if self.root: self.cut_ratio = 100 * height / self.root.value.height self.select_max_height(height) def _set_cut_line_visible(self, visible): self.cut_line.setVisible(visible) self.top_axis.line.setVisible(visible) self.bottom_axis.line.setVisible(visible) def select_top_n(self, n): root = self._displayed_root if root: clusters = top_clusters(root, n) self.dendrogram.set_selected_clusters(clusters) def select_max_height(self, height): root = self._displayed_root if root: clusters = clusters_at_height(root, height) self.dendrogram.set_selected_clusters(clusters) def _selection_method_changed(self): self._set_cut_line_visible(self.selection_method == 1) if self.root: self._apply_selection() def _apply_selection(self): if not self.root: return if self.selection_method == 0: pass elif self.selection_method == 1: height = self.cut_ratio * self.root.value.height / 100 self.set_cutoff_height(height) pos = self.dendrogram.pos_at_height(height) self._set_slider_value(pos.x(), self.dendrogram.size().width()) elif self.selection_method == 2: self.select_top_n(self.top_n) def _selection_edited(self): # Selection was edited by clicking on a cluster in the # dendrogram view. self.selection_method = 0 self._selection_method_changed()
class ImagesPreviewer(foundations.ui.common.QWidgetFactory(uiFile=UI_FILE)): """ | This class provides the Application images previewer. | It defines methods to navigate through the list of given images ( List of images paths ), zoom in / out and fit the displayed image, etc... """ def __init__(self, parent, paths=None, *args, **kwargs): """ This method initializes the class. :param parent: Object parent. ( QObject ) :param paths: Images paths. ( Tuple / List ) :param \*args: Arguments. ( \* ) :param \*\*kwargs: Keywords arguments. ( \*\* ) """ LOGGER.debug("> Initializing '{0}()' class.".format( self.__class__.__name__)) super(ImagesPreviewer, self).__init__(parent, *args, **kwargs) # --- Setting class attributes. --- self.__container = parent self.__paths = None self.paths = paths self.__uiResourcesDirectory = "resources" self.__uiResourcesDirectory = os.path.join(os.path.dirname(__file__), self.__uiResourcesDirectory) self.__uiPreviousImage = "Previous.png" self.__uiNextImage = "Next.png" self.__uiZoomOutImage = "Zoom_Out.png" self.__uiZoomInImage = "Zoom_In.png" # Ensure the ui object is destroyed on close to avoid memory leaks. self.setAttribute(Qt.WA_DeleteOnClose) self.__graphicsSceneBackgroundColor = QColor(32, 32, 32) self.__minimumZoomFactor = 0.05 self.__maximumZoomFactor = 25 self.__displayGraphicsItemMargin = 32 self.__graphicsSceneWidth = QApplication.desktop().screenGeometry( QApplication.desktop().primaryScreen()).width() * ( 1 / self.__minimumZoomFactor * 1.75) self.__graphicsSceneHeight = QApplication.desktop().screenGeometry( QApplication.desktop().primaryScreen()).height() * ( 1 / self.__minimumZoomFactor * 1.75) self.__wheelZoomFactor = 350.0 self.__keyZoomFactor = 1.20 self.__graphicsView = None self.__graphicsScene = None self.__displayGraphicsItem = None ImagesPreviewer.__initializeUi(self) self.loadImage() #****************************************************************************************************************** #*** Attributes properties. #****************************************************************************************************************** @property def container(self): """ This method is the property for **self.__container** attribute. :return: self.__container. ( QObject ) """ return self.__container @container.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def container(self, value): """ This method is the setter method for **self.__container** attribute. :param value: Attribute value. ( QObject ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "container")) @container.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def container(self): """ This method is the deleter method for **self.__container** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "container")) @property def paths(self): """ This method is the property for **self.__paths** attribute. :return: self.__paths. ( Tuple / List ) """ return self.__paths @paths.setter @foundations.exceptions.handleExceptions(AssertionError) def paths(self, value): """ This method is the setter method for **self.__paths** attribute. :param value: Attribute value. ( Tuple / List ) """ if value is not None: assert type(value) in ( tuple, list ), "'{0}' attribute: '{1}' type is not 'tuple' or 'list'!".format( "paths", value) for element in value: assert type( element ) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format( "paths", element) self.__paths = value @paths.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def paths(self): """ This method is the deleter method for **self.__paths** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "paths")) @property def uiResourcesDirectory(self): """ This method is the property for **self.__uiResourcesDirectory** attribute. :return: self.__uiResourcesDirectory. ( String ) """ return self.__uiResourcesDirectory @uiResourcesDirectory.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def uiResourcesDirectory(self, value): """ This method is the setter method for **self.__uiResourcesDirectory** attribute. :param value: Attribute value. ( String ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "uiResourcesDirectory")) @uiResourcesDirectory.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def uiResourcesDirectory(self): """ This method is the deleter method for **self.__uiResourcesDirectory** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "uiResourcesDirectory")) @property def uiPreviousImage(self): """ This method is the property for **self.__uiPreviousImage** attribute. :return: self.__uiPreviousImage. ( String ) """ return self.__uiPreviousImage @uiPreviousImage.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def uiPreviousImage(self, value): """ This method is the setter method for **self.__uiPreviousImage** attribute. :param value: Attribute value. ( String ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "uiPreviousImage")) @uiPreviousImage.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def uiPreviousImage(self): """ This method is the deleter method for **self.__uiPreviousImage** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "uiPreviousImage")) @property def uiNextImage(self): """ This method is the property for **self.__uiNextImage** attribute. :return: self.__uiNextImage. ( String ) """ return self.__uiNextImage @uiNextImage.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def uiNextImage(self, value): """ This method is the setter method for **self.__uiNextImage** attribute. :param value: Attribute value. ( String ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "uiNextImage")) @uiNextImage.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def uiNextImage(self): """ This method is the deleter method for **self.__uiNextImage** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "uiNextImage")) @property def uiZoomOutImage(self): """ This method is the property for **self.__uiZoomOutImage** attribute. :return: self.__uiZoomOutImage. ( String ) """ return self.__uiZoomOutImage @uiZoomOutImage.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def uiZoomOutImage(self, value): """ This method is the setter method for **self.__uiZoomOutImage** attribute. :param value: Attribute value. ( String ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "uiZoomOutImage")) @uiZoomOutImage.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def uiZoomOutImage(self): """ This method is the deleter method for **self.__uiZoomOutImage** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "uiZoomOutImage")) @property def uiZoomInImage(self): """ This method is the property for **self.__uiZoomInImage** attribute. :return: self.__uiZoomInImage. ( String ) """ return self.__uiZoomInImage @uiZoomInImage.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def uiZoomInImage(self, value): """ This method is the setter method for **self.__uiZoomInImage** attribute. :param value: Attribute value. ( String ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "uiZoomInImage")) @uiZoomInImage.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def uiZoomInImage(self): """ This method is the deleter method for **self.__uiZoomInImage** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "uiZoomInImage")) @property def graphicsSceneBackgroundColor(self): """ This method is the property for **self.__graphicsSceneBackgroundColor** attribute. :return: self.__graphicsSceneBackgroundColor. ( QColors ) """ return self.__graphicsSceneBackgroundColor @graphicsSceneBackgroundColor.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def graphicsSceneBackgroundColor(self, value): """ This method is the setter method for **self.__graphicsSceneBackgroundColor** attribute. :param value: Attribute value. ( QColors ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "graphicsSceneBackgroundColor")) @graphicsSceneBackgroundColor.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def graphicsSceneBackgroundColor(self): """ This method is the deleter method for **self.__graphicsSceneBackgroundColor** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "graphicsSceneBackgroundColor")) @property def graphicsSceneWidth(self): """ This method is the property for **self.__graphicsSceneWidth** attribute. :return: self.__graphicsSceneWidth. ( Integer ) """ return self.__graphicsSceneWidth @graphicsSceneWidth.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def graphicsSceneWidth(self, value): """ This method is the setter method for **self.__graphicsSceneWidth** attribute. :param value: Attribute value. ( Integer ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "graphicsSceneWidth")) @graphicsSceneWidth.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def graphicsSceneWidth(self): """ This method is the deleter method for **self.__graphicsSceneWidth** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "graphicsSceneWidth")) @property def graphicsSceneHeight(self): """ This method is the property for **self.__graphicsSceneHeight** attribute. :return: self.__graphicsSceneHeight. ( Object ) """ return self.__graphicsSceneHeight @graphicsSceneHeight.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def graphicsSceneHeight(self, value): """ This method is the setter method for **self.__graphicsSceneHeight** attribute. :param value: Attribute value. ( Object ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "graphicsSceneHeight")) @graphicsSceneHeight.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def graphicsSceneHeight(self): """ This method is the deleter method for **self.__graphicsSceneHeight** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "graphicsSceneHeight")) @property def minimumZoomFactor(self): """ This method is the property for **self.__minimumZoomFactor** attribute. :return: self.__minimumZoomFactor. ( Float ) """ return self.__minimumZoomFactor @minimumZoomFactor.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def minimumZoomFactor(self, value): """ This method is the setter method for **self.__minimumZoomFactor** attribute. :param value: Attribute value. ( Float ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "minimumZoomFactor")) @minimumZoomFactor.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def minimumZoomFactor(self): """ This method is the deleter method for **self.__minimumZoomFactor** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "minimumZoomFactor")) @property def maximumZoomFactor(self): """ This method is the property for **self.__maximumZoomFactor** attribute. :return: self.__maximumZoomFactor. ( Float ) """ return self.__maximumZoomFactor @maximumZoomFactor.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def maximumZoomFactor(self, value): """ This method is the setter method for **self.__maximumZoomFactor** attribute. :param value: Attribute value. ( Float ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "maximumZoomFactor")) @maximumZoomFactor.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def maximumZoomFactor(self): """ This method is the deleter method for **self.__maximumZoomFactor** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "maximumZoomFactor")) @property def wheelZoomFactor(self): """ This method is the property for **self.__wheelZoomFactor** attribute. :return: self.__wheelZoomFactor. ( Float ) """ return self.__wheelZoomFactor @wheelZoomFactor.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def wheelZoomFactor(self, value): """ This method is the setter method for **self.__wheelZoomFactor** attribute. :param value: Attribute value. ( Float ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "wheelZoomFactor")) @wheelZoomFactor.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def wheelZoomFactor(self): """ This method is the deleter method for **self.__wheelZoomFactor** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "wheelZoomFactor")) @property def keyZoomFactor(self): """ This method is the property for **self.__keyZoomFactor** attribute. :return: self.__keyZoomFactor. ( Float ) """ return self.__keyZoomFactor @keyZoomFactor.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def keyZoomFactor(self, value): """ This method is the setter method for **self.__keyZoomFactor** attribute. :param value: Attribute value. ( Float ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "keyZoomFactor")) @keyZoomFactor.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def keyZoomFactor(self): """ This method is the deleter method for **self.__keyZoomFactor** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "keyZoomFactor")) @property def graphicsView(self): """ This method is the property for **self.__graphicsView** attribute. :return: self.__graphicsView. ( QGraphicsView ) """ return self.__graphicsView @graphicsView.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def graphicsView(self, value): """ This method is the setter method for **self.__graphicsView** attribute. :param value: Attribute value. ( QGraphicsView ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "graphicsView")) @graphicsView.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def graphicsView(self): """ This method is the deleter method for **self.__graphicsView** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "graphicsView")) @property def graphicsScene(self): """ This method is the property for **self.__graphicsScene** attribute. :return: self.__graphicsScene. ( QGraphicsScene ) """ return self.__graphicsScene @graphicsScene.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def graphicsScene(self, value): """ This method is the setter method for **self.__graphicsScene** attribute. :param value: Attribute value. ( QGraphicsScene ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "graphicsScene")) @graphicsScene.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def graphicsScene(self): """ This method is the deleter method for **self.__graphicsScene** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "graphicsScene")) @property def displayGraphicsItem(self): """ This method is the property for **self.__displayGraphicsItem** attribute. :return: self.__displayGraphicsItem. ( QGraphicsItem ) """ return self.__displayGraphicsItem @displayGraphicsItem.setter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def displayGraphicsItem(self, value): """ This method is the setter method for **self.__displayGraphicsItem** attribute. :param value: Attribute value. ( QGraphicsItem ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format( self.__class__.__name__, "displayGraphicsItem")) @displayGraphicsItem.deleter @foundations.exceptions.handleExceptions( foundations.exceptions.ProgrammingError) def displayGraphicsItem(self): """ This method is the deleter method for **self.__displayGraphicsItem** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format( self.__class__.__name__, "displayGraphicsItem")) #****************************************************************************************************************** #*** Class methods. #****************************************************************************************************************** def show(self): """ This method reimplements the :meth:`QWidget.show` method. """ super(ImagesPreviewer, self).show() foundations.ui.common.centerWidgetOnScreen(self) def closeEvent(self, event): """ This method reimplements the :meth:`QWidget.closeEvent` method. :param event: QEvent ( QEvent ) """ LOGGER.debug( "> Removing '{0}' from Images Previewers list.".format(self)) self.__container.imagesPreviewers.remove(self) event.accept() def wheelEvent(self, event): """ This method reimplements the :meth:`QWidget.wheelEvent` method. :param event: QEvent ( QEvent ) """ self.scaleView(pow(1.5, event.delta() / self.__wheelZoomFactor)) def keyPressEvent(self, event): """ This method reimplements the :meth:`QWidget.keyPressEvent` method. :param event: QEvent ( QEvent ) """ key = event.key() if key == Qt.Key_Plus: self.scaleView(self.__keyZoomFactor) elif key == Qt.Key_Minus: self.scaleView(1 / self.__keyZoomFactor) else: super(ImagesPreviewer, self).keyPressEvent(event) def __initializeUi(self): """ This method initializes the Widget ui. """ LOGGER.debug("> Initializing '{0}' ui.".format( self.__class__.__name__)) self.Previous_Image_pushButton.setIcon( QIcon( os.path.join(self.__uiResourcesDirectory, self.__uiPreviousImage))) self.Next_Image_pushButton.setIcon( QIcon(os.path.join(self.__uiResourcesDirectory, self.__uiNextImage))) self.Zoom_In_pushButton.setIcon( QIcon( os.path.join(self.__uiResourcesDirectory, self.__uiZoomInImage))) self.Zoom_Out_pushButton.setIcon( QIcon( os.path.join(self.__uiResourcesDirectory, self.__uiZoomOutImage))) len(self.__paths) <= 1 and self.Navigation_frame.hide() LOGGER.debug("> Initializing graphics View.") self.__graphicsView = QGraphicsView() self.__graphicsView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.__graphicsView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.__graphicsView.setTransformationAnchor( QGraphicsView.AnchorUnderMouse) self.__graphicsView.setDragMode(QGraphicsView.ScrollHandDrag) # Reimplementing QGraphicsView wheelEvent method. self.__graphicsView.wheelEvent = self.wheelEvent LOGGER.debug("> Initializing graphics scene.") self.__graphicsScene = QGraphicsScene(self.__graphicsView) self.__graphicsScene.setItemIndexMethod(QGraphicsScene.NoIndex) self.__graphicsScene.setSceneRect( -(float(self.__graphicsSceneWidth)) / 2, -(float(self.__graphicsSceneHeight)) / 2, float(self.__graphicsSceneWidth), float(self.__graphicsSceneHeight)) self.__graphicsView.setScene(self.__graphicsScene) self.__graphicsView.setBackgroundBrush( QBrush(self.__graphicsSceneBackgroundColor)) self.Images_Previewer_frame_gridLayout.addWidget(self.__graphicsView) # Signals / Slots. self.__container.engine.imagesCaches.QImage.contentAdded.connect( self.__engine_imagesCaches_QImage__contentAdded) self.Previous_Image_pushButton.clicked.connect( self.__Previous_Image_pushButton__clicked) self.Next_Image_pushButton.clicked.connect( self.__Next_Image_pushButton__clicked) self.Zoom_Out_pushButton.clicked.connect( self.__Zoom_Out_pushButton__clicked) self.Zoom_In_pushButton.clicked.connect( self.__Zoom_In_pushButton__clicked) self.Zoom_Fit_pushButton.clicked.connect( self.__Zoom_Fit_pushButton__clicked) def __Images_Informations_label_setUi(self): """ This method sets the **Images_Informations_label** Widget ui. """ if not self.__displayGraphicsItem: return image = self.__displayGraphicsItem.image self.Images_Informations_label.setText( "{0} - {1}x{2} px - {3} bit".format( os.path.basename(image.data.path), image.data.width, image.data.height, image.data.bpp / 4)) def __engine_imagesCaches_QImage__contentAdded(self, content): """ This method is triggered by the Application **QImage** images cache when content has been added. :param content: Cache added content. ( List ) """ if not self.__paths: return path = foundations.common.getFirstItem(content) if not path in self.__paths: return image = self.__container.engine.imagesCaches.QImage.getContent(path) self.__setDisplayGraphicsItem(image) def __Previous_Image_pushButton__clicked(self, checked): """ This method is triggered when **Previous_Image_pushButton** Widget is clicked. :param checked: Checked state. ( Boolean ) """ self.loopThroughImages(True) def __Next_Image_pushButton__clicked(self, checked): """ This method is triggered when **Next_Image_pushButton** Widget is clicked. :param checked: Checked state. ( Boolean ) """ self.loopThroughImages() def __Zoom_In_pushButton__clicked(self, checked): """ This method is triggered when **Zoom_In_pushButton** Widget is clicked. :param checked: Checked state. ( Boolean ) """ self.scaleView(self.__keyZoomFactor) def __Zoom_Out_pushButton__clicked(self, checked): """ This method is triggered when **Zoom_Out_pushButton** Widget is clicked. :param checked: Checked state. ( Boolean ) """ self.scaleView(1 / self.__keyZoomFactor) def __Zoom_Fit_pushButton__clicked(self, checked): """ This method is triggered when **Zoom_Fit_pushButton** Widget is clicked. :param checked: Checked state. ( Boolean ) """ self.fitImage() def __clearGraphicsScene(self): """ This method clears the View. """ for graphicsItem in self.__graphicsScene.items(): self.__graphicsScene.removeItem(graphicsItem) def __setDisplayGraphicsItem(self, image): """ This method sets the View using given image. :param image: Image to display. ( Qimage ) """ self.__clearGraphicsScene() LOGGER.debug("> Initializing graphics item.") self.__displayGraphicsItem = Image_QGraphicsItem(image=image) self.__graphicsScene.addItem(self.__displayGraphicsItem) self.__Images_Informations_label_setUi() def loadImage(self, index=0): """ This method loads the display image in the View. :param index: Index to load. ( Integer ) :return: Method success. ( Boolean ) """ if not self.__paths: return False image = sibl_gui.ui.common.getImage(self.__paths[index]) self.__setDisplayGraphicsItem(image) return True def scaleView(self, scaleFactor): """ This method scales the Previewer view. :param scaleFactor: Float ( Float ) :return: Method success. ( Boolean ) """ graphicsView = self.findChild(QGraphicsView) factor = graphicsView.matrix().scale(scaleFactor, scaleFactor).mapRect( QRectF(0, 0, 1, 1)).width() if factor < self.__minimumZoomFactor or factor > self.__maximumZoomFactor: return False graphicsView.scale(scaleFactor, scaleFactor) return True def fitWindow(self): """ This method fits the View window. :return: Method success. ( Boolean ) """ if not self.__displayGraphicsItem: return False desktopWidth = QApplication.desktop().screenGeometry( QApplication.desktop().primaryScreen()).width() desktopHeight = QApplication.desktop().screenGeometry( QApplication.desktop().primaryScreen()).height() width = min(desktopWidth * 0.80, self.__displayGraphicsItem.width) height = min(desktopHeight * 0.80, self.__displayGraphicsItem.height) self.resize(width, height) foundations.ui.common.centerWidgetOnScreen(self) return True def fitImage(self): """ This method fits the image to the View. :return: Method success. ( Boolean ) """ if not self.__displayGraphicsItem: return False self.__graphicsView.fitInView( QRectF( -(self.__displayGraphicsItem.width / 2) - (self.__displayGraphicsItemMargin / 2), -(self.__displayGraphicsItem.height / 2) - (self.__displayGraphicsItemMargin / 2), self.__displayGraphicsItem.width + self.__displayGraphicsItemMargin, self.__displayGraphicsItem.height + self.__displayGraphicsItemMargin), Qt.KeepAspectRatio) return True def loopThroughImages(self, backward=False): """ This method loops through View images. :param backward: Looping backward. ( Boolean ) :return: Method success. ( Boolean ) """ index = self.__paths.index(self.__displayGraphicsItem.image.data.path) index += not backward and 1 or -1 if index < 0: index = len(self.__paths) - 1 elif index > len(self.__paths) - 1: index = 0 self.loadImage(index) return True
class ClassDiagram(QWidget, itab_item.ITabItem): def __init__(self, actions, parent=None): QWidget.__init__(self, parent) itab_item.ITabItem.__init__(self) self.actions = actions self.graphicView = QGraphicsView(self) self.scene = QGraphicsScene() self.graphicView.setScene(self.scene) self.graphicView.setViewportUpdateMode( QGraphicsView.BoundingRectViewportUpdate) vLayout = QVBoxLayout(self) self.setLayout(vLayout) vLayout.addWidget(self.graphicView) self.scene.setItemIndexMethod(QGraphicsScene.NoIndex) self.scene.setSceneRect(-200, -200, 400, 400) self.graphicView.setMinimumSize(400, 400) actualProject = self.actions.ide.explorer.get_actual_project() arrClasses = self.actions._locator.get_classes_from_project( actualProject) #FIXME:dirty need to fix self.mX = -400 self.mY = -320 self.hightestY = self.mY filesList = [] for elem in arrClasses: #loking for paths filesList.append(elem[2]) for path in set(filesList): self.create_class(path) def create_class(self, path): content = file_manager.read_file_content(path) items = introspection.obtain_symbols(content) mYPadding = 10 mXPadding = 10 for classname, classdetail in list(items["classes"].items()): cl = ClassModel(self.graphicView, self.scene) cl.set_class_name(classname) self.fill_clases(cl, classdetail[1]) self.scene.addItem(cl) cl.setPos(self.mX, self.mY) self.mX += cl._get_width() + mXPadding if self.hightestY < self.mY + cl.get_height(): self.hightestY = self.mY + cl.get_height() if self.mX > 2000: self.mX = -400 self.mY += self.hightestY + mYPadding def fill_clases(self, classComponent, classContent): funct = classContent['functions'] classComponent.set_functions_list(funct) attr = classContent['attributes'] classComponent.set_attributes_list(attr) def scale_view(self, scaleFactor): factor = self.graphicView.transform().scale( scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width() if factor > 0.05 and factor < 15: self.graphicView.scale(scaleFactor, scaleFactor) def keyPressEvent(self, event): taskList = { Qt.Key_Plus: lambda: self.scaleView(1.2), Qt.Key_Minus: lambda: self.scaleView(1 / 1.2)} if(event.key() in taskList): taskList[event.key()]() else: QWidget.keyPressEvent(self, event)
class Canvas(QGraphicsView): def __init__(self, window, resultDict, imagePath): QGraphicsView.__init__(self) self.window = window self.pen = QPen(QColor("red")) self.pen.setWidth(0.5) self.canvasScene = QGraphicsScene() self.setScene(self.canvasScene) self.resultDict = resultDict self.imagePath = imagePath self.setBackgroundBrush(QBrush(Qt.black, Qt.SolidPattern)) def drawImage(self, imageFile): """Draw an image on the canvas""" image = QPixmap(imageFile) self.canvasScene.addPixmap(image) return image def drawFeaturePoint(self, pointList): """Draw a feature point on the canvas""" radius = 0.5 width, height = 2, 2 x1, y1, x2, y2 = pointList #Draw ellipse and bounding rect. Is a hacked version! self.canvasScene.addEllipse(x1 - radius + 5, y1 - radius + 3, 2 * radius, 2 * radius, self.pen) self.canvasScene.addEllipse(x2 - radius + self.imageWidth + 10, y2 - radius + 3, 2 * radius, 2 * radius, self.pen) self.canvasScene.addRect(x1 - width / 2. + 5, y1 - height / 2. + 3, width, height, self.pen) self.canvasScene.addRect(x2 - width / 2. + self.imageWidth + 10, y2 - height / 2. + 3, width, height, self.pen) def drawFeatureImages(self, imageFile): """Draw two consecutive images on the screen""" #Load image files path, file_ = os.path.split(imageFile) image1 = QPixmap(os.path.join(path, 'first_' + file_)) image2 = QPixmap(os.path.join(path, 'second_' + file_)) self.imageWidth = image1.width() #Add pixmaps image1Map = self.canvasScene.addPixmap(image1) image2Map = self.canvasScene.addPixmap(image2) #Shift pixmaps to the right position image1Map.setOffset(QPointF(5, 3)) image2Map.setOffset(QPointF(10 + image1.width(), 3)) def drawPolygon(self, Polygon): """Draw a polygon on the canvas""" polygon = QPolygonF() for point in Polygon: polygon.append(QPointF(point[0], point[1])) self.canvasScene.addPolygon(polygon, self.pen) def getWorkerId(self): return self.resultDict.values()[self.index][0][0] def getAssignmentId(self): return self.resultDict.keys()[self.index] def nextImage(self): """Load next image""" self.index += 1 self.canvasScene.clear() if self.index > len(self.resultDict) - 1 or len(self.resultDict) <= 0: self.canvasScene.addText("No annotations to review") self.window.reviewFlag = False self.window.updateTable() else: #Draw Image and Polygon assignmentId = self.resultDict.keys()[self.index] result = self.resultDict[assignmentId] image = result[0][1] pointList = result[0][2] if self.window.segmentation_mode: pointList = [round(float(point), 3) for point in pointList] pointList = zip(*[iter(pointList)] * 2) self.drawImage(os.path.join(self.imagePath, image)) self.drawPolygon(pointList) else: pointList = [round(float(point), 3) for point in pointList] pointList = zip(*[iter(pointList)] * 4) self.drawFeatureImages(os.path.join(self.imagePath, image)) for point in pointList: self.drawFeaturePoint(point) #update scene self.window.setWindowTitle("MTurk Review Tool ({0}/{1}) Rejected: {2} Approved: {3}".format(self.index + 1, len(self.resultDict), len(self.window.rejected), len(self.window.approved))) self.canvasScene.setSceneRect(self.canvasScene.itemsBoundingRect()) self.fitInView(0, 0, self.canvasScene.width(), self.canvasScene.height(), 1) self.canvasScene.update(0, 0, self.canvasScene.width(), self.canvasScene.height())
class GUI(): def __init__(self): # init the widget #QWidget.__init__(self, parent) # set up the scene self.scene = QGraphicsScene() self.scene.setSceneRect(0, 0, 800, 600) # add a view of that scene self.view = QGraphicsView() self.view.setScene(self.scene) self.view.setRenderHint(QPainter.Antialiasing) self.view.setFixedSize(800, 600) self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # set the screen sync to vertical retrace val = "1" # Set for nVidia linux os.environ["__GL_SYNC_TO_VBLANK"] = val # Set for recent linux Mesa DRI Radeon os.environ["LIBGL_SYNC_REFRESH"] = val qglf = QGLFormat() qglf.setSampleBuffers(True) self.glw = QGLWidget(qglf) self.glw.setAutoBufferSwap(False) self.view.setViewport(self.glw) #self.view.showFullScreen() self.view.show() self.last_finish = 0 QTimer.singleShot(0, self.glw.swapBuffers) def swapBuffers(self): # first call the swap on the QGLWidget start = long(now() * 1000) self.glw.swapBuffers() #self.glw.makeCurrent() # The following is taken from the PsychToolbox # Draw a single pixel in left-top area of back-buffer. # This will wait/stall the rendering pipeline # until the buffer flip has happened, aka immediately after the VBL has started. # We need the pixel as "synchronization token", so the following glFinish() really # waits for VBL instead of just "falling through" due to the asynchronous nature of # OpenGL: glDrawBuffer(GL_BACK) # We draw our single pixel with an alpha-value of zero - so effectively it doesn't # change the color buffer - just the z-buffer if z-writes are enabled... glColor4f(0.0, 0.0, 0.0, 0.0) glBegin(GL_POINTS) glVertex2i(10, 10) glEnd() # This glFinish() will wait until point drawing is finished, ergo backbuffer was ready # for drawing, ergo buffer swap in sync with start of VBL has happened. glFinish() finish = long(now() * 1000) fdiff = finish - self.last_finish self.last_finish = finish return (start, finish - start, fdiff)
class ProfileGraphViewer( QWidget ): " Profiling results as a graph " escapePressed = pyqtSignal() def __init__( self, scriptName, params, reportTime, dataFile, stats, parent = None ): QWidget.__init__( self, parent ) self.__dataFile = dataFile self.__script = scriptName self.__reportTime = reportTime self.__params = params self.__stats = stats project = GlobalData().project if project.isLoaded(): self.__projectPrefix = os.path.dirname( project.fileName ) else: self.__projectPrefix = os.path.dirname( scriptName ) if not self.__projectPrefix.endswith( os.path.sep ): self.__projectPrefix += os.path.sep self.__createLayout() self.__getDiagramLayout() self.__viewer.setScene( self.__scene ) return def setFocus( self ): " Sets the focus properly " self.__viewer.setFocus() return def __isOutsideItem( self, fileName ): " Detects if the record should be shown as an outside one " return not fileName.startswith( self.__projectPrefix ) def __createLayout( self ): " Creates the widget layout " totalCalls = self.__stats.total_calls totalPrimitiveCalls = self.__stats.prim_calls # The calls were not induced via recursion totalTime = self.__stats.total_tt txt = "<b>Script:</b> " + self.__script + " " + self.__params.arguments + "<br>" \ "<b>Run at:</b> " + self.__reportTime + "<br>" + \ str( totalCalls ) + " function calls (" + \ str( totalPrimitiveCalls ) + " primitive calls) in " + \ FLOAT_FORMAT % totalTime + " CPU seconds" summary = QLabel( txt ) summary.setToolTip( txt ) summary.setSizePolicy( QSizePolicy.Ignored, QSizePolicy.Fixed ) summary.setFrameStyle( QFrame.StyledPanel ) summary.setAutoFillBackground( True ) summaryPalette = summary.palette() summaryBackground = summaryPalette.color( QPalette.Background ) summaryBackground.setRgb( min( summaryBackground.red() + 30, 255 ), min( summaryBackground.green() + 30, 255 ), min( summaryBackground.blue() + 30, 255 ) ) summaryPalette.setColor( QPalette.Background, summaryBackground ) summary.setPalette( summaryPalette ) self.__scene = QGraphicsScene() self.__viewer = DiagramWidget() self.__viewer.escapePressed.connect( self.__onESC ) vLayout = QVBoxLayout() vLayout.setContentsMargins( 0, 0, 0, 0 ) vLayout.setSpacing( 0 ) vLayout.addWidget( summary ) vLayout.addWidget( self.__viewer ) self.setLayout( vLayout ) return def __getDiagramLayout( self ): " Runs external tools to get the diagram layout " # Preparation: build a map of func ID -> fileName + line funcMap = {} index = 0 for func, props in self.__stats.stats.items(): funcMap[ index ] = ( func[ 0 ], func[ 1 ] ) index += 1 # First step is to run grpof2dot gprof2dot = thirdpartyDir + "gprof2dot" + os.path.sep + "gprof2dot.py" outputFile = self.__dataFile + ".dot" nodeLimit = Settings().profileNodeLimit edgeLimit = Settings().profileEdgeLimit dotSpec = safeRun( [ gprof2dot, '-n', str( nodeLimit ), '-e', str( edgeLimit ), '-f', 'pstats', '-o', outputFile, self.__dataFile ] ) graphDescr = safeRun( [ "dot", "-Tplain", outputFile ] ) graph = getGraphFromPlainDotData( graphDescr ) graph.normalize( self.physicalDpiX(), self.physicalDpiY() ) self.__scene.clear() self.__scene.setSceneRect( 0, 0, graph.width, graph.height ) for edge in graph.edges: self.__scene.addItem( FuncConnection( edge ) ) if edge.label != "": self.__scene.addItem( FuncConnectionLabel( edge ) ) for node in graph.nodes: fileName = "" lineNumber = 0 isOutside = True nodeID, newLabel = extractNodeID( node.label ) if nodeID != -1: node.label = newLabel # Now, detect the file name/line number and # if it belongs to the project ( fileName, lineNumber ) = funcMap[ nodeID ] self.__scene.addItem( Function( node, fileName, lineNumber, self.__isOutsideItem( fileName ) ) ) return def __onESC( self ): " Triggered when ESC is clicked " self.escapePressed.emit() return def onCopy( self ): " Copies the diagram to the exchange buffer " self.__viewer.onCopy() return def onSaveAs( self, fileName ): " Saves the diagram to a file " self.__viewer.onSaveAs( fileName ) return def zoomIn( self ): " Triggered on the 'zoom in' button " self.__viewer.zoomIn() return def zoomOut( self ): " Triggered on the 'zoom out' button " self.__viewer.zoomOut() return def resetZoom( self ): " Triggered on the 'zoom reset' button " self.__viewer.resetZoom() return
class GeorefDialog(QDialog, Ui_GeorefDialogBase): def __init__(self, types, parent=None): super(GeorefDialog, self).__init__(parent) self.setupUi(self) # Internal variables self._closeOnDone = False self._types = {} self._georeferencer = None self._types = types self._scene = QGraphicsScene(self) self._georeferencer = Georeferencer(self) self._georeferencer.status.connect(self._updateStatus) self._georeferencer.error.connect(self._updateError) # Init the gui for group in self._types: self.typeCombo.addItem(self._types[group]['name'], group) self.typeCombo.setCurrentIndex(0) for scale in Scale.Scale: self.scaleCombo.addItem(Scale.Label[scale], scale) self.scaleCombo.setCurrentIndex(Scale.OneToTwenty) self.processButton.clicked.connect(self._process) self.saveButton.clicked.connect(self._save) self.runButton.clicked.connect(self._run) self.closeButton.clicked.connect(self._close) self.siteEdit.textChanged.connect(self._updateGeoreference) self.typeCombo.currentIndexChanged.connect(self._updateGeoreference) self.scaleCombo.currentIndexChanged.connect(self._updateGeoreference) self.numberSpin.valueChanged.connect(self._updateGeoreference) self.suffixEdit.textChanged.connect(self._updateGeoreference) self.eastSpin.valueChanged.connect(self._updateGeoreference) self.northSpin.valueChanged.connect(self._updateGeoreference) def loadImage(self, inputFile): self._setStatusLabel('load', ProcessStatus.Running) if (not inputFile.exists()): self._showStatus('ERROR: Input file not found! File path was ' + inputFile.absoluteFilePath()) self._setStatusLabel('load', ProcessStatus.Failure) return False self._inputFile = inputFile pixmap = QPixmap(self._inputFile.absoluteFilePath()) if pixmap.isNull(): self._signalError('Loading of raw image failed.') return pixmap = QPixmap(self._inputFile.absoluteFilePath()) w = pixmap.width() h = pixmap.height() self._scene.addPixmap(pixmap) self._scene.setSceneRect(QRectF(0, 0, w, h)) self.planView.setSceneView(self._scene, QRectF(0, 0, w, h)) self.headerView.setSceneView(self._scene, QRectF(0, 0, w, 200)) self.footerView.setSceneView(self._scene, QRectF(100, h - 600, w - 200, 500)) self.gcpWidget1.setScene(self._scene, 250, 100, 2) self.gcpWidget2.setScene(self._scene, 250, 3050, 2) self.gcpWidget3.setScene(self._scene, 3200, 3050, 2) self.gcpWidget4.setScene(self._scene, 3200, 100, 2) self.inputFileNameLabel.setText(self._inputFile.baseName()) drawing = Drawing(self._inputFile) if drawing.isValid(): self.siteEdit.setText(drawing.item().siteCode()) self.typeCombo.setCurrentIndex( self.typeCombo.findData(drawing.item().classCode())) self.numberSpin.setValue(int(drawing.item().itemId()) or 0) self.eastSpin.setValue(drawing.easting() or 0) self.northSpin.setValue(drawing.northing() or 0) self.suffixEdit.setText(drawing.suffix()) self._updateFileNames(drawing) self._updateGeoPoints() pointFile = self.pointFileInfo() if pointFile.exists(): self._loadGcp(pointFile.absoluteFilePath()) self._setStatusLabel('load', ProcessStatus.Success) QCoreApplication.processEvents() return True return False def _loadGcp(self, path): gc = Georeferencer.loadGcpFile(path) gcTo = Transform() for index in gc.points(): gcp = gc.point(index) if gcp.map() == self.gcpWidget1.gcp().map(): gcTo.setPoint(1, gcp) elif gcp.map() == self.gcpWidget2.gcp().map(): gcTo.setPoint(2, gcp) elif gcp.map() == self.gcpWidget3.gcp().map(): gcTo.setPoint(3, gcp) elif gcp.map() == self.gcpWidget4.gcp().map(): gcTo.setPoint(4, gcp) if gcTo.isValid() and len(gcTo.points()) == 4: self.gcpWidget1.setRaw(gcTo.point(1).raw()) self.gcpWidget2.setRaw(gcTo.point(2).raw()) self.gcpWidget3.setRaw(gcTo.point(3).raw()) self.gcpWidget4.setRaw(gcTo.point(4).raw()) def _updateGeoPoints(self): mapUnits = Scale.Factor[self.drawingScale()] local1 = QPointF(self.eastSpin.value(), self.northSpin.value() + mapUnits) local2 = QPointF(self.eastSpin.value(), self.northSpin.value()) local3 = QPointF(self.eastSpin.value() + mapUnits, self.northSpin.value()) local4 = QPointF(self.eastSpin.value() + mapUnits, self.northSpin.value() + mapUnits) if self.drawingType() == 'sec': self.gcpWidget1.setGeo(local1, QgsPoint(local1)) self.gcpWidget2.setGeo(local2, QgsPoint(local2)) self.gcpWidget3.setGeo(local3, QgsPoint(local3)) self.gcpWidget4.setGeo(local4, QgsPoint(local4)) return typ = self._type() gridLayer = typ['grid'] features = gridLayer.getFeatures() localX = gridLayer.fieldNameIndex(typ['local_x']) localY = gridLayer.fieldNameIndex(typ['local_y']) for feature in features: local = QPoint(feature.attributes()[localX], feature.attributes()[localY]) map = geometry.toPoint(feature.geometry().geometry()) if local == local1: self.gcpWidget1.setGeo(local, map) elif local == local2: self.gcpWidget2.setGeo(local, map) elif local == local3: self.gcpWidget3.setGeo(local, map) elif local == local4: self.gcpWidget4.setGeo(local, map) def _updateGeoreference(self): self._updateFileNames(self.drawing()) self._updateGeoPoints() def _updateFileNames(self, drawing): self.rawFileNameLabel.setText(drawing.baseName()) self.geoFileNameLabel.setText(drawing.baseName() + self._type()['suffix']) def _toggleUi(self, status): self.processButton.setEnabled(status) self.saveButton.setEnabled(status) self.runButton.setEnabled(status) self.closeButton.setEnabled(status) self.siteEdit.setEnabled(status) self.typeCombo.setEnabled(status) self.numberSpin.setEnabled(status) self.suffixEdit.setEnabled(status) self.eastSpin.setEnabled(status) self.northSpin.setEnabled(status) self.cropCheck.setEnabled(status) self.addToMapCheck.setEnabled(status) self.gcpWidget1.setEnabled(status) self.gcpWidget2.setEnabled(status) self.gcpWidget3.setEnabled(status) self.gcpWidget4.setEnabled(status) self.planView.setEnabled(status) if (status): self.progressBar.setRange(0, 100) else: self.progressBar.setRange(0, 0) def drawing(self): return Drawing(self.item(), self.easting(), self.northing(), self.suffix(), self.rawFileName()) def item(self): return Item(self.siteCode(), self.classCode(), self.itemId()) def siteCode(self): return self.siteEdit.text().strip() def classCode(self): return self.drawingType() def itemId(self): return unicode(self.numberSpin.value()) def drawingType(self): return self.typeCombo.itemData(self.typeCombo.currentIndex()) def drawingScale(self): return self.scaleCombo.itemData(self.scaleCombo.currentIndex()) def easting(self): return self.eastSpin.value() def northing(self): return self.northSpin.value() def suffix(self): return self.suffixEdit.text().strip() def inputFileName(self): return self.inputFileNameLabel.text().strip() def rawFileName(self): return self.rawFileNameLabel.text().strip() def rawFileInfo(self): return QFileInfo(self._type()['raw'], self.rawFileName() + '.' + self._inputFile.suffix()) def pointFileInfo(self): return QFileInfo( self._type()['raw'], self.rawFileName() + '.' + self._inputFile.suffix() + '.points') def geoFileName(self): return self.geoFileNameLabel.text().strip() def geoFileInfo(self): return QFileInfo(self._type()['geo'], self.geoFileName() + '.tif') def _type(self): return self._types[self.drawingType()] def _updateStatus(self, step, status): self._setStatusLabel(step, status) self._showStatus(Georeferencer.Label[step] + ': ' + ProcessStatus.Label[status]) if step == Georeferencer.Stop and status == ProcessStatus.Success: if self._closeOnDone: self._close() else: self._toggleUi(True) def _updateError(self, step, msg): self._setStatusLabel(step, ProcessStatus.Failure) self._showStatus(msg) self._toggleUi(True) def _showStatus(self, text): self.statusBar.showMessage(text) def _save(self): self._copyInputFile() self._saveGcp() self._close() def _copyInputFile(self): if self.inputFileName() != self.rawFileName() or self._inputFile.dir( ) != self._type()['raw']: QFile.copy(self._inputFile.absoluteFilePath(), self.rawFileInfo().absoluteFilePath()) def _saveGcp(self): gc = self._gc() if (gc.isValid()): Georeferencer.writeGcpFile(gc, self.pointFileInfo().absoluteFilePath()) def _run(self): self._runGeoreference(False) def _process(self): self._runGeoreference(True) def _close(self): if (self._georeferencer.step() == Georeferencer.Stop): self.accept() else: self.reject() def _gc(self): gc = Transform() gc.crs = self._type()['crs'] gc.setPoint(1, self.gcpWidget1.gcp()) gc.setPoint(2, self.gcpWidget2.gcp()) gc.setPoint(3, self.gcpWidget3.gcp()) gc.setPoint(4, self.gcpWidget4.gcp()) return gc def _runGeoreference(self, closeOnDone): self._closeOnDone = closeOnDone gc = self._gc() if (not gc.isValid()): self._showStatus('ERROR: Please set all 4 Ground Control Points!') return self._toggleUi(False) self._copyInputFile() QCoreApplication.processEvents() self._georeferencer.run(gc, self.rawFileInfo(), self.pointFileInfo(), self.geoFileInfo()) def _finished(self, step, status): if step == Georeferencer.Stop and status == ProcessStatus.Success and self._closeOnDone: self._close() else: self._toggleUi(True) def _setStatusLabel(self, step, status): if step == 'load': label = self.loadStatusLabel elif step == Georeferencer.Crop: label = self.cropStatusLabel elif step == Georeferencer.Translate: label = self.translateStatusLabel elif step == Georeferencer.Warp: label = self.warpStatusLabel elif step == Georeferencer.Overview: label = self.overviewStatusLabel else: return if status == ProcessStatus.Success: label.setPixmap(QPixmap(':/plugins/ark/georef/success.png')) elif status == ProcessStatus.Failure: label.setPixmap(QPixmap(':/plugins/ark/georef/failure.png')) elif status == ProcessStatus.Running: label.setPixmap(QPixmap(':/plugins/ark/georef/running.png')) else: label.setPixmap(QPixmap(':/plugins/ark/georef/unknown.png'))
self.bars.append(bar) if i + 1 == len(values): xLabel = scene.addText("X") else: xLabel = scene.addText("%d" % (i)) xLabel.setPos(curX + BAR_WIDTH / 2 - xLabel.boundingRect().width() /2, h - xLabel.boundingRect().height()) self.xLabels.append(xLabel) barLabel = scene.addText("%d" % (value)) barLabel.setPos(curX + BAR_WIDTH / 2 - barLabel.boundingRect().width()/2, h - (bottomLine - top) - PADDING - barLabel.boundingRect().height()) self.barLabels.append(barLabel) curX += BAR_WIDTH + BAR_PADDING scene.setSceneRect(0,0,curX + PADDING, SCENE_HEIGHT) self.updateGeometry() def sizeHint(self): #import pdb; pdb.set_trace() size = self.sceneRect().size() return QSize(int(size.width()), int(size.height() + PADDING)) if __name__ == "__main__": app = QApplication(sys.argv) scene = QGraphicsScene() scene.setSceneRect(0,0,500.0,500.0) window = QBarGraph() window.setValues([50,20,75,205, 15, 400, 6000]) result = app.exec_() sys.exit(result)
class ProfileGraphViewer(QWidget): " Profiling results as a graph " escapePressed = pyqtSignal() def __init__(self, scriptName, params, reportTime, dataFile, stats, parent=None): QWidget.__init__(self, parent) self.__dataFile = dataFile self.__script = scriptName self.__reportTime = reportTime self.__params = params self.__stats = stats project = GlobalData().project if project.isLoaded(): self.__projectPrefix = os.path.dirname(project.fileName) else: self.__projectPrefix = os.path.dirname(scriptName) if not self.__projectPrefix.endswith(os.path.sep): self.__projectPrefix += os.path.sep self.__createLayout() self.__getDiagramLayout() self.__viewer.setScene(self.__scene) return def setFocus(self): " Sets the focus properly " self.__viewer.setFocus() return def __isOutsideItem(self, fileName): " Detects if the record should be shown as an outside one " return not fileName.startswith(self.__projectPrefix) def __createLayout(self): " Creates the widget layout " totalCalls = self.__stats.total_calls totalPrimitiveCalls = self.__stats.prim_calls # The calls were not induced via recursion totalTime = self.__stats.total_tt txt = "<b>Script:</b> " + self.__script + " " + self.__params.arguments + "<br>" \ "<b>Run at:</b> " + self.__reportTime + "<br>" + \ str( totalCalls ) + " function calls (" + \ str( totalPrimitiveCalls ) + " primitive calls) in " + \ FLOAT_FORMAT % totalTime + " CPU seconds" summary = QLabel(txt) summary.setToolTip(txt) summary.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed) summary.setFrameStyle(QFrame.StyledPanel) summary.setAutoFillBackground(True) summaryPalette = summary.palette() summaryBackground = summaryPalette.color(QPalette.Background) summaryBackground.setRgb(min(summaryBackground.red() + 30, 255), min(summaryBackground.green() + 30, 255), min(summaryBackground.blue() + 30, 255)) summaryPalette.setColor(QPalette.Background, summaryBackground) summary.setPalette(summaryPalette) self.__scene = QGraphicsScene() self.__viewer = DiagramWidget() self.__viewer.escapePressed.connect(self.__onESC) vLayout = QVBoxLayout() vLayout.setContentsMargins(0, 0, 0, 0) vLayout.setSpacing(0) vLayout.addWidget(summary) vLayout.addWidget(self.__viewer) self.setLayout(vLayout) return def __getDiagramLayout(self): " Runs external tools to get the diagram layout " # Preparation: build a map of func ID -> fileName + line funcMap = {} index = 0 for func, props in self.__stats.stats.items(): funcMap[index] = (func[0], func[1]) index += 1 # First step is to run grpof2dot gprof2dot = thirdpartyDir + "gprof2dot" + os.path.sep + "gprof2dot.py" outputFile = self.__dataFile + ".dot" nodeLimit = Settings().profileNodeLimit edgeLimit = Settings().profileEdgeLimit dotSpec = safeRun([ gprof2dot, '-n', str(nodeLimit), '-e', str(edgeLimit), '-f', 'pstats', '-o', outputFile, self.__dataFile ]) graphDescr = safeRun(["dot", "-Tplain", outputFile]) graph = getGraphFromPlainDotData(graphDescr) graph.normalize(self.physicalDpiX(), self.physicalDpiY()) self.__scene.clear() self.__scene.setSceneRect(0, 0, graph.width, graph.height) for edge in graph.edges: self.__scene.addItem(FuncConnection(edge)) if edge.label != "": self.__scene.addItem(FuncConnectionLabel(edge)) for node in graph.nodes: fileName = "" lineNumber = 0 isOutside = True nodeID, newLabel = extractNodeID(node.label) if nodeID != -1: node.label = newLabel # Now, detect the file name/line number and # if it belongs to the project (fileName, lineNumber) = funcMap[nodeID] self.__scene.addItem( Function(node, fileName, lineNumber, self.__isOutsideItem(fileName))) return def __onESC(self): " Triggered when ESC is clicked " self.escapePressed.emit() return def onCopy(self): " Copies the diagram to the exchange buffer " self.__viewer.onCopy() return def onSaveAs(self, fileName): " Saves the diagram to a file " self.__viewer.onSaveAs(fileName) return def zoomIn(self): " Triggered on the 'zoom in' button " self.__viewer.zoomIn() return def zoomOut(self): " Triggered on the 'zoom out' button " self.__viewer.zoomOut() return def resetZoom(self): " Triggered on the 'zoom reset' button " self.__viewer.resetZoom() return
# Hmm, obviously function needs an explicit add to the scene.. self.scene.addItem( self.function ) return self.function if __name__ == '__main__': import sys # this is to be factored out into a general loader. app = QApplication(sys.argv) width = 520 height = 520 scene = QGraphicsScene() scene.setSceneRect(0, 0, width, height) view = QGraphicsView() view.setScene(scene) view.setRenderHint(QPainter.Antialiasing) ccs = CartesianCoordinateSystemWidget(scene, width, height, 10, -5,5,-1,10) # coordinates are always relative to coordinate system, as it should be #point1 = ccs.addPoint(3,3,10) #point2 = ccs.addPointDependent(point1,1,1,10) #point3 = ccs.addPointDependent(point2,-1,0,10,0,0,100) function = '2.71**x' # two points on a function
class Window(QWidget): ''' The MainWindow widget ''' def __init__(self, game): super().__init__() self.game = game self.game.ui = self self.setWindowTitle('WordJuggler') self.resize(800, 600) self.setStyleSheet('QGroupBox { border:0; font:bold;' + 'padding:20px 10px; min-width:220px; }') self.board = BoardItem(game.width, game.height) self.rack = RackItem(game.rack_size, game.width, game.height) self.scene = QGraphicsScene() self.scene.setBackgroundBrush(QBrush(QColor('#f9ece0'))) self.scene.addItem(self.board) self.scene.addItem(self.rack) self.scene.setSceneRect(self.scene.itemsBoundingRect()) self.view = BoardView(self.scene, self) self.view.letterChanged.connect(self.letterChanged) self.ranking = QGroupBox('Rankings') self.rankings = QLabel() rankings = QVBoxLayout() rankings.addWidget(self.rankings) self.ranking.setLayout(rankings) self.statistic = QGroupBox('Statistics') self.statistics = QLabel() statistics = QVBoxLayout() statistics.addWidget(self.statistics) self.statistic.setLayout(statistics) self.move = QGroupBox('Last 10 Moves') self.moves = QLabel() moves = QVBoxLayout() moves.addWidget(self.moves) self.move.setLayout(moves) self.buttons = QVBoxLayout() self.buttons.setSpacing(3) self.continue_button = QPushButton('Place &Word') self.continue_button.setEnabled(False) self.continue_button.setFixedSize(130, 25) self.continue_button.clicked.connect(self.continueClicked) self.pass_button = QPushButton('&Pass') self.pass_button.setEnabled(False) self.pass_button.setFixedSize(130, 25) self.pass_button.clicked.connect(self.passClicked) self.exchange_button = QPushButton('&Exchange') self.exchange_button.setEnabled(False) self.exchange_button.setFixedSize(130, 25) self.exchange_button.clicked.connect(self.exchangeClicked) self.buttons.addWidget(self.exchange_button, alignment=Qt.AlignCenter) self.buttons.addWidget(self.pass_button, alignment=Qt.AlignCenter) self.buttons.addWidget(self.continue_button, alignment=Qt.AlignCenter) information = QVBoxLayout() information.setMargin(20) information.setSpacing(20) information.addWidget(self.ranking) information.addWidget(self.statistic) information.addWidget(self.move) information.addStretch() information.addLayout(self.buttons) layout = QHBoxLayout() layout.setSpacing(0) layout.setMargin(0) layout.addWidget(self.view) layout.addLayout(information) self.setLayout(layout) self.show() for player in self.game.players: player.played_cb = self.playerDone self.playerNext() def update(self, *args, **kwargs): self.rankings.setText( '<br>'.join('%i. <font color=%s>%s</font> (%i points)' % (i + 1, player.color, player.name, player.score) for i,player in enumerate(sorted(self.game.players, reverse=True, key=attrgetter('score'))))) self.statistics.setText(('Total Players: %i\n' + 'Placed Words: %i\n' + 'Remaining Letters: %i') % (len(self.game.players), len(list(self.game.board.get_words())), self.game.letters.remaining_letters)) moves = [] for i,(player,move) in list(enumerate(self.game.moves))[-10:]: if move[0] == Player.PASS: desc = 'Pass' elif move[0] == Player.EXCHANGE_LETTERS: desc = 'Exchange (%s,%s)' % move[1:] else: desc = 'Word (%i,%i,%s,%s,%i)' % move[1:] moves.append('%i. <font color=%s>%s</font>' % (i + 1, player.color, desc)) self.moves.setText('<br>'.join(moves)) super().update(*args, **kwargs) def letterChanged(self): ''' As soon as a letter changes we need to en/disable all controls ''' self.exchange_button.setEnabled(False) self.exchange_button.setText('Exchange') if self.game.letters.remaining_letters >= self.game.rack_size: selected = ''.join(l.char for l in self.scene.items() if type(l) is LetterItem and l.selected) if selected: self.exchange_button.setText('Exchange: %s' % selected) self.exchange_button.setEnabled(True) self.pass_button.setEnabled(True) self.continue_button.setEnabled(True if self.board.validNewWord() else False) def playerNext(self): player = self.game.next_player() self.letterChanged() self.update() player.update_letters() self.rack.name = self.game.current_player.name self.rack.color = self.game.current_player.color for i,letter in enumerate(player.letters): item = LetterItem(letter, self.game.letters.get_score(letter), player.color) item.own(self.rack, i, move=False) self.scene.addItem(item) self.update() player.played_cb = self.playerDone player.play() def continueClicked(self): if type(self.game.current_player) is Human: self.game.current_player.continue_cb() def passClicked(self): if type(self.game.current_player) is Human: self.game.current_player.pass_cb() def exchangeClicked(self): if type(self.game.current_player) is Human: self.game.current_player.exchange_cb() def playerDone(self, player, move, *args): self.exchange_button.setEnabled(False) self.exchange_button.setText('Exchange') self.pass_button.setEnabled(False) self.continue_button.setEnabled(False) for item in self.scene.items(): if type(item) is LetterItem and not item.is_safe and \ not item.deleted: item.own(None) item.fade() for x,y,letter in self.game.board: if not self.board.getLetter(x, y): item = LetterItem(letter.char, self.game.letters.get_score(letter), letter.player.color, safe=True) item.own(self.board, x, y, move=False) self.scene.addItem(item) self.update() if self.game.state() == self.game.RUNNING: self.game.current_player.update_letters() self.playerNext() else: self.game.finish_score() self.update() self.gameOver() def getLetters(self, count, msg=''): print('random letters: %s' % self.game.get_letters_old(count)) while True: text,ok = QInputDialog.getText(self, 'New Letters', 'Player: <font color=%s>%s</font><br>' % ( self.game.current_player.color, self.game.current_player.name) + msg + 'Tell me %i new letters in order to continue..' % count) text = ''.join(filter(lambda x: x in self.game.letters.letters, text.lower())) if len(text) == count and all(self.game.letters.available(c) for c in text): return text def gameOver(self): winner = sorted(self.game.players, reverse=True, key=attrgetter('score'))[0] self.dialog = QMessageBox(QMessageBox.Information, 'Game Over', ('<b>Game Over!</b><br><br>The player ' + '<b><font color=%s>%s</font></b> has won!') % (winner.color, winner.name), QMessageBox.Ok, self) self.dialog.show()
class SelectByColorDlg(QDialog): def __init__(self, color, pieceItems): super().__init__() self._color = color self.resize(800, 800) self.scene = QGraphicsScene() layout = QVBoxLayout(self) self.view = _MyView(self) layout.addWidget(self.view) self.view.setScene(self.scene) self._view_widget = QGLWidget() self.view.setViewport(self._view_widget) self.view.setMouseTracking(True) gry = sum(color) / 3.0 if (gry < 168): bg = [224,]*3 else: bg = [128,]*3 self.scene.setBackgroundBrush(QBrush(QColor(*bg))) self.setup_scene(self.scene, pieceItems) d = self.piece_diag self.view.scale(60./d, 60./d) self._hover_radius = 1.0 self.selected_item_ids = [] def setup_scene(self, scene, pieceItems): root = self._rootitem = _RootItem(self._color) scene.addItem(root) # order piece items by color distance of the most similar color pairs = [(self._distance(item), item) for item in pieceItems] pairs.sort(key = lambda pair: pair[0]) phi_increment = 0.61803398874 * 2 * pi phi = 0.0 gamma = 1.0 # scale distance relative to average piece size if pairs: rect = pairs[0][1].boundingRect() diag = (rect.width()**2 + rect.height()**2) ** 0.5 # take the median piece idx = len(pairs) // 2 meddist = pairs[idx][0] meddist = max(meddist, .1) scale = 6*diag/(meddist) ** gamma self.piece_diag = diag else: scale = 1.0 self.piece_diag = 1.0 self.dist_and_id = [] for distance, orig_item in pairs: item = orig_item.copy_to(root, rotate=False) rr = item.boundingRect() item.setTransformOriginPoint(rr.center()) item.setRotation(item.angle_deg) item.setPos( scale * distance**gamma * cos(phi)-rr.width()*0.5, scale * distance**gamma * sin(phi)-rr.height()*0.5 ) self.dist_and_id.append((scale*distance**gamma, item.id)) phi += phi_increment self.updateSceneRect() def set_hover_radius(self, r): self._hover_radius = r self.selected_item_ids = [pair[1] for pair in self.dist_and_id if pair[0] < r] self._rootitem.sel_size = r self._rootitem.update() def confirm_result(self): self.accept() def _distance(self, pieceItem): color = self._color def dst(c1, c2): c1 = rgb2Lab(c1) c2 = rgb2Lab(c2) return sum((c1i-c2i)**2 for c1i, c2i in zip(c1, c2)) ** 0.5 if not pieceItem.dominant_colors: return 255.0 return min(dst(color, piececolor) for piececolor in pieceItem.dominant_colors[:4]) def updateSceneRect(self): r = self.scene.itemsBoundingRect() w, h = r.width(), r.height() a = .05 r = r.adjusted(-w*a, -h*a, w*a, h*a) self.scene.setSceneRect(r)
class OWQualityControl(widget.OWWidget): name = "Quality Control" description = "Experiment quality control" icon = "../widgets/icons/QualityControl.svg" priority = 5000 inputs = [("Experiment Data", Orange.data.Table, "set_data")] outputs = [] DISTANCE_FUNCTIONS = [("Distance from Pearson correlation", dist_pcorr), ("Euclidean distance", dist_eucl), ("Distance from Spearman correlation", dist_spearman)] settingsHandler = SetContextHandler() split_by_labels = settings.ContextSetting({}) sort_by_labels = settings.ContextSetting({}) selected_distance_index = settings.Setting(0) def __init__(self, parent=None): super().__init__(parent) ## Attributes self.data = None self.distances = None self.groups = None self.unique_pos = None self.base_group_index = 0 ## GUI box = gui.widgetBox(self.controlArea, "Info") self.info_box = gui.widgetLabel(box, "\n") ## Separate By box box = gui.widgetBox(self.controlArea, "Separate By") self.split_by_model = itemmodels.PyListModel(parent=self) self.split_by_view = QListView() self.split_by_view.setSelectionMode(QListView.ExtendedSelection) self.split_by_view.setModel(self.split_by_model) box.layout().addWidget(self.split_by_view) self.split_by_view.selectionModel().selectionChanged.connect( self.on_split_key_changed) ## Sort By box box = gui.widgetBox(self.controlArea, "Sort By") self.sort_by_model = itemmodels.PyListModel(parent=self) self.sort_by_view = QListView() self.sort_by_view.setSelectionMode(QListView.ExtendedSelection) self.sort_by_view.setModel(self.sort_by_model) box.layout().addWidget(self.sort_by_view) self.sort_by_view.selectionModel().selectionChanged.connect( self.on_sort_key_changed) ## Distance box box = gui.widgetBox(self.controlArea, "Distance Measure") gui.comboBox(box, self, "selected_distance_index", items=[name for name, _ in self.DISTANCE_FUNCTIONS], callback=self.on_distance_measure_changed) self.scene = QGraphicsScene() self.scene_view = QGraphicsView(self.scene) self.scene_view.setRenderHints(QPainter.Antialiasing) self.scene_view.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.mainArea.layout().addWidget(self.scene_view) self.scene_view.installEventFilter(self) self._disable_updates = False self._cached_distances = {} self._base_index_hints = {} self.main_widget = None self.resize(800, 600) def clear(self): """Clear the widget state.""" self.data = None self.distances = None self.groups = None self.unique_pos = None with disable_updates(self): self.split_by_model[:] = [] self.sort_by_model[:] = [] self.main_widget = None self.scene.clear() self.info_box.setText("\n") self._cached_distances = {} def set_data(self, data=None): """Set input experiment data.""" self.closeContext() self.clear() self.error(0) self.warning(0) if data is not None: keys = self.get_suitable_keys(data) if not keys: self.error(0, "Data has no suitable feature labels.") data = None self.data = data if data is not None: self.on_new_data() def update_label_candidates(self): """Update the label candidates selection GUI (Group/Sort By views). """ keys = self.get_suitable_keys(self.data) with disable_updates(self): self.split_by_model[:] = keys self.sort_by_model[:] = keys def get_suitable_keys(self, data): """ Return suitable attr label keys from the data where the key has at least two unique values in the data. """ attrs = [attr.attributes.items() for attr in data.domain.attributes] attrs = reduce(operator.iadd, attrs, []) # in case someone put non string values in attributes dict attrs = [(str(key), str(value)) for key, value in attrs] attrs = set(attrs) values = defaultdict(set) for key, value in attrs: values[key].add(value) keys = [key for key in values if len(values[key]) > 1] return keys def selected_split_by_labels(self): """Return the current selected split labels. """ sel_m = self.split_by_view.selectionModel() indices = [r.row() for r in sel_m.selectedRows()] return [self.sort_by_model[i] for i in indices] def selected_sort_by_labels(self): """Return the current selected sort labels """ sel_m = self.sort_by_view.selectionModel() indices = [r.row() for r in sel_m.selectedRows()] return [self.sort_by_model[i] for i in indices] def selected_distance(self): """Return the selected distance function. """ return self.DISTANCE_FUNCTIONS[self.selected_distance_index][1] def selected_base_group_index(self): """Return the selected base group index """ return self.base_group_index def selected_base_indices(self, base_group_index=None): indices = [] for g, ind in self.groups: if base_group_index is None: label = group_label(self.selected_split_by_labels(), g) ind = [i for i in ind if i is not None] i = self._base_index_hints.get(label, ind[0] if ind else None) else: i = ind[base_group_index] indices.append(i) return indices def on_new_data(self): """We have new data and need to recompute all. """ self.closeContext() self.update_label_candidates() self.info_box.setText( "%s genes \n%s experiments" % (len(self.data), len(self.data.domain.attributes)) ) self.base_group_index = 0 keys = self.get_suitable_keys(self.data) self.openContext(keys) ## Restore saved context settings (split/sort selection) split_by_labels = self.split_by_labels sort_by_labels = self.sort_by_labels def select(model, selection_model, selected_items): """Select items in a Qt item model view """ all_items = list(model) try: indices = [all_items.index(item) for item in selected_items] except: indices = [] for ind in indices: selection_model.select(model.index(ind), QItemSelectionModel.Select) with disable_updates(self): select(self.split_by_view.model(), self.split_by_view.selectionModel(), split_by_labels) select(self.sort_by_view.model(), self.sort_by_view.selectionModel(), sort_by_labels) with widget_disable(self): self.split_and_update() def on_split_key_changed(self, *args): """Split key has changed """ with widget_disable(self): if not self._disable_updates: self.base_group_index = 0 self.split_by_labels = self.selected_split_by_labels() self.split_and_update() def on_sort_key_changed(self, *args): """Sort key has changed """ with widget_disable(self): if not self._disable_updates: self.base_group_index = 0 self.sort_by_labels = self.selected_sort_by_labels() self.split_and_update() def on_distance_measure_changed(self): """Distance measure has changed """ if self.data is not None: with widget_disable(self): self.update_distances() self.replot_experiments() def on_view_resize(self, size): """The view with the quality plot has changed """ if self.main_widget: current = self.main_widget.size() self.main_widget.resize(size.width() - 6, current.height()) self.scene.setSceneRect(self.scene.itemsBoundingRect()) def on_rug_item_clicked(self, item): """An ``item`` in the quality plot has been clicked. """ update = False sort_by_labels = self.selected_sort_by_labels() if sort_by_labels and item.in_group: ## The item is part of the group if item.group_index != self.base_group_index: self.base_group_index = item.group_index update = True else: if sort_by_labels: # If the user clicked on an background item it # invalidates the sorted labels selection with disable_updates(self): self.sort_by_view.selectionModel().clear() update = True index = item.index group = item.group label = group_label(self.selected_split_by_labels(), group) if self._base_index_hints.get(label, 0) != index: self._base_index_hints[label] = index update = True if update: with widget_disable(self): self.split_and_update() def eventFilter(self, obj, event): if obj is self.scene_view and event.type() == QEvent.Resize: self.on_view_resize(event.size()) return super().eventFilter(obj, event) def split_and_update(self): """ Split the data based on the selected sort/split labels and update the quality plot. """ split_labels = self.selected_split_by_labels() sort_labels = self.selected_sort_by_labels() self.warning(0) if not split_labels: self.warning(0, "No separate by label selected.") self.groups, self.unique_pos = \ exp.separate_by(self.data, split_labels, consider=sort_labels, add_empty=True) self.groups = sorted(self.groups.items(), key=lambda t: list(map(float_if_posible, t[0]))) self.unique_pos = sorted(self.unique_pos.items(), key=lambda t: list(map(float_if_posible, t[0]))) if self.groups: if sort_labels: group_base = self.selected_base_group_index() base_indices = self.selected_base_indices(group_base) else: base_indices = self.selected_base_indices() self.update_distances(base_indices) self.replot_experiments() def get_cached_distances(self, measure): if measure not in self._cached_distances: attrs = self.data.domain.attributes mat = numpy.zeros((len(attrs), len(attrs))) self._cached_distances[measure] = \ (mat, set(zip(range(len(attrs)), range(len(attrs))))) return self._cached_distances[measure] def get_cached_distance(self, measure, i, j): matrix, computed = self.get_cached_distances(measure) key = (i, j) if i < j else (j, i) if key in computed: return matrix[i, j] else: return None def get_distance(self, measure, i, j): d = self.get_cached_distance(measure, i, j) if d is None: vec_i = take_columns(self.data, [i]) vec_j = take_columns(self.data, [j]) d = measure(vec_i, vec_j) mat, computed = self.get_cached_distances(measure) mat[i, j] = d key = key = (i, j) if i < j else (j, i) computed.add(key) return d def store_distance(self, measure, i, j, dist): matrix, computed = self.get_cached_distances(measure) key = (i, j) if i < j else (j, i) matrix[j, i] = matrix[i, j] = dist computed.add(key) def update_distances(self, base_indices=()): """Recompute the experiment distances. """ distance = self.selected_distance() if base_indices == (): base_group_index = self.selected_base_group_index() base_indices = [ind[base_group_index] \ for _, ind in self.groups] assert(len(base_indices) == len(self.groups)) base_distances = [] attributes = self.data.domain.attributes pb = gui.ProgressBar(self, len(self.groups) * len(attributes)) for (group, indices), base_index in zip(self.groups, base_indices): # Base column of the group if base_index is not None: base_vec = take_columns(self.data, [base_index]) distances = [] # Compute the distances between base column # and all the rest data columns. for i in range(len(attributes)): if i == base_index: distances.append(0.0) elif self.get_cached_distance(distance, i, base_index) is not None: distances.append(self.get_cached_distance(distance, i, base_index)) else: vec_i = take_columns(self.data, [i]) dist = distance(base_vec, vec_i) self.store_distance(distance, i, base_index, dist) distances.append(dist) pb.advance() base_distances.append(distances) else: base_distances.append(None) pb.finish() self.distances = base_distances def replot_experiments(self): """Replot the whole quality plot. """ self.scene.clear() labels = [] max_dist = numpy.nanmax(list(filter(None, self.distances))) rug_widgets = [] group_pen = QPen(Qt.black) group_pen.setWidth(2) group_pen.setCapStyle(Qt.RoundCap) background_pen = QPen(QColor(0, 0, 250, 150)) background_pen.setWidth(1) background_pen.setCapStyle(Qt.RoundCap) main_widget = QGraphicsWidget() layout = QGraphicsGridLayout() attributes = self.data.domain.attributes if self.data is not None: for (group, indices), dist_vec in zip(self.groups, self.distances): indices_set = set(indices) rug_items = [] if dist_vec is not None: for i, attr in enumerate(attributes): # Is this a within group distance or background in_group = i in indices_set if in_group: rug_item = ClickableRugItem(dist_vec[i] / max_dist, 1.0, self.on_rug_item_clicked) rug_item.setPen(group_pen) tooltip = experiment_description(attr) rug_item.setToolTip(tooltip) rug_item.group_index = indices.index(i) rug_item.setZValue(rug_item.zValue() + 1) else: rug_item = ClickableRugItem(dist_vec[i] / max_dist, 0.85, self.on_rug_item_clicked) rug_item.setPen(background_pen) tooltip = experiment_description(attr) rug_item.setToolTip(tooltip) rug_item.group = group rug_item.index = i rug_item.in_group = in_group rug_items.append(rug_item) rug_widget = RugGraphicsWidget(parent=main_widget) rug_widget.set_rug(rug_items) rug_widgets.append(rug_widget) label = group_label(self.selected_split_by_labels(), group) label_item = QGraphicsSimpleTextItem(label, main_widget) label_item = GraphicsSimpleTextLayoutItem(label_item, parent=layout) label_item.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) labels.append(label_item) for i, (label, rug_w) in enumerate(zip(labels, rug_widgets)): layout.addItem(label, i, 0, Qt.AlignVCenter) layout.addItem(rug_w, i, 1) layout.setRowMaximumHeight(i, 30) main_widget.setLayout(layout) self.scene.addItem(main_widget) self.main_widget = main_widget self.rug_widgets = rug_widgets self.labels = labels self.on_view_resize(self.scene_view.size())
class Level(QFrame): def __init__(self, parent): QFrame.__init__(self,parent) self.filename = QString() self.copiedItem = QByteArray() self.pasteOffset = 5 self.prevPoint = QPoint() self.addOffset = 5 self.screenSize = (320, 240) self.bgColor = QColor(244,244,244) '''0.Portrait 1.Landscape''' self.orientation = 0 self.currentItem = None self.printer = QPrinter(QPrinter.HighResolution) self.printer.setPageSize(QPrinter.Letter) '''1.Header''' self.levelBar = LevelBar(self) '''3.Tiler''' self.tiler = TileMapGrid(self)#Tiler(self) self.tiler.setMinimumHeight(100) #self.tiler.currentChanged.connect(self.closeDesigner) #self.tiler.setTabsClosable(True) #self.tiler.setTabShape(0) #self.tiler.hide() #self.levelLayout.addWidget(self.levelBar) '''2.view''' viewLayoutWidget = QFrame() viewLayoutWidget.setFrameShape(QFrame.StyledPanel) viewLayout = QHBoxLayout(viewLayoutWidget) #viewLayout.setMargin(10) self.view = LevelView(viewLayoutWidget) '''scene''' self.scene = QGraphicsScene(self) #self.scene.selectionChanged.connect(self.setConnect) #self.view.setStyleSheet("border: 1px solid red;") self.setBackgroundColor(self.bgColor) self.setScreenSize(self.screenSize) self.view.setScene(self.scene) self.view.setAlignment(Qt.AlignCenter) self.scroll_off = 1 self.setScrollBar() viewLayout.setMargin(0) viewLayout.addWidget(self.view) self.wrapped = [] # Needed to keep wrappers alive layout = QVBoxLayout(self) layout.addWidget(self.levelBar) layout.addWidget(viewLayoutWidget) layout.addWidget(self.tiler) layout.setMargin(0) self.setLayout(layout) def setScrollBar(self): if(self.scroll_off): self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scroll_off = 0 else: self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.scroll_off = 1 def setBackgroundColor(self,color): self.bgColor = color self.scene.setBackgroundBrush(QBrush(color)) def setScreenSize(self,size): self.screenSize = size self.setOrientation(self.orientation) def setOrientation(self,idx): self.orientation = idx if(idx == 0): self.view.setMaximumSize(self.screenSize[1], self.screenSize[0]) self.scene.setSceneRect(0, 0, self.screenSize[1], self.screenSize[0]) else: self.view.setMaximumSize(self.screenSize[0], self.screenSize[1]) self.scene.setSceneRect(0, 0, self.screenSize[0], self.screenSize[1]) def offerSave(self): if (Dirty and QMessageBox.question(self, "Designer - Unsaved Changes", "Save unsaved changes?", QMessageBox.Yes|QMessageBox.No) == QMessageBox.Yes): self.save() def position(self): point = self.mapFromGlobal(QCursor.pos()) if not self.view.geometry().contains(point): coord = random.randint(36, 144) point = QPoint(coord, coord) else: if point == self.prevPoint: point += QPoint(self.addOffset, self.addOffset) self.addOffset += 5 else: self.addOffset = 5 self.prevPoint = point return self.view.mapToScene(point) def selectedItem(self): items = self.scene.selectedItems() if len(items) == 1: return items[0] return None def current(self,item): self.scene.clearSelection() sceneItems = self.scene.items() for items in sceneItems: if(items != item): item.setSelected(False) if(item.isConnected()): self.propertyBar.disconnectText(item) item.setConnected(False) self.currentItem = item self.currentItem.setConnected(True) self.currentItem.setSelected(True) self.propertyBar.connectText(self.currentItem) self.propertyBar.initText(self.currentItem) def addText(self): item = TextItem("SomeText", self.position()) self.connect(item, SIGNAL("current"),self.current) self.connect(item, SIGNAL("copy"),self.copy) self.connect(item, SIGNAL("cut"),self.cut) self.connect(item, SIGNAL("paste"),self.paste) self.connect(item, SIGNAL("delete"),self.delete) #self.current(item) self.scene.addItem(item) def copy(self): item = self.selectedItem() if item is None: return self.copiedItem.clear() self.pasteOffset = 5 stream = QDataStream(self.copiedItem, QIODevice.WriteOnly) self.writeItemToStream(stream, item) def cut(self): item = self.selectedItem() if item is None: return self.copy() self.scene.removeItem(item) del item def paste(self): if self.copiedItem.isEmpty(): return stream = QDataStream(self.copiedItem, QIODevice.ReadOnly) item = self.readItemFromStream(stream, self.pasteOffset) self.pasteOffset += 5 #self.scene.addItem(item) def delete(self): items = self.scene.selectedItems() if (len(items) and QMessageBox.question(self, "Designer - Delete", "Delete {0} item{1}?".format(len(items), "s" if len(items) != 1 else ""), QMessageBox.Yes|QMessageBox.No) == QMessageBox.Yes): while items: item = items.pop() self.scene.removeItem(item) del item def readItemFromStream(self, stream, offset=0): type = QString() position = QPointF() matrix = QMatrix() stream >> type >> position >> matrix if offset: position += QPointF(offset, offset) if type == "Text": text = QString() font = QFont() stream >> text >> font self.scene.addItem(TextItem(text, position, font, matrix)) elif type == "Box": rect = QRectF() stream >> rect style = Qt.PenStyle(stream.readInt16()) self.scene.addItem(BoxItem(position, style, matrix)) elif type == "Pixmap": pixmap = QPixmap() stream >> pixmap self.scene.addItem(self.createPixmapItem(pixmap, position, matrix)) def writeItemToStream(self, stream, item): if isinstance(item, QGraphicsTextItem): stream << QString("Text") << item.pos() \ << item.matrix() << item.toPlainText() << item.font() elif isinstance(item, QGraphicsPixmapItem): stream << QString("Pixmap") << item.pos() \ << item.matrix() << item.pixmap() elif isinstance(item, BoxItem): stream << QString("Box") << item.pos() \ << item.matrix() << item.rect stream.writeInt16(item.style) def rotate(self): for item in self.scene.selectedItems(): item.rotate(30) def print_(self): dialog = QPrintDialog(self.printer) if dialog.exec_(): painter = QPainter(self.printer) painter.setRenderHint(QPainter.Antialiasing) painter.setRenderHint(QPainter.TextAntialiasing) self.scene.clearSelection() #self.removeBorders() self.scene.render(painter) #self.addBorders() def open(self): self.offerSave() path = (QFileInfo(self.filename).path() if not self.filename.isEmpty() else ".") fname = QFileDialog.getOpenFileName(self, "Page Designer - Open", path, "Page Designer Files (*.pgd)") if fname.isEmpty(): return self.filename = fname fh = None try: fh = QFile(self.filename) if not fh.open(QIODevice.ReadOnly): raise IOError, unicode(fh.errorString()) items = self.scene.items() while items: item = items.pop() self.scene.removeItem(item) del item self.addBorders() stream = QDataStream(fh) stream.setVersion(QDataStream.Qt_4_2) magic = stream.readInt32() if magic != MagicNumber: raise IOError, "not a valid .pgd file" fileVersion = stream.readInt16() if fileVersion != FileVersion: raise IOError, "unrecognised .pgd file version" while not fh.atEnd(): self.readItemFromStream(stream) except IOError, e: QMessageBox.warning(self, "Page Designer -- Open Error", "Failed to open {0}: {1}".format(self.filename, e)) finally:
class GeorefDialog(QDialog, Ui_GeorefDialogBase): def __init__(self, types, parent=None): super(GeorefDialog, self).__init__(parent) self.setupUi(self) # Internal variables self._closeOnDone = False self._types = {} self._georeferencer = None self._types = types self._scene = QGraphicsScene(self) self._georeferencer = Georeferencer(self) self._georeferencer.status.connect(self._updateStatus) self._georeferencer.error.connect(self._updateError) # Init the gui for group in self._types: self.typeCombo.addItem(self._types[group]['name'], group) self.typeCombo.setCurrentIndex(0) for scale in Scale.Scale: self.scaleCombo.addItem(Scale.Label[scale], scale) self.scaleCombo.setCurrentIndex(Scale.OneToTwenty) self.processButton.clicked.connect(self._process) self.saveButton.clicked.connect(self._save) self.runButton.clicked.connect(self._run) self.closeButton.clicked.connect(self._close) self.siteEdit.textChanged.connect(self._updateGeoreference) self.typeCombo.currentIndexChanged.connect(self._updateGeoreference) self.scaleCombo.currentIndexChanged.connect(self._updateGeoreference) self.numberSpin.valueChanged.connect(self._updateGeoreference) self.suffixEdit.textChanged.connect(self._updateGeoreference) self.eastSpin.valueChanged.connect(self._updateGeoreference) self.northSpin.valueChanged.connect(self._updateGeoreference) def loadImage(self, inputFile): self._setStatusLabel('load', ProcessStatus.Running) if (not inputFile.exists()): self._showStatus('ERROR: Input file not found! File path was ' + inputFile.absoluteFilePath()) self._setStatusLabel('load', ProcessStatus.Failure) return False self._inputFile = inputFile pixmap = QPixmap(self._inputFile.absoluteFilePath()) if pixmap.isNull(): self._signalError('Loading of raw image failed.') return pixmap = QPixmap(self._inputFile.absoluteFilePath()) w = pixmap.width() h = pixmap.height() self._scene.addPixmap(pixmap) self._scene.setSceneRect(QRectF(0, 0, w, h)) self.planView.setSceneView(self._scene, QRectF(0, 0, w, h)) self.headerView.setSceneView(self._scene, QRectF(0, 0, w, 200)) self.footerView.setSceneView(self._scene, QRectF(100, h - 600, w - 200, 500)) self.gcpWidget1.setScene(self._scene, 250, 100, 2) self.gcpWidget2.setScene(self._scene, 250, 3050, 2) self.gcpWidget3.setScene(self._scene, 3200, 3050, 2) self.gcpWidget4.setScene(self._scene, 3200, 100, 2) self.inputFileNameLabel.setText(self._inputFile.baseName()) drawing = Drawing(self._inputFile) if drawing.isValid(): self.siteEdit.setText(drawing.item().siteCode()) self.typeCombo.setCurrentIndex(self.typeCombo.findData(drawing.item().classCode())) self.numberSpin.setValue(int(drawing.item().itemId()) or 0) self.eastSpin.setValue(drawing.easting() or 0) self.northSpin.setValue(drawing.northing() or 0) self.suffixEdit.setText(drawing.suffix()) self._updateFileNames(drawing) self._updateGeoPoints() pointFile = self.pointFileInfo() if pointFile.exists(): self._loadGcp(pointFile.absoluteFilePath()) self._setStatusLabel('load', ProcessStatus.Success) QCoreApplication.processEvents() return True return False def _loadGcp(self, path): gc = Georeferencer.loadGcpFile(path) gcTo = Transform() for index in gc.points(): gcp = gc.point(index) if gcp.map() == self.gcpWidget1.gcp().map(): gcTo.setPoint(1, gcp) elif gcp.map() == self.gcpWidget2.gcp().map(): gcTo.setPoint(2, gcp) elif gcp.map() == self.gcpWidget3.gcp().map(): gcTo.setPoint(3, gcp) elif gcp.map() == self.gcpWidget4.gcp().map(): gcTo.setPoint(4, gcp) if gcTo.isValid() and len(gcTo.points()) == 4: self.gcpWidget1.setRaw(gcTo.point(1).raw()) self.gcpWidget2.setRaw(gcTo.point(2).raw()) self.gcpWidget3.setRaw(gcTo.point(3).raw()) self.gcpWidget4.setRaw(gcTo.point(4).raw()) def _updateGeoPoints(self): mapUnits = Scale.Factor[self.drawingScale()] local1 = QPointF(self.eastSpin.value(), self.northSpin.value() + mapUnits) local2 = QPointF(self.eastSpin.value(), self.northSpin.value()) local3 = QPointF(self.eastSpin.value() + mapUnits, self.northSpin.value()) local4 = QPointF(self.eastSpin.value() + mapUnits, self.northSpin.value() + mapUnits) if self.drawingType() == 'sec': self.gcpWidget1.setGeo(local1, QgsPoint(local1)) self.gcpWidget2.setGeo(local2, QgsPoint(local2)) self.gcpWidget3.setGeo(local3, QgsPoint(local3)) self.gcpWidget4.setGeo(local4, QgsPoint(local4)) return typ = self._type() gridLayer = typ['grid'] features = gridLayer.getFeatures() localX = gridLayer.fieldNameIndex(typ['local_x']) localY = gridLayer.fieldNameIndex(typ['local_y']) for feature in features: local = QPoint(feature.attributes()[localX], feature.attributes()[localY]) map = geometry.toPoint(feature.geometry().geometry()) if local == local1: self.gcpWidget1.setGeo(local, map) elif local == local2: self.gcpWidget2.setGeo(local, map) elif local == local3: self.gcpWidget3.setGeo(local, map) elif local == local4: self.gcpWidget4.setGeo(local, map) def _updateGeoreference(self): self._updateFileNames(self.drawing()) self._updateGeoPoints() def _updateFileNames(self, drawing): self.rawFileNameLabel.setText(drawing.baseName()) self.geoFileNameLabel.setText(drawing.baseName() + self._type()['suffix']) def _toggleUi(self, status): self.processButton.setEnabled(status) self.saveButton.setEnabled(status) self.runButton.setEnabled(status) self.closeButton.setEnabled(status) self.siteEdit.setEnabled(status) self.typeCombo.setEnabled(status) self.numberSpin.setEnabled(status) self.suffixEdit.setEnabled(status) self.eastSpin.setEnabled(status) self.northSpin.setEnabled(status) self.cropCheck.setEnabled(status) self.addToMapCheck.setEnabled(status) self.gcpWidget1.setEnabled(status) self.gcpWidget2.setEnabled(status) self.gcpWidget3.setEnabled(status) self.gcpWidget4.setEnabled(status) self.planView.setEnabled(status) if (status): self.progressBar.setRange(0, 100) else: self.progressBar.setRange(0, 0) def drawing(self): return Drawing(self.item(), self.easting(), self.northing(), self.suffix(), self.rawFileName()) def item(self): return Item(self.siteCode(), self.classCode(), self.itemId()) def siteCode(self): return self.siteEdit.text().strip() def classCode(self): return self.drawingType() def itemId(self): return unicode(self.numberSpin.value()) def drawingType(self): return self.typeCombo.itemData(self.typeCombo.currentIndex()) def drawingScale(self): return self.scaleCombo.itemData(self.scaleCombo.currentIndex()) def easting(self): return self.eastSpin.value() def northing(self): return self.northSpin.value() def suffix(self): return self.suffixEdit.text().strip() def inputFileName(self): return self.inputFileNameLabel.text().strip() def rawFileName(self): return self.rawFileNameLabel.text().strip() def rawFileInfo(self): return QFileInfo(self._type()['raw'], self.rawFileName() + '.' + self._inputFile.suffix()) def pointFileInfo(self): return QFileInfo(self._type()['raw'], self.rawFileName() + '.' + self._inputFile.suffix() + '.points') def geoFileName(self): return self.geoFileNameLabel.text().strip() def geoFileInfo(self): return QFileInfo(self._type()['geo'], self.geoFileName() + '.tif') def _type(self): return self._types[self.drawingType()] def _updateStatus(self, step, status): self._setStatusLabel(step, status) self._showStatus(Georeferencer.Label[step] + ': ' + ProcessStatus.Label[status]) if step == Georeferencer.Stop and status == ProcessStatus.Success: if self._closeOnDone: self._close() else: self._toggleUi(True) def _updateError(self, step, msg): self._setStatusLabel(step, ProcessStatus.Failure) self._showStatus(msg) self._toggleUi(True) def _showStatus(self, text): self.statusBar.showMessage(text) def _save(self): self._copyInputFile() self._saveGcp() self._close() def _copyInputFile(self): if self.inputFileName() != self.rawFileName() or self._inputFile.dir() != self._type()['raw']: QFile.copy(self._inputFile.absoluteFilePath(), self.rawFileInfo().absoluteFilePath()) def _saveGcp(self): gc = self._gc() if (gc.isValid()): Georeferencer.writeGcpFile(gc, self.pointFileInfo().absoluteFilePath()) def _run(self): self._runGeoreference(False) def _process(self): self._runGeoreference(True) def _close(self): if (self._georeferencer.step() == Georeferencer.Stop): self.accept() else: self.reject() def _gc(self): gc = Transform() gc.crs = self._type()['crs'] gc.setPoint(1, self.gcpWidget1.gcp()) gc.setPoint(2, self.gcpWidget2.gcp()) gc.setPoint(3, self.gcpWidget3.gcp()) gc.setPoint(4, self.gcpWidget4.gcp()) return gc def _runGeoreference(self, closeOnDone): self._closeOnDone = closeOnDone gc = self._gc() if (not gc.isValid()): self._showStatus('ERROR: Please set all 4 Ground Control Points!') return self._toggleUi(False) self._copyInputFile() QCoreApplication.processEvents() self._georeferencer.run(gc, self.rawFileInfo(), self.pointFileInfo(), self.geoFileInfo()) def _finished(self, step, status): if step == Georeferencer.Stop and status == ProcessStatus.Success and self._closeOnDone: self._close() else: self._toggleUi(True) def _setStatusLabel(self, step, status): if step == 'load': label = self.loadStatusLabel elif step == Georeferencer.Crop: label = self.cropStatusLabel elif step == Georeferencer.Translate: label = self.translateStatusLabel elif step == Georeferencer.Warp: label = self.warpStatusLabel elif step == Georeferencer.Overview: label = self.overviewStatusLabel else: return if status == ProcessStatus.Success: label.setPixmap(QPixmap(':/plugins/ark/georef/success.png')) elif status == ProcessStatus.Failure: label.setPixmap(QPixmap(':/plugins/ark/georef/failure.png')) elif status == ProcessStatus.Running: label.setPixmap(QPixmap(':/plugins/ark/georef/running.png')) else: label.setPixmap(QPixmap(':/plugins/ark/georef/unknown.png'))
class MainForm(QDialog): def __init__(self, parent=None): super(MainForm, self).__init__(parent) self.Running = False self.scene = QGraphicsScene(self) self.scene.setSceneRect(0, 0, SCENESIZEX, SCENESIZEY) self.view = QGraphicsView() self.view.setRenderHint(QPainter.Antialiasing) self.view.setScene(self.scene) self.view.setFocusPolicy(Qt.NoFocus) #self.zoomSlider = QSlider(Qt.Horizontal) #self.zoomSlider.setRange(5, 200) #self.zoomSlider.setValue(100) self.pauseButton = QPushButton("Pa&use") self.quitButton = QPushButton("&Quit") layout = QVBoxLayout() layout.addWidget(self.view) #layout.addWidget(self.zoomSlider) layout.addWidget(self.pauseButton) layout.addWidget(self.quitButton) self.setLayout(layout) #self.connect(self.zoomSlider, SIGNAL("valueChanged(int))"), # self.zoom) self.connect(self.pauseButton, SIGNAL("clicked()"), self.pauseOrResume) self.connect(self.quitButton, SIGNAL("clicked()"), self.accept) self.readNodes() self.zoom(1.0) self.populate() #self.startTimer(INTERVAL) self.setWindowTitle("TdPaleo") def pauseOrResume(self): self.Running = not self.Running self.pauseButton.setText("Pa&use" if self.Running else "Res&ume") items = self.scene.items() for item in items: item.setRunning() def zoom(self, value): factor =1/ 1.5 matrix = self.view.matrix() matrix.reset() matrix.scale(factor, factor) self.view.setMatrix(matrix) def readNodes(self): file = open("tdp_geometry.dat") file.readline() while True: line = file.readline() if not line: break param = line.split(" ") if (line != "\n"): n = node() n.x = float(param[0]) n.y = 956 - float(param[1]) n.angle = float(param[2]) n.d = int(param[3]) n.type = int(param[4]) nodes.append(n) def populate(self): color = QColor(0, 150, 0) head = TdPCavallo(color, nodes[0].angle, QPointF(nodes[0].x, nodes[0].y)) #FIXME AGGIUNGERE POI IL FANTINO AL CAVALLO #segment = Segment(color, offset, head) self.scene.addItem(head) #Running = False def timerEvent(self, event): if not self.Running: return
class ConductorGraph(Plugin): _deferred_fit_in_view=Signal() _client_list_update_signal=Signal() def __init__(self, context): self._context=context super(ConductorGraph, self).__init__(context) self.initialised=False self.setObjectName('Conductor Graph') self._current_dotcode=None self._node_items=None self._edge_items=None self._node_item_events={} self._edge_item_events={} self._client_info_list={} self._widget=QWidget() self.cur_selected_client_name = "" self.pre_selected_client_name = "" # factory builds generic dotcode items self.dotcode_factory=PydotFactory() # self.dotcode_factory=PygraphvizFactory() self.dotcode_generator=RosGraphDotcodeGenerator() self.dot_to_qt=DotToQtGenerator() self._graph=ConductorGraphInfo() self._graph._reg_event_callback(self._update_client_list) self._graph._reg_period_callback(self._set_network_statisics) rospack=rospkg.RosPack() ui_file=os.path.join(rospack.get_path('concert_conductor_graph'), 'ui', 'conductor_graph.ui') loadUi(ui_file, self._widget, {'InteractiveGraphicsView': InteractiveGraphicsView}) self._widget.setObjectName('ConductorGraphUi') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) self._scene=QGraphicsScene() self._scene.setBackgroundBrush(Qt.white) self._widget.graphics_view.setScene(self._scene) #self._widget.refresh_graph_push_button.setIcon(QIcon.fromTheme('view-refresh')) self._widget.refresh_graph_push_button.setIcon(QIcon.fromTheme('window-new')) self._widget.refresh_graph_push_button.pressed.connect(self._update_conductor_graph) self._widget.highlight_connections_check_box.toggled.connect(self._redraw_graph_view) self._widget.auto_fit_graph_check_box.toggled.connect(self._redraw_graph_view) self._widget.fit_in_view_push_button.setIcon(QIcon.fromTheme('zoom-original')) self._widget.fit_in_view_push_button.pressed.connect(self._fit_in_view) self._deferred_fit_in_view.connect(self._fit_in_view, Qt.QueuedConnection) self._deferred_fit_in_view.emit() self._widget.tabWidget.currentChanged.connect(self._change_client_tab) self._client_list_update_signal.connect(self._update_conductor_graph) #rospy.Subscriber(concert_msgs.Strings.CONCERT_CLIENT_CHANGES, ConcertClients, self._update_client_list) context.add_widget(self._widget) def restore_settings(self, plugin_settings, instance_settings): self.initialised=True self._refresh_rosgraph() def shutdown_plugin(self): pass def _update_conductor_graph(self): # re-enable controls customizing fetched ROS graph self._refresh_rosgraph() self._update_client_tab() def _refresh_rosgraph(self): if not self.initialised: return self._update_graph_view(self._generate_dotcode()) def _generate_dotcode(self): return self.dotcode_generator.generate_dotcode(rosgraphinst=self._graph, dotcode_factory=self.dotcode_factory, orientation='LR' ) def _update_graph_view(self, dotcode): #if dotcode==self._current_dotcode: # return self._current_dotcode=dotcode self._redraw_graph_view() def _update_client_list(self): print "[conductor graph]: _update_client_list" self._client_list_update_signal.emit() pass def _start_service(self,node_name,service_name): service=self._graph._client_info_list[node_name]['gateway_name']+"/"+service_name info_text='' if service_name=='status': service_handle=rospy.ServiceProxy(service, Status) call_result=service_handle() info_text="<html>" info_text +="<p>-------------------------------------------</p>" info_text +="<p><b>application_namespace: </b>" +call_result.application_namespace+"</p>" info_text +="<p><b>remote_controller: </b>" +call_result.remote_controller+"</p>" info_text +="<p><b>application_status: </b>" +call_result.application_status+"</p>" info_text +="</html>" self._client_list_update_signal.emit() elif service_name=='platform_info': service_handle=rospy.ServiceProxy(service, GetPlatformInfo) call_result=service_handle() info_text = "<html>" info_text += "<p>-------------------------------------------</p>" info_text += "<p><b>rocon_uri: </b>" + call_result.platform_info.uri + "</p>" info_text += "<p><b>concert_version: </b>" + call_result.platform_info.version + "</p>" info_text += "</html>" self._client_list_update_signal.emit() elif service_name=='invite': #sesrvice service_handle=rospy.ServiceProxy(service, Invite) #dialog dlg=QDialog(self._widget) dlg.setMinimumSize(400,0) dlg.setMaximumSize(400,0) dlg.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Expanding) #dialog layout ver_layout=QVBoxLayout(dlg) ver_layout.setContentsMargins (0,0,0,0) dynamic_arg=[] dynamic_arg.append(DynamicArgumentLayer(ver_layout,'Remote Target Name',False,[('remote_target_name','string')])) dynamic_arg.append(DynamicArgumentLayer(ver_layout,'Application Namespace',False,[('application_namespace','string')])) dynamic_arg.append(DynamicArgumentLayer(ver_layout,'Cancel',False,[('cancel','bool')])) #button button_hor_sub_widget=QWidget() button_hor_layout=QHBoxLayout(button_hor_sub_widget) btn_call=QPushButton("Call") btn_cancel=QPushButton("cancel") btn_call.clicked.connect(lambda: dlg.done(0)) btn_call.clicked.connect(lambda : self._call_invite_service(service,service_handle,dynamic_arg)) btn_cancel.clicked.connect(lambda: dlg.done(0)) #add button button_hor_layout.addWidget(btn_call) button_hor_layout.addWidget(btn_cancel) #add button layout ver_layout.addWidget(button_hor_sub_widget) dlg.setVisible(True) elif service_name=='start_app': #sesrvice service_handle=rospy.ServiceProxy(service, StartApp) #dialog dlg=QDialog(self._widget) dlg.setMinimumSize(400,0) dlg.setMaximumSize(400,0) dlg.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Expanding) #dialog layout ver_layout=QVBoxLayout(dlg) ver_layout.setContentsMargins (0,0,0,0) dynamic_arg=[] dynamic_arg.append(DynamicArgumentLayer(ver_layout,'Name',False,[('name','string')])) dynamic_arg.append(DynamicArgumentLayer(ver_layout,'Remappings',True,[('remap to','string'),('remap from','string')])) #button button_hor_sub_widget=QWidget() button_hor_layout=QHBoxLayout(button_hor_sub_widget) btn_call=QPushButton("Call") btn_cancel=QPushButton("cancel") btn_call.clicked.connect(lambda: dlg.done(0)) btn_call.clicked.connect(lambda : self._call_start_app_service(service,service_handle,dynamic_arg)) btn_cancel.clicked.connect(lambda: dlg.done(0)) #add button button_hor_layout.addWidget(btn_call) button_hor_layout.addWidget(btn_cancel) #add button layout ver_layout.addWidget(button_hor_sub_widget) dlg.setVisible(True) elif service_name=='stop_app': service_handle=rospy.ServiceProxy(service, StopApp) call_result=service_handle() info_text="<html>" info_text +="<p>-------------------------------------------</p>" info_text +="<p><b>stopped: </b>" +str(call_result.stopped)+"</p>" info_text +="<p><b>error_code: </b>" +str(call_result.error_code)+"</p>" info_text +="<p><b>message: </b>" +call_result.message+"</p>" info_text +="</html>" self._update_client_tab() else: print 'has no service' return # display the result of calling service # get tab widget handle service_text_widget=None cur_tab_widget=self._widget.tabWidget.currentWidget() if cur_tab_widget==None: return object_name='services_text_widget' for k in cur_tab_widget.children(): if k.objectName().count(object_name) >=1 : service_text_widget=k break if service_text_widget==None: return service_text_widget.clear() service_text_widget.appendHtml(info_text) def _call_invite_service(self,service,service_handle,dynamic_arg): remote_target_name="" application_namespace="" cancel=False for k in dynamic_arg: if k.name=='Remote Target Name': item_widget=k._get_param_list()[0][0][1] remote_target_name=item_widget.toPlainText() elif k.name=='Application Namespace': item_widgetwidget=k._get_param_list()[0][0][1] application_namespace=item_widget.toPlainText() elif k.name=='Cancel': item_widget=k._get_param_list()[0][0][1] cancel=item_widget.itemData(item_widget.currentIndex()) #calling service call_result=service_handle(remote_target_name,application_namespace,cancel) #status update self._client_list_update_signal.emit() # display the result of calling service info_text="<html>" info_text +="<p>-------------------------------------------</p>" info_text +="<p><b>result: </b>" +str(call_result.result)+"</p>" info_text +="<p><b>error_code: </b>" +str(call_result.error_code)+"</p>" info_text +="<p><b>message: </b>" +call_result.message+"</p>" info_text +="</html>" # get tab widget handle service_text_widget=None cur_tab_widget=self._widget.tabWidget.currentWidget() if cur_tab_widget==None: return object_name='services_text_widget' for k in cur_tab_widget.children(): if k.objectName().count(object_name) >=1 : service_text_widget=k break if service_text_widget==None: return service_text_widget.clear() service_text_widget.appendHtml(info_text) pass def _call_start_app_service(self,service,service_handle,dynamic_arg): name="" remappings=[] for k in dynamic_arg: if k.name=='Name': name=k._get_param_list()[0][0][1].toPlainText() elif k.name=='Remappings': for l in k._get_param_list(): remap_to=l[0][1].toPlainText() remap_from=l[1][1].toPlainText() remappings.append(Remapping(remap_to,remap_from)) #calling service call_result=service_handle(name,remappings) #status update self._client_list_update_signal.emit() # display the result of calling service info_text = '' info_text="<html>" info_text +="<p>-------------------------------------------</p>" info_text +="<p><b>started: </b>" +str(call_result.started)+"</p>" info_text +="<p><b>error_code: </b>" +str(call_result.error_code)+"</p>" info_text +="<p><b>message: </b>" +call_result.message+"</p>" info_text +="<p><b>app_namespace: </b>" +call_result.app_namespace+"</p>" info_text +="</html>" # get tab widget handle service_text_widget=None cur_tab_widget=self._widget.tabWidget.currentWidget() if cur_tab_widget==None: return object_name='services_text_widget' for k in cur_tab_widget.children(): if k.objectName().count(object_name) >=1 : service_text_widget=k break if service_text_widget==None: return service_text_widget.clear() service_text_widget.appendHtml(info_text) pass def _update_client_tab(self): print '[_update_client_tab]' self.pre_selected_client_name = self.cur_selected_client_name self._widget.tabWidget.clear() for k in self._graph._client_info_list.values(): main_widget=QWidget() ver_layout=QVBoxLayout(main_widget) ver_layout.setContentsMargins (9,9,9,9) ver_layout.setSizeConstraint (ver_layout.SetDefaultConstraint) #button layout sub_widget=QWidget() sub_widget.setAccessibleName('sub_widget') btn_grid_layout=QGridLayout(sub_widget) btn_grid_layout.setContentsMargins (9,9,9,9) btn_grid_layout.setColumnStretch (1, 0) btn_grid_layout.setRowStretch (2, 0) invite_btn=QPushButton("Invite") platform_info_btn=QPushButton("Get Platform Info") status_btn=QPushButton("Get Status") start_app_btn=QPushButton("Start App") stop_app_btn=QPushButton("Stop App") invite_btn.clicked.connect(lambda: self._start_service(self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex()),"invite")) platform_info_btn.clicked.connect(lambda: self._start_service(self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex()),"platform_info")) status_btn.clicked.connect(lambda: self._start_service(self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex()),"status")) start_app_btn.clicked.connect(lambda: self._start_service(self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex()),"start_app")) stop_app_btn.clicked.connect(lambda: self._start_service(self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex()),"stop_app")) btn_grid_layout.addWidget(invite_btn) btn_grid_layout.addWidget(platform_info_btn) btn_grid_layout.addWidget(status_btn) btn_grid_layout.addWidget(start_app_btn) btn_grid_layout.addWidget(stop_app_btn) ver_layout.addWidget(sub_widget) #client information layout context_label = QLabel() context_label.setText("Client information") ver_layout.addWidget(context_label) app_context_widget=QPlainTextEdit() app_context_widget.setObjectName(k["name"]+'_'+'app_context_widget') app_context_widget.setAccessibleName('app_context_widget') app_context_widget.appendHtml(k["app_context"]) app_context_widget.setReadOnly(True) cursor = app_context_widget.textCursor() cursor.movePosition(QTextCursor.Start,QTextCursor.MoveAnchor,0) app_context_widget.setTextCursor(cursor) ver_layout.addWidget(app_context_widget) #service layout context_label = QLabel() context_label.setText("Service result") ver_layout.addWidget(context_label) services_text_widget=QPlainTextEdit() services_text_widget.setObjectName(k["name"]+'_'+'services_text_widget') services_text_widget.setReadOnly(True) cursor = services_text_widget.textCursor() cursor.movePosition(QTextCursor.Start,QTextCursor.MoveAnchor,0) services_text_widget.setTextCursor(cursor) ver_layout.addWidget(services_text_widget) # new icon path="" if k["is_new"]==True: path=os.path.join(os.path.dirname(os.path.abspath(__file__)),"../../resources/images/new.gif") #add tab self._widget.tabWidget.addTab(main_widget,QIcon(path), k["name"]); #set previous selected tab for k in range(self._widget.tabWidget.count()): tab_text=self._widget.tabWidget.tabText(k) if tab_text == self.pre_selected_client_name: self._widget.tabWidget.setCurrentIndex(k) def _change_client_tab(self,index): self.cur_selected_client_name = self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex()) if self._widget.tabWidget.widget(index) !=None: for k in self._widget.tabWidget.widget(index).children(): if k.objectName().count("services_text_widget"): k.clear() pass def _set_network_statisics(self): if self._edge_items == None: return else: for edge_items in self._edge_items.itervalues(): for edge_item in edge_items: edge_dst_name=edge_item.to_node._label.text() edge_item.setToolTip(str(self._graph._client_info_list[edge_dst_name]['conn_stats'])) def _redraw_graph_view(self): self._scene.clear() self._node_item_events={} self._edge_item_events={} self._node_items=None self._edge_items=None if self._widget.highlight_connections_check_box.isChecked(): highlight_level=3 else: highlight_level=1 highlight_level=3 if self._widget.highlight_connections_check_box.isChecked() else 1 # layout graph and create qt items (nodes, edges)=self.dot_to_qt.dotcode_to_qt_items(self._current_dotcode, highlight_level=highlight_level, same_label_siblings=True) self._node_items=nodes self._edge_items=edges # if we wish to make special nodes, do that here (maybe subclass GraphItem, just like NodeItem does) #node for node_item in nodes.itervalues(): # set the color of conductor to orange if node_item._label.text()==self._graph._concert_conductor_name: royal_blue=QColor(65, 105, 255) node_item._default_color=royal_blue node_item.set_color(royal_blue) # redefine mouse event self._node_item_events[node_item._label.text()]=GraphEventHandler(self._widget.tabWidget,node_item,node_item.mouseDoubleClickEvent); node_item.mouseDoubleClickEvent=self._node_item_events[node_item._label.text()].NodeEvent; self._scene.addItem(node_item) #edge for edge_items in edges.itervalues(): for edge_item in edge_items: #redefine the edge hover event self._edge_item_events[edge_item._label.text()]=GraphEventHandler(self._widget.tabWidget,edge_item,edge_item._label.hoverEnterEvent); edge_item._label.hoverEnterEvent =self._edge_item_events[edge_item._label.text()].EdgeEvent; #self._edge_item_events[edge_item._label.text()]=GraphEventHandler(self._widget.tabWidget,edge_item,edge_item.mouseDoubleClickEvent); #edge_item.mouseDoubleClickEvent=self._edge_item_events[edge_item._label.text()].EdgeEvent; edge_item.add_to_scene(self._scene) #set the color of node as connection strength one of red, yellow, green edge_dst_name=edge_item.to_node._label.text() if edge_dst_name in self._graph._client_info_list.keys(): connection_strength=self._graph._client_info_list[edge_dst_name]['connection_strength'] if connection_strength=='very_strong': green=QColor(0, 255, 0) edge_item._default_color=green edge_item.set_color(green) elif connection_strength=='strong': green_yellow=QColor(125, 255,0) edge_item._default_color=green_yellow edge_item.set_color(green_yellow) elif connection_strength=='normal': yellow=QColor(238, 238,0) edge_item._default_color=yellow edge_item.set_color(yellow) elif connection_strength=='weak': yellow_red=QColor(255, 125,0) edge_item._default_color=yellow_red edge_item.set_color(yellow_red) elif connection_strength=='very_weak': red=QColor(255, 0,0) edge_item._default_color=red edge_item.set_color(red) #set the tooltip about network information edge_item.setToolTip(str(self._graph._client_info_list[edge_dst_name]['conn_stats'])) self._scene.setSceneRect(self._scene.itemsBoundingRect()) if self._widget.auto_fit_graph_check_box.isChecked(): self._fit_in_view() def _fit_in_view(self): self._widget.graphics_view.fitInView(self._scene.itemsBoundingRect(), Qt.KeepAspectRatio)
class MainWindow(QMainWindow, Ui_MainWindow): """ Class documentation goes here. """ def __init__(self, parent=None): """ Constructor """ QMainWindow.__init__(self, parent) self.setupUi(self) self.countBattle = 0 self.timer = QTimer() self.tableWidget.horizontalHeader().setResizeMode( QtGui.QHeaderView.Stretch) self.tableWidget.hide() @pyqtSignature("") def on_pushButton_clicked(self): """ Start the last battle """ with open(os.getcwd() + "/.datas/lastArena", 'rb') as file: unpickler = pickle.Unpickler(file) dico = unpickler.load() file.close() self.setUpBattle(dico["width"], dico["height"], dico["botList"]) def setUpBattle(self, width, height, botList): self.tableWidget.clearContents() self.tableWidget.hide() self.graphicsView.show() self.width = width self.height = height self.botList = botList self.statisticDico = {} for bot in botList: self.statisticDico[self.repres(bot)] = statistic() self.startBattle() def startBattle(self): try: self.disconnect(self.timer, SIGNAL("timeout()"), self.scene.advance) del self.timer del self.scene del self.sceneMenu except: pass self.timer = QTimer() self.countBattle += 1 self.sceneMenu = QGraphicsScene() self.graphicsView_2.setScene(self.sceneMenu) self.scene = Graph(self, self.width, self.height) self.graphicsView.setScene(self.scene) self.scene.AddRobots(self.botList) self.connect(self.timer, SIGNAL("timeout()"), self.scene.advance) self.timer.start((self.horizontalSlider.value()**2) / 100.0) self.resizeEvent() @pyqtSignature("int") def on_horizontalSlider_valueChanged(self, value): """ Slot documentation goes here. """ self.timer.setInterval((value**2) / 100.0) @pyqtSignature("") def on_actionNew_activated(self): """ Battle Menu """ self.battleMenu = Battle(self) self.battleMenu.show() @pyqtSignature("") def on_actionNew_2_activated(self): """ Slot documentation goes here. """ # TODO: not implemented yet print("Not Implemented Yet") @pyqtSignature("") def on_actionOpen_activated(self): """ Slot documentation goes here. """ # TODO: not implemented yet print("Not Implemented Yet") def resizeEvent(self, evt=None): try: self.graphicsView.fitInView(self.scene.sceneRect(), 4) except: pass def addRobotInfo(self, robot): self.sceneMenu.setSceneRect(0, 0, 170, 800) rb = RobotInfo() rb.pushButton.setText(str(robot)) rb.progressBar.setValue(100) rb.robot = robot robot.info = rb robot.progressBar = rb.progressBar robot.icon = rb.toolButton robot.icon2 = rb.toolButton_2 p = self.sceneMenu.addWidget(rb) l = (len(self.scene.aliveBots)) self.sceneMenu.setSceneRect(0, 0, 170, l * 80) p.setPos(0, (l - 1) * 80) def chooseAction(self): if self.countBattle >= self.spinBox.value(): "Menu Statistic" self.graphicsView.hide() self.tableWidget.show() self.tableWidget.setRowCount(len(self.statisticDico)) i = 0 for key, value in self.statisticDico.items(): self.tableWidget.setItem(i, 0, QtGui.QTableWidgetItem(key)) self.tableWidget.setItem( i, 1, QtGui.QTableWidgetItem(str(value.first))) self.tableWidget.setItem( i, 2, QtGui.QTableWidgetItem(str(value.second))) self.tableWidget.setItem( i, 3, QtGui.QTableWidgetItem(str(value.third))) self.tableWidget.setItem( i, 4, QtGui.QTableWidgetItem(str(value.points))) i += 1 self.countBattle = 0 self.timer.stop() else: self.startBattle() def repres(self, bot): repres = repr(bot).split(".") return repres[1].replace("'>", "")
class ImagesPreviewer(foundations.ui.common.QWidgetFactory(uiFile=UI_FILE)): """ | This class provides the Application images previewer. | It defines methods to navigate through the list of given images ( List of images paths ), zoom in / out and fit the displayed image, etc... """ def __init__(self, parent, paths=None, *args, **kwargs): """ This method initializes the class. :param parent: Object parent. ( QObject ) :param paths: Images paths. ( Tuple / List ) :param \*args: Arguments. ( \* ) :param \*\*kwargs: Keywords arguments. ( \*\* ) """ LOGGER.debug("> Initializing '{0}()' class.".format(self.__class__.__name__)) super(ImagesPreviewer, self).__init__(parent, *args, **kwargs) # --- Setting class attributes. --- self.__container = parent self.__paths = None self.paths = paths self.__uiResourcesDirectory = "resources" self.__uiResourcesDirectory = os.path.join(os.path.dirname(__file__), self.__uiResourcesDirectory) self.__uiPreviousImage = "Previous.png" self.__uiNextImage = "Next.png" self.__uiZoomOutImage = "Zoom_Out.png" self.__uiZoomInImage = "Zoom_In.png" # Ensure the ui object is destroyed on close to avoid memory leaks. self.setAttribute(Qt.WA_DeleteOnClose) self.__graphicsSceneBackgroundColor = QColor(32, 32, 32) self.__minimumZoomFactor = 0.05 self.__maximumZoomFactor = 25 self.__displayGraphicsItemMargin = 32 self.__graphicsSceneWidth = QApplication.desktop().screenGeometry( QApplication.desktop().primaryScreen()).width() * (1 / self.__minimumZoomFactor * 1.75) self.__graphicsSceneHeight = QApplication.desktop().screenGeometry( QApplication.desktop().primaryScreen()).height() * (1 / self.__minimumZoomFactor * 1.75) self.__wheelZoomFactor = 350.0 self.__keyZoomFactor = 1.20 self.__graphicsView = None self.__graphicsScene = None self.__displayGraphicsItem = None ImagesPreviewer.__initializeUi(self) self.loadImage() #****************************************************************************************************************** #*** Attributes properties. #****************************************************************************************************************** @property def container(self): """ This method is the property for **self.__container** attribute. :return: self.__container. ( QObject ) """ return self.__container @container.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def container(self, value): """ This method is the setter method for **self.__container** attribute. :param value: Attribute value. ( QObject ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "container")) @container.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def container(self): """ This method is the deleter method for **self.__container** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "container")) @property def paths(self): """ This method is the property for **self.__paths** attribute. :return: self.__paths. ( Tuple / List ) """ return self.__paths @paths.setter @foundations.exceptions.handleExceptions(AssertionError) def paths(self, value): """ This method is the setter method for **self.__paths** attribute. :param value: Attribute value. ( Tuple / List ) """ if value is not None: assert type(value) in (tuple, list), "'{0}' attribute: '{1}' type is not 'tuple' or 'list'!".format("paths", value) for element in value: assert type(element) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format( "paths", element) self.__paths = value @paths.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def paths(self): """ This method is the deleter method for **self.__paths** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "paths")) @property def uiResourcesDirectory(self): """ This method is the property for **self.__uiResourcesDirectory** attribute. :return: self.__uiResourcesDirectory. ( String ) """ return self.__uiResourcesDirectory @uiResourcesDirectory.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def uiResourcesDirectory(self, value): """ This method is the setter method for **self.__uiResourcesDirectory** attribute. :param value: Attribute value. ( String ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "uiResourcesDirectory")) @uiResourcesDirectory.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def uiResourcesDirectory(self): """ This method is the deleter method for **self.__uiResourcesDirectory** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "uiResourcesDirectory")) @property def uiPreviousImage(self): """ This method is the property for **self.__uiPreviousImage** attribute. :return: self.__uiPreviousImage. ( String ) """ return self.__uiPreviousImage @uiPreviousImage.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def uiPreviousImage(self, value): """ This method is the setter method for **self.__uiPreviousImage** attribute. :param value: Attribute value. ( String ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "uiPreviousImage")) @uiPreviousImage.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def uiPreviousImage(self): """ This method is the deleter method for **self.__uiPreviousImage** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "uiPreviousImage")) @property def uiNextImage(self): """ This method is the property for **self.__uiNextImage** attribute. :return: self.__uiNextImage. ( String ) """ return self.__uiNextImage @uiNextImage.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def uiNextImage(self, value): """ This method is the setter method for **self.__uiNextImage** attribute. :param value: Attribute value. ( String ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "uiNextImage")) @uiNextImage.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def uiNextImage(self): """ This method is the deleter method for **self.__uiNextImage** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "uiNextImage")) @property def uiZoomOutImage(self): """ This method is the property for **self.__uiZoomOutImage** attribute. :return: self.__uiZoomOutImage. ( String ) """ return self.__uiZoomOutImage @uiZoomOutImage.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def uiZoomOutImage(self, value): """ This method is the setter method for **self.__uiZoomOutImage** attribute. :param value: Attribute value. ( String ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "uiZoomOutImage")) @uiZoomOutImage.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def uiZoomOutImage(self): """ This method is the deleter method for **self.__uiZoomOutImage** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "uiZoomOutImage")) @property def uiZoomInImage(self): """ This method is the property for **self.__uiZoomInImage** attribute. :return: self.__uiZoomInImage. ( String ) """ return self.__uiZoomInImage @uiZoomInImage.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def uiZoomInImage(self, value): """ This method is the setter method for **self.__uiZoomInImage** attribute. :param value: Attribute value. ( String ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "uiZoomInImage")) @uiZoomInImage.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def uiZoomInImage(self): """ This method is the deleter method for **self.__uiZoomInImage** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "uiZoomInImage")) @property def graphicsSceneBackgroundColor(self): """ This method is the property for **self.__graphicsSceneBackgroundColor** attribute. :return: self.__graphicsSceneBackgroundColor. ( QColors ) """ return self.__graphicsSceneBackgroundColor @graphicsSceneBackgroundColor.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def graphicsSceneBackgroundColor(self, value): """ This method is the setter method for **self.__graphicsSceneBackgroundColor** attribute. :param value: Attribute value. ( QColors ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "graphicsSceneBackgroundColor")) @graphicsSceneBackgroundColor.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def graphicsSceneBackgroundColor(self): """ This method is the deleter method for **self.__graphicsSceneBackgroundColor** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "graphicsSceneBackgroundColor")) @property def graphicsSceneWidth(self): """ This method is the property for **self.__graphicsSceneWidth** attribute. :return: self.__graphicsSceneWidth. ( Integer ) """ return self.__graphicsSceneWidth @graphicsSceneWidth.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def graphicsSceneWidth(self, value): """ This method is the setter method for **self.__graphicsSceneWidth** attribute. :param value: Attribute value. ( Integer ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "graphicsSceneWidth")) @graphicsSceneWidth.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def graphicsSceneWidth(self): """ This method is the deleter method for **self.__graphicsSceneWidth** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "graphicsSceneWidth")) @property def graphicsSceneHeight(self): """ This method is the property for **self.__graphicsSceneHeight** attribute. :return: self.__graphicsSceneHeight. ( Object ) """ return self.__graphicsSceneHeight @graphicsSceneHeight.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def graphicsSceneHeight(self, value): """ This method is the setter method for **self.__graphicsSceneHeight** attribute. :param value: Attribute value. ( Object ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "graphicsSceneHeight")) @graphicsSceneHeight.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def graphicsSceneHeight(self): """ This method is the deleter method for **self.__graphicsSceneHeight** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "graphicsSceneHeight")) @property def minimumZoomFactor(self): """ This method is the property for **self.__minimumZoomFactor** attribute. :return: self.__minimumZoomFactor. ( Float ) """ return self.__minimumZoomFactor @minimumZoomFactor.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def minimumZoomFactor(self, value): """ This method is the setter method for **self.__minimumZoomFactor** attribute. :param value: Attribute value. ( Float ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "minimumZoomFactor")) @minimumZoomFactor.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def minimumZoomFactor(self): """ This method is the deleter method for **self.__minimumZoomFactor** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "minimumZoomFactor")) @property def maximumZoomFactor(self): """ This method is the property for **self.__maximumZoomFactor** attribute. :return: self.__maximumZoomFactor. ( Float ) """ return self.__maximumZoomFactor @maximumZoomFactor.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def maximumZoomFactor(self, value): """ This method is the setter method for **self.__maximumZoomFactor** attribute. :param value: Attribute value. ( Float ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "maximumZoomFactor")) @maximumZoomFactor.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def maximumZoomFactor(self): """ This method is the deleter method for **self.__maximumZoomFactor** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "maximumZoomFactor")) @property def wheelZoomFactor(self): """ This method is the property for **self.__wheelZoomFactor** attribute. :return: self.__wheelZoomFactor. ( Float ) """ return self.__wheelZoomFactor @wheelZoomFactor.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def wheelZoomFactor(self, value): """ This method is the setter method for **self.__wheelZoomFactor** attribute. :param value: Attribute value. ( Float ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "wheelZoomFactor")) @wheelZoomFactor.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def wheelZoomFactor(self): """ This method is the deleter method for **self.__wheelZoomFactor** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "wheelZoomFactor")) @property def keyZoomFactor(self): """ This method is the property for **self.__keyZoomFactor** attribute. :return: self.__keyZoomFactor. ( Float ) """ return self.__keyZoomFactor @keyZoomFactor.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def keyZoomFactor(self, value): """ This method is the setter method for **self.__keyZoomFactor** attribute. :param value: Attribute value. ( Float ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "keyZoomFactor")) @keyZoomFactor.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def keyZoomFactor(self): """ This method is the deleter method for **self.__keyZoomFactor** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "keyZoomFactor")) @property def graphicsView(self): """ This method is the property for **self.__graphicsView** attribute. :return: self.__graphicsView. ( QGraphicsView ) """ return self.__graphicsView @graphicsView.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def graphicsView(self, value): """ This method is the setter method for **self.__graphicsView** attribute. :param value: Attribute value. ( QGraphicsView ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "graphicsView")) @graphicsView.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def graphicsView(self): """ This method is the deleter method for **self.__graphicsView** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "graphicsView")) @property def graphicsScene(self): """ This method is the property for **self.__graphicsScene** attribute. :return: self.__graphicsScene. ( QGraphicsScene ) """ return self.__graphicsScene @graphicsScene.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def graphicsScene(self, value): """ This method is the setter method for **self.__graphicsScene** attribute. :param value: Attribute value. ( QGraphicsScene ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "graphicsScene")) @graphicsScene.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def graphicsScene(self): """ This method is the deleter method for **self.__graphicsScene** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "graphicsScene")) @property def displayGraphicsItem(self): """ This method is the property for **self.__displayGraphicsItem** attribute. :return: self.__displayGraphicsItem. ( QGraphicsItem ) """ return self.__displayGraphicsItem @displayGraphicsItem.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def displayGraphicsItem(self, value): """ This method is the setter method for **self.__displayGraphicsItem** attribute. :param value: Attribute value. ( QGraphicsItem ) """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "displayGraphicsItem")) @displayGraphicsItem.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def displayGraphicsItem(self): """ This method is the deleter method for **self.__displayGraphicsItem** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "displayGraphicsItem")) #****************************************************************************************************************** #*** Class methods. #****************************************************************************************************************** def show(self): """ This method reimplements the :meth:`QWidget.show` method. """ super(ImagesPreviewer, self).show() foundations.ui.common.centerWidgetOnScreen(self) def closeEvent(self, event): """ This method reimplements the :meth:`QWidget.closeEvent` method. :param event: QEvent ( QEvent ) """ LOGGER.debug("> Removing '{0}' from Images Previewers list.".format(self)) self.__container.imagesPreviewers.remove(self) event.accept() def wheelEvent(self, event): """ This method reimplements the :meth:`QWidget.wheelEvent` method. :param event: QEvent ( QEvent ) """ self.scaleView(pow(1.5, event.delta() / self.__wheelZoomFactor)) def keyPressEvent(self, event): """ This method reimplements the :meth:`QWidget.keyPressEvent` method. :param event: QEvent ( QEvent ) """ key = event.key() if key == Qt.Key_Plus: self.scaleView(self.__keyZoomFactor) elif key == Qt.Key_Minus: self.scaleView(1 / self.__keyZoomFactor) else: super(ImagesPreviewer, self).keyPressEvent(event) def __initializeUi(self): """ This method initializes the Widget ui. """ LOGGER.debug("> Initializing '{0}' ui.".format(self.__class__.__name__)) self.Previous_Image_pushButton.setIcon(QIcon(os.path.join(self.__uiResourcesDirectory, self.__uiPreviousImage))) self.Next_Image_pushButton.setIcon(QIcon(os.path.join(self.__uiResourcesDirectory, self.__uiNextImage))) self.Zoom_In_pushButton.setIcon(QIcon(os.path.join(self.__uiResourcesDirectory, self.__uiZoomInImage))) self.Zoom_Out_pushButton.setIcon(QIcon(os.path.join(self.__uiResourcesDirectory, self.__uiZoomOutImage))) len(self.__paths) <= 1 and self.Navigation_frame.hide() LOGGER.debug("> Initializing graphics View.") self.__graphicsView = QGraphicsView() self.__graphicsView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.__graphicsView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.__graphicsView.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.__graphicsView.setDragMode(QGraphicsView.ScrollHandDrag) # Reimplementing QGraphicsView wheelEvent method. self.__graphicsView.wheelEvent = self.wheelEvent LOGGER.debug("> Initializing graphics scene.") self.__graphicsScene = QGraphicsScene(self.__graphicsView) self.__graphicsScene.setItemIndexMethod(QGraphicsScene.NoIndex) self.__graphicsScene.setSceneRect(-(float(self.__graphicsSceneWidth)) / 2, - (float(self.__graphicsSceneHeight)) / 2, float(self.__graphicsSceneWidth), float(self.__graphicsSceneHeight)) self.__graphicsView.setScene(self.__graphicsScene) self.__graphicsView.setBackgroundBrush(QBrush(self.__graphicsSceneBackgroundColor)) self.Images_Previewer_frame_gridLayout.addWidget(self.__graphicsView) # Signals / Slots. self.__container.engine.imagesCaches.QImage.contentAdded.connect(self.__engine_imagesCaches_QImage__contentAdded) self.Previous_Image_pushButton.clicked.connect(self.__Previous_Image_pushButton__clicked) self.Next_Image_pushButton.clicked.connect(self.__Next_Image_pushButton__clicked) self.Zoom_Out_pushButton.clicked.connect(self.__Zoom_Out_pushButton__clicked) self.Zoom_In_pushButton.clicked.connect(self.__Zoom_In_pushButton__clicked) self.Zoom_Fit_pushButton.clicked.connect(self.__Zoom_Fit_pushButton__clicked) def __Images_Informations_label_setUi(self): """ This method sets the **Images_Informations_label** Widget ui. """ if not self.__displayGraphicsItem: return image = self.__displayGraphicsItem.image self.Images_Informations_label.setText("{0} - {1}x{2} px - {3} bit".format(os.path.basename(image.data.path), image.data.width, image.data.height, image.data.bpp / 4)) def __engine_imagesCaches_QImage__contentAdded(self, content): """ This method is triggered by the Application **QImage** images cache when content has been added. :param content: Cache added content. ( List ) """ if not self.__paths: return path = foundations.common.getFirstItem(content) if not path in self.__paths: return image = self.__container.engine.imagesCaches.QImage.getContent(path) self.__setDisplayGraphicsItem(image) def __Previous_Image_pushButton__clicked(self, checked): """ This method is triggered when **Previous_Image_pushButton** Widget is clicked. :param checked: Checked state. ( Boolean ) """ self.loopThroughImages(True) def __Next_Image_pushButton__clicked(self, checked): """ This method is triggered when **Next_Image_pushButton** Widget is clicked. :param checked: Checked state. ( Boolean ) """ self.loopThroughImages() def __Zoom_In_pushButton__clicked(self, checked): """ This method is triggered when **Zoom_In_pushButton** Widget is clicked. :param checked: Checked state. ( Boolean ) """ self.scaleView(self.__keyZoomFactor) def __Zoom_Out_pushButton__clicked(self, checked): """ This method is triggered when **Zoom_Out_pushButton** Widget is clicked. :param checked: Checked state. ( Boolean ) """ self.scaleView(1 / self.__keyZoomFactor) def __Zoom_Fit_pushButton__clicked(self, checked): """ This method is triggered when **Zoom_Fit_pushButton** Widget is clicked. :param checked: Checked state. ( Boolean ) """ self.fitImage() def __clearGraphicsScene(self): """ This method clears the View. """ for graphicsItem in self.__graphicsScene.items(): self.__graphicsScene.removeItem(graphicsItem) def __setDisplayGraphicsItem(self, image): """ This method sets the View using given image. :param image: Image to display. ( Qimage ) """ self.__clearGraphicsScene() LOGGER.debug("> Initializing graphics item.") self.__displayGraphicsItem = Image_QGraphicsItem(image=image) self.__graphicsScene.addItem(self.__displayGraphicsItem) self.__Images_Informations_label_setUi() def loadImage(self, index=0): """ This method loads the display image in the View. :param index: Index to load. ( Integer ) :return: Method success. ( Boolean ) """ if not self.__paths: return False image = sibl_gui.ui.common.getImage(self.__paths[index]) self.__setDisplayGraphicsItem(image) return True def scaleView(self, scaleFactor): """ This method scales the Previewer view. :param scaleFactor: Float ( Float ) :return: Method success. ( Boolean ) """ graphicsView = self.findChild(QGraphicsView) factor = graphicsView.matrix().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width() if factor < self.__minimumZoomFactor or factor > self.__maximumZoomFactor: return False graphicsView.scale(scaleFactor, scaleFactor) return True def fitWindow(self): """ This method fits the View window. :return: Method success. ( Boolean ) """ if not self.__displayGraphicsItem: return False desktopWidth = QApplication.desktop().screenGeometry(QApplication.desktop().primaryScreen()).width() desktopHeight = QApplication.desktop().screenGeometry(QApplication.desktop().primaryScreen()).height() width = min(desktopWidth * 0.80, self.__displayGraphicsItem.width) height = min(desktopHeight * 0.80, self.__displayGraphicsItem.height) self.resize(width, height) foundations.ui.common.centerWidgetOnScreen(self) return True def fitImage(self): """ This method fits the image to the View. :return: Method success. ( Boolean ) """ if not self.__displayGraphicsItem: return False self.__graphicsView.fitInView( QRectF(-(self.__displayGraphicsItem.width / 2) - (self.__displayGraphicsItemMargin / 2), - (self.__displayGraphicsItem.height / 2) - (self.__displayGraphicsItemMargin / 2), self.__displayGraphicsItem.width + self.__displayGraphicsItemMargin, self.__displayGraphicsItem.height + self.__displayGraphicsItemMargin), Qt.KeepAspectRatio) return True def loopThroughImages(self, backward=False): """ This method loops through View images. :param backward: Looping backward. ( Boolean ) :return: Method success. ( Boolean ) """ index = self.__paths.index(self.__displayGraphicsItem.image.data.path) index += not backward and 1 or -1 if index < 0: index = len(self.__paths) - 1 elif index > len(self.__paths) - 1: index = 0 self.loadImage(index) return True
diagram.set_anchors() layouter.apply(diagram) # edges must be updated after nodes are updated and layouted for edge in diagram.edges.values(): edge.update() # this actually paints things, so must be invoked when everything is # ready for drawable in diagram.elements(): scene.addItem(drawable) drawable.resize_scene_rect() adj_scene_rect = scene.sceneRect().adjusted(-margin, -margin, margin, margin) scene.setSceneRect(adj_scene_rect) diagramsize = adj_scene_rect.toRect().size() img = QImage(QSize(diagramsize.width() * scale, diagramsize.height() * scale), QImage.Format_ARGB32) painter = QPainter(img) print margin absoluteRect = QRectF(0, 0, scene.sceneRect().width() * scale, scene.sceneRect().height() * scale) painter.fillRect(absoluteRect, QBrush(QColor(255, 255, 255), Qt.SolidPattern)) painter.resetMatrix() scene.render(painter) painter.end() ret = img.save(output) print("Saved to " + output) for e in logger.events:
def reduce_speed(self, factor=0.9): for particle in self.particles: particle.reduce_speed(factor) def increase_speed(self, factor=1.1): for particle in self.particles: particle.increase_speed(factor) def set_color(self, color): for particle in self.particles: particle.set_color(color) def recalculate_new_pos(self): for particle in self.particles: particle.instant_pos_change() if __name__ == "__main__": app = QApplication(sys.argv) scene = QGraphicsScene() scene.setSceneRect(-400, -400.0, 800.0, 800.0) particle_background = ParticlesBackgroundDecoration(scene) view = QGraphicsView(scene) view.showMaximized() scene.setSceneRect( view.mapToScene(view.viewport().geometry()).boundingRect()) particle_background.generate_particles(200) particle_background.reduce_speed(0.3) print scene.sceneRect() app.exec_()
class SpotguideShowImageDlg(QtGui.QDialog, FORM_CLASS): def __init__(self, theCanvas, theLayer, selFeatureIds, parent=None): super(SpotguideShowImageDlg, self).__init__(parent) self.setupUi(self) self.mTheCanvas = theCanvas self.mTheLayer = theLayer self.mSelFeatureIds = selFeatureIds self.mAllFeatureIds = [] self.highlightList = [] # members shown in graphic view. self.mScene = QGraphicsScene() self.graphicsViewShowImage.setScene(self.mScene) self.mPixmapList = [] featureIter = self.mTheLayer.getFeatures(QgsFeatureRequest().setFlags( QgsFeatureRequest.NoGeometry)) inti = 0 theFeature = QgsFeature() while (featureIter.nextFeature(theFeature) and inti < 512): inti += 1 self.mAllFeatureIds.append(theFeature.id()) self.spinBoxFeatureIndex.setValue(1) self.spinBoxFeatureIndex.setMinimum(1) self.spinBoxFeatureIndex.setMaximum(inti) errMsg = [''] self.initComboBoxOutlinkid() self.selectFeatureById(errMsg, self.mSelFeatureIds[0], bZoomToSelected=False) self.comboBoxOutlinkid.setFocus() self.pushButtonPrev.clicked.connect(self.onPushButtonPrev) self.pushButtonNext.clicked.connect(self.onPushButtonNext) self.connect(self.comboBoxOutlinkid, QtCore.SIGNAL('activated(QString)'), self.comboBoxOutlinkidChanged) def resizeEvent(self, event): self.showImageInGraphicsView() return def disableAllControls(self): self.pushButtonPrev.setEnabled(False) self.pushButtonPrev.setEnabled(False) self.comboBoxOutlinkid.setEnabled(False) self.textEditFeatureInfo.setEnabled(False) return def initComboBoxOutlinkid(self): while (self.comboBoxOutlinkid.count() > 0): self.comboBoxOutlinkid.removeItem(0) for oneFeatureId in self.mSelFeatureIds: featureIter = self.mTheLayer.getFeatures( QgsFeatureRequest(oneFeatureId).setFlags( QgsFeatureRequest.NoGeometry)) theFeature = QgsFeature() if featureIter.nextFeature(theFeature) == False: return if self.mIsMyFeature(theFeature): self.comboBoxOutlinkid.addItem( str(theFeature.attribute('out_link_id'))) def showFeatureDetail(self, errMsg, theFeature): strFeatureInfo = self.getFeatureInfoString(theFeature) self.textEditFeatureInfo.setText(strFeatureInfo) if self.mIsMyFeature(theFeature) == False: return errMsg = [''] pattern_dat, arrow_dat = self.getSpotguidePictures( errMsg, self.mTheLayer, theFeature) if errMsg[0] != '': #QMessageBox.information(self, "Show Spotguide", errMsg[0]) return self.mPixmapList = [] if pattern_dat is not None: patternDatParser = DatParser() patternDatParser.initFromMemory(errMsg, pattern_dat) # pattern picture patternPixmap = QPixmap() patternPixmap.loadFromData( patternDatParser.getDatContentByIndex(errMsg, 0)) self.mPixmapList.append(patternPixmap) if arrow_dat is not None: arrowDatParser = DatParser() arrowDatParser.initFromMemory(errMsg, arrow_dat) # arrow picture arrowPixmap = QPixmap() arrowPixmap.loadFromData( arrowDatParser.getDatContentByIndex(errMsg, 0)) if arrowDatParser.hasPointlist(): # draw the point list on the arrow picture vecCoors = arrowDatParser.getPointListCoordinatesByIndex( errMsg, arrowDatParser.getPointlistIndex()) if errMsg[0] != '': QMessageBox.information(self, "Show Spotguide", errMsg[0]) return with QPainter(arrowPixmap) as thePainter: for oneXYPair in vecCoors: thePainter.setPen(QPen(QColor(255, 0, 0))) thePainter.drawPoint(oneXYPair[0], oneXYPair[1]) thePainter.drawPoint(oneXYPair[0] - 1, oneXYPair[1]) thePainter.drawPoint(oneXYPair[0] + 1, oneXYPair[1]) thePainter.drawPoint(oneXYPair[0], oneXYPair[1] - 1) thePainter.drawPoint(oneXYPair[0], oneXYPair[1] + 1) # append pointlist information to the text box. strPointList = arrowDatParser.getPointListStringByIndex( errMsg, arrowDatParser.getPointlistIndex()) if errMsg[0] != '': QMessageBox.information(self, "Show Spotguide", errMsg[0]) return strTemp = self.textEditFeatureInfo.toPlainText() strTemp += """\n\npointlist:\n""" strTemp += strPointList self.textEditFeatureInfo.setText(strTemp) self.mPixmapList.append(arrowPixmap) self.showImageInGraphicsView() return def showImageInGraphicsView(self): # remove all items in member QGraphicsScene. for oneItem in self.mScene.items(): self.mScene.removeItem(oneItem) for onePixmap in self.mPixmapList: self.mScene.addPixmap( self.getPixMapSizedByWidgt(onePixmap, self.graphicsViewShowImage)) self.mScene.setSceneRect(0, 0, self.graphicsViewShowImage.width() - 5, self.graphicsViewShowImage.height() - 5) return def getFeatureInfoString(self, theFeature): fieldList = theFeature.fields() attrList = theFeature.attributes() strFeatureInfo = "field count: %d\n" % len(fieldList) for oneField, oneAttr in zip(fieldList, attrList): if isinstance(oneAttr, float): strFeatureInfo += "%s: %.0f\n" % (oneField.name(), oneAttr) else: strFeatureInfo += "%s: %s\n" % (oneField.name(), oneAttr) return strFeatureInfo # result[0] is pattern dat # result[1] is arrow dat def getSpotguidePictures(self, errMsg, layer, theFeature): try: uri = QgsDataSourceURI(layer.source()) conn = psycopg2.connect('''host='%s' dbname='%s' user='******' password='******' ''' %\ (uri.host(), uri.database(), uri.username(), uri.password())) pg = conn.cursor() # all these lane's keys must be found # if anyone is not found, a 'KeyError' exception will be thrown. in_link_id = theFeature.attribute('in_link_id') node_id = theFeature.attribute('node_id') out_link_id = theFeature.attribute('out_link_id') passlink_count = theFeature.attribute('passlink_count') pattern_id = theFeature.attribute('pattern_id') arrow_id = theFeature.attribute('arrow_id') # spotguide record filter. strFilter = '''in_link_id=%s and node_id=%s and out_link_id=%s and passlink_count=%s and pattern_id=%s and arrow_id=%s''' % \ (in_link_id, node_id, out_link_id, passlink_count, pattern_id, arrow_id) sqlcmd = \ """SET bytea_output TO escape; select pattern_dat, arrow_dat from %s where %s """ % (uri.table(), strFilter) pg.execute(sqlcmd) row = pg.fetchone() return row[0], row[1] except KeyError, kErr: errMsg[0] = """Selected feature is not a rdb spotguide feature.""" return None, None except Exception, ex: errMsg[0] = ex.message return None, None
class OWHierarchicalClustering(widget.OWWidget): name = "Hierarchical Clustering" description = ("Hierarchical clustering based on distance matrix, and " "a dendrogram viewer.") icon = "icons/HierarchicalClustering.svg" priority = 2100 inputs = [("Distances", Orange.misc.DistMatrix, "set_distances")] outputs = [("Selected Data", Orange.data.Table), ("Other Data", Orange.data.Table)] #: Selected linkage linkage = settings.Setting(1) #: Index of the selected annotation item (variable, ...) annotation_idx = settings.Setting(0) #: Selected tree pruning (none/max depth) pruning = settings.Setting(0) #: Maximum depth when max depth pruning is selected max_depth = settings.Setting(10) #: Selected cluster selection method (none, cut distance, top n) selection_method = settings.Setting(0) #: Cut height ratio wrt root height cut_ratio = settings.Setting(75.0) #: Number of top clusters to select top_n = settings.Setting(3) append_clusters = settings.Setting(True) cluster_role = settings.Setting(2) cluster_name = settings.Setting("Cluster") autocommit = settings.Setting(False) #: Cluster variable domain role AttributeRole, ClassRole, MetaRole = 0, 1, 2 def __init__(self, parent=None): super().__init__(parent) self.matrix = None self.items = None self.linkmatrix = None self.root = None self._displayed_root = None self.cutoff_height = 0.0 self._invalidated = False gui.comboBox(gui.widgetBox(self.controlArea, "Linkage"), self, "linkage", items=LINKAGE, callback=self._invalidate_clustering) box = gui.widgetBox(self.controlArea, "Annotation") self.label_cb = gui.comboBox(box, self, "annotation_idx", callback=self._update_labels) self.label_cb.setModel(itemmodels.VariableListModel()) self.label_cb.model()[:] = ["None", "Enumeration"] box = gui.radioButtons(self.controlArea, self, "pruning", box="Pruning", callback=self._invalidate_pruning) grid = QGridLayout() box.layout().addLayout(grid) grid.addWidget(gui.appendRadioButton(box, "None", addToLayout=False), 0, 0) self.max_depth_spin = gui.spin(box, self, "max_depth", minv=1, maxv=100, callback=self._invalidate_pruning, keyboardTracking=False) grid.addWidget( gui.appendRadioButton(box, "Max depth", addToLayout=False), 1, 0) grid.addWidget(self.max_depth_spin, 1, 1) box = gui.radioButtons(self.controlArea, self, "selection_method", box="Selection", callback=self._selection_method_changed) grid = QGridLayout() box.layout().addLayout(grid) grid.addWidget(gui.appendRadioButton(box, "Manual", addToLayout=False), 0, 0) grid.addWidget( gui.appendRadioButton(box, "Height ratio", addToLayout=False), 1, 0) self.cut_ratio_spin = gui.spin(box, self, "cut_ratio", 0, 100, step=1e-1, spinType=float, callback=self._selection_method_changed) self.cut_ratio_spin.setSuffix("%") grid.addWidget(self.cut_ratio_spin, 1, 1) grid.addWidget(gui.appendRadioButton(box, "Top N", addToLayout=False), 2, 0) self.top_n_spin = gui.spin(box, self, "top_n", 1, 20, callback=self._selection_method_changed) grid.addWidget(self.top_n_spin, 2, 1) box.layout().addLayout(grid) self.controlArea.layout().addStretch() box = gui.widgetBox(self.controlArea, "Output") gui.checkBox(box, self, "append_clusters", "Append cluster IDs", callback=self._invalidate_output) ibox = gui.indentedBox(box) name_edit = gui.lineEdit(ibox, self, "cluster_name") name_edit.editingFinished.connect(self._invalidate_output) cb = gui.comboBox( ibox, self, "cluster_role", callback=self._invalidate_output, items=["Attribute", "Class variable", "Meta variable"]) form = QFormLayout(fieldGrowthPolicy=QFormLayout.AllNonFixedFieldsGrow, labelAlignment=Qt.AlignLeft, spacing=8) form.addRow("Name", name_edit) form.addRow("Place", cb) ibox.layout().addSpacing(5) ibox.layout().addLayout(form) ibox.layout().addSpacing(5) cb = gui.checkBox(box, self, "autocommit", "Commit automatically") b = gui.button(box, self, "Commit", callback=self.commit, default=True) gui.setStopper(self, b, cb, "_invalidated", callback=self.commit) self.scene = QGraphicsScene() self.view = QGraphicsView( self.scene, horizontalScrollBarPolicy=Qt.ScrollBarAlwaysOff, verticalScrollBarPolicy=Qt.ScrollBarAlwaysOn, alignment=Qt.AlignLeft | Qt.AlignVCenter) def axis_view(orientation): ax = pg.AxisItem(orientation=orientation, maxTickLength=7) scene = QGraphicsScene() scene.addItem(ax) view = QGraphicsView( scene, horizontalScrollBarPolicy=Qt.ScrollBarAlwaysOff, verticalScrollBarPolicy=Qt.ScrollBarAlwaysOn, alignment=Qt.AlignLeft | Qt.AlignVCenter) view.setFixedHeight(ax.size().height()) ax.line = SliderLine(orientation=Qt.Horizontal, length=ax.size().height()) scene.addItem(ax.line) return view, ax self.top_axis_view, self.top_axis = axis_view("top") self.mainArea.layout().setSpacing(1) self.mainArea.layout().addWidget(self.top_axis_view) self.mainArea.layout().addWidget(self.view) self.bottom_axis_view, self.bottom_axis = axis_view("bottom") self.mainArea.layout().addWidget(self.bottom_axis_view) self._main_graphics = QGraphicsWidget() self._main_layout = QGraphicsLinearLayout(Qt.Horizontal) self._main_layout.setSpacing(1) self._main_graphics.setLayout(self._main_layout) self.scene.addItem(self._main_graphics) self.dendrogram = DendrogramWidget() self.dendrogram.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.dendrogram.selectionChanged.connect(self._invalidate_output) self.dendrogram.selectionEdited.connect(self._selection_edited) fm = self.fontMetrics() self.dendrogram.setContentsMargins(5, fm.lineSpacing() / 2, 5, fm.lineSpacing() / 2) self.labels = GraphicsSimpleTextList() self.labels.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.labels.setAlignment(Qt.AlignLeft) self.labels.setMaximumWidth(200) self.labels.layout().setSpacing(0) self._main_layout.addItem(self.dendrogram) self._main_layout.addItem(self.labels) self._main_layout.setAlignment(self.dendrogram, Qt.AlignLeft | Qt.AlignVCenter) self._main_layout.setAlignment(self.labels, Qt.AlignLeft | Qt.AlignVCenter) self.view.viewport().installEventFilter(self) self.top_axis_view.viewport().installEventFilter(self) self.bottom_axis_view.viewport().installEventFilter(self) self._main_graphics.installEventFilter(self) self.cut_line = SliderLine(self.dendrogram, orientation=Qt.Horizontal) self.cut_line.valueChanged.connect(self._dendrogram_slider_changed) self.cut_line.hide() self.bottom_axis.line.valueChanged.connect(self._axis_slider_changed) self.top_axis.line.valueChanged.connect(self._axis_slider_changed) self.dendrogram.geometryChanged.connect(self._dendrogram_geom_changed) self._set_cut_line_visible(self.selection_method == 1) def set_distances(self, matrix): self.matrix = matrix self._invalidate_clustering() self._set_items(matrix.row_items if matrix is not None else None) def _set_items(self, items): self.items = items if items is None: self.label_cb.model()[:] = ["None", "Enumeration"] elif isinstance(items, Orange.data.Table): vars = list(items.domain) self.label_cb.model()[:] = ["None", "Enumeration"] + vars elif isinstance(items, list) and \ all(isinstance(var, Orange.data.Variable) for var in items): self.label_cb.model()[:] = ["None", "Enumeration", "Name"] else: self.label_cb.model()[:] = ["None", "Enumeration"] self.annotation_idx = min(self.annotation_idx, len(self.label_cb.model()) - 1) def handleNewSignals(self): self._update_labels() def _clear_plot(self): self.labels.set_labels([]) self.dendrogram.set_root(None) def _set_displayed_root(self, root): self._clear_plot() self._displayed_root = root self.dendrogram.set_root(root) self._update_labels() self._main_graphics.resize( self._main_graphics.size().width(), self._main_graphics.sizeHint(Qt.PreferredSize).height()) self._main_graphics.layout().activate() def _update(self): self._clear_plot() distances = self.matrix if distances is not None: # Convert to flat upper triangular distances i, j = numpy.triu_indices(distances.X.shape[0], k=1) distances = distances.X[i, j] method = LINKAGE[self.linkage].lower() Z = scipy.cluster.hierarchy.linkage(distances, method=method) tree = tree_from_linkage(Z) self.linkmatrix = Z self.root = tree self.top_axis.setRange(tree.value.height, 0.0) self.bottom_axis.setRange(tree.value.height, 0.0) if self.pruning: self._set_displayed_root(prune(tree, level=self.max_depth)) else: self._set_displayed_root(tree) else: self.linkmatrix = None self.root = None self._set_displayed_root(None) self._apply_selection() def _update_labels(self): labels = [] if self.root and self._displayed_root: indices = [leaf.value.index for leaf in leaves(self.root)] if self.annotation_idx == 0: labels = [] elif self.annotation_idx == 1: labels = [str(i) for i in indices] elif isinstance(self.items, Orange.data.Table): var = self.label_cb.model()[self.annotation_idx] col = self.items[:, var] labels = [var.repr_val(next(iter(row))) for row in col] labels = [labels[idx] for idx in indices] else: labels = [] if labels and self._displayed_root is not self.root: joined = leaves(self._displayed_root) labels = [ ", ".join(labels[leaf.value.first:leaf.value.last]) for leaf in joined ] self.labels.set_labels(labels) self.labels.setMinimumWidth(1 if labels else -1) def _invalidate_clustering(self): self._update() self._update_labels() def _invalidate_output(self): self._invalidated = True if self.autocommit: self.commit() def _invalidate_pruning(self): if self.root: selection = self.dendrogram.selected_nodes() ranges = [node.value.range for node in selection] if self.pruning: self._set_displayed_root(prune(self.root, level=self.max_depth)) else: self._set_displayed_root(self.root) selected = [ node for node in preorder(self._displayed_root) if node.value.range in ranges ] self.dendrogram.set_selected_clusters(selected) self._apply_selection() def commit(self): self._invalidated = False items = getattr(self.matrix, "items", self.items) if not items: # nothing to commit return selection = self.dendrogram.selected_nodes() selection = sorted(selection, key=lambda c: c.value.first) indices = [leaf.value.index for leaf in leaves(self.root)] maps = [ indices[node.value.first:node.value.last] for node in selection ] selected_indices = list(chain(*maps)) unselected_indices = sorted( set(range(self.root.value.last)) - set(selected_indices)) selected = [items[k] for k in selected_indices] unselected = [items[k] for k in unselected_indices] if not selected: self.send("Selected Data", None) self.send("Other Data", None) return selected_data = unselected_data = None if isinstance(items, Orange.data.Table): c = numpy.zeros(len(items)) for i, indices in enumerate(maps): c[indices] = i c[unselected_indices] = len(maps) mask = c != len(maps) if self.append_clusters: clust_var = Orange.data.DiscreteVariable( str(self.cluster_name), values=[ "Cluster {}".format(i + 1) for i in range(len(maps)) ] + ["Other"]) data, domain = items, items.domain attrs = domain.attributes class_ = domain.class_vars metas = domain.metas X, Y, M = data.X, data.Y, data.metas if self.cluster_role == self.AttributeRole: attrs = attrs + (clust_var, ) X = numpy.c_[X, c] elif self.cluster_role == self.ClassRole: class_ = class_ + (clust_var, ) Y = numpy.c_[Y, c] elif self.cluster_role == self.MetaRole: metas = metas + (clust_var, ) M = numpy.c_[M, c] domain = Orange.data.Domain(attrs, class_, metas) data = Orange.data.Table(domain, X, Y, M) else: data = items if selected: selected_data = data[mask] if unselected: unselected_data = data[~mask] self.send("Selected Data", selected_data) self.send("Other Data", unselected_data) def sizeHint(self): return QSize(800, 500) def eventFilter(self, obj, event): if obj is self.view.viewport() and event.type() == QEvent.Resize: width = self.view.viewport().width() - 2 self._main_graphics.setMaximumWidth(width) self._main_graphics.setMinimumWidth(width) self._main_graphics.layout().activate() elif event.type() == QEvent.MouseButtonPress and \ (obj is self.top_axis_view.viewport() or obj is self.bottom_axis_view.viewport()): self.selection_method = 1 # Map click point to cut line local coordinates pos = self.top_axis_view.mapToScene(event.pos()) cut = self.top_axis.line.mapFromScene(pos) self.top_axis.line.setValue(cut.x()) # update the line visibility, output, ... self._selection_method_changed() return super().eventFilter(obj, event) def _dendrogram_geom_changed(self): pos = self.dendrogram.pos_at_height(self.cutoff_height) geom = self.dendrogram.geometry() crect = self.dendrogram.contentsRect() self._set_slider_value(pos.x(), geom.width()) self.cut_line.setLength(geom.height()) self.top_axis.resize(crect.width(), self.top_axis.height()) self.top_axis.setPos(geom.left() + crect.left(), 0) self.top_axis.line.setPos(self.cut_line.scenePos().x(), 0) self.bottom_axis.resize(crect.width(), self.bottom_axis.height()) self.bottom_axis.setPos(geom.left() + crect.left(), 0) self.bottom_axis.line.setPos(self.cut_line.scenePos().x(), 0) geom = self._main_graphics.geometry() assert geom.topLeft() == QPointF(0, 0) self.scene.setSceneRect(geom) geom.setHeight(self.top_axis.size().height()) self.top_axis.scene().setSceneRect(geom) self.bottom_axis.scene().setSceneRect(geom) def _axis_slider_changed(self, value): self.cut_line.setValue(value) def _dendrogram_slider_changed(self, value): p = QPointF(value, 0) cl_height = self.dendrogram.height_at(p) self.set_cutoff_height(cl_height) # Sync the cut positions between the dendrogram and the axis. self._set_slider_value(value, self.dendrogram.size().width()) def _set_slider_value(self, value, span): with blocked(self.cut_line): self.cut_line.setValue(value) self.cut_line.setRange(0, span) with blocked(self.top_axis.line): self.top_axis.line.setValue(value) self.top_axis.line.setRange(0, span) with blocked(self.bottom_axis.line): self.bottom_axis.line.setValue(value) self.bottom_axis.line.setRange(0, span) def set_cutoff_height(self, height): self.cutoff_height = height if self.root: self.cut_ratio = 100 * height / self.root.value.height self.select_max_height(height) def _set_cut_line_visible(self, visible): self.cut_line.setVisible(visible) self.top_axis.line.setVisible(visible) self.bottom_axis.line.setVisible(visible) def select_top_n(self, n): root = self._displayed_root if root: clusters = top_clusters(root, n) self.dendrogram.set_selected_clusters(clusters) def select_max_height(self, height): root = self._displayed_root if root: clusters = clusters_at_height(root, height) self.dendrogram.set_selected_clusters(clusters) def _selection_method_changed(self): self._set_cut_line_visible(self.selection_method == 1) if self.root: self._apply_selection() def _apply_selection(self): if not self.root: return if self.selection_method == 0: pass elif self.selection_method == 1: height = self.cut_ratio * self.root.value.height / 100 self.set_cutoff_height(height) pos = self.dendrogram.pos_at_height(height) self._set_slider_value(pos.x(), self.dendrogram.size().width()) elif self.selection_method == 2: self.select_top_n(self.top_n) def _selection_edited(self): # Selection was edited by clicking on a cluster in the # dendrogram view. self.selection_method = 0 self._selection_method_changed()
class MainForm(QDialog): def __init__(self, parent=None, filename=None): super(MainForm, self).__init__(parent) self.view = GraphicsView() background = QPixmap(filename) self.filename = os.path.splitext(filename)[0] if ("-%s" % ORG) in self.filename: self.filename = self.filename[:-len(ORG)-5] + ".png" self.view.setBackgroundBrush(QBrush(background)) # self.view.setCacheMode(QGraphicsView.CacheBackground) # self.view.setDragMode(QGraphicsView.ScrollHandDrag) self.scene = QGraphicsScene(self) global scene scene = self.scene self.view.dialog = self self.view.setScene(self.scene) self.prevPoint = QPoint() self.lastStamp = -1 buttonLayout = QVBoxLayout() for text, slot in ( ("&Tag", self.addTag), ("Align &bottom", self.alignBottom), ("Align &left", self.alignLeft), ("&Save", self.save), ("&Quit", self.accept)): button = QPushButton(text) if not MAC: button.setFocusPolicy(Qt.NoFocus) self.connect(button, SIGNAL("clicked()"), slot) if text == "&Save": buttonLayout.addStretch(5) if text == "&Quit": buttonLayout.addStretch(1) buttonLayout.addWidget(button) buttonLayout.addStretch() self.view.resize(background.width(), background.height()) self.scene.setSceneRect(0, 0, background.size().width(), background.size().height()) self.view.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) layout = QHBoxLayout() layout.addWidget(self.view, 1) layout.addLayout(buttonLayout) self.setLayout(layout) self.setWindowTitle(AppName) info_name = self.filename + "-" + TAG + ".txt" if os.path.exists(info_name): for tag, x, y in [line.strip().split("\t") for line in open(info_name, "rt").readlines()]: self.addTag(int(tag), QPointF(int(x), int(y)), adjust_position=False) global Dirty; Dirty=False self.show() self.raise_() def reject(self): self.accept() def accept(self): self.offerSave() QDialog.accept(self) def offerSave(self): if (Dirty and QMessageBox.question(self, "%s - Unsaved Changes" % AppName, "Save unsaved changes?", QMessageBox.Yes|QMessageBox.No) == QMessageBox.Yes): self.save() def position(self): return QPointF(self.view.mapFromGlobal(QCursor.pos())) def addTag(self, stamp=None, position=None, adjust_position=True): if not position: position = self.position() if stamp is not None: self.lastStamp = stamp else: self.lastStamp += 1 item = StampItem(self.lastStamp, position, self.scene, adjust_position=adjust_position) item.update() global Dirty; Dirty = True def save(self): vals = sorted([(item.stamp, item.pos().x(), item.pos().y()) for item in self.scene.items() if isinstance(item, StampItem)]) info_name = "%s-%s.txt" %(self.filename, TAG) f = open(info_name, "wt") for tag, x, y in vals: f.write("%s\t%d\t%d\n" % (tag, x, y)) f.close() save_png(self.filename, [(x-5, y-5) for _, x, y in vals]) global Dirty; Dirty = False def renumberTags(self): """Number the tags by skipping the missing values""" vals = sorted([(item.stamp, item) for item in self.scene.items() if isinstance(item, StampItem)]) for i, (_, v) in enumerate(vals): v.setStamp(i) if not vals: i = -1 self.lastStamp = i global Dirty; Dirty = True def alignBottom(self): """Align tags horizontally, use bottom margin as a reference""" items = [item for item in self.scene.selectedItems() if isinstance(item, StampItem)] if items: ref_y = max(item.pos().y() for item in items) for item in items: item.setY(ref_y) global Dirty; Dirty = True def alignLeft(self): """Align tags vertically, use left margin as a reference""" items = [item for item in self.scene.selectedItems() if isinstance(item, StampItem)] if items: ref_x = min(item.pos().x() for item in items) for item in items: item.setX(ref_x) global Dirty; Dirty = True
class Factura: def __init__(self,padre,num): self.padre=padre self.cursor=padre.cursor self.curser=padre.curser self.parent=padre self.num=num self.escena=QGraphicsScene() self.gvDocumento=QGraphicsView() #self.cfg=padre.cfg self.iniciar() def iniciar(self): if self.cargarPlantilla(): iva=0 subtotal=0 total=0 alto=int(self.cfg.get("documento", "alto")) ancho=int(self.cfg.get("documento", "ancho")) cfont=QFont("Droid Sans", int(self.cfg.get("cliente", "fuente")), int(self.cfg.get("cliente", "peso") )) pfont=QFont("Droid Sans", int(self.cfg.get("productos", "fuente")), int(self.cfg.get("productos", "peso") )) ffont=QFont("Droid Sans", int(self.cfg.get("fecha", "fuente")), int(self.cfg.get("fecha", "peso") )) tfont=QFont("Droid Sans", int(self.cfg.get("totales", "fuente")), int(self.cfg.get("totales", "peso") )) self.escena.setSceneRect(-int(self.cfg.get("documento", "x")),-int(self.cfg.get("documento", "y")),ancho,alto) fuente=QFont("Droid Sans", int(self.cfg.get("documento", "fuente")), int(self.cfg.get("documento", "peso") )) smallDroid=QFont("Droid Sans", 9) sql="""SELECT * FROM clientes as C, notas WHERE notas.id=%s and notas.cliente=C.id;"""%self.num self.curser.execute(sql) cliente=self.curser.fetchone() if cliente!=None: cliente=dicursor(self.curser,cliente) datos=self.escena.addText("",cfont) datos.setHtml("<p><b>Nombre:</b> %s<br><b>Direccion:</b> %s, C.P %s %s, %s.<br><b>RFC:</b> %s</p>"%(cliente['nombre'],cliente['direccion'],cliente['correo'],cliente['poblacion'],cliente['estado'],cliente['rfc'])) datos.setPos(int(self.cfg.get("cliente", "x")) ,int(self.cfg.get("cliente", "y"))) datos.setTextWidth(int(self.cfg.get("cliente", "ancho"))) self.curser.execute("SELECT cantidad, `descripcion`,total/cantidad as precio,total,porcentaje as imp,unidades.nombre as unidad, ' ' as espacio from productos,vendidos, impuestos , unidades where ref=producto and venta="+str(self.num)+" and impuestos.id=impuesto and unidades.id=unidad group by ref") fecha=self.escena.addText("",ffont) if isinstance(cliente['fecha'],datetime.datetime): fecha.setHtml(cliente['fecha'].strftime(self.cfg.get("fecha", "formato"))) else: fecha.setHtml(datetime.datetime.strptime(cliente['fecha'],'%Y-%m-%d %H:%M:%S').strftime(self.cfg.get("fecha", "formato"))) fecha.setPos(int(self.cfg.get("fecha", "x")),int(self.cfg.get("fecha", "y"))) fecha.setTextWidth(int(self.cfg.get("fecha", "ancho"))) #print "SELECT cantidad, `descripcion`,precio,total from productos,vendidos where ref=producto and venta="+str(self.num)+" group by ref" arts=self.curser.fetchall() if arts!=None: arts=dicursor(self.curser,arts) col=[[],[],[],[],[]] #dict(arts) for item in arts: imp=0;porc=0 imp=item['total']/float("1.%d"%item['imp']) porc=imp*(int(item['imp'])*.01) #imp=round(imp,2) #porc=round(porc,2) #porc+=item['total']-(imp+porc) total+=item['total'] item['precio']=round(imp/item['cantidad'],2) item['total']=round(imp,2) iva+=porc subtotal+=imp subtotal=round(subtotal,2) iva=round(iva,2) filas=[] campos=self.cfg.get("productos", "campos").replace(" ","").split(",") heads="{%s}"%"},{".join(campos) anchos=self.cfg.get("productos", "anchos").replace(" ","").split(",") #cabezas=heads.replace("{","").replace("}","").split(",") for item in arts: row=heads.format(**item) filas.append(row.split(',')) heads=heads.replace("{","").replace("}","") tabla=self.escena.addText("",pfont) tabla.setHtml(listaHtml(filas,cabezas=campos,color='#fff',fondo="#FFF", tfuente=11,opc="101",css="th{color:#FFF} .celda{margin:10px;padding:5px;}",anchos=anchos)) tabla.setPos(int(self.cfg.get("productos", "x")),int(self.cfg.get("productos", "y"))) tabla.setTextWidth(int(self.cfg.get("productos", "ancho"))) cantidad=self.escena.addText("",pfont) cantidad.setHtml("<center>%s</center>"%nletra(total)) cantidad.setPos(int(self.cfg.get("nletra", "x")),int(self.cfg.get("nletra", "y"))) cantidad.setTextWidth(int(self.cfg.get("nletra", "ancho"))) totales=self.escena.addText("",tfont) totales.setHtml("<p ALIGN=right>%.2f</p><p ALIGN=right>%.2f</p><p ALIGN=right>%.2f</p>"%(float(subtotal),float(iva),float(total))) totales.setPos(int(self.cfg.get("totales", "x")),int(self.cfg.get("totales", "y"))) totales.setTextWidth(int(self.cfg.get("totales", "ancho"))) #self.curser.execute("SELECT cantidad, `descripcion`,precio,total from productos,vendidos where ref=producto and venta="+str(self.num)+" group by ref") self.gvDocumento.setScene(self.escena) else: print "Error al cargar plantilla" def alinear(self,item): formato=QTextBlockFormat() formato.setAlignment(Qt.AlignRight) cursor = item.textCursor() cursor.select(QTextCursor.Document) cursor.mergeBlockFormat(formato) cursor.clearSelection() item.setTextCursor(cursor) def cargarPlantilla(self): self.cfg = Cp.ConfigParser() if self.cfg.read([os.path.join(home,"formas","factura.cfg")]): if self.cfg.has_option("documento", "version"): return True else: return False def br(self,texto): offset=1 font=texto.font() pos=texto.pos() return QPointF(pos.x(),float(pos.y())+float(font.pointSize())+offset) def imprimir(self): printer=QPrinter(QPrinter.HighResolution) printer.setPaperSize(QPrinter.Letter) printer.setOutputFormat(QPrinter.PdfFormat) ruta=os.path.join(self.parent.cfg.get("factura", "ruta"),'Factura-'+str(self.num)+'.pdf') printer.setOutputFileName(ruta) prev=QPrintDialog(printer,self.padre) if prev.exec_()==QDialog.Accepted: paint=QPainter() paint.begin(printer) self.escena.render(paint) paint.end() print "Imprimiendo..." if sys.platform == 'linux2': os.system("gnome-open '%s' "%ruta) elif sys.platform == 'win32': os.system("start '%s'"%ruta)
class MainMayaWindow (QObject): ''' Base QObject for the JADE Maya scripted plugin. Notice the difference with the MainMWindow. This class is subclassing QObject while the Standalone one subclasses QWidget. This class handles the Maya way to deal with the contextual pop-up menu. Additionally, this class shares some of the responsibilities with graph.py. ''' def __init__ (self, graph, parent=None): '''constructor @param graph the model @param parent a parent QObject, or None for root window. ''' super (MainMayaWindow, self).__init__(parent) QObject.__init__(self) # initiation indispensable for sending and receiving signals! # define scene and constrain its workspace self.scene = QGraphicsScene () self.scene.setSceneRect (QRectF (-1000, -1000, 2000, 2000)) self.graph_model = graph self.helper = utility.Helper (self, self.scene, self.graph_model) self.graph_view = grv.GraphView (self.graph_model, self.helper) self.helper.setGraphView (self.graph_view) # wirings self.comm = self.graph_model.getComm () self.connect (self.comm, SIGNAL ('deleteNode_MSignal(int)'), self.graph_view.removeTag) self.connect (self.comm, SIGNAL ('addLink_MSignal(int,int)'), self.graph_view.addWire) self.connect (self.comm, SIGNAL ('deleteLink_MSignal(int,int)'), self.graph_view.checkIfEmpty) self.connect (self.comm, SIGNAL ('addNode_MSignal(int, float, float)'), self.graph_view.addTag) self.scene.addItem (self.helper.getHarpoon ()) self.hovered_tag_id = None # register a new command that takes care of deleting selected items and bind it to the key 'd'. cmds.nameCommand ('delSelection', ann='deleteSelectedItems', c='python (\"ClientMaya.ui.graph_view.removeSelectedItems ()\");') cmds.hotkey (k='d', name='delSelection') def setupUi (self, MainWindow): '''sets up the Maya UI. @param MainWindow ''' MainWindow.setObjectName ('MainWindow') MainWindow.resize (800, 1396) sizePolicy = QSizePolicy (QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch (0) sizePolicy.setVerticalStretch (0) sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth()) MainWindow.setSizePolicy(sizePolicy) font = QFont () font.setPointSize (11) MainWindow.setFont (font) MainWindow.setWindowTitle (QApplication.translate("MainWindow", "Location Tool", None, QApplication.UnicodeUTF8)) MainWindow.setTabShape (QTabWidget.Rounded) MainWindow.setDockOptions (QMainWindow.AllowTabbedDocks|QMainWindow.AnimatedDocks) self.scrollAreaWidgetContents_3 = QWidget (MainWindow) self.scrollAreaWidgetContents_3.setGeometry (QRect(10, 10, 900, 940)) self.scrollAreaWidgetContents_3.setObjectName ('scrollAreaWidgetContents_3') self._view = View0.View ("JADEview", self.graph_view, self.scene, self.scrollAreaWidgetContents_3) self._view.setObjectName ('JADEview') # real ui name self._view.graphicsView.setObjectName ('JADEInnerView') self.connect (self.scene, SIGNAL("selectionChanged()"), self._view.selectionChanged) self._view.wireViewItemsUp () self._view.getGraphicsView().setScene (self.scene) self._view.setToolboxCSSColorScheme ('background-color: rgb(68,68,68);color: rgb(200,200,200)') # this needs to be done since the toolbox's background didn't have a uniform colour otherwise. #self._view.setGraphicsViewCSSBackground () # the CSS background doesn't seem to work in Maya as there seems to be a problem with cleaning QGraphicsLineItems when they move, that doesn't happen when there's no CSS applied to the background. self.graphicsView = self._view.getGraphicsView () self.node_coords = QPoint (0,0) layout = QHBoxLayout (self.scrollAreaWidgetContents_3) layout.setContentsMargins (QMargins(0,0,0,0)); layout.addWidget (self._view) QMetaObject.connectSlotsByName (MainWindow) """ cmds.control('JADEInnerView', edit=True, ebg=True, bgc=[.5,.5,.9]) print cmds.control('JADEInnerView', query=True, p=True) """ # wiring the Maya Contextual pop-up Menus - yes, in Maya we've split the pop-up menu definition in three pop-up menus although only one will be present at any time. self.menu = cmds.popupMenu ('JADEmenu', parent='JADEInnerView', button=3, pmc = 'ClientMaya.ui.ctxMenu()', aob=True) self.menuAddOuts = cmds.popupMenu ('JADEmenuAddOuts', parent='JADEInnerView', button=3, pmc = 'ClientMaya.ui.ctxMenuAddOuts()', aob=True, alt=True) self.menuAddIns = cmds.popupMenu ('JADEmenuAddIns', parent='JADEInnerView', button=3, pmc = 'ClientMaya.ui.ctxMenuAddIns()', aob=True, ctl=True) # this class property is used to keep track of the mouse position. self._mouse = QCursor # self._view's zoom slider (we need this to correct the bias added to sort the mouse position when the zoom changes - ONLY in Maya) self._zoom_slider = self._view.getZoomSlider() # - - - context menus methods - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def ctxMenu (self): '''this method invokes the general Maya pop-up menu. ''' self.hovered_tag_id = self.comm.getHoveredItemId() cmds.popupMenu ('JADEmenu', edit=True, dai=True) # clear all the menu items out. if self.hovered_tag_id==None: # ctx menu to establish what node is going to be retrieved tmp_ls = [] [tmp_ls.append(key) for key in self.graph_model.getNodesDecription()] self.prepareGeneralCtxMenu (tmp_ls) def prepareGeneralCtxMenu (self, list0): '''populates the self.menu dynamically with available node infos. @param list0 list of menu items ''' self.node_coords = self.graphicsView.mapToScene (self._mouse.pos()) # populate the QMenu dynamically and pass the menu string name to the receiver for i in sorted (list0): cmds.menuItem (parent=self.menu, label=str(i), c='ClientMaya.ui.addTag ("'+str(i)+'")') def addTag (self, name0): '''adds a Tag0 instance by name. the constants added to the are needed to make the tag pop up near the mouse pointer. @param name0 string ''' if self._view.getCurrentClusterIndex () != 0: # the piece-wise linear interpolation below is a workaround only present in the Maya JADE mapping tool since # the self.graphicsView.mapToScene() doesn't seem to work as the standalone's one. if self._zoom_slider.value() > 199 and self._zoom_slider.value() < 241: x_bias = -22.5*(self._zoom_slider.value()-200) + 2100 y_bias = -3.75*(self._zoom_slider.value()-200) + 400 elif self._zoom_slider.value() > 240 and self._zoom_slider.value() < 281: x_bias = -12.5*(self._zoom_slider.value()-240) + 1200 y_bias = -2.5* (self._zoom_slider.value()-240) + 250 new_node = self.graph_model.addNode (name0, self.node_coords.x() - x_bias, self.node_coords.y() - y_bias) self._view.updateCurrentClusterNodeList (new_node) self._view.setMessageBarText ('') else: self._view.setMessageBarText ('** Choose or create a cluster first. Node not created.') def ctxMenuAddOuts (self): '''this method invokes the Maya add-outs pop-up menu. ''' self.hovered_tag_id = self.comm.getHoveredItemId() cmds.popupMenu ('JADEmenuAddOuts', edit=True, dai=True) # clear all the menu items out. if self.hovered_tag_id!=None: right_list = self.graph_model.getOutsTypesLeft (self.hovered_tag_id) if len(right_list)!=0: self.prepareNodeCtxMenuOnAddingOuts (right_list) def ctxMenuAddIns (self): '''this method invokes the Maya add-ins pop-up menu. ''' self.hovered_tag_id = self.comm.getHoveredItemId() cmds.popupMenu ('JADEmenuAddIns', edit=True, dai=True) # clear all the menu items out. if self.hovered_tag_id!=None: left_list = self.graph_model.getInsTypesLeft (self.hovered_tag_id) if len(left_list)!=0: self.prepareNodeCtxMenuOnAddingIns (left_list) def prepareNodeCtxMenuOnAddingOuts (self, list0): '''populates the self.menuAddOuts dynamically with available node infos. @param list0 list of menu items ''' for i in sorted(list0): cmds.menuItem (parent=self.menuAddOuts, label=str(i), c='ClientMaya.ui.addOutSocketAction ("'+str(i)+'")') self.helper.setMenu (self.menuAddOuts) def prepareNodeCtxMenuOnAddingIns (self, list0): '''populates the self.menuAddIns dynamically with available node infos. @param list0 list of menu items ''' for i in sorted (list0): cmds.menuItem (parent=self.menuAddIns, label=str(i), c='ClientMaya.ui.addInSocketAction ("'+str(i)+'")') self.helper.setMenu (self.menuAddIns) def addOutSocketAction (self, value): '''adds an out-socket name based on the pressed key modifier. @param value ''' self.graph_view.getTag (self.hovered_tag_id) # retrieve the tag the ctx menu was open above. # the event released by adding an InSocket signal will trigger the Tag0's method appendOutHook as a result. self.graph_model.addOutSocket (self.hovered_tag_id, value) def addInSocketAction (self, value): '''adds an in-socket name based on the pressed key modifier. @param value ''' self.graph_view.getTag (self.hovered_tag_id) # retrieve the tag the ctx menu was open above. # the event released by adding an InSocket signal will trigger the Tag0's method appendInHook() as a result. self.graph_model.addInSocket (self.hovered_tag_id, value)
class FlowUIWidget( QWidget ): " The widget which goes along with the text editor " def __init__( self, editor, parent ): QWidget.__init__( self, parent ) # It is always not visible at the beginning because there is no # editor content at the start self.setVisible( False ) self.__editor = editor self.__parentWidget = parent self.__connected = False self.__needPathUpdate = False self.cflowSettings = getDefaultCflowSettings( self ) hLayout = QHBoxLayout() hLayout.setContentsMargins( 0, 0, 0, 0 ) hLayout.setSpacing( 0 ) vLayout = QVBoxLayout() vLayout.setContentsMargins( 0, 0, 0, 0 ) vLayout.setSpacing( 0 ) # Make pylint happy self.__toolbar = None self.__navBar = None self.__cf = None # Create the update timer self.__updateTimer = QTimer( self ) self.__updateTimer.setSingleShot( True ) self.__updateTimer.timeout.connect( self.process ) vLayout.addWidget( self.__createNavigationBar() ) vLayout.addWidget( self.__createGraphicsView() ) hLayout.addLayout( vLayout ) hLayout.addWidget( self.__createToolbar() ) self.setLayout( hLayout ) self.updateSettings() # Connect to the change file type signal mainWindow = GlobalData().mainWindow editorsManager = mainWindow.editorsManagerWidget.editorsManager self.connect( editorsManager, SIGNAL( 'fileTypeChanged' ), self.__onFileTypeChanged ) return def __createToolbar( self ): " Creates the toolbar " self.__toolbar = QToolBar( self ) self.__toolbar.setOrientation( Qt.Vertical ) self.__toolbar.setMovable( False ) self.__toolbar.setAllowedAreas( Qt.RightToolBarArea ) self.__toolbar.setIconSize( QSize( 16, 16 ) ) self.__toolbar.setFixedWidth( 28 ) self.__toolbar.setContentsMargins( 0, 0, 0, 0 ) return self.__toolbar def __createNavigationBar( self ): " Creates the navigation bar " self.__navBar = ControlFlowNavigationBar( self ) return self.__navBar def __createGraphicsView( self ): """ Creates the graphics view """ self.scene = QGraphicsScene( self ) self.view = CFGraphicsView( self ) self.view.setScene( self.scene ) self.view.zoomTo( Settings().flowScale ) return self.view def process( self ): """ Parses the content and displays the results """ if not self.__connected: self.__connectEditorSignals() content = self.__editor.text() self.__cf = getControlFlowFromMemory( content ) if len( self.__cf.errors ) != 0: self.__navBar.updateInfoIcon( self.__navBar.STATE_BROKEN_UTD ) return self.__navBar.updateInfoIcon( self.__navBar.STATE_OK_UTD ) # if len( self.__cf.warnings ) != 0: # self.logMessage( "Parser warnings: " ) # for warn in self.__cf.warnings: # print str( warn[0] ) + ": " + warn[1] self.scene.clear() try: # Top level canvas has no adress and no parent canvas canvas = VirtualCanvas( self.cflowSettings, None, None, None ) canvas.layout( self.__cf ) canvas.setEditor( self.__editor ) width, height = canvas.render() self.scene.setSceneRect( 0, 0, width, height ) canvas.draw( self.scene, 0, 0 ) except Exception, exc: print "Exception:\n" + str( exc ) return
def paintBoundaries(tgslicesFile, zSlice, d, boundaryData, mask, filename, swapCoordinates=False, colortable=None, penWidth=4.0): print "* making boundary img '%s'" % filename #b = BoundariesLayerPy(tgslicesFile=tgslicesFile, normalAxis=2, data2scene=QTransform(), swapCoordinates=True) b = BoundariesLayer(None, 2, QTransform(), True) n = b.normalAxis() axis = None if swapCoordinates: if n == 0: axis = "z" elif n == 1: axis = "y" else: axis = "x" else: if n == 0: axis = "x" elif n == 1: axis = "y" else: axis = "z" f = h5py.File(tgslicesFile, 'r') group = "%s/%d" % (axis, zSlice) serializedBoundaries = f[group].value f.close() assert d.ndim == 2 scene = QGraphicsScene() b.setSliceNumber( zSlice ) b.setBoundaries(serializedBoundaries) b.setColormap("tyr") assert boundaryData.dtype == numpy.float32 assert mask.dtype == numpy.float32 b.setBoundaryData(boundaryData, boundaryData.size, boundaryData) b.setBoundaryMask(mask, mask.size) if colortable is not None: b.setColormap(colortable) print "setting pen width to be %f" % penWidth b.setPenWidth(float(penWidth)) print "...done" mag = 4 shape = d.shape dBig = vigra.sampling.resizeImageNoInterpolation(d.astype(numpy.float32), (mag*shape[0], mag*shape[1])) #dBig = dBig.swapaxes(0,1) qimg = qimage2ndarray.gray2qimage(dBig) #qimg = qimg.mirrored(True, False) imgItm = QGraphicsPixmapItem(QPixmap(qimg)) imgItm.setScale(1.0/mag) scene.addItem(imgItm) sourceRect = QRectF(0,0,shape[1], shape[0]) targetRect = QRectF(0,0,mag*shape[1], mag*shape[0]) scene.setSceneRect(sourceRect) scene.addItem(b) img = QImage(targetRect.width(), targetRect.height(), QImage.Format_ARGB32); painter = QPainter(img); painter.setRenderHint(QPainter.Antialiasing); scene.render(painter, targetRect, sourceRect ); img.save(filename) painter.end() #print "img has size ", img.width(), img.height() img = None painter = None scene = None
class ClassDiagram(QWidget, itab_item.ITabItem): def __init__(self, actions, parent=None): QWidget.__init__(self, parent) itab_item.ITabItem.__init__(self) self.actions = actions self.graphicView = QGraphicsView(self) self.scene = QGraphicsScene() self.graphicView.setScene(self.scene) self.graphicView.setViewportUpdateMode( QGraphicsView.BoundingRectViewportUpdate) vLayout = QVBoxLayout(self) self.setLayout(vLayout) vLayout.addWidget(self.graphicView) self.scene.setItemIndexMethod(QGraphicsScene.NoIndex) self.scene.setSceneRect(-200, -200, 400, 400) self.graphicView.setMinimumSize(400, 400) actualProject = self.actions.ide.explorer.get_actual_project() arrClasses = self.actions._locator.get_classes_from_project( actualProject) #FIXME:dirty need to fix self.mX = -400 self.mY = -320 self.hightestY = self.mY filesList = [] for elem in arrClasses: #loking for paths filesList.append(elem[2]) for path in set(filesList): self.create_class(path) def create_class(self, path): content = file_manager.read_file_content(path) items = introspection.obtain_symbols(content) mYPadding = 10 mXPadding = 10 for classname, classdetail in list(items["classes"].items()): cl = ClassModel(self.graphicView, self.scene) cl.set_class_name(classname) self.fill_clases(cl, classdetail[1]) self.scene.addItem(cl) cl.setPos(self.mX, self.mY) self.mX += cl._get_width() + mXPadding if self.hightestY < self.mY + cl.get_height(): self.hightestY = self.mY + cl.get_height() if self.mX > 2000: self.mX = -400 self.mY += self.hightestY + mYPadding def fill_clases(self, classComponent, classContent): funct = classContent['functions'] classComponent.set_functions_list(funct) attr = classContent['attributes'] classComponent.set_attributes_list(attr) def scale_view(self, scaleFactor): factor = self.graphicView.transform().scale( scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width() if factor > 0.05 and factor < 15: self.graphicView.scale(scaleFactor, scaleFactor) def keyPressEvent(self, event): taskList = { Qt.Key_Plus: lambda: self.scaleView(1.2), Qt.Key_Minus: lambda: self.scaleView(1 / 1.2) } if (event.key() in taskList): taskList[event.key()]() else: QWidget.keyPressEvent(self, event)
class MainForm(QDialog): def __init__(self, parent=None): super(MainForm, self).__init__(parent) self.Running = False self.scene = QGraphicsScene(self) self.scene.setSceneRect(0, 0, SCENESIZEX, SCENESIZEY) self.view = QGraphicsView() self.view.setRenderHint(QPainter.Antialiasing) self.view.setScene(self.scene) self.view.setFocusPolicy(Qt.NoFocus) #self.zoomSlider = QSlider(Qt.Horizontal) #self.zoomSlider.setRange(5, 200) #self.zoomSlider.setValue(100) self.pauseButton = QPushButton("Pa&use") self.quitButton = QPushButton("&Quit") layout = QVBoxLayout() layout.addWidget(self.view) #layout.addWidget(self.zoomSlider) layout.addWidget(self.pauseButton) layout.addWidget(self.quitButton) self.setLayout(layout) #self.connect(self.zoomSlider, SIGNAL("valueChanged(int))"), # self.zoom) self.connect(self.pauseButton, SIGNAL("clicked()"), self.pauseOrResume) self.connect(self.quitButton, SIGNAL("clicked()"), self.accept) self.readNodes() self.zoom(1.0) self.populate() #self.startTimer(INTERVAL) self.setWindowTitle("TdPaleo") def pauseOrResume(self): self.Running = not self.Running self.pauseButton.setText("Pa&use" if self.Running else "Res&ume") items = self.scene.items() for item in items: item.setRunning() def zoom(self, value): factor = 1 / 1.5 matrix = self.view.matrix() matrix.reset() matrix.scale(factor, factor) self.view.setMatrix(matrix) def readNodes(self): file = open("tdp_geometry.dat") file.readline() while True: line = file.readline() if not line: break param = line.split(" ") if (line != "\n"): n = node() n.x = float(param[0]) n.y = 956 - float(param[1]) n.angle = float(param[2]) n.d = int(param[3]) n.type = int(param[4]) nodes.append(n) def populate(self): color = QColor(0, 150, 0) head = TdPCavallo(color, nodes[0].angle, QPointF(nodes[0].x, nodes[0].y)) #FIXME AGGIUNGERE POI IL FANTINO AL CAVALLO #segment = Segment(color, offset, head) self.scene.addItem(head) #Running = False def timerEvent(self, event): if not self.Running: return
class NostraIllustCheckDlg(QtGui.QDialog, FORM_CLASS): def __init__(self, theCanvas, theLayer, selFeatureIds, parent=None): super(NostraIllustCheckDlg, self).__init__(parent) self.setupUi(self) self.mTheCanvas = theCanvas self.mTheLayer = theLayer self.mSelFeatureIds = selFeatureIds self.mAllFeatureIds = [] self.highlightList = [] uri = QgsDataSourceURI(self.mTheLayer.source()) self.conn = psycopg2.connect('''host='%s' dbname='%s' user='******' password='******' ''' %\ (uri.host(), uri.database(), uri.username(), uri.password())) self.pg = self.conn.cursor() # members shown in graphic view. self.mScene = QGraphicsScene() self.graphicsViewShowImage.setScene(self.mScene) self.mPixmapList = [] featureIter = self.mTheLayer.getFeatures(QgsFeatureRequest().setFlags( QgsFeatureRequest.NoGeometry)) inti = 0 theFeature = QgsFeature() while (featureIter.nextFeature(theFeature)): inti += 1 self.mAllFeatureIds.append(theFeature.id()) self.spinBoxFeatureIndex.setValue(1) self.spinBoxFeatureIndex.setMinimum(1) self.spinBoxFeatureIndex.setMaximum(inti) errMsg = [''] self.initComboBoxOutlinkid() self.selectFeatureById(errMsg, self.mSelFeatureIds[0], bZoomToSelected=False) self.comboBoxOutlinkid.setFocus() self.pushButtonPrev.clicked.connect(self.onPushButtonPrev) self.pushButtonNext.clicked.connect(self.onPushButtonNext) self.connect(self.comboBoxOutlinkid, QtCore.SIGNAL('activated(QString)'), self.comboBoxOutlinkidChanged) def resizeEvent(self, event): self.showImageInGraphicsView() return def disableAllControls(self): self.pushButtonPrev.setEnabled(False) self.pushButtonPrev.setEnabled(False) self.comboBoxOutlinkid.setEnabled(False) self.textEditFeatureInfo.setEnabled(False) return def initComboBoxOutlinkid(self): while (self.comboBoxOutlinkid.count() > 0): self.comboBoxOutlinkid.removeItem(0) for oneFeatureId in self.mSelFeatureIds: featureIter = self.mTheLayer.getFeatures( QgsFeatureRequest(oneFeatureId).setFlags( QgsFeatureRequest.NoGeometry)) theFeature = QgsFeature() if featureIter.nextFeature(theFeature) == False: return if self.mIsMyFeature(theFeature): strTemp = "%.0f, %.0f" % (theFeature.attribute('arc1'), theFeature.attribute('arc2')) self.comboBoxOutlinkid.addItem(strTemp) def showFeatureDetail(self, errMsg, theFeature): strFeatureInfo = self.getFeatureInfoString(theFeature) self.textEditFeatureInfo.setText(strFeatureInfo) if self.mIsMyFeature(theFeature) == False: return errMsg = [''] day_pic = theFeature.attribute('day_pic') arrowimg = theFeature.attribute('arrowimg') basePath = r"\\tangpinghui\20151010_nostra_junctionview\output_jpg_and_png" day_pic_path = os.path.join(basePath, day_pic + ".psd\Main_Day.jpg") arrowimg_path = '' tempPath = os.path.join(basePath, day_pic + ".psd") for curDir, subDirs, fileNames in os.walk(tempPath): for oneFile in fileNames: if oneFile.find(arrowimg) != -1 and oneFile.find('_en') != -1: arrowimg_path = os.path.join(curDir, oneFile) self.mPixmapList = [] patternPixmap = QPixmap() patternPixmap.load(day_pic_path) self.mPixmapList.append(patternPixmap) arrowPixmap = QPixmap() arrowPixmap.load(arrowimg_path) self.mPixmapList.append(arrowPixmap) self.showImageInGraphicsView() return def showImageInGraphicsView(self): # remove all items in member QGraphicsScene. for oneItem in self.mScene.items(): self.mScene.removeItem(oneItem) for onePixmap in self.mPixmapList: self.mScene.addPixmap( self.getPixMapSizedByWidgt(onePixmap, self.graphicsViewShowImage)) self.mScene.setSceneRect(0, 0, self.graphicsViewShowImage.width() - 5, self.graphicsViewShowImage.height() - 5) return def getFeatureInfoString(self, theFeature): fieldList = theFeature.fields() attrList = theFeature.attributes() strFeatureInfo = "field count: %d\n" % len(fieldList) for oneField, oneAttr in zip(fieldList, attrList): if isinstance(oneAttr, float): strFeatureInfo += "%s: %.0f\n" % (oneField.name(), oneAttr) else: strFeatureInfo += "%s: %s\n" % (oneField.name(), oneAttr) return strFeatureInfo def comboBoxOutlinkidChanged(self, txt): errMsg = [''] inti = self.comboBoxOutlinkid.currentIndex() self.selectFeatureById(errMsg, self.mSelFeatureIds[inti], bZoomToSelected=False) if errMsg[0] <> '': QMessageBox.information(self, "Nostra Illust Check", """error:\n%s""" % errMsg[0]) return return def onPushButtonPrev(self): self.spinBoxFeatureIndex.setValue(self.spinBoxFeatureIndex.value() - 1) prevFeatureId = self.mAllFeatureIds[self.spinBoxFeatureIndex.value() - 1] errMsg = [''] self.selectFeatureById(errMsg, prevFeatureId) if errMsg[0] <> '': QMessageBox.information(self, "Nostra Illust Check", """error:\n%s""" % errMsg[0]) return return def onPushButtonNext(self): self.spinBoxFeatureIndex.setValue(self.spinBoxFeatureIndex.value() + 1) nextFeatureId = self.mAllFeatureIds[self.spinBoxFeatureIndex.value() - 1] errMsg = [''] self.selectFeatureById(errMsg, nextFeatureId) if errMsg[0] <> '': QMessageBox.information(self, "Nostra Illust Check", """error:\n%s""" % errMsg[0]) return return def selectFeatureById(self, errMsg, featureId, bZoomToSelected=True): self.mTheLayer.removeSelection() self.mTheLayer.select(featureId) theFeature = self.mTheLayer.selectedFeatures()[0] self.showFeatureDetail(errMsg, theFeature) if errMsg[0] <> '': return if bZoomToSelected == True: center = self.mTheCanvas.panToSelected(self.mTheLayer) self.mTheCanvas.refresh() self.clearHighlight() arc1 = "%.0f" % theFeature.attribute('arc1') sqlcmd = """ SET bytea_output TO escape; select st_asbinary(the_geom) from temp_topo_link where routeid=%s """ % arc1 self.pg.execute(sqlcmd) rows = self.pg.fetchall() for row in rows: qgsGeometry = QgsGeometry() qgsGeometry.fromWkb(str(row[0])) self.highlightByGeometry(qgsGeometry, QColor(249, 27, 15, 168)) arc2 = "%.0f" % theFeature.attribute('arc2') sqlcmd = """ SET bytea_output TO escape; select st_asbinary(the_geom) from temp_topo_link where routeid=%s """ % arc2 self.pg.execute(sqlcmd) rows = self.pg.fetchall() for row in rows: qgsGeometry = QgsGeometry() qgsGeometry.fromWkb(str(row[0])) self.highlightByGeometry(qgsGeometry, QColor(22, 151, 0, 168)) new_arc1 = "%.0f" % theFeature.attribute('new_arc1') if new_arc1 is not None and new_arc1 <> arc1: sqlcmd = """ SET bytea_output TO escape; select st_asbinary(the_geom) from temp_topo_link where routeid=%s """ % new_arc1 self.pg.execute(sqlcmd) rows = self.pg.fetchall() for row in rows: qgsGeometry = QgsGeometry() qgsGeometry.fromWkb(str(row[0])) self.highlightByGeometry(qgsGeometry, QColor(253, 158, 153, 128)) new_arc2 = "%.0f" % theFeature.attribute('new_arc2') if new_arc2 is not None and new_arc2 <> arc2: sqlcmd = """ SET bytea_output TO escape; select st_asbinary(the_geom) from temp_topo_link where routeid=%s """ % new_arc2 self.pg.execute(sqlcmd) rows = self.pg.fetchall() for row in rows: qgsGeometry = QgsGeometry() qgsGeometry.fromWkb(str(row[0])) self.highlightByGeometry(qgsGeometry, QColor(147, 255, 155, 128)) return def getPixMapSizedByWidgt(self, pixmap, theWidgt): pixmapWidth = pixmap.width() pixmapHeight = pixmap.height() gpViewWidth = theWidgt.width() gpViewHeight = theWidgt.height() destWidth = 0 destHeight = 0 if pixmapWidth > gpViewWidth - 5: destWidth = gpViewWidth - 5 else: destWidth = pixmapWidth if pixmapHeight > gpViewHeight - 5: destHeight = gpViewHeight - 5 else: destHeight = pixmapHeight return pixmap.scaled(destWidth, destHeight, QtCore.Qt.IgnoreAspectRatio, QtCore.Qt.SmoothTransformation) def mIsMyFeature(self, theFeature): return NostraIllustCheckDlg.isMyFeature(theFeature) @staticmethod def isMyFeature(theFeature): try: gid = theFeature.attribute('gid') arc1 = theFeature.attribute('arc1') arc2 = theFeature.attribute('arc2') day_pic = theFeature.attribute('day_pic') night_pic = theFeature.attribute('night_pic') arrowimg = theFeature.attribute('arrowimg') lon = theFeature.attribute('lon') lat = theFeature.attribute('lat') new_arc1 = theFeature.attribute('new_arc1') new_arc2 = theFeature.attribute('new_arc2') except KeyError, kErr: return False except Exception, ex: return False
class OWQualityControl(widget.OWWidget): name = "Quality Control" description = "Experiment quality control" icon = "../widgets/icons/QualityControl.svg" priority = 5000 inputs = [("Experiment Data", Orange.data.Table, "set_data")] outputs = [] DISTANCE_FUNCTIONS = [("Distance from Pearson correlation", dist_pcorr), ("Euclidean distance", dist_eucl), ("Distance from Spearman correlation", dist_spearman) ] settingsHandler = SetContextHandler() split_by_labels = settings.ContextSetting({}) sort_by_labels = settings.ContextSetting({}) selected_distance_index = settings.Setting(0) def __init__(self, parent=None): super().__init__(parent) ## Attributes self.data = None self.distances = None self.groups = None self.unique_pos = None self.base_group_index = 0 ## GUI box = gui.widgetBox(self.controlArea, "Info") self.info_box = gui.widgetLabel(box, "\n") ## Separate By box box = gui.widgetBox(self.controlArea, "Separate By") self.split_by_model = itemmodels.PyListModel(parent=self) self.split_by_view = QListView() self.split_by_view.setSelectionMode(QListView.ExtendedSelection) self.split_by_view.setModel(self.split_by_model) box.layout().addWidget(self.split_by_view) self.split_by_view.selectionModel().selectionChanged.connect( self.on_split_key_changed) ## Sort By box box = gui.widgetBox(self.controlArea, "Sort By") self.sort_by_model = itemmodels.PyListModel(parent=self) self.sort_by_view = QListView() self.sort_by_view.setSelectionMode(QListView.ExtendedSelection) self.sort_by_view.setModel(self.sort_by_model) box.layout().addWidget(self.sort_by_view) self.sort_by_view.selectionModel().selectionChanged.connect( self.on_sort_key_changed) ## Distance box box = gui.widgetBox(self.controlArea, "Distance Measure") gui.comboBox(box, self, "selected_distance_index", items=[name for name, _ in self.DISTANCE_FUNCTIONS], callback=self.on_distance_measure_changed) self.scene = QGraphicsScene() self.scene_view = QGraphicsView(self.scene) self.scene_view.setRenderHints(QPainter.Antialiasing) self.scene_view.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.mainArea.layout().addWidget(self.scene_view) self.scene_view.installEventFilter(self) self._disable_updates = False self._cached_distances = {} self._base_index_hints = {} self.main_widget = None self.resize(800, 600) def clear(self): """Clear the widget state.""" self.data = None self.distances = None self.groups = None self.unique_pos = None with disable_updates(self): self.split_by_model[:] = [] self.sort_by_model[:] = [] self.main_widget = None self.scene.clear() self.info_box.setText("\n") self._cached_distances = {} def set_data(self, data=None): """Set input experiment data.""" self.closeContext() self.clear() self.error(0) self.warning(0) if data is not None: keys = self.get_suitable_keys(data) if not keys: self.error(0, "Data has no suitable feature labels.") data = None self.data = data if data is not None: self.on_new_data() def update_label_candidates(self): """Update the label candidates selection GUI (Group/Sort By views). """ keys = self.get_suitable_keys(self.data) with disable_updates(self): self.split_by_model[:] = keys self.sort_by_model[:] = keys def get_suitable_keys(self, data): """ Return suitable attr label keys from the data where the key has at least two unique values in the data. """ attrs = [attr.attributes.items() for attr in data.domain.attributes] attrs = reduce(operator.iadd, attrs, []) # in case someone put non string values in attributes dict attrs = [(str(key), str(value)) for key, value in attrs] attrs = set(attrs) values = defaultdict(set) for key, value in attrs: values[key].add(value) keys = [key for key in values if len(values[key]) > 1] return keys def selected_split_by_labels(self): """Return the current selected split labels. """ sel_m = self.split_by_view.selectionModel() indices = [r.row() for r in sel_m.selectedRows()] return [self.sort_by_model[i] for i in indices] def selected_sort_by_labels(self): """Return the current selected sort labels """ sel_m = self.sort_by_view.selectionModel() indices = [r.row() for r in sel_m.selectedRows()] return [self.sort_by_model[i] for i in indices] def selected_distance(self): """Return the selected distance function. """ return self.DISTANCE_FUNCTIONS[self.selected_distance_index][1] def selected_base_group_index(self): """Return the selected base group index """ return self.base_group_index def selected_base_indices(self, base_group_index=None): indices = [] for g, ind in self.groups: if base_group_index is None: label = group_label(self.selected_split_by_labels(), g) ind = [i for i in ind if i is not None] i = self._base_index_hints.get(label, ind[0] if ind else None) else: i = ind[base_group_index] indices.append(i) return indices def on_new_data(self): """We have new data and need to recompute all. """ self.closeContext() self.update_label_candidates() self.info_box.setText( "%s genes \n%s experiments" % (len(self.data), len(self.data.domain.attributes))) self.base_group_index = 0 keys = self.get_suitable_keys(self.data) self.openContext(keys) ## Restore saved context settings (split/sort selection) split_by_labels = self.split_by_labels sort_by_labels = self.sort_by_labels def select(model, selection_model, selected_items): """Select items in a Qt item model view """ all_items = list(model) try: indices = [all_items.index(item) for item in selected_items] except: indices = [] for ind in indices: selection_model.select(model.index(ind), QItemSelectionModel.Select) with disable_updates(self): select(self.split_by_view.model(), self.split_by_view.selectionModel(), split_by_labels) select(self.sort_by_view.model(), self.sort_by_view.selectionModel(), sort_by_labels) with widget_disable(self): self.split_and_update() def on_split_key_changed(self, *args): """Split key has changed """ with widget_disable(self): if not self._disable_updates: self.base_group_index = 0 self.split_by_labels = self.selected_split_by_labels() self.split_and_update() def on_sort_key_changed(self, *args): """Sort key has changed """ with widget_disable(self): if not self._disable_updates: self.base_group_index = 0 self.sort_by_labels = self.selected_sort_by_labels() self.split_and_update() def on_distance_measure_changed(self): """Distance measure has changed """ if self.data is not None: with widget_disable(self): self.update_distances() self.replot_experiments() def on_view_resize(self, size): """The view with the quality plot has changed """ if self.main_widget: current = self.main_widget.size() self.main_widget.resize(size.width() - 6, current.height()) self.scene.setSceneRect(self.scene.itemsBoundingRect()) def on_rug_item_clicked(self, item): """An ``item`` in the quality plot has been clicked. """ update = False sort_by_labels = self.selected_sort_by_labels() if sort_by_labels and item.in_group: ## The item is part of the group if item.group_index != self.base_group_index: self.base_group_index = item.group_index update = True else: if sort_by_labels: # If the user clicked on an background item it # invalidates the sorted labels selection with disable_updates(self): self.sort_by_view.selectionModel().clear() update = True index = item.index group = item.group label = group_label(self.selected_split_by_labels(), group) if self._base_index_hints.get(label, 0) != index: self._base_index_hints[label] = index update = True if update: with widget_disable(self): self.split_and_update() def eventFilter(self, obj, event): if obj is self.scene_view and event.type() == QEvent.Resize: self.on_view_resize(event.size()) return super().eventFilter(obj, event) def split_and_update(self): """ Split the data based on the selected sort/split labels and update the quality plot. """ split_labels = self.selected_split_by_labels() sort_labels = self.selected_sort_by_labels() self.warning(0) if not split_labels: self.warning(0, "No separate by label selected.") self.groups, self.unique_pos = \ exp.separate_by(self.data, split_labels, consider=sort_labels, add_empty=True) self.groups = sorted(self.groups.items(), key=lambda t: list(map(float_if_posible, t[0]))) self.unique_pos = sorted( self.unique_pos.items(), key=lambda t: list(map(float_if_posible, t[0]))) if self.groups: if sort_labels: group_base = self.selected_base_group_index() base_indices = self.selected_base_indices(group_base) else: base_indices = self.selected_base_indices() self.update_distances(base_indices) self.replot_experiments() def get_cached_distances(self, measure): if measure not in self._cached_distances: attrs = self.data.domain.attributes mat = numpy.zeros((len(attrs), len(attrs))) self._cached_distances[measure] = \ (mat, set(zip(range(len(attrs)), range(len(attrs))))) return self._cached_distances[measure] def get_cached_distance(self, measure, i, j): matrix, computed = self.get_cached_distances(measure) key = (i, j) if i < j else (j, i) if key in computed: return matrix[i, j] else: return None def get_distance(self, measure, i, j): d = self.get_cached_distance(measure, i, j) if d is None: vec_i = take_columns(self.data, [i]) vec_j = take_columns(self.data, [j]) d = measure(vec_i, vec_j) mat, computed = self.get_cached_distances(measure) mat[i, j] = d key = key = (i, j) if i < j else (j, i) computed.add(key) return d def store_distance(self, measure, i, j, dist): matrix, computed = self.get_cached_distances(measure) key = (i, j) if i < j else (j, i) matrix[j, i] = matrix[i, j] = dist computed.add(key) def update_distances(self, base_indices=()): """Recompute the experiment distances. """ distance = self.selected_distance() if base_indices == (): base_group_index = self.selected_base_group_index() base_indices = [ind[base_group_index] \ for _, ind in self.groups] assert (len(base_indices) == len(self.groups)) base_distances = [] attributes = self.data.domain.attributes pb = gui.ProgressBar(self, len(self.groups) * len(attributes)) for (group, indices), base_index in zip(self.groups, base_indices): # Base column of the group if base_index is not None: base_vec = take_columns(self.data, [base_index]) distances = [] # Compute the distances between base column # and all the rest data columns. for i in range(len(attributes)): if i == base_index: distances.append(0.0) elif self.get_cached_distance(distance, i, base_index) is not None: distances.append( self.get_cached_distance(distance, i, base_index)) else: vec_i = take_columns(self.data, [i]) dist = distance(base_vec, vec_i) self.store_distance(distance, i, base_index, dist) distances.append(dist) pb.advance() base_distances.append(distances) else: base_distances.append(None) pb.finish() self.distances = base_distances def replot_experiments(self): """Replot the whole quality plot. """ self.scene.clear() labels = [] max_dist = numpy.nanmax(list(filter(None, self.distances))) rug_widgets = [] group_pen = QPen(Qt.black) group_pen.setWidth(2) group_pen.setCapStyle(Qt.RoundCap) background_pen = QPen(QColor(0, 0, 250, 150)) background_pen.setWidth(1) background_pen.setCapStyle(Qt.RoundCap) main_widget = QGraphicsWidget() layout = QGraphicsGridLayout() attributes = self.data.domain.attributes if self.data is not None: for (group, indices), dist_vec in zip(self.groups, self.distances): indices_set = set(indices) rug_items = [] if dist_vec is not None: for i, attr in enumerate(attributes): # Is this a within group distance or background in_group = i in indices_set if in_group: rug_item = ClickableRugItem( dist_vec[i] / max_dist, 1.0, self.on_rug_item_clicked) rug_item.setPen(group_pen) tooltip = experiment_description(attr) rug_item.setToolTip(tooltip) rug_item.group_index = indices.index(i) rug_item.setZValue(rug_item.zValue() + 1) else: rug_item = ClickableRugItem( dist_vec[i] / max_dist, 0.85, self.on_rug_item_clicked) rug_item.setPen(background_pen) tooltip = experiment_description(attr) rug_item.setToolTip(tooltip) rug_item.group = group rug_item.index = i rug_item.in_group = in_group rug_items.append(rug_item) rug_widget = RugGraphicsWidget(parent=main_widget) rug_widget.set_rug(rug_items) rug_widgets.append(rug_widget) label = group_label(self.selected_split_by_labels(), group) label_item = QGraphicsSimpleTextItem(label, main_widget) label_item = GraphicsSimpleTextLayoutItem(label_item, parent=layout) label_item.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) labels.append(label_item) for i, (label, rug_w) in enumerate(zip(labels, rug_widgets)): layout.addItem(label, i, 0, Qt.AlignVCenter) layout.addItem(rug_w, i, 1) layout.setRowMaximumHeight(i, 30) main_widget.setLayout(layout) self.scene.addItem(main_widget) self.main_widget = main_widget self.rug_widgets = rug_widgets self.labels = labels self.on_view_resize(self.scene_view.size())