Skip to content

Commit

Permalink
Added PyQt5 support (PyQ4 and PySide are also supported)
Browse files Browse the repository at this point in the history
  • Loading branch information
sandorracz committed Jan 5, 2015
1 parent 0c485fd commit 6629a92
Show file tree
Hide file tree
Showing 44 changed files with 384 additions and 74 deletions.
6 changes: 3 additions & 3 deletions bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
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: pyqt (for PyQt4/PyQt5) 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 Down Expand Up @@ -104,15 +104,15 @@
print(" and %s" % EXTPATH)


# Selecting the GUI toolkit: PySide if installed, otherwise PyQt4
# Selecting the GUI toolkit: PySide if installed, otherwise PyQt4 or PyQt5
# (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")
print("02. No PySide detected, using PyQt4 or PyQt5 if available")
else:
print ("02. Skipping GUI toolkit detection")
os.environ['QT_API'] = options.gui
Expand Down
22 changes: 16 additions & 6 deletions spyderlib/plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from spyderlib.plugins.configdialog import SpyderConfigPage
from spyderlib.py3compat import configparser, is_text_string
import sys
from spyderlib.qt import PYQT5


class PluginConfigPage(SpyderConfigPage):
Expand Down Expand Up @@ -154,9 +155,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 @@ -169,6 +173,7 @@ def __init__(self, main):
# the one that comes with dockwidget because it's not possible
# to raise and focus the plugin with it.
self.toggle_view_action = None


def initialize_plugin(self):
"""Initialize plugin: connect signals, setup actions, ..."""
Expand Down Expand Up @@ -341,6 +346,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"""
Expand Down Expand Up @@ -399,10 +405,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
16 changes: 13 additions & 3 deletions spyderlib/plugins/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from spyderlib.plugins import SpyderPluginWidget
from spyderlib.py3compat import to_text_string, getcwd

from spyderlib.qt import PYQT5

class Console(SpyderPluginWidget):
"""
Expand All @@ -43,10 +44,16 @@ class Console(SpyderPluginWidget):
focus_changed = Signal()
redirect_stdio = Signal(bool)
edit_goto = Signal(str, int, str)

show_message = Signal(str, int)
update_plugin_title = Signal()


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 +68,15 @@ 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 All @@ -85,6 +94,7 @@ def __init__(self, parent=None, namespace=None, commands=[], message=None,

# Accepting drops
self.setAcceptDrops(True)


#------ Private API --------------------------------------------------------
def set_historylog(self, historylog):
Expand Down
15 changes: 13 additions & 2 deletions spyderlib/plugins/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
get_run_configuration,
ALWAYS_OPEN_FIRST_RUN_OPTION)
from spyderlib.py3compat import to_text_string, getcwd, qbytearray_to_str
from spyderlib.qt import PYQT5


def _load_all_breakpoints():
Expand Down Expand Up @@ -339,9 +340,15 @@ class Editor(SpyderPluginWidget):
open_dir = Signal(str)
breakpoints_saved = Signal()
run_in_current_extconsole = Signal(str, str, str, bool)
show_message = Signal(str, int)
update_plugin_title = Signal()


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 @@ -1548,7 +1555,8 @@ def change_max_recent_files(self):
if valid:
self.set_option('max_recent_files', mrf)

@Slot()

