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
=== modified file 'openlp/core/ui/slidecontroller.py'
--- openlp/core/ui/slidecontroller.py 2011-10-22 11:09:01 +0000
+++ openlp/core/ui/slidecontroller.py 2011-10-31 09:17:27 +0000
@@ -321,6 +321,94 @@
321 self.slidePreview.setObjectName(u'slidePreview')321 self.slidePreview.setObjectName(u'slidePreview')
322 self.slideLayout.insertWidget(0, self.slidePreview)322 self.slideLayout.insertWidget(0, self.slidePreview)
323 self.grid.addLayout(self.slideLayout, 0, 0, 1, 1)323 self.grid.addLayout(self.slideLayout, 0, 0, 1, 1)
324 if self.isLive:
325 self.current_shortcut = u''
326 self.shortcutTimer = QtCore.QTimer()
327 self.shortcutTimer.setObjectName(u'shortcutTimer')
328 self.shortcutTimer.setSingleShot(True)
329 self.verseShortcut = shortcut_action(self, u'verseShortcut',
330 [QtGui.QKeySequence(u'V')], self.slideShortcutActivated,
331 category=UiStrings().LiveToolbar,
332 context=QtCore.Qt.WidgetWithChildrenShortcut)
333 self.verseShortcut.setText(translate(
334 'OpenLP.SlideController', 'Go to "Verse"'))
335 self.shortcut0 = shortcut_action(self, u'0',
336 [QtGui.QKeySequence(u'0')], self.slideShortcutActivated,
337 context=QtCore.Qt.WidgetWithChildrenShortcut)
338 self.shortcut1 = shortcut_action(self, u'1',
339 [QtGui.QKeySequence(u'1')], self.slideShortcutActivated,
340 context=QtCore.Qt.WidgetWithChildrenShortcut)
341 self.shortcut2 = shortcut_action(self, u'2',
342 [QtGui.QKeySequence(u'2')], self.slideShortcutActivated,
343 context=QtCore.Qt.WidgetWithChildrenShortcut)
344 self.shortcut3 = shortcut_action(self, u'3',
345 [QtGui.QKeySequence(u'3')], self.slideShortcutActivated,
346 context=QtCore.Qt.WidgetWithChildrenShortcut)
347 self.shortcut4 = shortcut_action(self, u'4',
348 [QtGui.QKeySequence(u'4')], self.slideShortcutActivated,
349 context=QtCore.Qt.WidgetWithChildrenShortcut)
350 self.shortcut5 = shortcut_action(self, u'5',
351 [QtGui.QKeySequence(u'5')], self.slideShortcutActivated,
352 context=QtCore.Qt.WidgetWithChildrenShortcut)
353 self.shortcut6 = shortcut_action(self, u'6',
354 [QtGui.QKeySequence(u'6')], self.slideShortcutActivated,
355 context=QtCore.Qt.WidgetWithChildrenShortcut)
356 self.shortcut7 = shortcut_action(self, u'7',
357 [QtGui.QKeySequence(u'7')], self.slideShortcutActivated,
358 context=QtCore.Qt.WidgetWithChildrenShortcut)
359 self.shortcut8 = shortcut_action(self, u'8',
360 [QtGui.QKeySequence(u'8')], self.slideShortcutActivated,
361 context=QtCore.Qt.WidgetWithChildrenShortcut)
362 self.shortcut9 = shortcut_action(self, u'9',
363 [QtGui.QKeySequence(u'9')], self.slideShortcutActivated,
364 context=QtCore.Qt.WidgetWithChildrenShortcut)
365 self.chorusShortcut = shortcut_action(self, u'chorusShortcut',
366 [QtGui.QKeySequence(u'C')], self.slideShortcutActivated,
367 category=UiStrings().LiveToolbar,
368 context=QtCore.Qt.WidgetWithChildrenShortcut)
369 self.chorusShortcut.setText(translate(
370 'OpenLP.SlideController', 'Go to "Chorus"'))
371 self.bridgeShortcut = shortcut_action(self, u'bridgeShortcut',
372 [QtGui.QKeySequence(u'B')], self.slideShortcutActivated,
373 category=UiStrings().LiveToolbar,
374 context=QtCore.Qt.WidgetWithChildrenShortcut)
375 self.bridgeShortcut.setText(translate(
376 'OpenLP.SlideController', 'Go to "Bridge"'))
377 self.preChorusShortcut = shortcut_action(self, u'preChorusShortcut',
378 [QtGui.QKeySequence(u'P')], self.slideShortcutActivated,
379 category=UiStrings().LiveToolbar,
380 context=QtCore.Qt.WidgetWithChildrenShortcut)
381 self.preChorusShortcut.setText(translate(
382 'OpenLP.SlideController', 'Go to "Pre-Chorus"'))
383 self.introShortcut = shortcut_action(self, u'introShortcut',
384 [QtGui.QKeySequence(u'I')], self.slideShortcutActivated,
385 category=UiStrings().LiveToolbar,
386 context=QtCore.Qt.WidgetWithChildrenShortcut)
387 self.introShortcut.setText(translate(
388 'OpenLP.SlideController', 'Go to "Intro"'))
389 self.endingShortcut = shortcut_action(self, u'endingShortcut',
390 [QtGui.QKeySequence(u'E')], self.slideShortcutActivated,
391 category=UiStrings().LiveToolbar,
392 context=QtCore.Qt.WidgetWithChildrenShortcut)
393 self.endingShortcut.setText(translate(
394 'OpenLP.SlideController', 'Go to "Ending"'))
395 self.otherShortcut = shortcut_action(self, u'otherShortcut',
396 [QtGui.QKeySequence(u'O')], self.slideShortcutActivated,
397 category=UiStrings().LiveToolbar,
398 context=QtCore.Qt.WidgetWithChildrenShortcut)
399 self.otherShortcut.setText(translate(
400 'OpenLP.SlideController', 'Go to "Other"'))
401 self.previewListWidget.addActions([
402 self.shortcut0, self.shortcut1, self.shortcut2, self.shortcut3,
403 self.shortcut4, self.shortcut5, self.shortcut6, self.shortcut7,
404 self.shortcut8, self.shortcut9, self.verseShortcut,
405 self.chorusShortcut, self.bridgeShortcut,
406 self.preChorusShortcut, self.introShortcut, self.endingShortcut,
407 self.otherShortcut
408 ])
409 QtCore.QObject.connect(
410 self.shortcutTimer, QtCore.SIGNAL(u'timeout()'),
411 self.slideShortcutActivated)
324 # Signals412 # Signals
325 QtCore.QObject.connect(self.previewListWidget,413 QtCore.QObject.connect(self.previewListWidget,
326 QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected)414 QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected)
@@ -367,6 +455,90 @@
367 QtCore.SIGNAL(u'slidecontroller_%s_unblank' % self.typePrefix),455 QtCore.SIGNAL(u'slidecontroller_%s_unblank' % self.typePrefix),
368 self.onSlideUnblank)456 self.onSlideUnblank)
369457
458 def slideShortcutActivated(self):
459 """
460 Called, when a shortcut has been activated to jump to a chorus, verse,
461 etc.
462
463 **Note**: This implementation is based on shortcuts. But it rather works
464 like "key sequenes". You have to press one key after the other and
465 **not** at the same time.
466 For example to jump to "V3" you have to press "V" and afterwards but
467 within a time frame of 350ms you have to press "3".
468 """
469 try:
470 from openlp.plugins.songs.lib import VerseType
471 SONGS_PLUGIN_AVAILABLE = True
472 except ImportError:
473 SONGS_PLUGIN_AVAILABLE = False
474 verse_type = unicode(self.sender().objectName())
475 if verse_type.startswith(u'verseShortcut'):
476 if SONGS_PLUGIN_AVAILABLE:
477 self.current_shortcut = \
478 VerseType.TranslatedTags[VerseType.Verse]
479 else:
480 self.current_shortcut = u'V'
481 elif verse_type.startswith(u'chorusShortcut'):
482 if SONGS_PLUGIN_AVAILABLE:
483 self.current_shortcut = \
484 VerseType.TranslatedTags[VerseType.Chorus]
485 else:
486 self.current_shortcut = u'C'
487 elif verse_type.startswith(u'bridgeShortcut'):
488 if SONGS_PLUGIN_AVAILABLE:
489 self.current_shortcut = \
490 VerseType.TranslatedTags[VerseType.Bridge]
491 else:
492 self.current_shortcut = u'B'
493 elif verse_type.startswith(u'preChorusShortcut'):
494 if SONGS_PLUGIN_AVAILABLE:
495 self.current_shortcut = \
496 VerseType.TranslatedTags[VerseType.PreChorus]
497 else:
498 self.current_shortcut = u'P'
499 elif verse_type.startswith(u'introShortcut'):
500 if SONGS_PLUGIN_AVAILABLE:
501 self.current_shortcut = \
502 VerseType.TranslatedTags[VerseType.Intro]
503 else:
504 self.current_shortcut = u'I'
505 elif verse_type.startswith(u'endingShortcut'):
506 if SONGS_PLUGIN_AVAILABLE:
507 self.current_shortcut = \
508 VerseType.TranslatedTags[VerseType.Ending]
509 else:
510 self.current_shortcut = u'E'
511 elif verse_type.startswith(u'otherShortcut'):
512 if SONGS_PLUGIN_AVAILABLE:
513 self.current_shortcut = \
514 VerseType.TranslatedTags[VerseType.Other]
515 else:
516 self.current_shortcut = u'O'
517 elif verse_type.isnumeric():
518 self.current_shortcut += verse_type
519 self.current_shortcut = self.current_shortcut.upper()
520 keys = self.slideList.keys()
521 matches = [match for match in keys
522 if match.startswith(self.current_shortcut)]
523 if len(matches) == 1:
524 self.shortcutTimer.stop()
525 self.current_shortcut = u''
526 self.__checkUpdateSelectedSlide(self.slideList[matches[0]])
527 self.slideSelected()
528 elif verse_type != u'shortcutTimer':
529 # Start the time as we did not have any match.
530 self.shortcutTimer.start(350)
531 else:
532 # The timer timed out.
533 if self.current_shortcut in keys:
534 # We had more than one match for example "V1" and "V10", but
535 # "V1" was the slide we wanted to go.
536 self.__checkUpdateSelectedSlide(
537 self.slideList[self.current_shortcut])
538 self.slideSelected()
539 # Reset the shortcut.
540 self.current_shortcut = u''
541
370 def setPreviewHotkeys(self, parent=None):542 def setPreviewHotkeys(self, parent=None):
371 self.previousItem.setObjectName(u'previousItemPreview')543 self.previousItem.setObjectName(u'previousItemPreview')
372 self.nextItem.setObjectName(u'nextItemPreview')544 self.nextItem.setObjectName(u'nextItemPreview')
@@ -643,13 +815,14 @@
643 verse_def = u'%s%s' % (verse_def[0], verse_def[1:])815 verse_def = u'%s%s' % (verse_def[0], verse_def[1:])
644 two_line_def = u'%s\n%s' % (verse_def[0], verse_def[1:])816 two_line_def = u'%s\n%s' % (verse_def[0], verse_def[1:])
645 row = two_line_def817 row = two_line_def
646 if self.isLive:818 if verse_def not in self.slideList:
647 if verse_def not in self.slideList:819 self.slideList[verse_def] = framenumber
648 self.slideList[verse_def] = framenumber820 if self.isLive:
649 self.songMenu.menu().addAction(verse_def,821 self.songMenu.menu().addAction(verse_def,
650 self.onSongBarHandler)822 self.onSongBarHandler)
651 else:823 else:
652 row += 1824 row += 1
825 self.slideList[unicode(row)] = row - 1
653 item.setText(frame[u'text'])826 item.setText(frame[u'text'])
654 else:827 else:
655 label = QtGui.QLabel()828 label = QtGui.QLabel()
@@ -667,6 +840,7 @@
667 self.previewListWidget.setCellWidget(framenumber, 0, label)840 self.previewListWidget.setCellWidget(framenumber, 0, label)
668 slideHeight = width * self.parent().renderer.screen_ratio841 slideHeight = width * self.parent().renderer.screen_ratio
669 row += 1842 row += 1
843 self.slideList[unicode(row)] = row - 1
670 text.append(unicode(row))844 text.append(unicode(row))
671 self.previewListWidget.setItem(framenumber, 0, item)845 self.previewListWidget.setItem(framenumber, 0, item)
672 if slideHeight != 0:846 if slideHeight != 0: