140 lines
5.6 KiB
Python
140 lines
5.6 KiB
Python
# Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
import logging
|
|
|
|
from PySide2 import QtWidgets, QtCore, QtGui
|
|
|
|
|
|
class LogWidget(logging.Handler):
|
|
"""
|
|
Custom Log Handler with embedded QtWidgets.QDockWidget
|
|
"""
|
|
|
|
def __init__(self):
|
|
super(LogWidget, self).__init__()
|
|
# Set default formatting
|
|
self.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(message)s', '%Y-%m-%d %H:%M:%S'))
|
|
# Create dock
|
|
self._log_dock = QtWidgets.QDockWidget()
|
|
# Only allow it to be parented to the bottom
|
|
self._log_dock.setAllowedAreas(QtCore.Qt.BottomDockWidgetArea)
|
|
|
|
central_widget = QtWidgets.QWidget()
|
|
central_widget.setContentsMargins(0, 0, 0, 0)
|
|
self._log_dock.setWidget(central_widget)
|
|
main_layout = QtWidgets.QVBoxLayout()
|
|
main_layout.setContentsMargins(0, 0, 0, 0)
|
|
central_widget.setLayout(main_layout)
|
|
|
|
toolbar_layout = QtWidgets.QHBoxLayout()
|
|
toolbar_layout.setContentsMargins(0, 0, 0, 0)
|
|
main_layout.addLayout(toolbar_layout)
|
|
|
|
self._output_log = QtWidgets.QListWidget()
|
|
self._output_log.setProperty("Log", True)
|
|
self._output_log.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
|
self._output_log.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
|
self._output_log.customContextMenuRequested.connect(self._show_context_menu)
|
|
main_layout.addWidget(self._output_log)
|
|
|
|
icon_size_px = 25
|
|
icon_size = QtCore.QSize(icon_size_px, icon_size_px)
|
|
btn_size_px = 30
|
|
btn_size = QtCore.QSize(btn_size_px, btn_size_px)
|
|
|
|
self._debug_btn = QtWidgets.QPushButton()
|
|
self._debug_btn.setIcon(QtGui.QIcon(QtGui.QPixmap("PoseWrangler:debug.png")))
|
|
self._debug_btn.setIconSize(icon_size)
|
|
self._debug_btn.setProperty("LogButton", True)
|
|
self._debug_btn.setCheckable(True)
|
|
self._debug_btn.setChecked(False)
|
|
self._debug_btn.setFixedSize(btn_size)
|
|
self._debug_btn.clicked.connect(self._refresh_log)
|
|
toolbar_layout.addWidget(self._debug_btn)
|
|
|
|
self._info_btn = QtWidgets.QPushButton()
|
|
self._info_btn.setIcon(QtGui.QIcon(QtGui.QPixmap("PoseWrangler:info.png")))
|
|
self._info_btn.setIconSize(icon_size)
|
|
self._info_btn.setProperty("LogButton", True)
|
|
self._info_btn.setCheckable(True)
|
|
self._info_btn.setChecked(True)
|
|
self._info_btn.setFixedSize(btn_size)
|
|
self._info_btn.clicked.connect(self._refresh_log)
|
|
toolbar_layout.addWidget(self._info_btn)
|
|
|
|
self._warning_btn = QtWidgets.QPushButton()
|
|
self._warning_btn.setIcon(QtGui.QIcon(QtGui.QPixmap("PoseWrangler:warning.png")))
|
|
self._warning_btn.setIconSize(icon_size)
|
|
self._warning_btn.setProperty("LogButton", True)
|
|
self._warning_btn.setCheckable(True)
|
|
self._warning_btn.setChecked(True)
|
|
self._warning_btn.setFixedSize(btn_size)
|
|
self._warning_btn.clicked.connect(self._refresh_log)
|
|
toolbar_layout.addWidget(self._warning_btn)
|
|
|
|
self._error_btn = QtWidgets.QPushButton()
|
|
self._error_btn.setIcon(QtGui.QIcon(QtGui.QPixmap("PoseWrangler:error.png")))
|
|
self._error_btn.setIconSize(icon_size)
|
|
self._error_btn.setProperty("LogButton", True)
|
|
self._error_btn.setCheckable(True)
|
|
self._error_btn.setChecked(True)
|
|
self._error_btn.setFixedSize(btn_size)
|
|
self._error_btn.clicked.connect(self._refresh_log)
|
|
toolbar_layout.addWidget(self._error_btn)
|
|
toolbar_layout.addStretch(0)
|
|
|
|
self._clear_log_btn = QtWidgets.QPushButton()
|
|
self._clear_log_btn.setIcon(QtGui.QIcon(QtGui.QPixmap("PoseWrangler:clear.png")))
|
|
self._clear_log_btn.setIconSize(icon_size)
|
|
self._clear_log_btn.setProperty("LogButton", True)
|
|
self._clear_log_btn.setFixedSize(btn_size)
|
|
self._clear_log_btn.clicked.connect(self._output_log.clear)
|
|
toolbar_layout.addWidget(self._clear_log_btn)
|
|
|
|
@property
|
|
def log_dock(self):
|
|
return self._log_dock
|
|
|
|
def emit(self, record):
|
|
level_colour_map = {
|
|
logging.DEBUG: QtGui.QColor(91, 192, 222),
|
|
logging.INFO: QtGui.QColor(247, 247, 247),
|
|
logging.WARNING: QtGui.QColor(240, 173, 78),
|
|
logging.ERROR: QtGui.QColor(217, 83, 79)
|
|
}
|
|
msg = self.format(record)
|
|
item = QtWidgets.QListWidgetItem(msg)
|
|
item.setData(QtCore.Qt.UserRole, record.levelno)
|
|
item.setForeground(QtGui.QBrush(level_colour_map[record.levelno]))
|
|
self._output_log.addItem(item)
|
|
self._refresh_log()
|
|
|
|
def _refresh_log(self):
|
|
level_btn_map = {
|
|
logging.DEBUG: self._debug_btn,
|
|
logging.INFO: self._info_btn,
|
|
logging.WARNING: self._warning_btn,
|
|
logging.ERROR: self._error_btn
|
|
}
|
|
for i in range(0, self._output_log.count()):
|
|
item = self._output_log.item(i)
|
|
data = item.data(QtCore.Qt.UserRole)
|
|
item.setHidden(not level_btn_map[data].isChecked())
|
|
|
|
def _copy_to_clipboard(self):
|
|
clipboard_text = ""
|
|
for item in self._output_log.selectedItems():
|
|
text = item.text()
|
|
clipboard_text += text
|
|
if text:
|
|
clipboard_text += "\n"
|
|
clipboard = QtWidgets.QApplication.clipboard()
|
|
clipboard.setText(clipboard_text)
|
|
|
|
def _show_context_menu(self, pos):
|
|
if not self._output_log.selectedItems():
|
|
return
|
|
menu = QtWidgets.QMenu(parent=self._output_log)
|
|
copy_action = menu.addAction("Copy")
|
|
copy_action.triggered.connect(self._copy_to_clipboard)
|
|
menu.exec_(QtGui.QCursor.pos()) |