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:
parent
a8f5d1f8e1
commit
abbb02a08e
@ -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() {
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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):
|
||||
|
@ -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))
|
||||
|
@ -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(' ')
|
||||
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 = [" "]
|
||||
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())
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user