Merge lp:~manndarryl/openlp/thememanger into lp:openlp

Proposed by Darryl Mann
Status: Work in progress
Proposed branch: lp:~manndarryl/openlp/thememanger
Merge into: lp:openlp
Diff against target: 2051 lines (+946/-345)
12 files modified
openlp/core/lib/htmlbuilder.py (+38/-14)
openlp/core/lib/imagemanager.py (+2/-0)
openlp/core/lib/json/theme.json (+22/-6)
openlp/core/lib/renderer.py (+67/-12)
openlp/core/lib/theme.py (+241/-103)
openlp/core/ui/maindisplay.py (+23/-13)
openlp/core/ui/themeform.py (+239/-84)
openlp/core/ui/thememanager.py (+20/-14)
openlp/core/ui/themewizard.py (+289/-95)
openlp/core/utils/__init__.py (+1/-0)
tests/functional/openlp_core_lib/test_htmlbuilder.py (+2/-2)
tests/functional/openlp_core_lib/test_theme.py (+2/-2)
To merge this branch: bzr merge lp:~manndarryl/openlp/thememanger
Reviewer Review Type Date Requested Status
OpenLP Core Pending
Review via email: mp+239527@code.launchpad.net

Description of the change

Added a few more options to the Theme Manager on background and output area pages. And a save button on every page execpt first and last.

To post a comment you must log in.
Revision history for this message
Darryl Mann (manndarryl) wrote :

Coded on Kubuntu 14.04, needs testing on Windows and Mac OSX.

lp:~manndarryl/openlp/thememanger updated
2430. By Darryl Mann

Fixed bug with image slide.

Revision history for this message
Tim Bentley (trb143) wrote :

Interesting changes.
Please can you explain the rational for you changes they are fundamental to the theme system and are wide ranging.
They make significant changes to how themes work and how OpenLP was designed so a understand is essential to move forwards.
As we are in the process of starting the 2.2 beta stage this code would need to wait till after 2.2 is release.

Before undertaking any more work an explanation please would make our lives easier.

Thanks

Revision history for this message
Darryl Mann (manndarryl) wrote :

Okay these changes consists of three new features. I understand that it is good to be cautious about new features and an unstanding is need to see if they are consistent with the direction the software development is headed.

The three features added to the Theme Manager are:

(1) Save button: to allow changes to be saved without the need to go to the last page

(2) Output area: allow main and footer area to be specified by relative measurements or margins. allowing a the same theme to be easily used on computers with different output screen sizes.

(3) Background: color and image are seperated to allow the user to choose different color type, solid, gradient or transparent along side with an image. Also, the ability to choose the size and alignment of the image to display.

So, that sums up the changes. The one you maybe most concerned about is the last one (3) -- changes to the background page. It is the one which has the most significant changes and is definatly wide ranging. The rational behind this change was to somehow pave the way to layer two themes or maybe better descibed how most presentation software has a master slide. This is in the hopes to give the song plugin the ability to choose a sub-theme for a verse.

After having the oppertunity to look deeper in how the HTML is generated, changing the way the background image is generated might not be needed. Guess, this is the stage where we re-think number (3), but I don't see any reason not to go ahead with (1) and (2) if you so choose. I can upload another trunk without number (3) changes if you wish.

What are your thoughts on the idea of each verse have the option to have a sub-theme?

Revision history for this message
Tim Bentley (trb143) wrote :

Ok I can see where you are going.
These changes will not make 2.2 as we plan start the release this week with a final release around Christmas. We then hope to move to a 6-9 month release pattern.
There is no reason to stop moving forward as these will take some time to get ready.
In 2.4 there is a plan to move to PyQt5 which could have a big impact on the htmlbuilder so it may be wise to park that for a bit so delaying (3) works there.
(1) I am not sure about as saving in the middle still needs to run the last stage of code. A button with fast paths to the last screen may be better. Come on to IRC as discuss Raoul will have strong views on this!
(2) IS interesting and a merge with this would be nice. Try to build on the existing code and not mess (too much) with variables. Any change to a theme variable will require code to handle old and new themes!

From a coding style point of view no immediate issues you seem to fit in with our standards.
You will need to develop some tests. We have a rule that ALL code merges need to add tests to build up the test base.

Revision history for this message
Tim Bentley (trb143) wrote :

BTW please do not use Trunk for development code. Truck is only for the master code.

Revision history for this message
Darryl Mann (manndarryl) wrote :

Thanks for the pointers. I was thinking that the save button could be a Preview button instead which just brings you to the last page. Anyway, for now I will focus on (2) for now.

Revision history for this message
Darryl Mann (manndarryl) wrote :

(2) Theme Manager margins feature can be found at the following branch:
https://code.launchpad.net/~manndarryl/openlp/thememanager-margins

Unmerged revisions

2430. By Darryl Mann

Fixed bug with image slide.

2429. By Darryl Mann

