Merge lp:~suutari-olli/openlp/click-slide-to-go-live-from-blank into lp:openlp

Proposed by Azaziah
Status: Superseded
Proposed branch: lp:~suutari-olli/openlp/click-slide-to-go-live-from-blank
Merge into: lp:openlp
Diff against target: 266 lines (+142/-3)
5 files modified
openlp/core/common/settings.py (+1/-0)
openlp/core/ui/generaltab.py (+7/-0)
openlp/core/ui/slidecontroller.py (+32/-2)
openlp/plugins/presentations/lib/messagelistener.py (+5/-1)
tests/functional/openlp_core_ui/test_slidecontroller.py (+97/-0)
To merge this branch: bzr merge lp:~suutari-olli/openlp/click-slide-to-go-live-from-blank
Reviewer Review Type Date Requested Status
Raoul Snyman Approve
Tomas Groth Pending
Review via email: mp+291690@code.launchpad.net

This proposal supersedes a proposal from 2016-04-10.

This proposal has been superseded by a proposal from 2016-04-13.

Description of the change

In this re-proposal: Merged to trunk on 13.4.16, tests are now passing again.

Add this to your merge proposal:
--------------------------------
lp:~suutari-olli/openlp/click-slide-to-go-live-from-blank (revision 2638)
[←[1;32mSUCCESS←[1;m] https://ci.openlp.io/job/Branch-01-Pull/1422/
[←[1;32mSUCCESS←[1;m] https://ci.openlp.io/job/Branch-02-Functional-Tests/1339/
[←[1;32mSUCCESS←[1;m] https://ci.openlp.io/job/Branch-03-Interface-Tests/1278/
[←[1;32mSUCCESS←[1;m] https://ci.openlp.io/job/Branch-04a-Windows_Functional_Tests/1087/
[←[1;32mSUCCESS←[1;m] https://ci.openlp.io/job/Branch-04b-Windows_Interface_Tests/678/
[←[1;32mSUCCESS←[1;m] https://ci.openlp.io/job/Branch-05a-Code_Analysis/745/
[←[1;32mSUCCESS←[1;m] https://ci.openlp.io/job/Branch-05b-Test_Coverage/613/

-------------------------------------------------------------
Merged trunk on 11.4.2016
---------------------------------------------------------------

Added 3 tests for checking display is re-blanked if it was blanked before re-processing edited Live item.

Also fixed the issue where Next/Previous slide does not unblank display for PowerPoint/Impress.

-------------------------------------------------------------------------

This branch introduces the functionality of unblanking
display from Blank to Black/Theme/Desktop for:

a) Clicking slide in “Live panel”
b) Next/Previous shortcuts (Green arrows)
c) Go to verse x.
d) When starting automatic playback (To end or Loop)
Also added “Unblank display when changing slide in Live” to advanced
options tab for disabling/enabling this behavior for a-c.

Additionally this branch also includes fix for bug
https://bugs.launchpad.net/openlp/+bug/1531691
Do note that this branch does not fix this for Escape item blanking,
creating yet an another Escape exclusive bug.

The only reason Escape item has been a good alternative for other
blank to methods is the functionality of resuming Live by clicking
slides and the fact it worked in single screen scenarios.
I can’t see any reason why it should not be removed after this branch
is merged since the single screen issue was already fixed earlier.

To post a comment you must log in.
Revision history for this message
Tomas Groth (tomasgroth) wrote : Posted in a previous version of this proposal

Just tested a bit.
You have introduced the "Click live slide to unblank" setting, but a "Unblank display when adding new item" also exists in the general tab. You should probably move yours to be under the exiting one to keep similar settings in the same place. Currently your code doesn't honor the "Unblank display when adding new item", which it will have to do. As it is now the item goes live no matter if the setting is enabled or not.
Also the new setting should be "false" as default, this is new behavior, so users should enabled it if they want it.
Also added a code-comment below.

review: Needs Fixing
Revision history for this message
Azaziah (suutari-olli) wrote : Posted in a previous version of this proposal

Hi Tomas and thank you for your comments!

"Unblank display when adding new item" also exists in the general tab. You should probably move yours to be under the exiting one to keep similar settings in the same place. Currently your code doesn't honor the "Unblank display when adding new item

# Done and Done, now also honoring double clicking preview

Also the new setting should be "false" as default, this is new behavior, so users should enabled it if they want it.

# Done
# Currently this is default behavior for Escape item and probably easier
to use than our current blank to modes. I think this and some other settings
should eventually be changed to be more user friendly by default.

Revision history for this message
Tomas Groth (tomasgroth) wrote : Posted in a previous version of this proposal

Looks good now. As you mention in one of your source-comments the previous slide is shortly visible when display is unblanked. Don't know if it can be helped.
Added a comment to the code below.
Besides that, you need tests :)

review: Needs Fixing
Revision history for this message
Azaziah (suutari-olli) wrote : Posted in a previous version of this proposal

Thanks again,

if by previous slide being shortly visible you mean it happens once you change slide inside the Live Panel
and the transition effect is applied, yes that can be changed. I've heard people complaining there's no transition effects when unblanking or changing items so maybe it should be left as it is since it would mean loosing effects.

If you were talking about this happening on song edit:
Think it would be possible but would require quite a effort,
maybe we can let it pass for the time being, it's still mostly fixed.

I really suck at writing tests, is one enough for a rookie?

I also replied to the code comment.

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

Looks good to me. Nice tests.

review: Approve
2639. By Azaziah

Changed spelling of live back to Live (Capitalized) on settings.

2640. By Azaziah

- Fixed bug 1462420 - Double clicking Preview adds item to Service countless times
  (Added hidden setting for controlling this, it is set to True once double clicking
  has added item to Service and gets reset to False once new item is sent to preview.

2641. By Azaziah

Fixed bug 1462420 (Double click on the preview duplicated the element in the service manger)
- Added a hidden setting for controlling this behaviour.
 It is reset if any item is sent to preview from library.
 Sending the same item to service multiple times is still possible by using the "Add icon"

2642. By Azaziah

Turned the new setting into question.

2643. By Azaziah

Made a better fix for fixing bug where display is unblanked on editing current live item.
This now sets a hidden setting to true while processing Live item and then changes it back to false.
Display is thus not unblanked at all during the process. (Old fix showed the edited slide for a small time)

Downside: All the new tests were based on the old method and thus they were removed.

2644. By Azaziah

Made a better fix for fixing bug where display is unblanked on editing current live item.
This now sets a hidden setting to true while processing Live item and then changes it back to false.
Display is thus not unblanked at all during the process. (Old fix showed the edited slide for a small time)

Downside: All the new tests were based on the old method and thus they were removed.

2645. By Azaziah

- Removed _ from end of one setting name.
- Fixed ident on replace_service_manager

2646. By Azaziah

- Added two tests for checking if doubleclicking preview should add item to service or send it to live.

2647. By Azaziah

Noticed I had removed one test from end of the file, added it back.

2648. By Azaziah

Added this to program startup code, should replace_service_manager_item ever crash the program.

Settings().setValue('core/is live item edited and replaced', False)

2649. By Azaziah

merged trunk on 14.6.16

2650. By Azaziah

- Turned the two new hidden settings into registry flags

2651. By Azaziah

Comment cleanup / Improvements

2652. By Azaziah

- Merged trunk on 27.6.16

2653. By Azaziah

- Tried to make the new text work with the registry changes but failed.
 > Test is broken, do not merge!

2654. By Azaziah

Merged trunk on 14.7.16

2655. By Azaziah

pep8 fixes, test still broken.

2656. By Azaziah

Fixed the tests.

2657. By Azaziah

- Reduced comments
- Removed unrequired reg_value from test.

2658. By Azaziah

- Fixed the issue where items sent to Preview from Service may cause tracebacks.

2659. By Azaziah

- Moved the 2nd new registry flag from one init to an another init which also has the 1st

2660. By Azaziah

- Moved them to another init since something broke

2661. By Azaziah

- removed one unrequired if statement.

2662. By Azaziah

- Merged trunk on 31.7.16

2663. By Azaziah

- Merged trunk on 10/8/16.

2664. By Azaziah

- Merged trunk and resolved conflict that was created by ui-messages-part-1 branch.

Unmerged revisions

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-03-20 15:00:15 +0000
3+++ openlp/core/common/settings.py 2016-04-13 14:24:17 +0000
4@@ -142,6 +142,7 @@
5 'core/auto preview': False,
6 'core/audio start paused': True,
7 'core/auto unblank': False,
8+ 'core/click live slide to unblank': False,
9 'core/blank warning': False,
10 'core/ccli number': '',
11 'core/has run wizard': False,
12
13=== modified file 'openlp/core/ui/generaltab.py'
14--- openlp/core/ui/generaltab.py 2016-01-16 20:13:41 +0000
15+++ openlp/core/ui/generaltab.py 2016-04-13 14:24:17 +0000
16@@ -173,6 +173,9 @@
17 self.auto_unblank_check_box = QtWidgets.QCheckBox(self.settings_group_box)
18 self.auto_unblank_check_box.setObjectName('auto_unblank_check_box')
19 self.settings_layout.addRow(self.auto_unblank_check_box)
20+ self.click_live_slide_to_unblank_check_box = QtWidgets.QCheckBox(self.settings_group_box)
21+ self.click_live_slide_to_unblank_check_box.setObjectName('click_live_slide_to_unblank_')
22+ self.settings_layout.addRow(self.click_live_slide_to_unblank_check_box)
23 self.auto_preview_check_box = QtWidgets.QCheckBox(self.settings_group_box)
24 self.auto_preview_check_box.setObjectName('auto_preview_check_box')
25 self.settings_layout.addRow(self.auto_preview_check_box)
26@@ -217,6 +220,8 @@
27 self.save_check_service_check_box.setText(translate('OpenLP.GeneralTab',
28 'Prompt to save before starting a new service'))
29 self.auto_unblank_check_box.setText(translate('OpenLP.GeneralTab', 'Unblank display when adding new live item'))
30+ self.click_live_slide_to_unblank_check_box.setText(translate('OpenLP.GeneralTab',
31+ 'Unblank display when changing slide in Live'))
32 self.auto_preview_check_box.setText(translate('OpenLP.GeneralTab',
33 'Automatically preview next item in service'))
34 self.timeout_label.setText(translate('OpenLP.GeneralTab', 'Timed slide interval:'))
35@@ -250,6 +255,7 @@
36 self.password_edit.setText(settings.value('songselect password'))
37 self.save_check_service_check_box.setChecked(settings.value('save prompt'))
38 self.auto_unblank_check_box.setChecked(settings.value('auto unblank'))
39+ self.click_live_slide_to_unblank_check_box.setChecked(settings.value('click live slide to unblank'))
40 self.display_on_monitor_check.setChecked(self.screens.display)
41 self.warning_check_box.setChecked(settings.value('blank warning'))
42 self.auto_open_check_box.setChecked(settings.value('auto open'))
43@@ -287,6 +293,7 @@
44 settings.setValue('update check', self.check_for_updates_check_box.isChecked())
45 settings.setValue('save prompt', self.save_check_service_check_box.isChecked())
46 settings.setValue('auto unblank', self.auto_unblank_check_box.isChecked())
47+ settings.setValue('click live slide to unblank', self.click_live_slide_to_unblank_check_box.isChecked())
48 settings.setValue('auto preview', self.auto_preview_check_box.isChecked())
49 settings.setValue('loop delay', self.timeout_spin_box.value())
50 settings.setValue('ccli number', self.number_edit.displayText())
51
52=== modified file 'openlp/core/ui/slidecontroller.py'
53--- openlp/core/ui/slidecontroller.py 2016-03-31 16:34:22 +0000
54+++ openlp/core/ui/slidecontroller.py 2016-04-13 14:24:17 +0000
55@@ -789,11 +789,28 @@
56 def replace_service_manager_item(self, item):
57 """
58 Replacement item following a remote edit
59+ This action also takes place when a song that is sent to live from Service Manager is edited.
60+ If display is blanked, this will update the song and then re-blank the display.
61+ As result, lyrics are flashed on screen for a very short time before re-blanking happens. (Bug)
62+ This happens only when Automatic unblanking is enabled when new item is sen to Live,
63+ if it's not enabled they won't flash.
64
65 :param item: The current service item
66 """
67 if item == self.service_item:
68- self._process_item(item, self.preview_widget.current_slide_number())
69+ if not self.hide_mode():
70+ self._process_item(item, self.preview_widget.current_slide_number())
71+ # "isChecked" method is required for checking blanks, on_xx_display(False) does not work.
72+ elif self.hide_mode():
73+ if self.blank_screen.isChecked():
74+ self._process_item(item, self.preview_widget.current_slide_number())
75+ self.on_blank_display(True)
76+ elif self.theme_screen.isChecked():
77+ self._process_item(item, self.preview_widget.current_slide_number())
78+ self.on_theme_display(True)
79+ elif self.desktop_screen.isChecked():
80+ self._process_item(item, self.preview_widget.current_slide_number())
81+ self.on_hide_display(True)
82
83 def add_service_manager_item(self, item, slide_no):
84 """
85@@ -1090,6 +1107,14 @@
86 self.log_debug('Could not get lock in slide_selected after waiting %f, skip to avoid deadlock.'
87 % timeout)
88 return
89+ # If "click live slide to unblank" is enabled, unblank the display.
90+ # Note: If this if statement is placed at the bottom of this function instead of top slide transitions are lost.
91+ if self.is_live and Settings().value('core/click live slide to unblank'):
92+ # With this display stays blanked when "auto unblank" setting is not enabled and new item is sent to Live.
93+ if not Settings().value('core/auto unblank') and start:
94+ ()
95+ else:
96+ Registry().execute('slidecontroller_live_unblank')
97 row = self.preview_widget.current_slide_number()
98 old_selected_row = self.selected_row
99 self.selected_row = 0
100@@ -1258,6 +1283,8 @@
101 self.play_slides_once.setText(UiStrings().PlaySlidesToEnd)
102 self.play_slides_menu.setDefaultAction(self.play_slides_loop)
103 self.play_slides_once.setChecked(False)
104+ if Settings().value('core/click live slide to unblank'):
105+ Registry().execute('slidecontroller_live_unblank')
106 else:
107 self.play_slides_loop.setIcon(build_icon(':/media/media_time.png'))
108 self.play_slides_loop.setText(UiStrings().PlaySlidesInLoop)
109@@ -1281,6 +1308,8 @@
110 self.play_slides_loop.setText(UiStrings().PlaySlidesInLoop)
111 self.play_slides_menu.setDefaultAction(self.play_slides_once)
112 self.play_slides_loop.setChecked(False)
113+ if Settings().value('core/click live slide to unblank'):
114+ Registry().execute('slidecontroller_live_unblank')
115 else:
116 self.play_slides_once.setIcon(build_icon(':/media/media_time'))
117 self.play_slides_once.setText(UiStrings().PlaySlidesToEnd)
118@@ -1342,7 +1371,8 @@
119 Registry().execute('%s_stop' % self.service_item.name.lower(), [self.service_item, self.is_live])
120 if self.service_item.is_media():
121 self.on_media_close()
122- self.on_go_live()
123+ if Settings().value('core/auto unblank'):
124+ self.on_go_live()
125 else:
126 self.on_preview_add_to_service()
127
128
129=== modified file 'openlp/plugins/presentations/lib/messagelistener.py'
130--- openlp/plugins/presentations/lib/messagelistener.py 2016-02-05 20:11:36 +0000
131+++ openlp/plugins/presentations/lib/messagelistener.py 2016-04-13 14:24:17 +0000
132@@ -26,7 +26,7 @@
133
134 from PyQt5 import QtCore
135
136-from openlp.core.common import Registry
137+from openlp.core.common import Registry, Settings
138 from openlp.core.ui import HideMode
139 from openlp.core.lib import ServiceItemContext, ServiceItem
140 from openlp.plugins.presentations.lib.pdfcontroller import PDF_CONTROLLER_FILETYPES
141@@ -419,6 +419,8 @@
142 is_live = message[1]
143 if is_live:
144 self.live_handler.next()
145+ if Settings().value('core/click live slide to unblank'):
146+ Registry().execute('slidecontroller_live_unblank')
147 else:
148 self.preview_handler.next()
149
150@@ -431,6 +433,8 @@
151 is_live = message[1]
152 if is_live:
153 self.live_handler.previous()
154+ if Settings().value('core/click live slide to unblank'):
155+ Registry().execute('slidecontroller_live_unblank')
156 else:
157 self.preview_handler.previous()
158
159
160=== modified file 'tests/functional/openlp_core_ui/test_slidecontroller.py'
161--- tests/functional/openlp_core_ui/test_slidecontroller.py 2016-02-27 14:25:31 +0000
162+++ tests/functional/openlp_core_ui/test_slidecontroller.py 2016-04-13 14:24:17 +0000
163@@ -538,6 +538,103 @@
164 mocked_preview_widget.current_slide_number.assert_called_with()
165 mocked_process_item.assert_called_once_with(mocked_item, 7)
166
167+ def replace_service_manager_item_on_blank_display_test(self):
168+ """
169+ Test that when the service item is replaced, display remains blanked if it was blanked.
170+ """
171+ # GIVEN: A slide controller and a new item to add, blanked display.
172+ mocked_item = MagicMock()
173+ mocked_preview_widget = MagicMock()
174+ mocked_preview_widget.current_slide_number = MagicMock()
175+ mocked_process_item = MagicMock()
176+ slide_controller = SlideController(None)
177+ slide_controller.preview_widget = mocked_preview_widget
178+ slide_controller._process_item = mocked_process_item
179+ slide_controller.service_item = mocked_item
180+ slide_controller.hide_menu = MagicMock()
181+ slide_controller.hide_mode = MagicMock()
182+ slide_controller.hide_mode.return_value = True
183+ slide_controller.blank_screen = MagicMock()
184+ slide_controller.blank_screen.isChecked = MagicMock()
185+ slide_controller.blank_screen.isChecked.return_value = True
186+ slide_controller.on_blank_display = mocked_item
187+ slide_controller.theme_screen = MagicMock()
188+ slide_controller.desktop_screen = MagicMock()
189+ slide_controller.log_debug = MagicMock()
190+
191+ # WHEN: The service item is replaced
192+ slide_controller.replace_service_manager_item(mocked_item)
193+
194+ # THEN: The display should remain blanked
195+ slide_controller.on_blank_display.assert_called_once_with(True)
196+
197+ def replace_service_manager_item_on_theme_display_test(self):
198+ """
199+ Test that when the service item is replaced, display remains blanked if it was blanked.
200+ """
201+ # GIVEN: A slide controller and a new item to add, blanked display.
202+ mocked_item = MagicMock()
203+ mocked_preview_widget = MagicMock()
204+ mocked_preview_widget.current_slide_number = MagicMock()
205+ mocked_process_item = MagicMock()
206+ slide_controller = SlideController(None)
207+ slide_controller.preview_widget = mocked_preview_widget
208+ slide_controller._process_item = mocked_process_item
209+ slide_controller.service_item = mocked_item
210+ slide_controller.hide_menu = MagicMock()
211+ slide_controller.hide_mode = MagicMock()
212+ slide_controller.hide_mode.return_value = True
213+ slide_controller.blank_screen = MagicMock()
214+ slide_controller.blank_screen.isChecked = MagicMock()
215+ slide_controller.blank_screen.isChecked.return_value = False
216+ slide_controller.theme_screen = MagicMock()
217+ slide_controller.theme_screen.isChecked = MagicMock()
218+ slide_controller.theme_screen.isChecked.return_value = True
219+ slide_controller.on_theme_display = mocked_item
220+ slide_controller.desktop_screen = MagicMock()
221+ slide_controller.log_debug = MagicMock()
222+
223+ # WHEN: The service item is replaced
224+ slide_controller.replace_service_manager_item(mocked_item)
225+
226+ # THEN: The display should remain blanked
227+ slide_controller.on_theme_display.assert_called_once_with(True)
228+
229+ def replace_service_manager_item_on_hide_display_test(self):
230+ """
231+ Test that when the service item is replaced, display remains blanked if it was blanked.
232+ """
233+ # GIVEN: A slide controller and a new item to add, blanked display.
234+ mocked_item = MagicMock()
235+ mocked_preview_widget = MagicMock()
236+ mocked_preview_widget.current_slide_number = MagicMock()
237+ mocked_process_item = MagicMock()
238+ slide_controller = SlideController(None)
239+ slide_controller.preview_widget = mocked_preview_widget
240+ slide_controller._process_item = mocked_process_item
241+ slide_controller.service_item = mocked_item
242+ slide_controller.hide_menu = MagicMock()
243+ slide_controller.hide_mode = MagicMock()
244+ slide_controller.hide_mode.return_value = True
245+ slide_controller.blank_screen = MagicMock()
246+ slide_controller.blank_screen.isChecked = MagicMock()
247+ slide_controller.blank_screen.isChecked.return_value = False
248+ slide_controller.theme_screen = MagicMock()
249+ slide_controller.theme_screen.isChecked = MagicMock()
250+ slide_controller.theme_screen.isChecked.return_value = False
251+ slide_controller.on_theme_display = mocked_item
252+ slide_controller.desktop_screen = MagicMock()
253+ slide_controller.desktop_screen.isChecked = MagicMock()
254+ slide_controller.desktop_screen.isChecked.return_value = True
255+ slide_controller.on_hide_display = MagicMock()
256+ slide_controller.log_debug = MagicMock()
257+
258+ # WHEN: The service item is replaced
259+ slide_controller.replace_service_manager_item(mocked_item)
260+
261+ # THEN: The display should remain blanked
262+ slide_controller.on_hide_display.assert_called_once_with(True)
263+
264 def on_slide_blank_test(self):
265 """
266 Test on_slide_blank