Skip to content

Commit

Permalink
Merge pull request #103 from andfoy/webchannel_implementation
Browse files Browse the repository at this point in the history
PR: QWebChannel implementation and tests
  • Loading branch information
andfoy committed Aug 1, 2017
2 parents 271bd84 + 16ff260 commit d97b0da
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 16 deletions.
2 changes: 1 addition & 1 deletion circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ dependencies:
export PATH="$HOME/miniconda/bin:$PATH" &&
source activate test &&
conda install -q ciocheck -c spyder-ide --no-update-deps &&
if [ "$CIRCLE_NODE_INDEX" = "2" ]; then pip install -q spyder pyqt5 tornado pexpect; else conda install -q -y spyder && conda install tornado pexpect; fi &&
if [ "$CIRCLE_NODE_INDEX" = "2" ]; then pip install -q spyder pyqt5==5.8.0 tornado pexpect; else conda install -q -y spyder && conda install tornado pexpect; fi &&
if [ "$CIRCLE_NODE_INDEX" = "2" ]; then pip uninstall -q -y spyder; else conda remove -q -y spyder; fi &&
mkdir spyder-source && cd spyder-source &&
wget -q https://github.com/spyder-ide/spyder/archive/3.x.zip && unzip -q 3.x.zip &&
Expand Down
1 change: 1 addition & 0 deletions spyder_terminal/server/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<script src="static/components/xterm.js/dist/addons/fit/fit.js" ></script>
<script src="static/components/xterm.js/dist/addons/fullscreen/fullscreen.js" ></script>
<script src="static/components/jquery/dist/jquery.min.js"></script>
<script src="qrc:///qtwebchannel/qwebchannel.js" defer ></script>
</head>
<body>
<div id="terminal-container"></div>
Expand Down
34 changes: 26 additions & 8 deletions spyder_terminal/server/static/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ var term,
path,
curFont;

var promptEvent = new Event('promptReady');
var closeEvent = new Event('terminalClose');
var alive = true;
var lineEnd = '\n';
var clearCmd = 'clear';
Expand Down Expand Up @@ -90,16 +92,22 @@ function createTerminal() {
});
}

function getFonts() {
return $('.terminal').css('font-family');
}

function setFont(font) {
fonts = "'Ubuntu Mono', monospace";
fonts = "'"+font+"', "+fonts;
$('.terminal').css('font-family', fonts);
term.fit();
var initialGeometry = term.proposeGeometry(),
cols = initialGeometry.cols,
rows = initialGeometry.rows;
fonts = "'Ubuntu Mono', monospace";
fonts = "'"+font+"', "+fonts;
$('.terminal').css('font-family', fonts);

term.fit();
var initialGeometry = term.proposeGeometry(),
cols = initialGeometry.cols,
rows = initialGeometry.rows;
}


