Skip to content

Commit

Permalink
Merge: Complete PyQt5 support (pull request #93)
Browse files Browse the repository at this point in the history
  • Loading branch information
ccordoba12 committed Feb 19, 2015
2 parents 2966523 + 085a7a9 commit 76eb4d8
Show file tree
Hide file tree
Showing 39 changed files with 242 additions and 79 deletions.
22 changes: 14 additions & 8 deletions bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
Type `python bootstrap.py -- --help` to read about Spyder
options.""")
parser.add_option('--gui', default=None,
help="GUI toolkit: pyqt (for PyQt4) or pyside (for PySide)")
help="GUI toolkit: pyqt5 (for PyQt5), pyqt (for PyQt4) or "
"pyside (for PySide)")
parser.add_option('--hide-console', action='store_true',
default=False, help="Hide parent console window (Windows only)")
parser.add_option('--test', dest="test", action='store_true', default=False,
Expand All @@ -43,7 +44,7 @@
default=False, help="Run Spyder in debug mode")
options, args = parser.parse_args()

assert options.gui in (None, 'pyqt', 'pyside'), \
assert options.gui in (None, 'pyqt5', 'pyqt', 'pyside'), \
"Invalid GUI toolkit option '%s'" % options.gui

# For testing purposes
Expand Down Expand Up @@ -104,15 +105,20 @@
print(" and %s" % EXTPATH)


# Selecting the GUI toolkit: PySide if installed, otherwise PyQt4
# Selecting the GUI toolkit: PyQt5 if installed, otherwise PySide or PyQt4
# (Note: PyQt4 is still the officially supported GUI toolkit for Spyder)
if options.gui is None:
try:
import PySide # analysis:ignore
print("02. PySide is detected, selecting (experimental)")
os.environ['QT_API'] = 'pyside'
except:
print("02. No PySide detected, using PyQt4 if available")
import PyQt5 # analysis:ignore
print("02. PyQt5 is detected, selecting (experimental)")
os.environ['QT_API'] = 'pyqt5'
except ImportError:
try:
import PySide # analysis:ignore
print("02. PySide is detected, selecting")
os.environ['QT_API'] = 'pyside'
except ImportError:
print("02. No PyQt5 or PySide detected, using PyQt4 if available")
else:
print ("02. Skipping GUI toolkit detection")
os.environ['QT_API'] = options.gui
Expand Down
12 changes: 12 additions & 0 deletions spyderlib/ipythonconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@
IPython configuration variables needed by Spyder
"""

import os

from spyderlib.utils import programs
from spyderlib import dependencies
from spyderlib.baseconfig import _

# Don't use spyderlib.qt.PYQT5 to avoid importing Qt here
PYQT5 = os.environ.get('QT_API', None) == 'pyqt5'

IPYTHON_REQVER = '>=1.0'
ZMQ_REQVER = '>=2.1.11'

Expand All @@ -21,6 +26,13 @@
required_version=ZMQ_REQVER)

def is_qtconsole_installed():
# Only IPython 3+ is compatible with PyQt5, so this will avoid a
# crash for us
# TODO: Remove this once IPython 3 is released
if programs.is_module_installed('IPython.qt', '<3.0') and PYQT5:
return False

# Check if pyzmq is installed too, else, what's the point?
pyzmq_installed = programs.is_module_installed('zmq', version=ZMQ_REQVER)
if programs.is_module_installed('IPython.qt') and pyzmq_installed:
return True
Expand Down
29 changes: 20 additions & 9 deletions spyderlib/plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@
# pylint: disable=R0911
# pylint: disable=R0201

# Qt imports
from spyderlib.qt import PYQT5
from spyderlib.qt.QtGui import (QDockWidget, QWidget, QShortcut, QCursor,
QKeySequence, QMainWindow, QApplication)
from spyderlib.qt.QtCore import Qt, Signal

# Stdlib imports
import sys

# Local imports
from spyderlib.utils.qthelpers import toggle_actions, get_icon, create_action
from spyderlib.baseconfig import _
Expand All @@ -30,7 +35,6 @@
from spyderlib.guiconfig import get_font, set_font
from spyderlib.plugins.configdialog import SpyderConfigPage
from spyderlib.py3compat import configparser, is_text_string
import sys


