forked from openlp/openlp
commit
713490896a
|
@ -54,6 +54,3 @@ class Event(object):
|
|||
def __init__(self, event_type=EventType.Default, payload=None):
|
||||
self.event_type = event_type
|
||||
self.payload = payload
|
||||
|
||||
def get_type(self):
|
||||
return self.event_type
|
||||
|
|
|
@ -40,7 +40,7 @@ class EventManager(object):
|
|||
self.endpoints.append(plugin)
|
||||
|
||||
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:
|
||||
point.handle_event(event)
|
||||
|
||||
|
|
|
@ -41,143 +41,160 @@ class Renderer:
|
|||
tell it to render a particular screenfull with render_screen(n)
|
||||
|
||||
"""
|
||||
def __init__(self, path=None):
|
||||
self._rect=None
|
||||
self._debug=0
|
||||
self.words=None
|
||||
def __init__(self):
|
||||
self._rect = None
|
||||
self._debug = 0
|
||||
self.words = None
|
||||
self._right_margin = 64 # the amount of right indent
|
||||
self._shadow_offset=5
|
||||
self._outline_offset=2
|
||||
self._theme=None
|
||||
self._bg_image_filename=None
|
||||
self._paint=None
|
||||
self._path = path
|
||||
self.img = None
|
||||
self._shadow_offset = 5
|
||||
self._outline_offset = 2
|
||||
self.theme_name = None
|
||||
self._theme = None
|
||||
self._bg_image_filename = None
|
||||
self._frame = None
|
||||
self._bg_frame = None
|
||||
self.bg_image = None
|
||||
|
||||
def set_debug(self, debug):
|
||||
self._debug=debug
|
||||
|
||||
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 self._path is not None:
|
||||
if theme.background_filename is not None:
|
||||
self.set_bg_image(theme.background_filename)
|
||||
|
||||
def set_bg_image(self, filename):
|
||||
log.debug(u'set bg image %s', filename)
|
||||
|
||||
self._bg_image_filename=os.path.join(self._path, self._theme.theme_name, filename)
|
||||
print self._bg_image_filename
|
||||
if self._paint is not None:
|
||||
self._bg_image_filename = str(filename)
|
||||
if self._frame is not None:
|
||||
self.scale_bg_image()
|
||||
|
||||
def scale_bg_image(self):
|
||||
assert self._paint
|
||||
i=QtGui.QImage(self._bg_image_filename)
|
||||
assert self._frame
|
||||
image = QtGui.QImage(self._bg_image_filename)
|
||||
# rescale and offset
|
||||
imw=i.width()
|
||||
imh=i.height()
|
||||
print imw, imh
|
||||
dcw=self._paint.width()+1
|
||||
dch=self._paint.height()
|
||||
imratio=imw/float(imh)
|
||||
dcratio=dcw/float(dch)
|
||||
imw = image.width()
|
||||
imh = image.height()
|
||||
dcw = self._frame.width()+1
|
||||
dch = self._frame.height()
|
||||
imratio = imw/float(imh)
|
||||
dcratio = dcw/float(dch)
|
||||
log.debug(u'Image scaling params %s %s %s %s %s %s', imw, imh, imratio, dcw, dch, dcratio)
|
||||
if imratio > dcratio:
|
||||
scale=dcw/float(imw)
|
||||
scale = dcw/float(imw)
|
||||
elif imratio < dcratio:
|
||||
scale=dch/float(imh)
|
||||
scale = dch/float(imh)
|
||||
else:
|
||||
scale=dcw/float(imw) # either will do
|
||||
neww=int(round(imw*scale))
|
||||
newh=int(round(imh*scale))
|
||||
scale = dcw/float(imw) # either will do
|
||||
neww = int(round(imw*scale))
|
||||
newh = int(round(imh*scale))
|
||||
self.background_offsetx=(dcw-neww)/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):
|
||||
log.debug(u'set paint dest (frame) w %d h %d',p.width(), p.height())
|
||||
self._paint=p
|
||||
def set_frame_dest(self, frame_width, frame_height, preview=False):
|
||||
"""
|
||||
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:
|
||||
self.scale_bg_image()
|
||||
if self._bg_frame is None:
|
||||
self._render_background()
|
||||
|
||||
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)
|
||||
verses=[]
|
||||
verses_text = words.splitlines()
|
||||
for v in verses_text:
|
||||
lines=v.split(u'\n')
|
||||
verses = []
|
||||
verses_text = words.split(u'\n\n')
|
||||
for verse in verses_text:
|
||||
lines = verse.split(u'\n')
|
||||
verses.append(self.split_set_of_lines(lines, footer)[0])
|
||||
self.words = verses
|
||||
verses_text=[]
|
||||
verses_text = []
|
||||
for v in verses:
|
||||
verses_text.append(u'\n'.join(v).lstrip()) # remove first \n
|
||||
return verses_text
|
||||
|
||||
def render_screen(self, screennum):
|
||||
log.debug(u'render screen\n %s %s ', screennum, self.words[screennum])
|
||||
t=0.0
|
||||
words=self.words[screennum]
|
||||
retval=self._render_lines(words)
|
||||
t = 0.0
|
||||
words = self.words[screennum]
|
||||
retval = self._render_lines(words)
|
||||
return retval
|
||||
|
||||
def set_text_rectangle(self, rect_main, rect_footer):
|
||||
""" Sets the rectangle within which text should be rendered"""
|
||||
self._rect=rect_main
|
||||
self._rect_footer=rect_footer
|
||||
self._rect = rect_main
|
||||
self._rect_footer = rect_footer
|
||||
|
||||
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._paint)
|
||||
self._bg_frame = QtGui.QPixmap(self._frame.width(), self._frame.height())
|
||||
log.debug(u'render background %s ', self._theme.background_type)
|
||||
bef = datetime.now()
|
||||
p=QtGui.QPainter()
|
||||
p.begin(self._paint)
|
||||
painter = QtGui.QPainter()
|
||||
painter.begin(self._bg_frame)
|
||||
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
|
||||
gradient = None
|
||||
if self._theme.background_direction == u'horizontal':
|
||||
w = int(self._paint.width())/2
|
||||
gradient = QtGui.QLinearGradient(w, 0, w, self._paint.height()) # vertical
|
||||
w = int(self._frame.width())/2
|
||||
gradient = QtGui.QLinearGradient(w, 0, w, self._frame.height()) # vertical
|
||||
elif self._theme.background_direction == u'vertical':
|
||||
h = int(self._paint.height())/2
|
||||
gradient = QtGui.QLinearGradient(0, h, self._paint.width(), h) # Horizontal
|
||||
h = int(self._frame.height())/2
|
||||
gradient = QtGui.QLinearGradient(0, h, self._frame.width(), h) # Horizontal
|
||||
else:
|
||||
w = int(self._paint.width())/2
|
||||
h = int(self._paint.height())/2
|
||||
w = int(self._frame.width())/2
|
||||
h = int(self._frame.height())/2
|
||||
gradient = QtGui.QRadialGradient(w, h, w) # Circular
|
||||
|
||||
gradient.setColorAt(0, QtGui.QColor(self._theme.background_startColor))
|
||||
gradient.setColorAt(1, QtGui.QColor(self._theme.background_endColor))
|
||||
|
||||
p.setBrush(QtGui.QBrush(gradient))
|
||||
painter.setBrush(QtGui.QBrush(gradient))
|
||||
rectPath = QtGui.QPainterPath()
|
||||
|
||||
max_x = self._paint.width()
|
||||
max_y = self._paint.height()
|
||||
max_x = self._frame.width()
|
||||
max_y = self._frame.height()
|
||||
rectPath.moveTo(0, 0)
|
||||
rectPath.lineTo(0, max_y)
|
||||
rectPath.lineTo(max_x, max_y)
|
||||
rectPath.lineTo(max_x, 0)
|
||||
|
||||
rectPath.closeSubpath()
|
||||
p.drawPath(rectPath)
|
||||
painter.drawPath(rectPath)
|
||||
|
||||
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' Background Parameter %d ', self._theme.background_color1)
|
||||
#if self._theme.background_color1 is not None:
|
||||
# p.fillRect(self._paint.rect(), self._theme.background_borderColor)
|
||||
if self.img is not None:
|
||||
p.drawPixmap(self.background_offsetx,self.background_offsety, self.img)
|
||||
# p.fillRect(self._frame.rect(), self._theme.background_borderColor)
|
||||
if self.bg_image is not None:
|
||||
painter.drawPixmap(self.background_offsetx,self.background_offsety, self.bg_image)
|
||||
else:
|
||||
p.fillRect(self._paint.rect(), QtGui.QColor(u'#000000'))
|
||||
p.end()
|
||||
painter.fillRect(self._frame.rect(), QtGui.QColor(u'#000000'))
|
||||
painter.end()
|
||||
aft = datetime.now()
|
||||
print "background time", bef, aft, aft-bef
|
||||
|
||||
log.debug(u'render background finish')
|
||||
|
||||
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
|
||||
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
|
||||
"""
|
||||
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 = []
|
||||
for line in lines:
|
||||
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):
|
||||
good=1
|
||||
startline=0
|
||||
endline=startline+ratio
|
||||
while (endline<=numlines):
|
||||
by=0
|
||||
good = 1
|
||||
startline = 0
|
||||
endline = startline + ratio
|
||||
while (endline <= numlines):
|
||||
by = 0
|
||||
for (x, y) in bboxes[startline:endline]:
|
||||
by+=y
|
||||
by += y
|
||||
if by > bottom:
|
||||
good=0
|
||||
break
|
||||
startline+=ratio
|
||||
endline=startline+ratio
|
||||
if good==1:
|
||||
startline += ratio
|
||||
endline = startline+ratio
|
||||
if good == 1:
|
||||
break
|
||||
|
||||
retval=[]
|
||||
numlines_per_page=ratio
|
||||
retval = []
|
||||
numlines_per_page = ratio
|
||||
if good:
|
||||
c=0
|
||||
thislines=[]
|
||||
c = 0
|
||||
thislines = []
|
||||
while c < numlines:
|
||||
thislines.append(lines[c])
|
||||
c+=1
|
||||
c += 1
|
||||
if len(thislines) == numlines_per_page:
|
||||
retval.append(thislines)
|
||||
thislines=[]
|
||||
thislines = []
|
||||
else:
|
||||
# log.debug(u" "Just split where you can"
|
||||
retval=[]
|
||||
startline=0
|
||||
endline=startline+1
|
||||
while (endline<=numlines):
|
||||
by=0
|
||||
retval = []
|
||||
startline = 0
|
||||
endline = startline+1
|
||||
while (endline <= numlines):
|
||||
by = 0
|
||||
for (x, y) in bboxes[startline:endline]:
|
||||
by+=y
|
||||
by += y
|
||||
if by > bottom:
|
||||
retval.append(lines[startline:endline-1])
|
||||
startline=endline-1
|
||||
endline=startline # gets incremented below
|
||||
by=0
|
||||
endline+=1
|
||||
|
||||
startline = endline-1
|
||||
endline = startline # gets incremented below
|
||||
by = 0
|
||||
endline += 1
|
||||
return retval
|
||||
|
||||
def _correctAlignment(self, rect, bbox):
|
||||
x=rect.left()
|
||||
x = rect.left()
|
||||
if int(self._theme.display_verticalAlign) == 0: # top align
|
||||
y = rect.top()
|
||||
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
|
||||
y=rect.top()+(rect.height()-bbox.height())/2
|
||||
y = rect.top()+(rect.height()-bbox.height())/2
|
||||
else:
|
||||
assert(0, u'Invalid value for theme.VerticalAlign:%s' % self._theme.display_verticalAlign)
|
||||
return x, y
|
||||
|
@ -259,51 +273,53 @@ class Renderer:
|
|||
"""render a set of lines according to the theme, return bounding box"""
|
||||
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:
|
||||
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)
|
||||
bbox=self._render_lines_unaligned(lines, False, (x, y))
|
||||
bbox = self._render_lines_unaligned(lines, False, (x, y))
|
||||
|
||||
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')
|
||||
return bbox
|
||||
|
||||
return self._frame
|
||||
|
||||
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
|
||||
off the bottom) They are expected to be pre-arranged to less
|
||||
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')
|
||||
x, y=tlcorner
|
||||
brx=x
|
||||
bry=y
|
||||
x, y = tlcorner
|
||||
brx = x
|
||||
bry = y
|
||||
for line in lines:
|
||||
# render after current bottom, but at original left edge
|
||||
# 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):
|
||||
brx=thisx
|
||||
retval=QtCore.QRect(x, y,brx-x, bry-y)
|
||||
brx = thisx
|
||||
retval = QtCore.QRect(x, y,brx-x, bry-y)
|
||||
if self._debug:
|
||||
p=QtGui.QPainter()
|
||||
p.begin(self._paint)
|
||||
p.setPen(QtGui.QPen(QtGui.QColor(0,0,255)))
|
||||
p.drawRect(retval)
|
||||
p.end()
|
||||
painter = QtGui.QPainter()
|
||||
painter.begin(self._frame)
|
||||
painter.setPen(QtGui.QPen(QtGui.QColor(0,0,255)))
|
||||
painter.drawRect(retval)
|
||||
painter.end()
|
||||
log.debug(u'render lines unaligned Finish')
|
||||
return retval
|
||||
|
||||
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.
|
||||
|
||||
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).
|
||||
"""
|
||||
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
|
||||
# when we line wrap we do in in the "lyrics" style, so the second line is
|
||||
# right aligned with a "hanging indent"
|
||||
|
||||
# get the words
|
||||
# log.debug(u" "Getting the words split right"
|
||||
words=line.split(u' ')
|
||||
thisline=u' '.join(words)
|
||||
lastword=len(words)
|
||||
lines=[]
|
||||
maxx=self._rect.width(); maxy=self._rect.height();
|
||||
words = line.split(u' ')
|
||||
thisline = u' '.join(words)
|
||||
lastword = len(words)
|
||||
lines = []
|
||||
maxx = self._rect.width();
|
||||
maxy = self._rect.height();
|
||||
while (len(words)>0):
|
||||
w,h=self._get_extent_and_render(thisline, footer)
|
||||
rhs=w+x
|
||||
w , h = self._get_extent_and_render(thisline, footer)
|
||||
rhs = w + x
|
||||
if rhs < maxx-self._right_margin:
|
||||
lines.append(thisline)
|
||||
words=words[lastword:]
|
||||
thisline=' '.join(words)
|
||||
lastword=len(words)
|
||||
words = words[lastword:]
|
||||
thisline = ' '.join(words)
|
||||
lastword = len(words)
|
||||
else:
|
||||
lastword-=1
|
||||
thisline=' '.join(words[:lastword])
|
||||
startx=x
|
||||
starty=y
|
||||
rightextent=None
|
||||
t=self._theme
|
||||
lastword -= 1
|
||||
thisline = ' '.join(words[:lastword])
|
||||
startx = x
|
||||
starty = y
|
||||
rightextent = None
|
||||
if footer: # dont allow alignment messing with footers
|
||||
align = 0
|
||||
else:
|
||||
align=t.display_horizontalAlign
|
||||
|
||||
wrapstyle=t.display_wrapStyle
|
||||
align = int(self._theme .display_horizontalAlign)
|
||||
|
||||
for linenum in range(len(lines)):
|
||||
line=lines[linenum]
|
||||
line = lines[linenum]
|
||||
#find out how wide line is
|
||||
w,h=self._get_extent_and_render(line, footer, tlcorner=(x, y), draw=False)
|
||||
|
||||
if t.display_shadow:
|
||||
w+=self._shadow_offset
|
||||
h+=self._shadow_offset
|
||||
if t.display_outline:
|
||||
w+=2*self._outline_offset # pixels either side
|
||||
h+=2*self._outline_offset # pixels top/bottom
|
||||
if align==0: # left align
|
||||
rightextent=x+w
|
||||
if wrapstyle==1 and linenum != 0: # shift right from last line's rh edge
|
||||
rightextent=self._first_line_right_extent + self._right_margin
|
||||
w , h = self._get_extent_and_render(line, footer, tlcorner=(x, y), draw=False)
|
||||
if self._theme.display_shadow:
|
||||
w += self._shadow_offset
|
||||
h += self._shadow_offset
|
||||
if self._theme.display_outline:
|
||||
w += 2*self._outline_offset # pixels either side
|
||||
h += 2*self._outline_offset # pixels top/bottom
|
||||
if align == 0: # left align
|
||||
rightextent = x + w
|
||||
if self._theme.display_wrapStyle == 1 and linenum != 0: # shift right from last line's rh edge
|
||||
rightextent = self._first_line_right_extent + self._right_margin
|
||||
if rightextent > maxx:
|
||||
rightextent = maxx
|
||||
x = rightextent-w
|
||||
|
||||
elif align==1: # right align
|
||||
rightextent=maxx
|
||||
x=maxx-w
|
||||
elif align==2: # centre
|
||||
x=(maxx-w)/2;
|
||||
rightextent=x+w
|
||||
x = rightextent - w
|
||||
elif align == 1: # right align
|
||||
rightextent = maxx
|
||||
x = maxx-w
|
||||
elif align == 2: # centre
|
||||
x = (maxx-w) / 2;
|
||||
rightextent = x+w
|
||||
# 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),
|
||||
draw=True, color = t.display_shadow_color)
|
||||
if t.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, 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, color = t.display_outline_color)
|
||||
self._get_extent_and_render(line, footer,(x-self._outline_offset,y), draw=True, color = t.display_outline_color)
|
||||
draw=True, color = self._theme.display_shadow_color)
|
||||
if self._theme.display_outline:
|
||||
self._get_extent_and_render(line, footer,(x+self._outline_offset,y), draw=True,
|
||||
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, 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:
|
||||
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, color = t.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, color = t.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,(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)
|
||||
# log.debug(u'Line %2d: Render '%s' at (%d, %d) wh=(%d,%d)' % ( linenum, line, x, y,w,h)
|
||||
y += h
|
||||
if linenum == 0:
|
||||
self._first_line_right_extent=rightextent
|
||||
self._first_line_right_extent = rightextent
|
||||
# draw a box around the text - debug only
|
||||
if self._debug:
|
||||
p=QtGui.QPainter()
|
||||
p.begin(self._paint)
|
||||
p.setPen(QtGui.QPen(QtGui.QColor(0,255,0)))
|
||||
p.drawRect(startx,starty,rightextent-startx, y-starty)
|
||||
p.end()
|
||||
painter = QtGui.QPainter()
|
||||
painter.begin(self._frame)
|
||||
painter.setPen(QtGui.QPen(QtGui.QColor(0,255,0)))
|
||||
painter.drawRect(startx , starty , rightextent-startx , y-starty)
|
||||
painter.end()
|
||||
|
||||
brcorner=(rightextent,y)
|
||||
brcorner = (rightextent , y)
|
||||
log.debug(u'Render single line Finish')
|
||||
return brcorner
|
||||
|
||||
# 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):
|
||||
"""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
|
||||
return width and height of text as a tuple (w,h)"""
|
||||
return width and height of text as a tuple (w,h)
|
||||
"""
|
||||
# setup defaults
|
||||
#log.debug(u'_get_extent_and_render %s %s %s ', [line], tlcorner, draw)
|
||||
p=QtGui.QPainter()
|
||||
p.begin(self._paint)
|
||||
painter = QtGui.QPainter()
|
||||
painter.begin(self._frame)
|
||||
# 'twould be more efficient to set this once when theme changes
|
||||
# or p changes
|
||||
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
|
||||
QtGui.QFont.Normal, # weight
|
||||
0)# italic
|
||||
font.setPixelSize(int(self._theme.font_footer_proportion))
|
||||
else:
|
||||
font=QtGui.QFont(self._theme.font_main_name,
|
||||
font = QtGui.QFont(self._theme.font_main_name,
|
||||
int(self._theme.font_main_proportion), # size
|
||||
QtGui.QFont.Normal, # weight
|
||||
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))
|
||||
#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 footer:
|
||||
p.setPen(QtGui.QColor(self._theme.font_footer_color))
|
||||
painter.setPen(QtGui.QColor(self._theme.font_footer_color))
|
||||
else:
|
||||
p.setPen(QtGui.QColor(self._theme.font_main_color))
|
||||
painter.setPen(QtGui.QColor(self._theme.font_main_color))
|
||||
else:
|
||||
p.setPen(QtGui.QColor(color))
|
||||
x, y=tlcorner
|
||||
painter.setPen(QtGui.QColor(color))
|
||||
x, y = tlcorner
|
||||
metrics=QtGui.QFontMetrics(font)
|
||||
# xxx some fudges to make it exactly like wx! Take 'em out later
|
||||
w=metrics.width(line)
|
||||
h=metrics.height()-2
|
||||
w = metrics.width(line)
|
||||
h = metrics.height()-2
|
||||
if draw:
|
||||
p.drawText(x, y+metrics.height()-metrics.descent()-1, line)
|
||||
p.end()
|
||||
painter.drawText(x, y+metrics.height()-metrics.descent()-1, line)
|
||||
painter.end()
|
||||
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")
|
||||
|
|
|
@ -29,6 +29,9 @@ import sys
|
|||
import linecache
|
||||
|
||||
def traceit(frame, event, arg):
|
||||
"""
|
||||
Code to allow calls to be traced by python runtime
|
||||
"""
|
||||
if event == "line":
|
||||
lineno = frame.f_lineno
|
||||
filename = frame.f_globals["__file__"]
|
||||
|
@ -59,7 +62,7 @@ class RenderManager:
|
|||
self.theme_manager = theme_manager
|
||||
self.displays = len(screen_list)
|
||||
self.current_display = 0
|
||||
self.renderer = Renderer(None)
|
||||
self.renderer = Renderer()
|
||||
self.calculate_default(self.screen_list[self.current_display]['size'])
|
||||
|
||||
def set_override_theme(self, theme):
|
||||
|
@ -68,11 +71,12 @@ class RenderManager:
|
|||
self.theme = theme
|
||||
else:
|
||||
self.theme = self.default_theme
|
||||
log.debug(u'theme is now %s', self.theme)
|
||||
self.themedata = self.theme_manager.getThemeData(self.theme)
|
||||
self.calculate_default(self.screen_list[self.current_display]['size'])
|
||||
self.renderer.set_theme(self.themedata)
|
||||
self.build_text_rectangle(self.themedata)
|
||||
if self.theme != self.renderer.theme_name:
|
||||
log.debug(u'theme is now %s', self.theme)
|
||||
self.themedata = self.theme_manager.getThemeData(self.theme)
|
||||
self.calculate_default(self.screen_list[self.current_display]['size'])
|
||||
self.renderer.set_theme(self.themedata)
|
||||
self.build_text_rectangle(self.themedata)
|
||||
|
||||
def build_text_rectangle(self, theme):
|
||||
log.debug(u'build_text_rectangle ')
|
||||
|
@ -95,50 +99,52 @@ class RenderManager:
|
|||
|
||||
def generate_preview(self, themedata):
|
||||
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.build_text_rectangle(themedata)
|
||||
|
||||
frame = QtGui.QPixmap(self.width, self.height)
|
||||
self.renderer.set_paint_dest(frame)
|
||||
self.renderer.set_frame_dest(self.width, self.height, True)
|
||||
|
||||
lines=[]
|
||||
lines = []
|
||||
lines.append(u'Amazing Grace!')
|
||||
lines.append(u'How sweet the sound')
|
||||
lines.append(u'To save a wretch like me;')
|
||||
lines.append(u'I once was lost but now am found,')
|
||||
lines.append(u'Was blind, but now I see.')
|
||||
lines1=[]
|
||||
lines1 = []
|
||||
lines1.append(u'Amazing Grace (John Newton)' )
|
||||
lines1.append(u'CCLI xxx (c)Openlp.org')
|
||||
answer=self.renderer.render_lines(lines, lines1)
|
||||
return frame
|
||||
lines1.append(u'Public Domain')
|
||||
lines1.append(u'CCLI xxx')
|
||||
return self.renderer.render_lines(lines, lines1)
|
||||
|
||||
|
||||
def format_slide(self, words, footer):
|
||||
log.debug(u'format slide')
|
||||
self.calculate_default(self.screen_list[self.current_display]['size'])
|
||||
self.renderer.set_paint_dest(QtGui.QPixmap(self.width, self.height))
|
||||
return self.renderer.format_slide(words, footer)
|
||||
self.build_text_rectangle(self.themedata)
|
||||
self.renderer.set_frame_dest(self.width, self.height)
|
||||
return self.renderer.format_slide(words, False)
|
||||
|
||||
def generate_slide(self,main_text, footer_text):
|
||||
log.debug(u'generate slide')
|
||||
#sys.settrace(traceit)
|
||||
|
||||
self.calculate_default(self.screen_list[self.current_display]['size'])
|
||||
|
||||
bef = datetime.now()
|
||||
frame = QtGui.QPixmap(self.width, self.height)
|
||||
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
|
||||
self.build_text_rectangle(self.themedata)
|
||||
self.renderer.set_frame_dest(self.width, self.height)
|
||||
return self.renderer.render_lines(main_text, footer_text)
|
||||
|
||||
def calculate_default(self, screen):
|
||||
log.debug(u'calculate default %s' , screen)
|
||||
self.width = screen.width()
|
||||
self.height = screen.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")
|
||||
|
|
|
@ -47,7 +47,7 @@ class ServiceItem():
|
|||
self.frames = []
|
||||
self.raw_footer = 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):
|
||||
self.iconic_representation = buildIcon(icon)
|
||||
|
|
|
@ -21,7 +21,7 @@ from xml.etree.ElementTree import ElementTree, XML, dump
|
|||
|
||||
For XML Schema see wiki.openlp.org
|
||||
"""
|
||||
|
||||
import os, os.path
|
||||
from openlp import convertStringToBoolean
|
||||
from xml.dom.minidom import Document
|
||||
from xml.etree.ElementTree import ElementTree, XML, dump
|
||||
|
@ -40,7 +40,7 @@ blankthemexml=\
|
|||
<direction>vertical</direction>
|
||||
</background>
|
||||
<background type="image" mode="opaque">
|
||||
<filename>fred.bmp</filename>
|
||||
<filename></filename>
|
||||
</background>
|
||||
<font type="main">
|
||||
<name>Arial</name>
|
||||
|
@ -69,6 +69,10 @@ class ThemeXML():
|
|||
# Create the minidom 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):
|
||||
# Create the <song> base element
|
||||
self.theme = self.theme_xml.createElement(u'theme')
|
||||
|
|
|
@ -22,10 +22,8 @@ import os, os.path
|
|||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
from PyQt4.QtGui import QColor, QFont
|
||||
from openlp.core.lib import ThemeXML
|
||||
from openlp.core.lib import Renderer
|
||||
from openlp.core import fileToXML
|
||||
from openlp.core import translate
|
||||
from openlp.core.lib import ThemeXML, Renderer
|
||||
from openlp.core import fileToXML, translate
|
||||
|
||||
from amendthemedialog import Ui_AmendThemeDialog
|
||||
|
||||
|
@ -53,6 +51,8 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
|
|||
QtCore.SIGNAL("pressed()"), self.onOutlineColorPushButtonClicked)
|
||||
QtCore.QObject.connect(self.ShadowColorPushButton,
|
||||
QtCore.SIGNAL("pressed()"), self.onShadowColorPushButtonClicked)
|
||||
QtCore.QObject.connect(self.ImageToolButton,
|
||||
QtCore.SIGNAL("pressed()"), self.onImageToolButtonClicked)
|
||||
|
||||
#Combo boxes
|
||||
QtCore.QObject.connect(self.BackgroundComboBox,
|
||||
|
@ -99,17 +99,22 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
|
|||
QtCore.QObject.connect(self.ShadowCheckBox,
|
||||
QtCore.SIGNAL("stateChanged(int)"), self.onShadowCheckBoxChanged)
|
||||
|
||||
|
||||
def accept(self):
|
||||
new_theme = ThemeXML()
|
||||
theme_name = str(self.ThemeNameEdit.displayText())
|
||||
new_theme.new_document(theme_name)
|
||||
save_from = None
|
||||
save_to = None
|
||||
if self.theme.background_type == u'solid':
|
||||
new_theme.add_background_solid(str(self.theme.background_color))
|
||||
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)
|
||||
#else:
|
||||
#newtheme.add_background_image(str(self.theme.))
|
||||
new_theme.add_background_gradient(str(self.theme.background_startColor),
|
||||
str(self.theme.background_endColor), self.theme.background_direction)
|
||||
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),
|
||||
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()
|
||||
|
||||
self.thememanager.saveTheme(theme_name, theme)
|
||||
self.thememanager.saveTheme(theme_name, theme, save_from, save_to)
|
||||
return QtGui.QDialog.accept(self)
|
||||
|
||||
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 = fileToXML(xml_file)
|
||||
self.theme.parse(xml)
|
||||
self.allowPreview = False
|
||||
self.paintUi(self.theme)
|
||||
self.allowPreview = True
|
||||
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
|
||||
#
|
||||
|
@ -196,8 +209,6 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
|
|||
def onFontMainHeightSpinBoxChanged(self, value):
|
||||
self.theme.font_main_height = value
|
||||
self.previewTheme(self.theme)
|
||||
|
||||
|
||||
#
|
||||
#Footer Font Tab
|
||||
#
|
||||
|
@ -217,7 +228,6 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
|
|||
self.theme.font_footer_proportion = value
|
||||
self.previewTheme(self.theme)
|
||||
|
||||
|
||||
def onFontFooterDefaultCheckBoxChanged(self, value):
|
||||
if value == 2: # checked
|
||||
self.theme.font_footer_override = False
|
||||
|
@ -516,5 +526,6 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
|
|||
|
||||
|
||||
def previewTheme(self, theme):
|
||||
frame = self.thememanager.generateImage(theme)
|
||||
self.ThemePreview.setPixmap(frame)
|
||||
if self.allowPreview:
|
||||
frame = self.thememanager.generateImage(theme)
|
||||
self.ThemePreview.setPixmap(frame)
|
||||
|
|
|
@ -60,9 +60,9 @@ class MainDisplay(QtGui.QWidget):
|
|||
painter.fillRect(self.blankFrame.rect(), QtGui.QColor(u'#000000'))
|
||||
|
||||
def frameView(self, frame):
|
||||
self.frame = frame
|
||||
if self.displayBlank == False:
|
||||
self.display.setPixmap(frame)
|
||||
self.frame = frame
|
||||
|
||||
def blankDisplay(self):
|
||||
if self.displayBlank == False:
|
||||
|
@ -71,7 +71,3 @@ class MainDisplay(QtGui.QWidget):
|
|||
else:
|
||||
self.displayBlank = False
|
||||
self.frameView(self.frame)
|
||||
|
||||
|
||||
def kill(self):
|
||||
pass
|
||||
|
|
|
@ -37,6 +37,7 @@ class MainWindow(object):
|
|||
|
||||
def __init__(self, screens):
|
||||
self.main_window = QtGui.QMainWindow()
|
||||
self.main_window.__class__.closeEvent = self.onCloseEvent
|
||||
self.main_display = MainDisplay(None, screens)
|
||||
self.screen_list = screens
|
||||
self.EventManager = EventManager()
|
||||
|
@ -89,23 +90,32 @@ class MainWindow(object):
|
|||
|
||||
# Once all components are initialised load the Themes
|
||||
log.info(u'Load Themes and Managers')
|
||||
self.PreviewController.eventManager = self.EventManager
|
||||
self.PreviewController.serviceManager = self.ServiceManagerContents
|
||||
self.LiveController.eventManager = self.EventManager
|
||||
self.LiveController.serviceManager = self.ServiceManagerContents
|
||||
self.ThemeManagerContents.eventManager = self.EventManager
|
||||
self.ThemeManagerContents.renderManager = self.RenderManager
|
||||
self.ServiceManagerContents.renderManager = self.RenderManager
|
||||
self.ServiceManagerContents.eventManager = self.EventManager
|
||||
self.ServiceManagerContents.liveController = self.LiveController
|
||||
self.ServiceManagerContents.previewController = self.PreviewController
|
||||
self.ThemeManagerContents.serviceManager = self.ServiceManagerContents
|
||||
self.PreviewController.ServiceManager = self.ServiceManagerContents
|
||||
self.LiveController.ServiceManager = self.ServiceManagerContents
|
||||
|
||||
self.ThemeManagerContents.EventManager = self.EventManager
|
||||
self.ThemeManagerContents.RenderManager = self.RenderManager
|
||||
self.ThemeManagerContents.ServiceManager = self.ServiceManagerContents
|
||||
#self.ThemeManagerContents.ThemesTab = self.ServiceManagerContents.ThemesTab
|
||||
|
||||
self.ServiceManagerContents.RenderManager = self.RenderManager
|
||||
self.ServiceManagerContents.EventManager = self.EventManager
|
||||
self.ServiceManagerContents.LiveController = self.LiveController
|
||||
self.ServiceManagerContents.PreviewController = self.PreviewController
|
||||
|
||||
self.ThemeManagerContents.loadThemes()
|
||||
|
||||
# Initialise SlideControllers
|
||||
log.info(u'Set Up SlideControllers')
|
||||
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):
|
||||
self.main_window.setObjectName(u'main_window')
|
||||
self.main_window.resize(1087, 847)
|
||||
|
|
|
@ -136,13 +136,13 @@ class ServiceManager(QtGui.QWidget):
|
|||
pass
|
||||
|
||||
def onSaveService(self):
|
||||
Pass
|
||||
pass
|
||||
|
||||
def onLoadService(self):
|
||||
Pass
|
||||
pass
|
||||
|
||||
def onThemeComboBoxSelected(self, currentIndex):
|
||||
self.renderManager.default_theme = self.ThemeComboBox.currentText()
|
||||
self.RenderManager.default_theme = self.ThemeComboBox.currentText()
|
||||
|
||||
def addServiceItem(self, item):
|
||||
self.serviceItems.append({u'data': item, u'order': len(self.serviceItems)+1})
|
||||
|
@ -162,11 +162,11 @@ class ServiceManager(QtGui.QWidget):
|
|||
|
||||
def makePreview(self):
|
||||
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):
|
||||
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):
|
||||
items = self.ServiceManagerList.selectedItems()
|
||||
|
@ -197,7 +197,7 @@ class ServiceManager(QtGui.QWidget):
|
|||
link=event.mimeData()
|
||||
if link.hasText():
|
||||
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):
|
||||
text=[]
|
||||
|
@ -226,5 +226,5 @@ class ServiceManager(QtGui.QWidget):
|
|||
self.ThemeComboBox.clear()
|
||||
for theme in theme_list:
|
||||
self.ThemeComboBox.addItem(theme)
|
||||
self.renderManager.default_theme = self.ThemeComboBox.currentText()
|
||||
self.RenderManager.default_theme = self.ThemeComboBox.currentText()
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ from PyQt4 import QtCore, QtGui
|
|||
|
||||
from openlp.core.lib import OpenLPToolbar
|
||||
from openlp.core import translate
|
||||
from openlp.core.lib import Event, EventType, EventManager
|
||||
|
||||
class SlideData(QtCore.QAbstractListModel):
|
||||
"""
|
||||
|
@ -37,17 +36,13 @@ class SlideData(QtCore.QAbstractListModel):
|
|||
|
||||
def __init__(self):
|
||||
QtCore.QAbstractListModel.__init__(self)
|
||||
self.items=[]
|
||||
self.rowheight=50
|
||||
self.maximagewidth=self.rowheight*16/9.0;
|
||||
self.items = []
|
||||
self.rowheight = 50
|
||||
self.maximagewidth = self.rowheight * 16/9.0;
|
||||
log.info(u'Starting')
|
||||
|
||||
def eventFilter(self, obj, event):
|
||||
print obj, event
|
||||
return false
|
||||
|
||||
def clear(self):
|
||||
self.items=[]
|
||||
self.items = []
|
||||
|
||||
def columnCount(self, parent):
|
||||
return 1
|
||||
|
|
|
@ -222,8 +222,10 @@ class ThemeManager(QWidget):
|
|||
for name in files:
|
||||
if name.endswith(u'.png'):
|
||||
self.themeData.addRow(os.path.join(self.path, name))
|
||||
self.eventManager.post_event(Event(EventType.ThemeListChanged))
|
||||
self.serviceManager.updateThemeList(self.getThemes())
|
||||
self.EventManager.post_event(Event(EventType.ThemeListChanged))
|
||||
self.ServiceManager.updateThemeList(self.getThemes())
|
||||
self.parent.settings_form.ThemesTab.updateThemeList(self.getThemes())
|
||||
|
||||
|
||||
def getThemes(self):
|
||||
return self.themeData.getList()
|
||||
|
@ -244,6 +246,7 @@ class ThemeManager(QWidget):
|
|||
xml = newtheme.extract_xml()
|
||||
theme = ThemeXML()
|
||||
theme.parse(xml)
|
||||
theme.extend_filename(self.path)
|
||||
return theme
|
||||
|
||||
def checkThemesExists(self, dir):
|
||||
|
@ -331,9 +334,8 @@ class ThemeManager(QWidget):
|
|||
str(theme.WrapStyle))
|
||||
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)
|
||||
self.generateAndSaveImage(self.path, name, theme_xml)
|
||||
theme_dir = os.path.join(self.path, name)
|
||||
if os.path.exists(theme_dir) == False:
|
||||
os.mkdir(os.path.join(self.path, name))
|
||||
|
@ -341,6 +343,9 @@ class ThemeManager(QWidget):
|
|||
outfile = open(theme_file, u'w')
|
||||
outfile.write(theme_xml)
|
||||
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.loadThemes()
|
||||
|
||||
|
@ -348,6 +353,7 @@ class ThemeManager(QWidget):
|
|||
log.debug(u'generateAndSaveImage %s %s %s', dir, name, theme_xml)
|
||||
theme = ThemeXML()
|
||||
theme.parse(theme_xml)
|
||||
theme.extend_filename(dir)
|
||||
frame = self.generateImage(theme)
|
||||
im = frame.toImage()
|
||||
samplepathname = os.path.join(self.path, name + u'.png')
|
||||
|
@ -358,6 +364,6 @@ class ThemeManager(QWidget):
|
|||
|
||||
def generateImage(self, themedata):
|
||||
log.debug(u'generateImage %s ', themedata)
|
||||
frame = self.renderManager.generate_preview(themedata)
|
||||
frame = self.RenderManager.generate_preview(themedata)
|
||||
return frame
|
||||
|
||||
|
|
|
@ -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.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.'))
|
||||
|
||||
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)
|
||||
|
|
|
@ -85,13 +85,13 @@ class BiblePlugin(Plugin):
|
|||
log.debug(u'Handle event called with event %s with payload %s'%(event.event_type, event.payload))
|
||||
if event.event_type == EventType.ThemeListChanged:
|
||||
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':
|
||||
log.debug(u'Load Service Item received')
|
||||
self.media_item.onBibleAddClick()
|
||||
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()
|
||||
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()
|
||||
|
|
|
@ -198,6 +198,7 @@ class BiblesTab(SettingsTab):
|
|||
self.BibleThemeComboBox.setCurrentIndex(self.bible_theme)
|
||||
else:
|
||||
pass # TODO need to code
|
||||
self.bible_theme = None
|
||||
|
||||
def save(self):
|
||||
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("search as type", str(self.bible_search))
|
||||
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)
|
||||
|
|
|
@ -369,13 +369,14 @@ class BibleMediaItem(MediaManagerItem):
|
|||
def generateSlideData(self, service_item):
|
||||
log.debug(u'Bible Preview Button pressed')
|
||||
items = self.BibleListView.selectedIndexes()
|
||||
old_chapter = ''
|
||||
old_chapter = u''
|
||||
raw_slides=[]
|
||||
raw_footer = []
|
||||
bible_text = u''
|
||||
for item in items:
|
||||
text = self.BibleListData.getValue(item)
|
||||
verse = text[:text.find("(")]
|
||||
bible = text[text.find("(") + 1:text.find(")")]
|
||||
verse = text[:text.find(u'(')]
|
||||
bible = text[text.find(u'(') + 1:text.find(u')')]
|
||||
self.searchByReference(bible, verse)
|
||||
book = self.search_results[0][0]
|
||||
chapter = str(self.search_results[0][1])
|
||||
|
@ -392,15 +393,15 @@ class BibleMediaItem(MediaManagerItem):
|
|||
else:
|
||||
loc = self.formatVerse(old_chapter, chapter, verse, u'', u'')
|
||||
old_chapter = chapter
|
||||
raw_slides.append(loc + u' '+text)
|
||||
bible_text = bible_text + u' '+ loc + u' '+ text
|
||||
service_item.title = book + u' ' + loc
|
||||
if len(raw_footer) <= 1:
|
||||
raw_footer.append(book)
|
||||
|
||||
if len(raw_slides) > 0:
|
||||
service_item.theme = None
|
||||
service_item.raw_slides = raw_slides
|
||||
service_item.raw_footer = raw_footer
|
||||
service_item.theme = self.parent.bibles_tab.bible_theme
|
||||
raw_slides.append(bible_text)
|
||||
service_item.raw_slides = raw_slides
|
||||
service_item.raw_footer = raw_footer
|
||||
|
||||
def formatVerse(self, old_chapter, chapter, verse, opening, closing):
|
||||
loc = opening
|
||||
|
|
|
@ -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
|
||||
|
||||
from PyQt4.QtCore import *
|
||||
|
@ -6,7 +25,7 @@ from PyQt4.QtGui import *
|
|||
|
||||
class TextListData(QAbstractListModel):
|
||||
"""
|
||||
An abstract list of strings
|
||||
An abstract list of strings
|
||||
"""
|
||||
global log
|
||||
log=logging.getLogger(u'TextListData')
|
||||
|
@ -14,18 +33,18 @@ class TextListData(QAbstractListModel):
|
|||
|
||||
def __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):
|
||||
#reset list so can be reloaded
|
||||
self.items=[]
|
||||
|
||||
self.items = []
|
||||
|
||||
def rowCount(self, parent):
|
||||
return len(self.items)
|
||||
|
||||
def insertRow(self, row, id, title):
|
||||
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.endInsertRows()
|
||||
|
||||
|
@ -36,18 +55,15 @@ class TextListData(QAbstractListModel):
|
|||
|
||||
def addRow(self, id, title):
|
||||
self.insertRow(len(self.items), id, title)
|
||||
|
||||
|
||||
def data(self, index, role):
|
||||
row=index.row()
|
||||
if row > len(self.items): # if the last row is selected and deleted, we then get called with an empty row!
|
||||
return QVariant()
|
||||
if role==Qt.DisplayRole:
|
||||
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]
|
||||
if role == Qt.DisplayRole:
|
||||
retval = self.items[row][1]
|
||||
else:
|
||||
retval= QVariant()
|
||||
# log.info("Returning"+ str(retval))
|
||||
retval = QVariant()
|
||||
if type(retval) is not type(QVariant):
|
||||
return QVariant(retval)
|
||||
else:
|
||||
|
@ -60,10 +76,7 @@ class TextListData(QAbstractListModel):
|
|||
def getValue(self, index):
|
||||
row = index.row()
|
||||
return self.items[row][1]
|
||||
|
||||
|
||||
def deleteRow(self, index):
|
||||
row = index.row()
|
||||
self.removeRow(row)
|
||||
|
||||
if __name__=="__main__":
|
||||
sxml=TextListData()
|
||||
|
|
|
@ -64,8 +64,8 @@ class CustomPlugin(Plugin):
|
|||
log.debug(u'Load Service Item received')
|
||||
self.media_item.onCustomAddClick()
|
||||
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()
|
||||
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()
|
||||
|
|
|
@ -60,10 +60,10 @@ class ImagePlugin(Plugin):
|
|||
log.debug(u'Load Service Item received')
|
||||
self.media_item.onImageAddClick()
|
||||
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()
|
||||
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()
|
||||
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ class ImageMediaItem(MediaManagerItem):
|
|||
self.parent.live_controller.addServiceItem(service_item)
|
||||
|
||||
def onImageAddClick(self):
|
||||
log.debug(u'Image Live Requested')
|
||||
log.debug(u'Image Add Requested')
|
||||
service_item = ServiceItem(self.parent)
|
||||
service_item.addIcon( ":/media/media_image.png")
|
||||
service_item.render_manager = self.parent.render_manager
|
||||
|
|
|
@ -30,7 +30,7 @@ from openlp.plugins.media.lib import FileListData
|
|||
|
||||
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
|
||||
log=logging.getLogger(u'MediaMediaItem')
|
||||
|
@ -93,13 +93,14 @@ class MediaMediaItem(MediaManagerItem):
|
|||
translate('MediaMediaItem',u'&Add to Service'), self.onMediaAddClick))
|
||||
|
||||
def initialise(self):
|
||||
list = self.parent.config.load_list(u'Medias')
|
||||
list = self.parent.config.load_list(u'Media')
|
||||
self.loadMediaList(list)
|
||||
|
||||
def onMediaNewClick(self):
|
||||
files = QtGui.QFileDialog.getOpenFileNames(None,
|
||||
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:
|
||||
self.loadMediaList(files)
|
||||
dir, filename = os.path.split(str(files[0]))
|
||||
|
|
|
@ -105,10 +105,6 @@ class SongsPlugin(Plugin):
|
|||
QtCore.QObject.connect(self.ExportOpenlp1Item, QtCore.SIGNAL("triggered()"), self.onExportOpenlp1ItemClicked)
|
||||
QtCore.QObject.connect(self.ExportOpenSongItem, QtCore.SIGNAL("triggered()"), self.onExportOpenSongItemClicked)
|
||||
|
||||
def get_settings_tab(self):
|
||||
self.SongsTab = SongsTab()
|
||||
return self.SongsTab
|
||||
|
||||
def initialise(self):
|
||||
pass
|
||||
|
||||
|
|
Loading…
Reference in New Issue