541 lines
21 KiB
Python
541 lines
21 KiB
Python
#!/usr/bin/env python3
|
|
|
|
from PySide6 import QtWidgets, QtCore, QtCharts, QtGui
|
|
from Core.Interface import Stylesheets
|
|
from datetime import datetime
|
|
from getpass import getuser
|
|
from time import sleep
|
|
import networkx as nx
|
|
import queue
|
|
|
|
|
|
class DockBarThree(QtWidgets.QDockWidget):
|
|
"""
|
|
Dockbar that hosts the Timeline, Chat and Server Status widgets.
|
|
"""
|
|
|
|
def initialiseLayout(self):
|
|
# self.setStyleSheet(Stylesheets.MAIN_WINDOW_STYLESHEET)
|
|
childWidget = QtWidgets.QWidget()
|
|
childWidget.setLayout(QtWidgets.QVBoxLayout())
|
|
childWidget.setContentsMargins(0, 0, 0, 0)
|
|
self.setWidget(childWidget)
|
|
|
|
childWidget2 = QtWidgets.QWidget()
|
|
childWidget2.setContentsMargins(0, 0, 0, 0)
|
|
childWidget2.setLayout(QtWidgets.QHBoxLayout())
|
|
childWidget.layout().addWidget(childWidget2)
|
|
childWidget2.layout().addWidget(self.tabPane)
|
|
self.tabPane.setContentsMargins(0, 0, 0, 0)
|
|
self.tabPane.addTab(self.logViewer, 'Program Log')
|
|
self.tabPane.addTab(self.timeWidget, 'Timeline')
|
|
childWidget2.layout().addWidget(self.chatBox)
|
|
self.serverStatus.setStyleSheet(Stylesheets.DOCK_BAR_LABEL)
|
|
childWidget.layout().addWidget(self.serverStatus)
|
|
|
|
def __init__(self, mainWindow, title="Dockbar Three"):
|
|
super(DockBarThree, self).__init__(parent=mainWindow)
|
|
self.setAllowedAreas(QtCore.Qt.TopDockWidgetArea |
|
|
QtCore.Qt.BottomDockWidgetArea)
|
|
self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable |
|
|
QtWidgets.QDockWidget.DockWidgetFloatable |
|
|
QtWidgets.QDockWidget.DockWidgetClosable)
|
|
self.setWindowTitle(title)
|
|
self.setObjectName(title)
|
|
self.setMaximumHeight(275)
|
|
self.setMinimumHeight(275)
|
|
|
|
self.tabPane = QtWidgets.QTabWidget()
|
|
|
|
self.serverStatus = ServerStatusBox(self)
|
|
self.chatBox = ChatBox(self, self.parent())
|
|
self.timeWidget = TimeWidget(self, self.parent())
|
|
self.logViewer = QtWidgets.QPlainTextEdit()
|
|
logViewerUpdateThread = LoggingUpdateThread(mainWindow.MESSAGEHANDLER)
|
|
logViewerUpdateThread.loggingSignal.connect(self.updateLogs)
|
|
logViewerUpdateThread.start()
|
|
self.logViewer.setReadOnly(True)
|
|
|
|
self.initialiseLayout()
|
|
|
|
def updateLogs(self, newLogMessage: str):
|
|
self.logViewer.appendPlainText(newLogMessage)
|
|
|
|
|
|
class TimeWidget(QtWidgets.QWidget):
|
|
|
|
def __init__(self, parent, mainWindow):
|
|
super(TimeWidget, self).__init__(parent=parent)
|
|
|
|
self.mainWindow = mainWindow
|
|
self.timeDetails = {}
|
|
self.currentTimeStep = []
|
|
|
|
self.timelineChart = QtCharts.QChart()
|
|
self.timelineChart.setTitle("Timeline")
|
|
self.timelineChart.setTheme(QtCharts.QChart.ChartThemeBlueCerulean)
|
|
self.timelineChart.setMargins(QtCore.QMargins(0, 0, 0, 0))
|
|
self.chartView = QtCharts.QChartView(self.timelineChart)
|
|
self.chartView.setRubberBand(QtCharts.QChartView.NoRubberBand)
|
|
self.timelineChart.setAnimationOptions(QtCharts.QChart.AllAnimations)
|
|
self.timelineChart.setAnimationDuration(250)
|
|
self.timelineChart.legend().hide()
|
|
|
|
self.timescaleSelector = TimelineTimescaleSelector(self)
|
|
|
|
self.setLayout(QtWidgets.QHBoxLayout())
|
|
self.layout().addWidget(self.timescaleSelector)
|
|
self.layout().addWidget(self.chartView)
|
|
|
|
def takePictureOfView(self, transparentBackground: bool = False):
|
|
# Need to set size and format of pic before using it.
|
|
# Ref: https://qtcentre.org/threads/10975-Help-Export-QGraphicsView-to-Image-File
|
|
# Rendering best optimized to rgb32 and argb32_premultiplied.
|
|
# Ref: https://doc.qt.io/qtforpython/PySide6/QtGui/QImage.html?highlight=qimage#image-formats
|
|
picture = QtGui.QImage(self.chartView.size(), QtGui.QImage.Format_ARGB32_Premultiplied)
|
|
picturePainter = QtGui.QPainter(picture)
|
|
if not transparentBackground:
|
|
picture.fill(QtGui.QColor(61, 61, 61))
|
|
self.chartView.render(picturePainter)
|
|
return picture
|
|
|
|
def updateTimeline(self, node, added: bool = True, updateGraph: bool = True):
|
|
nodeTime = datetime.fromisoformat(node['Date Created'])
|
|
|
|
nodeYear = nodeTime.year
|
|
nodeMonth = nodeTime.month
|
|
nodeDay = nodeTime.day
|
|
nodeHour = nodeTime.hour
|
|
nodeMinute = nodeTime.minute
|
|
|
|
# Dicts are fast, but this is not very efficient.
|
|
if nodeYear not in self.timeDetails:
|
|
self.timeDetails[nodeYear] = {}
|
|
|
|
if nodeMonth not in self.timeDetails[nodeYear]:
|
|
self.timeDetails[nodeYear][nodeMonth] = {}
|
|
|
|
if nodeDay not in self.timeDetails[nodeYear][nodeMonth]:
|
|
self.timeDetails[nodeYear][nodeMonth][nodeDay] = {}
|
|
|
|
if nodeHour not in self.timeDetails[nodeYear][nodeMonth][nodeDay]:
|
|
self.timeDetails[nodeYear][nodeMonth][nodeDay][nodeHour] = {}
|
|
|
|
if nodeMinute not in self.timeDetails[nodeYear][nodeMonth][nodeDay][nodeHour]:
|
|
# Sanity check. Should not be able to remove nodes that do not exist, but you never know.
|
|
if added:
|
|
self.timeDetails[nodeYear][nodeMonth][nodeDay][nodeHour][nodeMinute] = 1
|
|
else:
|
|
self.timeDetails[nodeYear][nodeMonth][nodeDay][nodeHour][nodeMinute] = 0
|
|
else:
|
|
if added:
|
|
self.timeDetails[nodeYear][nodeMonth][nodeDay][nodeHour][nodeMinute] += 1
|
|
else:
|
|
if self.timeDetails[nodeYear][nodeMonth][nodeDay][nodeHour][nodeMinute] > 0:
|
|
self.timeDetails[nodeYear][nodeMonth][nodeDay][nodeHour][nodeMinute] -= 1
|
|
|
|
if updateGraph:
|
|
self.drawChart([])
|
|
|
|
def resetTimeline(self, graph: nx.DiGraph, updateGraph: bool = True):
|
|
self.timeDetails = {}
|
|
|
|
for node in graph.nodes():
|
|
self.updateTimeline(graph.nodes[node], True, False)
|
|
|
|
if updateGraph:
|
|
self.drawChart([])
|
|
|
|
def drawChart(self, timescale: list):
|
|
try:
|
|
year = timescale[0]
|
|
except IndexError:
|
|
year = None
|
|
try:
|
|
month = timescale[1]
|
|
except IndexError:
|
|
month = None
|
|
try:
|
|
day = timescale[2]
|
|
except IndexError:
|
|
day = None
|
|
try:
|
|
hour = timescale[3]
|
|
except IndexError:
|
|
hour = None
|
|
try:
|
|
minute = timescale[4]
|
|
except IndexError:
|
|
minute = None
|
|
|
|
if minute is not None:
|
|
barsDict = {minute: self.timeDetails[year][month][day][hour][minute]}
|
|
self.currentTimeStep = [year, month, day, hour, minute]
|
|
self.drawChartHelper(barsDict, self.currentTimeStep)
|
|
|
|
elif hour is not None:
|
|
barsDict = {}
|
|
for minute in self.timeDetails[year][month][day][hour]:
|
|
barsDict[minute] = self.timeDetails[year][month][day][hour][minute]
|
|
self.currentTimeStep = [year, month, day, hour]
|
|
self.drawChartHelper(barsDict, self.currentTimeStep)
|
|
|
|
elif day is not None:
|
|
barsDict = {}
|
|
for hour in self.timeDetails[year][month][day]:
|
|
barsDict[hour] = 0
|
|
for minute in self.timeDetails[year][month][day][hour]:
|
|
barsDict[hour] += self.timeDetails[year][month][day][hour][minute]
|
|
self.currentTimeStep = [year, month, day]
|
|
self.drawChartHelper(barsDict, self.currentTimeStep)
|
|
|
|
elif month is not None:
|
|
barsDict = {}
|
|
for day in self.timeDetails[year][month]:
|
|
barsDict[day] = 0
|
|
for hour in self.timeDetails[year][month][day]:
|
|
for minute in self.timeDetails[year][month][day][hour]:
|
|
barsDict[day] += self.timeDetails[year][month][day][hour][minute]
|
|
self.currentTimeStep = [year, month]
|
|
self.drawChartHelper(barsDict, self.currentTimeStep)
|
|
|
|
elif year is not None:
|
|
barsDict = {}
|
|
for month in self.timeDetails[year]:
|
|
barsDict[month] = 0
|
|
for day in self.timeDetails[year][month]:
|
|
for hour in self.timeDetails[year][month][day]:
|
|
for minute in self.timeDetails[year][month][day][hour]:
|
|
barsDict[month] += self.timeDetails[year][month][day][hour][minute]
|
|
self.currentTimeStep = [year]
|
|
self.drawChartHelper(barsDict, self.currentTimeStep)
|
|
|
|
else:
|
|
barsDict = {}
|
|
for year in self.timeDetails:
|
|
barsDict[year] = 0
|
|
for month in self.timeDetails[year]:
|
|
for day in self.timeDetails[year][month]:
|
|
for hour in self.timeDetails[year][month][day]:
|
|
for minute in self.timeDetails[year][month][day][hour]:
|
|
barsDict[year] += self.timeDetails[year][month][day][hour][minute]
|
|
self.currentTimeStep = []
|
|
self.drawChartHelper(barsDict, self.currentTimeStep)
|
|
|
|
def drawChartHelper(self, barsDict: dict, timestep: list):
|
|
timelineSeries = QtCharts.QBarSeries(self.timelineChart)
|
|
maxEntityNum = 0
|
|
xAxisValues = []
|
|
|
|
barSet = TimelineBarSet('Entities', self, timestep, list(barsDict))
|
|
barSet.setColor(QtGui.Qt.darkCyan)
|
|
for bar in barsDict:
|
|
barSet.append(barsDict[bar])
|
|
timelineSeries.append(barSet)
|
|
if barsDict[bar] > maxEntityNum:
|
|
maxEntityNum = barsDict[bar]
|
|
value = ""
|
|
for step in range(len(timestep)):
|
|
if step <= 2:
|
|
value += str(timestep[step]) + '/'
|
|
if step == 2:
|
|
value = value[:-1]
|
|
value += " "
|
|
else:
|
|
value += str(timestep[step]) + ':'
|
|
value += str(bar)
|
|
xAxisValues.append(value)
|
|
self.timelineChart.removeAllSeries()
|
|
self.timelineChart.addSeries(timelineSeries)
|
|
self.timelineChart.createDefaultAxes()
|
|
self.timelineChart.removeAxis(self.timelineChart.axisX(timelineSeries))
|
|
self.timelineChart.removeAxis(self.timelineChart.axisY(timelineSeries))
|
|
|
|
yAxis = QtCharts.QValueAxis()
|
|
yAxis.applyNiceNumbers()
|
|
yAxis.setTickCount(min(maxEntityNum + 1, 4))
|
|
|
|
xAxis = QtCharts.QBarCategoryAxis()
|
|
xAxis.append(xAxisValues)
|
|
self.timelineChart.setAxisY(yAxis, timelineSeries)
|
|
self.timelineChart.setAxisX(xAxis, timelineSeries)
|
|
|
|
timesteps = len(timestep)
|
|
if timesteps == 0:
|
|
self.timescaleSelector.adjustLabelsToYear()
|
|
elif timesteps == 1:
|
|
self.timescaleSelector.adjustLabelsToMonth()
|
|
elif timesteps == 2:
|
|
self.timescaleSelector.adjustLabelsToDay()
|
|
elif timesteps == 3:
|
|
self.timescaleSelector.adjustLabelsToHour()
|
|
elif timesteps == 4:
|
|
self.timescaleSelector.adjustLabelsToMinute()
|
|
elif timesteps == 5:
|
|
self.timescaleSelector.adjustLabelsToSecond()
|
|
else:
|
|
# Just in case.
|
|
self.timescaleSelector.adjustLabelsToSecond()
|
|
|
|
self.mainWindow.timelineSelectMatchingEntities(timestep)
|
|
|
|
|
|
class TimelineBarSet(QtCharts.QBarSet):
|
|
|
|
def __init__(self, label: str, timeWidget: TimeWidget, timestep: list, barSeriesDict: list):
|
|
super(TimelineBarSet, self).__init__(label)
|
|
|
|
self.clicked.connect(self.selectedAction)
|
|
self.timeWidget = timeWidget
|
|
self.timestep = timestep
|
|
self.barSeriesDict = barSeriesDict
|
|
|
|
def selectedAction(self, index):
|
|
self.timestep.append(self.barSeriesDict[index])
|
|
self.timeWidget.drawChart(self.timestep)
|
|
|
|
|
|
class TimelineTimescaleSelector(QtWidgets.QLabel):
|
|
|
|
def __init__(self, timeWidget: TimeWidget):
|
|
super(TimelineTimescaleSelector, self).__init__(parent=timeWidget)
|
|
self.setStyleSheet("""border: 2px solid rgb(44, 49, 58);""")
|
|
|
|
self.timeWidget = timeWidget
|
|
self.setMinimumWidth(150)
|
|
self.setMaximumHeight(150)
|
|
|
|
self.setLayout(QtWidgets.QFormLayout())
|
|
self.setFrameStyle(QtWidgets.QFrame.Sunken)
|
|
|
|
self.yearButton = QtWidgets.QPushButton(' Year: ')
|
|
self.yearButton.clicked.connect(self.yearButtonPressed)
|
|
self.yearText = QtWidgets.QLabel('-')
|
|
self.yearText.setFrameStyle(QtWidgets.QFrame.Sunken)
|
|
self.monthButton = QtWidgets.QPushButton(' Month: ')
|
|
self.monthButton.clicked.connect(self.monthButtonPressed)
|
|
self.monthText = QtWidgets.QLabel('X')
|
|
self.monthText.setFrameStyle(QtWidgets.QFrame.Sunken)
|
|
self.dayButton = QtWidgets.QPushButton(' Day: ')
|
|
self.dayButton.clicked.connect(self.dayButtonPressed)
|
|
self.dayText = QtWidgets.QLabel('X')
|
|
self.dayText.setFrameStyle(QtWidgets.QFrame.Sunken)
|
|
self.hourButton = QtWidgets.QPushButton(' Hour: ')
|
|
self.hourButton.clicked.connect(self.hourButtonPressed)
|
|
self.hourText = QtWidgets.QLabel('X')
|
|
self.hourText.setFrameStyle(QtWidgets.QFrame.Sunken)
|
|
self.minuteButton = QtWidgets.QPushButton(' Minute: ')
|
|
self.minuteButton.clicked.connect(self.minuteButtonPressed)
|
|
self.minuteText = QtWidgets.QLabel('X')
|
|
self.minuteText.setFrameStyle(QtWidgets.QFrame.Sunken)
|
|
|
|
self.layout().addRow(self.yearButton, self.yearText)
|
|
self.layout().addRow(self.monthButton, self.monthText)
|
|
self.layout().addRow(self.dayButton, self.dayText)
|
|
self.layout().addRow(self.hourButton, self.hourText)
|
|
self.layout().addRow(self.minuteButton, self.minuteText)
|
|
|
|
self.yearButton.setDown(True)
|
|
self.yearButton.setDisabled(True)
|
|
self.monthButton.setDisabled(True)
|
|
self.dayButton.setDisabled(True)
|
|
self.hourButton.setDisabled(True)
|
|
self.minuteButton.setDisabled(True)
|
|
|
|
def yearButtonPressed(self):
|
|
self.timeWidget.drawChart(self.timeWidget.currentTimeStep[:0])
|
|
self.adjustLabelsToYear()
|
|
|
|
def adjustLabelsToYear(self):
|
|
self.yearButton.setDown(True)
|
|
self.yearButton.setDisabled(True)
|
|
self.monthButton.setDisabled(True)
|
|
self.monthButton.setDown(False)
|
|
self.dayButton.setDisabled(True)
|
|
self.dayButton.setDown(False)
|
|
self.hourButton.setDisabled(True)
|
|
self.hourButton.setDown(False)
|
|
self.minuteButton.setDown(False)
|
|
self.minuteButton.setDisabled(True)
|
|
|
|
self.yearText.setText('-')
|
|
self.monthText.setText('X')
|
|
self.dayText.setText('X')
|
|
self.hourText.setText('X')
|
|
self.minuteText.setText('X')
|
|
|
|
def monthButtonPressed(self):
|
|
self.timeWidget.drawChart(self.timeWidget.currentTimeStep[:1])
|
|
self.adjustLabelsToMonth()
|
|
|
|
def adjustLabelsToMonth(self):
|
|
self.yearButton.setDown(False)
|
|
self.yearButton.setDisabled(False)
|
|
self.monthButton.setDown(True)
|
|
self.monthButton.setDisabled(True)
|
|
self.dayButton.setDisabled(True)
|
|
self.dayButton.setDown(False)
|
|
self.hourButton.setDisabled(True)
|
|
self.hourButton.setDown(False)
|
|
self.minuteButton.setDown(False)
|
|
self.minuteButton.setDisabled(True)
|
|
|
|
self.yearText.setText(str(self.timeWidget.currentTimeStep[0]))
|
|
self.monthText.setText('-')
|
|
self.dayText.setText('X')
|
|
self.hourText.setText('X')
|
|
self.minuteText.setText('X')
|
|
|
|
def dayButtonPressed(self):
|
|
self.timeWidget.drawChart(self.timeWidget.currentTimeStep[:2])
|
|
self.adjustLabelsToDay()
|
|
|
|
def adjustLabelsToDay(self):
|
|
self.yearButton.setDown(False)
|
|
self.yearButton.setDisabled(False)
|
|
self.monthButton.setDown(False)
|
|
self.monthButton.setDisabled(False)
|
|
self.dayButton.setDown(True)
|
|
self.dayButton.setDisabled(True)
|
|
self.hourButton.setDisabled(True)
|
|
self.hourButton.setDown(False)
|
|
self.minuteButton.setDown(False)
|
|
self.minuteButton.setDisabled(True)
|
|
|
|
self.yearText.setText(str(self.timeWidget.currentTimeStep[0]))
|
|
self.monthText.setText(str(self.timeWidget.currentTimeStep[1]))
|
|
self.dayText.setText('-')
|
|
self.hourText.setText('X')
|
|
self.minuteText.setText('X')
|
|
|
|
def hourButtonPressed(self):
|
|
self.timeWidget.drawChart(self.timeWidget.currentTimeStep[:3])
|
|
self.adjustLabelsToHour()
|
|
|
|
def adjustLabelsToHour(self):
|
|
self.yearButton.setDown(False)
|
|
self.yearButton.setDisabled(False)
|
|
self.monthButton.setDown(False)
|
|
self.monthButton.setDisabled(False)
|
|
self.dayButton.setDown(False)
|
|
self.dayButton.setDisabled(False)
|
|
self.hourButton.setDown(True)
|
|
self.hourButton.setDisabled(True)
|
|
self.minuteButton.setDown(False)
|
|
self.minuteButton.setDisabled(True)
|
|
self.yearText.setText(str(self.timeWidget.currentTimeStep[0]))
|
|
self.monthText.setText(str(self.timeWidget.currentTimeStep[1]))
|
|
self.dayText.setText(str(self.timeWidget.currentTimeStep[2]))
|
|
self.hourText.setText('-')
|
|
self.minuteText.setText('X')
|
|
|
|
def minuteButtonPressed(self):
|
|
self.timeWidget.drawChart(self.timeWidget.currentTimeStep[:4])
|
|
self.adjustLabelsToMinute()
|
|
|
|
def adjustLabelsToMinute(self):
|
|
self.yearButton.setDown(False)
|
|
self.yearButton.setDisabled(False)
|
|
self.monthButton.setDown(False)
|
|
self.monthButton.setDisabled(False)
|
|
self.dayButton.setDown(False)
|
|
self.dayButton.setDisabled(False)
|
|
self.hourButton.setDown(False)
|
|
self.hourButton.setDisabled(False)
|
|
self.minuteButton.setDown(True)
|
|
self.minuteButton.setDisabled(True)
|
|
self.yearText.setText(str(self.timeWidget.currentTimeStep[0]))
|
|
self.monthText.setText(str(self.timeWidget.currentTimeStep[1]))
|
|
self.dayText.setText(str(self.timeWidget.currentTimeStep[2]))
|
|
self.hourText.setText(str(self.timeWidget.currentTimeStep[3]))
|
|
self.minuteText.setText('-')
|
|
|
|
def adjustLabelsToSecond(self):
|
|
self.yearButton.setDown(False)
|
|
self.yearButton.setDisabled(False)
|
|
self.monthButton.setDown(False)
|
|
self.monthButton.setDisabled(False)
|
|
self.dayButton.setDown(False)
|
|
self.dayButton.setDisabled(False)
|
|
self.hourButton.setDown(False)
|
|
self.hourButton.setDisabled(False)
|
|
self.minuteButton.setDown(False)
|
|
self.minuteButton.setDisabled(False)
|
|
self.yearText.setText(str(self.timeWidget.currentTimeStep[0]))
|
|
self.monthText.setText(str(self.timeWidget.currentTimeStep[1]))
|
|
self.dayText.setText(str(self.timeWidget.currentTimeStep[2]))
|
|
self.hourText.setText(str(self.timeWidget.currentTimeStep[3]))
|
|
self.minuteText.setText(str(self.timeWidget.currentTimeStep[4]))
|
|
|
|
|
|
class ServerStatusBox(QtWidgets.QLabel):
|
|
|
|
def __init__(self, parent):
|
|
super(ServerStatusBox, self).__init__(parent=parent)
|
|
self.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
|
|
self.setFrameStyle(QtWidgets.QFrame.Sunken | QtWidgets.QFrame.StyledPanel)
|
|
self.setText("Not connected to a server")
|
|
|
|
def updateStatus(self, status: str):
|
|
self.setText(status)
|
|
|
|
|
|
class ChatBox(QtWidgets.QWidget):
|
|
"""
|
|
Sends chat messages to everyone connected to the same server.
|
|
"""
|
|
|
|
def receiveMessage(self, message: str):
|
|
self.textView.appendPlainText(message)
|
|
|
|
def __init__(self, parent, mainWindow):
|
|
super().__init__(parent=parent)
|
|
|
|
self.mainWindow = mainWindow
|
|
self.setMinimumWidth(500)
|
|
self.setMaximumWidth(500)
|
|
|
|
self.chatName = getuser() + ": "
|
|
|
|
chatLayout = QtWidgets.QGridLayout()
|
|
self.setLayout(chatLayout)
|
|
|
|
chatLabel = QtWidgets.QLabel('Project Collaboration Chat')
|
|
chatLabel.setStyleSheet(Stylesheets.DOCK_BAR_LABEL)
|
|
chatLabel.setAlignment(QtCore.Qt.AlignCenter)
|
|
self.textView = QtWidgets.QPlainTextEdit()
|
|
self.textView.setReadOnly(True)
|
|
self.textSendBox = QtWidgets.QLineEdit()
|
|
self.textSendBox.setPlaceholderText("Type a message to send...")
|
|
self.textSendButton = QtWidgets.QPushButton(" Send ")
|
|
self.textSendButton.clicked.connect(self.sendMessage)
|
|
|
|
chatLayout.addWidget(chatLabel, 0, 0, 1, 2)
|
|
chatLayout.addWidget(self.textView, 1, 0, 1, 2)
|
|
chatLayout.addWidget(self.textSendBox, 2, 0)
|
|
chatLayout.addWidget(self.textSendButton, 2, 1)
|
|
|
|
def sendMessage(self):
|
|
self.mainWindow.sendChatMessage(self.chatName + self.textSendBox.text())
|
|
self.receiveMessage(self.chatName + self.textSendBox.text())
|
|
self.textSendBox.setText("")
|
|
|
|
|
|
class LoggingUpdateThread(QtCore.QThread):
|
|
loggingSignal = QtCore.Signal(str)
|
|
|
|
def __init__(self, messageHandler):
|
|
super().__init__()
|
|
self.messageHandler = messageHandler
|
|
|
|
def run(self):
|
|
while True:
|
|
if not self.messageHandler.logQueue.empty():
|
|
try:
|
|
logMsg = self.messageHandler.logQueue.get().getMessage()
|
|
self.loggingSignal.emit(logMsg)
|
|
except queue.Empty:
|
|
pass
|
|
else:
|
|
sleep(0.25)
|