From 2e1c320518bd08799b66f5cae2de13a6833e4f15 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sat, 8 Sep 2018 14:22:27 -0500 Subject: [PATCH 1/4] Main Window: Set software OpenGL backend for QtQuick too This really sets that backend for Qt components --- setup.py | 2 +- spyder/app/mainwindow.py | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d595e295342..5be973c5552 100644 --- a/setup.py +++ b/setup.py @@ -233,7 +233,7 @@ def run(self): 'pylint', 'psutil', 'qtawesome>=0.4.1', - 'qtpy>=1.2.0', + 'qtpy>=1.5.0', 'pickleshare', 'pyzmq', 'chardet>=2.0.0', diff --git a/spyder/app/mainwindow.py b/spyder/app/mainwindow.py index f6cd7823e92..0119a83df22 100644 --- a/spyder/app/mainwindow.py +++ b/spyder/app/mainwindow.py @@ -91,6 +91,12 @@ # Avoid a bug in Qt: https://bugreports.qt.io/browse/QTBUG-46720 from qtpy import QtWebEngineWidgets # analysis:ignore +# For issue 7447 +try: + from qtpy.QtQuick import QQuickWindow, QSGRendererInterface +except Exception: + QQuickWindow = QSGRendererInterface = None + # To catch font errors in QtAwesome from qtawesome.iconic_font import FontError @@ -3155,11 +3161,19 @@ def main(): if options.opengl_implementation: if options.opengl_implementation == 'software': QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL) + # Fix issue 7447 + if QQuickWindow is not None: + QQuickWindow.setSceneGraphBackend( + QSGRendererInterface.Software) elif options.opengl_implementation == 'desktop': QCoreApplication.setAttribute(Qt.AA_UseDesktopOpenGL) else: if CONF.get('main', 'opengl') == 'software': QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL) + # Fix issue 7447 + if QQuickWindow is not None: + QQuickWindow.setSceneGraphBackend( + QSGRendererInterface.Software) elif CONF.get('main', 'opengl') == 'desktop': QCoreApplication.setAttribute(Qt.AA_UseDesktopOpenGL) From 728e26edfbb6804bd8d981668fc02cf59e264d16 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sat, 8 Sep 2018 15:15:28 -0500 Subject: [PATCH 2/4] Main Window: Add GLES to the OpenGL implementations that users can select --- spyder/app/cli_options.py | 2 +- spyder/app/mainwindow.py | 39 ++++++++++++++++++++++------------ spyder/plugins/configdialog.py | 2 +- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/spyder/app/cli_options.py b/spyder/app/cli_options.py index 8da9a3a15e2..8d05485b9b2 100644 --- a/spyder/app/cli_options.py +++ b/spyder/app/cli_options.py @@ -45,7 +45,7 @@ def get_options(): help="Path that contains an Spyder project") parser.add_option('--opengl', default=None, type='choice', dest="opengl_implementation", - choices=['software', 'desktop'], + choices=['software', 'desktop', 'gles'], help=("OpenGL implementation to pass to Qt. Possible " "options are 'software' and 'desktop'") ) diff --git a/spyder/app/mainwindow.py b/spyder/app/mainwindow.py index 0119a83df22..9000549c415 100644 --- a/spyder/app/mainwindow.py +++ b/spyder/app/mainwindow.py @@ -3133,6 +3133,7 @@ def run_spyder(app, options, args): #============================================================================== def main(): """Main function""" + # **** For our tests **** if running_under_pytest(): try: from unittest.mock import Mock @@ -3158,25 +3159,34 @@ def main(): # otherwise, optparse won't be able to exit if --help option is passed options, args = get_options() - if options.opengl_implementation: - if options.opengl_implementation == 'software': + # **** Set OpenGL implementation to use **** + # See issue 7447 for how this works + def set_opengl_implementation(option): + if option == 'software': QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL) - # Fix issue 7447 if QQuickWindow is not None: QQuickWindow.setSceneGraphBackend( QSGRendererInterface.Software) - elif options.opengl_implementation == 'desktop': + elif option == 'desktop': QCoreApplication.setAttribute(Qt.AA_UseDesktopOpenGL) - else: - if CONF.get('main', 'opengl') == 'software': - QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL) - # Fix issue 7447 if QQuickWindow is not None: QQuickWindow.setSceneGraphBackend( - QSGRendererInterface.Software) - elif CONF.get('main', 'opengl') == 'desktop': - QCoreApplication.setAttribute(Qt.AA_UseDesktopOpenGL) + QSGRendererInterface.OpenGL) + elif option == 'gles': + QCoreApplication.setAttribute(Qt.AA_UseOpenGLES) + if QQuickWindow is not None: + QQuickWindow.setSceneGraphBackend( + QSGRendererInterface.OpenGL) + if options.opengl_implementation: + option = options.opengl_implementation + set_opengl_implementation(option) + else: + if CONF.get('main', 'opengl') != 'automatic': + option = CONF.get('main', 'opengl') + set_opengl_implementation(option) + + # **** Handle hide_console option **** if options.show_console: print("(Deprecated) --show console does nothing, now the default " " behavior is to show the console, use --hide-console if you " @@ -3188,7 +3198,10 @@ def main(): or options.reset_to_defaults or options.optimize or bool(DEBUG)) + # **** Create the application **** app = initialize() + + # **** Handle other options **** if options.reset_config_files: # Remove all configuration files! reset_config_files() @@ -3204,7 +3217,7 @@ def main(): args=[spyder.__path__[0]], p_args=['-O']) return - # Show crash dialog + # **** Show crash dialog **** if CONF.get('main', 'crash', False) and not DEV: CONF.set('main', 'crash', False) if SPLASH is not None: @@ -3231,7 +3244,7 @@ def main(): "" % (get_conf_path(), __trouble_url__, __project_url__, __forum_url__, __project_url__)) - # Create main window + # **** Create main window **** mainwindow = None try: mainwindow = run_spyder(app, options, args) diff --git a/spyder/plugins/configdialog.py b/spyder/plugins/configdialog.py index fc3df87851a..c680f6b4ad4 100644 --- a/spyder/plugins/configdialog.py +++ b/spyder/plugins/configdialog.py @@ -868,7 +868,7 @@ def setup_page(self): 'interface_language', restart=True) - opengl_options = ['Automatic', 'Desktop', 'Software'] + opengl_options = ['Automatic', 'Desktop', 'Software', 'GLES'] opengl_choices = list(zip(opengl_options, [c.lower() for c in opengl_options])) opengl_combo = self.create_combobox(_('Rendering engine:'), From 424c4a1888512052e6c08fc7b8289a57efb6f9c0 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sat, 8 Sep 2018 15:27:45 -0500 Subject: [PATCH 3/4] Testing: Add a test that verifies that we're setting the right OpenGL implementation --- spyder/app/mainwindow.py | 60 ++++++++++++++++++++--------- spyder/app/tests/test_mainwindow.py | 12 ++++++ 2 files changed, 53 insertions(+), 19 deletions(-) diff --git a/spyder/app/mainwindow.py b/spyder/app/mainwindow.py index 9000549c415..7921cf89b61 100644 --- a/spyder/app/mainwindow.py +++ b/spyder/app/mainwindow.py @@ -3013,6 +3013,16 @@ def check_updates(self, startup=False): self.thread_updates.started.connect(self.worker_updates.start) self.thread_updates.start() + # --- For OpenGL + def _test_setting_opengl(self, option): + """Get the current OpenGL implementation in use""" + if option == 'software': + return QCoreApplication.testAttribute(Qt.AA_UseSoftwareOpenGL) + elif option == 'desktop': + return QCoreApplication.testAttribute(Qt.AA_UseDesktopOpenGL) + elif option == 'gles': + return QCoreApplication.testAttribute(Qt.AA_UseOpenGLES) + #============================================================================== # Utilities to create the 'main' function @@ -3133,7 +3143,33 @@ def run_spyder(app, options, args): #============================================================================== def main(): """Main function""" - # **** For our tests **** + + def set_opengl_implementation(option): + """ + Auxiliary function to set the OpenGL implementation used by + Spyder. + + See issue 7447 for the details. + """ + if option == 'software': + QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL) + if QQuickWindow is not None: + QQuickWindow.setSceneGraphBackend( + QSGRendererInterface.Software) + elif option == 'desktop': + QCoreApplication.setAttribute(Qt.AA_UseDesktopOpenGL) + if QQuickWindow is not None: + QQuickWindow.setSceneGraphBackend( + QSGRendererInterface.OpenGL) + elif option == 'gles': + QCoreApplication.setAttribute(Qt.AA_UseOpenGLES) + if QQuickWindow is not None: + QQuickWindow.setSceneGraphBackend( + QSGRendererInterface.OpenGL) + + # **** For Pytest **** + # We need to create MainWindow **here** to avoid passing pytest + # options to Spyder if running_under_pytest(): try: from unittest.mock import Mock @@ -3149,6 +3185,10 @@ def main(): options.window_title = None options.opengl_implementation = None + if CONF.get('main', 'opengl') != 'automatic': + option = CONF.get('main', 'opengl') + set_opengl_implementation(option) + app = initialize() window = run_spyder(app, options, None) return window @@ -3160,24 +3200,6 @@ def main(): options, args = get_options() # **** Set OpenGL implementation to use **** - # See issue 7447 for how this works - def set_opengl_implementation(option): - if option == 'software': - QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL) - if QQuickWindow is not None: - QQuickWindow.setSceneGraphBackend( - QSGRendererInterface.Software) - elif option == 'desktop': - QCoreApplication.setAttribute(Qt.AA_UseDesktopOpenGL) - if QQuickWindow is not None: - QQuickWindow.setSceneGraphBackend( - QSGRendererInterface.OpenGL) - elif option == 'gles': - QCoreApplication.setAttribute(Qt.AA_UseOpenGLES) - if QQuickWindow is not None: - QQuickWindow.setSceneGraphBackend( - QSGRendererInterface.OpenGL) - if options.opengl_implementation: option = options.opengl_implementation set_opengl_implementation(option) diff --git a/spyder/app/tests/test_mainwindow.py b/spyder/app/tests/test_mainwindow.py index 6bfe61cc19d..7b7e27dd56f 100644 --- a/spyder/app/tests/test_mainwindow.py +++ b/spyder/app/tests/test_mainwindow.py @@ -223,6 +223,18 @@ def test_calltip(main_window, qtbot): main_window.editor.close_file() +@pytest.mark.slow +@pytest.mark.parametrize('main_window', [{'spy_config': ('main', 'opengl', 'software')}], indirect=True) +def test_opengl_implementation(main_window, qtbot): + """ + Test that we are setting the selected OpenGL implementation + """ + assert main_window._test_setting_opengl('software') + + # Restore default config value + CONF.set('main', 'opengl', 'automatic') + + @pytest.mark.slow @flaky(max_runs=3) @pytest.mark.skipif(np.__version__ < '1.14.0', reason="This only happens in Numpy 1.14+") From 6f0697850cb353c0395cff223178a29445bd4681 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sat, 8 Sep 2018 15:34:11 -0500 Subject: [PATCH 4/4] Main Window: Move set_opengl_implementation to a better place --- spyder/app/mainwindow.py | 46 ++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/spyder/app/mainwindow.py b/spyder/app/mainwindow.py index 7921cf89b61..968b21c2500 100644 --- a/spyder/app/mainwindow.py +++ b/spyder/app/mainwindow.py @@ -196,7 +196,7 @@ #============================================================================== -# Spyder's main window widgets utilities +# Utility functions #============================================================================== def get_python_doc_path(): """ @@ -219,6 +219,26 @@ def get_python_doc_path(): return file_uri(python_doc) +def set_opengl_implementation(option): + """ + Set the OpenGL implementation used by Spyder. + + See issue 7447 for the details. + """ + if option == 'software': + QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL) + if QQuickWindow is not None: + QQuickWindow.setSceneGraphBackend(QSGRendererInterface.Software) + elif option == 'desktop': + QCoreApplication.setAttribute(Qt.AA_UseDesktopOpenGL) + if QQuickWindow is not None: + QQuickWindow.setSceneGraphBackend(QSGRendererInterface.OpenGL) + elif option == 'gles': + QCoreApplication.setAttribute(Qt.AA_UseOpenGLES) + if QQuickWindow is not None: + QQuickWindow.setSceneGraphBackend(QSGRendererInterface.OpenGL) + + #============================================================================== # Main Window #============================================================================== @@ -3143,30 +3163,6 @@ def run_spyder(app, options, args): #============================================================================== def main(): """Main function""" - - def set_opengl_implementation(option): - """ - Auxiliary function to set the OpenGL implementation used by - Spyder. - - See issue 7447 for the details. - """ - if option == 'software': - QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL) - if QQuickWindow is not None: - QQuickWindow.setSceneGraphBackend( - QSGRendererInterface.Software) - elif option == 'desktop': - QCoreApplication.setAttribute(Qt.AA_UseDesktopOpenGL) - if QQuickWindow is not None: - QQuickWindow.setSceneGraphBackend( - QSGRendererInterface.OpenGL) - elif option == 'gles': - QCoreApplication.setAttribute(Qt.AA_UseOpenGLES) - if QQuickWindow is not None: - QQuickWindow.setSceneGraphBackend( - QSGRendererInterface.OpenGL) - # **** For Pytest **** # We need to create MainWindow **here** to avoid passing pytest # options to Spyder