Merge lp:~googol-deactivatedaccount/openlp/bug-827862 into lp:openlp

Proposed by Andreas Preikschat
Status: Merged
Approved by: Tim Bentley
Approved revision: 1799
Merged at revision: 1797
Proposed branch: lp:~googol-deactivatedaccount/openlp/bug-827862
Merge into: lp:openlp
Diff against target: 215 lines (+177/-3)
1 file modified
openlp/core/ui/slidecontroller.py (+177/-3)
To merge this branch: bzr merge lp:~googol-deactivatedaccount/openlp/bug-827862
Reviewer Review Type Date Requested Status
Tim Bentley Approve
Raoul Snyman Approve
Review via email: mp+80783@code.launchpad.net

This proposal supersedes a proposal from 2011-10-31.

Commit message

- fixed bug #827862 (Add Shortcut to change verse, chorus, ... in the live controller)

Description of the change

Hello,

- fixed bug #827862 (Add Shortcut to change verse, chorus, ... in the live controller)

What exactly can yo do?
You can navigate/jump to any (!) slide in the slidecontrollers. In other words you can navigate/jump to aother bible verse slide, presentation slide, image or song verse. There is no limitation (e. g. you can also go from bible verse slide 1 to slide 12.

How does it not work?
This does not use traditional shortcuts (shortcut = press one or more keys at the same time).

Why does it work this way?
Shortcuts are limited. E. g. you cannot have "v+1" as shortcut. You can have "v" or "1" as shortcut.

How does it work?
Imagine you want to jump to slide "v3". What do you do? First you press "v" and then you press "4". But you have to be fast enough. (This might sound stupid to you and you might want to criticise this, but remember that if we were using shortcuts you had to press them at the same time.)

Unfortunately this adds an import from plugins to core. Also it adds plugin specific shortcuts to core. I actually moved some code to the songs plugin, but then decided that this is wrong as well. The reason is quite simple: Core has to be able to display a song (from the service manager) even when the songs plugin is disabled. (Note, when you have a service file with English Verse Names, because the service file comes from an English OpenLP instance then this will not work on a German OpenLP instance, because the verse names are not translated!) Thus it is not plugin specific, but core. However, I made sure that core won't break if the songs plugin is not available.

To post a comment you must log in.
Revision history for this message
Tim Bentley (trb143) wrote :

Being unavailable will not stop imports it just switches them off so there would be no breakage.
I do not like imports in the the middle of code.
It would be better to move the verse case to core.

review: Needs Fixing
Revision history for this message
Andreas Preikschat (googol-deactivatedaccount) wrote :

> I do not like imports in the the middle of code.
Neither do I, but the import does not work in the header. Also because the method is called more than once...

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

Following discussion this is the bes we can do for now.

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

To stop accidents!

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

Making the best of a difficult situation.

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

> To stop accidents!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/core/ui/slidecontroller.py'
2--- openlp/core/ui/slidecontroller.py 2011-10-22 11:09:01 +0000
3+++ openlp/core/ui/slidecontroller.py 2011-10-31 09:17:27 +0000
4@@ -321,6 +321,94 @@
5 self.slidePreview.setObjectName(u'slidePreview')
6 self.slideLayout.insertWidget(0, self.slidePreview)
7 self.grid.addLayout(self.slideLayout, 0, 0, 1, 1)
8+ if self.isLive:
9+ self.current_shortcut = u''
10+ self.shortcutTimer = QtCore.QTimer()
11+ self.shortcutTimer.setObjectName(u'shortcutTimer')
12+ self.shortcutTimer.setSingleShot(True)
13+ self.verseShortcut = shortcut_action(self, u'verseShortcut',
14+ [QtGui.QKeySequence(u'V')], self.slideShortcutActivated,
15+ category=UiStrings().LiveToolbar,
16+ context=QtCore.Qt.WidgetWithChildrenShortcut)
17+ self.verseShortcut.setText(translate(
18+ 'OpenLP.SlideController', 'Go to "Verse"'))
19+ self.shortcut0 = shortcut_action(self, u'0',
20+ [QtGui.QKeySequence(u'0')], self.slideShortcutActivated,
21+ context=QtCore.Qt.WidgetWithChildrenShortcut)
22+ self.shortcut1 = shortcut_action(self, u'1',
23+ [QtGui.QKeySequence(u'1')], self.slideShortcutActivated,
24+ context=QtCore.Qt.WidgetWithChildrenShortcut)
25+ self.shortcut2 = shortcut_action(self, u'2',
26+ [QtGui.QKeySequence(u'2')], self.slideShortcutActivated,
27+ context=QtCore.Qt.WidgetWithChildrenShortcut)
28+ self.shortcut3 = shortcut_action(self, u'3',
29+ [QtGui.QKeySequence(u'3')], self.slideShortcutActivated,
30+ context=QtCore.Qt.WidgetWithChildrenShortcut)
31+ self.shortcut4 = shortcut_action(self, u'4',
32+ [QtGui.QKeySequence(u'4')], self.slideShortcutActivated,
33+ context=QtCore.Qt.WidgetWithChildrenShortcut)
34+ self.shortcut5 = shortcut_action(self, u'5',
35+ [QtGui.QKeySequence(u'5')], self.slideShortcutActivated,
36+ context=QtCore.Qt.WidgetWithChildrenShortcut)
37+ self.shortcut6 = shortcut_action(self, u'6',
38+ [QtGui.QKeySequence(u'6')], self.slideShortcutActivated,
39+ context=QtCore.Qt.WidgetWithChildrenShortcut)
40+ self.shortcut7 = shortcut_action(self, u'7',
41+ [QtGui.QKeySequence(u'7')], self.slideShortcutActivated,
42+ context=QtCore.Qt.WidgetWithChildrenShortcut)
43+ self.shortcut8 = shortcut_action(self, u'8',
44+ [QtGui.QKeySequence(u'8')], self.slideShortcutActivated,
45+ context=QtCore.Qt.WidgetWithChildrenShortcut)
46+ self.shortcut9 = shortcut_action(self, u'9',
47+ [QtGui.QKeySequence(u'9')], self.slideShortcutActivated,
48+ context=QtCore.Qt.WidgetWithChildrenShortcut)
49+ self.chorusShortcut = shortcut_action(self, u'chorusShortcut',
50+ [QtGui.QKeySequence(u'C')], self.slideShortcutActivated,
51+ category=UiStrings().LiveToolbar,
52+ context=QtCore.Qt.WidgetWithChildrenShortcut)
53+ self.chorusShortcut.setText(translate(
54+ 'OpenLP.SlideController', 'Go to "Chorus"'))
55+ self.bridgeShortcut = shortcut_action(self, u'bridgeShortcut',
56+ [QtGui.QKeySequence(u'B')], self.slideShortcutActivated,
57+ category=UiStrings().LiveToolbar,
58+ context=QtCore.Qt.WidgetWithChildrenShortcut)
59+ self.bridgeShortcut.setText(translate(
60+ 'OpenLP.SlideController', 'Go to "Bridge"'))
61+ self.preChorusShortcut = shortcut_action(self, u'preChorusShortcut',
62+ [QtGui.QKeySequence(u'P')], self.slideShortcutActivated,
63+ category=UiStrings().LiveToolbar,
64+ context=QtCore.Qt.WidgetWithChildrenShortcut)
65+ self.preChorusShortcut.setText(translate(
66+ 'OpenLP.SlideController', 'Go to "Pre-Chorus"'))
67+ self.introShortcut = shortcut_action(self, u'introShortcut',
68+ [QtGui.QKeySequence(u'I')], self.slideShortcutActivated,
69+ category=UiStrings().LiveToolbar,
70+ context=QtCore.Qt.WidgetWithChildrenShortcut)
71+ self.introShortcut.setText(translate(
72+ 'OpenLP.SlideController', 'Go to "Intro"'))
73+ self.endingShortcut = shortcut_action(self, u'endingShortcut',
74+ [QtGui.QKeySequence(u'E')], self.slideShortcutActivated,
75+ category=UiStrings().LiveToolbar,
76+ context=QtCore.Qt.WidgetWithChildrenShortcut)
77+ self.endingShortcut.setText(translate(
78+ 'OpenLP.SlideController', 'Go to "Ending"'))
79+ self.otherShortcut = shortcut_action(self, u'otherShortcut',
80+ [QtGui.QKeySequence(u'O')], self.slideShortcutActivated,
81+ category=UiStrings().LiveToolbar,
82+ context=QtCore.Qt.WidgetWithChildrenShortcut)
83+ self.otherShortcut.setText(translate(
84+ 'OpenLP.SlideController', 'Go to "Other"'))
85+ self.previewListWidget.addActions([
86+ self.shortcut0, self.shortcut1, self.shortcut2, self.shortcut3,
87+ self.shortcut4, self.shortcut5, self.shortcut6, self.shortcut7,
88+ self.shortcut8, self.shortcut9, self.verseShortcut,
89+ self.chorusShortcut, self.bridgeShortcut,
90+ self.preChorusShortcut, self.introShortcut, self.endingShortcut,
91+ self.otherShortcut
92+ ])
93+ QtCore.QObject.connect(
94+ self.shortcutTimer, QtCore.SIGNAL(u'timeout()'),
95+ self.slideShortcutActivated)
96 # Signals
97 QtCore.QObject.connect(self.previewListWidget,
98 QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected)
99@@ -367,6 +455,90 @@
100 QtCore.SIGNAL(u'slidecontroller_%s_unblank' % self.typePrefix),
101 self.onSlideUnblank)
102
103+ def slideShortcutActivated(self):
104+ """
105+ Called, when a shortcut has been activated to jump to a chorus, verse,
106+ etc.
107+
108+ **Note**: This implementation is based on shortcuts. But it rather works
109+ like "key sequenes". You have to press one key after the other and
110+ **not** at the same time.
111+ For example to jump to "V3" you have to press "V" and afterwards but
112+ within a time frame of 350ms you have to press "3".
113+ """
114+ try:
115+ from openlp.plugins.songs.lib import VerseType
116+ SONGS_PLUGIN_AVAILABLE = True
117+ except ImportError:
118+ SONGS_PLUGIN_AVAILABLE = False
119+ verse_type = unicode(self.sender().objectName())
120+ if verse_type.startswith(u'verseShortcut'):
121+ if SONGS_PLUGIN_AVAILABLE:
122+ self.current_shortcut = \
123+ VerseType.TranslatedTags[VerseType.Verse]
124+ else:
125+ self.current_shortcut = u'V'
126+ elif verse_type.startswith(u'chorusShortcut'):
127+ if SONGS_PLUGIN_AVAILABLE:
128+ self.current_shortcut = \
129+ VerseType.TranslatedTags[VerseType.Chorus]
130+ else:
131+ self.current_shortcut = u'C'
132+ elif verse_type.startswith(u'bridgeShortcut'):
133+ if SONGS_PLUGIN_AVAILABLE:
134+ self.current_shortcut = \
135+ VerseType.TranslatedTags[VerseType.Bridge]
136+ else:
137+ self.current_shortcut = u'B'
138+ elif verse_type.startswith(u'preChorusShortcut'):
139+ if SONGS_PLUGIN_AVAILABLE:
140+ self.current_shortcut = \
141+ VerseType.TranslatedTags[VerseType.PreChorus]
142+ else:
143+ self.current_shortcut = u'P'
144+ elif verse_type.startswith(u'introShortcut'):
145+ if SONGS_PLUGIN_AVAILABLE:
146+ self.current_shortcut = \
147+ VerseType.TranslatedTags[VerseType.Intro]
148+ else:
149+ self.current_shortcut = u'I'
150+ elif verse_type.startswith(u'endingShortcut'):
151+ if SONGS_PLUGIN_AVAILABLE:
152+ self.current_shortcut = \
153+ VerseType.TranslatedTags[VerseType.Ending]
154+ else:
155+ self.current_shortcut = u'E'
156+ elif verse_type.startswith(u'otherShortcut'):
157+ if SONGS_PLUGIN_AVAILABLE:
158+ self.current_shortcut = \
159+ VerseType.TranslatedTags[VerseType.Other]
160+ else:
161+ self.current_shortcut = u'O'
162+ elif verse_type.isnumeric():
163+ self.current_shortcut += verse_type
164+ self.current_shortcut = self.current_shortcut.upper()
165+ keys = self.slideList.keys()
166+ matches = [match for match in keys
167+ if match.startswith(self.current_shortcut)]
168+ if len(matches) == 1:
169+ self.shortcutTimer.stop()
170+ self.current_shortcut = u''
171+ self.__checkUpdateSelectedSlide(self.slideList[matches[0]])
172+ self.slideSelected()
173+ elif verse_type != u'shortcutTimer':
174+ # Start the time as we did not have any match.
175+ self.shortcutTimer.start(350)
176+ else:
177+ # The timer timed out.
178+ if self.current_shortcut in keys:
179+ # We had more than one match for example "V1" and "V10", but
180+ # "V1" was the slide we wanted to go.
181+ self.__checkUpdateSelectedSlide(
182+ self.slideList[self.current_shortcut])
183+ self.slideSelected()
184+ # Reset the shortcut.
185+ self.current_shortcut = u''
186+
187 def setPreviewHotkeys(self, parent=None):
188 self.previousItem.setObjectName(u'previousItemPreview')
189 self.nextItem.setObjectName(u'nextItemPreview')
190@@ -643,13 +815,14 @@
191 verse_def = u'%s%s' % (verse_def[0], verse_def[1:])
192 two_line_def = u'%s\n%s' % (verse_def[0], verse_def[1:])
193 row = two_line_def
194- if self.isLive:
195- if verse_def not in self.slideList:
196- self.slideList[verse_def] = framenumber
197+ if verse_def not in self.slideList:
198+ self.slideList[verse_def] = framenumber
199+ if self.isLive:
200 self.songMenu.menu().addAction(verse_def,
201 self.onSongBarHandler)
202 else:
203 row += 1
204+ self.slideList[unicode(row)] = row - 1
205 item.setText(frame[u'text'])
206 else:
207 label = QtGui.QLabel()
208@@ -667,6 +840,7 @@
209 self.previewListWidget.setCellWidget(framenumber, 0, label)
210 slideHeight = width * self.parent().renderer.screen_ratio
211 row += 1
212+ self.slideList[unicode(row)] = row - 1
213 text.append(unicode(row))
214 self.previewListWidget.setItem(framenumber, 0, item)
215 if slideHeight != 0: