Skip to content
Snippets Groups Projects
Unverified Commit 04b9d5b9 authored by WHITFIELDRE email's avatar WHITFIELDRE email Committed by GitHub
Browse files

Merge pull request #23811 from mantidproject/qt4_5_compatibility

Add abstractions between qt4 and qt5
parents e73317cb 6fc5ce02
No related branches found
No related tags found
No related merge requests found
# Mantid Repository : https://github.com/mantidproject/mantid
#
# Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
# NScD Oak Ridge National Laboratory, European Spallation Source
# & Institut Laue - Langevin
# SPDX - License - Identifier: GPL - 3.0 +
from __future__ import (absolute_import, division, print_function)
from gui_helper import set_matplotlib_backend
backend = set_matplotlib_backend() # must be at the top of this file
if backend == 'Qt4Agg':
from matplotlib.backends.backend_qt4agg import * # noqa
elif backend == 'Qt5Agg':
from matplotlib.backends.backend_qt5agg import * # noqa
else:
raise RuntimeError('Unrecognized backend {}'.format(backend))
# Mantid Repository : https://github.com/mantidproject/mantid
#
# Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
# NScD Oak Ridge National Laboratory, European Spallation Source
# & Institut Laue - Langevin
# SPDX - License - Identifier: GPL - 3.0 +
from __future__ import (absolute_import, division, print_function)
from qtpy.QtWidgets import (QApplication) # noqa
import matplotlib
import sys
def set_matplotlib_backend():
'''MUST be called before anything tries to use matplotlib
This will set the backend if it hasn't been already. It also returns
the name of the backend to be the name to be used for importing the
correct matplotlib widgets.'''
backend = matplotlib.get_backend()
if backend.startswith('module://'):
if backend.endswith('qt4agg'):
backend = 'Qt4Agg'
elif backend.endswith('workbench') or backend.endswith('qt5agg'):
backend = 'Qt5Agg'
else:
from qtpy import PYQT4, PYQT5 # noqa
if PYQT4:
backend = 'Qt4Agg'
elif PYQT5:
backend = 'Qt5Agg'
else:
raise RuntimeError('Do not know which matplotlib backend to set')
matplotlib.use(backend)
return backend
def get_qapplication():
''' Example usage:
app, within_mantid = get_qapplication()
reducer = eventFilterGUI.MainWindow() # the main ui class in this file
reducer.show()
if not within_mantid:
sys.exit(app.exec_())'''
app = QApplication.instance()
if app:
return app, app.applicationName().lower().startswith('mantid')
else:
return QApplication(sys.argv), False
#!/usr/bin/env python
from __future__ import (absolute_import, division, print_function, unicode_literals)
import os
import sys
def parse_old_style_connect(qt_old_line, linenum):
step1 = qt_old_line.split('connect(')[1]
step1 = step1.replace(' ', '')
terms = step1.split(',')
if len(terms) != 3:
raise RuntimeError('This is not right! L{1} {0}'.format(qt_old_line,
linenum))
# leading whitespace
whitespace = ' ' * (len(qt_old_line) - len(qt_old_line.lstrip(' ')))
# widget name
widget_name = terms[0]
# event signal
event_signal = terms[1]
# method to handle event
hander_method = terms[2].replace('(', '').replace(')', '').strip()
return whitespace, widget_name, event_signal, hander_method
def convert_signal_connect(cmd, linenum):
"""
Convert (very) old style signal connection to newer style
"""
try:
if cmd.strip().startswith('#'):
return cmd
if cmd.count('self.connect') != 1:
return cmd
except UnicodeDecodeError:
print('L{} of source file encountered UnicodeDecodeError - not changing line'.format(linenum))
return cmd
whitespace, widget_name, event_signal, handler_method = parse_old_style_connect(cmd, linenum)
if event_signal.count('accepted') > 0:
signal_call = 'accepted'
elif event_signal.count('activated') > 0:
signal_call = 'activated'
elif event_signal.count('clicked') > 0:
signal_call = 'clicked'
elif event_signal.count('currentIndexChanged') > 0:
signal_call = 'currentIndexChanged'
elif event_signal.count('indexChanged') > 0:
# must follow currentIndexChanged
signal_call = 'indexChanged'
elif event_signal.count('stateChanged') > 0:
signal_call = 'stateChanged'
elif event_signal.count('toggled') > 0:
signal_call = 'toggled'
elif event_signal.count('itemSelectionChanged') > 0:
signal_call = 'itemSelectionChanged'
elif event_signal.count('rejected') > 0:
signal_call = 'rejected'
elif event_signal.count('returnPressed') > 0:
signal_call = 'returnPressed'
elif event_signal.count('textChanged') > 0:
signal_call = 'textChanged'
elif event_signal.count('triggered') > 0:
signal_call = 'triggered'
elif event_signal.count('valueChanged') > 0:
signal_call = 'valueChanged'
else:
sys.stderr.write('L{1} signal {0} is not supported - skipping line\n'.format(event_signal, linenum))
return cmd
return '{0}{1}.{2}.connect({3})\n'.format(whitespace, widget_name, signal_call, handler_method)
QT4_TO_QTPY_FIXES = {'QtCore.QFileInfo': ('qtpy.QtCore', 'QFileInfo,'),
'QtCore.QRegExp': ('qtpy.QtCore', 'QRegExp'),
'QtCore.QSettings': ('qtpy.QtCore', 'QSettings'),
'QtGui.QButtonGroup': ('qtpy.QtWidgets', 'QButtonGroup'),
'QtGui.QDialog': ('qtpy.QtWidgets', 'QDialog'),
'QtGui.QDoubleValidator': ('qtpy.QtGui', 'QDoubleValidator'),
'QtGui.QFileDialog': ('qtpy.QtWidgets', 'QFileDialog'),
'QtGui.QFrame': ('qtpy.QtWidgets', 'QFrame'),
'QtGui.QGroupBox': ('qtpy.QtWidgets', 'QGroupBox'),
'QtGui.QIntValidator': ('qtpy.QtGui', 'QIntValidator'),
'QtGui.QMessageBox': ('qtpy.QtWidgets', 'QMessageBox'),
'QtGui.QRegExpValidator': ('qtpy.QtGui', 'QRegExpValidator')}
def convertToQtPy(command, linenum):
imports = dict()
try:
for old_txt, (import_mod, new_txt) in QT4_TO_QTPY_FIXES.items():
if old_txt in command:
items = imports.get(import_mod, set())
items.add(new_txt)
imports[import_mod] = items
command = command.replace(old_txt, new_txt)
if ('QtCore' in command or 'QtGui' in command) and 'import' not in command:
sys.stderr.write('L{} Found unknown qt call: "{}"\n'.format(linenum,
command.strip()))
except UnicodeDecodeError:
pass # would have already been an issue
return command, imports
def read_and_convert_pyqt4_functions(filename):
# parse and fix file
lines = list()
imports = dict()
with open(filename, 'r') as handle:
for linenum, line in enumerate(handle):
# editors count from 1
line = convert_signal_connect(line, linenum+1)
line, imports_for_line = convertToQtPy(line, linenum+1)
for key, values in imports_for_line.items():
items = imports.get(key, set())
for item in values:
items.add(item)
imports[key] = items
lines.append(line)
if len(imports) > 0:
print('========== Change imports of PyQt4 to be ==========')
for key, values in imports.items():
values = list(values)
values.sort()
values = ', '.join(values)
print('from {} import ({}) # noqa'.format(key, values))
# overwrite with new version since there weren't errors
with open(filename, 'w') as handle:
for line in lines:
handle.write(line)
return lines
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description='Convert old qt4 signals to qt5-style')
parser.add_argument('files', nargs='+', help='script to convert')
options = parser.parse_args()
for filename in options.files:
filename = os.path.abspath(os.path.expanduser(filename))
if not os.path.exists(filename):
parser.error('file "{}" does not exist'.format(filename))
read_and_convert_pyqt4_functions(filename)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment