def draw_snake_spinner(painter, rect, angle, light, dark): painter.setRenderHint(QPainter.Antialiasing) if rect.width() > rect.height(): delta = (rect.width() - rect.height()) // 2 rect = rect.adjusted(delta, 0, -delta, 0) elif rect.height() > rect.width(): delta = (rect.height() - rect.width()) // 2 rect = rect.adjusted(0, delta, 0, -delta) disc_width = max(4, rect.width() // 10) drawing_rect = QRect(rect.x() + disc_width, rect.y() + disc_width, rect.width() - 2 * disc_width, rect.height() - 2 *disc_width) try: angle_for_width = math.degrees(math.atan2(1.3 * disc_width, drawing_rect.width())) except ZeroDivisionError: angle_for_width = 5 gradient = QConicalGradient(drawing_rect.center(), angle - angle_for_width) gradient.setColorAt(1, light) gradient.setColorAt(0, dark) painter.setPen(QPen(light, disc_width)) painter.drawArc(drawing_rect, 0, 360 * 16) pen = QPen(QBrush(gradient), disc_width) pen.setCapStyle(Qt.RoundCap) painter.setPen(pen) painter.drawArc(drawing_rect, angle * 16, (360 - 2 * angle_for_width) * 16)
def paintEvent(self, event): canvas_size = self.rect() width = self.current_pixmap_size.width() extrax = canvas_size.width() - width if extrax < 0: extrax = 0 x = int(extrax/2.) height = self.current_pixmap_size.height() extray = canvas_size.height() - height if extray < 0: extray = 0 y = int(extray/2.) target = QRect(x, y, width, height) p = QPainter(self) p.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) try: dpr = self.devicePixelRatioF() except AttributeError: dpr = self.devicePixelRatio() spmap = self.pixmap.scaled(target.size() * dpr, Qt.KeepAspectRatio, Qt.SmoothTransformation) spmap.setDevicePixelRatio(dpr) p.drawPixmap(target, spmap) if gprefs['bd_overlay_cover_size']: sztgt = target.adjusted(0, 0, 0, -4) f = p.font() f.setBold(True) p.setFont(f) sz = u'\u00a0%d x %d\u00a0'%(self.pixmap.width(), self.pixmap.height()) flags = Qt.AlignBottom|Qt.AlignRight|Qt.TextSingleLine szrect = p.boundingRect(sztgt, flags, sz) p.fillRect(szrect.adjusted(0, 0, 0, 4), QColor(0, 0, 0, 200)) p.setPen(QPen(QColor(255,255,255))) p.drawText(sztgt, flags, sz) p.end()
def drag_icon(self, cover, multiple): cover = cover.scaledToHeight(120, Qt.SmoothTransformation) if multiple: base_width = cover.width() base_height = cover.height() base = QImage(base_width+21, base_height+21, QImage.Format_ARGB32_Premultiplied) base.fill(QColor(255, 255, 255, 0).rgba()) p = QPainter(base) rect = QRect(20, 0, base_width, base_height) p.fillRect(rect, QColor('white')) p.drawRect(rect) rect.moveLeft(10) rect.moveTop(10) p.fillRect(rect, QColor('white')) p.drawRect(rect) rect.moveLeft(0) rect.moveTop(20) p.fillRect(rect, QColor('white')) p.save() p.setCompositionMode(p.CompositionMode_SourceAtop) p.drawImage(rect.topLeft(), cover) p.restore() p.drawRect(rect) p.end() cover = base return QPixmap.fromImage(cover)
def paint(self, painter, option, index): QStyledItemDelegate.paint(self, painter, option, index) style = QApplication.style() waiting = self.timer.isActive() and bool(index.data(Qt.UserRole)) if waiting: rect = QRect(0, 0, self.spinner_width, self.spinner_width) rect.moveCenter(option.rect.center()) draw_snake_spinner(painter, rect, self.angle, self.light_color, self.dark_color) else: # Ensure the cover is rendered over any selection rect style.drawItemPixmap(painter, option.rect, Qt.AlignTop|Qt.AlignHCenter, QPixmap(index.data(Qt.DecorationRole)))
def __call__(self, painter, rect, color_theme, title_block, subtitle_block, footer_block): painter.fillRect(rect, self.color1) r = QRect(0, int(title_block.position.y), rect.width(), title_block.height + subtitle_block.height + subtitle_block.line_spacing // 2 + title_block.leading) painter.save() p = QPainterPath() p.addRoundedRect(QRectF(r), 10, 10 * r.width()/r.height(), Qt.RelativeSize) painter.setClipPath(p) painter.setRenderHint(QPainter.Antialiasing) painter.fillRect(r, self.color2) painter.restore() r = QRect(0, 0, int(title_block.position.x), rect.height()) painter.fillRect(r, self.color2) return self.ccolor2, self.ccolor2, self.ccolor1
def draw(self, painter, width, palette): flags = self.FLAGS | (Qt.AlignRight if self.right_align else Qt.AlignLeft) rect = QRect(self.rect) if self.right_align: rect.setRight(width - self.SIDE_MARGIN) painter.setPen(palette.color(self.color_role) if self.override_color is None else self.override_color) br = painter.drawText(rect, flags, self.text) if self.swatch is not None: r = QRect(br.right() + self.SIDE_MARGIN // 2, br.top() + 2, br.height() - 4, br.height() - 4) painter.fillRect(r, self.swatch) br.setRight(r.right()) if self.is_overriden: painter.setPen(palette.color(QPalette.WindowText)) painter.drawLine(br.left(), br.top() + br.height() // 2, br.right(), br.top() + br.height() // 2)
def paintEvent(self, event): if self.pixmap.isNull(): return canvas_size = self.rect() width = self.current_pixmap_size.width() extrax = canvas_size.width() - width if extrax < 0: extrax = 0 x = int(extrax / 2.0) height = self.current_pixmap_size.height() extray = canvas_size.height() - height if extray < 0: extray = 0 y = int(extray / 2.0) target = QRect(x, y, min(canvas_size.width(), width), min(canvas_size.height(), height)) p = QPainter(self) p.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) p.drawPixmap(target, self.pixmap.scaled(target.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)) p.end()
def draw_snake_spinner(painter, rect, angle, light, dark): painter.setRenderHint(QPainter.Antialiasing) if rect.width() > rect.height(): delta = (rect.width() - rect.height()) // 2 rect = rect.adjusted(delta, 0, -delta, 0) elif rect.height() > rect.width(): delta = (rect.height() - rect.width()) // 2 rect = rect.adjusted(0, delta, 0, -delta) disc_width = max(3, min(rect.width() // 10, 8)) drawing_rect = QRect(rect.x() + disc_width, rect.y() + disc_width, rect.width() - 2 * disc_width, rect.height() - 2 *disc_width) gap = 60 # degrees gradient = QConicalGradient(drawing_rect.center(), angle - gap // 2) gradient.setColorAt((360 - gap//2)/360.0, light) gradient.setColorAt(0, dark) pen = QPen(QBrush(gradient), disc_width) pen.setCapStyle(Qt.RoundCap) painter.setPen(pen) painter.drawArc(drawing_rect, angle * 16, (360 - gap) * 16)
def paintEvent(self, ev): if self.before_image is None: return canvas_size = self.rect() p = QPainter(self) p.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) p.drawPixmap(canvas_size, self.before_image, self.before_image.rect()) if self.after_image is not None: width = self._current_width iw = self.after_image.width() sh = min(self.after_image.height(), canvas_size.height()) if self.flip_forwards: source = QRect(max(0, iw - width), 0, width, sh) else: source = QRect(0, 0, width, sh) target = QRect(source) target.moveLeft(0) p.drawPixmap(target, self.after_image, source) p.end()
def do_layout(self): fm = self.fontMetrics() bounding_rect = lambda text: fm.boundingRect(0, 0, 10000, 10000, Cell.FLAGS, text) line_spacing = 2 side_margin = Cell.SIDE_MARGIN self.rows = [] ypos = line_spacing + (1 if self.is_first else 0) if "href" in self.data: name = self.data["href"] if isinstance(name, list): name = self.html_name br1 = bounding_rect(name) sel = self.data["selector"] or "" if self.data["type"] == "inline": sel = 'style=""' br2 = bounding_rect(sel) self.hyperlink_rect = QRect(side_margin, ypos, br1.width(), br1.height()) self.rows.append( [ Cell(name, self.hyperlink_rect, color_role=QPalette.Link), Cell(sel, QRect(br1.right() + side_margin, ypos, br2.width(), br2.height()), right_align=True), ] ) ypos += max(br1.height(), br2.height()) + 2 * line_spacing for prop in self.data["properties"]: text = prop.name + ":\xa0" br1 = bounding_rect(text) vtext = prop.value + "\xa0" + ("!" if prop.important else "") + prop.important br2 = bounding_rect(vtext) self.rows.append( [ Cell( text, QRect(side_margin, ypos, br1.width(), br1.height()), color_role=QPalette.LinkVisited, is_overriden=prop.is_overriden, ), Cell( vtext, QRect(br1.right() + side_margin, ypos, br2.width(), br2.height()), swatch=prop.color, is_overriden=prop.is_overriden, ), ] ) ypos += max(br1.height(), br2.height()) + line_spacing self.height_hint = ypos + line_spacing self.width_hint = max(row[-1].rect.right() + side_margin for row in self.rows) if self.rows else 0
def paintEvent(self, event): QWidget.paintEvent(self, event) pmap = self._pixmap if pmap.isNull(): return w, h = pmap.width(), pmap.height() ow, oh = w, h cw, ch = self.rect().width(), self.rect().height() scaled, nw, nh = fit_image(w, h, cw, ch) if scaled: pmap = pmap.scaled(int(nw*pmap.devicePixelRatio()), int(nh*pmap.devicePixelRatio()), Qt.IgnoreAspectRatio, Qt.SmoothTransformation) w, h = int(pmap.width()/pmap.devicePixelRatio()), int(pmap.height()/pmap.devicePixelRatio()) x = int(abs(cw - w)/2.) y = int(abs(ch - h)/2.) target = QRect(x, y, w, h) p = QPainter(self) p.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) p.drawPixmap(target, pmap) if self.draw_border: pen = QPen() pen.setWidth(self.BORDER_WIDTH) p.setPen(pen) p.drawRect(target) if self.show_size: sztgt = target.adjusted(0, 0, 0, -4) f = p.font() f.setBold(True) p.setFont(f) sz = u'\u00a0%d x %d\u00a0'%(ow, oh) flags = Qt.AlignBottom|Qt.AlignRight|Qt.TextSingleLine szrect = p.boundingRect(sztgt, flags, sz) p.fillRect(szrect.adjusted(0, 0, 0, 4), QColor(0, 0, 0, 200)) p.setPen(QPen(QColor(255,255,255))) p.drawText(sztgt, flags, sz) p.end()
def __call__(self, painter, rect, color_theme, title_block, subtitle_block, footer_block): painter.fillRect(rect, self.color1) y = rect.height() - rect.height() // 3 r = QRect(rect) r.setBottom(y) painter.fillRect(rect, self.color1) r = QRect(rect) r.setTop(y) painter.fillRect(r, self.color2) return self.ccolor1, self.ccolor1, self.ccolor2
def do_layout(self): fm = self.fontMetrics() bounding_rect = lambda text: fm.boundingRect(0, 0, 10000, 10000, Cell.FLAGS, text) line_spacing = 2 side_margin = Cell.SIDE_MARGIN self.rows = [] ypos = line_spacing + (1 if self.is_first else 0) if 'href' in self.data: name = self.data['href'] if isinstance(name, list): name = self.html_name br1 = bounding_rect(name) sel = self.data['selector'] or '' if self.data['type'] == 'inline': sel = 'style=""' br2 = bounding_rect(sel) self.hyperlink_rect = QRect(side_margin, ypos, br1.width(), br1.height()) self.rows.append([ Cell(name, self.hyperlink_rect, color_role=QPalette.Link), Cell(sel, QRect(br1.right() + side_margin, ypos, br2.width(), br2.height()), right_align=True) ]) ypos += max(br1.height(), br2.height()) + 2 * line_spacing self.lines_for_copy.append(name + ' ' + sel) for prop in self.data['properties']: text = prop.name + ':\xa0' br1 = bounding_rect(text) vtext = prop.value + '\xa0' + ('!' if prop.important else '') + prop.important br2 = bounding_rect(vtext) self.rows.append([ Cell(text, QRect(side_margin, ypos, br1.width(), br1.height()), color_role=QPalette.LinkVisited, is_overriden=prop.is_overriden), Cell(vtext, QRect(br1.right() + side_margin, ypos, br2.width(), br2.height()), swatch=prop.color, is_overriden=prop.is_overriden) ]) self.lines_for_copy.append(text + vtext) if prop.is_overriden: self.lines_for_copy[-1] += ' [overriden]' ypos += max(br1.height(), br2.height()) + line_spacing self.lines_for_copy.append('--------------------------\n') self.height_hint = ypos + line_spacing self.width_hint = max(row[-1].rect.right() + side_margin for row in self.rows) if self.rows else 0
def setupUi(self): self.setObjectName("Dialog") self.resize(1024, 700) self.setWindowIcon(QIcon(I('convert.png'))) self.gridLayout = QGridLayout(self) self.gridLayout.setObjectName("gridLayout") self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") self.input_label = QLabel(self) self.input_label.setObjectName("input_label") self.horizontalLayout.addWidget(self.input_label) self.input_formats = QComboBox(self) self.input_formats.setSizeAdjustPolicy( QComboBox.AdjustToMinimumContentsLengthWithIcon) self.input_formats.setMinimumContentsLength(5) self.input_formats.setObjectName("input_formats") self.horizontalLayout.addWidget(self.input_formats) self.opt_individual_saved_settings = QCheckBox(self) self.opt_individual_saved_settings.setObjectName( "opt_individual_saved_settings") self.horizontalLayout.addWidget(self.opt_individual_saved_settings) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) self.label_2 = QLabel(self) self.label_2.setObjectName("label_2") self.horizontalLayout.addWidget(self.label_2) self.output_formats = QComboBox(self) self.output_formats.setSizeAdjustPolicy( QComboBox.AdjustToMinimumContentsLengthWithIcon) self.output_formats.setMinimumContentsLength(5) self.output_formats.setObjectName("output_formats") self.horizontalLayout.addWidget(self.output_formats) self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 2) self.groups = QListView(self) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.groups.sizePolicy().hasHeightForWidth()) self.groups.setSizePolicy(sizePolicy) self.groups.setTabKeyNavigation(True) self.groups.setIconSize(QSize(48, 48)) self.groups.setWordWrap(True) self.groups.setObjectName("groups") self.gridLayout.addWidget(self.groups, 1, 0, 3, 1) self.scrollArea = QScrollArea(self) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(4) sizePolicy.setVerticalStretch(10) sizePolicy.setHeightForWidth( self.scrollArea.sizePolicy().hasHeightForWidth()) self.scrollArea.setSizePolicy(sizePolicy) self.scrollArea.setFrameShape(QFrame.NoFrame) self.scrollArea.setLineWidth(0) self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName("scrollArea") self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 810, 494)) self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents") self.verticalLayout_3 = QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) self.verticalLayout_3.setObjectName("verticalLayout_3") self.stack = QStackedWidget(self.scrollAreaWidgetContents) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.stack.sizePolicy().hasHeightForWidth()) self.stack.setSizePolicy(sizePolicy) self.stack.setObjectName("stack") self.page = QWidget() self.page.setObjectName("page") self.stack.addWidget(self.page) self.page_2 = QWidget() self.page_2.setObjectName("page_2") self.stack.addWidget(self.page_2) self.verticalLayout_3.addWidget(self.stack) self.scrollArea.setWidget(self.scrollAreaWidgetContents) self.gridLayout.addWidget(self.scrollArea, 1, 1, 1, 1) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok | QDialogButtonBox.RestoreDefaults) self.buttonBox.setObjectName("buttonBox") self.gridLayout.addWidget(self.buttonBox, 3, 1, 1, 1) self.help = QTextEdit(self) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.help.sizePolicy().hasHeightForWidth()) self.help.setSizePolicy(sizePolicy) self.help.setMaximumSize(QSize(16777215, 130)) self.help.setObjectName("help") self.gridLayout.addWidget(self.help, 2, 1, 1, 1) self.input_label.setBuddy(self.input_formats) self.label_2.setBuddy(self.output_formats) self.input_label.setText(_("&Input format:")) self.opt_individual_saved_settings.setText( _("Use &saved conversion settings for individual books")) self.label_2.setText(_("&Output format:")) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject)
def paint_embossed_emblem(self, pixmap, painter, orect, right_adjust, left=True): drect = QRect(orect) pw = int(pixmap.width() / pixmap.devicePixelRatio()) ph = int(pixmap.height() / pixmap.devicePixelRatio()) if left: drect.setLeft(drect.left() + right_adjust) drect.setRight(drect.left() + pw) else: drect.setRight(drect.right() - right_adjust) drect.setLeft(drect.right() - pw + 1) drect.setBottom(drect.bottom() - self.title_height) drect.setTop(drect.bottom() - ph) painter.drawPixmap(drect, pixmap)
def decoration_for_style(palette, style, icon_size, device_pixel_ratio, is_dark): style_key = (is_dark, icon_size, device_pixel_ratio, tuple((k, style[k]) for k in sorted(style))) sentinel = object() ans = decoration_cache.get(style_key, sentinel) if ans is not sentinel: return ans ans = None kind = style.get('kind') if kind == 'color': key = 'dark' if is_dark else 'light' val = style.get(key) if val is None: which = style.get('which') val = (builtin_colors_dark if is_dark else builtin_colors_light).get(which) if val is None: val = style.get('background-color') if val is not None: ans = QColor(val) elif kind == 'decoration': which = style.get('which') if which is not None: q = builtin_decorations.get(which) if q is not None: style = q sz = int(math.ceil(icon_size * device_pixel_ratio)) canvas = QImage(sz, sz, QImage.Format.Format_ARGB32) canvas.fill(Qt.GlobalColor.transparent) canvas.setDevicePixelRatio(device_pixel_ratio) p = QPainter(canvas) p.setRenderHint(QPainter.RenderHint.Antialiasing, True) p.setPen(palette.color(QPalette.ColorRole.WindowText)) irect = QRect(0, 0, icon_size, icon_size) adjust = -2 text_rect = p.drawText( irect.adjusted(0, adjust, 0, adjust), Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignTop, 'a') p.drawRect(irect) fm = p.fontMetrics() pen = p.pen() if 'text-decoration-color' in style: pen.setColor(QColor(style['text-decoration-color'])) lstyle = style.get('text-decoration-style') or 'solid' q = { 'dotted': Qt.PenStyle.DotLine, 'dashed': Qt.PenStyle.DashLine, }.get(lstyle) if q is not None: pen.setStyle(q) lw = fm.lineWidth() if lstyle == 'double': lw * 2 pen.setWidth(fm.lineWidth()) q = style.get('text-decoration-line') or 'underline' pos = text_rect.bottom() height = irect.bottom() - pos if q == 'overline': pos = height elif q == 'line-through': pos = text_rect.center().y() - adjust - lw // 2 p.setPen(pen) if lstyle == 'wavy': p.drawPath(wavy_path(icon_size, height, pos)) else: p.drawLine(0, pos, irect.right(), pos) p.end() ans = QPixmap.fromImage(canvas) elif 'background-color' in style: ans = QColor(style['background-color']) decoration_cache[style_key] = ans return ans
def __init__(self, plugin_action): self.gui = plugin_action.gui self.opts = plugin_action.opts QWidget.__init__(self) self.l = QVBoxLayout() self.setLayout(self.l) # ~~~~~~~~ Create the runtime options group box ~~~~~~~~ self.cfg_runtime_options_gb = QGroupBox(self) self.cfg_runtime_options_gb.setTitle(_('Runtime options')) self.l.addWidget(self.cfg_runtime_options_gb) self.cfg_runtime_options_qvl = QVBoxLayout(self.cfg_runtime_options_gb) # ~~~~~~~~ Disable caching checkbox ~~~~~~~~ self.cfg_disable_caching_checkbox = QCheckBox(_('Disable caching')) self.cfg_disable_caching_checkbox.setObjectName('cfg_disable_caching_checkbox') self.cfg_disable_caching_checkbox.setToolTip(_('Force reload of reader database')) self.cfg_disable_caching_checkbox.setChecked(False) self.cfg_runtime_options_qvl.addWidget(self.cfg_disable_caching_checkbox) # ~~~~~~~~ plugin logging checkbox ~~~~~~~~ self.cfg_plugin_debug_log_checkbox = QCheckBox(_('Enable debug logging for Annotations plugin')) self.cfg_plugin_debug_log_checkbox.setObjectName('cfg_plugin_debug_log_checkbox') self.cfg_plugin_debug_log_checkbox.setToolTip(_('Print plugin diagnostic messages to console')) self.cfg_plugin_debug_log_checkbox.setChecked(False) self.cfg_runtime_options_qvl.addWidget(self.cfg_plugin_debug_log_checkbox) # ~~~~~~~~ libiMobileDevice logging checkbox ~~~~~~~~ self.cfg_libimobiledevice_debug_log_checkbox = QCheckBox(_('Enable debug logging for libiMobileDevice')) self.cfg_libimobiledevice_debug_log_checkbox.setObjectName('cfg_libimobiledevice_debug_log_checkbox') self.cfg_libimobiledevice_debug_log_checkbox.setToolTip(_('Print libiMobileDevice debug messages to console')) self.cfg_libimobiledevice_debug_log_checkbox.setChecked(False) self.cfg_libimobiledevice_debug_log_checkbox.setEnabled(LIBIMOBILEDEVICE_AVAILABLE) self.cfg_runtime_options_qvl.addWidget(self.cfg_libimobiledevice_debug_log_checkbox) # ~~~~~~~~ Create the Annotations options group box ~~~~~~~~ self.cfg_annotation_options_gb = QGroupBox(self) self.cfg_annotation_options_gb.setTitle(_('Annotation options')) self.l.addWidget(self.cfg_annotation_options_gb) self.cfg_annotation_options_qgl = QGridLayout(self.cfg_annotation_options_gb) current_row = 0 # Add the label/combobox for annotations destination self.cfg_annotations_destination_label = QLabel(_('<b>Add fetched annotations to<b>')) self.cfg_annotations_destination_label.setAlignment(Qt.AlignLeft) self.cfg_annotation_options_qgl.addWidget(self.cfg_annotations_destination_label, current_row, 0) current_row += 1 self.cfg_annotations_destination_comboBox = QComboBox(self.cfg_annotation_options_gb) self.cfg_annotations_destination_comboBox.setObjectName('cfg_annotations_destination_comboBox') self.cfg_annotations_destination_comboBox.setToolTip(_('Custom field to store annotations')) self.cfg_annotation_options_qgl.addWidget(self.cfg_annotations_destination_comboBox, current_row, 0) # Populate annotations_field combobox db = self.gui.current_db all_custom_fields = db.custom_field_keys() self.custom_fields = {} for custom_field in all_custom_fields: field_md = db.metadata_for_field(custom_field) if field_md['datatype'] in ['comments']: self.custom_fields[field_md['name']] = {'field': custom_field, 'datatype': field_md['datatype']} all_fields = self.custom_fields.keys() + ['Comments'] for cf in sorted(all_fields): self.cfg_annotations_destination_comboBox.addItem(cf) # Add CC Wizard self.cfg_annotations_wizard = QToolButton() self.cfg_annotations_wizard.setIcon(QIcon(I('wizard.png'))) self.cfg_annotations_wizard.setToolTip(_("Create a custom column to store annotations")) self.cfg_annotations_wizard.clicked.connect(partial(self.launch_cc_wizard, 'Annotations')) self.cfg_annotation_options_qgl.addWidget(self.cfg_annotations_wizard, current_row, 2) current_row += 1 # ~~~~~~~~ Add a horizontal line ~~~~~~~~ self.cfg_appearance_hl = QFrame(self) self.cfg_appearance_hl.setGeometry(QRect(0, 0, 1, 3)) self.cfg_appearance_hl.setFrameShape(QFrame.HLine) self.cfg_appearance_hl.setFrameShadow(QFrame.Raised) self.cfg_annotation_options_qgl.addWidget(self.cfg_appearance_hl, current_row, 0) current_row += 1 # ~~~~~~~~ Add the Modify… button ~~~~~~~~ self.cfg_annotations_appearance_pushbutton = QPushButton(_("Modify appearance…")) self.cfg_annotations_appearance_pushbutton.clicked.connect(self.configure_appearance) self.cfg_annotation_options_qgl.addWidget(self.cfg_annotations_appearance_pushbutton, current_row, 0) current_row += 1 self.spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.cfg_annotation_options_qgl.addItem(self.spacerItem, current_row, 0, 1, 1) # ~~~~~~~~ Compilations group box ~~~~~~~~ self.cfg_compilation_options_gb = QGroupBox(self) self.cfg_compilation_options_gb.setTitle(_('Compilations')) self.l.addWidget(self.cfg_compilation_options_gb) self.cfg_compilation_options_qgl = QGridLayout(self.cfg_compilation_options_gb) current_row = 0 # News clippings self.cfg_news_clippings_checkbox = QCheckBox(_('Collect News clippings')) self.cfg_news_clippings_checkbox.setObjectName('cfg_news_clippings_checkbox') self.cfg_compilation_options_qgl.addWidget(self.cfg_news_clippings_checkbox, current_row, 0) self.cfg_news_clippings_lineEdit = QLineEdit() self.cfg_news_clippings_lineEdit.setObjectName('cfg_news_clippings_lineEdit') self.cfg_news_clippings_lineEdit.setToolTip(_('Title for collected news clippings')) self.cfg_compilation_options_qgl.addWidget(self.cfg_news_clippings_lineEdit, current_row, 1) # ~~~~~~~~ End of construction zone ~~~~~~~~ self.resize(self.sizeHint()) # Restore state of controls, populate annotations combobox self.controls = inventory_controls(self, dump_controls=False) restore_state(self) self.populate_annotations() # Hook changes to annotations_destination_combobox # self.connect(self.cfg_annotations_destination_comboBox, # pyqtSignal('currentIndexChanged(const QString &)'), # self.annotations_destination_changed) self.cfg_annotations_destination_comboBox.currentIndexChanged.connect(self.annotations_destination_changed) # Hook changes to diagnostic checkboxes self.cfg_disable_caching_checkbox.stateChanged.connect(self.restart_required) self.cfg_libimobiledevice_debug_log_checkbox.stateChanged.connect(self.restart_required) self.cfg_plugin_debug_log_checkbox.stateChanged.connect(self.restart_required) # Hook changes to News clippings, initialize self.cfg_news_clippings_checkbox.stateChanged.connect(self.news_clippings_toggled) self.news_clippings_toggled(self.cfg_news_clippings_checkbox.checkState()) self.cfg_news_clippings_lineEdit.editingFinished.connect(self.news_clippings_destination_changed) # Launch the annotated_books_scanner field = get_cc_mapping('annotations', 'field', 'Comments') self.annotated_books_scanner = InventoryAnnotatedBooks(self.gui, field) self.annotated_books_scanner.signal.connect(self.inventory_complete) # self.connect(self.annotated_books_scanner, self.annotated_books_scanner.signal, # self.inventory_complete) QTimer.singleShot(1, self.start_inventory)
def _paintGroupBox(self, rect, title): painter = QPainter(self) qDrawShadeRect(painter, rect, self.palette(), True) if len(title) > 0: fnt = self.font() fnt.setPointSize(fnt.pointSize() - 1) offset = 5 asterix = ' *' twidth = QFontMetrics(fnt).width(title) awidth = QFontMetrics(fnt).width(asterix) width = twidth + awidth + 2 * offset height = QFontMetrics(fnt).height() rect = QRect(rect.left() + 2 * offset, rect.top() - height / 2 + 1, width, height) painter.fillRect(rect, self.palette().color(self.backgroundRole())) painter.setFont(fnt) painter.drawText( QRect(rect.left() + offset, rect.top(), twidth, rect.height()), Qt.AlignLeft, title) painter.setPen(Qt.red) painter.drawText( QRect(rect.left() + offset + twidth, rect.top(), awidth, rect.height()), Qt.AlignRight, asterix)
def rect_at(self, frac): return QRect(self.point_at(frac), self.size())
def add_roca(self, position): y, x = position rect = QRect(1 + SIZE_TILE * x, 1 + SIZE_TILE * y, SIZE_TILE, SIZE_TILE) self.columns[y][x] = (rect, 'roca')
def geometry(self): return QRect()
def _setupUi(self): settings = Settings() settings.beginGroup('Browser-View-Settings') windowGeometry = settings.value('WindowGeometry', b'') keys = [ ('LocationBarWidth', int), ('WebSearchBarWidth', int), ('SideBarWidth', int), ('WebViewWidth', int), ('SideBar', str), ] uiState = {} for key, typ in keys: if settings.contains(key): uiState[key] = typ(settings.value(key)) settings.endGroup() widget = QWidget(self) widget.setCursor(Qt.ArrowCursor) self.setCentralWidget(widget) self._mainLayout = QVBoxLayout(widget) self._mainLayout.setContentsMargins(0, 0, 0, 0) self._mainLayout.setSpacing(0) self._mainSplitter = QSplitter(self) self._mainSplitter.setObjectName('sidebar-splitter') self._tabWidget = TabWidget(self) self._superMenu = QMenu(self) self._navigationToolbar = NavigationBar(self) self._bookmarksToolbar = BookmarksToolbar(self) self._tabModel = TabModel(self, self) self._tabMruModel = TabMruModel(self, self) self._tabMruModel.setSourceModel(self._tabModel) self._navigationContainer = NavigationContainer(self) self._navigationContainer.addWidget(self._navigationToolbar) self._navigationContainer.addWidget(self._bookmarksToolbar) self._navigationContainer.setTabBar(self._tabWidget.tabBar()) self._mainSplitter.addWidget(self._tabWidget) self._mainSplitter.setCollapsible(0, False) self._mainLayout.addWidget(self._navigationContainer) self._mainLayout.addWidget(self._mainSplitter) self._statusBar = StatusBar(self) self._statusBar.setObjectName('mainwindow-statusbar') self._statusBar.setCursor(Qt.ArrowCursor) self.setStatusBar(self._statusBar) self._progressBar = ProgressBar(self._statusBar) self._ipLabel = QLabel(self) self._ipLabel.setObjectName('statusbar-ip-label') self._ipLabel.setToolTip('IP Address of current page') self._statusBar.addPermanentWidget(self._progressBar) self._statusBar.addPermanentWidget(self.ipLabel()) downloadsButton = DownloadsButton(self) self._statusBar.addButton(downloadsButton) self._navigationToolbar.addToolButton(downloadsButton) desktop = gVar.app.desktop() windowWidth = desktop.availableGeometry().width() / 1.3 windowHeight = desktop.availableGeometry().height() / 1.3 # Let the WM decides where to put new browser window if self._windowType not in (const.BW_FirstAppWindow, const.BW_MacFirstWindow) and \ gVar.app.getWindow(): if const.OS_WIN: # Windows WM places every new window in the middle of screen .. for some reason p = gVar.app.getWindow().geometry().topLeft() p.setX(p.x() + 30) p.setY(p.y() + 30) if not desktop.availableGeometry( gVar.app.getWindow()).contains(p): p.setX( desktop.availableGeometry(gVar.app.getWindow()).x() + 30) p.setY( desktop.availableGeometry(gVar.app.getWindow()).y() + 30) self.setGeometry(QRect(p, gVar.app.getWindow().size())) else: self.resize(gVar.app.getWindow().size()) elif not self.restoreGeometry(windowGeometry): if const.OS_WIN: self.setGeometry( QRect( desktop.availableGeometry(gVar.app.getWindow()).x() + 30, desktop.availableGeometry(gVar.app.getWindow()).y() + 30, windowWidth, windowHeight)) else: self.resize(windowWidth, windowHeight) self._restoreUiState(uiState) # Set some sane minimum width self.setMinimumWidth(300)
def paintEvent(self, event): """ overload of paintEvent Qt function. Draw every stacked images with their proprieties (i.e.: opacity). Stack still has the same size after operation. Image are scaled during the process. QLabel's size is equals to maximum width & height found while reading images. Arguments: ev {QPaintEvent} -- A paint event which trigger display. """ if not self.images: return # new label size area_w = 0 area_h = 0 # Zoom zoom = self.zoom() # Init QPainter. painter = QPainter(self) # Draw every stacked images. # From the bottom of the stack to the top. for i in range(0, len(self.images)): # Opacity painter.setOpacity(self.opacities[i]) # Scale and Draw image = self.images[i] _w = image.width() * zoom _h = image.height() * zoom if _w > area_w: area_w = _w if _h > area_h: area_h = _h painter.drawImage( self.xx[i] * zoom, self.yy[i] * zoom, image.scaled( _w, _h, Qt.KeepAspectRatio, Qt.SmoothTransformation ) ) if self.draw_rect is True: painter.setPen(QPen(self.rect_color)) painter.drawRect(QRect(self.l_pos, self.r_pos)) self.setFixedSize(area_w, area_h)
def save(self, filename: str, do_crop: bool=False): """Save a RenderIrea as one image on disk. Arguments: filename {str} -- The filename of the new image. """ if not self.images: return # new label size dst_w = 0 dst_h = 0 # Zoom zoom = self.zoom() # Current number of images into the stack. nbimg = len(self.images) # Find the current size of the output image. images = [] for i in range(0, nbimg): image = self.images[i] _w = image.width() * zoom _h = image.height() * zoom if _w > dst_w: dst_w = _w if _h > dst_h: dst_h = _h # Scale now images.append( image.scaled( _w, _h, Qt.KeepAspectRatio, Qt.SmoothTransformation )) # Output image # ARGB since we can have all types of images (colors/grayscale/alpha channel) dst = QImage(dst_w, dst_h, QImage.Format_ARGB32) dst.fill(0) # black pixels everywhere # Init QPainter. painter = QPainter() painter.begin(dst) # Begin to draw inside the `dst` Image # Draw every stacked images. # From the bottom of the stack to the top. for i in range(0, nbimg): # Opacity painter.setOpacity(self.opacities[i]) painter.drawImage( self.xx[i] * zoom, self.yy[i] * zoom, images[i] ) painter.end() # Crop or not to crop? if do_crop and self.draw_rect: rect = QRect(self.l_pos, self.r_pos) dst = dst.copy(rect) # Save image, max quality dst.save(filename, None, 100)
def heightForWidth(self, width): return self.do_layout(QRect(0, 0, width, 0), apply_geometry=False)
def paintEvent(self, event): ''' @param: event QPaintEvent ''' p = QPainter(self) # Just draw separator if self._bookmark.isSeparator(): opt = QStyleOption() opt.initFrom(self) opt.state |= QStyle.State_Horizontal self.style().drawPrimitive(QStyle.PE_IndicatorToolBarSeparator, opt, p) return option = QStyleOptionButton() self.initStyleOption(option) # We are manually drawing the arrow option.features &= ~QStyleOptionButton.HasMenu # Draw button base (only under mouse, this is autoraise button) if self.isDown() or self.hitButton(self.mapFromGlobal(QCursor.pos())): option.state |= QStyle.State_AutoRaise | QStyle.State_Raised self.style().drawPrimitive(QStyle.PE_PanelButtonTool, option, p, self) if self.isDown(): shiftX = self.style().pixelMetric(QStyle.PM_ButtonShiftHorizontal, option, self) shiftY = self.style().pixelMetric(QStyle.PM_ButtonShiftVertical, option, self) else: shiftX = 0 shiftY = 0 height = option.rect.height() center = height / 2 + option.rect.top() + shiftY iconSize = 16 iconYPos = center - iconSize / 2 leftPosition = self.PADDING + shiftX rightPosition = option.rect.right() - self.PADDING # Draw icon if not self._showOnlyText: iconRect = QRect(leftPosition, iconYPos, iconSize, iconSize) p.drawPixmap( QStyle.visualRect(option.direction, option.rect, iconRect), self._bookmark.icon().pixmap(iconSize)) leftPosition = iconRect.right() + self.PADDING # Draw menu arrow if not self._showOnlyIcon and self.menu(): arrowSize = 8 opt = QStyleOption() opt.initFrom(self) rect = QRect(rightPosition - 8, center - arrowSize / 2, arrowSize, arrowSize) opt.rect = QStyle.visualRect(option.direction, option.rect, rect) opt.state &= ~QStyle.State_MouseOver self.style().drawPrimitive(QStyle.PE_IndicatorArrowDown, opt, p, self) rightPosition = rect.left() - self.PADDING # Draw text if not self._showOnlyIcon: textWidth = rightPosition - leftPosition textYPos = center - self.fontMetrics().height() / 2 txt = self.fontMetrics().elidedText(self._bookmark.title(), Qt.ElideRight, textWidth) textRect = QRect(leftPosition, textYPos, textWidth, self.fontMetrics().height()) self.style().drawItemText( p, QStyle.visualRect(option.direction, option.rect, textRect), Qt.TextSingleLine | Qt.AlignCenter, option.palette, True, txt)
def paint_embossed_emblem(self, pixmap, painter, orect, right_adjust, left=True): drect = QRect(orect) if left: drect.setLeft(drect.left() + right_adjust) drect.setRight(drect.left() + pixmap.width()) else: drect.setRight(drect.right() - right_adjust) drect.setLeft(drect.right() - pixmap.width() + 1) drect.setBottom(drect.bottom() - self.title_height) drect.setTop(drect.bottom() - pixmap.height()) painter.drawPixmap(drect, pixmap)
def dump(self, items, out_stream, pdf_metadata): opts = self.opts page_size = get_page_size(self.opts) xdpi, ydpi = self.view.logicalDpiX(), self.view.logicalDpiY() def margin(which): val = getattr(opts, 'pdf_page_margin_' + which) if val == 0.0: val = getattr(opts, 'margin_' + which) return val ml, mr, mt, mb = map(margin, 'left right top bottom'.split()) # We cannot set the side margins in the webview as there is no right # margin for the last page (the margins are implemented with # -webkit-column-gap) self.doc = PdfDevice(out_stream, page_size=page_size, left_margin=ml, top_margin=0, right_margin=mr, bottom_margin=0, xdpi=xdpi, ydpi=ydpi, errors=self.log.error, debug=self.log.debug, compress=not opts.uncompressed_pdf, opts=opts, mark_links=opts.pdf_mark_links, page_margins=(ml, mr, mt, mb)) self.footer = opts.pdf_footer_template if self.footer: self.footer = self.footer.strip() if not self.footer and opts.pdf_page_numbers: self.footer = '<p style="text-align:center; text-indent: 0">_PAGENUM_</p>' self.header = opts.pdf_header_template if self.header: self.header = self.header.strip() min_margin = 1.5 * opts._final_base_font_size if self.footer and mb < min_margin: self.log.warn('Bottom margin is too small for footer, increasing it to %.1fpts' % min_margin) mb = min_margin if self.header and mt < min_margin: self.log.warn('Top margin is too small for header, increasing it to %.1fpts' % min_margin) mt = min_margin self.page.setViewportSize(QSize(self.doc.width(), self.doc.height())) self.render_queue = items self.total_items = len(items) mt, mb = map(self.doc.to_px, (mt, mb)) self.margin_top, self.margin_bottom = map(lambda x:int(floor(x)), (mt, mb)) self.painter = QPainter(self.doc) try: self.book_language = pdf_metadata.mi.languages[0] except Exception: self.book_language = 'eng' self.doc.set_metadata(title=pdf_metadata.title, author=pdf_metadata.author, tags=pdf_metadata.tags, mi=pdf_metadata.mi) self.doc_title = pdf_metadata.title self.doc_author = pdf_metadata.author self.painter.save() try: if self.cover_data is not None: p = QPixmap() try: p.loadFromData(self.cover_data) except TypeError: self.log.warn('This ebook does not have a raster cover, cannot generate cover for PDF' '. Cover type: %s' % type(self.cover_data)) if not p.isNull(): self.doc.init_page() draw_image_page(QRect(*self.doc.full_page_rect), self.painter, p, preserve_aspect_ratio=self.opts.preserve_cover_aspect_ratio) self.doc.end_page() finally: self.painter.restore() QTimer.singleShot(0, self.render_book) if self.loop.exec_() == 1: raise Exception('PDF Output failed, see log for details') if self.toc is not None and len(self.toc) > 0: self.doc.add_outline(self.toc) self.painter.end() if self.doc.errors_occurred: raise Exception('PDF Output failed, see log for details')
def paintEvent(self, event): w = self.viewport().rect().width() painter = QPainter(self.viewport()) painter.setClipRect(event.rect()) painter.setRenderHint(QPainter.SmoothPixmapTransform, True) floor = event.rect().bottom() ceiling = event.rect().top() fv = self.firstVisibleBlock().blockNumber() origin = self.contentOffset() doc = self.document() lines = [] for num, text in self.headers: top, bot = num, num + 3 if bot < fv: continue y_top = self.blockBoundingGeometry( doc.findBlockByNumber(top)).translated(origin).y() y_bot = self.blockBoundingGeometry( doc.findBlockByNumber(bot)).translated(origin).y() if max(y_top, y_bot) < ceiling: continue if min(y_top, y_bot) > floor: break painter.setFont(self.heading_font) br = painter.drawText(3, y_top, w, y_bot - y_top - 5, Qt.TextSingleLine, text) painter.setPen(QPen(self.palette().text(), 2)) painter.drawLine(0, br.bottom() + 3, w, br.bottom() + 3) for top, bot, kind in self.changes: if bot < fv: continue y_top = self.blockBoundingGeometry( doc.findBlockByNumber(top)).translated(origin).y() y_bot = self.blockBoundingGeometry( doc.findBlockByNumber(bot)).translated(origin).y() if max(y_top, y_bot) < ceiling: continue if min(y_top, y_bot) > floor: break if y_top != y_bot: painter.fillRect(0, y_top, w, y_bot - y_top, self.diff_backgrounds[kind]) lines.append((y_top, y_bot, kind)) if top in self.images: img, maxw = self.images[top][:2] if bot > top + 1 and not img.isNull(): y_top = self.blockBoundingGeometry( doc.findBlockByNumber(top + 1)).translated(origin).y() + 3 y_bot -= 3 scaled, imgw, imgh = fit_image( int(img.width() / img.devicePixelRatio()), int(img.height() / img.devicePixelRatio()), w - 3, y_bot - y_top) painter.drawPixmap(QRect(3, y_top, imgw, imgh), img) painter.end() PlainTextEdit.paintEvent(self, event) painter = QPainter(self.viewport()) painter.setClipRect(event.rect()) for top, bottom, kind in sorted( lines, key=lambda t_b_k: {'replace': 0}.get(t_b_k[2], 1)): painter.setPen(QPen(self.diff_foregrounds[kind], 1)) painter.drawLine(0, top, w, top) painter.drawLine(0, bottom - 1, w, bottom - 1)
class Declaration(QWidget): hyperlink_activated = pyqtSignal(object) context_menu_requested = pyqtSignal(object, object) def __init__(self, html_name, data, is_first=False, parent=None): QWidget.__init__(self, parent) self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum) self.data = data self.is_first = is_first self.html_name = html_name self.lines_for_copy = [] self.do_layout() self.setMouseTracking(True) def do_layout(self): fm = self.fontMetrics() bounding_rect = lambda text: fm.boundingRect(0, 0, 10000, 10000, Cell. FLAGS, text) line_spacing = 2 side_margin = Cell.SIDE_MARGIN self.rows = [] ypos = line_spacing + (1 if self.is_first else 0) if 'href' in self.data: name = self.data['href'] if isinstance(name, list): name = self.html_name br1 = bounding_rect(name) sel = self.data['selector'] or '' if self.data['type'] == 'inline': sel = 'style=""' br2 = bounding_rect(sel) self.hyperlink_rect = QRect(side_margin, ypos, br1.width(), br1.height()) self.rows.append([ Cell(name, self.hyperlink_rect, color_role=QPalette.Link), Cell(sel, QRect(br1.right() + side_margin, ypos, br2.width(), br2.height()), right_align=True) ]) ypos += max(br1.height(), br2.height()) + 2 * line_spacing self.lines_for_copy.append(name + ' ' + sel) for prop in self.data['properties']: text = prop.name + ':\xa0' br1 = bounding_rect(text) vtext = prop.value + '\xa0' + ('!' if prop.important else '') + prop.important br2 = bounding_rect(vtext) self.rows.append([ Cell(text, QRect(side_margin, ypos, br1.width(), br1.height()), color_role=QPalette.LinkVisited, is_overriden=prop.is_overriden), Cell(vtext, QRect(br1.right() + side_margin, ypos, br2.width(), br2.height()), swatch=prop.color, is_overriden=prop.is_overriden) ]) self.lines_for_copy.append(text + vtext) ypos += max(br1.height(), br2.height()) + line_spacing self.height_hint = ypos + line_spacing self.width_hint = max(row[-1].rect.right() + side_margin for row in self.rows) if self.rows else 0 def sizeHint(self): return QSize(self.width_hint, self.height_hint) def paintEvent(self, ev): p = QPainter(self) p.setClipRect(ev.rect()) palette = self.palette() p.setPen(palette.color(QPalette.WindowText)) if not self.is_first: p.drawLine(0, 0, self.width(), 0) try: for row in self.rows: for cell in row: p.save() try: cell.draw(p, self.width(), palette) finally: p.restore() finally: p.end() def mouseMoveEvent(self, ev): if hasattr(self, 'hyperlink_rect'): pos = ev.pos() hovering = self.hyperlink_rect.contains(pos) self.update_hover(hovering) cursor = Qt.ArrowCursor for r, row in enumerate(self.rows): for cell in row: if cell.rect.contains(pos): cursor = Qt.PointingHandCursor if cell.rect is self.hyperlink_rect else Qt.IBeamCursor if r == 0: break if cursor != Qt.ArrowCursor: break self.setCursor(cursor) return QWidget.mouseMoveEvent(self, ev) def mousePressEvent(self, ev): if hasattr(self, 'hyperlink_rect') and ev.button() == Qt.LeftButton: pos = ev.pos() if self.hyperlink_rect.contains(pos): self.emit_hyperlink_activated() return QWidget.mousePressEvent(self, ev) def emit_hyperlink_activated(self): dt = self.data['type'] data = {'type': dt, 'name': self.html_name, 'syntax': 'html'} if dt == 'inline': # style attribute data['sourceline_address'] = self.data['href'] elif dt == 'elem': # <style> tag data['sourceline_address'] = self.data['href'] data['rule_address'] = self.data['rule_address'] else: # stylesheet data['name'] = self.data['href'] data['rule_address'] = self.data['rule_address'] data['syntax'] = 'css' self.hyperlink_activated.emit(data) def leaveEvent(self, ev): self.update_hover(False) self.setCursor(Qt.ArrowCursor) return QWidget.leaveEvent(self, ev) def update_hover(self, hovering): cell = self.rows[0][0] if (hovering and cell.override_color is None) or ( not hovering and cell.override_color is not None): cell.override_color = QColor(Qt.red) if hovering else None self.update() def contextMenuEvent(self, ev): self.context_menu_requested.emit(self, ev)
class Declaration(QWidget): hyperlink_activated = pyqtSignal(object) def __init__(self, html_name, data, is_first=False, parent=None): QWidget.__init__(self, parent) self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum) self.data = data self.is_first = is_first self.html_name = html_name self.do_layout() self.setMouseTracking(True) def do_layout(self): fm = self.fontMetrics() bounding_rect = lambda text: fm.boundingRect(0, 0, 10000, 10000, Cell.FLAGS, text) line_spacing = 2 side_margin = Cell.SIDE_MARGIN self.rows = [] ypos = line_spacing + (1 if self.is_first else 0) if "href" in self.data: name = self.data["href"] if isinstance(name, list): name = self.html_name br1 = bounding_rect(name) sel = self.data["selector"] or "" if self.data["type"] == "inline": sel = 'style=""' br2 = bounding_rect(sel) self.hyperlink_rect = QRect(side_margin, ypos, br1.width(), br1.height()) self.rows.append( [ Cell(name, self.hyperlink_rect, color_role=QPalette.Link), Cell(sel, QRect(br1.right() + side_margin, ypos, br2.width(), br2.height()), right_align=True), ] ) ypos += max(br1.height(), br2.height()) + 2 * line_spacing for prop in self.data["properties"]: text = prop.name + ":\xa0" br1 = bounding_rect(text) vtext = prop.value + "\xa0" + ("!" if prop.important else "") + prop.important br2 = bounding_rect(vtext) self.rows.append( [ Cell( text, QRect(side_margin, ypos, br1.width(), br1.height()), color_role=QPalette.LinkVisited, is_overriden=prop.is_overriden, ), Cell( vtext, QRect(br1.right() + side_margin, ypos, br2.width(), br2.height()), swatch=prop.color, is_overriden=prop.is_overriden, ), ] ) ypos += max(br1.height(), br2.height()) + line_spacing self.height_hint = ypos + line_spacing self.width_hint = max(row[-1].rect.right() + side_margin for row in self.rows) if self.rows else 0 def sizeHint(self): return QSize(self.width_hint, self.height_hint) def paintEvent(self, ev): p = QPainter(self) p.setClipRect(ev.rect()) palette = self.palette() p.setPen(palette.color(QPalette.WindowText)) if not self.is_first: p.drawLine(0, 0, self.width(), 0) try: for row in self.rows: for cell in row: p.save() try: cell.draw(p, self.width(), palette) finally: p.restore() finally: p.end() def mouseMoveEvent(self, ev): if hasattr(self, "hyperlink_rect"): pos = ev.pos() hovering = self.hyperlink_rect.contains(pos) self.update_hover(hovering) cursor = Qt.ArrowCursor for r, row in enumerate(self.rows): for cell in row: if cell.rect.contains(pos): cursor = Qt.PointingHandCursor if cell.rect is self.hyperlink_rect else Qt.IBeamCursor if r == 0: break if cursor != Qt.ArrowCursor: break self.setCursor(cursor) return QWidget.mouseMoveEvent(self, ev) def mousePressEvent(self, ev): if hasattr(self, "hyperlink_rect"): pos = ev.pos() if self.hyperlink_rect.contains(pos): self.emit_hyperlink_activated() return QWidget.mousePressEvent(self, ev) def emit_hyperlink_activated(self): dt = self.data["type"] data = {"type": dt, "name": self.html_name, "syntax": "html"} if dt == "inline": # style attribute data["sourceline_address"] = self.data["href"] elif dt == "elem": # <style> tag data["sourceline_address"] = self.data["href"] data["rule_address"] = self.data["rule_address"] else: # stylesheet data["name"] = self.data["href"] data["rule_address"] = self.data["rule_address"] data["syntax"] = "css" self.hyperlink_activated.emit(data) def leaveEvent(self, ev): self.update_hover(False) self.setCursor(Qt.ArrowCursor) return QWidget.leaveEvent(self, ev) def update_hover(self, hovering): cell = self.rows[0][0] if (hovering and cell.override_color is None) or (not hovering and cell.override_color is not None): cell.override_color = QColor(Qt.red) if hovering else None self.update()
default_config_path = join(dirname(abspath(__file__)), "config_test.cfg") @pytest.fixture def init_paths(): importExportUtils.DEFAULT_CONFIG_PATH = default_config_path importExportUtils.ALERT_DB_PATH = alert_db_path sound_path = join(dirname(dirname(abspath(__file__))), 'resources', 'sounds', 'floop.wav') im_path = join(dirname(dirname(abspath(__file__))), 'resources', 'images', 'notification_clock.png') notification = Notification("Test", "000000", "Times", 12, sound_path) rect = QRect(0, 0, 1024, 768) # A App is needed for the MainWindow app = App(default_config_path, alert_db_path, []) mw = app.main_window @pytest.mark.test def test_constructor(init_paths): """Test :class:~_clockalarm.UI.MainWindow constructor.""" global mw assert mw.minimumSize() == QSize(300, 100) assert mw.windowTitle() == "ClockAlarm Manager" assert mw.size() == QSize(800, 400)
def drawIconWithShadow(self, icon, rect, painter, iconMode, radius=3, color=QColor(0, 0, 0, 130), offset=QPoint(1, -2)): ''' @brief: Draw a cached pixmap with shadow @param: icon QIcon @param: rect QRect @param: painter QPainter @param: iconMode QIcon.Mode @param: radius int @param: color QColor @param: offset QPoint ''' cache = QPixmap() pixmapName = 'icon %s %s %s' % (icon.cacheKey(), iconMode, rect.height()) cache = QPixmapCache.find(pixmapName) if not cache: px = icon.pixmap(rect.size(), iconMode) px.setDevicePixelRatio(gVar.app.devicePixelRatio()) cache = QPixmap(px.size() + QSize(radius * 2, radius * 2)) cache.setDevicePixelRatio(px.devicePixelRatioF()) cache.fill(Qt.transparent) cachePainter = QPainter(cache) # Draw shadow tmp = QImage(px.size() + QSize(radius * 2, radius * 2 + 1), QImage.Format_ARGB32_Premultiplied) tmp.setDevicePixelRatio(px.devicePixelRatioF()) tmp.fill(Qt.transparent) tmpPainter = QPainter(tmp) tmpPainter.setCompositionMode(QPainter.CompositionMode_Source) tmpPainter.drawPixmap(QPoint(radius, radius), px) tmpPainter.end() # blur the alpha channel blurred = QImage(tmp.size(), QImage.Format_ARGB32_Premultiplied) blurred.fill(Qt.transparent) blurPainter = QPainter(blurred) # TODO: #qt_blurImage(blurPainter, tmp, radius, False, True) blurPainter.end() tmp = blurred # blacken the image... tmpPainter.begin(tmp) tmpPainter.setCompositionMode(QPainter.CompositionMode_SourceIn) tmpPainter.fillRect(tmp.rect(), color) tmpPainter.end() tmpPainter.begin(tmp) tmpPainter.setCompositionMode(QPainter.CompositionMode_SourceIn) tmpPainter.fillRect(tmp.rect(), color) tmpPainter.end() # draw the blurred drop shadow... cachePainter.drawImage( QRect(0, 0, cache.rect().width() / cache.devicePixelRatioF(), cache.rect().height() / cache.devicePixelRatioF()), tmp) # Draw the actual pixmap... cachePainter.drawPixmap(QPoint(radius, radius) + offset, px) if self.usePixmapCache(): QPixmapCache.insert(pixmapName, cache) sip.delete(cachePainter) sip.delete(tmpPainter) sip.delete(blurPainter) targetRect = QRect(cache.rect()) targetRect.setWidth(cache.rect().width() / cache.devicePixelRatioF()) targetRect.setHeight(cache.rect().height() / cache.devicePixelRatioF()) targetRect.moveCenter(rect.center()) painter.drawPixmap(targetRect.topLeft() - offset, cache)
def draw_text(self, style, painter, option, widget, index, item): tr = style.subElementRect(style.SE_ItemViewItemText, option, widget) text = index.data(Qt.DisplayRole) hover = option.state & style.State_MouseOver if hover or gprefs['tag_browser_show_counts']: count = unicode_type(index.data(COUNT_ROLE)) width = painter.fontMetrics().boundingRect(count).width() r = QRect(tr) r.setRight(r.right() - 1), r.setLeft(r.right() - width - 4) painter.drawText(r, Qt.AlignCenter | Qt.TextSingleLine, count) tr.setRight(r.left() - 1) else: tr.setRight(tr.right() - 1) is_rating = item.type == TagTreeItem.TAG and not self.rating_pat.sub('', text) if is_rating: painter.setFont(self.rating_font) flags = Qt.AlignVCenter | Qt.AlignLeft | Qt.TextSingleLine lr = QRect(tr) lr.setRight(lr.right() * 2) br = painter.boundingRect(lr, flags, text) if br.width() > tr.width(): g = QLinearGradient(tr.topLeft(), tr.topRight()) c = option.palette.color(QPalette.WindowText) g.setColorAt(0, c), g.setColorAt(0.8, c) c = QColor(c) c.setAlpha(0) g.setColorAt(1, c) pen = QPen() pen.setBrush(QBrush(g)) painter.setPen(pen) painter.drawText(tr, flags, text)
def __init__(self, opts): self.matched_ids = set() self.opts = opts self.prefs = opts.prefs super(FindAnnotationsDialog, self).__init__(self.opts.gui, 'find_annotations_dialog') self.setWindowTitle(_('Find Annotations')) self.setWindowIcon(self.opts.icon) self.l = QVBoxLayout(self) self.setLayout(self.l) self.search_criteria_gb = QGroupBox(self) self.search_criteria_gb.setTitle(_("Search criteria")) self.scgl = QGridLayout(self.search_criteria_gb) self.l.addWidget(self.search_criteria_gb) # addWidget(widget, row, col, rowspan, colspan) row = 0 # ~~~~~~~~ Create the Readers comboBox ~~~~~~~~ self.reader_label = QLabel(_('Reader')) self.reader_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.scgl.addWidget(self.reader_label, row, 0, 1, 1) self.find_annotations_reader_comboBox = QComboBox() self.find_annotations_reader_comboBox.setObjectName( 'find_annotations_reader_comboBox') self.find_annotations_reader_comboBox.setToolTip( _('Reader annotations to search for')) self.find_annotations_reader_comboBox.addItem(self.GENERIC_READER) racs = ReaderApp.get_reader_app_classes() for ra in sorted(list(racs.keys())): self.find_annotations_reader_comboBox.addItem(ra) self.scgl.addWidget(self.find_annotations_reader_comboBox, row, 1, 1, 4) row += 1 # ~~~~~~~~ Create the Styles comboBox ~~~~~~~~ self.style_label = QLabel(_('Style')) self.style_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.scgl.addWidget(self.style_label, row, 0, 1, 1) self.find_annotations_color_comboBox = QComboBox() self.find_annotations_color_comboBox.setObjectName( 'find_annotations_color_comboBox') self.find_annotations_color_comboBox.setToolTip( _('Annotation style to search for')) self.find_annotations_color_comboBox.addItem(self.GENERIC_STYLE) all_colors = list(COLOR_MAP.keys()) all_colors.remove('Default') for color in sorted(all_colors): self.find_annotations_color_comboBox.addItem(color) self.scgl.addWidget(self.find_annotations_color_comboBox, row, 1, 1, 4) row += 1 # ~~~~~~~~ Create the Text LineEdit control ~~~~~~~~ self.text_label = QLabel(_('Text')) self.text_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.scgl.addWidget(self.text_label, row, 0, 1, 1) self.find_annotations_text_lineEdit = MyLineEdit() self.find_annotations_text_lineEdit.setObjectName( 'find_annotations_text_lineEdit') self.scgl.addWidget(self.find_annotations_text_lineEdit, row, 1, 1, 3) self.reset_text_tb = QToolButton() self.reset_text_tb.setObjectName('reset_text_tb') self.reset_text_tb.setToolTip(_('Clear search criteria')) self.reset_text_tb.setIcon(QIcon(I('trash.png'))) self.reset_text_tb.clicked.connect(self.clear_text_field) self.scgl.addWidget(self.reset_text_tb, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create the Note LineEdit control ~~~~~~~~ self.note_label = QLabel(_('Note')) self.note_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.scgl.addWidget(self.note_label, row, 0, 1, 1) self.find_annotations_note_lineEdit = MyLineEdit() self.find_annotations_note_lineEdit.setObjectName( 'find_annotations_note_lineEdit') self.scgl.addWidget(self.find_annotations_note_lineEdit, row, 1, 1, 3) self.reset_note_tb = QToolButton() self.reset_note_tb.setObjectName('reset_note_tb') self.reset_note_tb.setToolTip(_('Clear search criteria')) self.reset_note_tb.setIcon(QIcon(I('trash.png'))) self.reset_note_tb.clicked.connect(self.clear_note_field) self.scgl.addWidget(self.reset_note_tb, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create the Date range controls ~~~~~~~~ self.date_range_label = QLabel(_('Date range')) self.date_range_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.scgl.addWidget(self.date_range_label, row, 0, 1, 1) # Date 'From' self.find_annotations_date_from_dateEdit = MyDateEdit( self, datetime(1970, 1, 1)) self.find_annotations_date_from_dateEdit.setObjectName( 'find_annotations_date_from_dateEdit') #self.find_annotations_date_from_dateEdit.current_val = datetime(1970,1,1) self.find_annotations_date_from_dateEdit.clear_button.clicked.connect( self.find_annotations_date_from_dateEdit.reset_from_date) self.scgl.addWidget(self.find_annotations_date_from_dateEdit, row, 1, 1, 1) self.scgl.addWidget( self.find_annotations_date_from_dateEdit.clear_button, row, 2, 1, 1) # Date 'To' self.find_annotations_date_to_dateEdit = MyDateEdit( self, datetime.today()) self.find_annotations_date_to_dateEdit.setObjectName( 'find_annotations_date_to_dateEdit') #self.find_annotations_date_to_dateEdit.current_val = datetime.today() self.find_annotations_date_to_dateEdit.clear_button.clicked.connect( self.find_annotations_date_to_dateEdit.reset_to_date) self.scgl.addWidget(self.find_annotations_date_to_dateEdit, row, 3, 1, 1) self.scgl.addWidget( self.find_annotations_date_to_dateEdit.clear_button, row, 4, 1, 1) row += 1 # ~~~~~~~~ Create a horizontal line ~~~~~~~~ self.hl = QFrame(self) self.hl.setGeometry(QRect(0, 0, 1, 3)) self.hl.setFrameShape(QFrame.HLine) self.hl.setFrameShadow(QFrame.Raised) self.scgl.addWidget(self.hl, row, 0, 1, 5) row += 1 # ~~~~~~~~ Create the results label field ~~~~~~~~ self.result_label = QLabel('<p style="color:red">{0}</p>'.format( _('scanning…'))) self.result_label.setAlignment(Qt.AlignCenter) self.result_label.setWordWrap(False) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Maximum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.result_label.sizePolicy().hasHeightForWidth()) self.result_label.setSizePolicy(sizePolicy) self.result_label.setMinimumSize(QtCore.QSize(250, 0)) self.scgl.addWidget(self.result_label, row, 0, 1, 5) row += 1 # ~~~~~~~~ Create the ButtonBox ~~~~~~~~ self.dialogButtonBox = QDialogButtonBox(self) self.dialogButtonBox.setOrientation(Qt.Horizontal) if False: self.update_button = QPushButton(_('Update results')) self.update_button.setDefault(True) self.update_button.setVisible(False) self.dialogButtonBox.addButton(self.update_button, QDialogButtonBox.ActionRole) self.cancel_button = self.dialogButtonBox.addButton( self.dialogButtonBox.Cancel) self.find_button = self.dialogButtonBox.addButton( self.dialogButtonBox.Ok) self.find_button.setText(_('Find Matching Books')) self.l.addWidget(self.dialogButtonBox) self.dialogButtonBox.clicked.connect( self.find_annotations_dialog_clicked) # ~~~~~~~~ Add a spacer ~~~~~~~~ self.spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.l.addItem(self.spacerItem) # ~~~~~~~~ Restore previously saved settings ~~~~~~~~ self.restore_settings() # ~~~~~~~~ Declare sizing ~~~~~~~~ sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(sizePolicy) self.resize_dialog() # ~~~~~~~~ Connect all signals ~~~~~~~~ self.find_annotations_reader_comboBox.currentIndexChanged.connect( partial(self.update_results, 'reader')) self.find_annotations_color_comboBox.currentIndexChanged.connect( partial(self.update_results, 'color')) self.find_annotations_text_lineEdit.editingFinished.connect( partial(self.update_results, 'text')) self.find_annotations_note_lineEdit.editingFinished.connect( partial(self.update_results, 'note')) # self.connect(self.find_annotations_text_lineEdit, pyqtSignal("return_pressed"), self.return_pressed) self.find_annotations_text_lineEdit.return_pressed.connect( self.return_pressed) # self.connect(self.find_annotations_note_lineEdit, pyqtSignal("return_pressed"), self.return_pressed) self.find_annotations_note_lineEdit.return_pressed.connect( self.return_pressed) # Date range signals connected in inventory_available() # ~~~~~~~~ Allow dialog to render before doing inventory ~~~~~~~~ #field = self.prefs.get('cfg_annotations_destination_field', None) field = get_cc_mapping('annotations', 'field', None) self.annotated_books_scanner = InventoryAnnotatedBooks( self.opts.gui, field, get_date_range=True) self.annotated_books_scanner.signal.connect(self.inventory_available) QTimer.singleShot(1, self.start_inventory_scan)
def paint(self, painter, option, index): QStyledItemDelegate.paint(self, painter, option, index) hovering = index.data(HOVER_ROLE) is True painter.save() rect = option.rect is_current = index.data(Qt.FontRole) is not None if not hovering and is_current: qpp = QPainterPath() qpp.addRoundedRect(QRectF(rect), 6, 6) painter.fillPath(qpp, self.current_background) icon_rect = QRect(rect.left() + self.MARGIN, rect.top() + self.MARGIN, ICON_SIZE, ICON_SIZE) left = icon_rect.right() + 2 * self.MARGIN text_rect = QRect(left, icon_rect.top(), rect.width() - left + rect.left(), icon_rect.height()) mark = index.data(MARK_ROLE) if hovering or mark: text_rect.adjust(0, 0, -text_rect.height(), 0) text = index.data(DISPLAY_ROLE) or '' font = index.data(Qt.FontRole) if font: painter.setFont(font) text_flags = Qt.AlignVCenter | Qt.AlignLeft | Qt.TextSingleLine text = elided_text(text, font, text_rect.width(), 'right') if option.state & QStyle.State_Selected: painter.setPen(QPen(self.highlighted_text)) painter.drawText(text_rect, text_flags, text) if mark: hrect = QRect(text_rect.right(), text_rect.top(), text_rect.height(), text_rect.height()) painter.fillRect(hrect, QColor('#ffffaa')) painter.drawText(hrect, Qt.AlignCenter, mark) elif hovering: hrect = QRect(text_rect.right(), text_rect.top(), text_rect.height(), text_rect.height()) close_hover = index.data(CLOSE_HOVER_ROLE) is True if close_hover: pen = painter.pen() pen.setColor(QColor('red')) painter.setPen(pen) painter.drawText(hrect, Qt.AlignCenter, '✖ ') if index.data(LOADING_ROLE): if not self.errored_out: angle = index.data(ANGLE_ROLE) try: draw_snake_spinner(painter, icon_rect, angle, self.light, self.dark) except Exception: import traceback traceback.print_exc() self.errored_out = True else: icurl = index.data(URL_ROLE) if icurl == WELCOME_URL: icon = welcome_icon() elif icurl == DOWNLOADS_URL: icon = downloads_icon() else: icon = index.data(DECORATION_ROLE) icon.paint(painter, icon_rect) painter.restore()
def paint_emblems(self, painter, rect, emblems): gutter = self.emblem_size + self.MARGIN grect = QRect(rect) gpos = self.gutter_position if gpos is self.TOP: grect.setBottom(grect.top() + gutter) rect.setTop(rect.top() + gutter) elif gpos is self.BOTTOM: grect.setTop(grect.bottom() - gutter + self.MARGIN) rect.setBottom(rect.bottom() - gutter) elif gpos is self.LEFT: grect.setRight(grect.left() + gutter) rect.setLeft(rect.left() + gutter) else: grect.setLeft(grect.right() - gutter + self.MARGIN) rect.setRight(rect.right() - gutter) horizontal = gpos in (self.TOP, self.BOTTOM) painter.save() painter.setClipRect(grect) try: for i, emblem in enumerate(emblems): delta = 0 if i == 0 else self.emblem_size + self.MARGIN grect.moveLeft(grect.left() + delta) if horizontal else grect.moveTop(grect.top() + delta) rect = QRect(grect) rect.setWidth(int(emblem.width() / emblem.devicePixelRatio())), rect.setHeight(int(emblem.height() / emblem.devicePixelRatio())) painter.drawPixmap(rect, emblem) finally: painter.restore()
class CameraImage(QWidget): _aspect_ratio = (setting.camera_resolution[1] / setting.camera_resolution[0]) def __init__(self, resize_leader): super().__init__() self._pixmap = None self._paint_rect = QRect(0, 0, self.width(), self.height()) self._hover = False self._inspect = False self._resize_leader = resize_leader self._setup_ui() def set_map(self, pixmap): if isinstance(pixmap, QPixmap): self._pixmap = pixmap self.update() def _setup_ui(self): self.setAttribute(Qt.WA_Hover, True) self.setContentsMargins(0, 0, 0, 0) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self._inspect_map = icons.get('inspect') self._pixmap = icons.get('connect_none') def set_inspect(self, inspect): if self._inspect != inspect: self._inspect = inspect self.update() def resizeEvent(self, event): if self.width() * setting.camera_resolution[1] >\ self.height() * setting.camera_resolution[0]: width = self.height() / self._aspect_ratio width_margin = (self.width() - width) / 2 self._paint_rect = QRect(width_margin, 0, width, self.height()) else: height = self.width() * self._aspect_ratio height_margin = (self.height() - height) / 2 self._paint_rect = QRect(0, height_margin, self.width(), height) if (self._resize_leader and self.isVisible()): value = self._paint_rect.width() if value > 0: state.set('live_view_size', value) def enterEvent(self, event): if not self._inspect: self._hover = True self.setCursor(Qt.PointingHandCursor) def leaveEvent(self, event): self._hover = False self.unsetCursor() def paintEvent(self, event): painter = QPainter(self) if self._inspect: painter.drawPixmap( (self.width() - self._inspect_map.width()) / 2, (self.height() - self._inspect_map.height()) / 2, self._inspect_map) return if self._pixmap.width() > 50: painter.setRenderHint(QPainter.SmoothPixmapTransform) painter.drawPixmap(self._paint_rect, self._pixmap) else: painter.drawPixmap((self.width() - self._pixmap.width()) / 2, (self.height() - self._pixmap.height()) / 2, self._pixmap) if self._hover: painter.setPen(QPen(self.palette().highlight().color(), 2)) painter.drawRect(self._paint_rect)
def resizeEvent(self, event): QPlainTextEdit.resizeEvent(self, event) contents_rect = self.contentsRect() self._line_number_area.setGeometry(QRect(contents_rect.left(), contents_rect.top(), self.lineNumberAreaWidth(), contents_rect.height()))
def draw_text(self, style, painter, option, widget, index, item): tr = style.subElementRect(style.SE_ItemViewItemText, option, widget) text = index.data(Qt.DisplayRole) hover = option.state & style.State_MouseOver if hover or gprefs['tag_browser_show_counts']: count = unicode_type(index.data(COUNT_ROLE)) width = painter.fontMetrics().boundingRect(count).width() r = QRect(tr) r.setRight(r.right() - 1), r.setLeft(r.right() - width - 4) painter.drawText(r, Qt.AlignCenter | Qt.TextSingleLine, count) tr.setRight(r.left() - 1) else: tr.setRight(tr.right() - 1) is_rating = item.type == TagTreeItem.TAG and not self.rating_pat.sub( '', text) if is_rating: painter.setFont(self.rating_font) flags = Qt.AlignVCenter | Qt.AlignLeft | Qt.TextSingleLine lr = QRect(tr) lr.setRight(lr.right() * 2) br = painter.boundingRect(lr, flags, text) if br.width() > tr.width(): g = QLinearGradient(tr.topLeft(), tr.topRight()) c = option.palette.color(QPalette.WindowText) g.setColorAt(0, c), g.setColorAt(0.8, c) c = QColor(c) c.setAlpha(0) g.setColorAt(1, c) pen = QPen() pen.setBrush(QBrush(g)) painter.setPen(pen) painter.drawText(tr, flags, text)
def mouseMoveInLabel(self, event): if not self.pt1.isNull(): pt = self.img_lbl.mapTo(self,event.pos()) self.rubberBand.setGeometry(QRect(self.pt1_rect, pt).normalized())
class Declaration(QWidget): hyperlink_activated = pyqtSignal(object) context_menu_requested = pyqtSignal(object, object) def __init__(self, html_name, data, is_first=False, parent=None): QWidget.__init__(self, parent) self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum) self.data = data self.is_first = is_first self.html_name = html_name self.lines_for_copy = [] self.do_layout() self.setMouseTracking(True) def do_layout(self): fm = self.fontMetrics() bounding_rect = lambda text: fm.boundingRect(0, 0, 10000, 10000, Cell.FLAGS, text) line_spacing = 2 side_margin = Cell.SIDE_MARGIN self.rows = [] ypos = line_spacing + (1 if self.is_first else 0) if 'href' in self.data: name = self.data['href'] if isinstance(name, list): name = self.html_name br1 = bounding_rect(name) sel = self.data['selector'] or '' if self.data['type'] == 'inline': sel = 'style=""' br2 = bounding_rect(sel) self.hyperlink_rect = QRect(side_margin, ypos, br1.width(), br1.height()) self.rows.append([ Cell(name, self.hyperlink_rect, color_role=QPalette.Link), Cell(sel, QRect(br1.right() + side_margin, ypos, br2.width(), br2.height()), right_align=True) ]) ypos += max(br1.height(), br2.height()) + 2 * line_spacing self.lines_for_copy.append(name + ' ' + sel) for prop in self.data['properties']: text = prop.name + ':\xa0' br1 = bounding_rect(text) vtext = prop.value + '\xa0' + ('!' if prop.important else '') + prop.important br2 = bounding_rect(vtext) self.rows.append([ Cell(text, QRect(side_margin, ypos, br1.width(), br1.height()), color_role=QPalette.LinkVisited, is_overriden=prop.is_overriden), Cell(vtext, QRect(br1.right() + side_margin, ypos, br2.width(), br2.height()), swatch=prop.color, is_overriden=prop.is_overriden) ]) self.lines_for_copy.append(text + vtext) if prop.is_overriden: self.lines_for_copy[-1] += ' [overriden]' ypos += max(br1.height(), br2.height()) + line_spacing self.lines_for_copy.append('--------------------------\n') self.height_hint = ypos + line_spacing self.width_hint = max(row[-1].rect.right() + side_margin for row in self.rows) if self.rows else 0 def sizeHint(self): return QSize(self.width_hint, self.height_hint) def paintEvent(self, ev): p = QPainter(self) p.setClipRect(ev.rect()) palette = self.palette() p.setPen(palette.color(QPalette.WindowText)) if not self.is_first: p.drawLine(0, 0, self.width(), 0) try: for row in self.rows: for cell in row: p.save() try: cell.draw(p, self.width(), palette) finally: p.restore() finally: p.end() def mouseMoveEvent(self, ev): if hasattr(self, 'hyperlink_rect'): pos = ev.pos() hovering = self.hyperlink_rect.contains(pos) self.update_hover(hovering) cursor = Qt.ArrowCursor for r, row in enumerate(self.rows): for cell in row: if cell.rect.contains(pos): cursor = Qt.PointingHandCursor if cell.rect is self.hyperlink_rect else Qt.IBeamCursor if r == 0: break if cursor != Qt.ArrowCursor: break self.setCursor(cursor) return QWidget.mouseMoveEvent(self, ev) def mousePressEvent(self, ev): if hasattr(self, 'hyperlink_rect') and ev.button() == Qt.LeftButton: pos = ev.pos() if self.hyperlink_rect.contains(pos): self.emit_hyperlink_activated() return QWidget.mousePressEvent(self, ev) def emit_hyperlink_activated(self): dt = self.data['type'] data = {'type':dt, 'name':self.html_name, 'syntax':'html'} if dt == 'inline': # style attribute data['sourceline_address'] = self.data['href'] elif dt == 'elem': # <style> tag data['sourceline_address'] = self.data['href'] data['rule_address'] = self.data['rule_address'] else: # stylesheet data['name'] = self.data['href'] data['rule_address'] = self.data['rule_address'] data['syntax'] = 'css' self.hyperlink_activated.emit(data) def leaveEvent(self, ev): self.update_hover(False) self.setCursor(Qt.ArrowCursor) return QWidget.leaveEvent(self, ev) def update_hover(self, hovering): cell = self.rows[0][0] if (hovering and cell.override_color is None) or ( not hovering and cell.override_color is not None): cell.override_color = QColor(Qt.red) if hovering else None self.update() def contextMenuEvent(self, ev): self.context_menu_requested.emit(self, ev)
def resizeEvent(self, ev): QPlainTextEdit.resizeEvent(self, ev) cr = self.contentsRect() self.line_number_area.setGeometry(QRect(cr.left(), cr.top(), self.line_number_area_width(), cr.height()))
def paint(self, painter, option, index): QStyledItemDelegate.paint(self, painter, option, empty_index) # draw the hover and selection highlights m = index.model() db = m.db try: book_id = db.id(index.row()) except (ValueError, IndexError, KeyError): return if book_id in m.ids_to_highlight_set: painter.save() try: painter.setPen(self.highlight_color) painter.setRenderHint(QPainter.Antialiasing, True) painter.drawRoundedRect(option.rect, 10, 10, Qt.RelativeSize) finally: painter.restore() marked = db.data.get_marked(book_id) db = db.new_api cdata = self.cover_cache[book_id] device_connected = self.parent().gui.device_connected is not None on_device = device_connected and db.field_for('ondevice', book_id) emblem_rules = db.pref('cover_grid_icon_rules', default=()) emblems = [] if self.emblem_size > 0: mi = None for i, (kind, column, rule) in enumerate(emblem_rules): icon_name, mi = self.render_emblem(book_id, rule, i, m.cover_grid_emblem_cache, mi, db, m.formatter, m.cover_grid_template_cache) if icon_name is not None: pixmap = self.cached_emblem(m.cover_grid_bitmap_cache, icon_name) if pixmap is not None: emblems.append(pixmap) if marked: emblems.insert(0, self.cached_emblem(m.cover_grid_bitmap_cache, ':marked', m.marked_icon)) if on_device: emblems.insert(0, self.cached_emblem(m.cover_grid_bitmap_cache, ':ondevice')) painter.save() right_adjust = 0 try: rect = option.rect rect.adjust(self.MARGIN, self.MARGIN, -self.MARGIN, -self.MARGIN) if self.emblem_size > 0: self.paint_emblems(painter, rect, emblems) orect = QRect(rect) trect = QRect(rect) if self.title_height != 0: rect.setBottom(rect.bottom() - self.title_height) trect.setTop(trect.bottom() - self.title_height + 5) if cdata is None or cdata is False: title = db.field_for('title', book_id, default_value='') authors = ' & '.join(db.field_for('authors', book_id, default_value=())) painter.setRenderHint(QPainter.TextAntialiasing, True) painter.drawText(rect, Qt.AlignCenter|Qt.TextWordWrap, '%s\n\n%s' % (title, authors)) if cdata is False: self.render_queue.put(book_id) if self.title_height != 0: self.paint_title(painter, trect, db, book_id) else: if self.animating is not None and self.animating.row() == index.row(): cdata = cdata.scaled(cdata.size() * self._animated_size) dpr = cdata.devicePixelRatio() cw, ch = int(cdata.width() / dpr), int(cdata.height() / dpr) dx = max(0, int((rect.width() - cw)/2.0)) dy = max(0, int((rect.height() - ch)/2.0)) right_adjust = dx rect.adjust(dx, dy, -dx, -dy) painter.drawPixmap(rect, cdata) if self.title_height != 0: self.paint_title(painter, trect, db, book_id) if self.emblem_size > 0: return # We dont draw embossed emblems as the ondevice/marked emblems are drawn in the gutter if marked: try: p = self.marked_emblem except AttributeError: p = self.marked_emblem = m.marked_icon.pixmap(48, 48) self.paint_embossed_emblem(p, painter, orect, right_adjust) if on_device: try: p = self.on_device_emblem except AttributeError: p = self.on_device_emblem = QIcon(I('ok.png')).pixmap(48, 48) self.paint_embossed_emblem(p, painter, orect, right_adjust, left=False) finally: painter.restore()
def paint(self, painter, option, index): # noqa C901 ''' @param painter QPainter @param option index QStyleOptionViewItem @param option index QModelIndex ''' from ..LocationBar import LocationBar opt = QStyleOptionViewItem(option) self.initStyleOption(opt, index) w = opt.widget if w: style = w.style() else: style = QApplication.style() height = opt.rect.height() center = height / 2 + opt.rect.top() # Prepare link font # QFont linkFont = opt.font linkFont.setPointSize(linkFont.pointSize() - 1) linkMetrics = QFontMetrics(linkFont) leftPosition = self._padding * 2 rightPosition = opt.rect.right() - self._padding opt.state |= QStyle.State_Active if opt.state & QStyle.State_Selected: iconMode = QIcon.Selected colorRole = QPalette.HighlightedText colorLinkRole = QPalette.HighlightedText else: iconMode = QIcon.Normal colorRole = QPalette.Text colorLinkRole = QPalette.Link if const.OS_WIN: opt.palette.setColor(QPalette.All, QPalette.HighlightedText, opt.palette.color(QPalette.Active, QPalette.Text)) opt.palette.setColor(QPalette.All, QPalette.Highlight, opt.palette.base().color().darker(108)) textPalette = QPalette(opt.palette) if opt.state & QStyle.State_Enabled: textPalette.setCurrentColorGroup(QPalette.Normal) else: textPalette.setCurrentColorGroup(QPalette.Disabled) # Draw background style.drawPrimitive(QStyle.PE_PanelItemViewItem, opt, painter, w) isVisitSearchItem = index.data(LocationCompleterModel.VisitSearchItemRole) isSearchSuggestion = index.data(LocationCompleterModel.SearchSuggestionRole) loadAction = LocationBar.LoadAction() isWebSearch = isSearchSuggestion # BookmarkItem bookmark = index.data(LocationCompleterModel.BookmarkItemRole) if isVisitSearchItem: text = index.data(LocationCompleterModel.SearchStringRole) loadAction = LocationBar.loadAction(text) isWebSearch = loadAction.type == LocationBar.LoadAction.Search if not self._forceVisitItem: bookmark = loadAction.bookmark # Draw icon iconSize = 16 iconYPos = center - iconSize / 2 iconRect = QRect(leftPosition, iconYPos, iconSize, iconSize) icon = index.data(Qt.DecorationRole) if not icon: icon = QIcon() pixmap = icon.pixmap(iconSize) if isSearchSuggestion or (isVisitSearchItem and isWebSearch): pixmap = QIcon.fromTheme('edit-find', QIcon(':/icons/menu/search-icon.svg')).pixmap(iconSize, iconMode) if isVisitSearchItem and bookmark: pixmap = bookmark.icon().pixmap(iconSize) elif loadAction.type == LocationBar.LoadAction.Search: if loadAction.searchEngine.name != LocationBar.searchEngine().name: pixmap = loadAction.searchEngine.icon.pixmap(iconSize) painter.drawPixmap(iconRect, pixmap) leftPosition = iconRect.right() + self._padding * 2 # Draw star to bookmark items starPixmapWidth = 0 if bookmark: icon = IconProvider.instance().bookmarkIcon starSize = QSize(16, 16) starPixmapWidth = starSize.width() pos = QPoint(rightPosition - starPixmapWidth, center - starSize.height() / 2) starRect = QRect(pos, starSize) painter.drawPixmap(starRect, icon.pixmap(starSize, iconMode)) searchText = index.data(LocationCompleterModel.SearchStringRole) # Draw title leftPosition += 2 titleRect = QRect(leftPosition, center - opt.fontMetrics.height() / 2, opt.rect.width() * 0.6, opt.fontMetrics.height()) title = index.data(LocationCompleterModel.TitleRole) painter.setFont(opt.font) if isVisitSearchItem: if bookmark: title = bookmark.title() else: title = index.data(LocationCompleterModel.SearchStringRole) searchText = '' leftPosition += self.viewItemDrawText(painter, opt, titleRect, title, textPalette.color(colorRole), searchText) leftPosition += self._padding * 2 # Trim link to maximum number characters that can be visible, # otherwise there may be perf issue with huge URLs maxChars = int((opt.rect.width() - leftPosition) / opt.fontMetrics.width('i')) link = index.data(Qt.DisplayRole) if not link.startswith('data') and not link.startswith('javascript'): link = unquote(link)[:maxChars] else: link = link[:maxChars] if isVisitSearchItem or isSearchSuggestion: if not (opt.state & QStyle.State_Selected) and not (opt.state & QStyle.State_MouseOver): link = '' elif isVisitSearchItem and (not isWebSearch or self._forceVisitItem): link = _('Visit') else: searchEngineName = loadAction.searchEngine.name if not searchEngineName: searchEngineName = LocationBar.searchEngine().name link = _('Search with %s') % searchEngineName if bookmark: link = bookmark.url().toString() # Draw separator if link: separator = '-' separatorRect = QRect(leftPosition, center - linkMetrics.height() / 2, linkMetrics.width(separator), linkMetrics.height()) style.drawItemText(painter, separatorRect, Qt.AlignCenter, textPalette, True, separator, colorRole) leftPosition += separatorRect.width() + self._padding * 2 # Draw link leftLinkEdge = leftPosition rightLinkEdge = rightPosition - self._padding - starPixmapWidth linkRect = QRect(leftLinkEdge, center - linkMetrics.height() / 2, rightLinkEdge - leftLinkEdge, linkMetrics.height()) painter.setFont(linkFont) # Darw url (or switch to tab) tabPos = index.data(LocationCompleterModel.TabPositionTabRole) if gVar.appSettings.showSwitchTab and not self._forceVisitItem and tabPos != -1: tabIcon = QIcon(':/icons/menu/tab.svg') iconRect = QRect(linkRect) iconRect.setX(iconRect.x()) iconRect.setWidth(16) painter.drawPixmap(iconRect, tabIcon.pixmap(iconRect.size(), iconMode)) textRect = QRect(linkRect) textRect.setX(textRect.x() + self._padding + 16 + self._padding) self.viewItemDrawText(painter, opt, textRect, _('Switch to tab'), textPalette.color(colorLinkRole)) elif isVisitSearchItem or isSearchSuggestion: self.viewItemDrawText(painter, opt, linkRect, link, textPalette.color(colorLinkRole)) else: self.viewItemDrawText(painter, opt, linkRect, link, textPalette.color(colorLinkRole), searchText)