class PluginConfigPage(SpyderConfigPage):
Expand Down Expand Up @@ -154,9 +158,12 @@ class SpyderPluginMixin(object):
show_message = None
update_plugin_title = None

def __init__(self, main):
def __init__(self, main = None, **kwds):
"""Bind widget to a QMainWindow instance"""
super(SpyderPluginMixin, self).__init__()
if PYQT5:
super().__init__(**kwds)
else:
super(SpyderPluginMixin, self).__init__()
assert self.CONF_SECTION is not None
self.main = main
self.default_margins = None
Expand All @@ -178,7 +185,7 @@ def __init__(self, main):
# We decided to create our own toggle action instead of using
# the one that comes with dockwidget because it's not possible
# to raise and focus the plugin with it.
self.toggle_view_action = None
self.toggle_view_action = None

def initialize_plugin(self):
"""Initialize plugin: connect signals, setup actions, ..."""
Expand Down Expand Up @@ -348,7 +355,7 @@ def get_plugin_font(self, option=None):
def set_plugin_font(self, font, option=None):
"""Set plugin font option"""
set_font(font, self.CONF_SECTION, option)

def __show_message(self, message, timeout=0):
"""Show message in main window's status bar"""
self.main.statusBar().showMessage(message, timeout)
Expand Down Expand Up @@ -412,10 +419,14 @@ class SpyderPluginWidget(QWidget, SpyderPluginMixin):
sig_option_changed = Signal(str, object)
show_message = Signal(str, int)
update_plugin_title = Signal()

def __init__(self, parent):
QWidget.__init__(self, parent)
SpyderPluginMixin.__init__(self, parent)

if PYQT5:
def __init__(self, parent, **kwds):
super().__init__(**kwds)
else:
def __init__(self, parent):
QWidget.__init__(self, parent)
SpyderPluginMixin.__init__(self, parent)

def get_plugin_title(self):
"""
Expand Down
11 changes: 8 additions & 3 deletions spyderlib/plugins/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# pylint: disable=R0911
# pylint: disable=R0201

from spyderlib.qt import PYQT5
from spyderlib.qt.QtGui import (QVBoxLayout, QFontDialog, QInputDialog,
QLineEdit, QMenu)
from spyderlib.qt.QtCore import Signal, Slot
Expand All @@ -34,7 +35,7 @@
from spyderlib.plugins import SpyderPluginWidget
from spyderlib.py3compat import to_text_string, getcwd


class Console(SpyderPluginWidget):
"""
Console widget
Expand All @@ -46,7 +47,10 @@ class Console(SpyderPluginWidget):

def __init__(self, parent=None, namespace=None, commands=[], message=None,
exitfunc=None, profile=False, multithreaded=False):
SpyderPluginWidget.__init__(self, parent)
if PYQT5:
SpyderPluginWidget.__init__(self, parent, main = parent)
else:
SpyderPluginWidget.__init__(self, parent)

