Erik Grinaker is sharing code with you

Bitbucket is a code hosting site. Unlimited public and private repositories. Free for small teams.

Don't show this again

erikg / Revelation

Revelation is a password manager for the GNOME desktop, released under the GNU GPL license. It stores all your accounts and passwords in a single, secure place, and gives you access to it through a user-friendly graphical interface.

Clone this repository (size: 2.1 MB): HTTPS / SSH
hg clone https://bitbucket.org/erikg/revelation
hg clone ssh://hg@bitbucket.org/erikg/revelation

Revelation / src / lib / datahandler / xhtml.py

commit
7ae1f811fd74
parent
2645d2e5e351
branch
default

fixed crash in XHTML exporter [Javier Kohen]

1
29c5326b470e
#
2
78fb3436ec03
# Revelation - a password manager for GNOME 2
3
29c5326b470e
# http://oss.codepoet.no/revelation/
4
29c5326b470e
# $Id$
5
29c5326b470e
#
6
29c5326b470e
# Module for exporting to XHTML files
7
29c5326b470e
#
8
29c5326b470e
#
9
d230b54e5239
# Copyright (c) 2003-2006 Erik Grinaker
10
29c5326b470e
#
11
29c5326b470e
# This program is free software; you can redistribute it and/or
12
29c5326b470e
# modify it under the terms of the GNU General Public License
13
29c5326b470e
# as published by the Free Software Foundation; either version 2
14
29c5326b470e
# of the License, or (at your option) any later version.
15
29c5326b470e
#
16
29c5326b470e
# This program is distributed in the hope that it will be useful,
17
29c5326b470e
# but WITHOUT ANY WARRANTY; without even the implied warranty of
18
29c5326b470e
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
29c5326b470e
# GNU General Public License for more details.
20
29c5326b470e
#
21
29c5326b470e
# You should have received a copy of the GNU General Public License
22
29c5326b470e
# along with this program; if not, write to the Free Software
23
29c5326b470e
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24
29c5326b470e
#
25
29c5326b470e
26
c094b5acab4e
import base
27
c094b5acab4e
from revelation import config, data, entry
28
c094b5acab4e
29
6f6f242dab09
import gettext, time
30
6f6f242dab09
31
6f6f242dab09
_ = gettext.gettext
32
c094b5acab4e
33
c094b5acab4e
34
c094b5acab4e
IMAGEPATH	= "http://oss.codepoet.no/revelation/img/fileicons"
35
29c5326b470e
36
29c5326b470e
37
29c5326b470e
class XHTML(base.DataHandler):
38
29c5326b470e
	"Data handler for XHTML export"
39
29c5326b470e
40
29c5326b470e
	name		= "XHTML / CSS"
41
c094b5acab4e
	importer	= False
42
c094b5acab4e
	exporter	= True
43
c094b5acab4e
	encryption	= False
44
29c5326b470e
45
29c5326b470e
46
29c5326b470e
	def __init__(self):
47
29c5326b470e
		base.DataHandler.__init__(self)
48
29c5326b470e
49
29c5326b470e
50
29c5326b470e
	def __generate_css(self):
51
29c5326b470e
		"Generates a CSS for the XHTML document"
