Merge lp:~trb143/openlp/servicing into lp:openlp

Proposed by Tim Bentley
Status: Merged
Merged at revision: not available
Proposed branch: lp:~trb143/openlp/servicing
Merge into: lp:openlp
Diff against target: None lines
To merge this branch: bzr merge lp:~trb143/openlp/servicing
Reviewer Review Type Date Requested Status
Tim Bentley Approve
Raoul Snyman Approve
Martin Thompson (community) Approve
Review via email: mp+6659@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Tim Bentley (trb143) wrote :

 460. By Tim Bentley 3 minutes ago

    Corrections to Renderer to handle slides not lines
    Fixes to Bibleplugin to renderer multiple verses per slide
    Pass Bible Theme to RenderManager
459. By Tim Bentley 7 hours ago

    hook up themes to combo boxes
458. By Tim Bentley 7 hours ago

    Rendering fixes
457. By Tim Bentley 19 hours ago

    Add Images to the themes
    Fix MainDisplay to record change of frame when blanked out.
456. By Tim Bentley 22 hours ago

    More code cleanups
455. By Tim Bentley on 2009-05-16

    Close display window on exit
    Performance improvements in renderer
    Performance improvements in Thememanager
    Fix review comments from last few reviews
    Add new media types to media plugin_helpers
    Code format cleanups

Revision history for this message
Martin Thompson (mjthompson) wrote :

In render.scale_bg_image(), I have a feeling all that messing about (my wx legacy code - sorry!) keeping the aspect ratio correct is now unnecessary, just the call to image.scaled with the KeepAspectRatio param will do it if the neww and newh are just set to the size of the new screen to fit to...

In render_single_line() - the 't' variable has been replaced by self._theme - this may have a significant -ve performance impact (I should've commented this when I wrote it :) -- effectively "t" acts as a cache to the member variable, which IIRC improved the render performance. However, given my own mantra of nor optimising too early, it's probably worth changing to the more readable version, until it's proven!

I can see I'll have to revisit bits to make the unit tests pass again :)

I think snoop_image would be better being passed a list of images? And it's duplicated - better to have it in /lib/ ?

Line 1432 of the diff - OnMediaNewClick - the file filters should be
u'Videos (*.avi *.mpeg);;Audio (*.mp3 *.ogg *.wma);;All files (*)')

review: Approve
Revision history for this message
Raoul Snyman (raoul-snyman) wrote :

I'm liking the correct coding style!

