1# ------------------------------------------------------------------------------ 2# Copyright (c) 2007, Riverbank Computing Limited 3# All rights reserved. 4# 5# This software is provided without warranty under the terms of the BSD license. 6# However, when used with the GPL version of PyQt the additional terms 7# described in the PyQt GPL exception also apply 8 9# 10# Author: Riverbank Computing Limited 11# ------------------------------------------------------------------------------ 12 13""" Trait definition for a PyQt-based font. 14""" 15 16 17from pyface.qt import QtGui 18 19from traits.api import Trait, TraitHandler, TraitError 20 21 22# ------------------------------------------------------------------------- 23# Convert a string into a valid QFont object (if possible): 24# ------------------------------------------------------------------------- 25 26# Mapping of strings to valid QFont style hints. 27font_families = { 28 "default": QtGui.QFont.AnyStyle, 29 "decorative": QtGui.QFont.Decorative, 30 "roman": QtGui.QFont.Serif, 31 "script": QtGui.QFont.SansSerif, 32 "swiss": QtGui.QFont.SansSerif, 33 "modern": QtGui.QFont.TypeWriter, 34} 35 36# Mapping of strings to QFont styles. 37font_styles = { 38 "slant": QtGui.QFont.StyleOblique, 39 "italic": QtGui.QFont.StyleItalic, 40} 41 42# Mapping of strings to QFont weights. 43font_weights = {"light": QtGui.QFont.Light, "bold": QtGui.QFont.Bold} 44 45# Strings to ignore in text representations of fonts 46font_noise = ["pt", "point", "family"] 47 48 49def font_to_str(font): 50 """ Converts a QFont into a string description of itself. 51 """ 52 weight = {QtGui.QFont.Light: " Light", QtGui.QFont.Bold: " Bold"}.get( 53 font.weight(), "" 54 ) 55 style = { 56 QtGui.QFont.StyleOblique: " Slant", 57 QtGui.QFont.StyleItalic: " Italic", 58 }.get(font.style(), "") 59 underline = "" 60 if font.underline(): 61 underline = " underline" 62 return "%s point %s%s%s%s" % ( 63 font.pointSize(), 64 str(font.family()), 65 style, 66 weight, 67 underline, 68 ) 69 70 71def create_traitsfont(value): 72 """ Create a TraitFont object from a string description. 73 """ 74 if isinstance(value, QtGui.QFont): 75 return TraitsFont(value) 76 77 point_size = None 78 family = "" 79 style = QtGui.QFont.StyleNormal 80 weight = QtGui.QFont.Normal 81 underline = False 82 facename = [] 83 84 for word in value.split(): 85 lword = word.lower() 86 if lword in font_families: 87 f = QtGui.QFont() 88 f.setStyleHint(font_families[lword]) 89 family = f.defaultFamily() 90 elif lword in font_styles: 91 style = font_styles[lword] 92 elif lword in font_weights: 93 weight = font_weights[lword] 94 elif lword == "underline": 95 underline = True 96 elif lword not in font_noise: 97 if point_size is None: 98 try: 99 point_size = int(lword) 100 continue 101 except: 102 pass 103 facename.append(word) 104 105 if facename: 106 family = " ".join(facename) 107 108 if family: 109 fnt = TraitsFont(family) 110 else: 111 fnt = TraitsFont() 112 113 fnt.setStyle(style) 114 fnt.setWeight(weight) 115 fnt.setUnderline(underline) 116 117 if point_size is None: 118 fnt.setPointSize(QtGui.QApplication.font().pointSize()) 119 else: 120 fnt.setPointSize(point_size) 121 122 return fnt 123 124 125class TraitsFont(QtGui.QFont): 126 """ A Traits-specific QFont. 127 """ 128 129 def __reduce_ex__(self, protocol): 130 """ Returns the pickleable form of a TraitsFont object. 131 """ 132 return (create_traitsfont, (font_to_str(self),)) 133 134 def __str__(self): 135 """ Returns a printable form of the font. 136 """ 137 return font_to_str(self) 138 139 140# ------------------------------------------------------------------------- 141# 'TraitPyQtFont' class' 142# ------------------------------------------------------------------------- 143 144 145class TraitPyQtFont(TraitHandler): 146 """ Ensures that values assigned to a trait attribute are valid font 147 descriptor strings; the value actually assigned is the corresponding 148 TraitsFont. 149 """ 150 151 def validate(self, object, name, value): 152 """ Validates that the value is a valid font descriptor string. If so, 153 it returns the corresponding TraitsFont; otherwise, it raises a 154 TraitError. 155 """ 156 if value is None: 157 return None 158 159 try: 160 return create_traitsfont(value) 161 except: 162 pass 163 164 raise TraitError(object, name, "a font descriptor string", repr(value)) 165 166 def info(self): 167 return ( 168 "a string describing a font (e.g. '12 pt bold italic " 169 "swiss family Arial' or 'default 12')" 170 ) 171 172 173# ------------------------------------------------------------------------- 174# Callable that returns an instance of the PyQtToolkitEditorFactory for font 175# editors. 176# ------------------------------------------------------------------------- 177 178### FIXME: We have declared the 'editor' to be a function instead of the 179# traitsui.qt4.font_editor.ToolkitEditorFactory class, since the 180# latter is leading to too many circular imports. In the future, try to see if 181# there is a better way to do this. 182 183 184def get_font_editor(*args, **traits): 185 from traitsui.qt4.font_editor import ToolkitEditorFactory 186 187 return ToolkitEditorFactory(*args, **traits) 188 189 190# ------------------------------------------------------------------------- 191# Define a PyQt specific font trait: 192# ------------------------------------------------------------------------- 193 194PyQtFont = Trait(TraitsFont(), TraitPyQtFont(), editor=get_font_editor) 195