1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
# -*- coding: utf-8 -*-
"""
Contains a custom QTableWidget for easier displaying of CheckerMessages
"""
from pyqode.core.api.utils import memoized
from pyqode.core.modes import CheckerMessage, CheckerMessages
from pyqode.qt import QtCore, QtWidgets, QtGui
COL_TYPE = 0
COL_FILE_NAME = 1
COL_LINE_NBR = 2
COL_MSG = 3
class ErrorsTable(QtWidgets.QTableWidget):
"""
Extends a QtWidgets.QTableWidget to easily show
:class:`pyqode.core.modes.CheckerMessage`.
You add messages to the table using
:meth:`pyqode.core.widgets.ErrorsTable.add_message`.
You clear the table using :meth:`pyqode.core.widgets.ErrorsTable`.
"""
#: Signal emitted when a message is activated, the clicked signal is passed
#: as a parameter
msg_activated = QtCore.Signal(CheckerMessage)
ICONS = {
CheckerMessages.INFO: ':pyqode-icons/rc/dialog-info.png',
CheckerMessages.WARNING: ':pyqode-icons/rc/dialog-warning.png',
CheckerMessages.ERROR: ':pyqode-icons/rc/dialog-error.png',
}
def __init__(self, parent=None):
QtWidgets.QTableWidget.__init__(self, parent)
self.setColumnCount(6)
self.setHorizontalHeaderLabels(
["Type", "File name", "Line", "Description", 'Details'])
try:
# pyqt4
self.horizontalHeader().setResizeMode(
QtWidgets.QHeaderView.ResizeToContents)
self.horizontalHeader().setResizeMode(
COL_MSG, QtWidgets.QHeaderView.Stretch)
except AttributeError:
# pyqt5
self.horizontalHeader().setSectionResizeMode(
QtWidgets.QHeaderView.ResizeToContents)
self.horizontalHeader().setSectionResizeMode(
COL_MSG, QtWidgets.QHeaderView.Stretch)
self.setMinimumSize(900, 200)
self.itemActivated.connect(self._on_item_activated)
self.setSelectionMode(self.SingleSelection)
self.setSelectionBehavior(self.SelectRows)
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self._show_context_menu)
self.context_mnu = QtWidgets.QMenu()
self.action_details = QtWidgets.QAction(_('View details'), self)
self.action_details.triggered.connect(self.showDetails)
self.action_copy = QtWidgets.QAction(_('Copy error'), self)
self.action_copy.triggered.connect(self._copy_cell_text)
self.context_mnu.addAction(self.action_details)
self.context_mnu.addAction(self.action_copy)
self.clear()
def _copy_cell_text(self):
"""
Copies the description of the selected message to the clipboard
"""
txt = self.currentItem().text()
QtWidgets.QApplication.clipboard().setText(txt)
def _show_context_menu(self, pos):
""" Shows the context menu """
self.context_mnu.exec_(self.mapToGlobal(pos))
def clear(self):
"""
Clears the tables and the message list
"""
QtWidgets.QTableWidget.clear(self)
self.setRowCount(0)
self.setColumnCount(4)
self.setHorizontalHeaderLabels(
["Type", "File name", "Line", "Description"])
@classmethod
@memoized
def _make_icon(cls, status):
"""
Make icon from icon filename/tuple (if you want to use a theme)
"""
icon = cls.ICONS[status]
if isinstance(icon, tuple):
return QtGui.QIcon.fromTheme(
icon[0], QtGui.QIcon(icon[1]))
elif isinstance(icon, str):
return QtGui.QIcon(icon)
elif isinstance(icon, QtGui.QIcon):
return icon
else:
return None
def add_message(self, msg):
"""
Adds a checker message to the table.
:param msg: The message to append
:type msg: pyqode.core.modes.CheckerMessage
"""
row = self.rowCount()
self.insertRow(row)
# type
item = QtWidgets.QTableWidgetItem(
self._make_icon(msg.status), msg.status_string)
item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
item.setData(QtCore.Qt.UserRole, msg)
self.setItem(row, COL_TYPE, item)
# filename
item = QtWidgets.QTableWidgetItem(
QtCore.QFileInfo(msg.path).fileName())
item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
item.setData(QtCore.Qt.UserRole, msg)
self.setItem(row, COL_FILE_NAME, item)
# line
if msg.line < 0:
item = QtWidgets.QTableWidgetItem("-")
else:
item = QtWidgets.QTableWidgetItem(str(msg.line + 1))
item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
item.setData(QtCore.Qt.UserRole, msg)
self.setItem(row, COL_LINE_NBR, item)
# desc
item = QtWidgets.QTableWidgetItem(msg.description)
item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
item.setData(QtCore.Qt.UserRole, msg)
self.setItem(row, COL_MSG, item)
def _on_item_activated(self, item):
"""
Emits the message activated signal
"""
msg = item.data(QtCore.Qt.UserRole)
self.msg_activated.emit(msg)
def showDetails(self):
"""
Shows the error details.
"""
msg = self.currentItem().data(QtCore.Qt.UserRole)
desc = msg.description
desc = desc.replace('\r\n', '\n').replace('\r', '\n')
desc = desc.replace('\n', '<br/>')
QtWidgets.QMessageBox.information(
self, _('Message details'),
_("""<p><b>Description:</b><br/>%s</p>
<p><b>File:</b><br/>%s</p>
<p><b>Line:</b><br/>%d</p>
""") % (desc, msg.path, msg.line + 1, ))
|