def calcitems(): font = painter.font() metrices = QFontMetrics(font) maxwidth = 0 maxheight = 0 for item, _ in itemlist(self.items): maxwidth = max(metrices.boundingRect(item).width(), maxwidth) maxheight = max(metrices.boundingRect(item).height(), maxheight) return maxwidth, maxheight
def calcitems(): font = painter.font() metrices = QFontMetrics(font) maxwidth = 0 maxheight = 0 for item, _ in itemlist(): maxwidth = max(metrices.boundingRect(item).width(), maxwidth) maxheight = max( metrices.boundingRect(item).height(), maxheight) return maxwidth, maxheight
def splash_screen(): """ """ pm = QPixmap( pkg_resources.resource_filename( __name__, "icons/orange-splash-screen.png") ) version = QCoreApplication.applicationVersion() size = 21 if len(version) < 5 else 16 font = QFont("Helvetica") font.setPixelSize(size) font.setBold(True) font.setItalic(True) font.setLetterSpacing(QFont.AbsoluteSpacing, 2) metrics = QFontMetrics(font) br = metrics.boundingRect(version).adjusted(-5, 0, 5, 0) br.moveCenter(QPoint(436, 224)) p = QPainter(pm) p.setRenderHint(QPainter.Antialiasing) p.setRenderHint(QPainter.TextAntialiasing) p.setFont(font) p.setPen(QColor("#231F20")) p.drawText(br, Qt.AlignCenter, version) p.end() return pm, QRect(88, 193, 200, 20)
def __init__(self, template, character, parent=None): super(AdvantagesWidget, self).__init__(parent) self.ui = Ui_AdvantagesWidget() self.ui.setupUi(self) self.__character = character self.__storage = template fontMetrics = QFontMetrics(self.font()) textRect = fontMetrics.boundingRect("0") iconGeneral = QIcon(":/items/images/svg/shield.svg") pixmapGeneral = iconGeneral.pixmap(textRect.height(), 10 * textRect.height()) self.ui.label_armorGeneralSign.setPixmap(pixmapGeneral) iconFirearms = QIcon(":/items/images/svg/uzi.svg") pixmapFirearms = iconFirearms.pixmap(textRect.height(), 10 * textRect.height()) self.ui.label_armorFirearmsSign.setPixmap(pixmapFirearms) self.ui.dots_health.setReadOnly(True) self.ui.dots_willpower.setMaximum(Config.TRAIT_WILLPOWER_VALUE_MAX) self.ui.dots_willpower.setReadOnly(True) self.ui.dots_powerstat.setMaximum(Config.TRAIT_POWERSTAT_VALUE_MAX) self.ui.dots_powerstat.setMinimum(Config.TRAIT_POWERSTAT_VALUE_MIN) # Damit später der Wert stimmt muß ich irgendeinen Wert != 1 geben, sonst wird kein Signal gesandt. self.ui.dots_powerstat.setValue(9) self.ui.squares_fuel.columnMax = 10 self.__character.speciesChanged.connect(self.setShapeSize) self.sizeChanged.connect(self.setShapeSize) self.__character.speciesChanged.connect(self.setShapeInitiaitve) self.initiativeChanged.connect(self.setShapeInitiaitve) self.__character.speciesChanged.connect(self.setShapeSpeed) self.speedChanged.connect(self.setShapeSpeed) self.__character.speciesChanged.connect(self.setShapeDefense) self.__character.traits["Attribute"]["Mental"][ "Wits"].valueChanged.connect(self.setShapeDefense) self.__character.traits["Attribute"]["Physical"][ "Dexterity"].valueChanged.connect(self.setShapeDefense) self.__character.speciesChanged.connect(self.setShapeHealth) self.healthChanged.connect(self.setShapeHealth) self.__character.armorChanged.connect(self.updateArmor) self.ui.dots_powerstat.valueChanged.connect( self.__character.setPowerstat) self.__character.powerstatChanged.connect( self.ui.dots_powerstat.setValue) self.__character.powerstatChanged.connect(self.setFuel) self.__character.speciesChanged.connect(self.setFuel) self.__character.speciesChanged.connect(self.renamePowerstatHeading) self.__character.speciesChanged.connect(self.hideSuper)
def __textLayout(self): fm = QFontMetrics(self.font()) text = str(self.defaultAction().text()) words = deque(text.split()) lines = [] curr_line = "" curr_line_word_count = 0 option = QStyleOptionToolButton() option.initFrom(self) margin = self.style().pixelMetric(QStyle.PM_ButtonMargin, option, self) width = self.width() - 2 * margin while words: w = words.popleft() if curr_line_word_count: line_extended = " ".join([curr_line, w]) else: line_extended = w line_w = fm.boundingRect(line_extended).width() if line_w >= width: if curr_line_word_count == 0 or len(lines) == 1: # A single word that is too long must be elided. # Also if the text overflows 2 lines # Warning: hardcoded max lines curr_line = fm.elidedText(line_extended, Qt.ElideRight, width) curr_line = str(curr_line) else: # Put the word back words.appendleft(w) lines.append(curr_line) curr_line = "" curr_line_word_count = 0 if len(lines) == 2: break else: curr_line = line_extended curr_line_word_count += 1 if curr_line: lines.append(curr_line) text = "\n".join(lines) text = text.replace('&', '&&') # Need escaped ampersand to show self.__text = text
def __createLayout( self ): """ Creates the dialog layout """ self.resize( 450, 220 ) self.setSizeGripEnabled( True ) self.verticalLayout = QVBoxLayout( self ) # Info label self.infoLabel = FitPathLabel( self ) #sizePolicy = QSizePolicy( QSizePolicy.Expanding, # QSizePolicy.Preferred ) sizePolicy = QSizePolicy( QSizePolicy.Minimum, QSizePolicy.Preferred ) sizePolicy.setHorizontalStretch( 0 ) sizePolicy.setVerticalStretch( 0 ) sizePolicy.setHeightForWidth( self.infoLabel.sizePolicy().hasHeightForWidth() ) self.infoLabel.setSizePolicy( sizePolicy ) self.verticalLayout.addWidget( self.infoLabel ) # Progress bar self.progressBar = QProgressBar( self ) self.progressBar.setValue( 0 ) self.progressBar.setOrientation( Qt.Horizontal ) self.verticalLayout.addWidget( self.progressBar ) # Result window self.resultEdit = QTextEdit( self ) self.resultEdit.setTabChangesFocus( False ) self.resultEdit.setAcceptRichText( False ) self.resultEdit.setReadOnly( True ) self.resultEdit.setFontFamily( GlobalData().skin.baseMonoFontFace ) font = self.resultEdit.font() # Calculate the vertical size fontMetrics = QFontMetrics( font ) rect = fontMetrics.boundingRect( "W" ) # 6 lines, 5 line spacings, 2 frames self.resultEdit.setMinimumHeight( rect.height() * 7 + 4 * 5 + self.resultEdit.frameWidth() * 2 ) self.verticalLayout.addWidget( self.resultEdit ) # Buttons self.buttonBox = QDialogButtonBox( self ) self.buttonBox.setOrientation( Qt.Horizontal ) self.buttonBox.setStandardButtons( QDialogButtonBox.Close ) self.verticalLayout.addWidget( self.buttonBox ) self.buttonBox.rejected.connect( self.__onClose ) return
def __init__(self, template, character, parent=None): super(AdvantagesWidget, self).__init__(parent) self.ui = Ui_AdvantagesWidget() self.ui.setupUi(self) self.__character = character self.__storage = template fontMetrics = QFontMetrics(self.font()) textRect = fontMetrics.boundingRect("0") iconGeneral = QIcon(":/items/images/svg/shield.svg") pixmapGeneral = iconGeneral.pixmap(textRect.height(), 10 * textRect.height()) self.ui.label_armorGeneralSign.setPixmap(pixmapGeneral) iconFirearms = QIcon(":/items/images/svg/uzi.svg") pixmapFirearms = iconFirearms.pixmap(textRect.height(), 10 * textRect.height()) self.ui.label_armorFirearmsSign.setPixmap(pixmapFirearms) self.ui.dots_health.setReadOnly( True ) self.ui.dots_willpower.setMaximum( Config.TRAIT_WILLPOWER_VALUE_MAX ) self.ui.dots_willpower.setReadOnly( True ) self.ui.dots_powerstat.setMaximum( Config.TRAIT_POWERSTAT_VALUE_MAX ) self.ui.dots_powerstat.setMinimum( Config.TRAIT_POWERSTAT_VALUE_MIN ) # Damit später der Wert stimmt muß ich irgendeinen Wert != 1 geben, sonst wird kein Signal gesandt. self.ui.dots_powerstat.setValue( 9 ) self.ui.squares_fuel.columnMax = 10 self.__character.speciesChanged.connect(self.setShapeSize) self.sizeChanged.connect(self.setShapeSize) self.__character.speciesChanged.connect(self.setShapeInitiaitve) self.initiativeChanged.connect(self.setShapeInitiaitve) self.__character.speciesChanged.connect(self.setShapeSpeed) self.speedChanged.connect(self.setShapeSpeed) self.__character.speciesChanged.connect(self.setShapeDefense) self.__character.traits["Attribute"]["Mental"]["Wits"].valueChanged.connect(self.setShapeDefense) self.__character.traits["Attribute"]["Physical"]["Dexterity"].valueChanged.connect(self.setShapeDefense) self.__character.speciesChanged.connect(self.setShapeHealth) self.healthChanged.connect(self.setShapeHealth) self.__character.armorChanged.connect(self.updateArmor) self.ui.dots_powerstat.valueChanged.connect(self.__character.setPowerstat) self.__character.powerstatChanged.connect(self.ui.dots_powerstat.setValue) self.__character.powerstatChanged.connect(self.setFuel) self.__character.speciesChanged.connect(self.setFuel) self.__character.speciesChanged.connect(self.renamePowerstatHeading) self.__character.speciesChanged.connect(self.hideSuper)
def __init__( self, edge ): text = edge.label.replace( '\\n', '\n' ) QGraphicsTextItem.__init__( self, text ) font = QFont( "Arial", 10 ) self.setFont( font ) metric = QFontMetrics( font ) rec = metric.boundingRect( 0, 0, 10000, 10000, Qt.AlignCenter, text ) self.setPos( edge.labelX - rec.width() / 2, edge.labelY - rec.height() / 2 ) # To make double click not delivered self.setFlag( QGraphicsItem.ItemIsSelectable, False ) return
def __init__(self, edge): text = edge.label.replace('\\n', '\n') QGraphicsTextItem.__init__(self, text) font = QFont("Arial", 10) self.setFont(font) metric = QFontMetrics(font) rec = metric.boundingRect(0, 0, 10000, 10000, Qt.AlignCenter, text) self.setPos(edge.labelX - rec.width() / 2, edge.labelY - rec.height() / 2) # To make double click not delivered self.setFlag(QGraphicsItem.ItemIsSelectable, False) return
class Scale(object): def __init__(self, tick_text_font, title_text_font): self.axis_line_thickness = 1 # px, fixed self.tick_mark_thickness = 1 # px, fixed self.tick_mark_size_small = 5 # px, fixed self.tick_mark_size_medium = 7 # px, fixed self.tick_mark_size_large = 9 # px, fixed self.tick_text_font = tick_text_font self.tick_text_font_metrics = QFontMetrics(self.tick_text_font) self.tick_text_height = self.tick_text_font_metrics.boundingRect('0123456789').height() self.tick_text_height_half = int(math.ceil(self.tick_text_height / 2.0)) self.tick_value_to_str = istr self.title_text_font = title_text_font self.title_text_font_metrics = QFontMetrics(self.title_text_font)
def create_font_array(self, char_height=62, pixel_margin=1, font_family='Courier', font_weight=50): # Load font and get the dimensions of one character (assuming monospaced font) f = QFont(font_family) f.setPixelSize(char_height) f.setWeight(font_weight) fm = QFontMetrics(f, QImage()) char_width = char_height = 0 char_y = 999 for i in range(32, 127): bb = fm.boundingRect(chr(i)) char_width = max(char_width, bb.width()) char_height = max(char_height, bb.height()) char_y = min(char_y, bb.y()) imgsize = (char_width + 2 * pixel_margin, char_height + 2 * pixel_margin) self.char_ar = float(imgsize[1]) / imgsize[0] # init the image and the painter that will draw the characters to each image img = QImage(imgsize[0], imgsize[1], QImage.Format_ARGB32) ptr = c_void_p(int(img.constBits())) painter = QPainter(img) painter.setFont(f) painter.setPen(QColor(255, 255, 255, 255)) # Set-up the texture array self.tex_id = gl.glGenTextures(1) gl.glBindTexture(gl.GL_TEXTURE_2D_ARRAY, self.tex_id) gl.glTexImage3D(gl.GL_TEXTURE_2D_ARRAY, 0, gl.GL_RGBA8, imgsize[0], imgsize[1], 127 - 32, 0, gl.GL_BGRA, gl.GL_UNSIGNED_BYTE, None) gl.glTexParameteri(gl.GL_TEXTURE_2D_ARRAY, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_2D_ARRAY, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameterf(gl.GL_TEXTURE_2D_ARRAY, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_BORDER) gl.glTexParameterf(gl.GL_TEXTURE_2D_ARRAY, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_BORDER) # We're using the ASCII range 32-126; space, uppercase, lower case, numbers, brackets, punctuation marks for i in range(32, 127): img.fill(0) painter.drawText(pixel_margin, pixel_margin - char_y, chr(i)) gl.glTexSubImage3D(gl.GL_TEXTURE_2D_ARRAY, 0, 0, 0, i - 32, imgsize[0], imgsize[1], 1, gl.GL_BGRA, gl.GL_UNSIGNED_BYTE, ptr) # We're done, close the painter, and return the texture ID, char width and char height painter.end()
class Scale(object): def __init__(self, tick_text_font, title_text_font): self.axis_line_thickness = 1 # px, fixed self.tick_mark_thickness = 1 # px, fixed self.tick_mark_size_small = 5 # px, fixed self.tick_mark_size_medium = 7 # px, fixed self.tick_mark_size_large = 9 # px, fixed self.tick_text_font = tick_text_font self.tick_text_font_metrics = QFontMetrics(self.tick_text_font) self.tick_text_height = self.tick_text_font_metrics.boundingRect( '0123456789').height() self.tick_text_height_half = int(math.ceil(self.tick_text_height / 2.0)) self.tick_value_to_str = istr self.title_text_font = title_text_font self.title_text_font_metrics = QFontMetrics(self.title_text_font)
def paintEvent(self, event): """ This is reimplemented method from QWidget.paintEvent() :param event: Paint Event :type event: QPaintEvent """ # Just re-paint if there is a text if self.text: # Get container boundaries wi = self.width() - 10 he = self.height() # Calculate Font Point for Width & Height over base font values fpt_w = (wi * 10) / (self.font_base_width) fpt_h = (he * 10) / (self.font_base_height) # Create a new font which fits to the container font = QFont(self.font, min(fpt_w, fpt_h), QFont.Normal) fm = QFontMetrics(font) # Calculate text boundaries over new font rect = fm.boundingRect(self.text) leftBearing = fm.leftBearing(QChar('X')) # Start to paint painter = QPainter() painter.begin(self) painter.setFont(font) # Draw the text at the center of the container painter.drawText(QPoint(wi/2 - rect.width()/2 - leftBearing, \ he/2 + rect.height()/3), self.text) # Finish paint painter.end()
def drawOverlay(self, image, entry): #establish painter painter = QPainter() #set adjustment factor corner_fac = 0.037 category_fac = 0.27 text_fac = 0.03 #load images category = QImage("res/" + str(entry[0]) + ".png") upperLeft = QImage("res/upperLeft.png") upperRight = QImage("res/upperRight.png") lowerLeft = QImage("res/lowerLeft.png") lowerRight = QImage("res/lowerRight.png") #adjust overlays to image size category = category.scaledToHeight(category_fac*image.height(), Qt.SmoothTransformation) upperLeft = upperLeft.scaledToHeight(corner_fac*image.height(), Qt.SmoothTransformation) upperRight = upperRight.scaledToHeight(corner_fac*image.height(), Qt.SmoothTransformation) lowerLeft = lowerLeft.scaledToHeight(corner_fac*image.height(), Qt.SmoothTransformation) lowerRight = lowerRight.scaledToHeight(corner_fac*image.height(), Qt.SmoothTransformation) self.voivoifont.setPixelSize(text_fac*image.height()) # create size calculator for font size_calculator = QFontMetrics(self.voivoifont) text_width = size_calculator.boundingRect(entry[3]).width() text_height = size_calculator.height() #define text-boundary margin_hor = 0.01*image.width() max_text_bound = QRect(margin_hor,image.height()-image.height()/3, image.width()-image.width()/3, image.height()/3) #format text for display #text_elided = size_calculator.elidedText(entry[3].upper(), Qt.ElideRight, max_text_bound.width(), Qt.TextWordWrap) text_upper = entry[3].upper() text_bounds = size_calculator.boundingRect(max_text_bound, Qt.TextWordWrap, text_upper) text_width = text_bounds.width() text_height = text_bounds.height() #calculate positions margin_ver = 0.018*image.height() #margin_hor = 0.01*image.width() lower_bound = image.height()-margin_ver upper_bound = lower_bound-lowerRight.height()-text_height-upperLeft.height() #begin painting on image painter.begin(image) #first paint category painter.drawImage(image.width()-category.width()-margin_hor, margin_ver, category) # now background rectangle and corners + comment if len(text_upper) > 0: painter.fillRect(margin_hor, upper_bound , lowerLeft.width()+text_width+lowerRight.width(), lowerLeft.height()+text_height+upperLeft.height(), QColor(qRgb(255,255,255))) painter.drawImage(margin_hor, lower_bound-lowerLeft.height(), lowerLeft) painter.drawImage(margin_hor, upper_bound, upperLeft) painter.drawImage(margin_hor+lowerLeft.width()+text_width, upper_bound, upperRight) painter.drawImage(margin_hor+lowerLeft.width()+text_width,lower_bound-lowerRight.height(), lowerRight) # write text to prepared rectangle painter.setPen(QColor(qRgb(17,195,159))) painter.setFont(self.voivoifont) #print(text_upper) painter.drawText(margin_hor+lowerLeft.width(),image.height()-lowerRight.height()-margin_ver-text_height, text_width, text_height, Qt.TextWordWrap, text_upper) painter.end()
def _updateSpacing(self): fm = QFontMetrics(self.noteFont) br = fm.boundingRect("X") self.xSpacing = 1.2 * br.width() + 2 br = fm.tightBoundingRect("X") self.ySpacing = br.height() + 2
class PackageDelegate(QStyledItemDelegate): AppStyle = qApp.style def __init__(self, parent=None, mainWindow=None, showDetailsButton=True, animatable=True): super(PackageDelegate, self).__init__(parent) self.webDialog = WebDialog(mainWindow) self.show_details_button = showDetailsButton self.rowAnimator = RowAnimator(parent.packageList) self.defaultIcon = KIcon(('package-x-generic', 'package_applications'), 32) self.defaultInstalledIcon = QIcon(KIconLoader.loadOverlayed(('package-x-generic', 'package_applications'), CHECK_ICON, 32)) self.animatable = animatable self._max_height = ROW_HEIGHT self._rt_0 = QIcon(":/data/star_0.png") self._rt_1 = QIcon(":/data/star_1.png") self.types = {'critical':(RED, i18n('critical')), 'security':(DARKRED, i18n('security'))} self.font = Pds.settings('font','Sans,10').split(',')[0] self.normalFont = QFont(self.font, 10, QFont.Normal) self.boldFont = QFont(self.font, 11, QFont.Bold) self.normalDetailFont = QFont(self.font, 9, QFont.Normal) self.boldDetailFont = QFont(self.font, 9, QFont.Bold) self.tagFont = QFont(self.font, 7, QFont.Normal) self.tagFontFM = QFontMetrics(self.tagFont) self.boldFontFM = QFontMetrics(self.boldFont) self.boldDetailFontFM = QFontMetrics(self.boldDetailFont) self.normalFontFM = QFontMetrics(self.normalFont) self.normalDetailFontFM = QFontMetrics(self.normalDetailFont) self._titles = {'description': i18n("Description:"), 'website' : i18n("Website:"), 'release' : i18n("Release:"), 'repository' : i18n("Repository:"), 'size' : i18n("Package Size:"), 'installVers': i18n("Installed Version:")} self._titleFM = {} for key, value in self._titles.items(): self._titleFM[key] = self.boldDetailFontFM.width(value) + ICON_SIZE + 3 self.baseWidth = self.boldFontFM.width(max(self._titles.values(), key=len)) + ICON_SIZE self.parent = parent.packageList # Base style for some of important features # self.plastik = QStyleFactory.create('plastique') def paint(self, painter, option, index): if not index.isValid(): return super(PackageDelegate, self).paint(painter, option, index) if index.flags() & Qt.ItemIsUserCheckable: if index.column() == 0: self.paintCheckBoxColumn(painter, option, index) else: self.paintInfoColumn(painter, option, index) else: self.paintInfoColumn(painter, option, index, width_limit = 10) def paintCheckBoxColumn(self, painter, option, index): opt = QStyleOptionViewItemV4(option) buttonStyle = QStyleOptionButton() buttonStyle.state = QStyle.State_On if index.model().data(index, Qt.CheckStateRole) == QVariant(Qt.Checked) else QStyle.State_Off if option.state & QStyle.State_MouseOver or option.state & QStyle.State_HasFocus: buttonStyle.state |= QStyle.State_HasFocus buttonStyle.rect = opt.rect.adjusted(4, -opt.rect.height() + ROW_HEIGHT, 0, 0) PackageDelegate.AppStyle().drawControl(QStyle.CE_CheckBox, buttonStyle, painter, None) def paintInfoColumn(self, painter, option, index, width_limit = 0): left = option.rect.left() + 3 top = option.rect.top() width = option.rect.width() - width_limit pixmap = QPixmap(option.rect.size()) pixmap.fill(Qt.transparent) p = QPainter(pixmap) p.setRenderHint(QPainter.Antialiasing, True) p.translate(-option.rect.topLeft()) textInner = 2 * ICON_PADDING + ROW_HEIGHT - 10 itemHeight = ROW_HEIGHT + 2 * ICON_PADDING margin = left + ICON_PADDING - 10 title = index.model().data(index, NameRole).toString() summary = index.model().data(index, SummaryRole).toString() ptype = str(index.model().data(index, TypeRole).toString()) rate = int(index.model().data(index, RateRole).toInt()[0]) installed = index.model().data(index, InstalledRole).toBool() # We need to request update if its not possible to get meta data about the package try: # Get Package Icon if exists _icon = index.model().data(index, Qt.DecorationRole).toString() except: p.end() painter.drawPixmap(option.rect.topLeft(), pixmap) self.parent.requestUpdate() return icon = None if _icon: overlay = [CHECK_ICON] if installed else [] KIconLoader._forceCache = True pix = KIconLoader.loadOverlayed(_icon, overlay, 32) if not pix.isNull(): icon = QIcon(pix.scaled(QSize(32, 32), Qt.KeepAspectRatio, Qt.SmoothTransformation)) KIconLoader._forceCache = False if not icon: icon = self.defaultIcon if not installed else self.defaultInstalledIcon # Paint the Icon icon.paint(p, margin, top + ICON_PADDING, ROW_HEIGHT, ROW_HEIGHT, Qt.AlignCenter) fix_pos = 0 if index.model().columnCount() <= 1: fix_pos = 22 if config.USE_APPINFO: # Rating Stars for _rt_i in range(5): self._rt_0.paint(p, width + 10 * _rt_i - 30 - fix_pos, top + ROW_HEIGHT / 4, 10, 10, Qt.AlignCenter) for _rt_i in range(rate): self._rt_1.paint(p, width + 10 * _rt_i - 30 - fix_pos, top + ROW_HEIGHT / 4, 10, 10, Qt.AlignCenter) foregroundColor = option.palette.color(QPalette.Text) p.setPen(foregroundColor) # Package Name p.setFont(self.boldFont) p.drawText(left + textInner, top, width - textInner, itemHeight / 2, Qt.AlignBottom | Qt.AlignLeft, title) tagWidth = 0 _component_width = 0 if self.parent.showComponents: component = str(index.model().data(index, ComponentRole).toString()) widthOfTitle = self.boldFontFM.width(title) + 6 + left + textInner p.setFont(self.tagFont) rect = self.tagFontFM.boundingRect(option.rect, Qt.TextWordWrap, component) p.setPen(LIGHTGREEN) p.setBrush(LIGHTGREEN) p.drawRoundRect(widthOfTitle , top + 12, rect.width() + 4, rect.height(), 10, 10) p.setPen(DARKGREEN) p.drawText(widthOfTitle + 2, top + 12, rect.width(), rect.height(), Qt.AlignCenter, component) p.setPen(foregroundColor) _component_width = rect.width() + 8 if self.parent.showIsA: isa = str(index.model().data(index, IsaRole).toString()) if not isa == '': widthOfTitle = self.boldFontFM.width(title) + 6 + left + textInner + _component_width p.setFont(self.tagFont) rect = self.tagFontFM.boundingRect(option.rect, Qt.TextWordWrap, isa) p.setPen(LIGHTBLUE) p.setBrush(LIGHTBLUE) p.drawRoundRect(widthOfTitle , top + 12, rect.width() + 4, rect.height(), 10, 10) p.setPen(DARKVIOLET) p.drawText(widthOfTitle + 2, top + 12, rect.width(), rect.height(), Qt.AlignCenter, isa) p.setPen(foregroundColor) _component_width += rect.width() + 8 if ptype not in ('None', 'normal'): widthOfTitle = self.boldFontFM.width(title) + 6 + left + textInner + _component_width p.setFont(self.tagFont) rect = self.tagFontFM.boundingRect(option.rect, Qt.TextWordWrap, self.types[ptype][1]) p.setPen(self.types[ptype][0]) p.setBrush(self.types[ptype][0]) p.drawRoundRect(widthOfTitle, top + 12, rect.width() + 4, rect.height(), 10, 10) p.setPen(WHITE) p.drawText(widthOfTitle + 2, top + 12, rect.width(), rect.height(), Qt.AlignCenter, self.types[ptype][1]) p.setPen(foregroundColor) tagWidth = rect.width() # Package Summary p.setFont(self.normalFont) foregroundColor.setAlpha(160) p.setPen(foregroundColor) elided_summary = self.normalFontFM.elidedText(summary, Qt.ElideRight, width - textInner - tagWidth - 22) p.drawText(left + textInner, top + itemHeight / 2, width - textInner, itemHeight / 2, Qt.TextDontClip, elided_summary) foregroundColor.setAlpha(255) p.setPen(foregroundColor) buttonStyle = None if self.rowAnimator.currentRow() == index.row(): description = index.model().data(index, DescriptionRole).toString() size = index.model().data(index, SizeRole).toString() homepage = index.model().data(index, HomepageRole).toString() installedVersion = str(index.model().data(index, InstalledVersionRole).toString()) version = index.model().data(index, VersionRole) # Package Detail Label position = top + ROW_HEIGHT p.setFont(self.normalDetailFont) baseRect = QRect(left, position, width - 8, option.rect.height()) rect = self.normalDetailFontFM.boundingRect(baseRect, Qt.TextWordWrap | Qt.TextDontClip, description) p.drawText(left + 2, position, width - 8, rect.height(), Qt.TextWordWrap | Qt.TextDontClip, description) # Package Detail Homepage position += rect.height() + 4 p.setFont(self.boldDetailFont) p.drawText(left + ICON_SIZE , position, width - textInner, itemHeight / 2, Qt.AlignLeft, self._titles['website']) p.setFont(self.normalDetailFont) homepage = self.normalDetailFontFM.elidedText(homepage, Qt.ElideRight, width - self._titleFM['website']) rect = self.normalDetailFontFM.boundingRect(option.rect, Qt.TextSingleLine, homepage) self.rowAnimator.hoverLinkFilter.link_rect = QRect(left + self._titleFM['website'] + 2, position + 2 + 32, rect.width(), rect.height()) p.setPen(option.palette.color(QPalette.Link)) p.drawText(left + self._titleFM['website'], position, width, rect.height(), Qt.TextSingleLine, homepage) p.setPen(foregroundColor) # Package Detail Version position += rect.height() p.setFont(self.boldDetailFont) p.drawText(left + ICON_SIZE , position, width - textInner, itemHeight / 2, Qt.AlignLeft, self._titles['release']) p.setFont(self.normalDetailFont) rect = self.normalDetailFontFM.boundingRect(option.rect, Qt.TextWordWrap, version.toString()) p.drawText(left + self._titleFM['release'], position, width, rect.height(), Qt.TextWordWrap, version.toString()) if not installedVersion == '': position += rect.height() p.setFont(self.boldDetailFont) p.drawText(left + ICON_SIZE , position, width - textInner, itemHeight / 2, Qt.AlignLeft, self._titles['installVers']) p.setFont(self.normalDetailFont) rect = self.normalDetailFontFM.boundingRect(option.rect, Qt.TextWordWrap, installedVersion) p.drawText(left + self._titleFM['installVers'], position, width, rect.height(), Qt.TextWordWrap, installedVersion) # Package Detail Repository repository = index.model().data(index, RepositoryRole).toString() if not repository == '': repository = i18n('Unknown') if repository == 'N/A' else repository position += rect.height() p.setFont(self.boldDetailFont) p.drawText(left + ICON_SIZE , position, width - textInner, itemHeight / 2, Qt.AlignLeft, self._titles['repository']) p.setFont(self.normalDetailFont) p.drawText(left + self._titleFM['repository'], position, width, itemHeight / 2, Qt.TextWordWrap, repository) # Package Detail Size position += rect.height() p.setFont(self.boldDetailFont) p.drawText(left + ICON_SIZE , position, width - textInner, itemHeight / 2, Qt.AlignLeft, self._titles['size']) p.setFont(self.normalDetailFont) p.drawText(left + self._titleFM['size'], position, width, itemHeight / 2, Qt.TextWordWrap, size) position += rect.height() self.rowAnimator.max_height = position - top + 8 # Package More info button opt = QStyleOptionViewItemV4(option) buttonStyle = QStyleOptionButton() if option.state & QStyle.State_MouseOver or option.state & QStyle.State_HasFocus: buttonStyle.state |= QStyle.State_HasFocus buttonStyle.state |= QStyle.State_Enabled buttonStyle.text = i18n("Details") buttonStyle.rect = QRect(width - 100, position - 22, 100, 22) p.end() # FIXME # if option.state & QStyle.State_HasFocus and self.animatable: # option.state |= QStyle.State_MouseOver # Use Plastique style to draw focus rect like MouseOver effect of Oxygen. # self.plastik.drawPrimitive(QStyle.PE_FrameLineEdit, option, painter, None) if not self.rowAnimator.running() and buttonStyle: if self.show_details_button and (installed or config.USE_APPINFO): PackageDelegate.AppStyle().drawControl(QStyle.CE_PushButton, buttonStyle, painter, None) self.rowAnimator.hoverLinkFilter.button_rect = QRect(buttonStyle.rect) painter.drawPixmap(option.rect.topLeft(), pixmap) del pixmap def editorEvent(self, event, model, option, index): if event.type() == QEvent.MouseButtonRelease and index.column() == 0 and index.flags() & Qt.ItemIsUserCheckable: toggled = Qt.Checked if model.data(index, Qt.CheckStateRole) == QVariant(Qt.Unchecked) else Qt.Unchecked return model.setData(index, toggled, Qt.CheckStateRole) __event = QItemDelegate(self).editorEvent(event, model, option, index) animate_requested = False if event.type() == QEvent.MouseButtonRelease and self.animatable: if self.rowAnimator.row == index.row(): epos = event.pos() if self.rowAnimator.hoverLinkFilter.link_rect.contains(QPoint(epos.x(), epos.y() + 32)): url = QUrl(model.data(index, HomepageRole).toString()) QDesktopServices.openUrl(url) return __event elif self.rowAnimator.hoverLinkFilter.button_rect.contains(epos, True): self.showPackageDetails(model, index) return __event animate_requested = True elif event.type() == QEvent.KeyPress and self.animatable: # KeyCode 32 : Space key if event.key() == 32 and index.column() == index.model().columnCount() - 1: animate_requested = True if not unicode(model.data(index, DescriptionRole).toString()) == '' and animate_requested: self.rowAnimator.animate(index.row()) return __event def showPackageDetails(self, model, index): def _getter(role): return model.data(index, role).toString() name = _getter(NameRole) summary = _getter(SummaryRole) description = _getter(DescriptionRole) installed = model.data(index, InstalledRole).toBool() self.webDialog.showPackageDetails(name, installed, summary, description) def sizeHint(self, option, index): if self.rowAnimator.currentRow() == index.row() and not index.row() == 0: return self.rowAnimator.size() else: width = ICON_SIZE if index.column() == 0 else 0 return QSize(width, ROW_HEIGHT) def setAnimatable(self, animatable): self.animatable = animatable def reset(self): self.rowAnimator.reset()
def __createLayout(self): " Creates the dialog layout " self.resize(640, 480) self.setSizeGripEnabled(True) layout = QVBoxLayout() # Plugins list self.__pluginsView = QTreeWidget() self.__pluginsView.setAlternatingRowColors(True) self.__pluginsView.setRootIsDecorated(False) self.__pluginsView.setItemsExpandable(False) self.__pluginsView.setSortingEnabled(True) self.__pluginsView.setItemDelegate(NoOutlineHeightDelegate(4)) self.__pluginsView.setUniformRowHeights(True) # Alert | system/user | Enable | Name | Version self.__pluginsHeader = QTreeWidgetItem( ["", "", "", "Name", "Version", ""]) self.__pluginsView.setHeaderItem(self.__pluginsHeader) self.__pluginsView.header().setSortIndicator(NAME_COL, Qt.AscendingOrder) self.connect(self.__pluginsView, SIGNAL("itemSelectionChanged()"), self.__pluginSelectionChanged) self.connect(self.__pluginsView, SIGNAL("itemChanged(QTreeWidgetItem*,int)"), self.__onItemChanged) layout.addWidget(self.__pluginsView) # Detailed information detailsLabel = QLabel("Detailed information") layout.addWidget(detailsLabel) self.__details = QTreeWidget() self.__details.setAlternatingRowColors(False) self.__details.setRootIsDecorated(False) self.__details.setItemsExpandable(False) self.__details.setSortingEnabled(False) self.__details.setItemDelegate(NoOutlineHeightDelegate(4)) self.__details.setUniformRowHeights(True) detailsHeader = QTreeWidgetItem(["", ""]) self.__details.setHeaderItem(detailsHeader) self.__details.setHeaderHidden(True) metrics = QFontMetrics(self.__details.font()) rect = metrics.boundingRect("X") self.__details.setFixedHeight(rect.height() * 6 + 5) layout.addWidget(self.__details) # Errors/warnings errorsLabel = QLabel("Errors / warnings") layout.addWidget(errorsLabel) self.__errorsText = QTextEdit() self.__errorsText.setReadOnly(True) self.__errorsText.setAcceptRichText(False) metrics = QFontMetrics(self.__errorsText.font()) rect = metrics.boundingRect("X") self.__errorsText.setFixedHeight(rect.height() * 4 + 5) layout.addWidget(self.__errorsText) # Buttons box buttonBox = QDialogButtonBox(self) buttonBox.setOrientation(Qt.Horizontal) buttonBox.setStandardButtons(QDialogButtonBox.Ok) self.__OKButton = buttonBox.button(QDialogButtonBox.Ok) self.__OKButton.setDefault(True) self.connect(buttonBox, SIGNAL("accepted()"), self.close) self.connect(buttonBox, SIGNAL("rejected()"), self.close) layout.addWidget(buttonBox) self.setLayout(layout) return
def __createLayout(self, pathsToCommit, pathsToIgnore): " Creates the dialog layout " self.resize(640, 480) self.setSizeGripEnabled(True) vboxLayout = QVBoxLayout(self) # Paths to commit part commitHeaderFrame = QFrame() commitHeaderFrame.setFrameStyle(QFrame.StyledPanel) commitHeaderFrame.setAutoFillBackground(True) self.__setLightPalette(commitHeaderFrame) commitHeaderFrame.setFixedHeight(24) expandingCommitSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding) self.__selectAllButton = QToolButton() self.__selectAllButton.setAutoRaise(True) self.__selectAllButton.setIcon( PixmapCache().getIcon(pluginHomeDir + 'svnselectall.png')) self.__selectAllButton.setFixedSize(20, 20) self.__selectAllButton.setToolTip("Select all") self.__selectAllButton.setFocusPolicy(Qt.NoFocus) self.__selectAllButton.clicked.connect(self.__onSelectAll) commitHeaderLayout = QHBoxLayout() commitHeaderLayout.setContentsMargins(3, 0, 0, 0) commitHeaderLayout.addWidget( QLabel("Paths to commit (total: " + str(len(pathsToCommit)) + ")")) commitHeaderLayout.addSpacerItem(expandingCommitSpacer) commitHeaderLayout.addWidget(self.__selectAllButton) commitHeaderFrame.setLayout(commitHeaderLayout) vboxLayout.addWidget(commitHeaderFrame) self.__pathToCommitView = QTreeWidget() self.__configTable(self.__pathToCommitView) self.__pathToCommitHeader = QTreeWidgetItem(["", "Path", "Status", ""]) self.__pathToCommitView.setHeaderItem(self.__pathToCommitHeader) self.__pathToCommitView.header().setSortIndicator( PATH_COL, Qt.AscendingOrder) self.__pathToCommitView.itemChanged.connect(self.__onCommitPathChanged) vboxLayout.addWidget(self.__pathToCommitView) # Paths to ignore part headerFrame = QFrame() headerFrame.setFrameStyle(QFrame.StyledPanel) headerFrame.setAutoFillBackground(True) self.__setLightPalette(headerFrame) headerFrame.setFixedHeight(24) ignoreLabel = QLabel("Ignored paths (total: " + str(len(pathsToIgnore)) + ")") expandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding) self.__showHideIgnoredButton = QToolButton() self.__showHideIgnoredButton.setAutoRaise(True) self.__showHideIgnoredButton.setIcon(PixmapCache().getIcon('less.png')) self.__showHideIgnoredButton.setFixedSize(20, 20) self.__showHideIgnoredButton.setToolTip("Show ignored path list") self.__showHideIgnoredButton.setFocusPolicy(Qt.NoFocus) self.__showHideIgnoredButton.clicked.connect(self.__onShowHideIgnored) ignoredHeaderLayout = QHBoxLayout() ignoredHeaderLayout.setContentsMargins(3, 0, 0, 0) ignoredHeaderLayout.addWidget(ignoreLabel) ignoredHeaderLayout.addSpacerItem(expandingSpacer) ignoredHeaderLayout.addWidget(self.__showHideIgnoredButton) headerFrame.setLayout(ignoredHeaderLayout) vboxLayout.addWidget(headerFrame) self.__pathToIgnoreView = QTreeWidget() self.__configTable(self.__pathToIgnoreView) self.__pathToIgnoreView.setVisible(False) pathToIgnoreHeader = QTreeWidgetItem(["Path", "Status"]) self.__pathToIgnoreView.setHeaderItem(pathToIgnoreHeader) self.__pathToIgnoreView.header().setSortIndicator(0, Qt.AscendingOrder) vboxLayout.addWidget(self.__pathToIgnoreView) # Message part vboxLayout.addWidget(QLabel("Message")) self.__message = QTextEdit() self.__message.setAcceptRichText(False) metrics = QFontMetrics(self.__message.font()) rect = metrics.boundingRect("X") self.__message.setFixedHeight(rect.height() * 4 + 5) vboxLayout.addWidget(self.__message) # Diff part diffHeaderFrame = QFrame() diffHeaderFrame.setFrameStyle(QFrame.StyledPanel) diffHeaderFrame.setAutoFillBackground(True) self.__setLightPalette(diffHeaderFrame) diffHeaderFrame.setFixedHeight(24) diffLabel = QLabel("Diff") diffExpandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding) self.__showHideDiffButton = QToolButton() self.__showHideDiffButton.setAutoRaise(True) self.__showHideDiffButton.setIcon(PixmapCache().getIcon('less.png')) self.__showHideDiffButton.setFixedSize(20, 20) self.__showHideDiffButton.setToolTip("Show diff") self.__showHideDiffButton.setFocusPolicy(Qt.NoFocus) self.__showHideDiffButton.clicked.connect(self.__onShowHideDiff) diffLayout = QHBoxLayout() diffLayout.setContentsMargins(3, 0, 0, 0) diffLayout.addWidget(diffLabel) diffLayout.addSpacerItem(diffExpandingSpacer) diffLayout.addWidget(self.__showHideDiffButton) diffHeaderFrame.setLayout(diffLayout) self.__diffViewer = DiffTabWidget() self.__diffViewer.setHTML(self.NODIFF) self.__diffViewer.setVisible(False) vboxLayout.addWidget(diffHeaderFrame) vboxLayout.addWidget(self.__diffViewer) # Buttons at the bottom buttonBox = QDialogButtonBox(self) buttonBox.setOrientation(Qt.Horizontal) buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.__OKButton = buttonBox.button(QDialogButtonBox.Ok) self.__OKButton.setText("Commit") buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) buttonBox.accepted.connect(self.userAccept) buttonBox.rejected.connect(self.close) vboxLayout.addWidget(buttonBox) return
class KnobWidget(QWidget): STYLE_ROUND = 1 STYLE_NEEDLE = 2 def __init__(self, parent=None): QWidget.__init__(self, parent) self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.minimum_value = -100 self.maximum_value = 100 self.value_range = self.maximum_value - self.minimum_value self.total_angle = 200 # degree self.pressed = False self.scale_visible = True self.scale_arc_visible = True self.scale_text_visible = True self.scale_step_size = 10 self.scale_step_divisions = 2 self.knob_radius = 20 # px self.knob_style = KnobWidget.STYLE_ROUND self.dynamic_resize = False self.dynamic_knob_radius = None self.needle_base_radius = 7 # px self.needle_color = Qt.red self.knob_to_scale = 4 # px self.knob_scaleless_to_border = 1 # px, applied if scale not visible self.base_color = QColor(245, 245, 245) self.base_color_pressed = Qt.red self.mark_color = Qt.black self.border_color = QColor(190, 190, 190) self.tick_size_large = 9 # px self.tick_size_small = 5 # px self.tick_to_text = 4 # px self.text_to_border = 2 # px self.text_radius = None self.title_text = None self.value = self.value_range / 2 self.value_factor = float(self.value - self.minimum_value) / self.value_range self.font_metrics = QFontMetrics(self.font()) self.recalculate_size() # override QWidget.resizeEvent def resizeEvent(self, event): QWidget.resizeEvent(self, event) self.recalculate_size() # override QWidget.paintEvent def paintEvent(self, event): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) width = self.width() height = self.height() if self.dynamic_resize: knob_radius = self.dynamic_knob_radius else: knob_radius = self.knob_radius # ensure that the center point is in the middle of a pixel to ensure # that exact vertial and horizantal ticks are drawn exactly 1px wide x = math.floor(width / 2.0) + 0.5 y = math.floor(height / 2.0) + 0.5 if DEBUG: painter.fillRect(0, 0, width, height, Qt.yellow) painter.translate(x, y) if self.knob_style == KnobWidget.STYLE_NEEDLE: r = min(x, y) - 1 painter.setPen(Qt.white) painter.setBrush(Qt.white) painter.drawEllipse(QPoint(0, 0), r, r) angle = self.value_factor * self.total_angle - (self.total_angle / 2.0) # draw base knob or needle spike if self.knob_style == KnobWidget.STYLE_ROUND: painter.setPen(self.border_color) if self.pressed: gradient = QRadialGradient(0, 0, knob_radius) gradient.setColorAt(0, self.base_color_pressed) gradient.setColorAt(0.85, self.base_color) gradient.setColorAt(1, self.base_color) painter.setBrush(gradient) else: painter.setBrush(self.base_color) painter.drawEllipse(QPoint(0, 0), knob_radius, knob_radius) elif self.knob_style == KnobWidget.STYLE_NEEDLE: painter.save() painter.rotate(angle) painter.setPen(self.needle_color) painter.setBrush(self.needle_color) needle = QPolygonF() needle.append(QPointF(self.needle_base_radius * 0.6, 0)) needle.append(QPointF(0, -knob_radius)) needle.append(QPointF(-self.needle_base_radius * 0.6, 0)) painter.drawPolygon(needle) painter.restore() # draw knob mark or needle base if self.knob_style == KnobWidget.STYLE_ROUND: painter.save() painter.rotate(angle) painter.setPen(QPen(self.mark_color, 2)) painter.drawLine(0, -knob_radius * 0.4, 0, -knob_radius * 0.8) painter.restore() elif self.knob_style == KnobWidget.STYLE_NEEDLE: painter.setPen(self.border_color) painter.setBrush(self.base_color) painter.drawEllipse(QPoint(0, 0), self.needle_base_radius, self.needle_base_radius) if self.scale_visible: painter.setPen(Qt.black) # draw scale arc if self.scale_arc_visible: painter.drawArc(-knob_radius - self.knob_to_scale, -knob_radius - self.knob_to_scale, knob_radius * 2 + self.knob_to_scale * 2, knob_radius * 2 + self.knob_to_scale * 2, (90 + self.total_angle / 2) * 16, -self.total_angle * 16) # draw scale ticks def value_to_angle(value): return (float(value - self.minimum_value) / self.value_range) * self.total_angle - (self.total_angle / 2.0) value = self.minimum_value while value <= self.maximum_value: angle = value_to_angle(value) painter.save() painter.rotate(value_to_angle(value)) painter.drawLine(0, -knob_radius - self.knob_to_scale, 0, -knob_radius - self.knob_to_scale - self.tick_size_large) if self.scale_text_visible: p = painter.worldTransform().map(QPoint(0, -knob_radius - \ self.knob_to_scale - \ self.tick_size_large - \ self.tick_to_text - \ self.text_radius)) painter.restore() if self.scale_text_visible: if DEBUG: painter.save() painter.setPen(QColor(255, 0, 0, 50)) painter.setBrush(QColor(255, 0, 0, 50)) painter.drawEllipse(QPoint(p.x() - x, p.y() - y), self.text_radius, self.text_radius) painter.restore() painter.drawText(p.x() - x - 30, p.y() - y - 30, 60, 60, Qt.TextDontClip | Qt.AlignHCenter | Qt.AlignVCenter, str(value)) for i in range(1, self.scale_step_divisions): sub_value = value + (float(self.scale_step_size) * i) / self.scale_step_divisions if sub_value > self.maximum_value: break painter.save() painter.rotate(value_to_angle(sub_value)) painter.drawLine(0, -knob_radius - self.knob_to_scale, 0, -knob_radius - self.knob_to_scale - self.tick_size_small) painter.restore() value += self.scale_step_size if self.title_text != None: painter.drawText(-knob_radius, knob_radius - 30, knob_radius * 2, 60, Qt.TextDontClip | Qt.AlignHCenter | Qt.AlignVCenter, self.title_text) def recalculate_size(self): if self.scale_visible: if self.scale_text_visible: text_width = 0 text_height = 0 value = self.minimum_value while value <= self.maximum_value: text_rect = self.font_metrics.boundingRect(str(value)) text_width = max(text_width, text_rect.width()) text_height = max(text_height, text_rect.height()) value += self.scale_step_size self.text_radius = math.sqrt((text_width / 2.0) ** 2 + (text_height / 2.0) ** 2) else: self.text_radius = 0 additional_radius = self.knob_to_scale + \ self.tick_size_large + \ self.tick_to_text + \ self.text_radius * 2 + \ self.text_to_border else: additional_radius = self.knob_scaleless_to_border diameter = (self.knob_radius + additional_radius) * 2 self.setMinimumSize(diameter, diameter) if self.dynamic_resize: radius = min(self.width(), self.height()) / 2 self.dynamic_knob_radius = radius - additional_radius def set_scale_visible(self, visible): self.scale_visible = visible self.recalculate_size() self.update() def set_scale_arc_visible(self, visible): self.scale_arc_visible = visible self.update() def set_scale_text_visible(self, visible): self.scale_text_visible = visible self.recalculate_size() self.update() def set_total_angle(self, total_angle): self.total_angle = max(min(total_angle, 360), 1) self.recalculate_size() self.set_value(self.value) def set_pressed(self, pressed): self.pressed = pressed self.update() def set_range(self, minimum_value, maximum_value): self.minimum_value = minimum_value self.maximum_value = maximum_value self.value_range = self.maximum_value - self.minimum_value self.recalculate_size() self.set_value(self.value) def set_knob_radius(self, radius): self.knob_radius = max(1, radius) self.recalculate_size() self.update() def set_knob_style(self, style): self.knob_style = style self.update() def set_dynamic_resize_enabled(self, enable): self.dynamic_resize = enable if self.dynamic_resize: self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) else: self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.recalculate_size() self.update() def set_scale(self, scale_step_size, scale_step_divisions): self.scale_step_size = max(EPSILON, scale_step_size) self.scale_step_divisions = scale_step_divisions self.recalculate_size() self.update() def set_title_text(self, text): self.title_text = text self.update() def set_value(self, value): self.value = max(min(value, self.maximum_value), self.minimum_value) self.value_factor = float(self.value - self.minimum_value) / self.value_range self.update() def get_value(self): return self.value
def sizeHint(self): metrics = QFontMetrics(self.font()) rect = metrics.boundingRect(self.text()) size = QSize(rect.height() + self.margin(), rect.width() + self.margin()) return size
def __createLayout( self, pathsToCommit, pathsToIgnore ): " Creates the dialog layout " self.resize( 640, 480 ) self.setSizeGripEnabled( True ) vboxLayout = QVBoxLayout( self ) # Paths to commit part commitHeaderFrame = QFrame() commitHeaderFrame.setFrameStyle( QFrame.StyledPanel ) commitHeaderFrame.setAutoFillBackground( True ) self.__setLightPalette( commitHeaderFrame ) commitHeaderFrame.setFixedHeight( 24 ) expandingCommitSpacer = QSpacerItem( 10, 10, QSizePolicy.Expanding ) self.__selectAllButton = QToolButton() self.__selectAllButton.setAutoRaise( True ) self.__selectAllButton.setIcon( PixmapCache().getIcon( pluginHomeDir + 'svnselectall.png' ) ) self.__selectAllButton.setFixedSize( 20, 20 ) self.__selectAllButton.setToolTip( "Select all" ) self.__selectAllButton.setFocusPolicy( Qt.NoFocus ) self.__selectAllButton.clicked.connect( self.__onSelectAll ) commitHeaderLayout = QHBoxLayout() commitHeaderLayout.setContentsMargins( 3, 0, 0, 0 ) commitHeaderLayout.addWidget( QLabel( "Paths to commit (total: " + str( len( pathsToCommit ) ) + ")" ) ) commitHeaderLayout.addSpacerItem( expandingCommitSpacer ) commitHeaderLayout.addWidget( self.__selectAllButton ) commitHeaderFrame.setLayout( commitHeaderLayout ) vboxLayout.addWidget( commitHeaderFrame ) self.__pathToCommitView = QTreeWidget() self.__configTable( self.__pathToCommitView ) self.__pathToCommitHeader = QTreeWidgetItem( [ "", "Path", "Status", "" ] ) self.__pathToCommitView.setHeaderItem( self.__pathToCommitHeader ) self.__pathToCommitView.header().setSortIndicator( PATH_COL, Qt.AscendingOrder ) self.__pathToCommitView.itemChanged.connect( self.__onCommitPathChanged ) vboxLayout.addWidget( self.__pathToCommitView ) # Paths to ignore part headerFrame = QFrame() headerFrame.setFrameStyle( QFrame.StyledPanel ) headerFrame.setAutoFillBackground( True ) self.__setLightPalette( headerFrame ) headerFrame.setFixedHeight( 24 ) ignoreLabel = QLabel( "Ignored paths (total: " + str( len( pathsToIgnore ) ) + ")" ) expandingSpacer = QSpacerItem( 10, 10, QSizePolicy.Expanding ) self.__showHideIgnoredButton = QToolButton() self.__showHideIgnoredButton.setAutoRaise( True ) self.__showHideIgnoredButton.setIcon( PixmapCache().getIcon( 'less.png' ) ) self.__showHideIgnoredButton.setFixedSize( 20, 20 ) self.__showHideIgnoredButton.setToolTip( "Show ignored path list" ) self.__showHideIgnoredButton.setFocusPolicy( Qt.NoFocus ) self.__showHideIgnoredButton.clicked.connect( self.__onShowHideIgnored ) ignoredHeaderLayout = QHBoxLayout() ignoredHeaderLayout.setContentsMargins( 3, 0, 0, 0 ) ignoredHeaderLayout.addWidget( ignoreLabel ) ignoredHeaderLayout.addSpacerItem( expandingSpacer ) ignoredHeaderLayout.addWidget( self.__showHideIgnoredButton ) headerFrame.setLayout( ignoredHeaderLayout ) vboxLayout.addWidget( headerFrame ) self.__pathToIgnoreView = QTreeWidget() self.__configTable( self.__pathToIgnoreView ) self.__pathToIgnoreView.setVisible( False ) pathToIgnoreHeader = QTreeWidgetItem( [ "Path", "Status" ] ) self.__pathToIgnoreView.setHeaderItem( pathToIgnoreHeader ) self.__pathToIgnoreView.header().setSortIndicator( 0, Qt.AscendingOrder ) vboxLayout.addWidget( self.__pathToIgnoreView ) # Message part vboxLayout.addWidget( QLabel( "Message" ) ) self.__message = QTextEdit() self.__message.setAcceptRichText( False ) metrics = QFontMetrics( self.__message.font() ) rect = metrics.boundingRect( "X" ) self.__message.setFixedHeight( rect.height() * 4 + 5 ) vboxLayout.addWidget( self.__message ) # Diff part diffHeaderFrame = QFrame() diffHeaderFrame.setFrameStyle( QFrame.StyledPanel ) diffHeaderFrame.setAutoFillBackground( True ) self.__setLightPalette( diffHeaderFrame ) diffHeaderFrame.setFixedHeight( 24 ) diffLabel = QLabel( "Diff" ) diffExpandingSpacer = QSpacerItem( 10, 10, QSizePolicy.Expanding ) self.__showHideDiffButton = QToolButton() self.__showHideDiffButton.setAutoRaise( True ) self.__showHideDiffButton.setIcon( PixmapCache().getIcon( 'less.png' ) ) self.__showHideDiffButton.setFixedSize( 20, 20 ) self.__showHideDiffButton.setToolTip( "Show diff" ) self.__showHideDiffButton.setFocusPolicy( Qt.NoFocus ) self.__showHideDiffButton.clicked.connect( self.__onShowHideDiff ) diffLayout = QHBoxLayout() diffLayout.setContentsMargins( 3, 0, 0, 0 ) diffLayout.addWidget( diffLabel ) diffLayout.addSpacerItem( diffExpandingSpacer ) diffLayout.addWidget( self.__showHideDiffButton ) diffHeaderFrame.setLayout( diffLayout ) self.__diffViewer = DiffTabWidget() self.__diffViewer.setHTML( self.NODIFF ) self.__diffViewer.setVisible( False ) vboxLayout.addWidget( diffHeaderFrame ) vboxLayout.addWidget( self.__diffViewer ) # Buttons at the bottom buttonBox = QDialogButtonBox( self ) buttonBox.setOrientation( Qt.Horizontal ) buttonBox.setStandardButtons( QDialogButtonBox.Ok | QDialogButtonBox.Cancel ) self.__OKButton = buttonBox.button( QDialogButtonBox.Ok ) self.__OKButton.setText( "Commit" ) buttonBox.button( QDialogButtonBox.Cancel ).setDefault( True ) buttonBox.accepted.connect( self.userAccept ) buttonBox.rejected.connect( self.close ) vboxLayout.addWidget( buttonBox ) return
def blink_cursor(cls, textedit, color=None): """Highlights the cursor in a Q(Plain)TextEdit.""" metrics = QFontMetrics(textedit.textCursor().charFormat().font()) width = metrics.boundingRect("m").width() rect = textedit.cursorRect().normalized().adjusted(0, 0, width, 0) cls.blink(textedit, rect.translated(textedit.viewport().pos()), color)
class LayerPainter( object ): def __init__(self): self.layer = None self.rect = QRect() self.fm = QFontMetrics(QFont()) self.iconSize = 20 self.iconXOffset = 5 self.textXOffset = 5 self.progressXOffset = self.iconXOffset+self.iconSize+self.textXOffset self.progressYOffset = self.iconSize+5 self.progressHeight = 10 self.alphaTextWidth = self.fm.boundingRect(u"\u03B1=100.0%").width() def sizeHint(self, mode): if mode == 'ReadOnly': return QSize(1,self.fm.height()+5) elif mode == 'Expanded' or mode == 'Editable': return QSize(1,self.progressYOffset+self.progressHeight+5) else: raise RuntimeError("Unknown mode") def overEyeIcon(self, x, y): #with a sufficiently large height (100) #we make sure that the user can also click below the eye to toggle #the layer return QPoint(x,y) in QRect(self.iconXOffset,0,self.iconSize,100) def percentForPosition(self, x, y, parentWidth, checkBoundaries=True): """ For some strange reason, self.rect.width() is sometimes 0 when this is called. For that reason, we can't use self._progressWidth and we must pass in the parentWidth as an argument. """ if checkBoundaries and (y < self.progressYOffset or y > self.progressYOffset + self.progressHeight) \ or (x < self.progressXOffset): return -1 percent = (x-self.progressXOffset)/float(parentWidth-self.progressXOffset-10) if percent < 0: return 0.0 if percent > 1: return 1.0 return percent @property def _progressWidth(self): return self.rect.width()-self.progressXOffset-10 def paint(self, painter, rect, palette, mode, isSelected): if not self.layer.visible: palette.setCurrentColorGroup(QPalette.Disabled) self.rect = rect painter.save() painter.setRenderHint(QPainter.Antialiasing, True) painter.setBrush(palette.text()) if isSelected: painter.save() painter.setBrush(palette.highlight()) painter.drawRect(rect) painter.restore() painter.translate(rect.x(), rect.y()) painter.setFont(QFont()) textOffsetX = self.progressXOffset textOffsetY = max(self.fm.height()-self.iconSize,0)/2.0+self.fm.height() if self.layer.visible: painter.drawImage(QRect(self.iconXOffset,0,self.iconSize,self.iconSize), \ QImage(":icons/icons/stock-eye-20.png")) else: painter.drawImage(QRect(self.iconXOffset,0,self.iconSize,self.iconSize), \ QImage(":icons/icons/stock-eye-20-gray.png")) if self.layer.direct: painter.save() painter.setBrush(palette.text()) painter.drawEllipse(self.iconXOffset+self.iconSize/2-2, self.iconSize+3, 4,4 ) painter.restore() #layer name text if mode != 'ReadOnly': painter.setBrush(palette.highlightedText()) else: painter.setBrush(palette.text()) #layer name painter.drawText(QPoint(textOffsetX, textOffsetY), "%s" % self.layer.name) #opacity text = u"\u03B1=%0.1f%%" % (100.0*(self.layer.opacity)) painter.drawText(QPoint(textOffsetX+self._progressWidth-self.alphaTextWidth, textOffsetY), text) if mode != 'ReadOnly': #frame around percentage indicator painter.setBrush(palette.dark()) painter.save() #no fill color b = painter.brush(); b.setStyle(Qt.NoBrush); painter.setBrush(b) painter.drawRect(QRect(QPoint(self.progressXOffset, self.progressYOffset), \ QSize(self._progressWidth, self.progressHeight))) painter.restore() #percentage indicator painter.drawRect(QRect(QPoint(self.progressXOffset, self.progressYOffset), \ QSize(self._progressWidth*self.layer.opacity, self.progressHeight))) painter.restore()
def __createLayout( self ): " Creates the dialog layout " self.resize( 640, 480 ) self.setSizeGripEnabled( True ) layout = QVBoxLayout() # Plugins list self.__pluginsView = QTreeWidget() self.__pluginsView.setAlternatingRowColors( True ) self.__pluginsView.setRootIsDecorated( False ) self.__pluginsView.setItemsExpandable( False ) self.__pluginsView.setSortingEnabled( True ) self.__pluginsView.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) self.__pluginsView.setUniformRowHeights( True ) # Alert | system/user | Enable | Name | Version self.__pluginsHeader = QTreeWidgetItem( [ "", "", "", "Name", "Version", "" ] ) self.__pluginsView.setHeaderItem( self.__pluginsHeader ) self.__pluginsView.header().setSortIndicator( NAME_COL, Qt.AscendingOrder ) self.connect( self.__pluginsView, SIGNAL( "itemSelectionChanged()" ), self.__pluginSelectionChanged ) self.connect( self.__pluginsView, SIGNAL( "itemChanged(QTreeWidgetItem*,int)" ), self.__onItemChanged ) layout.addWidget( self.__pluginsView ) # Detailed information detailsLabel = QLabel( "Detailed information" ) layout.addWidget( detailsLabel ) self.__details = QTreeWidget() self.__details.setAlternatingRowColors( False ) self.__details.setRootIsDecorated( False ) self.__details.setItemsExpandable( False ) self.__details.setSortingEnabled( False ) self.__details.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) self.__details.setUniformRowHeights( True ) detailsHeader = QTreeWidgetItem( [ "", "" ] ) self.__details.setHeaderItem( detailsHeader ) self.__details.setHeaderHidden( True ) metrics = QFontMetrics( self.__details.font() ) rect = metrics.boundingRect( "X" ) self.__details.setFixedHeight( rect.height() * 6 + 5 ) layout.addWidget( self.__details ) # Errors/warnings errorsLabel = QLabel( "Errors / warnings" ) layout.addWidget( errorsLabel ) self.__errorsText = QTextEdit() self.__errorsText.setReadOnly( True ) self.__errorsText.setAcceptRichText( False ) metrics = QFontMetrics( self.__errorsText.font() ) rect = metrics.boundingRect( "X" ) self.__errorsText.setFixedHeight( rect.height() * 4 + 5 ) layout.addWidget( self.__errorsText ) # Buttons box buttonBox = QDialogButtonBox( self ) buttonBox.setOrientation( Qt.Horizontal ) buttonBox.setStandardButtons( QDialogButtonBox.Ok ) self.__OKButton = buttonBox.button( QDialogButtonBox.Ok ) self.__OKButton.setDefault( True ) self.connect( buttonBox, SIGNAL( "accepted()" ), self.close ) self.connect( buttonBox, SIGNAL( "rejected()" ), self.close ) layout.addWidget( buttonBox ) self.setLayout( layout ) return
def __createLayout(self): " Creates the dialog layout " self.resize(640, 480) self.setSizeGripEnabled(True) vboxLayout = QVBoxLayout(self) hLayout = QHBoxLayout() self.__propsView = QTreeWidget() self.__propsView.setAlternatingRowColors(True) self.__propsView.setRootIsDecorated(False) self.__propsView.setItemsExpandable(False) self.__propsView.setSortingEnabled(True) self.__propsView.setItemDelegate(NoOutlineHeightDelegate(4)) self.__propsView.itemSelectionChanged.connect( self.__propsSelectionChanged) propsViewHeader = QTreeWidgetItem(["Property Name", "Property Value"]) self.__propsView.setHeaderItem(propsViewHeader) self.__propsView.header().setSortIndicator(0, Qt.DescendingOrder) hLayout.addWidget(self.__propsView) self.__delButton = QToolButton() self.__delButton.setText("Delete") self.__delButton.setFocusPolicy(Qt.NoFocus) self.__delButton.setEnabled(False) self.__delButton.clicked.connect(self.__onDel) hLayout.addWidget(self.__delButton, 0, Qt.AlignBottom) vboxLayout.addLayout(hLayout) # Set property part setGroupbox = QGroupBox(self) setGroupbox.setTitle("Set Property") setLayout = QGridLayout(setGroupbox) setLayout.addWidget(QLabel("Name"), 0, 0, Qt.AlignTop | Qt.AlignRight) setLayout.addWidget(QLabel("Value"), 1, 0, Qt.AlignTop | Qt.AlignRight) self.__nameEdit = QLineEdit() self.__nameEdit.textChanged.connect(self.__nameChanged) setLayout.addWidget(self.__nameEdit, 0, 1) self.__valueEdit = QTextEdit() self.__valueEdit.setAcceptRichText(False) self.__valueEdit.textChanged.connect(self.__valueChanged) metrics = QFontMetrics(self.__valueEdit.font()) rect = metrics.boundingRect("X") self.__valueEdit.setFixedHeight(rect.height() * 4 + 5) setLayout.addWidget(self.__valueEdit, 1, 1) self.__setButton = QToolButton() self.__setButton.setText("Set") self.__setButton.setFocusPolicy(Qt.NoFocus) self.__setButton.setEnabled(False) self.__setButton.clicked.connect(self.__onSet) setLayout.addWidget(self.__setButton, 1, 2, Qt.AlignBottom | Qt.AlignHCenter) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( setGroupbox.sizePolicy().hasHeightForWidth()) setGroupbox.setSizePolicy(sizePolicy) vboxLayout.addWidget(setGroupbox) # Buttons at the bottom buttonBox = QDialogButtonBox(self) buttonBox.setOrientation(Qt.Horizontal) buttonBox.setStandardButtons(QDialogButtonBox.Ok) buttonBox.button(QDialogButtonBox.Ok).setDefault(True) buttonBox.accepted.connect(self.close) vboxLayout.addWidget(buttonBox) return
class PackageDelegate(QStyledItemDelegate): AppStyle = qApp.style def __init__(self, parent=None, mainWindow=None, showDetailsButton=True, animatable=True): super(PackageDelegate, self).__init__(parent) self.webDialog = WebDialog(mainWindow) self.show_details_button = showDetailsButton self.rowAnimator = RowAnimator(parent.packageList) self.defaultIcon = KIcon(('package-x-generic', 'package_applications'), 32) self.defaultInstalledIcon = QIcon( KIconLoader.loadOverlayed( ('package-x-generic', 'package_applications'), CHECK_ICON, 32)) self.animatable = animatable self._max_height = ROW_HEIGHT self._rt_0 = QIcon(":/data/star_0.png") self._rt_1 = QIcon(":/data/star_1.png") self.types = { 'critical': (RED, i18n('critical')), 'security': (DARKRED, i18n('security')) } self.font = Pds.settings('font', 'Sans,10').split(',')[0] self.normalFont = QFont(self.font, 10, QFont.Normal) self.boldFont = QFont(self.font, 11, QFont.Bold) self.normalDetailFont = QFont(self.font, 9, QFont.Normal) self.boldDetailFont = QFont(self.font, 9, QFont.Bold) self.tagFont = QFont(self.font, 7, QFont.Normal) self.tagFontFM = QFontMetrics(self.tagFont) self.boldFontFM = QFontMetrics(self.boldFont) self.boldDetailFontFM = QFontMetrics(self.boldDetailFont) self.normalFontFM = QFontMetrics(self.normalFont) self.normalDetailFontFM = QFontMetrics(self.normalDetailFont) self._titles = { 'description': i18n("Description:"), 'website': i18n("Website:"), 'release': i18n("Release:"), 'repository': i18n("Repository:"), 'size': i18n("Package Size:"), 'installVers': i18n("Installed Version:") } self._titleFM = {} for key, value in self._titles.items(): self._titleFM[key] = self.boldDetailFontFM.width( value) + ICON_SIZE + 3 self.baseWidth = self.boldFontFM.width( max(self._titles.values(), key=len)) + ICON_SIZE self.parent = parent.packageList # Base style for some of important features # self.plastik = QStyleFactory.create('plastique') def paint(self, painter, option, index): if not index.isValid(): return super(PackageDelegate, self).paint(painter, option, index) if index.flags() & Qt.ItemIsUserCheckable: if index.column() == 0: self.paintCheckBoxColumn(painter, option, index) else: self.paintInfoColumn(painter, option, index) else: self.paintInfoColumn(painter, option, index, width_limit=10) def paintCheckBoxColumn(self, painter, option, index): opt = QStyleOptionViewItemV4(option) buttonStyle = QStyleOptionButton() buttonStyle.state = QStyle.State_On if index.model().data( index, Qt.CheckStateRole) == QVariant( Qt.Checked) else QStyle.State_Off if option.state & QStyle.State_MouseOver or option.state & QStyle.State_HasFocus: buttonStyle.state |= QStyle.State_HasFocus buttonStyle.rect = opt.rect.adjusted(4, -opt.rect.height() + ROW_HEIGHT, 0, 0) PackageDelegate.AppStyle().drawControl(QStyle.CE_CheckBox, buttonStyle, painter, None) def paintInfoColumn(self, painter, option, index, width_limit=0): left = option.rect.left() + 3 top = option.rect.top() width = option.rect.width() - width_limit pixmap = QPixmap(option.rect.size()) pixmap.fill(Qt.transparent) p = QPainter(pixmap) p.setRenderHint(QPainter.Antialiasing, True) p.translate(-option.rect.topLeft()) textInner = 2 * ICON_PADDING + ROW_HEIGHT - 10 itemHeight = ROW_HEIGHT + 2 * ICON_PADDING margin = left + ICON_PADDING - 10 title = index.model().data(index, NameRole).toString() summary = index.model().data(index, SummaryRole).toString() ptype = str(index.model().data(index, TypeRole).toString()) rate = int(index.model().data(index, RateRole).toInt()[0]) installed = index.model().data(index, InstalledRole).toBool() # We need to request update if its not possible to get meta data about the package try: # Get Package Icon if exists _icon = index.model().data(index, Qt.DecorationRole).toString() except: p.end() painter.drawPixmap(option.rect.topLeft(), pixmap) self.parent.requestUpdate() return icon = None if _icon: overlay = [CHECK_ICON] if installed else [] KIconLoader._forceCache = True pix = KIconLoader.loadOverlayed(_icon, overlay, 32) if not pix.isNull(): icon = QIcon( pix.scaled(QSize(32, 32), Qt.KeepAspectRatio, Qt.SmoothTransformation)) KIconLoader._forceCache = False if not icon: icon = self.defaultIcon if not installed else self.defaultInstalledIcon # Paint the Icon icon.paint(p, margin, top + ICON_PADDING, ROW_HEIGHT, ROW_HEIGHT, Qt.AlignCenter) fix_pos = 0 if index.model().columnCount() <= 1: fix_pos = 22 if config.USE_APPINFO: # Rating Stars for _rt_i in range(5): self._rt_0.paint(p, width + 10 * _rt_i - 30 - fix_pos, top + ROW_HEIGHT / 4, 10, 10, Qt.AlignCenter) for _rt_i in range(rate): self._rt_1.paint(p, width + 10 * _rt_i - 30 - fix_pos, top + ROW_HEIGHT / 4, 10, 10, Qt.AlignCenter) foregroundColor = option.palette.color(QPalette.Text) p.setPen(foregroundColor) # Package Name p.setFont(self.boldFont) p.drawText(left + textInner, top, width - textInner, itemHeight / 2, Qt.AlignBottom | Qt.AlignLeft, title) tagWidth = 0 _component_width = 0 if self.parent.showComponents: component = str(index.model().data(index, ComponentRole).toString()) widthOfTitle = self.boldFontFM.width(title) + 6 + left + textInner p.setFont(self.tagFont) rect = self.tagFontFM.boundingRect(option.rect, Qt.TextWordWrap, component) p.setPen(LIGHTGREEN) p.setBrush(LIGHTGREEN) p.drawRoundRect(widthOfTitle, top + 12, rect.width() + 4, rect.height(), 10, 10) p.setPen(DARKGREEN) p.drawText(widthOfTitle + 2, top + 12, rect.width(), rect.height(), Qt.AlignCenter, component) p.setPen(foregroundColor) _component_width = rect.width() + 8 if self.parent.showIsA: isa = str(index.model().data(index, IsaRole).toString()) if not isa == '': widthOfTitle = self.boldFontFM.width( title) + 6 + left + textInner + _component_width p.setFont(self.tagFont) rect = self.tagFontFM.boundingRect(option.rect, Qt.TextWordWrap, isa) p.setPen(LIGHTBLUE) p.setBrush(LIGHTBLUE) p.drawRoundRect(widthOfTitle, top + 12, rect.width() + 4, rect.height(), 10, 10) p.setPen(DARKVIOLET) p.drawText(widthOfTitle + 2, top + 12, rect.width(), rect.height(), Qt.AlignCenter, isa) p.setPen(foregroundColor) _component_width += rect.width() + 8 if ptype not in ('None', 'normal'): widthOfTitle = self.boldFontFM.width( title) + 6 + left + textInner + _component_width p.setFont(self.tagFont) rect = self.tagFontFM.boundingRect(option.rect, Qt.TextWordWrap, self.types[ptype][1]) p.setPen(self.types[ptype][0]) p.setBrush(self.types[ptype][0]) p.drawRoundRect(widthOfTitle, top + 12, rect.width() + 4, rect.height(), 10, 10) p.setPen(WHITE) p.drawText(widthOfTitle + 2, top + 12, rect.width(), rect.height(), Qt.AlignCenter, self.types[ptype][1]) p.setPen(foregroundColor) tagWidth = rect.width() # Package Summary p.setFont(self.normalFont) foregroundColor.setAlpha(160) p.setPen(foregroundColor) elided_summary = self.normalFontFM.elidedText( summary, Qt.ElideRight, width - textInner - tagWidth - 22) p.drawText(left + textInner, top + itemHeight / 2, width - textInner, itemHeight / 2, Qt.TextDontClip, elided_summary) foregroundColor.setAlpha(255) p.setPen(foregroundColor) buttonStyle = None if self.rowAnimator.currentRow() == index.row(): description = index.model().data(index, DescriptionRole).toString() size = index.model().data(index, SizeRole).toString() homepage = index.model().data(index, HomepageRole).toString() installedVersion = str(index.model().data( index, InstalledVersionRole).toString()) version = index.model().data(index, VersionRole) # Package Detail Label position = top + ROW_HEIGHT p.setFont(self.normalDetailFont) baseRect = QRect(left, position, width - 8, option.rect.height()) rect = self.normalDetailFontFM.boundingRect( baseRect, Qt.TextWordWrap | Qt.TextDontClip, description) p.drawText(left + 2, position, width - 8, rect.height(), Qt.TextWordWrap | Qt.TextDontClip, description) # Package Detail Homepage position += rect.height() + 4 p.setFont(self.boldDetailFont) p.drawText(left + ICON_SIZE, position, width - textInner, itemHeight / 2, Qt.AlignLeft, self._titles['website']) p.setFont(self.normalDetailFont) homepage = self.normalDetailFontFM.elidedText( homepage, Qt.ElideRight, width - self._titleFM['website']) rect = self.normalDetailFontFM.boundingRect( option.rect, Qt.TextSingleLine, homepage) self.rowAnimator.hoverLinkFilter.link_rect = QRect( left + self._titleFM['website'] + 2, position + 2 + 32, rect.width(), rect.height()) p.setPen(option.palette.color(QPalette.Link)) p.drawText(left + self._titleFM['website'], position, width, rect.height(), Qt.TextSingleLine, homepage) p.setPen(foregroundColor) # Package Detail Version position += rect.height() p.setFont(self.boldDetailFont) p.drawText(left + ICON_SIZE, position, width - textInner, itemHeight / 2, Qt.AlignLeft, self._titles['release']) p.setFont(self.normalDetailFont) rect = self.normalDetailFontFM.boundingRect( option.rect, Qt.TextWordWrap, version.toString()) p.drawText(left + self._titleFM['release'], position, width, rect.height(), Qt.TextWordWrap, version.toString()) if not installedVersion == '': position += rect.height() p.setFont(self.boldDetailFont) p.drawText(left + ICON_SIZE, position, width - textInner, itemHeight / 2, Qt.AlignLeft, self._titles['installVers']) p.setFont(self.normalDetailFont) rect = self.normalDetailFontFM.boundingRect( option.rect, Qt.TextWordWrap, installedVersion) p.drawText(left + self._titleFM['installVers'], position, width, rect.height(), Qt.TextWordWrap, installedVersion) # Package Detail Repository repository = index.model().data(index, RepositoryRole).toString() if not repository == '': repository = i18n( 'Unknown') if repository == 'N/A' else repository position += rect.height() p.setFont(self.boldDetailFont) p.drawText(left + ICON_SIZE, position, width - textInner, itemHeight / 2, Qt.AlignLeft, self._titles['repository']) p.setFont(self.normalDetailFont) p.drawText(left + self._titleFM['repository'], position, width, itemHeight / 2, Qt.TextWordWrap, repository) # Package Detail Size position += rect.height() p.setFont(self.boldDetailFont) p.drawText(left + ICON_SIZE, position, width - textInner, itemHeight / 2, Qt.AlignLeft, self._titles['size']) p.setFont(self.normalDetailFont) p.drawText(left + self._titleFM['size'], position, width, itemHeight / 2, Qt.TextWordWrap, size) position += rect.height() self.rowAnimator.max_height = position - top + 8 # Package More info button opt = QStyleOptionViewItemV4(option) buttonStyle = QStyleOptionButton() if option.state & QStyle.State_MouseOver or option.state & QStyle.State_HasFocus: buttonStyle.state |= QStyle.State_HasFocus buttonStyle.state |= QStyle.State_Enabled buttonStyle.text = i18n("Details") buttonStyle.rect = QRect(width - 100, position - 22, 100, 22) p.end() # FIXME # if option.state & QStyle.State_HasFocus and self.animatable: # option.state |= QStyle.State_MouseOver # Use Plastique style to draw focus rect like MouseOver effect of Oxygen. # self.plastik.drawPrimitive(QStyle.PE_FrameLineEdit, option, painter, None) if not self.rowAnimator.running() and buttonStyle: if self.show_details_button and (installed or config.USE_APPINFO): PackageDelegate.AppStyle().drawControl(QStyle.CE_PushButton, buttonStyle, painter, None) self.rowAnimator.hoverLinkFilter.button_rect = QRect( buttonStyle.rect) painter.drawPixmap(option.rect.topLeft(), pixmap) del pixmap def editorEvent(self, event, model, option, index): if event.type() == QEvent.MouseButtonRelease and index.column( ) == 0 and index.flags() & Qt.ItemIsUserCheckable: toggled = Qt.Checked if model.data( index, Qt.CheckStateRole) == QVariant( Qt.Unchecked) else Qt.Unchecked return model.setData(index, toggled, Qt.CheckStateRole) __event = QItemDelegate(self).editorEvent(event, model, option, index) animate_requested = False if event.type() == QEvent.MouseButtonRelease and self.animatable: if self.rowAnimator.row == index.row(): epos = event.pos() if self.rowAnimator.hoverLinkFilter.link_rect.contains( QPoint(epos.x(), epos.y() + 32)): url = QUrl(model.data(index, HomepageRole).toString()) QDesktopServices.openUrl(url) return __event elif self.rowAnimator.hoverLinkFilter.button_rect.contains( epos, True): self.showPackageDetails(model, index) return __event animate_requested = True elif event.type() == QEvent.KeyPress and self.animatable: # KeyCode 32 : Space key if event.key() == 32 and index.column( ) == index.model().columnCount() - 1: animate_requested = True if not unicode(model.data( index, DescriptionRole).toString()) == '' and animate_requested: self.rowAnimator.animate(index.row()) return __event def showPackageDetails(self, model, index): def _getter(role): return model.data(index, role).toString() name = _getter(NameRole) summary = _getter(SummaryRole) description = _getter(DescriptionRole) installed = model.data(index, InstalledRole).toBool() self.webDialog.showPackageDetails(name, installed, summary, description) def sizeHint(self, option, index): if self.rowAnimator.currentRow() == index.row( ) and not index.row() == 0: return self.rowAnimator.size() else: width = ICON_SIZE if index.column() == 0 else 0 return QSize(width, ROW_HEIGHT) def setAnimatable(self, animatable): self.animatable = animatable def reset(self): self.rowAnimator.reset()
def __createLayout( self ): " Creates the dialog layout " self.resize( 640, 480 ) self.setSizeGripEnabled( True ) vboxLayout = QVBoxLayout( self ) hLayout = QHBoxLayout() self.__propsView = QTreeWidget() self.__propsView.setAlternatingRowColors( True ) self.__propsView.setRootIsDecorated( False ) self.__propsView.setItemsExpandable( False ) self.__propsView.setSortingEnabled( True ) self.__propsView.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) self.__propsView.itemSelectionChanged.connect( self.__propsSelectionChanged ) propsViewHeader = QTreeWidgetItem( [ "Property Name", "Property Value" ] ) self.__propsView.setHeaderItem( propsViewHeader ) self.__propsView.header().setSortIndicator( 0, Qt.DescendingOrder ) hLayout.addWidget( self.__propsView ) self.__delButton = QToolButton() self.__delButton.setText( "Delete" ) self.__delButton.setFocusPolicy( Qt.NoFocus ) self.__delButton.setEnabled( False ) self.__delButton.clicked.connect( self.__onDel ) hLayout.addWidget( self.__delButton, 0, Qt.AlignBottom ) vboxLayout.addLayout( hLayout ) # Set property part setGroupbox = QGroupBox( self ) setGroupbox.setTitle( "Set Property" ) setLayout = QGridLayout( setGroupbox ) setLayout.addWidget( QLabel( "Name" ), 0, 0, Qt.AlignTop | Qt.AlignRight ) setLayout.addWidget( QLabel( "Value" ), 1, 0, Qt.AlignTop | Qt.AlignRight ) self.__nameEdit = QLineEdit() self.__nameEdit.textChanged.connect( self.__nameChanged ) setLayout.addWidget( self.__nameEdit, 0, 1 ) self.__valueEdit = QTextEdit() self.__valueEdit.setAcceptRichText( False ) self.__valueEdit.textChanged.connect( self.__valueChanged ) metrics = QFontMetrics( self.__valueEdit.font() ) rect = metrics.boundingRect( "X" ) self.__valueEdit.setFixedHeight( rect.height() * 4 + 5 ) setLayout.addWidget( self.__valueEdit, 1, 1 ) self.__setButton = QToolButton() self.__setButton.setText( "Set" ) self.__setButton.setFocusPolicy( Qt.NoFocus ) self.__setButton.setEnabled( False ) self.__setButton.clicked.connect( self.__onSet ) setLayout.addWidget( self.__setButton, 1, 2, Qt.AlignBottom | Qt.AlignHCenter ) sizePolicy = QSizePolicy( QSizePolicy.Expanding, QSizePolicy.Maximum ) sizePolicy.setHorizontalStretch( 0 ) sizePolicy.setVerticalStretch( 0 ) sizePolicy.setHeightForWidth( setGroupbox.sizePolicy().hasHeightForWidth() ) setGroupbox.setSizePolicy( sizePolicy ) vboxLayout.addWidget( setGroupbox ) # Buttons at the bottom buttonBox = QDialogButtonBox( self ) buttonBox.setOrientation( Qt.Horizontal ) buttonBox.setStandardButtons( QDialogButtonBox.Ok ) buttonBox.button( QDialogButtonBox.Ok ).setDefault( True ) buttonBox.accepted.connect( self.close ) vboxLayout.addWidget( buttonBox ) return
def drawTempo(self, painter, value): metric = QFontMetrics(painter.font()) rect = metric.boundingRect(str(value)) if rect.y() < 0: rect.adjust(0, abs(rect.y()), 0, 10) painter.drawText(rect, 0, str(value))
def setTime(self, time_str): #set default font sizes - might get reduced later self.font.setPointSize(self.default_quote_font_size) self.timeLabel.setFont(self.font) self.fonta.setPointSize(self.default_author_font_size) self.authLabel.setFont(self.fonta) #fixTime is set from the command line as is for debug if not self.fixedTime: qt = self._getQuote(time_str) else: qt = self._getQuote(self.fixedTime) log.debug('fixed time') #set up the html for the quotes and authors qstr = u"{:s} <b><em><font color =\"white\">{:s}</font></em></b> {:s}".format( qt['quote_first'], qt['quote_time_case'], qt['quote_last']) log.info(qstr) self.timeLabel.setHtml(qstr) authStr = u"- {:s}, <em><font color =\"white\">{:s}</font></em>".format( qt['title'], qt['author']) self.authLabel.setHtml(authStr) self.authLabel.setAlignment(Qt.AlignRight) log.info(authStr) #now the tricky bit, resize the fonts for the quote and author text to ensure it fits into the text boxes fs = self.default_quote_font_size log.debug('quote') while True: h = self.timeLabel.document().size().height() met = QFontMetrics(self.font) bb = met.boundingRect(self.timeLabel.geometry(), Qt.TextWordWrap, qstr) h = bb.height() if h > self.timeLabel.size().height(): fs = fs - 1 if fs <= self.min_font_size: log.debug('Min font size reached') break self.font.setPointSize(fs) self.timeLabel.setFont(self.font) else: break log.debug('author') fs = self.default_author_font_size while True: h = self.authLabel.document().size().height() met = QFontMetrics(self.fonta) bb = met.boundingRect(self.authLabel.geometry(), Qt.TextWordWrap, authStr) h = bb.height() if h > self.authLabel.size().height(): fs = fs - 1 if fs <= self.min_font_size: log.debug('Min font size reached') break self.fonta.setPointSize(fs) self.authLabel.setFont(self.fonta) else: #make the font a bit smaller still if possible if fs > self.min_font_size + 4: fs = fs - 4 self.fonta.setPointSize(fs) self.authLabel.setFont(self.fonta) break