def showDeleteConfirmationDialog(self, row): media_print = self.search_media or NSLocalizedString("all", "Label") tag = self.period.selectedItem().tag() period = '%s %s' % (NSLocalizedString(" newer than", "Date label") if tag < 4 else NSLocalizedString(" older than", "Date label"), self.period_array[tag].strftime("%Y-%m-%d")) if tag else '' if row == 0: label = NSLocalizedString("Please confirm the deletion of %s history entries", "Label") % media_print + period + ". "+ NSLocalizedString("This operation cannot be undone. ", "Label") ret = NSRunAlertPanel(NSLocalizedString("Purge History Entries", "Window title"), label, NSLocalizedString("Confirm", "Button title"), NSLocalizedString("Cancel", "Button title"), None) if ret == NSAlertDefaultReturn: self.delete_messages(media_type=self.search_media, after_date=self.after_date, before_date=self.before_date) elif row == 1: remote_uri=self.contacts[row].uri label = NSLocalizedString("Please confirm the deletion of %s Bonjour history entries", "Label") % media_print + period + ". "+ NSLocalizedString("This operation cannot be undone. ", "Label") ret = NSRunAlertPanel(NSLocalizedString("Purge History Entries", "Window title"), label, NSLocalizedString("Confirm", "Button title"), NSLocalizedString("Cancel", "Button title"), None) if ret == NSAlertDefaultReturn: self.delete_messages(local_uri='bonjour.local', media_type=self.search_media, after_date=self.after_date, before_date=self.before_date) else: contact = self.contacts[row] if contact.presence_contact is not None: remote_uri = list(str(contact.uri) for contact in contact.presence_contact.uris) else: remote_uri = contact.uri label = NSLocalizedString("Please confirm the deletion of %s history entries", "Label") % media_print + NSLocalizedString(" from ", "Label") + contact.name + period + ". "+ NSLocalizedString("This operation cannot be undone. ", "Label") ret = NSRunAlertPanel(NSLocalizedString("Purge History Entries", "Window title"), label, NSLocalizedString("Confirm", "Button title"), NSLocalizedString("Cancel", "Button title"), None) if ret == NSAlertDefaultReturn: self.delete_messages(remote_uri=remote_uri, media_type=self.search_media, after_date=self.after_date, before_date=self.before_date)
def about_(self, notification): if versionCheck(): AboutTitle = LONGVERSION + " (Update Available!)" about = NSRunAlertPanel(AboutTitle, AboutText , "OK", "Visit Website", "Download Update" ) else: about = NSRunAlertPanel(LONGVERSION, AboutText , "OK", "Visit Website", None ) if about == 0: webbrowser.open(appUrl) elif about == -1: webbrowser.open(updateUrl)
def validate(self): if self.radioMatrix.selectedCell().tag() == 1: # Login display_name = str(self.displayNameText.stringValue().strip()) address = str(self.addressText.stringValue().strip()) password = str(self.passwordText.stringValue().strip()) if not address or "@" not in address: NSRunAlertPanel(NSLocalizedString("Sign In to SIP Account", "Window title"), NSLocalizedString("Please enter your SIP address provided by your SIP service provider. The address must be in user@domain format, for example [email protected]", "Label"), NSLocalizedString("OK", "Button title"), None, None) return False if self.allowed_domains: domain = address.split("@")[1] if domain not in self.allowed_domains: NSRunAlertPanel(NSLocalizedString("Sign In to SIP Account", "Window title"), NSLocalizedString("Invalid domain name chosen. Valid domain names are: %s", "Label") % ",".join(self.allowed_domains), NSLocalizedString("OK", "Button title"), None, None) return False if not password: NSRunAlertPanel(NSLocalizedString("Sign In to SIP Account", "Window title"), NSLocalizedString("Please enter your account password.", "Label"), NSLocalizedString("OK", "Button title"), None, None) return False return True else: # Enroll display_name = str(self.newDisplayNameText.stringValue().strip()) username = str(self.newUsernameText.stringValue().strip()) password = str(self.newPasswordText.stringValue().strip()) password2 = str(self.newConfirmText.stringValue().strip()) email = str(self.newEmailText.stringValue()) if not display_name: NSRunAlertPanel(NSLocalizedString("Sign In to SIP Account", "Window title"), NSLocalizedString("Please enter your Display Name.", "Label"), NSLocalizedString("OK", "Button title"), None, None) return False if not username.strip(): NSRunAlertPanel(NSLocalizedString("Sign In to SIP Account", "Window title"), NSLocalizedString("Please choose a Username for your account.", "Label"), NSLocalizedString("OK", "Button title"), None, None) return False if not re.match("^[1-9a-z][0-9a-z_.-]{2,65}[0-9a-z]$", username): NSRunAlertPanel(NSLocalizedString("Sign Up For a SIP Account", "Window title"), NSLocalizedString("The Username must contain at least 4 lowercase alpha-numeric . _ or - characters and must start and end with a positive digit or letter", "Label"), NSLocalizedString("OK", "Button title"), None, None) return False def validate_email(email): return "@" in email if not password: NSRunAlertPanel(NSLocalizedString("Sign Up For a SIP Account", "Window title"), NSLocalizedString("Please enter a Password for your new SIP Account.", "Label"), NSLocalizedString("OK", "Button title"), None, None) return False if password != password2: NSRunAlertPanel(NSLocalizedString("Sign Up For a SIP Account", "Window title"), NSLocalizedString("Entered Password confirmation doesn't match.", "Label"), NSLocalizedString("OK", "Button title"), None, None) return False if not email or not validate_email(email): NSRunAlertPanel(NSLocalizedString("Sign Up For a SIP Account", "Window title"), NSLocalizedString("Please enter a valid email address.", "Label"), NSLocalizedString("OK", "Button title"), None, None) return False return True
def validateConference(self, allow_random_room=True): self.nickname = self.nickname_textfield.stringValue().strip() room = self.validateRoom(allow_random_room) if not room: return False if self.chat.state() == NSOffState and self.audio.state() == NSOffState: NSRunAlertPanel(NSLocalizedString("Start New Conference", "Window title"), NSLocalizedString("Please select at least one media type. ", "Label"), NSLocalizedString("OK", "Button title"), None, None) return False if "@" in room: self.target = '%s' % room else: account = AccountManager().default_account if isinstance(account, BonjourAccount): item = self.bonjour_server_combolist.selectedItem() if item is None: NSRunAlertPanel(NSLocalizedString("Start New Conference", "Window title"), NSLocalizedString("No conference server in this neighbourhood", "Label"), NSLocalizedString("OK", "Button title"), None, None) return False object = item.representedObject() if hasattr(object, 'host'): self.target = '%s@%s:%s;transport=%s' % (room, object.uri.host, object.uri.port, object.uri.parameters.get('transport','udp')) else: NSRunAlertPanel(NSLocalizedString("Start a new Conference", "Window title"), NSLocalizedString("No conference server in this neighbourhood", "Label"), NSLocalizedString("OK", "Button title"), None, None) return False else: if account.conference.server_address: self.target = '%s@%s' % (room, account.conference.server_address) else: self.target = '%s@%s' % (room, default_conference_server) if not validateParticipant(self.target): NSRunAlertPanel(NSLocalizedString("Start New Conference", "Window title"), NSLocalizedString("Invalid conference SIP address: %s", "Label") % self.target, NSLocalizedString("OK", "Button title"), None, None) return False return True
def addExistingAccount(self): try: display_name = str(self.displayNameText.stringValue().strip()) address = str(self.addressText.stringValue().strip()) password = str(self.passwordText.stringValue().strip()) sync_with_icloud = True if self.syncWithiCloudCheckbox.state() == NSOnState else False account = Account(str(address)) account.display_name = display_name account.auth.password = password account.enabled = True account.gui.sync_with_icloud = sync_with_icloud account.xcap.enabled = True if self.syncContactsCheckBox.state() == NSOnState else False account.presence.enabled = True if self.syncContactsCheckBox.state() == NSOnState else False if account.id.domain == 'sip2sip.info': account.server.settings_url = "https://blink.sipthor.net/settings.phtml" account.ldap.hostname = "ldap.sipthor.net" account.ldap.dn = "ou=addressbook, dc=sip2sip, dc=info" account.ldap.enabled = True account.nat_traversal.use_ice = True account.rtp.srtp_encryption = 'optional' account.save() except ValueError as e: NSRunAlertPanel(NSLocalizedString("Sign In to SIP Account", "Window title"), NSLocalizedString("Cannot add SIP Account: %s", "Label") % e, NSLocalizedString("OK", "Button title"), None, None) return False AccountManager().default_account = account return True
def userClickedToolbarItem_(self, sender): if sender.itemIdentifier() == 'smileys': self.chatViewController.expandSmileys = not self.chatViewController.expandSmileys sender.setImage_(NSImage.imageNamed_("smiley_on" if self.chatViewController.expandSmileys else "smiley_off")) self.chatViewController.toggleSmileys(self.chatViewController.expandSmileys) row = self.contactTable.selectedRow() if row and row > 1 and self.contacts[row].presence_contact is not None: self.contacts[row].presence_contact.contact.disable_smileys = not self.contacts[row].presence_contact.contact.disable_smileys self.contacts[row].presence_contact.contact.save() elif sender.itemIdentifier() == 'delete': if self.selectedTableView == self.contactTable: try: row = self.contactTable.selectedRow() self.showDeleteConfirmationDialog(row) except IndexError: pass elif self.selectedTableView == self.indexTable: try: row = self.indexTable.selectedRow() local_uri = self.dayly_entries[row].objectForKey_("local_uri") remote_uri = self.dayly_entries[row].objectForKey_("remote_uri") remote_uri_sql = self.dayly_entries[row].objectForKey_("remote_uri_sql") date = self.dayly_entries[row].objectForKey_("date") media_type = self.dayly_entries[row].objectForKey_("type") label = NSLocalizedString("Please confirm the deletion of %s history entries", "Label") % media_type + NSLocalizedString(" from %s", "SIP Address label") % remote_uri + NSLocalizedString(" on %s. ", "Date label") % date + NSLocalizedString("This operation cannot be undone. ", "Label") ret = NSRunAlertPanel(NSLocalizedString("Purge History Entries", "Window title"), label, NSLocalizedString("Confirm", "Button title"), NSLocalizedString("Cancel", "Button title"), None) if ret == NSAlertDefaultReturn: self.delete_messages(local_uri=local_uri, remote_uri=remote_uri_sql, media_type=media_type, date=date) except IndexError: pass
def cropAndAddImage(self, path): try: image = NSImage.alloc().initWithContentsOfFile_(path) except: NSRunAlertPanel( NSLocalizedString("Camera Capture Error", "Window title"), NSLocalizedString("%s is not a valid image", "Label") % path, NSLocalizedString("OK", "Button title"), None, None) return rect = NSZeroRect.copy() rect.size = image.size() curSize = self.cropWindow.frame().size if rect.size.width > curSize.width or rect.size.height > curSize.height: self.cropWindowImage.setFrame_(rect) self.cropOriginalImage = image.copy() self.cropWindowImage.setImage_(image) if NSApp.runModalForWindow_(self.cropWindow) == NSOKButton: dt = datetime.datetime.now().strftime("%Y%m%d%H%M%S") image = self.cropWindowImage.getCropped() path = self.storage_folder + "/photo%s.png" % dt jpg_data = NSBitmapImageRep.alloc().initWithData_( image. TIFFRepresentation()).representationUsingType_properties_( NSJPEGFileType, {NSImageCompressionFactor: 0.9}) data = jpg_data.bytes().tobytes() with open(path, 'wb') as f: f.write(data) self.cropWindow.orderOut_(None) self.refreshLibrary() else: self.cropWindow.orderOut_(None)
def addRemoveParticipant_(self, sender): if sender.selectedSegment() == 0: participant = self.participant.stringValue().strip().lower() if participant and "@" not in participant and self.default_domain: participant = '%s@%s' % (participant, self.default_domain) if participant: participant = sip_prefix_pattern.sub("", str(participant)) if not participant or not validateParticipant(participant): NSRunAlertPanel(NSLocalizedString("Add New Participant", "Window title"), NSLocalizedString("Participant must be a valid SIP address. ", "Label"), NSLocalizedString("OK", "Button title"), None, None) return if participant not in self._participants: self._participants.append(participant) self.startWhenParticipantsAvailable.setEnabled_(True) self.participantsTable.reloadData() self.participantsTable.scrollRowToVisible_(len(self._participants)-1) self.participant.setStringValue_('') elif sender.selectedSegment() == 1: participant = self.selectedParticipant() if participant is None and self._participants: participant = self._participants[-1] if participant is not None: self._participants.remove(participant) self.startWhenParticipantsAvailable.setEnabled_(bool(len(self._participants))) if len(self._participants) == 0: self.startWhenParticipantsAvailable.setState_(NSOffState) self.participantsTable.reloadData()
def addImageFile(self, path): path = os.path.normpath(path) if os.path.dirname(path) != self.storage_folder: # scale and copy the image to our photo dir try: image = NSImage.alloc().initWithContentsOfFile_(path) except: NSRunAlertPanel( NSLocalizedString("Camera Capture Error", "Window title"), NSLocalizedString("%s is not a valid image", "Label") % path, NSLocalizedString("OK", "Button title"), None, None) return size = image.size() if size.width > 128 or size.height > 128: image.setScalesWhenResized_(True) image.setSize_(NSMakeSize(128, 128 * size.height / size.width)) finalpath = self.storage_folder + "/" + os.path.basename(path) prefix, ext = os.path.splitext(finalpath) i = 0 while os.path.exists(finalpath): finalpath = prefix + str(i) + ext image.TIFFRepresentation().writeToFile_atomically_( finalpath, False) self.refreshLibrary()
def download_didFailWithError_(self, download, error): download.cancel() BlinkLogger().log_info("Download error: %s" % error.localizedDescription()) e = error.localizedDescription() NSRunAlertPanel( NSLocalizedString("Error", "Window title"), NSLocalizedString("Error downloading file: %s", "Label") % e, NSLocalizedString("OK", "Button title"), "", "")
def showWindow_(self, sender): """ Do something like show a window""" if not hasAllModules: ErrorString = "This plugin needs the vanilla and drawbot module to be installed for python %d.%d." % ( sys.version_info[0], sys.version_info[1]) NSRunAlertPanel("Problem with some modules", ErrorString, "", "", "") return GlyphGiffer()
def okClicked_(self, sender): if not len(self._participants): NSRunAlertPanel( NSLocalizedString("Add Participants to the Conference", "Window title"), NSLocalizedString("Please add at least one participant. ", "Label"), NSLocalizedString("OK", "Button title"), None, None) else: NSApp.stopModalWithCode_(NSOKButton)
class IDNSnitch(NSObject): def init(self): super(IDNSnitch, self).init() self.HOSTS = {} return self def runDialog_(self, (res, dialog)): from AppKit import NSRunAlertPanel, NSAlertDefaultReturn res.append(NSRunAlertPanel(*dialog) != NSAlertDefaultReturn) return
def convert_(self, sender): rate = self.rateField.floatValue() amt = self.dollarField.floatValue() total = self.converter.convertAmount(rate, amt) self.totalField.setFloatValue_(total) self.rateField.selectText_(self) x = NSRunAlertPanel("Calculation Result", "The result is %s" % (total), "OK", None, None)
def unexpectedErrorAlertPanel(): exceptionInfo = traceback.format_exception_only(*sys.exc_info()[:2])[0].strip() return NSRunAlertPanel( "An unexpected error has occurred", "%@", "Continue", "Quit", None, "(%s)" % exceptionInfo, )
def tableView_setObjectValue_forTableColumn_row_(self, table, object, column, row): cell = column.dataCell() column = int(column.identifier()) if not object: if column == 0: # delete row if row < len(self.uris): try: del self.uris[row] except IndexError: pass self.update_default_uri() table.reloadData() return else: return if row >= len(self.uris): if column == 0: has_empty_cell = any(value for value in self.uris if not value) if not has_empty_cell: self.uris.append(ContactURI(uri="", type="SIP")) try: contact_uri = self.uris[row] except IndexError: pass else: if column == 0: uri = str(object).strip().lower().replace(" ", "") if not self.checkURI(uri): NSRunAlertPanel(NSLocalizedString("Invalid Address", "Window title"), NSLocalizedString("Please enter an address containing alpha numeric characters", "Label"), NSLocalizedString("OK", "Button title"), None, None) return contact_uri.uri = uri if uri.startswith(('https:', 'http:')): contact_uri.type = 'URL' elif '@' in uri: domain = uri.partition("@")[-1] domain = domain if ':' not in domain else domain.partition(":")[0] if domain in ('jit.si', 'gmail.com', 'comm.unicate.me') or 'jabb' in domain or 'xmpp' in domain or domain.endswith('.im') or domain.startswith('im.'): contact_uri.type = 'XMPP' if len(self.uris) == 1: self.preferred_media = 'chat' self.updateSubscriptionMenus() elif column == 1: contact_uri.type = str(cell.itemAtIndex_(object).title()) self.update_default_uri() table.reloadData() row = self.addressTable.selectedRow() self.defaultButton.setEnabled_(row < len(self.uris))
def alert_n(kind, prompt, label1, label2, label3): splat = prompt.split("\n", 1) title = splat[0] if len(splat) > 1: msg = splat[1] else: msg = "" if kind == 'caution': return NSRunCriticalAlertPanel(title, msg, label1, label2, label3) elif kind == 'note': return NSRunInformationalAlertPanel(title, msg, label1, label2, label3) else: return NSRunAlertPanel(title, msg, label1, label2, label3)
def sessionStateChanged(self, newstate, detail): if newstate == STATE_DNS_FAILED: if self.statusWindow: self.statusLabel.setStringValue_( NSLocalizedString("Error starting screen sharing session.", "Label")) self.statusProgress.stopAnimation_(None) else: e = NSLocalizedString("Error starting screen sharing session.", "Label") + "\n%s" % detail NSRunAlertPanel(NSLocalizedString("Error", "Window title"), e, NSLocalizedString("OK", "Button title"), None, None) self.changeStatus(STREAM_FAILED, detail) elif newstate == STATE_FAILED: if self.statusWindow: self.statusProgress.stopAnimation_(None) else: if detail and detail.lower( ) != "session cancelled" and not self.sessionController.hasStreamOfType( "audio"): e = NSLocalizedString( "Error starting screen sharing session.", "Label") + "\n%s" % detail NSRunAlertPanel(NSLocalizedString("Error", "Window title"), e, NSLocalizedString("OK", "Button title"), "", "") self.changeStatus(STREAM_FAILED, detail) elif newstate == STATE_CONNECTED: # if the session is in connected state (ie, got SessionDidStart), we should have already # received MediaStreamDidStart or DidEnd to indicate whether we got accepted if self.status == STREAM_IDLE: if self.direction == "passive": # we got rejected self.statusLabel.setStringValue_( NSLocalizedString( "Error starting screen sharing session.", "Label")) self.statusProgress.stopAnimation_(None)
def validateRoom(self, allow_random_room=True): if not self.room.stringValue().strip() and allow_random_room: room = random_room() else: room=self.room.stringValue().lower().strip() if not re.match("^[+1-9a-z][0-9a-z_.-]{0,65}[0-9a-z]", room): NSRunAlertPanel(NSLocalizedString("Start New Conference", "Window title"), NSLocalizedString("Please enter a valid conference room of at least 2 alpha-numeric . _ or - characters, it must start and end with a +, a positive digit or letter", "Label"), NSLocalizedString("OK", "Button title"), None, None) return False else: return room
def check_version(self): infodict = NSBundle.mainBundle().infoDictionary() mailversion = infodict['CFBundleVersion'] lastknown = self.prefs.string["MailTrackLastKnownBundleVersion"] if lastknown and lastknown != mailversion: NSRunAlertPanel( 'MailTrack plug-in', ''' The MailTrack plug-in detected a different Mail.app version (perhaps you updated?). If you run into any problems with regards to replying or forwarding mail, consider removing this plug-in (from ~/Library/Mail/Bundles/). (This alert is only displayed once for each new version of Mail.app)''', None, None, None) self.prefs.string["MailTrackLastKnownBundleVersion"] = mailversion
def exception_handler(): import traceback, sys, os typ, info, trace = sys.exc_info() if typ in (KeyboardInterrupt, SystemExit): return tracetop = traceback.extract_tb(trace)[-1] tracetext = 'File %s, Line %d' % tracetop[:2] if tracetop[2] != '?': tracetext += ', Function %s' % tracetop[2] exception_message = '%s:\n%s\n\n%s\n"%s"' message = exception_message % (str(type), str(info), tracetext, tracetop[3]) title = os.path.splitext(os.path.basename(sys.argv[0]))[0] title = title.capitalize() + ' Error' NSRunAlertPanel(title, message, None, None, None)
def signature_matcher(self): matcher = None # use custom matcher? if self.prefs.bool["QuoteFixUseCustomSignatureMatcher"]: matcher = self.prefs.string["QuoteFixCustomSignatureMatcher"] if not matcher: matcher = self.default_signature_matcher # try to compile regular expression to catch errors early try: re.compile(matcher) except re.error, e: matcher = self.default_signature_matcher NSRunAlertPanel( 'QuoteFix plug-in', 'The supplied custom signature matcher contains an invalid regular expression (error: "%s").\n\nI will revert back to the default matcher until the problem is fixed in the preferences.' % str(e), None, None, None)
def addParticipant(self, participant): if participant and "@" not in participant: participant = participant + '@' + self.default_domain if not participant or not validateParticipant(participant): NSRunAlertPanel(NSLocalizedString("Add New Participant", "Window title"), NSLocalizedString("Participant must be a valid SIP address. ", "Label"), NSLocalizedString("OK", "Button title"), None, None) return if participant not in self._participants: self.startWhenParticipantsAvailable.setEnabled_(True) self._participants.append(participant) self.participantsTable.reloadData() self.participantsTable.scrollRowToVisible_(len(self._participants)-1) self.participant.setStringValue_('')
def doubleClick_(self, sender): row = self.contactTable.selectedRow() if row < 2: return try: contact = self.contacts[row] except IndexError: return if '@' in contact.uri: NSApp.delegate().contactsWindowController.startSessionWithTarget(contact.uri) else: bonjour_contact = NSApp.delegate().contactsWindowController.model.getBonjourContactMatchingDeviceId(contact.uri) if not bonjour_contact: BlinkLogger().log_info("Bonjour neighbour %s was not found on this network" % contact.name) message = NSLocalizedString("Bonjour neighbour %s was not found on this network. ", "label") % contact.name NSRunAlertPanel(NSLocalizedString("Error", "Window title"), message, NSLocalizedString("OK", "Button title"), None, None) return NSApp.delegate().contactsWindowController.startSessionWithTarget(bonjour_contact.uri)
def applicationDidFinishLaunching_(self, sender): BlinkLogger().log_debug("Application launched") branding_file = NSBundle.mainBundle().infoDictionary().objectForKey_("BrandingFile") try: branding = __import__(branding_file) except ImportError: try: import branding except ImportError: branding = Null branding.setup(self) if self.updater and self.sp_update_url is not None: self.updater.sp.setFeedURL_(NSURL.URLWithString_(self.sp_update_url)) self.blinkMenu.setTitle_(self.applicationNamePrint) config_file = ApplicationData.get('config') self.icloud_manager = iCloudManager() self.backend = SIPManager() self.contactsWindowController.setup(self.backend) while True: try: first_run = not os.path.exists(config_file) self.contactsWindowController.first_run = first_run self.backend.init() self.backend.fetch_account() accounts = AccountManager().get_accounts() if not accounts or (first_run and accounts == [BonjourAccount()]): self.wait_for_enrollment = True self.enroll() break except FileParserError as exc: BlinkLogger().log_warning("Error parsing configuration file: %s" % exc) if NSRunAlertPanel(NSLocalizedString("Error", "Window title"), NSLocalizedString("The configuration file is corrupted. You will need to replace it and re-enter your account information. \n\nYour current configuration file will be backed up to %s.corrupted. ", "Label") % config_file, NSLocalizedString("Replace", "Button title"), NSLocalizedString("Quit", "Button title"), None) != NSAlertDefaultReturn: NSApp.terminate_(None) return os.rename(config_file, config_file+".corrupted") BlinkLogger().log_info("Renamed configuration file to %s" % config_file+".corrupted") except BaseException as exc: import traceback print(traceback.print_exc()) NSRunAlertPanel(NSLocalizedString("Error", "Window title"), NSLocalizedString("There was an error during startup of core functionality:\n%s", "Label") % exc, NSLocalizedString("Quit", "Button title"), None, None) NSApp.terminate_(None) return # window should be shown only after enrollment check if self.wait_for_enrollment: BlinkLogger().log_info('Starting User Interface') self.contactsWindowController.model.moveBonjourGroupFirst() self.contactsWindowController.showWindow_(None) self.wait_for_enrollment = False self.contactsWindowController.setupFinished() SMSWindowManager.SMSWindowManager().setOwner_(self.contactsWindowController) self.debugWindow = DebugWindow.alloc().init() self.chatWindowController = ChatWindowController.ChatWindowController.alloc().init()
def fix(self): try: # if toggle key is active, temporarily switch the active state is_active = self.app.toggle_key_active ^ self.app.is_active # check if we can proceed if not is_active: logger.debug("QuoteFix is not active, so no QuoteFixing for you!") return # Grab some variables we need to perform our business view = self.composeWebView() # contains the message editor backend = self.backEnd() htmldom = view.mainFrame().DOMDocument() htmlroot = htmldom.documentElement() messageType = self.messageType() # XXX: hack alert! if message type is DRAFT, but we can determine this # is actually a Send Again action, adjust the message type. origmsg = backend.originalMessage() if origmsg and messageType == DRAFT and origmsg.type() == 0: messageType = SENDAGAIN # send original HTML to menu for debugging self.app.html = htmlroot.innerHTML() # provide custom attribution? attributor = None if self.app.use_custom_reply_attribution and messageType in [ REPLY, REPLY_ALL, REPLY_AS ]: logger.debug("calling customize_attribution() for reply{-all,-as}") attributor = CustomizedAttribution.customize_reply elif self.app.use_custom_sendagain_attribution and messageType in [ SENDAGAIN ]: logger.debug("calling customize_attribution() for Send Again") attributor = CustomizedAttribution.customize_sendagain elif self.app.use_custom_forwarding_attribution and messageType == FORWARD: logger.debug("calling customize_attribution() for forwarding") attributor = CustomizedAttribution.customize_forward if attributor: try: for original in objc.getInstanceVariable( backend, '_originalMessages'): attributor( app=self.app, editor=self, dom=htmldom, reply=backend.message(), inreplyto=original, ) backend.setHasChanges_(False) except: # ignore when not debugging if self.app.is_debugging: raise # should we be quotefixing? if not self.app.is_quotefixing: logger.debug( 'quotefixing turned off in preferences, skipping that part') elif messageType not in self.app.message_types_to_quotefix: logger.debug('message type "%s" not in %s, not quotefixing' % (messageType, self.app.message_types_to_quotefix)) else: # remove attachment placeholders? if self.app.remove_attachment_placeholders: logger.debug('calling remove_attachment_placeholders()') self.remove_attachment_placeholders(backend, htmlroot) # move cursor to end of document view.moveToEndOfDocument_(self) # remove quotes? if self.app.remove_quotes: logger.debug('calling remove_quotes()') self.remove_quotes(htmldom, self.app.remove_quotes_level) # make quotes selectable? if self.app.selectable_quotes: logger.debug('calling make_selectable_quotes()') self.make_selectable_quotes(view, htmldom) # remove signature from sender if not self.app.keep_sender_signature: logger.debug('calling remove_old_signature()') self.remove_old_signature(htmldom, view) # place cursor above own signature (if any) logger.debug('calling move_above_new_signature()') if self.move_above_new_signature(htmldom, view): # insert a paragraph break? if not self.app.no_whitespace_below_quote: view.insertParagraphSeparator_(self) else: view.insertNewline_(self) # perform some general cleanups logger.debug('calling cleanup_layout()') self.cleanup_layout(htmlroot, backend) # move cursor to top of document if self.app.move_cursor_to_top: view.moveToBeginningOfDocument_(self) # move to beginning of line logger.debug('calling view.moveToBeginningOfLine()') view.moveToBeginningOfLine_(self) # done logger.debug('QuoteFixing done') except Exception: logger.critical(traceback.format_exc()) if self.app.is_debugging: NSRunAlertPanel( 'QuoteFix caught an exception', 'The QuoteFix plug-in caught an exception:\n\n' + traceback.format_exc() + '\nPlease contact the developer quoting the contents of this alert.', None, None, None)
def show_error_panel(message): message = re.sub("%", "%%", message) NSRunAlertPanel("Error", message, "OK", None, None)
def checkForUpdates(): if versionCheck(): if NSRunAlertPanel(LONGVERSION, updateText , "Download Update", "Ignore for now", None ) == 1: webbrowser.open(updateUrl)
def customize_attribution(cls, original, editor, dom, reply, inreplyto, template, messagetype): is_forward = messagetype == FORWARD is_reply = messagetype == REPLY is_sendagain = messagetype == SENDAGAIN # create matcher for matching original attribution (and replace # nsbp's with normal spaces) if original: original = original.replace(u'\xa0', ' ').strip() original = original.replace('(', r'\(').replace(')', r'\)') original = re.sub(r'%\d+\$\@', '.*?', original) original = re.sub(r'\s+', '(?:\\s| )+', original) original = original + r'(?=[<\s])' matcher = re.compile(original) else: matcher = None # rich text message? is_rich = editor.backEnd().containsRichText() # should attribution be treated as HTML? is_html = (is_forward and cls.app.custom_forwarding_is_html) or \ (is_sendagain and cls.app.custom_sendagain_is_html) or \ (is_reply and cls.app.custom_reply_is_html) # check if message is rich text with HTML-attribution if is_html and not is_rich: if (is_forward and cls.app.custom_forwarding_convert_to_rich) or \ (is_sendagain and cls.app.custom_sendagain_convert_to_rich) or \ (is_reply and cls.app.custom_reply_convert_to_rich): editor.makeRichText_(editor) elif not cls.app.dont_show_html_attribution_warning: idx = NSRunAlertPanel( "QuoteFix warning", "You are using an HTML-attribution, but the current message format is plain text.\n\n" + "Unless you convert to rich text, the HTML-formatting will be lost when sending the message.", "OK", "Don't show this warning again", None) if idx == 0: cls.app.dont_show_html_attribution_warning = True # render attribution attribution = cls.render_attribution( reply=reply, inreplyto=inreplyto, template=template, is_html=is_html, ) # replace leading whitespace with non-breaking spaces attribution = re.sub(r'(?m)^( +)', lambda m: u'\u00a0' * len(m.group(1)), attribution) attribution = re.sub(r'(?m)^(\t+)', lambda m: u'\u00a0\u00a0' * len(m.group(1)), attribution) # replace newlines with hard linebreaks attribution = attribution.replace('\n', '<br/>') # Get HTML contents of e-mail. root = dom.documentElement() html = root.innerHTML() # Fix attributions for Yosemite and up osMinorVersion = int(platform.mac_ver()[0].split('.')[1]) if osMinorVersion >= 10: # move <blockquote> one level down html = re.sub(r'(?i)(<blockquote.*?>)(.*?)(<br.*?>)+', r'\2\1', html, count=1) # Special case: Mail doesn't include an attribution for Send Again messages, # so we'll just add a customized attribution right after the <body> element. if is_sendagain or matcher == None: # TODO: limit quote level! html = re.sub(r'(?i)(?P<element><\s?body.*?>)', r'\g<element>' + attribution, html, count=1) elif matcher: html = matcher.sub(attribution, html, count=1) # Restore HTML of root element. root.setInnerHTML_(html) # TODO: increase quote level of attribution? # if (is_forward and cls.app.custom_forwarding_increase_quotelevel) or \ # (is_reply and cls.app.custom_reply_increase_quotelevel): # copy = copynode.cloneNode_(True) # copynode.parentNode().removeChild_(copynode) # blockquote = root.firstDescendantBlockQuote() # blockquote.insertBefore_refChild_(copy, blockquote.childNodes().item_(0)) return True
def finishLoadingEditor(self, original): logger.debug('DocumentEditor finishLoadingEditor') # execute original finishLoadingEditor() original(self) try: # if toggle key is active, temporarily switch the active state is_active = self.app.toggle_key_active ^ self.app.is_active # check if we can proceed if not is_active: logger.debug( "MailTrack is not active, so no MailTracking for you!") return # grab composeView instance (this is the WebView which contains the # message editor) and check for the right conditions try: view = objc.getInstanceVariable(self, 'composeWebView') except: # was renamed in Lion view = objc.getInstanceVariable(self, '_composeWebView') # grab some other variables we need to perform our business backend = self.backEnd() htmldom = view.mainFrame().DOMDocument() htmlroot = htmldom.documentElement() messageType = self.messageType() # XXX: hack alert! if message type is DRAFT, but we can determine this # is actually a Send Again action, adjust the message type. origmsg = backend.originalMessage() if origmsg and messageType == DRAFT: # get the message viewer for this message viewer = MessageViewer.existingViewerShowingMessage_(origmsg) if not viewer: # XXX: this happens with conversation view active, not sure if this is stable enough though messageType = SENDAGAIN elif viewer: # get the mailbox for the viewer mailboxes = viewer.selectedMailboxes() # get the Drafts mailbox draftmailbox = viewer.draftsMailbox() # check if they're the same; if not, it's a Send-Again if draftmailbox not in mailboxes: messageType = SENDAGAIN # send original HTML to menu for debugging self.app.html = htmlroot.innerHTML() if not self.app.is_mailtracking: logger.debug( 'mailtracking turned off in preferences, skipping that part' ) elif messageType not in self.app.message_types_to_track: logger.debug('message type "%s" not in %s, not tracking' % (messageType, self.app.message_types_to_track)) else: # move cursor to end of document view.moveToEndOfDocument_(self) # perform some general cleanups logger.debug('calling cleanup_layout()') if self.cleanup_layout(htmlroot, backend): backend.setHasChanges_(False) # move cursor to end of document if self.app.move_cursor_to_top: view.moveToBeginningOfDocument_(self) # move to beginning of line logger.debug('calling view.moveToBeginningOfLine()') view.moveToBeginningOfLine_(self) # done logger.debug('MailTracking done') except Exception: logger.critical(traceback.format_exc()) if self.app.is_debugging: NSRunAlertPanel( 'MailTrack caught an exception', 'The MailTrack plug-in caught an exception:\n\n' + traceback.format_exc() + '\nPlease contact the developer quoting the contents of this alert.', None, None, None)