address_dialogs.py.bak
1 """ 2 Dialogs that work with BM address. 3 """ 4 # pylint: disable=attribute-defined-outside-init,too-few-public-methods,relative-import 5 6 import hashlib 7 8 from PyQt4 import QtCore, QtGui 9 10 import queues 11 import widgets 12 import state 13 from account import AccountMixin, GatewayAccount, MailchuckAccount, accountClass 14 from addresses import addBMIfNotPresent, decodeAddress, encodeVarint 15 from bmconfigparser import config as global_config 16 from tr import _translate 17 18 19 class AddressCheckMixin(object): 20 """Base address validation class for QT UI""" 21 22 def __init__(self): 23 self.valid = False 24 QtCore.QObject.connect( # pylint: disable=no-member 25 self.lineEditAddress, 26 QtCore.SIGNAL("textChanged(QString)"), 27 self.addressChanged) 28 29 def _onSuccess(self, addressVersion, streamNumber, ripe): 30 pass 31 32 def addressChanged(self, QString): 33 """ 34 Address validation callback, performs validation and gives feedback 35 """ 36 status, addressVersion, streamNumber, ripe = decodeAddress( 37 str(QString)) 38 self.valid = status == 'success' 39 if self.valid: 40 self.labelAddressCheck.setText( 41 _translate("MainWindow", "Address is valid.")) 42 self._onSuccess(addressVersion, streamNumber, ripe) 43 elif status == 'missingbm': 44 self.labelAddressCheck.setText(_translate( 45 "MainWindow", # dialog name should be here 46 "The address should start with ''BM-''" 47 )) 48 elif status == 'checksumfailed': 49 self.labelAddressCheck.setText(_translate( 50 "MainWindow", 51 "The address is not typed or copied correctly" 52 " (the checksum failed)." 53 )) 54 elif status == 'versiontoohigh': 55 self.labelAddressCheck.setText(_translate( 56 "MainWindow", 57 "The version number of this address is higher than this" 58 " software can support. Please upgrade Bitmessage." 59 )) 60 elif status == 'invalidcharacters': 61 self.labelAddressCheck.setText(_translate( 62 "MainWindow", 63 "The address contains invalid characters." 64 )) 65 elif status == 'ripetooshort': 66 self.labelAddressCheck.setText(_translate( 67 "MainWindow", 68 "Some data encoded in the address is too short." 69 )) 70 elif status == 'ripetoolong': 71 self.labelAddressCheck.setText(_translate( 72 "MainWindow", 73 "Some data encoded in the address is too long." 74 )) 75 elif status == 'varintmalformed': 76 self.labelAddressCheck.setText(_translate( 77 "MainWindow", 78 "Some data encoded in the address is malformed." 79 )) 80 81 82 class AddressDataDialog(QtGui.QDialog, AddressCheckMixin): 83 """QDialog with Bitmessage address validation""" 84 85 def __init__(self, parent): 86 super(AddressDataDialog, self).__init__(parent) 87 self.parent = parent 88 89 def accept(self): 90 """Callback for QDIalog accepting value""" 91 if self.valid: 92 self.data = ( 93 addBMIfNotPresent(str(self.lineEditAddress.text())), 94 str(self.lineEditLabel.text().toUtf8()) 95 ) 96 else: 97 queues.UISignalQueue.put(('updateStatusBar', _translate( 98 "MainWindow", 99 "The address you entered was invalid. Ignoring it." 100 ))) 101 super(AddressDataDialog, self).accept() 102 103 104 class AddAddressDialog(AddressDataDialog): 105 """QDialog for adding a new address""" 106 107 def __init__(self, parent=None, address=None): 108 super(AddAddressDialog, self).__init__(parent) 109 widgets.load('addaddressdialog.ui', self) 110 AddressCheckMixin.__init__(self) 111 if address: 112 self.lineEditAddress.setText(address) 113 114 115 class NewAddressDialog(QtGui.QDialog): 116 """QDialog for generating a new address""" 117 118 def __init__(self, parent=None): 119 super(NewAddressDialog, self).__init__(parent) 120 widgets.load('newaddressdialog.ui', self) 121 122 # Let's fill out the 'existing address' combo box with addresses 123 # from the 'Your Identities' tab. 124 for address in global_config.addresses(True): 125 self.radioButtonExisting.click() 126 self.comboBoxExisting.addItem(address) 127 self.groupBoxDeterministic.setHidden(True) 128 QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) 129 self.show() 130 131 def accept(self): 132 """accept callback""" 133 self.hide() 134 # self.buttonBox.enabled = False 135 if self.radioButtonRandomAddress.isChecked(): 136 if self.radioButtonMostAvailable.isChecked(): 137 streamNumberForAddress = 1 138 else: 139 # User selected 'Use the same stream as an existing 140 # address.' 141 streamNumberForAddress = decodeAddress( 142 self.comboBoxExisting.currentText())[2] 143 queues.addressGeneratorQueue.put(( 144 'createRandomAddress', 4, streamNumberForAddress, 145 str(self.newaddresslabel.text().toUtf8()), 1, "", 146 self.checkBoxEighteenByteRipe.isChecked() 147 )) 148 else: 149 if self.lineEditPassphrase.text() != \ 150 self.lineEditPassphraseAgain.text(): 151 QtGui.QMessageBox.about( 152 self, _translate("MainWindow", "Passphrase mismatch"), 153 _translate( 154 "MainWindow", 155 "The passphrase you entered twice doesn\'t" 156 " match. Try again.") 157 ) 158 elif self.lineEditPassphrase.text() == "": 159 QtGui.QMessageBox.about( 160 self, _translate("MainWindow", "Choose a passphrase"), 161 _translate( 162 "MainWindow", "You really do need a passphrase.") 163 ) 164 else: 165 # this will eventually have to be replaced by logic 166 # to determine the most available stream number. 167 streamNumberForAddress = 1 168 queues.addressGeneratorQueue.put(( 169 'createDeterministicAddresses', 4, streamNumberForAddress, 170 "unused deterministic address", 171 self.spinBoxNumberOfAddressesToMake.value(), 172 self.lineEditPassphrase.text().toUtf8(), 173 self.checkBoxEighteenByteRipe.isChecked() 174 )) 175 176 177 class NewSubscriptionDialog(AddressDataDialog): 178 """QDialog for subscribing to an address""" 179 180 def __init__(self, parent=None): 181 super(NewSubscriptionDialog, self).__init__(parent) 182 widgets.load('newsubscriptiondialog.ui', self) 183 AddressCheckMixin.__init__(self) 184 185 def _onSuccess(self, addressVersion, streamNumber, ripe): 186 if addressVersion <= 3: 187 self.checkBoxDisplayMessagesAlreadyInInventory.setText(_translate( 188 "MainWindow", 189 "Address is an old type. We cannot display its past" 190 " broadcasts." 191 )) 192 else: 193 state.Inventory.flush() 194 doubleHashOfAddressData = hashlib.sha512(hashlib.sha512( 195 encodeVarint(addressVersion) 196 + encodeVarint(streamNumber) + ripe 197 ).digest()).digest() 198 tag = doubleHashOfAddressData[32:] 199 self.recent = state.Inventory.by_type_and_tag(3, tag) 200 count = len(self.recent) 201 if count == 0: 202 self.checkBoxDisplayMessagesAlreadyInInventory.setText( 203 _translate( 204 "MainWindow", 205 "There are no recent broadcasts from this address" 206 " to display." 207 )) 208 else: 209 self.checkBoxDisplayMessagesAlreadyInInventory.setEnabled(True) 210 self.checkBoxDisplayMessagesAlreadyInInventory.setText( 211 _translate( 212 "MainWindow", 213 "Display the %n recent broadcast(s) from this address.", 214 None, 215 QtCore.QCoreApplication.CodecForTr, 216 count 217 )) 218 219 220 class RegenerateAddressesDialog(QtGui.QDialog): 221 """QDialog for regenerating deterministic addresses""" 222 def __init__(self, parent=None): 223 super(RegenerateAddressesDialog, self).__init__(parent) 224 widgets.load('regenerateaddresses.ui', self) 225 self.groupBox.setTitle('') 226 QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) 227 228 229 class SpecialAddressBehaviorDialog(QtGui.QDialog): 230 """ 231 QDialog for special address behaviour (e.g. mailing list functionality) 232 """ 233 234 def __init__(self, parent=None, config=global_config): 235 super(SpecialAddressBehaviorDialog, self).__init__(parent) 236 widgets.load('specialaddressbehavior.ui', self) 237 self.address = parent.getCurrentAccount() 238 self.parent = parent 239 self.config = config 240 241 try: 242 self.address_is_chan = config.safeGetBoolean( 243 self.address, 'chan' 244 ) 245 except AttributeError: 246 pass 247 else: 248 if self.address_is_chan: # address is a chan address 249 self.radioButtonBehaviorMailingList.setDisabled(True) 250 self.lineEditMailingListName.setText(_translate( 251 "SpecialAddressBehaviorDialog", 252 "This is a chan address. You cannot use it as a" 253 " pseudo-mailing list." 254 )) 255 else: 256 if config.safeGetBoolean(self.address, 'mailinglist'): 257 self.radioButtonBehaviorMailingList.click() 258 else: 259 self.radioButtonBehaveNormalAddress.click() 260 mailingListName = config.safeGet(self.address, 'mailinglistname', '') 261 self.lineEditMailingListName.setText( 262 unicode(mailingListName, 'utf-8') 263 ) 264 265 QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) 266 self.show() 267 268 def accept(self): 269 """Accept callback""" 270 self.hide() 271 if self.address_is_chan: 272 return 273 if self.radioButtonBehaveNormalAddress.isChecked(): 274 self.config.set(str(self.address), 'mailinglist', 'false') 275 # Set the color to either black or grey 276 if self.config.getboolean(self.address, 'enabled'): 277 self.parent.setCurrentItemColor( 278 QtGui.QApplication.palette().text().color() 279 ) 280 else: 281 self.parent.setCurrentItemColor(QtGui.QColor(128, 128, 128)) 282 else: 283 self.config.set(str(self.address), 'mailinglist', 'true') 284 self.config.set(str(self.address), 'mailinglistname', str( 285 self.lineEditMailingListName.text().toUtf8())) 286 self.parent.setCurrentItemColor( 287 QtGui.QColor(137, 4, 177)) # magenta 288 self.parent.rerenderComboBoxSendFrom() 289 self.parent.rerenderComboBoxSendFromBroadcast() 290 self.config.save() 291 self.parent.rerenderMessagelistToLabels() 292 293 294 class EmailGatewayDialog(QtGui.QDialog): 295 """QDialog for email gateway control""" 296 def __init__(self, parent, config=global_config, account=None): 297 super(EmailGatewayDialog, self).__init__(parent) 298 widgets.load('emailgateway.ui', self) 299 self.parent = parent 300 self.config = config 301 if account: 302 self.acct = account 303 self.setWindowTitle(_translate( 304 "EmailGatewayDialog", "Registration failed:")) 305 self.label.setText(_translate( 306 "EmailGatewayDialog", 307 "The requested email address is not available," 308 " please try a new one." 309 )) 310 self.radioButtonRegister.hide() 311 self.radioButtonStatus.hide() 312 self.radioButtonSettings.hide() 313 self.radioButtonUnregister.hide() 314 else: 315 address = parent.getCurrentAccount() 316 self.acct = accountClass(address) 317 try: 318 label = config.get(address, 'label') 319 except AttributeError: 320 pass 321 else: 322 if "@" in label: 323 self.lineEditEmail.setText(label) 324 if isinstance(self.acct, GatewayAccount): 325 self.radioButtonUnregister.setEnabled(True) 326 self.radioButtonStatus.setEnabled(True) 327 self.radioButtonStatus.setChecked(True) 328 self.radioButtonSettings.setEnabled(True) 329 self.lineEditEmail.setEnabled(False) 330 else: 331 self.acct = MailchuckAccount(address) 332 self.lineEditEmail.setFocus() 333 QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self)) 334 335 def accept(self): 336 """Accept callback""" 337 self.hide() 338 # no chans / mailinglists 339 if self.acct.type != AccountMixin.NORMAL: 340 return 341 342 if not isinstance(self.acct, GatewayAccount): 343 return 344 345 if self.radioButtonRegister.isChecked() \ 346 or self.radioButtonRegister.isHidden(): 347 email = str(self.lineEditEmail.text().toUtf8()) 348 self.acct.register(email) 349 self.config.set(self.acct.fromAddress, 'label', email) 350 self.config.set(self.acct.fromAddress, 'gateway', 'mailchuck') 351 self.config.save() 352 queues.UISignalQueue.put(('updateStatusBar', _translate( 353 "EmailGatewayDialog", 354 "Sending email gateway registration request" 355 ))) 356 elif self.radioButtonUnregister.isChecked(): 357 self.acct.unregister() 358 self.config.remove_option(self.acct.fromAddress, 'gateway') 359 self.config.save() 360 queues.UISignalQueue.put(('updateStatusBar', _translate( 361 "EmailGatewayDialog", 362 "Sending email gateway unregistration request" 363 ))) 364 elif self.radioButtonStatus.isChecked(): 365 self.acct.status() 366 queues.UISignalQueue.put(('updateStatusBar', _translate( 367 "EmailGatewayDialog", 368 "Sending email gateway status request" 369 ))) 370 elif self.radioButtonSettings.isChecked(): 371 self.data = self.acct 372 373 super(EmailGatewayDialog, self).accept()