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