|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2018 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a dialog to edit the MQTT connection profiles. |
|
8 """ |
|
9 |
|
10 from __future__ import unicode_literals |
|
11 |
|
12 import collections |
|
13 |
|
14 from PyQt5.QtCore import pyqtSlot, Qt, QUuid |
|
15 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton, \ |
|
16 QListWidgetItem, QInputDialog, QLineEdit |
|
17 |
|
18 from E5Gui import E5MessageBox |
|
19 from E5Gui.E5PathPicker import E5PathPickerModes |
|
20 |
|
21 from .Ui_MqttConnectionProfilesDialog import Ui_MqttConnectionProfilesDialog |
|
22 |
|
23 import UI.PixmapCache |
|
24 from Utilities.crypto import pwConvert |
|
25 |
|
26 |
|
27 class MqttConnectionProfilesDialog(QDialog, Ui_MqttConnectionProfilesDialog): |
|
28 """ |
|
29 Class implementing a dialog to edit the MQTT connection profiles. |
|
30 """ |
|
31 def __init__(self, client, profiles, parent=None): |
|
32 """ |
|
33 Constructor |
|
34 |
|
35 @param client reference to the MQTT client object |
|
36 @type MqttClient |
|
37 @param profiles dictionary containing dictionaries containing the |
|
38 connection parameters. Each entry must have the keys |
|
39 "BrokerAddress", "BrokerPort", "ClientId", |
|
40 "Keepalive", "CleanSession", "Username", "Password", "WillTopic", |
|
41 "WillMessage", "WillQos", "WillRetain", "TlsEnable", "TlsCaCert", |
|
42 "TlsClientCert", "TlsClientKey". |
|
43 @type dict |
|
44 @param parent reference to the parent widget |
|
45 @type QWidget |
|
46 """ |
|
47 super(MqttConnectionProfilesDialog, self).__init__(parent) |
|
48 self.setupUi(self) |
|
49 |
|
50 self.__client = client |
|
51 |
|
52 self.__profiles = collections.defaultdict(self.__defaultProfile) |
|
53 self.__profiles.update(profiles) |
|
54 self.__profilesChanged = False |
|
55 |
|
56 self.plusButton.setIcon(UI.PixmapCache.getIcon("plus.png")) |
|
57 self.copyButton.setIcon(UI.PixmapCache.getIcon("editCopy.png")) |
|
58 self.minusButton.setIcon(UI.PixmapCache.getIcon("minus.png")) |
|
59 |
|
60 self.tlsCertsFilePicker.setMode(E5PathPickerModes.OpenFileMode) |
|
61 self.tlsCertsFilePicker.setFilters( |
|
62 self.tr("Certificate Files (*.crt *.pem);;All Files (*)")) |
|
63 self.tlsSelfSignedCertsFilePicker.setMode( |
|
64 E5PathPickerModes.OpenFileMode) |
|
65 self.tlsSelfSignedCertsFilePicker.setFilters( |
|
66 self.tr("Certificate Files (*.crt *.pem);;All Files (*)")) |
|
67 self.tlsSelfSignedClientCertFilePicker.setMode( |
|
68 E5PathPickerModes.OpenFileMode) |
|
69 self.tlsSelfSignedClientCertFilePicker.setFilters( |
|
70 self.tr("Certificate Files (*.crt *.pem);;All Files (*)")) |
|
71 self.tlsSelfSignedClientKeyFilePicker.setMode( |
|
72 E5PathPickerModes.OpenFileMode) |
|
73 self.tlsSelfSignedClientKeyFilePicker.setFilters( |
|
74 self.tr("Key Files (*.key *.pem);;All Files (*)")) |
|
75 |
|
76 self.profileTabWidget.setCurrentIndex(0) |
|
77 |
|
78 if len(self.__profiles) == 0: |
|
79 self.minusButton.setEnabled(False) |
|
80 self.copyButton.setEnabled(False) |
|
81 |
|
82 self.profileFrame.setEnabled(False) |
|
83 self.__populatingProfile = False |
|
84 self.__deletingProfile = False |
|
85 |
|
86 self.__populateProfilesList() |
|
87 |
|
88 @pyqtSlot(str) |
|
89 def on_profileEdit_textChanged(self, name): |
|
90 """ |
|
91 Private slot to handle changes of the profile name. |
|
92 |
|
93 @param name name of the profile |
|
94 @type str |
|
95 """ |
|
96 self.__updateApplyButton() |
|
97 |
|
98 @pyqtSlot(QAbstractButton) |
|
99 def on_profileButtonBox_clicked(self, button): |
|
100 """ |
|
101 Private slot handling presses of the profile buttons. |
|
102 |
|
103 @param button reference to the pressed button |
|
104 @type QAbstractButton |
|
105 """ |
|
106 if button == self.profileButtonBox.button(QDialogButtonBox.Apply): |
|
107 currentProfile = self.__applyProfile() |
|
108 self.__populateProfilesList(currentProfile) |
|
109 |
|
110 elif button == self.profileButtonBox.button(QDialogButtonBox.Reset): |
|
111 self.__resetProfile() |
|
112 |
|
113 elif button == self.profileButtonBox.button( |
|
114 QDialogButtonBox.RestoreDefaults): |
|
115 self.__populateProfileDefault() |
|
116 |
|
117 @pyqtSlot(QListWidgetItem, QListWidgetItem) |
|
118 def on_profilesList_currentItemChanged(self, current, previous): |
|
119 """ |
|
120 Private slot to handle a change of the current profile. |
|
121 |
|
122 @param current new current item |
|
123 @type QListWidgetItem |
|
124 @param previous previous current item |
|
125 @type QListWidgetItem |
|
126 """ |
|
127 self.minusButton.setEnabled(current is not None) |
|
128 self.copyButton.setEnabled(current is not None) |
|
129 |
|
130 if current is not previous: |
|
131 if not self.__deletingProfile and self.__isChangedProfile(): |
|
132 # modified profile belongs to previous |
|
133 yes = E5MessageBox.yesNo( |
|
134 self, |
|
135 self.tr("Changed Connection Profile"), |
|
136 self.tr("""The current profile has unsaved changes.""" |
|
137 """ Shall these be saved?"""), |
|
138 icon=E5MessageBox.Warning, |
|
139 yesDefault=True) |
|
140 if yes: |
|
141 self.__applyProfile() |
|
142 |
|
143 if current: |
|
144 profileName = current.text() |
|
145 self.__populateProfile(profileName) |
|
146 else: |
|
147 self.__clearProfile() |
|
148 |
|
149 @pyqtSlot() |
|
150 def on_plusButton_clicked(self): |
|
151 """ |
|
152 Private slot to add a new empty profile entry. |
|
153 """ |
|
154 profileName, ok = QInputDialog.getText( |
|
155 self, |
|
156 self.tr("New Connection Profile"), |
|
157 self.tr("Enter name for the new Connection Profile:"), |
|
158 QLineEdit.Normal) |
|
159 if ok and bool(profileName): |
|
160 if profileName in self.__profiles: |
|
161 E5MessageBox.warning( |
|
162 self, |
|
163 self.tr("New Connection Profile"), |
|
164 self.tr("""<p>A connection named <b>{0}</b> exists""" |
|
165 """ already. Aborting...</p>""").format( |
|
166 profileName)) |
|
167 else: |
|
168 itm = QListWidgetItem(profileName, self.profilesList) |
|
169 self.profilesList.setCurrentItem(itm) |
|
170 self.brokerAddressEdit.setFocus(Qt.OtherFocusReason) |
|
171 |
|
172 @pyqtSlot() |
|
173 def on_copyButton_clicked(self): |
|
174 """ |
|
175 Private slot to copy the selected profile entry. |
|
176 """ |
|
177 itm = self.profilesList.currentItem() |
|
178 if itm: |
|
179 profileName = itm.text() |
|
180 newProfileName, ok = QInputDialog.getText( |
|
181 self, |
|
182 self.tr("Copy Connection Profile"), |
|
183 self.tr("Enter name for the copied Connection Profile:"), |
|
184 QLineEdit.Normal) |
|
185 if ok and bool(newProfileName): |
|
186 if newProfileName in self.__profiles: |
|
187 E5MessageBox.warning( |
|
188 self, |
|
189 self.tr("Copy Connection Profile"), |
|
190 self.tr("""<p>A connection named <b>{0}</b> exists""" |
|
191 """ already. Aborting...</p>""").format( |
|
192 newProfileName)) |
|
193 else: |
|
194 profile = self.__defaultProfile() |
|
195 profile.update(self.__profiles[profileName]) |
|
196 self.__profiles[newProfileName] = profile |
|
197 |
|
198 itm = QListWidgetItem(newProfileName, self.profilesList) |
|
199 self.profilesList.setCurrentItem(itm) |
|
200 self.brokerAddressEdit.setFocus(Qt.OtherFocusReason) |
|
201 |
|
202 @pyqtSlot() |
|
203 def on_minusButton_clicked(self): |
|
204 """ |
|
205 Private slot to delete the selected entry. |
|
206 """ |
|
207 itm = self.profilesList.currentItem() |
|
208 if itm: |
|
209 profileName = itm.text() |
|
210 yes = E5MessageBox.yesNo( |
|
211 self, |
|
212 self.tr("Delete Connection Profile"), |
|
213 self.tr("""<p>Shall the Connection Profile <b>{0}</b>""" |
|
214 """ really be deleted?</p>""").format(profileName) |
|
215 ) |
|
216 if yes: |
|
217 self.__deletingProfile = True |
|
218 del self.__profiles[profileName] |
|
219 self.__profilesChanged = True |
|
220 self.__populateProfilesList() |
|
221 self.__deletingProfile = False |
|
222 |
|
223 self.profilesList.setFocus(Qt.OtherFocusReason) |
|
224 |
|
225 def getProfiles(self): |
|
226 """ |
|
227 Public method to return a dictionary of profiles. |
|
228 |
|
229 @return dictionary containing dictionaries containing the defined |
|
230 connection profiles. Each entry have the keys "BrokerAddress", |
|
231 "BrokerPort", "ClientId", "Keepalive", "CleanSession", "Username", |
|
232 "Password", "WillTopic", "WillMessage", "WillQos", "WillRetain", |
|
233 "TlsEnable", "TlsCaCert", "TlsClientCert", "TlsClientKey". |
|
234 @rtype dict |
|
235 """ |
|
236 profilesDict = {} |
|
237 profilesDict.update(self.__profiles) |
|
238 return profilesDict |
|
239 |
|
240 def __applyProfile(self): |
|
241 """ |
|
242 Private method to apply the entered data to the list of profiles. |
|
243 |
|
244 @return name of the applied profile |
|
245 @rtype str |
|
246 """ |
|
247 profileName = self.profileEdit.text() |
|
248 profile = { |
|
249 "BrokerAddress": self.brokerAddressEdit.text(), |
|
250 "BrokerPort": self.brokerPortSpinBox.value(), |
|
251 "ClientId": self.clientIdEdit.text(), |
|
252 "Keepalive": self.keepaliveSpinBox.value(), |
|
253 "CleanSession": self.cleanSessionCheckBox.isChecked(), |
|
254 "Username": self.usernameEdit.text(), |
|
255 "Password": pwConvert(self.passwordEdit.text(), encode=True), |
|
256 "WillTopic": self.willTopicEdit.text(), |
|
257 "WillMessage": self.willMessageEdit.toPlainText(), |
|
258 "WillQos": self.willQosSpinBox.value(), |
|
259 "WillRetain": self.willRetainCheckBox.isChecked(), |
|
260 "TlsEnable": self.tlsGroupBox.isChecked(), |
|
261 "TlsCaCert": "", |
|
262 "TlsClientCert": "", |
|
263 "TlsClientKey": "", |
|
264 } |
|
265 if profile["TlsEnable"]: |
|
266 if self.tlsCertsFileButton.isChecked(): |
|
267 profile["TlsCaCert"] = self.tlsCertsFilePicker.text() |
|
268 elif self.tlsSelfSignedCertsButton.isChecked(): |
|
269 profile["TlsCaCert"] = \ |
|
270 self.tlsSelfSignedCertsFilePicker.text() |
|
271 profile["TlsClientCert"] = \ |
|
272 self.tlsSelfSignedClientCertFilePicker.text() |
|
273 profile["TlsClientKey"] = \ |
|
274 self.tlsSelfSignedClientKeyFilePicker.text() |
|
275 |
|
276 self.__profiles[profileName] = profile |
|
277 self.__profilesChanged = True |
|
278 |
|
279 return profileName |
|
280 |
|
281 def __defaultProfile(self): |
|
282 """ |
|
283 Private method to populate non-existing profile items. |
|
284 |
|
285 @return default dictionary entry |
|
286 @rtype dict |
|
287 """ |
|
288 defaultProfile = self.__client.defaultConnectionOptions() |
|
289 defaultProfile["BrokerAddress"] = "" |
|
290 if defaultProfile["TlsEnable"]: |
|
291 defaultProfile["BrokerPort"] = 8883 |
|
292 else: |
|
293 defaultProfile["BrokerPort"] = 1883 |
|
294 |
|
295 return defaultProfile |
|
296 |
|
297 def __populateProfilesList(self, currentProfile=""): |
|
298 """ |
|
299 Private method to populate the list of defined profiles. |
|
300 |
|
301 @param currentProfile name of the current profile |
|
302 @type str |
|
303 """ |
|
304 if not currentProfile: |
|
305 currentItem = self.profilesList.currentItem() |
|
306 if currentItem: |
|
307 currentProfile = currentItem.text() |
|
308 |
|
309 self.profilesList.clear() |
|
310 self.profilesList.addItems(sorted(self.__profiles.keys())) |
|
311 |
|
312 if currentProfile: |
|
313 items = self.profilesList.findItems( |
|
314 currentProfile, Qt.MatchExactly) |
|
315 if items: |
|
316 self.profilesList.setCurrentItem(items[0]) |
|
317 |
|
318 if len(self.__profiles) == 0: |
|
319 self.profileFrame.setEnabled(False) |
|
320 |
|
321 def __populateProfile(self, profileName): |
|
322 """ |
|
323 Private method to populate the profile data entry fields. |
|
324 |
|
325 @param profileName name of the profile to get data from |
|
326 @type str |
|
327 """ |
|
328 profile = self.__defaultProfile() |
|
329 if profileName: |
|
330 profile.update(self.__profiles[profileName]) |
|
331 |
|
332 self.__populatingProfile = True |
|
333 if profileName is not None: |
|
334 self.profileEdit.setText(profileName) |
|
335 self.brokerAddressEdit.setText(profile["BrokerAddress"]) |
|
336 self.brokerPortSpinBox.setValue(profile["BrokerPort"]) |
|
337 self.clientIdEdit.setText(profile["ClientId"]) |
|
338 self.keepaliveSpinBox.setValue(profile["Keepalive"]) |
|
339 self.cleanSessionCheckBox.setChecked(profile["CleanSession"]) |
|
340 self.usernameEdit.setText(profile["Username"]) |
|
341 self.passwordEdit.setText(pwConvert(profile["Password"], encode=False)) |
|
342 self.willTopicEdit.setText(profile["WillTopic"]) |
|
343 self.willMessageEdit.setPlainText(profile["WillMessage"]) |
|
344 self.willQosSpinBox.setValue(profile["WillQos"]) |
|
345 self.willRetainCheckBox.setChecked(profile["WillRetain"]) |
|
346 self.tlsGroupBox.setChecked(profile["TlsEnable"]) |
|
347 if profile["TlsCaCert"] and profile["TlsClientCert"]: |
|
348 self.tlsSelfSignedCertsButton.setChecked(True) |
|
349 self.tlsSelfSignedCertsFilePicker.setText(profile["TlsCaCert"]) |
|
350 self.tlsSelfSignedClientCertFilePicker.setText( |
|
351 profile["TlsClientCert"]) |
|
352 self.tlsSelfSignedClientKeyFilePicker.setText( |
|
353 profile["TlsClientKey"]) |
|
354 elif profile["TlsCaCert"]: |
|
355 self.tlsCertsFileButton.setChecked(True) |
|
356 self.tlsCertsFilePicker.setText(profile["TlsCaCert"]) |
|
357 else: |
|
358 self.tlsDefaultCertsButton.setChecked(True) |
|
359 self.__populatingProfile = False |
|
360 |
|
361 self.profileFrame.setEnabled(True) |
|
362 self.__updateApplyButton() |
|
363 |
|
364 def __clearProfile(self): |
|
365 """ |
|
366 Private method to clear the profile data entry fields. |
|
367 """ |
|
368 self.__populatingProfile = True |
|
369 self.profileEdit.setText("") |
|
370 self.brokerAddressEdit.setText("") |
|
371 self.brokerPortSpinBox.setValue(1883) |
|
372 self.clientIdEdit.setText("") |
|
373 self.keepaliveSpinBox.setValue(60) |
|
374 self.cleanSessionCheckBox.setChecked(True) |
|
375 self.usernameEdit.setText("") |
|
376 self.passwordEdit.setText("") |
|
377 self.willTopicEdit.setText("") |
|
378 self.willMessageEdit.setPlainText("") |
|
379 self.willQosSpinBox.setValue(0) |
|
380 self.willRetainCheckBox.setChecked(False) |
|
381 self.tlsGroupBox.setChecked(False) |
|
382 self.tlsDefaultCertsButton.setChecked(True) |
|
383 self.tlsCertsFileButton.setChecked(True) |
|
384 self.tlsCertsFilePicker.setText("") |
|
385 self.tlsSelfSignedCertsButton.setChecked(False) |
|
386 self.tlsSelfSignedCertsFilePicker.setText("") |
|
387 self.tlsSelfSignedClientCertFilePicker.setText("") |
|
388 self.tlsSelfSignedClientKeyFilePicker.setText("") |
|
389 self.__populatingProfile = False |
|
390 |
|
391 self.profileFrame.setEnabled(False) |
|
392 self.__updateApplyButton() |
|
393 |
|
394 def __resetProfile(self): |
|
395 """ |
|
396 Private method to reset the profile data entry fields to their stored |
|
397 values. |
|
398 """ |
|
399 profileName = self.profileEdit.text() |
|
400 if profileName in self.__profiles: |
|
401 self.__populateProfile(profileName) |
|
402 |
|
403 def __populateProfileDefault(self): |
|
404 """ |
|
405 Private method to populate the profile data entry fields with default |
|
406 profile values. |
|
407 """ |
|
408 self.__populateProfile(None) |
|
409 |
|
410 def __isChangedProfile(self): |
|
411 """ |
|
412 Private method to check, if the currently shown profile contains some |
|
413 changed data. |
|
414 |
|
415 @return flag indicating changed data |
|
416 @type bool |
|
417 """ |
|
418 profileName = self.profileEdit.text() |
|
419 if profileName == "": |
|
420 return False |
|
421 |
|
422 elif profileName in self.__profiles: |
|
423 profile = self.__defaultProfile() |
|
424 profile.update(self.__profiles[profileName]) |
|
425 changed = ( |
|
426 self.brokerAddressEdit.text() != profile["BrokerAddress"] or |
|
427 self.brokerPortSpinBox.value() != profile["BrokerPort"] or |
|
428 self.clientIdEdit.text() != profile["ClientId"] or |
|
429 self.keepaliveSpinBox.value() != profile["Keepalive"] or |
|
430 self.cleanSessionCheckBox.isChecked() != |
|
431 profile["CleanSession"] or |
|
432 self.usernameEdit.text() != profile["Username"] or |
|
433 self.passwordEdit.text() != |
|
434 pwConvert(profile["Password"], encode=False) or |
|
435 self.willTopicEdit.text() != profile["WillTopic"] or |
|
436 self.willMessageEdit.toPlainText() != profile["WillMessage"] or |
|
437 self.willQosSpinBox.value() != profile["WillQos"] or |
|
438 self.willRetainCheckBox.isChecked() != profile["WillRetain"] or |
|
439 self.tlsGroupBox.isChecked() != profile["TlsEnable"] |
|
440 ) |
|
441 # check TLS stuff only, if not yet changed |
|
442 if not changed: |
|
443 if self.tlsCertsFileButton.isChecked(): |
|
444 changed |= ( |
|
445 self.tlsCertsFilePicker.text() != profile["TlsCaCert"] |
|
446 ) |
|
447 elif self.tlsSelfSignedCertsButton.isChecked(): |
|
448 changed |= ( |
|
449 self.tlsSelfSignedCertsFilePicker.text() != |
|
450 profile["TlsCaCert"] or |
|
451 self.tlsSelfSignedClientCertFilePicker.text() != |
|
452 profile["TlsClientCert"] or |
|
453 self.tlsSelfSignedClientKeyFilePicker.text() != |
|
454 profile["TlsClientKey"] |
|
455 ) |
|
456 return changed |
|
457 |
|
458 else: |
|
459 return True |
|
460 |
|
461 def __updateApplyButton(self): |
|
462 """ |
|
463 Private method to set the state of the Apply button. |
|
464 """ |
|
465 # condition 1: profile name and broker address need to be given |
|
466 enable = (bool(self.profileEdit.text()) and |
|
467 bool(self.brokerAddressEdit.text())) |
|
468 |
|
469 # condition 2: if client ID is empty, clean session must be selected |
|
470 if not self.__populatingProfile: |
|
471 if self.clientIdEdit.text() == "" and \ |
|
472 not self.cleanSessionCheckBox.isChecked(): |
|
473 enable = False |
|
474 E5MessageBox.critical( |
|
475 self, |
|
476 self.tr("Invalid Connection Parameters"), |
|
477 self.tr("An empty Client ID requires a clean session.")) |
|
478 |
|
479 if self.tlsGroupBox.isChecked(): |
|
480 if self.tlsCertsFileButton.isChecked(): |
|
481 # condition 3a: if CA certificates file shall be used, it must |
|
482 # be given |
|
483 enable &= bool(self.tlsCertsFilePicker.text()) |
|
484 elif self.tlsSelfSignedCertsButton.isChecked(): |
|
485 # condition 3b: if client certificates shall be used, all files |
|
486 # must be given |
|
487 enable &= ( |
|
488 bool(self.tlsSelfSignedCertsFilePicker.text()) and |
|
489 bool(self.tlsSelfSignedClientCertFilePicker.text()) and |
|
490 bool(self.tlsSelfSignedClientKeyFilePicker.text()) |
|
491 ) |
|
492 |
|
493 self.profileButtonBox.button(QDialogButtonBox.Apply).setEnabled(enable) |
|
494 |
|
495 @pyqtSlot(str) |
|
496 def on_brokerAddressEdit_textChanged(self, address): |
|
497 """ |
|
498 Private slot handling a change of the broker address. |
|
499 |
|
500 @param address broker address |
|
501 @type str |
|
502 """ |
|
503 self.__updateApplyButton() |
|
504 |
|
505 @pyqtSlot() |
|
506 def on_generateIdButton_clicked(self): |
|
507 """ |
|
508 Private slot to generate a client ID. |
|
509 """ |
|
510 uuid = QUuid.createUuid() |
|
511 self.clientIdEdit.setText(uuid.toString(QUuid.WithoutBraces)) |
|
512 |
|
513 @pyqtSlot(str) |
|
514 def on_clientIdEdit_textChanged(self, clientId): |
|
515 """ |
|
516 Private slot handling a change of the client ID string. |
|
517 |
|
518 @param clientId client ID |
|
519 @type str |
|
520 """ |
|
521 self.__updateApplyButton() |
|
522 |
|
523 @pyqtSlot(bool) |
|
524 def on_cleanSessionCheckBox_clicked(self, checked): |
|
525 """ |
|
526 Private slot to handle a change of the clean session selection. |
|
527 |
|
528 @param checked current state of the clean session selection |
|
529 @type bool |
|
530 """ |
|
531 self.__updateApplyButton() |
|
532 |
|
533 @pyqtSlot(str) |
|
534 def on_tlsCertsFilePicker_textChanged(self, path): |
|
535 """ |
|
536 Private slot handling a change of the TLS CA certificates file. |
|
537 |
|
538 @param path file path |
|
539 @type str |
|
540 """ |
|
541 self.__updateApplyButton() |
|
542 |
|
543 @pyqtSlot(str) |
|
544 def on_tlsSelfSignedCertsFilePicker_textChanged(self, path): |
|
545 """ |
|
546 Private slot handling a change of the TLS CA certificates file. |
|
547 |
|
548 @param path file path |
|
549 @type str |
|
550 """ |
|
551 self.__updateApplyButton() |
|
552 |
|
553 @pyqtSlot(str) |
|
554 def on_tlsSelfSignedClientCertFilePicker_textChanged(self, path): |
|
555 """ |
|
556 Private slot handling a change of the TLS client certificate file. |
|
557 |
|
558 @param path file path |
|
559 @type str |
|
560 """ |
|
561 self.__updateApplyButton() |
|
562 |
|
563 @pyqtSlot(str) |
|
564 def on_tlsSelfSignedClientKeyFilePicker_textChanged(self, path): |
|
565 """ |
|
566 Private slot handling a change of the TLS client key file. |
|
567 |
|
568 @param path file path |
|
569 @type str |
|
570 """ |
|
571 self.__updateApplyButton() |
|
572 |
|
573 @pyqtSlot(bool) |
|
574 def on_tlsGroupBox_toggled(self, checked): |
|
575 """ |
|
576 Private slot handling the selection of TLS mode. |
|
577 |
|
578 @param checked state of the selection |
|
579 @type bool |
|
580 """ |
|
581 if checked and self.brokerPortSpinBox.value() == 1883: |
|
582 # port is still standard non-TLS port |
|
583 yes = E5MessageBox.yesNo( |
|
584 self, |
|
585 self.tr("SSL/TLS Enabled"), |
|
586 self.tr( |
|
587 """Encrypted connection using SSL/TLS has been enabled.""" |
|
588 """ However, the broker port is still the default""" |
|
589 """ unencrypted port (port 1883). Shall this be""" |
|
590 """ changed?"""), |
|
591 icon=E5MessageBox.Warning, |
|
592 yesDefault=True) |
|
593 if yes: |
|
594 self.brokerPortSpinBox.setValue(8883) |
|
595 elif not checked and self.brokerPortSpinBox.value() == 8883: |
|
596 # port is still standard TLS port |
|
597 yes = E5MessageBox.yesNo( |
|
598 self, |
|
599 self.tr("SSL/TLS Disabled"), |
|
600 self.tr( |
|
601 """Encrypted connection using SSL/TLS has been disabled.""" |
|
602 """ However, the broker port is still the default""" |
|
603 """ encrypted port (port 8883). Shall this be""" |
|
604 """ changed?"""), |
|
605 icon=E5MessageBox.Warning, |
|
606 yesDefault=True) |
|
607 if yes: |
|
608 self.brokerPortSpinBox.setValue(1883) |
|
609 |
|
610 self.__updateApplyButton() |
|
611 |
|
612 @pyqtSlot(bool) |
|
613 def on_tlsDefaultCertsButton_toggled(self, checked): |
|
614 """ |
|
615 Private slot handling the selection of using the default |
|
616 certificates file. |
|
617 |
|
618 @param checked state of the selection |
|
619 @type bool |
|
620 """ |
|
621 self.__updateApplyButton() |
|
622 |
|
623 @pyqtSlot(bool) |
|
624 def on_tlsCertsFileButton_toggled(self, checked): |
|
625 """ |
|
626 Private slot handling the selection of using a non-default |
|
627 certificates file. |
|
628 |
|
629 @param checked state of the selection |
|
630 @type bool |
|
631 """ |
|
632 self.__updateApplyButton() |
|
633 |
|
634 @pyqtSlot(bool) |
|
635 def on_tlsSelfSignedCertsButton_toggled(self, checked): |
|
636 """ |
|
637 Private slot handling the selection of using self signed |
|
638 client certificate and key files. |
|
639 |
|
640 @param checked state of the selection |
|
641 @type bool |
|
642 """ |
|
643 self.__updateApplyButton() |
|
644 |
|
645 @pyqtSlot() |
|
646 def reject(self): |
|
647 """ |
|
648 Public slot to reject the dialog changes. |
|
649 """ |
|
650 if self.__isChangedProfile(): |
|
651 button = E5MessageBox.warning( |
|
652 self, |
|
653 self.tr("Changed Connection Profile"), |
|
654 self.tr("""The current profile has unsaved changes. Shall""" |
|
655 """ these be saved?"""), |
|
656 E5MessageBox.StandardButtons( |
|
657 E5MessageBox.Discard | |
|
658 E5MessageBox.Save), |
|
659 E5MessageBox.Save) |
|
660 if button == E5MessageBox.Save: |
|
661 self.__applyProfile() |
|
662 return |
|
663 |
|
664 if self.__profilesChanged: |
|
665 button = E5MessageBox.warning( |
|
666 self, |
|
667 self.tr("Changed Connection Profiles"), |
|
668 self.tr("""The list of connection profiles has unsaved""" |
|
669 """ changes."""), |
|
670 E5MessageBox.StandardButtons( |
|
671 E5MessageBox.Abort | |
|
672 E5MessageBox.Discard | |
|
673 E5MessageBox.Save), |
|
674 E5MessageBox.Save) |
|
675 if button == E5MessageBox.Save: |
|
676 super(MqttConnectionProfilesDialog, self).accept() |
|
677 return |
|
678 elif button == E5MessageBox.Abort: |
|
679 return |
|
680 |
|
681 super(MqttConnectionProfilesDialog, self).reject() |
|
682 |
|
683 @pyqtSlot() |
|
684 def accept(self): |
|
685 """ |
|
686 Public slot to accept the dialog. |
|
687 """ |
|
688 if self.__isChangedProfile(): |
|
689 yes = E5MessageBox.yesNo( |
|
690 self, |
|
691 self.tr("Changed Connection Profile"), |
|
692 self.tr("""The current profile has unsaved changes. Shall""" |
|
693 """ these be saved?"""), |
|
694 icon=E5MessageBox.Warning, |
|
695 yesDefault=True) |
|
696 if yes: |
|
697 self.__applyProfile() |
|
698 |
|
699 super(MqttConnectionProfilesDialog, self).accept() |