cadquery-freecad-module/CadQuery/Libs/pyqode/core/widgets/encodings.py
2015-10-26 16:25:38 -04:00

199 lines
7.1 KiB
Python

"""
This module contains the encodings related widgets (combox, menus,...)
"""
import locale
import logging
from pyqode.core.api import ENCODINGS_MAP, convert_to_codec_key
from pyqode.qt import QtCore, QtWidgets
from pyqode.core.cache import Cache
def _logger():
return logging.getLogger(__name__)
class EncodingsComboBox(QtWidgets.QComboBox):
"""
This combo box display the list of user preferred encoding.
The last item let you choose an additional encoding from the list
of encodings define in :mod:`pyqode.core.api.encodings` using
the EncodingsEditorDialog.
You can also set the current encoding, it will be automatically appended
if not in the user list or set as the current index.
"""
@property
def current_encoding(self):
"""
Gets/Sets the current encoding
"""
return self._current_encoding
@current_encoding.setter
def current_encoding(self, value):
self._current_encoding = convert_to_codec_key(value)
self._refresh_items()
def __init__(self, parent, default_encoding=locale.getpreferredencoding()):
super(EncodingsComboBox, self).__init__(parent)
self._current_encoding = default_encoding
self._lock = False
self._refresh_items()
self.currentIndexChanged.connect(self._on_current_changed)
def _on_current_changed(self, index):
if self._lock:
return
if index == self.count() - 1:
from pyqode.core.dialogs import DlgPreferredEncodingsEditor
if DlgPreferredEncodingsEditor.edit_encoding(self):
self._refresh_items()
else:
self._current_encoding = self.itemData(index, QtCore.Qt.UserRole)
def _refresh_items(self):
self._lock = True
self.clear()
for i, encoding in enumerate(sorted(Cache().preferred_encodings)):
encoding = convert_to_codec_key(encoding)
try:
alias, lang = ENCODINGS_MAP[encoding]
except KeyError:
_logger().warning('KeyError with encoding: %s', encoding)
else:
self.addItem('%s (%s)' % (alias, lang))
self.setItemData(i, encoding, QtCore.Qt.UserRole)
if encoding == self._current_encoding or \
convert_to_codec_key(alias) == self._current_encoding:
self.setCurrentIndex(i)
self.insertSeparator(self.count())
self.addItem('Add or remove')
self._lock = False
class EncodingsMenu(QtWidgets.QMenu):
"""
Implements a menu that show the user preferred encoding and emit
reload_requested when the user changed the selected encoding.
This menu is a general purpose menu that you can put anywhere in your
application but you will have to manage the reload operation yourself.
For an integrated context menu, prefer using
:class:`pyqode.core.widgets.EncodingsContextMenu`.
"""
#: Signal emitted when the user triggered an action.
reload_requested = QtCore.Signal(str)
@property
def current_encoding(self):
"""
Gets/Sets the current encoding
"""
return self._current_encoding
@current_encoding.setter
def current_encoding(self, value):
self._current_encoding = convert_to_codec_key(value)
self._refresh()
def __init__(self, title='Encodings', parent=None,
selected_encoding=locale.getpreferredencoding()):
super(EncodingsMenu, self).__init__(parent)
self.setTitle(title)
self._group = QtWidgets.QActionGroup(self)
self._edit_action = None
self._current_encoding = ''
self.current_encoding = selected_encoding
def _clear_actions(self):
for action in self._group.actions():
self._group.removeAction(action)
self.removeAction(action)
self.removeAction(self._edit_action)
def _refresh(self):
self._clear_actions()
for i, encoding in enumerate(sorted(Cache().preferred_encodings)):
encoding = convert_to_codec_key(encoding)
try:
alias, lang = ENCODINGS_MAP[encoding]
except KeyError:
_logger().debug('KeyError with encoding:', encoding)
else:
action = QtWidgets.QAction('%s (%s)' % (alias, lang), self)
action.setData(encoding)
action.setCheckable(True)
if encoding == self._current_encoding or \
convert_to_codec_key(alias) == self._current_encoding:
action.setChecked(True)
self.addAction(action)
self._group.addAction(action)
self._group.triggered.connect(self._on_encoding_triggered)
self.addSeparator()
self._edit_action = QtWidgets.QAction('Add or remove', self)
self._edit_action.triggered.connect(self._on_edit_requested)
self.addAction(self._edit_action)
def _on_edit_requested(self):
from pyqode.core.dialogs import DlgPreferredEncodingsEditor
if DlgPreferredEncodingsEditor.edit_encoding(self):
self._refresh()
@QtCore.Slot(QtWidgets.QAction)
def _on_encoding_triggered(self, action):
self.reload_requested.emit(action.data())
class EncodingsContextMenu(EncodingsMenu):
"""
Extends the encoding menu to be tightly coupled with a CodeEdit instance
for an easier integration (automatically reload the editor file content
when the encoding changed).
The parent widget of the menu must be set to a CodeEdit instance.
"""
def __init__(self, title='Encodings', parent=None,
selected_encoding=locale.getpreferredencoding()):
from pyqode.core.api import CodeEdit
assert isinstance(parent, CodeEdit)
super(EncodingsContextMenu, self).__init__(
title, parent, selected_encoding)
self.reload_requested.connect(self._on_reload_requested)
parent.new_text_set.connect(self._refresh)
sep = QtWidgets.QAction(self.parent())
sep.setSeparator(True)
self.parent().add_menu(self)
self._timer = QtCore.QTimer()
self._timer.setInterval(1)
self._timer.timeout.connect(self._reload)
self._refresh()
def _refresh(self):
self._current_encoding = convert_to_codec_key(
self.parent().file.encoding)
super(EncodingsContextMenu, self)._refresh()
@QtCore.Slot(str)
def _on_reload_requested(self, encoding):
self._encoding = encoding
self._timer.start()
@QtCore.Slot()
def _reload(self):
self._timer.stop()
try:
self.parent().file.reload(self._encoding)
except UnicodeDecodeError:
QtWidgets.QMessageBox.warning(
self.parent(), 'Decoding error',
'Failed to reload file with encoding %s' % self._encoding)
else:
try:
from pyqode.core.panels import EncodingPanel
panel = self.parent().panels.get(EncodingPanel)
except KeyError:
pass
else:
panel.cancel()