Preferences widget for email sending

This commit is contained in:
Kovid Goyal 2010-09-04 22:33:33 -06:00
parent 6b8d204f07
commit a6bd77247d
5 changed files with 342 additions and 12 deletions

View File

@ -766,8 +766,17 @@ class Sending(PreferencesPlugin):
name_order = 3 name_order = 3
config_widget = 'calibre.gui2.preferences.sending' config_widget = 'calibre.gui2.preferences.sending'
class Email(PreferencesPlugin):
name = 'Email'
gui_name = _('Sending books by email')
category = 'Sharing'
gui_category = _('Sharing')
category_order = 4
name_order = 1
config_widget = 'calibre.gui2.preferences.emailp'
plugins += [LookAndFeel, Behavior, Columns, Toolbar, InputOptions, plugins += [LookAndFeel, Behavior, Columns, Toolbar, InputOptions,
CommonOptions, OutputOptions, Adding, Saving, Sending] CommonOptions, OutputOptions, Adding, Saving, Sending, Email]
#}}} #}}}

View File

@ -19,6 +19,7 @@ class AbortCommit(Exception):
class ConfigWidgetInterface(object): class ConfigWidgetInterface(object):
changed_signal = None changed_signal = None
supports_restoring_to_defaults = True
def genesis(self, gui): def genesis(self, gui):
raise NotImplementedError() raise NotImplementedError()
@ -165,6 +166,7 @@ class CommaSeparatedList(Setting):
class ConfigWidgetBase(QWidget, ConfigWidgetInterface): class ConfigWidgetBase(QWidget, ConfigWidgetInterface):
changed_signal = pyqtSignal() changed_signal = pyqtSignal()
supports_restoring_to_defaults = True
def __init__(self, parent=None): def __init__(self, parent=None):
QWidget.__init__(self, parent) QWidget.__init__(self, parent)
@ -243,6 +245,7 @@ def test_widget(category, name, gui=None):
w = pl.create_widget(d) w = pl.create_widget(d)
d.set_widget(w) d.set_widget(w)
bb.button(bb.RestoreDefaults).clicked.connect(w.restore_defaults) bb.button(bb.RestoreDefaults).clicked.connect(w.restore_defaults)
bb.button(bb.RestoreDefaults).setEnabled(w.supports_restoring_to_defaults)
bb.button(bb.Apply).setEnabled(False) bb.button(bb.Apply).setEnabled(False)
bb.button(bb.Apply).clicked.connect(d.accept) bb.button(bb.Apply).clicked.connect(d.accept)
w.changed_signal.connect(lambda : bb.button(bb.Apply).setEnabled(True)) w.changed_signal.connect(lambda : bb.button(bb.Apply).setEnabled(True))

View File

@ -0,0 +1,112 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>701</width>
<height>494</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_22">
<property name="text">
<string>calibre can send your books to you (or your reader) by email. Emails will be automatically sent for downloaded news to all email addresses that have Auto-send checked.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QTableView" name="email_view">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QToolButton" name="email_add">
<property name="toolTip">
<string>Add an email address to which to send books</string>
</property>
<property name="text">
<string>&amp;Add email</string>
</property>
<property name="icon">
<iconset resource="../../../../resources/images.qrc">
<normaloff>:/images/plus.png</normaloff>:/images/plus.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="email_make_default">
<property name="text">
<string>Make &amp;default</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="email_remove">
<property name="text">
<string>&amp;Remove email</string>
</property>
<property name="icon">
<iconset resource="../../../../resources/images.qrc">
<normaloff>:/images/minus.png</normaloff>:/images/minus.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="SendEmail" name="send_email_widget" native="true"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>SendEmail</class>
<extends>QWidget</extends>
<header>calibre/gui2/wizard/send_email.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../../../../resources/images.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -0,0 +1,196 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
__license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from PyQt4.Qt import QAbstractTableModel, QVariant, QFont, Qt
from calibre.gui2.preferences import ConfigWidgetBase, test_widget, \
AbortCommit
from calibre.gui2.preferences.email_ui import Ui_Form
from calibre.utils.config import ConfigProxy
from calibre.gui2 import NONE
from calibre.utils.smtp import config as smtp_prefs
class EmailAccounts(QAbstractTableModel): # {{{
def __init__(self, accounts):
QAbstractTableModel.__init__(self)
self.accounts = accounts
self.account_order = sorted(self.accounts.keys())
self.headers = map(QVariant, [_('Email'), _('Formats'), _('Auto send')])
self.default_font = QFont()
self.default_font.setBold(True)
self.default_font = QVariant(self.default_font)
self.tooltips =[NONE] + map(QVariant,
[_('Formats to email. The first matching format will be sent.'),
'<p>'+_('If checked, downloaded news will be automatically '
'mailed <br>to this email address '
'(provided it is in one of the listed formats).')])
def rowCount(self, *args):
return len(self.account_order)
def columnCount(self, *args):
return 3
def headerData(self, section, orientation, role):
if role == Qt.DisplayRole and orientation == Qt.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 role == Qt.UserRole:
return (account, self.accounts[account])
if role == Qt.ToolTipRole:
return self.tooltips[col]
if role in [Qt.DisplayRole, Qt.EditRole]:
if col == 0:
return QVariant(account)
if col == 1:
return QVariant(self.accounts[account][0])
if role == Qt.FontRole and self.accounts[account][2]:
return self.default_font
if role == Qt.CheckStateRole and col == 2:
return QVariant(Qt.Checked if self.accounts[account][1] else Qt.Unchecked)
return NONE
def flags(self, index):
if index.column() == 2:
return QAbstractTableModel.flags(self, index)|Qt.ItemIsUserCheckable
else:
return QAbstractTableModel.flags(self, index)|Qt.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 == 2:
self.accounts[account][1] ^= True
elif col == 1:
self.accounts[account][0] = unicode(value.toString()).upper()
else:
na = unicode(value.toString())
from email.utils import parseaddr
addr = parseaddr(na)[-1]
if not addr:
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(), 2))
return True
def make_default(self, index):
if index.isValid():
row = index.row()
for x in self.accounts.values():
x[2] = False
self.accounts[self.account_order[row]][2] = True
self.reset()
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.accounts[y] = ['MOBI, EPUB', auto_send,
len(self.account_order) == 0]
self.account_order = sorted(self.accounts.keys())
self.reset()
return self.index(self.account_order.index(y), 0)
def remove(self, index):
if index.isValid():
row = index.row()
account = self.account_order[row]
self.accounts.pop(account)
self.account_order = sorted(self.accounts.keys())
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.reset()
# }}}
class ConfigWidget(ConfigWidgetBase, Ui_Form):
supports_restoring_to_defaults = False
def genesis(self, gui):
self.gui = gui
self.proxy = ConfigProxy(smtp_prefs())
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)
self._email_accounts.dataChanged.connect(lambda x,y:
self.changed_signal.emit())
self.email_view.setModel(self._email_accounts)
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):
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
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):
idx = self.email_view.currentIndex()
self._email_accounts.remove(idx)
self.changed_signal.emit()
if __name__ == '__main__':
from PyQt4.Qt import QApplication
app = QApplication([])
test_widget('Sharing', 'Email')

View File

@ -9,7 +9,7 @@ __docformat__ = 'restructuredtext en'
import cStringIO, sys import cStringIO, sys
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
from PyQt4.Qt import QWidget, SIGNAL, QDialog, Qt from PyQt4.Qt import QWidget, pyqtSignal, QDialog, Qt
from calibre.gui2.wizard.send_email_ui import Ui_Form from calibre.gui2.wizard.send_email_ui import Ui_Form
from calibre.utils.smtp import config as smtp_prefs from calibre.utils.smtp import config as smtp_prefs
@ -24,7 +24,7 @@ class TestEmail(QDialog, TE_Dialog):
self.setupUi(self) self.setupUi(self)
opts = smtp_prefs().parse() opts = smtp_prefs().parse()
self.test_func = parent.test_email_settings self.test_func = parent.test_email_settings
self.connect(self.test_button, SIGNAL('clicked(bool)'), self.test) self.test_button.clicked.connect(self.test)
self.from_.setText(unicode(self.from_.text())%opts.from_) self.from_.setText(unicode(self.from_.text())%opts.from_)
if pa: if pa:
self.to.setText(pa) self.to.setText(pa)
@ -33,7 +33,7 @@ class TestEmail(QDialog, TE_Dialog):
(opts.relay_username, unhexlify(opts.relay_password), (opts.relay_username, unhexlify(opts.relay_password),
opts.relay_host, opts.relay_port, opts.encryption)) opts.relay_host, opts.relay_port, opts.encryption))
def test(self): def test(self, *args):
self.log.setPlainText(_('Sending...')) self.log.setPlainText(_('Sending...'))
self.test_button.setEnabled(False) self.test_button.setEnabled(False)
try: try:
@ -47,6 +47,8 @@ class TestEmail(QDialog, TE_Dialog):
class SendEmail(QWidget, Ui_Form): class SendEmail(QWidget, Ui_Form):
changed_signal = pyqtSignal()
def __init__(self, parent=None): def __init__(self, parent=None):
QWidget.__init__(self, parent) QWidget.__init__(self, parent)
self.setupUi(self) self.setupUi(self)
@ -57,23 +59,31 @@ class SendEmail(QWidget, Ui_Form):
self.smtp_opts = opts self.smtp_opts = opts
if opts.from_: if opts.from_:
self.email_from.setText(opts.from_) self.email_from.setText(opts.from_)
self.email_from.textChanged.connect(self.changed)
if opts.relay_host: if opts.relay_host:
self.relay_host.setText(opts.relay_host) self.relay_host.setText(opts.relay_host)
self.relay_host.textChanged.connect(self.changed)
self.relay_port.setValue(opts.relay_port) self.relay_port.setValue(opts.relay_port)
self.relay_port.valueChanged.connect(self.changed)
if opts.relay_username: if opts.relay_username:
self.relay_username.setText(opts.relay_username) self.relay_username.setText(opts.relay_username)
self.relay_username.textChanged.connect(self.changed)
if opts.relay_password: if opts.relay_password:
self.relay_password.setText(unhexlify(opts.relay_password)) self.relay_password.setText(unhexlify(opts.relay_password))
self.relay_password.textChanged.connect(self.changed)
(self.relay_tls if opts.encryption == 'TLS' else self.relay_ssl).setChecked(True) (self.relay_tls if opts.encryption == 'TLS' else self.relay_ssl).setChecked(True)
self.connect(self.relay_use_gmail, SIGNAL('clicked(bool)'), self.relay_tls.toggled.connect(self.changed)
self.create_gmail_relay)
self.connect(self.relay_show_password, SIGNAL('stateChanged(int)'),
lambda
state:self.relay_password.setEchoMode(self.relay_password.Password if
state == 0 else self.relay_password.Normal))
self.connect(self.test_email_button, SIGNAL('clicked(bool)'),
self.test_email)
self.relay_use_gmail.clicked.connect(
self.create_gmail_relay)
self.relay_show_password.stateChanged.connect(
lambda state : self.relay_password.setEchoMode(
self.relay_password.Password if
state == 0 else self.relay_password.Normal))
self.test_email_button.clicked.connect(self.test_email)
def changed(self, *args):
self.changed_signal.emit()
def test_email(self, *args): def test_email(self, *args):
pa = self.preferred_to_address() pa = self.preferred_to_address()