52
29c5326b470e
53
29c5326b470e
		css = """
54
29c5326b470e
		/* containers */
55
29c5326b470e
		body {
56
29c5326b470e
			margin: 20px 10px;
57
29c5326b470e
			padding: 0px;
58
29c5326b470e
59
29c5326b470e
			font-family: sans-serif;
60
29c5326b470e
			font-size: 10pt;
61
29c5326b470e
			line-height: 1.3;
62
29c5326b470e
63
29c5326b470e
			color: #333333;
64
29c5326b470e
			background-color: #ffffff;
65
29c5326b470e
		}
66
29c5326b470e
67
29c5326b470e
		div {
68
29c5326b470e
			margin: 0px;
69
29c5326b470e
			padding: 0px;
70
29c5326b470e
		}
71
29c5326b470e
72
29c5326b470e
		p {
73
29c5326b470e
			margin: 0px 0px 5px 0px;
74
29c5326b470e
			padding: 0px;
75
29c5326b470e
		}
76
29c5326b470e
77
6865ee763d14
		table {
78
29c5326b470e
			font-family: sans-serif;
79
29c5326b470e
			font-size: 10pt;
80
6865ee763d14
			line-height: 1.3;
81
6865ee763d14
82
6865ee763d14
			margin: 0px;
83
6865ee763d14
			border-collapse: collapse;
84
29c5326b470e
85
29c5326b470e
			color: #333333;
86
29c5326b470e
			background-color: transparent;
87
29c5326b470e
		}
88
29c5326b470e
89
6865ee763d14
		td {
90
29c5326b470e
			text-align: left;
91
6865ee763d14
			vertical-align: top;
92
29c5326b470e
		}
93
29c5326b470e
94
29c5326b470e
		th {
95
6865ee763d14
			text-align: left;
96
6865ee763d14
			vertical-align: top;
97
6865ee763d14
98
29c5326b470e
			font-weight: bold;
99
29c5326b470e
			color: #000000;
100
29c5326b470e
		}
101
29c5326b470e
102
29c5326b470e
103
29c5326b470e
104
29c5326b470e
		/* headings */
105
29c5326b470e
		h1, h2, h3 {
106
29c5326b470e
			margin: 0px;
107
29c5326b470e
			padding: 0px;
108
29c5326b470e
			line-height: 1;
109
29c5326b470e
			font-weight: bold;
110
29c5326b470e
			color: #000000;
111
29c5326b470e
		}
112
29c5326b470e
113
29c5326b470e
		h1 {
114
6865ee763d14
			margin-bottom: 20px;
115
29c5326b470e
			font-size: 16pt;
116
29c5326b470e
		}
117
29c5326b470e
118
29c5326b470e
		h2 {
119
29c5326b470e
			margin-bottom: 5px;
120
29c5326b470e
			font-size: 14pt;
121
29c5326b470e
		}
122
29c5326b470e
123
29c5326b470e
		h3 {
124
29c5326b470e
			font-size: 10pt;
125
29c5326b470e
		}
126
29c5326b470e
127
29c5326b470e
128
29c5326b470e
129
29c5326b470e
		/* content */
130
29c5326b470e
		a {
131
29c5326b470e
			color: #3333cc;
132
29c5326b470e
			text-decoration: none;
133
29c5326b470e
		}
134
29c5326b470e
135
29c5326b470e
		a:hover {
136
29c5326b470e
			text-decoration: underline;
137
29c5326b470e
		}
138
29c5326b470e
139
6865ee763d14
		img {
140
6865ee763d14
			margin: 0px;
141
6865ee763d14
			padding: 0px;
142
6865ee763d14
			border: none;
143
6865ee763d14
		}
144
6865ee763d14
145
29c5326b470e
		strong {
146
29c5326b470e
			color: #000000;
147
29c5326b470e
		}
148
29c5326b470e
149
29c5326b470e
150
29c5326b470e
151
6865ee763d14
		/* the content area */
152
6865ee763d14
		#content {
153
6865ee763d14
			margin-right: 220px;
154
6865ee763d14
		}
155
6865ee763d14
156
6865ee763d14
157
6865ee763d14
158
6865ee763d14
		/* the sidebar */
159
6865ee763d14
		#sidebar {
160
6865ee763d14
			width: 200px;
161
6865ee763d14
			float: right;
162
6865ee763d14
		}
163
6865ee763d14
164
6865ee763d14
		#sidebar h2 {
165
6865ee763d14
			margin: 20px 0px 10px 0px;
166
6865ee763d14
			padding: 0px 0px 5px 0px;
167
6865ee763d14
			border-bottom: 1px dashed #3366cc;
168
6865ee763d14
			text-transform: lowercase;
169
6865ee763d14
		}
170
6865ee763d14
171
6865ee763d14
		#sidebar h2 img.icon {
172
6865ee763d14
			width: 24px;
173
6865ee763d14
			height: 24px;
174
6865ee763d14
			margin-right: 5px;
175
6865ee763d14
			vertical-align: middle;
176
6865ee763d14
		}
177
6865ee763d14
178
6865ee763d14
		#sidebar h3 {
179
6865ee763d14
			margin-bottom: 2px;
180
6865ee763d14
			text-transform: lowercase;
181
6865ee763d14
		}
182
6865ee763d14
183
6865ee763d14
		#sidebar p {
184
6865ee763d14
			margin: 0px 5px 10px 15px;
185
6865ee763d14
		}
186
6865ee763d14
187
6865ee763d14
		#sidebar ul {
188
6865ee763d14
			list-style: none;
189
6865ee763d14
			padding: 0px;
190
29c5326b470e
			margin: 0px 0px 10px 0px;
191
29c5326b470e
		}
192
29c5326b470e
193
6865ee763d14
		#sidebar ul ul {
194
6865ee763d14
			margin: 0px 0px 0px 15px;
195
29c5326b470e
		}
196
29c5326b470e
197
6865ee763d14
		#sidebar ul.accountlist {
198
6865ee763d14
			margin-left: 15px;
199
6865ee763d14
		}
200
6865ee763d14
201
6865ee763d14
202
6865ee763d14
203
6865ee763d14
		/* the entrylist */
204
6865ee763d14
		#entrylist {
205
6865ee763d14
			width: 99%;
206
6865ee763d14
			padding: 0px;
207
29c5326b470e
			margin: 0px;
208
29c5326b470e
		}
209
29c5326b470e
210
6865ee763d14
211
6865ee763d14
212
6865ee763d14
		/* the footer */
213
6865ee763d14
		#footer {
214
6865ee763d14
			margin: 50px 220px 10px 0px;
215
6865ee763d14
			font-size: 8pt;
216
6865ee763d14
			text-align: center;
217
6865ee763d14
			color: #aaaaaa;
218
29c5326b470e
		}
219
29c5326b470e
220
6865ee763d14
		#footer a {
221
6865ee763d14
			color: #8888ee;
222
29c5326b470e
		}
223
29c5326b470e
224
6865ee763d14
225
6865ee763d14
226
6865ee763d14
		/* folders */
227
6865ee763d14
		li.folder {
228
6865ee763d14
			width: 100%;
229
6865ee763d14
			list-style-type: none;
230
6865ee763d14
		}
231
6865ee763d14
232
6865ee763d14
		li.folder .folder-data {
233
6865ee763d14
			margin: 0px 0px 10px 0px;
234
6865ee763d14
			padding: 2px 5px 3px 5px;
235
6865ee763d14
236
6865ee763d14
			border: 1px solid #3366cc;
237
6865ee763d14
			background-color: #e5ecf9;
238
6865ee763d14
		}
239
6865ee763d14
240
6865ee763d14
		li.folder .folder-data h2 {
241
6865ee763d14
			margin: 0px;
242
6865ee763d14
		}
243
6865ee763d14
244
6865ee763d14
		li.folder .folder-data p {
245
6865ee763d14
			margin: 0px;
246
6865ee763d14
		}
247
6865ee763d14
248
6865ee763d14
249
6865ee763d14
250
6865ee763d14
		/* accounts  */
251
6865ee763d14
		li.account {
252
6865ee763d14
			list-style-type: none;
253
6865ee763d14
			width: 350px;
254
6865ee763d14
			margin: 0px 0px 10px 0px;
255
6865ee763d14
			border: 1px solid #3366cc;
256
29c5326b470e
		}
257
29c5326b470e
258
29c5326b470e
		li.account .heading {
259
29c5326b470e
			padding: 2px 5px;
260
29c5326b470e
			background-color: #e5ecf9;
261
29c5326b470e
			border-bottom: 1px solid #3366cc;
262
29c5326b470e
		}
263
29c5326b470e
264
29c5326b470e
		li.account .heading h2 {
265
29c5326b470e
			margin: 0px 0px 1px 0px;
266
29c5326b470e
		}
267
29c5326b470e
268
29c5326b470e
		li.account .heading img {
269
29c5326b470e
			float: right;
270
29c5326b470e
			width: 24px;
271
29c5326b470e
			height: 24px;
272
29c5326b470e
		}
273
29c5326b470e
274
6865ee763d14
		li.account .heading .description {
275
6865ee763d14
			margin: 0px;
276
6865ee763d14
		}
277
6865ee763d14
278
29c5326b470e
		li.account .heading .type {
279
29c5326b470e
			color: #000000;
280
29c5326b470e
			font-weight: bold;
281
29c5326b470e
		}
282
29c5326b470e
283
6865ee763d14
		li.account .data {
284
6865ee763d14
			padding: 5px;
285
6865ee763d14
		}
286
6865ee763d14
287
6865ee763d14
		li.account .data .fields {
288
6865ee763d14
			margin: 0px 0px 3px 0px;
289
6865ee763d14
		}
290
6865ee763d14
291
6865ee763d14
		li.account .data .fields td {
292
6865ee763d14
			padding: 1px 0px;
293
6865ee763d14
		}
294
6865ee763d14
295
6865ee763d14
		li.account .data .fields th {
296
6865ee763d14
			padding: 1px 5px 1px 0px;
297
6865ee763d14
		}
298
6865ee763d14
299
29c5326b470e
		li.account .updated {
300
29c5326b470e
			font-size: 8pt;
301
29c5326b470e
			text-align: right;
302
29c5326b470e
			margin: 0px;
303
29c5326b470e
		}
304
29c5326b470e
"""
305
29c5326b470e
306
29c5326b470e
		return css
307
29c5326b470e
308
29c5326b470e
309
29c5326b470e
	def __generate_entry(self, entrystore, iter, depth = 0):
310
29c5326b470e
		"Generates xhtml for an entry"
311
29c5326b470e
312
29c5326b470e
		tabs = "\t" * (depth + 2)
313
c094b5acab4e
		e = entrystore.get_entry(iter)
314
29c5326b470e
315
c094b5acab4e
		if e is not None:
316
c094b5acab4e
			e.path = self.__get_entryid(entrystore, iter)
317
6865ee763d14
318
6865ee763d14
319
29c5326b470e
		xhtml = ""
320
29c5326b470e
321
c094b5acab4e
		if e is None:
322
6865ee763d14
323
6865ee763d14
			xhtml += "<div id=\"content\">\n"
324
6865ee763d14
			xhtml += "	<ul id=\"entrylist\">\n"
325
6865ee763d14
326
6865ee763d14
			for i in range(entrystore.iter_n_children(iter)):
327
6865ee763d14
				child = entrystore.iter_nth_child(iter, i)
328
6865ee763d14
				xhtml += self.__generate_entry(entrystore, child, depth)
329
6865ee763d14
330
6865ee763d14
			xhtml += "	</ul>\n"
331
6865ee763d14
			xhtml += "</div>\n"
