Merge lp:~knightrider0xd/openlp/non-text-item-height-default into lp:openlp

Proposed by Ian Knight
Status: Merged
Approved by: Tim Bentley
Approved revision: 2674
Merged at revision: 2674
Proposed branch: lp:~knightrider0xd/openlp/non-text-item-height-default
Merge into: lp:openlp
Diff against target: 252 lines (+111/-19)
7 files modified
openlp/core/common/settings.py (+1/-1)
openlp/core/ui/advancedtab.py (+18/-9)
openlp/core/ui/lib/listpreviewwidget.py (+18/-7)
tests/functional/openlp_core_common/test_registryproperties.py (+0/-1)
tests/functional/openlp_core_ui_lib/test_listpreviewwidget.py (+73/-0)
tests/functional/openlp_plugins/bibles/test_lib.py (+1/-0)
tests/functional/openlp_plugins/songs/test_opsproimport.py (+0/-1)
To merge this branch: bzr merge lp:~knightrider0xd/openlp/non-text-item-height-default
Reviewer Review Type Date Requested Status
Raoul Snyman Approve
Review via email: mp+296308@code.launchpad.net

This proposal supersedes a proposal from 2016-06-02.

Description of the change

Adds automatic functionality to the max-height for non-text items feature, and sets this as the default value.
Advanced tab spin box replaced with combo box.

Test coverage expanded on other functions in listpreviewwidget and pep8 errors fixed.
Fixed test naming.
Merged with trunk as of 2016-06-02_10:30.

lp:~knightrider0xd/openlp/non-text-item-height-default (revision 2674)
[SUCCESS] https://ci.openlp.io/job/Branch-01-Pull/1584/
[SUCCESS] https://ci.openlp.io/job/Branch-02-Functional-Tests/1495/
[SUCCESS] https://ci.openlp.io/job/Branch-03-Interface-Tests/1433/
[SUCCESS] https://ci.openlp.io/job/Branch-04a-Windows_Functional_Tests/1212/
[SUCCESS] https://ci.openlp.io/job/Branch-04b-Windows_Interface_Tests/802/
[SUCCESS] https://ci.openlp.io/job/Branch-05a-Code_Analysis/870/
[SUCCESS] https://ci.openlp.io/job/Branch-05b-Test_Coverage/738/

To post a comment you must log in.
Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal

Got this when I started OpenLP.

Traceback (most recent call last):
  File "./openlp.py", line 44, in <module>
    main()
  File "/home/raoul/Projects/OpenLP/OpenLP/non-text-item-height-default/openlp/core/__init__.py", line 392, in main
    sys.exit(application.run(qt_args))
  File "/home/raoul/Projects/OpenLP/OpenLP/non-text-item-height-default/openlp/core/__init__.py", line 142, in run
    Registry().execute('bootstrap_initialise')
  File "/home/raoul/Projects/OpenLP/OpenLP/non-text-item-height-default/openlp/core/common/registry.py", line 137, in execute
    result = function(*args, **kwargs)
  File "/home/raoul/Projects/OpenLP/OpenLP/non-text-item-height-default/openlp/core/lib/pluginmanager.py", line 68, in bootstrap_initialise
    self.initialise_plugins()
  File "/home/raoul/Projects/OpenLP/OpenLP/non-text-item-height-default/openlp/core/lib/pluginmanager.py", line 183, in initialise_plugins
    plugin.initialise()
  File "/home/raoul/Projects/OpenLP/OpenLP/non-text-item-height-default/openlp/plugins/media/mediaplugin.py", line 66, in initialise
    super().initialise()
  File "/home/raoul/Projects/OpenLP/OpenLP/non-text-item-height-default/openlp/core/lib/plugin.py", line 277, in initialise
    self.media_item.initialise()
  File "/home/raoul/Projects/OpenLP/OpenLP/non-text-item-height-default/openlp/plugins/media/lib/mediaitem.py", line 303, in initialise
    self.load_list(Settings().value(self.settings_section + '/media files'))
  File "/home/raoul/Projects/OpenLP/OpenLP/non-text-item-height-default/openlp/plugins/media/lib/mediaitem.py", line 368, in load_list
    item_name.setToolTip('%s@%s-%s' % (file_name, format_milliseconds(start), format_milliseconds(end)))
  File "/home/raoul/Projects/OpenLP/OpenLP/non-text-item-height-default/openlp/core/ui/media/__init__.py", line 143, in format_milliseconds
    millis=millis)