Added a few more options to the Theme Manager on background and output area pages.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/core/lib/htmlbuilder.py'
2--- openlp/core/lib/htmlbuilder.py 2014-07-21 06:37:41 +0000
3+++ openlp/core/lib/htmlbuilder.py 2014-10-24 20:09:17 +0000
4@@ -399,7 +399,8 @@
5 from PyQt4 import QtWebKit
6
7 from openlp.core.common import Settings
8-from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, VerticalType, HorizontalType
9+from openlp.core.lib.theme import BackgroundColorType, BackgroundGradientType, BackgroundMediaType, \
10+ VerticalType, HorizontalType, MediaAlignType, MediaScaleType
11
12 log = logging.getLogger(__name__)
13
14@@ -432,6 +433,7 @@
15 display: none;
16 }
17 #bgimage {
18+ position: absolute;
19 z-index: 1;
20 }
21 #image {
22@@ -544,7 +546,7 @@
23 </script>
24 </head>
25 <body>
26-<img id="bgimage" class="size" %s />
27+<img id="bgimage" %s />
28 <img id="image" class="size" %s />
29 %s
30 <div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"></div></div>
31@@ -566,6 +568,7 @@
32 :param image: Image media item - bytes
33 :param plugins: The List of available plugins
34 """
35+ css_additions = ''
36 width = screen['size'].width()
37 height = screen['size'].height()
38 theme_data = item.theme_data
39@@ -574,13 +577,34 @@
40 bgimage_src = 'src="data:image/png;base64,%s"' % background
41 elif item.bg_image_bytes:
42 bgimage_src = 'src="data:image/png;base64,%s"' % item.bg_image_bytes
43+ try:
44+ if theme_data.background_media_scale == MediaScaleType.to_string(MediaScaleType.Fullscreen):
45+ left = (width - (item.image_width * height / item.image_height )) / 2
46+ css_additions = '#bgimage { top:0; left:%dpx; width:auto; height:100%% }' % left
47+ else:
48+ media_alignment = MediaAlignType.from_string(theme_data.background_media_align)
49+ if media_alignment & MediaAlignType.Top:
50+ top = 25
51+ elif media_alignment & MediaAlignType.Bottom:
52+ top = item.footer.y() - item.image_height - 25
53+ else:
54+ top = (height - item.image_height) / 2
55+ if media_alignment & MediaAlignType.Left:
56+ left = 25
57+ elif media_alignment & MediaAlignType.Right:
58+ left = width - item.image_width - 25
59+ else:
60+ left = (width - item.image_width) / 2
61+
62+ css_additions = '#bgimage { top: %dpx; left: %dpx; }' % (top, left)
63+ except:
64+ pass
65 else:
66 bgimage_src = 'style="display:none;"'
67 if image:
68 image_src = 'src="data:image/png;base64,%s"' % image
69 else:
70 image_src = 'style="display:none;"'
71- css_additions = ''
72 js_additions = ''
73 html_additions = ''
74 if plugins:
75@@ -625,26 +649,26 @@
76 theme = item.theme_data
77 background = 'background-color: black'
78 if theme:
79- if theme.background_type == BackgroundType.to_string(BackgroundType.Transparent):
80+ if theme.background_color_type == BackgroundColorType.to_string(BackgroundColorType.Transparent):
81 background = ''
82- elif theme.background_type == BackgroundType.to_string(BackgroundType.Solid):
83+ elif theme.background_color_type == BackgroundColorType.to_string(BackgroundColorType.Solid):
84 background = 'background-color: %s' % theme.background_color
85 else:
86- if theme.background_direction == BackgroundGradientType.to_string(BackgroundGradientType.Horizontal):
87+ if theme.background_color_direction == BackgroundGradientType.to_string(BackgroundGradientType.Horizontal):
88 background = 'background: -webkit-gradient(linear, left top, left bottom, from(%s), to(%s)) fixed' \
89- % (theme.background_start_color, theme.background_end_color)
90- elif theme.background_direction == BackgroundGradientType.to_string(BackgroundGradientType.LeftTop):
91+ % (theme.background_color_start, theme.background_color_end)
92+ elif theme.background_color_direction == BackgroundGradientType.to_string(BackgroundGradientType.LeftTop):
93 background = 'background: -webkit-gradient(linear, left top, right bottom, from(%s), to(%s)) fixed' \
94- % (theme.background_start_color, theme.background_end_color)
95- elif theme.background_direction == BackgroundGradientType.to_string(BackgroundGradientType.LeftBottom):
96+ % (theme.background_color_start, theme.background_color_end)
97+ elif theme.background_color_direction == BackgroundGradientType.to_string(BackgroundGradientType.LeftBottom):
98 background = 'background: -webkit-gradient(linear, left bottom, right top, from(%s), to(%s)) fixed' \
99- % (theme.background_start_color, theme.background_end_color)
100- elif theme.background_direction == BackgroundGradientType.to_string(BackgroundGradientType.Vertical):
101+ % (theme.background_color_start, theme.background_color_end)
102+ elif theme.background_color_direction == BackgroundGradientType.to_string(BackgroundGradientType.Vertical):
103 background = 'background: -webkit-gradient(linear, left top, right top, from(%s), to(%s)) fixed' % \
104- (theme.background_start_color, theme.background_end_color)
105+ (theme.background_color_start, theme.background_color_end)
106 else:
107 background = 'background: -webkit-gradient(radial, %s 50%%, 100, %s 50%%, %s, from(%s), to(%s)) fixed'\
108- % (width, width, width, theme.background_start_color, theme.background_end_color)
109+ % (width, width, width, theme.background_color_start, theme.background_color_end)
110 return background
111
112
113
114=== modified file 'openlp/core/lib/imagemanager.py'
115--- openlp/core/lib/imagemanager.py 2014-09-11 10:08:44 +0000
116+++ openlp/core/lib/imagemanager.py 2014-10-24 20:09:17 +0000
117@@ -117,6 +117,8 @@
118 ratio does not match with the display ratio.
119 :param width: The width of the image, defaults to -1 meaning that the screen width will be used.
120 :param height: The height of the image, defaults to -1 meaning that the screen height will be used.
121+ :param valign: Vertical alignment of image, either top, middle (default) or bottom
122+ :param halign: Horizontal alignment of image, either left, center (default) or right
123 """
124 self.path = path
125 self.image = None
126
127=== modified file 'openlp/core/lib/json/theme.json'
128--- openlp/core/lib/json/theme.json 2013-10-18 18:10:47 +0000
129+++ openlp/core/lib/json/theme.json 2014-10-24 20:09:17 +0000
130@@ -1,12 +1,16 @@
131 {
132 "background" : {
133- "border_color": "#000000",
134 "color": "#000000",
135- "direction": "vertical",
136- "end_color": "#000000",
137- "filename": "",
138- "start_color": "#000000",
139- "type": "solid"
140+ "color_type": "solid",
141+ "color_end": "#000000",
142+ "color_start": "#000000",
143+ "color_direction": "vertical",
144+ "media_type": "none",
145+ "media_align": "middle-center",
146+ "media_scale": "fullscreen",
147+ "media_width": "-1",
148+ "media_height": "-1",
149+ "media_filename": ""
150 },
151 "display" :{
152 "horizontal_align": 0,
153@@ -16,40 +20,52 @@
154 "font": {
155 "footer": {
156 "bold": false,
157+ "bottom": 10,
158 "color": "#FFFFFF",
159 "height": 78,
160 "italics": false,
161+ "left": 10,
162 "line_adjustment": 0,
163+ "margin": "",
164 "location": "",
165+ "position": "location",
166 "name": "Arial",
167 "outline": false,
168 "outline_color": "#000000",
169 "outline_size": 2,
170 "override": false,
171+ "right": 10,
172 "shadow": true,
173 "shadow_color": "#000000",
174 "shadow_size": 5,
175 "size": 12,
176+ "top": 0,
177 "width": 1004,
178 "x": 10,
179 "y": 690
180 },
181 "main": {
182 "bold": false,
183+ "bottom": 10,
184 "color": "#FFFFFF",
185 "height": 690,
186 "italics": false,
187+ "left": 10,
188 "line_adjustment": 0,
189+ "margin": "margin",
190 "location": "",
191+ "position": "location",
192 "name": "Arial",
193 "outline": false,
194 "outline_color": "#000000",
195 "outline_size": 2,
196 "override": false,
197+ "right": 10,
198 "shadow": true,
199 "shadow_color": "#000000",
200 "shadow_size": 5,
201 "size": 40,
202+ "top": 10,
203 "width": 1004,
204 "x": 10,
205 "y": 10
206
207=== modified file 'openlp/core/lib/renderer.py'
208--- openlp/core/lib/renderer.py 2014-07-02 18:13:23 +0000
209+++ openlp/core/lib/renderer.py 2014-10-24 20:09:17 +0000
210@@ -122,9 +122,22 @@
211 else:
212 theme_data, main_rect, footer_rect = self._theme_dimensions[theme_name]
213 # if No file do not update cache
214- if theme_data.background_filename:
215- self.image_manager.add_image(theme_data.background_filename,
216- ImageSource.Theme, QtGui.QColor(theme_data.background_border_color))
217+ if theme_data.background_media_filename:
218+ theme_background_color = QtCore.Qt.transparent
219+ theme_media_width = int(theme_data.background_media_width)
220+ theme_media_height = int(theme_data.background_media_height)
221+ if theme_data.background_media_scale == 'auto':
222+ image = QtGui.QImage(theme_data.background_media_filename)
223+ theme_media_width = int(image.width())
224+ theme_media_height = int(image.height())
225+ if theme_data.background_color_type == 'solid':
226+ theme_background_color = QtGui.QColor(theme_data.background_color)
227+ self.image_manager.add_image(
228+ theme_data.background_media_filename,
229+ ImageSource.Theme,
230+ theme_background_color,
231+ theme_media_width,
232+ theme_media_height)
233
234 def pre_render(self, override_theme_data=None):
235 """
236@@ -211,9 +224,22 @@
237 service_item.add_from_text(VERSE)
238 service_item.raw_footer = FOOTER
239 # if No file do not update cache
240- if theme_data.background_filename:
241+ if theme_data.background_media_filename:
242+ theme_background_color = QtCore.Qt.transparent
243+ theme_media_width = int(theme_data.background_media_width)
244+ theme_media_height = int(theme_data.background_media_height)
245+ if theme_data.background_media_scale == 'auto':
246+ image = QtGui.QImage(theme_data.background_media_filename)
247+ theme_media_width = int(image.width())
248+ theme_media_height = int(image.height())
249+ if theme_data.background_color_type == 'solid':
250+ theme_background_color = QtGui.QColor(theme_data.background_color)
251 self.image_manager.add_image(
252- theme_data.background_filename, ImageSource.Theme, QtGui.QColor(theme_data.background_border_color))
253+ theme_data.background_media_filename,
254+ ImageSource.Theme,
255+ theme_background_color,
256+ theme_media_width,
257+ theme_media_height)
258 theme_data, main, footer = self.pre_render(theme_data)
259 service_item.theme_data = theme_data
260 service_item.main = main
261@@ -326,11 +352,18 @@
262
263 :param theme_data: The theme information
264 """
265- if not theme_data.font_main_override:
266- return QtCore.QRect(10, 0, self.width - 20, self.footer_start)
267- else:
268+ font_footer_top = self.get_footer_top(theme_data)
269+ if theme_data.font_main_override == 0:
270+ return QtCore.QRect(10, 0, self.width - 20, font_footer_top)
271+ elif theme_data.font_main_override == 1:
272 return QtCore.QRect(theme_data.font_main_x, theme_data.font_main_y,
273- theme_data.font_main_width - 1, theme_data.font_main_height - 1)
274+ theme_data.font_main_width - 1, font_footer_top - 1)
275+ elif theme_data.font_main_override == 3:
276+ main_width = self.width - theme_data.font_main_left - theme_data.font_main_right - 1
277+ main_height = font_footer_top - theme_data.font_main_top - theme_data.font_main_bottom - 1
278+ return QtCore.QRect(theme_data.font_main_left,theme_data.font_main_top, main_width, main_height)
279+ else:
280+ return QtCore.QRect(20, 20, self.width - 40, font_footer_top - 40)
281
282 def get_footer_rectangle(self, theme_data):
283 """
284@@ -338,12 +371,34 @@
285
286 :param theme_data: The theme data.
287 """
288- if not theme_data.font_footer_override:
289- return QtCore.QRect(10, self.footer_start, self.width - 20, self.height - self.footer_start)
290- else:
291+ font_footer_top = self.get_footer_top(theme_data)
292+ if theme_data.font_footer_override == 0:
293+ return QtCore.QRect(10, font_footer_top, self.width - 20, self.height - font_footer_top)
294+ elif theme_data.font_footer_override == 1:
295 return QtCore.QRect(theme_data.font_footer_x,
296 theme_data.font_footer_y, theme_data.font_footer_width - 1,
297 theme_data.font_footer_height - 1)
298+ elif theme_data.font_footer_override == 3:
299+ return QtCore.QRect(theme_data.font_footer_left, font_footer_top,
300+ self.width - theme_data.font_footer_left - theme_data.font_footer_right - 1,
301+ theme_data.font_footer_height - 1)
302+ else:
303+ return QtCore.QRect(20, font_footer_top, self.width - 40, theme_data.font_footer_height - 1)
304+
305+ def get_footer_top(self, theme_data):
306+ """
307+ Calculates the footer top coordinate
308+
309+ :param theme_data: The theme information
310+ """
311+ if theme_data.font_footer_override == 0:
312+ return self.footer_start
313+ elif theme_data.font_footer_override == 1:
314+ return theme_data.font_footer_y
315+ elif theme_data.font_footer_override == 3:
316+ return self.height - theme_data.font_footer_height - theme_data.font_footer_bottom
317+ else:
318+ return self.height - 78 - 20
319
320 def _set_text_rectangle(self, theme_data, rect_main, rect_footer):
321 """
322
323=== modified file 'openlp/core/lib/theme.py'
324--- openlp/core/lib/theme.py 2014-03-17 19:05:55 +0000
325+++ openlp/core/lib/theme.py 2014-10-24 20:09:17 +0000
326@@ -43,43 +43,150 @@
327 log = logging.getLogger(__name__)
328
329
330-class BackgroundType(object):
331+class BackgroundColorType(object):
332 """
333- Type enumeration for backgrounds.
334+ Color type enumeration for backgrounds.
335 """
336 Solid = 0
337 Gradient = 1
338- Image = 2
339- Transparent = 3
340+ Transparent = 2
341
342 @staticmethod
343- def to_string(background_type):
344- """
345- Return a string representation of a background type.
346- """
347- if background_type == BackgroundType.Solid:
348+ def to_string(background_color_type):
349+ """
350+ Return a string representation of a background color type.
351+ """
352+ if background_color_type == BackgroundColorType.Solid:
353 return 'solid'
354- elif background_type == BackgroundType.Gradient:
355+ elif background_color_type == BackgroundColorType.Gradient:
356 return 'gradient'
357- elif background_type == BackgroundType.Image:
358- return 'image'
359- elif background_type == BackgroundType.Transparent:
360+ elif background_color_type == BackgroundColorType.Transparent:
361 return 'transparent'
362
363 @staticmethod
364 def from_string(type_string):
365 """
366- Return a background type for the given string.
367+ Return a background color type for the given string.
368 """
369 if type_string == 'solid':
370- return BackgroundType.Solid
371+ return BackgroundColorType.Solid
372 elif type_string == 'gradient':
373- return BackgroundType.Gradient
374+ return BackgroundColorType.Gradient
375+ elif type_string == 'transparent':
376+ return BackgroundColorType.Transparent
377+
378+class BackgroundMediaType(object):
379+ """
380+ Media type enumeration for backgrounds.
381+ """
382+ Nothing = 0
383+ Image = 1
384+
385+ @staticmethod
386+ def to_string(media_type):
387+ """
388+ Return a string representation of a background media type.
389+ """
390+ if media_type == None or media_type == BackgroundMediaType.Nothing:
391+ return 'none'
392+ elif media_type == BackgroundMediaType.Image:
393+ return 'image'
394+
395+ @staticmethod
396+ def from_string(type_string):
397+ """
398+ Return a background media type for the given string.
399+ """
400+ if type_string == None or type_string == 'none':
401+ return BackgroundMediaType.Nothing
402 elif type_string == 'image':
403- return BackgroundType.Image
404- elif type_string == 'transparent':
405- return BackgroundType.Transparent
406-
407+ return BackgroundMediaType.Image
408+
409+class MediaScaleType(object):
410+ """
411+ Scale enumeration for media.
412+ """
413+ Auto = 0
414+ Fullscreen = 1
415+ Fixed = 2
416+
417+ @staticmethod
418+ def to_string(image_scale):
419+ """
420+ Return a string representation of a media scale.
421+ """
422+ if image_scale == MediaScaleType.Auto:
423+ return 'auto'
424+ elif image_scale == MediaScaleType.Fullscreen:
425+ return 'fullscreen'
426+ elif image_scale == MediaScaleType.Fixed:
427+ return 'fixed'
428+
429+ @staticmethod
430+ def from_string(image_scale):
431+ """
432+ Return a media scale for the given string.
433+ """
434+ if image_scale == 'auto':
435+ return MediaScaleType.Auto
436+ elif image_scale == 'fullscreen':
437+ return MediaScaleType.Fullscreen
438+ elif image_scale == 'fixed':
439+ return MediaScaleType.Fixed
440+
441+class MediaAlignType(object):
442+ """
443+ Alignment enumeration for media.
444+ """
445+ Top = 1
446+ Middle = 0
447+ Bottom = 2
448+ Left = 4
449+ Center = 0
450+ Right = 8
451+
452+ @staticmethod
453+ def to_string(media_align):
454+ """
455+ Return a string representation of a media alignment.
456+ """
457+ if media_align == None or media_align == 0:
458+ return 'middle-center'
459+ if media_align & MediaAlignType.Top:
460+ align = 'top'
461+ elif media_align & MediaAlignType.Bottom:
462+ align = 'bottom'
463+ else:
464+ align = 'middle'
465+ if media_align & MediaAlignType.Right:
466+ align = align + '-right'
467+ elif media_align & MediaAlignType.Left:
468+ align = align + '-left'
469+ else:
470+ align = align + '-center'
471+ return align
472+
473+ @staticmethod
474+ def from_string(media_align):
475+ """
476+ Return a media alignment for the given string.
477+ """
478+ align = 0
479+ media_align = str(media_align)
480+ valign, halign = media_align.split("-")
481+ if valign == 'top':
482+ align = MediaAlignType.Top
483+ elif valign == 'bottom':
484+ align = MediaAlignType.Bottom
485+ else:
486+ align = MediaAlignType.Middle
487+ if halign == 'left':
488+ align = align | MediaAlignType.Left
489+ elif halign == 'right':
490+ align = align | MediaAlignType.Right
491+ else:
492+ align = align | MediaAlignType.Center
493+ return align
494
495 class BackgroundGradientType(object):
496 """
497@@ -147,10 +254,10 @@
498 Names = ['top', 'middle', 'bottom']
499
500
501-BOOLEAN_LIST = ['bold', 'italics', 'override', 'outline', 'shadow', 'slide_transition']
502+BOOLEAN_LIST = ['bold', 'italics', 'outline', 'shadow', 'slide_transition']
503
504-INTEGER_LIST = ['size', 'line_adjustment', 'x', 'height', 'y', 'width', 'shadow_size', 'outline_size',
505- 'horizontal_align', 'vertical_align', 'wrap_style']
506+INTEGER_LIST = ['size', 'line_adjustment', 'x', 'height', 'y', 'width', 'left', 'right', 'top', 'bottom',
507+ 'shadow_size', 'outline_size', 'horizontal_align', 'vertical_align', 'wrap_style', 'override']
508
509
510 class ThemeXML(object):
511@@ -191,11 +298,10 @@
512
513 :param path: The path name to be added.
514 """
515- if self.background_type == 'image':
516- if self.background_filename and path:
517- self.theme_name = self.theme_name.strip()
518- self.background_filename = self.background_filename.strip()
519- self.background_filename = os.path.join(path, self.theme_name, self.background_filename)
520+ if self.background_media_filename and path:
521+ self.theme_name = self.theme_name.strip()
522+ self.background_media_filename = self.background_media_filename.strip()
523+ self.background_media_filename = os.path.join(path, self.theme_name, self.background_media_filename )
524
525 def _new_document(self, name):
526 """
527@@ -210,61 +316,45 @@
528 self.name.appendChild(text_node)
529 self.theme.appendChild(self.name)
530
531- def add_background_transparent(self):
532- """
533- Add a transparent background.
534- """
535- background = self.theme_xml.createElement('background')
536- background.setAttribute('type', 'transparent')
537- self.theme.appendChild(background)
538-
539- def add_background_solid(self, bkcolor):
540- """
541- Add a Solid background.
542-
543- :param bkcolor: The color of the background.
544- """
545- background = self.theme_xml.createElement('background')
546- background.setAttribute('type', 'solid')
547- self.theme.appendChild(background)
548- self.child_element(background, 'color', str(bkcolor))
549-
550- def add_background_gradient(self, startcolor, endcolor, direction):
551- """
552- Add a gradient background.
553-
554- :param startcolor: The gradient's starting colour.
555- :param endcolor: The gradient's ending colour.
556- :param direction: The direction of the gradient.
557- """
558- background = self.theme_xml.createElement('background')
559- background.setAttribute('type', 'gradient')
560- self.theme.appendChild(background)
561- # Create startColor element
562- self.child_element(background, 'startColor', str(startcolor))
563- # Create endColor element
564- self.child_element(background, 'endColor', str(endcolor))
565- # Create direction element
566- self.child_element(background, 'direction', str(direction))
567-
568- def add_background_image(self, filename, border_color):
569- """
570- Add a image background.
571-
572- :param filename: The file name of the image.
573- :param border_color:
574- """
575- background = self.theme_xml.createElement('background')
576- background.setAttribute('type', 'image')
577- self.theme.appendChild(background)
578- # Create Filename element
579- self.child_element(background, 'filename', filename)
580- # Create endColor element
581- self.child_element(background, 'borderColor', str(border_color))
582+ def add_background(self, color_type, bkcolor, color_start, color_end, color_direction,
583+ media_type, media_align, media_scale, media_width, media_height, media_filename):
584+ """
585+ Add a background.
586+ """
587+ filename = ''
588+ if media_type == None:
589+ media_type = 'none'
590+ if color_type == None:
591+ color_type = 'transparent'
592+ background = self.theme_xml.createElement('background')
593+ color = self.theme_xml.createElement('color')
594+ color.setAttribute('type', str(color_type))
595+ #if color_type == BackgroundColorType.to_string(BackgroundColorType.Gradient):
596+ color.setAttribute('start', str(color_start))
597+ color.setAttribute('end', str(color_end))
598+ color.setAttribute('direction', str(color_direction))
599+ #if not color_type == BackgroundColorType.to_string(BackgroundColorType.Transparent):
600+ color_node = self.theme_xml.createTextNode(str(bkcolor))
601+ color.appendChild(color_node)
602+ background.appendChild(color)
603+ #if not media_type == BackgroundMediaType.to_string(BackgroundMediaType.Nothing):
604+ if media_filename:
605+ filename = os.path.split(media_filename)[1]
606+ media = self.theme_xml.createElement('media')
607+ media.setAttribute('type', str(media_type))
608+ media.setAttribute('align', str(media_align))
609+ media.setAttribute('scale', str(media_scale))
610+ media.setAttribute('width', str(media_width))
611+ media.setAttribute('height', str(media_height))
612+ media.setAttribute('filename', str(filename))
613+ media.setAttribute('borderColor', str(bkcolor))
614+ background.appendChild(media)
615+ self.theme.appendChild(background)
616
617 def add_font(self, name, color, size, override, fonttype='main', bold='False', italics='False',
618- line_adjustment=0, xpos=0, ypos=0, width=0, height=0, outline='False', outline_color='#ffffff',
619- outline_pixel=2, shadow='False', shadow_color='#ffffff', shadow_pixel=5):
620+ line_adjustment=0, xpos=0, ypos=0, width=0, height=0, left=0, right=0, top=0, bottom=0,
621+ outline='False', outline_color='#ffffff', outline_pixel=2, shadow='False',
622+ shadow_color='#ffffff', shadow_pixel=5):
623 """
624 Add a Font.
625
626@@ -287,6 +377,14 @@
627 :param shadow_color: The colour of the shadow.
628 :param shadow_pixel: How big the Shadow is
629 """
630+ if override >= 2:
631+ margin_override = (override == 3)
632+ else:
633+ margin_override = 0
634+ if override <= 1:
635+ location_override = (override == 1)
636+ else:
637+ location_override = 0
638 background = self.theme_xml.createElement('font')
639 background.setAttribute('type', fonttype)
640 self.theme.appendChild(background)
641@@ -302,9 +400,20 @@
642 self.child_element(background, 'italics', str(italics))
643 # Create indentation name element
644 self.child_element(background, 'line_adjustment', str(line_adjustment))
645+ # Create Margin element
646+ element = self.theme_xml.createElement('margin')
647+ element.setAttribute('override', str(margin_override))
648+ element.setAttribute('left', str(left))
649+ element.setAttribute('right', str(right))
650+ element.setAttribute('bottom', str(bottom))
651+ if fonttype == 'footer':
652+ element.setAttribute('height', str(height))
653+ else:
654+ element.setAttribute('top', str(top))
655+ background.appendChild(element)
656 # Create Location element
657 element = self.theme_xml.createElement('location')
658- element.setAttribute('override', str(override))
659+ element.setAttribute('override', str(location_override))
660 element.setAttribute('x', str(xpos))
661 element.setAttribute('y', str(ypos))
662 element.setAttribute('width', str(width))
663@@ -333,23 +442,23 @@
664 :param vertical: The vertical alignment of the text.
665 :param transition: Whether the slide transition is active.
666 """
667- background = self.theme_xml.createElement('display')
668- self.theme.appendChild(background)
669+ display = self.theme_xml.createElement('display')
670+ self.theme.appendChild( display)
671 # Horizontal alignment
672 element = self.theme_xml.createElement('horizontalAlign')
673 value = self.theme_xml.createTextNode(str(horizontal))
674 element.appendChild(value)
675- background.appendChild(element)
676+ display.appendChild(element)
677 # Vertical alignment
678 element = self.theme_xml.createElement('verticalAlign')
679 value = self.theme_xml.createTextNode(str(vertical))
680 element.appendChild(value)
681- background.appendChild(element)
682+ display.appendChild(element)
683 # Slide Transition
684 element = self.theme_xml.createElement('slideTransition')
685 value = self.theme_xml.createTextNode(str(transition))
686 element.appendChild(value)
687- background.appendChild(element)
688+ display.appendChild(element)
689
690 def child_element(self, element, tag, value):
691 """
692@@ -439,8 +548,13 @@
693 if element.attrib:
694 for attr in element.attrib:
695 base_element = attr
696- # correction for the shadow and outline tags
697- if element.tag == 'shadow' or element.tag == 'outline':
698+ # correction for special tags -- shadow, outline, ect...
699+ special_tags = ['shadow', 'outline', 'color', 'media']
700+ override_tags = ['margin', 'location']
701+ if element.tag in special_tags:
702+ if not attr.startswith(element.tag):
703+ base_element = element.tag + '_' + attr
704+ elif attr == 'override' and element.tag in override_tags:
705 if not attr.startswith(element.tag):
706 base_element = element.tag + '_' + attr
707 self._create_attr(master, base_element, element.attrib[attr])
708@@ -469,6 +583,22 @@
709 value = True
710 if element == 'proportion':
711 element = 'size'
712+ if element == 'location_override':
713+ element = 'override'
714+ if value == 'False':
715+ value = '0'
716+ elif value == 'True':
717+ value = '1'
718+ else:
719+ return True, None, None, None
720+ elif element == 'margin_override':
721+ element = 'override'
722+ if value == 'False':
723+ value = '2'
724+ elif value == 'True':
725+ value = '3'
726+ else:
727+ return True, None, None, None
728 return False, master, element, value
729
730 def _create_attr(self, master, element, value):
731@@ -508,19 +638,19 @@
732 Build the XML from the varables in the object
733 """
734 self._new_document(self.theme_name)
735- if self.background_type == BackgroundType.to_string(BackgroundType.Solid):
736- self.add_background_solid(self.background_color)
737- elif self.background_type == BackgroundType.to_string(BackgroundType.Gradient):
738- self.add_background_gradient(
739- self.background_start_color,
740- self.background_end_color,
741- self.background_direction
742- )
743- elif self.background_type == BackgroundType.to_string(BackgroundType.Image):
744- filename = os.path.split(self.background_filename)[1]
745- self.add_background_image(filename, self.background_border_color)
746- elif self.background_type == BackgroundType.to_string(BackgroundType.Transparent):
747- self.add_background_transparent()
748+ self.add_background(
749+ self.background_color_type,
750+ self.background_color,
751+ self.background_color_start,
752+ self.background_color_end,
753+ self.background_color_direction,
754+ self.background_media_type,
755+ self.background_media_align,
756+ self.background_media_scale,
757+ self.background_media_width,
758+ self.background_media_height,
759+ self.background_media_filename
760+ )
761 self.add_font(
762 self.font_main_name,
763 self.font_main_color,
764@@ -533,6 +663,10 @@
765 self.font_main_y,
766 self.font_main_width,
767 self.font_main_height,
768+ self.font_main_left,
769+ self.font_main_right,
770+ self.font_main_top,
771+ self.font_main_bottom,
772 self.font_main_outline,
773 self.font_main_outline_color,
774 self.font_main_outline_size,
775@@ -547,11 +681,15 @@
776 self.font_footer_override, 'footer',
777 self.font_footer_bold,
778 self.font_footer_italics,
779- 0, # line adjustment
780+ self.font_footer_line_adjustment,
781 self.font_footer_x,
782 self.font_footer_y,
783 self.font_footer_width,
784 self.font_footer_height,
785+ self.font_footer_left,
786+ self.font_footer_right,
787+ self.font_footer_top,
788+ self.font_footer_bottom,
789 self.font_footer_outline,
790 self.font_footer_outline_color,
791 self.font_footer_outline_size,
792
793=== modified file 'openlp/core/ui/maindisplay.py'
794--- openlp/core/ui/maindisplay.py 2014-08-27 23:18:06 +0000
795+++ openlp/core/ui/maindisplay.py 2014-10-24 20:09:17 +0000
796@@ -45,7 +45,7 @@
797
798 from openlp.core.common import Registry, RegistryProperties, OpenLPMixin, Settings, translate, is_macosx
799 from openlp.core.lib import ServiceItem, ImageSource, build_html, expand_tags, image_to_byte
800-from openlp.core.lib.theme import BackgroundType
801+from openlp.core.lib.theme import BackgroundColorType, BackgroundMediaType
802
803 from openlp.core.lib import ScreenList
804 from openlp.core.ui import HideMode, AlertLocation
805@@ -168,7 +168,7 @@
806 self.setStyleSheet("QGraphicsView {background: transparent; border: 0px;}")
807 else:
808 self.setAttribute(QtCore.Qt.WA_NoSystemBackground, False)
809- self.setStyleSheet("QGraphicsView {}")
810+ self.setStyleSheet("QGraphicsView {border: 0px;}")
811 self.setAttribute(QtCore.Qt.WA_TranslucentBackground, enabled)
812 self.repaint()
813
814@@ -280,7 +280,7 @@
815 if not hasattr(self, 'service_item'):
816 return False
817 self.override['image'] = path
818- self.override['theme'] = self.service_item.theme_data.background_filename
819+ self.override['theme'] = self.service_item.theme_data.background_media_filename
820 self.image(path)
821 # Update the preview frame.
822 if self.is_live:
823@@ -376,21 +376,31 @@
824 Registry().execute('video_background_replaced')
825 self.override = {}
826 # We have a different theme.
827- elif self.override['theme'] != service_item.theme_data.background_filename:
828+ elif self.override['theme'] != service_item.theme_data.background_media_filename :
829 Registry().execute('live_theme_changed')
830 self.override = {}
831 else:
832 # replace the background
833 background = self.image_manager.get_image_bytes(self.override['image'], ImageSource.ImagePlugin)
834- self.set_transparency(self.service_item.theme_data.background_type ==
835- BackgroundType.to_string(BackgroundType.Transparent))
836- if self.service_item.theme_data.background_filename:
837- self.service_item.bg_image_bytes = self.image_manager.get_image_bytes(
838- self.service_item.theme_data.background_filename, ImageSource.Theme)
839- if image_path:
840- image_bytes = self.image_manager.get_image_bytes(image_path, ImageSource.ImagePlugin)
841- else:
842- image_bytes = None
843+ self.set_transparency(self.service_item.theme_data.background_color_type ==
844+ BackgroundColorType.to_string(BackgroundColorType.Transparent))
845+ image_bytes = None
846+ media_image = BackgroundMediaType.to_string(BackgroundMediaType.Image)
847+ if self.service_item.theme_data.background_media_type == media_image:
848+ if self.service_item.theme_data.background_media_filename:
849+ self.service_item.image_width = int(self.service_item.theme_data.background_media_width)
850+ self.service_item.image_height = int(self.service_item.theme_data.background_media_height)
851+ if self.service_item.theme_data.background_media_scale == 'auto':
852+ image = QtGui.QImage(self.service_item.theme_data.background_media_filename)
853+ self.service_item.image_width = int(image.width())
854+ self.service_item.image_height = int(image.height())
855+ self.service_item.bg_image_bytes = self.image_manager.get_image_bytes(
856+ self.service_item.theme_data.background_media_filename,
857+ ImageSource.Theme,
858+ self.service_item.image_width,
859+ self.service_item.image_height)
860+ if image_path:
861+ image_bytes = self.image_manager.get_image_bytes(image_path, ImageSource.ImagePlugin)
862 html = build_html(self.service_item, self.screen, self.is_live, background, image_bytes,
863 plugins=self.plugin_manager.plugins)
864 self.web_view.setHtml(html)
865
866=== modified file 'openlp/core/ui/themeform.py'
867--- openlp/core/ui/themeform.py 2014-09-04 20:25:23 +0000
868+++ openlp/core/ui/themeform.py 2014-10-24 20:09:17 +0000
869@@ -35,10 +35,11 @@
870 from PyQt4 import QtCore, QtGui
871
872 from openlp.core.common import Registry, RegistryProperties, UiStrings, translate
873-from openlp.core.lib.theme import BackgroundType, BackgroundGradientType
874+from openlp.core.lib.theme import BackgroundColorType, BackgroundGradientType, \
875+ BackgroundMediaType, MediaScaleType, MediaAlignType
876 from openlp.core.lib.ui import critical_error_message_box
877 from openlp.core.ui import ThemeLayoutForm
878-from openlp.core.utils import get_images_filter, is_not_image_file
879+from openlp.core.utils import get_images_filter, is_not_image_file, delete_file
880 from .themewizard import Ui_ThemeWizard
881
882 log = logging.getLogger(__name__)
883@@ -61,25 +62,32 @@
884 self.setupUi(self)
885 self.registerFields()
886 self.update_theme_allowed = True
887- self.temp_background_filename = ''
888+ self.old_background_filename = ''
889 self.theme_layout_form = ThemeLayoutForm(self)
890- self.background_combo_box.currentIndexChanged.connect(self.on_background_combo_box_current_index_changed)
891+ self.color_type_combo_box.currentIndexChanged.connect(self.on_color_type_combo_box_current_index_changed)
892+ self.media_type_combo_box.currentIndexChanged.connect(self.on_media_type_combo_box_current_index_changed)
893+ self.image_scale_combo_box.currentIndexChanged.connect(self.on_image_scale_combo_box_current_index_changed)
894+ self.image_valign_combo_box.currentIndexChanged.connect(self.on_alignment_combo_box_current_index_changed)
895+ self.image_halign_combo_box.currentIndexChanged.connect(self.on_alignment_combo_box_current_index_changed)
896 self.gradient_combo_box.currentIndexChanged.connect(self.on_gradient_combo_box_current_index_changed)
897 self.color_button.clicked.connect(self.on_color_button_clicked)
898- self.image_color_button.clicked.connect(self.on_image_color_button_clicked)
899 self.gradient_start_button.clicked.connect(self.on_gradient_start_button_clicked)
900 self.gradient_end_button.clicked.connect(self.on_gradient_end_button_clicked)
901 self.image_browse_button.clicked.connect(self.on_image_browse_button_clicked)
902 self.image_file_edit.editingFinished.connect(self.on_image_file_edit_editing_finished)
903+ self.image_width_spin_box.valueChanged.connect(self.update_theme)
904+ self.image_height_spin_box.valueChanged.connect(self.update_theme)
905 self.main_color_button.clicked.connect(self.on_main_color_button_clicked)
906 self.outline_color_button.clicked.connect(self.on_outline_color_button_clicked)
907 self.shadow_color_button.clicked.connect(self.on_shadow_color_button_clicked)
908 self.outline_check_box.stateChanged.connect(self.on_outline_check_check_box_state_changed)
909 self.shadow_check_box.stateChanged.connect(self.on_shadow_check_check_box_state_changed)
910 self.footer_color_button.clicked.connect(self.on_footer_color_button_clicked)
911- self.customButtonClicked.connect(self.on_custom_1_button_clicked)
912- self.main_position_check_box.stateChanged.connect(self.on_main_position_check_box_state_changed)
913- self.footer_position_check_box.stateChanged.connect(self.on_footer_position_check_box_state_changed)
914+ self.customButtonClicked.connect(self.on_custom_button_clicked)
915+ self.main_position_combo_box.currentIndexChanged.connect(
916+ self.on_main_position_combo_box_current_index_changed)
917+ self.footer_position_combo_box.currentIndexChanged.connect(
918+ self.on_footer_position_combo_box_current_index_changed)
919 self.currentIdChanged.connect(self.on_current_id_changed)
920 Registry().register_function('theme_line_count', self.update_lines_text)
921 self.main_size_spin_box.valueChanged.connect(self.calculate_lines)
922@@ -90,11 +98,19 @@
923 self.footer_font_combo_box.activated.connect(self.update_theme)
924 self.footer_size_spin_box.valueChanged.connect(self.update_theme)
925
926+ def init_values(self):
927+ """
928+ Set up the inital values of variables
929+ """
930+ self.setField('image_width', self.theme.background_media_width)
931+ self.setField('image_height', self.theme.background_media_height)
932+
933 def set_defaults(self):
934 """
935 Set up display at start of theme edit.
936 """
937 self.restart()
938+ self.init_values()
939 self.set_background_page_values()
940 self.set_main_area_page_values()
941 self.set_footer_area_page_values()
942@@ -106,12 +122,18 @@
943 """
944 Map field names to screen names,
945 """
946- self.background_page.registerField('background_type', self.background_combo_box)
947+ self.background_page.registerField('color_type', self.color_type_combo_box)
948+ self.background_page.registerField('media_type', self.media_type_combo_box)
949 self.background_page.registerField('color', self.color_button)
950 self.background_page.registerField('gradient_start', self.gradient_start_button)
951 self.background_page.registerField('gradient_end', self.gradient_end_button)
952 self.background_page.registerField('background_image', self.image_file_edit)
953 self.background_page.registerField('gradient', self.gradient_combo_box)
954+ self.background_page.registerField('image_valign', self.image_valign_combo_box)
955+ self.background_page.registerField('image_halign', self.image_halign_combo_box)
956+ self.background_page.registerField('image_scale', self.image_scale_combo_box)
957+ self.background_page.registerField('image_width', self.image_width_spin_box)
958+ self.background_page.registerField('image_height', self.image_height_spin_box)
959 self.main_area_page.registerField('main_color_button', self.main_color_button)
960 self.main_area_page.registerField('main_size_spin_box', self.main_size_spin_box)
961 self.main_area_page.registerField('line_spacing_spin_box', self.line_spacing_spin_box)
962@@ -124,13 +146,22 @@
963 self.main_area_page.registerField('shadow_color_button', self.shadow_color_button)
964 self.main_area_page.registerField('shadow_size_spin_box', self.shadow_size_spin_box)
965 self.main_area_page.registerField('footer_size_spin_box', self.footer_size_spin_box)
966+ self.area_position_page.registerField('main_position_override', self.main_position_combo_box)
967 self.area_position_page.registerField('main_position_x', self.main_x_spin_box)
968 self.area_position_page.registerField('main_position_y', self.main_y_spin_box)
969 self.area_position_page.registerField('main_position_width', self.main_width_spin_box)
970 self.area_position_page.registerField('main_position_height', self.main_height_spin_box)
971+ self.area_position_page.registerField('main_position_left', self.main_left_spin_box)
972+ self.area_position_page.registerField('main_position_right', self.main_right_spin_box)
973+ self.area_position_page.registerField('main_position_top', self.main_top_spin_box)
974+ self.area_position_page.registerField('main_position_bottom', self.main_bottom_spin_box)
975+ self.area_position_page.registerField('footer_position_override', self.footer_position_combo_box)
976 self.area_position_page.registerField('footer_position_x', self.footer_x_spin_box)
977 self.area_position_page.registerField('footer_position_y', self.footer_y_spin_box)
978 self.area_position_page.registerField('footer_position_width', self.footer_width_spin_box)
979+ self.area_position_page.registerField('footer_position_left', self.footer_left_spin_box)
980+ self.area_position_page.registerField('footer_position_right', self.footer_right_spin_box)
981+ self.area_position_page.registerField('footer_position_bottom', self.footer_bottom_spin_box)
982 self.area_position_page.registerField('footer_position_height', self.footer_height_spin_box)
983 self.background_page.registerField('horizontal', self.horizontal_combo_box)
984 self.background_page.registerField('vertical', self.vertical_combo_box)
985@@ -175,9 +206,10 @@
986 """
987 Validate the current page
988 """
989- background_image = BackgroundType.to_string(BackgroundType.Image)
990+ background_image = BackgroundMediaType.to_string(BackgroundMediaType.Image)
991 if self.page(self.currentId()) == self.background_page and \
992- self.theme.background_type == background_image and is_not_image_file(self.theme.background_filename):
993+ self.theme.background_media_type == background_image and \
994+ is_not_image_file(self.theme.background_media_filename):
995 QtGui.QMessageBox.critical(self, translate('OpenLP.ThemeWizard', 'Background Image Empty'),
996 translate('OpenLP.ThemeWizard', 'You have not selected a '
997 'background image. Please select one before continuing.'))
998@@ -189,8 +221,22 @@
999 """
1000 Detects Page changes and updates as appropriate.
1001 """
1002- enabled = self.page(page_id) == self.area_position_page
1003- self.setOption(QtGui.QWizard.HaveCustomButton1, enabled)
1004+ is_first_page = page_id == 0
1005+ is_last_page = self.page(page_id) == self.preview_page
1006+ is_position_page = self.page(page_id) == self.area_position_page
1007+ if is_first_page:
1008+ button_layout = [QtGui.QWizard.Stretch, QtGui.QWizard.NextButton, QtGui.QWizard.CancelButton]
1009+ elif is_position_page:
1010+ button_layout = [QtGui.QWizard.CustomButton1, QtGui.QWizard.Stretch, QtGui.QWizard.CustomButton2, \
1011+ QtGui.QWizard.BackButton, QtGui.QWizard.NextButton, QtGui.QWizard.CancelButton]
1012+ elif is_last_page:
1013+ button_layout = [QtGui.QWizard.Stretch, QtGui.QWizard.BackButton, \
1014+ QtGui.QWizard.FinishButton, QtGui.QWizard.CancelButton]
1015+ else:
1016+ button_layout = [QtGui.QWizard.CustomButton1, QtGui.QWizard.Stretch, \
1017+ QtGui.QWizard.BackButton, QtGui.QWizard.NextButton, \
1018+ QtGui.QWizard.CancelButton]
1019+ self.setButtonLayout(button_layout)
1020 if self.page(page_id) == self.preview_page:
1021 self.update_theme()
1022 frame = self.theme_manager.generate_image(self.theme)
1023@@ -198,8 +244,25 @@
1024 self.display_aspect_ratio = float(frame.width()) / frame.height()
1025 self.resizeEvent()
1026
1027+ def on_custom_button_clicked(self, number):
1028+ """
1029+ Determine which custom button was clicked
1030+ """
1031+ if number == QtGui.QWizard.CustomButton1.numerator:
1032+ self.on_custom_1_button_clicked(number)
1033+ elif number == QtGui.QWizard.CustomButton2.numerator:
1034+ self.on_custom_2_button_clicked(number)
1035+
1036 def on_custom_1_button_clicked(self, number):
1037 """
1038+ Save has been clicked
1039+ """
1040+ if self.validateCurrentPage():
1041+ self.update_theme()
1042+ self.accept()
1043+
1044+ def on_custom_2_button_clicked(self, number):
1045+ """
1046 Generate layout preview and display the form.
1047 """
1048 self.update_theme()
1049@@ -238,28 +301,47 @@
1050 self.shadow_size_spin_box.setEnabled(self.theme.font_main_shadow)
1051 self.calculate_lines()
1052
1053- def on_main_position_check_box_state_changed(self, value):
1054- """
1055- Change state as Main Area _position check box changed
1056- NOTE the font_main_override is the inverse of the check box value
1057- """
1058- if self.update_theme_allowed:
1059- self.theme.font_main_override = not (value == QtCore.Qt.Checked)
1060-
1061- def on_footer_position_check_box_state_changed(self, value):
1062- """
1063- Change state as Footer Area _position check box changed
1064- NOTE the font_footer_override is the inverse of the check box value
1065- """
1066- if self.update_theme_allowed:
1067- self.theme.font_footer_override = not (value == QtCore.Qt.Checked)
1068+ def on_main_position_combo_box_current_index_changed(self, index):
1069+ """
1070+ Change state as Main Area _position combo box changed
1071+ NOTE the font_main_override equals 1 means use location override
1072+ and 2 means use margin override; whereas, 0 means to use defaults
1073+ """
1074+ if self.update_theme_allowed:
1075+ self.theme.font_main_override = int(index)
1076+ self.set_position_page_values()
1077+
1078+ def on_main_position_combo_box_current_index_changed(self, index):
1079+ """
1080+ Change state as Main Area _position combo box changed
1081+ NOTE the font_main_override
1082+ 0 means to use location defaults
1083+ 1 means to use location user-defined values
1084+ 2 means to use margin defaults
1085+ 3 means to use margin user-defined values
1086+ """
1087+ if self.update_theme_allowed:
1088+ self.theme.font_main_override = int(index)
1089+ self.set_position_page_values()
1090+
1091+ def on_footer_position_combo_box_current_index_changed(self, index):
1092+ """
1093+ Change state as Footer Area _position combo box changed
1094+ NOTE the font_footer_override
1095+ 0 means to use location defaults
1096+ 1 means to use location user-defined values
1097+ 2 means to use margin defaults
1098+ 3 means to use margin user-defined values
1099+ """
1100+ if self.update_theme_allowed:
1101+ self.theme.font_footer_override = int(index)
1102+ self.set_position_page_values()
1103
1104 def exec_(self, edit=False):
1105 """
1106 Run the wizard.
1107 """
1108 log.debug('Editing theme %s' % self.theme.theme_name)
1109- self.temp_background_filename = ''
1110 self.update_theme_allowed = False
1111 self.set_defaults()
1112 self.update_theme_allowed = True
1113@@ -294,29 +376,51 @@
1114 """
1115 Handle the display and state of the Background page.
1116 """
1117- if self.theme.background_type == BackgroundType.to_string(BackgroundType.Solid):
1118+ if self.theme.background_color_type == BackgroundColorType.to_string(BackgroundColorType.Solid):
1119 self.color_button.setStyleSheet('background-color: %s' % self.theme.background_color)
1120- self.setField('background_type', 0)
1121- elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Gradient):
1122- self.gradient_start_button.setStyleSheet('background-color: %s' % self.theme.background_start_color)
1123- self.gradient_end_button.setStyleSheet('background-color: %s' % self.theme.background_end_color)
1124- self.setField('background_type', 1)
1125- elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Image):
1126- self.image_color_button.setStyleSheet('background-color: %s' % self.theme.background_border_color)
1127- self.image_file_edit.setText(self.theme.background_filename)
1128- self.setField('background_type', 2)
1129- elif self.theme.background_type == BackgroundType.to_string(BackgroundType.Transparent):
1130- self.setField('background_type', 3)
1131- if self.theme.background_direction == BackgroundGradientType.to_string(BackgroundGradientType.Horizontal):
1132- self.setField('gradient', 0)
1133- elif self.theme.background_direction == BackgroundGradientType.to_string(BackgroundGradientType.Vertical):
1134- self.setField('gradient', 1)
1135- elif self.theme.background_direction == BackgroundGradientType.to_string(BackgroundGradientType.Circular):
1136- self.setField('gradient', 2)
1137- elif self.theme.background_direction == BackgroundGradientType.to_string(BackgroundGradientType.LeftTop):
1138- self.setField('gradient', 3)
1139+ self.setField('color_type', BackgroundColorType.Solid)
1140+ elif self.theme.background_color_type == BackgroundColorType.to_string(BackgroundColorType.Gradient):
1141+ self.gradient_start_button.setStyleSheet('background-color: %s' % self.theme.background_color_start)
1142+ self.gradient_end_button.setStyleSheet('background-color: %s' % self.theme.background_color_end)
1143+ self.setField('color_type', BackgroundColorType.Gradient)
1144+ elif self.theme.background_color_type == BackgroundColorType.to_string(BackgroundColorType.Transparent):
1145+ self.setField('color_type', BackgroundColorType.Transparent)
1146+ if self.theme.background_color_direction == BackgroundGradientType.to_string(BackgroundGradientType.Horizontal):
1147+ self.setField('gradient', BackgroundGradientType.Horizontal)
1148+ elif self.theme.background_color_direction == BackgroundGradientType.to_string(BackgroundGradientType.Vertical):
1149+ self.setField('gradient', BackgroundGradientType.Vertical)
1150+ elif self.theme.background_color_direction == BackgroundGradientType.to_string(BackgroundGradientType.Circular):
1151+ self.setField('gradient', BackgroundGradientType.Circular)
1152+ elif self.theme.background_color_direction == BackgroundGradientType.to_string(BackgroundGradientType.LeftTop):
1153+ self.setField('gradient', BackgroundGradientType.LeftTop)
1154 else:
1155- self.setField('gradient', 4)
1156+ self.setField('gradient', BackgroundGradientType.LeftBottom)
1157+ if self.theme.background_media_type == BackgroundMediaType.to_string(BackgroundMediaType.Image):
1158+ if self.theme.background_media_filename:
1159+ self.image_file_edit.setText(os.path.split(str(self.theme.background_media_filename))[1])
1160+ self.setField('media_type', BackgroundMediaType.Image)
1161+ self.setField('image_scale', MediaScaleType.from_string(self.theme.background_media_scale))
1162+ fixed_enabled = self.theme.background_media_scale == \
1163+ MediaScaleType.to_string(MediaScaleType.Fixed)
1164+ self.image_fixed_widget.setVisible(fixed_enabled)
1165+ fullscreen_enabled = self.theme.background_media_scale == \
1166+ MediaScaleType.to_string(MediaScaleType.Fullscreen)
1167+ self.image_align_label.setVisible(not fullscreen_enabled)
1168+ self.image_align_widget.setVisible(not fullscreen_enabled)
1169+ if not fullscreen_enabled:
1170+ media_align = MediaAlignType.from_string(self.theme.background_media_align)
1171+ if media_align & MediaAlignType.Top:
1172+ self.setField('image_valign', 0)
1173+ elif media_align & MediaAlignType.Bottom:
1174+ self.setField('image_valign', 2)
1175+ else:
1176+ self.setField('image_valign', 1)
1177+ if media_align & MediaAlignType.Left:
1178+ self.setField('image_halign', 0)
1179+ elif media_align & MediaAlignType.Right:
1180+ self.setField('image_halign', 2)
1181+ else:
1182+ self.setField('image_halign', 1)
1183
1184 def set_main_area_page_values(self):
1185 """
1186@@ -348,17 +452,31 @@
1187 Handle the display and state of the _position page.
1188 """
1189 # Main Area
1190- self.main_position_check_box.setChecked(not self.theme.font_main_override)
1191 self.setField('main_position_x', self.theme.font_main_x)
1192 self.setField('main_position_y', self.theme.font_main_y)
1193 self.setField('main_position_height', self.theme.font_main_height)
1194 self.setField('main_position_width', self.theme.font_main_width)
1195- # Footer
1196- self.footer_position_check_box.setChecked(not self.theme.font_footer_override)
1197+ self.setField('main_position_left', self.theme.font_main_left)
1198+ self.setField('main_position_right', self.theme.font_main_right)
1199+ self.setField('main_position_top', self.theme.font_main_top)
1200+ self.setField('main_position_bottom', self.theme.font_main_bottom)
1201+ self.setField('main_position_override', self.theme.font_main_override)
1202+ self.main_margin_widget.setEnabled(self.theme.font_main_override == 3)
1203+ self.main_location_widget.setEnabled(self.theme.font_main_override == 1)
1204+ self.main_position_stack.setCurrentIndex(int(self.theme.font_main_override > 1))
1205+ # Footer Area
1206 self.setField('footer_position_x', self.theme.font_footer_x)
1207 self.setField('footer_position_y', self.theme.font_footer_y)
1208 self.setField('footer_position_height', self.theme.font_footer_height)
1209 self.setField('footer_position_width', self.theme.font_footer_width)
1210+ self.setField('footer_position_left', self.theme.font_footer_left)
1211+ self.setField('footer_position_right', self.theme.font_footer_right)
1212+ self.setField('footer_position_bottom', self.theme.font_footer_bottom)
1213+ self.setField('footer_position_override', self.theme.font_footer_override)
1214+ self.footer_height_widget.setEnabled(self.theme.font_footer_override % 2)
1215+ self.footer_margin_widget.setEnabled(self.theme.font_footer_override == 3)
1216+ self.footer_location_widget.setEnabled(self.theme.font_footer_override == 1)
1217+ self.footer_position_stack.setCurrentIndex(int(self.theme.font_footer_override > 1))
1218
1219 def set_alignment_page_values(self):
1220 """
1221@@ -374,21 +492,22 @@
1222 """
1223 self.setField('name', self.theme.theme_name)
1224
1225- def on_background_combo_box_current_index_changed(self, index):
1226- """
1227- Background style Combo box has changed.
1228- """
1229- # do not allow updates when screen is building for the first time.
1230- if self.update_theme_allowed:
1231- self.theme.background_type = BackgroundType.to_string(index)
1232- if self.theme.background_type != BackgroundType.to_string(BackgroundType.Image) and \
1233- self.temp_background_filename == '':
1234- self.temp_background_filename = self.theme.background_filename
1235- self.theme.background_filename = ''
1236- if self.theme.background_type == BackgroundType.to_string(BackgroundType.Image) and \
1237- self.temp_background_filename != '':
1238- self.theme.background_filename = self.temp_background_filename
1239- self.temp_background_filename = ''
1240+ def on_color_type_combo_box_current_index_changed(self, index):
1241+ """
1242+ Background color type Combo box has changed.
1243+ """
1244+ # do not allow updates when screen is building for the first time.
1245+ if self.update_theme_allowed:
1246+ self.theme.background_color_type = BackgroundColorType.to_string(index)
1247+ self.set_background_page_values()
1248+
1249+ def on_media_type_combo_box_current_index_changed(self, index):
1250+ """
1251+ Background media type Combo box has changed.
1252+ """
1253+ # do not allow updates when screen is building for the first time.
1254+ if self.update_theme_allowed:
1255+ self.theme.background_media_type = BackgroundMediaType.to_string(index)
1256 self.set_background_page_values()
1257
1258 def on_gradient_combo_box_current_index_changed(self, index):
1259@@ -396,7 +515,37 @@
1260 Background gradient Combo box has changed.
1261 """
1262 if self.update_theme_allowed:
1263- self.theme.background_direction = BackgroundGradientType.to_string(index)
1264+ self.theme.background_color_direction = BackgroundGradientType.to_string(index)
1265+ self.set_background_page_values()
1266+
1267+ def on_image_scale_combo_box_current_index_changed(self, index):
1268+ """
1269+ Background image scale Combo box has changed.
1270+ """
1271+ if self.update_theme_allowed:
1272+ self.theme.background_media_scale = MediaScaleType.to_string(index)
1273+ self.set_background_page_values()
1274+
1275+ def on_alignment_combo_box_current_index_changed(self, index):
1276+ """
1277+ Background image alignment Combo box has changed.
1278+ """
1279+ if self.update_theme_allowed:
1280+ valign = self.image_valign_combo_box.currentIndex()
1281+ halign = self.image_halign_combo_box.currentIndex()
1282+ if valign == 0:
1283+ valign = MediaAlignType.Top
1284+ elif valign == 1:
1285+ valign = MediaAlignType.Middle
1286+ elif valign == 2:
1287+ valign = MediaAlignType.Bottom
1288+ if halign == 0:
1289+ halign = MediaAlignType.Left
1290+ elif halign == 1:
1291+ halign = MediaAlignType.Center
1292+ elif halign == 2:
1293+ halign = MediaAlignType.Right
1294+ self.theme.background_media_align = MediaAlignType.to_string(valign | halign)
1295 self.set_background_page_values()
1296
1297 def on_color_button_clicked(self):
1298@@ -406,25 +555,18 @@
1299 self.theme.background_color = self._color_button(self.theme.background_color)
1300 self.set_background_page_values()
1301
1302- def on_image_color_button_clicked(self):
1303- """
1304- Background / Gradient 1 _color button pushed.
1305- """
1306- self.theme.background_border_color = self._color_button(self.theme.background_border_color)
1307- self.set_background_page_values()
1308-
1309 def on_gradient_start_button_clicked(self):
1310 """
1311 Gradient 2 _color button pushed.
1312 """
1313- self.theme.background_start_color = self._color_button(self.theme.background_start_color)
1314+ self.theme.background_color_start = self._color_button(self.theme.background_color_start)
1315 self.set_background_page_values()
1316
1317 def on_gradient_end_button_clicked(self):
1318 """
1319 Gradient 2 _color button pushed.
1320 """
1321- self.theme.background_end_color = self._color_button(self.theme.background_end_color)
1322+ self.theme.background_color_end = self._color_button(self.theme.background_color_end)
1323 self.set_background_page_values()
1324
1325 def on_image_browse_button_clicked(self):
1326@@ -436,14 +578,15 @@
1327 filename = QtGui.QFileDialog.getOpenFileName(self, translate('OpenLP.ThemeWizard', 'Select Image'), '',
1328 images_filter)
1329 if filename:
1330- self.theme.background_filename = str(filename)
1331+ self.theme.background_media_filename = str(filename)
1332 self.set_background_page_values()
1333
1334 def on_image_file_edit_editing_finished(self):
1335 """
1336 Background image path edited
1337 """
1338- self.theme.background_filename = str(self.image_file_edit.text())
1339+ if os.path.split(str(self.theme.background_media_filename))[1] != str(self.image_file_edit.text()):
1340+ self.theme.background_media_filename = str(self.image_file_edit.text())
1341
1342 def on_main_color_button_clicked(self):
1343 """
1344@@ -481,6 +624,11 @@
1345 if not self.update_theme_allowed:
1346 return
1347 log.debug('update_theme')
1348+ # background page
1349+ if self.theme.background_media_type == BackgroundMediaType.to_string(BackgroundMediaType.Image):
1350+ if self.theme.background_media_scale == MediaScaleType.to_string(MediaScaleType.Fixed):
1351+ self.theme.background_media_width = int(self.field('image_width'))
1352+ self.theme.background_media_height = int(self.field('image_height'))
1353 # main page
1354 self.theme.font_main_name = self.main_font_combo_box.currentFont().family()
1355 self.theme.font_main_size = self.field('main_size_spin_box')
1356@@ -497,10 +645,17 @@
1357 self.theme.font_main_y = self.field('main_position_y')
1358 self.theme.font_main_height = self.field('main_position_height')
1359 self.theme.font_main_width = self.field('main_position_width')
1360+ self.theme.font_main_left = self.field('main_position_left')
1361+ self.theme.font_main_right = self.field('main_position_right')
1362+ self.theme.font_main_top = self.field('main_position_top')
1363+ self.theme.font_main_bottom = self.field('main_position_bottom')
1364 self.theme.font_footer_x = self.field('footer_position_x')
1365 self.theme.font_footer_y = self.field('footer_position_y')
1366+ self.theme.font_footer_width = self.field('footer_position_width')
1367+ self.theme.font_footer_left = self.field('footer_position_left')
1368+ self.theme.font_footer_right = self.field('footer_position_right')
1369+ self.theme.font_footer_bottom = self.field('footer_position_bottom')
1370 self.theme.font_footer_height = self.field('footer_position_height')
1371- self.theme.font_footer_width = self.field('footer_position_width')
1372 # position page
1373 self.theme.display_horizontal_align = self.horizontal_combo_box.currentIndex()
1374 self.theme.display_vertical_align = self.vertical_combo_box.currentIndex()
1375@@ -524,10 +679,10 @@
1376 return
1377 save_from = None
1378 save_to = None
1379- if self.theme.background_type == BackgroundType.to_string(BackgroundType.Image):
1380- filename = os.path.split(str(self.theme.background_filename))[1]
1381+ if self.theme.background_media_type != BackgroundMediaType.to_string(BackgroundMediaType.Nothing):
1382+ filename = os.path.split(str(self.theme.background_media_filename ))[1]
1383 save_to = os.path.join(self.path, self.theme.theme_name, filename)
1384- save_from = self.theme.background_filename
1385+ save_from = self.theme.background_media_filename
1386 if not self.edit_mode and not self.theme_manager.check_if_theme_exists(self.theme.theme_name):
1387 return
1388 self.theme_manager.save_theme(self.theme, save_from, save_to)
1389
1390=== modified file 'openlp/core/ui/thememanager.py'
1391--- openlp/core/ui/thememanager.py 2014-08-04 17:12:03 +0000
1392+++ openlp/core/ui/thememanager.py 2014-10-24 20:09:17 +0000
1393@@ -40,7 +40,7 @@
1394 check_directory_exists, UiStrings, translate
1395 from openlp.core.lib import FileDialog, ImageSource, OpenLPToolbar, get_text_file_string, build_icon, \
1396 check_item_selected, create_thumb, validate_thumb
1397-from openlp.core.lib.theme import ThemeXML, BackgroundType
1398+from openlp.core.lib.theme import ThemeXML, BackgroundColorType, BackgroundMediaType
1399 from openlp.core.lib.ui import critical_error_message_box, create_widget_action
1400 from openlp.core.ui import FileRenameForm, ThemeForm
1401 from openlp.core.utils import delete_file, get_locale_key, get_filesystem_encoding
1402@@ -306,9 +306,9 @@
1403 """
1404 save_to = None
1405 save_from = None
1406- if theme_data.background_type == 'image':
1407- save_to = os.path.join(self.path, new_theme_name, os.path.split(str(theme_data.background_filename))[1])
1408- save_from = theme_data.background_filename
1409+ if theme_data.background_media_type == 'image':
1410+ save_to = os.path.join(self.path, new_theme_name, os.path.split(str(theme_data.background_media_filename ))[1])
1411+ save_from = theme_data.background_media_filename
1412 theme_data.theme_name = new_theme_name
1413 theme_data.extend_image_filename(self.path)
1414 self.save_theme(theme_data, save_from, save_to)
1415@@ -324,11 +324,9 @@
1416 translate('OpenLP.ThemeManager', 'You must select a theme to edit.')):
1417 item = self.theme_list_widget.currentItem()
1418 theme = self.get_theme_data(item.data(QtCore.Qt.UserRole))
1419- if theme.background_type == 'image':
1420- self.old_background_image = theme.background_filename
1421+ self.old_background_image = os.path.split(str(theme.background_media_filename))[1]
1422 self.theme_form.theme = theme
1423 self.theme_form.exec_(True)
1424- self.old_background_image = None
1425 self.renderer.update_theme(theme.theme_name)
1426 self.load_themes()
1427
1428@@ -630,10 +628,12 @@
1429 :param image_to: Where the Theme Image is to be saved to
1430 """
1431 self._write_theme(theme, image_from, image_to)
1432- if theme.background_type == BackgroundType.to_string(BackgroundType.Image):
1433- self.image_manager.update_image_border(theme.background_filename,
1434- ImageSource.Theme,
1435- QtGui.QColor(theme.background_border_color))
1436+ if theme.background_media_type == BackgroundMediaType.to_string(BackgroundMediaType.Image):
1437+ theme_background_color = QtCore.Qt.transparent
1438+ if theme.background_color_type == BackgroundColorType.to_string(BackgroundColorType.Solid):
1439+ theme_background_color = QtGui.QColor(theme.background_color)
1440+ self.image_manager.update_images_border(ImageSource.Theme,
1441+ theme_background_color)
1442 self.image_manager.process_updates()
1443
1444 def _write_theme(self, theme, image_from, image_to):
1445@@ -646,12 +646,14 @@
1446 """
1447 name = theme.theme_name
1448 theme_pretty_xml = theme.extract_formatted_xml()
1449+ filename = os.path.split(str(theme.background_media_filename))[1]
1450 theme_dir = os.path.join(self.path, name)
1451 check_directory_exists(theme_dir)
1452 theme_file = os.path.join(theme_dir, name + '.xml')
1453- if self.old_background_image and image_to != self.old_background_image:
1454- delete_file(self.old_background_image)
1455 out_file = None
1456+ if self.old_background_image:
1457+ if self.old_background_image != filename:
1458+ delete_file(os.path.join(self.path, name, self.old_background_image))
1459 try:
1460 out_file = open(theme_file, 'w')
1461 out_file.write(theme_pretty_xml.decode('UTF-8'))
1462@@ -722,7 +724,11 @@
1463 """
1464 theme = ThemeXML()
1465 theme.parse(theme_xml)
1466- theme.extend_image_filename(image_path)
1467+ if theme.background_media_filename:
1468+ theme.extend_image_filename(image_path)
1469+ if not os.path.isfile(theme.background_media_filename):
1470+ theme.background_media_type = None
1471+ theme.background_media_filename = None
1472 return theme
1473
1474 def _validate_theme_action(self, select_text, confirm_title, confirm_text, test_plugin=True, confirm=True):
1475
1476=== modified file 'openlp/core/ui/themewizard.py'
1477--- openlp/core/ui/themewizard.py 2014-10-08 19:42:30 +0000
1478+++ openlp/core/ui/themewizard.py 2014-10-24 20:09:17 +0000
1479@@ -33,7 +33,8 @@
1480
1481 from openlp.core.common import UiStrings, translate, is_macosx
1482 from openlp.core.lib import build_icon
1483-from openlp.core.lib.theme import HorizontalType, BackgroundType, BackgroundGradientType
1484+from openlp.core.lib.theme import HorizontalType, BackgroundColorType, BackgroundGradientType, \
1485+ BackgroundMediaType, MediaScaleType, MediaAlignType
1486 from openlp.core.lib.ui import add_welcome_page, create_valign_selection_widgets
1487
1488
1489@@ -47,12 +48,15 @@
1490 """
1491 theme_wizard.setObjectName('OpenLP.ThemeWizard')
1492 theme_wizard.setWindowIcon(build_icon(u':/icon/openlp-logo.svg'))
1493+ theme_wizard.setMinimumSize(0, 420)
1494 theme_wizard.setModal(True)
1495 theme_wizard.setOptions(QtGui.QWizard.IndependentPages |
1496- QtGui.QWizard.NoBackButtonOnStartPage | QtGui.QWizard.HaveCustomButton1)
1497+ QtGui.QWizard.NoBackButtonOnStartPage |
1498+ QtGui.QWizard.HaveCustomButton1 |
1499+ QtGui.QWizard.HaveCustomButton2 )
1500 if is_macosx():
1501 theme_wizard.setPixmap(QtGui.QWizard.BackgroundPixmap, QtGui.QPixmap(':/wizards/openlp-osx-wizard.png'))
1502- theme_wizard.resize(646, 400)
1503+ theme_wizard.resize(646, 420)
1504 else:
1505 theme_wizard.setWizardStyle(QtGui.QWizard.ModernStyle)
1506 self.spacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum)
1507@@ -63,18 +67,18 @@
1508 self.background_page.setObjectName('background_page')
1509 self.background_layout = QtGui.QVBoxLayout(self.background_page)
1510 self.background_layout.setObjectName('background_layout')
1511- self.background_type_layout = QtGui.QFormLayout()
1512- self.background_type_layout.setObjectName('background_type_layout')
1513- self.background_label = QtGui.QLabel(self.background_page)
1514- self.background_label.setObjectName('background_label')
1515- self.background_combo_box = QtGui.QComboBox(self.background_page)
1516- self.background_combo_box.addItems(['', '', '', ''])
1517- self.background_combo_box.setObjectName('background_combo_box')
1518- self.background_type_layout.addRow(self.background_label, self.background_combo_box)
1519- self.background_type_layout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
1520- self.background_layout.addLayout(self.background_type_layout)
1521- self.background_stack = QtGui.QStackedLayout()
1522- self.background_stack.setObjectName('background_stack')
1523+ self.color_type_layout = QtGui.QFormLayout()
1524+ self.color_type_layout.setObjectName('color_type_layout')
1525+ self.color_type_label = QtGui.QLabel(self.background_page)
1526+ self.color_type_label.setObjectName('color_type_label')
1527+ self.color_type_combo_box = QtGui.QComboBox(self.background_page)
1528+ self.color_type_combo_box.addItems(['', '', ''])
1529+ self.color_type_combo_box.setObjectName('color_type_combo_box')
1530+ self.color_type_layout.addRow(self.color_type_label, self.color_type_combo_box)
1531+ self.color_type_layout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
1532+ self.background_layout.addLayout(self.color_type_layout)
1533+ self.color_stack = QtGui.QStackedLayout()
1534+ self.color_stack.setObjectName('color_stack')
1535 self.color_widget = QtGui.QWidget(self.background_page)
1536 self.color_widget.setObjectName('color_widget')
1537 self.color_layout = QtGui.QFormLayout(self.color_widget)
1538@@ -86,7 +90,7 @@
1539 self.color_button.setObjectName('color_button')
1540 self.color_layout.addRow(self.color_label, self.color_button)
1541 self.color_layout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
1542- self.background_stack.addWidget(self.color_widget)
1543+ self.color_stack.addWidget(self.color_widget)
1544 self.gradient_widget = QtGui.QWidget(self.background_page)
1545 self.gradient_widget.setObjectName('Gradient_widget')
1546 self.gradient_layout = QtGui.QFormLayout(self.gradient_widget)
1547@@ -109,20 +113,87 @@
1548 self.gradient_combo_box.addItems(['', '', '', '', ''])
1549 self.gradient_layout.addRow(self.gradient_type_label, self.gradient_combo_box)
1550 self.gradient_layout.setItem(3, QtGui.QFormLayout.LabelRole, self.spacer)
1551- self.background_stack.addWidget(self.gradient_widget)
1552+ self.color_stack.addWidget(self.gradient_widget)
1553+ self.transparent_widget = QtGui.QWidget(self.background_page)
1554+ self.transparent_widget.setObjectName('TransparentWidget')
1555+ self.transparent_layout = QtGui.QFormLayout(self.transparent_widget)
1556+ self.transparent_layout.setMargin(0)
1557+ self.transparent_layout.setObjectName('Transparent_layout')
1558+ self.color_stack.addWidget(self.transparent_widget)
1559+ self.background_layout.addLayout(self.color_stack)
1560+ self.media_type_layout = QtGui.QFormLayout()
1561+ self.media_type_layout.setObjectName('media_type_layout')
1562+ self.media_type_label = QtGui.QLabel(self.background_page)
1563+ self.media_type_label.setObjectName('media_type_label')
1564+ self.media_type_combo_box = QtGui.QComboBox(self.background_page)
1565+ self.media_type_combo_box.addItems(['', ''])
1566+ self.media_type_combo_box.setObjectName('media_type_combo_box')
1567+ self.media_type_layout.addRow(self.media_type_label, self.media_type_combo_box)
1568+ self.media_type_layout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
1569+ self.background_layout.addLayout(self.media_type_layout)
1570+ self.media_stack = QtGui.QStackedLayout()
1571+ self.media_stack.setObjectName('media_stack')
1572+ self.nothing_widget = QtGui.QWidget(self.background_page)
1573+ self.nothing_widget.setObjectName('nothing_widget')
1574+ self.media_stack.addWidget(self.nothing_widget)
1575 self.image_widget = QtGui.QWidget(self.background_page)
1576 self.image_widget.setObjectName('image_widget')
1577 self.image_layout = QtGui.QFormLayout(self.image_widget)
1578 self.image_layout.setMargin(0)
1579 self.image_layout.setObjectName('image_layout')
1580- self.image_color_label = QtGui.QLabel(self.color_widget)
1581- self.image_color_label.setObjectName('image_color_label')
1582- self.image_color_button = QtGui.QPushButton(self.color_widget)
1583- self.image_color_button.setObjectName('image_color_button')
1584- self.image_layout.addRow(self.image_color_label, self.image_color_button)
1585- self.image_label = QtGui.QLabel(self.image_widget)
1586- self.image_label.setObjectName('image_label')
1587+ self.image_scale_label = QtGui.QLabel(self.image_widget)
1588+ self.image_scale_label.setObjectName('image_scale_label')
1589+ self.image_scale_layout = QtGui.QHBoxLayout()
1590+ self.image_scale_layout.setMargin(0)
1591+ self.image_scale_layout.setObjectName('image_scale_layout')
1592+ self.image_scale_combo_box = QtGui.QComboBox(self.image_widget)
1593+ self.image_scale_combo_box.addItems(['', '', ''])
1594+ self.image_scale_combo_box.setObjectName('image_scale_combo_box')
1595+ self.image_scale_layout.addWidget(self.image_scale_combo_box)
1596+ self.image_fixed_widget = QtGui.QWidget(self.background_page)
1597+ self.image_fixed_widget.setObjectName('image_fixed_widget')
1598+ self.image_fixed_layout = QtGui.QHBoxLayout(self.image_fixed_widget)
1599+ self.image_fixed_layout.setMargin(0)
1600+ self.image_fixed_layout.setObjectName('image_fixed_layout')
1601+ self.image_width_label = QtGui.QLabel(self.image_fixed_widget)
1602+ self.image_width_label.setObjectName('image_width_label')
1603+ self.image_fixed_layout.addWidget(self.image_width_label)
1604+ self.image_width_spin_box = QtGui.QSpinBox(self.image_widget)
1605+ self.image_width_spin_box.setMaximum(9999)
1606+ self.image_width_spin_box.setValue(0)
1607+ self.image_width_spin_box.setObjectName('image_width_spin_box')
1608+ self.image_fixed_layout.addWidget(self.image_width_spin_box)
1609+ self.image_height_label = QtGui.QLabel(self.image_widget)
1610+ self.image_height_label.setObjectName('image_height_label')
1611+ self.image_fixed_layout.addWidget(self.image_height_label)
1612+ self.image_height_spin_box = QtGui.QSpinBox(self.image_widget)
1613+ self.image_height_spin_box.setMaximum(9999)
1614+ self.image_height_spin_box.setValue(0)
1615+ self.image_height_spin_box.setObjectName('image_height_spin_box')
1616+ self.image_fixed_layout.addWidget(self.image_height_spin_box)
1617+ self.image_scale_layout.addWidget(self.image_fixed_widget)
1618+ self.image_layout.addRow(self.image_scale_label, self.image_scale_layout)
1619+ self.image_layout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
1620+ self.image_align_label = QtGui.QLabel(self.image_widget)
1621+ self.image_align_label.setObjectName('image_align_label')
1622+ self.image_align_widget = QtGui.QWidget(self.image_widget)
1623+ self.image_align_widget.setObjectName('image_align_widget')
1624+ self.image_align_layout = QtGui.QHBoxLayout(self.image_align_widget)
1625+ self.image_align_layout.setMargin(0)
1626+ self.image_align_layout.setObjectName('image_align_layout')
1627+ self.image_valign_combo_box = QtGui.QComboBox(self.image_align_widget)
1628+ self.image_valign_combo_box.addItems(['', '', ''])
1629+ self.image_valign_combo_box.setObjectName('image_valign_combo_box')
1630+ self.image_halign_combo_box = QtGui.QComboBox(self.image_align_widget)
1631+ self.image_halign_combo_box.addItems(['', '', ''])
1632+ self.image_halign_combo_box.setObjectName('image_halign_combo_box')
1633+ self.image_align_layout.addWidget(self.image_valign_combo_box)
1634+ self.image_align_layout.addWidget(self.image_halign_combo_box)
1635+ self.image_layout.addRow(self.image_align_label, self.image_align_widget)
1636+ self.image_file_label = QtGui.QLabel(self.image_widget)
1637+ self.image_file_label.setObjectName('image_file_label')
1638 self.image_file_layout = QtGui.QHBoxLayout()
1639+ self.image_file_layout.setMargin(0)
1640 self.image_file_layout.setObjectName('image_file_layout')
1641 self.image_file_edit = QtGui.QLineEdit(self.image_widget)
1642 self.image_file_edit.setObjectName('image_file_edit')
1643@@ -131,16 +202,9 @@
1644 self.image_browse_button.setObjectName('image_browse_button')
1645 self.image_browse_button.setIcon(build_icon(':/general/general_open.png'))
1646 self.image_file_layout.addWidget(self.image_browse_button)
1647- self.image_layout.addRow(self.image_label, self.image_file_layout)
1648- self.image_layout.setItem(2, QtGui.QFormLayout.LabelRole, self.spacer)
1649- self.background_stack.addWidget(self.image_widget)
1650- self.transparent_widget = QtGui.QWidget(self.background_page)
1651- self.transparent_widget.setObjectName('TransparentWidget')
1652- self.transparent_layout = QtGui.QFormLayout(self.transparent_widget)
1653- self.transparent_layout.setMargin(0)
1654- self.transparent_layout.setObjectName('Transparent_layout')
1655- self.background_stack.addWidget(self.transparent_widget)
1656- self.background_layout.addLayout(self.background_stack)
1657+ self.image_layout.addRow(self.image_file_label, self.image_file_layout)
1658+ self.media_stack.addWidget(self.image_widget)
1659+ self.background_layout.addLayout(self.media_stack)
1660 theme_wizard.addPage(self.background_page)
1661 # Main Area Page
1662 self.main_area_page = QtGui.QWizardPage()
1663@@ -274,69 +338,164 @@
1664 self.area_position_page.setObjectName('area_position_page')
1665 self.area_position_layout = QtGui.QHBoxLayout(self.area_position_page)
1666 self.area_position_layout.setObjectName('area_position_layout')
1667+ # main
1668 self.main_position_group_box = QtGui.QGroupBox(self.area_position_page)
1669 self.main_position_group_box.setObjectName('main_position_group_box')
1670 self.main_position_layout = QtGui.QFormLayout(self.main_position_group_box)
1671 self.main_position_layout.setObjectName('main_position_layout')
1672- self.main_position_check_box = QtGui.QCheckBox(self.main_position_group_box)
1673- self.main_position_check_box.setObjectName('main_position_check_box')
1674- self.main_position_layout.addRow(self.main_position_check_box)
1675- self.main_x_label = QtGui.QLabel(self.main_position_group_box)
1676+ self.main_position_combo_box = QtGui.QComboBox(self.main_position_group_box)
1677+ self.main_position_combo_box.addItems(['', '', '', ''])
1678+ self.main_position_combo_box.setObjectName('main_position_combo_box')
1679+ self.main_position_layout.addRow(self.main_position_combo_box)
1680+ self.main_position_stack = QtGui.QStackedLayout()
1681+ self.main_position_stack.setObjectName('main_position_stack')
1682+ # main location
1683+ self.main_location_widget = QtGui.QWidget(self.main_position_group_box)
1684+ self.main_location_widget.setObjectName('main_location_widget')
1685+ self.main_location_layout = QtGui.QFormLayout(self.main_location_widget)
1686+ self.main_location_layout.setObjectName('main_location_layout')
1687+ self.main_x_label = QtGui.QLabel()
1688 self.main_x_label.setObjectName('main_x_label')
1689- self.main_x_spin_box = QtGui.QSpinBox(self.main_position_group_box)
1690+ self.main_x_spin_box = QtGui.QSpinBox(self.main_location_widget)
1691 self.main_x_spin_box.setMaximum(9999)
1692 self.main_x_spin_box.setObjectName('main_x_spin_box')
1693- self.main_position_layout.addRow(self.main_x_label, self.main_x_spin_box)
1694- self.main_y_label = QtGui.QLabel(self.main_position_group_box)
1695+ self.main_location_layout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
1696+ self.main_location_layout.addRow(self.main_x_label, self.main_x_spin_box)
1697+ self.main_y_label = QtGui.QLabel(self.main_location_widget)
1698 self.main_y_label.setObjectName('main_y_label')
1699- self.main_y_spin_box = QtGui.QSpinBox(self.main_position_group_box)
1700+ self.main_y_spin_box = QtGui.QSpinBox(self.main_location_widget)
1701 self.main_y_spin_box.setMaximum(9999)
1702 self.main_y_spin_box.setObjectName('main_y_spin_box')
1703- self.main_position_layout.addRow(self.main_y_label, self.main_y_spin_box)
1704- self.main_width_label = QtGui.QLabel(self.main_position_group_box)
1705+ self.main_location_layout.addRow(self.main_y_label, self.main_y_spin_box)
1706+ self.main_width_label = QtGui.QLabel(self.main_location_widget)
1707 self.main_width_label.setObjectName('main_width_label')
1708- self.main_width_spin_box = QtGui.QSpinBox(self.main_position_group_box)
1709+ self.main_width_spin_box = QtGui.QSpinBox(self.main_location_widget)
1710 self.main_width_spin_box.setMaximum(9999)
1711 self.main_width_spin_box.setObjectName('main_width_spin_box')
1712- self.main_position_layout.addRow(self.main_width_label, self.main_width_spin_box)
1713- self.main_height_label = QtGui.QLabel(self.main_position_group_box)
1714+ self.main_location_layout.addRow(self.main_width_label, self.main_width_spin_box)
1715+ self.main_height_label = QtGui.QLabel(self.main_location_widget)
1716 self.main_height_label.setObjectName('main_height_label')
1717- self.main_height_spin_box = QtGui.QSpinBox(self.main_position_group_box)
1718+ self.main_height_spin_box = QtGui.QSpinBox(self.main_location_widget)
1719 self.main_height_spin_box.setMaximum(9999)
1720 self.main_height_spin_box.setObjectName('main_height_spin_box')
1721- self.main_position_layout.addRow(self.main_height_label, self.main_height_spin_box)
1722+ self.main_location_layout.addRow(self.main_height_label, self.main_height_spin_box)
1723+ # main margin
1724+ self.main_margin_widget = QtGui.QWidget(self.main_position_group_box)
1725+ self.main_margin_widget.setObjectName('main_margin_widget')
1726+ self.main_margin_layout = QtGui.QFormLayout(self.main_margin_widget)
1727+ self.main_margin_layout.setObjectName('main_margin_layout')
1728+ self.main_left_label = QtGui.QLabel()
1729+ self.main_left_label.setObjectName('main_left_label')
1730+ self.main_left_spin_box = QtGui.QSpinBox(self.main_margin_widget)
1731+ self.main_left_spin_box.setMaximum(9999)
1732+ self.main_left_spin_box.setObjectName('main_left_spin_box')
1733+ self.main_margin_layout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
1734+ self.main_margin_layout.addRow(self.main_left_label, self.main_left_spin_box)
1735+ self.main_right_label = QtGui.QLabel(self.main_margin_widget)
1736+ self.main_right_label.setObjectName('main_right_label')
1737+ self.main_right_spin_box = QtGui.QSpinBox(self.main_margin_widget)
1738+ self.main_right_spin_box.setMaximum(9999)
1739+ self.main_right_spin_box.setObjectName('main_right_spin_box')
1740+ self.main_margin_layout.addRow(self.main_right_label, self.main_right_spin_box)
1741+ self.main_top_label = QtGui.QLabel(self.main_margin_widget)
1742+ self.main_top_label.setObjectName('main_top_label')
1743+ self.main_top_spin_box = QtGui.QSpinBox(self.main_margin_widget)
1744+ self.main_top_spin_box.setMaximum(9999)
1745+ self.main_top_spin_box.setObjectName('main_top_spin_box')
1746+ self.main_margin_layout.addRow(self.main_top_label, self.main_top_spin_box)
1747+ self.main_bottom_label = QtGui.QLabel(self.main_margin_widget)
1748+ self.main_bottom_label.setObjectName('main_bottom_label')
1749+ self.main_bottom_spin_box = QtGui.QSpinBox(self.main_margin_widget)
1750+ self.main_bottom_spin_box.setMaximum(9999)
1751+ self.main_bottom_spin_box.setObjectName('main_bottom_spin_box')
1752+ self.main_margin_layout.addRow(self.main_bottom_label, self.main_bottom_spin_box)
1753+ self.main_position_stack.addWidget(self.main_location_widget)
1754+ self.main_position_stack.addWidget(self.main_margin_widget)
1755+ self.main_position_layout.addRow(self.main_position_stack)
1756 self.area_position_layout.addWidget(self.main_position_group_box)
1757+ # footer
1758 self.footer_position_group_box = QtGui.QGroupBox(self.area_position_page)
1759 self.footer_position_group_box.setObjectName('footer_position_group_box')
1760 self.footer_position_layout = QtGui.QFormLayout(self.footer_position_group_box)
1761+ self.footer_position_layout.setVerticalSpacing(0)
1762+ self.footer_position_layout.setContentsMargins(0,4,0,0)
1763 self.footer_position_layout.setObjectName('footer_position_layout')
1764- self.footer_position_check_box = QtGui.QCheckBox(self.footer_position_group_box)
1765- self.footer_position_check_box.setObjectName('footer_position_check_box')
1766- self.footer_position_layout.addRow(self.footer_position_check_box)
1767- self.footer_x_label = QtGui.QLabel(self.footer_position_group_box)
1768+ self.footer_position_combo_box = QtGui.QComboBox(self.footer_position_group_box)
1769+ self.footer_position_combo_box.addItems(['', '', '', ''])
1770+ self.footer_position_combo_box.setObjectName('footer_position_combo_box')
1771+ self.footer_position_layout.addRow(self.footer_position_combo_box)
1772+ self.footer_position_stack = QtGui.QStackedLayout()
1773+ self.footer_position_stack.setObjectName('footer_position_stack')
1774+ # footer location
1775+ self.footer_location_widget = QtGui.QWidget(self.footer_position_group_box)
1776+ self.footer_location_widget.setObjectName('footer_location_widget')
1777+ self.footer_location_layout = QtGui.QFormLayout(self.footer_location_widget)
1778+ self.footer_location_layout.setVerticalSpacing(4)
1779+ self.footer_location_layout.setContentsMargins(4,8,0,4)
1780+ self.footer_location_layout.setObjectName('footer_location_layout')
1781+ self.footer_x_label = QtGui.QLabel(self.footer_location_widget)
1782 self.footer_x_label.setObjectName('footer_x_label')
1783- self.footer_x_spin_box = QtGui.QSpinBox(self.footer_position_group_box)
1784+ self.footer_x_spin_box = QtGui.QSpinBox(self.footer_location_widget)
1785 self.footer_x_spin_box.setMaximum(9999)
1786 self.footer_x_spin_box.setObjectName('footer_x_spin_box')
1787- self.footer_position_layout.addRow(self.footer_x_label, self.footer_x_spin_box)
1788- self.footer_y_label = QtGui.QLabel(self.footer_position_group_box)
1789+ self.footer_location_layout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
1790+ self.footer_location_layout.addRow(self.footer_x_label, self.footer_x_spin_box)
1791+ self.footer_y_label = QtGui.QLabel(self.footer_location_widget)
1792 self.footer_y_label.setObjectName('footer_y_label')
1793- self.footer_y_spin_box = QtGui.QSpinBox(self.footer_position_group_box)
1794+ self.footer_y_spin_box = QtGui.QSpinBox(self.footer_location_widget)
1795 self.footer_y_spin_box.setMaximum(9999)
1796 self.footer_y_spin_box.setObjectName('footer_y_spin_box')
1797- self.footer_position_layout.addRow(self.footer_y_label, self.footer_y_spin_box)
1798- self.footer_width_label = QtGui.QLabel(self.footer_position_group_box)
1799+ self.footer_location_layout.addRow(self.footer_y_label, self.footer_y_spin_box)
1800+ self.footer_width_label = QtGui.QLabel(self.footer_location_widget)
1801 self.footer_width_label.setObjectName('footer_width_label')
1802- self.footer_width_spin_box = QtGui.QSpinBox(self.footer_position_group_box)
1803+ self.footer_width_spin_box = QtGui.QSpinBox(self.footer_location_widget)
1804 self.footer_width_spin_box.setMaximum(9999)
1805 self.footer_width_spin_box.setObjectName('footer_width_spin_box')
1806- self.footer_position_layout.addRow(self.footer_width_label, self.footer_width_spin_box)
1807- self.footer_height_label = QtGui.QLabel(self.footer_position_group_box)
1808+ self.footer_location_layout.addRow(self.footer_width_label, self.footer_width_spin_box)
1809+ self.footer_position_stack.addWidget(self.footer_location_widget)
1810+ # footer margin
1811+ self.footer_margin_widget = QtGui.QWidget(self.footer_position_group_box)
1812+ self.footer_margin_widget.setObjectName('footer_margin_widget')
1813+ self.footer_margin_layout = QtGui.QFormLayout(self.footer_margin_widget)
1814+ self.footer_margin_layout.setVerticalSpacing(4)
1815+ self.footer_margin_layout.setContentsMargins(4,8,0,4)
1816+ self.footer_margin_layout.setObjectName('footer_margin_layout')
1817+ self.footer_left_label = QtGui.QLabel(self.footer_margin_widget)
1818+ self.footer_left_label.setObjectName('footer_left_label')
1819+ self.footer_left_spin_box = QtGui.QSpinBox(self.footer_margin_widget)
1820+ self.footer_left_spin_box.setMaximum(9999)
1821+ self.footer_left_spin_box.setObjectName('footer_left_spin_box')
1822+ self.footer_margin_layout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
1823+ self.footer_margin_layout.addRow(self.footer_left_label, self.footer_left_spin_box)
1824+ self.footer_right_label = QtGui.QLabel(self.footer_margin_widget)
1825+ self.footer_right_label.setObjectName('footer_right_label')
1826+ self.footer_right_spin_box = QtGui.QSpinBox(self.footer_margin_widget)
1827+ self.footer_right_spin_box.setMaximum(9999)
1828+ self.footer_right_spin_box.setObjectName('footer_right_spin_box')
1829+ self.footer_margin_layout.addRow(self.footer_right_label, self.footer_right_spin_box)
1830+ self.footer_bottom_label = QtGui.QLabel(self.footer_margin_widget)
1831+ self.footer_bottom_label.setObjectName('footer_bottom_label')
1832+ self.footer_bottom_spin_box = QtGui.QSpinBox(self.footer_margin_widget)
1833+ self.footer_bottom_spin_box.setMaximum(9999)
1834+ self.footer_bottom_spin_box.setObjectName('footer_bottom_spin_box')
1835+ self.footer_margin_layout.addRow(self.footer_bottom_label, self.footer_bottom_spin_box)
1836+ self.footer_position_stack.addWidget(self.footer_margin_widget)
1837+ self.footer_position_layout.addRow(self.footer_position_stack)
1838+ # footer height
1839+ self.footer_height_widget = QtGui.QWidget(self.footer_position_group_box)
1840+ self.footer_height_widget.setObjectName('footer_height_widget')
1841+ self.footer_height_layout = QtGui.QFormLayout(self.footer_height_widget)
1842+ self.footer_height_layout.setVerticalSpacing(0)
1843+ self.footer_height_layout.setContentsMargins(0,0,0,0)
1844+ self.footer_height_layout.setObjectName('footer_height_layout')
1845+ self.footer_height_label = QtGui.QLabel(self.footer_height_widget)
1846 self.footer_height_label.setObjectName('footer_height_label')
1847- self.footer_height_spin_box = QtGui.QSpinBox(self.footer_position_group_box)
1848+ self.footer_height_spin_box = QtGui.QSpinBox(self.footer_height_widget)
1849 self.footer_height_spin_box.setMaximum(9999)
1850 self.footer_height_spin_box.setObjectName('footer_height_spin_box')
1851- self.footer_position_layout.addRow(self.footer_height_label, self.footer_height_spin_box)
1852+ self.footer_height_layout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
1853+ self.footer_height_layout.addRow(self.footer_height_label, self.footer_height_spin_box)
1854+ self.footer_position_layout.addWidget(self.footer_height_widget)
1855 self.area_position_layout.addWidget(self.footer_position_group_box)
1856 theme_wizard.addPage(self.area_position_page)
1857 # Preview Page
1858@@ -368,8 +527,10 @@
1859 self.preview_layout.addWidget(self.preview_area)
1860 theme_wizard.addPage(self.preview_page)
1861 self.retranslateUi(theme_wizard)
1862- QtCore.QObject.connect(self.background_combo_box, QtCore.SIGNAL('currentIndexChanged(int)'),
1863- self.background_stack, QtCore.SLOT('setCurrentIndex(int)'))
1864+ QtCore.QObject.connect(self.color_type_combo_box, QtCore.SIGNAL('currentIndexChanged(int)'),
1865+ self.color_stack, QtCore.SLOT('setCurrentIndex(int)'))
1866+ QtCore.QObject.connect(self.media_type_combo_box, QtCore.SIGNAL('currentIndexChanged(int)'),
1867+ self.media_stack, QtCore.SLOT('setCurrentIndex(int)'))
1868 QtCore.QObject.connect(self.outline_check_box, QtCore.SIGNAL('toggled(bool)'), self.outline_color_button,
1869 QtCore.SLOT('setEnabled(bool)'))
1870 QtCore.QObject.connect(self.outline_check_box, QtCore.SIGNAL('toggled(bool)'), self.outline_size_spin_box,
1871@@ -378,23 +539,6 @@
1872 QtCore.SLOT('setEnabled(bool)'))
1873 QtCore.QObject.connect(self.shadow_check_box, QtCore.SIGNAL('toggled(bool)'), self.shadow_size_spin_box,
1874 QtCore.SLOT('setEnabled(bool)'))
1875- QtCore.QObject.connect(self.main_position_check_box, QtCore.SIGNAL('toggled(bool)'), self.main_x_spin_box,
1876- QtCore.SLOT('setDisabled(bool)'))
1877- QtCore.QObject.connect(self.main_position_check_box, QtCore.SIGNAL('toggled(bool)'), self.main_y_spin_box,
1878- QtCore.SLOT('setDisabled(bool)'))
1879- QtCore.QObject.connect(self.main_position_check_box, QtCore.SIGNAL('toggled(bool)'), self.main_width_spin_box,
1880- QtCore.SLOT('setDisabled(bool)'))
1881- QtCore.QObject.connect(self.main_position_check_box, QtCore.SIGNAL('toggled(bool)'), self.main_height_spin_box,
1882- QtCore.SLOT('setDisabled(bool)'))
1883- QtCore.QObject.connect(self.footer_position_check_box, QtCore.SIGNAL('toggled(bool)'), self.footer_x_spin_box,
1884- QtCore.SLOT('setDisabled(bool)'))
1885- QtCore.QObject.connect(self.footer_position_check_box, QtCore.SIGNAL('toggled(bool)'), self.footer_y_spin_box,
1886- QtCore.SLOT('setDisabled(bool)'))
1887- QtCore.QObject.connect(self.footer_position_check_box, QtCore.SIGNAL('toggled(bool)'),
1888- self.footer_width_spin_box, QtCore.SLOT('setDisabled(bool)'))
1889- QtCore.QObject.connect(self.footer_position_check_box, QtCore.SIGNAL('toggled(bool)'),
1890- self.footer_height_spin_box, QtCore.SLOT('setDisabled(bool)'))
1891-
1892 def retranslateUi(self, theme_wizard):
1893 """
1894 Translate the UI on the fly
1895@@ -408,13 +552,12 @@
1896 self.background_page.setTitle(translate('OpenLP.ThemeWizard', 'Set Up Background'))
1897 self.background_page.setSubTitle(translate('OpenLP.ThemeWizard', 'Set up your theme\'s background '
1898 'according to the parameters below.'))
1899- self.background_label.setText(translate('OpenLP.ThemeWizard', 'Background type:'))
1900- self.background_combo_box.setItemText(BackgroundType.Solid,
1901+ self.color_type_label.setText(translate('OpenLP.ThemeWizard', 'Color type:'))
1902+ self.color_type_combo_box.setItemText(BackgroundColorType.Solid,
1903 translate('OpenLP.ThemeWizard', 'Solid color'))
1904- self.background_combo_box.setItemText(BackgroundType.Gradient,
1905+ self.color_type_combo_box.setItemText(BackgroundColorType.Gradient,
1906 translate('OpenLP.ThemeWizard', 'Gradient'))
1907- self.background_combo_box.setItemText(BackgroundType.Image, UiStrings().Image)
1908- self.background_combo_box.setItemText(BackgroundType.Transparent,
1909+ self.color_type_combo_box.setItemText(BackgroundColorType.Transparent,
1910 translate('OpenLP.ThemeWizard', 'Transparent'))
1911 self.color_label.setText(translate('OpenLP.ThemeWizard', 'color:'))
1912 self.gradient_start_label.setText(translate('OpenLP.ThemeWizard', 'Starting color:'))
1913@@ -430,8 +573,28 @@
1914 translate('OpenLP.ThemeWizard', 'Top Left - Bottom Right'))
1915 self.gradient_combo_box.setItemText(BackgroundGradientType.LeftBottom,
1916 translate('OpenLP.ThemeWizard', 'Bottom Left - Top Right'))
1917- self.image_color_label.setText(translate('OpenLP.ThemeWizard', 'Background color:'))
1918- self.image_label.setText('%s:' % UiStrings().Image)
1919+ self.media_type_label.setText(translate('OpenLP.ThemeWizard', 'Media type:'))
1920+ self.media_type_combo_box.setItemText(BackgroundMediaType.Nothing,
1921+ translate('OpenLP.ThemeWizard', 'None'))
1922+ self.media_type_combo_box.setItemText(BackgroundMediaType.Image,
1923+ UiStrings().Image)
1924+ self.image_align_label.setText(translate('OpenLP.ThemeWizard', 'Alignment:'))
1925+ self.image_valign_combo_box.setItemText(0, translate('OpenLP.ThemeWizard', 'Top'))
1926+ self.image_valign_combo_box.setItemText(1, translate('OpenLP.ThemeWizard', 'Middle'))
1927+ self.image_valign_combo_box.setItemText(2, translate('OpenLP.ThemeWizard', 'Bottom'))
1928+ self.image_halign_combo_box.setItemText(0, translate('OpenLP.ThemeWizard', 'Left'))
1929+ self.image_halign_combo_box.setItemText(1, translate('OpenLP.ThemeWizard', 'Center'))
1930+ self.image_halign_combo_box.setItemText(2, translate('OpenLP.ThemeWizard', 'Right'))
1931+ self.image_scale_label.setText(translate('OpenLP.ThemeWizard', 'Size:'))
1932+ self.image_scale_combo_box.setItemText(MediaScaleType.Auto,
1933+ translate('OpenLP.ThemeWizard', 'Auto'))
1934+ self.image_scale_combo_box.setItemText(MediaScaleType.Fullscreen,
1935+ translate('OpenLP.ThemeWizard', 'Fullscreen'))
1936+ self.image_scale_combo_box.setItemText(MediaScaleType.Fixed,
1937+ translate('OpenLP.ThemeWizard', 'Fixed'))
1938+ self.image_width_label.setText(translate('OpenLP.ThemeWizard', 'width:'))
1939+ self.image_height_label.setText(translate('OpenLP.ThemeWizard', 'height:'))
1940+ self.image_file_label.setText(translate('OpenLP.ThemeWizard', 'Filename:'))
1941 self.main_area_page.setTitle(translate('OpenLP.ThemeWizard', 'Main Area Font Details'))
1942 self.main_area_page.setSubTitle(translate('OpenLP.ThemeWizard', 'Define the font and display '
1943 'characteristics for the Display text'))
1944@@ -469,7 +632,14 @@
1945 self.area_position_page.setSubTitle(translate('OpenLP.ThemeWizard', 'Allows you to change and move the'
1946 ' Main and Footer areas.'))
1947 self.main_position_group_box.setTitle(translate('OpenLP.ThemeWizard', '&Main Area'))
1948- self.main_position_check_box.setText(translate('OpenLP.ThemeWizard', '&Use default location'))
1949+ self.main_position_combo_box.setItemText(0,
1950+ translate('OpenLP.ThemeWizard', 'Use default location'))
1951+ self.main_position_combo_box.setItemText(1,
1952+ translate('OpenLP.ThemeWizard', 'Specify custom location'))
1953+ self.main_position_combo_box.setItemText(2,
1954+ translate('OpenLP.ThemeWizard', 'Use default margins'))
1955+ self.main_position_combo_box.setItemText(3,
1956+ translate('OpenLP.ThemeWizard', 'Specify custom margins'))
1957 self.main_x_label.setText(translate('OpenLP.ThemeWizard', 'X position:'))
1958 self.main_x_spin_box.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
1959 self.main_y_spin_box.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
1960@@ -478,7 +648,23 @@
1961 self.main_width_label.setText(translate('OpenLP.ThemeWizard', 'Width:'))
1962 self.main_height_spin_box.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
1963 self.main_height_label.setText(translate('OpenLP.ThemeWizard', 'Height:'))
1964+ self.main_left_label.setText(translate('OpenLP.ThemeWizard', 'Left:'))
1965+ self.main_left_spin_box.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
1966+ self.main_right_label.setText(translate('OpenLP.ThemeWizard', 'Right:'))
1967+ self.main_right_spin_box.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
1968+ self.main_top_label.setText(translate('OpenLP.ThemeWizard', 'Top:'))
1969+ self.main_top_spin_box.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
1970+ self.main_bottom_label.setText(translate('OpenLP.ThemeWizard', 'Bottom:'))
1971+ self.main_bottom_spin_box.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
1972 self.footer_position_group_box.setTitle(translate('OpenLP.ThemeWizard', '&Footer Area'))
1973+ self.footer_position_combo_box.setItemText(0,
1974+ translate('OpenLP.ThemeWizard', 'Use default location'))
1975+ self.footer_position_combo_box.setItemText(1,
1976+ translate('OpenLP.ThemeWizard', 'Specify custom location'))
1977+ self.footer_position_combo_box.setItemText(2,
1978+ translate('OpenLP.ThemeWizard', 'Use default margins'))
1979+ self.footer_position_combo_box.setItemText(3,
1980+ translate('OpenLP.ThemeWizard', 'Specify custom margins'))
1981 self.footer_x_label.setText(translate('OpenLP.ThemeWizard', 'X position:'))
1982 self.footer_x_spin_box.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
1983 self.footer_y_label.setText(translate('OpenLP.ThemeWizard', 'Y position:'))
1984@@ -487,13 +673,21 @@
1985 self.footer_width_spin_box.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
1986 self.footer_height_label.setText(translate('OpenLP.ThemeWizard', 'Height:'))
1987 self.footer_height_spin_box.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
1988- self.footer_position_check_box.setText(translate('OpenLP.ThemeWizard', 'Use default location'))
1989- theme_wizard.setOption(QtGui.QWizard.HaveCustomButton1, False)
1990- theme_wizard.setButtonText(QtGui.QWizard.CustomButton1, translate('OpenLP.ThemeWizard', 'Layout Preview'))
1991+ self.footer_left_label.setText(translate('OpenLP.ThemeWizard', 'Left:'))
1992+ self.footer_left_spin_box.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
1993+ self.footer_right_label.setText(translate('OpenLP.ThemeWizard', 'Right:'))
1994+ self.footer_right_spin_box.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
1995+ self.footer_bottom_label.setText(translate('OpenLP.ThemeWizard', 'Bottom:'))
1996+ self.footer_bottom_spin_box.setSuffix(translate('OpenLP.ThemeWizard', 'px'))
1997+ theme_wizard.setButtonText(QtGui.QWizard.CustomButton1, translate('OpenLP.ThemeWizard', 'Save'))
1998+ theme_wizard.setButtonText(QtGui.QWizard.CustomButton2, translate('OpenLP.ThemeWizard', 'Layout Preview'))
1999+ button_layout = [QtGui.QWizard.CustomButton1, QtGui.QWizard.Stretch, \
2000+ QtGui.QWizard.BackButton, QtGui.QWizard.NextButton, QtGui.QWizard.CancelButton]
2001+ theme_wizard.setButtonLayout(button_layout)
2002 self.preview_page.setTitle(translate('OpenLP.ThemeWizard', 'Preview and Save'))
2003 self.preview_page.setSubTitle(translate('OpenLP.ThemeWizard', 'Preview the theme and save it.'))
2004 self.theme_name_label.setText(translate('OpenLP.ThemeWizard', 'Theme name:'))
2005 # Align all QFormLayouts towards each other.
2006- label_width = max(self.background_label.minimumSizeHint().width(),
2007+ label_width = max(self.color_type_label.minimumSizeHint().width(),
2008 self.horizontal_label.minimumSizeHint().width())
2009 self.spacer.changeSize(label_width, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
2010
2011=== modified file 'openlp/core/utils/__init__.py'
2012--- openlp/core/utils/__init__.py 2014-10-22 20:47:47 +0000
2013+++ openlp/core/utils/__init__.py 2014-10-24 20:09:17 +0000
2014@@ -304,6 +304,7 @@
2015
2016 :param file_name: File name to be checked.
2017 """
2018+ #QtGui.QMessageBox.warning(None,"Image File", "filename: %s | e: %d" % (file_name, os.path.exists(file_name)) )
2019 if not file_name:
2020 return True
2021 else:
2022
2023=== modified file 'tests/functional/openlp_core_lib/test_htmlbuilder.py'
2024--- tests/functional/openlp_core_lib/test_htmlbuilder.py 2014-07-24 21:57:16 +0000
2025+++ tests/functional/openlp_core_lib/test_htmlbuilder.py 2014-10-24 20:09:17 +0000
2026@@ -251,8 +251,8 @@
2027 """
2028 # GIVEN: Mocked arguments.
2029 item = MagicMock()
2030- item.theme_data.background_start_color = '#000000'
2031- item.theme_data.background_end_color = '#FFFFFF'
2032+ item.theme_data.background_color_start = '#000000'
2033+ item.theme_data.background_color_end = '#FFFFFF'
2034 width = 10
2035
2036 # WHEN: Create the css.
2037
2038=== modified file 'tests/functional/openlp_core_lib/test_theme.py'
2039--- tests/functional/openlp_core_lib/test_theme.py 2014-09-07 22:17:20 +0000
2040+++ tests/functional/openlp_core_lib/test_theme.py 2014-10-24 20:09:17 +0000
2041@@ -61,8 +61,8 @@
2042 default_theme = ThemeXML()
2043
2044 # THEN: We should get some default behaviours
2045- self.assertTrue(default_theme.background_border_color == '#000000', 'The theme should have a black border')
2046- self.assertTrue(default_theme.background_type == 'solid', 'The theme should have a solid backgrounds')
2047+ self.assertTrue(default_theme.background_color == '#000000', 'The theme should have a black border')
2048+ self.assertTrue(default_theme.background_color_type == 'solid', 'The theme should have a solid backgrounds')
2049 self.assertTrue(default_theme.display_vertical_align == 0,
2050 'The theme should have a display_vertical_align of 0')
2051 self.assertTrue(default_theme.font_footer_name == "Arial",