Fixed StyledTextTagType to match grampstype; fixed _DEFAULT on all types; editing notes on web not quite correct (error in DocBackend?)

svn: r19695
This commit is contained in:
Doug Blank 2012-05-29 13:39:55 +00:00
parent a8f5d1f8e1
commit abbb02a08e
7 changed files with 180 additions and 83 deletions

View File

@ -9,12 +9,13 @@
$('.wysiwyg').htmlarea({
toolbar: [
"bold", "italic", "underline",
"|", "forecolor",
"|", "forecolor", "superscript",
"|", "link", "unlink",
"|", "html"
]
});
// FIXME: easier way?
// FIXME: add font, fontsize, backcolor
// FIXME: find easier way:
$('.jHtmlArea').contents().find('iframe').contents().find('body').css({"background-color": "white"});
});
function setnotetext() {

View File

@ -63,11 +63,17 @@ def get_type(the_type, data, get_or_create=False):
def get_default_type(the_type):
"""
Gets the default row for a given Type.
Gets the default database object for a given GrampsType.
"""
val, name = the_type._DEFAULT
return the_type.objects.get(val=val, name=name)
def get_default_type_value(the_type):
"""
Gets the default value for a given gen.lib.GrampsType.
"""
return [x for x in the_type._DATAMAP if x[0] == the_type._DEFAULT][0]
def get_datamap(grampsclass):
return sorted([(x[0],x[2]) for x in grampsclass._DATAMAP],
key=lambda item: item[1])
@ -97,7 +103,7 @@ class mGrampsType(models.Model):
def get_default_type(self):
""" return a tuple default (val,name) """
return self._DATAMAP[self._DEFAULT]
return self._DEFAULT
def __len__(self):
""" For use as a sequence for getting (val, name) """
@ -116,35 +122,35 @@ class NameType(mGrampsType):
from gen.lib.nametype import NameType
_DATAMAP = get_datamap(NameType)
_CUSTOM = NameType._CUSTOM
_DEFAULT = [x for x in _DATAMAP if x[0] == NameType._DEFAULT][0]
_DEFAULT = get_default_type_value(NameType)
val = models.IntegerField('name type', choices=_DATAMAP, blank=False)
class NameOriginType(mGrampsType):
from gen.lib.nameorigintype import NameOriginType
_DATAMAP = get_datamap(NameOriginType)
_CUSTOM = NameOriginType._CUSTOM
_DEFAULT = [x for x in _DATAMAP if x[0] == NameOriginType._DEFAULT][0]
_DEFAULT = get_default_type_value(NameOriginType)
val = models.IntegerField('name origin type', choices=_DATAMAP, blank=False)
class AttributeType(mGrampsType):
from gen.lib.attrtype import AttributeType
_DATAMAP = get_datamap(AttributeType)
_CUSTOM = AttributeType._CUSTOM
_DEFAULT = [x for x in _DATAMAP if x[0] == AttributeType._DEFAULT][0]
_DEFAULT = get_default_type_value(AttributeType)
val = models.IntegerField('attribute type', choices=_DATAMAP, blank=False)
class UrlType(mGrampsType):
from gen.lib.urltype import UrlType
_DATAMAP = get_datamap(UrlType)
_CUSTOM = UrlType._CUSTOM
_DEFAULT = [x for x in _DATAMAP if x[0] == UrlType._DEFAULT][0]
_DEFAULT = get_default_type_value(UrlType)
val = models.IntegerField('url type', choices=_DATAMAP, blank=False)
class ChildRefType(mGrampsType):
from gen.lib.childreftype import ChildRefType
_DATAMAP = get_datamap(ChildRefType)
_CUSTOM = ChildRefType._CUSTOM
_DEFAULT = [x for x in _DATAMAP if x[0] == ChildRefType._DEFAULT][0]
_DEFAULT = get_default_type_value(ChildRefType)
val = models.IntegerField('child reference type', choices=_DATAMAP,
blank=False)
@ -152,14 +158,14 @@ class RepositoryType(mGrampsType):
from gen.lib.repotype import RepositoryType
_DATAMAP = get_datamap(RepositoryType)
_CUSTOM = RepositoryType._CUSTOM
_DEFAULT = [x for x in _DATAMAP if x[0] == RepositoryType._DEFAULT][0]
_DEFAULT = get_default_type_value(RepositoryType)
val = models.IntegerField('repository type', choices=_DATAMAP, blank=False)
class EventType(mGrampsType):
from gen.lib.eventtype import EventType
_DATAMAP = get_datamap(EventType)
_CUSTOM = EventType._CUSTOM
_DEFAULT = [x for x in _DATAMAP if x[0] == EventType._DEFAULT][0]
_DEFAULT = get_default_type_value(EventType)
BIRTH = 12
DEATH = 13
val = models.IntegerField('event type', choices=_DATAMAP, blank=False)
@ -168,7 +174,7 @@ class FamilyRelType(mGrampsType):
from gen.lib.familyreltype import FamilyRelType
_DATAMAP = get_datamap(FamilyRelType)
_CUSTOM = FamilyRelType._CUSTOM
_DEFAULT = [x for x in _DATAMAP if x[0] == FamilyRelType._DEFAULT][0]
_DEFAULT = get_default_type_value(FamilyRelType)
val = models.IntegerField('family relation type', choices=_DATAMAP,
blank=False)
@ -176,7 +182,7 @@ class SourceMediaType(mGrampsType):
from gen.lib.srcmediatype import SourceMediaType
_DATAMAP = get_datamap(SourceMediaType)
_CUSTOM = SourceMediaType._CUSTOM
_DEFAULT = [x for x in _DATAMAP if x[0] == SourceMediaType._DEFAULT][0]
_DEFAULT = get_default_type_value(SourceMediaType)
val = models.IntegerField('source medium type', choices=_DATAMAP,
blank=False)
@ -184,22 +190,22 @@ class EventRoleType(mGrampsType):
from gen.lib.eventroletype import EventRoleType
_DATAMAP = get_datamap(EventRoleType)
_CUSTOM = EventRoleType._CUSTOM
_DEFAULT = [x for x in _DATAMAP if x[0] == EventRoleType._DEFAULT][0]
_DEFAULT = get_default_type_value(EventRoleType)
val = models.IntegerField('event role type', choices=_DATAMAP, blank=False)
class NoteType(mGrampsType):
from gen.lib.notetype import NoteType
_DATAMAP = get_datamap(NoteType)
_CUSTOM = NoteType._CUSTOM
_DEFAULT = [x for x in _DATAMAP if x[0] == NoteType._DEFAULT][0]
_DEFAULT = get_default_type_value(NoteType)
val = models.IntegerField('note type', choices=_DATAMAP, blank=False)
class MarkupType(mGrampsType):
from gen.lib.notetype import NoteType
_DATAMAP = [(0, "Custom")]
_CUSTOM = 0
_DEFAULT = _DATAMAP[0]
val = models.IntegerField('note type', choices=_DATAMAP, blank=False)
class StyledTextTagType(mGrampsType):
from gen.lib.styledtexttagtype import StyledTextTagType
_DATAMAP = get_datamap(StyledTextTagType)
_CUSTOM = None
_DEFAULT = None
val = models.IntegerField('styled text tag type', choices=_DATAMAP, blank=False)
class GenderType(mGrampsType):
_DATAMAP = [(2, 'Unknown'), (1, 'Male'), (0, 'Female')]
@ -716,7 +722,7 @@ class Lds(DateObject, SecondaryObject):
class Markup(models.Model):
note = models.ForeignKey('Note')
markup_type = models.ForeignKey('MarkupType')
styled_text_tag_type = models.ForeignKey('StyledTextTagType')
order = models.PositiveIntegerField()
string = models.TextField(blank=True, null=True)
start_stop_list = models.TextField(default="[]")
@ -891,6 +897,7 @@ TABLES = [
("type", LdsType),
("type", LdsStatus),
("type", ThemeType),
("type", StyledTextTagType),
("abstract", DateObject),
("abstract", PrimaryObject),
("primary", Person),

View File

@ -22,7 +22,7 @@
""" Views for Person, Name, and Surname """
## Gramps Modules
from webapp.utils import _, boolean, update_last_changed, StyledNoteFormatter
from webapp.utils import _, boolean, update_last_changed, StyledNoteFormatter, parse_styled_text
from webapp.grampsdb.models import Note
from webapp.grampsdb.forms import *
from webapp.libdjango import DjangoInterface
@ -65,14 +65,15 @@ def process_note(request, context, handle, action, add_to=None): # view, edit, s
noteform.model = note
elif action == "save":
note = Note.objects.get(handle=handle)
genlibnote = db.get_note_from_handle(note.handle)
notetext = snf.format(genlibnote) # FIXME
notetext = ""
noteform = NoteForm(request.POST, instance=note, initial={"notetext": notetext})
noteform.model = note
#note.text = noteform.data["notetext"] # FIXME: split text and tags
if noteform.is_valid():
update_last_changed(note, request.user.username)
notedata = parse_styled_text(noteform.data["notetext"])
note.text = notedata[0]
note = noteform.save()
dji.save_note_markup(note, notedata[1])
dji.rebuild_cache(note)
notetext = noteform.data["notetext"]
action = "view"
@ -81,13 +82,15 @@ def process_note(request, context, handle, action, add_to=None): # view, edit, s
action = "edit"
elif action == "create":
note = Note(handle=create_id())
notetext = "" # FIXME
notetext = ""
noteform = NoteForm(request.POST, instance=note, initial={"notetext": notetext})
noteform.model = note
#note.text = noteform.data["notetext"] # FIXME: split text and tags
if noteform.is_valid():
update_last_changed(note, request.user.username)
notedata = parse_styled_text(noteform.data["notetext"])
note.text = notedata[0]
note = noteform.save()
dji.save_note_markup(note, notedata[1])
dji.rebuild_cache(note)
if add_to:
item, handle = add_to

View File

@ -42,6 +42,7 @@ from gen.lib.familyreltype import FamilyRelType
from gen.lib.srcmediatype import SourceMediaType
from gen.lib.eventroletype import EventRoleType
from gen.lib.notetype import NoteType
from gen.lib.styledtexttagtype import StyledTextTagType
from grampsdb.models import (GenderType, LdsType, LdsStatus,
NameFormatType, NameOriginType, ThemeType)
@ -61,7 +62,7 @@ for table, entries in [("grampsdb.config",
(("setting", "\"db_version\""),
("description", "\"database scheme version\""),
("value_type", "\"str\""),
("value", "\"0.5.1\"")),
("value", "\"0.6.0\"")),
(("setting", "\"db_created\""),
("description", "\"database creation date/time\""),
("value_type", "\"str\""),
@ -174,7 +175,7 @@ for table, entries in [("grampsdb.config",
type_models = [NameType, NameOriginType, AttributeType, UrlType, ChildRefType,
RepositoryType, EventType, FamilyRelType, SourceMediaType,
EventRoleType, NoteType, GenderType, LdsType, LdsStatus,
NameFormatType]
NameFormatType, StyledTextTagType]
for type in type_models:
count = 1
# Add each code:

View File

@ -299,14 +299,13 @@ class DjangoInterface(object):
retval = []
markups = models.Markup.objects.filter(note=note).order_by("order")
for markup in markups:
# FIXME: not all of these are strings; bummer
if markup.string and markup.string.isdigit():
value = int(markup.string)
else:
value = markup.string
start_stop_list = markup.start_stop_list
ss_list = eval(start_stop_list)
retval += [(tuple(markup.markup_type), value, ss_list)]
retval += [(tuple(markup.styled_text_tag_type), value, ss_list)]
return retval
def get_note(self, note):
@ -1257,12 +1256,14 @@ class DjangoInterface(object):
count = 1
for markup in markup_list:
markup_code, value, start_stop_list = markup
m = models.Markup(note=note, order=count,
markup_type=models.get_type(models.MarkupType,
markup_code,
get_or_create=True),
string=value,
start_stop_list=str(start_stop_list))
m = models.Markup(
note=note,
order=count,
styled_text_tag_type=models.get_type(models.StyledTextTagType,
markup_code,
get_or_create=False),
string=value,
start_stop_list=str(start_stop_list))
m.save()
def add_note(self, data):

View File

@ -30,7 +30,7 @@ dp = parser.parse
# "/home/dblank/gramps/trunk/example/gramps/data.gramps",
# cli.user.User())
from webapp.utils import StyledNoteFormatter
from webapp.utils import StyledNoteFormatter, parse_styled_text
snf = StyledNoteFormatter(db)
#for n in Note.objects.all():
# note = db.get_note_from_handle(n.handle)
@ -38,5 +38,9 @@ snf = StyledNoteFormatter(db)
note = Note.objects.get(handle="aef30789d3d2090abe2")
genlibnote = db.get_note_from_handle(note.handle)
print snf.format(genlibnote)
#st = gen.lib.StyledText(note.text, dji.get_note_markup(note))
html_text = snf.format(genlibnote)
# FIXME: this looks wrong:
#print html_text
#print parse_styled_text(html_text)
##st = gen.lib.StyledText(note.text, dji.get_note_markup(note))

View File

@ -28,7 +28,9 @@
#------------------------------------------------------------------------
import locale
import sys
import re
import datetime
from HTMLParser import HTMLParser
#------------------------------------------------------------------------
#
@ -744,6 +746,7 @@ class WebAppBackend(HtmlBackend):
DocBackend.FONTFACE,
DocBackend.FONTSIZE,
DocBackend.FONTCOLOR,
DocBackend.SUPERSCRIPT,
DocBackend.LINK,
]
@ -751,6 +754,7 @@ class WebAppBackend(HtmlBackend):
DocBackend.BOLD : ("<b>", "</b>"),
DocBackend.ITALIC : ("<i>", "</i>"),
DocBackend.UNDERLINE : ('<u>', '</u>'),
DocBackend.SUPERSCRIPT : ("<sup>", "</sup>"),
}
### Taken from Narrated Web Report
@ -761,53 +765,15 @@ class StyledNoteFormatter(object):
self._backend.build_link = self.build_link
def format(self, note):
return self.styled_note(
note.get_styledtext(),
note.get_format(),
contains_html=(note.get_type() == gen.lib.NoteType.HTML_CODE))
return self.styled_note(note.get_styledtext())
def styled_note(self, styledtext, format, contains_html=False):
"""
styledtext : assumed a StyledText object to write
format : = 0 : Flowed, = 1 : Preformatted
style_name : name of the style to use for default presentation
"""
def styled_note(self, styledtext):
text = str(styledtext)
if not text:
return ''
s_tags = styledtext.get_tags()
markuptext = self._backend.add_markup_from_styled(text, s_tags,
split='\n')
htmllist = Html("div") #"div", class_="grampsstylednote")
if contains_html:
htmllist += text
else:
linelist = []
linenb = 1
for line in markuptext.split('\n'):
[line, sigcount] = process_spaces(line, format)
if sigcount == 0:
# The rendering of an empty paragraph '<p></p>'
# is undefined so we use a non-breaking space
if linenb == 1:
linelist.append('&nbsp;')
htmllist.extend(Html('p') + linelist)
linelist = []
linenb = 1
else:
if linenb > 1:
linelist[-1] += '<br />'
linelist.append(line)
linenb += 1
if linenb > 1:
htmllist.extend(Html('p') + linelist)
# if the last line was blank, then as well as outputting the previous para,
# which we have just done,
# we also output a new blank para
if sigcount == 0:
linelist = ["&nbsp;"]
htmllist.extend(Html('p') + linelist)
return "".join(htmllist)
markuptext = self._backend.add_markup_from_styled(text, s_tags, split='\n').replace("\n", "<br/>")
return markuptext
def build_link(self, prop, handle, obj_class):
"""
@ -826,3 +792,117 @@ class StyledNoteFormatter(object):
"in table name '%s'" % obj_class)
# handle, ppl
return "/%s/%s" % (obj_class.lower(), handle)
class WebAppParser(HTMLParser):
BOLD = 0
ITALIC = 1
UNDERLINE = 2
FONTFACE = 3
FONTSIZE = 4
FONTCOLOR = 5
HIGHLIGHT = 6
SUPERSCRIPT = 7
LINK = 8
def __init__(self):
HTMLParser.__init__(self)
self.__text = ""
self.__tags = {}
self.__stack = []
def handle_data(self, data):
self.__text += data
def push(self, pos, tag, attrs):
self.__stack.append([pos, tag, attrs])
def pop(self):
return self.__stack.pop()
def handle_starttag(self, tag, attrs):
self.push(len(self.__text), tag.lower(), attrs)
def handle_endtag(self, tag):
tag = tag.lower()
(start_pos, start_tag, attrs) = self.pop()
attrs = {x[0]: x[1] for x in attrs}
if tag != start_tag: return # skip <i><b></i></b> formats
arg = None
tagtype = None
if tag == "span":
# "span": get color, font, size
if "style" in attrs:
style = attrs["style"]
if 'color' in style:
tagtype = self.FONTCOLOR
match = re.match("color:([^;]*);", style)
if match:
arg = match.groups()[0]
else:
print "Unhandled color tag: '%s'" % style
elif "font-family" in style:
tagtype = self.FONTFACE
match = re.match("font-family:'([^;]*)';", style)
if match:
arg = match.groups()[0]
else:
print "Unhandled font-family tag: '%s'" % style
elif "font-size" in style:
tagtype = self.FONTSIZE
match = re.match("font-size:([^;]*)px;", style)
if match:
arg = int(match.groups()[0])
else:
print "Unhandled font-size tag: '%s'" % style
else:
print "Unhandled span arg: '%s'" % attrs
else:
print "span has no style: '%s'" % attrs
# "b", "i", "u", "sup": direct conversion
elif tag == "b":
tagtype = self.BOLD
elif tag == "i":
tagtype = self.ITALIC
elif tag == "u":
tagtype = self.UNDERLINE
elif tag == "sup":
tagtype = self.SUPERSCRIPT
elif tag == "br":
self.__text += "\n"
return
elif tag == "p":
self.__text += "\n\n"
return
elif tag == "a":
tagtype = self.LINK
# "a": get /object/handle, or url
if "href" in attrs:
href = attrs["href"]
if href.startswith("/"):
parts = href.split("/")
arg = "gramps://%s/handle/%s" % (parts[-2].title(), parts[-1])
else:
arg = href
else:
print "Unhandled a with no href: '%s'" % attrs
else:
return
print "Unhandled tag: '%s'" % tag
key = ((tagtype, u''), arg)
if key not in self.__tags:
self.__tags[key] = []
self.__tags[key].append((start_pos, len(self.__text)))
def tags(self):
# [((code, u''), string/num, [(start, stop), ...]), ...]
return [(key[0], key[1], self.__tags[key]) for key in self.__tags]
def text(self):
return self.__text
def parse_styled_text(text):
parser = WebAppParser()
parser.feed(text)
parser.close()
return (parser.text(), parser.tags())