comparison inkscape/firefox/MBServer.py @ 288:d5327265da1e

Revert the firefox integration to 276
author wycc
date Sat, 31 Jan 2009 17:35:27 +0800
parents
children 63aaf96209cd
comparison
equal deleted inserted replaced
287:5c066380a84e 288:d5327265da1e
1 #!/usr/bin/python
2 import inkex
3 import pygtk
4 import gtk
5 from copy import deepcopy
6 from lxml import etree
7 from twisted.web import server, resource,soap
8 from twisted.internet import reactor
9 import traceback
10
11 import random
12
13 # Please refer to http://www.assembla.com/wiki/show/MadButterfly/Inkscape_extention for the designed document.
14
15
16 # Algorithm:
17 #
18 # We will parse the first two level of the SVG DOM. collect a table of layer and scene.
19 # 1. Collect the layer table which will be displayed as the first column of the grid.
20 # 2. Get the maximum scene number. This will decide the size of the grid.
21 # 3. When F6 is pressed, we will check if this scene has been defined. This can be done by scan all second level group and check if the current scene number is within the
22 # range specified by scene field. The function IsSceneDefined(scene) can be used for this purpose.
23 # 4. If this is a new scene, we will append a new group which duplication the content of the last scene in the same group. The scene field will contain the number from the
24 # last scene number of the last scene to the current scenen number. For example, if the last scene is from 4-7 and the new scene is 10, we will set the scene field as
25 # "8-10".
26 # 5. If this scene are filled screne, we will split the existing scene into two scenes with the same content.
27
28 class Layer:
29 def __init__(self,node):
30 self.scene = []
31 self.node = node
32 self.nodes=[]
33 class Scene:
34 def __init__(self, node, start,end):
35 self.node = node
36 self.start = int(start)
37 self.end = int(end)
38
39
40 class MBScene(inkex.Effect):
41 def confirm(self,msg):
42 vbox = gtk.VBox()
43 vbox.pack_start(gtk.Label(msg))
44 self.button = gtk.Button('OK')
45 vbox.pack_start(self.button)
46 self.button.connect("clicked", self.onQuit)
47 self.window.add(vbox)
48 def dumpattr(self,n):
49 s = ""
50 for a,v in n.attrib.items():
51 s = s + ("%s=%s" % (a,v))
52 return s
53
54 def dump(self,node,l=0):
55 print " " * l*2,"<", node.tag, self.dumpattr(node),">"
56 for n in node:
57 self.dump(n,l+1)
58 print " " * l * 2,"/>"
59 def parseMetadata(self,node):
60 self.current = 1
61 for n in node:
62 if n.tag == '{http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd}scenes':
63 self.scenemap={}
64 cur = int(n.get("current"))
65 self.current = cur
66
67 for s in n:
68 if s.tag == '{http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd}scene':
69 try:
70 start = int(s.get("start"))
71 except:
72 continue
73 try:
74 end = s.get("end")
75 if end == None:
76 end = start
77 except:
78 end = start
79 link = s.get("ref")
80 self.scenemap[link] = [int(start),int(end)]
81 if cur >= start and cur <= end:
82 self.currentscene = link
83
84 pass
85 pass
86 pass
87 pass
88
89
90 def parseScene(self):
91 """
92 In this function, we will collect all items for the current scene and then relocate them back to the appropriate scene object.
93 """
94 self.layer = []
95 self.scenemap = None
96 for node in self.document.getroot():
97 if node.tag == '{http://www.w3.org/2000/svg}metadata':
98 self.parseMetadata(node)
99 elif node.tag == '{http://www.w3.org/2000/svg}g':
100 oldscene = None
101 #print layer.attrib.get("id")
102 lyobj = Layer(node)
103 self.layer.append(lyobj)
104 lyobj.current_scene = []
105 for scene in node:
106 if scene.tag == '{http://www.w3.org/2000/svg}g':
107 try:
108 scmap = self.scenemap[scene.get("id")]
109 if scmap == None:
110 lyobj.current_scene.append(scene)
111 continue
112 if self.current <= scmap[1] and self.current >= scmap[0]:
113 oldscene = scene
114 except:
115 lyobj.current_scene.append(scene)
116 continue
117
118 lyobj.scene.append(Scene(scene,scmap[0],scmap[1]))
119 else:
120 lyobj.current_scene.append(scene)
121 pass
122 pass
123
124 if oldscene != None:
125 # Put the objects back to the current scene
126 for o in lyobj.current_scene:
127 #print o.tag
128 oldscene.append(o)
129 pass
130 pass
131 pass
132 pass
133
134 self.collectID()
135 #self.dumpID()
136 def collectID(self):
137 self.ID = {}
138 root = self.document.getroot()
139 for n in root:
140 self.collectID_recursive(n)
141 def collectID_recursive(self,node):
142 self.ID[node.get("id")] = 1
143 for n in node:
144 self.collectID_recursive(n)
145 def newID(self):
146 while True:
147 n = 's%d' % int(random.random()*10000)
148 #print "try %s" % n
149 if self.ID.has_key(n) == False:
150 return n
151 def dumpID(self):
152 for a,v in self.ID.items():
153 print a
154
155
156 def getLayer(self, layer):
157 for l in self.layer:
158 if l.node.attrib.get("id") == layer:
159 return l
160 return None
161
162
163 def insertKeyScene(self,layer,nth):
164 """
165 Insert a new key scene into the stage. If the nth is always a key scene, we will return without changing anything.
166 If the nth is a filled scene, we will break the original scene into two parts. If the nth is out of any scene, we will
167 append a new scene.
168
169 """
170 if layer == None: return
171
172 # Check if the nth is in the middle of any scene
173 for i in range(0,len(layer.scene)):
174 s = layer.scene[i]
175 if nth >= s.start and nth <= s.end:
176 if nth == s.start: return
177 newscene = Scene(deepcopy(s.node),nth,s.end)
178 newscene.node.set("id", self.newID())
179 layer.scene.insert(i+1,newscene)
180 layer.scene[i].end = nth-1
181 return
182 if len(layer.scene) > 0:
183 # extend the last scene befor eit automatically
184 last = nth
185 lastscene = None
186 # Find the last scene before it
187 for s in layer.scene:
188 if s.end < nth and last < s.end:
189 last = s.end
190 lastscene = s
191 if lastscene == None:
192 node = etree.Element('{http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd}scene')
193 node.set("id", self.newID())
194 newscene = Scene(node,nth,nth)
195 else:
196 lastscene.end = nth-1
197 newscene = Scene(deepcopy(lastscene.node),nth,nth)
198 newscene.node.set("id",self.newID())
199 layer.scene.append(newscene)
200 else:
201 # This is the first scene in the layer
202 node = etree.Element('{http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd}scene')
203 node.set("id", self.newID())
204 newscene = Scene(node,nth,nth)
205 layer.scene.append(newscene)
206
207
208 def deleteScene(self,layer,nth):
209 for i in range(0,len(layer.scene)):
210 s = layer.scene[i]
211 if nth == s.start:
212 if i == 0:
213 layer.scene.remove(s)
214 else:
215 if s.start == layer.scene[i-1].end+1:
216 # If the start of the delete scene segment is the end of the last scene segmenet, convert all scenes in the deleted
217 # scene segmenet to the last one
218 layer.scene[i-1].end = s.end
219 layer.scene.remove(s)
220 else:
221 # Convert all scenes into empty cell
222 layer.scene.remove(s)
223
224 return
225 pass
226 pass
227
228
229 def extendScene(self,layer,nth):
230 if layer == None: return
231
232 for i in range(0,len(layer.scene)-1):
233 s = layer.scene[i]
234 if nth >= layer.scene[i].start and nth <= layer.scene[i].end:
235 return
236
237 for i in range(0,len(layer.scene)-1):
238 s = layer.scene[i]
239 if nth >= layer.scene[i].start and nth < layer.scene[i+1].start:
240 layer.scene[i].end = nth
241 return
242 if len(layer.scene) > 0 and nth > layer.scene[len(layer.scene)-1].end:
243 layer.scene[len(layer.scene)-1].end = nth
244
245 def setCurrentScene(self,nth):
246 self.current = nth
247 for layer in self.layer:
248 for s in layer.scene:
249 if nth >= s.start and nth <= s.end:
250 s.node.set("style","")
251 #print "Put the elemenets out"
252 layer.nodes = []
253
254 for o in s.node:
255 #print " ",o.tag
256 layer.nodes.append(o)
257 for o in s.node:
258 s.node.remove(o)
259 else:
260 s.node.set("style","display:none")
261 def generate(self):
262 newdoc = deepcopy(self.document)
263 root = newdoc.getroot()
264 has_scene = False
265 for n in root:
266 if n.tag == '{http://www.w3.org/2000/svg}metadata':
267 for nn in n:
268 if nn.tag == '{http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd}scenes':
269 nn.clear()
270 nn.set("current", "%d" % self.current)
271 scenes = []
272 for l in self.layer:
273 for s in l.scene:
274 id = s.node.get("id")
275 scene = etree.Element('{http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd}scene')
276 scene.set("ref", id)
277 if s.start == s.end:
278 scene.set("start", "%d" % s.start)
279 else:
280 scene.set("start", "%d" % s.start)
281 scene.set("end", "%d" % s.end)
282
283 scenes.append(scene)
284 for s in scenes:
285 nn.append(s)
286 has_scene = True
287 if has_scene == False:
288 scenes = etree.Element('{http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd}scenes')
289 scenes.set("current","%d" % self.current)
290 for l in self.layer:
291 for s in l.scene:
292 scene = etree.Element('{http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd}scene')
293 scene.set("ref", s.node.get("id"))
294 if s.start == s.end:
295 scene.set("start", "%d" % s.start)
296 else:
297 scene.set("start", "%d" % s.start)
298 scene.set("end", "%d" % s.end)
299 scenes.append(scene)
300 n.append(scenes)
301 if n.tag == '{http://www.w3.org/2000/svg}g':
302 root.remove(n)
303
304 for l in self.layer:
305 # Duplicate all attribute of the layer
306 lnode = etree.Element("{http://www.w3.org/2000/svg}g")
307 for a,v in l.node.attrib.items():
308 lnode.set(a,v)
309 for n in l.nodes:
310 lnode.append(n)
311 root.append(lnode)
312 for s in l.scene:
313 snode = etree.Element("{http://www.w3.org/2000/svg}g")
314 for a,v in s.node.attrib.items():
315 snode.set(a,v)
316 for n in s.node:
317 snode.append(deepcopy(n))
318 lnode.append(snode)
319 self.document = newdoc
320 def newCell(self,file):
321 img = gtk.Image()
322 img.set_from_file(file)
323 btn = gtk.EventBox()
324 btn.add(img)
325 btn.connect("button_press_event", self.cellSelect)
326 btn.modify_bg(gtk.STATE_NORMAL, btn.get_colormap().alloc_color("gray"))
327 return btn
328 def showGrid(self):
329 max = 0
330 for layer in self.layer:
331 for s in layer.scene:
332 if s.end > max:
333 max = s.end
334 max = 50
335
336 self.grid = gtk.Table(len(self.layer)+1, 50)
337 self.scrollwin = gtk.ScrolledWindow()
338 self.scrollwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
339 self.scrollwin.add_with_viewport(self.grid)
340 for i in range(1,max):
341 self.grid.attach(gtk.Label('%d'% i), i,i+1,0,1,0,0,0,0)
342 for i in range(1,len(self.layer)+1):
343 l = self.layer[i-1]
344 self.grid.attach(gtk.Label(l.node.get('{http://www.inkscape.org/namespaces/inkscape}label')), 0, 1, i, i+1,0,0,10,0)
345 for s in l.scene:
346 btn = self.newCell('start.png')
347 btn.nScene = s.start
348 btn.layer = l.node.get('id')
349 btn.nLayer = i
350
351 self.grid.attach(btn, s.start, s.start+1, i, i+1,0,0,0,0)
352 for j in range(s.start+1,s.end+1):
353 btn = self.newCell('fill.png')
354 self.grid.attach(btn, j, j+1, i , i+1,0,0,0,0)
355 btn.modify_bg(gtk.STATE_NORMAL, btn.get_colormap().alloc_color("gray"))
356 btn.nScene = j
357 btn.layer = l.node.get('id')
358 btn.nLayer = i
359 if len(l.scene) == 0:
360 start = 0
361 else:
362 start = l.scene[len(l.scene)-1].end
363 for j in range(start,max):
364 btn = self.newCell('empty.png')
365 self.grid.attach(btn, j+1, j+2,i,i+1,0,0,0,0)
366 btn.modify_bg(gtk.STATE_NORMAL, btn.get_colormap().alloc_color("gray"))
367 btn.nScene = j+1
368 btn.layer = l.node.get('id')
369 btn.nLayer = i
370 self.last_cell = None
371 def cellSelect(self, cell, data):
372 if self.last_cell:
373 self.last_cell.modify_bg(gtk.STATE_NORMAL, self.last_cell.get_colormap().alloc_color("gray"))
374
375 self.last_cell = cell
376 cell.modify_bg(gtk.STATE_NORMAL, cell.get_colormap().alloc_color("green"))
377
378 def doEditScene(self,w):
379 self.setCurrentScene(self.last_cell.nScene)
380 self.generate()
381 gtk.main_quit()
382
383 def doRemoveScene(self,w):
384 self.removeKeyScene()
385 self.grid.show_all()
386 self.generate()
387 def addButtons(self,hbox):
388 btn = gtk.Button('Edit')
389 btn.connect('clicked', self.doEditScene)
390 hbox.pack_start(btn)
391 btn = gtk.Button('Insert Key')
392 btn.connect('clicked',self.doInsertKeyScene)
393 hbox.pack_start(btn)
394 btn=gtk.Button('Remove Key')
395 btn.connect('clicked', self.doRemoveScene)
396 hbox.pack_start(btn)
397 btn=gtk.Button('Extend scene')
398 btn.connect('clicked', self.doExtendScene)
399 hbox.pack_start(btn)
400 def onQuit(self, event):
401 self.OK = False
402 gtk.main_quit()
403 def onOK(self,event):
404 self.OK = True
405 gtk.main_quit()
406
407 def onConfirmDelete(self):
408 if self.scenemap == None:
409 vbox = gtk.VBox()
410 vbox.pack_start(gtk.Label('Convert the SVG into a MadButterfly SVG file. All current element will be delted'))
411 hbox = gtk.HBox()
412 self.button = gtk.Button('OK')
413 hbox.pack_start(self.button)
414 self.button.connect('clicked', self.onOK)
415 self.button = gtk.Button('Cancel')
416 hbox.pack_start(self.button)
417 self.button.connect("clicked", self.onQuit)
418 vbox.pack_start(hbox)
419 self.window.add(vbox)
420 self.window.show_all()
421 gtk.main()
422 self.window.remove(vbox)
423
424 def start_server(self):
425 root = MB()
426 root.target = self
427 site = server.Site(root)
428 reactor.listenTCP(8080, site)
429 reactor.run()
430
431
432 def effect(self):
433 self.OK = False
434 self.parseScene()
435 self.start_server()
436 self.generate()
437
438 class MB(soap.SOAPPublisher):
439 """
440 SOAP server for inkscape extension.
441 """
442
443 def soap_PUBLISH(self):
444 reactor.callLater(1,self.quit)
445 return "OK"
446 def quit(self):
447 reactor.stop()
448 def soap_SCENE(self,n):
449 self.target.setCurrentScene(int(n))
450 return "OK"
451 def soap_INSERTKEY(self,layer,n):
452 try:
453 layer = self.target.getLayer(layer)
454 self.target.insertKeyScene(layer,int(n))
455 return "OK"
456 except:
457 return traceback.format_exc()
458 def soap_EXTENDSCENE(self,layer,n):
459 try:
460 layer = self.target.getLayer(layer)
461 self.target.extendScene(layer,int(n))
462 return "OK"
463 except:
464 return traceback.format_exc()
465 def soap_DELETESCENE(self,layer,n):
466 try:
467 layer = self.target.getLayer(layer)
468 self.target.deleteScene(layer,int(n))
469 return "OK"
470 except:
471 return traceback.format_exc()
472 def soap_GETDOC(self):
473 try:
474 self.target.generate()
475 return etree.tostring(self.target.document)
476 except:
477 return traceback.format_exc()
478 import os
479 os.chdir('/usr/share/inkscape/extensions')
480
481 A = MBScene()
482 A.affect()
483
484