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