197 lines
7.0 KiB
Python
197 lines
7.0 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)
|
|
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()
|