cadquery-freecad-module/CadQuery/Libs/pyqode/core/panels/encodings.py

223 lines
7.8 KiB
Python

"""
Contains a panel to manage unicode decoding/encoding errors.
"""
from pyqode.core.api.panel import Panel
from pyqode.core.api.decoration import TextDecoration
from pyqode.qt import QtCore, QtGui, QtWidgets
class EncodingPanel(Panel):
""" Displays a warning when an encoding error occured and let you reload.
This panel display a warning in case encoding/decoding error and
give the user the possibility to try out another encoding, to edit any way
or to close the editor.
The panel is automatically shown by
:class:`pyqode.core.managers.FileManager` in case of error so that you
don't have to worry about encoding issues. The only think you might do
is to provide to your user a way to specify the default encoding, i.e. the
one that is tried before showing this panel.
The panel is a simple widget with a label describing the error, an encoding
menu and 3 buttons: ``Retry``, ``Edit`` anyway and ``Cancel``. It is
strongly inspired by the GEdit encoding panel.
You can change the background color and the label foreground color by
setting up the ``color`` and ``foreground`` properties.
It's up to the client code to handle cancel requests. To do that simply
connect ``cancel_requested`` signal to remove the editor from your
application.
"""
#: Signal emitted when the user pressed on cancel. It is up to the client
#: code to handle this event.
cancel_requested = QtCore.Signal(object)
_description = ('<html><head/><body><p><span style=" font-weight:600;">%s'
'</span></p><p><span style=" font-size:9pt;">'
'The file you opened has some invalid characters. '
'If you continue editing this file you could corrupt this '
'document. You can also choose another character encoding '
'and try again.</span></p></body></html>')
@property
def color(self):
"""
Returns the panel color.
"""
return self._color
@color.setter
def color(self, value):
self._color = value
self._refresh_stylesheet()
if self.editor:
# propagate changes to every clone
for clone in self.editor.clones:
try:
clone.modes.get(self.__class__).color = value
except KeyError:
# this should never happen since we're working with clones
pass
@property
def foreground(self):
return self._foreground
@foreground.setter
def foreground(self, value):
self._foreground = value
self._refresh_stylesheet()
# propagate changes to every clone
if self.editor:
for clone in self.editor.clones:
try:
clone.modes.get(self.__class__).foreground = value
except KeyError:
# this should never happen since we're working with clones
pass
def _refresh_stylesheet(self):
try:
self._lbl_stylesheet = ('color: %s;background: %s' %
(self._foreground.name(),
self._color.name()))
for lbl in self._labels:
lbl.setStyleSheet(self._lbl_stylesheet)
except AttributeError:
pass
def __init__(self, add_context_menu=True):
super(EncodingPanel, self).__init__()
# leave it here otherwise you will have circular import errors
from pyqode.core._forms.pnl_encoding_ui import Ui_Form
self.ui = Ui_Form()
self.ui.setupUi(self)
self.__add_ctx_mnu = add_context_menu
self._labels = [self.ui.label, self.ui.lblDescription]
self._color = None
self.color = QtGui.QColor('#8AADD4')
self._foreground = None
self.foreground = QtGui.QColor('#FFFFFF')
self._deco = None
self.ui.pushButtonRetry.clicked.connect(self._reload)
self.ui.pushButtonEdit.clicked.connect(self._edit_anyway)
self.ui.pushButtonCancel.clicked.connect(self.cancel)
self.hide()
def enable_caret_line(self, value=True):
try:
from pyqode.core.modes import CaretLineHighlighterMode
mode = self.editor.modes.get(CaretLineHighlighterMode)
except KeyError:
pass
else:
mode.enabled = value
def on_open_failed(self, path, encoding):
self.enable_caret_line(False)
self.ui.comboBoxEncodings.current_encoding = encoding
self.ui.lblDescription.setText(
self._description % ('There was a problem opening the file %r' %
path))
# load text as binary and mark it as red, user might make use the
# binary to recognize the original encoding
with open(path, 'rb') as file:
content = str(file.read(16))
# set plain text
self.editor.setPlainText(
content, self.editor.file.get_mimetype(path),
self.editor.file.encoding)
self.editor.setDocumentTitle(self.editor.file.name)
self.editor.setWindowTitle(self.editor.file.name)
# Delay because the editor might not have been shown yet
QtCore.QTimer.singleShot(1, self.show)
def show(self):
super(EncodingPanel, self).show()
self.editor.selectAll()
self._deco = TextDecoration(self.editor.textCursor())
self._deco.set_background(QtCore.Qt.red)
self._deco.set_foreground(QtCore.Qt.black)
self.editor.decorations.append(self._deco)
cursor = self.editor.textCursor()
cursor.clearSelection()
cursor.setPosition(0)
self.editor.setTextCursor(cursor)
self.editor.setReadOnly(True)
def paintEvent(self, event):
""" Fills the panel background. """
super(EncodingPanel, self).paintEvent(event)
if self.isVisible():
# fill background
painter = QtGui.QPainter(self)
self._background_brush = QtGui.QBrush(self._color)
painter.fillRect(event.rect(), self._background_brush)
def on_install(self, editor):
super(EncodingPanel, self).on_install(editor)
if self.__add_ctx_mnu:
# add context menu
from pyqode.core.widgets import EncodingsContextMenu
EncodingsContextMenu(parent=editor)
def _reload(self):
self.hide()
self._rm_deco()
self.editor.setReadOnly(False)
self.enable_caret_line(True)
self.editor.file.reload(self.ui.comboBoxEncodings.current_encoding)
def _edit_anyway(self):
self._rm_deco()
self.editor.setReadOnly(False)
self.enable_caret_line(True)
self.hide()
def _rm_deco(self):
if self._deco:
self.editor.decorations.remove(self._deco)
self._deco = None
def cancel(self):
if self.sender():
self.editor.clear()
self._rm_deco()
self.enable_caret_line(True)
self.cancel_requested.emit(self.editor)
self.hide()
def clone_settings(self, original):
self.color = original.color
self.foreground = original.foreground
if __name__ == '__main__':
import locale
import sys
from pyqode.core.api import CodeEdit
def simulate_open():
pnl.on_open_failed(__file__, locale.getpreferredencoding())
def simulate_save():
pnl.on_save_failed(__file__, locale.getpreferredencoding())
app = QtWidgets.QApplication(sys.argv)
# app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
edit = CodeEdit()
edit.setMinimumSize(800, 600)
edit.file.open(__file__)
pnl = EncodingPanel()
edit.panels.append(pnl, pnl.Position.TOP)
edit.show()
simulate_open()
QtCore.QTimer.singleShot(5000, simulate_save)
app.exec_()