MqttMonitor/MqttMonitorWidget.py

branch
eric7
changeset 102
70b8858199f5
parent 101
0eae5f616154
child 103
5fe4f179975f
equal deleted inserted replaced
101:0eae5f616154 102:70b8858199f5
10 import os 10 import os
11 import collections 11 import collections
12 import copy 12 import copy
13 import contextlib 13 import contextlib
14 14
15 from PyQt6.QtCore import pyqtSlot, Qt, QTimer, QFileInfo 15 from PyQt6.QtCore import pyqtSlot, Qt, QTimer, QFileInfo, QPoint
16 from PyQt6.QtGui import QFont, QTextCursor, QBrush, QColor 16 from PyQt6.QtGui import QFont, QTextCursor, QBrush, QColor
17 from PyQt6.QtWidgets import QWidget, QDialog 17 from PyQt6.QtWidgets import QWidget, QDialog, QMenu
18 18
19 from EricWidgets import EricMessageBox, EricFileDialog 19 from EricWidgets import EricMessageBox, EricFileDialog
20 from EricWidgets.EricPathPicker import EricPathPickerModes 20 from EricWidgets.EricPathPicker import EricPathPickerModes
21 21
22 from .Ui_MqttMonitorWidget import Ui_MqttMonitorWidget 22 from .Ui_MqttMonitorWidget import Ui_MqttMonitorWidget
73 self.__messagesTopicFormat = self.messagesEdit.currentCharFormat() 73 self.__messagesTopicFormat = self.messagesEdit.currentCharFormat()
74 self.__messagesTopicFormat.setFontWeight(QFont.Weight.Bold) 74 self.__messagesTopicFormat.setFontWeight(QFont.Weight.Bold)
75 self.__messagesQosFormat = self.messagesEdit.currentCharFormat() 75 self.__messagesQosFormat = self.messagesEdit.currentCharFormat()
76 self.__messagesQosFormat.setFontItalic(True) 76 self.__messagesQosFormat.setFontItalic(True)
77 77
78 self.__propertiesFormat = self.propertiesEdit.currentCharFormat()
79 self.__propertiesTopicFormat = self.propertiesEdit.currentCharFormat()
80 self.__propertiesTopicFormat.setFontWeight(QFont.Weight.Bold)
81 self.__propertiesNameFormat = self.propertiesEdit.currentCharFormat()
82 self.__propertiesNameFormat.setFontItalic(True)
83
78 self.messagesSearchWidget.attachTextEdit(self.messagesEdit) 84 self.messagesSearchWidget.attachTextEdit(self.messagesEdit)
79 self.messagesSearchWidget.setWidthForHeight(False) 85 self.messagesSearchWidget.setWidthForHeight(False)
80 86
81 self.__isAlternate = False 87 self.__isMessageAlternate = False
88 self.__isPropertiesAlternate = False
82 89
83 for logLevel in (MqttClient.LogDisabled, 90 for logLevel in (MqttClient.LogDisabled,
84 MqttClient.LogDebug, 91 MqttClient.LogDebug,
85 MqttClient.LogInfo, 92 MqttClient.LogInfo,
86 MqttClient.LogNotice, 93 MqttClient.LogNotice,
129 self.__populateBrokerComboBoxes() 136 self.__populateBrokerComboBoxes()
130 self.brokerStatusLabel.hide() 137 self.brokerStatusLabel.hide()
131 138
132 self.subscribeButton.setIcon(UI.PixmapCache.getIcon("plus")) 139 self.subscribeButton.setIcon(UI.PixmapCache.getIcon("plus"))
133 self.subscribeButton.setEnabled(False) 140 self.subscribeButton.setEnabled(False)
141 self.subscribePropertiesButton.setIcon(
142 UI.PixmapCache.getIcon("listSelection"))
143 self.subscribePropertiesButton.setEnabled(False)
144 self.subscribePropertiesButton.setVisible(False)
145
134 self.unsubscribeButton.setIcon(UI.PixmapCache.getIcon("minus")) 146 self.unsubscribeButton.setIcon(UI.PixmapCache.getIcon("minus"))
147 self.unsubscribeButton.setEnabled(False)
148 self.unsubscribePropertiesButton.setIcon(
149 UI.PixmapCache.getIcon("listSelection"))
150 self.unsubscribePropertiesButton.setEnabled(False)
151 self.unsubscribePropertiesButton.setVisible(False)
152
153 self.__initPropertiesEditMenu()
135 154
136 self.__subscribedTopics = [] 155 self.__subscribedTopics = []
137 self.__topicQueue = {} 156 self.__topicQueue = {}
138 self.__updateUnsubscribeTopicComboBox() 157 self.__updateUnsubscribeTopicComboBox()
139 158
185 } 204 }
186 205
187 self.__statusLoadValues = collections.defaultdict( 206 self.__statusLoadValues = collections.defaultdict(
188 self.__loadDefaultDictFactory) 207 self.__loadDefaultDictFactory)
189 208
190 #######################################################################
191 ## Slots handling MQTT related signals
192 #######################################################################
193
194 # TODO: make MQTT default protocol version a configuration option 209 # TODO: make MQTT default protocol version a configuration option
195 # (config page) 210 # (config page)
196 def __createClient(self, clientId="", cleanSession=None, 211 def __createClient(self, clientId="", cleanSession=None,
197 protocol=MqttProtocols.MQTTv311): 212 protocol=MqttProtocols.MQTTv311):
198 """ 213 """
227 242
228 client.connectTimeout.connect(self.__connectTimeout) 243 client.connectTimeout.connect(self.__connectTimeout)
229 244
230 return client 245 return client
231 246
247 def __initPropertiesEditMenu(self):
248 """
249 Private method to create the properties output context menu.
250 """
251 self.__propertiesEditMenu = QMenu(self)
252 self.__copyPropertiesAct = self.__propertiesEditMenu.addAction(
253 UI.PixmapCache.getIcon("editCopy"),
254 self.tr("Copy"), self.propertiesEdit.copy)
255 self.__propertiesEditMenu.addSeparator()
256 self.__selectAllPropertiesAct = self.__propertiesEditMenu.addAction(
257 UI.PixmapCache.getIcon("editSelectAll"),
258 self.tr("Select All"), self.propertiesEdit.selectAll)
259 self.__propertiesEditMenu.addSeparator()
260 self.__clearPropertiesAct = self.__propertiesEditMenu.addAction(
261 UI.PixmapCache.getIcon("editDelete"),
262 self.tr("Clear"), self.propertiesEdit.clear)
263
264 self.propertiesEdit.copyAvailable.connect(
265 self.__copyPropertiesAct.setEnabled)
266
267 self.__copyPropertiesAct.setEnabled(False)
268
232 ####################################################################### 269 #######################################################################
233 ## Slots handling MQTT related signals 270 ## Slots handling MQTT related signals
234 ####################################################################### 271 #######################################################################
235 272
236 @pyqtSlot(dict, int) 273 @pyqtSlot(dict, int)
237 @pyqtSlot(dict, int, int) 274 @pyqtSlot(dict, int, int, dict)
238 def __brokerConnected(self, flags, rc, packetType=None): 275 def __brokerConnected(self, flags, rc, packetType=None, properties=None):
239 """ 276 """
240 Private slot to handle being connected to a broker. 277 Private slot to handle being connected to a broker.
241 278
242 @param flags flags set for the connection 279 @param flags flags set for the connection
243 @type dict 280 @type dict
244 @param rc CONNACK result code or MQTTv5 reason code 281 @param rc CONNACK result code or MQTTv5 reason code
245 @type int 282 @type int
246 @param packetType packet type as reported by the client 283 @param packetType packet type as reported by the client
247 @type int 284 @type int
285 @param properties dictionary containing the received connection
286 properties
287 @type dict
248 """ 288 """
249 self.brokerStatusLabel.hide() 289 self.brokerStatusLabel.hide()
250 290
251 # TODO: add support for flags[‘session present’] 291 # TODO: add support for flags[‘session present’]
252 if rc == 0: 292 if rc == 0:
253 self.__connectedToBroker = True 293 self.__connectedToBroker = True
254 self.__connectionOptions = None 294 self.__connectionOptions = None
255 295
256 msg = ( 296 msg = (
257 mqttReasonCode(rc, packetType) 297 mqttReasonCode(rc, packetType)
258 if packetType is not None else 298 if packetType is not None else
259 mqttConnackMessage(rc) 299 mqttConnackMessage(rc)
260 ) 300 )
261 self.__flashBrokerStatusLabel(msg) 301 self.__flashBrokerStatusLabel(msg)
302
303 if properties:
304 self.__showProperties("Connect", properties)
262 305
263 self.connectButton.setEnabled(True) 306 self.connectButton.setEnabled(True)
264 if rc == 0: 307 if rc == 0:
265 self.__connectedToBroker = True 308 self.__connectedToBroker = True
266 self.__connectionOptions = None 309 self.__connectionOptions = None
267 310
268 self.connectButton.setIcon( 311 self.connectButton.setIcon(
269 UI.PixmapCache.getIcon("ircDisconnect")) 312 UI.PixmapCache.getIcon("ircDisconnect"))
270 313
271 self.subscribeGroup.setEnabled(True) 314 self.subscribeGroup.setEnabled(True)
315 self.subscribePropertiesButton.setVisible(
316 self.__client.getProtocol() == MqttProtocols.MQTTv5)
272 self.unsubscribeGroup.setEnabled(True) 317 self.unsubscribeGroup.setEnabled(True)
318 self.unsubscribePropertiesButton.setVisible(
319 self.__client.getProtocol() == MqttProtocols.MQTTv5)
273 self.publishGroup.setEnabled(True) 320 self.publishGroup.setEnabled(True)
274 self.brokerStatusButton.setEnabled(True) 321 self.brokerStatusButton.setEnabled(True)
275 322
276 self.__statusLoadValues.clear() 323 self.__statusLoadValues.clear()
277 self.__clearBrokerStatusLabels() 324 self.__clearBrokerStatusLabels()
323 self.__topicQueue = {} 370 self.__topicQueue = {}
324 self.__updateUnsubscribeTopicComboBox() 371 self.__updateUnsubscribeTopicComboBox()
325 self.__updatePublishTopicComboBox() 372 self.__updatePublishTopicComboBox()
326 373
327 self.subscribeGroup.setEnabled(False) 374 self.subscribeGroup.setEnabled(False)
375 self.subscribePropertiesButton.setVisible(False)
328 self.unsubscribeGroup.setEnabled(False) 376 self.unsubscribeGroup.setEnabled(False)
377 self.unsubscribePropertiesButton.setVisible(False)
329 self.publishGroup.setEnabled(False) 378 self.publishGroup.setEnabled(False)
330 self.brokerStatusButton.setEnabled(False) 379 self.brokerStatusButton.setEnabled(False)
331 380
332 self.__statusLoadValues.clear() 381 self.__statusLoadValues.clear()
333 382
371 if self.followLogMessagesCheckBox.isChecked(): 420 if self.followLogMessagesCheckBox.isChecked():
372 self.logEdit.ensureCursorVisible() 421 self.logEdit.ensureCursorVisible()
373 else: 422 else:
374 self.logEdit.verticalScrollBar().setValue(scrollbarValue) 423 self.logEdit.verticalScrollBar().setValue(scrollbarValue)
375 424
376 # TODO: add support for MQTT v5 properties
377 @pyqtSlot(str, bytes, int, bool) 425 @pyqtSlot(str, bytes, int, bool)
378 @pyqtSlot(str, bytes, int, bool, dict) 426 @pyqtSlot(str, bytes, int, bool, dict)
379 def __messageReceived(self, topic, payload, qos, retain, properties=None): 427 def __messageReceived(self, topic, payload, qos, retain, properties=None):
380 """ 428 """
381 Private slot to handle the receipt of a message. 429 Private slot to handle the receipt of a message.
404 Private slot to handle a message being published. 452 Private slot to handle a message being published.
405 453
406 @param mid ID of the published message 454 @param mid ID of the published message
407 @type int 455 @type int
408 """ 456 """
409 # TODO: check this 'pass' statement 457 # nothing to show for this
410 pass 458 pass
411 459
412 @pyqtSlot(int) 460 @pyqtSlot(int)
413 def __topicSubscribed(self, mid): 461 def __topicSubscribed(self, mid):
414 """ 462 """
424 self.subscribeTopicEdit.clear() 472 self.subscribeTopicEdit.clear()
425 473
426 self.__updateUnsubscribeTopicComboBox() 474 self.__updateUnsubscribeTopicComboBox()
427 self.__updatePublishTopicComboBox() 475 self.__updatePublishTopicComboBox()
428 476
429 @pyqtSlot(int, list) 477 @pyqtSlot(int, list, dict)
430 def __topicSubscribedV5(self, mid, reasonCodes): 478 def __topicSubscribedV5(self, mid, reasonCodes, properties):
431 """ 479 """
432 Private slot to handle being subscribed to topics (MQTT v5). 480 Private slot to handle being subscribed to topics (MQTT v5).
433 481
434 @param mid ID of the subscribe request 482 @param mid ID of the subscribe request
435 @type int 483 @type int
436 @param reasonCodes list of reason codes, one for each topic 484 @param reasonCodes list of reason codes, one for each topic
437 @type list of ReasonCodes 485 @type list of ReasonCodes
486 @param properties dictionary containing the received subscribe
487 properties
488 @type dict
438 """ 489 """
439 msg = mqttReasonCode(reasonCodes[0].value, reasonCodes[0].packetType) 490 msg = mqttReasonCode(reasonCodes[0].value, reasonCodes[0].packetType)
440 self.__flashBrokerStatusLabel(msg) 491 self.__flashBrokerStatusLabel(msg)
492
493 if properties:
494 self.__showProperties("Subscribe", properties)
495
441 self.__topicSubscribed(mid) 496 self.__topicSubscribed(mid)
442 497
443 @pyqtSlot(int) 498 @pyqtSlot(int)
444 def __topicUnsubscribed(self, mid): 499 def __topicUnsubscribed(self, mid):
445 """ 500 """
454 with contextlib.suppress(ValueError): 509 with contextlib.suppress(ValueError):
455 self.__subscribedTopics.remove(topic) 510 self.__subscribedTopics.remove(topic)
456 self.__updateUnsubscribeTopicComboBox() 511 self.__updateUnsubscribeTopicComboBox()
457 self.__updatePublishTopicComboBox() 512 self.__updatePublishTopicComboBox()
458 513
459 @pyqtSlot(int, int, int) 514 @pyqtSlot(int, int, int, dict)
460 def __topicUnsubscribedV5(self, mid, rc, packetType): 515 def __topicUnsubscribedV5(self, mid, rc, packetType, properties):
461 """ 516 """
462 Private slot to handle being unsubscribed to topics (MQTT v5). 517 Private slot to handle being unsubscribed to topics (MQTT v5).
463 518
464 @param mid ID of the subscribe request 519 @param mid ID of the subscribe request
465 @type int 520 @type int
466 @param rc MQTTv5 reason code 521 @param rc MQTTv5 reason code
467 @type int 522 @type int
468 @param packetType packet type as reported by the client 523 @param packetType packet type as reported by the client
469 @type int 524 @type int
525 @param properties dictionary containing the received subscribe
526 properties
527 @type dict
470 """ 528 """
471 msg = mqttReasonCode(rc, packetType) 529 msg = mqttReasonCode(rc, packetType)
472 self.__flashBrokerStatusLabel(msg) 530 self.__flashBrokerStatusLabel(msg)
531
532 if properties:
533 self.__showProperties("Subscribe", properties)
534
473 self.__topicUnsubscribed(mid) 535 self.__topicUnsubscribed(mid)
474 536
475 ####################################################################### 537 #######################################################################
476 ## Slots handling UI interactions 538 ## Slots handling UI interactions
477 ####################################################################### 539 #######################################################################
563 if self.__connectionModeProfile: 625 if self.__connectionModeProfile:
564 self.__profileConnectToBroker() 626 self.__profileConnectToBroker()
565 else: 627 else:
566 self.__directConnectToBroker() 628 self.__directConnectToBroker()
567 629
630 @pyqtSlot()
631 def on_subscribePropertiesButton_clicked(self):
632 """
633 Private slot to edit the subscribe user properties.
634 """
635 topic = self.subscribeTopicEdit.text()
636 self.__editProperties(
637 "subscribe",
638 self.tr("SUBSCRIBE: User Properties for '{0}'").format(topic),
639 topic
640 )
641
568 @pyqtSlot(str) 642 @pyqtSlot(str)
569 def on_subscribeTopicEdit_textChanged(self, topic): 643 def on_subscribeTopicEdit_textChanged(self, topic):
570 """ 644 """
571 Private slot to handle a change of the entered topic. 645 Private slot to handle a change of the entered topic.
572 646
573 @param topic entered topic text 647 @param topic entered topic text
574 @type str 648 @type str
575 """ 649 """
576 self.subscribeButton.setEnabled(bool(topic)) 650 self.subscribeButton.setEnabled(bool(topic))
651 self.subscribePropertiesButton.setEnabled(bool(topic))
577 652
578 @pyqtSlot() 653 @pyqtSlot()
579 def on_subscribeTopicEdit_returnPressed(self): 654 def on_subscribeTopicEdit_returnPressed(self):
580 """ 655 """
581 Private slot handling the user pressing the return button to subscribe 656 Private slot handling the user pressing the return button to subscribe
596 self, 671 self,
597 self.tr("Subscribe to Topic"), 672 self.tr("Subscribe to Topic"),
598 self.tr("Subscriptions to the Status topic '$SYS' shall" 673 self.tr("Subscriptions to the Status topic '$SYS' shall"
599 " be done on the 'Status' tab.")) 674 " be done on the 'Status' tab."))
600 else: 675 else:
601 self.__topicQueue[ 676 properties = (
602 self.__client.subscribe(topic, qos)[1]] = topic 677 self.__plugin.getPreferences("SubscribeProperties")
678 .get(topic, [])
679 if self.__client.getProtocol() == MqttProtocols.MQTTv5 else
680 None
681 )
682 result, mid = self.__client.subscribe(
683 topic, qos=qos, properties=properties)
684 self.__topicQueue[mid] = topic
685
686 @pyqtSlot()
687 def on_unsubscribePropertiesButton_clicked(self):
688 """
689 Private slot to edit the unsubscribe user properties.
690 """
691 topic = self.unsubscribeTopicComboBox.currentText()
692 self.__editProperties(
693 "unsubscribe",
694 self.tr("UNSUBSCRIBE: User Properties for '{0}'").format(topic),
695 topic
696 )
603 697
604 @pyqtSlot(str) 698 @pyqtSlot(str)
605 def on_unsubscribeTopicComboBox_currentIndexChanged(self, topic): 699 def on_unsubscribeTopicComboBox_currentIndexChanged(self, topic):
606 """ 700 """
607 Private slot to handle the selection of a topic to unsubscribe from. 701 Private slot to handle the selection of a topic to unsubscribe from.
608 702
609 @param topic topic text 703 @param topic topic text
610 @type str 704 @type str
611 """ 705 """
612 self.unsubscribeButton.setEnabled(bool(topic)) 706 self.unsubscribeButton.setEnabled(bool(topic))
707 self.unsubscribePropertiesButton.setEnabled(bool(topic))
613 708
614 @pyqtSlot() 709 @pyqtSlot()
615 def on_unsubscribeButton_clicked(self): 710 def on_unsubscribeButton_clicked(self):
616 """ 711 """
617 Private slot to unsubscribe from the selected topic. 712 Private slot to unsubscribe from the selected topic.
618 """ 713 """
619 topic = self.unsubscribeTopicComboBox.currentText() 714 topic = self.unsubscribeTopicComboBox.currentText()
620 if topic: 715 if topic:
621 self.__topicQueue[ 716 properties = (
622 self.__client.unsubscribe(topic)[1]] = topic 717 self.__plugin.getPreferences("SubscribeProperties")
718 .get(topic, [])
719 if self.__client.getProtocol() == MqttProtocols.MQTTv5 else
720 None
721 )
722 result, mid = self.__client.unsubscribe(
723 topic, properties=properties)
724 self.__topicQueue[mid] = topic
623 725
624 @pyqtSlot(str) 726 @pyqtSlot(str)
625 def on_publishTopicComboBox_editTextChanged(self, topic): 727 def on_publishTopicComboBox_editTextChanged(self, topic):
626 """ 728 """
627 Private slot to handle changes of the publish topic name. 729 Private slot to handle changes of the publish topic name.
671 self.__updatePublishTopicComboBox(resetTopic=False) 773 self.__updatePublishTopicComboBox(resetTopic=False)
672 if self.clearPublishCheckBox.isChecked(): 774 if self.clearPublishCheckBox.isChecked():
673 self.on_publishClearButton_clicked() 775 self.on_publishClearButton_clicked()
674 776
675 @pyqtSlot() 777 @pyqtSlot()
778 def on_publishClearRetainedButton_clicked(self):
779 """
780 Private slot to clear the retained messages for the topic.
781 """
782 topic = self.publishTopicComboBox.currentText()
783
784 msgInfo = self.__client.publish(topic, payload=None, retain=True)
785 if msgInfo.rc == 0:
786 if topic not in self.__publishedTopics:
787 self.__publishedTopics.append(topic)
788 self.__updatePublishTopicComboBox(resetTopic=False)
789
790 @pyqtSlot()
676 def on_publishClearButton_clicked(self): 791 def on_publishClearButton_clicked(self):
677 """ 792 """
678 Private slot to clear the publish data fields. 793 Private slot to clear the publish data fields.
679 """ 794 """
680 self.publishTopicComboBox.clearEditText() 795 self.publishTopicComboBox.clearEditText()
690 805
691 @param path path of the payload file 806 @param path path of the payload file
692 @type str 807 @type str
693 """ 808 """
694 self.publishPayloadEdit.setEnabled(not bool(path)) 809 self.publishPayloadEdit.setEnabled(not bool(path))
810
811 @pyqtSlot(QPoint)
812 def on_propertiesEdit_customContextMenuRequested(self, pos):
813 """
814 Private slot to show the context menu for the properties output.
815
816 @param pos the position of the mouse pointer
817 @type QPoint
818 """
819 self.__propertiesEditMenu.popup(self.propertiesEdit.mapToGlobal(pos))
695 820
696 @pyqtSlot() 821 @pyqtSlot()
697 def on_brokerStatusButton_clicked(self): 822 def on_brokerStatusButton_clicked(self):
698 """ 823 """
699 Private slot to subscribe or unsubscribe the broker status topic. 824 Private slot to subscribe or unsubscribe the broker status topic.
918 """ 1043 """
919 Private method to update the unsubcribe topic combo box. 1044 Private method to update the unsubcribe topic combo box.
920 """ 1045 """
921 self.unsubscribeTopicComboBox.clear() 1046 self.unsubscribeTopicComboBox.clear()
922 self.unsubscribeTopicComboBox.addItems(sorted(self.__subscribedTopics)) 1047 self.unsubscribeTopicComboBox.addItems(sorted(self.__subscribedTopics))
923 self.unsubscribeButton.setEnabled(len(self.__subscribedTopics) > 0) 1048 self.unsubscribeButton.setEnabled(
1049 bool(self.__subscribedTopics))
1050 self.unsubscribePropertiesButton.setEnabled(
1051 bool(self.__subscribedTopics))
924 1052
925 def __updatePublishTopicComboBox(self, resetTopic=True): 1053 def __updatePublishTopicComboBox(self, resetTopic=True):
926 """ 1054 """
927 Private method to update the publish topic combo box. 1055 Private method to update the publish topic combo box.
928 1056
952 @param retain flag indicating a retained message 1080 @param retain flag indicating a retained message
953 @type bool 1081 @type bool
954 @param properties properties sent with the message (MQTT v5) 1082 @param properties properties sent with the message (MQTT v5)
955 @type dict 1083 @type dict
956 """ 1084 """
957 # TODO: add Output for properties
958 scrollbarValue = self.messagesEdit.verticalScrollBar().value() 1085 scrollbarValue = self.messagesEdit.verticalScrollBar().value()
959 1086
960 textCursor = self.messagesEdit.textCursor() 1087 textCursor = self.messagesEdit.textCursor()
961 if not self.messagesEdit.document().isEmpty(): 1088 if not self.messagesEdit.document().isEmpty():
962 textCursor.movePosition(QTextCursor.MoveOperation.End) 1089 textCursor.movePosition(QTextCursor.MoveOperation.End)
963 self.messagesEdit.setTextCursor(textCursor) 1090 self.messagesEdit.setTextCursor(textCursor)
964 self.messagesEdit.insertPlainText("\n") 1091 self.messagesEdit.insertPlainText("\n")
965 1092
966 textBlockFormat = textCursor.blockFormat() 1093 textBlockFormat = textCursor.blockFormat()
967 if self.__isAlternate: 1094 if self.__isMessageAlternate:
968 textBlockFormat.setBackground( 1095 textBlockFormat.setBackground(
969 self.messagesEdit.palette().alternateBase()) 1096 self.messagesEdit.palette().alternateBase())
970 else: 1097 else:
971 textBlockFormat.setBackground( 1098 textBlockFormat.setBackground(
972 self.messagesEdit.palette().base()) 1099 self.messagesEdit.palette().base())
982 1109
983 if retain: 1110 if retain:
984 self.messagesEdit.setCurrentCharFormat(self.__messagesQosFormat) 1111 self.messagesEdit.setCurrentCharFormat(self.__messagesQosFormat)
985 self.messagesEdit.insertPlainText(self.tr("Retained Message\n")) 1112 self.messagesEdit.insertPlainText(self.tr("Retained Message\n"))
986 1113
1114 if properties:
1115 self.messagesEdit.setCurrentCharFormat(self.__messagesTopicFormat)
1116 self.messagesEdit.insertPlainText(self.tr("Properties:\n"))
1117 self.messagesEdit.setCurrentCharFormat(self.__messagesFormat)
1118 for name, value in sorted(properties.items):
1119 self.messagesEdit.insertPlainText(
1120 self.tr("{0}: {1}\n", "property name, property value")
1121 .format(name, value)
1122 )
1123
987 payloadStr = str(payload, encoding="utf-8", errors="replace") 1124 payloadStr = str(payload, encoding="utf-8", errors="replace")
988 self.messagesEdit.setCurrentCharFormat(self.__messagesFormat) 1125 self.messagesEdit.setCurrentCharFormat(self.__messagesFormat)
989 self.messagesEdit.insertPlainText( 1126 self.messagesEdit.insertPlainText(
990 Utilities.filterAnsiSequences(payloadStr)) 1127 Utilities.filterAnsiSequences(payloadStr))
991 1128
992 if self.followMessagesCheckBox.isChecked(): 1129 if self.followMessagesCheckBox.isChecked():
993 self.messagesEdit.ensureCursorVisible() 1130 self.messagesEdit.ensureCursorVisible()
994 else: 1131 else:
995 self.messagesEdit.verticalScrollBar().setValue(scrollbarValue) 1132 self.messagesEdit.verticalScrollBar().setValue(scrollbarValue)
996 1133
997 self.__isAlternate = not self.__isAlternate 1134 self.__isMessageAlternate = not self.__isMessageAlternate
998 1135
999 def __handleBrokerStatusMessage(self, topic, payload): 1136 def __handleBrokerStatusMessage(self, topic, payload):
1000 """ 1137 """
1001 Private method to append a received message to the output. 1138 Private method to handle a status message of the broker.
1002 1139
1003 @param topic topic of the received message 1140 @param topic topic of the received message
1004 @type str 1141 @type str
1005 @param payload payload of the received message 1142 @param payload payload of the received message
1006 @type bytes 1143 @type bytes
1156 cleanSession=connectionProfile["CleanSession"], 1293 cleanSession=connectionProfile["CleanSession"],
1157 protocol=protocol 1294 protocol=protocol
1158 ) 1295 )
1159 self.__client.connectToServerWithOptions( 1296 self.__client.connectToServerWithOptions(
1160 host, port=port, options=connectionProfile) 1297 host, port=port, options=connectionProfile)
1298
1299 def __showProperties(self, typeStr, properties):
1300 """
1301 Private method to display the received properties in the properties
1302 pane.
1303
1304 @param typeStr message type
1305 @type str
1306 @param properties dictionary containing the relevant properties
1307 @type dict
1308 """
1309 textCursor = self.propertiesEdit.textCursor()
1310 if not self.propertiesEdit.document().isEmpty():
1311 textCursor.movePosition(QTextCursor.MoveOperation.End)
1312 self.propertiesEdit.setTextCursor(textCursor)
1313
1314 textBlockFormat = textCursor.blockFormat()
1315 if self.__isPropertiesAlternate:
1316 textBlockFormat.setBackground(
1317 self.propertiesEdit.palette().alternateBase())
1318 else:
1319 textBlockFormat.setBackground(
1320 self.propertiesEdit.palette().base())
1321 textCursor.setBlockFormat(textBlockFormat)
1322 textCursor.movePosition(QTextCursor.MoveOperation.End)
1323 self.propertiesEdit.setTextCursor(textCursor)
1324
1325 self.propertiesEdit.setCurrentCharFormat(self.__propertiesTopicFormat)
1326 self.propertiesEdit.insertPlainText(typeStr + "\n")
1327
1328 for name, value in sorted(properties.items()):
1329 self.propertiesEdit.setCurrentCharFormat(
1330 self.__propertiesNameFormat)
1331 self.propertiesEdit.insertPlainText("{0}: ".format(name))
1332 self.propertiesEdit.setCurrentCharFormat(self.__propertiesFormat)
1333 self.propertiesEdit.insertPlainText("{0}\n".format(str(value)))
1334
1335 self.propertiesEdit.ensureCursorVisible()
1336
1337 self.__isPropertiesAlternate = not self.__isPropertiesAlternate
1338
1339 def __editProperties(self, propertiesType, header, key):
1340 """
1341 Private method to edit user properties of a given type.
1342
1343 @param propertiesType properties type (one of 'subscribe',
1344 'unsubscribe', 'publish')
1345 @type str
1346 @param header header to be shown in the edit dialog
1347 @type str
1348 @param key key to retrieve the right properties
1349 @type str
1350 """
1351 from .MqttUserPropertiesEditor import MqttUserPropertiesEditor
1352
1353 preferencesKey = "{0}Properties".format(propertiesType.capitalize())
1354 properties = self.__plugin.getPreferences(preferencesKey)
1355 dlg = MqttUserPropertiesEditor(header, properties.get(key, []), self)
1356 if dlg.exec() == QDialog.DialogCode.Accepted:
1357 properties[key] = dlg.getProperties()
1358 self.__plugin.setPreferences(preferencesKey, properties)

eric ide

mercurial