def show(cursor, pos=None, num_lines=6): """Displays a tooltip showing part of the cursor's Document. If the cursor has a selection, those blocks are displayed. Otherwise, num_lines lines are displayed. If pos is not given, the global mouse position is used. """ block = cursor.document().findBlock(cursor.selectionStart()) c2 = QTextCursor(block) if cursor.hasSelection(): c2.setPosition(cursor.selectionEnd(), QTextCursor.KeepAnchor) c2.movePosition(QTextCursor.EndOfBlock, QTextCursor.KeepAnchor) else: c2.movePosition(QTextCursor.NextBlock, QTextCursor.KeepAnchor, num_lines) data = textformats.formatData('editor') doc = QTextDocument() font = QFont(data.font) font.setPointSizeF(font.pointSizeF() * .8) doc.setDefaultFont(font) doc.setPlainText(c2.selection().toPlainText()) if metainfo.info(cursor.document()).highlighting: highlighter.highlight(doc, state=tokeniter.state(block)) size = doc.size().toSize() + QSize(8, -4) pix = QPixmap(size) pix.fill(data.baseColors['background']) doc.drawContents(QPainter(pix)) label = QLabel() label.setPixmap(pix) label.setStyleSheet("QLabel { border: 1px solid #777; }") label.resize(size) widgets.customtooltip.show(label, pos)
def loadSettings(self): s = QSettings() s.beginGroup("log") font = QFont(s.value("fontfamily", "monospace")) font.setPointSizeF(float(s.value("fontsize", 9.0))) with qutil.signalsBlocked(self.fontChooser, self.fontSize): self.fontChooser.setCurrentFont(font) self.fontSize.setValue(font.pointSizeF()) self.showlog.setChecked(s.value("show_on_start", True) not in (False, "false")) self.rawview.setChecked(s.value("rawview", True) not in (False, "false"))
def loadSettings(self): s = QSettings() s.beginGroup("log") font = QFont(s.value("fontfamily", "monospace", type(""))) font.setPointSizeF(s.value("fontsize", 9.0, float)) with qutil.signalsBlocked(self.fontChooser, self.fontSize): self.fontChooser.setCurrentFont(font) self.fontSize.setValue(font.pointSizeF()) self.showlog.setChecked(s.value("show_on_start", True, bool)) self.rawview.setChecked(s.value("rawview", True, bool)) self.hideauto.setChecked(s.value("hide_auto_engrave", False, bool))
def loadSettings(self): s = QSettings() s.beginGroup("log") font = QFont(s.value("fontfamily", "monospace", type(""))) font.setPointSizeF(s.value("fontsize", 9.0, float)) with qutil.signalsBlocked(self.fontChooser, self.fontSize): self.fontChooser.setCurrentFont(font) self.fontSize.setValue(font.pointSizeF()) self.showlog.setChecked(s.value("show_on_start", True, bool)) self.rawview.setChecked(s.value("rawview", True, bool)) self.hideauto.setChecked(s.value("hide_auto_engrave", False, bool))
def show(cursor, pos=None, num_lines=6): """Displays a tooltip showing part of the cursor's Document. If the cursor has a selection, those blocks are displayed. Otherwise, num_lines lines are displayed. If pos is not given, the global mouse position is used. """ block = cursor.document().findBlock(cursor.selectionStart()) c2 = QTextCursor(block) if cursor.hasSelection(): c2.setPosition(cursor.selectionEnd(), QTextCursor.KeepAnchor) c2.movePosition(QTextCursor.EndOfBlock, QTextCursor.KeepAnchor) else: c2.movePosition(QTextCursor.NextBlock, QTextCursor.KeepAnchor, num_lines) data = textformats.formatData('editor') doc = QTextDocument() font = QFont(data.font) font.setPointSizeF(font.pointSizeF() * .8) doc.setDefaultFont(font) doc.setPlainText(c2.selection().toPlainText()) if metainfo.info(cursor.document()).highlighting: highlighter.highlight(doc, state=tokeniter.state(block)) size = doc.size().toSize() + QSize(8, -4) pix = QPixmap(size) pix.fill(data.baseColors['background']) doc.drawContents(QPainter(pix)) label = QLabel() label.setPixmap(pix) label.setStyleSheet("QLabel { border: 1px solid #777; }") label.resize(size) widgets.customtooltip.show(label, pos)
def draw(self, painter, size=None): """ :Arguments: painter : QPainter Opened painter on which to draw """ bounding_rect = QRectF() position = self.position transfer_function = self.transfer_function font = QFont(self.font) text_color = self.text_color line_color = self.line_color line_thickness = self.line_thickness value_range = self.value_range if size is None: viewport = painter.viewport() # viewport rectangle mat, ok = painter.worldMatrix().inverted() if not ok: raise ValueError( "Transformation matrix of painter is singular.") viewport = mat.mapRect(viewport) else: viewport = size # First, prepare the gradient w = viewport.width() h = viewport.height() #print("Size of viewport: {0}x{1}".format(w, h)) gr = QLinearGradient() nb_values = ceil(w / 5.0) brush_color = QColor() for i in range(int(nb_values)): brush_color.setRgbF(*transfer_function.rgba(i / nb_values)) gr.setColorAt(i / nb_values, brush_color) # Second, find its position metric = QFontMetricsF(font, painter.device()) font_test = [str(i) * 5 for i in range(10)] lim_width = 0 lim_height = 0 for t in font_test: rect = metric.boundingRect(t) lim_width = max(lim_width, rect.width()) lim_height = max(lim_height, rect.height()) lim_height *= 3 length = self.scale_length shift_length = (1 - length) / 2 width = self.scale_width shift_width = self.scale_shift_width delta_value = value_range[1] - value_range[0] if position == "Top": scale_rect = QRectF(shift_length * w, shift_width * h, length * w, width * h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.left(), scale_rect.center().y()) gr.setFinalStop(scale_rect.right(), scale_rect.center().y()) start_pos = scale_rect.bottomLeft() end_pos = scale_rect.bottomRight() elif position == "Right": scale_rect = QRectF((1 - shift_width - width) * w, shift_length * h, width * w, length * h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.center().x(), scale_rect.bottom()) gr.setFinalStop(scale_rect.center().x(), scale_rect.top()) start_pos = scale_rect.bottomLeft() end_pos = scale_rect.topLeft() elif position == "Bottom": scale_rect = QRectF(shift_length * w, (1 - shift_width - width) * h, length * w, width * h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.left(), scale_rect.center().y()) gr.setFinalStop(scale_rect.right(), scale_rect.center().y()) start_pos = scale_rect.topLeft() end_pos = scale_rect.topRight() elif position == "Left": scale_rect = QRectF(shift_width * w, shift_length * h, width * w, length * h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.center().x(), scale_rect.bottom()) gr.setFinalStop(scale_rect.center().x(), scale_rect.top()) start_pos = scale_rect.bottomRight() end_pos = scale_rect.topRight() else: raise ValueError("Invalid scale position: %s" % position) shift_pos = (end_pos - start_pos) / delta_value if position in ["Left", "Right"]: is_vertical = True length = scale_rect.height() else: is_vertical = False length = scale_rect.width() # Get the ticks ticks = self.selectValues(length, is_vertical, painter) if len(ticks) == 0: return ticks_str, ticks_extra = self._tick2str(ticks) # Figure the shifts dist_to_bar = self.text_to_bar max_width = 0 max_height = 0 for t in ticks_str: rect = metric.boundingRect(t) max_width = max(rect.width(), max_width) max_height = max(rect.height(), max_height) if position == "Left": shift_left = dist_to_bar shift_top = None elif position == "Right": shift_left = -dist_to_bar - max_width shift_top = None elif position == "Top": shift_left = None shift_top = dist_to_bar else: shift_left = None shift_top = -dist_to_bar - max_height painter.save() painter.translate(viewport.topLeft()) #print("viewport.topLeft() = {0}x{1}".format(viewport.left(), viewport.top())) painter.setBrush(gr) line_pen = QPen(line_color) line_pen.setWidth(line_thickness) painter.setPen(line_pen) painter.drawRect(scale_rect) bounding_rect |= scale_rect #print("Scale rect: +{0}+{1}x{2}x{3}".format(scale_rect.left(), #scale_rect.top(), scale_rect.width(), scale_rect.height())) painter.setFont(font) painter.setPen(text_color) for ts, t in zip(ticks_str, ticks): r = metric.boundingRect(ts) pos = start_pos + shift_pos * (t - value_range[0]) if shift_left is None: pos.setX(pos.x() - r.width() / 2) else: pos.setX(pos.x() + shift_left) if shift_top is None: pos.setY(pos.y() - r.height() / 2) else: pos.setY(pos.y() + shift_top) r.moveTo(pos) real_rect = painter.drawText( r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, ts) bounding_rect |= real_rect if ticks_extra is not None or self.unit: unit = self.unit exp_width = width = space_width = 0 exp_txt = "" r = exp_r = unit_r = QRectF() exp_font = None if ticks_extra is not None: exp_txt = u"×10" r = metric.boundingRect(exp_txt) exp_font = QFont(font) exp_size = self.exp_size if exp_font.pixelSize() != -1: exp_font.setPixelSize(exp_size * exp_font.pixelSize()) else: exp_font.setPointSizeF(exp_size * exp_font.pointSizeF()) exp_metric = QFontMetricsF(exp_font, painter.device()) exp_r = exp_metric.boundingRect(ticks_extra) if unit: unit_r = metric.boundingRect(unit) total_width = r.width() + exp_r.width() + unit_r.width() total_height = max(r.height(), unit_r.height()) + exp_r.height() / 2 pos = scale_rect.topRight() log_debug("top right of scale bar = (%g,%g)" % (pos.x(), pos.y())) log_debug("Size of image = (%d,%d)" % (w, h)) log_debug("Size of text = (%g,%g)" % (total_width, total_height)) if position == "Bottom": pos.setY(pos.y() + scale_rect.height() + dist_to_bar) pos.setX(pos.x() - total_width) elif position == "Top": pos.setY(pos.y() - dist_to_bar - total_height) pos.setX(pos.x() - total_width) else: # position == "left" or "right" pos.setX(pos.x() - (scale_rect.width() + total_width) / 2) if pos.x() < 0: pos.setX(dist_to_bar) elif pos.x() + total_width + dist_to_bar > w: pos.setX(w - total_width - dist_to_bar) pos.setY(pos.y() - dist_to_bar - total_height) log_debug("Display unit at position: (%g,%g)" % (pos.x(), pos.y())) if ticks_extra is not None: r.moveTo(pos) real_rect = painter.drawText( r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, exp_txt) bounding_rect |= real_rect pos.setX(pos.x() + r.width()) pos.setY(pos.y() - metric.ascent() / 2) exp_r.moveTo(pos) painter.setFont(exp_font) real_rect = painter.drawText( exp_r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, ticks_extra) bounding_rect |= real_rect pos.setY(pos.y() + metric.ascent() / 2) if unit: pos.setX(pos.x() + space_width + exp_r.width()) unit_r.moveTo(pos) painter.setFont(font) real_rect = painter.drawText( unit_r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, unit) bounding_rect |= real_rect # Draw the ticks now painter.setPen(line_pen) tick_size = self.tick_size if is_vertical: width = scale_rect.width() * tick_size else: width = scale_rect.height() * tick_size pen_width = painter.pen().widthF() if pen_width == 0: pen_width = 1.0 for t in ticks: pos1 = start_pos + shift_pos * (t - value_range[0]) pos2 = QPointF(pos1) if is_vertical: pos1.setX(scale_rect.left() + pen_width) pos2.setX(pos1.x() + width - pen_width) painter.drawLine(pos1, pos2) pos1.setX(scale_rect.right() - pen_width) pos2.setX(pos1.x() - width + pen_width) painter.drawLine(pos1, pos2) else: pos1.setY(scale_rect.top() + pen_width) pos2.setY(pos1.y() + width - pen_width) painter.drawLine(pos1, pos2) pos1.setY(scale_rect.bottom() - pen_width) pos2.setY(pos1.y() - width + pen_width) painter.drawLine(pos1, pos2) painter.restore() bounding_rect = bounding_rect.adjusted(-pen_width, -pen_width, pen_width, pen_width) return bounding_rect
class CharMap(QWidget): """A widget displaying a table of characters.""" characterSelected = pyqtSignal(str) characterClicked = pyqtSignal(str) def __init__(self, parent=None): super(CharMap, self).__init__(parent) self._showToolTips = True self._showWhatsThis = True self._selected = -1 self._column_count = 32 self._square = 24 self._range = (0, 0) self._font = QFont() def setRange(self, first, last): self._range = (first, last) self._selected = -1 self.adjustSize() self.update() def range(self): return self._range def square(self): """Returns the width of one item (determined by font size).""" return self._square def select(self, charcode): """Selects the specified character (int or str).""" if not isinstance(charcode, int): charcode = ord(charcode) if not self._range[0] <= charcode <= self._range[1]: charcode = -1 if self._selected != charcode: self._selected = charcode self.characterSelected.emit(chr(charcode)) self.update() def character(self): """Returns the currently selected character, if any.""" if self._selected != -1: return chr(self._selected) def setDisplayFont(self, font): self._font.setFamily(font.family()) self.update() def displayFont(self): return QFont(self._font) def setDisplayFontSize(self, size): self._font.setPointSize(size) self._square = max(24, QFontMetrics(self._font).xHeight() * 3) self.adjustSize() self.update() def displayFontSize(self): return self._font.pointSize() def setDisplayFontSizeF(self, size): self._font.setPointSizeF(size) self._square = max(24, QFontMetrics(self._font).xHeight() * 3) self.adjustSize() self.update() def displayFontSizeF(self): return self._font.pointSizeF() def setColumnCount(self, count): """Sets how many columns should be used.""" count = max(1, count) self._column_count = count self.adjustSize() self.update() def columnCount(self): return self._column_count def sizeHint(self): return self.sizeForColumnCount(self._column_count) def paintEvent(self, ev): rect = ev.rect() s = self._square rows = range(rect.top() // s, rect.bottom() // s + 1) cols = range(rect.left() // s, rect.right() // s + 1) painter = QPainter(self) painter.setPen(QPen(self.palette().color(QPalette.Window))) painter.setFont(self._font) metrics = QFontMetrics(self._font) # draw characters on white tiles tile = self.palette().color(QPalette.Base) selected_tile = self.palette().color(QPalette.Highlight) selected_tile.setAlpha(96) selected_box = self.palette().color(QPalette.Highlight) text_pen = QPen(self.palette().text()) disabled_pen = QPen(self.palette().color(QPalette.Disabled, QPalette.Text)) selection_pen = QPen(selected_box) for row in rows: for col in cols: char = row * self._column_count + col + self._range[0] if char > self._range[1]: break printable = self.isprint(char) painter.setClipRect(col * s, row * s, s, s) if char == self._selected: painter.fillRect(col * s + 1, row * s + 1, s - 2, s - 2, selected_tile) painter.setPen(selection_pen) painter.drawRect(col * s, row * s, s - 1, s - 1) elif printable: painter.fillRect(col * s + 1, row * s + 1, s - 2, s - 2, tile) painter.setPen(text_pen if printable else disabled_pen) t = chr(char) x = col * s + s // 2 - metrics.width(t) // 2 y = row * s + 4 + metrics.ascent() painter.drawText(x, y, t) else: continue break def sizeForColumnCount(self, count): """Returns the size the widget would have in a certain column count. This can be used in e.g. a resizable scroll area. """ first, last = self._range rows = ((last - first) // count) + 1 return QSize(count, rows) * self._square def columnCountForWidth(self, width): """Returns the number of columns that would fit into the given width.""" return width // self._square def mousePressEvent(self, ev): charcode = self.charcodeAt(ev.pos()) if charcode != -1 and self.isprint(charcode): self.select(charcode) if ev.button() != Qt.RightButton: self.characterClicked.emit(chr(charcode)) def charcodeRect(self, charcode): """Returns the rectangular box around the given charcode, if any.""" if self._range[0] <= charcode <= self._range[1]: row, col = divmod(charcode - self._range[0], self._column_count) s = self._square return QRect(col * s, row * s, s, s) def charcodeAt(self, position): row = position.y() // self._square col = position.x() // self._square if col <= self._column_count: charcode = self._range[0] + row * self._column_count + col if charcode <= self._range[1]: return charcode return -1 def event(self, ev): if ev.type() == QEvent.ToolTip: if self._showToolTips: c = self.charcodeAt(ev.pos()) if c: text = self.getToolTipText(c) if text: rect = self.charcodeRect(c) QToolTip.showText(ev.globalPos(), text, self, rect) ev.accept() return True elif ev.type() == QEvent.QueryWhatsThis: if self._showWhatsThis: ev.accept() return True elif ev.type() == QEvent.WhatsThis: ev.accept() if self._showWhatsThis: c = self.charcodeAt(ev.pos()) text = self.getWhatsThisText(c) if c else None if text: QWhatsThis.showText(ev.globalPos(), text, self) else: QWhatsThis.leaveWhatsThisMode() return True return super(CharMap, self).event(ev) def getToolTipText(self, charcode): try: return unicodedata.name(chr(charcode)) except ValueError: pass def getWhatsThisText(self, charcode): try: name = unicodedata.name(chr(charcode)) except ValueError: return return whatsthis_html.format(self._font.family(), chr(charcode), name, charcode) def setShowToolTips(self, enabled): self._showToolTips = bool(enabled) def showToolTips(self): return self._showToolTips def setShowWhatsThis(self, enabled): self._showWhatsThis = bool(enabled) def showWhatsThis(self): return self._showWhatsThis def isprint(self, charcode): """Returns True if the given charcode is printable.""" return isprint(charcode)
class CharMap(QWidget): """A widget displaying a table of characters.""" characterSelected = pyqtSignal(str) characterClicked = pyqtSignal(str) def __init__(self, parent=None): super(CharMap, self).__init__(parent) self._showToolTips = True self._showWhatsThis = True self._selected = -1 self._column_count = 32 self._square = 24 self._range = (0, 0) self._font = QFont() def setRange(self, first, last): self._range = (first, last) self._selected = -1 self.adjustSize() self.update() def range(self): return self._range def square(self): """Returns the width of one item (determined by font size).""" return self._square def select(self, charcode): """Selects the specified character (int or str).""" if not isinstance(charcode, int): charcode = ord(charcode) if not self._range[0] <= charcode <= self._range[1]: charcode = -1 if self._selected != charcode: self._selected = charcode self.characterSelected.emit(chr(charcode)) self.update() def character(self): """Returns the currently selected character, if any.""" if self._selected != -1: return chr(self._selected) def setDisplayFont(self, font): self._font.setFamily(font.family()) self.update() def displayFont(self): return QFont(self._font) def setDisplayFontSize(self, size): self._font.setPointSize(size) self._square = max(24, QFontMetrics(self._font).xHeight() * 3) self.adjustSize() self.update() def displayFontSize(self): return self._font.pointSize() def setDisplayFontSizeF(self, size): self._font.setPointSizeF(size) self._square = max(24, QFontMetrics(self._font).xHeight() * 3) self.adjustSize() self.update() def displayFontSizeF(self): return self._font.pointSizeF() def setColumnCount(self, count): """Sets how many columns should be used.""" count = max(1, count) self._column_count = count self.adjustSize() self.update() def columnCount(self): return self._column_count def sizeHint(self): return self.sizeForColumnCount(self._column_count) def paintEvent(self, ev): rect = ev.rect() s = self._square rows = range(rect.top() // s, rect.bottom() // s + 1) cols = range(rect.left() // s, rect.right() // s + 1) painter = QPainter(self) painter.setPen(QPen(self.palette().color(QPalette.Window))) painter.setFont(self._font) metrics = QFontMetrics(self._font) # draw characters on white tiles tile = self.palette().color(QPalette.Base) selected_tile = self.palette().color(QPalette.Highlight) selected_tile.setAlpha(96) selected_box = self.palette().color(QPalette.Highlight) text_pen = QPen(self.palette().text()) disabled_pen = QPen(self.palette().color(QPalette.Disabled, QPalette.Text)) selection_pen = QPen(selected_box) for row in rows: for col in cols: char = row * self._column_count + col + self._range[0] if char > self._range[1]: break printable = self.isprint(char) painter.setClipRect(col * s, row * s, s, s) if char == self._selected: painter.fillRect(col * s + 1, row * s + 1, s - 2, s - 2, selected_tile) painter.setPen(selection_pen) painter.drawRect(col * s, row * s, s - 1, s - 1) elif printable: painter.fillRect(col * s + 1, row * s + 1, s - 2, s - 2, tile) painter.setPen(text_pen if printable else disabled_pen) t = chr(char) x = col * s + s // 2 - metrics.width(t) // 2 y = row * s + 4 + metrics.ascent() painter.drawText(x, y, t) else: continue break def sizeForColumnCount(self, count): """Returns the size the widget would have in a certain column count. This can be used in e.g. a resizable scroll area. """ first, last = self._range rows = ((last - first) // count) + 1 return QSize(count, rows) * self._square def columnCountForWidth(self, width): """Returns the number of columns that would fit into the given width.""" return width // self._square def mousePressEvent(self, ev): charcode = self.charcodeAt(ev.pos()) if charcode != -1 and self.isprint(charcode): self.select(charcode) if ev.button() != Qt.RightButton: self.characterClicked.emit(chr(charcode)) def charcodeRect(self, charcode): """Returns the rectangular box around the given charcode, if any.""" if self._range[0] <= charcode <= self._range[1]: row, col = divmod(charcode - self._range[0], self._column_count) s = self._square return QRect(col * s, row * s, s, s) def charcodeAt(self, position): row = position.y() // self._square col = position.x() // self._square if col <= self._column_count: charcode = self._range[0] + row * self._column_count + col if charcode <= self._range[1]: return charcode return -1 def event(self, ev): if ev.type() == QEvent.ToolTip: if self._showToolTips: c = self.charcodeAt(ev.pos()) if c: text = self.getToolTipText(c) if text: rect = self.charcodeRect(c) QToolTip.showText(ev.globalPos(), text, self, rect) ev.accept() return True elif ev.type() == QEvent.QueryWhatsThis: if self._showWhatsThis: ev.accept() return True elif ev.type() == QEvent.WhatsThis: ev.accept() if self._showWhatsThis: c = self.charcodeAt(ev.pos()) text = self.getWhatsThisText(c) if c else None if text: QWhatsThis.showText(ev.globalPos(), text, self) else: QWhatsThis.leaveWhatsThisMode() return True return super(CharMap, self).event(ev) def getToolTipText(self, charcode): try: return unicodedata.name(chr(charcode)) except ValueError: pass def getWhatsThisText(self, charcode): try: name = unicodedata.name(chr(charcode)) except ValueError: return return whatsthis_html.format( self._font.family(), chr(charcode), name, charcode) def setShowToolTips(self, enabled): self._showToolTips = bool(enabled) def showToolTips(self): return self._showToolTips def setShowWhatsThis(self, enabled): self._showWhatsThis = bool(enabled) def showWhatsThis(self): return self._showWhatsThis def isprint(self, charcode): """Returns True if the given charcode is printable.""" return isprint(charcode)
class TextFormatData(object): """Encapsulates all settings in the Fonts & Colors page for a scheme.""" def __init__(self, scheme): """Loads the data from scheme.""" self.font = None self.baseColors = {} self.defaultStyles = {} self.allStyles = {} self.load(scheme) def load(self, scheme): """Load the settings for the scheme. Called on init.""" s = QSettings() s.beginGroup("fontscolors/" + scheme) # load font self.font = QFont(s.value("fontfamily", "monospace")) self.font.setPointSizeF(float(s.value("fontsize", 10.0))) # load base colors s.beginGroup("basecolors") for name in baseColors: if s.contains(name): self.baseColors[name] = QColor(s.value(name)) else: self.baseColors[name] = baseColorDefaults[name]() s.endGroup() # load default styles s.beginGroup("defaultstyles") for name in defaultStyles: self.defaultStyles[name] = f = QTextCharFormat(defaultStyleDefaults[name]) s.beginGroup(name) self.loadTextFormat(f, s) s.endGroup() s.endGroup() # load specific styles s.beginGroup("allstyles") for group, styles in allStyles: self.allStyles[group]= {} s.beginGroup(group) for name in styles: default = allStyleDefaults[group].get(name) self.allStyles[group][name] = f = QTextCharFormat(default) if default else QTextCharFormat() s.beginGroup(name) self.loadTextFormat(f, s) s.endGroup() s.endGroup() s.endGroup() def save(self, scheme): """Save the settings to the scheme.""" s = QSettings() s.beginGroup("fontscolors/" + scheme) # save font s.setValue("fontfamily", self.font.family()) s.setValue("fontsize", self.font.pointSizeF()) # save base colors for name in baseColors: s.setValue("basecolors/"+name, self.baseColors[name].name()) # save default styles s.beginGroup("defaultstyles") for name in defaultStyles: s.beginGroup(name) self.saveTextFormat(self.defaultStyles[name], s) s.endGroup() s.endGroup() # save all specific styles s.beginGroup("allstyles") for group, styles in allStyles: s.beginGroup(group) for name in styles: s.beginGroup(name) self.saveTextFormat(self.allStyles[group][name], s) s.endGroup() s.endGroup() s.endGroup() def textFormat(self, group, name): """Return a QTextCharFormat() for the specified group and name.""" inherit = inherits[group].get(name) f = QTextCharFormat(self.defaultStyles[inherit]) if inherit else QTextCharFormat() f.merge(self.allStyles[group][name]) return f def palette(self): """Return a basic palette with text, background, selection and selection background filled in.""" p = QApplication.palette() p.setColor(QPalette.Text, self.baseColors['text']) p.setColor(QPalette.Base, self.baseColors['background']) p.setColor(QPalette.HighlightedText, self.baseColors['selectiontext']) p.setColor(QPalette.Highlight, self.baseColors['selectionbackground']) return p def saveTextFormat(self, fmt, settings): """(Internal) Store one QTextCharFormat in the QSettings instance.""" if fmt.hasProperty(QTextFormat.FontWeight): settings.setValue('bold', fmt.fontWeight() >= 70) else: settings.remove('bold') if fmt.hasProperty(QTextFormat.FontItalic): settings.setValue('italic', fmt.fontItalic()) else: settings.remove('italic') if fmt.hasProperty(QTextFormat.TextUnderlineStyle): settings.setValue('underline', fmt.fontUnderline()) else: settings.remove('underline') if fmt.hasProperty(QTextFormat.ForegroundBrush): settings.setValue('textColor', fmt.foreground().color().name()) else: settings.remove('textColor') if fmt.hasProperty(QTextFormat.BackgroundBrush): settings.setValue('backgroundColor', fmt.background().color().name()) else: settings.remove('backgroundColor') if fmt.hasProperty(QTextFormat.TextUnderlineColor): settings.setValue('underlineColor', fmt.underlineColor().name()) else: settings.remove('underlineColor') def loadTextFormat(self, fmt, settings): """(Internal) Merge values from the QSettings instance into the QTextCharFormat.""" if settings.contains('bold'): fmt.setFontWeight(QFont.Bold if settings.value('bold') in (True, 'true') else QFont.Normal) if settings.contains('italic'): fmt.setFontItalic(settings.value('italic') in (True, 'true')) if settings.contains('underline'): fmt.setFontUnderline(settings.value('underline') in (True, 'true')) if settings.contains('textColor'): fmt.setForeground(QColor(settings.value('textColor'))) if settings.contains('backgroundColor'): fmt.setBackground(QColor(settings.value('backgroundColor'))) if settings.contains('underlineColor'): fmt.setUnderlineColor(QColor(settings.value('underlineColor')))
class TextFormatData(object): """Encapsulates all settings in the Fonts & Colors page for a scheme.""" def __init__(self, scheme): """Loads the data from scheme.""" self.font = None self.baseColors = {} self.defaultStyles = {} self.allStyles = {} self.load(scheme) def load(self, scheme): s = QSettings() s.beginGroup("fontscolors/" + scheme) # load font self.font = QFont(s.value("fontfamily", "monospace")) self.font.setPointSizeF(float(s.value("fontsize", 10.0))) # load base colors s.beginGroup("basecolors") for name in baseColors: if s.contains(name): self.baseColors[name] = QColor(s.value(name)) else: self.baseColors[name] = baseColorDefaults[name]() s.endGroup() # load default styles s.beginGroup("defaultstyles") for name in defaultStyles: self.defaultStyles[name] = f = QTextCharFormat(defaultStyleDefaults[name]) s.beginGroup(name) loadTextFormat(f, s) s.endGroup() s.endGroup() # load specific styles s.beginGroup("allstyles") for group, styles in allStyles: self.allStyles[group]= {} s.beginGroup(group) for name in styles: default = allStyleDefaults[group].get(name) self.allStyles[group][name] = f = QTextCharFormat(default) if default else QTextCharFormat() s.beginGroup(name) loadTextFormat(f, s) s.endGroup() s.endGroup() s.endGroup() def save(self, scheme): s = QSettings() s.beginGroup("fontscolors/" + scheme) # save font s.setValue("fontfamily", self.font.family()) s.setValue("fontsize", self.font.pointSizeF()) # save base colors for name in baseColors: s.setValue("basecolors/"+name, self.baseColors[name].name()) # save default styles s.beginGroup("defaultstyles") for name in defaultStyles: s.beginGroup(name) saveTextFormat(self.defaultStyles[name], s) s.endGroup() s.endGroup() # save all specific styles s.beginGroup("allstyles") for group, styles in allStyles: s.beginGroup(group) for name in styles: s.beginGroup(name) saveTextFormat(self.allStyles[group][name], s) s.endGroup() s.endGroup() s.endGroup() def textFormat(self, group, name): inherit = inherits[group].get(name) f = QTextCharFormat(self.defaultStyles[inherit]) if inherit else QTextCharFormat() f.merge(self.allStyles[group][name]) return f def palette(self): """Returns a basic palette with text, background, selection and selection background filled in.""" p = QApplication.palette() p.setColor(QPalette.Text, self.baseColors['text']) p.setColor(QPalette.Base, self.baseColors['background']) p.setColor(QPalette.HighlightedText, self.baseColors['selectiontext']) p.setColor(QPalette.Highlight, self.baseColors['selectionbackground']) return p
def draw(self, painter, size = None): """ :Arguments: painter : QPainter Opened painter on which to draw """ bounding_rect = QRectF() position = self.position transfer_function = self.transfer_function font = QFont(self.font) text_color = self.text_color line_color = self.line_color line_thickness = self.line_thickness value_range = self.value_range if size is None: viewport = painter.viewport() # viewport rectangle mat, ok = painter.worldMatrix().inverted() if not ok: raise ValueError("Transformation matrix of painter is singular.") viewport = mat.mapRect(viewport) else: viewport = size # First, prepare the gradient w = viewport.width() h = viewport.height() #print("Size of viewport: {0}x{1}".format(w, h)) gr = QLinearGradient() nb_values = ceil(w/5.0) brush_color = QColor() for i in range(int(nb_values)): brush_color.setRgbF(*transfer_function.rgba(i/nb_values)) gr.setColorAt(i/nb_values, brush_color) # Second, find its position metric = QFontMetricsF(font, painter.device()) font_test = [ str(i)*5 for i in range(10) ] lim_width = 0 lim_height = 0 for t in font_test: rect = metric.boundingRect(t) lim_width = max(lim_width, rect.width()) lim_height = max(lim_height, rect.height()) lim_height *= 3 length = self.scale_length shift_length = (1-length)/2 width = self.scale_width shift_width = self.scale_shift_width delta_value = value_range[1]-value_range[0] if position == "Top": scale_rect = QRectF(shift_length*w, shift_width*h, length*w, width*h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.left(), scale_rect.center().y()) gr.setFinalStop(scale_rect.right(), scale_rect.center().y()) start_pos = scale_rect.bottomLeft() end_pos = scale_rect.bottomRight() elif position == "Right": scale_rect = QRectF((1-shift_width-width)*w, shift_length*h, width*w, length*h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.center().x(), scale_rect.bottom()) gr.setFinalStop(scale_rect.center().x(), scale_rect.top()) start_pos = scale_rect.bottomLeft() end_pos = scale_rect.topLeft() elif position == "Bottom": scale_rect = QRectF(shift_length*w, (1-shift_width-width)*h, length*w, width*h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.left(), scale_rect.center().y()) gr.setFinalStop(scale_rect.right(), scale_rect.center().y()) start_pos = scale_rect.topLeft() end_pos = scale_rect.topRight() elif position == "Left": scale_rect = QRectF(shift_width*w, shift_length*h, width*w, length*h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.center().x(), scale_rect.bottom()) gr.setFinalStop(scale_rect.center().x(), scale_rect.top()) start_pos = scale_rect.bottomRight() end_pos = scale_rect.topRight() else: raise ValueError("Invalid scale position: %s" % position) shift_pos = (end_pos-start_pos)/delta_value if position in ["Left", "Right"]: is_vertical = True length = scale_rect.height() else: is_vertical = False length = scale_rect.width() # Get the ticks ticks = self.selectValues(length, is_vertical, painter) if len(ticks) == 0: return ticks_str, ticks_extra = self._tick2str(ticks) # Figure the shifts dist_to_bar = self.text_to_bar max_width = 0 max_height = 0 for t in ticks_str: rect = metric.boundingRect(t) max_width = max(rect.width(), max_width) max_height = max(rect.height(), max_height) if position == "Left": shift_left = dist_to_bar shift_top = None elif position == "Right": shift_left = -dist_to_bar-max_width shift_top = None elif position == "Top": shift_left = None shift_top = dist_to_bar else: shift_left = None shift_top = -dist_to_bar-max_height painter.save() painter.translate(viewport.topLeft()) #print("viewport.topLeft() = {0}x{1}".format(viewport.left(), viewport.top())) painter.setBrush(gr) line_pen = QPen(line_color) line_pen.setWidth(line_thickness) painter.setPen(line_pen) painter.drawRect(scale_rect) bounding_rect |= scale_rect #print("Scale rect: +{0}+{1}x{2}x{3}".format(scale_rect.left(), #scale_rect.top(), scale_rect.width(), scale_rect.height())) painter.setFont(font) painter.setPen(text_color) for ts,t in zip(ticks_str, ticks): r = metric.boundingRect(ts) pos = start_pos+shift_pos*(t-value_range[0]) if shift_left is None: pos.setX( pos.x() - r.width()/2 ) else: pos.setX( pos.x() + shift_left ) if shift_top is None: pos.setY( pos.y() - r.height()/2) else: pos.setY( pos.y() + shift_top ) r.moveTo(pos) real_rect = painter.drawText(r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, ts) bounding_rect |= real_rect if ticks_extra is not None or self.unit: unit = self.unit exp_width = width = space_width = 0 exp_txt = "" r = exp_r = unit_r = QRectF() exp_font = None if ticks_extra is not None: exp_txt = u"×10" r = metric.boundingRect(exp_txt) exp_font = QFont(font) exp_size = self.exp_size if exp_font.pixelSize() != -1: exp_font.setPixelSize(exp_size*exp_font.pixelSize()) else: exp_font.setPointSizeF(exp_size*exp_font.pointSizeF()) exp_metric = QFontMetricsF(exp_font, painter.device()) exp_r = exp_metric.boundingRect(ticks_extra) if unit: unit_r = metric.boundingRect(unit) total_width = r.width()+exp_r.width()+unit_r.width() total_height = max(r.height(),unit_r.height())+exp_r.height()/2 pos = scale_rect.topRight() log_debug("top right of scale bar = (%g,%g)" % (pos.x(), pos.y())) log_debug("Size of image = (%d,%d)" % (w,h)) log_debug("Size of text = (%g,%g)" % (total_width, total_height)) if position == "Bottom": pos.setY(pos.y() + scale_rect.height() + dist_to_bar) pos.setX(pos.x() - total_width) elif position == "Top": pos.setY(pos.y() - dist_to_bar - total_height) pos.setX(pos.x() - total_width) else: # position == "left" or "right" pos.setX(pos.x() - (scale_rect.width() + total_width)/2) if pos.x() < 0: pos.setX(dist_to_bar) elif pos.x()+total_width+dist_to_bar > w: pos.setX(w - total_width - dist_to_bar) pos.setY(pos.y() - dist_to_bar - total_height) log_debug("Display unit at position: (%g,%g)" % (pos.x(), pos.y())) if ticks_extra is not None: r.moveTo(pos) real_rect = painter.drawText(r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, exp_txt) bounding_rect |= real_rect pos.setX( pos.x() + r.width() ) pos.setY( pos.y() - metric.ascent()/2 ) exp_r.moveTo(pos) painter.setFont(exp_font) real_rect = painter.drawText(exp_r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, ticks_extra) bounding_rect |= real_rect pos.setY(pos.y() + metric.ascent()/2) if unit: pos.setX(pos.x() + space_width + exp_r.width()) unit_r.moveTo(pos) painter.setFont(font) real_rect = painter.drawText(unit_r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, unit) bounding_rect |= real_rect # Draw the ticks now painter.setPen(line_pen) tick_size = self.tick_size if is_vertical: width = scale_rect.width()*tick_size else: width = scale_rect.height()*tick_size pen_width = painter.pen().widthF() if pen_width == 0: pen_width = 1.0 for t in ticks: pos1 = start_pos + shift_pos*(t-value_range[0]) pos2 = QPointF(pos1) if is_vertical: pos1.setX(scale_rect.left() + pen_width) pos2.setX(pos1.x() + width - pen_width) painter.drawLine(pos1, pos2) pos1.setX(scale_rect.right() - pen_width) pos2.setX(pos1.x() - width + pen_width) painter.drawLine(pos1, pos2) else: pos1.setY(scale_rect.top() + pen_width) pos2.setY(pos1.y() + width - pen_width) painter.drawLine(pos1, pos2) pos1.setY(scale_rect.bottom() - pen_width) pos2.setY(pos1.y() - width + pen_width) painter.drawLine(pos1, pos2) painter.restore() bounding_rect = bounding_rect.adjusted(-pen_width, -pen_width, pen_width, pen_width) return bounding_rect
class TextFormatData(object): """Encapsulates all settings in the Fonts & Colors page for a scheme.""" def __init__(self, scheme): """Loads the data from scheme.""" self.font = None self.baseColors = {} self.defaultStyles = {} self.allStyles = {} self._inherits = {} self.load(scheme) def load(self, scheme): """Load the settings for the scheme. Called on init.""" s = QSettings() s.beginGroup("fontscolors/" + scheme) # load font defaultfont = "Lucida Console" if os.name == "nt" else "monospace" self.font = QFont(s.value("fontfamily", defaultfont, type(""))) self.font.setPointSizeF(s.value("fontsize", 10.0, float)) # load base colors s.beginGroup("basecolors") for name in baseColors: if s.contains(name): self.baseColors[name] = QColor(s.value(name, "", type(""))) else: self.baseColors[name] = baseColorDefaults[name]() s.endGroup() # get the list of supported styles from ly.colorize all_styles = ly.colorize.default_mapping() default_styles = set() for group, styles in all_styles: d = self._inherits[group] = {} for style in styles: if style.base: default_styles.add(style.base) d[style.name] = style.base default_scheme = ly.colorize.default_scheme # load default styles s.beginGroup("defaultstyles") for name in default_styles: self.defaultStyles[name] = f = QTextCharFormat() css = default_scheme[None].get(name) if css: css2fmt(css, f) s.beginGroup(name) self.loadTextFormat(f, s) s.endGroup() s.endGroup() # load specific styles s.beginGroup("allstyles") for group, styles in all_styles: self.allStyles[group]= {} s.beginGroup(group) for style in styles: self.allStyles[group][style.name] = f = QTextCharFormat() css = default_scheme[group].get(style.name) if css: css2fmt(css, f) s.beginGroup(style.name) self.loadTextFormat(f, s) s.endGroup() s.endGroup() s.endGroup() def save(self, scheme): """Save the settings to the scheme.""" s = QSettings() s.beginGroup("fontscolors/" + scheme) # save font s.setValue("fontfamily", self.font.family()) s.setValue("fontsize", self.font.pointSizeF()) # save base colors for name in baseColors: s.setValue("basecolors/"+name, self.baseColors[name].name()) # save default styles s.beginGroup("defaultstyles") for name in defaultStyles: s.beginGroup(name) self.saveTextFormat(self.defaultStyles[name], s) s.endGroup() s.endGroup() # save all specific styles s.beginGroup("allstyles") for group, styles in ly.colorize.default_mapping(): s.beginGroup(group) for style in styles: s.beginGroup(style.name) self.saveTextFormat(self.allStyles[group][style.name], s) s.endGroup() s.endGroup() s.endGroup() def textFormat(self, group, name): """Return a QTextCharFormat() for the specified group and name.""" inherit = self._inherits[group].get(name) f = QTextCharFormat(self.defaultStyles[inherit]) if inherit else QTextCharFormat() f.merge(self.allStyles[group][name]) return f def css_scheme(self): """Return a dictionary of css dictionaries representing this scheme. This can be fed to the ly.colorize.format_stylesheet() function. """ scheme = {} # base/default styles d = scheme[None] = {} for name, fmt in self.defaultStyles.items(): d[name] = fmt2css(fmt) # mode/group styles for mode, styles in self.allStyles.items(): d = scheme[mode] = {} for name, fmt in styles.items(): d[name] = fmt2css(fmt) return scheme def palette(self): """Return a basic palette with text, background, selection and selection background filled in.""" p = QApplication.palette() p.setColor(QPalette.Text, self.baseColors['text']) p.setColor(QPalette.Base, self.baseColors['background']) p.setColor(QPalette.HighlightedText, self.baseColors['selectiontext']) p.setColor(QPalette.Highlight, self.baseColors['selectionbackground']) return p def saveTextFormat(self, fmt, settings): """(Internal) Store one QTextCharFormat in the QSettings instance.""" if fmt.hasProperty(QTextFormat.FontWeight): settings.setValue('bold', fmt.fontWeight() >= 70) else: settings.remove('bold') if fmt.hasProperty(QTextFormat.FontItalic): settings.setValue('italic', fmt.fontItalic()) else: settings.remove('italic') if fmt.hasProperty(QTextFormat.TextUnderlineStyle): settings.setValue('underline', fmt.fontUnderline()) else: settings.remove('underline') if fmt.hasProperty(QTextFormat.ForegroundBrush): settings.setValue('textColor', fmt.foreground().color().name()) else: settings.remove('textColor') if fmt.hasProperty(QTextFormat.BackgroundBrush): settings.setValue('backgroundColor', fmt.background().color().name()) else: settings.remove('backgroundColor') if fmt.hasProperty(QTextFormat.TextUnderlineColor): settings.setValue('underlineColor', fmt.underlineColor().name()) else: settings.remove('underlineColor') def loadTextFormat(self, fmt, settings): """(Internal) Merge values from the QSettings instance into the QTextCharFormat.""" if settings.contains('bold'): fmt.setFontWeight(QFont.Bold if settings.value('bold', False, bool) else QFont.Normal) if settings.contains('italic'): fmt.setFontItalic(settings.value('italic', False, bool)) if settings.contains('underline'): fmt.setFontUnderline(settings.value('underline', False, bool)) if settings.contains('textColor'): fmt.setForeground(QColor(settings.value('textColor', '' , type("")))) if settings.contains('backgroundColor'): fmt.setBackground(QColor(settings.value('backgroundColor', '' , type("")))) if settings.contains('underlineColor'): fmt.setUnderlineColor(QColor(settings.value('underlineColor', '' , type(""))))