ValueError: Unknown format code 'd' for object of type 'float'

review: Needs Fixing
Revision history for this message
Ian Knight (knightrider0xd) wrote : Posted in a previous version of this proposal

Hey superfly.
I can't replicate this bug, and looking at that trace, it appears to be related to something in media, not my changes.

Revision history for this message
Tim Bentley (trb143) wrote : Posted in a previous version of this proposal

This code is existing and connected to CD /dvd items in media.
Did you have some media items created and then take to cd / dvd out of the machine?

Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal

I figured this out, it's a bug in Ken's new formatting code. I've fixed it.

Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal

Please just merge trunk into your branch and resubmit? Thanks.

Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal

Sorry, just spotted this. Your tests are incorrectly named, and won't be picked up by the test runner (especially when we move to nose2).

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/core/common/settings.py'
2--- openlp/core/common/settings.py 2016-05-15 17:32:04 +0000
3+++ openlp/core/common/settings.py 2016-06-02 10:36:58 +0000
4@@ -129,7 +129,7 @@
5 'advanced/recent file count': 4,
6 'advanced/save current plugin': False,
7 'advanced/slide limits': SlideLimits.End,
8- 'advanced/slide max height': 0,
9+ 'advanced/slide max height': -4,
10 'advanced/single click preview': False,
11 'advanced/single click service preview': False,
12 'advanced/x11 bypass wm': X11_BYPASS_DEFAULT,
13
14=== modified file 'openlp/core/ui/advancedtab.py'
15--- openlp/core/ui/advancedtab.py 2016-05-20 16:22:06 +0000
16+++ openlp/core/ui/advancedtab.py 2016-06-02 10:36:58 +0000
17@@ -87,11 +87,14 @@
18 self.ui_layout.addRow(self.expand_service_item_check_box)
19 self.slide_max_height_label = QtWidgets.QLabel(self.ui_group_box)
20 self.slide_max_height_label.setObjectName('slide_max_height_label')
21- self.slide_max_height_spin_box = QtWidgets.QSpinBox(self.ui_group_box)
22- self.slide_max_height_spin_box.setObjectName('slide_max_height_spin_box')
23- self.slide_max_height_spin_box.setRange(0, 1000)
24- self.slide_max_height_spin_box.setSingleStep(20)
25- self.ui_layout.addRow(self.slide_max_height_label, self.slide_max_height_spin_box)
26+ self.slide_max_height_combo_box = QtWidgets.QComboBox(self.ui_group_box)
27+ self.slide_max_height_combo_box.addItem('', userData=0)
28+ self.slide_max_height_combo_box.addItem('', userData=-4)
29+ # Generate numeric values for combo box dynamically
30+ for px in range(60, 801, 5):
31+ self.slide_max_height_combo_box.addItem(str(px) + 'px', userData=px)
32+ self.slide_max_height_combo_box.setObjectName('slide_max_height_combo_box')
33+ self.ui_layout.addRow(self.slide_max_height_label, self.slide_max_height_combo_box)
34 self.autoscroll_label = QtWidgets.QLabel(self.ui_group_box)
35 self.autoscroll_label.setObjectName('autoscroll_label')
36 self.autoscroll_combo_box = QtWidgets.QComboBox(self.ui_group_box)
37@@ -265,7 +268,8 @@
38 'Expand new service items on creation'))
39 self.slide_max_height_label.setText(translate('OpenLP.AdvancedTab',
40 'Max height for non-text slides\nin slide controller:'))
41- self.slide_max_height_spin_box.setSpecialValueText(translate('OpenLP.AdvancedTab', 'Disabled'))
42+ self.slide_max_height_combo_box.setItemText(0, translate('OpenLP.AdvancedTab', 'Disabled'))
43+ self.slide_max_height_combo_box.setItemText(1, translate('OpenLP.AdvancedTab', 'Automatic'))
44 self.autoscroll_label.setText(translate('OpenLP.AdvancedTab',
45 'When changing slides:'))
46 self.autoscroll_combo_box.setItemText(0, translate('OpenLP.AdvancedTab', 'Do not auto-scroll'))
47@@ -355,10 +359,13 @@
48 self.single_click_preview_check_box.setChecked(settings.value('single click preview'))
49 self.single_click_service_preview_check_box.setChecked(settings.value('single click service preview'))
50 self.expand_service_item_check_box.setChecked(settings.value('expand service item'))
51- self.slide_max_height_spin_box.setValue(settings.value('slide max height'))
52+ slide_max_height_value = settings.value('slide max height')
53+ for i in range(0, self.slide_max_height_combo_box.count()):
54+ if self.slide_max_height_combo_box.itemData(i) == slide_max_height_value:
55+ self.slide_max_height_combo_box.setCurrentIndex(i)
56 autoscroll_value = settings.value('autoscrolling')
57 for i in range(0, len(self.autoscroll_map)):
58- if self.autoscroll_map[i] == autoscroll_value:
59+ if self.autoscroll_map[i] == autoscroll_value and i < self.autoscroll_combo_box.count():
60 self.autoscroll_combo_box.setCurrentIndex(i)
61 self.enable_auto_close_check_box.setChecked(settings.value('enable exit confirmation'))
62 self.hide_mouse_check_box.setChecked(settings.value('hide mouse'))
63@@ -439,7 +446,9 @@
64 settings.setValue('single click preview', self.single_click_preview_check_box.isChecked())
65 settings.setValue('single click service preview', self.single_click_service_preview_check_box.isChecked())
66 settings.setValue('expand service item', self.expand_service_item_check_box.isChecked())
67- settings.setValue('slide max height', self.slide_max_height_spin_box.value())
68+ slide_max_height_index = self.slide_max_height_combo_box.currentIndex()
69+ slide_max_height_value = self.slide_max_height_combo_box.itemData(slide_max_height_index)
70+ settings.setValue('slide max height', slide_max_height_value)
71 settings.setValue('autoscrolling', self.autoscroll_map[self.autoscroll_combo_box.currentIndex()])
72 settings.setValue('enable exit confirmation', self.enable_auto_close_check_box.isChecked())
73 settings.setValue('hide mouse', self.hide_mouse_check_box.isChecked())
74
75=== modified file 'openlp/core/ui/lib/listpreviewwidget.py'
76--- openlp/core/ui/lib/listpreviewwidget.py 2016-05-05 03:57:04 +0000
77+++ openlp/core/ui/lib/listpreviewwidget.py 2016-06-02 10:36:58 +0000
78@@ -63,6 +63,7 @@
79 # Initialize variables.
80 self.service_item = ServiceItem()
81 self.screen_ratio = screen_ratio
82+ self.auto_row_height = 100
83 # Connect signals
84 self.verticalHeader().sectionResized.connect(self.row_resized)
85
86@@ -87,8 +88,14 @@
87 height = self.viewport().width() // self.screen_ratio
88 max_img_row_height = Settings().value('advanced/slide max height')
89 # Adjust for row height cap if in use.
90- if isinstance(max_img_row_height, int) and max_img_row_height > 0 and height > max_img_row_height:
91- height = max_img_row_height
92+ if isinstance(max_img_row_height, int):
93+ if max_img_row_height > 0 and height > max_img_row_height:
94+ height = max_img_row_height
95+ elif max_img_row_height < 0:
96+ # If auto setting, show that number of slides, or if the resulting slides too small, 100px.
97+ # E.g. If setting is -4, 4 slides will be visible, unless those slides are < 100px high.
98+ self.auto_row_height = max(self.viewport().height() / (-1 * max_img_row_height), 100)
99+ height = min(height, self.auto_row_height)
100 # Apply new height to slides
101 for frame_number in range(len(self.service_item.get_frames())):
102 self.setRowHeight(frame_number, height)
103@@ -99,7 +106,7 @@
104 """
105 # Only for non-text slides when row height cap in use
106 max_img_row_height = Settings().value('advanced/slide max height')
107- if self.service_item.is_text() or not isinstance(max_img_row_height, int) or max_img_row_height <= 0:
108+ if self.service_item.is_text() or not isinstance(max_img_row_height, int) or max_img_row_height == 0:
109 return
110 # Get and validate label widget containing slide & adjust max width
111 try:
112@@ -165,11 +172,15 @@
113 slide_height = width // self.screen_ratio
114 # Setup and validate row height cap if in use.
115 max_img_row_height = Settings().value('advanced/slide max height')
116- if isinstance(max_img_row_height, int) and max_img_row_height > 0:
117- if slide_height > max_img_row_height:
118+ if isinstance(max_img_row_height, int) and max_img_row_height != 0:
119+ if max_img_row_height > 0 and slide_height > max_img_row_height:
120+ # Manual Setting
121 slide_height = max_img_row_height
122- label.setMaximumWidth(max_img_row_height * self.screen_ratio)
123- label.resize(max_img_row_height * self.screen_ratio, max_img_row_height)
124+ elif max_img_row_height < 0 and slide_height > self.auto_row_height:
125+ # Auto Setting
126+ slide_height = self.auto_row_height
127+ label.setMaximumWidth(slide_height * self.screen_ratio)
128+ label.resize(slide_height * self.screen_ratio, slide_height)
129 # Build widget with stretch padding
130 container = QtWidgets.QWidget()
131 hbox = QtWidgets.QHBoxLayout()
132
133=== modified file 'tests/functional/openlp_core_common/test_registryproperties.py'
134--- tests/functional/openlp_core_common/test_registryproperties.py 2016-05-31 21:40:13 +0000
135+++ tests/functional/openlp_core_common/test_registryproperties.py 2016-06-02 10:36:58 +0000
136@@ -75,4 +75,3 @@
137
138 # THEN the application should be none
139 self.assertEqual(self.application, application, 'The application value should match')
140-
141
142=== modified file 'tests/functional/openlp_core_ui_lib/test_listpreviewwidget.py'
143--- tests/functional/openlp_core_ui_lib/test_listpreviewwidget.py 2016-06-01 21:42:54 +0000
144+++ tests/functional/openlp_core_ui_lib/test_listpreviewwidget.py 2016-06-02 10:36:58 +0000
145@@ -227,6 +227,44 @@
146
147 @patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.resizeRowsToContents')
148 @patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.setRowHeight')
149+ def test_replace_recalculate_layout_img_auto(self, mocked_setRowHeight, mocked_resizeRowsToContents):
150+ """
151+ Test if "Max height for non-text slides..." auto, img slides resized in replace_service_item & __recalc...
152+ """
153+ # GIVEN: A setting to adjust "Max height for non-text slides in slide controller",
154+ # an image ServiceItem and a ListPreviewWidget.
155+
156+ # Mock Settings().value('advanced/slide max height')
157+ self.mocked_Settings_obj.value.return_value = -4
158+ # Mock self.viewport().width()
159+ self.mocked_viewport_obj.width.return_value = 200
160+ self.mocked_viewport_obj.height.return_value = 600
161+ # Mock image service item
162+ service_item = MagicMock()
163+ service_item.is_text.return_value = False
164+ service_item.is_capable.return_value = False
165+ service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': None},
166+ {'title': None, 'path': None, 'image': None}]
167+ # init ListPreviewWidget and load service item
168+ list_preview_widget = ListPreviewWidget(None, 1)
169+ list_preview_widget.replace_service_item(service_item, 200, 0)
170+ # Change viewport width before forcing a resize
171+ self.mocked_viewport_obj.width.return_value = 400
172+
173+ # WHEN: __recalculate_layout() is called (via screen_size_changed)
174+ list_preview_widget.screen_size_changed(1)
175+ self.mocked_viewport_obj.height.return_value = 200
176+ list_preview_widget.screen_size_changed(1)
177+
178+ # THEN: resizeRowsToContents() should not be called, while setRowHeight() should be called
179+ # twice for each slide.
180+ self.assertEquals(mocked_resizeRowsToContents.call_count, 0, 'Should not be called')
181+ self.assertEquals(mocked_setRowHeight.call_count, 6, 'Should be called 3 times for each slide')
182+ calls = [call(0, 100), call(1, 100), call(0, 150), call(1, 150), call(0, 100), call(1, 100)]
183+ mocked_setRowHeight.assert_has_calls(calls)
184+
185+ @patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.resizeRowsToContents')
186+ @patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.setRowHeight')
187 @patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.cellWidget')
188 def test_row_resized_text(self, mocked_cellWidget, mocked_setRowHeight, mocked_resizeRowsToContents):
189 """
190@@ -331,6 +369,41 @@
191 # THEN: self.cellWidget(row, 0).children()[1].setMaximumWidth() should be called
192 mocked_cellWidget_child.setMaximumWidth.assert_called_once_with(150)
193
194+ @patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.resizeRowsToContents')
195+ @patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.setRowHeight')
196+ @patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.cellWidget')
197+ def test_row_resized_setting_changed(self, mocked_cellWidget, mocked_setRowHeight, mocked_resizeRowsToContents):
198+ """
199+ Test if "Max height for non-text slides..." enabled while item live, program doesn't crash on row_resized.
200+ """
201+ # GIVEN: A setting to adjust "Max height for non-text slides in slide controller",
202+ # an image ServiceItem and a ListPreviewWidget.
203+
204+ # Mock Settings().value('advanced/slide max height')
205+ self.mocked_Settings_obj.value.return_value = 0
206+ # Mock self.viewport().width()
207+ self.mocked_viewport_obj.width.return_value = 200
208+ # Mock image service item
209+ service_item = MagicMock()
210+ service_item.is_text.return_value = False
211+ service_item.is_capable.return_value = False
212+ service_item.get_frames.return_value = [{'title': None, 'path': None, 'image': None},
213+ {'title': None, 'path': None, 'image': None}]
214+ # Mock self.cellWidget().children()
215+ mocked_cellWidget_obj = MagicMock()
216+ mocked_cellWidget_obj.children.return_value = None
217+ mocked_cellWidget.return_value = mocked_cellWidget_obj
218+ # init ListPreviewWidget and load service item
219+ list_preview_widget = ListPreviewWidget(None, 1)
220+ list_preview_widget.replace_service_item(service_item, 200, 0)
221+ self.mocked_Settings_obj.value.return_value = 100
222+
223+ # WHEN: row_resized() is called
224+ list_preview_widget.row_resized(0, 100, 150)
225+
226+ # THEN: self.cellWidget(row, 0).children()[1].setMaximumWidth() should fail
227+ self.assertRaises(Exception)
228+
229 @patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.selectRow')
230 @patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.scrollToItem')
231 @patch(u'openlp.core.ui.lib.listpreviewwidget.ListPreviewWidget.item')
232
233=== modified file 'tests/functional/openlp_plugins/bibles/test_lib.py'
234--- tests/functional/openlp_plugins/bibles/test_lib.py 2016-06-01 23:14:58 +0000
235+++ tests/functional/openlp_plugins/bibles/test_lib.py 2016-06-02 10:36:58 +0000
236@@ -43,6 +43,7 @@
237 separators = {'sep_r': '\\s*(?:e)\\s*', 'sep_e_default': 'end', 'sep_v_display': 'w', 'sep_l_display': 'r',
238 'sep_v_default': ':|v|V|verse|verses', 'sep_l': '\\s*(?:r)\\s*', 'sep_l_default': ',|and',
239 'sep_e': '\\s*(?:t)\\s*', 'sep_v': '\\s*(?:w)\\s*', 'sep_r_display': 'e', 'sep_r_default': '-|to'}
240+
241 def _update_side_effect():
242 """
243 Update the references after mocking out the method
244
245=== modified file 'tests/functional/openlp_plugins/songs/test_opsproimport.py'
246--- tests/functional/openlp_plugins/songs/test_opsproimport.py 2016-06-01 23:14:58 +0000
247+++ tests/functional/openlp_plugins/songs/test_opsproimport.py 2016-06-02 10:36:58 +0000
248@@ -171,4 +171,3 @@
249 result_data = json.loads(result_file.read().decode())
250 self.assertListEqual(importer.verses, _get_item(result_data, 'verses'))
251 self.assertListEqual(importer.verse_order_list_generated, _get_item(result_data, 'verse_order_list'))
252-