From c7f7068244c58b37d70e12bc2df6b880769568f9 Mon Sep 17 00:00:00 2001 From: Zsolt Foldvari Date: Wed, 7 Feb 2007 13:24:10 +0000 Subject: [PATCH] 2007-02-07 Zsolt Foldvari * src/DisplayTabs/_NoteTab.py: move "rich text" notes to 2.3 branch. svn: r8074 --- ChangeLog | 3 + src/DisplayTabs/_NoteTab.py | 372 +----------------------------------- 2 files changed, 6 insertions(+), 369 deletions(-) diff --git a/ChangeLog b/ChangeLog index 04b244e74..2b2c291a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2007-02-07 Zsolt Foldvari + * src/DisplayTabs/_NoteTab.py: move "rich text" notes to 2.3 branch. + 2007-02-06 Brian Matherly * src/docgen/PdfDoc.py: provide a more useful error when reportlab crashes diff --git a/src/DisplayTabs/_NoteTab.py b/src/DisplayTabs/_NoteTab.py index f780208cf..8577eb3f3 100644 --- a/src/DisplayTabs/_NoteTab.py +++ b/src/DisplayTabs/_NoteTab.py @@ -26,7 +26,6 @@ # #------------------------------------------------------------------------- from gettext import gettext as _ -import xml.sax.saxutils #------------------------------------------------------------------------- # @@ -34,7 +33,6 @@ import xml.sax.saxutils # #------------------------------------------------------------------------- import gtk -import pango #------------------------------------------------------------------------- # @@ -49,8 +47,6 @@ from _GrampsTab import GrampsTab # NoteTab # #------------------------------------------------------------------------- -FORMATTED_NOTE = False - class NoteTab(GrampsTab): def __init__(self, dbstate, uistate, track, note_obj, title=_('Note')): @@ -101,7 +97,6 @@ class NoteTab(GrampsTab): scroll = gtk.ScrolledWindow() scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scroll.add(self.text) - # FIXME: is this signal called at all scroll.connect('focus-out-event', self.update) vbox.pack_start(scroll, True) @@ -117,37 +112,17 @@ class NoteTab(GrampsTab): vbox.pack_start(hbox, False) self.pack_start(vbox, True) - if FORMATTED_NOTE: - self.buf = EditorBuffer() - self.text.set_buffer(self.buf) - for lab,stock,font in [('gtk-italic',True,'italic'), - ('gtk-bold',True,'bold'), - ('gtk-underline',True,'underline'), - #('Blue',True,'blue'), - #('Red',False,'smallcaps'), - ]: - button = gtk.ToggleButton(lab) - hbox.pack_start(button, False) - if stock: - button.set_use_stock(True) - self.buf.setup_widget_from_pango(button,font) - else: - self.buf = self.text.get_buffer() + self.buf = self.text.get_buffer() if self.note_obj: self.empty = False - if FORMATTED_NOTE: - self.buf.set_text(self.note_obj.get()) - else: - self.buf.insert_at_cursor(self.note_obj.get()) + self.buf.insert_at_cursor(self.note_obj.get()) else: self.empty = True self.buf.connect('changed', self.update) - self.buf.connect_after('apply-tag', self.update) - self.buf.connect_after('remove-tag', self.update) self.rebuild() - def update(self, obj, *args): + def update(self, obj): if self.note_obj: start = self.buf.get_start_iter() stop = self.buf.get_end_iter() @@ -171,344 +146,3 @@ class NoteTab(GrampsTab): def cancel(self): self.note_obj.unserialize(self.original) - -class FormattedBuffer (gtk.TextBuffer): - desc_to_attr_table = { - 'family':[pango.AttrFamily,""], - 'style':[pango.AttrStyle,pango.STYLE_NORMAL], - 'variant':[pango.AttrVariant,pango.VARIANT_NORMAL], - 'weight':[pango.AttrWeight,pango.WEIGHT_NORMAL], - 'stretch':[pango.AttrStretch,pango.STRETCH_NORMAL], - } - pango_translation_properties={ - # pango ATTR TYPE : (pango attr property / tag property) - pango.ATTR_SIZE : 'size', - pango.ATTR_WEIGHT: 'weight', - pango.ATTR_UNDERLINE: 'underline', - pango.ATTR_STRETCH: 'stretch', - pango.ATTR_VARIANT: 'variant', - pango.ATTR_STYLE: 'style', - pango.ATTR_SCALE: 'scale', - pango.ATTR_STRIKETHROUGH: 'strikethrough', - pango.ATTR_RISE: 'rise', - } - attval_to_markup={ - 'underline':{pango.UNDERLINE_SINGLE:'single', - pango.UNDERLINE_DOUBLE:'double', - pango.UNDERLINE_LOW:'low', - pango.UNDERLINE_NONE:'none'}, - 'stretch':{pango.STRETCH_ULTRA_EXPANDED:'ultraexpanded', - pango.STRETCH_EXPANDED:'expanded', - pango.STRETCH_EXTRA_EXPANDED:'extraexpanded', - pango.STRETCH_EXTRA_CONDENSED:'extracondensed', - pango.STRETCH_ULTRA_CONDENSED:'ultracondensed', - pango.STRETCH_CONDENSED:'condensed', - pango.STRETCH_NORMAL:'normal', - }, - 'variant':{pango.VARIANT_NORMAL:'normal', - pango.VARIANT_SMALL_CAPS:'smallcaps', - }, - 'style':{pango.STYLE_NORMAL:'normal', - pango.STYLE_OBLIQUE:'oblique', - pango.STYLE_ITALIC:'italic', - }, - 'stikethrough':{1:'true', - True:'true', - 0:'false', - False:'false'}, - } - def __init__ (self): - self.tagdict = {} - self.tags = {} - #self.buf = buf - #self.set_text(txt) - gtk.TextBuffer.__init__(self) - - def set_text (self, txt): - gtk.TextBuffer.set_text(self,"") - try: - self.parsed,self.txt,self.separator = pango.parse_markup(txt,u'\x00') - except: - log.debug('Escaping text, we seem to have a problem here!') - txt=xml.sax.saxutils.escape(txt) - self.parsed,self.txt,self.separator = pango.parse_markup(txt,u'\x00') - self.attrIter = self.parsed.get_iterator() - self.add_iter_to_buffer() - while self.attrIter.next(): - self.add_iter_to_buffer() - - def add_iter_to_buffer (self): - range=self.attrIter.range() - font,lang,attrs = self.attrIter.get_font() - tags = self.get_tags_from_attrs(font,lang,attrs) - text = self.txt[range[0]:range[1]] - if tags: self.insert_with_tags(self.get_end_iter(),text,*tags) - else: self.insert_with_tags(self.get_end_iter(),text) - - def get_tags_from_attrs (self, font,lang,attrs): - tags = [] - if font: - font,fontattrs = self.fontdesc_to_attrs(font) - fontdesc = font.to_string() - if fontattrs: - attrs.extend(fontattrs) - if fontdesc and fontdesc!='Normal': - if not self.tags.has_key(font.to_string()): - tag=self.create_tag() - tag.set_property('font-desc',font) - if not self.tagdict.has_key(tag): self.tagdict[tag]={} - self.tagdict[tag]['font_desc']=font.to_string() - self.tags[font.to_string()]=tag - tags.append(self.tags[font.to_string()]) - if lang: - if not self.tags.has_key(lang): - tag = self.create_tag() - tag.set_property('language',lang) - self.tags[lang]=tag - tags.append(self.tags[lang]) - if attrs: - for a in attrs: - if a.type == pango.ATTR_FOREGROUND: - gdkcolor = self.pango_color_to_gdk(a.color) - key = 'foreground%s'%self.color_to_hex(gdkcolor) - if not self.tags.has_key(key): - self.tags[key]=self.create_tag() - self.tags[key].set_property('foreground-gdk',gdkcolor) - self.tagdict[self.tags[key]]={} - self.tagdict[self.tags[key]]['foreground']="#%s"\ - %self.color_to_hex(gdkcolor) - tags.append(self.tags[key]) - if a.type == pango.ATTR_BACKGROUND: - gdkcolor = self.pango_color_to_gdk(a.color) - key = 'background%s'%self.color_to_hex(gdkcolor) - if not self.tags.has_key(key): - self.tags[key]=self.create_tag() - self.tags[key].set_property('background-gdk',gdkcolor) - self.tagdict[self.tags[key]]={} - self.tagdict[self.tags[key]]['background']="#%s"\ - %self.color_to_hex(gdkcolor) - tags.append(self.tags[key]) - if self.pango_translation_properties.has_key(a.type): - prop=self.pango_translation_properties[a.type] - ##log.debug('setting property %s of %s (type: %s)'\ - ##%(prop,a,a.type)) - val=getattr(a,'value') - #tag.set_property(prop,val) - mval = val - if self.attval_to_markup.has_key(prop): - #print 'converting ',prop,' in ',val - if self.attval_to_markup[prop].has_key(val): - mval = self.attval_to_markup[prop][val] - else: - log.debug("hmmm, didn't know what to do" - " with value %s"%val,0) - key="%s%s"%(prop,val) - if not self.tags.has_key(key): - self.tags[key]=self.create_tag() - self.tags[key].set_property(prop,val) - self.tagdict[self.tags[key]]={} - self.tagdict[self.tags[key]][prop]=mval - tags.append(self.tags[key]) - else: - ##log.debug("Don't know what to do with attr %s"%a,1) - pass - return tags - - def get_tags (self): - tagdict = {} - for pos in range(self.get_char_count()): - iter=self.get_iter_at_offset(pos) - for tag in iter.get_tags(): - if tagdict.has_key(tag): - if tagdict[tag][-1][1] == pos - 1: - tagdict[tag][-1] = (tagdict[tag][-1][0],pos) - else: - tagdict[tag].append((pos,pos)) - else: - tagdict[tag]=[(pos,pos)] - return tagdict - - def get_text (self, start=None, end=None, include_hidden_chars=True): - tagdict=self.get_tags() - if not start: start=self.get_start_iter() - if not end: end=self.get_end_iter() - txt = unicode(gtk.TextBuffer.get_text(self,start,end)) - cuts = {} - for k,v in tagdict.items(): - stag,etag = self.tag_to_markup(k) - for st,e in v: - #add start tags second - if cuts.has_key(st): cuts[st].append(stag) - else: cuts[st]=[stag] - #add end tags first - if cuts.has_key(e+1): cuts[e+1]=[etag]+cuts[e+1] - else: cuts[e+1]=[etag] - last_pos = 0 - outbuff = "" - cut_indices = cuts.keys() - cut_indices.sort() - soffset = start.get_offset() - eoffset = end.get_offset() - cut_indices = filter(lambda i: eoffset >= i >= soffset, cut_indices) - for c in cut_indices: - if not last_pos==c: - outbuff += xml.sax.saxutils.escape(txt[last_pos:c]) - last_pos = c - for tag in cuts[c]: - outbuff += tag - outbuff += xml.sax.saxutils.escape(txt[last_pos:]) - return outbuff - - def tag_to_markup (self, tag): - stag = "" - - def fontdesc_to_attrs (self,font): - nicks = font.get_set_fields().value_nicks - attrs = [] - for n in nicks: - if self.desc_to_attr_table.has_key(n): - Attr,norm = self.desc_to_attr_table[n] - # create an attribute with our current value - attrs.append(Attr(getattr(font,'get_%s'%n)())) - # unset our font's value - getattr(font,'set_%s'%n)(norm) - return font,attrs - - def pango_color_to_gdk (self, pc): - return gtk.gdk.Color(pc.red,pc.green,pc.blue) - - def color_to_hex (self, color): - hexstring = "" - for col in 'red','green','blue': - hexfrag = hex(getattr(color,col)/(16*16)).split("x")[1] - if len(hexfrag)<2: hexfrag = "0" + hexfrag - hexstring += hexfrag - return hexstring - - def apply_font_and_attrs (self, font, attrs): - tags = self.get_tags_from_attrs(font,None,attrs) - for t in tags: self.apply_tag_to_selection(t) - - def remove_font_and_attrs (self, font, attrs): - tags = self.get_tags_from_attrs(font,None,attrs) - for t in tags: self.remove_tag_from_selection(t) - - def setup_default_tags (self): - self.italics = self.get_tags_from_attrs(None,None, - [pango.AttrStyle('italic')])[0] - self.bold = self.get_tags_from_attrs(None,None, - [pango.AttrWeight('bold')])[0] - self.underline = self.get_tags_from_attrs(None,None, - [pango.AttrUnderline('single')])[0] - - def get_selection (self): - bounds = self.get_selection_bounds() - if not bounds: - iter=self.get_iter_at_mark(self.insert) - if iter.inside_word(): - start_pos = iter.get_offset() - iter.forward_word_end() - word_end = iter.get_offset() - iter.backward_word_start() - word_start = iter.get_offset() - iter.set_offset(start_pos) - bounds = (self.get_iter_at_offset(word_start), - self.get_iter_at_offset(word_end+1)) - else: - bounds = (iter,self.get_iter_at_offset(iter.get_offset()+1)) - return bounds - - def apply_tag_to_selection (self, tag): - selection = self.get_selection() - if selection: - self.apply_tag(tag,*selection) - - def remove_tag_from_selection (self, tag): - selection = self.get_selection() - if selection: - self.remove_tag(tag,*selection) - - def remove_all_tags (self): - selection = self.get_selection() - if selection: - for t in self.tags.values(): - self.remove_tag(t,*selection) - -class EditorBuffer(FormattedBuffer): - def __init__ (self, normal_button=None, toggle_widget_alist=[]): - """An interactive interface to allow marking up a gtk.TextBuffer. - - normal_button is a widget whose clicked signal will make us normal - toggle_widget_alist is a list that looks like this: - [(widget, (font,attr)), - (widget2, (font,attr))] - """ - FormattedBuffer.__init__(self) - if normal_button: - normal_button.connect('clicked',lambda *args: self.remove_all_tags()) - self.tag_widgets = {} - self.internal_toggle = False - self.insert = self.get_insert() - # FIXME: try to register class and use on_ methods - self.connect('mark-set',self._mark_set_cb) - self.connect('changed',self._changed_cb) - for w,tup in toggle_widget_alist: - self.setup_widget(w,*tup) - - def setup_widget_from_pango (self, widg, markupstring): - """Setup widget from a pango markup string""" - #font = pango.FontDescription(fontstring) - a,t,s = pango.parse_markup(markupstring,u'\x00') - ai=a.get_iterator() - font,lang,attrs=ai.get_font() - return self.setup_widget(widg,font,attrs) - - def setup_widget (self, widg, font, attr): - tags=self.get_tags_from_attrs(font,None,attr) - self.tag_widgets[tuple(tags)]=widg - return widg.connect('toggled',self._toggle,tags) - - def _toggle (self, widget, tags): - if self.internal_toggle: return - if widget.get_active(): - for t in tags: self.apply_tag_to_selection(t) - else: - for t in tags: self.remove_tag_from_selection(t) - - def _mark_set_cb (self, buffer, iter, mark, *params): - # Every time the cursor moves, update our widgets that reflect - # the state of the text. - if hasattr(self,'_in_mark_set') and self._in_mark_set: return - self._in_mark_set = True - if mark.get_name()=='insert': - for tags,widg in self.tag_widgets.items(): - active = True - for t in tags: - if not iter.has_tag(t): - active=False - self.internal_toggle=True - widg.set_active(active) - self.internal_toggle=False - if hasattr(self,'last_mark'): - self.move_mark(self.last_mark,iter) - else: - self.last_mark = self.create_mark('last',iter,left_gravity=True) - self._in_mark_set = False - - def _changed_cb (self, tb): - if not hasattr(self,'last_mark'): return - # If our insertion point has a mark, we want to apply the tag - # each time the user types... - old_itr = self.get_iter_at_mark(self.last_mark) - insert_itr = self.get_iter_at_mark(self.insert) - if old_itr!=insert_itr: - # Use the state of our widgets to determine what - # properties to apply... - for tags,w in self.tag_widgets.items(): - if w.get_active(): - #print 'apply tags...',tags - for t in tags: self.apply_tag(t,old_itr,insert_itr)