From 86cf77db83e7f98f0f7d23955ce6a4c52bf35d06 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Tue, 26 Sep 2017 18:21:54 +0100 Subject: [PATCH 01/19] add returns --- openlp/plugins/bibles/endpoint.py | 4 ++-- openlp/plugins/custom/endpoint.py | 4 ++-- openlp/plugins/images/endpoint.py | 4 ++-- openlp/plugins/media/endpoint.py | 4 ++-- openlp/plugins/presentations/endpoint.py | 4 ++-- openlp/plugins/songs/endpoint.py | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/openlp/plugins/bibles/endpoint.py b/openlp/plugins/bibles/endpoint.py index 08a945e7c..4d34eb966 100644 --- a/openlp/plugins/bibles/endpoint.py +++ b/openlp/plugins/bibles/endpoint.py @@ -62,7 +62,7 @@ def bibles_service(request): :param request: The http request object. """ - service(request, 'bibles', log) + return service(request, 'bibles', log) @api_bibles_endpoint.route('bibles/search') @@ -95,6 +95,6 @@ def bibles_service_api(request): :param request: The http request object. """ try: - search(request, 'bibles', log) + return search(request, 'bibles', log) except NotFound: return {'results': {'items': []}} diff --git a/openlp/plugins/custom/endpoint.py b/openlp/plugins/custom/endpoint.py index 687ffaa1b..ca5c39088 100644 --- a/openlp/plugins/custom/endpoint.py +++ b/openlp/plugins/custom/endpoint.py @@ -62,7 +62,7 @@ def custom_service(request): :param request: The http request object. """ - service(request, 'custom', log) + return service(request, 'custom', log) @api_custom_endpoint.route('custom/search') @@ -95,6 +95,6 @@ def custom_service_api(request): :param request: The http request object. """ try: - search(request, 'custom', log) + return search(request, 'custom', log) except NotFound: return {'results': {'items': []}} diff --git a/openlp/plugins/images/endpoint.py b/openlp/plugins/images/endpoint.py index ca82da00a..05c1e64b4 100644 --- a/openlp/plugins/images/endpoint.py +++ b/openlp/plugins/images/endpoint.py @@ -75,7 +75,7 @@ def images_service(request): :param request: The http request object. """ - service(request, 'images', log) + return service(request, 'images', log) @api_images_endpoint.route('images/search') @@ -108,6 +108,6 @@ def images_service_api(request): :param request: The http request object. """ try: - search(request, 'images', log) + return search(request, 'images', log) except NotFound: return {'results': {'items': []}} diff --git a/openlp/plugins/media/endpoint.py b/openlp/plugins/media/endpoint.py index 014c3c790..c7b703358 100644 --- a/openlp/plugins/media/endpoint.py +++ b/openlp/plugins/media/endpoint.py @@ -62,7 +62,7 @@ def media_service(request): :param request: The http request object. """ - service(request, 'media', log) + return service(request, 'media', log) @api_media_endpoint.route('media/search') @@ -95,6 +95,6 @@ def media_service_api(request): :param request: The http request object. """ try: - search(request, 'media', log) + return search(request, 'media', log) except NotFound: return {'results': {'items': []}} diff --git a/openlp/plugins/presentations/endpoint.py b/openlp/plugins/presentations/endpoint.py index ce622083c..99c828b4b 100644 --- a/openlp/plugins/presentations/endpoint.py +++ b/openlp/plugins/presentations/endpoint.py @@ -76,7 +76,7 @@ def presentations_service(request): :param request: The http request object. """ - service(request, 'presentations', log) + return service(request, 'presentations', log) @api_presentations_endpoint.route('presentations/search') @@ -109,6 +109,6 @@ def presentations_service_api(request): :param request: The http request object. """ try: - search(request, 'presentations', log) + return search(request, 'presentations', log) except NotFound: return {'results': {'items': []}} diff --git a/openlp/plugins/songs/endpoint.py b/openlp/plugins/songs/endpoint.py index 8711fcccd..6bd521872 100644 --- a/openlp/plugins/songs/endpoint.py +++ b/openlp/plugins/songs/endpoint.py @@ -62,7 +62,7 @@ def songs_service(request): :param request: The http request object. """ - service(request, 'songs', log) + return service(request, 'songs', log) @api_songs_endpoint.route('songs/search') @@ -95,6 +95,6 @@ def songs_service_api(request): :param request: The http request object. """ try: - search(request, 'songs', log) + return search(request, 'songs', log) except NotFound: return {'results': {'items': []}} From 9fc7f1b39b3d1b5df488050e192185518d671844 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Tue, 26 Sep 2017 18:48:01 +0100 Subject: [PATCH 02/19] restart removal --- openlp/plugins/remotes/endpoint.py | 46 -------------------------- openlp/plugins/remotes/remoteplugin.py | 7 ++-- 2 files changed, 3 insertions(+), 50 deletions(-) delete mode 100644 openlp/plugins/remotes/endpoint.py diff --git a/openlp/plugins/remotes/endpoint.py b/openlp/plugins/remotes/endpoint.py deleted file mode 100644 index a9b0d0815..000000000 --- a/openlp/plugins/remotes/endpoint.py +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### -import logging - -import os - -from openlp.core.api.http.endpoint import Endpoint -from openlp.core.api.endpoint.core import TRANSLATED_STRINGS -from openlp.core.common import AppLocation - - -static_dir = os.path.join(str(AppLocation.get_section_data_path('remotes'))) - -log = logging.getLogger(__name__) - -remote_endpoint = Endpoint('remote', template_dir=static_dir, static_dir=static_dir) - - -@remote_endpoint.route('{view}') -def index(request, view): - """ - Handles requests for /remotes url - - :param request: The http request object. - :param view: The view name to be servered. - """ - return remote_endpoint.render_template('{view}.mako'.format(view=view), **TRANSLATED_STRINGS) diff --git a/openlp/plugins/remotes/remoteplugin.py b/openlp/plugins/remotes/remoteplugin.py index 1344c66d1..4974e451b 100644 --- a/openlp/plugins/remotes/remoteplugin.py +++ b/openlp/plugins/remotes/remoteplugin.py @@ -20,16 +20,15 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -import logging -import os import time - from PyQt5 import QtCore, QtWidgets +import logging + +from openlp.core.api.endpoint.remote import remote_endpoint from openlp.core.api.http import register_endpoint from openlp.core.common import AppLocation, Registry, Settings, OpenLPMixin, UiStrings, check_directory_exists from openlp.core.lib import Plugin, StringContent, translate, build_icon -from openlp.plugins.remotes.endpoint import remote_endpoint from openlp.plugins.remotes.deploy import download_and_check, download_sha256 log = logging.getLogger(__name__) From 5b2ac0f97b7f655c47e33eb00e308ac9ea862abb Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Tue, 26 Sep 2017 18:49:41 +0100 Subject: [PATCH 03/19] more moves --- openlp/plugins/remotes/deploy.py | 69 ------------------- openlp/plugins/remotes/remoteplugin.py | 6 +- .../openlp_plugins/remotes/test_deploy.py | 4 +- 3 files changed, 4 insertions(+), 75 deletions(-) delete mode 100644 openlp/plugins/remotes/deploy.py diff --git a/openlp/plugins/remotes/deploy.py b/openlp/plugins/remotes/deploy.py deleted file mode 100644 index 44c628837..000000000 --- a/openlp/plugins/remotes/deploy.py +++ /dev/null @@ -1,69 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### -""" -Download and "install" the remote web client -""" -import os -from zipfile import ZipFile - -from openlp.core.common import AppLocation, Registry -from openlp.core.common.httputils import url_get_file, get_web_page, get_url_file_size - - -def deploy_zipfile(app_root, zip_name): - """ - Process the downloaded zip file and add to the correct directory - - :param zip_name: the zip file to be processed - :param app_root: the directory where the zip get expanded to - - :return: None - """ - zip_file = os.path.join(app_root, zip_name) - web_zip = ZipFile(zip_file) - web_zip.extractall(app_root) - - -def download_sha256(): - """ - Download the config file to extract the sha256 and version number - """ - user_agent = 'OpenLP/' + Registry().get('application').applicationVersion() - try: - web_config = get_web_page('https://get.openlp.org/webclient/download.cfg', headers={'User-Agent': user_agent}) - except ConnectionError: - return False - file_bits = web_config.split() - return file_bits[0], file_bits[2] - - -def download_and_check(callback=None): - """ - Download the web site and deploy it. - """ - sha256, version = download_sha256() - file_size = get_url_file_size('https://get.openlp.org/webclient/site.zip') - callback.setRange(0, file_size) - if url_get_file(callback, '{host}{name}'.format(host='https://get.openlp.org/webclient/', name='site.zip'), - AppLocation.get_section_data_path('remotes') / 'site.zip', - sha256=sha256): - deploy_zipfile(str(AppLocation.get_section_data_path('remotes')), 'site.zip') diff --git a/openlp/plugins/remotes/remoteplugin.py b/openlp/plugins/remotes/remoteplugin.py index 4974e451b..c223eb99e 100644 --- a/openlp/plugins/remotes/remoteplugin.py +++ b/openlp/plugins/remotes/remoteplugin.py @@ -20,16 +20,16 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +import logging import time + from PyQt5 import QtCore, QtWidgets -import logging - +from openlp.core.api.deploy import download_and_check, download_sha256 from openlp.core.api.endpoint.remote import remote_endpoint from openlp.core.api.http import register_endpoint from openlp.core.common import AppLocation, Registry, Settings, OpenLPMixin, UiStrings, check_directory_exists from openlp.core.lib import Plugin, StringContent, translate, build_icon -from openlp.plugins.remotes.deploy import download_and_check, download_sha256 log = logging.getLogger(__name__) __default_settings__ = { diff --git a/tests/functional/openlp_plugins/remotes/test_deploy.py b/tests/functional/openlp_plugins/remotes/test_deploy.py index 1909b94fd..14447a97e 100644 --- a/tests/functional/openlp_plugins/remotes/test_deploy.py +++ b/tests/functional/openlp_plugins/remotes/test_deploy.py @@ -22,12 +22,10 @@ import os import shutil - from tempfile import mkdtemp from unittest import TestCase -from openlp.plugins.remotes.deploy import deploy_zipfile - +from openlp.core.api.deploy import deploy_zipfile TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources')) From 64ba30b24dced2acb9fabf32f143bf28891736a7 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Tue, 26 Sep 2017 18:51:09 +0100 Subject: [PATCH 04/19] add files --- openlp/core/api/deploy.py | 69 ++++++++++++++++++++++++++++++ openlp/core/api/endpoint/remote.py | 46 ++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 openlp/core/api/deploy.py create mode 100644 openlp/core/api/endpoint/remote.py diff --git a/openlp/core/api/deploy.py b/openlp/core/api/deploy.py new file mode 100644 index 000000000..44c628837 --- /dev/null +++ b/openlp/core/api/deploy.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2017 OpenLP Developers # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +Download and "install" the remote web client +""" +import os +from zipfile import ZipFile + +from openlp.core.common import AppLocation, Registry +from openlp.core.common.httputils import url_get_file, get_web_page, get_url_file_size + + +def deploy_zipfile(app_root, zip_name): + """ + Process the downloaded zip file and add to the correct directory + + :param zip_name: the zip file to be processed + :param app_root: the directory where the zip get expanded to + + :return: None + """ + zip_file = os.path.join(app_root, zip_name) + web_zip = ZipFile(zip_file) + web_zip.extractall(app_root) + + +def download_sha256(): + """ + Download the config file to extract the sha256 and version number + """ + user_agent = 'OpenLP/' + Registry().get('application').applicationVersion() + try: + web_config = get_web_page('https://get.openlp.org/webclient/download.cfg', headers={'User-Agent': user_agent}) + except ConnectionError: + return False + file_bits = web_config.split() + return file_bits[0], file_bits[2] + + +def download_and_check(callback=None): + """ + Download the web site and deploy it. + """ + sha256, version = download_sha256() + file_size = get_url_file_size('https://get.openlp.org/webclient/site.zip') + callback.setRange(0, file_size) + if url_get_file(callback, '{host}{name}'.format(host='https://get.openlp.org/webclient/', name='site.zip'), + AppLocation.get_section_data_path('remotes') / 'site.zip', + sha256=sha256): + deploy_zipfile(str(AppLocation.get_section_data_path('remotes')), 'site.zip') diff --git a/openlp/core/api/endpoint/remote.py b/openlp/core/api/endpoint/remote.py new file mode 100644 index 000000000..a9b0d0815 --- /dev/null +++ b/openlp/core/api/endpoint/remote.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2017 OpenLP Developers # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +import logging + +import os + +from openlp.core.api.http.endpoint import Endpoint +from openlp.core.api.endpoint.core import TRANSLATED_STRINGS +from openlp.core.common import AppLocation + + +static_dir = os.path.join(str(AppLocation.get_section_data_path('remotes'))) + +log = logging.getLogger(__name__) + +remote_endpoint = Endpoint('remote', template_dir=static_dir, static_dir=static_dir) + + +@remote_endpoint.route('{view}') +def index(request, view): + """ + Handles requests for /remotes url + + :param request: The http request object. + :param view: The view name to be servered. + """ + return remote_endpoint.render_template('{view}.mako'.format(view=view), **TRANSLATED_STRINGS) From b783783a297362f1200f44b73b50311c2b978e00 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Tue, 26 Sep 2017 21:33:58 +0100 Subject: [PATCH 05/19] add files --- .../openlp_plugins/remotes/__init__.py | 21 ------- .../openlp_plugins/remotes/test_deploy.py | 62 ------------------- 2 files changed, 83 deletions(-) delete mode 100644 tests/functional/openlp_plugins/remotes/__init__.py delete mode 100644 tests/functional/openlp_plugins/remotes/test_deploy.py diff --git a/tests/functional/openlp_plugins/remotes/__init__.py b/tests/functional/openlp_plugins/remotes/__init__.py deleted file mode 100644 index ea62548f4..000000000 --- a/tests/functional/openlp_plugins/remotes/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### diff --git a/tests/functional/openlp_plugins/remotes/test_deploy.py b/tests/functional/openlp_plugins/remotes/test_deploy.py deleted file mode 100644 index 14447a97e..000000000 --- a/tests/functional/openlp_plugins/remotes/test_deploy.py +++ /dev/null @@ -1,62 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -import os -import shutil -from tempfile import mkdtemp -from unittest import TestCase - -from openlp.core.api.deploy import deploy_zipfile - -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources')) - - -class TestRemoteDeploy(TestCase): - """ - Test the Remote plugin deploy functions - """ - - def setUp(self): - """ - Setup for tests - """ - self.app_root = mkdtemp() - - def tearDown(self): - """ - Clean up after tests - """ - shutil.rmtree(self.app_root) - - def test_deploy_zipfile(self): - """ - Remote Deploy tests - test the dummy zip file is processed correctly - """ - # GIVEN: A new downloaded zip file - zip_file = os.path.join(TEST_PATH, 'remotes', 'site.zip') - app_root = os.path.join(self.app_root, 'site.zip') - shutil.copyfile(zip_file, app_root) - # WHEN: I process the zipfile - deploy_zipfile(self.app_root, 'site.zip') - - # THEN test if www directory has been created - self.assertTrue(os.path.isdir(os.path.join(self.app_root, 'www')), 'We should have a www directory') From 4451b65f04c2f6490fdf30902a3e3942d2565e8e Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Tue, 26 Sep 2017 21:34:08 +0100 Subject: [PATCH 06/19] add files2 --- .../functional/openlp_core_api/test_deploy.py | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 tests/functional/openlp_core_api/test_deploy.py diff --git a/tests/functional/openlp_core_api/test_deploy.py b/tests/functional/openlp_core_api/test_deploy.py new file mode 100644 index 000000000..14447a97e --- /dev/null +++ b/tests/functional/openlp_core_api/test_deploy.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2017 OpenLP Developers # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### + +import os +import shutil +from tempfile import mkdtemp +from unittest import TestCase + +from openlp.core.api.deploy import deploy_zipfile + +TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources')) + + +class TestRemoteDeploy(TestCase): + """ + Test the Remote plugin deploy functions + """ + + def setUp(self): + """ + Setup for tests + """ + self.app_root = mkdtemp() + + def tearDown(self): + """ + Clean up after tests + """ + shutil.rmtree(self.app_root) + + def test_deploy_zipfile(self): + """ + Remote Deploy tests - test the dummy zip file is processed correctly + """ + # GIVEN: A new downloaded zip file + zip_file = os.path.join(TEST_PATH, 'remotes', 'site.zip') + app_root = os.path.join(self.app_root, 'site.zip') + shutil.copyfile(zip_file, app_root) + # WHEN: I process the zipfile + deploy_zipfile(self.app_root, 'site.zip') + + # THEN test if www directory has been created + self.assertTrue(os.path.isdir(os.path.join(self.app_root, 'www')), 'We should have a www directory') From f58d1047db8f66ded0b82605495c63e266635b4f Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Tue, 26 Sep 2017 22:04:39 +0100 Subject: [PATCH 07/19] move endpoint --- openlp/core/api/endpoint/remote.py | 7 +------ openlp/core/api/endpoint/service.py | 2 +- openlp/core/api/http/server.py | 3 +++ openlp/plugins/songs/endpoint.py | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/openlp/core/api/endpoint/remote.py b/openlp/core/api/endpoint/remote.py index a9b0d0815..4741ada15 100644 --- a/openlp/core/api/endpoint/remote.py +++ b/openlp/core/api/endpoint/remote.py @@ -21,18 +21,13 @@ ############################################################################### import logging -import os - from openlp.core.api.http.endpoint import Endpoint from openlp.core.api.endpoint.core import TRANSLATED_STRINGS -from openlp.core.common import AppLocation -static_dir = os.path.join(str(AppLocation.get_section_data_path('remotes'))) - log = logging.getLogger(__name__) -remote_endpoint = Endpoint('remote', template_dir=static_dir, static_dir=static_dir) +remote_endpoint = Endpoint('remote', template_dir='remotes', static_dir='remotes') @remote_endpoint.route('{view}') diff --git a/openlp/core/api/endpoint/service.py b/openlp/core/api/endpoint/service.py index acb139b43..4e3b53fbb 100644 --- a/openlp/core/api/endpoint/service.py +++ b/openlp/core/api/endpoint/service.py @@ -23,7 +23,7 @@ import logging import json from openlp.core.api.http.endpoint import Endpoint -from openlp.core.api.http import register_endpoint, requires_auth +from openlp.core.api.http import requires_auth from openlp.core.common import Registry diff --git a/openlp/core/api/http/server.py b/openlp/core/api/http/server.py index a7ec34903..28d883487 100644 --- a/openlp/core/api/http/server.py +++ b/openlp/core/api/http/server.py @@ -37,6 +37,8 @@ from openlp.core.api.poll import Poller from openlp.core.api.endpoint.controller import controller_endpoint, api_controller_endpoint from openlp.core.api.endpoint.core import chords_endpoint, stage_endpoint, blank_endpoint, main_endpoint from openlp.core.api.endpoint.service import service_endpoint, api_service_endpoint +from openlp.core.api.endpoint.remote import remote_endpoint + log = logging.getLogger(__name__) @@ -95,3 +97,4 @@ class HttpServer(RegistryMixin, RegistryProperties, OpenLPMixin): register_endpoint(main_endpoint) register_endpoint(service_endpoint) register_endpoint(api_service_endpoint) + register_endpoint(remote_endpoint) diff --git a/openlp/plugins/songs/endpoint.py b/openlp/plugins/songs/endpoint.py index 6bd521872..c8af62764 100644 --- a/openlp/plugins/songs/endpoint.py +++ b/openlp/plugins/songs/endpoint.py @@ -95,6 +95,6 @@ def songs_service_api(request): :param request: The http request object. """ try: - return search(request, 'songs', log) + return service(request, 'songs', log) except NotFound: return {'results': {'items': []}} From 74cdc761d9459eed5398a9b32a956bce3881d050 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Tue, 26 Sep 2017 22:18:09 +0100 Subject: [PATCH 08/19] end of remote and server migration --- openlp/core/api/http/server.py | 88 +++++++++++++- openlp/core/common/settings.py | 1 + openlp/plugins/remotes/__init__.py | 21 ---- openlp/plugins/remotes/remoteplugin.py | 154 ------------------------- 4 files changed, 87 insertions(+), 177 deletions(-) delete mode 100644 openlp/plugins/remotes/__init__.py delete mode 100644 openlp/plugins/remotes/remoteplugin.py diff --git a/openlp/core/api/http/server.py b/openlp/core/api/http/server.py index 28d883487..9ba3a1bb0 100644 --- a/openlp/core/api/http/server.py +++ b/openlp/core/api/http/server.py @@ -26,13 +26,18 @@ with OpenLP. It uses JSON to communicate with the remotes. """ import logging +import time -from PyQt5 import QtCore +from PyQt5 import QtCore, QtWidgets from waitress import serve from openlp.core.api.http import register_endpoint from openlp.core.api.http import application -from openlp.core.common import RegistryMixin, RegistryProperties, OpenLPMixin, Settings, Registry +from openlp.core.common import AppLocation, RegistryMixin, RegistryProperties, OpenLPMixin, \ + Settings, Registry, UiStrings, check_directory_exists +from openlp.core.lib import translate + +from openlp.core.api.deploy import download_and_check, download_sha256 from openlp.core.api.poll import Poller from openlp.core.api.endpoint.controller import controller_endpoint, api_controller_endpoint from openlp.core.api.endpoint.core import chords_endpoint, stage_endpoint, blank_endpoint, main_endpoint @@ -81,11 +86,15 @@ class HttpServer(RegistryMixin, RegistryProperties, OpenLPMixin): self.worker.moveToThread(self.thread) self.thread.started.connect(self.worker.run) self.thread.start() + Registry().register_function('download_website', self.first_time) + Registry().register_function('get_website_version', self.website_version) + Registry().set_flag('website_version', '0001_01_01') def bootstrap_post_set_up(self): """ Register the poll return service and start the servers. """ + self.initialise() self.poller = Poller() Registry().register('poller', self.poller) application.initialise() @@ -98,3 +107,78 @@ class HttpServer(RegistryMixin, RegistryProperties, OpenLPMixin): register_endpoint(service_endpoint) register_endpoint(api_service_endpoint) register_endpoint(remote_endpoint) + + @staticmethod + def initialise(): + """ + Create the internal file structure if it does not exist + :return: + """ + check_directory_exists(AppLocation.get_section_data_path('remotes') / 'assets') + check_directory_exists(AppLocation.get_section_data_path('remotes') / 'images') + check_directory_exists(AppLocation.get_section_data_path('remotes') / 'static') + check_directory_exists(AppLocation.get_section_data_path('remotes') / 'static' / 'index') + check_directory_exists(AppLocation.get_section_data_path('remotes') / 'templates') + + def first_time(self): + """ + Import web site code if active + """ + self.application.process_events() + progress = Progress(self) + progress.forceShow() + self.application.process_events() + time.sleep(1) + download_and_check(progress) + self.application.process_events() + time.sleep(1) + progress.close() + self.application.process_events() + Settings().setValue('remotes/download version', self.version) + + def website_version(self): + """ + Download and save the website version and sha256 + :return: None + """ + sha256, self.version = download_sha256() + Registry().set_flag('website_sha256', sha256) + Registry().set_flag('website_version', self.version) + + +class Progress(QtWidgets.QProgressDialog): + """ + Local class to handle download display based and supporting httputils:get_web_page + """ + def __init__(self, parent): + super(Progress, self).__init__(parent.main_window) + self.parent = parent + self.setWindowModality(QtCore.Qt.WindowModal) + self.setWindowTitle(translate('RemotePlugin', 'Importing Website')) + self.setLabelText(UiStrings().StartingImport) + self.setCancelButton(None) + self.setRange(0, 1) + self.setMinimumDuration(0) + self.was_cancelled = False + self.previous_size = 0 + + def _download_progress(self, count, block_size): + """ + Calculate and display the download progress. + """ + increment = (count * block_size) - self.previous_size + self._increment_progress_bar(None, increment) + self.previous_size = count * block_size + + def _increment_progress_bar(self, status_text, increment=1): + """ + Update the wizard progress page. + + :param status_text: Current status information to display. + :param increment: The value to increment the progress bar by. + """ + if status_text: + self.setText(status_text) + if increment > 0: + self.setValue(self.value() + increment) + self.parent.application.process_events() \ No newline at end of file diff --git a/openlp/core/common/settings.py b/openlp/core/common/settings.py index be1b29c75..477925280 100644 --- a/openlp/core/common/settings.py +++ b/openlp/core/common/settings.py @@ -177,6 +177,7 @@ class Settings(QtCore.QSettings): 'images/background color': '#000000', 'media/players': 'system,webkit', 'media/override player': QtCore.Qt.Unchecked, + 'remotes/download version': '0000_00_00', 'players/background color': '#000000', 'servicemanager/last directory': None, 'servicemanager/last file': None, diff --git a/openlp/plugins/remotes/__init__.py b/openlp/plugins/remotes/__init__.py deleted file mode 100644 index ea62548f4..000000000 --- a/openlp/plugins/remotes/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### diff --git a/openlp/plugins/remotes/remoteplugin.py b/openlp/plugins/remotes/remoteplugin.py deleted file mode 100644 index c223eb99e..000000000 --- a/openlp/plugins/remotes/remoteplugin.py +++ /dev/null @@ -1,154 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -import logging -import time - -from PyQt5 import QtCore, QtWidgets - -from openlp.core.api.deploy import download_and_check, download_sha256 -from openlp.core.api.endpoint.remote import remote_endpoint -from openlp.core.api.http import register_endpoint -from openlp.core.common import AppLocation, Registry, Settings, OpenLPMixin, UiStrings, check_directory_exists -from openlp.core.lib import Plugin, StringContent, translate, build_icon - -log = logging.getLogger(__name__) -__default_settings__ = { - 'remotes/download version': '0000_00_00' -} - - -class RemotesPlugin(Plugin, OpenLPMixin): - log.info('Remotes Plugin loaded') - - def __init__(self): - """ - remotes constructor - """ - super(RemotesPlugin, self).__init__('remotes', __default_settings__, {}) - self.icon_path = ':/plugins/plugin_remote.png' - self.icon = build_icon(self.icon_path) - self.weight = -1 - register_endpoint(remote_endpoint) - Registry().register_function('download_website', self.first_time) - Registry().register_function('get_website_version', self.website_version) - Registry().set_flag('website_version', '0001_01_01') - - def initialise(self): - """ - Create the internal file structure if it does not exist - :return: - """ - check_directory_exists(AppLocation.get_section_data_path('remotes') / 'assets') - check_directory_exists(AppLocation.get_section_data_path('remotes') / 'images') - check_directory_exists(AppLocation.get_section_data_path('remotes') / 'static') - check_directory_exists(AppLocation.get_section_data_path('remotes') / 'static', 'index') - check_directory_exists(AppLocation.get_section_data_path('remotes') / 'templates') - - @staticmethod - def about(): - """ - Information about this plugin - """ - about_text = translate( - 'RemotePlugin', - 'Web Interface' - '
The web interface plugin provides the ability to develop web based interfaces using OpenLP web ' - 'services.\nPredefined interfaces can be download as well as custom developed interfaces.') - return about_text - - def set_plugin_text_strings(self): - """ - Called to define all translatable texts of the plugin - """ - # Name PluginList - self.text_strings[StringContent.Name] = { - 'singular': translate('RemotePlugin', 'Web Interface', 'name singular'), - 'plural': translate('RemotePlugin', 'Web Interface', 'name plural') - } - # Name for MediaDockManager, SettingsManager - self.text_strings[StringContent.VisibleName] = { - 'title': translate('RemotePlugin', 'Web Remote', 'container title') - } - - def first_time(self): - """ - Import web site code if active - """ - self.application.process_events() - progress = Progress(self) - progress.forceShow() - self.application.process_events() - time.sleep(1) - download_and_check(progress) - self.application.process_events() - time.sleep(1) - progress.close() - self.application.process_events() - Settings().setValue('remotes/download version', self.version) - - def website_version(self): - """ - Download and save the website version and sha256 - :return: None - """ - sha256, self.version = download_sha256() - Registry().set_flag('website_sha256', sha256) - Registry().set_flag('website_version', self.version) - - -class Progress(QtWidgets.QProgressDialog): - """ - Local class to handle download display based and supporting httputils:get_web_page - """ - def __init__(self, parent): - super(Progress, self).__init__(parent.main_window) - self.parent = parent - self.setWindowModality(QtCore.Qt.WindowModal) - self.setWindowTitle(translate('RemotePlugin', 'Importing Website')) - self.setLabelText(UiStrings().StartingImport) - self.setCancelButton(None) - self.setRange(0, 1) - self.setMinimumDuration(0) - self.was_cancelled = False - self.previous_size = 0 - - def _download_progress(self, count, block_size): - """ - Calculate and display the download progress. - """ - increment = (count * block_size) - self.previous_size - self._increment_progress_bar(None, increment) - self.previous_size = count * block_size - - def _increment_progress_bar(self, status_text, increment=1): - """ - Update the wizard progress page. - - :param status_text: Current status information to display. - :param increment: The value to increment the progress bar by. - """ - if status_text: - self.setText(status_text) - if increment > 0: - self.setValue(self.value() + increment) - self.parent.application.process_events() From 71a87f602b1011e47005c98542b6c485e683bfd8 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 27 Sep 2017 19:56:21 +0100 Subject: [PATCH 09/19] fix download date --- openlp/core/api/deploy.py | 2 +- openlp/core/api/http/server.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/openlp/core/api/deploy.py b/openlp/core/api/deploy.py index 44c628837..9b1e6e793 100644 --- a/openlp/core/api/deploy.py +++ b/openlp/core/api/deploy.py @@ -63,7 +63,7 @@ def download_and_check(callback=None): sha256, version = download_sha256() file_size = get_url_file_size('https://get.openlp.org/webclient/site.zip') callback.setRange(0, file_size) - if url_get_file(callback, '{host}{name}'.format(host='https://get.openlp.org/webclient/', name='site.zip'), + if url_get_file(callback, 'https://get.openlp.org/webclient/site.zip', AppLocation.get_section_data_path('remotes') / 'site.zip', sha256=sha256): deploy_zipfile(str(AppLocation.get_section_data_path('remotes')), 'site.zip') diff --git a/openlp/core/api/http/server.py b/openlp/core/api/http/server.py index 9ba3a1bb0..55f9a2305 100644 --- a/openlp/core/api/http/server.py +++ b/openlp/core/api/http/server.py @@ -66,6 +66,7 @@ class HttpWorker(QtCore.QObject): """ address = Settings().value('api/ip address') port = Settings().value('api/port') + Registry().execute('get_website_version') serve(application, host=address, port=port) def stop(self): From bfc8a5ae8c52fb0d994ce20b1f611f97fb6e7449 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 27 Sep 2017 20:12:22 +0100 Subject: [PATCH 10/19] fix tests --- tests/functional/openlp_core_api/test_deploy.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/functional/openlp_core_api/test_deploy.py b/tests/functional/openlp_core_api/test_deploy.py index 14447a97e..273894b99 100644 --- a/tests/functional/openlp_core_api/test_deploy.py +++ b/tests/functional/openlp_core_api/test_deploy.py @@ -27,7 +27,7 @@ from unittest import TestCase from openlp.core.api.deploy import deploy_zipfile -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources')) +TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'resources')) class TestRemoteDeploy(TestCase): @@ -52,6 +52,7 @@ class TestRemoteDeploy(TestCase): Remote Deploy tests - test the dummy zip file is processed correctly """ # GIVEN: A new downloaded zip file + aa = TEST_PATH zip_file = os.path.join(TEST_PATH, 'remotes', 'site.zip') app_root = os.path.join(self.app_root, 'site.zip') shutil.copyfile(zip_file, app_root) From e2fd8beb2a0090271a85475048835c74c88246fe Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 27 Sep 2017 20:16:24 +0100 Subject: [PATCH 11/19] fix tests --- tests/interfaces/openlp_core_lib/test_pluginmanager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/interfaces/openlp_core_lib/test_pluginmanager.py b/tests/interfaces/openlp_core_lib/test_pluginmanager.py index 2e9e8342f..3dbae0e03 100644 --- a/tests/interfaces/openlp_core_lib/test_pluginmanager.py +++ b/tests/interfaces/openlp_core_lib/test_pluginmanager.py @@ -94,4 +94,3 @@ class TestPluginManager(TestCase, TestMixin): self.assertIn('custom', plugin_names, 'There should be a "custom" plugin') self.assertIn('songusage', plugin_names, 'There should be a "songusage" plugin') self.assertIn('alerts', plugin_names, 'There should be a "alerts" plugin') - self.assertIn('remotes', plugin_names, 'There should be a "remotes" plugin') From 0c1b1dc2a5f1f5cc4b4852fea06793463a982328 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 27 Sep 2017 20:21:08 +0100 Subject: [PATCH 12/19] fix tests --- openlp/core/api/http/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/api/http/server.py b/openlp/core/api/http/server.py index 55f9a2305..916aedddd 100644 --- a/openlp/core/api/http/server.py +++ b/openlp/core/api/http/server.py @@ -182,4 +182,4 @@ class Progress(QtWidgets.QProgressDialog): self.setText(status_text) if increment > 0: self.setValue(self.value() + increment) - self.parent.application.process_events() \ No newline at end of file + self.parent.application.process_events() From 93fd4053b2e81184bead35035feebfb085fa3731 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Thu, 28 Sep 2017 10:31:28 -0700 Subject: [PATCH 13/19] Add dark theme from QDarkStyle. Part 1: Force the theme --- openlp/core/__init__.py | 19 ++++++++++++------- openlp/core/ui/dark.py | 32 ++++++++++++++++++++++++++++++++ openlp/core/ui/mainwindow.py | 4 +++- 3 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 openlp/core/ui/dark.py diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index 88b3dbfb7..c49ccff95 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -45,11 +45,13 @@ from openlp.core.common.versionchecker import VersionThread, get_application_ver from openlp.core.lib import ScreenList from openlp.core.resources import qInitResources from openlp.core.ui import SplashScreen +from openlp.core.ui.dark import HAS_DARK_STYLE, DARK_STYLESHEET from openlp.core.ui.exceptionform import ExceptionForm from openlp.core.ui.firsttimeform import FirstTimeForm from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm from openlp.core.ui.mainwindow import MainWindow + __all__ = ['OpenLP', 'main'] @@ -122,13 +124,16 @@ class OpenLP(OpenLPMixin, QtWidgets.QApplication): sys.exit() # Correct stylesheet bugs application_stylesheet = '' - if not Settings().value('advanced/alternate rows'): - base_color = self.palette().color(QtGui.QPalette.Active, QtGui.QPalette.Base) - alternate_rows_repair_stylesheet = \ - 'QTableWidget, QListWidget, QTreeWidget {alternate-background-color: ' + base_color.name() + ';}\n' - application_stylesheet += alternate_rows_repair_stylesheet - if is_win(): - application_stylesheet += WIN_REPAIR_STYLESHEET + if HAS_DARK_STYLE: + application_stylesheet = DARK_STYLESHEET + else: + if not Settings().value('advanced/alternate rows'): + base_color = self.palette().color(QtGui.QPalette.Active, QtGui.QPalette.Base) + alternate_rows_repair_stylesheet = \ + 'QTableWidget, QListWidget, QTreeWidget {alternate-background-color: ' + base_color.name() + ';}\n' + application_stylesheet += alternate_rows_repair_stylesheet + if is_win(): + application_stylesheet += WIN_REPAIR_STYLESHEET if application_stylesheet: self.setStyleSheet(application_stylesheet) can_show_splash = Settings().value('core/show splash') diff --git a/openlp/core/ui/dark.py b/openlp/core/ui/dark.py new file mode 100644 index 000000000..762c1ee4a --- /dev/null +++ b/openlp/core/ui/dark.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2017 OpenLP Developers # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +The :mod:`~openlp.core.ui.dark` module looks for and loads a dark theme +""" + +try: + import qdarkstyle + HAS_DARK_STYLE = True + DARK_STYLESHEET = qdarkstyle.load_stylesheet_pyqt5() +except: + HAS_DARK_STYLE = False + DARK_STYLESHEET = '' diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 413e97a17..33a9ec2ca 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -45,6 +45,7 @@ from openlp.core.lib import Renderer, PluginManager, ImageManager, PluginStatus, from openlp.core.lib.ui import create_action from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, ThemeManager, LiveController, PluginForm, \ ShortcutListForm, FormattingTagForm, PreviewController +from openlp.core.ui.dark import HAS_DARK_STYLE from openlp.core.ui.firsttimeform import FirstTimeForm from openlp.core.ui.media import MediaController from openlp.core.ui.printserviceform import PrintServiceForm @@ -155,7 +156,8 @@ class Ui_MainWindow(object): # Create the MediaManager self.media_manager_dock = OpenLPDockWidget(main_window, 'media_manager_dock', ':/system/system_mediamanager.png') - self.media_manager_dock.setStyleSheet(MEDIA_MANAGER_STYLE) + if not HAS_DARK_STYLE: + self.media_manager_dock.setStyleSheet(MEDIA_MANAGER_STYLE) # Create the media toolbox self.media_tool_box = QtWidgets.QToolBox(self.media_manager_dock) self.media_tool_box.setObjectName('media_tool_box') From 1b7482243da71ce8b248b146a2c38e60b5a1e797 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Thu, 28 Sep 2017 16:28:18 -0700 Subject: [PATCH 14/19] Centralise style tweaks --- openlp/core/__init__.py | 36 +------- openlp/core/common/settings.py | 1 + openlp/core/ui/advancedtab.py | 152 ++++++++++++++++++--------------- openlp/core/ui/dark.py | 32 ------- openlp/core/ui/mainwindow.py | 25 +----- openlp/core/ui/style.py | 119 ++++++++++++++++++++++++++ 6 files changed, 206 insertions(+), 159 deletions(-) delete mode 100644 openlp/core/ui/dark.py create mode 100644 openlp/core/ui/style.py diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index ef67ec745..c9e446143 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -42,11 +42,11 @@ from openlp.core.version import check_for_update, get_version from openlp.core.lib import ScreenList from openlp.core.resources import qInitResources from openlp.core.ui import SplashScreen -from openlp.core.ui.dark import HAS_DARK_STYLE, DARK_STYLESHEET from openlp.core.ui.exceptionform import ExceptionForm from openlp.core.ui.firsttimeform import FirstTimeForm from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm from openlp.core.ui.mainwindow import MainWindow +from openlp.core.ui.style import get_application_stylesheet __all__ = ['OpenLP', 'main'] @@ -54,28 +54,6 @@ __all__ = ['OpenLP', 'main'] log = logging.getLogger() -WIN_REPAIR_STYLESHEET = """ -QMainWindow::separator -{ - border: none; -} - -QDockWidget::title -{ - border: 1px solid palette(dark); - padding-left: 5px; - padding-top: 2px; - margin: 1px 0; -} - -QToolBar -{ - border: none; - margin: 0; - padding: 0; -} -""" - class OpenLP(OpenLPMixin, QtWidgets.QApplication): """ @@ -120,17 +98,7 @@ class OpenLP(OpenLPMixin, QtWidgets.QApplication): QtCore.QCoreApplication.exit() sys.exit() # Correct stylesheet bugs - application_stylesheet = '' - if HAS_DARK_STYLE: - application_stylesheet = DARK_STYLESHEET - else: - if not Settings().value('advanced/alternate rows'): - base_color = self.palette().color(QtGui.QPalette.Active, QtGui.QPalette.Base) - alternate_rows_repair_stylesheet = \ - 'QTableWidget, QListWidget, QTreeWidget {alternate-background-color: ' + base_color.name() + ';}\n' - application_stylesheet += alternate_rows_repair_stylesheet - if is_win(): - application_stylesheet += WIN_REPAIR_STYLESHEET + application_stylesheet = get_application_stylesheet() if application_stylesheet: self.setStyleSheet(application_stylesheet) can_show_splash = Settings().value('core/show splash') diff --git a/openlp/core/common/settings.py b/openlp/core/common/settings.py index be1b29c75..0540ff81e 100644 --- a/openlp/core/common/settings.py +++ b/openlp/core/common/settings.py @@ -136,6 +136,7 @@ class Settings(QtCore.QSettings): 'advanced/single click service preview': False, 'advanced/x11 bypass wm': X11_BYPASS_DEFAULT, 'advanced/search as type': True, + 'advanced/use_dark_style': False, 'api/twelve hour': True, 'api/port': 4316, 'api/websocket port': 4317, diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index 8ec55999b..b655b3899 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -32,6 +32,7 @@ from openlp.core.common.languagemanager import format_time from openlp.core.common.path import path_to_str from openlp.core.lib import SettingsTab, build_icon from openlp.core.ui.lib import PathEdit, PathType +from openlp.core.ui.style import HAS_DARK_STYLE log = logging.getLogger(__name__) @@ -109,8 +110,80 @@ class AdvancedTab(SettingsTab): self.enable_auto_close_check_box.setObjectName('enable_auto_close_check_box') self.ui_layout.addRow(self.enable_auto_close_check_box) self.left_layout.addWidget(self.ui_group_box) + if HAS_DARK_STYLE: + self.use_dark_style_checkbox = QtWidgets.QCheckBox(self.ui_group_box) + self.use_dark_style_checkbox.setObjectName('use_dark_style_checkbox') + self.ui_layout.addRow(self.use_dark_style_checkbox) + # Data Directory + self.data_directory_group_box = QtWidgets.QGroupBox(self.left_column) + self.data_directory_group_box.setObjectName('data_directory_group_box') + self.data_directory_layout = QtWidgets.QFormLayout(self.data_directory_group_box) + self.data_directory_layout.setObjectName('data_directory_layout') + self.data_directory_new_label = QtWidgets.QLabel(self.data_directory_group_box) + self.data_directory_new_label.setObjectName('data_directory_current_label') + self.data_directory_path_edit = PathEdit(self.data_directory_group_box, path_type=PathType.Directories, + default_path=AppLocation.get_directory(AppLocation.DataDir)) + self.data_directory_layout.addRow(self.data_directory_new_label, self.data_directory_path_edit) + self.new_data_directory_has_files_label = QtWidgets.QLabel(self.data_directory_group_box) + self.new_data_directory_has_files_label.setObjectName('new_data_directory_has_files_label') + self.new_data_directory_has_files_label.setWordWrap(True) + self.data_directory_cancel_button = QtWidgets.QToolButton(self.data_directory_group_box) + self.data_directory_cancel_button.setObjectName('data_directory_cancel_button') + self.data_directory_cancel_button.setIcon(build_icon(':/general/general_delete.png')) + self.data_directory_copy_check_layout = QtWidgets.QHBoxLayout() + self.data_directory_copy_check_layout.setObjectName('data_directory_copy_check_layout') + self.data_directory_copy_check_box = QtWidgets.QCheckBox(self.data_directory_group_box) + self.data_directory_copy_check_box.setObjectName('data_directory_copy_check_box') + self.data_directory_copy_check_layout.addWidget(self.data_directory_copy_check_box) + self.data_directory_copy_check_layout.addStretch() + self.data_directory_copy_check_layout.addWidget(self.data_directory_cancel_button) + self.data_directory_layout.addRow(self.data_directory_copy_check_layout) + self.data_directory_layout.addRow(self.new_data_directory_has_files_label) + self.left_layout.addWidget(self.data_directory_group_box) + # Hide mouse + self.hide_mouse_group_box = QtWidgets.QGroupBox(self.right_column) + self.hide_mouse_group_box.setObjectName('hide_mouse_group_box') + self.hide_mouse_layout = QtWidgets.QVBoxLayout(self.hide_mouse_group_box) + self.hide_mouse_layout.setObjectName('hide_mouse_layout') + self.hide_mouse_check_box = QtWidgets.QCheckBox(self.hide_mouse_group_box) + self.hide_mouse_check_box.setObjectName('hide_mouse_check_box') + self.hide_mouse_layout.addWidget(self.hide_mouse_check_box) + self.right_layout.addWidget(self.hide_mouse_group_box) + # Service Item Slide Limits + self.slide_group_box = QtWidgets.QGroupBox(self.right_column) + self.slide_group_box.setObjectName('slide_group_box') + self.slide_layout = QtWidgets.QVBoxLayout(self.slide_group_box) + self.slide_layout.setObjectName('slide_layout') + self.slide_label = QtWidgets.QLabel(self.slide_group_box) + self.slide_label.setWordWrap(True) + self.slide_layout.addWidget(self.slide_label) + self.end_slide_radio_button = QtWidgets.QRadioButton(self.slide_group_box) + self.end_slide_radio_button.setObjectName('end_slide_radio_button') + self.slide_layout.addWidget(self.end_slide_radio_button) + self.wrap_slide_radio_button = QtWidgets.QRadioButton(self.slide_group_box) + self.wrap_slide_radio_button.setObjectName('wrap_slide_radio_button') + self.slide_layout.addWidget(self.wrap_slide_radio_button) + self.next_item_radio_button = QtWidgets.QRadioButton(self.slide_group_box) + self.next_item_radio_button.setObjectName('next_item_radio_button') + self.slide_layout.addWidget(self.next_item_radio_button) + self.right_layout.addWidget(self.slide_group_box) + # Display Workarounds + self.display_workaround_group_box = QtWidgets.QGroupBox(self.right_column) + self.display_workaround_group_box.setObjectName('display_workaround_group_box') + self.display_workaround_layout = QtWidgets.QVBoxLayout(self.display_workaround_group_box) + self.display_workaround_layout.setObjectName('display_workaround_layout') + self.ignore_aspect_ratio_check_box = QtWidgets.QCheckBox(self.display_workaround_group_box) + self.ignore_aspect_ratio_check_box.setObjectName('ignore_aspect_ratio_check_box') + self.display_workaround_layout.addWidget(self.ignore_aspect_ratio_check_box) + self.x11_bypass_check_box = QtWidgets.QCheckBox(self.display_workaround_group_box) + self.x11_bypass_check_box.setObjectName('x11_bypass_check_box') + self.display_workaround_layout.addWidget(self.x11_bypass_check_box) + self.alternate_rows_check_box = QtWidgets.QCheckBox(self.display_workaround_group_box) + self.alternate_rows_check_box.setObjectName('alternate_rows_check_box') + self.display_workaround_layout.addWidget(self.alternate_rows_check_box) + self.right_layout.addWidget(self.display_workaround_group_box) # Default service name - self.service_name_group_box = QtWidgets.QGroupBox(self.left_column) + self.service_name_group_box = QtWidgets.QGroupBox(self.right_column) self.service_name_group_box.setObjectName('service_name_group_box') self.service_name_layout = QtWidgets.QFormLayout(self.service_name_group_box) self.service_name_check_box = QtWidgets.QCheckBox(self.service_name_group_box) @@ -147,77 +220,11 @@ class AdvancedTab(SettingsTab): self.service_name_example = QtWidgets.QLabel(self.service_name_group_box) self.service_name_example.setObjectName('service_name_example') self.service_name_layout.addRow(self.service_name_example_label, self.service_name_example) - self.left_layout.addWidget(self.service_name_group_box) - # Data Directory - self.data_directory_group_box = QtWidgets.QGroupBox(self.left_column) - self.data_directory_group_box.setObjectName('data_directory_group_box') - self.data_directory_layout = QtWidgets.QFormLayout(self.data_directory_group_box) - self.data_directory_layout.setObjectName('data_directory_layout') - self.data_directory_new_label = QtWidgets.QLabel(self.data_directory_group_box) - self.data_directory_new_label.setObjectName('data_directory_current_label') - self.data_directory_path_edit = PathEdit(self.data_directory_group_box, path_type=PathType.Directories, - default_path=AppLocation.get_directory(AppLocation.DataDir)) - self.data_directory_layout.addRow(self.data_directory_new_label, self.data_directory_path_edit) - self.new_data_directory_has_files_label = QtWidgets.QLabel(self.data_directory_group_box) - self.new_data_directory_has_files_label.setObjectName('new_data_directory_has_files_label') - self.new_data_directory_has_files_label.setWordWrap(True) - self.data_directory_cancel_button = QtWidgets.QToolButton(self.data_directory_group_box) - self.data_directory_cancel_button.setObjectName('data_directory_cancel_button') - self.data_directory_cancel_button.setIcon(build_icon(':/general/general_delete.png')) - self.data_directory_copy_check_layout = QtWidgets.QHBoxLayout() - self.data_directory_copy_check_layout.setObjectName('data_directory_copy_check_layout') - self.data_directory_copy_check_box = QtWidgets.QCheckBox(self.data_directory_group_box) - self.data_directory_copy_check_box.setObjectName('data_directory_copy_check_box') - self.data_directory_copy_check_layout.addWidget(self.data_directory_copy_check_box) - self.data_directory_copy_check_layout.addStretch() - self.data_directory_copy_check_layout.addWidget(self.data_directory_cancel_button) - self.data_directory_layout.addRow(self.data_directory_copy_check_layout) - self.data_directory_layout.addRow(self.new_data_directory_has_files_label) - self.left_layout.addWidget(self.data_directory_group_box) + self.right_layout.addWidget(self.service_name_group_box) + # After the last item on each side, add some spacing self.left_layout.addStretch() - # Hide mouse - self.hide_mouse_group_box = QtWidgets.QGroupBox(self.right_column) - self.hide_mouse_group_box.setObjectName('hide_mouse_group_box') - self.hide_mouse_layout = QtWidgets.QVBoxLayout(self.hide_mouse_group_box) - self.hide_mouse_layout.setObjectName('hide_mouse_layout') - self.hide_mouse_check_box = QtWidgets.QCheckBox(self.hide_mouse_group_box) - self.hide_mouse_check_box.setObjectName('hide_mouse_check_box') - self.hide_mouse_layout.addWidget(self.hide_mouse_check_box) - self.right_layout.addWidget(self.hide_mouse_group_box) - # Service Item Slide Limits - self.slide_group_box = QtWidgets.QGroupBox(self.right_column) - self.slide_group_box.setObjectName('slide_group_box') - self.slide_layout = QtWidgets.QVBoxLayout(self.slide_group_box) - self.slide_layout.setObjectName('slide_layout') - self.slide_label = QtWidgets.QLabel(self.slide_group_box) - self.slide_label.setWordWrap(True) - self.slide_layout.addWidget(self.slide_label) - self.end_slide_radio_button = QtWidgets.QRadioButton(self.slide_group_box) - self.end_slide_radio_button.setObjectName('end_slide_radio_button') - self.slide_layout.addWidget(self.end_slide_radio_button) - self.wrap_slide_radio_button = QtWidgets.QRadioButton(self.slide_group_box) - self.wrap_slide_radio_button.setObjectName('wrap_slide_radio_button') - self.slide_layout.addWidget(self.wrap_slide_radio_button) - self.next_item_radio_button = QtWidgets.QRadioButton(self.slide_group_box) - self.next_item_radio_button.setObjectName('next_item_radio_button') - self.slide_layout.addWidget(self.next_item_radio_button) - self.right_layout.addWidget(self.slide_group_box) - # Display Workarounds - self.display_workaround_group_box = QtWidgets.QGroupBox(self.left_column) - self.display_workaround_group_box.setObjectName('display_workaround_group_box') - self.display_workaround_layout = QtWidgets.QVBoxLayout(self.display_workaround_group_box) - self.display_workaround_layout.setObjectName('display_workaround_layout') - self.ignore_aspect_ratio_check_box = QtWidgets.QCheckBox(self.display_workaround_group_box) - self.ignore_aspect_ratio_check_box.setObjectName('ignore_aspect_ratio_check_box') - self.display_workaround_layout.addWidget(self.ignore_aspect_ratio_check_box) - self.x11_bypass_check_box = QtWidgets.QCheckBox(self.display_workaround_group_box) - self.x11_bypass_check_box.setObjectName('x11_bypass_check_box') - self.display_workaround_layout.addWidget(self.x11_bypass_check_box) - self.alternate_rows_check_box = QtWidgets.QCheckBox(self.display_workaround_group_box) - self.alternate_rows_check_box.setObjectName('alternate_rows_check_box') - self.display_workaround_layout.addWidget(self.alternate_rows_check_box) - self.right_layout.addWidget(self.display_workaround_group_box) self.right_layout.addStretch() + # Set up all the connections and things self.should_update_service_name_example = False self.service_name_check_box.toggled.connect(self.service_name_check_box_toggled) self.service_name_day.currentIndexChanged.connect(self.on_service_name_day_changed) @@ -282,6 +289,7 @@ class AdvancedTab(SettingsTab): 'Auto-scroll the next slide to bottom')) self.enable_auto_close_check_box.setText(translate('OpenLP.AdvancedTab', 'Enable application exit confirmation')) + self.use_dark_style_checkbox.setText(translate('OpenLP.AdvancedTab', 'Use dark style (needs restart)')) self.service_name_group_box.setTitle(translate('OpenLP.AdvancedTab', 'Default Service Name')) self.service_name_check_box.setText(translate('OpenLP.AdvancedTab', 'Enable default service name')) self.service_name_time_label.setText(translate('OpenLP.AdvancedTab', 'Date and Time:')) @@ -349,6 +357,8 @@ class AdvancedTab(SettingsTab): if self.autoscroll_map[i] == autoscroll_value and i < self.autoscroll_combo_box.count(): self.autoscroll_combo_box.setCurrentIndex(i) self.enable_auto_close_check_box.setChecked(settings.value('enable exit confirmation')) + if HAS_DARK_STYLE: + self.use_dark_style_checkbox.setChecked(settings.value('use_dark_style')) self.hide_mouse_check_box.setChecked(settings.value('hide mouse')) self.service_name_day.setCurrentIndex(settings.value('default service day')) self.service_name_time.setTime(QtCore.QTime(settings.value('default service hour'), @@ -420,6 +430,8 @@ class AdvancedTab(SettingsTab): self.settings_form.register_post_process('config_screen_changed') self.settings_form.register_post_process('slidecontroller_update_slide_limits') settings.setValue('search as type', self.is_search_as_you_type_enabled) + if HAS_DARK_STYLE: + settings.setValue('use_dark_style', self.use_dark_style_checkbox.isChecked()) settings.endGroup() def on_search_as_type_check_box_changed(self, check_state): diff --git a/openlp/core/ui/dark.py b/openlp/core/ui/dark.py deleted file mode 100644 index 762c1ee4a..000000000 --- a/openlp/core/ui/dark.py +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # -# --------------------------------------------------------------------------- # -# This program is free software; you can redistribute it and/or modify it # -# under the terms of the GNU General Public License as published by the Free # -# Software Foundation; version 2 of the License. # -# # -# This program is distributed in the hope that it will be useful, but WITHOUT # -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # -# more details. # -# # -# You should have received a copy of the GNU General Public License along # -# with this program; if not, write to the Free Software Foundation, Inc., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### -""" -The :mod:`~openlp.core.ui.dark` module looks for and loads a dark theme -""" - -try: - import qdarkstyle - HAS_DARK_STYLE = True - DARK_STYLESHEET = qdarkstyle.load_stylesheet_pyqt5() -except: - HAS_DARK_STYLE = False - DARK_STYLESHEET = '' diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 077883513..25fe818ee 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -44,7 +44,6 @@ from openlp.core.lib import Renderer, PluginManager, ImageManager, PluginStatus, from openlp.core.lib.ui import create_action from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, ThemeManager, LiveController, PluginForm, \ ShortcutListForm, FormattingTagForm, PreviewController -from openlp.core.ui.dark import HAS_DARK_STYLE from openlp.core.ui.firsttimeform import FirstTimeForm from openlp.core.ui.media import MediaController from openlp.core.ui.printserviceform import PrintServiceForm @@ -52,31 +51,12 @@ from openlp.core.ui.projector.manager import ProjectorManager from openlp.core.ui.lib.dockwidget import OpenLPDockWidget from openlp.core.ui.lib.filedialog import FileDialog from openlp.core.ui.lib.mediadockmanager import MediaDockManager +from openlp.core.ui.style import PROGRESSBAR_STYLE, get_library_stylesheet from openlp.core.version import get_version log = logging.getLogger(__name__) -MEDIA_MANAGER_STYLE = """ -::tab#media_tool_box { - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 palette(button), stop: 1.0 palette(mid)); - border: 0; - border-radius: 2px; - margin-top: 0; - margin-bottom: 0; - text-align: left; -} -/* This is here to make the tabs on KDE with the Breeze theme work */ -::tab:selected {} -""" - -PROGRESSBAR_STYLE = """ -QProgressBar{ - height: 10px; -} -""" - class Ui_MainWindow(object): """ @@ -156,8 +136,7 @@ class Ui_MainWindow(object): # Create the MediaManager self.media_manager_dock = OpenLPDockWidget(main_window, 'media_manager_dock', ':/system/system_mediamanager.png') - if not HAS_DARK_STYLE: - self.media_manager_dock.setStyleSheet(MEDIA_MANAGER_STYLE) + self.media_manager_dock.setStyleSheet(get_library_stylesheet()) # Create the media toolbox self.media_tool_box = QtWidgets.QToolBox(self.media_manager_dock) self.media_tool_box.setObjectName('media_tool_box') diff --git a/openlp/core/ui/style.py b/openlp/core/ui/style.py new file mode 100644 index 000000000..7ffeb9533 --- /dev/null +++ b/openlp/core/ui/style.py @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2017 OpenLP Developers # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +The :mod:`~openlp.core.ui.dark` module looks for and loads a dark theme +""" +from PyQt5 import QtGui + +from openlp.core.common import is_macosx, is_win +from openlp.core.common.registry import Registry +from openlp.core.common.settings import Settings + +try: + import qdarkstyle + HAS_DARK_STYLE = True +except ImportError: + HAS_DARK_STYLE = False + +WIN_REPAIR_STYLESHEET = """ +QMainWindow::separator +{ + border: none; +} + +QDockWidget::title +{ + border: 1px solid palette(dark); + padding-left: 5px; + padding-top: 2px; + margin: 1px 0; +} + +QToolBar +{ + border: none; + margin: 0; + padding: 0; +} +""" + +MEDIA_MANAGER_STYLE = """ +::tab#media_tool_box { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 palette(button), stop: 1.0 palette(mid)); + border: 0; + border-radius: 2px; + margin-top: 0; + margin-bottom: 0; + text-align: left; +} +/* This is here to make the tabs on KDE with the Breeze theme work */ +::tab:selected {} +""" + +PROGRESSBAR_STYLE = """ +QProgressBar{ + height: 10px; +} +""" + + +def can_show_icon(): + """ + A global method to determine if an icon can be shown on a widget + + .. note:: + This method uses internal imports to prevent circular imports. + """ + return not is_macosx() or Settings.value('advanced/use_dark_style') + + +def get_application_stylesheet(): + """ + Return the correct application stylesheet based on the current style and operating system + + :return str: The correct stylesheet as a string + """ + stylesheet = '' + if HAS_DARK_STYLE and Settings().value('advanced/use_dark_style'): + stylesheet = qdarkstyle.load_stylesheet_pyqt5() + else: + if not Settings().value('advanced/alternate rows'): + base_color = Registry().get('application').palette().color(QtGui.QPalette.Active, QtGui.QPalette.Base) + alternate_rows_repair_stylesheet = \ + 'QTableWidget, QListWidget, QTreeWidget {alternate-background-color: ' + base_color.name() + ';}\n' + stylesheet += alternate_rows_repair_stylesheet + if is_win(): + stylesheet += WIN_REPAIR_STYLESHEET + return stylesheet + + +def get_library_stylesheet(): + """ + Return the correct stylesheet for the main window + + :return str: The correct stylesheet as a string + """ + if not HAS_DARK_STYLE or not Settings().value('advanced/use_dark_style'): + return MEDIA_MANAGER_STYLE + else: + return '' From 77b9fee05010497be35188ea5ac4df1c8485ec3d Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Thu, 28 Sep 2017 16:39:44 -0700 Subject: [PATCH 15/19] Checkbox is only there is there is a dark style --- openlp/core/ui/advancedtab.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index b655b3899..26303f1cb 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -289,7 +289,8 @@ class AdvancedTab(SettingsTab): 'Auto-scroll the next slide to bottom')) self.enable_auto_close_check_box.setText(translate('OpenLP.AdvancedTab', 'Enable application exit confirmation')) - self.use_dark_style_checkbox.setText(translate('OpenLP.AdvancedTab', 'Use dark style (needs restart)')) + if HAS_DARK_STYLE: + self.use_dark_style_checkbox.setText(translate('OpenLP.AdvancedTab', 'Use dark style (needs restart)')) self.service_name_group_box.setTitle(translate('OpenLP.AdvancedTab', 'Default Service Name')) self.service_name_check_box.setText(translate('OpenLP.AdvancedTab', 'Enable default service name')) self.service_name_time_label.setText(translate('OpenLP.AdvancedTab', 'Date and Time:')) From 76bf162383d48d0f53bad07da8777b2dd650748e Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Thu, 28 Sep 2017 16:50:23 -0700 Subject: [PATCH 16/19] Fix error with Settings().value() call --- openlp/core/ui/style.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/core/ui/style.py b/openlp/core/ui/style.py index 7ffeb9533..71a7e5c15 100644 --- a/openlp/core/ui/style.py +++ b/openlp/core/ui/style.py @@ -84,7 +84,7 @@ def can_show_icon(): .. note:: This method uses internal imports to prevent circular imports. """ - return not is_macosx() or Settings.value('advanced/use_dark_style') + return not is_macosx() or Settings().value('advanced/use_dark_style') def get_application_stylesheet(): From 0dcf3de267bf726ee0029fae0edf946b94a00a3d Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Thu, 28 Sep 2017 20:06:00 -0700 Subject: [PATCH 17/19] Tests! --- openlp/core/ui/style.py | 10 -- tests/functional/openlp_core_ui/test_style.py | 110 ++++++++++++++++++ 2 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 tests/functional/openlp_core_ui/test_style.py diff --git a/openlp/core/ui/style.py b/openlp/core/ui/style.py index 71a7e5c15..764a3bd26 100644 --- a/openlp/core/ui/style.py +++ b/openlp/core/ui/style.py @@ -77,16 +77,6 @@ QProgressBar{ """ -def can_show_icon(): - """ - A global method to determine if an icon can be shown on a widget - - .. note:: - This method uses internal imports to prevent circular imports. - """ - return not is_macosx() or Settings().value('advanced/use_dark_style') - - def get_application_stylesheet(): """ Return the correct application stylesheet based on the current style and operating system diff --git a/tests/functional/openlp_core_ui/test_style.py b/tests/functional/openlp_core_ui/test_style.py new file mode 100644 index 000000000..8bdfea047 --- /dev/null +++ b/tests/functional/openlp_core_ui/test_style.py @@ -0,0 +1,110 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2017 OpenLP Developers # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +Package to test the :mod:`~openlp.core.ui.style` module. +""" +from unittest.mock import MagicMock, patch + +from openlp.core.ui.style import MEDIA_MANAGER_STYLE, WIN_REPAIR_STYLESHEET, get_application_stylesheet, \ + get_library_stylesheet + + +@patch('openlp.core.ui.style.HAS_DARK_STYLE', True) +@patch('openlp.core.ui.style.Settings') +@patch('openlp.core.ui.style.qdarkstyle') +def test_get_application_stylesheet_dark(mocked_qdarkstyle, MockSettings): + """Test that the dark stylesheet is returned when available and enabled""" + # GIVEN: We're on Windows and no dark style is set + mocked_settings = MagicMock() + mocked_settings.value.return_value = True + MockSettings.return_value = mocked_settings + mocked_qdarkstyle.load_stylesheet_pyqt5.return_value = 'dark_style' + + # WHEN: can_show_icon() is called + result = get_application_stylesheet() + + # THEN: the result should be false + assert result == 'dark_style' + + +@patch('openlp.core.ui.style.HAS_DARK_STYLE', False) +@patch('openlp.core.ui.style.is_win') +@patch('openlp.core.ui.style.Settings') +@patch('openlp.core.ui.style.Registry') +def test_get_application_stylesheet_not_alternate_rows(MockRegistry, MockSettings, mocked_is_win): + """Test that the alternate rows stylesheet is returned when enabled in settings""" + # GIVEN: We're on Windows and no dark style is set + mocked_is_win.return_value = False + MockSettings.return_value.value.return_value = False + MockRegistry.return_value.get.return_value.palette.return_value.color.return_value.name.return_value = 'color' + + # WHEN: can_show_icon() is called + result = get_application_stylesheet() + + # THEN: the result should be false + MockSettings.return_value.value.assert_called_once_with('advanced/alternate rows') + assert result == 'QTableWidget, QListWidget, QTreeWidget {alternate-background-color: color;}\n', result + + +@patch('openlp.core.ui.style.HAS_DARK_STYLE', False) +@patch('openlp.core.ui.style.is_win') +@patch('openlp.core.ui.style.Settings') +def test_get_application_stylesheet_win_repair(MockSettings, mocked_is_win): + """Test that the Windows repair stylesheet is returned when on Windows""" + # GIVEN: We're on Windows and no dark style is set + mocked_is_win.return_value = True + MockSettings.return_value.value.return_value = True + + # WHEN: can_show_icon() is called + result = get_application_stylesheet() + + # THEN: the result should be false + MockSettings.return_value.value.assert_called_once_with('advanced/alternate rows') + assert result == WIN_REPAIR_STYLESHEET + + +@patch('openlp.core.ui.style.HAS_DARK_STYLE', False) +@patch('openlp.core.ui.style.Settings') +def test_get_library_stylesheet_no_dark_style(MockSettings): + """Test that the media manager stylesheet is returned when there's no dark theme available""" + # GIVEN: No dark style + MockSettings.return_value.value.return_value = False + + # WHEN: get_library_stylesheet() is called + result = get_library_stylesheet() + + # THEN: The correct stylesheet should be returned + assert result == MEDIA_MANAGER_STYLE + + +@patch('openlp.core.ui.style.HAS_DARK_STYLE', True) +@patch('openlp.core.ui.style.Settings') +def test_get_library_stylesheet_dark_style(MockSettings): + """Test that no stylesheet is returned when the dark theme is enabled""" + # GIVEN: No dark style + MockSettings.return_value.value.return_value = True + + # WHEN: get_library_stylesheet() is called + result = get_library_stylesheet() + + # THEN: The correct stylesheet should be returned + assert result == '' From 11fbad77dc23c3036135bd5465110624bc7f5f12 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Fri, 29 Sep 2017 08:55:39 -0700 Subject: [PATCH 18/19] Fix some linting issues --- tests/functional/openlp_core_ui/test_style.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/functional/openlp_core_ui/test_style.py b/tests/functional/openlp_core_ui/test_style.py index 8bdfea047..7435df1c7 100644 --- a/tests/functional/openlp_core_ui/test_style.py +++ b/tests/functional/openlp_core_ui/test_style.py @@ -24,13 +24,14 @@ Package to test the :mod:`~openlp.core.ui.style` module. """ from unittest.mock import MagicMock, patch +import openlp.core.ui.style from openlp.core.ui.style import MEDIA_MANAGER_STYLE, WIN_REPAIR_STYLESHEET, get_application_stylesheet, \ get_library_stylesheet @patch('openlp.core.ui.style.HAS_DARK_STYLE', True) @patch('openlp.core.ui.style.Settings') -@patch('openlp.core.ui.style.qdarkstyle') +@patch.object(openlp.core.ui.style, 'qdarkstyle') def test_get_application_stylesheet_dark(mocked_qdarkstyle, MockSettings): """Test that the dark stylesheet is returned when available and enabled""" # GIVEN: We're on Windows and no dark style is set @@ -38,7 +39,7 @@ def test_get_application_stylesheet_dark(mocked_qdarkstyle, MockSettings): mocked_settings.value.return_value = True MockSettings.return_value = mocked_settings mocked_qdarkstyle.load_stylesheet_pyqt5.return_value = 'dark_style' - + # WHEN: can_show_icon() is called result = get_application_stylesheet() @@ -56,7 +57,7 @@ def test_get_application_stylesheet_not_alternate_rows(MockRegistry, MockSetting mocked_is_win.return_value = False MockSettings.return_value.value.return_value = False MockRegistry.return_value.get.return_value.palette.return_value.color.return_value.name.return_value = 'color' - + # WHEN: can_show_icon() is called result = get_application_stylesheet() @@ -73,7 +74,7 @@ def test_get_application_stylesheet_win_repair(MockSettings, mocked_is_win): # GIVEN: We're on Windows and no dark style is set mocked_is_win.return_value = True MockSettings.return_value.value.return_value = True - + # WHEN: can_show_icon() is called result = get_application_stylesheet() From cd1b6715b6cd01e31cd760140d0b81e723aabed3 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Fri, 29 Sep 2017 19:53:04 +0100 Subject: [PATCH 19/19] fix merge comments --- openlp/core/api/http/server.py | 8 ++++---- openlp/core/api/tab.py | 2 ++ openlp/core/common/settings.py | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/openlp/core/api/http/server.py b/openlp/core/api/http/server.py index 916aedddd..2a2ec7292 100644 --- a/openlp/core/api/http/server.py +++ b/openlp/core/api/http/server.py @@ -89,7 +89,7 @@ class HttpServer(RegistryMixin, RegistryProperties, OpenLPMixin): self.thread.start() Registry().register_function('download_website', self.first_time) Registry().register_function('get_website_version', self.website_version) - Registry().set_flag('website_version', '0001_01_01') + Registry().set_flag('website_version', '0.0') def bootstrap_post_set_up(self): """ @@ -126,7 +126,7 @@ class HttpServer(RegistryMixin, RegistryProperties, OpenLPMixin): Import web site code if active """ self.application.process_events() - progress = Progress(self) + progress = DownloadProgressDialog(self) progress.forceShow() self.application.process_events() time.sleep(1) @@ -147,12 +147,12 @@ class HttpServer(RegistryMixin, RegistryProperties, OpenLPMixin): Registry().set_flag('website_version', self.version) -class Progress(QtWidgets.QProgressDialog): +class DownloadProgressDialog(QtWidgets.QProgressDialog): """ Local class to handle download display based and supporting httputils:get_web_page """ def __init__(self, parent): - super(Progress, self).__init__(parent.main_window) + super(DownloadProgressDialog, self).__init__(parent.main_window) self.parent = parent self.setWindowModality(QtCore.Qt.WindowModal) self.setWindowTitle(translate('RemotePlugin', 'Importing Website')) diff --git a/openlp/core/api/tab.py b/openlp/core/api/tab.py index 3ec8c4515..e10a68238 100644 --- a/openlp/core/api/tab.py +++ b/openlp/core/api/tab.py @@ -222,6 +222,8 @@ class ApiTab(SettingsTab): self.remote_url.setText('{url}'.format(url=http_url)) http_url_temp = http_url + 'stage' self.stage_url.setText('{url}'.format(url=http_url_temp)) + http_url_temp = http_url + 'chords' + self.chords_url.setText('{url}'.format(url=http_url_temp)) http_url_temp = http_url + 'main' self.live_url.setText('{url}'.format(url=http_url_temp)) diff --git a/openlp/core/common/settings.py b/openlp/core/common/settings.py index 477925280..87efd10d3 100644 --- a/openlp/core/common/settings.py +++ b/openlp/core/common/settings.py @@ -177,7 +177,7 @@ class Settings(QtCore.QSettings): 'images/background color': '#000000', 'media/players': 'system,webkit', 'media/override player': QtCore.Qt.Unchecked, - 'remotes/download version': '0000_00_00', + 'remotes/download version': '0.0', 'players/background color': '#000000', 'servicemanager/last directory': None, 'servicemanager/last file': None,