332
6865ee763d14
333
6865ee763d14
334
c094b5acab4e
		elif type(e) == entry.FolderEntry:
335
c094b5acab4e
			xhtml += tabs + "<li class=\"folder\" id=\"%s\">\n" % e.path
336
29c5326b470e
			xhtml += tabs + "	<div class=\"folder-data\">\n"
337
c094b5acab4e
			xhtml += tabs + "		<h2>%s</h2>\n" % e.name
338
29c5326b470e
339
c094b5acab4e
			if e.description != "":
340
c094b5acab4e
				xhtml += tabs + "		<p class=\"description\">%s</p>\n" % e.description
341
29c5326b470e
342
29c5326b470e
			xhtml += tabs + "	</div>\n"
343
29c5326b470e
			xhtml += tabs + "\n"
344
29c5326b470e
			xhtml += tabs + "	<ul>\n"
345
29c5326b470e
346
29c5326b470e
			for i in range(entrystore.iter_n_children(iter)):
347
29c5326b470e
				child = entrystore.iter_nth_child(iter, i)
348
6865ee763d14
				xhtml += self.__generate_entry(entrystore, child, depth + 2)
349
29c5326b470e
350
29c5326b470e
			xhtml += tabs + "	</ul>\n"
351
29c5326b470e
			xhtml += tabs + "</li>\n"
352
29c5326b470e
			xhtml += tabs + "\n"
353
29c5326b470e
354
29c5326b470e
355
29c5326b470e
		else:
356
6865ee763d14
357
c094b5acab4e
			xhtml += tabs + "<li class=\"account\" id=\"%s\">\n" % e.path
358
29c5326b470e
			xhtml += tabs + "	<div class=\"heading\">\n"
359
c094b5acab4e
			xhtml += tabs + "		<img src=\"%s/entry/%s.png\" alt=\"%s\" />\n" % ( IMAGEPATH, e.id, e.typename )
360
c094b5acab4e
			xhtml += tabs + "		<h2>%s</h2>\n" % e.name
361
c094b5acab4e
			xhtml += tabs + "		<p class=\"description\"><span class=\"type\">%s</span>%s</p>\n" % ( e.typename + (e.description != "" and "; " or ""), e.description )
362
29c5326b470e
			xhtml += tabs + "	</div>\n"
363
29c5326b470e
			xhtml += tabs + "\n"
364
29c5326b470e
365
29c5326b470e
			xhtml += tabs + "	<div class=\"data\">\n"
366
29c5326b470e
367
6865ee763d14
			fields = []
368
c094b5acab4e
			for field in e.fields:
369
6865ee763d14
				if field.value != "":
370
6865ee763d14
					fields.append(field)
371
29c5326b470e
372
6865ee763d14
			if len(fields) > 0:
373
6865ee763d14
				xhtml += tabs + "		<table class=\"fields\">\n"
374
29c5326b470e
375
6865ee763d14
				for field in fields:
376
6865ee763d14
					xhtml += tabs + "			<tr>\n"
377
6865ee763d14
					xhtml += tabs + "				<th>" + field.name + ":</th>\n"
378
6865ee763d14
					xhtml += tabs + "				<td>" + field.value + "</td>\n"
379
6865ee763d14
					xhtml += tabs + "			</tr>\n"
380
6865ee763d14
381
6865ee763d14
				xhtml += tabs + "		</table>\n"
382
6865ee763d14
383
c094b5acab4e
			xhtml += tabs + "		<p class=\"updated\">Updated " + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(e.updated)) + "</p>\n"
384
29c5326b470e
			xhtml += tabs + "	</div>\n"
385
29c5326b470e
			xhtml += tabs + "</li>\n"
386
6865ee763d14
			xhtml += tabs + "\n"
387
29c5326b470e
388
29c5326b470e
		return xhtml
389
29c5326b470e
390
29c5326b470e
391
29c5326b470e
	def __generate_footer(self):
392
29c5326b470e
		"Generates an xhtml footer"
393
29c5326b470e
394
29c5326b470e
		xhtml = ""
395
6865ee763d14
		xhtml += "<div id=\"footer\">\n"
396
c094b5acab4e
		xhtml += "	Generated by <a href=\"%s\">%s %s</a>" % ( config.URL, config.APPNAME, config.VERSION )
397
6865ee763d14
		xhtml += "</div>\n"
398
29c5326b470e
		xhtml += "</body>\n"
399
29c5326b470e
		xhtml += "</html>\n"
400
29c5326b470e
401
29c5326b470e
		return xhtml
402
29c5326b470e
403
29c5326b470e
404
29c5326b470e
	def __generate_header(self):
405
29c5326b470e
		"Generates an xhtml header"
406
29c5326b470e
407
29c5326b470e
		xhtml = ""
408
29c5326b470e
		xhtml += "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
409
29c5326b470e
		xhtml += "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
410
29c5326b470e
		xhtml += "<head>\n"
411
29c5326b470e
		xhtml += "	<title>Revelation account list</title>\n"
412
29c5326b470e
		xhtml += "	<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\" />\n"
413
29c5326b470e
		xhtml += "\n"
414
29c5326b470e
		xhtml += "	<style type=\"text/css\">\n"
415
29c5326b470e
		xhtml += self.__generate_css()
416
29c5326b470e
		xhtml += "	</style>\n"
417
29c5326b470e
		xhtml += "</head>\n"
418
29c5326b470e
		xhtml += "\n"
419
29c5326b470e
		xhtml += "<body>\n"
420
e1117203c473
		xhtml += "<h1>" + _('Revelation account list') + "</h1>\n"
421
29c5326b470e
		xhtml += "\n"
422
29c5326b470e
423
29c5326b470e
		return xhtml
424
29c5326b470e
425
29c5326b470e
426
29c5326b470e
	def __generate_sidebar(self, entrystore):
427
29c5326b470e
		"Generates a sidebar"
428
29c5326b470e
429
6865ee763d14
		xhtml = ""
430
6865ee763d14
		xhtml += "<div id=\"sidebar\">\n"
431
6865ee763d14
		xhtml += self.__generate_sidebar_fileinfo()
432
6865ee763d14
		xhtml += self.__generate_sidebar_foldertree(entrystore)
433
6865ee763d14
		xhtml += self.__generate_sidebar_accountlist(entrystore)
434
6865ee763d14
		xhtml += "</div>\n"
435
6865ee763d14
436
6865ee763d14
		return xhtml
437
6865ee763d14
438
6865ee763d14
439
6865ee763d14
	def __generate_sidebar_accountlist(self, entrystore):
440
6865ee763d14
		"Generates an account list"
441
6865ee763d14
442
29c5326b470e
		# find the entries
443
29c5326b470e
		entries = {}
444
c094b5acab4e
		iter = entrystore.iter_nth_child(None, 0)
445
29c5326b470e
446
6865ee763d14
		while iter is not None:
447
c094b5acab4e
			e = entrystore.get_entry(iter)
448
c094b5acab4e
			e.path = self.__get_entryid(entrystore, iter)
449
29c5326b470e
450
c094b5acab4e
			if type(e) != entry.FolderEntry:
451
c094b5acab4e
				if not entries.has_key(type(e)):
452
c094b5acab4e
					entries[type(e)] = []
453
29c5326b470e
454
c094b5acab4e
				entries[type(e)].append(e)
455
29c5326b470e
456
6865ee763d14
			iter = entrystore.iter_traverse_next(iter)
457
29c5326b470e
458
29c5326b470e
459
29c5326b470e
		# generate the xhtml
460
29c5326b470e
		xhtml = ""
461
7ae1f811fd74
		xhtml += ("	<h2><img src=\"%s/sidebar/accountlist.png\" class=\"icon\" alt=\"Account list\" />" + _('Account list') + "</h2>\n") % IMAGEPATH
462
29c5326b470e
		xhtml += "\n"
463
29c5326b470e
464
c094b5acab4e
		for entrytype in entry.ENTRYLIST:
465
29c5326b470e
			if not entries.has_key(entrytype):
466
29c5326b470e
				continue
467
29c5326b470e
468
dc75ad09464f
			xhtml += "	<h3>%s:</h3>\n" % entrytype().typename
469
29c5326b470e
			xhtml += "\n"
470
29c5326b470e
			xhtml += "	<ul class=\"accountlist\">\n"
471
29c5326b470e
472
29c5326b470e
			entrylist = entries[entrytype]
473
29c5326b470e
			entrylist.sort(lambda x,y: cmp(x.name.lower(), y.name.lower()))
474
29c5326b470e
475
c094b5acab4e
			for e in entrylist:
476
c094b5acab4e
				xhtml += "		<li><a href=\"#%s\">%s</a></li>\n" % ( str(e.path), e.name )
477
29c5326b470e
478
29c5326b470e
			xhtml += "	</ul>\n"
479
29c5326b470e
			xhtml += "\n"
480
29c5326b470e
481
6865ee763d14
		return xhtml
482
6865ee763d14
483
6865ee763d14
484
6865ee763d14
	def __generate_sidebar_fileinfo(self):
485
6865ee763d14
		"Generates file info for the sidebar"
486
6865ee763d14
487
6865ee763d14
		xhtml = ""
488
c094b5acab4e
		xhtml += "	<h2 style=\"margin-top: 0px;\"><img src=\"%s/sidebar/file.png\" class=\"icon\" alt=\"File info\" />File info</h2>\n" % IMAGEPATH
489
6865ee763d14
		xhtml += "\n"
490
e1117203c473
		xhtml += "	<h3>" + _('Created:') + "</h3>\n"
491
c094b5acab4e
		xhtml += "	<p>%s</p>\n" % time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
492
6865ee763d14
		xhtml += "\n"
