bzr-revno: 447
This commit is contained in:
Tim Bentley 2009-05-17 21:00:50 +01:00
commit 713490896a
22 changed files with 410 additions and 333 deletions

View File

@ -54,6 +54,3 @@ class Event(object):
def __init__(self, event_type=EventType.Default, payload=None): def __init__(self, event_type=EventType.Default, payload=None):
self.event_type = event_type self.event_type = event_type
self.payload = payload self.payload = payload
def get_type(self):
return self.event_type

View File

@ -40,7 +40,7 @@ class EventManager(object):
self.endpoints.append(plugin) self.endpoints.append(plugin)
def post_event(self, event): def post_event(self, event):
log.debug(u'post event called for event %s', event.get_type) log.debug(u'post event called for event %s', event.event_type)
for point in self.endpoints: for point in self.endpoints:
point.handle_event(event) point.handle_event(event)

View File

@ -41,143 +41,160 @@ class Renderer:
tell it to render a particular screenfull with render_screen(n) tell it to render a particular screenfull with render_screen(n)
""" """
def __init__(self, path=None): def __init__(self):
self._rect=None self._rect = None
self._debug=0 self._debug = 0
self.words=None self.words = None
self._right_margin = 64 # the amount of right indent self._right_margin = 64 # the amount of right indent
self._shadow_offset=5 self._shadow_offset = 5
self._outline_offset=2 self._outline_offset = 2
self._theme=None self.theme_name = None
self._bg_image_filename=None self._theme = None
self._paint=None self._bg_image_filename = None
self._path = path self._frame = None
self.img = None self._bg_frame = None
self.bg_image = None
def set_debug(self, debug): def set_debug(self, debug):
self._debug=debug self._debug=debug
def set_theme(self, theme): def set_theme(self, theme):
self._theme=theme """
External API to pass in the theme to be used
"""
log.debug(u'set theme')
self._theme = theme
self._bg_frame = None
self.theme_name = theme.theme_name
if theme.background_type == u'image': if theme.background_type == u'image':
if self._path is not None: if theme.background_filename is not None:
self.set_bg_image(theme.background_filename) self.set_bg_image(theme.background_filename)
def set_bg_image(self, filename): def set_bg_image(self, filename):
log.debug(u'set bg image %s', filename) log.debug(u'set bg image %s', filename)
self._bg_image_filename = str(filename)
self._bg_image_filename=os.path.join(self._path, self._theme.theme_name, filename) if self._frame is not None:
print self._bg_image_filename
if self._paint is not None:
self.scale_bg_image() self.scale_bg_image()
def scale_bg_image(self): def scale_bg_image(self):
assert self._paint assert self._frame
i=QtGui.QImage(self._bg_image_filename) image = QtGui.QImage(self._bg_image_filename)
# rescale and offset # rescale and offset
imw=i.width() imw = image.width()
imh=i.height() imh = image.height()
print imw, imh dcw = self._frame.width()+1
dcw=self._paint.width()+1 dch = self._frame.height()
dch=self._paint.height() imratio = imw/float(imh)
imratio=imw/float(imh) dcratio = dcw/float(dch)
dcratio=dcw/float(dch)
log.debug(u'Image scaling params %s %s %s %s %s %s', imw, imh, imratio, dcw, dch, dcratio) log.debug(u'Image scaling params %s %s %s %s %s %s', imw, imh, imratio, dcw, dch, dcratio)
if imratio > dcratio: if imratio > dcratio:
scale=dcw/float(imw) scale = dcw/float(imw)
elif imratio < dcratio: elif imratio < dcratio:
scale=dch/float(imh) scale = dch/float(imh)
else: else:
scale=dcw/float(imw) # either will do scale = dcw/float(imw) # either will do
neww=int(round(imw*scale)) neww = int(round(imw*scale))
newh=int(round(imh*scale)) newh = int(round(imh*scale))
self.background_offsetx=(dcw-neww)/2 self.background_offsetx=(dcw-neww)/2
self.background_offsety=(dch-newh)/2 self.background_offsety=(dch-newh)/2
self.img=QtGui.QPixmap.fromImage(i.scaled(QtCore.QSize(neww, newh), Qt.Qt.KeepAspectRatio)) self.bg_image=QtGui.QPixmap.fromImage(image.scaled(QtCore.QSize(neww, newh), Qt.Qt.KeepAspectRatio))
def set_paint_dest(self, p): def set_frame_dest(self, frame_width, frame_height, preview=False):
log.debug(u'set paint dest (frame) w %d h %d',p.width(), p.height()) """
self._paint=p External API to pass the frame size to be painted
"""
if preview == True:
self._bg_frame = None
log.debug(u'set frame dest (frame) w %d h %d',frame_width, frame_height)
self._frame = QtGui.QPixmap(frame_width, frame_height)
if self._bg_image_filename is not None: if self._bg_image_filename is not None:
self.scale_bg_image() self.scale_bg_image()
if self._bg_frame is None:
self._render_background()
def format_slide(self, words, footer): def format_slide(self, words, footer):
"""
External API to sort out the text to pe placed on the frame
"""
log.debug(u'format_slide %s', words) log.debug(u'format_slide %s', words)
verses=[] verses = []
verses_text = words.splitlines() verses_text = words.split(u'\n\n')
for v in verses_text: for verse in verses_text:
lines=v.split(u'\n') lines = verse.split(u'\n')
verses.append(self.split_set_of_lines(lines, footer)[0]) verses.append(self.split_set_of_lines(lines, footer)[0])
self.words = verses self.words = verses
verses_text=[] verses_text = []
for v in verses: for v in verses:
verses_text.append(u'\n'.join(v).lstrip()) # remove first \n verses_text.append(u'\n'.join(v).lstrip()) # remove first \n
return verses_text return verses_text
def render_screen(self, screennum): def render_screen(self, screennum):
log.debug(u'render screen\n %s %s ', screennum, self.words[screennum]) log.debug(u'render screen\n %s %s ', screennum, self.words[screennum])
t=0.0 t = 0.0
words=self.words[screennum] words = self.words[screennum]
retval=self._render_lines(words) retval = self._render_lines(words)
return retval return retval
def set_text_rectangle(self, rect_main, rect_footer): def set_text_rectangle(self, rect_main, rect_footer):
""" Sets the rectangle within which text should be rendered""" """ Sets the rectangle within which text should be rendered"""
self._rect=rect_main self._rect = rect_main
self._rect_footer=rect_footer self._rect_footer = rect_footer
def _render_background(self): def _render_background(self):
"""
Generate a background frame to the same size as the frame to be used
Results cached for performance reasons.
"""
assert(self._theme) assert(self._theme)
assert(self._paint) self._bg_frame = QtGui.QPixmap(self._frame.width(), self._frame.height())
log.debug(u'render background %s ', self._theme.background_type) log.debug(u'render background %s ', self._theme.background_type)
bef = datetime.now() bef = datetime.now()
p=QtGui.QPainter() painter = QtGui.QPainter()
p.begin(self._paint) painter.begin(self._bg_frame)
if self._theme.background_type == u'solid': if self._theme.background_type == u'solid':
p.fillRect(self._paint.rect(), QtGui.QColor(self._theme.background_color)) painter.fillRect(self._frame.rect(), QtGui.QColor(self._theme.background_color))
elif self._theme.background_type == u'gradient' : # gradient elif self._theme.background_type == u'gradient' : # gradient
gradient = None gradient = None
if self._theme.background_direction == u'horizontal': if self._theme.background_direction == u'horizontal':
w = int(self._paint.width())/2 w = int(self._frame.width())/2
gradient = QtGui.QLinearGradient(w, 0, w, self._paint.height()) # vertical gradient = QtGui.QLinearGradient(w, 0, w, self._frame.height()) # vertical
elif self._theme.background_direction == u'vertical': elif self._theme.background_direction == u'vertical':
h = int(self._paint.height())/2 h = int(self._frame.height())/2
gradient = QtGui.QLinearGradient(0, h, self._paint.width(), h) # Horizontal gradient = QtGui.QLinearGradient(0, h, self._frame.width(), h) # Horizontal
else: else:
w = int(self._paint.width())/2 w = int(self._frame.width())/2
h = int(self._paint.height())/2 h = int(self._frame.height())/2
gradient = QtGui.QRadialGradient(w, h, w) # Circular gradient = QtGui.QRadialGradient(w, h, w) # Circular
gradient.setColorAt(0, QtGui.QColor(self._theme.background_startColor)) gradient.setColorAt(0, QtGui.QColor(self._theme.background_startColor))
gradient.setColorAt(1, QtGui.QColor(self._theme.background_endColor)) gradient.setColorAt(1, QtGui.QColor(self._theme.background_endColor))
p.setBrush(QtGui.QBrush(gradient)) painter.setBrush(QtGui.QBrush(gradient))
rectPath = QtGui.QPainterPath() rectPath = QtGui.QPainterPath()
max_x = self._paint.width() max_x = self._frame.width()
max_y = self._paint.height() max_y = self._frame.height()
rectPath.moveTo(0, 0) rectPath.moveTo(0, 0)
rectPath.lineTo(0, max_y) rectPath.lineTo(0, max_y)
rectPath.lineTo(max_x, max_y) rectPath.lineTo(max_x, max_y)
rectPath.lineTo(max_x, 0) rectPath.lineTo(max_x, 0)
rectPath.closeSubpath() rectPath.closeSubpath()
p.drawPath(rectPath) painter.drawPath(rectPath)
elif self._theme.background_type== u'image': # image elif self._theme.background_type== u'image': # image
r=self._paint.rect() r = self._frame.rect()
log.debug(u'Image size details %d %d %d %d ', r.x(), r.y(), r.width(),r.height()) log.debug(u'Image size details %d %d %d %d ', r.x(), r.y(), r.width(),r.height())
#log.debug(u' Background Parameter %d ', self._theme.background_color1) #log.debug(u' Background Parameter %d ', self._theme.background_color1)
#if self._theme.background_color1 is not None: #if self._theme.background_color1 is not None:
# p.fillRect(self._paint.rect(), self._theme.background_borderColor) # p.fillRect(self._frame.rect(), self._theme.background_borderColor)
if self.img is not None: if self.bg_image is not None:
p.drawPixmap(self.background_offsetx,self.background_offsety, self.img) painter.drawPixmap(self.background_offsetx,self.background_offsety, self.bg_image)
else: else:
p.fillRect(self._paint.rect(), QtGui.QColor(u'#000000')) painter.fillRect(self._frame.rect(), QtGui.QColor(u'#000000'))
p.end() painter.end()
aft = datetime.now() aft = datetime.now()
print "background time", bef, aft, aft-bef print "background time", bef, aft, aft-bef
log.debug(u'render background finish') log.debug(u'render background finish')
def split_set_of_lines(self, lines, footer): def split_set_of_lines(self, lines, footer):
@ -186,71 +203,68 @@ class Renderer:
- this is done by splitting at 1/2, 1/3 or 1/4 of the set - this is done by splitting at 1/2, 1/3 or 1/4 of the set
If it doesn't fit, even at this size, just split at each opportunity If it doesn't fit, even at this size, just split at each opportunity
We'll do this by getting the bounding box of each lline, and then summing them appropriately We'll do this by getting the bounding box of each line, and then summing them appropriately
Returns a list of [lists of lines], one set for each screenful Returns a list of [lists of lines], one set for each screenful
""" """
log.debug(u'Split set of lines') log.debug(u'Split set of lines')
# Probably ought to save the rendering results to a pseudoDC for redrawing efficiency. But let's not optimse prematurely!
bboxes = [] bboxes = []
for line in lines: for line in lines:
bboxes.append(self._render_single_line(line, footer)) bboxes.append(self._render_single_line(line, footer))
numlines=len(lines)
bottom=self._rect.bottom() numlines = len(lines)
bottom = self._rect.bottom()
for ratio in (numlines, numlines/2, numlines/3, numlines/4): for ratio in (numlines, numlines/2, numlines/3, numlines/4):
good=1 good = 1
startline=0 startline = 0
endline=startline+ratio endline = startline + ratio
while (endline<=numlines): while (endline <= numlines):
by=0 by = 0
for (x, y) in bboxes[startline:endline]: for (x, y) in bboxes[startline:endline]:
by+=y by += y
if by > bottom: if by > bottom:
good=0 good=0
break break
startline+=ratio startline += ratio
endline=startline+ratio endline = startline+ratio
if good==1: if good == 1:
break break
retval=[] retval = []
numlines_per_page=ratio numlines_per_page = ratio
if good: if good:
c=0 c = 0
thislines=[] thislines = []
while c < numlines: while c < numlines:
thislines.append(lines[c]) thislines.append(lines[c])
c+=1 c += 1
if len(thislines) == numlines_per_page: if len(thislines) == numlines_per_page:
retval.append(thislines) retval.append(thislines)
thislines=[] thislines = []
else: else:
# log.debug(u" "Just split where you can" # log.debug(u" "Just split where you can"
retval=[] retval = []
startline=0 startline = 0
endline=startline+1 endline = startline+1
while (endline<=numlines): while (endline <= numlines):
by=0 by = 0
for (x, y) in bboxes[startline:endline]: for (x, y) in bboxes[startline:endline]:
by+=y by += y
if by > bottom: if by > bottom:
retval.append(lines[startline:endline-1]) retval.append(lines[startline:endline-1])
startline=endline-1 startline = endline-1
endline=startline # gets incremented below endline = startline # gets incremented below
by=0 by = 0
endline+=1 endline += 1
return retval return retval
def _correctAlignment(self, rect, bbox): def _correctAlignment(self, rect, bbox):
x=rect.left() x = rect.left()
if int(self._theme.display_verticalAlign) == 0: # top align if int(self._theme.display_verticalAlign) == 0: # top align
y = rect.top() y = rect.top()
elif int(self._theme.display_verticalAlign) == 2: # bottom align elif int(self._theme.display_verticalAlign) == 2: # bottom align
y=rect.bottom()-bbox.height() y = rect.bottom()-bbox.height()
elif int(self._theme.display_verticalAlign) == 1: # centre align elif int(self._theme.display_verticalAlign) == 1: # centre align
y=rect.top()+(rect.height()-bbox.height())/2 y = rect.top()+(rect.height()-bbox.height())/2
else: else:
assert(0, u'Invalid value for theme.VerticalAlign:%s' % self._theme.display_verticalAlign) assert(0, u'Invalid value for theme.VerticalAlign:%s' % self._theme.display_verticalAlign)
return x, y return x, y
@ -259,51 +273,53 @@ class Renderer:
"""render a set of lines according to the theme, return bounding box""" """render a set of lines according to the theme, return bounding box"""
log.debug(u'render_lines - Start') log.debug(u'render_lines - Start')
bbox=self._render_lines_unaligned(lines, False) # Main font bbox = self._render_lines_unaligned(lines, False) # Main font
if footer_lines is not None: if footer_lines is not None:
bbox1=self._render_lines_unaligned(footer_lines, True) # Footer Font bbox1 = self._render_lines_unaligned(footer_lines, True) # Footer Font
self._frame = QtGui.QPixmap(self._bg_frame)
# put stuff on background so need to reset before doing the job properly.
self._render_background()
x, y = self._correctAlignment(self._rect, bbox) x, y = self._correctAlignment(self._rect, bbox)
bbox=self._render_lines_unaligned(lines, False, (x, y)) bbox = self._render_lines_unaligned(lines, False, (x, y))
if footer_lines is not None: if footer_lines is not None:
bbox=self._render_lines_unaligned(footer_lines, True, (self._rect_footer.left(), self._rect_footer.top()) ) bbox = self._render_lines_unaligned(footer_lines, True, (self._rect_footer.left(), self._rect_footer.top()) )
log.debug(u'render_lines- Finish') log.debug(u'render_lines- Finish')
return bbox
return self._frame
def _render_lines_unaligned(self, lines, footer, tlcorner=(0,0)): def _render_lines_unaligned(self, lines, footer, tlcorner=(0,0)):
"""
"""Given a list of lines to render, render each one in turn Given a list of lines to render, render each one in turn
(using the _render_single_line fn - which may result in going (using the _render_single_line fn - which may result in going
off the bottom) They are expected to be pre-arranged to less off the bottom) They are expected to be pre-arranged to less
than a screenful (eg. by using split_set_of_lines) than a screenful (eg. by using split_set_of_lines)
Returns the bounding box of the text as QRect""" Returns the bounding box of the text as QRect
"""
log.debug(u'render lines unaligned Start') log.debug(u'render lines unaligned Start')
x, y=tlcorner x, y = tlcorner
brx=x brx = x
bry=y bry = y
for line in lines: for line in lines:
# render after current bottom, but at original left edge # render after current bottom, but at original left edge
# keep track of right edge to see which is biggest # keep track of right edge to see which is biggest
(thisx, bry) = self._render_single_line(line, footer, (x,bry)) (thisx, bry) = self._render_single_line(line, footer, (x , bry))
if (thisx > brx): if (thisx > brx):
brx=thisx brx = thisx
retval=QtCore.QRect(x, y,brx-x, bry-y) retval = QtCore.QRect(x, y,brx-x, bry-y)
if self._debug: if self._debug:
p=QtGui.QPainter() painter = QtGui.QPainter()
p.begin(self._paint) painter.begin(self._frame)
p.setPen(QtGui.QPen(QtGui.QColor(0,0,255))) painter.setPen(QtGui.QPen(QtGui.QColor(0,0,255)))
p.drawRect(retval) painter.drawRect(retval)
p.end() painter.end()
log.debug(u'render lines unaligned Finish') log.debug(u'render lines unaligned Finish')
return retval return retval
def _render_single_line(self, line, footer, tlcorner=(0,0)): def _render_single_line(self, line, footer, tlcorner=(0,0)):
"""
"""render a single line of words onto the DC, top left corner Render a single line of words onto the DC, top left corner
specified. specified.
If the line is too wide for the context, it wraps, but If the line is too wide for the context, it wraps, but
@ -312,139 +328,147 @@ class Renderer:
Returns the bottom-right corner (of what was rendered) as a tuple(x, y). Returns the bottom-right corner (of what was rendered) as a tuple(x, y).
""" """
log.debug(u'Render single line %s @ %s '%( line, tlcorner)) log.debug(u'Render single line %s @ %s '%( line, tlcorner))
x, y=tlcorner x, y = tlcorner
# We draw the text to see how big it is and then iterate to make it fit # We draw the text to see how big it is and then iterate to make it fit
# when we line wrap we do in in the "lyrics" style, so the second line is # when we line wrap we do in in the "lyrics" style, so the second line is
# right aligned with a "hanging indent" # right aligned with a "hanging indent"
words = line.split(u' ')
# get the words thisline = u' '.join(words)
# log.debug(u" "Getting the words split right" lastword = len(words)
words=line.split(u' ') lines = []
thisline=u' '.join(words) maxx = self._rect.width();
lastword=len(words) maxy = self._rect.height();
lines=[]
maxx=self._rect.width(); maxy=self._rect.height();
while (len(words)>0): while (len(words)>0):
w,h=self._get_extent_and_render(thisline, footer) w , h = self._get_extent_and_render(thisline, footer)
rhs=w+x rhs = w + x
if rhs < maxx-self._right_margin: if rhs < maxx-self._right_margin:
lines.append(thisline) lines.append(thisline)
words=words[lastword:] words = words[lastword:]
thisline=' '.join(words) thisline = ' '.join(words)
lastword=len(words) lastword = len(words)
else: else:
lastword-=1 lastword -= 1
thisline=' '.join(words[:lastword]) thisline = ' '.join(words[:lastword])
startx=x startx = x
starty=y starty = y
rightextent=None rightextent = None
t=self._theme
if footer: # dont allow alignment messing with footers if footer: # dont allow alignment messing with footers
align = 0 align = 0
else: else:
align=t.display_horizontalAlign align = int(self._theme .display_horizontalAlign)
wrapstyle=t.display_wrapStyle
for linenum in range(len(lines)): for linenum in range(len(lines)):
line=lines[linenum] line = lines[linenum]
#find out how wide line is #find out how wide line is
w,h=self._get_extent_and_render(line, footer, tlcorner=(x, y), draw=False) w , h = self._get_extent_and_render(line, footer, tlcorner=(x, y), draw=False)
if self._theme.display_shadow:
if t.display_shadow: w += self._shadow_offset
w+=self._shadow_offset h += self._shadow_offset
h+=self._shadow_offset if self._theme.display_outline:
if t.display_outline: w += 2*self._outline_offset # pixels either side
w+=2*self._outline_offset # pixels either side h += 2*self._outline_offset # pixels top/bottom
h+=2*self._outline_offset # pixels top/bottom if align == 0: # left align
if align==0: # left align rightextent = x + w
rightextent=x+w if self._theme.display_wrapStyle == 1 and linenum != 0: # shift right from last line's rh edge
if wrapstyle==1 and linenum != 0: # shift right from last line's rh edge rightextent = self._first_line_right_extent + self._right_margin
rightextent=self._first_line_right_extent + self._right_margin
if rightextent > maxx: if rightextent > maxx:
rightextent = maxx rightextent = maxx
x = rightextent-w x = rightextent - w
elif align == 1: # right align
elif align==1: # right align rightextent = maxx
rightextent=maxx x = maxx-w
x=maxx-w elif align == 2: # centre
elif align==2: # centre x = (maxx-w) / 2;
x=(maxx-w)/2; rightextent = x+w
rightextent=x+w
# now draw the text, and any outlines/shadows # now draw the text, and any outlines/shadows
if t.display_shadow: if self._theme.display_shadow:
self._get_extent_and_render(line, footer,tlcorner=(x+self._shadow_offset,y+self._shadow_offset), self._get_extent_and_render(line, footer,tlcorner=(x+self._shadow_offset,y+self._shadow_offset),
draw=True, color = t.display_shadow_color) draw=True, color = self._theme.display_shadow_color)
if t.display_outline: if self._theme.display_outline:
self._get_extent_and_render(line, footer,(x+self._outline_offset,y), draw=True, color = t.display_outline_color) self._get_extent_and_render(line, footer,(x+self._outline_offset,y), draw=True,
self._get_extent_and_render(line, footer,(x, y+self._outline_offset), draw=True, color = t.display_outline_color) color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer,(x, y-self._outline_offset), draw=True, color = t.display_outline_color) self._get_extent_and_render(line, footer,(x, y+self._outline_offset), draw=True,
self._get_extent_and_render(line, footer,(x-self._outline_offset,y), draw=True, color = t.display_outline_color) color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer,(x, y-self._outline_offset), draw=True,
color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer,(x-self._outline_offset,y), draw=True,
color = self._theme.display_outline_color)
if self._outline_offset > 1: if self._outline_offset > 1:
self._get_extent_and_render(line, footer,(x+self._outline_offset,y+self._outline_offset), draw=True, color = t.display_outline_color) self._get_extent_and_render(line, footer,(x+self._outline_offset,y+self._outline_offset), draw=True,
self._get_extent_and_render(line, footer,(x-self._outline_offset,y+self._outline_offset), draw=True, color = t.display_outline_color) color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer,(x+self._outline_offset,y-self._outline_offset), draw=True, color = t.display_outline_color) self._get_extent_and_render(line, footer,(x-self._outline_offset,y+self._outline_offset), draw=True,
self._get_extent_and_render(line, footer,(x-self._outline_offset,y-self._outline_offset), draw=True, color = t.display_outline_color) color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer,(x+self._outline_offset,y-self._outline_offset), draw=True,
color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer,(x-self._outline_offset,y-self._outline_offset), draw=True,
color = self._theme.display_outline_color)
self._get_extent_and_render(line, footer,tlcorner=(x, y), draw=True) self._get_extent_and_render(line, footer,tlcorner=(x, y), draw=True)
# log.debug(u'Line %2d: Render '%s' at (%d, %d) wh=(%d,%d)' % ( linenum, line, x, y,w,h)
y += h y += h
if linenum == 0: if linenum == 0:
self._first_line_right_extent=rightextent self._first_line_right_extent = rightextent
# draw a box around the text - debug only # draw a box around the text - debug only
if self._debug: if self._debug:
p=QtGui.QPainter() painter = QtGui.QPainter()
p.begin(self._paint) painter.begin(self._frame)
p.setPen(QtGui.QPen(QtGui.QColor(0,255,0))) painter.setPen(QtGui.QPen(QtGui.QColor(0,255,0)))
p.drawRect(startx,starty,rightextent-startx, y-starty) painter.drawRect(startx , starty , rightextent-startx , y-starty)
p.end() painter.end()
brcorner=(rightextent,y) brcorner = (rightextent , y)
log.debug(u'Render single line Finish') log.debug(u'Render single line Finish')
return brcorner return brcorner
# xxx this is what to override for an SDL version # xxx this is what to override for an SDL version
def _get_extent_and_render(self, line, footer, tlcorner=(0,0), draw=False, color=None): def _get_extent_and_render(self, line, footer, tlcorner=(0,0), draw=False, color=None):
"""Find bounding box of text - as render_single_line. """
Find bounding box of text - as render_single_line.
If draw is set, actually draw the text to the current DC as well If draw is set, actually draw the text to the current DC as well
return width and height of text as a tuple (w,h)""" return width and height of text as a tuple (w,h)
"""
# setup defaults # setup defaults
#log.debug(u'_get_extent_and_render %s %s %s ', [line], tlcorner, draw) #log.debug(u'_get_extent_and_render %s %s %s ', [line], tlcorner, draw)
p=QtGui.QPainter() painter = QtGui.QPainter()
p.begin(self._paint) painter.begin(self._frame)
# 'twould be more efficient to set this once when theme changes # 'twould be more efficient to set this once when theme changes
# or p changes # or p changes
if footer : if footer :
font=QtGui.QFont(self._theme.font_footer_name, font = QtGui.QFont(self._theme.font_footer_name,
int(self._theme.font_footer_proportion), # size int(self._theme.font_footer_proportion), # size
QtGui.QFont.Normal, # weight QtGui.QFont.Normal, # weight
0)# italic 0)# italic
font.setPixelSize(int(self._theme.font_footer_proportion))
else: else:
font=QtGui.QFont(self._theme.font_main_name, font = QtGui.QFont(self._theme.font_main_name,
int(self._theme.font_main_proportion), # size int(self._theme.font_main_proportion), # size
QtGui.QFont.Normal, # weight QtGui.QFont.Normal, # weight
0)# italic 0)# italic
# to make the unit tests monitor independent, we have to be able to
# specify whether a font proportion is in pixels or points
if footer:
font.setPixelSize(int(self._theme.font_footer_proportion))
else:
font.setPixelSize(int(self._theme.font_main_proportion)) font.setPixelSize(int(self._theme.font_main_proportion))
#log.debug(u'Font details %s %s %s %d', self._theme.font_main_name, self._theme.font_main_proportion, font.family(), font.pointSize()) #log.debug(u'Font details %s %s %s %d', self._theme.font_main_name, self._theme.font_main_proportion, font.family(), font.pointSize())
p.setFont(font) painter.setFont(font)
if color == None: if color == None:
if footer: if footer:
p.setPen(QtGui.QColor(self._theme.font_footer_color)) painter.setPen(QtGui.QColor(self._theme.font_footer_color))
else: else:
p.setPen(QtGui.QColor(self._theme.font_main_color)) painter.setPen(QtGui.QColor(self._theme.font_main_color))
else: else:
p.setPen(QtGui.QColor(color)) painter.setPen(QtGui.QColor(color))
x, y=tlcorner x, y = tlcorner
metrics=QtGui.QFontMetrics(font) metrics=QtGui.QFontMetrics(font)
# xxx some fudges to make it exactly like wx! Take 'em out later # xxx some fudges to make it exactly like wx! Take 'em out later
w=metrics.width(line) w = metrics.width(line)
h=metrics.height()-2 h = metrics.height()-2
if draw: if draw:
p.drawText(x, y+metrics.height()-metrics.descent()-1, line) painter.drawText(x, y+metrics.height()-metrics.descent()-1, line)
p.end() painter.end()
return (w, h) return (w, h)
def snoop_Image(self, image, image2=None):
"""
Debugging method to allow images to be viewed
"""
im = image.toImage()
im.save("renderer.png", "png")
if image2 is not None:
im = image2.toImage()
im.save("renderer2.png", "png")

View File

@ -29,6 +29,9 @@ import sys
import linecache import linecache
def traceit(frame, event, arg): def traceit(frame, event, arg):
"""
Code to allow calls to be traced by python runtime
"""
if event == "line": if event == "line":
lineno = frame.f_lineno lineno = frame.f_lineno
filename = frame.f_globals["__file__"] filename = frame.f_globals["__file__"]
@ -59,7 +62,7 @@ class RenderManager:
self.theme_manager = theme_manager self.theme_manager = theme_manager
self.displays = len(screen_list) self.displays = len(screen_list)
self.current_display = 0 self.current_display = 0
self.renderer = Renderer(None) self.renderer = Renderer()
self.calculate_default(self.screen_list[self.current_display]['size']) self.calculate_default(self.screen_list[self.current_display]['size'])
def set_override_theme(self, theme): def set_override_theme(self, theme):
@ -68,11 +71,12 @@ class RenderManager:
self.theme = theme self.theme = theme
else: else:
self.theme = self.default_theme self.theme = self.default_theme
log.debug(u'theme is now %s', self.theme) if self.theme != self.renderer.theme_name:
self.themedata = self.theme_manager.getThemeData(self.theme) log.debug(u'theme is now %s', self.theme)
self.calculate_default(self.screen_list[self.current_display]['size']) self.themedata = self.theme_manager.getThemeData(self.theme)
self.renderer.set_theme(self.themedata) self.calculate_default(self.screen_list[self.current_display]['size'])
self.build_text_rectangle(self.themedata) self.renderer.set_theme(self.themedata)
self.build_text_rectangle(self.themedata)
def build_text_rectangle(self, theme): def build_text_rectangle(self, theme):
log.debug(u'build_text_rectangle ') log.debug(u'build_text_rectangle ')
@ -95,50 +99,52 @@ class RenderManager:
def generate_preview(self, themedata): def generate_preview(self, themedata):
log.debug(u'generate preview') log.debug(u'generate preview')
self.calculate_default(QtCore.QSize(800,600)) self.calculate_default(QtCore.QSize(800, 600))
self.renderer.set_theme(themedata) self.renderer.set_theme(themedata)
self.build_text_rectangle(themedata) self.build_text_rectangle(themedata)
frame = QtGui.QPixmap(self.width, self.height) self.renderer.set_frame_dest(self.width, self.height, True)
self.renderer.set_paint_dest(frame)
lines=[] lines = []
lines.append(u'Amazing Grace!') lines.append(u'Amazing Grace!')
lines.append(u'How sweet the sound') lines.append(u'How sweet the sound')
lines.append(u'To save a wretch like me;') lines.append(u'To save a wretch like me;')
lines.append(u'I once was lost but now am found,') lines.append(u'I once was lost but now am found,')
lines.append(u'Was blind, but now I see.') lines.append(u'Was blind, but now I see.')
lines1=[] lines1 = []
lines1.append(u'Amazing Grace (John Newton)' ) lines1.append(u'Amazing Grace (John Newton)' )
lines1.append(u'CCLI xxx (c)Openlp.org') lines1.append(u'Public Domain')
answer=self.renderer.render_lines(lines, lines1) lines1.append(u'CCLI xxx')
return frame return self.renderer.render_lines(lines, lines1)
def format_slide(self, words, footer): def format_slide(self, words, footer):
log.debug(u'format slide') log.debug(u'format slide')
self.calculate_default(self.screen_list[self.current_display]['size']) self.calculate_default(self.screen_list[self.current_display]['size'])
self.renderer.set_paint_dest(QtGui.QPixmap(self.width, self.height)) self.build_text_rectangle(self.themedata)
return self.renderer.format_slide(words, footer) self.renderer.set_frame_dest(self.width, self.height)
return self.renderer.format_slide(words, False)
def generate_slide(self,main_text, footer_text): def generate_slide(self,main_text, footer_text):
log.debug(u'generate slide') log.debug(u'generate slide')
#sys.settrace(traceit)
self.calculate_default(self.screen_list[self.current_display]['size']) self.calculate_default(self.screen_list[self.current_display]['size'])
self.build_text_rectangle(self.themedata)
bef = datetime.now() self.renderer.set_frame_dest(self.width, self.height)
frame = QtGui.QPixmap(self.width, self.height) return self.renderer.render_lines(main_text, footer_text)
aft = datetime.now()
print "framebuild time", bef, aft, aft-bef
self.renderer.set_paint_dest(frame)
answer=self.renderer.render_lines(main_text, footer_text)
#sys.settrace()
return frame
def calculate_default(self, screen): def calculate_default(self, screen):
log.debug(u'calculate default %s' , screen) log.debug(u'calculate default %s' , screen)
self.width = screen.width() self.width = screen.width()
self.height = screen.height() self.height = screen.height()
log.debug(u'calculate default %d,%d' , self.width, self.height) log.debug(u'calculate default %d,%d' , self.width, self.height)
self.footer_start = int(self.height*0.95) # 95% is start of footer self.footer_start = int(self.height*0.90) # 90% is start of footer
def snoop_Image(self, image, image2=None):
"""
Debugging method to allow images to be viewed
"""
im = image.toImage()
im.save("renderer.png", "png")
if image2 is not None:
im = image2.toImage()
im.save("renderer2.png", "png")

View File

@ -47,7 +47,7 @@ class ServiceItem():
self.frames = [] self.frames = []
self.raw_footer = None self.raw_footer = None
self.theme = None self.theme = None
log.debug(u'Service item created for %s', self.shortname) log.debug(u'Service item created for %s ', self.shortname)
def addIcon(self, icon): def addIcon(self, icon):
self.iconic_representation = buildIcon(icon) self.iconic_representation = buildIcon(icon)

View File

@ -21,7 +21,7 @@ from xml.etree.ElementTree import ElementTree, XML, dump
For XML Schema see wiki.openlp.org For XML Schema see wiki.openlp.org
""" """
import os, os.path
from openlp import convertStringToBoolean from openlp import convertStringToBoolean
from xml.dom.minidom import Document from xml.dom.minidom import Document
from xml.etree.ElementTree import ElementTree, XML, dump from xml.etree.ElementTree import ElementTree, XML, dump
@ -40,7 +40,7 @@ blankthemexml=\
<direction>vertical</direction> <direction>vertical</direction>
</background> </background>
<background type="image" mode="opaque"> <background type="image" mode="opaque">
<filename>fred.bmp</filename> <filename></filename>
</background> </background>
<font type="main"> <font type="main">
<name>Arial</name> <name>Arial</name>
@ -69,6 +69,10 @@ class ThemeXML():
# Create the minidom document # Create the minidom document
self.theme_xml = Document() self.theme_xml = Document()
def extend_filename(self, path):
if self.background_filename is not None:
self.background_filename = os.path.join(path, self.theme_name, self.background_filename)
def new_document(self, name): def new_document(self, name):
# Create the <song> base element # Create the <song> base element
self.theme = self.theme_xml.createElement(u'theme') self.theme = self.theme_xml.createElement(u'theme')

View File

@ -22,10 +22,8 @@ import os, os.path
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import QColor, QFont from PyQt4.QtGui import QColor, QFont
from openlp.core.lib import ThemeXML from openlp.core.lib import ThemeXML, Renderer
from openlp.core.lib import Renderer from openlp.core import fileToXML, translate
from openlp.core import fileToXML
from openlp.core import translate
from amendthemedialog import Ui_AmendThemeDialog from amendthemedialog import Ui_AmendThemeDialog
@ -53,6 +51,8 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
QtCore.SIGNAL("pressed()"), self.onOutlineColorPushButtonClicked) QtCore.SIGNAL("pressed()"), self.onOutlineColorPushButtonClicked)
QtCore.QObject.connect(self.ShadowColorPushButton, QtCore.QObject.connect(self.ShadowColorPushButton,
QtCore.SIGNAL("pressed()"), self.onShadowColorPushButtonClicked) QtCore.SIGNAL("pressed()"), self.onShadowColorPushButtonClicked)
QtCore.QObject.connect(self.ImageToolButton,
QtCore.SIGNAL("pressed()"), self.onImageToolButtonClicked)
#Combo boxes #Combo boxes
QtCore.QObject.connect(self.BackgroundComboBox, QtCore.QObject.connect(self.BackgroundComboBox,
@ -99,17 +99,22 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
QtCore.QObject.connect(self.ShadowCheckBox, QtCore.QObject.connect(self.ShadowCheckBox,
QtCore.SIGNAL("stateChanged(int)"), self.onShadowCheckBoxChanged) QtCore.SIGNAL("stateChanged(int)"), self.onShadowCheckBoxChanged)
def accept(self): def accept(self):
new_theme = ThemeXML() new_theme = ThemeXML()
theme_name = str(self.ThemeNameEdit.displayText()) theme_name = str(self.ThemeNameEdit.displayText())
new_theme.new_document(theme_name) new_theme.new_document(theme_name)
save_from = None
save_to = None
if self.theme.background_type == u'solid': if self.theme.background_type == u'solid':
new_theme.add_background_solid(str(self.theme.background_color)) new_theme.add_background_solid(str(self.theme.background_color))
elif self.theme.background_type == u'gradient': elif self.theme.background_type == u'gradient':
new_theme.add_background_gradient(str(self.theme.background_startColor), str(self.theme.background_endColor), self.theme.background_direction) new_theme.add_background_gradient(str(self.theme.background_startColor),
#else: str(self.theme.background_endColor), self.theme.background_direction)
#newtheme.add_background_image(str(self.theme.)) else:
(path, filename) =os.path.split(str(self.theme.background_filename))
new_theme.add_background_image(filename)
save_to= os.path.join(self.path, theme_name,filename )
save_from = self.theme.background_filename
new_theme.add_font(str(self.theme.font_main_name), str(self.theme.font_main_color), new_theme.add_font(str(self.theme.font_main_name), str(self.theme.font_main_color),
str(self.theme.font_main_proportion), str(self.theme.font_main_override),u'main', str(self.theme.font_main_proportion), str(self.theme.font_main_override),u'main',
@ -126,7 +131,7 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
theme = new_theme.extract_xml() theme = new_theme.extract_xml()
self.thememanager.saveTheme(theme_name, theme) self.thememanager.saveTheme(theme_name, theme, save_from, save_to)
return QtGui.QDialog.accept(self) return QtGui.QDialog.accept(self)
def themePath(self, path): def themePath(self, path):
@ -140,9 +145,17 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
xml_file = os.path.join(self.path, theme, theme+u'.xml') xml_file = os.path.join(self.path, theme, theme+u'.xml')
xml = fileToXML(xml_file) xml = fileToXML(xml_file)
self.theme.parse(xml) self.theme.parse(xml)
self.allowPreview = False
self.paintUi(self.theme) self.paintUi(self.theme)
self.allowPreview = True
self.previewTheme(self.theme) self.previewTheme(self.theme)
def onImageToolButtonClicked(self):
filename = QtGui.QFileDialog.getOpenFileName(self, 'Open file')
if filename != "":
self.ImageLineEdit.setText(filename)
self.theme.background_filename = filename
self.previewTheme(self.theme)
# #
#Main Font Tab #Main Font Tab
# #
@ -196,8 +209,6 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
def onFontMainHeightSpinBoxChanged(self, value): def onFontMainHeightSpinBoxChanged(self, value):
self.theme.font_main_height = value self.theme.font_main_height = value
self.previewTheme(self.theme) self.previewTheme(self.theme)
# #
#Footer Font Tab #Footer Font Tab
# #
@ -217,7 +228,6 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
self.theme.font_footer_proportion = value self.theme.font_footer_proportion = value
self.previewTheme(self.theme) self.previewTheme(self.theme)
def onFontFooterDefaultCheckBoxChanged(self, value): def onFontFooterDefaultCheckBoxChanged(self, value):
if value == 2: # checked if value == 2: # checked
self.theme.font_footer_override = False self.theme.font_footer_override = False
@ -516,5 +526,6 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
def previewTheme(self, theme): def previewTheme(self, theme):
frame = self.thememanager.generateImage(theme) if self.allowPreview:
self.ThemePreview.setPixmap(frame) frame = self.thememanager.generateImage(theme)
self.ThemePreview.setPixmap(frame)

View File

@ -60,9 +60,9 @@ class MainDisplay(QtGui.QWidget):
painter.fillRect(self.blankFrame.rect(), QtGui.QColor(u'#000000')) painter.fillRect(self.blankFrame.rect(), QtGui.QColor(u'#000000'))
def frameView(self, frame): def frameView(self, frame):
self.frame = frame
if self.displayBlank == False: if self.displayBlank == False:
self.display.setPixmap(frame) self.display.setPixmap(frame)
self.frame = frame
def blankDisplay(self): def blankDisplay(self):
if self.displayBlank == False: if self.displayBlank == False:
@ -71,7 +71,3 @@ class MainDisplay(QtGui.QWidget):
else: else:
self.displayBlank = False self.displayBlank = False
self.frameView(self.frame) self.frameView(self.frame)
def kill(self):
pass

View File

@ -37,6 +37,7 @@ class MainWindow(object):
def __init__(self, screens): def __init__(self, screens):
self.main_window = QtGui.QMainWindow() self.main_window = QtGui.QMainWindow()
self.main_window.__class__.closeEvent = self.onCloseEvent
self.main_display = MainDisplay(None, screens) self.main_display = MainDisplay(None, screens)
self.screen_list = screens self.screen_list = screens
self.EventManager = EventManager() self.EventManager = EventManager()
@ -89,23 +90,32 @@ class MainWindow(object):
# Once all components are initialised load the Themes # Once all components are initialised load the Themes
log.info(u'Load Themes and Managers') log.info(u'Load Themes and Managers')
self.PreviewController.eventManager = self.EventManager self.PreviewController.ServiceManager = self.ServiceManagerContents
self.PreviewController.serviceManager = self.ServiceManagerContents self.LiveController.ServiceManager = self.ServiceManagerContents
self.LiveController.eventManager = self.EventManager
self.LiveController.serviceManager = self.ServiceManagerContents self.ThemeManagerContents.EventManager = self.EventManager
self.ThemeManagerContents.eventManager = self.EventManager self.ThemeManagerContents.RenderManager = self.RenderManager
self.ThemeManagerContents.renderManager = self.RenderManager self.ThemeManagerContents.ServiceManager = self.ServiceManagerContents
self.ServiceManagerContents.renderManager = self.RenderManager #self.ThemeManagerContents.ThemesTab = self.ServiceManagerContents.ThemesTab
self.ServiceManagerContents.eventManager = self.EventManager
self.ServiceManagerContents.liveController = self.LiveController self.ServiceManagerContents.RenderManager = self.RenderManager
self.ServiceManagerContents.previewController = self.PreviewController self.ServiceManagerContents.EventManager = self.EventManager
self.ThemeManagerContents.serviceManager = self.ServiceManagerContents self.ServiceManagerContents.LiveController = self.LiveController
self.ServiceManagerContents.PreviewController = self.PreviewController
self.ThemeManagerContents.loadThemes() self.ThemeManagerContents.loadThemes()
# Initialise SlideControllers # Initialise SlideControllers
log.info(u'Set Up SlideControllers') log.info(u'Set Up SlideControllers')
self.LiveController.mainDisplay = self.main_display self.LiveController.mainDisplay = self.main_display
def onCloseEvent(self, event):
"""
Hook to close the main window and display windows on exit
"""
self.main_display.close()
event.accept()
def setupUi(self): def setupUi(self):
self.main_window.setObjectName(u'main_window') self.main_window.setObjectName(u'main_window')
self.main_window.resize(1087, 847) self.main_window.resize(1087, 847)

View File

@ -136,13 +136,13 @@ class ServiceManager(QtGui.QWidget):
pass pass
def onSaveService(self): def onSaveService(self):
Pass pass
def onLoadService(self): def onLoadService(self):
Pass pass
def onThemeComboBoxSelected(self, currentIndex): def onThemeComboBoxSelected(self, currentIndex):
self.renderManager.default_theme = self.ThemeComboBox.currentText() self.RenderManager.default_theme = self.ThemeComboBox.currentText()
def addServiceItem(self, item): def addServiceItem(self, item):
self.serviceItems.append({u'data': item, u'order': len(self.serviceItems)+1}) self.serviceItems.append({u'data': item, u'order': len(self.serviceItems)+1})
@ -162,11 +162,11 @@ class ServiceManager(QtGui.QWidget):
def makePreview(self): def makePreview(self):
item, count = self.findServiceItem() item, count = self.findServiceItem()
self.previewController.addServiceManagerItem(self.serviceItems[item][u'data'], count) self.PreviewController.addServiceManagerItem(self.serviceItems[item][u'data'], count)
def makeLive(self): def makeLive(self):
item, count = self.findServiceItem() item, count = self.findServiceItem()
self.liveController.addServiceManagerItem(self.serviceItems[item][u'data'], count) self.LiveController.addServiceManagerItem(self.serviceItems[item][u'data'], count)
def findServiceItem(self): def findServiceItem(self):
items = self.ServiceManagerList.selectedItems() items = self.ServiceManagerList.selectedItems()
@ -197,7 +197,7 @@ class ServiceManager(QtGui.QWidget):
link=event.mimeData() link=event.mimeData()
if link.hasText(): if link.hasText():
plugin = event.mimeData().text() plugin = event.mimeData().text()
self.eventManager.post_event(Event(EventType.LoadServiceItem, plugin)) self.EventManager.post_event(Event(EventType.LoadServiceItem, plugin))
def oos_as_text(self): def oos_as_text(self):
text=[] text=[]
@ -226,5 +226,5 @@ class ServiceManager(QtGui.QWidget):
self.ThemeComboBox.clear() self.ThemeComboBox.clear()
for theme in theme_list: for theme in theme_list:
self.ThemeComboBox.addItem(theme) self.ThemeComboBox.addItem(theme)
self.renderManager.default_theme = self.ThemeComboBox.currentText() self.RenderManager.default_theme = self.ThemeComboBox.currentText()

View File

@ -24,7 +24,6 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar from openlp.core.lib import OpenLPToolbar
from openlp.core import translate from openlp.core import translate
from openlp.core.lib import Event, EventType, EventManager
class SlideData(QtCore.QAbstractListModel): class SlideData(QtCore.QAbstractListModel):
""" """
@ -37,17 +36,13 @@ class SlideData(QtCore.QAbstractListModel):
def __init__(self): def __init__(self):
QtCore.QAbstractListModel.__init__(self) QtCore.QAbstractListModel.__init__(self)
self.items=[] self.items = []
self.rowheight=50 self.rowheight = 50
self.maximagewidth=self.rowheight*16/9.0; self.maximagewidth = self.rowheight * 16/9.0;
log.info(u'Starting') log.info(u'Starting')
def eventFilter(self, obj, event):
print obj, event
return false
def clear(self): def clear(self):
self.items=[] self.items = []
def columnCount(self, parent): def columnCount(self, parent):
return 1 return 1

View File

@ -222,8 +222,10 @@ class ThemeManager(QWidget):
for name in files: for name in files:
if name.endswith(u'.png'): if name.endswith(u'.png'):
self.themeData.addRow(os.path.join(self.path, name)) self.themeData.addRow(os.path.join(self.path, name))
self.eventManager.post_event(Event(EventType.ThemeListChanged)) self.EventManager.post_event(Event(EventType.ThemeListChanged))
self.serviceManager.updateThemeList(self.getThemes()) self.ServiceManager.updateThemeList(self.getThemes())
self.parent.settings_form.ThemesTab.updateThemeList(self.getThemes())
def getThemes(self): def getThemes(self):
return self.themeData.getList() return self.themeData.getList()
@ -244,6 +246,7 @@ class ThemeManager(QWidget):
xml = newtheme.extract_xml() xml = newtheme.extract_xml()
theme = ThemeXML() theme = ThemeXML()
theme.parse(xml) theme.parse(xml)
theme.extend_filename(self.path)
return theme return theme
def checkThemesExists(self, dir): def checkThemesExists(self, dir):
@ -331,9 +334,8 @@ class ThemeManager(QWidget):
str(theme.WrapStyle)) str(theme.WrapStyle))
return newtheme.extract_xml() return newtheme.extract_xml()
def saveTheme(self, name, theme_xml) : def saveTheme(self, name, theme_xml, image_from, image_to) :
log.debug(u'saveTheme %s %s', name, theme_xml) log.debug(u'saveTheme %s %s', name, theme_xml)
self.generateAndSaveImage(self.path, name, theme_xml)
theme_dir = os.path.join(self.path, name) theme_dir = os.path.join(self.path, name)
if os.path.exists(theme_dir) == False: if os.path.exists(theme_dir) == False:
os.mkdir(os.path.join(self.path, name)) os.mkdir(os.path.join(self.path, name))
@ -341,6 +343,9 @@ class ThemeManager(QWidget):
outfile = open(theme_file, u'w') outfile = open(theme_file, u'w')
outfile.write(theme_xml) outfile.write(theme_xml)
outfile.close() outfile.close()
if image_from is not None:
shutil.copyfile(image_from, image_to)
self.generateAndSaveImage(self.path, name, theme_xml)
self.themeData.clearItems() self.themeData.clearItems()
self.loadThemes() self.loadThemes()
@ -348,6 +353,7 @@ class ThemeManager(QWidget):
log.debug(u'generateAndSaveImage %s %s %s', dir, name, theme_xml) log.debug(u'generateAndSaveImage %s %s %s', dir, name, theme_xml)
theme = ThemeXML() theme = ThemeXML()
theme.parse(theme_xml) theme.parse(theme_xml)
theme.extend_filename(dir)
frame = self.generateImage(theme) frame = self.generateImage(theme)
im = frame.toImage() im = frame.toImage()
samplepathname = os.path.join(self.path, name + u'.png') samplepathname = os.path.join(self.path, name + u'.png')
@ -358,6 +364,6 @@ class ThemeManager(QWidget):
def generateImage(self, themedata): def generateImage(self, themedata):
log.debug(u'generateImage %s ', themedata) log.debug(u'generateImage %s ', themedata)
frame = self.renderManager.generate_preview(themedata) frame = self.RenderManager.generate_preview(themedata)
return frame return frame

View File

@ -105,3 +105,11 @@ class ThemesTab(SettingsTab):
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.')) 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.'))
self.GlobalLevelRadioButton.setText(translate(u'ThemesTab', u'Global level')) self.GlobalLevelRadioButton.setText(translate(u'ThemesTab', u'Global level'))
self.GlobalLevelLabel.setText(translate(u'ThemesTab', u'Use the global theme, overriding any themes associated wither either the service or the songs.')) self.GlobalLevelLabel.setText(translate(u'ThemesTab', u'Use the global theme, overriding any themes associated wither either the service or the songs.'))
def updateThemeList(self, theme_list):
"""
Called from ThemeManager when the Themes have changed
"""
self.DefaultComboBox.clear()
for theme in theme_list:
self.DefaultComboBox.addItem(theme)

View File

@ -85,13 +85,13 @@ class BiblePlugin(Plugin):
log.debug(u'Handle event called with event %s with payload %s'%(event.event_type, event.payload)) log.debug(u'Handle event called with event %s with payload %s'%(event.event_type, event.payload))
if event.event_type == EventType.ThemeListChanged: if event.event_type == EventType.ThemeListChanged:
log.debug(u'New Theme request received') log.debug(u'New Theme request received')
#self.edit_custom_form.loadThemes(self.theme_manager.getThemes()) self.bibles_tab.updateThemeList(self.theme_manager.getThemes())
if event.event_type == EventType.LoadServiceItem and event.payload == 'Bibles': if event.event_type == EventType.LoadServiceItem and event.payload == 'Bibles':
log.debug(u'Load Service Item received') log.debug(u'Load Service Item received')
self.media_item.onBibleAddClick() self.media_item.onBibleAddClick()
if event.event_type == EventType.PreviewShow and event.payload == 'Bibles': if event.event_type == EventType.PreviewShow and event.payload == 'Bibles':
log.debug(u'Load Service Item received') log.debug(u'Load Preview Item received')
self.media_item.onBiblePreviewClick() self.media_item.onBiblePreviewClick()
if event.event_type == EventType.LiveShow and event.payload == 'Bibles': if event.event_type == EventType.LiveShow and event.payload == 'Bibles':
log.debug(u'Load Service Item received') log.debug(u'Load Live Show Item received')
self.media_item.onBibleLiveClick() self.media_item.onBibleLiveClick()

View File

@ -198,6 +198,7 @@ class BiblesTab(SettingsTab):
self.BibleThemeComboBox.setCurrentIndex(self.bible_theme) self.BibleThemeComboBox.setCurrentIndex(self.bible_theme)
else: else:
pass # TODO need to code pass # TODO need to code
self.bible_theme = None
def save(self): def save(self):
self.config.set_config("paragraph style", str(self.paragraph_style)) self.config.set_config("paragraph style", str(self.paragraph_style))
@ -205,3 +206,11 @@ class BiblesTab(SettingsTab):
self.config.set_config("display brackets", str(self.display_style)) self.config.set_config("display brackets", str(self.display_style))
self.config.set_config("search as type", str(self.bible_search)) self.config.set_config("search as type", str(self.bible_search))
self.config.set_config("bible theme", str(self.bible_theme)) self.config.set_config("bible theme", str(self.bible_theme))
def updateThemeList(self, theme_list):
"""
Called from ThemeManager when the Themes have changed
"""
self.BibleThemeComboBox.clear()
for theme in theme_list:
self.BibleThemeComboBox.addItem(theme)

View File

@ -369,13 +369,14 @@ class BibleMediaItem(MediaManagerItem):
def generateSlideData(self, service_item): def generateSlideData(self, service_item):
log.debug(u'Bible Preview Button pressed') log.debug(u'Bible Preview Button pressed')
items = self.BibleListView.selectedIndexes() items = self.BibleListView.selectedIndexes()
old_chapter = '' old_chapter = u''
raw_slides=[] raw_slides=[]
raw_footer = [] raw_footer = []
bible_text = u''
for item in items: for item in items:
text = self.BibleListData.getValue(item) text = self.BibleListData.getValue(item)
verse = text[:text.find("(")] verse = text[:text.find(u'(')]
bible = text[text.find("(") + 1:text.find(")")] bible = text[text.find(u'(') + 1:text.find(u')')]
self.searchByReference(bible, verse) self.searchByReference(bible, verse)
book = self.search_results[0][0] book = self.search_results[0][0]
chapter = str(self.search_results[0][1]) chapter = str(self.search_results[0][1])
@ -392,15 +393,15 @@ class BibleMediaItem(MediaManagerItem):
else: else:
loc = self.formatVerse(old_chapter, chapter, verse, u'', u'') loc = self.formatVerse(old_chapter, chapter, verse, u'', u'')
old_chapter = chapter old_chapter = chapter
raw_slides.append(loc + u' '+text) bible_text = bible_text + u' '+ loc + u' '+ text
service_item.title = book + u' ' + loc service_item.title = book + u' ' + loc
if len(raw_footer) <= 1: if len(raw_footer) <= 1:
raw_footer.append(book) raw_footer.append(book)
if len(raw_slides) > 0: service_item.theme = self.parent.bibles_tab.bible_theme
service_item.theme = None raw_slides.append(bible_text)
service_item.raw_slides = raw_slides service_item.raw_slides = raw_slides
service_item.raw_footer = raw_footer service_item.raw_footer = raw_footer
def formatVerse(self, old_chapter, chapter, verse, opening, closing): def formatVerse(self, old_chapter, chapter, verse, opening, closing):
loc = opening loc = opening

View File

@ -1,3 +1,22 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
"""
OpenLP - Open Source Lyrics Projection
Copyright (c) 2008 Raoul Snyman
Portions copyright (c) 2008-2009 Martin Thompson, Tim Bentley
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
"""
import logging import logging
from PyQt4.QtCore import * from PyQt4.QtCore import *
@ -6,7 +25,7 @@ from PyQt4.QtGui import *
class TextListData(QAbstractListModel): class TextListData(QAbstractListModel):
""" """
An abstract list of strings An abstract list of strings
""" """
global log global log
log=logging.getLogger(u'TextListData') log=logging.getLogger(u'TextListData')
@ -14,18 +33,18 @@ class TextListData(QAbstractListModel):
def __init__(self): def __init__(self):
QAbstractListModel.__init__(self) QAbstractListModel.__init__(self)
self.items=[] # will be a list of (database id , title) tuples self.items = [] # will be a list of (database id , title) tuples
def resetStore(self): def resetStore(self):
#reset list so can be reloaded #reset list so can be reloaded
self.items=[] self.items = []
def rowCount(self, parent): def rowCount(self, parent):
return len(self.items) return len(self.items)
def insertRow(self, row, id, title): def insertRow(self, row, id, title):
self.beginInsertRows(QModelIndex(),row,row) self.beginInsertRows(QModelIndex(),row,row)
log.debug("insert row %d:%s for id %d"%(row,title, id)) log.debug(u'insert row %d:%s for id %d'%(row,title, id))
self.items.insert(row, (id, title)) self.items.insert(row, (id, title))
self.endInsertRows() self.endInsertRows()
@ -36,18 +55,15 @@ class TextListData(QAbstractListModel):
def addRow(self, id, title): def addRow(self, id, title):
self.insertRow(len(self.items), id, title) self.insertRow(len(self.items), id, title)
def data(self, index, role): def data(self, index, role):
row=index.row() row=index.row()
if row > len(self.items): # if the last row is selected and deleted, we then get called with an empty row! if row > len(self.items): # if the last row is selected and deleted, we then get called with an empty row!
return QVariant() return QVariant()
if role==Qt.DisplayRole: if role == Qt.DisplayRole:
retval= self.items[row][1] retval = self.items[row][1]
# elif role == Qt.ToolTipRole: #not sure if need as it shows the database row number
# retval= self.items[row][0]
else: else:
retval= QVariant() retval = QVariant()
# log.info("Returning"+ str(retval))
if type(retval) is not type(QVariant): if type(retval) is not type(QVariant):
return QVariant(retval) return QVariant(retval)
else: else:
@ -60,10 +76,7 @@ class TextListData(QAbstractListModel):
def getValue(self, index): def getValue(self, index):
row = index.row() row = index.row()
return self.items[row][1] return self.items[row][1]
def deleteRow(self, index): def deleteRow(self, index):
row = index.row() row = index.row()
self.removeRow(row) self.removeRow(row)
if __name__=="__main__":
sxml=TextListData()

View File

@ -64,8 +64,8 @@ class CustomPlugin(Plugin):
log.debug(u'Load Service Item received') log.debug(u'Load Service Item received')
self.media_item.onCustomAddClick() self.media_item.onCustomAddClick()
if event.event_type == EventType.PreviewShow and event.payload == 'Custom': if event.event_type == EventType.PreviewShow and event.payload == 'Custom':
log.debug(u'Load Service Item received ') log.debug(u'Load Preview Item received ')
self.media_item.onCustomPreviewClick() self.media_item.onCustomPreviewClick()
if event.event_type == EventType.LiveShow and event.payload == 'Custom': if event.event_type == EventType.LiveShow and event.payload == 'Custom':
log.debug(u'Load Service Item received') log.debug(u'Load Live Show Item received')
self.media_item.onCustomLiveClick() self.media_item.onCustomLiveClick()

View File

@ -60,10 +60,10 @@ class ImagePlugin(Plugin):
log.debug(u'Load Service Item received') log.debug(u'Load Service Item received')
self.media_item.onImageAddClick() self.media_item.onImageAddClick()
if event.event_type == EventType.PreviewShow and event.payload == 'Image': if event.event_type == EventType.PreviewShow and event.payload == 'Image':
log.debug(u'Load Service Item received') log.debug(u'Load Preview Item received')
self.media_item.onImagePreviewClick() self.media_item.onImagePreviewClick()
if event.event_type == EventType.LiveShow and event.payload == 'Image': if event.event_type == EventType.LiveShow and event.payload == 'Image':
log.debug(u'Load Service Item received') log.debug(u'Load Live Show Item received')
self.media_item.onImageLiveClick() self.media_item.onImageLiveClick()

View File

@ -175,7 +175,7 @@ class ImageMediaItem(MediaManagerItem):
self.parent.live_controller.addServiceItem(service_item) self.parent.live_controller.addServiceItem(service_item)
def onImageAddClick(self): def onImageAddClick(self):
log.debug(u'Image Live Requested') log.debug(u'Image Add Requested')
service_item = ServiceItem(self.parent) service_item = ServiceItem(self.parent)
service_item.addIcon( ":/media/media_image.png") service_item.addIcon( ":/media/media_image.png")
service_item.render_manager = self.parent.render_manager service_item.render_manager = self.parent.render_manager

View File

@ -30,7 +30,7 @@ from openlp.plugins.media.lib import FileListData
class MediaMediaItem(MediaManagerItem): class MediaMediaItem(MediaManagerItem):
""" """
This is the custom media manager item for Custom Slides. This is the custom media manager item for Media Slides.
""" """
global log global log
log=logging.getLogger(u'MediaMediaItem') log=logging.getLogger(u'MediaMediaItem')
@ -93,13 +93,14 @@ class MediaMediaItem(MediaManagerItem):
translate('MediaMediaItem',u'&Add to Service'), self.onMediaAddClick)) translate('MediaMediaItem',u'&Add to Service'), self.onMediaAddClick))
def initialise(self): def initialise(self):
list = self.parent.config.load_list(u'Medias') list = self.parent.config.load_list(u'Media')
self.loadMediaList(list) self.loadMediaList(list)
def onMediaNewClick(self): def onMediaNewClick(self):
files = QtGui.QFileDialog.getOpenFileNames(None, files = QtGui.QFileDialog.getOpenFileNames(None,
translate('MediaMediaItem', u'Select Media(s) items'), translate('MediaMediaItem', u'Select Media(s) items'),
self.parent.config.get_last_dir(), u'Images (*.avi *.mpeg)') self.parent.config.get_last_dir(),
u'Images (*.avi *.mpeg);;Audio (*.mp3 *.ogg *.wma);;All files (*)')
if len(files) > 0: if len(files) > 0:
self.loadMediaList(files) self.loadMediaList(files)
dir, filename = os.path.split(str(files[0])) dir, filename = os.path.split(str(files[0]))

View File

@ -105,10 +105,6 @@ class SongsPlugin(Plugin):
QtCore.QObject.connect(self.ExportOpenlp1Item, QtCore.SIGNAL("triggered()"), self.onExportOpenlp1ItemClicked) QtCore.QObject.connect(self.ExportOpenlp1Item, QtCore.SIGNAL("triggered()"), self.onExportOpenlp1ItemClicked)
QtCore.QObject.connect(self.ExportOpenSongItem, QtCore.SIGNAL("triggered()"), self.onExportOpenSongItemClicked) QtCore.QObject.connect(self.ExportOpenSongItem, QtCore.SIGNAL("triggered()"), self.onExportOpenSongItemClicked)
def get_settings_tab(self):
self.SongsTab = SongsTab()
return self.SongsTab
def initialise(self): def initialise(self):
pass pass