Wed, 05 Sep 2018 19:52:30 +0200
MqttConnectionProfilesDialog: continued implementing the connections profile dialog.
--- a/MqttMonitor/MqttConnectionProfilesDialog.py Tue Sep 04 19:42:24 2018 +0200 +++ b/MqttMonitor/MqttConnectionProfilesDialog.py Wed Sep 05 19:52:30 2018 +0200 @@ -11,11 +11,16 @@ import collections -from PyQt5.QtCore import pyqtSlot -from PyQt5.QtWidgets import QDialog, QAbstractButton, QListWidgetItem +from PyQt5.QtCore import pyqtSlot, Qt, QUuid +from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton, \ + QListWidgetItem, QInputDialog, QLineEdit + +from E5Gui import E5MessageBox from .Ui_MqttConnectionProfilesDialog import Ui_MqttConnectionProfilesDialog +import UI.PixmapCache + class MqttConnectionProfilesDialog(QDialog, Ui_MqttConnectionProfilesDialog): """ @@ -39,68 +44,133 @@ super(MqttConnectionProfilesDialog, self).__init__(parent) self.setupUi(self) + self.__client = client + self.__profiles = collections.defaultdict(self.__defaultProfile) self.__profiles.update(profiles) + + self.plusButton.setIcon(UI.PixmapCache.getIcon("plus.png")) + self.minusButton.setIcon(UI.PixmapCache.getIcon("minus.png")) + + self.__populateProfilesList() + + if len(self.__profiles) == 0: + self.minusButton.setEnabled(False) + + self.__updateApplyButton() + + self.profileTabWidget.setCurrentIndex(0) @pyqtSlot(str) - def on_profileEdit_textChanged(self, p0): + def on_profileEdit_textChanged(self, name): """ - Slot documentation goes here. + Private slot to handle changes of the profile name. - @param p0 DESCRIPTION + @param name name of the profile @type str """ - # TODO: not implemented yet - raise NotImplementedError + self.__updateApplyButton() @pyqtSlot(QAbstractButton) def on_profileButtonBox_clicked(self, button): """ - Slot documentation goes here. + Private slot handling presses of the profile buttons. - @param button DESCRIPTION + @param button reference to the pressed button @type QAbstractButton """ - # TODO: not implemented yet - raise NotImplementedError + if button == self.profileButtonBox.button(QDialogButtonBox.Apply): + currentProfile = self.__applyProfile() + self.__populateProfilesList(currentProfile) + + # TODO: not implemented other paths @pyqtSlot(QListWidgetItem, QListWidgetItem) def on_profilesList_currentItemChanged(self, current, previous): """ - Slot documentation goes here. + Private slot to handle a change of the current profile. - @param current DESCRIPTION + @param current new current item @type QListWidgetItem - @param previous DESCRIPTION + @param previous previous current item @type QListWidgetItem """ - # TODO: not implemented yet - raise NotImplementedError + self.minusButton.setEnabled(current is not None) + if current: + profileName = current.text() + self.__populateProfile(profileName) @pyqtSlot() def on_plusButton_clicked(self): """ - Slot documentation goes here. + Private slot to add a new empty profile entry. """ - # TODO: not implemented yet - raise NotImplementedError + profileName, ok = QInputDialog.getText( + self, + self.tr("New Connection Profile"), + self.tr("Enter name for the new Connection Profile:"), + QLineEdit.Normal) + if ok and bool(profileName) and profileName not in self.__profiles: + itm = QListWidgetItem(profileName, self.profilesList) + self.profilesList.setCurrentItem(itm) + self.brokerAddressEdit.setFocus(Qt.OtherFocusReason) @pyqtSlot() def on_minusButton_clicked(self): """ - Slot documentation goes here. + Private slot to delete the selected entry. """ - # TODO: not implemented yet - raise NotImplementedError + itm = self.profilesList.currentItem() + if itm: + profileName = itm.text() + yes = E5MessageBox.yesNo( + self, + self.tr("Delete Connection Profile"), + self.tr("""<p>Shall the Connection Profile <b>{0}</b>""" + """ really be deleted?</p>""").format(profileName) + ) + if yes: + del self.__profiles[profileName] + self.__populateProfilesList() def getProfiles(self): """ Public method to return a dictionary of profiles. - @return dictionary containing the defined connection profiles + @return dictionary containing dictionaries containing the defined + connection profiles. Each entry have the keys "BrokerAddress", + "BrokerPort", "ClientId", "Keepalive", "CleanSession", "Username", + "Password", "WillTopic", "WillMessage", "WillQos", "WillRetain". @rtype dict """ - return {} + profilesDict = {} + profilesDict.update(self.__profiles) + return profilesDict + + def __applyProfile(self): + """ + Private method to apply the entered data to the list of profiles. + + @return name of the applied profile + @rtype str + """ + profileName = self.profileEdit.text() + profile = { + "BrokerAddress": self.brokerAddressEdit.text(), + "BrokerPort": self.brokerPortSpinBox.value(), + "ClientId": self.clientIdEdit.text(), + "Keepalive": self.keepaliveSpinBox.value(), + "CleanSession": self.cleanSessionCheckBox.isChecked(), + "Username": self.usernameEdit.text(), + "Password": self.passwordEdit.text(), + "WillTopic": self.willTopicEdit.text(), + "WillMessage": self.willMessageEdit.toPlainText(), + "WillQos": self.willQosSpinBox.value(), + "WillRetain": self.willRetainCheckBox.isChecked(), + } + self.__profiles[profileName] = profile + + return profileName def __defaultProfile(self): """ @@ -114,3 +184,77 @@ defaultProfile["BrokerPort"] = 1883 return defaultProfile + + def __populateProfilesList(self, currentProfile=""): + """ + Private method to populate the list of defined profiles. + + @param currentProfile name of the current profile + @type str + """ + if not currentProfile: + currentItem = self.profilesList.currentItem() + if currentItem: + currentProfile = currentItem.text() + + self.profilesList.clear() + self.profilesList.addItems(sorted(self.__profiles.keys())) + + if currentProfile: + items = self.profilesList.findItems( + currentProfile, Qt.MatchExactly) + if items: + self.profilesList.setCurrentItem(items[0]) + + def __populateProfile(self, profileName): + """ + Private method to populate the profile data entry fields. + + @param profileName name of the profile to get data from + @type str + """ + if profileName: + profile = self.__profiles[profileName] + else: + profile = self.__defaultProfile() + + self.profileEdit.setText(profileName) + self.brokerAddressEdit.setText(profile["BrokerAddress"]) + self.brokerPortSpinBox.setValue(profile["BrokerPort"]) + self.clientIdEdit.setText(profile["ClientId"]) + self.keepaliveSpinBox.setValue(profile["Keepalive"]) + self.cleanSessionCheckBox.setChecked(profile["CleanSession"]) + self.usernameEdit.setText(profile["Username"]) + self.passwordEdit.setText(profile["Password"]) + self.willTopicEdit.setText(profile["WillTopic"]) + self.willMessageEdit.setPlainText(profile["WillMessage"]) + self.willQosSpinBox.setValue(profile["WillQos"]) + self.willRetainCheckBox.setChecked(profile["WillRetain"]) + + self.__updateApplyButton() + + def __updateApplyButton(self): + """ + Private method to set the state of the Apply button. + """ + enable = (bool(self.profileEdit.text()) and + bool(self.brokerAddressEdit.text())) + self.profileButtonBox.button(QDialogButtonBox.Apply).setEnabled(enable) + + @pyqtSlot(str) + def on_brokerAddressEdit_textChanged(self, address): + """ + Private slot handling a change of the broker address. + + @param address broker address + @type str + """ + self.__updateApplyButton() + + @pyqtSlot() + def on_generateIdButton_clicked(self): + """ + Private slot to generate a client ID. + """ + uuid = QUuid.createUuid() + self.clientIdEdit.setText(uuid.toString(QUuid.WithoutBraces))
--- a/MqttMonitor/MqttConnectionProfilesDialog.ui Tue Sep 04 19:42:24 2018 +0200 +++ b/MqttMonitor/MqttConnectionProfilesDialog.ui Wed Sep 05 19:52:30 2018 +0200 @@ -199,7 +199,7 @@ </layout> </item> <item> - <widget class="QTabWidget" name="tabWidget"> + <widget class="QTabWidget" name="profileTabWidget"> <property name="currentIndex"> <number>0</number> </property> @@ -382,7 +382,7 @@ <item> <widget class="QDialogButtonBox" name="profileButtonBox"> <property name="standardButtons"> - <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Reset</set> + <set>QDialogButtonBox::Apply|QDialogButtonBox::Reset|QDialogButtonBox::RestoreDefaults</set> </property> </widget> </item> @@ -418,7 +418,7 @@ <tabstop>brokerPortSpinBox</tabstop> <tabstop>clientIdEdit</tabstop> <tabstop>generateIdButton</tabstop> - <tabstop>tabWidget</tabstop> + <tabstop>profileTabWidget</tabstop> <tabstop>keepaliveSpinBox</tabstop> <tabstop>cleanSessionCheckBox</tabstop> <tabstop>usernameEdit</tabstop>
--- a/MqttMonitor/MqttMonitorWidget.py Tue Sep 04 19:42:24 2018 +0200 +++ b/MqttMonitor/MqttMonitorWidget.py Wed Sep 05 19:52:30 2018 +0200 @@ -16,6 +16,7 @@ import os import collections +import copy from PyQt5.QtCore import pyqtSlot, QTimer from PyQt5.QtGui import QTextCursor @@ -303,10 +304,7 @@ @param host host name of the broker @type str """ - if not self.__connectedToBroker and not host: - self.connectButton.setEnabled(False) - else: - self.connectButton.setEnabled(True) + self.__setConnectButtonState() @pyqtSlot() def on_brokerConnectionOptionsButton_clicked(self): @@ -315,15 +313,14 @@ dialog to edit connection profiles. """ if self.__connectionModeProfile: - # TODO: implement this path from .MqttConnectionProfilesDialog import \ MqttConnectionProfilesDialog dlg = MqttConnectionProfilesDialog( self.__client, self.__plugin.getPreferences("BrokerProfiles"), parent=self) if dlg.exec_() == QDialog.Accepted: - profiles = dlg.getProfiles() - self.__plugin.setPreferences("BrokerProfiles", profiles) + profilesDict = dlg.getProfiles() + self.__plugin.setPreferences("BrokerProfiles", profilesDict) self.__populateProfileComboBox() else: from .MqttConnectionOptionsDialog import \ @@ -342,8 +339,7 @@ self.__client.disconnectFromServer() else: if self.__connectionModeProfile: - # TODO: implement this path - pass + self.__profileConnectToBroker else: self.__directConnectToBroker() @@ -509,6 +505,8 @@ # step 2a: populate the broker name list self.brokerComboBox.addItems([b[0].strip() for b in brokerList]) + self.__setConnectButtonState() + # step 2b: populate the broker ports list if brokerList: currentPort = brokerList[0][1] @@ -530,6 +528,8 @@ self.profileComboBox.clear() self.profileComboBox.addItems(sorted(profilesDict.keys())) + + self.__setConnectButtonState() def __updateUnsubscribeTopicComboBox(self): """ @@ -654,8 +654,19 @@ os.path.join("MqttMonitor", "icons", "quickopen.png"))) self.profileComboBox.setVisible(profileMode) - self.brokerComboBox.setVisible(not profileMode) - self.brokerPortComboBox.setVisible(not profileMode) + self.brokerConnectionWidget.setVisible(not profileMode) + self.__setConnectButtonState() + + def __setConnectButtonState(self): + """ + Private method to set the enabled state of the connect button. + """ + if self.__connectionModeProfile: + self.connectButton.setEnabled( + bool(self.profileComboBox.currentText())) + else: + self.connectButton.setEnabled( + bool(self.brokerComboBox.currentText())) def __directConnectToBroker(self): """ @@ -682,5 +693,10 @@ """ profileName = self.profileComboBox.currentText() if profileName: - # TODO: implement connect by profile name - pass + profilesDict = self.__plugin.getPreferences("BrokerProfiles") + profile = copy.copy(profilesDict[profileName]) # play it save + host = profile["BrokerAddress"] + port = profile["BrokerPort"] + + self.__client.connectToServerWithOptions(host, port=port, + options=profile)
--- a/MqttMonitor/MqttMonitorWidget.ui Tue Sep 04 19:42:24 2018 +0200 +++ b/MqttMonitor/MqttMonitorWidget.ui Wed Sep 05 19:52:30 2018 +0200 @@ -48,49 +48,80 @@ </widget> </item> <item row="0" column="1"> - <widget class="QComboBox" name="profileComboBox"> - <property name="toolTip"> - <string>Select the profile to be used to connect to the broker</string> + <layout class="QHBoxLayout" name="horizontalLayout_15"> + <property name="spacing"> + <number>0</number> </property> - </widget> + <item> + <widget class="QComboBox" name="profileComboBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Select the profile to be used to connect to the broker</string> + </property> + </widget> + </item> + <item> + <widget class="QWidget" name="brokerConnectionWidget" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout_14"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="E5ClearableComboBox" name="brokerComboBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Enter the host name of the broker</string> + </property> + <property name="editable"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="brokerPortComboBox"> + <property name="toolTip"> + <string>Enter the broker port to connect to</string> + </property> + <property name="editable"> + <bool>true</bool> + </property> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToContents</enum> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> </item> <item row="0" column="2"> - <widget class="E5ClearableComboBox" name="brokerComboBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="toolTip"> - <string>Enter the host name of the broker</string> - </property> - <property name="editable"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="0" column="3"> - <widget class="QComboBox" name="brokerPortComboBox"> - <property name="toolTip"> - <string>Enter the broker port to connect to</string> - </property> - <property name="editable"> - <bool>true</bool> - </property> - <property name="sizeAdjustPolicy"> - <enum>QComboBox::AdjustToContents</enum> - </property> - </widget> - </item> - <item row="0" column="4"> <widget class="QToolButton" name="brokerConnectionOptionsButton"> <property name="toolTip"> <string>Press to open a dialog to enter connection options</string> </property> </widget> </item> - <item row="0" column="5"> + <item row="0" column="3"> <widget class="QToolButton" name="connectButton"> <property name="toolTip"> <string>Press to connect to/disconnect from the broker</string> @@ -100,7 +131,7 @@ </property> </widget> </item> - <item row="1" column="0" colspan="6"> + <item row="1" column="0" colspan="4"> <widget class="QLabel" name="brokerStatusLabel"> <property name="wordWrap"> <bool>true</bool>
--- a/PluginMqttMonitor.py Tue Sep 04 19:42:24 2018 +0200 +++ b/PluginMqttMonitor.py Wed Sep 05 19:52:30 2018 +0200 @@ -95,6 +95,7 @@ self.__defaults = { "RecentBrokersWithPort": "[]", # JSON formatted empty list "BrokerProfiles": "{}", # JSON formatted empty dict + # __IGNORE_WARNING_M613__ } self.__translator = None