- fixed the Tcl Command Help to work as expected; made the text of the commands to be colored in Red color and bold

- added a 'Close' menu entry in the Tcl Shell context menu that will close (hide) the Tcl Shell Dock widget
- on launching the Tcl Shell the Edit line will take focus immediately
- in App.on_mouse_move_over_plot() method no longer will be done a setFocus() on every move, only when it is needed
This commit is contained in:
Marius Stanciu 2020-04-23 02:07:55 +03:00 committed by Marius
parent a1499158c2
commit 3735753a93
7 changed files with 105 additions and 64 deletions

View File

@ -7,6 +7,13 @@ CHANGELOG for FlatCAM beta
=================================================
23.04.2020
- fixed the Tcl Command Help to work as expected; made the text of the commands to be colored in Red color and bold
- added a 'Close' menu entry in the Tcl Shell context menu that will close (hide) the Tcl Shell Dock widget
- on launching the Tcl Shell the Edit line will take focus immediately
- in App.on_mouse_move_over_plot() method no longer will be done a setFocus() on every move, only when it is needed
22.04.2020
- added a new feature, project auto-saving controlled from Edit -> Preferences -> General -> APP. Preferences -> Enable Auto Save checkbox

View File

@ -2105,7 +2105,7 @@ class App(QtCore.QObject):
self.ui.menuview_toggle_axis.triggered.connect(self.on_toggle_axis)
self.ui.menuview_toggle_workspace.triggered.connect(self.on_workspace_toggle)
self.ui.menutoolshell.triggered.connect(self.on_toggle_shell)
self.ui.menutoolshell.triggered.connect(self.toggle_shell)
self.ui.menuhelp_about.triggered.connect(self.on_about)
self.ui.menuhelp_manual.triggered.connect(lambda: webbrowser.open(self.manual_url))
@ -3326,7 +3326,7 @@ class App(QtCore.QObject):
# re-add the TCL Shell action to the Tools menu and reconnect it to ist slot function
self.ui.menutoolshell = self.ui.menutool.addAction(QtGui.QIcon(self.resource_location + '/shell16.png'),
'&Command Line\tS')
self.ui.menutoolshell.triggered.connect(self.on_toggle_shell)
self.ui.menutoolshell.triggered.connect(self.toggle_shell)
# third install all of them
try:
@ -3377,7 +3377,7 @@ class App(QtCore.QObject):
self.ui.jmp_btn.triggered.connect(self.on_jump_to)
self.ui.locate_btn.triggered.connect(lambda: self.on_locate(obj=self.collection.get_active()))
self.ui.shell_btn.triggered.connect(self.on_toggle_shell)
self.ui.shell_btn.triggered.connect(self.toggle_shell)
self.ui.new_script_btn.triggered.connect(self.on_filenewscript)
self.ui.open_script_btn.triggered.connect(self.on_fileopenscript)
self.ui.run_script_btn.triggered.connect(self.on_filerunscript)
@ -5274,34 +5274,6 @@ class App(QtCore.QObject):
with open(config_file, 'w') as f:
f.writelines(data)
def on_toggle_shell(self):
"""
Toggle shell: if is visible close it, if it is closed then open it
:return: None
"""
self.report_usage("on_toggle_shell()")
if self.ui.shell_dock.isVisible():
self.ui.shell_dock.hide()
else:
self.ui.shell_dock.show()
def on_toggle_shell_from_settings(self, state):
"""
Toggle shell: if is visible close it, if it is closed then open it
:return: None
"""
self.report_usage("on_toggle_shell_from_settings()")
if state is True:
if not self.ui.shell_dock.isVisible():
self.ui.shell_dock.show()
else:
if self.ui.shell_dock.isVisible():
self.ui.shell_dock.hide()
def on_register_files(self, obj_type=None):
"""
Called whenever there is a need to register file extensions with FlatCAM.
@ -8601,8 +8573,11 @@ class App(QtCore.QObject):
pan_button = 2
self.event_is_dragging = self.plotcanvas.is_dragging
# So it can receive key presses
# So it can receive key presses but not when the Tcl Shell is active
if not self.ui.shell_dock.isVisible():
if not self.plotcanvas.native.hasFocus():
self.plotcanvas.native.setFocus()
self.pos_jump = event_pos
self.ui.popMenu.mouse_is_panning = False
@ -12813,6 +12788,49 @@ class App(QtCore.QObject):
"""
pass
def toggle_shell(self):
"""
Toggle shell: if is visible close it, if it is closed then open it
:return: None
"""
self.report_usage("toggle_shell()")
if self.ui.shell_dock.isVisible():
self.ui.shell_dock.hide()
self.plotcanvas.native.setFocus()
else:
self.ui.shell_dock.show()
# I want to take the focus and give it to the Tcl Shell when the Tcl Shell is run
# self.shell._edit.setFocus()
QtCore.QTimer.singleShot(0, lambda: self.ui.shell_dock.widget()._edit.setFocus())
# HACK - simulate a mouse click - alternative
# no_km = QtCore.Qt.KeyboardModifier(QtCore.Qt.NoModifier) # no KB modifier
# pos = QtCore.QPoint((self.shell._edit.width() - 40), (self.shell._edit.height() - 2))
# e = QtGui.QMouseEvent(QtCore.QEvent.MouseButtonPress, pos, QtCore.Qt.LeftButton, QtCore.Qt.LeftButton,
# no_km)
# QtWidgets.qApp.sendEvent(self.shell._edit, e)
# f = QtGui.QMouseEvent(QtCore.QEvent.MouseButtonRelease, pos, QtCore.Qt.LeftButton, QtCore.Qt.LeftButton,
# no_km)
# QtWidgets.qApp.sendEvent(self.shell._edit, f)
def on_toggle_shell_from_settings(self, state):
"""
Toggle shell: if is visible close it, if it is closed then open it
:return: None
"""
self.report_usage("on_toggle_shell_from_settings()")
if state is True:
if not self.ui.shell_dock.isVisible():
self.ui.shell_dock.show()
else:
if self.ui.shell_dock.isVisible():
self.ui.shell_dock.hide()
def shell_message(self, msg, show=False, error=False, warning=False, success=False, selected=False):
"""
Shows a message on the FlatCAM Shell

View File

@ -3247,7 +3247,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
# Shell toggle
if key == QtCore.Qt.Key_S:
self.app.on_toggle_shell()
self.app.toggle_shell()
# Add a Tool from shortcut
if key == QtCore.Qt.Key_T:

View File

@ -2560,10 +2560,11 @@ class DialogBoxRadio(QtWidgets.QDialog):
class _BrowserTextEdit(QTextEdit):
def __init__(self, version):
def __init__(self, version, app=None):
QTextEdit.__init__(self)
self.menu = None
self.version = version
self.app = app
def contextMenuEvent(self, event):
self.menu = self.createStandardContextMenu(event.pos())
@ -2571,6 +2572,12 @@ class _BrowserTextEdit(QTextEdit):
clear_action.setShortcut(QKeySequence(Qt.Key_Delete)) # it's not working, the shortcut
self.menu.addAction(clear_action)
clear_action.triggered.connect(self.clear)
if self.app:
close_action = QAction("Close", self)
self.menu.addAction(close_action)
close_action.triggered.connect(lambda: self.app.ui.shell_dock.hide())
self.menu.exec_(event.globalPos())
def clear(self):

View File

@ -33,10 +33,10 @@ class TermWidget(QWidget):
User pressed Enter. Client class should decide, if command must be executed or user may continue edit it
"""
def __init__(self, version, *args):
def __init__(self, version, app, *args):
QWidget.__init__(self, *args)
self._browser = _BrowserTextEdit(version=version)
self._browser = _BrowserTextEdit(version=version, app=app)
self._browser.setStyleSheet("font: 9pt \"Courier\";")
self._browser.setReadOnly(True)
self._browser.document().setDefaultStyleSheet(
@ -92,10 +92,14 @@ class TermWidget(QWidget):
"""
Convert text to HTML for inserting it to browser
"""
assert style in ('in', 'out', 'err', 'warning', 'success', 'selected')
assert style in ('in', 'out', 'err', 'warning', 'success', 'selected', 'raw')
if style != 'raw':
text = html.escape(text)
text = text.replace('\n', '<br/>')
else:
text = text.replace('\n', '<br>')
text = text.replace('\t', '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;')
if style == 'in':
text = '<span style="font-weight: bold;">%s</span>' % text
@ -107,6 +111,8 @@ class TermWidget(QWidget):
text = '<span style="font-weight: bold; color: #15b300;">%s</span>' % text
elif style == 'selected':
text = ''
elif style == 'raw':
text = text
else:
text = '<span>%s</span>' % text # without span <br/> is ignored!!!
@ -177,23 +183,29 @@ class TermWidget(QWidget):
"""
self._append_to_browser('out', text)
def append_raw(self, text):
"""
Append text to output widget as it is
"""
self._append_to_browser('raw', text)
def append_success(self, text):
"""Appent text to output widget
"""Append text to output widget
"""
self._append_to_browser('success', text)
def append_selected(self, text):
"""Appent text to output widget
"""Append text to output widget
"""
self._append_to_browser('selected', text)
def append_warning(self, text):
"""Appent text to output widget
"""Append text to output widget
"""
self._append_to_browser('warning', text)
def append_error(self, text):
"""Appent error text to output widget. Text is drawn with red background
"""Append error text to output widget. Text is drawn with red background
"""
self._append_to_browser('err', text)
@ -235,7 +247,7 @@ class FCShell(TermWidget):
:param version: FlatCAM version string
:param args: Parameters passed to the TermWidget parent class
"""
TermWidget.__init__(self, version, *args)
TermWidget.__init__(self, version, *args, app=sysShell)
self._sysShell = sysShell
def is_command_complete(self, text):

View File

@ -22,10 +22,10 @@ if '_' not in builtins.__dict__:
class TclCommandHelp(TclCommand):
"""
Tcl shell command to get the value of a system variable
Tcl shell command to show Help
example:
get_sys excellon_zeros
help add_circle
"""
# List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon)
@ -58,21 +58,21 @@ class TclCommandHelp(TclCommand):
def execute(self, args, unnamed_args):
"""
:param args:
:param args: Without any argument will display the list of commands. Can have as a argument
a tcl command name to display the help for that command.
:param unnamed_args:
:return:
"""
print(self.app.tcl_commands_storage)
if 'name' in args:
name = args['name']
if name not in self.app.tcl_commands_storage:
return "Unknown command: %s" % name
print(self.app.tcl_commands_storage[name]["help"])
self.app.shell.append_output(self.app.tcl_commands_storage[name]["help"])
else:
if args is None:
cmd_enum = _("Available commands:\n")
if not args:
cmd_enum = '%s\n' % _("Available commands:")
displayed_text = []
try:
@ -85,14 +85,12 @@ class TclCommandHelp(TclCommand):
max_tabs = math.ceil(max_len / 8)
for cmd_name in sorted(self.app.tcl_commands_storage):
cmd_description = self.app.tcl_commands_storage[cmd_name]['description']
cmd_description = "<span>%s</span>" % self.app.tcl_commands_storage[cmd_name]['description']
curr_len = len(cmd_name)
tabs = '\t'
cmd_name_colored = "<span style=\" color:#ff0000;\" >"
cmd_name_colored += str(cmd_name)
cmd_name_colored += "</span>"
cmd_name_colored = "<span style=\" font-weight: bold; color: red;\" >%s</span>" % str(cmd_name)
# make sure to add the right number of tabs (1 tab = 8 spaces) so all the commands
# descriptions are aligned
@ -102,7 +100,7 @@ class TclCommandHelp(TclCommand):
nr_tabs = 0
for x in range(max_tabs):
if curr_len <= (x * 8):
if curr_len < (x * 8):
nr_tabs += 1
# nr_tabs = 2 if curr_len <= 8 else 1
@ -111,9 +109,9 @@ class TclCommandHelp(TclCommand):
displayed_text.append(cmd_line_txt)
except Exception as err:
self.app.log.debug("App.setup_shell.shelp() when run as 'help' --> %s" % str(err))
displayed_text = [' %s' % cmd for cmd in sorted(self.app.tcl_commands_storage)]
displayed_text = ['> %s\n' % cmd for cmd in sorted(self.app.tcl_commands_storage)]
cmd_enum += '\n'.join(displayed_text)
cmd_enum += '\n\n%s\n%s' % (_("Type help <command_name> for usage."), _("Example: help open_gerber"))
cmd_enum += '<br>'.join(displayed_text)
cmd_enum += '<br><br>%s<br>%s' % (_("Type help <command_name> for usage."), _("Example: help open_gerber"))
print(cmd_enum)
self.app.shell.append_raw(cmd_enum)

View File

@ -1,7 +1,6 @@
import pkgutil
import sys
# Todo: I think these imports are not needed.
# allowed command modules (please append them alphabetically ordered)
import tclCommands.TclCommandAddCircle
import tclCommands.TclCommandAddPolygon
@ -27,6 +26,7 @@ import tclCommands.TclCommandGeoCutout
import tclCommands.TclCommandGeoUnion
import tclCommands.TclCommandGetNames
import tclCommands.TclCommandGetSys
import tclCommands.TclCommandHelp
import tclCommands.TclCommandImportSvg
import tclCommands.TclCommandInteriors
import tclCommands.TclCommandIsolate
@ -93,7 +93,6 @@ def register_all_commands(app, commands):
tcl_modules = {k: v for k, v in list(sys.modules.items()) if k.startswith('tclCommands.TclCommand')}
for key, mod in list(tcl_modules.items()):
print(key)
if key != 'tclCommands.TclCommand':
class_name = key.split('.')[1]
class_type = getattr(mod, class_name)