2007-07-15 Zsolt Foldvari <zfoldvar@users.sourceforge.net>

* src/MarkupText.py: support font and color formats.



svn: r8716
This commit is contained in:
Zsolt Foldvari 2007-07-15 20:03:51 +00:00
parent dcf46f3521
commit ca1e510b3e
2 changed files with 123 additions and 90 deletions

View File

@ -1,3 +1,6 @@
2007-07-15 Zsolt Foldvari <zfoldvar@users.sourceforge.net>
* src/MarkupText.py: support font and color formats.
2007-07-14 Alex Roitman <shura@gramps-project.org> 2007-07-14 Alex Roitman <shura@gramps-project.org>
* src/Editors/_EditLdsOrd.py (_setup_fields): Typo. * src/Editors/_EditLdsOrd.py (_setup_fields): Typo.

View File

@ -177,6 +177,69 @@ class MarkupWriter:
else: else:
eventdict[end] = [(name, attrs, self.EVENT_END, start)] eventdict[end] = [(name, attrs, self.EVENT_END, start)]
# first round optimization
active_tags = {}
active_idx = {}
indices = eventdict.keys()
indices.sort()
for index in indices:
modified_tags = []
for (name, attrs, type, pair_idx) in eventdict[index]:
if attrs.getLength():
# remove this event, we will insert new ones instead
eventdict[index].remove((name, attrs, type, pair_idx))
# if the tag is already open first we need to close it
if active_tags.has_key(name):
tmp_attrs = xmlreader.AttributesImpl({})
tmp_attrs._attrs.update(active_tags[name])
eventdict[index].insert(0, (name, tmp_attrs,
self.EVENT_END,
active_idx[name]))
# update pair index in tag opening event
# FIXME this is ugly
for event in eventdict[active_idx[name]]:
if (event[0] == name and
event[2] == self.EVENT_START):
new_event = (event[0], event[1], event[2], index)
eventdict[active_idx[name]].remove(event)
eventdict[active_idx[name]].append(new_event)
else:
active_tags[name] = xmlreader.AttributesImpl({})
# update the active attribute object for the tag
if type == self.EVENT_START:
active_tags[name]._attrs.update(attrs)
elif type == self.EVENT_END:
for attr_name in attrs.getNames():
try:
del active_tags[name]._attrs[attr_name]
except:
pass # error
else:
pass # error
# if the tag's attr list is empty after the updates
# delete the tag completely from the list of active tags
if not active_tags[name].getLength():
del active_tags[name]
##del active_idx[name]
# remember this tag has changes
if name not in modified_tags:
modified_tags.append(name)
# re-open all tags with updated attrs
for name in modified_tags:
if active_tags.has_key(name):
tmp_attrs = xmlreader.AttributesImpl({})
tmp_attrs._attrs.update(active_tags[name])
eventdict[index].append((name, tmp_attrs,
self.EVENT_START, pair_idx))
# also save the index of tag opening
active_idx[name] = index
# sort events at the same index # sort events at the same index
indices = eventdict.keys() indices = eventdict.keys()
for idx in indices: for idx in indices:
@ -209,7 +272,7 @@ class MarkupWriter:
if not attrs: if not attrs:
attrs = self._attrs attrs = self._attrs
self._writer.startElement(name, attrs) self._writer.startElement(name, attrs)
self._open_elements.append(name) self._open_elements.append((name, attrs))
def _endElement(self, name): def _endElement(self, name):
"""Insert end tag.""" """Insert end tag."""
@ -223,10 +286,10 @@ class MarkupWriter:
# close all open elements until we reach to the requested one # close all open elements until we reach to the requested one
while elem != name: while elem != name:
try: try:
elem = self._open_elements.pop() elem, attrs = self._open_elements.pop()
self._writer.endElement(elem) self._writer.endElement(elem)
if elem != name: if elem != name:
tmp_list.append(elem) tmp_list.append((elem, attrs))
except: except:
# we need to do something smart here... # we need to do something smart here...
log.debug("Trying to close non open element '%s'" % name) log.debug("Trying to close non open element '%s'" % name)
@ -235,8 +298,8 @@ class MarkupWriter:
# open all other elements again # open all other elements again
while True: while True:
try: try:
elem = tmp_list.pop() elem, attrs = tmp_list.pop()
self._startElement(elem) self._startElement(elem, attrs)
except: except:
break break
@ -569,28 +632,31 @@ class MarkupBuffer(gtk.TextBuffer):
@param attrs: attributes of the XML tag @param attrs: attributes of the XML tag
@param type: xmlreader.AttributesImpl @param type: xmlreader.AttributesImpl
@return: property of gtk.TextTag, value of property @return: property of gtk.TextTag, value of property
@rtype: string, string @rtype: [(string, string), ]
""" """
if name == 'b': if name == 'b':
return 'bold', None return [('bold', None)]
elif name == 'i': elif name == 'i':
return 'italic', None return [('italic', None)]
elif name == 'u': elif name == 'u':
return 'underline', None return [('underline', None)]
##elif name == 'font': elif name == 'font':
##attr_names = attrs.getNames() ret = []
##if 'color' in attr_names: attr_names = attrs.getNames()
##return 'foreground', attrs.getValue('color') if 'color' in attr_names:
##elif 'highlight' in attr_names: ret.append(('foreground', attrs.getValue('color')))
##return 'background', attrs.getValue('highlight') if 'highlight' in attr_names:
##elif 'face' in attr_names and 'size' in attr_names: ret.append(('background', attrs.getValue('highlight')))
##return 'font', '%s %s' % (attrs.getValue('face'), if ('face' in attr_names) and ('size' in attr_names):
##attrs.getValue('size')) ret.append(('font', '%s %s' % (attrs.getValue('face'),
##else: attrs.getValue('size'))))
##return None, None if len(ret):
return ret
else:
return [(None, None)]
else: else:
return None, None return [(None, None)]
def _texttag_to_xmltag(self, name): def _texttag_to_xmltag(self, name):
"""Convert gtk.TextTag to XML tag. """Convert gtk.TextTag to XML tag.
@ -608,17 +674,17 @@ class MarkupBuffer(gtk.TextBuffer):
return 'i', attrs return 'i', attrs
elif name == 'underline': elif name == 'underline':
return 'u', attrs return 'u', attrs
##elif name.startswith('foreground'): elif name.startswith('foreground'):
##attrs._attrs['color'] = name.split()[1] attrs._attrs['color'] = name.split()[1]
##return 'font', attrs return 'font', attrs
##elif name.startswith('background'): elif name.startswith('background'):
##attrs._attrs['highlight'] = name.split()[1] attrs._attrs['highlight'] = name.split()[1]
##return 'font', attrs return 'font', attrs
##elif name.startswith('font'): elif name.startswith('font'):
##name = name.replace('font ', '') name = name.replace('font ', '')
##attrs._attrs['face'] = name.rsplit(' ', 1)[0] attrs._attrs['face'] = name.rsplit(' ', 1)[0]
##attrs._attrs['size'] = name.rsplit(' ', 1)[1] attrs._attrs['size'] = name.rsplit(' ', 1)[1]
##return 'font', attrs return 'font', attrs
else: else:
return None, None return None, None
@ -649,9 +715,9 @@ class MarkupBuffer(gtk.TextBuffer):
def _hex_to_color(self, hex): def _hex_to_color(self, hex):
"""Convert hex string to gtk.gdk.Color.""" """Convert hex string to gtk.gdk.Color."""
return gtk.gdk.Color(int(hex[1:3], 16), color = gtk.gdk.Color()
int(hex[3:5], 16), color = gtk.gdk.color_parse(hex)
int(hex[5:7], 16)) return color
def get_selection(self): def get_selection(self):
bounds = self.get_selection_bounds() bounds = self.get_selection_bounds()
@ -773,6 +839,9 @@ class MarkupBuffer(gtk.TextBuffer):
if format == 'foreground': if format == 'foreground':
color_selection = gtk.ColorSelectionDialog(_("Select font color")) color_selection = gtk.ColorSelectionDialog(_("Select font color"))
if self.foreground:
color_selection.colorsel.set_current_color(
self._hex_to_color(self.foreground))
response = color_selection.run() response = color_selection.run()
color = color_selection.colorsel.get_current_color() color = color_selection.colorsel.get_current_color()
value = self._color_to_hex(color) value = self._color_to_hex(color)
@ -780,12 +849,17 @@ class MarkupBuffer(gtk.TextBuffer):
elif format == 'background': elif format == 'background':
color_selection = gtk.ColorSelectionDialog(_("Select " color_selection = gtk.ColorSelectionDialog(_("Select "
"background color")) "background color"))
if self.background:
color_selection.colorsel.set_current_color(
self._hex_to_color(self.background))
response = color_selection.run() response = color_selection.run()
color = color_selection.colorsel.get_current_color() color = color_selection.colorsel.get_current_color()
value = self._color_to_hex(color) value = self._color_to_hex(color)
color_selection.destroy() color_selection.destroy()
elif format == 'font': elif format == 'font':
font_selection = gtk.FontSelectionDialog(_("Select font")) font_selection = gtk.FontSelectionDialog(_("Select font"))
if self.font:
font_selection.fontsel.set_font_name(self.font)
response = font_selection.run() response = font_selection.run()
value = font_selection.fontsel.get_font_name() value = font_selection.fontsel.get_font_name()
font_selection.destroy() font_selection.destroy()
@ -840,19 +914,22 @@ class MarkupBuffer(gtk.TextBuffer):
for element in self.parser.elements: for element in self.parser.elements:
(start, end), xmltag_name, attrs = element (start, end), xmltag_name, attrs = element
texttag_name, value = self._xmltag_to_texttag(xmltag_name, attrs) #texttag_name, value = self._xmltag_to_texttag(xmltag_name, attrs)
tags = self._xmltag_to_texttag(xmltag_name, attrs)
if texttag_name is not None: for texttag_name, value in tags:
start_iter = self.get_iter_at_offset(start) if texttag_name is not None:
end_iter = self.get_iter_at_offset(end) start_iter = self.get_iter_at_offset(start)
tag = self._find_tag_by_name(texttag_name, value) end_iter = self.get_iter_at_offset(end)
if tag is not None: tag = self._find_tag_by_name(texttag_name, value)
self.apply_tag(tag, start_iter, end_iter) if tag is not None:
self.apply_tag(tag, start_iter, end_iter)
def get_text(self, start=None, end=None, include_hidden_chars=True): def get_text(self, start=None, end=None, include_hidden_chars=True):
"""Returns the buffer text with xml markup tags. """Returns the buffer text with xml markup tags.
If no markup was applied returns clean text. If no markup was applied returns clean text
(i.e. without even root tags).
""" """
# get the clear text from the buffer # get the clear text from the buffer
@ -881,53 +958,6 @@ class MarkupBuffer(gtk.TextBuffer):
return txt return txt
##def apply_format(self, format, value=None):
##"""."""
##if format not in self.formats:
##raise TypeError("%s is not a valid format name" % format)
##start, end = self.get_selection()
##log.debug("Applying format '%s' with value '%s' for range %d - %d" %
##(format, value, start.get_offset(), end.get_offset()))
##if format == 'bold':
##self.apply_tag_by_name('bold', start, end)
##elif format == 'italic':
##self.apply_tag_by_name('italic', start, end)
##elif format == 'underline':
##self.apply_tag_by_name('underline', start, end)
##else:
##log.error("Format '%s' is not yet implemented" % format)
##def remove_format(self, format, value=None):
##"""."""
##if format not in self.formats:
##raise TypeError("%s is not a valid format name" % format)
##start, end = self.get_selection()
##log.debug("Removing format '%s' with value '%s' for range %d - %d" %
##(format, value, start.get_offset(), end.get_offset()))
##if format == 'bold':
##self.remove_tag_by_name('bold', start, end)
##elif format == 'italic':
##self.remove_tag_by_name('italic', start, end)
##elif format == 'underline':
##self.remove_tag_by_name('underline', start, end)
##else:
##log.error("Format '%s' is not yet implemented" % format)
##def remove_all_formats(self):
##"""."""
##start, end = self.get_selection()
##log.debug("Removing all format for range %d - %d" %
##(start.get_offset(), end.get_offset()))
##self.remove_all_tags(start, end)
def match_add(self, pattern, flavor): def match_add(self, pattern, flavor):
"""Add a pattern to look for in the text.""" """Add a pattern to look for in the text."""
regex = re.compile(pattern) regex = re.compile(pattern)