493
e1117203c473
		xhtml += "	<h3>" + _('Revelation version:') + "</h3>\n"
494
c094b5acab4e
		xhtml += "	<p>%s</p>\n" % config.VERSION
495
29c5326b470e
		xhtml += "\n"
496
29c5326b470e
497
29c5326b470e
		return xhtml
498
29c5326b470e
499
29c5326b470e
500
6865ee763d14
	def __generate_sidebar_foldertree(self, entrystore, parent = None, depth = 0):
501
6865ee763d14
		"Generates a folder tree for the sidebar"
502
6865ee763d14
503
6865ee763d14
		tabs = "\t" * ((depth * 2) - 2)
504
6865ee763d14
		xhtml = ""
505
6865ee763d14
506
6865ee763d14
		if parent is None:
507
c094b5acab4e
			xhtml += "	<h2><img src=\"%s/sidebar/foldertree.png\" class=\"icon\" alt=\"Folder tree\" />Folder tree</h2>\n" % IMAGEPATH
508
6865ee763d14
			xhtml += "\n"
509
6865ee763d14
510
6865ee763d14
		# fetch folder list
511
6865ee763d14
		folders = []
512
6865ee763d14
		for i in range(entrystore.iter_n_children(parent)):
513
6865ee763d14
			iter = entrystore.iter_nth_child(parent, i)
514
c094b5acab4e
			e = entrystore.get_entry(iter)
515
c094b5acab4e
			e.path = self.__get_entryid(entrystore, iter)
516
c094b5acab4e
			e.iter = iter
517
6865ee763d14
518
c094b5acab4e
			if type(e) == entry.FolderEntry:
519
c094b5acab4e
				folders.append(e)
520
6865ee763d14
521
6865ee763d14
522
6865ee763d14
		# generate xhtml
523
6865ee763d14
		if len(folders) > 0:
524
6865ee763d14
			xhtml += tabs + "<ul>\n"
525
6865ee763d14
526
c094b5acab4e
			for e in folders:
527
c094b5acab4e
				childxhtml = self.__generate_sidebar_foldertree(entrystore, e.iter, depth + 1)
528
6865ee763d14
529
6865ee763d14
				if childxhtml != "":
530
6865ee763d14
					xhtml += tabs + "	<li>\n"
531
c094b5acab4e
					xhtml += tabs + "		<a href=\"#%s\">%s</a>\n" % ( str(e.path), e.name )
532
6865ee763d14
					xhtml += childxhtml
533
6865ee763d14
					xhtml += tabs + "	</li>\n"
534
6865ee763d14
535
6865ee763d14
				else:
536
c094b5acab4e
					xhtml += tabs + "	<li><a href=\"#%s\">%s</a></li>\n" % ( str(e.path), e.name )
537
6865ee763d14
538
6865ee763d14
			xhtml += tabs + "</ul>\n"
539
6865ee763d14
540
6865ee763d14
541
6865ee763d14
		return xhtml
542
6865ee763d14
543
6865ee763d14
544
6865ee763d14
	def __get_entryid(self, entrystore, iter):
545
6865ee763d14
		"Returns an entry id for an iter"
546
6865ee763d14
547
6865ee763d14
		path = "entry-"
548
c094b5acab4e
549
6865ee763d14
		for i in entrystore.get_path(iter):
550
6865ee763d14
			path += str(i) + "-"
551
c094b5acab4e
552
6865ee763d14
		path = path[:-1]
553
6865ee763d14
554
6865ee763d14
		return path
555
6865ee763d14
556
6865ee763d14
557
29c5326b470e
	def export_data(self, entrystore, password = None):
558
29c5326b470e
		"Exports data from an entrystore into a XHTML document"
559
29c5326b470e
560
29c5326b470e
		xhtml = ""
561
29c5326b470e
		xhtml += self.__generate_header()
562
29c5326b470e
		xhtml += self.__generate_sidebar(entrystore)
563
6865ee763d14
		xhtml += self.__generate_entry(entrystore, None)
564
29c5326b470e
		xhtml += self.__generate_footer()
565
29c5326b470e
566
29c5326b470e
		return xhtml
567
29c5326b470e