import sys
import logging

from PyQt5 import QtCore, QtGui, QtQuick


class Model(QtCore.QAbstractListModel):
    def __init__(self, parent=None):
        super(Model, self).__init__(parent)
        self.items = []
        self.roles = {
            257: "threadName",
            258: "name",
            259: "thread",
            260: "created",
            261: "process",
            262: "processName",
            263: "args",
            264: "module",
            265: "filename",
            266: "levelno",
            267: "exc_text",
            268: "pathname",
            269: "lineno",
            270: "msg",
            271: "exc_info",
            272: "funcName",
            273: "relativeCreated",
            274: "levelname",
            275: "msecs",
        }

    def addItem(self, item):
        self.beginInsertRows(QtCore.QModelIndex(),
                             self.rowCount(),
                             self.rowCount())

        self.items.append(item.__dict__)
        self.endInsertRows()

    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.items)

    def data(self, index, role=QtCore.Qt.DisplayRole):
        try:
            item = self.items[index.row()]
        except IndexError:
            return QtCore.QVariant()

        if role in self.roles:
            return item.get(self.roles[role], QtCore.QVariant())

        return QtCore.QVariant()

    def roleNames(self):
        return self.roles


class MessageHandler(logging.Handler):
    def __init__(self, model, *args, **kwargs):
        logging.Handler.__init__(self, *args, **kwargs)
        self.model = model

    def emit(self, record):
        self.model.addItem(record)


app = QtGui.QGuiApplication(sys.argv)

view = QtQuick.QQuickView()

model = Model()
proxy = QtCore.QSortFilterProxyModel()
proxy.setSourceModel(model)
proxy.setFilterRole(model.roles.keys()[0])
proxy.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)


class Control(QtCore.QObject):
    """Controller

    This object is only used to synchronise a list
    between Python and QML; it's messy and not ideal.

    """

    _levels = "INFO;WARNING"

    @QtCore.pyqtProperty(str)
    def levels(self):
        return self._levels

    @QtCore.pyqtSlot(str)
    def updateLevels(self, levels):
        self._levels = levels
        proxy.invalidate()

control = Control()


def filterAcceptsRow(source_row, source_parent):
    """Exclude levels

    Overridden in order to exclude any log-record
    that isn't part of Control._levels

    """

    row = model.items[source_row]

    if not row["levelname"] in control._levels.split(";"):
        return False

    return QtCore.QSortFilterProxyModel.filterAcceptsRow(
        proxy, source_row, source_parent)

proxy.filterAcceptsRow = filterAcceptsRow

engine = view.engine()
context = engine.rootContext()
context.setContextProperty("qmodel", proxy)
context.setContextProperty("control", control)

view.setSource(QtCore.QUrl("tst_LogObjectMulti.qml"))
view.setResizeMode(view.SizeRootObjectToView)
view.show()

handler = MessageHandler(model)

log = logging.getLogger()
log.addHandler(handler)
log.setLevel(logging.DEBUG)

# Test data
log.debug("e = mc^2")
log.info("Some information here")
log.info("Some more information")
log.warning("Don't go into the light!")
log.critical("You, sir, are done for.")
log.error("Does not compute")

app.exec_()