function fitFont(font) {
curFont = font;
setFont(font);
Expand Down Expand Up @@ -127,6 +135,7 @@ function exec(cmd)

function closeTerm() {
alive = false;
window.dispatchEvent(closeEvent);
console.log("Closed via server");
term.writeln("Pipe closed");
}
Expand Down Expand Up @@ -157,8 +166,8 @@ function runRealTerminal() {
var initialX = term.x;
var timer = setInterval(function() {
if(term.x != initialX) {
// term.clear();
fitFont(curFont);
window.dispatchEvent(promptEvent);
clearInterval(timer);
}
}, 200);
Expand All @@ -167,4 +176,13 @@ function runRealTerminal() {

$(document).ready(function() {
createTerminal();
new QWebChannel(qt.webChannelTransport, function (channel) {
window.handler = channel.objects.handler;
window.addEventListener('promptReady', function(e) {
window.handler.ready();
}, false);
window.addEventListener('terminalClose', function(e) {
window.handler.close();
}, false);
});
});
22 changes: 19 additions & 3 deletions spyder_terminal/tests/test_terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
from spyder_terminal.terminalplugin import TerminalPlugin
from spyder.py3compat import getcwd


LOCATION = os.path.realpath(os.path.join(os.getcwd(),
os.path.dirname(__file__)))
LOCATION_SLASH = LOCATION.replace('\\', '/')
Expand Down Expand Up @@ -52,6 +51,23 @@ def callback(data):
return LOCATION in termwidget.body.toHtml()


def check_fonts(term, expected):
"""Check if terminal fonts were updated."""
if WEBENGINE:
def callback(data):
global term_fonts
term_fonts = data
term.body.runJavaScript("getFonts()", callback)
try:
return term_fonts == expected
except NameError:
return False
else:
fonts = term.get_fonts()
fonts = fonts.replace("'", '"')
return fonts == expected


def check_num_tabs(terminal, ref_value):
"""Check if total number of terminal tabs has changed."""
value = len(terminal.get_terms())
Expand Down Expand Up @@ -81,8 +97,8 @@ def test_terminal_font(qtbot):
status_code = requests.get('http://127.0.0.1:{}'.format(port)).status_code
assert status_code == 200
term.set_font('Ubuntu Mono')
fonts = term.get_fonts()
assert fonts == "'Ubuntu Mono', 'Ubuntu Mono', monospace"
expected = '"Ubuntu Mono", "Ubuntu Mono", monospace'
qtbot.waitUntil(lambda: check_fonts(term, expected), timeout=TERM_UP)
terminal.closing_plugin()


Expand Down
40 changes: 36 additions & 4 deletions spyder_terminal/widgets/terminalgui.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
import sys

from spyder.config.base import _, DEV
from qtpy.QtCore import Qt, QUrl, Slot, QEvent, QTimer, Signal
from qtpy.QtCore import (Qt, QUrl, Slot, QEvent, QTimer, Signal,
QObject)
from qtpy.QtWidgets import (QMenu, QFrame, QVBoxLayout, QWidget)
from qtpy.QtGui import QKeySequence
from spyder.widgets.browser import WebView
Expand All @@ -21,6 +22,29 @@
from spyder.utils.qthelpers import create_action, add_actions

from qtpy.QtWebEngineWidgets import WEBENGINE
if WEBENGINE:
from PyQt5.QtWebChannel import QWebChannel


class ChannelHandler(QObject):
"""QWebChannel handler for JS calls."""

sig_ready = Signal()
sig_closed = Signal()

def __init__(self, parent):
"""Handler main constructor."""
QObject.__init__(self, parent)

@Slot()
def ready(self):
"""Invoke signal when terminal prompt is ready."""
self.sig_ready.emit()

@Slot()
def close(self):
"""Invoke signal when terminal process was closed externally."""
self.sig_closed.emit()


class TerminalWidget(QFrame):
Expand All @@ -33,7 +57,10 @@ def __init__(self, parent, port, path='~', font=None):
"""Frame main constructor."""
QWidget.__init__(self, parent)
url = 'http://127.0.0.1:{0}?path={1}'.format(port, path)
self.view = TermView(self, term_url=url)
self.handler = ChannelHandler(self)
self.handler.sig_ready.connect(lambda: self.terminal_ready.emit())
self.handler.sig_closed.connect(lambda: self.terminal_closed.emit())
self.view = TermView(self, term_url=url, handler=self.handler)
self.font = font
self.initial_path = path

Expand Down Expand Up @@ -73,7 +100,7 @@ def set_font(self, font):

def get_fonts(self):
"""List terminal CSS fonts."""
return self.eval_javascript("$('.terminal').css('font-family')")
return self.eval_javascript("getFonts()")

def exec_cmd(self, cmd):
"""Execute a command inside the terminal."""
Expand All @@ -95,7 +122,8 @@ def is_alive(self):
class TermView(WebView):
"""XTerm Wrapper."""

def __init__(self, parent, term_url='http://127.0.0.1:8070'):
def __init__(self, parent, term_url='http://127.0.0.1:8070',
handler=None):
"""Webview main constructor."""
WebView.__init__(self, parent)
self.parent = parent
Expand All @@ -107,6 +135,10 @@ def __init__(self, parent, term_url='http://127.0.0.1:8070'):
icon=ima.icon('editpaste'),
triggered=self.paste,
shortcut='Ctrl+Shift+V')
if WEBENGINE:
self.channel = QWebChannel(self.page())
self.page().setWebChannel(self.channel)
self.channel.registerObject('handler', handler)
self.term_url = QUrl(term_url)
self.load(self.term_url)

Expand Down

0 comments on commit d97b0da

Please sign in to comment.