diff --git a/appveyor.yml b/appveyor.yml
index e6bec242b..efea42aba 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -30,7 +30,7 @@ install:
# Update pip
- python -m pip install --upgrade pip
# Install generic dependencies from pypi
- - python -m pip install sqlalchemy alembic appdirs chardet beautifulsoup4 lxml Mako mysql-connector-python pytest mock psycopg2-binary websockets waitress six webob requests QtAwesome PyQt5 PyQtWebEngine pymediainfo PyMuPDF QDarkStyle python-vlc zeroconf flask-cors pytest-qt pyenchant pysword
+ - python -m pip install sqlalchemy alembic appdirs chardet beautifulsoup4 lxml Mako mysql-connector-python pytest mock psycopg2-binary websockets waitress six webob requests QtAwesome PyQt5 PyQtWebEngine pymediainfo PyMuPDF QDarkStyle python-vlc zeroconf flask-cors pytest-qt pyenchant pysword qrcode pillow
# Install Windows only dependencies
- cmd: python -m pip install pyodbc pypiwin32
# Mac only dependencies
diff --git a/openlp/core/api/tab.py b/openlp/core/api/tab.py
index a0d3e8f4c..cd134ae45 100644
--- a/openlp/core/api/tab.py
+++ b/openlp/core/api/tab.py
@@ -21,6 +21,11 @@
"""
The :mod:`~openlp.core.api.tab` module contains the settings tab for the API
"""
+
+import PIL.ImageQt
+import PIL.Image
+import qrcode
+
from time import sleep
from PyQt5 import QtCore, QtGui, QtWidgets
@@ -213,9 +218,7 @@ class ApiTab(SettingsTab):
'Show thumbnails of non-text slides in remote and stage view.'))
self.app_group_box.setTitle(translate('RemotePlugin.RemoteTab', 'Remote App'))
self.app_qr_description_label.setText(
- translate('RemotePlugin.RemoteTab',
- 'Scan the QR code or click download to download an app for your mobile device'
- ).format(qr='https://openlp.org/#mobile-app-downloads'))
+ translate('RemotePlugin.RemoteTab', 'Scan the QR code to open the remote view on your mobile device'))
self.user_login_group_box.setTitle(translate('RemotePlugin.RemoteTab', 'User Authentication'))
self.web_remote_group_box.setTitle(translate('RemotePlugin.RemoteTab', 'Web Remote'))
self.check_version_button.setText(translate('RemotePlugin.RemoteTab', 'Check for Updates'))
@@ -268,14 +271,15 @@ class ApiTab(SettingsTab):
Update the display based on the data input on the screen
"""
ip_address = self.get_ip_address(self.address_edit.text())
- http_url = 'http://{url}:{text}/'.format(url=ip_address, text=self.port_spin_box.text())
- 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))
+ http_url = f'http://{ip_address}:{self.port_spin_box.text()}/'
+ self.remote_url.setText(f'{http_url}')
+ self.stage_url.setText(f'{http_url}stage')
+ self.chords_url.setText(f'{http_url}chords')
+ self.live_url.setText(f'{http_url}main')
+ img = qrcode.make(http_url)
+ img = PIL.ImageQt.ImageQt(img)
+ image = QtGui.QPixmap.fromImage(img)
+ self.app_qr_code_label.setPixmap(image)
def get_server_states(self):
"""
diff --git a/setup.py b/setup.py
index b89a89e8e..d3e591ea7 100644
--- a/setup.py
+++ b/setup.py
@@ -106,6 +106,7 @@ using a computer and a data projector.""",
'flask-cors',
'lxml',
'Mako',
+ "pillow",
'pymediainfo >= 2.2',
'pyobjc; platform_system=="Darwin"',
'pyobjc-framework-Cocoa; platform_system=="Darwin"',
@@ -115,6 +116,7 @@ using a computer and a data projector.""",
'python-vlc',
'pywin32; platform_system=="Windows"',
'QtAwesome',
+ "qrcode",
'requests',
'SQLAlchemy >= 0.5',
'waitress',
diff --git a/tests/openlp_core/api/test_tab.py b/tests/openlp_core/api/test_tab.py
index 1e96beb0e..a40d3bf3a 100644
--- a/tests/openlp_core/api/test_tab.py
+++ b/tests/openlp_core/api/test_tab.py
@@ -21,6 +21,7 @@
"""
This module contains tests for the lib submodule of the Remotes plugin.
"""
+import hashlib
import pytest
import re
@@ -94,6 +95,11 @@ def test_set_urls(api_tab):
assert api_tab.live_url.text() == \
"http://192.168.1.1:4316/main", \
'The return value should be a fully formed main link'
+ assert api_tab.chords_url.text() == \
+ "http://192.168.1.1:4316/chords", \
+ 'The return value should be a fully formed chords link'
+ assert hashlib.sha256(api_tab.app_qr_code_label.text().encode()).hexdigest() \
+ == 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 'Incorrect QR Code generated'
def test_address_revert_button_clicked(api_tab, settings):