Merge branch 'horizontals'
[swftools.git] / wx / lib / document.py
1 #!/usr/bin/env python
2 # -*- coding: UTF-8 -*-
3 #
4 # gpdf2swf.py
5 # graphical user interface for pdf2swf
6 #
7 # Part of the swftools package.
8
9 # Copyright (c) 2008,2009 Matthias Kramm <kramm@quiss.org> 
10 #
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 2 of the License, or
14 # (at your option) any later version.
15 #
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 # GNU General Public License for more details.
20 #
21 # You should have received a copy of the GNU General Public License
22 # along with this program; if not, write to the Free Software
23 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
24
25 from __future__ import division
26 import os
27 import time
28 import thread
29 import gfx
30 import wx
31 from wx.lib.pubsub import Publisher
32 from subprocess import Popen, PIPE
33
34 class _SaveSWFThread:
35     def __init__(self, pdffilename, filename, one_page_per_file, doc, pages, options):
36         #self.__doc = doc
37         self.__filename = filename
38         self.__pdffilename = pdffilename
39         self.__pages = pages or range(1, doc.pages+1)
40         self.__options = options
41         self.__one_page_per_file = one_page_per_file
42
43     def Start(self):
44         self.__keep_running = self.__running = True
45         thread.start_new_thread(self.Run, ())
46         #self.Run()
47
48     def Stop(self):
49         self.__keep_running = False
50
51     def IsRunning(self):
52         return self.__running
53
54     def Run(self):
55         swf = gfx.SWF()
56
57         try:
58             plugin = self.__options.viewers.init(swf, self.__filename)
59         except Exception, e:
60             wx.CallAfter(Publisher.sendMessage, "PLUGIN_ERROR")
61             self.__running = False
62             return
63
64         if self.__one_page_per_file and not plugin.one_page_per_file:
65             wx.CallAfter(Publisher.sendMessage,
66                          "PLUGIN_ONE_PAGE_PER_FILE_NOT_SUPPORTED",
67                          {'plugin': plugin,})
68             self.__running = False
69             return
70
71         pages = len(self.__pages)
72         wx.CallAfter(Publisher.sendMessage, "SWF_BEGIN_SAVE",
73                                             {'pages': pages,})
74
75         time.sleep(0.05)
76
77         self.setparameters(gfx)
78         self.__doc = gfx.open("pdf", self.__pdffilename)
79
80         self.setparameters(swf)
81
82         try:
83             plugin.before_render()
84         except Exception, e:
85             wx.CallAfter(Publisher.sendMessage, "PLUGIN_ERROR")
86             self.__running = False
87             return
88
89         for pagenr in self.__pages:
90             page = self.__doc.getPage(pagenr)
91             swf.startpage(page.width, page.height)
92             page.render(swf)
93             swf.endpage()
94             wx.CallAfter(Publisher.sendMessage, "SWF_PAGE_SAVED",
95                                                 {'pagenr': pagenr,
96                                                  'pages': pages,})
97             time.sleep(0.05)
98
99             if self.__one_page_per_file:
100                 form = '.%%0%dd.swf' % len(str(len(self.__pages)))
101                 filename = self.__filename.replace('.swf', form % pagenr)
102                 swf.save(filename)
103                 swf = gfx.SWF()
104
105                 try:
106                     plugin = self.__options.viewers.init(swf, self.__filename)
107                 except Exception, e:
108                     wx.CallAfter(Publisher.sendMessage, "PLUGIN_ERROR")
109                     self.__running = False
110                     return
111
112                 self.setparameters(swf)
113
114             if not self.__keep_running:
115                 break
116         else:
117             # This will not run if we break the for loop
118             if not self.__one_page_per_file:
119                 try:
120                     plugin.before_save(page)
121                 except Exception, e:
122                     wx.CallAfter(Publisher.sendMessage, "PLUGIN_ERROR")
123                     self.__running = False
124                     return
125                 swf.save(self.__filename)
126                 try:
127                     plugin.after_save(page)
128                 except Exception, e:
129                     wx.CallAfter(Publisher.sendMessage, "PLUGIN_ERROR")
130                     self.__running = False
131                     return
132
133         # No need. But to be sure that it's clean up
134         # as soon as possible
135         del swf
136
137         wx.CallAfter(Publisher.sendMessage, "SWF_FILE_SAVED")
138         time.sleep(0.05)
139
140         self.__running = False
141
142     def setparameters(self, swf):
143         #print "driver", swf
144         for opt in self.__options.quality:
145             if type(opt.name) in (tuple, list):
146                 for name, value in (
147                     # Example to better understand the list comprehension:
148                     # opt.name = ['a', 'b', 'c']
149                     # opt.value = [1, 2, 3]
150                     # zip them = [('a',1), ('b', 2), ('c', 3)]
151                     # pair will be in this example ('a', 1) due to
152                     # the if pair[1] condition
153                     pair for pair in zip(opt.name, opt.value) #if pair[1] == 1
154                 ):
155                     #print "1.swf.setparameter(%s, %s)" % (name, value)
156                     swf.setparameter(str(name), str(value))
157             else:
158                 #print "2.swf.setparameter(%s, %s)" % (opt.name, str(opt.value))
159                 swf.setparameter(opt.name, str(opt.value))
160
161         #swf.setparameter('noclips', '1')
162         #swf.setparameter('reordertags', '1')
163         #swf.setparameter('animate', '1')
164
165 PDF_INFO = [
166     "title", "subject", "keywords", "author",
167     "creator", "producer", "creationdate", "moddate",
168     "linearized", "tagged", "encrypted", "oktoprint",
169     "oktocopy", "oktochange", "oktoaddnotes", "version",
170 ]
171
172 class Document(object):
173     def __init__(self):
174         self.__page = None
175         self.__zoom = 1
176         self.__lastsavefile = "output.swf"
177         self.__pdffilename = None
178         self.__preview_parameters = []
179
180     def __getattr__(self, name):
181         if name in PDF_INFO:
182             return self.__pdf.getInfo(name) or "n/a"
183         raise AttributeError, name
184
185     def filename(self):
186         return self.__pdffilename
187     filename = property(filename)
188
189     def __get_lastsavefile(self):
190         return self.__lastsavefile
191     def __set_lastsavefile(self, lastsavefile):
192         self.__lastsavefile = lastsavefile
193     lastsavefile = property(__get_lastsavefile, __set_lastsavefile)
194
195     def __SwapExtension(self, filename, newext):
196         basename, ext = os.path.splitext(filename)
197         return "%s.%s" % (basename, newext)
198
199     def __Reload(self):
200         Publisher.sendMessage("PAGE_CHANGED",
201                               {'page': self.__page,
202                                'width': int(self.__page.width * self.__zoom),
203                                'height': int(self.__page.height * self.__zoom)})
204
205     def __get_preview_parameters(self):
206         return self.__preview_parameters
207     def __set_preview_parameters(self, parameters):
208         self.__preview_parameters = parameters
209     preview_parameters = property(__get_preview_parameters,
210                                   __set_preview_parameters)
211
212     def Load(self, filename):
213         self.__lastsavefile = self.__SwapExtension(filename, "swf")
214         self.__pdffilename = filename
215
216         #print 'Load',self.__preview_parameters
217         for parameter, value in self.__preview_parameters:
218             gfx.setparameter(parameter, value)
219
220         try:
221             self.__pdf = gfx.open("pdf", filename)
222         except:
223             Publisher.sendMessage("FILE_NOT_LOADED", {'filename': filename})
224         else:
225             Publisher.sendMessage("FILE_LOADED", {'pages': self.__pdf.pages})
226
227     def ChangePage(self, pagenr=1, size=None):
228         self.__page = page = self.__pdf.getPage(pagenr)
229         self.__Reload()
230
231     def Fit(self, size):
232         w = size[0] / self.__page.width
233         h = size[1] / self.__page.height
234         self.__zoom = min(w, h)
235         self.__Reload()
236
237     def Zoom(self, zoom):
238         if zoom == 1:
239             self.__zoom = 1
240         else:
241             self.__zoom += zoom
242         self.__Reload()
243
244     def GetThumbnails(self):
245         for pagenr in range(1, self.__pdf.pages + 1):
246             page = self.__pdf.getPage(pagenr)
247             yield page
248
249     def SaveSWF(self, filename, one_page_per_file, pages, options):
250         self.__lastsavefile = filename
251         t = _SaveSWFThread(self.__pdffilename, filename, one_page_per_file, self.__pdf, pages, options)
252         t.Start()
253         return t
254         
255