@Slot(str, int, str, object)
def load(self, filenames=None, goto=None, word='', editorwindow=None,
processevents=True):
"""
Expand Down Expand Up @@ -1985,9 +1993,12 @@ def debug_command(self, command):
self.main.extconsole.execute_python_code(command)
else:
self.main.ipyconsole.write_to_stdin(command)

focus_widget = self.main.ipyconsole.get_focus_widget()

if focus_widget:
focus_widget.setFocus()

else:
self.main.extconsole.execute_python_code(command)

Expand Down
3 changes: 3 additions & 0 deletions spyderlib/plugins/explorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ class Explorer(ExplorerWidget, SpyderPluginMixin):
create_module = Signal(str)
run = Signal(str)
open_dir = Signal(str)
show_message = Signal(str, int)
update_plugin_title = Signal()


def __init__(self, parent=None):
ExplorerWidget.__init__(self, parent=parent,
Expand Down
13 changes: 11 additions & 2 deletions spyderlib/plugins/externalconsole.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@
from spyderlib.plugins.runconfig import get_run_configuration
from spyderlib.py3compat import to_text_string, is_text_string, getcwd
from spyderlib import dependencies
from spyderlib.qt import PYQT5

MPL_REQVER = '>=1.0'
dependencies.add("matplotlib", _("Interactive data plotting in the consoles"),
required_version=MPL_REQVER)


class ExternalConsoleConfigPage(PluginConfigPage):

def __init__(self, plugin, parent):
PluginConfigPage.__init__(self, plugin, parent)
self.get_name = lambda: _("Console")
Expand Down Expand Up @@ -448,9 +450,16 @@ class ExternalConsole(SpyderPluginWidget):
edit_goto = Signal(str, int, str, bool)
focus_changed = Signal()
redirect_stdio = Signal(bool)
show_message = Signal(str, int)
update_plugin_title = Signal()
go_to_error = Signal(str)


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 Expand Up @@ -693,7 +702,7 @@ def pdb_has_stopped(self, fname, lineno, shellwidget):
# This is a unique form of the edit_goto signal that is intended to
# prevent keyboard input from accidentally entering the editor
# during repeated, rapid entry of debugging commands.
self.edit_got.emit(fname, lineno, '', False)
self.edit_goto.emit(fname, lineno, '', False)
if shellwidget.is_ipykernel:
# Focus client widget, not kernel
ipw = self.main.ipyconsole.get_focus_widget()
Expand Down
3 changes: 3 additions & 0 deletions spyderlib/plugins/findinfiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class FindInFiles(FindInFilesWidget, SpyderPluginMixin):
toggle_visibility = Signal(bool)
edit_goto = Signal(str, int, str)
redirect_stdio = Signal(bool)
show_message = Signal(str, int)
update_plugin_title = Signal()


def __init__(self, parent=None):
supported_encodings = self.get_option('supported_encodings')
Expand Down
10 changes: 8 additions & 2 deletions spyderlib/plugins/history.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from spyderlib.widgets.findreplace import FindReplace
from spyderlib.plugins import SpyderPluginWidget, PluginConfigPage
from spyderlib.py3compat import to_text_string, is_text_string
from spyderlib.qt import PYQT5


class HistoryConfigPage(PluginConfigPage):
Expand Down Expand Up @@ -75,6 +76,9 @@ class HistoryLog(SpyderPluginWidget):
CONFIGWIDGET_CLASS = HistoryConfigPage
# Signals
focus_changed = Signal()
show_message = Signal(str, int)
update_plugin_title = Signal()


def __init__(self, parent):
self.tabwidget = None
Expand All @@ -85,8 +89,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
11 changes: 10 additions & 1 deletion spyderlib/plugins/inspector.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from spyderlib.widgets.externalshell.pythonshell import ExtPythonShellWidget
from spyderlib.plugins import SpyderPluginWidget, PluginConfigPage
from spyderlib.py3compat import to_text_string, get_meth_class_inst
from spyderlib.qt import PYQT5

#XXX: Hardcoded dependency on optional IPython plugin component
# that requires the hack to make this work without IPython
Expand Down Expand Up @@ -354,9 +355,16 @@ class ObjectInspector(SpyderPluginWidget):
LOG_PATH = get_conf_path(CONF_SECTION)
# Signals
focus_changed = Signal()
show_message = Signal(str, int)
update_plugin_title = Signal()
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 All @@ -371,6 +379,7 @@ def __init__(self, parent):
self.set_default_color_scheme()

self.plain_text = PlainText(self)

self.rich_text = RichText(self)

color_scheme = get_color_scheme(self.get_option('color_scheme_name'))
Expand Down
10 changes: 9 additions & 1 deletion spyderlib/plugins/ipythonconsole.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
from spyderlib.widgets.findreplace import FindReplace
from spyderlib.plugins import SpyderPluginWidget, PluginConfigPage
from spyderlib.py3compat import to_text_string, u
from spyderlib.qt import PYQT5


SYMPY_REQVER = '>=0.7.0'
Expand Down Expand Up @@ -148,6 +149,8 @@ def openssh_tunnel(self, lport, rport, server, remoteip='127.0.0.1',


class IPythonConsoleConfigPage(PluginConfigPage):

append_to_history = Signal(str, str)

def __init__(self, plugin, parent):
PluginConfigPage.__init__(self, plugin, parent)
Expand Down Expand Up @@ -577,9 +580,14 @@ class IPythonConsole(SpyderPluginWidget):
focus_changed = Signal()
edit_goto = Signal(str, int, str)
focus_changed = Signal()
show_message = Signal(str, int)
update_plugin_title = 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
4 changes: 4 additions & 0 deletions spyderlib/plugins/onlinehelp.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@ class OnlineHelp(PydocBrowser, SpyderPluginMixin):
Online Help Plugin
"""
sig_option_changed = Signal(str, object)
show_message = Signal(str, int)
update_plugin_title = Signal()

CONF_SECTION = 'onlinehelp'
LOG_PATH = get_conf_path(CONF_SECTION)

def __init__(self, parent):
self.main = parent
PydocBrowser.__init__(self, parent)
Expand Down
2 changes: 2 additions & 0 deletions spyderlib/plugins/outlineexplorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
class OutlineExplorer(OutlineExplorerWidget, SpyderPluginMixin):
CONF_SECTION = 'outline_explorer'
sig_option_changed = Signal(str, object)
show_message = Signal(str, int)
update_plugin_title = Signal()

def __init__(self, parent=None, fullpath_sorting=True):
show_fullpath = self.get_option('show_fullpath')
Expand Down
3 changes: 3 additions & 0 deletions spyderlib/plugins/projectexplorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ class ProjectExplorer(ProjectExplorerWidget, SpyderPluginMixin):
removed_tree = Signal(str)
renamed = Signal(str, str)
redirect_stdio = Signal(bool)
show_message = Signal(str, int)
update_plugin_title = Signal()


def __init__(self, parent=None):
ProjectExplorerWidget.__init__(self, parent=parent,
Expand Down
5 changes: 5 additions & 0 deletions spyderlib/plugins/shortcuts.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@ 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
3 changes: 3 additions & 0 deletions spyderlib/plugins/variableexplorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ class VariableExplorer(QStackedWidget, SpyderPluginMixin):
CONF_SECTION = 'variable_explorer'
CONFIGWIDGET_CLASS = VariableExplorerConfigPage
sig_option_changed = Signal(str, object)
show_message = Signal(str, int)
update_plugin_title = Signal()

def __init__(self, parent):
QStackedWidget.__init__(self, parent)
SpyderPluginMixin.__init__(self, parent)
Expand Down
Loading

0 comments on commit 6629a92

Please sign in to comment.