Преобразовать строку разметки Панго в свойства GtkTextTag
У меня есть gtk.TextView
что я хотел бы добавить подобный разметке текст к. Я знаю, что это может быть достигнуто с помощью gtk.TextTag
который вы можете создать с похожими свойствами в виде строки разметки Панго. Я заметил, что нет простого способа сказать set_markup gtk.TextBuffer
так же, как вы можете с несколькими другими виджетами. Вместо этого вам нужно создать TextTag, присвоить ему свойства, а затем вставить его в TagTable TextBuffer's, указав теги, к которым применяется тег.
В идеале я хотел бы создать функцию, которая может преобразовать строку разметки Панго в TextTag, чтобы получить тот же эффект. Но gtk, похоже, не имеет такой встроенной функциональности. Я заметил, что вы можете использовать pango.parse_markup()
на размеченной строке, и это создаст pango.AttributeList
которая содержит информацию о свойствах, заданных в строке, и индексах, в которых они встречаются. Но есть небольшие различия в каждом типе атрибута, которые затрудняют обобщение для каждого случая. Есть ли лучший способ сделать это? Или разметка панго просто не предназначена для преобразования в gtk.TextTag
"S?
2 ответа
Я наконец-то выработал собственное решение этой проблемы. Я создал функцию, которая анализирует строку разметки (используя pango.parse_markup
). Благодаря чтению документации и интроспекции Python я смог понять, как pango.Attribute
и превратить его в свойства, которые GtkTextTag
можешь использовать.
Вот функция:
def parse_markup_string(string):
'''
Parses the string and returns a MarkupProps instance
'''
#The 'value' of an attribute...for some reason the same attribute is called several different things...
attr_values = ('value', 'ink_rect', 'logical_rect', 'desc', 'color')
#Get the AttributeList and text
attr_list, text, accel = pango.parse_markup( string )
attr_iter = attr_list.get_iterator()
#Create the converter
props = MarkupProps()
props.text = text
val = True
while val:
attrs = attr_iter.get_attrs()
for attr in attrs:
name = attr.type
start = attr.start_index
end = attr.end_index
name = pango.AttrType(name).value_nick
value = None
#Figure out which 'value' attribute to use...there's only one per pango.Attribute
for attr_value in attr_values:
if hasattr( attr, attr_value ):
value = getattr( attr, attr_value )
break
#There are some irregularities...'font_desc' of the pango.Attribute
#should be mapped to the 'font' property of a GtkTextTag
if name == 'font_desc':
name = 'font'
props.add( name, value, start, end )
val = attr_iter.next()
return props
Эта функция создает MarkupProps()
объект, который имеет способность генерировать GtkTextTag
s вместе с индексом в тексте, к которому они применяются.
Вот объект:
class MarkupProps():
'''
Stores properties that contain indices and appropriate values for that property.
Includes an iterator that generates GtkTextTags with the start and end indices to
apply them to
'''
def __init__(self):
'''
properties = ( {
'properties': {'foreground': 'green', 'background': 'red'}
'start': 0,
'end': 3
},
{
'properties': {'font': 'Lucida Sans 10'},
'start': 1,
'end':2,
},
)
'''
self.properties = []#Sequence containing all the properties, and values, organized by like start and end indices
self.text = ""#The raw text without any markup
def add( self, label, value, start, end ):
'''
Add a property to MarkupProps. If the start and end indices are already in
a property dictionary, then add the property:value entry into
that property, otherwise create a new one
'''
for prop in self.properties:
if prop['start'] == start and prop['end'] == end:
prop['properties'].update({label:value})
else:
new_prop = {
'properties': {label:value},
'start': start,
'end':end,
}
self.properties.append( new_prop )
def __iter__(self):
'''
Creates a GtkTextTag for each dict of properties
Yields (TextTag, start, end)
'''
for prop in self.properties:
tag = gtk.TextTag()
tag.set_properties( **prop['properties'] )
yield (tag, prop['start'], prop['end'])
Так с этой функцией и MarkupProps
объект, я могу, учитывая строку разметки Панго, разбить строку на ее свойства и текстовую форму, а затем преобразовать это в GtkTextTag
s.