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 |
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() |
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. |
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() |
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) |