- moved some graphical classes out of Tool Shell to GUIElements.py where they belong

- when selecting an object on canvas by single click, it's name is displayed in status bar. When nothing is selected a blank message (nothing) it's displayed
- in Move Tool I've added the type of object that was moved in the status bar message
- color coded the status bar bullet to blue for selection
- the name of the selected objects are displayed in the status bar color coded: green for Gerber objects, Brown for Excellon, Red for Geometry and Blue for CNCJobs.
This commit is contained in:
Marius Stanciu
2019-02-07 22:37:51 +02:00
committed by Marius S
parent c888303146
commit 5b75d416ec
7 changed files with 245 additions and 166 deletions

View File

@@ -1700,7 +1700,7 @@ class App(QtCore.QObject):
""" """
pass pass
def shell_message(self, msg, show=False, error=False, warning=False, success=False): def shell_message(self, msg, show=False, error=False, warning=False, success=False, selected=False):
""" """
Shows a message on the FlatCAM Shell Shows a message on the FlatCAM Shell
@@ -1720,8 +1720,10 @@ class App(QtCore.QObject):
else: else:
if success: if success:
self.shell.append_success(msg + "\n") self.shell.append_success(msg + "\n")
else: if success:
self.shell.append_output(msg + "\n") self.shell.append_selected(msg + "\n")
else:
self.shell.append_output(msg + "\n")
except AttributeError: except AttributeError:
log.debug("shell_message() is called before Shell Class is instantiated. The message is: %s", str(msg)) log.debug("shell_message() is called before Shell Class is instantiated. The message is: %s", str(msg))
@@ -1894,13 +1896,19 @@ class App(QtCore.QObject):
elif level.lower() == "error_notcl": elif level.lower() == "error_notcl":
self.shell_message(msg, error=True, show=False) self.shell_message(msg, error=True, show=False)
elif level.lower() == "warning_notcl": elif level.lower() == "warning_notcl":
self.shell_message(msg, warning=True, show=False) self.shell_message(msg, warning=True, show=False)
elif level.lower() == "success": elif level.lower() == "success":
self.shell_message(msg, success=True, show=False) self.shell_message(msg, success=True, show=False)
elif level.lower() == "selected":
self.shell_message(msg, selected=True, show=False)
else: else:
self.shell_message(msg, show=False) self.shell_message(msg, show=False)
else: else:
self.ui.fcinfo.set_status(str(msg), level="info") self.ui.fcinfo.set_status(str(msg), level="info")
@@ -4440,6 +4448,9 @@ class App(QtCore.QObject):
# and as a convenience move the focus to the Project tab because Selected tab is now empty # and as a convenience move the focus to the Project tab because Selected tab is now empty
self.ui.notebook.setCurrentWidget(self.ui.project_tab) self.ui.notebook.setCurrentWidget(self.ui.project_tab)
# delete any text in the status bar, implicitly the last object name that was selected
self.inform.emit("")
else: else:
# case when there is only an object under the click and we toggle it # case when there is only an object under the click and we toggle it
if len(objects_under_the_click_list) == 1: if len(objects_under_the_click_list) == 1:
@@ -4448,6 +4459,20 @@ class App(QtCore.QObject):
# create the selection box around the selected object # create the selection box around the selected object
curr_sel_obj = self.collection.get_active() curr_sel_obj = self.collection.get_active()
self.draw_selection_shape(curr_sel_obj) self.draw_selection_shape(curr_sel_obj)
if curr_sel_obj.kind == 'gerber':
self.inform.emit('[selected]<span style="color:%s;">%s</span> selected' %
('green', str(curr_sel_obj.options['name'])))
elif curr_sel_obj.kind == 'excellon':
self.inform.emit('[selected]<span style="color:%s;">%s</span> selected' %
('brown', str(curr_sel_obj.options['name'])))
elif curr_sel_obj.kind == 'cncjob':
self.inform.emit('[selected]<span style="color:%s;">%s</span> selected' %
('blue', str(curr_sel_obj.options['name'])))
elif curr_sel_obj.kind == 'geometry':
self.inform.emit('[selected]<span style="color:%s;">%s</span> selected' %
('red', str(curr_sel_obj.options['name'])))
elif self.collection.get_active().options['name'] not in objects_under_the_click_list: elif self.collection.get_active().options['name'] not in objects_under_the_click_list:
self.collection.set_all_inactive() self.collection.set_all_inactive()
self.delete_selection_shape() self.delete_selection_shape()
@@ -4455,9 +4480,25 @@ class App(QtCore.QObject):
# create the selection box around the selected object # create the selection box around the selected object
curr_sel_obj = self.collection.get_active() curr_sel_obj = self.collection.get_active()
self.draw_selection_shape(curr_sel_obj) self.draw_selection_shape(curr_sel_obj)
if curr_sel_obj.kind == 'gerber':
self.inform.emit('[selected]<span style="color:%s;">%s</span> selected' %
('green', str(curr_sel_obj.options['name'])))
elif curr_sel_obj.kind == 'excellon':
self.inform.emit('[selected]<span style="color:%s;">%s</span> selected' %
('brown', str(curr_sel_obj.options['name'])))
elif curr_sel_obj.kind == 'cncjob':
self.inform.emit('[selected]<span style="color:%s;">%s</span> selected' %
('blue', str(curr_sel_obj.options['name'])))
elif curr_sel_obj.kind == 'geometry':
self.inform.emit('[selected]<span style="color:%s;">%s</span> selected' %
('red', str(curr_sel_obj.options['name'])))
else: else:
self.collection.set_all_inactive() self.collection.set_all_inactive()
self.delete_selection_shape() self.delete_selection_shape()
self.inform.emit("")
else: else:
# If there is no selected object # If there is no selected object
# make active the first element of the overlapped objects list # make active the first element of the overlapped objects list
@@ -4482,6 +4523,19 @@ class App(QtCore.QObject):
# create the selection box around the selected object # create the selection box around the selected object
self.draw_selection_shape(curr_sel_obj) self.draw_selection_shape(curr_sel_obj)
if curr_sel_obj.kind == 'gerber':
self.inform.emit('[selected]<span style="color:%s;">%s</span> selected' %
('green', str(curr_sel_obj.options['name'])))
elif curr_sel_obj.kind == 'excellon':
self.inform.emit('[selected]<span style="color:%s;">%s</span> selected' %
('brown', str(curr_sel_obj.options['name'])))
elif curr_sel_obj.kind == 'cncjob':
self.inform.emit('[selected]<span style="color:%s;">%s</span> selected' %
('blue', str(curr_sel_obj.options['name'])))
elif curr_sel_obj.kind == 'geometry':
self.inform.emit('[selected]<span style="color:%s;">%s</span> selected' %
('red', str(curr_sel_obj.options['name'])))
# for obj in self.collection.get_list(): # for obj in self.collection.get_list():
# obj.plot() # obj.plot()
# curr_sel_obj.plot(color=self.FC_dark_blue, face_color=self.FC_light_blue) # curr_sel_obj.plot(color=self.FC_dark_blue, face_color=self.FC_light_blue)

