1# -*- coding: utf-8 -*- 2# 3# (c) Copyright 2003-2015 HP Development Company, L.P. 4# 5# This program is free software; you can redistribute it and/or modify 6# it under the terms of the GNU General Public License as published by 7# the Free Software Foundation; either version 2 of the License, or 8# (at your option) any later version. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program; if not, write to the Free Software 17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18# 19# Author: Don Welch 20# 21 22# Std Lib 23import sys 24import os 25import os.path 26 27# Local 28from base.g import * 29from base import utils 30from base.sixext import to_unicode 31from .ui_utils import load_pixmap 32 33try: 34 from fax import fax 35except ImportError: 36 # This can fail on Python < 2.3 due to the datetime module 37 log.error("Fax address book disabled - Python 2.3+ required.") 38 sys.exit(1) 39 40# Qt 41from qt import * 42from .faxaddrbookform_base import FaxAddrBookForm_base 43from .faxaddrbookeditform_base import FaxAddrBookEditForm_base 44from .faxaddrbookgroupsform_base import FaxAddrBookGroupsForm_base 45from .faxaddrbookgroupeditform_base import FaxAddrBookGroupEditForm_base 46 47# globals 48db = None 49 50# **************************************************************************** 51 52class AddressBookItem2(QListViewItem): 53 54 def __init__(self, parent, entry): 55 QListViewItem.__init__(self, parent) 56 self.entry = entry 57 self.setText(0, entry['name']) 58 self.setText(1, entry['title']) 59 self.setText(2, entry['firstname']) 60 self.setText(3, entry['lastname']) 61 self.setText(4, entry['fax']) 62 self.setText(5, ', '.join(entry['groups'])) 63 self.setText(6, entry['notes']) 64 65class GroupValidator(QValidator): 66 def __init__(self, parent=None, name=None): 67 QValidator.__init__(self, parent, name) 68 69 def validate(self, input, pos): 70 input = to_unicode(input) 71 if input.find(',') > 0: 72 return QValidator.Invalid, pos 73 elif len(input) > 50: 74 return QValidator.Invalid, pos 75 else: 76 return QValidator.Acceptable, pos 77 78 79class PhoneNumValidator(QValidator): 80 def __init__(self, parent=None, name=None): 81 QValidator.__init__(self, parent, name) 82 83 def validate(self, input, pos): 84 input = to_unicode(input) 85 if not input: 86 return QValidator.Acceptable, pos 87 elif input[pos-1] not in '0123456789-(+) *#': 88 return QValidator.Invalid, pos 89 elif len(input) > 50: 90 return QValidator.Invalid, pos 91 else: 92 return QValidator.Acceptable, pos 93 94 95# **************************************************************************** # 96 97class FaxAddrBookGroupEditForm(FaxAddrBookGroupEditForm_base): 98 """ 99 Called when clicking New... or Edit... from the Group Dialog 100 """ 101 def __init__(self,parent = None,name = None,modal = 0,fl = 0): 102 FaxAddrBookGroupEditForm_base.__init__(self,parent,name,modal,fl) 103 self.edit_mode = False 104 self.okButton.setEnabled(True) 105 self.all_groups = db.get_all_groups() 106 self.groupnameEdit.setValidator(GroupValidator(self.groupnameEdit)) 107 108 def setDlgData(self, group_name): 109 self.edit_mode = True 110 self.groupnameEdit.setText(group_name) 111 self.groupnameEdit.setReadOnly(True) 112 self.setEntries(group_name) 113 114 def setEntries(self, group_name=''): 115 self.entriesListView.clear() 116 all_entries = db.get_all_records() 117 118 for e, v in list(all_entries.items()): 119 i = QCheckListItem(self.entriesListView, e, QCheckListItem.CheckBox) 120 121 if group_name and group_name in v['groups']: 122 i.setState(QCheckListItem.On) 123 124 self.CheckOKButton() 125 126 127 def getDlgData(self): 128 group_name = to_unicode(self.groupnameEdit.text()) 129 entries = [] 130 131 i = self.entriesListView.firstChild() 132 133 while i is not None: 134 if i.isOn(): 135 entries.append(to_unicode(i.text())) 136 137 i = i.itemBelow() 138 139 return group_name, entries 140 141 def groupnameEdit_textChanged(self,a0): 142 self.CheckOKButton() 143 144 def entriesListView_clicked(self,a0): 145 self.CheckOKButton() 146 147 def CheckOKButton(self): 148 group_name = to_unicode(self.groupnameEdit.text()) 149 150 if not group_name or \ 151 (not self.edit_mode and group_name in self.all_groups): 152 153 self.okButton.setEnabled(False) 154 return 155 156 i = self.entriesListView.firstChild() 157 158 while i is not None: 159 if i.isOn(): 160 break 161 162 i = i.itemBelow() 163 164 else: 165 self.okButton.setEnabled(False) 166 return 167 168 self.okButton.setEnabled(True) 169 170 def __tr(self,s,c = None): 171 return qApp.translate("FaxAddrBookGroupEditForm",s,c) 172 173 174# **************************************************************************** # 175 176class FaxAddrBookGroupsForm(FaxAddrBookGroupsForm_base): 177 178 def __init__(self,parent = None,name = None,modal = 0,fl = 0): 179 FaxAddrBookGroupsForm_base.__init__(self,parent,name,modal,fl) 180 self.current = None 181 QTimer.singleShot(0, self.InitialUpdate) 182 183 def InitialUpdate(self): 184 self.UpdateList() 185 186 def UpdateList(self): 187 self.groupListView.clear() 188 first_rec = None 189 all_groups = db.get_all_groups() 190 if all_groups: 191 192 for group in all_groups: 193 i = QListViewItem(self.groupListView, group, 194 ', '.join(db.group_members(group))) 195 196 if first_rec is None: 197 first_rec = i 198 199 self.groupListView.setCurrentItem(i) 200 self.current = i 201 202 self.editButton.setEnabled(True) 203 self.deleteButton.setEnabled(True) 204 205 else: 206 self.editButton.setEnabled(False) 207 self.deleteButton.setEnabled(False) 208 209 def newButton_clicked(self): 210 dlg = FaxAddrBookGroupEditForm(self) 211 dlg.setEntries() 212 if dlg.exec_loop() == QDialog.Accepted: 213 group_name, entries = dlg.getDlgData() 214 db.update_groups(group_name, entries) 215 self.UpdateList() 216 217 def editButton_clicked(self): 218 dlg = FaxAddrBookGroupEditForm(self) 219 group_name = to_unicode(self.current.text(0)) 220 dlg.setDlgData(group_name) 221 if dlg.exec_loop() == QDialog.Accepted: 222 group_name, entries = dlg.getDlgData() 223 db.update_groups(group_name, entries) 224 self.UpdateList() 225 226 227 def deleteButton_clicked(self): 228 x = QMessageBox.critical(self, 229 self.caption(), 230 self.__tr("<b>Annoying Confirmation: Are you sure you want to delete this group?</b>"), 231 QMessageBox.Yes, 232 QMessageBox.No | QMessageBox.Default, 233 QMessageBox.NoButton) 234 if x == QMessageBox.Yes: 235 db.delete_group(to_unicode(self.current.text(0))) 236 self.UpdateList() 237 238 def groupListView_currentChanged(self, a0): 239 self.current = a0 240 241 def groupListView_doubleClicked(self, a0): 242 self.editButton_clicked() 243 244 def groupListView_rightButtonClicked(self, item, pos, a2): 245 popup = QPopupMenu(self) 246 247 popup.insertItem(self.__tr("New..."), self.newButton_clicked) 248 249 if item is not None: 250 popup.insertItem(self.__tr("Edit..."), self.editButton_clicked) 251 popup.insertItem(self.__tr("Delete..."), self.deleteButton_clicked) 252 253 popup.insertSeparator() 254 popup.insertItem(self.__tr("Refresh List"), self.UpdateList) 255 popup.popup(pos) 256 257 def __tr(self,s,c = None): 258 return qApp.translate("FaxAddrBookGroupsForm",s,c) 259 260 261# **************************************************************************** # 262 263 264class FaxAddrBookEditForm(FaxAddrBookEditForm_base): 265 def __init__(self, editing=True, parent = None,name = None,modal = 0,fl = 0): 266 FaxAddrBookEditForm_base.__init__(self,parent,name,modal,fl) 267 self.editing = editing 268 self.faxEdit.setValidator(PhoneNumValidator(self.faxEdit)) 269 self.initial_nickname = '' 270 self.OKButton.setEnabled(self.editing) 271 272 def setDlgData(self, name, title, firstname, lastname, fax, group_list, notes): 273 self.initial_nickname = name 274 self.name = name 275 self.titleEdit.setText(title) 276 self.firstnameEdit.setText(firstname) 277 self.lastnameEdit.setText(lastname) 278 self.faxEdit.setText(fax) 279 self.notesEdit.setText(notes) 280 self.nicknameEdit.setText(name) 281 self.setGroups(group_list) 282 283 def setGroups(self, entry_groups=[]): 284 self.groupListView.clear() 285 for g in db.get_all_groups(): 286 i = QCheckListItem(self.groupListView, g, QCheckListItem.CheckBox) 287 288 if g in entry_groups: 289 i.setState(QCheckListItem.On) 290 291 def getDlgData(self): 292 in_groups = [] 293 i = self.groupListView.firstChild() 294 295 while i is not None: 296 if i.isOn(): 297 in_groups.append(to_unicode(i.text())) 298 i = i.itemBelow() 299 300 return {'name': to_unicode(self.nicknameEdit.text()), 301 'title': to_unicode(self.titleEdit.text()), 302 'firstname': to_unicode(self.firstnameEdit.text()), 303 'lastname': to_unicode(self.lastnameEdit.text()), 304 'fax': to_unicode(self.faxEdit.text()), 305 'groups': in_groups, 306 'notes': to_unicode(self.notesEdit.text())} 307 308 def firstnameEdit_textChanged(self,a0): 309 pass 310 311 def lastnameEdit_textChanged(self,a0): 312 pass 313 314 def nicknameEdit_textChanged(self, nickname): 315 self.CheckOKButton(nickname, None) 316 317 def faxEdit_textChanged(self, fax): 318 self.CheckOKButton(None, fax) 319 320 def CheckOKButton(self, nickname=None, fax=None): 321 if nickname is None: 322 nickname = to_unicode(self.nicknameEdit.text()) 323 324 if fax is None: 325 fax = to_unicode(self.faxEdit.text()) 326 327 ok = bool(len(nickname) and len(fax)) 328 329 if nickname: 330 all_entries = db.get_all_records() 331 for e, v in list(all_entries.items()): 332 if nickname == e and nickname != self.initial_nickname: 333 ok = False 334 335 self.OKButton.setEnabled(ok) 336 337 def __tr(self,s,c = None): 338 return qApp.translate("FaxAddrBookEditForm",s,c) 339 340# **************************************************************************** # 341 342class FaxAddrBookForm(FaxAddrBookForm_base): 343 def __init__(self,parent = None,name = None,modal = 0,fl = 0): 344 FaxAddrBookForm_base.__init__(self,parent,name,modal,fl) 345 346 self.setIcon(load_pixmap('hp_logo', '128x128')) 347 348 global db 349 db = fax.FaxAddressBook() 350 self.init_problem = False 351 352 QTimer.singleShot(0, self.InitialUpdate) 353 354 355 def InitialUpdate(self): 356 if self.init_problem: 357 self.close() 358 return 359 360 self.UpdateList() 361 362 def UpdateList(self): 363 self.addressListView.clear() 364 first_rec = None 365 all_entries = db.get_all_records() 366 log.debug("Number of records is: %d" % len(all_entries)) 367 368 if all_entries: 369 for e, v in list(all_entries.items()): 370 371 if v['name'].startswith('__'): 372 continue 373 374 i = AddressBookItem2(self.addressListView, v) 375 376 if first_rec is None: 377 first_rec = i 378 379 self.addressListView.setCurrentItem(i) 380 self.current = i 381 382 self.editButton.setEnabled(True) 383 self.deleteButton.setEnabled(True) 384 385 else: 386 self.editButton.setEnabled(False) 387 self.deleteButton.setEnabled(False) 388 389 def groupButton_clicked(self): 390 FaxAddrBookGroupsForm(self).exec_loop() 391 self.sendUpdateEvent() 392 self.UpdateList() 393 394 def newButton_clicked(self): 395 dlg = FaxAddrBookEditForm(False, self) 396 dlg.setGroups() 397 if dlg.exec_loop() == QDialog.Accepted: 398 d = dlg.getDlgData() 399 db.set(**d) 400 self.sendUpdateEvent() 401 self.UpdateList() 402 403 def editButton_clicked(self): 404 dlg = FaxAddrBookEditForm(True, self) 405 c = self.current.entry 406 dlg.setDlgData(c['name'], c['title'], c['firstname'], 407 c['lastname'], c['fax'], c['groups'], c['notes']) 408 prev_name = c['name'] 409 if dlg.exec_loop() == QDialog.Accepted: 410 d = dlg.getDlgData() 411 412 if prev_name != d['name']: 413 db.delete(prev_name) 414 415 db.set(**d) 416 self.sendUpdateEvent() 417 self.UpdateList() 418 419 420 def deleteButton_clicked(self): 421 if QMessageBox.critical(self, 422 self.caption(), 423 self.__tr("<b>Annoying Confirmation: Are you sure you want to delete this address book entry?</b>"), 424 QMessageBox.Yes, 425 QMessageBox.No | QMessageBox.Default, 426 QMessageBox.NoButton) == QMessageBox.Yes: 427 db.delete(self.current.entry['name']) 428 self.UpdateList() 429 self.sendUpdateEvent() 430 431 432 def addressListView_rightButtonClicked(self, item, pos, a2): 433 popup = QPopupMenu(self) 434 popup.insertItem(self.__tr("New..."), self.newButton_clicked) 435 if item is not None: 436 popup.insertItem(self.__tr("Edit..."), self.editButton_clicked) 437 popup.insertItem(self.__tr("Delete..."), self.deleteButton_clicked) 438 439 popup.insertSeparator() 440 popup.insertItem(self.__tr("Refresh List"), self.UpdateList) 441 popup.popup(pos) 442 443 def addressListView_doubleClicked(self,a0): 444 self.editButton_clicked() 445 446 def addressListView_currentChanged(self,item): 447 self.current = item 448 449 def FailureUI(self, error_text): 450 log.error(to_unicode(error_text).replace("<b>", "").replace("</b>", "").replace("<p>", " ")) 451 QMessageBox.critical(self, 452 self.caption(), 453 QString(error_text), 454 QMessageBox.Ok, 455 QMessageBox.NoButton, 456 QMessageBox.NoButton) 457 458 def __tr(self,s,c = None): 459 return qApp.translate("FaxAddrBookForm",s,c) 460 461 def accept(self): 462 self.sendUpdateEvent() 463 464 FaxAddrBookForm_base.accept(self) 465 466 def sendUpdateEvent(self): 467 pass # TODO: 468 469 def importPushButton_clicked(self): 470 dlg = QFileDialog(user_conf.workingDirectory(), "LDIF (*.ldif *.ldi);;vCard (*.vcf)", None, None, True) 471 472 dlg.setCaption("openfile") 473 dlg.setMode(QFileDialog.ExistingFile) 474 dlg.show() 475 476 if dlg.exec_loop() == QDialog.Accepted: 477 result = str(dlg.selectedFile()) 478 working_directory = to_unicode(dlg.dir().absPath()) 479 log.debug("result: %s" % result) 480 user_conf.setWorkingDirectory(working_directory) 481 482 if result: 483 if result.endswith('.vcf'): 484 ok, error_str = db.import_vcard(result) 485 else: 486 ok, error_str = db.import_ldif(result) 487 488 if not ok: 489 self.FailureUI(error_str) 490 491 else: 492 self.UpdateList() 493 494