debug_print(" ..internal console: initializing")
self.dialog_manager = DialogManager()
Expand All @@ -61,13 +65,14 @@ def __init__(self, parent=None, namespace=None, commands=[], message=None,
self.shell.status.connect(lambda msg: self.show_message.emit(msg, 0))
self.shell.go_to_error.connect(self.go_to_error)
self.shell.focus_changed.connect(lambda: self.focus_changed.emit())

# Redirecting some signals:
self.shell.redirect_stdio.connect(lambda state:
self.redirect_stdio.emit(state))

# Initialize plugin
self.initialize_plugin()

# Find/replace widget
self.find_widget = FindReplace(self)
self.find_widget.set_editor(self.shell)
Expand Down
9 changes: 7 additions & 2 deletions spyderlib/plugins/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# pylint: disable=R0911
# pylint: disable=R0201

from spyderlib.qt import PYQT5
from spyderlib.qt.QtGui import (QVBoxLayout, QPrintDialog, QSplitter, QToolBar,
QAction, QApplication, QDialog, QWidget,
QPrinter, QActionGroup, QInputDialog, QMenu,
Expand Down Expand Up @@ -343,7 +344,10 @@ class Editor(SpyderPluginWidget):
run_in_current_extconsole = Signal(str, str, str, bool, bool)

def __init__(self, parent, ignore_last_opened_files=False):
SpyderPluginWidget.__init__(self, parent)
if PYQT5:
SpyderPluginWidget.__init__(self, parent, main=parent)
else:
SpyderPluginWidget.__init__(self, parent)

self.__set_eol_chars = True

Expand Down Expand Up @@ -1560,7 +1564,8 @@ def change_max_recent_files(self):
if valid:
self.set_option('max_recent_files', mrf)

@Slot(str, int, str)

@Slot(str, int, str, object)
def load(self, filenames=None, goto=None, word='', editorwindow=None,
processevents=True):
"""
Expand Down
7 changes: 6 additions & 1 deletion spyderlib/plugins/externalconsole.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# pylint: disable=R0201

# Qt imports
from spyderlib.qt import PYQT5
from spyderlib.qt.QtGui import (QVBoxLayout, QMessageBox, QInputDialog,
QLineEdit, QPushButton, QGroupBox, QLabel,
QTabWidget, QFontComboBox, QHBoxLayout,
Expand Down Expand Up @@ -48,6 +49,7 @@


class ExternalConsoleConfigPage(PluginConfigPage):

def __init__(self, plugin, parent):
PluginConfigPage.__init__(self, plugin, parent)
self.get_name = lambda: _("Console")
Expand Down Expand Up @@ -436,7 +438,10 @@ class ExternalConsole(SpyderPluginWidget):
redirect_stdio = Signal(bool)

def __init__(self, parent, light_mode):
SpyderPluginWidget.__init__(self, parent)
if PYQT5:
SpyderPluginWidget.__init__(self, parent, main = parent)
else:
SpyderPluginWidget.__init__(self, parent)
self.light_mode = light_mode
self.tabwidget = None
self.menu_actions = None
Expand Down
8 changes: 5 additions & 3 deletions spyderlib/plugins/history.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

"""Console History Plugin"""

from spyderlib.qt import PYQT5
from spyderlib.qt.QtGui import (QVBoxLayout, QFontDialog, QInputDialog,
QToolButton, QMenu, QFontComboBox, QGroupBox)
from spyderlib.qt.QtCore import Signal, Slot
Expand Down Expand Up @@ -73,7 +74,6 @@ class HistoryLog(SpyderPluginWidget):
"""
CONF_SECTION = 'historylog'
CONFIGWIDGET_CLASS = HistoryConfigPage
# Signals
focus_changed = Signal()

def __init__(self, parent):
Expand All @@ -85,8 +85,10 @@ def __init__(self, parent):
self.editors = []
self.filenames = []
self.icons = []

SpyderPluginWidget.__init__(self, parent)
if PYQT5:
SpyderPluginWidget.__init__(self, parent, main = parent)
else:
SpyderPluginWidget.__init__(self, parent)

# Initialize plugin
self.initialize_plugin()
Expand Down
7 changes: 5 additions & 2 deletions spyderlib/plugins/inspector.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

"""Object Inspector Plugin"""

from spyderlib.qt import PYQT5
from spyderlib.qt.QtGui import (QHBoxLayout, QVBoxLayout, QLabel, QSizePolicy,
QMenu, QToolButton, QGroupBox, QFontComboBox,
QActionGroup, QFontDialog, QWidget, QComboBox,
Expand Down Expand Up @@ -352,11 +353,13 @@ class ObjectInspector(SpyderPluginWidget):
CONF_SECTION = 'inspector'
CONFIGWIDGET_CLASS = ObjectInspectorConfigPage
LOG_PATH = get_conf_path(CONF_SECTION)
# Signals
focus_changed = Signal()

def __init__(self, parent):
SpyderPluginWidget.__init__(self, parent)
if PYQT5:
SpyderPluginWidget.__init__(self, parent, main = parent)
else:
SpyderPluginWidget.__init__(self, parent)

self.internal_shell = None

Expand Down
7 changes: 5 additions & 2 deletions spyderlib/plugins/ipythonconsole.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import sys

# Qt imports
from spyderlib.qt import PYQT5
from spyderlib.qt.QtGui import (QVBoxLayout, QHBoxLayout, QFormLayout,
QMessageBox, QGroupBox, QDialogButtonBox,
QDialog, QTabWidget, QFontComboBox,
Expand Down Expand Up @@ -573,10 +574,12 @@ class IPythonConsole(SpyderPluginWidget):
# Signals
focus_changed = Signal()
edit_goto = Signal(str, int, str)
focus_changed = Signal()

def __init__(self, parent):
SpyderPluginWidget.__init__(self, parent)
if PYQT5:
SpyderPluginWidget.__init__(self, parent, main = parent)
else:
SpyderPluginWidget.__init__(self, parent)

self.tabwidget = None
self.menu_actions = None
Expand Down
1 change: 1 addition & 0 deletions spyderlib/plugins/onlinehelp.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class OnlineHelp(PydocBrowser, SpyderPluginMixin):
sig_option_changed = Signal(str, object)
CONF_SECTION = 'onlinehelp'
LOG_PATH = get_conf_path(CONF_SECTION)

def __init__(self, parent):
self.main = parent
PydocBrowser.__init__(self, parent)
Expand Down
1 change: 1 addition & 0 deletions spyderlib/plugins/projectexplorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
class ProjectExplorer(ProjectExplorerWidget, SpyderPluginMixin):
"""Project explorer plugin"""
CONF_SECTION = 'project_explorer'

open_terminal = Signal(str)
open_interpreter = Signal(str)
pythonpath_changed = Signal()
Expand Down
4 changes: 4 additions & 0 deletions spyderlib/plugins/shortcuts.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ def setData(self, index, value, role=Qt.EditRole):
return True
return False

def reset(self):
self.beginResetModel()
self.endResetModel()


class ShortcutsDelegate(QItemDelegate):
def __init__(self, parent=None):
Expand Down
1 change: 1 addition & 0 deletions spyderlib/plugins/variableexplorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class VariableExplorer(QStackedWidget, SpyderPluginMixin):
CONF_SECTION = 'variable_explorer'
CONFIGWIDGET_CLASS = VariableExplorerConfigPage
sig_option_changed = Signal(str, object)

def __init__(self, parent):
QStackedWidget.__init__(self, parent)
SpyderPluginMixin.__init__(self, parent)
Expand Down
11 changes: 8 additions & 3 deletions spyderlib/plugins/workingdirectory.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# pylint: disable=R0911
# pylint: disable=R0201

from spyderlib.qt import PYQT5
from spyderlib.qt.QtGui import (QToolBar, QLabel, QGroupBox, QVBoxLayout,
QHBoxLayout, QButtonGroup)
from spyderlib.qt.QtCore import Signal, Slot
Expand Down Expand Up @@ -140,6 +141,7 @@ class WorkingDirectory(QToolBar, SpyderPluginMixin):
CONF_SECTION = 'workingdir'
CONFIGWIDGET_CLASS = WorkingDirectoryConfigPage
LOG_PATH = get_conf_path(CONF_SECTION)

sig_option_changed = Signal(str, object)
set_previous_enabled = Signal(bool)
set_next_enabled = Signal(bool)
Expand All @@ -148,9 +150,12 @@ class WorkingDirectory(QToolBar, SpyderPluginMixin):
refresh_findinfiles = Signal()
set_current_console_wd = Signal(str)

def __init__(self, parent, workdir=None):
QToolBar.__init__(self, parent)
SpyderPluginMixin.__init__(self, parent)
def __init__(self, parent, workdir=None, **kwds):
if PYQT5:
super().__init__(**kwds)
else:
QToolBar.__init__(self, parent)
SpyderPluginMixin.__init__(self, parent)

# Initialize plugin
self.initialize_plugin()
Expand Down
Loading

0 comments on commit 76eb4d8

Please sign in to comment.