%PDF- %PDF-
Direktori : /lib/calibre/calibre/gui2/preferences/ |
Current File : //lib/calibre/calibre/gui2/preferences/emailp.py |
#!/usr/bin/env python3 # License: GPLv3 Copyright: 2010, Kovid Goyal <kovid at kovidgoyal.net> import re import textwrap from qt.core import QAbstractTableModel, QFont, Qt, QAbstractItemView from calibre.gui2 import gprefs from calibre.gui2.preferences import AbortCommit, ConfigWidgetBase, test_widget from calibre.gui2.preferences.email_ui import Ui_Form from calibre.utils.config import ConfigProxy from calibre.utils.icu import numeric_sort_key from calibre.utils.smtp import config as smtp_prefs from polyglot.builtins import as_unicode class EmailAccounts(QAbstractTableModel): # {{{ def __init__(self, accounts, subjects, aliases={}, tags={}): QAbstractTableModel.__init__(self) self.accounts = accounts self.subjects = subjects self.aliases = aliases self.tags = tags self.sorted_on = (0, True) self.account_order = list(self.accounts) self.do_sort() self.headers = [_('Email'), _('Formats'), _('Subject'), _('Auto send'), _('Alias'), _('Auto send only tags')] self.default_font = QFont() self.default_font.setBold(True) self.default_font = (self.default_font) self.tooltips =[None] + list(map(textwrap.fill, [_('Formats to email. The first matching format will be sent.'), _('Subject of the email to use when sending. When left blank ' 'the title will be used for the subject. Also, the same ' 'templates used for "Save to disk" such as {title} and ' '{author_sort} can be used here.'), '<p>'+_('If checked, downloaded news will be automatically ' 'mailed to this email address ' '(provided it is in one of the listed formats and has not been filtered by tags).'), _('Friendly name to use for this email address'), _('If specified, only news with one of these tags will be sent to' ' this email address. All news downloads have their title as a' ' tag, so you can use this to easily control which news downloads' ' are sent to this email address.') ])) def do_sort(self): col = self.sorted_on[0] if col == 0: def key(account_key): return numeric_sort_key(account_key) elif col == 1: def key(account_key): return numeric_sort_key(self.accounts[account_key][0] or '') elif col == 2: def key(account_key): return numeric_sort_key(self.subjects.get(account_key) or '') elif col == 3: def key(account_key): return numeric_sort_key(as_unicode(self.accounts[account_key][0]) or '') elif col == 4: def key(account_key): return numeric_sort_key(self.aliases.get(account_key) or '') elif col == 5: def key(account_key): return numeric_sort_key(self.tags.get(account_key) or '') self.account_order.sort(key=key, reverse=not self.sorted_on[1]) def sort(self, column, order=Qt.SortOrder.AscendingOrder): nsort = (column, order == Qt.SortOrder.AscendingOrder) if nsort != self.sorted_on: self.sorted_on = nsort self.beginResetModel() try: self.do_sort() finally: self.endResetModel() def rowCount(self, *args): return len(self.account_order) def columnCount(self, *args): return len(self.headers) def headerData(self, section, orientation, role): if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal: return self.headers[section] return None def data(self, index, role): row, col = index.row(), index.column() if row < 0 or row >= self.rowCount(): return None account = self.account_order[row] if account not in self.accounts: return None if role == Qt.ItemDataRole.UserRole: return (account, self.accounts[account]) if role == Qt.ItemDataRole.ToolTipRole: return self.tooltips[col] if role in [Qt.ItemDataRole.DisplayRole, Qt.ItemDataRole.EditRole]: if col == 0: return (account) if col == 1: return ', '.join(x.strip() for x in (self.accounts[account][0] or '').split(',')) if col == 2: return (self.subjects.get(account, '')) if col == 4: return (self.aliases.get(account, '')) if col == 5: return (self.tags.get(account, '')) if role == Qt.ItemDataRole.FontRole and self.accounts[account][2]: return self.default_font if role == Qt.ItemDataRole.CheckStateRole and col == 3: return (Qt.CheckState.Checked if self.accounts[account][1] else Qt.CheckState.Unchecked) return None def flags(self, index): if index.column() == 3: return QAbstractTableModel.flags(self, index)|Qt.ItemFlag.ItemIsUserCheckable else: return QAbstractTableModel.flags(self, index)|Qt.ItemFlag.ItemIsEditable def setData(self, index, value, role): if not index.isValid(): return False row, col = index.row(), index.column() account = self.account_order[row] if col == 3: self.accounts[account][1] ^= True elif col == 2: self.subjects[account] = as_unicode(value or '') elif col == 4: self.aliases.pop(account, None) aval = as_unicode(value or '').strip() if aval: self.aliases[account] = aval elif col == 5: self.tags.pop(account, None) aval = as_unicode(value or '').strip() if aval: self.tags[account] = aval elif col == 1: self.accounts[account][0] = re.sub(',+', ',', re.sub(r'\s+', ',', as_unicode(value or '').upper())) elif col == 0: na = as_unicode(value or '') from email.utils import parseaddr addr = parseaddr(na)[-1] if not addr or '@' not in na: return False self.accounts[na] = self.accounts.pop(account) self.account_order[row] = na if '@kindle.com' in addr: self.accounts[na][0] = 'AZW, MOBI, TPZ, PRC, AZW1' self.dataChanged.emit( self.index(index.row(), 0), self.index(index.row(), 3)) return True def make_default(self, index): if index.isValid(): self.beginResetModel() row = index.row() for x in self.accounts.values(): x[2] = False self.accounts[self.account_order[row]][2] = True self.endResetModel() def add(self): x = _('new email address') y = x c = 0 while y in self.accounts: c += 1 y = x + str(c) auto_send = len(self.accounts) < 1 self.beginResetModel() self.accounts[y] = ['MOBI, EPUB', auto_send, len(self.account_order) == 0] self.account_order = list(self.accounts) self.do_sort() self.endResetModel() return self.index(self.account_order.index(y), 0) def remove_rows(self, *rows): for row in sorted(rows, reverse=True): try: account = self.account_order[row] except Exception: continue self.accounts.pop(account) self.account_order = sorted(self.accounts) has_default = False for account in self.account_order: if self.accounts[account][2]: has_default = True break if not has_default and self.account_order: self.accounts[self.account_order[0]][2] = True self.beginResetModel() self.endResetModel() self.do_sort() def remove(self, index): if index.isValid(): self.remove(index.row()) # }}} class ConfigWidget(ConfigWidgetBase, Ui_Form): supports_restoring_to_defaults = False def genesis(self, gui): self.gui = gui self.proxy = ConfigProxy(smtp_prefs()) r = self.register r('add_comments_to_email', gprefs) self.send_email_widget.initialize(self.preferred_to_address) self.send_email_widget.changed_signal.connect(self.changed_signal.emit) opts = self.send_email_widget.smtp_opts self._email_accounts = EmailAccounts(opts.accounts, opts.subjects, opts.aliases, opts.tags) connect_lambda(self._email_accounts.dataChanged, self, lambda self: self.changed_signal.emit()) self.email_view.setModel(self._email_accounts) self.email_view.sortByColumn(0, Qt.SortOrder.AscendingOrder) self.email_view.setSortingEnabled(True) self.email_add.clicked.connect(self.add_email_account) self.email_make_default.clicked.connect(self.make_default) self.email_view.resizeColumnsToContents() self.email_remove.clicked.connect(self.remove_email_account) def preferred_to_address(self): if self._email_accounts.account_order: return self._email_accounts.account_order[0] def initialize(self): ConfigWidgetBase.initialize(self) # Initializing all done in genesis def restore_defaults(self): ConfigWidgetBase.restore_defaults(self) # No defaults to restore to def commit(self): if self.email_view.state() == QAbstractItemView.State.EditingState: # Ensure that the cell being edited is committed by switching focus # to some other widget, which automatically closes the open editor self.send_email_widget.setFocus(Qt.FocusReason.OtherFocusReason) to_set = bool(self._email_accounts.accounts) if not self.send_email_widget.set_email_settings(to_set): raise AbortCommit('abort') self.proxy['accounts'] = self._email_accounts.accounts self.proxy['subjects'] = self._email_accounts.subjects self.proxy['aliases'] = self._email_accounts.aliases self.proxy['tags'] = self._email_accounts.tags return ConfigWidgetBase.commit(self) def make_default(self, *args): self._email_accounts.make_default(self.email_view.currentIndex()) self.changed_signal.emit() def add_email_account(self, *args): index = self._email_accounts.add() self.email_view.setCurrentIndex(index) self.email_view.resizeColumnsToContents() self.email_view.edit(index) self.changed_signal.emit() def remove_email_account(self, *args): rows = set() for idx in self.email_view.selectionModel().selectedIndexes(): rows.add(idx.row()) self._email_accounts.remove_rows(*rows) self.changed_signal.emit() def refresh_gui(self, gui): from calibre.gui2.email import gui_sendmail gui_sendmail.calculate_rate_limit() if __name__ == '__main__': from calibre.gui2 import Application app = Application([]) test_widget('Sharing', 'Email')