View File

@@ -4016,9 +4016,11 @@ class FlatCAMInfoBar(QtWidgets.QWidget):
layout.addStretch() layout.addStretch()
def set_text_(self, text): def set_text_(self, text, color=None):
self.text.setText(text) self.text.setText(text)
self.text.setToolTip(text) self.text.setToolTip(text)
if color:
self.text.setStyleSheet('color: %s' % str(color))
def set_status(self, text, level="info"): def set_status(self, text, level="info"):
level = str(level) level = str(level)
@@ -4029,9 +4031,11 @@ class FlatCAMInfoBar(QtWidgets.QWidget):
self.pmap = QtGui.QPixmap('share/greenlight12.png') self.pmap = QtGui.QPixmap('share/greenlight12.png')
elif level == "WARNING" or level == "WARNING_NOTCL": elif level == "WARNING" or level == "WARNING_NOTCL":
self.pmap = QtGui.QPixmap('share/yellowlight12.png') self.pmap = QtGui.QPixmap('share/yellowlight12.png')
elif level == "selected" or level == "SELECTED":
self.pmap = QtGui.QPixmap('share/bluelight12.png')
else: else:
self.pmap = QtGui.QPixmap('share/graylight12.png') self.pmap = QtGui.QPixmap('share/graylight12.png')
self.icon.setPixmap(self.pmap)
self.set_text_(text) self.set_text_(text)
self.icon.setPixmap(self.pmap)
# end of file # end of file

