MqttMonitor/MqttConnectionProfilesDialog.py

branch
connection_profiles
changeset 23
0b23bd856e43
parent 19
889a7c3c0e63
child 26
ad232a5129cc
equal deleted inserted replaced
22:545979c7dcd4 23:0b23bd856e43
18 from E5Gui import E5MessageBox 18 from E5Gui import E5MessageBox
19 19
20 from .Ui_MqttConnectionProfilesDialog import Ui_MqttConnectionProfilesDialog 20 from .Ui_MqttConnectionProfilesDialog import Ui_MqttConnectionProfilesDialog
21 21
22 import UI.PixmapCache 22 import UI.PixmapCache
23 from Utilities.crypto import pwConvert
23 24
24 25
25 class MqttConnectionProfilesDialog(QDialog, Ui_MqttConnectionProfilesDialog): 26 class MqttConnectionProfilesDialog(QDialog, Ui_MqttConnectionProfilesDialog):
26 """ 27 """
27 Class implementing a dialog to edit the MQTT connection profiles. 28 Class implementing a dialog to edit the MQTT connection profiles.
46 47
47 self.__client = client 48 self.__client = client
48 49
49 self.__profiles = collections.defaultdict(self.__defaultProfile) 50 self.__profiles = collections.defaultdict(self.__defaultProfile)
50 self.__profiles.update(profiles) 51 self.__profiles.update(profiles)
52 self.__profilesChanged = False
51 53
52 self.plusButton.setIcon(UI.PixmapCache.getIcon("plus.png")) 54 self.plusButton.setIcon(UI.PixmapCache.getIcon("plus.png"))
53 self.minusButton.setIcon(UI.PixmapCache.getIcon("minus.png")) 55 self.minusButton.setIcon(UI.PixmapCache.getIcon("minus.png"))
54 56
55 self.__populateProfilesList() 57 self.profileTabWidget.setCurrentIndex(0)
56 58
57 if len(self.__profiles) == 0: 59 if len(self.__profiles) == 0:
58 self.minusButton.setEnabled(False) 60 self.minusButton.setEnabled(False)
59 61
60 self.__updateApplyButton() 62 self.profileFrame.setEnabled(False)
61 63 self.__populatingProfile = False
62 self.profileTabWidget.setCurrentIndex(0) 64 self.__deletingProfile = False
65
66 self.__populateProfilesList()
63 67
64 @pyqtSlot(str) 68 @pyqtSlot(str)
65 def on_profileEdit_textChanged(self, name): 69 def on_profileEdit_textChanged(self, name):
66 """ 70 """
67 Private slot to handle changes of the profile name. 71 Private slot to handle changes of the profile name.
81 """ 85 """
82 if button == self.profileButtonBox.button(QDialogButtonBox.Apply): 86 if button == self.profileButtonBox.button(QDialogButtonBox.Apply):
83 currentProfile = self.__applyProfile() 87 currentProfile = self.__applyProfile()
84 self.__populateProfilesList(currentProfile) 88 self.__populateProfilesList(currentProfile)
85 89
86 # TODO: not implemented other paths 90 elif button == self.profileButtonBox.button(QDialogButtonBox.Reset):
91 self.__resetProfile()
92
93 elif button == self.profileButtonBox.button(
94 QDialogButtonBox.RestoreDefaults):
95 self.__populateProfileDefault()
87 96
88 @pyqtSlot(QListWidgetItem, QListWidgetItem) 97 @pyqtSlot(QListWidgetItem, QListWidgetItem)
89 def on_profilesList_currentItemChanged(self, current, previous): 98 def on_profilesList_currentItemChanged(self, current, previous):
90 """ 99 """
91 Private slot to handle a change of the current profile. 100 Private slot to handle a change of the current profile.
94 @type QListWidgetItem 103 @type QListWidgetItem
95 @param previous previous current item 104 @param previous previous current item
96 @type QListWidgetItem 105 @type QListWidgetItem
97 """ 106 """
98 self.minusButton.setEnabled(current is not None) 107 self.minusButton.setEnabled(current is not None)
108
109 if current is not previous:
110 if not self.__deletingProfile and self.__isChangedProfile():
111 # modified profile belongs to previous
112 yes = E5MessageBox.yesNo(
113 self,
114 self.tr("Changed Connection Profile"),
115 self.tr("""The current profile has unsaved changes."""
116 """ Shall these be saved?"""),
117 icon=E5MessageBox.Warning,
118 yesDefault=True)
119 if yes:
120 self.__applyProfile()
121
99 if current: 122 if current:
100 profileName = current.text() 123 profileName = current.text()
101 self.__populateProfile(profileName) 124 self.__populateProfile(profileName)
125 else:
126 self.__clearProfile()
102 127
103 @pyqtSlot() 128 @pyqtSlot()
104 def on_plusButton_clicked(self): 129 def on_plusButton_clicked(self):
105 """ 130 """
106 Private slot to add a new empty profile entry. 131 Private slot to add a new empty profile entry.
128 self.tr("Delete Connection Profile"), 153 self.tr("Delete Connection Profile"),
129 self.tr("""<p>Shall the Connection Profile <b>{0}</b>""" 154 self.tr("""<p>Shall the Connection Profile <b>{0}</b>"""
130 """ really be deleted?</p>""").format(profileName) 155 """ really be deleted?</p>""").format(profileName)
131 ) 156 )
132 if yes: 157 if yes:
158 self.__deletingProfile = True
133 del self.__profiles[profileName] 159 del self.__profiles[profileName]
160 self.__profilesChanged = True
134 self.__populateProfilesList() 161 self.__populateProfilesList()
162 self.__deletingProfile = False
163
164 self.profilesList.setFocus(Qt.OtherFocusReason)
135 165
136 def getProfiles(self): 166 def getProfiles(self):
137 """ 167 """
138 Public method to return a dictionary of profiles. 168 Public method to return a dictionary of profiles.
139 169
160 "BrokerPort": self.brokerPortSpinBox.value(), 190 "BrokerPort": self.brokerPortSpinBox.value(),
161 "ClientId": self.clientIdEdit.text(), 191 "ClientId": self.clientIdEdit.text(),
162 "Keepalive": self.keepaliveSpinBox.value(), 192 "Keepalive": self.keepaliveSpinBox.value(),
163 "CleanSession": self.cleanSessionCheckBox.isChecked(), 193 "CleanSession": self.cleanSessionCheckBox.isChecked(),
164 "Username": self.usernameEdit.text(), 194 "Username": self.usernameEdit.text(),
165 "Password": self.passwordEdit.text(), 195 "Password": pwConvert(self.passwordEdit.text(), encode=True),
166 "WillTopic": self.willTopicEdit.text(), 196 "WillTopic": self.willTopicEdit.text(),
167 "WillMessage": self.willMessageEdit.toPlainText(), 197 "WillMessage": self.willMessageEdit.toPlainText(),
168 "WillQos": self.willQosSpinBox.value(), 198 "WillQos": self.willQosSpinBox.value(),
169 "WillRetain": self.willRetainCheckBox.isChecked(), 199 "WillRetain": self.willRetainCheckBox.isChecked(),
170 } 200 }
171 self.__profiles[profileName] = profile 201 self.__profiles[profileName] = profile
202 self.__profilesChanged = True
172 203
173 return profileName 204 return profileName
174 205
175 def __defaultProfile(self): 206 def __defaultProfile(self):
176 """ 207 """
203 if currentProfile: 234 if currentProfile:
204 items = self.profilesList.findItems( 235 items = self.profilesList.findItems(
205 currentProfile, Qt.MatchExactly) 236 currentProfile, Qt.MatchExactly)
206 if items: 237 if items:
207 self.profilesList.setCurrentItem(items[0]) 238 self.profilesList.setCurrentItem(items[0])
239
240 if len(self.__profiles) == 0:
241 self.profileFrame.setEnabled(False)
208 242
209 def __populateProfile(self, profileName): 243 def __populateProfile(self, profileName):
210 """ 244 """
211 Private method to populate the profile data entry fields. 245 Private method to populate the profile data entry fields.
212 246
216 if profileName: 250 if profileName:
217 profile = self.__profiles[profileName] 251 profile = self.__profiles[profileName]
218 else: 252 else:
219 profile = self.__defaultProfile() 253 profile = self.__defaultProfile()
220 254
221 self.profileEdit.setText(profileName) 255 self.__populatingProfile = True
256 if profileName is not None:
257 self.profileEdit.setText(profileName)
222 self.brokerAddressEdit.setText(profile["BrokerAddress"]) 258 self.brokerAddressEdit.setText(profile["BrokerAddress"])
223 self.brokerPortSpinBox.setValue(profile["BrokerPort"]) 259 self.brokerPortSpinBox.setValue(profile["BrokerPort"])
224 self.clientIdEdit.setText(profile["ClientId"]) 260 self.clientIdEdit.setText(profile["ClientId"])
225 self.keepaliveSpinBox.setValue(profile["Keepalive"]) 261 self.keepaliveSpinBox.setValue(profile["Keepalive"])
226 self.cleanSessionCheckBox.setChecked(profile["CleanSession"]) 262 self.cleanSessionCheckBox.setChecked(profile["CleanSession"])
227 self.usernameEdit.setText(profile["Username"]) 263 self.usernameEdit.setText(profile["Username"])
228 self.passwordEdit.setText(profile["Password"]) 264 self.passwordEdit.setText(pwConvert(profile["Password"], encode=False))
229 self.willTopicEdit.setText(profile["WillTopic"]) 265 self.willTopicEdit.setText(profile["WillTopic"])
230 self.willMessageEdit.setPlainText(profile["WillMessage"]) 266 self.willMessageEdit.setPlainText(profile["WillMessage"])
231 self.willQosSpinBox.setValue(profile["WillQos"]) 267 self.willQosSpinBox.setValue(profile["WillQos"])
232 self.willRetainCheckBox.setChecked(profile["WillRetain"]) 268 self.willRetainCheckBox.setChecked(profile["WillRetain"])
233 269 self.__populatingProfile = False
234 self.__updateApplyButton() 270
271 self.profileFrame.setEnabled(True)
272 self.__updateApplyButton()
273
274 def __clearProfile(self):
275 """
276 Private method to clear the profile data entry fields.
277 """
278 self.__populatingProfile = True
279 self.profileEdit.setText("")
280 self.brokerAddressEdit.setText("")
281 self.brokerPortSpinBox.setValue(1883)
282 self.clientIdEdit.setText("")
283 self.keepaliveSpinBox.setValue(60)
284 self.cleanSessionCheckBox.setChecked(True)
285 self.usernameEdit.setText("")
286 self.passwordEdit.setText("")
287 self.willTopicEdit.setText("")
288 self.willMessageEdit.setPlainText("")
289 self.willQosSpinBox.setValue(0)
290 self.willRetainCheckBox.setChecked(False)
291 self.__populatingProfile = False
292
293 self.profileFrame.setEnabled(False)
294 self.__updateApplyButton()
295
296 def __resetProfile(self):
297 """
298 Private method to reset the profile data entry fields to their stored
299 values.
300 """
301 profileName = self.profileEdit.text()
302 if profileName in self.__profiles:
303 self.__populateProfile(profileName)
304
305 def __populateProfileDefault(self):
306 """
307 Private method to populate the profile data entry fields with default
308 profile values.
309 """
310 self.__populateProfile(None)
311
312 def __isChangedProfile(self):
313 """
314 Private method to check, if the currently shown profile contains some
315 changed data.
316
317 @return flag indicating changed data
318 @type bool
319 """
320 profileName = self.profileEdit.text()
321 if profileName == "":
322 return False
323
324 elif profileName in self.__profiles:
325 profile = self.__profiles[profileName]
326 return (
327 self.brokerAddressEdit.text() != profile["BrokerAddress"] or
328 self.brokerPortSpinBox.value() != profile["BrokerPort"] or
329 self.clientIdEdit.text() != profile["ClientId"] or
330 self.keepaliveSpinBox.value() != profile["Keepalive"] or
331 self.cleanSessionCheckBox.isChecked() !=
332 profile["CleanSession"] or
333 self.usernameEdit.text() != profile["Username"] or
334 self.passwordEdit.text() !=
335 pwConvert(profile["Password"], encode=False) or
336 self.willTopicEdit.text() != profile["WillTopic"] or
337 self.willMessageEdit.toPlainText() != profile["WillMessage"] or
338 self.willQosSpinBox.value() != profile["WillQos"] or
339 self.willRetainCheckBox.isChecked() != profile["WillRetain"]
340 )
341
342 else:
343 return True
235 344
236 def __updateApplyButton(self): 345 def __updateApplyButton(self):
237 """ 346 """
238 Private method to set the state of the Apply button. 347 Private method to set the state of the Apply button.
239 """ 348 """
349 # condition 1: profile name and broker address need to be given
240 enable = (bool(self.profileEdit.text()) and 350 enable = (bool(self.profileEdit.text()) and
241 bool(self.brokerAddressEdit.text())) 351 bool(self.brokerAddressEdit.text()))
352
353 # condition 2: if client ID is empty, clean session must be selected
354 if not self.__populatingProfile:
355 if self.clientIdEdit.text() == "" and \
356 not self.cleanSessionCheckBox.isChecked():
357 enable = False
358 E5MessageBox.critical(
359 self,
360 self.tr("Invalid Connection Parameters"),
361 self.tr("An empty Client ID requires a clean session."))
362
242 self.profileButtonBox.button(QDialogButtonBox.Apply).setEnabled(enable) 363 self.profileButtonBox.button(QDialogButtonBox.Apply).setEnabled(enable)
243 364
244 @pyqtSlot(str) 365 @pyqtSlot(str)
245 def on_brokerAddressEdit_textChanged(self, address): 366 def on_brokerAddressEdit_textChanged(self, address):
246 """ 367 """
256 """ 377 """
257 Private slot to generate a client ID. 378 Private slot to generate a client ID.
258 """ 379 """
259 uuid = QUuid.createUuid() 380 uuid = QUuid.createUuid()
260 self.clientIdEdit.setText(uuid.toString(QUuid.WithoutBraces)) 381 self.clientIdEdit.setText(uuid.toString(QUuid.WithoutBraces))
382
383 @pyqtSlot()
384 def reject(self):
385 """
386 Public slot to reject the dialog changes.
387 """
388 if self.__isChangedProfile():
389 button = E5MessageBox.warning(
390 self,
391 self.tr("Changed Connection Profile"),
392 self.tr("""The current profile has unsaved changes. Shall"""
393 """ these be saved?"""),
394 E5MessageBox.StandardButtons(
395 E5MessageBox.Discard |
396 E5MessageBox.Save),
397 E5MessageBox.Save)
398 if button == E5MessageBox.Save:
399 self.__applyProfile()
400 return
401
402 if self.__profilesChanged:
403 button = E5MessageBox.warning(
404 self,
405 self.tr("Changed Connection Profiles"),
406 self.tr("""The list of connection profiles has unsaved"""
407 """ changes."""),
408 E5MessageBox.StandardButtons(
409 E5MessageBox.Abort |
410 E5MessageBox.Discard |
411 E5MessageBox.Save),
412 E5MessageBox.Save)
413 if button == E5MessageBox.Save:
414 super(MqttConnectionProfilesDialog, self).accept()
415 return
416 elif button == E5MessageBox.Abort:
417 return
418
419 super(MqttConnectionProfilesDialog, self).reject()
420
421 @pyqtSlot()
422 def accept(self):
423 """
424 Public slot to accept the dialog.
425 """
426 if self.__isChangedProfile():
427 yes = E5MessageBox.yesNo(
428 self,
429 self.tr("Changed Connection Profile"),
430 self.tr("""The current profile has unsaved changes. Shall"""
431 """ these be saved?"""),
432 icon=E5MessageBox.Warning,
433 yesDefault=True)
434 if yes:
435 self.__applyProfile()
436
437 super(MqttConnectionProfilesDialog, self).accept()
438
439 @pyqtSlot(str)
440 def on_clientIdEdit_textChanged(self, clientId):
441 """
442 Private slot handling a change of the client ID string.
443
444 @param clientId client ID
445 @type str
446 """
447 self.__updateApplyButton()
448
449 @pyqtSlot(bool)
450 def on_cleanSessionCheckBox_clicked(self, checked):
451 """
452 Private slot to handle a change of the clean session selection.
453
454 @param checked current state of the clean session selection
455 @type bool
456 """
457 self.__updateApplyButton()

eric ide

mercurial