support new Values* classes and ICapAccount with a 'Register' button (closes #390)

This commit is contained in:
Romain Bignon 2010-10-26 21:00:29 +02:00
commit a792b6601c
3 changed files with 201 additions and 57 deletions

View file

@ -15,15 +15,18 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from PyQt4.QtGui import QDialog, QTreeWidgetItem, QLabel, QLineEdit, QCheckBox, \ from PyQt4.QtGui import QDialog, QTreeWidgetItem, QLabel, QFormLayout, \
QMessageBox, QPixmap, QImage, QIcon, QHeaderView, \ QMessageBox, QPixmap, QImage, QIcon, QHeaderView, \
QListWidgetItem, QTextDocument, QComboBox QListWidgetItem, QTextDocument, QVBoxLayout, \
QDialogButtonBox
from PyQt4.QtCore import SIGNAL, Qt, QVariant, QUrl from PyQt4.QtCore import SIGNAL, Qt, QVariant, QUrl
import re
from logging import warning from logging import warning
from weboob.capabilities.account import ICapAccount, Account, AccountRegisterError
from weboob.tools.application.qt.backendcfg_ui import Ui_BackendCfg from weboob.tools.application.qt.backendcfg_ui import Ui_BackendCfg
from weboob.tools.ordereddict import OrderedDict
from .qt import QtValue
class BackendCfg(QDialog): class BackendCfg(QDialog):
def __init__(self, weboob, caps=None, parent=None): def __init__(self, weboob, caps=None, parent=None):
@ -68,6 +71,7 @@ class BackendCfg(QDialog):
self.connect(self.ui.proxyBox, SIGNAL('toggled(bool)'), self.proxyEditEnabled) self.connect(self.ui.proxyBox, SIGNAL('toggled(bool)'), self.proxyEditEnabled)
self.connect(self.ui.addButton, SIGNAL('clicked()'), self.addEvent) self.connect(self.ui.addButton, SIGNAL('clicked()'), self.addEvent)
self.connect(self.ui.removeButton, SIGNAL('clicked()'), self.removeEvent) self.connect(self.ui.removeButton, SIGNAL('clicked()'), self.removeEvent)
self.connect(self.ui.registerButton, SIGNAL('clicked()'), self.registerEvent)
self.connect(self.ui.configButtonBox, SIGNAL('accepted()'), self.acceptBackend) self.connect(self.ui.configButtonBox, SIGNAL('accepted()'), self.acceptBackend)
self.connect(self.ui.configButtonBox, SIGNAL('rejected()'), self.rejectBackend) self.connect(self.ui.configButtonBox, SIGNAL('rejected()'), self.rejectBackend)
@ -140,6 +144,7 @@ class BackendCfg(QDialog):
self.loadConfiguredBackendsList() self.loadConfiguredBackendsList()
def editBackend(self, bname=None): def editBackend(self, bname=None):
self.ui.registerButton.hide()
self.ui.configFrame.show() self.ui.configFrame.show()
if bname is not None: if bname is not None:
@ -164,18 +169,12 @@ class BackendCfg(QDialog):
params.pop('_enabled', None) params.pop('_enabled', None)
for key, value in params.iteritems(): for key, value in params.iteritems():
try:
l, widget = self.config_widgets[key] l, widget = self.config_widgets[key]
if isinstance(widget, QLineEdit): except KeyError:
widget.setText(unicode(value)) warning('Key "%s" is not found' % key)
elif isinstance(widget, QCheckBox):
widget.setChecked(value.lower() in ('1', 'true', 'yes', 'on'))
elif isinstance(widget, QComboBox):
for i in xrange(widget.count()):
if unicode(widget.itemData(i).toString()) == value:
widget.setCurrentIndex(i)
break
else: else:
warning('Unknown type field "%s": %s', key, widget) widget.set_data(value)
else: else:
self.ui.nameEdit.clear() self.ui.nameEdit.clear()
self.ui.nameEdit.setEnabled(True) self.ui.nameEdit.setEnabled(True)
@ -201,44 +200,31 @@ class BackendCfg(QDialog):
return return
params = {} params = {}
missing = []
if not bname: if not bname:
missing.append(self.tr('Name')) QMessageBox.critical(self, self.tr('Missing field'),
self.tr('Please specify a backend name'))
return
if self.ui.proxyBox.isChecked(): if self.ui.proxyBox.isChecked():
params['_proxy'] = unicode(self.ui.proxyEdit.text()) params['_proxy'] = unicode(self.ui.proxyEdit.text())
if not params['_proxy']: if not params['_proxy']:
missing.append(self.tr('Proxy')) QMessageBox.critical(self, self.tr('Missing field'),
self.tr('Please specify a proxy URL'))
return
for key, field in backend.config.iteritems(): for key, field in backend.config.iteritems():
label, value = self.config_widgets[key] label, qtvalue = self.config_widgets[key]
if isinstance(value, QLineEdit): try:
params[key] = unicode(value.text()) value = qtvalue.get_value()
elif isinstance(value, QCheckBox): except ValueError, e:
params[key] = '1' if value.isChecked() else '0'
elif isinstance(value, QComboBox):
params[key] = unicode(value.itemData(value.currentIndex()).toString())
else:
warning('Unknown type field "%s": %s', key, value)
if not params[key]:
params[key] = field.default
if not params[key]:
missing.append(field.description)
elif field.regexp and not re.match(field.regexp, params[key]):
QMessageBox.critical(self, QMessageBox.critical(self,
self.tr('Invalid value'), self.tr('Invalid value'),
unicode(self.tr('Invalid value for field "%s":\n\n%s')) % (field.description, params[key])) unicode(self.tr('Invalid value for field "%s":<br /><br />%s')) % (field.label, e))
return return
if missing: params[key] = value.value
QMessageBox.critical(self,
self.tr('Missing fields'),
unicode(self.tr('Please set a value in this fields:\n%s')) % ('\n'.join(['- %s' % s for s in missing])))
return
self.weboob.backends_config.add_backend(bname, backend.name, params, edit=not self.ui.nameEdit.isEnabled()) self.weboob.backends_config.add_backend(bname, backend.name, params, edit=not self.ui.nameEdit.isEnabled())
self.to_load.add(bname) self.to_load.add(bname)
@ -287,28 +273,81 @@ class BackendCfg(QDialog):
backend.description, backend.description,
', '.join([cap.__name__ for cap in backend.iter_caps()]))) ', '.join([cap.__name__ for cap in backend.iter_caps()])))
for key, field in backend.config.iteritems(): if backend.has_caps(ICapAccount) and self.ui.nameEdit.isEnabled():
label = QLabel(u'%s:' % field.description) self.ui.registerButton.show()
if isinstance(field.default, bool):
value = QCheckBox()
if field.default:
value.setChecked(True)
elif field.choices:
value = QComboBox()
for k, l in (field.choices.iteritems() if isinstance(field.choices, dict) else ((k,k) for k in field.choices)):
value.addItem(l, QVariant(k))
else: else:
value = QLineEdit() self.ui.registerButton.hide()
if field.default is not None:
value.setText(unicode(field.default)) for key, field in backend.config.iteritems():
if field.is_masked: label = QLabel(u'%s:' % field.label)
value.setEchoMode(value.Password) value = QtValue(field)
self.ui.configLayout.addRow(label, value) self.ui.configLayout.addRow(label, value)
self.config_widgets[key] = (label, value) self.config_widgets[key] = (label, value)
def proxyEditEnabled(self, state): def proxyEditEnabled(self, state):
self.ui.proxyEdit.setEnabled(state) self.ui.proxyEdit.setEnabled(state)
def registerEvent(self):
selection = self.ui.backendsList.selectedItems()
if not selection:
return
backend = self.weboob.modules_loader.get_or_load_module(unicode(selection[0].text()).lower())
if not backend:
return
dialog = QDialog(self)
vbox = QVBoxLayout(dialog)
if backend.website:
website = 'on the website <b>%s</b>' % backend.website
else:
website = 'with the backend <b>%s</b>' % backend.name
vbox.addWidget(QLabel('To create an account %s, please give that informations:' % website))
formlayout = QFormLayout()
props_widgets = OrderedDict()
for key, prop in backend.klass.ACCOUNT_REGISTER_PROPERTIES.iteritems():
widget = QtValue(prop)
formlayout.addRow(QLabel(u'%s:' % prop.label), widget)
props_widgets[prop.id] = widget
vbox.addLayout(formlayout)
buttonBox = QDialogButtonBox(dialog)
buttonBox.setStandardButtons(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
self.connect(buttonBox, SIGNAL("accepted()"), dialog.accept)
self.connect(buttonBox, SIGNAL("rejected()"), dialog.reject)
vbox.addWidget(buttonBox)
end = False
while not end:
end = True
if dialog.exec_():
account = Account()
account.properties = {}
for key, widget in props_widgets.iteritems():
try:
v = widget.get_value()
except ValueError, e:
QMessageBox.critical(self,
self.tr('Invalid value'),
unicode(self.tr('Invalid value for field "%s":<br /><br />%s')) % (key, e))
end = False
break
else:
account.properties[key] = v
if end:
try:
backend.klass.register_account(account)
except AccountRegisterError, e:
QMessageBox.critical(self,
self.tr('Error during register'),
unicode(self.tr('Unable to register account %s:<br /><br />%s')) % (website, e))
end = False
else:
for key, value in account.properties.iteritems():
if key in self.config_widgets:
self.config_widgets[key][1].set_data(value.value)
def run(self): def run(self):
self.exec_() self.exec_()

View file

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>645</width> <width>646</width>
<height>652</height> <height>652</height>
</rect> </rect>
</property> </property>
@ -189,6 +189,9 @@
</item> </item>
<item> <item>
<layout class="QFormLayout" name="configLayout"> <layout class="QFormLayout" name="configLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
@ -213,6 +216,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1">
<widget class="QPushButton" name="registerButton">
<property name="text">
<string>Register an account...</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
@ -241,6 +251,19 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<tabstops>
<tabstop>configuredBackendsList</tabstop>
<tabstop>addButton</tabstop>
<tabstop>removeButton</tabstop>
<tabstop>backendsList</tabstop>
<tabstop>backendInfo</tabstop>
<tabstop>nameEdit</tabstop>
<tabstop>proxyBox</tabstop>
<tabstop>proxyEdit</tabstop>
<tabstop>registerButton</tabstop>
<tabstop>configButtonBox</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/> <resources/>
<connections> <connections>
<connection> <connection>

View file

@ -18,13 +18,16 @@
import sys import sys
import logging import logging
import re import re
from PyQt4.QtCore import QTimer, SIGNAL, QObject, QString, QSize from copy import deepcopy
from PyQt4.QtCore import QTimer, SIGNAL, QObject, QString, QSize, QVariant
from PyQt4.QtGui import QMainWindow, QApplication, QStyledItemDelegate, \ from PyQt4.QtGui import QMainWindow, QApplication, QStyledItemDelegate, \
QStyleOptionViewItemV4, QTextDocument, QStyle, \ QStyleOptionViewItemV4, QTextDocument, QStyle, \
QAbstractTextDocumentLayout, QPalette, QMessageBox QAbstractTextDocumentLayout, QPalette, QMessageBox, \
QSpinBox, QLineEdit, QComboBox, QCheckBox
from weboob.core.ouiboube import Weboob from weboob.core.ouiboube import Weboob
from weboob.core.scheduler import IScheduler from weboob.core.scheduler import IScheduler
from weboob.tools.value import ValueInt, ValueBool
from ..base import BaseApplication from ..base import BaseApplication
@ -181,3 +184,82 @@ class HTMLDelegate(QStyledItemDelegate):
doc.setTextWidth(optionV4.rect.width()) doc.setTextWidth(optionV4.rect.width())
return QSize(doc.idealWidth(), max(doc.size().height(), optionV4.decorationSize.height())) return QSize(doc.idealWidth(), max(doc.size().height(), optionV4.decorationSize.height()))
class _QtValueStr(QLineEdit):
def __init__(self, value):
QLineEdit.__init__(self)
self._value = value
if value.default:
self.setText(unicode(value.default))
if value.masked:
self.setEchoMode(self.Password)
def set_data(self, text):
self._value.set_value(unicode(text))
self.setText(self._value.value)
def get_value(self):
self._value.set_value(unicode(self.text()))
return self._value
class _QtValueBool(QCheckBox):
def __init__(self, value):
QCheckBox.__init__(self)
self._value = value
if value.default:
self.setChecked(True)
def set_data(self, b):
self._value.set_value(b)
self.setChecked(self._value.value)
def get_value(self):
self._value.set_value(self.isChecked())
return self._value
class _QtValueInt(QSpinBox):
def __init__(self, value):
QSpinBox.__init__(self)
self._value = value
if value.default:
self.setValue(int(value.default))
def set_data(self, i):
self._value.set_value(i)
self.setValue(self._value.value)
def get_value(self):
self._value.set_value(self.getValue())
return self._value
class _QtValueChoices(QComboBox):
def __init__(self, value):
QComboBox.__init__(self)
self._value = value
for k, l in value.choices.iteritems():
self.addItem(l, QVariant(k))
if value.default == k:
self.setCurrentIndex(self.count()-1)
def set_data(self, c):
self._value.set_value(c)
for i in xrange(self.count()):
if unicode(self.itemData(i).toString()) == self._value.value:
self.setCurrentIndex(i)
return
def get_value(self):
self._value.set_value(unicode(self.itemData(self.currentIndex()).toString()))
return self._value
def QtValue(value):
if isinstance(value, ValueBool):
klass = _QtValueBool
elif isinstance(value, ValueInt):
klass = _QtValueInt
elif value.choices is not None:
klass = _QtValueChoices
else:
klass = _QtValueStr
return klass(deepcopy(value))