View File

@@ -1,14 +1,18 @@
from PyQt5 import QtGui, QtCore, QtWidgets from PyQt5 import QtGui, QtCore, QtWidgets
from PyQt5.QtCore import pyqtSignal, pyqtSlot from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QTextEdit, QCompleter, QAction
from PyQt5.QtGui import QColor, QKeySequence, QPalette, QTextCursor
from copy import copy from copy import copy
import re import re
import logging import logging
import html
log = logging.getLogger('base') log = logging.getLogger('base')
EDIT_SIZE_HINT = 70 EDIT_SIZE_HINT = 70
class RadioSet(QtWidgets.QWidget): class RadioSet(QtWidgets.QWidget):
activated_custom = QtCore.pyqtSignal() activated_custom = QtCore.pyqtSignal()
@@ -1218,3 +1222,158 @@ class Dialog_box(QtWidgets.QWidget):
self.location, self.ok = dialog_box.getText(self, title, label) self.location, self.ok = dialog_box.getText(self, title, label)
class _BrowserTextEdit(QTextEdit):
def __init__(self, version):
QTextEdit.__init__(self)
self.menu = None
self.version = version
def contextMenuEvent(self, event):
self.menu = self.createStandardContextMenu(event.pos())
clear_action = QAction("Clear", self)
clear_action.setShortcut(QKeySequence(Qt.Key_Delete)) # it's not working, the shortcut
self.menu.addAction(clear_action)
clear_action.triggered.connect(self.clear)
self.menu.exec_(event.globalPos())
def clear(self):
QTextEdit.clear(self)
text = "FlatCAM %s (c)2014-2019 Juan Pablo Caram (Type help to get started)\n\n" % self.version
text = html.escape(text)
text = text.replace('\n', '<br/>')
self.moveCursor(QTextCursor.End)
self.insertHtml(text)
class _ExpandableTextEdit(QTextEdit):
"""
Class implements edit line, which expands themselves automatically
"""
historyNext = pyqtSignal()
historyPrev = pyqtSignal()
def __init__(self, termwidget, *args):
QTextEdit.__init__(self, *args)
self.setStyleSheet("font: 9pt \"Courier\";")
self._fittedHeight = 1
self.textChanged.connect(self._fit_to_document)
self._fit_to_document()
self._termWidget = termwidget
self.completer = MyCompleter()
self.model = QtCore.QStringListModel()
self.completer.setModel(self.model)
self.set_model_data(keyword_list=[])
self.completer.insertText.connect(self.insertCompletion)
def set_model_data(self, keyword_list):
self.model.setStringList(keyword_list)
def insertCompletion(self, completion):
tc = self.textCursor()
extra = (len(completion) - len(self.completer.completionPrefix()))
tc.movePosition(QTextCursor.Left)
tc.movePosition(QTextCursor.EndOfWord)
tc.insertText(completion[-extra:])
self.setTextCursor(tc)
self.completer.popup().hide()
def focusInEvent(self, event):
if self.completer:
self.completer.setWidget(self)
QTextEdit.focusInEvent(self, event)
def keyPressEvent(self, event):
"""
Catch keyboard events. Process Enter, Up, Down
"""
if event.matches(QKeySequence.InsertParagraphSeparator):
text = self.toPlainText()
if self._termWidget.is_command_complete(text):
self._termWidget.exec_current_command()
return
elif event.matches(QKeySequence.MoveToNextLine):
text = self.toPlainText()
cursor_pos = self.textCursor().position()
textBeforeEnd = text[cursor_pos:]
if len(textBeforeEnd.split('\n')) <= 1:
self.historyNext.emit()
return
elif event.matches(QKeySequence.MoveToPreviousLine):
text = self.toPlainText()
cursor_pos = self.textCursor().position()
text_before_start = text[:cursor_pos]
# lineCount = len(textBeforeStart.splitlines())
line_count = len(text_before_start.split('\n'))
if len(text_before_start) > 0 and \
(text_before_start[-1] == '\n' or text_before_start[-1] == '\r'):
line_count += 1
if line_count <= 1:
self.historyPrev.emit()
return
elif event.matches(QKeySequence.MoveToNextPage) or \
event.matches(QKeySequence.MoveToPreviousPage):
return self._termWidget.browser().keyPressEvent(event)
tc = self.textCursor()
if event.key() == Qt.Key_Tab and self.completer.popup().isVisible():
self.completer.insertText.emit(self.completer.getSelected())
self.completer.setCompletionMode(QCompleter.PopupCompletion)
return
QTextEdit.keyPressEvent(self, event)
tc.select(QTextCursor.WordUnderCursor)
cr = self.cursorRect()
if len(tc.selectedText()) > 0:
self.completer.setCompletionPrefix(tc.selectedText())
popup = self.completer.popup()
popup.setCurrentIndex(self.completer.completionModel().index(0, 0))
cr.setWidth(self.completer.popup().sizeHintForColumn(0)
+ self.completer.popup().verticalScrollBar().sizeHint().width())
self.completer.complete(cr)
else:
self.completer.popup().hide()
def sizeHint(self):
"""
QWidget sizeHint impelemtation
"""
hint = QTextEdit.sizeHint(self)
hint.setHeight(self._fittedHeight)
return hint
def _fit_to_document(self):
"""
Update widget height to fit all text
"""
documentsize = self.document().size().toSize()
self._fittedHeight = documentsize.height() + (self.height() - self.viewport().height())
self.setMaximumHeight(self._fittedHeight)
self.updateGeometry()
def insertFromMimeData(self, mime_data):
# Paste only plain text.
self.insertPlainText(mime_data.text())
class MyCompleter(QCompleter):
insertText = pyqtSignal(str)
def __init__(self, parent=None):
QCompleter.__init__(self)
self.setCompletionMode(QCompleter.PopupCompletion)
self.highlighted.connect(self.setHighlighted)
def setHighlighted(self, text):
self.lastSelected = text
def getSelected(self):
return self.lastSelected

