Merge upstream

This commit is contained in:
Ken Roberts 2014-10-23 15:16:38 -07:00
commit f81903bbcf
45 changed files with 262 additions and 153 deletions

View File

@ -118,7 +118,9 @@ class OpenLP(OpenLPMixin, QtGui.QApplication):
# First time checks in settings # First time checks in settings
has_run_wizard = Settings().value('core/has run wizard') has_run_wizard = Settings().value('core/has run wizard')
if not has_run_wizard: if not has_run_wizard:
if FirstTimeForm(screens).exec_() == QtGui.QDialog.Accepted: ftw = FirstTimeForm()
ftw.initialize(screens)
if ftw.exec_() == QtGui.QDialog.Accepted:
Settings().setValue('core/has run wizard', True) Settings().setValue('core/has run wizard', True)
# Correct stylesheet bugs # Correct stylesheet bugs
application_stylesheet = '' application_stylesheet = ''

View File

@ -44,7 +44,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.common import Registry, RegistryProperties, AppLocation, Settings, check_directory_exists, translate from openlp.core.common import Registry, RegistryProperties, AppLocation, Settings, check_directory_exists, translate
from openlp.core.lib import PluginStatus, build_icon from openlp.core.lib import PluginStatus, build_icon
from openlp.core.utils import get_web_page from openlp.core.utils import get_web_page
from .firsttimewizard import Ui_FirstTimeWizard, FirstTimePage from .firsttimewizard import UiFirstTimeWizard, FirstTimePage
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -75,18 +75,58 @@ class ThemeScreenshotThread(QtCore.QThread):
item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable) item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard, RegistryProperties): class FirstTimeForm(QtGui.QWizard, UiFirstTimeWizard, RegistryProperties):
""" """
This is the Theme Import Wizard, which allows easy creation and editing of OpenLP themes. This is the Theme Import Wizard, which allows easy creation and editing of OpenLP themes.
""" """
log.info('ThemeWizardForm loaded') log.info('ThemeWizardForm loaded')
def __init__(self, screens, parent=None): def __init__(self, parent=None):
""" """
Create and set up the first time wizard. Create and set up the first time wizard.
""" """
super(FirstTimeForm, self).__init__(parent) super(FirstTimeForm, self).__init__(parent)
self.setupUi(self) self.setup_ui(self)
def nextId(self):
"""
Determine the next page in the Wizard to go to.
"""
self.application.process_events()
if self.currentId() == FirstTimePage.Plugins:
if not self.web_access:
return FirstTimePage.NoInternet
else:
return FirstTimePage.Songs
elif self.currentId() == FirstTimePage.Progress:
return -1
elif self.currentId() == FirstTimePage.NoInternet:
return FirstTimePage.Progress
elif self.currentId() == FirstTimePage.Themes:
self.application.set_busy_cursor()
while not self.theme_screenshot_thread.isFinished():
time.sleep(0.1)
self.application.process_events()
# Build the screenshot icons, as this can not be done in the thread.
self._build_theme_screenshots()
self.application.set_normal_cursor()
return FirstTimePage.Defaults
else:
return self.currentId() + 1
def exec_(self):
"""
Run the wizard.
"""
self.set_defaults()
return QtGui.QWizard.exec_(self)
def initialize(self, screens):
"""
Set up the First Time Wizard
:param screens: The screens detected by OpenLP
"""
self.screens = screens self.screens = screens
# check to see if we have web access # check to see if we have web access
self.web = 'http://openlp.org/files/frw/' self.web = 'http://openlp.org/files/frw/'
@ -110,13 +150,6 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard, RegistryProperties):
self.currentIdChanged.connect(self.on_current_id_changed) self.currentIdChanged.connect(self.on_current_id_changed)
Registry().register_function('config_screen_changed', self.update_screen_list_combo) Registry().register_function('config_screen_changed', self.update_screen_list_combo)
def exec_(self):
"""
Run the wizard.
"""
self.set_defaults()
return QtGui.QWizard.exec_(self)
def set_defaults(self): def set_defaults(self):
""" """
Set up display at start of theme edit. Set up display at start of theme edit.
@ -157,31 +190,14 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard, RegistryProperties):
self.theme_screenshot_thread.start() self.theme_screenshot_thread.start()
self.application.set_normal_cursor() self.application.set_normal_cursor()
def nextId(self): def update_screen_list_combo(self):
""" """
Determine the next page in the Wizard to go to. The user changed screen resolution or enabled/disabled more screens, so
we need to update the combo box.
""" """
self.application.process_events() self.display_combo_box.clear()
if self.currentId() == FirstTimePage.Plugins: self.display_combo_box.addItems(self.screens.get_screen_list())
if not self.web_access: self.display_combo_box.setCurrentIndex(self.display_combo_box.count() - 1)
return FirstTimePage.NoInternet
else:
return FirstTimePage.Songs
elif self.currentId() == FirstTimePage.Progress:
return -1
elif self.currentId() == FirstTimePage.NoInternet:
return FirstTimePage.Progress
elif self.currentId() == FirstTimePage.Themes:
self.application.set_busy_cursor()
while not self.theme_screenshot_thread.isFinished():
time.sleep(0.1)
self.application.process_events()
# Build the screenshot icons, as this can not be done in the thread.
self._build_theme_screenshots()
self.application.set_normal_cursor()
return FirstTimePage.Defaults
else:
return self.currentId() + 1
def on_current_id_changed(self, page_id): def on_current_id_changed(self, page_id):
""" """
@ -196,7 +212,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard, RegistryProperties):
if self.has_run_wizard: if self.has_run_wizard:
self.no_internet_label.setText(self.no_internet_text) self.no_internet_label.setText(self.no_internet_text)
else: else:
self.no_internet_label.setText(self.no_internet_text + self.cancelWizardText) self.no_internet_label.setText(self.no_internet_text + self.cancel_wizard_text)
elif page_id == FirstTimePage.Defaults: elif page_id == FirstTimePage.Defaults:
self.theme_combo_box.clear() self.theme_combo_box.clear()
for index in range(self.themes_list_widget.count()): for index in range(self.themes_list_widget.count()):
@ -230,15 +246,6 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard, RegistryProperties):
self._post_wizard() self._post_wizard()
self.application.set_normal_cursor() self.application.set_normal_cursor()
def update_screen_list_combo(self):
"""
The user changed screen resolution or enabled/disabled more screens, so
we need to update the combo box.
"""
self.display_combo_box.clear()
self.display_combo_box.addItems(self.screens.get_screen_list())
self.display_combo_box.setCurrentIndex(self.display_combo_box.count() - 1)
def on_cancel_button_clicked(self): def on_cancel_button_clicked(self):
""" """
Process the triggering of the cancel button. Process the triggering of the cancel button.

View File

@ -50,13 +50,15 @@ class FirstTimePage(object):
Progress = 7 Progress = 7
class Ui_FirstTimeWizard(object): class UiFirstTimeWizard(object):
""" """
The UI widgets for the first time wizard. The UI widgets for the first time wizard.
""" """
def setupUi(self, first_time_wizard): def setup_ui(self, first_time_wizard):
""" """
Set up the UI. Set up the UI.
:param first_time_wizard: The wizard form
""" """
first_time_wizard.setObjectName('first_time_wizard') first_time_wizard.setObjectName('first_time_wizard')
first_time_wizard.setWindowIcon(build_icon(u':/icon/openlp-logo.svg')) first_time_wizard.setWindowIcon(build_icon(u':/icon/openlp-logo.svg'))
@ -68,6 +70,8 @@ class Ui_FirstTimeWizard(object):
first_time_wizard.setPixmap(QtGui.QWizard.BackgroundPixmap, first_time_wizard.setPixmap(QtGui.QWizard.BackgroundPixmap,
QtGui.QPixmap(':/wizards/openlp-osx-wizard.png')) QtGui.QPixmap(':/wizards/openlp-osx-wizard.png'))
first_time_wizard.resize(634, 386) first_time_wizard.resize(634, 386)
else:
first_time_wizard.setWizardStyle(QtGui.QWizard.ModernStyle)
self.finish_button = self.button(QtGui.QWizard.FinishButton) self.finish_button = self.button(QtGui.QWizard.FinishButton)
self.no_internet_finish_button = self.button(QtGui.QWizard.CustomButton1) self.no_internet_finish_button = self.button(QtGui.QWizard.CustomButton1)
self.cancel_button = self.button(QtGui.QWizard.CancelButton) self.cancel_button = self.button(QtGui.QWizard.CancelButton)
@ -202,19 +206,21 @@ class Ui_FirstTimeWizard(object):
self.progress_bar.setObjectName('progress_bar') self.progress_bar.setObjectName('progress_bar')
self.progress_layout.addWidget(self.progress_bar) self.progress_layout.addWidget(self.progress_bar)
first_time_wizard.setPage(FirstTimePage.Progress, self.progress_page) first_time_wizard.setPage(FirstTimePage.Progress, self.progress_page)
self.retranslateUi(first_time_wizard) self.retranslate_ui(first_time_wizard)
def retranslateUi(self, first_time_wizard): def retranslate_ui(self, first_time_wizard):
""" """
Translate the UI on the fly Translate the UI on the fly
:param first_time_wizard: The wizard form
""" """
first_time_wizard.setWindowTitle(translate('OpenLP.FirstTimeWizard', 'First Time Wizard')) first_time_wizard.setWindowTitle(translate('OpenLP.FirstTimeWizard', 'First Time Wizard'))
self.title_label.setText('<span style="font-size:14pt; font-weight:600;">%s</span>' % first_time_wizard.title_label.setText('<span style="font-size:14pt; font-weight:600;">%s</span>' %
translate('OpenLP.FirstTimeWizard', 'Welcome to the First Time Wizard')) translate('OpenLP.FirstTimeWizard', 'Welcome to the First Time Wizard'))
self.information_label.setText( first_time_wizard.information_label.setText(
translate('OpenLP.FirstTimeWizard', 'This wizard will help you to configure OpenLP for initial use. ' translate('OpenLP.FirstTimeWizard', 'This wizard will help you to configure OpenLP for initial use. '
'Click the %s button below to start.') % 'Click the %s button below to start.') %
self.buttonText(QtGui.QWizard.NextButton)) first_time_wizard.buttonText(QtGui.QWizard.NextButton))
self.plugin_page.setTitle(translate('OpenLP.FirstTimeWizard', 'Activate required Plugins')) self.plugin_page.setTitle(translate('OpenLP.FirstTimeWizard', 'Activate required Plugins'))
self.plugin_page.setSubTitle(translate('OpenLP.FirstTimeWizard', 'Select the Plugins you wish to use. ')) self.plugin_page.setSubTitle(translate('OpenLP.FirstTimeWizard', 'Select the Plugins you wish to use. '))
self.songs_check_box.setText(translate('OpenLP.FirstTimeWizard', 'Songs')) self.songs_check_box.setText(translate('OpenLP.FirstTimeWizard', 'Songs'))
@ -236,9 +242,10 @@ class Ui_FirstTimeWizard(object):
'no sample data.\n\nTo re-run the First Time Wizard and import this sample ' 'no sample data.\n\nTo re-run the First Time Wizard and import this sample '
'data at a later time, check your Internet connection and re-run this ' 'data at a later time, check your Internet connection and re-run this '
'wizard by selecting "Tools/Re-run First Time Wizard" from OpenLP.') 'wizard by selecting "Tools/Re-run First Time Wizard" from OpenLP.')
self.cancelWizardText = translate('OpenLP.FirstTimeWizard', self.cancel_wizard_text = translate('OpenLP.FirstTimeWizard',
'\n\nTo cancel the First Time Wizard completely (and not start OpenLP), ' '\n\nTo cancel the First Time Wizard completely (and not start OpenLP), '
'click the %s button now.') % self.buttonText(QtGui.QWizard.CancelButton) 'click the %s button now.') % \
first_time_wizard.buttonText(QtGui.QWizard.CancelButton)
self.songs_page.setTitle(translate('OpenLP.FirstTimeWizard', 'Sample Songs')) self.songs_page.setTitle(translate('OpenLP.FirstTimeWizard', 'Sample Songs'))
self.songs_page.setSubTitle(translate('OpenLP.FirstTimeWizard', 'Select and download public domain songs.')) self.songs_page.setSubTitle(translate('OpenLP.FirstTimeWizard', 'Select and download public domain songs.'))
self.bibles_page.setTitle(translate('OpenLP.FirstTimeWizard', 'Sample Bibles')) self.bibles_page.setTitle(translate('OpenLP.FirstTimeWizard', 'Sample Bibles'))

View File

@ -38,17 +38,30 @@ from openlp.core.lib import ImageSource, ServiceItem
class ListPreviewWidget(QtGui.QTableWidget, RegistryProperties): class ListPreviewWidget(QtGui.QTableWidget, RegistryProperties):
"""
A special type of QTableWidget which lists the slides in the slide controller
:param parent:
:param screen_ratio:
"""
def __init__(self, parent, screen_ratio): def __init__(self, parent, screen_ratio):
""" """
Initializes the widget to default state. Initializes the widget to default state.
An empty ServiceItem is used per default.
One needs to call replace_service_manager_item() to make this widget display something. An empty ``ServiceItem`` is used by default. replace_service_manager_item() needs to be called to make this
widget display something.
""" """
super(QtGui.QTableWidget, self).__init__(parent) super(QtGui.QTableWidget, self).__init__(parent)
# Set up the widget. self._setup(screen_ratio)
def _setup(self, screen_ratio):
"""
Set up the widget
"""
self.setColumnCount(1) self.setColumnCount(1)
self.horizontalHeader().setVisible(False) self.horizontalHeader().setVisible(False)
self.setColumnWidth(0, parent.width()) self.setColumnWidth(0, self.parent().width())
self.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) self.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
self.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) self.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
self.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) self.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
@ -58,7 +71,7 @@ class ListPreviewWidget(QtGui.QTableWidget, RegistryProperties):
self.service_item = ServiceItem() self.service_item = ServiceItem()
self.screen_ratio = screen_ratio self.screen_ratio = screen_ratio
def resizeEvent(self, QResizeEvent): def resizeEvent(self, event):
""" """
Overloaded method from QTableWidget. Will recalculate the layout. Overloaded method from QTableWidget. Will recalculate the layout.
""" """
@ -82,16 +95,20 @@ class ListPreviewWidget(QtGui.QTableWidget, RegistryProperties):
def screen_size_changed(self, screen_ratio): def screen_size_changed(self, screen_ratio):
""" """
To be called whenever the live screen size changes. This method is called whenever the live screen size changes, which then makes a layout recalculation necessary
Because this makes a layout recalculation necessary.
:param screen_ratio: The new screen ratio
""" """
self.screen_ratio = screen_ratio self.screen_ratio = screen_ratio
self.__recalculate_layout() self.__recalculate_layout()
def replace_service_item(self, service_item, width, slide_number): def replace_service_item(self, service_item, width, slide_number):
""" """
Replaces the current preview items with the ones in service_item. Replace the current preview items with the ones in service_item and display the given slide
Displays the given slide.
:param service_item: The service item to insert
:param width: The width of the column
:param slide_number: The slide number to pre-select
""" """
self.service_item = service_item self.service_item = service_item
self.setRowCount(0) self.setRowCount(0)

View File

@ -687,8 +687,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow, RegistryProperties):
QtGui.QMessageBox.No) QtGui.QMessageBox.No)
if answer == QtGui.QMessageBox.No: if answer == QtGui.QMessageBox.No:
return return
screens = ScreenList() first_run_wizard = FirstTimeForm(self)
first_run_wizard = FirstTimeForm(screens, self) first_run_wizard.initialize(ScreenList())
first_run_wizard.exec_() first_run_wizard.exec_()
if first_run_wizard.was_download_cancelled: if first_run_wizard.was_download_cancelled:
return return

View File

@ -53,6 +53,8 @@ class Ui_ThemeWizard(object):
if is_macosx(): if is_macosx():
theme_wizard.setPixmap(QtGui.QWizard.BackgroundPixmap, QtGui.QPixmap(':/wizards/openlp-osx-wizard.png')) theme_wizard.setPixmap(QtGui.QWizard.BackgroundPixmap, QtGui.QPixmap(':/wizards/openlp-osx-wizard.png'))
theme_wizard.resize(646, 400) theme_wizard.resize(646, 400)
else:
theme_wizard.setWizardStyle(QtGui.QWizard.ModernStyle)
self.spacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) self.spacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum)
# Welcome Page # Welcome Page
add_welcome_page(theme_wizard, ':/wizards/wizard_createtheme.bmp') add_welcome_page(theme_wizard, ':/wizards/wizard_createtheme.bmp')

View File

@ -125,6 +125,8 @@ class OpenLPWizard(QtGui.QWizard, RegistryProperties):
QtGui.QWizard.NoBackButtonOnStartPage | QtGui.QWizard.NoBackButtonOnLastPage) QtGui.QWizard.NoBackButtonOnStartPage | QtGui.QWizard.NoBackButtonOnLastPage)
if is_macosx(): if is_macosx():
self.setPixmap(QtGui.QWizard.BackgroundPixmap, QtGui.QPixmap(':/wizards/openlp-osx-wizard.png')) self.setPixmap(QtGui.QWizard.BackgroundPixmap, QtGui.QPixmap(':/wizards/openlp-osx-wizard.png'))
else:
self.setWizardStyle(QtGui.QWizard.ModernStyle)
add_welcome_page(self, image) add_welcome_page(self, image)
self.add_custom_pages() self.add_custom_pages()
if self.with_progress_page: if self.with_progress_page:

View File

@ -52,6 +52,7 @@ if not is_win() and not is_macosx():
from xdg import BaseDirectory from xdg import BaseDirectory
XDG_BASE_AVAILABLE = True XDG_BASE_AVAILABLE = True
except ImportError: except ImportError:
BaseDirectory = None
XDG_BASE_AVAILABLE = False XDG_BASE_AVAILABLE = False
from openlp.core.common import translate from openlp.core.common import translate
@ -125,14 +126,25 @@ class HTTPRedirectHandlerFixed(urllib.request.HTTPRedirectHandler):
Special HTTPRedirectHandler used to work around http://bugs.python.org/issue22248 Special HTTPRedirectHandler used to work around http://bugs.python.org/issue22248
(Redirecting to urls with special chars) (Redirecting to urls with special chars)
""" """
def redirect_request(self, req, fp, code, msg, headers, newurl): def redirect_request(self, req, fp, code, msg, headers, new_url):
# Test if the newurl can be decoded to ascii #
"""
Test if the new_url can be decoded to ascii
:param req:
:param fp:
:param code:
:param msg:
:param headers:
:param new_url:
:return:
"""
try: try:
test_url = newurl.encode('latin1').decode('ascii') new_url.encode('latin1').decode('ascii')
fixed_url = newurl fixed_url = new_url
except Exception: except Exception:
# The url could not be decoded to ascii, so we do some url encoding # The url could not be decoded to ascii, so we do some url encoding
fixed_url = urllib.parse.quote(newurl.encode('latin1').decode('utf-8', 'replace'), safe='/:') fixed_url = urllib.parse.quote(new_url.encode('latin1').decode('utf-8', 'replace'), safe='/:')
return super(HTTPRedirectHandlerFixed, self).redirect_request(req, fp, code, msg, headers, fixed_url) return super(HTTPRedirectHandlerFixed, self).redirect_request(req, fp, code, msg, headers, fixed_url)
@ -181,18 +193,18 @@ def get_application_version():
full_version = '%s-bzr%s' % (tag_version.decode('utf-8'), tree_revision.decode('utf-8')) full_version = '%s-bzr%s' % (tag_version.decode('utf-8'), tree_revision.decode('utf-8'))
else: else:
# We're not running the development version, let's use the file. # We're not running the development version, let's use the file.
filepath = AppLocation.get_directory(AppLocation.VersionDir) file_path = AppLocation.get_directory(AppLocation.VersionDir)
filepath = os.path.join(filepath, '.version') file_path = os.path.join(file_path, '.version')
fversion = None version_file = None
try: try:
fversion = open(filepath, 'r') version_file = open(file_path, 'r')
full_version = str(fversion.read()).rstrip() full_version = str(version_file.read()).rstrip()
except IOError: except IOError:
log.exception('Error in version file.') log.exception('Error in version file.')
full_version = '0.0.0-bzr000' full_version = '0.0.0-bzr000'
finally: finally:
if fversion: if version_file:
fversion.close() version_file.close()
bits = full_version.split('-') bits = full_version.split('-')
APPLICATION_VERSION = { APPLICATION_VERSION = {
'full': full_version, 'full': full_version,
@ -211,13 +223,13 @@ def check_latest_version(current_version):
Check the latest version of OpenLP against the version file on the OpenLP Check the latest version of OpenLP against the version file on the OpenLP
site. site.
:param current_version: The current version of OpenLP.
**Rules around versions and version files:** **Rules around versions and version files:**
* If a version number has a build (i.e. -bzr1234), then it is a nightly. * If a version number has a build (i.e. -bzr1234), then it is a nightly.
* If a version number's minor version is an odd number, it is a development release. * If a version number's minor version is an odd number, it is a development release.
* If a version number's minor version is an even number, it is a stable release. * If a version number's minor version is an even number, it is a stable release.
:param current_version: The current version of OpenLP.
""" """
version_string = current_version['full'] version_string = current_version['full']
# set to prod in the distribution config file. # set to prod in the distribution config file.

View File

@ -45,7 +45,7 @@ def try_int(s):
""" """
try: try:
return int(s) return int(s)
except Exception: except (TypeError, ValueError):
return s return s
@ -58,27 +58,23 @@ def natural_sort_key(s):
return list(map(try_int, SPLIT_ALPHA_DIGITS.findall(s))) return list(map(try_int, SPLIT_ALPHA_DIGITS.findall(s)))
def natural_compare(a, b): def natural_sort(seq):
"""
Compare two strings naturally and return the result.
:param a: A string to compare.
:param b: A string to compare.
"""
return cmp(natural_sort_key(a), natural_sort_key(b))
def natural_sort(seq, compare=natural_compare):
""" """
Returns a copy of seq, sorted by natural string sort. Returns a copy of seq, sorted by natural string sort.
:param seq: The sequence to sort.
:param compare: The comparison method to use
:return: The sorted sequence
""" """
import copy import copy
temp = copy.copy(seq) temp = copy.copy(seq)
temp.sort(compare) temp.sort(key=natural_sort_key)
return temp return temp
# NOTE: The following code is a duplicate of the code in openlp/core/utils/__init__.py. Any fix applied here should also # NOTE: The following code is a duplicate of the code in openlp/core/utils/__init__.py. Any fix applied here should also
# be applied there. # be applied there.
ver_file = None
try: try:
# Get the revision of this tree. # Get the revision of this tree.
bzr = Popen(('bzr', 'revno'), stdout=PIPE) bzr = Popen(('bzr', 'revno'), stdout=PIPE)

View File

@ -43,7 +43,7 @@ class TestSettings(TestCase, TestMixin):
""" """
Create the UI Create the UI
""" """
self.get_application() self.setup_application()
self.build_settings() self.build_settings()
def tearDown(self): def tearDown(self):

View File

@ -52,7 +52,7 @@ class TestImageManager(TestCase, TestMixin):
Create the UI Create the UI
""" """
Registry.create() Registry.create()
self.get_application() self.setup_application()
ScreenList.create(self.app.desktop()) ScreenList.create(self.app.desktop())
self.image_manager = ImageManager() self.image_manager = ImageManager()
self.lock = Lock() self.lock = Lock()

View File

@ -29,44 +29,78 @@
""" """
Package to test the openlp.core.ui.firsttimeform package. Package to test the openlp.core.ui.firsttimeform package.
""" """
from configparser import ConfigParser
from unittest import TestCase from unittest import TestCase
from openlp.core.common import Registry from openlp.core.common import Registry
from openlp.core.ui.firsttimeform import FirstTimeForm from openlp.core.ui.firsttimeform import FirstTimeForm
from tests.functional import MagicMock from tests.functional import MagicMock, patch
from tests.helpers.testmixin import TestMixin from tests.helpers.testmixin import TestMixin
FAKE_CONFIG = b"""
[general]
base url = http://example.com/frw/
[songs]
directory = songs
[bibles]
directory = bibles
[themes]
directory = themes
"""
class TestFirstTimeForm(TestCase, TestMixin): class TestFirstTimeForm(TestCase, TestMixin):
def setUp(self): def setUp(self):
screens = MagicMock() self.setup_application()
self.get_application() self.app.setApplicationVersion('0.0')
Registry.create() Registry.create()
Registry().register('application', self.app) Registry().register('application', self.app)
self.first_time_form = FirstTimeForm(screens)
def access_to_config_test(self): def basic_initialise_test(self):
""" """
Test if we can access the First Time Form's config file Test if we can intialise the FirstTimeForm without a config file
""" """
# GIVEN A new First Time Form instance. # GIVEN: A mocked get_web_page, a First Time Wizard and an expected screen object
with patch('openlp.core.ui.firsttimeform.get_web_page') as mocked_get_web_page:
first_time_form = FirstTimeForm(None)
expected_screens = MagicMock()
expected_web_url = 'http://openlp.org/files/frw/'
expected_user_agent = 'OpenLP/0.0'
mocked_get_web_page.return_value = None
# WHEN The default First Time Form is built. # WHEN: The First Time Wizard is initialised
first_time_form.initialize(expected_screens)
# THEN The First Time Form web configuration file should be accessable. # THEN: The First Time Form web configuration file should be accessible and parseable
self.assertTrue(self.first_time_form.web_access, self.assertEqual(expected_screens, first_time_form.screens, 'The screens should be correct')
'First Time Wizard\'s web configuration file should be available') self.assertEqual(expected_web_url, first_time_form.web, 'The base path of the URL should be correct')
self.assertIsInstance(first_time_form.config, ConfigParser, 'The config object should be a ConfigParser')
mocked_get_web_page.assert_called_with(expected_web_url + 'download.cfg',
header=('User-Agent', expected_user_agent))
def parsable_config_test(self): def config_initialise_test(self):
""" """
Test if the First Time Form's config file is parsable Test if we can intialise the FirstTimeForm with a config file
""" """
# GIVEN A new First Time Form instance. # GIVEN: A mocked get_web_page, a First Time Wizard and an expected screen object
with patch('openlp.core.ui.firsttimeform.get_web_page') as mocked_get_web_page:
first_time_form = FirstTimeForm(None)
expected_web_url = 'http://openlp.org/files/frw/'
expected_songs_url = 'http://example.com/frw/songs/'
expected_bibles_url = 'http://example.com/frw/bibles/'
expected_themes_url = 'http://example.com/frw/themes/'
expected_user_agent = 'OpenLP/0.0'
mocked_get_web_page.return_value.read.return_value = FAKE_CONFIG
# WHEN The default First Time Form is built. # WHEN: The First Time Wizard is initialised
first_time_form.initialize(MagicMock())
# THEN The First Time Form web configuration file should be parsable # THEN: The First Time Form web configuration file should be accessible and parseable
self.assertTrue(self.first_time_form.songs_url, self.assertIsInstance(first_time_form.config, ConfigParser, 'The config object should be a ConfigParser')
'First Time Wizard\'s web configuration file should be parsable') mocked_get_web_page.assert_called_with(expected_web_url + 'download.cfg',
header=('User-Agent', expected_user_agent))
self.assertEqual(expected_songs_url, first_time_form.songs_url, 'The songs URL should be correct')
self.assertEqual(expected_bibles_url, first_time_form.bibles_url, 'The bibles URL should be correct')
self.assertEqual(expected_themes_url, first_time_form.themes_url, 'The themes URL should be correct')

View File

@ -29,9 +29,7 @@
""" """
Package to test the openlp.core.ui.formattingtagsform package. Package to test the openlp.core.ui.formattingtagsform package.
""" """
from PyQt4 import QtGui
from unittest import TestCase from unittest import TestCase
from openlp.core.common import translate
from tests.functional import MagicMock, patch, call from tests.functional import MagicMock, patch, call

View File

@ -27,8 +27,38 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
""" """
The :mod:`resources` module contains a bunch of resources for OpenLP. Package to test the openlp.core.ui.listpreviewwidget package.
DO NOT REMOVE THIS FILE, IT IS REQUIRED FOR INCLUDING THE RESOURCES ON SOME
PLATFORMS!
""" """
from unittest import TestCase
from openlp.core.ui.listpreviewwidget import ListPreviewWidget
from tests.functional import patch
class TestListPreviewWidget(TestCase):
def setUp(self):
"""
Mock out stuff for all the tests
"""
self.setup_patcher = patch('openlp.core.ui.listpreviewwidget.ListPreviewWidget._setup')
self.mocked_setup = self.setup_patcher.start()
def tearDown(self):
"""
Remove the mocks
"""
self.setup_patcher.stop()
def new_list_preview_widget_test(self):
"""
Test that creating an instance of ListPreviewWidget works
"""
# GIVEN: A ListPreviewWidget class
# WHEN: An object is created
list_preview_widget = ListPreviewWidget(None, 1)
# THEN: The object is not None, and the _setup() method was called.
self.assertIsNotNone(list_preview_widget, 'The ListPreviewWidget object should not be None')
self.mocked_setup.assert_called_with(1)

View File

@ -46,7 +46,7 @@ class TestMainWindow(TestCase, TestMixin):
def setUp(self): def setUp(self):
Registry.create() Registry.create()
self.registry = Registry() self.registry = Registry()
self.get_application() self.setup_application()
# Mock cursor busy/normal methods. # Mock cursor busy/normal methods.
self.app.set_busy_cursor = MagicMock() self.app.set_busy_cursor = MagicMock()
self.app.set_normal_cursor = MagicMock() self.app.set_normal_cursor = MagicMock()

View File

@ -51,7 +51,7 @@ class TestImpressController(TestCase, TestMixin):
""" """
Set up the patches and mocks need for all tests. Set up the patches and mocks need for all tests.
""" """
self.get_application() self.setup_application()
self.build_settings() self.build_settings()
self.mock_plugin = MagicMock() self.mock_plugin = MagicMock()
self.temp_folder = mkdtemp() self.temp_folder = mkdtemp()

View File

@ -51,7 +51,7 @@ class TestMediaItem(TestCase, TestMixin):
with patch('openlp.plugins.presentations.lib.mediaitem.MediaManagerItem._setup'), \ with patch('openlp.plugins.presentations.lib.mediaitem.MediaManagerItem._setup'), \
patch('openlp.plugins.presentations.lib.mediaitem.PresentationMediaItem.setup_item'): patch('openlp.plugins.presentations.lib.mediaitem.PresentationMediaItem.setup_item'):
self.media_item = PresentationMediaItem(None, MagicMock, MagicMock()) self.media_item = PresentationMediaItem(None, MagicMock, MagicMock())
self.get_application() self.setup_application()
def build_file_mask_string_test(self): def build_file_mask_string_test(self):
""" """

View File

@ -61,7 +61,7 @@ class TestPdfController(TestCase, TestMixin):
""" """
Set up the components need for all tests. Set up the components need for all tests.
""" """
self.get_application() self.setup_application()
self.build_settings() self.build_settings()
# Mocked out desktop object # Mocked out desktop object
self.desktop = MagicMock() self.desktop = MagicMock()

View File

@ -55,7 +55,7 @@ class TestPowerpointController(TestCase, TestMixin):
""" """
Set up the patches and mocks need for all tests. Set up the patches and mocks need for all tests.
""" """
self.get_application() self.setup_application()
self.build_settings() self.build_settings()
self.mock_plugin = MagicMock() self.mock_plugin = MagicMock()
self.temp_folder = mkdtemp() self.temp_folder = mkdtemp()
@ -92,7 +92,7 @@ class TestPowerpointDocument(TestCase, TestMixin):
""" """
Set up the patches and mocks need for all tests. Set up the patches and mocks need for all tests.
""" """
self.get_application() self.setup_application()
self.build_settings() self.build_settings()
self.mock_plugin = MagicMock() self.mock_plugin = MagicMock()
self.temp_folder = mkdtemp() self.temp_folder = mkdtemp()

View File

@ -59,7 +59,7 @@ class TestPptviewController(TestCase, TestMixin):
""" """
Set up the patches and mocks need for all tests. Set up the patches and mocks need for all tests.
""" """
self.get_application() self.setup_application()
self.build_settings() self.build_settings()
self.mock_plugin = MagicMock() self.mock_plugin = MagicMock()
self.temp_folder = mkdtemp() self.temp_folder = mkdtemp()

View File

@ -63,7 +63,7 @@ class TestRemoteTab(TestCase, TestMixin):
""" """
Create the UI Create the UI
""" """
self.get_application() self.setup_application()
self.build_settings() self.build_settings()
Settings().extend_default_settings(__default_settings__) Settings().extend_default_settings(__default_settings__)
self.parent = QtGui.QMainWindow() self.parent = QtGui.QMainWindow()

View File

@ -61,7 +61,7 @@ class TestRouter(TestCase, TestMixin):
""" """
Create the UI Create the UI
""" """
self.get_application() self.setup_application()
self.build_settings() self.build_settings()
Settings().extend_default_settings(__default_settings__) Settings().extend_default_settings(__default_settings__)
self.router = HttpRouter() self.router = HttpRouter()

View File

@ -29,7 +29,7 @@ class TestMediaItem(TestCase, TestMixin):
self.media_item = SongMediaItem(None, MagicMock()) self.media_item = SongMediaItem(None, MagicMock())
self.media_item.display_songbook = False self.media_item.display_songbook = False
self.media_item.display_copyright_symbol = False self.media_item.display_copyright_symbol = False
self.get_application() self.setup_application()
self.build_settings() self.build_settings()
QtCore.QLocale.setDefault(QtCore.QLocale('en_GB')) QtCore.QLocale.setDefault(QtCore.QLocale('en_GB'))

View File

@ -41,7 +41,6 @@ from openlp.plugins.songs.lib.importers.openlyrics import OpenLyricsImport
from openlp.plugins.songs.lib.importers.songimport import SongImport from openlp.plugins.songs.lib.importers.songimport import SongImport
from openlp.plugins.songs.lib.openlyricsxml import OpenLyrics from openlp.plugins.songs.lib.openlyricsxml import OpenLyrics
from openlp.core.common import Registry, Settings from openlp.core.common import Registry, Settings
from openlp.core.lib import FormattingTags
TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
@ -83,7 +82,7 @@ class TestOpenLyricsImport(TestCase, TestMixin):
""" """
Create the registry Create the registry
""" """
self.get_application() self.setup_application()
Registry.create() Registry.create()
self.build_settings() self.build_settings()

View File

@ -37,8 +37,11 @@ from openlp.core.common import Settings
class TestMixin(object): class TestMixin(object):
"""
The :class:`TestMixin` class provides test with extra functionality
"""
def get_application(self): def setup_application(self):
""" """
Build or reuse the Application object Build or reuse the Application object
""" """

View File

@ -43,7 +43,7 @@ from tests.interfaces import MagicMock, patch
class TestHistoryComboBox(TestCase, TestMixin): class TestHistoryComboBox(TestCase, TestMixin):
def setUp(self): def setUp(self):
Registry.create() Registry.create()
self.get_application() self.setup_application()
self.main_window = QtGui.QMainWindow() self.main_window = QtGui.QMainWindow()
Registry().register('main_window', self.main_window) Registry().register('main_window', self.main_window)
self.combo = HistoryComboBox(self.main_window) self.combo = HistoryComboBox(self.main_window)

View File

@ -58,7 +58,7 @@ class TestPluginManager(TestCase, TestMixin):
Settings().setValue('advanced/data path', self.temp_dir) Settings().setValue('advanced/data path', self.temp_dir)
Registry.create() Registry.create()
Registry().register('service_list', MagicMock()) Registry().register('service_list', MagicMock())
self.get_application() self.setup_application()
self.main_window = QtGui.QMainWindow() self.main_window = QtGui.QMainWindow()
Registry().register('main_window', self.main_window) Registry().register('main_window', self.main_window)

View File

@ -57,7 +57,7 @@ class TestSearchEdit(TestCase, TestMixin):
Create the UI Create the UI
""" """
Registry.create() Registry.create()
self.get_application() self.setup_application()
self.main_window = QtGui.QMainWindow() self.main_window = QtGui.QMainWindow()
Registry().register('main_window', self.main_window) Registry().register('main_window', self.main_window)

View File

@ -46,7 +46,7 @@ class TestStartFileRenameForm(TestCase, TestMixin):
Create the UI Create the UI
""" """
Registry.create() Registry.create()
self.get_application() self.setup_application()
self.main_window = QtGui.QMainWindow() self.main_window = QtGui.QMainWindow()
Registry().register('main_window', self.main_window) Registry().register('main_window', self.main_window)
self.form = filerenameform.FileRenameForm() self.form = filerenameform.FileRenameForm()

View File

@ -49,7 +49,7 @@ class TestListPreviewWidget(TestCase, TestMixin):
Create the UI. Create the UI.
""" """
Registry.create() Registry.create()
self.get_application() self.setup_application()
self.main_window = QtGui.QMainWindow() self.main_window = QtGui.QMainWindow()
self.image = QtGui.QImage(1, 1, QtGui.QImage.Format_RGB32) self.image = QtGui.QImage(1, 1, QtGui.QImage.Format_RGB32)
self.image_manager = MagicMock() self.image_manager = MagicMock()

View File

@ -46,7 +46,7 @@ class TestMainWindow(TestCase, TestMixin):
""" """
Registry.create() Registry.create()
self.registry = Registry() self.registry = Registry()
self.get_application() self.setup_application()
# Mock cursor busy/normal methods. # Mock cursor busy/normal methods.
self.app.set_busy_cursor = MagicMock() self.app.set_busy_cursor = MagicMock()
self.app.set_normal_cursor = MagicMock() self.app.set_normal_cursor = MagicMock()

View File

@ -46,7 +46,7 @@ class TestServiceManager(TestCase, TestMixin):
Create the UI Create the UI
""" """
Registry.create() Registry.create()
self.get_application() self.setup_application()
ScreenList.create(self.app.desktop()) ScreenList.create(self.app.desktop())
Registry().register('application', MagicMock()) Registry().register('application', MagicMock())
with patch('openlp.core.lib.PluginManager'): with patch('openlp.core.lib.PluginManager'):

View File

@ -46,7 +46,7 @@ class TestStartNoteDialog(TestCase, TestMixin):
Create the UI Create the UI
""" """
Registry.create() Registry.create()
self.get_application() self.setup_application()
self.main_window = QtGui.QMainWindow() self.main_window = QtGui.QMainWindow()
Registry().register('main_window', self.main_window) Registry().register('main_window', self.main_window)
self.form = servicenoteform.ServiceNoteForm() self.form = servicenoteform.ServiceNoteForm()

View File

@ -59,7 +59,7 @@ class TestSettingsForm(TestCase, TestMixin):
self.dummy2 = MagicMock() self.dummy2 = MagicMock()
self.dummy3 = MagicMock() self.dummy3 = MagicMock()
self.desktop = MagicMock() self.desktop = MagicMock()
self.get_application() self.setup_application()
self.desktop.primaryScreen.return_value = SCREEN['primary'] self.desktop.primaryScreen.return_value = SCREEN['primary']
self.desktop.screenCount.return_value = SCREEN['number'] self.desktop.screenCount.return_value = SCREEN['number']
self.desktop.screenGeometry.return_value = SCREEN['size'] self.desktop.screenGeometry.return_value = SCREEN['size']

View File

@ -46,7 +46,7 @@ class TestShortcutform(TestCase, TestMixin):
Create the UI Create the UI
""" """
Registry.create() Registry.create()
self.get_application() self.setup_application()
self.main_window = QtGui.QMainWindow() self.main_window = QtGui.QMainWindow()
Registry().register('main_window', self.main_window) Registry().register('main_window', self.main_window)
self.form = ShortcutListForm() self.form = ShortcutListForm()

View File

@ -46,7 +46,7 @@ class TestStartTimeDialog(TestCase, TestMixin):
Create the UI Create the UI
""" """
Registry.create() Registry.create()
self.get_application() self.setup_application()
self.main_window = QtGui.QMainWindow() self.main_window = QtGui.QMainWindow()
Registry().register('main_window', self.main_window) Registry().register('main_window', self.main_window)
self.form = starttimeform.StartTimeForm() self.form = starttimeform.StartTimeForm()

View File

@ -46,7 +46,7 @@ class TestThemeManager(TestCase, TestMixin):
Create the UI Create the UI
""" """
self.build_settings() self.build_settings()
self.get_application() self.setup_application()
Registry.create() Registry.create()
self.theme_manager = ThemeManager() self.theme_manager = ThemeManager()

View File

@ -46,7 +46,7 @@ class TestUtils(TestCase, TestMixin):
""" """
Some pre-test setup required. Some pre-test setup required.
""" """
self.get_application() self.setup_application()
def is_not_image_empty_test(self): def is_not_image_empty_test(self):
""" """

View File

@ -50,7 +50,7 @@ class TestEditCustomForm(TestCase, TestMixin):
Create the UI Create the UI
""" """
Registry.create() Registry.create()
self.get_application() self.setup_application()
self.main_window = QtGui.QMainWindow() self.main_window = QtGui.QMainWindow()
Registry().register('main_window', self.main_window) Registry().register('main_window', self.main_window)
media_item = MagicMock() media_item = MagicMock()

View File

@ -48,7 +48,7 @@ class TestEditCustomSlideForm(TestCase, TestMixin):
Create the UI Create the UI
""" """
Registry.create() Registry.create()
self.get_application() self.setup_application()
self.main_window = QtGui.QMainWindow() self.main_window = QtGui.QMainWindow()
Registry().register('main_window', self.main_window) Registry().register('main_window', self.main_window)
self.form = EditCustomSlideForm() self.form = EditCustomSlideForm()

View File

@ -54,7 +54,7 @@ class TestMediaClipSelectorForm(TestCase, TestMixin):
Create the UI Create the UI
""" """
Registry.create() Registry.create()
self.get_application() self.setup_application()
self.main_window = QtGui.QMainWindow() self.main_window = QtGui.QMainWindow()
Registry().register('main_window', self.main_window) Registry().register('main_window', self.main_window)
# Mock VLC so we don't actually use it # Mock VLC so we don't actually use it

View File

@ -48,7 +48,7 @@ class TestAuthorsForm(TestCase, TestMixin):
Create the UI Create the UI
""" """
Registry.create() Registry.create()
self.get_application() self.setup_application()
self.main_window = QtGui.QMainWindow() self.main_window = QtGui.QMainWindow()
Registry().register('main_window', self.main_window) Registry().register('main_window', self.main_window)
self.form = AuthorsForm() self.form = AuthorsForm()

View File

@ -49,7 +49,7 @@ class TestEditSongForm(TestCase, TestMixin):
Create the UI Create the UI
""" """
Registry.create() Registry.create()
self.get_application() self.setup_application()
self.main_window = QtGui.QMainWindow() self.main_window = QtGui.QMainWindow()
Registry().register('main_window', self.main_window) Registry().register('main_window', self.main_window)
Registry().register('theme_manager', MagicMock()) Registry().register('theme_manager', MagicMock())

View File

@ -48,7 +48,7 @@ class TestEditVerseForm(TestCase, TestMixin):
Create the UI Create the UI
""" """
Registry.create() Registry.create()
self.get_application() self.setup_application()
self.main_window = QtGui.QMainWindow() self.main_window = QtGui.QMainWindow()
Registry().register('main_window', self.main_window) Registry().register('main_window', self.main_window)
self.form = EditVerseForm() self.form = EditVerseForm()

View File

@ -48,7 +48,7 @@ class TestTopicsForm(TestCase, TestMixin):
Create the UI Create the UI
""" """
Registry.create() Registry.create()
self.get_application() self.setup_application()
self.main_window = QtGui.QMainWindow() self.main_window = QtGui.QMainWindow()
Registry().register('main_window', self.main_window) Registry().register('main_window', self.main_window)
self.form = TopicsForm() self.form = TopicsForm()