review: Approve
Revision history for this message
Tim Bentley (trb143) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/core/lib/event.py'
2--- openlp/core/lib/event.py 2009-05-12 21:06:35 +0000
3+++ openlp/core/lib/event.py 2009-05-16 16:38:03 +0000
4@@ -54,6 +54,3 @@
5 def __init__(self, event_type=EventType.Default, payload=None):
6 self.event_type = event_type
7 self.payload = payload
8-
9- def get_type(self):
10- return self.event_type
11
12=== modified file 'openlp/core/lib/eventmanager.py'
13--- openlp/core/lib/eventmanager.py 2009-04-06 18:45:45 +0000
14+++ openlp/core/lib/eventmanager.py 2009-05-16 16:38:03 +0000
15@@ -40,7 +40,7 @@
16 self.endpoints.append(plugin)
17
18 def post_event(self, event):
19- log.debug(u'post event called for event %s', event.get_type)
20+ log.debug(u'post event called for event %s', event.event_type)
21 for point in self.endpoints:
22 point.handle_event(event)
23
24
25=== modified file 'openlp/core/lib/renderer.py'
26--- openlp/core/lib/renderer.py 2009-05-11 05:09:43 +0000
27+++ openlp/core/lib/renderer.py 2009-05-17 15:24:02 +0000
28@@ -41,143 +41,160 @@
29 tell it to render a particular screenfull with render_screen(n)
30
31 """
32- def __init__(self, path=None):
33- self._rect=None
34- self._debug=0
35- self.words=None
36+ def __init__(self):
37+ self._rect = None
38+ self._debug = 0
39+ self.words = None
40 self._right_margin = 64 # the amount of right indent
41- self._shadow_offset=5
42- self._outline_offset=2
43- self._theme=None
44- self._bg_image_filename=None
45- self._paint=None
46- self._path = path
47- self.img = None
48+ self._shadow_offset = 5
49+ self._outline_offset = 2
50+ self.theme_name = None
51+ self._theme = None
52+ self._bg_image_filename = None
53+ self._frame = None
54+ self._bg_frame = None
55+ self.bg_image = None
56
57 def set_debug(self, debug):
58 self._debug=debug
59
60 def set_theme(self, theme):
61- self._theme=theme
62+ """
63+ External API to pass in the theme to be used
64+ """
65+ log.debug(u'set theme')
66+ self._theme = theme
67+ self._bg_frame = None
68+ self.theme_name = theme.theme_name
69 if theme.background_type == u'image':
70- if self._path is not None:
71+ if theme.background_filename is not None:
72 self.set_bg_image(theme.background_filename)
73
74 def set_bg_image(self, filename):
75 log.debug(u'set bg image %s', filename)
76-
77- self._bg_image_filename=os.path.join(self._path, self._theme.theme_name, filename)
78- print self._bg_image_filename
79- if self._paint is not None:
80+ self._bg_image_filename = str(filename)
81+ if self._frame is not None:
82 self.scale_bg_image()
83
84 def scale_bg_image(self):
85- assert self._paint
86- i=QtGui.QImage(self._bg_image_filename)
87+ assert self._frame
88+ image = QtGui.QImage(self._bg_image_filename)
89 # rescale and offset
90- imw=i.width()
91- imh=i.height()
92- print imw, imh
93- dcw=self._paint.width()+1
94- dch=self._paint.height()
95- imratio=imw/float(imh)
96- dcratio=dcw/float(dch)
97+ imw = image.width()
98+ imh = image.height()
99+ dcw = self._frame.width()+1
100+ dch = self._frame.height()
101+ imratio = imw/float(imh)
102+ dcratio = dcw/float(dch)
103 log.debug(u'Image scaling params %s %s %s %s %s %s', imw, imh, imratio, dcw, dch, dcratio)
104 if imratio > dcratio:
105- scale=dcw/float(imw)
106+ scale = dcw/float(imw)
107 elif imratio < dcratio:
108- scale=dch/float(imh)
109+ scale = dch/float(imh)
110 else:
111- scale=dcw/float(imw) # either will do
112- neww=int(round(imw*scale))
113- newh=int(round(imh*scale))
114+ scale = dcw/float(imw) # either will do
115+ neww = int(round(imw*scale))
116+ newh = int(round(imh*scale))
117 self.background_offsetx=(dcw-neww)/2
118 self.background_offsety=(dch-newh)/2
119- self.img=QtGui.QPixmap.fromImage(i.scaled(QtCore.QSize(neww, newh), Qt.Qt.KeepAspectRatio))
120+ self.bg_image=QtGui.QPixmap.fromImage(image.scaled(QtCore.QSize(neww, newh), Qt.Qt.KeepAspectRatio))
121
122- def set_paint_dest(self, p):
123- log.debug(u'set paint dest (frame) w %d h %d',p.width(), p.height())
124- self._paint=p
125+ def set_frame_dest(self, frame_width, frame_height, preview=False):
126+ """
127+ External API to pass the frame size to be painted
128+ """
129+ if preview == True:
130+ self._bg_frame = None
131+ log.debug(u'set frame dest (frame) w %d h %d',frame_width, frame_height)
132+ self._frame = QtGui.QPixmap(frame_width, frame_height)
133 if self._bg_image_filename is not None:
134 self.scale_bg_image()
135+ if self._bg_frame is None:
136+ self._render_background()
137
138 def format_slide(self, words, footer):
139+ """
140+ External API to sort out the text to pe placed on the frame
141+ """
142 log.debug(u'format_slide %s', words)
143- verses=[]
144- verses_text = words.splitlines()
145- for v in verses_text:
146- lines=v.split(u'\n')
147+ verses = []
148+ verses_text = words.split(u'\n\n')
149+ for verse in verses_text:
150+ lines = verse.split(u'\n')
151 verses.append(self.split_set_of_lines(lines, footer)[0])
152 self.words = verses
153- verses_text=[]
154+ verses_text = []
155 for v in verses:
156 verses_text.append(u'\n'.join(v).lstrip()) # remove first \n
157 return verses_text
158
159 def render_screen(self, screennum):
160 log.debug(u'render screen\n %s %s ', screennum, self.words[screennum])
161- t=0.0
162- words=self.words[screennum]
163- retval=self._render_lines(words)
164+ t = 0.0
165+ words = self.words[screennum]
166+ retval = self._render_lines(words)
167 return retval
168
169 def set_text_rectangle(self, rect_main, rect_footer):
170 """ Sets the rectangle within which text should be rendered"""
171- self._rect=rect_main
172- self._rect_footer=rect_footer
173+ self._rect = rect_main
174+ self._rect_footer = rect_footer
175
176 def _render_background(self):
177+ """
178+ Generate a background frame to the same size as the frame to be used
179+ Results cached for performance reasons.
180+ """
181 assert(self._theme)
182- assert(self._paint)
183+ self._bg_frame = QtGui.QPixmap(self._frame.width(), self._frame.height())
184 log.debug(u'render background %s ', self._theme.background_type)
185 bef = datetime.now()
186- p=QtGui.QPainter()
187- p.begin(self._paint)
188+ painter = QtGui.QPainter()
189+ painter.begin(self._bg_frame)
190 if self._theme.background_type == u'solid':
191- p.fillRect(self._paint.rect(), QtGui.QColor(self._theme.background_color))
192+ painter.fillRect(self._frame.rect(), QtGui.QColor(self._theme.background_color))
193 elif self._theme.background_type == u'gradient' : # gradient
194 gradient = None
195 if self._theme.background_direction == u'horizontal':
196- w = int(self._paint.width())/2
197- gradient = QtGui.QLinearGradient(w, 0, w, self._paint.height()) # vertical
198+ w = int(self._frame.width())/2
199+ gradient = QtGui.QLinearGradient(w, 0, w, self._frame.height()) # vertical
200 elif self._theme.background_direction == u'vertical':
201- h = int(self._paint.height())/2
202- gradient = QtGui.QLinearGradient(0, h, self._paint.width(), h) # Horizontal
203+ h = int(self._frame.height())/2
204+ gradient = QtGui.QLinearGradient(0, h, self._frame.width(), h) # Horizontal
205 else:
206- w = int(self._paint.width())/2
207- h = int(self._paint.height())/2
208+ w = int(self._frame.width())/2
209+ h = int(self._frame.height())/2
210 gradient = QtGui.QRadialGradient(w, h, w) # Circular
211
212 gradient.setColorAt(0, QtGui.QColor(self._theme.background_startColor))
213 gradient.setColorAt(1, QtGui.QColor(self._theme.background_endColor))
214
215- p.setBrush(QtGui.QBrush(gradient))
216+ painter.setBrush(QtGui.QBrush(gradient))
217 rectPath = QtGui.QPainterPath()
218
219- max_x = self._paint.width()
220- max_y = self._paint.height()
221+ max_x = self._frame.width()
222+ max_y = self._frame.height()
223 rectPath.moveTo(0, 0)
224 rectPath.lineTo(0, max_y)
225 rectPath.lineTo(max_x, max_y)
226 rectPath.lineTo(max_x, 0)
227
228 rectPath.closeSubpath()
229- p.drawPath(rectPath)
230+ painter.drawPath(rectPath)
231
232 elif self._theme.background_type== u'image': # image
233- r=self._paint.rect()
234+ r = self._frame.rect()
235 log.debug(u'Image size details %d %d %d %d ', r.x(), r.y(), r.width(),r.height())
236 #log.debug(u' Background Parameter %d ', self._theme.background_color1)
237 #if self._theme.background_color1 is not None:
238- # p.fillRect(self._paint.rect(), self._theme.background_borderColor)
239- if self.img is not None:
240- p.drawPixmap(self.background_offsetx,self.background_offsety, self.img)
241+ # p.fillRect(self._frame.rect(), self._theme.background_borderColor)
242+ if self.bg_image is not None:
243+ painter.drawPixmap(self.background_offsetx,self.background_offsety, self.bg_image)
244 else:
245- p.fillRect(self._paint.rect(), QtGui.QColor(u'#000000'))
246- p.end()
247+ painter.fillRect(self._frame.rect(), QtGui.QColor(u'#000000'))
248+ painter.end()
249 aft = datetime.now()
250 print "background time", bef, aft, aft-bef
251-
252 log.debug(u'render background finish')
253
254 def split_set_of_lines(self, lines, footer):
255@@ -186,71 +203,68 @@
256 - this is done by splitting at 1/2, 1/3 or 1/4 of the set
257 If it doesn't fit, even at this size, just split at each opportunity
258
259- We'll do this by getting the bounding box of each lline, and then summing them appropriately
260-
261+ We'll do this by getting the bounding box of each line, and then summing them appropriately
262 Returns a list of [lists of lines], one set for each screenful
263 """
264 log.debug(u'Split set of lines')
265- # Probably ought to save the rendering results to a pseudoDC for redrawing efficiency. But let's not optimse prematurely!
266-
267 bboxes = []
268 for line in lines:
269 bboxes.append(self._render_single_line(line, footer))
270- numlines=len(lines)
271- bottom=self._rect.bottom()
272+
273+ numlines = len(lines)
274+ bottom = self._rect.bottom()
275 for ratio in (numlines, numlines/2, numlines/3, numlines/4):
276- good=1
277- startline=0
278- endline=startline+ratio
279- while (endline<=numlines):
280- by=0
281+ good = 1
282+ startline = 0
283+ endline = startline + ratio
284+ while (endline <= numlines):
285+ by = 0
286 for (x, y) in bboxes[startline:endline]:
287- by+=y
288+ by += y
289 if by > bottom:
290 good=0
291 break
292- startline+=ratio
293- endline=startline+ratio
294- if good==1:
295+ startline += ratio
296+ endline = startline+ratio
297+ if good == 1:
298 break
299
300- retval=[]
301- numlines_per_page=ratio
302+ retval = []
303+ numlines_per_page = ratio
304 if good:
305- c=0
306- thislines=[]
307+ c = 0
308+ thislines = []
309 while c < numlines:
310 thislines.append(lines[c])
311- c+=1
312+ c += 1
313 if len(thislines) == numlines_per_page:
314 retval.append(thislines)
315- thislines=[]
316+ thislines = []
317 else:
318 # log.debug(u" "Just split where you can"
319- retval=[]
320- startline=0
321- endline=startline+1
322- while (endline<=numlines):
323- by=0
324+ retval = []
325+ startline = 0
326+ endline = startline+1
327+ while (endline <= numlines):
328+ by = 0
329 for (x, y) in bboxes[startline:endline]:
330- by+=y
331+ by += y
332 if by > bottom:
333 retval.append(lines[startline:endline-1])
334- startline=endline-1
335- endline=startline # gets incremented below
336- by=0
337- endline+=1
338-
339+ startline = endline-1
340+ endline = startline # gets incremented below
341+ by = 0
342+ endline += 1
343 return retval
344
345 def _correctAlignment(self, rect, bbox):
346- x=rect.left()
347+ x = rect.left()
348 if int(self._theme.display_verticalAlign) == 0: # top align
349 y = rect.top()
350 elif int(self._theme.display_verticalAlign) == 2: # bottom align
351- y=rect.bottom()-bbox.height()
352+ y = rect.bottom()-bbox.height()
353 elif int(self._theme.display_verticalAlign) == 1: # centre align
354- y=rect.top()+(rect.height()-bbox.height())/2
355+ y = rect.top()+(rect.height()-bbox.height())/2
356 else:
357 assert(0, u'Invalid value for theme.VerticalAlign:%s' % self._theme.display_verticalAlign)
358 return x, y
359@@ -259,51 +273,53 @@
360 """render a set of lines according to the theme, return bounding box"""
361 log.debug(u'render_lines - Start')
362
363- bbox=self._render_lines_unaligned(lines, False) # Main font
364+ bbox = self._render_lines_unaligned(lines, False) # Main font
365 if footer_lines is not None:
366- bbox1=self._render_lines_unaligned(footer_lines, True) # Footer Font
367-
368- # put stuff on background so need to reset before doing the job properly.
369- self._render_background()
370+ bbox1 = self._render_lines_unaligned(footer_lines, True) # Footer Font
371+
372+ self._frame = QtGui.QPixmap(self._bg_frame)
373+
374 x, y = self._correctAlignment(self._rect, bbox)
375- bbox=self._render_lines_unaligned(lines, False, (x, y))
376+ bbox = self._render_lines_unaligned(lines, False, (x, y))
377
378 if footer_lines is not None:
379- bbox=self._render_lines_unaligned(footer_lines, True, (self._rect_footer.left(), self._rect_footer.top()) )
380+ bbox = self._render_lines_unaligned(footer_lines, True, (self._rect_footer.left(), self._rect_footer.top()) )
381 log.debug(u'render_lines- Finish')
382- return bbox
383+
384+ return self._frame
385
386 def _render_lines_unaligned(self, lines, footer, tlcorner=(0,0)):
387-
388- """Given a list of lines to render, render each one in turn
389+ """
390+ Given a list of lines to render, render each one in turn
391 (using the _render_single_line fn - which may result in going
392 off the bottom) They are expected to be pre-arranged to less
393 than a screenful (eg. by using split_set_of_lines)
394
395- Returns the bounding box of the text as QRect"""
396+ Returns the bounding box of the text as QRect
397+ """
398 log.debug(u'render lines unaligned Start')
399- x, y=tlcorner
400- brx=x
401- bry=y
402+ x, y = tlcorner
403+ brx = x
404+ bry = y
405 for line in lines:
406 # render after current bottom, but at original left edge
407 # keep track of right edge to see which is biggest
408- (thisx, bry) = self._render_single_line(line, footer, (x,bry))
409+ (thisx, bry) = self._render_single_line(line, footer, (x , bry))
410 if (thisx > brx):
411- brx=thisx
412- retval=QtCore.QRect(x, y,brx-x, bry-y)
413+ brx = thisx
414+ retval = QtCore.QRect(x, y,brx-x, bry-y)
415 if self._debug:
416- p=QtGui.QPainter()
417- p.begin(self._paint)
418- p.setPen(QtGui.QPen(QtGui.QColor(0,0,255)))
419- p.drawRect(retval)
420- p.end()
421+ painter = QtGui.QPainter()
422+ painter.begin(self._frame)
423+ painter.setPen(QtGui.QPen(QtGui.QColor(0,0,255)))
424+ painter.drawRect(retval)
425+ painter.end()
426 log.debug(u'render lines unaligned Finish')
427 return retval
428
429 def _render_single_line(self, line, footer, tlcorner=(0,0)):
430-
431- """render a single line of words onto the DC, top left corner
432+ """
433+ Render a single line of words onto the DC, top left corner
434 specified.
435
436 If the line is too wide for the context, it wraps, but
437@@ -312,139 +328,147 @@
438 Returns the bottom-right corner (of what was rendered) as a tuple(x, y).
439 """
440 log.debug(u'Render single line %s @ %s '%( line, tlcorner))
441- x, y=tlcorner
442+ x, y = tlcorner
443 # We draw the text to see how big it is and then iterate to make it fit
444 # when we line wrap we do in in the "lyrics" style, so the second line is
445 # right aligned with a "hanging indent"
446-
447- # get the words
448-# log.debug(u" "Getting the words split right"
449- words=line.split(u' ')
450- thisline=u' '.join(words)
451- lastword=len(words)
452- lines=[]
453- maxx=self._rect.width(); maxy=self._rect.height();
454+ words = line.split(u' ')
455+ thisline = u' '.join(words)
456+ lastword = len(words)
457+ lines = []
458+ maxx = self._rect.width();
459+ maxy = self._rect.height();
460 while (len(words)>0):
461- w,h=self._get_extent_and_render(thisline, footer)
462- rhs=w+x
463+ w , h = self._get_extent_and_render(thisline, footer)
464+ rhs = w + x
465 if rhs < maxx-self._right_margin:
466 lines.append(thisline)
467- words=words[lastword:]
468- thisline=' '.join(words)
469- lastword=len(words)
470+ words = words[lastword:]
471+ thisline = ' '.join(words)
472+ lastword = len(words)
473 else:
474- lastword-=1
475- thisline=' '.join(words[:lastword])
476- startx=x
477- starty=y
478- rightextent=None
479- t=self._theme
480+ lastword -= 1
481+ thisline = ' '.join(words[:lastword])
482+ startx = x
483+ starty = y
484+ rightextent = None
485 if footer: # dont allow alignment messing with footers
486 align = 0
487 else:
488- align=t.display_horizontalAlign
489-
490- wrapstyle=t.display_wrapStyle
491+ align = int(self._theme .display_horizontalAlign)
492
493 for linenum in range(len(lines)):
494- line=lines[linenum]
495+ line = lines[linenum]
496 #find out how wide line is
497- w,h=self._get_extent_and_render(line, footer, tlcorner=(x, y), draw=False)
498-
499- if t.display_shadow:
500- w+=self._shadow_offset
501- h+=self._shadow_offset
502- if t.display_outline:
503- w+=2*self._outline_offset # pixels either side
504- h+=2*self._outline_offset # pixels top/bottom
505- if align==0: # left align
506- rightextent=x+w
507- if wrapstyle==1 and linenum != 0: # shift right from last line's rh edge
508- rightextent=self._first_line_right_extent + self._right_margin
509+ w , h = self._get_extent_and_render(line, footer, tlcorner=(x, y), draw=False)
510+ if self._theme.display_shadow:
511+ w += self._shadow_offset
512+ h += self._shadow_offset
513+ if self._theme.display_outline:
514+ w += 2*self._outline_offset # pixels either side
515+ h += 2*self._outline_offset # pixels top/bottom
516+ if align == 0: # left align
517+ rightextent = x + w
518+ if self._theme.display_wrapStyle == 1 and linenum != 0: # shift right from last line's rh edge
519+ rightextent = self._first_line_right_extent + self._right_margin
520 if rightextent > maxx:
521 rightextent = maxx
522- x = rightextent-w
523-
524- elif align==1: # right align
525- rightextent=maxx
526- x=maxx-w
527- elif align==2: # centre
528- x=(maxx-w)/2;
529- rightextent=x+w
530+ x = rightextent - w
531+ elif align == 1: # right align
532+ rightextent = maxx
533+ x = maxx-w
534+ elif align == 2: # centre
535+ x = (maxx-w) / 2;
536+ rightextent = x+w
537 # now draw the text, and any outlines/shadows
538- if t.display_shadow:
539+ if self._theme.display_shadow:
540 self._get_extent_and_render(line, footer,tlcorner=(x+self._shadow_offset,y+self._shadow_offset),
541- draw=True, color = t.display_shadow_color)
542- if t.display_outline:
543- self._get_extent_and_render(line, footer,(x+self._outline_offset,y), draw=True, color = t.display_outline_color)
544- self._get_extent_and_render(line, footer,(x, y+self._outline_offset), draw=True, color = t.display_outline_color)
545- self._get_extent_and_render(line, footer,(x, y-self._outline_offset), draw=True, color = t.display_outline_color)
546- self._get_extent_and_render(line, footer,(x-self._outline_offset,y), draw=True, color = t.display_outline_color)
547+ draw=True, color = self._theme.display_shadow_color)
548+ if self._theme.display_outline:
549+ self._get_extent_and_render(line, footer,(x+self._outline_offset,y), draw=True,
550+ color = self._theme.display_outline_color)
551+ self._get_extent_and_render(line, footer,(x, y+self._outline_offset), draw=True,
552+ color = self._theme.display_outline_color)
553+ self._get_extent_and_render(line, footer,(x, y-self._outline_offset), draw=True,
554+ color = self._theme.display_outline_color)
555+ self._get_extent_and_render(line, footer,(x-self._outline_offset,y), draw=True,
556+ color = self._theme.display_outline_color)
557 if self._outline_offset > 1:
558- self._get_extent_and_render(line, footer,(x+self._outline_offset,y+self._outline_offset), draw=True, color = t.display_outline_color)
559- self._get_extent_and_render(line, footer,(x-self._outline_offset,y+self._outline_offset), draw=True, color = t.display_outline_color)
560- self._get_extent_and_render(line, footer,(x+self._outline_offset,y-self._outline_offset), draw=True, color = t.display_outline_color)
561- self._get_extent_and_render(line, footer,(x-self._outline_offset,y-self._outline_offset), draw=True, color = t.display_outline_color)
562+ self._get_extent_and_render(line, footer,(x+self._outline_offset,y+self._outline_offset), draw=True,
563+ color = self._theme.display_outline_color)
564+ self._get_extent_and_render(line, footer,(x-self._outline_offset,y+self._outline_offset), draw=True,
565+ color = self._theme.display_outline_color)
566+ self._get_extent_and_render(line, footer,(x+self._outline_offset,y-self._outline_offset), draw=True,
567+ color = self._theme.display_outline_color)
568+ self._get_extent_and_render(line, footer,(x-self._outline_offset,y-self._outline_offset), draw=True,
569+ color = self._theme.display_outline_color)
570
571 self._get_extent_and_render(line, footer,tlcorner=(x, y), draw=True)
572-# log.debug(u'Line %2d: Render '%s' at (%d, %d) wh=(%d,%d)' % ( linenum, line, x, y,w,h)
573 y += h
574 if linenum == 0:
575- self._first_line_right_extent=rightextent
576+ self._first_line_right_extent = rightextent
577 # draw a box around the text - debug only
578 if self._debug:
579- p=QtGui.QPainter()
580- p.begin(self._paint)
581- p.setPen(QtGui.QPen(QtGui.QColor(0,255,0)))
582- p.drawRect(startx,starty,rightextent-startx, y-starty)
583- p.end()
584+ painter = QtGui.QPainter()
585+ painter.begin(self._frame)
586+ painter.setPen(QtGui.QPen(QtGui.QColor(0,255,0)))
587+ painter.drawRect(startx , starty , rightextent-startx , y-starty)
588+ painter.end()
589
590- brcorner=(rightextent,y)
591+ brcorner = (rightextent , y)
592 log.debug(u'Render single line Finish')
593 return brcorner
594
595 # xxx this is what to override for an SDL version
596 def _get_extent_and_render(self, line, footer, tlcorner=(0,0), draw=False, color=None):
597- """Find bounding box of text - as render_single_line.
598+ """
599+ Find bounding box of text - as render_single_line.
600 If draw is set, actually draw the text to the current DC as well
601- return width and height of text as a tuple (w,h)"""
602+ return width and height of text as a tuple (w,h)
603+ """
604 # setup defaults
605 #log.debug(u'_get_extent_and_render %s %s %s ', [line], tlcorner, draw)
606- p=QtGui.QPainter()
607- p.begin(self._paint)
608+ painter = QtGui.QPainter()
609+ painter.begin(self._frame)
610 # 'twould be more efficient to set this once when theme changes
611 # or p changes
612 if footer :
613- font=QtGui.QFont(self._theme.font_footer_name,
614+ font = QtGui.QFont(self._theme.font_footer_name,
615 int(self._theme.font_footer_proportion), # size
616 QtGui.QFont.Normal, # weight
617 0)# italic
618+ font.setPixelSize(int(self._theme.font_footer_proportion))
619 else:
620- font=QtGui.QFont(self._theme.font_main_name,
621+ font = QtGui.QFont(self._theme.font_main_name,
622 int(self._theme.font_main_proportion), # size
623 QtGui.QFont.Normal, # weight
624 0)# italic
625- # to make the unit tests monitor independent, we have to be able to
626- # specify whether a font proportion is in pixels or points
627- if footer:
628- font.setPixelSize(int(self._theme.font_footer_proportion))
629- else:
630 font.setPixelSize(int(self._theme.font_main_proportion))
631 #log.debug(u'Font details %s %s %s %d', self._theme.font_main_name, self._theme.font_main_proportion, font.family(), font.pointSize())
632- p.setFont(font)
633+ painter.setFont(font)
634 if color == None:
635 if footer:
636- p.setPen(QtGui.QColor(self._theme.font_footer_color))
637+ painter.setPen(QtGui.QColor(self._theme.font_footer_color))
638 else:
639- p.setPen(QtGui.QColor(self._theme.font_main_color))
640+ painter.setPen(QtGui.QColor(self._theme.font_main_color))
641 else:
642- p.setPen(QtGui.QColor(color))
643- x, y=tlcorner
644+ painter.setPen(QtGui.QColor(color))
645+ x, y = tlcorner
646 metrics=QtGui.QFontMetrics(font)
647 # xxx some fudges to make it exactly like wx! Take 'em out later
648- w=metrics.width(line)
649- h=metrics.height()-2
650+ w = metrics.width(line)
651+ h = metrics.height()-2
652 if draw:
653- p.drawText(x, y+metrics.height()-metrics.descent()-1, line)
654- p.end()
655+ painter.drawText(x, y+metrics.height()-metrics.descent()-1, line)
656+ painter.end()
657 return (w, h)
658+
659+ def snoop_Image(self, image, image2=None):
660+ """
661+ Debugging method to allow images to be viewed
662+ """
663+ im = image.toImage()
664+ im.save("renderer.png", "png")
665+ if image2 is not None:
666+ im = image2.toImage()
667+ im.save("renderer2.png", "png")
668
669=== modified file 'openlp/core/lib/rendermanager.py'
670--- openlp/core/lib/rendermanager.py 2009-05-11 05:09:43 +0000
671+++ openlp/core/lib/rendermanager.py 2009-05-17 15:24:02 +0000
672@@ -29,6 +29,9 @@
673 import linecache
674
675 def traceit(frame, event, arg):
676+ """
677+ Code to allow calls to be traced by python runtime
678+ """
679 if event == "line":
680 lineno = frame.f_lineno
681 filename = frame.f_globals["__file__"]
682@@ -59,7 +62,7 @@
683 self.theme_manager = theme_manager
684 self.displays = len(screen_list)
685 self.current_display = 0
686- self.renderer = Renderer(None)
687+ self.renderer = Renderer()
688 self.calculate_default(self.screen_list[self.current_display]['size'])
689
690 def set_override_theme(self, theme):
691@@ -68,11 +71,12 @@
692 self.theme = theme
693 else:
694 self.theme = self.default_theme
695- log.debug(u'theme is now %s', self.theme)
696- self.themedata = self.theme_manager.getThemeData(self.theme)
697- self.calculate_default(self.screen_list[self.current_display]['size'])
698- self.renderer.set_theme(self.themedata)
699- self.build_text_rectangle(self.themedata)
700+ if self.theme != self.renderer.theme_name:
701+ log.debug(u'theme is now %s', self.theme)
702+ self.themedata = self.theme_manager.getThemeData(self.theme)
703+ self.calculate_default(self.screen_list[self.current_display]['size'])
704+ self.renderer.set_theme(self.themedata)
705+ self.build_text_rectangle(self.themedata)
706
707 def build_text_rectangle(self, theme):
708 log.debug(u'build_text_rectangle ')
709@@ -95,50 +99,52 @@
710
711 def generate_preview(self, themedata):
712 log.debug(u'generate preview')
713- self.calculate_default(QtCore.QSize(800,600))
714+ self.calculate_default(QtCore.QSize(800, 600))
715 self.renderer.set_theme(themedata)
716 self.build_text_rectangle(themedata)
717
718- frame = QtGui.QPixmap(self.width, self.height)
719- self.renderer.set_paint_dest(frame)
720+ self.renderer.set_frame_dest(self.width, self.height, True)
721
722- lines=[]
723+ lines = []
724 lines.append(u'Amazing Grace!')
725 lines.append(u'How sweet the sound')
726 lines.append(u'To save a wretch like me;')
727 lines.append(u'I once was lost but now am found,')
728 lines.append(u'Was blind, but now I see.')
729- lines1=[]
730+ lines1 = []
731 lines1.append(u'Amazing Grace (John Newton)' )
732- lines1.append(u'CCLI xxx (c)Openlp.org')
733- answer=self.renderer.render_lines(lines, lines1)
734- return frame
735+ lines1.append(u'Public Domain')
736+ lines1.append(u'CCLI xxx')
737+ return self.renderer.render_lines(lines, lines1)
738+
739
740 def format_slide(self, words, footer):
741 log.debug(u'format slide')
742 self.calculate_default(self.screen_list[self.current_display]['size'])
743- self.renderer.set_paint_dest(QtGui.QPixmap(self.width, self.height))
744- return self.renderer.format_slide(words, footer)
745+ self.build_text_rectangle(self.themedata)
746+ self.renderer.set_frame_dest(self.width, self.height)
747+ return self.renderer.format_slide(words, False)
748
749 def generate_slide(self,main_text, footer_text):
750 log.debug(u'generate slide')
751- #sys.settrace(traceit)
752-
753 self.calculate_default(self.screen_list[self.current_display]['size'])
754-
755- bef = datetime.now()
756- frame = QtGui.QPixmap(self.width, self.height)
757- aft = datetime.now()
758- print "framebuild time", bef, aft, aft-bef
759-
760- self.renderer.set_paint_dest(frame)
761- answer=self.renderer.render_lines(main_text, footer_text)
762- #sys.settrace()
763- return frame
764+ self.build_text_rectangle(self.themedata)
765+ self.renderer.set_frame_dest(self.width, self.height)
766+ return self.renderer.render_lines(main_text, footer_text)
767
768 def calculate_default(self, screen):
769 log.debug(u'calculate default %s' , screen)
770 self.width = screen.width()
771 self.height = screen.height()
772 log.debug(u'calculate default %d,%d' , self.width, self.height)
773- self.footer_start = int(self.height*0.95) # 95% is start of footer
774+ self.footer_start = int(self.height*0.90) # 90% is start of footer
775+
776+ def snoop_Image(self, image, image2=None):
777+ """
778+ Debugging method to allow images to be viewed
779+ """
780+ im = image.toImage()
781+ im.save("renderer.png", "png")
782+ if image2 is not None:
783+ im = image2.toImage()
784+ im.save("renderer2.png", "png")
785
786=== modified file 'openlp/core/lib/serviceitem.py'
787--- openlp/core/lib/serviceitem.py 2009-05-13 19:47:25 +0000
788+++ openlp/core/lib/serviceitem.py 2009-05-17 15:24:02 +0000
789@@ -47,7 +47,7 @@
790 self.frames = []
791 self.raw_footer = None
792 self.theme = None
793- log.debug(u'Service item created for %s', self.shortname)
794+ log.debug(u'Service item created for %s ', self.shortname)
795
796 def addIcon(self, icon):
797 self.iconic_representation = buildIcon(icon)
798
799=== modified file 'openlp/core/lib/themexmlhandler.py'
800--- openlp/core/lib/themexmlhandler.py 2009-04-30 21:02:28 +0000
801+++ openlp/core/lib/themexmlhandler.py 2009-05-16 19:47:30 +0000
802@@ -21,7 +21,7 @@
803
804 For XML Schema see wiki.openlp.org
805 """
806-
807+import os, os.path
808 from openlp import convertStringToBoolean
809 from xml.dom.minidom import Document
810 from xml.etree.ElementTree import ElementTree, XML, dump
811@@ -40,7 +40,7 @@
812 <direction>vertical</direction>
813 </background>
814 <background type="image" mode="opaque">
815- <filename>fred.bmp</filename>
816+ <filename></filename>
817 </background>
818 <font type="main">
819 <name>Arial</name>
820@@ -69,6 +69,10 @@
821 # Create the minidom document
822 self.theme_xml = Document()
823
824+ def extend_filename(self, path):
825+ if self.background_filename is not None:
826+ self.background_filename = os.path.join(path, self.theme_name, self.background_filename)
827+
828 def new_document(self, name):
829 # Create the <song> base element
830 self.theme = self.theme_xml.createElement(u'theme')
831
832=== modified file 'openlp/core/ui/amendthemeform.py'
833--- openlp/core/ui/amendthemeform.py 2009-04-30 21:02:28 +0000
834+++ openlp/core/ui/amendthemeform.py 2009-05-16 19:47:30 +0000
835@@ -22,10 +22,8 @@
836
837 from PyQt4 import QtCore, QtGui
838 from PyQt4.QtGui import QColor, QFont
839-from openlp.core.lib import ThemeXML
840-from openlp.core.lib import Renderer
841-from openlp.core import fileToXML
842-from openlp.core import translate
843+from openlp.core.lib import ThemeXML, Renderer
844+from openlp.core import fileToXML, translate
845
846 from amendthemedialog import Ui_AmendThemeDialog
847
848@@ -53,6 +51,8 @@
849 QtCore.SIGNAL("pressed()"), self.onOutlineColorPushButtonClicked)
850 QtCore.QObject.connect(self.ShadowColorPushButton,
851 QtCore.SIGNAL("pressed()"), self.onShadowColorPushButtonClicked)
852+ QtCore.QObject.connect(self.ImageToolButton,
853+ QtCore.SIGNAL("pressed()"), self.onImageToolButtonClicked)
854
855 #Combo boxes
856 QtCore.QObject.connect(self.BackgroundComboBox,
857@@ -99,17 +99,22 @@
858 QtCore.QObject.connect(self.ShadowCheckBox,
859 QtCore.SIGNAL("stateChanged(int)"), self.onShadowCheckBoxChanged)
860
861-
862 def accept(self):
863 new_theme = ThemeXML()
864 theme_name = str(self.ThemeNameEdit.displayText())
865 new_theme.new_document(theme_name)
866+ save_from = None
867+ save_to = None
868 if self.theme.background_type == u'solid':
869 new_theme.add_background_solid(str(self.theme.background_color))
870 elif self.theme.background_type == u'gradient':
871- new_theme.add_background_gradient(str(self.theme.background_startColor), str(self.theme.background_endColor), self.theme.background_direction)
872- #else:
873- #newtheme.add_background_image(str(self.theme.))
874+ new_theme.add_background_gradient(str(self.theme.background_startColor),
875+ str(self.theme.background_endColor), self.theme.background_direction)
876+ else:
877+ (path, filename) =os.path.split(str(self.theme.background_filename))
878+ new_theme.add_background_image(filename)
879+ save_to= os.path.join(self.path, theme_name,filename )
880+ save_from = self.theme.background_filename
881
882 new_theme.add_font(str(self.theme.font_main_name), str(self.theme.font_main_color),
883 str(self.theme.font_main_proportion), str(self.theme.font_main_override),u'main',
884@@ -126,7 +131,7 @@
885
886 theme = new_theme.extract_xml()
887
888- self.thememanager.saveTheme(theme_name, theme)
889+ self.thememanager.saveTheme(theme_name, theme, save_from, save_to)
890 return QtGui.QDialog.accept(self)
891
892 def themePath(self, path):
893@@ -140,9 +145,17 @@
894 xml_file = os.path.join(self.path, theme, theme+u'.xml')
895 xml = fileToXML(xml_file)
896 self.theme.parse(xml)
897+ self.allowPreview = False
898 self.paintUi(self.theme)
899+ self.allowPreview = True
900 self.previewTheme(self.theme)
901
902+ def onImageToolButtonClicked(self):
903+ filename = QtGui.QFileDialog.getOpenFileName(self, 'Open file')
904+ if filename != "":
905+ self.ImageLineEdit.setText(filename)
906+ self.theme.background_filename = filename
907+ self.previewTheme(self.theme)
908 #
909 #Main Font Tab
910 #
911@@ -196,8 +209,6 @@
912 def onFontMainHeightSpinBoxChanged(self, value):
913 self.theme.font_main_height = value
914 self.previewTheme(self.theme)
915-
916-
917 #
918 #Footer Font Tab
919 #
920@@ -217,7 +228,6 @@
921 self.theme.font_footer_proportion = value
922 self.previewTheme(self.theme)
923
924-
925 def onFontFooterDefaultCheckBoxChanged(self, value):
926 if value == 2: # checked
927 self.theme.font_footer_override = False
928@@ -516,5 +526,6 @@
929
930
931 def previewTheme(self, theme):
932- frame = self.thememanager.generateImage(theme)
933- self.ThemePreview.setPixmap(frame)
934+ if self.allowPreview:
935+ frame = self.thememanager.generateImage(theme)
936+ self.ThemePreview.setPixmap(frame)
937
938=== modified file 'openlp/core/ui/maindisplay.py'
939--- openlp/core/ui/maindisplay.py 2009-05-04 13:51:56 +0000
940+++ openlp/core/ui/maindisplay.py 2009-05-16 19:47:30 +0000
941@@ -60,9 +60,9 @@
942 painter.fillRect(self.blankFrame.rect(), QtGui.QColor(u'#000000'))
943
944 def frameView(self, frame):
945+ self.frame = frame
946 if self.displayBlank == False:
947 self.display.setPixmap(frame)
948- self.frame = frame
949
950 def blankDisplay(self):
951 if self.displayBlank == False:
952@@ -71,7 +71,3 @@
953 else:
954 self.displayBlank = False
955 self.frameView(self.frame)
956-
957-
958- def kill(self):
959- pass
960
961=== modified file 'openlp/core/ui/mainwindow.py'
962--- openlp/core/ui/mainwindow.py 2009-05-14 18:00:36 +0000
963+++ openlp/core/ui/mainwindow.py 2009-05-16 16:38:03 +0000
964@@ -37,6 +37,7 @@
965
966 def __init__(self, screens):
967 self.main_window = QtGui.QMainWindow()
968+ self.main_window.__class__.closeEvent = self.onCloseEvent
969 self.main_display = MainDisplay(None, screens)
970 self.screen_list = screens
971 self.EventManager = EventManager()
972@@ -89,23 +90,32 @@
973
974 # Once all components are initialised load the Themes
975 log.info(u'Load Themes and Managers')
976- self.PreviewController.eventManager = self.EventManager
977- self.PreviewController.serviceManager = self.ServiceManagerContents
978- self.LiveController.eventManager = self.EventManager
979- self.LiveController.serviceManager = self.ServiceManagerContents
980- self.ThemeManagerContents.eventManager = self.EventManager
981- self.ThemeManagerContents.renderManager = self.RenderManager
982- self.ServiceManagerContents.renderManager = self.RenderManager
983- self.ServiceManagerContents.eventManager = self.EventManager
984- self.ServiceManagerContents.liveController = self.LiveController
985- self.ServiceManagerContents.previewController = self.PreviewController
986- self.ThemeManagerContents.serviceManager = self.ServiceManagerContents
987+ self.PreviewController.ServiceManager = self.ServiceManagerContents
988+ self.LiveController.ServiceManager = self.ServiceManagerContents
989+
990+ self.ThemeManagerContents.EventManager = self.EventManager
991+ self.ThemeManagerContents.RenderManager = self.RenderManager
992+ self.ThemeManagerContents.ServiceManager = self.ServiceManagerContents
993+ #self.ThemeManagerContents.ThemesTab = self.ServiceManagerContents.ThemesTab
994+
995+ self.ServiceManagerContents.RenderManager = self.RenderManager
996+ self.ServiceManagerContents.EventManager = self.EventManager
997+ self.ServiceManagerContents.LiveController = self.LiveController
998+ self.ServiceManagerContents.PreviewController = self.PreviewController
999+
1000 self.ThemeManagerContents.loadThemes()
1001
1002 # Initialise SlideControllers
1003 log.info(u'Set Up SlideControllers')
1004 self.LiveController.mainDisplay = self.main_display
1005
1006+ def onCloseEvent(self, event):
1007+ """
1008+ Hook to close the main window and display windows on exit
1009+ """
1010+ self.main_display.close()
1011+ event.accept()
1012+
1013 def setupUi(self):
1014 self.main_window.setObjectName(u'main_window')
1015 self.main_window.resize(1087, 847)
1016
1017=== modified file 'openlp/core/ui/servicemanager.py'
1018--- openlp/core/ui/servicemanager.py 2009-05-14 18:00:36 +0000
1019+++ openlp/core/ui/servicemanager.py 2009-05-16 16:38:03 +0000
1020@@ -136,13 +136,13 @@
1021 pass
1022
1023 def onSaveService(self):
1024- Pass
1025+ pass
1026
1027 def onLoadService(self):
1028- Pass
1029+ pass
1030
1031 def onThemeComboBoxSelected(self, currentIndex):
1032- self.renderManager.default_theme = self.ThemeComboBox.currentText()
1033+ self.RenderManager.default_theme = self.ThemeComboBox.currentText()
1034
1035 def addServiceItem(self, item):
1036 self.serviceItems.append({u'data': item, u'order': len(self.serviceItems)+1})
1037@@ -162,11 +162,11 @@
1038
1039 def makePreview(self):
1040 item, count = self.findServiceItem()
1041- self.previewController.addServiceManagerItem(self.serviceItems[item][u'data'], count)
1042+ self.PreviewController.addServiceManagerItem(self.serviceItems[item][u'data'], count)
1043
1044 def makeLive(self):
1045 item, count = self.findServiceItem()
1046- self.liveController.addServiceManagerItem(self.serviceItems[item][u'data'], count)
1047+ self.LiveController.addServiceManagerItem(self.serviceItems[item][u'data'], count)
1048
1049 def findServiceItem(self):
1050 items = self.ServiceManagerList.selectedItems()
1051@@ -197,7 +197,7 @@
1052 link=event.mimeData()
1053 if link.hasText():
1054 plugin = event.mimeData().text()
1055- self.eventManager.post_event(Event(EventType.LoadServiceItem, plugin))
1056+ self.EventManager.post_event(Event(EventType.LoadServiceItem, plugin))
1057
1058 def oos_as_text(self):
1059 text=[]
1060@@ -226,5 +226,5 @@
1061 self.ThemeComboBox.clear()
1062 for theme in theme_list:
1063 self.ThemeComboBox.addItem(theme)
1064- self.renderManager.default_theme = self.ThemeComboBox.currentText()
1065+ self.RenderManager.default_theme = self.ThemeComboBox.currentText()
1066
1067
1068=== modified file 'openlp/core/ui/slidecontroller.py'
1069--- openlp/core/ui/slidecontroller.py 2009-05-14 18:00:36 +0000
1070+++ openlp/core/ui/slidecontroller.py 2009-05-16 10:24:03 +0000
1071@@ -24,7 +24,6 @@
1072
1073 from openlp.core.lib import OpenLPToolbar
1074 from openlp.core import translate
1075-from openlp.core.lib import Event, EventType, EventManager
1076
1077 class SlideData(QtCore.QAbstractListModel):
1078 """
1079@@ -37,17 +36,13 @@
1080
1081 def __init__(self):
1082 QtCore.QAbstractListModel.__init__(self)
1083- self.items=[]
1084- self.rowheight=50
1085- self.maximagewidth=self.rowheight*16/9.0;
1086+ self.items = []
1087+ self.rowheight = 50
1088+ self.maximagewidth = self.rowheight * 16/9.0;
1089 log.info(u'Starting')
1090
1091- def eventFilter(self, obj, event):
1092- print obj, event
1093- return false
1094-
1095 def clear(self):
1096- self.items=[]
1097+ self.items = []
1098
1099 def columnCount(self, parent):
1100 return 1
1101
1102=== modified file 'openlp/core/ui/thememanager.py'
1103--- openlp/core/ui/thememanager.py 2009-05-11 05:09:43 +0000
1104+++ openlp/core/ui/thememanager.py 2009-05-17 08:25:15 +0000
1105@@ -222,8 +222,10 @@
1106 for name in files:
1107 if name.endswith(u'.png'):
1108 self.themeData.addRow(os.path.join(self.path, name))
1109- self.eventManager.post_event(Event(EventType.ThemeListChanged))
1110- self.serviceManager.updateThemeList(self.getThemes())
1111+ self.EventManager.post_event(Event(EventType.ThemeListChanged))
1112+ self.ServiceManager.updateThemeList(self.getThemes())
1113+ self.parent.settings_form.ThemesTab.updateThemeList(self.getThemes())
1114+
1115
1116 def getThemes(self):
1117 return self.themeData.getList()
1118@@ -244,6 +246,7 @@
1119 xml = newtheme.extract_xml()
1120 theme = ThemeXML()
1121 theme.parse(xml)
1122+ theme.extend_filename(self.path)
1123 return theme
1124
1125 def checkThemesExists(self, dir):
1126@@ -331,9 +334,8 @@
1127 str(theme.WrapStyle))
1128 return newtheme.extract_xml()
1129
1130- def saveTheme(self, name, theme_xml) :
1131+ def saveTheme(self, name, theme_xml, image_from, image_to) :
1132 log.debug(u'saveTheme %s %s', name, theme_xml)
1133- self.generateAndSaveImage(self.path, name, theme_xml)
1134 theme_dir = os.path.join(self.path, name)
1135 if os.path.exists(theme_dir) == False:
1136 os.mkdir(os.path.join(self.path, name))
1137@@ -341,6 +343,9 @@
1138 outfile = open(theme_file, u'w')
1139 outfile.write(theme_xml)
1140 outfile.close()
1141+ if image_from is not None:
1142+ shutil.copyfile(image_from, image_to)
1143+ self.generateAndSaveImage(self.path, name, theme_xml)
1144 self.themeData.clearItems()
1145 self.loadThemes()
1146
1147@@ -348,6 +353,7 @@
1148 log.debug(u'generateAndSaveImage %s %s %s', dir, name, theme_xml)
1149 theme = ThemeXML()
1150 theme.parse(theme_xml)
1151+ theme.extend_filename(dir)
1152 frame = self.generateImage(theme)
1153 im = frame.toImage()
1154 samplepathname = os.path.join(self.path, name + u'.png')
1155@@ -358,6 +364,6 @@
1156
1157 def generateImage(self, themedata):
1158 log.debug(u'generateImage %s ', themedata)
1159- frame = self.renderManager.generate_preview(themedata)
1160+ frame = self.RenderManager.generate_preview(themedata)
1161 return frame
1162
1163
1164=== modified file 'openlp/core/ui/themestab.py'
1165--- openlp/core/ui/themestab.py 2009-03-23 19:17:07 +0000
1166+++ openlp/core/ui/themestab.py 2009-05-16 16:38:03 +0000
1167@@ -105,3 +105,11 @@
1168 self.ServiceLevelLabel.setText(translate(u'ThemesTab', u'Use the theme from the service , overriding any of the individual songs\' themes. If the service doesn\'t have a theme, then use the global theme.'))
1169 self.GlobalLevelRadioButton.setText(translate(u'ThemesTab', u'Global level'))
1170 self.GlobalLevelLabel.setText(translate(u'ThemesTab', u'Use the global theme, overriding any themes associated wither either the service or the songs.'))
1171+
1172+ def updateThemeList(self, theme_list):
1173+ """
1174+ Called from ThemeManager when the Themes have changed
1175+ """
1176+ self.DefaultComboBox.clear()
1177+ for theme in theme_list:
1178+ self.DefaultComboBox.addItem(theme)
1179
1180=== modified file 'openlp/plugins/bibles/bibleplugin.py'
1181--- openlp/plugins/bibles/bibleplugin.py 2009-05-12 21:06:35 +0000
1182+++ openlp/plugins/bibles/bibleplugin.py 2009-05-17 08:25:15 +0000
1183@@ -85,13 +85,13 @@
1184 log.debug(u'Handle event called with event %s with payload %s'%(event.event_type, event.payload))
1185 if event.event_type == EventType.ThemeListChanged:
1186 log.debug(u'New Theme request received')
1187- #self.edit_custom_form.loadThemes(self.theme_manager.getThemes())
1188+ self.bibles_tab.updateThemeList(self.theme_manager.getThemes())
1189 if event.event_type == EventType.LoadServiceItem and event.payload == 'Bibles':
1190 log.debug(u'Load Service Item received')
1191 self.media_item.onBibleAddClick()
1192 if event.event_type == EventType.PreviewShow and event.payload == 'Bibles':
1193- log.debug(u'Load Service Item received')
1194+ log.debug(u'Load Preview Item received')
1195 self.media_item.onBiblePreviewClick()
1196 if event.event_type == EventType.LiveShow and event.payload == 'Bibles':
1197- log.debug(u'Load Service Item received')
1198+ log.debug(u'Load Live Show Item received')
1199 self.media_item.onBibleLiveClick()
1200
1201=== modified file 'openlp/plugins/bibles/lib/biblestab.py'
1202--- openlp/plugins/bibles/lib/biblestab.py 2009-04-15 04:58:51 +0000
1203+++ openlp/plugins/bibles/lib/biblestab.py 2009-05-17 15:24:02 +0000
1204@@ -198,6 +198,7 @@
1205 self.BibleThemeComboBox.setCurrentIndex(self.bible_theme)
1206 else:
1207 pass # TODO need to code
1208+ self.bible_theme = None
1209
1210 def save(self):
1211 self.config.set_config("paragraph style", str(self.paragraph_style))
1212@@ -205,3 +206,11 @@
1213 self.config.set_config("display brackets", str(self.display_style))
1214 self.config.set_config("search as type", str(self.bible_search))
1215 self.config.set_config("bible theme", str(self.bible_theme))
1216+
1217+ def updateThemeList(self, theme_list):
1218+ """
1219+ Called from ThemeManager when the Themes have changed
1220+ """
1221+ self.BibleThemeComboBox.clear()
1222+ for theme in theme_list:
1223+ self.BibleThemeComboBox.addItem(theme)
1224
1225=== modified file 'openlp/plugins/bibles/lib/mediaitem.py'
1226--- openlp/plugins/bibles/lib/mediaitem.py 2009-05-13 19:47:25 +0000
1227+++ openlp/plugins/bibles/lib/mediaitem.py 2009-05-17 15:24:02 +0000
1228@@ -369,13 +369,14 @@
1229 def generateSlideData(self, service_item):
1230 log.debug(u'Bible Preview Button pressed')
1231 items = self.BibleListView.selectedIndexes()
1232- old_chapter = ''
1233+ old_chapter = u''
1234 raw_slides=[]
1235 raw_footer = []
1236+ bible_text = u''
1237 for item in items:
1238 text = self.BibleListData.getValue(item)
1239- verse = text[:text.find("(")]
1240- bible = text[text.find("(") + 1:text.find(")")]
1241+ verse = text[:text.find(u'(')]
1242+ bible = text[text.find(u'(') + 1:text.find(u')')]
1243 self.searchByReference(bible, verse)
1244 book = self.search_results[0][0]
1245 chapter = str(self.search_results[0][1])
1246@@ -392,15 +393,15 @@
1247 else:
1248 loc = self.formatVerse(old_chapter, chapter, verse, u'', u'')
1249 old_chapter = chapter
1250- raw_slides.append(loc + u' '+text)
1251+ bible_text = bible_text + u' '+ loc + u' '+ text
1252 service_item.title = book + u' ' + loc
1253 if len(raw_footer) <= 1:
1254 raw_footer.append(book)
1255
1256- if len(raw_slides) > 0:
1257- service_item.theme = None
1258- service_item.raw_slides = raw_slides
1259- service_item.raw_footer = raw_footer
1260+ service_item.theme = self.parent.bibles_tab.bible_theme
1261+ raw_slides.append(bible_text)
1262+ service_item.raw_slides = raw_slides
1263+ service_item.raw_footer = raw_footer
1264
1265 def formatVerse(self, old_chapter, chapter, verse, opening, closing):
1266 loc = opening
1267
1268=== modified file 'openlp/plugins/bibles/lib/textlistdata.py'
1269--- openlp/plugins/bibles/lib/textlistdata.py 2009-03-16 17:33:51 +0000
1270+++ openlp/plugins/bibles/lib/textlistdata.py 2009-05-17 15:24:02 +0000
1271@@ -1,3 +1,22 @@
1272+# -*- coding: utf-8 -*-
1273+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
1274+"""
1275+OpenLP - Open Source Lyrics Projection
1276+Copyright (c) 2008 Raoul Snyman
1277+Portions copyright (c) 2008-2009 Martin Thompson, Tim Bentley
1278+
1279+This program is free software; you can redistribute it and/or modify it under
1280+the terms of the GNU General Public License as published by the Free Software
1281+Foundation; version 2 of the License.
1282+
1283+This program is distributed in the hope that it will be useful, but WITHOUT ANY
1284+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
1285+PARTICULAR PURPOSE. See the GNU General Public License for more details.
1286+
1287+You should have received a copy of the GNU General Public License along with
1288+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
1289+Place, Suite 330, Boston, MA 02111-1307 USA
1290+"""
1291 import logging
1292
1293 from PyQt4.QtCore import *
1294@@ -6,7 +25,7 @@
1295
1296 class TextListData(QAbstractListModel):
1297 """
1298- An abstract list of strings
1299+ An abstract list of strings
1300 """
1301 global log
1302 log=logging.getLogger(u'TextListData')
1303@@ -14,18 +33,18 @@
1304
1305 def __init__(self):
1306 QAbstractListModel.__init__(self)
1307- self.items=[] # will be a list of (database id , title) tuples
1308+ self.items = [] # will be a list of (database id , title) tuples
1309
1310 def resetStore(self):
1311 #reset list so can be reloaded
1312- self.items=[]
1313-
1314+ self.items = []
1315+
1316 def rowCount(self, parent):
1317 return len(self.items)
1318
1319 def insertRow(self, row, id, title):
1320 self.beginInsertRows(QModelIndex(),row,row)
1321- log.debug("insert row %d:%s for id %d"%(row,title, id))
1322+ log.debug(u'insert row %d:%s for id %d'%(row,title, id))
1323 self.items.insert(row, (id, title))
1324 self.endInsertRows()
1325
1326@@ -36,18 +55,15 @@
1327
1328 def addRow(self, id, title):
1329 self.insertRow(len(self.items), id, title)
1330-
1331+
1332 def data(self, index, role):
1333 row=index.row()
1334 if row > len(self.items): # if the last row is selected and deleted, we then get called with an empty row!
1335 return QVariant()
1336- if role==Qt.DisplayRole:
1337- retval= self.items[row][1]
1338-# elif role == Qt.ToolTipRole: #not sure if need as it shows the database row number
1339-# retval= self.items[row][0]
1340+ if role == Qt.DisplayRole:
1341+ retval = self.items[row][1]
1342 else:
1343- retval= QVariant()
1344-# log.info("Returning"+ str(retval))
1345+ retval = QVariant()
1346 if type(retval) is not type(QVariant):
1347 return QVariant(retval)
1348 else:
1349@@ -60,10 +76,7 @@
1350 def getValue(self, index):
1351 row = index.row()
1352 return self.items[row][1]
1353-
1354+
1355 def deleteRow(self, index):
1356 row = index.row()
1357 self.removeRow(row)
1358-
1359-if __name__=="__main__":
1360- sxml=TextListData()
1361
1362=== modified file 'openlp/plugins/custom/customplugin.py'
1363--- openlp/plugins/custom/customplugin.py 2009-05-12 21:06:35 +0000
1364+++ openlp/plugins/custom/customplugin.py 2009-05-16 10:24:03 +0000
1365@@ -64,8 +64,8 @@
1366 log.debug(u'Load Service Item received')
1367 self.media_item.onCustomAddClick()
1368 if event.event_type == EventType.PreviewShow and event.payload == 'Custom':
1369- log.debug(u'Load Service Item received ')
1370+ log.debug(u'Load Preview Item received ')
1371 self.media_item.onCustomPreviewClick()
1372 if event.event_type == EventType.LiveShow and event.payload == 'Custom':
1373- log.debug(u'Load Service Item received')
1374+ log.debug(u'Load Live Show Item received')
1375 self.media_item.onCustomLiveClick()
1376
1377=== modified file 'openlp/plugins/images/imageplugin.py'
1378--- openlp/plugins/images/imageplugin.py 2009-05-12 21:06:35 +0000
1379+++ openlp/plugins/images/imageplugin.py 2009-05-16 10:24:03 +0000
1380@@ -60,10 +60,10 @@
1381 log.debug(u'Load Service Item received')
1382 self.media_item.onImageAddClick()
1383 if event.event_type == EventType.PreviewShow and event.payload == 'Image':
1384- log.debug(u'Load Service Item received')
1385+ log.debug(u'Load Preview Item received')
1386 self.media_item.onImagePreviewClick()
1387 if event.event_type == EventType.LiveShow and event.payload == 'Image':
1388- log.debug(u'Load Service Item received')
1389+ log.debug(u'Load Live Show Item received')
1390 self.media_item.onImageLiveClick()
1391
1392
1393
1394=== modified file 'openlp/plugins/images/lib/mediaitem.py'
1395--- openlp/plugins/images/lib/mediaitem.py 2009-05-13 19:47:25 +0000
1396+++ openlp/plugins/images/lib/mediaitem.py 2009-05-16 10:24:03 +0000
1397@@ -175,7 +175,7 @@
1398 self.parent.live_controller.addServiceItem(service_item)
1399
1400 def onImageAddClick(self):
1401- log.debug(u'Image Live Requested')
1402+ log.debug(u'Image Add Requested')
1403 service_item = ServiceItem(self.parent)
1404 service_item.addIcon( ":/media/media_image.png")
1405 service_item.render_manager = self.parent.render_manager
1406
1407=== modified file 'openlp/plugins/media/lib/mediaitem.py'
1408--- openlp/plugins/media/lib/mediaitem.py 2009-05-15 05:15:53 +0000
1409+++ openlp/plugins/media/lib/mediaitem.py 2009-05-16 16:38:03 +0000
1410@@ -30,7 +30,7 @@
1411
1412 class MediaMediaItem(MediaManagerItem):
1413 """
1414- This is the custom media manager item for Custom Slides.
1415+ This is the custom media manager item for Media Slides.
1416 """
1417 global log
1418 log=logging.getLogger(u'MediaMediaItem')
1419@@ -93,13 +93,14 @@
1420 translate('MediaMediaItem',u'&Add to Service'), self.onMediaAddClick))
1421
1422 def initialise(self):
1423- list = self.parent.config.load_list(u'Medias')
1424+ list = self.parent.config.load_list(u'Media')
1425 self.loadMediaList(list)
1426
1427 def onMediaNewClick(self):
1428 files = QtGui.QFileDialog.getOpenFileNames(None,
1429 translate('MediaMediaItem', u'Select Media(s) items'),
1430- self.parent.config.get_last_dir(), u'Images (*.avi *.mpeg)')
1431+ self.parent.config.get_last_dir(),
1432+ u'Images (*.avi *.mpeg);;Audio (*.mp3 *.ogg *.wma);;All files (*)')
1433 if len(files) > 0:
1434 self.loadMediaList(files)
1435 dir, filename = os.path.split(str(files[0]))
1436
1437=== modified file 'openlp/plugins/songs/songsplugin.py'
1438--- openlp/plugins/songs/songsplugin.py 2009-04-10 06:06:41 +0000
1439+++ openlp/plugins/songs/songsplugin.py 2009-05-16 16:38:03 +0000
1440@@ -105,10 +105,6 @@
1441 QtCore.QObject.connect(self.ExportOpenlp1Item, QtCore.SIGNAL("triggered()"), self.onExportOpenlp1ItemClicked)
1442 QtCore.QObject.connect(self.ExportOpenSongItem, QtCore.SIGNAL("triggered()"), self.onExportOpenSongItemClicked)
1443
1444- def get_settings_tab(self):
1445- self.SongsTab = SongsTab()
1446- return self.SongsTab
1447-
1448 def initialise(self):
1449 pass
1450