mirror of
https://github.com/GNS3/gns3-gui.git
synced 2026-05-17 00:46:01 +03:00
Base for the GNS3 console & some minor fixes.
This commit is contained in:
58
gns3/console_cmd.py
Normal file
58
gns3/console_cmd.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2014 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Handles commands typed in the GNS3 console.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import cmd
|
||||
import logging
|
||||
from .version import __version__
|
||||
|
||||
|
||||
class ConsoleCmd(cmd.Cmd):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
cmd.Cmd.__init__(self)
|
||||
|
||||
def do_version(self, args):
|
||||
|
||||
print("GNS3 version {}".format(__version__))
|
||||
|
||||
def do_debug(self, args):
|
||||
"""
|
||||
debug [level] (0 or 1).
|
||||
"""
|
||||
|
||||
root = logging.getLogger()
|
||||
ch = logging.StreamHandler(sys.stdout)
|
||||
|
||||
if len(args) == 1:
|
||||
try:
|
||||
level = int(args[0])
|
||||
if level == 0:
|
||||
print("Deactivating debugging")
|
||||
root.removeHandler(ch)
|
||||
else:
|
||||
print("Activating debugging")
|
||||
root.addHandler(ch)
|
||||
except:
|
||||
print(self.do_debug.__doc__)
|
||||
else:
|
||||
print(self.do_debug.__doc__)
|
||||
143
gns3/console_view.py
Normal file
143
gns3/console_view.py
Normal file
@@ -0,0 +1,143 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2014 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import sys
|
||||
from .version import __version__
|
||||
from .console_cmd import ConsoleCmd
|
||||
from .pycutext import PyCutExt
|
||||
|
||||
|
||||
class ConsoleView(PyCutExt, ConsoleCmd):
|
||||
|
||||
# list of keywords to color
|
||||
keywords = set(["aux",
|
||||
"capture",
|
||||
"clear",
|
||||
"console",
|
||||
"export",
|
||||
"filter",
|
||||
"help",
|
||||
"hist",
|
||||
"idlepc",
|
||||
"import",
|
||||
"list",
|
||||
"no",
|
||||
"push",
|
||||
"reload",
|
||||
"resume",
|
||||
"save",
|
||||
"send",
|
||||
"show",
|
||||
"start",
|
||||
"stop",
|
||||
"suspend",
|
||||
"telnet",
|
||||
"vboxexec",
|
||||
"qmonitor",
|
||||
"ver"])
|
||||
|
||||
def __init__(self, parent):
|
||||
|
||||
# Set the prompt PyCutExt
|
||||
self.prompt = '=> '
|
||||
sys.ps1 = '=> '
|
||||
|
||||
# Set introduction message
|
||||
self.intro = "GNS3 management console. Running GNS3 version %s.\nCopyright (c) 2006-2014 GNS3 Project." % __version__
|
||||
|
||||
# Parent class initialization
|
||||
try:
|
||||
PyCutExt.__init__(self, None, self.intro, parent=parent)
|
||||
# put our own keywords list
|
||||
self.colorizer.keywords = self.keywords
|
||||
#self._Dynagen_Console_init()
|
||||
except Exception as e:
|
||||
sys.stderr.write(e)
|
||||
|
||||
def onKeyPress_Tab(self):
|
||||
"""
|
||||
Imitate cmd.Cmd.complete(self, text, state) function.
|
||||
"""
|
||||
|
||||
line = str(self.line).lstrip()
|
||||
cmd = line
|
||||
args = ''
|
||||
|
||||
if len(self.line) > 0:
|
||||
cmd, args, _ = self.parseline(line)
|
||||
if cmd == '':
|
||||
compfunc = self.completedefault
|
||||
else:
|
||||
try:
|
||||
compfunc = getattr(self, 'complete_' + cmd)
|
||||
except AttributeError:
|
||||
compfunc = self.completenames
|
||||
else:
|
||||
compfunc = self.completenames
|
||||
|
||||
self.completion_matches = compfunc(cmd, line, 0, 0)
|
||||
if self.completion_matches is not None:
|
||||
# Eliminate repeating values
|
||||
matches = []
|
||||
for m in self.completion_matches:
|
||||
try:
|
||||
matches.index(m)
|
||||
except ValueError:
|
||||
matches.append(m)
|
||||
|
||||
# Update original list
|
||||
self.completion_matches = matches
|
||||
|
||||
# In case we only have one possible value replace it on cmdline
|
||||
if len(self.completion_matches) == 1:
|
||||
newLine = self.completion_matches[0] + " " + args
|
||||
self.line = newLine
|
||||
self.point = len(newLine)
|
||||
# Else, display possible values
|
||||
else:
|
||||
self.write("\n")
|
||||
self.columnize(self.completion_matches)
|
||||
|
||||
# In any case, reprint promt + line
|
||||
self.write("\n" + sys.ps1 + str(self.line))
|
||||
|
||||
def write_error(self, name, code, message):
|
||||
|
||||
print("Error received from {} with code {} and message: {}\n".format(name, code, message))
|
||||
|
||||
def _run(self):
|
||||
"""
|
||||
Runs as command as the cmd.Cmd class would do.
|
||||
PyCutExt was originally using as Interpreter to exec user's commands.
|
||||
Here we use directly the cmd.Cmd class.
|
||||
"""
|
||||
|
||||
self.pointer = 0
|
||||
if len(self.line):
|
||||
self.history.append(self.line)
|
||||
try:
|
||||
self.lines.append(self.line)
|
||||
source = "\n".join(self.lines)
|
||||
self.more = self.onecmd(source)
|
||||
except Exception as e:
|
||||
print("Unknown command")
|
||||
#print(str(e))
|
||||
|
||||
self.write(self.prompt)
|
||||
self.lines = []
|
||||
self._clearLine()
|
||||
@@ -659,7 +659,7 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
contextual menu.
|
||||
"""
|
||||
|
||||
from .console import telnetConsole
|
||||
from .telnet_console import telnetConsole
|
||||
for item in self.scene().selectedItems():
|
||||
if hasattr(item.node(), "console"):
|
||||
node = item.node()
|
||||
@@ -761,6 +761,9 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
if not node_module:
|
||||
raise ModuleError("Could not find any module for {}".format(node_class))
|
||||
node = node_module.createNode(node_class)
|
||||
# from .main_window import MainWindow
|
||||
# mainwindow = MainWindow.instance()
|
||||
# node.error_signal.connect(mainwindow.uiConsoleTextEdit.write_error)
|
||||
node_item = NodeItem(node)
|
||||
node_module.setupNode(node)
|
||||
except ModuleError as e:
|
||||
|
||||
@@ -443,7 +443,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
Slot called when connecting to all the nodes using the console.
|
||||
"""
|
||||
|
||||
from .console import telnetConsole
|
||||
from .telnet_console import telnetConsole
|
||||
for item in self.uiGraphicsView.scene().items():
|
||||
if isinstance(item, NodeItem) and hasattr(item.node(), "console"):
|
||||
node = item.node()
|
||||
|
||||
@@ -285,6 +285,8 @@ class Router(Node):
|
||||
# update the node with setup initial settings if any
|
||||
if self._inital_settings:
|
||||
self.update(self._inital_settings)
|
||||
elif self._loading:
|
||||
self.updated_signal.emit()
|
||||
else:
|
||||
self.setInitialized(True)
|
||||
log.debug("router {} has been created".format(self.name()))
|
||||
|
||||
@@ -237,6 +237,8 @@ class RouterConfigurationPage(QtGui.QWidget, Ui_routerConfigPageWidget):
|
||||
self.uiNameLineEdit.setText(settings["name"])
|
||||
self.uiConsolePortSpinBox.setValue(settings["console"])
|
||||
self.uiAuxPortSpinBox.setValue(settings["aux"])
|
||||
# load the startup-config
|
||||
self.uiStartupConfigTextLabel.setText(settings["startup_config"])
|
||||
# load the MAC address setting
|
||||
if settings["mac_addr"]:
|
||||
self.uiBaseMACLineEdit.setText(settings["mac_addr"])
|
||||
@@ -245,6 +247,8 @@ class RouterConfigurationPage(QtGui.QWidget, Ui_routerConfigPageWidget):
|
||||
else:
|
||||
self.uiNameLabel.hide()
|
||||
self.uiNameLineEdit.hide()
|
||||
self.uiStartupConfigLabel.hide()
|
||||
self.uiStartupConfigTextLabel.hide()
|
||||
self.uiConsolePortLabel.hide()
|
||||
self.uiConsolePortSpinBox.hide()
|
||||
self.uiAuxPortLabel.hide()
|
||||
@@ -266,8 +270,7 @@ class RouterConfigurationPage(QtGui.QWidget, Ui_routerConfigPageWidget):
|
||||
# load the IOS image name without the full path
|
||||
self.uiIOSImageTextLabel.setText(os.path.basename(settings["image"]))
|
||||
|
||||
# load the startup-config
|
||||
self.uiStartupConfigTextLabel.setText(settings["startup_config"])
|
||||
|
||||
|
||||
#TODO: startup-config setting
|
||||
#self.uiStartupConfigTextLabel.setText("None")
|
||||
@@ -392,6 +395,7 @@ class RouterConfigurationPage(QtGui.QWidget, Ui_routerConfigPageWidget):
|
||||
del settings["console"]
|
||||
del settings["aux"]
|
||||
del settings["mac_addr"]
|
||||
del settings["startup_config"]
|
||||
|
||||
#del self._settings["image"]
|
||||
# get the platform and chassis if applicable
|
||||
|
||||
@@ -143,6 +143,8 @@ class IOUDevice(Node):
|
||||
# update the node with setup initial settings if any
|
||||
if self._inital_settings:
|
||||
self.update(self._inital_settings)
|
||||
elif self._loading:
|
||||
self.updated_signal.emit()
|
||||
else:
|
||||
self.setInitialized(True)
|
||||
log.info("IOU instance {} has been created".format(self.name()))
|
||||
@@ -307,6 +309,28 @@ class IOUDevice(Node):
|
||||
port.setStatus(Port.stopped)
|
||||
self.stopped_signal.emit()
|
||||
|
||||
def reload(self):
|
||||
"""
|
||||
Reloads this IOU instance.
|
||||
"""
|
||||
|
||||
log.debug("{} is being reloaded".format(self.name()))
|
||||
self._server.send_message("iou.reload", {"id": self._iou_id}, self._reloadCallback)
|
||||
|
||||
def _reloadCallback(self, result, error=False):
|
||||
"""
|
||||
Callback for reload.
|
||||
|
||||
:param result: server response
|
||||
:param error: indicates an error (boolean)
|
||||
"""
|
||||
|
||||
if error:
|
||||
log.error("error while suspending {}: {}".format(self.name(), result["message"]))
|
||||
self.error_signal.emit(self.name(), result["code"], result["message"])
|
||||
else:
|
||||
log.info("{} has reloaded".format(self.name()))
|
||||
|
||||
def allocateUDPPort(self, port_id):
|
||||
"""
|
||||
Requests an UDP port allocation.
|
||||
@@ -529,7 +553,7 @@ class IOUDevice(Node):
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/router.normal.svg"
|
||||
return ":/symbols/multilayer_switch.normal.svg"
|
||||
|
||||
@staticmethod
|
||||
def hoverSymbol():
|
||||
@@ -539,7 +563,7 @@ class IOUDevice(Node):
|
||||
:returns: symbol path (or resource).
|
||||
"""
|
||||
|
||||
return ":/symbols/router.selected.svg"
|
||||
return ":/symbols/multilayer_switch.selected.svg"
|
||||
|
||||
@staticmethod
|
||||
def symbolName():
|
||||
|
||||
389
gns3/pycutext.py
Normal file
389
gns3/pycutext.py
Normal file
@@ -0,0 +1,389 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2014 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
This module implements a QT4 Python interpreter widget.
|
||||
It is inspired by PyCute : http://gerard.vermeulen.free.fr
|
||||
"""
|
||||
|
||||
import sys
|
||||
from .qt import QtCore, QtGui
|
||||
#from code import InteractiveInterpreter as Interpreter
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# class MultipleRedirection:
|
||||
# """ Dummy file which redirects stream to multiple file """
|
||||
#
|
||||
# def __init__(self, files):
|
||||
# """ The stream is redirect to the file list 'files' """
|
||||
#
|
||||
# self.files = files
|
||||
#
|
||||
# def write(self, str):
|
||||
# """ Emulate write function """
|
||||
#
|
||||
# for f in self.files:
|
||||
# f.write(str)
|
||||
#===============================================================================
|
||||
|
||||
class PyCutExt(QtGui.QTextEdit):
|
||||
"""
|
||||
PyCute is a Python shell for PyQt.
|
||||
|
||||
Creating, displaying and controlling PyQt widgets from the Python command
|
||||
line interpreter is very hard, if not, impossible. PyCute solves this
|
||||
problem by interfacing the Python interpreter to a PyQt widget.
|
||||
"""
|
||||
|
||||
def __init__(self, interpreter, message="", log="", parent=None):
|
||||
|
||||
QtGui.QTextEdit.__init__(self, parent)
|
||||
|
||||
self.interpreter = interpreter
|
||||
self.colorizer = SyntaxColor()
|
||||
|
||||
# session log
|
||||
self.log = log or ''
|
||||
|
||||
# to exit the main interpreter by a Ctrl-D if PyCute has no parent
|
||||
if parent is None:
|
||||
self.eofKey = QtCore.Qt.Key_D
|
||||
else:
|
||||
self.eofKey = None
|
||||
|
||||
# capture all interactive input/output
|
||||
sys.stdout = self
|
||||
#sys.stderr = MultipleRedirection((sys.stderr, self))
|
||||
sys.stdin = self
|
||||
|
||||
# last line + last incomplete lines
|
||||
self.line = ""
|
||||
self.lines = []
|
||||
|
||||
# the cursor position in the last line
|
||||
self.point = 0
|
||||
|
||||
# flag: the interpreter needs more input to run the last lines.
|
||||
self.more = 0
|
||||
|
||||
# flag: readline() is being used for e.g. raw_input() and input()
|
||||
self.reading = 0
|
||||
|
||||
# history
|
||||
self.history = []
|
||||
self.pointer = 0
|
||||
self.cursor_pos = 0
|
||||
|
||||
self.setLineWrapMode(QtGui.QTextEdit.NoWrap)
|
||||
|
||||
try:
|
||||
sys.ps1
|
||||
except AttributeError:
|
||||
sys.ps1 = ">>> "
|
||||
try:
|
||||
sys.ps2
|
||||
except AttributeError:
|
||||
sys.ps2 = "... "
|
||||
|
||||
self.write(message + '\n\n')
|
||||
self.write(sys.ps1)
|
||||
|
||||
def get_interpreter(self):
|
||||
"""
|
||||
Return the interpreter object
|
||||
"""
|
||||
|
||||
return self.interpreter
|
||||
|
||||
def moveCursor(self, operation, mode=QtGui.QTextCursor.MoveAnchor):
|
||||
"""
|
||||
Convenience function to move the cursor
|
||||
This function will be present in PyQT4.2
|
||||
"""
|
||||
cursor = self.textCursor()
|
||||
cursor.movePosition(operation, mode)
|
||||
self.setTextCursor(cursor)
|
||||
|
||||
def flush(self):
|
||||
"""
|
||||
Simulate stdin, stdout, and stderr.
|
||||
"""
|
||||
pass
|
||||
|
||||
def isatty(self):
|
||||
"""
|
||||
Simulate stdin, stdout, and stderr.
|
||||
"""
|
||||
return 1
|
||||
|
||||
def readline(self):
|
||||
"""
|
||||
Simulate stdin, stdout, and stderr.
|
||||
"""
|
||||
|
||||
self.reading = 1
|
||||
self._clearLine()
|
||||
self.moveCursor(QtGui.QTextCursor.End)
|
||||
while self.reading:
|
||||
QtGui.QApplication.processEvents(QtCore.QEventLoop.AllEvents, 1000)
|
||||
if len(self.line) == 0:
|
||||
return '\n'
|
||||
else:
|
||||
return self.line
|
||||
|
||||
def write(self, text):
|
||||
"""
|
||||
Simulates stdin, stdout, and stderr.
|
||||
"""
|
||||
|
||||
cursor = self.textCursor()
|
||||
cursor.movePosition(QtGui.QTextCursor.End)
|
||||
|
||||
pos1 = cursor.position()
|
||||
cursor.insertText(text)
|
||||
|
||||
self.cursor_pos = cursor.position()
|
||||
self.setTextCursor(cursor)
|
||||
self.ensureCursorVisible()
|
||||
|
||||
# Set the format
|
||||
cursor.setPosition(pos1, QtGui.QTextCursor.KeepAnchor)
|
||||
char_format = cursor.charFormat()
|
||||
char_format.setForeground(QtGui.QBrush(QtGui.QColor(0, 0, 0)))
|
||||
cursor.setCharFormat(char_format)
|
||||
|
||||
def writelines(self, text):
|
||||
"""
|
||||
Simulate stdin, stdout, and stderr.
|
||||
"""
|
||||
map(self.write, text)
|
||||
|
||||
def _run(self):
|
||||
"""
|
||||
Append the last line to the history list, let the interpreter execute
|
||||
the last line(s), and clean up accounting for the interpreter results:
|
||||
(1) the interpreter succeeds
|
||||
(2) the interpreter fails, finds no errors and wants more line(s)
|
||||
(3) the interpreter fails, finds errors and writes them to sys.stderr
|
||||
"""
|
||||
|
||||
self.pointer = 0
|
||||
self.history.append(self.line)
|
||||
try:
|
||||
self.lines.append(self.line)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
source = '\n'.join(self.lines)
|
||||
self.more = self.interpreter.runsource(source)
|
||||
|
||||
if self.more:
|
||||
self.write(sys.ps2)
|
||||
else:
|
||||
self.write(sys.ps1)
|
||||
self.lines = []
|
||||
self._clearLine()
|
||||
|
||||
def _clearLine(self):
|
||||
"""
|
||||
Clear input line buffer
|
||||
"""
|
||||
self.line = ""
|
||||
self.point = 0
|
||||
|
||||
def _insertText(self, text):
|
||||
"""
|
||||
Inserts text at the current cursor position.
|
||||
"""
|
||||
|
||||
self.line = self.line[:self.point] + text + self.line[self.point:]
|
||||
self.point += len(text)
|
||||
|
||||
cursor = self.textCursor()
|
||||
cursor.insertText(text)
|
||||
self.color_line()
|
||||
|
||||
def keyPressEvent(self, e):
|
||||
"""
|
||||
Handle user input a key at a time.
|
||||
"""
|
||||
|
||||
text = e.text()
|
||||
key = e.key()
|
||||
|
||||
# Keep the cursor after the last prompt.
|
||||
self.moveCursor(QtGui.QTextCursor.End)
|
||||
|
||||
if key == QtCore.Qt.Key_Backspace:
|
||||
if self.point:
|
||||
cursor = self.textCursor()
|
||||
cursor.movePosition(QtGui.QTextCursor.PreviousCharacter, QtGui.QTextCursor.KeepAnchor)
|
||||
cursor.removeSelectedText()
|
||||
self.color_line()
|
||||
|
||||
self.point -= 1
|
||||
self.line = self.line[:-1]
|
||||
|
||||
elif key == QtCore.Qt.Key_Delete:
|
||||
cursor = self.textCursor()
|
||||
cursor.movePosition(QtGui.QTextCursor.NextCharacter, QtGui.QTextCursor.KeepAnchor)
|
||||
cursor.removeSelectedText()
|
||||
self.color_line()
|
||||
|
||||
self.line = self.line[:-1]
|
||||
|
||||
elif key == QtCore.Qt.Key_Return or key == QtCore.Qt.Key_Enter:
|
||||
self.write("\n")
|
||||
if self.reading:
|
||||
self.reading = 0
|
||||
else:
|
||||
self._run()
|
||||
|
||||
elif key == QtCore.Qt.Key_Tab:
|
||||
self.onKeyPress_Tab()
|
||||
elif key == QtCore.Qt.Key_Left:
|
||||
if self.point:
|
||||
self.moveCursor(QtGui.QTextCursor.Left)
|
||||
self.point -= 1
|
||||
elif key == QtCore.Qt.Key_Right:
|
||||
if self.point < len(self.line):
|
||||
self.moveCursor(QtGui.QTextCursor.Right)
|
||||
self.point += 1
|
||||
|
||||
elif key == QtCore.Qt.Key_Home:
|
||||
cursor = self.textCursor()
|
||||
cursor.setPosition(self.cursor_pos)
|
||||
self.setTextCursor(cursor)
|
||||
self.point = 0
|
||||
|
||||
elif key == QtCore.Qt.Key_End:
|
||||
self.moveCursor(QtGui.QTextCursor.EndOfLine)
|
||||
self.point = len(self.line)
|
||||
|
||||
elif key == QtCore.Qt.Key_Up:
|
||||
|
||||
if len(self.history):
|
||||
if self.pointer == 0:
|
||||
self.pointer = len(self.history)
|
||||
self.pointer -= 1
|
||||
self._recall()
|
||||
|
||||
elif key == QtCore.Qt.Key_Down:
|
||||
if len(self.history):
|
||||
self.pointer += 1
|
||||
if self.pointer == len(self.history):
|
||||
self.pointer = 0
|
||||
self._recall()
|
||||
|
||||
elif len(text):
|
||||
self._insertText(text)
|
||||
return
|
||||
|
||||
else:
|
||||
e.ignore()
|
||||
|
||||
def _recall(self):
|
||||
"""
|
||||
Display the current item from the command history.
|
||||
"""
|
||||
|
||||
cursor = self.textCursor()
|
||||
cursor.select(QtGui.QTextCursor.LineUnderCursor)
|
||||
cursor.removeSelectedText()
|
||||
|
||||
if self.more:
|
||||
self.write(sys.ps2)
|
||||
else:
|
||||
self.write(sys.ps1)
|
||||
|
||||
self._clearLine()
|
||||
self._insertText(self.history[self.pointer])
|
||||
|
||||
def contentsContextMenuEvent(self, ev):
|
||||
"""
|
||||
Suppress the right button context menu.
|
||||
"""
|
||||
|
||||
return
|
||||
|
||||
def color_line(self):
|
||||
"""
|
||||
Color the current line.
|
||||
"""
|
||||
|
||||
cursor = self.textCursor()
|
||||
cursor.movePosition(QtGui.QTextCursor.StartOfLine)
|
||||
|
||||
newpos = cursor.position()
|
||||
pos = -1
|
||||
|
||||
while(newpos != pos):
|
||||
cursor.movePosition(QtGui.QTextCursor.NextWord)
|
||||
|
||||
pos = newpos
|
||||
newpos = cursor.position()
|
||||
|
||||
cursor.select(QtGui.QTextCursor.WordUnderCursor)
|
||||
word = cursor.selectedText()
|
||||
|
||||
if not word:
|
||||
continue
|
||||
|
||||
(R, G, B) = self.colorizer.get_color(word)
|
||||
char_format = cursor.charFormat()
|
||||
char_format.setForeground(QtGui.QBrush(QtGui.QColor(R, G, B)))
|
||||
cursor.setCharFormat(char_format)
|
||||
|
||||
|
||||
class SyntaxColor(object):
|
||||
"""
|
||||
Allows to color python keywords.
|
||||
"""
|
||||
|
||||
keywords = set(["and", "del", "from", "not", "while",
|
||||
"as", "elif", "global", "or", "with",
|
||||
"assert", "else", "if", "pass", "yield",
|
||||
"break", "except", "import", "print",
|
||||
"class", "exec", "in", "raise",
|
||||
"continue", "finally", "is", "return",
|
||||
"def", "for", "lambda", "try"])
|
||||
|
||||
def get_color(self, word):
|
||||
""" Return a color tuple (R,G,B) depending of the string word """
|
||||
|
||||
stripped = word.strip()
|
||||
|
||||
if(stripped in self.keywords):
|
||||
return (165, 42, 42) # brown
|
||||
elif(self.is_python_string(stripped)):
|
||||
return (61, 120, 9) # dark green
|
||||
else:
|
||||
return (0, 0, 0)
|
||||
|
||||
def is_python_string(self, string):
|
||||
"""
|
||||
Return True if string is enclosed by a string mark
|
||||
"""
|
||||
|
||||
# return (
|
||||
# (string.startswith("'''") and string.endswith("'''")) or
|
||||
# (string.startswith('"""') and string.endswith('"""')) or
|
||||
# (string.startswith("'") and string.endswith("'")) or
|
||||
# (string.startswith('"') and string.endswith('"'))
|
||||
# )
|
||||
return False
|
||||
@@ -45,7 +45,7 @@ if sys.platform.startswith("win") and "PROGRAMFILES(X86)" in os.environ and os.p
|
||||
'Xshell 4': 'C:\Program Files (x86)\\NetSarang\\Xshell 4\\xshell.exe -url telnet://%h:%p'}
|
||||
|
||||
# default Windows 64-bit Telnet console command
|
||||
if os.path.exists(os.getcwdu() + os.sep + "SuperPutty.exe"):
|
||||
if os.path.exists(os.getcwd() + os.sep + "SuperPutty.exe"):
|
||||
DEFAULT_TELNET_CONSOLE_COMMAND = PRECONFIGURED_TELNET_CONSOLE_COMMANDS["SuperPutty"]
|
||||
else:
|
||||
DEFAULT_TELNET_CONSOLE_COMMAND = PRECONFIGURED_TELNET_CONSOLE_COMMANDS["Putty (included with GNS3)"]
|
||||
@@ -60,7 +60,7 @@ elif sys.platform.startswith("win"):
|
||||
'Xshell 4': 'C:\Program Files\\NetSarang\\Xshell 4\\xshell.exe -url telnet://%h:%p'}
|
||||
|
||||
# default Windows 32-bit Telnet console command
|
||||
if os.path.exists(os.getcwdu() + os.sep + "SuperPutty.exe"):
|
||||
if os.path.exists(os.getcwd() + os.sep + "SuperPutty.exe"):
|
||||
DEFAULT_TELNET_CONSOLE_COMMAND = PRECONFIGURED_TELNET_CONSOLE_COMMANDS["SuperPutty"]
|
||||
else:
|
||||
DEFAULT_TELNET_CONSOLE_COMMAND = PRECONFIGURED_TELNET_CONSOLE_COMMANDS["Putty (included with GNS3)"]
|
||||
@@ -97,7 +97,7 @@ if sys.platform.startswith("win"):
|
||||
'SuperPutty': 'SuperPutty.exe -serial "%s -wt \"%d\" -gns3 5 -skin 4"'}
|
||||
|
||||
# default Windows serial console command
|
||||
if os.path.exists(os.getcwdu() + os.sep + "SuperPutty.exe"):
|
||||
if os.path.exists(os.getcwd() + os.sep + "SuperPutty.exe"):
|
||||
DEFAULT_SERIAL_CONSOLE_COMMAND = PRECONFIGURED_SERIAL_CONSOLE_COMMANDS["SuperPutty"]
|
||||
else:
|
||||
DEFAULT_SERIAL_CONSOLE_COMMAND = PRECONFIGURED_SERIAL_CONSOLE_COMMANDS["Putty (included with GNS3)"]
|
||||
|
||||
@@ -343,7 +343,7 @@ background-none;
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="uiConsoleTextEdit">
|
||||
<widget class="ConsoleView" name="uiConsoleTextEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -1147,6 +1147,11 @@ background-none;
|
||||
<extends>QTreeWidget</extends>
|
||||
<header>..nodes_view.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ConsoleView</class>
|
||||
<extends>QTextEdit</extends>
|
||||
<header>..console_view.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>uiGraphicsView</tabstop>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# Form implementation generated from reading ui file '/home/grossmj/workspace/git/gns3-gui/gns3/ui/main_window.ui'
|
||||
#
|
||||
# Created: Thu Feb 13 15:42:20 2014
|
||||
# Created: Tue Mar 11 18:26:17 2014
|
||||
# by: PyQt4 UI code generator 4.10
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
@@ -141,7 +141,7 @@ class Ui_MainWindow(object):
|
||||
self.vboxlayout1.setSpacing(0)
|
||||
self.vboxlayout1.setMargin(0)
|
||||
self.vboxlayout1.setObjectName(_fromUtf8("vboxlayout1"))
|
||||
self.uiConsoleTextEdit = QtGui.QTextEdit(self.uiConsoleDockWidgetContents)
|
||||
self.uiConsoleTextEdit = ConsoleView(self.uiConsoleDockWidgetContents)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@@ -654,6 +654,7 @@ class Ui_MainWindow(object):
|
||||
self.uiLabInstructionsAction.setText(_translate("MainWindow", "Lab instructions", None))
|
||||
self.uiFitInViewAction.setText(_translate("MainWindow", "Fit in view", None))
|
||||
|
||||
from ..console_view import ConsoleView
|
||||
from ..nodes_view import NodesView
|
||||
from ..graphics_view import GraphicsView
|
||||
from . import resources_rc
|
||||
|
||||
@@ -25,5 +25,5 @@ or negative for a release candidate or beta (after the base version
|
||||
number has been incremented)
|
||||
"""
|
||||
|
||||
__version__ = "0.1.dev"
|
||||
__version_info__ = (0, 1, 0, -99)
|
||||
__version__ = "0.9.dev"
|
||||
__version_info__ = (0, 9, 0, -99)
|
||||
|
||||
Reference in New Issue
Block a user