MqttConnectionProfilesDialog: continued implementing the connections profile dialog. connection_profiles

Wed, 05 Sep 2018 19:52:30 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Wed, 05 Sep 2018 19:52:30 +0200
branch
connection_profiles
changeset 19
889a7c3c0e63
parent 18
bbfe5866b6aa
child 20
3737a78bb6c5

MqttConnectionProfilesDialog: continued implementing the connections profile dialog.

MqttMonitor/MqttConnectionProfilesDialog.py file | annotate | diff | comparison | revisions
MqttMonitor/MqttConnectionProfilesDialog.ui file | annotate | diff | comparison | revisions
MqttMonitor/MqttMonitorWidget.py file | annotate | diff | comparison | revisions
MqttMonitor/MqttMonitorWidget.ui file | annotate | diff | comparison | revisions
PluginMqttMonitor.py file | annotate | diff | comparison | revisions
--- 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

eric ide

mercurial