diff --git a/openlp.pyw b/openlp.pyw index c287072f5..76d334bae 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -115,8 +115,7 @@ class OpenLP(QtGui.QApplication): # make sure Qt really display the splash screen self.processEvents() # start the main app window - self.mainWindow = MainWindow(screens, self.clipboard(), - self.arguments()) + self.mainWindow = MainWindow(self.clipboard(), self.arguments()) self.mainWindow.show() if show_splash: # now kill the splashscreen diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 7a1d1a679..27a34d54d 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -223,28 +223,6 @@ def resize_image(image, width, height, background=QtCore.Qt.black): painter.drawImage((width - realw) / 2, (height - realh) / 2, preview) return new_image -def check_search_result(treeWidget, search_results): - """ - Checks if the given ``search_results`` is empty and adds a - "No Search Results" item to the given ``treeWidget``. - - ``treeWidget`` - The ``QTreeWidget`` where the "No Search Results" item should be added - to, if the ``search_results`` is empty. - - ``search_results`` - This can either be a list or a dict. - """ - if search_results or treeWidget.count(): - return - message = translate('OpenLP.MediaManagerItem', 'No Search Results') - item = QtGui.QListWidgetItem(message) - item.setFlags(QtCore.Qt.NoItemFlags) - font = QtGui.QFont() - font.setItalic(True) - item.setFont(font) - treeWidget.addItem(item) - def check_item_selected(list_widget, message): """ Check if a list item is selected so an action may be performed on it @@ -299,7 +277,6 @@ from listwidgetwithdnd import ListWidgetWithDnD from displaytags import DisplayTags from eventreceiver import Receiver from spelltextedit import SpellTextEdit -from imagemanager import ImageManager from settingsmanager import SettingsManager from plugin import PluginStatus, StringContent, Plugin from pluginmanager import PluginManager @@ -311,6 +288,7 @@ from htmlbuilder import build_html, build_lyrics_format_css, \ build_lyrics_outline_css from toolbar import OpenLPToolbar from dockwidget import OpenLPDockWidget +from imagemanager import ImageManager from renderer import Renderer from mediamanageritem import MediaManagerItem from openlp.core.utils.actions import ActionList diff --git a/openlp/core/lib/dockwidget.py b/openlp/core/lib/dockwidget.py index 9b4661fee..ace364ed0 100644 --- a/openlp/core/lib/dockwidget.py +++ b/openlp/core/lib/dockwidget.py @@ -32,6 +32,7 @@ import logging from PyQt4 import QtGui from openlp.core.lib import build_icon +from openlp.core.ui import ScreenList log = logging.getLogger(__name__) @@ -50,3 +51,11 @@ class OpenLPDockWidget(QtGui.QDockWidget): self.setObjectName(name) if icon: self.setWindowIcon(build_icon(icon)) + # Sort out the minimum width. + screens = ScreenList.get_instance() + screen_width = screens.current[u'size'].width() + mainwindow_docbars = screen_width / 5 + if mainwindow_docbars > 300: + self.setMinimumWidth(300) + else: + self.setMinimumWidth(mainwindow_docbars) diff --git a/openlp/core/lib/htmlbuilder.py b/openlp/core/lib/htmlbuilder.py index 9d35ee9a8..69126163a 100644 --- a/openlp/core/lib/htmlbuilder.py +++ b/openlp/core/lib/htmlbuilder.py @@ -396,17 +396,22 @@ def build_html(item, screen, alert, islive, background, image=None): """ Build the full web paged structure for display - `item` + ``item`` Service Item to be displayed - `screen` + + ``screen`` Current display information - `alert` + + ``alert`` Alert display display information - `islive` + + ``islive`` Item is going live, rather than preview/theme building - `background` + + ``background`` Theme background image - bytes - `image` + + ``image`` Image media item - bytes """ width = screen[u'size'].width() @@ -451,7 +456,7 @@ def build_background_css(item, width, height): """ Build the background css - `item` + ``item`` Service Item containing theme and location information """ @@ -504,10 +509,10 @@ def build_lyrics_css(item, webkitvers): """ Build the lyrics display css - `item` + ``item`` Service Item containing theme and location information - `webkitvers` + ``webkitvers`` The version of qtwebkit we're using """ @@ -581,10 +586,10 @@ def build_lyrics_outline_css(theme, is_shadow=False): Build the css which controls the theme outline Also used by renderer for splitting verses - `theme` + ``theme`` Object containing theme information - `is_shadow` + ``is_shadow`` If true, use the shadow colors instead """ if theme.font_main_outline: @@ -605,13 +610,13 @@ def build_lyrics_format_css(theme, width, height): Build the css which controls the theme format Also used by renderer for splitting verses - `theme` + ``theme`` Object containing theme information - `width` + ``width`` Width of the lyrics block - `height` + ``height`` Height of the lyrics block """ @@ -641,10 +646,10 @@ def build_lyrics_html(item, webkitvers): """ Build the HTML required to show the lyrics - `item` + ``item`` Service Item containing theme and location information - `webkitvers` + ``webkitvers`` The version of qtwebkit we're using """ # Bugs in some versions of QtWebKit mean we sometimes need additional @@ -670,7 +675,7 @@ def build_footer_css(item, height): """ Build the display of the item footer - `item` + ``item`` Service Item to be processed. """ style = """ @@ -696,7 +701,7 @@ def build_alert_css(alertTab, width): """ Build the display of the footer - `alertTab` + ``alertTab`` Details from the Alert tab for fonts etc """ style = """ diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 4873f4975..f06dc2767 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -35,6 +35,7 @@ import time from PyQt4 import QtCore from openlp.core.lib import resize_image, image_to_byte +from openlp.core.ui import ScreenList log = logging.getLogger(__name__) @@ -70,18 +71,22 @@ class ImageManager(QtCore.QObject): def __init__(self): QtCore.QObject.__init__(self) + current_screen = ScreenList.get_instance().current + self.width = current_screen[u'size'].width() + self.height = current_screen[u'size'].height() self._cache = {} self._thread_running = False self._cache_dirty = False self.image_thread = ImageThread(self) - def update_display(self, width, height): + def update_display(self): """ Screen has changed size so rebuild the cache to new size """ log.debug(u'update_display') - self.width = width - self.height = height + current_screen = ScreenList.get_instance().current + self.width = current_screen[u'size'].width() + self.height = current_screen[u'size'].height() # mark the images as dirty for a rebuild for key in self._cache.keys(): image = self._cache[key] diff --git a/openlp/core/lib/listwidgetwithdnd.py b/openlp/core/lib/listwidgetwithdnd.py index c45b4cc9d..2419d1a35 100644 --- a/openlp/core/lib/listwidgetwithdnd.py +++ b/openlp/core/lib/listwidgetwithdnd.py @@ -49,6 +49,9 @@ class ListWidgetWithDnD(QtGui.QListWidget): if event.buttons() != QtCore.Qt.LeftButton: event.ignore() return + if not self.selectedItems(): + event.ignore() + return drag = QtGui.QDrag(self) mimeData = QtCore.QMimeData() drag.setMimeData(mimeData) diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index e5e8ed3b1..9c1a84c99 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -244,7 +244,6 @@ class MediaManagerItem(QtGui.QWidget): """ # Add the List widget self.listView = ListWidgetWithDnD(self, self.plugin.name) - self.listView.uniformItemSizes = True self.listView.setSpacing(1) self.listView.setSelectionMode( QtGui.QAbstractItemView.ExtendedSelection) @@ -254,54 +253,49 @@ class MediaManagerItem(QtGui.QWidget): # Add to pageLayout self.pageLayout.addWidget(self.listView) # define and add the context menu - self.listView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) + self.listView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) if self.hasEditIcon: - self.listView.addAction( - context_menu_action( - self.listView, u':/general/general_edit.png', - self.plugin.getString(StringContent.Edit)[u'title'], - self.onEditClick, context=QtCore.Qt.WidgetShortcut)) - self.listView.addAction(context_menu_separator(self.listView)) + context_menu_action( + self.listView, u':/general/general_edit.png', + self.plugin.getString(StringContent.Edit)[u'title'], + self.onEditClick) + context_menu_separator(self.listView) if self.hasDeleteIcon: - self.listView.addAction( - context_menu_action( - self.listView, u':/general/general_delete.png', - self.plugin.getString(StringContent.Delete)[u'title'], - self.onDeleteClick, [QtCore.Qt.Key_Delete], - context=QtCore.Qt.WidgetShortcut)) - self.listView.addAction(context_menu_separator(self.listView)) - self.listView.addAction( context_menu_action( - self.listView, u':/general/general_preview.png', - self.plugin.getString(StringContent.Preview)[u'title'], - self.onPreviewClick, [QtCore.Qt.Key_Enter, - QtCore.Qt.Key_Return], context=QtCore.Qt.WidgetShortcut)) - self.listView.addAction( - context_menu_action( - self.listView, u':/general/general_live.png', - self.plugin.getString(StringContent.Live)[u'title'], - self.onLiveClick, [QtCore.Qt.ShiftModifier + \ - QtCore.Qt.Key_Enter, QtCore.Qt.ShiftModifier + \ - QtCore.Qt.Key_Return], context=QtCore.Qt.WidgetShortcut)) - self.listView.addAction( + self.listView, u':/general/general_delete.png', + self.plugin.getString(StringContent.Delete)[u'title'], + self.onDeleteClick, [QtCore.Qt.Key_Delete]) + context_menu_separator(self.listView) + context_menu_action( + self.listView, u':/general/general_preview.png', + self.plugin.getString(StringContent.Preview)[u'title'], + self.onPreviewClick, [QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return]) + context_menu_action( + self.listView, u':/general/general_live.png', + self.plugin.getString(StringContent.Live)[u'title'], + self.onLiveClick, [QtCore.Qt.ShiftModifier + QtCore.Qt.Key_Enter, + QtCore.Qt.ShiftModifier + QtCore.Qt.Key_Return]) + context_menu_action( + self.listView, u':/general/general_add.png', + self.plugin.getString(StringContent.Service)[u'title'], + self.onAddClick, [QtCore.Qt.Key_Plus, QtCore.Qt.Key_Equal]) + if self.addToServiceItem: context_menu_action( self.listView, u':/general/general_add.png', - self.plugin.getString(StringContent.Service)[u'title'], - self.onAddClick, [QtCore.Qt.Key_Plus, QtCore.Qt.Key_Equal], - context=QtCore.Qt.WidgetShortcut)) - if self.addToServiceItem: - self.listView.addAction( - context_menu_action( - self.listView, u':/general/general_add.png', - translate('OpenLP.MediaManagerItem', - '&Add to selected Service Item'), - self.onAddEditClick, context=QtCore.Qt.WidgetShortcut)) + translate('OpenLP.MediaManagerItem', + '&Add to selected Service Item'), self.onAddEditClick) + # Create the context menu and add all actions from the listView. + self.menu = QtGui.QMenu() + self.menu.addActions(self.listView.actions()) QtCore.QObject.connect(self.listView, QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onClickPressed) QtCore.QObject.connect(self.listView, QtCore.SIGNAL(u'itemSelectionChanged()'), self.onSelectionChange) + QtCore.QObject.connect(self.listView, + QtCore.SIGNAL('customContextMenuRequested(QPoint)'), + self.contextMenu) def initialise(self): """ @@ -354,6 +348,15 @@ class MediaManagerItem(QtGui.QWidget): self.settingsSection, self.getFileList()) Receiver.send_message(u'cursor_normal') + def contextMenu(self, point): + item = self.listView.itemAt(point) + # Decide if we have to show the context menu or not. + if item is None: + return + if not item.flags() & QtCore.Qt.ItemIsSelectable: + return + self.menu.exec_(self.listView.mapToGlobal(point)) + def getFileList(self): """ Return the current list of files @@ -548,6 +551,20 @@ class MediaManagerItem(QtGui.QWidget): """ pass + def check_search_result(self): + """ + Checks if the listView is empty and adds a "No Search Results" item. + """ + if self.listView.count(): + return + message = translate('OpenLP.MediaManagerItem', 'No Search Results') + item = QtGui.QListWidgetItem(message) + item.setFlags(QtCore.Qt.NoItemFlags) + font = QtGui.QFont() + font.setItalic(True) + item.setFont(font) + self.listView.addItem(item) + def _getIdOfItemToGenerate(self, item, remoteItem): """ Utility method to check items being submitted for slide generation. diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index bba85d176..5a4e62254 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -28,11 +28,11 @@ import logging from PyQt4 import QtCore, QtWebKit -from openlp.core.lib import ServiceItem, ImageManager, expand_tags, \ +from openlp.core.lib import ServiceItem, expand_tags, \ build_lyrics_format_css, build_lyrics_outline_css, Receiver, \ ItemCapabilities from openlp.core.lib.theme import ThemeLevel -from openlp.core.ui import MainDisplay +from openlp.core.ui import MainDisplay, ScreenList log = logging.getLogger(__name__) @@ -52,33 +52,32 @@ class Renderer(object): Class to pull all Renderer interactions into one place. The plugins will call helper methods to do the rendering but this class will provide display defense code. - - ``theme_manager`` - The ThemeManager instance, used to get the current theme details. - - ``screens`` - Contains information about the Screens. - - ``screen_number`` - Defaults to *0*. The index of the output/display screen. """ log.info(u'Renderer Loaded') - def __init__(self, theme_manager, screens): + def __init__(self, image_manager, theme_manager): """ Initialise the render manager. + + ``image_manager`` + A ImageManager instance which takes care of e. g. caching and resizing + images. + + ``theme_manager`` + The ThemeManager instance, used to get the current theme details. """ log.debug(u'Initilisation started') - self.screens = screens - self.image_manager = ImageManager() - self.display = MainDisplay(self, screens, False) - self.display.imageManager = self.image_manager self.theme_manager = theme_manager + self.image_manager = image_manager + self.screens = ScreenList.get_instance() self.service_theme = u'' self.theme_level = u'' self.override_background = None self.theme_data = None + self.bg_frame = None self.force_page = False + self.display = MainDisplay(self, self.image_manager, False) + self.display.setup() def update_display(self): """ @@ -86,12 +85,10 @@ class Renderer(object): """ log.debug(u'Update Display') self._calculate_default(self.screens.current[u'size']) - self.display = MainDisplay(self, self.screens, False) - self.display.imageManager = self.image_manager + self.display = MainDisplay(self, self.image_manager, False) self.display.setup() self.bg_frame = None self.theme_data = None - self.image_manager.update_display(self.width, self.height) def set_global_theme(self, global_theme, theme_level=ThemeLevel.Global): """ @@ -165,8 +162,10 @@ class Renderer(object): self.theme_data = self.theme_manager.getThemeData(theme) self._calculate_default(self.screens.current[u'size']) self._build_text_rectangle(self.theme_data) - self.image_manager.add_image(self.theme_data.theme_name, - self.theme_data.background_filename) + # if No file do not update cache + if self.theme_data.background_filename: + self.image_manager.add_image(self.theme_data.theme_name, + self.theme_data.background_filename) return self._rect, self._rect_footer def generate_preview(self, theme_data, force_page=False): @@ -189,10 +188,10 @@ class Renderer(object): serviceItem.theme = theme_data if self.force_page: # make big page for theme edit dialog to get line count - serviceItem.add_from_text(u'', VERSE + VERSE + VERSE, FOOTER) + serviceItem.add_from_text(u'', VERSE + VERSE + VERSE) else: self.image_manager.del_image(theme_data.theme_name) - serviceItem.add_from_text(u'', VERSE, FOOTER) + serviceItem.add_from_text(u'', VERSE) serviceItem.renderer = self serviceItem.raw_footer = FOOTER serviceItem.render(True) diff --git a/openlp/core/lib/searchedit.py b/openlp/core/lib/searchedit.py index b524855ba..fc007227e 100644 --- a/openlp/core/lib/searchedit.py +++ b/openlp/core/lib/searchedit.py @@ -62,6 +62,7 @@ class SearchEdit(QtGui.QLineEdit): self._onSearchEditTextChanged ) self._updateStyleSheet() + self.setAcceptDrops(False) def _updateStyleSheet(self): """ diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index c1ae95b8b..95702f229 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -219,6 +219,8 @@ class ServiceItem(object): ``raw_slide`` The raw text of the slide. """ + if verse_tag: + verse_tag = verse_tag.upper() self.service_item_type = ServiceItemType.Text title = title.split(u'\n')[0] self._raw_frames.append( diff --git a/openlp/core/lib/settingsmanager.py b/openlp/core/lib/settingsmanager.py index bb83371e6..472c66e23 100644 --- a/openlp/core/lib/settingsmanager.py +++ b/openlp/core/lib/settingsmanager.py @@ -37,26 +37,9 @@ from openlp.core.utils import AppLocation class SettingsManager(object): """ - Class to control the initial settings for the UI and provide helper - functions for the loading and saving of application settings. + Class to provide helper functions for the loading and saving of application + settings. """ - def __init__(self, screen): - self.screen = screen.current - self.width = self.screen[u'size'].width() - self.height = self.screen[u'size'].height() - self.mainwindow_height = self.height * 0.8 - mainwindow_docbars = self.width / 5 - self.mainwindow_left = 0 - self.mainwindow_right = 0 - if mainwindow_docbars > 300: - self.mainwindow_left = 300 - self.mainwindow_right = 300 - else: - self.mainwindow_left = mainwindow_docbars - self.mainwindow_right = mainwindow_docbars - self.slidecontroller = (self.width - ( - self.mainwindow_left + self.mainwindow_right) - 100) / 2 - self.slidecontroller_image = self.slidecontroller - 50 @staticmethod def get_last_dir(section, num=None): diff --git a/openlp/core/lib/settingstab.py b/openlp/core/lib/settingstab.py index e1396d984..53fd37ed9 100644 --- a/openlp/core/lib/settingstab.py +++ b/openlp/core/lib/settingstab.py @@ -50,7 +50,6 @@ class SettingsTab(QtGui.QWidget): self.setupUi() self.retranslateUi() self.initialise() - self.preLoad() self.load() def setupUi(self): @@ -86,12 +85,6 @@ class SettingsTab(QtGui.QWidget): left_width = max(left_width, self.leftColumn.minimumSizeHint().width()) self.leftColumn.setFixedWidth(left_width) - def preLoad(self): - """ - Setup the tab's interface. - """ - pass - def retranslateUi(self): """ Setup the interface translation strings. @@ -118,9 +111,9 @@ class SettingsTab(QtGui.QWidget): def cancel(self): """ - Reset any settings + Reset any settings if cancel pressed """ - pass + self.load() def postSetUp(self, postUpdate=False): """ diff --git a/openlp/core/lib/ui.py b/openlp/core/lib/ui.py index e8be32a92..311c579ca 100644 --- a/openlp/core/lib/ui.py +++ b/openlp/core/lib/ui.py @@ -329,9 +329,9 @@ def shortcut_action(parent, name, shortcuts, function, icon=None, checked=None, return action def context_menu_action(base, icon, text, slot, shortcuts=None, category=None, - context=QtCore.Qt.WindowShortcut): + context=QtCore.Qt.WidgetShortcut): """ - Utility method to help build context menus for plugins + Utility method to help build context menus. ``base`` The parent menu to add this menu item to @@ -350,7 +350,7 @@ def context_menu_action(base, icon, text, slot, shortcuts=None, category=None, ``category`` The category the shortcut should be listed in the shortcut dialog. If - left to None, then the action will be hidden in the shortcut dialog. + left to ``None``, then the action will be hidden in the shortcut dialog. ``context`` The context the shortcut is valid. @@ -364,11 +364,12 @@ def context_menu_action(base, icon, text, slot, shortcuts=None, category=None, action.setShortcutContext(context) action_list = ActionList.get_instance() action_list.add_action(action) + base.addAction(action) return action def context_menu(base, icon, text): """ - Utility method to help build context menus for plugins + Utility method to help build context menus. ``base`` The parent object to add this menu to @@ -392,6 +393,7 @@ def context_menu_separator(base): """ action = QtGui.QAction(u'', base) action.setSeparator(True) + base.addAction(action) return action def add_widget_completer(cache, widget): diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py index c6ac9d35a..db77dd2d3 100644 --- a/openlp/core/ui/__init__.py +++ b/openlp/core/ui/__init__.py @@ -56,10 +56,10 @@ from firsttimelanguageform import FirstTimeLanguageForm from themeform import ThemeForm from filerenameform import FileRenameForm from starttimeform import StartTimeForm +from screen import ScreenList from maindisplay import MainDisplay, Display from servicenoteform import ServiceNoteForm from serviceitemeditform import ServiceItemEditForm -from screen import ScreenList from slidecontroller import SlideController from splashscreen import SplashScreen from generaltab import GeneralTab diff --git a/openlp/core/ui/displaytagform.py b/openlp/core/ui/displaytagform.py index b8169b9be..c439fc116 100644 --- a/openlp/core/ui/displaytagform.py +++ b/openlp/core/ui/displaytagform.py @@ -47,7 +47,7 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog): """ QtGui.QDialog.__init__(self, parent) self.setupUi(self) - self.preLoad() + self._loadDisplayTags() QtCore.QObject.connect(self.tagTableWidget, QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onRowSelected) QtCore.QObject.connect(self.defaultPushButton, @@ -66,12 +66,12 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog): Load Display and set field state. """ # Create initial copy from master - self.preLoad() + self._loadDisplayTags() self._resetTable() self.selected = -1 return QtGui.QDialog.exec_(self) - def preLoad(self): + def _loadDisplayTags(self): """ Load the Tags from store so can be used in the system or used to update the display. If Cancel was selected this is needed to reset the diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py index 6931c3e7f..75cb8fa98 100644 --- a/openlp/core/ui/generaltab.py +++ b/openlp/core/ui/generaltab.py @@ -29,6 +29,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import SettingsTab, Receiver, translate from openlp.core.lib.ui import UiStrings +from openlp.core.ui import ScreenList log = logging.getLogger(__name__) @@ -36,33 +37,15 @@ class GeneralTab(SettingsTab): """ GeneralTab is the general settings tab in the settings dialog. """ - def __init__(self, parent, screens): + def __init__(self, parent): """ Initialise the general settings tab """ - self.screens = screens - self.monitorNumber = 0 - # Set to True to allow PostSetup to work on application start up - self.overrideChanged = True + self.screens = ScreenList.get_instance() self.icon_path = u':/icon/openlp-logo-16x16.png' generalTranslated = translate('GeneralTab', 'General') SettingsTab.__init__(self, parent, u'General', generalTranslated) - def preLoad(self): - """ - Set up the display screen and set correct screen values. - If not set before default to last screen. - """ - settings = QtCore.QSettings() - settings.beginGroup(self.settingsSection) - self.monitorNumber = settings.value(u'monitor', - QtCore.QVariant(self.screens.display_count - 1)).toInt()[0] - self.screens.set_current_display(self.monitorNumber) - self.screens.monitor_number = self.monitorNumber - self.screens.display = settings.value( - u'display on monitor', QtCore.QVariant(True)).toBool() - settings.endGroup() - def setupUi(self): """ Create the user interface for the general settings tab @@ -118,6 +101,7 @@ class GeneralTab(SettingsTab): self.timeoutLabel.setObjectName(u'timeoutLabel') self.timeoutSpinBox = QtGui.QSpinBox(self.settingsGroupBox) self.timeoutSpinBox.setObjectName(u'timeoutSpinBox') + self.timeoutSpinBox.setRange(1, 180) self.settingsLayout.addRow(self.timeoutLabel, self.timeoutSpinBox) self.leftLayout.addWidget(self.settingsGroupBox) self.leftLayout.addStretch() @@ -158,14 +142,14 @@ class GeneralTab(SettingsTab): self.displayLayout.addWidget(self.customXLabel, 3, 0) self.customXValueEdit = QtGui.QSpinBox(self.displayGroupBox) self.customXValueEdit.setObjectName(u'customXValueEdit') - self.customXValueEdit.setMaximum(9999) + self.customXValueEdit.setRange(-9999, 9999) self.displayLayout.addWidget(self.customXValueEdit, 4, 0) self.customYLabel = QtGui.QLabel(self.displayGroupBox) self.customYLabel.setObjectName(u'customYLabel') self.displayLayout.addWidget(self.customYLabel, 3, 1) self.customYValueEdit = QtGui.QSpinBox(self.displayGroupBox) self.customYValueEdit.setObjectName(u'customYValueEdit') - self.customYValueEdit.setMaximum(9999) + self.customYValueEdit.setRange(-9999, 9999) self.displayLayout.addWidget(self.customYValueEdit, 4, 1) self.customWidthLabel = QtGui.QLabel(self.displayGroupBox) self.customWidthLabel.setObjectName(u'customWidthLabel') @@ -187,13 +171,15 @@ class GeneralTab(SettingsTab): QtCore.QObject.connect(self.overrideCheckBox, QtCore.SIGNAL(u'toggled(bool)'), self.onOverrideCheckBoxToggled) QtCore.QObject.connect(self.customHeightValueEdit, - QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayPositionChanged) + QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayChanged) QtCore.QObject.connect(self.customWidthValueEdit, - QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayPositionChanged) + QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayChanged) QtCore.QObject.connect(self.customYValueEdit, - QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayPositionChanged) + QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayChanged) QtCore.QObject.connect(self.customXValueEdit, - QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayPositionChanged) + QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayChanged) + QtCore.QObject.connect(self.monitorComboBox, + QtCore.SIGNAL(u'currentIndexChanged(int)'), self.onDisplayChanged) # Reload the tab, as the screen resolution/count may have changed. QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_screen_changed'), self.load) @@ -203,7 +189,6 @@ class GeneralTab(SettingsTab): self.passwordLabel.setVisible(False) self.passwordEdit.setVisible(False) - def retranslateUi(self): """ Translate the general settings tab to the currently selected language @@ -261,6 +246,9 @@ class GeneralTab(SettingsTab): settings.beginGroup(self.settingsSection) self.monitorComboBox.clear() self.monitorComboBox.addItems(self.screens.get_screen_list()) + monitorNumber = settings.value(u'monitor', + QtCore.QVariant(self.screens.display_count - 1)).toInt()[0] + self.monitorComboBox.setCurrentIndex(monitorNumber) self.numberEdit.setText(unicode(settings.value( u'ccli number', QtCore.QVariant(u'')).toString())) self.usernameEdit.setText(unicode(settings.value( @@ -271,7 +259,6 @@ class GeneralTab(SettingsTab): QtCore.QVariant(False)).toBool()) self.autoUnblankCheckBox.setChecked(settings.value(u'auto unblank', QtCore.QVariant(False)).toBool()) - self.monitorComboBox.setCurrentIndex(self.monitorNumber) self.displayOnMonitorCheck.setChecked(self.screens.display) self.warningCheckBox.setChecked(settings.value(u'blank warning', QtCore.QVariant(False)).toBool()) @@ -300,15 +287,16 @@ class GeneralTab(SettingsTab): self.customYValueEdit.setEnabled(self.overrideCheckBox.isChecked()) self.customHeightValueEdit.setEnabled(self.overrideCheckBox.isChecked()) self.customWidthValueEdit.setEnabled(self.overrideCheckBox.isChecked()) + self.display_changed = False def save(self): """ Save the settings from the form """ - self.monitorNumber = self.monitorComboBox.currentIndex() settings = QtCore.QSettings() settings.beginGroup(self.settingsSection) - settings.setValue(u'monitor', QtCore.QVariant(self.monitorNumber)) + settings.setValue(u'monitor', + QtCore.QVariant(self.monitorComboBox.currentIndex())) settings.setValue(u'display on monitor', QtCore.QVariant(self.displayOnMonitorCheck.isChecked())) settings.setValue(u'blank warning', @@ -344,15 +332,8 @@ class GeneralTab(SettingsTab): settings.setValue(u'override position', QtCore.QVariant(self.overrideCheckBox.isChecked())) settings.endGroup() - self.screens.display = self.displayOnMonitorCheck.isChecked() - # Monitor Number has changed. - postUpdate = False - if self.screens.monitor_number != self.monitorNumber: - self.screens.monitor_number = self.monitorNumber - self.screens.set_current_display(self.monitorNumber) - postUpdate = True # On save update the screens as well - self.postSetUp(postUpdate) + self.postSetUp(True) def postSetUp(self, postUpdate=False): """ @@ -361,7 +342,11 @@ class GeneralTab(SettingsTab): """ Receiver.send_message(u'slidecontroller_live_spin_delay', self.timeoutSpinBox.value()) - # Reset screens after initial definition + # Do not continue on start up. + if not postUpdate: + return + self.screens.set_current_display(self.monitorComboBox.currentIndex()) + self.screens.display = self.displayOnMonitorCheck.isChecked() self.screens.override[u'size'] = QtCore.QRect( self.customXValueEdit.value(), self.customYValueEdit.value(), @@ -371,10 +356,9 @@ class GeneralTab(SettingsTab): self.screens.set_override_display() else: self.screens.reset_current_display() - # Order is important so be careful if you change - if self.overrideChanged or postUpdate: + if self.display_changed: Receiver.send_message(u'config_screen_changed') - self.overrideChanged = False + self.display_changed = False def onOverrideCheckBoxToggled(self, checked): """ @@ -387,10 +371,10 @@ class GeneralTab(SettingsTab): self.customYValueEdit.setEnabled(checked) self.customHeightValueEdit.setEnabled(checked) self.customWidthValueEdit.setEnabled(checked) - self.overrideChanged = True + self.display_changed = True - def onDisplayPositionChanged(self): + def onDisplayChanged(self): """ Called when the width, height, x position or y position has changed. """ - self.overrideChanged = True + self.display_changed = True diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 1e27cb97d..15780b6c5 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -36,25 +36,13 @@ from PyQt4.phonon import Phonon from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, \ translate -from openlp.core.ui import HideMode +from openlp.core.ui import HideMode, ScreenList log = logging.getLogger(__name__) #http://www.steveheffernan.com/html5-video-player/demo-video-player.html #http://html5demos.com/two-videos -class DisplayWidget(QtGui.QGraphicsView): - """ - Customised version of QTableWidget which can respond to keyboard - events. - """ - log.info(u'Display Widget loaded') - - def __init__(self, live, parent=None): - QtGui.QGraphicsView.__init__(self) - self.parent = parent - self.live = live - class Display(QtGui.QFrame): """ This is the display screen for preview Widgets. @@ -80,15 +68,16 @@ class Display(QtGui.QFrame): None, None, None)) self.webView.hide() -class MainDisplay(DisplayWidget): +class MainDisplay(QtGui.QGraphicsView): """ This is the display screen. """ - def __init__(self, parent, screens, live): - DisplayWidget.__init__(self, live, parent=None) + def __init__(self, parent, image_manager, live): + QtGui.QGraphicsView.__init__(self) self.parent = parent - self.screens = screens self.isLive = live + self.image_manager = image_manager + self.screens = ScreenList.get_instance() self.alertTab = None self.hideMode = None self.videoHide = False @@ -115,13 +104,11 @@ class MainDisplay(DisplayWidget): """ Set up and build the output screen """ - log.debug(u'Start setup for monitor %s (live = %s)' % - (self.screens.monitor_number, self.isLive)) - self.phononActive = False + log.debug(u'Start MainDisplay setup (live = %s)' % self.isLive) self.screen = self.screens.current self.setVisible(False) self.setGeometry(self.screen[u'size']) - log.debug(u'Setup webView for monitor %s' % self.screens.monitor_number) + log.debug(u'Setup webView') self.webView = QtWebKit.QWebView(self) self.webView.setGeometry(0, 0, self.screen[u'size'].width(), self.screen[u'size'].height()) @@ -139,8 +126,8 @@ class MainDisplay(DisplayWidget): if self.isLive: # Build the initial frame. self.black = QtGui.QImage( - self.screens.current[u'size'].width(), - self.screens.current[u'size'].height(), + self.screen[u'size'].width(), + self.screen[u'size'].height(), QtGui.QImage.Format_ARGB32_Premultiplied) painter_image = QtGui.QPainter() painter_image.begin(self.black) @@ -157,17 +144,16 @@ class MainDisplay(DisplayWidget): background_color = QtCore.Qt.white splash_image = QtGui.QImage(image_file) self.initialFrame = QtGui.QImage( - self.screens.current[u'size'].width(), - self.screens.current[u'size'].height(), + self.screen[u'size'].width(), + self.screen[u'size'].height(), QtGui.QImage.Format_ARGB32_Premultiplied) painter_image = QtGui.QPainter() painter_image.begin(self.initialFrame) painter_image.fillRect(self.initialFrame.rect(), background_color) painter_image.drawImage( - (self.screens.current[u'size'].width() - - splash_image.width()) / 2, - (self.screens.current[u'size'].height() - - splash_image.height()) / 2, splash_image) + (self.screen[u'size'].width() - splash_image.width()) / 2, + (self.screen[u'size'].height() - splash_image.height()) / 2, + splash_image) serviceItem = ServiceItem() serviceItem.bg_image_bytes = image_to_byte(self.initialFrame) self.webView.setHtml(build_html(serviceItem, self.screen, @@ -179,8 +165,7 @@ class MainDisplay(DisplayWidget): self.primary = False else: self.primary = True - log.debug( - u'Finished setup for monitor %s' % self.screens.monitor_number) + log.debug(u'Finished MainDisplay setup') def text(self, slide): """ @@ -235,7 +220,7 @@ class MainDisplay(DisplayWidget): """ API for replacement backgrounds so Images are added directly to cache """ - self.imageManager.add_image(name, path) + self.image_manager.add_image(name, path) self.image(name) if hasattr(self, u'serviceItem'): self.override[u'image'] = name @@ -250,7 +235,7 @@ class MainDisplay(DisplayWidget): The name of the image to be displayed """ log.debug(u'image to display') - image = self.imageManager.get_image_bytes(name) + image = self.image_manager.get_image_bytes(name) self.resetVideo() self.displayImage(image) return self.preview() @@ -317,7 +302,7 @@ class MainDisplay(DisplayWidget): self.hideDisplay(self.hideMode) else: # Single screen active - if self.screens.monitor_number == 0: + if self.screens.display_count == 1: # Only make visible if setting enabled if QtCore.QSettings().value(u'general/display on monitor', QtCore.QVariant(True)).toBool(): @@ -355,13 +340,13 @@ class MainDisplay(DisplayWidget): self.override = {} else: # replace the background - background = self.imageManager. \ + background = self.image_manager. \ get_image_bytes(self.override[u'image']) if self.serviceItem.themedata.background_filename: - self.serviceItem.bg_image_bytes = self.imageManager. \ + self.serviceItem.bg_image_bytes = self.image_manager. \ get_image_bytes(self.serviceItem.themedata.theme_name) if image: - image_bytes = self.imageManager.get_image_bytes(image) + image_bytes = self.image_manager.get_image_bytes(image) else: image_bytes = None html = build_html(self.serviceItem, self.screen, self.alertTab, diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index a115d8905..09e2ec9e7 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -31,7 +31,7 @@ from tempfile import gettempdir from PyQt4 import QtCore, QtGui from openlp.core.lib import Renderer, build_icon, OpenLPDockWidget, \ - SettingsManager, PluginManager, Receiver, translate + PluginManager, Receiver, translate, ImageManager from openlp.core.lib.ui import UiStrings, base_action, checkable_action, \ icon_action, shortcut_action from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \ @@ -69,8 +69,6 @@ class Ui_MainWindow(object): Set up the user interface """ mainWindow.setObjectName(u'MainWindow') - mainWindow.resize(self.settingsmanager.width, - self.settingsmanager.height) mainWindow.setWindowIcon(build_icon(u':/icon/openlp-logo-64x64.png')) mainWindow.setDockNestingEnabled(True) # Set up the main container, which contains all the other form widgets. @@ -86,10 +84,8 @@ class Ui_MainWindow(object): self.controlSplitter.setObjectName(u'controlSplitter') self.mainContentLayout.addWidget(self.controlSplitter) # Create slide controllers - self.previewController = SlideController(self, self.settingsmanager, - self.screens) - self.liveController = SlideController(self, self.settingsmanager, - self.screens, True) + self.previewController = SlideController(self) + self.liveController = SlideController(self, True) previewVisible = QtCore.QSettings().value( u'user interface/preview panel', QtCore.QVariant(True)).toBool() self.previewController.panel.setVisible(previewVisible) @@ -137,8 +133,6 @@ class Ui_MainWindow(object): self.mediaManagerDock = OpenLPDockWidget(mainWindow, u'mediaManagerDock', u':/system/system_mediamanager.png') self.mediaManagerDock.setStyleSheet(MEDIA_MANAGER_STYLE) - self.mediaManagerDock.setMinimumWidth( - self.settingsmanager.mainwindow_left) # Create the media toolbox self.MediaToolBox = QtGui.QToolBox(self.mediaManagerDock) self.MediaToolBox.setObjectName(u'MediaToolBox') @@ -148,8 +142,6 @@ class Ui_MainWindow(object): # Create the service manager self.serviceManagerDock = OpenLPDockWidget(mainWindow, u'serviceManagerDock', u':/system/system_servicemanager.png') - self.serviceManagerDock.setMinimumWidth( - self.settingsmanager.mainwindow_right) self.ServiceManagerContents = ServiceManager(mainWindow, self.serviceManagerDock) self.serviceManagerDock.setWidget(self.ServiceManagerContents) @@ -158,8 +150,6 @@ class Ui_MainWindow(object): # Create the theme manager self.themeManagerDock = OpenLPDockWidget(mainWindow, u'themeManagerDock', u':/system/system_thememanager.png') - self.themeManagerDock.setMinimumWidth( - self.settingsmanager.mainwindow_right) self.themeManagerContents = ThemeManager(mainWindow, self.themeManagerDock) self.themeManagerContents.setObjectName(u'themeManagerContents') @@ -461,13 +451,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ log.info(u'MainWindow loaded') - def __init__(self, screens, clipboard, arguments): + def __init__(self, clipboard, arguments): """ This constructor sets up the interface, the various managers, and the plugins. """ QtGui.QMainWindow.__init__(self) - self.screens = screens self.clipboard = clipboard self.arguments = arguments # Set up settings sections for the main application @@ -477,9 +466,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.serviceSettingsSection = u'servicemanager' self.songsSettingsSection = u'songs' self.serviceNotSaved = False - self.settingsmanager = SettingsManager(screens) self.aboutForm = AboutForm(self) - self.settingsForm = SettingsForm(self.screens, self, self) + self.settingsForm = SettingsForm(self, self) self.displayTagForm = DisplayTagForm(self) self.shortcutForm = ShortcutListForm(self) self.recentFiles = QtCore.QStringList() @@ -487,6 +475,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): pluginpath = AppLocation.get_directory(AppLocation.PluginsDir) self.pluginManager = PluginManager(pluginpath) self.pluginHelpers = {} + self.image_manager = ImageManager() # Set up the interface self.setupUi(self) # Load settings after setupUi so default UI sizes are overwritten @@ -552,8 +541,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): # warning cyclic dependency # renderer needs to call ThemeManager and # ThemeManager needs to call Renderer - self.renderer = Renderer( - self.themeManagerContents, self.screens) + self.renderer = Renderer(self.image_manager, self.themeManagerContents) # Define the media Dock Manager self.mediaDockManager = MediaDockManager(self.MediaToolBox) log.info(u'Load Plugins') @@ -585,6 +573,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): # Call the initialise method to setup plugins. log.info(u'initialise plugins') self.pluginManager.initialise_plugins() + # Create the displays as all necessary components are loaded. + self.previewController.screenSizeChanged() + self.liveController.screenSizeChanged() log.info(u'Load data from Settings') if QtCore.QSettings().value(u'advanced/save current plugin', QtCore.QVariant(False)).toBool(): @@ -681,12 +672,15 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): 'The Main Display has been blanked out')) def onErrorMessage(self, data): + Receiver.send_message(u'close_splash') QtGui.QMessageBox.critical(self, data[u'title'], data[u'message']) def onWarningMessage(self, data): + Receiver.send_message(u'close_splash') QtGui.QMessageBox.warning(self, data[u'title'], data[u'message']) def onInformationMessage(self, data): + Receiver.send_message(u'close_splash') QtGui.QMessageBox.information(self, data[u'title'], data[u'message']) def onHelpWebSiteClicked(self): @@ -788,7 +782,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): their locations """ log.debug(u'screenChanged') + self.image_manager.update_display() self.renderer.update_display() + self.liveController.screenSizeChanged() + self.previewController.screenSizeChanged() self.setFocus() self.activateWindow() diff --git a/openlp/core/ui/screen.py b/openlp/core/ui/screen.py index 15dbd9883..2186a221e 100644 --- a/openlp/core/ui/screen.py +++ b/openlp/core/ui/screen.py @@ -38,9 +38,16 @@ log = logging.getLogger(__name__) class ScreenList(object): """ - Wrapper to handle the parameters of the display screen + Wrapper to handle the parameters of the display screen. + + To get access to the screen list call ``ScreenList.get_instance()``. """ log.info(u'Screen loaded') + instance = None + + @staticmethod + def get_instance(): + return ScreenList.instance def __init__(self, desktop): """ @@ -49,17 +56,15 @@ class ScreenList(object): ``desktop`` A ``QDesktopWidget`` object. """ + ScreenList.instance = self self.desktop = desktop self.preview = None self.current = None self.override = None self.screen_list = [] self.display_count = 0 - # actual display number - self.current_display = 0 - # save config display number - self.monitor_number = 0 self.screen_count_changed() + self._load_screen_settings() QtCore.QObject.connect(desktop, QtCore.SIGNAL(u'resized(int)'), self.screen_resolution_changed) QtCore.QObject.connect(desktop, @@ -150,6 +155,7 @@ class ScreenList(object): screen[u'number'], screen[u'size']) if screen[u'primary']: self.current = screen + self.override = copy.deepcopy(self.current) self.screen_list.append(screen) self.display_count += 1 @@ -189,13 +195,10 @@ class ScreenList(object): log.debug(u'set_current_display %s', number) if number + 1 > self.display_count: self.current = self.screen_list[0] - self.override = copy.deepcopy(self.current) - self.current_display = 0 else: self.current = self.screen_list[number] - self.override = copy.deepcopy(self.current) self.preview = copy.deepcopy(self.current) - self.current_display = number + self.override = copy.deepcopy(self.current) if self.display_count == 1: self.preview = self.screen_list[0] @@ -214,4 +217,31 @@ class ScreenList(object): use the correct screen attributes. """ log.debug(u'reset_current_display') - self.set_current_display(self.current_display) + self.set_current_display(self.current[u'number']) + + def _load_screen_settings(self): + """ + Loads the screen size and the monitor number from the settings. + """ + settings = QtCore.QSettings() + settings.beginGroup(u'general') + self.set_current_display(settings.value(u'monitor', + QtCore.QVariant(self.display_count - 1)).toInt()[0]) + self.display = settings.value( + u'display on monitor', QtCore.QVariant(True)).toBool() + override_display = settings.value( + u'override position', QtCore.QVariant(False)).toBool() + x = settings.value(u'x position', + QtCore.QVariant(self.current[u'size'].x())).toInt()[0] + y = settings.value(u'y position', + QtCore.QVariant(self.current[u'size'].y())).toInt()[0] + width = settings.value(u'width', + QtCore.QVariant(self.current[u'size'].width())).toInt()[0] + height = settings.value(u'height', + QtCore.QVariant(self.current[u'size'].height())).toInt()[0] + self.override[u'size'] = QtCore.QRect(x, y, width, height) + settings.endGroup() + if override_display: + self.set_override_display() + else: + self.reset_current_display() diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index b5e8bbc54..358877cc7 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -36,7 +36,7 @@ from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, \ ItemCapabilities, SettingsManager, translate from openlp.core.lib.theme import ThemeLevel from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ - context_menu_action, find_and_set_in_combo_box + context_menu_action, context_menu_separator, find_and_set_in_combo_box from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm from openlp.core.ui.printserviceform import PrintServiceForm from openlp.core.utils import AppLocation, delete_file, file_is_unicode, \ @@ -73,6 +73,9 @@ class ServiceManagerList(QtGui.QTreeWidget): if event.buttons() != QtCore.Qt.LeftButton: event.ignore() return + if not self.selectedItems(): + event.ignore() + return drag = QtGui.QDrag(self) mimeData = QtCore.QMimeData() drag.setMimeData(mimeData) @@ -298,31 +301,34 @@ class ServiceManager(QtGui.QWidget): self.addToAction.setIcon(build_icon(u':/general/general_edit.png')) # build the context menu self.menu = QtGui.QMenu() - self.editAction = self.menu.addAction( - translate('OpenLP.ServiceManager', '&Edit Item')) - self.editAction.setIcon(build_icon(u':/general/general_edit.png')) - self.maintainAction = self.menu.addAction( - translate('OpenLP.ServiceManager', '&Reorder Item')) - self.maintainAction.setIcon(build_icon(u':/general/general_edit.png')) - self.notesAction = self.menu.addAction( - translate('OpenLP.ServiceManager', '&Notes')) - self.notesAction.setIcon(build_icon(u':/services/service_notes.png')) - self.timeAction = self.menu.addAction( - translate('OpenLP.ServiceManager', '&Start Time')) - self.timeAction.setIcon(build_icon(u':/media/media_time.png')) - self.deleteAction = self.menu.addAction( - translate('OpenLP.ServiceManager', '&Delete From Service')) - self.deleteAction.setIcon(build_icon(u':/general/general_delete.png')) - self.sep1 = self.menu.addAction(u'') - self.sep1.setSeparator(True) - self.previewAction = self.menu.addAction( - translate('OpenLP.ServiceManager', 'Show &Preview')) - self.previewAction.setIcon(build_icon(u':/general/general_preview.png')) - self.liveAction = self.menu.addAction( - translate('OpenLP.ServiceManager', 'Show &Live')) - self.liveAction.setIcon(build_icon(u':/general/general_live.png')) - self.sep2 = self.menu.addAction(u'') - self.sep2.setSeparator(True) + self.editAction = context_menu_action( + self.menu, u':/general/general_edit.png', + translate('OpenLP.ServiceManager', '&Edit Item'), self.remoteEdit) + self.maintainAction = context_menu_action( + self.menu, u':/general/general_edit.png', + translate('OpenLP.ServiceManager', '&Reorder Item'), + self.onServiceItemEditForm) + self.notesAction = context_menu_action( + self.menu, u':/services/service_notes.png', + translate('OpenLP.ServiceManager', '&Notes'), + self.onServiceItemNoteForm) + self.timeAction = context_menu_action( + self.menu, u':/media/media_time.png', + translate('OpenLP.ServiceManager', '&Start Time'), + self.onStartTimeForm) + self.deleteAction = context_menu_action( + self.menu, u':/general/general_delete.png', + translate('OpenLP.ServiceManager', '&Delete From Service'), + self.onDeleteFromService) + context_menu_separator(self.menu) + self.previewAction = context_menu_action( + self.menu, u':/general/general_preview.png', + translate('OpenLP.ServiceManager', 'Show &Preview'), + self.makePreview) + self.liveAction = context_menu_action( + self.menu, u':/general/general_live.png', + translate('OpenLP.ServiceManager', 'Show &Live'), self.makeLive) + context_menu_separator(self.menu) self.themeMenu = QtGui.QMenu( translate('OpenLP.ServiceManager', '&Change Item Theme')) self.menu.addMenu(self.themeMenu) @@ -672,20 +678,6 @@ class ServiceManager(QtGui.QWidget): if serviceItem[u'service_item'].is_text(): self.themeMenu.menuAction().setVisible(True) action = self.menu.exec_(self.serviceManagerList.mapToGlobal(point)) - if action == self.editAction: - self.remoteEdit() - elif action == self.maintainAction: - self.onServiceItemEditForm() - elif action == self.deleteAction: - self.onDeleteFromService() - elif action == self.notesAction: - self.onServiceItemNoteForm() - elif action == self.timeAction: - self.onStartTimeForm() - elif action == self.previewAction: - self.makePreview() - elif action == self.liveAction: - self.makeLive() def onServiceItemNoteForm(self): item = self.findServiceItem()[0] @@ -837,7 +829,7 @@ class ServiceManager(QtGui.QWidget): correct state. """ pos = item.data(0, QtCore.Qt.UserRole).toInt()[0] - self.serviceItems[pos -1 ][u'expanded'] = False + self.serviceItems[pos - 1][u'expanded'] = False def onExpandAll(self): """ @@ -1285,9 +1277,8 @@ class ServiceManager(QtGui.QWidget): self.themeComboBox.addItem(u'') for theme in theme_list: self.themeComboBox.addItem(theme) - action = context_menu_action(self.serviceManagerList, None, theme, - self.onThemeChangeAction, context=QtCore.Qt.WidgetShortcut) - self.themeMenu.addAction(action) + context_menu_action(self.themeMenu, None, theme, + self.onThemeChangeAction) find_and_set_in_combo_box(self.themeComboBox, self.service_theme) self.mainwindow.renderer.set_service_theme(self.service_theme) self.regenerateServiceItems() diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py index 1967412f5..265a03f48 100644 --- a/openlp/core/ui/settingsform.py +++ b/openlp/core/ui/settingsform.py @@ -40,14 +40,14 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): """ Provide the form to manipulate the settings for OpenLP """ - def __init__(self, screens, mainWindow, parent=None): + def __init__(self, mainWindow, parent=None): """ Initialise the settings form """ QtGui.QDialog.__init__(self, parent) self.setupUi(self) # General tab - self.generalTab = GeneralTab(self, screens) + self.generalTab = GeneralTab(self) # Themes tab self.themesTab = ThemesTab(self, mainWindow) # Advanced tab diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index bed7a7ed2..a4242c0ff 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -33,7 +33,7 @@ from PyQt4.phonon import Phonon from openlp.core.lib import OpenLPToolbar, Receiver, resize_image, \ ItemCapabilities, translate from openlp.core.lib.ui import UiStrings, shortcut_action -from openlp.core.ui import HideMode, MainDisplay, Display +from openlp.core.ui import HideMode, MainDisplay, Display, ScreenList from openlp.core.utils.actions import ActionList, CategoryOrder log = logging.getLogger(__name__) @@ -53,18 +53,18 @@ class SlideController(QtGui.QWidget): SlideController is the slide controller widget. This widget is what the user uses to control the displaying of verses/slides/etc on the screen. """ - def __init__(self, parent, settingsmanager, screens, isLive=False): + def __init__(self, parent, isLive=False): """ Set up the Slide Controller. """ QtGui.QWidget.__init__(self, parent) - self.settingsmanager = settingsmanager self.isLive = isLive self.parent = parent - self.screens = screens + self.screens = ScreenList.get_instance() self.ratio = float(self.screens.current[u'size'].width()) / \ float(self.screens.current[u'size'].height()) - self.display = MainDisplay(self, screens, isLive) + self.display = MainDisplay(self, self.screens, isLive) + self.image_manager = self.parent.image_manager self.loopList = [ u'Start Loop', u'Loop Separator', @@ -200,8 +200,7 @@ class SlideController(QtGui.QWidget): 'Start/Stop continuous loop')) self.addAction(self.toogleLoop) self.delaySpinBox = QtGui.QSpinBox() - self.delaySpinBox.setMinimum(1) - self.delaySpinBox.setMaximum(180) + self.delaySpinBox.setRange(1, 180) self.toolbar.addToolbarWidget(u'Image SpinBox', self.delaySpinBox) self.delaySpinBox.setSuffix(UiStrings().Seconds) self.delaySpinBox.setToolTip(translate('OpenLP.SlideController', @@ -288,9 +287,6 @@ class SlideController(QtGui.QWidget): sizePolicy.setHeightForWidth( self.slidePreview.sizePolicy().hasHeightForWidth()) self.slidePreview.setSizePolicy(sizePolicy) - self.slidePreview.setFixedSize( - QtCore.QSize(self.settingsmanager.slidecontroller_image, - self.settingsmanager.slidecontroller_image / self.ratio)) self.slidePreview.setFrameShape(QtGui.QFrame.Box) self.slidePreview.setFrameShadow(QtGui.QFrame.Plain) self.slidePreview.setLineWidth(1) @@ -322,7 +318,6 @@ class SlideController(QtGui.QWidget): if self.isLive: self.setLiveHotkeys(self) self.__addActionsToWidget(self.previewListWidget) - self.__addActionsToWidget(self.display) else: self.setPreviewHotkeys() self.previewListWidget.addActions( @@ -365,8 +360,6 @@ class SlideController(QtGui.QWidget): QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'slidecontroller_%s_text_request' % self.typePrefix), self.onTextRequest) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'config_screen_changed'), self.screenSizeChanged) def setPreviewHotkeys(self, parent=None): self.previousItem.setObjectName(u'previousItemPreview') @@ -418,8 +411,7 @@ class SlideController(QtGui.QWidget): screen previews. """ # rebuild display as screen size changed - self.display = MainDisplay(self, self.screens, self.isLive) - self.display.imageManager = self.parent.renderer.image_manager + self.display = MainDisplay(self, self.image_manager, self.isLive) self.display.alertTab = self.alertTab self.display.setup() if self.isLive: @@ -614,7 +606,7 @@ class SlideController(QtGui.QWidget): if frame[u'verseTag']: # These tags are already translated. verse_def = frame[u'verseTag'] - verse_def = u'%s%s' % (verse_def[0].upper(), verse_def[1:]) + verse_def = u'%s%s' % (verse_def[0], verse_def[1:]) two_line_def = u'%s\n%s' % (verse_def[0], verse_def[1:]) row = two_line_def if self.isLive: @@ -637,10 +629,8 @@ class SlideController(QtGui.QWidget): # If current slide set background to image if framenumber == slideno: self.serviceItem.bg_image_bytes = \ - self.parent.renderer.image_manager. \ - get_image_bytes(frame[u'title']) - image = self.parent.renderer.image_manager. \ - get_image(frame[u'title']) + self.image_manager.get_image_bytes(frame[u'title']) + image = self.image_manager.get_image(frame[u'title']) label.setPixmap(QtGui.QPixmap.fromImage(image)) self.previewListWidget.setCellWidget(framenumber, 0, label) slideHeight = width * self.parent.renderer.screen_ratio diff --git a/openlp/core/ui/splashscreen.py b/openlp/core/ui/splashscreen.py index 84aa1d7df..2bb516d00 100644 --- a/openlp/core/ui/splashscreen.py +++ b/openlp/core/ui/splashscreen.py @@ -23,6 +23,7 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +from openlp.core.lib import Receiver from PyQt4 import QtCore, QtGui @@ -30,6 +31,8 @@ class SplashScreen(QtGui.QSplashScreen): def __init__(self): QtGui.QSplashScreen.__init__(self) self.setupUi() + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'close_splash'), self.close) def setupUi(self): self.setObjectName(u'splash_screen') diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 0cfa9c60a..979ebb01d 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -118,4 +118,5 @@ class AlertsPlugin(Plugin): ## Name for MediaDockManager, SettingsManager ## self.textStrings[StringContent.VisibleName] = { u'title': translate('AlertsPlugin', 'Alerts', 'container title') - } \ No newline at end of file + } + diff --git a/openlp/plugins/alerts/lib/alertstab.py b/openlp/plugins/alerts/lib/alertstab.py index 2ec2be24b..8c8778f9f 100644 --- a/openlp/plugins/alerts/lib/alertstab.py +++ b/openlp/plugins/alerts/lib/alertstab.py @@ -191,4 +191,5 @@ class AlertsTab(SettingsTab): font.setPointSize(self.font_size) self.FontPreview.setFont(font) self.FontPreview.setStyleSheet(u'background-color: %s; color: %s' % - (self.bg_color, self.font_color)) \ No newline at end of file + (self.bg_color, self.font_color)) + diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index ec63dc02f..028a2867b 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -401,7 +401,7 @@ class BibleDB(QtCore.QObject, Manager): """ log.debug(u'BibleDB.get_chapter_count("%s")', book) count = self.session.query(Verse.chapter).join(Book)\ - .filter(Book.name==book)\ + .filter(Book.name == book)\ .distinct().count() if not count: return 0 @@ -420,8 +420,8 @@ class BibleDB(QtCore.QObject, Manager): """ log.debug(u'BibleDB.get_verse_count("%s", %s)', book, chapter) count = self.session.query(Verse).join(Book)\ - .filter(Book.name==book)\ - .filter(Verse.chapter==chapter)\ + .filter(Book.name == book)\ + .filter(Verse.chapter == chapter)\ .count() if not count: return 0 diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 67469e063..3dfefb3e6 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -285,7 +285,7 @@ class BibleManager(object): Does a verse search for the given bible and text. ``bible`` - The bible to seach in (unicode). + The bible to search in (unicode). ``second_bible`` The second bible (unicode). We do not search in this bible. @@ -294,6 +294,15 @@ class BibleManager(object): The text to search for (unicode). """ log.debug(u'BibleManager.verse_search("%s", "%s")', bible, text) + if not bible: + Receiver.send_message(u'openlp_information_message', { + u'title': translate('BiblesPlugin.BibleManager', + 'No Bibles Available'), + u'message': translate('BiblesPlugin.BibleManager', + 'There are no Bibles currently installed. Please use the ' + 'Import Wizard to install one or more Bibles.') + }) + return None # Check if the bible or second_bible is a web bible. webbible = self.db_cache[bible].get_object(BibleMeta, u'download source') diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 461828d9e..0fb3b1eee 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -29,7 +29,7 @@ import logging from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ - translate, check_search_result + translate from openlp.core.lib.searchedit import SearchEdit from openlp.core.lib.ui import UiStrings, add_widget_completer, \ media_item_combo_box, critical_error_message_box, find_and_set_in_combo_box @@ -55,16 +55,51 @@ class BibleMediaItem(MediaManagerItem): def __init__(self, parent, plugin, icon): self.IconPath = u'songs/song' + self.lockIcon = QtGui.QIcon(u':/bibles/bibles_search_lock.png') + self.unlockIcon = QtGui.QIcon(u':/bibles/bibles_search_unlock.png') MediaManagerItem.__init__(self, parent, plugin, icon) # Place to store the search results for both bibles. self.settings = self.parent.settings_tab self.quickPreviewAllowed = True self.search_results = {} self.second_search_results = {} - check_search_result(self.listView, self.search_results) + self.check_search_result() QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'bibles_load_list'), self.reloadBibles) + def __checkSecondBible(self, bible, second_bible): + """ + Check if the first item is a second bible item or not. + """ + bitem = self.listView.item(0) + if not bitem.flags() & QtCore.Qt.ItemIsSelectable: + # The item is the "No Search Results" item. + self.listView.clear() + self.displayResults(bible, second_bible) + return + else: + item_second_bible = self._decodeQtObject(bitem, 'second_bible') + if item_second_bible and second_bible or not item_second_bible and \ + not second_bible: + self.displayResults(bible, second_bible) + elif critical_error_message_box( + message=translate('BiblePlugin.MediaItem', + 'You cannot combine single and dual Bible verse search results. ' + 'Do you want to delete your search results and start a new ' + 'search?'), + parent=self, question=True) == QtGui.QMessageBox.Yes: + self.listView.clear() + self.displayResults(bible, second_bible) + + def _decodeQtObject(self, bitem, key): + reference = bitem.data(QtCore.Qt.UserRole) + if isinstance(reference, QtCore.QVariant): + reference = reference.toPyObject() + obj = reference[QtCore.QString(key)] + if isinstance(obj, QtCore.QVariant): + obj = obj.toPyObject() + return unicode(obj).strip() + def requiredIcons(self): MediaManagerItem.requiredIcons(self) self.hasImportIcon = True @@ -74,6 +109,16 @@ class BibleMediaItem(MediaManagerItem): self.addToServiceItem = False def addSearchTab(self, prefix, name): + self.searchTabBar.addTab(name) + tab = QtGui.QWidget() + tab.setObjectName(prefix + u'Tab') + tab.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum) + layout = QtGui.QGridLayout(tab) + layout.setObjectName(prefix + u'Layout') + setattr(self, prefix + u'Tab', tab) + setattr(self, prefix + u'Layout', layout) + + def addSearchFields(self, prefix, name): """ Creates and adds generic search tab. @@ -83,121 +128,113 @@ class BibleMediaItem(MediaManagerItem): ``name`` The translated string to display. """ - tab = QtGui.QWidget() - tab.setObjectName(prefix + u'Tab') - layout = QtGui.QGridLayout(tab) - layout.setObjectName(prefix + u'Layout') + if prefix == u'quick': + idx = 2 + else: + idx = 5 + tab = getattr(self, prefix + u'Tab') + layout = getattr(self, prefix + u'Layout') versionLabel = QtGui.QLabel(tab) versionLabel.setObjectName(prefix + u'VersionLabel') - layout.addWidget(versionLabel, 0, 0, QtCore.Qt.AlignRight) - versionComboBox = media_item_combo_box(tab, prefix + u'VersionComboBox') + layout.addWidget(versionLabel, idx, 0, QtCore.Qt.AlignRight) + versionComboBox = media_item_combo_box(tab, + prefix + u'VersionComboBox') versionLabel.setBuddy(versionComboBox) - layout.addWidget(versionComboBox, 0, 1, 1, 2) + layout.addWidget(versionComboBox, idx, 1, 1, 2) secondLabel = QtGui.QLabel(tab) secondLabel.setObjectName(prefix + u'SecondLabel') - layout.addWidget(secondLabel, 1, 0, QtCore.Qt.AlignRight) + layout.addWidget(secondLabel, idx + 1, 0, QtCore.Qt.AlignRight) secondComboBox = media_item_combo_box(tab, prefix + u'SecondComboBox') versionLabel.setBuddy(secondComboBox) - layout.addWidget(secondComboBox, 1, 1, 1, 2) + layout.addWidget(secondComboBox, idx + 1, 1, 1, 2) + styleLabel = QtGui.QLabel(tab) + styleLabel.setObjectName(prefix + u'StyleLabel') + layout.addWidget(styleLabel, idx + 2, 0, QtCore.Qt.AlignRight) + styleComboBox = media_item_combo_box(tab, prefix + u'StyleComboBox') + styleComboBox.addItems([u'', u'', u'']) + layout.addWidget(styleComboBox, idx + 2, 1, 1, 2) searchButtonLayout = QtGui.QHBoxLayout() searchButtonLayout.setObjectName(prefix + u'SearchButtonLayout') searchButtonLayout.addStretch() + lockButton = QtGui.QToolButton(tab) + lockButton.setIcon(self.unlockIcon) + lockButton.setCheckable(True) + lockButton.setObjectName(prefix + u'LockButton') + searchButtonLayout.addWidget(lockButton) searchButton = QtGui.QPushButton(tab) searchButton.setObjectName(prefix + u'SearchButton') searchButtonLayout.addWidget(searchButton) - self.searchTabWidget.addTab(tab, name) - setattr(self, prefix + u'Tab', tab) - setattr(self, prefix + u'Layout', layout) + layout.addLayout(searchButtonLayout, idx + 3, 1, 1, 2) + self.pageLayout.addWidget(tab) + tab.setVisible(False) + QtCore.QObject.connect(lockButton, QtCore.SIGNAL(u'toggled(bool)'), + self.onLockButtonToggled) setattr(self, prefix + u'VersionLabel', versionLabel) setattr(self, prefix + u'VersionComboBox', versionComboBox) setattr(self, prefix + u'SecondLabel', secondLabel) setattr(self, prefix + u'SecondComboBox', secondComboBox) + setattr(self, prefix + u'StyleLabel', styleLabel) + setattr(self, prefix + u'StyleComboBox', styleComboBox) + setattr(self, prefix + u'LockButton', lockButton) setattr(self, prefix + u'SearchButtonLayout', searchButtonLayout) setattr(self, prefix + u'SearchButton', searchButton) def addEndHeaderBar(self): - self.searchTabWidget = QtGui.QTabWidget(self) - self.searchTabWidget.setSizePolicy( - QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum) - self.searchTabWidget.setObjectName(u'searchTabWidget') + self.searchTabBar = QtGui.QTabBar(self) + self.searchTabBar.setExpanding(False) + self.searchTabBar.setObjectName(u'searchTabBar') + self.pageLayout.addWidget(self.searchTabBar) # Add the Quick Search tab. self.addSearchTab( u'quick', translate('BiblesPlugin.MediaItem', 'Quick')) self.quickSearchLabel = QtGui.QLabel(self.quickTab) self.quickSearchLabel.setObjectName(u'quickSearchLabel') self.quickLayout.addWidget( - self.quickSearchLabel, 2, 0, QtCore.Qt.AlignRight) + self.quickSearchLabel, 0, 0, QtCore.Qt.AlignRight) self.quickSearchEdit = SearchEdit(self.quickTab) self.quickSearchEdit.setObjectName(u'quickSearchEdit') self.quickSearchLabel.setBuddy(self.quickSearchEdit) - self.quickLayout.addWidget(self.quickSearchEdit, 2, 1, 1, 2) - self.quickLayoutLabel = QtGui.QLabel(self.quickTab) - self.quickLayoutLabel.setObjectName(u'quickClearLabel') - self.quickLayout.addWidget( - self.quickLayoutLabel, 3, 0, QtCore.Qt.AlignRight) - self.quickLayoutComboBox = media_item_combo_box(self.quickTab, - u'quickLayoutComboBox') - self.quickLayoutComboBox.addItems([u'', u'', u'']) - self.quickLayout.addWidget(self.quickLayoutComboBox, 3, 1, 1, 2) - self.quickClearLabel = QtGui.QLabel(self.quickTab) - self.quickClearLabel.setObjectName(u'quickClearLabel') - self.quickLayout.addWidget( - self.quickClearLabel, 4, 0, QtCore.Qt.AlignRight) - self.quickClearComboBox = media_item_combo_box(self.quickTab, - u'quickClearComboBox') - self.quickLayout.addWidget(self.quickClearComboBox, 4, 1, 1, 2) - self.quickLayout.addLayout(self.quickSearchButtonLayout, 6, 1, 1, 2) - # Add a QWidget, so that the quick tab has as many rows as the advanced - # tab. - self.quickLayout.addWidget(QtGui.QWidget(), 7, 0) + self.quickLayout.addWidget(self.quickSearchEdit, 0, 1, 1, 2) + self.addSearchFields( + u'quick', translate('BiblesPlugin.MediaItem', 'Quick')) + self.quickTab.setVisible(True) # Add the Advanced Search tab. self.addSearchTab(u'advanced', UiStrings().Advanced) self.advancedBookLabel = QtGui.QLabel(self.advancedTab) self.advancedBookLabel.setObjectName(u'advancedBookLabel') - self.advancedLayout.addWidget(self.advancedBookLabel, 2, 0, + self.advancedLayout.addWidget(self.advancedBookLabel, 0, 0, QtCore.Qt.AlignRight) self.advancedBookComboBox = media_item_combo_box(self.advancedTab, u'advancedBookComboBox') self.advancedBookLabel.setBuddy(self.advancedBookComboBox) - self.advancedLayout.addWidget(self.advancedBookComboBox, 2, 1, 1, 2) + self.advancedLayout.addWidget(self.advancedBookComboBox, 0, 1, 1, 2) self.advancedChapterLabel = QtGui.QLabel(self.advancedTab) self.advancedChapterLabel.setObjectName(u'advancedChapterLabel') - self.advancedLayout.addWidget(self.advancedChapterLabel, 3, 1, 1, 2) + self.advancedLayout.addWidget(self.advancedChapterLabel, 1, 1, 1, 2) self.advancedVerseLabel = QtGui.QLabel(self.advancedTab) self.advancedVerseLabel.setObjectName(u'advancedVerseLabel') - self.advancedLayout.addWidget(self.advancedVerseLabel, 3, 2) + self.advancedLayout.addWidget(self.advancedVerseLabel, 1, 2) self.advancedFromLabel = QtGui.QLabel(self.advancedTab) self.advancedFromLabel.setObjectName(u'advancedFromLabel') - self.advancedLayout.addWidget(self.advancedFromLabel, 4, 0, + self.advancedLayout.addWidget(self.advancedFromLabel, 3, 0, QtCore.Qt.AlignRight) self.advancedFromChapter = QtGui.QComboBox(self.advancedTab) self.advancedFromChapter.setObjectName(u'advancedFromChapter') - self.advancedLayout.addWidget(self.advancedFromChapter, 4, 1) + self.advancedLayout.addWidget(self.advancedFromChapter, 3, 1) self.advancedFromVerse = QtGui.QComboBox(self.advancedTab) self.advancedFromVerse.setObjectName(u'advancedFromVerse') - self.advancedLayout.addWidget(self.advancedFromVerse, 4, 2) + self.advancedLayout.addWidget(self.advancedFromVerse, 3, 2) self.advancedToLabel = QtGui.QLabel(self.advancedTab) self.advancedToLabel.setObjectName(u'advancedToLabel') - self.advancedLayout.addWidget(self.advancedToLabel, 5, 0, + self.advancedLayout.addWidget(self.advancedToLabel, 4, 0, QtCore.Qt.AlignRight) self.advancedToChapter = QtGui.QComboBox(self.advancedTab) self.advancedToChapter.setObjectName(u'advancedToChapter') - self.advancedLayout.addWidget(self.advancedToChapter, 5, 1) + self.advancedLayout.addWidget(self.advancedToChapter, 4, 1) self.advancedToVerse = QtGui.QComboBox(self.advancedTab) self.advancedToVerse.setObjectName(u'advancedToVerse') - self.advancedLayout.addWidget(self.advancedToVerse, 5, 2) - self.advancedClearLabel = QtGui.QLabel(self.quickTab) - self.advancedClearLabel.setObjectName(u'advancedClearLabel') - self.advancedLayout.addWidget(self.advancedClearLabel, 6, 0, - QtCore.Qt.AlignRight) - self.advancedClearComboBox = media_item_combo_box(self.quickTab, - u'advancedClearComboBox') - self.advancedClearLabel.setBuddy(self.advancedClearComboBox) - self.advancedLayout.addWidget(self.advancedClearComboBox, 6, 1, 1, 2) - self.advancedLayout.addLayout( - self.advancedSearchButtonLayout, 7, 0, 1, 3) - # Add the search tab widget to the page layout. - self.pageLayout.addWidget(self.searchTabWidget) + self.advancedLayout.addWidget(self.advancedToVerse, 4, 2) + self.addSearchFields(u'advanced', UiStrings().Advanced) # Combo Boxes QtCore.QObject.connect(self.advancedVersionComboBox, QtCore.SIGNAL(u'activated(int)'), self.onAdvancedVersionComboBox) @@ -214,8 +251,11 @@ class BibleMediaItem(MediaManagerItem): QtCore.QObject.connect(self.quickVersionComboBox, QtCore.SIGNAL(u'activated(int)'), self.updateAutoCompleter) QtCore.QObject.connect( - self.quickLayoutComboBox, QtCore.SIGNAL(u'activated(int)'), - self.onLayoutStyleComboBoxChanged) + self.quickStyleComboBox, QtCore.SIGNAL(u'activated(int)'), + self.onQuickStyleComboBoxChanged) + QtCore.QObject.connect( + self.advancedStyleComboBox, QtCore.SIGNAL(u'activated(int)'), + self.onAdvancedStyleComboBoxChanged) # Buttons QtCore.QObject.connect(self.advancedSearchButton, QtCore.SIGNAL(u'pressed()'), self.onAdvancedSearchButton) @@ -226,6 +266,9 @@ class BibleMediaItem(MediaManagerItem): # Other stuff QtCore.QObject.connect(self.quickSearchEdit, QtCore.SIGNAL(u'returnPressed()'), self.onQuickSearchButton) + QtCore.QObject.connect(self.searchTabBar, + QtCore.SIGNAL(u'currentChanged(int)'), + self.onSearchTabBarCurrentChanged) def configUpdated(self): log.debug(u'configUpdated') @@ -240,21 +283,26 @@ class BibleMediaItem(MediaManagerItem): self.advancedSecondComboBox.setVisible(False) self.quickSecondLabel.setVisible(False) self.quickSecondComboBox.setVisible(False) - self.quickLayoutComboBox.setCurrentIndex(self.settings.layout_style) + self.quickStyleComboBox.setCurrentIndex(self.settings.layout_style) + self.advancedStyleComboBox.setCurrentIndex(self.settings.layout_style) def retranslateUi(self): log.debug(u'retranslateUi') + self.quickSearchLabel.setText( + translate('BiblesPlugin.MediaItem', 'Find:')) self.quickVersionLabel.setText(u'%s:' % UiStrings().Version) self.quickSecondLabel.setText( translate('BiblesPlugin.MediaItem', 'Second:')) - self.quickSearchLabel.setText( - translate('BiblesPlugin.MediaItem', 'Find:')) + self.quickStyleLabel.setText(UiStrings().LayoutStyle) + self.quickStyleComboBox.setItemText(LayoutStyle.VersePerSlide, + UiStrings().VersePerSlide) + self.quickStyleComboBox.setItemText(LayoutStyle.VersePerLine, + UiStrings().VersePerLine) + self.quickStyleComboBox.setItemText(LayoutStyle.Continuous, + UiStrings().Continuous) + self.quickLockButton.setToolTip(translate('BiblesPlugin.MediaItem', + 'Toggle to keep or clear the previous results.')) self.quickSearchButton.setText(UiStrings().Search) - self.quickClearLabel.setText( - translate('BiblesPlugin.MediaItem', 'Results:')) - self.advancedVersionLabel.setText(u'%s:' % UiStrings().Version) - self.advancedSecondLabel.setText( - translate('BiblesPlugin.MediaItem', 'Second:')) self.advancedBookLabel.setText( translate('BiblesPlugin.MediaItem', 'Book:')) self.advancedChapterLabel.setText( @@ -265,24 +313,19 @@ class BibleMediaItem(MediaManagerItem): translate('BiblesPlugin.MediaItem', 'From:')) self.advancedToLabel.setText( translate('BiblesPlugin.MediaItem', 'To:')) - self.advancedClearLabel.setText( - translate('BiblesPlugin.MediaItem', 'Results:')) - self.advancedSearchButton.setText(UiStrings().Search) - self.quickClearComboBox.addItem( - translate('BiblesPlugin.MediaItem', 'Clear')) - self.quickClearComboBox.addItem( - translate('BiblesPlugin.MediaItem', 'Keep')) - self.advancedClearComboBox.addItem( - translate('BiblesPlugin.MediaItem', 'Clear')) - self.advancedClearComboBox.addItem( - translate('BiblesPlugin.MediaItem', 'Keep')) - self.quickLayoutLabel.setText(UiStrings().LayoutStyle) - self.quickLayoutComboBox.setItemText(LayoutStyle.VersePerSlide, + self.advancedVersionLabel.setText(u'%s:' % UiStrings().Version) + self.advancedSecondLabel.setText( + translate('BiblesPlugin.MediaItem', 'Second:')) + self.advancedStyleLabel.setText(UiStrings().LayoutStyle) + self.advancedStyleComboBox.setItemText(LayoutStyle.VersePerSlide, UiStrings().VersePerSlide) - self.quickLayoutComboBox.setItemText(LayoutStyle.VersePerLine, + self.advancedStyleComboBox.setItemText(LayoutStyle.VersePerLine, UiStrings().VersePerLine) - self.quickLayoutComboBox.setItemText(LayoutStyle.Continuous, + self.advancedStyleComboBox.setItemText(LayoutStyle.Continuous, UiStrings().Continuous) + self.advancedLockButton.setToolTip(translate('BiblesPlugin.MediaItem', + 'Toggle to keep or clear the previous results.')) + self.advancedSearchButton.setText(UiStrings().Search) def initialise(self): log.debug(u'bible manager initialise') @@ -304,14 +347,6 @@ class BibleMediaItem(MediaManagerItem): self.configUpdated() log.debug(u'bible manager initialise complete') - def onImportClick(self): - if not hasattr(self, u'import_wizard'): - self.import_wizard = BibleImportForm(self, self.parent.manager, - self.parent) - # If the import was not cancelled then reload. - if self.import_wizard.exec_(): - self.reloadBibles() - def loadBibles(self): log.debug(u'Loading Bibles') self.quickVersionComboBox.clear() @@ -409,6 +444,47 @@ class BibleMediaItem(MediaManagerItem): books.sort() add_widget_completer(books, self.quickSearchEdit) + def onImportClick(self): + if not hasattr(self, u'import_wizard'): + self.import_wizard = BibleImportForm(self, self.parent.manager, + self.parent) + # If the import was not cancelled then reload. + if self.import_wizard.exec_(): + self.reloadBibles() + + def onSearchTabBarCurrentChanged(self, index): + if index == 0: + self.advancedTab.setVisible(False) + self.quickTab.setVisible(True) + self.quickSearchEdit.setFocus() + else: + self.quickTab.setVisible(False) + self.advancedTab.setVisible(True) + + def onLockButtonToggled(self, checked): + if checked: + self.sender().setIcon(self.lockIcon) + else: + self.sender().setIcon(self.unlockIcon) + + def onQuickStyleComboBoxChanged(self): + self.settings.layout_style = self.quickStyleComboBox.currentIndex() + self.advancedStyleComboBox.setCurrentIndex(self.settings.layout_style) + self.settings.layoutStyleComboBox.setCurrentIndex( + self.settings.layout_style) + QtCore.QSettings().setValue( + self.settingsSection + u'/verse layout style', + QtCore.QVariant(self.settings.layout_style)) + + def onAdvancedStyleComboBoxChanged(self): + self.settings.layout_style = self.advancedStyleComboBox.currentIndex() + self.quickStyleComboBox.setCurrentIndex(self.settings.layout_style) + self.settings.layoutStyleComboBox.setCurrentIndex( + self.settings.layout_style) + QtCore.QSettings().setValue( + self.settingsSection + u'/verse layout style', + QtCore.QVariant(self.settings.layout_style)) + def onAdvancedVersionComboBox(self): QtCore.QSettings().setValue(self.settingsSection + u'/advanced bible', QtCore.QVariant(self.advancedVersionComboBox.currentText())) @@ -517,14 +593,14 @@ class BibleMediaItem(MediaManagerItem): if second_bible: self.second_search_results = self.parent.manager.get_verses( second_bible, versetext) - if self.advancedClearComboBox.currentIndex() == 0: + if not self.advancedLockButton.isChecked(): self.listView.clear() if self.listView.count() != 0: self.__checkSecondBible(bible, second_bible) elif self.search_results: self.displayResults(bible, second_bible) self.advancedSearchButton.setEnabled(True) - check_search_result(self.listView, self.search_results) + self.check_search_result() Receiver.send_message(u'cursor_normal') Receiver.send_message(u'openlp_process_events') @@ -558,35 +634,17 @@ class BibleMediaItem(MediaManagerItem): verse.verse)) self.second_search_results = \ bibles[second_bible].get_verses(text) - if self.quickClearComboBox.currentIndex() == 0: + if not self.quickLockButton.isChecked(): self.listView.clear() if self.listView.count() != 0 and self.search_results: self.__checkSecondBible(bible, second_bible) elif self.search_results: self.displayResults(bible, second_bible) self.quickSearchButton.setEnabled(True) - check_search_result(self.listView, self.search_results) + self.check_search_result() Receiver.send_message(u'cursor_normal') Receiver.send_message(u'openlp_process_events') - def __checkSecondBible(self, bible, second_bible): - """ - Check if the first item is a second bible item or not. - """ - bitem = self.listView.item(0) - item_second_bible = self._decodeQtObject(bitem, 'second_bible') - if item_second_bible and second_bible or not item_second_bible and \ - not second_bible: - self.displayResults(bible, second_bible) - elif critical_error_message_box( - message=translate('BiblePlugin.MediaItem', - 'You cannot combine single and dual Bible verse search results. ' - 'Do you want to delete your search results and start a new ' - 'search?'), - parent=self, question=True) == QtGui.QMessageBox.Yes: - self.listView.clear() - self.displayResults(bible, second_bible) - def displayResults(self, bible, second_bible=u''): """ Displays the search results in the media manager. All data needed for @@ -644,15 +702,6 @@ class BibleMediaItem(MediaManagerItem): self.search_results = {} self.second_search_results = {} - def _decodeQtObject(self, bitem, key): - reference = bitem.data(QtCore.Qt.UserRole) - if isinstance(reference, QtCore.QVariant): - reference = reference.toPyObject() - obj = reference[QtCore.QString(key)] - if isinstance(obj, QtCore.QVariant): - obj = obj.toPyObject() - return unicode(obj).strip() - def generateSlideData(self, service_item, item=None, xmlVersion=False): """ Generates and formats the slides for the service item as well as the @@ -847,11 +896,3 @@ class BibleMediaItem(MediaManagerItem): if self.settings.display_style == DisplayStyle.Square: return u'{su}[%s]{/su}' % verse_text return u'{su}%s{/su}' % verse_text - - def onLayoutStyleComboBoxChanged(self): - self.settings.layout_style = self.quickLayoutComboBox.currentIndex() - self.settings.layoutStyleComboBox.setCurrentIndex( - self.settings.layout_style) - QtCore.QSettings().setValue( - self.settingsSection + u'/verse layout style', - QtCore.QVariant(self.settings.layout_style)) diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index a67d8f818..b691c47ce 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -252,7 +252,7 @@ class ImpressDocument(PresentationDocument): window.setVisible(False) self.presentation = self.document.getPresentation() self.presentation.Display = \ - self.controller.plugin.renderer.screens.current_display + 1 + self.controller.plugin.renderer.screens.current[u'number'] + 1 self.control = None self.create_thumbnails() return True diff --git a/openlp/plugins/remotes/html/openlp.js b/openlp/plugins/remotes/html/openlp.js index 811ce0cac..74463ffbc 100644 --- a/openlp/plugins/remotes/html/openlp.js +++ b/openlp/plugins/remotes/html/openlp.js @@ -63,8 +63,10 @@ window.OpenLP = { var ul = $("#slide-controller > div[data-role=content] > ul[data-role=listview]"); ul.html(""); for (idx in data.results.slides) { + var text = data.results.slides[idx]["text"]; + text = text.replace(/\n/g, '
'); var li = $("
  • ").append( - $("").attr("value", parseInt(idx, 10)).html(data.results.slides[idx]["text"])); + $("").attr("value", parseInt(idx, 10)).html(text)); if (data.results.slides[idx]["selected"]) { li.attr("data-theme", "e"); } diff --git a/openlp/plugins/remotes/html/stage.css b/openlp/plugins/remotes/html/stage.css index a773c2393..73551b92e 100644 --- a/openlp/plugins/remotes/html/stage.css +++ b/openlp/plugins/remotes/html/stage.css @@ -30,12 +30,14 @@ body { #currentslide { font-size: 40pt; color: white; + padding-bottom: 0px; } #nextslide { - font-size: 30pt; + font-size: 40pt; color: grey; - padding-top: 25px; + padding-top: 0px; + padding-bottom: 0px; } #right { diff --git a/openlp/plugins/remotes/html/stage.html b/openlp/plugins/remotes/html/stage.html index 99090b6f9..9c74cc371 100644 --- a/openlp/plugins/remotes/html/stage.html +++ b/openlp/plugins/remotes/html/stage.html @@ -26,7 +26,7 @@ --> - OpenLP 2.0 Remote + OpenLP 2.0 Stage View diff --git a/openlp/plugins/remotes/html/stage.js b/openlp/plugins/remotes/html/stage.js index 8b8a83f6a..8ca041366 100644 --- a/openlp/plugins/remotes/html/stage.js +++ b/openlp/plugins/remotes/html/stage.js @@ -46,30 +46,79 @@ window.OpenLP = { function (data, status) { OpenLP.currentSlides = data.results.slides; OpenLP.currentSlide = 0; + OpenLP.currentTags = Array(); var div = $("#verseorder"); div.html(""); - for (idx in data.results.slides) { - idx = parseInt(idx, 10); - div.append(" "); - var tag = data.results.slides[idx]["tag"]; - if (tag == 'None') - tag = idx; - $("#verseorder span").last().attr("id", "tag" + idx).text(tag); - if (data.results.slides[idx]["selected"]) + var tag = ""; + var tags = 0; + var lastChange = 0; + $.each(data.results.slides, function(idx, slide) { + var prevtag = tag; + tag = slide["tag"]; + if (tag != prevtag) { + // If the tag has changed, add new one to the list + lastChange = idx; + tags = tags + 1; + div.append(" "); + $("#verseorder span").last().attr("id", "tag" + tags).text(tag); + } + else { + if ((slide["text"] == data.results.slides[lastChange]["text"]) && + (data.results.slides.length > idx + (idx - lastChange))) { + // If the tag hasn't changed, check to see if the same verse + // has been repeated consecutively. Note the verse may have been + // split over several slides, so search through. If so, repeat the tag. + var match = true; + for (var idx2 = 0; idx2 < idx - lastChange; idx2++) { + if(data.results.slides[lastChange + idx2]["text"] != data.results.slides[idx + idx2]["text"]) { + match = false; + break; + } + } + if (match) { + lastChange = idx; + tags = tags + 1; + div.append(" "); + $("#verseorder span").last().attr("id", "tag" + tags).text(tag); + } + } + } + OpenLP.currentTags[idx] = tags; + if (slide["selected"]) OpenLP.currentSlide = idx; - } + }) OpenLP.loadService(); } ); }, updateSlide: function() { + // Show the current slide on top. Any trailing slides for the same verse + // are shown too underneath in grey. + // Then leave a blank line between following verses $("#verseorder span").removeClass("currenttag"); - $("#tag" + OpenLP.currentSlide).addClass("currenttag"); - $("#currentslide").html(OpenLP.currentSlides[OpenLP.currentSlide]["text"]); - if (OpenLP.currentSlide < OpenLP.currentSlides.length - 1) - $("#nextslide").html(OpenLP.currentSlides[OpenLP.currentSlide + 1]["text"]); - else - $("#nextslide").html("Next: " + OpenLP.nextSong); + $("#tag" + OpenLP.currentTags[OpenLP.currentSlide]).addClass("currenttag"); + var slide = OpenLP.currentSlides[OpenLP.currentSlide]; + var text = slide["text"]; + text = text.replace(/\n/g, '
    '); + $("#currentslide").html(text); + text = ""; + if (OpenLP.currentSlide < OpenLP.currentSlides.length - 1) { + for (var idx = OpenLP.currentSlide + 1; idx < OpenLP.currentSlides.length; idx++) { + if (OpenLP.currentTags[idx] != OpenLP.currentTags[idx - 1]) + text = text + '

    '; + text = text + OpenLP.currentSlides[idx]["text"]; + if (OpenLP.currentTags[idx] != OpenLP.currentTags[idx - 1]) + text = text + '

    '; + else + text = text + '
    '; + } + text = text.replace(/\n/g, '
    '); + $("#nextslide").html(text); + } + else { + text = '

    Next: ' + OpenLP.nextSong + '

    '; + $("#nextslide").html(text); + } }, updateClock: function() { var div = $("#clock"); diff --git a/openlp/plugins/remotes/lib/httpserver.py b/openlp/plugins/remotes/lib/httpserver.py index 70f02ff36..20005840c 100644 --- a/openlp/plugins/remotes/lib/httpserver.py +++ b/openlp/plugins/remotes/lib/httpserver.py @@ -401,11 +401,16 @@ class HttpConnection(object): for index, frame in enumerate(current_item.get_frames()): item = {} if current_item.is_text(): - item[u'tag'] = unicode(frame[u'verseTag']) - item[u'text'] = unicode(frame[u'html']) + if frame[u'verseTag']: + item[u'tag'] = unicode(frame[u'verseTag']) + else: + item[u'tag'] = unicode(index + 1) + item[u'text'] = unicode(frame[u'text']) + item[u'html'] = unicode(frame[u'html']) else: - item[u'tag'] = unicode(index) + item[u'tag'] = unicode(index + 1) item[u'text'] = u'' + item[u'html'] = u'' item[u'selected'] = (self.parent.current_slide == index) data.append(item) json_data = {u'results': {u'slides': data}} diff --git a/openlp/plugins/remotes/lib/remotetab.py b/openlp/plugins/remotes/lib/remotetab.py index bfb05d486..07f24dbee 100644 --- a/openlp/plugins/remotes/lib/remotetab.py +++ b/openlp/plugins/remotes/lib/remotetab.py @@ -93,24 +93,23 @@ class RemoteTab(SettingsTab): 'Stage view URL:')) def setUrls(self): - ipAddress = None + ipAddress = u'localhost' if self.addressEdit.text() == ZERO_URL: - for ip in QtNetwork.QNetworkInterface.allAddresses(): - if ip.protocol() == 0 and ip != QtNetwork.QHostAddress.LocalHost: - ipAddress = ip.toString() - break + ifaces = QtNetwork.QNetworkInterface.allInterfaces() + for iface in ifaces: + if not iface.isValid(): + continue + if not (iface.flags() & (QtNetwork.QNetworkInterface.IsUp | + QtNetwork.QNetworkInterface.IsRunning)): + continue + for addr in iface.addressEntries(): + ip = addr.ip() + if ip.protocol() == 0 and \ + ip != QtNetwork.QHostAddress.LocalHost: + ipAddress = ip.toString() + break else: ipAddress = self.addressEdit.text() - if not ipAddress: - self.remoteUrlLabel.setVisible(False) - self.remoteUrl.setVisible(False) - self.stageUrlLabel.setVisible(False) - self.stageUrl.setVisible(False) - return - self.remoteUrlLabel.setVisible(True) - self.remoteUrl.setVisible(True) - self.stageUrlLabel.setVisible(True) - self.stageUrl.setVisible(True) url = u'http://%s:%s/' % (ipAddress, self.portSpinBox.value()) self.remoteUrl.setText(u'
    %s' % (url, url)) url = url + u'stage' diff --git a/openlp/plugins/songs/lib/foilpresenterimport.py b/openlp/plugins/songs/lib/foilpresenterimport.py index 0c7152bfd..c5dfd5d96 100644 --- a/openlp/plugins/songs/lib/foilpresenterimport.py +++ b/openlp/plugins/songs/lib/foilpresenterimport.py @@ -431,7 +431,7 @@ class FoilPresenter(object): verse_sortnr = self._child(strophe.sortnr) sortnr = True # In older Version there is no sortnr, but we need one - if sortnr == False: + if not sortnr: verse_sortnr = unicode(temp_sortnr_backup) temp_sortnr_backup += 1 # Foilpresenter allows e. g. "Ref" or "1", but we need "C1" or "V1". @@ -467,7 +467,7 @@ class FoilPresenter(object): # test if foilpresenter have the same versenumber two times with # different parts raise the verse number for value in temp_verse_order_backup: - if value == (u''.join((verse_type, verse_number))): + if value == u''.join((verse_type, verse_number)): verse_number = unicode(int(verse_number) + 1) verse_type_index = VerseType.from_tag(verse_type[0]) verse_type = VerseType.Names[verse_type_index] diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 3b014d4b0..8ac69392e 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -32,7 +32,7 @@ from PyQt4 import QtCore, QtGui from sqlalchemy.sql import or_ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ - translate, check_item_selected, PluginStatus, check_search_result + translate, check_item_selected, PluginStatus from openlp.core.lib.searchedit import SearchEdit from openlp.core.lib.ui import UiStrings from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ @@ -199,7 +199,7 @@ class SongMediaItem(MediaManagerItem): search_results = self.parent.manager.get_all_objects(Song, Song.theme_name == search_keywords) self.displayResultsSong(search_results) - check_search_result(self.listView, search_results) + self.check_search_result() def onSongListLoad(self): """ diff --git a/openlp/plugins/songs/lib/songshowplusimport.py b/openlp/plugins/songs/lib/songshowplusimport.py index 6d2e1f5b6..ac06d7840 100644 --- a/openlp/plugins/songs/lib/songshowplusimport.py +++ b/openlp/plugins/songs/lib/songshowplusimport.py @@ -150,13 +150,13 @@ class SongShowPlusImport(SongImport): self.ccli_number = int(data) elif blockKey == VERSE: self.add_verse(unicode(data, u'cp1252'), - "V%s" % verseNo) + "%s%s" % (VerseType.Tags[VerseType.Verse], verseNo)) elif blockKey == CHORUS: self.add_verse(unicode(data, u'cp1252'), - "C%s" % verseNo) + "%s%s" % (VerseType.Tags[VerseType.Chorus], verseNo)) elif blockKey == BRIDGE: self.add_verse(unicode(data, u'cp1252'), - "B%s" % verseNo) + "%s%s" % (VerseType.Tags[VerseType.Bridge], verseNo)) elif blockKey == TOPIC: self.topics.append(unicode(data, u'cp1252')) elif blockKey == COMMENTS: diff --git a/resources/images/bibles_search_lock.png b/resources/images/bibles_search_lock.png new file mode 100644 index 000000000..ac2fd6f90 Binary files /dev/null and b/resources/images/bibles_search_lock.png differ diff --git a/resources/images/bibles_search_unlock.png b/resources/images/bibles_search_unlock.png new file mode 100644 index 000000000..d03a1f415 Binary files /dev/null and b/resources/images/bibles_search_unlock.png differ diff --git a/resources/images/openlp-2.qrc b/resources/images/openlp-2.qrc index 364a75810..a32d15940 100644 --- a/resources/images/openlp-2.qrc +++ b/resources/images/openlp-2.qrc @@ -24,6 +24,8 @@ bibles_search_text.png bibles_search_reference.png + bibles_search_unlock.png + bibles_search_lock.png plugin_alerts.png diff --git a/resources/windows/OpenLP-2.0.iss b/resources/windows/OpenLP-2.0.iss index 8cc8a4aa7..9f193b0e8 100644 --- a/resources/windows/OpenLP-2.0.iss +++ b/resources/windows/OpenLP-2.0.iss @@ -69,7 +69,7 @@ Source: ..\..\dist\OpenLP\*; DestDir: {app}; Flags: ignoreversion recursesubdirs [Icons] Name: {group}\{#AppName}; Filename: {app}\{#AppExeName} Name: {group}\{#AppName} (Debug); Filename: {app}\{#AppExeName}; Parameters: -l debug -Name: {group}\{#AppName} Help; Filename: {app}\{#AppName}.chm +Name: {group}\{#AppName} Help; Filename: {app}\{#AppName}.chm; Check: FileExists(ExpandConstant('{app}\{#AppName}.chm')) Name: {group}\{cm:ProgramOnTheWeb,{#AppName}}; Filename: {#AppURL} Name: {group}\{cm:UninstallProgram,{#AppName}}; Filename: {uninstallexe} Name: {commondesktop}\{#AppName}; Filename: {app}\{#AppExeName}; Tasks: desktopicon diff --git a/scripts/windows-builder.py b/scripts/windows-builder.py index 0271f80b8..8f2dc0171 100644 --- a/scripts/windows-builder.py +++ b/scripts/windows-builder.py @@ -53,7 +53,8 @@ UPX add that directory to your PATH environment variable. Sphinx - This is used to build the documentation + This is used to build the documentation. The documentation trunk must be at + the same directory level as Openlp trunk and named "documentation" HTML Help Workshop This is used to create the help file @@ -99,6 +100,7 @@ windows-builder.py import os import sys from shutil import copy +from shutil import rmtree from subprocess import Popen, PIPE python_exe = sys.executable @@ -108,12 +110,14 @@ sphinx_exe = os.path.join(os.path.split(python_exe)[0], u'Scripts', u'sphinx-build.exe') hhc_exe = os.path.join(os.getenv(u'PROGRAMFILES'), 'HTML Help Workshop', u'hhc.exe') -vcbuild_exe = os.path.join(os.getenv(u'PROGRAMFILES'), +vcbuild_exe = os.path.join(os.getenv(u'PROGRAMFILES'), u'Microsoft Visual Studio 9.0', u'VC', u'vcpackages', u'vcbuild.exe') # Base paths script_path = os.path.split(os.path.abspath(__file__))[0] branch_path = os.path.abspath(os.path.join(script_path, u'..')) +doc_branch_path = os.path.abspath(os.path.join(script_path, u'..', + u'..', u'documentation')) site_packages = os.path.join(os.path.split(python_exe)[0], u'Lib', u'site-packages') @@ -125,7 +129,9 @@ i18n_utils = os.path.join(script_path, u'translation_utils.py') # Paths source_path = os.path.join(branch_path, u'openlp') -manual_path = os.path.join(branch_path, u'documentation', u'manual') +manual_path = os.path.join(doc_branch_path, u'manual') +manual_build_path = os.path.join(manual_path, u'build') +helpfile_path = os.path.join(manual_build_path, u'htmlhelp') i18n_path = os.path.join(branch_path, u'resources', u'i18n') winres_path = os.path.join(branch_path, u'resources', u'windows') build_path = os.path.join(branch_path, u'build', u'pyi.win32', u'OpenLP') @@ -219,6 +225,12 @@ def copy_windows_files(): os.path.join(dist_path, u'OpenLP.ico')) copy(os.path.join(winres_path, u'LICENSE.txt'), os.path.join(dist_path, u'LICENSE.txt')) + if os.path.isfile(os.path.join(helpfile_path, u'Openlp.chm')): + print u' Windows help file found' + copy(os.path.join(helpfile_path, u'Openlp.chm'), + os.path.join(dist_path, u'Openlp.chm')) + else: + print u' WARNING ---- Windows help file not found ---- WARNING' def update_translations(): print u'Updating translations...' @@ -253,6 +265,9 @@ def compile_translations(): os.path.join(dist_path, u'i18n', filename)) def run_sphinx(): + print u'Deleting previous manual build...', manual_build_path + if os.path.exists(manual_build_path): + rmtree(manual_build_path) print u'Running Sphinx...' os.chdir(manual_path) sphinx = Popen((sphinx_exe, u'-b', u'htmlhelp', u'-d', u'build/doctrees', @@ -265,7 +280,7 @@ def run_sphinx(): def run_htmlhelp(): print u'Running HTML Help Workshop...' - os.chdir(os.path.join(manual_path, u'build', u'htmlhelp')) + os.chdir(os.path.join(manual_build_path, u'htmlhelp')) hhc = Popen((hhc_exe, u'OpenLP.chm'), stdout=PIPE) output, error = hhc.communicate() code = hhc.wait() @@ -273,9 +288,6 @@ def run_htmlhelp(): print u'Exit code:', code print output raise Exception(u'Error running HTML Help Workshop') - else: - copy(os.path.join(manual_path, u'build', 'htmlhelp', u'OpenLP.chm'), - os.path.join(dist_path, u'OpenLP.chm')) def run_innosetup(): print u'Running Inno Setup...' @@ -306,6 +318,8 @@ def main(): print "Source path:", source_path print "\"dist\" path:", dist_path print "PyInstaller:", pyi_build + print "Documentation branch path:", doc_branch_path + print "Help file build path;", helpfile_path print "Inno Setup path:", innosetup_exe print "Windows resources:", winres_path print "VCBuild path:", vcbuild_exe @@ -324,11 +338,17 @@ def main(): write_version_file() copy_enchant() copy_plugins() + if os.path.exists(manual_path): + run_sphinx() + run_htmlhelp() + else: + print u' ' + print u' WARNING ---- Documentation Trunk not found ---- WARNING' + print u' --- Windows Help file will not be included in build ---' + print u' ' copy_windows_files() update_translations() compile_translations() - run_sphinx() - run_htmlhelp() run_innosetup() print "Done."