diff --git a/nose2.cfg b/nose2.cfg index c34cc46e1..1f2e01126 100644 --- a/nose2.cfg +++ b/nose2.cfg @@ -1,17 +1,22 @@ [unittest] -verbose = True +verbose = true +plugins = nose2.plugins.mp [log-capture] -always-on = True -clear-handlers = True +always-on = true +clear-handlers = true filter = -nose log-level = ERROR [test-result] -always-on = True -descriptions = True +always-on = true +descriptions = true [coverage] -always-on = False +always-on = true coverage = openlp coverage-report = html + +[multiprocess] +always-on = false +processes = 4 diff --git a/openlp/core/lib/projector/constants.py b/openlp/core/lib/projector/constants.py index 5c0d6c6c2..748163493 100644 --- a/openlp/core/lib/projector/constants.py +++ b/openlp/core/lib/projector/constants.py @@ -131,227 +131,243 @@ S_INFO = 310 S_NETWORK_SENDING = 400 S_NETWORK_RECEIVED = 401 -CONNECTION_ERRORS = {E_NOT_CONNECTED, E_NO_AUTHENTICATION, E_AUTHENTICATION, E_CLASS, - E_PREFIX, E_CONNECTION_REFUSED, E_REMOTE_HOST_CLOSED_CONNECTION, - E_HOST_NOT_FOUND, E_SOCKET_ACCESS, E_SOCKET_RESOURCE, E_SOCKET_TIMEOUT, - E_DATAGRAM_TOO_LARGE, E_NETWORK, E_ADDRESS_IN_USE, E_SOCKET_ADDRESS_NOT_AVAILABLE, - E_UNSUPPORTED_SOCKET_OPERATION, E_PROXY_AUTHENTICATION_REQUIRED, - E_SLS_HANDSHAKE_FAILED, E_UNFINISHED_SOCKET_OPERATION, E_PROXY_CONNECTION_REFUSED, - E_PROXY_CONNECTION_CLOSED, E_PROXY_CONNECTION_TIMEOUT, E_PROXY_NOT_FOUND, - E_PROXY_PROTOCOL, E_UNKNOWN_SOCKET_ERROR - } +CONNECTION_ERRORS = { + E_NOT_CONNECTED, E_NO_AUTHENTICATION, E_AUTHENTICATION, E_CLASS, + E_PREFIX, E_CONNECTION_REFUSED, E_REMOTE_HOST_CLOSED_CONNECTION, + E_HOST_NOT_FOUND, E_SOCKET_ACCESS, E_SOCKET_RESOURCE, E_SOCKET_TIMEOUT, + E_DATAGRAM_TOO_LARGE, E_NETWORK, E_ADDRESS_IN_USE, E_SOCKET_ADDRESS_NOT_AVAILABLE, + E_UNSUPPORTED_SOCKET_OPERATION, E_PROXY_AUTHENTICATION_REQUIRED, + E_SLS_HANDSHAKE_FAILED, E_UNFINISHED_SOCKET_OPERATION, E_PROXY_CONNECTION_REFUSED, + E_PROXY_CONNECTION_CLOSED, E_PROXY_CONNECTION_TIMEOUT, E_PROXY_NOT_FOUND, + E_PROXY_PROTOCOL, E_UNKNOWN_SOCKET_ERROR +} -PJLINK_ERRORS = {'ERRA': E_AUTHENTICATION, # Authentication error - 'ERR1': E_UNDEFINED, # Undefined command error - 'ERR2': E_PARAMETER, # Invalid parameter error - 'ERR3': E_UNAVAILABLE, # Projector busy - 'ERR4': E_PROJECTOR, # Projector or display failure - E_AUTHENTICATION: 'ERRA', - E_UNDEFINED: 'ERR1', - E_PARAMETER: 'ERR2', - E_UNAVAILABLE: 'ERR3', - E_PROJECTOR: 'ERR4'} +PJLINK_ERRORS = { + 'ERRA': E_AUTHENTICATION, # Authentication error + 'ERR1': E_UNDEFINED, # Undefined command error + 'ERR2': E_PARAMETER, # Invalid parameter error + 'ERR3': E_UNAVAILABLE, # Projector busy + 'ERR4': E_PROJECTOR, # Projector or display failure + E_AUTHENTICATION: 'ERRA', + E_UNDEFINED: 'ERR1', + E_PARAMETER: 'ERR2', + E_UNAVAILABLE: 'ERR3', + E_PROJECTOR: 'ERR4' +} # Map error/status codes to string -ERROR_STRING = {0: 'S_OK', - E_GENERAL: 'E_GENERAL', - E_NOT_CONNECTED: 'E_NOT_CONNECTED', - E_FAN: 'E_FAN', - E_LAMP: 'E_LAMP', - E_TEMP: 'E_TEMP', - E_COVER: 'E_COVER', - E_FILTER: 'E_FILTER', - E_AUTHENTICATION: 'E_AUTHENTICATION', - E_NO_AUTHENTICATION: 'E_NO_AUTHENTICATION', - E_UNDEFINED: 'E_UNDEFINED', - E_PARAMETER: 'E_PARAMETER', - E_UNAVAILABLE: 'E_UNAVAILABLE', - E_PROJECTOR: 'E_PROJECTOR', - E_INVALID_DATA: 'E_INVALID_DATA', - E_WARN: 'E_WARN', - E_ERROR: 'E_ERROR', - E_CLASS: 'E_CLASS', - E_PREFIX: 'E_PREFIX', # Last projector error - E_CONNECTION_REFUSED: 'E_CONNECTION_REFUSED', # First QtSocket error - E_REMOTE_HOST_CLOSED_CONNECTION: 'E_REMOTE_HOST_CLOSED_CONNECTION', - E_HOST_NOT_FOUND: 'E_HOST_NOT_FOUND', - E_SOCKET_ACCESS: 'E_SOCKET_ACCESS', - E_SOCKET_RESOURCE: 'E_SOCKET_RESOURCE', - E_SOCKET_TIMEOUT: 'E_SOCKET_TIMEOUT', - E_DATAGRAM_TOO_LARGE: 'E_DATAGRAM_TOO_LARGE', - E_NETWORK: 'E_NETWORK', - E_ADDRESS_IN_USE: 'E_ADDRESS_IN_USE', - E_SOCKET_ADDRESS_NOT_AVAILABLE: 'E_SOCKET_ADDRESS_NOT_AVAILABLE', - E_UNSUPPORTED_SOCKET_OPERATION: 'E_UNSUPPORTED_SOCKET_OPERATION', - E_PROXY_AUTHENTICATION_REQUIRED: 'E_PROXY_AUTHENTICATION_REQUIRED', - E_SLS_HANDSHAKE_FAILED: 'E_SLS_HANDSHAKE_FAILED', - E_UNFINISHED_SOCKET_OPERATION: 'E_UNFINISHED_SOCKET_OPERATION', - E_PROXY_CONNECTION_REFUSED: 'E_PROXY_CONNECTION_REFUSED', - E_PROXY_CONNECTION_CLOSED: 'E_PROXY_CONNECTION_CLOSED', - E_PROXY_CONNECTION_TIMEOUT: 'E_PROXY_CONNECTION_TIMEOUT', - E_PROXY_NOT_FOUND: 'E_PROXY_NOT_FOUND', - E_PROXY_PROTOCOL: 'E_PROXY_PROTOCOL', - E_UNKNOWN_SOCKET_ERROR: 'E_UNKNOWN_SOCKET_ERROR'} +ERROR_STRING = { + 0: 'S_OK', + E_GENERAL: 'E_GENERAL', + E_NOT_CONNECTED: 'E_NOT_CONNECTED', + E_FAN: 'E_FAN', + E_LAMP: 'E_LAMP', + E_TEMP: 'E_TEMP', + E_COVER: 'E_COVER', + E_FILTER: 'E_FILTER', + E_AUTHENTICATION: 'E_AUTHENTICATION', + E_NO_AUTHENTICATION: 'E_NO_AUTHENTICATION', + E_UNDEFINED: 'E_UNDEFINED', + E_PARAMETER: 'E_PARAMETER', + E_UNAVAILABLE: 'E_UNAVAILABLE', + E_PROJECTOR: 'E_PROJECTOR', + E_INVALID_DATA: 'E_INVALID_DATA', + E_WARN: 'E_WARN', + E_ERROR: 'E_ERROR', + E_CLASS: 'E_CLASS', + E_PREFIX: 'E_PREFIX', # Last projector error + E_CONNECTION_REFUSED: 'E_CONNECTION_REFUSED', # First QtSocket error + E_REMOTE_HOST_CLOSED_CONNECTION: 'E_REMOTE_HOST_CLOSED_CONNECTION', + E_HOST_NOT_FOUND: 'E_HOST_NOT_FOUND', + E_SOCKET_ACCESS: 'E_SOCKET_ACCESS', + E_SOCKET_RESOURCE: 'E_SOCKET_RESOURCE', + E_SOCKET_TIMEOUT: 'E_SOCKET_TIMEOUT', + E_DATAGRAM_TOO_LARGE: 'E_DATAGRAM_TOO_LARGE', + E_NETWORK: 'E_NETWORK', + E_ADDRESS_IN_USE: 'E_ADDRESS_IN_USE', + E_SOCKET_ADDRESS_NOT_AVAILABLE: 'E_SOCKET_ADDRESS_NOT_AVAILABLE', + E_UNSUPPORTED_SOCKET_OPERATION: 'E_UNSUPPORTED_SOCKET_OPERATION', + E_PROXY_AUTHENTICATION_REQUIRED: 'E_PROXY_AUTHENTICATION_REQUIRED', + E_SLS_HANDSHAKE_FAILED: 'E_SLS_HANDSHAKE_FAILED', + E_UNFINISHED_SOCKET_OPERATION: 'E_UNFINISHED_SOCKET_OPERATION', + E_PROXY_CONNECTION_REFUSED: 'E_PROXY_CONNECTION_REFUSED', + E_PROXY_CONNECTION_CLOSED: 'E_PROXY_CONNECTION_CLOSED', + E_PROXY_CONNECTION_TIMEOUT: 'E_PROXY_CONNECTION_TIMEOUT', + E_PROXY_NOT_FOUND: 'E_PROXY_NOT_FOUND', + E_PROXY_PROTOCOL: 'E_PROXY_PROTOCOL', + E_UNKNOWN_SOCKET_ERROR: 'E_UNKNOWN_SOCKET_ERROR' +} -STATUS_STRING = {S_NOT_CONNECTED: 'S_NOT_CONNECTED', - S_CONNECTING: 'S_CONNECTING', - S_CONNECTED: 'S_CONNECTED', - S_STATUS: 'S_STATUS', - S_OFF: 'S_OFF', - S_INITIALIZE: 'S_INITIALIZE', - S_STANDBY: 'S_STANDBY', - S_WARMUP: 'S_WARMUP', - S_ON: 'S_ON', - S_COOLDOWN: 'S_COOLDOWN', - S_INFO: 'S_INFO', - S_NETWORK_SENDING: 'S_NETWORK_SENDING', - S_NETWORK_RECEIVED: 'S_NETWORK_RECEIVED'} +STATUS_STRING = { + S_NOT_CONNECTED: 'S_NOT_CONNECTED', + S_CONNECTING: 'S_CONNECTING', + S_CONNECTED: 'S_CONNECTED', + S_STATUS: 'S_STATUS', + S_OFF: 'S_OFF', + S_INITIALIZE: 'S_INITIALIZE', + S_STANDBY: 'S_STANDBY', + S_WARMUP: 'S_WARMUP', + S_ON: 'S_ON', + S_COOLDOWN: 'S_COOLDOWN', + S_INFO: 'S_INFO', + S_NETWORK_SENDING: 'S_NETWORK_SENDING', + S_NETWORK_RECEIVED: 'S_NETWORK_RECEIVED' +} # Map error/status codes to message strings -ERROR_MSG = {E_OK: translate('OpenLP.ProjectorConstants', 'OK'), # E_OK | S_OK - E_GENERAL: translate('OpenLP.ProjectorConstants', 'General projector error'), - E_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Not connected error'), - E_LAMP: translate('OpenLP.ProjectorConstants', 'Lamp error'), - E_FAN: translate('OpenLP.ProjectorConstants', 'Fan error'), - E_TEMP: translate('OpenLP.ProjectorConstants', 'High temperature detected'), - E_COVER: translate('OpenLP.ProjectorConstants', 'Cover open detected'), - E_FILTER: translate('OpenLP.ProjectorConstants', 'Check filter'), - E_AUTHENTICATION: translate('OpenLP.ProjectorConstants', 'Authentication Error'), - E_UNDEFINED: translate('OpenLP.ProjectorConstants', 'Undefined Command'), - E_PARAMETER: translate('OpenLP.ProjectorConstants', 'Invalid Parameter'), - E_UNAVAILABLE: translate('OpenLP.ProjectorConstants', 'Projector Busy'), - E_PROJECTOR: translate('OpenLP.ProjectorConstants', 'Projector/Display Error'), - E_INVALID_DATA: translate('OpenLP.ProjectorConstants', 'Invalid packet received'), - E_WARN: translate('OpenLP.ProjectorConstants', 'Warning condition detected'), - E_ERROR: translate('OpenLP.ProjectorConstants', 'Error condition detected'), - E_CLASS: translate('OpenLP.ProjectorConstants', 'PJLink class not supported'), - E_PREFIX: translate('OpenLP.ProjectorConstants', 'Invalid prefix character'), - E_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants', - 'The connection was refused by the peer (or timed out)'), - E_REMOTE_HOST_CLOSED_CONNECTION: translate('OpenLP.ProjectorConstants', - 'The remote host closed the connection'), - E_HOST_NOT_FOUND: translate('OpenLP.ProjectorConstants', 'The host address was not found'), - E_SOCKET_ACCESS: translate('OpenLP.ProjectorConstants', - 'The socket operation failed because the application ' - 'lacked the required privileges'), - E_SOCKET_RESOURCE: translate('OpenLP.ProjectorConstants', - 'The local system ran out of resources (e.g., too many sockets)'), - E_SOCKET_TIMEOUT: translate('OpenLP.ProjectorConstants', - 'The socket operation timed out'), - E_DATAGRAM_TOO_LARGE: translate('OpenLP.ProjectorConstants', - 'The datagram was larger than the operating system\'s limit'), - E_NETWORK: translate('OpenLP.ProjectorConstants', - 'An error occurred with the network (Possibly someone pulled the plug?)'), - E_ADDRESS_IN_USE: translate('OpenLP.ProjectorConstants', - 'The address specified with socket.bind() ' - 'is already in use and was set to be exclusive'), - E_SOCKET_ADDRESS_NOT_AVAILABLE: translate('OpenLP.ProjectorConstants', - 'The address specified to socket.bind() ' - 'does not belong to the host'), - E_UNSUPPORTED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants', - 'The requested socket operation is not supported by the local ' - 'operating system (e.g., lack of IPv6 support)'), - E_PROXY_AUTHENTICATION_REQUIRED: translate('OpenLP.ProjectorConstants', - 'The socket is using a proxy, ' - 'and the proxy requires authentication'), - E_SLS_HANDSHAKE_FAILED: translate('OpenLP.ProjectorConstants', - 'The SSL/TLS handshake failed'), - E_UNFINISHED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants', - 'The last operation attempted has not finished yet ' - '(still in progress in the background)'), - E_PROXY_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants', - 'Could not contact the proxy server because the connection ' - 'to that server was denied'), - E_PROXY_CONNECTION_CLOSED: translate('OpenLP.ProjectorConstants', - 'The connection to the proxy server was closed unexpectedly ' - '(before the connection to the final peer was established)'), - E_PROXY_CONNECTION_TIMEOUT: translate('OpenLP.ProjectorConstants', - 'The connection to the proxy server timed out or the proxy ' - 'server stopped responding in the authentication phase.'), - E_PROXY_NOT_FOUND: translate('OpenLP.ProjectorConstants', - 'The proxy address set with setProxy() was not found'), - E_PROXY_PROTOCOL: translate('OpenLP.ProjectorConstants', - 'The connection negotiation with the proxy server failed because the ' - 'response from the proxy server could not be understood'), - E_UNKNOWN_SOCKET_ERROR: translate('OpenLP.ProjectorConstants', 'An unidentified error occurred'), - S_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Not connected'), - S_CONNECTING: translate('OpenLP.ProjectorConstants', 'Connecting'), - S_CONNECTED: translate('OpenLP.ProjectorConstants', 'Connected'), - S_STATUS: translate('OpenLP.ProjectorConstants', 'Getting status'), - S_OFF: translate('OpenLP.ProjectorConstants', 'Off'), - S_INITIALIZE: translate('OpenLP.ProjectorConstants', 'Initialize in progress'), - S_STANDBY: translate('OpenLP.ProjectorConstants', 'Power in standby'), - S_WARMUP: translate('OpenLP.ProjectorConstants', 'Warmup in progress'), - S_ON: translate('OpenLP.ProjectorConstants', 'Power is on'), - S_COOLDOWN: translate('OpenLP.ProjectorConstants', 'Cooldown in progress'), - S_INFO: translate('OpenLP.ProjectorConstants', 'Projector Information available'), - S_NETWORK_SENDING: translate('OpenLP.ProjectorConstants', 'Sending data'), - S_NETWORK_RECEIVED: translate('OpenLP.ProjectorConstants', 'Received data')} +ERROR_MSG = { + E_OK: translate('OpenLP.ProjectorConstants', 'OK'), # E_OK | S_OK + E_GENERAL: translate('OpenLP.ProjectorConstants', 'General projector error'), + E_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Not connected error'), + E_LAMP: translate('OpenLP.ProjectorConstants', 'Lamp error'), + E_FAN: translate('OpenLP.ProjectorConstants', 'Fan error'), + E_TEMP: translate('OpenLP.ProjectorConstants', 'High temperature detected'), + E_COVER: translate('OpenLP.ProjectorConstants', 'Cover open detected'), + E_FILTER: translate('OpenLP.ProjectorConstants', 'Check filter'), + E_AUTHENTICATION: translate('OpenLP.ProjectorConstants', 'Authentication Error'), + E_UNDEFINED: translate('OpenLP.ProjectorConstants', 'Undefined Command'), + E_PARAMETER: translate('OpenLP.ProjectorConstants', 'Invalid Parameter'), + E_UNAVAILABLE: translate('OpenLP.ProjectorConstants', 'Projector Busy'), + E_PROJECTOR: translate('OpenLP.ProjectorConstants', 'Projector/Display Error'), + E_INVALID_DATA: translate('OpenLP.ProjectorConstants', 'Invalid packet received'), + E_WARN: translate('OpenLP.ProjectorConstants', 'Warning condition detected'), + E_ERROR: translate('OpenLP.ProjectorConstants', 'Error condition detected'), + E_CLASS: translate('OpenLP.ProjectorConstants', 'PJLink class not supported'), + E_PREFIX: translate('OpenLP.ProjectorConstants', 'Invalid prefix character'), + E_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants', + 'The connection was refused by the peer (or timed out)'), + E_REMOTE_HOST_CLOSED_CONNECTION: translate('OpenLP.ProjectorConstants', + 'The remote host closed the connection'), + E_HOST_NOT_FOUND: translate('OpenLP.ProjectorConstants', 'The host address was not found'), + E_SOCKET_ACCESS: translate('OpenLP.ProjectorConstants', + 'The socket operation failed because the application ' + 'lacked the required privileges'), + E_SOCKET_RESOURCE: translate('OpenLP.ProjectorConstants', + 'The local system ran out of resources (e.g., too many sockets)'), + E_SOCKET_TIMEOUT: translate('OpenLP.ProjectorConstants', + 'The socket operation timed out'), + E_DATAGRAM_TOO_LARGE: translate('OpenLP.ProjectorConstants', + 'The datagram was larger than the operating system\'s limit'), + E_NETWORK: translate('OpenLP.ProjectorConstants', + 'An error occurred with the network (Possibly someone pulled the plug?)'), + E_ADDRESS_IN_USE: translate('OpenLP.ProjectorConstants', + 'The address specified with socket.bind() ' + 'is already in use and was set to be exclusive'), + E_SOCKET_ADDRESS_NOT_AVAILABLE: translate('OpenLP.ProjectorConstants', + 'The address specified to socket.bind() ' + 'does not belong to the host'), + E_UNSUPPORTED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants', + 'The requested socket operation is not supported by the local ' + 'operating system (e.g., lack of IPv6 support)'), + E_PROXY_AUTHENTICATION_REQUIRED: translate('OpenLP.ProjectorConstants', + 'The socket is using a proxy, ' + 'and the proxy requires authentication'), + E_SLS_HANDSHAKE_FAILED: translate('OpenLP.ProjectorConstants', + 'The SSL/TLS handshake failed'), + E_UNFINISHED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants', + 'The last operation attempted has not finished yet ' + '(still in progress in the background)'), + E_PROXY_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants', + 'Could not contact the proxy server because the connection ' + 'to that server was denied'), + E_PROXY_CONNECTION_CLOSED: translate('OpenLP.ProjectorConstants', + 'The connection to the proxy server was closed unexpectedly ' + '(before the connection to the final peer was established)'), + E_PROXY_CONNECTION_TIMEOUT: translate('OpenLP.ProjectorConstants', + 'The connection to the proxy server timed out or the proxy ' + 'server stopped responding in the authentication phase.'), + E_PROXY_NOT_FOUND: translate('OpenLP.ProjectorConstants', + 'The proxy address set with setProxy() was not found'), + E_PROXY_PROTOCOL: translate('OpenLP.ProjectorConstants', + 'The connection negotiation with the proxy server failed because the ' + 'response from the proxy server could not be understood'), + E_UNKNOWN_SOCKET_ERROR: translate('OpenLP.ProjectorConstants', 'An unidentified error occurred'), + S_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Not connected'), + S_CONNECTING: translate('OpenLP.ProjectorConstants', 'Connecting'), + S_CONNECTED: translate('OpenLP.ProjectorConstants', 'Connected'), + S_STATUS: translate('OpenLP.ProjectorConstants', 'Getting status'), + S_OFF: translate('OpenLP.ProjectorConstants', 'Off'), + S_INITIALIZE: translate('OpenLP.ProjectorConstants', 'Initialize in progress'), + S_STANDBY: translate('OpenLP.ProjectorConstants', 'Power in standby'), + S_WARMUP: translate('OpenLP.ProjectorConstants', 'Warmup in progress'), + S_ON: translate('OpenLP.ProjectorConstants', 'Power is on'), + S_COOLDOWN: translate('OpenLP.ProjectorConstants', 'Cooldown in progress'), + S_INFO: translate('OpenLP.ProjectorConstants', 'Projector Information available'), + S_NETWORK_SENDING: translate('OpenLP.ProjectorConstants', 'Sending data'), + S_NETWORK_RECEIVED: translate('OpenLP.ProjectorConstants', 'Received data') +} # Map for ERST return codes to string -PJLINK_ERST_STATUS = {'0': ERROR_STRING[E_OK], - '1': ERROR_STRING[E_WARN], - '2': ERROR_STRING[E_ERROR]} +PJLINK_ERST_STATUS = { + '0': ERROR_STRING[E_OK], + '1': ERROR_STRING[E_WARN], + '2': ERROR_STRING[E_ERROR] +} # Map for POWR return codes to status code -PJLINK_POWR_STATUS = {'0': S_STANDBY, - '1': S_ON, - '2': S_COOLDOWN, - '3': S_WARMUP, - S_STANDBY: '0', - S_ON: '1', - S_COOLDOWN: '2', - S_WARMUP: '3'} +PJLINK_POWR_STATUS = { + '0': S_STANDBY, + '1': S_ON, + '2': S_COOLDOWN, + '3': S_WARMUP, + S_STANDBY: '0', + S_ON: '1', + S_COOLDOWN: '2', + S_WARMUP: '3' +} -PJLINK_DEFAULT_SOURCES = {'1': translate('OpenLP.DB', 'RGB'), - '2': translate('OpenLP.DB', 'Video'), - '3': translate('OpenLP.DB', 'Digital'), - '4': translate('OpenLP.DB', 'Storage'), - '5': translate('OpenLP.DB', 'Network')} +PJLINK_DEFAULT_SOURCES = { + '1': translate('OpenLP.DB', 'RGB'), + '2': translate('OpenLP.DB', 'Video'), + '3': translate('OpenLP.DB', 'Digital'), + '4': translate('OpenLP.DB', 'Storage'), + '5': translate('OpenLP.DB', 'Network') +} -PJLINK_DEFAULT_CODES = {'11': translate('OpenLP.DB', 'RGB 1'), - '12': translate('OpenLP.DB', 'RGB 2'), - '13': translate('OpenLP.DB', 'RGB 3'), - '14': translate('OpenLP.DB', 'RGB 4'), - '15': translate('OpenLP.DB', 'RGB 5'), - '16': translate('OpenLP.DB', 'RGB 6'), - '17': translate('OpenLP.DB', 'RGB 7'), - '18': translate('OpenLP.DB', 'RGB 8'), - '19': translate('OpenLP.DB', 'RGB 9'), - '21': translate('OpenLP.DB', 'Video 1'), - '22': translate('OpenLP.DB', 'Video 2'), - '23': translate('OpenLP.DB', 'Video 3'), - '24': translate('OpenLP.DB', 'Video 4'), - '25': translate('OpenLP.DB', 'Video 5'), - '26': translate('OpenLP.DB', 'Video 6'), - '27': translate('OpenLP.DB', 'Video 7'), - '28': translate('OpenLP.DB', 'Video 8'), - '29': translate('OpenLP.DB', 'Video 9'), - '31': translate('OpenLP.DB', 'Digital 1'), - '32': translate('OpenLP.DB', 'Digital 2'), - '33': translate('OpenLP.DB', 'Digital 3'), - '34': translate('OpenLP.DB', 'Digital 4'), - '35': translate('OpenLP.DB', 'Digital 5'), - '36': translate('OpenLP.DB', 'Digital 6'), - '37': translate('OpenLP.DB', 'Digital 7'), - '38': translate('OpenLP.DB', 'Digital 8'), - '39': translate('OpenLP.DB', 'Digital 9'), - '41': translate('OpenLP.DB', 'Storage 1'), - '42': translate('OpenLP.DB', 'Storage 2'), - '43': translate('OpenLP.DB', 'Storage 3'), - '44': translate('OpenLP.DB', 'Storage 4'), - '45': translate('OpenLP.DB', 'Storage 5'), - '46': translate('OpenLP.DB', 'Storage 6'), - '47': translate('OpenLP.DB', 'Storage 7'), - '48': translate('OpenLP.DB', 'Storage 8'), - '49': translate('OpenLP.DB', 'Storage 9'), - '51': translate('OpenLP.DB', 'Network 1'), - '52': translate('OpenLP.DB', 'Network 2'), - '53': translate('OpenLP.DB', 'Network 3'), - '54': translate('OpenLP.DB', 'Network 4'), - '55': translate('OpenLP.DB', 'Network 5'), - '56': translate('OpenLP.DB', 'Network 6'), - '57': translate('OpenLP.DB', 'Network 7'), - '58': translate('OpenLP.DB', 'Network 8'), - '59': translate('OpenLP.DB', 'Network 9') - } +PJLINK_DEFAULT_CODES = { + '11': translate('OpenLP.DB', 'RGB 1'), + '12': translate('OpenLP.DB', 'RGB 2'), + '13': translate('OpenLP.DB', 'RGB 3'), + '14': translate('OpenLP.DB', 'RGB 4'), + '15': translate('OpenLP.DB', 'RGB 5'), + '16': translate('OpenLP.DB', 'RGB 6'), + '17': translate('OpenLP.DB', 'RGB 7'), + '18': translate('OpenLP.DB', 'RGB 8'), + '19': translate('OpenLP.DB', 'RGB 9'), + '21': translate('OpenLP.DB', 'Video 1'), + '22': translate('OpenLP.DB', 'Video 2'), + '23': translate('OpenLP.DB', 'Video 3'), + '24': translate('OpenLP.DB', 'Video 4'), + '25': translate('OpenLP.DB', 'Video 5'), + '26': translate('OpenLP.DB', 'Video 6'), + '27': translate('OpenLP.DB', 'Video 7'), + '28': translate('OpenLP.DB', 'Video 8'), + '29': translate('OpenLP.DB', 'Video 9'), + '31': translate('OpenLP.DB', 'Digital 1'), + '32': translate('OpenLP.DB', 'Digital 2'), + '33': translate('OpenLP.DB', 'Digital 3'), + '34': translate('OpenLP.DB', 'Digital 4'), + '35': translate('OpenLP.DB', 'Digital 5'), + '36': translate('OpenLP.DB', 'Digital 6'), + '37': translate('OpenLP.DB', 'Digital 7'), + '38': translate('OpenLP.DB', 'Digital 8'), + '39': translate('OpenLP.DB', 'Digital 9'), + '41': translate('OpenLP.DB', 'Storage 1'), + '42': translate('OpenLP.DB', 'Storage 2'), + '43': translate('OpenLP.DB', 'Storage 3'), + '44': translate('OpenLP.DB', 'Storage 4'), + '45': translate('OpenLP.DB', 'Storage 5'), + '46': translate('OpenLP.DB', 'Storage 6'), + '47': translate('OpenLP.DB', 'Storage 7'), + '48': translate('OpenLP.DB', 'Storage 8'), + '49': translate('OpenLP.DB', 'Storage 9'), + '51': translate('OpenLP.DB', 'Network 1'), + '52': translate('OpenLP.DB', 'Network 2'), + '53': translate('OpenLP.DB', 'Network 3'), + '54': translate('OpenLP.DB', 'Network 4'), + '55': translate('OpenLP.DB', 'Network 5'), + '56': translate('OpenLP.DB', 'Network 6'), + '57': translate('OpenLP.DB', 'Network 7'), + '58': translate('OpenLP.DB', 'Network 8'), + '59': translate('OpenLP.DB', 'Network 9') +} diff --git a/openlp/core/lib/projector/pjlink1.py b/openlp/core/lib/projector/pjlink1.py index ed7b82209..555c2f5be 100644 --- a/openlp/core/lib/projector/pjlink1.py +++ b/openlp/core/lib/projector/pjlink1.py @@ -46,15 +46,19 @@ __all__ = ['PJLink1'] from codecs import decode -from PyQt5.QtCore import pyqtSignal, pyqtSlot -from PyQt5.QtNetwork import QAbstractSocket, QTcpSocket +from PyQt5 import QtCore, QtNetwork from openlp.core.common import translate, qmd5_hash -from openlp.core.lib.projector.constants import * +from openlp.core.lib.projector.constants import CONNECTION_ERRORS, CR, ERROR_MSG, ERROR_STRING, \ + E_AUTHENTICATION, E_CONNECTION_REFUSED, E_GENERAL, E_INVALID_DATA, E_NETWORK, E_NOT_CONNECTED, \ + E_PARAMETER, E_PROJECTOR, E_SOCKET_TIMEOUT, E_UNAVAILABLE, E_UNDEFINED, PJLINK_ERRORS, \ + PJLINK_ERST_STATUS, PJLINK_MAX_PACKET, PJLINK_PORT, PJLINK_POWR_STATUS, PJLINK_VALID_CMD, \ + STATUS_STRING, S_CONNECTED, S_CONNECTING, S_NETWORK_RECEIVED, S_NETWORK_SENDING, S_NOT_CONNECTED, \ + S_OFF, S_OK, S_ON, S_STATUS # Shortcuts -SocketError = QAbstractSocket.SocketError -SocketSTate = QAbstractSocket.SocketState +SocketError = QtNetwork.QAbstractSocket.SocketError +SocketSTate = QtNetwork.QAbstractSocket.SocketState PJLINK_PREFIX = '%' PJLINK_CLASS = '1' @@ -62,18 +66,18 @@ PJLINK_HEADER = '{prefix}{linkclass}'.format(prefix=PJLINK_PREFIX, linkclass=PJL PJLINK_SUFFIX = CR -class PJLink1(QTcpSocket): +class PJLink1(QtNetwork.QTcpSocket): """ Socket service for connecting to a PJLink-capable projector. """ # Signals sent by this module - changeStatus = pyqtSignal(str, int, str) - projectorNetwork = pyqtSignal(int) # Projector network activity - projectorStatus = pyqtSignal(int) # Status update - projectorAuthentication = pyqtSignal(str) # Authentication error - projectorNoAuthentication = pyqtSignal(str) # PIN set and no authentication needed - projectorReceivedData = pyqtSignal() # Notify when received data finished processing - projectorUpdateIcons = pyqtSignal() # Update the status icons on toolbar + changeStatus = QtCore.pyqtSignal(str, int, str) + projectorNetwork = QtCore.pyqtSignal(int) # Projector network activity + projectorStatus = QtCore.pyqtSignal(int) # Status update + projectorAuthentication = QtCore.pyqtSignal(str) # Authentication error + projectorNoAuthentication = QtCore.pyqtSignal(str) # PIN set and no authentication needed + projectorReceivedData = QtCore.pyqtSignal() # Notify when received data finished processing + projectorUpdateIcons = QtCore.pyqtSignal() # Update the status icons on toolbar def __init__(self, name=None, ip=None, port=PJLINK_PORT, pin=None, *args, **kwargs): """ @@ -116,8 +120,8 @@ class PJLink1(QTcpSocket): self.error_status = S_OK # Socket information # Add enough space to input buffer for extraneous \n \r - self.maxSize = PJLINK_MAX_PACKET + 2 - self.setReadBufferSize(self.maxSize) + self.max_size = PJLINK_MAX_PACKET + 2 + self.setReadBufferSize(self.max_size) # PJLink information self.pjlink_class = '1' # Default class self.reset_information() @@ -129,19 +133,20 @@ class PJLink1(QTcpSocket): # Socket timer for some possible brain-dead projectors or network cable pulled self.socket_timer = None # Map command to function - self.PJLINK1_FUNC = {'AVMT': self.process_avmt, - 'CLSS': self.process_clss, - 'ERST': self.process_erst, - 'INFO': self.process_info, - 'INF1': self.process_inf1, - 'INF2': self.process_inf2, - 'INPT': self.process_inpt, - 'INST': self.process_inst, - 'LAMP': self.process_lamp, - 'NAME': self.process_name, - 'PJLINK': self.check_login, - 'POWR': self.process_powr - } + self.pjlink1_functions = { + 'AVMT': self.process_avmt, + 'CLSS': self.process_clss, + 'ERST': self.process_erst, + 'INFO': self.process_info, + 'INF1': self.process_inf1, + 'INF2': self.process_inf2, + 'INPT': self.process_inpt, + 'INST': self.process_inst, + 'LAMP': self.process_lamp, + 'NAME': self.process_name, + 'PJLINK': self.check_login, + 'POWR': self.process_powr + } def reset_information(self): """ @@ -291,7 +296,7 @@ class PJLink1(QTcpSocket): message=status_message if msg is None else msg)) self.changeStatus.emit(self.ip, status, message) - @pyqtSlot() + @QtCore.pyqtSlot() def check_login(self, data=None): """ Processes the initial connection and authentication (if needed). @@ -309,8 +314,8 @@ class PJLink1(QTcpSocket): log.error('({ip}) Socket timeout waiting for login'.format(ip=self.ip)) self.change_status(E_SOCKET_TIMEOUT) return - read = self.readLine(self.maxSize) - dontcare = self.readLine(self.maxSize) # Clean out the trailing \r\n + read = self.readLine(self.max_size) + dontcare = self.readLine(self.max_size) # Clean out the trailing \r\n if read is None: log.warning('({ip}) read is None - socket error?'.format(ip=self.ip)) return @@ -320,7 +325,7 @@ class PJLink1(QTcpSocket): data = decode(read, 'ascii') # Possibility of extraneous data on input when reading. # Clean out extraneous characters in buffer. - dontcare = self.readLine(self.maxSize) + dontcare = self.readLine(self.max_size) log.debug('({ip}) check_login() read "{data}"'.format(ip=self.ip, data=data.strip())) # At this point, we should only have the initial login prompt with # possible authentication @@ -379,7 +384,7 @@ class PJLink1(QTcpSocket): self.timer.setInterval(2000) # Set 2 seconds for initial information self.timer.start() - @pyqtSlot() + @QtCore.pyqtSlot() def get_data(self): """ Socket interface to retrieve data. @@ -389,7 +394,7 @@ class PJLink1(QTcpSocket): log.debug('({ip}) get_data(): Not connected - returning'.format(ip=self.ip)) self.send_busy = False return - read = self.readLine(self.maxSize) + read = self.readLine(self.max_size) if read == -1: # No data available log.debug('({ip}) get_data(): No data available (-1)'.format(ip=self.ip)) @@ -436,7 +441,7 @@ class PJLink1(QTcpSocket): return return self.process_command(cmd, data) - @pyqtSlot(QAbstractSocket.SocketError) + @QtCore.pyqtSlot(QtNetwork.QAbstractSocket.SocketError) def get_error(self, err): """ Process error from SocketError signal. @@ -504,7 +509,7 @@ class PJLink1(QTcpSocket): log.debug('({ip}) send_command() calling _send_string()'.format(ip=self.ip)) self._send_command() - @pyqtSlot() + @QtCore.pyqtSlot() def _send_command(self, data=None): """ Socket interface to send data. If data=None, then check queue. @@ -586,8 +591,8 @@ class PJLink1(QTcpSocket): self.projectorReceivedData.emit() return - if cmd in self.PJLINK1_FUNC: - self.PJLINK1_FUNC[cmd](data) + if cmd in self.pjlink1_functions: + self.pjlink1_functions[cmd](data) else: log.warning('({ip}) Invalid command {data}'.format(ip=self.ip, data=cmd)) self.send_busy = False @@ -812,9 +817,9 @@ class PJLink1(QTcpSocket): log.warning('({ip}) connect_to_host(): Already connected - returning'.format(ip=self.ip)) return self.change_status(S_CONNECTING) - self.connectToHost(self.ip, self.port if type(self.port) is int else int(self.port)) + self.connectToHost(self.ip, self.port if isinstance(self.port, int) else int(self.port)) - @pyqtSlot() + @QtCore.pyqtSlot() def disconnect_from_host(self, abort=False): """ Close socket and cleanup. diff --git a/openlp/core/ui/projector/editform.py b/openlp/core/ui/projector/editform.py index 4996cc75f..f4cf8a774 100644 --- a/openlp/core/ui/projector/editform.py +++ b/openlp/core/ui/projector/editform.py @@ -30,8 +30,6 @@ log = logging.getLogger(__name__) log.debug('editform loaded') from PyQt5 import QtCore, QtWidgets -from PyQt5.QtCore import pyqtSlot, pyqtSignal -from PyQt5.QtWidgets import QDialog, QPlainTextEdit, QLineEdit, QDialogButtonBox, QLabel, QGridLayout from openlp.core.common import translate, verify_ip_address from openlp.core.lib import build_icon @@ -53,56 +51,56 @@ class Ui_ProjectorEditForm(object): edit_projector_dialog.setMinimumWidth(400) edit_projector_dialog.setModal(True) # Define the basic layout - self.dialog_layout = QGridLayout(edit_projector_dialog) + self.dialog_layout = QtWidgets.QGridLayout(edit_projector_dialog) self.dialog_layout.setObjectName('dialog_layout') self.dialog_layout.setSpacing(8) self.dialog_layout.setContentsMargins(8, 8, 8, 8) # IP Address - self.ip_label = QLabel(edit_projector_dialog) + self.ip_label = QtWidgets.QLabel(edit_projector_dialog) self.ip_label.setObjectName('projector_edit_ip_label') - self.ip_text = QLineEdit(edit_projector_dialog) + self.ip_text = QtWidgets.QLineEdit(edit_projector_dialog) self.ip_text.setObjectName('projector_edit_ip_text') self.dialog_layout.addWidget(self.ip_label, 0, 0) self.dialog_layout.addWidget(self.ip_text, 0, 1) # Port number - self.port_label = QLabel(edit_projector_dialog) + self.port_label = QtWidgets.QLabel(edit_projector_dialog) self.port_label.setObjectName('projector_edit_ip_label') - self.port_text = QLineEdit(edit_projector_dialog) + self.port_text = QtWidgets.QLineEdit(edit_projector_dialog) self.port_text.setObjectName('projector_edit_port_text') self.dialog_layout.addWidget(self.port_label, 1, 0) self.dialog_layout.addWidget(self.port_text, 1, 1) # PIN - self.pin_label = QLabel(edit_projector_dialog) + self.pin_label = QtWidgets.QLabel(edit_projector_dialog) self.pin_label.setObjectName('projector_edit_pin_label') - self.pin_text = QLineEdit(edit_projector_dialog) + self.pin_text = QtWidgets.QLineEdit(edit_projector_dialog) self.pin_label.setObjectName('projector_edit_pin_text') self.dialog_layout.addWidget(self.pin_label, 2, 0) self.dialog_layout.addWidget(self.pin_text, 2, 1) # Name - self.name_label = QLabel(edit_projector_dialog) + self.name_label = QtWidgets.QLabel(edit_projector_dialog) self.name_label.setObjectName('projector_edit_name_label') - self.name_text = QLineEdit(edit_projector_dialog) + self.name_text = QtWidgets.QLineEdit(edit_projector_dialog) self.name_text.setObjectName('projector_edit_name_text') self.dialog_layout.addWidget(self.name_label, 3, 0) self.dialog_layout.addWidget(self.name_text, 3, 1) # Location - self.location_label = QLabel(edit_projector_dialog) + self.location_label = QtWidgets.QLabel(edit_projector_dialog) self.location_label.setObjectName('projector_edit_location_label') - self.location_text = QLineEdit(edit_projector_dialog) + self.location_text = QtWidgets.QLineEdit(edit_projector_dialog) self.location_text.setObjectName('projector_edit_location_text') self.dialog_layout.addWidget(self.location_label, 4, 0) self.dialog_layout.addWidget(self.location_text, 4, 1) # Notes - self.notes_label = QLabel(edit_projector_dialog) + self.notes_label = QtWidgets.QLabel(edit_projector_dialog) self.notes_label.setObjectName('projector_edit_notes_label') - self.notes_text = QPlainTextEdit(edit_projector_dialog) + self.notes_text = QtWidgets.QPlainTextEdit(edit_projector_dialog) self.notes_text.setObjectName('projector_edit_notes_text') self.dialog_layout.addWidget(self.notes_label, 5, 0, alignment=QtCore.Qt.AlignTop) self.dialog_layout.addWidget(self.notes_text, 5, 1) # Time for the buttons - self.button_box = QDialogButtonBox(QDialogButtonBox.Help | - QDialogButtonBox.Save | - QDialogButtonBox.Cancel) + self.button_box = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Help | + QtWidgets.QDialogButtonBox.Save | + QtWidgets.QDialogButtonBox.Cancel) self.dialog_layout.addWidget(self.button_box, 8, 0, 1, 2) def retranslateUi(self, edit_projector_dialog): @@ -128,7 +126,7 @@ class Ui_ProjectorEditForm(object): self.notes_text.insertPlainText(self.projector.notes) -class ProjectorEditForm(QDialog, Ui_ProjectorEditForm): +class ProjectorEditForm(QtWidgets.QDialog, Ui_ProjectorEditForm): """ Class to add or edit a projector entry in the database. @@ -140,8 +138,8 @@ class ProjectorEditForm(QDialog, Ui_ProjectorEditForm): location = Column(String(30)) notes = Column(String(200)) """ - newProjector = pyqtSignal(str) - editProjector = pyqtSignal(object) + newProjector = QtCore.pyqtSignal(str) + editProjector = QtCore.pyqtSignal(object) def __init__(self, parent=None, projectordb=None): super(ProjectorEditForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint) @@ -159,10 +157,10 @@ class ProjectorEditForm(QDialog, Ui_ProjectorEditForm): self.projector = projector self.new_projector = False self.retranslateUi(self) - reply = QDialog.exec(self) + reply = QtWidgets.QDialog.exec(self) return reply - @pyqtSlot() + @QtCore.pyqtSlot() def accept_me(self): """ Validate input before accepting input. @@ -247,14 +245,14 @@ class ProjectorEditForm(QDialog, Ui_ProjectorEditForm): self.editProjector.emit(self.projector) self.close() - @pyqtSlot() + @QtCore.pyqtSlot() def help_me(self): """ Show a help message about the input fields. """ log.debug('help_me() signal received') - @pyqtSlot() + @QtCore.pyqtSlot() def cancel_me(self): """ Cancel button clicked - just close. diff --git a/openlp/core/ui/projector/manager.py b/openlp/core/ui/projector/manager.py index 7c56c2916..bfb58232f 100644 --- a/openlp/core/ui/projector/manager.py +++ b/openlp/core/ui/projector/manager.py @@ -26,43 +26,46 @@ """ import logging -log = logging.getLogger(__name__) -log.debug('projectormanager loaded') from PyQt5 import QtCore, QtGui, QtWidgets -from PyQt5.QtCore import QObject, QThread, pyqtSlot -from PyQt5.QtWidgets import QWidget from openlp.core.common import RegistryProperties, Settings, OpenLPMixin, \ RegistryMixin, translate from openlp.core.ui.lib import OpenLPToolbar from openlp.core.lib.ui import create_widget_action from openlp.core.lib.projector import DialogSourceStyle -from openlp.core.lib.projector.constants import * +from openlp.core.lib.projector.constants import ERROR_MSG, ERROR_STRING, E_AUTHENTICATION, E_ERROR, \ + E_NETWORK, E_NOT_CONNECTED, E_UNKNOWN_SOCKET_ERROR, STATUS_STRING, S_CONNECTED, S_CONNECTING, S_COOLDOWN, \ + S_INITIALIZE, S_NOT_CONNECTED, S_OFF, S_ON, S_STANDBY, S_WARMUP from openlp.core.lib.projector.db import ProjectorDB from openlp.core.lib.projector.pjlink1 import PJLink1 from openlp.core.ui.projector.editform import ProjectorEditForm from openlp.core.ui.projector.sourceselectform import SourceSelectTabs, SourceSelectSingle +log = logging.getLogger(__name__) +log.debug('projectormanager loaded') + + # Dict for matching projector status to display icon -STATUS_ICONS = {S_NOT_CONNECTED: ':/projector/projector_item_disconnect.png', - S_CONNECTING: ':/projector/projector_item_connect.png', - S_CONNECTED: ':/projector/projector_off.png', - S_OFF: ':/projector/projector_off.png', - S_INITIALIZE: ':/projector/projector_off.png', - S_STANDBY: ':/projector/projector_off.png', - S_WARMUP: ':/projector/projector_warmup.png', - S_ON: ':/projector/projector_on.png', - S_COOLDOWN: ':/projector/projector_cooldown.png', - E_ERROR: ':/projector/projector_error.png', - E_NETWORK: ':/projector/projector_not_connected_error.png', - E_AUTHENTICATION: ':/projector/projector_not_connected_error.png', - E_UNKNOWN_SOCKET_ERROR: ':/projector/projector_not_connected_error.png', - E_NOT_CONNECTED: ':/projector/projector_not_connected_error.png' - } +STATUS_ICONS = { + S_NOT_CONNECTED: ':/projector/projector_item_disconnect.png', + S_CONNECTING: ':/projector/projector_item_connect.png', + S_CONNECTED: ':/projector/projector_off.png', + S_OFF: ':/projector/projector_off.png', + S_INITIALIZE: ':/projector/projector_off.png', + S_STANDBY: ':/projector/projector_off.png', + S_WARMUP: ':/projector/projector_warmup.png', + S_ON: ':/projector/projector_on.png', + S_COOLDOWN: ':/projector/projector_cooldown.png', + E_ERROR: ':/projector/projector_error.png', + E_NETWORK: ':/projector/projector_not_connected_error.png', + E_AUTHENTICATION: ':/projector/projector_not_connected_error.png', + E_UNKNOWN_SOCKET_ERROR: ':/projector/projector_not_connected_error.png', + E_NOT_CONNECTED: ':/projector/projector_not_connected_error.png' +} -class Ui_ProjectorManager(object): +class UiProjectorManager(object): """ UI part of the Projector Manager """ @@ -271,7 +274,7 @@ class Ui_ProjectorManager(object): self.update_icons() -class ProjectorManager(OpenLPMixin, RegistryMixin, QWidget, Ui_ProjectorManager, RegistryProperties): +class ProjectorManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, UiProjectorManager, RegistryProperties): """ Manage the projectors. """ @@ -720,7 +723,7 @@ class ProjectorManager(OpenLPMixin, RegistryMixin, QWidget, Ui_ProjectorManager, widget.setData(QtCore.Qt.UserRole, item) item.link.db_item = item.db_item item.widget = widget - thread = QThread(parent=self) + thread = QtCore.QThread(parent=self) thread.my_parent = self item.moveToThread(thread) thread.started.connect(item.link.thread_started) @@ -751,7 +754,7 @@ class ProjectorManager(OpenLPMixin, RegistryMixin, QWidget, Ui_ProjectorManager, for item in self.projector_list: log.debug('New projector list - item: ({ip}) {name}'.format(ip=item.link.ip, name=item.link.name)) - @pyqtSlot(str) + @QtCore.pyqtSlot(str) def add_projector_from_wizard(self, ip, opts=None): """ Add a projector from the edit dialog @@ -763,7 +766,7 @@ class ProjectorManager(OpenLPMixin, RegistryMixin, QWidget, Ui_ProjectorManager, item = self.projectordb.get_projector_by_ip(ip) self.add_projector(item) - @pyqtSlot(object) + @QtCore.pyqtSlot(object) def edit_projector_from_wizard(self, projector): """ Update projector from the wizard edit page @@ -796,7 +799,7 @@ class ProjectorManager(OpenLPMixin, RegistryMixin, QWidget, Ui_ProjectorManager, """ return self.projector_list - @pyqtSlot(str, int, str) + @QtCore.pyqtSlot(str, int, str) def update_status(self, ip, status=None, msg=None): """ Update the status information/icon for selected list item @@ -846,7 +849,7 @@ class ProjectorManager(OpenLPMixin, RegistryMixin, QWidget, Ui_ProjectorManager, item.setVisible(False if hidden else True) item.setEnabled(True if enabled else False) - @pyqtSlot() + @QtCore.pyqtSlot() def update_icons(self): """ Update the icons when the selected projectors change @@ -919,7 +922,7 @@ class ProjectorManager(OpenLPMixin, RegistryMixin, QWidget, Ui_ProjectorManager, self.get_toolbar_item('blank_projector_multiple', hidden=False, enabled=True) self.get_toolbar_item('show_projector_multiple', hidden=False, enabled=True) - @pyqtSlot(str) + @QtCore.pyqtSlot(str) def authentication_error(self, name): """ Display warning dialog when attempting to connect with invalid pin @@ -933,7 +936,7 @@ class ProjectorManager(OpenLPMixin, RegistryMixin, QWidget, Ui_ProjectorManager, '

Please verify your PIN setting ' 'for projector item "{name}"'.format(name=name)) - @pyqtSlot(str) + @QtCore.pyqtSlot(str) def no_authentication_error(self, name): """ Display warning dialog when pin saved for item but projector does not @@ -949,7 +952,7 @@ class ProjectorManager(OpenLPMixin, RegistryMixin, QWidget, Ui_ProjectorManager, 'for projector item "{name}"'.format(name=name)) -class ProjectorItem(QObject): +class ProjectorItem(QtCore.QObject): """ Class for the projector list widget item. NOTE: Actual PJLink class instance should be saved as self.link diff --git a/openlp/core/ui/projector/sourceselectform.py b/openlp/core/ui/projector/sourceselectform.py index 8f811c6dd..c2b1c2a1b 100644 --- a/openlp/core/ui/projector/sourceselectform.py +++ b/openlp/core/ui/projector/sourceselectform.py @@ -20,24 +20,21 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### """ - :mod: `openlp.core.ui.projector.sourceselectform` module +:mod: `openlp.core.ui.projector.sourceselectform` module - Provides the dialog window for selecting video source for projector. +Provides the dialog window for selecting video source for projector. """ import logging -log = logging.getLogger(__name__) -log.debug('editform loaded') from PyQt5 import QtCore, QtWidgets -from PyQt5.QtCore import pyqtSlot, QSize -from PyQt5.QtWidgets import QAbstractButton, QDialog, QButtonGroup, QDialogButtonBox, QFormLayout, QLineEdit, \ - QRadioButton, QStyle, QStylePainter, QStyleOptionTab, QTabBar, QTabWidget, QVBoxLayout, QWidget from openlp.core.common import translate, is_macosx from openlp.core.lib import build_icon from openlp.core.lib.projector.db import ProjectorSource from openlp.core.lib.projector.constants import PJLINK_DEFAULT_SOURCES, PJLINK_DEFAULT_CODES +log = logging.getLogger(__name__) + def source_group(inputs, source_text): """ @@ -78,7 +75,7 @@ def source_group(inputs, source_text): return keydict -def Build_Tab(group, source_key, default, projector, projectordb, edit=False): +def build_tab(group, source_key, default, projector, projectordb, edit=False): """ Create the radio button page for a tab. Dictionary will be a 1-key entry where key=tab to setup, val=list of inputs. @@ -104,8 +101,8 @@ def Build_Tab(group, source_key, default, projector, projectordb, edit=False): :param edit: If we're editing the source text """ buttonchecked = False - widget = QWidget() - layout = QFormLayout() if edit else QVBoxLayout() + widget = QtWidgets.QWidget() + layout = QtWidgets.QFormLayout() if edit else QtWidgets.QVBoxLayout() layout.setSpacing(10) widget.setLayout(layout) tempkey = list(source_key.keys())[0] # Should only be 1 key @@ -114,7 +111,7 @@ def Build_Tab(group, source_key, default, projector, projectordb, edit=False): button_count = len(sourcelist) if edit: for key in sourcelist: - item = QLineEdit() + item = QtWidgets.QLineEdit() item.setObjectName('source_key_{key}'.format(key=key)) source_item = projectordb.get_source_by_code(code=key, projector_id=projector.db_item.id) if source_item is None: @@ -130,7 +127,7 @@ def Build_Tab(group, source_key, default, projector, projectordb, edit=False): text = source_key[tempkey][key] else: text = source_item.text - itemwidget = QRadioButton(text) + itemwidget = QtWidgets.QRadioButton(text) itemwidget.setAutoExclusive(True) if default == key: itemwidget.setChecked(True) @@ -148,23 +145,23 @@ def set_button_tooltip(button_bar): :param button_bar: QDialogButtonBar instance to update """ for button in button_bar.buttons(): - if button_bar.standardButton(button) == QDialogButtonBox.Cancel: + if button_bar.standardButton(button) == QtWidgets.QDialogButtonBox.Cancel: button.setToolTip(translate('OpenLP.SourceSelectForm', 'Ignoring current changes and return to OpenLP')) - elif button_bar.standardButton(button) == QDialogButtonBox.Reset: + elif button_bar.standardButton(button) == QtWidgets.QDialogButtonBox.Reset: button.setToolTip(translate('OpenLP.SourceSelectForm', 'Delete all user-defined text and revert to PJLink default text')) - elif button_bar.standardButton(button) == QDialogButtonBox.Discard: + elif button_bar.standardButton(button) == QtWidgets.QDialogButtonBox.Discard: button.setToolTip(translate('OpenLP.SourceSelectForm', 'Discard changes and reset to previous user-defined text')) - elif button_bar.standardButton(button) == QDialogButtonBox.Ok: + elif button_bar.standardButton(button) == QtWidgets.QDialogButtonBox.Ok: button.setToolTip(translate('OpenLP.SourceSelectForm', 'Save changes and return to OpenLP')) else: log.debug('No tooltip for button {text}'.format(text=button.text())) -class FingerTabBarWidget(QTabBar): +class FingerTabBarWidget(QtWidgets.QTabBar): """ Realign west -orientation tabs to left-right text rather than south-north text Borrowed from @@ -177,8 +174,8 @@ class FingerTabBarWidget(QTabBar): :param width: Remove default width parameter in kwargs :param height: Remove default height parameter in kwargs """ - self.tabSize = QSize(kwargs.pop('width', 100), kwargs.pop('height', 25)) - QTabBar.__init__(self, parent, *args, **kwargs) + self.tabSize = QtCore.QSize(kwargs.pop('width', 100), kwargs.pop('height', 25)) + QtWidgets.QTabBar.__init__(self, parent, *args, **kwargs) def paintEvent(self, event): """ @@ -186,14 +183,14 @@ class FingerTabBarWidget(QTabBar): :param event: Repaint event signal """ - painter = QStylePainter(self) - option = QStyleOptionTab() + painter = QtWidgets.QStylePainter(self) + option = QtWidgets.QStyleOptionTab() for index in range(self.count()): self.initStyleOption(option, index) tabRect = self.tabRect(index) tabRect.moveLeft(10) - painter.drawControl(QStyle.CE_TabBarTabShape, option) + painter.drawControl(QtWidgets.QStyle.CE_TabBarTabShape, option) painter.drawText(tabRect, QtCore.Qt.AlignVCenter | QtCore.Qt.TextDontClip, self.tabText(index)) @@ -209,7 +206,7 @@ class FingerTabBarWidget(QTabBar): return self.tabSize -class FingerTabWidget(QTabWidget): +class FingerTabWidget(QtWidgets.QTabWidget): """ A QTabWidget equivalent which uses our FingerTabBarWidget @@ -220,11 +217,11 @@ class FingerTabWidget(QTabWidget): """ Initialize FingerTabWidget instance """ - QTabWidget.__init__(self, parent, *args) + QtWidgets.QTabWidget.__init__(self, parent, *args) self.setTabBar(FingerTabBarWidget(self)) -class SourceSelectTabs(QDialog): +class SourceSelectTabs(QtWidgets.QDialog): """ Class for handling selecting the source for the projector to use. Uses tabbed interface. @@ -248,18 +245,18 @@ class SourceSelectTabs(QDialog): self.setObjectName('source_select_tabs') self.setWindowIcon(build_icon(':/icon/openlp-log-32x32.png')) self.setModal(True) - self.layout = QVBoxLayout() + self.layout = QtWidgets.QVBoxLayout() self.layout.setObjectName('source_select_tabs_layout') if is_macosx(): - self.tabwidget = QTabWidget(self) + self.tabwidget = QtWidgets.QTabWidget(self) else: self.tabwidget = FingerTabWidget(self) self.tabwidget.setObjectName('source_select_tabs_tabwidget') self.tabwidget.setUsesScrollButtons(False) if is_macosx(): - self.tabwidget.setTabPosition(QTabWidget.North) + self.tabwidget.setTabPosition(QtWidgets.QTabWidget.North) else: - self.tabwidget.setTabPosition(QTabWidget.West) + self.tabwidget.setTabPosition(QtWidgets.QTabWidget.West) self.layout.addWidget(self.tabwidget) self.setLayout(self.layout) @@ -272,13 +269,12 @@ class SourceSelectTabs(QDialog): self.projector = projector self.source_text = self.projectordb.get_source_list(projector=projector) self.source_group = source_group(projector.source_available, self.source_text) - # self.source_group = {'4': {'41': 'Storage 1'}, '5': {"51": 'Network 1'}} - self.button_group = [] if self.edit else QButtonGroup() + self.button_group = [] if self.edit else QtWidgets.QButtonGroup() keys = list(self.source_group.keys()) keys.sort() if self.edit: for key in keys: - (tab, button_count, buttonchecked) = Build_Tab(group=self.button_group, + (tab, button_count, buttonchecked) = build_tab(group=self.button_group, source_key={key: self.source_group[key]}, default=self.projector.source, projector=self.projector, @@ -287,13 +283,13 @@ class SourceSelectTabs(QDialog): thistab = self.tabwidget.addTab(tab, PJLINK_DEFAULT_SOURCES[key]) if buttonchecked: self.tabwidget.setCurrentIndex(thistab) - self.button_box = QDialogButtonBox(QtWidgets.QDialogButtonBox.Reset | - QtWidgets.QDialogButtonBox.Discard | - QtWidgets.QDialogButtonBox.Ok | - QtWidgets.QDialogButtonBox.Cancel) + self.button_box = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Reset | + QtWidgets.QDialogButtonBox.Discard | + QtWidgets.QDialogButtonBox.Ok | + QtWidgets.QDialogButtonBox.Cancel) else: for key in keys: - (tab, button_count, buttonchecked) = Build_Tab(group=self.button_group, + (tab, button_count, buttonchecked) = build_tab(group=self.button_group, source_key={key: self.source_group[key]}, default=self.projector.source, projector=self.projector, @@ -302,15 +298,15 @@ class SourceSelectTabs(QDialog): thistab = self.tabwidget.addTab(tab, PJLINK_DEFAULT_SOURCES[key]) if buttonchecked: self.tabwidget.setCurrentIndex(thistab) - self.button_box = QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | - QtWidgets.QDialogButtonBox.Cancel) + self.button_box = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | + QtWidgets.QDialogButtonBox.Cancel) self.button_box.clicked.connect(self.button_clicked) self.layout.addWidget(self.button_box) set_button_tooltip(self.button_box) selected = super(SourceSelectTabs, self).exec() return selected - @pyqtSlot(object) + @QtCore.pyqtSlot(QtWidgets.QAbstractButton) def button_clicked(self, button): """ Checks which button was clicked @@ -333,6 +329,9 @@ class SourceSelectTabs(QDialog): return 100 def delete_sources(self): + """ + Delete the sources for this projector + """ msg = QtWidgets.QMessageBox() msg.setText(translate('OpenLP.SourceSelectForm', 'Delete entries for this projector')) msg.setInformativeText(translate('OpenLP.SourceSelectForm', @@ -376,7 +375,7 @@ class SourceSelectTabs(QDialog): self.done(selected) -class SourceSelectSingle(QDialog): +class SourceSelectSingle(QtWidgets.QDialog): """ Class for handling selecting the source for the projector to use. Uses single dialog interface. @@ -407,12 +406,12 @@ class SourceSelectSingle(QDialog): :param projector: Projector instance to build source list from """ self.projector = projector - self.layout = QFormLayout() if self.edit else QVBoxLayout() + self.layout = QtWidgets.QFormLayout() if self.edit else QtWidgets.QVBoxLayout() self.layout.setObjectName('source_select_tabs_layout') self.layout.setSpacing(10) self.setLayout(self.layout) self.setMinimumWidth(350) - self.button_group = [] if self.edit else QButtonGroup() + self.button_group = [] if self.edit else QtWidgets.QButtonGroup() self.source_text = self.projectordb.get_source_list(projector=projector) keys = list(self.source_text.keys()) keys.sort() @@ -420,7 +419,7 @@ class SourceSelectSingle(QDialog): button_list = [] if self.edit: for key in keys: - item = QLineEdit() + item = QtWidgets.QLineEdit() item.setObjectName('source_key_{key}'.format(key=key)) source_item = self.projectordb.get_source_by_code(code=key, projector_id=self.projector.db_item.id) if source_item is None: @@ -430,10 +429,10 @@ class SourceSelectSingle(QDialog): item.setText(source_item.text) self.layout.addRow(PJLINK_DEFAULT_CODES[key], item) self.button_group.append(item) - self.button_box = QDialogButtonBox(QtWidgets.QDialogButtonBox.Reset | - QtWidgets.QDialogButtonBox.Discard | - QtWidgets.QDialogButtonBox.Ok | - QtWidgets.QDialogButtonBox.Cancel) + self.button_box = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Reset | + QtWidgets.QDialogButtonBox.Discard | + QtWidgets.QDialogButtonBox.Ok | + QtWidgets.QDialogButtonBox.Cancel) else: for key in keys: source_text = self.projectordb.get_source_by_code(code=key, projector_id=self.projector.db_item.id) @@ -443,8 +442,8 @@ class SourceSelectSingle(QDialog): self.layout.addWidget(button) self.button_group.addButton(button, int(key)) button_list.append(key) - self.button_box = QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | - QtWidgets.QDialogButtonBox.Cancel) + self.button_box = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | + QtWidgets.QDialogButtonBox.Cancel) self.button_box.clicked.connect(self.button_clicked) self.layout.addWidget(self.button_box) self.setMinimumHeight(key_count * 25) @@ -452,7 +451,7 @@ class SourceSelectSingle(QDialog): selected = super(SourceSelectSingle, self).exec() return selected - @pyqtSlot(QAbstractButton) + @QtCore.pyqtSlot(QtWidgets.QAbstractButton) def button_clicked(self, button): """ Checks which button was clicked @@ -488,7 +487,7 @@ class SourceSelectSingle(QDialog): self.projectordb.delete_all_objects(ProjectorSource, ProjectorSource.projector_id == self.projector.db_item.id) self.done(100) - @pyqtSlot() + @QtCore.pyqtSlot() def accept_me(self): """ Slot to accept 'OK' button diff --git a/tests/functional/openlp_core_common/test_registryproperties.py b/tests/functional/openlp_core_common/test_registryproperties.py index 45eb4d45e..38ae6471b 100644 --- a/tests/functional/openlp_core_common/test_registryproperties.py +++ b/tests/functional/openlp_core_common/test_registryproperties.py @@ -75,3 +75,24 @@ class TestRegistryProperties(TestCase, RegistryProperties): # THEN the application should be none self.assertEqual(self.application, application, 'The application value should match') + + @patch('openlp.core.common.registryproperties.is_win') + def test_get_application_on_windows(self, mocked_is_win): + """ + Set that getting the application object on Windows happens dynamically + """ + # GIVEN an Empty Registry and we're on Windows + mocked_is_win.return_value = True + mock_application = MagicMock() + reg_props = RegistryProperties() + registry = Registry() + + # WHEN the application is accessed + with patch.object(registry, 'get') as mocked_get: + mocked_get.return_value = mock_application + actual_application = reg_props.application + + # THEN the application should be the mock object, and the correct function should have been called + self.assertEqual(mock_application, actual_application, 'The application value should match') + mocked_is_win.assert_called_with() + mocked_get.assert_called_with('application') diff --git a/tests/interfaces/openlp_core_ui/test_projectoreditform.py b/tests/interfaces/openlp_core_ui/test_projectoreditform.py index 77685ca2e..a3c980789 100644 --- a/tests/interfaces/openlp_core_ui/test_projectoreditform.py +++ b/tests/interfaces/openlp_core_ui/test_projectoreditform.py @@ -26,7 +26,7 @@ class and methods. import os from unittest import TestCase -from openlp.core.common import Registry, Settings +from openlp.core.common import Registry from openlp.core.lib.projector.db import Projector, ProjectorDB from openlp.core.ui import ProjectorEditForm @@ -63,43 +63,41 @@ class TestProjectorEditForm(TestCase, TestMixin): :return: None """ self.projectordb.session.close() - del(self.projector_form) + del self.projector_form self.destroy_settings() - def test_edit_form_add_projector(self): + @patch('openlp.core.ui.projector.editform.QtWidgets.QDialog.exec') + def test_edit_form_add_projector(self, mocked_exec): """ Test projector edit form with no parameters creates a new entry. :return: None """ # GIVEN: Mocked setup - with patch('openlp.core.ui.projector.editform.QDialog.exec'): + # WHEN: Calling edit form with no parameters + self.projector_form.exec() + item = self.projector_form.projector - # WHEN: Calling edit form with no parameters - self.projector_form.exec() - item = self.projector_form.projector + # THEN: Should be creating a new instance + self.assertTrue(self.projector_form.new_projector, + 'Projector edit form should be marked as a new entry') + self.assertTrue((item.ip is None and item.name is None), + 'Projector edit form should have a new Projector() instance to edit') - # THEN: Should be creating a new instance - self.assertTrue(self.projector_form.new_projector, - 'Projector edit form should be marked as a new entry') - self.assertTrue((item.ip is None and item.name is None), - 'Projector edit form should have a new Projector() instance to edit') - - def test_edit_form_edit_projector(self): + @patch('openlp.core.ui.projector.editform.QtWidgets.QDialog.exec') + def test_edit_form_edit_projector(self, mocked_exec): """ Test projector edit form with existing projector entry :return: """ # GIVEN: Mocked setup - with patch('openlp.core.ui.projector.editform.QDialog.exec'): + # WHEN: Calling edit form with existing projector instance + self.projector_form.exec(projector=Projector(**TEST1_DATA)) + item = self.projector_form.projector - # WHEN: Calling edit form with existing projector instance - self.projector_form.exec(projector=Projector(**TEST1_DATA)) - item = self.projector_form.projector - - # THEN: Should be editing an existing entry - self.assertFalse(self.projector_form.new_projector, - 'Projector edit form should be marked as existing entry') - self.assertTrue((item.ip is TEST1_DATA['ip'] and item.name is TEST1_DATA['name']), - 'Projector edit form should have TEST1_DATA() instance to edit') + # THEN: Should be editing an existing entry + self.assertFalse(self.projector_form.new_projector, + 'Projector edit form should be marked as existing entry') + self.assertTrue((item.ip is TEST1_DATA['ip'] and item.name is TEST1_DATA['name']), + 'Projector edit form should have TEST1_DATA() instance to edit')