View File

@@ -19,6 +19,12 @@ CAD program, and create G-Code for Isolation routing.
- added some new icons in the help menu and reorganized this menu - added some new icons in the help menu and reorganized this menu
- added a new function and the shortcut 'leftquote' (left of Key 1) for toggle of the notebook section - added a new function and the shortcut 'leftquote' (left of Key 1) for toggle of the notebook section
- changed the Shortcut list shortcut key to F3 - changed the Shortcut list shortcut key to F3
- moved some graphical classes out of Tool Shell to GUIElements.py where they belong
- when selecting an object on canvas by single click, it's name is displayed in status bar. When nothing is selected a blank message (nothing) it's displayed
- in Move Tool I've added the type of object that was moved in the status bar message
- color coded the status bar bullet to blue for selection
- the name of the selected objects are displayed in the status bar color coded: green for Gerber objects, Brown for Excellon, Red for Geometry and Blue for CNCJobs.
6.02.2019 6.02.2019

View File

@@ -139,12 +139,13 @@ class ToolMove(FlatCAMTool):
proc.done() proc.done()
# delete the selection bounding box # delete the selection bounding box
self.delete_shape() self.delete_shape()
self.app.inform.emit('[success]%s object was moved ...' %
str(sel_obj.kind).capitalize())
self.app.worker_task.emit({'fcn': job_move, 'params': [self]}) self.app.worker_task.emit({'fcn': job_move, 'params': [self]})
self.clicked_move = 0 self.clicked_move = 0
self.toggle() self.toggle()
self.app.inform.emit("[success]Object was moved ...")
return return
except TypeError: except TypeError:

View File

@@ -6,165 +6,12 @@
# MIT Licence # # MIT Licence #
############################################################ ############################################################
# from PyQt5.QtCore import pyqtSignal
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QTextCursor
from PyQt5.QtWidgets import QVBoxLayout, QWidget
from GUIElements import _BrowserTextEdit, _ExpandableTextEdit
import html import html
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtCore import Qt, QStringListModel
from PyQt5.QtGui import QColor, QKeySequence, QPalette, QTextCursor
from PyQt5.QtWidgets import QLineEdit, QSizePolicy, QTextEdit, QVBoxLayout, QWidget, QCompleter, QAction
class _BrowserTextEdit(QTextEdit):
def __init__(self, version):
QTextEdit.__init__(self)
self.menu = None
self.version = version
def contextMenuEvent(self, event):
self.menu = self.createStandardContextMenu(event.pos())
clear_action = QAction("Clear", self)
clear_action.setShortcut(QKeySequence(Qt.Key_Delete)) # it's not working, the shortcut
self.menu.addAction(clear_action)
clear_action.triggered.connect(self.clear)
self.menu.exec_(event.globalPos())
def clear(self):
QTextEdit.clear(self)
text = "FlatCAM %s (c)2014-2019 Juan Pablo Caram (Type help to get started)\n\n" % self.version
text = html.escape(text)
text = text.replace('\n', '<br/>')
self.moveCursor(QTextCursor.End)
self.insertHtml(text)
class _ExpandableTextEdit(QTextEdit):
"""
Class implements edit line, which expands themselves automatically
"""
historyNext = pyqtSignal()
historyPrev = pyqtSignal()
def __init__(self, termwidget, *args):
QTextEdit.__init__(self, *args)
self.setStyleSheet("font: 9pt \"Courier\";")
self._fittedHeight = 1
self.textChanged.connect(self._fit_to_document)
self._fit_to_document()
self._termWidget = termwidget
self.completer = MyCompleter()
self.model = QStringListModel()
self.completer.setModel(self.model)
self.set_model_data(keyword_list=[])
self.completer.insertText.connect(self.insertCompletion)
def set_model_data(self, keyword_list):
self.model.setStringList(keyword_list)
def insertCompletion(self, completion):
tc = self.textCursor()
extra = (len(completion) - len(self.completer.completionPrefix()))
tc.movePosition(QTextCursor.Left)
tc.movePosition(QTextCursor.EndOfWord)
tc.insertText(completion[-extra:])
self.setTextCursor(tc)
self.completer.popup().hide()
def focusInEvent(self, event):
if self.completer:
self.completer.setWidget(self)
QTextEdit.focusInEvent(self, event)
def keyPressEvent(self, event):
"""
Catch keyboard events. Process Enter, Up, Down
"""
if event.matches(QKeySequence.InsertParagraphSeparator):
text = self.toPlainText()
if self._termWidget.is_command_complete(text):
self._termWidget.exec_current_command()
return
elif event.matches(QKeySequence.MoveToNextLine):
text = self.toPlainText()
cursor_pos = self.textCursor().position()
textBeforeEnd = text[cursor_pos:]
if len(textBeforeEnd.split('\n')) <= 1:
self.historyNext.emit()
return
elif event.matches(QKeySequence.MoveToPreviousLine):
text = self.toPlainText()
cursor_pos = self.textCursor().position()
text_before_start = text[:cursor_pos]
# lineCount = len(textBeforeStart.splitlines())
line_count = len(text_before_start.split('\n'))
if len(text_before_start) > 0 and \
(text_before_start[-1] == '\n' or text_before_start[-1] == '\r'):
line_count += 1
if line_count <= 1:
self.historyPrev.emit()
return
elif event.matches(QKeySequence.MoveToNextPage) or \
event.matches(QKeySequence.MoveToPreviousPage):
return self._termWidget.browser().keyPressEvent(event)
tc = self.textCursor()
if event.key() == Qt.Key_Tab and self.completer.popup().isVisible():
self.completer.insertText.emit(self.completer.getSelected())
self.completer.setCompletionMode(QCompleter.PopupCompletion)
return
QTextEdit.keyPressEvent(self, event)
tc.select(QTextCursor.WordUnderCursor)
cr = self.cursorRect()
if len(tc.selectedText()) > 0:
self.completer.setCompletionPrefix(tc.selectedText())
popup = self.completer.popup()
popup.setCurrentIndex(self.completer.completionModel().index(0, 0))
cr.setWidth(self.completer.popup().sizeHintForColumn(0)
+ self.completer.popup().verticalScrollBar().sizeHint().width())
self.completer.complete(cr)
else:
self.completer.popup().hide()
def sizeHint(self):
"""
QWidget sizeHint impelemtation
"""
hint = QTextEdit.sizeHint(self)
hint.setHeight(self._fittedHeight)
return hint
def _fit_to_document(self):
"""
Update widget height to fit all text
"""
documentsize = self.document().size().toSize()
self._fittedHeight = documentsize.height() + (self.height() - self.viewport().height())
self.setMaximumHeight(self._fittedHeight)
self.updateGeometry()
def insertFromMimeData(self, mime_data):
# Paste only plain text.
self.insertPlainText(mime_data.text())
class MyCompleter(QCompleter):
insertText = pyqtSignal(str)
def __init__(self, parent=None):
QCompleter.__init__(self)
self.setCompletionMode(QCompleter.PopupCompletion)
self.highlighted.connect(self.setHighlighted)
def setHighlighted(self, text):
self.lastSelected = text
def getSelected(self):
return self.lastSelected
class TermWidget(QWidget): class TermWidget(QWidget):
@@ -234,7 +81,7 @@ class TermWidget(QWidget):
""" """
Convert text to HTML for inserting it to browser Convert text to HTML for inserting it to browser
""" """
assert style in ('in', 'out', 'err', 'warning', 'success') assert style in ('in', 'out', 'err', 'warning', 'success', 'selected')
text = html.escape(text) text = html.escape(text)
text = text.replace('\n', '<br/>') text = text.replace('\n', '<br/>')
@@ -247,6 +94,8 @@ class TermWidget(QWidget):
text = '<span style="font-weight: bold; color: rgb(244, 182, 66);">%s</span>' % text text = '<span style="font-weight: bold; color: rgb(244, 182, 66);">%s</span>' % text
elif style == 'success': elif style == 'success':
text = '<span style="font-weight: bold; color: rgb(8, 68, 0);">%s</span>' % text text = '<span style="font-weight: bold; color: rgb(8, 68, 0);">%s</span>' % text
elif style == 'selected':
text = '<span style="font-weight: bold; color: rgb(0, 8, 255);">%s</span>' % text
else: else:
text = '<span>%s</span>' % text # without span <br/> is ignored!!! text = '<span>%s</span>' % text # without span <br/> is ignored!!!
@@ -313,6 +162,11 @@ class TermWidget(QWidget):
""" """
self._append_to_browser('success', text) self._append_to_browser('success', text)
def append_selected(self, text):
"""Appent text to output widget
"""
self._append_to_browser('selected', text)
def append_warning(self, text): def append_warning(self, text):
"""Appent text to output widget """Appent text to output widget
""" """
@@ -352,6 +206,7 @@ class TermWidget(QWidget):
self._edit.setPlainText(self._history[self._historyIndex]) self._edit.setPlainText(self._history[self._historyIndex])
self._edit.moveCursor(QTextCursor.End) self._edit.moveCursor(QTextCursor.End)
class FCShell(TermWidget): class FCShell(TermWidget):
def __init__(self, sysShell, version, *args): def __init__(self, sysShell, version, *args):
TermWidget.__init__(self, version, *args) TermWidget.__init__(self, version, *args)

BIN
share/bluelight12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B