1
# -*- coding: utf-8 -*-
2
# -----------------------------------------------------------------------------
3
# Gettings Things Gnome! - a personal organizer for the GNOME desktop
4
# Copyright (c) 2008-2009 - Lionel Dricot & Bertrand Rousseau
6
# This program is free software: you can redistribute it and/or modify it under
7
# the terms of the GNU General Public License as published by the Free Software
8
# Foundation, either version 3 of the License, or (at your option) any later
11
# This program is distributed in the hope that it will be useful, but WITHOUT
12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16
# You should have received a copy of the GNU General Public License along with
17
# this program. If not, see <http://www.gnu.org/licenses/>.
18
# -----------------------------------------------------------------------------
19
import xml.dom.minidom
22
#The following functions are used by the gtk.TextBuffer to serialize
23
# the content of the task
25
########### Serializing functions ##############
26
### Serialize the task : transform it's content in something
27
#we can store. This function signature is defined in PyGTK
30
#Disabling pylint argument usage since we know we are not using all args
31
def serialize(self, register_buf, content_buf, start, end, udata):
32
#Currently we serialize in XML
35
#Warning : the serialization process cannot be allowed to modify
36
#the content of the buffer.
37
doc = xml.dom.minidom.Document()
38
parent = doc.createElement("content")
39
doc.appendChild(self.parse_buffer(content_buf, its, ite, parent, doc))
40
#We don't want the whole doc with the XML declaration
41
#we only take the first node (the "content" one)
42
node = doc.firstChild #pylint: disable-msg=E1101
43
#print "********************"
44
#print node.toxml().encode("utf-8")
45
return node.toxml().encode("utf-8")
47
def parse_buffer(self, buff, start, end, parent, doc, done=[]):
49
Parse the buffer and output an XML representation.
51
@var buff, start, end : the buffer to parse from start to end
52
@var parent, doc: the XML element to add data and doc is
54
@done : the list of parsed tags
59
Return True if "tag" is a know tag. "tag" must be a gtk.TextTag.
61
know_tags = ["is_subtask", "is_indent", "is_tag"]
62
for know in know_tags:
63
if tag.get_data(know):
68
start_it = start.copy()
74
# We are not in a tag context
75
# Get list of know tags which begin here
76
# and are not already process
78
for ta in it.get_tags():
79
if it.begins_tag(ta) and ta not in done and \
82
#print ta.get_data("tagname")
83
if it.begins_tag() and len(tags) > 0:
84
# We enter in a tag context
89
# We stay out of a tag context
90
# We write the char in the xml node
91
if it.get_char() != "\0":
92
parent.appendChild(doc.createTextNode(it.get_char()))
94
# We are in a tag context
95
if it.ends_tag(tag) or it.equal(end):
96
# There is the end of the gtkTextTag
99
end_it.backward_char()
100
if tag.get_data("is_tag"):
101
#The current gtkTextTag is a tag
103
nparent = doc.createElement("tag")
104
child = self.parse_buffer(buff, start_it, end_it, \
105
nparent, doc, done=done)
106
parent.appendChild(child)
107
elif ta.get_data('is_subtask'):
108
#The current gtkTextTag is a subtask
110
subt = doc.createElement(tagname)
111
target = ta.get_data('child')
112
subt.appendChild(doc.createTextNode(target))
113
parent.appendChild(subt)
114
parent.appendChild(doc.createTextNode("\n"))
116
elif ta.get_data('is_indent'):
117
#The current gtkTextTag is a indent
118
indent = buff.get_text(start_it, end_it)
120
parent.appendChild(doc.createTextNode('\n'))
122
# We go out the tag context
124
if not it.equal(end):
131
#Finishing with an \n before closing </content>
132
if parent.localName == "content":
133
last_val = parent.lastChild
134
#We add a \n only if needed (= we don't have a "\n" at the end)
135
if last_val and last_val.nodeType == 3 and \
136
last_val.nodeValue[-1] != '\n':
137
parent.appendChild(doc.createTextNode('\n'))
138
#This function concatenates all the adjacent text node of the XML
143
######################## Deserializing ##################################
144
### Deserialize : put all in the TextBuffer
145
# This function signature is defined in PyGTK
149
def __init__(self, taskview):
150
#We keep a reference to the original taskview
151
#Not very pretty but convenient
154
#Disabling pylint argument usage since we know we are not using all args
155
def unserialize(self, register_buf, content_buf, ite, data,\
158
element = xml.dom.minidom.parseString(data)
159
success = self.parsexml(content_buf, ite, element.firstChild)
161
success = self.parsexml(content_buf, ite, None)
164
#Insert a list of subtasks at the end of the buffer
165
def insert_subtasks(self, buff, st_list):
166
#If the lastline of the buffer is not empty, we add an extra \n
167
end_end = buff.get_end_iter()
168
end_line = end_end.get_line()
169
start_end = buff.get_iter_at_line(end_line)
170
if buff.get_text(start_end, end_end).strip():
173
self.tv.write_subtask(buff, end_line, tid)
176
#insert a GTG tag with its TextView tag.
177
#Yes, we know : the word tag is used for two different concepts here.
178
def insert_tag(self, buff, tag, itera=None):
180
itera = buff.get_end_iter()
182
sm = buff.create_mark(None, itera, True)
183
em = buff.create_mark(None, itera, False)
184
buff.insert(itera, tag)
185
self.tv.apply_tag_tag(buff, tag, sm, em)
187
#parse the XML and put the content in the buffer
188
def parsexml(self, buf, ite, element):
189
start = buf.create_mark(None, ite, True)
190
end = buf.create_mark(None, ite, False)
191
subtasks = self.tv.get_subtasks()
194
for n in element.childNodes:
195
itera = buf.get_iter_at_mark(end)
196
if n.nodeType == n.ELEMENT_NODE:
197
#print "<%s>" %n.nodeName
198
if n.nodeName == "subtask":
199
tid = n.firstChild.nodeValue
200
#We remove the added subtask from the list
202
#If the subtask is not in the list, we don't write it
205
line_nbr = itera.get_line()
206
self.tv.write_subtask(buf, line_nbr, tid)
207
elif n.nodeName == "tag":
208
text = n.firstChild.nodeValue
210
self.insert_tag(buf, text, itera)
211
#We remove the added tag from the tag list
212
#of known tag for this task
213
taglist2.append(text)
215
self.parsexml(buf, itera, n)
216
s = buf.get_iter_at_mark(start)
217
e = buf.get_iter_at_mark(end)
218
if n.nodeName == "link":
219
anchor = n.getAttribute("target")
220
tag = self.tv.create_anchor_tag(buf, anchor, None)
221
buf.apply_tag(tag, s, e)
223
buf.apply_tag_by_name(n.nodeName, s, e)
224
elif n.nodeType == n.TEXT_NODE:
225
buf.insert(itera, n.nodeValue)
226
#Now, we insert the remaining subtasks
227
self.insert_subtasks(buf, subtasks)
228
#We also insert the remaining tags (a a new line)
229
taglist = self.tv.get_tagslist()
233
#We remove duplicates
239
self.tv.insert_tags(taglist)
240
buf.delete_mark(start)