~ubuntu-branches/ubuntu/trusty/gtg/trusty

« back to all changes in this revision

Viewing changes to GTG/taskeditor/taskviewserial.py

  • Committer: Package Import Robot
  • Author(s): Luca Falavigna
  • Date: 2012-04-10 23:08:21 UTC
  • mfrom: (1.1.8)
  • Revision ID: package-import@ubuntu.com-20120410230821-q6it7f4d7elut6pv
Tags: 0.2.9-1
* New upstream release (Closes: #668096).
  - Implement a search text box (Closes: #650279).
  - Window title reflects active tasks (LP: #537096).
  - Fix misbehaviours of the indicator applet (LP: #548836, #676353).
  - Fix crash when selecting notification area plugin twice (LP: #550321).
  - Fix sorting of tasks by date (LP: #556159).
  - Fix excessive delays at startup (LP: #558600).
  - Fix crash with dates having unknown values (LP: #561449).
  - Fix crash issued when pressing delete key (LP: #583103).
  - Keep notification plugin enabled after logoff (LP: #617257).
  - Fix Hamster plugin to work with recent Hamster versions (LP: #620313).
  - No longer use non-unicode strings (LP: #680632).
  - New RTM sync mechanism (LP: #753327).
  - Fix crashes while handling XML storage file (LP: #916474, #917634).
* debian/patches/*:
  - Drop all patches, they have been merged upstream.
* debian/patches/shebang.patch:
  - Fix shebang line.
* debian/patches/manpages.patch:
  - Fix some groff warnings in gtg_new_task man page
* debian/compat:
  - Bump compatibility level to 9.
* debian/control:
  - Bump X-Python-Version to >= 2.6.
  - Add python-liblarch and python-liblarch-gtk to Depends field.
  - Add python-cheetah, python-geoclue, python-gnomekeyring,
    python-launchpadlib and python-suds to Suggests field.
  - Bump Standards-Version to 3.9.3.
* debian/copyright:
  - Refresh copyright information.
  - Format now points to copyright-format site.
* debian/rules:
  - Make gtcli_bash_completion script executable.
* debian/watch:
  - Update watch file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
5
 
#
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
9
 
# version.
10
 
#
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
14
 
# details.
15
 
#
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
20
 
 
21
 
 
22
 
#The following functions are used by the gtk.TextBuffer to serialize
23
 
# the content of the task
24
 
 
25
 
########### Serializing functions ##############
26
 
### Serialize the task : transform it's content in something
27
 
#we can store. This function signature is defined in PyGTK
28
 
 
29
 
class Serializer:
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
33
 
        its = start.copy()
34
 
        ite = end.copy()
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")
46
 
 
47
 
    def parse_buffer(self, buff, start, end, parent, doc, done=[]):
48
 
        """
49
 
        Parse the buffer and output an XML representation.
50
 
 
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
53
 
                                the XML dom
54
 
            @done : the list of parsed tags
55
 
        """
56
 
 
57
 
        def is_know_tag(tag):
58
 
            """
59
 
            Return True if "tag" is a know tag. "tag" must be a gtk.TextTag.
60
 
            """
61
 
            know_tags = ["is_subtask", "is_indent", "is_tag"]
62
 
            for know in know_tags:
63
 
                if tag.get_data(know):
64
 
                    return True
65
 
            return False
66
 
        it = start.copy()
67
 
        tag = None
68
 
        start_it = start.copy()
69
 
        end_it = start.copy()
70
 
 
71
 
        buffer_end = False
72
 
        while not buffer_end:
73
 
            if tag is None:
74
 
                # We are not in a tag context
75
 
                # Get list of know tags which begin here
76
 
                # and are not already process
77
 
                tags = []
78
 
                for ta in it.get_tags():
79
 
                    if it.begins_tag(ta) and ta not in done and \
80
 
                                                is_know_tag(ta):
81
 
                        tags.append(ta)
82
 
                        #print ta.get_data("tagname")
83
 
                if it.begins_tag() and len(tags) > 0:
84
 
                    # We enter in a tag context
85
 
                    tag = tags.pop()
86
 
                    done.append(tag)
87
 
                    start_it = it.copy()
88
 
                else:
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()))
93
 
            else:
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
97
 
                    # We process the tag
98
 
                    end_it = it.copy()
99
 
                    end_it.backward_char()
100
 
                    if tag.get_data("is_tag"):
101
 
                        #The current gtkTextTag is a tag
102
 
                        #Recursive call
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
109
 
                        tagname = "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"))
115
 
                        it.forward_line()
116
 
                    elif ta.get_data('is_indent'):
117
 
                        #The current gtkTextTag is a indent
118
 
                        indent = buff.get_text(start_it, end_it)
119
 
                        if '\n' in indent:
120
 
                            parent.appendChild(doc.createTextNode('\n'))
121
 
                        it = end_it
122
 
                    # We go out the tag context
123
 
                    tag = None
124
 
                    if not it.equal(end):
125
 
                        it.backward_char()
126
 
            if it.equal(end):
127
 
                buffer_end = True
128
 
            else:
129
 
                it.forward_char()
130
 
 
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
139
 
        parent.normalize()
140
 
        return parent
141
 
 
142
 
 
143
 
######################## Deserializing ##################################
144
 
### Deserialize : put all in the TextBuffer
145
 
# This function signature is defined in PyGTK
146
 
 
147
 
class Unserializer:
148
 
 
149
 
    def __init__(self, taskview):
150
 
        #We keep a reference to the original taskview
151
 
        #Not very pretty but convenient
152
 
        self.tv = taskview
153
 
 
154
 
    #Disabling pylint argument usage since we know we are not using all args
155
 
    def unserialize(self, register_buf, content_buf, ite, data,\
156
 
                    cr_tags, udata):
157
 
        if data:
158
 
            element = xml.dom.minidom.parseString(data)
159
 
            success = self.parsexml(content_buf, ite, element.firstChild)
160
 
        else:
161
 
            success = self.parsexml(content_buf, ite, None)
162
 
        return success
163
 
 
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():
171
 
            end_line += 1
172
 
        for tid in st_list:
173
 
            self.tv.write_subtask(buff, end_line, tid)
174
 
            end_line += 1
175
 
 
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):
179
 
        if not itera:
180
 
            itera = buff.get_end_iter()
181
 
        if tag:
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)
186
 
 
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()
192
 
        taglist2 = []
193
 
        if element:
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
201
 
                        #Of known subtasks
202
 
                        #If the subtask is not in the list, we don't write it
203
 
                        if tid in subtasks:
204
 
                            subtasks.remove(tid)
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
209
 
                        if text:
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)
214
 
                    else:
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)
222
 
                        else:
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()
230
 
        for t in taglist2:
231
 
            if t in taglist:
232
 
                taglist.remove(t)
233
 
        #We remove duplicates
234
 
        for t in taglist:
235
 
            while t in taglist:
236
 
                taglist.remove(t)
237
 
            taglist.append(t)
238
 
        if len(taglist) > 0:
239
 
            self.tv.insert_tags(taglist)
240
 
        buf.delete_mark(start)
241
 
        buf.delete_mark(end)
242
 
        return True