|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2012 - 2025 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the identities management dialog. |
|
8 """ |
|
9 |
|
10 import copy |
|
11 |
|
12 from PyQt6.QtCore import QEvent, QItemSelectionModel, Qt, pyqtSlot |
|
13 from PyQt6.QtWidgets import QDialog, QInputDialog, QLineEdit |
|
14 |
|
15 from eric7.EricGui import EricPixmapCache |
|
16 from eric7.EricWidgets import EricMessageBox |
|
17 from eric7.SystemUtilities import OSUtilities |
|
18 |
|
19 from .IrcNetworkManager import IrcIdentity |
|
20 from .Ui_IrcIdentitiesEditDialog import Ui_IrcIdentitiesEditDialog |
|
21 |
|
22 |
|
23 class IrcIdentitiesEditDialog(QDialog, Ui_IrcIdentitiesEditDialog): |
|
24 """ |
|
25 Class implementing the identities management dialog. |
|
26 """ |
|
27 |
|
28 def __init__(self, manager, identityName, parent=None): |
|
29 """ |
|
30 Constructor |
|
31 |
|
32 @param manager reference to the IRC network manager object |
|
33 @type IrcNetworkManager |
|
34 @param identityName name of the identity to be selected |
|
35 @type str |
|
36 @param parent reference to the parent widget |
|
37 @type QWidget |
|
38 """ |
|
39 super().__init__(parent) |
|
40 self.setupUi(self) |
|
41 |
|
42 self.addButton.setIcon(EricPixmapCache.getIcon("plus")) |
|
43 self.copyButton.setIcon(EricPixmapCache.getIcon("editCopy")) |
|
44 self.renameButton.setIcon(EricPixmapCache.getIcon("editRename")) |
|
45 self.deleteButton.setIcon(EricPixmapCache.getIcon("minus")) |
|
46 self.nicknameAddButton.setIcon(EricPixmapCache.getIcon("plus")) |
|
47 self.nicknameDeleteButton.setIcon(EricPixmapCache.getIcon("minus")) |
|
48 self.nicknameUpButton.setIcon(EricPixmapCache.getIcon("1uparrow")) |
|
49 self.nicknameDownButton.setIcon(EricPixmapCache.getIcon("1downarrow")) |
|
50 self.showPasswordButton.setIcon(EricPixmapCache.getIcon("showPassword")) |
|
51 |
|
52 self.__manager = manager |
|
53 |
|
54 self.__identities = self.__manager.getIdentities() |
|
55 self.__currentIdentity = None |
|
56 |
|
57 identities = sorted(self.__manager.getIdentityNames()) |
|
58 identities[identities.index(IrcIdentity.DefaultIdentityName)] = ( |
|
59 IrcIdentity.DefaultIdentityDisplay |
|
60 ) |
|
61 self.identitiesCombo.addItems(identities) |
|
62 if identityName == IrcIdentity.DefaultIdentityName: |
|
63 identityName = IrcIdentity.DefaultIdentityDisplay |
|
64 index = self.identitiesCombo.findText(identityName) |
|
65 if index == -1: |
|
66 index = 0 |
|
67 identityName = self.identitiesCombo.itemText(0) |
|
68 self.identitiesCombo.setCurrentIndex(index) |
|
69 |
|
70 self.on_identitiesCombo_currentIndexChanged(index) |
|
71 |
|
72 self.nicknameEdit.installEventFilter(self) |
|
73 |
|
74 def eventFilter(self, obj, evt): |
|
75 """ |
|
76 Public method to handle events for other objects. |
|
77 |
|
78 @param obj reference to the object |
|
79 @type QObject |
|
80 @param evt reference to the event |
|
81 @type QEvent |
|
82 @return flag indicating that the event should be filtered out |
|
83 @rtype bool |
|
84 """ |
|
85 if ( |
|
86 obj == self.nicknameEdit |
|
87 and evt.type() == QEvent.Type.KeyPress |
|
88 and evt.key() in [Qt.Key.Key_Enter, Qt.Key.Key_Return] |
|
89 ): |
|
90 self.on_nicknameAddButton_clicked() |
|
91 return True |
|
92 |
|
93 return super().eventFilter(obj, evt) |
|
94 |
|
95 def __updateIdentitiesButtons(self): |
|
96 """ |
|
97 Private slot to update the status of the identity related buttons. |
|
98 """ |
|
99 enable = ( |
|
100 self.identitiesCombo.currentText() != IrcIdentity.DefaultIdentityDisplay |
|
101 ) |
|
102 self.renameButton.setEnabled(enable) |
|
103 self.deleteButton.setEnabled(enable) |
|
104 |
|
105 @pyqtSlot(int) |
|
106 def on_identitiesCombo_currentIndexChanged(self, index): |
|
107 """ |
|
108 Private slot to handle the selection of an identity. |
|
109 |
|
110 @param index index of the selected entry |
|
111 @type int |
|
112 """ |
|
113 identity = self.identitiesCombo.itemText(index) |
|
114 if identity == IrcIdentity.DefaultIdentityDisplay: |
|
115 identity = IrcIdentity.DefaultIdentityName |
|
116 self.__updateIdentitiesButtons() |
|
117 |
|
118 if self.__currentIdentity and not self.__checkCurrentIdentity(): |
|
119 return |
|
120 |
|
121 self.__refreshCurrentIdentity() |
|
122 |
|
123 self.__currentIdentity = self.__identities[identity] |
|
124 |
|
125 # General Tab |
|
126 self.realnameEdit.setText(self.__currentIdentity.getRealName()) |
|
127 self.nicknamesList.clear() |
|
128 self.nicknamesList.addItems(self.__currentIdentity.getNickNames()) |
|
129 self.serviceEdit.setText(self.__currentIdentity.getServiceName()) |
|
130 self.passwordEdit.setText(self.__currentIdentity.getPassword()) |
|
131 |
|
132 # Away Tab |
|
133 self.rememberPosOnAwayCheckBox.setChecked( |
|
134 self.__currentIdentity.rememberAwayPosition() |
|
135 ) |
|
136 self.awayEdit.setText(self.__currentIdentity.getAwayMessage()) |
|
137 |
|
138 # Advanced Tab |
|
139 self.identEdit.setText(self.__currentIdentity.getIdent()) |
|
140 self.quitEdit.setText(self.__currentIdentity.getQuitMessage()) |
|
141 self.partEdit.setText(self.__currentIdentity.getPartMessage()) |
|
142 |
|
143 self.__updateIdentitiesButtons() |
|
144 self.__updateNicknameUpDownButtons() |
|
145 self.__updateNicknameButtons() |
|
146 |
|
147 self.identityTabWidget.setCurrentIndex(0) |
|
148 |
|
149 def __refreshCurrentIdentity(self): |
|
150 """ |
|
151 Private method to read back the data for the current identity. |
|
152 """ |
|
153 if self.__currentIdentity is None: |
|
154 return |
|
155 |
|
156 # General Tab |
|
157 self.__currentIdentity.setRealName(self.realnameEdit.text()) |
|
158 self.__currentIdentity.setNickNames( |
|
159 [ |
|
160 self.nicknamesList.item(row).text() |
|
161 for row in range(self.nicknamesList.count()) |
|
162 ] |
|
163 ) |
|
164 self.__currentIdentity.setServiceName(self.serviceEdit.text()) |
|
165 self.__currentIdentity.setPassword(self.passwordEdit.text()) |
|
166 |
|
167 # Away Tab |
|
168 self.__currentIdentity.setRememberAwayPosition( |
|
169 self.rememberPosOnAwayCheckBox.isChecked() |
|
170 ) |
|
171 self.__currentIdentity.setAwayMessage(self.awayEdit.text()) |
|
172 |
|
173 # Advanced Tab |
|
174 self.__currentIdentity.setIdent(self.identEdit.text()) |
|
175 self.__currentIdentity.setQuitMessage(self.quitEdit.text()) |
|
176 self.__currentIdentity.setPartMessage(self.partEdit.text()) |
|
177 |
|
178 def __checkCurrentIdentity(self): |
|
179 """ |
|
180 Private method to check the data for the current identity. |
|
181 |
|
182 @return flag indicating a successful check |
|
183 @rtype bool |
|
184 """ |
|
185 if self.nicknamesList.count() == 0: |
|
186 EricMessageBox.critical( |
|
187 self, |
|
188 self.tr("Edit Identity"), |
|
189 self.tr("""The identity must contain at least one nick name."""), |
|
190 ) |
|
191 block = self.identitiesCombo.blockSignals(True) |
|
192 identity = self.__currentIdentity.getName() |
|
193 if identity == IrcIdentity.DefaultIdentityName: |
|
194 identity = IrcIdentity.DefaultIdentityDisplay |
|
195 self.identitiesCombo.setCurrentIndex( |
|
196 self.identitiesCombo.findText(identity) |
|
197 ) |
|
198 self.identitiesCombo.blockSignals(block) |
|
199 self.identityTabWidget.setCurrentIndex(0) |
|
200 self.nicknameEdit.setFocus() |
|
201 return False |
|
202 |
|
203 if not self.realnameEdit.text(): |
|
204 EricMessageBox.critical( |
|
205 self, |
|
206 self.tr("Edit Identity"), |
|
207 self.tr("""The identity must have a real name."""), |
|
208 ) |
|
209 block = self.identitiesCombo.blockSignals(True) |
|
210 identity = self.__currentIdentity.getName() |
|
211 if identity == IrcIdentity.DefaultIdentityName: |
|
212 identity = IrcIdentity.DefaultIdentityDisplay |
|
213 self.identitiesCombo.setCurrentIndex( |
|
214 self.identitiesCombo.findText(identity) |
|
215 ) |
|
216 self.identitiesCombo.blockSignals(block) |
|
217 self.identityTabWidget.setCurrentIndex(0) |
|
218 self.realnameEdit.setFocus() |
|
219 return False |
|
220 |
|
221 return True |
|
222 |
|
223 @pyqtSlot() |
|
224 def on_addButton_clicked(self): |
|
225 """ |
|
226 Private slot to add a new idntity. |
|
227 """ |
|
228 name, ok = QInputDialog.getText( |
|
229 self, |
|
230 self.tr("Add Identity"), |
|
231 self.tr("Identity Name:"), |
|
232 QLineEdit.EchoMode.Normal, |
|
233 ) |
|
234 |
|
235 if ok: |
|
236 if name: |
|
237 if name in self.__identities: |
|
238 EricMessageBox.critical( |
|
239 self, |
|
240 self.tr("Add Identity"), |
|
241 self.tr( |
|
242 """An identity named <b>{0}</b> already exists.""" |
|
243 """ You must provide a different name.""" |
|
244 ).format(name), |
|
245 ) |
|
246 self.on_addButton_clicked() |
|
247 else: |
|
248 identity = IrcIdentity(name) |
|
249 identity.setIdent(OSUtilities.getUserName()) |
|
250 identity.setRealName(OSUtilities.getRealName()) |
|
251 self.__identities[name] = identity |
|
252 self.identitiesCombo.addItem(name) |
|
253 self.identitiesCombo.setCurrentIndex( |
|
254 self.identitiesCombo.count() - 1 |
|
255 ) |
|
256 else: |
|
257 EricMessageBox.critical( |
|
258 self, |
|
259 self.tr("Add Identity"), |
|
260 self.tr("""The identity has to have a name."""), |
|
261 ) |
|
262 self.on_addButton_clicked() |
|
263 |
|
264 @pyqtSlot() |
|
265 def on_copyButton_clicked(self): |
|
266 """ |
|
267 Private slot to copy the selected identity. |
|
268 """ |
|
269 currentIdentity = self.identitiesCombo.currentText() |
|
270 name, ok = QInputDialog.getText( |
|
271 self, |
|
272 self.tr("Copy Identity"), |
|
273 self.tr("Identity Name:"), |
|
274 QLineEdit.EchoMode.Normal, |
|
275 currentIdentity, |
|
276 ) |
|
277 |
|
278 if ok: |
|
279 if name: |
|
280 if name in self.__identities: |
|
281 EricMessageBox.critical( |
|
282 self, |
|
283 self.tr("Copy Identity"), |
|
284 self.tr( |
|
285 """An identity named <b>{0}</b> already exists.""" |
|
286 """ You must provide a different name.""" |
|
287 ).format(name), |
|
288 ) |
|
289 self.on_copyButton_clicked() |
|
290 else: |
|
291 identity = copy.deepcopy(self.__currentIdentity) |
|
292 identity.setName(name) |
|
293 self.__identities[name] = identity |
|
294 self.identitiesCombo.addItem(name) |
|
295 self.identitiesCombo.setCurrentIndex( |
|
296 self.identitiesCombo.count() - 1 |
|
297 ) |
|
298 else: |
|
299 EricMessageBox.critical( |
|
300 self, |
|
301 self.tr("Copy Identity"), |
|
302 self.tr("""The identity has to have a name."""), |
|
303 ) |
|
304 self.on_copyButton_clicked() |
|
305 |
|
306 @pyqtSlot() |
|
307 def on_renameButton_clicked(self): |
|
308 """ |
|
309 Private slot to rename the selected identity. |
|
310 """ |
|
311 currentIdentity = self.identitiesCombo.currentText() |
|
312 name, ok = QInputDialog.getText( |
|
313 self, |
|
314 self.tr("Rename Identity"), |
|
315 self.tr("Identity Name:"), |
|
316 QLineEdit.EchoMode.Normal, |
|
317 currentIdentity, |
|
318 ) |
|
319 |
|
320 if ok and name != currentIdentity: |
|
321 if name: |
|
322 if name in self.__identities: |
|
323 EricMessageBox.critical( |
|
324 self, |
|
325 self.tr("Rename Identity"), |
|
326 self.tr( |
|
327 """An identity named <b>{0}</b> already exists.""" |
|
328 """ You must provide a different name.""" |
|
329 ).format(name), |
|
330 ) |
|
331 self.on_renameButton_clicked() |
|
332 else: |
|
333 del self.__identities[currentIdentity] |
|
334 self.__currentIdentity.setName(name) |
|
335 self.__identities[name] = self.__currentIdentity |
|
336 self.identitiesCombo.setItemText( |
|
337 self.identitiesCombo.currentIndex(), name |
|
338 ) |
|
339 else: |
|
340 EricMessageBox.critical( |
|
341 self, |
|
342 self.tr("Copy Identity"), |
|
343 self.tr("""The identity has to have a name."""), |
|
344 ) |
|
345 self.on_renameButton_clicked() |
|
346 |
|
347 @pyqtSlot() |
|
348 def on_deleteButton_clicked(self): |
|
349 """ |
|
350 Private slot to rename the selected identity. |
|
351 """ |
|
352 currentIdentity = self.identitiesCombo.currentText() |
|
353 if currentIdentity == IrcIdentity.DefaultIdentityDisplay: |
|
354 return |
|
355 |
|
356 inUse = False |
|
357 for networkName in self.__manager.getNetworkNames(): |
|
358 inUse = ( |
|
359 self.__manager.getNetwork(networkName).getIdentityName() |
|
360 == currentIdentity |
|
361 ) |
|
362 if inUse: |
|
363 break |
|
364 |
|
365 msg = ( |
|
366 self.tr( |
|
367 "This identity is in use. If you remove it, the network" |
|
368 " settings using it will fall back to the default" |
|
369 " identity. Should it be deleted anyway?" |
|
370 ) |
|
371 if inUse |
|
372 else self.tr( |
|
373 "Do you really want to delete all information for this identity?" |
|
374 ) |
|
375 ) |
|
376 res = EricMessageBox.yesNo( |
|
377 self, self.tr("Delete Identity"), msg, icon=EricMessageBox.Warning |
|
378 ) |
|
379 if res: |
|
380 del self.__identities[currentIdentity] |
|
381 self.identitiesCombo.removeItem( |
|
382 self.identitiesCombo.findText(currentIdentity) |
|
383 ) |
|
384 |
|
385 def __updateNicknameUpDownButtons(self): |
|
386 """ |
|
387 Private method to set the enabled state of the nick name up and |
|
388 down buttons. |
|
389 """ |
|
390 if len(self.nicknamesList.selectedItems()) == 0: |
|
391 self.nicknameUpButton.setEnabled(False) |
|
392 self.nicknameDownButton.setEnabled(False) |
|
393 else: |
|
394 if self.nicknamesList.currentRow() == 0: |
|
395 self.nicknameUpButton.setEnabled(False) |
|
396 self.nicknameDownButton.setEnabled(True) |
|
397 elif self.nicknamesList.currentRow() == self.nicknamesList.count() - 1: |
|
398 self.nicknameUpButton.setEnabled(True) |
|
399 self.nicknameDownButton.setEnabled(False) |
|
400 else: |
|
401 self.nicknameUpButton.setEnabled(True) |
|
402 self.nicknameDownButton.setEnabled(True) |
|
403 |
|
404 def __updateNicknameButtons(self): |
|
405 """ |
|
406 Private slot to update the nick name buttons except the up and |
|
407 down buttons. |
|
408 """ |
|
409 self.nicknameDeleteButton.setEnabled( |
|
410 len(self.nicknamesList.selectedItems()) != 0 |
|
411 ) |
|
412 |
|
413 self.nicknameAddButton.setEnabled(self.nicknameEdit.text() != "") |
|
414 |
|
415 @pyqtSlot(str) |
|
416 def on_nicknameEdit_textEdited(self, nick): |
|
417 """ |
|
418 Private slot handling a change of the nick name. |
|
419 |
|
420 @param nick new nick name |
|
421 @type str |
|
422 """ |
|
423 sel = self.nicknamesList.selectedItems() |
|
424 if sel: |
|
425 sel[0].setText(nick) |
|
426 |
|
427 self.__updateNicknameButtons() |
|
428 |
|
429 @pyqtSlot() |
|
430 def on_nicknamesList_itemSelectionChanged(self): |
|
431 """ |
|
432 Private slot handling the selection of a nick name. |
|
433 """ |
|
434 items = self.nicknamesList.selectedItems() |
|
435 if items: |
|
436 self.nicknameEdit.setText(items[0].text()) |
|
437 |
|
438 self.__updateNicknameUpDownButtons() |
|
439 self.__updateNicknameButtons() |
|
440 |
|
441 self.nicknameEdit.setFocus() |
|
442 |
|
443 @pyqtSlot() |
|
444 def on_nicknameAddButton_clicked(self): |
|
445 """ |
|
446 Private slot to add a new nickname. |
|
447 """ |
|
448 nick = self.nicknameEdit.text() |
|
449 if nick not in [ |
|
450 self.nicknamesList.item(row).text() |
|
451 for row in range(self.nicknamesList.count()) |
|
452 ]: |
|
453 self.nicknamesList.insertItem(0, nick) |
|
454 self.nicknamesList.setCurrentRow(0, QItemSelectionModel.SelectionFlag.Clear) |
|
455 self.nicknameEdit.clear() |
|
456 self.__updateNicknameButtons() |
|
457 |
|
458 @pyqtSlot() |
|
459 def on_nicknameDeleteButton_clicked(self): |
|
460 """ |
|
461 Private slot to delete a nick name. |
|
462 """ |
|
463 itm = self.nicknamesList.takeItem(self.nicknamesList.currentRow()) |
|
464 del itm |
|
465 self.__updateNicknameButtons() |
|
466 |
|
467 @pyqtSlot() |
|
468 def on_nicknameUpButton_clicked(self): |
|
469 """ |
|
470 Private slot to move the selected entry up one row. |
|
471 """ |
|
472 row = self.nicknamesList.currentRow() |
|
473 if row > 0: |
|
474 itm = self.nicknamesList.takeItem(row) |
|
475 row -= 1 |
|
476 self.nicknamesList.insertItem(row, itm) |
|
477 self.nicknamesList.setCurrentItem(itm) |
|
478 |
|
479 @pyqtSlot() |
|
480 def on_nicknameDownButton_clicked(self): |
|
481 """ |
|
482 Private slot to move the selected entry down one row. |
|
483 """ |
|
484 row = self.nicknamesList.currentRow() |
|
485 if row < self.nicknamesList.count() - 1: |
|
486 itm = self.nicknamesList.takeItem(row) |
|
487 row += 1 |
|
488 self.nicknamesList.insertItem(row, itm) |
|
489 self.nicknamesList.setCurrentItem(itm) |
|
490 |
|
491 @pyqtSlot(bool) |
|
492 def on_showPasswordButton_clicked(self, checked): |
|
493 """ |
|
494 Private slot to show or hide the password. |
|
495 |
|
496 @param checked state of the button |
|
497 @type bool |
|
498 """ |
|
499 if checked: |
|
500 self.passwordEdit.setEchoMode(QLineEdit.EchoMode.Normal) |
|
501 self.showPasswordButton.setIcon(EricPixmapCache.getIcon("hidePassword")) |
|
502 self.showPasswordButton.setToolTip(self.tr("Press to hide the password")) |
|
503 else: |
|
504 self.passwordEdit.setEchoMode(QLineEdit.EchoMode.Password) |
|
505 self.showPasswordButton.setIcon(EricPixmapCache.getIcon("showPassword")) |
|
506 self.showPasswordButton.setToolTip(self.tr("Press to show the password")) |
|
507 |
|
508 def accept(self): |
|
509 """ |
|
510 Public slot handling the acceptance of the dialog. |
|
511 """ |
|
512 if not self.__checkCurrentIdentity(): |
|
513 return |
|
514 |
|
515 self.__refreshCurrentIdentity() |
|
516 self.__manager.setIdentities(self.__identities) |
|
517 |
|
518 super().accept() |