def paintEvent(self, ev): """Called when paint is needed, finds out which page to magnify.""" layout = self.parent().pageLayout() pos = self.geometry().center() page = layout.pageAt(pos) if not page: return pagePos = pos - page.pos() newPage = Page(page, self._scale) if newPage != self._page: if self._page: self._page.magnifier = None self._page = newPage self._page.magnifier = self relx = pagePos.x() / float(page.width()) rely = pagePos.y() / float(page.height()) image = cache.image(self._page) img_rect = QRect(self.rect()) if not image: cache.generate(self._page) image = cache.image(self._page, False) if image: img_rect.setWidth(self.width() * image.width() / self._page.width()) img_rect.setHeight(self.height() * image.height() / self._page.height()) if image: img_rect.moveCenter( QPoint(relx * image.width(), rely * image.height())) QPainter(self).drawImage(self.rect(), image, img_rect)
def paintEvent(self, ev): """Called when paint is needed, finds out which page to magnify.""" layout = self.parent().surface().pageLayout() pos = self.geometry().center() - self.parent().surface().pos() page = layout.pageAt(pos) if not page: return pagePos = pos - page.pos() newPage = Page(page, self._scale) if not newPage.same_page(self._page): if self._page: self._page.magnifier = None self._page = newPage self._page.magnifier = self relx = pagePos.x() / float(page.width()) rely = pagePos.y() / float(page.height()) image = cache.image(self._page) img_rect = QRect(self.rect()) if not image: cache.generate(self._page) image = cache.image(self._page, False) if image: img_rect.setWidth(self.width() * image.width() / self._page.width()) img_rect.setHeight(self.height() * image.height() / self._page.height()) if image: img_rect.moveCenter(QPoint(relx * image.width(), rely * image.height())) p = QPainter(self) p.drawImage(self.rect(), image, img_rect) p.setRenderHint(QPainter.Antialiasing, True) p.setPen(QPen(QColor(192, 192, 192, 128), 6)) p.drawEllipse(self.rect().adjusted(2, 2, -2, -2))
def paintEvent(self, ev): """Called when paint is needed, finds out which page to magnify.""" layout = self.parent().pageLayout() pos = self.geometry().center() page = layout.pageAt(pos) if not page: return pagePos = pos - page.pos() newPage = Page(page, self._scale) if newPage != self._page: if self._page: self._page.magnifier = None self._page = newPage self._page.magnifier = self relx = pagePos.x() / float(page.width()) rely = pagePos.y() / float(page.height()) image = cache.image(self._page) img_rect = QRect(self.rect()) if not image: cache.generate(self._page) image = cache.image(self._page, False) if image: img_rect.setWidth(self.width() * image.width() / self._page.width()) img_rect.setHeight(self.height() * image.height() / self._page.height()) if image: img_rect.moveCenter(QPoint(relx * image.width(), rely * image.height())) QPainter(self).drawImage(self.rect(), image, img_rect)
def calculateLogicalRect(self, physicalRect): gridX = self.parent().width() / 40 gridY = self.parent().height() / 30 logicalRect = QRect() logicalRect.setTop(round(physicalRect.top() / gridY)) logicalRect.setLeft(round(physicalRect.left() / gridX)) logicalRect.setWidth(round(physicalRect.width() / gridX)) logicalRect.setHeight(round(physicalRect.height() / gridY)) return logicalRect
def paint(self, painter, option, index): painter.setFont(option.font) painter.setBrush(QBrush(Qt.black)) if option.state & QStyle.State_Selected: painter.setPen(QPen(Qt.white)) rect = QRect(option.rect) rect.setLeft(rect.left() + 4) rect.setTop(rect.top() + 4) rect.setWidth(rect.width() - 8) rect.setHeight(rect.height() - 8) painter.drawText(rect, Qt.Horizontal | Qt.TextWordWrap, forceString(index.data()))
def paintEvent(self,event): painter = QPainter(self) btnRect = self.geometry() color = QColor(Qt.black) if self.hovered: color = self.color if self.pressed: color = self.color.darker(120) painter.setBrush(QBrush(color)) painter_path = QPainterPath() painter_path.addRoundedRect(1, 1, btnRect.width() - 2, btnRect.height() - 2, 0, 0) if self.hovered: painter.setPen(QPen(color,2)) outline = QPainterPath() outline.addRoundedRect(0, 0, btnRect.width(), btnRect.height(), 0, 0) painter.setOpacity(1) painter.drawPath(outline) painter.setClipPath(painter_path) painter.drawRoundedRect(1, 1, btnRect.width() - 2, btnRect.height() - 2, 0, 0) iconWidth = self.iconSize().width()*3/5 iconHeight = self.iconSize().height()*3/5 iconX = (btnRect.width()-iconWidth)/2 iconY = (btnRect.height()-iconHeight)/2 if self.pressed: iconX += 2 iconY += 2 iconPos = QRect() iconPos.setX(iconX) iconPos.setY(iconY) iconPos.setWidth(iconWidth) iconPos.setHeight(iconHeight) painter.drawPixmap(iconPos, QPixmap(self.icon().pixmap(self.iconSize())))
def __init__(self, parent = None): QDialog.__init__(self, parent) # get primiry monitor resolution qdw = QDesktopWidget() mainScreenSize = qdw.availableGeometry(qdw.primaryScreen()) # get center of the monitor center = mainScreenSize.center() # calculate width, height and x,y positions of the window r_width = round(mainScreenSize.width()/2) r_height = round(mainScreenSize.height()/2) r_x = round(center.x()-r_width/2) r_y = round(center.y()-r_height/2) # set default geometry of the window rect = QRect() rect.setX(r_x) rect.setY(r_y) rect.setWidth(r_width) rect.setHeight(r_height) self.setGeometry(rect)
def calIconTextPos(self,btnSize,iconSize): if self.text().isNull(): iconWidth = iconSize.width()*3/5 iconHeight = iconSize.height()*3/5 else: iconWidth = iconSize.width() iconHeight = iconSize.height() - 50 iconX = (btnSize.width()-iconWidth)/2 iconY = (btnSize.height()-iconHeight)/2 iconPos = QRect() iconPos.setX(iconX) iconPos.setY(iconY) iconPos.setWidth(iconWidth) iconPos.setHeight(iconHeight) textPos = QRect() if not self.text().isNull(): textPos.setX(iconX) textPos.setY(btnSize.height()- 50) textPos.setWidth(iconWidth) textPos.setHeight(50) return (iconPos,textPos)
def calIconTextPos(self, btnSize, iconSize): if self.text().isNull(): iconWidth = iconSize.width() * 3 / 5 iconHeight = iconSize.height() * 3 / 5 else: iconWidth = iconSize.width() iconHeight = iconSize.height() - 50 iconX = (btnSize.width() - iconWidth) / 2 iconY = (btnSize.height() - iconHeight) / 2 iconPos = QRect() iconPos.setX(iconX) iconPos.setY(iconY) iconPos.setWidth(iconWidth) iconPos.setHeight(iconHeight) textPos = QRect() if not self.text().isNull(): textPos.setX(iconX) textPos.setY(btnSize.height() - 50) textPos.setWidth(iconWidth) textPos.setHeight(50) return (iconPos, textPos)
def paint(self, painter, option, index): """ Draws the widget Arguments: painter -- a QPainter option -- a QStyleOptionView index -- a QModelIndex """ # Retrieve the data model = index.model() record = model.data(index) text = record.toString() zoteroItem = zoteroCache[unicode(text)] l = zoteroItem.full_format().split(u"\n") if zoteroItem.fulltext == None: pixmap = self.noPdfPixmap else: pixmap = self.pdfPixmap # Choose the colors self.palette = self.qnotero.ui.listWidgetResults.palette() if option.state & QStyle.State_MouseOver: background = self.palette.Highlight foreground = self.palette.HighlightedText _note = zoteroItem.get_note() if _note != None: self.qnotero.showNoteHint() else: self.qnotero.hideNoteHint() elif option.state & QStyle.State_Selected: background = self.palette.Dark foreground = self.palette.WindowText else: background = self.palette.Base foreground = self.palette.WindowText # Draw the frame _rect = option.rect.adjusted(self._margin, self._margin, \ -2*self._margin, -self._margin) pen = painter.pen() pen.setColor(self.palette.color(background)) painter.setPen(pen) painter.setBrush(self.palette.brush(background)) painter.drawRoundedRect(_rect, self.roundness, self.roundness) font = painter.font pen = painter.pen() pen.setColor(self.palette.color(foreground)) painter.setPen(pen) # Draw icon _rect = QRect(option.rect) _rect.moveBottom(_rect.bottom() + 0.5 * self.dy) _rect.moveLeft(_rect.left() + 0.5 * self.dy) _rect.setHeight(self.pixmapSize) _rect.setWidth(self.pixmapSize) painter.drawPixmap(_rect, pixmap) # Draw the text _rect = option.rect.adjusted(self.pixmapSize+self.dy, 0.5*self.dy, \ -self.dy, 0) f = [self.tagFont, self.italicFont, self.regularFont, \ self.boldFont] l.reverse() while len(l) > 0: s = l.pop() if len(f) > 0: painter.setFont(f.pop()) painter.drawText(_rect, Qt.AlignLeft, s) _rect = _rect.adjusted(0, self.dy, 0, 0)
def paint(self, painter, option, index): self.initStyleOption(option, index) if hasattr(option, "checkState"): if option.checkState == Qt.Unchecked: option.checkState = Qt.PartiallyChecked elif option.checkState == Qt.PartiallyChecked: option.checkState = Qt.Unchecked elif option.checkState == Qt.Checked: option.font = QFont(option.font) option.font.setStrikeOut(True) # ref: qt4-x11-4.6.2/src/gui/styles/qcommonstyle.cpp painter.save() painter.setClipRect(option.rect) # QApplication.style().drawControl( # QStyle.CE_ItemViewItem, option, painter, # getattr(option, "widget", None)) style = QApplication.style() widget = getattr(option, "widget", None) # log.debug("widget: %r style: %r" % (widget, style.metaObject().className())) style.drawPrimitive( QStyle.PE_PanelItemViewItem, option, painter, widget) if option.checkState == Qt.Checked: painter.setOpacity(0.3) text_rect = style.subElementRect( QStyle.SE_ItemViewItemText, option, widget) item_text = option.fontMetrics.elidedText( option.text, option.textElideMode, text_rect.width()) painter.setFont(option.font) style.drawItemText(painter, text_rect, option.displayAlignment, option.palette, True, item_text, QPalette.Text) check_rect = style.subElementRect( QStyle.SE_ItemViewItemCheckIndicator, option, widget) if option.checkState == Qt.PartiallyChecked: brush = option.palette.brush(QPalette.Base) painter.fillRect(check_rect, brush) bullet_rect = QRect(check_rect) if bullet_rect.width() > BULLET_SIZE: bullet_rect.setLeft( bullet_rect.left() + (bullet_rect.width() - BULLET_SIZE) / 2) bullet_rect.setWidth(BULLET_SIZE) if bullet_rect.height() > BULLET_SIZE: bullet_rect.setTop( bullet_rect.top() + (bullet_rect.height() - BULLET_SIZE) / 2) bullet_rect.setHeight(BULLET_SIZE) painter.setPen(QPen(option.palette.color(QPalette.Text))) painter.setBrush(option.palette.brush(QPalette.Text)) painter.drawEllipse(bullet_rect) else: check_opt = QStyleOptionButton() check_opt.rect = check_rect check_opt.state = option.state & ~QStyle.State_HasFocus if option.checkState == Qt.Checked: check_opt.state |= QStyle.State_On else: check_opt.state |= QStyle.State_Off style.drawPrimitive( QStyle.PE_IndicatorItemViewItemCheck, check_opt, painter, widget) painter.restore()
class PlottingThread(QThread): def __init__(self, parent): QThread.__init__(self) self.result = None self.parent = parent self._stopped = False self.mutex = QMutex() self.filePrefix = None self.fileFormat = None self.wallColoring = None self.cellColoring = None self.pointColoring = None self.extraDrawing = [] self.pointSize = None self.pointLineColor = None self.pointLineThickness = None self.ellipsisDraw = None self.overSampling = None self.wallThickness = None self.bgColor = None self.loading = False self._crop = QRect(0,0,1,1) self._pix = None self._end_image_plot = False self._loading_arguments = {} self.retryObject = None def end_step(self): return len(self.result)+1 def stop(self, value = True): self.mutex.lock() self._stopped = value self.mutex.unlock() def stopped(self): self.mutex.lock() val = self._stopped self.mutex.unlock() return val def nextImage(self): QCoreApplication.postEvent(self.parent, NextImageEvent()) def abort(self, reason, **others): e = AbortPlottingEvent(reason) if others: e.others = others QCoreApplication.postEvent(self.parent, e) def finished(self): if self.loading: QCoreApplication.postEvent(self.parent, FinishLoadingEvent()) self.loading = False else: QCoreApplication.postEvent(self.parent, FinishPlottingEvent()) def image_ready(self): QCoreApplication.postEvent(self.parent, ImageReadyPlottingEvent()) def update_nb_images(self, nb): QCoreApplication.postEvent(self.parent, UpdateNbImageEvent(nb)) @property def crop_left(self): return self._crop.left() @crop_left.setter def crop_left(self, value): self._crop.moveLeft(int(value)) @property def crop_top(self): return self._crop.top() @crop_top.setter def crop_top(self, value): self._crop.moveTop(int(value)) @property def crop_width(self): return self._crop.width() @crop_width.setter def crop_width(self, value): self._crop.setWidth(int(value)) @property def crop_height(self): return self._crop.height() @crop_height.setter def crop_height(self, value): self._crop.setHeight(int(value)) def reset_crop(self): self._crop = QRect(QPoint(0,0), self.img_size) @property def crop(self): return QRect(self._crop) @crop.deleter def crop(self): self.reset_crop() @property def end_image_plot(self): ''' If true, plot the growth data on the end image rather than the start image of the growth calculation. ''' return self._end_image_plot @end_image_plot.setter def end_image_plot(self, value): self._end_image_plot = bool(value) @property def pix(self): '''Thread-safe image storage.''' self.mutex.lock() pix = self._pix self.mutex.unlock() return pix @pix.setter def pix(self, value): self.mutex.lock() self._pix = value self.mutex.unlock() def render_valid(self): if self.result is None: log_debug("result is None") return False if self.parent is None: log_debug("parent is None") return False if self.ellipsisDraw is None: log_debug("ellipsisDraw is None") return False if self.cellColoring is None: log_debug("cellColoring is None") return False if self.wallColoring is None: log_debug("wallColoring is None") return False if self.pointColoring is None: log_debug("pointColoring is None") return False if self.pointSize is None: log_debug("pointSize is None") return False if self.pointLineThickness is None: log_debug("pointSize is None") return False if self.pointLineColor is None: log_debug("pointSize is None") return False if self.wallThickness is None: log_debug("wallThickness is None") return False if self.overSampling is None: log_debug("overSampling is None") return False if self.bgColor is None: log_debug("bgColor is None") return False return True def valid(self): if self.filePrefix is None: log_debug("filePrefix is None") return False if not self.filePrefix: log_debug("filePrefix is Empty") return False if self.fileFormat is None: log_debug("fileFormat is None") return False return self.render_valid() def drawImage(self, imageid): cache = image_cache.cache cellColoring = self.cellColoring wallColoring = self.wallColoring pointColoring = self.pointColoring ellipsisDraw = self.ellipsisDraw overSampling = self.overSampling extraDrawing = self.extraDrawing bgColor = self.bgColor.rgb() result = self.result if self.result_type == "Data": data = result img_name = result.images_name[imageid] else: data = result.data img_name = result.images[imageid] #scale = data.images_scale[img_name] min_scale = data.minScale() img = cache.image(data.image_path(img_name)) img_data = data[img_name] size = self._crop.size() pix = QImage(size*overSampling, QImage.Format_ARGB32) pix.fill(bgColor) painter = QPainter() if not painter.begin(pix): self.abort("Cannot create painter on QImage") return None, None, None painter.setRenderHints(QPainter.SmoothPixmapTransform, True) painter.setRenderHints(QPainter.Antialiasing, True) if overSampling > 1: painter.scale(overSampling, overSampling) painter.translate(-self._crop.topLeft()) painter.save() painter.translate(self.translate) log_debug("Translating: %gx%g" % (self.translate.x(), self.translate.y()) ) painter.scale(1/min_scale, 1/min_scale) painter.save() matrix = img_data.matrix() painter.setWorldTransform(matrix, True) painter.drawImage(QPoint(0,0), img) painter.restore() #pt_matrix = QTransform() #pt_matrix.scale(1/min_scale, 1/min_scale) #painter.setTransform(pt_matrix, True) cellColoring.startImage(painter, imageid) wallColoring.startImage(painter, imageid) for ed in extraDrawing: ed.startImage(painter, imageid) if self.result_type == "Growth": cells = result.cells[imageid] walls = result.walls[imageid] else: cells = img_data.cells walls = set() for cid in img_data.cells: pts = [ pt for pt in data.cells[cid] if pt in img_data ] if len(pts) > 1: for i in range(len(pts)): walls.add(data.wallId(pts[i-1], pts[i])) # Now, draw the cells and the ellipsis for cid in cells: painter.setPen(Qt.NoPen) color = cellColoring(imageid, cid) painter.setBrush(color) pts = data.cellAtTime(cid, img_data.index) if pts: pts.append(pts[0]) ppts = [] for p1,p2 in zip(pts[:-1], pts[1:]): ppts.append(img_data[p1]) ppts.extend(img_data.walls[p1,p2]) ppts.append(ppts[0]) poly = QPolygonF(ppts) painter.drawPolygon(poly) # And draw the walls wallThickness = self.wallThickness*min_scale for wid in walls: color = wallColoring(imageid, wid) if color.alpha() > 0: pen = QPen(color) pen.setWidthF(wallThickness) painter.setPen(pen) pts = [img_data[wid[0]]] + img_data.walls[wid[0], wid[1]] + [img_data[wid[1]]] #painter.drawLine(img_data[wid[0]], img_data[wid[1]]) painter.drawPolyline(*pts) # Then, draw the points pointSize = self.pointSize*min_scale pointLineColor = self.pointLineColor pointLineThickness = self.pointLineThickness*min_scale log_debug("pointSize = %g" % pointSize) for pid in img_data: color = pointColoring(imageid, pid) if color.alpha() > 0: pen = QPen(pointLineColor) pen.setWidthF(pointLineThickness) brush = QBrush(color) painter.setPen(pen) painter.setBrush(brush) pos = img_data[pid] rect = QRectF(pos.x()-pointSize, pos.y()-pointSize, 2*pointSize, 2*pointSize) painter.drawEllipse(rect) if ellipsisDraw.plot: for cid in cells: pts = data.cellAtTime(cid, img_data.index) if pts: pts.append(pts[0]) ppts = [] for p1,p2 in zip(pts[:-1], pts[1:]): ppts.append(img_data[p1]) ppts.extend(img_data.walls[p1,p2]) ppts.append(ppts[0]) #poly = QPolygonF(ppts) #painter.drawPolygon(poly) ellipsisDraw(painter, imageid, cid, ppts, min_scale) # At last, draw the extra data for ed in extraDrawing: ed(painter, imageid) tr = painter.worldTransform() painter.restore() pic_w = wallColoring.finalizeImage(painter, imageid, tr, self.crop) pic_c = cellColoring.finalizeImage(painter, imageid, tr, self.crop) for ed in extraDrawing: ed.finalizeImage(painter, imageid, tr, self.crop) painter.end() return pix, pic_w, pic_c def start(self): if self.isRunning(): assert not self.rendering_all, "Cannot run twice the rendering of all images with the same object." return if parameters.instance.use_thread: log_debug("Starting rendering thread.") QThread.start(self) return False else: self.run() return True def render_all(self): self.rendering_all = True return self.start() def render_single(self, img_id, retry=False): if retry: while self.isRunning(): self.wait(10000) elif self.isRunning(): return self.rendering_all = False self.current_image = img_id return self.start() def load(self, filename): self.loading = True self.result = filename return self.start() def run(self): if self.loading: self.run_loader() elif self.rendering_all: self.run_full() else: self.run_single() def run_single(self): img = self.current_image self.cellColoring.init() self.wallColoring.init() self.pointColoring.init() log_debug("Rendering image %d" % img) self.pix, self.pic_w, self.pic_c = self.drawImage(img) if self.pic_w is not None: log_debug("Has wall image") if self.pic_c is not None: log_debug("Has cell image") if self.pix is not None: log_debug("Pix correctly rendered") log_debug("Rendered image %d = %s" % (img, self.pix)) self.image_ready() def reload(self): if self.retryObject is None: return self._loading_arguments.update(self.retryObject.method_args) self.load(self.retryObject.filename) def run_loader(self): filename = self.result try: self.retryObject = None # First, prepare the data by getting the images and computing how big they # should be f = open(filename) first_line = f.readline() f.close() if first_line.startswith("TRKR_VERSION"): result = Result(None) result.load(self.result, **self._loading_arguments) result_type = "Growth" else: result = TrackingData() result.load(self.result, **self._loading_arguments) result_type = "Data" self.result = result self.result_type = result_type if result_type == "Data": data = result images = data.images_name if data.cells: self.has_cells = True self.has_walls = True else: self.has_cells = False self.has_walls = False self.has_points = bool(data.cell_points) else: data = result.data images = result.images self.has_cells = False self.has_walls = False self.has_points = False self.images = images cache = image_cache.cache self.update_nb_images(len(result)) bbox = QRectF() ms = data.minScale() for i in range(len(result)): img_name = images[i] img_data = data[img_name] img = cache.image(data.image_path(img_name)) matrix = QTransform() matrix = img_data.matrix() sc = QTransform() sc.scale(1.0/ms, 1.0/ms) matrix *= sc r = QRectF(img.rect()) rbox = matrix.map(QPolygonF(r)).boundingRect() bbox |= rbox log_debug("Image '%s':\n\tSize = %gx%g\n\tTransformed = %gx%g %+g %+g\n\tGlobal bbox = %gx%g %+g %+g\n" % (img_name, r.width(), r.height(), rbox.width(), rbox.height(), rbox.left(), rbox.top(), bbox.width(), bbox.height(), bbox.left(), bbox.top())) log_debug("Matrix:\n%g\t%g\t%g\n%g\t%g\t%g\n" % (matrix.m11(), matrix.m12(), matrix.dx(), matrix.m21(), matrix.m22(), matrix.dy())) if result_type == "Growth": if result.cells[i]: self.has_cells = True if result.walls[i]: self.has_walls = True self.has_points = bool(result.data.cell_points) self.nextImage() translate = bbox.topLeft() translate *= -1 self.translate = translate size = bbox.size().toSize() self.img_size = size self._crop = QRect(QPoint(0,0), size) self.finished() self._loading_arguments = {} # All done, we don't need that anymore except RetryTrackingDataException as ex: ex.filename = filename self.retryObject = ex self.finished() return except Exception as ex: _, _, exceptionTraceback = sys.exc_info() self.abort(ex, traceback=exceptionTraceback) raise def run_full(self): if not self.valid(): self.abort("Object was not correctly initialized") return self.stop(False) painter = None try: result = self.result self.update_nb_images(len(result)) # if self.result_type == "Data": # data = result # images = result.images_name # else: # data = result.data # images = result.images # cache = image_cache.cache cellColoring = self.cellColoring wallColoring = self.wallColoring pointColoring = self.pointColoring file_format = self.fileFormat file_pattern = "%s%%0%dd.%s" % (self.filePrefix, len(str(len(result))), file_format) wall_file_pattern = "%s%%0%dd_wall.%s" % (self.filePrefix, len(str(len(result))), file_format) cell_file_pattern = "%s%%0%dd_cell.%s" % (self.filePrefix, len(str(len(result))), file_format) cellColoring.init() wallColoring.init() pointColoring.init() self.nextImage() for i in range(len(result)): if self.stopped(): self.abort("User interruption") return pix, pic_w, pic_c = self.drawImage(i) pix.save(file_pattern % (i+1), file_format) if pic_w is not None: self.saveExtra(pic_w, wall_file_pattern % (i+1), file_format) if pic_c is not None: self.saveExtra(pic_c, cell_file_pattern % (i+1), file_format) self.nextImage() self.finished() except Exception as ex: if painter is not None: painter.end() _, _, exceptionTraceback = sys.exc_info() self.abort(ex, traceback=exceptionTraceback) raise def saveExtra(self, picture, file_name, file_format): rect = picture.boundingRect() pix = QImage(rect.size(), QImage.Format_ARGB32) pix.fill(QColor(0, 0, 0, 0).rgba()) paint = QPainter() paint.begin(pix) paint.drawPicture(rect.topLeft()*-1, picture) paint.end() pix.save(file_name, file_format)
def paint(self, painter, option, index): """ Draws the widget Arguments: painter -- a QPainter option -- a QStyleOptionView index -- a QModelIndex """ # Retrieve the data model = index.model() record = model.data(index) text = record.toString() zoteroItem = zoteroCache[unicode(text)] l = zoteroItem.full_format().split("\n") if zoteroItem.fulltext == None: pixmap = self.noPdfPixmap else: pixmap = self.pdfPixmap # Choose the colors self.palette = self.qnotero.ui.listWidgetResults.palette() if option.state & QStyle.State_MouseOver: background = self.palette.Highlight foreground = self.palette.HighlightedText _note = zoteroItem.get_note() if _note != None: self.qnotero.showNoteHint() else: self.qnotero.hideNoteHint() elif option.state & QStyle.State_Selected: background = self.palette.Dark foreground = self.palette.WindowText else: background = self.palette.Base foreground = self.palette.WindowText # Draw the frame _rect = option.rect.adjusted(self._margin, self._margin, \ -2*self._margin, -self._margin) pen = painter.pen() pen.setColor(self.palette.color(background)) painter.setPen(pen) painter.setBrush(self.palette.brush(background)) painter.drawRoundedRect(_rect, self.roundness, self.roundness) font = painter.font pen = painter.pen() pen.setColor(self.palette.color(foreground)) painter.setPen(pen) # Draw icon _rect = QRect(option.rect) _rect.moveBottom(_rect.bottom() + 0.5*self.dy) _rect.moveLeft(_rect.left() + 0.5*self.dy) _rect.setHeight(self.pixmapSize) _rect.setWidth(self.pixmapSize) painter.drawPixmap(_rect, pixmap) # Draw the text _rect = option.rect.adjusted(self.pixmapSize+self.dy, 0.5*self.dy, \ -self.dy, 0) f = [self.tagFont, self.italicFont, self.regularFont, \ self.boldFont] l.reverse() while len(l) > 0: s = l.pop() if len(f) > 0: painter.setFont(f.pop()) painter.drawText(_rect, Qt.AlignLeft, s) _rect = _rect.adjusted(0, self.dy, 0, 0)
class XSnapshotWidget(QWidget): def __init__(self, parent=None): super(XSnapshotWidget, self).__init__(parent) # define custom properties self._region = QRect() self._filepath = '' # define custom properties palette = self.palette() palette.setColor(palette.Window, QColor('white')) self.setPalette(palette) self.setWindowOpacity(0.5) self.setWindowFlags(Qt.SplashScreen) self.setFocus() def accept(self): """ Prompts the user for the filepath to save and then saves the image. """ filetypes = 'PNG Files (*.png);;JPG Files (*.jpg);;All Files (*.*)' filename = QFileDialog.getSaveFileName(None, 'Save Snapshot', self.filepath(), filetypes) if type(filename) == tuple: filename = filename[0] filename = str(filename) if not filename: self.reject() else: self.setFilepath(filename) self.save() def filepath(self): """ Returns the filepath that is going to be asved for this snapshot widget. :return <str> """ return self._filepath def hideWindow(self): """ Sets the window to hide/show while taking the snapshot. :param window | <QMainWindow> || <QDialog> """ return self._hideWindow def keyPressEvent(self, event): """ Listens for the escape key to cancel out from this snapshot. :param event | <QKeyPressEvent> """ # reject on a cancel if event.key() == Qt.Key_Escape: self.reject() super(XSnapshotWidget, self).keyPressEvent(event) def mousePressEvent(self, event): """ Starts the selection process for this widget and snapshot area. :param event | <QMousePressEvent> """ self._region.setX(event.pos().x()) self._region.setY(event.pos().y()) super(XSnapshotWidget, self).mousePressEvent(event) def mouseMoveEvent(self, event): """ Drags the selection view for this widget. :param event | <QMouseMoveEvent> """ w = event.pos().x() - self._region.x() h = event.pos().y() - self._region.y() self._region.setWidth(w) self._region.setHeight(h) self.repaint() super(XSnapshotWidget, self).mouseMoveEvent(event) def mouseReleaseEvent(self, event): """ Finishes the selection event. :param event | <QMouseReleaseEvent> """ self.accept() super(XSnapshotWidget, self).mouseReleaseEvent(event) def paintEvent(self, event): """ Handles the drawing for this widget and its selection region. :param event | <QPaintEvent> """ pen = QPen(Qt.DashLine) pen.setColor(QColor('red')) painter = QPainter(self) painter.setPen(pen) clr = QColor('black') clr.setAlpha(100) painter.setBrush(clr) painter.drawRect(self._region) def reject(self): """ Rejects the snapshot and closes the widget. """ if self.hideWindow(): self.hideWindow().show() self.close() self.deleteLater() def region(self): """ Returns the selection region defined by the rectangle for snapshoting. :return <QRect> """ return self._region def save(self): """ Saves the snapshot based on the current region. """ # close down the snapshot widget if self.hideWindow(): self.hideWindow().hide() self.hide() QApplication.processEvents() time.sleep(1) # create the pixmap to save wid = QApplication.desktop().winId() if not self._region.isNull(): x = self._region.x() y = self._region.y() w = self._region.width() h = self._region.height() else: x = self.x() y = self.y() w = self.width() h = self.height() pixmap = QPixmap.grabWindow(wid, x, y, w, h) pixmap.save(self.filepath()) self.close() self.deleteLater() if self.hideWindow(): self.hideWindow().show() def show(self): """ Shows this widget and hides the specified window if necessary. """ super(XSnapshotWidget, self).show() if self.hideWindow(): self.hideWindow().hide() QApplication.processEvents() def setFilepath(self, filepath): """ Sets the filepath that will be saved for this snapshot. :param filepath | <str> """ self._filepath = filepath def setHideWindow(self, window): """ Sets the window that will be hidden while this snapshot is being taken. :param window | <QMainWindow> """ self._hideWindow = window def setRegion(self, rect): """ Sets the region rectangle to the inputed rect. :param rect | <QRect> """ if rect is not None: self._region = rect @staticmethod def capture(rect=None, filepath='', prompt=True, hideWindow=None): """ Prompts the user to capture the screen. :param rect | <QRect> filepath | <str> prompt | <bool> :return (<str> filepath, <bool> accepted) """ widget = XSnapshotWidget(QApplication.desktop()) widget.setRegion(rect) widget.setHideWindow(hideWindow) widget.setFilepath(filepath) widget.move(1, 1) widget.resize(QApplication.desktop().size()) if prompt or not filepath: widget.show() else: widget.save()
class PlottingThread(QThread): def __init__(self, parent): QThread.__init__(self) self.result = None self.parent = parent self._stopped = False self.mutex = QMutex() self.filePrefix = None self.fileFormat = None self.wallColoring = None self.cellColoring = None self.pointColoring = None self.extraDrawing = [] self.pointSize = None self.pointLineColor = None self.pointLineThickness = None self.ellipsisDraw = None self.overSampling = None self.wallThickness = None self.bgColor = None self.loading = False self._crop = QRect(0, 0, 1, 1) self._pix = None self._end_image_plot = False self._loading_arguments = {} self.retryObject = None def end_step(self): return len(self.result) + 1 def stop(self, value=True): self.mutex.lock() self._stopped = value self.mutex.unlock() def stopped(self): self.mutex.lock() val = self._stopped self.mutex.unlock() return val def nextImage(self): QCoreApplication.postEvent(self.parent, NextImageEvent()) def abort(self, reason, **others): e = AbortPlottingEvent(reason) if others: e.others = others QCoreApplication.postEvent(self.parent, e) def finished(self): if self.loading: QCoreApplication.postEvent(self.parent, FinishLoadingEvent()) self.loading = False else: QCoreApplication.postEvent(self.parent, FinishPlottingEvent()) def image_ready(self): QCoreApplication.postEvent(self.parent, ImageReadyPlottingEvent()) def update_nb_images(self, nb): QCoreApplication.postEvent(self.parent, UpdateNbImageEvent(nb)) @property def crop_left(self): return self._crop.left() @crop_left.setter def crop_left(self, value): self._crop.moveLeft(int(value)) @property def crop_top(self): return self._crop.top() @crop_top.setter def crop_top(self, value): self._crop.moveTop(int(value)) @property def crop_width(self): return self._crop.width() @crop_width.setter def crop_width(self, value): self._crop.setWidth(int(value)) @property def crop_height(self): return self._crop.height() @crop_height.setter def crop_height(self, value): self._crop.setHeight(int(value)) def reset_crop(self): self._crop = QRect(QPoint(0, 0), self.img_size) @property def crop(self): return QRect(self._crop) @crop.deleter def crop(self): self.reset_crop() @property def end_image_plot(self): ''' If true, plot the growth data on the end image rather than the start image of the growth calculation. ''' return self._end_image_plot @end_image_plot.setter def end_image_plot(self, value): self._end_image_plot = bool(value) @property def pix(self): '''Thread-safe image storage.''' self.mutex.lock() pix = self._pix self.mutex.unlock() return pix @pix.setter def pix(self, value): self.mutex.lock() self._pix = value self.mutex.unlock() def render_valid(self): if self.result is None: log_debug("result is None") return False if self.parent is None: log_debug("parent is None") return False if self.ellipsisDraw is None: log_debug("ellipsisDraw is None") return False if self.cellColoring is None: log_debug("cellColoring is None") return False if self.wallColoring is None: log_debug("wallColoring is None") return False if self.pointColoring is None: log_debug("pointColoring is None") return False if self.pointSize is None: log_debug("pointSize is None") return False if self.pointLineThickness is None: log_debug("pointSize is None") return False if self.pointLineColor is None: log_debug("pointSize is None") return False if self.wallThickness is None: log_debug("wallThickness is None") return False if self.overSampling is None: log_debug("overSampling is None") return False if self.bgColor is None: log_debug("bgColor is None") return False return True def valid(self): if self.filePrefix is None: log_debug("filePrefix is None") return False if not self.filePrefix: log_debug("filePrefix is Empty") return False if self.fileFormat is None: log_debug("fileFormat is None") return False return self.render_valid() def drawImage(self, imageid): cache = image_cache.cache cellColoring = self.cellColoring wallColoring = self.wallColoring pointColoring = self.pointColoring ellipsisDraw = self.ellipsisDraw overSampling = self.overSampling extraDrawing = self.extraDrawing bgColor = self.bgColor.rgb() result = self.result if self.result_type == "Data": data = result img_name = result.images_name[imageid] else: data = result.data img_name = result.images[imageid] #scale = data.images_scale[img_name] min_scale = data.minScale() img = cache.image(data.image_path(img_name)) img_data = data[img_name] size = self._crop.size() pix = QImage(size * overSampling, QImage.Format_ARGB32) pix.fill(bgColor) painter = QPainter() if not painter.begin(pix): self.abort("Cannot create painter on QImage") return None, None, None painter.setRenderHints(QPainter.SmoothPixmapTransform, True) painter.setRenderHints(QPainter.Antialiasing, True) if overSampling > 1: painter.scale(overSampling, overSampling) painter.translate(-self._crop.topLeft()) painter.save() painter.translate(self.translate) log_debug("Translating: %gx%g" % (self.translate.x(), self.translate.y())) painter.scale(1 / min_scale, 1 / min_scale) painter.save() matrix = img_data.matrix() painter.setWorldTransform(matrix, True) painter.drawImage(QPoint(0, 0), img) painter.restore() #pt_matrix = QTransform() #pt_matrix.scale(1/min_scale, 1/min_scale) #painter.setTransform(pt_matrix, True) cellColoring.startImage(painter, imageid) wallColoring.startImage(painter, imageid) for ed in extraDrawing: ed.startImage(painter, imageid) if self.result_type == "Growth": cells = result.cells[imageid] walls = result.walls[imageid] else: cells = img_data.cells walls = set() for cid in img_data.cells: pts = [pt for pt in data.cells[cid] if pt in img_data] if len(pts) > 1: for i in range(len(pts)): walls.add(data.wallId(pts[i - 1], pts[i])) # Now, draw the cells and the ellipsis for cid in cells: painter.setPen(Qt.NoPen) color = cellColoring(imageid, cid) painter.setBrush(color) pts = data.cellAtTime(cid, img_data.index) if pts: pts.append(pts[0]) ppts = [] for p1, p2 in zip(pts[:-1], pts[1:]): ppts.append(img_data[p1]) ppts.extend(img_data.walls[p1, p2]) ppts.append(ppts[0]) poly = QPolygonF(ppts) painter.drawPolygon(poly) # And draw the walls wallThickness = self.wallThickness * min_scale for wid in walls: color = wallColoring(imageid, wid) if color.alpha() > 0: pen = QPen(color) pen.setWidthF(wallThickness) painter.setPen(pen) pts = [img_data[wid[0]] ] + img_data.walls[wid[0], wid[1]] + [img_data[wid[1]]] #painter.drawLine(img_data[wid[0]], img_data[wid[1]]) painter.drawPolyline(*pts) # Then, draw the points pointSize = self.pointSize * min_scale pointLineColor = self.pointLineColor pointLineThickness = self.pointLineThickness * min_scale log_debug("pointSize = %g" % pointSize) for pid in img_data: color = pointColoring(imageid, pid) if color.alpha() > 0: pen = QPen(pointLineColor) pen.setWidthF(pointLineThickness) brush = QBrush(color) painter.setPen(pen) painter.setBrush(brush) pos = img_data[pid] rect = QRectF(pos.x() - pointSize, pos.y() - pointSize, 2 * pointSize, 2 * pointSize) painter.drawEllipse(rect) if ellipsisDraw.plot: for cid in cells: pts = data.cellAtTime(cid, img_data.index) if pts: pts.append(pts[0]) ppts = [] for p1, p2 in zip(pts[:-1], pts[1:]): ppts.append(img_data[p1]) ppts.extend(img_data.walls[p1, p2]) ppts.append(ppts[0]) #poly = QPolygonF(ppts) #painter.drawPolygon(poly) ellipsisDraw(painter, imageid, cid, ppts, min_scale) # At last, draw the extra data for ed in extraDrawing: ed(painter, imageid) tr = painter.worldTransform() painter.restore() pic_w = wallColoring.finalizeImage(painter, imageid, tr, self.crop) pic_c = cellColoring.finalizeImage(painter, imageid, tr, self.crop) for ed in extraDrawing: ed.finalizeImage(painter, imageid, tr, self.crop) painter.end() return pix, pic_w, pic_c def start(self): if self.isRunning(): assert not self.rendering_all, "Cannot run twice the rendering of all images with the same object." return if parameters.instance.use_thread: log_debug("Starting rendering thread.") QThread.start(self) return False else: self.run() return True def render_all(self): self.rendering_all = True return self.start() def render_single(self, img_id, retry=False): if retry: while self.isRunning(): self.wait(10000) elif self.isRunning(): return self.rendering_all = False self.current_image = img_id return self.start() def load(self, filename): self.loading = True self.result = filename return self.start() def run(self): if self.loading: self.run_loader() elif self.rendering_all: self.run_full() else: self.run_single() def run_single(self): img = self.current_image self.cellColoring.init() self.wallColoring.init() self.pointColoring.init() log_debug("Rendering image %d" % img) self.pix, self.pic_w, self.pic_c = self.drawImage(img) if self.pic_w is not None: log_debug("Has wall image") if self.pic_c is not None: log_debug("Has cell image") if self.pix is not None: log_debug("Pix correctly rendered") log_debug("Rendered image %d = %s" % (img, self.pix)) self.image_ready() def reload(self): if self.retryObject is None: return self._loading_arguments.update(self.retryObject.method_args) self.load(self.retryObject.filename) def run_loader(self): filename = self.result try: self.retryObject = None # First, prepare the data by getting the images and computing how big they # should be f = open(filename) first_line = f.readline() f.close() if first_line.startswith("TRKR_VERSION"): result = Result(None) result.load(self.result, **self._loading_arguments) result_type = "Growth" else: result = TrackingData() result.load(self.result, **self._loading_arguments) result_type = "Data" self.result = result self.result_type = result_type if result_type == "Data": data = result images = data.images_name if data.cells: self.has_cells = True self.has_walls = True else: self.has_cells = False self.has_walls = False self.has_points = bool(data.cell_points) else: data = result.data images = result.images self.has_cells = False self.has_walls = False self.has_points = False self.images = images cache = image_cache.cache self.update_nb_images(len(result)) bbox = QRectF() ms = data.minScale() for i in range(len(result)): img_name = images[i] img_data = data[img_name] img = cache.image(data.image_path(img_name)) matrix = QTransform() matrix = img_data.matrix() sc = QTransform() sc.scale(1.0 / ms, 1.0 / ms) matrix *= sc r = QRectF(img.rect()) rbox = matrix.map(QPolygonF(r)).boundingRect() bbox |= rbox log_debug( "Image '%s':\n\tSize = %gx%g\n\tTransformed = %gx%g %+g %+g\n\tGlobal bbox = %gx%g %+g %+g\n" % (img_name, r.width(), r.height(), rbox.width(), rbox.height(), rbox.left(), rbox.top(), bbox.width(), bbox.height(), bbox.left(), bbox.top())) log_debug("Matrix:\n%g\t%g\t%g\n%g\t%g\t%g\n" % (matrix.m11(), matrix.m12(), matrix.dx(), matrix.m21(), matrix.m22(), matrix.dy())) if result_type == "Growth": if result.cells[i]: self.has_cells = True if result.walls[i]: self.has_walls = True self.has_points = bool(result.data.cell_points) self.nextImage() translate = bbox.topLeft() translate *= -1 self.translate = translate size = bbox.size().toSize() self.img_size = size self._crop = QRect(QPoint(0, 0), size) self.finished() self._loading_arguments = { } # All done, we don't need that anymore except RetryTrackingDataException as ex: ex.filename = filename self.retryObject = ex self.finished() return except Exception as ex: _, _, exceptionTraceback = sys.exc_info() self.abort(ex, traceback=exceptionTraceback) raise def run_full(self): if not self.valid(): self.abort("Object was not correctly initialized") return self.stop(False) painter = None try: result = self.result self.update_nb_images(len(result)) # if self.result_type == "Data": # data = result # images = result.images_name # else: # data = result.data # images = result.images # cache = image_cache.cache cellColoring = self.cellColoring wallColoring = self.wallColoring pointColoring = self.pointColoring file_format = self.fileFormat file_pattern = "%s%%0%dd.%s" % (self.filePrefix, len(str(len(result))), file_format) wall_file_pattern = "%s%%0%dd_wall.%s" % ( self.filePrefix, len(str(len(result))), file_format) cell_file_pattern = "%s%%0%dd_cell.%s" % ( self.filePrefix, len(str(len(result))), file_format) cellColoring.init() wallColoring.init() pointColoring.init() self.nextImage() for i in range(len(result)): if self.stopped(): self.abort("User interruption") return pix, pic_w, pic_c = self.drawImage(i) pix.save(file_pattern % (i + 1), file_format) if pic_w is not None: self.saveExtra(pic_w, wall_file_pattern % (i + 1), file_format) if pic_c is not None: self.saveExtra(pic_c, cell_file_pattern % (i + 1), file_format) self.nextImage() self.finished() except Exception as ex: if painter is not None: painter.end() _, _, exceptionTraceback = sys.exc_info() self.abort(ex, traceback=exceptionTraceback) raise def saveExtra(self, picture, file_name, file_format): rect = picture.boundingRect() pix = QImage(rect.size(), QImage.Format_ARGB32) pix.fill(QColor(0, 0, 0, 0).rgba()) paint = QPainter() paint.begin(pix) paint.drawPicture(rect.topLeft() * -1, picture) paint.end() pix.save(file_name, file_format)